aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorIan Lance Taylor <ian@gcc.gnu.org>2019-07-03 23:13:09 +0000
committerIan Lance Taylor <ian@gcc.gnu.org>2019-07-03 23:13:09 +0000
commit0baa9d1d59bf17177e80838ebe66df10a7a909c0 (patch)
treea1b956eacf43ba6ac1d052faad8a2df8f4f6ef5a /gcc
parent133d3bd8362f0c438017ca18adb51afb7288f78b (diff)
parent651c754cfbd1928abd8ac6b3121fc37c85907dcb (diff)
downloadgcc-0baa9d1d59bf17177e80838ebe66df10a7a909c0.zip
gcc-0baa9d1d59bf17177e80838ebe66df10a7a909c0.tar.gz
gcc-0baa9d1d59bf17177e80838ebe66df10a7a909c0.tar.bz2
Merge from trunk revision 273026.
From-SVN: r273027
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog5643
-rw-r--r--gcc/ChangeLog-20182
-rw-r--r--gcc/DATESTAMP2
-rw-r--r--gcc/Makefile.in8
-rw-r--r--gcc/ada/ChangeLog816
-rw-r--r--gcc/ada/Makefile.rtl1
-rw-r--r--gcc/ada/ali.adb744
-rw-r--r--gcc/ada/ali.ads316
-rw-r--r--gcc/ada/binde.adb306
-rw-r--r--gcc/ada/binde.ads14
-rw-r--r--gcc/ada/bindgen.adb10
-rw-r--r--gcc/ada/bindgen.ads3
-rw-r--r--gcc/ada/bindo-augmentors.adb372
-rw-r--r--gcc/ada/bindo-augmentors.ads62
-rw-r--r--gcc/ada/bindo-builders.adb748
-rw-r--r--gcc/ada/bindo-builders.ads65
-rw-r--r--gcc/ada/bindo-diagnostics.adb72
-rw-r--r--gcc/ada/bindo-diagnostics.ads61
-rw-r--r--gcc/ada/bindo-elaborators.adb1418
-rw-r--r--gcc/ada/bindo-elaborators.ads55
-rw-r--r--gcc/ada/bindo-graphs.adb2886
-rw-r--r--gcc/ada/bindo-graphs.ads1248
-rw-r--r--gcc/ada/bindo-units.adb410
-rw-r--r--gcc/ada/bindo-units.ads154
-rw-r--r--gcc/ada/bindo-validators.adb679
-rw-r--r--gcc/ada/bindo-validators.ads95
-rw-r--r--gcc/ada/bindo-writers.adb1333
-rw-r--r--gcc/ada/bindo-writers.ads125
-rw-r--r--gcc/ada/bindo.adb287
-rw-r--r--gcc/ada/bindo.ads44
-rw-r--r--gcc/ada/bindusg.adb5
-rw-r--r--gcc/ada/butil.adb521
-rw-r--r--gcc/ada/butil.ads53
-rw-r--r--gcc/ada/checks.adb13
-rw-r--r--gcc/ada/debug.adb198
-rw-r--r--gcc/ada/doc/gnat_rm/implementation_defined_pragmas.rst13
-rw-r--r--gcc/ada/doc/gnat_rm/interfacing_to_other_languages.rst6
-rw-r--r--gcc/ada/doc/gnat_rm/representation_clauses_and_pragmas.rst25
-rw-r--r--gcc/ada/doc/gnat_rm/standard_and_implementation_defined_restrictions.rst17
-rw-r--r--gcc/ada/doc/gnat_ugn/building_executable_programs_with_gnat.rst27
-rw-r--r--gcc/ada/doc/gnat_ugn/elaboration_order_handling_in_gnat.rst14
-rw-r--r--gcc/ada/doc/gnat_ugn/gnat_utility_programs.rst39
-rw-r--r--gcc/ada/einfo.adb4
-rw-r--r--gcc/ada/einfo.ads4
-rw-r--r--gcc/ada/erroutc.adb30
-rw-r--r--gcc/ada/exp_attr.adb104
-rw-r--r--gcc/ada/exp_ch7.adb9
-rw-r--r--gcc/ada/exp_ch9.adb19
-rw-r--r--gcc/ada/exp_unst.adb38
-rw-r--r--gcc/ada/exp_util.adb18
-rw-r--r--gcc/ada/exp_util.ads4
-rw-r--r--gcc/ada/freeze.adb44
-rw-r--r--gcc/ada/gcc-interface/Make-lang.in18
-rw-r--r--gcc/ada/gcc-interface/ada-builtin-types.def25
-rw-r--r--gcc/ada/gcc-interface/ada-builtins.def30
-rw-r--r--gcc/ada/gcc-interface/ada-tree.h7
-rw-r--r--gcc/ada/gcc-interface/decl.c446
-rw-r--r--gcc/ada/gcc-interface/gigi.h12
-rw-r--r--gcc/ada/gcc-interface/trans.c436
-rw-r--r--gcc/ada/gcc-interface/utils.c489
-rw-r--r--gcc/ada/gnat1drv.adb8
-rw-r--r--gcc/ada/gnat_rm.texi63
-rw-r--r--gcc/ada/gnat_ugn.texi61
-rw-r--r--gcc/ada/gnatbind.adb16
-rw-r--r--gcc/ada/gnatlink.adb30
-rw-r--r--gcc/ada/gsocket.h8
-rw-r--r--gcc/ada/impunit.adb1
-rw-r--r--gcc/ada/inline.adb362
-rw-r--r--gcc/ada/layout.adb10
-rw-r--r--gcc/ada/layout.ads2
-rw-r--r--gcc/ada/lib-writ.adb372
-rw-r--r--gcc/ada/lib-writ.ads88
-rw-r--r--gcc/ada/libgnat/a-calend.ads19
-rw-r--r--gcc/ada/libgnat/g-dynhta.adb340
-rw-r--r--gcc/ada/libgnat/g-dynhta.ads82
-rw-r--r--gcc/ada/libgnat/g-graphs.adb1491
-rw-r--r--gcc/ada/libgnat/g-graphs.ads536
-rw-r--r--gcc/ada/libgnat/g-lists.adb170
-rw-r--r--gcc/ada/libgnat/g-lists.ads84
-rw-r--r--gcc/ada/libgnat/g-sets.adb82
-rw-r--r--gcc/ada/libgnat/g-sets.ads54
-rw-r--r--gcc/ada/libgnat/g-sothco.adb9
-rw-r--r--gcc/ada/libgnat/s-win32.ads9
-rw-r--r--gcc/ada/libgnat/system-darwin-ppc.ads2
-rw-r--r--gcc/ada/namet.adb27
-rw-r--r--gcc/ada/namet.ads12
-rw-r--r--gcc/ada/opt.ads4
-rw-r--r--gcc/ada/osint.adb9
-rw-r--r--gcc/ada/osint.ads3
-rw-r--r--gcc/ada/par-ch3.adb6
-rw-r--r--gcc/ada/rtsfind.ads2
-rw-r--r--gcc/ada/sem_attr.adb8
-rw-r--r--gcc/ada/sem_ch12.adb99
-rw-r--r--gcc/ada/sem_ch13.adb34
-rw-r--r--gcc/ada/sem_ch3.adb30
-rw-r--r--gcc/ada/sem_ch4.adb22
-rw-r--r--gcc/ada/sem_ch5.adb75
-rw-r--r--gcc/ada/sem_ch6.adb8
-rw-r--r--gcc/ada/sem_ch7.adb16
-rw-r--r--gcc/ada/sem_ch8.adb46
-rw-r--r--gcc/ada/sem_elab.adb19683
-rw-r--r--gcc/ada/sem_elab.ads81
-rw-r--r--gcc/ada/sem_prag.adb34
-rw-r--r--gcc/ada/sem_spark.adb6136
-rw-r--r--gcc/ada/sem_spark.ads8
-rw-r--r--gcc/ada/sem_util.adb131
-rw-r--r--gcc/ada/sem_util.ads8
-rw-r--r--gcc/ada/sem_warn.adb13
-rw-r--r--gcc/ada/sinfo.adb46
-rw-r--r--gcc/ada/sinfo.ads85
-rw-r--r--gcc/ada/style.ads4
-rw-r--r--gcc/ada/styleg.adb25
-rw-r--r--gcc/ada/styleg.ads5
-rw-r--r--gcc/ada/stylesw.adb8
-rw-r--r--gcc/ada/stylesw.ads4
-rw-r--r--gcc/ada/switch-b.adb95
-rw-r--r--gcc/ada/sysdep.c1
-rw-r--r--gcc/ada/uintp.adb89
-rw-r--r--gcc/ada/uintp.ads6
-rw-r--r--gcc/alias.c21
-rw-r--r--gcc/asan.c4
-rw-r--r--gcc/attribs.c37
-rw-r--r--gcc/attribs.h1
-rw-r--r--gcc/bb-reorder.c17
-rw-r--r--gcc/brig/ChangeLog9
-rw-r--r--gcc/brig/brig-lang.c6
-rw-r--r--gcc/brig/brigfrontend/brig-control-handler.cc2
-rw-r--r--gcc/brig/brigfrontend/brig-module-handler.cc4
-rw-r--r--gcc/bt-load.c1
-rw-r--r--gcc/builtin-attrs.def37
-rw-r--r--gcc/builtins.c95
-rw-r--r--gcc/builtins.def14
-rw-r--r--gcc/c-family/ChangeLog175
-rw-r--r--gcc/c-family/c-ada-spec.c26
-rw-r--r--gcc/c-family/c-ada-spec.h1
-rw-r--r--gcc/c-family/c-attribs.c64
-rw-r--r--gcc/c-family/c-common.c44
-rw-r--r--gcc/c-family/c-common.h2
-rw-r--r--gcc/c-family/c-format.c1057
-rw-r--r--gcc/c-family/c-lex.c4
-rw-r--r--gcc/c-family/c-omp.c30
-rw-r--r--gcc/c-family/c-opts.c10
-rw-r--r--gcc/c-family/c-pch.c16
-rw-r--r--gcc/c-family/c-pragma.c60
-rw-r--r--gcc/c-family/c-pragma.h1
-rw-r--r--gcc/c-family/c-warn.c34
-rw-r--r--gcc/c-family/c.opt20
-rw-r--r--gcc/c/ChangeLog91
-rw-r--r--gcc/c/c-decl.c39
-rw-r--r--gcc/c/c-parser.c176
-rw-r--r--gcc/c/c-typeck.c91
-rw-r--r--gcc/c/gimple-parser.c196
-rw-r--r--gcc/calls.c47
-rw-r--r--gcc/ccmp.c7
-rw-r--r--gcc/cfg.c7
-rw-r--r--gcc/cfgexpand.c88
-rw-r--r--gcc/cfghooks.c12
-rw-r--r--gcc/cfgloop.c15
-rw-r--r--gcc/cfgloop.h3
-rw-r--r--gcc/cfgloopmanip.c2
-rw-r--r--gcc/cfgrtl.c20
-rw-r--r--gcc/cgraph.c15
-rw-r--r--gcc/cgraphunit.c8
-rw-r--r--gcc/collect-utils.c4
-rw-r--r--gcc/collect2.c13
-rw-r--r--gcc/combine.c9
-rw-r--r--gcc/common.opt18
-rw-r--r--gcc/common/config/aarch64/aarch64-common.c37
-rw-r--r--gcc/common/config/i386/i386-common.c37
-rw-r--r--gcc/common/config/pru/pru-common.c36
-rw-r--r--gcc/config.gcc93
-rw-r--r--gcc/config.host4
-rw-r--r--gcc/config.in6
-rw-r--r--gcc/config/aarch64/aarch64-bti-insert.c4
-rw-r--r--gcc/config/aarch64/aarch64-builtins.c32
-rw-r--r--gcc/config/aarch64/aarch64-c.c1
-rw-r--r--gcc/config/aarch64/aarch64-elf-raw.h19
-rw-r--r--gcc/config/aarch64/aarch64-errata.h44
-rw-r--r--gcc/config/aarch64/aarch64-freebsd.h20
-rw-r--r--gcc/config/aarch64/aarch64-linux.h21
-rw-r--r--gcc/config/aarch64/aarch64-modes.def2
-rw-r--r--gcc/config/aarch64/aarch64-netbsd.h63
-rw-r--r--gcc/config/aarch64/aarch64-option-extensions.def58
-rw-r--r--gcc/config/aarch64/aarch64-protos.h23
-rw-r--r--gcc/config/aarch64/aarch64-simd.md560
-rw-r--r--gcc/config/aarch64/aarch64-sve.md530
-rw-r--r--gcc/config/aarch64/aarch64-sve2.md65
-rw-r--r--gcc/config/aarch64/aarch64.c496
-rw-r--r--gcc/config/aarch64/aarch64.h25
-rw-r--r--gcc/config/aarch64/aarch64.md249
-rw-r--r--gcc/config/aarch64/aarch64.opt2
-rw-r--r--gcc/config/aarch64/atomics.md36
-rw-r--r--gcc/config/aarch64/driver-aarch64.c10
-rw-r--r--gcc/config/aarch64/iterators.md47
-rw-r--r--gcc/config/aarch64/predicates.md6
-rw-r--r--gcc/config/aarch64/t-aarch64-netbsd21
-rw-r--r--gcc/config/alpha/alpha-protos.h3
-rw-r--r--gcc/config/alpha/alpha.c376
-rw-r--r--gcc/config/alpha/alpha.h2
-rw-r--r--gcc/config/alpha/alpha.md10
-rw-r--r--gcc/config/alpha/sync.md8
-rw-r--r--gcc/config/arc/arc-protos.h6
-rw-r--r--gcc/config/arc/arc.c534
-rw-r--r--gcc/config/arc/arc.h2
-rw-r--r--gcc/config/arc/arc.md227
-rw-r--r--gcc/config/arc/constraints.md22
-rw-r--r--gcc/config/arm/arm-fixed.md54
-rw-r--r--gcc/config/arm/arm-protos.h6
-rw-r--r--gcc/config/arm/arm.c26
-rw-r--r--gcc/config/arm/arm.md635
-rw-r--r--gcc/config/arm/cortex-a57.md7
-rw-r--r--gcc/config/arm/iterators.md3
-rw-r--r--gcc/config/arm/iwmmxt.md16
-rw-r--r--gcc/config/arm/neon.md480
-rw-r--r--gcc/config/arm/netbsd-eabi.h105
-rw-r--r--gcc/config/arm/netbsd-elf.h29
-rw-r--r--gcc/config/arm/sync.md10
-rw-r--r--gcc/config/arm/t-rtems11
-rw-r--r--gcc/config/arm/thumb1.md28
-rw-r--r--gcc/config/arm/unspecs.md2
-rw-r--r--gcc/config/arm/vec-common.md54
-rw-r--r--gcc/config/avr/avr-protos.h4
-rw-r--r--gcc/config/avr/avr.c33
-rw-r--r--gcc/config/avr/avr.md32
-rw-r--r--gcc/config/bfin/bfin-protos.h2
-rw-r--r--gcc/config/bfin/bfin.c15
-rw-r--r--gcc/config/bfin/bfin.h2
-rw-r--r--gcc/config/bfin/bfin.md4
-rw-r--r--gcc/config/c6x/c6x-protos.h2
-rw-r--r--gcc/config/c6x/c6x.c7
-rw-r--r--gcc/config/c6x/c6x.md4
-rw-r--r--gcc/config/cris/cris.c4
-rw-r--r--gcc/config/csky/csky.c3
-rw-r--r--gcc/config/darwin-c.c41
-rw-r--r--gcc/config/darwin-driver.c145
-rw-r--r--gcc/config/darwin.c313
-rw-r--r--gcc/config/darwin.h123
-rw-r--r--gcc/config/darwin.opt401
-rw-r--r--gcc/config/darwin10.h9
-rw-r--r--gcc/config/darwin9.h6
-rw-r--r--gcc/config/epiphany/epiphany.c3
-rw-r--r--gcc/config/frv/frv.c4
-rw-r--r--gcc/config/frv/frv.md2
-rw-r--r--gcc/config/ft32/ft32.md2
-rw-r--r--gcc/config/gcn/gcn-run.c41
-rw-r--r--gcc/config/gcn/gcn.c34
-rw-r--r--gcc/config/gcn/gcn.md38
-rw-r--r--gcc/config/gcn/gcn.opt3
-rw-r--r--gcc/config/gcn/t-gcn-hsa4
-rw-r--r--gcc/config/h8300/h8300.md4
-rw-r--r--gcc/config/i386/avx512dqintrin.h38
-rw-r--r--gcc/config/i386/avx512vp2intersectintrin.h35
-rw-r--r--gcc/config/i386/avx512vp2intersectvlintrin.h49
-rw-r--r--gcc/config/i386/constraints.md7
-rw-r--r--gcc/config/i386/cpuid.h19
-rw-r--r--gcc/config/i386/darwin.h28
-rw-r--r--gcc/config/i386/driver-i386.c8
-rw-r--r--gcc/config/i386/enqcmdintrin.h55
-rw-r--r--gcc/config/i386/host-mingw32.c4
-rw-r--r--gcc/config/i386/i386-builtin-types.def10
-rw-r--r--gcc/config/i386/i386-builtin.def148
-rw-r--r--gcc/config/i386/i386-builtins.c30
-rw-r--r--gcc/config/i386/i386-c.c6
-rw-r--r--gcc/config/i386/i386-expand.c859
-rw-r--r--gcc/config/i386/i386-features.c11
-rw-r--r--gcc/config/i386/i386-modes.def6
-rw-r--r--gcc/config/i386/i386-options.c67
-rw-r--r--gcc/config/i386/i386-options.h15
-rw-r--r--gcc/config/i386/i386-protos.h9
-rw-r--r--gcc/config/i386/i386.c381
-rw-r--r--gcc/config/i386/i386.h26
-rw-r--r--gcc/config/i386/i386.md1436
-rw-r--r--gcc/config/i386/i386.opt8
-rw-r--r--gcc/config/i386/immintrin.h6
-rw-r--r--gcc/config/i386/mmintrin.h12
-rw-r--r--gcc/config/i386/mmx.md1088
-rw-r--r--gcc/config/i386/predicates.md10
-rw-r--r--gcc/config/i386/sol2.h10
-rw-r--r--gcc/config/i386/sse.md770
-rw-r--r--gcc/config/i386/x86-tune-sched.c63
-rw-r--r--gcc/config/i386/xmmintrin.h61
-rw-r--r--gcc/config/ia64/ia64.c6
-rw-r--r--gcc/config/lm32/lm32.md2
-rw-r--r--gcc/config/m32c/blkmov.md12
-rw-r--r--gcc/config/m32c/m32c-protos.h2
-rw-r--r--gcc/config/m32c/m32c.c10
-rw-r--r--gcc/config/m32r/m32r.c4
-rw-r--r--gcc/config/m32r/m32r.md4
-rw-r--r--gcc/config/m68k/m68k.c3
-rw-r--r--gcc/config/mcore/mcore.md2
-rw-r--r--gcc/config/microblaze/microblaze.c5
-rw-r--r--gcc/config/microblaze/microblaze.md2
-rw-r--r--gcc/config/mips/mips.c59
-rw-r--r--gcc/config/mips/mips.h10
-rw-r--r--gcc/config/mips/mips.md2
-rw-r--r--gcc/config/mmix/mmix.c6
-rw-r--r--gcc/config/mn10300/mn10300.c3
-rw-r--r--gcc/config/msp430/msp430.c13
-rw-r--r--gcc/config/msp430/msp430.h6
-rw-r--r--gcc/config/msp430/msp430.md66
-rw-r--r--gcc/config/nds32/nds32-memory-manipulation.c30
-rw-r--r--gcc/config/nds32/nds32-multiple.md4
-rw-r--r--gcc/config/nds32/nds32-protos.h2
-rw-r--r--gcc/config/nds32/nds32.c3
-rw-r--r--gcc/config/netbsd-elf.h14
-rw-r--r--gcc/config/nios2/nios2.c6
-rw-r--r--gcc/config/nvptx/nvptx.c18
-rw-r--r--gcc/config/nvptx/nvptx.md44
-rw-r--r--gcc/config/or1k/or1k.c8
-rw-r--r--gcc/config/pa/pa-linux.h7
-rw-r--r--gcc/config/pa/pa-protos.h1
-rw-r--r--gcc/config/pa/pa.c67
-rw-r--r--gcc/config/pa/pa.h3
-rw-r--r--gcc/config/pa/pa.md65
-rw-r--r--gcc/config/pdp11/pdp11.md16
-rw-r--r--gcc/config/pru/alu-zext.md181
-rw-r--r--gcc/config/pru/constraints.md108
-rw-r--r--gcc/config/pru/predicates.md287
-rw-r--r--gcc/config/pru/pru-opts.h31
-rw-r--r--gcc/config/pru/pru-passes.c228
-rw-r--r--gcc/config/pru/pru-pragma.c86
-rw-r--r--gcc/config/pru/pru-protos.h72
-rw-r--r--gcc/config/pru/pru.c3036
-rw-r--r--gcc/config/pru/pru.h573
-rw-r--r--gcc/config/pru/pru.md1022
-rw-r--r--gcc/config/pru/pru.opt54
-rw-r--r--gcc/config/pru/t-pru31
-rw-r--r--gcc/config/riscv/freebsd.h6
-rw-r--r--gcc/config/riscv/linux.h6
-rw-r--r--gcc/config/riscv/riscv.c5
-rw-r--r--gcc/config/riscv/riscv.h14
-rw-r--r--gcc/config/riscv/riscv.md2
-rw-r--r--gcc/config/rs6000/altivec.h8
-rw-r--r--gcc/config/rs6000/altivec.md56
-rw-r--r--gcc/config/rs6000/constraints.md79
-rw-r--r--gcc/config/rs6000/darwin.h32
-rw-r--r--gcc/config/rs6000/driver-rs6000.c12
-rw-r--r--gcc/config/rs6000/predicates.md86
-rw-r--r--gcc/config/rs6000/rs6000-c.c20
-rw-r--r--gcc/config/rs6000/rs6000-cpus.def45
-rw-r--r--gcc/config/rs6000/rs6000-internal.h127
-rw-r--r--gcc/config/rs6000/rs6000-logue.c5639
-rw-r--r--gcc/config/rs6000/rs6000-opts.h2
-rw-r--r--gcc/config/rs6000/rs6000-protos.h5
-rw-r--r--gcc/config/rs6000/rs6000-string.c1
-rw-r--r--gcc/config/rs6000/rs6000-tables.opt3
-rw-r--r--gcc/config/rs6000/rs6000.c6245
-rw-r--r--gcc/config/rs6000/rs6000.h96
-rw-r--r--gcc/config/rs6000/rs6000.md1067
-rw-r--r--gcc/config/rs6000/rs6000.opt19
-rw-r--r--gcc/config/rs6000/t-rs60004
-rw-r--r--gcc/config/rs6000/vsx.md794
-rw-r--r--gcc/config/rx/elf.opt44
-rw-r--r--gcc/config/rx/linux.h231
-rw-r--r--gcc/config/rx/rx.c4
-rw-r--r--gcc/config/rx/rx.h2
-rw-r--r--gcc/config/rx/rx.md12
-rw-r--r--gcc/config/rx/rx.opt12
-rw-r--r--gcc/config/rx/t-linux34
-rw-r--r--gcc/config/s390/s390-builtins.def20
-rw-r--r--gcc/config/s390/s390-protos.h2
-rw-r--r--gcc/config/s390/s390.c21
-rw-r--r--gcc/config/s390/s390.md16
-rw-r--r--gcc/config/s390/vector.md2
-rw-r--r--gcc/config/sh/sh.c8
-rw-r--r--gcc/config/sh/sh.md2
-rw-r--r--gcc/config/sol2.h4
-rw-r--r--gcc/config/sparc/driver-sparc.c11
-rw-r--r--gcc/config/sparc/sparc.c18
-rw-r--r--gcc/config/sparc/sparc.h2
-rw-r--r--gcc/config/sparc/sparc.md18
-rw-r--r--gcc/config/spu/spu.c3
-rw-r--r--gcc/config/stormy16/stormy16.c3
-rw-r--r--gcc/config/tilegx/tilegx.c6
-rw-r--r--gcc/config/tilepro/tilepro.c6
-rw-r--r--gcc/config/vax/vax-protos.h1
-rw-r--r--gcc/config/vax/vax.c14
-rw-r--r--gcc/config/vax/vax.h2
-rw-r--r--gcc/config/vax/vax.md8
-rw-r--r--gcc/config/visium/visium.h4
-rw-r--r--gcc/config/visium/visium.md2
-rw-r--r--gcc/config/xtensa/xtensa.c5
-rw-r--r--gcc/config/xtensa/xtensa.md2
-rwxr-xr-xgcc/configure204
-rw-r--r--gcc/configure.ac110
-rw-r--r--gcc/convert.c12
-rw-r--r--gcc/coverage.c11
-rw-r--r--gcc/cp/ChangeLog827
-rw-r--r--gcc/cp/call.c97
-rw-r--r--gcc/cp/class.c82
-rw-r--r--gcc/cp/config-lang.in2
-rw-r--r--gcc/cp/constexpr.c494
-rw-r--r--gcc/cp/constraint.cc6
-rw-r--r--gcc/cp/cp-gimplify.c63
-rw-r--r--gcc/cp/cp-lang.c3
-rw-r--r--gcc/cp/cp-objcp-common.c8
-rw-r--r--gcc/cp/cp-tree.def7
-rw-r--r--gcc/cp/cp-tree.h136
-rw-r--r--gcc/cp/cvt.c24
-rw-r--r--gcc/cp/cxx-pretty-print.c1
-rw-r--r--gcc/cp/decl.c420
-rw-r--r--gcc/cp/decl2.c17
-rw-r--r--gcc/cp/error.c23
-rw-r--r--gcc/cp/except.c14
-rw-r--r--gcc/cp/friend.c7
-rw-r--r--gcc/cp/init.c40
-rw-r--r--gcc/cp/lambda.c24
-rw-r--r--gcc/cp/lex.c20
-rw-r--r--gcc/cp/mangle.c19
-rw-r--r--gcc/cp/method.c22
-rw-r--r--gcc/cp/name-lookup.c631
-rw-r--r--gcc/cp/name-lookup.h11
-rw-r--r--gcc/cp/optimize.c12
-rw-r--r--gcc/cp/parser.c884
-rw-r--r--gcc/cp/parser.h3
-rw-r--r--gcc/cp/pt.c368
-rw-r--r--gcc/cp/repo.c2
-rw-r--r--gcc/cp/rtti.c19
-rw-r--r--gcc/cp/search.c56
-rw-r--r--gcc/cp/semantics.c172
-rw-r--r--gcc/cp/tree.c62
-rw-r--r--gcc/cp/typeck.c96
-rw-r--r--gcc/cp/typeck2.c59
-rw-r--r--gcc/cse.c2
-rw-r--r--gcc/cselib.c12
-rw-r--r--gcc/d/ChangeLog47
-rw-r--r--gcc/d/d-builtins.cc2
-rw-r--r--gcc/d/d-codegen.cc2
-rw-r--r--gcc/d/d-convert.cc6
-rw-r--r--gcc/d/d-frontend.cc2
-rw-r--r--gcc/d/d-lang.cc8
-rw-r--r--gcc/d/d-target.cc5
-rw-r--r--gcc/d/decl.cc2
-rw-r--r--gcc/d/dmd/MERGE2
-rw-r--r--gcc/d/dmd/attrib.c3
-rw-r--r--gcc/d/dmd/blockexit.c2
-rw-r--r--gcc/d/dmd/clone.c21
-rw-r--r--gcc/d/dmd/dclass.c10
-rw-r--r--gcc/d/dmd/declaration.c13
-rw-r--r--gcc/d/dmd/declaration.h1
-rw-r--r--gcc/d/dmd/denum.c3
-rw-r--r--gcc/d/dmd/dimport.c8
-rw-r--r--gcc/d/dmd/dinterpret.c17
-rw-r--r--gcc/d/dmd/dmodule.c3
-rw-r--r--gcc/d/dmd/dstruct.c5
-rw-r--r--gcc/d/dmd/dtemplate.c9
-rw-r--r--gcc/d/dmd/expression.c9
-rw-r--r--gcc/d/dmd/expressionsem.c75
-rw-r--r--gcc/d/dmd/func.c17
-rw-r--r--gcc/d/dmd/intrange.c6
-rw-r--r--gcc/d/dmd/mtype.c109
-rw-r--r--gcc/d/dmd/mtype.h1
-rw-r--r--gcc/d/dmd/optimize.c4
-rw-r--r--gcc/d/dmd/statement.c3
-rw-r--r--gcc/d/dmd/statementsem.c80
-rw-r--r--gcc/d/dmd/traits.c6
-rw-r--r--gcc/d/expr.cc2
-rw-r--r--gcc/d/toir.cc47
-rw-r--r--gcc/d/typeinfo.cc87
-rw-r--r--gcc/d/types.cc9
-rw-r--r--gcc/dbgcnt.def1
-rw-r--r--gcc/defaults.h6
-rw-r--r--gcc/df-scan.c46
-rw-r--r--gcc/diagnostic-format-json.cc60
-rw-r--r--gcc/diagnostic-show-locus.c11
-rw-r--r--gcc/diagnostic.c11
-rw-r--r--gcc/doc/cppopts.texi4
-rw-r--r--gcc/doc/extend.texi55
-rw-r--r--gcc/doc/generic.texi5
-rw-r--r--gcc/doc/install.texi120
-rw-r--r--gcc/doc/invoke.texi341
-rw-r--r--gcc/doc/loop.texi5
-rw-r--r--gcc/doc/md.texi300
-rw-r--r--gcc/doc/rtl.texi2
-rw-r--r--gcc/doc/sourcebuild.texi10
-rw-r--r--gcc/doc/tm.texi21
-rw-r--r--gcc/doc/tm.texi.in4
-rw-r--r--gcc/dojump.c2
-rw-r--r--gcc/dwarf2out.c122
-rw-r--r--gcc/early-remat.c1
-rw-r--r--gcc/edit-context.c4
-rw-r--r--gcc/emit-rtl.c26
-rw-r--r--gcc/except.c14
-rw-r--r--gcc/expr.c31
-rw-r--r--gcc/expr.h4
-rw-r--r--gcc/fold-const.c128
-rw-r--r--gcc/fold-const.h4
-rw-r--r--gcc/fortran/ChangeLog383
-rw-r--r--gcc/fortran/arith.c51
-rw-r--r--gcc/fortran/array.c18
-rw-r--r--gcc/fortran/check.c18
-rw-r--r--gcc/fortran/decl.c180
-rw-r--r--gcc/fortran/dependency.c68
-rw-r--r--gcc/fortran/dump-parse-tree.c37
-rw-r--r--gcc/fortran/expr.c14
-rw-r--r--gcc/fortran/f95-lang.c2
-rw-r--r--gcc/fortran/frontend-passes.c13
-rw-r--r--gcc/fortran/gfc-internals.texi143
-rw-r--r--gcc/fortran/gfortran.h6
-rw-r--r--gcc/fortran/gfortran.texi44
-rw-r--r--gcc/fortran/gfortranspec.c2
-rw-r--r--gcc/fortran/interface.c4
-rw-r--r--gcc/fortran/intrinsic.texi62
-rw-r--r--gcc/fortran/invoke.texi66
-rw-r--r--gcc/fortran/io.c109
-rw-r--r--gcc/fortran/lang.opt15
-rw-r--r--gcc/fortran/match.c35
-rw-r--r--gcc/fortran/options.c2
-rw-r--r--gcc/fortran/parse.c21
-rw-r--r--gcc/fortran/resolve.c38
-rw-r--r--gcc/fortran/simplify.c27
-rw-r--r--gcc/fortran/symbol.c10
-rw-r--r--gcc/fortran/trans-array.c62
-rw-r--r--gcc/fortran/trans-common.c6
-rw-r--r--gcc/fortran/trans-decl.c83
-rw-r--r--gcc/fortran/trans-expr.c240
-rw-r--r--gcc/fortran/trans-intrinsic.c33
-rw-r--r--gcc/fortran/trans-openmp.c4
-rw-r--r--gcc/fortran/trans-stmt.c16
-rw-r--r--gcc/fortran/trans-types.c23
-rw-r--r--gcc/fortran/trans.c26
-rw-r--r--gcc/fortran/trans.h11
-rw-r--r--gcc/function.c15
-rw-r--r--gcc/function.h3
-rw-r--r--gcc/fwprop.c2
-rw-r--r--gcc/gcc.c36
-rw-r--r--gcc/gcov-counter.def7
-rw-r--r--gcc/gcov-io.h8
-rw-r--r--gcc/gcov-tool.c10
-rw-r--r--gcc/gcov.c75
-rw-r--r--gcc/gcse.c3
-rw-r--r--gcc/gdbhooks.py13
-rw-r--r--gcc/gdbinit.in10
-rw-r--r--gcc/generic-match-head.c3
-rw-r--r--gcc/genmatch.c4
-rw-r--r--gcc/gensupport.c74
-rw-r--r--gcc/ggc-common.c24
-rw-r--r--gcc/ggc-page.c18
-rw-r--r--gcc/gimple-fold.c68
-rw-r--r--gcc/gimple-loop-versioning.cc2
-rw-r--r--gcc/gimple-low.c1
-rw-r--r--gcc/gimple-match-head.c3
-rw-r--r--gcc/gimple-pretty-print.c103
-rw-r--r--gcc/gimple-ssa-evrp-analyze.c5
-rw-r--r--gcc/gimple-ssa-evrp.c27
-rw-r--r--gcc/gimple-ssa-nonnull-compare.c2
-rw-r--r--gcc/gimple-ssa-sprintf.c6
-rw-r--r--gcc/gimple-ssa-strength-reduction.c75
-rw-r--r--gcc/gimple-walk.c11
-rw-r--r--gcc/gimple.c25
-rw-r--r--gcc/gimple.def5
-rw-r--r--gcc/gimple.h57
-rw-r--r--gcc/gimplify.c364
-rw-r--r--gcc/ginclude/float.h3
-rw-r--r--gcc/go/ChangeLog18
-rw-r--r--gcc/go/go-gcc.cc143
-rw-r--r--gcc/go/gofrontend/MERGE2
-rw-r--r--gcc/go/gofrontend/ast-dump.cc3
-rw-r--r--gcc/go/gofrontend/escape.cc242
-rw-r--r--gcc/go/gofrontend/export.cc854
-rw-r--r--gcc/go/gofrontend/export.h61
-rw-r--r--gcc/go/gofrontend/expressions.cc2392
-rw-r--r--gcc/go/gofrontend/expressions.h182
-rw-r--r--gcc/go/gofrontend/go-diagnostics.cc22
-rw-r--r--gcc/go/gofrontend/go-diagnostics.h12
-rw-r--r--gcc/go/gofrontend/go.cc9
-rw-r--r--gcc/go/gofrontend/gogo.cc555
-rw-r--r--gcc/go/gofrontend/gogo.h133
-rw-r--r--gcc/go/gofrontend/import-archive.cc8
-rw-r--r--gcc/go/gofrontend/import.cc194
-rw-r--r--gcc/go/gofrontend/import.h75
-rw-r--r--gcc/go/gofrontend/lex.cc2
-rw-r--r--gcc/go/gofrontend/names.cc52
-rw-r--r--gcc/go/gofrontend/parse.cc22
-rw-r--r--gcc/go/gofrontend/runtime.cc21
-rw-r--r--gcc/go/gofrontend/runtime.def170
-rw-r--r--gcc/go/gofrontend/statements.cc715
-rw-r--r--gcc/go/gofrontend/statements.h158
-rw-r--r--gcc/go/gofrontend/types.cc118
-rw-r--r--gcc/go/gofrontend/types.h32
-rw-r--r--gcc/go/gofrontend/wb.cc187
-rw-r--r--gcc/graph.c13
-rw-r--r--gcc/graphite-scop-detection.c2
-rw-r--r--gcc/hash-map-tests.c134
-rw-r--r--gcc/hash-map.h48
-rw-r--r--gcc/hash-set-tests.c154
-rw-r--r--gcc/hash-set.h14
-rw-r--r--gcc/hash-table.c15
-rw-r--r--gcc/hash-table.h68
-rw-r--r--gcc/hsa-gen.c35
-rw-r--r--gcc/input.c7
-rw-r--r--gcc/internal-fn.c5
-rw-r--r--gcc/internal-fn.def4
-rw-r--r--gcc/ipa-cp.c21
-rw-r--r--gcc/ipa-devirt.c290
-rw-r--r--gcc/ipa-icf-gimple.c38
-rw-r--r--gcc/ipa-icf-gimple.h34
-rw-r--r--gcc/ipa-icf.c154
-rw-r--r--gcc/ipa-icf.h62
-rw-r--r--gcc/ipa-inline.c12
-rw-r--r--gcc/ipa-profile.c12
-rw-r--r--gcc/ipa-prop.c239
-rw-r--r--gcc/ipa-pure-const.c25
-rw-r--r--gcc/ipa-reference.c17
-rw-r--r--gcc/ipa-utils.c3
-rw-r--r--gcc/ipa-utils.h37
-rw-r--r--gcc/ira-color.c1
-rw-r--r--gcc/ira-conflicts.c4
-rw-r--r--gcc/ira-int.h4
-rw-r--r--gcc/ira-lives.c25
-rw-r--r--gcc/ira.c146
-rw-r--r--gcc/json.cc29
-rw-r--r--gcc/json.h1
-rw-r--r--gcc/loop-iv.c14
-rw-r--r--gcc/lra-assigns.c2
-rw-r--r--gcc/lra-constraints.c2
-rw-r--r--gcc/lra-eliminations.c95
-rw-r--r--gcc/lra.c8
-rw-r--r--gcc/lto-compress.c141
-rw-r--r--gcc/lto-compress.h3
-rw-r--r--gcc/lto-section-in.c11
-rw-r--r--gcc/lto-section-out.c2
-rw-r--r--gcc/lto-streamer-in.c3
-rw-r--r--gcc/lto-streamer-out.c77
-rw-r--r--gcc/lto-streamer.c27
-rw-r--r--gcc/lto-streamer.h29
-rw-r--r--gcc/lto-wrapper.c27
-rw-r--r--gcc/lto/ChangeLog47
-rw-r--r--gcc/lto/Make-lang.in3
-rw-r--r--gcc/lto/config-lang.in2
-rw-r--r--gcc/lto/lto-common.c167
-rw-r--r--gcc/lto/lto-dump.c25
-rw-r--r--gcc/lto/lto-lang.c6
-rw-r--r--gcc/lto/lto.c2
-rw-r--r--gcc/match.pd200
-rw-r--r--gcc/mem-stats.h6
-rw-r--r--gcc/multiple_target.c8
-rw-r--r--gcc/objc/ChangeLog30
-rw-r--r--gcc/objc/config-lang.in2
-rw-r--r--gcc/objc/objc-act.c36
-rw-r--r--gcc/objc/objc-act.h7
-rw-r--r--gcc/objc/objc-encoding.c2
-rw-r--r--gcc/objc/objc-next-runtime-abi-01.c3
-rw-r--r--gcc/objc/objc-next-runtime-abi-02.c6
-rw-r--r--gcc/objcp/ChangeLog5
-rw-r--r--gcc/objcp/config-lang.in1
-rw-r--r--gcc/omp-expand.c767
-rw-r--r--gcc/omp-general.c164
-rw-r--r--gcc/omp-general.h4
-rw-r--r--gcc/omp-low.c1892
-rw-r--r--gcc/omp-offload.c11
-rw-r--r--gcc/optabs-query.c7
-rw-r--r--gcc/optabs.c80
-rw-r--r--gcc/optabs.def3
-rw-r--r--gcc/optc-save-gen.awk41
-rw-r--r--gcc/opts-common.c6
-rw-r--r--gcc/opts-global.c17
-rw-r--r--gcc/opts.c40
-rw-r--r--gcc/opts.h5
-rw-r--r--gcc/params.def30
-rw-r--r--gcc/passes.c4
-rw-r--r--gcc/passes.def7
-rw-r--r--gcc/plugin.c13
-rw-r--r--gcc/po/ChangeLog24
-rw-r--r--gcc/po/de.po85
-rw-r--r--gcc/po/es.po6
-rw-r--r--gcc/po/fi.po974
-rw-r--r--gcc/po/fr.po84
-rw-r--r--gcc/po/sv.po4088
-rw-r--r--gcc/predict.def7
-rw-r--r--gcc/print-rtl.c11
-rw-r--r--gcc/print-tree.c23
-rw-r--r--gcc/profile-count.c24
-rw-r--r--gcc/profile-count.h324
-rw-r--r--gcc/profile.c5
-rw-r--r--gcc/read-md.h1
-rw-r--r--gcc/read-rtl-function.c4
-rw-r--r--gcc/read-rtl.c143
-rw-r--r--gcc/reg-stack.c12
-rw-r--r--gcc/regcprop.c17
-rw-r--r--gcc/reginfo.c6
-rw-r--r--gcc/regrename.c3
-rw-r--r--gcc/reload1.c92
-rw-r--r--gcc/reorg.c3
-rw-r--r--gcc/rtl.def6
-rw-r--r--gcc/rtl.h4
-rw-r--r--gcc/sched-rgn.c11
-rw-r--r--gcc/selftest-run-tests.c1
-rw-r--r--gcc/selftest.h1
-rw-r--r--gcc/stmt.c2
-rw-r--r--gcc/stor-layout.c6
-rw-r--r--gcc/symbol-summary.h14
-rw-r--r--gcc/symtab.c15
-rw-r--r--gcc/target.def24
-rw-r--r--gcc/targhooks.c31
-rw-r--r--gcc/targhooks.h4
-rw-r--r--gcc/testsuite/ChangeLog3252
-rw-r--r--gcc/testsuite/ChangeLog-20182
-rw-r--r--gcc/testsuite/brig.dg/test/gimple/packed.hsail2
-rw-r--r--gcc/testsuite/c-c++-common/Wbool-operation-1.c24
-rw-r--r--gcc/testsuite/c-c++-common/Wreturn-local-addr.c47
-rw-r--r--gcc/testsuite/c-c++-common/Wswitch-outside-range-1.c8
-rw-r--r--gcc/testsuite/c-c++-common/Wswitch-outside-range-2.c9
-rw-r--r--gcc/testsuite/c-c++-common/Wswitch-outside-range-3.c9
-rw-r--r--gcc/testsuite/c-c++-common/Wswitch-outside-range-4.c9
-rw-r--r--gcc/testsuite/c-c++-common/Wvarargs-2.c2
-rw-r--r--gcc/testsuite/c-c++-common/Wvarargs.c2
-rw-r--r--gcc/testsuite/c-c++-common/asan/alloca_loop_unpoisoning.c2
-rw-r--r--gcc/testsuite/c-c++-common/asan/pr88619.c2
-rw-r--r--gcc/testsuite/c-c++-common/builtin-arith-overflow-3.c42
-rw-r--r--gcc/testsuite/c-c++-common/convert-vec-1.c2
-rw-r--r--gcc/testsuite/c-c++-common/cpp/fmax-include-depth-1a.h1
-rw-r--r--gcc/testsuite/c-c++-common/cpp/fmax-include-depth-1b.h1
-rw-r--r--gcc/testsuite/c-c++-common/cpp/fmax-include-depth.c4
-rw-r--r--gcc/testsuite/c-c++-common/goacc/acc-icf.c4
-rw-r--r--gcc/testsuite/c-c++-common/goacc/classify-routine.c4
-rw-r--r--gcc/testsuite/c-c++-common/goacc/declare-1.c165
-rw-r--r--gcc/testsuite/c-c++-common/goacc/declare-2.c134
-rw-r--r--gcc/testsuite/c-c++-common/goacc/declare-pr90861.c21
-rw-r--r--gcc/testsuite/c-c++-common/goacc/firstprivate-mappings-1.c536
-rw-r--r--gcc/testsuite/c-c++-common/goacc/routine-2.c20
-rw-r--r--gcc/testsuite/c-c++-common/goacc/routine-5.c48
-rw-r--r--gcc/testsuite/c-c++-common/goacc/routine-level-of-parallelism-1.c449
-rw-r--r--gcc/testsuite/c-c++-common/goacc/routine-level-of-parallelism-2.c71
-rw-r--r--gcc/testsuite/c-c++-common/gomp/lastprivate-conditional-2.c10
-rw-r--r--gcc/testsuite/c-c++-common/gomp/lastprivate-conditional-3.c44
-rw-r--r--gcc/testsuite/c-c++-common/gomp/lastprivate-conditional-4.c23
-rw-r--r--gcc/testsuite/c-c++-common/gomp/lastprivate-conditional-5.c33
-rw-r--r--gcc/testsuite/c-c++-common/gomp/pr90954.c27
-rw-r--r--gcc/testsuite/c-c++-common/gomp/scan-1.c209
-rw-r--r--gcc/testsuite/c-c++-common/gomp/scan-2.c14
-rw-r--r--gcc/testsuite/c-c++-common/gomp/scan-3.c14
-rw-r--r--gcc/testsuite/c-c++-common/gomp/scan-4.c14
-rw-r--r--gcc/testsuite/c-c++-common/gomp/scan-5.c13
-rw-r--r--gcc/testsuite/c-c++-common/gomp/simd8.c37
-rw-r--r--gcc/testsuite/c-c++-common/nonnull-1.c12
-rw-r--r--gcc/testsuite/c-c++-common/nonnull-2.c8
-rw-r--r--gcc/testsuite/c-c++-common/nonnull-3.c2
-rw-r--r--gcc/testsuite/c-c++-common/pr35503-1.c2
-rw-r--r--gcc/testsuite/c-c++-common/pr35503-2.c2
-rw-r--r--gcc/testsuite/c-c++-common/pr35503-3.c2
-rw-r--r--gcc/testsuite/c-c++-common/pr51768.c6
-rw-r--r--gcc/testsuite/c-c++-common/pr90927.c6
-rw-r--r--gcc/testsuite/c-c++-common/scal-to-vec1.c6
-rw-r--r--gcc/testsuite/c-c++-common/tm/inline-asm.c2
-rw-r--r--gcc/testsuite/c-c++-common/tm/safe-1.c8
-rw-r--r--gcc/testsuite/g++.dg/DRs/dr1940.C13
-rw-r--r--gcc/testsuite/g++.dg/abi/empty12.C2
-rw-r--r--gcc/testsuite/g++.dg/abi/empty13.C2
-rw-r--r--gcc/testsuite/g++.dg/abi/empty14.C2
-rw-r--r--gcc/testsuite/g++.dg/abi/empty15.C2
-rw-r--r--gcc/testsuite/g++.dg/abi/empty16.C2
-rw-r--r--gcc/testsuite/g++.dg/abi/empty17.C2
-rw-r--r--gcc/testsuite/g++.dg/abi/empty18.C2
-rw-r--r--gcc/testsuite/g++.dg/abi/empty19.C2
-rw-r--r--gcc/testsuite/g++.dg/abi/empty22.C2
-rw-r--r--gcc/testsuite/g++.dg/abi/empty25.C2
-rw-r--r--gcc/testsuite/g++.dg/abi/empty26.C2
-rw-r--r--gcc/testsuite/g++.dg/asan/pr90570.C18
-rw-r--r--gcc/testsuite/g++.dg/asm-qual-1.C4
-rw-r--r--gcc/testsuite/g++.dg/asm-qual-3.C8
-rw-r--r--gcc/testsuite/g++.dg/cet-notrack-1.C2
-rw-r--r--gcc/testsuite/g++.dg/concepts/decl-diagnose.C2
-rw-r--r--gcc/testsuite/g++.dg/concepts/pr60573.C6
-rw-r--r--gcc/testsuite/g++.dg/conversion/bitfield7.C2
-rw-r--r--gcc/testsuite/g++.dg/conversion/dynamic1.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/Wattributes1.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/Wattributes2.C32
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/Wunused-value1.C20
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/addressof2.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/alias-decl-1.C3
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/alias-decl-18.C3
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/alias-decl-68.C10
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/alias-decl-69.C40
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/alignas4.C8
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/alignof5.C6
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/auto9.C10
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-77771.C16
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-89599.C4
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-cast.C4
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-condition.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-decltype4.C21
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-neg1.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-object1.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-shift1.C6
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-sizeof2.C14
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-sizeof3.C22
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/decltype-pr66548.C3
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/decltype71.C25
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/defaulted18.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/defaulted2.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/deleted13.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/gen-attrs-67.C11
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/gnu_fext-numeric-literals.C24
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/inh-ctor33.C19
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/initlist-deduce2.C8
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/lambda/lambda-conv11.C6
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/lambda/lambda-ice32.C9
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/lambda/lambda-this21.C10
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/literal-type1.C54
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/noexcept15.C40
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/noexcept41.C12
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/noexcept42.C21
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/noexcept43.C10
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/noexcept44.C8
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/noexcept45.C23
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/noexcept46.C28
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/noexcept47.C83
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/noexcept48.C11
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/noexcept49.C12
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/noexcept50.C147
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/noexcept51.C14
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/noexcept52.C9
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/noexcept53.C26
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/noexcept54.C10
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/nondeduced1.C16
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/nondeduced2.C14
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/nondeduced3.C16
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/nondeduced4.C13
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/nondeduced5.C12
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/nondeduced6.C24
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/nondeduced7.C6
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/nsdmi-list5.C30
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/nullptr04.C4
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/pr42844-2.C8
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/pr83993.C6
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/pr84497.C1
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/pr87250.C12
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/pr90598.C8
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/static_assert12.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/static_assert8.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/std_fext-numeric-literals.C24
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/udlit-nofunc-neg.C4
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/udlit-shadow-neg.C4
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/udlit-tmpl-arg-neg2.C4
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/udlit-tmpl-parms-neg.C6
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic177.C12
-rw-r--r--gcc/testsuite/g++.dg/cpp1y/constexpr-79655.C12
-rw-r--r--gcc/testsuite/g++.dg/cpp1y/constexpr-90383-1.C15
-rw-r--r--gcc/testsuite/g++.dg/cpp1y/constexpr-90383-2.C22
-rw-r--r--gcc/testsuite/g++.dg/cpp1y/feat-cxx14.C4
-rw-r--r--gcc/testsuite/g++.dg/cpp1y/lambda-conv1.C12
-rw-r--r--gcc/testsuite/g++.dg/cpp1y/lambda-generic-90548.C22
-rw-r--r--gcc/testsuite/g++.dg/cpp1y/noexcept1.C13
-rw-r--r--gcc/testsuite/g++.dg/cpp1y/pr77830.C4
-rw-r--r--gcc/testsuite/g++.dg/cpp1y/pr79393-3.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp1y/pr87410.C19
-rw-r--r--gcc/testsuite/g++.dg/cpp1y/static_assert1.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp1y/udlit-char-template-neg.C4
-rw-r--r--gcc/testsuite/g++.dg/cpp1z/constexpr-if4.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp1z/constexpr-if5.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp1z/constexpr-if9.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp1z/decomp3.C7
-rw-r--r--gcc/testsuite/g++.dg/cpp1z/feat-cxx1z.C4
-rw-r--r--gcc/testsuite/g++.dg/cpp1z/inline-var2.C4
-rw-r--r--gcc/testsuite/g++.dg/cpp1z/inline-var7.C20
-rw-r--r--gcc/testsuite/g++.dg/cpp1z/pr85569.C1
-rw-r--r--gcc/testsuite/g++.dg/cpp1z/register1.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp1z/register2.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp1z/register3.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/decomp1-aux.cc52
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/decomp1.C92
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/decomp2.C76
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/decomp3.C26
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/feat-cxx2a.C4
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/is-constant-evaluated8.C19
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/multiple-deleted-destroying-delete-error-1.C12
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/multiple-deleted-destroying-delete-error-2.C12
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/nontype-class17.C17
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/typename16.C11
-rw-r--r--gcc/testsuite/g++.dg/debug/dwarf2/fesd-any.C2
-rw-r--r--gcc/testsuite/g++.dg/debug/dwarf2/fesd-baseonly.C2
-rw-r--r--gcc/testsuite/g++.dg/debug/dwarf2/fesd-none.C2
-rw-r--r--gcc/testsuite/g++.dg/debug/dwarf2/fesd-reduced.C2
-rw-r--r--gcc/testsuite/g++.dg/debug/dwarf2/fesd-sys.C2
-rw-r--r--gcc/testsuite/g++.dg/debug/dwarf2/inline-var-1.C2
-rw-r--r--gcc/testsuite/g++.dg/debug/enum-1.C1
-rw-r--r--gcc/testsuite/g++.dg/debug/enum-2.C1
-rw-r--r--gcc/testsuite/g++.dg/debug/pr90914.C8
-rw-r--r--gcc/testsuite/g++.dg/diagnostic/auto-storage-1.C6
-rw-r--r--gcc/testsuite/g++.dg/diagnostic/conflicting-specifiers-1.C1
-rw-r--r--gcc/testsuite/g++.dg/diagnostic/friend2.C10
-rw-r--r--gcc/testsuite/g++.dg/diagnostic/friend3.C9
-rw-r--r--gcc/testsuite/g++.dg/diagnostic/main1.C1
-rw-r--r--gcc/testsuite/g++.dg/diagnostic/no-type-1.C1
-rw-r--r--gcc/testsuite/g++.dg/diagnostic/no-type-2.C3
-rw-r--r--gcc/testsuite/g++.dg/diagnostic/return-type-invalid-1.C27
-rw-r--r--gcc/testsuite/g++.dg/diagnostic/top-level-auto-1.C3
-rw-r--r--gcc/testsuite/g++.dg/diagnostic/trailing1.C5
-rw-r--r--gcc/testsuite/g++.dg/diagnostic/two-or-more-data-types-1.C1
-rw-r--r--gcc/testsuite/g++.dg/diagnostic/variably-modified-type-1.C12
-rw-r--r--gcc/testsuite/g++.dg/eh/goto2.C4
-rw-r--r--gcc/testsuite/g++.dg/eh/goto3.C4
-rw-r--r--gcc/testsuite/g++.dg/eh/o32-fp.C47
-rw-r--r--gcc/testsuite/g++.dg/eh/shadow1.C2
-rw-r--r--gcc/testsuite/g++.dg/expr/static_cast8.C12
-rw-r--r--gcc/testsuite/g++.dg/ext/90532.C27
-rw-r--r--gcc/testsuite/g++.dg/ext/alignof2.C2
-rw-r--r--gcc/testsuite/g++.dg/ext/altivec-15.C2
-rw-r--r--gcc/testsuite/g++.dg/ext/constexpr-vla1.C4
-rw-r--r--gcc/testsuite/g++.dg/ext/flexary5.C14
-rw-r--r--gcc/testsuite/g++.dg/ext/goto1.C9
-rw-r--r--gcc/testsuite/g++.dg/ext/is_final.C14
-rw-r--r--gcc/testsuite/g++.dg/ext/is_trivially_constructible1.C4
-rw-r--r--gcc/testsuite/g++.dg/ext/is_trivially_copyable.C16
-rw-r--r--gcc/testsuite/g++.dg/ext/utf-array-short-wchar.C12
-rw-r--r--gcc/testsuite/g++.dg/ext/utf-array.C12
-rw-r--r--gcc/testsuite/g++.dg/ext/utf8-2.C16
-rw-r--r--gcc/testsuite/g++.dg/ext/vector37.C29
-rw-r--r--gcc/testsuite/g++.dg/ext/vector38.C5
-rw-r--r--gcc/testsuite/g++.dg/goacc/firstprivate-mappings-1.C529
-rw-r--r--gcc/testsuite/g++.dg/gomp/lastprivate-1.C16
-rw-r--r--gcc/testsuite/g++.dg/gomp/loop-4.C56
-rw-r--r--gcc/testsuite/g++.dg/gomp/macro-4.C8
-rw-r--r--gcc/testsuite/g++.dg/gomp/scan-1.C26
-rw-r--r--gcc/testsuite/g++.dg/gomp/udr-1.C24
-rw-r--r--gcc/testsuite/g++.dg/init/initializer-string-too-long.C2
-rw-r--r--gcc/testsuite/g++.dg/init/pr42844.C12
-rw-r--r--gcc/testsuite/g++.dg/init/static5.C9
-rw-r--r--gcc/testsuite/g++.dg/lookup/pr90754.C11
-rw-r--r--gcc/testsuite/g++.dg/lookup/strong-using2.C11
-rw-r--r--gcc/testsuite/g++.dg/lookup/using53.C2
-rw-r--r--gcc/testsuite/g++.dg/lto/alias-1_0.C33
-rw-r--r--gcc/testsuite/g++.dg/lto/alias-1_1.C16
-rw-r--r--gcc/testsuite/g++.dg/lto/alias-2_0.C33
-rw-r--r--gcc/testsuite/g++.dg/lto/alias-2_1.C16
-rw-r--r--gcc/testsuite/g++.dg/lto/pr90939_0.C64
-rw-r--r--gcc/testsuite/g++.dg/lto/pr90939_1.C45
-rw-r--r--gcc/testsuite/g++.dg/lto/pr90990_0.C31
-rw-r--r--gcc/testsuite/g++.dg/other/error34.C2
-rw-r--r--gcc/testsuite/g++.dg/other/final3.C28
-rw-r--r--gcc/testsuite/g++.dg/other/final5.C19
-rw-r--r--gcc/testsuite/g++.dg/other/final6.C9
-rw-r--r--gcc/testsuite/g++.dg/other/final7.C11
-rw-r--r--gcc/testsuite/g++.dg/other/final8.C9
-rw-r--r--gcc/testsuite/g++.dg/other/friend4.C4
-rw-r--r--gcc/testsuite/g++.dg/other/friend5.C2
-rw-r--r--gcc/testsuite/g++.dg/other/friend7.C2
-rw-r--r--gcc/testsuite/g++.dg/other/i386-2.C7
-rw-r--r--gcc/testsuite/g++.dg/other/i386-3.C7
-rw-r--r--gcc/testsuite/g++.dg/other/offsetof9.C6
-rw-r--r--gcc/testsuite/g++.dg/other/pr77548.C9
-rw-r--r--gcc/testsuite/g++.dg/other/pr84792-1.C2
-rw-r--r--gcc/testsuite/g++.dg/other/pr84792-2.C2
-rw-r--r--gcc/testsuite/g++.dg/overload/conv-op1.C2
-rw-r--r--gcc/testsuite/g++.dg/overload/using2.C2
-rw-r--r--gcc/testsuite/g++.dg/parse/alignas1.C10
-rw-r--r--gcc/testsuite/g++.dg/parse/crash59.C3
-rw-r--r--gcc/testsuite/g++.dg/parse/error10.C2
-rw-r--r--gcc/testsuite/g++.dg/parse/error24.C2
-rw-r--r--gcc/testsuite/g++.dg/parse/error29.C6
-rw-r--r--gcc/testsuite/g++.dg/parse/error32.C2
-rw-r--r--gcc/testsuite/g++.dg/parse/error33.C2
-rw-r--r--gcc/testsuite/g++.dg/parse/error38.C2
-rw-r--r--gcc/testsuite/g++.dg/parse/error39.C4
-rw-r--r--gcc/testsuite/g++.dg/parse/error62.C10
-rw-r--r--gcc/testsuite/g++.dg/parse/friend13.C16
-rw-r--r--gcc/testsuite/g++.dg/parse/pragma2.C3
-rw-r--r--gcc/testsuite/g++.dg/parse/qualified4.C2
-rw-r--r--gcc/testsuite/g++.dg/parse/saved1.C3
-rw-r--r--gcc/testsuite/g++.dg/pch/operator-1.C2
-rw-r--r--gcc/testsuite/g++.dg/pch/operator-1.Hs9
-rw-r--r--gcc/testsuite/g++.dg/pch/pr90326.C9
-rw-r--r--gcc/testsuite/g++.dg/pch/pr90326.Hs1
-rw-r--r--gcc/testsuite/g++.dg/pr71694.C1
-rw-r--r--gcc/testsuite/g++.dg/pr90462.C49
-rw-r--r--gcc/testsuite/g++.dg/pr90981.C8
-rw-r--r--gcc/testsuite/g++.dg/template/crash31.C3
-rw-r--r--gcc/testsuite/g++.dg/template/crash96.C2
-rw-r--r--gcc/testsuite/g++.dg/template/operator15.C6
-rw-r--r--gcc/testsuite/g++.dg/template/operator6.C2
-rw-r--r--gcc/testsuite/g++.dg/template/operator8.C3
-rw-r--r--gcc/testsuite/g++.dg/template/operator9.C3
-rw-r--r--gcc/testsuite/g++.dg/template/pr61745.C3
-rw-r--r--gcc/testsuite/g++.dg/template/sizeof-template-argument.C4
-rw-r--r--gcc/testsuite/g++.dg/template/typedef41.C2
-rw-r--r--gcc/testsuite/g++.dg/torture/pr34850.C3
-rw-r--r--gcc/testsuite/g++.dg/torture/pr90982.C23
-rw-r--r--gcc/testsuite/g++.dg/tree-ssa/alias-access-path-1.C24
-rw-r--r--gcc/testsuite/g++.dg/tree-ssa/cprop-vcond.C12
-rw-r--r--gcc/testsuite/g++.dg/tree-ssa/empty-3.C16
-rw-r--r--gcc/testsuite/g++.dg/tree-ssa/empty-loop.C33
-rw-r--r--gcc/testsuite/g++.dg/tree-ssa/final1.C8
-rw-r--r--gcc/testsuite/g++.dg/tree-ssa/pr19807.C3
-rw-r--r--gcc/testsuite/g++.dg/tree-ssa/pr20280.C6
-rw-r--r--gcc/testsuite/g++.dg/tree-ssa/pr31146.C4
-rw-r--r--gcc/testsuite/g++.dg/tree-ssa/pr69336.C1
-rw-r--r--gcc/testsuite/g++.dg/tree-ssa/pr78847.C4
-rw-r--r--gcc/testsuite/g++.dg/tree-ssa/pr80293.C1
-rw-r--r--gcc/testsuite/g++.dg/tree-ssa/pr90883.C20
-rw-r--r--gcc/testsuite/g++.dg/tree-ssa/ssa-dse-1.C4
-rw-r--r--gcc/testsuite/g++.dg/ubsan/pr63956.C12
-rw-r--r--gcc/testsuite/g++.dg/vect/simd-1.cc114
-rw-r--r--gcc/testsuite/g++.dg/vect/simd-10.cc8
-rw-r--r--gcc/testsuite/g++.dg/vect/simd-2.cc153
-rw-r--r--gcc/testsuite/g++.dg/vect/simd-3.cc120
-rw-r--r--gcc/testsuite/g++.dg/vect/simd-4.cc122
-rw-r--r--gcc/testsuite/g++.dg/vect/simd-5.cc153
-rw-r--r--gcc/testsuite/g++.dg/vect/simd-6.cc161
-rw-r--r--gcc/testsuite/g++.dg/vect/simd-7.cc124
-rw-r--r--gcc/testsuite/g++.dg/vect/simd-8.cc122
-rw-r--r--gcc/testsuite/g++.dg/vect/simd-9.cc153
-rw-r--r--gcc/testsuite/g++.dg/warn/Wbool-operation-1.C2
-rw-r--r--gcc/testsuite/g++.dg/warn/Wfloat-equal-1.C8
-rw-r--r--gcc/testsuite/g++.dg/warn/Wimplicit-fallthrough-4.C22
-rw-r--r--gcc/testsuite/g++.dg/warn/Winaccessible-base-1.C7
-rw-r--r--gcc/testsuite/g++.dg/warn/Winaccessible-base-2.C8
-rw-r--r--gcc/testsuite/g++.dg/warn/Winaccessible-virtual-base-1.C10
-rw-r--r--gcc/testsuite/g++.dg/warn/Winaccessible-virtual-base-2.C10
-rw-r--r--gcc/testsuite/g++.dg/warn/Wrestrict-1.C2
-rw-r--r--gcc/testsuite/g++.dg/warn/Wrestrict-2.C8
-rw-r--r--gcc/testsuite/g++.dg/warn/Wreturn-local-addr-6.C29
-rw-r--r--gcc/testsuite/g++.dg/warn/Wsuggest-override-2.C9
-rw-r--r--gcc/testsuite/g++.dg/warn/Wtype-limits-Wextra.C24
-rw-r--r--gcc/testsuite/g++.dg/warn/Wtype-limits.C24
-rw-r--r--gcc/testsuite/g++.dg/warn/ctor-dtor-privacy-4.C5
-rw-r--r--gcc/testsuite/g++.dg/warn/ctor-dtor-privacy-4.h7
-rw-r--r--gcc/testsuite/g++.dg/warn/miss-format-7.C29
-rw-r--r--gcc/testsuite/g++.dg/warn/nonnull3.C2
-rw-r--r--gcc/testsuite/g++.dg/warn/noreturn-10.C10
-rw-r--r--gcc/testsuite/g++.dg/warn/noreturn-11.C25
-rw-r--r--gcc/testsuite/g++.dg/warn/noreturn-8.C21
-rw-r--r--gcc/testsuite/g++.dg/warn/noreturn-9.C21
-rw-r--r--gcc/testsuite/g++.dg/warn/pr8715.C2
-rw-r--r--gcc/testsuite/g++.dg/wrappers/pr88680.C8
-rw-r--r--gcc/testsuite/g++.old-deja/g++.abi/ptrmem.C2
-rw-r--r--gcc/testsuite/g++.old-deja/g++.brendan/crash16.C3
-rw-r--r--gcc/testsuite/g++.old-deja/g++.brendan/crash22.C4
-rw-r--r--gcc/testsuite/g++.old-deja/g++.brendan/crash23.C4
-rw-r--r--gcc/testsuite/g++.old-deja/g++.jason/crash10.C2
-rw-r--r--gcc/testsuite/g++.old-deja/g++.law/ctors5.C3
-rw-r--r--gcc/testsuite/g++.old-deja/g++.law/visibility10.C2
-rw-r--r--gcc/testsuite/g++.old-deja/g++.mike/eh55.C2
-rw-r--r--gcc/testsuite/g++.old-deja/g++.other/cond5.C4
-rw-r--r--gcc/testsuite/g++.old-deja/g++.other/decl5.C2
-rw-r--r--gcc/testsuite/g++.old-deja/g++.pt/assign1.C2
-rw-r--r--gcc/testsuite/g++.target/aarch64/return_address_sign_ab_exception.C30
-rw-r--r--gcc/testsuite/g++.target/aarch64/return_address_sign_b_exception.C17
-rw-r--r--gcc/testsuite/g++.target/i386/pr90424-1.C32
-rw-r--r--gcc/testsuite/g++.target/i386/pr90424-2.C31
-rw-r--r--gcc/testsuite/g++.target/powerpc/powerpc.exp44
-rw-r--r--gcc/testsuite/g++.target/powerpc/undef-bool-3.C13
-rw-r--r--gcc/testsuite/gcc.c-torture/compile/pr77754-1.c1
-rw-r--r--gcc/testsuite/gcc.c-torture/compile/pr77754-2.c1
-rw-r--r--gcc/testsuite/gcc.c-torture/compile/pr77754-3.c1
-rw-r--r--gcc/testsuite/gcc.c-torture/compile/pr77754-4.c1
-rw-r--r--gcc/testsuite/gcc.c-torture/compile/pr77754-5.c1
-rw-r--r--gcc/testsuite/gcc.c-torture/compile/pr77754-6.c1
-rw-r--r--gcc/testsuite/gcc.c-torture/compile/pr87110.c1
-rw-r--r--gcc/testsuite/gcc.c-torture/compile/pr89280.c2
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/20030125-1.c2
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/20101011-1.c3
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/alias-access-path-1.c19
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/builtins/builtins.exp2
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/pr64242.c34
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/pr84521.c53
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/pr86528.c1
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/pr90949.c42
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/shiftdi-2.c24
-rw-r--r--gcc/testsuite/gcc.dg/20020312-2.c2
-rw-r--r--gcc/testsuite/gcc.dg/Walloca-13.c2
-rw-r--r--gcc/testsuite/gcc.dg/Walloca-larger-than-2.c1
-rw-r--r--gcc/testsuite/gcc.dg/Walloca-larger-than.c1
-rw-r--r--gcc/testsuite/gcc.dg/Warray-bounds-41.c1
-rw-r--r--gcc/testsuite/gcc.dg/Wattribute-alias.c2
-rw-r--r--gcc/testsuite/gcc.dg/Wfloat-equal-1.c8
-rw-r--r--gcc/testsuite/gcc.dg/Wrestrict-17.c1
-rw-r--r--gcc/testsuite/gcc.dg/Wsign-compare-1.c16
-rw-r--r--gcc/testsuite/gcc.dg/Wstrict-overflow-27.c1
-rw-r--r--gcc/testsuite/gcc.dg/Wstringop-truncation-3.c1
-rw-r--r--gcc/testsuite/gcc.dg/Wtype-limits-Wextra.c32
-rw-r--r--gcc/testsuite/gcc.dg/Wtype-limits.c32
-rw-r--r--gcc/testsuite/gcc.dg/Wunknownprag.c8
-rw-r--r--gcc/testsuite/gcc.dg/Wunsuffixed-float-constants-1.c4
-rw-r--r--gcc/testsuite/gcc.dg/asm-6.c2
-rw-r--r--gcc/testsuite/gcc.dg/asm-qual-1.c4
-rw-r--r--gcc/testsuite/gcc.dg/atomic/c11-atomic-exec-4.c2
-rw-r--r--gcc/testsuite/gcc.dg/atomic/c11-atomic-exec-5.c2
-rw-r--r--gcc/testsuite/gcc.dg/attr-alloc_size-5.c2
-rw-r--r--gcc/testsuite/gcc.dg/attr-assume_aligned-4.c4
-rw-r--r--gcc/testsuite/gcc.dg/attr-copy-6.c1
-rw-r--r--gcc/testsuite/gcc.dg/attr-noinline.c6
-rw-r--r--gcc/testsuite/gcc.dg/attr-noipa.c2
-rw-r--r--gcc/testsuite/gcc.dg/attr-weakref-2.c2
-rw-r--r--gcc/testsuite/gcc.dg/autopar/pr39500-1.c2
-rw-r--r--gcc/testsuite/gcc.dg/autopar/reduc-1char.c2
-rw-r--r--gcc/testsuite/gcc.dg/autopar/reduc-7.c2
-rw-r--r--gcc/testsuite/gcc.dg/builtin-apply2.c2
-rw-r--r--gcc/testsuite/gcc.dg/builtin-memchr-4.c40
-rw-r--r--gcc/testsuite/gcc.dg/builtin-stringop-chk-1.c2
-rw-r--r--gcc/testsuite/gcc.dg/c90-const-expr-6.c12
-rw-r--r--gcc/testsuite/gcc.dg/c99-math-double-1.c2
-rw-r--r--gcc/testsuite/gcc.dg/c99-math-float-1.c2
-rw-r--r--gcc/testsuite/gcc.dg/c99-math-long-double-1.c2
-rw-r--r--gcc/testsuite/gcc.dg/cast-1.c4
-rw-r--r--gcc/testsuite/gcc.dg/cast-2.c4
-rw-r--r--gcc/testsuite/gcc.dg/cast-3.c4
-rw-r--r--gcc/testsuite/gcc.dg/cdce1.c7
-rw-r--r--gcc/testsuite/gcc.dg/cdce2.c7
-rw-r--r--gcc/testsuite/gcc.dg/cdce3.c12
-rw-r--r--gcc/testsuite/gcc.dg/const-1.c2
-rw-r--r--gcc/testsuite/gcc.dg/cpp/isysroot-1.c11
-rw-r--r--gcc/testsuite/gcc.dg/cpp/source_date_epoch-2.c2
-rw-r--r--gcc/testsuite/gcc.dg/cpp/usr/include/example.h (renamed from gcc/testsuite/gcc.dg/cpp/usr/include/stdio.h)0
-rw-r--r--gcc/testsuite/gcc.dg/darwin-minversion-1.c2
-rw-r--r--gcc/testsuite/gcc.dg/darwin-minversion-2.c2
-rw-r--r--gcc/testsuite/gcc.dg/darwin-minversion-link.c26
-rw-r--r--gcc/testsuite/gcc.dg/darwin-weakimport-3.c17
-rw-r--r--gcc/testsuite/gcc.dg/debug/dwarf2/fesd-any.c2
-rw-r--r--gcc/testsuite/gcc.dg/debug/dwarf2/fesd-baseonly.c2
-rw-r--r--gcc/testsuite/gcc.dg/debug/dwarf2/fesd-none.c2
-rw-r--r--gcc/testsuite/gcc.dg/debug/dwarf2/fesd-reduced.c2
-rw-r--r--gcc/testsuite/gcc.dg/debug/dwarf2/fesd-sys.c2
-rw-r--r--gcc/testsuite/gcc.dg/debug/enum-1.c1
-rw-r--r--gcc/testsuite/gcc.dg/debug/pr85252.c4
-rw-r--r--gcc/testsuite/gcc.dg/dfp/cast-bad.c12
-rw-r--r--gcc/testsuite/gcc.dg/dfp/warn-abs-2.c10
-rw-r--r--gcc/testsuite/gcc.dg/enum-mode-1.c12
-rw-r--r--gcc/testsuite/gcc.dg/format/dfp-printf-1.c28
-rw-r--r--gcc/testsuite/gcc.dg/format/dfp-scanf-1.c22
-rw-r--r--gcc/testsuite/gcc.dg/format/gcc_diag-1.c2
-rw-r--r--gcc/testsuite/gcc.dg/format/gcc_diag-11.c455
-rw-r--r--gcc/testsuite/gcc.dg/funroll-loops-all.c2
-rw-r--r--gcc/testsuite/gcc.dg/gimplefe-40.c24
-rw-r--r--gcc/testsuite/gcc.dg/gimplefe-41.c39
-rw-r--r--gcc/testsuite/gcc.dg/gimplefe-42.c18
-rw-r--r--gcc/testsuite/gcc.dg/gnu-cond-expr-2.c2
-rw-r--r--gcc/testsuite/gcc.dg/gnu-cond-expr-3.c2
-rw-r--r--gcc/testsuite/gcc.dg/gomp/macro-4.c8
-rw-r--r--gcc/testsuite/gcc.dg/gomp/pr90637.c14
-rw-r--r--gcc/testsuite/gcc.dg/gomp/pr90900.c11
-rw-r--r--gcc/testsuite/gcc.dg/graphite/graphite.exp2
-rw-r--r--gcc/testsuite/gcc.dg/guality/pr90716.c25
-rw-r--r--gcc/testsuite/gcc.dg/init-bad-1.c6
-rw-r--r--gcc/testsuite/gcc.dg/init-bad-2.c6
-rw-r--r--gcc/testsuite/gcc.dg/init-bad-3.c6
-rw-r--r--gcc/testsuite/gcc.dg/ipa/ipcp-agg-10.c78
-rw-r--r--gcc/testsuite/gcc.dg/ipa/pr68035.c2
-rw-r--r--gcc/testsuite/gcc.dg/ipa/pr90555.c66
-rw-r--r--gcc/testsuite/gcc.dg/loop-unswitch-1.c2
-rw-r--r--gcc/testsuite/gcc.dg/lto/alias-access-path-2_0.c38
-rw-r--r--gcc/testsuite/gcc.dg/memcpy-2.c2
-rw-r--r--gcc/testsuite/gcc.dg/misc-column.c2
-rw-r--r--gcc/testsuite/gcc.dg/no_profile_instrument_function-attr-1.c2
-rw-r--r--gcc/testsuite/gcc.dg/nonnull-3.c4
-rw-r--r--gcc/testsuite/gcc.dg/opts-5.c2
-rw-r--r--gcc/testsuite/gcc.dg/parm-mismatch-1.c10
-rw-r--r--gcc/testsuite/gcc.dg/plugin/start_unit_plugin.c13
-rw-r--r--gcc/testsuite/gcc.dg/pr27528.c8
-rw-r--r--gcc/testsuite/gcc.dg/pr28322-2.c2
-rw-r--r--gcc/testsuite/gcc.dg/pr28322-3.c4
-rw-r--r--gcc/testsuite/gcc.dg/pr40340-1.c2
-rw-r--r--gcc/testsuite/gcc.dg/pr40340-2.c2
-rw-r--r--gcc/testsuite/gcc.dg/pr40340-5.c2
-rw-r--r--gcc/testsuite/gcc.dg/pr43643.c6
-rw-r--r--gcc/testsuite/gcc.dg/pr48552-1.c6
-rw-r--r--gcc/testsuite/gcc.dg/pr48552-2.c6
-rw-r--r--gcc/testsuite/gcc.dg/pr53265.c3
-rw-r--r--gcc/testsuite/gcc.dg/pr59717.c8
-rw-r--r--gcc/testsuite/gcc.dg/pr59846.c4
-rw-r--r--gcc/testsuite/gcc.dg/pr60087.c6
-rw-r--r--gcc/testsuite/gcc.dg/pr61096-1.c2
-rw-r--r--gcc/testsuite/gcc.dg/pr78902.c15
-rw-r--r--gcc/testsuite/gcc.dg/pr78957.c2
-rw-r--r--gcc/testsuite/gcc.dg/pr87099.c1
-rw-r--r--gcc/testsuite/gcc.dg/pr8715.c2
-rw-r--r--gcc/testsuite/gcc.dg/pr87320.c1
-rw-r--r--gcc/testsuite/gcc.dg/pr87600.h2
-rw-r--r--gcc/testsuite/gcc.dg/pr8788-1.c2
-rw-r--r--gcc/testsuite/gcc.dg/pr87954.c21
-rw-r--r--gcc/testsuite/gcc.dg/pr88870.c1
-rw-r--r--gcc/testsuite/gcc.dg/pr89045.c1
-rw-r--r--gcc/testsuite/gcc.dg/pr89737.c2
-rw-r--r--gcc/testsuite/gcc.dg/pr90082.c4
-rw-r--r--gcc/testsuite/gcc.dg/pr90263.c12
-rw-r--r--gcc/testsuite/gcc.dg/pr90726.c56
-rw-r--r--gcc/testsuite/gcc.dg/pr90733.c22
-rw-r--r--gcc/testsuite/gcc.dg/pr90760.c9
-rw-r--r--gcc/testsuite/gcc.dg/pr90866-2.c26
-rw-r--r--gcc/testsuite/gcc.dg/pr90866.c18
-rw-r--r--gcc/testsuite/gcc.dg/pr90892.c14
-rw-r--r--gcc/testsuite/gcc.dg/pr91069.c20
-rw-r--r--gcc/testsuite/gcc.dg/predict-9.c2
-rw-r--r--gcc/testsuite/gcc.dg/pure-2.c2
-rw-r--r--gcc/testsuite/gcc.dg/simd-1.c2
-rw-r--r--gcc/testsuite/gcc.dg/simd-2.c4
-rw-r--r--gcc/testsuite/gcc.dg/spellcheck-options-1.c2
-rw-r--r--gcc/testsuite/gcc.dg/spellcheck-options-10.c2
-rw-r--r--gcc/testsuite/gcc.dg/spellcheck-options-12.c2
-rw-r--r--gcc/testsuite/gcc.dg/spellcheck-options-13.c2
-rw-r--r--gcc/testsuite/gcc.dg/spellcheck-options-18.c2
-rw-r--r--gcc/testsuite/gcc.dg/spellcheck-options-19.c2
-rw-r--r--gcc/testsuite/gcc.dg/spellcheck-options-2.c2
-rw-r--r--gcc/testsuite/gcc.dg/spellcheck-options-20.c2
-rw-r--r--gcc/testsuite/gcc.dg/spellcheck-options-3.c2
-rw-r--r--gcc/testsuite/gcc.dg/spellcheck-options-4.c2
-rw-r--r--gcc/testsuite/gcc.dg/spellcheck-options-5.c2
-rw-r--r--gcc/testsuite/gcc.dg/spellcheck-options-6.c2
-rw-r--r--gcc/testsuite/gcc.dg/spellcheck-options-7.c2
-rw-r--r--gcc/testsuite/gcc.dg/spellcheck-options-8.c2
-rw-r--r--gcc/testsuite/gcc.dg/spellcheck-options-9.c2
-rw-r--r--gcc/testsuite/gcc.dg/spellcheck-params-2.c2
-rw-r--r--gcc/testsuite/gcc.dg/spellcheck-params.c2
-rw-r--r--gcc/testsuite/gcc.dg/stack-usage-1.c2
-rw-r--r--gcc/testsuite/gcc.dg/store_merging_27.c2
-rw-r--r--gcc/testsuite/gcc.dg/store_merging_28.c2
-rw-r--r--gcc/testsuite/gcc.dg/store_merging_29.c4
-rw-r--r--gcc/testsuite/gcc.dg/store_merging_5.c6
-rw-r--r--gcc/testsuite/gcc.dg/strlenopt-49.c4
-rw-r--r--gcc/testsuite/gcc.dg/strlenopt-62.c190
-rw-r--r--gcc/testsuite/gcc.dg/strlenopt-63.c158
-rw-r--r--gcc/testsuite/gcc.dg/strlenopt-64.c182
-rw-r--r--gcc/testsuite/gcc.dg/strlenopt-65.c162
-rw-r--r--gcc/testsuite/gcc.dg/strlenopt-66.c72
-rw-r--r--gcc/testsuite/gcc.dg/strlenopt.h2
-rw-r--r--gcc/testsuite/gcc.dg/tm/pr52141.c2
-rw-r--r--gcc/testsuite/gcc.dg/torture/20190604-1.c21
-rw-r--r--gcc/testsuite/gcc.dg/torture/ftrapv-2.c2
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr51106-1.c2
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr51106-2.c2
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr71816.c2
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr87693.c1
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr89135.c2
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr89247.c1
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr90071.c2
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr90402-1.c26
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr90553.c128
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr90671.c16
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr90738.c20
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr90972.c24
-rw-r--r--gcc/testsuite/gcc.dg/torture/pta-ptrarith-3.c2
-rw-r--r--gcc/testsuite/gcc.dg/torture/stackalign/builtin-apply-2.c2
-rw-r--r--gcc/testsuite/gcc.dg/tree-prof/stringop-2.c5
-rw-r--r--gcc/testsuite/gcc.dg/tree-prof/val-prof-2.c5
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/20040204-1.c2
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/20040211-1.c2
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/alias-37.c18
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/alias-access-path-1.c21
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/alias-access-path-2.c22
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/alias-access-path-4.c24
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/alias-access-path-5.c25
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/alias-access-path-6.c29
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/alias-access-path-7.c20
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/cmpexactdiv-3.c10
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/cmpexactdiv-4.c10
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/cmpexactdiv-5.c11
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/dce-2.c37
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/dump-5.c15
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/dump-6.c38
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/gen-vect-2.c4
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/gen-vect-26.c4
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/gen-vect-28.c4
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/gen-vect-32.c2
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/ivopts-lt-2.c2
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/ivopts-lt.c2
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/ldist-26.c8
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/ldist-37.c10
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/ldist-38.c10
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/loop-10.c2
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/phi_on_compare-1.c30
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/phi_on_compare-2.c23
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/phi_on_compare-3.c25
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/phi_on_compare-4.c40
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/pr30375.c3
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/pr66726-4.c12
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/pr77445-2.c8
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/pr78886.c2
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/pr79697.c6
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/pr90340-2.c31
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/pr90340.c31
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/pr90478.c19
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/predcom-dse-1.c2
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/predcom-dse-2.c2
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/predcom-dse-3.c2
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/predcom-dse-4.c2
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/prefetch-7.c2
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/prefetch-8.c2
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/prefetch-9.c2
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/pta-callused.c2
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/reassoc-24.c4
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/reassoc-25.c4
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/reassoc-33.c2
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/reassoc-34.c2
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/reassoc-35.c2
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/reassoc-36.c2
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/scev-11.c2
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/slsr-27.c3
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/slsr-28.c2
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/slsr-29.c2
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/split-path-6.c2
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-cse-8.c15
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/ssa-dse-24.c2
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/ssa-dse-26.c2
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/ssa-dse-36.c65
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-69.c32
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/ssa-lim-13.c53
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/ssa-thread-12.c2
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/vector-6.c5
-rw-r--r--gcc/testsuite/gcc.dg/uninit-19.c4
-rw-r--r--gcc/testsuite/gcc.dg/uninit-28-gimple.c47
-rw-r--r--gcc/testsuite/gcc.dg/uninit-29-gimple.c45
-rw-r--r--gcc/testsuite/gcc.dg/uninit-30-gimple.c43
-rw-r--r--gcc/testsuite/gcc.dg/uninit-31-gimple.c48
-rw-r--r--gcc/testsuite/gcc.dg/uninit-pr90394-1-gimple.c47
-rw-r--r--gcc/testsuite/gcc.dg/uninit-pr90394.c33
-rw-r--r--gcc/testsuite/gcc.dg/utf-array-short-wchar.c14
-rw-r--r--gcc/testsuite/gcc.dg/utf-array.c14
-rw-r--r--gcc/testsuite/gcc.dg/utf8-2.c12
-rw-r--r--gcc/testsuite/gcc.dg/vect/O3-pr70130.c2
-rw-r--r--gcc/testsuite/gcc.dg/vect/costmodel/i386/costmodel-vect-31.c1
-rw-r--r--gcc/testsuite/gcc.dg/vect/costmodel/i386/costmodel-vect-33.c1
-rw-r--r--gcc/testsuite/gcc.dg/vect/costmodel/ppc/costmodel-vect-31b.c1
-rw-r--r--gcc/testsuite/gcc.dg/vect/costmodel/ppc/costmodel-vect-33.c1
-rw-r--r--gcc/testsuite/gcc.dg/vect/costmodel/ppc/costmodel-vect-76a.c1
-rw-r--r--gcc/testsuite/gcc.dg/vect/costmodel/ppc/costmodel-vect-76b.c1
-rw-r--r--gcc/testsuite/gcc.dg/vect/costmodel/ppc/costmodel-vect-76c.c1
-rw-r--r--gcc/testsuite/gcc.dg/vect/costmodel/x86_64/costmodel-vect-31.c1
-rw-r--r--gcc/testsuite/gcc.dg/vect/costmodel/x86_64/costmodel-vect-33.c1
-rw-r--r--gcc/testsuite/gcc.dg/vect/pr48765.c2
-rw-r--r--gcc/testsuite/gcc.dg/vect/vect-simd-1.c64
-rw-r--r--gcc/testsuite/gcc.dg/vect/vect-simd-10.c96
-rw-r--r--gcc/testsuite/gcc.dg/vect/vect-simd-11.c186
-rw-r--r--gcc/testsuite/gcc.dg/vect/vect-simd-12.c122
-rw-r--r--gcc/testsuite/gcc.dg/vect/vect-simd-13.c124
-rw-r--r--gcc/testsuite/gcc.dg/vect/vect-simd-14.c94
-rw-r--r--gcc/testsuite/gcc.dg/vect/vect-simd-15.c186
-rw-r--r--gcc/testsuite/gcc.dg/vect/vect-simd-2.c18
-rw-r--r--gcc/testsuite/gcc.dg/vect/vect-simd-3.c17
-rw-r--r--gcc/testsuite/gcc.dg/vect/vect-simd-4.c18
-rw-r--r--gcc/testsuite/gcc.dg/vect/vect-simd-5.c14
-rw-r--r--gcc/testsuite/gcc.dg/vect/vect-simd-6.c52
-rw-r--r--gcc/testsuite/gcc.dg/vect/vect-simd-7.c51
-rw-r--r--gcc/testsuite/gcc.dg/vect/vect-simd-8.c122
-rw-r--r--gcc/testsuite/gcc.dg/vect/vect-simd-9.c124
-rw-r--r--gcc/testsuite/gcc.dg/vect/vect-version-1.c20
-rw-r--r--gcc/testsuite/gcc.dg/vect/vect-version-2.c20
-rw-r--r--gcc/testsuite/gcc.dg/vect/vect.exp2
-rw-r--r--gcc/testsuite/gcc.dg/warn-abs-1.c6
-rw-r--r--gcc/testsuite/gcc.dg/warn-sprintf-no-nul.c2
-rw-r--r--gcc/testsuite/gcc.dg/weak/weak-19.c8
-rw-r--r--gcc/testsuite/gcc.misc-tests/gcov-pr90574-1.c20
-rw-r--r--gcc/testsuite/gcc.misc-tests/gcov-pr90574-2.c15
-rw-r--r--gcc/testsuite/gcc.misc-tests/linkage.exp2
-rw-r--r--gcc/testsuite/gcc.target/aarch64/pcs_attribute-2.c93
-rw-r--r--gcc/testsuite/gcc.target/aarch64/pcs_attribute-3.c58
-rw-r--r--gcc/testsuite/gcc.target/aarch64/pr88838.c11
-rw-r--r--gcc/testsuite/gcc.target/aarch64/return_address_sign_b_1.c52
-rw-r--r--gcc/testsuite/gcc.target/aarch64/return_address_sign_b_2.c18
-rw-r--r--gcc/testsuite/gcc.target/aarch64/return_address_sign_b_3.c22
-rw-r--r--gcc/testsuite/gcc.target/aarch64/return_address_sign_builtin.c16
-rw-r--r--gcc/testsuite/gcc.target/aarch64/signbitv2sf.c40
-rw-r--r--gcc/testsuite/gcc.target/aarch64/signbitv4sf.c38
-rw-r--r--gcc/testsuite/gcc.target/aarch64/ssadv16qi-dotprod.c31
-rw-r--r--gcc/testsuite/gcc.target/aarch64/ssadv16qi.c2
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/fabd_1.c35
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/fadda_1.c20
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/index_offset_1.c2
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/init_1.c26
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/init_10.c28
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/init_10_run.c21
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/init_11.c27
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/init_11_run.c20
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/init_12.c29
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/init_12_run.c20
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/init_1_run.c19
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/init_2.c29
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/init_2_run.c19
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/init_3.c27
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/init_3_run.c19
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/init_4.c30
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/init_4_run.c19
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/init_5.c26
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/init_5_run.c20
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/init_6.c27
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/init_6_run.c20
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/init_7.c31
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/init_7_run.c25
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/init_8.c32
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/init_8_run.c21
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/init_9.c26
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/init_9_run.c19
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/mask_load_slp_1.c90
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/pr88834.c15
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/single_1.c2
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/single_2.c2
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/single_3.c2
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/single_4.c2
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/struct_vect_1.c8
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/struct_vect_14.c8
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/struct_vect_15.c8
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/struct_vect_16.c8
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/struct_vect_17.c8
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/struct_vect_18.c2
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/struct_vect_19.c2
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/struct_vect_20.c2
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/struct_vect_21.c2
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/struct_vect_22.c2
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/struct_vect_23.c2
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/struct_vect_7.c8
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/unroll-1.c2
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/vec_init_1.c2
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/while_1.c17
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve2/aarch64-sve2.exp52
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve2/average_1.c46
-rw-r--r--gcc/testsuite/gcc.target/aarch64/target_attr_10.c2
-rw-r--r--gcc/testsuite/gcc.target/aarch64/torture/simd-abi-4.c3
-rw-r--r--gcc/testsuite/gcc.target/aarch64/usadv16qi-dotprod.c30
-rw-r--r--gcc/testsuite/gcc.target/aarch64/usadv16qi.c2
-rw-r--r--gcc/testsuite/gcc.target/aarch64/vect-fmovd-zero.c2
-rw-r--r--gcc/testsuite/gcc.target/aarch64/vect-fmovf-zero.c2
-rw-r--r--gcc/testsuite/gcc.target/arc/and-cnst-size.c16
-rw-r--r--gcc/testsuite/gcc.target/arc/arc700-stld-hazard.c5
-rw-r--r--gcc/testsuite/gcc.target/arc/cmem-1.c6
-rw-r--r--gcc/testsuite/gcc.target/arc/cmem-2.c6
-rw-r--r--gcc/testsuite/gcc.target/arc/cmem-3.c6
-rw-r--r--gcc/testsuite/gcc.target/arc/cmem-4.c6
-rw-r--r--gcc/testsuite/gcc.target/arc/cmem-5.c6
-rw-r--r--gcc/testsuite/gcc.target/arc/cmem-6.c6
-rw-r--r--gcc/testsuite/gcc.target/arc/jumptable.c2
-rw-r--r--gcc/testsuite/gcc.target/arc/loop-4.c3
-rw-r--r--gcc/testsuite/gcc.target/arc/mov-cnst-size.c42
-rw-r--r--gcc/testsuite/gcc.target/arc/movh_cl-1.c2
-rw-r--r--gcc/testsuite/gcc.target/arc/or-cnst-size.c16
-rw-r--r--gcc/testsuite/gcc.target/arc/pr89838.c16
-rw-r--r--gcc/testsuite/gcc.target/arc/sdata-3.c20
-rw-r--r--gcc/testsuite/gcc.target/arc/store-merge-1.c2
-rw-r--r--gcc/testsuite/gcc.target/arc/tmac-1.c3
-rw-r--r--gcc/testsuite/gcc.target/arc/tmac-2.c2
-rw-r--r--gcc/testsuite/gcc.target/arm/attr-neon-builtin-fail.c2
-rw-r--r--gcc/testsuite/gcc.target/arm/ivopts.c2
-rw-r--r--gcc/testsuite/gcc.target/arm/ssadv16qi.c29
-rw-r--r--gcc/testsuite/gcc.target/arm/usadv16qi.c29
-rw-r--r--gcc/testsuite/gcc.target/i386/asm-flag-0.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/attr-aligned-2.c4
-rw-r--r--gcc/testsuite/gcc.target/i386/avx-1.c4
-rw-r--r--gcc/testsuite/gcc.target/i386/avx2-pr90991-1.c50
-rw-r--r--gcc/testsuite/gcc.target/i386/avx2-vect-simd-10.c16
-rw-r--r--gcc/testsuite/gcc.target/i386/avx2-vect-simd-11.c16
-rw-r--r--gcc/testsuite/gcc.target/i386/avx2-vect-simd-12.c16
-rw-r--r--gcc/testsuite/gcc.target/i386/avx2-vect-simd-13.c16
-rw-r--r--gcc/testsuite/gcc.target/i386/avx2-vect-simd-14.c16
-rw-r--r--gcc/testsuite/gcc.target/i386/avx2-vect-simd-15.c16
-rw-r--r--gcc/testsuite/gcc.target/i386/avx2-vect-simd-8.c16
-rw-r--r--gcc/testsuite/gcc.target/i386/avx2-vect-simd-9.c16
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512-check.h3
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512bw-vect-simd-11.c16
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512bw-vect-simd-15.c16
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512bw-vpmovswb-1.c1
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512bw-vpmovuswb-1.c1
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512bw-vpmovwb-1.c1
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512dq-pr90991-1.c47
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512dq-pr90991-2.c47
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512dq-vfpclasspd-1.c12
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512dq-vfpclassps-1.c12
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512dq-vfpclasssd-1.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512dq-vfpclasssd-2.c75
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512dq-vfpclassss-1.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512dq-vfpclassss-2.c76
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512f-simd-1.c35
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512f-vcomisd-2.c104
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512f-vcomiss-2.c104
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512f-vect-simd-10.c16
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512f-vect-simd-12.c16
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512f-vect-simd-13.c16
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512f-vect-simd-14.c16
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512f-vect-simd-8.c16
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512f-vect-simd-9.c16
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512vp2intersect-2intersect-1a.c18
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512vp2intersect-2intersect-1b.c29
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512vp2intersect-2intersectvl-1a.c21
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512vp2intersect-2intersectvl-1b.c42
-rw-r--r--gcc/testsuite/gcc.target/i386/cet-label-3.c23
-rw-r--r--gcc/testsuite/gcc.target/i386/cet-label-4.c12
-rw-r--r--gcc/testsuite/gcc.target/i386/cet-label-5.c13
-rw-r--r--gcc/testsuite/gcc.target/i386/cet-notrack-5a.c3
-rw-r--r--gcc/testsuite/gcc.target/i386/cet-notrack-5b.c3
-rw-r--r--gcc/testsuite/gcc.target/i386/cet-notrack-6b.c3
-rw-r--r--gcc/testsuite/gcc.target/i386/cet-notrack-icf-1.c4
-rw-r--r--gcc/testsuite/gcc.target/i386/cet-notrack-icf-2.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/cet-notrack-icf-3.c4
-rw-r--r--gcc/testsuite/gcc.target/i386/cet-notrack-icf-4.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/cet-sjlj-3.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/cet-sjlj-5.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/cet-sjlj-6b.c1
-rw-r--r--gcc/testsuite/gcc.target/i386/cvtpd2pi.c36
-rw-r--r--gcc/testsuite/gcc.target/i386/enqcmd.c16
-rw-r--r--gcc/testsuite/gcc.target/i386/enqcmds.c15
-rw-r--r--gcc/testsuite/gcc.target/i386/falign-functions-2.c1
-rw-r--r--gcc/testsuite/gcc.target/i386/falign-functions-3.c9
-rw-r--r--gcc/testsuite/gcc.target/i386/fentry-override.c1
-rw-r--r--gcc/testsuite/gcc.target/i386/fentry.c1
-rw-r--r--gcc/testsuite/gcc.target/i386/fentryname1.c1
-rw-r--r--gcc/testsuite/gcc.target/i386/fentryname2.c1
-rw-r--r--gcc/testsuite/gcc.target/i386/fentryname3.c1
-rw-r--r--gcc/testsuite/gcc.target/i386/fnabs.c21
-rw-r--r--gcc/testsuite/gcc.target/i386/fuse-caller-save-rec.c8
-rw-r--r--gcc/testsuite/gcc.target/i386/fuse-caller-save-xmm.c16
-rw-r--r--gcc/testsuite/gcc.target/i386/fuse-caller-save.c8
-rw-r--r--gcc/testsuite/gcc.target/i386/gfni-4.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/gfni-5.c19
-rw-r--r--gcc/testsuite/gcc.target/i386/indirect-thunk-1.c13
-rw-r--r--gcc/testsuite/gcc.target/i386/indirect-thunk-2.c13
-rw-r--r--gcc/testsuite/gcc.target/i386/indirect-thunk-3.c13
-rw-r--r--gcc/testsuite/gcc.target/i386/indirect-thunk-4.c13
-rw-r--r--gcc/testsuite/gcc.target/i386/indirect-thunk-7.c11
-rw-r--r--gcc/testsuite/gcc.target/i386/indirect-thunk-attr-1.c13
-rw-r--r--gcc/testsuite/gcc.target/i386/indirect-thunk-attr-2.c13
-rw-r--r--gcc/testsuite/gcc.target/i386/indirect-thunk-attr-3.c13
-rw-r--r--gcc/testsuite/gcc.target/i386/indirect-thunk-attr-4.c13
-rw-r--r--gcc/testsuite/gcc.target/i386/indirect-thunk-attr-5.c13
-rw-r--r--gcc/testsuite/gcc.target/i386/indirect-thunk-attr-6.c13
-rw-r--r--gcc/testsuite/gcc.target/i386/indirect-thunk-attr-7.c11
-rw-r--r--gcc/testsuite/gcc.target/i386/indirect-thunk-attr-8.c9
-rw-r--r--gcc/testsuite/gcc.target/i386/indirect-thunk-extern-1.c13
-rw-r--r--gcc/testsuite/gcc.target/i386/indirect-thunk-extern-2.c13
-rw-r--r--gcc/testsuite/gcc.target/i386/indirect-thunk-extern-3.c13
-rw-r--r--gcc/testsuite/gcc.target/i386/indirect-thunk-extern-4.c10
-rw-r--r--gcc/testsuite/gcc.target/i386/indirect-thunk-extern-7.c9
-rw-r--r--gcc/testsuite/gcc.target/i386/indirect-thunk-inline-1.c13
-rw-r--r--gcc/testsuite/gcc.target/i386/indirect-thunk-inline-2.c13
-rw-r--r--gcc/testsuite/gcc.target/i386/indirect-thunk-inline-3.c13
-rw-r--r--gcc/testsuite/gcc.target/i386/indirect-thunk-inline-4.c13
-rw-r--r--gcc/testsuite/gcc.target/i386/indirect-thunk-inline-7.c9
-rw-r--r--gcc/testsuite/gcc.target/i386/indirect-thunk-register-1.c11
-rw-r--r--gcc/testsuite/gcc.target/i386/indirect-thunk-register-2.c9
-rw-r--r--gcc/testsuite/gcc.target/i386/indirect-thunk-register-3.c9
-rw-r--r--gcc/testsuite/gcc.target/i386/indirect-thunk-register-4.c3
-rw-r--r--gcc/testsuite/gcc.target/i386/inline_error.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/interrupt-6.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/interrupt-7.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/mcount_pic.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/memcpy-strategy-3.c5
-rw-r--r--gcc/testsuite/gcc.target/i386/memset-strategy-1.c6
-rw-r--r--gcc/testsuite/gcc.target/i386/mmx-vals.h77
-rw-r--r--gcc/testsuite/gcc.target/i386/nop-mcount.c1
-rw-r--r--gcc/testsuite/gcc.target/i386/pconfig-1.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/pr18041-1.c4
-rw-r--r--gcc/testsuite/gcc.target/i386/pr18041-2.c4
-rw-r--r--gcc/testsuite/gcc.target/i386/pr22076.c18
-rw-r--r--gcc/testsuite/gcc.target/i386/pr24414.c1
-rw-r--r--gcc/testsuite/gcc.target/i386/pr30848.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/pr30970.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/pr32219-1.c12
-rw-r--r--gcc/testsuite/gcc.target/i386/pr32219-2.c11
-rw-r--r--gcc/testsuite/gcc.target/i386/pr32219-3.c17
-rw-r--r--gcc/testsuite/gcc.target/i386/pr32219-4.c10
-rw-r--r--gcc/testsuite/gcc.target/i386/pr32219-5.c10
-rw-r--r--gcc/testsuite/gcc.target/i386/pr32219-6.c15
-rw-r--r--gcc/testsuite/gcc.target/i386/pr32219-7.c16
-rw-r--r--gcc/testsuite/gcc.target/i386/pr32219-8.c12
-rw-r--r--gcc/testsuite/gcc.target/i386/pr39013-1.c8
-rw-r--r--gcc/testsuite/gcc.target/i386/pr39013-2.c8
-rw-r--r--gcc/testsuite/gcc.target/i386/pr39082-1.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/pr39678.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/pr49866.c1
-rw-r--r--gcc/testsuite/gcc.target/i386/pr52146.c1
-rw-r--r--gcc/testsuite/gcc.target/i386/pr52698.c1
-rw-r--r--gcc/testsuite/gcc.target/i386/pr52857-1.c1
-rw-r--r--gcc/testsuite/gcc.target/i386/pr52857-2.c1
-rw-r--r--gcc/testsuite/gcc.target/i386/pr52876.c1
-rw-r--r--gcc/testsuite/gcc.target/i386/pr53698.c1
-rw-r--r--gcc/testsuite/gcc.target/i386/pr54157.c1
-rw-r--r--gcc/testsuite/gcc.target/i386/pr54855-1.c16
-rw-r--r--gcc/testsuite/gcc.target/i386/pr54855-10.c13
-rw-r--r--gcc/testsuite/gcc.target/i386/pr54855-2.c15
-rw-r--r--gcc/testsuite/gcc.target/i386/pr54855-3.c14
-rw-r--r--gcc/testsuite/gcc.target/i386/pr54855-4.c14
-rw-r--r--gcc/testsuite/gcc.target/i386/pr54855-5.c16
-rw-r--r--gcc/testsuite/gcc.target/i386/pr54855-6.c14
-rw-r--r--gcc/testsuite/gcc.target/i386/pr54855-7.c14
-rw-r--r--gcc/testsuite/gcc.target/i386/pr54855-8.c14
-rw-r--r--gcc/testsuite/gcc.target/i386/pr54855-9.c14
-rw-r--r--gcc/testsuite/gcc.target/i386/pr55049-1.c1
-rw-r--r--gcc/testsuite/gcc.target/i386/pr55093.c1
-rw-r--r--gcc/testsuite/gcc.target/i386/pr55116-1.c1
-rw-r--r--gcc/testsuite/gcc.target/i386/pr55116-2.c1
-rw-r--r--gcc/testsuite/gcc.target/i386/pr55597.c1
-rw-r--r--gcc/testsuite/gcc.target/i386/pr57756.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/pr59874-3.c3
-rw-r--r--gcc/testsuite/gcc.target/i386/pr59929.c1
-rw-r--r--gcc/testsuite/gcc.target/i386/pr61599-1.c1
-rw-r--r--gcc/testsuite/gcc.target/i386/pr63538.c4
-rw-r--r--gcc/testsuite/gcc.target/i386/pr63620.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/pr64317.c11
-rw-r--r--gcc/testsuite/gcc.target/i386/pr66470.c1
-rw-r--r--gcc/testsuite/gcc.target/i386/pr66819-3.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/pr66819-4.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/pr67985-2.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/pr68843-1.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/pr70738-7.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/pr77881.c4
-rw-r--r--gcc/testsuite/gcc.target/i386/pr79804.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/pr81563.c3
-rw-r--r--gcc/testsuite/gcc.target/i386/pr82483-1.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/pr82483-2.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/pr82659-3.c1
-rw-r--r--gcc/testsuite/gcc.target/i386/pr82662.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/pr82673.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/pr82699-2.c1
-rw-r--r--gcc/testsuite/gcc.target/i386/pr82699-4.c1
-rw-r--r--gcc/testsuite/gcc.target/i386/pr82699-5.c1
-rw-r--r--gcc/testsuite/gcc.target/i386/pr82699-6.c1
-rw-r--r--gcc/testsuite/gcc.target/i386/pr84723-1.c1
-rw-r--r--gcc/testsuite/gcc.target/i386/pr84723-2.c1
-rw-r--r--gcc/testsuite/gcc.target/i386/pr84723-3.c1
-rw-r--r--gcc/testsuite/gcc.target/i386/pr84723-4.c1
-rw-r--r--gcc/testsuite/gcc.target/i386/pr84723-5.c1
-rw-r--r--gcc/testsuite/gcc.target/i386/pr86257.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/pr88828-1.c49
-rw-r--r--gcc/testsuite/gcc.target/i386/pr88828-1a.c17
-rw-r--r--gcc/testsuite/gcc.target/i386/pr88828-1b.c23
-rw-r--r--gcc/testsuite/gcc.target/i386/pr88828-1c.c18
-rw-r--r--gcc/testsuite/gcc.target/i386/pr88828-4a.c18
-rw-r--r--gcc/testsuite/gcc.target/i386/pr88828-4b.c21
-rw-r--r--gcc/testsuite/gcc.target/i386/pr88828-5a.c18
-rw-r--r--gcc/testsuite/gcc.target/i386/pr88828-5b.c20
-rw-r--r--gcc/testsuite/gcc.target/i386/pr88828-7.c53
-rw-r--r--gcc/testsuite/gcc.target/i386/pr88828-7a.c16
-rw-r--r--gcc/testsuite/gcc.target/i386/pr88828-7b.c22
-rw-r--r--gcc/testsuite/gcc.target/i386/pr88828-8.c46
-rw-r--r--gcc/testsuite/gcc.target/i386/pr88828-8a.c15
-rw-r--r--gcc/testsuite/gcc.target/i386/pr88828-8b.c21
-rw-r--r--gcc/testsuite/gcc.target/i386/pr88828-9.c46
-rw-r--r--gcc/testsuite/gcc.target/i386/pr88828-9a.c16
-rw-r--r--gcc/testsuite/gcc.target/i386/pr88828-9b.c23
-rw-r--r--gcc/testsuite/gcc.target/i386/pr89261.c3
-rw-r--r--gcc/testsuite/gcc.target/i386/pr90497-1.c12
-rw-r--r--gcc/testsuite/gcc.target/i386/pr90497-2.c11
-rw-r--r--gcc/testsuite/gcc.target/i386/pr90500-1.c7
-rw-r--r--gcc/testsuite/gcc.target/i386/pr90500-2.c7
-rw-r--r--gcc/testsuite/gcc.target/i386/pr90510.c22
-rw-r--r--gcc/testsuite/gcc.target/i386/pr90547.c21
-rw-r--r--gcc/testsuite/gcc.target/i386/pr90552.c11
-rw-r--r--gcc/testsuite/gcc.target/i386/pr90765-1.c11
-rw-r--r--gcc/testsuite/gcc.target/i386/pr90765-2.c18
-rw-r--r--gcc/testsuite/gcc.target/i386/pr90856.c14
-rw-r--r--gcc/testsuite/gcc.target/i386/pr90899.c6
-rw-r--r--gcc/testsuite/gcc.target/i386/pr91033.c15
-rw-r--r--gcc/testsuite/gcc.target/i386/ptwrite2.c4
-rw-r--r--gcc/testsuite/gcc.target/i386/ret-thunk-1.c6
-rw-r--r--gcc/testsuite/gcc.target/i386/ret-thunk-10.c13
-rw-r--r--gcc/testsuite/gcc.target/i386/ret-thunk-11.c13
-rw-r--r--gcc/testsuite/gcc.target/i386/ret-thunk-12.c13
-rw-r--r--gcc/testsuite/gcc.target/i386/ret-thunk-13.c13
-rw-r--r--gcc/testsuite/gcc.target/i386/ret-thunk-14.c15
-rw-r--r--gcc/testsuite/gcc.target/i386/ret-thunk-15.c15
-rw-r--r--gcc/testsuite/gcc.target/i386/ret-thunk-16.c11
-rw-r--r--gcc/testsuite/gcc.target/i386/ret-thunk-2.c6
-rw-r--r--gcc/testsuite/gcc.target/i386/ret-thunk-22.c12
-rw-r--r--gcc/testsuite/gcc.target/i386/ret-thunk-23.c12
-rw-r--r--gcc/testsuite/gcc.target/i386/ret-thunk-24.c12
-rw-r--r--gcc/testsuite/gcc.target/i386/ret-thunk-3.c6
-rw-r--r--gcc/testsuite/gcc.target/i386/ret-thunk-4.c6
-rw-r--r--gcc/testsuite/gcc.target/i386/ret-thunk-5.c6
-rw-r--r--gcc/testsuite/gcc.target/i386/ret-thunk-6.c6
-rw-r--r--gcc/testsuite/gcc.target/i386/ret-thunk-7.c6
-rw-r--r--gcc/testsuite/gcc.target/i386/ret-thunk-8.c6
-rw-r--r--gcc/testsuite/gcc.target/i386/ret-thunk-9.c17
-rw-r--r--gcc/testsuite/gcc.target/i386/returninst1.c1
-rw-r--r--gcc/testsuite/gcc.target/i386/returninst2.c1
-rw-r--r--gcc/testsuite/gcc.target/i386/returninst3.c1
-rw-r--r--gcc/testsuite/gcc.target/i386/spellcheck-options-5.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/sse-12.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/sse-13.c6
-rw-r--r--gcc/testsuite/gcc.target/i386/sse-14.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/sse-22.c9
-rw-r--r--gcc/testsuite/gcc.target/i386/sse-23.c11
-rw-r--r--gcc/testsuite/gcc.target/i386/sse2-mmx-10.c43
-rw-r--r--gcc/testsuite/gcc.target/i386/sse2-mmx-11.c39
-rw-r--r--gcc/testsuite/gcc.target/i386/sse2-mmx-12.c42
-rw-r--r--gcc/testsuite/gcc.target/i386/sse2-mmx-13.c40
-rw-r--r--gcc/testsuite/gcc.target/i386/sse2-mmx-14.c31
-rw-r--r--gcc/testsuite/gcc.target/i386/sse2-mmx-15.c36
-rw-r--r--gcc/testsuite/gcc.target/i386/sse2-mmx-16.c40
-rw-r--r--gcc/testsuite/gcc.target/i386/sse2-mmx-17.c51
-rw-r--r--gcc/testsuite/gcc.target/i386/sse2-mmx-18a.c14
-rw-r--r--gcc/testsuite/gcc.target/i386/sse2-mmx-18b.c7
-rw-r--r--gcc/testsuite/gcc.target/i386/sse2-mmx-18c.c7
-rw-r--r--gcc/testsuite/gcc.target/i386/sse2-mmx-19a.c14
-rw-r--r--gcc/testsuite/gcc.target/i386/sse2-mmx-19b.c7
-rw-r--r--gcc/testsuite/gcc.target/i386/sse2-mmx-19c.c7
-rw-r--r--gcc/testsuite/gcc.target/i386/sse2-mmx-19d.c7
-rw-r--r--gcc/testsuite/gcc.target/i386/sse2-mmx-19e.c7
-rw-r--r--gcc/testsuite/gcc.target/i386/sse2-mmx-2.c12
-rw-r--r--gcc/testsuite/gcc.target/i386/sse2-mmx-20.c12
-rw-r--r--gcc/testsuite/gcc.target/i386/sse2-mmx-21.c13
-rw-r--r--gcc/testsuite/gcc.target/i386/sse2-mmx-22.c14
-rw-r--r--gcc/testsuite/gcc.target/i386/sse2-mmx-3.c13
-rw-r--r--gcc/testsuite/gcc.target/i386/sse2-mmx-4.c4
-rw-r--r--gcc/testsuite/gcc.target/i386/sse2-mmx-5.c11
-rw-r--r--gcc/testsuite/gcc.target/i386/sse2-mmx-6.c11
-rw-r--r--gcc/testsuite/gcc.target/i386/sse2-mmx-7.c13
-rw-r--r--gcc/testsuite/gcc.target/i386/sse2-mmx-8.c4
-rw-r--r--gcc/testsuite/gcc.target/i386/sse2-mmx-9.c79
-rw-r--r--gcc/testsuite/gcc.target/i386/sse2-mmx-cvtpi2ps.c43
-rw-r--r--gcc/testsuite/gcc.target/i386/sse2-mmx-cvtps2pi.c36
-rw-r--r--gcc/testsuite/gcc.target/i386/sse2-mmx-cvttps2pi.c36
-rw-r--r--gcc/testsuite/gcc.target/i386/sse2-mmx-maskmovq.c102
-rw-r--r--gcc/testsuite/gcc.target/i386/sse2-mmx-packssdw.c52
-rw-r--r--gcc/testsuite/gcc.target/i386/sse2-mmx-packsswb.c52
-rw-r--r--gcc/testsuite/gcc.target/i386/sse2-mmx-packuswb.c52
-rw-r--r--gcc/testsuite/gcc.target/i386/sse2-mmx-paddb.c48
-rw-r--r--gcc/testsuite/gcc.target/i386/sse2-mmx-paddd.c48
-rw-r--r--gcc/testsuite/gcc.target/i386/sse2-mmx-paddq.c43
-rw-r--r--gcc/testsuite/gcc.target/i386/sse2-mmx-paddsb.c48
-rw-r--r--gcc/testsuite/gcc.target/i386/sse2-mmx-paddsw.c48
-rw-r--r--gcc/testsuite/gcc.target/i386/sse2-mmx-paddusb.c48
-rw-r--r--gcc/testsuite/gcc.target/i386/sse2-mmx-paddusw.c48
-rw-r--r--gcc/testsuite/gcc.target/i386/sse2-mmx-paddw.c48
-rw-r--r--gcc/testsuite/gcc.target/i386/sse2-mmx-pand.c44
-rw-r--r--gcc/testsuite/gcc.target/i386/sse2-mmx-pandn.c44
-rw-r--r--gcc/testsuite/gcc.target/i386/sse2-mmx-pavgb.c52
-rw-r--r--gcc/testsuite/gcc.target/i386/sse2-mmx-pavgw.c52
-rw-r--r--gcc/testsuite/gcc.target/i386/sse2-mmx-pcmpeqb.c48
-rw-r--r--gcc/testsuite/gcc.target/i386/sse2-mmx-pcmpeqd.c48
-rw-r--r--gcc/testsuite/gcc.target/i386/sse2-mmx-pcmpeqw.c48
-rw-r--r--gcc/testsuite/gcc.target/i386/sse2-mmx-pcmpgtb.c48
-rw-r--r--gcc/testsuite/gcc.target/i386/sse2-mmx-pcmpgtd.c48
-rw-r--r--gcc/testsuite/gcc.target/i386/sse2-mmx-pcmpgtw.c48
-rw-r--r--gcc/testsuite/gcc.target/i386/sse2-mmx-pextrw.c59
-rw-r--r--gcc/testsuite/gcc.target/i386/sse2-mmx-pinsrw.c61
-rw-r--r--gcc/testsuite/gcc.target/i386/sse2-mmx-pmaddwd.c47
-rw-r--r--gcc/testsuite/gcc.target/i386/sse2-mmx-pmaxsw.c48
-rw-r--r--gcc/testsuite/gcc.target/i386/sse2-mmx-pmaxub.c48
-rw-r--r--gcc/testsuite/gcc.target/i386/sse2-mmx-pminsw.c48
-rw-r--r--gcc/testsuite/gcc.target/i386/sse2-mmx-pminub.c48
-rw-r--r--gcc/testsuite/gcc.target/i386/sse2-mmx-pmovmskb.c46
-rw-r--r--gcc/testsuite/gcc.target/i386/sse2-mmx-pmulhuw.c51
-rw-r--r--gcc/testsuite/gcc.target/i386/sse2-mmx-pmulhw.c53
-rw-r--r--gcc/testsuite/gcc.target/i386/sse2-mmx-pmullw.c52
-rw-r--r--gcc/testsuite/gcc.target/i386/sse2-mmx-pmuludq.c47
-rw-r--r--gcc/testsuite/gcc.target/i386/sse2-mmx-por.c44
-rw-r--r--gcc/testsuite/gcc.target/i386/sse2-mmx-psadbw.c58
-rw-r--r--gcc/testsuite/gcc.target/i386/sse2-mmx-pshufw.c248
-rw-r--r--gcc/testsuite/gcc.target/i386/sse2-mmx-pslld.c52
-rw-r--r--gcc/testsuite/gcc.target/i386/sse2-mmx-pslldi.c153
-rw-r--r--gcc/testsuite/gcc.target/i386/sse2-mmx-psllq.c47
-rw-r--r--gcc/testsuite/gcc.target/i386/sse2-mmx-psllqi.c245
-rw-r--r--gcc/testsuite/gcc.target/i386/sse2-mmx-psllw.c52
-rw-r--r--gcc/testsuite/gcc.target/i386/sse2-mmx-psllwi.c105
-rw-r--r--gcc/testsuite/gcc.target/i386/sse2-mmx-psrad.c52
-rw-r--r--gcc/testsuite/gcc.target/i386/sse2-mmx-psradi.c153
-rw-r--r--gcc/testsuite/gcc.target/i386/sse2-mmx-psraw.c52
-rw-r--r--gcc/testsuite/gcc.target/i386/sse2-mmx-psrawi.c105
-rw-r--r--gcc/testsuite/gcc.target/i386/sse2-mmx-psrld.c52
-rw-r--r--gcc/testsuite/gcc.target/i386/sse2-mmx-psrldi.c153
-rw-r--r--gcc/testsuite/gcc.target/i386/sse2-mmx-psrlq.c47
-rw-r--r--gcc/testsuite/gcc.target/i386/sse2-mmx-psrlqi.c245
-rw-r--r--gcc/testsuite/gcc.target/i386/sse2-mmx-psrlw.c52
-rw-r--r--gcc/testsuite/gcc.target/i386/sse2-mmx-psrlwi.c105
-rw-r--r--gcc/testsuite/gcc.target/i386/sse2-mmx-psubb.c48
-rw-r--r--gcc/testsuite/gcc.target/i386/sse2-mmx-psubd.c48
-rw-r--r--gcc/testsuite/gcc.target/i386/sse2-mmx-psubq.c43
-rw-r--r--gcc/testsuite/gcc.target/i386/sse2-mmx-psubusb.c48
-rw-r--r--gcc/testsuite/gcc.target/i386/sse2-mmx-psubusw.c48
-rw-r--r--gcc/testsuite/gcc.target/i386/sse2-mmx-psubw.c48
-rw-r--r--gcc/testsuite/gcc.target/i386/sse2-mmx-punpckhbw.c53
-rw-r--r--gcc/testsuite/gcc.target/i386/sse2-mmx-punpckhdq.c47
-rw-r--r--gcc/testsuite/gcc.target/i386/sse2-mmx-punpckhwd.c49
-rw-r--r--gcc/testsuite/gcc.target/i386/sse2-mmx-punpcklbw.c53
-rw-r--r--gcc/testsuite/gcc.target/i386/sse2-mmx-punpckldq.c47
-rw-r--r--gcc/testsuite/gcc.target/i386/sse2-mmx-punpcklwd.c49
-rw-r--r--gcc/testsuite/gcc.target/i386/sse2-mmx-pxor.c44
-rw-r--r--gcc/testsuite/gcc.target/i386/sse2-vect-simd-10.c15
-rw-r--r--gcc/testsuite/gcc.target/i386/sse2-vect-simd-11.c16
-rw-r--r--gcc/testsuite/gcc.target/i386/sse2-vect-simd-12.c16
-rw-r--r--gcc/testsuite/gcc.target/i386/sse2-vect-simd-13.c16
-rw-r--r--gcc/testsuite/gcc.target/i386/sse2-vect-simd-14.c15
-rw-r--r--gcc/testsuite/gcc.target/i386/sse2-vect-simd-15.c16
-rw-r--r--gcc/testsuite/gcc.target/i386/sse2-vect-simd-8.c16
-rw-r--r--gcc/testsuite/gcc.target/i386/sse2-vect-simd-9.c16
-rw-r--r--gcc/testsuite/gcc.target/i386/stack-prot-sym.c1
-rw-r--r--gcc/testsuite/gcc.target/i386/stackalign/pr88483-1.c18
-rw-r--r--gcc/testsuite/gcc.target/i386/stackalign/pr88483-2.c18
-rw-r--r--gcc/testsuite/gcc.target/i386/vect-double-1.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/vect-double-2.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/vect-signbitf.c30
-rw-r--r--gcc/testsuite/gcc.target/i386/wbinvd-1.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/wbnoinvd-1.c2
-rw-r--r--gcc/testsuite/gcc.target/mips/data-sym-multi-pool.c45
-rw-r--r--gcc/testsuite/gcc.target/mips/data-sym-pool.c5
-rw-r--r--gcc/testsuite/gcc.target/mips/dwarfregtable-1.c5
-rw-r--r--gcc/testsuite/gcc.target/mips/dwarfregtable-2.c5
-rw-r--r--gcc/testsuite/gcc.target/mips/dwarfregtable-3.c5
-rw-r--r--gcc/testsuite/gcc.target/mips/dwarfregtable-4.c5
-rw-r--r--gcc/testsuite/gcc.target/mips/dwarfregtable.h22
-rw-r--r--gcc/testsuite/gcc.target/mips/msa-fmadd.c101
-rw-r--r--gcc/testsuite/gcc.target/msp430/emulate-slli.c15
-rw-r--r--gcc/testsuite/gcc.target/msp430/emulate-srai.c15
-rw-r--r--gcc/testsuite/gcc.target/msp430/emulate-srli.c15
-rw-r--r--gcc/testsuite/gcc.target/msp430/mlarge-pedwarns.c11
-rw-r--r--gcc/testsuite/gcc.target/msp430/mspabi_sllll.c10
-rw-r--r--gcc/testsuite/gcc.target/msp430/mspabi_srall.c10
-rw-r--r--gcc/testsuite/gcc.target/msp430/mspabi_srlll.c10
-rw-r--r--gcc/testsuite/gcc.target/msp430/size-optimized-shifts.c26
-rw-r--r--gcc/testsuite/gcc.target/powerpc/bfp/bfp.exp6
-rw-r--r--gcc/testsuite/gcc.target/powerpc/builtins-1.c8
-rw-r--r--gcc/testsuite/gcc.target/powerpc/builtins-2.c1
-rw-r--r--gcc/testsuite/gcc.target/powerpc/cpu-future.c7
-rw-r--r--gcc/testsuite/gcc.target/powerpc/darwin-bool-1.c2
-rw-r--r--gcc/testsuite/gcc.target/powerpc/dfp/dfp.exp7
-rw-r--r--gcc/testsuite/gcc.target/powerpc/direct-move-double1.c1
-rw-r--r--gcc/testsuite/gcc.target/powerpc/direct-move-double2.c1
-rw-r--r--gcc/testsuite/gcc.target/powerpc/direct-move-float1.c1
-rw-r--r--gcc/testsuite/gcc.target/powerpc/direct-move-float2.c1
-rw-r--r--gcc/testsuite/gcc.target/powerpc/direct-move-vint1.c1
-rw-r--r--gcc/testsuite/gcc.target/powerpc/direct-move-vint2.c1
-rw-r--r--gcc/testsuite/gcc.target/powerpc/fold-vec-splats-floatdouble.c8
-rw-r--r--gcc/testsuite/gcc.target/powerpc/localentry-1.c20
-rw-r--r--gcc/testsuite/gcc.target/powerpc/localentry-detect-1.c15
-rw-r--r--gcc/testsuite/gcc.target/powerpc/maddld-1.c21
-rw-r--r--gcc/testsuite/gcc.target/powerpc/mmfpgpr.c22
-rw-r--r--gcc/testsuite/gcc.target/powerpc/notoc-direct-1.c43
-rw-r--r--gcc/testsuite/gcc.target/powerpc/p9-dimode1.c14
-rw-r--r--gcc/testsuite/gcc.target/powerpc/p9-dimode2.c14
-rw-r--r--gcc/testsuite/gcc.target/powerpc/pcrel-sibcall-1.c50
-rw-r--r--gcc/testsuite/gcc.target/powerpc/ppc32-abi-dfp-1.c16
-rw-r--r--gcc/testsuite/gcc.target/powerpc/ppc64-abi-warn-1.c2
-rw-r--r--gcc/testsuite/gcc.target/powerpc/pr62147.c24
-rw-r--r--gcc/testsuite/gcc.target/powerpc/pr64205.c1
-rw-r--r--gcc/testsuite/gcc.target/powerpc/pr71785.c7
-rw-r--r--gcc/testsuite/gcc.target/powerpc/pr79909.c1
-rw-r--r--gcc/testsuite/gcc.target/powerpc/pr80125.c2
-rw-r--r--gcc/testsuite/gcc.target/powerpc/pr80315-1.c2
-rw-r--r--gcc/testsuite/gcc.target/powerpc/pr80315-2.c2
-rw-r--r--gcc/testsuite/gcc.target/powerpc/pr80315-3.c2
-rw-r--r--gcc/testsuite/gcc.target/powerpc/pr80315-4.c2
-rw-r--r--gcc/testsuite/gcc.target/powerpc/safe-indirect-jump-1.c1
-rw-r--r--gcc/testsuite/gcc.target/powerpc/safe-indirect-jump-7.c1
-rw-r--r--gcc/testsuite/gcc.target/powerpc/spec-barr-1.c2
-rw-r--r--gcc/testsuite/gcc.target/powerpc/vsx-vectorize-1.c2
-rw-r--r--gcc/testsuite/gcc.target/powerpc/warn-lvsl-lvsr.c4
-rw-r--r--gcc/testsuite/gcc.target/pru/abi-arg-struct.c164
-rw-r--r--gcc/testsuite/gcc.target/pru/ashiftrt.c13
-rw-r--r--gcc/testsuite/gcc.target/pru/builtins-1.c12
-rw-r--r--gcc/testsuite/gcc.target/pru/builtins-error.c6
-rw-r--r--gcc/testsuite/gcc.target/pru/clearbit.c13
-rw-r--r--gcc/testsuite/gcc.target/pru/loop-asm.c19
-rw-r--r--gcc/testsuite/gcc.target/pru/loop-dowhile.c45
-rw-r--r--gcc/testsuite/gcc.target/pru/loop-hi-1.c38
-rw-r--r--gcc/testsuite/gcc.target/pru/loop-hi-2.c17
-rw-r--r--gcc/testsuite/gcc.target/pru/loop-qi-1.c38
-rw-r--r--gcc/testsuite/gcc.target/pru/loop-qi-2.c17
-rw-r--r--gcc/testsuite/gcc.target/pru/loop-short-1.c53
-rw-r--r--gcc/testsuite/gcc.target/pru/loop-short-2.c21
-rw-r--r--gcc/testsuite/gcc.target/pru/loop-si-1.c41
-rw-r--r--gcc/testsuite/gcc.target/pru/loop-si-2.c20
-rw-r--r--gcc/testsuite/gcc.target/pru/loop-u8_pcrel_overflow.c42
-rw-r--r--gcc/testsuite/gcc.target/pru/loop-ubyte-1.c30
-rw-r--r--gcc/testsuite/gcc.target/pru/loop-ubyte-2.c18
-rw-r--r--gcc/testsuite/gcc.target/pru/lra-framepointer-fragmentation-1.c33
-rw-r--r--gcc/testsuite/gcc.target/pru/lra-framepointer-fragmentation-2.c61
-rw-r--r--gcc/testsuite/gcc.target/pru/mabi-ti-1.c10
-rw-r--r--gcc/testsuite/gcc.target/pru/mabi-ti-2.c15
-rw-r--r--gcc/testsuite/gcc.target/pru/mabi-ti-3.c12
-rw-r--r--gcc/testsuite/gcc.target/pru/mabi-ti-4.c14
-rw-r--r--gcc/testsuite/gcc.target/pru/mabi-ti-5.c33
-rw-r--r--gcc/testsuite/gcc.target/pru/mabi-ti-6.c12
-rw-r--r--gcc/testsuite/gcc.target/pru/mabi-ti-7.c21
-rw-r--r--gcc/testsuite/gcc.target/pru/pr64366.c128
-rw-r--r--gcc/testsuite/gcc.target/pru/pragma-ctable_entry.c22
-rw-r--r--gcc/testsuite/gcc.target/pru/pru.exp41
-rw-r--r--gcc/testsuite/gcc.target/pru/qbbc-1.c29
-rw-r--r--gcc/testsuite/gcc.target/pru/qbbc-2.c15
-rw-r--r--gcc/testsuite/gcc.target/pru/qbbc-3.c15
-rw-r--r--gcc/testsuite/gcc.target/pru/qbbs-1.c29
-rw-r--r--gcc/testsuite/gcc.target/pru/qbbs-2.c15
-rw-r--r--gcc/testsuite/gcc.target/pru/setbit.c13
-rw-r--r--gcc/testsuite/gcc.target/pru/zero_extend-and-hisi.c16
-rw-r--r--gcc/testsuite/gcc.target/pru/zero_extend-and-qihi.c16
-rw-r--r--gcc/testsuite/gcc.target/pru/zero_extend-and-qisi.c16
-rw-r--r--gcc/testsuite/gcc.target/pru/zero_extend-hisi.c43
-rw-r--r--gcc/testsuite/gcc.target/pru/zero_extend-qihi.c43
-rw-r--r--gcc/testsuite/gcc.target/pru/zero_extend-qisi.c43
-rw-r--r--gcc/testsuite/gcc.target/s390/global-array-element-pic.c2
-rw-r--r--gcc/testsuite/gcc.target/s390/global-array-element-pic2.c13
-rw-r--r--gcc/testsuite/gcc.target/s390/pr91014.c8
-rw-r--r--gcc/testsuite/gcc.target/s390/vector/vec-shift-2.c24
-rw-r--r--gcc/testsuite/gcc.target/s390/zvector/vec-sldw.c55
-rw-r--r--gcc/testsuite/gcc.target/sh/pr50749-qihisi-predec-3.c2
-rw-r--r--gcc/testsuite/gcc.target/sh/pr51244-20.c2
-rw-r--r--gcc/testsuite/gcc.target/x86_64/abi/avx/test_varargs-m256.c104
-rw-r--r--gcc/testsuite/gcc.target/x86_64/abi/avx512f/abi-avx512f.exp1
-rw-r--r--gcc/testsuite/gcc.target/x86_64/abi/avx512f/asm-support-darwin.s93
-rw-r--r--gcc/testsuite/gcc.target/x86_64/abi/avx512f/test_varargs-m512.c104
-rw-r--r--gcc/testsuite/gcc.target/x86_64/abi/test_varargs-m128.c110
-rw-r--r--gcc/testsuite/gdc.dg/pr90650a.d14
-rw-r--r--gcc/testsuite/gdc.dg/pr90650b.d13
-rw-r--r--gcc/testsuite/gdc.test/compilable/aggr_alignment.d13
-rw-r--r--gcc/testsuite/gdc.test/compilable/b16976.d66
-rw-r--r--gcc/testsuite/gdc.test/compilable/imports/test16214b.d10
-rw-r--r--gcc/testsuite/gdc.test/compilable/interpret3.d20
-rw-r--r--gcc/testsuite/gdc.test/compilable/test16214a.d7
-rw-r--r--gcc/testsuite/gdc.test/compilable/test19912.d3
-rw-r--r--gcc/testsuite/gdc.test/compilable/test19941.d57
-rw-r--r--gcc/testsuite/gdc.test/compilable/traits.d10
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/b15875.d10
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/b17285.d15
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/b19691.d20
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/b19691e.d24
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/b19717.d16
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/b19717a.d14
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/diag16976.d44
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/extra-files/minimal/object.d1
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/fail110.d2
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/fail19890a.d7
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/fail19890b.d7
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/fail19897.d13
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/fail19898a.d14
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/fail19898b.d21
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/fail19911a.d11
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/fail19911b.d13
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/fail19911c.d17
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/fail19912a.d9
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/fail19912b.d9
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/fail19912c.d9
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/fail19912d.d9
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/fail19912e.d9
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/fail19913.d13
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/fail19914.d10
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/fail19915.d10
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/fail19922.d19
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/fail19923.d19
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/fail19941.d62
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/fail19955.d8
-rw-r--r--gcc/testsuite/gdc.test/fail_compilation/staticarrayoverflow.d16
-rw-r--r--gcc/testsuite/gfortran.dg/ISO_Fortran_binding_12.c29
-rw-r--r--gcc/testsuite/gfortran.dg/ISO_Fortran_binding_12.f9053
-rw-r--r--gcc/testsuite/gfortran.dg/ISO_Fortran_binding_4.f9028
-rw-r--r--gcc/testsuite/gfortran.dg/alloc_comp_auto_array_3.f902
-rw-r--r--gcc/testsuite/gfortran.dg/assign_10.f902
-rw-r--r--gcc/testsuite/gfortran.dg/associate_48.f9041
-rw-r--r--gcc/testsuite/gfortran.dg/assumed_rank_bounds_3.f90219
-rw-r--r--gcc/testsuite/gfortran.dg/assumed_type_10.f9046
-rw-r--r--gcc/testsuite/gfortran.dg/assumed_type_11.f9046
-rw-r--r--gcc/testsuite/gfortran.dg/assumed_type_2.f904
-rw-r--r--gcc/testsuite/gfortran.dg/assumed_type_2a.f90139
-rw-r--r--gcc/testsuite/gfortran.dg/c_loc_test_22.f902
-rw-r--r--gcc/testsuite/gfortran.dg/coarray_lock_7.f904
-rw-r--r--gcc/testsuite/gfortran.dg/common_1.f14
-rw-r--r--gcc/testsuite/gfortran.dg/common_26.f9014
-rw-r--r--gcc/testsuite/gfortran.dg/contiguous_3.f902
-rw-r--r--gcc/testsuite/gfortran.dg/dec_format_empty_item_1.f19
-rw-r--r--gcc/testsuite/gfortran.dg/dec_format_empty_item_2.f19
-rw-r--r--gcc/testsuite/gfortran.dg/dec_format_empty_item_3.f19
-rw-r--r--gcc/testsuite/gfortran.dg/dec_io_1.f902
-rw-r--r--gcc/testsuite/gfortran.dg/deferred_character_33.f9035
-rw-r--r--gcc/testsuite/gfortran.dg/deferred_character_33a.f909
-rw-r--r--gcc/testsuite/gfortran.dg/dtio_1.f902
-rw-r--r--gcc/testsuite/gfortran.dg/dtio_12.f902
-rw-r--r--gcc/testsuite/gfortran.dg/dummy_derived_typed.f905
-rw-r--r--gcc/testsuite/gfortran.dg/dummy_procedure_8.f904
-rw-r--r--gcc/testsuite/gfortran.dg/external_procedure_4.f9019
-rw-r--r--gcc/testsuite/gfortran.dg/fmt_en.f902
-rw-r--r--gcc/testsuite/gfortran.dg/fmt_f_default_field_width_1.f9045
-rw-r--r--gcc/testsuite/gfortran.dg/fmt_f_default_field_width_2.f9048
-rw-r--r--gcc/testsuite/gfortran.dg/fmt_f_default_field_width_3.f9035
-rw-r--r--gcc/testsuite/gfortran.dg/fmt_g_default_field_width_1.f9050
-rw-r--r--gcc/testsuite/gfortran.dg/fmt_g_default_field_width_2.f9053
-rw-r--r--gcc/testsuite/gfortran.dg/fmt_g_default_field_width_3.f9038
-rw-r--r--gcc/testsuite/gfortran.dg/fmt_i_default_field_width_1.f9040
-rw-r--r--gcc/testsuite/gfortran.dg/fmt_i_default_field_width_2.f9044
-rw-r--r--gcc/testsuite/gfortran.dg/fmt_i_default_field_width_3.f9037
-rw-r--r--gcc/testsuite/gfortran.dg/goacc/classify-routine.f954
-rw-r--r--gcc/testsuite/gfortran.dg/goacc/declare-3.f9553
-rw-r--r--gcc/testsuite/gfortran.dg/goacc/pr78027.f904
-rw-r--r--gcc/testsuite/gfortran.dg/goacc/routine-level-of-parallelism-1.f906
-rw-r--r--gcc/testsuite/gfortran.dg/ieee/ieee_4.f902
-rw-r--r--gcc/testsuite/gfortran.dg/integer_exponentiation_4.f908
-rw-r--r--gcc/testsuite/gfortran.dg/integer_exponentiation_5.F902
-rw-r--r--gcc/testsuite/gfortran.dg/internal_pack_11.f902
-rw-r--r--gcc/testsuite/gfortran.dg/internal_pack_12.f902
-rw-r--r--gcc/testsuite/gfortran.dg/internal_pack_16.f902
-rw-r--r--gcc/testsuite/gfortran.dg/internal_pack_17.f902
-rw-r--r--gcc/testsuite/gfortran.dg/internal_pack_18.f902
-rw-r--r--gcc/testsuite/gfortran.dg/internal_pack_19.f9023
-rw-r--r--gcc/testsuite/gfortran.dg/internal_pack_20.f9023
-rw-r--r--gcc/testsuite/gfortran.dg/internal_pack_21.f9024
-rw-r--r--gcc/testsuite/gfortran.dg/internal_pack_22.f9036
-rw-r--r--gcc/testsuite/gfortran.dg/internal_pack_23.f9027
-rw-r--r--gcc/testsuite/gfortran.dg/internal_pack_24.f9039
-rw-r--r--gcc/testsuite/gfortran.dg/internal_pack_4.f904
-rw-r--r--gcc/testsuite/gfortran.dg/internal_pack_5.f902
-rw-r--r--gcc/testsuite/gfortran.dg/internal_pack_6.f904
-rw-r--r--gcc/testsuite/gfortran.dg/internal_pack_6a.f9056
-rw-r--r--gcc/testsuite/gfortran.dg/internal_pack_9.f902
-rw-r--r--gcc/testsuite/gfortran.dg/io_constraints_14.f9013
-rw-r--r--gcc/testsuite/gfortran.dg/iso_c_binding_char_1.f9010
-rw-r--r--gcc/testsuite/gfortran.dg/lrshift_1.f902
-rw-r--r--gcc/testsuite/gfortran.dg/missing_optional_dummy_6.f9011
-rw-r--r--gcc/testsuite/gfortran.dg/missing_optional_dummy_6a.f9059
-rw-r--r--gcc/testsuite/gfortran.dg/module_error_1.f902
-rw-r--r--gcc/testsuite/gfortran.dg/namelist_89.f902
-rw-r--r--gcc/testsuite/gfortran.dg/no_arg_check_2.f904
-rw-r--r--gcc/testsuite/gfortran.dg/no_arg_check_2a.f90121
-rw-r--r--gcc/testsuite/gfortran.dg/no_range_check_1.f903
-rw-r--r--gcc/testsuite/gfortran.dg/open_errors_2.f903
-rw-r--r--gcc/testsuite/gfortran.dg/open_errors_3.f9011
-rw-r--r--gcc/testsuite/gfortran.dg/pr51991.f9021
-rw-r--r--gcc/testsuite/gfortran.dg/pr67884.f9021
-rw-r--r--gcc/testsuite/gfortran.dg/pr68544.f9013
-rw-r--r--gcc/testsuite/gfortran.dg/pr69398.f9011
-rw-r--r--gcc/testsuite/gfortran.dg/pr69499.f907
-rw-r--r--gcc/testsuite/gfortran.dg/pr77632_1.f907
-rw-r--r--gcc/testsuite/gfortran.dg/pr78290.f9035
-rw-r--r--gcc/testsuite/gfortran.dg/pr85687.f902
-rw-r--r--gcc/testsuite/gfortran.dg/pr86587.f9018
-rw-r--r--gcc/testsuite/gfortran.dg/pr87907.f9023
-rw-r--r--gcc/testsuite/gfortran.dg/pr89344.f9015
-rw-r--r--gcc/testsuite/gfortran.dg/pr89646.f9024
-rw-r--r--gcc/testsuite/gfortran.dg/pr90002.f906
-rw-r--r--gcc/testsuite/gfortran.dg/pr90385.f906
-rw-r--r--gcc/testsuite/gfortran.dg/pr90988_1.f9014
-rw-r--r--gcc/testsuite/gfortran.dg/pr90988_2.f9014
-rw-r--r--gcc/testsuite/gfortran.dg/pr90988_3.f9014
-rw-r--r--gcc/testsuite/gfortran.dg/proc_ptr_51.f9038
-rw-r--r--gcc/testsuite/gfortran.dg/shiftalr_3.f9042
-rw-r--r--gcc/testsuite/gfortran.dg/transpose_optimization_2.f902
-rw-r--r--gcc/testsuite/gfortran.dg/typebound_assignment_5.f034
-rw-r--r--gcc/testsuite/gfortran.dg/typebound_assignment_5a.f0339
-rw-r--r--gcc/testsuite/gfortran.dg/typebound_assignment_6.f034
-rw-r--r--gcc/testsuite/gfortran.dg/typebound_assignment_6a.f0342
-rw-r--r--gcc/testsuite/gfortran.dg/vect/pr45714-b.f2
-rw-r--r--gcc/testsuite/gfortran.dg/vect/pr90681.f13
-rw-r--r--gcc/testsuite/gfortran.dg/vect/pr90913.f9022
-rw-r--r--gcc/testsuite/gfortran.dg/vect/vect-5.f902
-rw-r--r--gcc/testsuite/gfortran.dg/vect/vect-8.f902
-rw-r--r--gcc/testsuite/gnat.dg/aliased2.adb23
-rw-r--r--gcc/testsuite/gnat.dg/alignment14.adb17
-rw-r--r--gcc/testsuite/gnat.dg/array35.adb24
-rw-r--r--gcc/testsuite/gnat.dg/array36.adb28
-rw-r--r--gcc/testsuite/gnat.dg/derived_type6.adb5
-rw-r--r--gcc/testsuite/gnat.dg/derived_type6.ads9
-rw-r--r--gcc/testsuite/gnat.dg/dynhash.adb41
-rw-r--r--gcc/testsuite/gnat.dg/dynhash1.adb8
-rw-r--r--gcc/testsuite/gnat.dg/enum_rep.adb5
-rw-r--r--gcc/testsuite/gnat.dg/enum_rep.ads22
-rw-r--r--gcc/testsuite/gnat.dg/expect2.adb24
-rw-r--r--gcc/testsuite/gnat.dg/expect2_pkg.ads15
-rw-r--r--gcc/testsuite/gnat.dg/freezing1.adb5
-rw-r--r--gcc/testsuite/gnat.dg/freezing1.ads10
-rw-r--r--gcc/testsuite/gnat.dg/freezing1_pack.adb8
-rw-r--r--gcc/testsuite/gnat.dg/freezing1_pack.ads16
-rw-r--r--gcc/testsuite/gnat.dg/generic_inst3.adb20
-rw-r--r--gcc/testsuite/gnat.dg/generic_inst3_kafka_lib-topic.ads7
-rw-r--r--gcc/testsuite/gnat.dg/generic_inst3_kafka_lib.ads2
-rw-r--r--gcc/testsuite/gnat.dg/generic_inst3_markets.ads10
-rw-r--r--gcc/testsuite/gnat.dg/generic_inst3_traits-encodables.ads8
-rw-r--r--gcc/testsuite/gnat.dg/generic_inst3_traits.ads3
-rw-r--r--gcc/testsuite/gnat.dg/inline15.adb11
-rw-r--r--gcc/testsuite/gnat.dg/inline15_gen.adb27
-rw-r--r--gcc/testsuite/gnat.dg/inline15_gen.ads11
-rw-r--r--gcc/testsuite/gnat.dg/inline15_types.ads17
-rw-r--r--gcc/testsuite/gnat.dg/inline16.adb26
-rw-r--r--gcc/testsuite/gnat.dg/inline16_gen.adb16
-rw-r--r--gcc/testsuite/gnat.dg/inline16_gen.ads9
-rw-r--r--gcc/testsuite/gnat.dg/inline16_types.ads7
-rw-r--r--gcc/testsuite/gnat.dg/inline3.adb2
-rw-r--r--gcc/testsuite/gnat.dg/inline5.adb2
-rw-r--r--gcc/testsuite/gnat.dg/inline7.adb2
-rw-r--r--gcc/testsuite/gnat.dg/inline9.adb2
-rw-r--r--gcc/testsuite/gnat.dg/limited_with7.adb12
-rw-r--r--gcc/testsuite/gnat.dg/limited_with7.ads7
-rw-r--r--gcc/testsuite/gnat.dg/limited_with7_pkg.ads9
-rw-r--r--gcc/testsuite/gnat.dg/linkedlist.adb72
-rw-r--r--gcc/testsuite/gnat.dg/machine_attr1.adb41
-rw-r--r--gcc/testsuite/gnat.dg/machine_attr1.ads25
-rw-r--r--gcc/testsuite/gnat.dg/opt39.adb3
-rw-r--r--gcc/testsuite/gnat.dg/opt78.adb16
-rw-r--r--gcc/testsuite/gnat.dg/opt78.ads13
-rw-r--r--gcc/testsuite/gnat.dg/opt79.adb28
-rw-r--r--gcc/testsuite/gnat.dg/opt79.ads7
-rw-r--r--gcc/testsuite/gnat.dg/predicate4.adb19
-rw-r--r--gcc/testsuite/gnat.dg/predicate4_pkg.ads16
-rw-r--r--gcc/testsuite/gnat.dg/predicate5.adb5
-rw-r--r--gcc/testsuite/gnat.dg/predicate5.ads17
-rw-r--r--gcc/testsuite/gnat.dg/predicate6.adb5
-rw-r--r--gcc/testsuite/gnat.dg/predicate6.ads10
-rw-r--r--gcc/testsuite/gnat.dg/prefetch1.adb29
-rw-r--r--gcc/testsuite/gnat.dg/prefetch1.ads9
-rw-r--r--gcc/testsuite/gnat.dg/prot7.adb22
-rw-r--r--gcc/testsuite/gnat.dg/prot7.ads16
-rw-r--r--gcc/testsuite/gnat.dg/renaming13.adb21
-rw-r--r--gcc/testsuite/gnat.dg/renaming14.adb32
-rw-r--r--gcc/testsuite/gnat.dg/sets1.adb48
-rw-r--r--gcc/testsuite/gnat.dg/specs/array4.ads17
-rw-r--r--gcc/testsuite/gnat.dg/specs/array5.ads9
-rw-r--r--gcc/testsuite/gnat.dg/specs/array5_pkg1.ads14
-rw-r--r--gcc/testsuite/gnat.dg/specs/array5_pkg2-g.ads13
-rw-r--r--gcc/testsuite/gnat.dg/specs/array5_pkg2.ads5
-rw-r--r--gcc/testsuite/gnat.dg/specs/atomic2.ads2
-rw-r--r--gcc/testsuite/gnat.dg/specs/clause_on_volatile.ads4
-rw-r--r--gcc/testsuite/gnat.dg/specs/debug1.ads18
-rw-r--r--gcc/testsuite/gnat.dg/specs/discr5.ads57
-rw-r--r--gcc/testsuite/gnat.dg/specs/discr6.ads21
-rw-r--r--gcc/testsuite/gnat.dg/specs/size_clause3.ads4
-rw-r--r--gcc/testsuite/gnat.dg/specs/unchecked_convert1.ads20
-rw-r--r--gcc/testsuite/gnat.dg/specs/unchecked_convert2.ads19
-rw-r--r--gcc/testsuite/gnat.dg/static_pred1.adb2
-rw-r--r--gcc/testsuite/gnat.dg/task2.adb9
-rw-r--r--gcc/testsuite/gnat.dg/task2_pkg.adb6
-rw-r--r--gcc/testsuite/gnat.dg/task2_pkg.ads4
-rw-r--r--gcc/testsuite/gnat.dg/unchecked_convert13.adb30
-rw-r--r--gcc/testsuite/gnat.dg/warn20.adb11
-rw-r--r--gcc/testsuite/gnat.dg/warn20_pkg.adb10
-rw-r--r--gcc/testsuite/gnat.dg/warn20_pkg.ads8
-rw-r--r--gcc/testsuite/gnat.dg/weak3.adb11
-rw-r--r--gcc/testsuite/gnat.dg/weak3.ads3
-rw-r--r--gcc/testsuite/go.dg/concatstring.go8
-rw-r--r--gcc/testsuite/go.dg/mapstring.go11
-rw-r--r--gcc/testsuite/go.test/test/blank1.go6
-rw-r--r--gcc/testsuite/go.test/test/nilptr2.go5
-rw-r--r--gcc/testsuite/lib/gcc-dg.exp11
-rw-r--r--gcc/testsuite/lib/scanasm.exp5
-rw-r--r--gcc/testsuite/lib/target-supports.exp225
-rw-r--r--gcc/testsuite/lib/target-utils.exp12
-rw-r--r--gcc/testsuite/obj-c++.dg/class-protocol-1.mm4
-rw-r--r--gcc/testsuite/obj-c++.dg/cxx-ivars-3.mm5
-rw-r--r--gcc/testsuite/obj-c++.dg/exceptions-3.mm16
-rw-r--r--gcc/testsuite/obj-c++.dg/exceptions-4.mm8
-rw-r--r--gcc/testsuite/obj-c++.dg/exceptions-5.mm16
-rw-r--r--gcc/testsuite/obj-c++.dg/exceptions-6.mm2
-rw-r--r--gcc/testsuite/obj-c++.dg/isa-field-1.mm2
-rw-r--r--gcc/testsuite/obj-c++.dg/method-12.mm4
-rw-r--r--gcc/testsuite/obj-c++.dg/method-13.mm7
-rw-r--r--gcc/testsuite/obj-c++.dg/method-6.mm8
-rw-r--r--gcc/testsuite/obj-c++.dg/method-7.mm8
-rw-r--r--gcc/testsuite/obj-c++.dg/method-9.mm5
-rw-r--r--gcc/testsuite/obj-c++.dg/method-lookup-1.mm4
-rw-r--r--gcc/testsuite/obj-c++.dg/objc-gc-3.mm1
-rw-r--r--gcc/testsuite/obj-c++.dg/property/dotsyntax-17.mm10
-rw-r--r--gcc/testsuite/obj-c++.dg/property/property-neg-7.mm8
-rw-r--r--gcc/testsuite/obj-c++.dg/proto-lossage-4.mm4
-rw-r--r--gcc/testsuite/obj-c++.dg/proto-lossage-7.mm4
-rw-r--r--gcc/testsuite/obj-c++.dg/protocol-qualifier-2.mm5
-rw-r--r--gcc/testsuite/obj-c++.dg/qual-types-1.mm2
-rw-r--r--gcc/testsuite/obj-c++.dg/strings/const-cfstring-2.mm4
-rw-r--r--gcc/testsuite/obj-c++.dg/strings/const-cfstring-5.mm2
-rw-r--r--gcc/testsuite/obj-c++.dg/strings/const-str-12.mm2
-rw-r--r--gcc/testsuite/obj-c++.dg/stubify-1.mm20
-rw-r--r--gcc/testsuite/obj-c++.dg/stubify-2.mm16
-rw-r--r--gcc/testsuite/obj-c++.dg/syntax-error-1.mm4
-rw-r--r--gcc/testsuite/obj-c++.dg/torture/strings/const-cfstring-1.mm12
-rw-r--r--gcc/testsuite/obj-c++.dg/torture/strings/const-str-10.mm2
-rw-r--r--gcc/testsuite/obj-c++.dg/torture/strings/const-str-11.mm2
-rw-r--r--gcc/testsuite/obj-c++.dg/torture/strings/const-str-9.mm2
-rw-r--r--gcc/testsuite/obj-c++.dg/try-catch-1.mm1
-rw-r--r--gcc/testsuite/obj-c++.dg/try-catch-3.mm1
-rw-r--r--gcc/testsuite/objc-obj-c++-shared/CF-CFString.h33
-rw-r--r--gcc/testsuite/objc-obj-c++-shared/F-NSArray.h33
-rw-r--r--gcc/testsuite/objc-obj-c++-shared/F-NSAutoreleasePool.h33
-rw-r--r--gcc/testsuite/objc-obj-c++-shared/F-NSObject.h33
-rw-r--r--gcc/testsuite/objc-obj-c++-shared/F-NSString.h33
-rw-r--r--gcc/testsuite/objc-obj-c++-shared/F-NSValue.h33
-rw-r--r--gcc/testsuite/objc-obj-c++-shared/GNUStep/CoreFoundation/CFArray.h191
-rw-r--r--gcc/testsuite/objc-obj-c++-shared/GNUStep/CoreFoundation/CFAvailability.h52
-rw-r--r--gcc/testsuite/objc-obj-c++-shared/GNUStep/CoreFoundation/CFBase.h464
-rw-r--r--gcc/testsuite/objc-obj-c++-shared/GNUStep/CoreFoundation/CFCharacterSet.h173
-rw-r--r--gcc/testsuite/objc-obj-c++-shared/GNUStep/CoreFoundation/CFData.h114
-rw-r--r--gcc/testsuite/objc-obj-c++-shared/GNUStep/CoreFoundation/CFDictionary.h174
-rw-r--r--gcc/testsuite/objc-obj-c++-shared/GNUStep/CoreFoundation/CFLocale.h249
-rw-r--r--gcc/testsuite/objc-obj-c++-shared/GNUStep/CoreFoundation/CFString.h593
-rw-r--r--gcc/testsuite/objc-obj-c++-shared/GNUStep/Foundation/NSArray.h430
-rw-r--r--gcc/testsuite/objc-obj-c++-shared/GNUStep/Foundation/NSAutoreleasePool.h333
-rw-r--r--gcc/testsuite/objc-obj-c++-shared/GNUStep/Foundation/NSDate.h300
-rw-r--r--gcc/testsuite/objc-obj-c++-shared/GNUStep/Foundation/NSEnumerator.h63
-rw-r--r--gcc/testsuite/objc-obj-c++-shared/GNUStep/Foundation/NSGeometry.h609
-rw-r--r--gcc/testsuite/objc-obj-c++-shared/GNUStep/Foundation/NSObjCRuntime.h317
-rw-r--r--gcc/testsuite/objc-obj-c++-shared/GNUStep/Foundation/NSObject.h594
-rw-r--r--gcc/testsuite/objc-obj-c++-shared/GNUStep/Foundation/NSRange.h235
-rw-r--r--gcc/testsuite/objc-obj-c++-shared/GNUStep/Foundation/NSString.h977
-rw-r--r--gcc/testsuite/objc-obj-c++-shared/GNUStep/Foundation/NSValue.h370
-rw-r--r--gcc/testsuite/objc-obj-c++-shared/GNUStep/Foundation/NSZone.h335
-rw-r--r--gcc/testsuite/objc-obj-c++-shared/GNUStep/GNUstepBase/GNUstep.h418
-rw-r--r--gcc/testsuite/objc-obj-c++-shared/GNUStep/GNUstepBase/GSBlocks.h145
-rw-r--r--gcc/testsuite/objc-obj-c++-shared/GNUStep/GNUstepBase/GSConfig.h462
-rw-r--r--gcc/testsuite/objc-obj-c++-shared/GNUStep/GNUstepBase/GSObjCRuntime.h631
-rw-r--r--gcc/testsuite/objc-obj-c++-shared/GNUStep/GNUstepBase/GSVersionMacros.h460
-rw-r--r--gcc/testsuite/objc-obj-c++-shared/GNUStep/GNUstepBase/NSArray+GNUstepBase.h78
-rw-r--r--gcc/testsuite/objc-obj-c++-shared/GNUStep/GNUstepBase/NSMutableString+GNUstepBase.h57
-rw-r--r--gcc/testsuite/objc-obj-c++-shared/GNUStep/GNUstepBase/NSNumber+GNUstepBase.h56
-rw-r--r--gcc/testsuite/objc-obj-c++-shared/GNUStep/GNUstepBase/NSObject+GNUstepBase.h242
-rw-r--r--gcc/testsuite/objc-obj-c++-shared/GNUStep/GNUstepBase/NSString+GNUstepBase.h105
-rw-r--r--gcc/testsuite/objc.dg/call-super-2.m4
-rw-r--r--gcc/testsuite/objc.dg/class-protocol-1.m4
-rw-r--r--gcc/testsuite/objc.dg/desig-init-1.m6
-rw-r--r--gcc/testsuite/objc.dg/encode-7-next-64bit.m5
-rw-r--r--gcc/testsuite/objc.dg/exceptions-3.m16
-rw-r--r--gcc/testsuite/objc.dg/exceptions-4.m2
-rw-r--r--gcc/testsuite/objc.dg/exceptions-5.m16
-rw-r--r--gcc/testsuite/objc.dg/exceptions-6.m2
-rw-r--r--gcc/testsuite/objc.dg/headers.m1
-rw-r--r--gcc/testsuite/objc.dg/image-info.m2
-rw-r--r--gcc/testsuite/objc.dg/instancetype-0.m30
-rw-r--r--gcc/testsuite/objc.dg/isa-field-1.m2
-rw-r--r--gcc/testsuite/objc.dg/method-19.m8
-rw-r--r--gcc/testsuite/objc.dg/method-2.m4
-rw-r--r--gcc/testsuite/objc.dg/method-5.m8
-rw-r--r--gcc/testsuite/objc.dg/method-6.m14
-rw-r--r--gcc/testsuite/objc.dg/method-7.m4
-rw-r--r--gcc/testsuite/objc.dg/method-lookup-1.m4
-rw-r--r--gcc/testsuite/objc.dg/no-extra-load.m2
-rw-r--r--gcc/testsuite/objc.dg/objc-foreach-4.m6
-rw-r--r--gcc/testsuite/objc.dg/objc-foreach-5.m5
-rw-r--r--gcc/testsuite/objc.dg/objc-gc-4.m1
-rw-r--r--gcc/testsuite/objc.dg/property/dotsyntax-17.m10
-rw-r--r--gcc/testsuite/objc.dg/property/property-neg-7.m8
-rw-r--r--gcc/testsuite/objc.dg/proto-hier-1.m4
-rw-r--r--gcc/testsuite/objc.dg/proto-lossage-4.m4
-rw-r--r--gcc/testsuite/objc.dg/proto-lossage-7.m2
-rw-r--r--gcc/testsuite/objc.dg/protocol-qualifier-2.m4
-rw-r--r--gcc/testsuite/objc.dg/strings/const-cfstring-2.m4
-rw-r--r--gcc/testsuite/objc.dg/strings/const-cfstring-5.m2
-rw-r--r--gcc/testsuite/objc.dg/strings/const-str-12b.m8
-rw-r--r--gcc/testsuite/objc.dg/stubify-1.m12
-rw-r--r--gcc/testsuite/objc.dg/stubify-2.m12
-rw-r--r--gcc/testsuite/objc.dg/symtab-1.m2
-rw-r--r--gcc/testsuite/objc.dg/torture/strings/const-cfstring-1.m4
-rw-r--r--gcc/testsuite/objc.dg/torture/strings/const-str-10.m3
-rw-r--r--gcc/testsuite/objc.dg/torture/strings/const-str-11.m2
-rw-r--r--gcc/testsuite/objc.dg/torture/strings/const-str-9.m2
-rw-r--r--gcc/testsuite/objc.dg/zero-link-1.m2
-rw-r--r--gcc/testsuite/objc.dg/zero-link-2.m2
-rw-r--r--gcc/testsuite/objc.dg/zero-link-3.m10
-rw-r--r--gcc/timevar.def4
-rw-r--r--gcc/tlink.c6
-rw-r--r--gcc/toplev.c16
-rw-r--r--gcc/trans-mem.c13
-rw-r--r--gcc/tree-affine.c217
-rw-r--r--gcc/tree-call-cdce.c90
-rw-r--r--gcc/tree-cfg.c248
-rw-r--r--gcc/tree-cfg.h9
-rw-r--r--gcc/tree-chrec.c65
-rw-r--r--gcc/tree-chrec.h11
-rw-r--r--gcc/tree-core.h20
-rw-r--r--gcc/tree-data-ref.c2
-rw-r--r--gcc/tree-eh.c12
-rw-r--r--gcc/tree-if-conv.c4
-rw-r--r--gcc/tree-inline.c51
-rw-r--r--gcc/tree-inline.h3
-rw-r--r--gcc/tree-into-ssa.c8
-rw-r--r--gcc/tree-loop-distribution.c102
-rw-r--r--gcc/tree-nested.c7
-rw-r--r--gcc/tree-parloops.c16
-rw-r--r--gcc/tree-predcom.c2
-rw-r--r--gcc/tree-pretty-print.c297
-rw-r--r--gcc/tree-pretty-print.h2
-rw-r--r--gcc/tree-profile.c49
-rw-r--r--gcc/tree-scalar-evolution.c144
-rw-r--r--gcc/tree-sra.c134
-rw-r--r--gcc/tree-ssa-address.c33
-rw-r--r--gcc/tree-ssa-address.h3
-rw-r--r--gcc/tree-ssa-alias.c701
-rw-r--r--gcc/tree-ssa-copy.c11
-rw-r--r--gcc/tree-ssa-dce.c19
-rw-r--r--gcc/tree-ssa-dse.c160
-rw-r--r--gcc/tree-ssa-forwprop.c97
-rw-r--r--gcc/tree-ssa-loop-im.c11
-rw-r--r--gcc/tree-ssa-loop-ivopts.c173
-rw-r--r--gcc/tree-ssa-loop-niter.c73
-rw-r--r--gcc/tree-ssa-loop.c2
-rw-r--r--gcc/tree-ssa-operands.c14
-rw-r--r--gcc/tree-ssa-phiopt.c19
-rw-r--r--gcc/tree-ssa-pre.c122
-rw-r--r--gcc/tree-ssa-reassoc.c30
-rw-r--r--gcc/tree-ssa-sccvn.c236
-rw-r--r--gcc/tree-ssa-scopedtables.c16
-rw-r--r--gcc/tree-ssa-sink.c10
-rw-r--r--gcc/tree-ssa-strlen.c273
-rw-r--r--gcc/tree-ssa-structalias.c130
-rw-r--r--gcc/tree-ssa-tail-merge.c2
-rw-r--r--gcc/tree-ssa-threadbackward.c5
-rw-r--r--gcc/tree-ssa-threadedge.c71
-rw-r--r--gcc/tree-ssa-threadupdate.c81
-rw-r--r--gcc/tree-ssa-uninit.c66
-rw-r--r--gcc/tree-ssa.c61
-rw-r--r--gcc/tree-ssanames.c7
-rw-r--r--gcc/tree-streamer-in.c11
-rw-r--r--gcc/tree-streamer-out.c13
-rw-r--r--gcc/tree-streamer.c3
-rw-r--r--gcc/tree-switch-conversion.c15
-rw-r--r--gcc/tree-switch-conversion.h6
-rw-r--r--gcc/tree-tailcall.c6
-rw-r--r--gcc/tree-vect-data-refs.c131
-rw-r--r--gcc/tree-vect-generic.c28
-rw-r--r--gcc/tree-vect-loop-manip.c309
-rw-r--r--gcc/tree-vect-loop.c271
-rw-r--r--gcc/tree-vect-slp.c63
-rw-r--r--gcc/tree-vect-stmts.c881
-rw-r--r--gcc/tree-vectorizer.c7
-rw-r--r--gcc/tree-vectorizer.h37
-rw-r--r--gcc/tree-vrp.c228
-rw-r--r--gcc/tree-vrp.h35
-rw-r--r--gcc/tree.c232
-rw-r--r--gcc/tree.def5
-rw-r--r--gcc/tree.h56
-rw-r--r--gcc/value-prof.c260
-rw-r--r--gcc/value-prof.h12
-rw-r--r--gcc/var-tracking.c2
-rw-r--r--gcc/varasm.c12
-rw-r--r--gcc/vector-builder.h18
-rw-r--r--gcc/vr-values.c35
2302 files changed, 126276 insertions, 37571 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index aebd830..2d6758d 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,5606 @@
+2019-07-03 Dennis Zhang <dennis.zhang@arm.com>
+
+ * config/aarch64/aarch64.md: Remove redundant constraints from
+ define_expand but keep some patterns untouched if they are
+ specially selected by TARGET_SECONDARY_RELOAD hook.
+ * config/aarch64/aarch64-sve.md: Likewise.
+ * config/aarch64/atomics.md: Remove redundant constraints from
+ define_expand.
+ * config/aarch64/aarch64-simd.md: Likewise.
+
+2019-07-03 Iain Sandoe <iain@sandoe.co.uk>
+
+ * config/darwin.h (DRIVER_SELF_SPECS): Remove the linker cases.
+ (RDYNAMIC): Rename to, DARWIN_RDYNAMIC.
+ (DARWIN_PIE_SPEC, DARWIN_NOPIE_SPEC): Adjust to remove the Xlinker
+ clauses.
+ (LINK_COMMAND_SPEC_A): Add DARWIN_RDYNAMIC, DARWIN_PIE_SPEC and
+ DARWIN_NOPIE_SPEC.
+
+2019-07-03 Iain Sandoe <iain@sandoe.co.uk>
+
+ * config/darwin.h (REAL_LIBGCC_SPEC): Adjust for earlier Darwin.
+ (STARTFILE_SPEC): Split crt3 into a separate spec.
+ (DARWIN_EXTRA_SPECS): Add crt2 and crt3 spec.
+ (DARWIN_CRT2_SPEC): New.
+ (DARWIN_CRT3_SPEC): New.
+ (MIN_LD64_OMIT_STUBS): Revise to 62.1.
+ * config/rs6000/darwin.h (DARWIN_CRT2_SPEC): Revise conditions.
+ (DARWIN_CRT3_SPEC): New.
+
+2019-07-03 Michael Meissner <meissner@linux.ibm.com>
+
+ * config/rs6000/altivec.md (altivec_mov<mode>, VM2 iterator):
+ Change the RTL attribute "length" from "4" to "*" to allow the
+ length attribute to be adjusted automatically for prefixed load,
+ store, and add immediate instructions.
+ * config/rs6000/rs6000.md (extendhi<mode>2, EXTHI iterator):
+ Likewise.
+ (extendsi<mode>2, EXTSI iterator): Likewise.
+ (movsi_internal1): Likewise.
+ (movsi_from_sf): Likewise.
+ (movdi_from_sf_zero_ext): Likewise.
+ (mov<mode>_internal): Likewise.
+ (movcc_internal1, QHI iterator): Likewise.
+ (mov<mode>_softfloat, FMOVE32 iterator): Likewise.
+ (movsf_from_si): Likewise.
+ (mov<mode>_hardfloat32, FMOVE64 iterator): Likewise.
+ (mov<mode>_softfloat64, FMOVE64 iterator): Likewise.
+ (mov<mode>, FMOVE128 iterator): Likewise.
+ (movdi_internal64): Likewise.
+ * config/rs6000/vsx.md (vsx_le_permute_<mode>, VSX_TI iterator):
+ Likewise.
+ (vsx_le_undo_permute_<mode>, VSX_TI iterator): Likewise.
+ (vsx_mov<mode>_64bit, VSX_M iterator): Likewise.
+ (vsx_mov<mode>_32bit, VSX_M iterator): Likewise.
+ (vsx_splat_v4sf): Likewise.
+
+2019-07-03 Mark Wielaard <mark@klomp.org>
+
+ PR debug/90981
+ * dwarf2out.c (add_top_level_skeleton_die_attrs): Only add
+ DW_AT_addr_base if there is actually a .debug_addr section with
+ addresses.
+ (output_addr_table): Add DWARF5 table header generation here after
+ checking there are actually any addresses from...
+ (dwarf2out_finish): ...here.
+ * testsuite/g++.dg/pr90981.C: New test.
+
+2019-07-03 Richard Biener <rguenther@suse.de>
+
+ PR middle-end/91069
+ * match.pd (vec_perm -> bit_insert): Fix element read from
+ first vector.
+
+2019-07-03 Martin Liska <mliska@suse.cz>
+
+ * dbgcnt.def (DEBUG_COUNTER): Add match debug counter.
+ * genmatch.c (dt_simplify::gen_1): Generate dbgcnt
+ condition.
+ * generic-match-head.c: Include dbgcnt.h.
+ * gimple-match-head.c: Likewise.
+
+2019-07-03 Martin Liska <mliska@suse.cz>
+
+ * gcov-counter.def (GCOV_COUNTER_V_SINGLE): Remove.
+ (GCOV_COUNTER_V_TOPN): New.
+ (GCOV_COUNTER_V_INDIR): Use _topn.
+ * gcov-io.h (GCOV_DISK_SINGLE_VALUES): Remove.
+ (GCOV_TOPN_VALUES): New.
+ (GCOV_SINGLE_VALUE_COUNTERS): Remove.
+ (GCOV_TOPN_VALUES_COUNTERS): New.
+ * profile.c (instrument_values): Use HIST_TYPE_TOPN_VALUES.
+ * tree-profile.c:
+ (gimple_init_gcov_profiler): Rename variables from one_value
+ to topn_values.
+ (gimple_gen_one_value_profiler): Remove.
+ (gimple_gen_topn_values_profiler): New function.
+ * value-prof.c (dump_histogram_value): Use TOPN_VALUES
+ names instead of SINGLE_VALUE.
+ (stream_out_histogram_value): Likewise.
+ (stream_in_histogram_value): Likewise.
+ (get_most_common_single_value): Likewise.
+ (gimple_divmod_fixed_value_transform): Likewise.
+ (gimple_stringops_transform): Likewise.
+ (gimple_divmod_values_to_profile): Likewise.
+ (gimple_stringops_values_to_profile): Likewise.
+ (gimple_find_values_to_profile): Likewise.
+ * value-prof.h (enum hist_type): Rename to TOPN.
+ (gimple_gen_one_value_profiler): Remove.
+ (gimple_gen_topn_values_profiler): New.
+
+2019-07-03 Eric Botcazou <ebotcazou@adacore.com>
+
+ * dwarf2out.c (add_scalar_info): Add back refererence to existing DIE
+ if it has the DW_AT_data_member_location attribute.
+
+2019-07-03 Richard Biener <rguenther@suse.de>
+
+ * gimple-pretty-print.c (dump_ternary_rhs): Fix BIT_INSERT_EXPR
+ dumping.
+
+2019-07-03 Sylvia Taylor <sylvia.taylor@arm.com>
+
+ * config/aarch64/aarch64.md (FP_REGNUM): New constant.
+ (tlsdesc_small_advsimd_<mode>): Add use of FP_REGNUM.
+ (tlsdesc_small_sve_<mode>): Likewise.
+
+2019-07-03 Martin Liska <mliska@suse.cz>
+
+ * Makefile.in: Define ZSTD_LIB.
+ * common.opt: Adjust compression level
+ to support also zstd levels.
+ * config.in: Regenerate.
+ * configure: Likewise.
+ * configure.ac: Add --with-zstd and --with-zstd-include options
+ and detect ZSTD.
+ * doc/install.texi: Mention zstd dependency.
+ * gcc.c: Print supported LTO compression algorithms.
+ * lto-compress.c (lto_normalized_zstd_level): Likewise.
+ (lto_compression_zstd): Likewise.
+ (lto_uncompression_zstd): Likewise.
+ (lto_end_compression): Dispatch in between zlib and zstd.
+ (lto_compression_zlib): Mark with ATTRIBUTE_UNUSED.
+ (lto_uncompression_zlib): Make it static.
+ * lto-compress.h (lto_end_uncompression): Fix GNU coding style.
+ * lto-section-in.c (lto_get_section_data): Pass info
+ about used compression.
+ * lto-streamer-out.c: By default use zstd when possible.
+ * timevar.def (TV_IPA_LTO_DECOMPRESS): Rename to decompression
+ (TV_IPA_LTO_COMPRESS): Likewise for compression.
+
+2019-07-03 Martin Liska <mliska@suse.cz>
+
+ * lto-section-in.c (lto_get_section_data): Add "lto" section.
+ * lto-section-out.c (lto_destroy_simple_output_block): Never
+ compress LTO_section_lto section.
+ * lto-streamer-out.c (produce_asm): Do not set major_version
+ and minor_version.
+ (lto_output_toplevel_asms): Likewise.
+ (produce_lto_section): New function.
+ (lto_output): Call produce_lto_section.
+ (lto_write_mode_table): Do not set major_version and
+ minor_version.
+ (produce_asm_for_decls): Likewise.
+ * lto-streamer.h (enum lto_section_type): Add LTO_section_lto
+ type.
+ (struct lto_header): Remove.
+ (struct lto_section): New struct.
+ (struct lto_simple_header): Do not inherit from lto_header.
+ (struct lto_file_decl_data): Add lto_section_header field.
+
+2019-07-03 Martin Liska <mliska@suse.cz>
+
+ * lra-eliminations.c (eliminate_regs_in_insn): Remove
+ dead assignemts.
+ * reg-stack.c (check_asm_stack_operands): Likewise.
+ * tree-ssa-structalias.c (create_function_info_for): Likewise.
+ * tree-vect-generic.c (expand_vector_operations_1): Likewise.
+ * config/i386/i386-expand.c (ix86_expand_sse2_mulvxdi3): Use
+ force_expand_binop.
+
+2019-07-03 Martin Liska <mliska@suse.cz>
+
+ PR tree-optimization/90892
+ * builtins.c (inline_expand_builtin_string_cmp): Handle '\0'
+ in string constants.
+
+2019-07-03 Martin Liska <mliska@suse.cz>
+
+ PR middle-end/90899
+ * multiple_target.c (create_dispatcher_calls): Add to comdat
+ group only if set for ifunc.
+
+2019-07-03 Martin Liska <mliska@suse.cz>
+
+ PR target/88056
+ * config/i386/host-mingw32.c (mingw32_gt_pch_use_address):
+ Define local_object_name in outer scope in order to handle
+ use-after-scope issue.
+
+2019-07-03 Martin Liska <mliska@suse.cz>
+
+ * common.opt: Add fprofile-note.
+ * coverage.c (coverage_init): Append the option
+ to bbg_file_name.
+ * doc/invoke.texi: Document -fprofile-note.
+
+2019-07-03 Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/91033
+ * tree-vectorizer.h (vect_mark_stmts_to_be_vectorized,
+ vect_analyze_data_refs): Add bool * arguments.
+ * tree-vect-data-refs.c (vect_analyze_data_refs): Add fatal argument,
+ if failure is due to scatter/gather, set *fatal to false if non-NULL.
+ * tree-vect-stmts.c (vect_mark_stmts_to_be_vectorized): Likewise.
+ * tree-vect-loop.c (vect_analyze_loop_2): Adjust
+ vect_mark_stmts_to_be_vectorized and vect_analyze_data_refs callers.
+ * tree-vect-slp.c (vect_slp_analyze_bb_1): Adjust
+ vect_analyze_data_refs caller.
+
+ * tree-core.h (enum omp_clause_code): Add OMP_CLAUSE__SCANTEMP_
+ clause.
+ * tree.h (OMP_CLAUSE_DECL): Use OMP_CLAUSE__SCANTEMP_ instead of
+ OMP_CLAUSE__CONDTEMP_ as range's upper bound.
+ (OMP_CLAUSE__SCANTEMP__ALLOC, OMP_CLAUSE__SCANTEMP__CONTROL): Define.
+ * tree.c (omp_clause_num_ops, omp_clause_code_name): Add
+ OMP_CLAUSE__SCANTEMP_ entry.
+ (walk_tree_1): Handle OMP_CLAUSE__SCANTEMP_.
+ * tree-pretty-print.c (dump_omp_clause): Likewise.
+ * tree-nested.c (convert_nonlocal_omp_clauses,
+ convert_local_omp_clauses): Likewise.
+ * omp-general.h (struct omp_for_data): Add have_scantemp and
+ have_nonctrl_scantemp members.
+ * omp-general.c (omp_extract_for_data): Initialize them.
+ * omp-low.c (struct omp_context): Add scan_exclusive member.
+ (scan_omp_1_stmt): Don't unnecessarily mask gimple_omp_for_kind
+ result again with GF_OMP_FOR_KIND_MASK. Initialize also
+ ctx->scan_exclusive.
+ (lower_rec_simd_input_clauses): Use ctx->scan_exclusive instead
+ of !ctx->scan_inclusive.
+ (lower_rec_input_clauses): Simplify gimplification of dtors using
+ gimplify_and_add. For non-is_simd test OMP_CLAUSE_REDUCTION_INSCAN
+ rather than rvarp. Handle OMP_CLAUSE_REDUCTION_INSCAN in worksharing
+ loops. Don't add barrier for reduction_omp_orig_ref if
+ ctx->scan_??xclusive.
+ (lower_reduction_clauses): Don't do anything for ctx->scan_??xclusive.
+ (lower_omp_scan): Use ctx->scan_exclusive instead
+ of !ctx->scan_inclusive. Handle worksharing loops with inscan
+ reductions. Use new_vard != new_var instead of repeated
+ omp_is_reference calls.
+ (omp_find_scan, lower_omp_for_scan): New functions.
+ (lower_omp_for): Call lower_omp_for_scan for worksharing loops with
+ inscan reductions.
+ * omp-expand.c (expand_omp_scantemp_alloc): New function.
+ (expand_omp_for_static_nochunk): Handle fd->have_nonctrl_scantemp
+ and fd->have_scantemp.
+
+ * gimplify.c (gimplify_scan_omp_clauses): For inscan reductions
+ on worksharing loop propagate it as shared clause to containing
+ combined parallel.
+
+ * omp-expand.c (expand_omp_for_static_nochunk,
+ expand_omp_for_static_chunk): For nowait worksharing loop with
+ conditional lastprivate clause(s), emit GOMP_loop_end_nowait call
+ at the end.
+
+2019-07-02 Joern Rennecke <joern.rennecke@riscy-ip.com>
+
+ PR testsuite/91065
+ * testsuite/gcc.dg/plugin/start_unit_plugin.c: Register a root tab
+ to reference fake_var.
+
+2019-07-02 qing zhao <qing.zhao@oracle.com>
+
+ PR preprocessor/90581
+ * doc/cppopts.texi: Add document for -fmax-include-depth.
+ * doc/invoke.texi (Preprocessor Options): List -fmax-include-depth.
+
+2019-07-02 Uroš Bizjak <ubizjak@gmail.com>
+
+ * config/i386/mmx.md (mmx_pack<s_trunsuffix>swb):
+ Use TARGET_SSE2 && SSE_REGNO_P in split condition.
+ (mmx_packssdw): Ditto.
+ (mmx_punpckhbw): Ditto.
+ (mmx_punpcklbw): Ditto.
+ (mmx_punpckhwd): Ditto.
+ (mmx_punpcklwd): Ditto.
+ (mmx_punpckhdq): Ditto.
+ (mmx_punpckldq): Ditto.
+ (*vec_dupv4hi): Ditto.
+ (*vec_dupv2si): Ditto.
+ (mmx_pmovmskb): Ditto.
+ * config/i386/sse.md (sse_cvtpi2ps): Use
+ TARGET_SSE2 && SSE_REG_P in split condition.
+ (ssse3_ph<plusminus_mnemonic>wv4hi3): Use
+ TARGET_SSSE3 && SSE_REGNO_P in split condition.
+ (ssse3_ph<plusminus_mnemonic>dv2si3): Ditto.
+ (ssse3_pshufbv8qi3): Ditto.
+ (ssse3_palignrdi): Ditto.
+
+2019-07-02 Andrew Stubbs <ams@codesourcery.com>
+
+ * config/gcn/gcn.md (movdi_symbol_save_scc): Convert to define_insn
+ with inlined save and restore.
+
+2019-07-02 Eric Botcazou <ebotcazou@adacore.com>
+
+ * cfgexpand.c (pass_expand::execute): Deal specially with instructions
+ to be inserted on single successor edge of the entry block. Then call
+ commit_edge_insertions instead of inserting the instructions manually.
+ * cfgrtl.c (commit_edge_insertions): Do not verify flow info during
+ RTL expansion and rebuild jump labels chain.
+
+2019-07-02 Richard Biener <rguenther@suse.de>
+
+ * tree-core.h (enum tree_index): Add TI_CHREC_DONT_KNOW and
+ TI_CHREC_KNOWN.
+ * tree.h (chrec_not_analyzed_yet, chrec_dont_know, chrec_known):
+ Define here.
+ * tree.c (build_common_tree_nodes): Initialize them.
+ * tree-chrec.h (chrec_not_analyzed_yet, chrec_dont_know, chrec_known):
+ Make declarations comments.
+ * tree-scalar-evolution.c (chrec_not_analyzed_yet, chrec_dont_know,
+ chrec_known): Remove definitions.
+ (initialize_scalar_evolutions_analyzer): Remove.
+ (scev_initialize): Do not call initialize_scalar_evolutions_analyzer.
+ * tree-streamer.c (preload_common_nodes): Do not preload
+ TI_CHREC_DONT_KNOW or TI_CHREC_KNOWN.
+
+2019-07-02 Jan Hubicka <jh@suse.cz>
+
+ * tree-ssa-alias.c (aliasing_component_refs_p): Remove forgotten
+ sanity check.
+
+2019-07-02 Jan Hubicka <jh@suse.cz>
+
+ * tree-ssa-alias.c (nonoverlapping_component_refs_for_decl_p): Rename
+ to ..
+ (nonoverlapping_component_refs_since_match_p): ... this one;
+ handle also non-decl bases; return -1 if search gave up.
+ (alias_stats): Rename nonoverlapping_component_refs_of_decl_p_may_alias,
+ nonoverlapping_component_refs_of_decl_p_no_alias to
+ nonoverlapping_component_refs_since_match_p_may_alias,
+ nonoverlapping_component_refs_since_match_p_no_alias.
+ (dump_alias_stats): Update dumping.
+ (aliasing_matching_component_refs_p): Break out from ...;
+ dispatch to nonoverlapping_component_refs_for_decl_p
+ and nonoverlapping_component_refs_since_match_p.
+ (aliasing_component_refs_p): ... here; call
+ nonoverlapping_component_refs_p in scenarios where we can not
+ precisely determine base match.
+ (decl_refs_may_alias_p): Use
+ nonoverlapping_component_refs_since_match_p.
+ (indirect_ref_may_alias_decl_p): Do not call
+ nonoverlapping_component_refs_p.
+ (indirect_refs_may_alias_p): Likewise.
+
+2019-07-02 Jan Hubicka <jh@suse.cz>
+
+ * tree-inline.c (remap_gimple_stmt): Do not subtitute handled components
+ to clobber of return value.
+
+2019-07-02 Kyrylo Tkachov <kyrylo.tkachov@arm.com>
+
+ * config/arm/cortex-a57.md (cortex_a57_neon_type): Use neon_arith_basic
+ for is_neon_type instructions that have not already been categorized.
+
+2019-07-02 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/58483
+ * tree-ssa-scopedtables.c (avail_expr_hash): Use OEP_ADDRESS_OF
+ for MEM_REF base hashing.
+ (equal_mem_array_ref_p): Likewise for base comparison.
+
+2019-07-01 Segher Boessenkool <segher@kernel.crashing.org>
+
+ * config/rs6000/rs6000.md (signbit<mode>2_dm): Make this a
+ parameterized name.
+ (signbit<mode>2): Use that name. Simplify.
+
+2019-07-01 Joern Rennecke <joern.rennecke@riscy-ip.com>
+
+ PR middle-end/66726
+ * tree-ssa-phiopt.c (factor_out_conditional_conversion):
+ Tune heuristic from PR71016 to allow MIN / MAX.
+ * testsuite/gcc.dg/tree-ssa/pr66726-4.c: New testcase.
+
+2019-07-01 Segher Boessenkool <segher@kernel.crashing.org>
+
+ * config/rs6000/rs6000.md (ieee_128bit_vsx_abs<mode>2): Make this a
+ parameterized name.
+ (abs<mode>2): Use that name. Simplify.
+
+2019-07-01 Segher Boessenkool <segher@kernel.crashing.org>
+
+ * config/rs6000/rs6000.md (ieee_128bit_vsx_neg<mode>2): Make this a
+ parameterized name.
+ (neg<mode>2): Use that name. Simplify.
+
+2019-07-01 Segher Boessenkool <segher@kernel.crashing.org>
+
+ * config/rs6000/rs6000.md (abs<mode>2_hw): Make this a parameterized
+ name.
+ (abs<mode>2): Use that name. Simplify.
+
+2019-07-01 Segher Boessenkool <segher@kernel.crashing.org>
+
+ * config/rs6000/rs6000.md (neg<mode>2_hw): Make this a parameterized
+ name.
+ (neg<mode>2): Use that name. Simplify.
+
+2019-07-01 Uroš Bizjak <ubizjak@gmail.com>
+
+ * config/i386/i386.md ("isa" attribute): Add sse_noavx.
+ ("enabled" attribute): Handle sse_noavx isa attribute.
+ * config/i386/mmx.md (*vec_dupv2sf): Add "isa" attribute.
+ Use TARGET_SSE && SSE_REGNO_P in split condition.
+ (*vec_dupv2sf): Ditto.
+
+2019-07-01 Segher Boessenkool <segher@kernel.crashing.org>
+
+ * config/rs6000/rs6000.md (extenddf<mode>2): Make this a parameterized
+ name.
+ (floatsi<mode>2): Use that name. Simplify.
+
+2019-07-01 Segher Boessenkool <segher@kernel.crashing.org>
+
+ * config/rs6000/rs6000.md (extenddf<mode>2_fprs): Make this a
+ parameterized name.
+ (extenddf<mode>2_vsx): Make this a parameterized name.
+ (extenddf<mode>2): Use those names. Simplify.
+
+2019-07-01 Segher Boessenkool <segher@kernel.crashing.org>
+
+ * config/rs6000/rs6000.md (eh_set_lr_<mode>): Make this a parameterized
+ name.
+ (eh_return): Use that name. Simplify.
+
+2019-07-01 Segher Boessenkool <segher@kernel.crashing.org>
+
+ * config/rs6000/rs6000.md (ctr<mode>): Make this a parameterized name.
+ (doloop_end): Use that name. Simplify.
+
+2019-07-01 Segher Boessenkool <segher@kernel.crashing.org>
+
+ * config/rs6000/rs6000.md (indirect_jump<mode>_nospec): Make this a
+ parameterized name.
+ (indirect_jump): Use that name. Simplify.
+
+2019-07-01 Segher Boessenkool <segher@kernel.crashing.org>
+
+ * config/rs6000/rs6000.md (abs<mode>2_internal): Make this a
+ parameterized name.
+ (abs<mode>2): Use that name. Simplify.
+
+2019-07-01 Segher Boessenkool <segher@kernel.crashing.org>
+
+ * config/rs6000/rs6000.md (fix_trunc<mode>si2_fprs): Make this a
+ parameterized name.
+ (fix_trunc<mode>si2): Use that name. Simplify.
+
+2019-07-01 Segher Boessenkool <segher@kernel.crashing.org>
+
+ * config/rs6000/rs6000.md (neg<mode>2): Make this a parameterized name.
+ (allocate_stack): Use that name. Simplify.
+
+2019-07-01 Martin Sebor <msebor@redhat.com>
+
+ PR middle-end/90923
+ * hash-map.h (hash_map::put): On insertion invoke element ctor.
+ (hash_map::get_or_insert): Same. Reformat comment.
+ * hash-set.h (hash_set::add): On insertion invoke element ctor.
+ * hash-map-tests.c (test_map_of_type_with_ctor_and_dtor): New.
+ * hash-set-tests.c (test_map_of_type_with_ctor_and_dtor): New.
+ * hash-table.h (hash_table::operator=): Prevent copy assignment.
+ (hash_table::hash_table (const hash_table&)): Use copy ctor
+ instead of assignment to copy elements.
+
+2019-07-01 Wilco Dijkstra <wdijkstr@arm.com>
+ John David Anglin <danglin@gcc.gnu.org>
+
+ PR target/90963
+ * config/pa/pa.md (builtin_longjmp): Restore hard_frame_pointer_rtx
+ using saved frame pointer.
+
+2019-07-01 Eric Botcazou <ebotcazou@adacore.com>
+
+ PR middle-end/64242
+ * config/sparc/sparc.md (nonlocal_goto): Restore frame pointer last.
+ Add frame clobber and schedule blockage.
+
+2019-07-01 Sandra Loosemore <sandra@codesourcery.com>
+
+ * doc/invoke.texi (Link Options): Further editorial changes to
+ -flinker-output docs.
+
+2019-07-01 Segher Boessenkool <segher@kernel.crashing.org>
+
+ * config/rs6000/rs6000.c (rs6000_force_indexed_or_indirect_mem):
+ Load both operands of a PLUS into registers separately.
+
+2019-07-01 Andreas Krebbel <krebbel@linux.ibm.com>
+
+ * config/s390/vector.md: Fix shift count operand printing.
+
+2019-07-01 Richard Sandiford <richard.sandiford@arm.com>
+
+ * ira-lives.c (process_bb_node_lives): Use ira_setup_alts.
+
+2019-07-01 Richard Sandiford <richard.sandiford@arm.com>
+
+ * ira.c (ira_get_dup_out_num): Don't punt for earlyclobbers.
+ Use recog_data to test for an output operand.
+
+2019-07-01 Richard Sandiford <richard.sandiford@arm.com>
+
+ * ira.c (ira_setup_alts): If any valid alternatives have zero cost,
+ exclude any others that are disparaged or that are bound to need
+ a reload or spill.
+ (ira_get_dup_out_num): Expand comment.
+
+2019-07-01 Richard Sandiford <richard.sandiford@arm.com>
+
+ * ira.c (ira_setup_alts): Use preprocess_constraints to get the
+ constraint string for each operand/alternative combo. Only handle
+ '%' at the start of constraint strings, and look for it outside
+ the main loop.
+
+2019-07-01 Richard Sandiford <richard.sandiford@arm.com>
+
+ * ira-int.h (ira_setup_alts, ira_get_dup_out_num): Use
+ alternative_mask instead of HARD_REG_SET to represent a
+ bitmask of alternatives.
+ * ira.c (ira_setup_alts, ira_get_dup_out_num): Likewise.
+ * ira-conflicts.c (add_insn_allocno_copies): Likewise.
+
+2019-07-01 Martin Liska <mliska@suse.cz>
+
+ * edit-context.c (test_applying_fixits_unreadable_file): Do not
+ use () for a constructor call.
+ (test_applying_fixits_line_out_of_range): Likewise.
+ * ggc-page.c (alloc_page): Use (void *) for %p printf format
+ argument.
+ (free_page): Likewise.
+
+2019-07-01 Vladislav Ivanishin <vlad@ispras.ru>
+
+ * gdbhooks.py (GdbPrettyPrinters.add_printer_for_types): Reorder
+ parameter names to match usage (no functional change).
+ (GdbPrettyPrinters.add_printer_for_regex): Ditto.
+
+2019-07-01 Richard Biener <rguenther@suse.de>
+
+ * tree-ssa-sccvn.c (class pass_fre): Add may_iterate
+ pass parameter.
+ (pass_fre::execute): Honor it.
+ * passes.def: Adjust pass_fre invocations to allow iterating,
+ add non-iterating pass_fre before late threading/dom.
+
+2019-07-01 Richard Biener <rguenther@suse.de>
+
+ * tree-ssa-sccvn.c (copy_reference_ops_from_ref): Adjust
+ TARGET_MEM_REF handling to also handle address-taken ones.
+
+2019-07-01 Hongtao Liu <hongtao.liu@intel.com>
+
+ * doc/sourcebuild.texi (Effective-Target Keywords, Other
+ hardware attributes): Document avx512vp2intersect.
+
+2019-06-30 Uroš Bizjak <ubizjak@gmail.com>
+
+ * config/i386/sse.md (ssse3_abs<mode>2): Rename from abs<mode>2.
+ (abs<mode>2): New expander.
+ * config/i386/i386-builtin.def (__builtin_ia32_pabsb):
+ Use CODE_FOR_ssse3_absv8qi2.
+ (__builtin_ia32_pabsw): Use CODE_FOR_ssse3_absv4hi2.
+ (__builtin_ia32_pabsd): Use CODE_FOR_ssse3_absv2si2.
+
+2019-06-30 Uroš Bizjak <ubizjak@gmail.com>
+
+ * config/i386/i386.md (mmx_isa): Rename x64, x64_noavx and x64_avx
+ to sse, sse_noavx and avx. Update all uses.
+
+2019-06-30 Uroš Bizjak <ubizjak@gmail.com>
+
+ * config/i386/mmx.md (sse_movntq): Add "isa" attribute.
+ (*mmx_<plusminus_insn><mode>3): Ditto.
+ (*mmx_mulv4hi3"): Ditto.
+ (*mmx_smulv4hi3_highpart): Ditto.
+ (*mmx_umulv4hi3_highpart): Ditto.
+ (*mmx_pmaddwd): Ditto.
+ (*sse2_umulv1siv1di3): Ditto.
+ (*mmx_<code>v4hi3): Ditto.
+ (*mmx_<code>v8qi3): Ditto.
+ (mmx_ashr<mode>3): Ditto.
+ ("mmx_<shift_insn><mode>3): Ditto.
+ (*mmx_eq<mode>3): Ditto.
+ (mmx_gt<mode>3): Ditto.
+ (mmx_andnot<mode>3): Ditto.
+ (*mmx_<code><mode>3): Ditto.
+ (*mmx_pinsrw): Ditto.
+ (*mmx_pextrw): Ditto.
+ (mmx_pshufw_1): Ditto.
+ (*mmx_uavgv8qi3): Ditto.
+ (*mmx_uavgv4hi3): Ditto.
+ ("mmx_psadbw): Ditto.
+ * config/i386/sse.md (sse_cvtps2pi): Ditto.
+ (sse_cvttps2pi): Ditto.
+ (ssse3_pmaddubsw): Ditto.
+ (*ssse3_pmulhrswv4hi3): Ditto.
+ (ssse3_psign<mode>3): Ditto.
+
+2019-06-29 Eric Botcazou <ebotcazou@adacore.com>
+
+ * expr.c (expand_expr_real_1) <BIT_FIELD_REF>: Apply the big-endian
+ adjustment for bit-fields to all aggregate types.
+
+2019-06-28 Michael Meissner <meissner@linux.ibm.com>
+
+ * config/rs6000/predicates.md (pcrel_address): Use
+ SYMBOL_REF_LOCAL_P to determine if a label is local.
+ (pcrel_external_address): New predicate.
+ (non_prefixed_mem_operand): Delete, predicate not used.
+ * config/rs6000/rs6000.h (SYMBOL_FLAG_PCREL_P): Delete, we now use
+ SYMBOL_REF_LOCAL_P to determine if we can use pc-relative
+ addressing.
+ (SYMBOL_REF_PCREL_P): Likewise.
+
+ PR target/91009
+ * config/rs6000/rs6000.md (floatsi<mode>2_lfiwax): Add non-VSX
+ alternative.
+ (floatsi<mode>2_lfiwax_mem): Add non-VSX alternative.
+ (floatunssi<mode>2_lfiwzx): Add non-VSX alternative.
+ (floatunssi<mode>2_lfiwzx_mem): Add non-VSX alternative.
+
+2019-06-28 Iain Sandoe <iain@sandoe.co.uk>
+
+ * config.gcc (powerpc-*-darwin*, powerpc64-*-darwin*): Remove
+ override on extra_headers.
+
+2019-06-28 Iain Sandoe <iain@sandoe.co.uk>
+
+ * config/darwin-c.c (pop_field_alignment): Quote #pragma options.
+ * config/darwin-driver.c (darwin_default_min_version): Remove newline
+ from warning.
+ (darwin_driver_init): Likewise.
+
+2019-06-28 Jan Beulich <jbeulich@suse.com>
+
+ * config/i386/sse.md (vgf2p8affineinvqb_<mode><mask_name>,
+ vgf2p8affineqb_<mode><mask_name>, vgf2p8mulb_<mode><mask_name>):
+ Eliminate redundant alternative.
+
+2019-06-28 Jan Beulich <jbeulich@suse.com>
+
+ * config/i386/sse.md (vgf2p8affineinvqb_<mode><mask_name>,
+ vgf2p8affineqb_<mode><mask_name>): Drop % constraint modifier.
+ Use vector_operand.
+
+2019-06-28 Claudiu Zissulescu <claziss@synopsys.com>
+
+ * config/arc/arc.c (arc_rtx_costs): All short instructions are
+ having a lower cost regardless of the speed option.
+
+2019-06-28 Jan Beulich <jbeulich@suse.com>
+
+ * config/i386/sse.md (sse2_cvtpd2pi, sse2_cvttpd2pi): Use
+ vector_operand plus, on both alternatives, "Bm" constraint.
+
+2019-06-28 Dennis Zhang <dennis.zhang@arm.com>
+
+ * config/arm/arm.md: Remove redundant constraints from
+ define_expand but leave reload_inm and reload_outm patterns
+ untouched since they need special constraints to work.
+ * config/arm/arm-fixed.md: Remove redundant constraints from
+ define_expand.
+ * config/arm/iwmmxt.md: Likewise.
+ * config/arm/neon.md: Likewise.
+ * config/arm/sync.md: Likewise.
+ * config/arm/thumb1.md: Likewise.
+ * config/arm/vec-common.md: Likewise.
+
+2019-06-27 Ilia Diachkov <ilia.diachkov@optimitech.com>
+
+ * doc/install.texi: Document --disable-tm-clone-registry.
+
+2019-06-27 Jakub Jelinek <jakub@redhat.com>
+
+ PR c++/91024
+ * gimplify.c (collect_fallthrough_labels): Ignore GIMPLE_PREDICT
+ statements.
+
+ PR tree-optimization/91010
+ * tree-vect-stmts.c (scan_operand_equal_p): If offset1 == offset2,
+ return true. Otherwise, don't call operand_equal_p if offset1 or
+ offset2 is NULL and just return false.
+
+2019-06-27 Iain Sandoe <iain@sandoe.co.uk>
+
+ * config/rs6000/rs6000.c (darwin_rs6000_override_options): Honour
+ user-specified float mode choice for kernel mode code.
+
+2019-06-27 Iain Sandoe <iain@sandoe.co.uk>
+
+ * config/rs6000/darwin.h (ENDFILE_SPEC): Correct whitespace in the
+ spec.
+
+2019-06-27 Iain Sandoe <iain@sandoe.co.uk>
+
+ * config/rs6000/rs6000.c (darwin_rs6000_override_options): Do not
+ use longcall for 64b code.
+
+2019-06-27 Aaron Sawdey <acsawdey@linux.ibm.com>
+
+ * builtins.c (get_memory_rtx): Fix comment.
+ * optabs.def (movmem_optab): Change to cpymem_optab.
+ * expr.c (emit_block_move_via_cpymem): Change movmem to cpymem.
+ (emit_block_move_hints): Change movmem to cpymem.
+ * defaults.h: Change movmem to cpymem.
+ * targhooks.c (get_move_ratio): Change movmem to cpymem.
+ (default_use_by_pieces_infrastructure_p): Ditto.
+ * config/aarch64/aarch64-protos.h: Change movmem to cpymem.
+ * config/aarch64/aarch64.c (aarch64_expand_movmem): Change movmem
+ to cpymem.
+ * config/aarch64/aarch64.h: Change movmem to cpymem.
+ * config/aarch64/aarch64.md (movmemdi): Change name to cpymemdi.
+ * config/alpha/alpha.h: Change movmem to cpymem in comment.
+ * config/alpha/alpha.md (movmemqi, movmemdi, *movmemdi_1): Change
+ movmem to cpymem.
+ * config/arc/arc-protos.h: Change movmem to cpymem.
+ * config/arc/arc.c (arc_expand_movmem): Change movmem to cpymem.
+ * config/arc/arc.h: Change movmem to cpymem in comment.
+ * config/arc/arc.md (movmemsi): Change movmem to cpymem.
+ * config/arm/arm-protos.h: Change movmem to cpymem in names.
+ * config/arm/arm.c (arm_movmemqi_unaligned, arm_gen_movmemqi,
+ gen_movmem_ldrd_strd, thumb_expand_movmemqi) Change movmem to cpymem.
+ * config/arm/arm.md (movmemqi): Change movmem to cpymem.
+ * config/arm/thumb1.md (movmem12b, movmem8b): Change movmem to cpymem.
+ * config/avr/avr-protos.h: Change movmem to cpymem.
+ * config/avr/avr.c (avr_adjust_insn_length, avr_emit_movmemhi,
+ avr_out_movmem): Change movmem to cpymem.
+ * config/avr/avr.md (movmemhi, movmem_<mode>, movmemx_<mode>):
+ Change movmem to cpymem.
+ * config/bfin/bfin-protos.h: Change movmem to cpymem.
+ * config/bfin/bfin.c (single_move_for_movmem, bfin_expand_movmem):
+ Change movmem to cpymem.
+ * config/bfin/bfin.h: Change movmem to cpymem in comment.
+ * config/bfin/bfin.md (movmemsi): Change name to cpymemsi.
+ * config/c6x/c6x-protos.h: Change movmem to cpymem.
+ * config/c6x/c6x.c (c6x_expand_movmem): Change movmem to cpymem.
+ * config/c6x/c6x.md (movmemsi): Change name to cpymemsi.
+ * config/frv/frv.md (movmemsi): Change name to cpymemsi.
+ * config/ft32/ft32.md (movmemsi): Change name to cpymemsi.
+ * config/h8300/h8300.md (movmemsi): Change name to cpymemsi.
+ * config/i386/i386-expand.c (expand_set_or_movmem_via_loop,
+ expand_set_or_movmem_via_rep, expand_movmem_epilogue,
+ expand_setmem_epilogue_via_loop, expand_set_or_cpymem_prologue,
+ expand_small_cpymem_or_setmem,
+ expand_set_or_cpymem_prologue_epilogue_by_misaligned_moves,
+ expand_set_or_cpymem_constant_prologue,
+ ix86_expand_set_or_cpymem): Change movmem to cpymem.
+ * config/i386/i386-protos.h: Change movmem to cpymem.
+ * config/i386/i386.h: Change movmem to cpymem in comment.
+ * config/i386/i386.md (movmem<mode>): Change name to cpymem.
+ (setmem<mode>): Change expansion function name.
+ * config/lm32/lm32.md (movmemsi): Change name to cpymemsi.
+ * config/m32c/blkmov.md (movmemhi, movmemhi_bhi_op, movmemhi_bpsi_op,
+ movmemhi_whi_op, movmemhi_wpsi_op): Change movmem to cpymem.
+ * config/m32c/m32c-protos.h: Change movmem to cpymem.
+ * config/m32c/m32c.c (m32c_expand_movmemhi): Change movmem to cpymem.
+ * config/m32r/m32r.c (m32r_expand_block_move): Change movmem to cpymem.
+ * config/m32r/m32r.md (movmemsi, movmemsi_internal): Change movmem
+ to cpymem.
+ * config/mcore/mcore.md (movmemsi): Change name to cpymemsi.
+ * config/microblaze/microblaze.c: Change movmem to cpymem in comment.
+ * config/microblaze/microblaze.md (movmemsi): Change name to cpymemsi.
+ * config/mips/mips.c (mips_use_by_pieces_infrastructure_p):
+ Change movmem to cpymem.
+ * config/mips/mips.h: Change movmem to cpymem.
+ * config/mips/mips.md (movmemsi): Change name to cpymemsi.
+ * config/nds32/nds32-memory-manipulation.c
+ (nds32_expand_movmemsi_loop_unknown_size,
+ nds32_expand_movmemsi_loop_known_size, nds32_expand_movmemsi_loop,
+ nds32_expand_movmemsi_unroll,
+ nds32_expand_movmemsi): Change movmem to cpymem.
+ * config/nds32/nds32-multiple.md (movmemsi): Change name to cpymemsi.
+ * config/nds32/nds32-protos.h: Change movmem to cpymem.
+ * config/pa/pa.c (compute_movmem_length): Change movmem to cpymem.
+ (pa_adjust_insn_length): Change call to compute_movmem_length.
+ * config/pa/pa.md (movmemsi, movmemsi_prereload, movmemsi_postreload,
+ movmemdi, movmemdi_prereload,
+ movmemdi_postreload): Change movmem to cpymem.
+ * config/pdp11/pdp11.md (movmemhi, movmemhi1,
+ movmemhi_nocc, UNSPEC_MOVMEM): Change movmem to cpymem.
+ * config/riscv/riscv.c: Change movmem to cpymem in comment.
+ * config/riscv/riscv.h: Change movmem to cpymem.
+ * config/riscv/riscv.md: (movmemsi) Change name to cpymemsi.
+ * config/rs6000/rs6000.md: (movmemsi) Change name to cpymemsi.
+ * config/rx/rx.md: (UNSPEC_MOVMEM, movmemsi, rx_movmem): Change
+ movmem to cpymem.
+ * config/s390/s390-protos.h: Change movmem to cpymem.
+ * config/s390/s390.c (s390_expand_movmem, s390_expand_setmem,
+ s390_expand_insv): Change movmem to cpymem.
+ * config/s390/s390.md (movmem<mode>, movmem_short, *movmem_short,
+ movmem_long, *movmem_long, *movmem_long_31z): Change movmem to cpymem.
+ * config/sh/sh.md (movmemsi): Change name to cpymemsi.
+ * config/sparc/sparc.h: Change movmem to cpymem in comment.
+ * config/vax/vax-protos.h (vax_output_movmemsi): Remove prototype
+ for nonexistent function.
+ * config/vax/vax.h: Change movmem to cpymem in comment.
+ * config/vax/vax.md (movmemhi, movmemhi1): Change movmem to cpymem.
+ * config/visium/visium.h: Change movmem to cpymem in comment.
+ * config/visium/visium.md (movmemsi): Change name to cpymemsi.
+ * config/xtensa/xtensa.md (movmemsi): Change name to cpymemsi.
+ * doc/md.texi: Change movmem to cpymem and update description to match.
+ * doc/rtl.texi: Change movmem to cpymem.
+ * target.def (use_by_pieces_infrastructure_p): Change movmem to cpymem.
+ * doc/tm.texi: Regenerate.
+
+2019-06-27 Bill Schmidt <wschmidt@linux.ibm.com>
+
+ * config/rs6000/rs6000.c (rs6000_option_override_internal): Enable
+ -fvariable-expansion-in-unroller by default.
+ * doc/invoke.texi (-fvariable-expansion-in-unroller): Document new
+ default for Power.
+
+2019-06-27 David Edelsohn <dje.gcc@gmail.com>
+
+ Revert
+ 2019-06-26 David Edelsohn <dje.gcc@gmail.com>
+ * config.gcc (powerpc-ibm-aix*): Define target_gtfiles.
+
+ * config.gcc(rs6000-*-*): Define target_gtfiles.
+
+2019-06-27 Jan Hubicka <jh@suse.cz>
+
+ * ipa-devirt.c (odr_type_d): Add tbaa_enabled flag.
+ (add_type_duplicate): When odr hash is not allocated, to nothing.
+ (odr_based_tbaa_p): New function.
+ (set_type_canonical_for_odr_type): New function.
+ * ipa-utils.h (enable_odr_based_tbaa, odr_based_tbaa_p,
+ set_type_canonical_for_odr_type): New.
+ * tree.c (gimple_canonical_types_compatible_p): ODR types with
+ ODR based TBAA are not equivalent to non-ODR types.
+
+2019-06-27 Martin Liska <mliska@suse.cz>
+
+ PR tree-optimization/90974
+ PR rtl-optimization/90975
+ PR rtl-optimization/90976
+ PR target/91016
+ PR tree-optimization/91017
+ * config/i386/i386-expand.c (ix86_expand_rounddf_32): Remove
+ unused tmp.
+ * lra.c (lra_set_insn_recog_data): Remove a leftover from
+ initial commit of IRA.
+ * optabs.c (expand_twoval_binop): Use xop0 and xop1 instead
+ of op0 and op1.
+ * tree-vect-loop.c (vect_create_epilog_for_reduction):
+ Remove unused mode1.
+ * tree-vect-stmts.c (vectorizable_call): Remove dead assignment
+ to new_stmt_info.
+
+2019-06-27 Jakub Jelinek <jakub@redhat.com>
+
+ PR target/90991
+ * config/i386/sse.md (avx_vec_concat<mode>): Use nonimmediate_operand
+ instead of register_operand for operands[1], add m to its constraints
+ if operands[2] uses "C" constraint. Ensure in condition that if
+ operands[2] is not 0, then operands[1] is not a MEM. For last two
+ alternatives, use unaligned loads instead of aligned if operands[1] is
+ misaligned_operand.
+
+2019-06-27 Martin Liska <mliska@suse.cz>
+
+ * asan.c (asan_emit_allocas_unpoison): Remove obviously
+ dead assignments.
+ * bt-load.c (move_btr_def): Likewise.
+ * builtins.c (expand_builtin_apply_args_1): Likewise.
+ (expand_builtin_apply): Likewise.
+ * cfgexpand.c (expand_asm_stmt): Likewise.
+ (construct_init_block): Likewise.
+ * cfghooks.c (verify_flow_info): Likewise.
+ * cfgloopmanip.c (remove_path): Likewise.
+ * cfgrtl.c (rtl_verify_bb_layout): Likewise.
+ * cgraph.c (cgraph_node::set_pure_flag): Likewise.
+ * combine.c (simplify_if_then_else): Likewise.
+ * config/i386/i386.c (ix86_setup_incoming_vararg_bounds): Likewise.
+ (choose_basereg): Likewise.
+ (ix86_expand_prologue): Likewise.
+ (ix86_preferred_output_reload_class): Likewise.
+ * cselib.c (cselib_record_sets): Likewise.
+ * df-scan.c (df_scan_alloc): Likewise.
+ * dojump.c (do_jump_by_parts_greater_rtx): Likewise.
+ * early-remat.c (early_remat::record_equiv_candidates): Likewise.
+ * emit-rtl.c (try_split): Likewise.
+ * graphite-scop-detection.c (assign_parameter_index_in_region): Likewise.
+ * ipa-cp.c (cgraph_edge_brings_all_agg_vals_for_node): Likewise.
+ * ira-color.c (setup_profitable_hard_regs): Likewise.
+ * ira.c (rtx_moveable_p): Likewise.
+ * lra-eliminations.c (eliminate_regs_in_insn): Likewise.
+ * read-rtl.c (read_subst_mapping): Likewise.
+ * regrename.c (scan_rtx): Likewise.
+ * reorg.c (fill_slots_from_thread): Likewise.
+ * tree-inline.c (tree_function_versioning): Likewise.
+ * tree-ssa-reassoc.c (optimize_ops_list): Likewise.
+ * tree-ssa-sink.c (statement_sink_location): Likewise.
+ * tree-ssa-threadedge.c (thread_across_edge): Likewise.
+ * tree-vect-loop.c (vect_get_loop_niters): Likewise.
+ (vect_create_epilog_for_reduction): Likewise.
+ * tree.c (build_nonstandard_integer_type): Likewise.
+
+2019-06-27 Richard Biener <rguenther@suse.de>
+
+ * tree-ssa-sccvn.c (vn_reference_lookup_3): Encode valueized RHS.
+
+2019-06-27 Jun Ma <JunMa@linux.alibaba.com>
+
+ PR tree-optimization/89772
+ * gimple-fold.c (gimple_fold_builtin_memchr): consider trailing nuls in
+ out-of-bound accesses checking.
+
+2019-06-27 Martin Liska <mliska@suse.cz>
+
+ PR tree-optimization/91014
+ * tree-ssa-dse.c (initialize_ao_ref_for_dse): Bail out
+ when LHS is NULL_TREE.
+
+2019-06-27 Martin Liska <mliska@suse.cz>
+
+ * symbol-summary.h (traverse): Pass
+ argument a to the call of callback.
+ (gt_ggc_mx): Mark arguments as unused.
+ (gt_pch_nx): Likewise.
+
+2019-06-27 Kewen Lin <linkw@gcc.gnu.org>
+
+ PR target/62147
+ * gcc/loop-iv.c (find_simple_exit): Call finite_loop_p to update
+ finiteness.
+
+2019-06-26 Jeff Law <law@redhat.com>
+
+ PR tree-optimization/90883
+ * tree-ssa-dse.c (delete_dead_or_redundant_call): Fix signature.
+ (delete_dead_or_redundant_assignment): Likewise.
+
+ PR tree-optimization/90883
+ * tree-ssa-alias.c (stmt_kills_ref_p): Handle BUILT_IN_CALLOC.
+ * tree-ssa-dse.c: Update various comments to distinguish between
+ dead and redundant stores.
+ (initialize_ao_ref_for_dse): Handle BUILT_IN_CALLOC.
+ (dse_optimize_redundant_stores): New function.
+ (delete_dead_or_redundant_call): Renamed from delete_dead_call.
+ Distinguish between dead and redundant calls in dump output. All
+ callers updated.
+ (delete_dead_or_redundant_assignment): Similarly for assignments.
+ (dse_optimize_stmt): Handle _CHK variants. For statements which
+ store 0 into multiple memory locations, try to prove a subsequent
+ store is redundant.
+
+2019-06-26 Uroš Bizjak <ubizjak@gmail.com>
+
+ PR target/89021
+ * config/i386/i386.c (ix86_autovectorize_vector_sizes):
+ Autovectorize 8-byte vectors for TARGET_MMX_WITH_SSE.
+
+2019-06-26 Iain Sandoe <iain@sandoe.co.uk>
+
+ * config/rs6000/rs6000-internal.h (branch_island): New typedef.
+ (branch_islands): New extern.
+ * config/rs6000/rs6000-logue.c (macho_branch_islands): Moved from
+ * config/rs6000/rs6000.c: .. here.
+
+2019-06-26 Iain Sandoe <iain@sandoe.co.uk>
+
+ * config.gcc (powerpc*-*-linux*): Move target_gtfiles from here..
+ (powerpc*-*-*) ... to here.
+
+2019-06-26 Jeff Law <law@redhat.com>
+
+ * tree-ssa-dse.c (initialize_ao_ref_for_dse): Handle _chk variants of
+ memcpy, memmove and memset builtins.
+ (maybe_trim_memstar_call): Likewise.
+
+2019-06-26 David Edelsohn <dje.gcc@gmail.com>
+
+ * config/rs6000/rs6000-logue.c: Add #ifndef TARGET_PROFILE_KERNEL.
+
+2019-06-26 David Edelsohn <dje.gcc@gmail.com>
+
+ * config.gcc (powerpc-ibm-aix*): Define target_gtfiles.
+
+2019-06-26 Segher Boessenkool <segher@kernel.crashing.org>
+
+ * config/rs6000/rs6000-internal.h (rs6000_keep_leaf_when_profiled): New
+ declaration.
+ * config/rs6000/rs6000-logue.c (rs6000_keep_leaf_when_profiled): Remove
+ "static".
+ * config/rs6000/rs6000-logue.c (rs6000_keep_leaf_when_profiled): Delete
+ declaration.
+
+2019-06-26 Segher Boessenkool <segher@kernel.crashing.org>
+
+ * config/rs6000/rs6000.c: Fix previous commit, it missed some changes.
+
+2019-06-26 Richard Biener <rguenther@suse.de>
+
+ PR ipa/90982
+ * tree-inline.c (remap_ssa_name): Copy SSA range info.
+
+2019-06-26 Richard Biener <rguenther@suse.de>
+
+ * lto-streamer.h (lto_bitmap_alloc): Remove.
+ (lto_bitmap_free): Likewise.
+ * lto-streamer.c (lto_bitmap_alloc): Remove.
+ (lto_bitmap_free): Likewise.
+ (lto_obstack): Likewise.
+ (lto_obstack_initialized): Likewise.
+ * lto-streamer-out.c (lto_output): Use own obstack for local
+ bitmap, free it consistently.
+
+2019-06-26 Jakub Jelinek <jakub@redhat.com>
+
+ PR target/90991
+ * config/i386/sse.md
+ (*<extract_type>_vinsert<shuffletype><extract_suf>_0): Use vmovupd,
+ vmovups, vmovdqu, vmovdqu32 or vmovdqu64 instead of the aligned
+ insns if operands[2] is misaligned_operand.
+
+2019-06-26 Li Jia He <helijia@linux.ibm.com>
+
+ * config/rs6000/rs6000.h (TARGET_MADDLD): Remove the restriction of
+ TARGET_POWERPC64.
+ * config/rs6000/rs6000.md (maddld): Change maddld match_operand from DI
+ to GPR.
+
+2019-06-26 Segher Boessenkool <segher@kernel.crashing.org>
+
+ * doc/invoke.texi (Warning Options): Fix some @opindex syntax.
+
+2019-06-26 Martin Liska <mliska@suse.cz>
+
+ PR tree-optimization/90973
+ * tree-vect-loop.c (vect_get_known_peeling_cost): Use
+ epilogue_cost_vec instead of prologue_cost_vec for
+ a epilogue cost.
+
+2019-06-26 Martin Liska <mliska@suse.cz>
+
+ * bb-reorder.c (connect_better_edge_p): Add missing else
+ statement in the middle of if-else statements.
+
+/home/marxin/Programming/gcc/gcc/bb-reorder.c:1031:2: warning: Value stored to 'is_better_edge' is never read
+ is_better_edge = true;
+ ^ ~~~~
+/home/marxin/Programming/gcc/gcc/bb-reorder.c:1034:2: warning: Value stored to 'is_better_edge' is never read
+ is_better_edge = false;
+ ^ ~~~~~
+
+2019-06-25 Hongtao Liu <hongtao.liu@intel.com>
+ H.J. Lu <hongjiu.lu@intel.com>
+ Olga Makhotina <olga.makhotina@intel.com>
+
+ * common/config/i386/i386-common.c
+ (OPTION_MASK_ISA_AVX512VP2INTERSECT_SET,
+ OPTION_MASK_ISA_AVX512VP2INTERSECT_UNSET): New macros.
+ (OPTION_MASK_ISA2_AVX512F_UNSET): Add
+ OPTION_MASK_ISA_AVX512VP2INTERSECT_UNSET.
+ (ix86_handle_option): Handle -mavx512vp2intersect.
+ * config/i386/avx512vp2intersectintrin.h: New.
+ * config/i386/avx512vp2intersectvlintrin.h: New.
+ * config/i386/cpuid.h (bit_AVX512VP2INTERSECT): New.
+ * config/i386/driver-i386.c (host_detect_local_cpu): Detect
+ AVX512VP2INTERSECT.
+ * config/i386/i386-builtin-types.def: Add new types.
+ * config/i386/i386-builtin.def: Add new builtins.
+ * config/i386/i386-builtins.c: (enum processor_features): Add
+ F_AVX512VP2INTERSECT.
+ (static const _isa_names_table isa_names_table): Ditto.
+ * config/i386/i386-c.c (ix86_target_macros_internal): Define
+ __AVX512VP2INTERSECT__.
+ * config/i386/i386-expand.c (ix86_expand_builtin): Expand
+ IX86_BUILTIN_2INTERSECTD512, IX86_BUILTIN_2INTERSECTQ512,
+ IX86_BUILTIN_2INTERSECTD256, IX86_BUILTIN_2INTERSECTQ256,
+ IX86_BUILTIN_2INTERSECTD128, IX86_BUILTIN_2INTERSECTQ128.
+ * config/i386/i386-modes.def (P2QI, P2HI): New modes.
+ * config/i386/i386-options.c (ix86_target_string): Add
+ -mavx512vp2intersect.
+ (ix86_option_override_internal): Handle AVX512VP2INTERSECT.
+ * config/i386/i386.c (ix86_hard_regno_nregs): Allocate two regs for
+ P2HImode and P2QImode.
+ (ix86_hard_regno_mode_ok): Register pair only starts at even hardreg
+ number for P2QImode and P2HImode.
+ (ix86_regmode_natural_size): New function.
+ * config/i386/i386.h (TARGET_AVX512VP2INTERSECT,
+ TARGET_AVX512VP2INTERSECT_P, PTA_AVX512VP2INTERSECT
+ REGMODE_NATURAL_SIZE, MASK_PAIR_REGNO_P): New.
+ * config/i386/i386-protos.h (ix86_regmode_natural_size): Declare
+ * config/i386/i386.opt: Add -mavx512vp2intersect.
+ * config/i386/immintrin.h: Include avx512vp2intersectintrin.h and
+ avx512vp2intersectvlintrin.h.
+ * config/i386/sse.md (define_c_enum "unspec"): Add UNSPEC_VP2INTERSECT.
+ (define_mode_iterator VI48_AVX512VP2VL): New.
+ (avx512vp2intersect_2intersect<mode>,
+ avx512vp2intersect_2intersectv16si): New define_insn patterns.
+ * config.gcc: Add avx512vp2intersectvlintrin.h and
+ avx512vp2intersectintrin.h to extra_headers.
+ * doc/invoke.texi: Document -mavx512vp2intersect.
+
+2019-06-25 Iain Sandoe <iain@sandoe.co.uk>
+
+ * config/rs6000/darwin.h (ENDFILE_SPEC): New.
+
+2019-06-25 Bill Seurer <seurer@linux.vnet.ibm.com>
+
+ * config/rs6000/rs6000.c (stack_info, rs6000_pic_labelno,
+ savres_routine_syms, savres_routine_name, morestack_ref,
+ rs6000_init_machine_status, save_reg_p, first_reg_to_save,
+ first_fp_reg_to_save, first_altivec_reg_to_save, compute_vrsave_mask,
+ compute_save_world_info, is_altivec_return_reg, fixed_reg_p,
+ rs6000_savres_strategy, rs6000_stack_info, debug_stack_info,
+ rs6000_return_addr, rs6000_decl_ok_for_sibcall,
+ rs6000_function_ok_for_sibcall, rs6000_ra_ever_killed,
+ rs6000_emit_load_toc_table, rs6000_emit_eh_reg_restore, uses_TOC,
+ create_TOC_reference, rs6000_aix_asm_output_dwarf_table_ref,
+ rs6000_emit_stack_tie, rs6000_emit_allocate_stack_1,
+ get_stack_clash_protection_probe_interval,
+ get_stack_clash_protection_guard_size,
+ rs6000_emit_probe_stack_range_stack_clash, rs6000_emit_allocate_stack,
+ rs6000_emit_probe_stack_range, output_probe_stack_range_1,
+ interesting_frame_related_regno, output_probe_stack_range_stack_clash,
+ output_probe_stack_range, rs6000_frame_related, generate_set_vrsave,
+ gen_frame_set, gen_frame_load, gen_frame_store, emit_frame_save,
+ gen_frame_mem_offset, rs6000_savres_routine_name,
+ rs6000_savres_routine_sym, rs6000_emit_stack_reset,
+ ptr_regno_for_savres, rs6000_emit_savres_rtx,
+ rs6000_emit_prologue_move_from_cr, split_stack_arg_pointer_used_p,
+ rs6000_global_entry_point_prologue_needed_p,
+ rs6000_get_separate_components, rs6000_components_for_bb,
+ rs6000_disqualify_components, rs6000_emit_prologue_components,
+ rs6000_emit_epilogue_components, rs6000_set_handled_components,
+ emit_vrsave_prologue, emit_split_stack_prologue, rs6000_emit_prologue,
+ rs6000_output_savres_externs, rs6000_output_function_prologue,
+ rs6000_keep_leaf_when_profiled, load_cr_save, restore_saved_cr,
+ load_lr_save, restore_saved_lr, add_crlr_cfa_restore,
+ offset_below_red_zone_p, emit_cfa_restores, rs6000_emit_epilogue,
+ rs6000_output_function_epilogue, gen_add3_const,
+ rs6000_expand_split_stack_prologue, rs6000_live_on_entry,
+ rs6000_split_stack_space_check, rs6000_save_toc_in_prologue_p): Moved
+ to rs6000-logue.c.
+ (machine_function): Moved to rs6000.h.
+ (rs6000_stack_t, ALTIVEC_REG_BIT, quad_address_offset_p) Moved to
+ rs6000-internal.h.
+ * config/rs6000/rs6000-logue.c(stack_info, rs6000_pic_labelno,
+ savres_routine_syms, savres_routine_name, morestack_ref,
+ rs6000_init_machine_status, save_reg_p, first_reg_to_save,
+ first_fp_reg_to_save, first_altivec_reg_to_save, compute_vrsave_mask,
+ compute_save_world_info, is_altivec_return_reg, fixed_reg_p,
+ rs6000_savres_strategy, rs6000_stack_info, debug_stack_info,
+ rs6000_return_addr, rs6000_decl_ok_for_sibcall,
+ rs6000_function_ok_for_sibcall, rs6000_ra_ever_killed,
+ rs6000_emit_load_toc_table, rs6000_emit_eh_reg_restore, uses_TOC,
+ create_TOC_reference, rs6000_aix_asm_output_dwarf_table_ref,
+ rs6000_emit_stack_tie, rs6000_emit_allocate_stack_1,
+ get_stack_clash_protection_probe_interval,
+ get_stack_clash_protection_guard_size,
+ rs6000_emit_probe_stack_range_stack_clash, rs6000_emit_allocate_stack,
+ rs6000_emit_probe_stack_range, output_probe_stack_range_1,
+ interesting_frame_related_regno, output_probe_stack_range_stack_clash,
+ output_probe_stack_range, rs6000_frame_related, generate_set_vrsave,
+ gen_frame_set, gen_frame_load, gen_frame_store, emit_frame_save,
+ gen_frame_mem_offset, rs6000_savres_routine_name,
+ rs6000_savres_routine_sym, rs6000_emit_stack_reset,
+ ptr_regno_for_savres, rs6000_emit_savres_rtx,
+ rs6000_emit_prologue_move_from_cr, split_stack_arg_pointer_used_p,
+ rs6000_global_entry_point_prologue_needed_p,
+ rs6000_get_separate_components, rs6000_components_for_bb,
+ rs6000_disqualify_components, rs6000_emit_prologue_components,
+ rs6000_emit_epilogue_components, rs6000_set_handled_components,
+ emit_vrsave_prologue, emit_split_stack_prologue, rs6000_emit_prologue,
+ rs6000_output_savres_externs, rs6000_output_function_prologue,
+ rs6000_keep_leaf_when_profiled, load_cr_save, restore_saved_cr,
+ load_lr_save, restore_saved_lr, add_crlr_cfa_restore,
+ offset_below_red_zone_p, emit_cfa_restores, rs6000_emit_epilogue,
+ rs6000_output_function_epilogue, gen_add3_const,
+ rs6000_expand_split_stack_prologue, rs6000_live_on_entry,
+ rs6000_split_stack_space_check, rs6000_save_toc_in_prologue_p): Moved
+ to here from rs6000.c.
+ * config/rs6000/rs6000.h (machine_function): Moved to here from rs6000.c.
+ * config/rs6000/rs6000-internal.h: (rs6000_stack_t, ALTIVEC_REG_BIT,
+ quad_address_offset_p) Moved to here from rs6000.c.
+ * config/rs6000/t-rs6000: Add new source file rs6000-logue.c.
+ * config/config.gcc: Add new source file rs6000-logue.c to garbage
+ collector.
+
+2019-06-25 Martin Liska <mliska@suse.cz>
+
+ * hash-table.c (hashtab_chk_error): Move here from ...
+ * hash-table.h (hashtab_chk_error): ... here.
+
+2019-06-25 Martin Liska <mliska@suse.cz>
+
+ PR tree-optimization/90978
+ * df-scan.c (df_update_entry_block_defs): Remove dead else
+ branch.
+ (df_update_exit_block_uses): Likewise.
+
+2019-06-25 Kwok Cheung Yeung <kcy@codesourcery.com>
+ Andrew Stubbs <ams@codesourcery.com>
+
+ * config.gcc (thread_file): Set to gcn for AMD GCN.
+ * config/gcn/gcn.c (gcn_emutls_var_init): New function.
+ (TARGET_EMUTLS_VAR_INIT): New hook.
+
+2019-06-25 Martin Jambor <mjambor@suse.cz>
+
+ PR ipa/90939
+ * ipa-cp.c (ipcp_bits_lattice::meet_with): Remove assert.
+
+2019-06-25 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/90930
+ * tree-ssa-reassoc.c (reassociate_bb): Only rewrite expression
+ into parallel form in the last pass instance.
+
+2019-06-25 Claudiu Zissulescu <claziss@synopsys.com>
+
+ * config/arc/arc.c (arc_symbol_binds_local_p): New function.
+ (arc_legitimize_pic_address): Simplify and cleanup the function.
+ (SYMBOLIC_CONST): Remove.
+ (prepare_pic_move): Likewise.
+ (prepare_move_operands): Handle complex mov cases here.
+ (arc_legitimize_address_0): Remove call to
+ arc_legitimize_pic_address.
+ (arc_legitimize_address): Remove call to
+ arc_legitimize_tls_address.
+ * config/arc/arc.md (movqi_insn): Allow Cm3 match.
+ (movhi_insn): Likewise.
+
+2019-06-25 Jozef Lawrynowicz <jozef.l@mittosystems.com>
+
+ * gcc/c-family/c-common.c (c_common_nodes_and_builtins): Define
+ alternate "__intN__" name for "__intN" types.
+ * gcc/c/c-parser.c (c_parse_init): Create keyword for "__intN__" type.
+ * gcc/cp/lex.c (init_reswords): Likewise.
+ * gcc/config/msp430/msp430.h: Use __int20__ for SIZE_TYPE and
+ PTRDIFF_TYPE.
+ * gcc/cp/cp-tree.h (cp_decl_specifier_seq): New bitfield "int_n_alt".
+ * gcc/c/c-decl.c (declspecs_add_type): Don't pedwarn about "__intN" ISO
+ C incompatibility if alternate "__intN__" form is used.
+ * gcc/cp/decl.c (grokdeclarator): Likewise.
+ * gcc/cp/parser.c (cp_parser_simple_type_specifier): Set
+ decl_specs->int_n_alt if "__intN__" form is used.
+ * gcc/gimple-ssa-sprintf.c (build_intmax_type_nodes): Accept "__intN__"
+ format of "__intN" types for UINTMAX_TYPE.
+ * gcc/brig/brig-lang.c (brig_build_c_type_nodes): Accept "__intN__"
+ format of "__intN" types for SIZE_TYPE.
+ * gcc/lto/lto-lang.c (lto_build_c_type_nodes): Likewise.
+ * gcc/stor-layout.c (initialize_sizetypes): Accept "__intN__"
+ format of "__intN" types for SIZETYPE.
+ * gcc/tree.c (build_common_tree_nodes): Accept "__intN__"
+ format of "__intN" types for SIZE_TYPE and PTRDIFF_TYPE.
+ * gcc/doc/invoke.texi: Document that __intN__ disables pedantic
+ warnings.
+
+2019-06-25 Jan Hubicka <jh@suse.cz>
+
+ * tree-ssa-alias.c (indirect_ref_may_alias_decl_p): Check that
+ base2_alias_set is non-zero before doing TBAA based disambiguation.
+
+2019-06-25 Martin Liska <mliska@suse.cz>
+
+ PR tree-optimization/90973
+ * tree-vect-loop.c (vect_get_known_peeling_cost): Sum retval
+ of prologue and epilogue.
+
+2019-06-24 Jan Hubicka <jh@suse.cz>
+
+ * ipa-utils.h (type_with_linkage_p): Verify that type is
+ CXX_ODR_P.
+ (odr_type_p): Remove extra return.
+ * lto-streamer-out.c (hash_tree): Hash TYPE_CXX_ODR_P;
+ hash STRING_FLAG only for arrays and integers.
+ * tree-stremaer-in.c (unpack_ts_type_common_value_fields):
+ Update analogously.
+ * tree-streamer-out.c (pack_ts_type_common_value_fields):
+ Likewise.
+ * print-tree.c (print_node): Print cxx-odr-p
+ and string-flag.
+ * tree.c (need_assembler_name_p): Also check that type
+ is CXX_ODR_TYPE_P
+ (verify_type_variant): Update verification of SRING_FLAG;
+ also check CXX_ODR_P.
+ * tree.h (ARRAY_OR_INTEGER_TYPE_CHECK): New macro.
+ (TYPE_STRING_FLAG): Use it.
+ (TYPE_CXX_ODR_P): New macro.
+ * dwarf2out.c (gen_array_type_die): First check that type
+ is an array and then test string flag.
+
+2019-06-24 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/90972
+ * tree-vect-stmts.c (vect_init_vector): Handle CONSTANT_CLASS_P
+ in common code, dealing with STRING_CST properly.
+
+2019-06-24 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/90930
+ PR tree-optimization/90316
+ * tree-ssa-alias.c (walk_non_aliased_vuses): Add missing
+ decrement of limit.
+
+2019-06-24 Martin Sebor <msebor@redhat.com>
+
+ * tree-pretty-print.h: Remove unnecessary punctuation characters
+ from a diagnostic.
+ * tree-ssa.c (release_defs_bitset): Correct preprocessor conditional.
+
+2019-06-24 Jonathan Wakely <jwakely@redhat.com>
+
+ * ginclude/float.h (FLT_DECIMAL_DIG, DBL_DECIMAL_DIG, LDBL_DECIMAL_DIG)
+ (FLT_HAS_SUBNORM, DBL_HAS_SUBNORM, LDBL_HAS_SUBNORM, FLT_TRUE_MIN)
+ (DBL_TRUE_MIN, LDBL_TRUE_MIN): Also define for C++17.
+
+2019-06-23 Iain Sandoe <iain@sandoe.co.uk>
+
+ * config/rs6000/darwin.h: Handle GCC target pragma.
+
+2019-06-23 Iain Sandoe <iain@sandoe.co.uk>
+
+ * config/rs6000/darwin.h: (__PPC__, __PPC64__): New.
+
+2019-06-22 Jeff Law <law@redhat.com>
+
+ * config/avr/avr.c (TARGET_BUILTIN_SETJMP_FRAME_VALUE): Remove.
+
+2019-06-22 Jan Hubicka <jh@suse.cz>
+
+ * tree-ssa-alias.c (nonoverlapping_component_refs_p): Do not
+ give up on bitfields; continue searching for different refs
+ appearing later.
+
+2019-06-21 Jakub Jelinek <jakub@redhat.com>
+
+ * tree-vect-data-refs.c (vect_find_stmt_data_reference): Handle
+ even zero DR_OFFSET, but DR_BASE_ADDRESS of POINTER_PLUS_EXPR
+ containing the offset as possible simd lane access. Look through
+ widening conversion. Move the
+ TREE_CODE (DR_INIT (newdr)) == INTEGER_CST test earlier and reindent.
+
+2019-06-21 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/90930
+ * tree-ssa-reassoc.c (rewrite_expr_tree_parallel): Set visited
+ flag on new stmts to avoid re-processing them.
+
+2019-06-21 Matthew Beliveau <mbelivea@redhat.com>
+
+ PR c++/90875 - added -Wswitch-outside-range option
+ * doc/invoke.texi (Wswitch-outside-range): Document.
+
+2019-06-21 Jeff Law <law@redhat.com>
+
+ PR tree-optimization/90949
+ * tree-ssa-copy.c (fini_copy_prop): Use reset_flow_sensitive_info.
+ * tree-ssanames.c (reset_flow_sensitive_info): Reset non-null state.
+
+2019-06-21 Richard Biener <rguenther@suse.de>
+
+ PR debug/90914
+ * dwarf2out.c (prune_unused_types_walk): Always consider
+ function-local extern declarations as used.
+
+2019-06-21 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/90913
+ * tree-vect-loop-manip.c (vect_loop_versioning): Do not re-use
+ the scalar variant of if-conversion versioning.
+
+2019-06-21 Jakub Jelinek <jakub@redhat.com>
+
+ * omp-low.c (lower_rec_simd_input_clauses): Add rvar2 argument,
+ create another "omp scan inscan exclusive" array if
+ !ctx->scan_inclusive.
+ (lower_rec_input_clauses): Handle exclusive scan inscan reductions.
+ (lower_omp_scan): Likewise.
+ * tree-vectorizer.h (struct _stmt_vec_info): Use 3-bit instead of
+ 2-bit bitfield for simd_lane_access_p member.
+ * tree-vect-data-refs.c (vect_analyze_data_refs): Also handle
+ aux == (void *)-4 as simd lane access.
+ * tree-vect-stmts.c (check_scan_store): Handle exclusive scan. Update
+ comment with permutations to show the canonical permutation order.
+ (vectorizable_scan_store): Handle exclusive scan.
+ (vectorizable_store): Call vectorizable_scan_store even for
+ STMT_VINFO_SIMD_LANE_ACCESS_P > 3.
+
+ * tree-vect-data-refs.c (vect_find_stmt_data_reference): Handle
+ "omp simd array" arrays with one byte elements.
+
+2019-06-20 Uroš Bizjak <ubizjak@gmail.com>
+
+ * config/alpha/alpha.md (@unaligned_store<mode>):
+ Rename from unaligned_store<mode>.
+ (@reload_in<mode>_aligned): Rename from reload_in<mode>_aligned.
+ * config/alpha/sync.md (@load_locked_<mode>): Rename
+ from load_locked_<mode>.
+ (@store_conditional_<mode>): Rename from store_conditional_<mode>.
+ (@atomic_compare_and_swap<mode>_1): Rename
+ from atomic_compare_and_swap<mode>_1.
+ (@atomic_exchange<mode>_1): Rename from atomic_exchange<mode>_1.
+ * config/alpha/alpha.c (alpha_expand_mov_nobwx):
+ Use gen_reload_in_aligned and gen_unaligned_store.
+ (emit_load_locked): Remove.
+ (emit_store_conditional): Ditto.
+ (alpha_split_atomic_op): Use gen_load_locked and gen_store_conditional.
+ (alpha_split_compare_and_swap): Ditto.
+ (alpha_expand_compare_and_swap_12): Use gen_atomic_compare_and_swap_1.
+ (alpha_split_compare_and_swap_12): Use gen_load_locked
+ and gen_store_conditional.
+ (alpha_split_atomic_exchange): Ditto.
+ (alpha_expand_atomic_exchange_12): Use gen_atomic_exchange_1.
+ (alpha_split_atomic_exchange_12): Use gen_load_locked
+ and gen_store_conditional.
+
+2019-06-20 Richard Earnshaw <rearnsha@arm.com>
+
+ * config/aarch64/aarch64-errata.h: New file.
+ * config/aarch64/aarch64-elf-raw.h (CA53_ERR_835769_SPEC): Delete.
+ (CA53_ERR_843419_SPEC): Delete.
+ (LINK_SPEC): Use AARCH64_ERRATA_LINK_SPEC instead of above.
+ * config/aarch64/aarch64-linux.h: Likewise.
+ * config/aarch64/aarch64-netbsd.h: Likewise.
+ * config/aarch64/aarch64-freebsd.h: Likewise.
+
+2019-06-20 Marek Polacek <polacek@redhat.com>
+
+ * config/sh/sh.c (sh2a_function_vector_p): Use get_attribute_name.
+
+2019-06-20 Michael Meissner <meissner@linux.ibm.com>
+
+ * config/rs6000/rs6000.md (isa attribute): Add support for
+ for a future processor.
+
+2019-06-20 H.J. Lu <hongjiu.lu@intel.com>
+
+ PR target/54855
+ * config/i386/i386-expand.c (ix86_expand_vector_set): Generate
+ standard scalar operation pattern for V2DF.
+ * config/i386/sse.md (*<sse>_vm<plusminus_insn><mode>3): New.
+ (*<sse>_vm<multdiv_mnemonic><mode>3): Likewise.
+ (*ieee_<ieee_maxmin><mode>3): Likewise.
+ (vec_setv2df_0): Likewise.
+
+2019-06-20 Jan Hubicka <jh@suse.cz>
+
+ * tree-ssa-alias.c (aliasing_component_refs_p): Remove ref2_is_decl
+ parameter; it has no use in gimple memory model.
+ (indirect_ref_may_alias_decl_p): Update.
+
+2019-06-20 Martin Liska <mliska@suse.cz>
+
+ * params.def (PARAM_HASH_TABLE_VERIFICATION_LIMIT): Decrease
+ to 10.
+
+2019-06-20 Jakub Jelinek <jakub@redhat.com>
+
+ * tree-vect-stmts.c (enum scan_store_kind): New type.
+ (scan_store_can_perm_p): Change last argument from int * to
+ vec<enum scan_store_kind> *, record precisely which permutations
+ need whole vector left shift or that plus VEC_COND_EXPR.
+ (vectorizable_scan_store): Adjust caller, use whole vector left shift
+ and additional VEC_COND_EXPR only for those iterations that need it.
+
+2019-06-20 Alexandre Oliva <oliva@adacore.com>
+
+ * config.gcc: Fix ARM --with-fpu checking and error message.
+
+2019-06-19 Marek Polacek <polacek@redhat.com>
+
+ PR c++/60364 - noreturn after first decl not diagnosed.
+ * attribs.c (get_attribute_namespace): No longer static.
+ (decl_attributes): Avoid shadowing. Preserve the C++11 form for C++11
+ attributes.
+ (attr_noreturn_exclusions): Make it extern.
+ * attribs.h (get_attribute_namespace): Declare.
+ * tree-inline.c (function_attribute_inlinable_p): Use
+ get_attribute_name.
+
+2019-06-19 Martin Sebor <msebor@redhat.com>
+
+ PR tree-optimization/90626
+ * tree-ssa-strlen.c (strxcmp_unequal): Fix typos.
+
+ PR tree-optimization/90626
+ * tree-ssa-strlen.c (strxcmp_unequal): New function.
+ (handle_builtin_string_cmp): Call it.
+
+2019-06-19 Iain Sandoe <iain@sandoe.co.uk>
+
+ * config/darwin.h (DRIVER_SELF_SPECS): Add RDYNAMIC, DARWIN_PIE_SPEC
+ and DARWIN_NOPIE_SPEC.
+ (RDYNAMIC): New, modified from DARWIN_EXPORT_DYNAMIC.
+ (DARWIN_PIE_SPEC): Collate from darwin.h and darwin9.h.
+ (DARWIN_NOPIE_SPEC): Collate from darwin10.h.
+ (DARWIN_NOCOMPACT_UNWIND): New from darwin10.h
+ (DARWIN_EXPORT_DYNAMIC): Delete.
+ * config/darwin10.h (LINK_GCC_C_SEQUENCE_SPEC): Move no_compact_unwind
+ and pie options processing to darwin.h.
+ * config/darwin9.h (DARWIN_PIE_SPEC): Move pie processing to darwin.h
+
+2019-06-19 Iain Sandoe <iain@sandoe.co.uk>
+
+ * config/darwin-driver.c (darwin_driver_init): Fix off-by-one errors
+ in computing the number of options to be moved.
+
+2019-06-19 Maya Rashish <coypu@sdf.org>
+
+ * config/arm/netbsd-elf.h (SYSARCH_ARM_SYNC_ICACHE): New definition.
+ (CLEAR_INSN_CACHE) Use it.
+
+2019-06-19 Uroš Bizjak <ubizjak@gmail.com>
+
+ * config/i386/i386.md (cmpstrnsi): Remove dead code.
+
+2019-06-19 Wilco Dijkstra <wdijkstr@arm.com>
+
+ PR middle-end/84521
+ * builtins.c (expand_builtin_setjmp_setup): Save
+ hard_frame_pointer_rtx.
+ (expand_builtin_setjmp_receiver): Do not emit sfp = fp move since we
+ restore fp.
+ * function.c (expand_function_start): Save hard_frame_pointer_rtx for
+ non-local goto.
+ * lra-eliminations.c (eliminate_regs_in_insn): Remove sfp = fp
+ elimination code.
+ (remove_reg_equal_offset_note): Remove unused function.
+ * reload1.c (eliminate_regs_in_insn): Remove sfp = hfp elimination
+ code.
+ * config/arc/arc.c (TARGET_BUILTIN_SETJMP_FRAME_VALUE): Remove.
+ (arc_builtin_setjmp_frame_value): Remove function.
+ * config/avr/avr.c (TARGET_BUILTIN_SETJMP_FRAME_VALUE): Remove.
+ (avr_builtin_setjmp_frame_value): Remove function.
+ * config/i386/i386.c (TARGET_BUILTIN_SETJMP_FRAME_VALUE): Remove.
+ (ix86_builtin_setjmp_frame_value): Remove function.
+ * config/pa/pa.md (nonlocal_goto): Remove FP adjustment.
+ * config/sparc/sparc.c (TARGET_BUILTIN_SETJMP_FRAME_VALUE): Remove.
+ (sparc_builtin_setjmp_frame_value): Remove function.
+ * config/vax/vax.c (TARGET_BUILTIN_SETJMP_FRAME_VALUE): Remove.
+ (vax_builtin_setjmp_frame_value): Remove function.
+ * config/xtensa/xtensa.c (xtensa_frame_pointer_required): Force frame
+ pointer if has_nonlocal_label.
+
+2019-06-19 Jakub Jelinek <jakub@redhat.com>
+
+ * doc/md.texi: Document vec_shl_<mode> pattern.
+ * optabs.def (vec_shl_optab): New optab.
+ * optabs.c (shift_amt_for_vec_perm_mask): Add shift_optab
+ argument, if == vec_shl_optab, check for left whole vector shift
+ pattern rather than right shift.
+ (expand_vec_perm_const): Add vec_shl_optab support.
+ * optabs-query.c (can_vec_perm_var_p): Mention also vec_shl optab
+ in the comment.
+ * tree-vect-generic.c (lower_vec_perm): Support permutations which
+ can be handled by vec_shl_optab.
+ * tree-vect-stmts.c (scan_store_can_perm_p): New function.
+ (check_scan_store): Use it.
+ (vectorizable_scan_store): If target can't do normal permutations,
+ try to use whole vector left shifts and if needed a VEC_COND_EXPR
+ after it.
+ * config/i386/sse.md (vec_shl_<mode>): New expander.
+
+ * omp-low.c (lower_rec_input_clauses): Handle references properly
+ in inscan clauses.
+ (lower_omp_scan): Likewise.
+
+2019-06-19 Kugan Vivekanandarajah <kugan.vivekanandarajah@linaro.org>
+
+ * tree-ssa-address.c (preferred_mem_scale_factor): Handle when
+ mem_mode is BLKmode.
+
+2019-06-18 Max Filippov <jcmvbkbc@gmail.com>
+
+ PR target/90922
+ * config/xtensa/xtensa.c (xtensa_expand_prologue): Add stack
+ pointer adjustment for the case of no callee-saved registers and
+ stack frame bigger than 128 bytes.
+
+2019-06-18 Thomas Schwinge <thomas@codesourcery.com>
+
+ PR middle-end/90862
+ * omp-low.c (check_omp_nesting_restrictions): Handle
+ GF_OMP_TARGET_KIND_OACC_DECLARE.
+
+2019-06-18 Uroš Bizjak <ubizjak@gmail.com>
+
+ * config/i386/i386.md (@cmp<mode>_1): Rename from cmp<mode>_1.
+ (@add<mode>3_carry): Rename from add<mode>3_carry.
+ (@sub<mode>3_carry_ccc): Rename from sub<mode>3_carry_ccc.
+ (@sub<mode>3_carry_ccgz): Rename form sub<mode>3_carry_ccgz.
+ (@copysign<mode>3_const): Rename from copysign<mode>3_const.
+ (@copysign<mode>3_var): Rename from copysign<mode>3_var.
+ (@xorsign<mode>3_1): Rename from xorsign<mode>3_1.
+ (@x86_shift<mode>_adj_1): Rename from x86_shift<mode>_adj_1.
+ (@x86_shift<mode>_adj_2): Rename from x86_shift<mode>_adj_2.
+ (@x86_shift<mode>_adj_3): Rename from x86_shift<mode>_adj_3.
+ (cmpstrnsi): Use gen_cmp_1.
+ (lwp_slwpcb): Use gen_lwp_slwpcb_1.
+ (@lwp_slwpcb<mode>_1): Rename from lwp_slwpcb<mode>_1.
+ (@umonitor_<mode>): Rename from umonitor_<mode>.
+ * config/i386/i386-expand.c (ix86_expand_copysign):
+ Use gen_copysign3_const and gen_copysign3_var.
+ (ix86_expand_xorsign): Use gen_xorsign3_1.
+ (ix86_expand_branch): Use gen_sub3_carry_ccc,
+ gen_sub3_carry_ccgz and gen_cmp1.
+ (ix86_expand_int_addcc): Use gen_sub3_carry and gen_add3_carry.
+ (ix86_split_ashl): Use gen_x86_shift_adj_1 and gen_x86_shift_adj_2.
+ (ix86_split_ashr): Use gen_x86_shift_adj_1 and gen_x86_shift_adj_3.
+ (ix86_split_lshr): Ditto.
+ (ix86_expand_builtin) <case IX86_BUILTIN_UMONITOR>: Use gen_umonitor.
+
+2019-06-18 Jason Merrill <jason@redhat.com>
+
+ * tree.c (build_constructor): Add MEM_STAT_DECL.
+
+2019-06-18 Richard Sandiford <richard.sandiford@arm.com>
+
+ * config/aarch64/aarch64-modes.def (CC_NZC): New CC_MODE.
+ * config/aarch64/aarch64-sve.md (*<optab><mode>3_cc)
+ (ptest_ptrue<mode>, while_ult<GPI:mode><PRED_ALL:mode>)
+ (*while_ult<GPI:mode><PRED_ALL:mode>_cc, *cmp<cmp_op><mode>)
+ (*cmp<cmp_op><mode>_ptest, *cmp<cmp_op><mode>_cc)
+ (*pred_cmp<cmp_op><mode>_combine, *pred_cmp<cmp_op><mode>)
+ (vec_cmp<mode><vpred>, vec_cmpu<mode><vpred>, cbranch<mode>4):
+ Use CC_NZC instead of CC.
+ * config/aarch64/aarch64.md (condjump): Print a '.' in SVE conditions.
+ * config/aarch64/aarch64.c (aarch64_sve_condition_codes): New variable.
+ (aarch64_print_operand): Handle E_CC_NZCmode.
+ (aarch64_emit_sve_ptrue_op_cc): Use gen_set_clobber_cc_nzc instead
+ of gen_set_clobber_cc.
+
+2019-06-18 Richard Sandiford <richard.sandiford@arm.com>
+
+ * config/aarch64/aarch64-sve.md: Tabify file.
+
+2019-06-18 Richard Sandiford <richard.sandiford@arm.com>
+
+ * config/aarch64/aarch64-protos.h (aarch64_pfalse_reg): Declare.
+ * config/aarch64/aarch64.c (aarch64_pfalse_reg): New function.
+ * config/aarch64/aarch64-sve.md: Use it.
+
+2019-06-18 Richard Sandiford <richard.sandiford@arm.com>
+
+ * config/aarch64/aarch64-protos.h (aarch64_ptrue_reg): Declare.
+ * config/aarch64/aarch64.c (aarch64_ptrue_reg): New functions.
+ (aarch64_expand_sve_widened_duplicate, aarch64_expand_sve_mem_move)
+ (aarch64_maybe_expand_sve_subreg_move, aarch64_evpc_rev_local)
+ (aarch64_expand_sve_vec_cmp_int): Use it.
+ (aarch64_expand_sve_vec_cmp_float): Likewise.
+ * config/aarch64/aarch64-sve.md: Likewise throughout.
+
+2019-06-18 Richard Sandiford <richard.sandiford@arm.com>
+ Kugan Vivekanandarajah <kuganv@linaro.org>
+
+ * config/aarch64/aarch64-sve.md (*cond_<optab><mode>_0): Delete.
+ (*cond_<optab><mode>_z): Fold into...
+ (*cond_<optab><mode>_any): ...here. Also handle cases in which
+ operand 4 can be tied to operand 0 (either inherently or via RA).
+
+2019-06-18 Richard Biener <rguenther@suse.de>
+
+ PR debug/90900
+ * cfgexpand.c (expand_debug_expr): Treat NOTE_P DECL_RTL
+ as if optimized away.
+
+2019-06-18 Tom de Vries <tdevries@suse.de>
+
+ * config/nvptx/nvptx-protos.h (gen_set_softstack_insn): Remove.
+ * config/nvptx/nvptx.c (gen_set_softstack_insn): Remove.
+ * config/nvptx/nvptx.md (define_insn "set_softstack_<mode>"):
+ Rename to ...
+ (define_insn "@set_softstack_<mode>"): ... this.
+ (define_insn "omp_simt_enter_<mode>"): Rename to ...
+ (define_insn "@omp_simt_enter_<mode>"): ... this.
+ (define_insn "omp_simt_exit_<mode>"): Rename to ...
+ (define_insn "@omp_simt_exit_<mode>"): ... this.
+
+2019-06-18 Richard Sandiford <richard.sandiford@arm.com>
+
+ * tree-vect-loop-manip.c (vect_set_loop_masks_directly): Remove
+ vf parameter. Restore the previous iv step of nscalars_step,
+ but give it iv_type rather than compare_type. Tweak code order
+ to match the comments.
+ (vect_set_loop_condition_masked): Update accordingly.
+ * tree-vect-loop.c (vect_verify_full_masking): Use "unsigned int"
+ for iv_precision. Tweak comment formatting.
+
+2019-06-18 Iain Sandoe <iain@sandoe.co.uk>
+
+ * config/darwin.c: Strip trailing whitespace.
+
+2019-06-18 Iain Sandoe <iain@sandoe.co.uk>
+
+ * config/darwin.c (darwin_emit_unwind_label): New default to false.
+ (darwin_override_options): Set darwin_emit_unwind_label as needed.
+
+2019-06-18 Martin Jambor <mjambor@suse.cz>
+
+ PR ipa/90889
+ * ipa-cp.c (ignore_edge_p): Do not ignore edges when only the
+ caller does not have flag_ipa_cp set.
+
+2019-06-18 Alejandro Martinez <alejandro.martinezvicente@arm.com>
+
+ * config/aarch64/aarch64-sve.md (mask_fold_left_plus_<mode>): Renamed
+ from "*fold_left_plus_<mode>", updated operands order.
+ * doc/md.texi (mask_fold_left_plus_@var{m}): Documented new optab.
+ * internal-fn.c (mask_fold_left_direct): New define.
+ (expand_mask_fold_left_optab_fn): Likewise.
+ (direct_mask_fold_left_optab_supported_p): Likewise.
+ * internal-fn.def (MASK_FOLD_LEFT_PLUS): New internal function.
+ * optabs.def (mask_fold_left_plus_optab): New optab.
+ * tree-vect-loop.c (mask_fold_left_plus_optab): New function to get a
+ masked internal_fn for a reduction ifn.
+ (vectorize_fold_left_reduction): Add support for masking reductions.
+
+2019-06-18 Kewen Lin <linkw@gcc.gnu.org>
+
+ PR middle-end/80791
+ * target.def (predict_doloop_p): New hook.
+ * targhooks.h (default_predict_doloop_p): New declaration.
+ * targhooks.c (default_predict_doloop_p): New function.
+ * doc/tm.texi.in (TARGET_PREDICT_DOLOOP_P): New hook.
+ * doc/tm.texi: Regenerate.
+ * config/rs6000/rs6000.c (rs6000_predict_doloop_p): New function.
+ (TARGET_PREDICT_DOLOOP_P): New macro.
+ * tree-ssa-loop-ivopts.c (generic_predict_doloop_p): New function.
+
+2019-06-17 Jakub Jelinek <jakub@redhat.com>
+
+ * omp-low.c (struct omp_context): Add scan_inclusive field.
+ (scan_omp_1_stmt) <case GIMPLE_OMP_SCAN>: Set ctx->scan_inclusive
+ if inclusive scan.
+ (struct omplow_simd_context): Add lastlane member.
+ (lower_rec_simd_input_clauses): Add rvar argument, handle inscan
+ reductions. Build 2 or 3 argument .GOMP_SIMD_LANE calls rather than
+ 1 or 2 argument.
+ (lower_rec_input_clauses): Handle inscan reductions in simd contexts.
+ (lower_lastprivate_clauses): Set TREE_THIS_NOTRAP on the ARRAY_REF.
+ (lower_omp_scan): New function.
+ (lower_omp_1) <case GIMPLE_OMP_SCAN>: Use lower_omp_scan.
+ * tree-ssa-dce.c (eliminate_unnecessary_stmts): For IFN_GOMP_SIMD_LANE
+ check 3rd argument if present rather than 2nd.
+ * tree-vectorizer.h (struct _loop_vec_info): Add scan_map member.
+ (struct _stmt_vec_info): Change simd_lane_access_p from bool into
+ 2-bit bitfield.
+ * tree-vect-loop.c (_loop_vec_info::_loop_vec_info): Initialize
+ scan_map. For IFN_GOMP_SIMD_LANE check 3rd argument if present rather
+ than 2nd.
+ (_loop_vec_info::~_loop_vec_info): Delete scan_map.
+ * tree-vect-data-refs.c (vect_analyze_data_ref_accesses): Allow two
+ different STMT_VINFO_SIMD_LANE_ACCESS_P refs if they have the same
+ init.
+ (vect_find_stmt_data_reference): Encode in ->aux the 2nd
+ IFN_GOMP_SIMD_LANE argument.
+ (vect_analyze_data_refs): Set STMT_VINFO_SIMD_LANE_ACCESS_P from the
+ encoded ->aux value.
+ * tree-vect-stmts.c: Include attribs.h.
+ (vectorizable_call): Adjust comment about IFN_GOMP_SIMD_LANE.
+ (scan_operand_equal_p, check_scan_store, vectorizable_scan_store): New
+ functions.
+ (vectorizable_load): For STMT_VINFO_SIMD_LANE_ACCESS_P tests use != 0.
+ (vectorizable_store): Handle STMT_VINFO_SIMD_LANE_ACCESS_P > 1.
+
+2019-06-17 Uroš Bizjak <ubizjak@gmail.com>
+
+ PR target/62055
+ * config/i386/i386.md (*nabstf2_1): New insn pattern.
+ (*nabs<mode>2_1): Ditto.
+ (nabs sse-reg splitter): New splitter.
+ * config/i386/sse.md (*nabs<mode>2): New insn_and_split pattern.
+
+2019-06-17 Jan Hubicka <hubicka@ucw.cz>
+
+ PR bootstrap/90873.
+ * tree-ssa-alias.c (indirect_ref_may_alias_decl_p): Fix
+ TMR index check.
+
+2019-06-17 Tom de Vries <tdevries@suse.de>
+
+ * config/nvptx/nvptx-protos.h (gen_set_softstack_insn): Declare.
+ * config/nvptx/nvptx.c (gen_set_softstack_insn): New function.
+ * config/nvptx/nvptx.md (define_insn "set_softstack_insn"): Rename to
+ ...
+ (define_insn "set_softstack_<mode>"): ... this. Use P iterator on
+ match_operand 0.
+ (define_insn "omp_simt_enter_insn"): Rename to ...
+ (define_insn "omp_simt_enter_<mode>"): ... this. Use P iterator on
+ match_operand 0, 1 and 2, as well as the unspec_volatile result.
+ (define_expand "omp_simt_enter): Use gen_omp_simt_enter_di and
+ gen_omp_simt_enter_si.
+ (define_expand "omp_simt_exit"): New.
+ (define_insn "omp_simt_exit"): Rename to ...
+ (define_insn "omp_simt_exit_<mode>"): ... this. Use P iterator on
+ match_operand 0.
+
+2019-06-17 Matthew Green <mrg@eterna.com.au>
+ Maya Rashish <coypu@sdf.org>
+
+ * config.gcc (aarch64*-*-netbsd*): New target.
+ * config/aarch64/aarch64-netbsd.h: New file.
+ * config/aarch64/t-aarch64-netbsd: Likewise.
+
+2019-06-17 Jan Hubicka <hubicka@ucw.cz>
+
+ * tree-ssa-alias.c (aliasing_component_refs_p): Consider only
+ the access path from base to first VIEW_CONVERT_EXPR or
+ BIT_FIELD_REF.
+
+2019-06-17 Jan Hubicka <hubicka@ucw.cz>
+
+ * tree-ssa-alias.c (nonoverlapping_component_refs_p): Also truncate
+ access path on BIT_FIELD_REFs.
+
+2019-06-17 Martin Liska <mliska@suse.cz>
+
+ PR ipa/90874
+ * ipa-utils.h (odr_type_p): Remove dead code.
+
+2019-06-17 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE>
+
+ * configure.ac (ld_vers) <*-*-solaris2*>: Remove support for
+ alternative Solaris 11.4 format.
+ * configure: Regenerate.
+
+2019-06-17 Tom de Vries <tdevries@suse.de>
+
+ * config/nvptx/nvptx.md (define_insn "call_insn"): Rename to ...
+ (define_insn "call_insn_<mode>"): ... this. Use P iterator on
+ match_operand 0.
+ (define_insn "call_value_insn"): Rename to ...
+ (define_insn "call_value_insn_<mode>"): this. Use P iterator on
+ match_operand 0.
+ (define_insn "nvptx_red_partition"): Set unspec_volatile result mode to
+ DI.
+
+2019-06-16 John David Anglin <danglin@gcc.gnu.org>
+
+ PR middle-end/64242
+ * config/pa/pa.md (nonlocal_goto): Restore frame pointer last. Add
+ frame clobbers and schedule block.
+ (builtin_longjmp): Likewise.
+
+2019-06-16 Jozef Lawrynowicz <jozef.l@mittosystems.com>
+
+ * config/msp430/msp430.c (msp430_expand_helper): Setup arguments which
+ describe how to perform MSPABI compliant 64-bit shift.
+ * config/msp430/msp430.md (ashldi3): New define_expand.
+ (ashrdi3): New define_expand.
+ (lshrdi3): New define_expand.
+
+2019-06-16 Jozef Lawrynowicz <jozef.l@mittosystems.com>
+
+ * doc/sourcebuild.texi: Document new effective target keyword
+ longlong64.
+
+2019-06-16 Jan Hubicka <hubicka@ucw.cz>
+
+ * tree-ssa-alias.c (indirect_ref_may_alias_decl_p,
+ indirect_refs_may_alias_p): Revert accidental commits.
+
+ * tree-ssa-alias.c (aliasing_component_refs_p): Watch for arrays
+ at the end of structures.
+
+2019-06-16 Iain Sandoe <iain@sandoe.co.uk>
+
+ * config/darwin.c (machopic_indirect_call_target): Use renamed
+ darwin_picsymbol_stubs to decide on output.
+ (darwin_override_options): Handle darwin_picsymbol_stubs.
+ * config/darwin.h (MIN_LD64_OMIT_STUBS): New.
+ (LD64_VERSION): Revise default.
+ * config/darwin.opt: (mpic-symbol-stubs): New option.
+ (darwin_picsymbol_stubs): New variable.
+ * config/i386/darwin.h (TARGET_MACHO_BRANCH_ISLANDS):
+ rename to TARGET_MACHO_PICSYM_STUBS.
+ * config/i386/i386.c (output_pic_addr_const): Likewise.
+ * config/i386/i386.h Likewise.
+ * config/rs6000/darwin.h: Likewise.
+ * config/rs6000/rs6000.c (rs6000_call_darwin_1): Use renamed
+ darwin_picsymbol_stubs.
+
+2019-06-16 Iain Sandoe <iain@sandoe.co.uk>
+
+ * config/darwin.opt (prebind, noprebind, seglinkedit,
+ noseglinkedit): Add RejectNegative.
+
+2019-06-16 Jan Hubicka <hubicka@ucw.cz>
+
+ * tree-ssa-alias.c (nonoverlapping_component_refs_p): Fix pasto
+ in my previous patch.
+
+2019-06-16 Tom de Vries <tdevries@suse.de>
+
+ PR tree-optimization/89376
+ * tree-parloops.c (oacc_entry_exit_ok_1): Handle red == NULL.
+
+2019-06-15 Maya Rashish <coypu@sdf.org>
+
+ * doc/invoke.texi (Spec Files): Update location of the
+ Fortran spec file.
+
+2019-06-15 Gerald Pfeifer <gerald@pfeifer.com>
+
+ * doc/extend.texi (Common Function Attributes): Clarify
+ no_sanitize. Fix grammar.
+
+2019-06-15 Jan Hubicka <hubicka@ucw.cz>
+
+ * tree-ssa-alias.c (alias_stats): Add
+ nonoverlapping_component_refs_p_may_alias,
+ nonoverlapping_component_refs_p_no_alias,
+ nonoverlapping_component_refs_of_decl_p_may_alias,
+ nonoverlapping_component_refs_of_decl_p_no_alias.
+ (dump_alias_stats): Dump them.
+ (nonoverlapping_component_refs_of_decl_p): Add stats.
+ (nonoverlapping_component_refs_p): Add stats; do not stop on first
+ ARRAY_REF.
+
+2019-06-15 Uroš Bizjak <ubizjak@gmail.com>
+
+ * config/i386/i386.md (and<mode>3): Generate zero-extends for
+ TARGET_ZERO_EXTEND_WITH_AND && optimize_function_for_speed_p (cfun))
+ only.
+ (*anddi3_doubleword): Split before reload. Merge with
+ anddi->zext pre-reload splitter.
+ (*andndi3_doubleword): Split before reload.
+ (*<code>di3_doubleword): Ditto.
+ (*one_cmpldi2_doubleword): Ditto.
+
+2019-06-15 Jakub Jelinek <jakub@redhat.com>
+
+ PR middle-end/90779
+ * gimplify.c: Include omp-offload.h and context.h.
+ (gimplify_bind_expr): Add "omp declare target" attributes
+ to static block scope variables inside of target region or target
+ functions.
+
+2019-06-15 Tom de Vries <tdevries@suse.de>
+
+ PR tree-optimization/90009
+ * tree-ssa-threadbackward.c (thread_jumps::profitable_jump_thread_path):
+ Return NULL if bb contains IFN_UNIQUE.
+
+2019-06-14 Segher Boessenkool <segher@kernel.crashing.org>
+
+ * config/rs6000/rs6000.md (CCEITHER): New define_mode_iterator.
+ (un): New define_mode_attr.
+ (isel_signed_<mode>, isel_unsigned_<mode>): Delete, merge into ...
+ (isel_<un>signed_<GPR:mode>): ... this. New define_insn.
+ (isel_reversed_signed_<mode>, isel_reversed_unsigned_<mode>): Delete,
+ merge into ...
+ (isel_reversed_<un>signed_<GPR:mode>): ... this. New define_insn.
+
+2019-06-14 Iain Sandoe <iain@sandoe.co.uk>
+
+ * config/darwin.opt: Add RejectNegative where needed, reorder
+ and add minimal functional descriptions.
+
+2019-06-14 H.J. Lu <hongjiu.lu@intel.com>
+
+ PR rtl-optimization/90765
+ * calls.c (update_stack_alignment_for_call): New function.
+ (expand_call): Call update_stack_alignment_for_call when
+ outgoing parameter is passed in the stack.
+ (emit_library_call_value_1): Likewise.
+ * function.c (locate_and_pad_parm): Don't update
+ stack_alignment_needed and preferred_stack_boundary.
+
+2019-06-14 H.J. Lu <hongjiu.lu@intel.com>
+
+ PR target/90877
+ * config/i386/i386-features.c
+ (dimode_scalar_chain::compute_convert_gain): Replace
+ mmxsse_to_integer with sse_to_integer.
+ * config/i386/i386.c (ix86_register_move_cost): Verify that
+ moves between MMX and non-MMX units require secondary memory.
+ Correct costs of moves between SSE and integer units.
+ * config/i386/i386.h (processor_costs): Rename cost of moving
+ SSE register to integer to sse_to_integer. Rename cost of
+
+2019-06-14 Matt Thomas <matt@3am-software.com>
+ Matthew Green <mrg@eterna.com.au>
+ Nick Hudson <skrll@netbsd.org>
+ Maya Rashish <coypu@sdf.org>
+ Richard Earnshaw <rearnsha@arm.com>
+
+ * config.gcc (arm*-*-netbsdelf*) Add support for EABI configuration.
+ * config.host (arm*-*-netbsd*): Use driver-arm.o on native NetBSD.
+ * config/arm/netbsd-eabi.h: New file.
+ * config/arm/netbsd-elf.h (TARGET_OS_CPP_BUILTINS): Undefine before
+ redefining.
+ (SUBTARGET_EXTRA_ASM_SPEC): Don't pass -matpcs to the assembler.
+ * config/netbsd-elf.h (NETBSD_LINK_LD_ELF_SO_SPEC): New define.
+ (NETBSD_SUBTARGET_EXTRA_SPECS): New define.
+ (SUBTARGET_EXTRA_SPECS): Define to NETBSD_SUBTARGET_EXTRA_SPECS.
+
+2019-06-14 Richard Biener <rguenther@suse.de>
+
+ * tree-loop-distribution.c (classify_partition): Return
+ whether a reduction appeared in all partitions and do not
+ stop builtin detection because of this.
+ (distribute_loop): Sort a non-builtin partition last if
+ there's a reduction in all partitions and make sure the
+ partition prevailing as last is not a builtin.
+
+2019-06-14 Feng Xue <fxue@os.amperecomputing.com>
+
+ PR ipa/90401
+ * ipa-prop.c (add_to_agg_contents_list): New function.
+ (clobber_by_agg_contents_list_p): Likewise.
+ (extract_mem_content): Likewise.
+ (get_place_in_agg_contents_list): Delete.
+ (determine_known_aggregate_parts): Renamed from
+ determine_locally_known_aggregate_parts. New parameter
+ aa_walk_budget_p.
+
+2019-06-13 Martin Sebor <msebor@redhat.com>
+
+ PR tree-optimization/90662
+ * tree-ssa-strlen.c (get_stridx): Convert fold_build2 operands
+ to the same type.
+
+2019-06-13 Jan Hubicka <hubicka@ucw.cz>
+
+ PR bootstrap/90873
+ * tree-ssa-alias.c (indirect_ref_may_alias_decl_p): Also check that
+ dbase is not TARGET_MEM_REF.
+
+2019-06-13 Uroš Bizjak <ubizjak@gmail.com>
+
+ * config/i386/i386.md (SWIM1248s): Rename from SWIM1248x.
+ Update all uses.
+ (and<mode>3): Use gen_extend_insn instead of indirect functions.
+ Do not generate DImode extends for 32bit targets.
+ (and->zext post-reload splitter): Use gen_extend_insn
+ instead of indirect functions.
+ (anddi->zext pre-reload splitter): New.
+ (*zext<mode>_doubleword_and): Remove.
+ (*zext<mode>_doubleword): Ditto.
+ (*zextsi_doubleword): Dittto.
+
+2019-06-13 Uroš Bizjak <ubizjak@gmail.com>
+
+ * config/i386/i386-expand.c (ix86_expand_int_sse_cmp):
+ Use gen_sub3_insn instead of indirect function.
+ (ix86_expand_ashl_const): Use gen_add2_insn instead of
+ indirect function.
+ (ix86_adjust_counter): Ditto.
+
+2019-06-13 Jiufu Guo <guojiufu@linux.ibm.com>
+ Lijia He <helijia@linux.ibm.com>
+
+ PR tree-optimization/77820
+ * tree-ssa-threadedge.c
+ (edge_forwards_cmp_to_conditional_jump_through_empty_bb_p): New
+ function.
+ (thread_across_edge): Add call to
+ edge_forwards_cmp_to_conditional_jump_through_empty_bb_p.
+
+2019-06-13 Iain Sandoe <iain@sandoe.co.uk>
+
+ * config/darwin-driver.c (validate_macosx_version_min): New.
+ (darwin_default_min_version): Cleanup and validate supplied version.
+ (darwin_driver_init): Likewise and push cleaned version into opts.
+
+2019-06-13 Jan Hubicka <hubicka@ucw.cz>
+
+ PR tree-optimization/90869
+ * tree-ssa-alias.c (indirect_ref_may_alias_decl_p): Watch for view
+ converts in MEM_REF referencing decl rather than view converts
+ from decl type to MEM_REF type.
+
+2019-06-13 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/90856
+ * tree-sra.c (build_ref_for_model): Only use
+ build_reconstructed_reference when address-spaces are the same.
+
+2019-06-13 Jakub Jelinek <jakub@redhat.com>
+
+ * config/nvptx/nvptx.c (nvptx_sese_number, nvptx_sese_pseudo): Don't
+ wrap ei variable name in the declaration in ()s.
+ (nvptx_single): Actually use mode_label variable. Formatting fix.
+
+2019-06-13 Richard Biener <rguenther@suse.de>
+
+ * tree-vectorizer.h (vect_loop_vectorized_call): Declare.
+ * tree-vectorizer.c (vect_loop_vectorized_call): Export and
+ also return the condition stmt.
+ * tree-vect-loop-manip.c (vect_loop_versioning): Compute outermost
+ loop we can version and version that, reusing the loop version
+ created by if-conversion instead of versioning again.
+
+2019-06-13 Aldy Hernandez <aldyh@redhat.com>
+
+ * gimple-loop-versioning.cc (prune_loop_conditions): Use
+ may_contain_p.
+ * tree-vrp (value_range_base::may_contain_p): Call into
+ value_inside_range.
+ (value_inside_range): Make private inside value_range_base class.
+ Take min/max from *this.
+ (range_includes_p): Remove.
+ * tree-vrp.h (value_range_base): Add value_inside_range.
+ (range_includes_p): Remove.
+ (range_includes_zero_p): Call may_contain_p.
+ * vr-values.c (compare_range_with_value): Same.
+
+2019-06-13 Claudiu Zissulescu <claziss@synopsys.com>
+
+ * doc/extend.texi (ARC Function Attributes): Update info.
+
+2019-06-13 Feng Xue <fxue@os.amperecomputing.com>
+
+ PR tree-optimization/89713
+ * doc/invoke.texi (-ffinite-loops): Document new option.
+ * common.opt (-ffinite-loops): New option.
+ * tree-ssa-dce.c (mark_stmt_if_obviously_necessary): Mark
+ IFN_GOACC_LOOP calls as necessary.
+ * tree-ssa-loop-niter.c (finite_loop_p): Assume loop with an exit
+ is finite.
+ * omp-offload.c (oacc_xform_loop): Skip lowering if return value of
+ IFN_GOACC_LOOP call is not used.
+ * opts.c (default_options_table): Enable -ffinite-loops at -O2+.
+
+2019-06-13 Kugan Vivekanandarajah <kugan.vivekanandarajah@linaro.org>
+
+ PR target/88838
+ * tree-vect-loop-manip.c (vect_set_loop_masks_directly): If the
+ compare_type is not with Pmode size, we will create an IV with
+ Pmode size with truncated use (i.e. converted to the correct type).
+ * tree-vect-loop.c (vect_verify_full_masking): Find IV type.
+ (vect_iv_limit_for_full_masking): New. Factored out of
+ vect_set_loop_condition_masked.
+ * tree-vectorizer.h (LOOP_VINFO_MASK_IV_TYPE): New.
+ (vect_iv_limit_for_full_masking): Declare.
+
+2019-06-13 Kugan Vivekanandarajah <kugan.vivekanandarajah@linaro.org>
+
+ PR target/88834
+ * tree-ssa-loop-ivopts.c (get_mem_type_for_internal_fn): Handle
+ IFN_MASK_LOAD_LANES and IFN_MASK_STORE_LANES.
+ (get_alias_ptr_type_for_ptr_address): Likewise.
+ (add_iv_candidate_for_use): Add scaled index candidate if useful.
+ * tree-ssa-address.c (preferred_mem_scale_factor): New.
+ * config/aarch64/aarch64.c (aarch64_classify_address): Relax
+ allow_reg_index_p.
+
+2019-06-13 Kugan Vivekanandarajah <kugan.vivekanandarajah@linaro.org>
+
+ * config/aarch64/iterators.md (ADDSUB): Fix typo in comment.
+
+2019-06-12 Dimitar Dimitrov <dimitar@dinux.eu>
+
+ * common/config/pru/pru-common.c: New file.
+ * config.gcc: Add PRU target.
+ * config/pru/alu-zext.md: New file.
+ * config/pru/constraints.md: New file.
+ * config/pru/predicates.md: New file.
+ * config/pru/pru-opts.h: New file.
+ * config/pru/pru-passes.c: New file.
+ * config/pru/pru-pragma.c: New file.
+ * config/pru/pru-protos.h: New file.
+ * config/pru/pru.c: New file.
+ * config/pru/pru.h: New file.
+ * config/pru/pru.md: New file.
+ * config/pru/pru.opt: New file.
+ * config/pru/t-pru: New file.
+ * doc/extend.texi: Document PRU pragmas.
+ * doc/invoke.texi: Document PRU-specific options.
+ * doc/md.texi: Document PRU asm constraints.
+
+2019-06-12 Martin Sebor <msebor@redhat.com>
+
+ PR middle-end/90676
+ * tree-pretty-print.c (dump_mem_ref): New function. Include
+ MEM_REF type in output when different size than operand.
+ (dump_generic_node): Move code to dump_mem_ref and call it.
+
+2019-06-12 Martin Sebor <msebor@redhat.com>
+
+ PR tree-optimization/90662
+ * tree-ssa-strlen.c (get_stridx): Handle simple VLAs and pointers
+ to arrays.
+
+2019-06-12 Tom de Vries <tdevries@suse.de>
+
+ PR tree-optimization/90009
+ * config/nvptx/nvptx.c (nvptx_find_par): Assert fork has at most join.
+
+2019-06-12 Martin Liska <mliska@suse.cz>
+
+ * ggc-common.c (ggc_prune_overhead_list): Do not sanitize
+ the created map.
+ * hash-map.h: Add sanitize_eq_and_hash into ::hash_map.
+ * mem-stats.h (mem_alloc_description::mem_alloc_description):
+ Do not sanitize created maps.
+
+2019-06-12 Aldy Hernandez <aldyh@redhat.com>
+
+ * gimple-ssa-evrp.c (evrp_dom_walker::before_dom_children): Use
+ value_range::singleton_p.
+ * tree-vrp.c (value_range_constant_singleton): Remove.
+ * tree-vrp.h (value_range_constant_singleton): Remove.
+ * vr-values.c (vr_values::singleton): Use
+ value_range::singleton_p.
+
+2019-06-12 Jakub Jelinek <jakub@redhat.com>
+
+ PR target/90811
+ * cfgexpand.c (align_local_variable): Add really_expand argument,
+ don't SET_DECL_ALIGN if it is false.
+ (add_stack_var): Add really_expand argument, pass it through to
+ align_local_variable.
+ (expand_one_stack_var_1): Pass true as really_expand to
+ align_local_variable.
+ (expand_one_ssa_partition): Pass true as really_expand to
+ add_stack_var.
+ (expand_one_var): Pass really_expand through to add_stack_var.
+
+2019-06-12 Przemyslaw Wirkus <przemyslaw.wirkus@arm.com>
+
+ * config/arm/iterators.md (VABAL): New int iterator.
+ * config/arm/neon.md (<sup>sadv16qi): New define_expand.
+ * config/arm/unspecs.md ("unspec"): Define UNSPEC_VABAL_S, UNSPEC_VABAL_U
+ values.
+
+2019-06-12 Martin Liska <mliska@suse.cz>
+
+ * value-prof.c (stream_out_histogram_value): Only first value
+ can't be negative.
+
+2019-06-12 Jakub Jelinek <jakub@redhat.com>
+
+ PR c/90760
+ * symtab.c (symtab_node::set_section): Allow being called on aliases
+ as long as they aren't analyzed yet.
+
+2019-06-11 Faraz Shahbazker <fshahbazker@wavecomp.com>
+
+ * config/mips/mips.c (mips_final_postscan_insn): Modify call
+ to `mips_set_text_contents_type' to indicate whether a
+ non-debug insn follows.
+
+2019-06-11 Michael Meissner <meissner@linux.ibm.com>
+
+ * config/rs6000/rs6000-cpus.def (ISA_FUTURE_MASKS_SERVER): Delete
+ enabling -mpcrel by default.
+ * config/rs6000/rs6000.c (rs6000_option_override_internal): Update
+ test for -mpcrel and/or -mprefixed-addr needing -mcpu=future, so
+ that the test against -mcpu=future is done first. Then test if
+ -mprefixed-addr is on for -mpcrel.
+ (rs6000_disable_incompatible_switches): Add -mcpu=future support.
+
+2019-06-11 Jakub Jelinek <jakub@redhat.com>
+
+ PR target/90811
+ * config/nvptx/nvptx.c (nvptx_output_softstack_switch): Use and.b%d
+ instead of and.u%d.
+
+2019-06-11 Marc Glisse <marc.glisse@inria.fr>
+
+ * match.pd (X/[ex]4<Y/[ex]4): Handle conversions.
+
+2019-06-11 Matthew Beliveau <mbelivea@redhat.com>
+
+ PR c++/90449 - add -Winaccessible-base option.
+ * doc/invoke.texi (Winaccessible-base): Document.
+
+2019-06-11 Marc Glisse <marc.glisse@inria.fr>
+
+ PR tree-optimization/62041
+ * fold-const.c (fold_real_zero_addition_p): Handle vectors.
+
+2019-06-11 Jason Merrill <jason@redhat.com>
+
+ * gdbhooks.py (TreePrinter.to_string): Recognize ggc_free'd memory.
+ * tree.c (get_tree_code_name): Likewise.
+ * print-tree.c (print_node): Only briefly print a node with an
+ invalid code.
+
+2019-06-11 Jakub Jelinek <jakub@redhat.com>
+
+ PR bootstrap/90819
+ * trans-mem.c (tm_memopt_compute_available): Add assertion
+ that blocks is not empty. Formatting fix.
+
+2019-06-11 Martin Liska <mliska@suse.cz>
+
+ PR c++/87847
+ * hash-table.h: Extend create_gcc, add one parameter
+ that is passed into hash_table::hash_table.
+
+2019-06-10 Uroš Bizjak <ubizjak@gmail.com>
+
+ * config/i386/i386-protos.h (ix86_split_fp_absneg_operator):
+ New prototype.
+ * config/i386/i386-expand.c (ix86_expand_fp_absneg_operator):
+ Emit clobber also for non-sse operations.
+ (ix86_split_fp_absneg_operator): New function.
+ * config/i386/i386.md (SSEMODEF): New mode iterator.
+ (ssevecmodef): New mode attribute.
+ (<code>tf2): Use absneg code iterator.
+ (*<code>tf2_1): Rename from *absnegtf3_sse. Use absneg code iterator.
+ Add three-operand AVX alternatives.
+ (*<code><mode>2_i387_1): Rename from *absnegxf2_i387.
+ Use absneg code iterator and X87MODEF mode iterator.
+ (absneg fp_reg non-sse splitter): Call absneg code iterator
+ and X87MODEF mode iterator.
+ (absneg general_reg non-sse splitter): Use absneg code iterator
+ and X87MODEF mode iterator. Use ix86_split_fp_absneg_operator.
+ (*<code><mode>2_1): Rename from *absneg<mode>2. Use absneg
+ code iterator. Add three-operand AVX alternative.
+ (absneg sse_reg splitter): Use absneg code iterator
+ and SSEMODEF mode iterator. Handle AVX operands.
+ (absneg fp_reg splitter): Use absneg code iterator
+ and MODEF mode iterator.
+ (absneg general_reg splitter): Merge splitters using MODEF mode
+ iterator. Use absneg code iterator. Call
+ ix86_split_fp_absneg_operator.
+ (*<code><mode>2_i387): Rename from *<code><mode>2_1.
+ Do not enable for non-sse modes before reload.
+ (CSGNMODE): Remove.
+ (CSGNVMODE): Ditto.
+ (copysing<mode>3): Use SSEMODEF instead of CSGNMODE and
+ ssevecmodef mode attribute instaed of CSGNVMODE.
+ (copysign<mode>3_const): Ditto.
+ (copysign<mode>3_var): Ditto.
+ * config/i386/i386.md (*<code><mode>2): Rename from *absneg<mode>2.
+ Use absneg code iterator. Simplify code using std::swap.
+ * config/i386/predicates.md (absneg_operator): Remove.
+
+2019-06-10 Martin Sebor <msebor@redhat.com>
+
+ * gimple-fold.c (get_range_strlen): Update comment that didn't
+ make it into r267503 or related commits.
+
+2019-06-10 Vladislav Ivanishin <vlad@ispras.ru>
+
+ * gcov-tool.c (merge_usage, rewrite_usage): Mark with
+ ATTRIBUTE_NORETURN thus making consistent with overlap_usage.
+
+2019-06-10 Jakub Jelinek <jakub@redhat.com>
+
+ * tree.def (OMP_SCAN): New tree code.
+ * tree-core.h (enum omp_clause_code): Add OMP_CLAUSE_INCLUSIVE and
+ OMP_CLAUSE_EXCLUSIVE.
+ * tree.h (OMP_CLAUSES): Use OMP_SCAN instead of OMP_TASKGROUP.
+ (OMP_SCAN_BODY, OMP_SCAN_CLAUSES): Define.
+ * tree.c (omp_clause_num_ops, omp_clause_code_name): Add entries for
+ OMP_CLAUSE_{IN,EX}CLUSIVE.
+ (walk_tree_1): Handle OMP_CLAUSE_{IN,EX}CLUSIVE.
+ * tree-nested.c (convert_nonlocal_reference_stmt,
+ convert_local_reference_stmt, convert_gimple_call): Handle
+ GIMPLE_OMP_SCAN.
+ * tree-pretty-print.c (dump_omp_clause): Handle
+ OMP_CLAUSE_{IN,EX}CLUSIVE.
+ (dump_generic_node): Handle OMP_SCAN.
+ * gimple.def (GIMPLE_OMP_SCAN): New gimple code.
+ * gimple.h (gomp_scan): New type.
+ (is_a_helper <gomp_scan *>::test,
+ is_a_helper <const gomp_scan *>::test): New templates.
+ (gimple_build_omp_scan): Declare.
+ (gimple_omp_scan_clauses, gimple_omp_scan_clauses_ptr,
+ gimple_omp_scan_set_clauses): New inline functions.
+ (CASE_GIMPLE_OMP): Add case GIMPLE_OMP_SCAN:.
+ * gimple.c (gimple_build_omp_scan): New function.
+ (gimple_copy): Handle GIMPLE_OMP_SCAN.
+ * gimple-walk.c (walk_gimple_op, walk_gimple_stmt): Likewise.
+ * gimple-pretty-print.c (dump_gimple_omp_block): Don't handle
+ GIMPLE_OMP_TASKGROUP.
+ (dump_gimple_omp_scan): New function.
+ (pp_gimple_stmt_1): Handle GIMPLE_OMP_SCAN.
+ * gimple-low.c (lower_stmt): Handle GIMPLE_OMP_SCAN.
+ * tree-inline.c (remap_gimple_stmt, estimate_num_insns): Likewise.
+ * gimplify.c (enum gimplify_omp_var_data): Add GOVD_REDUCTION_INSCAN.
+ (is_gimple_stmt): Handle OMP_SCAN.
+ (gimplify_scan_omp_clauses): Reject inscan reductions on constructs
+ other than OMP_FOR or OMP_SIMD. Handle OMP_CLAUSE_{IN,EX}CLUSIVE.
+ (gimplify_adjust_omp_clauses): Diagnose inscan reductions not
+ mentioned in nested #pragma omp scan. Handle
+ OMP_CLAUSE_{IN,EX}CLUSIVE.
+ (gimplify_expr): Handle OMP_SCAN.
+ * omp-low.c (check_omp_nesting_restrictions): For parent context,
+ look through GIMPLE_OMP_SCAN context. Allow #pragma omp scan in
+ simd constructs.
+ (scan_omp_1_stmt, lower_omp_1, diagnose_sb_1, diagnose_sb_2): Handle
+ GIMPLE_OMP_SCAN.
+
+2019-06-10 Martin Liska <mliska@suse.cz>
+
+ * ipa-cp.c (ignore_edge_p): New function.
+ (build_toporder_info): Use it.
+ * ipa-inline.c (ignore_edge_p): New function.
+ (inline_small_functions): Use it.
+ * ipa-pure-const.c (ignore_edge_for_nothrow):
+ Verify opt_for_fn for caller and callee.
+ (ignore_edge_for_pure_const): Likewise.
+ * ipa-reference.c (ignore_edge_p): Extend to check
+ for opt_for_fn.
+ * ipa-utils.c (searchc): Refactor.
+ * ipa-utils.h: Fix coding style.
+
+2019-06-10 Claudiu Zissulescu <claziss@synopsys.com>
+
+ * config/arc/arc.c (arc_rtx_costs): Update costs.
+
+2019-06-10 Claudiu Zissulescu <claziss@synopsys.com>
+
+ * config/arc/arc-protos.h (arc_check_ior_const): Declare.
+ (arc_split_ior): Likewise.
+ (arc_check_mov_const): Likewise.
+ (arc_split_mov_const): Likewise.
+ * config/arc/arc.c (arc_print_operand): Fix 'z' letter.
+ (arc_rtx_costs): Replace check Crr with Cax constraint.
+ (prepare_move_operands): Cleanup, remove unused code.
+ (arc_split_ior): New function.
+ (arc_check_ior_const): Likewise.
+ (arc_split_mov_const): Likewise.
+ (arc_check_mov_const): Likewise.
+ * config/arc/arc.md (movsi_insn): Restructure it, and convert it
+ in define_insn_and_split pattern.
+ (iorsi3): Likewise.
+ (mulsi3_v2): Add new matching variant.
+ (andsi3_i): Cleanup pattern.
+ (rotrsi3_cnt1): Update pattern.
+ (rotrsi3_cnt8): New pattern.
+ (ashlsi2_cnt8): Likewise.
+ (ashlsi2_cnt16): Likewise.
+ * config/arc/constraints.md (C0p): Update constraint.
+ (Crr): Remove it.
+ (C0x): New pattern.
+ (Cax): New pattern.
+
+2019-06-10 Martin Liska <mliska@suse.cz>
+
+ * ipa-icf.c (sem_item_optimizer::parse_nonsingleton_classes):
+ Update coding style.
+ (sem_item_optimizer::dump_cong_classes):
+ Print how many items are in a non-singular class. Improve
+ coding style.
+
+2019-06-10 Martin Liska <mliska@suse.cz>
+
+ * value-prof.c (dump_histogram_value): Change dump format.
+ (gimple_mod_subtract_transform): Remove legacy comment.
+
+2019-06-10 Martin Liska <mliska@suse.cz>
+
+ * value-prof.c (dump_histogram_value): Print histogram values
+ only if present.
+
+2019-06-10 Martin Liska <mliska@suse.cz>
+
+ * gcov-io.h (GCOV_DISK_SINGLE_VALUES): New.
+ (GCOV_SINGLE_VALUE_COUNTERS): Likewise.
+ * ipa-profile.c (ipa_profile_generate_summary):
+ Use get_most_common_single_value.
+ * tree-profile.c (gimple_init_gcov_profiler):
+ Instrument with __gcov_one_value_profiler_v2
+ and __gcov_indirect_call_profiler_v4.
+ * value-prof.c (dump_histogram_value):
+ Print all values for HIST_TYPE_SINGLE_VALUE.
+ (stream_out_histogram_value): Update assert for
+ N values.
+ (stream_in_histogram_value): Set number of
+ counters for HIST_TYPE_SINGLE_VALUE.
+ (get_most_common_single_value): New.
+ (gimple_divmod_fixed_value_transform):
+ Use get_most_common_single_value.
+ (gimple_ic_transform): Likewise.
+ (gimple_stringops_transform): Likewise.
+ (gimple_find_values_to_profile): Set number
+ of counters for HIST_TYPE_SINGLE_VALUE.
+ * value-prof.h (get_most_common_single_value):
+ New.
+
+2019-06-10 Martin Liska <mliska@suse.cz>
+
+ * hash-map.h: Pass default value to hash_table ctor.
+ * hash-table.h: Add default value to call of a ctor.
+
+2019-06-08 Jonathan Wakely <jwakely@redhat.com>
+
+ * doc/invoke.texi (C Dialect Options): Minor grammatical change.
+ (x86 Options): Replace all uses of "PCL_MUL" with "PCLMUL"
+
+2019-06-07 John David Anglin <danglin@gcc.gnu.orig>
+
+ PR target/90751
+ * config/pa/pa-linux.h (ASM_DECLARE_FUNCTION_NAME): Update comment.
+ Call pa_output_function_label.
+ (TARGET_ASM_FUNCTION_PROLOGUE): define.
+ * config/pa/pa-protos.h (pa_output_function_label): Declare.
+ * config/pa/pa.c (pa_output_function_prologue): Add ATTRIBUTE_UNUSED
+ to declaration.
+ (pa_linux_output_function_prologue): Declare.
+ (TARGET_ASM_FUNCTION_PROLOGUE): Delete define.
+ (pa_output_function_label): New.
+ (pa_output_function_prologue): Revise to use pa_output_function_label.
+ (pa_linux_output_function_prologue): New.
+ * config/pa/pa.h (TARGET_ASM_FUNCTION_PROLOGUE): Define.
+
+2019-06-07 Aldy Hernandez <aldyh@redhat.com>
+
+ * tree-vrp.h (value_range_base::intersect): New.
+ (value_range::intersect_helper): Move from here...
+ (value_range_base::intersect_helper): ...to here.
+ * tree-vrp.c (value_range::intersect_helper): Rename to...
+ (value_range_base::intersect_helper): ...this, and rewrite to
+ return a value instead of modifying THIS in place.
+ Also, move equivalence handling...
+ (value_range::intersect): ...here, while calling intersect_helper.
+ * gimple-fold.c (size_must_be_zero_p): Use value_range_base when
+ calling intersect.
+ * gimple-ssa-evrp-analyze.c (ecord_ranges_from_incoming_edge):
+ Same.
+ * vr-values.c (vrp_evaluate_conditional_warnv_with_ops): Same.
+
+2019-06-07 Jakub Jelinek <jakub@redhat.com>
+
+ * Makefile.in (genprogerr): Add condmd.
+ (genprog): Remove it here.
+
+2019-06-07 Andrew Stubbs <ams@codesourcery.com>
+
+ * doc/invoke.texi (AMD GCN Options): Add gfx906.
+
+2019-06-07 Richard Biener <rguenther@suse.de>
+
+ PR debug/90574
+ * tree-cfg.c (stmt_starts_bb_p): Split blocks at labels
+ that appear after user labels.
+
+2019-06-07 Martin Liska <mliska@suse.cz>
+
+ * cselib.c (cselib_init): Disable hash table
+ sanitization.
+ * hash-set.h: Pass new default argument to m_table.
+ * hash-table.c: Add global variable with hash table
+ sanitization limit.
+ * hash-table.h (Allocator>::hash_table): Add new argument
+ to ctor.
+ (hashtab_chk_error): New.
+ * params.def (PARAM_HASH_TABLE_VERIFICATION_LIMIT): New.
+ * toplev.c (process_options): Set hash_table_sanitize_eq_limit
+ from the PARAM_HASH_TABLE_VERIFICATION_LIMIT value.
+
+2019-06-07 Jan Hubicka <hubicka@ucw.cz>
+
+ * common.opt (flto-odr-type-merging): Ignore.
+ * invoke.texi (-flto-odr-type-merging): Remove.
+ * ipa-devirt.c (odr_vtable_hasher:odr_name_hasher): Remove.
+ (can_be_vtable_hashed_p): Remove.
+ (hash_odr_vtable): Remove.
+ (odr_vtable_hasher::hash): Remove.
+ (types_same_for_odr): Remove.
+ (types_odr_comparable): Remove.
+ (odr_vtable_hasher::equal): Remove.
+ (odr_vtable_hash_type, odr_vtable_hash): Remove.
+ (add_type_duplicate): Do not synchronize vtable and name hashtables.
+ (get_odr_type): Do not use vtable hash.
+ (dump_odr_type): Remove commented out code.
+ (build_type_inheritance_graph): Do not allocate vtable hash.
+ (rebuild_type_inheritance_graph): Do not delete vtable hash.
+ * ipa-utils.h (type_with_linkage_p): Drop vtable hash path.
+ (odr_type_p): Likewise.
+ * tree.c (need_assembler_name_p): Remove flag_lto_odr_type_mering
+ test.
+
+2019-06-07 Jan Hubicka <hubicka@ucw.cz>
+
+ * tree-ssa-alias.c (aliasing_component_refs_p): Do not give up
+ immediately after same_types_for_tbaa_p returns -1 and continue
+ looking for possible exact match; if matching types are arrays
+ watch for partial overlaps.
+ (indirect_ref_may_alias_decl_p): Watch for partial array overlaps.
+ (indirect_refs_may_alias_p): Do type based disambiguation first;
+ update comment.
+
+2019-06-07 Richard Sandiford <richard.sandiford@arm.com>
+
+ * fwprop.c (propagate_rtx): Fix call to paradoxical_subreg_p.
+
+2019-06-07 Martin Liska <mliska@suse.cz>
+
+ * doc/invoke.texi: Remove param.
+ * gcov-counter.def (GCOV_COUNTER_ICALL_TOPNV):
+ Remove.
+ * gcov-io.h (GCOV_ICALL_TOPN_VAL): Likewise.
+ (GCOV_ICALL_TOPN_NCOUNTS): Likewise.
+ * params.def (PARAM_INDIR_CALL_TOPN_PROFILE): Likewise.
+ * profile.c (instrument_values): Remove
+ HIST_TYPE_INDIR_CALL_TOPN.
+ * tree-profile.c (init_ic_make_global_vars):
+ Always build __gcov_indirect_call only.
+ (gimple_init_gcov_profiler): Remove usage
+ of PARAM_INDIR_CALL_TOPN_PROFILE.
+ (gimple_gen_ic_profiler): Likewise.
+ * value-prof.c (dump_histogram_value): Likewise.
+ (stream_in_histogram_value): Likewise.
+ (gimple_indirect_call_to_profile): Likewise.
+ (gimple_find_values_to_profile): Likewise.
+ * value-prof.h (enum hist_type): Likewise.
+
+2019-06-07 Martin Liska <mliska@suse.cz>
+
+ * tree-ssa-loop.c (get_lsm_tmp_name): Return at the end of the
+ function.
+
+2019-06-07 Martin Liska <mliska@suse.cz>
+
+ PR tree-optimization/78902
+ * builtin-attrs.def (ATTR_WARN_UNUSED_RESULT): New.
+ (ATTR_MALLOC_NOTHROW_LEAF_LIST): Remove.
+ (ATTR_WARN_UNUSED_RESULT_NOTHROW_LEAF_LIST): New.
+ (ATTR_MALLOC_WARN_UNUSED_RESULT_NOTHROW_LEAF_LIST): New.
+ (ATTR_ALLOC_SIZE_2_NOTHROW_LIST): Remove.
+ (ATTR_MALLOC_SIZE_1_NOTHROW_LEAF_LIST): Remove.
+ (ATTR_MALLOC_WARN_UNUSED_RESULT_NOTHROW_LIST): New.
+ (ATTR_ALLOC_WARN_UNUSED_RESULT_SIZE_2_NOTHROW_LIST): New.
+ (ATTR_MALLOC_WARN_UNUSED_RESULT_SIZE_1_NOTHROW_LEAF_LIST): New.
+ (ATTR_ALLOCA_SIZE_1_NOTHROW_LEAF_LIST): Remove.
+ (ATTR_ALLOCA_WARN_UNUSED_RESULT_SIZE_1_NOTHROW_LEAF_LIST): New.
+ (ATTR_MALLOC_SIZE_1_2_NOTHROW_LEAF_LIST): Remove.
+ (ATTR_MALLOC_WARN_UNUSED_RESULT_SIZE_1_2_NOTHROW_LEAF_LIST):
+ New.
+ (ATTR_ALLOC_SIZE_2_NOTHROW_LEAF_LIST): Remove.
+ (ATTR_ALLOC_WARN_UNUSED_RESULT_SIZE_2_NOTHROW_LEAF_LIST): New.
+ (ATTR_MALLOC_NOTHROW_NONNULL): Remove.
+ (ATTR_WARN_UNUSED_RESULT_NOTHROW_NONNULL): New.
+ (ATTR_MALLOC_WARN_UNUSED_RESULT_NOTHROW_NONNULL): New.
+ (ATTR_MALLOC_NOTHROW_NONNULL_LEAF): Remove.
+ (ATTR_WARN_UNUSED_RESULT_NOTHROW_NONNULL_LEAF): New.
+ (ATTR_MALLOC_WARN_UNUSED_RESULT_NOTHROW_NONNULL_LEAF): New.
+ * builtins.def (BUILT_IN_ALIGNED_ALLOC): Change to use
+ warn_unused_result attribute.
+ (BUILT_IN_STRDUP): Likewise.
+ (BUILT_IN_STRNDUP): Likewise.
+ (BUILT_IN_ALLOCA): Likewise.
+ (BUILT_IN_CALLOC): Likewise.
+ (BUILT_IN_MALLOC): Likewise.
+ (BUILT_IN_REALLOC): Likewise.
+
+2019-06-06 Jim Wilson <jimw@sifive.com>
+
+ PR target/89955
+ * config/riscv/riscv.h (STARTFILE_PREFIX_SPEC): Deleted.
+ * config/riscv/freebsd.h (STARTFILE_PREFIX_SPEC): Added.
+ * config/riscv/linux.h (STARTFILE_PREFIX_SPEC): Added.
+
+2019-06-06 Martin Sebor <msebor@redhat.com>
+
+ * tree-ssa-strlen.c (adjust_related_strinfos): Avoid trailing article.
+ (handle_builtin_malloc): Remove trailing spaces.
+ (handle_builtin_memset): Same.
+ (handle_builtin_memcmp): Same.
+ (compute_string_length): Same.
+ (determine_min_objsize): Same.
+ (handle_builtin_string_cmp): Same.
+ (handle_char_store): Same. Break up excessively long line.
+
+2019-06-06 Martin Jambor <mjambor@suse.cz>
+
+ * tree-sra.c (build_reconstructed_reference): Drop the alignment
+ check.
+
+2019-06-06 Martin Jambor <mjambor@suse.cz>
+
+ * tree-sra.c (struct access): New field grp_same_access_path.
+ (dump_access): Dump it.
+ (build_reconstructed_reference): New function.
+ (build_ref_for_model): Use it if possible.
+ (path_comparable_for_same_access): New function.
+ (same_access_path_p): Likewise.
+ (sort_and_splice_var_accesses): Set the new flag.
+ (analyze_access_subtree): Likewise.
+ (propagate_subaccesses_across_link): Propagate zero value of the new
+ flag down the access tree.
+
+2019-06-06 Andrew Stubbs <ams@codesourcery.com>
+
+ * config.gcc (amdgcn-*-*): Allow --with-arch=gfx906.
+ * config/gcn/gcn.opt (gpu_type): Add gfx906.
+ * config/gcn/t-gcn-hsa (MULTILIB_OPTIONS): Add gfx906 multilib.
+ (MULTILIB_DIRNAMES): Rename gcn5 to gfx900.
+ Add gfx906.
+
+2019-06-06 Kyrylo Tkachov <kyrylo.tkachov@arm.com>
+
+ PR tree-optimization/90332
+ * config/aarch64/aarch64.c (aarch64_expand_vector_init):
+ Handle VALS containing two vectors.
+ * config/aarch64/aarch64-simd.md (*aarch64_combinez<mode>): Rename
+ to...
+ (@aarch64_combinez<mode>): ... This.
+ (*aarch64_combinez_be<mode>): Rename to...
+ (@aarch64_combinez_be<mode>): ... This.
+ (vec_init<mode><Vhalf>): New define_expand.
+ * config/aarch64/iterators.md (Vhalf): Handle V8HF.
+
+2019-06-06 Jozef Lawrynowicz <jozef.l@mittosystems.com>
+
+ * config/msp430/msp430.md (ashlhi3): Use the const_variant of shift
+ library functions only when not optimizing for size.
+ (ashlsi3): Likewise.
+ (ashrhi3): Likewise.
+ (ashrsi3): Likewise.
+ (lshrhi3): Likewise.
+ (lshrsi3): Likewise.
+
+2019-06-06 Andreas Krebbel <krebbel@linux.ibm.com>
+
+ PR rtl-optimization/88751
+ * ira.c (ira): Use the number of the actually referenced registers
+ when calculating the threshold.
+
+2019-06-06 Jakub Jelinek <jakub@redhat.com>
+
+ * configure: Regenerate.
+
+2019-06-06 Jozef Lawrynowicz <jozef.l@mittosystems.com>
+
+ * config/msp430/msp430.md (ashlhi3): Force shift src operand into a
+ register if it is in memory, so the shift can be emulated with a rotate
+ instruction.
+ (ashrhi3): Likewise.
+ (lshrhi3): Likewise.
+
+2019-06-06 Martin Liska <mliska@suse.cz>
+
+ PR tree-optimization/87954
+ * match.pd: Simplify mult where both arguments are 0 or 1.
+
+2019-06-06 Richard Biener <rguenther@suse.de>
+
+ * vr-values.c (vr_values::extract_range_from_ssa_name): Do not
+ put equivalences on UNDEFINED ranges.
+ * gimple-ssa-evrp.c (evrp_dom_walker::before_dom_children):
+ Make sure to drop defs of stmts added during simplification
+ to VARYING.
+
+2019-06-06 Richard Biener <rguenther@suse.de>
+
+ * tree-ssa-structalias.c: Include tree-cfg.h.
+ (make_heapvar): Do not make heap vars artificial.
+ (find_func_aliases_for_builtin_call): Handle stack allocation
+ functions.
+ (find_func_aliases): Delay processing of simple enough returns
+ in non-IPA mode.
+ (set_uids_in_ptset): Adjust.
+ (find_what_var_points_to): Likewise.
+ (solve_constraints): Do not dump points-to sets here.
+ (compute_points_to_sets): Post-process return statements,
+ amending the escaped solution. Dump points-to sets afterwards.
+ (ipa_pta_execute): Dump points-to sets.
+
+2019-06-06 Martin Liska <mliska@suse.cz>
+
+ PR web/87933
+ * doc/install.texi: Fix HTML headers and
+ titles for 'Installing GCC' pages.
+
+2019-06-06 Martin Liska <mliska@suse.cz>
+
+ * ipa-icf-gimple.h (dump_message_1): Remove.
+ (dump_message): Likewise.
+ (return_false_with_message_1): Print also file.
+ (return_false_with_msg): Likewise.
+ (return_with_result): Likewise.
+ (return_with_debug): Likewise.
+ * ipa-icf.c (sem_function::equals_private): Remove call
+ to dump_message.
+
+2019-06-05 Hongtao Liu <hongtao.liu@intel.com>
+
+ * config/i386/sse.md (define_mode_suffix vecmemsuffix): New.
+ (define_insn "avx512dq_fpclass<mode><mask_scalar_merge_name>"): Enable
+ memory operand for it.
+ (define_insn "avx512dq_vmfpclass<mode><mask_scalar_merge_name>"): Ditto.
+
+2019-06-05 Martin Sebor <msebor@redhat.com>
+
+ * config/i386/i386-features.c (ix86_get_function_versions_dispatcher):
+ Adjust quoting and hyphenation.
+ * convert.c (convert_to_real_1): Same.
+ * gcc.c (driver_wrong_lang_callback): Same.
+ (driver::handle_unrecognized_options): Same.
+ * gimple-ssa-nonnull-compare.c (do_warn_nonnull_compare): Same.
+ * opts-common.c (cmdline_handle_error): Same.
+ (read_cmdline_option): Same.
+ * opts-global.c (complain_wrong_lang): Same.
+ (print_ignored_options): Same.
+ (handle_common_deferred_options): Same.
+ * pretty-print.h: Same.
+ * print-rtl.c (debug_bb_n_slim): Same.
+ * sched-rgn.c (make_pass_sched_fusion): Same.
+ * tree-cfg.c (verify_gimple_assign_unary): Same.
+ (verify_gimple_label): Same.
+ * tree-ssa-operands.c (verify_ssa_operands): Same.
+ * varasm.c (do_assemble_alias): Same.
+ (assemble_alias): Same.
+
+2019-06-05 Richard Henderson <rth@twiddle.net>
+
+ * config/alpha/alpha.c (direct_return): Move down after
+ struct machine_function definition; use saved frame_size;
+ return bool.
+ (struct machine_function): Add sa_mask, sa_size, frame_size.
+ (alpha_sa_mask, alpha_sa_size, compute_frame_size): Merge into ...
+ (alpha_compute_frame_layout): ... new function.
+ (TARGET_COMPUTE_FRAME_LAYOUT): New.
+ (alpha_initial_elimination_offset): Use saved sa_size.
+ (alpha_vms_initial_elimination_offset): Likewise.
+ (alpha_vms_can_eliminate): Remove alpha_sa_size call.
+ (alpha_expand_prologue): Use saved frame data. Merge integer
+ and fp register save loops.
+ (alpha_expand_epilogue): Likewise.
+ (alpha_start_function): Use saved frame data.
+ * config/alpha/alpha-protos.h (direct_return): Update.
+ (alpha_sa_size): Remove.
+
+2019-06-05 Eric Botcazou <ebotcazou@adacore.com>
+
+ * fold-const.c (extract_muldiv_1) <PLUS_EXPR>: Do not distribute a
+ multiplication by a power-of-two value.
+ (fold_plusminus_mult_expr): Use pow2p_hwi to spot a power-of-two value
+ and turn the modulo operation into a masking operation.
+
+2019-06-05 Jakub Jelinek <jakub@redhat.com>
+
+ PR debug/90733
+ * var-tracking.c (vt_expand_loc_callback): Don't create raw subregs
+ with VOIDmode inner operands.
+
+2019-06-05 Richard Biener <rguenther@suse.de>
+
+ PR middle-end/90726
+ * tree-ssa-loop-niter.c (expand_simple_operations): Do not
+ turn an expression graph into a tree.
+
+2019-06-05 Jakub Jelinek <jakub@redhat.com>
+
+ * omp-expand.c (struct omp_region): Add has_lastprivate_conditional
+ member.
+ (expand_parallel_call): If region->inner->has_lastprivate_conditional,
+ treat it like explicit monotonic schedule modifier.
+ (expand_omp_for): Initialize has_lastprivate_conditional.
+ If fd.lastprivate_conditional != 0, treat it like explicit monotonic
+ schedule modifier.
+
+ * omp-low.c (lower_rec_input_clauses): For lastprivate conditional
+ references, lookup in in hash map MEM_REF operand instead of the
+ MEM_REF itself.
+ (lower_omp_1): When looking for lastprivate conditional assignments,
+ handle MEM_REFs with REFERENCE_TYPE operands.
+
+ * omp-low.c (lower_rec_input_clauses): Force max_vf if is_simd and
+ on privatization clauses OMP_CLAUSE_DECL is privatized by reference
+ and references a VLA. Handle references to non-VLAs if is_simd
+ all privatization clauses like reductions.
+ (lower_rec_input_clauses) <case do_private, case do_firstprivate>:
+ If omp_is_reference, use always omp simd arrays and set
+ DECL_VALUE_EXPR in that case, if lower_rec_simd_input_clauses
+ fails, emit reference initialization.
+
+2019-06-05 Hongtao Liu <hongtao.liu@intel.com>
+
+ PR target/89803
+ * config/i386/avx512dqintrin.h (_mm_mask_fpclass_ss_mask,
+ _mm_mask_fpclass_sd_mask): New intrinsics.
+ (_mm_fpclass_ss_mask, _mm_fpclass_sd_mask): Modified, use new builtins.
+ * config/i386/i386-builtin.def
+ (__builtin_ia32_fpclassss_mask, __builtin_ia32_fpclasssd_mask):
+ New builtins.
+ (__builtin_ia32_fpclassss, __builtin_ia32_fpclasssd): Deleted.
+ * config/i386/i386-builtin-types.def (DEF_FUNCTION_TYPE (QI, V2DF, INT),
+ DEF_FUNCTION_TYPE (QI, V4SF, INT)): Deleted.
+ * config/i386/i386-expand.c (case QI_FTYPE_V4SF_INT,
+ case QI_FTYPE_V2SF_INT): Ditto.
+ * config/i386/sse.md
+ (define_insn "avx512dq_vmfpclass<mode><mask_scalar_merge_name>):
+ Extended to insnstructions with mask operands.
+
+2019-06-04 Segher Boessenkool <segher@kernel.crashing.org>
+
+ * config/rs6000/constraints.md (define_register_constraint "wp"):
+ Delete.
+ (define_register_constraint "wq"): Delete.
+ * config/rs6000/rs6000.c (rs6000_debug_reg_global): Adjust.
+ (rs6000_init_hard_regno_mode_ok): Adjust.
+ * config/rs6000/rs6000.h (enum r6000_reg_class_enum): Delete
+ RS6000_CONSTRAINT_wp and RS6000_CONSTRAINT_wq.
+ * config/rs6000/vsx.md (define_mode_attr VSr3): Delete.
+ (define_mode_attr VSa): Delete.
+ (define_mode_attr VSisa): New.
+ (rest of file): Adjust.
+ * doc/md.texi (Machine Constraints): Adjust.
+
+2019-06-04 Segher Boessenkool <segher@kernel.crashing.org>
+
+ * config/rs6000/rs6000.md (define_attr "isa"): Add p9kf and p9tf.
+ (define_attr "enabled"): Handle those new isa values.
+
+2019-06-04 Segher Boessenkool <segher@kernel.crashing.org>
+
+ * config/rs6000/vsx.md (define_mode_attr VSr4): Delete.
+ (define_mode_attr VSr5): Delete.
+ (define_mode_attr VStype_sqrt): Delete.
+ (define_mode_iterator VSX_SPDP): Delete.
+ (define_mode_attr VS_spdp_res): Delete.
+ (define_mode_attr VS_spdp_insn): Delete.
+ (define_mode_attr VS_spdp_type): Delete.
+ (*vsx_sqrt<mode>2): Adjust.
+ (vsx_<VS_spdp_insn>): Delete, split to...
+ (vsx_xscvdpsp): ... this. New. And...
+ (vsx_xvcvspdp): ... this. New. And...
+ (vsx_xvcvdpsp): ... this. New.
+
+2019-06-04 Segher Boessenkool <segher@kernel.crashing.org>
+
+ * config/rs6000/rs6000.md (define_mode_attr sd): Add values for V4SF
+ and V2DF.
+ * config/rs6000/vsx.md (define_mode_attr VSs): Delete.
+ (rest of file): Adjust.
+
+2019-06-04 Segher Boessenkool <segher@kernel.crashing.org>
+
+ * config/rs6000/vsx.md (vsx_<VS_spdp_insn>): Use wa instead of <VSa>.
+ (vsx_extract_<mode>_var): Ditto.
+
+2019-06-04 Segher Boessenkool <segher@kernel.crashing.org>
+
+ * config/rs6000/vsx.md: Replace all <VSa> that are used with VSX_TI
+ with just "wa".
+
+2019-06-04 Segher Boessenkool <segher@kernel.crashing.org>
+
+ * config/rs6000/constraints.md (define_register_constraint "ww"):
+ Delete.
+ * config/rs6000/rs6000.c (rs6000_debug_reg_global): Adjust.
+ (rs6000_init_hard_regno_mode_ok): Adjust.
+ * config/rs6000/rs6000.h (enum r6000_reg_class_enum): Delete
+ RS6000_CONSTRAINT_ww.
+ * config/rs6000/rs6000.md: Adjust.
+ * config/rs6000/vsx.md: Adjust.
+ * doc/md.texi (Machine Constraints): Adjust.
+
+2019-06-04 Segher Boessenkool <segher@kernel.crashing.org>
+
+ * config/rs6000/rs6000.md (SFDF, SFDF2): Adjust comments.
+ (define_mode_attr sd): New.
+ (define_mode_attr s): New.
+ (define_mode_attr Ftrad): Delete.
+ (define_mode_attr Fvsx): Delete.
+ (define_mode_attr Fs): Delete.
+ (rest of file): Use the new mode attributes.
+ * config.rs6000/vsx.md: Use the new mode attributes.
+
+2019-06-04 Segher Boessenkool <segher@kernel.crashing.org>
+
+ * config/rs6000/vsx.md: Replace all <VSa> that are used with VSX_W
+ with just "wa".
+
+2019-06-04 Segher Boessenkool <segher@kernel.crashing.org>
+
+ * config/rs6000/vsx.md (define_mode_attr VSr2): Delete.
+ (rest of file): Replace all <VSa>, <VSr>, <VSr2>, and <VSr3> that are
+ used with VSX_B, VSX_D, or VSX_F, with just "wa".
+
+2019-06-04 Bill Schmidt <wschmidt@linux.ibm.com>
+
+ PR target/78263
+ * config/rs6000/altivec.h: Don't #define vector, pixel, bool for
+ C++ with strict ANSI requirements.
+
+2019-06-04 Marc Glisse <marc.glisse@inria.fr>
+
+ * tree-ssa-loop-niter.c (number_of_iterations_ne): Skip
+ computations when step is 1.
+
+2019-06-04 Segher Boessenkool <segher@kernel.crashing.org>
+
+ * config/rs6000/constraints.md (define_register_constraint "wf"):
+ Delete.
+ * config/rs6000/rs6000.c (rs6000_debug_reg_global): Adjust.
+ (rs6000_init_hard_regno_mode_ok): Adjust.
+ * config/rs6000/rs6000.h (enum r6000_reg_class_enum): Delete
+ RS6000_CONSTRAINT_wf.
+ * config/rs6000/rs6000.md: Adjust.
+ * config/rs6000/vsx.md: Adjust.
+ * doc/md.texi (Machine Constraints): Adjust.
+
+2019-06-04 Andrew Pinski <apinski@marvell.com>
+
+ * config/aarch64/aarch64.c (aarch64_asan_shadow_offset):
+ Fix ILP32 value.
+
+2019-06-04 Segher Boessenkool <segher@kernel.crashing.org>
+
+ * config/rs6000/constraints.md (define_register_constraint "wd"):
+ Delete.
+ * config/rs6000/rs6000.c (rs6000_debug_reg_global): Adjust.
+ (rs6000_init_hard_regno_mode_ok): Adjust.
+ * config/rs6000/rs6000.h (enum r6000_reg_class_enum): Delete
+ RS6000_CONSTRAINT_wd.
+ * config/rs6000/rs6000.md: Adjust.
+ * config/rs6000/vsx.md: Adjust.
+ * doc/md.texi (Machine Constraints): Adjust.
+
+2019-06-04 Segher Boessenkool <segher@kernel.crashing.org>
+
+ * config/rs6000/rs6000.md (define_mode_attr Fv2): Delete.
+ (rest of file): Adjust.
+
+2019-06-04 Segher Boessenkool <segher@kernel.crashing.org>
+
+ * config/rs6000/vsx.md (define_mode_attr VS_64reg): Delete.
+ (*vsx_extract_<P:mode>_<VSX_D:mode>_load): Adjust.
+ (vsx_splat_<mode>_reg): Adjust.
+
+2019-06-04 Segher Boessenkool <segher@kernel.crashing.org>
+
+ * config/rs6000/constraints.md (define_register_constraint "ws"):
+ Delete.
+ * config/rs6000/rs6000.c (rs6000_debug_reg_global): Adjust.
+ (rs6000_init_hard_regno_mode_ok): Adjust.
+ * config/rs6000/rs6000.h (enum r6000_reg_class_enum): Delete
+ RS6000_CONSTRAINT_ws.
+ * config/rs6000/rs6000.md: Adjust.
+ * config/rs6000/vsx.md: Adjust.
+ * doc/md.texi (Machine Constraints): Adjust.
+
+2019-06-04 Segher Boessenkool <segher@kernel.crashing.org>
+
+ * config/rs6000/constraints.md (define_register_constraint "wv"):
+ Delete.
+ * config/rs6000/rs6000.c (rs6000_debug_reg_global): Adjust.
+ (rs6000_init_hard_regno_mode_ok): Adjust.
+ * config/rs6000/rs6000.h (enum r6000_reg_class_enum): Delete
+ RS6000_CONSTRAINT_wv.
+ * config/rs6000/rs6000.md: Adjust.
+ * config/rs6000/vsx.md: Adjust.
+ * doc/md.texi (Machine Constraints): Adjust.
+
+2019-06-04 Segher Boessenkool <segher@kernel.crashing.org>
+
+ * config/rs6000/constraints.md (define_register_constraint "wi"):
+ Delete.
+ (define_register_constraint "wt"): Delete.
+ * config/rs6000/rs6000.c (rs6000_debug_reg_global): Adjust.
+ (rs6000_init_hard_regno_mode_ok): Adjust.
+ * config/rs6000/rs6000.h (enum r6000_reg_class_enum): Delete
+ RS6000_CONSTRAINT_wi and RS6000_CONSTRAINT_wt.
+ * config/rs6000/rs6000.md: Adjust.
+ * config/rs6000/vsx.md: Adjust.
+ * doc/md.texi (Machine Constraints): Adjust.
+
+2019-06-04 Szabolcs Nagy <szabolcs.nagy@arm.com>
+
+ * config/aarch64/aarch64-protos.h (aarch64_asm_output_external): Remove
+ const.
+ * config/aarch64/aarch64.c (aarch64_asm_output_external): Call
+ default_elf_asm_output_external.
+
+2019-06-04 Martin Liska <mliska@suse.cz>
+
+ * ipa-icf.c (INCLUDE_LIST): Remove.
+ (sem_item_optimizer::execute): Remove call to init_wpa.
+ * ipa-icf.h (init_wpa): Remove.
+
+2019-06-04 Jakub Jelinek <jakub@redhat.com>
+
+ * gimplify.c (gimplify_scan_omp_clauses): Don't sorry_at on lastprivate
+ conditional on combined for simd.
+ * omp-low.c (struct omp_context): Add combined_into_simd_safelen0
+ member.
+ (lower_rec_input_clauses): For gimple_omp_for_combined_into_p max_vf 1
+ constructs, don't remove lastprivate_conditional_map, but instead set
+ ctx->combined_into_simd_safelen0 and adjust hash_map, so that it points
+ to parent construct temporaries.
+ (lower_lastprivate_clauses): Handle ctx->combined_into_simd_safelen0
+ like !ctx->lastprivate_conditional_map.
+ (lower_omp_1) <case GIMPLE_ASSIGN>: If up->combined_into_simd_safelen0,
+ use up->outer context instead of up.
+ * omp-expand.c (expand_omp_for_generic): Perform cond_var bump even if
+ gimple_omp_for_combined_p.
+ (expand_omp_for_static_nochunk): Likewise.
+ (expand_omp_for_static_chunk): Add forgotten cond_var bump that was
+ probably moved over into expand_omp_for_generic rather than being copied
+ there.
+
+2019-06-04 Martin Liska <mliska@suse.cz>
+
+ * value-prof.c (dump_histogram_value): Fix typo.
+ (gimple_mod_subtract_transform): Likewise.
+
+2019-06-04 Richard Biener <rguenther@suse.de>
+
+ PR middle-end/90726
+ * tree-chrec.c (chrec_contains_symbols): Add to visited.
+ (tree_contains_chrecs): Likewise.
+ (chrec_contains_symbols_defined_in_loop): Move here and avoid
+ exponential behaivor from ...
+ * tree-scalar-evolution.c (chrec_contains_symbols_defined_in_loop):
+ ... here.
+ (expression_expensive_p): Avoid exponential behavior and compute
+ expanded size, rejecting any expansion.
+ * tree-ssa-loop-ivopts.c (abnormal_ssa_name_p): Remove.
+ (idx_contains_abnormal_ssa_name_p): Likewise.
+ (contains_abnormal_ssa_name_p_1): New helper for walk_tree.
+ (contains_abnormal_ssa_name_p): Simplify and use
+ walk_tree_without_duplicates.
+
+2019-06-04 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/90738
+ Revert
+ 2019-06-03 Richard Biener <rguenther@suse.de>
+
+ * tree-ssa-sccvn.c (ao_ref_init_from_vn_reference): Get original
+ full reference tree and record in ref->ref.
+ (vn_reference_lookup_3): Pass in original ref to
+ ao_ref_init_from_vn_reference.
+ (vn_reference_lookup): Likewise.
+ * tree-ssa-sccvn.h (ao_ref_init_from_vn_reference): Adjust prototype.
+ * tree-ssa-alias.c (nonoverlapping_component_refs_of_decl_p):
+ Handle non-decl bases in the original reference.
+
+2019-06-04 Martin Liska <mliska@suse.cz>
+
+ * ipa-icf.c (sem_item_optimizer::add_item_to_class): Count
+ number of references.
+ (sem_item_optimizer::do_congruence_step):
+ (sem_item_optimizer::worklist_push): Dump how references
+ a class has.
+ (sem_item_optimizer::worklist_pop): Use heap.
+ (sem_item_optimizer::process_cong_reduction): Likewise.
+ * ipa-icf.h: Use fibonacci_heap insteam of std::list.
+
+2019-06-04 Martin Liska <mliska@suse.cz>
+
+ * ipa-icf.h (struct sem_usage_pair_hash): New.
+ (sem_usage_pair_hash::hash): Likewise.
+ (sem_usage_pair_hash::equal): Likewise.
+ (struct sem_usage_hash): Likewise.
+ * ipa-icf.c (sem_item::sem_item): Initialize
+ referenced_by_count.
+ (sem_item::add_reference): Register a reference
+ in ref_map and not in target->usages.
+ (sem_item::setup): Remove initialization of
+ dead vectors.
+ (sem_item::~sem_item): Remove usage of dead vectors.
+ (sem_item::dump): Remove dump of references.
+ (sem_item_optimizer::sem_item_optimizer): Initialize
+ m_references.
+ (sem_item_optimizer::read_section): Remove useless
+ dump.
+ (sem_item_optimizer::parse_funcs_and_vars): Likewise here.
+ (sem_item_optimizer::build_graph): Pass m_references
+ to ::add_reference.
+ (sem_item_optimizer::verify_classes): Remove usage of dead
+ vectors.
+ (sem_item_optimizer::traverse_congruence_split): Return true
+ when a class is split.
+ (sem_item_optimizer::do_congruence_step_for_index): Use
+ hash_map for look up of (sem_item *, index). That brings
+ significant speed up.
+ (sem_item_optimizer::do_congruence_step): Return true
+ when a split is done.
+ (congruence_class::is_class_used): Use referenced_by_count.
+
+2019-06-04 Alan Modra <amodra@gmail.com>
+
+ PR target/90689
+ * config/rs6000/rs6000.c (rs6000_call_aix): Correct r271753 merge
+ error.
+
+2019-06-03 Segher Boessenkool <segher@kernel.crashing.org>
+
+ * config/rs6000/rs6000.h (MASK_MFPGPR): Delete.
+ * config/rs6000/rs6000.c (direct_move_p): Adjust.
+ (rs6000_secondary_reload_simple_move): Adjust.
+ (rs6000_opt_masks): Neuter the "mfpgpr" option.
+ * config/rs6000/rs6000-c.c (rs6000_target_modify_macros): Adjust.
+ * config/rs6000/rs6000-cpus.def (ISA_2_5_MASKS_EMBEDDED): Adjust
+ comment.
+ (power6x): Adjust.
+ * config/rs6000/rs6000.md (floatsi<mode>2_lfiwax): Adjust.
+ (floatunssi<mode>2_lfiwzx): Adjust.
+ (fix_trunc<mode>si2_stfiwx): Adjust.
+ (fixuns_trunc<mode>si2_stfiwx): Adjust.
+ * config/rs6000/rs6000.opt (mno-mfpgpr): New.
+ (mfpgpr): Mark as deprecated.
+ * doc/extend.texi (PowerPC Function Attributes): Delete mfpgpr.
+ (Basic PowerPC Built-in Functions Available on ISA 2.05): Adjust.
+ * doc/invoke.texi (RS/6000 and PowerPC Options): Delete -mmfpgpr.
+
+2019-06-03 Segher Boessenkool <segher@kernel.crashing.org>
+
+ * config/rs6000/constraints.md (define_register_constraint "wg"):
+ Delete.
+ * config/rs6000/rs6000.h (enum r6000_reg_class_enum): Delete
+ RS6000_CONSTRAINT_wg.
+ * config/rs6000/rs6000.c (rs6000_debug_reg_global): Adjust.
+ (rs6000_init_hard_regno_mode_ok): Adjust.
+ * config/rs6000/rs6000.md (*mov<mode>_softfloat32, *movdi_internal64):
+ Delete "wg" alternatives.
+ * doc/md.texi (Machine Constraints): Adjust.
+
+2019-06-03 Alan Modra <amodra@gmail.com>
+
+ * bb-reorder.c (copy_bb_p): Don't overflow size calculation.
+ (get_uncond_jump_length): Assert length less than INT_MAX and
+ non-negative.
+
+2019-06-03 Wilco Dijkstra <wdijkstr@arm.com>
+
+ PR middle-end/64242
+ * builtins.c (expand_builtin_longjmp): Add frame clobbers and schedule
+ block.
+ (expand_builtin_nonlocal_goto): Likewise.
+
+2019-06-03 Szabolcs Nagy <szabolcs.nagy@arm.com>
+
+ * config/aarch64/aarch64-protos.h (aarch64_asm_output_alias): Declare.
+ (aarch64_asm_output_external): Declare.
+ * config/aarch64/aarch64.c (aarch64_asm_output_variant_pcs): New.
+ (aarch64_declare_function_name): Call aarch64_asm_output_variant_pcs.
+ (aarch64_asm_output_alias): New.
+ (aarch64_asm_output_external): New.
+ * config/aarch64/aarch64.h (ASM_OUTPUT_DEF_FROM_DECLS): Define.
+ (ASM_OUTPUT_EXTERNAL): Define.
+
+2019-06-03 Aldy Hernandez <aldyh@redhat.com>
+ * tree-vrp.h (value_range_base::nonzero_p): New.
+ (value_range_base::set_nonnull): Rename to...
+ (value_range_base::set_nonzero): ...this.
+ (value_range_base::set_null): Rename to...
+ (value_range_base::set_zero): ...this.
+ (value_range::set_nonnull): Remove.
+ (value_range::set_null): Remove.
+ * tree-vrp.c (range_is_null): Remove.
+ (range_is_nonnull): Remove.
+ (extract_range_from_binary_expr): Use value_range_base::*zero_p
+ instead of range_is_*null.
+ (extract_range_from_unary_expr): Same.
+ (value_range_base::set_nonnull): Rename to...
+ (value_range_base::set_nonzero): ...this.
+ (value_range::set_nonnull): Remove.
+ (value_range_base::set_null): Rename to...
+ (value_range_base::set_zero): ...this.
+ (value_range::set_null): Remove.
+ (extract_range_from_binary_expr): Rename set_*null uses to
+ set_*zero.
+ (extract_range_from_unary_expr): Same.
+ (union_helper): Same.
+ * vr-values.c (get_value_range): Use set_*zero instead of
+ set_*null.
+ (vr_values::extract_range_from_binary_expr): Same.
+ (vr_values::extract_range_basic): Same.
+
+2019-06-03 Wilco Dijkstra <wdijkstr@arm.com>
+
+ PR driver/90684
+ * opts.c (parse_and_check_align_values): Allow 4 alignment values.
+
+2019-06-03 Kyrylo Tkachov <kyrylo.tkachov@arm.com>
+
+ * config/aarch64/iterators.md (MAX_OPP): New code attr.
+ * config/aarch64/aarch64-simd.md (*aarch64_<su>abd<mode>_3): Rename to...
+ (aarch64_<su>abd<mode>_3): ... This.
+ (<sur>sadv16qi): Add TARGET_DOTPROD expansion.
+
+2019-06-03 Richard Biener <rguenther@suse.de>
+
+ * tree-ssa-sccvn.c (ao_ref_init_from_vn_reference): Get original
+ full reference tree and record in ref->ref.
+ (vn_reference_lookup_3): Pass in original ref to
+ ao_ref_init_from_vn_reference.
+ (vn_reference_lookup): Likewise.
+ * tree-ssa-sccvn.h (ao_ref_init_from_vn_reference): Adjust prototype.
+ * tree-ssa-alias.c (nonoverlapping_component_refs_of_decl_p):
+ Handle non-decl bases in the original reference.
+
+2019-06-03 Martin Liska <mliska@suse.cz>
+
+ * doc/generic.texi: Remove Java Trees.
+
+2019-06-03 Martin Liska <mliska@suse.cz>
+
+ * fold-const.c (operand_equal_p): Fix typo as compare_tree_int
+ returns 0 when operands are equal.
+
+2019-06-03 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/90716
+ * tree-loop-distribution.c (destroy_loop): Process blocks in
+ correct order.
+
+2019-06-03 Prathamesh Kulkarni <prathamesh.kulkarni@linaro.org>
+
+ PR target/88837
+ * vector-builder.h (vector_builder::count_dups): New method.
+ * config/aarch64/aarch64-protos.h (aarch64_expand_sve_vector_init):
+ Declare prototype.
+ * config/aarch64/aarch64/sve.md (aarch64_sve_rev64<mode>): Use @.
+ (vec_init<mode><Vel>): New pattern.
+ * config/aarch64/aarch64.c (emit_insr): New function.
+ (aarch64_sve_expand_vector_init_handle_trailing_constants): Likewise.
+ (aarch64_sve_expand_vector_init_insert_elems): Likewise.
+ (aarch64_sve_expand_vector_init_handle_trailing_same_elem): Likewise.
+ (aarch64_sve_expand_vector_init): Define two overloaded functions.
+
+2019-06-03 Alejandro Martinez <alejandro.martinezvicente@arm.com>
+
+ PR tree-optimization/90681
+ * internal-fn.c (mask_load_direct): Mark as non-vectorizable again.
+ * tree-vect-slp.c (vect_build_slp_tree_1): Add masked loads as a
+ special case for SLP, but fail on non-groupped loads.
+
+2019-06-03 Martin Liska <mliska@suse.cz>
+
+ * cfg.c (debug): Use TDF_DETAILS for debug and
+ print edge info only once.
+
+2019-06-02 Thomas Koenig <tkoenig@gcc.gnu.org>
+
+ PR fortran/90539
+ * predict.def (PRED_FORTRAN_CONTIGUOUS): New predictor.
+
+2019-06-01 Martin Sebor <msebor@redhat.com>
+
+ PR middle-end/90694
+ * tree-pretty-print.c (dump_generic_node): Add parentheses.
+
+2019-05-31 Jan Hubicka <jh@suse.cz>
+
+ * alias.c: Include ipa-utils.h.
+ (get_alias_set): Try to complete ODR type via ODR type hash lookup.
+ * ipa-devirt.c (prevailing_odr_type): New.
+ * ipa-utils.h (previaling_odr_type): Declare.
+
+2019-05-31 H.J. Lu <hongjiu.lu@intel.com>
+ Hongtao Liu <hongtao.liu@intel.com>
+
+ PR target/89355
+ * config/i386/i386-features.c (rest_of_insert_endbranch): Remove
+ NOTE_INSN_DELETED_LABEL check.
+
+2019-05-31 Prachi Godbole <prachi.godbole@imgtec.com>
+ Robert Suchanek <robert.suchanek@mips.com>
+
+ * config/mips/mips.c (mips_expand_builtin_insn): Swap the 1st
+ and 3rd operands of the fmadd/fmsub/maddv builtin.
+
+2019-05-31 Jakub Jelinek <jakub@redhat.com>
+
+ * tree.h (OMP_CLAUSE__CONDTEMP__ITER): Define.
+ * gimplify.c (gimplify_scan_omp_clauses): Allow lastprivate conditional
+ on OMP_SIMD if not nested inside of worksharing loop that also has
+ lastprivate conditional clause for the same decl.
+ (gimplify_omp_for): Add _condtemp_ clauses to OMP_SIMD if needed.
+ * omp-low.c (scan_sharing_clauses): Handle OMP_CLAUSE__CONDTEMP_ also
+ on simd.
+ (lower_rec_input_clauses): Likewise. Handle lastprivate conditional
+ on simd construct.
+ (lower_lastprivate_conditional_clauses): Handle lastprivate conditional
+ on simd construct.
+ (lower_lastprivate_clauses): Likewise.
+ (lower_omp_sections): Call lower_lastprivate_conditional_clauses before
+ calling lower_rec_input_clauses.
+ (lower_omp_for): Likewise.
+ (lower_omp_1): Use first rather than second OMP_CLAUSE__CONDTEMP_
+ clause on simd construct.
+ * omp-expand.c (expand_omp_simd): Initialize cond_var if
+ OMP_CLAUSE__CONDTEMP_ clause is present.
+
+ * omp-low.c (lower_rec_simd_input_clauses): Set TREE_THIS_NOTRAP on
+ ivar and lvar.
+
+2019-05-31 Xiong Hu Luo <luoxhu@linux.ibm.com>
+
+ PR c/43673
+ * c-format.c (print_char_table, scanf_char_table): Replace BADLEN with
+ TEX_D32, TEX_D64 or TEX_D128.
+
+2019-05-31 Marc Glisse <marc.glisse@inria.fr>
+
+ * match.pd (~(vec?cst1:cst2)): New transformation.
+
+2019-05-31 Marc Glisse <marc.glisse@inria.fr>
+
+ * match.pd (X/[ex]D<Y/[ex]D): Handle negative denominator.
+ ((size_t)(A /[ex] B) CMP C): New transformation.
+
+2019-05-31 Richard Sandiford <richard.sandiford@arm.com>
+
+ * doc/md.texi: Document define_insn_and_rewrite.
+ * rtl.def (DEFINE_INSN_AND_REWRITE): New rtx code.
+ * gensupport.c (queue_elem): Update comment.
+ (replace_operands_with_dups): New function.
+ (gen_rewrite_sequence): Likewise.
+ (process_rtx): Handle DEFINE_INSN_AND_REWRITE.
+ * read-rtl.c (apply_subst_iterator): Likewise.
+ (add_condition_to_rtx, named_rtx_p): Likewise.
+ (rtx_reader::read_rtx_operand): Likewise.
+ * config/aarch64/aarch64-sve.md
+ (while_ult<GPI:mode><PRED_ALL:mode>_cc): Rename to...
+ (*while_ult<GPI:mode><PRED_ALL:mode>_cc): ...this and use
+ define_insn_and_rewrite.
+ (*cond_<optab><mode>_any): Turn into define_insn_and_rewrites.
+ Remove separate define_split.
+
+2019-05-31 Jan Hubicka <jh@suse.cz>
+
+ * tree-ssa-alias.c (type_has_components_p): New function.
+ (aliasing_component_refs_p): Use it.
+
+2019-05-31 Martin Liska <mliska@suse.cz>
+
+ * gdbhooks.py: Add const_tree to TreePrinter.
+
+2019-05-31 Thomas De Schampheleire <thomas.de_schampheleire@nokia.com>
+
+ PR debug/86964
+ * common.opt (feliminate-unused-debug-symbols): Enable by default.
+ * doc/invoke.texi (Debugging Options): Document new default of
+ -feliminate-unused-debug-symbols and remove restriction to 'stabs'.
+
+2019-05-31 Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/90671
+ * tree-ssa-threadupdate.c (ssa_create_duplicates): If
+ template_block used to be empty on the first call, don't use
+ gsi_split_seq_after and gsi_insert_seq_after, but remember whole
+ seq with bb_seq and set it with set_bb_seq.
+
+2019-05-31 Iain Sandoe <iain@sandoe.co.uk>
+
+ * config/i386/darwin.h (ASM_OUTPUT_MAX_SKIP_ALIGN): New.
+
+2019-05-30 Bill Schmidt <wschmidt@linux.ibm.com>
+ Michael Meissner <meissner@linux.ibm.com>
+
+ * config/rs6000/predicates.md (pcrel_address): New define_predicate.
+ (prefixed_mem_operand): Likewise.
+ (non_prefixed_mem_operand): Likewise.
+ * config/rs6000/rs6000-protos.h (rs6000_prefixed_address): New
+ prototype.
+ * config/rs6000/rs6000.c (print_operand_address): Handle
+ PC-relative addresses.
+ (mode_supports_prefixed_address_p): New function.
+ (rs6000_prefixed_address): New function.
+ * config/rs6000/rs6000.h (SYMBOL_FLAG_PCREL): New #define.
+ (SYMBOL_REF_PCREL_P): Likewise.
+
+2019-05-30 Jakub Jelinek <jakub@redhat.com>
+
+ * gimplify.c (enum gimplify_omp_var_data): Add GOVD_CONDTEMP.
+ (gimplify_adjust_omp_clauses_1): Handle GOVD_CONDTEMP.
+ (gimplify_omp_for): If worksharing loop with lastprivate conditional
+ is nested inside of parallel region, add _condtemp_ clause to both.
+ * tree-nested.c (convert_nonlocal_omp_clauses,
+ convert_local_omp_clauses): Ignore OMP_CLAUSE__CONDTEMP_ instead of
+ assertion failure.
+ * omp-general.h (struct omp_for_data): Add have_pointer_condtemp
+ member.
+ * omp-general.c (omp_extract_for_data): Compute it.
+ * omp-low.c (scan_sharing_clauses): Handle OMP_CLAUSE__CONDTEMP_.
+ (lower_rec_input_clauses): Likewise.
+ (lower_lastprivate_conditional_clauses): If OMP_CLAUSE__CONDTEMP_
+ clause is already present, just add one further one after it.
+ (lower_lastprivate_clauses): Handle cond_ptr with array type.
+ (lower_send_shared_vars): Clear _condtemp_ vars.
+ (lower_omp_1) <case GIMPLE_ASSIGN>: Handle target data like critical
+ or section or taskgroup.
+ * omp-expand.c (determine_parallel_type): Disallow combining only if
+ first OMP_CLAUSE__CONDTEMP_ has pointer type. Disallow combining
+ of parallel sections if OMP_CLAUSE__CONDTEMP_ is present.
+ (expand_omp_for_generic, expand_omp_for_static_nochunk,
+ expand_omp_for_static_chunk, expand_omp_for): Use
+ fd->have_pointer_condtemp instead of fd->lastprivate_conditional to
+ determine if a special set of API routines are needed and if condtemp
+ needs to be initialized, while always initialize cond_var if
+ fd->lastprivate_conditional is non-zero.
+
+2019-05-30 Bill Schmidt <wschmidt@linux.ibm.com>
+ Michael Meissner <meissner@linux.ibm.com>
+
+ * config/rs6000/constraints.md (eI): New constraint.
+ * config/rs6000/predicates.md (cint34_operand): New predicate.
+ * config/rs6000/rs6000.h (SIGNED_16BIT_OFFSET_P): New #define.
+ (SIGNED_34BIT_OFFSET_P): Likewise.
+ * doc/md.texi (eI): Document constraint.
+
+2019-05-30 Sylvia Taylor <sylvia.taylor@arm.com>
+
+ * config/aarch64/aarch64-sve.md (*fabd<mode>3): New.
+
+2019-05-30 Bill Schmidt <wschmidt@linux.ibm.com>
+ Michael Meissner <meissner@linux.ibm.com>
+
+ * rs6000-cpus.def (OTHER_FUSION_MASKS): New #define.
+ (ISA_3_0_MASKS_SERVER): Mask off OTHER_FUSION_MASKS.
+ (ISA_3_0_MASKS_IEEE): Remove OPTION_MASK_DIRECT_MOVE.
+ (ISA_FUTURE_MASKS_SERVER): Add OPTION_MASK_PREFIXED_ADDR.
+ (OTHER_FUTURE_MASKS): Likewise.
+ (POWERPC_MASKS): Likewise.
+ * rs6000.c (rs6000_option_override_internal): Error if -mpcrel is
+ specified without -mprefixed-addr or -mcpu=future. Error if
+ -mprefixed-addr is specified without -mcpu=future.
+ (rs6000_opt_masks): Add entry for prefixed-addr.
+ * rs6000.opt (mprefixed-addr): New option.
+
+2019-05-30 Sam Tebbs <sam.tebbs@arm.com>
+
+ * aarch64/aarch64.c (aarch64_post_cfi_startproc): Add
+ cfun->is_thunk check.
+
+2019-05-30 Jakub Jelinek <jakub@redhat.com>
+
+ * tree-predcom.c (is_inv_store_elimination_chain): Fix a typo - lenght
+ to length.
+
+2019-05-30 Martin Liska <mliska@suse.cz>
+
+ * gdbinit.in: Fix 'ptc' command. Add trt
+ that prints TREE_TYPE($).
+
+2019-05-29 Bill Schmidt <wschmidt@linux.ibm.com>
+ Alan Modra <amodra@gmail.com>
+
+ * config/rs6000/rs6000.c (rs6000_call_template_1): Handle pcrel
+ calls here...
+ (rs6000_indirect_call_template_1): ...and here.
+ (rs6000_pltseq_template): Handle plt_pcrel34. Rework tocsave,
+ plt16_ha, plt16_lo, mtctr indirect calls. Use
+ rs6000_pltseq_enum.
+ (rs6000_decl_ok_for_sibcall): New function.
+ (rs6000_function_ok_for_sibcall): Refactor.
+ (rs6000_longcall_ref): Use UNSPEC_PLT_PCREL when pcrel.
+ (rs6000_call_aix): Don't emit toc restore rtl for indirect calls
+ when pcrel. Reorganize.
+ (rs6000_sibcall_aix): Don't add r2 to function usage when pcrel.
+ * rs6000.h (rs6000_pltseq_enum): New enum.
+ * rs6000.md (UNSPEC_PLT_PCREL): New unspec.
+ (*pltseq_tocsave): Use rs6000_pltseq_enum.
+ (*pltseq_plt16_ha): Likewise.
+ (*pltseq_plt16_lo): Likewise.
+ (*pltseq_mtctr): Likewise.
+ (*pltseq_plt_pcrel): New insn.
+ (*call_local_aix): Handle @notoc calls.
+ (*call_value_local_aix): Likewise.
+ (*call_nonlocal_aix): Adjust lengths for pcrel calls.
+ (*call_value_nonlocal_aix): Likewise.
+ (*call_indirect_pcrel): New insn.
+ (*call_value_indirect_pcrel): Likewise.
+
+
+2019-05-29 Uroš Bizjak <ubizjak@gmail.com>
+
+ * config/i386/sse.md (*save_multiple<mode>): Rename from
+ save_multiple<mode>.
+ (*restore_multiple<mode>): Rename from restore_multiple<mode>.
+ (*restore_multiple_and_return<mode>): Rename from
+ restore_multiple_and_return<mode>.
+ (*restore_multiple_leave_return<mode>): Rename from
+ restore_multiple_leave_return<mode>.
+
+2019-05-29 Yoshinori Sato <ysato@users.sourceforge.jp>
+
+ * config.gcc (rx-*-linux*): New target.
+ * config/rx/elf.opt: New file.
+ * config/rx/linux.h: Likewise.
+ * config/rx/t-linux: Likewise.
+ * config/rx/rx.c (TARGET_SAVE_ACC_REGISTER): If not defined,
+ make it zero.
+ * config/rx/rx.h (ASM_APP_ON): Allow to be overridden.
+ (ASM_APP_OFF): Likewise.
+ * config/rx/rx.opt: Drop -msim and -mas100-syntax, they were
+ moved elsewhere.
+
+2019-05-29 Jan Hubicka <jh@suse.cz>
+
+ * tree-ssa-alias.c (same_type_for_tbaa): Return ture if main
+ variants are pointer equivalent.
+
+2019-05-29 Alejandro Martinez <alejandro.martinezvicente@arm.com>
+
+ * config/aarch64/aarch64-c.c: Added TARGET_SVE2.
+ * config/aarch64/aarch64-sve2.md: New file.
+ (<u>avg<mode>3_floor): New pattern.
+ (<u>avg<mode>3_ceil): Likewise.
+ (*<sur>h<addsub><mode>): Likewise.
+ * config/aarch64/aarch64.h: Added AARCH64_ISA_SVE2 and TARGET_SVE2.
+ * config/aarch64/aarch64.md: Include aarch64-sve2.md.
+
+2019-05-29 Jakub Jelinek <jakub@redhat.com>
+
+ PR bootstrap/90543
+ * optc-save-gen.awk: In cl_optimization_print, use correct condition
+ for var_opt_string printing. In cl_optimization_print_diff, print
+ (null) instead of invoking undefined behavior if one of the
+ var_opt_string pointers is NULL and use && instead of first || in the
+ guarding condition. For var_target_other options, handle const char *
+ target variables similarly to const char * optimize node variables.
+
+2019-05-29 Sam Tebbs <sam.tebbs@arm.com>
+
+ * config/aarch64/aarch64-builtins.c (aarch64_builtins): Add
+ AARCH64_PAUTH_BUILTIN_AUTIB1716 and AARCH64_PAUTH_BUILTIN_PACIB1716.
+ * config/aarch64/aarch64-builtins.c (aarch64_init_pauth_hint_builtins):
+ Add autib1716 and pacib1716 initialisation.
+ * config/aarch64/aarch64-builtins.c (aarch64_expand_builtin): Add checks
+ for autib1716 and pacib1716.
+ * config/aarch64/aarch64-protos.h (aarch64_key_type,
+ aarch64_post_cfi_startproc): Define.
+ * config/aarch64/aarch64-protos.h (aarch64_ra_sign_key): Define extern.
+ * config/aarch64/aarch64.c (aarch64_handle_standard_branch_protection,
+ aarch64_handle_pac_ret_protection): Set default sign key to A.
+ * config/aarch64/aarch64.c (aarch64_expand_epilogue,
+ aarch64_expand_prologue): Add check for b-key.
+ * config/aarch64/aarch64.c (aarch64_ra_sign_key,
+ aarch64_post_cfi_startproc, aarch64_handle_pac_ret_b_key): Define.
+ * config/aarch64/aarch64.h (TARGET_ASM_POST_CFI_STARTPROC): Define.
+ * config/aarch64/aarch64.c (aarch64_pac_ret_subtypes): Add "b-key".
+ * config/aarch64/aarch64.md (unspec): Add UNSPEC_AUTIA1716,
+ UNSPEC_AUTIB1716, UNSPEC_AUTIASP, UNSPEC_AUTIBSP, UNSPEC_PACIA1716,
+ UNSPEC_PACIB1716, UNSPEC_PACIASP, UNSPEC_PACIBSP.
+ * config/aarch64/aarch64.md (do_return): Add check for b-key.
+ * config/aarch64/aarch64.md (<pauth_mnem_prefix>sp): Replace
+ pauth_hint_num_a with pauth_hint_num.
+ * config/aarch64/aarch64.md (<pauth_mnem_prefix>1716): Replace
+ pauth_hint_num_a with pauth_hint_num.
+ * config/aarch64/aarch64.opt (msign-return-address=): Deprecate.
+ * config/aarch64/iterators.md (PAUTH_LR_SP): Add UNSPEC_AUTIASP,
+ UNSPEC_AUTIBSP, UNSPEC_PACIASP, UNSPEC_PACIBSP.
+ * config/aarch64/iterators.md (PAUTH_17_16): Add UNSPEC_AUTIA1716,
+ UNSPEC_AUTIB1716, UNSPEC_PACIA1716, UNSPEC_PACIB1716.
+ * config/aarch64/iterators.md (pauth_mnem_prefix): Add UNSPEC_AUTIA1716,
+ UNSPEC_AUTIB1716, UNSPEC_PACIA1716, UNSPEC_PACIB1716, UNSPEC_AUTIASP,
+ UNSPEC_AUTIBSP, UNSPEC_PACIASP, UNSPEC_PACIBSP.
+ * config/aarch64/iterators.md (pauth_hint_num_a): Replace
+ UNSPEC_PACI1716 and UNSPEC_AUTI1716 with UNSPEC_PACIA1716 and
+ UNSPEC_AUTIA1716 respectively.
+ * config/aarch64/iterators.md (pauth_hint_num_a): Rename to pauth_hint_num
+ and add UNSPEC_PACIBSP, UNSPEC_AUTIBSP, UNSPEC_PACIB1716, UNSPEC_AUTIB1716.
+ * doc/invoke.texi (-mbranch-protection): Add b-key type.
+ * config/aarch64/aarch64-bti-insert.c (aarch64_pac_insn_p): Rename
+ UNSPEC_PACISP to UNSPEC_PACIASP and UNSPEC_PACIBSP.
+
+2019-05-29 Jakub Jelinek <jakub@redhat.com>
+
+ * gimplify.c (struct gimplify_omp_ctx): Add clauses member.
+ (gimplify_scan_omp_clauses): Initialize ctx->clauses.
+ (gimplify_adjust_omp_clauses_1): Transform lastprivate conditional
+ explicit clause on combined parallel into implicit shared clause.
+ (gimplify_adjust_omp_clauses): Move lastprivate conditional clause
+ and firstprivate if the decl has one too from combined parallel to
+ the worksharing construct.
+
+2019-05-28 Bill Schmidt <wschmidt@linux.ibm.com>
+ Michael Meissner <meissner@linux.ibm.com>
+
+ * config/rs6000/rs6000-cpus.def (OTHER_FUTURES_MASK): New #define.
+
+2019-05-28 Michael Meissner <meissner@linux.ibm.com>
+
+ * rtl.h (LABEL_REF_P): New #define.
+
+2019-05-28 John David Anglin <danglin@gcc.gnu.org>
+
+ * config/pa/pa.c (hppa_profile_hook): Remove offset adjustment.
+
+2019-05-28 Alejandro Martinez <alejandro.martinezvicente@arm.com>
+
+ * internal-fn.c: Marked mask_load_direct as vectorizable.
+ * tree-data-ref.c (data_ref_compare_tree): Fixed comment typo.
+ * tree-vect-data-refs.c (can_group_stmts_p): Allow masked loads to be
+ combined even if masks different with allow_slp_p param.
+ (vect_analyze_data_ref_accesses): Mark SLP only vectorizable groups.
+ * tree-vect-loop.c (vect_dissolve_slp_only_groups): New function to
+ dissolve SLP-only vectorizable groups when SLP has been discarded.
+ (vect_analyze_loop_2): Call vect_dissolve_slp_only_groups when needed.
+ * tree-vect-slp.c (vect_get_and_check_slp_defs): Check masked loads
+ masks.
+ (vect_build_slp_tree_1): Fixed comment typo.
+ (vect_build_slp_tree_2): Include masks from masked loads in SLP tree.
+ * tree-vect-stmts.c (vectorizable_load): Allow vectorizaion of masked
+ loads for SLP only.
+ * tree-vectorizer.h (_stmt_vec_info): Added flag for SLP-only
+ vectorizable.
+ * tree-vectorizer.c (vec_info::new_stmt_vec_info): Likewise.
+
+2019-05-28 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE>
+
+ * config/alpha/alpha.c [TARGET_ABI_OSF] (alpha_output_mi_thunk_osf):
+ Remove obsolete use_thunk reference.
+ * config/i386/i386.c (x86_output_mi_thunk): Likewise.
+ * config/ia64/ia64.c (ia64_output_mi_thunk): Likewise.
+ * config/nios2/nios2.c (nios2_asm_output_mi_thunk): Likewise.
+ * config/or1k/or1k.c (or1k_output_mi_thunk): Likewise.
+ * config/rs6000/rs6000.c (rs6000_output_mi_thunk): Likewise.
+ * config/sh/sh.c (sh_output_mi_thunk): Likewise.
+ * config/sparc/sparc.c (sparc_output_mi_thunk): Likewise.
+ * config/tilegx/tilegx.c (tilegx_output_mi_thunk): Likewise.
+ * config/tilepro/tilepro.c (tilepro_asm_output_mi_thunk): Likewise.
+
+2019-05-28 Nathan Sidwell <nathan@acm.org>
+
+ * tree.h (IDENTIFIER_ANON_P): New.
+ (anon_aggrname_format, anon_aggname_p): Don't declare.
+ (make_anon_name): Declare.
+ * lto-streamer-out.c (DFS::DFS_write_tree_body): Use IDENTIFIER_ANON_P.
+ (hash_tree): Likewise.
+ * tree-streamer-out.c (write_ts_decl_minimal_tree): Likewise.
+ * tree.c (anon_aggrname_p, anon_aggrname_format): Delete.
+ (anon_cnt, make_anon_name): New.
+
+2019-05-28 Martin Liska <mliska@suse.cz>
+
+ PR other/90315
+ * opts-global.c (decode_options): Print help for all
+ help_option_arguments.
+ * opts.c (print_help): Add new argument.
+ (common_handle_option): Remember all values into
+ help_option_arguments.
+ * opts.h (print_help): Add new argument.
+
+2019-05-28 Martin Liska <mliska@suse.cz>
+
+ PR ipa/90555
+ * ipa-icf-gimple.c (func_checker::compare_loops): New function.
+ * ipa-icf-gimple.h (func_checker::compare_loops): Likewise.
+ (func_checker::compare_bb): Call compare_loops.
+
+2019-05-27 Jakub Jelinek <jakub@redhat.com>
+
+ * gimplify.c (gimplify_scan_omp_clauses): Allow lastprivate conditional
+ on sections construct.
+ * omp-low.c (lower_lastprivate_conditional_clauses): Handle sections
+ construct.
+ (lower_omp_sections): Handle lastprivate conditional.
+ (lower_omp_1) <case GIMPLE_ASSIGN>: Handle sections construct with
+ lastprivate_conditional_map.
+ * omp-expand.c (expand_omp_sections): Handle lastprivate conditional.
+
+ * omp-low.c (lower_omp_1) <case GIMPLE_ASSIGN>: Look through ordered,
+ critical, taskgroup and section regions when looking for a region
+ with non-NULL lastprivate_conditional_map.
+
+2019-05-27 Uroš Bizjak <ubizjak@gmail.com>
+
+ * config/i386/i386.c (ix86_gen_add3): Remove indirect function.
+ (*ix86_gen_sub3): Ditto.
+ (*ix86_gen_sub3_carry): Ditto.
+ (*ix86_gen_one_cmpl2): Ditto.
+ (*ix86_gen_andsp): Ditto.
+ (ix86_init_large_pic_reg): Use gen_add2_insn instead of ix86_gen_add3.
+ (gen_and2_insn): New static function.
+ (ix86_expand_prologue): Use gen_and2_insn instead of ix86_gen_andsp.
+ Use gen_add3_insn instead of ix86_gen_add3.
+ (ix86_expand_split_stack_prologue): Use gen_add2_insn
+ instead of ix86_gen_add3.
+ (legitimize_tls_address): Use gen_add2_insn instead of ix86_gen_add3.
+ Use gen_sub3_insn instead of ix86_gen_sub3.
+ * config/i386-expand.c (ix86_split_long_move): Use gen_add2_insn
+ instead of ix86_gen_add3.
+ (ix86_expand_strlensi_unroll_1): Use gen_add2_insn instead of
+ ix86_gen_add3. Use gen_sub3_insn instead of ix86_gen_sub3.
+ (construct_plt_address): Use gen_add2_insn instead of ix86_gen_add3.
+ * config/i386/i386-options.c (ix86_option_override_internal):
+ Do not initialize ix86_gen_add3, ix86_gen_sub3, ix86_gen_sub3_carry,
+ ix86_gen_one_cmpl2 and ix86_gen_andsp.
+
+2019-05-27 Eric Botcazou <ebotcazou@adacore.com>
+
+ * dwarf2out.c (resolve_args_picking_1): Deal with DW_OP_GNU_addr_index
+ and DW_OP_GNU_const_index opcodes.
+
+2019-05-27 Uroš Bizjak <ubizjak@gmail.com>
+
+ * config/i386/i386.h (STACK_SIZE_MODE): Define.
+
+2019-05-27 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/90637
+ * tree-ssa-sink.c (statement_sink_location): Honor the
+ computed sink location for single-uses.
+
+2019-05-27 Richard Biener <rguenther@suse.de>
+
+ PR middle-end/90610
+ * match.pd (vec_perm): Avoid clobbering op0 when not generating
+ a bit-insert.
+
+2019-05-26 Uroš Bizjak <ubizjak@gmail.com>
+
+ * config/i386/i386.md (@sub<mode>3_carry): Rename
+ from sub<mode>3_carry.
+ (@leave_<mode>): New expander.
+ (*leave): Rename from leave.
+ (*leave_rex64): Rename from leave_rex64.
+ (@monitorx_<mode>): Rename from monitorx_<mode>.
+ (@clzero_<mode>): Rename from clzero_<mode>.
+ * config/i386/sse.md (@sse3_monitor_<mode>): Rename
+ from sse3_monitor_<mode>.
+ * config/i386/i386.c (ix86_gen_sub3_carry): Remove indirect function.
+ (*ix86_gen_leave): Ditto.
+ (*ix86_gen_monitor): Ditto.
+ (*ix86_gen_monitorx): Ditto.
+ (*ix86_gen_clzero): Ditto.
+ (ix86_emit_leave): Use gen_leave instead of ix86_gen_leave.
+ * config/i386/i386-expand.c (ix86_expand_strlensi_unroll_1):
+ Use gen_sub3_carry instead of ix86_gen_sub3_carry.
+ (ix86_expand_builtin) <case IX86_BUILTIN_MONITOR>:
+ Use gen_sse3_monitor instead of ix86_gen_monitor.
+ <case IX86_BUILTIN_MONITORX>: Use gen_monitorx
+ instead of ix86_gen_monitorx.
+ <case IX86_BUILTIN_CLZERO>: Use gen_clzero
+ instead of ix86_gen_clzero.
+ * config/i386/i386-options.c (ix86_option_override_internal):
+ Do not initialize ix86_gen_leave, ix86_gen_sub3_carry,
+ ix86_gen_monitor, ix86_gen_monitorx and ix86_gen_clzero.
+
+2019-05-26 Uroš Bizjak <ubizjak@gmail.com>
+
+ * config/i386/i386.md (@tls_global_dynamic_64_<mode>):
+ Rename from tls_global_dynamic_64_<mode>.
+ (@tls_local_dynamic_base_64_<mode>): Rename from
+ tls_local_dynamic_base_64_<mode>.
+ * config/i386/i386.c (*ix86_gen_tls_global_dynamic_64):
+ Remove indirect function.
+ (*ix86_gen_tls_local_dynamic_base_64): Ditto.
+ (legitimize_tls_address): Use gen_tls_global_dynamic_64 function
+ instead of ix86_gen_tls_global_dynamic_64.
+ Use gen_tls_local_dynamic_base_64 instead of
+ ix86_gen_tls_local_dynamic_base_64.
+ * config/i386/i386-options.c (ix86_option_override_internal):
+ Do not initialize ix86_gen_tls_global_dynamic_64 and
+ ix86_gen_tls_local_dynamic_base_64.
+
+2019-05-26 Uroš Bizjak <ubizjak@gmail.com>
+
+ * config/i386/i386.md (@pro_epilogue_adjust_stack_add_<mode>)
+ Rename from pro_epilogue_adjust_stack_<mode>_add.
+ (@pro_epilogue_adjust_stack_sub_<mode>)
+ Rename from pro_epilogue_adjust_stack_<mode>_sub.
+ (@allocate_stack_worker_probe_<mode>):
+ Rename from allocate_stack_worker_probe_<mode>.
+ (allocate_stack): Use gen_allocate_stack_worker_probe.
+ (probe_stack): Use gen_probe_stack_1.
+ (@probe_stack_1_<mode>): Rename from probe_stack_<mode>.
+ (@adjust_stack_and_probe_<mode>): Rename from
+ adjust_stack_and_probe<mode>.
+ (@probe_stack_range_<mode>): Rename from probe_stack_range<mode>.
+ (stack_protect_set): Use gen_stack_protect_set_1.
+ (@stack_protect_set_1_<mode>): Rename from stack_protect_set_<mode>.
+ (stack_protect_test): Use gen_stack_protect_test_1.
+ (@stack_protect_test_1_<mode>): Rename from stack_protect_test_<mode>.
+ * config/i386/i386.c (*ix86_gen_allocate_stack_worker):
+ Remove indirect function.
+ (*ix86_gen_adjust_stack_and_probe): Ditto.
+ (*ix86_gen_probe_stack_range): Ditto.
+ (pro_epilogue_adjust_stack): Use gen_pro_epilogue_adjust_stack_add
+ instead of gen_pro_epilogue_adjust_stack_{si,di}_add.
+ (ix86_adjust_stack_and_probe_stack_clash): Use
+ gen_adjust_stack_and_probe instead of ix86_gen_adjust_stack_and_probe.
+ (ix86_adjust_stack_and_probe): Ditto.
+ (ix86_emit_probe_stack_range): Use gen_probe_stack_range instead
+ of ix86_gen_probe_stack_range.
+ (ix86_expand_prologue): Use gen_pro_epilogue_adjust_stack_sub
+ instead of gen_pro_epilogue_adjust_stack_{si,di}_sub.
+ * config/i386/x86-tune-sched.c (ix86_macro_fusion_pair_p):
+ Include insn-opinit.h. Use code_for_stack_protect_test_1 instead of
+ CODE_FOR_stack_protect_test_{si,di}.
+ * config/i386/i386-options.c (ix86_option_override_internal):
+ Do not initialize ix86_gen_allocate_stack_worker,
+ ix86_gen_adjust_stack_and_probe and ix86_gen_probe_stack_range.
+
+2019-05-26 Gerald Pfeifer <gerald@pfeifer.com>
+
+ * doc/invoke.texi (Link Options): Many editorial changes around
+ -flinker-output.
+
+2019-05-26 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE>
+
+ * doc/invoke.texi (x86 Options, -mvect8-ret-in-mem): Remove
+ pre-Solaris 11 referene and most Studio compiler details.
+
+2019-05-24 John David Anglin <danglin@gcc.gnu.org>
+
+ PR target/90530
+ * config/pa/pa.c (pa_can_change_mode_class): Accept mode changes from
+ DImode to SImode in floating-point registers on 64-bit target.
+ * config/pa/pa.md (umulsidi3): Change nonimmediate_operand to
+ register_operand in xmpyu patterns.
+
+2019-05-24 Jakub Jelinek <jakub@redhat.com>
+
+ * tree-core.h (enum omp_clause_code): Add OMP_CLAUSE__CONDTEMP_.
+ * tree.h (OMP_CLAUSE_DECL): Use OMP_CLAUSE__CONDTEMP_ instead of
+ OMP_CLAUSE__REDUCTEMP_.
+ * tree.c (omp_clause_num_ops, omp_clause_code_name): Add
+ OMP_CLAUSE__CONDTEMP_.
+ (walk_tree_1): Handle OMP_CLAUSE__CONDTEMP_.
+ * tree-pretty-print.c (dump_omp_clause): Likewise.
+ * tree-nested.c (convert_nonlocal_omp_clauses,
+ convert_local_omp_clauses): Likewise.
+ * gimplify.c (enum gimplify_omp_var_data): Use hexadecimal constants
+ instead of decimal. Add GOVD_LASTPRIVATE_CONDITIONAL.
+ (gimplify_scan_omp_clauses): Don't reject lastprivate conditional
+ on OMP_FOR.
+ (gimplify_omp_for): Warn and disable conditional modifier from
+ lastprivate on loop iterators.
+ * omp-general.h (struct omp_for_data): Add lastprivate_conditional
+ member.
+ * omp-general.c (omp_extract_for_data): Initialize it.
+ * omp-low.c (struct omp_context): Add lastprivate_conditional_map
+ member.
+ (delete_omp_context): Delete it.
+ (lower_lastprivate_conditional_clauses): New function.
+ (lower_lastprivate_clauses): Add BODY_P and CSTMT_LIST arguments,
+ handle lastprivate conditional clauses.
+ (lower_reduction_clauses): Add CLIST argument, emit it into
+ the critical section if any.
+ (lower_omp_sections): Adjust lower_lastprivate_clauses and
+ lower_reduction_clauses callers.
+ (lower_omp_for_lastprivate): Add CLIST argument, pass it through
+ to lower_lastprivate_clauses.
+ (lower_omp_for): Call lower_lastprivate_conditional_clauses, adjust
+ lower_omp_for_lastprivate and lower_reduction_clauses callers, emit
+ clist into a critical section if not emitted there already by
+ lower_reduction_clauses.
+ (lower_omp_taskreg, lower_omp_teams): Adjust lower_reduction_clauses
+ callers.
+ (lower_omp_1): Handle GIMPLE_ASSIGNs storing into lastprivate
+ conditional variables.
+ * omp-expand.c (determine_parallel_type): Punt if OMP_CLAUSE__CONDTEMP_
+ clause is present.
+ (expand_omp_for_generic, expand_omp_for_static_nochunk,
+ expand_omp_for_static_chunk): Handle lastprivate conditional.
+ (expand_omp_for): Handle fd.lastprivate_conditional like
+ fd.have_reductemp.
+
+2019-05-24 Andrew Stubbs <ams@codesourcery.com>
+
+ * config/gcn/gcn-run.c (main): Set a non-zero return value if the
+ kernel does not exit cleanly.
+ * config/gcn/gcn.md (gcn_return): Insert s_waitcnt before s_dcache_wb.
+
+2019-05-24 Jason Merrill <jason@redhat.com>
+
+ Revert:
+ * gimplify.c (gimplify_cond_expr): Don't check TREE_ADDRESSABLE.
+
+2019-05-24 Richard Biener <rguenther@suse.de>
+
+ PR testsuite/90607
+ * tree-loop-distribution.c (struct partition): Add location
+ member.
+ (partition_alloc): Initialize all fields.
+ (generate_memset_builtin): Use the location recorded in the
+ partition for the generated call.
+ (generate_memcpy_builtin): Likewise.
+ (classify_partition): Record the location of a single store
+ as location for the partition.
+
+2019-05-24 Andrew Stubbs <ams@codesourcery.com>
+
+ * config/gcn/gcn.c (gcn_expand_prologue): Use gen_addsi3_scalar_carry
+ for lo-part.
+
+2019-05-24 Matthew Malcomson <matthew.malcomson@arm.com>
+
+ PR target/90588
+ * common/config/aarch64/aarch64-common.c
+ (aarch64_rewrite_selected_cpu): Change local temporary variable
+ type from unsigned long to uint64_t.
+ * config/aarch64/aarch64-protos.h (aarch64_parse_extension,
+ aarch64_get_extension_string_for_isa_flags): Change declaration to
+ match new definition by replacing unsigned long with uint64_t.
+
+2019-05-24 Jakub Jelinek <jakub@redhat.com>
+
+ PR target/90568
+ * config/i386/x86-tune-sched.c (ix86_macro_funsion_pair_p): Call
+ gen_attr_type just once instead of 4-7 times. Formatting fixes.
+ Handle stack_protect_test_<mode> codegen similarly to corresponding
+ sub instruction.
+
+2019-05-23 Iain Sandoe <iain@sandoe.co.uk>
+
+ * config/i386/darwin.h: Reject -mfentry*.
+ * doc/sourcebuild.texi: Document mfentry target support.
+
+2019-05-23 Bill Schmidt <wschmidt@linux.ibm.com>
+
+ * config/rs6000/rs6000.c (rs6000_global_entry_point_needed_p):
+ Rename to rs6000_global_entry_point_prologue_needed_p. Return
+ false for PC-relative functions.
+ (rs6000_output_function_prologue): Change called function name to
+ rs6000_global_entry_point_prologue_needed_p. Emit ".localentry
+ name,1" for PC-relative functions.
+ (rs6000_elf_declare_function_name): Change called function name to
+ rs6000_global_entry_point_prologue_needed_p.
+
+2019-05-23 Uroš Bizjak <ubizjak@gmail.com>
+
+ PR target/90552
+ * config/i386/i386.c (gen_rtx_cost):
+ Use ix86_tune_cost instead of ix86_cost.
+
+2019-05-23 Bill Schmidt <wschmidt@linux.ibm.com>
+ Michael Meissner <meissner@linux.ibm.com>
+ Segher Boessenkool <segher@kernel.crashing.org>
+
+ * config/rs6000/rs6000-cpus.def (ISA_FUTURE_MASKS_SERVER): Add
+ OPTION_MASK_PCREL.
+ (POWERPC_MASKS): Add OPTION_MASK_PCREL.
+ * config/rs6000/rs6000-protos.h (rs6000_pcrel_p): New prototype.
+ (rs6000_fndecl_pcrel_p): Likewise.
+ * config/rs6000/rs6000.c (rs6000_option_override_internal): Report
+ error if -mpcrel is requested without -mcpu=future.
+ (rs6000_opt_masks): Add entry for pcrel.
+ (rs6000_fndecl_pcrel_p): New function.
+ (rs6000_pcrel_p): Likewise.
+ * config/rs6000/rs6000.opt (mpcrel): New option.
+ * doc/invoke.texi: Document -mpcrel and -mno-pcrel.
+
+2019-05-23 Jan Hubicka <jh@suse.cz>
+ Martin Liska <mliska@suse.cz>
+
+ PR tree-optimization/90576
+ * tree-ssa-alias.c (compare_sizes): Remove dead calls to
+ poly_int_tree_p.
+ (aliasing_component_refs_p): Fix three way size compare conditional;
+ give up earlier in case we can not decide on equivalence.
+
+2019-05-23 Bill Schmidt <wschmidt@linux.ibm.com>
+ Michael Meissner <meissner@linux.ibm.com>
+ Segher Boessenkool <segher@kernel.crashing.org>
+
+ * config.gcc: Add future cpu.
+ * config/rs6000/driver-rs6000.c (asm_names): Add future cpu.
+ * config/rs6000/rs6000-cpus.def (ISA_FUTURE_MASKS_SERVER): New
+ #define.
+ (POWERPC_MASKS): Add OPTION_MASK_FUTURE.
+ (RS6000_CPU): New instantiation for future cpu.
+ * config/rs6000/rs6000-opts.h (enum processor_type): Add
+ PROCESSOR_FUTURE.
+ * config/rs6000/rs6000-string.c (expand_compare_loop): Treat
+ PROCESSOR_FUTURE like PROCESSOR_POWER9 for now.
+ * config/rs6000/rs6000-tables.opt: Regenerate.
+ * config/rs6000/rs6000.c (rs6000_option_override_internal): Treat
+ PROCESSOR_FUTURE similarly to PROCESSOR_POWER9 for now.
+ (rs6000_machine_from_flags): Handle future cpu.
+ (rs6000_reassociation_width): Treat PROCESSOR_FUTURE like
+ PROCESSOR_POWER9 for now.
+ (rs6000_adjust_cost): Likewise.
+ (rs6000_issue_rate): Likewise.
+ (rs6000_register_move_cost): Likewise.
+ (rs6000_opt_masks): Add entry for future.
+ * config/rs6000/rs6000.h (ASM_CPU_SPEC): Add future cpu.
+ (MASK_FUTURE): New #define.
+ * config/rs6000/rs6000.md (define_attr "cpu"): Add future cpu.
+ * config/rs6000/rs6000.opt (mfuture): New target option.
+ * doc/invoke.texi (mcpu): Add future cpu.
+
+2019-05-23 Martin Liska <mliska@suse.cz>
+
+ PR c++/90587
+ * tree-ssa-uninit.c (value_sat_pred_p): The result of &
+ operation points to a temporary (pointed via tree_to_wide_ref)
+ that is out of scope after the &.
+
+2019-05-23 Jonathan Wakely <jwakely@redhat.com>
+
+ PR c++/90592
+ * doc/extend.texi (Function Names): Add missing word.
+
+2019-05-23 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/88440
+ * opts.c (default_options_table): Enable -ftree-loop-distribute-patterns
+ at -O[2s]+.
+ * tree-loop-distribution.c (generate_memset_builtin): Fold the
+ generated call.
+ (generate_memcpy_builtin): Likewise.
+ (distribute_loop): Pass in whether to only distribute patterns.
+ (prepare_perfect_loop_nest): Also allow size optimization.
+ (pass_loop_distribution::execute): When optimizing a loop
+ nest for size allow pattern replacement.
+
+2019-05-23 Jakub Jelinek <jakub@redhat.com>
+
+ PR target/90568
+ * config/i386/i386.md (stack_protect_test_<mode>): Use sub instead
+ of xor.
+
+2019-05-23 Martin Liska <mliska@suse.cz>
+
+ PR sanitizer/90570
+ * gimplify.c (gimplify_target_expr): Skip TREE_STATIC target
+ expression similarly to gimplify_decl_expr.
+
+2019-05-23 Prathamesh Kulkarni <prathamesh.kulkarni@linaro.org>
+
+ * cse.c (cse_dump_path): s/dump_file/f.
+
+2019-05-22 David Malcolm <dmalcolm@redhat.com>
+
+ PR c++/90462
+ * diagnostic-format-json.cc: Include "selftest.h".
+ (json_from_expanded_location): Only add "file" key for non-NULL
+ file strings.
+ (json_from_location_range): Don't add "start" and "finish"
+ children if they are UNKNOWN_LOCATION.
+ (selftest::test_unknown_location): New selftest.
+ (selftest::test_bad_endpoints): New selftest.
+ (selftest::diagnostic_format_json_cc_tests): New function.
+ * json.cc (json::object::get): New function.
+ (selftest::test_object_get): New selftest.
+ (selftest::json_cc_tests): Call it.
+ * json.h (json::object::get): New decl.
+ * selftest-run-tests.c (selftest::run_tests): Call
+ selftest::diagnostic_format_json_cc_tests.
+ * selftest.h (selftest::diagnostic_format_json_cc_tests): New
+ decl.
+
+2019-05-22 Kwok Cheung Yeung <kcy@codesourcery.com>
+ Andrew Stubbs <amd@codesourcery.com>
+
+ * config.gcc (gcc_cv_initfini_array): Set for AMD GCN.
+ * config/gcn/gcn-run.c (init_array_kernel, fini_array_kernel): New.
+ (kernel): Rename to...
+ (main_kernel): ... this.
+ (load_image): Load _init_array and _fini_array kernels.
+ (run): Add argument for kernel to run.
+ (main): Run init_array_kernel before main_kernel, and
+ fini_array_kernel after.
+ * config/gcn/gcn.c (gcn_handle_amdgpu_hsa_kernel_attribute): Allow
+ amdgpu_hsa_kernel attribute on functions.
+ (gcn_disable_constructors): Delete.
+ (TARGET_ASM_CONSTRUCTOR, TARGET_ASM_DESTRUCTOR): Delete.
+ * config/gcn/crt0.c (size_t): Define.
+ (_init_array, _fini_array): New.
+ (__preinit_array_start, __preinit_array_end,
+ __init_array_start, __init_array_end,
+ __fini_array_start, __fini_array_end): Declare weak references.
+
+2019-05-22 Andrew Stubbs <ams@codesourcery.com>
+
+ * config/gcn/gcn.c (gcn_trampoline_init): Call "sorry" on GCN5.
+
+2019-05-22 Jason Merrill <jason@redhat.com>
+
+ * gimplify.c (gimplify_cond_expr): Don't check TREE_ADDRESSABLE.
+
+2019-05-22 H.J. Lu <hongjiu.lu@intel.com>
+
+ PR target/88483
+ * config/i386/i386-options.c (ix86_init_machine_status): Set
+ stack_frame_required to true.
+ * config/i386/i386.c (ix86_get_frame_size): New function.
+ (ix86_frame_pointer_required): Replace get_frame_size with
+ ix86_get_frame_size.
+ (ix86_compute_frame_layout): Likewise.
+ (ix86_find_max_used_stack_alignment): Changed to void. Set
+ stack_frame_required.
+ (ix86_finalize_stack_frame_flags): Always call
+ ix86_find_max_used_stack_alignment. Replace get_frame_size with
+ ix86_get_frame_size.
+ * config/i386/i386.h (machine_function): Add stack_frame_required.
+
+2019-05-22 Uroš Bizjak <ubizjak@gmail.com>
+
+ * config/i386/sse.md (sse_cvtpi2ps): Use TARGET_MMX in insn condition.
+
+2019-05-22 Matthew Malcomson <matthew.malcomson@arm.com>
+
+ * common/config/aarch64/aarch64-common.c
+ (struct aarch64_option_extension, struct processor_name_to_arch,
+ struct arch_to_arch_name, aarch64_parse_extension, opt_ext_cmp,
+ aarch64_contains_opt,
+ aarch64_get_extension_string_for_isa_flags): Change type of
+ variables storing flags to uint64_t.
+ * config/aarch64/aarch64-option-extensions.def (sve2, sve2-sm4,
+ sve2-aes, sve2-sha3, bitperm): New optional SVE2 extension flags.
+ * config/aarch64/aarch64.c (struct processor,
+ aarch64_parse_arch, aarch64_parse_cpu, aarch64_validate_mcpu,
+ aarch64_validate_march, aarch64_override_options,
+ aarch64_option_print, aarch64_handle_attr_isa_flags,
+ aarch64_declare_function_name, aarch64_start_file): Make flag
+ variables uint64_t.
+ * config/aarch64/aarch64.h (AARCH64_FL_SVE2, AARCH64_FL_SVE2_AES,
+ AARCH64_FL_SVE2_SM4, AARCH64_FL_SVE2_SHA3,
+ AARCH64_FL_SVE2_BITPERM): New macro feature flags.
+ * config/aarch64/aarch64.opt (aarch64_isa_flags): Make uint64_t.
+ * config/aarch64/driver-aarch64.c
+ (struct aarch64_arch_extension, struct aarch64_core_data,
+ struct aarch64_arch_driver_info, host_detect_local_cpu): Make
+ flag variables uint64_t.
+ * doc/invoke.texi: Add documentation for new arguments.
+
+2019-05-22 Richard Biener <rguenther@suse.de>
+
+ * alias.c (ao_ref_from_mem): Move stack-slot sharing
+ rewrite ...
+ * emit-rtl.c (set_mem_attributes_minus_bitpos): ... here.
+
+2019-05-22 Martin Liska <mliska@suse.cz>
+
+ PR lto/90500
+ * doc/extend.texi: Document the change.
+
+2019-05-22 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/90450
+ * tree-ssa-loop-im.c (struct im_mem_ref): Add ref_decomposed.
+ (mem_ref_hasher::equal): Check it.
+ (mem_ref_alloc): Initialize it.
+ (gather_mem_refs_stmt): Set it.
+
+2019-05-22 Richard Biener <rguenther@suse.de>
+
+ * gimple-fold.c (arith_code_with_undefined_signed_overflow):
+ Add ABS_EXPR.
+ (rewrite_to_defined_overflow): Handle rewriting ABS_EXPR
+ as ABSU_EXPR.
+
+2019-05-22 Alan Modra <amodra@gmail.com>
+
+ * config/rs6000/rs6000.h (ASM_OPT_ANY): Define.
+ (ASM_CPU_SPEC): Conditionally add -many.
+ * config/rs6000/rs6000.c (rs6000_machine): New static var.
+ (rs6000_machine_from_flags, emit_asm_machine): New functions..
+ (rs6000_file_start): ..extracted from here, and modified to
+ test all ISA bits.
+ (rs6000_output_function_prologue): Emit .machine as necessary.
+ * testsuite/gcc.target/powerpc/ppc32-abi-dfp-1.c: Don't use
+ power mnemonics.
+ * testsuite/gcc.dg/vect/O3-pr70130.c: Disable default options
+ added by check_vect_support_and_set_flags.
+ * testsuite/gcc.dg/vect/pr48765.c: Likewise.
+ * testsuite/gfortran.dg/vect/pr45714-b.f: Likewise.
+
+2019-05-22 Hans-Peter Nilsson <hp@axis.com>
+
+ PR middle-end/90553
+ * ira-lives.c (process_bb_node_lives): Consider defs
+ for a call insn to be die before the call, not after.
+
+ * function.c (assign_parm_setup_block): Raise alignment of
+ stacked parameter only for STRICT_ALIGNMENT targets.
+
+2019-05-21 Segher Boessenkool <segher@kernel.crashing.org>
+
+ * config/rs6000/constraints.md (define_register_constraint "wz"):
+ Delete.
+ * config/rs6000/rs6000.h (enum r6000_reg_class_enum): Delete
+ RS6000_CONSTRAINT_wz.
+ * config/rs6000/rs6000.c (rs6000_debug_reg_global): Adjust.
+ (rs6000_init_hard_regno_mode_ok): Adjust.
+ * config/rs6000/rs6000.md: Replace "wz" constraint by "d" with "p7".
+ * doc/md.texi (Machine Constraints): Adjust.
+
+2019-05-21 Segher Boessenkool <segher@kernel.crashing.org>
+
+ * config/rs6000/constraints.md (define_register_constraint "wl"):
+ Delete.
+ * config/rs6000/rs6000.h (enum r6000_reg_class_enum): Delete
+ RS6000_CONSTRAINT_wl.
+ * config/rs6000/rs6000.c (rs6000_debug_reg_global): Adjust.
+ (rs6000_init_hard_regno_mode_ok): Adjust.
+ * config/rs6000/rs6000.md: Replace "wl" constraint by "d" with "p6".
+ * doc/md.texi (Machine Constraints): Adjust.
+
+2019-05-21 Segher Boessenkool <segher@kernel.crashing.org>
+
+ * config/rs6000/constraints.md (define_register_constraint "wm"):
+ Delete.
+ * config/rs6000/rs6000.h (enum r6000_reg_class_enum): Delete
+ RS6000_CONSTRAINT_wm.
+ * config/rs6000/rs6000.c (rs6000_debug_reg_global): Adjust.
+ (rs6000_init_hard_regno_mode_ok): Adjust.
+ * config/rs6000/vsx.md: Replace "wm" constraint by "wa" with "p8v".
+ * doc/md.texi (Machine Constraints): Adjust.
+
+2019-05-21 Segher Boessenkool <segher@kernel.crashing.org>
+
+ * config/rs6000/constraints.md (define_register_constraint "wk"):
+ Delete.
+ * config/rs6000/rs6000.h (enum r6000_reg_class_enum): Delete
+ RS6000_CONSTRAINT_wk.
+ * config/rs6000/rs6000.c (rs6000_debug_reg_global): Adjust.
+ (rs6000_init_hard_regno_mode_ok): Adjust.
+ * config/rs6000/rs6000.md: Replace "wk" constraint by "ws" with "p8v".
+ * doc/md.texi (Machine Constraints): Adjust.
+
+2019-05-21 Segher Boessenkool <segher@kernel.crashing.org>
+
+ * config/rs6000/constraints.md (define_register_constraint "wj"):
+ Delete.
+ * config/rs6000/rs6000.h (enum r6000_reg_class_enum): Delete
+ RS6000_CONSTRAINT_wj.
+ * config/rs6000/rs6000.c (rs6000_debug_reg_global): Adjust.
+ (rs6000_init_hard_regno_mode_ok): Adjust.
+ * config/rs6000/rs6000.md: Replace "wj" constraint by "wi" with "p8v".
+ (VS_64dm): Delete.
+ * config/rs6000/vsx.md: Ditto.
+ * doc/md.texi (Machine Constraints): Adjust.
+
+2019-05-21 Segher Boessenkool <segher@kernel.crashing.org>
+
+ * config/rs6000/constraints.md (define_register_constraint "wh"):
+ Delete.
+ * config/rs6000/rs6000.h (enum r6000_reg_class_enum): Delete
+ RS6000_CONSTRAINT_wh.
+ * config/rs6000/rs6000.c (rs6000_debug_reg_global): Adjust.
+ (rs6000_init_hard_regno_mode_ok): Adjust.
+ * config/rs6000/rs6000.md: Replace "wh" constraint by "wa" with "p8v".
+ * doc/md.texi (Machine Constraints): Adjust.
+
+2019-05-21 Uroš Bizjak <ubizjak@gmail.com>
+
+ PR target/90547
+ * config/i386/i386.md (anddi_1 to andsi_1_zext splitter):
+ Avoid calling gen_lowpart with CONST operand.
+
+2019-05-21 Alexandre Oliva <aoliva@redhat.com>
+
+ * tree-ssa-threadupdate.c (struct ssa_local_info_t): Add
+ field template_last_to_copy.
+ (ssa_create_duplicates): Set it, and use it. Attempt to
+ preserve more debug stmts.
+
+2019-05-21 Uroš Bizjak <ubizjak@gmail.com>
+
+ * config/i386/sse.md (VF1_AVX2): New mode iterator.
+ (signbit<mode>2): New expander
+
+2019-05-21 James Clarke <jrtc27@jrtc27.com>
+
+ PR bootstrap/87338
+ * dwarf2out.c (dwarf2out_inline_entry): Use ASM_OUTPUT_DEBUG_LABEL
+ instead of ASM_GENERATE_INTERNAL_LABEL and ASM_OUTPUT_LABEL.
+
+2019-05-21 Uroš Bizjak <ubizjak@gmail.com>
+
+ * config/i386/cpuid.h (__cpuid): For 32bit targets, zero
+ %ebx and %ecx bafore calling cpuid with leaf 1 or
+ non-constant leaf argument.
+
+2019-05-21 Alan Modra <amodra@gmail.com>
+
+ PR target/90545
+ * config/rs6000/rs6000.c (rs6000_register_move_cost): Increase
+ power9 direct move cost.
+ * testsuite/gcc.target/powerpc/fold-vec-splats-floatdouble.c:
+ Correct comments and rename functions to suit parameters.
+
+2019-05-21 Richard Biener <rguenther@suse.de>
+
+ PR middle-end/90510
+ * fold-const.c (fold_read_from_vector): New function.
+ * fold-const.h (fold_read_from_vector): Declare.
+ * match.pd (VEC_PERM_EXPR): Build BIT_INSERT_EXPRs for
+ single-element insert permutations. Canonicalize selector
+ further and fix issue with last commit.
+
+2019-05-21 Vladislav Ivanishin <vlad@ispras.ru>
+
+ * tree-cfg.h (split_critical_edges): Add for_edge_insertion_p
+ parameter with default value false to declaration.
+ (split_edges_for_insertion): New inline function. Wrapper for
+ split_critical_edges with for_edge_insertion_p = true.
+ * tree-cfg.c (split_critical_edges): Don't split non-critical
+ edges if for_edge_insertion_p is false. Fix whitespace.
+ * tree-ssa-pre.c (pass_pre::execute): Call
+ split_edges_for_insertion instead of split_critical_edges.
+ * gcc/tree-ssa-tail-merge.c (tail_merge_optimize): Ditto.
+ * gcc/tree-ssa-sink.c (pass_sink_code::execute): Ditto.
+ (pass_data_sink_code): Update function name in the comment.
+
+2019-05-21 Vladislav Ivanishin <vlad@ispras.ru>
+
+ * tree-ssa-uninit.c (value_sat_pred_p): This new function is a wrapper
+ around is_value_included_in that knows how to handle BIT_AND_EXPR.
+ (is_pred_expr_subset_of): Use the new function. Handle more cases where
+ code1 == EQ_EXPR and where code1 == BIT_AND_EXPR and thus fix some false
+ positives.
+
+2019-05-21 Martin Liska <mliska@suse.cz>
+
+ * config/rs6000/driver-rs6000.c (elf_platform): Do not use
+ an extra newline.
+ * config/rs6000/rs6000-c.c (rs6000_pragma_longcal): Wrap pragma in %<%>.
+ (altivec_resolve_overloaded_builtin): Likewise for vec_lvsl and
+ vec_lvsr.
+ * config/rs6000/rs6000.c (rs6000_option_override_internal):
+ Quote a C type.
+ (rs6000_function_arg): Likewise.
+ (rs6000_expand_set_fpscr_drn_builtin): Remove trailing dot.
+ (rs6000_expand_ternop_builtin): Use interval syntax.
+ (get_element_number): Likewise.
+ (altivec_expand_builtin): Likewise.
+ (rs6000_get_function_versions_dispatcher): Quote target_clones.
+
+Fix test-suite.
+
+2019-05-20 Jakub Jelinek <jakub@redhat.com>
+
+ PR c++/59813
+ PR target/90418
+ * function.h (struct function): Add calls_eh_return member.
+ * gimplify.c (gimplify_call_expr): Set cfun->calls_eh_return when
+ gimplifying __builtin_eh_return call.
+ * tree-inline.c (initialize_cfun): Copy calls_eh_return from src_cfun
+ to cfun.
+ (expand_call_inline): Or in src_cfun->calls_eh_return into
+ dst_cfun->calls_eh_return.
+ * tree-tailcall.c (suitable_for_tail_call_opt_p): Return false if
+ cfun->calls_eh_return.
+ * lto-streamer-in.c (input_struct_function_base): Read calls_eh_return.
+ * lto-streamer-out.c (output_struct_function_base): Write
+ calls_eh_return.
+
+2019-05-20 Marc Glisse <marc.glisse@inria.fr>
+
+ PR rtl-optimization/43147
+ * config/i386/i386.c (ix86_gimple_fold_builtin): Handle
+ IX86_BUILTIN_SHUFPD.
+
+2019-05-20 Jan Hubicka <hubicka@ucw.cz>
+
+ * tree-ssa-alias.c (refs_may_alias_p_2): Break out from ...
+ (refs_may_alias_p_1): ... here; update stats.
+ (refs_may_alias_p): Do not update stats here.
+
+2019-05-20 Richard Biener <rguenther@suse.de>
+
+ * tree-ssa-structalias.c (find_func_aliases): POINTER_DIFF_EXPR
+ doesn't produce pointers.
+ {TRUNC,CEIL,FLOOR,ROUND,EXACT}_{DIV,MOD}_EXPR points to what
+ the first operand points to.
+
+2019-05-20 Jan Hubicka <hubicka@ucw.cz>
+
+ * tree-ssa-alias.c (compare_sizes): New function.
+ (sompare_type_sizes): New function
+ (aliasing_component_refs_p): Use it.
+ (indirect_ref_may_alias_decl_p): Likewise.
+
+2019-05-20 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE>
+
+ * config/i386/sol2.h (CC1_SPEC): Reject -mx32.
+
+2019-05-20 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE>
+
+ * config/sol2.h (LIBTSAN_EARLY_SPEC): Remove : after %e.
+ (LIBLSAN_EARLY_SPEC): Likewise.
+ * config/i386/sol2.h (ASAN_REJECT_SPEC): Likewise.
+
+2019-05-20 Martin Liska <mliska@suse.cz>
+
+ * config/i386/i386.c (ix86_libc_has_fast_function):
+ Add ATTRIBUTE_UNUSED for the argument.
+
+2019-05-20 Richard Biener <rguenther@suse.de>
+
+ * gimple-match-head.c: Include vec-perm-indices.h.
+ * generic-match-head.c: Likewise.
+ * fold-const.h (fold_vec_perm): Declare when vec-perm-indices.h
+ is included.
+ * fold-const.c (fold_vec_perm): Export.
+ (fold_ternary_loc): Move non-constant folding of VEC_PERM_EXPR...
+ (match.pd): ...here.
+
+2019-05-20 Jakub Jelinek <jakub@redhat.com>
+
+ * cfgloop.h (struct loop): Add simdlen member.
+ * cfgloopmanip.c (copy_loop_info): Copy simdlen as well.
+ * omp-expand.c (expand_omp_simd): Set it if simdlen clause is present.
+ * tree-vect-loop.c (vect_analyze_loop): Pass loop->simdlen != 0
+ as new argument to autovectorize_vector_sizes target hook. If
+ loop->simdlen, pick up vector size where the vectorization factor
+ is equal to loop->simd, and if there is none, fall back to the first
+ successful one.
+ (vect_transform_loop): Adjust autovectorize_vector_sizes target hook
+ caller.
+ * omp-low.c (omp_clause_aligned_alignment): Likewise.
+ * omp-general.c (omp_max_vf): Likewise.
+ * optabs-query.c (can_vec_mask_load_store_p): Likewise.
+ * tree-vect-slp.c (vect_slp_bb): Likewise.
+ * target.def (autovectorize_vector_sizes): Add ALL argument and
+ document it.
+ * doc/tm.texi: Adjust documentation.
+ * targhooks.c (default_autovectorize_vector_sizes): Add bool argument.
+ * targhooks.h (default_autovectorize_vector_sizes): Likewise.
+ * config/aarch64/aarch64.c (aarch64_autovectorize_vector_sizes): Add
+ bool argument.
+ * config/arc/arc.c (arc_autovectorize_vector_sizes): Likewise.
+ * config/arm/arm.c (arm_autovectorize_vector_sizes): Likewise.
+ * config/mips/mips.c (mips_autovectorize_vector_sizes): Likewise.
+ * config/i386/i386.c (ix86_autovectorize_vector_sizes): Likewise. If
+ true and TARGET_AVX512F or TARGET_AVX, push 3 or 2 sizes even if
+ preferred vector size is not 512-bit or 256-bit, just put those
+ unpreferred ones last.
+
+2019-05-20 Martin Liska <mliska@suse.cz>
+
+ * targhooks.c (default_libc_has_fast_function): New function.
+ * targhooks.h (default_libc_has_fast_function): Likewise.
+
+2019-05-20 Martin Liska <mliska@suse.cz>
+
+ PR middle-end/90263
+ * builtins.c (expand_builtin_memory_copy_args): When having a
+ target with fast mempcpy implementation do now use memcpy.
+ * config/i386/i386.c (ix86_libc_has_fast_function): New.
+ (TARGET_LIBC_HAS_FAST_FUNCTION): Likewise.
+ * doc/tm.texi: Likewise.
+ * doc/tm.texi.in: Likewise.
+ * target.def:
+ * expr.c (emit_block_move_hints): Add 2 new arguments.
+ * expr.h (emit_block_move_hints): Bail out when libcall
+ to memcpy would be used.
+
+2019-05-20 Martin Liska <mliska@suse.cz>
+
+ * profile-count.c: Add vertical spacing in order
+ to separate functions.
+ * profile-count.h: Likewise.
+
+2019-05-20 Martin Liska <mliska@suse.cz>
+
+ * profile-count.h: Do not use full qualified
+ names if possible.
+ * profile-count.c (profile_count::to_frequency): Likewise.
+
+2019-05-20 Martin Liska <mliska@suse.cz>
+
+ * profile-count.h (enum profile_quality): Use capital letters
+ for enum value names. Use the adjusted names.
+ * profile-count.c: Use the adjusted names.
+
+2019-05-19 Segher Boessenkool <segher@kernel.crashing.org>
+
+ * config/rs6000/constraints.md (define_register_constraint "wH"):
+ Delete.
+ (define_register_constraint "wI"): Delete.
+ * config/rs6000/rs6000.h (enum r6000_reg_class_enum): Delete
+ RS6000_CONSTRAINT_wH and RS6000_CONSTRAINT_wI.
+ * config/rs6000/rs6000.c (rs6000_debug_reg_global): Adjust.
+ (rs6000_init_hard_regno_mode_ok): Adjust.
+ * config/rs6000/rs6000.md: Replace "wH" and "wI" constraints by "v"
+ resp. "d", or with "wa" as appropriate, all with "p8v".
+ * config/rs6000/vsx.md: Ditto.
+ * doc/md.texi (Machine Constraints): Adjust.
+
+2019-05-19 Segher Boessenkool <segher@kernel.crashing.org>
+
+ * config/rs6000/constraints.md (define_register_constraint "wy"):
+ Delete.
+ * config/rs6000/rs6000.h (enum r6000_reg_class_enum): Delete
+ RS6000_CONSTRAINT_wy.
+ * config/rs6000/rs6000.c (rs6000_debug_reg_global): Adjust.
+ (rs6000_init_hard_regno_mode_ok): Adjust.
+ * config/rs6000/rs6000.md: Replace "wy" constraint by "wa" with "p8v".
+ Use "<Fisa>" as "isa" in all alternatives that use "<Fv2>".
+ (define_mode_attr Fisa): New.
+ * config/rs6000/vsx.md: Replace "wy" constraint by "wa" with "p8v".
+ * doc/md.texi (Machine Constraints): Adjust.
+
+2019-05-19 Segher Boessenkool <segher@kernel.crashing.org>
+
+ * config/rs6000/constraints.md (define_register_constraint "wu"):
+ Delete.
+ * config/rs6000/rs6000.h (enum r6000_reg_class_enum): Delete
+ RS6000_CONSTRAINT_wu.
+ * config/rs6000/rs6000.c (rs6000_debug_reg_global): Adjust.
+ (rs6000_init_hard_regno_mode_ok): Adjust.
+ * config/rs6000/rs6000.md: Replace "wu" constraint by "v" or "wa",
+ both with "p8v".
+ (define_mode_attr Fa): Delete.
+ * config/rs6000/vsx.md: Ditto.
+ * doc/md.texi (Machine Constraints): Adjust.
+
+2019-05-19 Segher Boessenkool <segher@kernel.crashing.org>
+
+ * config/rs6000/constraints.md (define_register_constraint "wJ"):
+ Delete.
+ (define_register_constraint "wK"): Delete.
+ * config/rs6000/rs6000.h (enum r6000_reg_class_enum): Delete
+ RS6000_CONSTRAINT_wJ and RS6000_CONSTRAINT_wK.
+ * config/rs6000/rs6000.c (rs6000_debug_reg_global): Adjust.
+ (rs6000_init_hard_regno_mode_ok): Adjust.
+ * config/rs6000/rs6000.md: Replace "wJ" constraint by "wI" with "p9v".
+ Replace "wK" constraint by "wH" with "p9v".
+ * config/rs6000/vsx.md: Ditto.
+ * doc/md.texi (Machine Constraints): Adjust.
+
+2019-05-19 Segher Boessenkool <segher@kernel.crashing.org>
+
+ * config/rs6000/constraints.md (define_register_constraint "wb"):
+ Delete.
+ * config/rs6000/rs6000.h (enum r6000_reg_class_enum): Delete
+ RS6000_CONSTRAINT_wb.
+ * config/rs6000/rs6000.c (rs6000_debug_reg_global): Adjust.
+ (rs6000_init_hard_regno_mode_ok): Adjust.
+ * config/rs6000/rs6000.md: Replace "wb" constraint by "v" with "p9v".
+ * config/rs6000/vsx.md: Ditto.
+ * doc/md.texi (Machine Constraints): Adjust.
+
+2019-05-19 Segher Boessenkool <segher@kernel.crashing.org>
+
+ * config/rs6000/constraints.md (define_register_constraint "wo"):
+ Delete.
+ * config/rs6000/rs6000.h (enum r6000_reg_class_enum): Delete
+ RS6000_CONSTRAINT_wo.
+ * config/rs6000/rs6000.c (rs6000_debug_reg_global): Adjust.
+ (rs6000_init_hard_regno_mode_ok): Adjust.
+ * config/rs6000/rs6000.md: Replace "wo" constraint by "wa" with "p9v".
+ * config/rs6000/altivec.md: Ditto.
+ * doc/md.texi (Machine Constraints): Adjust.
+
+2019-05-18 Iain Sandoe <iain@sandoe.co.uk>
+
+ * config/darwin-c.c (darwin_register_objc_includes): Do not
+ prepend the sysroot when building gnu-runtime header search
+ paths.
+
+2019-05-18 Iain Sandoe <iain@sandoe.co.uk>
+
+ * config/darwin.c (darwin_file_end): Use switch_to_section ()
+ instead of direct output of the asm.
+
+2019-05-17 Segher Boessenkool <segher@kernel.crashing.org>
+
+ * config/rs6000/rs6000.c (restore_saved_cr): Change a boolean
+ argument to be type bool (was int before).
+ (rs6000_emit_epilogue): Simplify some code. Declare some variables
+ at first use. Use type bool for some variables. Fix a theoretical
+ eh_return bug for svr4.
+
+2019-05-17 Segher Boessenkool <segher@kernel.crashing.org>
+
+ * config/rs6000/rs6000.md (isa): New attribute.
+ (enabled): New attribute.
+
+2019-05-17 Max Filippov <jcmvbkbc@gmail.com>
+
+ * config/aarch64/aarch64.c (aarch64_output_mi_thunk): Call
+ assemble_start_function and assemble_end_function.
+
+2019-05-17 Thomas Schwinge <thomas@codesourcery.com>
+
+ PR middle-end/89433
+ * omp-general.c (oacc_verify_routine_clauses): Change formal
+ parameters. Add checking if already marked with an OpenACC
+ 'routine' directive. Adjust all users.
+
+ PR middle-end/89433
+ * omp-general.c (oacc_build_routine_dims): Move some of its
+ processing into...
+ (oacc_verify_routine_clauses): ... this new function.
+ * omp-general.h (oacc_verify_routine_clauses): New prototype.
+
+2019-05-17 Iain Sandoe <iain@sandoe.co.uk>
+
+ * config/rs6000/rs6000.c (machopic_output_stub): Adjust the
+ formating of picbase labels to match other ports.
+
+2019-05-17 Iain Sandoe <iain@sandoe.co.uk>
+
+ * config/rs6000/rs6000.c (macho_branch_islands): Fix bad indent
+ in the generated code.
+
+2019-05-16 Martin Sebor <msebor@redhat.com>
+
+ * builtins.c (expand_builtin_atomic_always_lock_free): Quote
+ identifiers, keywords, operators, and types in diagnostics. Correct
+ quoting, spelling, and sentence capitalization issues.
+ (expand_builtin_atomic_is_lock_free): Same.
+ (fold_builtin_next_arg): Same.
+ * cfgexpand.c (expand_one_var): Same.
+ (tree_conflicts_with_clobbers_p): Same.
+ (expand_asm_stmt): Same.
+ (verify_loop_structure): Same.
+ * cgraphunit.c (process_function_and_variable_attributes): Same.
+ * collect-utils.c (collect_execute): Same.
+ * collect2.c (maybe_run_lto_and_relink): Same.
+ (is_lto_object_file): Same.
+ (scan_prog_file): Same.
+ * convert.c (convert_to_real_1): Same.
+ * dwarf2out.c (dwarf2out_begin_prologue): Same.
+ * except.c (verify_eh_tree): Same.
+ * gcc.c (execute): Same.
+ (eval_spec_function): Same.
+ (run_attempt): Same.
+ (driver::set_up_specs): Same.
+ (compare_debug_auxbase_opt_spec_function): Same.
+ * gcov-tool.c (unlink_gcda_file): Same.
+ (do_merge): Same.
+ (do_rewrite): Same.
+ * gcse.c (gcse_or_cprop_is_too_expensive): Same.
+ * gimplify.c (gimplify_asm_expr): Same.
+ (gimplify_adjust_omp_clauses): Same.
+ * hsa-gen.c (gen_hsa_addr_insns): Same.
+ (gen_hsa_insns_for_load): Same.
+ (gen_hsa_cmp_insn_from_gimple): Same.
+ (gen_hsa_insns_for_operation_assignment): Same.
+ (gen_get_level): Same.
+ (gen_hsa_alloca): Same.
+ (omp_simple_builtin::generate): Same.
+ (gen_hsa_atomic_for_builtin): Same.
+ (gen_hsa_insns_for_call): Same.
+ * input.c (dump_location_info): Same.
+ * ipa-devirt.c (compare_virtual_tables): Same.
+ * ira.c (ira_setup_eliminable_regset): Same.
+ * lra-assigns.c (lra_assign): Same.
+ * lra-constraints.c (lra_constraints): Same.
+ * lto-streamer-in.c (lto_input_mode_table): Same.
+ * lto-wrapper.c (get_options_from_collect_gcc_options): Same.
+ (merge_and_complain): Same.
+ (compile_offload_image): Same.
+ (compile_images_for_offload_targets): Same.
+ (debug_objcopy): Same.
+ (run_gcc): Same.
+ (main): Same.
+ * opts.c (print_specific_help): Same.
+ (parse_no_sanitize_attribute): Same.
+ (print_help): Same.
+ (handle_param): Same.
+ * plugin.c (add_new_plugin): Same.
+ (parse_plugin_arg_opt): Same.
+ (try_init_one_plugin): Same.
+ * print-rtl.c (debug_bb_n_slim): Quote identifiers, keywords,
+ operators, and types in diagnostics. Correct quoting and spelling
+ issues.
+ * read-rtl-function.c (parse_edge_flag_token): Same.
+ (function_reader::parse_enum_value): Same.
+ * reg-stack.c (check_asm_stack_operands): Same.
+ * regcprop.c (validate_value_data): Same.
+ * sched-rgn.c (make_pass_sched_fusion): Same.
+ * stmt.c (check_unique_operand_names): Same.
+ * targhooks.c (default_target_option_pragma_parse): Same.
+ * tlink.c (recompile_files): Same.
+ * toplev.c (process_options): Same.
+ (do_compile): Same.
+ * trans-mem.c (diagnose_tm_1): Same.
+ (ipa_tm_scan_irr_block): Same.
+ (ipa_tm_diagnose_transaction): Same.
+ * tree-cfg.c (verify_address): Same. Use get_tree_code_name to
+ format a tree code name in a diagnostic.
+ (verify_types_in_gimple_min_lval): Same.
+ (verify_types_in_gimple_reference): Same.
+ (verify_gimple_call): Same.
+ (verify_gimple_assign_unary): Same.
+ (verify_gimple_assign_binary): Same.
+ (verify_gimple_assign_ternary): Same.
+ (verify_gimple_assign_single): Same.
+ (verify_gimple_switch): Same.
+ (verify_gimple_label): Same.
+ (verify_gimple_phi): Same.
+ (verify_gimple_in_seq): Same.
+ (verify_eh_throw_stmt_node): Same.
+ (collect_subblocks): Same.
+ (gimple_verify_flow_info): Same.
+ (do_warn_unused_result): Same.
+ * tree-inline.c (expand_call_inline): Same.
+ * tree-into-ssa.c (update_ssa): Same.
+ * tree.c (tree_int_cst_elt_check_failed): Same.
+ (tree_vec_elt_check_failed): Same.
+ (omp_clause_operand_check_failed): Same.
+ (verify_type_variant): Same.
+ (verify_type): Same.
+ * value-prof.c (verify_histograms): Same.
+ * varasm.c (assemble_start_function): Same.
+
+2019-05-16 Martin Sebor <msebor@redhat.com>
+
+ * config/i386/i386-expand.c (get_element_number): Quote keywords
+ and other internal names in diagnostics. Adjust other diagnostic
+ formatting issues noted by -Wformat-diag.
+ * config/i386/i386-features.c
+ (ix86_mangle_function_version_assembler_name): Same.
+ * config/i386/i386-options.c (ix86_handle_abi_attribute): Same.
+ * config/i386/i386.c (ix86_function_type_abi): Same.
+ (ix86_function_ms_hook_prologue): Same.
+ (classify_argument): Same.
+ (ix86_expand_prologue): Same.
+ (ix86_md_asm_adjust): Same.
+ (ix86_memmodel_check): Same.
+
+2019-05-17 Dragan Mladjenovic <dmladjenovic@wavecomp.com>
+
+ * config/mips/mips.c (mips_dwarf_frame_reg_mode): Replace
+ TARGET_FLOAT64 with !TARGET_FLOAT32, thus handling both fp64
+ and fpxx modes.
+
+2019-05-17 H.J. Lu <hongjiu.lu@intel.com>
+
+ PR target/90497
+ * config/i386/i386-expand.c (ix86_expand_builtin): Enable MMX
+ intrinsics without SSE/SSE2/SSSE3.
+ * config/i386/mmx.md (mmx_uavgv8qi3): Restore TARGET_3DNOW
+ check.
+ (*mmx_uavgv8qi3): Likewise.
+
+2019-05-17 Richard Biener <rguenther@suse.de>
+
+ * gimple-pretty-print.c (dump_ternary_rhs): Handle dumping
+ VEC_PERM_EXPR as __VEC_PERM with -gimple.
+
+2019-05-17 Andreas Krebbel <krebbel@linux.ibm.com>
+
+ * config/s390/s390-builtins.def (s390_vec_sldw_*): Use the
+ vec_sldw insn pattern.
+
+2019-05-17 Richard Biener <rguenther@suse.de>
+
+ * ccmp.c (expand_ccmp_expr_1): Do not use gimple_assign_rhs_to_tree.
+
+2019-05-17 Martin Liska <mliska@suse.cz>
+
+ PR driver/90496
+ * toplev.c (output_stack_usage): With LTO and sanitizer it
+ happens that a global ctor (_GLOBAL__sub_I_00099_0_main)
+ has no file location.
+
+2019-05-16 Jakub Jelinek <jakub@redhat.com>
+
+ PR c++/90484
+ * tree-ssa-scopedtables.c (equal_mem_array_ref_p): Don't assert that
+ sz0 is equal to sz1, instead return false in that case.
+
+ * omp-low.c (lower_rec_input_clauses): If OMP_CLAUSE_IF
+ has non-constant expression, force sctx.lane and use two
+ argument IFN_GOMP_SIMD_LANE instead of single argument.
+ * tree-ssa-dce.c (eliminate_unnecessary_stmts): Don't DCE
+ two argument IFN_GOMP_SIMD_LANE without lhs.
+ * tree-vectorizer.h (struct _loop_vec_info): Add simd_if_cond
+ member.
+ (LOOP_VINFO_SIMD_IF_COND, LOOP_REQUIRES_VERSIONING_FOR_SIMD_IF_COND):
+ Define.
+ (LOOP_REQUIRES_VERSIONING): Or in
+ LOOP_REQUIRES_VERSIONING_FOR_SIMD_IF_COND.
+ * tree-vect-loop.c (_loop_vec_info::_loop_vec_info): Initialize
+ simd_if_cond.
+ (vect_analyze_loop_2): Punt if LOOP_VINFO_SIMD_IF_COND is constant 0.
+ * tree-vect-loop-manip.c (vect_loop_versioning): Add runtime check
+ from simd if clause if needed.
+
+2019-05-16 Richard Biener <rguenther@suse.de>
+
+ * tree-affine.c (expr_to_aff_combination): New function split
+ out from...
+ (tree_to_aff_combination): ... here.
+ (aff_combination_expand): Avoid building a GENERIC tree.
+
+2019-05-16 Max Filippov <jcmvbkbc@gmail.com>
+
+ * cgraphunit.c (cgraph_node::expand_thunk): Remove
+ assemble_start_function and assemble_end_function calls.
+ * config/alpha/alpha.c (alpha_output_mi_thunk_osf): Call
+ assemble_start_function and assemble_end_function.
+ * config/arc/arc.c (arc_output_mi_thunk): Likewise.
+ * config/arm/arm.c (arm_output_mi_thunk): Likewise.
+ * config/bfin/bfin.c (bfin_output_mi_thunk): Likewise.
+ * config/c6x/c6x.c (c6x_output_mi_thunk): Likewise.
+ * config/cris/cris.c (cris_asm_output_mi_thunk): Likewise.
+ * config/csky/csky.c (csky_output_mi_thunk): Likewise.
+ * config/epiphany/epiphany.c (epiphany_output_mi_thunk): Likewise.
+ * config/frv/frv.c (frv_asm_output_mi_thunk): Likewise.
+ * config/i386/i386.c (x86_output_mi_thunk): Likewise.
+ * config/ia64/ia64.c (ia64_output_mi_thunk): Likewise.
+ * config/m68k/m68k.c (m68k_output_mi_thunk): Likewise.
+ * config/microblaze/microblaze.c (microblaze_asm_output_mi_thunk):
+ Likewise.
+ * config/mips/mips.c (mips_output_mi_thunk): Likewise.
+ * config/mmix/mmix.c (mmix_asm_output_mi_thunk): Likewise.
+ * config/mn10300/mn10300.c (mn10300_asm_output_mi_thunk): Likewise.
+ * config/nds32/nds32.c (nds32_asm_output_mi_thunk): Likewise.
+ * config/nios2/nios2.c (nios2_asm_output_mi_thunk): Likewise.
+ * config/or1k/or1k.c (or1k_output_mi_thunk): Likewise.
+ * config/pa/pa.c (pa_asm_output_mi_thunk): Likewise.
+ * config/riscv/riscv.c (riscv_output_mi_thunk): Likewise.
+ * config/rs6000/rs6000.c (rs6000_output_mi_thunk): Likewise.
+ * config/s390/s390.c (s390_output_mi_thunk): Likewise.
+ * config/sh/sh.c (sh_output_mi_thunk): Likewise.
+ * config/sparc/sparc.c (sparc_output_mi_thunk): Likewise.
+ * config/spu/spu.c (spu_output_mi_thunk): Likewise.
+ * config/stormy16/stormy16.c (xstormy16_asm_output_mi_thunk):
+ Likewise.
+ * config/tilegx/tilegx.c (tilegx_output_mi_thunk): Likewise.
+ * config/tilepro/tilepro.c (tilepro_asm_output_mi_thunk): Likewise.
+ * config/vax/vax.c (vax_output_mi_thunk): Likewise.
+
+2019-05-16 Jan Hubicka <hubicka@ucw.cz>
+
+ * tree-ssa-alias.c (alias_stats): Add
+ aliasing_component_refs_p_may_alias and
+ aliasing_component_refs_p_no_alias.
+ (dump_alias_stats): Print aliasing_component_refs_p stats.
+ (aliasing_component_refs_p): Update stats.
+
+2019-05-16 Martin Liska <mliska@suse.cz>
+
+ PR lto/90500
+ * multiple_target.c (expand_target_clones): Do not allow
+ target_clones being used with a symbol that is an alias.
+
+2019-05-16 Vladislav Ivanishin <vlad@ispras.ru>
+
+ PR tree-optimization/90394
+ * tree-ssa-uninit.c (is_pred_expr_subset_of): Potentially give false
+ positives rather than ICE for cases where (code2 == NE_EXPR
+ && code1 == BIT_AND_EXPR).
+
+2019-05-16 Jakub Jelinek <jakub@redhat.com>
+
+ PR fortran/90329
+ * tree-core.h (struct tree_decl_common): Document
+ decl_nonshareable_flag for PARM_DECLs.
+ * tree.h (DECL_HIDDEN_STRING_LENGTH): Define.
+ * calls.c (expand_call): Don't try tail call if caller
+ has any DECL_HIDDEN_STRING_LENGTH PARM_DECLs that are or might be
+ passed on the stack and callee needs to pass any arguments on the
+ stack.
+ * tree-streamer-in.c (unpack_ts_decl_common_value_fields): Use
+ else if instead of series of mutually exclusive ifs. Handle
+ DECL_HIDDEN_STRING_LENGTH for PARM_DECLs.
+ * tree-streamer-out.c (pack_ts_decl_common_value_fields): Likewise.
+
+ * lto-streamer.h (LTO_major_version): Bump to 9.
+
+2019-05-16 Jun Ma <JunMa@linux.alibaba.com>
+
+ PR tree-optimization/90106
+ * tree-call-cdce.c (shrink_wrap_one_built_in_call_with_conds): Add
+ new parameter as new internal function call, also move it to new
+ basic block.
+ (use_internal_fn): Pass internal function call to
+ shrink_wrap_one_built_in_call_with_conds.
+
+2019-05-15 Jakub Jelinek <jakub@redhat.com>
+
+ * omp-low.c (lower_rec_input_clauses): For if (0) or simdlen (1) set
+ max_vf to 1.
+ * omp-expand.c (expand_omp_simd): For if (0) or simdlen (1) clear
+ safelen_int and set loop->dont_vectorize.
+
+2019-05-15 H.J. Lu <hongjiu.lu@intel.com>
+
+ PR target/89021
+ * config/i386/i386-builtin.def: Enable MMX intrinsics with
+ SSE/SSE2/SSSE3.
+ * config/i386/i386-builtins.c (ix86_init_mmx_sse_builtins):
+ Likewise.
+ * config/i386/i386-expand.c (ix86_expand_builtin): Allow
+ SSE/SSE2/SSSE3 to emulate MMX intrinsics with TARGET_MMX_WITH_SSE.
+ * config/i386/mmintrin.h: Only require SSE2 if __MMX_WITH_SSE__
+ is defined.
+
+2019-05-15 H.J. Lu <hongjiu.lu@intel.com>
+
+ PR target/89021
+ * config/i386/mmx.md (*vec_dupv2sf): Changed to
+ define_insn_and_split to support SSE emulation.
+ (*vec_extractv2sf_0): Likewise.
+ (*vec_extractv2sf_1): Likewise.
+ (*vec_extractv2si_0): Likewise.
+ (*vec_extractv2si_1): Likewise.
+ (*vec_extractv2si_zext_mem): Likewise.
+ (vec_setv2sf): Also allow TARGET_MMX_WITH_SSE.
+ (vec_extractv2sf_1 splitter): Likewise.
+ (vec_extractv2sfsf): Likewise.
+ (vec_setv2si): Likewise.
+ (vec_extractv2si_1 splitter): Likewise.
+ (vec_extractv2sisi): Likewise.
+ (vec_setv4hi): Likewise.
+ (vec_extractv4hihi): Likewise.
+ (vec_setv8qi): Likewise.
+ (vec_extractv8qiqi): Likewise.
+ (vec_extractv2sfsf): Also allow TARGET_MMX_WITH_SSE. Pass
+ TARGET_MMX_WITH_SSE ix86_expand_vector_extract.
+ (vec_extractv2sisi): Likewise.
+ (vec_extractv4hihi): Likewise.
+ (vec_extractv8qiqi): Likewise.
+ (vec_initv2sfsf): Also allow TARGET_MMX_WITH_SSE. Pass
+ TARGET_MMX_WITH_SSE to ix86_expand_vector_init.
+ (vec_initv2sisi): Likewise.
+ (vec_initv4hihi): Likewise.
+ (vec_initv8qiqi): Likewise.
+ (vec_setv2si): Also allow TARGET_MMX_WITH_SSE. Pass
+ TARGET_MMX_WITH_SSE to ix86_expand_vector_set.
+ (vec_setv4hi): Likewise.
+ (vec_setv8qi): Likewise.
+
+2019-05-15 H.J. Lu <hongjiu.lu@intel.com>
+
+ PR target/89021
+ * config/i386/mmx.md (MMXMODE:mov<mode>): Also allow
+ TARGET_MMX_WITH_SSE.
+ (MMXMODE:*mov<mode>_internal): Likewise.
+ (MMXMODE:movmisalign<mode>): Likewise.
+
+2019-05-15 Uroš Bizjak <ubizjak@gmail.com>
+
+ PR target/89021
+ * config/i386/i386.md (*zero_extendsidi2): Add mmx_isa attribute.
+ * config/i386/sse.md (sse2_cvtpi2pd): Ditto.
+ (sse2_cvtpd2pi): Ditto.
+ (sse2_cvttpd2pi): Ditto.
+ (*vec_concatv2sf_sse4_1): Ditto.
+ (*vec_concatv2sf_sse): Ditto.
+ (*vec_concatv2si_sse4_1): Ditto.
+ (*vec_concatv2si): Ditto.
+ (*vec_concatv4si_0): Ditto.
+ (*vec_concatv2di_0): Ditto.
+
+2019-05-15 H.J. Lu <hongjiu.lu@intel.com>
+
+ PR target/89021
+ * config/i386/sse.md (abs<mode>2): Add SSE emulation.
+
+2019-05-15 H.J. Lu <hongjiu.lu@intel.com>
+
+ PR target/89021
+ * config/i386/sse.md (ssse3_palignrdi): Changed to
+ define_insn_and_split to support SSE emulation.
+
+2019-05-15 H.J. Lu <hongjiu.lu@intel.com>
+
+ PR target/89021
+ * config/i386/sse.md (ssse3_psign<mode>3): Add SSE emulation.
+
+2019-05-15 H.J. Lu <hongjiu.lu@intel.com>
+
+ PR target/89021
+ * config/i386/sse.md (ssse3_pshufbv8qi3): Changed to
+ define_insn_and_split. Also allow TARGET_MMX_WITH_SSE. Add
+ SSE emulation.
+
+2019-05-15 H.J. Lu <hongjiu.lu@intel.com>
+
+ PR target/89021
+ * config/i386/sse.md (ssse3_pmulhrswv4hi3): Require TARGET_MMX
+ or TARGET_MMX_WITH_SSE.
+ (*ssse3_pmulhrswv4hi3): Add SSE emulation.
+
+2019-05-15 H.J. Lu <hongjiu.lu@intel.com>
+
+ PR target/89021
+ * config/i386/sse.md (ssse3_pmaddubsw): Add SSE emulation.
+
+2019-05-15 H.J. Lu <hongjiu.lu@intel.com>
+
+ PR target/89021
+ * config/i386/sse.md (ssse3_ph<plusminus_mnemonic>dv2si3):
+ Changed to define_insn_and_split to support SSE emulation.
+
+2019-05-15 H.J. Lu <hongjiu.lu@intel.com>
+
+ PR target/89021
+ * config/i386/sse.md (ssse3_ph<plusminus_mnemonic>wv4hi3):
+ Changed to define_insn_and_split to support SSE emulation.
+
+2019-05-15 H.J. Lu <hongjiu.lu@intel.com>
+
+ PR target/89021
+ * config/i386/mmx.md (mmx_<emms>): Renamed to ...
+ (*mmx_<emms>): This.
+ (mmx_<emms>): New expander.
+
+2019-05-15 H.J. Lu <hongjiu.lu@intel.com>
+
+ PR target/89021
+ * config/i386/mmx.md (sse2_umulv1siv1di3): Add SSE emulation
+ support.
+ (*sse2_umulv1siv1di3): Add SSE2 emulation.
+
+2019-05-15 H.J. Lu <hongjiu.lu@intel.com>
+
+ PR target/89021
+ * config/i386/mmx.md (sse_movntq): Add SSE2 emulation.
+
+2019-05-15 H.J. Lu <hongjiu.lu@intel.com>
+
+ PR target/89021
+ * config/i386/mmx.md (mmx_psadbw): Add SSE emulation.
+
+2019-05-15 H.J. Lu <hongjiu.lu@intel.com>
+
+ PR target/89021
+ * config/i386/mmx.md (mmx_uavgv4hi3): Also check TARGET_MMX and
+ TARGET_MMX_WITH_SSE.
+ (*mmx_uavgv4hi3): Add SSE emulation.
+
+2019-05-15 H.J. Lu <hongjiu.lu@intel.com>
+
+ PR target/89021
+ * config/i386/mmx.md (mmx_uavgv8qi3): Also check TARGET_MMX
+ and TARGET_MMX_WITH_SSE.
+ (*mmx_uavgv8qi3): Add SSE emulation.
+
+2019-05-15 H.J. Lu <hongjiu.lu@intel.com>
+
+ PR target/89021
+ * config/i386/xmmintrin.h: Emulate MMX maskmovq with SSE2
+ maskmovdqu for __MMX_WITH_SSE__.
+
+2019-05-15 H.J. Lu <hongjiu.lu@intel.com>
+
+ PR target/89021
+ * config/i386/mmx.md (mmx_umulv4hi3_highpart): Also check
+ TARGET_MMX and TARGET_MMX_WITH_SSE.
+ (*mmx_umulv4hi3_highpart): Add SSE emulation.
+
+2019-05-15 H.J. Lu <hongjiu.lu@intel.com>
+
+ PR target/89021
+ * config/i386/mmx.md (mmx_pmovmskb): Changed to
+ define_insn_and_split to support SSE emulation.
+
+2019-05-15 H.J. Lu <hongjiu.lu@intel.com>
+
+ PR target/89021
+ * config/i386/mmx.md (mmx_<code>v4hi3): Also check TARGET_MMX
+ and TARGET_MMX_WITH_SSE.
+ (mmx_<code>v8qi3): Likewise.
+ (smaxmin:<code>v4hi3): New.
+ (umaxmin:<code>v8qi3): Likewise.
+ (smaxmin:*mmx_<code>v4hi3): Add SSE emulation.
+ (umaxmin:*mmx_<code>v8qi3): Likewise.
+
+2019-05-15 H.J. Lu <hongjiu.lu@intel.com>
+
+ PR target/89021
+ * config/i386/mmx.md (mmx_pinsrw): Also check TARGET_MMX and
+ TARGET_MMX_WITH_SSE.
+ (*mmx_pinsrw): Add SSE emulation.
+
+2019-05-15 H.J. Lu <hongjiu.lu@intel.com>
+
+ PR target/89021
+ * config/i386/mmx.md (mmx_pextrw): Add SSE emulation.
+
+2019-05-15 H.J. Lu <hongjiu.lu@intel.com>
+
+ PR target/89021
+ * config/i386/sse.md (sse_cvtpi2ps): Changed to
+ define_insn_and_split. Also allow TARGET_MMX_WITH_SSE. Add
+ SSE emulation.
+
+2019-05-15 H.J. Lu <hongjiu.lu@intel.com>
+
+ PR target/89021
+ * config/i386/sse.md (sse_cvtps2pi): Add SSE emulation.
+ (sse_cvttps2pi): Likewise.
+
+2019-05-15 H.J. Lu <hongjiu.lu@intel.com>
+
+ PR target/89021
+ * config/i386/mmx.md (mmx_pshufw): Also check TARGET_MMX and
+ TARGET_MMX_WITH_SSE.
+ (mmx_pshufw_1): Add SSE emulation.
+ (*vec_dupv4hi): Changed to define_insn_and_split and also allow
+ TARGET_MMX_WITH_SSE to support SSE emulation.
+
+2019-05-15 H.J. Lu <hongjiu.lu@intel.com>
+
+ PR target/89021
+ * config/i386/constraints.md (Yw): New constraint.
+ * config/i386/mmx.md (*vec_dupv2si): Changed to
+ define_insn_and_split and also allow TARGET_MMX_WITH_SSE to
+ support SSE emulation.
+
+2019-05-15 H.J. Lu <hongjiu.lu@intel.com>
+
+ PR target/89021
+ * config/i386/mmx.md (mmx_eq<mode>3): Also allow
+ TARGET_MMX_WITH_SSE.
+ (*mmx_eq<mode>3): Also allow TARGET_MMX_WITH_SSE. Add SSE
+ support.
+ (mmx_gt<mode>3): Likewise.
+
+2019-05-15 H.J. Lu <hongjiu.lu@intel.com>
+
+ PR target/89021
+ * config/i386/mmx.md (mmx_andnot<mode>3): Also allow
+ TARGET_MMX_WITH_SSE. Add SSE support.
+
+2019-05-15 H.J. Lu <hongjiu.lu@intel.com>
+
+ PR target/89021
+ * config/i386/mmx.md (any_logic:mmx_<code><mode>3): Also allow
+ TARGET_MMX_WITH_SSE.
+ (any_logic:<code><mode>3): New.
+ (any_logic:*mmx_<code><mode>3): Also allow TARGET_MMX_WITH_SSE.
+ Add SSE support.
+
+2019-05-15 H.J. Lu <hongjiu.lu@intel.com>
+
+ PR target/89021
+ * config/i386/mmx.md (mmx_ashr<mode>3): Also allow
+ TARGET_MMX_WITH_SSE. Add SSE emulation.
+ (mmx_<shift_insn><mode>3): Likewise.
+ (ashr<mode>3): New.
+ (<shift_insn><mode>3): Likewise.
+
+2019-05-15 H.J. Lu <hongjiu.lu@intel.com>
+
+ PR target/89021
+ * config/i386/mmx.md (mmx_pmaddwd): Also allow TARGET_MMX_WITH_SSE.
+ (*mmx_pmaddwd): Also allow TARGET_MMX_WITH_SSE. Add SSE support.
+
+2019-05-15 H.J. Lu <hongjiu.lu@intel.com>
+
+ PR target/89021
+ * config/i386/mmx.md (mmx_smulv4hi3_highpart): Also allow
+ TARGET_MMX_WITH_SSE.
+ (*mmx_smulv4hi3_highpart): Also allow TARGET_MMX_WITH_SSE. Add
+ SSE support.
+
+2019-05-15 H.J. Lu <hongjiu.lu@intel.com>
+
+ PR target/89021
+ * config/i386/mmx.md (mmx_mulv4hi3): Also allow
+ TARGET_MMX_WITH_SSE.
+ (mulv4hi3): New.
+ (*mmx_mulv4hi3): Also allow TARGET_MMX_WITH_SSE. Add SSE
+ support.
+
+2019-05-15 H.J. Lu <hongjiu.lu@intel.com>
+
+ PR target/89021
+ * config/i386/mmx.md (MMXMODEI8): Require TARGET_SSE2 for V1DI.
+ (plusminus:mmx_<plusminus_insn><mode>3): Check
+ TARGET_MMX_WITH_SSE.
+ (sat_plusminus:mmx_<plusminus_insn><mode>3): Likewise.
+ (<plusminus_insn><mode>3): New.
+ (*mmx_<plusminus_insn><mode>3): Add SSE emulation.
+ (*mmx_<plusminus_insn><mode>3): Likewise.
+
+2019-05-15 H.J. Lu <hongjiu.lu@intel.com>
+
+ PR target/89021
+ * config/i386/i386-expand.c (ix86_split_mmx_punpck): New function.
+ * config/i386/i386-protos.h (ix86_split_mmx_punpck): New
+ prototype.
+ * config/i386/mmx.m (mmx_punpckhbw): Changed to
+ define_insn_and_split to support SSE emulation.
+ (mmx_punpcklbw): Likewise.
+ (mmx_punpckhwd): Likewise.
+ (mmx_punpcklwd): Likewise.
+ (mmx_punpckhdq): Likewise.
+ (mmx_punpckldq): Likewise.
+
+2019-05-15 H.J. Lu <hongjiu.lu@intel.com>
+ Uros Bizjak <ubizjak@gmail.com>
+
+ PR target/89021
+ * config/i386/i386-expand.c (ix86_move_vector_high_sse_to_mmx):
+ New function.
+ (ix86_split_mmx_pack): Likewise.
+ * config/i386/i386-protos.h (ix86_move_vector_high_sse_to_mmx):
+ New prototype.
+ (ix86_split_mmx_pack): Likewise.
+ * config/i386/i386.md (mmx_isa): New.
+ (enabled): Also check mmx_isa.
+ * config/i386/mmx.md (any_s_truncate): New code iterator.
+ (s_trunsuffix): New code attr.
+ (mmx_packsswb): Removed.
+ (mmx_packssdw): Likewise.
+ (mmx_packuswb): Likewise.
+ (mmx_pack<s_trunsuffix>swb): New define_insn_and_split to emulate
+ MMX packsswb/packuswb with SSE2.
+ (mmx_packssdw): Likewise.
+ * config/i386/predicates.md (register_mmxmem_operand): New.
+
+2019-05-15 H.J. Lu <hongjiu.lu@intel.com>
+
+ PR target/89021
+ * config/i386/i386-c.c (ix86_target_macros_internal): Define
+ __MMX_WITH_SSE__ for TARGET_MMX_WITH_SSE.
+ * config/i386/i386.c (ix86_set_reg_reg_cost): Add support for
+ TARGET_MMX_WITH_SSE with VALID_MMX_REG_MODE.
+ (ix86_vector_mode_supported_p): Likewise.
+ * config/i386/i386.h (TARGET_MMX_WITH_SSE): New.
+
+2019-05-15 Martin Liska <mliska@suse.cz>
+
+ PR middle-end/90478
+ * tree-switch-conversion.c (jump_table_cluster::can_be_handled):
+ Check for overflow.
+
+2019-05-15 Richard Biener <rguenther@suse.de>
+
+ * tree-into-ssa.c (pass_build_ssa::execute): Run
+ update_address_taken before going into SSA.
+
+2019-05-15 Richard Biener <rguenther@suse.de>
+
+ * tree-pretty-print.c (dump_generic_node): Dump BIT_FIELD_REF
+ as __BIT_FIELD_REF with type with -gimple.
+
+2019-05-15 Vladislav Ivanishin <vlad@ispras.ru>
+
+ * tree-ssa-uninit.c (is_value_included_in): Remove is_unsigned and merge
+ semantically equivalent branches (left over after prior refactorings).
+
+2019-05-15 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/88828
+ * tree-ssa-forwprop.c (simplify_vector_constructor): Fix
+ bogus check.
+
+2019-05-14 Richard Biener <rguenther@suse.de>
+
+ * tree-pretty-print.c (dump_generic_node): Dump VIEW_CONVERT_EXPR
+ as __VIEW_CONVERT with -gimple.
+
+2019-05-12 Iain Sandoe <iain@sandoe.co.uk>
+
+ PR target/82920
+ * config/i386/darwin.h (CC1_SPEC): Report -mx32 as an error for
+ Darwin.
+
+2019-05-14 Segher Boessenkool <segher@kernel.crashing.org>
+
+ * config/rs6000/rs6000.md (eh_set_lr_<mode>): Merge with following
+ define_split to become a define_insn_and_split.
+
+2019-05-14 Segher Boessenkool <segher@kernel.crashing.org>
+
+ * config/rs6000/rs6000-protos.h (rs6000_emit_epilogue): Change
+ arguments.
+ * config/rs6000/rs6000.c (rs6000_emit_epilogue): Change arguments.
+ * config/rs6000/rs6000.md (epilogue_type): New define_enum.
+ (sibcall_epilogue): Adjust.
+ (epilogue): Adjust.
+
+2019-05-14 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE>
+
+ * config.gcc: Move *-*-solaris2.10* from obsolete configurations
+ to unsupported ones.
+ Simplify x86_64-*-solaris2.1[0-9]* to x86_64-*-solaris2*.
+ * config.host: Likewise.
+ * config/i386/sol2.h (ASM_COMMENT_START): Remove.
+ * config/sparc/driver-sparc.c (host_detect_local_cpu) [__sun__ &&
+ __svr4__]: Remove "brand" fallback.
+ [!KSTAT_DATA_STRING]: Remove.
+ * configure.ac (gcc_cv_ld_hidden): Simplify *-*-solaris2.1[0-9]*
+ to *-*-solaris2*.
+ (comdat_group): Likewise.
+ (set_have_as_tls): Likewise.
+ (gcc_cv_target_dl_iterate_phdr): Likewise.
+ (gcc_cv_as_shf_merge): Remove Solaris 10/x86 workaround.
+ (gcc_cv_ld_aligned_shf_merge): Remove Solaris 10/SPARC workaround.
+ * configure: Regenerate.
+ * doc/install.texi: Simplify Solaris target triplets.
+ (Specific, i?86-*-solaris2*): Remove Solaris 10 references.
+ (Specific, *-*-solaris2*): Document Solaris 10 removal.
+ Remove Solaris 10 references.
+ Remove obsolete Solaris bug reference.
+ (Specific, sparc-sun-solaris2.10): Remove.
+
+2019-05-14 Uroš Bizjak <ubizjak@gmail.com>
+
+ * config/i386/i386.md (any_div): New code iterator.
+ (paired_mod): New code attribute.
+ (sgnprefix): Handle DIV and UDIV RTXes.
+ (u): Ditto.
+ (<u>divmod<mode>4): Macroize expander from divmod<mode>4
+ and udivmod<mode>4 patterns using any_div code iterator.
+ (divmod splitters): Macroize splitters using any_div code iterator.
+ (*udivmodsi4_pow2_zext_1): Use exactl_log2 in insn condition.
+ (*udivmodsi4_pow2_zext_2): Ditto.
+ (*<u>divmod<mode>4_noext): Macroize insn from *divmod<mode>4_noext
+ and *udivmod<mode>4_noext patterns using any_div code iterator.
+ (*<u>divmod<mode>4_noext_zext_1): Macroize insn from
+ *divmod<mode>4_noext_zext_1 and *udivmod<mode>4_noext_zext_1
+ patterns using any_div code iterator.
+ (*<u>divmod<mode>4_noext_zext_2): Macroize insn from
+ *divmod<mode>4_noext_zext_2 and *udivmod<mode>4_noext_zext_2
+ patterns using any_div code iterator.
+ (<u>divmodhiqi3): Macroize insn from divmodhiqi3 and
+ udivmodhiqi3 patterns using any_extend code iterator.
+
+2019-05-14 Richard Biener <rguenther@suse.de>
+ H.J. Lu <hongjiu.lu@intel.com>
+
+ PR tree-optimization/88828
+ * tree-ssa-forwprop.c (simplify_vector_constructor): Handle
+ permuting in a single non-constant element not extracted
+ from a vector.
+
+2019-05-14 Przemyslaw Wirkus <przemyslaw.wirkus@arm.com>
+
+ * internal-fn.def (SIGNBIT): New.
+ * config/aarch64/aarch64-simd.md (signbitv2sf2): New expand
+ defined.
+ (signbitv4sf2): Likewise.
+
+2019-05-14 Chenghua Xu <paul.hua.gm@gmail.com>
+
+ PR target/90357
+ * config/mips/mips.c (mips_split_move): Skip forward SRC into
+ next insn when the SRC reg is dead.
+
+2019-05-14 Bin Cheng <bin.cheng@linux.alibaba.com>
+
+ * gimple-ssa-strength-reduction.c (lookup_cand): Adjust index by 1.
+ (alloc_cand_and_find_basis): Ditto.
+ (backtrace_base_for_ref, create_mul_ssa_cand): Remove if-then-else.
+ (create_mul_imm_cand, create_add_ssa_cand): Ditto.
+ (create_add_imm_cand, slsr_process_cast): Ditto.
+ (slsr_process_copy, replace_mult_candidate): Ditto.
+ (replace_rhs_if_not_dup, replace_one_candidate): Ditto.
+ (dump_cand_vec, analyze_candidates_and_replace): Skip NULL element.
+ (pass_strength_reduction::execute): Init the first NULL element.
+
+2019-05-13 Nathan Sidwell <nathan@acm.org>
+
+ * gcc.c (execute): Simplify cond-expr into if. Reformat comment.
+ (run_attempt): Reformat line break.
+
+2019-05-13 David Edelsohn <dje.gcc@gmail.com>
+
+ PR target/90418
+ * config/rs6000/rs6000.c (rs6000_emit_epilogue): Don't load EH
+ data registers in sibcall epilogues.
+ Don't add EH_RETURN_STACKADJ_RTX to sp in sibcall epilogues.
+
+2019-05-13 Uroš Bizjak <ubizjak@gmail.com>
+
+ PR target/89221
+ * configure.ac (--enable-frame-pointer):
+ Disable by default for cygwin and mingw.
+ * configure: Regenerate.
+
+2019-05-13 Nathan Sidwell <nathan@acm.org>
+
+ * dwarf2out.c (breakout_comdat_types): Move comment to correct
+ piece of code.
+ (const_ok_for_output_1): Balance parens around #if/#else/#endif
+ (gen_member_die): Move abstract origin check earlier. Only VARs
+ can be static_inline_p. Simplify splicing control flow.
+
+2019-05-13 Richard Biener <rguenther@suse.de>
+
+ * tree-vect-slp.c (vect_get_and_check_slp_defs): Handle
+ VIEW_CONVERT_EXPR.
+ (vect_build_slp_tree_1): Likewise.
+
+2019-05-13 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/90402
+ * tree-if-conv.c (tree_if_conversion): Value number only
+ the loop body by making the latch an exit of the region
+ as well.
+ * tree-ssa-sccvn.c (process_bb): Add flag whether to skip
+ processing PHIs.
+ (do_rpo_vn): Deal with multiple edges into the entry block
+ that are not backedges inside the region by skipping PHIs
+ of the entry block.
+
+2019-05-13 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/90316
+ * tree-ssa-pre.c (insert_aux): Fold into ...
+ (insert): ... this function. Use a RPO walk to reduce the
+ number of required iterations.
+
+2019-05-13 Martin Liska <mliska@suse.cz>
+
+ PR tree-optimization/90416
+ * tree-vect-stmts.c (vect_check_load_store_mask): Concatenate
+ string instead of passing the second part as va_arg argument.
+
+2019-05-13 Martin Liska <mliska@suse.cz>
+
+ PR gcov-profile/90380
+ * gcov.c (handle_cycle): Do not support zero cycle count,
+ it should not be possible.
+ (path_contains_zero_cycle_arc): New function.
+ (circuit): Ignore zero cycle arc counts.
+
+2019-05-13 Martin Liska <mliska@suse.cz>
+
+ PR gcov-profile/90380
+ * gcov.c (enum loop_type): Remove the enum and
+ the operator.
+ (handle_cycle): Assert that we should not reach
+ a negative count.
+ (circuit): Use loop_found instead of a tri-state loop_type.
+ (get_cycles_count): Do not handle NEGATIVE_LOOP as it can't
+ happen.
+
+2019-05-12 Iain Sandoe <iain@sandoe.co.uk>
+
+ PR target/82920
+ * config/i386/i386.c (ix86_output_jmp_thunk_or_indirect): New.
+ (ix86_output_indirect_branch_via_reg): Use output mechanism
+ accounting for __USER_LABEL_PREFIX__.
+ (ix86_output_indirect_branch_via_push): Likewise.
+ (ix86_output_function_return): Likewise.
+ (ix86_output_indirect_function_return): Likewise.
+
+2019-05-12 Richard Sandiford <richard.sandiford@arm.com>
+
+ * doc/md.texi: Document use of code attributes in rtx patterns.
+ * read-md.h (rtx_reader::rtx_alloc_for_name): New member function.
+ * read-rtl.c (find_code): Split out search loops into...
+ (maybe_find_code): ...this new function.
+ (check_code_iterator): Make the error message more informative.
+ (check_code_attribute): New function.
+ (rtx_reader::rtx_alloc_for_name): Likewise.
+ (rtx_reader::read_rtx_code): Use rtx_alloc_for_name.
+ * config/aarch64/predicates.md (aarch64_smin, aarch64_umin): Delete.
+ * config/aarch64/aarch64-simd.md (*aarch64_<su>abd<mode>_3): Use
+ <max_opp> directly as an rtx code instead of via a match_operator.
+ * config/aarch64/aarch64-sve.md (aarch64_<su>abd<mode>_3): Likewise.
+ (<su>abd<mode>_3): Update accordingly.
+
+2019-05-12 Iain Sandoe <iain@sandoe.co.uk>
+
+ * config/rs6000/rs6000.c (debug_stack_info): When -mdebug=stack
+ is given, print the state of the EH "save world" computation for
+ Darwin.
+
+2019-05-11 Jakub Jelinek <jakub@redhat.com>
+
+ PR c++/59813
+ * config/aarch64/aarch64.c (aarch64_expand_epilogue): Don't add
+ EH_RETURN_STACKADJ_RTX to sp in sibcall epilogues.
+
+2019-05-11 Uroš Bizjak <ubizjak@gmail.com>
+
+ * config/i386/i386.md (floatdi<X87MODEF:mode>2_i387_with_xmm):
+ Use pinsrd for TARGET_SSE4_1.
+ * config/i386/sse.md (movdi_to_sse): Ditto.
+
+2019-05-10 Richard Biener <rguenther@suse.de>
+
+ * tree-ssa-sccvn.c (visit_reference_op_call): Initialize value-id.
+ (do_rpo_vn): Initialize next_value_id.
+
+2019-05-10 Martin Liska <mliska@suse.cz>
+
+ * params.def (PARAM_GIMPLE_FE_COMPUTED_HOT_BB_THRESHOLD):
+ Fix plural form.
+
+2019-05-10 Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/90385
+ * tree-parloops.c (try_create_reduction_list): Punt on non-SSA_NAME
+ arguments of the exit phis.
+
+ PR c++/90383
+ * tree-inline.h (struct copy_body_data): Add do_not_fold member.
+ * tree-inline.c (remap_gimple_op_r): Avoid folding expressions if
+ id->do_not_fold.
+ (copy_tree_body_r): Likewise.
+ (copy_fn): Set id.do_not_fold to true.
+
+2019-05-10 Martin Liska <mliska@suse.cz>
+
+ * config/i386/i386-expand.c (ix86_expand_floorceildf_32):
+ Reapply changes from r269790.
+
+2019-05-10 Martin Liska <mliska@suse.cz>
+
+ PR middle-end/90340
+ * doc/invoke.texi: New params.
+ * params.def (PARAM_JUMP_TABLE_MAX_GROWTH_RATIO_FOR_SIZE): New.
+ (PARAM_JUMP_TABLE_MAX_GROWTH_RATIO_FOR_SPEED): Likewise.
+ * tree-switch-conversion.c (jump_table_cluster::can_be_handled):
+ Use it.
+ * tree-switch-conversion.h (struct jump_table_cluster):
+ Likewise.
+
+2019-05-09 Segher Boessenkool <segher@kernel.crashing.org>
+
+ * combine.c (combine_simplify_rtx): Don't make IF_THEN_ELSE RTL.
+
+2019-05-09 Bill Schmidt <wschmidt@linux.ibm.com>
+
+ * doc/loop.texi: Remove reference to FOR_EACH_LOOP_BREAK.
+
2019-05-09 Alexander Monakov <amonakov@ispras.ru>
PR rtl-optimization/88879
@@ -308,6 +5911,14 @@
* tree-ssa-phiopt.c (two_value_replacement): Fix a typo in parameter
detection.
+2019-05-06 H.J. Lu <hongjiu.lu@intel.com>
+ Hongtao Liu <hongtao.liu@intel.com>
+
+ PR target/89750
+ PR target/86444
+ * config/i386/i386-expand.c (ix86_expand_sse_comi_round):
+ Modified, original implementation isn't correct.
+
2019-05-06 Segher Boessenkool <segher@kernel.crashing.org>
* config/rs6000/rs6000.md (FIRST_ALTIVEC_REGNO, LAST_ALTIVEC_REGNO)
@@ -488,7 +6099,6 @@
and macros.
* config/i386/t-i386: Define dependencies for new files.
->>>>>>> .r270937
2019-05-03 Richard Earnshaw <rearnsha@arm.com>
PR target/89400
@@ -5684,6 +11294,37 @@
* tree-ssa-dom.c (test_for_singularity): Fix a comment typo.
* vr-values.c (find_case_label_ranges): Fix a comment typo.
+2019-01-23 Xuepeng Guo <xuepeng.guo@intel.com>
+
+ * common/config/i386/i386-common.c
+ (OPTION_MASK_ISA_ENQCMD_SET,
+ OPTION_MASK_ISA_ENQCMD_UNSET): New macros.
+ (ix86_handle_option): Handle -menqcmd.
+ * config.gcc (enqcmdintrin.h): New header file.
+ * config/i386/cpuid.h (bit_ENQCMD): New bit.
+ * config/i386/driver-i386.c (host_detect_local_cpu): Handle
+ -menqcmd.
+ * config/i386/i386-builtin-types.def ((INT, PVOID, PCVOID)): New
+ function type.
+ * config/i386/i386-builtin.def (__builtin_ia32_enqcmd,
+ __builtin_ia32_enqcmds): New builtins.
+ * config/i386/i386-c.c (__ENQCMD__): New macro.
+ * config/i386/i386-option.c (ix86_target_string): Add
+ -menqcmd.
+ (ix86_valid_target_attribute_inner_p): Likewise.
+ * config/i386/i386-expand.c
+ (ix86_expand_builtin): Expand IX86_BUILTIN_ENQCMD and
+ IX86_BUILTIN_ENQCMDS.
+ * config/i386/i386.h (TARGET_ENQCMD): New.
+ * config/i386/i386.md (UNSPECV_ENQCMD, UNSPECV_ENQCMDS): New.
+ (@enqcmd<enqcmd_sfx>_<mode>): New insn pattern.
+ (movdir64b_<mode>): Parameterize to enable share expansion code
+ with ENQCMD in function ix86_expand_builtin.
+ * config/i386/i386.opt: Add -menqcmd.
+ * config/i386/immintrin.h: Include enqcmdintrin.h.
+ * config/i386/enqcmdintrin.h: New intrinsic file.
+ * doc/invoke.texi: Add -menqcmd.
+
2019-01-23 Bin Cheng <bin.cheng@arm.com>
Steve Ellcey <sellcey@marvell.com>
diff --git a/gcc/ChangeLog-2018 b/gcc/ChangeLog-2018
index ced3782..a6a4011 100644
--- a/gcc/ChangeLog-2018
+++ b/gcc/ChangeLog-2018
@@ -836,6 +836,8 @@
substituting by zero.
2018-12-17 Richard Sandiford <richard.sandiford@arm.com>
+ Ramana Radhakrishnan <ramana.radhakrishnan@arm.com>
+ Kyrylo Tkachov <kyrylo.tkachov@arm.com>
* doc/invoke.texi (-fversion-loops-for-strides): Document
(loop-versioning-group-size, loop-versioning-max-inner-insns)
diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP
index fab1183..905e21d 100644
--- a/gcc/DATESTAMP
+++ b/gcc/DATESTAMP
@@ -1 +1 @@
-20190509
+20190703
diff --git a/gcc/Makefile.in b/gcc/Makefile.in
index 6677f77..597dc01 100644
--- a/gcc/Makefile.in
+++ b/gcc/Makefile.in
@@ -1065,7 +1065,7 @@ BUILD_LIBDEPS= $(BUILD_LIBIBERTY)
LIBS = @LIBS@ libcommon.a $(CPPLIB) $(LIBINTL) $(LIBICONV) $(LIBBACKTRACE) \
$(LIBIBERTY) $(LIBDECNUMBER) $(HOST_LIBS)
BACKENDLIBS = $(ISLLIBS) $(GMPLIBS) $(PLUGINLIBS) $(HOST_LIBS) \
- $(ZLIB)
+ $(ZLIB) $(ZSTD_LIB)
# Any system libraries needed just for GNAT.
SYSLIBS = @GNAT_LIBEXC@
@@ -1076,6 +1076,8 @@ GNATMAKE = @GNATMAKE@
# Libs needed (at present) just for jcf-dump.
LDEXP_LIB = @LDEXP_LIB@
+ZSTD_LIB = @ZSTD_LIB@
+
# Likewise, for use in the tools that must run on this machine
# even if we are cross-building GCC.
BUILD_LIBS = $(BUILD_LIBIBERTY)
@@ -2802,11 +2804,11 @@ genprogmd = $(genprogrtl) mddeps constants enums
$(genprogmd:%=build/gen%$(build_exeext)): $(BUILD_MD)
# All these programs need to report errors.
-genprogerr = $(genprogmd) genrtl modes gtype hooks cfn-macros
+genprogerr = $(genprogmd) genrtl modes gtype hooks cfn-macros condmd
$(genprogerr:%=build/gen%$(build_exeext)): $(BUILD_ERRORS)
# Remaining build programs.
-genprog = $(genprogerr) check checksum condmd match
+genprog = $(genprogerr) check checksum match
# These programs need libs over and above what they get from the above list.
build/genautomata$(build_exeext) : BUILD_LIBS += -lm
diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog
index 9116b92..c28a942 100644
--- a/gcc/ada/ChangeLog
+++ b/gcc/ada/ChangeLog
@@ -1,3 +1,819 @@
+2019-07-03 Bob Duff <duff@adacore.com>
+
+ * doc/gnat_ugn/gnat_utility_programs.rst: Document new flags in
+ GNATpp.
+
+2019-07-03 Hristian Kirtchev <kirtchev@adacore.com>
+
+ * binde.adb: Remove with clause for System.OS_Lib.
+ (Force_Elab_Order): Refactor the majority of the code in Butil.
+ Use the new forced units iterator to obtain unit names.
+ * bindo-builders.adb: Add with and use clauses for Binderr,
+ Butil, Opt, Output, Types, GNAT, and GNAT.Dynamic_HTables. Add
+ a hash table which maps units to line number in the forced
+ elaboration order file.
+ (Add_Unit): New routine.
+ (Build_Library_Graph): Create forced edges between pairs of
+ units listed in the forced elaboration order file.
+ (Create_Forced_Edge, Create_Forced_Edges, Destroy_Line_Number,
+ Duplicate_Unit_Error, Hash_Unit, Internal_Unit_Info,
+ Is_Duplicate_Unit, Missing_Unit_Info): New routines.
+ * bindo-graphs.adb (Is_Internal_Unit, Is_Predefined_Unit):
+ Refactor some of the behavior to Bindo-Units.
+ * bindo-graphs.ads: Enable the enumeration literal for forced
+ edges.
+ * bindo-units.adb, bindo-units.ads (Is_Internal_Unit,
+ Is_Predefined_Unit): New routines.
+ * butil.adb: Add with and use clauses for Opt, GNAT, and
+ System.OS_Lib. Add with clause for Unchecked_Deallocation.
+ (Has_Next, Iterate_Forced_Units, Next, Parse_Next_Unit_Name,
+ Read_Forced_Elab_Order_File): New routines.
+ * butil.ads: Add with and use clauses for Types. Add new
+ iterator over the units listed in the forced elaboration order
+ file.
+ (Has_Next, Iterate_Forced_Units, Next): New routine.
+ * namet.adb, namet.ads (Present): New routine.
+
+2019-07-03 Bob Duff <duff@adacore.com>
+
+ * sem_ch3.adb (Access_Definition): The code was creating a
+ master in the case where the designated type is a class-wide
+ interface type. Create a master in the noninterface case as
+ well. That is, create a master for all limited class-wide types.
+
+2019-07-03 Yannick Moy <moy@adacore.com>
+
+ * erroutc.adb (Sloc_In_Range): New function to determine whether
+ the range of a pragma Warnings covers a location, taking
+ instantiations into account.
+
+2019-07-03 Johannes Kanig <kanig@adacore.com>
+
+ * osint.ads, osint.adb (Get_First_Main_File_Name): New routine
+ to access the first file provided on the command line.
+
+2019-07-03 Ed Schonberg <schonberg@adacore.com>
+
+ * inline.adb (Process_Formals_In_Aspects): New procedure within
+ Expand_Inlined_Call, to perform a replacement of references to
+ formals that appear in aspect specifications within the body
+ being inlined.
+
+2019-07-03 Justin Squirek <squirek@adacore.com>
+
+ * sem_ch8.adb (Analyze_Object_Renaming): Add call to search for
+ the appropriate actual subtype of the object renaming being
+ analyzed.
+ (Check_Constrained_Object): Minor cleanup.
+
+2019-07-03 Yannick Moy <moy@adacore.com>
+
+ * sem_spark.adb (Get_Observed_Or_Borrowed_Expr): New function to
+ return go through traversal function call.
+ (Check_Type): Consistently use underlying type.
+ (Get_Perm): Adapt for case of elaboration code where variables
+ are not declared in the environment. Remove incorrect handling
+ of borrow and observe.
+
+2019-07-03 Hristian Kirtchev <kirtchev@adacore.com>
+
+ * inline.adb (Build_Return_Object_Formal): New routine.
+ (Can_Split_Unconstrained_Function): Code clean up.
+ (Copy_Formals,Copy_Return_Object): New routines.
+ (Split_Unconstrained_Function): Code clean up and refactoring.
+
+2019-07-03 Gary Dismukes <dismukes@adacore.com>
+
+ * bindo-augmentors.adb, bindo-augmentors.ads,
+ bindo-builders.ads, bindo-elaborators.adb, sem_ch12.adb,
+ sem_ch13.adb, sem_spark.adb, sinfo.ads: Minor editorial
+ corrections and reformatting.
+
+2019-07-03 Bob Duff <duff@adacore.com>
+
+ * sem_warn.adb (Check_Infinite_Loop_Warning): Avoid the warning
+ if an Iterator_Specification is present.
+
+2019-07-03 Bob Duff <duff@adacore.com>
+
+ * doc/gnat_ugn/gnat_utility_programs.rst: Document default
+ new-line behavior.
+
+2019-07-03 Hristian Kirtchev <kirtchev@adacore.com>
+
+ * ali.adb: Add with and use clauses for GNAT,
+ GNAT.Dynamic_HTables, and Snames. Add a map from invocation
+ signature records to invocation signature ids. Add various
+ encodings of invocation-related attributes. Sort and update
+ table Known_ALI_Lines.
+ (Add_Invocation_Construct, Add_Invocation_Relation,
+ Body_Placement_Kind_To_Code, Code_To_Body_Placement_Kind,
+ Code_To_Invocation_Construct_Kind, Code_To_Invocation_Kind,
+ Code_To_Invocation_Graph_Line_Kind, Destroy, Hash): New
+ routines.
+ (Initialize_ALI): Sort the initialization sequence. Add
+ initialization for all invocation-related tables.
+ (Invocation_Construct_Kind_To_Code,
+ Invocation_Graph_Line_Kind_To_Code, Invocation_Kind_To_Code,
+ Invocation_Signature_Of, Present): New routines.
+ (Scan_ALI): Add the default values for invocation-related ids.
+ Scan invocation graph lines.
+ (Scan_Invocation_Graph_Line): New routine.
+ * ali.ads: Add with clause for GNAT.Dynamic_Tables. Add types
+ for invocation constructs, relations, and signatures. Add
+ tables for invocation constructs, relations, and signatures.
+ Update Unit_Record to capture invocation-related ids. Relocate
+ table Unit_Id_Tables and subtypes Unit_Id_Table, Unit_Id_Array
+ from Binde.
+ (Add_Invocation_Construct, Add_Invocation_Relation,
+ Body_Placement_Kind_To_Code, Code_To_Body_Placement_Kind,
+ Code_To_Invocation_Construct_Kind, Code_To_Invocation_Kind,
+ Code_To_Invocation_Graph_Line_Kind,
+ Invocation_Construct_Kind_To_Code,
+ Invocation_Graph_Line_Kind_To_Code, Invocation_Kind_To_Code,
+ Invocation_Signature_Of, Present): New routines.
+ * binde.adb: Add with and use clause for Types. Add use clause
+ for ALI.Unit_Id_Tables;
+ * binde.ads: Relocate table Unit_Id_Tables and subtypes
+ Unit_Id_Table, Unit_Id_Array to ALI.
+ * bindgen.adb: Remove with and use clause for ALI.
+ * bindgen.ads: Remove with and use clause for Binde. Add with
+ and use clause for ALI.
+ * bindo.adb, bindo.ads, bindo-augmentors.adb,
+ bindo-augmentors.ads, bindo-builders.adb, bindo-builders.ads,
+ bindo-diagnostics.adb, bindo-diagnostics.ads,
+ bindo-elaborators.adb, bindo-elaborators.ads, bindo-graphs.adb,
+ bindo-graphs.ads, bindo-units.adb, bindo-units.ads,
+ bindo-validators.adb, bindo-validators.ads, bindo-writers.adb,
+ bindo-writers.ads: New units.
+ * debug.adb: Use and describe GNAT debug switches -gnatd_F and
+ -gnatd_G. Add GNATbind debug switches in the ranges dA .. dZ,
+ d.a .. d.z, d.A .. d.Z, d.1 .. d.9, d_a .. d_z, d_A .. d_Z, and
+ d_1 .. d_9. Use and describe GNATbind debug switches -d_A,
+ -d_I, -d_L, -d_N, -d_O, -d_T, and -d_V.
+ * exp_util.adb, exp_util.ads (Exceptions_OK): Relocate to
+ Sem_Util.
+ * gnatbind.adb: Add with and use clause for Bindo. Use the new
+ Bindo elaboration order only when -d_N is in effect.
+ * lib-writ.adb
+ (Column, Extra, Invoker, Kind, Line, Locations, Name, Placement,
+ Scope, Signature, Target): New routines.
+ (Write_ALI): Output all invocation-related data.
+ (Write_Invocation_Graph): New routine.
+ * lib-writ.ads: Document the invocation graph ALI line.
+ * namet.adb, namet.ads (Present): New routines.
+ * sem_ch8.adb (Find_Direct_Name): Capture the status of
+ elaboration checks and warnings of an identifier.
+ (Find_Expanded_Name): Capture the status of elaboration checks
+ and warnings of an expanded name.
+ * sem_ch12.adb (Analyze_Generic_Package_Declaration): Ensure
+ that invocation graph-related data within the body of the main
+ unit is encoded in the ALI file.
+ (Analyze_Generic_Subprogram_Declaration): Ensure that invocation
+ graph-related data within the body of the main unit is encoded
+ in the ALI file.
+ (Analyze_Package_Instantiation): Perform minimal decoration of
+ the instance entity.
+ (Analyze_Subprogram_Instantiation): Perform minimal decoration
+ of the instance entity.
+ * sem_elab.adb: Perform heavy refactoring of all code. The unit
+ is now split into "services" which specialize in one area of ABE
+ checks. Add processing in order to capture invocation-graph
+ related attributes of the main unit, and encode them in the ALI
+ file. The Processing phase can now operate in multiple modes,
+ all described by type Processing_Kind. Scenarios and targets
+ are now distinct at the higher level, and carry their own
+ representations. This eliminates the need to constantly
+ recompute their attributes, and offers the various processors a
+ uniform interface. The various initial states of the Processing
+ phase are now encoded using type Processing_In_State, and
+ xxx_State constants.
+ * sem_elab.ads: Update the literals of type
+ Enclosing_Level_Kind. Add Inline pragmas on several routines.
+ * sem_prag.adb (Process_Inline): Ensure that invocation
+ graph-related data within the body of the main unit is encoded
+ in the ALI file.
+ * sem_util.adb (Enclosing_Generic_Body, Enclosing_Generic_Unit):
+ Code clean up.
+ (Exceptions_OK): Relocated from Sem_Util.
+ (Mark_Save_Invocation_Graph_Of_Body): New routine.
+ * sem_util.ads (Exceptions_OK): Relocated from Sem_Util.
+ (Mark_Save_Invocation_Graph_Of_Body): New routine.
+ * sinfo.adb (Is_Elaboration_Checks_OK_Node): Now applicable to
+ N_Variable_Reference_Marker.
+ (Is_Elaboration_Warnings_OK_Node): Now applicable to
+ N_Expanded_Name, N_Identifier, N_Variable_Reference_Marker.
+ (Is_Read): Use Flag4.
+ (Is_SPARK_Mode_On_Node): New applicable to
+ N_Variable_Reference_Marker.
+ (Is_Write): Use Flag5.
+ (Save_Invocation_Graph_Of_Body): New routine.
+ (Set_Is_Elaboration_Checks_OK_Node): Now applicable to
+ N_Variable_Reference_Marker.
+ (Set_Is_Elaboration_Warnings_OK_Node): Now applicable to
+ N_Expanded_Name, N_Identifier, N_Variable_Reference_Marker.
+ (Set_Is_SPARK_Mode_On_Node): New applicable to
+ N_Variable_Reference_Marker.
+ (Set_Save_Invocation_Graph_Of_Body): New routine.
+ * sinfo.ads: Update the documentation of attributes
+ Is_Elaboration_Checks_OK_Node, Is_Elaboration_Warnings_OK_Node,
+ Is_SPARK_Mode_On_Node. Update the flag usage of attributes
+ Is_Read, Is_Write. Add attribute Save_Invocation_Graph_Of_Body
+ and update its occurrence in nodes.
+ (Save_Invocation_Graph_Of_Body): New routine along with pragma
+ Inline.
+ (Set_Save_Invocation_Graph_Of_Body): New routine along with
+ pragma Inline.
+ * switch-b.adb (Scan_Binder_Switches): Refactor the scanning of
+ debug switches.
+ (Scan_Debug_Switches): New routine.
+ * libgnat/g-dynhta.adb, libgnat/g-dynhta.ads (Contains): New routine.
+ * libgnat/g-graphs.adb (Associate_Vertices): Update the use of
+ Component_Vertex_Iterator.
+ (Contains_Component, Contains_Edge, Contains_Vertex, Has_Next):
+ Reimplemented.
+ (Iterate_Component_Vertices): New routine.
+ (Iterate_Vertices): Removed.
+ (Next): Update the parameter profile.
+ (Number_Of_Component_Vertices, Number_Of_Outgoing_Edges): New
+ routines.
+ * libgnat/g-graphs.ads: Update the initialization of
+ No_Component. Add type Component_Vertex_Iterator. Remove type
+ Vertex_Iterator.
+ (Has_Next): Add new versions and remove old ones.
+ (Iterate_Component_Vertices): New routine.
+ (Iterate_Vertices): Removed.
+ (Next): Add new versions and remove old ones.
+ (Number_Of_Component_Vertices, Number_Of_Outgoing_Edges): New
+ routines.
+ * libgnat/g-sets.adb (Contains): Reimplemented.
+ * gcc-interface/Make-lang.in (GNATBIND_OBJS): Add
+ GNAT.Dynamic_HTables, GNAT.Graphs and Bindo units.
+ * rtsfind.ads: Remove extra space.
+
+2019-07-03 Yannick Moy <moy@adacore.com>
+
+ * sem_spark.adb: Add support for locally borrowing and observing
+ a path.
+ (Get_Root_Object): Add parameter Through_Traversal to denote
+ when we are interesting in getting to the traversed parameter.
+ (Is_Prefix_Or_Almost): New function to support detection of
+ illegal access to borrowed or observed paths.
+ (Check_Pragma): Add analysis of assertion pragmas.
+
+2019-07-03 Ed Schonberg <schonberg@adacore.com>
+
+ * sem_ch13.adb (Build_Predicate_Functions): In a generic context
+ we do not build the bodies of predicate fuctions, but the
+ expression in a static predicate must be elaborated to allow
+ case coverage checking within the generic unit.
+ (Build_Discrete_Static_Predicate): In a generic context, return
+ without building function body once the
+ Static_Discrete_Predicate expression for the type has been
+ constructed.
+
+2019-07-03 Hristian Kirtchev <kirtchev@adacore.com>
+
+ * bindgen.adb, inline.adb, layout.adb, sem_ch12.adb,
+ sem_ch13.adb, sem_ch7.adb, styleg.adb: Minor reformatting.
+
+2019-07-03 Bob Duff <duff@adacore.com>
+
+ * par-ch3.adb (P_Defining_Identifier): Call
+ Check_Defining_Identifier_Casing.
+ * style.ads, styleg.ads, styleg.adb
+ (Check_Defining_Identifier_Casing): New procedure to check for
+ mixed-case defining identifiers.
+ * stylesw.ads, stylesw.adb (Style_Check_Mixed_Case_Decls): New
+ flag for checking for mixed-case defining identifiers.
+ * doc/gnat_ugn/building_executable_programs_with_gnat.rst:
+ Document new feature.
+ * gnat_ugn.texi: Regenerate.
+
+2019-07-03 Eric Botcazou <ebotcazou@adacore.com>
+
+ * doc/gnat_ugn/building_executable_programs_with_gnat.rst
+ (Warning message control): Document that -gnatw.z/Z apply to
+ array types.
+ * freeze.adb (Freeze_Entity): Give -gnatw.z warning for array
+ types as well, but not if the specified alignment is the minimum
+ one.
+ * gnat_ugn.texi: Regenerate.
+
+2019-07-03 Bob Duff <duff@adacore.com>
+
+ * einfo.ads, exp_util.adb, layout.ads, sinfo.ads: Spell "laid"
+ correctly.
+
+2019-07-03 Ed Schonberg <schonberg@adacore.com>
+
+ * sem_ch13.adb (Analyze_Attribute_Definition_Clause): No error
+ message on attribute applied to a renaming when the renamed
+ object is an aggregate (from code reading).
+ (Check_Aspect_At_End_Of_Declarations): In a generic context
+ where freeze nodes are not generated, the original expression
+ for an aspect may need to be analyzed to precent spurious
+ conformance errors when compared with the expression that is
+ anakyzed at the end of the current declarative list.
+
+2019-07-03 Eric Botcazou <ebotcazou@adacore.com>
+
+ * layout.adb (Layout_Type): Do not set the component size of an
+ array with a scalar component if the component type is
+ overaligned.
+
+2019-07-03 Ed Schonberg <schonberg@adacore.com>
+
+ * inline.adb (Make_Loop_Labels_Unique): New procedure to modify
+ the source code of subprograms that are inlined by the
+ front-end, to prevent accidental duplication between loop labels
+ in the inlined code and the code surrounding the inlined call.
+
+2019-07-03 Hristian Kirtchev <kirtchev@adacore.com>
+
+ * doc/gnat_ugn/elaboration_order_handling_in_gnat.rst: Update
+ the section on resolving elaboration circularities to eliminate
+ certain combinations of switches which together do not produce
+ the desired effect and confuse users.
+ * gnat_ugn.texi: Regenerate.
+
+2019-07-03 Arnaud Charlet <charlet@adacore.com>
+
+ * bindgen.adb (Gen_Main): Disable generation of reference to
+ Ada_Main_Program_Name for CCG.
+ * bindusg.adb (Display): Add -G to the command-line usage for
+ gnatbind.
+ * opt.ads (Generate_C_Code): Update comment.
+ * switch-b.adb (Scan_Binder_Switches): Add handling for -G.
+
+2019-07-03 Arnaud Charlet <charlet@adacore.com>
+
+ * sem_ch7.adb (Has_Referencer): Do not consider inlined
+ subprograms when generating C code, which allows us to generate
+ static inline subprograms.
+
+2019-07-03 Justin Squirek <squirek@adacore.com>
+
+ * sem_ch6.adb (Check_Conformance): Add expression checking for
+ constant modifiers in anonymous access types (in addition to
+ "non-null" types) so that they are considered "matching" for
+ subsequent conformance tests.
+
+2019-07-03 Arnaud Charlet <charlet@adacore.com>
+
+ * doc/gnat_rm/standard_and_implementation_defined_restrictions.rst:
+ Clarify wording on No_Multiple_Elaboration.
+ * gnat_rm.texi: Regenerate.
+
+2019-07-03 Ed Schonberg <schonberg@adacore.com>
+
+ * sem_ch8.adb (Find_Selected_Component): If the prefix is the
+ current instance of a type or subtype, complete the resolution
+ of the name by finding the component of the type denoted by the
+ selector name.
+
+2019-07-03 Eric Botcazou <ebotcazou@adacore.com>
+
+ * doc/gnat_rm/interfacing_to_other_languages.rst (Interfacing to C):
+ Document that boolean types with convention C now map to C99 bool.
+ * gnat_rm.texi: Regenerate.
+
+2019-07-03 Javier Miranda <miranda@adacore.com>
+
+ * exp_attr.adb (Expand_Min_Max_Attribute): Code cleanup:
+ removing code that it is now never executed in the CCG compiler
+ (dead code).
+
+2019-07-02 Iain Sandoe <iain@sandoe.co.uk>
+
+ * libgnat/system-darwin-ppc.ads: Set Stack_Check_Probes True for
+ PPC Darwin.
+
+2019-07-01 Ed Schonberg <schonberg@adacore.com>
+
+ * sem_ch12.adb (Is_Defaulted): New predicate in
+ Check_Formal_Package_Intance, to skip the conformance of checks
+ on parameters of a formal package that are defaulted,
+
+2019-07-01 Hristian Kirtchev <kirtchev@adacore.com>
+
+ * checks.adb, exp_ch9.adb, exp_unst.adb, sem_ch4.adb,
+ sem_prag.adb, sem_spark.adb: Minor reformatting.
+
+2019-07-01 Ed Schonberg <schonberg@adacore.com>
+
+ * sem_attr.adb (Analyze_Attribute, case Enum_Rep): Allow prefix
+ of attribute to be an attribute reference of a discrete type.
+
+2019-07-01 Eric Botcazou <ebotcazou@adacore.com>
+
+ * sem_ch12.adb (Analyze_Subprogram_Instantiation): Move up
+ handling of Has_Pragma_Inline_Always and deal with
+ Has_Pragma_No_Inline.
+
+2019-07-01 Ed Schonberg <schonberg@adacore.com>
+
+ * sem_ch3.adb (Build_Derived_Record_Type): If the parent type is
+ declared as a subtype of a private type with an inherited
+ discriminant constraint, its generated full base appears as a
+ record subtype, so we need to retrieve its oen base type so that
+ the inherited constraint can be applied to it.
+
+2019-07-01 Yannick Moy <moy@adacore.com>
+
+ * sem_spark.adb: Completely rework the algorithm for ownership
+ checking, as the rules in SPARK RM have changed a lot.
+ * sem_spark.ads: Update comments.
+
+2019-07-01 Dmitriy Anisimkov <anisimko@adacore.com>
+
+ * gsocket.h (Has_Sockaddr_Len): Use the offset of sin_family offset in
+ the sockaddr_in structure to determine the existence of length field
+ before the sin_family.
+
+2019-07-01 Ed Schonberg <schonberg@adacore.com>
+
+ * sem_prag.adb (Analyze_Pragma, case Weak_External): Pragma only
+ applies to entities with run-time addresses, not to types.
+
+2019-07-01 Piotr Trojanek <trojanek@adacore.com>
+
+ * einfo.adb, sem_ch7.adb, sem_prag.adb, sem_util.adb: Update
+ references to the SPARK RM after the removal of Rule 7.1.4(5).
+
+2019-07-01 Piotr Trojanek <trojanek@adacore.com>
+
+ * sysdep.c: Cleanup references to LynuxWorks in docs and
+ comments.
+
+2019-07-01 Ed Schonberg <schonberg@adacore.com>
+
+ * checks.adb (Insert_Valid_Check): Do not apply validity check
+ to variable declared within a protected object that uses the
+ Lock_Free implementation, to prevent unwarranted constant
+ folding, because entities within such an object msut be treated
+ as volatile.
+
+2019-07-01 Eric Botcazou <ebotcazou@adacore.com>
+
+ * exp_ch9.adb (Check_Inlining): Deal with Has_Pragma_No_Inline.
+
+2019-07-01 Ed Schonberg <schonberg@adacore.com>
+
+ * exp_unst.adb (Visit_Node, Check_Static_Type): Improve the
+ handling of private and incomplete types whose full view is an
+ access type, to detect additional uplevel references in dynamic
+ bounds. This is relevant to N_Free_Statement among others that
+ manipulate types whose full viww may be an access type.
+
+2019-07-01 Pat Rogers <rogers@adacore.com>
+
+ * doc/gnat_rm/representation_clauses_and_pragmas.rst: Correct
+ size indicated for R as a component of an array.
+ * gnat_rm.texi: Regenerate.
+
+2019-07-01 Justin Squirek <squirek@adacore.com>
+
+ * libgnat/s-win32.ads: Add definition for ULONG, modify
+ OVERLAPPED type, and add appropriate pragmas.
+
+2019-07-01 Bob Duff <duff@adacore.com>
+
+ * gnat1drv.adb (gnat1drv): Call Write_ALI if the main unit is
+ ignored-ghost.
+
+2019-07-01 Yannick Moy <moy@adacore.com>
+
+ * sem_ch4.adb (Operator_Check): Refine error message.
+
+2019-07-01 Piotr Trojanek <trojanek@adacore.com>
+
+ * libgnat/a-calend.ads: Revert "Global => null" contracts on
+ non-pure routines.
+
+2019-07-01 Piotr Trojanek <trojanek@adacore.com>
+
+ * exp_attr.adb, libgnat/g-graphs.ads: Fix typos in comments:
+ componant -> component.
+
+2019-07-01 Hristian Kirtchev <kirtchev@adacore.com>
+
+ * libgnat/g-graphs.adb: Use type Directed_Graph rather than
+ Instance in various routines.
+ * libgnat/g-graphs.ads: Change type Instance to Directed_Graph.
+ Update various routines that mention the type.
+
+2019-07-01 Hristian Kirtchev <kirtchev@adacore.com>
+
+ * libgnat/g-sets.adb: Use type Membership_Set rathern than
+ Instance in various routines.
+ * libgnat/g-sets.ads: Change type Instance to Membership_Set.
+ Update various routines that mention the type.
+
+2019-07-01 Hristian Kirtchev <kirtchev@adacore.com>
+
+ * libgnat/g-lists.adb: Use type Doubly_Linked_List rather than
+ Instance in various routines.
+ * libgnat/g-lists.ads: Change type Instance to
+ Doubly_Linked_List. Update various routines that mention the
+ type.
+
+2019-07-01 Hristian Kirtchev <kirtchev@adacore.com>
+
+ * libgnat/g-dynhta.adb: Use type Dynamic_Hash_Table rather than
+ Instance in various routines.
+ * libgnat/g-dynhta.ads: Change type Instance to
+ Dynamic_Hash_Table. Update various routines that mention the
+ type.
+
+2019-07-01 Hristian Kirtchev <kirtchev@adacore.com>
+
+ * exp_attr.adb, exp_ch7.adb, exp_unst.adb, sem_ch3.adb,
+ sem_util.adb, uintp.adb, uintp.ads: Minor reformatting.
+
+2019-07-01 Javier Miranda <miranda@adacore.com>
+
+ * exp_attr.adb (Expand_Min_Max_Attribute): Disable expansion of
+ 'Min/'Max on integer, enumeration, fixed point and floating
+ point types since the CCG backend now provides in file
+ standard.h routines to support it.
+
+2019-07-01 Hristian Kirtchev <kirtchev@adacore.com>
+
+ * impunit.adb: Add GNAT.Graphs to list Non_Imp_File_Names_95.
+ * Makefile.rtl, gcc-interface/Make-lang.in: Register unit
+ GNAT.Graphs.
+ * libgnat/g-dynhta.adb: Various minor cleanups (use Present
+ rather than direct comparisons).
+ (Delete): Reimplement to use Delete_Node.
+ (Delete_Node): New routine.
+ (Destroy_Bucket): Invoke the provided destructor.
+ (Present): New routines.
+ * libgnat/g-dynhta.ads: Add new generic formal Destroy_Value.
+ Use better names for the components of iterators.
+ * libgnat/g-graphs.adb, libgnat/g-graphs.ads: New unit.
+ * libgnat/g-lists.adb: Various minor cleanups (use Present
+ rather than direct comparisons).
+ (Delete_Node): Invoke the provided destructor.
+ (Present): New routine.
+ * libgnat/g-lists.ads: Add new generic formal Destroy_Element.
+ Use better names for the components of iterators.
+ (Present): New routine.
+ * libgnat/g-sets.adb, libgnat/g-sets.ads (Destroy, Preset,
+ Reset): New routines.
+
+2019-07-01 Dmitriy Anisimkov <anisimko@adacore.com>
+
+ * libgnat/g-sothco.adb (Get_Address): Fix the case when AF_INET6
+ is not defined.
+
+2019-07-01 Ed Schonberg <schonberg@adacore.com>
+
+ * exp_attr.adb (Expand_Attribute_Reference, case Invalid_Value):
+ Resolve result of call to Get_Simple_Init_Val, which may be a
+ conversion of a literal.
+
+2019-07-01 Hristian Kirtchev <kirtchev@adacore.com>
+
+ * freeze.adb (Freeze_Expression): Remove the horrible useless
+ name hiding of N. Insert the freeze nodes generated by the
+ expression prior to the expression when the nearest enclosing
+ scope is transient.
+
+2019-07-01 Pierre-Marie de Rodat <derodat@adacore.com>
+
+ * doc/gnat_ugn/building_executable_programs_with_gnat.rst: Fix
+ formatting issues in the -gnatR section.
+ * gnat_ugn.texi: Regenerate.
+
+2019-06-30 Iain Sandoe <iain@sandoe.co.uk>
+
+ * gnatlink.adb (Link_Step): Remove duplicate -static-libgcc switches.
+ Push -shared-libgcc explicitly, when it is the target default (unless
+ overidden by the static flag).
+ When the user has put an instance of shared/static-libgcc do not push
+ a duplicate of this.
+
+2019-06-29 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gcc-interface/decl.c (gnat_to_gnu_entity): Beep up comment on SAVED,
+ and tweak comment on the assertion about the scopes of Itypes. Do not
+ skip the regular processing for Itypes that are E_Record_Subtype with
+ a Cloned_Subtype. Get the Cloned_Subtype for every E_Record_Subtype
+ if the type is dummy and hasn't got its own freeze node.
+ <E_Record_Subtype>: Save again the DECL of the Cloned_Subtype, if any.
+ <E_Access_Subtype>: Save again the DECL of the equivalent type.
+ (Gigi_Equivalent_Type) <E_Access_Subtype>: New case.
+
+2019-06-29 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gcc-interface/utils.c (unchecked_convert): Tweak comment. Only skip
+ dereferences when padding to have the same size on both sides. Do it
+ for destination types with self-referential size too.
+
+2019-06-29 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gcc-interface/decl.c (gnat_to_gnu_entity) <E_Record_Type>: If the
+ type requires strict alignment, then set the RM size to the type size.
+ Rework handling of alignment and sizes of tagged types in ASIS mode.
+ (validate_size): Rename local variable and remove special handling for
+ strict-alignment types.
+ * gcc-interface/utils.c (finish_record_type): Constify local variables
+ and use properly typed constants.
+
+2019-06-29 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gcc-interface/decl.c (gnat_to_gnu_field): Rework error messages for
+ fields requiring strict alignment, add explicit test on Storage_Unit
+ for position and size, and mention type alignment for position.
+
+2019-06-29 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gcc-interface/trans.c (mark_visited_r): Set TYPE_SIZES_GIMPLIFIED on
+ the main variant of a type, if any.
+
+2019-06-29 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gcc-interface/decl.c (set_nonaliased_component_on_array_type): Add
+ missing guard for the presence of TYPE_CANONICAL.
+ (set_reverse_storage_order_on_array_type): Likewise.
+
+2019-06-29 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gcc-interface/gigi.h (make_packable_type): Remove default value.
+ (value_factor_p): Tweak prototype.
+ * gcc-interface/decl.c (gnat_to_gnu_entity): Add comment.
+ (gnat_to_gnu_component_type): Likewise.
+ (gnat_to_gnu_field): Likewise. Fetch the position of the field earlier
+ and simplify the condition under which the type is packed. Declare
+ local variable is_bitfield. Pass 1 as max_align to make_packable_type
+ if it is set to true.
+ (copy_and_substitute_in_layout): Pass 0 to make_packable_type.
+ * gcc-interface/utils.c (make_packable_array_type): New function.
+ (make_packable_type): Use it to rewrite the type of array field.
+ (maybe_pad_type): Pass align parameter to make_packable_type.
+ (create_field_decl): Minor tweaks.
+ (value_factor_p): Assert that FACTOR is a power of 2 and replace the
+ modulo computation by a masking operation.
+
+2019-06-25 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gcc-interface/decl.c (gnat_to_gnu_entity): Remove superfluous test
+ in previous change.
+ * gcc-interface/gigi.h (maybe_character_type): Fix formatting.
+ (maybe_character_value): Likewise.
+
+2019-06-24 Jan Hubicka <jh@suse.cz>
+
+ * gcc-interface/decl.c (gnat_to_gnu_entity): Check that
+ type is array or integer prior checking string flag.
+ * gcc-interface/gigi.h (maybe_character_type): Likewise.
+ (maybe_character_value): Likewise.
+
+2019-06-24 Martin Sebor <msebor@redhat.com>
+
+ * gcc-interface/utils.c (handle_nonnull_attribute): Quote attribute
+ name.
+
+2019-06-18 Arnaud Charlet <charlet@adacore.com>
+
+ PR ada/80590
+ * sem_ch5.adb (Analyze_Loop_Statement): Avoid exception propagation
+ during normal processing.
+
+2019-06-17 Arnaud Charlet <charlet@adacore.com>
+
+ PR ada/80590
+ * exp_ch9.adb (Expand_N_Delay_Relative_Statement): Swap the two
+ conditions to avoid a unnecessary exception propagation in the default
+ case.
+
+2019-05-28 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gcc-interface/utils.c (handle_stack_protect_attribute): Move around.
+
+2019-05-28 Eric Botcazou <ebotcazou@adacore.com>
+
+ * doc/gnat_rm/implementation_defined_pragmas.rst (Machine_Attribute):
+ Document additional optional parameters.
+ * sem_prag.adb (Analyze_Pragma) <Pragma_Machine_Attribute>: Accept
+ more than one optional parameter.
+ * gcc-interface/decl.c (prepend_one_attribute_pragma): Alphabetize
+ the list of supported pragmas. Simplify the handling of parameters
+ and add support for more than one optional parameter.
+ * gcc-interface/utils.c (attr_cold_hot_exclusions): New constant.
+ (gnat_internal_attribute_table): Add entry for no_icf, noipa, flatten,
+ used, cold, hot, target and target_clones.
+ (begin_subprog_body): Do not create the RTL for the subprogram here.
+ (handle_noicf_attribute): New static function.
+ (handle_noipa_attribute): Likewise.
+ (handle_flatten_attribute): Likewise.
+ (handle_used_attribute): Likewise.
+ (handle_cold_attribute): Likewise.
+ (handle_hot_attribute): Likewise.
+ (handle_target_attribute): Likewise.
+ (handle_target_clones_attribute): Likewise.
+
+2019-05-28 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gcc-interface/trans.c (lvalue_required_for_attribute_p): Return 0
+ for 'Size too.
+ (Identifier_to_gnu): Use the actual subtype for a reference to a
+ packed array in a return statement.
+ (Attribute_to_gnu) <Attr_Size>: Do not strip VIEW_CONVERT_EXPRs from
+ the prefix in every case.
+
+2019-05-28 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gcc-interface/trans.c (gnat_to_gnu): Remove superfluous tests on
+ Backend_Overflow_Checks_On_Target and rework comments.
+
+2019-05-28 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gcc-interface/trans.c (walk_nesting_tree): New static function.
+ (finalize_nrv): Use it to walk the entire nesting tree.
+
+2019-05-28 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gcc-interface/decl.c (gnat_to_gnu_entity) <E_Record_Subtype>: Remove
+ obsolete test on Is_For_Access_Subtype.
+
+2019-05-28 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gcc-interface/decl.c (components_to_record): Set a name on the type
+ created for the REP part, if any.
+ * gcc-interface/utils.c (finish_record_type): Only take the maximum
+ when merging sizes for a variant part at offset 0.
+ (merge_sizes): Rename has_rep parameter into max.
+
+2019-05-28 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gcc-interface/utils.c (gnat_internal_attribute_table): Add support
+ for stack_protect attribute.
+ (handle_stack_protect_attribute): New static function.
+
+2019-05-28 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gcc-interface/decl.c (intrin_arglists_compatible_p): Do not return
+ false if the internal builtin uses a variable list.
+
+2019-05-27 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gcc-interface/trans.c (Call_to_gnu): Do not initialize the temporary
+ created out of addressability concerns if it's for the _Init parameter
+ of an initialization procedure.
+
+2019-05-27 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gcc-interface/ada-builtin-types.def: New file.
+ * gcc-interface/ada-builtins.def: Likewise.
+ * gcc-interface/ada-tree.h (BUILT_IN_LIKELY): New macro.
+ (BUILT_IN_UNLIKELY): Likewise.
+ * gcc-interface/trans.c (independent_iterations_p): Initialize the
+ auto-vector to 16 elements.
+ (Call_to_gnu): Remove local variable and change the vector of actual
+ parameters to an auto-vector. Do not convert actual parameters to
+ the argument type for front-end built-in functions. Add support for
+ front-end built-in functions.
+ (build_noreturn_cond): Use internal instead of built-in function.
+ * gcc-interface/utils.c (c_builtin_type): Include ada-builtin-types.def
+ (install_builtin_function_types): Likewise.
+ (install_builtin_functions): Include ada-builtins.def first.
+
+2019-05-27 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gcc-interface/utils.c (maybe_pad_type): Issue the warning for the
+ specific case of component types preferably.
+
+2019-05-27 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gcc-interface/trans.c (Identifier_to_gnu): Minor tweaks.
+ (gnat_to_gnu): Do not convert the result if it is a reference to an
+ unconstrained array used as the prefix of an attribute reference that
+ requires an lvalue.
+
+2019-05-27 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gcc-interface/trans.c (Gigi_Types_Compatible): New predicate.
+ (Identifier_to_gnu): Use it to assert that the type of the identifier
+ and that of its entity are compatible for gigi. Rename a couple of
+ local variables and separate the processing of the result type.
+
+2019-05-27 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gcc-interface/trans.c (Call_to_gnu): Use the unpadded type when
+ putting back an intermediate conversion the type of the actuals.
+
+2019-05-27 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gcc-interface/trans.c (gnat_to_gnu) <Shift operations>: Convert the
+ count to the unsigned version of its base type before proceeding.
+
+2019-05-16 Martin Sebor <msebor@redhat.com>
+
+ * gcc-interface/trans.c (check_inlining_for_nested_subprog): Quote
+ reserved names.
+
2019-05-08 Arnaud Charlet <charlet@adacore.com>
* standard.ads.h: New file.
diff --git a/gcc/ada/Makefile.rtl b/gcc/ada/Makefile.rtl
index 775ab98..916ae3e 100644
--- a/gcc/ada/Makefile.rtl
+++ b/gcc/ada/Makefile.rtl
@@ -421,6 +421,7 @@ GNATRTL_NONTASKING_OBJS= \
g-exptty$(objext) \
g-flocon$(objext) \
g-forstr$(objext) \
+ g-graphs$(objext) \
g-heasor$(objext) \
g-hesora$(objext) \
g-hesorg$(objext) \
diff --git a/gcc/ada/ali.adb b/gcc/ada/ali.adb
index 818e67a..978fb3d 100644
--- a/gcc/ada/ali.adb
+++ b/gcc/ada/ali.adb
@@ -29,39 +29,328 @@ with Fname; use Fname;
with Opt; use Opt;
with Osint; use Osint;
with Output; use Output;
+with Snames; use Snames;
+
+with GNAT; use GNAT;
+with GNAT.Dynamic_HTables; use GNAT.Dynamic_HTables;
package body ALI is
use ASCII;
-- Make control characters visible
+ ---------------------
+ -- Data structures --
+ ---------------------
+
+ procedure Destroy (IS_Id : in out Invocation_Signature_Id);
+ -- Destroy an invocation signature with id IS_Id
+
+ function Hash
+ (IS_Rec : Invocation_Signature_Record) return Bucket_Range_Type;
+ -- Obtain the hash of key IS_Rec
+
+ package Sig_Map is new Dynamic_Hash_Tables
+ (Key_Type => Invocation_Signature_Record,
+ Value_Type => Invocation_Signature_Id,
+ No_Value => No_Invocation_Signature,
+ Expansion_Threshold => 1.5,
+ Expansion_Factor => 2,
+ Compression_Threshold => 0.3,
+ Compression_Factor => 2,
+ "=" => "=",
+ Destroy_Value => Destroy,
+ Hash => Hash);
+
+ -- The following map relates invocation signature records to invocation
+ -- signature ids.
+
+ Sig_To_Sig_Map : constant Sig_Map.Dynamic_Hash_Table :=
+ Sig_Map.Create (500);
+
+ -- The folowing table maps body placement kinds to character codes for
+ -- invocation construct encoding in ALI files.
+
+ Body_Placement_Codes :
+ constant array (Body_Placement_Kind) of Character :=
+ (In_Body => 'b',
+ In_Spec => 's',
+ No_Body_Placement => 'Z');
+
+ -- The following table maps invocation kinds to character codes for
+ -- invocation relation encoding in ALI files.
+
+ Invocation_Codes :
+ constant array (Invocation_Kind) of Character :=
+ (Accept_Alternative => 'a',
+ Access_Taken => 'b',
+ Call => 'c',
+ Controlled_Adjustment => 'd',
+ Controlled_Finalization => 'e',
+ Controlled_Initialization => 'f',
+ Default_Initial_Condition_Verification => 'g',
+ Initial_Condition_Verification => 'h',
+ Instantiation => 'i',
+ Internal_Controlled_Adjustment => 'j',
+ Internal_Controlled_Finalization => 'k',
+ Internal_Controlled_Initialization => 'l',
+ Invariant_Verification => 'm',
+ Postcondition_Verification => 'n',
+ Protected_Entry_Call => 'o',
+ Protected_Subprogram_Call => 'p',
+ Task_Activation => 'q',
+ Task_Entry_Call => 'r',
+ Type_Initialization => 's',
+ No_Invocation => 'Z');
+
+ -- The following table maps invocation construct kinds to character codes
+ -- for invocation construct encoding in ALI files.
+
+ Invocation_Construct_Codes :
+ constant array (Invocation_Construct_Kind) of Character :=
+ (Elaborate_Body_Procedure => 'b',
+ Elaborate_Spec_Procedure => 's',
+ Regular_Construct => 'Z');
+
+ -- The following table maps invocation graph line kinds to character codes
+ -- used in ALI files.
+
+ Invocation_Graph_Line_Codes :
+ constant array (Invocation_Graph_Line_Kind) of Character :=
+ (Invocation_Construct_Line => 'c',
+ Invocation_Relation_Line => 'r');
+
-- The following variable records which characters currently are used as
-- line type markers in the ALI file. This is used in Scan_ALI to detect
-- (or skip) invalid lines. The following letters are still available:
--
- -- B F G H J K O Q Z
+ -- B F H J K O Q Z
Known_ALI_Lines : constant array (Character range 'A' .. 'Z') of Boolean :=
- ('V' => True, -- version
- 'M' => True, -- main program
- 'A' => True, -- argument
- 'P' => True, -- program
- 'R' => True, -- restriction
- 'I' => True, -- interrupt
- 'U' => True, -- unit
- 'W' => True, -- with
- 'L' => True, -- linker option
- 'N' => True, -- notes
- 'E' => True, -- external
- 'D' => True, -- dependency
- 'X' => True, -- xref
- 'S' => True, -- specific dispatching
- 'Y' => True, -- limited_with
- 'Z' => True, -- implicit with from instantiation
- 'C' => True, -- SCO information
- 'T' => True, -- task stack information
+ ('A' => True, -- argument
+ 'C' => True, -- SCO information
+ 'D' => True, -- dependency
+ 'E' => True, -- external
+ 'G' => True, -- invocation graph
+ 'I' => True, -- interrupt
+ 'L' => True, -- linker option
+ 'M' => True, -- main program
+ 'N' => True, -- notes
+ 'P' => True, -- program
+ 'R' => True, -- restriction
+ 'S' => True, -- specific dispatching
+ 'T' => True, -- task stack information
+ 'U' => True, -- unit
+ 'V' => True, -- version
+ 'W' => True, -- with
+ 'X' => True, -- xref
+ 'Y' => True, -- limited_with
+ 'Z' => True, -- implicit with from instantiation
others => False);
+ ------------------------------
+ -- Add_Invocation_Construct --
+ ------------------------------
+
+ procedure Add_Invocation_Construct
+ (IC_Rec : Invocation_Construct_Record;
+ Update_Units : Boolean := True)
+ is
+ IC_Id : Invocation_Construct_Id;
+
+ begin
+ pragma Assert (Present (IC_Rec.Signature));
+
+ -- Create a invocation construct from the scanned attributes
+
+ Invocation_Constructs.Append (IC_Rec);
+ IC_Id := Invocation_Constructs.Last;
+
+ -- Update the invocation construct counter of the current unit only when
+ -- requested by the caller.
+
+ if Update_Units then
+ declare
+ Curr_Unit : Unit_Record renames Units.Table (Units.Last);
+
+ begin
+ Curr_Unit.Last_Invocation_Construct := IC_Id;
+ end;
+ end if;
+ end Add_Invocation_Construct;
+
+ -----------------------------
+ -- Add_Invocation_Relation --
+ -----------------------------
+
+ procedure Add_Invocation_Relation
+ (IR_Rec : Invocation_Relation_Record;
+ Update_Units : Boolean := True)
+ is
+ IR_Id : Invocation_Relation_Id;
+
+ begin
+ pragma Assert (Present (IR_Rec.Invoker));
+ pragma Assert (Present (IR_Rec.Target));
+ pragma Assert (IR_Rec.Kind /= No_Invocation);
+
+ -- Create an invocation relation from the scanned attributes
+
+ Invocation_Relations.Append (IR_Rec);
+ IR_Id := Invocation_Relations.Last;
+
+ -- Update the invocation relation counter of the current unit only when
+ -- requested by the caller.
+
+ if Update_Units then
+ declare
+ Curr_Unit : Unit_Record renames Units.Table (Units.Last);
+
+ begin
+ Curr_Unit.Last_Invocation_Relation := IR_Id;
+ end;
+ end if;
+ end Add_Invocation_Relation;
+
+ ---------------------------------
+ -- Body_Placement_Kind_To_Code --
+ ---------------------------------
+
+ function Body_Placement_Kind_To_Code
+ (Kind : Body_Placement_Kind) return Character
+ is
+ begin
+ return Body_Placement_Codes (Kind);
+ end Body_Placement_Kind_To_Code;
+
+ ---------------------------------
+ -- Code_To_Body_Placement_Kind --
+ ---------------------------------
+
+ function Code_To_Body_Placement_Kind
+ (Code : Character) return Body_Placement_Kind
+ is
+ begin
+ -- Determine which body placement kind corresponds to the character code
+ -- by traversing the contents of the mapping table.
+
+ for Kind in Body_Placement_Kind loop
+ if Body_Placement_Codes (Kind) = Code then
+ return Kind;
+ end if;
+ end loop;
+
+ raise Program_Error;
+ end Code_To_Body_Placement_Kind;
+
+ ---------------------------------------
+ -- Code_To_Invocation_Construct_Kind --
+ ---------------------------------------
+
+ function Code_To_Invocation_Construct_Kind
+ (Code : Character) return Invocation_Construct_Kind
+ is
+ begin
+ -- Determine which invocation construct kind matches the character code
+ -- by traversing the contents of the mapping table.
+
+ for Kind in Invocation_Construct_Kind loop
+ if Invocation_Construct_Codes (Kind) = Code then
+ return Kind;
+ end if;
+ end loop;
+
+ raise Program_Error;
+ end Code_To_Invocation_Construct_Kind;
+
+ -----------------------------
+ -- Code_To_Invocation_Kind --
+ -----------------------------
+
+ function Code_To_Invocation_Kind
+ (Code : Character) return Invocation_Kind
+ is
+ begin
+ -- Determine which invocation kind corresponds to the character code by
+ -- traversing the contents of the mapping table.
+
+ for Kind in Invocation_Kind loop
+ if Invocation_Codes (Kind) = Code then
+ return Kind;
+ end if;
+ end loop;
+
+ raise Program_Error;
+ end Code_To_Invocation_Kind;
+
+ ----------------------------------------
+ -- Code_To_Invocation_Graph_Line_Kind --
+ ----------------------------------------
+
+ function Code_To_Invocation_Graph_Line_Kind
+ (Code : Character) return Invocation_Graph_Line_Kind
+ is
+ begin
+ -- Determine which invocation graph line kind matches the character
+ -- code by traversing the contents of the mapping table.
+
+ for Kind in Invocation_Graph_Line_Kind loop
+ if Invocation_Graph_Line_Codes (Kind) = Code then
+ return Kind;
+ end if;
+ end loop;
+
+ raise Program_Error;
+ end Code_To_Invocation_Graph_Line_Kind;
+
+ -------------
+ -- Destroy --
+ -------------
+
+ procedure Destroy (IS_Id : in out Invocation_Signature_Id) is
+ pragma Unreferenced (IS_Id);
+ begin
+ null;
+ end Destroy;
+
+ ----------
+ -- Hash --
+ ----------
+
+ function Hash
+ (IS_Rec : Invocation_Signature_Record) return Bucket_Range_Type
+ is
+ Buffer : Bounded_String (2052);
+ IS_Nam : Name_Id;
+
+ begin
+ -- The hash is obtained in the following manner:
+ --
+ -- * A String signature based on the scope, name, line number, column
+ -- number, and locations, in the following format:
+ --
+ -- scope__name__line_column__locations
+ --
+ -- * The String is converted into a Name_Id
+ -- * The Name_Id is used as the hash
+
+ Append (Buffer, IS_Rec.Scope);
+ Append (Buffer, "__");
+ Append (Buffer, IS_Rec.Name);
+ Append (Buffer, "__");
+ Append (Buffer, IS_Rec.Line);
+ Append (Buffer, '_');
+ Append (Buffer, IS_Rec.Column);
+
+ if IS_Rec.Locations /= No_Name then
+ Append (Buffer, "__");
+ Append (Buffer, IS_Rec.Locations);
+ end if;
+
+ IS_Nam := Name_Find (Buffer);
+ return Bucket_Range_Type (IS_Nam);
+ end Hash;
+
--------------------
-- Initialize_ALI --
--------------------
@@ -90,16 +379,19 @@ package body ALI is
-- Initialize all tables
ALIs.Init;
+ Invocation_Constructs.Init;
+ Invocation_Relations.Init;
+ Invocation_Signatures.Init;
+ Linker_Options.Init;
No_Deps.Init;
+ Notes.Init;
+ Sdep.Init;
Units.Init;
+ Version_Ref.Reset;
Withs.Init;
- Sdep.Init;
- Linker_Options.Init;
- Notes.Init;
- Xref_Section.Init;
Xref_Entity.Init;
Xref.Init;
- Version_Ref.Reset;
+ Xref_Section.Init;
-- Add dummy zero'th item in Linker_Options and Notes for sort calls
@@ -125,6 +417,131 @@ package body ALI is
Zero_Cost_Exceptions_Specified := False;
end Initialize_ALI;
+ ---------------------------------------
+ -- Invocation_Construct_Kind_To_Code --
+ ---------------------------------------
+
+ function Invocation_Construct_Kind_To_Code
+ (Kind : Invocation_Construct_Kind) return Character
+ is
+ begin
+ return Invocation_Construct_Codes (Kind);
+ end Invocation_Construct_Kind_To_Code;
+
+ ----------------------------------------
+ -- Invocation_Graph_Line_Kind_To_Code --
+ ----------------------------------------
+
+ function Invocation_Graph_Line_Kind_To_Code
+ (Kind : Invocation_Graph_Line_Kind) return Character
+ is
+ begin
+ return Invocation_Graph_Line_Codes (Kind);
+ end Invocation_Graph_Line_Kind_To_Code;
+
+ -----------------------------
+ -- Invocation_Kind_To_Code --
+ -----------------------------
+
+ function Invocation_Kind_To_Code
+ (Kind : Invocation_Kind) return Character
+ is
+ begin
+ return Invocation_Codes (Kind);
+ end Invocation_Kind_To_Code;
+
+ -----------------------------
+ -- Invocation_Signature_Of --
+ -----------------------------
+
+ function Invocation_Signature_Of
+ (Column : Nat;
+ Line : Nat;
+ Locations : Name_Id;
+ Name : Name_Id;
+ Scope : Name_Id) return Invocation_Signature_Id
+ is
+ IS_Rec : constant Invocation_Signature_Record :=
+ (Column => Column,
+ Line => Line,
+ Locations => Locations,
+ Name => Name,
+ Scope => Scope);
+ IS_Id : Invocation_Signature_Id;
+
+ begin
+ IS_Id := Sig_Map.Get (Sig_To_Sig_Map, IS_Rec);
+
+ -- The invocation signature lacks an id. This indicates that it
+ -- is encountered for the first time during the construction of
+ -- the graph.
+
+ if not Present (IS_Id) then
+ Invocation_Signatures.Append (IS_Rec);
+ IS_Id := Invocation_Signatures.Last;
+
+ -- Map the invocation signature record to its corresponding id
+
+ Sig_Map.Put (Sig_To_Sig_Map, IS_Rec, IS_Id);
+ end if;
+
+ return IS_Id;
+ end Invocation_Signature_Of;
+
+ -------------
+ -- Present --
+ -------------
+
+ function Present (IC_Id : Invocation_Construct_Id) return Boolean is
+ begin
+ return IC_Id /= No_Invocation_Construct;
+ end Present;
+
+ -------------
+ -- Present --
+ -------------
+
+ function Present (IR_Id : Invocation_Relation_Id) return Boolean is
+ begin
+ return IR_Id /= No_Invocation_Relation;
+ end Present;
+
+ -------------
+ -- Present --
+ -------------
+
+ function Present (IS_Id : Invocation_Signature_Id) return Boolean is
+ begin
+ return IS_Id /= No_Invocation_Signature;
+ end Present;
+
+ -------------
+ -- Present --
+ -------------
+
+ function Present (Dep : Sdep_Id) return Boolean is
+ begin
+ return Dep /= No_Sdep_Id;
+ end Present;
+
+ -------------
+ -- Present --
+ -------------
+
+ function Present (U_Id : Unit_Id) return Boolean is
+ begin
+ return U_Id /= No_Unit_Id;
+ end Present;
+
+ -------------
+ -- Present --
+ -------------
+
+ function Present (W_Id : With_Id) return Boolean is
+ begin
+ return W_Id /= No_With_Id;
+ end Present;
+
--------------
-- Scan_ALI --
--------------
@@ -256,6 +673,9 @@ package body ALI is
Standard_Entity : out Name_Id);
-- Parse the definition of a typeref (<...>, {...} or (...))
+ procedure Scan_Invocation_Graph_Line;
+ -- Parse a single line which encodes a piece of the invocation graph
+
procedure Skip_Eol;
-- Skip past spaces, then skip past end of line (fatal error if not
-- at end of line). Also skips past any following blank lines.
@@ -771,6 +1191,202 @@ package body ALI is
return T (P);
end Nextc;
+ --------------------------------
+ -- Scan_Invocation_Graph_Line --
+ --------------------------------
+
+ procedure Scan_Invocation_Graph_Line is
+ procedure Scan_Invocation_Construct_Line;
+ pragma Inline (Scan_Invocation_Construct_Line);
+ -- Parse an invocation construct line and construct the corresponding
+ -- construct. The following data structures are updated:
+ --
+ -- * Invocation_Constructs
+ -- * Units
+
+ procedure Scan_Invocation_Relation_Line;
+ pragma Inline (Scan_Invocation_Relation_Line);
+ -- Parse an invocation relation line and construct the corresponding
+ -- relation. The following data structures are updated:
+ --
+ -- * Invocation_Relations
+ -- * Units
+
+ function Scan_Invocation_Signature return Invocation_Signature_Id;
+ pragma Inline (Scan_Invocation_Signature);
+ -- Parse a single invocation signature while populating the following
+ -- data structures:
+ --
+ -- * Invocation_Signatures
+ -- * Sig_To_Sig_Map
+
+ ------------------------------------
+ -- Scan_Invocation_Construct_Line --
+ ------------------------------------
+
+ procedure Scan_Invocation_Construct_Line is
+ IC_Rec : Invocation_Construct_Record;
+
+ begin
+ -- construct-kind
+
+ IC_Rec.Kind := Code_To_Invocation_Construct_Kind (Getc);
+ Checkc (' ');
+ Skip_Space;
+
+ -- construct-body-placement
+
+ IC_Rec.Placement := Code_To_Body_Placement_Kind (Getc);
+ Checkc (' ');
+ Skip_Space;
+
+ -- construct-signature
+
+ IC_Rec.Signature := Scan_Invocation_Signature;
+ pragma Assert (Present (IC_Rec.Signature));
+
+ Skip_Eol;
+
+ Add_Invocation_Construct (IC_Rec);
+ end Scan_Invocation_Construct_Line;
+
+ -----------------------------------
+ -- Scan_Invocation_Relation_Line --
+ -----------------------------------
+
+ procedure Scan_Invocation_Relation_Line is
+ IR_Rec : Invocation_Relation_Record;
+
+ begin
+ -- relation-kind
+
+ IR_Rec.Kind := Code_To_Invocation_Kind (Getc);
+ Checkc (' ');
+ Skip_Space;
+
+ -- (extra-name | "none")
+
+ IR_Rec.Extra := Get_Name;
+
+ if IR_Rec.Extra = Name_None then
+ IR_Rec.Extra := No_Name;
+ end if;
+
+ Checkc (' ');
+ Skip_Space;
+
+ -- invoker-signature
+
+ IR_Rec.Invoker := Scan_Invocation_Signature;
+ pragma Assert (Present (IR_Rec.Invoker));
+
+ Checkc (' ');
+ Skip_Space;
+
+ -- target-signature
+
+ IR_Rec.Target := Scan_Invocation_Signature;
+ pragma Assert (Present (IR_Rec.Target));
+
+ Skip_Eol;
+
+ Add_Invocation_Relation (IR_Rec);
+ end Scan_Invocation_Relation_Line;
+
+ -------------------------------
+ -- Scan_Invocation_Signature --
+ -------------------------------
+
+ function Scan_Invocation_Signature return Invocation_Signature_Id is
+ Column : Nat;
+ Line : Nat;
+ Locations : Name_Id;
+ Name : Name_Id;
+ Scope : Name_Id;
+
+ begin
+ -- [
+
+ Checkc ('[');
+
+ -- name
+
+ Name := Get_Name;
+ Checkc (' ');
+ Skip_Space;
+
+ -- scope
+
+ Scope := Get_Name;
+ Checkc (' ');
+ Skip_Space;
+
+ -- line
+
+ Line := Get_Nat;
+ Checkc (' ');
+ Skip_Space;
+
+ -- column
+
+ Column := Get_Nat;
+ Checkc (' ');
+ Skip_Space;
+
+ -- (locations | "none")
+
+ Locations := Get_Name;
+
+ if Locations = Name_None then
+ Locations := No_Name;
+ end if;
+
+ -- ]
+
+ Checkc (']');
+
+ -- Create an invocation signature from the scanned attributes
+
+ return
+ Invocation_Signature_Of
+ (Column => Column,
+ Line => Line,
+ Locations => Locations,
+ Name => Name,
+ Scope => Scope);
+ end Scan_Invocation_Signature;
+
+ -- Local variables
+
+ Line : Invocation_Graph_Line_Kind;
+
+ -- Start of processing for Scan_Invocation_Graph_Line
+
+ begin
+ if Ignore ('G') then
+ return;
+ end if;
+
+ Checkc (' ');
+ Skip_Space;
+
+ -- line-kind
+
+ Line := Code_To_Invocation_Graph_Line_Kind (Getc);
+ Checkc (' ');
+ Skip_Space;
+
+ -- line-attributes
+
+ if Line = Invocation_Construct_Line then
+ Scan_Invocation_Construct_Line;
+
+ else
+ pragma Assert (Line = Invocation_Relation_Line);
+ Scan_Invocation_Relation_Line;
+ end if;
+ end Scan_Invocation_Graph_Line;
+
--------------
-- Skip_Eol --
--------------
@@ -1716,38 +2332,42 @@ package body ALI is
UL : Unit_Record renames Units.Table (Units.Last);
begin
- UL.Uname := Get_Unit_Name;
- UL.Predefined := Is_Predefined_Unit;
- UL.Internal := Is_Internal_Unit;
- UL.My_ALI := Id;
- UL.Sfile := Get_File_Name (Lower => True);
- UL.Pure := False;
- UL.Preelab := False;
- UL.No_Elab := False;
- UL.Shared_Passive := False;
- UL.RCI := False;
- UL.Remote_Types := False;
- UL.Serious_Errors := False;
- UL.Has_RACW := False;
- UL.Init_Scalars := False;
- UL.Is_Generic := False;
- UL.Icasing := Mixed_Case;
- UL.Kcasing := All_Lower_Case;
- UL.Dynamic_Elab := False;
- UL.Elaborate_Body := False;
- UL.Set_Elab_Entity := False;
- UL.Version := "00000000";
- UL.First_With := Withs.Last + 1;
- UL.First_Arg := First_Arg;
- UL.Elab_Position := 0;
- UL.SAL_Interface := ALIs.Table (Id).SAL_Interface;
- UL.Directly_Scanned := Directly_Scanned;
- UL.Body_Needed_For_SAL := False;
- UL.Elaborate_Body_Desirable := False;
- UL.Optimize_Alignment := 'O';
- UL.Has_Finalizer := False;
- UL.Primary_Stack_Count := 0;
- UL.Sec_Stack_Count := 0;
+ UL.Uname := Get_Unit_Name;
+ UL.Predefined := Is_Predefined_Unit;
+ UL.Internal := Is_Internal_Unit;
+ UL.My_ALI := Id;
+ UL.Sfile := Get_File_Name (Lower => True);
+ UL.Pure := False;
+ UL.Preelab := False;
+ UL.No_Elab := False;
+ UL.Shared_Passive := False;
+ UL.RCI := False;
+ UL.Remote_Types := False;
+ UL.Serious_Errors := False;
+ UL.Has_RACW := False;
+ UL.Init_Scalars := False;
+ UL.Is_Generic := False;
+ UL.Icasing := Mixed_Case;
+ UL.Kcasing := All_Lower_Case;
+ UL.Dynamic_Elab := False;
+ UL.Elaborate_Body := False;
+ UL.Set_Elab_Entity := False;
+ UL.Version := "00000000";
+ UL.First_With := Withs.Last + 1;
+ UL.First_Arg := First_Arg;
+ UL.First_Invocation_Construct := Invocation_Constructs.Last + 1;
+ UL.Last_Invocation_Construct := No_Invocation_Construct;
+ UL.First_Invocation_Relation := Invocation_Relations.Last + 1;
+ UL.Last_Invocation_Relation := No_Invocation_Relation;
+ UL.Elab_Position := 0;
+ UL.SAL_Interface := ALIs.Table (Id).SAL_Interface;
+ UL.Directly_Scanned := Directly_Scanned;
+ UL.Body_Needed_For_SAL := False;
+ UL.Elaborate_Body_Desirable := False;
+ UL.Optimize_Alignment := 'O';
+ UL.Has_Finalizer := False;
+ UL.Primary_Stack_Count := 0;
+ UL.Sec_Stack_Count := 0;
if Debug_Flag_U then
Write_Str (" ----> reading unit ");
@@ -2444,6 +3064,17 @@ package body ALI is
ALIs.Table (Id).Last_Sdep := Sdep.Last;
+ -- Loop through invocation graph lines
+
+ G_Loop : loop
+ Check_Unknown_Line;
+ exit G_Loop when C /= 'G';
+
+ Scan_Invocation_Graph_Line;
+
+ C := Getc;
+ end loop G_Loop;
+
-- We must at this stage be at an Xref line or the end of file
if C = EOF then
@@ -2786,7 +3417,6 @@ package body ALI is
-- Record last entity
XS.Last_Entity := Xref_Entity.Last;
-
end Read_Refs_For_One_File;
C := Getc;
diff --git a/gcc/ada/ali.ads b/gcc/ada/ali.ads
index 7835857..79eabb1 100644
--- a/gcc/ada/ali.ads
+++ b/gcc/ada/ali.ads
@@ -34,6 +34,7 @@ with Rident; use Rident;
with Table;
with Types; use Types;
+with GNAT.Dynamic_Tables;
with GNAT.HTable; use GNAT.HTable;
package ALI is
@@ -66,6 +67,39 @@ package ALI is
type Priority_Specific_Dispatching_Id is range 0 .. 99_999_999;
-- Id values used for Priority_Specific_Dispatching table entries
+ type Invocation_Construct_Id is range 0 .. 99_999_999;
+ -- Id values used for Invocation_Constructs table entries
+
+ type Invocation_Relation_Id is range 0 .. 99_999_999;
+ -- Id values used for Invocation_Relations table entries
+
+ type Invocation_Signature_Id is range 0 .. 99_999_999;
+ -- Id values used for Invocation_Signatures table entries
+
+ function Present (IC_Id : Invocation_Construct_Id) return Boolean;
+ pragma Inline (Present);
+ -- Determine whether invocation construct IC_Id exists
+
+ function Present (IR_Id : Invocation_Relation_Id) return Boolean;
+ pragma Inline (Present);
+ -- Determine whether invocation relation IR_Id exists
+
+ function Present (IS_Id : Invocation_Signature_Id) return Boolean;
+ pragma Inline (Present);
+ -- Determine whether invocation signature IS_Id exists
+
+ function Present (Dep : Sdep_Id) return Boolean;
+ pragma Inline (Present);
+ -- Determine whether dependant Dep exists
+
+ function Present (U_Id : Unit_Id) return Boolean;
+ pragma Inline (Present);
+ -- Determine whether unit U_Id exists
+
+ function Present (W_Id : With_Id) return Boolean;
+ pragma Inline (Present);
+ -- Determine whether with W_Id exists
+
--------------------
-- ALI File Table --
--------------------
@@ -334,6 +368,18 @@ package ALI is
Last_Arg : Arg_Id;
-- Id of last args table entry for this file
+ First_Invocation_Construct : Invocation_Construct_Id;
+ -- Id of the first invocation construct for this unit
+
+ Last_Invocation_Construct : Invocation_Construct_Id;
+ -- Id of the last invocation construct for this unit
+
+ First_Invocation_Relation : Invocation_Relation_Id;
+ -- Id of the first invocation relation for this unit
+
+ Last_Invocation_Relation : Invocation_Relation_Id;
+ -- Id of the last invocation relation for this unit
+
Utype : Unit_Type;
-- Type of entry
@@ -408,6 +454,16 @@ package ALI is
Table_Increment => 200,
Table_Name => "Unit");
+ package Unit_Id_Tables is new GNAT.Dynamic_Tables
+ (Table_Component_Type => Unit_Id,
+ Table_Index_Type => Nat,
+ Table_Low_Bound => 1,
+ Table_Initial => 500,
+ Table_Increment => 200);
+
+ subtype Unit_Id_Table is Unit_Id_Tables.Instance;
+ subtype Unit_Id_Array is Unit_Id_Tables.Table_Type;
+
---------------------------
-- Interrupt State Table --
---------------------------
@@ -794,6 +850,7 @@ package ALI is
Unit_Name : Name_Id;
-- Name_Id for the unit name if not a subunit (No_Name for a subunit)
+
Rfile : File_Name_Type;
-- Reference file name. Same as Sfile unless a Source_Reference pragma
-- was used, in which case it reflects the name used in the pragma.
@@ -1026,6 +1083,265 @@ package ALI is
Table_Increment => 300,
Table_Name => "Xref");
+ ----------------------------
+ -- Invocation Graph Types --
+ ----------------------------
+
+ -- The following type identifies an invocation signature
+
+ No_Invocation_Signature : constant Invocation_Signature_Id :=
+ Invocation_Signature_Id'First;
+ First_Invocation_Signature : constant Invocation_Signature_Id :=
+ No_Invocation_Signature + 1;
+
+ -- The following type represents an invocation signature. Its purpose is
+ -- to uniquely identify an invocation construct within the ALI space. The
+ -- signature is comprised out of several pieces, some of which are used in
+ -- error diagnostics by the binder. Identification issues are resolved as
+ -- follows:
+ --
+ -- * The Column, Line, and Locations attributes together differentiate
+ -- between homonyms. In most cases, the Column and Line are sufficient
+ -- except when generic instantiations are involved. Together, the three
+ -- attributes offer a sequence of column-line pairs which eventually
+ -- reflect the location within the generic template.
+ --
+ -- * The Name attribute differentiates between invocation constructs at
+ -- the scope level. Since it is illegal for two entities with the same
+ -- name to coexist in the same scope, the Name attribute is sufficient
+ -- to distinguish them. Overloaded entities are already handled by the
+ -- Column, Line, and Locations attributes.
+ --
+ -- * The Scope attribute differentiates between invocation constructs at
+ -- various levels of nesting.
+
+ type Invocation_Signature_Record is record
+ Column : Nat := 0;
+ -- The column number where the invocation construct is declared
+
+ Line : Nat := 0;
+ -- The line number where the invocation construct is declared
+
+ Locations : Name_Id := No_Name;
+ -- Sequence of column and line numbers within nested instantiations
+
+ Name : Name_Id := No_Name;
+ -- The name of the invocation construct
+
+ Scope : Name_Id := No_Name;
+ -- The qualified name of the scope where the invocation construct is
+ -- declared.
+ end record;
+
+ -- The following type enumerates all possible placements of an invocation
+ -- construct's body body with respect to the unit it is declared in.
+
+ type Body_Placement_Kind is
+ (In_Body,
+ -- The body of the invocation construct is within the body of the unit
+ -- it is declared in.
+
+ In_Spec,
+ -- The body of the invocation construct is within the spec of the unit
+ -- it is declared in.
+
+ No_Body_Placement);
+ -- The invocation construct does not have a body
+
+ -- The following type enumerates all possible invocation construct kinds
+
+ type Invocation_Construct_Kind is
+ (Elaborate_Body_Procedure,
+ -- The invocation construct denotes the procedure which elaborates a
+ -- package body.
+
+ Elaborate_Spec_Procedure,
+ -- The invocation construct denotes the procedure which elaborates a
+ -- package spec.
+
+ Regular_Construct);
+ -- The invocation construct is a normal invocation construct
+
+ -- The following type identifies an invocation construct
+
+ No_Invocation_Construct : constant Invocation_Construct_Id :=
+ Invocation_Construct_Id'First;
+ First_Invocation_Construct : constant Invocation_Construct_Id :=
+ No_Invocation_Construct + 1;
+
+ -- The following type represents an invocation construct
+
+ type Invocation_Construct_Record is record
+ Kind : Invocation_Construct_Kind := Regular_Construct;
+ -- The nature of the invocation construct
+
+ Placement : Body_Placement_Kind := No_Body_Placement;
+ -- The location of the invocation construct's body with respect to the
+ -- body of the unit it is declared in.
+
+ Signature : Invocation_Signature_Id := No_Invocation_Signature;
+ -- The invocation signature which uniquely identifies the invocation
+ -- construct in the ALI space.
+ end record;
+
+ -- The following type identifies an invocation relation
+
+ No_Invocation_Relation : constant Invocation_Relation_Id :=
+ Invocation_Relation_Id'First;
+ First_Invocation_Relation : constant Invocation_Relation_Id :=
+ No_Invocation_Relation + 1;
+
+ -- The following type enumerates all possible invocation kinds
+
+ type Invocation_Kind is
+ (Accept_Alternative,
+ Access_Taken,
+ Call,
+ Controlled_Adjustment,
+ Controlled_Finalization,
+ Controlled_Initialization,
+ Default_Initial_Condition_Verification,
+ Initial_Condition_Verification,
+ Instantiation,
+ Internal_Controlled_Adjustment,
+ Internal_Controlled_Finalization,
+ Internal_Controlled_Initialization,
+ Invariant_Verification,
+ Postcondition_Verification,
+ Protected_Entry_Call,
+ Protected_Subprogram_Call,
+ Task_Activation,
+ Task_Entry_Call,
+ Type_Initialization,
+ No_Invocation);
+
+ subtype Internal_Controlled_Invocation_Kind is Invocation_Kind range
+ Internal_Controlled_Adjustment ..
+ -- Internal_Controlled_Finalization
+ Internal_Controlled_Initialization;
+
+ -- The following type represents an invocation relation. It associates an
+ -- invoker which activates/calls/instantiates with a target.
+
+ type Invocation_Relation_Record is record
+ Extra : Name_Id := No_Name;
+ -- The name of an additional entity used in error diagnostics
+
+ Invoker : Invocation_Signature_Id := No_Invocation_Signature;
+ -- The invocation signature which uniquely identifies the invoker within
+ -- the ALI space.
+
+ Kind : Invocation_Kind := No_Invocation;
+ -- The nature of the invocation
+
+ Target : Invocation_Signature_Id := No_Invocation_Signature;
+ -- The invocation signature which uniquely identifies the target within
+ -- the ALI space.
+ end record;
+
+ -- The following type enumerates all possible invocation graph ALI lines
+
+ type Invocation_Graph_Line_Kind is
+ (Invocation_Construct_Line,
+ Invocation_Relation_Line);
+
+ --------------------------------------
+ -- Invocation Graph Data Structures --
+ --------------------------------------
+
+ package Invocation_Constructs is new Table.Table
+ (Table_Index_Type => Invocation_Construct_Id,
+ Table_Component_Type => Invocation_Construct_Record,
+ Table_Low_Bound => First_Invocation_Construct,
+ Table_Initial => 2500,
+ Table_Increment => 200,
+ Table_Name => "Invocation_Constructs");
+
+ package Invocation_Relations is new Table.Table
+ (Table_Index_Type => Invocation_Relation_Id,
+ Table_Component_Type => Invocation_Relation_Record,
+ Table_Low_Bound => First_Invocation_Relation,
+ Table_Initial => 2500,
+ Table_Increment => 200,
+ Table_Name => "Invocation_Relation");
+
+ package Invocation_Signatures is new Table.Table
+ (Table_Index_Type => Invocation_Signature_Id,
+ Table_Component_Type => Invocation_Signature_Record,
+ Table_Low_Bound => First_Invocation_Signature,
+ Table_Initial => 2500,
+ Table_Increment => 200,
+ Table_Name => "Invocation_Signatures");
+
+ ----------------------------------
+ -- Invocation Graph Subprograms --
+ ----------------------------------
+
+ procedure Add_Invocation_Construct
+ (IC_Rec : Invocation_Construct_Record;
+ Update_Units : Boolean := True);
+ pragma Inline (Add_Invocation_Construct);
+ -- Add invocation construct attributes IC_Rec to internal data structures.
+ -- Flag Undate_Units should be set when this addition must be reflected in
+ -- the attributes of the current unit.
+
+ procedure Add_Invocation_Relation
+ (IR_Rec : Invocation_Relation_Record;
+ Update_Units : Boolean := True);
+ pragma Inline (Add_Invocation_Relation);
+ -- Add invocation relation attributes IR_Rec to internal data structures.
+ -- Flag Undate_Units should be set when this addition must be reflected in
+ -- the attributes of the current unit.
+
+ function Body_Placement_Kind_To_Code
+ (Kind : Body_Placement_Kind) return Character;
+ pragma Inline (Body_Placement_Kind_To_Code);
+ -- Obtain the character encoding of body placement kind Kind
+
+ function Code_To_Body_Placement_Kind
+ (Code : Character) return Body_Placement_Kind;
+ pragma Inline (Code_To_Body_Placement_Kind);
+ -- Obtain the body placement kind of character encoding Code
+
+ function Code_To_Invocation_Construct_Kind
+ (Code : Character) return Invocation_Construct_Kind;
+ pragma Inline (Code_To_Invocation_Construct_Kind);
+ -- Obtain the invocation construct kind of character encoding Code
+
+ function Code_To_Invocation_Kind
+ (Code : Character) return Invocation_Kind;
+ pragma Inline (Code_To_Invocation_Kind);
+ -- Obtain the invocation kind of character encoding Code
+
+ function Code_To_Invocation_Graph_Line_Kind
+ (Code : Character) return Invocation_Graph_Line_Kind;
+ pragma Inline (Code_To_Invocation_Graph_Line_Kind);
+ -- Obtain the invocation graph line kind of character encoding Code
+
+ function Invocation_Construct_Kind_To_Code
+ (Kind : Invocation_Construct_Kind) return Character;
+ pragma Inline (Invocation_Construct_Kind_To_Code);
+ -- Obtain the character encoding of invocation kind Kind
+
+ function Invocation_Graph_Line_Kind_To_Code
+ (Kind : Invocation_Graph_Line_Kind) return Character;
+ pragma Inline (Invocation_Graph_Line_Kind_To_Code);
+ -- Obtain the character encoding for invocation like kind Kind
+
+ function Invocation_Kind_To_Code
+ (Kind : Invocation_Kind) return Character;
+ pragma Inline (Invocation_Kind_To_Code);
+ -- Obtain the character encoding of invocation kind Kind
+
+ function Invocation_Signature_Of
+ (Column : Nat;
+ Line : Nat;
+ Locations : Name_Id;
+ Name : Name_Id;
+ Scope : Name_Id) return Invocation_Signature_Id;
+ pragma Inline (Invocation_Signature_Of);
+ -- Obtain the invocation signature that corresponds to the input attributes
+
--------------------------------------
-- Subprograms for Reading ALI File --
--------------------------------------
diff --git a/gcc/ada/binde.adb b/gcc/ada/binde.adb
index f5bd4b8..5caee49 100644
--- a/gcc/ada/binde.adb
+++ b/gcc/ada/binde.adb
@@ -23,20 +23,21 @@
-- --
------------------------------------------------------------------------------
-with Binderr; use Binderr;
-with Butil; use Butil;
-with Debug; use Debug;
-with Fname; use Fname;
-with Opt; use Opt;
+with Binderr; use Binderr;
+with Butil; use Butil;
+with Debug; use Debug;
+with Fname; use Fname;
+with Opt; use Opt;
with Osint;
-with Output; use Output;
+with Output; use Output;
with Table;
+with Types; use Types;
with System.Case_Util; use System.Case_Util;
with System.HTable;
-with System.OS_Lib;
package body Binde is
+ use Unit_Id_Tables;
-- We now have Elab_New, a new elaboration-order algorithm.
--
@@ -113,7 +114,7 @@ package body Binde is
-- elaborated before After is elaborated.
Forced,
- -- Before and After come from a pair of lines in the forced elaboration
+ -- Before and After come from a pair of lines in the forced-elaboration-
-- order file.
Elab,
@@ -380,7 +381,7 @@ package body Binde is
-- "$ must be elaborated before $ ..." where ... is the reason.
procedure Force_Elab_Order;
- -- Gather dependencies from the forced elaboration order file (-f switch)
+ -- Gather dependencies from the forced-elaboration-order file (-f switch)
procedure Gather_Dependencies;
-- Compute dependencies, building the Succ and UNR tables
@@ -1793,30 +1794,13 @@ package body Binde is
----------------------
procedure Force_Elab_Order is
- use System.OS_Lib;
- -- There is a lot of fiddly string manipulation below, because we don't
- -- want to depend on misc utility packages like Ada.Characters.Handling.
-
- function Get_Line return String;
- -- Read the next line from the file content read by Read_File. Strip
- -- all leading and trailing blanks. Convert "(spec)" or "(body)" to
- -- "%s"/"%b". Remove comments (Ada style; "--" to end of line).
-
- function Read_File (Name : String) return String_Ptr;
- -- Read the entire contents of the named file
-
subtype Header_Num is Unit_Name_Type'Base range 0 .. 2**16 - 1;
- type Line_Number is new Nat;
- No_Line_Number : constant Line_Number := 0;
- Cur_Line_Number : Line_Number := 0;
- -- Current line number in the Force_Elab_Order_File.
- -- Incremented by Get_Line. Used in error messages.
function Hash (N : Unit_Name_Type) return Header_Num;
package Name_Map is new System.HTable.Simple_HTable
(Header_Num => Header_Num,
- Element => Line_Number,
+ Element => Logical_Line_Number,
No_Element => No_Line_Number,
Key => Unit_Name_Type,
Hash => Hash,
@@ -1837,234 +1821,86 @@ package body Binde is
return (N - Unit_Name_Type'First) mod (Header_Num'Last + 1);
end Hash;
- ---------------
- -- Read_File --
- ---------------
-
- function Read_File (Name : String) return String_Ptr is
-
- -- All of the following calls should succeed, because we checked the
- -- file in Switch.B, but we double check and raise Program_Error on
- -- failure, just in case.
-
- F : constant File_Descriptor := Open_Read (Name, Binary);
-
- begin
- if F = Invalid_FD then
- raise Program_Error;
- end if;
-
- declare
- Len : constant Natural := Natural (File_Length (F));
- Result : constant String_Ptr := new String (1 .. Len);
- Len_Read : constant Natural :=
- Read (F, Result (1)'Address, Len);
-
- Status : Boolean;
-
- begin
- if Len_Read /= Len then
- raise Program_Error;
- end if;
-
- Close (F, Status);
-
- if not Status then
- raise Program_Error;
- end if;
-
- return Result;
- end;
- end Read_File;
-
- Cur : Positive := 1;
- S : String_Ptr := Read_File (Force_Elab_Order_File.all);
-
- --------------
- -- Get_Line --
- --------------
-
- function Get_Line return String is
- First : Positive := Cur;
- Last : Natural;
-
- begin
- Cur_Line_Number := Cur_Line_Number + 1;
-
- -- Skip to end of line
-
- while Cur <= S'Last
- and then S (Cur) /= ASCII.LF
- and then S (Cur) /= ASCII.CR
- loop
- Cur := Cur + 1;
- end loop;
-
- -- Strip leading blanks
-
- while First <= S'Last and then S (First) = ' ' loop
- First := First + 1;
- end loop;
-
- -- Strip trailing blanks and comment
+ -- Local variables
- Last := Cur - 1;
+ Cur_Line_Number : Logical_Line_Number;
+ Error : Boolean := False;
+ Iter : Forced_Units_Iterator;
+ Prev_Unit : Unit_Id := No_Unit_Id;
+ Uname : Unit_Name_Type;
- for J in First .. Last - 1 loop
- if S (J .. J + 1) = "--" then
- Last := J - 1;
- exit;
- end if;
- end loop;
-
- while Last >= First and then S (Last) = ' ' loop
- Last := Last - 1;
- end loop;
+ -- Start of processing for Force_Elab_Order
- -- Convert "(spec)" or "(body)" to "%s"/"%b", strip trailing blanks
- -- again.
+ begin
+ Iter := Iterate_Forced_Units;
+ while Has_Next (Iter) loop
+ Next (Iter, Uname, Cur_Line_Number);
declare
- Body_String : constant String := "(body)";
- BL : constant Positive := Body_String'Length;
- Spec_String : constant String := "(spec)";
- SL : constant Positive := Spec_String'Length;
-
- Line : String renames S (First .. Last);
-
- Is_Body : Boolean := False;
- Is_Spec : Boolean := False;
-
+ Dup : constant Logical_Line_Number := Name_Map.Get (Uname);
begin
- if Line'Length >= SL
- and then Line (Last - SL + 1 .. Last) = Spec_String
- then
- Is_Spec := True;
- Last := Last - SL;
- elsif Line'Length >= BL
- and then Line (Last - BL + 1 .. Last) = Body_String
- then
- Is_Body := True;
- Last := Last - BL;
- end if;
-
- while Last >= First and then S (Last) = ' ' loop
- Last := Last - 1;
- end loop;
+ if Dup = No_Line_Number then
+ Name_Map.Set (Uname, Cur_Line_Number);
- -- Skip past LF or CR/LF
+ -- We don't need to give the "not present" message in the case
+ -- of "duplicate unit", because we would have already given the
+ -- "not present" message on the first occurrence.
- if Cur <= S'Last and then S (Cur) = ASCII.CR then
- Cur := Cur + 1;
- end if;
-
- if Cur <= S'Last and then S (Cur) = ASCII.LF then
- Cur := Cur + 1;
- end if;
+ if Get_Name_Table_Int (Uname) = 0
+ or else Unit_Id (Get_Name_Table_Int (Uname)) = No_Unit_Id
+ then
+ Error := True;
+ if Doing_New then
+ Write_Line
+ ("""" & Get_Name_String (Uname)
+ & """: not present; ignored");
+ end if;
+ end if;
- if Is_Spec then
- return Line (First .. Last) & "%s";
- elsif Is_Body then
- return Line (First .. Last) & "%b";
else
- return Line;
+ Error := True;
+ if Doing_New then
+ Error_Msg_Nat_1 := Nat (Cur_Line_Number);
+ Error_Msg_Unit_1 := Uname;
+ Error_Msg_Nat_2 := Nat (Dup);
+ Error_Msg
+ (Force_Elab_Order_File.all
+ & ":#: duplicate unit name $ from line #");
+ end if;
end if;
end;
- end Get_Line;
- -- Local variables
-
- Empty_Name : constant Unit_Name_Type := Name_Find ("");
- Prev_Unit : Unit_Id := No_Unit_Id;
-
- -- Start of processing for Force_Elab_Order
-
- begin
- -- Loop through the file content, and build a dependency link for each
- -- pair of lines. Ignore lines that should be ignored.
-
- while Cur <= S'Last loop
- declare
- Uname : constant Unit_Name_Type := Name_Find (Get_Line);
- Error : Boolean := False;
-
- begin
- if Uname = Empty_Name then
- null; -- silently skip blank lines
- else
- declare
- Dup : constant Line_Number := Name_Map.Get (Uname);
- begin
- if Dup = No_Line_Number then
- Name_Map.Set (Uname, Cur_Line_Number);
-
- -- We don't need to give the "not present" message in
- -- the case of "duplicate unit", because we would have
- -- already given the "not present" message on the
- -- first occurrence.
-
- if Get_Name_Table_Int (Uname) = 0
- or else Unit_Id (Get_Name_Table_Int (Uname)) =
- No_Unit_Id
- then
- Error := True;
- if Doing_New then
- Write_Line
- ("""" & Get_Name_String (Uname)
- & """: not present; ignored");
- end if;
- end if;
+ if not Error then
+ declare
+ Cur_Unit : constant Unit_Id := Unit_Id_Of (Uname);
+ begin
+ if Is_Internal_File_Name (Units.Table (Cur_Unit).Sfile) then
+ if Doing_New then
+ Write_Line
+ ("""" & Get_Name_String (Uname)
+ & """: predefined unit ignored");
+ end if;
- else
- Error := True;
+ else
+ if Prev_Unit /= No_Unit_Id then
if Doing_New then
- Error_Msg_Nat_1 := Nat (Cur_Line_Number);
- Error_Msg_Unit_1 := Uname;
- Error_Msg_Nat_2 := Nat (Dup);
- Error_Msg
- (Force_Elab_Order_File.all
- & ":#: duplicate unit name $ from line #");
+ Write_Unit_Name (Units.Table (Prev_Unit).Uname);
+ Write_Str (" <-- ");
+ Write_Unit_Name (Units.Table (Cur_Unit).Uname);
+ Write_Eol;
end if;
- end if;
- end;
-
- if not Error then
- declare
- Cur_Unit : constant Unit_Id := Unit_Id_Of (Uname);
- begin
- if Is_Internal_File_Name
- (Units.Table (Cur_Unit).Sfile)
- then
- if Doing_New then
- Write_Line
- ("""" & Get_Name_String (Uname)
- & """: predefined unit ignored");
- end if;
- else
- if Prev_Unit /= No_Unit_Id then
- if Doing_New then
- Write_Unit_Name (Units.Table (Prev_Unit).Uname);
- Write_Str (" <-- ");
- Write_Unit_Name (Units.Table (Cur_Unit).Uname);
- Write_Eol;
- end if;
-
- Build_Link
- (Before => Prev_Unit,
- After => Cur_Unit,
- R => Forced);
- end if;
+ Build_Link
+ (Before => Prev_Unit,
+ After => Cur_Unit,
+ R => Forced);
+ end if;
- Prev_Unit := Cur_Unit;
- end if;
- end;
+ Prev_Unit := Cur_Unit;
end if;
- end if;
- end;
+ end;
+ end if;
end loop;
-
- Free (S);
end Force_Elab_Order;
-------------------------
diff --git a/gcc/ada/binde.ads b/gcc/ada/binde.ads
index 6412d26..bdea7dc 100644
--- a/gcc/ada/binde.ads
+++ b/gcc/ada/binde.ads
@@ -28,23 +28,9 @@
with ALI; use ALI;
with Namet; use Namet;
-with Types; use Types;
-
-with GNAT.Dynamic_Tables;
package Binde is
- package Unit_Id_Tables is new GNAT.Dynamic_Tables
- (Table_Component_Type => Unit_Id,
- Table_Index_Type => Nat,
- Table_Low_Bound => 1,
- Table_Initial => 500,
- Table_Increment => 200);
- use Unit_Id_Tables;
-
- subtype Unit_Id_Table is Unit_Id_Tables.Instance;
- subtype Unit_Id_Array is Unit_Id_Tables.Table_Type;
-
procedure Find_Elab_Order
(Elab_Order : out Unit_Id_Table;
First_Main_Lib_File : File_Name_Type);
diff --git a/gcc/ada/bindgen.adb b/gcc/ada/bindgen.adb
index b5637a4..e135540 100644
--- a/gcc/ada/bindgen.adb
+++ b/gcc/ada/bindgen.adb
@@ -23,7 +23,6 @@
-- --
------------------------------------------------------------------------------
-with ALI; use ALI;
with Casing; use Casing;
with Fname; use Fname;
with Gnatvsn; use Gnatvsn;
@@ -1805,13 +1804,18 @@ package body Bindgen is
-- referenced elsewhere in the generated program, but is needed by
-- the debugger (that's why it is generated in the first place). The
-- reference stops Ada_Main_Program_Name from being optimized away by
- -- smart linkers, such as the AiX linker.
+ -- smart linkers.
-- Because this variable is unused, we make this variable "aliased"
-- with a pragma Volatile in order to tell the compiler to preserve
-- this variable at any level of optimization.
- if Bind_Main_Program and not CodePeer_Mode then
+ -- CodePeer and CCG do not need this extra code on the other hand
+
+ if Bind_Main_Program
+ and then not CodePeer_Mode
+ and then not Generate_C_Code
+ then
WBI (" Ensure_Reference : aliased System.Address := " &
"Ada_Main_Program_Name'Address;");
WBI (" pragma Volatile (Ensure_Reference);");
diff --git a/gcc/ada/bindgen.ads b/gcc/ada/bindgen.ads
index 86466f4..722cfad 100644
--- a/gcc/ada/bindgen.ads
+++ b/gcc/ada/bindgen.ads
@@ -32,10 +32,9 @@
-- See the body for exact details of the file that is generated
-with Binde; use Binde;
+with ALI; use ALI;
package Bindgen is
-
procedure Gen_Output_File
(Filename : String;
Elab_Order : Unit_Id_Array);
diff --git a/gcc/ada/bindo-augmentors.adb b/gcc/ada/bindo-augmentors.adb
new file mode 100644
index 0000000..f97f0d0
--- /dev/null
+++ b/gcc/ada/bindo-augmentors.adb
@@ -0,0 +1,372 @@
+------------------------------------------------------------------------------
+-- --
+-- GNAT COMPILER COMPONENTS --
+-- --
+-- B I N D O . A U G M E N T O R S --
+-- --
+-- B o d y --
+-- --
+-- Copyright (C) 2019, 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. See the GNU General Public License --
+-- for more details. You should have received a copy of the GNU General --
+-- Public License distributed with GNAT; see file COPYING3. If not, go to --
+-- http://www.gnu.org/licenses for a complete copy of the license. --
+-- --
+-- GNAT was originally developed by the GNAT team at New York University. --
+-- Extensive contributions were provided by Ada Core Technologies Inc. --
+-- --
+------------------------------------------------------------------------------
+
+with Debug; use Debug;
+with Output; use Output;
+with Types; use Types;
+
+with Bindo.Writers; use Bindo.Writers;
+
+with GNAT; use GNAT;
+with GNAT.Sets; use GNAT.Sets;
+
+package body Bindo.Augmentors is
+
+ ------------------------------
+ -- Library_Graph_Augmentors --
+ ------------------------------
+
+ package body Library_Graph_Augmentors is
+
+ -----------------
+ -- Visited set --
+ -----------------
+
+ package VS is new Membership_Sets
+ (Element_Type => Invocation_Graph_Vertex_Id,
+ "=" => "=",
+ Hash => Hash_Invocation_Graph_Vertex);
+ use VS;
+
+ -----------------
+ -- Global data --
+ -----------------
+
+ Inv_Graph : Invocation_Graph := Invocation_Graphs.Nil;
+ Lib_Graph : Library_Graph := Library_Graphs.Nil;
+ Visited : Membership_Set := VS.Nil;
+
+ ----------------
+ -- Statistics --
+ ----------------
+
+ Longest_Path : Natural := 0;
+ -- The length of the longest path found during the traversal of the
+ -- invocation graph.
+
+ Total_Visited : Natural := 0;
+ -- The number of visited invocation graph vertices during the process
+ -- of augmentation.
+
+ -----------------------
+ -- Local subprograms --
+ -----------------------
+
+ function Is_Visited
+ (IGV_Id : Invocation_Graph_Vertex_Id) return Boolean;
+ pragma Inline (Is_Visited);
+ -- Determine whether invocation graph vertex IGV_Id has been visited
+ -- during the traversal.
+
+ procedure Set_Is_Visited
+ (IGV_Id : Invocation_Graph_Vertex_Id;
+ Val : Boolean := True);
+ pragma Inline (Set_Is_Visited);
+ -- Mark invocation graph vertex IGV_Id as visited during the traversal
+ -- depending on value Val.
+
+ procedure Visit_Elaboration_Root (Root : Invocation_Graph_Vertex_Id);
+ pragma Inline (Visit_Elaboration_Root);
+ -- Start a DFS traversal from elaboration root Root to:
+ --
+ -- * Detect transitions between units.
+ --
+ -- * Create invocation edges for each such transition where the
+ -- successor is Root.
+
+ procedure Visit_Elaboration_Roots;
+ pragma Inline (Visit_Elaboration_Roots);
+ -- Start a DFS traversal from all elaboration roots to:
+ --
+ -- * Detect transitions between units.
+ --
+ -- * Create invocation edges for each such transition where the
+ -- successor is the current root.
+
+ procedure Visit_Vertex
+ (Curr_IGV_Id : Invocation_Graph_Vertex_Id;
+ Last_LGV_Id : Library_Graph_Vertex_Id;
+ Root_LGV_Id : Library_Graph_Vertex_Id;
+ Internal_Ctrl : Boolean;
+ Path : Natural);
+ pragma Inline (Visit_Vertex);
+ -- Visit invocation graph vertex Curr_IGV_Id to:
+ --
+ -- * Detect a transition from the last library graph vertex denoted by
+ -- Last_LGV_Id to the library graph vertex of Curr_IGV_Id.
+ --
+ -- * Create an invocation edge in library graph Lib_Graph to reflect
+ -- the transition, where the predecessor is the library graph vertex
+ -- or Curr_IGV_Id, and the successor is Root_LGV_Id.
+ --
+ -- * Visit the neighbours of Curr_IGV_Id.
+ --
+ -- Flag Internal_Ctrl should be set when the DFS traversal visited an
+ -- internal controlled invocation edge. Path denotes the length of the
+ -- path.
+
+ procedure Write_Statistics;
+ pragma Inline (Write_Statistics);
+ -- Write the statistical information of the augmentation to standard
+ -- output.
+
+ ---------------------------
+ -- Augment_Library_Graph --
+ ---------------------------
+
+ procedure Augment_Library_Graph
+ (Inv_G : Invocation_Graph;
+ Lib_G : Library_Graph)
+ is
+ begin
+ pragma Assert (Present (Lib_G));
+
+ -- Nothing to do when there is no invocation graph
+
+ if not Present (Inv_G) then
+ return;
+ end if;
+
+ -- Prepare the global data. Note that Visited is initialized for each
+ -- elaboration root.
+
+ Inv_Graph := Inv_G;
+ Lib_Graph := Lib_G;
+ Longest_Path := 0;
+ Total_Visited := 0;
+
+ Visit_Elaboration_Roots;
+ Write_Statistics;
+ end Augment_Library_Graph;
+
+ ----------------
+ -- Is_Visited --
+ ----------------
+
+ function Is_Visited
+ (IGV_Id : Invocation_Graph_Vertex_Id) return Boolean
+ is
+ begin
+ pragma Assert (Present (Visited));
+ pragma Assert (Present (IGV_Id));
+
+ return Contains (Visited, IGV_Id);
+ end Is_Visited;
+
+ --------------------
+ -- Set_Is_Visited --
+ --------------------
+
+ procedure Set_Is_Visited
+ (IGV_Id : Invocation_Graph_Vertex_Id;
+ Val : Boolean := True)
+ is
+ begin
+ pragma Assert (Present (Visited));
+ pragma Assert (Present (IGV_Id));
+
+ if Val then
+ Insert (Visited, IGV_Id);
+ else
+ Delete (Visited, IGV_Id);
+ end if;
+ end Set_Is_Visited;
+
+ ----------------------------
+ -- Visit_Elaboration_Root --
+ ----------------------------
+
+ procedure Visit_Elaboration_Root (Root : Invocation_Graph_Vertex_Id) is
+ pragma Assert (Present (Inv_Graph));
+ pragma Assert (Present (Root));
+ pragma Assert (Present (Lib_Graph));
+
+ Root_LGV_Id : constant Library_Graph_Vertex_Id :=
+ Lib_Vertex (Inv_Graph, Root);
+
+ pragma Assert (Present (Root_LGV_Id));
+
+ begin
+ -- Prepare the global data
+
+ Visited := Create (Number_Of_Vertices (Inv_Graph));
+
+ Visit_Vertex
+ (Curr_IGV_Id => Root,
+ Last_LGV_Id => Root_LGV_Id,
+ Root_LGV_Id => Root_LGV_Id,
+ Internal_Ctrl => False,
+ Path => 0);
+
+ Destroy (Visited);
+ end Visit_Elaboration_Root;
+
+ -----------------------------
+ -- Visit_Elaboration_Roots --
+ -----------------------------
+
+ procedure Visit_Elaboration_Roots is
+ Iter : Elaboration_Root_Iterator;
+ Root : Invocation_Graph_Vertex_Id;
+
+ begin
+ pragma Assert (Present (Inv_Graph));
+
+ Iter := Iterate_Elaboration_Roots (Inv_Graph);
+ while Has_Next (Iter) loop
+ Next (Iter, Root);
+ pragma Assert (Present (Root));
+
+ Visit_Elaboration_Root (Root);
+ end loop;
+ end Visit_Elaboration_Roots;
+
+ ------------------
+ -- Visit_Vertex --
+ ------------------
+
+ procedure Visit_Vertex
+ (Curr_IGV_Id : Invocation_Graph_Vertex_Id;
+ Last_LGV_Id : Library_Graph_Vertex_Id;
+ Root_LGV_Id : Library_Graph_Vertex_Id;
+ Internal_Ctrl : Boolean;
+ Path : Natural)
+ is
+ New_Path : constant Natural := Path + 1;
+
+ Curr_LGV_Id : Library_Graph_Vertex_Id;
+ IGE_Id : Invocation_Graph_Edge_Id;
+ Iter : Edges_To_Targets_Iterator;
+ Targ : Invocation_Graph_Vertex_Id;
+
+ begin
+ pragma Assert (Present (Inv_Graph));
+ pragma Assert (Present (Curr_IGV_Id));
+ pragma Assert (Present (Lib_Graph));
+ pragma Assert (Present (Last_LGV_Id));
+ pragma Assert (Present (Root_LGV_Id));
+
+ -- Nothing to do when the current invocation graph vertex has already
+ -- been visited.
+
+ if Is_Visited (Curr_IGV_Id) then
+ return;
+ end if;
+
+ Set_Is_Visited (Curr_IGV_Id);
+
+ -- Update the statistics
+
+ Longest_Path := Natural'Max (Longest_Path, New_Path);
+ Total_Visited := Total_Visited + 1;
+
+ -- The library graph vertex of the current invocation graph vertex
+ -- differs from that of the previous invocation graph vertex. This
+ -- indicates that elaboration is transitioning from one unit to
+ -- another. Add a library graph edge to capture this dependency.
+
+ Curr_LGV_Id := Lib_Vertex (Inv_Graph, Curr_IGV_Id);
+ pragma Assert (Present (Curr_LGV_Id));
+
+ if Curr_LGV_Id /= Last_LGV_Id then
+
+ -- The path ultimately reaches back into the unit where the root
+ -- resides, resulting in a self dependency. In most cases this is
+ -- a valid circularity, except when the path went through one of
+ -- the Deep_xxx finalization-related routines. Do not create a
+ -- library graph edge because the circularity is the result of
+ -- expansion and thus spurious.
+
+ if Curr_LGV_Id = Root_LGV_Id and then Internal_Ctrl then
+ null;
+
+ -- Otherwise create the library graph edge, even if this results
+ -- in a self dependency.
+
+ else
+ Add_Edge
+ (G => Lib_Graph,
+ Pred => Curr_LGV_Id,
+ Succ => Root_LGV_Id,
+ Kind => Invocation_Edge);
+ end if;
+ end if;
+
+ -- Extend the DFS traversal to all targets of the invocation graph
+ -- vertex.
+
+ Iter := Iterate_Edges_To_Targets (Inv_Graph, Curr_IGV_Id);
+ while Has_Next (Iter) loop
+ Next (Iter, IGE_Id);
+ pragma Assert (Present (IGE_Id));
+
+ Targ := Target (Inv_Graph, IGE_Id);
+ pragma Assert (Present (Targ));
+
+ Visit_Vertex
+ (Curr_IGV_Id => Targ,
+ Last_LGV_Id => Curr_LGV_Id,
+ Root_LGV_Id => Root_LGV_Id,
+ Internal_Ctrl =>
+ Internal_Ctrl
+ or else Kind (Inv_Graph, IGE_Id) in
+ Internal_Controlled_Invocation_Kind,
+ Path => New_Path);
+ end loop;
+ end Visit_Vertex;
+
+ ----------------------
+ -- Write_Statistics --
+ ----------------------
+
+ procedure Write_Statistics is
+ begin
+ -- Nothing to do when switch -d_L (output library item graph) is not
+ -- in effect.
+
+ if not Debug_Flag_Underscore_LL then
+ return;
+ end if;
+
+ Write_Str ("Library Graph Augmentation");
+ Write_Eol;
+ Write_Eol;
+
+ Write_Str ("Vertices visited : ");
+ Write_Num (Int (Total_Visited));
+ Write_Eol;
+
+ Write_Str ("Longest path length: ");
+ Write_Num (Int (Longest_Path));
+ Write_Eol;
+ Write_Eol;
+
+ Write_Str ("Library Graph Augmentation end");
+ Write_Eol;
+ Write_Eol;
+ end Write_Statistics;
+ end Library_Graph_Augmentors;
+
+end Bindo.Augmentors;
diff --git a/gcc/ada/bindo-augmentors.ads b/gcc/ada/bindo-augmentors.ads
new file mode 100644
index 0000000..de6317c
--- /dev/null
+++ b/gcc/ada/bindo-augmentors.ads
@@ -0,0 +1,62 @@
+------------------------------------------------------------------------------
+-- --
+-- GNAT COMPILER COMPONENTS --
+-- --
+-- B I N D O . A U G M E N T O R S --
+-- --
+-- S p e c --
+-- --
+-- Copyright (C) 2019, 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. See the GNU General Public License --
+-- for more details. You should have received a copy of the GNU General --
+-- Public License distributed with GNAT; see file COPYING3. If not, go to --
+-- http://www.gnu.org/licenses for a complete copy of the license. --
+-- --
+-- GNAT was originally developed by the GNAT team at New York University. --
+-- Extensive contributions were provided by Ada Core Technologies Inc. --
+-- --
+------------------------------------------------------------------------------
+
+-- For full architecture, see unit Bindo.
+
+-- The following unit contains facilities to enhance the library graph, which
+-- reflects source dependencies between units, with information obtained from
+-- the invocation graph, which reflects all activations of tasks, calls, and
+-- instantiations within units.
+
+with Bindo.Graphs;
+use Bindo.Graphs;
+use Bindo.Graphs.Invocation_Graphs;
+use Bindo.Graphs.Library_Graphs;
+
+package Bindo.Augmentors is
+
+ ------------------------------
+ -- Library_Graph_Augmentors --
+ ------------------------------
+
+ package Library_Graph_Augmentors is
+ procedure Augment_Library_Graph
+ (Inv_G : Invocation_Graph;
+ Lib_G : Library_Graph);
+ -- Augment library graph Lib_G with information from invocation graph
+ -- Inv_G as follows:
+ --
+ -- 1) Traverse the invocation graph starting from each elaboration
+ -- procedure of unit Root.
+ --
+ -- 2) Each time the traversal transitions from one unit into another
+ -- unit Curr, add an invocation edge between predecessor Curr and
+ -- successor Root in the library graph.
+ --
+ -- 3) Do the above steps for all units with an elaboration procedure.
+
+ end Library_Graph_Augmentors;
+
+end Bindo.Augmentors;
diff --git a/gcc/ada/bindo-builders.adb b/gcc/ada/bindo-builders.adb
new file mode 100644
index 0000000..c0340c0
--- /dev/null
+++ b/gcc/ada/bindo-builders.adb
@@ -0,0 +1,748 @@
+------------------------------------------------------------------------------
+-- --
+-- GNAT COMPILER COMPONENTS --
+-- --
+-- B I N D O . B U I L D E R S --
+-- --
+-- B o d y --
+-- --
+-- Copyright (C) 2019, 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. See the GNU General Public License --
+-- for more details. You should have received a copy of the GNU General --
+-- Public License distributed with GNAT; see file COPYING3. If not, go to --
+-- http://www.gnu.org/licenses for a complete copy of the license. --
+-- --
+-- GNAT was originally developed by the GNAT team at New York University. --
+-- Extensive contributions were provided by Ada Core Technologies Inc. --
+-- --
+------------------------------------------------------------------------------
+
+with Binderr; use Binderr;
+with Butil; use Butil;
+with Opt; use Opt;
+with Output; use Output;
+with Types; use Types;
+
+with Bindo.Units; use Bindo.Units;
+
+with GNAT; use GNAT;
+with GNAT.Dynamic_HTables; use GNAT.Dynamic_HTables;
+
+package body Bindo.Builders is
+
+ -------------------------------
+ -- Invocation_Graph_Builders --
+ -------------------------------
+
+ package body Invocation_Graph_Builders is
+
+ -----------------
+ -- Global data --
+ -----------------
+
+ Inv_Graph : Invocation_Graph := Invocation_Graphs.Nil;
+ Lib_Graph : Library_Graph := Library_Graphs.Nil;
+
+ -----------------------
+ -- Local subprograms --
+ -----------------------
+
+ procedure Create_Edge (IR_Id : Invocation_Relation_Id);
+ pragma Inline (Create_Edge);
+ -- Create a new edge for invocation relation IR_Id in invocation graph
+ -- Inv_Graph.
+
+ procedure Create_Edges (U_Id : Unit_Id);
+ pragma Inline (Create_Edges);
+ -- Create new edges for all invocation relations of unit U_Id
+
+ procedure Create_Vertex
+ (IC_Id : Invocation_Construct_Id;
+ LGV_Id : Library_Graph_Vertex_Id);
+ pragma Inline (Create_Vertex);
+ -- Create a new vertex for invocation construct IC_Id in invocation
+ -- graph Inv_Graph. The vertex is linked to vertex LGV_Id of library
+ -- graph Lib_Graph.
+
+ procedure Create_Vertices (U_Id : Unit_Id);
+ pragma Inline (Create_Vertices);
+ -- Create new vertices for all invocation constructs of unit U_Id in
+ -- invocation graph Inv_Graph.
+
+ ----------------------------
+ -- Build_Invocation_Graph --
+ ----------------------------
+
+ function Build_Invocation_Graph
+ (Lib_G : Library_Graph) return Invocation_Graph
+ is
+ begin
+ pragma Assert (Present (Lib_G));
+
+ -- Prepare the global data
+
+ Inv_Graph :=
+ Create (Initial_Vertices => Number_Of_Elaborable_Units,
+ Initial_Edges => Number_Of_Elaborable_Units);
+ Lib_Graph := Lib_G;
+
+ For_Each_Elaborable_Unit (Create_Vertices'Access);
+ For_Each_Elaborable_Unit (Create_Edges'Access);
+
+ return Inv_Graph;
+ end Build_Invocation_Graph;
+
+ -----------------
+ -- Create_Edge --
+ -----------------
+
+ procedure Create_Edge (IR_Id : Invocation_Relation_Id) is
+ pragma Assert (Present (Inv_Graph));
+ pragma Assert (Present (Lib_Graph));
+ pragma Assert (Present (IR_Id));
+
+ IR_Rec : Invocation_Relation_Record renames
+ Invocation_Relations.Table (IR_Id);
+
+ pragma Assert (Present (IR_Rec.Invoker));
+ pragma Assert (Present (IR_Rec.Target));
+
+ Invoker : Invocation_Graph_Vertex_Id;
+ Target : Invocation_Graph_Vertex_Id;
+
+ begin
+ -- Nothing to do when the target denotes an invocation construct that
+ -- resides in a unit which will never be elaborated.
+
+ if not Needs_Elaboration (IR_Rec.Target) then
+ return;
+ end if;
+
+ Invoker := Corresponding_Vertex (Inv_Graph, IR_Rec.Invoker);
+ Target := Corresponding_Vertex (Inv_Graph, IR_Rec.Target);
+
+ pragma Assert (Present (Invoker));
+ pragma Assert (Present (Target));
+
+ Add_Edge
+ (G => Inv_Graph,
+ Source => Invoker,
+ Target => Target,
+ IR_Id => IR_Id);
+ end Create_Edge;
+
+ ------------------
+ -- Create_Edges --
+ ------------------
+
+ procedure Create_Edges (U_Id : Unit_Id) is
+ pragma Assert (Present (Inv_Graph));
+ pragma Assert (Present (Lib_Graph));
+ pragma Assert (Present (U_Id));
+
+ U_Rec : Unit_Record renames ALI.Units.Table (U_Id);
+
+ begin
+ for IR_Id in U_Rec.First_Invocation_Relation ..
+ U_Rec.Last_Invocation_Relation
+ loop
+ Create_Edge (IR_Id);
+ end loop;
+ end Create_Edges;
+
+ -------------------
+ -- Create_Vertex --
+ -------------------
+
+ procedure Create_Vertex
+ (IC_Id : Invocation_Construct_Id;
+ LGV_Id : Library_Graph_Vertex_Id)
+ is
+ pragma Assert (Present (Inv_Graph));
+ pragma Assert (Present (Lib_Graph));
+ pragma Assert (Present (IC_Id));
+ pragma Assert (Present (LGV_Id));
+
+ IC_Rec : Invocation_Construct_Record renames
+ Invocation_Constructs.Table (IC_Id);
+
+ Body_LGV_Id : Library_Graph_Vertex_Id;
+
+ begin
+ -- Determine the proper library graph vertex which holds the body of
+ -- the invocation construct.
+
+ if IC_Rec.Placement = In_Body then
+ Body_LGV_Id := Proper_Body (Lib_Graph, LGV_Id);
+ else
+ pragma Assert (IC_Rec.Placement = In_Spec);
+ Body_LGV_Id := Proper_Spec (Lib_Graph, LGV_Id);
+ end if;
+
+ pragma Assert (Present (Body_LGV_Id));
+
+ Add_Vertex
+ (G => Inv_Graph,
+ IC_Id => IC_Id,
+ LGV_Id => Body_LGV_Id);
+ end Create_Vertex;
+
+ ---------------------
+ -- Create_Vertices --
+ ---------------------
+
+ procedure Create_Vertices (U_Id : Unit_Id) is
+ pragma Assert (Present (Inv_Graph));
+ pragma Assert (Present (Lib_Graph));
+ pragma Assert (Present (U_Id));
+
+ U_Rec : Unit_Record renames ALI.Units.Table (U_Id);
+ LGV_Id : constant Library_Graph_Vertex_Id :=
+ Corresponding_Vertex (Lib_Graph, U_Id);
+
+ pragma Assert (Present (LGV_Id));
+
+ begin
+ for IC_Id in U_Rec.First_Invocation_Construct ..
+ U_Rec.Last_Invocation_Construct
+ loop
+ Create_Vertex (IC_Id, LGV_Id);
+ end loop;
+ end Create_Vertices;
+ end Invocation_Graph_Builders;
+
+ ----------------------------
+ -- Library_Graph_Builders --
+ ----------------------------
+
+ package body Library_Graph_Builders is
+
+ ---------------------
+ -- Data structures --
+ ---------------------
+
+ procedure Destroy_Line_Number (Line : in out Logical_Line_Number);
+ pragma Inline (Destroy_Line_Number);
+ -- Destroy line number Line
+
+ function Hash_Unit (U_Id : Unit_Id) return Bucket_Range_Type;
+ pragma Inline (Hash_Unit);
+ -- Obtain the hash value of key U_Id
+
+ package UL is new Dynamic_Hash_Tables
+ (Key_Type => Unit_Id,
+ Value_Type => Logical_Line_Number,
+ No_Value => No_Line_Number,
+ Expansion_Threshold => 1.5,
+ Expansion_Factor => 2,
+ Compression_Threshold => 0.3,
+ Compression_Factor => 2,
+ "=" => "=",
+ Destroy_Value => Destroy_Line_Number,
+ Hash => Hash_Unit);
+
+ -----------------
+ -- Global data --
+ -----------------
+
+ Lib_Graph : Library_Graph := Library_Graphs.Nil;
+
+ Unit_To_Line : UL.Dynamic_Hash_Table := UL.Nil;
+ -- The map of unit name -> line number, used to detect duplicate unit
+ -- names and report errors.
+
+ -----------------------
+ -- Local subprograms --
+ -----------------------
+
+ procedure Add_Unit
+ (U_Id : Unit_Id;
+ Line : Logical_Line_Number);
+ pragma Inline (Add_Unit);
+ -- Create a relationship between unit U_Id and its declaration line in
+ -- map Unit_To_Line.
+
+ procedure Create_Forced_Edge
+ (Pred : Unit_Id;
+ Succ : Unit_Id);
+ pragma Inline (Create_Forced_Edge);
+ -- Create a new forced edge between predecessor unit Pred and successor
+ -- unit Succ.
+
+ procedure Create_Forced_Edges;
+ pragma Inline (Create_Forced_Edges);
+ -- Inspect the contents of the forced-elaboration-order file, and create
+ -- specialized edges for each valid pair of units listed within.
+
+ procedure Create_Spec_And_Body_Edge (U_Id : Unit_Id);
+ pragma Inline (Create_Spec_And_Body_Edge);
+ -- Establish a link between the spec and body of unit U_Id. In certain
+ -- cases this may result in a new edge which is added to library graph
+ -- Lib_Graph.
+
+ procedure Create_Vertex (U_Id : Unit_Id);
+ pragma Inline (Create_Vertex);
+ -- Create a new vertex for unit U_Id in library graph Lib_Graph
+
+ procedure Create_With_Edge
+ (W_Id : With_Id;
+ Succ : Library_Graph_Vertex_Id);
+ pragma Inline (Create_With_Edge);
+ -- Create a new edge for with W_Id where the predecessor is the library
+ -- graph vertex of the withed unit, and the successor is Succ. The edge
+ -- is added to library graph Lib_Graph.
+
+ procedure Create_With_Edges (U_Id : Unit_Id);
+ pragma Inline (Create_With_Edges);
+ -- Establish links between unit U_Id and its predecessor units. The new
+ -- edges are added to library graph Lib_Graph.
+
+ procedure Create_With_Edges
+ (U_Id : Unit_Id;
+ Succ : Library_Graph_Vertex_Id);
+ pragma Inline (Create_With_Edges);
+ -- Create new edges for all withs of unit U_Id where the predecessor is
+ -- some withed unit, and the successor is Succ. The edges are added to
+ -- library graph Lib_Graph.
+
+ procedure Duplicate_Unit_Error
+ (U_Id : Unit_Id;
+ Nam : Unit_Name_Type;
+ Line : Logical_Line_Number);
+ pragma Inline (Duplicate_Unit_Error);
+ -- Emit an error concerning the duplication of unit U_Id with name Nam
+ -- that is redeclared in the forced-elaboration-order file at line Line.
+
+ procedure Internal_Unit_Info (Nam : Unit_Name_Type);
+ pragma Inline (Internal_Unit_Info);
+ -- Emit an information message concerning the omission of an internal
+ -- unit with name Nam from the creation of forced edges.
+
+ function Is_Duplicate_Unit (U_Id : Unit_Id) return Boolean;
+ pragma Inline (Is_Duplicate_Unit);
+ -- Determine whether unit U_Id is already recorded in map Unit_To_Line
+
+ function Is_Significant_With (W_Id : With_Id) return Boolean;
+ pragma Inline (Is_Significant_With);
+ -- Determine whether with W_Id plays a significant role in elaboration
+
+ procedure Missing_Unit_Info (Nam : Unit_Name_Type);
+ pragma Inline (Missing_Unit_Info);
+ -- Emit an information message concerning the omission of an undefined
+ -- unit found in the forced-elaboration-order file.
+
+ --------------
+ -- Add_Unit --
+ --------------
+
+ procedure Add_Unit
+ (U_Id : Unit_Id;
+ Line : Logical_Line_Number)
+ is
+ begin
+ pragma Assert (Present (U_Id));
+
+ UL.Put (Unit_To_Line, U_Id, Line);
+ end Add_Unit;
+
+ -------------------------
+ -- Build_Library_Graph --
+ -------------------------
+
+ function Build_Library_Graph return Library_Graph is
+ begin
+ -- Prepare the global data
+
+ Lib_Graph :=
+ Create (Initial_Vertices => Number_Of_Elaborable_Units,
+ Initial_Edges => Number_Of_Elaborable_Units);
+
+ For_Each_Elaborable_Unit (Create_Vertex'Access);
+ For_Each_Elaborable_Unit (Create_Spec_And_Body_Edge'Access);
+ For_Each_Elaborable_Unit (Create_With_Edges'Access);
+
+ Create_Forced_Edges;
+
+ return Lib_Graph;
+ end Build_Library_Graph;
+
+ ------------------------
+ -- Create_Forced_Edge --
+ ------------------------
+
+ procedure Create_Forced_Edge
+ (Pred : Unit_Id;
+ Succ : Unit_Id)
+ is
+ pragma Assert (Present (Pred));
+ pragma Assert (Present (Succ));
+
+ Pred_LGV_Id : constant Library_Graph_Vertex_Id :=
+ Corresponding_Vertex (Lib_Graph, Pred);
+ Succ_LGV_Id : constant Library_Graph_Vertex_Id :=
+ Corresponding_Vertex (Lib_Graph, Succ);
+
+ pragma Assert (Present (Pred_LGV_Id));
+ pragma Assert (Present (Succ_LGV_Id));
+
+ begin
+ Write_Unit_Name (Name (Pred));
+ Write_Str (" <-- ");
+ Write_Unit_Name (Name (Succ));
+ Write_Eol;
+
+ Add_Edge
+ (G => Lib_Graph,
+ Pred => Pred_LGV_Id,
+ Succ => Succ_LGV_Id,
+ Kind => Forced_Edge);
+ end Create_Forced_Edge;
+
+ -------------------------
+ -- Create_Forced_Edges --
+ -------------------------
+
+ procedure Create_Forced_Edges is
+ Curr_Unit : Unit_Id;
+ Iter : Forced_Units_Iterator;
+ Prev_Unit : Unit_Id;
+ Unit_Line : Logical_Line_Number;
+ Unit_Name : Unit_Name_Type;
+
+ begin
+ Prev_Unit := No_Unit_Id;
+ Unit_To_Line := UL.Create (20);
+
+ -- Inspect the contents of the forced-elaboration-order file supplied
+ -- to the binder using switch -f, and diagnose each unit accordingly.
+
+ Iter := Iterate_Forced_Units;
+ while Has_Next (Iter) loop
+ Next (Iter, Unit_Name, Unit_Line);
+ pragma Assert (Present (Unit_Name));
+
+ Curr_Unit := Corresponding_Unit (Unit_Name);
+
+ if not Present (Curr_Unit) then
+ Missing_Unit_Info (Unit_Name);
+
+ elsif Is_Internal_Unit (Curr_Unit) then
+ Internal_Unit_Info (Unit_Name);
+
+ elsif Is_Duplicate_Unit (Curr_Unit) then
+ Duplicate_Unit_Error (Curr_Unit, Unit_Name, Unit_Line);
+
+ -- Otherwise the unit is a valid candidate for a vertex. Create a
+ -- forced edge between each pair of units.
+
+ else
+ Add_Unit (Curr_Unit, Unit_Line);
+
+ if Present (Prev_Unit) then
+ Create_Forced_Edge
+ (Pred => Prev_Unit,
+ Succ => Curr_Unit);
+ end if;
+
+ Prev_Unit := Curr_Unit;
+ end if;
+ end loop;
+
+ UL.Destroy (Unit_To_Line);
+ end Create_Forced_Edges;
+
+ -------------------------------
+ -- Create_Spec_And_Body_Edge --
+ -------------------------------
+
+ procedure Create_Spec_And_Body_Edge (U_Id : Unit_Id) is
+ Aux_LGV_Id : Library_Graph_Vertex_Id;
+ LGV_Id : Library_Graph_Vertex_Id;
+
+ begin
+ pragma Assert (Present (Lib_Graph));
+ pragma Assert (Present (U_Id));
+
+ LGV_Id := Corresponding_Vertex (Lib_Graph, U_Id);
+ pragma Assert (Present (LGV_Id));
+
+ -- The unit denotes a body that completes a previous spec. Link the
+ -- spec and body. Add an edge between the predecessor spec and the
+ -- successor body.
+
+ if Is_Body_With_Spec (Lib_Graph, LGV_Id) then
+ Aux_LGV_Id :=
+ Corresponding_Vertex (Lib_Graph, Corresponding_Spec (U_Id));
+ pragma Assert (Present (Aux_LGV_Id));
+
+ Set_Corresponding_Item (Lib_Graph, LGV_Id, Aux_LGV_Id);
+
+ Add_Edge
+ (G => Lib_Graph,
+ Pred => Aux_LGV_Id,
+ Succ => LGV_Id,
+ Kind => Spec_Before_Body_Edge);
+
+ -- The unit denotes a spec with a completing body. Link the spec and
+ -- body.
+
+ elsif Is_Spec_With_Body (Lib_Graph, LGV_Id) then
+ Aux_LGV_Id :=
+ Corresponding_Vertex (Lib_Graph, Corresponding_Body (U_Id));
+ pragma Assert (Present (Aux_LGV_Id));
+
+ Set_Corresponding_Item (Lib_Graph, LGV_Id, Aux_LGV_Id);
+ end if;
+ end Create_Spec_And_Body_Edge;
+
+ -------------------
+ -- Create_Vertex --
+ -------------------
+
+ procedure Create_Vertex (U_Id : Unit_Id) is
+ begin
+ pragma Assert (Present (Lib_Graph));
+ pragma Assert (Present (U_Id));
+
+ Add_Vertex
+ (G => Lib_Graph,
+ U_Id => U_Id);
+ end Create_Vertex;
+
+ ----------------------
+ -- Create_With_Edge --
+ ----------------------
+
+ procedure Create_With_Edge
+ (W_Id : With_Id;
+ Succ : Library_Graph_Vertex_Id)
+ is
+ pragma Assert (Present (Lib_Graph));
+ pragma Assert (Present (W_Id));
+ pragma Assert (Present (Succ));
+
+ Withed_Rec : With_Record renames Withs.Table (W_Id);
+ Withed_U_Id : constant Unit_Id :=
+ Corresponding_Unit (Withed_Rec.Uname);
+
+ pragma Assert (Present (Withed_U_Id));
+
+ Aux_LGV_Id : Library_Graph_Vertex_Id;
+ Kind : Library_Graph_Edge_Kind;
+ Withed_LGV_Id : Library_Graph_Vertex_Id;
+
+ begin
+ -- Nothing to do when the withed unit does not need to be elaborated.
+ -- This prevents spurious dependencies that can never be satisfied.
+
+ if not Needs_Elaboration (Withed_U_Id) then
+ return;
+ end if;
+
+ Withed_LGV_Id := Corresponding_Vertex (Lib_Graph, Withed_U_Id);
+ pragma Assert (Present (Withed_LGV_Id));
+
+ -- The with comes with pragma Elaborate
+
+ if Withed_Rec.Elaborate then
+ Kind := Elaborate_Edge;
+
+ -- The withed unit is a spec with a completing body. Add an edge
+ -- between the body of the withed predecessor and the withing
+ -- successor.
+
+ if Is_Spec_With_Body (Lib_Graph, Withed_LGV_Id) then
+ Aux_LGV_Id :=
+ Corresponding_Vertex
+ (Lib_Graph, Corresponding_Body (Withed_U_Id));
+ pragma Assert (Present (Aux_LGV_Id));
+
+ Add_Edge
+ (G => Lib_Graph,
+ Pred => Aux_LGV_Id,
+ Succ => Succ,
+ Kind => Kind);
+ end if;
+
+ -- The with comes with pragma Elaborate_All
+
+ elsif Withed_Rec.Elaborate_All then
+ Kind := Elaborate_All_Edge;
+
+ -- Otherwise this is a regular with
+
+ else
+ Kind := With_Edge;
+ end if;
+
+ -- Add an edge between the withed predecessor unit and the withing
+ -- successor.
+
+ Add_Edge
+ (G => Lib_Graph,
+ Pred => Withed_LGV_Id,
+ Succ => Succ,
+ Kind => Kind);
+ end Create_With_Edge;
+
+ -----------------------
+ -- Create_With_Edges --
+ -----------------------
+
+ procedure Create_With_Edges (U_Id : Unit_Id) is
+ LGV_Id : Library_Graph_Vertex_Id;
+
+ begin
+ pragma Assert (Present (Lib_Graph));
+ pragma Assert (Present (U_Id));
+
+ LGV_Id := Corresponding_Vertex (Lib_Graph, U_Id);
+ pragma Assert (Present (LGV_Id));
+
+ Create_With_Edges
+ (U_Id => U_Id,
+ Succ => LGV_Id);
+ end Create_With_Edges;
+
+ -----------------------
+ -- Create_With_Edges --
+ -----------------------
+
+ procedure Create_With_Edges
+ (U_Id : Unit_Id;
+ Succ : Library_Graph_Vertex_Id)
+ is
+ pragma Assert (Present (Lib_Graph));
+ pragma Assert (Present (U_Id));
+ pragma Assert (Present (Succ));
+
+ U_Rec : Unit_Record renames ALI.Units.Table (U_Id);
+
+ begin
+ for W_Id in U_Rec.First_With .. U_Rec.Last_With loop
+ if Is_Significant_With (W_Id) then
+ Create_With_Edge (W_Id, Succ);
+ end if;
+ end loop;
+ end Create_With_Edges;
+
+ ------------------
+ -- Destroy_Unit --
+ ------------------
+
+ procedure Destroy_Line_Number (Line : in out Logical_Line_Number) is
+ pragma Unreferenced (Line);
+ begin
+ null;
+ end Destroy_Line_Number;
+
+ --------------------------
+ -- Duplicate_Unit_Error --
+ --------------------------
+
+ procedure Duplicate_Unit_Error
+ (U_Id : Unit_Id;
+ Nam : Unit_Name_Type;
+ Line : Logical_Line_Number)
+ is
+ pragma Assert (Present (U_Id));
+ pragma Assert (Present (Nam));
+
+ Prev_Line : constant Logical_Line_Number :=
+ UL.Get (Unit_To_Line, U_Id);
+
+ begin
+ Error_Msg_Nat_1 := Nat (Line);
+ Error_Msg_Nat_2 := Nat (Prev_Line);
+ Error_Msg_Unit_1 := Nam;
+
+ Error_Msg
+ (Force_Elab_Order_File.all
+ & ":#: duplicate unit name $ from line #");
+ end Duplicate_Unit_Error;
+
+ ---------------
+ -- Hash_Unit --
+ ---------------
+
+ function Hash_Unit (U_Id : Unit_Id) return Bucket_Range_Type is
+ begin
+ pragma Assert (Present (U_Id));
+
+ return Bucket_Range_Type (U_Id);
+ end Hash_Unit;
+
+ ------------------------
+ -- Internal_Unit_Info --
+ ------------------------
+
+ procedure Internal_Unit_Info (Nam : Unit_Name_Type) is
+ begin
+ pragma Assert (Present (Nam));
+
+ Write_Line
+ ("""" & Get_Name_String (Nam) & """: predefined unit ignored");
+ end Internal_Unit_Info;
+
+ -----------------------
+ -- Is_Duplicate_Unit --
+ -----------------------
+
+ function Is_Duplicate_Unit (U_Id : Unit_Id) return Boolean is
+ begin
+ pragma Assert (Present (U_Id));
+
+ return UL.Contains (Unit_To_Line, U_Id);
+ end Is_Duplicate_Unit;
+
+ -------------------------
+ -- Is_Significant_With --
+ -------------------------
+
+ function Is_Significant_With (W_Id : With_Id) return Boolean is
+ pragma Assert (Present (W_Id));
+
+ Withed_Rec : With_Record renames Withs.Table (W_Id);
+ Withed_U_Id : constant Unit_Id :=
+ Corresponding_Unit (Withed_Rec.Uname);
+
+ begin
+ -- Nothing to do for a unit which does not exist any more
+
+ if not Present (Withed_U_Id) then
+ return False;
+
+ -- Nothing to do for a limited with
+
+ elsif Withed_Rec.Limited_With then
+ return False;
+
+ -- Nothing to do when the unit does not need to be elaborated
+
+ elsif not Needs_Elaboration (Withed_U_Id) then
+ return False;
+ end if;
+
+ return True;
+ end Is_Significant_With;
+
+ -----------------------
+ -- Missing_Unit_Info --
+ -----------------------
+
+ procedure Missing_Unit_Info (Nam : Unit_Name_Type) is
+ begin
+ pragma Assert (Present (Nam));
+
+ Write_Line
+ ("""" & Get_Name_String (Nam) & """: not present; ignored");
+ end Missing_Unit_Info;
+ end Library_Graph_Builders;
+
+end Bindo.Builders;
diff --git a/gcc/ada/bindo-builders.ads b/gcc/ada/bindo-builders.ads
new file mode 100644
index 0000000..54c39e4
--- /dev/null
+++ b/gcc/ada/bindo-builders.ads
@@ -0,0 +1,65 @@
+------------------------------------------------------------------------------
+-- --
+-- GNAT COMPILER COMPONENTS --
+-- --
+-- B I N D O . B U I L D E R S --
+-- --
+-- S p e c --
+-- --
+-- Copyright (C) 2019, 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. See the GNU General Public License --
+-- for more details. You should have received a copy of the GNU General --
+-- Public License distributed with GNAT; see file COPYING3. If not, go to --
+-- http://www.gnu.org/licenses for a complete copy of the license. --
+-- --
+-- GNAT was originally developed by the GNAT team at New York University. --
+-- Extensive contributions were provided by Ada Core Technologies Inc. --
+-- --
+------------------------------------------------------------------------------
+
+-- For full architecture, see unit Bindo.
+
+-- The following unit contains facilities to create various graphs that
+-- reflect dependencies between units, as well as activations of tasks,
+-- calls, and instantiations within them.
+
+with Bindo.Graphs;
+use Bindo.Graphs;
+use Bindo.Graphs.Invocation_Graphs;
+use Bindo.Graphs.Library_Graphs;
+
+package Bindo.Builders is
+
+ -------------------------------
+ -- Invocation_Graph_Builders --
+ -------------------------------
+
+ package Invocation_Graph_Builders is
+ function Build_Invocation_Graph
+ (Lib_G : Library_Graph) return Invocation_Graph;
+ -- Return a new invocation graph that reflects the activations of
+ -- tasks, calls, and instantiations in all units of the bind. Each
+ -- invocation graph vertex is linked with the corresponding vertex
+ -- of library graph Lib_G, which contains the body of the activated
+ -- task, invoked subprogram, or instantiated generic.
+
+ end Invocation_Graph_Builders;
+
+ ----------------------------
+ -- Library_Graph_Builders --
+ ----------------------------
+
+ package Library_Graph_Builders is
+ function Build_Library_Graph return Library_Graph;
+ -- Return a new library graph that reflects the dependencies between
+ -- all units of the bind.
+
+ end Library_Graph_Builders;
+
+end Bindo.Builders;
diff --git a/gcc/ada/bindo-diagnostics.adb b/gcc/ada/bindo-diagnostics.adb
new file mode 100644
index 0000000..bf11d39
--- /dev/null
+++ b/gcc/ada/bindo-diagnostics.adb
@@ -0,0 +1,72 @@
+------------------------------------------------------------------------------
+-- --
+-- GNAT COMPILER COMPONENTS --
+-- --
+-- B I N D O . D I A G N O S T I C S --
+-- --
+-- B o d y --
+-- --
+-- Copyright (C) 2019, 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. See the GNU General Public License --
+-- for more details. You should have received a copy of the GNU General --
+-- Public License distributed with GNAT; see file COPYING3. If not, go to --
+-- http://www.gnu.org/licenses for a complete copy of the license. --
+-- --
+-- GNAT was originally developed by the GNAT team at New York University. --
+-- Extensive contributions were provided by Ada Core Technologies Inc. --
+-- --
+------------------------------------------------------------------------------
+
+package body Bindo.Diagnostics is
+
+ -----------------------
+ -- Cycle_Diagnostics --
+ -----------------------
+
+ package body Cycle_Diagnostics is
+
+ -----------------------------
+ -- Has_Elaborate_All_Cycle --
+ -----------------------------
+
+ function Has_Elaborate_All_Cycle (G : Library_Graph) return Boolean is
+ Has_Cycle : Boolean;
+ Iter : All_Edge_Iterator;
+ LGE_Id : Library_Graph_Edge_Id;
+
+ begin
+ pragma Assert (Present (G));
+
+ -- Assume that the graph lacks a cycle
+
+ Has_Cycle := False;
+
+ -- The library graph has an Elaborate_All cycle when one of its edges
+ -- represents a with clause for a unit with pragma Elaborate_All, and
+ -- both the predecessor and successor reside in the same component.
+ -- Note that the iteration must run to completion in order to unlock
+ -- the graph.
+
+ Iter := Iterate_All_Edges (G);
+ while Has_Next (Iter) loop
+ Next (Iter, LGE_Id);
+ pragma Assert (Present (LGE_Id));
+
+ if Kind (G, LGE_Id) = Elaborate_All_Edge
+ and then Links_Vertices_In_Same_Component (G, LGE_Id)
+ then
+ Has_Cycle := True;
+ end if;
+ end loop;
+
+ return Has_Cycle;
+ end Has_Elaborate_All_Cycle;
+ end Cycle_Diagnostics;
+
+end Bindo.Diagnostics;
diff --git a/gcc/ada/bindo-diagnostics.ads b/gcc/ada/bindo-diagnostics.ads
new file mode 100644
index 0000000..3b1d01c
--- /dev/null
+++ b/gcc/ada/bindo-diagnostics.ads
@@ -0,0 +1,61 @@
+------------------------------------------------------------------------------
+-- --
+-- GNAT COMPILER COMPONENTS --
+-- --
+-- B I N D O . D I A G N O S T I C S --
+-- --
+-- S p e c --
+-- --
+-- Copyright (C) 2019, 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. See the GNU General Public License --
+-- for more details. You should have received a copy of the GNU General --
+-- Public License distributed with GNAT; see file COPYING3. If not, go to --
+-- http://www.gnu.org/licenses for a complete copy of the license. --
+-- --
+-- GNAT was originally developed by the GNAT team at New York University. --
+-- Extensive contributions were provided by Ada Core Technologies Inc. --
+-- --
+------------------------------------------------------------------------------
+
+-- For full architecture, see unit Bindo.
+
+-- The following unit contains facilities to diagnose various issues with the
+-- elaboration order.
+
+with Bindo.Graphs;
+use Bindo.Graphs;
+use Bindo.Graphs.Library_Graphs;
+
+package Bindo.Diagnostics is
+
+ -----------
+ -- Types --
+ -----------
+
+ -- The following type enumerates all possible statuses of the elaboration
+ -- order.
+
+ type Elaboration_Order_Status is
+ (Order_Has_Circularity,
+ Order_Has_Elaborate_All_Circularity,
+ Order_OK);
+
+ -----------------------
+ -- Cycle_Diagnostics --
+ -----------------------
+
+ package Cycle_Diagnostics is
+ function Has_Elaborate_All_Cycle (G : Library_Graph) return Boolean;
+ pragma Inline (Has_Elaborate_All_Cycle);
+ -- Determine whether library graph G contains a cycle where pragma
+ -- Elaborate_All appears within a component.
+
+ end Cycle_Diagnostics;
+
+end Bindo.Diagnostics;
diff --git a/gcc/ada/bindo-elaborators.adb b/gcc/ada/bindo-elaborators.adb
new file mode 100644
index 0000000..b11598c
--- /dev/null
+++ b/gcc/ada/bindo-elaborators.adb
@@ -0,0 +1,1418 @@
+------------------------------------------------------------------------------
+-- --
+-- GNAT COMPILER COMPONENTS --
+-- --
+-- B I N D O . E L A B O R A T O R S --
+-- --
+-- B o d y --
+-- --
+-- Copyright (C) 2019, 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. See the GNU General Public License --
+-- for more details. You should have received a copy of the GNU General --
+-- Public License distributed with GNAT; see file COPYING3. If not, go to --
+-- http://www.gnu.org/licenses for a complete copy of the license. --
+-- --
+-- GNAT was originally developed by the GNAT team at New York University. --
+-- Extensive contributions were provided by Ada Core Technologies Inc. --
+-- --
+------------------------------------------------------------------------------
+
+with Binderr; use Binderr;
+with Butil; use Butil;
+with Debug; use Debug;
+with Output; use Output;
+with Types; use Types;
+
+with Bindo.Augmentors;
+use Bindo.Augmentors;
+use Bindo.Augmentors.Library_Graph_Augmentors;
+
+with Bindo.Builders;
+use Bindo.Builders;
+use Bindo.Builders.Invocation_Graph_Builders;
+use Bindo.Builders.Library_Graph_Builders;
+
+with Bindo.Diagnostics;
+use Bindo.Diagnostics;
+use Bindo.Diagnostics.Cycle_Diagnostics;
+
+with Bindo.Units;
+use Bindo.Units;
+
+with Bindo.Validators;
+use Bindo.Validators;
+use Bindo.Validators.Elaboration_Order_Validators;
+use Bindo.Validators.Invocation_Graph_Validators;
+use Bindo.Validators.Library_Graph_Validators;
+
+with Bindo.Writers;
+use Bindo.Writers;
+use Bindo.Writers.ALI_Writers;
+use Bindo.Writers.Elaboration_Order_Writers;
+use Bindo.Writers.Invocation_Graph_Writers;
+use Bindo.Writers.Library_Graph_Writers;
+use Bindo.Writers.Unit_Closure_Writers;
+
+with GNAT; use GNAT;
+with GNAT.Graphs; use GNAT.Graphs;
+with GNAT.Sets; use GNAT.Sets;
+
+package body Bindo.Elaborators is
+
+ -- The following type defines the advancement of the elaboration order
+ -- algorithm in terms of steps.
+
+ type Elaboration_Order_Step is new Natural;
+
+ Initial_Step : constant Elaboration_Order_Step :=
+ Elaboration_Order_Step'First;
+
+ ----------------------------------------------
+ -- Invocation_And_Library_Graph_Elaborators --
+ ----------------------------------------------
+
+ package body Invocation_And_Library_Graph_Elaborators is
+ Add_To_All_Candidates_Msg : aliased String :=
+ "add vertex to all candidates";
+ Add_To_Comp_Candidates_Msg : aliased String :=
+ "add vertex to component candidates";
+
+ -----------
+ -- Types --
+ -----------
+
+ type String_Ptr is access all String;
+
+ -----------------
+ -- Visited set --
+ -----------------
+
+ package VS is new Membership_Sets
+ (Element_Type => Library_Graph_Vertex_Id,
+ "=" => "=",
+ Hash => Hash_Library_Graph_Vertex);
+ use VS;
+
+ -----------------------
+ -- Local subprograms --
+ -----------------------
+
+ procedure Add_Vertex
+ (G : Library_Graph;
+ LGV_Id : Library_Graph_Vertex_Id;
+ Set : Membership_Set;
+ Msg : String;
+ Step : Elaboration_Order_Step;
+ Indent : Indentation_Level);
+ pragma Inline (Add_Vertex);
+ -- Add vertex LGV_Id of library graph G to membership set Set. Msg is
+ -- a message emitted for tracing purposes. Step is the current step in
+ -- the elaboration order. Indent is the desired indentation level for
+ -- tracing.
+
+ procedure Add_Vertex_If_Elaborable
+ (G : Library_Graph;
+ LGV_Id : Library_Graph_Vertex_Id;
+ Set : Membership_Set;
+ Msg : String;
+ Step : Elaboration_Order_Step;
+ Indent : Indentation_Level);
+ pragma Inline (Add_Vertex_If_Elaborable);
+ -- Add vertex LGV_Id of library graph G to membership set Set if it can
+ -- be elaborated. Msg is a message emitted for tracing purposes. Step is
+ -- the current step in the elaboration order. Indent is the desired
+ -- indentation level for tracing.
+
+ function Create_All_Candidates_Set
+ (G : Library_Graph;
+ Step : Elaboration_Order_Step) return Membership_Set;
+ pragma Inline (Create_All_Candidates_Set);
+ -- Collect all elaborable candidate vertices of library graph G in a
+ -- set. Step is the current step in the elaboration order.
+
+ function Create_Component_Candidates_Set
+ (G : Library_Graph;
+ Comp : Component_Id;
+ Step : Elaboration_Order_Step) return Membership_Set;
+ pragma Inline (Create_Component_Candidates_Set);
+ -- Collect all elaborable candidate vertices that appear in component
+ -- Comp of library graph G in a set. Step is the current step in the
+ -- elaboration order.
+
+ procedure Elaborate_Component
+ (G : Library_Graph;
+ Comp : Component_Id;
+ All_Candidates : Membership_Set;
+ Remaining_Vertices : in out Natural;
+ Order : in out Unit_Id_Table;
+ Step : Elaboration_Order_Step);
+ pragma Inline (Elaborate_Component);
+ -- Elaborate as many vertices as possible that appear in component
+ -- Comp of library graph G. All_Candidates is the set of all elaborable
+ -- vertices across the whole library graph. Remaining_Vertices is the
+ -- number of vertices that remain to be elaborated. Order denotes the
+ -- elaboration order. Step is the current step in the elaboration order.
+
+ procedure Elaborate_Library_Graph
+ (G : Library_Graph;
+ Order : out Unit_Id_Table;
+ Status : out Elaboration_Order_Status);
+ pragma Inline (Elaborate_Library_Graph);
+ -- Elaborate as many vertices as possible of library graph G. Order is
+ -- the elaboration order. Status is the condition of the elaboration
+ -- order.
+
+ procedure Elaborate_Units_Common
+ (Use_Inv_Graph : Boolean;
+ Inv_Graph : out Invocation_Graph;
+ Lib_Graph : out Library_Graph;
+ Order : out Unit_Id_Table;
+ Status : out Elaboration_Order_Status);
+ pragma Inline (Elaborate_Units_Common);
+ -- Find the elaboration order of all units in the bind. Use_Inv_Graph
+ -- should be set when library graph Lib_Graph is to be augmented with
+ -- information from invocation graph Inv_Graph. Order is the elaboration
+ -- order. Status is the condition of the elaboration order.
+
+ procedure Elaborate_Units_Dynamic (Order : out Unit_Id_Table);
+ pragma Inline (Elaborate_Units_Dynamic);
+ -- Find the elaboration order of all units in the bind using the dynamic
+ -- model. Order is the elaboration order. In the event where no ordering
+ -- is possible, this routine diagnoses the issue(s) and raises exception
+ -- Unrecoverable_Error.
+
+ procedure Elaborate_Units_Static (Order : out Unit_Id_Table);
+ pragma Inline (Elaborate_Units_Static);
+ -- Find the elaboration order of all units in the bind using the static
+ -- model. Order is the elaboration order. In the event where no ordering
+ -- is possible, this routine diagnoses the issue(s) and raises exception
+ -- Unrecoverable_Error.
+
+ procedure Elaborate_Vertex
+ (G : Library_Graph;
+ LGV_Id : Library_Graph_Vertex_Id;
+ All_Candidates : Membership_Set;
+ Comp_Candidates : Membership_Set;
+ Remaining_Vertices : in out Natural;
+ Order : in out Unit_Id_Table;
+ Step : Elaboration_Order_Step;
+ Indent : Indentation_Level);
+ pragma Inline (Elaborate_Vertex);
+ -- Elaborate vertex LGV_Id of library graph G by adding its unit to
+ -- elaboration order Order. The routine updates awaiting successors
+ -- where applicable. All_Candidates denotes the set of all elaborable
+ -- vertices across the whole library graph. Comp_Candidates is the set
+ -- of all elaborable vertices in the component of LGV_Id. Parameter
+ -- Remaining_Vertices denotes the number of vertices that remain to
+ -- be elaborated. Step is the current step in the elaboration order.
+ -- Indent is the desired indentation level for tracing.
+
+ function Find_Best_Candidate
+ (G : Library_Graph;
+ Set : Membership_Set;
+ Step : Elaboration_Order_Step;
+ Indent : Indentation_Level) return Library_Graph_Vertex_Id;
+ pragma Inline (Find_Best_Candidate);
+ -- Find the most suitable vertex of library graph G for elaboration from
+ -- membership set Set. Step denotes the current step in the elaboration
+ -- order. Indent is the desired indentation level for tracing.
+
+ function Is_Better_Candidate
+ (G : Library_Graph;
+ Best_Candid : Library_Graph_Vertex_Id;
+ New_Candid : Library_Graph_Vertex_Id) return Boolean;
+ pragma Inline (Is_Better_Candidate);
+ -- Determine whether new candidate vertex New_Candid of library graph
+ -- G is a more suitable choice for elaboration compared to the current
+ -- best candidate Best_Candid.
+
+ procedure Trace_Candidate_Vertices
+ (G : Library_Graph;
+ Set : Membership_Set;
+ Step : Elaboration_Order_Step);
+ pragma Inline (Trace_Candidate_Vertices);
+ -- Write the candidate vertices of library graph G present in membership
+ -- set Set to standard output. Formal Step denotes the current step in
+ -- the elaboration order.
+
+ procedure Trace_Component
+ (G : Library_Graph;
+ Comp : Component_Id;
+ Msg : String;
+ Step : Elaboration_Order_Step);
+ pragma Inline (Trace_Component);
+ -- Write elaboration-related information for component Comp of library
+ -- graph G to standard output, starting with message Msg. Step is the
+ -- current step in the elaboration order.
+
+ procedure Trace_Step (Step : Elaboration_Order_Step);
+ pragma Inline (Trace_Step);
+ -- Write current step Step of the elaboration order to standard output
+
+ procedure Trace_Unelaborated_Vertices
+ (G : Library_Graph;
+ Count : Natural;
+ Step : Elaboration_Order_Step);
+ pragma Inline (Trace_Unelaborated_Vertices);
+ -- Write the remaining unelaborated vertices of library graph G to
+ -- standard output. Count is the number of vertices that remain to
+ -- be elaborated. Step is the current step in the elaboration order.
+
+ procedure Trace_Vertex
+ (G : Library_Graph;
+ LGV_Id : Library_Graph_Vertex_Id;
+ Msg : String;
+ Step : Elaboration_Order_Step;
+ Indent : Indentation_Level);
+ pragma Inline (Trace_Vertex);
+ -- Write elaboration-related information for vertex LGV_Id of library
+ -- graph G to standard output, starting with message Msg. Step is the
+ -- current step in the elaboration order. Indent denotes the desired
+ -- indentation level for tracing.
+
+ procedure Update_Successor
+ (G : Library_Graph;
+ Pred : Library_Graph_Vertex_Id;
+ Succ : Library_Graph_Vertex_Id;
+ All_Candidates : Membership_Set;
+ Comp_Candidates : Membership_Set;
+ Step : Elaboration_Order_Step;
+ Indent : Indentation_Level);
+ pragma Inline (Update_Successor);
+ -- Notify successor vertex Succ of library graph G along with its
+ -- component that their predecessor Pred has just been elaborated.
+ -- This may cause new vertices to become elaborable, and thus be added
+ -- to one of the two sets. All_Candidates is the set of all elaborable
+ -- vertices across the whole library graph. Comp_Candidates is the set
+ -- of all elaborable vertices in the component of Pred. Step is the
+ -- current step in the elaboration order. Indent denotes the desired
+ -- indentation level for tracing.
+
+ procedure Update_Successors
+ (G : Library_Graph;
+ Pred : Library_Graph_Vertex_Id;
+ All_Candidates : Membership_Set;
+ Comp_Candidates : Membership_Set;
+ Step : Elaboration_Order_Step;
+ Indent : Indentation_Level);
+ pragma Inline (Update_Successors);
+ -- Notify all successors along with their components that their
+ -- predecessor vertex Pred of ligrary graph G has just been elaborated.
+ -- This may cause new vertices to become elaborable, and thus be added
+ -- to one of the two sets. All_Candidates is the set of all elaborable
+ -- vertices across the whole library graph. Comp_Candidates is the set
+ -- of all elaborable vertices in the component of Pred. Step is the
+ -- current step in the elaboration order. Indent denotes the desired
+ -- indentation level for tracing.
+
+ ----------------
+ -- Add_Vertex --
+ ----------------
+
+ procedure Add_Vertex
+ (G : Library_Graph;
+ LGV_Id : Library_Graph_Vertex_Id;
+ Set : Membership_Set;
+ Msg : String;
+ Step : Elaboration_Order_Step;
+ Indent : Indentation_Level)
+ is
+ begin
+ pragma Assert (Present (LGV_Id));
+ pragma Assert (Needs_Elaboration (G, LGV_Id));
+ pragma Assert (Present (Set));
+
+ -- Add vertex only when it is not present in the set. This is not
+ -- strictly necessary because the set implementation handles this
+ -- case, however the check eliminates spurious traces.
+
+ if not Contains (Set, LGV_Id) then
+ Trace_Vertex
+ (G => G,
+ LGV_Id => LGV_Id,
+ Msg => Msg,
+ Step => Step,
+ Indent => Indent);
+
+ Insert (Set, LGV_Id);
+ end if;
+ end Add_Vertex;
+
+ ------------------------------
+ -- Add_Vertex_If_Elaborable --
+ ------------------------------
+
+ procedure Add_Vertex_If_Elaborable
+ (G : Library_Graph;
+ LGV_Id : Library_Graph_Vertex_Id;
+ Set : Membership_Set;
+ Msg : String;
+ Step : Elaboration_Order_Step;
+ Indent : Indentation_Level)
+ is
+ Aux_LGV_Id : Library_Graph_Vertex_Id;
+
+ begin
+ pragma Assert (Present (G));
+ pragma Assert (Present (LGV_Id));
+ pragma Assert (Needs_Elaboration (G, LGV_Id));
+ pragma Assert (Present (Set));
+
+ if Is_Elaborable_Vertex (G, LGV_Id) then
+ Add_Vertex
+ (G => G,
+ LGV_Id => LGV_Id,
+ Set => Set,
+ Msg => Msg,
+ Step => Step,
+ Indent => Indent);
+
+ -- Assume that there is no extra vertex that needs to be added
+
+ Aux_LGV_Id := No_Library_Graph_Vertex;
+
+ -- A spec-body pair where the spec carries pragma Elaborate_Body
+ -- must be treated as one vertex for elaboration purposes. If one
+ -- of them is elaborable, then the other is also elaborable. This
+ -- property is guaranteed by predicate Is_Elaborable_Vertex.
+
+ if Is_Body_Of_Spec_With_Elaborate_Body (G, LGV_Id) then
+ Aux_LGV_Id := Proper_Spec (G, LGV_Id);
+ pragma Assert (Present (Aux_LGV_Id));
+
+ elsif Is_Spec_With_Elaborate_Body (G, LGV_Id) then
+ Aux_LGV_Id := Proper_Body (G, LGV_Id);
+ pragma Assert (Present (Aux_LGV_Id));
+ end if;
+
+ if Present (Aux_LGV_Id) then
+ pragma Assert (Needs_Elaboration (G, Aux_LGV_Id));
+
+ Add_Vertex
+ (G => G,
+ LGV_Id => Aux_LGV_Id,
+ Set => Set,
+ Msg => Msg,
+ Step => Step,
+ Indent => Indent);
+ end if;
+ end if;
+ end Add_Vertex_If_Elaborable;
+
+ -------------------------------
+ -- Create_All_Candidates_Set --
+ -------------------------------
+
+ function Create_All_Candidates_Set
+ (G : Library_Graph;
+ Step : Elaboration_Order_Step) return Membership_Set
+ is
+ Iter : Library_Graphs.All_Vertex_Iterator;
+ LGV_Id : Library_Graph_Vertex_Id;
+ Set : Membership_Set;
+
+ begin
+ pragma Assert (Present (G));
+
+ Set := Create (Number_Of_Vertices (G));
+ Iter := Iterate_All_Vertices (G);
+ while Has_Next (Iter) loop
+ Next (Iter, LGV_Id);
+ pragma Assert (Present (LGV_Id));
+
+ Add_Vertex_If_Elaborable
+ (G => G,
+ LGV_Id => LGV_Id,
+ Set => Set,
+ Msg => Add_To_All_Candidates_Msg,
+ Step => Step,
+ Indent => No_Indentation);
+ end loop;
+
+ return Set;
+ end Create_All_Candidates_Set;
+
+ -------------------------------------
+ -- Create_Component_Candidates_Set --
+ -------------------------------------
+
+ function Create_Component_Candidates_Set
+ (G : Library_Graph;
+ Comp : Component_Id;
+ Step : Elaboration_Order_Step) return Membership_Set
+ is
+ Iter : Component_Vertex_Iterator;
+ LGV_Id : Library_Graph_Vertex_Id;
+ Set : Membership_Set;
+
+ begin
+ pragma Assert (Present (G));
+ pragma Assert (Present (Comp));
+
+ Set := Create (Number_Of_Component_Vertices (G, Comp));
+ Iter := Iterate_Component_Vertices (G, Comp);
+ while Has_Next (Iter) loop
+ Next (Iter, LGV_Id);
+ pragma Assert (Present (LGV_Id));
+
+ Add_Vertex_If_Elaborable
+ (G => G,
+ LGV_Id => LGV_Id,
+ Set => Set,
+ Msg => Add_To_Comp_Candidates_Msg,
+ Step => Step,
+ Indent => No_Indentation);
+ end loop;
+
+ return Set;
+ end Create_Component_Candidates_Set;
+
+ -------------------------
+ -- Elaborate_Component --
+ -------------------------
+
+ procedure Elaborate_Component
+ (G : Library_Graph;
+ Comp : Component_Id;
+ All_Candidates : Membership_Set;
+ Remaining_Vertices : in out Natural;
+ Order : in out Unit_Id_Table;
+ Step : Elaboration_Order_Step)
+ is
+ Candidate : Library_Graph_Vertex_Id;
+ Comp_Candidates : Membership_Set;
+
+ begin
+ pragma Assert (Present (G));
+ pragma Assert (Present (Comp));
+ pragma Assert (Present (All_Candidates));
+
+ Trace_Component
+ (G => G,
+ Comp => Comp,
+ Msg => "elaborating component",
+ Step => Step);
+
+ Comp_Candidates := Create_Component_Candidates_Set (G, Comp, Step);
+
+ loop
+ Candidate :=
+ Find_Best_Candidate
+ (G => G,
+ Set => Comp_Candidates,
+ Step => Step,
+ Indent => Nested_Indentation);
+
+ -- Stop the elaboration of the component when there is no suitable
+ -- candidate. This indicates that either all vertices within the
+ -- component have been elaborated, or the library graph contains a
+ -- circularity.
+
+ exit when not Present (Candidate);
+
+ Elaborate_Vertex
+ (G => G,
+ LGV_Id => Candidate,
+ All_Candidates => All_Candidates,
+ Comp_Candidates => Comp_Candidates,
+ Remaining_Vertices => Remaining_Vertices,
+ Order => Order,
+ Step => Step,
+ Indent => Nested_Indentation);
+ end loop;
+
+ Destroy (Comp_Candidates);
+ end Elaborate_Component;
+
+ -----------------------------
+ -- Elaborate_Library_Graph --
+ -----------------------------
+
+ procedure Elaborate_Library_Graph
+ (G : Library_Graph;
+ Order : out Unit_Id_Table;
+ Status : out Elaboration_Order_Status)
+ is
+ All_Candidates : Membership_Set;
+ Candidate : Library_Graph_Vertex_Id;
+ Comp : Component_Id;
+ Remaining_Vertices : Natural;
+ Step : Elaboration_Order_Step;
+
+ begin
+ pragma Assert (Present (G));
+
+ Step := Initial_Step;
+
+ All_Candidates := Create_All_Candidates_Set (G, Step);
+ Remaining_Vertices := Number_Of_Vertices (G);
+
+ loop
+ Step := Step + 1;
+
+ Trace_Candidate_Vertices
+ (G => G,
+ Set => All_Candidates,
+ Step => Step);
+
+ Trace_Unelaborated_Vertices
+ (G => G,
+ Count => Remaining_Vertices,
+ Step => Step);
+
+ Candidate :=
+ Find_Best_Candidate
+ (G => G,
+ Set => All_Candidates,
+ Step => Step,
+ Indent => No_Indentation);
+
+ -- Stop the elaboration when there is no suitable candidate. This
+ -- indicates that either all units were elaborated or the library
+ -- graph contains a circularity.
+
+ exit when not Present (Candidate);
+
+ -- Elaborate the component of the candidate vertex by trying to
+ -- elaborate as many vertices within the component as possible.
+ -- Each successful elaboration signals the appropriate successors
+ -- and their components that they have one less predecessor to
+ -- wait on. This may add new candidates to set All_Candidates.
+
+ Comp := Component (G, Candidate);
+ pragma Assert (Present (Comp));
+
+ Elaborate_Component
+ (G => G,
+ Comp => Comp,
+ All_Candidates => All_Candidates,
+ Remaining_Vertices => Remaining_Vertices,
+ Order => Order,
+ Step => Step);
+ end loop;
+
+ Destroy (All_Candidates);
+
+ -- The library graph contains an Elaborate_All circularity when
+ -- at least one edge subject to the related pragma appears in a
+ -- component.
+
+ if Has_Elaborate_All_Cycle (G) then
+ Status := Order_Has_Elaborate_All_Circularity;
+
+ -- The library contains a circularity when at least one vertex failed
+ -- to elaborate.
+
+ elsif Remaining_Vertices /= 0 then
+ Status := Order_Has_Circularity;
+
+ -- Otherwise the elaboration order is satisfactory
+
+ else
+ Status := Order_OK;
+ end if;
+ end Elaborate_Library_Graph;
+
+ ---------------------
+ -- Elaborate_Units --
+ ---------------------
+
+ procedure Elaborate_Units
+ (Order : out Unit_Id_Table;
+ Main_Lib_File : File_Name_Type)
+ is
+ Main_Lib_Unit : constant Unit_Id :=
+ Corresponding_Unit (Unit_Name_Type (Main_Lib_File));
+
+ begin
+ pragma Assert (Present (Main_Lib_Unit));
+
+ -- Initialize all unit-related data structures and gather all units
+ -- that need elaboration.
+
+ Initialize_Units;
+ Collect_Elaborable_Units;
+
+ Write_ALI_Tables;
+
+ -- Choose the proper elaboration strategy based on whether the main
+ -- library unit was compiled with dynamic elaboration checks.
+
+ if Is_Dynamically_Elaborated (Main_Lib_Unit) then
+ Elaborate_Units_Dynamic (Order);
+ else
+ Elaborate_Units_Static (Order);
+ end if;
+
+ Validate_Elaboration_Order (Order);
+ Write_Elaboration_Order (Order);
+
+ -- Enumerate the sources referenced in the closure of the order
+
+ Write_Unit_Closure (Order);
+
+ -- Destroy all unit-delated data structures
+
+ Finalize_Units;
+
+ exception
+ when others =>
+ Finalize_Units;
+ raise;
+ end Elaborate_Units;
+
+ ----------------------------
+ -- Elaborate_Units_Common --
+ ----------------------------
+
+ procedure Elaborate_Units_Common
+ (Use_Inv_Graph : Boolean;
+ Inv_Graph : out Invocation_Graph;
+ Lib_Graph : out Library_Graph;
+ Order : out Unit_Id_Table;
+ Status : out Elaboration_Order_Status)
+ is
+ begin
+ -- Create, validate, and output the library graph that captures the
+ -- dependencies between library items.
+
+ Lib_Graph := Build_Library_Graph;
+ Validate_Library_Graph (Lib_Graph);
+ Write_Library_Graph (Lib_Graph);
+
+ -- Create, validate, output, and use the invocation graph that
+ -- represents the flow of execusion only when requested by the
+ -- caller.
+
+ if Use_Inv_Graph then
+ Inv_Graph := Build_Invocation_Graph (Lib_Graph);
+ Validate_Invocation_Graph (Inv_Graph);
+ Write_Invocation_Graph (Inv_Graph);
+
+ -- Otherwise the invocation graph is not used. Create a dummy graph
+ -- as this allows for a uniform behavior on the caller side.
+
+ else
+ Inv_Graph :=
+ Invocation_Graphs.Create
+ (Initial_Vertices => 1,
+ Initial_Edges => 1);
+ end if;
+
+ -- Traverse the invocation graph starting from elaboration code in
+ -- order to discover transitions of the execution flow from a unit
+ -- to a unit that result in extra edges within the library graph.
+
+ Augment_Library_Graph (Inv_Graph, Lib_Graph);
+
+ -- Create and output the component graph by collapsing all library
+ -- items into library units and traversing the library graph.
+
+ Find_Components (Lib_Graph);
+ Write_Library_Graph (Lib_Graph);
+
+ -- Traverse the library graph to determine the elaboration order of
+ -- units.
+
+ Elaborate_Library_Graph
+ (G => Lib_Graph,
+ Order => Order,
+ Status => Status);
+ end Elaborate_Units_Common;
+
+ -----------------------------
+ -- Elaborate_Units_Dynamic --
+ -----------------------------
+
+ procedure Elaborate_Units_Dynamic (Order : out Unit_Id_Table) is
+ Dyn_Inv_Graph : Invocation_Graph;
+ Dyn_Lib_Graph : Library_Graph;
+ Dyn_Order : Unit_Id_Table;
+ Mix_Inv_Graph : Invocation_Graph;
+ Mix_Lib_Graph : Library_Graph;
+ Mix_Order : Unit_Id_Table;
+ Status : Elaboration_Order_Status;
+
+ begin
+ -- Attempt to elaborate the units in the library graph by mixing in
+ -- the information from the invocation graph. This assumes that all
+ -- invocations will take place at elaboration time.
+
+ Elaborate_Units_Common
+ (Use_Inv_Graph => True,
+ Inv_Graph => Mix_Inv_Graph,
+ Lib_Graph => Mix_Lib_Graph,
+ Order => Mix_Order,
+ Status => Status);
+
+ -- The elaboration order is satisfactory
+
+ if Status = Order_OK then
+ Order := Mix_Order;
+
+ -- The library graph contains an Elaborate_All circularity. There is
+ -- no point in re-elaborating the units without the information from
+ -- the invocation graph because the circularity will persist.
+
+ elsif Status = Order_Has_Elaborate_All_Circularity then
+ Error_Msg ("elaboration circularity detected");
+
+ -- Report error here
+
+ -- Otherwise the library graph contains a circularity, or the extra
+ -- information provided by the invocation graph caused a circularity.
+ -- Re-elaborate the units without using the invocation graph. This
+ -- assumes that all invocations will not take place at elaboration
+ -- time.
+
+ else
+ pragma Assert (Status = Order_Has_Circularity);
+
+ Elaborate_Units_Common
+ (Use_Inv_Graph => False,
+ Inv_Graph => Dyn_Inv_Graph,
+ Lib_Graph => Dyn_Lib_Graph,
+ Order => Dyn_Order,
+ Status => Status);
+
+ -- The elaboration order is satisfactory. The elaboration of the
+ -- program may still fail at runtime with an ABE.
+
+ if Status = Order_OK then
+ Order := Dyn_Order;
+
+ -- Otherwise the library graph contains a circularity without the
+ -- extra information provided by the invocation graph. Diagnose
+ -- the circularity.
+
+ else
+ Error_Msg ("elaboration circularity detected");
+
+ -- Report error here
+ end if;
+
+ Destroy (Dyn_Inv_Graph);
+ Destroy (Dyn_Lib_Graph);
+ end if;
+
+ Destroy (Mix_Inv_Graph);
+ Destroy (Mix_Lib_Graph);
+
+ -- Halt the bind as there is no satisfactory elaboration order
+
+ if Status /= Order_OK then
+ raise Unrecoverable_Error;
+ end if;
+ end Elaborate_Units_Dynamic;
+
+ ----------------------------
+ -- Elaborate_Units_Static --
+ ----------------------------
+
+ procedure Elaborate_Units_Static (Order : out Unit_Id_Table) is
+ Inv_Graph : Invocation_Graph;
+ Lib_Graph : Library_Graph;
+ Status : Elaboration_Order_Status;
+
+ begin
+ -- Attempt to elaborate the units in the library graph by mixing in
+ -- the information from the invocation graph. This assumes that all
+ -- invocations will take place at elaboration time.
+
+ Elaborate_Units_Common
+ (Use_Inv_Graph => True,
+ Inv_Graph => Inv_Graph,
+ Lib_Graph => Lib_Graph,
+ Order => Order,
+ Status => Status);
+
+ -- The augmented library graph contains a circularity
+
+ if Status /= Order_OK then
+ Error_Msg ("elaboration circularity detected");
+
+ -- Report error here
+ end if;
+
+ Destroy (Inv_Graph);
+ Destroy (Lib_Graph);
+
+ -- Halt the bind as there is no satisfactory elaboration order
+
+ if Status /= Order_OK then
+ raise Unrecoverable_Error;
+ end if;
+ end Elaborate_Units_Static;
+
+ ----------------------
+ -- Elaborate_Vertex --
+ ----------------------
+
+ procedure Elaborate_Vertex
+ (G : Library_Graph;
+ LGV_Id : Library_Graph_Vertex_Id;
+ All_Candidates : Membership_Set;
+ Comp_Candidates : Membership_Set;
+ Remaining_Vertices : in out Natural;
+ Order : in out Unit_Id_Table;
+ Step : Elaboration_Order_Step;
+ Indent : Indentation_Level)
+ is
+ Body_LGV_Id : Library_Graph_Vertex_Id;
+ U_Id : Unit_Id;
+
+ begin
+ pragma Assert (Present (G));
+ pragma Assert (Present (LGV_Id));
+ pragma Assert (Needs_Elaboration (G, LGV_Id));
+ pragma Assert (Present (All_Candidates));
+ pragma Assert (Present (Comp_Candidates));
+
+ Trace_Vertex
+ (G => G,
+ LGV_Id => LGV_Id,
+ Msg => "elaborating vertex",
+ Step => Step,
+ Indent => Indent);
+
+ -- Remove the vertex from both candidate sets. This is needed when
+ -- the vertex is both an overall best candidate among all vertices,
+ -- and the best candidate within the component. There is no need to
+ -- check that the vertex is present in either set because the set
+ -- implementation handles this case.
+
+ Delete (All_Candidates, LGV_Id);
+ Delete (Comp_Candidates, LGV_Id);
+
+ -- Mark the vertex as elaborated in order to prevent further attempts
+ -- to re-elaborate it.
+
+ Set_In_Elaboration_Order (G, LGV_Id);
+
+ -- Add the unit represented by the vertex to the elaboration order
+
+ U_Id := Unit (G, LGV_Id);
+ pragma Assert (Present (U_Id));
+
+ Unit_Id_Tables.Append (Order, U_Id);
+
+ -- There is now one fewer vertex to elaborate
+
+ Remaining_Vertices := Remaining_Vertices - 1;
+
+ -- Notify all successors and their components that they have one
+ -- fewer predecessor to wait on. This may cause some successors to
+ -- be included in one of the sets.
+
+ Update_Successors
+ (G => G,
+ Pred => LGV_Id,
+ All_Candidates => All_Candidates,
+ Comp_Candidates => Comp_Candidates,
+ Step => Step,
+ Indent => Indent + Nested_Indentation);
+
+ -- The vertex denotes a spec with a completing body, and is subject
+ -- to pragma Elaborate_Body. Elaborate the body in order to satisfy
+ -- the semantics of the pragma.
+
+ if Is_Spec_With_Elaborate_Body (G, LGV_Id) then
+ Body_LGV_Id := Proper_Body (G, LGV_Id);
+ pragma Assert (Present (Body_LGV_Id));
+
+ Elaborate_Vertex
+ (G => G,
+ LGV_Id => Body_LGV_Id,
+ All_Candidates => All_Candidates,
+ Comp_Candidates => Comp_Candidates,
+ Remaining_Vertices => Remaining_Vertices,
+ Order => Order,
+ Step => Step,
+ Indent => Indent);
+ end if;
+ end Elaborate_Vertex;
+
+ -------------------------
+ -- Find_Best_Candidate --
+ -------------------------
+
+ function Find_Best_Candidate
+ (G : Library_Graph;
+ Set : Membership_Set;
+ Step : Elaboration_Order_Step;
+ Indent : Indentation_Level) return Library_Graph_Vertex_Id
+ is
+ Best : Library_Graph_Vertex_Id;
+ Curr : Library_Graph_Vertex_Id;
+ Iter : Iterator;
+
+ begin
+ pragma Assert (Present (G));
+ pragma Assert (Present (Set));
+
+ -- Assume that there is no candidate
+
+ Best := No_Library_Graph_Vertex;
+
+ -- Inspect all vertices in the set, looking for the best candidate to
+ -- elaborate.
+
+ Iter := Iterate (Set);
+ while Has_Next (Iter) loop
+ Next (Iter, Curr);
+
+ pragma Assert (Present (Curr));
+ pragma Assert (Needs_Elaboration (G, Curr));
+
+ -- Update the best candidate when there is no such candidate
+
+ if not Present (Best) then
+ Best := Curr;
+
+ Trace_Vertex
+ (G => G,
+ LGV_Id => Best,
+ Msg => "initial best candidate vertex",
+ Step => Step,
+ Indent => Indent);
+
+ -- Update the best candidate when the current vertex is a better
+ -- choice.
+
+ elsif Is_Better_Candidate
+ (G => G,
+ Best_Candid => Best,
+ New_Candid => Curr)
+ then
+ Best := Curr;
+
+ Trace_Vertex
+ (G => G,
+ LGV_Id => Best,
+ Msg => "best candidate vertex",
+ Step => Step,
+ Indent => Indent);
+ end if;
+ end loop;
+
+ return Best;
+ end Find_Best_Candidate;
+
+ -------------------------
+ -- Is_Better_Candidate --
+ -------------------------
+
+ function Is_Better_Candidate
+ (G : Library_Graph;
+ Best_Candid : Library_Graph_Vertex_Id;
+ New_Candid : Library_Graph_Vertex_Id) return Boolean
+ is
+ begin
+ pragma Assert (Present (G));
+ pragma Assert (Present (Best_Candid));
+ pragma Assert (Present (New_Candid));
+
+ -- Prefer a predefined unit over a non-predefined unit
+
+ if Is_Predefined_Unit (G, Best_Candid)
+ and then not Is_Predefined_Unit (G, New_Candid)
+ then
+ return False;
+
+ elsif not Is_Predefined_Unit (G, Best_Candid)
+ and then Is_Predefined_Unit (G, New_Candid)
+ then
+ return True;
+
+ -- Prefer an internal unit over a non-iternal unit
+
+ elsif Is_Internal_Unit (G, Best_Candid)
+ and then not Is_Internal_Unit (G, New_Candid)
+ then
+ return False;
+
+ elsif not Is_Internal_Unit (G, Best_Candid)
+ and then Is_Internal_Unit (G, New_Candid)
+ then
+ return True;
+
+ -- Prefer a preelaborated unit over a non-preelaborated unit
+
+ elsif Is_Preelaborated_Unit (G, Best_Candid)
+ and then not Is_Preelaborated_Unit (G, New_Candid)
+ then
+ return False;
+
+ elsif not Is_Preelaborated_Unit (G, Best_Candid)
+ and then Is_Preelaborated_Unit (G, New_Candid)
+ then
+ return True;
+
+ -- Otherwise default to lexicographical order to ensure deterministic
+ -- behavior.
+
+ else
+ return Uname_Less (Name (G, Best_Candid), Name (G, New_Candid));
+ end if;
+ end Is_Better_Candidate;
+
+ ------------------------------
+ -- Trace_Candidate_Vertices --
+ ------------------------------
+
+ procedure Trace_Candidate_Vertices
+ (G : Library_Graph;
+ Set : Membership_Set;
+ Step : Elaboration_Order_Step)
+ is
+ Iter : Iterator;
+ LGV_Id : Library_Graph_Vertex_Id;
+
+ begin
+ pragma Assert (Present (G));
+ pragma Assert (Present (Set));
+
+ -- Nothing to do when switch -d_T (output elaboration order trace
+ -- information) is not in effect.
+
+ if not Debug_Flag_Underscore_TT then
+ return;
+ end if;
+
+ Trace_Step (Step);
+ Write_Str ("candidate vertices: ");
+ Write_Int (Int (Size (Set)));
+ Write_Eol;
+
+ Iter := Iterate (Set);
+ while Has_Next (Iter) loop
+ Next (Iter, LGV_Id);
+ pragma Assert (Present (LGV_Id));
+
+ Trace_Vertex
+ (G => G,
+ LGV_Id => LGV_Id,
+ Msg => "candidate vertex",
+ Step => Step,
+ Indent => Nested_Indentation);
+ end loop;
+ end Trace_Candidate_Vertices;
+
+ ---------------------
+ -- Trace_Component --
+ ---------------------
+
+ procedure Trace_Component
+ (G : Library_Graph;
+ Comp : Component_Id;
+ Msg : String;
+ Step : Elaboration_Order_Step)
+ is
+ begin
+ pragma Assert (Present (G));
+ pragma Assert (Present (Comp));
+
+ -- Nothing to do when switch -d_T (output elaboration order trace
+ -- information) is not in effect.
+
+ if not Debug_Flag_Underscore_TT then
+ return;
+ end if;
+
+ Trace_Step (Step);
+ Write_Str (Msg);
+ Write_Str (" (Comp_Id_");
+ Write_Int (Int (Comp));
+ Write_Str (")");
+ Write_Eol;
+
+ Trace_Step (Step);
+ Indent_By (Nested_Indentation);
+ Write_Str ("pending predecessors: ");
+ Write_Num (Int (Pending_Predecessors (G, Comp)));
+ Write_Eol;
+ end Trace_Component;
+
+ ----------------
+ -- Trace_Step --
+ ----------------
+
+ procedure Trace_Step (Step : Elaboration_Order_Step) is
+ begin
+ -- Nothing to do when switch -d_T (output elaboration order trace
+ -- information) is not in effect.
+
+ if not Debug_Flag_Underscore_TT then
+ return;
+ end if;
+
+ Write_Num
+ (Val => Int (Step),
+ Val_Indent => Step_Column);
+ Write_Str (": ");
+ end Trace_Step;
+
+ ---------------------------------
+ -- Trace_Unelaborated_Vertices --
+ ---------------------------------
+
+ procedure Trace_Unelaborated_Vertices
+ (G : Library_Graph;
+ Count : Natural;
+ Step : Elaboration_Order_Step)
+ is
+ Iter : Library_Graphs.All_Vertex_Iterator;
+ LGV_Id : Library_Graph_Vertex_Id;
+
+ begin
+ pragma Assert (Present (G));
+
+ -- Nothing to do when switch -d_T (output elaboration order trace
+ -- information) is not in effect.
+
+ if not Debug_Flag_Underscore_TT then
+ return;
+ end if;
+
+ Trace_Step (Step);
+ Write_Str ("remaining unelaborated vertices: ");
+ Write_Int (Int (Count));
+ Write_Eol;
+
+ Iter := Iterate_All_Vertices (G);
+ while Has_Next (Iter) loop
+ Next (Iter, LGV_Id);
+ pragma Assert (Present (LGV_Id));
+
+ if Needs_Elaboration (G, LGV_Id)
+ and then not In_Elaboration_Order (G, LGV_Id)
+ then
+ Trace_Vertex
+ (G => G,
+ LGV_Id => LGV_Id,
+ Msg => "remaining vertex",
+ Step => Step,
+ Indent => Nested_Indentation);
+ end if;
+ end loop;
+ end Trace_Unelaborated_Vertices;
+
+ ------------------
+ -- Trace_Vertex --
+ ------------------
+
+ procedure Trace_Vertex
+ (G : Library_Graph;
+ LGV_Id : Library_Graph_Vertex_Id;
+ Msg : String;
+ Step : Elaboration_Order_Step;
+ Indent : Indentation_Level)
+ is
+ pragma Assert (Present (G));
+ pragma Assert (Present (LGV_Id));
+
+ Comp : constant Component_Id := Component (G, LGV_Id);
+
+ pragma Assert (Present (Comp));
+
+ begin
+ -- Nothing to do when switch -d_T (output elaboration order trace
+ -- information) is not in effect.
+
+ if not Debug_Flag_Underscore_TT then
+ return;
+ end if;
+
+ Trace_Step (Step);
+ Indent_By (Indent);
+ Write_Str (Msg);
+ Write_Str (" (LGV_Id_");
+ Write_Int (Int (LGV_Id));
+ Write_Str (")");
+ Write_Eol;
+
+ Trace_Step (Step);
+ Indent_By (Indent + Nested_Indentation);
+ Write_Str ("name = ");
+ Write_Name (Name (G, LGV_Id));
+ Write_Eol;
+
+ Trace_Step (Step);
+ Indent_By (Indent + Nested_Indentation);
+ Write_Str ("Component (Comp_Id_");
+ Write_Int (Int (Comp));
+ Write_Str (")");
+ Write_Eol;
+
+ Trace_Step (Step);
+ Indent_By (Indent + Nested_Indentation);
+ Write_Str ("pending predecessors: ");
+ Write_Num (Int (Pending_Predecessors (G, LGV_Id)));
+ Write_Eol;
+
+ Trace_Step (Step);
+ Indent_By (Indent + Nested_Indentation);
+ Write_Str ("pending components : ");
+ Write_Num (Int (Pending_Predecessors (G, Comp)));
+ Write_Eol;
+ end Trace_Vertex;
+
+ ----------------------
+ -- Update_Successor --
+ ----------------------
+
+ procedure Update_Successor
+ (G : Library_Graph;
+ Pred : Library_Graph_Vertex_Id;
+ Succ : Library_Graph_Vertex_Id;
+ All_Candidates : Membership_Set;
+ Comp_Candidates : Membership_Set;
+ Step : Elaboration_Order_Step;
+ Indent : Indentation_Level)
+ is
+ pragma Assert (Present (G));
+ pragma Assert (Present (Pred));
+ pragma Assert (Needs_Elaboration (G, Pred));
+ pragma Assert (Present (Succ));
+ pragma Assert (Needs_Elaboration (G, Succ));
+ pragma Assert (Present (All_Candidates));
+ pragma Assert (Present (Comp_Candidates));
+
+ Pred_Comp : constant Component_Id := Component (G, Pred);
+ Succ_Comp : constant Component_Id := Component (G, Succ);
+
+ pragma Assert (Present (Pred_Comp));
+ pragma Assert (Present (Succ_Comp));
+
+ In_Different_Components : constant Boolean := Pred_Comp /= Succ_Comp;
+
+ Candidate : Library_Graph_Vertex_Id;
+ Iter : Component_Vertex_Iterator;
+ Msg : String_Ptr;
+ Set : Membership_Set;
+
+ begin
+ Trace_Vertex
+ (G => G,
+ LGV_Id => Succ,
+ Msg => "updating successor",
+ Step => Step,
+ Indent => Indent);
+
+ -- Notify the successor that it has one less predecessor to wait on.
+ -- This effectively eliminates the edge that links the two.
+
+ Decrement_Pending_Predecessors (G, Succ);
+
+ -- The predecessor and successor reside in different components.
+ -- Notify the successor component it has one fewer components to
+ -- wait on.
+
+ if In_Different_Components then
+ Decrement_Pending_Predecessors (G, Succ_Comp);
+ end if;
+
+ -- At this point the successor may become elaborable when its final
+ -- predecessor or final predecessor component is elaborated.
+
+ -- The predecessor and successor reside in different components.
+ -- The successor must not be added to the candidates of Pred's
+ -- component because this will mix units from the two components.
+ -- Instead, the successor is added to the set of all candidates
+ -- that must be elaborated.
+
+ if In_Different_Components then
+ Msg := Add_To_All_Candidates_Msg'Access;
+ Set := All_Candidates;
+
+ -- Otherwise the predecessor and successor reside within the same
+ -- component. Pred's component gains another elaborable node.
+
+ else
+ Msg := Add_To_Comp_Candidates_Msg'Access;
+ Set := Comp_Candidates;
+ end if;
+
+ Add_Vertex_If_Elaborable
+ (G => G,
+ LGV_Id => Succ,
+ Set => Set,
+ Msg => Msg.all,
+ Step => Step,
+ Indent => Indent + Nested_Indentation);
+
+ -- At this point the successor component may become elaborable when
+ -- its final predecessor component is elaborated. This in turn may
+ -- allow vertices of the successor component to be elaborated.
+
+ if In_Different_Components
+ and then Is_Elaborable_Component (G, Succ_Comp)
+ then
+ Iter := Iterate_Component_Vertices (G, Succ_Comp);
+ while Has_Next (Iter) loop
+ Next (Iter, Candidate);
+ pragma Assert (Present (Candidate));
+
+ Add_Vertex_If_Elaborable
+ (G => G,
+ LGV_Id => Candidate,
+ Set => All_Candidates,
+ Msg => Add_To_All_Candidates_Msg,
+ Step => Step,
+ Indent => Indent + Nested_Indentation);
+ end loop;
+ end if;
+ end Update_Successor;
+
+ -----------------------
+ -- Update_Successors --
+ -----------------------
+
+ procedure Update_Successors
+ (G : Library_Graph;
+ Pred : Library_Graph_Vertex_Id;
+ All_Candidates : Membership_Set;
+ Comp_Candidates : Membership_Set;
+ Step : Elaboration_Order_Step;
+ Indent : Indentation_Level)
+ is
+ Iter : Edges_To_Successors_Iterator;
+ LGE_Id : Library_Graph_Edge_Id;
+ Succ : Library_Graph_Vertex_Id;
+
+ begin
+ pragma Assert (Present (G));
+ pragma Assert (Present (Pred));
+ pragma Assert (Needs_Elaboration (G, Pred));
+ pragma Assert (Present (All_Candidates));
+ pragma Assert (Present (Comp_Candidates));
+
+ Iter := Iterate_Edges_To_Successors (G, Pred);
+ while Has_Next (Iter) loop
+ Next (Iter, LGE_Id);
+
+ pragma Assert (Present (LGE_Id));
+ pragma Assert (Predecessor (G, LGE_Id) = Pred);
+
+ Succ := Successor (G, LGE_Id);
+ pragma Assert (Present (Succ));
+
+ Update_Successor
+ (G => G,
+ Pred => Pred,
+ Succ => Succ,
+ All_Candidates => All_Candidates,
+ Comp_Candidates => Comp_Candidates,
+ Step => Step,
+ Indent => Indent);
+ end loop;
+ end Update_Successors;
+ end Invocation_And_Library_Graph_Elaborators;
+
+end Bindo.Elaborators;
diff --git a/gcc/ada/bindo-elaborators.ads b/gcc/ada/bindo-elaborators.ads
new file mode 100644
index 0000000..c65f593
--- /dev/null
+++ b/gcc/ada/bindo-elaborators.ads
@@ -0,0 +1,55 @@
+------------------------------------------------------------------------------
+-- --
+-- GNAT COMPILER COMPONENTS --
+-- --
+-- B I N D O . E L A B O R A T O R S --
+-- --
+-- S p e c --
+-- --
+-- Copyright (C) 2019, 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. See the GNU General Public License --
+-- for more details. You should have received a copy of the GNU General --
+-- Public License distributed with GNAT; see file COPYING3. If not, go to --
+-- http://www.gnu.org/licenses for a complete copy of the license. --
+-- --
+-- GNAT was originally developed by the GNAT team at New York University. --
+-- Extensive contributions were provided by Ada Core Technologies Inc. --
+-- --
+------------------------------------------------------------------------------
+
+-- For full architecture, see unit Bindo.
+
+-- The following unit contains facilities to find the elaboration order of
+-- units based on various graphs.
+
+with Bindo.Graphs;
+use Bindo.Graphs;
+use Bindo.Graphs.Invocation_Graphs;
+use Bindo.Graphs.Library_Graphs;
+
+package Bindo.Elaborators is
+
+ ----------------------------------------------
+ -- Invocation_And_Library_Graph_Elaborators --
+ ----------------------------------------------
+
+ package Invocation_And_Library_Graph_Elaborators is
+ procedure Elaborate_Units
+ (Order : out Unit_Id_Table;
+ Main_Lib_File : File_Name_Type);
+ -- Find an order of all units in the bind that need to be elaborated
+ -- such that elaboration code flow, pragmas Elaborate, Elaborate_All,
+ -- and Elaborate_Body, and with clause dependencies are all honoured.
+ -- Main_Lib_File is the argument of the bind. If a satisfactory order
+ -- exists, it is returned in Order, otherwise Unrecoverable_Error is
+ -- raised.
+
+ end Invocation_And_Library_Graph_Elaborators;
+
+end Bindo.Elaborators;
diff --git a/gcc/ada/bindo-graphs.adb b/gcc/ada/bindo-graphs.adb
new file mode 100644
index 0000000..b2f458c
--- /dev/null
+++ b/gcc/ada/bindo-graphs.adb
@@ -0,0 +1,2886 @@
+------------------------------------------------------------------------------
+-- --
+-- GNAT COMPILER COMPONENTS --
+-- --
+-- B I N D O . G R A P H S --
+-- --
+-- B o d y --
+-- --
+-- Copyright (C) 2019, 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. See the GNU General Public License --
+-- for more details. You should have received a copy of the GNU General --
+-- Public License distributed with GNAT; see file COPYING3. If not, go to --
+-- http://www.gnu.org/licenses for a complete copy of the license. --
+-- --
+-- GNAT was originally developed by the GNAT team at New York University. --
+-- Extensive contributions were provided by Ada Core Technologies Inc. --
+-- --
+------------------------------------------------------------------------------
+
+with Ada.Unchecked_Deallocation;
+
+with GNAT.Lists; use GNAT.Lists;
+
+package body Bindo.Graphs is
+
+ -----------------------
+ -- Local subprograms --
+ -----------------------
+
+ function Sequence_Next_IGE_Id return Invocation_Graph_Edge_Id;
+ pragma Inline (Sequence_Next_IGE_Id);
+ -- Generate a new unique invocation graph edge handle
+
+ function Sequence_Next_IGV_Id return Invocation_Graph_Vertex_Id;
+ pragma Inline (Sequence_Next_IGV_Id);
+ -- Generate a new unique invocation graph vertex handle
+
+ function Sequence_Next_LGE_Id return Library_Graph_Edge_Id;
+ pragma Inline (Sequence_Next_LGE_Id);
+ -- Generate a new unique library graph edge handle
+
+ function Sequence_Next_LGV_Id return Library_Graph_Vertex_Id;
+ pragma Inline (Sequence_Next_LGV_Id);
+ -- Generate a new unique library graph vertex handle
+
+ --------------------------------
+ -- Hash_Invocation_Graph_Edge --
+ --------------------------------
+
+ function Hash_Invocation_Graph_Edge
+ (IGE_Id : Invocation_Graph_Edge_Id) return Bucket_Range_Type
+ is
+ begin
+ pragma Assert (Present (IGE_Id));
+
+ return Bucket_Range_Type (IGE_Id);
+ end Hash_Invocation_Graph_Edge;
+
+ ----------------------------------
+ -- Hash_Invocation_Graph_Vertex --
+ ----------------------------------
+
+ function Hash_Invocation_Graph_Vertex
+ (IGV_Id : Invocation_Graph_Vertex_Id) return Bucket_Range_Type
+ is
+ begin
+ pragma Assert (Present (IGV_Id));
+
+ return Bucket_Range_Type (IGV_Id);
+ end Hash_Invocation_Graph_Vertex;
+
+ -----------------------------
+ -- Hash_Library_Graph_Edge --
+ -----------------------------
+
+ function Hash_Library_Graph_Edge
+ (LGE_Id : Library_Graph_Edge_Id) return Bucket_Range_Type
+ is
+ begin
+ pragma Assert (Present (LGE_Id));
+
+ return Bucket_Range_Type (LGE_Id);
+ end Hash_Library_Graph_Edge;
+
+ -------------------------------
+ -- Hash_Library_Graph_Vertex --
+ -------------------------------
+
+ function Hash_Library_Graph_Vertex
+ (LGV_Id : Library_Graph_Vertex_Id) return Bucket_Range_Type
+ is
+ begin
+ pragma Assert (Present (LGV_Id));
+
+ return Bucket_Range_Type (LGV_Id);
+ end Hash_Library_Graph_Vertex;
+
+ -----------------------
+ -- Invocation_Graphs --
+ -----------------------
+
+ package body Invocation_Graphs is
+
+ -----------------------
+ -- Local subprograms --
+ -----------------------
+
+ procedure Free is
+ new Ada.Unchecked_Deallocation
+ (Invocation_Graph_Attributes, Invocation_Graph);
+
+ function Get_IGE_Attributes
+ (G : Invocation_Graph;
+ IGE_Id : Invocation_Graph_Edge_Id)
+ return Invocation_Graph_Edge_Attributes;
+ pragma Inline (Get_IGE_Attributes);
+ -- Obtain the attributes of edge IGE_Id of invocation graph G
+
+ function Get_IGV_Attributes
+ (G : Invocation_Graph;
+ IGV_Id : Invocation_Graph_Vertex_Id)
+ return Invocation_Graph_Vertex_Attributes;
+ pragma Inline (Get_IGV_Attributes);
+ -- Obtain the attributes of vertex IGV_Id of invocation graph G
+
+ procedure Increment_Invocation_Graph_Edge_Count
+ (G : Invocation_Graph;
+ Kind : Invocation_Kind);
+ pragma Inline (Increment_Invocation_Graph_Edge_Count);
+ -- Increment the number of edges of king Kind in invocation graph G by
+ -- one.
+
+ function Is_Elaboration_Root
+ (G : Invocation_Graph;
+ IGV_Id : Invocation_Graph_Vertex_Id) return Boolean;
+ pragma Inline (Is_Elaboration_Root);
+ -- Determine whether vertex IGV_Id of invocation graph denotes the
+ -- elaboration procedure of a spec or a body.
+
+ function Is_Existing_Source_Target_Relation
+ (G : Invocation_Graph;
+ Rel : Source_Target_Relation) return Boolean;
+ pragma Inline (Is_Existing_Source_Target_Relation);
+ -- Determine whether a source vertex and a target vertex desctibed by
+ -- relation Rel are already related in invocation graph G.
+
+ procedure Save_Elaboration_Root
+ (G : Invocation_Graph;
+ Root : Invocation_Graph_Vertex_Id);
+ pragma Inline (Save_Elaboration_Root);
+ -- Save elaboration root Root of invocation graph G
+
+ procedure Set_Corresponding_Vertex
+ (G : Invocation_Graph;
+ IS_Id : Invocation_Signature_Id;
+ IGV_Id : Invocation_Graph_Vertex_Id);
+ pragma Inline (Set_Corresponding_Vertex);
+ -- Associate vertex IGV_Id of invocation graph G with signature IS_Id
+
+ procedure Set_Is_Existing_Source_Target_Relation
+ (G : Invocation_Graph;
+ Rel : Source_Target_Relation;
+ Val : Boolean := True);
+ pragma Inline (Set_Is_Existing_Source_Target_Relation);
+ -- Mark a source vertex and a target vertex desctibed by relation Rel as
+ -- already related in invocation graph G depending on value Val.
+
+ procedure Set_IGE_Attributes
+ (G : Invocation_Graph;
+ IGE_Id : Invocation_Graph_Edge_Id;
+ Val : Invocation_Graph_Edge_Attributes);
+ pragma Inline (Set_IGE_Attributes);
+ -- Set the attributes of edge IGE_Id of invocation graph G to value Val
+
+ procedure Set_IGV_Attributes
+ (G : Invocation_Graph;
+ IGV_Id : Invocation_Graph_Vertex_Id;
+ Val : Invocation_Graph_Vertex_Attributes);
+ pragma Inline (Set_IGV_Attributes);
+ -- Set the attributes of vertex IGV_Id of invocation graph G to value
+ -- Val.
+
+ --------------
+ -- Add_Edge --
+ --------------
+
+ procedure Add_Edge
+ (G : Invocation_Graph;
+ Source : Invocation_Graph_Vertex_Id;
+ Target : Invocation_Graph_Vertex_Id;
+ IR_Id : Invocation_Relation_Id)
+ is
+ pragma Assert (Present (G));
+ pragma Assert (Present (Source));
+ pragma Assert (Present (Target));
+ pragma Assert (Present (IR_Id));
+
+ Rel : constant Source_Target_Relation :=
+ (Source => Source,
+ Target => Target);
+
+ IR_Rec : Invocation_Relation_Record renames
+ Invocation_Relations.Table (IR_Id);
+
+ IGE_Id : Invocation_Graph_Edge_Id;
+
+ begin
+ -- Nothing to do when the source and target are already related by an
+ -- edge.
+
+ if Is_Existing_Source_Target_Relation (G, Rel) then
+ return;
+ end if;
+
+ IGE_Id := Sequence_Next_IGE_Id;
+
+ -- Add the edge to the underlying graph
+
+ DG.Add_Edge
+ (G => G.Graph,
+ E => IGE_Id,
+ Source => Source,
+ Destination => Target);
+
+ -- Build and save the attributes of the edge
+
+ Set_IGE_Attributes
+ (G => G,
+ IGE_Id => IGE_Id,
+ Val => (Relation => IR_Id));
+
+ -- Mark the source and target as related by the new edge. This
+ -- prevents all further attempts to link the same source and target.
+
+ Set_Is_Existing_Source_Target_Relation (G, Rel);
+
+ -- Update the edge statistics
+
+ Increment_Invocation_Graph_Edge_Count (G, IR_Rec.Kind);
+ end Add_Edge;
+
+ ----------------
+ -- Add_Vertex --
+ ----------------
+
+ procedure Add_Vertex
+ (G : Invocation_Graph;
+ IC_Id : Invocation_Construct_Id;
+ LGV_Id : Library_Graph_Vertex_Id)
+ is
+ pragma Assert (Present (G));
+ pragma Assert (Present (IC_Id));
+ pragma Assert (Present (LGV_Id));
+
+ IC_Rec : Invocation_Construct_Record renames
+ Invocation_Constructs.Table (IC_Id);
+
+ pragma Assert (Present (IC_Rec.Signature));
+
+ IGV_Id : Invocation_Graph_Vertex_Id;
+
+ begin
+ -- Nothing to do when the construct already has a vertex
+
+ if Present (Corresponding_Vertex (G, IC_Rec.Signature)) then
+ return;
+ end if;
+
+ IGV_Id := Sequence_Next_IGV_Id;
+
+ -- Add the vertex to the underlying graph
+
+ DG.Add_Vertex (G.Graph, IGV_Id);
+
+ -- Build and save the attributes of the vertex
+
+ Set_IGV_Attributes
+ (G => G,
+ IGV_Id => IGV_Id,
+ Val => (Construct => IC_Id,
+ Lib_Vertex => LGV_Id));
+
+ -- Associate the construct with its corresponding vertex
+
+ Set_Corresponding_Vertex (G, IC_Rec.Signature, IGV_Id);
+
+ -- Save the vertex for later processing when it denotes a spec or
+ -- body elaboration procedure.
+
+ if Is_Elaboration_Root (G, IGV_Id) then
+ Save_Elaboration_Root (G, IGV_Id);
+ end if;
+ end Add_Vertex;
+
+ ---------------
+ -- Construct --
+ ---------------
+
+ function Construct
+ (G : Invocation_Graph;
+ IGV_Id : Invocation_Graph_Vertex_Id) return Invocation_Construct_Id
+ is
+ begin
+ pragma Assert (Present (G));
+ pragma Assert (Present (IGV_Id));
+
+ return Get_IGV_Attributes (G, IGV_Id).Construct;
+ end Construct;
+
+ --------------------------
+ -- Corresponding_Vertex --
+ --------------------------
+
+ function Corresponding_Vertex
+ (G : Invocation_Graph;
+ IS_Id : Invocation_Signature_Id) return Invocation_Graph_Vertex_Id
+ is
+ begin
+ pragma Assert (Present (G));
+ pragma Assert (Present (IS_Id));
+
+ return SV.Get (G.Signature_To_Vertex, IS_Id);
+ end Corresponding_Vertex;
+
+ ------------
+ -- Create --
+ ------------
+
+ function Create
+ (Initial_Vertices : Positive;
+ Initial_Edges : Positive) return Invocation_Graph
+ is
+ G : constant Invocation_Graph := new Invocation_Graph_Attributes;
+
+ begin
+ G.Edge_Attributes := EA.Create (Initial_Edges);
+ G.Graph :=
+ DG.Create
+ (Initial_Vertices => Initial_Vertices,
+ Initial_Edges => Initial_Edges);
+ G.Relations := ST.Create (Initial_Edges);
+ G.Roots := ER.Create (Initial_Vertices);
+ G.Signature_To_Vertex := SV.Create (Initial_Vertices);
+ G.Vertex_Attributes := VA.Create (Initial_Vertices);
+
+ return G;
+ end Create;
+
+ -------------
+ -- Destroy --
+ -------------
+
+ procedure Destroy (G : in out Invocation_Graph) is
+ begin
+ pragma Assert (Present (G));
+
+ EA.Destroy (G.Edge_Attributes);
+ DG.Destroy (G.Graph);
+ ST.Destroy (G.Relations);
+ ER.Destroy (G.Roots);
+ SV.Destroy (G.Signature_To_Vertex);
+ VA.Destroy (G.Vertex_Attributes);
+
+ Free (G);
+ end Destroy;
+
+ -----------------------------------
+ -- Destroy_Invocation_Graph_Edge --
+ -----------------------------------
+
+ procedure Destroy_Invocation_Graph_Edge
+ (IGE_Id : in out Invocation_Graph_Edge_Id)
+ is
+ pragma Unreferenced (IGE_Id);
+ begin
+ null;
+ end Destroy_Invocation_Graph_Edge;
+
+ ----------------------------------------------
+ -- Destroy_Invocation_Graph_Edge_Attributes --
+ ----------------------------------------------
+
+ procedure Destroy_Invocation_Graph_Edge_Attributes
+ (Attrs : in out Invocation_Graph_Edge_Attributes)
+ is
+ pragma Unreferenced (Attrs);
+ begin
+ null;
+ end Destroy_Invocation_Graph_Edge_Attributes;
+
+ -------------------------------------
+ -- Destroy_Invocation_Graph_Vertex --
+ -------------------------------------
+
+ procedure Destroy_Invocation_Graph_Vertex
+ (IGV_Id : in out Invocation_Graph_Vertex_Id)
+ is
+ pragma Unreferenced (IGV_Id);
+ begin
+ null;
+ end Destroy_Invocation_Graph_Vertex;
+
+ ------------------------------------------------
+ -- Destroy_Invocation_Graph_Vertex_Attributes --
+ ------------------------------------------------
+
+ procedure Destroy_Invocation_Graph_Vertex_Attributes
+ (Attrs : in out Invocation_Graph_Vertex_Attributes)
+ is
+ pragma Unreferenced (Attrs);
+ begin
+ null;
+ end Destroy_Invocation_Graph_Vertex_Attributes;
+
+ ------------------------
+ -- Get_IGE_Attributes --
+ ------------------------
+
+ function Get_IGE_Attributes
+ (G : Invocation_Graph;
+ IGE_Id : Invocation_Graph_Edge_Id)
+ return Invocation_Graph_Edge_Attributes
+ is
+ begin
+ pragma Assert (Present (G));
+ pragma Assert (Present (IGE_Id));
+
+ return EA.Get (G.Edge_Attributes, IGE_Id);
+ end Get_IGE_Attributes;
+
+ ------------------------
+ -- Get_IGV_Attributes --
+ ------------------------
+
+ function Get_IGV_Attributes
+ (G : Invocation_Graph;
+ IGV_Id : Invocation_Graph_Vertex_Id)
+ return Invocation_Graph_Vertex_Attributes
+ is
+ begin
+ pragma Assert (Present (G));
+ pragma Assert (Present (IGV_Id));
+
+ return VA.Get (G.Vertex_Attributes, IGV_Id);
+ end Get_IGV_Attributes;
+
+ --------------
+ -- Has_Next --
+ --------------
+
+ function Has_Next (Iter : All_Edge_Iterator) return Boolean is
+ begin
+ return DG.Has_Next (DG.All_Edge_Iterator (Iter));
+ end Has_Next;
+
+ --------------
+ -- Has_Next --
+ --------------
+
+ function Has_Next (Iter : All_Vertex_Iterator) return Boolean is
+ begin
+ return DG.Has_Next (DG.All_Vertex_Iterator (Iter));
+ end Has_Next;
+
+ --------------
+ -- Has_Next --
+ --------------
+
+ function Has_Next (Iter : Edges_To_Targets_Iterator) return Boolean is
+ begin
+ return DG.Has_Next (DG.Outgoing_Edge_Iterator (Iter));
+ end Has_Next;
+
+ --------------
+ -- Has_Next --
+ --------------
+
+ function Has_Next (Iter : Elaboration_Root_Iterator) return Boolean is
+ begin
+ return ER.Has_Next (ER.Iterator (Iter));
+ end Has_Next;
+
+ -------------------------------
+ -- Hash_Invocation_Signature --
+ -------------------------------
+
+ function Hash_Invocation_Signature
+ (IS_Id : Invocation_Signature_Id) return Bucket_Range_Type
+ is
+ begin
+ pragma Assert (Present (IS_Id));
+
+ return Bucket_Range_Type (IS_Id);
+ end Hash_Invocation_Signature;
+
+ ---------------------------------
+ -- Hash_Source_Target_Relation --
+ ---------------------------------
+
+ function Hash_Source_Target_Relation
+ (Rel : Source_Target_Relation) return Bucket_Range_Type
+ is
+ begin
+ pragma Assert (Present (Rel.Source));
+ pragma Assert (Present (Rel.Target));
+
+ return
+ Hash_Two_Keys
+ (Bucket_Range_Type (Rel.Source),
+ Bucket_Range_Type (Rel.Target));
+ end Hash_Source_Target_Relation;
+
+ -------------------------------------------
+ -- Increment_Invocation_Graph_Edge_Count --
+ -------------------------------------------
+
+ procedure Increment_Invocation_Graph_Edge_Count
+ (G : Invocation_Graph;
+ Kind : Invocation_Kind)
+ is
+ pragma Assert (Present (G));
+
+ Count : Natural renames G.Counts (Kind);
+
+ begin
+ Count := Count + 1;
+ end Increment_Invocation_Graph_Edge_Count;
+
+ ---------------------------------
+ -- Invocation_Graph_Edge_Count --
+ ---------------------------------
+
+ function Invocation_Graph_Edge_Count
+ (G : Invocation_Graph;
+ Kind : Invocation_Kind) return Natural
+ is
+ begin
+ pragma Assert (Present (G));
+
+ return G.Counts (Kind);
+ end Invocation_Graph_Edge_Count;
+
+ -------------------------
+ -- Is_Elaboration_Root --
+ -------------------------
+
+ function Is_Elaboration_Root
+ (G : Invocation_Graph;
+ IGV_Id : Invocation_Graph_Vertex_Id) return Boolean
+ is
+ pragma Assert (Present (G));
+ pragma Assert (Present (IGV_Id));
+
+ IC_Id : constant Invocation_Construct_Id := Construct (G, IGV_Id);
+
+ pragma Assert (Present (IC_Id));
+
+ IC_Rec : Invocation_Construct_Record renames
+ Invocation_Constructs.Table (IC_Id);
+
+ begin
+ return
+ IC_Rec.Kind = Elaborate_Body_Procedure
+ or else
+ IC_Rec.Kind = Elaborate_Spec_Procedure;
+ end Is_Elaboration_Root;
+
+ ----------------------------------------
+ -- Is_Existing_Source_Target_Relation --
+ ----------------------------------------
+
+ function Is_Existing_Source_Target_Relation
+ (G : Invocation_Graph;
+ Rel : Source_Target_Relation) return Boolean
+ is
+ begin
+ pragma Assert (Present (G));
+
+ return ST.Contains (G.Relations, Rel);
+ end Is_Existing_Source_Target_Relation;
+
+ -----------------------
+ -- Iterate_All_Edges --
+ -----------------------
+
+ function Iterate_All_Edges
+ (G : Invocation_Graph) return All_Edge_Iterator
+ is
+ begin
+ pragma Assert (Present (G));
+
+ return All_Edge_Iterator (DG.Iterate_All_Edges (G.Graph));
+ end Iterate_All_Edges;
+
+ --------------------------
+ -- Iterate_All_Vertices --
+ --------------------------
+
+ function Iterate_All_Vertices
+ (G : Invocation_Graph) return All_Vertex_Iterator
+ is
+ begin
+ pragma Assert (Present (G));
+
+ return All_Vertex_Iterator (DG.Iterate_All_Vertices (G.Graph));
+ end Iterate_All_Vertices;
+
+ ------------------------------
+ -- Iterate_Edges_To_Targets --
+ ------------------------------
+
+ function Iterate_Edges_To_Targets
+ (G : Invocation_Graph;
+ IGV_Id : Invocation_Graph_Vertex_Id) return Edges_To_Targets_Iterator
+ is
+ begin
+ pragma Assert (Present (G));
+ pragma Assert (Present (IGV_Id));
+
+ return
+ Edges_To_Targets_Iterator
+ (DG.Iterate_Outgoing_Edges (G.Graph, IGV_Id));
+ end Iterate_Edges_To_Targets;
+
+ -------------------------------
+ -- Iterate_Elaboration_Roots --
+ -------------------------------
+
+ function Iterate_Elaboration_Roots
+ (G : Invocation_Graph) return Elaboration_Root_Iterator
+ is
+ begin
+ pragma Assert (Present (G));
+
+ return Elaboration_Root_Iterator (ER.Iterate (G.Roots));
+ end Iterate_Elaboration_Roots;
+
+ ----------
+ -- Kind --
+ ----------
+
+ function Kind
+ (G : Invocation_Graph;
+ IGE_Id : Invocation_Graph_Edge_Id) return Invocation_Kind
+ is
+ pragma Assert (Present (G));
+ pragma Assert (Present (IGE_Id));
+
+ IR_Id : constant Invocation_Relation_Id := Relation (G, IGE_Id);
+
+ pragma Assert (Present (IR_Id));
+
+ IR_Rec : Invocation_Relation_Record renames
+ Invocation_Relations.Table (IR_Id);
+
+ begin
+ return IR_Rec.Kind;
+ end Kind;
+
+ ----------------
+ -- Lib_Vertex --
+ ----------------
+
+ function Lib_Vertex
+ (G : Invocation_Graph;
+ IGV_Id : Invocation_Graph_Vertex_Id) return Library_Graph_Vertex_Id
+ is
+ begin
+ pragma Assert (Present (G));
+ pragma Assert (Present (IGV_Id));
+
+ return Get_IGV_Attributes (G, IGV_Id).Lib_Vertex;
+ end Lib_Vertex;
+
+ ----------
+ -- Name --
+ ----------
+
+ function Name
+ (G : Invocation_Graph;
+ IGV_Id : Invocation_Graph_Vertex_Id) return Name_Id
+ is
+ pragma Assert (Present (G));
+ pragma Assert (Present (IGV_Id));
+
+ IC_Id : constant Invocation_Construct_Id := Construct (G, IGV_Id);
+
+ pragma Assert (Present (IC_Id));
+
+ IC_Rec : Invocation_Construct_Record renames
+ Invocation_Constructs.Table (IC_Id);
+
+ pragma Assert (Present (IC_Rec.Signature));
+
+ IS_Rec : Invocation_Signature_Record renames
+ Invocation_Signatures.Table (IC_Rec.Signature);
+
+ begin
+ return IS_Rec.Name;
+ end Name;
+
+ ----------
+ -- Next --
+ ----------
+
+ procedure Next
+ (Iter : in out All_Edge_Iterator;
+ IGE_Id : out Invocation_Graph_Edge_Id)
+ is
+ begin
+ DG.Next (DG.All_Edge_Iterator (Iter), IGE_Id);
+ end Next;
+
+ ----------
+ -- Next --
+ ----------
+
+ procedure Next
+ (Iter : in out All_Vertex_Iterator;
+ IGV_Id : out Invocation_Graph_Vertex_Id)
+ is
+ begin
+ DG.Next (DG.All_Vertex_Iterator (Iter), IGV_Id);
+ end Next;
+
+ ----------
+ -- Next --
+ ----------
+
+ procedure Next
+ (Iter : in out Edges_To_Targets_Iterator;
+ IGE_Id : out Invocation_Graph_Edge_Id)
+ is
+ begin
+ DG.Next (DG.Outgoing_Edge_Iterator (Iter), IGE_Id);
+ end Next;
+
+ ----------
+ -- Next --
+ ----------
+
+ procedure Next
+ (Iter : in out Elaboration_Root_Iterator;
+ Root : out Invocation_Graph_Vertex_Id)
+ is
+ begin
+ ER.Next (ER.Iterator (Iter), Root);
+ end Next;
+
+ ---------------------
+ -- Number_Of_Edges --
+ ---------------------
+
+ function Number_Of_Edges (G : Invocation_Graph) return Natural is
+ begin
+ pragma Assert (Present (G));
+
+ return DG.Number_Of_Edges (G.Graph);
+ end Number_Of_Edges;
+
+ --------------------------------
+ -- Number_Of_Edges_To_Targets --
+ --------------------------------
+
+ function Number_Of_Edges_To_Targets
+ (G : Invocation_Graph;
+ IGV_Id : Invocation_Graph_Vertex_Id) return Natural
+ is
+ begin
+ pragma Assert (Present (G));
+ pragma Assert (Present (IGV_Id));
+
+ return DG.Number_Of_Outgoing_Edges (G.Graph, IGV_Id);
+ end Number_Of_Edges_To_Targets;
+
+ ---------------------------------
+ -- Number_Of_Elaboration_Roots --
+ ---------------------------------
+
+ function Number_Of_Elaboration_Roots
+ (G : Invocation_Graph) return Natural
+ is
+ begin
+ pragma Assert (Present (G));
+
+ return ER.Size (G.Roots);
+ end Number_Of_Elaboration_Roots;
+
+ ------------------------
+ -- Number_Of_Vertices --
+ ------------------------
+
+ function Number_Of_Vertices (G : Invocation_Graph) return Natural is
+ begin
+ pragma Assert (Present (G));
+
+ return DG.Number_Of_Vertices (G.Graph);
+ end Number_Of_Vertices;
+
+ -------------
+ -- Present --
+ -------------
+
+ function Present (G : Invocation_Graph) return Boolean is
+ begin
+ return G /= Nil;
+ end Present;
+
+ --------------
+ -- Relation --
+ --------------
+
+ function Relation
+ (G : Invocation_Graph;
+ IGE_Id : Invocation_Graph_Edge_Id) return Invocation_Relation_Id
+ is
+ begin
+ pragma Assert (Present (G));
+ pragma Assert (Present (IGE_Id));
+
+ return Get_IGE_Attributes (G, IGE_Id).Relation;
+ end Relation;
+
+ ---------------------------
+ -- Save_Elaboration_Root --
+ ---------------------------
+
+ procedure Save_Elaboration_Root
+ (G : Invocation_Graph;
+ Root : Invocation_Graph_Vertex_Id)
+ is
+ begin
+ pragma Assert (Present (G));
+ pragma Assert (Present (Root));
+
+ ER.Insert (G.Roots, Root);
+ end Save_Elaboration_Root;
+
+ ------------------------------
+ -- Set_Corresponding_Vertex --
+ ------------------------------
+
+ procedure Set_Corresponding_Vertex
+ (G : Invocation_Graph;
+ IS_Id : Invocation_Signature_Id;
+ IGV_Id : Invocation_Graph_Vertex_Id)
+ is
+ begin
+ pragma Assert (Present (G));
+ pragma Assert (Present (IS_Id));
+ pragma Assert (Present (IGV_Id));
+
+ SV.Put (G.Signature_To_Vertex, IS_Id, IGV_Id);
+ end Set_Corresponding_Vertex;
+
+ --------------------------------------------
+ -- Set_Is_Existing_Source_Target_Relation --
+ --------------------------------------------
+
+ procedure Set_Is_Existing_Source_Target_Relation
+ (G : Invocation_Graph;
+ Rel : Source_Target_Relation;
+ Val : Boolean := True)
+ is
+ begin
+ pragma Assert (Present (G));
+ pragma Assert (Present (Rel.Source));
+ pragma Assert (Present (Rel.Target));
+
+ if Val then
+ ST.Insert (G.Relations, Rel);
+ else
+ ST.Delete (G.Relations, Rel);
+ end if;
+ end Set_Is_Existing_Source_Target_Relation;
+
+ ------------------------
+ -- Set_IGE_Attributes --
+ ------------------------
+
+ procedure Set_IGE_Attributes
+ (G : Invocation_Graph;
+ IGE_Id : Invocation_Graph_Edge_Id;
+ Val : Invocation_Graph_Edge_Attributes)
+ is
+ begin
+ pragma Assert (Present (G));
+ pragma Assert (Present (IGE_Id));
+
+ EA.Put (G.Edge_Attributes, IGE_Id, Val);
+ end Set_IGE_Attributes;
+
+ ------------------------
+ -- Set_IGV_Attributes --
+ ------------------------
+
+ procedure Set_IGV_Attributes
+ (G : Invocation_Graph;
+ IGV_Id : Invocation_Graph_Vertex_Id;
+ Val : Invocation_Graph_Vertex_Attributes)
+ is
+ begin
+ pragma Assert (Present (G));
+ pragma Assert (Present (IGV_Id));
+
+ VA.Put (G.Vertex_Attributes, IGV_Id, Val);
+ end Set_IGV_Attributes;
+
+ ------------
+ -- Target --
+ ------------
+
+ function Target
+ (G : Invocation_Graph;
+ IGE_Id : Invocation_Graph_Edge_Id) return Invocation_Graph_Vertex_Id
+ is
+ begin
+ pragma Assert (Present (G));
+ pragma Assert (Present (IGE_Id));
+
+ return DG.Destination_Vertex (G.Graph, IGE_Id);
+ end Target;
+ end Invocation_Graphs;
+
+ --------------------
+ -- Library_Graphs --
+ --------------------
+
+ package body Library_Graphs is
+
+ ---------------
+ -- Edge list --
+ ---------------
+
+ package EL is new Doubly_Linked_Lists
+ (Element_Type => Library_Graph_Edge_Id,
+ "=" => "=",
+ Destroy_Element => Destroy_Library_Graph_Edge);
+
+ -----------------------
+ -- Local subprograms --
+ -----------------------
+
+ procedure Add_Body_Before_Spec_Edge
+ (G : Library_Graph;
+ LGV_Id : Library_Graph_Vertex_Id;
+ Edges : EL.Doubly_Linked_List);
+ pragma Inline (Add_Body_Before_Spec_Edge);
+ -- Create a new edge in library graph G between vertex LGV_Id and its
+ -- corresponding spec or body, where the body is a predecessor and the
+ -- spec a successor. Add the edge to list Edges.
+
+ procedure Add_Body_Before_Spec_Edges
+ (G : Library_Graph;
+ Edges : EL.Doubly_Linked_List);
+ pragma Inline (Add_Body_Before_Spec_Edges);
+ -- Create new edges in library graph G for all vertices and their
+ -- corresponding specs or bodies, where the body is a predecessor
+ -- and the spec is a successor. Add all edges to list Edges.
+
+ function Add_Edge_With_Return
+ (G : Library_Graph;
+ Pred : Library_Graph_Vertex_Id;
+ Succ : Library_Graph_Vertex_Id;
+ Kind : Library_Graph_Edge_Kind) return Library_Graph_Edge_Id;
+ pragma Inline (Add_Edge_With_Return);
+ -- Create a new edge in library graph G with source vertex Pred and
+ -- destination vertex Succ, and return its handle. Kind denotes the
+ -- nature of the edge. If Pred and Succ are already related, no edge
+ -- is created and No_Library_Graph_Edge is returned.
+
+ procedure Decrement_Library_Graph_Edge_Count
+ (G : Library_Graph;
+ Kind : Library_Graph_Edge_Kind);
+ pragma Inline (Decrement_Library_Graph_Edge_Count);
+ -- Decrement the number of edges of kind King in library graph G by one
+
+ procedure Delete_Body_Before_Spec_Edges
+ (G : Library_Graph;
+ Edges : EL.Doubly_Linked_List);
+ pragma Inline (Delete_Body_Before_Spec_Edges);
+ -- Delete all edges in list Edges from library graph G, that link spec
+ -- and bodies, where the body acts as the predecessor and the spec as a
+ -- successor.
+
+ procedure Delete_Edge
+ (G : Library_Graph;
+ LGE_Id : Library_Graph_Edge_Id);
+ pragma Inline (Delete_Edge);
+ -- Delete edge LGE_Id from library graph G
+
+ procedure Free is
+ new Ada.Unchecked_Deallocation
+ (Library_Graph_Attributes, Library_Graph);
+
+ function Get_Component_Attributes
+ (G : Library_Graph;
+ Comp : Component_Id) return Component_Attributes;
+ pragma Inline (Get_Component_Attributes);
+ -- Obtain the attributes of component Comp of library graph G
+
+ function Get_LGE_Attributes
+ (G : Library_Graph;
+ LGE_Id : Library_Graph_Edge_Id)
+ return Library_Graph_Edge_Attributes;
+ pragma Inline (Get_LGE_Attributes);
+ -- Obtain the attributes of edge LGE_Id of library graph G
+
+ function Get_LGV_Attributes
+ (G : Library_Graph;
+ LGV_Id : Library_Graph_Vertex_Id)
+ return Library_Graph_Vertex_Attributes;
+ pragma Inline (Get_LGV_Attributes);
+ -- Obtain the attributes of vertex LGE_Id of library graph G
+
+ function Has_Elaborate_Body
+ (G : Library_Graph;
+ LGV_Id : Library_Graph_Vertex_Id) return Boolean;
+ pragma Inline (Has_Elaborate_Body);
+ -- Determine whether vertex LGV_Id of library graph G is subject to
+ -- pragma Elaborate_Body.
+
+ procedure Increment_Library_Graph_Edge_Count
+ (G : Library_Graph;
+ Kind : Library_Graph_Edge_Kind);
+ pragma Inline (Increment_Library_Graph_Edge_Count);
+ -- Increment the number of edges of king Kind in library graph G by one
+
+ procedure Increment_Pending_Predecessors
+ (G : Library_Graph;
+ Comp : Component_Id);
+ pragma Inline (Increment_Pending_Predecessors);
+ -- Increment the number of pending precedessors component Comp of
+ -- library graph G must wait on before it can be elaborated by one.
+
+ procedure Increment_Pending_Predecessors
+ (G : Library_Graph;
+ LGV_Id : Library_Graph_Vertex_Id);
+ pragma Inline (Increment_Pending_Predecessors);
+ -- Increment the number of pending precedessors vertex LGV_Id of library
+ -- graph G must wait on before it can be elaborated by one.
+
+ procedure Initialize_Components (G : Library_Graph);
+ pragma Inline (Initialize_Components);
+ -- Initialize on the initial call or re-initialize on subsequent calls
+ -- all components of library graph G.
+
+ function Is_Elaborable_Vertex
+ (G : Library_Graph;
+ LGV_Id : Library_Graph_Vertex_Id;
+ Predecessors : Natural) return Boolean;
+ pragma Inline (Is_Elaborable_Vertex);
+ -- Determine whether vertex LGV_Id of library graph G can be elaborated
+ -- given that it meets number of predecessors Predecessors.
+
+ function Is_Existing_Predecessor_Successor_Relation
+ (G : Library_Graph;
+ Rel : Predecessor_Successor_Relation) return Boolean;
+ pragma Inline (Is_Existing_Predecessor_Successor_Relation);
+ -- Determine whether a predecessor vertex and a successor vertex
+ -- desctibed by relation Rel are already related in library graph G.
+
+ procedure Set_Component_Attributes
+ (G : Library_Graph;
+ Comp : Component_Id;
+ Val : Component_Attributes);
+ pragma Inline (Set_Component_Attributes);
+ -- Set the attributes of component Comp of library graph G to value Val
+
+ procedure Set_Corresponding_Vertex
+ (G : Library_Graph;
+ U_Id : Unit_Id;
+ Val : Library_Graph_Vertex_Id);
+ pragma Inline (Set_Corresponding_Vertex);
+ -- Associate vertex Val of library graph G with unit U_Id
+
+ procedure Set_Is_Existing_Predecessor_Successor_Relation
+ (G : Library_Graph;
+ Rel : Predecessor_Successor_Relation;
+ Val : Boolean := True);
+ pragma Inline (Set_Is_Existing_Predecessor_Successor_Relation);
+ -- Mark a a predecessor vertex and a successor vertex desctibed by
+ -- relation Rel as already related depending on value Val.
+
+ procedure Set_LGE_Attributes
+ (G : Library_Graph;
+ LGE_Id : Library_Graph_Edge_Id;
+ Val : Library_Graph_Edge_Attributes);
+ pragma Inline (Set_LGE_Attributes);
+ -- Set the attributes of edge LGE_Id of library graph G to value Val
+
+ procedure Set_LGV_Attributes
+ (G : Library_Graph;
+ LGV_Id : Library_Graph_Vertex_Id;
+ Val : Library_Graph_Vertex_Attributes);
+ pragma Inline (Set_LGV_Attributes);
+ -- Set the attributes of vertex LGV_Id of library graph G to value Val
+
+ procedure Update_Pending_Predecessors_Of_Components (G : Library_Graph);
+ pragma Inline (Update_Pending_Predecessors_Of_Components);
+ -- Update the number of pending predecessors all components of library
+ -- graph G must wait on before they can be elaborated.
+
+ procedure Update_Pending_Predecessors_Of_Components
+ (G : Library_Graph;
+ LGE_Id : Library_Graph_Edge_Id);
+ pragma Inline (Update_Pending_Predecessors_Of_Components);
+ -- Update the number of pending predecessors the component of edge
+ -- LGE_Is's successor vertex of library graph G must wait on before
+ -- it can be elaborated.
+
+ -------------------------------
+ -- Add_Body_Before_Spec_Edge --
+ -------------------------------
+
+ procedure Add_Body_Before_Spec_Edge
+ (G : Library_Graph;
+ LGV_Id : Library_Graph_Vertex_Id;
+ Edges : EL.Doubly_Linked_List)
+ is
+ LGE_Id : Library_Graph_Edge_Id;
+
+ begin
+ pragma Assert (Present (G));
+ pragma Assert (Present (LGV_Id));
+ pragma Assert (EL.Present (Edges));
+
+ -- A vertex requires a special Body_Before_Spec edge to its
+ -- Corresponging_Item when it either denotes a
+ --
+ -- * Body that completes a previous spec
+ --
+ -- * Spec with a completing body
+ --
+ -- The edge creates an intentional circularity between the spec and
+ -- body in order to emulate a library unit, and guarantees that both
+ -- will appear in the same component.
+ --
+ -- Due to the structure of the library graph, either the spec or
+ -- the body may be visited first, yet Corresponding_Item will still
+ -- attempt to create the Body_Before_Spec edge. This is OK because
+ -- successor and predecessor are kept consistent in both cases, and
+ -- Add_Edge_With_Return will prevent the creation of the second edge.
+
+ -- Assume that that no Body_Before_Spec is necessary
+
+ LGE_Id := No_Library_Graph_Edge;
+
+ -- A body that completes a previous spec
+
+ if Is_Body_With_Spec (G, LGV_Id) then
+ LGE_Id :=
+ Add_Edge_With_Return
+ (G => G,
+ Pred => LGV_Id, -- body
+ Succ => Corresponding_Item (G, LGV_Id), -- spec
+ Kind => Body_Before_Spec_Edge);
+
+ -- A spec with a completing body
+
+ elsif Is_Spec_With_Body (G, LGV_Id) then
+ LGE_Id :=
+ Add_Edge_With_Return
+ (G => G,
+ Pred => Corresponding_Item (G, LGV_Id), -- body
+ Succ => LGV_Id, -- spec
+ Kind => Body_Before_Spec_Edge);
+ end if;
+
+ if Present (LGE_Id) then
+ EL.Append (Edges, LGE_Id);
+ end if;
+ end Add_Body_Before_Spec_Edge;
+
+ --------------------------------
+ -- Add_Body_Before_Spec_Edges --
+ --------------------------------
+
+ procedure Add_Body_Before_Spec_Edges
+ (G : Library_Graph;
+ Edges : EL.Doubly_Linked_List)
+ is
+ Iter : Elaborable_Units_Iterator;
+ LGV_Id : Library_Graph_Vertex_Id;
+ U_Id : Unit_Id;
+
+ begin
+ pragma Assert (Present (G));
+ pragma Assert (EL.Present (Edges));
+
+ Iter := Iterate_Elaborable_Units;
+ while Has_Next (Iter) loop
+ Next (Iter, U_Id);
+
+ LGV_Id := Corresponding_Vertex (G, U_Id);
+ pragma Assert (Present (LGV_Id));
+
+ Add_Body_Before_Spec_Edge (G, LGV_Id, Edges);
+ end loop;
+ end Add_Body_Before_Spec_Edges;
+
+ --------------
+ -- Add_Edge --
+ --------------
+
+ procedure Add_Edge
+ (G : Library_Graph;
+ Pred : Library_Graph_Vertex_Id;
+ Succ : Library_Graph_Vertex_Id;
+ Kind : Library_Graph_Edge_Kind)
+ is
+ LGE_Id : Library_Graph_Edge_Id;
+ pragma Unreferenced (LGE_Id);
+
+ begin
+ pragma Assert (Present (G));
+ pragma Assert (Present (Pred));
+ pragma Assert (Present (Succ));
+ pragma Assert (Kind /= No_Edge);
+
+ LGE_Id :=
+ Add_Edge_With_Return
+ (G => G,
+ Pred => Pred,
+ Succ => Succ,
+ Kind => Kind);
+ end Add_Edge;
+
+ --------------------------
+ -- Add_Edge_With_Return --
+ --------------------------
+
+ function Add_Edge_With_Return
+ (G : Library_Graph;
+ Pred : Library_Graph_Vertex_Id;
+ Succ : Library_Graph_Vertex_Id;
+ Kind : Library_Graph_Edge_Kind) return Library_Graph_Edge_Id
+ is
+ pragma Assert (Present (G));
+ pragma Assert (Present (Pred));
+ pragma Assert (Present (Succ));
+ pragma Assert (Kind /= No_Edge);
+
+ Rel : constant Predecessor_Successor_Relation :=
+ (Predecessor => Pred,
+ Successor => Succ);
+
+ LGE_Id : Library_Graph_Edge_Id;
+
+ begin
+ -- Nothing to do when the predecessor and successor are already
+ -- related by an edge.
+
+ if Is_Existing_Predecessor_Successor_Relation (G, Rel) then
+ return No_Library_Graph_Edge;
+ end if;
+
+ LGE_Id := Sequence_Next_LGE_Id;
+
+ -- Add the edge to the underlying graph. Note that the predecessor
+ -- is the source of the edge because it will later need to notify
+ -- all its successors that it has been elaborated.
+
+ DG.Add_Edge
+ (G => G.Graph,
+ E => LGE_Id,
+ Source => Pred,
+ Destination => Succ);
+
+ -- Construct and save the attributes of the edge
+
+ Set_LGE_Attributes
+ (G => G,
+ LGE_Id => LGE_Id,
+ Val => (Kind => Kind));
+
+ -- Mark the predecessor and successor as related by the new edge.
+ -- This prevents all further attempts to link the same predecessor
+ -- and successor.
+
+ Set_Is_Existing_Predecessor_Successor_Relation (G, Rel);
+
+ -- Update the number of pending predecessors the successor must wait
+ -- on before it is elaborated.
+
+ Increment_Pending_Predecessors (G, Succ);
+
+ -- Update the edge statistics
+
+ Increment_Library_Graph_Edge_Count (G, Kind);
+
+ return LGE_Id;
+ end Add_Edge_With_Return;
+
+ ----------------
+ -- Add_Vertex --
+ ----------------
+
+ procedure Add_Vertex
+ (G : Library_Graph;
+ U_Id : Unit_Id)
+ is
+ LGV_Id : Library_Graph_Vertex_Id;
+
+ begin
+ pragma Assert (Present (G));
+ pragma Assert (Present (U_Id));
+
+ -- Nothing to do when the unit already has a vertex
+
+ if Present (Corresponding_Vertex (G, U_Id)) then
+ return;
+ end if;
+
+ LGV_Id := Sequence_Next_LGV_Id;
+
+ -- Add the vertex to the underlying graph
+
+ DG.Add_Vertex (G.Graph, LGV_Id);
+
+ -- Construct and save the attributes of the vertex
+
+ Set_LGV_Attributes
+ (G => G,
+ LGV_Id => LGV_Id,
+ Val => (Corresponding_Item => No_Library_Graph_Vertex,
+ In_Elaboration_Order => False,
+ Pending_Predecessors => 0,
+ Unit => U_Id));
+
+ -- Associate the unit with its corresponding vertex
+
+ Set_Corresponding_Vertex (G, U_Id, LGV_Id);
+ end Add_Vertex;
+
+ ---------------
+ -- Component --
+ ---------------
+
+ function Component
+ (G : Library_Graph;
+ LGV_Id : Library_Graph_Vertex_Id) return Component_Id
+ is
+ begin
+ pragma Assert (Present (G));
+ pragma Assert (Present (LGV_Id));
+
+ return DG.Component (G.Graph, LGV_Id);
+ end Component;
+
+ ------------------------
+ -- Corresponding_Item --
+ ------------------------
+
+ function Corresponding_Item
+ (G : Library_Graph;
+ LGV_Id : Library_Graph_Vertex_Id) return Library_Graph_Vertex_Id
+ is
+ begin
+ pragma Assert (Present (G));
+ pragma Assert (Present (LGV_Id));
+
+ return Get_LGV_Attributes (G, LGV_Id).Corresponding_Item;
+ end Corresponding_Item;
+
+ --------------------------
+ -- Corresponding_Vertex --
+ --------------------------
+
+ function Corresponding_Vertex
+ (G : Library_Graph;
+ U_Id : Unit_Id) return Library_Graph_Vertex_Id
+ is
+ begin
+ pragma Assert (Present (G));
+ pragma Assert (Present (U_Id));
+
+ return UV.Get (G.Unit_To_Vertex, U_Id);
+ end Corresponding_Vertex;
+
+ ------------
+ -- Create --
+ ------------
+
+ function Create
+ (Initial_Vertices : Positive;
+ Initial_Edges : Positive) return Library_Graph
+ is
+ G : constant Library_Graph := new Library_Graph_Attributes;
+
+ begin
+ G.Component_Attributes := CA.Create (Initial_Vertices);
+ G.Edge_Attributes := EA.Create (Initial_Edges);
+ G.Graph :=
+ DG.Create
+ (Initial_Vertices => Initial_Vertices,
+ Initial_Edges => Initial_Edges);
+ G.Relations := PS.Create (Initial_Edges);
+ G.Unit_To_Vertex := UV.Create (Initial_Vertices);
+ G.Vertex_Attributes := VA.Create (Initial_Vertices);
+
+ return G;
+ end Create;
+
+ ----------------------------------------
+ -- Decrement_Library_Graph_Edge_Count --
+ ----------------------------------------
+
+ procedure Decrement_Library_Graph_Edge_Count
+ (G : Library_Graph;
+ Kind : Library_Graph_Edge_Kind)
+ is
+ pragma Assert (Present (G));
+
+ Count : Natural renames G.Counts (Kind);
+
+ begin
+ Count := Count - 1;
+ end Decrement_Library_Graph_Edge_Count;
+
+ ------------------------------------
+ -- Decrement_Pending_Predecessors --
+ ------------------------------------
+
+ procedure Decrement_Pending_Predecessors
+ (G : Library_Graph;
+ Comp : Component_Id)
+ is
+ Attrs : Component_Attributes;
+
+ begin
+ pragma Assert (Present (G));
+ pragma Assert (Present (Comp));
+
+ Attrs := Get_Component_Attributes (G, Comp);
+ Attrs.Pending_Predecessors := Attrs.Pending_Predecessors - 1;
+ Set_Component_Attributes (G, Comp, Attrs);
+ end Decrement_Pending_Predecessors;
+
+ ------------------------------------
+ -- Decrement_Pending_Predecessors --
+ ------------------------------------
+
+ procedure Decrement_Pending_Predecessors
+ (G : Library_Graph;
+ LGV_Id : Library_Graph_Vertex_Id)
+ is
+ Attrs : Library_Graph_Vertex_Attributes;
+
+ begin
+ pragma Assert (Present (G));
+ pragma Assert (Present (LGV_Id));
+
+ Attrs := Get_LGV_Attributes (G, LGV_Id);
+ Attrs.Pending_Predecessors := Attrs.Pending_Predecessors - 1;
+ Set_LGV_Attributes (G, LGV_Id, Attrs);
+ end Decrement_Pending_Predecessors;
+
+ -----------------------------------
+ -- Delete_Body_Before_Spec_Edges --
+ -----------------------------------
+
+ procedure Delete_Body_Before_Spec_Edges
+ (G : Library_Graph;
+ Edges : EL.Doubly_Linked_List)
+ is
+ Iter : EL.Iterator;
+ LGE_Id : Library_Graph_Edge_Id;
+
+ begin
+ pragma Assert (Present (G));
+ pragma Assert (EL.Present (Edges));
+
+ Iter := EL.Iterate (Edges);
+ while EL.Has_Next (Iter) loop
+ EL.Next (Iter, LGE_Id);
+ pragma Assert (Present (LGE_Id));
+ pragma Assert (Kind (G, LGE_Id) = Body_Before_Spec_Edge);
+
+ Delete_Edge (G, LGE_Id);
+ end loop;
+ end Delete_Body_Before_Spec_Edges;
+
+ -----------------
+ -- Delete_Edge --
+ -----------------
+
+ procedure Delete_Edge
+ (G : Library_Graph;
+ LGE_Id : Library_Graph_Edge_Id)
+ is
+ pragma Assert (Present (G));
+ pragma Assert (Present (LGE_Id));
+
+ Pred : constant Library_Graph_Vertex_Id := Predecessor (G, LGE_Id);
+ Succ : constant Library_Graph_Vertex_Id := Successor (G, LGE_Id);
+
+ pragma Assert (Present (Pred));
+ pragma Assert (Present (Succ));
+
+ Rel : constant Predecessor_Successor_Relation :=
+ (Predecessor => Pred,
+ Successor => Succ);
+
+ begin
+ -- Update the edge statistics
+
+ Decrement_Library_Graph_Edge_Count (G, Kind (G, LGE_Id));
+
+ -- Update the number of pending predecessors the successor must wait
+ -- on before it is elaborated.
+
+ Decrement_Pending_Predecessors (G, Succ);
+
+ -- Delete the link between the predecessor and successor. This allows
+ -- for further attempts to link the same predecessor and successor.
+
+ PS.Delete (G.Relations, Rel);
+
+ -- Delete the attributes of the edge
+
+ EA.Delete (G.Edge_Attributes, LGE_Id);
+
+ -- Delete the edge from the underlying graph
+
+ DG.Delete_Edge (G.Graph, LGE_Id);
+ end Delete_Edge;
+
+ -------------
+ -- Destroy --
+ -------------
+
+ procedure Destroy (G : in out Library_Graph) is
+ begin
+ pragma Assert (Present (G));
+
+ CA.Destroy (G.Component_Attributes);
+ EA.Destroy (G.Edge_Attributes);
+ DG.Destroy (G.Graph);
+ PS.Destroy (G.Relations);
+ UV.Destroy (G.Unit_To_Vertex);
+ VA.Destroy (G.Vertex_Attributes);
+
+ Free (G);
+ end Destroy;
+
+ ----------------------------------
+ -- Destroy_Component_Attributes --
+ ----------------------------------
+
+ procedure Destroy_Component_Attributes
+ (Attrs : in out Component_Attributes)
+ is
+ pragma Unreferenced (Attrs);
+ begin
+ null;
+ end Destroy_Component_Attributes;
+
+ --------------------------------
+ -- Destroy_Library_Graph_Edge --
+ --------------------------------
+
+ procedure Destroy_Library_Graph_Edge
+ (LGE_Id : in out Library_Graph_Edge_Id)
+ is
+ pragma Unreferenced (LGE_Id);
+ begin
+ null;
+ end Destroy_Library_Graph_Edge;
+
+ -------------------------------------------
+ -- Destroy_Library_Graph_Edge_Attributes --
+ -------------------------------------------
+
+ procedure Destroy_Library_Graph_Edge_Attributes
+ (Attrs : in out Library_Graph_Edge_Attributes)
+ is
+ pragma Unreferenced (Attrs);
+ begin
+ null;
+ end Destroy_Library_Graph_Edge_Attributes;
+
+ ----------------------------------
+ -- Destroy_Library_Graph_Vertex --
+ ----------------------------------
+
+ procedure Destroy_Library_Graph_Vertex
+ (LGV_Id : in out Library_Graph_Vertex_Id)
+ is
+ pragma Unreferenced (LGV_Id);
+ begin
+ null;
+ end Destroy_Library_Graph_Vertex;
+
+ ---------------------------------------------
+ -- Destroy_Library_Graph_Vertex_Attributes --
+ ---------------------------------------------
+
+ procedure Destroy_Library_Graph_Vertex_Attributes
+ (Attrs : in out Library_Graph_Vertex_Attributes)
+ is
+ pragma Unreferenced (Attrs);
+ begin
+ null;
+ end Destroy_Library_Graph_Vertex_Attributes;
+
+ ---------------------
+ -- Find_Components --
+ ---------------------
+
+ procedure Find_Components (G : Library_Graph) is
+ Edges : EL.Doubly_Linked_List;
+
+ begin
+ pragma Assert (Present (G));
+
+ -- Initialize or reinitialize the components of the graph
+
+ Initialize_Components (G);
+
+ -- Create a set of special edges that link a predecessor body with a
+ -- successor spec. This is an illegal dependency, however using such
+ -- edges eliminates the need to create yet another graph, where both
+ -- spec and body are collapsed into a single vertex.
+
+ Edges := EL.Create;
+ Add_Body_Before_Spec_Edges (G, Edges);
+
+ DG.Find_Components (G.Graph);
+
+ -- Remove the special edges that link a predecessor body with a
+ -- successor spec because they cause unresolvable circularities.
+
+ Delete_Body_Before_Spec_Edges (G, Edges);
+ EL.Destroy (Edges);
+
+ -- Update the number of predecessors various components must wait on
+ -- before they can be elaborated.
+
+ Update_Pending_Predecessors_Of_Components (G);
+ end Find_Components;
+
+ ------------------------------
+ -- Get_Component_Attributes --
+ ------------------------------
+
+ function Get_Component_Attributes
+ (G : Library_Graph;
+ Comp : Component_Id) return Component_Attributes
+ is
+ begin
+ pragma Assert (Present (G));
+ pragma Assert (Present (Comp));
+
+ return CA.Get (G.Component_Attributes, Comp);
+ end Get_Component_Attributes;
+
+ ------------------------
+ -- Get_LGE_Attributes --
+ ------------------------
+
+ function Get_LGE_Attributes
+ (G : Library_Graph;
+ LGE_Id : Library_Graph_Edge_Id)
+ return Library_Graph_Edge_Attributes
+ is
+ begin
+ pragma Assert (Present (G));
+ pragma Assert (Present (LGE_Id));
+
+ return EA.Get (G.Edge_Attributes, LGE_Id);
+ end Get_LGE_Attributes;
+
+ ------------------------
+ -- Get_LGV_Attributes --
+ ------------------------
+
+ function Get_LGV_Attributes
+ (G : Library_Graph;
+ LGV_Id : Library_Graph_Vertex_Id)
+ return Library_Graph_Vertex_Attributes
+ is
+ begin
+ pragma Assert (Present (G));
+ pragma Assert (Present (LGV_Id));
+
+ return VA.Get (G.Vertex_Attributes, LGV_Id);
+ end Get_LGV_Attributes;
+
+ ------------------------
+ -- Has_Elaborate_Body --
+ ------------------------
+
+ function Has_Elaborate_Body
+ (G : Library_Graph;
+ LGV_Id : Library_Graph_Vertex_Id) return Boolean
+ is
+ pragma Assert (Present (G));
+ pragma Assert (Present (LGV_Id));
+
+ U_Id : constant Unit_Id := Unit (G, LGV_Id);
+
+ pragma Assert (Present (U_Id));
+
+ U_Rec : Unit_Record renames ALI.Units.Table (U_Id);
+
+ begin
+ return U_Rec.Elaborate_Body;
+ end Has_Elaborate_Body;
+
+ --------------
+ -- Has_Next --
+ --------------
+
+ function Has_Next (Iter : All_Edge_Iterator) return Boolean is
+ begin
+ return DG.Has_Next (DG.All_Edge_Iterator (Iter));
+ end Has_Next;
+
+ --------------
+ -- Has_Next --
+ --------------
+
+ function Has_Next (Iter : All_Vertex_Iterator) return Boolean is
+ begin
+ return DG.Has_Next (DG.All_Vertex_Iterator (Iter));
+ end Has_Next;
+
+ --------------
+ -- Has_Next --
+ --------------
+
+ function Has_Next (Iter : Component_Iterator) return Boolean is
+ begin
+ return DG.Has_Next (DG.Component_Iterator (Iter));
+ end Has_Next;
+
+ --------------
+ -- Has_Next --
+ --------------
+
+ function Has_Next (Iter : Component_Vertex_Iterator) return Boolean is
+ begin
+ return DG.Has_Next (DG.Component_Vertex_Iterator (Iter));
+ end Has_Next;
+
+ --------------
+ -- Has_Next --
+ --------------
+
+ function Has_Next (Iter : Edges_To_Successors_Iterator) return Boolean is
+ begin
+ return DG.Has_Next (DG.Outgoing_Edge_Iterator (Iter));
+ end Has_Next;
+
+ -----------------------------------------
+ -- Hash_Predecessor_Successor_Relation --
+ -----------------------------------------
+
+ function Hash_Predecessor_Successor_Relation
+ (Rel : Predecessor_Successor_Relation) return Bucket_Range_Type
+ is
+ begin
+ pragma Assert (Present (Rel.Predecessor));
+ pragma Assert (Present (Rel.Successor));
+
+ return
+ Hash_Two_Keys
+ (Bucket_Range_Type (Rel.Predecessor),
+ Bucket_Range_Type (Rel.Successor));
+ end Hash_Predecessor_Successor_Relation;
+
+ --------------------------
+ -- In_Elaboration_Order --
+ --------------------------
+
+ function In_Elaboration_Order
+ (G : Library_Graph;
+ LGV_Id : Library_Graph_Vertex_Id) return Boolean
+ is
+ begin
+ pragma Assert (Present (G));
+ pragma Assert (Present (LGV_Id));
+
+ return Get_LGV_Attributes (G, LGV_Id).In_Elaboration_Order;
+ end In_Elaboration_Order;
+
+ ----------------------------------------
+ -- Increment_Library_Graph_Edge_Count --
+ ----------------------------------------
+
+ procedure Increment_Library_Graph_Edge_Count
+ (G : Library_Graph;
+ Kind : Library_Graph_Edge_Kind)
+ is
+ pragma Assert (Present (G));
+
+ Count : Natural renames G.Counts (Kind);
+
+ begin
+ Count := Count + 1;
+ end Increment_Library_Graph_Edge_Count;
+
+ ------------------------------------
+ -- Increment_Pending_Predecessors --
+ ------------------------------------
+
+ procedure Increment_Pending_Predecessors
+ (G : Library_Graph;
+ Comp : Component_Id)
+ is
+ Attrs : Component_Attributes;
+
+ begin
+ pragma Assert (Present (G));
+ pragma Assert (Present (Comp));
+
+ Attrs := Get_Component_Attributes (G, Comp);
+ Attrs.Pending_Predecessors := Attrs.Pending_Predecessors + 1;
+ Set_Component_Attributes (G, Comp, Attrs);
+ end Increment_Pending_Predecessors;
+
+ ------------------------------------
+ -- Increment_Pending_Predecessors --
+ ------------------------------------
+
+ procedure Increment_Pending_Predecessors
+ (G : Library_Graph;
+ LGV_Id : Library_Graph_Vertex_Id)
+ is
+ Attrs : Library_Graph_Vertex_Attributes;
+
+ begin
+ pragma Assert (Present (G));
+ pragma Assert (Present (LGV_Id));
+
+ Attrs := Get_LGV_Attributes (G, LGV_Id);
+ Attrs.Pending_Predecessors := Attrs.Pending_Predecessors + 1;
+ Set_LGV_Attributes (G, LGV_Id, Attrs);
+ end Increment_Pending_Predecessors;
+
+ ---------------------------
+ -- Initialize_Components --
+ ---------------------------
+
+ procedure Initialize_Components (G : Library_Graph) is
+ begin
+ pragma Assert (Present (G));
+
+ -- The graph already contains a set of components. Reinitialize
+ -- them in order to accomodate the new set of components about to
+ -- be computed.
+
+ if Number_Of_Components (G) > 0 then
+ CA.Destroy (G.Component_Attributes);
+ G.Component_Attributes := CA.Create (Number_Of_Vertices (G));
+ end if;
+ end Initialize_Components;
+
+ -------------
+ -- Is_Body --
+ -------------
+
+ function Is_Body
+ (G : Library_Graph;
+ LGV_Id : Library_Graph_Vertex_Id) return Boolean
+ is
+ pragma Assert (Present (G));
+ pragma Assert (Present (LGV_Id));
+
+ U_Id : constant Unit_Id := Unit (G, LGV_Id);
+
+ pragma Assert (Present (U_Id));
+
+ U_Rec : Unit_Record renames ALI.Units.Table (U_Id);
+
+ begin
+ return U_Rec.Utype = Is_Body or else U_Rec.Utype = Is_Body_Only;
+ end Is_Body;
+
+ -----------------------------------------
+ -- Is_Body_Of_Spec_With_Elaborate_Body --
+ -----------------------------------------
+
+ function Is_Body_Of_Spec_With_Elaborate_Body
+ (G : Library_Graph;
+ LGV_Id : Library_Graph_Vertex_Id) return Boolean
+ is
+ Spec_LGV_Id : Library_Graph_Vertex_Id;
+
+ begin
+ pragma Assert (Present (G));
+ pragma Assert (Present (LGV_Id));
+
+ if Is_Body_With_Spec (G, LGV_Id) then
+ Spec_LGV_Id := Proper_Spec (G, LGV_Id);
+ pragma Assert (Present (Spec_LGV_Id));
+
+ return Is_Spec_With_Elaborate_Body (G, Spec_LGV_Id);
+ end if;
+
+ return False;
+ end Is_Body_Of_Spec_With_Elaborate_Body;
+
+ -----------------------
+ -- Is_Body_With_Spec --
+ -----------------------
+
+ function Is_Body_With_Spec
+ (G : Library_Graph;
+ LGV_Id : Library_Graph_Vertex_Id) return Boolean
+ is
+ pragma Assert (Present (G));
+ pragma Assert (Present (LGV_Id));
+
+ U_Id : constant Unit_Id := Unit (G, LGV_Id);
+
+ pragma Assert (Present (U_Id));
+
+ U_Rec : Unit_Record renames ALI.Units.Table (U_Id);
+
+ begin
+ return U_Rec.Utype = Is_Body;
+ end Is_Body_With_Spec;
+
+ -----------------------------
+ -- Is_Elaborable_Component --
+ -----------------------------
+
+ function Is_Elaborable_Component
+ (G : Library_Graph;
+ Comp : Component_Id) return Boolean
+ is
+ begin
+ pragma Assert (Present (G));
+ pragma Assert (Present (Comp));
+
+ -- A component can be elaborated when
+ --
+ -- * The component is no longer wanting on any of its predecessors
+ -- to be elaborated.
+
+ return Pending_Predecessors (G, Comp) = 0;
+ end Is_Elaborable_Component;
+
+ --------------------------
+ -- Is_Elaborable_Vertex --
+ --------------------------
+
+ function Is_Elaborable_Vertex
+ (G : Library_Graph;
+ LGV_Id : Library_Graph_Vertex_Id) return Boolean
+ is
+ Check_LGV_Id : Library_Graph_Vertex_Id;
+
+ begin
+ pragma Assert (Present (G));
+ pragma Assert (Present (LGV_Id));
+
+ Check_LGV_Id := LGV_Id;
+
+ -- A spec-body pair where the spec carries pragma Elaborate_Body must
+ -- be treated as one vertex for elaboration purposes. Use the spec as
+ -- the point of reference for the composite vertex.
+
+ if Is_Body_Of_Spec_With_Elaborate_Body (G, Check_LGV_Id) then
+ Check_LGV_Id := Proper_Spec (G, Check_LGV_Id);
+ pragma Assert (Present (Check_LGV_Id));
+ end if;
+
+ return
+ Is_Elaborable_Vertex
+ (G => G,
+ LGV_Id => Check_LGV_Id,
+ Predecessors => 0);
+ end Is_Elaborable_Vertex;
+
+ --------------------------
+ -- Is_Elaborable_Vertex --
+ --------------------------
+
+ function Is_Elaborable_Vertex
+ (G : Library_Graph;
+ LGV_Id : Library_Graph_Vertex_Id;
+ Predecessors : Natural) return Boolean
+ is
+ pragma Assert (Present (G));
+ pragma Assert (Present (LGV_Id));
+
+ Comp : constant Component_Id := Component (G, LGV_Id);
+
+ pragma Assert (Present (Comp));
+
+ Body_LGV_Id : Library_Graph_Vertex_Id;
+
+ begin
+ -- The vertex must not be re-elaborated once it has been elaborated
+
+ if In_Elaboration_Order (G, LGV_Id) then
+ return False;
+
+ -- The vertex must not be waiting on more precedessors than requested
+ -- to be elaborated.
+
+ elsif Pending_Predecessors (G, LGV_Id) /= Predecessors then
+ return False;
+
+ -- The component where the vertex resides must not be waiting on any
+ -- of its precedessors to be elaborated.
+
+ elsif not Is_Elaborable_Component (G, Comp) then
+ return False;
+
+ -- The vertex denotes a spec with a completing body, and is subject
+ -- to pragma Elaborate_Body. The body must be elaborable for the
+ -- vertex to be elaborated. Account for the sole predecessor of the
+ -- body which is the vertex itself.
+
+ elsif Is_Spec_With_Elaborate_Body (G, LGV_Id) then
+ Body_LGV_Id := Proper_Body (G, LGV_Id);
+ pragma Assert (Present (Body_LGV_Id));
+
+ return
+ Is_Elaborable_Vertex
+ (G => G,
+ LGV_Id => Body_LGV_Id,
+ Predecessors => 1);
+ end if;
+
+ -- At this point it is known that the vertex can be elaborated
+
+ return True;
+ end Is_Elaborable_Vertex;
+
+ ------------------------------------------------
+ -- Is_Existing_Predecessor_Successor_Relation --
+ ------------------------------------------------
+
+ function Is_Existing_Predecessor_Successor_Relation
+ (G : Library_Graph;
+ Rel : Predecessor_Successor_Relation) return Boolean
+ is
+ begin
+ pragma Assert (Present (G));
+ pragma Assert (Present (Rel.Predecessor));
+ pragma Assert (Present (Rel.Successor));
+
+ return PS.Contains (G.Relations, Rel);
+ end Is_Existing_Predecessor_Successor_Relation;
+
+ ----------------------
+ -- Is_Internal_Unit --
+ ----------------------
+
+ function Is_Internal_Unit
+ (G : Library_Graph;
+ LGV_Id : Library_Graph_Vertex_Id) return Boolean
+ is
+ pragma Assert (Present (G));
+ pragma Assert (Present (LGV_Id));
+
+ U_Id : constant Unit_Id := Unit (G, LGV_Id);
+
+ pragma Assert (Present (U_Id));
+
+ begin
+ return Is_Internal_Unit (U_Id);
+ end Is_Internal_Unit;
+
+ ------------------------
+ -- Is_Predefined_Unit --
+ ------------------------
+
+ function Is_Predefined_Unit
+ (G : Library_Graph;
+ LGV_Id : Library_Graph_Vertex_Id) return Boolean
+ is
+ pragma Assert (Present (G));
+ pragma Assert (Present (LGV_Id));
+
+ U_Id : constant Unit_Id := Unit (G, LGV_Id);
+
+ pragma Assert (Present (U_Id));
+
+ begin
+ return Is_Predefined_Unit (U_Id);
+ end Is_Predefined_Unit;
+
+ ---------------------------
+ -- Is_Preelaborated_Unit --
+ ---------------------------
+
+ function Is_Preelaborated_Unit
+ (G : Library_Graph;
+ LGV_Id : Library_Graph_Vertex_Id) return Boolean
+ is
+ pragma Assert (Present (G));
+ pragma Assert (Present (LGV_Id));
+
+ U_Id : constant Unit_Id := Unit (G, LGV_Id);
+
+ pragma Assert (Present (U_Id));
+
+ U_Rec : Unit_Record renames ALI.Units.Table (U_Id);
+
+ begin
+ return U_Rec.Preelab or else U_Rec.Pure;
+ end Is_Preelaborated_Unit;
+
+ -------------
+ -- Is_Spec --
+ -------------
+
+ function Is_Spec
+ (G : Library_Graph;
+ LGV_Id : Library_Graph_Vertex_Id) return Boolean
+ is
+ pragma Assert (Present (G));
+ pragma Assert (Present (LGV_Id));
+
+ U_Id : constant Unit_Id := Unit (G, LGV_Id);
+
+ pragma Assert (Present (U_Id));
+
+ U_Rec : Unit_Record renames ALI.Units.Table (U_Id);
+
+ begin
+ return U_Rec.Utype = Is_Spec or else U_Rec.Utype = Is_Spec_Only;
+ end Is_Spec;
+
+ -----------------------
+ -- Is_Spec_With_Body --
+ -----------------------
+
+ function Is_Spec_With_Body
+ (G : Library_Graph;
+ LGV_Id : Library_Graph_Vertex_Id) return Boolean
+ is
+ pragma Assert (Present (G));
+ pragma Assert (Present (LGV_Id));
+
+ U_Id : constant Unit_Id := Unit (G, LGV_Id);
+
+ pragma Assert (Present (U_Id));
+
+ U_Rec : Unit_Record renames ALI.Units.Table (U_Id);
+
+ begin
+ return U_Rec.Utype = Is_Spec;
+ end Is_Spec_With_Body;
+
+ ---------------------------------
+ -- Is_Spec_With_Elaborate_Body --
+ ---------------------------------
+
+ function Is_Spec_With_Elaborate_Body
+ (G : Library_Graph;
+ LGV_Id : Library_Graph_Vertex_Id) return Boolean
+ is
+ begin
+ pragma Assert (Present (G));
+ pragma Assert (Present (LGV_Id));
+
+ return
+ Is_Spec_With_Body (G, LGV_Id)
+ and then Has_Elaborate_Body (G, LGV_Id);
+ end Is_Spec_With_Elaborate_Body;
+
+ -----------------------
+ -- Iterate_All_Edges --
+ -----------------------
+
+ function Iterate_All_Edges
+ (G : Library_Graph) return All_Edge_Iterator
+ is
+ begin
+ pragma Assert (Present (G));
+
+ return All_Edge_Iterator (DG.Iterate_All_Edges (G.Graph));
+ end Iterate_All_Edges;
+
+ --------------------------
+ -- Iterate_All_Vertices --
+ --------------------------
+
+ function Iterate_All_Vertices
+ (G : Library_Graph) return All_Vertex_Iterator
+ is
+ begin
+ pragma Assert (Present (G));
+
+ return All_Vertex_Iterator (DG.Iterate_All_Vertices (G.Graph));
+ end Iterate_All_Vertices;
+
+ ------------------------
+ -- Iterate_Components --
+ ------------------------
+
+ function Iterate_Components
+ (G : Library_Graph) return Component_Iterator
+ is
+ begin
+ pragma Assert (Present (G));
+
+ return Component_Iterator (DG.Iterate_Components (G.Graph));
+ end Iterate_Components;
+
+ --------------------------------
+ -- Iterate_Component_Vertices --
+ --------------------------------
+
+ function Iterate_Component_Vertices
+ (G : Library_Graph;
+ Comp : Component_Id) return Component_Vertex_Iterator
+ is
+ begin
+ pragma Assert (Present (G));
+ pragma Assert (Present (Comp));
+
+ return
+ Component_Vertex_Iterator
+ (DG.Iterate_Component_Vertices (G.Graph, Comp));
+ end Iterate_Component_Vertices;
+
+ ---------------------------------
+ -- Iterate_Edges_To_Successors --
+ ---------------------------------
+
+ function Iterate_Edges_To_Successors
+ (G : Library_Graph;
+ LGV_Id : Library_Graph_Vertex_Id)
+ return Edges_To_Successors_Iterator
+ is
+ begin
+ pragma Assert (Present (G));
+ pragma Assert (Present (LGV_Id));
+
+ return
+ Edges_To_Successors_Iterator
+ (DG.Iterate_Outgoing_Edges (G.Graph, LGV_Id));
+ end Iterate_Edges_To_Successors;
+
+ ----------
+ -- Kind --
+ ----------
+
+ function Kind
+ (G : Library_Graph;
+ LGE_Id : Library_Graph_Edge_Id) return Library_Graph_Edge_Kind
+ is
+ begin
+ pragma Assert (Present (G));
+ pragma Assert (Present (LGE_Id));
+
+ return Get_LGE_Attributes (G, LGE_Id).Kind;
+ end Kind;
+
+ ------------------------------
+ -- Library_Graph_Edge_Count --
+ ------------------------------
+
+ function Library_Graph_Edge_Count
+ (G : Library_Graph;
+ Kind : Library_Graph_Edge_Kind) return Natural
+ is
+ begin
+ pragma Assert (Present (G));
+
+ return G.Counts (Kind);
+ end Library_Graph_Edge_Count;
+
+ --------------------------------------
+ -- Links_Vertices_In_Same_Component --
+ --------------------------------------
+
+ function Links_Vertices_In_Same_Component
+ (G : Library_Graph;
+ LGE_Id : Library_Graph_Edge_Id) return Boolean
+ is
+ pragma Assert (Present (G));
+ pragma Assert (Present (LGE_Id));
+
+ Pred : constant Library_Graph_Vertex_Id := Predecessor (G, LGE_Id);
+ Succ : constant Library_Graph_Vertex_Id := Successor (G, LGE_Id);
+
+ pragma Assert (Present (Pred));
+ pragma Assert (Present (Succ));
+
+ Pred_Comp : constant Component_Id := Component (G, Pred);
+ Succ_Comp : constant Component_Id := Component (G, Succ);
+
+ pragma Assert (Present (Pred_Comp));
+ pragma Assert (Present (Succ_Comp));
+
+ begin
+ return Pred_Comp = Succ_Comp;
+ end Links_Vertices_In_Same_Component;
+
+ ----------
+ -- Name --
+ ----------
+
+ function Name
+ (G : Library_Graph;
+ LGV_Id : Library_Graph_Vertex_Id) return Unit_Name_Type
+ is
+ pragma Assert (Present (G));
+ pragma Assert (Present (LGV_Id));
+
+ U_Id : constant Unit_Id := Unit (G, LGV_Id);
+
+ pragma Assert (Present (U_Id));
+
+ begin
+ return Name (U_Id);
+ end Name;
+
+ -----------------------
+ -- Needs_Elaboration --
+ -----------------------
+
+ function Needs_Elaboration
+ (G : Library_Graph;
+ LGV_Id : Library_Graph_Vertex_Id) return Boolean
+ is
+ pragma Assert (Present (G));
+ pragma Assert (Present (LGV_Id));
+
+ U_Id : constant Unit_Id := Unit (G, LGV_Id);
+
+ pragma Assert (Present (U_Id));
+
+ begin
+ return Needs_Elaboration (U_Id);
+ end Needs_Elaboration;
+
+ ----------
+ -- Next --
+ ----------
+
+ procedure Next
+ (Iter : in out All_Edge_Iterator;
+ LGE_Id : out Library_Graph_Edge_Id)
+ is
+ begin
+ DG.Next (DG.All_Edge_Iterator (Iter), LGE_Id);
+ end Next;
+
+ ----------
+ -- Next --
+ ----------
+
+ procedure Next
+ (Iter : in out All_Vertex_Iterator;
+ LGV_Id : out Library_Graph_Vertex_Id)
+ is
+ begin
+ DG.Next (DG.All_Vertex_Iterator (Iter), LGV_Id);
+ end Next;
+
+ ----------
+ -- Next --
+ ----------
+
+ procedure Next
+ (Iter : in out Component_Iterator;
+ Comp : out Component_Id)
+ is
+ begin
+ DG.Next (DG.Component_Iterator (Iter), Comp);
+ end Next;
+
+ ----------
+ -- Next --
+ ----------
+
+ procedure Next
+ (Iter : in out Edges_To_Successors_Iterator;
+ LGE_Id : out Library_Graph_Edge_Id)
+ is
+ begin
+ DG.Next (DG.Outgoing_Edge_Iterator (Iter), LGE_Id);
+ end Next;
+
+ ----------
+ -- Next --
+ ----------
+
+ procedure Next
+ (Iter : in out Component_Vertex_Iterator;
+ LGV_Id : out Library_Graph_Vertex_Id)
+ is
+ begin
+ DG.Next (DG.Component_Vertex_Iterator (Iter), LGV_Id);
+ end Next;
+
+ ----------------------------------
+ -- Number_Of_Component_Vertices --
+ ----------------------------------
+
+ function Number_Of_Component_Vertices
+ (G : Library_Graph;
+ Comp : Component_Id) return Natural
+ is
+ begin
+ pragma Assert (Present (G));
+ pragma Assert (Present (Comp));
+
+ return DG.Number_Of_Component_Vertices (G.Graph, Comp);
+ end Number_Of_Component_Vertices;
+
+ --------------------------
+ -- Number_Of_Components --
+ --------------------------
+
+ function Number_Of_Components (G : Library_Graph) return Natural is
+ begin
+ pragma Assert (Present (G));
+
+ return DG.Number_Of_Components (G.Graph);
+ end Number_Of_Components;
+
+ ---------------------
+ -- Number_Of_Edges --
+ ---------------------
+
+ function Number_Of_Edges (G : Library_Graph) return Natural is
+ begin
+ pragma Assert (Present (G));
+
+ return DG.Number_Of_Edges (G.Graph);
+ end Number_Of_Edges;
+
+ -----------------------------------
+ -- Number_Of_Edges_To_Successors --
+ -----------------------------------
+
+ function Number_Of_Edges_To_Successors
+ (G : Library_Graph;
+ LGV_Id : Library_Graph_Vertex_Id) return Natural
+ is
+ begin
+ pragma Assert (Present (G));
+
+ return DG.Number_Of_Outgoing_Edges (G.Graph, LGV_Id);
+ end Number_Of_Edges_To_Successors;
+
+ ------------------------
+ -- Number_Of_Vertices --
+ ------------------------
+
+ function Number_Of_Vertices (G : Library_Graph) return Natural is
+ begin
+ pragma Assert (Present (G));
+
+ return DG.Number_Of_Vertices (G.Graph);
+ end Number_Of_Vertices;
+
+ --------------------------
+ -- Pending_Predecessors --
+ --------------------------
+
+ function Pending_Predecessors
+ (G : Library_Graph;
+ Comp : Component_Id) return Natural
+ is
+ begin
+ pragma Assert (Present (G));
+ pragma Assert (Present (Comp));
+
+ return Get_Component_Attributes (G, Comp).Pending_Predecessors;
+ end Pending_Predecessors;
+
+ --------------------------
+ -- Pending_Predecessors --
+ --------------------------
+
+ function Pending_Predecessors
+ (G : Library_Graph;
+ LGV_Id : Library_Graph_Vertex_Id) return Natural
+ is
+ begin
+ pragma Assert (Present (G));
+ pragma Assert (Present (LGV_Id));
+
+ return Get_LGV_Attributes (G, LGV_Id).Pending_Predecessors;
+ end Pending_Predecessors;
+
+ -----------------
+ -- Predecessor --
+ -----------------
+
+ function Predecessor
+ (G : Library_Graph;
+ LGE_Id : Library_Graph_Edge_Id) return Library_Graph_Vertex_Id
+ is
+ begin
+ pragma Assert (Present (G));
+ pragma Assert (Present (LGE_Id));
+
+ return DG.Source_Vertex (G.Graph, LGE_Id);
+ end Predecessor;
+
+ -------------
+ -- Present --
+ -------------
+
+ function Present (G : Library_Graph) return Boolean is
+ begin
+ return G /= Nil;
+ end Present;
+
+ -----------------
+ -- Proper_Body --
+ -----------------
+
+ function Proper_Body
+ (G : Library_Graph;
+ LGV_Id : Library_Graph_Vertex_Id) return Library_Graph_Vertex_Id
+ is
+ begin
+ pragma Assert (Present (G));
+ pragma Assert (Present (LGV_Id));
+
+ -- When the vertex denotes a spec with a completing body, return the
+ -- body.
+
+ if Is_Spec_With_Body (G, LGV_Id) then
+ return Corresponding_Item (G, LGV_Id);
+
+ -- Otherwise the vertex must be a body
+
+ else
+ pragma Assert (Is_Body (G, LGV_Id));
+ return LGV_Id;
+ end if;
+ end Proper_Body;
+
+ -----------------
+ -- Proper_Spec --
+ -----------------
+
+ function Proper_Spec
+ (G : Library_Graph;
+ LGV_Id : Library_Graph_Vertex_Id) return Library_Graph_Vertex_Id
+ is
+ begin
+ pragma Assert (Present (G));
+ pragma Assert (Present (LGV_Id));
+
+ -- When the vertex denotes a body that completes a spec, return the
+ -- spec.
+
+ if Is_Body_With_Spec (G, LGV_Id) then
+ return Corresponding_Item (G, LGV_Id);
+
+ -- Otherwise the vertex must denote a spec
+
+ else
+ pragma Assert (Is_Spec (G, LGV_Id));
+ return LGV_Id;
+ end if;
+ end Proper_Spec;
+
+ ------------------------------
+ -- Set_Component_Attributes --
+ ------------------------------
+
+ procedure Set_Component_Attributes
+ (G : Library_Graph;
+ Comp : Component_Id;
+ Val : Component_Attributes)
+ is
+ begin
+ pragma Assert (Present (G));
+ pragma Assert (Present (Comp));
+
+ CA.Put (G.Component_Attributes, Comp, Val);
+ end Set_Component_Attributes;
+
+ ----------------------------
+ -- Set_Corresponding_Item --
+ ----------------------------
+
+ procedure Set_Corresponding_Item
+ (G : Library_Graph;
+ LGV_Id : Library_Graph_Vertex_Id;
+ Val : Library_Graph_Vertex_Id)
+ is
+ Attrs : Library_Graph_Vertex_Attributes;
+
+ begin
+ pragma Assert (Present (G));
+ pragma Assert (Present (LGV_Id));
+
+ Attrs := Get_LGV_Attributes (G, LGV_Id);
+ Attrs.Corresponding_Item := Val;
+ Set_LGV_Attributes (G, LGV_Id, Attrs);
+ end Set_Corresponding_Item;
+
+ ------------------------------
+ -- Set_Corresponding_Vertex --
+ ------------------------------
+
+ procedure Set_Corresponding_Vertex
+ (G : Library_Graph;
+ U_Id : Unit_Id;
+ Val : Library_Graph_Vertex_Id)
+ is
+ begin
+ pragma Assert (Present (G));
+ pragma Assert (Present (U_Id));
+
+ UV.Put (G.Unit_To_Vertex, U_Id, Val);
+ end Set_Corresponding_Vertex;
+
+ ------------------------------
+ -- Set_In_Elaboration_Order --
+ ------------------------------
+
+ procedure Set_In_Elaboration_Order
+ (G : Library_Graph;
+ LGV_Id : Library_Graph_Vertex_Id;
+ Val : Boolean := True)
+ is
+ Attrs : Library_Graph_Vertex_Attributes;
+
+ begin
+ pragma Assert (Present (G));
+ pragma Assert (Present (LGV_Id));
+
+ Attrs := Get_LGV_Attributes (G, LGV_Id);
+ Attrs.In_Elaboration_Order := Val;
+ Set_LGV_Attributes (G, LGV_Id, Attrs);
+ end Set_In_Elaboration_Order;
+
+ ----------------------------------------------------
+ -- Set_Is_Existing_Predecessor_Successor_Relation --
+ ----------------------------------------------------
+
+ procedure Set_Is_Existing_Predecessor_Successor_Relation
+ (G : Library_Graph;
+ Rel : Predecessor_Successor_Relation;
+ Val : Boolean := True)
+ is
+ begin
+ pragma Assert (Present (G));
+ pragma Assert (Present (Rel.Predecessor));
+ pragma Assert (Present (Rel.Successor));
+
+ if Val then
+ PS.Insert (G.Relations, Rel);
+ else
+ PS.Delete (G.Relations, Rel);
+ end if;
+ end Set_Is_Existing_Predecessor_Successor_Relation;
+
+ ------------------------
+ -- Set_LGE_Attributes --
+ ------------------------
+
+ procedure Set_LGE_Attributes
+ (G : Library_Graph;
+ LGE_Id : Library_Graph_Edge_Id;
+ Val : Library_Graph_Edge_Attributes)
+ is
+ begin
+ pragma Assert (Present (G));
+ pragma Assert (Present (LGE_Id));
+
+ EA.Put (G.Edge_Attributes, LGE_Id, Val);
+ end Set_LGE_Attributes;
+
+ ------------------------
+ -- Set_LGV_Attributes --
+ ------------------------
+
+ procedure Set_LGV_Attributes
+ (G : Library_Graph;
+ LGV_Id : Library_Graph_Vertex_Id;
+ Val : Library_Graph_Vertex_Attributes)
+ is
+ begin
+ pragma Assert (Present (G));
+ pragma Assert (Present (LGV_Id));
+
+ VA.Put (G.Vertex_Attributes, LGV_Id, Val);
+ end Set_LGV_Attributes;
+
+ ---------------
+ -- Successor --
+ ---------------
+
+ function Successor
+ (G : Library_Graph;
+ LGE_Id : Library_Graph_Edge_Id) return Library_Graph_Vertex_Id
+ is
+ begin
+ pragma Assert (Present (G));
+ pragma Assert (Present (LGE_Id));
+
+ return DG.Destination_Vertex (G.Graph, LGE_Id);
+ end Successor;
+
+ ----------
+ -- Unit --
+ ----------
+
+ function Unit
+ (G : Library_Graph;
+ LGV_Id : Library_Graph_Vertex_Id) return Unit_Id
+ is
+ begin
+ pragma Assert (Present (G));
+ pragma Assert (Present (LGV_Id));
+
+ return Get_LGV_Attributes (G, LGV_Id).Unit;
+ end Unit;
+
+ -----------------------------------------------
+ -- Update_Pending_Predecessors_Of_Components --
+ -----------------------------------------------
+
+ procedure Update_Pending_Predecessors_Of_Components
+ (G : Library_Graph)
+ is
+ Iter : All_Edge_Iterator;
+ LGE_Id : Library_Graph_Edge_Id;
+
+ begin
+ pragma Assert (Present (G));
+
+ Iter := Iterate_All_Edges (G);
+ while Has_Next (Iter) loop
+ Next (Iter, LGE_Id);
+ pragma Assert (Present (LGE_Id));
+
+ Update_Pending_Predecessors_Of_Components (G, LGE_Id);
+ end loop;
+ end Update_Pending_Predecessors_Of_Components;
+
+ -----------------------------------------------
+ -- Update_Pending_Predecessors_Of_Components --
+ -----------------------------------------------
+
+ procedure Update_Pending_Predecessors_Of_Components
+ (G : Library_Graph;
+ LGE_Id : Library_Graph_Edge_Id)
+ is
+ pragma Assert (Present (G));
+ pragma Assert (Present (LGE_Id));
+
+ Pred : constant Library_Graph_Vertex_Id := Predecessor (G, LGE_Id);
+ Succ : constant Library_Graph_Vertex_Id := Successor (G, LGE_Id);
+
+ pragma Assert (Present (Pred));
+ pragma Assert (Present (Succ));
+
+ Pred_Comp : constant Component_Id := Component (G, Pred);
+ Succ_Comp : constant Component_Id := Component (G, Succ);
+
+ pragma Assert (Present (Pred_Comp));
+ pragma Assert (Present (Succ_Comp));
+
+ begin
+ -- The edge links a successor and a predecessor coming from two
+ -- different SCCs. This indicates that the SCC of the successor
+ -- must wait on another predecessor until it can be elaborated.
+
+ if Pred_Comp /= Succ_Comp then
+ Increment_Pending_Predecessors (G, Succ_Comp);
+ end if;
+ end Update_Pending_Predecessors_Of_Components;
+ end Library_Graphs;
+
+ -------------
+ -- Present --
+ -------------
+
+ function Present (IGE_Id : Invocation_Graph_Edge_Id) return Boolean is
+ begin
+ return IGE_Id /= No_Invocation_Graph_Edge;
+ end Present;
+
+ -------------
+ -- Present --
+ -------------
+
+ function Present (IGV_Id : Invocation_Graph_Vertex_Id) return Boolean is
+ begin
+ return IGV_Id /= No_Invocation_Graph_Vertex;
+ end Present;
+
+ -------------
+ -- Present --
+ -------------
+
+ function Present (LGE_Id : Library_Graph_Edge_Id) return Boolean is
+ begin
+ return LGE_Id /= No_Library_Graph_Edge;
+ end Present;
+
+ -------------
+ -- Present --
+ -------------
+
+ function Present (LGV_Id : Library_Graph_Vertex_Id) return Boolean is
+ begin
+ return LGV_Id /= No_Library_Graph_Vertex;
+ end Present;
+
+ --------------------------
+ -- Sequence_Next_IGE_Id --
+ --------------------------
+
+ IGE_Sequencer : Invocation_Graph_Edge_Id := First_Invocation_Graph_Edge;
+ -- The counter for invocation graph edges. Do not directly manipulate its
+ -- value.
+
+ function Sequence_Next_IGE_Id return Invocation_Graph_Edge_Id is
+ IGE_Id : constant Invocation_Graph_Edge_Id := IGE_Sequencer;
+
+ begin
+ IGE_Sequencer := IGE_Sequencer + 1;
+ return IGE_Id;
+ end Sequence_Next_IGE_Id;
+
+ --------------------------
+ -- Sequence_Next_IGV_Id --
+ --------------------------
+
+ IGV_Sequencer : Invocation_Graph_Vertex_Id := First_Invocation_Graph_Vertex;
+ -- The counter for invocation graph vertices. Do not directly manipulate
+ -- its value.
+
+ --------------------------
+ -- Sequence_Next_IGV_Id --
+ --------------------------
+
+ function Sequence_Next_IGV_Id return Invocation_Graph_Vertex_Id is
+ IGV_Id : constant Invocation_Graph_Vertex_Id := IGV_Sequencer;
+
+ begin
+ IGV_Sequencer := IGV_Sequencer + 1;
+ return IGV_Id;
+ end Sequence_Next_IGV_Id;
+
+ --------------------------
+ -- Sequence_Next_LGE_Id --
+ --------------------------
+
+ LGE_Sequencer : Library_Graph_Edge_Id := First_Library_Graph_Edge;
+ -- The counter for library graph edges. Do not directly manipulate its
+ -- value.
+
+ function Sequence_Next_LGE_Id return Library_Graph_Edge_Id is
+ LGE_Id : constant Library_Graph_Edge_Id := LGE_Sequencer;
+
+ begin
+ LGE_Sequencer := LGE_Sequencer + 1;
+ return LGE_Id;
+ end Sequence_Next_LGE_Id;
+
+ --------------------------
+ -- Sequence_Next_LGV_Id --
+ --------------------------
+
+ LGV_Sequencer : Library_Graph_Vertex_Id := First_Library_Graph_Vertex;
+ -- The counter for library graph vertices. Do not directly manipulate its
+ -- value.
+
+ function Sequence_Next_LGV_Id return Library_Graph_Vertex_Id is
+ LGV_Id : constant Library_Graph_Vertex_Id := LGV_Sequencer;
+
+ begin
+ LGV_Sequencer := LGV_Sequencer + 1;
+ return LGV_Id;
+ end Sequence_Next_LGV_Id;
+
+end Bindo.Graphs;
diff --git a/gcc/ada/bindo-graphs.ads b/gcc/ada/bindo-graphs.ads
new file mode 100644
index 0000000..a5dc6ea
--- /dev/null
+++ b/gcc/ada/bindo-graphs.ads
@@ -0,0 +1,1248 @@
+------------------------------------------------------------------------------
+-- --
+-- GNAT COMPILER COMPONENTS --
+-- --
+-- B I N D O . G R A P H S --
+-- --
+-- S p e c --
+-- --
+-- Copyright (C) 2019, 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. See the GNU General Public License --
+-- for more details. You should have received a copy of the GNU General --
+-- Public License distributed with GNAT; see file COPYING3. If not, go to --
+-- http://www.gnu.org/licenses for a complete copy of the license. --
+-- --
+-- GNAT was originally developed by the GNAT team at New York University. --
+-- Extensive contributions were provided by Ada Core Technologies Inc. --
+-- --
+------------------------------------------------------------------------------
+
+-- For full architecture, see unit Bindo.
+
+-- The following unit defines the various graphs used in determining the
+-- elaboration order of units.
+
+with Bindo.Units; use Bindo.Units;
+
+with GNAT; use GNAT;
+with GNAT.Dynamic_HTables; use GNAT.Dynamic_HTables;
+with GNAT.Graphs; use GNAT.Graphs;
+with GNAT.Sets; use GNAT.Sets;
+
+package Bindo.Graphs is
+
+ ---------------------------
+ -- Invocation graph edge --
+ ---------------------------
+
+ -- The following type denotes an invocation graph edge handle
+
+ type Invocation_Graph_Edge_Id is new Natural;
+ No_Invocation_Graph_Edge : constant Invocation_Graph_Edge_Id :=
+ Invocation_Graph_Edge_Id'First;
+ First_Invocation_Graph_Edge : constant Invocation_Graph_Edge_Id :=
+ No_Invocation_Graph_Edge + 1;
+
+ function Hash_Invocation_Graph_Edge
+ (IGE_Id : Invocation_Graph_Edge_Id) return Bucket_Range_Type;
+ pragma Inline (Hash_Invocation_Graph_Edge);
+ -- Obtain the hash value of key IGE_Id
+
+ function Present (IGE_Id : Invocation_Graph_Edge_Id) return Boolean;
+ pragma Inline (Present);
+ -- Determine whether invocation graph edge IGE_Id exists
+
+ ------------------------------
+ -- Invocation graph vertex --
+ ------------------------------
+
+ -- The following type denotes an invocation graph vertex handle
+
+ type Invocation_Graph_Vertex_Id is new Natural;
+ No_Invocation_Graph_Vertex : constant Invocation_Graph_Vertex_Id :=
+ Invocation_Graph_Vertex_Id'First;
+ First_Invocation_Graph_Vertex : constant Invocation_Graph_Vertex_Id :=
+ No_Invocation_Graph_Vertex + 1;
+
+ function Hash_Invocation_Graph_Vertex
+ (IGV_Id : Invocation_Graph_Vertex_Id) return Bucket_Range_Type;
+ pragma Inline (Hash_Invocation_Graph_Vertex);
+ -- Obtain the hash value of key IGV_Id
+
+ function Present (IGV_Id : Invocation_Graph_Vertex_Id) return Boolean;
+ pragma Inline (Present);
+ -- Determine whether invocation graph vertex IGV_Id exists
+
+ ------------------------
+ -- Library graph edge --
+ ------------------------
+
+ -- The following type denotes a library graph edge handle
+
+ type Library_Graph_Edge_Id is new Natural;
+ No_Library_Graph_Edge : constant Library_Graph_Edge_Id :=
+ Library_Graph_Edge_Id'First;
+ First_Library_Graph_Edge : constant Library_Graph_Edge_Id :=
+ No_Library_Graph_Edge + 1;
+
+ function Hash_Library_Graph_Edge
+ (LGE_Id : Library_Graph_Edge_Id) return Bucket_Range_Type;
+ pragma Inline (Hash_Library_Graph_Edge);
+ -- Obtain the hash value of key LGE_Id
+
+ function Present (LGE_Id : Library_Graph_Edge_Id) return Boolean;
+ pragma Inline (Present);
+ -- Determine whether library graph edge LGE_Id exists
+
+ --------------------------
+ -- Library graph vertex --
+ --------------------------
+
+ -- The following type denotes a library graph vertex handle
+
+ type Library_Graph_Vertex_Id is new Natural;
+ No_Library_Graph_Vertex : constant Library_Graph_Vertex_Id :=
+ Library_Graph_Vertex_Id'First;
+ First_Library_Graph_Vertex : constant Library_Graph_Vertex_Id :=
+ No_Library_Graph_Vertex + 1;
+
+ function Hash_Library_Graph_Vertex
+ (LGV_Id : Library_Graph_Vertex_Id) return Bucket_Range_Type;
+ pragma Inline (Hash_Library_Graph_Vertex);
+ -- Obtain the hash value of key LGV_Id
+
+ function Present (LGV_Id : Library_Graph_Vertex_Id) return Boolean;
+ pragma Inline (Present);
+ -- Determine whether library graph vertex LGV_Id exists
+
+ -----------------------
+ -- Invocation_Graphs --
+ -----------------------
+
+ package Invocation_Graphs is
+
+ -----------
+ -- Graph --
+ -----------
+
+ -- The following type denotes an invocation graph handle. Each instance
+ -- must be created using routine Create.
+
+ type Invocation_Graph is private;
+ Nil : constant Invocation_Graph;
+
+ ----------------------
+ -- Graph operations --
+ ----------------------
+
+ procedure Add_Edge
+ (G : Invocation_Graph;
+ Source : Invocation_Graph_Vertex_Id;
+ Target : Invocation_Graph_Vertex_Id;
+ IR_Id : Invocation_Relation_Id);
+ pragma Inline (Add_Edge);
+ -- Create a new edge in invocation graph G with source vertex Source and
+ -- destination vertex Target. IR_Id is the invocation relation the edge
+ -- describes.
+
+ procedure Add_Vertex
+ (G : Invocation_Graph;
+ IC_Id : Invocation_Construct_Id;
+ LGV_Id : Library_Graph_Vertex_Id);
+ pragma Inline (Add_Vertex);
+ -- Create a new vertex in invocation graph G. IC_Id is the invocation
+ -- construct the vertex describes. LGV_Id is the library graph vertex
+ -- where the invocation construct appears.
+
+ function Create
+ (Initial_Vertices : Positive;
+ Initial_Edges : Positive) return Invocation_Graph;
+ pragma Inline (Create);
+ -- Create a new empty graph with vertex capacity Initial_Vertices and
+ -- edge capacity Initial_Edges.
+
+ procedure Destroy (G : in out Invocation_Graph);
+ pragma Inline (Destroy);
+ -- Destroy the contents of invocation graph G, rendering it unusable
+
+ function Present (G : Invocation_Graph) return Boolean;
+ pragma Inline (Present);
+ -- Determine whether invocation graph G exists
+
+ -----------------------
+ -- Vertex attributes --
+ -----------------------
+
+ function Construct
+ (G : Invocation_Graph;
+ IGV_Id : Invocation_Graph_Vertex_Id) return Invocation_Construct_Id;
+ pragma Inline (Construct);
+ -- Obtain the invocation construct vertex IGV_Id of invocation graph G
+ -- describes.
+
+ function Corresponding_Vertex
+ (G : Invocation_Graph;
+ IS_Id : Invocation_Signature_Id) return Invocation_Graph_Vertex_Id;
+ pragma Inline (Corresponding_Vertex);
+ -- Obtain the vertex of invocation graph G that corresponds to signature
+ -- IS_Id.
+
+ function Lib_Vertex
+ (G : Invocation_Graph;
+ IGV_Id : Invocation_Graph_Vertex_Id) return Library_Graph_Vertex_Id;
+ pragma Inline (Lib_Vertex);
+ -- Obtain the library graph vertex where vertex IGV_Id of invocation
+ -- graph appears.
+
+ function Name
+ (G : Invocation_Graph;
+ IGV_Id : Invocation_Graph_Vertex_Id) return Name_Id;
+ pragma Inline (Name);
+ -- Obtain the name of the construct vertex IGV_Id of invocation graph G
+ -- describes.
+
+ ---------------------
+ -- Edge attributes --
+ ---------------------
+
+ function Kind
+ (G : Invocation_Graph;
+ IGE_Id : Invocation_Graph_Edge_Id) return Invocation_Kind;
+ pragma Inline (Kind);
+ -- Obtain the nature of edge IGE_Id of invocation graph G
+
+ function Relation
+ (G : Invocation_Graph;
+ IGE_Id : Invocation_Graph_Edge_Id) return Invocation_Relation_Id;
+ pragma Inline (Relation);
+ -- Obtain the relation edge IGE_Id of invocation graph G describes
+
+ function Target
+ (G : Invocation_Graph;
+ IGE_Id : Invocation_Graph_Edge_Id) return Invocation_Graph_Vertex_Id;
+ pragma Inline (Target);
+ -- Obtain the target vertex edge IGE_Id of invocation graph G designates
+
+ ----------------
+ -- Statistics --
+ ----------------
+
+ function Invocation_Graph_Edge_Count
+ (G : Invocation_Graph;
+ Kind : Invocation_Kind) return Natural;
+ pragma Inline (Invocation_Graph_Edge_Count);
+ -- Obtain the total number of edges of kind Kind in invocation graph G
+
+ function Number_Of_Edges (G : Invocation_Graph) return Natural;
+ pragma Inline (Number_Of_Edges);
+ -- Obtain the total number of edges in invocation graph G
+
+ function Number_Of_Edges_To_Targets
+ (G : Invocation_Graph;
+ IGV_Id : Invocation_Graph_Vertex_Id) return Natural;
+ pragma Inline (Number_Of_Edges_To_Targets);
+ -- Obtain the total number of edges to targets vertex IGV_Id of
+ -- invocation graph G has.
+
+ function Number_Of_Elaboration_Roots
+ (G : Invocation_Graph) return Natural;
+ pragma Inline (Number_Of_Elaboration_Roots);
+ -- Obtain the total number of elaboration roots in invocation graph G
+
+ function Number_Of_Vertices (G : Invocation_Graph) return Natural;
+ pragma Inline (Number_Of_Vertices);
+ -- Obtain the total number of vertices in invocation graph G
+
+ ---------------
+ -- Iterators --
+ ---------------
+
+ -- The following type represents an iterator over all edges of an
+ -- invocation graph.
+
+ type All_Edge_Iterator is private;
+
+ function Has_Next (Iter : All_Edge_Iterator) return Boolean;
+ pragma Inline (Has_Next);
+ -- Determine whether iterator Iter has more edges to examine
+
+ function Iterate_All_Edges
+ (G : Invocation_Graph) return All_Edge_Iterator;
+ pragma Inline (Iterate_All_Edges);
+ -- Obtain an iterator over all edges of invocation graph G
+
+ procedure Next
+ (Iter : in out All_Edge_Iterator;
+ IGE_Id : out Invocation_Graph_Edge_Id);
+ pragma Inline (Next);
+ -- Return the current edge referenced by iterator Iter and advance to
+ -- the next available edge.
+
+ -- The following type represents an iterator over all vertices of an
+ -- invocation graph.
+
+ type All_Vertex_Iterator is private;
+
+ function Has_Next (Iter : All_Vertex_Iterator) return Boolean;
+ pragma Inline (Has_Next);
+ -- Determine whether iterator Iter has more vertices to examine
+
+ function Iterate_All_Vertices
+ (G : Invocation_Graph) return All_Vertex_Iterator;
+ pragma Inline (Iterate_All_Vertices);
+ -- Obtain an iterator over all vertices of invocation graph G
+
+ procedure Next
+ (Iter : in out All_Vertex_Iterator;
+ IGV_Id : out Invocation_Graph_Vertex_Id);
+ pragma Inline (Next);
+ -- Return the current vertex referenced by iterator Iter and advance
+ -- to the next available vertex.
+
+ -- The following type represents an iterator over all edges that reach
+ -- targets starting from a particular source vertex.
+
+ type Edges_To_Targets_Iterator is private;
+
+ function Has_Next (Iter : Edges_To_Targets_Iterator) return Boolean;
+ pragma Inline (Has_Next);
+ -- Determine whether iterator Iter has more edges to examine
+
+ function Iterate_Edges_To_Targets
+ (G : Invocation_Graph;
+ IGV_Id : Invocation_Graph_Vertex_Id) return Edges_To_Targets_Iterator;
+ pragma Inline (Iterate_Edges_To_Targets);
+ -- Obtain an iterator over all edges to targets with source vertex
+ -- IGV_Id of invocation graph G.
+
+ procedure Next
+ (Iter : in out Edges_To_Targets_Iterator;
+ IGE_Id : out Invocation_Graph_Edge_Id);
+ pragma Inline (Next);
+ -- Return the current edge referenced by iterator Iter and advance to
+ -- the next available edge.
+
+ -- The following type represents an iterator over all vertices of an
+ -- invocation graph that denote the elaboration procedure or a spec or
+ -- a body, referred to as elaboration root.
+
+ type Elaboration_Root_Iterator is private;
+
+ function Has_Next (Iter : Elaboration_Root_Iterator) return Boolean;
+ pragma Inline (Has_Next);
+ -- Determine whether iterator Iter has more elaboration roots to examine
+
+ function Iterate_Elaboration_Roots
+ (G : Invocation_Graph) return Elaboration_Root_Iterator;
+ pragma Inline (Iterate_Elaboration_Roots);
+ -- Obtain an iterator over all elaboration roots of invocation graph G
+
+ procedure Next
+ (Iter : in out Elaboration_Root_Iterator;
+ Root : out Invocation_Graph_Vertex_Id);
+ pragma Inline (Next);
+ -- Return the current elaboration root referenced by iterator Iter and
+ -- advance to the next available elaboration root.
+
+ private
+
+ --------------
+ -- Vertices --
+ --------------
+
+ procedure Destroy_Invocation_Graph_Vertex
+ (IGV_Id : in out Invocation_Graph_Vertex_Id);
+ pragma Inline (Destroy_Invocation_Graph_Vertex);
+ -- Destroy invocation graph vertex IGV_Id
+
+ -- The following type represents the attributes of an invocation graph
+ -- vertex.
+
+ type Invocation_Graph_Vertex_Attributes is record
+ Construct : Invocation_Construct_Id := No_Invocation_Construct;
+ -- Reference to the invocation construct this vertex represents
+
+ Lib_Vertex : Library_Graph_Vertex_Id := No_Library_Graph_Vertex;
+ -- Reference to the library graph vertex where this vertex resides
+ end record;
+
+ No_Invocation_Graph_Vertex_Attributes :
+ constant Invocation_Graph_Vertex_Attributes :=
+ (Construct => No_Invocation_Construct,
+ Lib_Vertex => No_Library_Graph_Vertex);
+
+ procedure Destroy_Invocation_Graph_Vertex_Attributes
+ (Attrs : in out Invocation_Graph_Vertex_Attributes);
+ pragma Inline (Destroy_Invocation_Graph_Vertex_Attributes);
+ -- Destroy the contents of attributes Attrs
+
+ package VA is new Dynamic_Hash_Tables
+ (Key_Type => Invocation_Graph_Vertex_Id,
+ Value_Type => Invocation_Graph_Vertex_Attributes,
+ No_Value => No_Invocation_Graph_Vertex_Attributes,
+ Expansion_Threshold => 1.5,
+ Expansion_Factor => 2,
+ Compression_Threshold => 0.3,
+ Compression_Factor => 2,
+ "=" => "=",
+ Destroy_Value => Destroy_Invocation_Graph_Vertex_Attributes,
+ Hash => Hash_Invocation_Graph_Vertex);
+
+ -----------
+ -- Edges --
+ -----------
+
+ procedure Destroy_Invocation_Graph_Edge
+ (IGE_Id : in out Invocation_Graph_Edge_Id);
+ pragma Inline (Destroy_Invocation_Graph_Edge);
+ -- Destroy invocation graph edge IGE_Id
+
+ -- The following type represents the attributes of an invocation graph
+ -- edge.
+
+ type Invocation_Graph_Edge_Attributes is record
+ Relation : Invocation_Relation_Id := No_Invocation_Relation;
+ -- Reference to the invocation relation this edge represents
+ end record;
+
+ No_Invocation_Graph_Edge_Attributes :
+ constant Invocation_Graph_Edge_Attributes :=
+ (Relation => No_Invocation_Relation);
+
+ procedure Destroy_Invocation_Graph_Edge_Attributes
+ (Attrs : in out Invocation_Graph_Edge_Attributes);
+ pragma Inline (Destroy_Invocation_Graph_Edge_Attributes);
+ -- Destroy the contents of attributes Attrs
+
+ package EA is new Dynamic_Hash_Tables
+ (Key_Type => Invocation_Graph_Edge_Id,
+ Value_Type => Invocation_Graph_Edge_Attributes,
+ No_Value => No_Invocation_Graph_Edge_Attributes,
+ Expansion_Threshold => 1.5,
+ Expansion_Factor => 2,
+ Compression_Threshold => 0.3,
+ Compression_Factor => 2,
+ "=" => "=",
+ Destroy_Value => Destroy_Invocation_Graph_Edge_Attributes,
+ Hash => Hash_Invocation_Graph_Edge);
+
+ ---------------
+ -- Relations --
+ ---------------
+
+ -- The following type represents a relation between a source and target
+ -- vertices.
+
+ type Source_Target_Relation is record
+ Source : Invocation_Graph_Vertex_Id := No_Invocation_Graph_Vertex;
+ -- The source vertex
+
+ Target : Invocation_Graph_Vertex_Id := No_Invocation_Graph_Vertex;
+ -- The destination vertex
+ end record;
+
+ No_Source_Target_Relation :
+ constant Source_Target_Relation :=
+ (Source => No_Invocation_Graph_Vertex,
+ Target => No_Invocation_Graph_Vertex);
+
+ function Hash_Source_Target_Relation
+ (Rel : Source_Target_Relation) return Bucket_Range_Type;
+ pragma Inline (Hash_Source_Target_Relation);
+ -- Obtain the hash value of key Rel
+
+ package ST is new Membership_Sets
+ (Element_Type => Source_Target_Relation,
+ "=" => "=",
+ Hash => Hash_Source_Target_Relation);
+
+ ----------------
+ -- Statistics --
+ ----------------
+
+ type Invocation_Graph_Edge_Counts is array (Invocation_Kind) of Natural;
+
+ ----------------
+ -- Signatures --
+ ----------------
+
+ function Hash_Invocation_Signature
+ (IS_Id : Invocation_Signature_Id) return Bucket_Range_Type;
+ pragma Inline (Hash_Invocation_Signature);
+ -- Obtain the hash value of key IS_Id
+
+ package SV is new Dynamic_Hash_Tables
+ (Key_Type => Invocation_Signature_Id,
+ Value_Type => Invocation_Graph_Vertex_Id,
+ No_Value => No_Invocation_Graph_Vertex,
+ Expansion_Threshold => 1.5,
+ Expansion_Factor => 2,
+ Compression_Threshold => 0.3,
+ Compression_Factor => 2,
+ "=" => "=",
+ Destroy_Value => Destroy_Invocation_Graph_Vertex,
+ Hash => Hash_Invocation_Signature);
+
+ -----------------------
+ -- Elaboration roots --
+ -----------------------
+
+ package ER is new Membership_Sets
+ (Element_Type => Invocation_Graph_Vertex_Id,
+ "=" => "=",
+ Hash => Hash_Invocation_Graph_Vertex);
+
+ -----------
+ -- Graph --
+ -----------
+
+ package DG is new Directed_Graphs
+ (Vertex_Id => Invocation_Graph_Vertex_Id,
+ No_Vertex => No_Invocation_Graph_Vertex,
+ Hash_Vertex => Hash_Invocation_Graph_Vertex,
+ Same_Vertex => "=",
+ Edge_id => Invocation_Graph_Edge_Id,
+ No_Edge => No_Invocation_Graph_Edge,
+ Hash_Edge => Hash_Invocation_Graph_Edge,
+ Same_Edge => "=");
+
+ -- The following type represents the attributes of an invocation graph
+
+ type Invocation_Graph_Attributes is record
+ Counts : Invocation_Graph_Edge_Counts := (others => 0);
+ -- Edge statistics
+
+ Edge_Attributes : EA.Dynamic_Hash_Table := EA.Nil;
+ -- The map of edge -> edge attributes for all edges in the graph
+
+ Graph : DG.Directed_Graph := DG.Nil;
+ -- The underlying graph describing the relations between edges and
+ -- vertices.
+
+ Relations : ST.Membership_Set := ST.Nil;
+ -- The set of relations between source and targets, used to prevent
+ -- duplicate edges in the graph.
+
+ Roots : ER.Membership_Set := ER.Nil;
+ -- The set of elaboration root vertices
+
+ Signature_To_Vertex : SV.Dynamic_Hash_Table := SV.Nil;
+ -- The map of signature -> vertex
+
+ Vertex_Attributes : VA.Dynamic_Hash_Table := VA.Nil;
+ -- The map of vertex -> vertex attributes for all vertices in the
+ -- graph.
+ end record;
+
+ type Invocation_Graph is access Invocation_Graph_Attributes;
+ Nil : constant Invocation_Graph := null;
+
+ ---------------
+ -- Iterators --
+ ---------------
+
+ type All_Edge_Iterator is new DG.All_Edge_Iterator;
+ type All_Vertex_Iterator is new DG.All_Vertex_Iterator;
+ type Edges_To_Targets_Iterator is new DG.Outgoing_Edge_Iterator;
+ type Elaboration_Root_Iterator is new ER.Iterator;
+ end Invocation_Graphs;
+
+ --------------------
+ -- Library_Graphs --
+ --------------------
+
+ package Library_Graphs is
+
+ -- The following type represents the various kinds of library edges
+
+ type Library_Graph_Edge_Kind is
+ (Body_Before_Spec_Edge,
+ -- Successor denotes spec, Predecessor denotes a body. This is a
+ -- special edge kind used only during the discovery of components.
+ -- Note that a body can never be elaborated before its spec.
+
+ Elaborate_Edge,
+ -- Successor withs Predecessor, and has pragma Elaborate for it
+
+ Elaborate_All_Edge,
+ -- Successor withs Predecessor, and has pragma Elaborate_All for it
+
+ Forced_Edge,
+ -- Successor is forced to with Predecessor by virtue of an existing
+ -- elaboration order provided in a file.
+
+ Invocation_Edge,
+ -- An invocation construct in unit Successor invokes a target in unit
+ -- Predecessor.
+
+ Spec_Before_Body_Edge,
+ -- Successor denotes a body, Predecessor denotes a spec
+
+ With_Edge,
+ -- Successor withs Predecessor
+
+ No_Edge);
+
+ -----------
+ -- Graph --
+ -----------
+
+ -- The following type denotes a library graph handle. Each instance must
+ -- be created using routine Create.
+
+ type Library_Graph is private;
+ Nil : constant Library_Graph;
+
+ ----------------------
+ -- Graph operations --
+ ----------------------
+
+ procedure Add_Edge
+ (G : Library_Graph;
+ Pred : Library_Graph_Vertex_Id;
+ Succ : Library_Graph_Vertex_Id;
+ Kind : Library_Graph_Edge_Kind);
+ pragma Inline (Add_Edge);
+ -- Create a new edge in library graph G with source vertex Pred and
+ -- destination vertex Succ. Kind denotes the nature of the edge.
+
+ procedure Add_Vertex
+ (G : Library_Graph;
+ U_Id : Unit_Id);
+ pragma Inline (Add_Vertex);
+ -- Create a new vertex in library graph G. U_Id is the unit the vertex
+ -- describes.
+
+ function Create
+ (Initial_Vertices : Positive;
+ Initial_Edges : Positive) return Library_Graph;
+ pragma Inline (Create);
+ -- Create a new empty graph with vertex capacity Initial_Vertices and
+ -- edge capacity Initial_Edges.
+
+ procedure Destroy (G : in out Library_Graph);
+ pragma Inline (Destroy);
+ -- Destroy the contents of library graph G, rendering it unusable
+
+ procedure Find_Components (G : Library_Graph);
+ pragma Inline (Find_Components);
+ -- Find all components in library graph G
+
+ function Present (G : Library_Graph) return Boolean;
+ pragma Inline (Present);
+ -- Determine whether library graph G exists
+
+ -----------------------
+ -- Vertex attributes --
+ -----------------------
+
+ function Component
+ (G : Library_Graph;
+ LGV_Id : Library_Graph_Vertex_Id) return Component_Id;
+ pragma Inline (Component);
+ -- Obtain the component where vertex LGV_Id of library graph G resides
+
+ function Corresponding_Item
+ (G : Library_Graph;
+ LGV_Id : Library_Graph_Vertex_Id) return Library_Graph_Vertex_Id;
+ pragma Inline (Corresponding_Item);
+ -- Obtain the complementary vertex which represents the corresponding
+ -- spec or body of vertex LGV_Id of library graph G.
+
+ function Corresponding_Vertex
+ (G : Library_Graph;
+ U_Id : Unit_Id) return Library_Graph_Vertex_Id;
+ pragma Inline (Corresponding_Vertex);
+ -- Obtain the corresponding vertex of library graph G which represents
+ -- unit U_Id.
+
+ procedure Decrement_Pending_Predecessors
+ (G : Library_Graph;
+ LGV_Id : Library_Graph_Vertex_Id);
+ pragma Inline (Decrement_Pending_Predecessors);
+ -- Decrease the number of pending predecessors vertex LGV_Id of library
+ -- graph G must wait on until it can be elaborated.
+
+ function In_Elaboration_Order
+ (G : Library_Graph;
+ LGV_Id : Library_Graph_Vertex_Id) return Boolean;
+ pragma Inline (In_Elaboration_Order);
+ -- Determine whether vertex LGV_Id of library graph G is already in some
+ -- elaboration order.
+
+ function Name
+ (G : Library_Graph;
+ LGV_Id : Library_Graph_Vertex_Id) return Unit_Name_Type;
+ pragma Inline (Name);
+ -- Obtain the name of the unit which vertex LGV_Id of library graph G
+ -- represents.
+
+ function Pending_Predecessors
+ (G : Library_Graph;
+ LGV_Id : Library_Graph_Vertex_Id) return Natural;
+ pragma Inline (Pending_Predecessors);
+ -- Obtain the number of pending predecessors vertex LGV_Id of library
+ -- graph G must wait on until it can be elaborated.
+
+ procedure Set_Corresponding_Item
+ (G : Library_Graph;
+ LGV_Id : Library_Graph_Vertex_Id;
+ Val : Library_Graph_Vertex_Id);
+ pragma Inline (Set_Corresponding_Item);
+ -- Set the complementary vertex which represents the corresponding
+ -- spec or body of vertex LGV_Id of library graph G to value Val.
+
+ procedure Set_In_Elaboration_Order
+ (G : Library_Graph;
+ LGV_Id : Library_Graph_Vertex_Id;
+ Val : Boolean := True);
+ pragma Inline (Set_In_Elaboration_Order);
+ -- Mark vertex LGV_Id of library graph G as included in some elaboration
+ -- order depending on value Val.
+
+ function Unit
+ (G : Library_Graph;
+ LGV_Id : Library_Graph_Vertex_Id) return Unit_Id;
+ pragma Inline (Unit);
+ -- Obtain the unit vertex LGV_Id of library graph G represents
+
+ ---------------------
+ -- Edge attributes --
+ ---------------------
+
+ function Kind
+ (G : Library_Graph;
+ LGE_Id : Library_Graph_Edge_Id) return Library_Graph_Edge_Kind;
+ pragma Inline (Kind);
+ -- Obtain the nature of edge LGE_Id of library graph G
+
+ function Predecessor
+ (G : Library_Graph;
+ LGE_Id : Library_Graph_Edge_Id) return Library_Graph_Vertex_Id;
+ pragma Inline (Predecessor);
+ -- Obtain the predecessor vertex of edge LGE_Id of library graph G
+
+ function Successor
+ (G : Library_Graph;
+ LGE_Id : Library_Graph_Edge_Id) return Library_Graph_Vertex_Id;
+ pragma Inline (Successor);
+ -- Obtain the successor vertex of edge LGE_Id of library graph G
+
+ --------------------------
+ -- Component attributes --
+ --------------------------
+
+ procedure Decrement_Pending_Predecessors
+ (G : Library_Graph;
+ Comp : Component_Id);
+ pragma Inline (Decrement_Pending_Predecessors);
+ -- Decrease the number of pending predecessors component Comp of library
+ -- graph G must wait on until it can be elaborated.
+
+ function Pending_Predecessors
+ (G : Library_Graph;
+ Comp : Component_Id) return Natural;
+ pragma Inline (Pending_Predecessors);
+ -- Obtain the number of pending predecessors component Comp of library
+ -- graph G must wait on until it can be elaborated.
+
+ ---------------
+ -- Semantics --
+ ---------------
+
+ function Is_Body
+ (G : Library_Graph;
+ LGV_Id : Library_Graph_Vertex_Id) return Boolean;
+ pragma Inline (Is_Body);
+ -- Determine whether vertex LGV_Id of library graph G denotes a body
+
+ function Is_Body_Of_Spec_With_Elaborate_Body
+ (G : Library_Graph;
+ LGV_Id : Library_Graph_Vertex_Id) return Boolean;
+ pragma Inline (Is_Body_Of_Spec_With_Elaborate_Body);
+ -- Determine whether vertex LGV_Id of library graph G denotes a body
+ -- with a corresponding spec, and the spec has pragma Elaborate_Body.
+
+ function Is_Body_With_Spec
+ (G : Library_Graph;
+ LGV_Id : Library_Graph_Vertex_Id) return Boolean;
+ pragma Inline (Is_Body_With_Spec);
+ -- Determine whether vertex LGV_Id of library graph G denotes a body
+ -- with a corresponding spec.
+
+ function Is_Elaborable_Component
+ (G : Library_Graph;
+ Comp : Component_Id) return Boolean;
+ pragma Inline (Is_Elaborable_Component);
+ -- Determine whether component Comp of library graph G can be elaborated
+
+ function Is_Elaborable_Vertex
+ (G : Library_Graph;
+ LGV_Id : Library_Graph_Vertex_Id) return Boolean;
+ pragma Inline (Is_Elaborable_Vertex);
+ -- Determine whether vertex LGV_Id of library graph G can be elaborated
+
+ function Is_Internal_Unit
+ (G : Library_Graph;
+ LGV_Id : Library_Graph_Vertex_Id) return Boolean;
+ pragma Inline (Is_Internal_Unit);
+ -- Determine whether vertex LGV_Id of library graph G denotes an
+ -- internal unit.
+
+ function Is_Predefined_Unit
+ (G : Library_Graph;
+ LGV_Id : Library_Graph_Vertex_Id) return Boolean;
+ pragma Inline (Is_Predefined_Unit);
+ -- Determine whether vertex LGV_Id of library graph G denotes a
+ -- predefined unit.
+
+ function Is_Preelaborated_Unit
+ (G : Library_Graph;
+ LGV_Id : Library_Graph_Vertex_Id) return Boolean;
+ pragma Inline (Is_Preelaborated_Unit);
+ -- Determine whether vertex LGV_Id of library graph G denotes a unit
+ -- subjec to pragma Pure or Preelaborable.
+
+ function Is_Spec
+ (G : Library_Graph;
+ LGV_Id : Library_Graph_Vertex_Id) return Boolean;
+ pragma Inline (Is_Spec);
+ -- Determine whether vertex LGV_Id of library graph G denotes a spec
+
+ function Is_Spec_With_Body
+ (G : Library_Graph;
+ LGV_Id : Library_Graph_Vertex_Id) return Boolean;
+ pragma Inline (Is_Spec_With_Body);
+ -- Determine whether vertex LGV_Id of library graph G denotes a spec
+ -- with a corresponding body.
+
+ function Is_Spec_With_Elaborate_Body
+ (G : Library_Graph;
+ LGV_Id : Library_Graph_Vertex_Id) return Boolean;
+ pragma Inline (Is_Spec_With_Elaborate_Body);
+ -- Determine whether vertex LGV_Id of library graph G denotes a spec
+ -- with a corresponding body, and is subject to pragma Elaborate_Body.
+
+ function Links_Vertices_In_Same_Component
+ (G : Library_Graph;
+ LGE_Id : Library_Graph_Edge_Id) return Boolean;
+ pragma Inline (Links_Vertices_In_Same_Component);
+ -- Determine whether edge LGE_Id of library graph G links a predecessor
+ -- and a successor that reside within the same component.
+
+ function Needs_Elaboration
+ (G : Library_Graph;
+ LGV_Id : Library_Graph_Vertex_Id) return Boolean;
+ pragma Inline (Needs_Elaboration);
+ -- Determine whether vertex LGV_Id of library graph G represents a unit
+ -- that needs to be elaborated.
+
+ function Proper_Body
+ (G : Library_Graph;
+ LGV_Id : Library_Graph_Vertex_Id) return Library_Graph_Vertex_Id;
+ pragma Inline (Proper_Body);
+ -- Obtain the body of vertex LGV_Id of library graph G
+
+ function Proper_Spec
+ (G : Library_Graph;
+ LGV_Id : Library_Graph_Vertex_Id) return Library_Graph_Vertex_Id;
+ pragma Inline (Proper_Spec);
+ -- Obtain the spec of vertex LGV_Id of library graph G
+
+ ----------------
+ -- Statistics --
+ ----------------
+
+ function Library_Graph_Edge_Count
+ (G : Library_Graph;
+ Kind : Library_Graph_Edge_Kind) return Natural;
+ pragma Inline (Library_Graph_Edge_Count);
+ -- Obtain the total number of edges of kind Kind in library graph G
+
+ function Number_Of_Component_Vertices
+ (G : Library_Graph;
+ Comp : Component_Id) return Natural;
+ pragma Inline (Number_Of_Component_Vertices);
+ -- Obtain the total number of vertices component Comp of library graph
+ -- contains.
+
+ function Number_Of_Components (G : Library_Graph) return Natural;
+ pragma Inline (Number_Of_Components);
+ -- Obtain the total number of components in library graph G
+
+ function Number_Of_Edges (G : Library_Graph) return Natural;
+ pragma Inline (Number_Of_Edges);
+ -- Obtain the total number of edges in library graph G
+
+ function Number_Of_Edges_To_Successors
+ (G : Library_Graph;
+ LGV_Id : Library_Graph_Vertex_Id) return Natural;
+ pragma Inline (Number_Of_Edges_To_Successors);
+ -- Obtain the total number of edges to successors vertex LGV_Id of
+ -- library graph G has.
+
+ function Number_Of_Vertices (G : Library_Graph) return Natural;
+ pragma Inline (Number_Of_Vertices);
+ -- Obtain the total number of vertices in library graph G
+
+ ---------------
+ -- Iterators --
+ ---------------
+
+ -- The following type represents an iterator over all edges of a library
+ -- graph.
+
+ type All_Edge_Iterator is private;
+
+ function Has_Next (Iter : All_Edge_Iterator) return Boolean;
+ pragma Inline (Has_Next);
+ -- Determine whether iterator Iter has more edges to examine
+
+ function Iterate_All_Edges (G : Library_Graph) return All_Edge_Iterator;
+ pragma Inline (Iterate_All_Edges);
+ -- Obtain an iterator over all edges of library graph G
+
+ procedure Next
+ (Iter : in out All_Edge_Iterator;
+ LGE_Id : out Library_Graph_Edge_Id);
+ pragma Inline (Next);
+ -- Return the current edge referenced by iterator Iter and advance to
+ -- the next available edge.
+
+ -- The following type represents an iterator over all vertices of a
+ -- library graph.
+
+ type All_Vertex_Iterator is private;
+
+ function Has_Next (Iter : All_Vertex_Iterator) return Boolean;
+ pragma Inline (Has_Next);
+ -- Determine whether iterator Iter has more vertices to examine
+
+ function Iterate_All_Vertices
+ (G : Library_Graph) return All_Vertex_Iterator;
+ pragma Inline (Iterate_All_Vertices);
+ -- Obtain an iterator over all vertices of library graph G
+
+ procedure Next
+ (Iter : in out All_Vertex_Iterator;
+ LGV_Id : out Library_Graph_Vertex_Id);
+ pragma Inline (Next);
+ -- Return the current vertex referenced by iterator Iter and advance
+ -- to the next available vertex.
+
+ -- The following type represents an iterator over all components of a
+ -- library graph.
+
+ type Component_Iterator is private;
+
+ function Has_Next (Iter : Component_Iterator) return Boolean;
+ pragma Inline (Has_Next);
+ -- Determine whether iterator Iter has more components to examine
+
+ function Iterate_Components
+ (G : Library_Graph) return Component_Iterator;
+ pragma Inline (Iterate_Components);
+ -- Obtain an iterator over all components of library graph G
+
+ procedure Next
+ (Iter : in out Component_Iterator;
+ Comp : out Component_Id);
+ pragma Inline (Next);
+ -- Return the current component referenced by iterator Iter and advance
+ -- to the next available component.
+
+ -- The following type represents an iterator over all vertices of a
+ -- component.
+
+ type Component_Vertex_Iterator is private;
+
+ function Has_Next (Iter : Component_Vertex_Iterator) return Boolean;
+ pragma Inline (Has_Next);
+ -- Determine whether iterator Iter has more vertices to examine
+
+ function Iterate_Component_Vertices
+ (G : Library_Graph;
+ Comp : Component_Id) return Component_Vertex_Iterator;
+ pragma Inline (Iterate_Component_Vertices);
+ -- Obtain an iterator over all vertices of component Comp of library
+ -- graph G.
+
+ procedure Next
+ (Iter : in out Component_Vertex_Iterator;
+ LGV_Id : out Library_Graph_Vertex_Id);
+ pragma Inline (Next);
+ -- Return the current vertex referenced by iterator Iter and advance
+ -- to the next available vertex.
+
+ -- The following type represents an iterator over all edges that reach
+ -- successors starting from a particular predecessor vertex.
+
+ type Edges_To_Successors_Iterator is private;
+
+ function Has_Next (Iter : Edges_To_Successors_Iterator) return Boolean;
+ pragma Inline (Has_Next);
+ -- Determine whether iterator Iter has more edges to examine
+
+ function Iterate_Edges_To_Successors
+ (G : Library_Graph;
+ LGV_Id : Library_Graph_Vertex_Id) return Edges_To_Successors_Iterator;
+ pragma Inline (Iterate_Components);
+ -- Obtain an iterator over all edges to successors with predecessor
+ -- vertex LGV_Id of library graph G.
+
+ procedure Next
+ (Iter : in out Edges_To_Successors_Iterator;
+ LGE_Id : out Library_Graph_Edge_Id);
+ pragma Inline (Next);
+ -- Return the current edge referenced by iterator Iter and advance to
+ -- the next available edge.
+
+ private
+
+ --------------
+ -- Vertices --
+ --------------
+
+ procedure Destroy_Library_Graph_Vertex
+ (LGV_Id : in out Library_Graph_Vertex_Id);
+ pragma Inline (Destroy_Library_Graph_Vertex);
+ -- Destroy library graph vertex LGV_Id
+
+ -- The following type represents the attributes of a library graph
+ -- vertex.
+
+ type Library_Graph_Vertex_Attributes is record
+ Corresponding_Item : Library_Graph_Vertex_Id :=
+ No_Library_Graph_Vertex;
+ -- The reference to the corresponding spec or body. This attribute is
+ -- set as follows:
+ --
+ -- * If predicate Is_Body_With_Spec is True, the reference denotes
+ -- the corresponding spec.
+ --
+ -- * If predicate Is_Spec_With_Body is True, the reference denotes
+ -- the corresponding body.
+ --
+ -- * Otherwise the attribute remains empty.
+
+ In_Elaboration_Order : Boolean := False;
+ -- Set when this vertex is elaborated
+
+ Pending_Predecessors : Natural := 0;
+ -- The number of pending predecessor vertices this vertex must wait
+ -- on before it can be elaborated.
+
+ Unit : Unit_Id := No_Unit_Id;
+ -- The reference to unit this vertex represents
+ end record;
+
+ No_Library_Graph_Vertex_Attributes :
+ constant Library_Graph_Vertex_Attributes :=
+ (Corresponding_Item => No_Library_Graph_Vertex,
+ In_Elaboration_Order => False,
+ Pending_Predecessors => 0,
+ Unit => No_Unit_Id);
+
+ procedure Destroy_Library_Graph_Vertex_Attributes
+ (Attrs : in out Library_Graph_Vertex_Attributes);
+ pragma Inline (Destroy_Library_Graph_Vertex_Attributes);
+ -- Destroy the contents of attributes Attrs
+
+ package VA is new Dynamic_Hash_Tables
+ (Key_Type => Library_Graph_Vertex_Id,
+ Value_Type => Library_Graph_Vertex_Attributes,
+ No_Value => No_Library_Graph_Vertex_Attributes,
+ Expansion_Threshold => 1.5,
+ Expansion_Factor => 2,
+ Compression_Threshold => 0.3,
+ Compression_Factor => 2,
+ "=" => "=",
+ Destroy_Value => Destroy_Library_Graph_Vertex_Attributes,
+ Hash => Hash_Library_Graph_Vertex);
+
+ -----------
+ -- Edges --
+ -----------
+
+ procedure Destroy_Library_Graph_Edge
+ (LGE_Id : in out Library_Graph_Edge_Id);
+ pragma Inline (Destroy_Library_Graph_Edge);
+ -- Destroy library graph edge LGE_Id
+
+ -- The following type represents the attributes of a library graph edge
+
+ type Library_Graph_Edge_Attributes is record
+ Kind : Library_Graph_Edge_Kind := No_Edge;
+ -- The nature of the library graph edge
+ end record;
+
+ No_Library_Graph_Edge_Attributes :
+ constant Library_Graph_Edge_Attributes :=
+ (Kind => No_Edge);
+
+ procedure Destroy_Library_Graph_Edge_Attributes
+ (Attrs : in out Library_Graph_Edge_Attributes);
+ pragma Inline (Destroy_Library_Graph_Edge_Attributes);
+ -- Destroy the contents of attributes Attrs
+
+ package EA is new Dynamic_Hash_Tables
+ (Key_Type => Library_Graph_Edge_Id,
+ Value_Type => Library_Graph_Edge_Attributes,
+ No_Value => No_Library_Graph_Edge_Attributes,
+ Expansion_Threshold => 1.5,
+ Expansion_Factor => 2,
+ Compression_Threshold => 0.3,
+ Compression_Factor => 2,
+ "=" => "=",
+ Destroy_Value => Destroy_Library_Graph_Edge_Attributes,
+ Hash => Hash_Library_Graph_Edge);
+
+ ----------------
+ -- Components --
+ ----------------
+
+ -- The following type represents the attributes of a component
+
+ type Component_Attributes is record
+ Pending_Predecessors : Natural := 0;
+ -- The number of pending predecessor components this component must
+ -- wait on before it can be elaborated.
+ end record;
+
+ No_Component_Attributes : constant Component_Attributes :=
+ (Pending_Predecessors => 0);
+
+ procedure Destroy_Component_Attributes
+ (Attrs : in out Component_Attributes);
+ pragma Inline (Destroy_Component_Attributes);
+ -- Destroy the contents of attributes Attrs
+
+ package CA is new Dynamic_Hash_Tables
+ (Key_Type => Component_Id,
+ Value_Type => Component_Attributes,
+ No_Value => No_Component_Attributes,
+ Expansion_Threshold => 1.5,
+ Expansion_Factor => 2,
+ Compression_Threshold => 0.3,
+ Compression_Factor => 2,
+ "=" => "=",
+ Destroy_Value => Destroy_Component_Attributes,
+ Hash => Hash_Component);
+
+ ---------------
+ -- Relations --
+ ---------------
+
+ -- The following type represents a relation between a predecessor and
+ -- successor vertices.
+
+ type Predecessor_Successor_Relation is record
+ Predecessor : Library_Graph_Vertex_Id := No_Library_Graph_Vertex;
+ -- The source vertex
+
+ Successor : Library_Graph_Vertex_Id := No_Library_Graph_Vertex;
+ -- The destination vertex
+ end record;
+
+ No_Predecessor_Successor_Relation :
+ constant Predecessor_Successor_Relation :=
+ (Predecessor => No_Library_Graph_Vertex,
+ Successor => No_Library_Graph_Vertex);
+
+ function Hash_Predecessor_Successor_Relation
+ (Rel : Predecessor_Successor_Relation) return Bucket_Range_Type;
+ pragma Inline (Hash_Predecessor_Successor_Relation);
+ -- Obtain the hash value of key Rel
+
+ package PS is new Membership_Sets
+ (Element_Type => Predecessor_Successor_Relation,
+ "=" => "=",
+ Hash => Hash_Predecessor_Successor_Relation);
+
+ ----------------
+ -- Statistics --
+ ----------------
+
+ type Library_Graph_Edge_Counts is
+ array (Library_Graph_Edge_Kind) of Natural;
+
+ -----------
+ -- Units --
+ -----------
+
+ package UV is new Dynamic_Hash_Tables
+ (Key_Type => Unit_Id,
+ Value_Type => Library_Graph_Vertex_Id,
+ No_Value => No_Library_Graph_Vertex,
+ Expansion_Threshold => 1.5,
+ Expansion_Factor => 2,
+ Compression_Threshold => 0.3,
+ Compression_Factor => 2,
+ "=" => "=",
+ Destroy_Value => Destroy_Library_Graph_Vertex,
+ Hash => Hash_Unit);
+
+ -----------
+ -- Graph --
+ -----------
+
+ package DG is new Directed_Graphs
+ (Vertex_Id => Library_Graph_Vertex_Id,
+ No_Vertex => No_Library_Graph_Vertex,
+ Hash_Vertex => Hash_Library_Graph_Vertex,
+ Same_Vertex => "=",
+ Edge_Id => Library_Graph_Edge_Id,
+ No_Edge => No_Library_Graph_Edge,
+ Hash_Edge => Hash_Library_Graph_Edge,
+ Same_Edge => "=");
+
+ -- The following type represents the attributes of a library graph
+
+ type Library_Graph_Attributes is record
+ Component_Attributes : CA.Dynamic_Hash_Table := CA.Nil;
+ -- The map of component -> component attributes for all components in
+ -- the graph.
+
+ Counts : Library_Graph_Edge_Counts := (others => 0);
+ -- Edge statistics
+
+ Edge_Attributes : EA.Dynamic_Hash_Table := EA.Nil;
+ -- The map of edge -> edge attributes for all edges in the graph
+
+ Graph : DG.Directed_Graph := DG.Nil;
+ -- The underlying graph describing the relations between edges and
+ -- vertices.
+
+ Relations : PS.Membership_Set := PS.Nil;
+ -- The set of relations between successors and predecessors, used to
+ -- prevent duplicate edges in the graph.
+
+ Unit_To_Vertex : UV.Dynamic_Hash_Table := UV.Nil;
+ -- The map of unit -> vertex
+
+ Vertex_Attributes : VA.Dynamic_Hash_Table := VA.Nil;
+ -- The map of vertex -> vertex attributes for all vertices in the
+ -- graph.
+ end record;
+
+ type Library_Graph is access Library_Graph_Attributes;
+ Nil : constant Library_Graph := null;
+
+ ---------------
+ -- Iterators --
+ ---------------
+
+ type All_Edge_Iterator is new DG.All_Edge_Iterator;
+ type All_Vertex_Iterator is new DG.All_Vertex_Iterator;
+ type Component_Iterator is new DG.Component_Iterator;
+ type Component_Vertex_Iterator is new DG.Component_Vertex_Iterator;
+ type Edges_To_Successors_Iterator is new DG.Outgoing_Edge_Iterator;
+ end Library_Graphs;
+
+end Bindo.Graphs;
diff --git a/gcc/ada/bindo-units.adb b/gcc/ada/bindo-units.adb
new file mode 100644
index 0000000..de0afb9f
--- /dev/null
+++ b/gcc/ada/bindo-units.adb
@@ -0,0 +1,410 @@
+------------------------------------------------------------------------------
+-- --
+-- GNAT COMPILER COMPONENTS --
+-- --
+-- B I N D O . U N I T S --
+-- --
+-- B o d y --
+-- --
+-- Copyright (C) 2019, 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. See the GNU General Public License --
+-- for more details. You should have received a copy of the GNU General --
+-- Public License distributed with GNAT; see file COPYING3. If not, go to --
+-- http://www.gnu.org/licenses for a complete copy of the license. --
+-- --
+-- GNAT was originally developed by the GNAT team at New York University. --
+-- Extensive contributions were provided by Ada Core Technologies Inc. --
+-- --
+------------------------------------------------------------------------------
+
+package body Bindo.Units is
+
+ -------------------
+ -- Signature set --
+ -------------------
+
+ package SS is new Membership_Sets
+ (Element_Type => Invocation_Signature_Id,
+ "=" => "=",
+ Hash => Hash_Invocation_Signature);
+
+ -----------------
+ -- Global data --
+ -----------------
+
+ -- The following set stores all invocation signatures that appear in
+ -- elaborable units.
+
+ Elaborable_Constructs : SS.Membership_Set := SS.Nil;
+
+ -- The following set stores all units the need to be elaborated
+
+ Elaborable_Units : US.Membership_Set := US.Nil;
+
+ -----------------------
+ -- Local subprograms --
+ -----------------------
+
+ function Corresponding_Unit (Nam : Name_Id) return Unit_Id;
+ pragma Inline (Corresponding_Unit);
+ -- Obtain the unit which corresponds to name Nam
+
+ function Is_Stand_Alone_Library_Unit (U_Id : Unit_Id) return Boolean;
+ pragma Inline (Is_Stand_Alone_Library_Unit);
+ -- Determine whether unit U_Id is part of a stand-alone library
+
+ procedure Process_Invocation_Construct (IC_Id : Invocation_Construct_Id);
+ pragma Inline (Process_Invocation_Construct);
+ -- Process invocation construct IC_Id by adding its signature to set
+ -- Elaborable_Constructs_Set.
+
+ procedure Process_Invocation_Constructs (U_Id : Unit_Id);
+ pragma Inline (Process_Invocation_Constructs);
+ -- Process all invocation constructs of unit U_Id for classification
+ -- purposes.
+
+ procedure Process_Unit (U_Id : Unit_Id);
+ pragma Inline (Process_Unit);
+ -- Process unit U_Id for unit classification purposes
+
+ ------------------------------
+ -- Collect_Elaborable_Units --
+ ------------------------------
+
+ procedure Collect_Elaborable_Units is
+ begin
+ for U_Id in ALI.Units.First .. ALI.Units.Last loop
+ Process_Unit (U_Id);
+ end loop;
+ end Collect_Elaborable_Units;
+
+ ------------------------
+ -- Corresponding_Body --
+ ------------------------
+
+ function Corresponding_Body (U_Id : Unit_Id) return Unit_Id is
+ pragma Assert (Present (U_Id));
+
+ U_Rec : Unit_Record renames ALI.Units.Table (U_Id);
+
+ begin
+ pragma Assert (U_Rec.Utype = Is_Spec);
+ return U_Id - 1;
+ end Corresponding_Body;
+
+ ------------------------
+ -- Corresponding_Spec --
+ ------------------------
+
+ function Corresponding_Spec (U_Id : Unit_Id) return Unit_Id is
+ pragma Assert (Present (U_Id));
+
+ U_Rec : Unit_Record renames ALI.Units.Table (U_Id);
+
+ begin
+ pragma Assert (U_Rec.Utype = Is_Body);
+ return U_Id + 1;
+ end Corresponding_Spec;
+
+ ------------------------
+ -- Corresponding_Unit --
+ ------------------------
+
+ function Corresponding_Unit (FNam : File_Name_Type) return Unit_Id is
+ begin
+ return Corresponding_Unit (Name_Id (FNam));
+ end Corresponding_Unit;
+
+ ------------------------
+ -- Corresponding_Unit --
+ ------------------------
+
+ function Corresponding_Unit (Nam : Name_Id) return Unit_Id is
+ begin
+ return Unit_Id (Get_Name_Table_Int (Nam));
+ end Corresponding_Unit;
+
+ ------------------------
+ -- Corresponding_Unit --
+ ------------------------
+
+ function Corresponding_Unit (UNam : Unit_Name_Type) return Unit_Id is
+ begin
+ return Corresponding_Unit (Name_Id (UNam));
+ end Corresponding_Unit;
+
+ --------------------
+ -- Finalize_Units --
+ --------------------
+
+ procedure Finalize_Units is
+ begin
+ SS.Destroy (Elaborable_Constructs);
+ US.Destroy (Elaborable_Units);
+ end Finalize_Units;
+
+ ------------------------------
+ -- For_Each_Elaborable_Unit --
+ ------------------------------
+
+ procedure For_Each_Elaborable_Unit (Processor : Unit_Processor_Ptr) is
+ Iter : Elaborable_Units_Iterator;
+ U_Id : Unit_Id;
+
+ begin
+ Iter := Iterate_Elaborable_Units;
+ while Has_Next (Iter) loop
+ Next (Iter, U_Id);
+
+ Processor.all (U_Id);
+ end loop;
+ end For_Each_Elaborable_Unit;
+
+ -------------------
+ -- For_Each_Unit --
+ -------------------
+
+ procedure For_Each_Unit (Processor : Unit_Processor_Ptr) is
+ begin
+ for U_Id in ALI.Units.First .. ALI.Units.Last loop
+ Processor.all (U_Id);
+ end loop;
+ end For_Each_Unit;
+
+ --------------
+ -- Has_Next --
+ --------------
+
+ function Has_Next (Iter : Elaborable_Units_Iterator) return Boolean is
+ begin
+ return US.Has_Next (US.Iterator (Iter));
+ end Has_Next;
+
+ -------------------------------
+ -- Hash_Invocation_Signature --
+ -------------------------------
+
+ function Hash_Invocation_Signature
+ (IS_Id : Invocation_Signature_Id) return Bucket_Range_Type
+ is
+ begin
+ pragma Assert (Present (IS_Id));
+
+ return Bucket_Range_Type (IS_Id);
+ end Hash_Invocation_Signature;
+
+ ---------------
+ -- Hash_Unit --
+ ---------------
+
+ function Hash_Unit (U_Id : Unit_Id) return Bucket_Range_Type is
+ begin
+ pragma Assert (Present (U_Id));
+
+ return Bucket_Range_Type (U_Id);
+ end Hash_Unit;
+
+ ----------------------
+ -- Initialize_Units --
+ ----------------------
+
+ procedure Initialize_Units is
+ begin
+ Elaborable_Constructs := SS.Create (Number_Of_Units);
+ Elaborable_Units := US.Create (Number_Of_Units);
+ end Initialize_Units;
+
+ -------------------------------
+ -- Is_Dynamically_Elaborated --
+ -------------------------------
+
+ function Is_Dynamically_Elaborated (U_Id : Unit_Id) return Boolean is
+ pragma Assert (Present (U_Id));
+
+ U_Rec : Unit_Record renames ALI.Units.Table (U_Id);
+
+ begin
+ return U_Rec.Dynamic_Elab;
+ end Is_Dynamically_Elaborated;
+
+ ----------------------
+ -- Is_Internal_Unit --
+ ----------------------
+
+ function Is_Internal_Unit (U_Id : Unit_Id) return Boolean is
+ pragma Assert (Present (U_Id));
+
+ U_Rec : Unit_Record renames ALI.Units.Table (U_Id);
+
+ begin
+ return U_Rec.Internal;
+ end Is_Internal_Unit;
+
+ ------------------------
+ -- Is_Predefined_Unit --
+ ------------------------
+
+ function Is_Predefined_Unit (U_Id : Unit_Id) return Boolean is
+ pragma Assert (Present (U_Id));
+
+ U_Rec : Unit_Record renames ALI.Units.Table (U_Id);
+
+ begin
+ return U_Rec.Predefined;
+ end Is_Predefined_Unit;
+
+ ---------------------------------
+ -- Is_Stand_Alone_Library_Unit --
+ ---------------------------------
+
+ function Is_Stand_Alone_Library_Unit (U_Id : Unit_Id) return Boolean is
+ pragma Assert (Present (U_Id));
+
+ U_Rec : Unit_Record renames ALI.Units.Table (U_Id);
+
+ begin
+ return U_Rec.SAL_Interface;
+ end Is_Stand_Alone_Library_Unit;
+
+ ------------------------------
+ -- Iterate_Elaborable_Units --
+ ------------------------------
+
+ function Iterate_Elaborable_Units return Elaborable_Units_Iterator is
+ begin
+ return Elaborable_Units_Iterator (US.Iterate (Elaborable_Units));
+ end Iterate_Elaborable_Units;
+
+ ----------
+ -- Name --
+ ----------
+
+ function Name (U_Id : Unit_Id) return Unit_Name_Type is
+ pragma Assert (Present (U_Id));
+
+ U_Rec : Unit_Record renames ALI.Units.Table (U_Id);
+
+ begin
+ return U_Rec.Uname;
+ end Name;
+
+ -----------------------
+ -- Needs_Elaboration --
+ -----------------------
+
+ function Needs_Elaboration
+ (IS_Id : Invocation_Signature_Id) return Boolean
+ is
+ begin
+ pragma Assert (Present (IS_Id));
+
+ return SS.Contains (Elaborable_Constructs, IS_Id);
+ end Needs_Elaboration;
+
+ -----------------------
+ -- Needs_Elaboration --
+ -----------------------
+
+ function Needs_Elaboration (U_Id : Unit_Id) return Boolean is
+ begin
+ pragma Assert (Present (U_Id));
+
+ return US.Contains (Elaborable_Units, U_Id);
+ end Needs_Elaboration;
+
+ ----------
+ -- Next --
+ ----------
+
+ procedure Next
+ (Iter : in out Elaborable_Units_Iterator;
+ U_Id : out Unit_Id)
+ is
+ begin
+ US.Next (US.Iterator (Iter), U_Id);
+ end Next;
+
+ --------------------------------
+ -- Number_Of_Elaborable_Units --
+ --------------------------------
+
+ function Number_Of_Elaborable_Units return Natural is
+ begin
+ return US.Size (Elaborable_Units);
+ end Number_Of_Elaborable_Units;
+
+ ---------------------
+ -- Number_Of_Units --
+ ---------------------
+
+ function Number_Of_Units return Natural is
+ begin
+ return Natural (ALI.Units.Last) - Natural (ALI.Units.First) + 1;
+ end Number_Of_Units;
+
+ ----------------------------------
+ -- Process_Invocation_Construct --
+ ----------------------------------
+
+ procedure Process_Invocation_Construct (IC_Id : Invocation_Construct_Id) is
+ pragma Assert (Present (IC_Id));
+
+ IC_Rec : Invocation_Construct_Record renames
+ Invocation_Constructs.Table (IC_Id);
+ IC_Sig : constant Invocation_Signature_Id := IC_Rec.Signature;
+
+ pragma Assert (Present (IC_Sig));
+
+ begin
+ SS.Insert (Elaborable_Constructs, IC_Sig);
+ end Process_Invocation_Construct;
+
+ -----------------------------------
+ -- Process_Invocation_Constructs --
+ -----------------------------------
+
+ procedure Process_Invocation_Constructs (U_Id : Unit_Id) is
+ pragma Assert (Present (U_Id));
+
+ U_Rec : Unit_Record renames ALI.Units.Table (U_Id);
+
+ begin
+ for IC_Id in U_Rec.First_Invocation_Construct ..
+ U_Rec.Last_Invocation_Construct
+ loop
+ Process_Invocation_Construct (IC_Id);
+ end loop;
+ end Process_Invocation_Constructs;
+
+ ------------------
+ -- Process_Unit --
+ ------------------
+
+ procedure Process_Unit (U_Id : Unit_Id) is
+ begin
+ pragma Assert (Present (U_Id));
+
+ -- A stand-alone library unit must not be elaborated as part of the
+ -- current compilation because the library already carries its own
+ -- elaboration code.
+
+ if Is_Stand_Alone_Library_Unit (U_Id) then
+ null;
+
+ -- Otherwise the unit needs to be elaborated. Add it to the set
+ -- of units that require elaboration, as well as all invocation
+ -- signatures of constructs it declares.
+
+ else
+ US.Insert (Elaborable_Units, U_Id);
+ Process_Invocation_Constructs (U_Id);
+ end if;
+ end Process_Unit;
+
+end Bindo.Units;
diff --git a/gcc/ada/bindo-units.ads b/gcc/ada/bindo-units.ads
new file mode 100644
index 0000000..93caadf
--- /dev/null
+++ b/gcc/ada/bindo-units.ads
@@ -0,0 +1,154 @@
+------------------------------------------------------------------------------
+-- --
+-- GNAT COMPILER COMPONENTS --
+-- --
+-- B I N D O . U N I T S --
+-- --
+-- S p e c --
+-- --
+-- Copyright (C) 2019, 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. See the GNU General Public License --
+-- for more details. You should have received a copy of the GNU General --
+-- Public License distributed with GNAT; see file COPYING3. If not, go to --
+-- http://www.gnu.org/licenses for a complete copy of the license. --
+-- --
+-- GNAT was originally developed by the GNAT team at New York University. --
+-- Extensive contributions were provided by Ada Core Technologies Inc. --
+-- --
+------------------------------------------------------------------------------
+
+-- For full architecture, see unit Bindo.
+
+-- The following unit contains facilities to collect all elaborable units in
+-- the bind and inspect their properties.
+
+with GNAT; use GNAT;
+with GNAT.Sets; use GNAT.Sets;
+
+package Bindo.Units is
+
+ procedure Collect_Elaborable_Units;
+ pragma Inline (Collect_Elaborable_Units);
+ -- Gather all units in the bind that require elaboration. The units are
+ -- accessible via iterator Elaborable_Units_Iterator.
+
+ function Corresponding_Body (U_Id : Unit_Id) return Unit_Id;
+ pragma Inline (Corresponding_Body);
+ -- Return the body of a spec unit U_Id
+
+ function Corresponding_Spec (U_Id : Unit_Id) return Unit_Id;
+ pragma Inline (Corresponding_Spec);
+ -- Return the spec of a body unit U_Id
+
+ function Corresponding_Unit (FNam : File_Name_Type) return Unit_Id;
+ pragma Inline (Corresponding_Unit);
+ -- Obtain the unit which corresponds to name FNam
+
+ function Corresponding_Unit (UNam : Unit_Name_Type) return Unit_Id;
+ pragma Inline (Corresponding_Unit);
+ -- Obtain the unit which corresponds to name FNam
+
+ type Unit_Processor_Ptr is access procedure (U_Id : Unit_Id);
+
+ procedure For_Each_Elaborable_Unit (Processor : Unit_Processor_Ptr);
+ pragma Inline (For_Each_Elaborable_Unit);
+ -- Invoke Processor on each elaborable unit in the bind
+
+ procedure For_Each_Unit (Processor : Unit_Processor_Ptr);
+ pragma Inline (For_Each_Unit);
+ -- Invoke Processor on each unit in the bind
+
+ function Hash_Invocation_Signature
+ (IS_Id : Invocation_Signature_Id) return Bucket_Range_Type;
+ pragma Inline (Hash_Invocation_Signature);
+ -- Obtain the hash value of key IS_Id
+
+ function Hash_Unit (U_Id : Unit_Id) return Bucket_Range_Type;
+ pragma Inline (Hash_Unit);
+ -- Obtain the hash value of key U_Id
+
+ function Is_Dynamically_Elaborated (U_Id : Unit_Id) return Boolean;
+ pragma Inline (Is_Dynamically_Elaborated);
+ -- Determine whether unit U_Id was compiled using the dynamic elaboration
+ -- model.
+
+ function Is_Internal_Unit (U_Id : Unit_Id) return Boolean;
+ pragma Inline (Is_Internal_Unit);
+ -- Determine whether unit U_Id is internal
+
+ function Is_Predefined_Unit (U_Id : Unit_Id) return Boolean;
+ pragma Inline (Is_Predefined_Unit);
+ -- Determine whether unit U_Id is predefined
+
+ function Name (U_Id : Unit_Id) return Unit_Name_Type;
+ pragma Inline (Name);
+ -- Obtain the name of unit U_Id
+
+ function Needs_Elaboration (IS_Id : Invocation_Signature_Id) return Boolean;
+ pragma Inline (Needs_Elaboration);
+ -- Determine whether invocation signature IS_Id belongs to a construct that
+ -- appears in a unit which needs to be elaborated.
+
+ function Needs_Elaboration (U_Id : Unit_Id) return Boolean;
+ pragma Inline (Needs_Elaboration);
+ -- Determine whether unit U_Id needs to be elaborated
+
+ function Number_Of_Elaborable_Units return Natural;
+ pragma Inline (Number_Of_Elaborable_Units);
+ -- Obtain the number of units in the bind that need to be elaborated
+
+ function Number_Of_Units return Natural;
+ pragma Inline (Number_Of_Units);
+ -- Obtain the number of units in the bind
+
+ ---------------
+ -- Iterators --
+ ---------------
+
+ -- The following type represents an iterator over all units that need to be
+ -- elaborated.
+
+ type Elaborable_Units_Iterator is private;
+
+ function Has_Next (Iter : Elaborable_Units_Iterator) return Boolean;
+ pragma Inline (Has_Next);
+ -- Determine whether iterator Iter has more units to examine
+
+ function Iterate_Elaborable_Units return Elaborable_Units_Iterator;
+ pragma Inline (Iterate_Elaborable_Units);
+ -- Obtain an iterator over all units that need to be elaborated
+
+ procedure Next
+ (Iter : in out Elaborable_Units_Iterator;
+ U_Id : out Unit_Id);
+ pragma Inline (Next);
+ -- Return the current unit referenced by iterator Iter and advance to the
+ -- next available unit.
+
+ -----------------
+ -- Maintenance --
+ -----------------
+
+ procedure Finalize_Units;
+ pragma Inline (Finalize_Units);
+ -- Destroy the internal structures of this unit
+
+ procedure Initialize_Units;
+ pragma Inline (Initialize_Units);
+ -- Initialize the internal structures of this unit
+
+private
+ package US is new Membership_Sets
+ (Element_Type => Unit_Id,
+ "=" => "=",
+ Hash => Hash_Unit);
+
+ type Elaborable_Units_Iterator is new US.Iterator;
+
+end Bindo.Units;
diff --git a/gcc/ada/bindo-validators.adb b/gcc/ada/bindo-validators.adb
new file mode 100644
index 0000000..54d2fc6
--- /dev/null
+++ b/gcc/ada/bindo-validators.adb
@@ -0,0 +1,679 @@
+------------------------------------------------------------------------------
+-- --
+-- GNAT COMPILER COMPONENTS --
+-- --
+-- B I N D O . V A L I D A T O R S --
+-- --
+-- B o d y --
+-- --
+-- Copyright (C) 2019, 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. See the GNU General Public License --
+-- for more details. You should have received a copy of the GNU General --
+-- Public License distributed with GNAT; see file COPYING3. If not, go to --
+-- http://www.gnu.org/licenses for a complete copy of the license. --
+-- --
+-- GNAT was originally developed by the GNAT team at New York University. --
+-- Extensive contributions were provided by Ada Core Technologies Inc. --
+-- --
+------------------------------------------------------------------------------
+
+with Debug; use Debug;
+with Output; use Output;
+with Types; use Types;
+
+with Bindo.Units; use Bindo.Units;
+
+with GNAT; use GNAT;
+with GNAT.Sets; use GNAT.Sets;
+
+package body Bindo.Validators is
+
+ ----------------------------------
+ -- Elaboration_Order_Validators --
+ ----------------------------------
+
+ package body Elaboration_Order_Validators is
+ package US is new Membership_Sets
+ (Element_Type => Unit_Id,
+ "=" => "=",
+ Hash => Hash_Unit);
+ use US;
+
+ Has_Invalid_Data : Boolean := False;
+ -- Flag set when the elaboration order contains invalid data
+
+ -----------------------
+ -- Local subprograms --
+ -----------------------
+
+ function Build_Elaborable_Unit_Set return Membership_Set;
+ pragma Inline (Build_Elaborable_Unit_Set);
+ -- Create a set from all units that need to be elaborated
+
+ procedure Report_Missing_Elaboration (U_Id : Unit_Id);
+ pragma Inline (Report_Missing_Elaboration);
+ -- Emit an error concerning unit U_Id that must be elaborated, but was
+ -- not.
+
+ procedure Report_Missing_Elaborations (Set : Membership_Set);
+ pragma Inline (Report_Missing_Elaborations);
+ -- Emit errors on all units in set Set that must be elaborated, but were
+ -- not.
+
+ procedure Report_Spurious_Elaboration (U_Id : Unit_Id);
+ pragma Inline (Report_Spurious_Elaboration);
+ -- Emit an error concerning unit U_Id that is incorrectly elaborated
+
+ procedure Validate_Unit (U_Id : Unit_Id; Elab_Set : Membership_Set);
+ pragma Inline (Validate_Unit);
+ -- Validate the elaboration status of unit U_Id. Elab_Set is the set of
+ -- all units that need to be elaborated.
+
+ procedure Validate_Units (Order : Unit_Id_Table);
+ pragma Inline (Validate_Units);
+ -- Validate all units in elaboration order Order
+
+ procedure Write_Error (Msg : String);
+ pragma Inline (Write_Error);
+ -- Write error message Msg to standard output and signal that the
+ -- elaboration order is incorrect.
+
+ -------------------------------
+ -- Build_Elaborable_Unit_Set --
+ -------------------------------
+
+ function Build_Elaborable_Unit_Set return Membership_Set is
+ Iter : Elaborable_Units_Iterator;
+ Set : Membership_Set;
+ U_Id : Unit_Id;
+
+ begin
+ Set := Create (Number_Of_Elaborable_Units);
+ Iter := Iterate_Elaborable_Units;
+ while Has_Next (Iter) loop
+ Next (Iter, U_Id);
+ pragma Assert (Present (U_Id));
+
+ Insert (Set, U_Id);
+ end loop;
+
+ return Set;
+ end Build_Elaborable_Unit_Set;
+
+ --------------------------------
+ -- Report_Missing_Elaboration --
+ --------------------------------
+
+ procedure Report_Missing_Elaboration (U_Id : Unit_Id) is
+ Msg : constant String := "Report_Missing_Elaboration";
+
+ begin
+ pragma Assert (Present (U_Id));
+ Write_Error (Msg);
+
+ Write_Str ("unit (U_Id_");
+ Write_Int (Int (U_Id));
+ Write_Str (") name = ");
+ Write_Name (Name (U_Id));
+ Write_Str (" must be elaborated");
+ Write_Eol;
+ end Report_Missing_Elaboration;
+
+ ---------------------------------
+ -- Report_Missing_Elaborations --
+ ---------------------------------
+
+ procedure Report_Missing_Elaborations (Set : Membership_Set) is
+ Iter : Iterator;
+ U_Id : Unit_Id;
+
+ begin
+ Iter := Iterate (Set);
+ while Has_Next (Iter) loop
+ Next (Iter, U_Id);
+ pragma Assert (Present (U_Id));
+
+ Report_Missing_Elaboration (U_Id);
+ end loop;
+ end Report_Missing_Elaborations;
+
+ ---------------------------------
+ -- Report_Spurious_Elaboration --
+ ---------------------------------
+
+ procedure Report_Spurious_Elaboration (U_Id : Unit_Id) is
+ Msg : constant String := "Report_Spurious_Elaboration";
+
+ begin
+ pragma Assert (Present (U_Id));
+ Write_Error (Msg);
+
+ Write_Str ("unit (U_Id_");
+ Write_Int (Int (U_Id));
+ Write_Str (") name = ");
+ Write_Name (Name (U_Id));
+ Write_Str (" must not be elaborated");
+ end Report_Spurious_Elaboration;
+
+ --------------------------------
+ -- Validate_Elaboration_Order --
+ --------------------------------
+
+ procedure Validate_Elaboration_Order (Order : Unit_Id_Table) is
+ begin
+ -- Nothing to do when switch -d_V (validate bindo graphs and order)
+ -- is not in effect.
+
+ if not Debug_Flag_Underscore_VV then
+ return;
+ end if;
+
+ Validate_Units (Order);
+
+ if Has_Invalid_Data then
+ raise Invalid_Elaboration_Order;
+ end if;
+ end Validate_Elaboration_Order;
+
+ -------------------
+ -- Validate_Unit --
+ -------------------
+
+ procedure Validate_Unit (U_Id : Unit_Id; Elab_Set : Membership_Set) is
+ begin
+ pragma Assert (Present (U_Id));
+
+ -- The current unit in the elaboration order appears within the set
+ -- of units that require elaboration. Remove it from the set.
+
+ if Contains (Elab_Set, U_Id) then
+ Delete (Elab_Set, U_Id);
+
+ -- Otherwise the current unit in the elaboration order must not be
+ -- elaborated.
+
+ else
+ Report_Spurious_Elaboration (U_Id);
+ end if;
+ end Validate_Unit;
+
+ --------------------
+ -- Validate_Units --
+ --------------------
+
+ procedure Validate_Units (Order : Unit_Id_Table) is
+ Elab_Set : Membership_Set;
+
+ begin
+ -- Collect all units in the compilation that need to be elaborated
+ -- in a set.
+
+ Elab_Set := Build_Elaborable_Unit_Set;
+
+ -- Validate each unit in the elaboration order against the set of
+ -- units that need to be elaborated.
+
+ for Index in Unit_Id_Tables.First .. Unit_Id_Tables.Last (Order) loop
+ Validate_Unit
+ (U_Id => Order.Table (Index),
+ Elab_Set => Elab_Set);
+ end loop;
+
+ -- At this point all units that need to be elaborated should have
+ -- been eliminated from the set. Report any units that are missing
+ -- their elaboration.
+
+ Report_Missing_Elaborations (Elab_Set);
+ Destroy (Elab_Set);
+ end Validate_Units;
+
+ -----------------
+ -- Write_Error --
+ -----------------
+
+ procedure Write_Error (Msg : String) is
+ begin
+ Has_Invalid_Data := True;
+
+ Write_Str ("ERROR: ");
+ Write_Str (Msg);
+ Write_Eol;
+ end Write_Error;
+ end Elaboration_Order_Validators;
+
+ ---------------------------------
+ -- Invocation_Graph_Validators --
+ ---------------------------------
+
+ package body Invocation_Graph_Validators is
+ Has_Invalid_Data : Boolean := False;
+ -- Flag set when the invocation graph contains invalid data
+
+ -----------------------
+ -- Local subprograms --
+ -----------------------
+
+ procedure Validate_Invocation_Graph_Edge
+ (G : Invocation_Graph;
+ IGE_Id : Invocation_Graph_Edge_Id);
+ pragma Inline (Validate_Invocation_Graph_Edge);
+ -- Verify that the attributes of edge IGE_Id of invocation graph G are
+ -- properly set.
+
+ procedure Validate_Invocation_Graph_Edges (G : Invocation_Graph);
+ pragma Inline (Validate_Invocation_Graph_Edges);
+ -- Verify that the attributes of all edges of invocation graph G are
+ -- properly set.
+
+ procedure Validate_Invocation_Graph_Vertex
+ (G : Invocation_Graph;
+ IGV_Id : Invocation_Graph_Vertex_Id);
+ pragma Inline (Validate_Invocation_Graph_Vertex);
+ -- Verify that the attributes of vertex IGV_Id of inbocation graph G are
+ -- properly set.
+
+ procedure Validate_Invocation_Graph_Vertices (G : Invocation_Graph);
+ pragma Inline (Validate_Invocation_Graph_Vertices);
+ -- Verify that the attributes of all vertices of invocation graph G are
+ -- properly set.
+
+ procedure Write_Error (Msg : String);
+ pragma Inline (Write_Error);
+ -- Write error message Msg to standard output and signal that the
+ -- invocation graph is incorrect.
+
+ -------------------------------
+ -- Validate_Invocation_Graph --
+ -------------------------------
+
+ procedure Validate_Invocation_Graph (G : Invocation_Graph) is
+ begin
+ pragma Assert (Present (G));
+
+ -- Nothing to do when switch -d_V (validate bindo graphs and order)
+ -- is not in effect.
+
+ if not Debug_Flag_Underscore_VV then
+ return;
+ end if;
+
+ Validate_Invocation_Graph_Vertices (G);
+ Validate_Invocation_Graph_Edges (G);
+
+ if Has_Invalid_Data then
+ raise Invalid_Invocation_Graph;
+ end if;
+ end Validate_Invocation_Graph;
+
+ ------------------------------------
+ -- Validate_Invocation_Graph_Edge --
+ ------------------------------------
+
+ procedure Validate_Invocation_Graph_Edge
+ (G : Invocation_Graph;
+ IGE_Id : Invocation_Graph_Edge_Id)
+ is
+ Msg : constant String := "Validate_Invocation_Graph_Edge";
+
+ begin
+ pragma Assert (Present (G));
+
+ if not Present (IGE_Id) then
+ Write_Error (Msg);
+
+ Write_Str (" emply invocation graph edge");
+ Write_Eol;
+ Write_Eol;
+ return;
+ end if;
+
+ if not Present (Relation (G, IGE_Id)) then
+ Write_Error (Msg);
+
+ Write_Str (" invocation graph edge (IGE_Id_");
+ Write_Int (Int (IGE_Id));
+ Write_Str (") lacks Relation");
+ Write_Eol;
+ Write_Eol;
+ end if;
+
+ if not Present (Target (G, IGE_Id)) then
+ Write_Error (Msg);
+
+ Write_Str (" invocation graph edge (IGE_Id_");
+ Write_Int (Int (IGE_Id));
+ Write_Str (") lacks Target");
+ Write_Eol;
+ Write_Eol;
+ end if;
+ end Validate_Invocation_Graph_Edge;
+
+ -------------------------------------
+ -- Validate_Invocation_Graph_Edges --
+ -------------------------------------
+
+ procedure Validate_Invocation_Graph_Edges (G : Invocation_Graph) is
+ IGE_Id : Invocation_Graph_Edge_Id;
+ Iter : Invocation_Graphs.All_Edge_Iterator;
+
+ begin
+ pragma Assert (Present (G));
+
+ Iter := Iterate_All_Edges (G);
+ while Has_Next (Iter) loop
+ Next (Iter, IGE_Id);
+
+ Validate_Invocation_Graph_Edge (G, IGE_Id);
+ end loop;
+ end Validate_Invocation_Graph_Edges;
+
+ --------------------------------------
+ -- Validate_Invocation_Graph_Vertex --
+ --------------------------------------
+
+ procedure Validate_Invocation_Graph_Vertex
+ (G : Invocation_Graph;
+ IGV_Id : Invocation_Graph_Vertex_Id)
+ is
+ Msg : constant String := "Validate_Invocation_Graph_Vertex";
+
+ begin
+ pragma Assert (Present (G));
+
+ if not Present (IGV_Id) then
+ Write_Error (Msg);
+
+ Write_Str (" emply invocation graph vertex");
+ Write_Eol;
+ Write_Eol;
+ return;
+ end if;
+
+ if not Present (Construct (G, IGV_Id)) then
+ Write_Error (Msg);
+
+ Write_Str (" invocation graph vertex (IGV_Id_");
+ Write_Int (Int (IGV_Id));
+ Write_Str (") lacks Construct");
+ Write_Eol;
+ Write_Eol;
+ end if;
+
+ if not Present (Lib_Vertex (G, IGV_Id)) then
+ Write_Error (Msg);
+
+ Write_Str (" invocation graph vertex (IGV_Id_");
+ Write_Int (Int (IGV_Id));
+ Write_Str (") lacks Lib_Vertex");
+ Write_Eol;
+ Write_Eol;
+ end if;
+ end Validate_Invocation_Graph_Vertex;
+
+ ----------------------------------------
+ -- Validate_Invocation_Graph_Vertices --
+ ----------------------------------------
+
+ procedure Validate_Invocation_Graph_Vertices (G : Invocation_Graph) is
+ IGV_Id : Invocation_Graph_Vertex_Id;
+ Iter : Invocation_Graphs.All_Vertex_Iterator;
+
+ begin
+ pragma Assert (Present (G));
+
+ Iter := Iterate_All_Vertices (G);
+ while Has_Next (Iter) loop
+ Next (Iter, IGV_Id);
+
+ Validate_Invocation_Graph_Vertex (G, IGV_Id);
+ end loop;
+ end Validate_Invocation_Graph_Vertices;
+
+ -----------------
+ -- Write_Error --
+ -----------------
+
+ procedure Write_Error (Msg : String) is
+ begin
+ Has_Invalid_Data := True;
+
+ Write_Str ("ERROR: ");
+ Write_Str (Msg);
+ Write_Eol;
+ end Write_Error;
+ end Invocation_Graph_Validators;
+
+ ------------------------------
+ -- Library_Graph_Validators --
+ ------------------------------
+
+ package body Library_Graph_Validators is
+ Has_Invalid_Data : Boolean := False;
+ -- Flag set when the library graph contains invalid data
+
+ -----------------------
+ -- Local subprograms --
+ -----------------------
+
+ procedure Validate_Library_Graph_Edge
+ (G : Library_Graph;
+ LGE_Id : Library_Graph_Edge_Id);
+ pragma Inline (Validate_Library_Graph_Edge);
+ -- Verify that the attributes of edge LGE_Id of library graph G are
+ -- properly set.
+
+ procedure Validate_Library_Graph_Edges (G : Library_Graph);
+ pragma Inline (Validate_Library_Graph_Edges);
+ -- Verify that the attributes of all edges of library graph G are
+ -- properly set.
+
+ procedure Validate_Library_Graph_Vertex
+ (G : Library_Graph;
+ LGV_Id : Library_Graph_Vertex_Id);
+ pragma Inline (Validate_Library_Graph_Vertex);
+ -- Verify that the attributes of vertex LGV_Id of library graph G are
+ -- properly set.
+
+ procedure Validate_Library_Graph_Vertices (G : Library_Graph);
+ pragma Inline (Validate_Library_Graph_Vertices);
+ -- Verify that the attributes of all vertices of library graph G are
+ -- properly set.
+
+ procedure Write_Error (Msg : String);
+ pragma Inline (Write_Error);
+ -- Write error message Msg to standard output and signal that the
+ -- library graph is incorrect.
+
+ ----------------------------
+ -- Validate_Library_Graph --
+ ----------------------------
+
+ procedure Validate_Library_Graph (G : Library_Graph) is
+ begin
+ pragma Assert (Present (G));
+
+ -- Nothing to do when switch -d_V (validate bindo graphs and order)
+ -- is not in effect.
+
+ if not Debug_Flag_Underscore_VV then
+ return;
+ end if;
+
+ Validate_Library_Graph_Vertices (G);
+ Validate_Library_Graph_Edges (G);
+
+ if Has_Invalid_Data then
+ raise Invalid_Library_Graph;
+ end if;
+ end Validate_Library_Graph;
+
+ ---------------------------------
+ -- Validate_Library_Graph_Edge --
+ ---------------------------------
+
+ procedure Validate_Library_Graph_Edge
+ (G : Library_Graph;
+ LGE_Id : Library_Graph_Edge_Id)
+ is
+ Msg : constant String := "Validate_Library_Graph_Edge";
+
+ begin
+ pragma Assert (Present (G));
+
+ if not Present (LGE_Id) then
+ Write_Error (Msg);
+
+ Write_Str (" emply library graph edge");
+ Write_Eol;
+ Write_Eol;
+ return;
+ end if;
+
+ if Kind (G, LGE_Id) = No_Edge then
+ Write_Error (Msg);
+
+ Write_Str (" library graph edge (LGE_Id_");
+ Write_Int (Int (LGE_Id));
+ Write_Str (") is not a valid edge");
+ Write_Eol;
+ Write_Eol;
+
+ elsif Kind (G, LGE_Id) = Body_Before_Spec_Edge then
+ Write_Error (Msg);
+
+ Write_Str (" library graph edge (LGE_Id_");
+ Write_Int (Int (LGE_Id));
+ Write_Str (") is a Body_Before_Spec edge");
+ Write_Eol;
+ Write_Eol;
+ end if;
+
+ if not Present (Predecessor (G, LGE_Id)) then
+ Write_Error (Msg);
+
+ Write_Str (" library graph edge (LGE_Id_");
+ Write_Int (Int (LGE_Id));
+ Write_Str (") lacks Predecessor");
+ Write_Eol;
+ Write_Eol;
+ end if;
+
+ if not Present (Successor (G, LGE_Id)) then
+ Write_Error (Msg);
+
+ Write_Str (" library graph edge (LGE_Id_");
+ Write_Int (Int (LGE_Id));
+ Write_Str (") lacks Successor");
+ Write_Eol;
+ Write_Eol;
+ end if;
+ end Validate_Library_Graph_Edge;
+
+ ----------------------------------
+ -- Validate_Library_Graph_Edges --
+ ----------------------------------
+
+ procedure Validate_Library_Graph_Edges (G : Library_Graph) is
+ Iter : Library_Graphs.All_Edge_Iterator;
+ LGE_Id : Library_Graph_Edge_Id;
+
+ begin
+ pragma Assert (Present (G));
+
+ Iter := Iterate_All_Edges (G);
+ while Has_Next (Iter) loop
+ Next (Iter, LGE_Id);
+ pragma Assert (Present (LGE_Id));
+
+ Validate_Library_Graph_Edge (G, LGE_Id);
+ end loop;
+ end Validate_Library_Graph_Edges;
+
+ -----------------------------------
+ -- Validate_Library_Graph_Vertex --
+ -----------------------------------
+
+ procedure Validate_Library_Graph_Vertex
+ (G : Library_Graph;
+ LGV_Id : Library_Graph_Vertex_Id)
+ is
+ Msg : constant String := "Validate_Library_Graph_Vertex";
+
+ begin
+ pragma Assert (Present (G));
+
+ if not Present (LGV_Id) then
+ Write_Error (Msg);
+
+ Write_Str (" empty library graph vertex");
+ Write_Eol;
+ Write_Eol;
+ return;
+ end if;
+
+ if (Is_Body_With_Spec (G, LGV_Id)
+ or else
+ Is_Spec_With_Body (G, LGV_Id))
+ and then not Present (Corresponding_Item (G, LGV_Id))
+ then
+ Write_Error (Msg);
+
+ Write_Str (" library graph vertex (LGV_Id_");
+ Write_Int (Int (LGV_Id));
+ Write_Str (") lacks Corresponding_Item");
+ Write_Eol;
+ Write_Eol;
+ end if;
+
+ if not Present (Unit (G, LGV_Id)) then
+ Write_Error (Msg);
+
+ Write_Str (" library graph vertex (LGV_Id_");
+ Write_Int (Int (LGV_Id));
+ Write_Str (") lacks Unit");
+ Write_Eol;
+ Write_Eol;
+ end if;
+ end Validate_Library_Graph_Vertex;
+
+ -------------------------------------
+ -- Validate_Library_Graph_Vertices --
+ -------------------------------------
+
+ procedure Validate_Library_Graph_Vertices (G : Library_Graph) is
+ Iter : Library_Graphs.All_Vertex_Iterator;
+ LGV_Id : Library_Graph_Vertex_Id;
+
+ begin
+ pragma Assert (Present (G));
+
+ Iter := Iterate_All_Vertices (G);
+ while Has_Next (Iter) loop
+ Next (Iter, LGV_Id);
+ pragma Assert (Present (LGV_Id));
+
+ Validate_Library_Graph_Vertex (G, LGV_Id);
+ end loop;
+ end Validate_Library_Graph_Vertices;
+
+ -----------------
+ -- Write_Error --
+ -----------------
+
+ procedure Write_Error (Msg : String) is
+ begin
+ Has_Invalid_Data := True;
+
+ Write_Str ("ERROR: ");
+ Write_Str (Msg);
+ Write_Eol;
+ end Write_Error;
+ end Library_Graph_Validators;
+
+end Bindo.Validators;
diff --git a/gcc/ada/bindo-validators.ads b/gcc/ada/bindo-validators.ads
new file mode 100644
index 0000000..39fccc6
--- /dev/null
+++ b/gcc/ada/bindo-validators.ads
@@ -0,0 +1,95 @@
+------------------------------------------------------------------------------
+-- --
+-- GNAT COMPILER COMPONENTS --
+-- --
+-- B I N D O . V A L I D A T O R S --
+-- --
+-- S p e c --
+-- --
+-- Copyright (C) 2019, 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. See the GNU General Public License --
+-- for more details. You should have received a copy of the GNU General --
+-- Public License distributed with GNAT; see file COPYING3. If not, go to --
+-- http://www.gnu.org/licenses for a complete copy of the license. --
+-- --
+-- GNAT was originally developed by the GNAT team at New York University. --
+-- Extensive contributions were provided by Ada Core Technologies Inc. --
+-- --
+------------------------------------------------------------------------------
+
+-- For full architecture, see unit Bindo.
+
+-- The following unit contains facilities to verify the validity of the
+-- various graphs used in determining the elaboration order of units.
+
+with Bindo.Graphs;
+use Bindo.Graphs;
+use Bindo.Graphs.Invocation_Graphs;
+use Bindo.Graphs.Library_Graphs;
+
+package Bindo.Validators is
+
+ ----------------------------------
+ -- Elaboration_Order_Validators --
+ ----------------------------------
+
+ package Elaboration_Order_Validators is
+ Invalid_Elaboration_Order : exception;
+ -- Exception raised when the elaboration order contains invalid data
+
+ procedure Validate_Elaboration_Order (Order : Unit_Id_Table);
+ -- Ensure that elaboration order Order meets the following requirements:
+ --
+ -- * All units that must be elaborated appear in the order
+ -- * No other units appear in the order
+ --
+ -- Diagnose issues and raise Invalid_Elaboration_Order if this is not
+ -- the case.
+
+ end Elaboration_Order_Validators;
+
+ ---------------------------------
+ -- Invocation_Graph_Validators --
+ ---------------------------------
+
+ package Invocation_Graph_Validators is
+ Invalid_Invocation_Graph : exception;
+ -- Exception raised when the invocation graph contains invalid data
+
+ procedure Validate_Invocation_Graph (G : Invocation_Graph);
+ -- Ensure that invocation graph G meets the following requirements:
+ --
+ -- * All attributes of edges are properly set
+ -- * All attributes of vertices are properly set
+ --
+ -- Diagnose issues and raise Invalid_Invocation_Graph if this is not the
+ -- case.
+
+ end Invocation_Graph_Validators;
+
+ ------------------------------
+ -- Library_Graph_Validators --
+ ------------------------------
+
+ package Library_Graph_Validators is
+ Invalid_Library_Graph : exception;
+ -- Exception raised when the library graph contains invalid data
+
+ procedure Validate_Library_Graph (G : Library_Graph);
+ -- Ensure that library graph G meets the following requirements:
+ --
+ -- * All attributes edges are properly set
+ -- * All attributes of vertices are properly set
+ --
+ -- Diagnose issues and raise Invalid_Library_Graph if this is not the
+ -- case.
+
+ end Library_Graph_Validators;
+
+end Bindo.Validators;
diff --git a/gcc/ada/bindo-writers.adb b/gcc/ada/bindo-writers.adb
new file mode 100644
index 0000000..7450c15
--- /dev/null
+++ b/gcc/ada/bindo-writers.adb
@@ -0,0 +1,1333 @@
+------------------------------------------------------------------------------
+-- --
+-- GNAT COMPILER COMPONENTS --
+-- --
+-- B I N D O . W R I T E R S --
+-- --
+-- B o d y --
+-- --
+-- Copyright (C) 2019, 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. See the GNU General Public License --
+-- for more details. You should have received a copy of the GNU General --
+-- Public License distributed with GNAT; see file COPYING3. If not, go to --
+-- http://www.gnu.org/licenses for a complete copy of the license. --
+-- --
+-- GNAT was originally developed by the GNAT team at New York University. --
+-- Extensive contributions were provided by Ada Core Technologies Inc. --
+-- --
+------------------------------------------------------------------------------
+
+with Debug; use Debug;
+with Fname; use Fname;
+with Opt; use Opt;
+with Output; use Output;
+
+with Bindo.Units; use Bindo.Units;
+
+with GNAT; use GNAT;
+with GNAT.Graphs; use GNAT.Graphs;
+with GNAT.Sets; use GNAT.Sets;
+
+package body Bindo.Writers is
+
+ -----------------
+ -- ALI_Writers --
+ -----------------
+
+ package body ALI_Writers is
+
+ -----------------------
+ -- Local subprograms --
+ -----------------------
+
+ procedure Write_All_Units;
+ pragma Inline (Write_All_Units);
+ -- Write the common form of units to standard output
+
+ procedure Write_Invocation_Construct (IC_Id : Invocation_Construct_Id);
+ pragma Inline (Write_Invocation_Construct);
+ -- Write invocation construct IC_Id to standard output
+
+ procedure Write_Invocation_Relation (IR_Id : Invocation_Relation_Id);
+ pragma Inline (Write_Invocation_Relation);
+ -- Write invocation relation IR_Id to standard output
+
+ procedure Write_Invocation_Signature (IS_Id : Invocation_Signature_Id);
+ pragma Inline (Write_Invocation_Signature);
+ -- Write invocation signature IS_Id to standard output
+
+ procedure Write_Statistics;
+ pragma Inline (Write_Statistics);
+ -- Write the statistical information of units to standard output
+
+ procedure Write_Unit (U_Id : Unit_Id);
+ pragma Inline (Write_Unit);
+ -- Write the invocation constructs and relations of unit U_Id to
+ -- standard output.
+
+ procedure Write_Unit_Common (U_Id : Unit_Id);
+ pragma Inline (Write_Unit_Common);
+ -- Write the common form of unit U_Id to standard output
+
+ -----------
+ -- Debug --
+ -----------
+
+ procedure pau renames Write_All_Units;
+ pragma Unreferenced (pau);
+
+ procedure pu (U_Id : Unit_Id) renames Write_Unit_Common;
+ pragma Unreferenced (pu);
+
+ ----------------------
+ -- Write_ALI_Tables --
+ ----------------------
+
+ procedure Write_ALI_Tables is
+ begin
+ -- Nothing to do when switch -d_A (output invocation tables) is not
+ -- in effect.
+
+ if not Debug_Flag_Underscore_AA then
+ return;
+ end if;
+
+ Write_Str ("ALI Tables");
+ Write_Eol;
+ Write_Eol;
+
+ Write_Statistics;
+ For_Each_Unit (Write_Unit'Access);
+
+ Write_Str ("ALI Tables end");
+ Write_Eol;
+ Write_Eol;
+ end Write_ALI_Tables;
+
+ ---------------------
+ -- Write_All_Units --
+ ---------------------
+
+ procedure Write_All_Units is
+ begin
+ For_Each_Unit (Write_Unit_Common'Access);
+ end Write_All_Units;
+
+ --------------------------------
+ -- Write_Invocation_Construct --
+ --------------------------------
+
+ procedure Write_Invocation_Construct (IC_Id : Invocation_Construct_Id) is
+ pragma Assert (Present (IC_Id));
+
+ IC_Rec : Invocation_Construct_Record renames
+ Invocation_Constructs.Table (IC_Id);
+
+ begin
+ Write_Str (" invocation construct (IC_Id_");
+ Write_Int (Int (IC_Id));
+ Write_Str (")");
+ Write_Eol;
+
+ Write_Str (" Kind = ");
+ Write_Str (IC_Rec.Kind'Img);
+ Write_Eol;
+
+ Write_Str (" Placement = ");
+ Write_Str (IC_Rec.Placement'Img);
+ Write_Eol;
+
+ Write_Invocation_Signature (IC_Rec.Signature);
+ Write_Eol;
+ end Write_Invocation_Construct;
+
+ -------------------------------
+ -- Write_Invocation_Relation --
+ -------------------------------
+
+ procedure Write_Invocation_Relation (IR_Id : Invocation_Relation_Id) is
+ pragma Assert (Present (IR_Id));
+
+ IR_Rec : Invocation_Relation_Record renames
+ Invocation_Relations.Table (IR_Id);
+
+ begin
+ Write_Str (" invocation relation (IR_Id_");
+ Write_Int (Int (IR_Id));
+ Write_Str (")");
+ Write_Eol;
+
+ if Present (IR_Rec.Extra) then
+ Write_Str (" Extra = ");
+ Write_Name (IR_Rec.Extra);
+ else
+ Write_Str (" Extra = none");
+ end if;
+
+ Write_Eol;
+ Write_Str (" Invoker");
+ Write_Eol;
+
+ Write_Invocation_Signature (IR_Rec.Invoker);
+
+ Write_Str (" Kind = ");
+ Write_Str (IR_Rec.Kind'Img);
+ Write_Eol;
+
+ Write_Str (" Target");
+ Write_Eol;
+
+ Write_Invocation_Signature (IR_Rec.Target);
+ Write_Eol;
+ end Write_Invocation_Relation;
+
+ --------------------------------
+ -- Write_Invocation_Signature --
+ --------------------------------
+
+ procedure Write_Invocation_Signature (IS_Id : Invocation_Signature_Id) is
+ pragma Assert (Present (IS_Id));
+
+ IS_Rec : Invocation_Signature_Record renames
+ Invocation_Signatures.Table (IS_Id);
+
+ begin
+ Write_Str (" Signature (IS_Id_");
+ Write_Int (Int (IS_Id));
+ Write_Str (")");
+ Write_Eol;
+
+ Write_Str (" Column = ");
+ Write_Int (Int (IS_Rec.Column));
+ Write_Eol;
+
+ Write_Str (" Line = ");
+ Write_Int (Int (IS_Rec.Line));
+ Write_Eol;
+
+ if Present (IS_Rec.Locations) then
+ Write_Str (" Locations = ");
+ Write_Name (IS_Rec.Locations);
+ else
+ Write_Str (" Locations = none");
+ end if;
+
+ Write_Eol;
+ Write_Str (" Name = ");
+ Write_Name (IS_Rec.Name);
+ Write_Eol;
+
+ Write_Str (" Scope = ");
+ Write_Name (IS_Rec.Scope);
+ Write_Eol;
+ end Write_Invocation_Signature;
+
+ ----------------------
+ -- Write_Statistics --
+ ----------------------
+
+ procedure Write_Statistics is
+ begin
+ Write_Str ("Units : ");
+ Write_Num (Int (Number_Of_Units));
+ Write_Eol;
+
+ Write_Str ("Units to elaborate: ");
+ Write_Num (Int (Number_Of_Elaborable_Units));
+ Write_Eol;
+ Write_Eol;
+ end Write_Statistics;
+
+ ----------------
+ -- Write_Unit --
+ ----------------
+
+ procedure Write_Unit (U_Id : Unit_Id) is
+ pragma Assert (Present (U_Id));
+
+ U_Rec : Unit_Record renames ALI.Units.Table (U_Id);
+
+ begin
+ Write_Unit_Common (U_Id);
+
+ Write_Str (" First_Invocation_Construct (IC_Id_");
+ Write_Int (Int (U_Rec.First_Invocation_Construct));
+ Write_Str (")");
+ Write_Eol;
+
+ Write_Str (" Last_Invocation_Construct (IC_Id_");
+ Write_Int (Int (U_Rec.Last_Invocation_Construct));
+ Write_Str (")");
+ Write_Eol;
+
+ Write_Str (" First_Invocation_Relation (IR_Id_");
+ Write_Int (Int (U_Rec.First_Invocation_Relation));
+ Write_Str (")");
+ Write_Eol;
+
+ Write_Str (" Last_Invocation_Relation (IR_Id_");
+ Write_Int (Int (U_Rec.Last_Invocation_Relation));
+ Write_Str (")");
+ Write_Eol;
+ Write_Eol;
+
+ for IC_Id in U_Rec.First_Invocation_Construct ..
+ U_Rec.Last_Invocation_Construct
+ loop
+ Write_Invocation_Construct (IC_Id);
+ end loop;
+
+ for IR_Id in U_Rec.First_Invocation_Relation ..
+ U_Rec.Last_Invocation_Relation
+ loop
+ Write_Invocation_Relation (IR_Id);
+ end loop;
+ end Write_Unit;
+
+ -----------------------
+ -- Write_Unit_Common --
+ -----------------------
+
+ procedure Write_Unit_Common (U_Id : Unit_Id) is
+ pragma Assert (Present (U_Id));
+
+ U_Rec : Unit_Record renames ALI.Units.Table (U_Id);
+
+ begin
+ Write_Str ("unit (U_Id_");
+ Write_Int (Int (U_Id));
+ Write_Str (") name = ");
+ Write_Name (U_Rec.Uname);
+ Write_Eol;
+
+ if U_Rec.SAL_Interface then
+ Write_Str (" SAL_Interface = True");
+ Write_Eol;
+ end if;
+ end Write_Unit_Common;
+ end ALI_Writers;
+
+ -------------------------------
+ -- Elaboration_Order_Writers --
+ -------------------------------
+
+ package body Elaboration_Order_Writers is
+
+ -----------------------
+ -- Local subprograms --
+ -----------------------
+
+ procedure Write_Unit (U_Id : Unit_Id);
+ pragma Inline (Write_Unit);
+ -- Write unit U_Id to standard output
+
+ procedure Write_Units (Order : Unit_Id_Table);
+ pragma Inline (Write_Units);
+ -- Write all units found in elaboration order Order to standard output
+
+ -----------------------------
+ -- Write_Elaboration_Order --
+ -----------------------------
+
+ procedure Write_Elaboration_Order (Order : Unit_Id_Table) is
+ begin
+ -- Nothing to do when switch -d_O (output elaboration order) is not
+ -- in effect.
+
+ if not Debug_Flag_Underscore_OO then
+ return;
+ end if;
+
+ Write_Str ("Elaboration Order");
+ Write_Eol;
+ Write_Eol;
+
+ Write_Units (Order);
+
+ Write_Eol;
+ Write_Str ("Elaboration Order end");
+ Write_Eol;
+
+ Write_Eol;
+ end Write_Elaboration_Order;
+
+ ----------------
+ -- Write_Unit --
+ ----------------
+
+ procedure Write_Unit (U_Id : Unit_Id) is
+ begin
+ pragma Assert (Present (U_Id));
+
+ Write_Str ("unit (U_Id_");
+ Write_Int (Int (U_Id));
+ Write_Str (") name = ");
+ Write_Name (Name (U_Id));
+ Write_Eol;
+ end Write_Unit;
+
+ -----------------
+ -- Write_Units --
+ -----------------
+
+ procedure Write_Units (Order : Unit_Id_Table) is
+ begin
+ for Index in Unit_Id_Tables.First .. Unit_Id_Tables.Last (Order) loop
+ Write_Unit (Order.Table (Index));
+ end loop;
+ end Write_Units;
+ end Elaboration_Order_Writers;
+
+ ---------------
+ -- Indent_By --
+ ---------------
+
+ procedure Indent_By (Indent : Indentation_Level) is
+ begin
+ for Count in 1 .. Indent loop
+ Write_Char (' ');
+ end loop;
+ end Indent_By;
+
+ ------------------------------
+ -- Invocation_Graph_Writers --
+ ------------------------------
+
+ package body Invocation_Graph_Writers is
+
+ -----------------------
+ -- Local subprograms --
+ -----------------------
+
+ procedure Write_Elaboration_Root
+ (G : Invocation_Graph;
+ Root : Invocation_Graph_Vertex_Id);
+ pragma Inline (Write_Elaboration_Root);
+ -- Write elaboration root Root of invocation graph G to standard output
+
+ procedure Write_Elaboration_Roots (G : Invocation_Graph);
+ pragma Inline (Write_Elaboration_Roots);
+ -- Write all elaboration roots of invocation graph G to standard output
+
+ procedure Write_Invocation_Graph_Edge
+ (G : Invocation_Graph;
+ IGE_Id : Invocation_Graph_Edge_Id);
+ pragma Inline (Write_Invocation_Graph_Edge);
+ -- Write edge IGE_Id of invocation graph G to standard output
+
+ procedure Write_Invocation_Graph_Edges
+ (G : Invocation_Graph;
+ IGV_Id : Invocation_Graph_Vertex_Id);
+ pragma Inline (Write_Invocation_Graph_Edges);
+ -- Write all edges of invocation graph G to standard output
+
+ procedure Write_Invocation_Graph_Vertex
+ (G : Invocation_Graph;
+ IGV_Id : Invocation_Graph_Vertex_Id);
+ pragma Inline (Write_Invocation_Graph_Vertex);
+ -- Write vertex IGV_Id of invocation graph G to standard output
+
+ procedure Write_Invocation_Graph_Vertices (G : Invocation_Graph);
+ pragma Inline (Write_Invocation_Graph_Vertices);
+ -- Write all vertices of invocation graph G to standard output
+
+ procedure Write_Statistics (G : Invocation_Graph);
+ pragma Inline (Write_Statistics);
+ -- Write the statistical information of invocation graph G to standard
+ -- output.
+
+ -----------
+ -- Debug --
+ -----------
+
+ procedure pige
+ (G : Invocation_Graph;
+ IGE_Id : Invocation_Graph_Edge_Id)
+ renames Write_Invocation_Graph_Edge;
+ pragma Unreferenced (pige);
+
+ procedure pigv
+ (G : Invocation_Graph;
+ IGV_Id : Invocation_Graph_Vertex_Id)
+ renames Write_Invocation_Graph_Vertex;
+ pragma Unreferenced (pigv);
+
+ ----------------------------
+ -- Write_Elaboration_Root --
+ ----------------------------
+
+ procedure Write_Elaboration_Root
+ (G : Invocation_Graph;
+ Root : Invocation_Graph_Vertex_Id)
+ is
+ begin
+ pragma Assert (Present (G));
+ pragma Assert (Present (Root));
+
+ Write_Str ("elaboration root (IGV_Id_");
+ Write_Int (Int (Root));
+ Write_Str (") name = ");
+ Write_Name (Name (G, Root));
+ Write_Eol;
+ end Write_Elaboration_Root;
+
+ -----------------------------
+ -- Write_Elaboration_Roots --
+ -----------------------------
+
+ procedure Write_Elaboration_Roots (G : Invocation_Graph) is
+ pragma Assert (Present (G));
+
+ Num_Of_Roots : constant Natural := Number_Of_Elaboration_Roots (G);
+
+ Iter : Elaboration_Root_Iterator;
+ Root : Invocation_Graph_Vertex_Id;
+
+ begin
+ Write_Str ("Elaboration roots: ");
+ Write_Int (Int (Num_Of_Roots));
+ Write_Eol;
+
+ if Num_Of_Roots > 0 then
+ Iter := Iterate_Elaboration_Roots (G);
+ while Has_Next (Iter) loop
+ Next (Iter, Root);
+ pragma Assert (Present (Root));
+
+ Write_Elaboration_Root (G, Root);
+ end loop;
+ else
+ Write_Eol;
+ end if;
+ end Write_Elaboration_Roots;
+
+ ----------------------------
+ -- Write_Invocation_Graph --
+ ----------------------------
+
+ procedure Write_Invocation_Graph (G : Invocation_Graph) is
+ begin
+ pragma Assert (Present (G));
+
+ -- Nothing to do when switch -d_I (output invocation graph) is not in
+ -- effect.
+
+ if not Debug_Flag_Underscore_II then
+ return;
+ end if;
+
+ Write_Str ("Invocation Graph");
+ Write_Eol;
+ Write_Eol;
+
+ Write_Statistics (G);
+ Write_Invocation_Graph_Vertices (G);
+ Write_Elaboration_Roots (G);
+
+ Write_Str ("Invocation Graph end");
+ Write_Eol;
+
+ Write_Eol;
+ end Write_Invocation_Graph;
+
+ ---------------------------------
+ -- Write_Invocation_Graph_Edge --
+ ---------------------------------
+
+ procedure Write_Invocation_Graph_Edge
+ (G : Invocation_Graph;
+ IGE_Id : Invocation_Graph_Edge_Id)
+ is
+ pragma Assert (Present (G));
+ pragma Assert (Present (IGE_Id));
+
+ Targ : constant Invocation_Graph_Vertex_Id := Target (G, IGE_Id);
+
+ pragma Assert (Present (Targ));
+
+ begin
+ Write_Str (" invocation graph edge (IGE_Id_");
+ Write_Int (Int (IGE_Id));
+ Write_Str (")");
+ Write_Eol;
+
+ Write_Str (" Relation (IR_Id_");
+ Write_Int (Int (Relation (G, IGE_Id)));
+ Write_Str (")");
+ Write_Eol;
+
+ Write_Str (" Target (IGV_Id_");
+ Write_Int (Int (Targ));
+ Write_Str (") name = ");
+ Write_Name (Name (G, Targ));
+ Write_Eol;
+
+ Write_Eol;
+ end Write_Invocation_Graph_Edge;
+
+ ----------------------------------
+ -- Write_Invocation_Graph_Edges --
+ ----------------------------------
+
+ procedure Write_Invocation_Graph_Edges
+ (G : Invocation_Graph;
+ IGV_Id : Invocation_Graph_Vertex_Id)
+ is
+ pragma Assert (Present (G));
+ pragma Assert (Present (IGV_Id));
+
+ Num_Of_Edges : constant Natural :=
+ Number_Of_Edges_To_Targets (G, IGV_Id);
+
+ IGE_Id : Invocation_Graph_Edge_Id;
+ Iter : Invocation_Graphs.Edges_To_Targets_Iterator;
+
+ begin
+ Write_Str (" Edges to targets: ");
+ Write_Int (Int (Num_Of_Edges));
+ Write_Eol;
+
+ if Num_Of_Edges > 0 then
+ Iter := Iterate_Edges_To_Targets (G, IGV_Id);
+ while Has_Next (Iter) loop
+ Next (Iter, IGE_Id);
+ pragma Assert (Present (IGE_Id));
+
+ Write_Invocation_Graph_Edge (G, IGE_Id);
+ end loop;
+ else
+ Write_Eol;
+ end if;
+ end Write_Invocation_Graph_Edges;
+
+ -----------------------------------
+ -- Write_Invocation_Graph_Vertex --
+ -----------------------------------
+
+ procedure Write_Invocation_Graph_Vertex
+ (G : Invocation_Graph;
+ IGV_Id : Invocation_Graph_Vertex_Id)
+ is
+ begin
+ pragma Assert (Present (G));
+ pragma Assert (Present (IGV_Id));
+
+ Write_Str ("invocation graph vertex (IGV_Id_");
+ Write_Int (Int (IGV_Id));
+ Write_Str (") name = ");
+ Write_Name (Name (G, IGV_Id));
+ Write_Eol;
+
+ Write_Str (" Construct (IC_Id_");
+ Write_Int (Int (Construct (G, IGV_Id)));
+ Write_Str (")");
+ Write_Eol;
+
+ Write_Str (" Lib_Vertex (LGV_Id_");
+ Write_Int (Int (Lib_Vertex (G, IGV_Id)));
+ Write_Str (")");
+ Write_Eol;
+
+ Write_Invocation_Graph_Edges (G, IGV_Id);
+ end Write_Invocation_Graph_Vertex;
+
+ -------------------------------------
+ -- Write_Invocation_Graph_Vertices --
+ -------------------------------------
+
+ procedure Write_Invocation_Graph_Vertices (G : Invocation_Graph) is
+ IGV_Id : Invocation_Graph_Vertex_Id;
+ Iter : Invocation_Graphs.All_Vertex_Iterator;
+
+ begin
+ pragma Assert (Present (G));
+
+ Iter := Iterate_All_Vertices (G);
+ while Has_Next (Iter) loop
+ Next (Iter, IGV_Id);
+ pragma Assert (Present (IGV_Id));
+
+ Write_Invocation_Graph_Vertex (G, IGV_Id);
+ end loop;
+ end Write_Invocation_Graph_Vertices;
+
+ ----------------------
+ -- Write_Statistics --
+ ----------------------
+
+ procedure Write_Statistics (G : Invocation_Graph) is
+ begin
+ pragma Assert (Present (G));
+
+ Write_Str ("Edges : ");
+ Write_Num (Int (Number_Of_Edges (G)));
+ Write_Eol;
+
+ Write_Str ("Roots : ");
+ Write_Num (Int (Number_Of_Elaboration_Roots (G)));
+ Write_Eol;
+
+ Write_Str ("Vertices: ");
+ Write_Num (Int (Number_Of_Vertices (G)));
+ Write_Eol;
+ Write_Eol;
+
+ for Kind in Invocation_Kind'Range loop
+ Write_Str (" ");
+ Write_Num (Int (Invocation_Graph_Edge_Count (G, Kind)));
+ Write_Str (" - ");
+ Write_Str (Kind'Img);
+ Write_Eol;
+ end loop;
+
+ Write_Eol;
+ end Write_Statistics;
+ end Invocation_Graph_Writers;
+
+ ---------------------------
+ -- Library_Graph_Writers --
+ ---------------------------
+
+ package body Library_Graph_Writers is
+
+ -----------------------
+ -- Local subprograms --
+ -----------------------
+
+ procedure Write_Component
+ (G : Library_Graph;
+ Comp : Component_Id);
+ pragma Inline (Write_Component);
+ -- Write component Comp of library graph G to standard output
+
+ procedure Write_Component_Vertices
+ (G : Library_Graph;
+ Comp : Component_Id);
+ pragma Inline (Write_Component_Vertices);
+ -- Write all vertices of component Comp of library graph G to standard
+ -- output.
+
+ procedure Write_Components (G : Library_Graph);
+ pragma Inline (Write_Components);
+ -- Write all components of library graph G to standard output
+
+ procedure Write_Edges_To_Successors
+ (G : Library_Graph;
+ LGV_Id : Library_Graph_Vertex_Id);
+ pragma Inline (Write_Edges_To_Successors);
+ -- Write all edges to successors of predecessor LGV_Id of library graph
+ -- G to standard output.
+
+ procedure Write_Library_Graph_Edge
+ (G : Library_Graph;
+ LGE_Id : Library_Graph_Edge_Id);
+ pragma Inline (Write_Library_Graph_Edge);
+ -- Write edge LGE_Id of library graph G to standard output
+
+ procedure Write_Library_Graph_Vertex
+ (G : Library_Graph;
+ LGV_Id : Library_Graph_Vertex_Id);
+ pragma Inline (Write_Library_Graph_Vertex);
+ -- Write vertex LGV_Id of library graph G to standard output
+
+ procedure Write_Library_Graph_Vertices (G : Library_Graph);
+ pragma Inline (Write_Library_Graph_Vertices);
+ -- Write all vertices of library graph G to standard output
+
+ procedure Write_Statistics (G : Library_Graph);
+ pragma Inline (Write_Statistics);
+ -- Write the statistical information of library graph G to standard
+ -- output.
+
+ -----------
+ -- Debug --
+ -----------
+
+ procedure pc
+ (G : Library_Graph;
+ Comp : Component_Id) renames Write_Component;
+ pragma Unreferenced (pc);
+
+ procedure plge
+ (G : Library_Graph;
+ LGE_Id : Library_Graph_Edge_Id) renames Write_Library_Graph_Edge;
+ pragma Unreferenced (plge);
+
+ procedure plgv
+ (G : Library_Graph;
+ LGV_Id : Library_Graph_Vertex_Id) renames Write_Library_Graph_Vertex;
+ pragma Unreferenced (plgv);
+
+ ---------------------
+ -- Write_Component --
+ ---------------------
+
+ procedure Write_Component
+ (G : Library_Graph;
+ Comp : Component_Id)
+ is
+ begin
+ pragma Assert (Present (G));
+ pragma Assert (Present (Comp));
+
+ Write_Str ("component (Comp_");
+ Write_Int (Int (Comp));
+ Write_Str (")");
+ Write_Eol;
+
+ Write_Str (" Pending_Predecessors = ");
+ Write_Int (Int (Pending_Predecessors (G, Comp)));
+ Write_Eol;
+
+ Write_Component_Vertices (G, Comp);
+ end Write_Component;
+
+ ------------------------------
+ -- Write_Component_Vertices --
+ ------------------------------
+
+ procedure Write_Component_Vertices
+ (G : Library_Graph;
+ Comp : Component_Id)
+ is
+ Iter : Component_Vertex_Iterator;
+ LGV_Id : Library_Graph_Vertex_Id;
+
+ begin
+ pragma Assert (Present (G));
+ pragma Assert (Present (Comp));
+
+ Iter := Iterate_Component_Vertices (G, Comp);
+ while Has_Next (Iter) loop
+ Next (Iter, LGV_Id);
+ pragma Assert (Present (LGV_Id));
+
+ Write_Str (" library graph vertex (LGV_Id_");
+ Write_Int (Int (LGV_Id));
+ Write_Str (") name = ");
+ Write_Name (Name (G, LGV_Id));
+ Write_Eol;
+ end loop;
+
+ Write_Eol;
+ end Write_Component_Vertices;
+
+ ----------------------
+ -- Write_Components --
+ ----------------------
+
+ procedure Write_Components (G : Library_Graph) is
+ pragma Assert (Present (G));
+
+ Num_Of_Comps : constant Natural := Number_Of_Components (G);
+
+ Comp : Component_Id;
+ Iter : Component_Iterator;
+
+ begin
+ if Num_Of_Comps > 0 then
+ Iter := Iterate_Components (G);
+ while Has_Next (Iter) loop
+ Next (Iter, Comp);
+ pragma Assert (Present (Comp));
+
+ Write_Component (G, Comp);
+ end loop;
+ else
+ Write_Eol;
+ end if;
+ end Write_Components;
+
+ -------------------------------
+ -- Write_Edges_To_Successors --
+ -------------------------------
+
+ procedure Write_Edges_To_Successors
+ (G : Library_Graph;
+ LGV_Id : Library_Graph_Vertex_Id)
+ is
+ pragma Assert (Present (G));
+ pragma Assert (Present (LGV_Id));
+
+ Num_Of_Edges : constant Natural :=
+ Number_Of_Edges_To_Successors (G, LGV_Id);
+
+ Iter : Edges_To_Successors_Iterator;
+ LGE_Id : Library_Graph_Edge_Id;
+
+ begin
+ Write_Str (" Edges to successors: ");
+ Write_Int (Int (Num_Of_Edges));
+ Write_Eol;
+
+ if Num_Of_Edges > 0 then
+ Iter := Iterate_Edges_To_Successors (G, LGV_Id);
+ while Has_Next (Iter) loop
+ Next (Iter, LGE_Id);
+ pragma Assert (Present (LGE_Id));
+
+ Write_Library_Graph_Edge (G, LGE_Id);
+ end loop;
+ else
+ Write_Eol;
+ end if;
+ end Write_Edges_To_Successors;
+
+ -------------------------
+ -- Write_Library_Graph --
+ -------------------------
+
+ procedure Write_Library_Graph (G : Library_Graph) is
+ begin
+ pragma Assert (Present (G));
+
+ -- Nothing to do when switch -d_L (output library item graph) is not
+ -- in effect.
+
+ if not Debug_Flag_Underscore_LL then
+ return;
+ end if;
+
+ Write_Str ("Library Graph");
+ Write_Eol;
+ Write_Eol;
+
+ Write_Statistics (G);
+ Write_Library_Graph_Vertices (G);
+ Write_Components (G);
+
+ Write_Str ("Library Graph end");
+ Write_Eol;
+
+ Write_Eol;
+ end Write_Library_Graph;
+
+ ------------------------------
+ -- Write_Library_Graph_Edge --
+ ------------------------------
+
+ procedure Write_Library_Graph_Edge
+ (G : Library_Graph;
+ LGE_Id : Library_Graph_Edge_Id)
+ is
+ pragma Assert (Present (G));
+ pragma Assert (Present (LGE_Id));
+
+ Pred : constant Library_Graph_Vertex_Id := Predecessor (G, LGE_Id);
+ Succ : constant Library_Graph_Vertex_Id := Successor (G, LGE_Id);
+
+ pragma Assert (Present (Pred));
+ pragma Assert (Present (Succ));
+
+ begin
+ Write_Str (" library graph edge (LGE_Id_");
+ Write_Int (Int (LGE_Id));
+ Write_Str (")");
+ Write_Eol;
+
+ Write_Str (" Kind = ");
+ Write_Str (Kind (G, LGE_Id)'Img);
+ Write_Eol;
+
+ Write_Str (" Predecessor (LGV_Id_");
+ Write_Int (Int (Pred));
+ Write_Str (") name = ");
+ Write_Name (Name (G, Pred));
+ Write_Eol;
+
+ Write_Str (" Successor (LGV_Id_");
+ Write_Int (Int (Succ));
+ Write_Str (") name = ");
+ Write_Name (Name (G, Succ));
+ Write_Eol;
+
+ Write_Eol;
+ end Write_Library_Graph_Edge;
+
+ --------------------------------
+ -- Write_Library_Graph_Vertex --
+ --------------------------------
+
+ procedure Write_Library_Graph_Vertex
+ (G : Library_Graph;
+ LGV_Id : Library_Graph_Vertex_Id)
+ is
+ pragma Assert (Present (G));
+ pragma Assert (Present (LGV_Id));
+
+ Item : constant Library_Graph_Vertex_Id :=
+ Corresponding_Item (G, LGV_Id);
+ U_Id : constant Unit_Id := Unit (G, LGV_Id);
+
+ pragma Assert (Present (U_Id));
+
+ begin
+ Write_Str ("library graph vertex (LGV_Id_");
+ Write_Int (Int (LGV_Id));
+ Write_Str (") name = ");
+ Write_Name (Name (G, LGV_Id));
+ Write_Eol;
+
+ if Present (Item) then
+ Write_Str (" Corresponding_Item (LGV_Id_");
+ Write_Int (Int (Item));
+ Write_Str (") name = ");
+ Write_Name (Name (G, Item));
+ else
+ Write_Str (" Corresponding_Item = none");
+ end if;
+
+ Write_Eol;
+ Write_Str (" In_Elaboration_Order = ");
+
+ if In_Elaboration_Order (G, LGV_Id) then
+ Write_Str ("True");
+ else
+ Write_Str ("False");
+ end if;
+
+ Write_Eol;
+ Write_Str (" Pending_Predecessors = ");
+ Write_Int (Int (Pending_Predecessors (G, LGV_Id)));
+ Write_Eol;
+
+ Write_Str (" Component (Comp_Id_");
+ Write_Int (Int (Component (G, LGV_Id)));
+ Write_Str (")");
+ Write_Eol;
+
+ Write_Str (" Unit (U_Id_");
+ Write_Int (Int (U_Id));
+ Write_Str (") name = ");
+ Write_Name (Name (U_Id));
+ Write_Eol;
+
+ Write_Edges_To_Successors (G, LGV_Id);
+ end Write_Library_Graph_Vertex;
+
+ ----------------------------------
+ -- Write_Library_Graph_Vertices --
+ ----------------------------------
+
+ procedure Write_Library_Graph_Vertices (G : Library_Graph) is
+ Iter : Library_Graphs.All_Vertex_Iterator;
+ LGV_Id : Library_Graph_Vertex_Id;
+
+ begin
+ pragma Assert (Present (G));
+
+ Iter := Iterate_All_Vertices (G);
+ while Has_Next (Iter) loop
+ Next (Iter, LGV_Id);
+ pragma Assert (Present (LGV_Id));
+
+ Write_Library_Graph_Vertex (G, LGV_Id);
+ end loop;
+ end Write_Library_Graph_Vertices;
+
+ ----------------------
+ -- Write_Statistics --
+ ----------------------
+
+ procedure Write_Statistics (G : Library_Graph) is
+ begin
+ Write_Str ("Components: ");
+ Write_Num (Int (Number_Of_Components (G)));
+ Write_Eol;
+
+ Write_Str ("Edges : ");
+ Write_Num (Int (Number_Of_Edges (G)));
+ Write_Eol;
+
+ Write_Str ("Vertices : ");
+ Write_Num (Int (Number_Of_Vertices (G)));
+ Write_Eol;
+ Write_Eol;
+
+ for Kind in Library_Graph_Edge_Kind'Range loop
+ Write_Str (" ");
+ Write_Num (Int (Library_Graph_Edge_Count (G, Kind)));
+ Write_Str (" - ");
+ Write_Str (Kind'Img);
+ Write_Eol;
+ end loop;
+
+ Write_Eol;
+ end Write_Statistics;
+ end Library_Graph_Writers;
+
+ --------------------------
+ -- Unit_Closure_Writers --
+ --------------------------
+
+ package body Unit_Closure_Writers is
+ function Hash_File_Name (Nam : File_Name_Type) return Bucket_Range_Type;
+ pragma Inline (Hash_File_Name);
+ -- Obtain the hash value of key Nam
+
+ package FS is new Membership_Sets
+ (Element_Type => File_Name_Type,
+ "=" => "=",
+ Hash => Hash_File_Name);
+ use FS;
+
+ -----------------------
+ -- Local subprograms --
+ -----------------------
+
+ procedure Write_File_Name (Nam : File_Name_Type);
+ pragma Inline (Write_File_Name);
+ -- Write file name Nam to standard output
+
+ procedure Write_Subunit_Closure
+ (Dep : Sdep_Id;
+ Set : Membership_Set);
+ pragma Inline (Write_Subunit_Closure);
+ -- Write the subunit which corresponds to dependency Dep to standard
+ -- output if it does not appear in set Set.
+
+ procedure Write_Subunits_Closure (Set : Membership_Set);
+ pragma Inline (Write_Subunits_Closure);
+ -- Write all subunits to standard output if they do not appear in set
+ -- Set.
+
+ procedure Write_Unit_Closure
+ (U_Id : Unit_Id;
+ Set : Membership_Set);
+ pragma Inline (Write_Unit_Closure);
+ -- Write unit U_Id to standard output if it does not appear in set Set
+
+ procedure Write_Units_Closure
+ (Order : Unit_Id_Table;
+ Set : Membership_Set);
+ pragma Inline (Write_Units_Closure);
+ -- Write all units of elaboration order Order to standard output if they
+ -- do not appear in set Set.
+
+ --------------------
+ -- Hash_File_Name --
+ --------------------
+
+ function Hash_File_Name
+ (Nam : File_Name_Type) return Bucket_Range_Type
+ is
+ begin
+ pragma Assert (Present (Nam));
+
+ return Bucket_Range_Type (Nam);
+ end Hash_File_Name;
+
+ ---------------------
+ -- Write_File_Name --
+ ---------------------
+
+ procedure Write_File_Name (Nam : File_Name_Type) is
+ begin
+ pragma Assert (Present (Nam));
+
+ if not Zero_Formatting then
+ Write_Str (" ");
+ end if;
+
+ Write_Line (Get_Name_String (Nam));
+ end Write_File_Name;
+
+ ---------------------------
+ -- Write_Subunit_Closure --
+ ---------------------------
+
+ procedure Write_Subunit_Closure
+ (Dep : Sdep_Id;
+ Set : Membership_Set)
+ is
+ pragma Assert (Present (Dep));
+ pragma Assert (Present (Set));
+
+ Dep_Rec : Sdep_Record renames Sdep.Table (Dep);
+ Source : constant File_Name_Type := Dep_Rec.Sfile;
+
+ pragma Assert (Present (Source));
+
+ begin
+ -- Nothing to do when the source file has already been written
+
+ if Contains (Set, Source) then
+ return;
+
+ -- Nothing to do when the source file does not denote a non-internal
+ -- subunit.
+
+ elsif not Present (Dep_Rec.Subunit_Name)
+ or else Is_Internal_File_Name (Source)
+ then
+ return;
+ end if;
+
+ -- Mark the subunit as written
+
+ Insert (Set, Source);
+ Write_File_Name (Source);
+ end Write_Subunit_Closure;
+
+ ----------------------------
+ -- Write_Subunits_Closure --
+ ----------------------------
+
+ procedure Write_Subunits_Closure (Set : Membership_Set) is
+ begin
+ pragma Assert (Present (Set));
+
+ for Dep in Sdep.First .. Sdep.Last loop
+ Write_Subunit_Closure (Dep, Set);
+ end loop;
+ end Write_Subunits_Closure;
+
+ ------------------------
+ -- Write_Unit_Closure --
+ ------------------------
+
+ procedure Write_Unit_Closure (Order : Unit_Id_Table) is
+ Set : Membership_Set;
+
+ begin
+ -- Nothing to do when switch -R (list sources referenced in closure)
+ -- is not in effect.
+
+ if not List_Closure then
+ return;
+ end if;
+
+ if not Zero_Formatting then
+ Write_Eol;
+ Write_Line ("REFERENCED SOURCES");
+ end if;
+
+ -- Use a set to avoid writing duplicate units and subunits
+
+ Set := Create (Number_Of_Elaborable_Units);
+
+ Write_Units_Closure (Order, Set);
+ Write_Subunits_Closure (Set);
+
+ Destroy (Set);
+
+ if not Zero_Formatting then
+ Write_Eol;
+ end if;
+ end Write_Unit_Closure;
+
+ ------------------------
+ -- Write_Unit_Closure --
+ ------------------------
+
+ procedure Write_Unit_Closure
+ (U_Id : Unit_Id;
+ Set : Membership_Set)
+ is
+ pragma Assert (Present (U_Id));
+ pragma Assert (Present (Set));
+
+ U_Rec : Unit_Record renames ALI.Units.Table (U_Id);
+ Source : constant File_Name_Type := U_Rec.Sfile;
+
+ pragma Assert (Present (Source));
+
+ begin
+ -- Nothing to do when the source file has already been written
+
+ if Contains (Set, Source) then
+ return;
+
+ -- Nothing to do for internal source files unless switch -Ra (???) is
+ -- in effect.
+
+ elsif Is_Internal_File_Name (Source)
+ and then not List_Closure_All
+ then
+ return;
+ end if;
+
+ -- Mark the source file as written
+
+ Insert (Set, Source);
+ Write_File_Name (Source);
+ end Write_Unit_Closure;
+
+ -------------------------
+ -- Write_Units_Closure --
+ -------------------------
+
+ procedure Write_Units_Closure
+ (Order : Unit_Id_Table;
+ Set : Membership_Set)
+ is
+ begin
+ pragma Assert (Present (Set));
+
+ for Index in reverse Unit_Id_Tables.First ..
+ Unit_Id_Tables.Last (Order)
+ loop
+ Write_Unit_Closure
+ (U_Id => Order.Table (Index),
+ Set => Set);
+ end loop;
+ end Write_Units_Closure;
+ end Unit_Closure_Writers;
+
+ ---------------
+ -- Write_Num --
+ ---------------
+
+ procedure Write_Num
+ (Val : Int;
+ Val_Indent : Indentation_Level := Number_Column)
+ is
+ function Digits_Indentation return Indentation_Level;
+ pragma Inline (Digits_Indentation);
+ -- Determine the level of indentation the number requies in order to
+ -- be right-justified by Val_Indent.
+
+ ------------------------
+ -- Digits_Indentation --
+ ------------------------
+
+ function Digits_Indentation return Indentation_Level is
+ Indent : Indentation_Level;
+ Num : Int;
+
+ begin
+ -- Treat zero as a single digit
+
+ if Val = 0 then
+ Indent := 1;
+
+ else
+ Indent := 0;
+ Num := Val;
+
+ -- Shrink the input value by dividing it until all of its digits
+ -- are exhausted.
+
+ while Num /= 0 loop
+ Indent := Indent + 1;
+ Num := Num / 10;
+ end loop;
+ end if;
+
+ return Val_Indent - Indent;
+ end Digits_Indentation;
+
+ -- Start of processing for Write_Num
+
+ begin
+ Indent_By (Digits_Indentation);
+ Write_Int (Val);
+ end Write_Num;
+
+end Bindo.Writers;
diff --git a/gcc/ada/bindo-writers.ads b/gcc/ada/bindo-writers.ads
new file mode 100644
index 0000000..9ed598e
--- /dev/null
+++ b/gcc/ada/bindo-writers.ads
@@ -0,0 +1,125 @@
+------------------------------------------------------------------------------
+-- --
+-- GNAT COMPILER COMPONENTS --
+-- --
+-- B I N D O . W R I T E R S --
+-- --
+-- S p e c --
+-- --
+-- Copyright (C) 2019, 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. See the GNU General Public License --
+-- for more details. You should have received a copy of the GNU General --
+-- Public License distributed with GNAT; see file COPYING3. If not, go to --
+-- http://www.gnu.org/licenses for a complete copy of the license. --
+-- --
+-- GNAT was originally developed by the GNAT team at New York University. --
+-- Extensive contributions were provided by Ada Core Technologies Inc. --
+-- --
+------------------------------------------------------------------------------
+
+-- For full architecture, see unit Bindo.
+
+-- The following unit contains facilities to output the various graphs used in
+-- determining the elaboration order, as well as the elaboration order itself
+-- to standard output.
+
+with Types; use Types;
+
+with Bindo.Graphs;
+use Bindo.Graphs;
+use Bindo.Graphs.Invocation_Graphs;
+use Bindo.Graphs.Library_Graphs;
+
+package Bindo.Writers is
+
+ -----------------
+ -- Indentation --
+ -----------------
+
+ -- The following type defines the level of indentation used in various
+ -- output routines.
+
+ type Indentation_Level is new Natural;
+ No_Indentation : constant Indentation_Level := Indentation_Level'First;
+
+ Nested_Indentation : constant Indentation_Level := 2;
+ -- The level of indentation for a nested new line
+
+ Number_Column : constant Indentation_Level := 6;
+ -- The level of right justification of numbers
+
+ Step_Column : constant Indentation_Level := 4;
+ -- The level of right justification of the elaboration order step
+
+ procedure Indent_By (Indent : Indentation_Level);
+ pragma Inline (Indent_By);
+ -- Indent the current line by Indent spaces
+
+ procedure Write_Num
+ (Val : Int;
+ Val_Indent : Indentation_Level := Number_Column);
+ pragma Inline (Write_Num);
+ -- Output integer value Val in a right-justified form based on the value of
+ -- Val_Col.
+
+ -----------------
+ -- ALI_Writers --
+ -----------------
+
+ package ALI_Writers is
+ procedure Write_ALI_Tables;
+ -- Write the contents of the following tables to standard output:
+ --
+ -- * ALI.Invocation_Constructs
+ -- * ALI.Invocation_Relations
+
+ end ALI_Writers;
+
+ -------------------------------
+ -- Elaboration_Order_Writers --
+ -------------------------------
+
+ package Elaboration_Order_Writers is
+ procedure Write_Elaboration_Order (Order : Unit_Id_Table);
+ -- Write elaboration order Order to standard output
+
+ end Elaboration_Order_Writers;
+
+ ------------------------------
+ -- Invocation_Graph_Writers --
+ ------------------------------
+
+ package Invocation_Graph_Writers is
+ procedure Write_Invocation_Graph (G : Invocation_Graph);
+ -- Write invocation graph G to standard output
+
+ end Invocation_Graph_Writers;
+
+ ---------------------------
+ -- Library_Graph_Writers --
+ ---------------------------
+
+ package Library_Graph_Writers is
+ procedure Write_Library_Graph (G : Library_Graph);
+ -- Write library graph G to standard output
+
+ end Library_Graph_Writers;
+
+ --------------------------
+ -- Unit_Closure_Writers --
+ --------------------------
+
+ package Unit_Closure_Writers is
+ procedure Write_Unit_Closure (Order : Unit_Id_Table);
+ -- Write all sources in the closure of the main unit as enumerated in
+ -- elaboration order Order.
+
+ end Unit_Closure_Writers;
+
+end Bindo.Writers;
diff --git a/gcc/ada/bindo.adb b/gcc/ada/bindo.adb
new file mode 100644
index 0000000..7d26476
--- /dev/null
+++ b/gcc/ada/bindo.adb
@@ -0,0 +1,287 @@
+------------------------------------------------------------------------------
+-- --
+-- GNAT COMPILER COMPONENTS --
+-- --
+-- B I N D O --
+-- --
+-- B o d y --
+-- --
+-- Copyright (C) 2019, 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. See the GNU General Public License --
+-- for more details. You should have received a copy of the GNU General --
+-- Public License distributed with GNAT; see file COPYING3. If not, go to --
+-- http://www.gnu.org/licenses for a complete copy of the license. --
+-- --
+-- GNAT was originally developed by the GNAT team at New York University. --
+-- Extensive contributions were provided by Ada Core Technologies Inc. --
+-- --
+------------------------------------------------------------------------------
+
+with Bindo.Elaborators;
+use Bindo.Elaborators.Invocation_And_Library_Graph_Elaborators;
+
+package body Bindo is
+
+ ---------------------------------
+ -- Elaboration order mechanism --
+ ---------------------------------
+
+ -- The elaboration order (EO) mechanism implemented in this unit and its
+ -- children has the following objectives:
+ --
+ -- * Find an ordering of all library items (historically referred to as
+ -- "units") in the bind which require elaboration, taking into account:
+ --
+ -- - The dependencies between units expressed in the form of with
+ -- clauses.
+ --
+ -- - Pragmas Elaborate, Elaborate_All, Elaborate_Body, Preelaborable,
+ -- and Pure.
+ --
+ -- - The flow of execution at elaboration time.
+ --
+ -- - Additional dependencies between units supplied to the binder by
+ -- means of a file.
+ --
+ -- The high-level idea is to construct two graphs:
+ --
+ -- - Invocation graph - Models the flow of execution at elaboration
+ -- time.
+ --
+ -- - Library graph - Represents with clause and pragma dependencies
+ -- between units.
+ --
+ -- The library graph is further augmented with additional information
+ -- from the invocation graph by exploring the execution paths from a
+ -- unit with elaboration code to other external units. All strongly
+ -- connected components of the library graph are discovered. Finally,
+ -- the order is obtained via a topological sort-like algorithm which
+ -- attempts to order available units while enabling other units to be
+ -- ordered.
+ --
+ -- * Diagnose elaboration circularities between units
+ --
+ -- The library graph may contain at least one cycle, in which case no
+ -- ordering is possible.
+ --
+ -- ??? more on this later
+
+ -----------------
+ -- Terminology --
+ -----------------
+
+ -- * Component - A strongly connected component of a graph.
+ --
+ -- * Elaboration root - A special invocation construct which denotes the
+ -- elaboration procedure of a unit.
+ --
+ -- * Invocation - The act of activating a task, calling a subprogram, or
+ -- instantiating a generic.
+ --
+ -- * Invocation construct - An entry declaration, [single] protected type,
+ -- subprogram declaration, subprogram instantiation, or a [single] task
+ -- type declared in the visible, private, or body declarations of some
+ -- unit. The construct is encoded in the ALI file of the related unit.
+ --
+ -- * Invocation graph - A directed graph which models the flow of execution
+ -- at elaboration time.
+ --
+ -- - Vertices - Invocation constructs plus extra information. Certain
+ -- vertices act as elaboration roots.
+ --
+ -- - Edges - Invocation relations plus extra information.
+ --
+ -- * Invocation relation - A flow link between two invocation constructs.
+ -- This link is encoded in the ALI file of unit that houses the invoker.
+ --
+ -- * Invocation signature - A set of attributes that uniquely identify an
+ -- invocation construct within the namespace of all ALI files.
+ --
+ -- * Invoker - The source construct of an invocation relation (the caller,
+ -- instantiator, or task activator).
+ --
+ -- * Library graph - A directed graph which captures with clause and pragma
+ -- dependencies between units.
+ --
+ -- - Vertices - Units plus extra information.
+ --
+ -- - Edges - With clause, pragma, and additional dependencies between
+ -- units.
+ --
+ -- * Pending predecessor - A vertex that must be elaborated before another
+ -- vertex can be elaborated.
+ --
+ -- * Target - The destination construct of an invocation relation (the
+ -- generic, subprogram, or task type).
+
+ ------------------
+ -- Architecture --
+ ------------------
+
+ -- Find_Elaboration_Order
+ -- |
+ -- +--> Collect_Elaborable_Units
+ -- +--> Write_ALI_Tables
+ -- +--> Elaborate_Units
+ -- |
+ -- +------ | -------------- Construction phase ------------------------+
+ -- | | |
+ -- | +--> Build_Library_Graph |
+ -- | +--> Validate_Library_Graph |
+ -- | +--> Write_Library_Graph |
+ -- | | |
+ -- | +--> Build_Invocation_Graph |
+ -- | +--> Validate_Invocation_Graph |
+ -- | +--> Write_Invocation_Graph |
+ -- | | |
+ -- +------ | ----------------------------------------------------------+
+ -- |
+ -- +------ | -------------- Augmentation phase ------------------------+
+ -- | | |
+ -- | +--> Augment_Library_Graph |
+ -- | | |
+ -- +------ | ----------------------------------------------------------+
+ -- |
+ -- +------ | -------------- Ordering phase ----------------------------+
+ -- | | |
+ -- | +--> Find_Components |
+ -- | | |
+ -- | +--> Elaborate_Library_Graph |
+ -- | +--> Validate_Elaboration_Order |
+ -- | +--> Write_Elaboration_Order |
+ -- | | |
+ -- | +--> Write_Unit_Closure |
+ -- | | |
+ -- +------ | ----------------------------------------------------------+
+ -- |
+ -- +------ | -------------- Diagnostics phase -------------------------+
+ -- | | |
+ -- | +--> ??? more on this later |
+ -- | |
+ -- +-------------------------------------------------------------------+
+
+ ------------------------
+ -- Construction phase --
+ ------------------------
+
+ -- The Construction phase has the following objectives:
+ --
+ -- * Build the library graph by inspecting the ALI file of each unit that
+ -- requires elaboration.
+ --
+ -- * Validate the consistency of the library graph, only when switch -d_V
+ -- is in effect.
+ --
+ -- * Write the contents of the invocation graph in human-readable form to
+ -- standard output when switch -d_L is in effect.
+ --
+ -- * Build the invocation graph by inspecting invocation constructs and
+ -- relations in the ALI file of each unit that requires elaboration.
+ --
+ -- * Validate the consistency of the invocation graph, only when switch
+ -- -d_V is in effect.
+ --
+ -- * Write the contents of the invocation graph in human-readable form to
+ -- standard output when switch -d_I is in effect.
+
+ ------------------------
+ -- Augmentation phase --
+ ------------------------
+
+ -- The Augmentation phase has the following objectives:
+ --
+ -- * Discover transitions of the elaboration flow from a unit with an
+ -- elaboration root to other units. Augment the library graph with
+ -- extra edges for each such transition.
+
+ --------------------
+ -- Ordering phase --
+ --------------------
+
+ -- The Ordering phase has the following objectives:
+ --
+ -- * Discover all components of the library graph by treating specs and
+ -- bodies as single vertices.
+ --
+ -- * Try to order as many vertices of the library graph as possible by
+ -- peforming a topological sort based on the pending predecessors of
+ -- vertices across all components and within a single component.
+ --
+ -- * Validate the consistency of the order, only when switch -d_V is in
+ -- effect.
+ --
+ -- * Write the contents of the order in human-readable form to standard
+ -- output when switch -d_O is in effect.
+ --
+ -- * Write the sources of the order closure when switch -R is in effect.
+
+ -----------------------
+ -- Diagnostics phase --
+ -----------------------
+
+ -- ??? more on this later
+
+ --------------
+ -- Switches --
+ --------------
+
+ -- -d_A Output ALI invocation tables
+ --
+ -- GNATbind outputs the contents of ALI table Invocation_Constructs
+ -- and Invocation_Edges in textual format to standard output.
+ --
+ -- -d_I Output invocation graph
+ --
+ -- GNATbind outputs the invocation graph in text format to standard
+ -- output.
+ --
+ -- -d_L Output library graph
+ --
+ -- GNATbind outputs the library graph in textual format to standard
+ -- output.
+ --
+ -- -d_N New bindo order
+ --
+ -- GNATbind utilizes the new bindo elaboration order
+ --
+ -- -d_O Output elaboration order
+ --
+ -- GNATbind outputs the elaboration order in text format to standard
+ -- output.
+ --
+ -- -d_T Output elaboration order trace information
+ --
+ -- GNATbind outputs trace information on elaboration order activities
+ -- to standard output.
+ --
+ -- -d_V Validate bindo graphs and order
+ --
+ -- GNATbind validates the invocation graph, library graph, SCC graph
+ -- and elaboration order by detecting inconsistencies and producing
+ -- error reports.
+
+ ----------------------------------------
+ -- Debugging elaboration order issues --
+ ----------------------------------------
+
+ -- ??? more on this later
+
+ ----------------------------
+ -- Find_Elaboration_Order --
+ ----------------------------
+
+ procedure Find_Elaboration_Order
+ (Order : out Unit_Id_Table;
+ Main_Lib_File : File_Name_Type)
+ is
+ begin
+ Elaborate_Units (Order, Main_Lib_File);
+ end Find_Elaboration_Order;
+
+end Bindo;
diff --git a/gcc/ada/bindo.ads b/gcc/ada/bindo.ads
new file mode 100644
index 0000000..39cf7a4
--- /dev/null
+++ b/gcc/ada/bindo.ads
@@ -0,0 +1,44 @@
+------------------------------------------------------------------------------
+-- --
+-- GNAT COMPILER COMPONENTS --
+-- --
+-- B I N D O --
+-- --
+-- S p e c --
+-- --
+-- Copyright (C) 2019, 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. See the GNU General Public License --
+-- for more details. You should have received a copy of the GNU General --
+-- Public License distributed with GNAT; see file COPYING3. If not, go to --
+-- http://www.gnu.org/licenses for a complete copy of the license. --
+-- --
+-- GNAT was originally developed by the GNAT team at New York University. --
+-- Extensive contributions were provided by Ada Core Technologies Inc. --
+-- --
+------------------------------------------------------------------------------
+
+-- The following unit contains the main entry point into the elaboration order
+-- mechanism. See the body for details.
+
+with ALI; use ALI;
+with Namet; use Namet;
+
+package Bindo is
+
+ procedure Find_Elaboration_Order
+ (Order : out Unit_Id_Table;
+ Main_Lib_File : File_Name_Type);
+ -- Find an order of all units in the bind that need to be elaborated
+ -- such that elaboration code flow, pragmas Elaborate, Elaborate_All,
+ -- and Elaborate_Body, and with clause dependencies are all honoured.
+ -- Main_Lib_File is the argument of the bind. If a satisfactory order
+ -- exists, it is returned in Order, otherwise Unrecoverable_Error is
+ -- raised.
+
+end Bindo;
diff --git a/gcc/ada/bindusg.adb b/gcc/ada/bindusg.adb
index d4ac1b3..8c51d11 100644
--- a/gcc/ada/bindusg.adb
+++ b/gcc/ada/bindusg.adb
@@ -133,6 +133,11 @@ package body Bindusg is
Write_Line
(" -F Force checking of elaboration Flags");
+ -- Line for -G switch
+
+ Write_Line
+ (" -G Generate binder file suitable for CCG");
+
-- Line for -h switch
Write_Line
diff --git a/gcc/ada/butil.adb b/gcc/ada/butil.adb
index d0cb41c..9427ddd 100644
--- a/gcc/ada/butil.adb
+++ b/gcc/ada/butil.adb
@@ -23,10 +23,38 @@
-- --
------------------------------------------------------------------------------
+with Opt; use Opt;
with Output; use Output;
+with Unchecked_Deallocation;
+
+with GNAT; use GNAT;
+
+with System.OS_Lib; use System.OS_Lib;
package body Butil is
+ -----------------------
+ -- Local subprograms --
+ -----------------------
+
+ procedure Parse_Next_Unit_Name (Iter : in out Forced_Units_Iterator);
+ -- Parse the name of the next available unit accessible through iterator
+ -- Iter and save it in the iterator.
+
+ function Read_Forced_Elab_Order_File return String_Ptr;
+ -- Read the contents of the forced-elaboration-order file supplied to the
+ -- binder via switch -f and return them as a string. Return null if the
+ -- file is not available.
+
+ --------------
+ -- Has_Next --
+ --------------
+
+ function Has_Next (Iter : Forced_Units_Iterator) return Boolean is
+ begin
+ return Present (Iter.Unit_Name);
+ end Has_Next;
+
----------------------
-- Is_Internal_Unit --
----------------------
@@ -71,6 +99,499 @@ package body Butil is
or else (L > 4 and then B (1 .. 5) = "gnat.");
end Is_Predefined_Unit;
+ --------------------------
+ -- Iterate_Forced_Units --
+ --------------------------
+
+ function Iterate_Forced_Units return Forced_Units_Iterator is
+ Iter : Forced_Units_Iterator;
+
+ begin
+ Iter.Order := Read_Forced_Elab_Order_File;
+ Parse_Next_Unit_Name (Iter);
+
+ return Iter;
+ end Iterate_Forced_Units;
+
+ ----------
+ -- Next --
+ ----------
+
+ procedure Next
+ (Iter : in out Forced_Units_Iterator;
+ Unit_Name : out Unit_Name_Type;
+ Unit_Line : out Logical_Line_Number)
+ is
+ begin
+ if not Has_Next (Iter) then
+ raise Iterator_Exhausted;
+ end if;
+
+ Unit_Line := Iter.Unit_Line;
+ Unit_Name := Iter.Unit_Name;
+ pragma Assert (Present (Unit_Name));
+
+ Parse_Next_Unit_Name (Iter);
+ end Next;
+
+ --------------------------
+ -- Parse_Next_Unit_Name --
+ --------------------------
+
+ procedure Parse_Next_Unit_Name (Iter : in out Forced_Units_Iterator) is
+ Body_Suffix : constant String := " (body)";
+ Body_Type : constant String := "%b";
+ Body_Length : constant Positive := Body_Suffix'Length;
+ Body_Offset : constant Natural := Body_Length - 1;
+
+ Comment_Header : constant String := "--";
+ Comment_Offset : constant Natural := Comment_Header'Length - 1;
+
+ Spec_Suffix : constant String := " (spec)";
+ Spec_Type : constant String := "%s";
+ Spec_Length : constant Positive := Spec_Suffix'Length;
+ Spec_Offset : constant Natural := Spec_Length - 1;
+
+ Index : Positive renames Iter.Order_Index;
+ Line : Logical_Line_Number renames Iter.Order_Line;
+ Order : String_Ptr renames Iter.Order;
+
+ function At_Comment return Boolean;
+ pragma Inline (At_Comment);
+ -- Determine whether iterator Iter is positioned over the start of a
+ -- comment.
+
+ function At_Terminator return Boolean;
+ pragma Inline (At_Terminator);
+ -- Determine whether iterator Iter is positioned over a line terminator
+ -- character.
+
+ function At_Whitespace return Boolean;
+ pragma Inline (At_Whitespace);
+ -- Determine whether iterator Iter is positioned over a whitespace
+ -- character.
+
+ function Is_Terminator (C : Character) return Boolean;
+ pragma Inline (Is_Terminator);
+ -- Determine whether character C denotes a line terminator
+
+ function Is_Whitespace (C : Character) return Boolean;
+ pragma Inline (Is_Whitespace);
+ -- Determine whether character C denotes a whitespace
+
+ procedure Parse_Unit_Name;
+ pragma Inline (Parse_Unit_Name);
+ -- Find and parse the first available unit name
+
+ procedure Skip_Comment;
+ pragma Inline (Skip_Comment);
+ -- Skip a comment by reaching a line terminator
+
+ procedure Skip_Terminator;
+ pragma Inline (Skip_Terminator);
+ -- Skip a line terminator and deal with the logical line numbering
+
+ procedure Skip_Whitespace;
+ pragma Inline (Skip_Whitespace);
+ -- Skip whitespace
+
+ function Within_Order
+ (Low_Offset : Natural := 0;
+ High_Offset : Natural := 0) return Boolean;
+ pragma Inline (Within_Order);
+ -- Determine whether index of iterator Iter is still within the range of
+ -- the order string. Low_Offset may be used to inspect the area that is
+ -- less than the index. High_Offset may be used to inspect the area that
+ -- is greater than the index.
+
+ ----------------
+ -- At_Comment --
+ ----------------
+
+ function At_Comment return Boolean is
+ begin
+ -- The interator is over a comment when the index is positioned over
+ -- the start of a comment header.
+ --
+ -- unit (spec) -- comment
+ -- ^
+ -- Index
+
+ return
+ Within_Order (High_Offset => Comment_Offset)
+ and then Order (Index .. Index + Comment_Offset) = Comment_Header;
+ end At_Comment;
+
+ -------------------
+ -- At_Terminator --
+ -------------------
+
+ function At_Terminator return Boolean is
+ begin
+ return Within_Order and then Is_Terminator (Order (Index));
+ end At_Terminator;
+
+ -------------------
+ -- At_Whitespace --
+ -------------------
+
+ function At_Whitespace return Boolean is
+ begin
+ return Within_Order and then Is_Whitespace (Order (Index));
+ end At_Whitespace;
+
+ -------------------
+ -- Is_Terminator --
+ -------------------
+
+ function Is_Terminator (C : Character) return Boolean is
+ begin
+ -- Carriage return is treated intentionally as whitespace since it
+ -- appears only on certain targets, while line feed is consistent on
+ -- all of them.
+
+ return C = ASCII.LF;
+ end Is_Terminator;
+
+ -------------------
+ -- Is_Whitespace --
+ -------------------
+
+ function Is_Whitespace (C : Character) return Boolean is
+ begin
+ return
+ C = ' '
+ or else C = ASCII.CR -- carriage return
+ or else C = ASCII.FF -- form feed
+ or else C = ASCII.HT -- horizontal tab
+ or else C = ASCII.VT; -- vertical tab
+ end Is_Whitespace;
+
+ ---------------------
+ -- Parse_Unit_Name --
+ ---------------------
+
+ procedure Parse_Unit_Name is
+ pragma Assert (not At_Comment);
+ pragma Assert (not At_Terminator);
+ pragma Assert (not At_Whitespace);
+ pragma Assert (Within_Order);
+
+ procedure Find_End_Index_Of_Unit_Name;
+ pragma Inline (Find_End_Index_Of_Unit_Name);
+ -- Position the index of iterator Iter at the last character of the
+ -- first available unit name.
+
+ ---------------------------------
+ -- Find_End_Index_Of_Unit_Name --
+ ---------------------------------
+
+ procedure Find_End_Index_Of_Unit_Name is
+ begin
+ -- At this point the index points at the start of a unit name. The
+ -- unit name may be legal, in which case it appears as:
+ --
+ -- unit (body)
+ --
+ -- However, it may also be illegal:
+ --
+ -- unit without suffix
+ -- unit with multiple prefixes (spec)
+ --
+ -- In order to handle both forms, find the construct following the
+ -- unit name. This is either a comment, a terminator, or the end
+ -- of the order:
+ --
+ -- unit (body) -- comment
+ -- unit without suffix <terminator>
+ -- unit with multiple prefixes (spec)<end of order>
+ --
+ -- Once the construct is found, truncate the unit name by skipping
+ -- all white space between the construct and the end of the unit
+ -- name.
+
+ -- Find the construct that follows the unit name
+
+ while Within_Order loop
+ if At_Comment then
+ exit;
+
+ elsif At_Terminator then
+ exit;
+ end if;
+
+ Index := Index + 1;
+ end loop;
+
+ -- Position the index prior to the construct that follows the unit
+ -- name.
+
+ Index := Index - 1;
+
+ -- Truncate towards the end of the unit name
+
+ while Within_Order loop
+ if At_Whitespace then
+ Index := Index - 1;
+ else
+ exit;
+ end if;
+ end loop;
+ end Find_End_Index_Of_Unit_Name;
+
+ -- Local variables
+
+ Start_Index : constant Positive := Index;
+
+ End_Index : Positive;
+ Is_Body : Boolean := False;
+ Is_Spec : Boolean := False;
+
+ -- Start of processing for Parse_Unit_Name
+
+ begin
+ Find_End_Index_Of_Unit_Name;
+ End_Index := Index;
+
+ pragma Assert (Start_Index <= End_Index);
+
+ -- At this point the indices are positioned as follows:
+ --
+ -- End_Index
+ -- Index
+ -- v
+ -- unit (spec) -- comment
+ -- ^
+ -- Start_Index
+
+ -- Rewind the index, skipping over the legal suffixes
+ --
+ -- Index End_Index
+ -- v v
+ -- unit (spec) -- comment
+ -- ^
+ -- Start_Index
+
+ if Within_Order (Low_Offset => Body_Offset)
+ and then Order (Index - Body_Offset .. Index) = Body_Suffix
+ then
+ Is_Body := True;
+ Index := Index - Body_Length;
+
+ elsif Within_Order (Low_Offset => Spec_Offset)
+ and then Order (Index - Spec_Offset .. Index) = Spec_Suffix
+ then
+ Is_Spec := True;
+ Index := Index - Spec_Length;
+ end if;
+
+ -- Capture the line where the unit name is defined
+
+ Iter.Unit_Line := Line;
+
+ -- Transform the unit name to match the format recognized by the
+ -- name table.
+
+ if Is_Body then
+ Iter.Unit_Name :=
+ Name_Find (Order (Start_Index .. Index) & Body_Type);
+
+ elsif Is_Spec then
+ Iter.Unit_Name :=
+ Name_Find (Order (Start_Index .. Index) & Spec_Type);
+
+ -- Otherwise the unit name is illegal, so leave it as is
+
+ else
+ Iter.Unit_Name := Name_Find (Order (Start_Index .. Index));
+ end if;
+
+ -- Advance the index past the unit name
+ --
+ -- End_IndexIndex
+ -- vv
+ -- unit (spec) -- comment
+ -- ^
+ -- Start_Index
+
+ Index := End_Index + 1;
+ end Parse_Unit_Name;
+
+ ------------------
+ -- Skip_Comment --
+ ------------------
+
+ procedure Skip_Comment is
+ begin
+ pragma Assert (At_Comment);
+
+ while Within_Order loop
+ if At_Terminator then
+ exit;
+ end if;
+
+ Index := Index + 1;
+ end loop;
+ end Skip_Comment;
+
+ ---------------------
+ -- Skip_Terminator --
+ ---------------------
+
+ procedure Skip_Terminator is
+ begin
+ pragma Assert (At_Terminator);
+
+ Index := Index + 1;
+ Line := Line + 1;
+ end Skip_Terminator;
+
+ ---------------------
+ -- Skip_Whitespace --
+ ---------------------
+
+ procedure Skip_Whitespace is
+ begin
+ while Within_Order loop
+ if At_Whitespace then
+ Index := Index + 1;
+ else
+ exit;
+ end if;
+ end loop;
+ end Skip_Whitespace;
+
+ ------------------
+ -- Within_Order --
+ ------------------
+
+ function Within_Order
+ (Low_Offset : Natural := 0;
+ High_Offset : Natural := 0) return Boolean
+ is
+ begin
+ return
+ Order /= null
+ and then Index - Low_Offset >= Order'First
+ and then Index + High_Offset <= Order'Last;
+ end Within_Order;
+
+ -- Start of processing for Parse_Next_Unit_Name
+
+ begin
+ -- A line in the forced-elaboration-order file has the following
+ -- grammar:
+ --
+ -- LINE ::=
+ -- [WHITESPACE] UNIT_NAME [WHITESPACE] [COMMENT] TERMINATOR
+ --
+ -- WHITESPACE ::=
+ -- <any whitespace character>
+ -- | <carriage return>
+ --
+ -- UNIT_NAME ::=
+ -- UNIT_PREFIX [WHITESPACE] UNIT_SUFFIX
+ --
+ -- UNIT_PREFIX ::=
+ -- <any string>
+ --
+ -- UNIT_SUFFIX ::=
+ -- (body)
+ -- | (spec)
+ --
+ -- COMMENT ::=
+ -- -- <any string>
+ --
+ -- TERMINATOR ::=
+ -- <line feed>
+ -- <end of file>
+ --
+ -- Items in <> brackets are semantic notions
+
+ -- Assume that the order has no remaining units
+
+ Iter.Unit_Line := No_Line_Number;
+ Iter.Unit_Name := No_Unit_Name;
+
+ -- Try to find the first available unit name from the current position
+ -- of iteration.
+
+ while Within_Order loop
+ Skip_Whitespace;
+
+ if At_Comment then
+ Skip_Comment;
+
+ elsif not Within_Order then
+ exit;
+
+ elsif At_Terminator then
+ Skip_Terminator;
+
+ else
+ Parse_Unit_Name;
+ exit;
+ end if;
+ end loop;
+ end Parse_Next_Unit_Name;
+
+ ---------------------------------
+ -- Read_Forced_Elab_Order_File --
+ ---------------------------------
+
+ function Read_Forced_Elab_Order_File return String_Ptr is
+ procedure Free is new Unchecked_Deallocation (String, String_Ptr);
+
+ Descr : File_Descriptor;
+ Len : Natural;
+ Len_Read : Natural;
+ Result : String_Ptr;
+ Success : Boolean;
+
+ begin
+ if Force_Elab_Order_File = null then
+ return null;
+ end if;
+
+ -- Obtain and sanitize a descriptor to the elaboration-order file
+
+ Descr := Open_Read (Force_Elab_Order_File.all, Binary);
+
+ if Descr = Invalid_FD then
+ return null;
+ end if;
+
+ -- Determine the size of the file, allocate a result large enough to
+ -- house its contents, and read it.
+
+ Len := Natural (File_Length (Descr));
+
+ if Len = 0 then
+ return null;
+ end if;
+
+ Result := new String (1 .. Len);
+ Len_Read := Read (Descr, Result (1)'Address, Len);
+
+ -- The read failed to acquire the whole content of the file
+
+ if Len_Read /= Len then
+ Free (Result);
+ return null;
+ end if;
+
+ Close (Descr, Success);
+
+ -- The file failed to close
+
+ if not Success then
+ Free (Result);
+ return null;
+ end if;
+
+ return Result;
+ end Read_Forced_Elab_Order_File;
+
----------------
-- Uname_Less --
----------------
diff --git a/gcc/ada/butil.ads b/gcc/ada/butil.ads
index 80eb2a5..3ce2f1e 100644
--- a/gcc/ada/butil.ads
+++ b/gcc/ada/butil.ads
@@ -23,12 +23,13 @@
-- --
------------------------------------------------------------------------------
+-- This package contains utility routines for the binder
+
with Namet; use Namet;
+with Types; use Types;
package Butil is
--- This package contains utility routines for the binder
-
function Is_Predefined_Unit return Boolean;
-- Given a unit name stored in Name_Buffer with length in Name_Len,
-- returns True if this is the name of a predefined unit or a child of
@@ -51,4 +52,52 @@ package Butil is
-- Output unit name with (body) or (spec) after as required. On return
-- Name_Len is set to the number of characters which were output.
+ ---------------
+ -- Iterators --
+ ---------------
+
+ -- The following type represents an iterator over all units that are
+ -- specified in the forced-elaboration-order file supplied by the binder
+ -- via switch -f.
+
+ type Forced_Units_Iterator is private;
+
+ function Has_Next (Iter : Forced_Units_Iterator) return Boolean;
+ pragma Inline (Has_Next);
+ -- Determine whether iterator Iter has more units to examine
+
+ function Iterate_Forced_Units return Forced_Units_Iterator;
+ pragma Inline (Iterate_Forced_Units);
+ -- Obtain an iterator over all units in the forced-elaboration-order file
+
+ procedure Next
+ (Iter : in out Forced_Units_Iterator;
+ Unit_Name : out Unit_Name_Type;
+ Unit_Line : out Logical_Line_Number);
+ pragma Inline (Next);
+ -- Return the current unit referenced by iterator Iter along with the
+ -- line number it appears on, and advance to the next available unit.
+
+private
+ First_Line_Number : constant Logical_Line_Number := No_Line_Number + 1;
+
+ type Forced_Units_Iterator is record
+ Order : String_Ptr := null;
+ -- A reference to the contents of the forced-elaboration-order file,
+ -- read in as a string.
+
+ Order_Index : Positive := 1;
+ -- Index into the order string
+
+ Order_Line : Logical_Line_Number := First_Line_Number;
+ -- Logical line number within the order string
+
+ Unit_Line : Logical_Line_Number := No_Line_Number;
+ -- The logical line number of the current unit name within the order
+ -- string.
+
+ Unit_Name : Unit_Name_Type := No_Unit_Name;
+ -- The current unit name parsed from the order string
+ end record;
+
end Butil;
diff --git a/gcc/ada/checks.adb b/gcc/ada/checks.adb
index fcfaec7..33fb27e 100644
--- a/gcc/ada/checks.adb
+++ b/gcc/ada/checks.adb
@@ -7429,6 +7429,19 @@ package body Checks is
return;
end if;
+ -- Entities declared in Lock_free protected types must be treated as
+ -- volatile, and we must inhibit validity checks to prevent improper
+ -- constant folding.
+
+ if Is_Entity_Name (Expr)
+ and then Is_Subprogram (Scope (Entity (Expr)))
+ and then Present (Protected_Subprogram (Scope (Entity (Expr))))
+ and then Uses_Lock_Free
+ (Scope (Protected_Subprogram (Scope (Entity (Expr)))))
+ then
+ return;
+ end if;
+
-- If we have a checked conversion, then validity check applies to
-- the expression inside the conversion, not the result, since if
-- the expression inside is valid, then so is the conversion result.
diff --git a/gcc/ada/debug.adb b/gcc/ada/debug.adb
index e43174c..d76d93d 100644
--- a/gcc/ada/debug.adb
+++ b/gcc/ada/debug.adb
@@ -177,8 +177,8 @@ package body Debug is
-- d_C
-- d_D
-- d_E
- -- d_F
- -- d_G
+ -- d_F Encode full invocation paths in ALI files
+ -- d_G Encode invocation graph in ALI files
-- d_H
-- d_I
-- d_J
@@ -191,7 +191,7 @@ package body Debug is
-- d_Q
-- d_R
-- d_S
- -- d_T
+ -- d_T Output trace information on invocation path recording
-- d_U
-- d_V
-- d_W
@@ -258,6 +258,160 @@ package body Debug is
-- dy
-- dz
+ -- dA
+ -- dB
+ -- dC
+ -- dD
+ -- dE
+ -- dF
+ -- dG
+ -- dH
+ -- dI
+ -- dJ
+ -- dK
+ -- dL
+ -- dM
+ -- dN
+ -- dO
+ -- dP
+ -- dQ
+ -- dR
+ -- dS
+ -- dT
+ -- dU
+ -- dV
+ -- dW
+ -- dX
+ -- dY
+ -- dZ
+
+ -- d.a
+ -- d.b
+ -- d.c
+ -- d.d
+ -- d.e
+ -- d.f
+ -- d.g
+ -- d.h
+ -- d.i
+ -- d.j
+ -- d.k
+ -- d.l
+ -- d.m
+ -- d.n
+ -- d.o
+ -- d.p
+ -- d.q
+ -- d.r
+ -- d.s
+ -- d.t
+ -- d.u
+ -- d.v
+ -- d.w
+ -- d.x
+ -- d.y
+ -- d.z
+
+ -- d.A
+ -- d.B
+ -- d.C
+ -- d.D
+ -- d.E
+ -- d.F
+ -- d.G
+ -- d.H
+ -- d.I
+ -- d.J
+ -- d.K
+ -- d.L
+ -- d.M
+ -- d.N
+ -- d.O
+ -- d.P
+ -- d.Q
+ -- d.R
+ -- d.S
+ -- d.T
+ -- d.U
+ -- d.V
+ -- d.W
+ -- d.X
+ -- d.Y
+ -- d.Z
+
+ -- d.1
+ -- d.2
+ -- d.3
+ -- d.4
+ -- d.5
+ -- d.6
+ -- d.7
+ -- d.8
+ -- d.9
+
+ -- d_a
+ -- d_b
+ -- d_c
+ -- d_d
+ -- d_e
+ -- d_f
+ -- d_g
+ -- d_h
+ -- d_i
+ -- d_j
+ -- d_k
+ -- d_l
+ -- d_m
+ -- d_n
+ -- d_o
+ -- d_p
+ -- d_q
+ -- d_r
+ -- d_s
+ -- d_t
+ -- d_u
+ -- d_v
+ -- d_w
+ -- d_x
+ -- d_y
+ -- d_z
+
+ -- d_A Output ALI invocation tables
+ -- d_B
+ -- d_C
+ -- d_D
+ -- d_F
+ -- d_G
+ -- d_H
+ -- d_I Output invocation graph
+ -- d_J
+ -- d_K
+ -- d_L Output library graph
+ -- d_M
+ -- d_N New bindo order
+ -- d_O Output elaboration order
+ -- d_P
+ -- d_Q
+ -- d_R
+ -- d_S
+ -- d_T Output elaboration order trace information
+ -- d_U
+ -- d_V Validate bindo graphs and order
+ -- d_W
+ -- d_X
+ -- d_Y
+ -- d_Z
+
+ -- d_1
+ -- d_2
+ -- d_3
+ -- d_4
+ -- d_5
+ -- d_6
+ -- d_7
+ -- d_8
+ -- d_9
+
-- Debug flags used in package Make and its clients (e.g. GNATMAKE)
-- da
@@ -850,11 +1004,21 @@ package body Debug is
-- d_A Do not generate ALI files by setting Opt.Disable_ALI_File.
+ -- d_F The compiler encodes the full path from an invocation construct to
+ -- an external target, offering additional information to GNATBIND for
+ -- purposes of error diagnostics.
+
+ -- d_G The compiler encodes the invocation graph of a unit in its ALI
+ -- file.
+
-- d_L Output trace information on elaboration checking. This debug switch
-- causes output to be generated showing each call or instantiation as
-- it is checked, and the progress of the recursive trace through
-- elaboration calls at compile time.
+ -- d_T The compiler outputs trance information to standard output whenever
+ -- an invocation path is recorded.
+
-- d1 Error messages have node numbers where possible. Normally error
-- messages have only source locations. This option is useful when
-- debugging errors caused by expanded code, where the source location
@@ -954,11 +1118,10 @@ package body Debug is
-- dependencies) except that internal units are included in the
-- listing.
- -- di Normally gnatbind calls Read_Ali with Ignore_Errors set to
- -- False, since the binder really needs correct version ALI
- -- files to do its job. This debug flag causes Ignore_Errors
- -- mode to be set for the binder (and is particularly useful
- -- for testing ignore errors mode).
+ -- di Normally GNATBIND calls Read_Ali with Ignore_Errors set to False,
+ -- since the binder really needs correct version ALI files to do its
+ -- job. This debug flag causes Ignore_Errors mode to be set for the
+ -- binder (and is particularly useful for testing ignore errors mode).
-- dn List details of manipulation of Num_Pred values during execution of
-- the algorithm used to determine a correct order of elaboration. This
@@ -985,6 +1148,25 @@ package body Debug is
-- dx Force the binder to read (and then ignore) the xref information
-- in ali files (used to check that read circuit is working OK).
+ -- d_A GNATBIND output the contents of all ALI invocation-related tables
+ -- in textual format to standard output.
+ --
+ -- d_I GNATBIND outputs the contents of the invocation graph in textual
+ -- format to standard output.
+ --
+ -- d_L GNATBIND outputs the contents of the library graph in textual
+ -- format to standard output.
+ --
+ -- d_N GNATBIND utilizes the elaboration order provided by bindo
+ --
+ -- d_O GNATBIND outputs the elaboration order of units to standard output
+ --
+ -- d_T GNATBIND outputs trace information of elaboration order activities
+ -- to standard output.
+ --
+ -- d_V GNATBIND validates the invocation graph, library graph, SCC graph
+ -- and elaboration order.
+
--------------------------------------------
-- Documentation for gnatmake Debug Flags --
--------------------------------------------
diff --git a/gcc/ada/doc/gnat_rm/implementation_defined_pragmas.rst b/gcc/ada/doc/gnat_rm/implementation_defined_pragmas.rst
index 6074cd4..955a137 100644
--- a/gcc/ada/doc/gnat_rm/implementation_defined_pragmas.rst
+++ b/gcc/ada/doc/gnat_rm/implementation_defined_pragmas.rst
@@ -3766,18 +3766,19 @@ Syntax:
pragma Machine_Attribute (
[Entity =>] LOCAL_NAME,
[Attribute_Name =>] static_string_EXPRESSION
- [, [Info =>] static_EXPRESSION] );
+ [, [Info =>] static_EXPRESSION {, static_EXPRESSION}] );
Machine-dependent attributes can be specified for types and/or
declarations. This pragma is semantically equivalent to
:samp:`__attribute__(({attribute_name}))` (if ``info`` is not
specified) or :samp:`__attribute__(({attribute_name(info})))`
-in GNU C, where *attribute_name* is recognized by the
-compiler middle-end or the ``TARGET_ATTRIBUTE_TABLE`` machine
-specific macro. A string literal for the optional parameter ``info``
-is transformed into an identifier, which may make this pragma unusable
-for some attributes.
+or :samp:`__attribute__(({attribute_name(info,...})))` in GNU C,
+where *attribute_name* is recognized by the compiler middle-end
+or the ``TARGET_ATTRIBUTE_TABLE`` machine specific macro. Note
+that a string literal for the optional parameter ``info`` or the
+following ones is transformed by default into an identifier,
+which may make this pragma unusable for some attributes.
For further information see :title:`GNU Compiler Collection (GCC) Internals`.
Pragma Main
diff --git a/gcc/ada/doc/gnat_rm/interfacing_to_other_languages.rst b/gcc/ada/doc/gnat_rm/interfacing_to_other_languages.rst
index bb629f4..ad0be51 100644
--- a/gcc/ada/doc/gnat_rm/interfacing_to_other_languages.rst
+++ b/gcc/ada/doc/gnat_rm/interfacing_to_other_languages.rst
@@ -46,8 +46,10 @@ and C types:
*
Ada enumeration types map to C enumeration types directly if pragma
- ``Convention C`` is specified, which causes them to have int
- length. Without pragma ``Convention C``, Ada enumeration types map to
+ ``Convention C`` is specified, which causes them to have a length of
+ 32 bits, except for boolean types which map to C99 ``bool`` and for
+ which the length is 8 bits.
+ Without pragma ``Convention C``, Ada enumeration types map to
8, 16, or 32 bits (i.e., C types ``signed char``, ``short``,
``int``, respectively) depending on the number of values passed.
This is the only case in which pragma ``Convention C`` affects the
diff --git a/gcc/ada/doc/gnat_rm/representation_clauses_and_pragmas.rst b/gcc/ada/doc/gnat_rm/representation_clauses_and_pragmas.rst
index 5ad8e03..82dc97c 100644
--- a/gcc/ada/doc/gnat_rm/representation_clauses_and_pragmas.rst
+++ b/gcc/ada/doc/gnat_rm/representation_clauses_and_pragmas.rst
@@ -610,14 +610,23 @@ alignment of the type (this is true for all types). In some cases the
end record;
-On a typical 32-bit architecture, the X component will be four bytes, and
-require four-byte alignment, and the Y component will be one byte. In this
-case ``R'Value_Size`` will be 40 (bits) since this is the minimum size
-required to store a value of this type, and for example, it is permissible
-to have a component of type R in an outer array whose component size is
-specified to be 48 bits. However, ``R'Object_Size`` will be 64 (bits),
-since it must be rounded up so that this value is a multiple of the
-alignment (4 bytes = 32 bits).
+On a typical 32-bit architecture, the X component will occupy four bytes
+and the Y component will occupy one byte, for a total of 5 bytes. As a
+result ``R'Value_Size`` will be 40 (bits) since this is the minimum size
+required to store a value of this type. For example, it is permissible
+to have a component of type R in an array whose component size is
+specified to be 40 bits.
+
+However, ``R'Object_Size`` will be 64 (bits). The difference is due to
+the alignment requirement for objects of the record type. The X
+component will require four-byte alignment because that is what type
+Integer requires, whereas the Y component, a Character, will only
+require 1-byte alignment. Since the alignment required for X is the
+greatest of all the components' alignments, that is the alignment
+required for the enclosing record type, i.e., 4 bytes or 32 bits. As
+indicated above, the actual object size must be rounded up so that it is
+a multiple of the alignment value. Therefore, 40 bits rounded up to the
+next multiple of 32 yields 64 bits.
For all other types, the ``Object_Size``
and ``Value_Size`` are the same (and equivalent to the RM attribute ``Size``).
diff --git a/gcc/ada/doc/gnat_rm/standard_and_implementation_defined_restrictions.rst b/gcc/ada/doc/gnat_rm/standard_and_implementation_defined_restrictions.rst
index 0b9f6dc..7b599be 100644
--- a/gcc/ada/doc/gnat_rm/standard_and_implementation_defined_restrictions.rst
+++ b/gcc/ada/doc/gnat_rm/standard_and_implementation_defined_restrictions.rst
@@ -510,15 +510,14 @@ No_Multiple_Elaboration
-----------------------
.. index:: No_Multiple_Elaboration
-[GNAT] When this restriction is active, we are not requesting control-flow
-preservation with -fpreserve-control-flow, and the static elaboration model is
-used, the compiler is allowed to suppress the elaboration counter normally
-associated with the unit, even if the unit has elaboration code. This counter
-is typically used to check for access before elaboration and to control
-multiple elaboration attempts. If the restriction is used, then the
-situations in which multiple elaboration is possible, including non-Ada main
-programs and Stand Alone libraries, are not permitted and will be diagnosed
-by the binder.
+[GNAT] When this restriction is active and the static elaboration model is
+used, and -fpreserve-control-flow is not used, the compiler is allowed to
+suppress the elaboration counter normally associated with the unit, even if
+the unit has elaboration code. This counter is typically used to check for
+access before elaboration and to control multiple elaboration attempts. If the
+restriction is used, then the situations in which multiple elaboration is
+possible, including non-Ada main programs and Stand Alone libraries, are not
+permitted and will be diagnosed by the binder.
No_Nested_Finalization
----------------------
diff --git a/gcc/ada/doc/gnat_ugn/building_executable_programs_with_gnat.rst b/gcc/ada/doc/gnat_ugn/building_executable_programs_with_gnat.rst
index b5363da..57c3fe1 100644
--- a/gcc/ada/doc/gnat_ugn/building_executable_programs_with_gnat.rst
+++ b/gcc/ada/doc/gnat_ugn/building_executable_programs_with_gnat.rst
@@ -4045,8 +4045,8 @@ of the pragma in the :title:`GNAT_Reference_manual`).
:switch:`-gnatw.z`
*Activate warnings for size not a multiple of alignment.*
- This switch activates warnings for cases of record types with
- specified ``Size`` and ``Alignment`` attributes where the
+ This switch activates warnings for cases of array and record types
+ with specified ``Size`` and ``Alignment`` attributes where the
size is not a multiple of the alignment, resulting in an object
size that is greater than the specified size. The default
is that such warnings are generated.
@@ -4058,12 +4058,11 @@ of the pragma in the :title:`GNAT_Reference_manual`).
:switch:`-gnatw.Z`
*Suppress warnings for size not a multiple of alignment.*
- This switch suppresses warnings for cases of record types with
- specified ``Size`` and ``Alignment`` attributes where the
+ This switch suppresses warnings for cases of array and record types
+ with specified ``Size`` and ``Alignment`` attributes where the
size is not a multiple of the alignment, resulting in an object
- size that is greater than the specified size.
- The warning can also be
- suppressed by giving an explicit ``Object_Size`` value.
+ size that is greater than the specified size. The warning can also
+ be suppressed by giving an explicit ``Object_Size`` value.
.. index:: -Wunused (gcc)
@@ -4691,6 +4690,16 @@ checks to be performed. The following checks are defined:
allowed).
+.. index:: -gnatyD (gcc)
+
+:switch:`-gnatyD`
+ *Check declared identifiers in mixed case.*
+
+ Declared identifiers must be in mixed case, as in
+ This_Is_An_Identifier. Use -gnatyr in addition to ensure
+ that references match declarations.
+
+
.. index:: -gnatye (gcc)
:switch:`-gnatye`
@@ -5889,8 +5898,8 @@ Debugging Control
compiler sources.
If the switch is followed by an ``s`` (e.g., :switch:`-gnatR3s`), then
- the output is to a file with the name :file:`file.rep` where file is
- the name of the corresponding source file, except if `j`` is also
+ the output is to a file with the name :file:`file.rep` where ``file`` is
+ the name of the corresponding source file, except if ``j`` is also
specified, in which case the file name is :file:`file.json`.
Note that it is possible for record components to have zero size. In
diff --git a/gcc/ada/doc/gnat_ugn/elaboration_order_handling_in_gnat.rst b/gcc/ada/doc/gnat_ugn/elaboration_order_handling_in_gnat.rst
index a4b8b7f..336555c 100644
--- a/gcc/ada/doc/gnat_ugn/elaboration_order_handling_in_gnat.rst
+++ b/gcc/ada/doc/gnat_ugn/elaboration_order_handling_in_gnat.rst
@@ -1056,17 +1056,17 @@ available.
If the compilation was performed using a post-18.x version of GNAT, consider
using the legacy elaboration model, in the following order:
+ - Use the relaxed static elaboration model, with compiler switch
+ :switch:`-gnatJ`.
+
+ - Use the relaxed dynamic elaboration model, with compiler switches
+ :switch:`-gnatE` :switch:`-gnatJ`.
+
- Use the legacy static elaboration model, with compiler switch
:switch:`-gnatH`.
- Use the legacy dynamic elaboration model, with compiler switches
- :switch:`-gnatH` :switch:`-gnatE`.
-
- - Use the relaxed legacy static elaboration model, with compiler switches
- :switch:`-gnatH` :switch:`-gnatJ`.
-
- - Use the relaxed legacy dynamic elaboration model, with compiler switches
- :switch:`-gnatH` :switch:`-gnatJ` :switch:`-gnatE`.
+ :switch:`-gnatE` :switch:`-gnatH`.
* *Suppress all elaboration checks*
diff --git a/gcc/ada/doc/gnat_ugn/gnat_utility_programs.rst b/gcc/ada/doc/gnat_ugn/gnat_utility_programs.rst
index 17ce45a..53904b1 100644
--- a/gcc/ada/doc/gnat_ugn/gnat_utility_programs.rst
+++ b/gcc/ada/doc/gnat_ugn/gnat_utility_programs.rst
@@ -3181,20 +3181,47 @@ Alternatively, you may run the script using the following command line:
Do not place the keyword ``is`` on a separate line in a subprogram body in
case if the spec occupies more than one line.
+ .. index:: --separate-loop (gnatpp)
+
+
+ :switch:`--separate-loop`
+ Place the keyword ``loop`` in FOR and WHILE loop statements
+ on a separate line.
+
+ .. index:: --no-separate-then (gnatpp)
+
+
+ :switch:`--separate-then`
+ Place the keyword ``then`` in IF statements
+ on a separate line.
+
+ .. index:: --no-separate-loop (gnatpp)
+
+
+ :switch:`--no-separate-loop`
+ Do not place the keyword ``loop`` in FOR and WHILE loop statements
+ on a separate line. This option is
+ incompatible with the :switch:`--separate-loop` option.
+
+ .. index:: --no-separate-then (gnatpp)
+
+
+ :switch:`--no-separate-then`
+ Do not place the keyword ``then`` in IF statements
+ on a separate line. This option is
+ incompatible with the :switch:`--separate-then` option.
+
.. index:: --separate-loop-then (gnatpp)
:switch:`--separate-loop-then`
- Place the keyword ``loop`` in FOR and WHILE loop statements and the
- keyword ``then`` in IF statements on a separate line.
+ Equivalent to :switch:`--separate-loop` :switch:`--separate-then`.
.. index:: --no-separate-loop-then (gnatpp)
:switch:`--no-separate-loop-then`
- Do not place the keyword ``loop`` in FOR and WHILE loop statements and the
- keyword ``then`` in IF statements on a separate line. This option is
- incompatible with the :switch:`--separate-loop-then` option.
+ Equivalent to :switch:`--no-separate-loop` :switch:`--no-separate-then`.
.. index:: --use-on-new-line (gnatpp)
@@ -3458,6 +3485,8 @@ Alternatively, you may run the script using the following command line:
* *unix* - UNIX style, lines end with LF character*
* *lf* - the same as *unix*
+ The default is to use the same end-of-line convention as the input.
+
.. index:: --wide-character-encoding (gnatpp)
:switch:`--wide-character-encoding={e}`
diff --git a/gcc/ada/einfo.adb b/gcc/ada/einfo.adb
index 13f381d..b9a9a8d 100644
--- a/gcc/ada/einfo.adb
+++ b/gcc/ada/einfo.adb
@@ -8141,7 +8141,7 @@ package body Einfo is
function Is_External_State (Id : E) return B is
begin
-- To qualify, the abstract state must appear with option "external" or
- -- "synchronous" (SPARK RM 7.1.4(8) and (10)).
+ -- "synchronous" (SPARK RM 7.1.4(7) and (9)).
return
Ekind (Id) = E_Abstract_State
@@ -8319,7 +8319,7 @@ package body Einfo is
function Is_Synchronized_State (Id : E) return B is
begin
-- To qualify, the abstract state must appear with simple option
- -- "synchronous" (SPARK RM 7.1.4(10)).
+ -- "synchronous" (SPARK RM 7.1.4(9)).
return
Ekind (Id) = E_Abstract_State
diff --git a/gcc/ada/einfo.ads b/gcc/ada/einfo.ads
index 70d374b..9dc6cc2 100644
--- a/gcc/ada/einfo.ads
+++ b/gcc/ada/einfo.ads
@@ -3779,7 +3779,7 @@ package Einfo is
-- Optimize_Alignment_Space (Flag241)
-- Defined in type, subtype, variable, and constant entities. This
--- flag records that the type or object is to be layed out in a manner
+-- flag records that the type or object is to be laid out in a manner
-- consistent with Optimize_Alignment (Space) mode. The compiler and
-- binder ensure a consistent view of any given type or object. If pragma
-- Optimize_Alignment (Off) mode applies to the type/object, then neither
@@ -3787,7 +3787,7 @@ package Einfo is
-- Optimize_Alignment_Time (Flag242)
-- Defined in type, subtype, variable, and constant entities. This
--- flag records that the type or object is to be layed out in a manner
+-- flag records that the type or object is to be laid out in a manner
-- consistent with Optimize_Alignment (Time) mode. The compiler and
-- binder ensure a consistent view of any given type or object. If pragma
-- Optimize_Alignment (Off) mode applies to the type/object, then neither
diff --git a/gcc/ada/erroutc.adb b/gcc/ada/erroutc.adb
index 57a169b..0c8ef5d 100644
--- a/gcc/ada/erroutc.adb
+++ b/gcc/ada/erroutc.adb
@@ -56,6 +56,12 @@ package body Erroutc is
-- wild card chars (*). The entire pattern must match the entire string.
-- Case is ignored in the comparison (so X matches x).
+ function Sloc_In_Range (Loc, Start, Stop : Source_Ptr) return Boolean;
+ -- Return whether Loc is in the range Start .. Stop, taking instantiation
+ -- locations of Loc into account. This is useful for suppressing warnings
+ -- from generic instantiations by using pragma Warnings around generic
+ -- instances, as needed in GNATprove.
+
---------------
-- Add_Class --
---------------
@@ -1588,6 +1594,24 @@ package body Erroutc is
end if;
end Set_Warnings_Mode_On;
+ -------------------
+ -- Sloc_In_Range --
+ -------------------
+
+ function Sloc_In_Range (Loc, Start, Stop : Source_Ptr) return Boolean is
+ Cur_Loc : Source_Ptr := Loc;
+
+ begin
+ while Cur_Loc /= No_Location loop
+ if Start <= Cur_Loc and then Cur_Loc <= Stop then
+ return True;
+ end if;
+ Cur_Loc := Instantiation_Location (Cur_Loc);
+ end loop;
+
+ return False;
+ end Sloc_In_Range;
+
--------------------------------
-- Validate_Specific_Warnings --
--------------------------------
@@ -1652,7 +1676,7 @@ package body Erroutc is
-- location is in range of a specific non-configuration pragma.
if SWE.Config
- or else (SWE.Start <= Loc and then Loc <= SWE.Stop)
+ or else Sloc_In_Range (Loc, SWE.Start, SWE.Stop)
then
if Matches (Msg.all, SWE.Msg.all)
or else Matches (Tag, SWE.Msg.all)
@@ -1691,8 +1715,8 @@ package body Erroutc is
-- Loop through table of ON/OFF warnings
for J in Warnings.First .. Warnings.Last loop
- if Warnings.Table (J).Start <= Loc
- and then Loc <= Warnings.Table (J).Stop
+ if Sloc_In_Range (Loc, Warnings.Table (J).Start,
+ Warnings.Table (J).Stop)
then
return Warnings.Table (J).Reason;
end if;
diff --git a/gcc/ada/exp_attr.adb b/gcc/ada/exp_attr.adb
index 22368a1..1e1b2f9 100644
--- a/gcc/ada/exp_attr.adb
+++ b/gcc/ada/exp_attr.adb
@@ -639,7 +639,7 @@ package body Exp_Attr is
Stmts := No_List;
- -- Validate componants
+ -- Validate components
Validate_Component_List
(Obj_Id => Obj_Id,
@@ -1693,103 +1693,6 @@ package body Exp_Attr is
-- generate conditionals in the code, so check the relevant restriction.
Check_Restriction (No_Implicit_Conditionals, N);
-
- -- In Modify_Tree_For_C mode, we rewrite as an if expression
-
- if Modify_Tree_For_C then
- declare
- Loc : constant Source_Ptr := Sloc (N);
- Typ : constant Entity_Id := Etype (N);
- Expr : constant Node_Id := First (Expressions (N));
- Left : constant Node_Id := Relocate_Node (Expr);
- Right : constant Node_Id := Relocate_Node (Next (Expr));
-
- function Make_Compare (Left, Right : Node_Id) return Node_Id;
- -- Returns Left >= Right for Max, Left <= Right for Min
-
- ------------------
- -- Make_Compare --
- ------------------
-
- function Make_Compare (Left, Right : Node_Id) return Node_Id is
- begin
- if Attribute_Name (N) = Name_Max then
- return
- Make_Op_Ge (Loc,
- Left_Opnd => Left,
- Right_Opnd => Right);
- else
- return
- Make_Op_Le (Loc,
- Left_Opnd => Left,
- Right_Opnd => Right);
- end if;
- end Make_Compare;
-
- -- Start of processing for Min_Max
-
- begin
- -- If both Left and Right are side effect free, then we can just
- -- use Duplicate_Expr to duplicate the references and return
-
- -- (if Left >=|<= Right then Left else Right)
-
- if Side_Effect_Free (Left) and then Side_Effect_Free (Right) then
- Rewrite (N,
- Make_If_Expression (Loc,
- Expressions => New_List (
- Make_Compare (Left, Right),
- Duplicate_Subexpr_No_Checks (Left),
- Duplicate_Subexpr_No_Checks (Right))));
-
- -- Otherwise we generate declarations to capture the values.
-
- -- The translation is
-
- -- do
- -- T1 : constant typ := Left;
- -- T2 : constant typ := Right;
- -- in
- -- (if T1 >=|<= T2 then T1 else T2)
- -- end;
-
- else
- declare
- T1 : constant Entity_Id := Make_Temporary (Loc, 'T', Left);
- T2 : constant Entity_Id := Make_Temporary (Loc, 'T', Right);
-
- begin
- Rewrite (N,
- Make_Expression_With_Actions (Loc,
- Actions => New_List (
- Make_Object_Declaration (Loc,
- Defining_Identifier => T1,
- Constant_Present => True,
- Object_Definition =>
- New_Occurrence_Of (Etype (Left), Loc),
- Expression => Relocate_Node (Left)),
-
- Make_Object_Declaration (Loc,
- Defining_Identifier => T2,
- Constant_Present => True,
- Object_Definition =>
- New_Occurrence_Of (Etype (Right), Loc),
- Expression => Relocate_Node (Right))),
-
- Expression =>
- Make_If_Expression (Loc,
- Expressions => New_List (
- Make_Compare
- (New_Occurrence_Of (T1, Loc),
- New_Occurrence_Of (T2, Loc)),
- New_Occurrence_Of (T1, Loc),
- New_Occurrence_Of (T2, Loc)))));
- end;
- end if;
-
- Analyze_And_Resolve (N, Typ);
- end;
- end if;
end Expand_Min_Max_Attribute;
----------------------------------
@@ -4242,6 +4145,11 @@ package body Exp_Attr is
when Attribute_Invalid_Value =>
Rewrite (N, Get_Simple_Init_Val (Ptyp, N));
+ -- The value produced may be a conversion of a literal, which must be
+ -- resolved to establish its proper type.
+
+ Analyze_And_Resolve (N);
+
----------
-- Last --
----------
diff --git a/gcc/ada/exp_ch7.adb b/gcc/ada/exp_ch7.adb
index 96742e5..4209785 100644
--- a/gcc/ada/exp_ch7.adb
+++ b/gcc/ada/exp_ch7.adb
@@ -379,10 +379,6 @@ package body Exp_Ch7 is
-- references within these nested subprograms (typically generated
-- subprograms to handle finalization actions).
- function Contains_Subprogram (Blk : Entity_Id) return Boolean;
- -- Check recursively whether a loop or block contains a subprogram that
- -- may need an activation record.
-
procedure Check_Visibly_Controlled
(Prim : Final_Primitives;
Typ : Entity_Id;
@@ -400,6 +396,10 @@ package body Exp_Ch7 is
-- and use it instead. This is one case that might be solved more cleanly
-- once Overriding pragmas or declarations are in place.
+ function Contains_Subprogram (Blk : Entity_Id) return Boolean;
+ -- Check recursively whether a loop or block contains a subprogram that
+ -- may need an activation record.
+
function Convert_View
(Proc : Entity_Id;
Arg : Node_Id;
@@ -5187,6 +5187,7 @@ package body Exp_Ch7 is
Set_Finalizer (Id, Fin_Id);
end if;
+
Check_Unnesting_In_Declarations (Visible_Declarations (Spec));
Check_Unnesting_In_Declarations (Private_Declarations (Spec));
end Expand_N_Package_Declaration;
diff --git a/gcc/ada/exp_ch9.adb b/gcc/ada/exp_ch9.adb
index 5ec9fb4..0f83d57 100644
--- a/gcc/ada/exp_ch9.adb
+++ b/gcc/ada/exp_ch9.adb
@@ -8258,18 +8258,17 @@ package body Exp_Ch9 is
Proc : Entity_Id;
begin
- -- Try to use System.Relative_Delays.Delay_For only if available. This
- -- is the implementation used on restricted platforms when Ada.Calendar
- -- is not available.
+ -- Try to use Ada.Calendar.Delays.Delay_For if available.
- if RTE_Available (RO_RD_Delay_For) then
- Proc := RTE (RO_RD_Delay_For);
+ if RTE_Available (RO_CA_Delay_For) then
+ Proc := RTE (RO_CA_Delay_For);
- -- Otherwise, use Ada.Calendar.Delays.Delay_For and emit an error
- -- message if not available.
+ -- Otherwise, use System.Relative_Delays.Delay_For and emit an error
+ -- message if not available. This is the implementation used on
+ -- restricted platforms when Ada.Calendar is not available.
else
- Proc := RTE (RO_CA_Delay_For);
+ Proc := RTE (RO_RD_Delay_For);
end if;
Rewrite (N,
@@ -8951,6 +8950,10 @@ package body Exp_Ch9 is
Set_Is_Inlined (Protected_Body_Subprogram (Subp));
Set_Is_Inlined (Subp, False);
end if;
+
+ if Has_Pragma_No_Inline (Subp) then
+ Set_Has_Pragma_No_Inline (Protected_Body_Subprogram (Subp));
+ end if;
end Check_Inlining;
---------------------------
diff --git a/gcc/ada/exp_unst.adb b/gcc/ada/exp_unst.adb
index 3d533ba..b81b1b9 100644
--- a/gcc/ada/exp_unst.adb
+++ b/gcc/ada/exp_unst.adb
@@ -254,8 +254,7 @@ package body Exp_Unst is
Typ := Full_View (Typ);
end if;
- return Is_Array_Type (Typ)
- and then not Is_Constrained (Typ);
+ return Is_Array_Type (Typ) and then not Is_Constrained (Typ);
else
return False;
end if;
@@ -464,7 +463,10 @@ package body Exp_Unst is
Callee : Entity_Id;
procedure Check_Static_Type
- (T : Entity_Id; N : Node_Id; DT : in out Boolean);
+ (T : Entity_Id;
+ N : Node_Id;
+ DT : in out Boolean;
+ Check_Designated : Boolean := False);
-- Given a type T, checks if it is a static type defined as a type
-- with no dynamic bounds in sight. If so, the only action is to
-- set Is_Static_Type True for T. If T is not a static type, then
@@ -474,6 +476,9 @@ package body Exp_Unst is
-- node that will need to be replaced. If not specified, it means
-- we can't do a replacement because the bound is implicit.
+ -- If Check_Designated is True and T or its full view is an access
+ -- type, check whether the designated type has dynamic bounds.
+
procedure Note_Uplevel_Ref
(E : Entity_Id;
N : Node_Id;
@@ -492,7 +497,10 @@ package body Exp_Unst is
-----------------------
procedure Check_Static_Type
- (T : Entity_Id; N : Node_Id; DT : in out Boolean)
+ (T : Entity_Id;
+ N : Node_Id;
+ DT : in out Boolean;
+ Check_Designated : Boolean := False)
is
procedure Note_Uplevel_Bound (N : Node_Id; Ref : Node_Id);
-- N is the bound of a dynamic type. This procedure notes that
@@ -602,7 +610,7 @@ package body Exp_Unst is
begin
-- If already marked static, immediate return
- if Is_Static_Type (T) then
+ if Is_Static_Type (T) and then not Check_Designated then
return;
end if;
@@ -685,13 +693,20 @@ package body Exp_Unst is
-- For private type, examine whether full view is static
- elsif Is_Private_Type (T) and then Present (Full_View (T)) then
- Check_Static_Type (Full_View (T), N, DT);
+ elsif Is_Incomplete_Or_Private_Type (T)
+ and then Present (Full_View (T))
+ then
+ Check_Static_Type (Full_View (T), N, DT, Check_Designated);
if Is_Static_Type (Full_View (T)) then
Set_Is_Static_Type (T);
end if;
+ -- For access types, check designated type when required
+
+ elsif Is_Access_Type (T) and then Check_Designated then
+ Check_Static_Type (Directly_Designated_Type (T), N, DT);
+
-- For now, ignore other types
else
@@ -936,7 +951,11 @@ package body Exp_Unst is
declare
DT : Boolean := False;
begin
- Check_Static_Type (Etype (Expression (N)), Empty, DT);
+ Check_Static_Type
+ (Etype (Expression (N)),
+ Empty,
+ DT,
+ Check_Designated => Nkind (N) = N_Free_Statement);
end;
end if;
@@ -2188,8 +2207,7 @@ package body Exp_Unst is
and then Present (Constant_Value (UPJ.Ent))
and then Is_Static_Expression (Constant_Value (UPJ.Ent))
then
- Rewrite (UPJ.Ref,
- New_Copy_Tree (Constant_Value (UPJ.Ent)));
+ Rewrite (UPJ.Ref, New_Copy_Tree (Constant_Value (UPJ.Ent)));
goto Continue;
end if;
diff --git a/gcc/ada/exp_util.adb b/gcc/ada/exp_util.adb
index b127f03..4206090 100644
--- a/gcc/ada/exp_util.adb
+++ b/gcc/ada/exp_util.adb
@@ -4940,18 +4940,6 @@ package body Exp_Util is
end if;
end Evolve_Or_Else;
- -------------------
- -- Exceptions_OK --
- -------------------
-
- function Exceptions_OK return Boolean is
- begin
- return
- not (Restriction_Active (No_Exception_Handlers) or else
- Restriction_Active (No_Exception_Propagation) or else
- Restriction_Active (No_Exceptions));
- end Exceptions_OK;
-
-----------------------------------------
-- Expand_Static_Predicates_In_Choices --
-----------------------------------------
@@ -8258,8 +8246,8 @@ package body Exp_Util is
return False;
end if;
- -- Here we have a tagged type, see if it has any unlayed out fields
- -- other than a possible tag and parent fields. If so, we return False.
+ -- Here we have a tagged type, see if it has any component (other than
+ -- tag and parent) with no component_clause. If so, we return False.
Comp := First_Component (U);
while Present (Comp) loop
@@ -8273,7 +8261,7 @@ package body Exp_Util is
end if;
end loop;
- -- All components are layed out
+ -- All components have clauses
return True;
end Is_Fully_Repped_Tagged_Type;
diff --git a/gcc/ada/exp_util.ads b/gcc/ada/exp_util.ads
index aac4433..7cb9d2d 100644
--- a/gcc/ada/exp_util.ads
+++ b/gcc/ada/exp_util.ads
@@ -559,10 +559,6 @@ package Exp_Util is
-- indicating that no checks were required). The Sloc field of the
-- constructed N_Or_Else node is copied from Cond1.
- function Exceptions_OK return Boolean;
- -- Determine whether exceptions are allowed to be caught, propagated, or
- -- raised.
-
procedure Expand_Static_Predicates_In_Choices (N : Node_Id);
-- N is either a case alternative or a variant. The Discrete_Choices field
-- of N points to a list of choices. If any of these choices is the name
diff --git a/gcc/ada/freeze.adb b/gcc/ada/freeze.adb
index 8e55fb8..5b843f2 100644
--- a/gcc/ada/freeze.adb
+++ b/gcc/ada/freeze.adb
@@ -5943,17 +5943,29 @@ package body Freeze is
Inherit_Aspects_At_Freeze_Point (E);
end if;
- -- Check for incompatible size and alignment for record type
+ -- Case of array type
+
+ if Is_Array_Type (E) then
+ Freeze_Array_Type (E);
+ end if;
+
+ -- Check for incompatible size and alignment for array/record type
if Warn_On_Size_Alignment
- and then Is_Record_Type (E)
- and then Has_Size_Clause (E) and then Has_Alignment_Clause (E)
+ and then (Is_Array_Type (E) or else Is_Record_Type (E))
+ and then Has_Size_Clause (E)
+ and then Has_Alignment_Clause (E)
-- If explicit Object_Size clause given assume that the programmer
-- knows what he is doing, and expects the compiler behavior.
and then not Has_Object_Size_Clause (E)
+ -- It does not really make sense to warn for the minimum alignment
+ -- since the programmer could not get rid of the warning.
+
+ and then Alignment (E) > 1
+
-- Check for size not a multiple of alignment
and then RM_Size (E) mod (Alignment (E) * System_Storage_Unit) /= 0
@@ -5994,15 +6006,10 @@ package body Freeze is
end;
end if;
- -- Array type
-
- if Is_Array_Type (E) then
- Freeze_Array_Type (E);
-
-- For a class-wide type, the corresponding specific type is
-- frozen as well (RM 13.14(15))
- elsif Is_Class_Wide_Type (E) then
+ if Is_Class_Wide_Type (E) then
Freeze_And_Append (Root_Type (E), N, Result);
-- If the base type of the class-wide type is still incomplete,
@@ -7665,9 +7672,8 @@ package body Freeze is
or else Ekind (Current_Scope) = E_Void
then
declare
- N : constant Node_Id := Current_Scope;
- Freeze_Nodes : List_Id := No_List;
- Pos : Int := Scope_Stack.Last;
+ Freeze_Nodes : List_Id := No_List;
+ Pos : Int := Scope_Stack.Last;
begin
if Present (Desig_Typ) then
@@ -7700,7 +7706,19 @@ package body Freeze is
end if;
if Is_Non_Empty_List (Freeze_Nodes) then
- if No (Scope_Stack.Table (Pos).Pending_Freeze_Actions) then
+
+ -- When the current scope is transient, insert the freeze nodes
+ -- prior to the expression that produced them. Transient scopes
+ -- may create additional declarations when finalizing objects
+ -- or managing the secondary stack. Inserting the freeze nodes
+ -- of those constructs prior to the scope would result in a
+ -- freeze-before-declaration, therefore the freeze node must
+ -- remain interleaved with their constructs.
+
+ if Scope_Is_Transient then
+ Insert_Actions (N, Freeze_Nodes);
+
+ elsif No (Scope_Stack.Table (Pos).Pending_Freeze_Actions) then
Scope_Stack.Table (Pos).Pending_Freeze_Actions :=
Freeze_Nodes;
else
diff --git a/gcc/ada/gcc-interface/Make-lang.in b/gcc/ada/gcc-interface/Make-lang.in
index de23b14..dd90c7b 100644
--- a/gcc/ada/gcc-interface/Make-lang.in
+++ b/gcc/ada/gcc-interface/Make-lang.in
@@ -317,10 +317,11 @@ GNAT_ADA_OBJS = \
ada/frontend.o \
ada/libgnat/g-byorma.o \
ada/libgnat/g-dynhta.o \
+ ada/libgnat/g-graphs.o \
ada/libgnat/g-hesora.o \
ada/libgnat/g-htable.o \
- ada/libgnat/g-lists.o \
- ada/libgnat/g-sets.o \
+ ada/libgnat/g-lists.o \
+ ada/libgnat/g-sets.o \
ada/libgnat/g-spchge.o \
ada/libgnat/g-speche.o \
ada/libgnat/g-u3spch.o \
@@ -507,6 +508,15 @@ GNATBIND_OBJS = \
ada/binde.o \
ada/binderr.o \
ada/bindgen.o \
+ ada/bindo.o \
+ ada/bindo-augmentors.o \
+ ada/bindo-builders.o \
+ ada/bindo-diagnostics.o \
+ ada/bindo-elaborators.o \
+ ada/bindo-graphs.o \
+ ada/bindo-units.o \
+ ada/bindo-validators.o \
+ ada/bindo-writers.o \
ada/bindusg.o \
ada/butil.o \
ada/casing.o \
@@ -526,8 +536,12 @@ GNATBIND_OBJS = \
ada/fname-uf.o \
ada/fname.o \
ada/libgnat/g-byorma.o \
+ ada/libgnat/g-dynhta.o \
+ ada/libgnat/g-graphs.o \
ada/libgnat/g-hesora.o \
ada/libgnat/g-htable.o \
+ ada/libgnat/g-lists.o \
+ ada/libgnat/g-sets.o \
ada/libgnat/gnat.o \
ada/gnatbind.o \
ada/gnatvsn.o \
diff --git a/gcc/ada/gcc-interface/ada-builtin-types.def b/gcc/ada/gcc-interface/ada-builtin-types.def
new file mode 100644
index 0000000..f00845b
--- /dev/null
+++ b/gcc/ada/gcc-interface/ada-builtin-types.def
@@ -0,0 +1,25 @@
+/* This file contains the type definitions for the builtins exclusively
+ used in the GNU Ada compiler.
+
+ Copyright (C) 2019 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/>. */
+
+/* See builtin-types.def for details. */
+
+DEF_FUNCTION_TYPE_1 (BT_FN_BOOL_BOOL, BT_BOOL, BT_BOOL)
+DEF_FUNCTION_TYPE_2 (BT_FN_BOOL_BOOL_BOOL, BT_BOOL, BT_BOOL, BT_BOOL)
diff --git a/gcc/ada/gcc-interface/ada-builtins.def b/gcc/ada/gcc-interface/ada-builtins.def
new file mode 100644
index 0000000..dcdc4d9
--- /dev/null
+++ b/gcc/ada/gcc-interface/ada-builtins.def
@@ -0,0 +1,30 @@
+/* This file contains the definitions for the builtins exclusively used
+ in the GNU Ada compiler.
+
+ Copyright (C) 2019 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/>. */
+
+/* Before including this file, you should define a macro:
+
+ DEF_ADA_BUILTIN (ENUM, NAME, TYPE, ATTRS)
+
+ See builtins.def for details. */
+
+DEF_ADA_BUILTIN (BUILT_IN_EXPECT, "expect", BT_FN_BOOL_BOOL_BOOL, ATTR_CONST_NOTHROW_LEAF_LIST)
+DEF_ADA_BUILTIN (BUILT_IN_LIKELY, "likely", BT_FN_BOOL_BOOL, ATTR_CONST_NOTHROW_LEAF_LIST)
+DEF_ADA_BUILTIN (BUILT_IN_UNLIKELY, "unlikely", BT_FN_BOOL_BOOL, ATTR_CONST_NOTHROW_LEAF_LIST)
diff --git a/gcc/ada/gcc-interface/ada-tree.h b/gcc/ada/gcc-interface/ada-tree.h
index ea2c945..2029b7c 100644
--- a/gcc/ada/gcc-interface/ada-tree.h
+++ b/gcc/ada/gcc-interface/ada-tree.h
@@ -6,7 +6,7 @@
* *
* C Header File *
* *
- * Copyright (C) 1992-2018, Free Software Foundation, Inc. *
+ * Copyright (C) 1992-2019, 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- *
@@ -582,3 +582,8 @@ do { \
#define EXIT_STMT_COND(NODE) TREE_OPERAND_CHECK_CODE (NODE, EXIT_STMT, 0)
#define EXIT_STMT_LABEL(NODE) TREE_OPERAND_CHECK_CODE (NODE, EXIT_STMT, 1)
+
+/* Small kludge to be able to define Ada built-in functions locally.
+ We overload them on top of the HSAIL/BRIG builtin functions. */
+#define BUILT_IN_LIKELY BUILT_IN_HSAIL_WORKITEMABSID
+#define BUILT_IN_UNLIKELY BUILT_IN_HSAIL_GRIDSIZE
diff --git a/gcc/ada/gcc-interface/decl.c b/gcc/ada/gcc-interface/decl.c
index ed015ba..81f621b 100644
--- a/gcc/ada/gcc-interface/decl.c
+++ b/gcc/ada/gcc-interface/decl.c
@@ -308,7 +308,10 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, bool definition)
tree gnu_size = NULL_TREE;
/* Contains the GCC name to be used for the GCC node. */
tree gnu_entity_name;
- /* True if we have already saved gnu_decl as a GNAT association. */
+ /* True if we have already saved gnu_decl as a GNAT association. This can
+ also be used to purposely avoid making such an association but this use
+ case ought not to be applied to types because it can break the deferral
+ mechanism implemented for access types. */
bool saved = false;
/* True if we incremented defer_incomplete_level. */
bool this_deferred = false;
@@ -325,14 +328,11 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, bool definition)
/* Since a use of an Itype is a definition, process it as such if it is in
the main unit, except for E_Access_Subtype because it's actually a use
- of its base type, and for E_Record_Subtype with cloned subtype because
- it's actually a use of the cloned subtype, see below. */
+ of its base type, see below. */
if (!definition
&& is_type
&& Is_Itype (gnat_entity)
- && !(kind == E_Access_Subtype
- || (kind == E_Record_Subtype
- && Present (Cloned_Subtype (gnat_entity))))
+ && Ekind (gnat_entity) != E_Access_Subtype
&& !present_gnu_tree (gnat_entity)
&& In_Extended_Main_Code_Unit (gnat_entity))
{
@@ -375,7 +375,7 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, bool definition)
}
/* This abort means the Itype has an incorrect scope, i.e. that its
- scope does not correspond to the subprogram it is declared in. */
+ scope does not correspond to the subprogram it is first used in. */
gcc_unreachable ();
}
@@ -384,7 +384,9 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, bool definition)
In that case, we will abort below when we try to save a new GCC tree
for this object. We also need to handle the case of getting a dummy
type when a Full_View exists but be careful so as not to trigger its
- premature elaboration. */
+ premature elaboration. Likewise for a cloned subtype without its own
+ freeze node, which typically happens when a generic gets instantiated
+ on an incomplete or private type. */
if ((!definition || (is_type && imported_p))
&& present_gnu_tree (gnat_entity))
{
@@ -398,7 +400,23 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, bool definition)
|| No (Freeze_Node (Full_View (gnat_entity)))))
{
gnu_decl
- = gnat_to_gnu_entity (Full_View (gnat_entity), NULL_TREE, false);
+ = gnat_to_gnu_entity (Full_View (gnat_entity), NULL_TREE,
+ false);
+ save_gnu_tree (gnat_entity, NULL_TREE, false);
+ save_gnu_tree (gnat_entity, gnu_decl, false);
+ }
+
+ if (TREE_CODE (gnu_decl) == TYPE_DECL
+ && TYPE_IS_DUMMY_P (TREE_TYPE (gnu_decl))
+ && Ekind (gnat_entity) == E_Record_Subtype
+ && No (Freeze_Node (gnat_entity))
+ && Present (Cloned_Subtype (gnat_entity))
+ && (present_gnu_tree (Cloned_Subtype (gnat_entity))
+ || No (Freeze_Node (Cloned_Subtype (gnat_entity)))))
+ {
+ gnu_decl
+ = gnat_to_gnu_entity (Cloned_Subtype (gnat_entity), NULL_TREE,
+ false);
save_gnu_tree (gnat_entity, NULL_TREE, false);
save_gnu_tree (gnat_entity, gnu_decl, false);
}
@@ -1855,7 +1873,8 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, bool definition)
= Has_Biased_Representation (gnat_entity);
/* Do the same processing for Character subtypes as for types. */
- if (TYPE_STRING_FLAG (TREE_TYPE (gnu_type)))
+ if (TREE_CODE (TREE_TYPE (gnu_type)) == INTEGER_TYPE
+ && TYPE_STRING_FLAG (TREE_TYPE (gnu_type)))
{
TYPE_NAME (gnu_type) = gnu_entity_name;
TYPE_STRING_FLAG (gnu_type) = 1;
@@ -3003,9 +3022,9 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, bool definition)
{
SET_TYPE_ALIGN (gnu_type, 0);
- /* If a type needs strict alignment, the minimum size will be the
- type size instead of the RM size (see validate_size). Cap the
- alignment lest it causes this type size to become too large. */
+ /* If a type needs strict alignment, then its type size will also
+ be the RM size (see below). Cap the alignment if needed, lest
+ it may cause this type size to become too large. */
if (Strict_Alignment (gnat_entity) && Known_RM_Size (gnat_entity))
{
unsigned int max_size = UI_To_Int (RM_Size (gnat_entity));
@@ -3282,6 +3301,12 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, bool definition)
compute_record_mode (gnu_type);
}
+ /* If the type needs strict alignment, then no object of the type
+ may have a size smaller than the natural size, which means that
+ the RM size of the type is equal to the type size. */
+ if (Strict_Alignment (gnat_entity))
+ SET_TYPE_ADA_SIZE (gnu_type, TYPE_SIZE (gnu_type));
+
/* If there are entities in the chain corresponding to components
that we did not elaborate, ensure we elaborate their types if
they are Itypes. */
@@ -3331,14 +3356,14 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, bool definition)
case E_Record_Subtype:
/* If Cloned_Subtype is Present it means this record subtype has
identical layout to that type or subtype and we should use
- that GCC type for this one. The front end guarantees that
+ that GCC type for this one. The front-end guarantees that
the component list is shared. */
if (Present (Cloned_Subtype (gnat_entity)))
{
gnu_decl = gnat_to_gnu_entity (Cloned_Subtype (gnat_entity),
NULL_TREE, false);
gnat_annotate_type = Cloned_Subtype (gnat_entity);
- saved = true;
+ maybe_present = true;
break;
}
@@ -3373,7 +3398,6 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, bool definition)
Unchecked_Union (it must be an Itype), just return the type. */
if (Has_Discriminants (gnat_entity)
&& Stored_Constraint (gnat_entity) != No_Elist
- && !Is_For_Access_Subtype (gnat_entity)
&& Is_Record_Type (gnat_base_type)
&& !Is_Unchecked_Union (gnat_base_type))
{
@@ -3752,8 +3776,8 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, bool definition)
case E_Access_Subtype:
/* We treat this as identical to its base type; any constraint is
meaningful only to the front-end. */
- gnu_decl = gnat_to_gnu_entity (Etype (gnat_entity), NULL_TREE, false);
- saved = true;
+ gnu_decl = gnat_to_gnu_entity (gnat_equiv_type, NULL_TREE, false);
+ maybe_present = true;
/* The designated subtype must be elaborated as well, if it does
not have its own freeze node. But designated subtypes created
@@ -4187,7 +4211,10 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, bool definition)
already defined so we cannot pass true for IN_PLACE here. */
process_attributes (&gnu_type, &attr_list, false, gnat_entity);
- /* ??? Don't set the size for a String_Literal since it is either
+ /* See if a size was specified, by means of either an Object_Size or
+ a regular Size clause, and validate it if so.
+
+ ??? Don't set the size for a String_Literal since it is either
confirming or we don't handle it properly (if the low bound is
non-constant). */
if (!gnu_size && kind != E_String_Literal_Subtype)
@@ -4309,49 +4336,44 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, bool definition)
/* If we are just annotating types and the type is tagged, the tag
and the parent components are not generated by the front-end so
- alignment and sizes must be adjusted if there is no rep clause. */
- if (type_annotate_only
- && Is_Tagged_Type (gnat_entity)
- && Unknown_RM_Size (gnat_entity)
- && !VOID_TYPE_P (gnu_type)
- && (!TYPE_FIELDS (gnu_type)
- || integer_zerop (bit_position (TYPE_FIELDS (gnu_type)))))
+ alignment and sizes must be adjusted. */
+ if (type_annotate_only && Is_Tagged_Type (gnat_entity))
{
- tree offset;
-
- if (Is_Derived_Type (gnat_entity))
- {
- Entity_Id gnat_parent = Etype (Base_Type (gnat_entity));
- offset = UI_To_gnu (Esize (gnat_parent), bitsizetype);
- Set_Alignment (gnat_entity, Alignment (gnat_parent));
- }
- else
+ const bool derived_p = Is_Derived_Type (gnat_entity);
+ const Entity_Id gnat_parent
+ = derived_p ? Etype (Base_Type (gnat_entity)) : Empty;
+ const unsigned int inherited_align
+ = derived_p
+ ? UI_To_Int (Alignment (gnat_parent)) * BITS_PER_UNIT
+ : POINTER_SIZE;
+ const unsigned int align
+ = MAX (TYPE_ALIGN (gnu_type), inherited_align);
+
+ Set_Alignment (gnat_entity, UI_From_Int (align / BITS_PER_UNIT));
+
+ /* If there is neither size clause nor representation clause, the
+ sizes need to be adjusted. */
+ if (Unknown_RM_Size (gnat_entity)
+ && !VOID_TYPE_P (gnu_type)
+ && (!TYPE_FIELDS (gnu_type)
+ || integer_zerop (bit_position (TYPE_FIELDS (gnu_type)))))
{
- unsigned int align
- = MAX (TYPE_ALIGN (gnu_type), POINTER_SIZE) / BITS_PER_UNIT;
- offset = bitsize_int (POINTER_SIZE);
- Set_Alignment (gnat_entity, UI_From_Int (align));
+ tree offset
+ = derived_p
+ ? UI_To_gnu (Esize (gnat_parent), bitsizetype)
+ : bitsize_int (POINTER_SIZE);
+ if (TYPE_FIELDS (gnu_type))
+ offset
+ = round_up (offset, DECL_ALIGN (TYPE_FIELDS (gnu_type)));
+ gnu_size = size_binop (PLUS_EXPR, gnu_size, offset);
}
- if (TYPE_FIELDS (gnu_type))
- offset
- = round_up (offset, DECL_ALIGN (TYPE_FIELDS (gnu_type)));
-
- gnu_size = size_binop (PLUS_EXPR, gnu_size, offset);
- gnu_size = round_up (gnu_size, POINTER_SIZE);
- Uint uint_size = annotate_value (gnu_size);
- Set_RM_Size (gnat_entity, uint_size);
- Set_Esize (gnat_entity, uint_size);
- }
-
- /* If there is a rep clause, only adjust alignment and Esize. */
- else if (type_annotate_only && Is_Tagged_Type (gnat_entity))
- {
- unsigned int align
- = MAX (TYPE_ALIGN (gnu_type), POINTER_SIZE) / BITS_PER_UNIT;
- Set_Alignment (gnat_entity, UI_From_Int (align));
- gnu_size = round_up (gnu_size, POINTER_SIZE);
+ gnu_size = round_up (gnu_size, align);
Set_Esize (gnat_entity, annotate_value (gnu_size));
+
+ /* Tagged types are Strict_Alignment so RM_Size = Esize. */
+ if (Unknown_RM_Size (gnat_entity))
+ Set_RM_Size (gnat_entity, Esize (gnat_entity));
}
/* Otherwise no adjustment is needed. */
@@ -4481,6 +4503,7 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, bool definition)
}
}
+ /* Now check if the type allows atomic access. */
if (Is_Atomic_Or_VFA (gnat_entity))
check_ok_for_atomic_type (gnu_type, gnat_entity, false);
@@ -4978,6 +5001,10 @@ Gigi_Equivalent_Type (Entity_Id gnat_entity)
gnat_equiv = Equivalent_Type (gnat_entity);
break;
+ case E_Access_Subtype:
+ gnat_equiv = Etype (gnat_entity);
+ break;
+
case E_Class_Wide_Type:
gnat_equiv = Root_Type (gnat_entity);
break;
@@ -5100,6 +5127,7 @@ gnat_to_gnu_component_type (Entity_Id gnat_array, bool definition,
}
}
+ /* Now check if the type of the component allows atomic access. */
if (Has_Atomic_Components (gnat_array) || Is_Atomic_Or_VFA (gnat_type))
check_ok_for_atomic_type (gnu_type, gnat_array, true);
@@ -6148,7 +6176,8 @@ static void
set_nonaliased_component_on_array_type (tree type)
{
TYPE_NONALIASED_COMPONENT (type) = 1;
- TYPE_NONALIASED_COMPONENT (TYPE_CANONICAL (type)) = 1;
+ if (TYPE_CANONICAL (type))
+ TYPE_NONALIASED_COMPONENT (TYPE_CANONICAL (type)) = 1;
}
/* Set TYPE_REVERSE_STORAGE_ORDER on an array type built by means of
@@ -6158,7 +6187,8 @@ static void
set_reverse_storage_order_on_array_type (tree type)
{
TYPE_REVERSE_STORAGE_ORDER (type) = 1;
- TYPE_REVERSE_STORAGE_ORDER (TYPE_CANONICAL (type)) = 1;
+ if (TYPE_CANONICAL (type))
+ TYPE_REVERSE_STORAGE_ORDER (TYPE_CANONICAL (type)) = 1;
}
/* Return true if DISCR1 and DISCR2 represent the same discriminant. */
@@ -6459,25 +6489,18 @@ prepend_one_attribute (struct attrib **attr_list,
static void
prepend_one_attribute_pragma (struct attrib **attr_list, Node_Id gnat_pragma)
{
- const Node_Id gnat_arg = Pragma_Argument_Associations (gnat_pragma);
- tree gnu_arg0 = NULL_TREE, gnu_arg1 = NULL_TREE;
+ const Node_Id gnat_arg = First (Pragma_Argument_Associations (gnat_pragma));
+ Node_Id gnat_next_arg = Next (gnat_arg);
+ tree gnu_arg1 = NULL_TREE, gnu_arg_list = NULL_TREE;
enum attrib_type etype;
/* Map the pragma at hand. Skip if this isn't one we know how to handle. */
switch (Get_Pragma_Id (Chars (Pragma_Identifier (gnat_pragma))))
{
- case Pragma_Machine_Attribute:
- etype = ATTR_MACHINE_ATTRIBUTE;
- break;
-
case Pragma_Linker_Alias:
etype = ATTR_LINK_ALIAS;
break;
- case Pragma_Linker_Section:
- etype = ATTR_LINK_SECTION;
- break;
-
case Pragma_Linker_Constructor:
etype = ATTR_LINK_CONSTRUCTOR;
break;
@@ -6486,58 +6509,58 @@ prepend_one_attribute_pragma (struct attrib **attr_list, Node_Id gnat_pragma)
etype = ATTR_LINK_DESTRUCTOR;
break;
- case Pragma_Weak_External:
- etype = ATTR_WEAK_EXTERNAL;
+ case Pragma_Linker_Section:
+ etype = ATTR_LINK_SECTION;
+ break;
+
+ case Pragma_Machine_Attribute:
+ etype = ATTR_MACHINE_ATTRIBUTE;
break;
case Pragma_Thread_Local_Storage:
etype = ATTR_THREAD_LOCAL_STORAGE;
break;
+ case Pragma_Weak_External:
+ etype = ATTR_WEAK_EXTERNAL;
+ break;
+
default:
return;
}
/* See what arguments we have and turn them into GCC trees for attribute
- handlers. These expect identifier for strings. We handle at most two
- arguments and static expressions only. */
- if (Present (gnat_arg) && Present (First (gnat_arg)))
+ handlers. The first one is always expected to be a string meant to be
+ turned into an identifier. The next ones are all static expressions,
+ among which strings meant to be turned into an identifier, except for
+ a couple of specific attributes that require raw strings. */
+ if (Present (gnat_next_arg))
{
- Node_Id gnat_arg0 = Next (First (gnat_arg));
- Node_Id gnat_arg1 = Empty;
-
- if (Present (gnat_arg0)
- && Is_OK_Static_Expression (Expression (gnat_arg0)))
+ gnu_arg1 = gnat_to_gnu (Expression (gnat_next_arg));
+ gcc_assert (TREE_CODE (gnu_arg1) == STRING_CST);
+
+ const char *const p = TREE_STRING_POINTER (gnu_arg1);
+ const bool string_args
+ = strcmp (p, "target") == 0 || strcmp (p, "target_clones") == 0;
+ gnu_arg1 = get_identifier (p);
+ if (IDENTIFIER_LENGTH (gnu_arg1) == 0)
+ return;
+ gnat_next_arg = Next (gnat_next_arg);
+
+ while (Present (gnat_next_arg))
{
- gnu_arg0 = gnat_to_gnu (Expression (gnat_arg0));
-
- if (TREE_CODE (gnu_arg0) == STRING_CST)
- {
- gnu_arg0 = get_identifier (TREE_STRING_POINTER (gnu_arg0));
- if (IDENTIFIER_LENGTH (gnu_arg0) == 0)
- return;
- }
-
- gnat_arg1 = Next (gnat_arg0);
- }
-
- if (Present (gnat_arg1)
- && Is_OK_Static_Expression (Expression (gnat_arg1)))
- {
- gnu_arg1 = gnat_to_gnu (Expression (gnat_arg1));
-
- if (TREE_CODE (gnu_arg1) == STRING_CST)
- gnu_arg1 = get_identifier (TREE_STRING_POINTER (gnu_arg1));
+ tree gnu_arg = gnat_to_gnu (Expression (gnat_next_arg));
+ if (TREE_CODE (gnu_arg) == STRING_CST && !string_args)
+ gnu_arg = get_identifier (TREE_STRING_POINTER (gnu_arg));
+ gnu_arg_list
+ = chainon (gnu_arg_list, build_tree_list (NULL_TREE, gnu_arg));
+ gnat_next_arg = Next (gnat_next_arg);
}
}
- /* Prepend to the list. Make a list of the argument we might have, as GCC
- expects it. */
- prepend_one_attribute (attr_list, etype, gnu_arg0,
- gnu_arg1
- ? build_tree_list (NULL_TREE, gnu_arg1) : NULL_TREE,
- Present (Next (First (gnat_arg)))
- ? Expression (Next (First (gnat_arg))) : gnat_pragma);
+ prepend_one_attribute (attr_list, etype, gnu_arg1, gnu_arg_list,
+ Present (Next (gnat_arg))
+ ? Expression (Next (gnat_arg)) : gnat_pragma);
}
/* Prepend to ATTR_LIST the list of attributes for GNAT_ENTITY, if any. */
@@ -6908,6 +6931,7 @@ gnat_to_gnu_field (Entity_Id gnat_field, tree gnu_record_type, int packed,
boundaries, but that should be guaranteed by the GCC memory model. */
const bool needs_strict_alignment
= (is_atomic || is_aliased || is_independent || is_strict_alignment);
+ bool is_bitfield;
tree gnu_field_type = gnat_to_gnu_type (gnat_field_type);
tree gnu_field_id = get_entity_name (gnat_field);
tree gnu_field, gnu_size, gnu_pos;
@@ -6922,7 +6946,7 @@ gnat_to_gnu_field (Entity_Id gnat_field, tree gnu_record_type, int packed,
/* If a size is specified, use it. Otherwise, if the record type is packed,
use the official RM size. See "Handling of Type'Size Values" in Einfo
for further details. */
- if (Known_Esize (gnat_field) || Present (gnat_clause))
+ if (Present (gnat_clause) || Known_Esize (gnat_field))
gnu_size = validate_size (Esize (gnat_field), gnu_field_type, gnat_field,
FIELD_DECL, false, true);
else if (packed == 1)
@@ -6934,12 +6958,36 @@ gnat_to_gnu_field (Entity_Id gnat_field, tree gnu_record_type, int packed,
else
gnu_size = NULL_TREE;
- /* If we have a specified size that is smaller than that of the field's type,
- or a position is specified, and the field's type is a record that doesn't
- require strict alignment, see if we can get either an integral mode form
- of the type or a smaller form. If we can, show a size was specified for
- the field if there wasn't one already, so we know to make this a bitfield
- and avoid making things wider.
+ /* Likewise for the position. */
+ if (Present (gnat_clause))
+ {
+ gnu_pos = UI_To_gnu (Component_Bit_Offset (gnat_field), bitsizetype);
+ is_bitfield = !value_factor_p (gnu_pos, BITS_PER_UNIT);
+ }
+
+ /* If the record has rep clauses and this is the tag field, make a rep
+ clause for it as well. */
+ else if (Has_Specified_Layout (gnat_record_type)
+ && Chars (gnat_field) == Name_uTag)
+ {
+ gnu_pos = bitsize_zero_node;
+ gnu_size = TYPE_SIZE (gnu_field_type);
+ is_bitfield = false;
+ }
+
+ else
+ {
+ gnu_pos = NULL_TREE;
+ is_bitfield = false;
+ }
+
+ /* If the field's type is a fixed-size record that does not require strict
+ alignment, and the record is packed or we have a position specified for
+ the field that makes it a bitfield or we have a specified size that is
+ smaller than that of the field's type, then see if we can get either an
+ integral mode form of the field's type or a smaller form. If we can,
+ consider that a size was specified for the field if there wasn't one
+ already, so we know to make it a bitfield and avoid making things wider.
Changing to an integral mode form is useful when the record is packed as
we can then place the field at a non-byte-aligned position and so achieve
@@ -6961,14 +7009,12 @@ gnat_to_gnu_field (Entity_Id gnat_field, tree gnu_record_type, int packed,
&& !TYPE_FAT_POINTER_P (gnu_field_type)
&& tree_fits_uhwi_p (TYPE_SIZE (gnu_field_type))
&& (packed == 1
+ || is_bitfield
|| (gnu_size
- && (tree_int_cst_lt (gnu_size, TYPE_SIZE (gnu_field_type))
- || (Present (gnat_clause)
- && !(UI_To_Int (Component_Bit_Offset (gnat_field))
- % BITS_PER_UNIT == 0
- && value_factor_p (gnu_size, BITS_PER_UNIT)))))))
+ && tree_int_cst_lt (gnu_size, TYPE_SIZE (gnu_field_type)))))
{
- tree gnu_packable_type = make_packable_type (gnu_field_type, true);
+ tree gnu_packable_type
+ = make_packable_type (gnu_field_type, true, is_bitfield ? 1 : 0);
if (gnu_packable_type != gnu_field_type)
{
gnu_field_type = gnu_packable_type;
@@ -6977,6 +7023,7 @@ gnat_to_gnu_field (Entity_Id gnat_field, tree gnu_record_type, int packed,
}
}
+ /* Now check if the type of the field allows atomic access. */
if (Is_Atomic_Or_VFA (gnat_field))
{
const unsigned int align
@@ -6988,12 +7035,11 @@ gnat_to_gnu_field (Entity_Id gnat_field, tree gnu_record_type, int packed,
check_ok_for_atomic_type (gnu_field_type, gnat_field, false);
}
- if (Present (gnat_clause))
+ /* If a position is specified, check that it is valid. */
+ if (gnu_pos)
{
Entity_Id gnat_parent = Parent_Subtype (gnat_record_type);
- gnu_pos = UI_To_gnu (Component_Bit_Offset (gnat_field), bitsizetype);
-
/* Ensure the position does not overlap with the parent subtype, if there
is one. This test is omitted if the parent of the tagged type has a
full rep clause since, in this case, component clauses are allowed to
@@ -7006,7 +7052,7 @@ gnat_to_gnu_field (Entity_Id gnat_field, tree gnu_record_type, int packed,
if (TREE_CODE (TYPE_SIZE (gnu_parent)) == INTEGER_CST
&& tree_int_cst_lt (gnu_pos, TYPE_SIZE (gnu_parent)))
post_error_ne_tree
- ("offset of& must be beyond parent{, minimum allowed is ^}",
+ ("position for& must be beyond parent{, minimum allowed is ^}",
Position (gnat_clause), gnat_field, TYPE_SIZE_UNIT (gnu_parent));
}
@@ -7020,98 +7066,90 @@ gnat_to_gnu_field (Entity_Id gnat_field, tree gnu_record_type, int packed,
&& !(type_annotate_only && Is_Tagged_Type (gnat_field_type)))
{
const unsigned int type_align = TYPE_ALIGN (gnu_field_type);
+ const char *field_s;
if (TYPE_ALIGN (gnu_record_type)
&& TYPE_ALIGN (gnu_record_type) < type_align)
SET_TYPE_ALIGN (gnu_record_type, type_align);
- /* If the position is not a multiple of the alignment of the type,
- then error out and reset the position. */
+ if (is_atomic)
+ field_s = "atomic &";
+ else if (is_aliased)
+ field_s = "aliased &";
+ else if (is_independent)
+ field_s = "independent &";
+ else if (is_strict_alignment)
+ field_s = "& with aliased or tagged part";
+ else
+ gcc_unreachable ();
+
+ /* If the position is not a multiple of the storage unit, then error
+ out and reset the position. */
if (!integer_zerop (size_binop (TRUNC_MOD_EXPR, gnu_pos,
- bitsize_int (type_align))))
+ bitsize_unit_node)))
{
- const char *s;
-
- if (is_atomic)
- s = "position of atomic field& must be multiple of ^ bits";
- else if (is_aliased)
- s = "position of aliased field& must be multiple of ^ bits";
- else if (is_independent)
- s = "position of independent field& must be multiple of ^ bits";
- else if (is_strict_alignment)
- s = "position of & with aliased or tagged part must be"
- " multiple of ^ bits";
- else
- gcc_unreachable ();
+ char s[128];
+ snprintf (s, sizeof (s), "position for %s must be "
+ "multiple of Storage_Unit", field_s);
+ post_error_ne (s, First_Bit (gnat_clause), gnat_field);
+ gnu_pos = NULL_TREE;
+ }
+ /* If the position is not a multiple of the alignment of the type,
+ then error out and reset the position. */
+ else if (type_align > BITS_PER_UNIT
+ && !integer_zerop (size_binop (TRUNC_MOD_EXPR, gnu_pos,
+ bitsize_int (type_align))))
+ {
+ char s[128];
+ snprintf (s, sizeof (s), "position for %s must be multiple of ^",
+ field_s);
post_error_ne_num (s, First_Bit (gnat_clause), gnat_field,
- type_align);
+ type_align / BITS_PER_UNIT);
+ post_error_ne_num ("\\because alignment of its type& is ^",
+ First_Bit (gnat_clause), Etype (gnat_field),
+ type_align / BITS_PER_UNIT);
gnu_pos = NULL_TREE;
}
if (gnu_size)
{
- tree gnu_type_size = TYPE_SIZE (gnu_field_type);
- const int cmp = tree_int_cst_compare (gnu_size, gnu_type_size);
+ tree type_size = TYPE_SIZE (gnu_field_type);
+ int cmp;
- /* If the size is lower than that of the type, or greater for
- atomic and aliased, then error out and reset the size. */
- if (cmp < 0 || (cmp > 0 && (is_atomic || is_aliased)))
+ /* If the size is not a multiple of the storage unit, then error
+ out and reset the size. */
+ if (!integer_zerop (size_binop (TRUNC_MOD_EXPR, gnu_size,
+ bitsize_unit_node)))
{
- const char *s;
-
- if (is_atomic)
- s = "size of atomic field& must be ^ bits";
- else if (is_aliased)
- s = "size of aliased field& must be ^ bits";
- else if (is_independent)
- s = "size of independent field& must be at least ^ bits";
- else if (is_strict_alignment)
- s = "size of & with aliased or tagged part must be"
- " at least ^ bits";
- else
- gcc_unreachable ();
-
- post_error_ne_tree (s, Last_Bit (gnat_clause), gnat_field,
- gnu_type_size);
+ char s[128];
+ snprintf (s, sizeof (s), "size for %s must be "
+ "multiple of Storage_Unit", field_s);
+ post_error_ne (s, Last_Bit (gnat_clause), gnat_field);
gnu_size = NULL_TREE;
}
- /* Likewise if the size is not a multiple of a byte, */
- else if (!integer_zerop (size_binop (TRUNC_MOD_EXPR, gnu_size,
- bitsize_unit_node)))
+ /* If the size is lower than that of the type, or greater for
+ atomic and aliased, then error out and reset the size. */
+ else if ((cmp = tree_int_cst_compare (gnu_size, type_size)) < 0
+ || (cmp > 0 && (is_atomic || is_aliased)))
{
- const char *s;
-
- if (is_independent)
- s = "size of independent field& must be multiple of"
- " Storage_Unit";
- else if (is_strict_alignment)
- s = "size of & with aliased or tagged part must be"
- " multiple of Storage_Unit";
+ char s[128];
+ if (is_atomic || is_aliased)
+ snprintf (s, sizeof (s), "size for %s must be ^", field_s);
else
- gcc_unreachable ();
-
- post_error_ne (s, Last_Bit (gnat_clause), gnat_field);
+ snprintf (s, sizeof (s), "size for %s must be at least ^",
+ field_s);
+ post_error_ne_tree (s, Last_Bit (gnat_clause), gnat_field,
+ type_size);
gnu_size = NULL_TREE;
}
}
}
}
- /* If the record has rep clauses and this is the tag field, make a rep
- clause for it as well. */
- else if (Has_Specified_Layout (gnat_record_type)
- && Chars (gnat_field) == Name_uTag)
- {
- gnu_pos = bitsize_zero_node;
- gnu_size = TYPE_SIZE (gnu_field_type);
- }
-
else
{
- gnu_pos = NULL_TREE;
-
/* If we are packing the record and the field is BLKmode, round the
size up to a byte boundary. */
if (packed && TYPE_MODE (gnu_field_type) == BLKmode && gnu_size)
@@ -8162,6 +8200,8 @@ components_to_record (Node_Id gnat_component_list, Entity_Id gnat_record_type,
gnu_field_list = gnu_rep_list;
else
{
+ TYPE_NAME (gnu_rep_type)
+ = create_concat_name (gnat_record_type, "REP");
TYPE_REVERSE_STORAGE_ORDER (gnu_rep_type)
= TYPE_REVERSE_STORAGE_ORDER (gnu_record_type);
finish_record_type (gnu_rep_type, gnu_rep_list, 1, debug_info);
@@ -8718,7 +8758,7 @@ validate_size (Uint uint_size, tree gnu_type, Entity_Id gnat_object,
enum tree_code kind, bool component_p, bool zero_ok)
{
Node_Id gnat_error_node;
- tree type_size, size;
+ tree old_size, size;
/* Return 0 if no size was specified. */
if (uint_size == No_Uint)
@@ -8783,17 +8823,11 @@ validate_size (Uint uint_size, tree gnu_type, Entity_Id gnat_object,
&& TYPE_CONTAINS_TEMPLATE_P (gnu_type))
size = size_binop (PLUS_EXPR, DECL_SIZE (TYPE_FIELDS (gnu_type)), size);
- if (kind == VAR_DECL
- /* If a type needs strict alignment, a component of this type in
- a packed record cannot be packed and thus uses the type size. */
- || (kind == TYPE_DECL && Strict_Alignment (gnat_object)))
- type_size = TYPE_SIZE (gnu_type);
- else
- type_size = rm_size (gnu_type);
+ old_size = (kind == VAR_DECL ? TYPE_SIZE (gnu_type) : rm_size (gnu_type));
- /* Modify the size of a discriminated type to be the maximum size. */
- if (type_size && CONTAINS_PLACEHOLDER_P (type_size))
- type_size = max_size (type_size, true);
+ /* If the old size is self-referential, get the maximum size. */
+ if (CONTAINS_PLACEHOLDER_P (old_size))
+ old_size = max_size (old_size, true);
/* If this is an access type or a fat pointer, the minimum size is that given
by the smallest integral mode that's valid for pointers. */
@@ -8802,23 +8836,23 @@ validate_size (Uint uint_size, tree gnu_type, Entity_Id gnat_object,
scalar_int_mode p_mode = NARROWEST_INT_MODE;
while (!targetm.valid_pointer_mode (p_mode))
p_mode = GET_MODE_WIDER_MODE (p_mode).require ();
- type_size = bitsize_int (GET_MODE_BITSIZE (p_mode));
+ old_size = bitsize_int (GET_MODE_BITSIZE (p_mode));
}
/* Issue an error either if the default size of the object isn't a constant
or if the new size is smaller than it. */
- if (TREE_CODE (type_size) != INTEGER_CST
- || TREE_OVERFLOW (type_size)
- || tree_int_cst_lt (size, type_size))
+ if (TREE_CODE (old_size) != INTEGER_CST
+ || TREE_OVERFLOW (old_size)
+ || tree_int_cst_lt (size, old_size))
{
if (component_p)
post_error_ne_tree
("component size for& too small{, minimum allowed is ^}",
- gnat_error_node, gnat_object, type_size);
+ gnat_error_node, gnat_object, old_size);
else
post_error_ne_tree
("size for& too small{, minimum allowed is ^}",
- gnat_error_node, gnat_object, type_size);
+ gnat_error_node, gnat_object, old_size);
return NULL_TREE;
}
@@ -9174,9 +9208,9 @@ intrin_arglists_compatible_p (intrin_binding_t * inb)
if (!ada_type && !btin_type)
break;
- /* If one list is shorter than the other, they fail to match. */
- if (!ada_type || !btin_type)
- return false;
+ /* If the internal builtin uses a variable list, accept anything. */
+ if (!btin_type)
+ break;
/* If we're done with the Ada args and not with the internal builtin
args, or the other way around, complain. */
@@ -9686,7 +9720,7 @@ copy_and_substitute_in_layout (Entity_Id gnat_new_type,
if (RECORD_OR_UNION_TYPE_P (gnu_field_type)
&& !TYPE_FAT_POINTER_P (gnu_field_type)
&& tree_fits_uhwi_p (TYPE_SIZE (gnu_field_type)))
- gnu_field_type = make_packable_type (gnu_field_type, true);
+ gnu_field_type = make_packable_type (gnu_field_type, true, 0);
}
else
diff --git a/gcc/ada/gcc-interface/gigi.h b/gcc/ada/gcc-interface/gigi.h
index 191a017..f7415c7 100644
--- a/gcc/ada/gcc-interface/gigi.h
+++ b/gcc/ada/gcc-interface/gigi.h
@@ -126,7 +126,7 @@ extern tree make_aligning_type (tree type, unsigned int align, tree size,
MAX_ALIGN alignment if the value is non-zero. If so, return the new
type; if not, return the original type. */
extern tree make_packable_type (tree type, bool in_record,
- unsigned int max_align = 0);
+ unsigned int max_align);
/* Given a type TYPE, return a new type whose size is appropriate for SIZE.
If TYPE is the best type, return it. Otherwise, make a new type. We
@@ -837,7 +837,7 @@ extern unsigned int known_alignment (tree exp);
/* Return true if VALUE is a multiple of FACTOR. FACTOR must be a power
of 2. */
-extern bool value_factor_p (tree value, HOST_WIDE_INT factor);
+extern bool value_factor_p (tree value, unsigned HOST_WIDE_INT factor);
/* Build an atomic load for the underlying atomic object in SRC. SYNC is
true if the load requires synchronization. */
@@ -1138,7 +1138,9 @@ gnat_signed_type_for (tree type_node)
static inline tree
maybe_character_type (tree type)
{
- if (TYPE_STRING_FLAG (type) && !TYPE_UNSIGNED (type))
+ if (TREE_CODE (type) == INTEGER_TYPE
+ && TYPE_STRING_FLAG (type)
+ && !TYPE_UNSIGNED (type))
type = gnat_unsigned_type_for (type);
return type;
@@ -1151,7 +1153,9 @@ maybe_character_value (tree expr)
{
tree type = TREE_TYPE (expr);
- if (TYPE_STRING_FLAG (type) && !TYPE_UNSIGNED (type))
+ if (TREE_CODE (type) == INTEGER_TYPE
+ && TYPE_STRING_FLAG (type)
+ && !TYPE_UNSIGNED (type))
{
type = gnat_unsigned_type_for (type);
expr = convert (type, expr);
diff --git a/gcc/ada/gcc-interface/trans.c b/gcc/ada/gcc-interface/trans.c
index 155cb4b..32dd132 100644
--- a/gcc/ada/gcc-interface/trans.c
+++ b/gcc/ada/gcc-interface/trans.c
@@ -778,6 +778,7 @@ lvalue_required_for_attribute_p (Node_Id gnat_node)
case Attr_Range_Length:
case Attr_Length:
case Attr_Object_Size:
+ case Attr_Size:
case Attr_Value_Size:
case Attr_Component_Size:
case Attr_Descriptor_Size:
@@ -797,7 +798,6 @@ lvalue_required_for_attribute_p (Node_Id gnat_node)
case Attr_Unrestricted_Access:
case Attr_Code_Address:
case Attr_Pool_Address:
- case Attr_Size:
case Attr_Alignment:
case Attr_Bit_Position:
case Attr_Position:
@@ -1021,6 +1021,42 @@ fold_constant_decl_in_expr (tree exp)
gcc_unreachable ();
}
+/* Return true if TYPE and DEF_TYPE are compatible GNAT types for Gigi. */
+
+static bool
+Gigi_Types_Compatible (Entity_Id type, Entity_Id def_type)
+{
+ /* The trivial case. */
+ if (type == def_type)
+ return true;
+
+ /* A class-wide type is equivalent to a subtype of itself. */
+ if (Is_Class_Wide_Type (type))
+ return true;
+
+ /* A packed array type is compatible with its implementation type. */
+ if (Is_Packed (def_type) && type == Packed_Array_Impl_Type (def_type))
+ return true;
+
+ /* If both types are Itypes, one may be a copy of the other. */
+ if (Is_Itype (def_type) && Is_Itype (type))
+ return true;
+
+ /* If the type is incomplete and comes from a limited context, then also
+ consider its non-limited view. */
+ if (Is_Incomplete_Type (def_type)
+ && From_Limited_With (def_type)
+ && Present (Non_Limited_View (def_type)))
+ return Gigi_Types_Compatible (type, Non_Limited_View (def_type));
+
+ /* If the type is incomplete/private, then also consider its full view. */
+ if (Is_Incomplete_Or_Private_Type (def_type)
+ && Present (Full_View (def_type)))
+ return Gigi_Types_Compatible (type, Full_View (def_type));
+
+ return false;
+}
+
/* Subroutine of gnat_to_gnu to translate gnat_node, an N_Identifier,
to a GCC tree, which is returned. GNU_RESULT_TYPE_P is a pointer
to where we should place the result type. */
@@ -1028,55 +1064,31 @@ fold_constant_decl_in_expr (tree exp)
static tree
Identifier_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p)
{
- Node_Id gnat_temp, gnat_temp_type;
- tree gnu_result, gnu_result_type;
-
- /* Whether we should require an lvalue for GNAT_NODE. Needed in
- specific circumstances only, so evaluated lazily. < 0 means
- unknown, > 0 means known true, 0 means known false. */
- int require_lvalue = -1;
-
+ /* The entity of GNAT_NODE and its type. */
+ Node_Id gnat_entity = (Nkind (gnat_node) == N_Defining_Identifier
+ || Nkind (gnat_node) == N_Defining_Operator_Symbol)
+ ? gnat_node : Entity (gnat_node);
+ Node_Id gnat_entity_type = Etype (gnat_entity);
/* If GNAT_NODE is a constant, whether we should use the initialization
value instead of the constant entity, typically for scalars with an
address clause when the parent doesn't require an lvalue. */
bool use_constant_initializer = false;
+ /* Whether we should require an lvalue for GNAT_NODE. Needed in
+ specific circumstances only, so evaluated lazily. < 0 means
+ unknown, > 0 means known true, 0 means known false. */
+ int require_lvalue = -1;
+ Node_Id gnat_result_type;
+ tree gnu_result, gnu_result_type;
/* If the Etype of this node is not the same as that of the Entity, then
something went wrong, probably in generic instantiation. However, this
does not apply to types. Since we sometime have strange Ekind's, just
- do this test for objects. Moreover, if the Etype of the Entity is private
- or incomplete coming from a limited context, the Etype of the N_Identifier
- is allowed to be the full/non-limited view and we also consider a packed
- array type to be the same as the original type. Similarly, a CW type is
- equivalent to a subtype of itself. Finally, if the types are Itypes, one
- may be a copy of the other, which is also legal. */
- gnat_temp = ((Nkind (gnat_node) == N_Defining_Identifier
- || Nkind (gnat_node) == N_Defining_Operator_Symbol)
- ? gnat_node : Entity (gnat_node));
- gnat_temp_type = Etype (gnat_temp);
-
- gcc_assert (Etype (gnat_node) == gnat_temp_type
- || (Is_Packed (gnat_temp_type)
- && (Etype (gnat_node)
- == Packed_Array_Impl_Type (gnat_temp_type)))
- || (Is_Class_Wide_Type (Etype (gnat_node)))
- || (Is_Incomplete_Or_Private_Type (gnat_temp_type)
- && Present (Full_View (gnat_temp_type))
- && ((Etype (gnat_node) == Full_View (gnat_temp_type))
- || (Is_Packed (Full_View (gnat_temp_type))
- && (Etype (gnat_node)
- == Packed_Array_Impl_Type
- (Full_View (gnat_temp_type))))))
- || (Is_Incomplete_Type (gnat_temp_type)
- && From_Limited_With (gnat_temp_type)
- && Present (Non_Limited_View (gnat_temp_type))
- && Etype (gnat_node) == Non_Limited_View (gnat_temp_type))
- || (Is_Itype (Etype (gnat_node)) && Is_Itype (gnat_temp_type))
- || !(Ekind (gnat_temp) == E_Variable
- || Ekind (gnat_temp) == E_Component
- || Ekind (gnat_temp) == E_Constant
- || Ekind (gnat_temp) == E_Loop_Parameter
- || Is_Formal (gnat_temp)));
+ do this test for objects, except for discriminants because their type
+ may have been changed to a subtype by Exp_Ch3.Adjust_Discriminants. */
+ gcc_assert (!Is_Object (gnat_entity)
+ || Ekind (gnat_entity) == E_Discriminant
+ || Etype (gnat_node) == gnat_entity_type
+ || Gigi_Types_Compatible (Etype (gnat_node), gnat_entity_type));
/* If this is a reference to a deferred constant whose partial view is an
unconstrained private type, the proper type is on the full view of the
@@ -1086,36 +1098,40 @@ Identifier_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p)
attribute Position, generated for dispatching code (see Make_DT in
exp_disp,adb). In that case we need the type itself, not is parent,
in particular if it is a derived type */
- if (Ekind (gnat_temp) == E_Constant
- && Is_Private_Type (gnat_temp_type)
- && (Has_Unknown_Discriminants (gnat_temp_type)
- || (Present (Full_View (gnat_temp_type))
- && Has_Discriminants (Full_View (gnat_temp_type))))
- && Present (Full_View (gnat_temp)))
+ if (Ekind (gnat_entity) == E_Constant
+ && Is_Private_Type (gnat_entity_type)
+ && (Has_Unknown_Discriminants (gnat_entity_type)
+ || (Present (Full_View (gnat_entity_type))
+ && Has_Discriminants (Full_View (gnat_entity_type))))
+ && Present (Full_View (gnat_entity)))
{
- gnat_temp = Full_View (gnat_temp);
- gnat_temp_type = Etype (gnat_temp);
+ gnat_entity = Full_View (gnat_entity);
+ gnat_result_type = Etype (gnat_entity);
}
else
{
- /* We want to use the Actual_Subtype if it has already been elaborated,
- otherwise the Etype. Avoid using Actual_Subtype for packed arrays to
- simplify things. */
- if ((Ekind (gnat_temp) == E_Constant
- || Ekind (gnat_temp) == E_Variable || Is_Formal (gnat_temp))
- && !(Is_Array_Type (Etype (gnat_temp))
- && Present (Packed_Array_Impl_Type (Etype (gnat_temp))))
- && Present (Actual_Subtype (gnat_temp))
- && present_gnu_tree (Actual_Subtype (gnat_temp)))
- gnat_temp_type = Actual_Subtype (gnat_temp);
+ /* We use the Actual_Subtype only if it has already been elaborated,
+ as we may be invoked precisely during its elaboration, otherwise
+ the Etype. Avoid using it for packed arrays to simplify things,
+ except in a return statement because we need the actual size and
+ the front-end does not make it explicit in this case. */
+ if ((Ekind (gnat_entity) == E_Constant
+ || Ekind (gnat_entity) == E_Variable
+ || Is_Formal (gnat_entity))
+ && !(Is_Array_Type (Etype (gnat_entity))
+ && Present (Packed_Array_Impl_Type (Etype (gnat_entity)))
+ && Nkind (Parent (gnat_node)) != N_Simple_Return_Statement)
+ && Present (Actual_Subtype (gnat_entity))
+ && present_gnu_tree (Actual_Subtype (gnat_entity)))
+ gnat_result_type = Actual_Subtype (gnat_entity);
else
- gnat_temp_type = Etype (gnat_node);
+ gnat_result_type = Etype (gnat_node);
}
/* Expand the type of this identifier first, in case it is an enumeral
literal, which only get made when the type is expanded. There is no
order-of-elaboration issue here. */
- gnu_result_type = get_unpadded_type (gnat_temp_type);
+ gnu_result_type = get_unpadded_type (gnat_result_type);
/* If this is a non-imported elementary constant with an address clause,
retrieve the value instead of a pointer to be dereferenced unless
@@ -1125,10 +1141,10 @@ Identifier_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p)
statement alternative or a record discriminant. There is no possible
volatile-ness short-circuit here since Volatile constants must be
imported per C.6. */
- if (Ekind (gnat_temp) == E_Constant
- && Is_Elementary_Type (gnat_temp_type)
- && !Is_Imported (gnat_temp)
- && Present (Address_Clause (gnat_temp)))
+ if (Ekind (gnat_entity) == E_Constant
+ && Is_Elementary_Type (gnat_result_type)
+ && !Is_Imported (gnat_entity)
+ && Present (Address_Clause (gnat_entity)))
{
require_lvalue
= lvalue_required_p (gnat_node, gnu_result_type, true, false);
@@ -1139,13 +1155,13 @@ Identifier_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p)
{
/* If this is a deferred constant, the initializer is attached to
the full view. */
- if (Present (Full_View (gnat_temp)))
- gnat_temp = Full_View (gnat_temp);
+ if (Present (Full_View (gnat_entity)))
+ gnat_entity = Full_View (gnat_entity);
- gnu_result = gnat_to_gnu (Expression (Declaration_Node (gnat_temp)));
+ gnu_result = gnat_to_gnu (Expression (Declaration_Node (gnat_entity)));
}
else
- gnu_result = gnat_to_gnu_entity (gnat_temp, NULL_TREE, false);
+ gnu_result = gnat_to_gnu_entity (gnat_entity, NULL_TREE, false);
/* Some objects (such as parameters passed by reference, globals of
variable size, and renamed objects) actually represent the address
@@ -1184,7 +1200,7 @@ Identifier_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p)
if ((TREE_CODE (gnu_result) == INDIRECT_REF
|| TREE_CODE (gnu_result) == UNCONSTRAINED_ARRAY_REF)
- && No (Address_Clause (gnat_temp)))
+ && No (Address_Clause (gnat_entity)))
TREE_THIS_NOTRAP (gnu_result) = 1;
if (read_only)
@@ -1218,9 +1234,9 @@ Identifier_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p)
/* But for a constant renaming we couldn't do that incrementally for its
definition because of the need to return an lvalue so, if the present
context doesn't itself require an lvalue, we try again here. */
- else if (Ekind (gnat_temp) == E_Constant
- && Is_Elementary_Type (gnat_temp_type)
- && Present (Renamed_Object (gnat_temp)))
+ else if (Ekind (gnat_entity) == E_Constant
+ && Is_Elementary_Type (gnat_result_type)
+ && Present (Renamed_Object (gnat_entity)))
{
if (require_lvalue < 0)
require_lvalue
@@ -1236,10 +1252,10 @@ Identifier_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p)
avoid problematic conversions to the nominal subtype. But remove any
padding from the resulting type. */
if (FUNC_OR_METHOD_TYPE_P (TREE_TYPE (gnu_result))
- || Is_Constr_Subt_For_UN_Aliased (gnat_temp_type)
- || (Ekind (gnat_temp) == E_Constant
- && Present (Full_View (gnat_temp))
- && Has_Discriminants (gnat_temp_type)
+ || Is_Constr_Subt_For_UN_Aliased (gnat_result_type)
+ || (Ekind (gnat_entity) == E_Constant
+ && Present (Full_View (gnat_entity))
+ && Has_Discriminants (gnat_result_type)
&& TREE_CODE (gnu_result) == CONSTRUCTOR))
{
gnu_result_type = TREE_TYPE (gnu_result);
@@ -2024,12 +2040,13 @@ check_inlining_for_nested_subprog (tree fndecl)
if (lookup_attribute ("always_inline", DECL_ATTRIBUTES (parent_decl)))
{
- error_at (loc1, "subprogram %q+F not marked Inline_Always", fndecl);
+ error_at (loc1, "subprogram %q+F not marked %<Inline_Always%>",
+ fndecl);
error_at (loc2, "parent subprogram cannot be inlined");
}
else
{
- warning_at (loc1, OPT_Winline, "subprogram %q+F not marked Inline",
+ warning_at (loc1, OPT_Winline, "subprogram %q+F not marked %<Inline%>",
fndecl);
warning_at (loc2, OPT_Winline, "parent subprogram cannot be inlined");
}
@@ -2300,21 +2317,24 @@ Attribute_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p, int attribute)
case Attr_Object_Size:
case Attr_Value_Size:
case Attr_Max_Size_In_Storage_Elements:
- gnu_expr = gnu_prefix;
-
- /* Remove NOPs and conversions between original and packable version
- from GNU_EXPR, and conversions from GNU_PREFIX. We use GNU_EXPR
- to see if a COMPONENT_REF was involved. */
- while (TREE_CODE (gnu_expr) == NOP_EXPR
- || (TREE_CODE (gnu_expr) == VIEW_CONVERT_EXPR
- && TREE_CODE (TREE_TYPE (gnu_expr)) == RECORD_TYPE
- && TREE_CODE (TREE_TYPE (TREE_OPERAND (gnu_expr, 0)))
+ /* Strip NOPs, conversions between original and packable versions, and
+ unpadding from GNU_PREFIX. Note that we cannot simply strip every
+ VIEW_CONVERT_EXPR because some of them may give the actual size, e.g.
+ for nominally unconstrained packed array. We use GNU_EXPR to see
+ if a COMPONENT_REF was involved. */
+ while (CONVERT_EXPR_P (gnu_prefix)
+ || TREE_CODE (gnu_prefix) == NON_LVALUE_EXPR
+ || (TREE_CODE (gnu_prefix) == VIEW_CONVERT_EXPR
+ && TREE_CODE (TREE_TYPE (gnu_prefix)) == RECORD_TYPE
+ && TREE_CODE (TREE_TYPE (TREE_OPERAND (gnu_prefix, 0)))
== RECORD_TYPE
- && TYPE_NAME (TREE_TYPE (gnu_expr))
- == TYPE_NAME (TREE_TYPE (TREE_OPERAND (gnu_expr, 0)))))
- gnu_expr = TREE_OPERAND (gnu_expr, 0);
-
- gnu_prefix = remove_conversions (gnu_prefix, true);
+ && TYPE_NAME (TREE_TYPE (gnu_prefix))
+ == TYPE_NAME (TREE_TYPE (TREE_OPERAND (gnu_prefix, 0)))))
+ gnu_prefix = TREE_OPERAND (gnu_prefix, 0);
+ gnu_expr = gnu_prefix;
+ if (TREE_CODE (gnu_prefix) == COMPONENT_REF
+ && TYPE_IS_PADDING_P (TREE_TYPE (TREE_OPERAND (gnu_prefix, 0))))
+ gnu_prefix = TREE_OPERAND (gnu_prefix, 0);
prefix_unused = true;
gnu_type = TREE_TYPE (gnu_prefix);
@@ -2377,7 +2397,7 @@ Attribute_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p, int attribute)
/* Deal with a self-referential size by qualifying the size with the
object or returning the maximum size for a type. */
if (TREE_CODE (gnu_prefix) != TYPE_DECL)
- gnu_result = SUBSTITUTE_PLACEHOLDER_IN_EXPR (gnu_result, gnu_expr);
+ gnu_result = SUBSTITUTE_PLACEHOLDER_IN_EXPR (gnu_result, gnu_prefix);
else if (CONTAINS_PLACEHOLDER_P (gnu_result))
gnu_result = max_size (gnu_result, true);
@@ -3293,7 +3313,7 @@ independent_iterations_p (tree stmt_list)
{
tree_stmt_iterator tsi;
bitmap params = BITMAP_GGC_ALLOC();
- auto_vec<tree> rhs;
+ auto_vec<tree, 16> rhs;
tree iter;
int i;
@@ -4266,6 +4286,20 @@ finalize_nrv_unc_r (tree *tp, int *walk_subtrees, void *data)
return NULL_TREE;
}
+/* Apply FUNC to all the sub-trees of nested functions in NODE. FUNC is called
+ with the DATA and the address of each sub-tree. If FUNC returns a non-NULL
+ value, the traversal is stopped. */
+
+static void
+walk_nesting_tree (struct cgraph_node *node, walk_tree_fn func, void *data)
+{
+ for (node = node->nested; node; node = node->next_nested)
+ {
+ walk_tree_without_duplicates (&DECL_SAVED_TREE (node->decl), func, data);
+ walk_nesting_tree (node, func, 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. GNAT_RET is a representative return node. */
@@ -4273,7 +4307,6 @@ finalize_nrv_unc_r (tree *tp, int *walk_subtrees, void *data)
static void
finalize_nrv (tree fndecl, bitmap nrv, vec<tree, va_gc> *other, Node_Id gnat_ret)
{
- struct cgraph_node *node;
struct nrv_data data;
walk_tree_fn func;
unsigned int i;
@@ -4294,10 +4327,7 @@ finalize_nrv (tree fndecl, bitmap nrv, vec<tree, va_gc> *other, Node_Id gnat_ret
return;
/* Prune also the candidates that are referenced by nested functions. */
- node = cgraph_node::get_create (fndecl);
- for (node = node->nested; node; node = node->next_nested)
- walk_tree_without_duplicates (&DECL_SAVED_TREE (node->decl), prune_nrv_r,
- &data);
+ walk_nesting_tree (cgraph_node::get_create (fndecl), prune_nrv_r, &data);
if (bitmap_empty_p (nrv))
return;
@@ -5015,8 +5045,10 @@ Call_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p, tree gnu_target,
tree gnu_subprog_type = TREE_TYPE (gnu_subprog);
/* The return type of the FUNCTION_TYPE. */
tree gnu_result_type = TREE_TYPE (gnu_subprog_type);
- tree gnu_subprog_addr = build_unary_op (ADDR_EXPR, NULL_TREE, gnu_subprog);
- vec<tree, va_gc> *gnu_actual_vec = NULL;
+ const bool frontend_builtin
+ = (TREE_CODE (gnu_subprog) == FUNCTION_DECL
+ && DECL_BUILT_IN_CLASS (gnu_subprog) == BUILT_IN_FRONTEND);
+ auto_vec<tree, 16> gnu_actual_vec;
tree gnu_name_list = NULL_TREE;
tree gnu_stmt_list = NULL_TREE;
tree gnu_after_list = NULL_TREE;
@@ -5297,13 +5329,23 @@ Call_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p, tree gnu_target,
/* Create an explicit temporary holding the copy. */
if (atomic_p)
gnu_name = build_atomic_load (gnu_name, sync);
- gnu_temp
- = create_init_temporary ("A", gnu_name, &gnu_stmt, gnat_actual);
- /* But initialize it on the fly like for an implicit temporary as
- we aren't necessarily having a statement list. */
- gnu_name = build_compound_expr (TREE_TYPE (gnu_name), gnu_stmt,
- gnu_temp);
+ /* Do not initialize it for the _Init parameter of an initialization
+ procedure since no data is meant to be passed in. */
+ if (Ekind (gnat_formal) == E_Out_Parameter
+ && Is_Entity_Name (Name (gnat_node))
+ && Is_Init_Proc (Entity (Name (gnat_node))))
+ gnu_name = gnu_temp = create_temporary ("A", TREE_TYPE (gnu_name));
+
+ /* Initialize it on the fly like for an implicit temporary in the
+ other cases, as we don't necessarily have a statement list. */
+ else
+ {
+ gnu_temp = create_init_temporary ("A", gnu_name, &gnu_stmt,
+ gnat_actual);
+ gnu_name = build_compound_expr (TREE_TYPE (gnu_name), gnu_stmt,
+ gnu_temp);
+ }
/* Set up to move the copy back to the original if needed. */
if (!in_param)
@@ -5354,7 +5396,7 @@ Call_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p, tree gnu_target,
since the parent is a procedure call, so put it back here. Note that
we might have a dummy type here if the actual is the dereference of a
pointer to it, but that's OK if the formal is passed by reference. */
- tree gnu_actual_type = gnat_to_gnu_type (Etype (gnat_actual));
+ tree gnu_actual_type = get_unpadded_type (Etype (gnat_actual));
if (TYPE_IS_DUMMY_P (gnu_actual_type))
gcc_assert (is_true_formal_parm && DECL_BY_REF_P (gnu_formal));
else if (suppress_type_conversion
@@ -5473,16 +5515,56 @@ Call_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p, tree gnu_target,
build_int_cst (type_for_size, 0),
false);
}
- else
+
+ /* If this is a front-end built-in function, there is no need to
+ convert to the type used to pass the argument. */
+ else if (!frontend_builtin)
gnu_actual = convert (DECL_ARG_TYPE (gnu_formal), gnu_actual);
}
- vec_safe_push (gnu_actual_vec, gnu_actual);
+ gnu_actual_vec.safe_push (gnu_actual);
+ }
+
+ if (frontend_builtin)
+ {
+ tree pred_cst = build_int_cst (integer_type_node, PRED_BUILTIN_EXPECT);
+ enum internal_fn icode = IFN_BUILTIN_EXPECT;
+
+ switch (DECL_FUNCTION_CODE (gnu_subprog))
+ {
+ case BUILT_IN_EXPECT:
+ break;
+ case BUILT_IN_LIKELY:
+ gnu_actual_vec.safe_push (boolean_true_node);
+ break;
+ case BUILT_IN_UNLIKELY:
+ gnu_actual_vec.safe_push (boolean_false_node);
+ break;
+ default:
+ gcc_unreachable ();
+ }
+
+ gnu_actual_vec.safe_push (pred_cst);
+
+ gnu_call
+ = build_call_expr_internal_loc_array (UNKNOWN_LOCATION,
+ icode,
+ gnu_result_type,
+ gnu_actual_vec.length (),
+ gnu_actual_vec.begin ());
+ }
+ else
+ {
+ gnu_call
+ = build_call_array_loc (UNKNOWN_LOCATION,
+ gnu_result_type,
+ build_unary_op (ADDR_EXPR, NULL_TREE,
+ gnu_subprog),
+ gnu_actual_vec.length (),
+ gnu_actual_vec.begin ());
+ CALL_EXPR_BY_DESCRIPTOR (gnu_call) = by_descriptor;
}
- gnu_call
- = build_call_vec (gnu_result_type, gnu_subprog_addr, gnu_actual_vec);
- CALL_EXPR_BY_DESCRIPTOR (gnu_call) = by_descriptor;
set_expr_location_from_node (gnu_call, gnat_node);
/* If we have created a temporary for the return value, initialize it. */
@@ -6306,24 +6388,17 @@ Compilation_Unit_to_gnu (Node_Id gnat_node)
The compiler will automatically predict the last edge leading to a call
to a noreturn function as very unlikely taken. This function makes it
- possible to expand the prediction to predecessors in case the condition
+ possible to extend the prediction to predecessors in case the condition
is made up of several short-circuit operators. */
static tree
build_noreturn_cond (tree cond)
{
- tree fn = builtin_decl_explicit (BUILT_IN_EXPECT);
- tree arg_types = TYPE_ARG_TYPES (TREE_TYPE (fn));
- tree pred_type = TREE_VALUE (arg_types);
- tree expected_type = TREE_VALUE (TREE_CHAIN (arg_types));
-
- tree t = build_call_expr (fn, 3,
- fold_convert (pred_type, cond),
- build_int_cst (expected_type, 0),
- build_int_cst (integer_type_node,
- PRED_NORETURN));
-
- return build1 (NOP_EXPR, boolean_type_node, t);
+ tree pred_cst = build_int_cst (integer_type_node, PRED_NORETURN);
+ return
+ build_call_expr_internal_loc (UNKNOWN_LOCATION, IFN_BUILTIN_EXPECT,
+ boolean_type_node, 3, cond,
+ boolean_false_node, pred_cst);
}
/* Subroutine of gnat_to_gnu to translate GNAT_RANGE, a node representing a
@@ -7421,7 +7496,7 @@ gnat_to_gnu (Node_Id gnat_node)
enum tree_code code = gnu_codes[kind];
bool ignore_lhs_overflow = false;
location_t saved_location = input_location;
- tree gnu_type;
+ tree gnu_type, gnu_max_shift = NULL_TREE;
/* Fix operations set up for boolean types in GNU_CODES above. */
if (Is_Modular_Integer_Type (Underlying_Type (Etype (gnat_node))))
@@ -7444,6 +7519,17 @@ gnat_to_gnu (Node_Id gnat_node)
gnu_rhs = gnat_to_gnu (Right_Opnd (gnat_node));
gnu_type = gnu_result_type = get_unpadded_type (Etype (gnat_node));
+ /* If this is a shift, take the count as unsigned since that is what
+ most machines do and will generate simpler adjustments below. */
+ if (IN (kind, N_Op_Shift))
+ {
+ tree gnu_count_type
+ = gnat_unsigned_type_for (get_base_type (TREE_TYPE (gnu_rhs)));
+ gnu_rhs = convert (gnu_count_type, gnu_rhs);
+ gnu_max_shift
+ = convert (TREE_TYPE (gnu_rhs), TYPE_SIZE (gnu_type));
+ }
+
/* Pending generic support for efficient vector logical operations in
GCC, convert vectors to their representative array type view and
fallthrough. */
@@ -7467,25 +7553,20 @@ gnat_to_gnu (Node_Id gnat_node)
/* If this is a shift whose count is not guaranteed to be correct,
we need to adjust the shift count. */
- if (IN (kind, N_Op_Shift) && !Shift_Count_OK (gnat_node))
- {
- tree gnu_count_type = get_base_type (TREE_TYPE (gnu_rhs));
- tree gnu_max_shift
- = convert (gnu_count_type, TYPE_SIZE (gnu_type));
-
- if (kind == N_Op_Rotate_Left || kind == N_Op_Rotate_Right)
- gnu_rhs = build_binary_op (TRUNC_MOD_EXPR, gnu_count_type,
- gnu_rhs, gnu_max_shift);
- else if (kind == N_Op_Shift_Right_Arithmetic)
- gnu_rhs
- = build_binary_op
- (MIN_EXPR, gnu_count_type,
- build_binary_op (MINUS_EXPR,
- gnu_count_type,
- gnu_max_shift,
- build_int_cst (gnu_count_type, 1)),
- gnu_rhs);
- }
+ if ((kind == N_Op_Rotate_Left || kind == N_Op_Rotate_Right)
+ && !Shift_Count_OK (gnat_node))
+ gnu_rhs = build_binary_op (TRUNC_MOD_EXPR, TREE_TYPE (gnu_rhs),
+ gnu_rhs, gnu_max_shift);
+ else if (kind == N_Op_Shift_Right_Arithmetic
+ && !Shift_Count_OK (gnat_node))
+ gnu_rhs
+ = build_binary_op (MIN_EXPR, TREE_TYPE (gnu_rhs),
+ build_binary_op (MINUS_EXPR,
+ TREE_TYPE (gnu_rhs),
+ gnu_max_shift,
+ build_int_cst
+ (TREE_TYPE (gnu_rhs), 1)),
+ gnu_rhs);
/* For right shifts, the type says what kind of shift to do,
so we may need to choose a different type. In this case,
@@ -7512,16 +7593,15 @@ gnat_to_gnu (Node_Id gnat_node)
gnu_rhs = convert (gnu_type, gnu_rhs);
}
- /* Instead of expanding overflow checks for addition, subtraction
- and multiplication itself, the front end will leave this to
- the back end when Backend_Overflow_Checks_On_Target is set. */
+ /* For signed integer addition, subtraction and multiplication, do an
+ overflow check if required. */
if (Do_Overflow_Check (gnat_node)
- && Backend_Overflow_Checks_On_Target
&& (code == PLUS_EXPR || code == MINUS_EXPR || code == MULT_EXPR)
&& !TYPE_UNSIGNED (gnu_type)
&& !FLOAT_TYPE_P (gnu_type))
- gnu_result = build_binary_op_trapv (code, gnu_type,
- gnu_lhs, gnu_rhs, gnat_node);
+ gnu_result
+ = build_binary_op_trapv (code, gnu_type, gnu_lhs, gnu_rhs,
+ gnat_node);
else
{
/* Some operations, e.g. comparisons of arrays, generate complex
@@ -7532,18 +7612,15 @@ gnat_to_gnu (Node_Id gnat_node)
/* If this is a logical shift with the shift count not verified,
we must return zero if it is too large. We cannot compensate
- above in this case. */
+ beforehand in this case. */
if ((kind == N_Op_Shift_Left || kind == N_Op_Shift_Right)
&& !Shift_Count_OK (gnat_node))
gnu_result
- = build_cond_expr
- (gnu_type,
- build_binary_op (GE_EXPR, boolean_type_node,
- gnu_rhs,
- convert (TREE_TYPE (gnu_rhs),
- TYPE_SIZE (gnu_type))),
- build_int_cst (gnu_type, 0),
- gnu_result);
+ = build_cond_expr (gnu_type,
+ build_binary_op (GE_EXPR, boolean_type_node,
+ gnu_rhs, gnu_max_shift),
+ build_int_cst (gnu_type, 0),
+ gnu_result);
}
break;
@@ -7585,19 +7662,17 @@ gnat_to_gnu (Node_Id gnat_node)
gnu_expr = gnat_to_gnu (Right_Opnd (gnat_node));
gnu_result_type = get_unpadded_type (Etype (gnat_node));
- /* Instead of expanding overflow checks for negation and absolute
- value itself, the front end will leave this to the back end
- when Backend_Overflow_Checks_On_Target is set. */
+ /* For signed integer negation and absolute value, do an overflow check
+ if required. */
if (Do_Overflow_Check (gnat_node)
- && Backend_Overflow_Checks_On_Target
&& !TYPE_UNSIGNED (gnu_result_type)
&& !FLOAT_TYPE_P (gnu_result_type))
gnu_result
- = build_unary_op_trapv (gnu_codes[kind],
- gnu_result_type, gnu_expr, gnat_node);
+ = build_unary_op_trapv (gnu_codes[kind], gnu_result_type, gnu_expr,
+ gnat_node);
else
- gnu_result = build_unary_op (gnu_codes[kind],
- gnu_result_type, gnu_expr);
+ gnu_result
+ = build_unary_op (gnu_codes[kind], gnu_result_type, gnu_expr);
break;
case N_Allocator:
@@ -8669,7 +8744,11 @@ gnat_to_gnu (Node_Id gnat_node)
declaration, return the result unmodified because we want to use the
return slot optimization in this case.
- 5. Finally, if the type of the result is already correct. */
+ 5. If this is a reference to an unconstrained array which is used as the
+ prefix of an attribute reference that requires an lvalue, return the
+ result unmodified because we want return the original bounds.
+
+ 6. Finally, if the type of the result is already correct. */
if (Present (Parent (gnat_node))
&& (lhs_or_actual_p (gnat_node)
@@ -8718,13 +8797,19 @@ gnat_to_gnu (Node_Id gnat_node)
else if (gnu_result == error_mark_node || gnu_result_type == void_type_node)
gnu_result = error_mark_node;
- else if (Present (Parent (gnat_node))
+ else if (TREE_CODE (gnu_result) == CALL_EXPR
+ && Present (Parent (gnat_node))
&& (Nkind (Parent (gnat_node)) == N_Object_Declaration
|| Nkind (Parent (gnat_node)) == N_Object_Renaming_Declaration)
- && TREE_CODE (gnu_result) == CALL_EXPR
&& return_type_with_variable_size_p (TREE_TYPE (gnu_result)))
;
+ else if (TREE_CODE (gnu_result) == UNCONSTRAINED_ARRAY_REF
+ && Present (Parent (gnat_node))
+ && Nkind (Parent (gnat_node)) == N_Attribute_Reference
+ && lvalue_required_for_attribute_p (Parent (gnat_node)))
+ ;
+
else if (TREE_TYPE (gnu_result) != gnu_result_type)
gnu_result = convert (gnu_result_type, gnu_result);
@@ -8957,8 +9042,9 @@ mark_visited_r (tree *tp, int *walk_subtrees, void *data ATTRIBUTE_UNUSED)
else if (!TYPE_IS_DUMMY_P (t))
TREE_VISITED (t) = 1;
+ /* The test in gimplify_type_sizes is on the main variant. */
if (TYPE_P (t))
- TYPE_SIZES_GIMPLIFIED (t) = 1;
+ TYPE_SIZES_GIMPLIFIED (TYPE_MAIN_VARIANT (t)) = 1;
return NULL_TREE;
}
diff --git a/gcc/ada/gcc-interface/utils.c b/gcc/ada/gcc-interface/utils.c
index da4e100..c6942fe 100644
--- a/gcc/ada/gcc-interface/utils.c
+++ b/gcc/ada/gcc-interface/utils.c
@@ -90,15 +90,31 @@ static tree handle_novops_attribute (tree *, tree, tree, int, bool *);
static tree handle_nonnull_attribute (tree *, tree, tree, int, bool *);
static tree handle_sentinel_attribute (tree *, tree, tree, int, bool *);
static tree handle_noreturn_attribute (tree *, tree, tree, int, bool *);
+static tree handle_stack_protect_attribute (tree *, tree, tree, int, bool *);
static tree handle_noinline_attribute (tree *, tree, tree, int, bool *);
static tree handle_noclone_attribute (tree *, tree, tree, int, bool *);
+static tree handle_noicf_attribute (tree *, tree, tree, int, bool *);
+static tree handle_noipa_attribute (tree *, tree, tree, int, bool *);
static tree handle_leaf_attribute (tree *, tree, tree, int, bool *);
static tree handle_always_inline_attribute (tree *, tree, tree, int, bool *);
static tree handle_malloc_attribute (tree *, tree, tree, int, bool *);
static tree handle_type_generic_attribute (tree *, tree, tree, int, bool *);
+static tree handle_flatten_attribute (tree *, tree, tree, int, bool *);
+static tree handle_used_attribute (tree *, tree, tree, int, bool *);
+static tree handle_cold_attribute (tree *, tree, tree, int, bool *);
+static tree handle_hot_attribute (tree *, tree, tree, int, bool *);
+static tree handle_target_attribute (tree *, tree, tree, int, bool *);
+static tree handle_target_clones_attribute (tree *, tree, tree, int, bool *);
static tree handle_vector_size_attribute (tree *, tree, tree, int, bool *);
static tree handle_vector_type_attribute (tree *, tree, tree, int, bool *);
+static const struct attribute_spec::exclusions attr_cold_hot_exclusions[] =
+{
+ { "cold", true, true, true },
+ { "hot" , true, true, true },
+ { NULL , false, false, false }
+};
+
/* Fake handler for attributes we don't properly support, typically because
they'd require dragging a lot of the common-c front-end circuitry. */
static tree fake_attribute_handler (tree *, tree, tree, int, bool *);
@@ -123,34 +139,55 @@ const struct attribute_spec gnat_internal_attribute_table[] =
handle_sentinel_attribute, NULL },
{ "noreturn", 0, 0, true, false, false, false,
handle_noreturn_attribute, NULL },
+ { "stack_protect",0, 0, true, false, false, false,
+ handle_stack_protect_attribute, NULL },
{ "noinline", 0, 0, true, false, false, false,
handle_noinline_attribute, NULL },
{ "noclone", 0, 0, true, false, false, false,
handle_noclone_attribute, NULL },
+ { "no_icf", 0, 0, true, false, false, false,
+ handle_noicf_attribute, NULL },
+ { "noipa", 0, 0, true, false, false, false,
+ handle_noipa_attribute, NULL },
{ "leaf", 0, 0, true, false, false, false,
handle_leaf_attribute, NULL },
{ "always_inline",0, 0, true, false, false, false,
handle_always_inline_attribute, NULL },
{ "malloc", 0, 0, true, false, false, false,
handle_malloc_attribute, NULL },
- { "type generic", 0, 0, false, true, true, false,
+ { "type generic", 0, 0, false, true, true, false,
handle_type_generic_attribute, NULL },
- { "vector_size", 1, 1, false, true, false, false,
+ { "flatten", 0, 0, true, false, false, false,
+ handle_flatten_attribute, NULL },
+ { "used", 0, 0, true, false, false, false,
+ handle_used_attribute, NULL },
+ { "cold", 0, 0, true, false, false, false,
+ handle_cold_attribute, attr_cold_hot_exclusions },
+ { "hot", 0, 0, true, false, false, false,
+ handle_hot_attribute, attr_cold_hot_exclusions },
+ { "target", 1, -1, true, false, false, false,
+ handle_target_attribute, NULL },
+ { "target_clones",1, -1, true, false, false, false,
+ handle_target_clones_attribute, NULL },
+
+ { "vector_size", 1, 1, false, true, false, false,
handle_vector_size_attribute, NULL },
- { "vector_type", 0, 0, false, true, false, false,
+ { "vector_type", 0, 0, false, true, false, false,
handle_vector_type_attribute, NULL },
- { "may_alias", 0, 0, false, true, false, false, NULL, NULL },
+ { "may_alias", 0, 0, false, true, false, false,
+ NULL, NULL },
/* ??? format and format_arg are heavy and not supported, which actually
prevents support for stdio builtins, which we however declare as part
of the common builtins.def contents. */
- { "format", 3, 3, false, true, true, false, fake_attribute_handler,
- NULL },
- { "format_arg", 1, 1, false, true, true, false, fake_attribute_handler,
- NULL },
+ { "format", 3, 3, false, true, true, false,
+ fake_attribute_handler, NULL },
+ { "format_arg", 1, 1, false, true, true, false,
+ fake_attribute_handler, NULL },
- { NULL, 0, 0, false, false, false, false, NULL, NULL }
+ { NULL, 0, 0, false, false, false, false,
+ NULL, NULL }
};
/* Associates a GNAT tree node to a GCC tree node. It is used in
@@ -947,10 +984,45 @@ make_aligning_type (tree type, unsigned int align, tree size,
return record_type;
}
+/* TYPE is an ARRAY_TYPE that is being used as the type of a field in a packed
+ record. See if we can rewrite it as a type that has non-BLKmode, which we
+ can pack tighter in the packed record. If so, return the new type; if not,
+ return the original type. */
+
+static tree
+make_packable_array_type (tree type)
+{
+ const unsigned HOST_WIDE_INT size = tree_to_uhwi (TYPE_SIZE (type));
+ unsigned HOST_WIDE_INT new_size;
+ unsigned int new_align;
+
+ /* No point in doing anything if the size is either zero or too large for an
+ integral mode, or if the type already has non-BLKmode. */
+ if (size == 0 || size > MAX_FIXED_MODE_SIZE || TYPE_MODE (type) != BLKmode)
+ return type;
+
+ /* Punt if the component type is an aggregate type for now. */
+ if (AGGREGATE_TYPE_P (TREE_TYPE (type)))
+ return type;
+
+ tree new_type = copy_type (type);
+
+ new_size = ceil_pow2 (size);
+ new_align = MIN (new_size, BIGGEST_ALIGNMENT);
+ SET_TYPE_ALIGN (new_type, new_align);
+
+ TYPE_SIZE (new_type) = bitsize_int (new_size);
+ TYPE_SIZE_UNIT (new_type) = size_int (new_size / BITS_PER_UNIT);
+
+ SET_TYPE_MODE (new_type, mode_for_size (new_size, MODE_INT, 1).else_blk ());
+
+ return new_type;
+}
+
/* TYPE is a RECORD_TYPE, UNION_TYPE or QUAL_UNION_TYPE that is being used
- as the field type of a packed record if IN_RECORD is true, or as the
- component type of a packed array if IN_RECORD is false. See if we can
- rewrite it either as a type that has non-BLKmode, which we can pack
+ as the type of a field in a packed record if IN_RECORD is true, or as
+ the component type of a packed array if IN_RECORD is false. See if we
+ can rewrite it either as a type that has non-BLKmode, which we can pack
tighter in the packed record case, or as a smaller type with at most
MAX_ALIGN alignment if the value is non-zero. If so, return the new
type; if not, return the original type. */
@@ -958,9 +1030,9 @@ make_aligning_type (tree type, unsigned int align, tree size,
tree
make_packable_type (tree type, bool in_record, unsigned int max_align)
{
- unsigned HOST_WIDE_INT size = tree_to_uhwi (TYPE_SIZE (type));
+ const unsigned HOST_WIDE_INT size = tree_to_uhwi (TYPE_SIZE (type));
+ const unsigned int align = TYPE_ALIGN (type);
unsigned HOST_WIDE_INT new_size;
- unsigned int align = TYPE_ALIGN (type);
unsigned int new_align;
/* No point in doing anything if the size is zero. */
@@ -1021,10 +1093,19 @@ make_packable_type (tree type, bool in_record, unsigned int max_align)
tree new_field_type = TREE_TYPE (field);
tree new_field, new_field_size;
- if (RECORD_OR_UNION_TYPE_P (new_field_type)
- && !TYPE_FAT_POINTER_P (new_field_type)
+ if (AGGREGATE_TYPE_P (new_field_type)
&& tree_fits_uhwi_p (TYPE_SIZE (new_field_type)))
- new_field_type = make_packable_type (new_field_type, true, max_align);
+ {
+ if (RECORD_OR_UNION_TYPE_P (new_field_type)
+ && !TYPE_FAT_POINTER_P (new_field_type))
+ new_field_type
+ = make_packable_type (new_field_type, true, max_align);
+ else if (in_record
+ && max_align > 0
+ && max_align < BITS_PER_UNIT
+ && TREE_CODE (new_field_type) == ARRAY_TYPE)
+ new_field_type = make_packable_array_type (new_field_type);
+ }
/* However, for the last field in a not already packed record type
that is of an aggregate type, we need to use the RM size in the
@@ -1374,7 +1455,7 @@ maybe_pad_type (tree type, tree size, unsigned int align,
different modes, a VIEW_CONVERT_EXPR will be required for converting
between them and it might be hard to overcome afterwards, including
at the RTL level when the stand-alone object is accessed as a whole. */
- if (align != 0
+ if (align > 0
&& RECORD_OR_UNION_TYPE_P (type)
&& TYPE_MODE (type) == BLKmode
&& !TYPE_BY_REFERENCE_P (type)
@@ -1385,7 +1466,7 @@ maybe_pad_type (tree type, tree size, unsigned int align,
|| (TREE_CODE (size) == INTEGER_CST
&& compare_tree_int (size, MAX_FIXED_MODE_SIZE) <= 0)))
{
- tree packable_type = make_packable_type (type, true);
+ tree packable_type = make_packable_type (type, true, align);
if (TYPE_MODE (packable_type) != BLKmode
&& align >= TYPE_ALIGN (packable_type))
type = packable_type;
@@ -1530,14 +1611,14 @@ built:
generated for some other corresponding source entity. */
if (Comes_From_Source (gnat_entity))
{
- if (Present (gnat_error_node))
- post_error_ne_tree ("{^ }bits of & unused?",
- gnat_error_node, gnat_entity,
- size_diffop (size, orig_size));
- else if (is_component_type)
+ if (is_component_type)
post_error_ne_tree ("component of& padded{ by ^ bits}?",
gnat_entity, gnat_entity,
size_diffop (size, orig_size));
+ else if (Present (gnat_error_node))
+ post_error_ne_tree ("{^ }bits of & unused?",
+ gnat_error_node, gnat_entity,
+ size_diffop (size, orig_size));
}
}
@@ -1778,13 +1859,18 @@ void
finish_record_type (tree record_type, tree field_list, int rep_level,
bool debug_info_p)
{
- enum tree_code code = TREE_CODE (record_type);
+ const enum tree_code orig_code = TREE_CODE (record_type);
+ const bool had_size = TYPE_SIZE (record_type) != NULL_TREE;
+ const bool had_size_unit = TYPE_SIZE_UNIT (record_type) != NULL_TREE;
+ const bool had_align = TYPE_ALIGN (record_type) > 0;
+ /* For all-repped records with a size specified, lay the QUAL_UNION_TYPE
+ out just like a UNION_TYPE, since the size will be fixed. */
+ const enum tree_code code
+ = (orig_code == QUAL_UNION_TYPE && rep_level > 0 && had_size
+ ? UNION_TYPE : orig_code);
tree name = TYPE_IDENTIFIER (record_type);
tree ada_size = bitsize_zero_node;
tree size = bitsize_zero_node;
- bool had_size = TYPE_SIZE (record_type) != 0;
- bool had_size_unit = TYPE_SIZE_UNIT (record_type) != 0;
- bool had_align = TYPE_ALIGN (record_type) != 0;
tree field;
TYPE_FIELDS (record_type) = field_list;
@@ -1797,26 +1883,21 @@ finish_record_type (tree record_type, tree field_list, int rep_level,
that just means some initializations; otherwise, layout the record. */
if (rep_level > 0)
{
- SET_TYPE_ALIGN (record_type, MAX (BITS_PER_UNIT,
- TYPE_ALIGN (record_type)));
-
- if (!had_size_unit)
- TYPE_SIZE_UNIT (record_type) = size_zero_node;
+ if (TYPE_ALIGN (record_type) < BITS_PER_UNIT)
+ SET_TYPE_ALIGN (record_type, BITS_PER_UNIT);
if (!had_size)
TYPE_SIZE (record_type) = bitsize_zero_node;
- /* For all-repped records with a size specified, lay the QUAL_UNION_TYPE
- out just like a UNION_TYPE, since the size will be fixed. */
- else if (code == QUAL_UNION_TYPE)
- code = UNION_TYPE;
+ if (!had_size_unit)
+ TYPE_SIZE_UNIT (record_type) = size_zero_node;
}
else
{
/* Ensure there isn't a size already set. There can be in an error
case where there is a rep clause but all fields have errors and
no longer have a position. */
- TYPE_SIZE (record_type) = 0;
+ TYPE_SIZE (record_type) = NULL_TREE;
/* Ensure we use the traditional GCC layout for bitfields when we need
to pack the record type or have a representation clause. The other
@@ -1860,6 +1941,9 @@ finish_record_type (tree record_type, tree field_list, int rep_level,
else
this_ada_size = this_size;
+ const bool variant_part = (TREE_CODE (type) == QUAL_UNION_TYPE);
+ const bool variant_part_at_zero = variant_part && integer_zerop (pos);
+
/* Clear DECL_BIT_FIELD for the cases layout_decl does not handle. */
if (DECL_BIT_FIELD (field)
&& operand_equal_p (this_size, TYPE_SIZE (type), 0))
@@ -1901,9 +1985,7 @@ finish_record_type (tree record_type, tree field_list, int rep_level,
/* Clear DECL_BIT_FIELD_TYPE for a variant part at offset 0, it's simply
not supported by the DECL_BIT_FIELD_REPRESENTATIVE machinery because
the variant part is always the last field in the list. */
- if (DECL_INTERNAL_P (field)
- && TREE_CODE (TREE_TYPE (field)) == QUAL_UNION_TYPE
- && integer_zerop (pos))
+ if (variant_part_at_zero)
DECL_BIT_FIELD_TYPE (field) = NULL_TREE;
/* If we still have DECL_BIT_FIELD set at this point, we know that the
@@ -1938,18 +2020,18 @@ finish_record_type (tree record_type, tree field_list, int rep_level,
case RECORD_TYPE:
/* Since we know here that all fields are sorted in order of
increasing bit position, the size of the record is one
- higher than the ending bit of the last field processed
- unless we have a rep clause, since in that case we might
- have a field outside a QUAL_UNION_TYPE that has a higher ending
- position. So use a MAX in that case. Also, if this field is a
- QUAL_UNION_TYPE, we need to take into account the previous size in
- the case of empty variants. */
+ higher than the ending bit of the last field processed,
+ unless we have a variant part at offset 0, since in this
+ case we might have a field outside the variant part that
+ has a higher ending position; so use a MAX in this case.
+ Also, if this field is a QUAL_UNION_TYPE, we need to take
+ into account the previous size in the case of empty variants. */
ada_size
- = merge_sizes (ada_size, pos, this_ada_size,
- TREE_CODE (type) == QUAL_UNION_TYPE, rep_level > 0);
+ = merge_sizes (ada_size, pos, this_ada_size, variant_part,
+ variant_part_at_zero);
size
- = merge_sizes (size, pos, this_size,
- TREE_CODE (type) == QUAL_UNION_TYPE, rep_level > 0);
+ = merge_sizes (size, pos, this_size, variant_part,
+ variant_part_at_zero);
break;
default:
@@ -2230,13 +2312,12 @@ rest_of_record_type_compilation (tree record_type)
/* Utility function of above to merge LAST_SIZE, the previous size of a record
with FIRST_BIT and SIZE that describe a field. SPECIAL is true if this
represents a QUAL_UNION_TYPE in which case we must look for COND_EXPRs and
- replace a value of zero with the old size. If HAS_REP is true, we take the
+ replace a value of zero with the old size. If MAX is true, we take the
MAX of the end position of this field with LAST_SIZE. In all other cases,
we use FIRST_BIT plus SIZE. Return an expression for the size. */
static tree
-merge_sizes (tree last_size, tree first_bit, tree size, bool special,
- bool has_rep)
+merge_sizes (tree last_size, tree first_bit, tree size, bool special, bool max)
{
tree type = TREE_TYPE (last_size);
tree new_size;
@@ -2244,7 +2325,7 @@ merge_sizes (tree last_size, tree first_bit, tree size, bool special,
if (!special || TREE_CODE (size) != COND_EXPR)
{
new_size = size_binop (PLUS_EXPR, first_bit, size);
- if (has_rep)
+ if (max)
new_size = size_binop (MAX_EXPR, last_size, new_size);
}
@@ -2253,11 +2334,11 @@ merge_sizes (tree last_size, tree first_bit, tree size, bool special,
integer_zerop (TREE_OPERAND (size, 1))
? last_size : merge_sizes (last_size, first_bit,
TREE_OPERAND (size, 1),
- 1, has_rep),
+ 1, max),
integer_zerop (TREE_OPERAND (size, 2))
? last_size : merge_sizes (last_size, first_bit,
TREE_OPERAND (size, 2),
- 1, has_rep));
+ 1, max));
/* We don't need any NON_VALUE_EXPRs and they can confuse us (especially
when fed through SUBSTITUTE_IN_EXPR) into thinking that a constant
@@ -2753,10 +2834,9 @@ create_field_decl (tree name, tree type, tree record_type, tree size, tree pos,
size = round_up (size, BITS_PER_UNIT);
}
- /* If we may, according to ADDRESSABLE, make a bitfield when the size is
- specified for two reasons: first if the size differs from the natural
- size; second, if the alignment is insufficient. There are a number of
- ways the latter can be true.
+ /* If we may, according to ADDRESSABLE, then make a bitfield when the size
+ is specified for two reasons: first, when it differs from the natural
+ size; second, when the alignment is insufficient.
We never make a bitfield if the type of the field has a nonconstant size,
because no such entity requiring bitfield operations should reach here.
@@ -2772,17 +2852,17 @@ create_field_decl (tree name, tree type, tree record_type, tree size, tree pos,
&& size
&& TREE_CODE (size) == INTEGER_CST
&& TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST
- && (!tree_int_cst_equal (size, TYPE_SIZE (type))
+ && (packed
+ || !tree_int_cst_equal (size, TYPE_SIZE (type))
|| (pos && !value_factor_p (pos, TYPE_ALIGN (type)))
- || packed
- || (TYPE_ALIGN (record_type) != 0
+ || (TYPE_ALIGN (record_type)
&& TYPE_ALIGN (record_type) < TYPE_ALIGN (type))))
{
DECL_BIT_FIELD (field_decl) = 1;
DECL_SIZE (field_decl) = size;
if (!packed && !pos)
{
- if (TYPE_ALIGN (record_type) != 0
+ if (TYPE_ALIGN (record_type)
&& TYPE_ALIGN (record_type) < TYPE_ALIGN (type))
SET_DECL_ALIGN (field_decl, TYPE_ALIGN (record_type));
else
@@ -2964,10 +3044,12 @@ process_attributes (tree *node, struct attrib **attr_list, bool in_place,
a power of 2. */
bool
-value_factor_p (tree value, HOST_WIDE_INT factor)
+value_factor_p (tree value, unsigned HOST_WIDE_INT factor)
{
+ gcc_checking_assert (pow2p_hwi (factor));
+
if (tree_fits_uhwi_p (value))
- return tree_to_uhwi (value) % factor == 0;
+ return (tree_to_uhwi (value) & (factor - 1)) == 0;
if (TREE_CODE (value) == MULT_EXPR)
return (value_factor_p (TREE_OPERAND (value, 0), factor)
@@ -3394,8 +3476,6 @@ begin_subprog_body (tree subprog_decl)
for (param_decl = DECL_ARGUMENTS (subprog_decl); param_decl;
param_decl = DECL_CHAIN (param_decl))
DECL_CONTEXT (param_decl) = subprog_decl;
-
- make_decl_rtl (subprog_decl);
}
/* Finish translating the current subprogram and set its BODY. */
@@ -5185,8 +5265,8 @@ unchecked_convert (tree type, tree expr, bool notrunc_p)
if (etype == type)
return expr;
- /* If both types are integral just do a normal conversion.
- Likewise for a conversion to an unconstrained array. */
+ /* If both types are integral or regular pointer, then just do a normal
+ conversion. Likewise for a conversion to an unconstrained array. */
if (((INTEGRAL_TYPE_P (type)
|| (POINTER_TYPE_P (type) && !TYPE_IS_THIN_POINTER_P (type))
|| (code == RECORD_TYPE && TYPE_JUSTIFIED_MODULAR_P (type)))
@@ -5317,14 +5397,16 @@ unchecked_convert (tree type, tree expr, bool notrunc_p)
we need to pad to have the same size on both sides.
??? We cannot do it unconditionally because unchecked conversions are
- used liberally by the front-end to implement polymorphism, e.g. in:
+ used liberally by the front-end to implement interface thunks:
+ type ada__tags__addr_ptr is access system.address;
S191s : constant ada__tags__addr_ptr := ada__tags__addr_ptr!(S190s);
return p___size__4 (p__object!(S191s.all));
- so we skip all expressions that are references. */
- else if (!REFERENCE_CLASS_P (expr)
+ so we need to skip dereferences. */
+ else if (!INDIRECT_REF_P (expr)
&& !AGGREGATE_TYPE_P (etype)
+ && ecode != UNCONSTRAINED_ARRAY_TYPE
&& TREE_CONSTANT (TYPE_SIZE (type))
&& (c = tree_int_cst_compare (TYPE_SIZE (etype), TYPE_SIZE (type))))
{
@@ -5344,6 +5426,31 @@ unchecked_convert (tree type, tree expr, bool notrunc_p)
}
}
+ /* Likewise if we are converting from a scalar type to a type with self-
+ referential size. We use the max size to do the padding in this case. */
+ else if (!INDIRECT_REF_P (expr)
+ && !AGGREGATE_TYPE_P (etype)
+ && ecode != UNCONSTRAINED_ARRAY_TYPE
+ && CONTAINS_PLACEHOLDER_P (TYPE_SIZE (type)))
+ {
+ tree new_size = max_size (TYPE_SIZE (type), true);
+ c = tree_int_cst_compare (TYPE_SIZE (etype), new_size);
+ if (c < 0)
+ {
+ expr = convert (maybe_pad_type (etype, new_size, 0, Empty,
+ false, false, false, true),
+ expr);
+ expr = unchecked_convert (type, expr, notrunc_p);
+ }
+ else
+ {
+ tree rec_type = maybe_pad_type (type, TYPE_SIZE (etype), 0, Empty,
+ false, false, false, true);
+ expr = unchecked_convert (rec_type, expr, notrunc_p);
+ expr = build_component_ref (expr, TYPE_FIELDS (rec_type), false);
+ }
+ }
+
/* We have a special case when we are converting between two unconstrained
array types. In that case, take the address, convert the fat pointer
types, and dereference. */
@@ -5877,6 +5984,7 @@ enum c_builtin_type
ARG6, ARG7) NAME,
#define DEF_POINTER_TYPE(NAME, TYPE) NAME,
#include "builtin-types.def"
+#include "ada-builtin-types.def"
#undef DEF_PRIMITIVE_TYPE
#undef DEF_FUNCTION_TYPE_0
#undef DEF_FUNCTION_TYPE_1
@@ -6025,6 +6133,7 @@ install_builtin_function_types (void)
builtin_types[(int) ENUM] = build_pointer_type (builtin_types[(int) TYPE]);
#include "builtin-types.def"
+#include "ada-builtin-types.def"
#undef DEF_PRIMITIVE_TYPE
#undef DEF_FUNCTION_TYPE_0
@@ -6197,7 +6306,8 @@ handle_nonnull_attribute (tree *node, tree ARG_UNUSED (name),
&& (!TYPE_ATTRIBUTES (type)
|| !lookup_attribute ("type generic", TYPE_ATTRIBUTES (type))))
{
- error ("nonnull attribute without arguments on a non-prototype");
+ error ("%qs attribute without arguments on a non-prototype",
+ "nonnull");
*no_add_attrs = true;
}
return NULL_TREE;
@@ -6211,8 +6321,8 @@ handle_nonnull_attribute (tree *node, tree ARG_UNUSED (name),
if (!get_nonnull_operand (TREE_VALUE (args), &arg_num))
{
- error ("nonnull argument has invalid operand number (argument %lu)",
- (unsigned long) attr_arg_num);
+ error ("%qs argument has invalid operand number (argument %lu)",
+ "nonnull", (unsigned long) attr_arg_num);
*no_add_attrs = true;
return NULL_TREE;
}
@@ -6233,8 +6343,8 @@ handle_nonnull_attribute (tree *node, tree ARG_UNUSED (name),
if (!argument
|| TREE_CODE (argument) == VOID_TYPE)
{
- error ("nonnull argument with out-of-range operand number "
- "(argument %lu, operand %lu)",
+ error ("%qs argument with out-of-range operand number "
+ "(argument %lu, operand %lu)", "nonnull",
(unsigned long) attr_arg_num, (unsigned long) arg_num);
*no_add_attrs = true;
return NULL_TREE;
@@ -6242,8 +6352,8 @@ handle_nonnull_attribute (tree *node, tree ARG_UNUSED (name),
if (TREE_CODE (argument) != POINTER_TYPE)
{
- error ("nonnull argument references non-pointer operand "
- "(argument %lu, operand %lu)",
+ error ("%qs argument references non-pointer operand "
+ "(argument %lu, operand %lu)", "nonnull",
(unsigned long) attr_arg_num, (unsigned long) arg_num);
*no_add_attrs = true;
return NULL_TREE;
@@ -6327,6 +6437,22 @@ handle_noreturn_attribute (tree *node, tree name, tree ARG_UNUSED (args),
return NULL_TREE;
}
+/* Handle a "stack_protect" attribute; arguments as in
+ struct attribute_spec.handler. */
+
+static tree
+handle_stack_protect_attribute (tree *node, tree name, tree, int,
+ bool *no_add_attrs)
+{
+ if (TREE_CODE (*node) != FUNCTION_DECL)
+ {
+ warning (OPT_Wattributes, "%qE attribute ignored", name);
+ *no_add_attrs = true;
+ }
+
+ return NULL_TREE;
+}
+
/* Handle a "noinline" attribute; arguments as in
struct attribute_spec.handler. */
@@ -6372,6 +6498,38 @@ handle_noclone_attribute (tree *node, tree name,
return NULL_TREE;
}
+/* Handle a "no_icf" attribute; arguments as in
+ struct attribute_spec.handler. */
+
+static tree
+handle_noicf_attribute (tree *node, tree name,
+ tree ARG_UNUSED (args),
+ int ARG_UNUSED (flags), bool *no_add_attrs)
+{
+ if (TREE_CODE (*node) != FUNCTION_DECL)
+ {
+ warning (OPT_Wattributes, "%qE attribute ignored", name);
+ *no_add_attrs = true;
+ }
+
+ return NULL_TREE;
+}
+
+/* Handle a "noipa" attribute; arguments as in
+ struct attribute_spec.handler. */
+
+static tree
+handle_noipa_attribute (tree *node, tree name, tree, int, bool *no_add_attrs)
+{
+ if (TREE_CODE (*node) != FUNCTION_DECL)
+ {
+ warning (OPT_Wattributes, "%qE attribute ignored", name);
+ *no_add_attrs = true;
+ }
+
+ return NULL_TREE;
+}
+
/* Handle a "leaf" attribute; arguments as in
struct attribute_spec.handler. */
@@ -6462,6 +6620,166 @@ handle_type_generic_attribute (tree *node, tree ARG_UNUSED (name),
return NULL_TREE;
}
+/* Handle a "flatten" attribute; arguments as in
+ struct attribute_spec.handler. */
+
+static tree
+handle_flatten_attribute (tree *node, tree name,
+ tree args ATTRIBUTE_UNUSED,
+ int flags ATTRIBUTE_UNUSED, bool *no_add_attrs)
+{
+ if (TREE_CODE (*node) == FUNCTION_DECL)
+ /* Do nothing else, just set the attribute. We'll get at
+ it later with lookup_attribute. */
+ ;
+ else
+ {
+ warning (OPT_Wattributes, "%qE attribute ignored", name);
+ *no_add_attrs = true;
+ }
+
+ return NULL_TREE;
+}
+
+/* Handle a "used" attribute; arguments as in
+ struct attribute_spec.handler. */
+
+static tree
+handle_used_attribute (tree *pnode, tree name, tree ARG_UNUSED (args),
+ int ARG_UNUSED (flags), bool *no_add_attrs)
+{
+ tree node = *pnode;
+
+ if (TREE_CODE (node) == FUNCTION_DECL
+ || (VAR_P (node) && TREE_STATIC (node))
+ || (TREE_CODE (node) == TYPE_DECL))
+ {
+ TREE_USED (node) = 1;
+ DECL_PRESERVE_P (node) = 1;
+ if (VAR_P (node))
+ DECL_READ_P (node) = 1;
+ }
+ else
+ {
+ warning (OPT_Wattributes, "%qE attribute ignored", name);
+ *no_add_attrs = true;
+ }
+
+ return NULL_TREE;
+}
+
+/* Handle a "cold" and attribute; arguments as in
+ struct attribute_spec.handler. */
+
+static tree
+handle_cold_attribute (tree *node, tree name, tree ARG_UNUSED (args),
+ int ARG_UNUSED (flags), bool *no_add_attrs)
+{
+ if (TREE_CODE (*node) == FUNCTION_DECL
+ || TREE_CODE (*node) == LABEL_DECL)
+ {
+ /* Attribute cold processing is done later with lookup_attribute. */
+ }
+ else
+ {
+ warning (OPT_Wattributes, "%qE attribute ignored", name);
+ *no_add_attrs = true;
+ }
+
+ return NULL_TREE;
+}
+
+/* Handle a "hot" and attribute; arguments as in
+ struct attribute_spec.handler. */
+
+static tree
+handle_hot_attribute (tree *node, tree name, tree ARG_UNUSED (args),
+ int ARG_UNUSED (flags), bool *no_add_attrs)
+{
+ if (TREE_CODE (*node) == FUNCTION_DECL
+ || TREE_CODE (*node) == LABEL_DECL)
+ {
+ /* Attribute hot processing is done later with lookup_attribute. */
+ }
+ else
+ {
+ warning (OPT_Wattributes, "%qE attribute ignored", name);
+ *no_add_attrs = true;
+ }
+
+ return NULL_TREE;
+}
+
+/* Handle a "target" attribute. */
+
+static tree
+handle_target_attribute (tree *node, tree name, tree args, int flags,
+ bool *no_add_attrs)
+{
+ /* Ensure we have a function type. */
+ if (TREE_CODE (*node) != FUNCTION_DECL)
+ {
+ warning (OPT_Wattributes, "%qE attribute ignored", name);
+ *no_add_attrs = true;
+ }
+ else if (lookup_attribute ("target_clones", DECL_ATTRIBUTES (*node)))
+ {
+ warning (OPT_Wattributes, "%qE attribute ignored due to conflict "
+ "with %qs attribute", name, "target_clones");
+ *no_add_attrs = true;
+ }
+ else if (!targetm.target_option.valid_attribute_p (*node, name, args, flags))
+ *no_add_attrs = true;
+
+ /* Check that there's no empty string in values of the attribute. */
+ for (tree t = args; t != NULL_TREE; t = TREE_CHAIN (t))
+ {
+ tree value = TREE_VALUE (t);
+ if (TREE_CODE (value) == STRING_CST
+ && TREE_STRING_LENGTH (value) == 1
+ && TREE_STRING_POINTER (value)[0] == '\0')
+ {
+ warning (OPT_Wattributes, "empty string in attribute %<target%>");
+ *no_add_attrs = true;
+ }
+ }
+
+ return NULL_TREE;
+}
+
+/* Handle a "target_clones" attribute. */
+
+static tree
+handle_target_clones_attribute (tree *node, tree name, tree ARG_UNUSED (args),
+ int ARG_UNUSED (flags), bool *no_add_attrs)
+{
+ /* Ensure we have a function type. */
+ if (TREE_CODE (*node) == FUNCTION_DECL)
+ {
+ if (lookup_attribute ("always_inline", DECL_ATTRIBUTES (*node)))
+ {
+ warning (OPT_Wattributes, "%qE attribute ignored due to conflict "
+ "with %qs attribute", name, "always_inline");
+ *no_add_attrs = true;
+ }
+ else if (lookup_attribute ("target", DECL_ATTRIBUTES (*node)))
+ {
+ warning (OPT_Wattributes, "%qE attribute ignored due to conflict "
+ "with %qs attribute", name, "target");
+ *no_add_attrs = true;
+ }
+ else
+ /* Do not inline functions with multiple clone targets. */
+ DECL_UNINLINABLE (*node) = 1;
+ }
+ else
+ {
+ warning (OPT_Wattributes, "%qE attribute ignored", name);
+ *no_add_attrs = true;
+ }
+ return NULL_TREE;
+}
+
/* Handle a "vector_size" attribute; arguments as in
struct attribute_spec.handler. */
@@ -6574,7 +6892,10 @@ static int flag_isoc94 = 0;
static int flag_isoc99 = 0;
static int flag_isoc11 = 0;
-/* Install what the common builtins.def offers. */
+/* Install what the common builtins.def offers plus our local additions.
+
+ Note that ada-builtins.def is included first so that locally redefined
+ built-in functions take precedence over the commonly defined ones. */
static void
install_builtin_functions (void)
@@ -6587,6 +6908,10 @@ install_builtin_functions (void)
builtin_types[(int) LIBTYPE], \
BOTH_P, FALLBACK_P, NONANSI_P, \
built_in_attributes[(int) ATTRS], IMPLICIT);
+#define DEF_ADA_BUILTIN(ENUM, NAME, TYPE, ATTRS) \
+ DEF_BUILTIN (ENUM, "__builtin_" NAME, BUILT_IN_FRONTEND, TYPE, BT_LAST, \
+ false, false, false, ATTRS, true, true)
+#include "ada-builtins.def"
#include "builtins.def"
}
diff --git a/gcc/ada/gnat1drv.adb b/gcc/ada/gnat1drv.adb
index cd4518f..1f5817a 100644
--- a/gcc/ada/gnat1drv.adb
+++ b/gcc/ada/gnat1drv.adb
@@ -1453,9 +1453,13 @@ begin
-- Generate ALI file if specially requested, or for missing subunits,
-- subunits or predefined generic. For ignored ghost code, the object
- -- file IS generated, so Object should be True.
+ -- file IS generated, so Object should be True, and since the object
+ -- file is generated, we need to generate the ALI file. We never want
+ -- an object file without an ALI file.
- if Opt.Force_ALI_Tree_File then
+ if Is_Ignored_Ghost_Unit (Main_Unit_Node)
+ or else Opt.Force_ALI_Tree_File
+ then
Write_ALI (Object => Is_Ignored_Ghost_Unit (Main_Unit_Node));
end if;
diff --git a/gcc/ada/gnat_rm.texi b/gcc/ada/gnat_rm.texi
index 85bc144..39a24ab 100644
--- a/gcc/ada/gnat_rm.texi
+++ b/gcc/ada/gnat_rm.texi
@@ -21,7 +21,7 @@
@copying
@quotation
-GNAT Reference Manual , Sep 24, 2018
+GNAT Reference Manual , Jun 21, 2019
AdaCore
@@ -5220,18 +5220,19 @@ Syntax:
pragma Machine_Attribute (
[Entity =>] LOCAL_NAME,
[Attribute_Name =>] static_string_EXPRESSION
- [, [Info =>] static_EXPRESSION] );
+ [, [Info =>] static_EXPRESSION @{, static_EXPRESSION@}] );
@end example
Machine-dependent attributes can be specified for types and/or
declarations. This pragma is semantically equivalent to
@code{__attribute__((@emph{attribute_name}))} (if @code{info} is not
specified) or @code{__attribute__((@emph{attribute_name(info})))}
-in GNU C, where @emph{attribute_name} is recognized by the
-compiler middle-end or the @code{TARGET_ATTRIBUTE_TABLE} machine
-specific macro. A string literal for the optional parameter @code{info}
-is transformed into an identifier, which may make this pragma unusable
-for some attributes.
+or @code{__attribute__((@emph{attribute_name(info,...})))} in GNU C,
+where @emph{attribute_name} is recognized by the compiler middle-end
+or the @code{TARGET_ATTRIBUTE_TABLE} machine specific macro. Note
+that a string literal for the optional parameter @code{info} or the
+following ones is transformed by default into an identifier,
+which may make this pragma unusable for some attributes.
For further information see @cite{GNU Compiler Collection (GCC) Internals}.
@node Pragma Main,Pragma Main_Storage,Pragma Machine_Attribute,Implementation Defined Pragmas
@@ -12673,15 +12674,14 @@ Long_Integer'Size.
@geindex No_Multiple_Elaboration
-[GNAT] When this restriction is active, we are not requesting control-flow
-preservation with -fpreserve-control-flow, and the static elaboration model is
-used, the compiler is allowed to suppress the elaboration counter normally
-associated with the unit, even if the unit has elaboration code. This counter
-is typically used to check for access before elaboration and to control
-multiple elaboration attempts. If the restriction is used, then the
-situations in which multiple elaboration is possible, including non-Ada main
-programs and Stand Alone libraries, are not permitted and will be diagnosed
-by the binder.
+[GNAT] When this restriction is active and the static elaboration model is
+used, and -fpreserve-control-flow is not used, the compiler is allowed to
+suppress the elaboration counter normally associated with the unit, even if
+the unit has elaboration code. This counter is typically used to check for
+access before elaboration and to control multiple elaboration attempts. If the
+restriction is used, then the situations in which multiple elaboration is
+possible, including non-Ada main programs and Stand Alone libraries, are not
+permitted and will be diagnosed by the binder.
@node No_Nested_Finalization,No_Protected_Type_Allocators,No_Multiple_Elaboration,Partition-Wide Restrictions
@anchor{gnat_rm/standard_and_implementation_defined_restrictions no-nested-finalization}@anchor{1e1}
@@ -18982,14 +18982,23 @@ type R is record
end record;
@end example
-On a typical 32-bit architecture, the X component will be four bytes, and
-require four-byte alignment, and the Y component will be one byte. In this
-case @code{R'Value_Size} will be 40 (bits) since this is the minimum size
-required to store a value of this type, and for example, it is permissible
-to have a component of type R in an outer array whose component size is
-specified to be 48 bits. However, @code{R'Object_Size} will be 64 (bits),
-since it must be rounded up so that this value is a multiple of the
-alignment (4 bytes = 32 bits).
+On a typical 32-bit architecture, the X component will occupy four bytes
+and the Y component will occupy one byte, for a total of 5 bytes. As a
+result @code{R'Value_Size} will be 40 (bits) since this is the minimum size
+required to store a value of this type. For example, it is permissible
+to have a component of type R in an array whose component size is
+specified to be 40 bits.
+
+However, @code{R'Object_Size} will be 64 (bits). The difference is due to
+the alignment requirement for objects of the record type. The X
+component will require four-byte alignment because that is what type
+Integer requires, whereas the Y component, a Character, will only
+require 1-byte alignment. Since the alignment required for X is the
+greatest of all the components' alignments, that is the alignment
+required for the enclosing record type, i.e., 4 bytes or 32 bits. As
+indicated above, the actual object size must be rounded up so that it is
+a multiple of the alignment value. Therefore, 40 bits rounded up to the
+next multiple of 32 yields 64 bits.
For all other types, the @code{Object_Size}
and @code{Value_Size} are the same (and equivalent to the RM attribute @code{Size}).
@@ -25531,8 +25540,10 @@ and C types:
@item
Ada enumeration types map to C enumeration types directly if pragma
-@code{Convention C} is specified, which causes them to have int
-length. Without pragma @code{Convention C}, Ada enumeration types map to
+@code{Convention C} is specified, which causes them to have a length of
+32 bits, except for boolean types which map to C99 @code{bool} and for
+which the length is 8 bits.
+Without pragma @code{Convention C}, Ada enumeration types map to
8, 16, or 32 bits (i.e., C types @code{signed char}, @code{short},
@code{int}, respectively) depending on the number of values passed.
This is the only case in which pragma @code{Convention C} affects the
diff --git a/gcc/ada/gnat_ugn.texi b/gcc/ada/gnat_ugn.texi
index faf01c6..7371a76 100644
--- a/gcc/ada/gnat_ugn.texi
+++ b/gcc/ada/gnat_ugn.texi
@@ -21,7 +21,7 @@
@copying
@quotation
-GNAT User's Guide for Native Platforms , Dec 05, 2018
+GNAT User's Guide for Native Platforms , Jun 21, 2019
AdaCore
@@ -12683,8 +12683,8 @@ sizes or conventions.
@emph{Activate warnings for size not a multiple of alignment.}
-This switch activates warnings for cases of record types with
-specified @code{Size} and @code{Alignment} attributes where the
+This switch activates warnings for cases of array and record types
+with specified @code{Size} and @code{Alignment} attributes where the
size is not a multiple of the alignment, resulting in an object
size that is greater than the specified size. The default
is that such warnings are generated.
@@ -12701,12 +12701,11 @@ is that such warnings are generated.
@emph{Suppress warnings for size not a multiple of alignment.}
-This switch suppresses warnings for cases of record types with
-specified @code{Size} and @code{Alignment} attributes where the
+This switch suppresses warnings for cases of array and record types
+with specified @code{Size} and @code{Alignment} attributes where the
size is not a multiple of the alignment, resulting in an object
-size that is greater than the specified size.
-The warning can also be
-suppressed by giving an explicit @code{Object_Size} value.
+size that is greater than the specified size. The warning can also
+be suppressed by giving an explicit @code{Object_Size} value.
@end table
@geindex -Wunused (gcc)
@@ -13516,6 +13515,20 @@ character (in particular the DOS line terminator sequence CR/LF is not
allowed).
@end table
+@geindex -gnatyD (gcc)
+
+
+@table @asis
+
+@item @code{-gnatyD}
+
+@emph{Check declared identifiers in mixed case.}
+
+Declared identifiers must be in mixed case, as in
+This_Is_An_Identifier. Use -gnatyr in addition to ensure
+that references match declarations.
+@end table
+
@geindex -gnatye (gcc)
@@ -15143,8 +15156,8 @@ available in the specification of the Repinfo unit present in the
compiler sources.
If the switch is followed by an @code{s} (e.g., @code{-gnatR3s}), then
-the output is to a file with the name @code{file.rep} where file is
-the name of the corresponding source file, except if @cite{j`} is also
+the output is to a file with the name @code{file.rep} where @code{file} is
+the name of the corresponding source file, except if @code{j} is also
specified, in which case the file name is @code{file.json}.
Note that it is possible for record components to have zero size. In
@@ -23556,15 +23569,15 @@ the set of handlers
Most programs should experience a substantial speed improvement by
being compiled with a ZCX run-time.
This is especially true for
-tasking applications or applications with many exception handlers.@}
+tasking applications or applications with many exception handlers.
+Note however that the ZCX run-time does not support asynchronous abort
+of tasks (@code{abort} and @code{select-then-abort} constructs) and will instead
+implement abort by polling points in the runtime. You can also add additional
+polling points explicitly if needed in your application via @code{pragma
+Abort_Defer}.
This section summarizes which combinations of threads and exception support
are supplied on various GNAT platforms.
-It then shows how to select a particular library either
-permanently or temporarily,
-explains the properties of (and tradeoffs among) the various threads
-libraries, and provides some additional
-information about several specific platforms.
@menu
* Summary of Run-Time Configurations::
@@ -28348,20 +28361,20 @@ using the legacy elaboration model, in the following order:
@itemize -
@item
-Use the legacy static elaboration model, with compiler switch
-@code{-gnatH}.
+Use the relaxed static elaboration model, with compiler switch
+@code{-gnatJ}.
@item
-Use the legacy dynamic elaboration model, with compiler switches
-@code{-gnatH} @code{-gnatE}.
+Use the relaxed dynamic elaboration model, with compiler switches
+@code{-gnatE} @code{-gnatJ}.
@item
-Use the relaxed legacy static elaboration model, with compiler switches
-@code{-gnatH} @code{-gnatJ}.
+Use the legacy static elaboration model, with compiler switch
+@code{-gnatH}.
@item
-Use the relaxed legacy dynamic elaboration model, with compiler switches
-@code{-gnatH} @code{-gnatJ} @code{-gnatE}.
+Use the legacy dynamic elaboration model, with compiler switches
+@code{-gnatE} @code{-gnatH}.
@end itemize
@item
diff --git a/gcc/ada/gnatbind.adb b/gcc/ada/gnatbind.adb
index be703a9..41541c3 100644
--- a/gcc/ada/gnatbind.adb
+++ b/gcc/ada/gnatbind.adb
@@ -29,6 +29,7 @@ with Bcheck; use Bcheck;
with Binde; use Binde;
with Binderr; use Binderr;
with Bindgen; use Bindgen;
+with Bindo; use Bindo;
with Bindusg;
with Casing; use Casing;
with Csets;
@@ -878,11 +879,18 @@ begin
if Errors_Detected = 0 then
declare
- Elab_Order : Unit_Id_Table;
use Unit_Id_Tables;
+ Elab_Order : Unit_Id_Table;
begin
- Find_Elab_Order (Elab_Order, First_Main_Lib_File);
+ -- Use the invocation and library graph-based elaboration order
+ -- when switch -d_N (new bindo order) is in effect.
+
+ if Debug_Flag_Underscore_NN then
+ Find_Elaboration_Order (Elab_Order, First_Main_Lib_File);
+ else
+ Find_Elab_Order (Elab_Order, First_Main_Lib_File);
+ end if;
if Errors_Detected = 0 and then not Check_Only then
Gen_Output_File
@@ -892,12 +900,12 @@ begin
end;
end if;
- Total_Errors := Total_Errors + Errors_Detected;
+ Total_Errors := Total_Errors + Errors_Detected;
Total_Warnings := Total_Warnings + Warnings_Detected;
exception
when Unrecoverable_Error =>
- Total_Errors := Total_Errors + Errors_Detected;
+ Total_Errors := Total_Errors + Errors_Detected;
Total_Warnings := Total_Warnings + Warnings_Detected;
end;
diff --git a/gcc/ada/gnatlink.adb b/gcc/ada/gnatlink.adb
index e8a1b92..5e5ede0 100644
--- a/gcc/ada/gnatlink.adb
+++ b/gcc/ada/gnatlink.adb
@@ -1884,6 +1884,7 @@ begin
Clean_Link_Option_Set : declare
J : Natural;
Shared_Libgcc_Seen : Boolean := False;
+ Static_Libgcc_Seen : Boolean := False;
begin
J := Linker_Options.First;
@@ -1905,7 +1906,7 @@ begin
end if;
end if;
- -- Remove duplicate -shared-libgcc switch
+ -- Remove duplicate -shared-libgcc switches
if Linker_Options.Table (J).all = Shared_Libgcc_String then
if Shared_Libgcc_Seen then
@@ -1919,6 +1920,20 @@ begin
end if;
end if;
+ -- Remove duplicate -static-libgcc switches
+
+ if Linker_Options.Table (J).all = Static_Libgcc_String then
+ if Static_Libgcc_Seen then
+ Linker_Options.Table (J .. Linker_Options.Last - 1) :=
+ Linker_Options.Table (J + 1 .. Linker_Options.Last);
+ Linker_Options.Decrement_Last;
+ Num_Args := Num_Args - 1;
+
+ else
+ Static_Libgcc_Seen := True;
+ end if;
+ end if;
+
-- Here we just check for a canonical form that matches the
-- pragma Linker_Options set in the NT runtime.
@@ -1950,14 +1965,27 @@ begin
-- libgcc, if gcc is not called with -shared-libgcc, call it
-- with -static-libgcc, as there are some platforms where one
-- of these two switches is compulsory to link.
+ -- Don't push extra switches if we already saw one.
if Shared_Libgcc_Default = 'T'
and then not Shared_Libgcc_Seen
+ and then not Static_Libgcc_Seen
then
Linker_Options.Increment_Last;
Linker_Options.Table (Linker_Options.Last) := Static_Libgcc;
Num_Args := Num_Args + 1;
end if;
+
+ -- Likewise, the reverse.
+
+ if Shared_Libgcc_Default = 'H'
+ and then not Static_Libgcc_Seen
+ and then not Shared_Libgcc_Seen
+ then
+ Linker_Options.Increment_Last;
+ Linker_Options.Table (Linker_Options.Last) := Shared_Libgcc;
+ Num_Args := Num_Args + 1;
+ end if;
end if;
end Clean_Link_Option_Set;
diff --git a/gcc/ada/gsocket.h b/gcc/ada/gsocket.h
index 200edaba..1821b1b 100644
--- a/gcc/ada/gsocket.h
+++ b/gcc/ada/gsocket.h
@@ -185,6 +185,7 @@
#include <limits.h>
#include <errno.h>
+#include <stddef.h>
#if defined (__vxworks) && ! defined (__RTP__)
#include <sys/times.h>
@@ -252,12 +253,7 @@
# endif
#endif
-#if defined (__FreeBSD__) || defined (__vxworks) || defined(__rtems__) \
- || defined (__DragonFly__) || defined (__NetBSD__) || defined (__OpenBSD__)
-# define Has_Sockaddr_Len 1
-#else
-# define Has_Sockaddr_Len 0
-#endif
+# define Has_Sockaddr_Len (offsetof(struct sockaddr_in, sin_family) != 0)
#if !(defined (_WIN32) || defined (__hpux__) || defined (VMS))
# define HAVE_INET_PTON
diff --git a/gcc/ada/impunit.adb b/gcc/ada/impunit.adb
index 4ee99e6..80857b3 100644
--- a/gcc/ada/impunit.adb
+++ b/gcc/ada/impunit.adb
@@ -275,6 +275,7 @@ package body Impunit is
("g-exptty", F), -- GNAT.Expect.TTY
("g-flocon", F), -- GNAT.Float_Control
("g-forstr", F), -- GNAT.Formatted_String
+ ("g-graphs", F), -- GNAT.Graphs
("g-heasor", F), -- GNAT.Heap_Sort
("g-hesora", F), -- GNAT.Heap_Sort_A
("g-hesorg", F), -- GNAT.Heap_Sort_G
diff --git a/gcc/ada/inline.adb b/gcc/ada/inline.adb
index 709513d..b2038a6 100644
--- a/gcc/ada/inline.adb
+++ b/gcc/ada/inline.adb
@@ -1706,11 +1706,29 @@ package body Inline is
-- Use generic machinery to build an unexpanded body for the subprogram.
-- This body is subsequently used for inline expansions at call sites.
+ procedure Build_Return_Object_Formal
+ (Loc : Source_Ptr;
+ Obj_Decl : Node_Id;
+ Formals : List_Id);
+ -- Create a formal parameter for return object declaration Obj_Decl of
+ -- an extended return statement and add it to list Formals.
+
function Can_Split_Unconstrained_Function (N : Node_Id) return Boolean;
-- Return true if we generate code for the function body N, the function
-- body N has no local declarations and its unique statement is a single
-- extended return statement with a handled statements sequence.
+ procedure Copy_Formals
+ (Loc : Source_Ptr;
+ Subp_Id : Entity_Id;
+ Formals : List_Id);
+ -- Create new formal parameters from the formal parameters of subprogram
+ -- Subp_Id and add them to list Formals.
+
+ function Copy_Return_Object (Obj_Decl : Node_Id) return Node_Id;
+ -- Create a copy of return object declaration Obj_Decl of an extended
+ -- return statement.
+
procedure Split_Unconstrained_Function
(N : Node_Id;
Spec_Id : Entity_Id);
@@ -1757,6 +1775,9 @@ package body Inline is
Body_To_Inline :=
Copy_Generic_Node (N, Empty, Instantiating => True);
else
+ -- ??? Shouldn't this use New_Copy_Tree? What about global
+ -- references captured in the body to inline?
+
Body_To_Inline := Copy_Separate_Tree (N);
end if;
@@ -1845,30 +1866,70 @@ package body Inline is
Set_Ekind (Defining_Entity (Original_Body), Ekind (Spec_Id));
end Build_Body_To_Inline;
+ --------------------------------
+ -- Build_Return_Object_Formal --
+ --------------------------------
+
+ procedure Build_Return_Object_Formal
+ (Loc : Source_Ptr;
+ Obj_Decl : Node_Id;
+ Formals : List_Id)
+ is
+ Obj_Def : constant Node_Id := Object_Definition (Obj_Decl);
+ Obj_Id : constant Entity_Id := Defining_Entity (Obj_Decl);
+ Typ_Def : Node_Id;
+
+ begin
+ -- Build the type definition of the formal parameter. The use of
+ -- New_Copy_Tree ensures that global references preserved in the
+ -- case of generics.
+
+ if Is_Entity_Name (Obj_Def) then
+ Typ_Def := New_Copy_Tree (Obj_Def);
+ else
+ Typ_Def := New_Copy_Tree (Subtype_Mark (Obj_Def));
+ end if;
+
+ -- Generate:
+ --
+ -- Obj_Id : [out] Typ_Def
+
+ -- Mode OUT should not be used when the return object is declared as
+ -- a constant. Check the definition of the object declaration because
+ -- the object has not been analyzed yet.
+
+ Append_To (Formals,
+ Make_Parameter_Specification (Loc,
+ Defining_Identifier =>
+ Make_Defining_Identifier (Loc, Chars (Obj_Id)),
+ In_Present => False,
+ Out_Present => not Constant_Present (Obj_Decl),
+ Null_Exclusion_Present => False,
+ Parameter_Type => Typ_Def));
+ end Build_Return_Object_Formal;
+
--------------------------------------
-- Can_Split_Unconstrained_Function --
--------------------------------------
function Can_Split_Unconstrained_Function (N : Node_Id) return Boolean is
- Ret_Node : constant Node_Id :=
- First (Statements (Handled_Statement_Sequence (N)));
- D : Node_Id;
+ Stmt : constant Node_Id :=
+ First (Statements (Handled_Statement_Sequence (N)));
+ Decl : Node_Id;
begin
-- No user defined declarations allowed in the function except inside
-- the unique return statement; implicit labels are the only allowed
-- declarations.
- if not Is_Empty_List (Declarations (N)) then
- D := First (Declarations (N));
- while Present (D) loop
- if Nkind (D) /= N_Implicit_Label_Declaration then
- return False;
- end if;
+ Decl := First (Declarations (N));
+ while Present (Decl) loop
+ if Nkind (Decl) /= N_Implicit_Label_Declaration then
+ return False;
+ end if;
- Next (D);
- end loop;
- end if;
+ Next (Decl);
+ end loop;
-- We only split the inlined function when we are generating the code
-- of its body; otherwise we leave duplicated split subprograms in
@@ -1876,12 +1937,71 @@ package body Inline is
-- time.
return In_Extended_Main_Code_Unit (N)
- and then Present (Ret_Node)
- and then Nkind (Ret_Node) = N_Extended_Return_Statement
- and then No (Next (Ret_Node))
- and then Present (Handled_Statement_Sequence (Ret_Node));
+ and then Present (Stmt)
+ and then Nkind (Stmt) = N_Extended_Return_Statement
+ and then No (Next (Stmt))
+ and then Present (Handled_Statement_Sequence (Stmt));
end Can_Split_Unconstrained_Function;
+ ------------------
+ -- Copy_Formals --
+ ------------------
+
+ procedure Copy_Formals
+ (Loc : Source_Ptr;
+ Subp_Id : Entity_Id;
+ Formals : List_Id)
+ is
+ Formal : Entity_Id;
+ Spec : Node_Id;
+
+ begin
+ Formal := First_Formal (Subp_Id);
+ while Present (Formal) loop
+ Spec := Parent (Formal);
+
+ -- Create an exact copy of the formal parameter. The use of
+ -- New_Copy_Tree ensures that global references are preserved
+ -- in case of generics.
+
+ Append_To (Formals,
+ Make_Parameter_Specification (Loc,
+ Defining_Identifier =>
+ Make_Defining_Identifier (Sloc (Formal), Chars (Formal)),
+ In_Present => In_Present (Spec),
+ Out_Present => Out_Present (Spec),
+ Null_Exclusion_Present => Null_Exclusion_Present (Spec),
+ Parameter_Type =>
+ New_Copy_Tree (Parameter_Type (Spec)),
+ Expression => New_Copy_Tree (Expression (Spec))));
+
+ Next_Formal (Formal);
+ end loop;
+ end Copy_Formals;
+
+ ------------------------
+ -- Copy_Return_Object --
+ ------------------------
+
+ function Copy_Return_Object (Obj_Decl : Node_Id) return Node_Id is
+ Obj_Id : constant Entity_Id := Defining_Entity (Obj_Decl);
+
+ begin
+ -- The use of New_Copy_Tree ensures that global references are
+ -- preserved in case of generics.
+
+ return
+ Make_Object_Declaration (Sloc (Obj_Decl),
+ Defining_Identifier =>
+ Make_Defining_Identifier (Sloc (Obj_Id), Chars (Obj_Id)),
+ Aliased_Present => Aliased_Present (Obj_Decl),
+ Constant_Present => Constant_Present (Obj_Decl),
+ Null_Exclusion_Present => Null_Exclusion_Present (Obj_Decl),
+ Object_Definition =>
+ New_Copy_Tree (Object_Definition (Obj_Decl)),
+ Expression => New_Copy_Tree (Expression (Obj_Decl)));
+ end Copy_Return_Object;
+
----------------------------------
-- Split_Unconstrained_Function --
----------------------------------
@@ -1891,10 +2011,10 @@ package body Inline is
Spec_Id : Entity_Id)
is
Loc : constant Source_Ptr := Sloc (N);
- Ret_Node : constant Node_Id :=
+ Ret_Stmt : constant Node_Id :=
First (Statements (Handled_Statement_Sequence (N)));
Ret_Obj : constant Node_Id :=
- First (Return_Object_Declarations (Ret_Node));
+ First (Return_Object_Declarations (Ret_Stmt));
procedure Build_Procedure
(Proc_Id : out Entity_Id;
@@ -1910,63 +2030,35 @@ package body Inline is
(Proc_Id : out Entity_Id;
Decl_List : out List_Id)
is
- Formal : Entity_Id;
- Formal_List : constant List_Id := New_List;
- Proc_Spec : Node_Id;
- Proc_Body : Node_Id;
- Subp_Name : constant Name_Id := New_Internal_Name ('F');
- Body_Decl_List : List_Id := No_List;
- Param_Type : Node_Id;
-
- begin
- if Nkind (Object_Definition (Ret_Obj)) = N_Identifier then
- Param_Type :=
- New_Copy (Object_Definition (Ret_Obj));
- else
- Param_Type :=
- New_Copy (Subtype_Mark (Object_Definition (Ret_Obj)));
- end if;
-
- Append_To (Formal_List,
- Make_Parameter_Specification (Loc,
- Defining_Identifier =>
- Make_Defining_Identifier (Loc,
- Chars => Chars (Defining_Identifier (Ret_Obj))),
- In_Present => False,
- Out_Present => True,
- Null_Exclusion_Present => False,
- Parameter_Type => Param_Type));
+ Formals : constant List_Id := New_List;
+ Subp_Name : constant Name_Id := New_Internal_Name ('F');
- Formal := First_Formal (Spec_Id);
+ Body_Decls : List_Id := No_List;
+ Decl : Node_Id;
+ Proc_Body : Node_Id;
+ Proc_Spec : Node_Id;
- -- Note that we copy the parameter type rather than creating
- -- a reference to it, because it may be a class-wide entity
- -- that will not be retrieved by name.
+ begin
+ -- Create formal parameters for the return object and all formals
+ -- of the unconstrained function in order to pass their values to
+ -- the procedure.
- while Present (Formal) loop
- Append_To (Formal_List,
- Make_Parameter_Specification (Loc,
- Defining_Identifier =>
- Make_Defining_Identifier (Sloc (Formal),
- Chars => Chars (Formal)),
- In_Present => In_Present (Parent (Formal)),
- Out_Present => Out_Present (Parent (Formal)),
- Null_Exclusion_Present =>
- Null_Exclusion_Present (Parent (Formal)),
- Parameter_Type =>
- New_Copy_Tree (Parameter_Type (Parent (Formal))),
- Expression =>
- Copy_Separate_Tree (Expression (Parent (Formal)))));
+ Build_Return_Object_Formal
+ (Loc => Loc,
+ Obj_Decl => Ret_Obj,
+ Formals => Formals);
- Next_Formal (Formal);
- end loop;
+ Copy_Formals
+ (Loc => Loc,
+ Subp_Id => Spec_Id,
+ Formals => Formals);
Proc_Id := Make_Defining_Identifier (Loc, Chars => Subp_Name);
Proc_Spec :=
Make_Procedure_Specification (Loc,
Defining_Unit_Name => Proc_Id,
- Parameter_Specifications => Formal_List);
+ Parameter_Specifications => Formals);
Decl_List := New_List;
@@ -1978,37 +2070,30 @@ package body Inline is
-- Copy these declarations to the built procedure.
if Present (Declarations (N)) then
- Body_Decl_List := New_List;
+ Body_Decls := New_List;
- declare
- D : Node_Id;
- New_D : Node_Id;
+ Decl := First (Declarations (N));
+ while Present (Decl) loop
+ pragma Assert (Nkind (Decl) = N_Implicit_Label_Declaration);
- begin
- D := First (Declarations (N));
- while Present (D) loop
- pragma Assert (Nkind (D) = N_Implicit_Label_Declaration);
-
- New_D :=
- Make_Implicit_Label_Declaration (Loc,
- Make_Defining_Identifier (Loc,
- Chars => Chars (Defining_Identifier (D))),
- Label_Construct => Empty);
- Append_To (Body_Decl_List, New_D);
-
- Next (D);
- end loop;
- end;
+ Append_To (Body_Decls,
+ Make_Implicit_Label_Declaration (Loc,
+ Make_Defining_Identifier (Loc,
+ Chars => Chars (Defining_Identifier (Decl))),
+ Label_Construct => Empty));
+
+ Next (Decl);
+ end loop;
end if;
- pragma Assert (Present (Handled_Statement_Sequence (Ret_Node)));
+ pragma Assert (Present (Handled_Statement_Sequence (Ret_Stmt)));
Proc_Body :=
Make_Subprogram_Body (Loc,
- Specification => Copy_Separate_Tree (Proc_Spec),
- Declarations => Body_Decl_List,
+ Specification => Copy_Subprogram_Spec (Proc_Spec),
+ Declarations => Body_Decls,
Handled_Statement_Sequence =>
- Copy_Separate_Tree (Handled_Statement_Sequence (Ret_Node)));
+ New_Copy_Tree (Handled_Statement_Sequence (Ret_Stmt)));
Set_Defining_Unit_Name (Specification (Proc_Body),
Make_Defining_Identifier (Loc, Subp_Name));
@@ -2018,10 +2103,10 @@ package body Inline is
-- Local variables
- New_Obj : constant Node_Id := Copy_Separate_Tree (Ret_Obj);
+ New_Obj : constant Node_Id := Copy_Return_Object (Ret_Obj);
Blk_Stmt : Node_Id;
- Proc_Id : Entity_Id;
Proc_Call : Node_Id;
+ Proc_Id : Entity_Id;
-- Start of processing for Split_Unconstrained_Function
@@ -2089,7 +2174,7 @@ package body Inline is
New_Occurrence_Of
(Defining_Identifier (New_Obj), Loc)))));
- Rewrite (Ret_Node, Blk_Stmt);
+ Rewrite (Ret_Stmt, Blk_Stmt);
end Split_Unconstrained_Function;
-- Local variables
@@ -2386,11 +2471,23 @@ package body Inline is
-- sets Exit_Lab (the label node) and Lab_Decl (corresponding implicit
-- declaration). Does nothing if Exit_Lab already set.
+ procedure Make_Loop_Labels_Unique (HSS : Node_Id);
+ -- When compiling for CCG and performing front-end inlining, replace
+ -- loop names and references to them so that they do not conflict with
+ -- homographs in the current subprogram.
+
function Process_Formals (N : Node_Id) return Traverse_Result;
-- Replace occurrence of a formal with the corresponding actual, or the
-- thunk generated for it. Replace a return statement with an assignment
-- to the target of the call, with appropriate conversions if needed.
+ function Process_Formals_In_Aspects (N : Node_Id)
+ return Traverse_Result;
+ -- Because aspects are linked indirectly to the rest of the tree,
+ -- replacement of formals appearing in aspect specifications must
+ -- be performed in a separate pass, using an instantiation of the
+ -- previous subprogram over aspect specifications reachable from N.
+
function Process_Sloc (Nod : Node_Id) return Traverse_Result;
-- If the call being expanded is that of an internal subprogram, set the
-- sloc of the generated block to that of the call itself, so that the
@@ -2474,6 +2571,61 @@ package body Inline is
end if;
end Make_Exit_Label;
+ -----------------------------
+ -- Make_Loop_Labels_Unique --
+ -----------------------------
+
+ procedure Make_Loop_Labels_Unique (HSS : Node_Id) is
+ function Process_Loop (N : Node_Id) return Traverse_Result;
+
+ ------------------
+ -- Process_Loop --
+ ------------------
+
+ function Process_Loop (N : Node_Id) return Traverse_Result is
+ Id : Entity_Id;
+
+ begin
+ if Nkind (N) = N_Loop_Statement
+ and then Present (Identifier (N))
+ then
+ -- Create new external name for loop and update the
+ -- corresponding entity.
+
+ Id := Entity (Identifier (N));
+ Set_Chars (Id, New_External_Name (Chars (Id), 'L', -1));
+ Set_Chars (Identifier (N), Chars (Id));
+
+ elsif Nkind (N) = N_Exit_Statement
+ and then Present (Name (N))
+ then
+ -- The exit statement must name an enclosing loop, whose name
+ -- has already been updated.
+
+ Set_Chars (Name (N), Chars (Entity (Name (N))));
+ end if;
+
+ return OK;
+ end Process_Loop;
+
+ procedure Update_Loop_Names is new Traverse_Proc (Process_Loop);
+
+ -- Local variables
+
+ Stmt : Node_Id;
+
+ -- Start of processing for Make_Loop_Labels_Unique
+
+ begin
+ if Modify_Tree_For_C then
+ Stmt := First (Statements (HSS));
+ while Present (Stmt) loop
+ Update_Loop_Names (Stmt);
+ Next (Stmt);
+ end loop;
+ end if;
+ end Make_Loop_Labels_Unique;
+
---------------------
-- Process_Formals --
---------------------
@@ -2676,6 +2828,29 @@ package body Inline is
procedure Replace_Formals is new Traverse_Proc (Process_Formals);
+ --------------------------------
+ -- Process_Formals_In_Aspects --
+ --------------------------------
+
+ function Process_Formals_In_Aspects (N : Node_Id)
+ return Traverse_Result
+ is
+ A : Node_Id;
+ begin
+ if Has_Aspects (N) then
+ A := First (Aspect_Specifications (N));
+ while Present (A) loop
+ Replace_Formals (Expression (A));
+
+ Next (A);
+ end loop;
+ end if;
+ return OK;
+ end Process_Formals_In_Aspects;
+
+ procedure Replace_Formals_In_Aspects is
+ new Traverse_Proc (Process_Formals_In_Aspects);
+
------------------
-- Process_Sloc --
------------------
@@ -2742,6 +2917,8 @@ package body Inline is
Fst : constant Node_Id := First (Statements (HSS));
begin
+ Make_Loop_Labels_Unique (HSS);
+
-- Optimize simple case: function body is a single return statement,
-- which has been expanded into an assignment.
@@ -2829,6 +3006,8 @@ package body Inline is
HSS : constant Node_Id := Handled_Statement_Sequence (Blk);
begin
+ Make_Loop_Labels_Unique (HSS);
+
-- If there is a transient scope for N, this will be the scope of the
-- actions for N, and the statements in Blk need to be within this
-- scope. For example, they need to have visibility on the constant
@@ -3484,6 +3663,7 @@ package body Inline is
-- Attach block to tree before analysis and rewriting.
Replace_Formals (Blk);
+ Replace_Formals_In_Aspects (Blk);
Set_Parent (Blk, N);
if GNATprove_Mode then
diff --git a/gcc/ada/layout.adb b/gcc/ada/layout.adb
index f5f6aa8..f8e9099 100644
--- a/gcc/ada/layout.adb
+++ b/gcc/ada/layout.adb
@@ -443,9 +443,12 @@ package body Layout is
Set_RM_Size (E, Esize (E));
end if;
- -- For array base types, set component size if object size of the
+ -- For array base types, set the component size if object size of the
-- component type is known and is a small power of 2 (8, 16, 32, 64),
- -- since this is what will always be used.
+ -- since this is what will always be used, except if a very large
+ -- alignment was specified and so Adjust_Esize_For_Alignment gave up
+ -- because, in this case, the object size is not a multiple of the
+ -- alignment and, therefore, cannot be the component size.
if Ekind (E) = E_Array_Type and then Unknown_Component_Size (E) then
declare
@@ -458,6 +461,9 @@ package body Layout is
if Present (CT)
and then Is_Scalar_Type (CT)
and then Known_Static_Esize (CT)
+ and then not (Known_Alignment (CT)
+ and then Alignment_In_Bits (CT) >
+ Standard_Long_Long_Integer_Size)
then
declare
S : constant Uint := Esize (CT);
diff --git a/gcc/ada/layout.ads b/gcc/ada/layout.ads
index c38d529..81162c1 100644
--- a/gcc/ada/layout.ads
+++ b/gcc/ada/layout.ads
@@ -34,7 +34,7 @@ package Layout is
-- The following procedures are called from Freeze, so all entities
-- for types and objects that get frozen (which should be all such
- -- entities which are seen by the back end) will get layed out by one
+ -- entities which are seen by the back end) will get laid out by one
-- of these two procedures.
procedure Layout_Type (E : Entity_Id);
diff --git a/gcc/ada/lib-writ.adb b/gcc/ada/lib-writ.adb
index 319557e..ffd6a90 100644
--- a/gcc/ada/lib-writ.adb
+++ b/gcc/ada/lib-writ.adb
@@ -62,6 +62,63 @@ package body Lib.Writ is
-- Local Subprograms --
-----------------------
+ function Column (IS_Id : Invocation_Signature_Id) return Nat;
+ pragma Inline (Column);
+ -- Obtain attribute Column of an invocation signature with id IS_Id
+
+ function Extra (IR_Id : Invocation_Relation_Id) return Name_Id;
+ pragma Inline (Extra);
+ -- Obtain attribute Extra of an invocation relation with id IR_Id
+
+ function Invoker
+ (IR_Id : Invocation_Relation_Id) return Invocation_Signature_Id;
+ pragma Inline (Invoker);
+ -- Obtain attribute Invoker of an invocation relation with id IR_Id
+
+ function Kind
+ (IC_Id : Invocation_Construct_Id) return Invocation_Construct_Kind;
+ pragma Inline (Kind);
+ -- Obtain attribute Kind of an invocation construct with id IC_Id
+
+ function Kind (IR_Id : Invocation_Relation_Id) return Invocation_Kind;
+ pragma Inline (Kind);
+ -- Obtain attribute Kind of an invocation relation with id IR_Id
+
+ function Line (IS_Id : Invocation_Signature_Id) return Nat;
+ pragma Inline (Line);
+ -- Obtain attribute Line of an invocation signature with id IS_Id
+
+ function Locations (IS_Id : Invocation_Signature_Id) return Name_Id;
+ pragma Inline (Locations);
+ -- Obtain attribute Locations of an invocation signature with id IS_Id
+
+ function Name (IS_Id : Invocation_Signature_Id) return Name_Id;
+ pragma Inline (Name);
+ -- Obtain attribute Name of an invocation signature with id IS_Id
+
+ function Placement
+ (IC_Id : Invocation_Construct_Id) return Body_Placement_Kind;
+ pragma Inline (Placement);
+ -- Obtain attribute Placement of an invocation construct with id IC_Id
+
+ function Present (N_Id : Name_Id) return Boolean;
+ pragma Inline (Present);
+ -- Determine whether a name with id N_Id exists
+
+ function Scope (IS_Id : Invocation_Signature_Id) return Name_Id;
+ pragma Inline (Scope);
+ -- Obtain attribute Scope of an invocation signature with id IS_Id
+
+ function Signature
+ (IC_Id : Invocation_Construct_Id) return Invocation_Signature_Id;
+ pragma Inline (Signature);
+ -- Obtain attribute Signature of an invocation construct with id IC_Id
+
+ function Target
+ (IR_Id : Invocation_Relation_Id) return Invocation_Signature_Id;
+ pragma Inline (Target);
+ -- Obtain attribute Target of an invocation relation with id IR_Id
+
procedure Write_Unit_Name (N : Node_Id);
-- Used to write out the unit name for R (pragma Restriction) lines
-- for uses of Restriction (No_Dependence => unit-name).
@@ -104,6 +161,16 @@ package body Lib.Writ is
OA_Setting => 'O');
end Add_Preprocessing_Dependency;
+ ------------
+ -- Column --
+ ------------
+
+ function Column (IS_Id : Invocation_Signature_Id) return Nat is
+ begin
+ pragma Assert (Present (IS_Id));
+ return Invocation_Signatures.Table (IS_Id).Column;
+ end Column;
+
------------------------------
-- Ensure_System_Dependency --
------------------------------
@@ -185,6 +252,135 @@ package body Lib.Writ is
end;
end Ensure_System_Dependency;
+ -----------
+ -- Extra --
+ -----------
+
+ function Extra (IR_Id : Invocation_Relation_Id) return Name_Id is
+ begin
+ pragma Assert (Present (IR_Id));
+ return Invocation_Relations.Table (IR_Id).Extra;
+ end Extra;
+
+ -------------
+ -- Invoker --
+ -------------
+
+ function Invoker
+ (IR_Id : Invocation_Relation_Id) return Invocation_Signature_Id
+ is
+ begin
+ pragma Assert (Present (IR_Id));
+ return Invocation_Relations.Table (IR_Id).Invoker;
+ end Invoker;
+
+ ----------
+ -- Kind --
+ ----------
+
+ function Kind
+ (IC_Id : Invocation_Construct_Id) return Invocation_Construct_Kind
+ is
+ begin
+ pragma Assert (Present (IC_Id));
+ return Invocation_Constructs.Table (IC_Id).Kind;
+ end Kind;
+
+ ----------
+ -- Kind --
+ ----------
+
+ function Kind (IR_Id : Invocation_Relation_Id) return Invocation_Kind is
+ begin
+ pragma Assert (Present (IR_Id));
+ return Invocation_Relations.Table (IR_Id).Kind;
+ end Kind;
+
+ ----------
+ -- Line --
+ ----------
+
+ function Line (IS_Id : Invocation_Signature_Id) return Nat is
+ begin
+ pragma Assert (Present (IS_Id));
+ return Invocation_Signatures.Table (IS_Id).Line;
+ end Line;
+
+ ---------------
+ -- Locations --
+ ---------------
+
+ function Locations (IS_Id : Invocation_Signature_Id) return Name_Id is
+ begin
+ pragma Assert (Present (IS_Id));
+ return Invocation_Signatures.Table (IS_Id).Locations;
+ end Locations;
+
+ ----------
+ -- Name --
+ ----------
+
+ function Name (IS_Id : Invocation_Signature_Id) return Name_Id is
+ begin
+ pragma Assert (Present (IS_Id));
+ return Invocation_Signatures.Table (IS_Id).Name;
+ end Name;
+
+ ---------------
+ -- Placement --
+ ---------------
+
+ function Placement
+ (IC_Id : Invocation_Construct_Id) return Body_Placement_Kind
+ is
+ begin
+ pragma Assert (Present (IC_Id));
+ return Invocation_Constructs.Table (IC_Id).Placement;
+ end Placement;
+
+ -------------
+ -- Present --
+ -------------
+
+ function Present (N_Id : Name_Id) return Boolean is
+ begin
+ return N_Id /= No_Name;
+ end Present;
+
+ -----------
+ -- Scope --
+ -----------
+
+ function Scope (IS_Id : Invocation_Signature_Id) return Name_Id is
+ begin
+ pragma Assert (Present (IS_Id));
+ return Invocation_Signatures.Table (IS_Id).Scope;
+ end Scope;
+
+ ---------------
+ -- Signature --
+ ---------------
+
+ function Signature
+ (IC_Id : Invocation_Construct_Id) return Invocation_Signature_Id
+ is
+ begin
+ pragma Assert (Present (IC_Id));
+ return Invocation_Constructs.Table (IC_Id).Signature;
+ end Signature;
+
+ ------------
+ -- Target --
+ ------------
+
+ function Target
+ (IR_Id : Invocation_Relation_Id) return Invocation_Signature_Id
+ is
+ begin
+ pragma Assert (Present (IR_Id));
+ return Invocation_Relations.Table (IR_Id).Target;
+ end Target;
+
---------------
-- Write_ALI --
---------------
@@ -245,6 +441,9 @@ package body Lib.Writ is
-- this file (using Scan_ALI) and returns True. If no file exists,
-- or the file is not up to date, then False is returned.
+ procedure Write_Invocation_Graph;
+ -- Write out the invocation graph
+
procedure Write_Unit_Information (Unit_Num : Unit_Number_Type);
-- Write out the library information for one unit for which code is
-- generated (includes unit line and with lines).
@@ -434,6 +633,175 @@ package body Lib.Writ is
end Update_Tables_From_ALI_File;
----------------------------
+ -- Write_Invocation_Graph --
+ ----------------------------
+
+ procedure Write_Invocation_Graph is
+ procedure Write_Invocation_Construct
+ (IC_Id : Invocation_Construct_Id);
+ pragma Inline (Write_Invocation_Construct);
+ -- Write invocation construct IC_Id to the ALI file
+
+ procedure Write_Invocation_Relation (IR_Id : Invocation_Relation_Id);
+ pragma Inline (Write_Invocation_Relation);
+ -- Write invocation relation IR_Id to the ALI file
+
+ procedure Write_Invocation_Signature
+ (IS_Id : Invocation_Signature_Id);
+ pragma Inline (Write_Invocation_Signature);
+ -- Write invocation signature IS_Id to the ALI file
+
+ --------------------------------
+ -- Write_Invocation_Construct --
+ --------------------------------
+
+ procedure Write_Invocation_Construct
+ (IC_Id : Invocation_Construct_Id)
+ is
+ begin
+ -- G header
+
+ Write_Info_Initiate ('G');
+ Write_Info_Char (' ');
+
+ -- line-kind
+
+ Write_Info_Char
+ (Invocation_Graph_Line_Kind_To_Code (Invocation_Construct_Line));
+ Write_Info_Char (' ');
+
+ -- construct-kind
+
+ Write_Info_Char (Invocation_Construct_Kind_To_Code (Kind (IC_Id)));
+ Write_Info_Char (' ');
+
+ -- construct-body-placement
+
+ Write_Info_Char (Body_Placement_Kind_To_Code (Placement (IC_Id)));
+ Write_Info_Char (' ');
+
+ -- construct-signature
+
+ Write_Invocation_Signature (Signature (IC_Id));
+ Write_Info_EOL;
+ end Write_Invocation_Construct;
+
+ -------------------------------
+ -- Write_Invocation_Relation --
+ -------------------------------
+
+ procedure Write_Invocation_Relation
+ (IR_Id : Invocation_Relation_Id)
+ is
+ begin
+ -- G header
+
+ Write_Info_Initiate ('G');
+ Write_Info_Char (' ');
+
+ -- line-kind
+
+ Write_Info_Char
+ (Invocation_Graph_Line_Kind_To_Code (Invocation_Relation_Line));
+ Write_Info_Char (' ');
+
+ -- relation-kind
+
+ Write_Info_Char (Invocation_Kind_To_Code (Kind (IR_Id)));
+ Write_Info_Char (' ');
+
+ -- (extra-name | "none")
+
+ if Present (Extra (IR_Id)) then
+ Write_Info_Name (Extra (IR_Id));
+ else
+ Write_Info_Str ("none");
+ end if;
+
+ Write_Info_Char (' ');
+
+ -- invoker-signature
+
+ Write_Invocation_Signature (Invoker (IR_Id));
+ Write_Info_Char (' ');
+
+ -- target-signature
+
+ Write_Invocation_Signature (Target (IR_Id));
+
+ Write_Info_EOL;
+ end Write_Invocation_Relation;
+
+ --------------------------------
+ -- Write_Invocation_Signature --
+ --------------------------------
+
+ procedure Write_Invocation_Signature
+ (IS_Id : Invocation_Signature_Id)
+ is
+ begin
+ -- [
+
+ Write_Info_Char ('[');
+
+ -- name
+
+ Write_Info_Name (Name (IS_Id));
+ Write_Info_Char (' ');
+
+ -- scope
+
+ Write_Info_Name (Scope (IS_Id));
+ Write_Info_Char (' ');
+
+ -- line
+
+ Write_Info_Nat (Line (IS_Id));
+ Write_Info_Char (' ');
+
+ -- column
+
+ Write_Info_Nat (Column (IS_Id));
+ Write_Info_Char (' ');
+
+ -- (locations | "none")
+
+ if Present (Locations (IS_Id)) then
+ Write_Info_Name (Locations (IS_Id));
+ else
+ Write_Info_Str ("none");
+ end if;
+
+ -- ]
+
+ Write_Info_Char (']');
+ end Write_Invocation_Signature;
+
+ -- Start of processing for Write_Invocation_Graph
+
+ begin
+ -- First write out all invocation constructs declared within the
+ -- current unit. This ensures that when this invocation is read,
+ -- the invocation constructs are materialized before they are
+ -- referenced by invocation relations.
+
+ for IC_Id in Invocation_Constructs.First ..
+ Invocation_Constructs.Last
+ loop
+ Write_Invocation_Construct (IC_Id);
+ end loop;
+
+ -- Write out all invocation relations that originate from invocation
+ -- constructs delared in the current unit.
+
+ for IR_Id in Invocation_Relations.First ..
+ Invocation_Relations.Last
+ loop
+ Write_Invocation_Relation (IR_Id);
+ end loop;
+ end Write_Invocation_Graph;
+
+ ----------------------------
-- Write_Unit_Information --
----------------------------
@@ -1618,6 +1986,10 @@ package body Lib.Writ is
end loop;
end;
+ -- Output the invocation graph
+
+ Write_Invocation_Graph;
+
-- Output cross-references
if Opt.Xref_Active then
diff --git a/gcc/ada/lib-writ.ads b/gcc/ada/lib-writ.ads
index 34e2480..c17233a 100644
--- a/gcc/ada/lib-writ.ads
+++ b/gcc/ada/lib-writ.ads
@@ -846,6 +846,94 @@ package Lib.Writ is
-- dependency checking, but must be present for proper interpretation
-- of the cross-reference data.
+ -- -------------------------
+ -- -- G Invocation Graph --
+ -- -------------------------
+
+ -- An invocation graph line has the following format:
+ --
+ -- G line-kind line-attributes
+ --
+ -- Attribute line-kind is a Character which denotes the nature of the
+ -- line. Table ALI.Invocation_Graph_Line_Codes lists all legal values.
+ --
+ -- Attribute line-attributes depends on the value of line-kind, and is
+ -- contents are described further below.
+ --
+ -- An invocation signature uniquely identifies an invocation construct in
+ -- the ALI file namespace, and has the following format:
+ --
+ -- [ name scope line column (locations | "none") ]
+ --
+ -- Attribute name is a String which denotes the name of the construct
+ --
+ -- Attribute scope is a String which denotes the qualified name of the
+ -- scope where the construct is declared.
+ --
+ -- Attribute line is a Positive which denotes the line number where the
+ -- initial declaration of the construct appears.
+ --
+ -- Attribute column is a Positive which denotes the column number where
+ -- the initial declaration of the construct appears.
+ --
+ -- Attribute locations is a String which denotes the line and column
+ -- locations of all instances where the initial declaration of the
+ -- construct appears.
+ --
+ -- When the line-kind denotes an invocation construct, line-attributes are
+ -- set as follows:
+ --
+ -- construct-kind construct-body-placement construct-signature
+ --
+ -- Attribute construct-kind is a Character which denotes the nature of
+ -- the construct. Table ALI.Invocation_Construct_Codes lists all legal
+ -- values.
+ --
+ -- Attribute construct-body-placement is a Character which denotes the
+ -- placement of the construct's body within the unit. All legal values
+ -- are listed in table ALI.Body_Placement_Codes.
+ --
+ -- Attribute construct-signature is the invocation signature of the
+ -- construct.
+ --
+ -- When the line-kind denotes an invocation relation, line-attributes are
+ -- set as follows:
+ --
+ -- relation-kind (extra-name | "none") invoker-signature
+ -- target-signature
+ --
+ -- Attribute relation-kind is a Character which denotes the nature of
+ -- the relation. All legal values are listed in ALI.Invocation_Codes.
+ --
+ -- Attribute extra-name is a String which denotes the name of an extra
+ -- entity used for error diagnostics. The value of extra-name depends
+ -- on the relation-kind as follows:
+ --
+ -- Accept_Alternative - related entry
+ -- Access_Taken - related subprogram
+ -- Call - not present
+ -- Controlled_Adjustment - related controlled type
+ -- Controlled_Finalization - related controlled type
+ -- Controlled_Initialization - related controlled type
+ -- Default_Initial_Condition_Verification - related private type
+ -- Initial_Condition_Verification - not present
+ -- Instantiation - not present
+ -- Internal_Controlled_Adjustment - related controlled type
+ -- Internal_Controlled_Finalization - related controlled type
+ -- Internal_Controlled_Initialization - related controlled type
+ -- Invariant_Verification - related private type
+ -- Postcondition_Verification - related routine
+ -- Protected_Entry_Call - not present
+ -- Protected_Subprogram_Call - not present
+ -- Task_Activation - related task object
+ -- Task_Entry_Call - not present
+ -- Type_Initialization - related type
+ --
+ -- Attribute invoker-signature is the invocation signature of the
+ -- invoker.
+ --
+ -- Attribute target-signature is the invocation signature of the target
+
--------------------------
-- Cross-Reference Data --
--------------------------
diff --git a/gcc/ada/libgnat/a-calend.ads b/gcc/ada/libgnat/a-calend.ads
index 139c5fc..1b782f0 100644
--- a/gcc/ada/libgnat/a-calend.ads
+++ b/gcc/ada/libgnat/a-calend.ads
@@ -61,19 +61,20 @@ is
-- the result will contain all elapsed leap seconds since the start of
-- Ada time until now.
- function Year (Date : Time) return Year_Number with Global => null;
- function Month (Date : Time) return Month_Number with Global => null;
- function Day (Date : Time) return Day_Number with Global => null;
- function Seconds (Date : Time) return Day_Duration with Global => null;
+ function Year (Date : Time) return Year_Number;
+ function Month (Date : Time) return Month_Number;
+ function Day (Date : Time) return Day_Number;
+ function Seconds (Date : Time) return Day_Duration;
+ -- SPARK Note: These routines, just like Split and Time_Of below, might use
+ -- the OS-specific timezone database that is typically stored in a file.
+ -- This side effect needs to be modeled, so there is no Global => null.
procedure Split
(Date : Time;
Year : out Year_Number;
Month : out Month_Number;
Day : out Day_Number;
- Seconds : out Day_Duration)
- with
- Global => null;
+ Seconds : out Day_Duration);
-- Break down a time value into its date components set in the current
-- time zone. If Split is called on a time value created using Ada 2005
-- Time_Of in some arbitrary time zone, the input value will always be
@@ -83,9 +84,7 @@ is
(Year : Year_Number;
Month : Month_Number;
Day : Day_Number;
- Seconds : Day_Duration := 0.0) return Time
- with
- Global => null;
+ Seconds : Day_Duration := 0.0) return Time;
-- GNAT Note: Normally when procedure Split is called on a Time value
-- result of a call to function Time_Of, the out parameters of procedure
-- Split are identical to the in parameters of function Time_Of. However,
diff --git a/gcc/ada/libgnat/g-dynhta.adb b/gcc/ada/libgnat/g-dynhta.adb
index c47f6ff..84dcc30 100644
--- a/gcc/ada/libgnat/g-dynhta.adb
+++ b/gcc/ada/libgnat/g-dynhta.adb
@@ -34,6 +34,34 @@ with Ada.Unchecked_Deallocation;
package body GNAT.Dynamic_HTables is
-------------------
+ -- Hash_Two_Keys --
+ -------------------
+
+ function Hash_Two_Keys
+ (Left : Bucket_Range_Type;
+ Right : Bucket_Range_Type) return Bucket_Range_Type
+ is
+ Half : constant := 2 ** (Bucket_Range_Type'Size / 2);
+ Mask : constant := Half - 1;
+
+ begin
+ -- The hash is obtained in the following manner:
+ --
+ -- 1) The low bits of Left are obtained, then shifted over to the high
+ -- bits position.
+ --
+ -- 2) The low bits of Right are obtained
+ --
+ -- The results from 1) and 2) are or-ed to produce a value within the
+ -- range of Bucket_Range_Type.
+
+ return
+ ((Left and Mask) * Half)
+ or
+ (Right and Mask);
+ end Hash_Two_Keys;
+
+ -------------------
-- Static_HTable --
-------------------
@@ -364,11 +392,11 @@ package body GNAT.Dynamic_HTables is
end Set_Next;
end Simple_HTable;
- --------------------
- -- Dynamic_HTable --
- --------------------
+ -------------------------
+ -- Dynamic_Hash_Tables --
+ -------------------------
- package body Dynamic_HTable is
+ package body Dynamic_Hash_Tables is
Minimum_Size : constant Bucket_Range_Type := 8;
-- Minimum size of the buckets
@@ -382,6 +410,12 @@ package body GNAT.Dynamic_HTables is
-- Maximum safe size for hash table expansion. Beyond this size, an
-- expansion will overflow the buckets.
+ procedure Delete_Node
+ (T : Dynamic_Hash_Table;
+ Nod : Node_Ptr);
+ pragma Inline (Delete_Node);
+ -- Detach and delete node Nod from table T
+
procedure Destroy_Buckets (Bkts : Bucket_Table_Ptr);
pragma Inline (Destroy_Buckets);
-- Destroy all nodes within buckets Bkts
@@ -394,12 +428,12 @@ package body GNAT.Dynamic_HTables is
pragma Inline (Ensure_Circular);
-- Ensure that dummy head Head is circular with respect to itself
- procedure Ensure_Created (T : Instance);
+ procedure Ensure_Created (T : Dynamic_Hash_Table);
pragma Inline (Ensure_Created);
-- Verify that hash table T is created. Raise Not_Created if this is not
-- the case.
- procedure Ensure_Unlocked (T : Instance);
+ procedure Ensure_Unlocked (T : Dynamic_Hash_Table);
pragma Inline (Ensure_Unlocked);
-- Verify that hash table T is unlocked. Raise Iterated if this is not
-- the case.
@@ -418,7 +452,7 @@ package body GNAT.Dynamic_HTables is
-- otherwise return null.
procedure First_Valid_Node
- (T : Instance;
+ (T : Dynamic_Hash_Table;
Low_Bkt : Bucket_Range_Type;
High_Bkt : Bucket_Range_Type;
Idx : out Bucket_Range_Type;
@@ -433,7 +467,8 @@ package body GNAT.Dynamic_HTables is
new Ada.Unchecked_Deallocation (Bucket_Table, Bucket_Table_Ptr);
procedure Free is
- new Ada.Unchecked_Deallocation (Hash_Table, Instance);
+ new Ada.Unchecked_Deallocation
+ (Dynamic_Hash_Table_Attributes, Dynamic_Hash_Table);
procedure Free is
new Ada.Unchecked_Deallocation (Node, Node_Ptr);
@@ -447,15 +482,17 @@ package body GNAT.Dynamic_HTables is
-- Determine whether node Nod is non-null and does not refer to dummy
-- head Head, thus making it valid.
- function Load_Factor (T : Instance) return Threshold_Type;
+ function Load_Factor (T : Dynamic_Hash_Table) return Threshold_Type;
pragma Inline (Load_Factor);
-- Calculate the load factor of hash table T
- procedure Lock (T : Instance);
+ procedure Lock (T : Dynamic_Hash_Table);
pragma Inline (Lock);
-- Lock all mutation functionality of hash table T
- procedure Mutate_And_Rehash (T : Instance; Size : Bucket_Range_Type);
+ procedure Mutate_And_Rehash
+ (T : Dynamic_Hash_Table;
+ Size : Bucket_Range_Type);
pragma Inline (Mutate_And_Rehash);
-- Replace the buckets of hash table T with a new set of buckets of size
-- Size. Rehash all key-value pairs from the old to the new buckets.
@@ -464,21 +501,55 @@ package body GNAT.Dynamic_HTables is
pragma Inline (Prepend);
-- Insert node Nod immediately after dummy head Head
- procedure Unlock (T : Instance);
+ function Present (Bkts : Bucket_Table_Ptr) return Boolean;
+ pragma Inline (Present);
+ -- Determine whether buckets Bkts exist
+
+ function Present (Nod : Node_Ptr) return Boolean;
+ pragma Inline (Present);
+ -- Determine whether node Nod exists
+
+ procedure Unlock (T : Dynamic_Hash_Table);
pragma Inline (Unlock);
-- Unlock all mutation functionality of hash table T
+ --------------
+ -- Contains --
+ --------------
+
+ function Contains
+ (T : Dynamic_Hash_Table;
+ Key : Key_Type) return Boolean
+ is
+ Head : Node_Ptr;
+ Nod : Node_Ptr;
+
+ begin
+ Ensure_Created (T);
+
+ -- Obtain the dummy head of the bucket which should house the
+ -- key-value pair.
+
+ Head := Find_Bucket (T.Buckets, Key);
+
+ -- Try to find a node in the bucket which matches the key
+
+ Nod := Find_Node (Head, Key);
+
+ return Is_Valid (Nod, Head);
+ end Contains;
+
------------
-- Create --
------------
- function Create (Initial_Size : Positive) return Instance is
+ function Create (Initial_Size : Positive) return Dynamic_Hash_Table is
Size : constant Bucket_Range_Type :=
Bucket_Range_Type'Max
(Bucket_Range_Type (Initial_Size), Minimum_Size);
-- Ensure that the buckets meet a minimum size
- T : constant Instance := new Hash_Table;
+ T : constant Dynamic_Hash_Table := new Dynamic_Hash_Table_Attributes;
begin
T.Buckets := new Bucket_Table (0 .. Size - 1);
@@ -491,7 +562,41 @@ package body GNAT.Dynamic_HTables is
-- Delete --
------------
- procedure Delete (T : Instance; Key : Key_Type) is
+ procedure Delete
+ (T : Dynamic_Hash_Table;
+ Key : Key_Type)
+ is
+ Head : Node_Ptr;
+ Nod : Node_Ptr;
+
+ begin
+ Ensure_Created (T);
+ Ensure_Unlocked (T);
+
+ -- Obtain the dummy head of the bucket which should house the
+ -- key-value pair.
+
+ Head := Find_Bucket (T.Buckets, Key);
+
+ -- Try to find a node in the bucket which matches the key
+
+ Nod := Find_Node (Head, Key);
+
+ -- If such a node exists, remove it from the bucket and deallocate it
+
+ if Is_Valid (Nod, Head) then
+ Delete_Node (T, Nod);
+ end if;
+ end Delete;
+
+ -----------------
+ -- Delete_Node --
+ -----------------
+
+ procedure Delete_Node
+ (T : Dynamic_Hash_Table;
+ Nod : Node_Ptr)
+ is
procedure Compress;
pragma Inline (Compress);
-- Determine whether hash table T requires compression, and if so,
@@ -502,8 +607,8 @@ package body GNAT.Dynamic_HTables is
--------------
procedure Compress is
- pragma Assert (T /= null);
- pragma Assert (T.Buckets /= null);
+ pragma Assert (Present (T));
+ pragma Assert (Present (T.Buckets));
Old_Size : constant Bucket_Range_Type := T.Buckets'Length;
@@ -520,47 +625,33 @@ package body GNAT.Dynamic_HTables is
-- Local variables
- Head : Node_Ptr;
- Nod : Node_Ptr;
+ Ref : Node_Ptr := Nod;
- -- Start of processing for Delete
+ -- Start of processing for Delete_Node
begin
- Ensure_Created (T);
- Ensure_Unlocked (T);
-
- -- Obtain the dummy head of the bucket which should house the
- -- key-value pair.
-
- Head := Find_Bucket (T.Buckets, Key);
-
- -- Try to find a node in the bucket which matches the key
+ pragma Assert (Present (Ref));
+ pragma Assert (Present (T));
- Nod := Find_Node (Head, Key);
-
- -- If such a node exists, remove it from the bucket and deallocate it
+ Detach (Ref);
+ Free (Ref);
- if Is_Valid (Nod, Head) then
- Detach (Nod);
- Free (Nod);
+ -- The number of key-value pairs is updated when the hash table
+ -- contains a valid node which represents the pair.
- -- The number of key-value pairs is updated when the hash table
- -- contains a valid node which represents the pair.
+ T.Pairs := T.Pairs - 1;
- T.Pairs := T.Pairs - 1;
+ -- Compress the hash table if the load factor drops below the value
+ -- of Compression_Threshold.
- -- Compress the hash table if the load factor drops below
- -- Compression_Threshold.
-
- Compress;
- end if;
- end Delete;
+ Compress;
+ end Delete_Node;
-------------
-- Destroy --
-------------
- procedure Destroy (T : in out Instance) is
+ procedure Destroy (T : in out Dynamic_Hash_Table) is
begin
Ensure_Created (T);
Ensure_Unlocked (T);
@@ -594,6 +685,10 @@ package body GNAT.Dynamic_HTables is
while Is_Valid (Head.Next, Head) loop
Nod := Head.Next;
+ -- Invoke the value destructor before deallocating the node
+
+ Destroy_Value (Nod.Value);
+
Detach (Nod);
Free (Nod);
end loop;
@@ -602,7 +697,7 @@ package body GNAT.Dynamic_HTables is
-- Start of processing for Destroy_Buckets
begin
- pragma Assert (Bkts /= null);
+ pragma Assert (Present (Bkts));
for Scan_Idx in Bkts'Range loop
Destroy_Bucket (Bkts (Scan_Idx)'Access);
@@ -614,17 +709,17 @@ package body GNAT.Dynamic_HTables is
------------
procedure Detach (Nod : Node_Ptr) is
- pragma Assert (Nod /= null);
+ pragma Assert (Present (Nod));
Next : constant Node_Ptr := Nod.Next;
Prev : constant Node_Ptr := Nod.Prev;
begin
- pragma Assert (Next /= null);
- pragma Assert (Prev /= null);
+ pragma Assert (Present (Next));
+ pragma Assert (Present (Prev));
- Prev.Next := Next;
- Next.Prev := Prev;
+ Prev.Next := Next; -- Prev ---> Next
+ Next.Prev := Prev; -- Prev <--> Next
Nod.Next := null;
Nod.Prev := null;
@@ -635,10 +730,10 @@ package body GNAT.Dynamic_HTables is
---------------------
procedure Ensure_Circular (Head : Node_Ptr) is
- pragma Assert (Head /= null);
+ pragma Assert (Present (Head));
begin
- if Head.Next = null and then Head.Prev = null then
+ if not Present (Head.Next) and then not Present (Head.Prev) then
Head.Next := Head;
Head.Prev := Head;
end if;
@@ -648,9 +743,9 @@ package body GNAT.Dynamic_HTables is
-- Ensure_Created --
--------------------
- procedure Ensure_Created (T : Instance) is
+ procedure Ensure_Created (T : Dynamic_Hash_Table) is
begin
- if T = null then
+ if not Present (T) then
raise Not_Created;
end if;
end Ensure_Created;
@@ -659,9 +754,9 @@ package body GNAT.Dynamic_HTables is
-- Ensure_Unlocked --
---------------------
- procedure Ensure_Unlocked (T : Instance) is
+ procedure Ensure_Unlocked (T : Dynamic_Hash_Table) is
begin
- pragma Assert (T /= null);
+ pragma Assert (Present (T));
-- The hash table has at least one outstanding iterator
@@ -678,7 +773,7 @@ package body GNAT.Dynamic_HTables is
(Bkts : Bucket_Table_Ptr;
Key : Key_Type) return Node_Ptr
is
- pragma Assert (Bkts /= null);
+ pragma Assert (Present (Bkts));
Idx : constant Bucket_Range_Type := Hash (Key) mod Bkts'Length;
@@ -691,7 +786,7 @@ package body GNAT.Dynamic_HTables is
---------------
function Find_Node (Head : Node_Ptr; Key : Key_Type) return Node_Ptr is
- pragma Assert (Head /= null);
+ pragma Assert (Present (Head));
Nod : Node_Ptr;
@@ -716,7 +811,7 @@ package body GNAT.Dynamic_HTables is
----------------------
procedure First_Valid_Node
- (T : Instance;
+ (T : Dynamic_Hash_Table;
Low_Bkt : Bucket_Range_Type;
High_Bkt : Bucket_Range_Type;
Idx : out Bucket_Range_Type;
@@ -725,8 +820,8 @@ package body GNAT.Dynamic_HTables is
Head : Node_Ptr;
begin
- pragma Assert (T /= null);
- pragma Assert (T.Buckets /= null);
+ pragma Assert (Present (T));
+ pragma Assert (Present (T.Buckets));
-- Assume that no valid node exists
@@ -754,7 +849,10 @@ package body GNAT.Dynamic_HTables is
-- Get --
---------
- function Get (T : Instance; Key : Key_Type) return Value_Type is
+ function Get
+ (T : Dynamic_Hash_Table;
+ Key : Key_Type) return Value_Type
+ is
Head : Node_Ptr;
Nod : Node_Ptr;
@@ -784,11 +882,11 @@ package body GNAT.Dynamic_HTables is
--------------
function Has_Next (Iter : Iterator) return Boolean is
- Is_OK : constant Boolean := Is_Valid (Iter);
- T : constant Instance := Iter.Table;
+ Is_OK : constant Boolean := Is_Valid (Iter);
+ T : constant Dynamic_Hash_Table := Iter.Table;
begin
- pragma Assert (T /= null);
+ pragma Assert (Present (T));
-- The iterator is no longer valid which indicates that it has been
-- exhausted. Unlock all mutation functionality of the hash table
@@ -805,7 +903,7 @@ package body GNAT.Dynamic_HTables is
-- Is_Empty --
--------------
- function Is_Empty (T : Instance) return Boolean is
+ function Is_Empty (T : Dynamic_Hash_Table) return Boolean is
begin
Ensure_Created (T);
@@ -821,7 +919,7 @@ package body GNAT.Dynamic_HTables is
-- The invariant of Iterate and Next ensures that the iterator always
-- refers to a valid node if there exists one.
- return Iter.Nod /= null;
+ return Present (Iter.Curr_Nod);
end Is_Valid;
--------------
@@ -833,19 +931,19 @@ package body GNAT.Dynamic_HTables is
-- A node is valid if it is non-null, and does not refer to the dummy
-- head of some bucket.
- return Nod /= null and then Nod /= Head;
+ return Present (Nod) and then Nod /= Head;
end Is_Valid;
-------------
-- Iterate --
-------------
- function Iterate (T : Instance) return Iterator is
+ function Iterate (T : Dynamic_Hash_Table) return Iterator is
Iter : Iterator;
begin
Ensure_Created (T);
- pragma Assert (T.Buckets /= null);
+ pragma Assert (Present (T.Buckets));
-- Initialize the iterator to reference the first valid node in
-- the full range of hash table buckets. If no such node exists,
@@ -856,8 +954,8 @@ package body GNAT.Dynamic_HTables is
(T => T,
Low_Bkt => T.Buckets'First,
High_Bkt => T.Buckets'Last,
- Idx => Iter.Idx,
- Nod => Iter.Nod);
+ Idx => Iter.Curr_Idx,
+ Nod => Iter.Curr_Nod);
-- Associate the iterator with the hash table to allow for future
-- mutation functionality unlocking.
@@ -876,9 +974,9 @@ package body GNAT.Dynamic_HTables is
-- Load_Factor --
-----------------
- function Load_Factor (T : Instance) return Threshold_Type is
- pragma Assert (T /= null);
- pragma Assert (T.Buckets /= null);
+ function Load_Factor (T : Dynamic_Hash_Table) return Threshold_Type is
+ pragma Assert (Present (T));
+ pragma Assert (Present (T.Buckets));
begin
-- The load factor is the ratio of key-value pairs to buckets
@@ -890,7 +988,7 @@ package body GNAT.Dynamic_HTables is
-- Lock --
----------
- procedure Lock (T : Instance) is
+ procedure Lock (T : Dynamic_Hash_Table) is
begin
-- The hash table may be locked multiple times if multiple iterators
-- are operating over it.
@@ -902,7 +1000,10 @@ package body GNAT.Dynamic_HTables is
-- Mutate_And_Rehash --
-----------------------
- procedure Mutate_And_Rehash (T : Instance; Size : Bucket_Range_Type) is
+ procedure Mutate_And_Rehash
+ (T : Dynamic_Hash_Table;
+ Size : Bucket_Range_Type)
+ is
procedure Rehash (From : Bucket_Table_Ptr; To : Bucket_Table_Ptr);
pragma Inline (Rehash);
-- Remove all nodes from buckets From and rehash them into buckets To
@@ -922,8 +1023,8 @@ package body GNAT.Dynamic_HTables is
procedure Rehash (From : Bucket_Table_Ptr; To : Bucket_Table_Ptr) is
begin
- pragma Assert (From /= null);
- pragma Assert (To /= null);
+ pragma Assert (Present (From));
+ pragma Assert (Present (To));
for Scan_Idx in From'Range loop
Rehash_Bucket (From (Scan_Idx)'Access, To);
@@ -935,7 +1036,7 @@ package body GNAT.Dynamic_HTables is
-------------------
procedure Rehash_Bucket (Head : Node_Ptr; To : Bucket_Table_Ptr) is
- pragma Assert (Head /= null);
+ pragma Assert (Present (Head));
Nod : Node_Ptr;
@@ -955,7 +1056,7 @@ package body GNAT.Dynamic_HTables is
-----------------
procedure Rehash_Node (Nod : Node_Ptr; To : Bucket_Table_Ptr) is
- pragma Assert (Nod /= null);
+ pragma Assert (Present (Nod));
Head : Node_Ptr;
@@ -982,7 +1083,7 @@ package body GNAT.Dynamic_HTables is
-- Start of processing for Mutate_And_Rehash
begin
- pragma Assert (T /= null);
+ pragma Assert (Present (T));
Old_Bkts := T.Buckets;
T.Buckets := new Bucket_Table (0 .. Size - 1);
@@ -1000,13 +1101,13 @@ package body GNAT.Dynamic_HTables is
procedure Next (Iter : in out Iterator; Key : out Key_Type) is
Is_OK : constant Boolean := Is_Valid (Iter);
- Saved : constant Node_Ptr := Iter.Nod;
- T : constant Instance := Iter.Table;
+ Saved : constant Node_Ptr := Iter.Curr_Nod;
+ T : constant Dynamic_Hash_Table := Iter.Table;
Head : Node_Ptr;
begin
- pragma Assert (T /= null);
- pragma Assert (T.Buckets /= null);
+ pragma Assert (Present (T));
+ pragma Assert (Present (T.Buckets));
-- The iterator is no longer valid which indicates that it has been
-- exhausted. Unlock all mutation functionality of the hash table as
@@ -1019,21 +1120,21 @@ package body GNAT.Dynamic_HTables is
-- Advance to the next node along the same bucket
- Iter.Nod := Iter.Nod.Next;
- Head := T.Buckets (Iter.Idx)'Access;
+ Iter.Curr_Nod := Iter.Curr_Nod.Next;
+ Head := T.Buckets (Iter.Curr_Idx)'Access;
-- If the new node is no longer valid, then this indicates that the
-- current bucket has been exhausted. Advance to the next valid node
-- within the remaining range of buckets. If no such node exists, the
-- iterator is left in a state which does not allow it to advance.
- if not Is_Valid (Iter.Nod, Head) then
+ if not Is_Valid (Iter.Curr_Nod, Head) then
First_Valid_Node
- (T => T,
- Low_Bkt => Iter.Idx + 1,
+ (T => T,
+ Low_Bkt => Iter.Curr_Idx + 1,
High_Bkt => T.Buckets'Last,
- Idx => Iter.Idx,
- Nod => Iter.Nod);
+ Idx => Iter.Curr_Idx,
+ Nod => Iter.Curr_Nod);
end if;
Key := Saved.Key;
@@ -1044,8 +1145,8 @@ package body GNAT.Dynamic_HTables is
-------------
procedure Prepend (Nod : Node_Ptr; Head : Node_Ptr) is
- pragma Assert (Nod /= null);
- pragma Assert (Head /= null);
+ pragma Assert (Present (Nod));
+ pragma Assert (Present (Head));
Next : constant Node_Ptr := Head.Next;
@@ -1057,11 +1158,42 @@ package body GNAT.Dynamic_HTables is
Nod.Prev := Head;
end Prepend;
+ -------------
+ -- Present --
+ -------------
+
+ function Present (Bkts : Bucket_Table_Ptr) return Boolean is
+ begin
+ return Bkts /= null;
+ end Present;
+
+ -------------
+ -- Present --
+ -------------
+
+ function Present (Nod : Node_Ptr) return Boolean is
+ begin
+ return Nod /= null;
+ end Present;
+
+ -------------
+ -- Present --
+ -------------
+
+ function Present (T : Dynamic_Hash_Table) return Boolean is
+ begin
+ return T /= Nil;
+ end Present;
+
---------
-- Put --
---------
- procedure Put (T : Instance; Key : Key_Type; Value : Value_Type) is
+ procedure Put
+ (T : Dynamic_Hash_Table;
+ Key : Key_Type;
+ Value : Value_Type)
+ is
procedure Expand;
pragma Inline (Expand);
-- Determine whether hash table T requires expansion, and if so,
@@ -1078,8 +1210,8 @@ package body GNAT.Dynamic_HTables is
------------
procedure Expand is
- pragma Assert (T /= null);
- pragma Assert (T.Buckets /= null);
+ pragma Assert (Present (T));
+ pragma Assert (Present (T.Buckets));
Old_Size : constant Bucket_Range_Type := T.Buckets'Length;
@@ -1099,7 +1231,7 @@ package body GNAT.Dynamic_HTables is
------------------------
procedure Prepend_Or_Replace (Head : Node_Ptr) is
- pragma Assert (Head /= null);
+ pragma Assert (Present (Head));
Nod : Node_Ptr;
@@ -1166,7 +1298,7 @@ package body GNAT.Dynamic_HTables is
-- Reset --
-----------
- procedure Reset (T : Instance) is
+ procedure Reset (T : Dynamic_Hash_Table) is
begin
Ensure_Created (T);
Ensure_Unlocked (T);
@@ -1186,7 +1318,7 @@ package body GNAT.Dynamic_HTables is
-- Size --
----------
- function Size (T : Instance) return Natural is
+ function Size (T : Dynamic_Hash_Table) return Natural is
begin
Ensure_Created (T);
@@ -1197,13 +1329,13 @@ package body GNAT.Dynamic_HTables is
-- Unlock --
------------
- procedure Unlock (T : Instance) is
+ procedure Unlock (T : Dynamic_Hash_Table) is
begin
-- The hash table may be locked multiple times if multiple iterators
-- are operating over it.
T.Iterators := T.Iterators - 1;
end Unlock;
- end Dynamic_HTable;
+ end Dynamic_Hash_Tables;
end GNAT.Dynamic_HTables;
diff --git a/gcc/ada/libgnat/g-dynhta.ads b/gcc/ada/libgnat/g-dynhta.ads
index 0f81d72..107c4c0 100644
--- a/gcc/ada/libgnat/g-dynhta.ads
+++ b/gcc/ada/libgnat/g-dynhta.ads
@@ -50,6 +50,12 @@ pragma Compiler_Unit_Warning;
package GNAT.Dynamic_HTables is
+ function Hash_Two_Keys
+ (Left : Bucket_Range_Type;
+ Right : Bucket_Range_Type) return Bucket_Range_Type;
+ pragma Inline (Hash_Two_Keys);
+ -- Obtain the hash value of keys Left and Right
+
-------------------
-- Static_HTable --
-------------------
@@ -258,16 +264,16 @@ package GNAT.Dynamic_HTables is
Nil : constant Instance := Instance (Tab.Nil);
end Simple_HTable;
- --------------------
- -- Dynamic_HTable --
- --------------------
+ -------------------------
+ -- Dynamic_Hash_Tables --
+ -------------------------
-- The following package offers a hash table abstraction with the following
-- characteristics:
--
- -- * Dynamic resizing based on load factor.
- -- * Creation of multiple instances, of different sizes.
- -- * Iterable keys.
+ -- * Dynamic resizing based on load factor
+ -- * Creation of multiple instances, of different sizes
+ -- * Iterable keys
--
-- This type of hash table is best used in scenarios where the size of the
-- key set is not known. The dynamic resizing aspect allows for performance
@@ -275,7 +281,7 @@ package GNAT.Dynamic_HTables is
--
-- The following use pattern must be employed when operating this table:
--
- -- Table : Instance := Create (<some size>);
+ -- Table : Dynamic_Hash_Table := Create (<some size>);
--
-- <various operations>
--
@@ -327,10 +333,13 @@ package GNAT.Dynamic_HTables is
(Left : Key_Type;
Right : Key_Type) return Boolean;
+ with procedure Destroy_Value (Val : in out Value_Type);
+ -- Value destructor
+
with function Hash (Key : Key_Type) return Bucket_Range_Type;
-- Map an arbitrary key into the range of buckets
- package Dynamic_HTable is
+ package Dynamic_Hash_Tables is
----------------------
-- Table operations --
@@ -339,34 +348,49 @@ package GNAT.Dynamic_HTables is
-- The following type denotes a hash table handle. Each instance must be
-- created using routine Create.
- type Instance is private;
- Nil : constant Instance;
+ type Dynamic_Hash_Table is private;
+ Nil : constant Dynamic_Hash_Table;
- function Create (Initial_Size : Positive) return Instance;
+ function Contains
+ (T : Dynamic_Hash_Table;
+ Key : Key_Type) return Boolean;
+ -- Determine whether key Key exists in hash table T
+
+ function Create (Initial_Size : Positive) return Dynamic_Hash_Table;
-- Create a new table with bucket capacity Initial_Size. This routine
-- must be called at the start of a hash table's lifetime.
- procedure Delete (T : Instance; Key : Key_Type);
+ procedure Delete
+ (T : Dynamic_Hash_Table;
+ Key : Key_Type);
-- Delete the value which corresponds to key Key from hash table T. The
-- routine has no effect if the value is not present in the hash table.
-- This action will raise Iterated if the hash table has outstanding
-- iterators. If the load factor drops below Compression_Threshold, the
-- size of the buckets is decreased by Copression_Factor.
- procedure Destroy (T : in out Instance);
+ procedure Destroy (T : in out Dynamic_Hash_Table);
-- Destroy the contents of hash table T, rendering it unusable. This
-- routine must be called at the end of a hash table's lifetime. This
-- action will raise Iterated if the hash table has outstanding
-- iterators.
- function Get (T : Instance; Key : Key_Type) return Value_Type;
+ function Get
+ (T : Dynamic_Hash_Table;
+ Key : Key_Type) return Value_Type;
-- Obtain the value which corresponds to key Key from hash table T. If
-- the value does not exist, return No_Value.
- function Is_Empty (T : Instance) return Boolean;
+ function Is_Empty (T : Dynamic_Hash_Table) return Boolean;
-- Determine whether hash table T is empty
- procedure Put (T : Instance; Key : Key_Type; Value : Value_Type);
+ function Present (T : Dynamic_Hash_Table) return Boolean;
+ -- Determine whether hash table T exists
+
+ procedure Put
+ (T : Dynamic_Hash_Table;
+ Key : Key_Type;
+ Value : Value_Type);
-- Associate value Value with key Key in hash table T. If the table
-- already contains a mapping of the same key to a previous value, the
-- previous value is overwritten. This action will raise Iterated if
@@ -374,12 +398,12 @@ package GNAT.Dynamic_HTables is
-- over Expansion_Threshold, the size of the buckets is increased by
-- Expansion_Factor.
- procedure Reset (T : Instance);
+ procedure Reset (T : Dynamic_Hash_Table);
-- Destroy the contents of hash table T, and reset it to its initial
-- created state. This action will raise Iterated if the hash table
-- has outstanding iterators.
- function Size (T : Instance) return Natural;
+ function Size (T : Dynamic_Hash_Table) return Natural;
-- Obtain the number of key-value pairs in hash table T
-------------------------
@@ -401,15 +425,15 @@ package GNAT.Dynamic_HTables is
type Iterator is private;
- function Iterate (T : Instance) return Iterator;
- -- Obtain an iterator over the keys of hash table T. This action locks
- -- all mutation functionality of the associated hash table.
-
function Has_Next (Iter : Iterator) return Boolean;
-- Determine whether iterator Iter has more keys to examine. If the
-- iterator has been exhausted, restore all mutation functionality of
-- the associated hash table.
+ function Iterate (T : Dynamic_Hash_Table) return Iterator;
+ -- Obtain an iterator over the keys of hash table T. This action locks
+ -- all mutation functionality of the associated hash table.
+
procedure Next (Iter : in out Iterator; Key : out Key_Type);
-- Return the current key referenced by iterator Iter and advance to
-- the next available key. If the iterator has been exhausted and
@@ -455,7 +479,7 @@ package GNAT.Dynamic_HTables is
-- The following type represents a hash table
- type Hash_Table is record
+ type Dynamic_Hash_Table_Attributes is record
Buckets : Bucket_Table_Ptr := null;
-- Reference to the compressing / expanding buckets
@@ -469,25 +493,25 @@ package GNAT.Dynamic_HTables is
-- Number of key-value pairs in the buckets
end record;
- type Instance is access Hash_Table;
- Nil : constant Instance := null;
+ type Dynamic_Hash_Table is access Dynamic_Hash_Table_Attributes;
+ Nil : constant Dynamic_Hash_Table := null;
-- The following type represents a key iterator
type Iterator is record
- Idx : Bucket_Range_Type := 0;
+ Curr_Idx : Bucket_Range_Type := 0;
-- Index of the current bucket being examined. This index is always
-- kept within the range of the buckets.
- Nod : Node_Ptr := null;
+ Curr_Nod : Node_Ptr := null;
-- Reference to the current node being examined within the current
-- bucket. The invariant of the iterator requires that this field
-- always point to a valid node. A value of null indicates that the
-- iterator is exhausted.
- Table : Instance := null;
+ Table : Dynamic_Hash_Table := null;
-- Reference to the associated hash table
end record;
- end Dynamic_HTable;
+ end Dynamic_Hash_Tables;
end GNAT.Dynamic_HTables;
diff --git a/gcc/ada/libgnat/g-graphs.adb b/gcc/ada/libgnat/g-graphs.adb
new file mode 100644
index 0000000..1049641
--- /dev/null
+++ b/gcc/ada/libgnat/g-graphs.adb
@@ -0,0 +1,1491 @@
+------------------------------------------------------------------------------
+-- --
+-- GNAT RUN-TIME COMPONENTS --
+-- --
+-- G N A T . G R A P H S --
+-- --
+-- B o d y --
+-- --
+-- Copyright (C) 2018-2019, 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. --
+-- --
+------------------------------------------------------------------------------
+
+with Ada.Unchecked_Deallocation;
+
+package body GNAT.Graphs is
+
+ -----------------------
+ -- Local subprograms --
+ -----------------------
+
+ function Sequence_Next_Component return Component_Id;
+ -- Produce the next handle for a component. The handle is guaranteed to be
+ -- unique across all graphs.
+
+ --------------------
+ -- Directed_Graph --
+ --------------------
+
+ package body Directed_Graphs is
+
+ -----------------------
+ -- Local subprograms --
+ -----------------------
+
+ procedure Add_Component
+ (G : Directed_Graph;
+ Comp : Component_Id;
+ Vertices : Vertex_List.Doubly_Linked_List);
+ pragma Inline (Add_Component);
+ -- Add component Comp which houses vertices Vertices to graph G
+
+ procedure Ensure_Created (G : Directed_Graph);
+ pragma Inline (Ensure_Created);
+ -- Verify that graph G is created. Raise Not_Created if this is not the
+ -- case.
+
+ procedure Ensure_Not_Present
+ (G : Directed_Graph;
+ E : Edge_Id);
+ pragma Inline (Ensure_Not_Present);
+ -- Verify that graph G lacks edge E. Raise Duplicate_Edge if this is not
+ -- the case.
+
+ procedure Ensure_Not_Present
+ (G : Directed_Graph;
+ V : Vertex_Id);
+ pragma Inline (Ensure_Not_Present);
+ -- Verify that graph G lacks vertex V. Raise Duplicate_Vertex if this is
+ -- not the case.
+
+ procedure Ensure_Present
+ (G : Directed_Graph;
+ Comp : Component_Id);
+ pragma Inline (Ensure_Present);
+ -- Verify that component Comp exists in graph G. Raise Missing_Component
+ -- if this is not the case.
+
+ procedure Ensure_Present
+ (G : Directed_Graph;
+ E : Edge_Id);
+ pragma Inline (Ensure_Present);
+ -- Verify that edge E is present in graph G. Raise Missing_Edge if this
+ -- is not the case.
+
+ procedure Ensure_Present
+ (G : Directed_Graph;
+ V : Vertex_Id);
+ pragma Inline (Ensure_Present);
+ -- Verify that vertex V is present in graph G. Raise Missing_Vertex if
+ -- this is not the case.
+
+ procedure Free is
+ new Ada.Unchecked_Deallocation
+ (Directed_Graph_Attributes, Directed_Graph);
+
+ function Get_Component_Attributes
+ (G : Directed_Graph;
+ Comp : Component_Id) return Component_Attributes;
+ pragma Inline (Get_Component_Attributes);
+ -- Obtain the attributes of component Comp of graph G
+
+ function Get_Edge_Attributes
+ (G : Directed_Graph;
+ E : Edge_Id) return Edge_Attributes;
+ pragma Inline (Get_Edge_Attributes);
+ -- Obtain the attributes of edge E of graph G
+
+ function Get_Vertex_Attributes
+ (G : Directed_Graph;
+ V : Vertex_Id) return Vertex_Attributes;
+ pragma Inline (Get_Vertex_Attributes);
+ -- Obtain the attributes of vertex V of graph G
+
+ function Get_Outgoing_Edges
+ (G : Directed_Graph;
+ V : Vertex_Id) return Edge_Set.Membership_Set;
+ pragma Inline (Get_Outgoing_Edges);
+ -- Obtain the Outgoing_Edges attribute of vertex V of graph G
+
+ function Get_Vertices
+ (G : Directed_Graph;
+ Comp : Component_Id) return Vertex_List.Doubly_Linked_List;
+ pragma Inline (Get_Vertices);
+ -- Obtain the Vertices attribute of component Comp of graph G
+
+ procedure Set_Component
+ (G : Directed_Graph;
+ V : Vertex_Id;
+ Val : Component_Id);
+ pragma Inline (Set_Component);
+ -- Set attribute Component of vertex V of graph G to value Val
+
+ procedure Set_Outgoing_Edges
+ (G : Directed_Graph;
+ V : Vertex_Id;
+ Val : Edge_Set.Membership_Set);
+ pragma Inline (Set_Outgoing_Edges);
+ -- Set attribute Outgoing_Edges of vertex V of graph G to value Val
+
+ procedure Set_Vertex_Attributes
+ (G : Directed_Graph;
+ V : Vertex_Id;
+ Val : Vertex_Attributes);
+ pragma Inline (Set_Vertex_Attributes);
+ -- Set the attributes of vertex V of graph G to value Val
+
+ -------------------
+ -- Add_Component --
+ -------------------
+
+ procedure Add_Component
+ (G : Directed_Graph;
+ Comp : Component_Id;
+ Vertices : Vertex_List.Doubly_Linked_List)
+ is
+ begin
+ pragma Assert (Present (G));
+
+ -- Add the component to the set of all components in the graph
+
+ Component_Map.Put
+ (T => G.Components,
+ Key => Comp,
+ Value => (Vertices => Vertices));
+ end Add_Component;
+
+ --------------
+ -- Add_Edge --
+ --------------
+
+ procedure Add_Edge
+ (G : Directed_Graph;
+ E : Edge_Id;
+ Source : Vertex_Id;
+ Destination : Vertex_Id)
+ is
+ begin
+ Ensure_Created (G);
+ Ensure_Not_Present (G, E);
+ Ensure_Present (G, Source);
+ Ensure_Present (G, Destination);
+
+ -- Add the edge to the set of all edges in the graph
+
+ Edge_Map.Put
+ (T => G.All_Edges,
+ Key => E,
+ Value =>
+ (Destination => Destination,
+ Source => Source));
+
+ -- Associate the edge with its source vertex which effectively "owns"
+ -- the edge.
+
+ Edge_Set.Insert
+ (S => Get_Outgoing_Edges (G, Source),
+ Elem => E);
+ end Add_Edge;
+
+ ----------------
+ -- Add_Vertex --
+ ----------------
+
+ procedure Add_Vertex
+ (G : Directed_Graph;
+ V : Vertex_Id)
+ is
+ begin
+ Ensure_Created (G);
+ Ensure_Not_Present (G, V);
+
+ -- Add the vertex to the set of all vertices in the graph
+
+ Vertex_Map.Put
+ (T => G.All_Vertices,
+ Key => V,
+ Value =>
+ (Component => No_Component,
+ Outgoing_Edges => Edge_Set.Nil));
+
+ -- It is assumed that the vertex will have at least one outgoing
+ -- edge. It is important not to create the set of edges above as
+ -- the call to Put may fail in case the vertices are iterated.
+ -- This would lead to a memory leak because the set would not be
+ -- reclaimed.
+
+ Set_Outgoing_Edges (G, V, Edge_Set.Create (1));
+ end Add_Vertex;
+
+ ---------------
+ -- Component --
+ ---------------
+
+ function Component
+ (G : Directed_Graph;
+ V : Vertex_Id) return Component_Id
+ is
+ begin
+ Ensure_Created (G);
+ Ensure_Present (G, V);
+
+ return Get_Vertex_Attributes (G, V).Component;
+ end Component;
+
+ ------------------------
+ -- Contains_Component --
+ ------------------------
+
+ function Contains_Component
+ (G : Directed_Graph;
+ Comp : Component_Id) return Boolean
+ is
+ begin
+ Ensure_Created (G);
+
+ return Component_Map.Contains (G.Components, Comp);
+ end Contains_Component;
+
+ -------------------
+ -- Contains_Edge --
+ -------------------
+
+ function Contains_Edge
+ (G : Directed_Graph;
+ E : Edge_Id) return Boolean
+ is
+ begin
+ Ensure_Created (G);
+
+ return Edge_Map.Contains (G.All_Edges, E);
+ end Contains_Edge;
+
+ ---------------------
+ -- Contains_Vertex --
+ ---------------------
+
+ function Contains_Vertex
+ (G : Directed_Graph;
+ V : Vertex_Id) return Boolean
+ is
+ begin
+ Ensure_Created (G);
+
+ return Vertex_Map.Contains (G.All_Vertices, V);
+ end Contains_Vertex;
+
+ ------------
+ -- Create --
+ ------------
+
+ function Create
+ (Initial_Vertices : Positive;
+ Initial_Edges : Positive) return Directed_Graph
+ is
+ G : constant Directed_Graph := new Directed_Graph_Attributes;
+
+ begin
+ G.All_Edges := Edge_Map.Create (Initial_Edges);
+ G.All_Vertices := Vertex_Map.Create (Initial_Vertices);
+ G.Components := Component_Map.Create (Initial_Vertices);
+
+ return G;
+ end Create;
+
+ -----------------
+ -- Delete_Edge --
+ -----------------
+
+ procedure Delete_Edge
+ (G : Directed_Graph;
+ E : Edge_Id)
+ is
+ Source : Vertex_Id;
+
+ begin
+ Ensure_Created (G);
+ Ensure_Present (G, E);
+
+ Source := Source_Vertex (G, E);
+ Ensure_Present (G, Source);
+
+ -- Delete the edge from its source vertex which effectively "owns"
+ -- the edge.
+
+ Edge_Set.Delete (Get_Outgoing_Edges (G, Source), E);
+
+ -- Delete the edge from the set of all edges
+
+ Edge_Map.Delete (G.All_Edges, E);
+ end Delete_Edge;
+
+ ------------------------
+ -- Destination_Vertex --
+ ------------------------
+
+ function Destination_Vertex
+ (G : Directed_Graph;
+ E : Edge_Id) return Vertex_Id
+ is
+ begin
+ Ensure_Created (G);
+ Ensure_Present (G, E);
+
+ return Get_Edge_Attributes (G, E).Destination;
+ end Destination_Vertex;
+
+ -------------
+ -- Destroy --
+ -------------
+
+ procedure Destroy (G : in out Directed_Graph) is
+ begin
+ Ensure_Created (G);
+
+ Edge_Map.Destroy (G.All_Edges);
+ Vertex_Map.Destroy (G.All_Vertices);
+ Component_Map.Destroy (G.Components);
+
+ Free (G);
+ end Destroy;
+
+ ----------------------------------
+ -- Destroy_Component_Attributes --
+ ----------------------------------
+
+ procedure Destroy_Component_Attributes
+ (Attrs : in out Component_Attributes)
+ is
+ begin
+ Vertex_List.Destroy (Attrs.Vertices);
+ end Destroy_Component_Attributes;
+
+ -----------------------------
+ -- Destroy_Edge_Attributes --
+ -----------------------------
+
+ procedure Destroy_Edge_Attributes (Attrs : in out Edge_Attributes) is
+ pragma Unreferenced (Attrs);
+ begin
+ null;
+ end Destroy_Edge_Attributes;
+
+ --------------------
+ -- Destroy_Vertex --
+ --------------------
+
+ procedure Destroy_Vertex (V : in out Vertex_Id) is
+ pragma Unreferenced (V);
+ begin
+ null;
+ end Destroy_Vertex;
+
+ -------------------------------
+ -- Destroy_Vertex_Attributes --
+ -------------------------------
+
+ procedure Destroy_Vertex_Attributes (Attrs : in out Vertex_Attributes) is
+ begin
+ Edge_Set.Destroy (Attrs.Outgoing_Edges);
+ end Destroy_Vertex_Attributes;
+
+ --------------------
+ -- Ensure_Created --
+ --------------------
+
+ procedure Ensure_Created (G : Directed_Graph) is
+ begin
+ if not Present (G) then
+ raise Not_Created;
+ end if;
+ end Ensure_Created;
+
+ ------------------------
+ -- Ensure_Not_Present --
+ ------------------------
+
+ procedure Ensure_Not_Present
+ (G : Directed_Graph;
+ E : Edge_Id)
+ is
+ begin
+ if Contains_Edge (G, E) then
+ raise Duplicate_Edge;
+ end if;
+ end Ensure_Not_Present;
+
+ ------------------------
+ -- Ensure_Not_Present --
+ ------------------------
+
+ procedure Ensure_Not_Present
+ (G : Directed_Graph;
+ V : Vertex_Id)
+ is
+ begin
+ if Contains_Vertex (G, V) then
+ raise Duplicate_Vertex;
+ end if;
+ end Ensure_Not_Present;
+
+ --------------------
+ -- Ensure_Present --
+ --------------------
+
+ procedure Ensure_Present
+ (G : Directed_Graph;
+ Comp : Component_Id)
+ is
+ begin
+ if not Contains_Component (G, Comp) then
+ raise Missing_Component;
+ end if;
+ end Ensure_Present;
+
+ --------------------
+ -- Ensure_Present --
+ --------------------
+
+ procedure Ensure_Present
+ (G : Directed_Graph;
+ E : Edge_Id)
+ is
+ begin
+ if not Contains_Edge (G, E) then
+ raise Missing_Edge;
+ end if;
+ end Ensure_Present;
+
+ --------------------
+ -- Ensure_Present --
+ --------------------
+
+ procedure Ensure_Present
+ (G : Directed_Graph;
+ V : Vertex_Id)
+ is
+ begin
+ if not Contains_Vertex (G, V) then
+ raise Missing_Vertex;
+ end if;
+ end Ensure_Present;
+
+ ---------------------
+ -- Find_Components --
+ ---------------------
+
+ procedure Find_Components (G : Directed_Graph) is
+
+ -- The components of graph G are discovered using Tarjan's strongly
+ -- connected component algorithm. Do not modify this code unless you
+ -- intimately understand the algorithm.
+
+ ----------------
+ -- Tarjan_Map --
+ ----------------
+
+ type Visitation_Number is new Natural;
+ No_Visitation_Number : constant Visitation_Number :=
+ Visitation_Number'First;
+ First_Visitation_Number : constant Visitation_Number :=
+ No_Visitation_Number + 1;
+
+ type Tarjan_Attributes is record
+ Index : Visitation_Number := No_Visitation_Number;
+ -- Visitation number
+
+ Low_Link : Visitation_Number := No_Visitation_Number;
+ -- Lowest visitation number
+
+ On_Stack : Boolean := False;
+ -- Set when the corresponding vertex appears on the Stack
+ end record;
+
+ No_Tarjan_Attributes : constant Tarjan_Attributes :=
+ (Index => No_Visitation_Number,
+ Low_Link => No_Visitation_Number,
+ On_Stack => False);
+
+ procedure Destroy_Tarjan_Attributes
+ (Attrs : in out Tarjan_Attributes);
+ -- Destroy the contents of attributes Attrs
+
+ package Tarjan_Map is new Dynamic_Hash_Tables
+ (Key_Type => Vertex_Id,
+ Value_Type => Tarjan_Attributes,
+ No_Value => No_Tarjan_Attributes,
+ Expansion_Threshold => 1.5,
+ Expansion_Factor => 2,
+ Compression_Threshold => 0.3,
+ Compression_Factor => 2,
+ "=" => Same_Vertex,
+ Destroy_Value => Destroy_Tarjan_Attributes,
+ Hash => Hash_Vertex);
+
+ ------------------
+ -- Tarjan_Stack --
+ ------------------
+
+ package Tarjan_Stack is new Doubly_Linked_Lists
+ (Element_Type => Vertex_Id,
+ "=" => Same_Vertex,
+ Destroy_Element => Destroy_Vertex);
+
+ -----------------
+ -- Global data --
+ -----------------
+
+ Attrs : Tarjan_Map.Dynamic_Hash_Table := Tarjan_Map.Nil;
+ Stack : Tarjan_Stack.Doubly_Linked_List := Tarjan_Stack.Nil;
+
+ -----------------------
+ -- Local subprograms --
+ -----------------------
+
+ procedure Associate_All_Vertices;
+ pragma Inline (Associate_All_Vertices);
+ -- Associate all vertices in the graph with the corresponding
+ -- components that house them.
+
+ procedure Associate_Vertices (Comp : Component_Id);
+ pragma Inline (Associate_Vertices);
+ -- Associate all vertices of component Comp with the component
+
+ procedure Create_Component (V : Vertex_Id);
+ pragma Inline (Create_Component);
+ -- Create a new component with root vertex V
+
+ function Get_Tarjan_Attributes
+ (V : Vertex_Id) return Tarjan_Attributes;
+ pragma Inline (Get_Tarjan_Attributes);
+ -- Obtain the Tarjan attributes of vertex V
+
+ function Index (V : Vertex_Id) return Visitation_Number;
+ pragma Inline (Index);
+ -- Obtain the Index attribute of vertex V
+
+ procedure Initialize_Components;
+ pragma Inline (Initialize_Components);
+ -- Initialize or reinitialize the components of the graph
+
+ function Is_Visited (V : Vertex_Id) return Boolean;
+ pragma Inline (Is_Visited);
+ -- Determine whether vertex V has been visited
+
+ function Low_Link (V : Vertex_Id) return Visitation_Number;
+ pragma Inline (Low_Link);
+ -- Obtain the Low_Link attribute of vertex V
+
+ function On_Stack (V : Vertex_Id) return Boolean;
+ pragma Inline (On_Stack);
+ -- Obtain the On_Stack attribute of vertex V
+
+ function Pop return Vertex_Id;
+ pragma Inline (Pop);
+ -- Pop a vertex off Stack
+
+ procedure Push (V : Vertex_Id);
+ pragma Inline (Push);
+ -- Push vertex V on Stack
+
+ procedure Record_Visit (V : Vertex_Id);
+ pragma Inline (Record_Visit);
+ -- Save the visitation of vertex V by setting relevant attributes
+
+ function Sequence_Next_Index return Visitation_Number;
+ pragma Inline (Sequence_Next_Index);
+ -- Procedure the next visitation number of the DFS traversal
+
+ procedure Set_Index
+ (V : Vertex_Id;
+ Val : Visitation_Number);
+ pragma Inline (Set_Index);
+ -- Set attribute Index of vertex V to value Val
+
+ procedure Set_Low_Link
+ (V : Vertex_Id;
+ Val : Visitation_Number);
+ pragma Inline (Set_Low_Link);
+ -- Set attribute Low_Link of vertex V to value Val
+
+ procedure Set_On_Stack
+ (V : Vertex_Id;
+ Val : Boolean);
+ pragma Inline (Set_On_Stack);
+ -- Set attribute On_Stack of vertex V to value Val
+
+ procedure Set_Tarjan_Attributes
+ (V : Vertex_Id;
+ Val : Tarjan_Attributes);
+ pragma Inline (Set_Tarjan_Attributes);
+ -- Set the attributes of vertex V to value Val
+
+ procedure Visit_Successors (V : Vertex_Id);
+ pragma Inline (Visit_Successors);
+ -- Visit the successors of vertex V
+
+ procedure Visit_Vertex (V : Vertex_Id);
+ pragma Inline (Visit_Vertex);
+ -- Visit single vertex V
+
+ procedure Visit_Vertices;
+ pragma Inline (Visit_Vertices);
+ -- Visit all vertices in the graph
+
+ ----------------------------
+ -- Associate_All_Vertices --
+ ----------------------------
+
+ procedure Associate_All_Vertices is
+ Comp : Component_Id;
+ Iter : Component_Iterator;
+
+ begin
+ Iter := Iterate_Components (G);
+ while Has_Next (Iter) loop
+ Next (Iter, Comp);
+
+ Associate_Vertices (Comp);
+ end loop;
+ end Associate_All_Vertices;
+
+ ------------------------
+ -- Associate_Vertices --
+ ------------------------
+
+ procedure Associate_Vertices (Comp : Component_Id) is
+ Iter : Component_Vertex_Iterator;
+ V : Vertex_Id;
+
+ begin
+ Iter := Iterate_Component_Vertices (G, Comp);
+ while Has_Next (Iter) loop
+ Next (Iter, V);
+
+ Set_Component (G, V, Comp);
+ end loop;
+ end Associate_Vertices;
+
+ ----------------------
+ -- Create_Component --
+ ----------------------
+
+ procedure Create_Component (V : Vertex_Id) is
+ Curr_V : Vertex_Id;
+ Vertices : Vertex_List.Doubly_Linked_List;
+
+ begin
+ Vertices := Vertex_List.Create;
+
+ -- Collect all vertices that comprise the current component by
+ -- popping the stack until reaching the root vertex V.
+
+ loop
+ Curr_V := Pop;
+ Vertex_List.Append (Vertices, Curr_V);
+
+ exit when Same_Vertex (Curr_V, V);
+ end loop;
+
+ Add_Component
+ (G => G,
+ Comp => Sequence_Next_Component,
+ Vertices => Vertices);
+ end Create_Component;
+
+ -------------------------------
+ -- Destroy_Tarjan_Attributes --
+ -------------------------------
+
+ procedure Destroy_Tarjan_Attributes
+ (Attrs : in out Tarjan_Attributes)
+ is
+ pragma Unreferenced (Attrs);
+ begin
+ null;
+ end Destroy_Tarjan_Attributes;
+
+ ---------------------------
+ -- Get_Tarjan_Attributes --
+ ---------------------------
+
+ function Get_Tarjan_Attributes
+ (V : Vertex_Id) return Tarjan_Attributes
+ is
+ begin
+ pragma Assert (Present (G));
+ pragma Assert (Contains_Vertex (G, V));
+
+ return Tarjan_Map.Get (Attrs, V);
+ end Get_Tarjan_Attributes;
+
+ -----------
+ -- Index --
+ -----------
+
+ function Index (V : Vertex_Id) return Visitation_Number is
+ begin
+ pragma Assert (Present (G));
+ pragma Assert (Contains_Vertex (G, V));
+
+ return Get_Tarjan_Attributes (V).Index;
+ end Index;
+
+ ---------------------------
+ -- Initialize_Components --
+ ---------------------------
+
+ procedure Initialize_Components is
+ begin
+ pragma Assert (Present (G));
+
+ -- The graph already contains a set of components. Reinitialize
+ -- them in order to accommodate the new set of components about to
+ -- be computed.
+
+ if Number_Of_Components (G) > 0 then
+ Component_Map.Destroy (G.Components);
+ G.Components := Component_Map.Create (Number_Of_Vertices (G));
+ end if;
+ end Initialize_Components;
+
+ ----------------
+ -- Is_Visited --
+ ----------------
+
+ function Is_Visited (V : Vertex_Id) return Boolean is
+ begin
+ pragma Assert (Present (G));
+ pragma Assert (Contains_Vertex (G, V));
+
+ return Index (V) /= No_Visitation_Number;
+ end Is_Visited;
+
+ --------------
+ -- Low_Link --
+ --------------
+
+ function Low_Link (V : Vertex_Id) return Visitation_Number is
+ begin
+ pragma Assert (Present (G));
+ pragma Assert (Contains_Vertex (G, V));
+
+ return Get_Tarjan_Attributes (V).Low_Link;
+ end Low_Link;
+
+ --------------
+ -- On_Stack --
+ --------------
+
+ function On_Stack (V : Vertex_Id) return Boolean is
+ begin
+ pragma Assert (Present (G));
+ pragma Assert (Contains_Vertex (G, V));
+
+ return Get_Tarjan_Attributes (V).On_Stack;
+ end On_Stack;
+
+ ---------
+ -- Pop --
+ ---------
+
+ function Pop return Vertex_Id is
+ V : Vertex_Id;
+
+ begin
+ V := Tarjan_Stack.Last (Stack);
+ Tarjan_Stack.Delete_Last (Stack);
+ Set_On_Stack (V, False);
+
+ pragma Assert (Present (G));
+ pragma Assert (Contains_Vertex (G, V));
+
+ return V;
+ end Pop;
+
+ ----------
+ -- Push --
+ ----------
+
+ procedure Push (V : Vertex_Id) is
+ begin
+ pragma Assert (Present (G));
+ pragma Assert (Contains_Vertex (G, V));
+
+ Tarjan_Stack.Append (Stack, V);
+ Set_On_Stack (V, True);
+ end Push;
+
+ ------------------
+ -- Record_Visit --
+ ------------------
+
+ procedure Record_Visit (V : Vertex_Id) is
+ Index : constant Visitation_Number := Sequence_Next_Index;
+
+ begin
+ pragma Assert (Present (G));
+ pragma Assert (Contains_Vertex (G, V));
+
+ Set_Index (V, Index);
+ Set_Low_Link (V, Index);
+ end Record_Visit;
+
+ -------------------------
+ -- Sequence_Next_Index --
+ -------------------------
+
+ Index_Sequencer : Visitation_Number := First_Visitation_Number;
+ -- The counter for visitation numbers. Do not directly manipulate its
+ -- value because this will destroy the Index and Low_Link invariants
+ -- of the algorithm.
+
+ function Sequence_Next_Index return Visitation_Number is
+ Index : constant Visitation_Number := Index_Sequencer;
+
+ begin
+ Index_Sequencer := Index_Sequencer + 1;
+ return Index;
+ end Sequence_Next_Index;
+
+ ---------------
+ -- Set_Index --
+ ---------------
+
+ procedure Set_Index
+ (V : Vertex_Id;
+ Val : Visitation_Number)
+ is
+ TA : Tarjan_Attributes;
+
+ begin
+ pragma Assert (Present (G));
+ pragma Assert (Contains_Vertex (G, V));
+
+ TA := Get_Tarjan_Attributes (V);
+ TA.Index := Val;
+ Set_Tarjan_Attributes (V, TA);
+ end Set_Index;
+
+ ------------------
+ -- Set_Low_Link --
+ ------------------
+
+ procedure Set_Low_Link
+ (V : Vertex_Id;
+ Val : Visitation_Number)
+ is
+ TA : Tarjan_Attributes;
+
+ begin
+ pragma Assert (Present (G));
+ pragma Assert (Contains_Vertex (G, V));
+
+ TA := Get_Tarjan_Attributes (V);
+ TA.Low_Link := Val;
+ Set_Tarjan_Attributes (V, TA);
+ end Set_Low_Link;
+
+ ------------------
+ -- Set_On_Stack --
+ ------------------
+
+ procedure Set_On_Stack
+ (V : Vertex_Id;
+ Val : Boolean)
+ is
+ TA : Tarjan_Attributes;
+
+ begin
+ pragma Assert (Present (G));
+ pragma Assert (Contains_Vertex (G, V));
+
+ TA := Get_Tarjan_Attributes (V);
+ TA.On_Stack := Val;
+ Set_Tarjan_Attributes (V, TA);
+ end Set_On_Stack;
+
+ ---------------------------
+ -- Set_Tarjan_Attributes --
+ ---------------------------
+
+ procedure Set_Tarjan_Attributes
+ (V : Vertex_Id;
+ Val : Tarjan_Attributes)
+ is
+ begin
+ pragma Assert (Present (G));
+ pragma Assert (Contains_Vertex (G, V));
+
+ Tarjan_Map.Put (Attrs, V, Val);
+ end Set_Tarjan_Attributes;
+
+ ----------------------
+ -- Visit_Successors --
+ ----------------------
+
+ procedure Visit_Successors (V : Vertex_Id) is
+ E : Edge_Id;
+ Iter : Outgoing_Edge_Iterator;
+ Succ : Vertex_Id;
+
+ begin
+ pragma Assert (Present (G));
+ pragma Assert (Contains_Vertex (G, V));
+
+ Iter := Iterate_Outgoing_Edges (G, V);
+ while Has_Next (Iter) loop
+ Next (Iter, E);
+
+ Succ := Destination_Vertex (G, E);
+ pragma Assert (Contains_Vertex (G, Succ));
+
+ -- The current successor has not been visited yet. Extend the
+ -- DFS traversal into it.
+
+ if not Is_Visited (Succ) then
+ Visit_Vertex (Succ);
+
+ Set_Low_Link (V,
+ Visitation_Number'Min (Low_Link (V), Low_Link (Succ)));
+
+ -- The current successor has been visited, and still remains on
+ -- the stack which indicates that it does not participate in a
+ -- component yet.
+
+ elsif On_Stack (Succ) then
+ Set_Low_Link (V,
+ Visitation_Number'Min (Low_Link (V), Index (Succ)));
+ end if;
+ end loop;
+ end Visit_Successors;
+
+ ------------------
+ -- Visit_Vertex --
+ ------------------
+
+ procedure Visit_Vertex (V : Vertex_Id) is
+ begin
+ pragma Assert (Present (G));
+ pragma Assert (Contains_Vertex (G, V));
+
+ if not Is_Visited (V) then
+ Record_Visit (V);
+ Push (V);
+ Visit_Successors (V);
+
+ -- The current vertex is the root of a component
+
+ if Low_Link (V) = Index (V) then
+ Create_Component (V);
+ end if;
+ end if;
+ end Visit_Vertex;
+
+ --------------------
+ -- Visit_Vertices --
+ --------------------
+
+ procedure Visit_Vertices is
+ Iter : All_Vertex_Iterator;
+ V : Vertex_Id;
+
+ begin
+ Iter := Iterate_All_Vertices (G);
+ while Has_Next (Iter) loop
+ Next (Iter, V);
+
+ Visit_Vertex (V);
+ end loop;
+ end Visit_Vertices;
+
+ -- Start of processing for Find_Components
+
+ begin
+ -- Initialize or reinitialize the components of the graph
+
+ Initialize_Components;
+
+ -- Prepare the extra attributes needed for each vertex, global
+ -- visitation number, and the stack where examined vertices are
+ -- placed.
+
+ Attrs := Tarjan_Map.Create (Number_Of_Vertices (G));
+ Stack := Tarjan_Stack.Create;
+
+ -- Start the DFS traversal of Tarjan's SCC algorithm
+
+ Visit_Vertices;
+
+ Tarjan_Map.Destroy (Attrs);
+ Tarjan_Stack.Destroy (Stack);
+
+ -- Associate each vertex with the component it belongs to
+
+ Associate_All_Vertices;
+ end Find_Components;
+
+ ------------------------------
+ -- Get_Component_Attributes --
+ ------------------------------
+
+ function Get_Component_Attributes
+ (G : Directed_Graph;
+ Comp : Component_Id) return Component_Attributes
+ is
+ begin
+ pragma Assert (Present (G));
+ pragma Assert (Contains_Component (G, Comp));
+
+ return Component_Map.Get (G.Components, Comp);
+ end Get_Component_Attributes;
+
+ -------------------------
+ -- Get_Edge_Attributes --
+ -------------------------
+
+ function Get_Edge_Attributes
+ (G : Directed_Graph;
+ E : Edge_Id) return Edge_Attributes
+ is
+ begin
+ pragma Assert (Present (G));
+ pragma Assert (Contains_Edge (G, E));
+
+ return Edge_Map.Get (G.All_Edges, E);
+ end Get_Edge_Attributes;
+
+ ---------------------------
+ -- Get_Vertex_Attributes --
+ ---------------------------
+
+ function Get_Vertex_Attributes
+ (G : Directed_Graph;
+ V : Vertex_Id) return Vertex_Attributes
+ is
+ begin
+ pragma Assert (Present (G));
+ pragma Assert (Contains_Vertex (G, V));
+
+ return Vertex_Map.Get (G.All_Vertices, V);
+ end Get_Vertex_Attributes;
+
+ ------------------------
+ -- Get_Outgoing_Edges --
+ ------------------------
+
+ function Get_Outgoing_Edges
+ (G : Directed_Graph;
+ V : Vertex_Id) return Edge_Set.Membership_Set
+ is
+ begin
+ pragma Assert (Present (G));
+ pragma Assert (Contains_Vertex (G, V));
+
+ return Get_Vertex_Attributes (G, V).Outgoing_Edges;
+ end Get_Outgoing_Edges;
+
+ ------------------
+ -- Get_Vertices --
+ ------------------
+
+ function Get_Vertices
+ (G : Directed_Graph;
+ Comp : Component_Id) return Vertex_List.Doubly_Linked_List
+ is
+ begin
+ pragma Assert (Present (G));
+ pragma Assert (Contains_Component (G, Comp));
+
+ return Get_Component_Attributes (G, Comp).Vertices;
+ end Get_Vertices;
+
+ --------------
+ -- Has_Next --
+ --------------
+
+ function Has_Next (Iter : All_Edge_Iterator) return Boolean is
+ begin
+ return Edge_Map.Has_Next (Edge_Map.Iterator (Iter));
+ end Has_Next;
+
+ --------------
+ -- Has_Next --
+ --------------
+
+ function Has_Next (Iter : All_Vertex_Iterator) return Boolean is
+ begin
+ return Vertex_Map.Has_Next (Vertex_Map.Iterator (Iter));
+ end Has_Next;
+
+ --------------
+ -- Has_Next --
+ --------------
+
+ function Has_Next (Iter : Component_Iterator) return Boolean is
+ begin
+ return Component_Map.Has_Next (Component_Map.Iterator (Iter));
+ end Has_Next;
+
+ --------------
+ -- Has_Next --
+ --------------
+
+ function Has_Next (Iter : Component_Vertex_Iterator) return Boolean is
+ begin
+ return Vertex_List.Has_Next (Vertex_List.Iterator (Iter));
+ end Has_Next;
+
+ --------------
+ -- Has_Next --
+ --------------
+
+ function Has_Next (Iter : Outgoing_Edge_Iterator) return Boolean is
+ begin
+ return Edge_Set.Has_Next (Edge_Set.Iterator (Iter));
+ end Has_Next;
+
+ --------------
+ -- Is_Empty --
+ --------------
+
+ function Is_Empty (G : Directed_Graph) return Boolean is
+ begin
+ Ensure_Created (G);
+
+ return
+ Edge_Map.Is_Empty (G.All_Edges)
+ and then Vertex_Map.Is_Empty (G.All_Vertices);
+ end Is_Empty;
+
+ -----------------------
+ -- Iterate_All_Edges --
+ -----------------------
+
+ function Iterate_All_Edges
+ (G : Directed_Graph) return All_Edge_Iterator
+ is
+ begin
+ Ensure_Created (G);
+
+ return All_Edge_Iterator (Edge_Map.Iterate (G.All_Edges));
+ end Iterate_All_Edges;
+
+ --------------------------
+ -- Iterate_All_Vertices --
+ --------------------------
+
+ function Iterate_All_Vertices
+ (G : Directed_Graph) return All_Vertex_Iterator
+ is
+ begin
+ Ensure_Created (G);
+
+ return All_Vertex_Iterator (Vertex_Map.Iterate (G.All_Vertices));
+ end Iterate_All_Vertices;
+
+ ------------------------
+ -- Iterate_Components --
+ ------------------------
+
+ function Iterate_Components
+ (G : Directed_Graph) return Component_Iterator
+ is
+ begin
+ Ensure_Created (G);
+
+ return Component_Iterator (Component_Map.Iterate (G.Components));
+ end Iterate_Components;
+
+ --------------------------------
+ -- Iterate_Component_Vertices --
+ --------------------------------
+
+ function Iterate_Component_Vertices
+ (G : Directed_Graph;
+ Comp : Component_Id) return Component_Vertex_Iterator
+ is
+ begin
+ Ensure_Created (G);
+ Ensure_Present (G, Comp);
+
+ return
+ Component_Vertex_Iterator
+ (Vertex_List.Iterate (Get_Vertices (G, Comp)));
+ end Iterate_Component_Vertices;
+
+ ----------------------------
+ -- Iterate_Outgoing_Edges --
+ ----------------------------
+
+ function Iterate_Outgoing_Edges
+ (G : Directed_Graph;
+ V : Vertex_Id) return Outgoing_Edge_Iterator
+ is
+ begin
+ Ensure_Created (G);
+ Ensure_Present (G, V);
+
+ return
+ Outgoing_Edge_Iterator
+ (Edge_Set.Iterate (Get_Outgoing_Edges (G, V)));
+ end Iterate_Outgoing_Edges;
+
+ ----------
+ -- Next --
+ ----------
+
+ procedure Next
+ (Iter : in out All_Edge_Iterator;
+ E : out Edge_Id)
+ is
+ begin
+ Edge_Map.Next (Edge_Map.Iterator (Iter), E);
+ end Next;
+
+ ----------
+ -- Next --
+ ----------
+
+ procedure Next
+ (Iter : in out All_Vertex_Iterator;
+ V : out Vertex_Id)
+ is
+ begin
+ Vertex_Map.Next (Vertex_Map.Iterator (Iter), V);
+ end Next;
+
+ ----------
+ -- Next --
+ ----------
+
+ procedure Next
+ (Iter : in out Component_Iterator;
+ Comp : out Component_Id)
+ is
+ begin
+ Component_Map.Next (Component_Map.Iterator (Iter), Comp);
+ end Next;
+
+ ----------
+ -- Next --
+ ----------
+
+ procedure Next
+ (Iter : in out Component_Vertex_Iterator;
+ V : out Vertex_Id)
+ is
+ begin
+ Vertex_List.Next (Vertex_List.Iterator (Iter), V);
+ end Next;
+
+ ----------
+ -- Next --
+ ----------
+
+ procedure Next
+ (Iter : in out Outgoing_Edge_Iterator;
+ E : out Edge_Id)
+ is
+ begin
+ Edge_Set.Next (Edge_Set.Iterator (Iter), E);
+ end Next;
+
+ ----------------------------------
+ -- Number_Of_Component_Vertices --
+ ----------------------------------
+
+ function Number_Of_Component_Vertices
+ (G : Directed_Graph;
+ Comp : Component_Id) return Natural
+ is
+ begin
+ Ensure_Created (G);
+ Ensure_Present (G, Comp);
+
+ return Vertex_List.Size (Get_Vertices (G, Comp));
+ end Number_Of_Component_Vertices;
+
+ --------------------------
+ -- Number_Of_Components --
+ --------------------------
+
+ function Number_Of_Components (G : Directed_Graph) return Natural is
+ begin
+ Ensure_Created (G);
+
+ return Component_Map.Size (G.Components);
+ end Number_Of_Components;
+
+ ---------------------
+ -- Number_Of_Edges --
+ ---------------------
+
+ function Number_Of_Edges (G : Directed_Graph) return Natural is
+ begin
+ Ensure_Created (G);
+
+ return Edge_Map.Size (G.All_Edges);
+ end Number_Of_Edges;
+
+ ------------------------------
+ -- Number_Of_Outgoing_Edges --
+ ------------------------------
+
+ function Number_Of_Outgoing_Edges
+ (G : Directed_Graph;
+ V : Vertex_Id) return Natural
+ is
+ begin
+ Ensure_Created (G);
+ Ensure_Present (G, V);
+
+ return Edge_Set.Size (Get_Outgoing_Edges (G, V));
+ end Number_Of_Outgoing_Edges;
+
+ ------------------------
+ -- Number_Of_Vertices --
+ ------------------------
+
+ function Number_Of_Vertices (G : Directed_Graph) return Natural is
+ begin
+ Ensure_Created (G);
+
+ return Vertex_Map.Size (G.All_Vertices);
+ end Number_Of_Vertices;
+
+ -------------
+ -- Present --
+ -------------
+
+ function Present (G : Directed_Graph) return Boolean is
+ begin
+ return G /= Nil;
+ end Present;
+
+ -------------------
+ -- Set_Component --
+ -------------------
+
+ procedure Set_Component
+ (G : Directed_Graph;
+ V : Vertex_Id;
+ Val : Component_Id)
+ is
+ VA : Vertex_Attributes;
+
+ begin
+ pragma Assert (Present (G));
+ pragma Assert (Contains_Vertex (G, V));
+
+ VA := Get_Vertex_Attributes (G, V);
+ VA.Component := Val;
+ Set_Vertex_Attributes (G, V, VA);
+ end Set_Component;
+
+ ------------------------
+ -- Set_Outgoing_Edges --
+ ------------------------
+
+ procedure Set_Outgoing_Edges
+ (G : Directed_Graph;
+ V : Vertex_Id;
+ Val : Edge_Set.Membership_Set)
+ is
+ VA : Vertex_Attributes;
+
+ begin
+ pragma Assert (Present (G));
+ pragma Assert (Contains_Vertex (G, V));
+
+ VA := Get_Vertex_Attributes (G, V);
+ VA.Outgoing_Edges := Val;
+ Set_Vertex_Attributes (G, V, VA);
+ end Set_Outgoing_Edges;
+
+ ---------------------------
+ -- Set_Vertex_Attributes --
+ ---------------------------
+
+ procedure Set_Vertex_Attributes
+ (G : Directed_Graph;
+ V : Vertex_Id;
+ Val : Vertex_Attributes)
+ is
+ begin
+ pragma Assert (Present (G));
+ pragma Assert (Contains_Vertex (G, V));
+
+ Vertex_Map.Put (G.All_Vertices, V, Val);
+ end Set_Vertex_Attributes;
+
+ -------------------
+ -- Source_Vertex --
+ -------------------
+
+ function Source_Vertex
+ (G : Directed_Graph;
+ E : Edge_Id) return Vertex_Id
+ is
+ begin
+ Ensure_Created (G);
+ Ensure_Present (G, E);
+
+ return Get_Edge_Attributes (G, E).Source;
+ end Source_Vertex;
+ end Directed_Graphs;
+
+ --------------------
+ -- Hash_Component --
+ --------------------
+
+ function Hash_Component (Comp : Component_Id) return Bucket_Range_Type is
+ begin
+ return Bucket_Range_Type (Comp);
+ end Hash_Component;
+
+ -------------
+ -- Present --
+ -------------
+
+ function Present (Comp : Component_Id) return Boolean is
+ begin
+ return Comp /= No_Component;
+ end Present;
+
+ -----------------------------
+ -- Sequence_Next_Component --
+ -----------------------------
+
+ Component_Sequencer : Component_Id := First_Component;
+ -- The counter for component handles. Do not directly manipulate its value
+ -- because this will destroy the invariant of the handles.
+
+ function Sequence_Next_Component return Component_Id is
+ Component : constant Component_Id := Component_Sequencer;
+
+ begin
+ Component_Sequencer := Component_Sequencer + 1;
+ return Component;
+ end Sequence_Next_Component;
+
+end GNAT.Graphs;
diff --git a/gcc/ada/libgnat/g-graphs.ads b/gcc/ada/libgnat/g-graphs.ads
new file mode 100644
index 0000000..3b65522
--- /dev/null
+++ b/gcc/ada/libgnat/g-graphs.ads
@@ -0,0 +1,536 @@
+------------------------------------------------------------------------------
+-- --
+-- GNAT RUN-TIME COMPONENTS --
+-- --
+-- G N A T . G R A P H S --
+-- --
+-- S p e c --
+-- --
+-- Copyright (C) 2018-2019, 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. --
+-- --
+------------------------------------------------------------------------------
+
+pragma Compiler_Unit_Warning;
+
+with GNAT.Dynamic_HTables; use GNAT.Dynamic_HTables;
+with GNAT.Lists; use GNAT.Lists;
+with GNAT.Sets; use GNAT.Sets;
+
+package GNAT.Graphs is
+
+ ---------------
+ -- Component --
+ ---------------
+
+ -- The following type denotes a strongly connected component handle
+ -- (referred to as simply "component") in a graph.
+
+ type Component_Id is new Natural;
+ No_Component : constant Component_Id := Component_Id'First;
+
+ function Hash_Component (Comp : Component_Id) return Bucket_Range_Type;
+ -- Map component Comp into the range of buckets
+
+ function Present (Comp : Component_Id) return Boolean;
+ -- Determine whether component Comp exists
+
+ ---------------------
+ -- Directed_Graphs --
+ ---------------------
+
+ -- The following package offers a directed graph abstraction with the
+ -- following characteristics:
+ --
+ -- * Dynamic resizing based on number of vertices and edges
+ -- * Creation of multiple instances, of different sizes
+ -- * Discovery of strongly connected components
+ -- * Iterable attributes
+ --
+ -- The following use pattern must be employed when operating this graph:
+ --
+ -- Graph : Directed_Graph := Create (<some size>, <some size>);
+ --
+ -- <various operations>
+ --
+ -- Destroy (Graph);
+ --
+ -- The destruction of the graph reclaims all storage occupied by it.
+
+ generic
+
+ --------------
+ -- Vertices --
+ --------------
+
+ type Vertex_Id is private;
+ -- The handle of a vertex
+
+ No_Vertex : Vertex_Id;
+ -- An indicator for a nonexistent vertex
+
+ with function Hash_Vertex (V : Vertex_Id) return Bucket_Range_Type;
+ -- Map vertex V into the range of buckets
+
+ with function Same_Vertex
+ (Left : Vertex_Id;
+ Right : Vertex_Id) return Boolean;
+ -- Compare vertex Left to vertex Right for identity
+
+ -----------
+ -- Edges --
+ -----------
+
+ type Edge_Id is private;
+ -- The handle of an edge
+
+ No_Edge : Edge_Id;
+ -- An indicator for a nonexistent edge
+
+ with function Hash_Edge (E : Edge_Id) return Bucket_Range_Type;
+ -- Map edge E into the range of buckets
+
+ with function Same_Edge
+ (Left : Edge_Id;
+ Right : Edge_Id) return Boolean;
+ -- Compare edge Left to edge Right for identity
+
+ package Directed_Graphs is
+
+ -- The following exceptions are raised when an attempt is made to add
+ -- the same edge or vertex in a graph.
+
+ Duplicate_Edge : exception;
+ Duplicate_Vertex : exception;
+
+ -- The following exceptions are raised when an attempt is made to delete
+ -- or reference a nonexistent component, edge, or vertex in a graph.
+
+ Missing_Component : exception;
+ Missing_Edge : exception;
+ Missing_Vertex : exception;
+
+ ----------------------
+ -- Graph operations --
+ ----------------------
+
+ -- The following type denotes a graph handle. Each instance must be
+ -- created using routine Create.
+
+ type Directed_Graph is private;
+ Nil : constant Directed_Graph;
+
+ procedure Add_Edge
+ (G : Directed_Graph;
+ E : Edge_Id;
+ Source : Vertex_Id;
+ Destination : Vertex_Id);
+ -- Add edge E to graph G which links vertex source Source and desination
+ -- vertex Destination. The edge is "owned" by vertex Source. This action
+ -- raises the following exceptions:
+ --
+ -- * Duplicate_Edge, when the edge is already present in the graph
+ --
+ -- * Iterated, when the graph has an outstanding edge iterator
+ --
+ -- * Missing_Vertex, when either the source or desination are not
+ -- present in the graph.
+
+ procedure Add_Vertex
+ (G : Directed_Graph;
+ V : Vertex_Id);
+ -- Add vertex V to graph G. This action raises the following exceptions:
+ --
+ -- * Duplicate_Vertex, when the vertex is already present in the graph
+ --
+ -- * Iterated, when the graph has an outstanding vertex iterator
+
+ function Component
+ (G : Directed_Graph;
+ V : Vertex_Id) return Component_Id;
+ -- Obtain the component where vertex V of graph G resides. This action
+ -- raises the following exceptions:
+ --
+ -- * Missing_Vertex, when the vertex is not present in the graph
+
+ function Contains_Component
+ (G : Directed_Graph;
+ Comp : Component_Id) return Boolean;
+ -- Determine whether graph G contains component Comp
+
+ function Contains_Edge
+ (G : Directed_Graph;
+ E : Edge_Id) return Boolean;
+ -- Determine whether graph G contains edge E
+
+ function Contains_Vertex
+ (G : Directed_Graph;
+ V : Vertex_Id) return Boolean;
+ -- Determine whether graph G contains vertex V
+
+ function Create
+ (Initial_Vertices : Positive;
+ Initial_Edges : Positive) return Directed_Graph;
+ -- Create a new graph with vertex capacity Initial_Vertices and edge
+ -- capacity Initial_Edges. This routine must be called at the start of
+ -- a graph's lifetime.
+
+ procedure Delete_Edge
+ (G : Directed_Graph;
+ E : Edge_Id);
+ -- Delete edge E from graph G. This action raises these exceptions:
+ --
+ -- * Iterated, when the graph has an outstanding edge iterator
+ --
+ -- * Missing_Edge, when the edge is not present in the graph
+ --
+ -- * Missing_Vertex, when the source vertex that "owns" the edge is
+ -- not present in the graph.
+
+ function Destination_Vertex
+ (G : Directed_Graph;
+ E : Edge_Id) return Vertex_Id;
+ -- Obtain the destination vertex of edge E of graph G. This action
+ -- raises the following exceptions:
+ --
+ -- * Missing_Edge, when the edge is not present in the graph
+
+ procedure Destroy (G : in out Directed_Graph);
+ -- Destroy the contents of graph G, rendering it unusable. This routine
+ -- must be called at the end of a graph's lifetime. This action raises
+ -- the following exceptions:
+ --
+ -- * Iterated, if the graph has any outstanding iterator
+
+ procedure Find_Components (G : Directed_Graph);
+ -- Find all components of graph G. This action raises the following
+ -- exceptions:
+ --
+ -- * Iterated, when the components or vertices of the graph have an
+ -- outstanding iterator.
+
+ function Is_Empty (G : Directed_Graph) return Boolean;
+ -- Determine whether graph G is empty
+
+ function Number_Of_Component_Vertices
+ (G : Directed_Graph;
+ Comp : Component_Id) return Natural;
+ -- Obtain the total number of vertices of component Comp of graph G
+
+ function Number_Of_Components (G : Directed_Graph) return Natural;
+ -- Obtain the total number of components of graph G
+
+ function Number_Of_Edges (G : Directed_Graph) return Natural;
+ -- Obtain the total number of edges of graph G
+
+ function Number_Of_Outgoing_Edges
+ (G : Directed_Graph;
+ V : Vertex_Id) return Natural;
+ -- Obtain the total number of outgoing edges of vertex V of graph G
+
+ function Number_Of_Vertices (G : Directed_Graph) return Natural;
+ -- Obtain the total number of vertices of graph G
+
+ function Present (G : Directed_Graph) return Boolean;
+ -- Determine whether graph G exists
+
+ function Source_Vertex
+ (G : Directed_Graph;
+ E : Edge_Id) return Vertex_Id;
+ -- Obtain the source vertex that "owns" edge E of graph G. This action
+ -- raises the following exceptions:
+ --
+ -- * Missing_Edge, when the edge is not present in the graph
+
+ -------------------------
+ -- Iterator operations --
+ -------------------------
+
+ -- The following types represent iterators over various attributes of a
+ -- graph. Each iterator locks all mutation operations of its associated
+ -- attribute, and unlocks them once it is exhausted. The iterators must
+ -- be used with the following pattern:
+ --
+ -- Iter : Iterate_XXX (Graph);
+ -- while Has_Next (Iter) loop
+ -- Next (Iter, Element);
+ -- end loop;
+ --
+ -- It is possible to advance the iterators by using Next only, however
+ -- this risks raising Iterator_Exhausted.
+
+ -- The following type represents an iterator over all edges of a graph
+
+ type All_Edge_Iterator is private;
+
+ function Has_Next (Iter : All_Edge_Iterator) return Boolean;
+ -- Determine whether iterator Iter has more edges to examine
+
+ function Iterate_All_Edges (G : Directed_Graph) return All_Edge_Iterator;
+ -- Obtain an iterator over all edges of graph G
+
+ procedure Next
+ (Iter : in out All_Edge_Iterator;
+ E : out Edge_Id);
+ -- Return the current edge referenced by iterator Iter and advance to
+ -- the next available edge. This action raises the following exceptions:
+ --
+ -- * Iterator_Exhausted, when the iterator has been exhausted and
+ -- further attempts are made to advance it.
+
+ -- The following type represents an iterator over all vertices of a
+ -- graph.
+
+ type All_Vertex_Iterator is private;
+
+ function Has_Next (Iter : All_Vertex_Iterator) return Boolean;
+ -- Determine whether iterator Iter has more vertices to examine
+
+ function Iterate_All_Vertices
+ (G : Directed_Graph) return All_Vertex_Iterator;
+ -- Obtain an iterator over all vertices of graph G
+
+ procedure Next
+ (Iter : in out All_Vertex_Iterator;
+ V : out Vertex_Id);
+ -- Return the current vertex referenced by iterator Iter and advance
+ -- to the next available vertex. This action raises the following
+ -- exceptions:
+ --
+ -- * Iterator_Exhausted, when the iterator has been exhausted and
+ -- further attempts are made to advance it.
+
+ -- The following type represents an iterator over all components of a
+ -- graph.
+
+ type Component_Iterator is private;
+
+ function Has_Next (Iter : Component_Iterator) return Boolean;
+ -- Determine whether iterator Iter has more components to examine
+
+ function Iterate_Components
+ (G : Directed_Graph) return Component_Iterator;
+ -- Obtain an iterator over all components of graph G
+
+ procedure Next
+ (Iter : in out Component_Iterator;
+ Comp : out Component_Id);
+ -- Return the current component referenced by iterator Iter and advance
+ -- to the next component. This action raises the following exceptions:
+ --
+ -- * Iterator_Exhausted, when the iterator has been exhausted and
+ -- further attempts are made to advance it.
+
+ -- The following type prepresents an iterator over all vertices of a
+ -- component.
+
+ type Component_Vertex_Iterator is private;
+
+ function Has_Next (Iter : Component_Vertex_Iterator) return Boolean;
+ -- Determine whether iterator Iter has more vertices to examine
+
+ function Iterate_Component_Vertices
+ (G : Directed_Graph;
+ Comp : Component_Id) return Component_Vertex_Iterator;
+ -- Obtain an iterator over all vertices that comprise component Comp of
+ -- graph G.
+
+ procedure Next
+ (Iter : in out Component_Vertex_Iterator;
+ V : out Vertex_Id);
+ -- Return the current vertex referenced by iterator Iter and advance to
+ -- the next vertex. This action raises the following exceptions:
+ --
+ -- * Iterator_Exhausted, when the iterator has been exhausted and
+ -- further attempts are made to advance it.
+
+ -- The following type represents an iterator over all outgoing edges of
+ -- a vertex.
+
+ type Outgoing_Edge_Iterator is private;
+
+ function Has_Next (Iter : Outgoing_Edge_Iterator) return Boolean;
+ -- Determine whether iterator Iter has more outgoing edges to examine
+
+ function Iterate_Outgoing_Edges
+ (G : Directed_Graph;
+ V : Vertex_Id) return Outgoing_Edge_Iterator;
+ -- Obtain an iterator over all the outgoing edges "owned" by vertex V of
+ -- graph G.
+
+ procedure Next
+ (Iter : in out Outgoing_Edge_Iterator;
+ E : out Edge_Id);
+ -- Return the current outgoing edge referenced by iterator Iter and
+ -- advance to the next available outgoing edge. This action raises the
+ -- following exceptions:
+ --
+ -- * Iterator_Exhausted, when the iterator has been exhausted and
+ -- further attempts are made to advance it.
+
+ private
+ pragma Unreferenced (No_Edge);
+
+ --------------
+ -- Edge_Map --
+ --------------
+
+ type Edge_Attributes is record
+ Destination : Vertex_Id := No_Vertex;
+ -- The target of a directed edge
+
+ Source : Vertex_Id := No_Vertex;
+ -- The origin of a directed edge. The source vertex "owns" the edge.
+ end record;
+
+ No_Edge_Attributes : constant Edge_Attributes :=
+ (Destination => No_Vertex,
+ Source => No_Vertex);
+
+ procedure Destroy_Edge_Attributes (Attrs : in out Edge_Attributes);
+ -- Destroy the contents of attributes Attrs
+
+ package Edge_Map is new Dynamic_Hash_Tables
+ (Key_Type => Edge_Id,
+ Value_Type => Edge_Attributes,
+ No_Value => No_Edge_Attributes,
+ Expansion_Threshold => 1.5,
+ Expansion_Factor => 2,
+ Compression_Threshold => 0.3,
+ Compression_Factor => 2,
+ "=" => Same_Edge,
+ Destroy_Value => Destroy_Edge_Attributes,
+ Hash => Hash_Edge);
+
+ --------------
+ -- Edge_Set --
+ --------------
+
+ package Edge_Set is new Membership_Sets
+ (Element_Type => Edge_Id,
+ "=" => "=",
+ Hash => Hash_Edge);
+
+ -----------------
+ -- Vertex_List --
+ -----------------
+
+ procedure Destroy_Vertex (V : in out Vertex_Id);
+ -- Destroy the contents of a vertex
+
+ package Vertex_List is new Doubly_Linked_Lists
+ (Element_Type => Vertex_Id,
+ "=" => Same_Vertex,
+ Destroy_Element => Destroy_Vertex);
+
+ ----------------
+ -- Vertex_Map --
+ ----------------
+
+ type Vertex_Attributes is record
+ Component : Component_Id := No_Component;
+ -- The component where a vertex lives
+
+ Outgoing_Edges : Edge_Set.Membership_Set := Edge_Set.Nil;
+ -- The set of edges that extend out from a vertex
+ end record;
+
+ No_Vertex_Attributes : constant Vertex_Attributes :=
+ (Component => No_Component,
+ Outgoing_Edges => Edge_Set.Nil);
+
+ procedure Destroy_Vertex_Attributes (Attrs : in out Vertex_Attributes);
+ -- Destroy the contents of attributes Attrs
+
+ package Vertex_Map is new Dynamic_Hash_Tables
+ (Key_Type => Vertex_Id,
+ Value_Type => Vertex_Attributes,
+ No_Value => No_Vertex_Attributes,
+ Expansion_Threshold => 1.5,
+ Expansion_Factor => 2,
+ Compression_Threshold => 0.3,
+ Compression_Factor => 2,
+ "=" => Same_Vertex,
+ Destroy_Value => Destroy_Vertex_Attributes,
+ Hash => Hash_Vertex);
+
+ -------------------
+ -- Component_Map --
+ -------------------
+
+ type Component_Attributes is record
+ Vertices : Vertex_List.Doubly_Linked_List := Vertex_List.Nil;
+ end record;
+
+ No_Component_Attributes : constant Component_Attributes :=
+ (Vertices => Vertex_List.Nil);
+
+ procedure Destroy_Component_Attributes
+ (Attrs : in out Component_Attributes);
+ -- Destroy the contents of attributes Attrs
+
+ package Component_Map is new Dynamic_Hash_Tables
+ (Key_Type => Component_Id,
+ Value_Type => Component_Attributes,
+ No_Value => No_Component_Attributes,
+ Expansion_Threshold => 1.5,
+ Expansion_Factor => 2,
+ Compression_Threshold => 0.3,
+ Compression_Factor => 2,
+ "=" => "=",
+ Destroy_Value => Destroy_Component_Attributes,
+ Hash => Hash_Component);
+
+ -----------
+ -- Graph --
+ -----------
+
+ type Directed_Graph_Attributes is record
+ All_Edges : Edge_Map.Dynamic_Hash_Table := Edge_Map.Nil;
+ -- The map of edge -> edge attributes for all edges in the graph
+
+ All_Vertices : Vertex_Map.Dynamic_Hash_Table := Vertex_Map.Nil;
+ -- The map of vertex -> vertex attributes for all vertices in the
+ -- graph.
+
+ Components : Component_Map.Dynamic_Hash_Table := Component_Map.Nil;
+ -- The map of component -> component attributes for all components
+ -- in the graph.
+ end record;
+
+ type Directed_Graph is access Directed_Graph_Attributes;
+ Nil : constant Directed_Graph := null;
+
+ ---------------
+ -- Iterators --
+ ---------------
+
+ type All_Edge_Iterator is new Edge_Map.Iterator;
+ type All_Vertex_Iterator is new Vertex_Map.Iterator;
+ type Component_Iterator is new Component_Map.Iterator;
+ type Component_Vertex_Iterator is new Vertex_List.Iterator;
+ type Outgoing_Edge_Iterator is new Edge_Set.Iterator;
+ end Directed_Graphs;
+
+private
+ First_Component : constant Component_Id := No_Component + 1;
+
+end GNAT.Graphs;
diff --git a/gcc/ada/libgnat/g-lists.adb b/gcc/ada/libgnat/g-lists.adb
index 7cf7aa6..f7447a5 100644
--- a/gcc/ada/libgnat/g-lists.adb
+++ b/gcc/ada/libgnat/g-lists.adb
@@ -33,8 +33,10 @@ with Ada.Unchecked_Deallocation;
package body GNAT.Lists is
- package body Doubly_Linked_List is
- procedure Delete_Node (L : Instance; Nod : Node_Ptr);
+ package body Doubly_Linked_Lists is
+ procedure Delete_Node
+ (L : Doubly_Linked_List;
+ Nod : Node_Ptr);
pragma Inline (Delete_Node);
-- Detach and delete node Nod from list L
@@ -42,17 +44,17 @@ package body GNAT.Lists is
pragma Inline (Ensure_Circular);
-- Ensure that dummy head Head is circular with respect to itself
- procedure Ensure_Created (L : Instance);
+ procedure Ensure_Created (L : Doubly_Linked_List);
pragma Inline (Ensure_Created);
-- Verify that list L is created. Raise Not_Created if this is not the
-- case.
- procedure Ensure_Full (L : Instance);
+ procedure Ensure_Full (L : Doubly_Linked_List);
pragma Inline (Ensure_Full);
-- Verify that list L contains at least one element. Raise List_Empty if
-- this is not the case.
- procedure Ensure_Unlocked (L : Instance);
+ procedure Ensure_Unlocked (L : Doubly_Linked_List);
pragma Inline (Ensure_Unlocked);
-- Verify that list L is unlocked. Raise Iterated if this is not the
-- case.
@@ -65,12 +67,14 @@ package body GNAT.Lists is
-- exists a node with element Elem. If such a node exists, return it,
-- otherwise return null;
- procedure Free is new Ada.Unchecked_Deallocation (Linked_List, Instance);
+ procedure Free is
+ new Ada.Unchecked_Deallocation
+ (Doubly_Linked_List_Attributes, Doubly_Linked_List);
procedure Free is new Ada.Unchecked_Deallocation (Node, Node_Ptr);
procedure Insert_Between
- (L : Instance;
+ (L : Doubly_Linked_List;
Elem : Element_Type;
Left : Node_Ptr;
Right : Node_Ptr);
@@ -81,16 +85,22 @@ package body GNAT.Lists is
pragma Inline (Is_Valid);
-- Determine whether iterator Iter refers to a valid element
- function Is_Valid (Nod : Node_Ptr; Head : Node_Ptr) return Boolean;
+ function Is_Valid
+ (Nod : Node_Ptr;
+ Head : Node_Ptr) return Boolean;
pragma Inline (Is_Valid);
-- Determine whether node Nod is non-null and does not refer to dummy
-- head Head, thus making it valid.
- procedure Lock (L : Instance);
+ procedure Lock (L : Doubly_Linked_List);
pragma Inline (Lock);
-- Lock all mutation functionality of list L
- procedure Unlock (L : Instance);
+ function Present (Nod : Node_Ptr) return Boolean;
+ pragma Inline (Present);
+ -- Determine whether node Nod exists
+
+ procedure Unlock (L : Doubly_Linked_List);
pragma Inline (Unlock);
-- Unlock all mutation functionality of list L
@@ -98,7 +108,10 @@ package body GNAT.Lists is
-- Append --
------------
- procedure Append (L : Instance; Elem : Element_Type) is
+ procedure Append
+ (L : Doubly_Linked_List;
+ Elem : Element_Type)
+ is
Head : Node_Ptr;
begin
@@ -125,16 +138,19 @@ package body GNAT.Lists is
-- Create --
------------
- function Create return Instance is
+ function Create return Doubly_Linked_List is
begin
- return new Linked_List;
+ return new Doubly_Linked_List_Attributes;
end Create;
--------------
-- Contains --
--------------
- function Contains (L : Instance; Elem : Element_Type) return Boolean is
+ function Contains
+ (L : Doubly_Linked_List;
+ Elem : Element_Type) return Boolean
+ is
Head : Node_Ptr;
Nod : Node_Ptr;
@@ -151,7 +167,10 @@ package body GNAT.Lists is
-- Delete --
------------
- procedure Delete (L : Instance; Elem : Element_Type) is
+ procedure Delete
+ (L : Doubly_Linked_List;
+ Elem : Element_Type)
+ is
Head : Node_Ptr;
Nod : Node_Ptr;
@@ -172,7 +191,7 @@ package body GNAT.Lists is
-- Delete_First --
------------------
- procedure Delete_First (L : Instance) is
+ procedure Delete_First (L : Doubly_Linked_List) is
Head : Node_Ptr;
Nod : Node_Ptr;
@@ -193,7 +212,7 @@ package body GNAT.Lists is
-- Delete_Last --
-----------------
- procedure Delete_Last (L : Instance) is
+ procedure Delete_Last (L : Doubly_Linked_List) is
Head : Node_Ptr;
Nod : Node_Ptr;
@@ -214,18 +233,21 @@ package body GNAT.Lists is
-- Delete_Node --
-----------------
- procedure Delete_Node (L : Instance; Nod : Node_Ptr) is
+ procedure Delete_Node
+ (L : Doubly_Linked_List;
+ Nod : Node_Ptr)
+ is
Ref : Node_Ptr := Nod;
- pragma Assert (Ref /= null);
+ pragma Assert (Present (Ref));
Next : constant Node_Ptr := Ref.Next;
Prev : constant Node_Ptr := Ref.Prev;
begin
- pragma Assert (L /= null);
- pragma Assert (Next /= null);
- pragma Assert (Prev /= null);
+ pragma Assert (Present (L));
+ pragma Assert (Present (Next));
+ pragma Assert (Present (Prev));
Prev.Next := Next; -- Prev ---> Next
Next.Prev := Prev; -- Prev <--> Next
@@ -235,6 +257,10 @@ package body GNAT.Lists is
L.Elements := L.Elements - 1;
+ -- Invoke the element destructor before deallocating the node
+
+ Destroy_Element (Nod.Elem);
+
Free (Ref);
end Delete_Node;
@@ -242,7 +268,7 @@ package body GNAT.Lists is
-- Destroy --
-------------
- procedure Destroy (L : in out Instance) is
+ procedure Destroy (L : in out Doubly_Linked_List) is
Head : Node_Ptr;
begin
@@ -263,10 +289,10 @@ package body GNAT.Lists is
---------------------
procedure Ensure_Circular (Head : Node_Ptr) is
- pragma Assert (Head /= null);
+ pragma Assert (Present (Head));
begin
- if Head.Next = null and then Head.Prev = null then
+ if not Present (Head.Next) and then not Present (Head.Prev) then
Head.Next := Head;
Head.Prev := Head;
end if;
@@ -276,9 +302,9 @@ package body GNAT.Lists is
-- Ensure_Created --
--------------------
- procedure Ensure_Created (L : Instance) is
+ procedure Ensure_Created (L : Doubly_Linked_List) is
begin
- if L = null then
+ if not Present (L) then
raise Not_Created;
end if;
end Ensure_Created;
@@ -287,9 +313,9 @@ package body GNAT.Lists is
-- Ensure_Full --
-----------------
- procedure Ensure_Full (L : Instance) is
+ procedure Ensure_Full (L : Doubly_Linked_List) is
begin
- pragma Assert (L /= null);
+ pragma Assert (Present (L));
if L.Elements = 0 then
raise List_Empty;
@@ -300,9 +326,9 @@ package body GNAT.Lists is
-- Ensure_Unlocked --
---------------------
- procedure Ensure_Unlocked (L : Instance) is
+ procedure Ensure_Unlocked (L : Doubly_Linked_List) is
begin
- pragma Assert (L /= null);
+ pragma Assert (Present (L));
-- The list has at least one outstanding iterator
@@ -319,7 +345,7 @@ package body GNAT.Lists is
(Head : Node_Ptr;
Elem : Element_Type) return Node_Ptr
is
- pragma Assert (Head /= null);
+ pragma Assert (Present (Head));
Nod : Node_Ptr;
@@ -342,7 +368,7 @@ package body GNAT.Lists is
-- First --
-----------
- function First (L : Instance) return Element_Type is
+ function First (L : Doubly_Linked_List) return Element_Type is
begin
Ensure_Created (L);
Ensure_Full (L);
@@ -374,7 +400,7 @@ package body GNAT.Lists is
------------------
procedure Insert_After
- (L : Instance;
+ (L : Doubly_Linked_List;
After : Element_Type;
Elem : Element_Type)
is
@@ -402,7 +428,7 @@ package body GNAT.Lists is
-------------------
procedure Insert_Before
- (L : Instance;
+ (L : Doubly_Linked_List;
Before : Element_Type;
Elem : Element_Type)
is
@@ -430,14 +456,14 @@ package body GNAT.Lists is
--------------------
procedure Insert_Between
- (L : Instance;
+ (L : Doubly_Linked_List;
Elem : Element_Type;
Left : Node_Ptr;
Right : Node_Ptr)
is
- pragma Assert (L /= null);
- pragma Assert (Left /= null);
- pragma Assert (Right /= null);
+ pragma Assert (Present (L));
+ pragma Assert (Present (Left));
+ pragma Assert (Present (Right));
Nod : constant Node_Ptr :=
new Node'(Elem => Elem,
@@ -455,7 +481,7 @@ package body GNAT.Lists is
-- Is_Empty --
--------------
- function Is_Empty (L : Instance) return Boolean is
+ function Is_Empty (L : Doubly_Linked_List) return Boolean is
begin
Ensure_Created (L);
@@ -471,26 +497,29 @@ package body GNAT.Lists is
-- The invariant of Iterate and Next ensures that the iterator always
-- refers to a valid node if there exists one.
- return Is_Valid (Iter.Nod, Iter.List.Nodes'Access);
+ return Is_Valid (Iter.Curr_Nod, Iter.List.Nodes'Access);
end Is_Valid;
--------------
-- Is_Valid --
--------------
- function Is_Valid (Nod : Node_Ptr; Head : Node_Ptr) return Boolean is
+ function Is_Valid
+ (Nod : Node_Ptr;
+ Head : Node_Ptr) return Boolean
+ is
begin
-- A node is valid if it is non-null, and does not refer to the dummy
-- head of some list.
- return Nod /= null and then Nod /= Head;
+ return Present (Nod) and then Nod /= Head;
end Is_Valid;
-------------
-- Iterate --
-------------
- function Iterate (L : Instance) return Iterator is
+ function Iterate (L : Doubly_Linked_List) return Iterator is
begin
Ensure_Created (L);
@@ -499,14 +528,14 @@ package body GNAT.Lists is
Lock (L);
- return (List => L, Nod => L.Nodes.Next);
+ return (List => L, Curr_Nod => L.Nodes.Next);
end Iterate;
----------
-- Last --
----------
- function Last (L : Instance) return Element_Type is
+ function Last (L : Doubly_Linked_List) return Element_Type is
begin
Ensure_Created (L);
Ensure_Full (L);
@@ -518,9 +547,9 @@ package body GNAT.Lists is
-- Lock --
----------
- procedure Lock (L : Instance) is
+ procedure Lock (L : Doubly_Linked_List) is
begin
- pragma Assert (L /= null);
+ pragma Assert (Present (L));
-- The list may be locked multiple times if multiple iterators are
-- operating over it.
@@ -532,9 +561,12 @@ package body GNAT.Lists is
-- Next --
----------
- procedure Next (Iter : in out Iterator; Elem : out Element_Type) is
+ procedure Next
+ (Iter : in out Iterator;
+ Elem : out Element_Type)
+ is
Is_OK : constant Boolean := Is_Valid (Iter);
- Saved : constant Node_Ptr := Iter.Nod;
+ Saved : constant Node_Ptr := Iter.Curr_Nod;
begin
-- The iterator is no linger valid which indicates that it has been
@@ -548,15 +580,19 @@ package body GNAT.Lists is
-- Advance to the next node along the list
- Iter.Nod := Iter.Nod.Next;
- Elem := Saved.Elem;
+ Iter.Curr_Nod := Iter.Curr_Nod.Next;
+
+ Elem := Saved.Elem;
end Next;
-------------
-- Prepend --
-------------
- procedure Prepend (L : Instance; Elem : Element_Type) is
+ procedure Prepend
+ (L : Doubly_Linked_List;
+ Elem : Element_Type)
+ is
Head : Node_Ptr;
begin
@@ -580,11 +616,29 @@ package body GNAT.Lists is
end Prepend;
-------------
+ -- Present --
+ -------------
+
+ function Present (L : Doubly_Linked_List) return Boolean is
+ begin
+ return L /= Nil;
+ end Present;
+
+ -------------
+ -- Present --
+ -------------
+
+ function Present (Nod : Node_Ptr) return Boolean is
+ begin
+ return Nod /= null;
+ end Present;
+
+ -------------
-- Replace --
-------------
procedure Replace
- (L : Instance;
+ (L : Doubly_Linked_List;
Old_Elem : Element_Type;
New_Elem : Element_Type)
is
@@ -607,7 +661,7 @@ package body GNAT.Lists is
-- Size --
----------
- function Size (L : Instance) return Natural is
+ function Size (L : Doubly_Linked_List) return Natural is
begin
Ensure_Created (L);
@@ -618,15 +672,15 @@ package body GNAT.Lists is
-- Unlock --
------------
- procedure Unlock (L : Instance) is
+ procedure Unlock (L : Doubly_Linked_List) is
begin
- pragma Assert (L /= null);
+ pragma Assert (Present (L));
-- The list may be locked multiple times if multiple iterators are
-- operating over it.
L.Iterators := L.Iterators - 1;
end Unlock;
- end Doubly_Linked_List;
+ end Doubly_Linked_Lists;
end GNAT.Lists;
diff --git a/gcc/ada/libgnat/g-lists.ads b/gcc/ada/libgnat/g-lists.ads
index 75dfeb5..b64ef08 100644
--- a/gcc/ada/libgnat/g-lists.ads
+++ b/gcc/ada/libgnat/g-lists.ads
@@ -40,12 +40,12 @@ package GNAT.Lists is
-- The following package offers a doubly linked list abstraction with the
-- following characteristics:
--
- -- * Creation of multiple instances, of different sizes.
- -- * Iterable elements.
+ -- * Creation of multiple instances, of different sizes
+ -- * Iterable elements
--
-- The following use pattern must be employed with this list:
--
- -- List : Instance := Create;
+ -- List : Doubly_Linked_List := Create;
--
-- <various operations>
--
@@ -60,60 +60,69 @@ package GNAT.Lists is
(Left : Element_Type;
Right : Element_Type) return Boolean;
- package Doubly_Linked_List is
+ with procedure Destroy_Element (Elem : in out Element_Type);
+ -- Element destructor
+
+ package Doubly_Linked_Lists is
---------------------
-- List operations --
---------------------
- type Instance is private;
- Nil : constant Instance;
+ type Doubly_Linked_List is private;
+ Nil : constant Doubly_Linked_List;
-- The following exception is raised when the list is empty, and an
-- attempt is made to delete an element from it.
List_Empty : exception;
- procedure Append (L : Instance; Elem : Element_Type);
+ procedure Append
+ (L : Doubly_Linked_List;
+ Elem : Element_Type);
-- Insert element Elem at the end of list L. This action will raise
-- Iterated if the list has outstanding iterators.
- function Contains (L : Instance; Elem : Element_Type) return Boolean;
+ function Contains
+ (L : Doubly_Linked_List;
+ Elem : Element_Type) return Boolean;
-- Determine whether list L contains element Elem
- function Create return Instance;
+ function Create return Doubly_Linked_List;
-- Create a new list
- procedure Delete (L : Instance; Elem : Element_Type);
+ procedure Delete
+ (L : Doubly_Linked_List;
+ Elem : Element_Type);
-- Delete element Elem from list L. The routine has no effect if Elem is
-- not present. This action will raise
--
-- * List_Empty if the list is empty.
-- * Iterated if the list has outstanding iterators.
- procedure Delete_First (L : Instance);
+ procedure Delete_First (L : Doubly_Linked_List);
-- Delete an element from the start of list L. This action will raise
--
-- * List_Empty if the list is empty.
-- * Iterated if the list has outstanding iterators.
- procedure Delete_Last (L : Instance);
+ procedure Delete_Last (L : Doubly_Linked_List);
-- Delete an element from the end of list L. This action will raise
--
-- * List_Empty if the list is empty.
-- * Iterated if the list has outstanding iterators.
- procedure Destroy (L : in out Instance);
+ procedure Destroy (L : in out Doubly_Linked_List);
-- Destroy the contents of list L. This routine must be called at the
-- end of a list's lifetime. This action will raise Iterated if the
-- list has outstanding iterators.
- function First (L : Instance) return Element_Type;
+ function First (L : Doubly_Linked_List) return Element_Type;
-- Obtain an element from the start of list L. This action will raise
-- List_Empty if the list is empty.
procedure Insert_After
- (L : Instance;
+ (L : Doubly_Linked_List;
After : Element_Type;
Elem : Element_Type);
-- Insert new element Elem after element After in list L. The routine
@@ -121,33 +130,38 @@ package GNAT.Lists is
-- Iterated if the list has outstanding iterators.
procedure Insert_Before
- (L : Instance;
+ (L : Doubly_Linked_List;
Before : Element_Type;
Elem : Element_Type);
-- Insert new element Elem before element Before in list L. The routine
-- has no effect if After is not present. This action will raise
-- Iterated if the list has outstanding iterators.
- function Is_Empty (L : Instance) return Boolean;
+ function Is_Empty (L : Doubly_Linked_List) return Boolean;
-- Determine whether list L is empty
- function Last (L : Instance) return Element_Type;
+ function Last (L : Doubly_Linked_List) return Element_Type;
-- Obtain an element from the end of list L. This action will raise
-- List_Empty if the list is empty.
- procedure Prepend (L : Instance; Elem : Element_Type);
+ procedure Prepend
+ (L : Doubly_Linked_List;
+ Elem : Element_Type);
-- Insert element Elem at the start of list L. This action will raise
-- Iterated if the list has outstanding iterators.
+ function Present (L : Doubly_Linked_List) return Boolean;
+ -- Determine whether list L exists
+
procedure Replace
- (L : Instance;
+ (L : Doubly_Linked_List;
Old_Elem : Element_Type;
New_Elem : Element_Type);
-- Replace old element Old_Elem with new element New_Elem in list L. The
-- routine has no effect if Old_Elem is not present. This action will
-- raise Iterated if the list has outstanding iterators.
- function Size (L : Instance) return Natural;
+ function Size (L : Doubly_Linked_List) return Natural;
-- Obtain the number of elements in list L
-------------------------
@@ -168,16 +182,18 @@ package GNAT.Lists is
type Iterator is private;
- function Iterate (L : Instance) return Iterator;
- -- Obtain an iterator over the elements of list L. This action locks all
- -- mutation functionality of the associated list.
-
function Has_Next (Iter : Iterator) return Boolean;
-- Determine whether iterator Iter has more elements to examine. If the
-- iterator has been exhausted, restore all mutation functionality of
-- the associated list.
- procedure Next (Iter : in out Iterator; Elem : out Element_Type);
+ function Iterate (L : Doubly_Linked_List) return Iterator;
+ -- Obtain an iterator over the elements of list L. This action locks all
+ -- mutation functionality of the associated list.
+
+ procedure Next
+ (Iter : in out Iterator;
+ Elem : out Element_Type);
-- Return the current element referenced by iterator Iter and advance
-- to the next available element. If the iterator has been exhausted
-- and further attempts are made to advance it, this routine restores
@@ -198,7 +214,7 @@ package GNAT.Lists is
-- The following type represents a list
- type Linked_List is record
+ type Doubly_Linked_List_Attributes is record
Elements : Natural := 0;
-- The number of elements in the list
@@ -209,20 +225,20 @@ package GNAT.Lists is
-- The dummy head of the list
end record;
- type Instance is access all Linked_List;
- Nil : constant Instance := null;
+ type Doubly_Linked_List is access all Doubly_Linked_List_Attributes;
+ Nil : constant Doubly_Linked_List := null;
-- The following type represents an element iterator
type Iterator is record
- List : Instance := null;
- -- Reference to the associated list
-
- Nod : Node_Ptr := null;
+ Curr_Nod : Node_Ptr := null;
-- Reference to the current node being examined. The invariant of the
-- iterator requires that this field always points to a valid node. A
-- value of null indicates that the iterator is exhausted.
+
+ List : Doubly_Linked_List := null;
+ -- Reference to the associated list
end record;
- end Doubly_Linked_List;
+ end Doubly_Linked_Lists;
end GNAT.Lists;
diff --git a/gcc/ada/libgnat/g-sets.adb b/gcc/ada/libgnat/g-sets.adb
index bd367cb..b588880 100644
--- a/gcc/ada/libgnat/g-sets.adb
+++ b/gcc/ada/libgnat/g-sets.adb
@@ -31,46 +31,59 @@
package body GNAT.Sets is
- --------------------
- -- Membership_Set --
- --------------------
+ ---------------------
+ -- Membership_Sets --
+ ---------------------
- package body Membership_Set is
+ package body Membership_Sets is
--------------
-- Contains --
--------------
- function Contains (S : Instance; Elem : Element_Type) return Boolean is
+ function Contains
+ (S : Membership_Set;
+ Elem : Element_Type) return Boolean
+ is
begin
- return Hashed_Set.Get (Hashed_Set.Instance (S), Elem);
+ return Hashed_Set.Contains (Hashed_Set.Dynamic_Hash_Table (S), Elem);
end Contains;
------------
-- Create --
------------
- function Create (Initial_Size : Positive) return Instance is
+ function Create (Initial_Size : Positive) return Membership_Set is
begin
- return Instance (Hashed_Set.Create (Initial_Size));
+ return Membership_Set (Hashed_Set.Create (Initial_Size));
end Create;
------------
-- Delete --
------------
- procedure Delete (S : Instance; Elem : Element_Type) is
+ procedure Delete (S : Membership_Set; Elem : Element_Type) is
begin
- Hashed_Set.Delete (Hashed_Set.Instance (S), Elem);
+ Hashed_Set.Delete (Hashed_Set.Dynamic_Hash_Table (S), Elem);
end Delete;
-------------
-- Destroy --
-------------
- procedure Destroy (S : in out Instance) is
+ procedure Destroy (B : in out Boolean) is
+ pragma Unreferenced (B);
begin
- Hashed_Set.Destroy (Hashed_Set.Instance (S));
+ null;
+ end Destroy;
+
+ -------------
+ -- Destroy --
+ -------------
+
+ procedure Destroy (S : in out Membership_Set) is
+ begin
+ Hashed_Set.Destroy (Hashed_Set.Dynamic_Hash_Table (S));
end Destroy;
--------------
@@ -86,46 +99,71 @@ package body GNAT.Sets is
-- Insert --
------------
- procedure Insert (S : Instance; Elem : Element_Type) is
+ procedure Insert
+ (S : Membership_Set;
+ Elem : Element_Type)
+ is
begin
- Hashed_Set.Put (Hashed_Set.Instance (S), Elem, True);
+ Hashed_Set.Put (Hashed_Set.Dynamic_Hash_Table (S), Elem, True);
end Insert;
--------------
-- Is_Empty --
--------------
- function Is_Empty (S : Instance) return Boolean is
+ function Is_Empty (S : Membership_Set) return Boolean is
begin
- return Hashed_Set.Is_Empty (Hashed_Set.Instance (S));
+ return Hashed_Set.Is_Empty (Hashed_Set.Dynamic_Hash_Table (S));
end Is_Empty;
-------------
-- Iterate --
-------------
- function Iterate (S : Instance) return Iterator is
+ function Iterate (S : Membership_Set) return Iterator is
begin
- return Iterator (Hashed_Set.Iterate (Hashed_Set.Instance (S)));
+ return
+ Iterator (Hashed_Set.Iterate (Hashed_Set.Dynamic_Hash_Table (S)));
end Iterate;
----------
-- Next --
----------
- procedure Next (Iter : in out Iterator; Elem : out Element_Type) is
+ procedure Next
+ (Iter : in out Iterator;
+ Elem : out Element_Type)
+ is
begin
Hashed_Set.Next (Hashed_Set.Iterator (Iter), Elem);
end Next;
+ -------------
+ -- Present --
+ -------------
+
+ function Present (S : Membership_Set) return Boolean is
+ begin
+ return Hashed_Set.Present (Hashed_Set.Dynamic_Hash_Table (S));
+ end Present;
+
+ -----------
+ -- Reset --
+ -----------
+
+ procedure Reset (S : Membership_Set) is
+ begin
+ Hashed_Set.Reset (Hashed_Set.Dynamic_Hash_Table (S));
+ end Reset;
+
----------
-- Size --
----------
- function Size (S : Instance) return Natural is
+ function Size (S : Membership_Set) return Natural is
begin
- return Hashed_Set.Size (Hashed_Set.Instance (S));
+ return Hashed_Set.Size (Hashed_Set.Dynamic_Hash_Table (S));
end Size;
- end Membership_Set;
+ end Membership_Sets;
end GNAT.Sets;
diff --git a/gcc/ada/libgnat/g-sets.ads b/gcc/ada/libgnat/g-sets.ads
index 27b1a65..1898e26 100644
--- a/gcc/ada/libgnat/g-sets.ads
+++ b/gcc/ada/libgnat/g-sets.ads
@@ -42,12 +42,12 @@ package GNAT.Sets is
-- The following package offers a membership set abstraction with the
-- following characteristics:
--
- -- * Creation of multiple instances, of different sizes.
- -- * Iterable elements.
+ -- * Creation of multiple instances, of different sizes
+ -- * Iterable elements
--
-- The following use pattern must be employed with this set:
--
- -- Set : Instance := Create (<some size>);
+ -- Set : Membership_Set := Create (<some size>);
--
-- <various operations>
--
@@ -65,7 +65,7 @@ package GNAT.Sets is
with function Hash (Key : Element_Type) return Bucket_Range_Type;
-- Map an arbitrary key into the range of buckets
- package Membership_Set is
+ package Membership_Sets is
--------------------
-- Set operations --
@@ -74,36 +74,50 @@ package GNAT.Sets is
-- The following type denotes a membership set handle. Each instance
-- must be created using routine Create.
- type Instance is private;
- Nil : constant Instance;
+ type Membership_Set is private;
+ Nil : constant Membership_Set;
- function Contains (S : Instance; Elem : Element_Type) return Boolean;
+ function Contains
+ (S : Membership_Set;
+ Elem : Element_Type) return Boolean;
-- Determine whether membership set S contains element Elem
- function Create (Initial_Size : Positive) return Instance;
+ function Create (Initial_Size : Positive) return Membership_Set;
-- Create a new membership set with bucket capacity Initial_Size. This
-- routine must be called at the start of the membership set's lifetime.
- procedure Delete (S : Instance; Elem : Element_Type);
+ procedure Delete
+ (S : Membership_Set;
+ Elem : Element_Type);
-- Delete element Elem from membership set S. The routine has no effect
-- if the element is not present in the membership set. This action will
-- raise Iterated if the membership set has outstanding iterators.
- procedure Destroy (S : in out Instance);
+ procedure Destroy (S : in out Membership_Set);
-- Destroy the contents of membership set S, rendering it unusable. This
-- routine must be called at the end of the membership set's lifetime.
-- This action will raise Iterated if the hash table has outstanding
-- iterators.
- procedure Insert (S : Instance; Elem : Element_Type);
+ procedure Insert
+ (S : Membership_Set;
+ Elem : Element_Type);
-- Insert element Elem in membership set S. The routine has no effect
-- if the element is already present in the membership set. This action
-- will raise Iterated if the membership set has outstanding iterators.
- function Is_Empty (S : Instance) return Boolean;
+ function Is_Empty (S : Membership_Set) return Boolean;
-- Determine whether set S is empty
- function Size (S : Instance) return Natural;
+ function Present (S : Membership_Set) return Boolean;
+ -- Determine whether set S exists
+
+ procedure Reset (S : Membership_Set);
+ -- Destroy the contents of membership set S, and reset it to its initial
+ -- created state. This action will raise Iterated if the membership set
+ -- has outstanding iterators.
+
+ function Size (S : Membership_Set) return Natural;
-- Obtain the number of elements in membership set S
-------------------------
@@ -124,7 +138,7 @@ package GNAT.Sets is
type Iterator is private;
- function Iterate (S : Instance) return Iterator;
+ function Iterate (S : Membership_Set) return Iterator;
-- Obtain an iterator over the elements of membership set S. This action
-- locks all mutation functionality of the associated membership set.
@@ -141,7 +155,10 @@ package GNAT.Sets is
-- raises Iterator_Exhausted.
private
- package Hashed_Set is new Dynamic_HTable
+ procedure Destroy (B : in out Boolean);
+ -- Destroy boolean B
+
+ package Hashed_Set is new Dynamic_Hash_Tables
(Key_Type => Element_Type,
Value_Type => Boolean,
No_Value => False,
@@ -150,12 +167,13 @@ package GNAT.Sets is
Compression_Threshold => 0.3,
Compression_Factor => 2,
"=" => "=",
+ Destroy_Value => Destroy,
Hash => Hash);
- type Instance is new Hashed_Set.Instance;
- Nil : constant Instance := Instance (Hashed_Set.Nil);
+ type Membership_Set is new Hashed_Set.Dynamic_Hash_Table;
+ Nil : constant Membership_Set := Membership_Set (Hashed_Set.Nil);
type Iterator is new Hashed_Set.Iterator;
- end Membership_Set;
+ end Membership_Sets;
end GNAT.Sets;
diff --git a/gcc/ada/libgnat/g-sothco.adb b/gcc/ada/libgnat/g-sothco.adb
index df82d01..eb15ac2 100644
--- a/gcc/ada/libgnat/g-sothco.adb
+++ b/gcc/ada/libgnat/g-sothco.adb
@@ -59,14 +59,15 @@ package body GNAT.Sockets.Thin_Common is
-----------------
function Get_Address (Sin : Sockaddr) return Sock_Addr_Type is
+ use type C.unsigned_short;
Family : constant C.unsigned_short :=
(if SOSC.Has_Sockaddr_Len = 0 then Sin.Sin_Family.Short_Family
else C.unsigned_short (Sin.Sin_Family.Char_Family));
+ AF_INET6_Defined : constant Boolean := SOSC.AF_INET6 > 0;
Result : Sock_Addr_Type
- (case Family is
- when SOSC.AF_INET6 => Family_Inet6,
- when SOSC.AF_INET => Family_Inet,
- when others => Family_Unspec);
+ (if AF_INET6_Defined and then SOSC.AF_INET6 = Family then Family_Inet6
+ elsif SOSC.AF_INET = Family then Family_Inet
+ else Family_Unspec);
begin
Result.Port := Port_Type (Network_To_Short (Sin.Sin_Port));
diff --git a/gcc/ada/libgnat/s-win32.ads b/gcc/ada/libgnat/s-win32.ads
index e69c01e..d09c4b3 100644
--- a/gcc/ada/libgnat/s-win32.ads
+++ b/gcc/ada/libgnat/s-win32.ads
@@ -57,6 +57,7 @@ package System.Win32 is
INVALID_HANDLE_VALUE : constant HANDLE := -1;
INVALID_FILE_SIZE : constant := 16#FFFFFFFF#;
+ type ULONG is new Interfaces.C.unsigned_long;
type DWORD is new Interfaces.C.unsigned_long;
type WORD is new Interfaces.C.unsigned_short;
type BYTE is new Interfaces.C.unsigned_char;
@@ -157,18 +158,20 @@ package System.Win32 is
GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS : constant := 16#00000004#;
type OVERLAPPED is record
- Internal : DWORD;
- InternalHigh : DWORD;
+ Internal : access ULONG;
+ InternalHigh : access ULONG;
Offset : DWORD;
OffsetHigh : DWORD;
hEvent : HANDLE;
end record;
+ pragma Convention (C_Pass_By_Copy, OVERLAPPED);
type SECURITY_ATTRIBUTES is record
nLength : DWORD;
pSecurityDescriptor : PVOID;
bInheritHandle : BOOL;
end record;
+ pragma Convention (C_Pass_By_Copy, SECURITY_ATTRIBUTES);
function CreateFileA
(lpFileName : Address;
@@ -267,6 +270,7 @@ package System.Win32 is
dwAllocationGranularity : DWORD;
dwReserved : DWORD;
end record;
+ pragma Convention (C_Pass_By_Copy, SYSTEM_INFO);
procedure GetSystemInfo (SI : access SYSTEM_INFO);
pragma Import (Stdcall, GetSystemInfo, "GetSystemInfo");
@@ -285,6 +289,7 @@ package System.Win32 is
wSecond : WORD;
wMilliseconds : WORD;
end record;
+ pragma Convention (C_Pass_By_Copy, SYSTEMTIME);
procedure GetSystemTime (pSystemTime : access SYSTEMTIME);
pragma Import (Stdcall, GetSystemTime, "GetSystemTime");
diff --git a/gcc/ada/libgnat/system-darwin-ppc.ads b/gcc/ada/libgnat/system-darwin-ppc.ads
index d314b66..9adc2de 100644
--- a/gcc/ada/libgnat/system-darwin-ppc.ads
+++ b/gcc/ada/libgnat/system-darwin-ppc.ads
@@ -158,7 +158,7 @@ private
Preallocated_Stacks : constant Boolean := False;
Signed_Zeros : constant Boolean := True;
Stack_Check_Default : constant Boolean := False;
- Stack_Check_Probes : constant Boolean := False;
+ Stack_Check_Probes : constant Boolean := True;
Stack_Check_Limits : constant Boolean := False;
Support_Aggregates : constant Boolean := True;
Support_Atomic_Primitives : constant Boolean := Word_Size = 64;
diff --git a/gcc/ada/namet.adb b/gcc/ada/namet.adb
index 5f1ff90..c5454d4 100644
--- a/gcc/ada/namet.adb
+++ b/gcc/ada/namet.adb
@@ -1497,6 +1497,33 @@ package body Namet is
return N1 = N2 or else Get_Name_String (N1) = Get_Name_String (N2);
end Name_Equals;
+ -------------
+ -- Present --
+ -------------
+
+ function Present (Nam : File_Name_Type) return Boolean is
+ begin
+ return Nam /= No_File;
+ end Present;
+
+ -------------
+ -- Present --
+ -------------
+
+ function Present (Nam : Name_Id) return Boolean is
+ begin
+ return Nam /= No_Name;
+ end Present;
+
+ -------------
+ -- Present --
+ -------------
+
+ function Present (Nam : Unit_Name_Type) return Boolean is
+ begin
+ return Nam /= No_Unit_Name;
+ end Present;
+
------------------
-- Reinitialize --
------------------
diff --git a/gcc/ada/namet.ads b/gcc/ada/namet.ads
index 58fbc08..a54735a 100644
--- a/gcc/ada/namet.ads
+++ b/gcc/ada/namet.ads
@@ -204,6 +204,10 @@ package Namet is
subtype Valid_Name_Id is Name_Id range First_Name_Id .. Name_Id'Last;
-- All but No_Name and Error_Name
+ function Present (Nam : Name_Id) return Boolean;
+ pragma Inline (Present);
+ -- Determine whether name Nam exists
+
------------------------------
-- Name_Id Membership Tests --
------------------------------
@@ -626,6 +630,10 @@ package Namet is
-- Constant used to indicate no file is present (this is used for example
-- when a search for a file indicates that no file of the name exists).
+ function Present (Nam : File_Name_Type) return Boolean;
+ pragma Inline (Present);
+ -- Determine whether file name Nam exists
+
Error_File_Name : constant File_Name_Type := File_Name_Type (Error_Name);
-- The special File_Name_Type value Error_File_Name is used to indicate
-- a unit name where some previous processing has found an error.
@@ -650,6 +658,10 @@ package Namet is
No_Unit_Name : constant Unit_Name_Type := Unit_Name_Type (No_Name);
-- Constant used to indicate no file name present
+ function Present (Nam : Unit_Name_Type) return Boolean;
+ pragma Inline (Present);
+ -- Determine whether unit name Nam exists
+
Error_Unit_Name : constant Unit_Name_Type := Unit_Name_Type (Error_Name);
-- The special Unit_Name_Type value Error_Unit_Name is used to indicate
-- a unit name where some previous processing has found an error.
diff --git a/gcc/ada/opt.ads b/gcc/ada/opt.ads
index 4ee5fdb..16b5cba 100644
--- a/gcc/ada/opt.ads
+++ b/gcc/ada/opt.ads
@@ -746,9 +746,9 @@ package Opt is
-- file name with extension stripped.
Generate_C_Code : Boolean := False;
- -- GNAT
+ -- GNAT, GNATBIND
-- If True, the Cprint circuitry to generate C code output is activated.
- -- Set True by use of -gnateg or -gnatd.V.
+ -- Set True by use of -gnateg or -gnatd.V for GNAT, and -G for GNATBIND.
Generate_CodePeer_Messages : Boolean := False;
-- GNAT
diff --git a/gcc/ada/osint.adb b/gcc/ada/osint.adb
index 40772c3..d9d72d0 100644
--- a/gcc/ada/osint.adb
+++ b/gcc/ada/osint.adb
@@ -1422,6 +1422,15 @@ package body Osint is
return Name_Find;
end Get_Directory;
+ ------------------------------
+ -- Get_First_Main_File_Name --
+ ------------------------------
+
+ function Get_First_Main_File_Name return String is
+ begin
+ return File_Names (1).all;
+ end Get_First_Main_File_Name;
+
--------------------------
-- Get_Next_Dir_In_Path --
--------------------------
diff --git a/gcc/ada/osint.ads b/gcc/ada/osint.ads
index 048225e..dda44e7 100644
--- a/gcc/ada/osint.ads
+++ b/gcc/ada/osint.ads
@@ -511,6 +511,9 @@ package Osint is
procedure Dump_Command_Line_Source_File_Names;
-- Prints out the names of all source files on the command-line
+ function Get_First_Main_File_Name return String;
+ -- Return the file name of the first main file
+
-------------------------------------------
-- Representation of Library Information --
-------------------------------------------
diff --git a/gcc/ada/par-ch3.adb b/gcc/ada/par-ch3.adb
index 75c17c3..aff14ed 100644
--- a/gcc/ada/par-ch3.adb
+++ b/gcc/ada/par-ch3.adb
@@ -228,8 +228,12 @@ package body Ch3 is
raise Error_Resync;
end if;
+ if Style_Check then
+ Style.Check_Defining_Identifier_Casing;
+ end if;
+
Ident_Node := Token_Node;
- Scan; -- past the reserved identifier
+ Scan; -- past the identifier
-- If we already have a defining identifier, clean it out and make
-- a new clean identifier. This situation arises in some error cases
diff --git a/gcc/ada/rtsfind.ads b/gcc/ada/rtsfind.ads
index cd6e521..47ad874 100644
--- a/gcc/ada/rtsfind.ads
+++ b/gcc/ada/rtsfind.ads
@@ -3155,7 +3155,7 @@ package Rtsfind is
-- immediately, since obviously Ent cannot be the entity in question if the
-- corresponding unit has not been loaded.
- function Is_RTU (Ent : Entity_Id; U : RTU_Id) return Boolean;
+ function Is_RTU (Ent : Entity_Id; U : RTU_Id) return Boolean;
pragma Inline (Is_RTU);
-- This function determines if the given entity corresponds to the entity
-- for the unit referenced by U. If this unit has not been loaded, the
diff --git a/gcc/ada/sem_attr.adb b/gcc/ada/sem_attr.adb
index e966bf1..bdc76c3 100644
--- a/gcc/ada/sem_attr.adb
+++ b/gcc/ada/sem_attr.adb
@@ -3833,14 +3833,16 @@ package body Sem_Attr is
Check_Discrete_Type;
Resolve (E1, P_Base_Type);
- -- X'Enum_Rep case. X must be an object or enumeration literal, and
- -- it must be of a discrete type.
+ -- X'Enum_Rep case. X must be an object or enumeration literal
+ -- (including an attribute reference), and it must be of a
+ -- discrete type.
elsif not
((Is_Object_Reference (P)
or else
(Is_Entity_Name (P)
- and then Ekind (Entity (P)) = E_Enumeration_Literal))
+ and then Ekind (Entity (P)) = E_Enumeration_Literal)
+ or else Nkind (P) = N_Attribute_Reference)
and then Is_Discrete_Type (Etype (P)))
then
Error_Attr_P ("prefix of % attribute must be discrete object");
diff --git a/gcc/ada/sem_ch12.adb b/gcc/ada/sem_ch12.adb
index efbb6cc..42feab0 100644
--- a/gcc/ada/sem_ch12.adb
+++ b/gcc/ada/sem_ch12.adb
@@ -3473,6 +3473,17 @@ package body Sem_Ch12 is
begin
Check_SPARK_05_Restriction ("generic is not allowed", N);
+ -- A generic may grant access to its private enclosing context depending
+ -- on the placement of its corresponding body. From elaboration point of
+ -- view, the flow of execution may enter this private context, and then
+ -- reach an external unit, thus producing a dependency on that external
+ -- unit. For such a path to be properly discovered and encoded in the
+ -- ALI file of the main unit, let the ABE mechanism process the body of
+ -- the main unit, and encode all relevant invocation constructs and the
+ -- relations between them.
+
+ Mark_Save_Invocation_Graph_Of_Body;
+
-- We introduce a renaming of the enclosing package, to have a usable
-- entity as the prefix of an expanded name for a local entity of the
-- form Par.P.Q, where P is the generic package. This is because a local
@@ -3668,6 +3679,17 @@ package body Sem_Ch12 is
begin
Check_SPARK_05_Restriction ("generic is not allowed", N);
+ -- A generic may grant access to its private enclosing context depending
+ -- on the placement of its corresponding body. From elaboration point of
+ -- view, the flow of execution may enter this private context, and then
+ -- reach an external unit, thus producing a dependency on that external
+ -- unit. For such a path to be properly discovered and encoded in the
+ -- ALI file of the main unit, let the ABE mechanism process the body of
+ -- the main unit, and encode all relevant invocation constructs and the
+ -- relations between them.
+
+ Mark_Save_Invocation_Graph_Of_Body;
+
-- Create copy of generic unit, and save for instantiation. If the unit
-- is a child unit, do not copy the specifications for the parent, which
-- are not part of the generic tree.
@@ -3899,8 +3921,8 @@ package body Sem_Ch12 is
-- Local declarations
Gen_Id : constant Node_Id := Name (N);
- Is_Actual_Pack : constant Boolean :=
- Is_Internal (Defining_Entity (N));
+ Inst_Id : constant Entity_Id := Defining_Entity (N);
+ Is_Actual_Pack : constant Boolean := Is_Internal (Inst_Id);
Loc : constant Source_Ptr := Sloc (N);
Saved_GM : constant Ghost_Mode_Type := Ghost_Mode;
@@ -4109,6 +4131,9 @@ package body Sem_Ch12 is
goto Leave;
else
+ Set_Ekind (Inst_Id, E_Package);
+ Set_Scope (Inst_Id, Current_Scope);
+
-- If the context of the instance is subject to SPARK_Mode "off" or
-- the annotation is altogether missing, set the global flag which
-- signals Analyze_Pragma to ignore all SPARK_Mode pragmas within
@@ -5156,14 +5181,13 @@ package body Sem_Ch12 is
(N : Node_Id;
K : Entity_Kind)
is
- Loc : constant Source_Ptr := Sloc (N);
- Gen_Id : constant Node_Id := Name (N);
- Errs : constant Nat := Serious_Errors_Detected;
-
- Anon_Id : constant Entity_Id :=
- Make_Defining_Identifier (Sloc (Defining_Entity (N)),
- Chars => New_External_Name
- (Chars (Defining_Entity (N)), 'R'));
+ Errs : constant Nat := Serious_Errors_Detected;
+ Gen_Id : constant Node_Id := Name (N);
+ Inst_Id : constant Entity_Id := Defining_Entity (N);
+ Anon_Id : constant Entity_Id :=
+ Make_Defining_Identifier (Sloc (Inst_Id),
+ Chars => New_External_Name (Chars (Inst_Id), 'R'));
+ Loc : constant Source_Ptr := Sloc (N);
Act_Decl_Id : Entity_Id := Empty; -- init to avoid warning
Act_Decl : Node_Id;
@@ -5489,6 +5513,9 @@ package body Sem_Ch12 is
Error_Msg_NE ("instantiation of & within itself", N, Gen_Unit);
else
+ Set_Ekind (Inst_Id, K);
+ Set_Scope (Inst_Id, Current_Scope);
+
Set_Entity (Gen_Id, Gen_Unit);
Set_Is_Instantiated (Gen_Unit);
@@ -5654,6 +5681,16 @@ package body Sem_Ch12 is
Set_Has_Pragma_Inline (Act_Decl_Id, Has_Pragma_Inline (Gen_Unit));
Set_Has_Pragma_Inline (Anon_Id, Has_Pragma_Inline (Gen_Unit));
+ Set_Has_Pragma_Inline_Always
+ (Act_Decl_Id, Has_Pragma_Inline_Always (Gen_Unit));
+ Set_Has_Pragma_Inline_Always
+ (Anon_Id, Has_Pragma_Inline_Always (Gen_Unit));
+
+ Set_Has_Pragma_No_Inline
+ (Act_Decl_Id, Has_Pragma_No_Inline (Gen_Unit));
+ Set_Has_Pragma_No_Inline
+ (Anon_Id, Has_Pragma_No_Inline (Gen_Unit));
+
-- Propagate No_Return if pragma applied to generic unit. This must
-- be done explicitly because pragma does not appear in generic
-- declaration (unlike the aspect case).
@@ -5663,11 +5700,6 @@ package body Sem_Ch12 is
Set_No_Return (Anon_Id);
end if;
- Set_Has_Pragma_Inline_Always
- (Act_Decl_Id, Has_Pragma_Inline_Always (Gen_Unit));
- Set_Has_Pragma_Inline_Always
- (Anon_Id, Has_Pragma_Inline_Always (Gen_Unit));
-
-- Mark both the instance spec and the anonymous package in case the
-- body is instantiated at a later pass. This preserves the original
-- context in effect for the body.
@@ -6190,6 +6222,12 @@ package body Sem_Ch12 is
-- Common error routine for mismatch between the parameters of the
-- actual instance and those of the formal package.
+ function Is_Defaulted (Param : Entity_Id) return Boolean;
+ -- If the formal package has partly box-initialized formals, skip
+ -- conformance check for these formals. Previously the code assumed
+ -- that box initialization for a formal package applied to all its
+ -- formal parameters.
+
function Same_Instantiated_Constant (E1, E2 : Entity_Id) return Boolean;
-- The formal may come from a nested formal package, and the actual may
-- have been constant-folded. To determine whether the two denote the
@@ -6240,6 +6278,34 @@ package body Sem_Ch12 is
end if;
end Check_Mismatch;
+ ------------------
+ -- Is_Defaulted --
+ ------------------
+
+ function Is_Defaulted (Param : Entity_Id) return Boolean is
+ Assoc : Node_Id;
+
+ begin
+ Assoc :=
+ First (Generic_Associations (Parent
+ (Associated_Formal_Package (Actual_Pack))));
+
+ while Present (Assoc) loop
+ if Nkind (Assoc) = N_Others_Choice then
+ return True;
+
+ elsif Nkind (Assoc) = N_Generic_Association
+ and then Chars (Selector_Name (Assoc)) = Chars (Param)
+ then
+ return Box_Present (Assoc);
+ end if;
+
+ Next (Assoc);
+ end loop;
+
+ return False;
+ end Is_Defaulted;
+
--------------------------------
-- Same_Instantiated_Constant --
--------------------------------
@@ -6409,6 +6475,9 @@ package body Sem_Ch12 is
then
goto Next_E;
+ elsif Is_Defaulted (E1) then
+ goto Next_E;
+
elsif Is_Type (E1) then
-- Subtypes must statically match. E1, E2 are the local entities
diff --git a/gcc/ada/sem_ch13.adb b/gcc/ada/sem_ch13.adb
index 7e6e5fc..2a4afb8 100644
--- a/gcc/ada/sem_ch13.adb
+++ b/gcc/ada/sem_ch13.adb
@@ -4933,9 +4933,13 @@ package body Sem_Ch13 is
elsif Is_Object (Ent)
and then Present (Renamed_Object (Ent))
then
- -- Case of renamed object from source, this is an error
+ -- In the case of a renamed object from source, this is an error
+ -- unless the object is an aggregate and the renaming is created
+ -- for an object declaration.
- if Comes_From_Source (Renamed_Object (Ent)) then
+ if Comes_From_Source (Renamed_Object (Ent))
+ and then Nkind (Renamed_Object (Ent)) /= N_Aggregate
+ then
Get_Name_String (Chars (N));
Error_Msg_Strlen := Name_Len;
Error_Msg_String (1 .. Name_Len) := Name_Buffer (1 .. Name_Len);
@@ -8197,6 +8201,13 @@ package body Sem_Ch13 is
Set_Static_Discrete_Predicate (Typ, Plist);
+ -- Within a generic the predicate functions themselves need not
+ -- be constructed.
+
+ if Inside_A_Generic then
+ return;
+ end if;
+
-- The processing for static predicates put the expression into
-- canonical form as a series of ranges. It also eliminated
-- duplicates and collapsed and combined ranges. We might as well
@@ -8729,9 +8740,13 @@ package body Sem_Ch13 is
-- Do not generate predicate bodies within a generic unit. The
-- expressions have been analyzed already, and the bodies play
- -- no role if not within an executable unit.
+ -- no role if not within an executable unit. However, if a statc
+ -- predicate is present it must be processed for legality checks
+ -- such as case coverage in an expression.
- elsif Inside_A_Generic then
+ elsif Inside_A_Generic
+ and then not Has_Static_Predicate_Aspect (Typ)
+ then
return;
end if;
@@ -9324,8 +9339,8 @@ package body Sem_Ch13 is
Analyze (End_Decl_Expr);
Set_Is_Frozen (Ent, True);
- -- If the end of declarations comes before any other freeze
- -- point, the Freeze_Expr is not analyzed: no check needed.
+ -- If the end of declarations comes before any other freeze point,
+ -- the Freeze_Expr is not analyzed: no check needed.
if Analyzed (Freeze_Expr) and then not In_Instance then
Check_Overloaded_Name;
@@ -9336,6 +9351,13 @@ package body Sem_Ch13 is
-- All other cases
else
+ -- In a generic context freeze nodes are not always generated, so
+ -- analyze the expression now.
+
+ if not Analyzed (Freeze_Expr) and then Inside_A_Generic then
+ Preanalyze (Freeze_Expr);
+ end if;
+
-- Indicate that the expression comes from an aspect specification,
-- which is used in subsequent analysis even if expansion is off.
diff --git a/gcc/ada/sem_ch3.adb b/gcc/ada/sem_ch3.adb
index 8b06223..75a0099 100644
--- a/gcc/ada/sem_ch3.adb
+++ b/gcc/ada/sem_ch3.adb
@@ -924,15 +924,16 @@ package body Sem_Ch3 is
Set_Has_Delayed_Freeze (Current_Scope);
end if;
- -- Ada 2005: If the designated type is an interface that may contain
- -- tasks, create a Master entity for the declaration. This must be done
- -- before expansion of the full declaration, because the declaration may
- -- include an expression that is an allocator, whose expansion needs the
- -- proper Master for the created tasks.
+ -- If the designated type is limited and class-wide, the object might
+ -- contain tasks, so we create a Master entity for the declaration. This
+ -- must be done before expansion of the full declaration, because the
+ -- declaration may include an expression that is an allocator, whose
+ -- expansion needs the proper Master for the created tasks.
if Nkind (Related_Nod) = N_Object_Declaration and then Expander_Active
then
- if Is_Interface (Desig_Type) and then Is_Limited_Record (Desig_Type)
+ if Is_Limited_Record (Desig_Type)
+ and then Is_Class_Wide_Type (Desig_Type)
then
Build_Class_Wide_Master (Anon_Type);
@@ -8582,6 +8583,16 @@ package body Sem_Ch3 is
Parent_Base := Base_Type (Parent_Type);
end if;
+ -- If the parent type is declared as a subtype of another private
+ -- type with inherited discriminants, its generated base type is
+ -- itself a record subtype. To further inherit the constraint we
+ -- need to use its own base to have an unconstrained type on which
+ -- to apply the inherited constraint.
+
+ if Ekind (Parent_Base) = E_Record_Subtype then
+ Parent_Base := Base_Type (Parent_Base);
+ end if;
+
-- AI05-0115: if this is a derivation from a private type in some
-- other scope that may lead to invisible components for the derived
-- type, mark it accordingly.
@@ -10376,10 +10387,9 @@ package body Sem_Ch3 is
-- build-in-place library function, child unit or not.
if (Nkind (Nod) in N_Entity and then Is_Compilation_Unit (Nod))
- or else
- (Nkind_In (Nod,
- N_Defining_Program_Unit_Name, N_Subprogram_Declaration)
- and then Is_Compilation_Unit (Defining_Entity (Nod)))
+ or else (Nkind_In (Nod, N_Defining_Program_Unit_Name,
+ N_Subprogram_Declaration)
+ and then Is_Compilation_Unit (Defining_Entity (Nod)))
then
Add_Global_Declaration (IR);
else
diff --git a/gcc/ada/sem_ch4.adb b/gcc/ada/sem_ch4.adb
index 2c40011..3328f96 100644
--- a/gcc/ada/sem_ch4.adb
+++ b/gcc/ada/sem_ch4.adb
@@ -7375,7 +7375,7 @@ package body Sem_Ch4 is
Etype (Next_Formal (First_Formal (Op_Id))))
then
Error_Msg_N
- ("No legal interpretation for operator&", N);
+ ("no legal interpretation for operator&", N);
Error_Msg_NE
("\use clause on& would make operation legal",
N, Scope (Op_Id));
@@ -7393,6 +7393,26 @@ package body Sem_Ch4 is
Error_Msg_NE ("\left operand has}!", N, Etype (L));
Error_Msg_NE ("\right operand has}!", N, Etype (R));
+ -- For multiplication and division operators with
+ -- a fixed-point operand and an integer operand,
+ -- indicate that the integer operand should be of
+ -- type Integer.
+
+ if Nkind_In (N, N_Op_Multiply, N_Op_Divide)
+ and then Is_Fixed_Point_Type (Etype (L))
+ and then Is_Integer_Type (Etype (R))
+ then
+ Error_Msg_N
+ ("\convert right operand to `Integer`", N);
+
+ elsif Nkind (N) = N_Op_Multiply
+ and then Is_Fixed_Point_Type (Etype (R))
+ and then Is_Integer_Type (Etype (L))
+ then
+ Error_Msg_N
+ ("\convert left operand to `Integer`", N);
+ end if;
+
-- For concatenation operators it is more difficult to
-- determine which is the wrong operand. It is worth
-- flagging explicitly an access type, for those who
diff --git a/gcc/ada/sem_ch5.adb b/gcc/ada/sem_ch5.adb
index 76d6bcb..88fd204 100644
--- a/gcc/ada/sem_ch5.adb
+++ b/gcc/ada/sem_ch5.adb
@@ -3359,8 +3359,6 @@ package body Sem_Ch5 is
-- The following exception is raised by routine Prepare_Loop_Statement
-- to avoid further analysis of a transformed loop.
- Skip_Analysis : exception;
-
function Disable_Constant (N : Node_Id) return Traverse_Result;
-- If N represents an E_Variable entity, set Is_True_Constant To False
@@ -3368,11 +3366,12 @@ package body Sem_Ch5 is
-- Helper for Analyze_Loop_Statement, to unset Is_True_Constant on
-- variables referenced within an OpenACC construct.
- procedure Prepare_Loop_Statement (Iter : Node_Id);
+ procedure Prepare_Loop_Statement
+ (Iter : Node_Id;
+ Stop_Processing : out Boolean);
-- Determine whether loop statement N with iteration scheme Iter must be
- -- transformed prior to analysis, and if so, perform it. The routine
- -- raises Skip_Analysis to prevent further analysis of the transformed
- -- loop.
+ -- transformed prior to analysis, and if so, perform it.
+ -- If Stop_Processing is set to True, should stop further processing.
----------------------
-- Disable_Constant --
@@ -3394,7 +3393,10 @@ package body Sem_Ch5 is
-- Prepare_Loop_Statement --
----------------------------
- procedure Prepare_Loop_Statement (Iter : Node_Id) is
+ procedure Prepare_Loop_Statement
+ (Iter : Node_Id;
+ Stop_Processing : out Boolean)
+ is
function Has_Sec_Stack_Default_Iterator
(Cont_Typ : Entity_Id) return Boolean;
pragma Inline (Has_Sec_Stack_Default_Iterator);
@@ -3414,21 +3416,27 @@ package body Sem_Ch5 is
-- Determine whether arbitrary statement Stmt is the sole statement
-- wrapped within some block, excluding pragmas.
- procedure Prepare_Iterator_Loop (Iter_Spec : Node_Id);
+ procedure Prepare_Iterator_Loop
+ (Iter_Spec : Node_Id;
+ Stop_Processing : out Boolean);
pragma Inline (Prepare_Iterator_Loop);
-- Prepare an iterator loop with iteration specification Iter_Spec
-- for transformation if needed.
+ -- If Stop_Processing is set to True, should stop further processing.
- procedure Prepare_Param_Spec_Loop (Param_Spec : Node_Id);
+ procedure Prepare_Param_Spec_Loop
+ (Param_Spec : Node_Id;
+ Stop_Processing : out Boolean);
pragma Inline (Prepare_Param_Spec_Loop);
-- Prepare a discrete loop with parameter specification Param_Spec
-- for transformation if needed.
+ -- If Stop_Processing is set to True, should stop further processing.
procedure Wrap_Loop_Statement (Manage_Sec_Stack : Boolean);
- pragma Inline (Wrap_Loop_Statement);
- pragma No_Return (Wrap_Loop_Statement);
+ pragma Inline (Wrap_Loop_Statement);
-- Wrap loop statement N within a block. Flag Manage_Sec_Stack must
-- be set when the block must mark and release the secondary stack.
+ -- Should stop further processing after calling this procedure.
------------------------------------
-- Has_Sec_Stack_Default_Iterator --
@@ -3504,12 +3512,17 @@ package body Sem_Ch5 is
-- Prepare_Iterator_Loop --
---------------------------
- procedure Prepare_Iterator_Loop (Iter_Spec : Node_Id) is
+ procedure Prepare_Iterator_Loop
+ (Iter_Spec : Node_Id;
+ Stop_Processing : out Boolean)
+ is
Cont_Typ : Entity_Id;
Nam : Node_Id;
Nam_Copy : Node_Id;
begin
+ Stop_Processing := False;
+
-- The iterator specification has syntactic errors. Transform the
-- loop into an infinite loop in order to safely perform at least
-- some minor analysis. This check must come first.
@@ -3517,8 +3530,7 @@ package body Sem_Ch5 is
if Error_Posted (Iter_Spec) then
Set_Iteration_Scheme (N, Empty);
Analyze (N);
-
- raise Skip_Analysis;
+ Stop_Processing := True;
-- Nothing to do when the loop is already wrapped in a block
@@ -3578,6 +3590,7 @@ package body Sem_Ch5 is
(Cont_Typ, Name_First)
or else Is_Sec_Stack_Iteration_Primitive
(Cont_Typ, Name_Next));
+ Stop_Processing := True;
end if;
end if;
end Prepare_Iterator_Loop;
@@ -3586,7 +3599,10 @@ package body Sem_Ch5 is
-- Prepare_Param_Spec_Loop --
-----------------------------
- procedure Prepare_Param_Spec_Loop (Param_Spec : Node_Id) is
+ procedure Prepare_Param_Spec_Loop
+ (Param_Spec : Node_Id;
+ Stop_Processing : out Boolean)
+ is
High : Node_Id;
Low : Node_Id;
Rng : Node_Id;
@@ -3594,6 +3610,7 @@ package body Sem_Ch5 is
Rng_Typ : Entity_Id;
begin
+ Stop_Processing := False;
Rng := Discrete_Subtype_Definition (Param_Spec);
-- Nothing to do when the loop is already wrapped in a block
@@ -3622,11 +3639,10 @@ package body Sem_Ch5 is
-- on the secondary stack. Note that the loop must be wrapped
-- only when such a call exists.
- if Has_Sec_Stack_Call (Low)
- or else
- Has_Sec_Stack_Call (High)
+ if Has_Sec_Stack_Call (Low) or else Has_Sec_Stack_Call (High)
then
Wrap_Loop_Statement (Manage_Sec_Stack => True);
+ Stop_Processing := True;
end if;
-- Otherwise the parameter specification appears in the form
@@ -3663,6 +3679,7 @@ package body Sem_Ch5 is
and then Needs_Finalization (Rng_Typ))
then
Wrap_Loop_Statement (Manage_Sec_Stack => True);
+ Stop_Processing := True;
end if;
end if;
end Prepare_Param_Spec_Loop;
@@ -3690,8 +3707,6 @@ package body Sem_Ch5 is
Rewrite (N, Blk);
Analyze (N);
-
- raise Skip_Analysis;
end Wrap_Loop_Statement;
-- Local variables
@@ -3702,11 +3717,13 @@ package body Sem_Ch5 is
-- Start of processing for Prepare_Loop_Statement
begin
+ Stop_Processing := False;
+
if Present (Iter_Spec) then
- Prepare_Iterator_Loop (Iter_Spec);
+ Prepare_Iterator_Loop (Iter_Spec, Stop_Processing);
elsif Present (Param_Spec) then
- Prepare_Param_Spec_Loop (Param_Spec);
+ Prepare_Param_Spec_Loop (Param_Spec, Stop_Processing);
end if;
end Prepare_Loop_Statement;
@@ -3805,7 +3822,15 @@ package body Sem_Ch5 is
-- wrapped within a block in order to manage the secondary stack.
if Present (Iter) then
- Prepare_Loop_Statement (Iter);
+ declare
+ Stop_Processing : Boolean;
+ begin
+ Prepare_Loop_Statement (Iter, Stop_Processing);
+
+ if Stop_Processing then
+ return;
+ end if;
+ end;
end if;
-- Kill current values on entry to loop, since statements in the body of
@@ -3979,10 +4004,6 @@ package body Sem_Ch5 is
if Is_OpenAcc_Environment (Stmt) then
Disable_Constants (Stmt);
end if;
-
- exception
- when Skip_Analysis =>
- null;
end Analyze_Loop_Statement;
----------------------------
diff --git a/gcc/ada/sem_ch6.adb b/gcc/ada/sem_ch6.adb
index d635543c..cf1b0e7 100644
--- a/gcc/ada/sem_ch6.adb
+++ b/gcc/ada/sem_ch6.adb
@@ -5444,10 +5444,14 @@ package body Sem_Ch6 is
and then Directly_Designated_Type (Old_Formal_Base) =
Directly_Designated_Type (New_Formal_Base)
and then ((Is_Itype (Old_Formal_Base)
- and then Can_Never_Be_Null (Old_Formal_Base))
+ and then (Can_Never_Be_Null (Old_Formal_Base)
+ or else Is_Access_Constant
+ (Old_Formal_Base)))
or else
(Is_Itype (New_Formal_Base)
- and then Can_Never_Be_Null (New_Formal_Base)));
+ and then (Can_Never_Be_Null (New_Formal_Base)
+ or else Is_Access_Constant
+ (New_Formal_Base))));
-- Types must always match. In the visible part of an instance,
-- usual overloading rules for dispatching operations apply, and
diff --git a/gcc/ada/sem_ch7.adb b/gcc/ada/sem_ch7.adb
index c6095ef..6f5126e 100644
--- a/gcc/ada/sem_ch7.adb
+++ b/gcc/ada/sem_ch7.adb
@@ -389,6 +389,8 @@ package body Sem_Ch7 is
end if;
-- An inlined subprogram body acts as a referencer
+ -- unless we generate C code since inlining is then
+ -- handled by the C compiler.
-- Note that we test Has_Pragma_Inline here in addition
-- to Is_Inlined. We are doing this for a client, since
@@ -397,8 +399,9 @@ package body Sem_Ch7 is
-- should occur, so we need to catch all cases where the
-- subprogram may be inlined by the client.
- if Is_Inlined (Decl_Id)
- or else Has_Pragma_Inline (Decl_Id)
+ if not Generate_C_Code
+ and then (Is_Inlined (Decl_Id)
+ or else Has_Pragma_Inline (Decl_Id))
then
Has_Referencer_Of_Non_Subprograms := True;
@@ -415,9 +418,12 @@ package body Sem_Ch7 is
Decl_Id := Defining_Entity (Decl);
-- An inlined subprogram body acts as a referencer
+ -- unless we generate C code since inlining is then
+ -- handled by the C compiler.
- if Is_Inlined (Decl_Id)
- or else Has_Pragma_Inline (Decl_Id)
+ if not Generate_C_Code
+ and then (Is_Inlined (Decl_Id)
+ or else Has_Pragma_Inline (Decl_Id))
then
Has_Referencer_Of_Non_Subprograms := True;
@@ -3253,7 +3259,7 @@ package body Sem_Ch7 is
-- A [generic] package that defines at least one non-null abstract state
-- requires a completion only when at least one other construct requires
- -- a completion in a body (SPARK RM 7.1.4(4) and (6)). This check is not
+ -- a completion in a body (SPARK RM 7.1.4(4) and (5)). This check is not
-- performed if the caller requests this behavior.
if Do_Abstract_States
diff --git a/gcc/ada/sem_ch8.adb b/gcc/ada/sem_ch8.adb
index a5e821d..b58ad64 100644
--- a/gcc/ada/sem_ch8.adb
+++ b/gcc/ada/sem_ch8.adb
@@ -784,9 +784,9 @@ package body Sem_Ch8 is
begin
if Nkind_In (Nam, N_Function_Call, N_Explicit_Dereference)
- and then Is_Composite_Type (Etype (Nam))
- and then not Is_Constrained (Etype (Nam))
- and then not Has_Unknown_Discriminants (Etype (Nam))
+ and then Is_Composite_Type (Typ)
+ and then not Is_Constrained (Typ)
+ and then not Has_Unknown_Discriminants (Typ)
and then Expander_Active
then
-- If Actual_Subtype is already set, nothing to do
@@ -1122,7 +1122,11 @@ package body Sem_Ch8 is
Wrong_Type (Nam, T);
end if;
- T2 := Etype (Nam);
+ -- We must search for an actual subtype here so that the bounds of
+ -- objects of unconstrained types don't get dropped on the floor - such
+ -- as with renamings of formal parameters.
+
+ T2 := Get_Actual_Subtype_If_Available (Nam);
-- Ada 2005 (AI-326): Handle wrong use of incomplete type
@@ -5489,8 +5493,10 @@ package body Sem_Ch8 is
if Nkind (N) = N_Identifier then
Mark_Elaboration_Attributes
- (N_Id => N,
- Modes => True);
+ (N_Id => N,
+ Checks => True,
+ Modes => True,
+ Warnings => True);
end if;
-- Here if Entity pointer was not set, we need full visibility analysis
@@ -6514,8 +6520,10 @@ package body Sem_Ch8 is
-- resolution, and expansion are over.
Mark_Elaboration_Attributes
- (N_Id => N,
- Modes => True);
+ (N_Id => N,
+ Checks => True,
+ Modes => True,
+ Warnings => True);
-- Set appropriate type
@@ -7418,10 +7426,28 @@ package body Sem_Ch8 is
-- It is not an error if the prefix is the current instance of
-- type name, e.g. the expression of a type aspect, when it is
- -- analyzed for ASIS use.
+ -- analyzed for ASIS use, or within a generic unit. We still
+ -- have to verify that a component of that name exists, and
+ -- decorate the node accordingly.
elsif Is_Entity_Name (P) and then Is_Current_Instance (P) then
- null;
+ declare
+ Comp : Entity_Id;
+
+ begin
+ Comp := First_Entity (Entity (P));
+ while Present (Comp) loop
+ if Chars (Comp) = Chars (Selector_Name (N)) then
+ Set_Entity (N, Comp);
+ Set_Etype (N, Etype (Comp));
+ Set_Entity (Selector_Name (N), Comp);
+ Set_Etype (Selector_Name (N), Etype (Comp));
+ return;
+ end if;
+
+ Next_Entity (Comp);
+ end loop;
+ end;
elsif Ekind (P_Name) = E_Void then
Premature_Usage (P);
diff --git a/gcc/ada/sem_elab.adb b/gcc/ada/sem_elab.adb
index b74f88d..f57b3b1 100644
--- a/gcc/ada/sem_elab.adb
+++ b/gcc/ada/sem_elab.adb
@@ -23,6 +23,7 @@
-- --
------------------------------------------------------------------------------
+with ALI; use ALI;
with Atree; use Atree;
with Checks; use Checks;
with Debug; use Debug;
@@ -59,7 +60,10 @@ with Tbuild; use Tbuild;
with Uintp; use Uintp;
with Uname; use Uname;
-with GNAT.HTable; use GNAT.HTable;
+with GNAT; use GNAT;
+with GNAT.Dynamic_HTables; use GNAT.Dynamic_HTables;
+with GNAT.Lists; use GNAT.Lists;
+with GNAT.Sets; use GNAT.Sets;
package body Sem_Elab is
@@ -80,30 +84,41 @@ package body Sem_Elab is
-- Due to control and data flow, the ABE mechanism cannot accurately
-- determine whether a particular scenario will be elaborated or not.
-- Conditional ABE checks are therefore used to verify the elaboration
- -- status of a local and external target at run time.
+ -- status of local and external targets at run time.
--
- -- * Supply elaboration dependencies for a unit to binde
+ -- * Supply implicit elaboration dependencies for a unit to binde
--
- -- The ABE mechanism registers each outgoing elaboration edge for the
- -- main unit in its ALI file. GNATbind and binde can then reconstruct
- -- the full elaboration graph and determine the proper elaboration
- -- order for all units in the compilation.
+ -- The ABE mechanism creates implicit dependencies in the form of with
+ -- clauses subject to pragma Elaborate[_All] when the elaboration graph
+ -- reaches into an external unit. The implicit dependencies are encoded
+ -- in the ALI file of the main unit. GNATbind and binde then use these
+ -- dependencies to augment the library item graph and determine the
+ -- elaboration order of all units in the compilation.
+ --
+ -- * Supply pieces of the invocation graph for a unit to bindo
+ --
+ -- The ABE mechanism captures paths starting from elaboration code or
+ -- top level constructs that reach into an external unit. The paths are
+ -- encoded in the ALI file of the main unit in the form of declarations
+ -- which represent nodes, and relations which represent edges. GNATbind
+ -- and bindo then build the full invocation graph in order to augment
+ -- the library item graph and determine the elaboration order of all
+ -- units in the compilation.
--
-- The ABE mechanism supports three models of elaboration:
--
-- * Dynamic model - This is the most permissive of the three models.
- -- When the dynamic model is in effect, the mechanism performs very
- -- little diagnostics and generates run-time checks to detect ABE
- -- issues. The behaviour of this model is identical to that specified
- -- by the Ada RM. This model is enabled with switch -gnatE.
+ -- When the dynamic model is in effect, the mechanism diagnoses and
+ -- installs run-time checks to detect ABE issues in the main unit.
+ -- The behaviour of this model is identical to that specified by the
+ -- Ada RM. This model is enabled with switch -gnatE.
--
- -- * Static model - This is the middle ground of the three models. When
+ -- Static model - This is the middle ground of the three models. When
-- the static model is in effect, the mechanism diagnoses and installs
-- run-time checks to detect ABE issues in the main unit. In addition,
- -- the mechanism generates implicit Elaborate or Elaborate_All pragmas
- -- to ensure the prior elaboration of withed units. The model employs
- -- textual order, with clause context, and elaboration-related source
- -- pragmas. This is the default model.
+ -- the mechanism generates implicit dependencies between units in the
+ -- form of with clauses subject to pragma Elaborate[_All] to ensure
+ -- the prior elaboration of withed units. This is the default model.
--
-- * SPARK model - This is the most conservative of the three models and
-- impelements the semantics defined in SPARK RM 7.7. The SPARK model
@@ -117,8 +132,8 @@ package body Sem_Elab is
-- Terminology --
-----------------
- -- * ABE - An attempt to activate, call, or instantiate a scenario which
- -- has not been fully elaborated.
+ -- * ABE - An attempt to invoke a scenario which has not been elaborated
+ -- yet.
--
-- * Bridge target - A type of target. A bridge target is a link between
-- scenarios. It is usually a byproduct of expansion and does not have
@@ -129,9 +144,9 @@ package body Sem_Elab is
-- call. N_Call_Marker nodes do not have static and run-time semantics.
--
-- * Conditional ABE - A type of ABE. A conditional ABE occurs when the
- -- elaboration or invocation of a target by a scenario within the main
- -- unit causes an ABE, but does not cause an ABE for another scenarios
- -- within the main unit.
+ -- invocation of a target by a scenario within the main unit causes an
+ -- ABE, but does not cause an ABE for another scenarios within the main
+ -- unit.
--
-- * Declaration level - A type of enclosing level. A scenario or target is
-- at the declaration level when it appears within the declarations of a
@@ -148,13 +163,26 @@ package body Sem_Elab is
-- package library unit, ignoring enclosing packages.
--
-- * Guaranteed ABE - A type of ABE. A guaranteed ABE occurs when the
- -- elaboration or invocation of a target by all scenarios within the
- -- main unit causes an ABE.
+ -- invocation of a target by all scenarios within the main unit causes
+ -- an ABE.
--
-- * Instantiation library level - A type of enclosing level. A scenario
-- or target is at the instantiation library level if it appears in an
-- instantiation library unit, ignoring enclosing packages.
--
+ -- * Invocation - The act of activating a task, calling a subprogram, or
+ -- instantiating a generic.
+ --
+ -- * Invocation construct - An entry declaration, [single] protected type,
+ -- subprogram declaration, subprogram instantiation, or a [single] task
+ -- type declared in the visible, private, or body declarations of the
+ -- main unit.
+ --
+ -- * Invocation relation - A flow link between two invocation constructs
+ --
+ -- * Invocation signature - A set of attributes that uniquely identify an
+ -- invocation construct within the namespace of all ALI files.
+ --
-- * Library level - A type of enclosing level. A scenario or target is at
-- the library level if it appears in a package library unit, ignoring
-- enclosng packages.
@@ -162,9 +190,9 @@ package body Sem_Elab is
-- * Non-library-level encapsulator - A construct that cannot be elaborated
-- on its own and requires elaboration by a top-level scenario.
--
- -- * Scenario - A construct or context which may be elaborated or executed
- -- by elaboration code. The scenarios recognized by the ABE mechanism are
- -- as follows:
+ -- * Scenario - A construct or context which is invoked by elaboration code
+ -- or invocation construct. The scenarios recognized by the ABE mechanism
+ -- are as follows:
--
-- - '[Unrestricted_]Access of entries, operators, and subprograms
--
@@ -182,8 +210,8 @@ package body Sem_Elab is
--
-- - Task activation
--
- -- * Target - A construct referenced by a scenario. The targets recognized
- -- by the ABE mechanism are as follows:
+ -- * Target - A construct invoked by a scenario. The targets recognized by
+ -- the ABE mechanism are as follows:
--
-- - For '[Unrestricted_]Access of entries, operators, and subprograms,
-- the target is the entry, operator, or subprogram.
@@ -201,16 +229,84 @@ package body Sem_Elab is
-- - For reads of variables, the target is the variable
--
-- - For task activation, the target is the task body
- --
- -- * Top-level scenario - A scenario which appears in a non-generic main
- -- unit. Depending on the elaboration model is in effect, the following
- -- addotional restrictions apply:
- --
- -- - Dynamic model - No restrictions
- --
- -- - SPARK model - Falls back to either the dynamic or static model
- --
- -- - Static model - The scenario must be at the library level
+
+ ------------------
+ -- Architecture --
+ ------------------
+
+ -- Analysis/Resolution
+ -- |
+ -- +- Build_Call_Marker
+ -- |
+ -- +- Build_Variable_Reference_Marker
+ -- |
+ -- +- | -------------------- Recording phase ---------------------------+
+ -- | v |
+ -- | Record_Elaboration_Scenario |
+ -- | | |
+ -- | +--> Check_Preelaborated_Call |
+ -- | | |
+ -- | +--> Process_Guaranteed_ABE |
+ -- | | | |
+ -- | | +--> Process_Guaranteed_ABE_Activation |
+ -- | | +--> Process_Guaranteed_ABE_Call |
+ -- | | +--> Process_Guaranteed_ABE_Instantiation |
+ -- | | |
+ -- +- | ----------------------------------------------------------------+
+ -- |
+ -- |
+ -- +--> Internal_Representation
+ -- |
+ -- +--> Scenario_Storage
+ -- |
+ -- End of Compilation
+ -- |
+ -- +- | --------------------- Processing phase -------------------------+
+ -- | v |
+ -- | Check_Elaboration_Scenarios |
+ -- | | |
+ -- | +--> Check_Conditional_ABE_Scenarios |
+ -- | | | |
+ -- | | +--> Process_Conditional_ABE <----------------------+ |
+ -- | | | | |
+ -- | | +--> Process_Conditional_ABE_Activation | |
+ -- | | | | | |
+ -- | | | +-----------------------------+ | |
+ -- | | | | | |
+ -- | | +--> Process_Conditional_ABE_Call +---> Traverse_Body |
+ -- | | | | | |
+ -- | | | +-----------------------------+ |
+ -- | | | |
+ -- | | +--> Process_Conditional_ABE_Access_Taken |
+ -- | | +--> Process_Conditional_ABE_Instantiation |
+ -- | | +--> Process_Conditional_ABE_Variable_Assignment |
+ -- | | +--> Process_Conditional_ABE_Variable_Reference |
+ -- | | |
+ -- | +--> Check_SPARK_Scenario |
+ -- | | | |
+ -- | | +--> Process_SPARK_Scenario |
+ -- | | | |
+ -- | | +--> Process_SPARK_Derived_Type |
+ -- | | +--> Process_SPARK_Instantiation |
+ -- | | +--> Process_SPARK_Refined_State_Pragma |
+ -- | | |
+ -- | +--> Record_Invocation_Graph |
+ -- | | |
+ -- | +--> Process_Invocation_Body_Scenarios |
+ -- | +--> Process_Invocation_Spec_Scenarios |
+ -- | +--> Process_Main_Unit |
+ -- | | |
+ -- | +--> Process_Invocation_Scenario <-------------+ |
+ -- | | | |
+ -- | +--> Process_Invocation_Activation | |
+ -- | | | | |
+ -- | | +------------------------+ | |
+ -- | | | | |
+ -- | +--> Process_Invocation_Call +---> Traverse_Body |
+ -- | | | |
+ -- | +------------------------+ |
+ -- | |
+ -- +--------------------------------------------------------------------+
---------------------
-- Recording phase --
@@ -219,14 +315,14 @@ package body Sem_Elab is
-- The Recording phase coincides with the analysis/resolution phase of the
-- compiler. It has the following objectives:
--
- -- * Record all top-level scenarios for examination by the Processing
+ -- * Record all suitable scenarios for examination by the Processing
-- phase.
--
-- Saving only a certain number of nodes improves the performance of
-- the ABE mechanism. This eliminates the need to examine the whole
-- tree in a separate pass.
--
- -- * Record certain SPARK scenarios which are not necessarily executable
+ -- * Record certain SPARK scenarios which are not necessarily invoked
-- during elaboration, but still require elaboration-related checks.
--
-- Saving only a certain number of nodes improves the performance of
@@ -240,8 +336,8 @@ package body Sem_Elab is
-- does not need the heavy recursive traversal done by the Processing
-- phase.
--
- -- * Detect and diagnose guaranteed ABEs caused by instantiations,
- -- calls, and task activation.
+ -- * Detect and diagnose guaranteed ABEs caused by instantiations, calls,
+ -- and task activation.
--
-- The issues detected by the ABE mechanism are reported as warnings
-- because they do not violate Ada semantics. Forward instantiations
@@ -259,101 +355,34 @@ package body Sem_Elab is
-- and/or inlining of bodies, but before the removal of Ghost code. It has
-- the following objectives:
--
- -- * Examine all top-level scenarios saved during the Recording phase
+ -- * Examine all scenarios saved during the Recording phase, and perform
+ -- the following actions:
--
- -- The top-level scenarios act as roots for depth-first traversal of
- -- the call/instantiation/task activation graph. The traversal stops
- -- when an outgoing edge leaves the main unit.
+ -- - Dynamic model
--
- -- * Examine all SPARK scenarios saved during the Recording phase
+ -- Diagnose conditional ABEs, and install run-time conditional ABE
+ -- checks for all scenarios.
--
- -- * Depending on the elaboration model in effect, perform the following
- -- actions:
+ -- - SPARK model
--
- -- - Dynamic model - Install run-time conditional ABE checks.
+ -- Enforce the SPARK elaboration rules
--
- -- - SPARK model - Enforce the SPARK elaboration rules
+ -- - Static model
--
- -- - Static model - Diagnose conditional ABEs, install run-time
- -- conditional ABE checks, and guarantee the elaboration of
- -- external units.
+ -- Diagnose conditional ABEs, install run-time conditional ABE
+ -- checks only for scenarios are reachable from elaboration code,
+ -- and guarantee the elaboration of external units by creating
+ -- implicit with clauses subject to pragma Elaborate[_All].
--
- -- * Examine nested scenarios
+ -- * Examine library-level scenarios and invocation constructs, and
+ -- perform the following actions:
--
- -- Nested scenarios discovered during the depth-first traversal are
- -- in turn subjected to the same actions outlined above and examined
- -- for the next level of nested scenarios.
-
- ------------------
- -- Architecture --
- ------------------
-
- -- Analysis/Resolution
- -- |
- -- +- Build_Call_Marker
- -- |
- -- +- Build_Variable_Reference_Marker
- -- |
- -- +- | -------------------- Recording phase ---------------------------+
- -- | v |
- -- | Record_Elaboration_Scenario |
- -- | | |
- -- | +--> Check_Preelaborated_Call |
- -- | | |
- -- | +--> Process_Guaranteed_ABE |
- -- | | | |
- -- | | +--> Process_Guaranteed_ABE_Activation |
- -- | | | |
- -- | | +--> Process_Guaranteed_ABE_Call |
- -- | | | |
- -- | | +--> Process_Guaranteed_ABE_Instantiation |
- -- | | |
- -- +- | ----------------------------------------------------------------+
- -- |
- -- |
- -- +--> SPARK_Scenarios
- -- | +-----------+-----------+ .. +-----------+
- -- | | Scenario1 | Scenario2 | .. | ScenarioN |
- -- | +-----------+-----------+ .. +-----------+
- -- |
- -- +--> Top_Level_Scenarios
- -- | +-----------+-----------+ .. +-----------+
- -- | | Scenario1 | Scenario2 | .. | ScenarioN |
- -- | +-----------+-----------+ .. +-----------+
- -- |
- -- End of Compilation
- -- |
- -- +- | --------------------- Processing phase -------------------------+
- -- | v |
- -- | Check_Elaboration_Scenarios |
- -- | | |
- -- | +--> Check_SPARK_Scenario |
- -- | | | |
- -- | | +--> Check_SPARK_Derived_Type |
- -- | | | |
- -- | | +--> Check_SPARK_Instantiation |
- -- | | | |
- -- | | +--> Check_SPARK_Refined_State_Pragma |
- -- | | |
- -- | +--> Process_Conditional_ABE <---------------------------+ |
- -- | | | |
- -- | +--> Process_Conditional_ABE_Access Is_Suitable_Scenario |
- -- | | ^ |
- -- | +--> Process_Conditional_ABE_Activation | |
- -- | | | | |
- -- | | +-----------------------------+ | |
- -- | | | | |
- -- | +--> Process_Conditional_ABE_Call +--------> Traverse_Body |
- -- | | | | |
- -- | | +-----------------------------+ |
- -- | | |
- -- | +--> Process_Conditional_ABE_Instantiation |
- -- | | |
- -- | +--> Process_Conditional_ABE_Variable_Assignment |
- -- | | |
- -- | +--> Process_Conditional_ABE_Variable_Reference |
- -- | |
- -- +--------------------------------------------------------------------+
+ -- - Determine whether the flow of execution reaches into an external
+ -- unit. If this is the case, encode the path in the ALI file of
+ -- the main unit.
+ --
+ -- - Create declarations for invocation constructs in the ALI file of
+ -- the main unit.
----------------------
-- Important points --
@@ -364,11 +393,11 @@ package body Sem_Elab is
-- available. The scope stack is empty, global flags such as In_Instance
-- or Inside_A_Generic become useless. To remedy this, the ABE mechanism
-- must either save or recompute semantic information.
-
+ --
-- Expansion heavily transforms calls and to some extent instantiations. To
-- remedy this, the ABE mechanism generates N_Call_Marker nodes in order to
-- capture the target and relevant attributes of the original call.
-
+ --
-- The diagnostics of the ABE mechanism depend on accurate source locations
-- to determine the spacial relation of nodes.
@@ -453,6 +482,13 @@ package body Sem_Elab is
-- The ABE mechanism considers scenarios which appear in internal
-- units (Ada, GNAT, Interfaces, System).
--
+ -- -gnatd_F encode full invocation paths in ALI files
+ --
+ -- The ABE mechanism encodes the full path from an elaboration
+ -- procedure or invocable construct to an external target. The
+ -- path contains all intermediate activations, instantiations,
+ -- and calls.
+ --
-- -gnatd.G ignore calls through generic formal parameters for elaboration
--
-- The ABE mechanism does not generate N_Call_Marker nodes for
@@ -460,6 +496,12 @@ package body Sem_Elab is
-- actual subprograms through generic formal subprograms. As a
-- result, the calls are not recorded or processed.
--
+ -- -gnatd_G encode invocation graph in ALI files
+ --
+ -- The ABE mechanism encodes the invocation graph of the main
+ -- unit. This includes elaboration code, as well as invocation
+ -- constructs.
+ --
-- -gnatd_i ignore activations and calls to instances for elaboration
--
-- The ABE mechanism ignores calls and task activations when they
@@ -508,6 +550,11 @@ package body Sem_Elab is
-- Ada.Synchronous_Barriers.Wait_For_Release
-- Ada.Synchronous_Task_Control.Suspend_Until_True
--
+ -- -gnatd_T output trace information on invocation relation construction
+ --
+ -- The ABE mechanism outputs text information concerning relation
+ -- construction to standard output.
+ --
-- -gnatd.U ignore indirect calls for static elaboration
--
-- The ABE mechanism does not consider '[Unrestricted_]Access of
@@ -589,66 +636,6 @@ package body Sem_Elab is
--
-- The complementary switch for -gnatwl.
- ---------------------------
- -- Adding a new scenario --
- ---------------------------
-
- -- The following steps describe how to add a new elaboration scenario and
- -- preserve the existing architecture. Note that not all of the steps may
- -- need to be carried out.
- --
- -- 1) Update predicate Is_Scenario
- --
- -- 2) Add predicate Is_Suitable_xxx. Include a call to it in predicate
- -- Is_Suitable_Scenario.
- --
- -- 3) Update routine Record_Elaboration_Scenario
- --
- -- 4) Add routine Process_Conditional_ABE_xxx. Include a call to it in
- -- routine Process_Conditional_ABE.
- --
- -- 5) Add routine Process_Guaranteed_ABE_xxx. Include a call to it in
- -- routine Process_Guaranteed_ABE.
- --
- -- 6) Add routine Check_SPARK_xxx. Include a call to it in routine
- -- Check_SPARK_Scenario.
- --
- -- 7) Add routine Info_xxx. Include a call to it in routine
- -- Process_Conditional_ABE_xxx.
- --
- -- 8) Add routine Output_xxx. Include a call to it in routine
- -- Output_Active_Scenarios.
- --
- -- 9) Add routine Extract_xxx_Attributes
- --
- -- 10) Update routine Is_Potential_Scenario
-
- -------------------------
- -- Adding a new target --
- -------------------------
-
- -- The following steps describe how to add a new elaboration target and
- -- preserve the existing architecture. Note that not all of the steps may
- -- need to be carried out.
- --
- -- 1) Add predicate Is_xxx.
- --
- -- 2) Update the following predicates
- --
- -- Is_Ada_Semantic_Target
- -- Is_Assertion_Pragma_Target
- -- Is_Bridge_Target
- -- Is_SPARK_Semantic_Target
- --
- -- If necessary, create a new category.
- --
- -- 3) Update the appropriate Info_xxx routine.
- --
- -- 4) Update the appropriate Output_xxx routine.
- --
- -- 5) Update routine Extract_Target_Attributes. If necessary, create a
- -- new Extract_xxx routine.
-
--------------------------
-- Debugging ABE issues --
--------------------------
@@ -659,7 +646,7 @@ package body Sem_Elab is
--
-- Build_Call_Marker
-- Record_Elaboration_Scenario
-
+ --
-- * If the issue involves an arbitrary scenario, ensure that the scenario
-- is either recorded, or is successfully recognized while traversing a
-- body. The routines of interest are
@@ -668,7 +655,7 @@ package body Sem_Elab is
-- Process_Conditional_ABE
-- Process_Guaranteed_ABE
-- Traverse_Body
-
+ --
-- * If the issue involves a circularity in the elaboration order, examine
-- the ALI files and look for the following encodings next to units:
--
@@ -685,601 +672,1272 @@ package body Sem_Elab is
--
-- Ensure_Prior_Elaboration
- ----------------
- -- Attributes --
- ----------------
+ -----------
+ -- Kinds --
+ -----------
- -- To minimize the amount of code within routines, the ABE mechanism relies
- -- on "attribute" records to capture relevant information for a scenario or
- -- a target.
+ -- The following type enumerates all subprogram body traversal modes
- -- The following type captures relevant attributes which pertain to a call
+ type Body_Traversal_Kind is
+ (Deep_Traversal,
+ -- The traversal examines the internals of a subprogram
- type Call_Attributes is record
- Elab_Checks_OK : Boolean;
- -- This flag is set when the call has elaboration checks enabled
+ No_Traversal);
- Elab_Warnings_OK : Boolean;
- -- This flag is set when the call has elaboration warnings elabled
+ -- The following type enumerates all operation modes
- From_Source : Boolean;
- -- This flag is set when the call comes from source
+ type Processing_Kind is
+ (Conditional_ABE_Processing,
+ -- The ABE mechanism detects and diagnoses conditional ABEs for library
+ -- and declaration-level scenarios.
- Ghost_Mode_Ignore : Boolean;
- -- This flag is set when the call appears in a region subject to pragma
- -- Ghost with policy Ignore.
+ Dynamic_Model_Processing,
+ -- The ABE mechanism installs conditional ABE checks for all eligible
+ -- scenarios when the dynamic model is in effect.
- In_Declarations : Boolean;
- -- This flag is set when the call appears at the declaration level
+ Guaranteed_ABE_Processing,
+ -- The ABE mechanism detects and diagnoses guaranteed ABEs caused by
+ -- calls, instantiations, and task activations.
- Is_Dispatching : Boolean;
- -- This flag is set when the call is dispatching
+ Invocation_Construct_Processing,
+ -- The ABE mechanism locates all invocation constructs within the main
+ -- unit and utilizes them as roots of miltiple DFS traversals aimed at
+ -- detecting transitions from the main unit to an external unit.
- SPARK_Mode_On : Boolean;
- -- This flag is set when the call appears in a region subject to pragma
- -- SPARK_Mode with value On.
- end record;
+ Invocation_Body_Processing,
+ -- The ABE mechanism utilizes all library-level body scenarios as roots
+ -- of miltiple DFS traversals aimed at detecting transitions from the
+ -- main unit to an external unit.
- -- The following type captures relevant attributes which pertain to the
- -- prior elaboration of a unit. This type is coupled together with a unit
- -- to form a key -> value relationship.
-
- type Elaboration_Attributes is record
- Source_Pragma : Node_Id;
- -- This attribute denotes a source Elaborate or Elaborate_All pragma
- -- which guarantees the prior elaboration of some unit with respect
- -- to the main unit. The pragma may come from the following contexts:
-
- -- * The main unit
- -- * The spec of the main unit (if applicable)
- -- * Any parent spec of the main unit (if applicable)
- -- * Any parent subunit of the main unit (if applicable)
-
- -- The attribute remains Empty if no such pragma is available. Source
- -- pragmas play a role in satisfying SPARK elaboration requirements.
-
- With_Clause : Node_Id;
- -- This attribute denotes an internally generated or source with clause
- -- for some unit withed by the main unit. With clauses carry flags which
- -- represent implicit Elaborate or Elaborate_All pragmas. These clauses
- -- play a role in supplying the elaboration dependencies to binde.
- end record;
+ Invocation_Spec_Processing,
+ -- The ABE mechanism utilizes all library-level spec scenarios as roots
+ -- of miltiple DFS traversals aimed at detecting transitions from the
+ -- main unit to an external unit.
- No_Elaboration_Attributes : constant Elaboration_Attributes :=
- (Source_Pragma => Empty,
- With_Clause => Empty);
+ SPARK_Processing,
+ -- The ABE mechanism detects and diagnoses violations of the SPARK
+ -- elaboration rules for SPARK-specific scenarios.
- -- The following type captures relevant attributes which pertain to an
- -- instantiation.
+ No_Processing);
- type Instantiation_Attributes is record
- Elab_Checks_OK : Boolean;
- -- This flag is set when the instantiation has elaboration checks
- -- enabled.
+ -- The following type enumerates all possible scenario kinds
- Elab_Warnings_OK : Boolean;
- -- This flag is set when the instantiation has elaboration warnings
- -- enabled.
+ type Scenario_Kind is
+ (Access_Taken_Scenario,
+ -- An attribute reference which takes 'Access or 'Unrestricted_Access of
+ -- an entry, operator, or subprogram.
- Ghost_Mode_Ignore : Boolean;
- -- This flag is set when the instantiation appears in a region subject
- -- to pragma Ghost with policy ignore, or starts one such region.
+ Call_Scenario,
+ -- A call which invokes an entry, operator, or subprogram
- In_Declarations : Boolean;
- -- This flag is set when the instantiation appears at the declaration
- -- level.
+ Derived_Type_Scenario,
+ -- A declaration of a derived type. This is a SPARK-specific scenario.
- SPARK_Mode_On : Boolean;
- -- This flag is set when the instantiation appears in a region subject
- -- to pragma SPARK_Mode with value On, or starts one such region.
- end record;
+ Instantiation_Scenario,
+ -- An instantiation which instantiates a generic package or subprogram.
+ -- This scenario is also subject to SPARK-specific rules.
+
+ Refined_State_Pragma_Scenario,
+ -- A Refined_State pragma. This is a SPARK-specific scenario.
+
+ Task_Activation_Scenario,
+ -- A call which activates objects of various task types
+
+ Variable_Assignment_Scenario,
+ -- An assignment statement which modifies the value of some variable
+
+ Variable_Reference_Scenario,
+ -- A reference to a variable. This is a SPARK-specific scenario.
+
+ No_Scenario);
+
+ -- The following type enumerates all possible consistency models of target
+ -- and scenario representations.
+
+ type Representation_Kind is
+ (Inconsistent_Representation,
+ -- A representation is said to be "inconsistent" when it is created from
+ -- a partially analyzed tree. In such an environment, certain attributes
+ -- such as a completing body may not be available yet.
+
+ Consistent_Representation,
+ -- A representation is said to be "consistent" when it is created from a
+ -- fully analyzed tree, where all attributes are available.
+
+ No_Representation);
+
+ -- The following type enumerates all possible target kinds
+
+ type Target_Kind is
+ (Generic_Target,
+ -- A generic unit being instantiated
+
+ Subprogram_Target,
+ -- An entry, operator, or subprogram being invoked, or aliased through
+ -- 'Access or 'Unrestricted_Access.
+
+ Task_Target,
+ -- A task being activated by an activation call
+
+ Variable_Target,
+ -- A variable being updated through an assignment statement, or read
+ -- through a variable reference.
+
+ No_Target);
+
+ -----------
+ -- Types --
+ -----------
+
+ procedure Destroy (NE : in out Node_Or_Entity_Id);
+ pragma Inline (Destroy);
+ -- Destroy node or entity NE
+
+ function Hash (NE : Node_Or_Entity_Id) return Bucket_Range_Type;
+ pragma Inline (Hash);
+ -- Obtain the hash value of key NE
+
+ -- The following is a general purpose list for nodes and entities
+
+ package NE_List is new Doubly_Linked_Lists
+ (Element_Type => Node_Or_Entity_Id,
+ "=" => "=",
+ Destroy_Element => Destroy);
+
+ -- The following is a general purpose map which relates nodes and entities
+ -- to lists of nodes and entities.
+
+ package NE_List_Map is new Dynamic_Hash_Tables
+ (Key_Type => Node_Or_Entity_Id,
+ Value_Type => NE_List.Doubly_Linked_List,
+ No_Value => NE_List.Nil,
+ Expansion_Threshold => 1.5,
+ Expansion_Factor => 2,
+ Compression_Threshold => 0.3,
+ Compression_Factor => 2,
+ "=" => "=",
+ Destroy_Value => NE_List.Destroy,
+ Hash => Hash);
+
+ -- The following is a general purpose membership set for nodes and entities
+
+ package NE_Set is new Membership_Sets
+ (Element_Type => Node_Or_Entity_Id,
+ "=" => "=",
+ Hash => Hash);
-- The following type captures relevant attributes which pertain to the
- -- state of the Processing phase.
+ -- in state of the Processing phase.
- type Processing_Attributes is record
- Suppress_Implicit_Pragmas : Boolean;
+ type Processing_In_State is record
+ Processing : Processing_Kind := No_Processing;
+ -- Operation mode of the Processing phase. Once set, this value should
+ -- not be changed.
+
+ Representation : Representation_Kind := No_Representation;
+ -- Required level of scenario and target representation. Once set, this
+ -- value should not be changed.
+
+ Suppress_Checks : Boolean := False;
+ -- This flag is set when the Processing phase must not generate any ABE
+ -- checks.
+
+ Suppress_Implicit_Pragmas : Boolean := False;
-- This flag is set when the Processing phase must not generate any
-- implicit Elaborate[_All] pragmas.
- Suppress_Warnings : Boolean;
+ Suppress_Info_Messages : Boolean := False;
+ -- This flag is set when the Processing phase must not emit any info
+ -- messages.
+
+ Suppress_Up_Level_Targets : Boolean := False;
+ -- This flag is set when the Processing phase must ignore up-level
+ -- targets.
+
+ Suppress_Warnings : Boolean := False;
-- This flag is set when the Processing phase must not emit any warnings
-- on elaboration problems.
- Within_Initial_Condition : Boolean;
- -- This flag is set when the Processing phase is currently examining a
- -- scenario which was reached from an initial condition procedure.
+ Traversal : Body_Traversal_Kind := No_Traversal;
+ -- The subprogram body traversal mode. Once set, this value should not
+ -- be changed.
+
+ Within_Generic : Boolean := False;
+ -- This flag is set when the Processing phase is currently within a
+ -- generic unit.
- Within_Instance : Boolean;
+ Within_Initial_Condition : Boolean := False;
-- This flag is set when the Processing phase is currently examining a
- -- scenario which was reached from a scenario defined in an instance.
+ -- scenario which was reached from an initial condition procedure.
- Within_Partial_Finalization : Boolean;
+ Within_Partial_Finalization : Boolean := False;
-- This flag is set when the Processing phase is currently examining a
-- scenario which was reached from a partial finalization procedure.
- Within_Task_Body : Boolean;
+ Within_Task_Body : Boolean := False;
-- This flag is set when the Processing phase is currently examining a
-- scenario which was reached from a task body.
end record;
- Initial_State : constant Processing_Attributes :=
- (Suppress_Implicit_Pragmas => False,
- Suppress_Warnings => False,
- Within_Initial_Condition => False,
- Within_Instance => False,
- Within_Partial_Finalization => False,
- Within_Task_Body => False);
+ -- The following constants define the various operational states of the
+ -- Processing phase.
- -- The following type captures relevant attributes which pertain to a
- -- target.
+ -- The conditional ABE state is used when processing scenarios that appear
+ -- at the declaration, instantiation, and library levels to detect errors
+ -- and install conditional ABE checks.
+
+ Conditional_ABE_State : constant Processing_In_State :=
+ (Processing => Conditional_ABE_Processing,
+ Representation => Consistent_Representation,
+ Traversal => Deep_Traversal,
+ others => False);
+
+ -- The dynamic model state is used to install conditional ABE checks when
+ -- switch -gnatE (dynamic elaboration checking mode enabled) is in effect.
+
+ Dynamic_Model_State : constant Processing_In_State :=
+ (Processing => Dynamic_Model_Processing,
+ Representation => Consistent_Representation,
+ Suppress_Implicit_Pragmas => True,
+ Suppress_Info_Messages => True,
+ Suppress_Up_Level_Targets => True,
+ Suppress_Warnings => True,
+ Traversal => No_Traversal,
+ others => False);
+
+ -- The guaranteed ABE state is used when processing scenarios that appear
+ -- at the declaration, instantiation, and library levels to detect errors
+ -- and install guarateed ABE failures.
+
+ Guaranteed_ABE_State : constant Processing_In_State :=
+ (Processing => Guaranteed_ABE_Processing,
+ Representation => Inconsistent_Representation,
+ Suppress_Implicit_Pragmas => True,
+ Traversal => No_Traversal,
+ others => False);
+
+ -- The invocation body state is used when processing scenarios that appear
+ -- at the body library level to encode paths that start from elaboration
+ -- code and ultimately reach into external units.
+
+ Invocation_Body_State : constant Processing_In_State :=
+ (Processing => Invocation_Body_Processing,
+ Representation => Consistent_Representation,
+ Suppress_Checks => True,
+ Suppress_Implicit_Pragmas => True,
+ Suppress_Info_Messages => True,
+ Suppress_Up_Level_Targets => True,
+ Suppress_Warnings => True,
+ Traversal => Deep_Traversal,
+ others => False);
+
+ -- The invocation construct state is used when processing constructs that
+ -- appear within the spec and body of the main unit and eventually reach
+ -- into external units.
+
+ Invocation_Construct_State : constant Processing_In_State :=
+ (Processing => Invocation_Construct_Processing,
+ Representation => Consistent_Representation,
+ Suppress_Checks => True,
+ Suppress_Implicit_Pragmas => True,
+ Suppress_Info_Messages => True,
+ Suppress_Up_Level_Targets => True,
+ Suppress_Warnings => True,
+ Traversal => Deep_Traversal,
+ others => False);
+
+ -- The invocation spec state is used when processing scenarios that appear
+ -- at the spec library level to encode paths that start from elaboration
+ -- code and ultimately reach into external units.
+
+ Invocation_Spec_State : constant Processing_In_State :=
+ (Processing => Invocation_Spec_Processing,
+ Representation => Consistent_Representation,
+ Suppress_Checks => True,
+ Suppress_Implicit_Pragmas => True,
+ Suppress_Info_Messages => True,
+ Suppress_Up_Level_Targets => True,
+ Suppress_Warnings => True,
+ Traversal => Deep_Traversal,
+ others => False);
+
+ -- The SPARK state is used when verying SPARK-specific semantics of certain
+ -- scenarios.
+
+ SPARK_State : constant Processing_In_State :=
+ (Processing => SPARK_Processing,
+ Representation => Consistent_Representation,
+ Traversal => No_Traversal,
+ others => False);
+
+ -- The following type identifies a scenario representation
+
+ type Scenario_Rep_Id is new Natural;
+
+ No_Scenario_Rep : constant Scenario_Rep_Id := Scenario_Rep_Id'First;
+ First_Scenario_Rep : constant Scenario_Rep_Id := No_Scenario_Rep + 1;
+
+ -- The following type identifies a target representation
+
+ type Target_Rep_Id is new Natural;
+
+ No_Target_Rep : constant Target_Rep_Id := Target_Rep_Id'First;
+ First_Target_Rep : constant Target_Rep_Id := No_Target_Rep + 1;
- type Target_Attributes is record
- Elab_Checks_OK : Boolean;
- -- This flag is set when the target has elaboration checks enabled
+ --------------
+ -- Services --
+ --------------
- Elab_Warnings_OK : Boolean;
- -- This flag is set when the target has elaboration warnings enabled
+ -- The following package keeps track of all active scenarios during a DFS
+ -- traversal.
- From_Source : Boolean;
- -- This flag is set when the target comes from source
+ package Active_Scenarios is
- Ghost_Mode_Ignore : Boolean;
- -- This flag is set when the target appears in a region subject to
- -- pragma Ghost with policy ignore, or starts one such region.
+ -----------
+ -- Types --
+ -----------
- SPARK_Mode_On : Boolean;
- -- This flag is set when the target appears in a region subject to
- -- pragma SPARK_Mode with value On, or starts one such region.
+ -- The following type defines the position within the active scenario
+ -- stack.
- Spec_Decl : Node_Id;
- -- This attribute denotes the declaration of Spec_Id
+ type Active_Scenario_Pos is new Natural;
- Unit_Id : Entity_Id;
- -- This attribute denotes the top unit where Spec_Id resides
+ ---------------------
+ -- Data structures --
+ ---------------------
- -- The semantics of the following attributes depend on the target
+ -- The following table stores all active scenarios in a DFS traversal.
+ -- This table must be maintained in a FIFO fashion.
+
+ package Active_Scenario_Stack is new Table.Table
+ (Table_Index_Type => Active_Scenario_Pos,
+ Table_Component_Type => Node_Id,
+ Table_Low_Bound => 1,
+ Table_Initial => 50,
+ Table_Increment => 200,
+ Table_Name => "Active_Scenario_Stack");
+
+ ---------
+ -- API --
+ ---------
+
+ procedure Output_Active_Scenarios
+ (Error_Nod : Node_Id;
+ In_State : Processing_In_State);
+ pragma Inline (Output_Active_Scenarios);
+ -- Output the contents of the active scenario stack from earliest to
+ -- latest to supplement an earlier error emitted for node Error_Nod.
+ -- In_State denotes the current state of the Processing phase.
+
+ procedure Pop_Active_Scenario (N : Node_Id);
+ pragma Inline (Pop_Active_Scenario);
+ -- Pop the top of the scenario stack. A check is made to ensure that the
+ -- scenario being removed is the same as N.
+
+ procedure Push_Active_Scenario (N : Node_Id);
+ pragma Inline (Push_Active_Scenario);
+ -- Push scenario N on top of the scenario stack
+
+ function Root_Scenario return Node_Id;
+ pragma Inline (Root_Scenario);
+ -- Return the scenario which started a DFS traversal
+
+ end Active_Scenarios;
+ use Active_Scenarios;
+
+ -- The following package provides the main entry point for task activation
+ -- processing.
- Body_Barf : Node_Id;
- Body_Decl : Node_Id;
- Spec_Id : Entity_Id;
+ package Activation_Processor is
+
+ -----------
+ -- Types --
+ -----------
+
+ type Activation_Processor_Ptr is access procedure
+ (Call : Node_Id;
+ Call_Rep : Scenario_Rep_Id;
+ Obj_Id : Entity_Id;
+ Obj_Rep : Target_Rep_Id;
+ Task_Typ : Entity_Id;
+ Task_Rep : Target_Rep_Id;
+ In_State : Processing_In_State);
+ -- Reference to a procedure that takes all attributes of an activation
+ -- and performs a desired action. Call is the activation call. Call_Rep
+ -- is the representation of the call. Obj_Id is the task object being
+ -- activated. Obj_Rep is the representation of the object. Task_Typ is
+ -- the task type whose body is being activated. Task_Rep denotes the
+ -- representation of the task type. In_State is the current state of
+ -- the Processing phase.
+
+ ---------
+ -- API --
+ ---------
+
+ procedure Process_Activation
+ (Call : Node_Id;
+ Call_Rep : Scenario_Rep_Id;
+ Processor : Activation_Processor_Ptr;
+ In_State : Processing_In_State);
+ -- Find all task objects activated by activation call Call and invoke
+ -- Processor on them. Call_Rep denotes the representation of the call.
+ -- In_State is the current state of the Processing phase.
+
+ end Activation_Processor;
+ use Activation_Processor;
+
+ -- The following package profides functionality for traversing subprogram
+ -- bodies in DFS manner and processing of eligible scenarios within.
+
+ package Body_Processor is
+
+ -----------
+ -- Types --
+ -----------
+
+ type Scenario_Predicate_Ptr is access function
+ (N : Node_Id) return Boolean;
+ -- Reference to a function which determines whether arbitrary node N
+ -- denotes a suitable scenario for processing.
+
+ type Scenario_Processor_Ptr is access procedure
+ (N : Node_Id; In_State : Processing_In_State);
+ -- Reference to a procedure which processes scenario N. In_State is the
+ -- current state of the Processing phase.
+
+ ---------
+ -- API --
+ ---------
+
+ procedure Traverse_Body
+ (N : Node_Id;
+ Requires_Processing : Scenario_Predicate_Ptr;
+ Processor : Scenario_Processor_Ptr;
+ In_State : Processing_In_State);
+ pragma Inline (Traverse_Body);
+ -- Traverse the declarations and handled statements of subprogram body
+ -- N, looking for scenarios that satisfy predicate Requires_Processing.
+ -- Routine Processor is invoked for each such scenario.
+
+ procedure Reset_Traversed_Bodies;
+ pragma Inline (Reset_Traversed_Bodies);
+ -- Reset the visited status of all subprogram bodies that have already
+ -- been processed by routine Traverse_Body.
- -- The target is a generic package or a subprogram
- --
- -- * Body_Barf - Empty
- --
- -- * Body_Decl - This attribute denotes the generic or subprogram
- -- body.
- --
- -- * Spec_Id - This attribute denotes the entity of the generic
- -- package or subprogram.
+ -----------------
+ -- Maintenance --
+ -----------------
- -- The target is a protected entry
- --
- -- * Body_Barf - This attribute denotes the body of the barrier
- -- function if expansion took place, otherwise it is Empty.
- --
- -- * Body_Decl - This attribute denotes the body of the procedure
- -- which emulates the entry if expansion took place, otherwise it
- -- denotes the body of the protected entry.
- --
- -- * Spec_Id - This attribute denotes the entity of the procedure
- -- which emulates the entry if expansion took place, otherwise it
- -- denotes the protected entry.
+ procedure Finalize_Body_Processor;
+ pragma Inline (Finalize_Body_Processor);
+ -- Finalize all internal data structures
+
+ procedure Initialize_Body_Processor;
+ pragma Inline (Initialize_Body_Processor);
+ -- Initialize all internal data structures
+
+ end Body_Processor;
+ use Body_Processor;
+
+ -- The following package provides functionality for installing ABE-related
+ -- checks and failures.
+
+ package Check_Installer is
+
+ ---------
+ -- API --
+ ---------
+
+ function Check_Or_Failure_Generation_OK return Boolean;
+ pragma Inline (Check_Or_Failure_Generation_OK);
+ -- Determine whether a conditional ABE check or guaranteed ABE failure
+ -- can be generated.
+
+ procedure Install_Dynamic_ABE_Checks;
+ pragma Inline (Install_Dynamic_ABE_Checks);
+ -- Install conditional ABE checks for all saved scenarios when the
+ -- dynamic model is in effect.
+
+ procedure Install_Scenario_ABE_Check
+ (N : Node_Id;
+ Targ_Id : Entity_Id;
+ Targ_Rep : Target_Rep_Id;
+ Disable : Scenario_Rep_Id);
+ pragma Inline (Install_Scenario_ABE_Check);
+ -- Install a conditional ABE check for scenario N to ensure that target
+ -- Targ_Id is properly elaborated. Targ_Rep is the representation of the
+ -- target. If the check is installed, disable the elaboration checks of
+ -- scenario Disable.
+
+ procedure Install_Scenario_ABE_Check
+ (N : Node_Id;
+ Targ_Id : Entity_Id;
+ Targ_Rep : Target_Rep_Id;
+ Disable : Target_Rep_Id);
+ pragma Inline (Install_Scenario_ABE_Check);
+ -- Install a conditional ABE check for scenario N to ensure that target
+ -- Targ_Id is properly elaborated. Targ_Rep is the representation of the
+ -- target. If the check is installed, disable the elaboration checks of
+ -- target Disable.
+
+ procedure Install_Scenario_ABE_Failure
+ (N : Node_Id;
+ Targ_Id : Entity_Id;
+ Targ_Rep : Target_Rep_Id;
+ Disable : Scenario_Rep_Id);
+ pragma Inline (Install_Scenario_ABE_Failure);
+ -- Install a guaranteed ABE failure for scenario N with target Targ_Id.
+ -- Targ_Rep denotes the representation of the target. If the failure is
+ -- installed, disable the elaboration checks of scenario Disable.
+
+ procedure Install_Scenario_ABE_Failure
+ (N : Node_Id;
+ Targ_Id : Entity_Id;
+ Targ_Rep : Target_Rep_Id;
+ Disable : Target_Rep_Id);
+ pragma Inline (Install_Scenario_ABE_Failure);
+ -- Install a guaranteed ABE failure for scenario N with target Targ_Id.
+ -- Targ_Rep denotes the representation of the target. If the failure is
+ -- installed, disable the elaboration checks of target Disable.
+
+ procedure Install_Unit_ABE_Check
+ (N : Node_Id;
+ Unit_Id : Entity_Id;
+ Disable : Scenario_Rep_Id);
+ pragma Inline (Install_Unit_ABE_Check);
+ -- Install a conditional ABE check for scenario N to ensure that unit
+ -- Unit_Id is properly elaborated. If the check is installed, disable
+ -- the elaboration checks of scenario Disable.
+
+ procedure Install_Unit_ABE_Check
+ (N : Node_Id;
+ Unit_Id : Entity_Id;
+ Disable : Target_Rep_Id);
+ pragma Inline (Install_Unit_ABE_Check);
+ -- Install a conditional ABE check for scenario N to ensure that unit
+ -- Unit_Id is properly elaborated. If the check is installed, disable
+ -- the elaboration checks of target Disable.
+
+ end Check_Installer;
+ use Check_Installer;
+
+ -- The following package provides the main entry point for conditional ABE
+ -- checks and diagnostics.
+
+ package Conditional_ABE_Processor is
+
+ ---------
+ -- API --
+ ---------
+
+ procedure Check_Conditional_ABE_Scenarios
+ (Iter : in out NE_Set.Iterator);
+ pragma Inline (Check_Conditional_ABE_Scenarios);
+ -- Perform conditional ABE checks and diagnostics for all scenarios
+ -- available through iterator Iter.
+
+ procedure Process_Conditional_ABE
+ (N : Node_Id;
+ In_State : Processing_In_State);
+ pragma Inline (Process_Conditional_ABE);
+ -- Perform conditional ABE checks and diagnostics for scenario N.
+ -- In_State denotes the current state of the Processing phase.
+
+ end Conditional_ABE_Processor;
+ use Conditional_ABE_Processor;
+
+ -- The following package provides functionality to emit errors, information
+ -- messages, and warnings.
+
+ package Diagnostics is
+
+ ---------
+ -- API --
+ ---------
+
+ procedure Elab_Msg_NE
+ (Msg : String;
+ N : Node_Id;
+ Id : Entity_Id;
+ Info_Msg : Boolean;
+ In_SPARK : Boolean);
+ pragma Inline (Elab_Msg_NE);
+ -- Wrapper around Error_Msg_NE. Emit message Msg concerning arbitrary
+ -- node N and entity. If flag Info_Msg is set, the routine emits an
+ -- information message, otherwise it emits an error. If flag In_SPARK
+ -- is set, then string " in SPARK" is added to the end of the message.
+
+ procedure Info_Call
+ (Call : Node_Id;
+ Subp_Id : Entity_Id;
+ Info_Msg : Boolean;
+ In_SPARK : Boolean);
+ pragma Inline (Info_Call);
+ -- Output information concerning call Call that invokes subprogram
+ -- Subp_Id. When flag Info_Msg is set, the routine emits an information
+ -- message, otherwise it emits an error. When flag In_SPARK is set, " in
+ -- SPARK" is added to the end of the message.
+
+ procedure Info_Instantiation
+ (Inst : Node_Id;
+ Gen_Id : Entity_Id;
+ Info_Msg : Boolean;
+ In_SPARK : Boolean);
+ pragma Inline (Info_Instantiation);
+ -- Output information concerning instantiation Inst which instantiates
+ -- generic unit Gen_Id. If flag Info_Msg is set, the routine emits an
+ -- information message, otherwise it emits an error. If flag In_SPARK
+ -- is set, then string " in SPARK" is added to the end of the message.
+
+ procedure Info_Variable_Reference
+ (Ref : Node_Id;
+ Var_Id : Entity_Id;
+ Info_Msg : Boolean;
+ In_SPARK : Boolean);
+ pragma Inline (Info_Variable_Reference);
+ -- Output information concerning reference Ref which mentions variable
+ -- Var_Id. If flag Info_Msg is set, the routine emits an information
+ -- message, otherwise it emits an error. If flag In_SPARK is set, then
+ -- string " in SPARK" is added to the end of the message.
+
+ end Diagnostics;
+ use Diagnostics;
+
+ -- The following package provides functionality to locate the early call
+ -- region of a subprogram body.
+
+ package Early_Call_Region_Processor is
+
+ ---------
+ -- API --
+ ---------
+
+ function Find_Early_Call_Region
+ (Body_Decl : Node_Id;
+ Assume_Elab_Body : Boolean := False;
+ Skip_Memoization : Boolean := False) return Node_Id;
+ pragma Inline (Find_Early_Call_Region);
+ -- Find the start of the early call region that belongs to subprogram
+ -- body Body_Decl as defined in SPARK RM 7.7. This routine finds the
+ -- early call region, memoizes it, and returns it, but this behavior
+ -- can be altered. Flag Assume_Elab_Body should be set when a package
+ -- spec may lack pragma Elaborate_Body, but the routine must still
+ -- examine that spec. Flag Skip_Memoization should be set when the
+ -- routine must avoid memoizing the region.
+
+ -----------------
+ -- Maintenance --
+ -----------------
+
+ procedure Finalize_Early_Call_Region_Processor;
+ pragma Inline (Finalize_Early_Call_Region_Processor);
+ -- Finalize all internal data structures
- -- The target is a protected subprogram
+ procedure Initialize_Early_Call_Region_Processor;
+ pragma Inline (Initialize_Early_Call_Region_Processor);
+ -- Initialize all internal data structures
+
+ end Early_Call_Region_Processor;
+ use Early_Call_Region_Processor;
+
+ -- The following package provides access to the elaboration statuses of all
+ -- units withed by the main unit.
+
+ package Elaborated_Units is
+
+ ---------
+ -- API --
+ ---------
+
+ procedure Collect_Elaborated_Units;
+ pragma Inline (Collect_Elaborated_Units);
+ -- Save the elaboration statuses of all units withed by the main unit
+
+ procedure Ensure_Prior_Elaboration
+ (N : Node_Id;
+ Unit_Id : Entity_Id;
+ Prag_Nam : Name_Id;
+ In_State : Processing_In_State);
+ pragma Inline (Ensure_Prior_Elaboration);
+ -- Guarantee the elaboration of unit Unit_Id with respect to the main
+ -- unit by either suggesting or installing an Elaborate[_All] pragma
+ -- denoted by Prag_Nam. N denotes the related scenario. In_State is the
+ -- current state of the Processing phase.
+
+ function Has_Prior_Elaboration
+ (Unit_Id : Entity_Id;
+ Context_OK : Boolean := False;
+ Elab_Body_OK : Boolean := False;
+ Same_Unit_OK : Boolean := False) return Boolean;
+ pragma Inline (Has_Prior_Elaboration);
+ -- Determine whether unit Unit_Id is elaborated prior to the main unit.
+ -- If flag Context_OK is set, the routine considers the following case
+ -- as valid prior elaboration:
--
- -- * Body_Barf - Empty
+ -- * Unit_Id is in the elaboration context of the main unit
--
- -- * Body_Decl - This attribute denotes the body of the protected or
- -- unprotected version of the protected subprogram if expansion took
- -- place, otherwise it denotes the body of the protected subprogram.
+ -- If flag Elab_Body_OK is set, the routine considers the following case
+ -- as valid prior elaboration:
--
- -- * Spec_Id - This attribute denotes the entity of the protected or
- -- unprotected version of the protected subprogram if expansion took
- -- place, otherwise it is the entity of the protected subprogram.
-
- -- The target is a task entry
+ -- * Unit_Id has pragma Elaborate_Body and is not the main unit
--
- -- * Body_Barf - Empty
+ -- If flag Same_Unit_OK is set, the routine considers the following
+ -- cases as valid prior elaboration:
--
- -- * Body_Decl - This attribute denotes the body of the procedure
- -- which emulates the task body if expansion took place, otherwise
- -- it denotes the body of the task type.
+ -- * Unit_Id is the main unit
--
- -- * Spec_Id - This attribute denotes the entity of the procedure
- -- which emulates the task body if expansion took place, otherwise
- -- it denotes the entity of the task type.
- end record;
+ -- * Unit_Id denotes the spec of the main unit body
+
+ procedure Meet_Elaboration_Requirement
+ (N : Node_Id;
+ Targ_Id : Entity_Id;
+ Req_Nam : Name_Id;
+ In_State : Processing_In_State);
+ pragma Inline (Meet_Elaboration_Requirement);
+ -- Determine whether elaboration requirement Req_Nam for scenario N with
+ -- target Targ_Id is met by the context of the main unit using the SPARK
+ -- rules. Req_Nam must denote either Elaborate or Elaborate_All. Emit an
+ -- error if this is not the case. In_State denotes the current state of
+ -- the Processing phase.
- -- The following type captures relevant attributes which pertain to a task
- -- type.
+ -----------------
+ -- Maintenance --
+ -----------------
- type Task_Attributes is record
- Body_Decl : Node_Id;
- -- This attribute denotes the declaration of the procedure body which
- -- emulates the behaviour of the task body.
+ procedure Finalize_Elaborated_Units;
+ pragma Inline (Finalize_Elaborated_Units);
+ -- Finalize all internal data structures
- Elab_Checks_OK : Boolean;
- -- This flag is set when the task type has elaboration checks enabled
+ procedure Initialize_Elaborated_Units;
+ pragma Inline (Initialize_Elaborated_Units);
+ -- Initialize all internal data structures
- Elab_Warnings_OK : Boolean;
- -- This flag is set when the task type has elaboration warnings enabled
+ end Elaborated_Units;
+ use Elaborated_Units;
- Ghost_Mode_Ignore : Boolean;
- -- This flag is set when the task type appears in a region subject to
- -- pragma Ghost with policy ignore, or starts one such region.
+ -- The following package provides the main entry point for guaranteed ABE
+ -- checks and diagnostics.
- SPARK_Mode_On : Boolean;
- -- This flag is set when the task type appears in a region subject to
- -- pragma SPARK_Mode with value On, or starts one such region.
+ package Guaranteed_ABE_Processor is
- Spec_Id : Entity_Id;
- -- This attribute denotes the entity of the initial declaration of the
- -- procedure body which emulates the behaviour of the task body.
+ ---------
+ -- API --
+ ---------
- Task_Decl : Node_Id;
- -- This attribute denotes the declaration of the task type
+ procedure Process_Guaranteed_ABE
+ (N : Node_Id;
+ In_State : Processing_In_State);
+ pragma Inline (Process_Guaranteed_ABE);
+ -- Perform guaranteed ABE checks and diagnostics for scenario N.
+ -- In_State is the current state of the Processing phase.
- Unit_Id : Entity_Id;
- -- This attribute denotes the entity of the compilation unit where the
- -- task type resides.
- end record;
+ end Guaranteed_ABE_Processor;
+ use Guaranteed_ABE_Processor;
- -- The following type captures relevant attributes which pertain to a
- -- variable.
+ -- The following package provides access to the internal representation of
+ -- scenarios and targets.
- type Variable_Attributes is record
- Unit_Id : Entity_Id;
- -- This attribute denotes the entity of the compilation unit where the
- -- variable resides.
- end record;
+ package Internal_Representation is
- ---------------------
- -- Data structures --
- ---------------------
+ -----------
+ -- Types --
+ -----------
+
+ -- The following type enumerates all possible Ghost mode mode kinds
+
+ type Extended_Ghost_Mode is
+ (Is_Ignored,
+ Is_Checked_Or_Not_Specified);
+
+ -- The following type enumerates all possible SPARK mode kinds
+
+ type Extended_SPARK_Mode is
+ (Is_On,
+ Is_Off_Or_Not_Specified);
- -- The ABE mechanism employs lists and hash tables to store information
- -- pertaining to scenarios and targets, as well as the Processing phase.
- -- The need for data structures comes partly from the size limitation of
- -- nodes. Note that the use of hash tables is conservative and operations
- -- are carried out only when a particular hash table has at least one key
- -- value pair (see xxx_In_Use flags).
+ --------------
+ -- Builders --
+ --------------
- -- The following table stores the early call regions of subprogram bodies
+ function Scenario_Representation_Of
+ (N : Node_Id;
+ In_State : Processing_In_State) return Scenario_Rep_Id;
+ pragma Inline (Scenario_Representation_Of);
+ -- Obtain the id of elaboration scenario N's representation. The routine
+ -- constructs the representation if it is not available. In_State is the
+ -- current state of the Processing phase.
+
+ function Target_Representation_Of
+ (Id : Entity_Id;
+ In_State : Processing_In_State) return Target_Rep_Id;
+ pragma Inline (Target_Representation_Of);
+ -- Obtain the id of elaboration target Id's representation. The routine
+ -- constructs the representation if it is not available. In_State is the
+ -- current state of the Processing phase.
- Early_Call_Regions_Max : constant := 101;
+ -------------------------
+ -- Scenario attributes --
+ -------------------------
- type Early_Call_Regions_Index is range 0 .. Early_Call_Regions_Max - 1;
+ function Activated_Task_Objects
+ (S_Id : Scenario_Rep_Id) return NE_List.Doubly_Linked_List;
+ pragma Inline (Activated_Task_Objects);
+ -- For Task_Activation_Scenario S_Id, obtain the list of task objects
+ -- the scenario is activating.
+
+ function Activated_Task_Type (S_Id : Scenario_Rep_Id) return Entity_Id;
+ pragma Inline (Activated_Task_Type);
+ -- For Task_Activation_Scenario S_Id, obtain the currently activated
+ -- task type.
+
+ procedure Disable_Elaboration_Checks (S_Id : Scenario_Rep_Id);
+ pragma Inline (Disable_Elaboration_Checks);
+ -- Disable elaboration checks of scenario S_Id
+
+ function Elaboration_Checks_OK (S_Id : Scenario_Rep_Id) return Boolean;
+ pragma Inline (Elaboration_Checks_OK);
+ -- Determine whether scenario S_Id may be subjected to elaboration
+ -- checks.
+
+ function Elaboration_Warnings_OK (S_Id : Scenario_Rep_Id) return Boolean;
+ pragma Inline (Elaboration_Warnings_OK);
+ -- Determine whether scenario S_Id may be subjected to elaboration
+ -- warnings.
+
+ function Ghost_Mode_Of
+ (S_Id : Scenario_Rep_Id) return Extended_Ghost_Mode;
+ pragma Inline (Ghost_Mode_Of);
+ -- Obtain the Ghost mode of scenario S_Id
+
+ function Is_Dispatching_Call (S_Id : Scenario_Rep_Id) return Boolean;
+ pragma Inline (Is_Dispatching_Call);
+ -- For Call_Scenario S_Id, determine whether the call is dispatching
+
+ function Is_Read_Reference (S_Id : Scenario_Rep_Id) return Boolean;
+ pragma Inline (Is_Read_Reference);
+ -- For Variable_Reference_Scenario S_Id, determine whether the reference
+ -- is a read.
+
+ function Kind (S_Id : Scenario_Rep_Id) return Scenario_Kind;
+ pragma Inline (Kind);
+ -- Obtain the nature of scenario S_Id
+
+ function Level (S_Id : Scenario_Rep_Id) return Enclosing_Level_Kind;
+ pragma Inline (Level);
+ -- Obtain the enclosing level of scenario S_Id
+
+ procedure Set_Activated_Task_Objects
+ (S_Id : Scenario_Rep_Id;
+ Task_Objs : NE_List.Doubly_Linked_List);
+ pragma Inline (Set_Activated_Task_Objects);
+ -- For Task_Activation_Scenario S_Id, set the list of task objects
+ -- activated by the scenario to Task_Objs.
+
+ procedure Set_Activated_Task_Type
+ (S_Id : Scenario_Rep_Id;
+ Task_Typ : Entity_Id);
+ pragma Inline (Set_Activated_Task_Type);
+ -- For Task_Activation_Scenario S_Id, set the currently activated task
+ -- type to Task_Typ.
+
+ function SPARK_Mode_Of
+ (S_Id : Scenario_Rep_Id) return Extended_SPARK_Mode;
+ pragma Inline (SPARK_Mode_Of);
+ -- Obtain the SPARK mode of scenario S_Id
+
+ function Target (S_Id : Scenario_Rep_Id) return Entity_Id;
+ pragma Inline (Target);
+ -- Obtain the target of scenario S_Id
- function Early_Call_Regions_Hash
- (Key : Entity_Id) return Early_Call_Regions_Index;
- -- Obtain the hash value of entity Key
+ -----------------------
+ -- Target attributes --
+ -----------------------
- Early_Call_Regions_In_Use : Boolean := False;
- -- This flag determines whether table Early_Call_Regions contains at least
- -- least one key/value pair.
+ function Barrier_Body_Declaration (T_Id : Target_Rep_Id) return Node_Id;
+ pragma Inline (Barrier_Body_Declaration);
+ -- For Subprogram_Target T_Id, obtain the declaration of the barrier
+ -- function's body.
- Early_Call_Regions_No_Element : constant Node_Id := Empty;
+ function Body_Declaration (T_Id : Target_Rep_Id) return Node_Id;
+ pragma Inline (Body_Declaration);
+ -- Obtain the declaration of the body which belongs to target T_Id
- package Early_Call_Regions is new Simple_HTable
- (Header_Num => Early_Call_Regions_Index,
- Element => Node_Id,
- No_Element => Early_Call_Regions_No_Element,
- Key => Entity_Id,
- Hash => Early_Call_Regions_Hash,
- Equal => "=");
+ procedure Disable_Elaboration_Checks (T_Id : Target_Rep_Id);
+ pragma Inline (Disable_Elaboration_Checks);
+ -- Disable elaboration checks of target T_Id
- -- The following table stores the elaboration status of all units withed by
- -- the main unit.
+ function Elaboration_Checks_OK (T_Id : Target_Rep_Id) return Boolean;
+ pragma Inline (Elaboration_Checks_OK);
+ -- Determine whether target T_Id may be subjected to elaboration checks
- Elaboration_Statuses_Max : constant := 1009;
+ function Elaboration_Warnings_OK (T_Id : Target_Rep_Id) return Boolean;
+ pragma Inline (Elaboration_Warnings_OK);
+ -- Determine whether target T_Id may be subjected to elaboration
+ -- warnings.
- type Elaboration_Statuses_Index is range 0 .. Elaboration_Statuses_Max - 1;
+ function Ghost_Mode_Of (T_Id : Target_Rep_Id) return Extended_Ghost_Mode;
+ pragma Inline (Ghost_Mode_Of);
+ -- Obtain the Ghost mode of target T_Id
- function Elaboration_Statuses_Hash
- (Key : Entity_Id) return Elaboration_Statuses_Index;
- -- Obtain the hash value of entity Key
+ function Kind (T_Id : Target_Rep_Id) return Target_Kind;
+ pragma Inline (Kind);
+ -- Obtain the nature of target T_Id
- Elaboration_Statuses_In_Use : Boolean := False;
- -- This flag flag determines whether table Elaboration_Statuses contains at
- -- least one key/value pair.
+ function SPARK_Mode_Of (T_Id : Target_Rep_Id) return Extended_SPARK_Mode;
+ pragma Inline (SPARK_Mode_Of);
+ -- Obtain the SPARK mode of target T_Id
- Elaboration_Statuses_No_Element : constant Elaboration_Attributes :=
- No_Elaboration_Attributes;
+ function Spec_Declaration (T_Id : Target_Rep_Id) return Node_Id;
+ pragma Inline (Spec_Declaration);
+ -- Obtain the declaration of the spec which belongs to target T_Id
- package Elaboration_Statuses is new Simple_HTable
- (Header_Num => Elaboration_Statuses_Index,
- Element => Elaboration_Attributes,
- No_Element => Elaboration_Statuses_No_Element,
- Key => Entity_Id,
- Hash => Elaboration_Statuses_Hash,
- Equal => "=");
+ function Unit (T_Id : Target_Rep_Id) return Entity_Id;
+ pragma Inline (Unit);
+ -- Obtain the unit where the target is defined
- -- The following table stores a status flag for each SPARK scenario saved
- -- in table SPARK_Scenarios.
+ function Variable_Declaration (T_Id : Target_Rep_Id) return Node_Id;
+ pragma Inline (Variable_Declaration);
+ -- For Variable_Target T_Id, obtain the declaration of the variable
- Recorded_SPARK_Scenarios_Max : constant := 127;
+ -----------------
+ -- Maintenance --
+ -----------------
- type Recorded_SPARK_Scenarios_Index is
- range 0 .. Recorded_SPARK_Scenarios_Max - 1;
+ procedure Finalize_Internal_Representation;
+ pragma Inline (Finalize_Internal_Representation);
+ -- Finalize all internal data structures
- function Recorded_SPARK_Scenarios_Hash
- (Key : Node_Id) return Recorded_SPARK_Scenarios_Index;
- -- Obtain the hash value of Key
+ procedure Initialize_Internal_Representation;
+ pragma Inline (Initialize_Internal_Representation);
+ -- Initialize all internal data structures
- Recorded_SPARK_Scenarios_In_Use : Boolean := False;
- -- This flag flag determines whether table Recorded_SPARK_Scenarios
- -- contains at least one key/value pair.
+ end Internal_Representation;
+ use Internal_Representation;
- Recorded_SPARK_Scenarios_No_Element : constant Boolean := False;
+ -- The following package provides functionality for recording pieces of the
+ -- invocation graph in the ALI file of the main unit.
- package Recorded_SPARK_Scenarios is new Simple_HTable
- (Header_Num => Recorded_SPARK_Scenarios_Index,
- Element => Boolean,
- No_Element => Recorded_SPARK_Scenarios_No_Element,
- Key => Node_Id,
- Hash => Recorded_SPARK_Scenarios_Hash,
- Equal => "=");
+ package Invocation_Graph is
- -- The following table stores a status flag for each top-level scenario
- -- recorded in table Top_Level_Scenarios.
+ ---------
+ -- API --
+ ---------
- Recorded_Top_Level_Scenarios_Max : constant := 503;
+ procedure Record_Invocation_Graph;
+ pragma Inline (Record_Invocation_Graph);
+ -- Process all declaration, instantiation, and library level scenarios,
+ -- along with invocation construct within the spec and body of the main
+ -- unit to determine whether any of these reach into an external unit.
+ -- If such a path exists, encode in the ALI file of the main unit.
- type Recorded_Top_Level_Scenarios_Index is
- range 0 .. Recorded_Top_Level_Scenarios_Max - 1;
+ -----------------
+ -- Maintenance --
+ -----------------
- function Recorded_Top_Level_Scenarios_Hash
- (Key : Node_Id) return Recorded_Top_Level_Scenarios_Index;
- -- Obtain the hash value of entity Key
+ procedure Finalize_Invocation_Graph;
+ pragma Inline (Finalize_Invocation_Graph);
+ -- Finalize all internal data structures
- Recorded_Top_Level_Scenarios_In_Use : Boolean := False;
- -- This flag flag determines whether table Recorded_Top_Level_Scenarios
- -- contains at least one key/value pair.
+ procedure Initialize_Invocation_Graph;
+ pragma Inline (Initialize_Invocation_Graph);
+ -- Initialize all internal data structures
- Recorded_Top_Level_Scenarios_No_Element : constant Boolean := False;
+ end Invocation_Graph;
+ use Invocation_Graph;
- package Recorded_Top_Level_Scenarios is new Simple_HTable
- (Header_Num => Recorded_Top_Level_Scenarios_Index,
- Element => Boolean,
- No_Element => Recorded_Top_Level_Scenarios_No_Element,
- Key => Node_Id,
- Hash => Recorded_Top_Level_Scenarios_Hash,
- Equal => "=");
+ -- The following package stores scenarios
- -- The following table stores all active scenarios in a recursive traversal
- -- starting from a top-level scenario. This table must be maintained in a
- -- FIFO fashion.
+ package Scenario_Storage is
- package Scenario_Stack is new Table.Table
- (Table_Component_Type => Node_Id,
- Table_Index_Type => Int,
- Table_Low_Bound => 1,
- Table_Initial => 50,
- Table_Increment => 100,
- Table_Name => "Scenario_Stack");
+ ---------
+ -- API --
+ ---------
- -- The following table stores SPARK scenarios which are not necessarily
- -- executable during elaboration, but still require elaboration-related
- -- checks.
+ procedure Add_Declaration_Scenario (N : Node_Id);
+ pragma Inline (Add_Declaration_Scenario);
+ -- Save declaration level scenario N
- package SPARK_Scenarios is new Table.Table
- (Table_Component_Type => Node_Id,
- Table_Index_Type => Int,
- Table_Low_Bound => 1,
- Table_Initial => 50,
- Table_Increment => 100,
- Table_Name => "SPARK_Scenarios");
+ procedure Add_Dynamic_ABE_Check_Scenario (N : Node_Id);
+ pragma Inline (Add_Dynamic_ABE_Check_Scenario);
+ -- Save scenario N for conditional ABE check installation purposes when
+ -- the dynamic model is in effect.
- -- The following table stores all top-level scenario saved during the
- -- Recording phase. The contents of this table act as traversal roots
- -- later in the Processing phase. This table must be maintained in a
- -- LIFO fashion.
+ procedure Add_Library_Body_Scenario (N : Node_Id);
+ pragma Inline (Add_Library_Body_Scenario);
+ -- Save library-level body scenario N
- package Top_Level_Scenarios is new Table.Table
- (Table_Component_Type => Node_Id,
- Table_Index_Type => Int,
- Table_Low_Bound => 1,
- Table_Initial => 1000,
- Table_Increment => 100,
- Table_Name => "Top_Level_Scenarios");
+ procedure Add_Library_Spec_Scenario (N : Node_Id);
+ pragma Inline (Add_Library_Spec_Scenario);
+ -- Save library-level spec scenario N
+
+ procedure Add_SPARK_Scenario (N : Node_Id);
+ pragma Inline (Add_SPARK_Scenario);
+ -- Save SPARK scenario N
+
+ procedure Delete_Scenario (N : Node_Id);
+ pragma Inline (Delete_Scenario);
+ -- Delete arbitrary scenario N
+
+ function Iterate_Declaration_Scenarios return NE_Set.Iterator;
+ pragma Inline (Iterate_Declaration_Scenarios);
+ -- Obtain an iterator over all declaration level scenarios
+
+ function Iterate_Dynamic_ABE_Check_Scenarios return NE_Set.Iterator;
+ pragma Inline (Iterate_Dynamic_ABE_Check_Scenarios);
+ -- Obtain an iterator over all scenarios that require a conditional ABE
+ -- check when the dynamic model is in effect.
+
+ function Iterate_Library_Body_Scenarios return NE_Set.Iterator;
+ pragma Inline (Iterate_Library_Body_Scenarios);
+ -- Obtain an iterator over all library level body scenarios
+
+ function Iterate_Library_Spec_Scenarios return NE_Set.Iterator;
+ pragma Inline (Iterate_Library_Spec_Scenarios);
+ -- Obtain an iterator over all library level spec scenarios
+
+ function Iterate_SPARK_Scenarios return NE_Set.Iterator;
+ pragma Inline (Iterate_SPARK_Scenarios);
+ -- Obtain an iterator over all SPARK scenarios
+
+ procedure Replace_Scenario (Old_N : Node_Id; New_N : Node_Id);
+ pragma Inline (Replace_Scenario);
+ -- Replace scenario Old_N with scenario New_N
+
+ -----------------
+ -- Maintenance --
+ -----------------
+
+ procedure Finalize_Scenario_Storage;
+ pragma Inline (Finalize_Scenario_Storage);
+ -- Finalize all internal data structures
+
+ procedure Initialize_Scenario_Storage;
+ pragma Inline (Initialize_Scenario_Storage);
+ -- Initialize all internal data structures
+
+ end Scenario_Storage;
+ use Scenario_Storage;
+
+ -- The following package provides various semantic predicates
+
+ package Semantics is
+
+ ---------
+ -- API --
+ ---------
+
+ function Is_Accept_Alternative_Proc (Id : Entity_Id) return Boolean;
+ pragma Inline (Is_Accept_Alternative_Proc);
+ -- Determine whether arbitrary entity Id denotes an internally generated
+ -- procedure which encapsulates the statements of an accept alternative.
+
+ function Is_Activation_Proc (Id : Entity_Id) return Boolean;
+ pragma Inline (Is_Activation_Proc);
+ -- Determine whether arbitrary entity Id denotes a runtime procedure in
+ -- charge with activating tasks.
+
+ function Is_Ada_Semantic_Target (Id : Entity_Id) return Boolean;
+ pragma Inline (Is_Ada_Semantic_Target);
+ -- Determine whether arbitrary entity Id denodes a source or internally
+ -- generated subprogram which emulates Ada semantics.
- -- The following table stores the bodies of all eligible scenarios visited
- -- during a traversal starting from a top-level scenario. The contents of
- -- this table must be reset upon each new traversal.
+ function Is_Assertion_Pragma_Target (Id : Entity_Id) return Boolean;
+ pragma Inline (Is_Assertion_Pragma_Target);
+ -- Determine whether arbitrary entity Id denotes a procedure which
+ -- varifies the run-time semantics of an assertion pragma.
- Visited_Bodies_Max : constant := 511;
+ function Is_Bodiless_Subprogram (Subp_Id : Entity_Id) return Boolean;
+ pragma Inline (Is_Bodiless_Subprogram);
+ -- Determine whether subprogram Subp_Id will never have a body
- type Visited_Bodies_Index is range 0 .. Visited_Bodies_Max - 1;
+ function Is_Bridge_Target (Id : Entity_Id) return Boolean;
+ pragma Inline (Is_Bridge_Target);
+ -- Determine whether arbitrary entity Id denotes a bridge target
- function Visited_Bodies_Hash (Key : Node_Id) return Visited_Bodies_Index;
- -- Obtain the hash value of node Key
+ function Is_Controlled_Proc
+ (Subp_Id : Entity_Id;
+ Subp_Nam : Name_Id) return Boolean;
+ pragma Inline (Is_Controlled_Proc);
+ -- Determine whether subprogram Subp_Id denotes controlled type
+ -- primitives Adjust, Finalize, or Initialize as denoted by name
+ -- Subp_Nam.
+
+ function Is_Default_Initial_Condition_Proc
+ (Id : Entity_Id) return Boolean;
+ pragma Inline (Is_Default_Initial_Condition_Proc);
+ -- Determine whether arbitrary entity Id denotes internally generated
+ -- routine Default_Initial_Condition.
+
+ function Is_Finalizer_Proc (Id : Entity_Id) return Boolean;
+ pragma Inline (Is_Finalizer_Proc);
+ -- Determine whether arbitrary entity Id denotes internally generated
+ -- routine _Finalizer.
+
+ function Is_Initial_Condition_Proc (Id : Entity_Id) return Boolean;
+ pragma Inline (Is_Initial_Condition_Proc);
+ -- Determine whether arbitrary entity Id denotes internally generated
+ -- routine Initial_Condition.
+
+ function Is_Initialized (Obj_Decl : Node_Id) return Boolean;
+ pragma Inline (Is_Initialized);
+ -- Determine whether object declaration Obj_Decl is initialized
+
+ function Is_Invariant_Proc (Id : Entity_Id) return Boolean;
+ pragma Inline (Is_Invariant_Proc);
+ -- Determine whether arbitrary entity Id denotes an invariant procedure
+
+ function Is_Non_Library_Level_Encapsulator (N : Node_Id) return Boolean;
+ pragma Inline (Is_Non_Library_Level_Encapsulator);
+ -- Determine whether arbitrary node N is a non-library encapsulator
+
+ function Is_Partial_Invariant_Proc (Id : Entity_Id) return Boolean;
+ pragma Inline (Is_Partial_Invariant_Proc);
+ -- Determine whether arbitrary entity Id denotes a partial invariant
+ -- procedure.
- Visited_Bodies_In_Use : Boolean := False;
- -- This flag determines whether table Visited_Bodies contains at least one
- -- key/value pair.
+ function Is_Postconditions_Proc (Id : Entity_Id) return Boolean;
+ pragma Inline (Is_Postconditions_Proc);
+ -- Determine whether arbitrary entity Id denotes internally generated
+ -- routine _Postconditions.
- Visited_Bodies_No_Element : constant Boolean := False;
+ function Is_Preelaborated_Unit (Id : Entity_Id) return Boolean;
+ pragma Inline (Is_Preelaborated_Unit);
+ -- Determine whether arbitrary entity Id denotes a unit which is subject
+ -- to one of the following pragmas:
+ --
+ -- * Preelaborable
+ -- * Pure
+ -- * Remote_Call_Interface
+ -- * Remote_Types
+ -- * Shared_Passive
+
+ function Is_Protected_Entry (Id : Entity_Id) return Boolean;
+ pragma Inline (Is_Protected_Entry);
+ -- Determine whether arbitrary entity Id denotes a protected entry
+
+ function Is_Protected_Subp (Id : Entity_Id) return Boolean;
+ pragma Inline (Is_Protected_Subp);
+ -- Determine whether entity Id denotes a protected subprogram
+
+ function Is_Protected_Body_Subp (Id : Entity_Id) return Boolean;
+ pragma Inline (Is_Protected_Body_Subp);
+ -- Determine whether entity Id denotes the protected or unprotected
+ -- version of a protected subprogram.
+
+ function Is_Scenario (N : Node_Id) return Boolean;
+ pragma Inline (Is_Scenario);
+ -- Determine whether attribute node N denotes a scenario. The scenario
+ -- may not necessarily be eligible for ABE processing.
+
+ function Is_SPARK_Semantic_Target (Id : Entity_Id) return Boolean;
+ pragma Inline (Is_SPARK_Semantic_Target);
+ -- Determine whether arbitrary entity Id nodes a source or internally
+ -- generated subprogram which emulates SPARK semantics.
+
+ function Is_Subprogram_Inst (Id : Entity_Id) return Boolean;
+ pragma Inline (Is_Subprogram_Inst);
+ -- Determine whether arbitrary entity Id denotes a subprogram instance
+
+ function Is_Suitable_Access_Taken (N : Node_Id) return Boolean;
+ pragma Inline (Is_Suitable_Access_Taken);
+ -- Determine whether arbitrary node N denotes a suitable attribute for
+ -- ABE processing.
+
+ function Is_Suitable_Call (N : Node_Id) return Boolean;
+ pragma Inline (Is_Suitable_Call);
+ -- Determine whether arbitrary node N denotes a suitable call for ABE
+ -- processing.
- package Visited_Bodies is new Simple_HTable
- (Header_Num => Visited_Bodies_Index,
- Element => Boolean,
- No_Element => Visited_Bodies_No_Element,
- Key => Node_Id,
- Hash => Visited_Bodies_Hash,
- Equal => "=");
+ function Is_Suitable_Instantiation (N : Node_Id) return Boolean;
+ pragma Inline (Is_Suitable_Instantiation);
+ -- Determine whether arbitrary node N is a suitable instantiation for
+ -- ABE processing.
+
+ function Is_Suitable_SPARK_Derived_Type (N : Node_Id) return Boolean;
+ pragma Inline (Is_Suitable_SPARK_Derived_Type);
+ -- Determine whether arbitrary node N denotes a suitable derived type
+ -- declaration for ABE processing using the SPARK rules.
+
+ function Is_Suitable_SPARK_Instantiation (N : Node_Id) return Boolean;
+ pragma Inline (Is_Suitable_SPARK_Instantiation);
+ -- Determine whether arbitrary node N denotes a suitable instantiation
+ -- for ABE processing using the SPARK rules.
+
+ function Is_Suitable_SPARK_Refined_State_Pragma
+ (N : Node_Id) return Boolean;
+ pragma Inline (Is_Suitable_SPARK_Refined_State_Pragma);
+ -- Determine whether arbitrary node N denotes a suitable Refined_State
+ -- pragma for ABE processing using the SPARK rules.
+
+ function Is_Suitable_Variable_Assignment (N : Node_Id) return Boolean;
+ pragma Inline (Is_Suitable_Variable_Assignment);
+ -- Determine whether arbitrary node N denotes a suitable assignment for
+ -- ABE processing.
+
+ function Is_Suitable_Variable_Reference (N : Node_Id) return Boolean;
+ pragma Inline (Is_Suitable_Variable_Reference);
+ -- Determine whether arbitrary node N is a suitable variable reference
+ -- for ABE processing.
+
+ function Is_Task_Entry (Id : Entity_Id) return Boolean;
+ pragma Inline (Is_Task_Entry);
+ -- Determine whether arbitrary entity Id denotes a task entry
+
+ function Is_Up_Level_Target
+ (Targ_Decl : Node_Id;
+ In_State : Processing_In_State) return Boolean;
+ pragma Inline (Is_Up_Level_Target);
+ -- Determine whether the current root resides at the declaration level.
+ -- If this is the case, determine whether a target with by declaration
+ -- Target_Decl is within a context which encloses the current root or is
+ -- in a different unit. In_State is the current state of the Processing
+ -- phase.
+
+ end Semantics;
+ use Semantics;
+
+ -- The following package provides the main entry point for SPARK-related
+ -- checks and diagnostics.
+
+ package SPARK_Processor is
+
+ ---------
+ -- API --
+ ---------
+
+ procedure Check_SPARK_Model_In_Effect;
+ pragma Inline (Check_SPARK_Model_In_Effect);
+ -- Determine whether a suitable elaboration model is currently in effect
+ -- for verifying SPARK rules. Emit a warning if this is not the case.
+
+ procedure Check_SPARK_Scenarios;
+ pragma Inline (Check_SPARK_Scenarios);
+ -- Examine SPARK scenarios which are not necessarily executable during
+ -- elaboration, but still requires elaboration-related checks.
+
+ end SPARK_Processor;
+ use SPARK_Processor;
-----------------------
-- Local subprograms --
-----------------------
- -- Multiple local subprograms are utilized to lower the semantic complexity
- -- of the Recording and Processing phase.
-
- procedure Check_Preelaborated_Call (Call : Node_Id);
- pragma Inline (Check_Preelaborated_Call);
- -- Verify that entry, operator, or subprogram call Call does not appear at
- -- the library level of a preelaborated unit.
-
- procedure Check_SPARK_Derived_Type (Typ_Decl : Node_Id);
- pragma Inline (Check_SPARK_Derived_Type);
- -- Verify that the freeze node of a derived type denoted by declaration
- -- Typ_Decl is within the early call region of each overriding primitive
- -- body that belongs to the derived type (SPARK RM 7.7(8)).
-
- procedure Check_SPARK_Instantiation (Exp_Inst : Node_Id);
- pragma Inline (Check_SPARK_Instantiation);
- -- Verify that expanded instance Exp_Inst does not precede the generic body
- -- it instantiates (SPARK RM 7.7(6)).
-
- procedure Check_SPARK_Model_In_Effect (N : Node_Id);
- pragma Inline (Check_SPARK_Model_In_Effect);
- -- Determine whether a suitable elaboration model is currently in effect
- -- for verifying the SPARK rules of scenario N. Emit a warning if this is
- -- not the case.
-
- procedure Check_SPARK_Scenario (N : Node_Id);
- pragma Inline (Check_SPARK_Scenario);
- -- Top-level dispatcher for verifying SPARK scenarios which are not always
- -- executable during elaboration but still need elaboration-related checks.
-
- procedure Check_SPARK_Refined_State_Pragma (N : Node_Id);
- pragma Inline (Check_SPARK_Refined_State_Pragma);
- -- Verify that each constituent of Refined_State pragma N which belongs to
- -- an abstract state mentioned in pragma Initializes has prior elaboration
- -- with respect to the main unit (SPARK RM 7.7.1(7)).
+ function Assignment_Target (Asmt : Node_Id) return Node_Id;
+ pragma Inline (Assignment_Target);
+ -- Obtain the target of assignment statement Asmt
+
+ function Call_Name (Call : Node_Id) return Node_Id;
+ pragma Inline (Call_Name);
+ -- Obtain the name of an entry, operator, or subprogram call Call
+
+ function Canonical_Subprogram (Subp_Id : Entity_Id) return Entity_Id;
+ pragma Inline (Canonical_Subprogram);
+ -- Obtain the uniform canonical entity of subprogram Subp_Id
function Compilation_Unit (Unit_Id : Entity_Id) return Node_Id;
pragma Inline (Compilation_Unit);
-- Return the N_Compilation_Unit node of unit Unit_Id
- function Early_Call_Region (Body_Id : Entity_Id) return Node_Id;
- pragma Inline (Early_Call_Region);
- -- Return the early call region associated with entry or subprogram body
- -- Body_Id. IMPORTANT: This routine does not find the early call region.
- -- To compute it, use routine Find_Early_Call_Region.
-
- procedure Elab_Msg_NE
- (Msg : String;
- N : Node_Id;
- Id : Entity_Id;
- Info_Msg : Boolean;
- In_SPARK : Boolean);
- pragma Inline (Elab_Msg_NE);
- -- Wrapper around Error_Msg_NE. Emit message Msg concerning arbitrary node
- -- N and entity. If flag Info_Msg is set, the routine emits an information
- -- message, otherwise it emits an error. If flag In_SPARK is set, then
- -- string " in SPARK" is added to the end of the message.
-
- function Elaboration_Status
- (Unit_Id : Entity_Id) return Elaboration_Attributes;
- pragma Inline (Elaboration_Status);
- -- Return the set of elaboration attributes associated with unit Unit_Id
-
- procedure Ensure_Prior_Elaboration
- (N : Node_Id;
- Unit_Id : Entity_Id;
- Prag_Nam : Name_Id;
- State : Processing_Attributes);
- -- Guarantee the elaboration of unit Unit_Id with respect to the main unit
- -- by installing pragma Elaborate or Elaborate_All denoted by Prag_Nam. N
- -- denotes the related scenario. State denotes the current state of the
- -- Processing phase.
-
- procedure Ensure_Prior_Elaboration_Dynamic
- (N : Node_Id;
- Unit_Id : Entity_Id;
- Prag_Nam : Name_Id);
- -- Guarantee the elaboration of unit Unit_Id with respect to the main unit
- -- by suggesting the use of Elaborate[_All] with name Prag_Nam. N denotes
- -- the related scenario.
-
- procedure Ensure_Prior_Elaboration_Static
- (N : Node_Id;
- Unit_Id : Entity_Id;
- Prag_Nam : Name_Id);
- -- Guarantee the elaboration of unit Unit_Id with respect to the main unit
- -- by installing an implicit Elaborate[_All] pragma with name Prag_Nam. N
- -- denotes the related scenario.
-
- function Extract_Assignment_Name (Asmt : Node_Id) return Node_Id;
- pragma Inline (Extract_Assignment_Name);
- -- Obtain the Name attribute of assignment statement Asmt
-
- procedure Extract_Call_Attributes
- (Call : Node_Id;
- Target_Id : out Entity_Id;
- Attrs : out Call_Attributes);
- pragma Inline (Extract_Call_Attributes);
- -- Obtain attributes Attrs associated with call Call. Target_Id is the
- -- entity of the call target.
-
- function Extract_Call_Name (Call : Node_Id) return Node_Id;
- pragma Inline (Extract_Call_Name);
- -- Obtain the Name attribute of entry or subprogram call Call
-
- procedure Extract_Instance_Attributes
- (Exp_Inst : Node_Id;
- Inst_Body : out Node_Id;
- Inst_Decl : out Node_Id);
- pragma Inline (Extract_Instance_Attributes);
- -- Obtain body Inst_Body and spec Inst_Decl of expanded instance Exp_Inst
-
- procedure Extract_Instantiation_Attributes
- (Exp_Inst : Node_Id;
- Inst : out Node_Id;
- Inst_Id : out Entity_Id;
- Gen_Id : out Entity_Id;
- Attrs : out Instantiation_Attributes);
- pragma Inline (Extract_Instantiation_Attributes);
- -- Obtain attributes Attrs associated with expanded instantiation Exp_Inst.
- -- Inst is the instantiation. Inst_Id is the entity of the instance. Gen_Id
- -- is the entity of the generic unit being instantiated.
-
- procedure Extract_Target_Attributes
- (Target_Id : Entity_Id;
- Attrs : out Target_Attributes);
- -- Obtain attributes Attrs associated with an entry, package, or subprogram
- -- denoted by Target_Id.
-
- procedure Extract_Task_Attributes
- (Typ : Entity_Id;
- Attrs : out Task_Attributes);
- pragma Inline (Extract_Task_Attributes);
- -- Obtain attributes Attrs associated with task type Typ
-
- procedure Extract_Variable_Reference_Attributes
- (Ref : Node_Id;
- Var_Id : out Entity_Id;
- Attrs : out Variable_Attributes);
- pragma Inline (Extract_Variable_Reference_Attributes);
- -- Obtain attributes Attrs associated with reference Ref that mentions
- -- variable Var_Id.
-
- function Find_Code_Unit (N : Node_Or_Entity_Id) return Entity_Id;
- pragma Inline (Find_Code_Unit);
- -- Return the code unit which contains arbitrary node or entity N. This
- -- is the unit of the file which physically contains the related construct
- -- denoted by N except when N is within an instantiation. In that case the
- -- unit is that of the top-level instantiation.
-
- function Find_Early_Call_Region
- (Body_Decl : Node_Id;
- Assume_Elab_Body : Boolean := False;
- Skip_Memoization : Boolean := False) return Node_Id;
- -- Find the start of the early call region which belongs to subprogram body
- -- Body_Decl as defined in SPARK RM 7.7. The behavior of the routine is to
- -- find the early call region, memoize it, and return it, but this behavior
- -- can be altered. Flag Assume_Elab_Body should be set when a package spec
- -- may lack pragma Elaborate_Body, but the routine must still examine that
- -- spec. Flag Skip_Memoization should be set when the routine must avoid
- -- memoizing the region.
-
- procedure Find_Elaborated_Units;
- -- Populate table Elaboration_Statuses with all units which have prior
- -- elaboration with respect to the main unit.
-
function Find_Enclosing_Instance (N : Node_Id) return Node_Id;
pragma Inline (Find_Enclosing_Instance);
-- Find the declaration or body of the nearest expanded instance which
@@ -1301,33 +1959,10 @@ package body Sem_Elab is
-- subprogram lacks formal parameters, return Empty.
function Has_Body (Pack_Decl : Node_Id) return Boolean;
+ pragma Inline (Has_Body);
-- Determine whether package declaration Pack_Decl has a corresponding body
-- or would eventually have one.
- function Has_Prior_Elaboration
- (Unit_Id : Entity_Id;
- Context_OK : Boolean := False;
- Elab_Body_OK : Boolean := False;
- Same_Unit_OK : Boolean := False) return Boolean;
- pragma Inline (Has_Prior_Elaboration);
- -- Determine whether unit Unit_Id is elaborated prior to the main unit.
- -- If flag Context_OK is set, the routine considers the following case
- -- as valid prior elaboration:
- --
- -- * Unit_Id is in the elaboration context of the main unit
- --
- -- If flag Elab_Body_OK is set, the routine considers the following case
- -- as valid prior elaboration:
- --
- -- * Unit_Id has pragma Elaborate_Body and is not the main unit
- --
- -- If flag Same_Unit_OK is set, the routine considers the following cases
- -- as valid prior elaboration:
- --
- -- * Unit_Id is the main unit
- --
- -- * Unit_Id denotes the spec of the main unit body
-
function In_External_Instance
(N : Node_Id;
Target_Decl : Node_Id) return Boolean;
@@ -1344,204 +1979,38 @@ package body Sem_Elab is
(N1 : Node_Id;
N2 : Node_Id;
Nested_OK : Boolean := False) return Boolean;
+ pragma Inline (In_Same_Context);
-- Determine whether two arbitrary nodes N1 and N2 appear within the same
-- context ignoring enclosing library levels. Nested_OK should be set when
-- the context of N1 can enclose that of N2.
- function In_Task_Body (N : Node_Id) return Boolean;
- pragma Inline (In_Task_Body);
- -- Determine whether arbitrary node N appears within a task body
-
- procedure Info_Call
- (Call : Node_Id;
- Target_Id : Entity_Id;
- Info_Msg : Boolean;
- In_SPARK : Boolean);
- -- Output information concerning call Call which invokes target Target_Id.
- -- If flag Info_Msg is set, the routine emits an information message,
- -- otherwise it emits an error. If flag In_SPARK is set, then the string
- -- " in SPARK" is added to the end of the message.
-
- procedure Info_Instantiation
- (Inst : Node_Id;
- Gen_Id : Entity_Id;
- Info_Msg : Boolean;
- In_SPARK : Boolean);
- pragma Inline (Info_Instantiation);
- -- Output information concerning instantiation Inst which instantiates
- -- generic unit Gen_Id. If flag Info_Msg is set, the routine emits an
- -- information message, otherwise it emits an error. If flag In_SPARK
- -- is set, then string " in SPARK" is added to the end of the message.
-
- procedure Info_Variable_Reference
- (Ref : Node_Id;
- Var_Id : Entity_Id;
- Info_Msg : Boolean;
- In_SPARK : Boolean);
- pragma Inline (Info_Variable_Reference);
- -- Output information concerning reference Ref which mentions variable
- -- Var_Id. If flag Info_Msg is set, the routine emits an information
- -- message, otherwise it emits an error. If flag In_SPARK is set, then
- -- string " in SPARK" is added to the end of the message.
-
- function Insertion_Node (N : Node_Id; Ins_Nod : Node_Id) return Node_Id;
- pragma Inline (Insertion_Node);
- -- Obtain the proper insertion node of an ABE check or failure for scenario
- -- N and candidate insertion node Ins_Nod.
-
- procedure Install_ABE_Check
- (N : Node_Id;
- Id : Entity_Id;
- Ins_Nod : Node_Id);
- -- Insert a run-time ABE check for elaboration scenario N which verifies
- -- whether arbitrary entity Id is elaborated. The check in inserted prior
- -- to node Ins_Nod.
-
- procedure Install_ABE_Check
- (N : Node_Id;
- Target_Id : Entity_Id;
- Target_Decl : Node_Id;
- Target_Body : Node_Id;
- Ins_Nod : Node_Id);
- -- Insert a run-time ABE check for elaboration scenario N which verifies
- -- whether target Target_Id with initial declaration Target_Decl and body
- -- Target_Body is elaborated. The check is inserted prior to node Ins_Nod.
-
- procedure Install_ABE_Failure (N : Node_Id; Ins_Nod : Node_Id);
- -- Insert a Program_Error concerning a guaranteed ABE for elaboration
- -- scenario N. The failure is inserted prior to node Node_Id.
-
- function Is_Accept_Alternative_Proc (Id : Entity_Id) return Boolean;
- pragma Inline (Is_Accept_Alternative_Proc);
- -- Determine whether arbitrary entity Id denotes an internally generated
- -- procedure which encapsulates the statements of an accept alternative.
-
- function Is_Activation_Proc (Id : Entity_Id) return Boolean;
- pragma Inline (Is_Activation_Proc);
- -- Determine whether arbitrary entity Id denotes a runtime procedure in
- -- charge with activating tasks.
-
- function Is_Ada_Semantic_Target (Id : Entity_Id) return Boolean;
- pragma Inline (Is_Ada_Semantic_Target);
- -- Determine whether arbitrary entity Id denodes a source or internally
- -- generated subprogram which emulates Ada semantics.
-
- function Is_Assertion_Pragma_Target (Id : Entity_Id) return Boolean;
- pragma Inline (Is_Assertion_Pragma_Target);
- -- Determine whether arbitrary entity Id denotes a procedure which varifies
- -- the run-time semantics of an assertion pragma.
-
- function Is_Bodiless_Subprogram (Subp_Id : Entity_Id) return Boolean;
- pragma Inline (Is_Bodiless_Subprogram);
- -- Determine whether subprogram Subp_Id will never have a body
-
- function Is_Controlled_Proc
- (Subp_Id : Entity_Id;
- Subp_Nam : Name_Id) return Boolean;
- pragma Inline (Is_Controlled_Proc);
- -- Determine whether subprogram Subp_Id denotes controlled type primitives
- -- Adjust, Finalize, or Initialize as denoted by name Subp_Nam.
-
- function Is_Default_Initial_Condition_Proc (Id : Entity_Id) return Boolean;
- pragma Inline (Is_Default_Initial_Condition_Proc);
- -- Determine whether arbitrary entity Id denotes internally generated
- -- routine Default_Initial_Condition.
-
- function Is_Finalizer_Proc (Id : Entity_Id) return Boolean;
- pragma Inline (Is_Finalizer_Proc);
- -- Determine whether arbitrary entity Id denotes internally generated
- -- routine _Finalizer.
-
- function Is_Guaranteed_ABE
- (N : Node_Id;
- Target_Decl : Node_Id;
- Target_Body : Node_Id) return Boolean;
- pragma Inline (Is_Guaranteed_ABE);
- -- Determine whether scenario N with a target described by its initial
- -- declaration Target_Decl and body Target_Decl results in a guaranteed
- -- ABE.
-
- function Is_Initial_Condition_Proc (Id : Entity_Id) return Boolean;
- pragma Inline (Is_Initial_Condition_Proc);
- -- Determine whether arbitrary entity Id denotes internally generated
- -- routine Initial_Condition.
-
- function Is_Initialized (Obj_Decl : Node_Id) return Boolean;
- pragma Inline (Is_Initialized);
- -- Determine whether object declaration Obj_Decl is initialized
-
- function Is_Invariant_Proc (Id : Entity_Id) return Boolean;
- pragma Inline (Is_Invariant_Proc);
- -- Determine whether arbitrary entity Id denotes an invariant procedure
-
- function Is_Non_Library_Level_Encapsulator (N : Node_Id) return Boolean;
- pragma Inline (Is_Non_Library_Level_Encapsulator);
- -- Determine whether arbitrary node N is a non-library encapsulator
-
- function Is_Partial_Invariant_Proc (Id : Entity_Id) return Boolean;
- pragma Inline (Is_Partial_Invariant_Proc);
- -- Determine whether arbitrary entity Id denotes a partial invariant
- -- procedure.
-
- function Is_Postconditions_Proc (Id : Entity_Id) return Boolean;
- pragma Inline (Is_Postconditions_Proc);
- -- Determine whether arbitrary entity Id denotes internally generated
- -- routine _Postconditions.
-
- function Is_Preelaborated_Unit (Id : Entity_Id) return Boolean;
- pragma Inline (Is_Preelaborated_Unit);
- -- Determine whether arbitrary entity Id denotes a unit which is subject to
- -- one of the following pragmas:
- --
- -- * Preelaborable
- -- * Pure
- -- * Remote_Call_Interface
- -- * Remote_Types
- -- * Shared_Passive
-
- function Is_Protected_Entry (Id : Entity_Id) return Boolean;
- pragma Inline (Is_Protected_Entry);
- -- Determine whether arbitrary entity Id denotes a protected entry
-
- function Is_Protected_Subp (Id : Entity_Id) return Boolean;
- pragma Inline (Is_Protected_Subp);
- -- Determine whether entity Id denotes a protected subprogram
-
- function Is_Protected_Body_Subp (Id : Entity_Id) return Boolean;
- pragma Inline (Is_Protected_Body_Subp);
- -- Determine whether entity Id denotes the protected or unprotected version
- -- of a protected subprogram.
-
- function Is_Recorded_SPARK_Scenario (N : Node_Id) return Boolean;
- pragma Inline (Is_Recorded_SPARK_Scenario);
- -- Determine whether arbitrary node N is a recorded SPARK scenario which
- -- appears in table SPARK_Scenarios.
-
- function Is_Recorded_Top_Level_Scenario (N : Node_Id) return Boolean;
- pragma Inline (Is_Recorded_Top_Level_Scenario);
- -- Determine whether arbitrary node N is a recorded top-level scenario
- -- which appears in table Top_Level_Scenarios.
+ function Instantiated_Generic (Inst : Node_Id) return Entity_Id;
+ pragma Inline (Instantiated_Generic);
+ -- Obtain the generic instantiated by instance Inst
function Is_Safe_Activation
- (Call : Node_Id;
- Task_Decl : Node_Id) return Boolean;
+ (Call : Node_Id;
+ Task_Rep : Target_Rep_Id) return Boolean;
pragma Inline (Is_Safe_Activation);
- -- Determine whether call Call which activates a task object described by
- -- declaration Task_Decl is always ABE-safe.
+ -- Determine whether activation call Call which activates an object of a
+ -- task type described by representation Task_Rep is always ABE-safe.
function Is_Safe_Call
- (Call : Node_Id;
- Target_Attrs : Target_Attributes) return Boolean;
+ (Call : Node_Id;
+ Subp_Id : Entity_Id;
+ Subp_Rep : Target_Rep_Id) return Boolean;
pragma Inline (Is_Safe_Call);
- -- Determine whether call Call which invokes a target described by
- -- attributes Target_Attrs is always ABE-safe.
+ -- Determine whether call Call which invokes entry, operator, or subprogram
+ -- Subp_Id is always ABE-safe. Subp_Rep is the representation of the entry,
+ -- operator, or subprogram.
function Is_Safe_Instantiation
- (Inst : Node_Id;
- Gen_Attrs : Target_Attributes) return Boolean;
+ (Inst : Node_Id;
+ Gen_Id : Entity_Id;
+ Gen_Rep : Target_Rep_Id) return Boolean;
pragma Inline (Is_Safe_Instantiation);
- -- Determine whether instance Inst which instantiates a generic unit
- -- described by attributes Gen_Attrs is always ABE-safe.
+ -- Determine whether instantiation Inst which instantiates generic Gen_Id
+ -- is always ABE-safe. Gen_Rep is the representation of the generic.
function Is_Same_Unit
(Unit_1 : Entity_Id;
@@ -1549,332 +2018,1374 @@ package body Sem_Elab is
pragma Inline (Is_Same_Unit);
-- Determine whether entities Unit_1 and Unit_2 denote the same unit
- function Is_Scenario (N : Node_Id) return Boolean;
- pragma Inline (Is_Scenario);
- -- Determine whether attribute node N denotes a scenario. The scenario may
- -- not necessarily be eligible for ABE processing.
+ function Non_Private_View (Typ : Entity_Id) return Entity_Id;
+ pragma Inline (Non_Private_View);
+ -- Return the full view of private type Typ if available, otherwise return
+ -- type Typ.
- function Is_SPARK_Semantic_Target (Id : Entity_Id) return Boolean;
- pragma Inline (Is_SPARK_Semantic_Target);
- -- Determine whether arbitrary entity Id nodes a source or internally
- -- generated subprogram which emulates SPARK semantics.
+ function Scenario (N : Node_Id) return Node_Id;
+ pragma Inline (Scenario);
+ -- Return the appropriate scenario node for scenario N
- function Is_Suitable_Access (N : Node_Id) return Boolean;
- pragma Inline (Is_Suitable_Access);
- -- Determine whether arbitrary node N denotes a suitable attribute for ABE
- -- processing.
+ procedure Spec_And_Body_From_Entity
+ (Id : Node_Id;
+ Spec_Decl : out Node_Id;
+ Body_Decl : out Node_Id);
+ pragma Inline (Spec_And_Body_From_Entity);
+ -- Given arbitrary entity Id representing a construct with a spec and body,
+ -- retrieve declaration of the spec in Spec_Decl and the declaration of the
+ -- body in Body_Decl.
- function Is_Suitable_Call (N : Node_Id) return Boolean;
- pragma Inline (Is_Suitable_Call);
- -- Determine whether arbitrary node N denotes a suitable call for ABE
- -- processing.
+ procedure Spec_And_Body_From_Node
+ (N : Node_Id;
+ Spec_Decl : out Node_Id;
+ Body_Decl : out Node_Id);
+ pragma Inline (Spec_And_Body_From_Node);
+ -- Given arbitrary node N representing a construct with a spec and body,
+ -- retrieve declaration of the spec in Spec_Decl and the declaration of
+ -- the body in Body_Decl.
- function Is_Suitable_Instantiation (N : Node_Id) return Boolean;
- pragma Inline (Is_Suitable_Instantiation);
- -- Determine whether arbitrary node N is a suitable instantiation for ABE
- -- processing.
+ function Static_Elaboration_Checks return Boolean;
+ pragma Inline (Static_Elaboration_Checks);
+ -- Determine whether the static model is in effect
- function Is_Suitable_Scenario (N : Node_Id) return Boolean;
- pragma Inline (Is_Suitable_Scenario);
- -- Determine whether arbitrary node N is a suitable scenario for ABE
- -- processing.
+ function Unit_Entity (Unit_Id : Entity_Id) return Entity_Id;
+ pragma Inline (Unit_Entity);
+ -- Return the entity of the initial declaration for unit Unit_Id
- function Is_Suitable_SPARK_Derived_Type (N : Node_Id) return Boolean;
- pragma Inline (Is_Suitable_SPARK_Derived_Type);
- -- Determine whether arbitrary node N denotes a suitable derived type
- -- declaration for ABE processing using the SPARK rules.
-
- function Is_Suitable_SPARK_Instantiation (N : Node_Id) return Boolean;
- pragma Inline (Is_Suitable_SPARK_Instantiation);
- -- Determine whether arbitrary node N denotes a suitable instantiation for
- -- ABE processing using the SPARK rules.
-
- function Is_Suitable_SPARK_Refined_State_Pragma
- (N : Node_Id) return Boolean;
- pragma Inline (Is_Suitable_SPARK_Refined_State_Pragma);
- -- Determine whether arbitrary node N denotes a suitable Refined_State
- -- pragma for ABE processing using the SPARK rules.
-
- function Is_Suitable_Variable_Assignment (N : Node_Id) return Boolean;
- pragma Inline (Is_Suitable_Variable_Assignment);
- -- Determine whether arbitrary node N denotes a suitable assignment for ABE
- -- processing.
+ procedure Update_Elaboration_Scenario (New_N : Node_Id; Old_N : Node_Id);
+ pragma Inline (Update_Elaboration_Scenario);
+ -- Update all relevant internal data structures when scenario Old_N is
+ -- transformed into scenario New_N by Atree.Rewrite.
- function Is_Suitable_Variable_Reference (N : Node_Id) return Boolean;
- pragma Inline (Is_Suitable_Variable_Reference);
- -- Determine whether arbitrary node N is a suitable variable reference for
- -- ABE processing.
+ ----------------------
+ -- Active_Scenarios --
+ ----------------------
- function Is_Synchronous_Suspension_Call (N : Node_Id) return Boolean;
- pragma Inline (Is_Synchronous_Suspension_Call);
- -- Determine whether arbitrary node N denotes a call to one the following
- -- routines:
- --
- -- Ada.Synchronous_Barriers.Wait_For_Release
- -- Ada.Synchronous_Task_Control.Suspend_Until_True
+ package body Active_Scenarios is
- function Is_Task_Entry (Id : Entity_Id) return Boolean;
- pragma Inline (Is_Task_Entry);
- -- Determine whether arbitrary entity Id denotes a task entry
+ -----------------------
+ -- Local subprograms --
+ -----------------------
- function Is_Up_Level_Target (Target_Decl : Node_Id) return Boolean;
- pragma Inline (Is_Up_Level_Target);
- -- Determine whether the current root resides at the declaration level. If
- -- this is the case, determine whether a target described by declaration
- -- Target_Decl is within a context which encloses the current root or is in
- -- a different unit.
+ procedure Output_Access_Taken
+ (Attr : Node_Id;
+ Attr_Rep : Scenario_Rep_Id;
+ Error_Nod : Node_Id);
+ pragma Inline (Output_Access_Taken);
+ -- Emit a specific diagnostic message for 'Access attribute reference
+ -- Attr with representation Attr_Rep. The message is associated with
+ -- node Error_Nod.
- function Is_Visited_Body (Body_Decl : Node_Id) return Boolean;
- pragma Inline (Is_Visited_Body);
- -- Determine whether subprogram body Body_Decl is already visited during a
- -- recursive traversal started from a top-level scenario.
+ procedure Output_Active_Scenario
+ (N : Node_Id;
+ Error_Nod : Node_Id;
+ In_State : Processing_In_State);
+ pragma Inline (Output_Active_Scenario);
+ -- Top level dispatcher for outputting a scenario. Emit a specific
+ -- diagnostic message for scenario N. The message is associated with
+ -- node Error_Nod. In_State is the current state of the Processing
+ -- phase.
+
+ procedure Output_Call
+ (Call : Node_Id;
+ Call_Rep : Scenario_Rep_Id;
+ Error_Nod : Node_Id);
+ pragma Inline (Output_Call);
+ -- Emit a diagnostic message for call Call with representation Call_Rep.
+ -- The message is associated with node Error_Nod.
+
+ procedure Output_Header (Error_Nod : Node_Id);
+ pragma Inline (Output_Header);
+ -- Emit a specific diagnostic message for the unit of the root scenario.
+ -- The message is associated with node Error_Nod.
+
+ procedure Output_Instantiation
+ (Inst : Node_Id;
+ Inst_Rep : Scenario_Rep_Id;
+ Error_Nod : Node_Id);
+ pragma Inline (Output_Instantiation);
+ -- Emit a specific diagnostic message for instantiation Inst with
+ -- representation Inst_Rep. The message is associated with node
+ -- Error_Nod.
+
+ procedure Output_Refined_State_Pragma
+ (Prag : Node_Id;
+ Prag_Rep : Scenario_Rep_Id;
+ Error_Nod : Node_Id);
+ pragma Inline (Output_Refined_State_Pragma);
+ -- Emit a specific diagnostic message for Refined_State pragma Prag
+ -- with representation Prag_Rep. The message is associated with node
+ -- Error_Nod.
+
+ procedure Output_Task_Activation
+ (Call : Node_Id;
+ Call_Rep : Scenario_Rep_Id;
+ Error_Nod : Node_Id);
+ pragma Inline (Output_Task_Activation);
+ -- Emit a specific diagnostic message for activation call Call
+ -- with representation Call_Rep. The message is associated with
+ -- node Error_Nod.
+
+ procedure Output_Variable_Assignment
+ (Asmt : Node_Id;
+ Asmt_Rep : Scenario_Rep_Id;
+ Error_Nod : Node_Id);
+ pragma Inline (Output_Variable_Assignment);
+ -- Emit a specific diagnostic message for assignment statement Asmt
+ -- with representation Asmt_Rep. The message is associated with node
+ -- Error_Nod.
+
+ procedure Output_Variable_Reference
+ (Ref : Node_Id;
+ Ref_Rep : Scenario_Rep_Id;
+ Error_Nod : Node_Id);
+ pragma Inline (Output_Variable_Reference);
+ -- Emit a specific diagnostic message for read reference Ref with
+ -- representation Ref_Rep. The message is associated with node
+ -- Error_Nod.
- procedure Meet_Elaboration_Requirement
- (N : Node_Id;
- Target_Id : Entity_Id;
- Req_Nam : Name_Id);
- -- Determine whether elaboration requirement Req_Nam for scenario N with
- -- target Target_Id is met by the context of the main unit using the SPARK
- -- rules. Req_Nam must denote either Elaborate or Elaborate_All. Emit an
- -- error if this is not the case.
+ -------------------
+ -- Output_Access --
+ -------------------
- function Non_Private_View (Typ : Entity_Id) return Entity_Id;
- pragma Inline (Non_Private_View);
- -- Return the full view of private type Typ if available, otherwise return
- -- type Typ.
+ procedure Output_Access_Taken
+ (Attr : Node_Id;
+ Attr_Rep : Scenario_Rep_Id;
+ Error_Nod : Node_Id)
+ is
+ Subp_Id : constant Entity_Id := Target (Attr_Rep);
- procedure Output_Active_Scenarios (Error_Nod : Node_Id);
- -- Output the contents of the active scenario stack from earliest to latest
- -- to supplement an earlier error emitted for node Error_Nod.
-
- procedure Pop_Active_Scenario (N : Node_Id);
- pragma Inline (Pop_Active_Scenario);
- -- Pop the top of the scenario stack. A check is made to ensure that the
- -- scenario being removed is the same as N.
-
- generic
- with procedure Process_Single_Activation
- (Call : Node_Id;
- Call_Attrs : Call_Attributes;
- Obj_Id : Entity_Id;
- Task_Attrs : Task_Attributes;
- State : Processing_Attributes);
- -- Perform ABE checks and diagnostics for task activation call Call
- -- which activates task Obj_Id. Call_Attrs are the attributes of the
- -- activation call. Task_Attrs are the attributes of the task type.
- -- State is the current state of the Processing phase.
-
- procedure Process_Activation_Generic
- (Call : Node_Id;
- Call_Attrs : Call_Attributes;
- State : Processing_Attributes);
- -- Perform ABE checks and diagnostics for activation call Call by invoking
- -- routine Process_Single_Activation on each task object being activated.
- -- Call_Attrs are the attributes of the activation call. State is the
- -- current state of the Processing phase.
-
- procedure Process_Conditional_ABE
- (N : Node_Id;
- State : Processing_Attributes := Initial_State);
- -- Top-level dispatcher for processing of various elaboration scenarios.
- -- Perform conditional ABE checks and diagnostics for scenario N. State
- -- is the current state of the Processing phase.
-
- procedure Process_Conditional_ABE_Access
- (Attr : Node_Id;
- State : Processing_Attributes);
- -- Perform ABE checks and diagnostics for 'Access to entry, operator, or
- -- subprogram denoted by Attr. State is the current state of the Processing
- -- phase.
+ begin
+ Error_Msg_Name_1 := Attribute_Name (Attr);
+ Error_Msg_Sloc := Sloc (Attr);
+ Error_Msg_NE ("\\ % of & taken #", Error_Nod, Subp_Id);
+ end Output_Access_Taken;
- procedure Process_Conditional_ABE_Activation_Impl
- (Call : Node_Id;
- Call_Attrs : Call_Attributes;
- Obj_Id : Entity_Id;
- Task_Attrs : Task_Attributes;
- State : Processing_Attributes);
- -- Perform common conditional ABE checks and diagnostics for call Call
- -- which activates task Obj_Id ignoring the Ada or SPARK rules. Call_Attrs
- -- are the attributes of the activation call. Task_Attrs are the attributes
- -- of the task type. State is the current state of the Processing phase.
-
- procedure Process_Conditional_ABE_Call
- (Call : Node_Id;
- Call_Attrs : Call_Attributes;
- Target_Id : Entity_Id;
- State : Processing_Attributes);
- -- Top-level dispatcher for processing of calls. Perform ABE checks and
- -- diagnostics for call Call which invokes target Target_Id. Call_Attrs
- -- are the attributes of the call. State is the current state of the
- -- Processing phase.
+ ----------------------------
+ -- Output_Active_Scenario --
+ ----------------------------
- procedure Process_Conditional_ABE_Call_Ada
- (Call : Node_Id;
- Call_Attrs : Call_Attributes;
- Target_Id : Entity_Id;
- Target_Attrs : Target_Attributes;
- State : Processing_Attributes);
- -- Perform ABE checks and diagnostics for call Call which invokes target
- -- Target_Id using the Ada rules. Call_Attrs are the attributes of the
- -- call. Target_Attrs are attributes of the target. State is the current
- -- state of the Processing phase.
-
- procedure Process_Conditional_ABE_Call_SPARK
- (Call : Node_Id;
- Target_Id : Entity_Id;
- Target_Attrs : Target_Attributes;
- State : Processing_Attributes);
- -- Perform ABE checks and diagnostics for call Call which invokes target
- -- Target_Id using the SPARK rules. Target_Attrs denotes the attributes of
- -- the target. State is the current state of the Processing phase.
-
- procedure Process_Conditional_ABE_Instantiation
- (Exp_Inst : Node_Id;
- State : Processing_Attributes);
- -- Top-level dispatcher for processing of instantiations. Perform ABE
- -- checks and diagnostics for expanded instantiation Exp_Inst. State is
- -- the current state of the Processing phase.
-
- procedure Process_Conditional_ABE_Instantiation_Ada
- (Exp_Inst : Node_Id;
- Inst : Node_Id;
- Inst_Attrs : Instantiation_Attributes;
- Gen_Id : Entity_Id;
- Gen_Attrs : Target_Attributes;
- State : Processing_Attributes);
- -- Perform ABE checks and diagnostics for expanded instantiation Exp_Inst
- -- of generic Gen_Id using the Ada rules. Inst is the instantiation node.
- -- Inst_Attrs are the attributes of the instance. Gen_Attrs denotes the
- -- attributes of the generic. State is the current state of the Processing
- -- phase.
+ procedure Output_Active_Scenario
+ (N : Node_Id;
+ Error_Nod : Node_Id;
+ In_State : Processing_In_State)
+ is
+ Scen : constant Node_Id := Scenario (N);
+ Scen_Rep : Scenario_Rep_Id;
- procedure Process_Conditional_ABE_Instantiation_SPARK
- (Inst : Node_Id;
- Gen_Id : Entity_Id;
- Gen_Attrs : Target_Attributes;
- State : Processing_Attributes);
- -- Perform ABE checks and diagnostics for instantiation Inst of generic
- -- Gen_Id using the SPARK rules. Gen_Attrs denotes the attributes of the
- -- generic. State is the current state of the Processing phase.
-
- procedure Process_Conditional_ABE_Variable_Assignment (Asmt : Node_Id);
- -- Top-level dispatcher for processing of variable assignments. Perform ABE
- -- checks and diagnostics for assignment statement Asmt.
-
- procedure Process_Conditional_ABE_Variable_Assignment_Ada
- (Asmt : Node_Id;
- Var_Id : Entity_Id);
- -- Perform ABE checks and diagnostics for assignment statement Asmt that
- -- updates the value of variable Var_Id using the Ada rules.
-
- procedure Process_Conditional_ABE_Variable_Assignment_SPARK
- (Asmt : Node_Id;
- Var_Id : Entity_Id);
- -- Perform ABE checks and diagnostics for assignment statement Asmt that
- -- updates the value of variable Var_Id using the SPARK rules.
-
- procedure Process_Conditional_ABE_Variable_Reference (Ref : Node_Id);
- -- Top-level dispatcher for processing of variable references. Perform ABE
- -- checks and diagnostics for variable reference Ref.
-
- procedure Process_Conditional_ABE_Variable_Reference_Read
- (Ref : Node_Id;
- Var_Id : Entity_Id;
- Attrs : Variable_Attributes);
- -- Perform ABE checks and diagnostics for reference Ref described by its
- -- attributes Attrs, that reads variable Var_Id.
-
- procedure Process_Guaranteed_ABE (N : Node_Id);
- -- Top-level dispatcher for processing of scenarios which result in a
- -- guaranteed ABE.
-
- procedure Process_Guaranteed_ABE_Activation_Impl
- (Call : Node_Id;
- Call_Attrs : Call_Attributes;
- Obj_Id : Entity_Id;
- Task_Attrs : Task_Attributes;
- State : Processing_Attributes);
- -- Perform common guaranteed ABE checks and diagnostics for call Call which
- -- activates task Obj_Id ignoring the Ada or SPARK rules. Call_Attrs are
- -- the attributes of the activation call. Task_Attrs are the attributes of
- -- the task type. State is provided for compatibility and is not used.
-
- procedure Process_Guaranteed_ABE_Call
- (Call : Node_Id;
- Call_Attrs : Call_Attributes;
- Target_Id : Entity_Id);
- -- Perform common guaranteed ABE checks and diagnostics for call Call which
- -- invokes target Target_Id ignoring the Ada or SPARK rules. Call_Attrs are
- -- the attributes of the call.
-
- procedure Process_Guaranteed_ABE_Instantiation (Exp_Inst : Node_Id);
- -- Perform common guaranteed ABE checks and diagnostics for expanded
- -- instantiation Exp_Inst of generic Gen_Id ignoring the Ada or SPARK
- -- rules.
-
- procedure Push_Active_Scenario (N : Node_Id);
- pragma Inline (Push_Active_Scenario);
- -- Push scenario N on top of the scenario stack
-
- procedure Record_SPARK_Elaboration_Scenario (N : Node_Id);
- pragma Inline (Record_SPARK_Elaboration_Scenario);
- -- Save SPARK scenario N in table SPARK_Scenarios for later processing
-
- procedure Reset_Visited_Bodies;
- pragma Inline (Reset_Visited_Bodies);
- -- Clear the contents of table Visited_Bodies
-
- function Root_Scenario return Node_Id;
- pragma Inline (Root_Scenario);
- -- Return the top-level scenario which started a recursive search for other
- -- scenarios. It is assumed that there is a valid top-level scenario on the
- -- active scenario stack.
-
- procedure Set_Early_Call_Region (Body_Id : Entity_Id; Start : Node_Id);
- pragma Inline (Set_Early_Call_Region);
- -- Associate an early call region with begins at construct Start with entry
- -- or subprogram body Body_Id.
-
- procedure Set_Elaboration_Status
- (Unit_Id : Entity_Id;
- Val : Elaboration_Attributes);
- pragma Inline (Set_Elaboration_Status);
- -- Associate an set of elaboration attributes with unit Unit_Id
-
- procedure Set_Is_Recorded_SPARK_Scenario
- (N : Node_Id;
- Val : Boolean := True);
- pragma Inline (Set_Is_Recorded_SPARK_Scenario);
- -- Mark scenario N as being recorded in table SPARK_Scenarios
-
- procedure Set_Is_Recorded_Top_Level_Scenario
- (N : Node_Id;
- Val : Boolean := True);
- pragma Inline (Set_Is_Recorded_Top_Level_Scenario);
- -- Mark scenario N as being recorded in table Top_Level_Scenarios
-
- procedure Set_Is_Visited_Body (Subp_Body : Node_Id);
- pragma Inline (Set_Is_Visited_Body);
- -- Mark subprogram body Subp_Body as being visited during a recursive
- -- traversal started from a top-level scenario.
+ begin
+ -- 'Access
- function Static_Elaboration_Checks return Boolean;
- pragma Inline (Static_Elaboration_Checks);
- -- Determine whether the static model is in effect
+ if Is_Suitable_Access_Taken (Scen) then
+ Output_Access_Taken
+ (Attr => Scen,
+ Attr_Rep => Scenario_Representation_Of (Scen, In_State),
+ Error_Nod => Error_Nod);
- procedure Traverse_Body (N : Node_Id; State : Processing_Attributes);
- -- Inspect the declarative and statement lists of subprogram body N for
- -- suitable elaboration scenarios and process them. State is the current
- -- state of the Processing phase.
+ -- Call or task activation
- function Unit_Entity (Unit_Id : Entity_Id) return Entity_Id;
- pragma Inline (Unit_Entity);
- -- Return the entity of the initial declaration for unit Unit_Id
+ elsif Is_Suitable_Call (Scen) then
+ Scen_Rep := Scenario_Representation_Of (Scen, In_State);
- procedure Update_Elaboration_Scenario (New_N : Node_Id; Old_N : Node_Id);
- pragma Inline (Update_Elaboration_Scenario);
- -- Update all relevant internal data structures when scenario Old_N is
- -- transformed into scenario New_N by Atree.Rewrite.
+ if Kind (Scen_Rep) = Call_Scenario then
+ Output_Call
+ (Call => Scen,
+ Call_Rep => Scen_Rep,
+ Error_Nod => Error_Nod);
+
+ else
+ pragma Assert (Kind (Scen_Rep) = Task_Activation_Scenario);
+
+ Output_Task_Activation
+ (Call => Scen,
+ Call_Rep => Scen_Rep,
+ Error_Nod => Error_Nod);
+ end if;
+
+ -- Instantiation
+
+ elsif Is_Suitable_Instantiation (Scen) then
+ Output_Instantiation
+ (Inst => Scen,
+ Inst_Rep => Scenario_Representation_Of (Scen, In_State),
+ Error_Nod => Error_Nod);
+
+ -- Pragma Refined_State
+
+ elsif Is_Suitable_SPARK_Refined_State_Pragma (Scen) then
+ Output_Refined_State_Pragma
+ (Prag => Scen,
+ Prag_Rep => Scenario_Representation_Of (Scen, In_State),
+ Error_Nod => Error_Nod);
+
+ -- Variable assignment
+
+ elsif Is_Suitable_Variable_Assignment (Scen) then
+ Output_Variable_Assignment
+ (Asmt => Scen,
+ Asmt_Rep => Scenario_Representation_Of (Scen, In_State),
+ Error_Nod => Error_Nod);
+
+ -- Variable reference
+
+ elsif Is_Suitable_Variable_Reference (Scen) then
+ Output_Variable_Reference
+ (Ref => Scen,
+ Ref_Rep => Scenario_Representation_Of (Scen, In_State),
+ Error_Nod => Error_Nod);
+ end if;
+ end Output_Active_Scenario;
+
+ -----------------------------
+ -- Output_Active_Scenarios --
+ -----------------------------
+
+ procedure Output_Active_Scenarios
+ (Error_Nod : Node_Id;
+ In_State : Processing_In_State)
+ is
+ package Scenarios renames Active_Scenario_Stack;
+
+ Header_Posted : Boolean := False;
+
+ begin
+ -- Output the contents of the active scenario stack starting from the
+ -- bottom, or the least recent scenario.
+
+ for Index in Scenarios.First .. Scenarios.Last loop
+ if not Header_Posted then
+ Output_Header (Error_Nod);
+ Header_Posted := True;
+ end if;
+
+ Output_Active_Scenario
+ (N => Scenarios.Table (Index),
+ Error_Nod => Error_Nod,
+ In_State => In_State);
+ end loop;
+ end Output_Active_Scenarios;
+
+ -----------------
+ -- Output_Call --
+ -----------------
+
+ procedure Output_Call
+ (Call : Node_Id;
+ Call_Rep : Scenario_Rep_Id;
+ Error_Nod : Node_Id)
+ is
+ procedure Output_Accept_Alternative (Alt_Id : Entity_Id);
+ pragma Inline (Output_Accept_Alternative);
+ -- Emit a specific diagnostic message concerning accept alternative
+ -- with entity Alt_Id.
+
+ procedure Output_Call (Subp_Id : Entity_Id; Kind : String);
+ pragma Inline (Output_Call);
+ -- Emit a specific diagnostic message concerning a call of kind Kind
+ -- which invokes subprogram Subp_Id.
+
+ procedure Output_Type_Actions (Subp_Id : Entity_Id; Action : String);
+ pragma Inline (Output_Type_Actions);
+ -- Emit a specific diagnostic message concerning action Action of a
+ -- type performed by subprogram Subp_Id.
+
+ procedure Output_Verification_Call
+ (Pred : String;
+ Id : Entity_Id;
+ Id_Kind : String);
+ pragma Inline (Output_Verification_Call);
+ -- Emit a specific diagnostic message concerning the verification of
+ -- predicate Pred applied to related entity Id with kind Id_Kind.
+
+ -------------------------------
+ -- Output_Accept_Alternative --
+ -------------------------------
+
+ procedure Output_Accept_Alternative (Alt_Id : Entity_Id) is
+ Entry_Id : constant Entity_Id := Receiving_Entry (Alt_Id);
+
+ begin
+ pragma Assert (Present (Entry_Id));
+
+ Error_Msg_NE ("\\ entry & selected #", Error_Nod, Entry_Id);
+ end Output_Accept_Alternative;
+
+ -----------------
+ -- Output_Call --
+ -----------------
+
+ procedure Output_Call (Subp_Id : Entity_Id; Kind : String) is
+ begin
+ Error_Msg_NE ("\\ " & Kind & " & called #", Error_Nod, Subp_Id);
+ end Output_Call;
+
+ -------------------------
+ -- Output_Type_Actions --
+ -------------------------
+
+ procedure Output_Type_Actions
+ (Subp_Id : Entity_Id;
+ Action : String)
+ is
+ Typ : constant Entity_Id := First_Formal_Type (Subp_Id);
+
+ begin
+ pragma Assert (Present (Typ));
+
+ Error_Msg_NE
+ ("\\ " & Action & " actions for type & #", Error_Nod, Typ);
+ end Output_Type_Actions;
+
+ ------------------------------
+ -- Output_Verification_Call --
+ ------------------------------
+
+ procedure Output_Verification_Call
+ (Pred : String;
+ Id : Entity_Id;
+ Id_Kind : String)
+ is
+ begin
+ pragma Assert (Present (Id));
+
+ Error_Msg_NE
+ ("\\ " & Pred & " of " & Id_Kind & " & verified #",
+ Error_Nod, Id);
+ end Output_Verification_Call;
+
+ -- Local variables
+
+ Subp_Id : constant Entity_Id := Target (Call_Rep);
+
+ -- Start of processing for Output_Call
+
+ begin
+ Error_Msg_Sloc := Sloc (Call);
+
+ -- Accept alternative
+
+ if Is_Accept_Alternative_Proc (Subp_Id) then
+ Output_Accept_Alternative (Subp_Id);
+
+ -- Adjustment
+
+ elsif Is_TSS (Subp_Id, TSS_Deep_Adjust) then
+ Output_Type_Actions (Subp_Id, "adjustment");
+
+ -- Default_Initial_Condition
+
+ elsif Is_Default_Initial_Condition_Proc (Subp_Id) then
+ Output_Verification_Call
+ (Pred => "Default_Initial_Condition",
+ Id => First_Formal_Type (Subp_Id),
+ Id_Kind => "type");
+
+ -- Entries
+
+ elsif Is_Protected_Entry (Subp_Id) then
+ Output_Call (Subp_Id, "entry");
+
+ -- Task entry calls are never processed because the entry being
+ -- invoked does not have a corresponding "body", it has a select. A
+ -- task entry call appears in the stack of active scenarios for the
+ -- sole purpose of checking No_Entry_Calls_In_Elaboration_Code and
+ -- nothing more.
+
+ elsif Is_Task_Entry (Subp_Id) then
+ null;
+
+ -- Finalization
+
+ elsif Is_TSS (Subp_Id, TSS_Deep_Finalize) then
+ Output_Type_Actions (Subp_Id, "finalization");
+
+ -- Calls to _Finalizer procedures must not appear in the output
+ -- because this creates confusing noise.
+
+ elsif Is_Finalizer_Proc (Subp_Id) then
+ null;
+
+ -- Initial_Condition
+
+ elsif Is_Initial_Condition_Proc (Subp_Id) then
+ Output_Verification_Call
+ (Pred => "Initial_Condition",
+ Id => Find_Enclosing_Scope (Call),
+ Id_Kind => "package");
+
+ -- Initialization
+
+ elsif Is_Init_Proc (Subp_Id)
+ or else Is_TSS (Subp_Id, TSS_Deep_Initialize)
+ then
+ Output_Type_Actions (Subp_Id, "initialization");
+
+ -- Invariant
+
+ elsif Is_Invariant_Proc (Subp_Id) then
+ Output_Verification_Call
+ (Pred => "invariants",
+ Id => First_Formal_Type (Subp_Id),
+ Id_Kind => "type");
+
+ -- Partial invariant calls must not appear in the output because this
+ -- creates confusing noise. Note that a partial invariant is always
+ -- invoked by the "full" invariant which is already placed on the
+ -- stack.
+
+ elsif Is_Partial_Invariant_Proc (Subp_Id) then
+ null;
+
+ -- _Postconditions
+
+ elsif Is_Postconditions_Proc (Subp_Id) then
+ Output_Verification_Call
+ (Pred => "postconditions",
+ Id => Find_Enclosing_Scope (Call),
+ Id_Kind => "subprogram");
+
+ -- Subprograms must come last because some of the previous cases fall
+ -- under this category.
+
+ elsif Ekind (Subp_Id) = E_Function then
+ Output_Call (Subp_Id, "function");
+
+ elsif Ekind (Subp_Id) = E_Procedure then
+ Output_Call (Subp_Id, "procedure");
+
+ else
+ pragma Assert (False);
+ return;
+ end if;
+ end Output_Call;
+
+ -------------------
+ -- Output_Header --
+ -------------------
+
+ procedure Output_Header (Error_Nod : Node_Id) is
+ Unit_Id : constant Entity_Id := Find_Top_Unit (Root_Scenario);
+
+ begin
+ if Ekind (Unit_Id) = E_Package then
+ Error_Msg_NE ("\\ spec of unit & elaborated", Error_Nod, Unit_Id);
+
+ elsif Ekind (Unit_Id) = E_Package_Body then
+ Error_Msg_NE ("\\ body of unit & elaborated", Error_Nod, Unit_Id);
+
+ else
+ Error_Msg_NE ("\\ in body of unit &", Error_Nod, Unit_Id);
+ end if;
+ end Output_Header;
+
+ --------------------------
+ -- Output_Instantiation --
+ --------------------------
+
+ procedure Output_Instantiation
+ (Inst : Node_Id;
+ Inst_Rep : Scenario_Rep_Id;
+ Error_Nod : Node_Id)
+ is
+ procedure Output_Instantiation (Gen_Id : Entity_Id; Kind : String);
+ pragma Inline (Output_Instantiation);
+ -- Emit a specific diagnostic message concerning an instantiation of
+ -- generic unit Gen_Id. Kind denotes the kind of the instantiation.
+
+ --------------------------
+ -- Output_Instantiation --
+ --------------------------
+
+ procedure Output_Instantiation (Gen_Id : Entity_Id; Kind : String) is
+ begin
+ Error_Msg_NE
+ ("\\ " & Kind & " & instantiated as & #", Error_Nod, Gen_Id);
+ end Output_Instantiation;
+
+ -- Local variables
+
+ Gen_Id : constant Entity_Id := Target (Inst_Rep);
+
+ -- Start of processing for Output_Instantiation
+
+ begin
+ Error_Msg_Node_2 := Defining_Entity (Inst);
+ Error_Msg_Sloc := Sloc (Inst);
+
+ if Nkind (Inst) = N_Function_Instantiation then
+ Output_Instantiation (Gen_Id, "function");
+
+ elsif Nkind (Inst) = N_Package_Instantiation then
+ Output_Instantiation (Gen_Id, "package");
+
+ elsif Nkind (Inst) = N_Procedure_Instantiation then
+ Output_Instantiation (Gen_Id, "procedure");
+
+ else
+ pragma Assert (False);
+ return;
+ end if;
+ end Output_Instantiation;
+
+ ---------------------------------
+ -- Output_Refined_State_Pragma --
+ ---------------------------------
+
+ procedure Output_Refined_State_Pragma
+ (Prag : Node_Id;
+ Prag_Rep : Scenario_Rep_Id;
+ Error_Nod : Node_Id)
+ is
+ pragma Unreferenced (Prag_Rep);
+
+ begin
+ Error_Msg_Sloc := Sloc (Prag);
+ Error_Msg_N ("\\ refinement constituents read #", Error_Nod);
+ end Output_Refined_State_Pragma;
+
+ ----------------------------
+ -- Output_Task_Activation --
+ ----------------------------
+
+ procedure Output_Task_Activation
+ (Call : Node_Id;
+ Call_Rep : Scenario_Rep_Id;
+ Error_Nod : Node_Id)
+ is
+ pragma Unreferenced (Call_Rep);
+
+ function Find_Activator return Entity_Id;
+ -- Find the nearest enclosing construct which houses call Call
+
+ --------------------
+ -- Find_Activator --
+ --------------------
+
+ function Find_Activator return Entity_Id is
+ Par : Node_Id;
+
+ begin
+ -- Climb the parent chain looking for a package [body] or a
+ -- construct with a statement sequence.
+
+ Par := Parent (Call);
+ while Present (Par) loop
+ if Nkind_In (Par, N_Package_Body, N_Package_Declaration) then
+ return Defining_Entity (Par);
+
+ elsif Nkind (Par) = N_Handled_Sequence_Of_Statements then
+ return Defining_Entity (Parent (Par));
+ end if;
+
+ Par := Parent (Par);
+ end loop;
+
+ return Empty;
+ end Find_Activator;
+
+ -- Local variables
+
+ Activator : constant Entity_Id := Find_Activator;
+
+ -- Start of processing for Output_Task_Activation
+
+ begin
+ pragma Assert (Present (Activator));
+
+ Error_Msg_NE ("\\ local tasks of & activated", Error_Nod, Activator);
+ end Output_Task_Activation;
+
+ --------------------------------
+ -- Output_Variable_Assignment --
+ --------------------------------
+
+ procedure Output_Variable_Assignment
+ (Asmt : Node_Id;
+ Asmt_Rep : Scenario_Rep_Id;
+ Error_Nod : Node_Id)
+ is
+ Var_Id : constant Entity_Id := Target (Asmt_Rep);
+
+ begin
+ Error_Msg_Sloc := Sloc (Asmt);
+ Error_Msg_NE ("\\ variable & assigned #", Error_Nod, Var_Id);
+ end Output_Variable_Assignment;
+
+ -------------------------------
+ -- Output_Variable_Reference --
+ -------------------------------
+
+ procedure Output_Variable_Reference
+ (Ref : Node_Id;
+ Ref_Rep : Scenario_Rep_Id;
+ Error_Nod : Node_Id)
+ is
+ Var_Id : constant Entity_Id := Target (Ref_Rep);
+
+ begin
+ Error_Msg_Sloc := Sloc (Ref);
+ Error_Msg_NE ("\\ variable & read #", Error_Nod, Var_Id);
+ end Output_Variable_Reference;
+
+ -------------------------
+ -- Pop_Active_Scenario --
+ -------------------------
+
+ procedure Pop_Active_Scenario (N : Node_Id) is
+ package Scenarios renames Active_Scenario_Stack;
+ Top : Node_Id renames Scenarios.Table (Scenarios.Last);
+
+ begin
+ pragma Assert (Top = N);
+ Scenarios.Decrement_Last;
+ end Pop_Active_Scenario;
+
+ --------------------------
+ -- Push_Active_Scenario --
+ --------------------------
+
+ procedure Push_Active_Scenario (N : Node_Id) is
+ begin
+ Active_Scenario_Stack.Append (N);
+ end Push_Active_Scenario;
+
+ -------------------
+ -- Root_Scenario --
+ -------------------
+
+ function Root_Scenario return Node_Id is
+ package Scenarios renames Active_Scenario_Stack;
+
+ begin
+ -- Ensure that the scenario stack has at least one active scenario in
+ -- it. The one at the bottom (index First) is the root scenario.
+
+ pragma Assert (Scenarios.Last >= Scenarios.First);
+ return Scenarios.Table (Scenarios.First);
+ end Root_Scenario;
+ end Active_Scenarios;
+
+ --------------------------
+ -- Activation_Processor --
+ --------------------------
+
+ package body Activation_Processor is
+
+ ------------------------
+ -- Process_Activation --
+ ------------------------
+
+ procedure Process_Activation
+ (Call : Node_Id;
+ Call_Rep : Scenario_Rep_Id;
+ Processor : Activation_Processor_Ptr;
+ In_State : Processing_In_State)
+ is
+ procedure Process_Task_Object (Obj_Id : Entity_Id; Typ : Entity_Id);
+ pragma Inline (Process_Task_Object);
+ -- Invoke Processor for task object Obj_Id of type Typ
+
+ procedure Process_Task_Objects
+ (Task_Objs : NE_List.Doubly_Linked_List);
+ pragma Inline (Process_Task_Objects);
+ -- Invoke Processor for all task objects found in list Task_Objs
+
+ procedure Traverse_List
+ (List : List_Id;
+ Task_Objs : NE_List.Doubly_Linked_List);
+ pragma Inline (Traverse_List);
+ -- Traverse declarative or statement list List while searching for
+ -- objects of a task type, or containing task components. If such an
+ -- object is found, first save it in list Task_Objs and then invoke
+ -- Processor on it.
+
+ -------------------------
+ -- Process_Task_Object --
+ -------------------------
+
+ procedure Process_Task_Object (Obj_Id : Entity_Id; Typ : Entity_Id) is
+ Root_Typ : constant Entity_Id :=
+ Non_Private_View (Root_Type (Typ));
+ Comp_Id : Entity_Id;
+ Obj_Rep : Target_Rep_Id;
+ Root_Rep : Target_Rep_Id;
+
+ New_In_State : Processing_In_State := In_State;
+ -- Each step of the Processing phase constitutes a new state
+
+ begin
+ if Is_Task_Type (Typ) then
+ Obj_Rep := Target_Representation_Of (Obj_Id, New_In_State);
+ Root_Rep := Target_Representation_Of (Root_Typ, New_In_State);
+
+ -- Warnings are suppressed when a prior scenario is already in
+ -- that mode, or when the object, activation call, or task type
+ -- have warnings suppressed. Update the state of the Processing
+ -- phase to reflect this.
+
+ New_In_State.Suppress_Warnings :=
+ New_In_State.Suppress_Warnings
+ or else not Elaboration_Warnings_OK (Call_Rep)
+ or else not Elaboration_Warnings_OK (Obj_Rep)
+ or else not Elaboration_Warnings_OK (Root_Rep);
+
+ -- Update the state of the Processing phase to indicate that
+ -- any further traversal is now within a task body.
+
+ New_In_State.Within_Task_Body := True;
+
+ -- Associate the current task type with the activation call
+
+ Set_Activated_Task_Type (Call_Rep, Root_Typ);
+
+ -- Process the activation of the current task object by calling
+ -- the supplied processor.
+
+ Processor.all
+ (Call => Call,
+ Call_Rep => Call_Rep,
+ Obj_Id => Obj_Id,
+ Obj_Rep => Obj_Rep,
+ Task_Typ => Root_Typ,
+ Task_Rep => Root_Rep,
+ In_State => New_In_State);
+
+ -- Reset the association between the current task and the
+ -- activtion call.
+
+ Set_Activated_Task_Type (Call_Rep, Empty);
+
+ -- Examine the component type when the object is an array
+
+ elsif Is_Array_Type (Typ) and then Has_Task (Root_Typ) then
+ Process_Task_Object
+ (Obj_Id => Obj_Id,
+ Typ => Component_Type (Typ));
+
+ -- Examine individual component types when the object is a record
+
+ elsif Is_Record_Type (Typ) and then Has_Task (Root_Typ) then
+ Comp_Id := First_Component (Typ);
+ while Present (Comp_Id) loop
+ Process_Task_Object
+ (Obj_Id => Obj_Id,
+ Typ => Etype (Comp_Id));
+
+ Next_Component (Comp_Id);
+ end loop;
+ end if;
+ end Process_Task_Object;
+
+ --------------------------
+ -- Process_Task_Objects --
+ --------------------------
+
+ procedure Process_Task_Objects
+ (Task_Objs : NE_List.Doubly_Linked_List)
+ is
+ Iter : NE_List.Iterator;
+ Obj_Id : Entity_Id;
+
+ begin
+ Iter := NE_List.Iterate (Task_Objs);
+ while NE_List.Has_Next (Iter) loop
+ NE_List.Next (Iter, Obj_Id);
+
+ Process_Task_Object
+ (Obj_Id => Obj_Id,
+ Typ => Etype (Obj_Id));
+ end loop;
+ end Process_Task_Objects;
+
+ -------------------
+ -- Traverse_List --
+ -------------------
+
+ procedure Traverse_List
+ (List : List_Id;
+ Task_Objs : NE_List.Doubly_Linked_List)
+ is
+ Item : Node_Id;
+ Item_Id : Entity_Id;
+ Item_Typ : Entity_Id;
+
+ begin
+ -- Examine the contents of the list looking for an object
+ -- declaration of a task type or one that contains a task
+ -- within.
+
+ Item := First (List);
+ while Present (Item) loop
+ if Nkind (Item) = N_Object_Declaration then
+ Item_Id := Defining_Entity (Item);
+ Item_Typ := Etype (Item_Id);
+
+ if Has_Task (Item_Typ) then
+
+ -- The object is either of a task type, or contains a
+ -- task component. Save it in the list of task objects
+ -- associated with the activation call.
+
+ NE_List.Append (Task_Objs, Item_Id);
+
+ Process_Task_Object
+ (Obj_Id => Item_Id,
+ Typ => Item_Typ);
+ end if;
+ end if;
+
+ Next (Item);
+ end loop;
+ end Traverse_List;
+
+ -- Local variables
+
+ Context : Node_Id;
+ Spec : Node_Id;
+ Task_Objs : NE_List.Doubly_Linked_List;
+
+ -- Start of processing for Process_Activation
+
+ begin
+ -- Nothing to do when the activation is a guaranteed ABE
+
+ if Is_Known_Guaranteed_ABE (Call) then
+ return;
+ end if;
+
+ Task_Objs := Activated_Task_Objects (Call_Rep);
+
+ -- The activation call has been processed at least once, and all
+ -- task objects have already been collected. Directly process the
+ -- objects without having to reexamine the context of the call.
+
+ if NE_List.Present (Task_Objs) then
+ Process_Task_Objects (Task_Objs);
+
+ -- Otherwise the activation call is being processed for the first
+ -- time. Collect all task objects in case the call is reprocessed
+ -- multiple times.
+
+ else
+ Task_Objs := NE_List.Create;
+ Set_Activated_Task_Objects (Call_Rep, Task_Objs);
+
+ -- Find the context of the activation call where all task objects
+ -- being activated are declared. This is usually the parent of the
+ -- call.
+
+ Context := Parent (Call);
+
+ -- Handle the case where the activation call appears within the
+ -- handled statements of a block or a body.
+
+ if Nkind (Context) = N_Handled_Sequence_Of_Statements then
+ Context := Parent (Context);
+ end if;
+
+ -- Process all task objects in both the spec and body when the
+ -- activation call appears in a package body.
+
+ if Nkind (Context) = N_Package_Body then
+ Spec :=
+ Specification
+ (Unit_Declaration_Node (Corresponding_Spec (Context)));
+
+ Traverse_List
+ (List => Visible_Declarations (Spec),
+ Task_Objs => Task_Objs);
+
+ Traverse_List
+ (List => Private_Declarations (Spec),
+ Task_Objs => Task_Objs);
+
+ Traverse_List
+ (List => Declarations (Context),
+ Task_Objs => Task_Objs);
+
+ -- Process all task objects in the spec when the activation call
+ -- appears in a package spec.
+
+ elsif Nkind (Context) = N_Package_Specification then
+ Traverse_List
+ (List => Visible_Declarations (Context),
+ Task_Objs => Task_Objs);
+
+ Traverse_List
+ (List => Private_Declarations (Context),
+ Task_Objs => Task_Objs);
+
+ -- Otherwise the context must be a block or a body. Process all
+ -- task objects found in the declarations.
+
+ else
+ pragma Assert (Nkind_In (Context, N_Block_Statement,
+ N_Entry_Body,
+ N_Protected_Body,
+ N_Subprogram_Body,
+ N_Task_Body));
+
+ Traverse_List
+ (List => Declarations (Context),
+ Task_Objs => Task_Objs);
+ end if;
+ end if;
+ end Process_Activation;
+ end Activation_Processor;
+
+ -----------------------
+ -- Assignment_Target --
+ -----------------------
+
+ function Assignment_Target (Asmt : Node_Id) return Node_Id is
+ Nam : Node_Id;
+
+ begin
+ Nam := Name (Asmt);
+
+ -- When the name denotes an array or record component, find the whole
+ -- object.
+
+ while Nkind_In (Nam, N_Explicit_Dereference,
+ N_Indexed_Component,
+ N_Selected_Component,
+ N_Slice)
+ loop
+ Nam := Prefix (Nam);
+ end loop;
+
+ return Nam;
+ end Assignment_Target;
+
+ --------------------
+ -- Body_Processor --
+ --------------------
+
+ package body Body_Processor is
+
+ ---------------------
+ -- Data structures --
+ ---------------------
+
+ -- The following map relates scenario lists to subprogram bodies
+
+ Nested_Scenarios_Map : NE_List_Map.Dynamic_Hash_Table := NE_List_Map.Nil;
+
+ -- The following set contains all subprogram bodies that have been
+ -- processed by routine Traverse_Body.
+
+ Traversed_Bodies_Set : NE_Set.Membership_Set := NE_Set.Nil;
+
+ -----------------------
+ -- Local subprograms --
+ -----------------------
+
+ function Is_Traversed_Body (N : Node_Id) return Boolean;
+ pragma Inline (Is_Traversed_Body);
+ -- Determine whether subprogram body N has already been traversed
+
+ function Nested_Scenarios
+ (N : Node_Id) return NE_List.Doubly_Linked_List;
+ pragma Inline (Nested_Scenarios);
+ -- Obtain the list of scenarios associated with subprogram body N
+
+ procedure Set_Is_Traversed_Body
+ (N : Node_Id;
+ Val : Boolean := True);
+ pragma Inline (Set_Is_Traversed_Body);
+ -- Mark subprogram body N as traversed depending on value Val
+
+ procedure Set_Nested_Scenarios
+ (N : Node_Id;
+ Scenarios : NE_List.Doubly_Linked_List);
+ pragma Inline (Set_Nested_Scenarios);
+ -- Associate scenario list Scenarios with subprogram body N
+
+ -----------------------------
+ -- Finalize_Body_Processor --
+ -----------------------------
+
+ procedure Finalize_Body_Processor is
+ begin
+ NE_List_Map.Destroy (Nested_Scenarios_Map);
+ NE_Set.Destroy (Traversed_Bodies_Set);
+ end Finalize_Body_Processor;
+
+ -------------------------------
+ -- Initialize_Body_Processor --
+ -------------------------------
+
+ procedure Initialize_Body_Processor is
+ begin
+ Nested_Scenarios_Map := NE_List_Map.Create (250);
+ Traversed_Bodies_Set := NE_Set.Create (250);
+ end Initialize_Body_Processor;
+
+ -----------------------
+ -- Is_Traversed_Body --
+ -----------------------
+
+ function Is_Traversed_Body (N : Node_Id) return Boolean is
+ pragma Assert (Present (N));
+ begin
+ return NE_Set.Contains (Traversed_Bodies_Set, N);
+ end Is_Traversed_Body;
+
+ ----------------------
+ -- Nested_Scenarios --
+ ----------------------
+
+ function Nested_Scenarios
+ (N : Node_Id) return NE_List.Doubly_Linked_List
+ is
+ pragma Assert (Present (N));
+ pragma Assert (Nkind (N) = N_Subprogram_Body);
+
+ begin
+ return NE_List_Map.Get (Nested_Scenarios_Map, N);
+ end Nested_Scenarios;
+
+ ----------------------------
+ -- Reset_Traversed_Bodies --
+ ----------------------------
+
+ procedure Reset_Traversed_Bodies is
+ begin
+ NE_Set.Reset (Traversed_Bodies_Set);
+ end Reset_Traversed_Bodies;
+
+ ---------------------------
+ -- Set_Is_Traversed_Body --
+ ---------------------------
+
+ procedure Set_Is_Traversed_Body
+ (N : Node_Id;
+ Val : Boolean := True)
+ is
+ pragma Assert (Present (N));
+
+ begin
+ if Val then
+ NE_Set.Insert (Traversed_Bodies_Set, N);
+ else
+ NE_Set.Delete (Traversed_Bodies_Set, N);
+ end if;
+ end Set_Is_Traversed_Body;
+
+ --------------------------
+ -- Set_Nested_Scenarios --
+ --------------------------
+
+ procedure Set_Nested_Scenarios
+ (N : Node_Id;
+ Scenarios : NE_List.Doubly_Linked_List)
+ is
+ pragma Assert (Present (N));
+ begin
+ NE_List_Map.Put (Nested_Scenarios_Map, N, Scenarios);
+ end Set_Nested_Scenarios;
+
+ -------------------
+ -- Traverse_Body --
+ -------------------
+
+ procedure Traverse_Body
+ (N : Node_Id;
+ Requires_Processing : Scenario_Predicate_Ptr;
+ Processor : Scenario_Processor_Ptr;
+ In_State : Processing_In_State)
+ is
+ Scenarios : NE_List.Doubly_Linked_List := NE_List.Nil;
+ -- The list of scenarios that appear within the declarations and
+ -- statement of subprogram body N. The variable is intentionally
+ -- global because Is_Potential_Scenario needs to populate it.
+
+ function In_Task_Body (Nod : Node_Id) return Boolean;
+ pragma Inline (In_Task_Body);
+ -- Determine whether arbitrary node Nod appears within a task body
+
+ function Is_Synchronous_Suspension_Call
+ (Nod : Node_Id) return Boolean;
+ pragma Inline (Is_Synchronous_Suspension_Call);
+ -- Determine whether arbitrary node Nod denotes a call to one of
+ -- these routines:
+ --
+ -- Ada.Synchronous_Barriers.Wait_For_Release
+ -- Ada.Synchronous_Task_Control.Suspend_Until_True
+
+ procedure Traverse_Collected_Scenarios;
+ pragma Inline (Traverse_Collected_Scenarios);
+ -- Traverse the already collected scenarios in list Scenarios by
+ -- invoking Processor on each individual one.
+
+ procedure Traverse_List (List : List_Id);
+ pragma Inline (Traverse_List);
+ -- Invoke Traverse_Potential_Scenarios on each node in list List
+
+ function Traverse_Potential_Scenario
+ (Scen : Node_Id) return Traverse_Result;
+ pragma Inline (Traverse_Potential_Scenario);
+ -- Determine whether arbitrary node Scen is a suitable scenario using
+ -- predicate Is_Scenario and traverse it by invoking Processor on it.
+
+ procedure Traverse_Potential_Scenarios is
+ new Traverse_Proc (Traverse_Potential_Scenario);
+
+ ------------------
+ -- In_Task_Body --
+ ------------------
+
+ function In_Task_Body (Nod : Node_Id) return Boolean is
+ Par : Node_Id;
+
+ begin
+ -- Climb the parent chain looking for a task body [procedure]
+
+ Par := Nod;
+ while Present (Par) loop
+ if Nkind (Par) = N_Task_Body then
+ return True;
+
+ elsif Nkind (Par) = N_Subprogram_Body
+ and then Is_Task_Body_Procedure (Par)
+ then
+ return True;
+
+ -- Prevent the search from going too far. Note that this test
+ -- shares nodes with the two cases above, and must come last.
+
+ elsif Is_Body_Or_Package_Declaration (Par) then
+ return False;
+ end if;
+
+ Par := Parent (Par);
+ end loop;
+
+ return False;
+ end In_Task_Body;
+
+ ------------------------------------
+ -- Is_Synchronous_Suspension_Call --
+ ------------------------------------
+
+ function Is_Synchronous_Suspension_Call
+ (Nod : Node_Id) return Boolean
+ is
+ Subp_Id : Entity_Id;
+
+ begin
+ -- To qualify, the call must invoke one of the runtime routines
+ -- which perform synchronous suspension.
+
+ if Is_Suitable_Call (Nod) then
+ Subp_Id := Target (Nod);
+
+ return
+ Is_RTE (Subp_Id, RE_Suspend_Until_True)
+ or else
+ Is_RTE (Subp_Id, RE_Wait_For_Release);
+ end if;
+
+ return False;
+ end Is_Synchronous_Suspension_Call;
+
+ ----------------------------------
+ -- Traverse_Collected_Scenarios --
+ ----------------------------------
+
+ procedure Traverse_Collected_Scenarios is
+ Iter : NE_List.Iterator;
+ Scen : Node_Id;
+
+ begin
+ Iter := NE_List.Iterate (Scenarios);
+ while NE_List.Has_Next (Iter) loop
+ NE_List.Next (Iter, Scen);
+
+ -- The current scenario satisfies the input predicate, process
+ -- it.
+
+ if Requires_Processing.all (Scen) then
+ Processor.all (Scen, In_State);
+ end if;
+ end loop;
+ end Traverse_Collected_Scenarios;
+
+ -------------------
+ -- Traverse_List --
+ -------------------
+
+ procedure Traverse_List (List : List_Id) is
+ Scen : Node_Id;
+
+ begin
+ Scen := First (List);
+ while Present (Scen) loop
+ Traverse_Potential_Scenarios (Scen);
+ Next (Scen);
+ end loop;
+ end Traverse_List;
+
+ ---------------------------------
+ -- Traverse_Potential_Scenario --
+ ---------------------------------
+
+ function Traverse_Potential_Scenario
+ (Scen : Node_Id) return Traverse_Result
+ is
+ begin
+ -- Special cases
+
+ -- Skip constructs which do not have elaboration of their own and
+ -- need to be elaborated by other means such as invocation, task
+ -- activation, etc.
+
+ if Is_Non_Library_Level_Encapsulator (Scen) then
+ return Skip;
+
+ -- Terminate the traversal of a task body when encountering an
+ -- accept or select statement, and
+ --
+ -- * Entry calls during elaboration are not allowed. In this
+ -- case the accept or select statement will cause the task
+ -- to block at elaboration time because there are no entry
+ -- calls to unblock it.
+ --
+ -- or
+ --
+ -- * Switch -gnatd_a (stop elaboration checks on accept or
+ -- select statement) is in effect.
+
+ elsif (Debug_Flag_Underscore_A
+ or else Restriction_Active
+ (No_Entry_Calls_In_Elaboration_Code))
+ and then Nkind_In (Original_Node (Scen), N_Accept_Statement,
+ N_Selective_Accept)
+ then
+ return Abandon;
+
+ -- Terminate the traversal of a task body when encountering a
+ -- suspension call, and
+ --
+ -- * Entry calls during elaboration are not allowed. In this
+ -- case the suspension call emulates an entry call and will
+ -- cause the task to block at elaboration time.
+ --
+ -- or
+ --
+ -- * Switch -gnatd_s (stop elaboration checks on synchronous
+ -- suspension) is in effect.
+ --
+ -- Note that the guard should not be checking the state of flag
+ -- Within_Task_Body because only suspension calls which appear
+ -- immediately within the statements of the task are supported.
+ -- Flag Within_Task_Body carries over to deeper levels of the
+ -- traversal.
+
+ elsif (Debug_Flag_Underscore_S
+ or else Restriction_Active
+ (No_Entry_Calls_In_Elaboration_Code))
+ and then Is_Synchronous_Suspension_Call (Scen)
+ and then In_Task_Body (Scen)
+ then
+ return Abandon;
+
+ -- Certain nodes carry semantic lists which act as repositories
+ -- until expansion transforms the node and relocates the contents.
+ -- Examine these lists in case expansion is disabled.
+
+ elsif Nkind_In (Scen, N_And_Then, N_Or_Else) then
+ Traverse_List (Actions (Scen));
+
+ elsif Nkind_In (Scen, N_Elsif_Part, N_Iteration_Scheme) then
+ Traverse_List (Condition_Actions (Scen));
+
+ elsif Nkind (Scen) = N_If_Expression then
+ Traverse_List (Then_Actions (Scen));
+ Traverse_List (Else_Actions (Scen));
+
+ elsif Nkind_In (Scen, N_Component_Association,
+ N_Iterated_Component_Association)
+ then
+ Traverse_List (Loop_Actions (Scen));
+
+ -- General case
+
+ -- The current node satisfies the input predicate, process it
+
+ elsif Requires_Processing.all (Scen) then
+ Processor.all (Scen, In_State);
+ end if;
+
+ -- Save a general scenario regardless of whether it satisfies the
+ -- input predicate. This allows for quick subsequent traversals of
+ -- general scenarios, even with different predicates.
+
+ if Is_Suitable_Access_Taken (Scen)
+ or else Is_Suitable_Call (Scen)
+ or else Is_Suitable_Instantiation (Scen)
+ or else Is_Suitable_Variable_Assignment (Scen)
+ or else Is_Suitable_Variable_Reference (Scen)
+ then
+ NE_List.Append (Scenarios, Scen);
+ end if;
+
+ return OK;
+ end Traverse_Potential_Scenario;
+
+ -- Start of processing for Traverse_Body
+
+ begin
+ -- Nothing to do when the traversal is suppressed
+
+ if In_State.Traversal = No_Traversal then
+ return;
+
+ -- Nothing to do when there is no input
+
+ elsif No (N) then
+ return;
+
+ -- Nothing to do when the input is not a subprogram body
+
+ elsif Nkind (N) /= N_Subprogram_Body then
+ return;
+
+ -- Nothing to do if the subprogram body was already traversed
+
+ elsif Is_Traversed_Body (N) then
+ return;
+ end if;
+
+ -- Mark the subprogram body as traversed
+
+ Set_Is_Traversed_Body (N);
+
+ Scenarios := Nested_Scenarios (N);
+
+ -- The subprogram body has been traversed at least once, and all
+ -- scenarios that appear within its declarations and statements
+ -- have already been collected. Directly retraverse the scenarios
+ -- without having to retraverse the subprogram body subtree.
+
+ if NE_List.Present (Scenarios) then
+ Traverse_Collected_Scenarios;
+
+ -- Otherwise the subprogram body is being traversed for the first
+ -- time. Collect all scenarios that appear within its declarations
+ -- and statements in case the subprogram body has to be retraversed
+ -- multiple times.
+
+ else
+ Scenarios := NE_List.Create;
+ Set_Nested_Scenarios (N, Scenarios);
+
+ Traverse_List (Declarations (N));
+ Traverse_Potential_Scenarios (Handled_Statement_Sequence (N));
+ end if;
+ end Traverse_Body;
+ end Body_Processor;
-----------------------
-- Build_Call_Marker --
@@ -1882,19 +3393,16 @@ package body Sem_Elab is
procedure Build_Call_Marker (N : Node_Id) is
function In_External_Context
- (Call : Node_Id;
- Target_Attrs : Target_Attributes) return Boolean;
+ (Call : Node_Id;
+ Subp_Id : Entity_Id) return Boolean;
pragma Inline (In_External_Context);
- -- Determine whether a target described by attributes Target_Attrs is
- -- external to call Call which must reside within an instance.
+ -- Determine whether entry, operator, or subprogram Subp_Id is external
+ -- to call Call which must reside within an instance.
function In_Premature_Context (Call : Node_Id) return Boolean;
+ pragma Inline (In_Premature_Context);
-- Determine whether call Call appears within a premature context
- function Is_Bridge_Target (Id : Entity_Id) return Boolean;
- pragma Inline (Is_Bridge_Target);
- -- Determine whether arbitrary entity Id denotes a bridge target
-
function Is_Default_Expression (Call : Node_Id) return Boolean;
pragma Inline (Is_Default_Expression);
-- Determine whether call Call acts as the expression of a defaulted
@@ -1910,16 +3418,16 @@ package body Sem_Elab is
-------------------------
function In_External_Context
- (Call : Node_Id;
- Target_Attrs : Target_Attributes) return Boolean
+ (Call : Node_Id;
+ Subp_Id : Entity_Id) return Boolean
is
+ Spec_Decl : constant Entity_Id := Unit_Declaration_Node (Subp_Id);
+
Inst : Node_Id;
Inst_Body : Node_Id;
- Inst_Decl : Node_Id;
+ Inst_Spec : Node_Id;
begin
- -- Performance note: parent traversal
-
Inst := Find_Enclosing_Instance (Call);
-- The call appears within an instance
@@ -1929,7 +3437,7 @@ package body Sem_Elab is
-- The call comes from the main unit and the target does not
if In_Extended_Main_Code_Unit (Call)
- and then not In_Extended_Main_Code_Unit (Target_Attrs.Spec_Decl)
+ and then not In_Extended_Main_Code_Unit (Spec_Decl)
then
return True;
@@ -1937,16 +3445,14 @@ package body Sem_Elab is
-- instance spec or body.
else
- Extract_Instance_Attributes
- (Exp_Inst => Inst,
- Inst_Decl => Inst_Decl,
- Inst_Body => Inst_Body);
-
- -- Performance note: parent traversal
+ Spec_And_Body_From_Node
+ (N => Inst,
+ Spec_Decl => Inst_Spec,
+ Body_Decl => Inst_Body);
return not In_Subtree
- (N => Target_Attrs.Spec_Decl,
- Root1 => Inst_Decl,
+ (N => Spec_Decl,
+ Root1 => Inst_Spec,
Root2 => Inst_Body);
end if;
end if;
@@ -1988,22 +3494,6 @@ package body Sem_Elab is
return False;
end In_Premature_Context;
- ----------------------
- -- Is_Bridge_Target --
- ----------------------
-
- function Is_Bridge_Target (Id : Entity_Id) return Boolean is
- begin
- return
- Is_Accept_Alternative_Proc (Id)
- or else Is_Finalizer_Proc (Id)
- or else Is_Partial_Invariant_Proc (Id)
- or else Is_Postconditions_Proc (Id)
- or else Is_TSS (Id, TSS_Deep_Adjust)
- or else Is_TSS (Id, TSS_Deep_Finalize)
- or else Is_TSS (Id, TSS_Deep_Initialize);
- end Is_Bridge_Target;
-
---------------------------
-- Is_Default_Expression --
---------------------------
@@ -2021,7 +3511,7 @@ package body Sem_Elab is
N_Procedure_Call_Statement)
and then Comes_From_Source (Outer_Call)
then
- Outer_Nam := Extract_Call_Name (Outer_Call);
+ Outer_Nam := Call_Name (Outer_Call);
return
Is_Entity_Name (Outer_Nam)
@@ -2056,11 +3546,9 @@ package body Sem_Elab is
-- Local variables
- Call_Attrs : Call_Attributes;
- Call_Nam : Node_Id;
- Marker : Node_Id;
- Target_Attrs : Target_Attributes;
- Target_Id : Entity_Id;
+ Call_Nam : Node_Id;
+ Marker : Node_Id;
+ Subp_Id : Entity_Id;
-- Start of processing for Build_Call_Marker
@@ -2101,9 +3589,16 @@ package body Sem_Elab is
and then Nkind_In (N, N_Entry_Call_Statement, N_Requeue_Statement)
then
return;
+
+ -- Nothing to do when the call is analyzed/resolved too early within an
+ -- intermediate context. This check is saved for last because it incurs
+ -- a performance penalty.
+
+ elsif In_Premature_Context (N) then
+ return;
end if;
- Call_Nam := Extract_Call_Name (N);
+ Call_Nam := Call_Name (N);
-- Nothing to do when the call is erroneous or left in a bad state
@@ -2112,6 +3607,9 @@ package body Sem_Elab is
and then Is_Subprogram_Or_Entry (Entity (Call_Nam)))
then
return;
+ end if;
+
+ Subp_Id := Canonical_Subprogram (Entity (Call_Nam));
-- Nothing to do when the call invokes a generic formal subprogram and
-- switch -gnatd.G (ignore calls through generic formal parameters for
@@ -2119,44 +3617,24 @@ package body Sem_Elab is
-- direct target of the call to avoid the side effects of mapping
-- actuals to formals using renamings.
- elsif Debug_Flag_Dot_GG
+ if Debug_Flag_Dot_GG
and then Is_Generic_Formal_Subp (Entity (Call_Nam))
then
return;
- -- Nothing to do when the call is analyzed/resolved too early within an
- -- intermediate context. This check is saved for last because it incurs
- -- a performance penalty.
-
- -- Performance note: parent traversal
-
- elsif In_Premature_Context (N) then
- return;
- end if;
-
- Extract_Call_Attributes
- (Call => N,
- Target_Id => Target_Id,
- Attrs => Call_Attrs);
-
- Extract_Target_Attributes
- (Target_Id => Target_Id,
- Attrs => Target_Attrs);
-
-- Nothing to do when the call appears within the expanded spec or
-- body of an instantiated generic, the call does not invoke a generic
-- formal subprogram, the target is external to the instance, and switch
-- -gnatdL (ignore external calls from instances for elaboration) is in
- -- effect.
+ -- effect. This check must be performed with the direct target of the
+ -- call to avoid the side effects of mapping actuals to formals using
+ -- renamings.
- if Debug_Flag_LL
+ elsif Debug_Flag_LL
and then not Is_Generic_Formal_Subp (Entity (Call_Nam))
-
- -- Performance note: parent traversal
-
and then In_External_Context
- (Call => N,
- Target_Attrs => Target_Attrs)
+ (Call => N,
+ Subp_Id => Subp_Id)
then
return;
@@ -2165,20 +3643,20 @@ package body Sem_Elab is
-- in effect.
elsif Debug_Flag_Underscore_P
- and then Is_Assertion_Pragma_Target (Target_Id)
+ and then Is_Assertion_Pragma_Target (Subp_Id)
then
return;
-- Source calls to source targets are always considered because they
-- reflect the original call graph.
- elsif Target_Attrs.From_Source and then Call_Attrs.From_Source then
+ elsif Comes_From_Source (N) and then Comes_From_Source (Subp_Id) then
null;
-- A call to a source function which acts as the default expression in
-- another call requires special detection.
- elsif Target_Attrs.From_Source
+ elsif Comes_From_Source (Subp_Id)
and then Nkind (N) = N_Function_Call
and then Is_Default_Expression (N)
then
@@ -2186,17 +3664,17 @@ package body Sem_Elab is
-- The target emulates Ada semantics
- elsif Is_Ada_Semantic_Target (Target_Id) then
+ elsif Is_Ada_Semantic_Target (Subp_Id) then
null;
-- The target acts as a link between scenarios
- elsif Is_Bridge_Target (Target_Id) then
+ elsif Is_Bridge_Target (Subp_Id) then
null;
-- The target emulates SPARK semantics
- elsif Is_SPARK_Semantic_Target (Target_Id) then
+ elsif Is_SPARK_Semantic_Target (Subp_Id) then
null;
-- Otherwise the call is not suitable for ABE processing. This prevents
@@ -2215,16 +3693,23 @@ package body Sem_Elab is
-- Inherit the attributes of the original call
- Set_Target (Marker, Target_Id);
- Set_Is_Declaration_Level_Node (Marker, Call_Attrs.In_Declarations);
- Set_Is_Dispatching_Call (Marker, Call_Attrs.Is_Dispatching);
+ Set_Is_Declaration_Level_Node
+ (Marker, Find_Enclosing_Level (N) = Declaration_Level);
+
+ Set_Is_Dispatching_Call
+ (Marker, Nkind_In (N, N_Function_Call, N_Procedure_Call_Statement)
+ and then Present (Controlling_Argument (N)));
+
Set_Is_Elaboration_Checks_OK_Node
- (Marker, Call_Attrs.Elab_Checks_OK);
+ (Marker, Is_Elaboration_Checks_OK_Node (N));
+
Set_Is_Elaboration_Warnings_OK_Node
- (Marker, Call_Attrs.Elab_Warnings_OK);
- Set_Is_Ignored_Ghost_Node (Marker, Call_Attrs.Ghost_Mode_Ignore);
- Set_Is_Source_Call (Marker, Call_Attrs.From_Source);
- Set_Is_SPARK_Mode_On_Node (Marker, Call_Attrs.SPARK_Mode_On);
+ (Marker, Is_Elaboration_Warnings_OK_Node (N));
+
+ Set_Is_Ignored_Ghost_Node (Marker, Is_Ignored_Ghost_Node (N));
+ Set_Is_Source_Call (Marker, Comes_From_Source (N));
+ Set_Is_SPARK_Mode_On_Node (Marker, Is_SPARK_Mode_On_Node (N));
+ Set_Target (Marker, Subp_Id);
-- The marker is inserted prior to the original call. This placement has
-- several desirable effects:
@@ -2274,23 +3759,50 @@ package body Sem_Elab is
Read : Boolean;
Write : Boolean)
is
- Marker : Node_Id;
- Var_Attrs : Variable_Attributes;
- Var_Id : Entity_Id;
+ function Ultimate_Variable (Var_Id : Entity_Id) return Entity_Id;
+ pragma Inline (Ultimate_Variable);
+ -- Obtain the ultimate renamed variable of variable Var_Id
- begin
- Extract_Variable_Reference_Attributes
- (Ref => N,
- Var_Id => Var_Id,
- Attrs => Var_Attrs);
+ -----------------------
+ -- Ultimate_Variable --
+ -----------------------
+
+ function Ultimate_Variable (Var_Id : Entity_Id) return Entity_Id is
+ Ren_Id : Entity_Id;
+
+ begin
+ Ren_Id := Var_Id;
+ while Present (Renamed_Entity (Ren_Id))
+ and then Nkind (Renamed_Entity (Ren_Id)) in N_Entity
+ loop
+ Ren_Id := Renamed_Entity (Ren_Id);
+ end loop;
+ return Ren_Id;
+ end Ultimate_Variable;
+
+ -- Local variables
+
+ Var_Id : constant Entity_Id := Ultimate_Variable (Entity (N));
+ Marker : Node_Id;
+
+ -- Start of processing for Build_Variable_Reference_Marker
+
+ begin
Marker := Make_Variable_Reference_Marker (Sloc (N));
-- Inherit the attributes of the original variable reference
- Set_Target (Marker, Var_Id);
- Set_Is_Read (Marker, Read);
- Set_Is_Write (Marker, Write);
+ Set_Is_Elaboration_Checks_OK_Node
+ (Marker, Is_Elaboration_Checks_OK_Node (N));
+
+ Set_Is_Elaboration_Warnings_OK_Node
+ (Marker, Is_Elaboration_Warnings_OK_Node (N));
+
+ Set_Is_Read (Marker, Read);
+ Set_Is_SPARK_Mode_On_Node (Marker, Is_SPARK_Mode_On_Node (N));
+ Set_Is_Write (Marker, Write);
+ Set_Target (Marker, Var_Id);
-- The marker is inserted prior to the original variable reference. The
-- insertion must take place even when the reference does not occur in
@@ -2306,11 +3818,69 @@ package body Sem_Elab is
Record_Elaboration_Scenario (Marker);
end Build_Variable_Reference_Marker;
+ ---------------
+ -- Call_Name --
+ ---------------
+
+ function Call_Name (Call : Node_Id) return Node_Id is
+ Nam : Node_Id;
+
+ begin
+ Nam := Name (Call);
+
+ -- When the call invokes an entry family, the name appears as an indexed
+ -- component.
+
+ if Nkind (Nam) = N_Indexed_Component then
+ Nam := Prefix (Nam);
+ end if;
+
+ -- When the call employs the object.operation form, the name appears as
+ -- a selected component.
+
+ if Nkind (Nam) = N_Selected_Component then
+ Nam := Selector_Name (Nam);
+ end if;
+
+ return Nam;
+ end Call_Name;
+
+ --------------------------
+ -- Canonical_Subprogram --
+ --------------------------
+
+ function Canonical_Subprogram (Subp_Id : Entity_Id) return Entity_Id is
+ Canon_Id : Entity_Id;
+
+ begin
+ Canon_Id := Subp_Id;
+
+ -- Use the original protected subprogram when dealing with one of the
+ -- specialized lock-manipulating versions.
+
+ if Is_Protected_Body_Subp (Canon_Id) then
+ Canon_Id := Protected_Subprogram (Canon_Id);
+ end if;
+
+ -- Obtain the original subprogram except when the subprogram is also
+ -- an instantiation. In this case the alias is the internally generated
+ -- subprogram which appears within the anonymous package created for the
+ -- instantiation, making it unuitable.
+
+ if not Is_Generic_Instance (Canon_Id) then
+ Canon_Id := Get_Renamed_Entity (Canon_Id);
+ end if;
+
+ return Canon_Id;
+ end Canonical_Subprogram;
+
---------------------------------
-- Check_Elaboration_Scenarios --
---------------------------------
procedure Check_Elaboration_Scenarios is
+ Iter : NE_Set.Iterator;
+
begin
-- Nothing to do when switch -gnatH (legacy elaboration checking mode
-- enabled) is in effect because the legacy ABE mechanism does not need
@@ -2326,6 +3896,15 @@ package body Sem_Elab is
return;
end if;
+ -- Create all internal data structures
+
+ Initialize_Body_Processor;
+ Initialize_Early_Call_Region_Processor;
+ Initialize_Elaborated_Units;
+ Initialize_Internal_Representation;
+ Initialize_Invocation_Graph;
+ Initialize_Scenario_Storage;
+
-- Restore the original elaboration model which was in effect when the
-- scenarios were first recorded. The model may be specified by pragma
-- Elaboration_Checks which appears on the initial declaration of the
@@ -2336,2996 +3915,4910 @@ package body Sem_Elab is
-- Examine the context of the main unit and record all units with prior
-- elaboration with respect to it.
- Find_Elaborated_Units;
+ Collect_Elaborated_Units;
- -- Examine each top-level scenario saved during the Recording phase for
- -- conditional ABEs and perform various actions depending on the model
- -- in effect. The table of visited bodies is created for each new top-
- -- level scenario.
+ -- Examine all scenarios saved during the Recording phase applying the
+ -- Ada or SPARK elaboration rules in order to detect and diagnose ABE
+ -- issues, install conditional ABE checks, and ensure the elaboration
+ -- of units.
- for Index in Top_Level_Scenarios.First .. Top_Level_Scenarios.Last loop
- Reset_Visited_Bodies;
+ Iter := Iterate_Declaration_Scenarios;
+ Check_Conditional_ABE_Scenarios (Iter);
- Process_Conditional_ABE (Top_Level_Scenarios.Table (Index));
- end loop;
+ Iter := Iterate_Library_Body_Scenarios;
+ Check_Conditional_ABE_Scenarios (Iter);
+
+ Iter := Iterate_Library_Spec_Scenarios;
+ Check_Conditional_ABE_Scenarios (Iter);
-- Examine each SPARK scenario saved during the Recording phase which
-- is not necessarily executable during elaboration, but still requires
-- elaboration-related checks.
- for Index in SPARK_Scenarios.First .. SPARK_Scenarios.Last loop
- Check_SPARK_Scenario (SPARK_Scenarios.Table (Index));
- end loop;
+ Check_SPARK_Scenarios;
+
+ -- Add conditional ABE checks for all scenarios that require one when
+ -- the dynamic model is in effect.
+
+ Install_Dynamic_ABE_Checks;
+
+ -- Examine all scenarios saved during the Recording phase along with
+ -- invocation constructs within the spec and body of the main unit.
+ -- Record the declarations and paths that reach into an external unit
+ -- in the ALI file of the main unit.
+
+ Record_Invocation_Graph;
+
+ -- Destroy all internal data structures
+
+ Finalize_Body_Processor;
+ Finalize_Early_Call_Region_Processor;
+ Finalize_Elaborated_Units;
+ Finalize_Internal_Representation;
+ Finalize_Invocation_Graph;
+ Finalize_Scenario_Storage;
end Check_Elaboration_Scenarios;
- ------------------------------
- -- Check_Preelaborated_Call --
- ------------------------------
+ ---------------------
+ -- Check_Installer --
+ ---------------------
- procedure Check_Preelaborated_Call (Call : Node_Id) is
- function In_Preelaborated_Context (N : Node_Id) return Boolean;
- -- Determine whether arbitrary node appears in a preelaborated context
+ package body Check_Installer is
- ------------------------------
- -- In_Preelaborated_Context --
- ------------------------------
+ -----------------------
+ -- Local subprograms --
+ -----------------------
- function In_Preelaborated_Context (N : Node_Id) return Boolean is
- Body_Id : constant Entity_Id := Find_Code_Unit (N);
- Spec_Id : constant Entity_Id := Unique_Entity (Body_Id);
+ function ABE_Check_Or_Failure_OK
+ (N : Node_Id;
+ Targ_Id : Entity_Id;
+ Unit_Id : Entity_Id) return Boolean;
+ pragma Inline (ABE_Check_Or_Failure_OK);
+ -- Determine whether a conditional ABE check or guaranteed ABE failure
+ -- can be installed for scenario N with target Targ_Id which resides in
+ -- unit Unit_Id.
+
+ function Insertion_Node (N : Node_Id) return Node_Id;
+ pragma Inline (Insertion_Node);
+ -- Obtain the proper insertion node of an ABE check or failure for
+ -- scenario N.
+
+ procedure Insert_ABE_Check_Or_Failure (N : Node_Id; Check : Node_Id);
+ pragma Inline (Insert_ABE_Check_Or_Failure);
+ -- Insert conditional ABE check or guaranteed ABE failure Check prior to
+ -- scenario N.
+
+ procedure Install_Scenario_ABE_Check_Common
+ (N : Node_Id;
+ Targ_Id : Entity_Id;
+ Targ_Rep : Target_Rep_Id);
+ pragma Inline (Install_Scenario_ABE_Check_Common);
+ -- Install a conditional ABE check for scenario N to ensure that target
+ -- Targ_Id is properly elaborated. Targ_Rep is the representation of the
+ -- target.
+
+ procedure Install_Scenario_ABE_Failure_Common (N : Node_Id);
+ pragma Inline (Install_Scenario_ABE_Failure_Common);
+ -- Install a guaranteed ABE failure for scenario N
+
+ procedure Install_Unit_ABE_Check_Common
+ (N : Node_Id;
+ Unit_Id : Entity_Id);
+ pragma Inline (Install_Unit_ABE_Check_Common);
+ -- Install a conditional ABE check for scenario N to ensure that unit
+ -- Unit_Id is properly elaborated.
+
+ -----------------------------
+ -- ABE_Check_Or_Failure_OK --
+ -----------------------------
+
+ function ABE_Check_Or_Failure_OK
+ (N : Node_Id;
+ Targ_Id : Entity_Id;
+ Unit_Id : Entity_Id) return Boolean
+ is
+ pragma Unreferenced (Targ_Id);
+
+ Ins_Node : constant Node_Id := Insertion_Node (N);
begin
- -- The node appears within a package body whose corresponding spec is
- -- subject to pragma Remote_Call_Interface or Remote_Types. This does
- -- not result in a preelaborated context because the package body may
- -- be on another machine.
+ if not Check_Or_Failure_Generation_OK then
+ return False;
- if Ekind (Body_Id) = E_Package_Body
- and then Ekind_In (Spec_Id, E_Generic_Package, E_Package)
- and then (Is_Remote_Call_Interface (Spec_Id)
- or else Is_Remote_Types (Spec_Id))
+ -- Nothing to do when the scenario denots a compilation unit because
+ -- there is no executable environment at that level.
+
+ elsif Nkind (Parent (Ins_Node)) = N_Compilation_Unit then
+ return False;
+
+ -- An ABE check or failure is not needed when the target is defined
+ -- in a unit which is elaborated prior to the main unit. This check
+ -- must also consider the following cases:
+ --
+ -- * The unit of the target appears in the context of the main unit
+ --
+ -- * The unit of the target is subject to pragma Elaborate_Body. An
+ -- ABE check MUST NOT be generated because the unit is always
+ -- elaborated prior to the main unit.
+ --
+ -- * The unit of the target is the main unit. An ABE check MUST be
+ -- added in this case because a conditional ABE may be raised
+ -- depending on the flow of execution within the main unit (flag
+ -- Same_Unit_OK is False).
+
+ elsif Has_Prior_Elaboration
+ (Unit_Id => Unit_Id,
+ Context_OK => True,
+ Elab_Body_OK => True)
then
return False;
+ end if;
- -- Otherwise the node appears within a preelaborated context when the
- -- associated unit is preelaborated.
+ return True;
+ end ABE_Check_Or_Failure_OK;
- else
- return Is_Preelaborated_Unit (Spec_Id);
- end if;
- end In_Preelaborated_Context;
+ ------------------------------------
+ -- Check_Or_Failure_Generation_OK --
+ ------------------------------------
- -- Local variables
+ function Check_Or_Failure_Generation_OK return Boolean is
+ begin
+ -- An ABE check or failure is not needed when the compilation will
+ -- not produce an executable.
- Call_Attrs : Call_Attributes;
- Level : Enclosing_Level_Kind;
- Target_Id : Entity_Id;
+ if Serious_Errors_Detected > 0 then
+ return False;
- -- Start of processing for Check_Preelaborated_Call
+ -- An ABE check or failure must not be installed when compiling for
+ -- GNATprove because raise statements are not supported.
- begin
- Extract_Call_Attributes
- (Call => Call,
- Target_Id => Target_Id,
- Attrs => Call_Attrs);
+ elsif GNATprove_Mode then
+ return False;
+ end if;
- -- Nothing to do when the call is internally generated because it is
- -- assumed that it will never violate preelaboration.
+ return True;
+ end Check_Or_Failure_Generation_OK;
- if not Call_Attrs.From_Source then
- return;
- end if;
+ --------------------
+ -- Insertion_Node --
+ --------------------
- -- Performance note: parent traversal
+ function Insertion_Node (N : Node_Id) return Node_Id is
+ begin
+ -- When the scenario denotes an instantiation, the proper insertion
+ -- node is the instance spec. This ensures that the generic actuals
+ -- will not be evaluated prior to a potential ABE.
- Level := Find_Enclosing_Level (Call);
+ if Nkind (N) in N_Generic_Instantiation
+ and then Present (Instance_Spec (N))
+ then
+ return Instance_Spec (N);
- -- Library-level calls are always considered because they are part of
- -- the associated unit's elaboration actions.
+ -- Otherwise the proper insertion node is the scenario itself
- if Level in Library_Level then
- null;
+ else
+ return N;
+ end if;
+ end Insertion_Node;
- -- Calls at the library level of a generic package body must be checked
- -- because they would render an instantiation illegal if the template is
- -- marked as preelaborated. Note that this does not apply to calls at
- -- the library level of a generic package spec.
+ ---------------------------------
+ -- Insert_ABE_Check_Or_Failure --
+ ---------------------------------
- elsif Level = Generic_Package_Body then
- null;
+ procedure Insert_ABE_Check_Or_Failure (N : Node_Id; Check : Node_Id) is
+ Ins_Nod : constant Node_Id := Insertion_Node (N);
+ Scop_Id : constant Entity_Id := Find_Enclosing_Scope (Ins_Nod);
- -- Otherwise the call does not appear at the proper level and must not
- -- be considered for this check.
+ begin
+ -- Install the nearest enclosing scope of the scenario as there must
+ -- be something on the scope stack.
- else
- return;
- end if;
+ Push_Scope (Scop_Id);
- -- The call appears within a preelaborated unit. Emit a warning only for
- -- internal uses, otherwise this is an error.
+ Insert_Action (Ins_Nod, Check);
- if In_Preelaborated_Context (Call) then
- Error_Msg_Warn := GNAT_Mode;
- Error_Msg_N
- ("<<non-static call not allowed in preelaborated unit", Call);
- end if;
- end Check_Preelaborated_Call;
+ Pop_Scope;
+ end Insert_ABE_Check_Or_Failure;
- ------------------------------
- -- Check_SPARK_Derived_Type --
- ------------------------------
+ --------------------------------
+ -- Install_Dynamic_ABE_Checks --
+ --------------------------------
- procedure Check_SPARK_Derived_Type (Typ_Decl : Node_Id) is
- Typ : constant Entity_Id := Defining_Entity (Typ_Decl);
+ procedure Install_Dynamic_ABE_Checks is
+ Iter : NE_Set.Iterator;
+ N : Node_Id;
- -- NOTE: The routines within Check_SPARK_Derived_Type are intentionally
- -- unnested to avoid deep indentation of code.
+ begin
+ if not Check_Or_Failure_Generation_OK then
+ return;
- Stop_Check : exception;
- -- This exception is raised when the freeze node violates the placement
- -- rules.
+ -- Nothing to do if the dynamic model is not in effect
- procedure Check_Overriding_Primitive
- (Prim : Entity_Id;
- FNode : Node_Id);
- pragma Inline (Check_Overriding_Primitive);
- -- Verify that freeze node FNode is within the early call region of
- -- overriding primitive Prim's body.
+ elsif not Dynamic_Elaboration_Checks then
+ return;
+ end if;
- function Freeze_Node_Location (FNode : Node_Id) return Source_Ptr;
- pragma Inline (Freeze_Node_Location);
- -- Return a more accurate source location associated with freeze node
- -- FNode.
+ -- Install a conditional ABE check for each saved scenario
- function Precedes_Source_Construct (N : Node_Id) return Boolean;
- pragma Inline (Precedes_Source_Construct);
- -- Determine whether arbitrary node N appears prior to some source
- -- construct.
+ Iter := Iterate_Dynamic_ABE_Check_Scenarios;
+ while NE_Set.Has_Next (Iter) loop
+ NE_Set.Next (Iter, N);
- procedure Suggest_Elaborate_Body
- (N : Node_Id;
- Body_Decl : Node_Id;
- Error_Nod : Node_Id);
- pragma Inline (Suggest_Elaborate_Body);
- -- Suggest the use of pragma Elaborate_Body when the pragma will allow
- -- for node N to appear within the early call region of subprogram body
- -- Body_Decl. The suggestion is attached to Error_Nod as a continuation
- -- error.
+ Process_Conditional_ABE
+ (N => N,
+ In_State => Dynamic_Model_State);
+ end loop;
+ end Install_Dynamic_ABE_Checks;
--------------------------------
- -- Check_Overriding_Primitive --
+ -- Install_Scenario_ABE_Check --
--------------------------------
- procedure Check_Overriding_Primitive
- (Prim : Entity_Id;
- FNode : Node_Id)
+ procedure Install_Scenario_ABE_Check
+ (N : Node_Id;
+ Targ_Id : Entity_Id;
+ Targ_Rep : Target_Rep_Id;
+ Disable : Scenario_Rep_Id)
is
- Prim_Decl : constant Node_Id := Unit_Declaration_Node (Prim);
- Body_Decl : Node_Id;
- Body_Id : Entity_Id;
- Region : Node_Id;
-
begin
- -- Nothing to do for predefined primitives because they are artifacts
- -- of tagged type expansion and cannot override source primitives.
+ -- Nothing to do when the scenario does not need an ABE check
- if Is_Predefined_Dispatching_Operation (Prim) then
+ if not ABE_Check_Or_Failure_OK
+ (N => N,
+ Targ_Id => Targ_Id,
+ Unit_Id => Unit (Targ_Rep))
+ then
return;
end if;
- Body_Id := Corresponding_Body (Prim_Decl);
+ -- Prevent multiple attempts to install the same ABE check
- -- Nothing to do when the primitive does not have a corresponding
- -- body. This can happen when the unit with the bodies is not the
- -- main unit subjected to ABE checks.
+ Disable_Elaboration_Checks (Disable);
- if No (Body_Id) then
+ Install_Scenario_ABE_Check_Common
+ (N => N,
+ Targ_Id => Targ_Id,
+ Targ_Rep => Targ_Rep);
+ end Install_Scenario_ABE_Check;
+
+ --------------------------------
+ -- Install_Scenario_ABE_Check --
+ --------------------------------
+
+ procedure Install_Scenario_ABE_Check
+ (N : Node_Id;
+ Targ_Id : Entity_Id;
+ Targ_Rep : Target_Rep_Id;
+ Disable : Target_Rep_Id)
+ is
+ begin
+ -- Nothing to do when the scenario does not need an ABE check
+
+ if not ABE_Check_Or_Failure_OK
+ (N => N,
+ Targ_Id => Targ_Id,
+ Unit_Id => Unit (Targ_Rep))
+ then
return;
+ end if;
- -- The primitive overrides a parent or progenitor primitive
+ -- Prevent multiple attempts to install the same ABE check
- elsif Present (Overridden_Operation (Prim)) then
+ Disable_Elaboration_Checks (Disable);
- -- Nothing to do when overriding an interface primitive happens by
- -- inheriting a non-interface primitive as the check would be done
- -- on the parent primitive.
+ Install_Scenario_ABE_Check_Common
+ (N => N,
+ Targ_Id => Targ_Id,
+ Targ_Rep => Targ_Rep);
+ end Install_Scenario_ABE_Check;
- if Present (Alias (Prim)) then
+ ---------------------------------------
+ -- Install_Scenario_ABE_Check_Common --
+ ---------------------------------------
+
+ procedure Install_Scenario_ABE_Check_Common
+ (N : Node_Id;
+ Targ_Id : Entity_Id;
+ Targ_Rep : Target_Rep_Id)
+ is
+ Targ_Body : constant Node_Id := Body_Declaration (Targ_Rep);
+ Targ_Decl : constant Node_Id := Spec_Declaration (Targ_Rep);
+
+ pragma Assert (Present (Targ_Body));
+ pragma Assert (Present (Targ_Decl));
+
+ procedure Build_Elaboration_Entity;
+ pragma Inline (Build_Elaboration_Entity);
+ -- Create a new elaboration flag for Targ_Id, insert it prior to
+ -- Targ_Decl, and set it after Targ_Body.
+
+ ------------------------------
+ -- Build_Elaboration_Entity --
+ ------------------------------
+
+ procedure Build_Elaboration_Entity is
+ Loc : constant Source_Ptr := Sloc (Targ_Id);
+ Flag_Id : Entity_Id;
+
+ begin
+ -- Nothing to do if the target has an elaboration flag
+
+ if Present (Elaboration_Entity (Targ_Id)) then
return;
end if;
- -- Nothing to do when the primitive is not overriding. The body of
- -- such a primitive cannot be targeted by a dispatching call which
- -- is executable during elaboration, and cannot cause an ABE.
+ -- Create the declaration of the elaboration flag. The name
+ -- carries a unique counter in case the name is overloaded.
- else
- return;
- end if;
+ Flag_Id :=
+ Make_Defining_Identifier (Loc,
+ Chars => New_External_Name (Chars (Targ_Id), 'E', -1));
- Body_Decl := Unit_Declaration_Node (Body_Id);
- Region := Find_Early_Call_Region (Body_Decl);
+ Set_Elaboration_Entity (Targ_Id, Flag_Id);
+ Set_Elaboration_Entity_Required (Targ_Id);
- -- The freeze node appears prior to the early call region of the
- -- primitive body.
+ Push_Scope (Scope (Targ_Id));
- -- IMPORTANT: This check must always be performed even when -gnatd.v
- -- (enforce SPARK elaboration rules in SPARK code) is not specified
- -- because the static model cannot guarantee the absence of ABEs in
- -- in the presence of dispatching calls.
+ -- Generate:
+ -- Enn : Short_Integer := 0;
- if Earlier_In_Extended_Unit (FNode, Region) then
- Error_Msg_Node_2 := Prim;
- Error_Msg_NE
- ("first freezing point of type & must appear within early call "
- & "region of primitive body & (SPARK RM 7.7(8))",
- Typ_Decl, Typ);
+ Insert_Action (Targ_Decl,
+ Make_Object_Declaration (Loc,
+ Defining_Identifier => Flag_Id,
+ Object_Definition =>
+ New_Occurrence_Of (Standard_Short_Integer, Loc),
+ Expression => Make_Integer_Literal (Loc, Uint_0)));
- Error_Msg_Sloc := Sloc (Region);
- Error_Msg_N ("\region starts #", Typ_Decl);
+ -- Generate:
+ -- Enn := 1;
- Error_Msg_Sloc := Sloc (Body_Decl);
- Error_Msg_N ("\region ends #", Typ_Decl);
+ Set_Elaboration_Flag (Targ_Body, Targ_Id);
+
+ Pop_Scope;
+ end Build_Elaboration_Entity;
- Error_Msg_Sloc := Freeze_Node_Location (FNode);
- Error_Msg_N ("\first freezing point #", Typ_Decl);
+ -- Local variables
- -- If applicable, suggest the use of pragma Elaborate_Body in the
- -- associated package spec.
+ Loc : constant Source_Ptr := Sloc (N);
- Suggest_Elaborate_Body
- (N => FNode,
- Body_Decl => Body_Decl,
- Error_Nod => Typ_Decl);
+ -- Start for processing for Install_Scenario_ABE_Check_Common
- raise Stop_Check;
- end if;
- end Check_Overriding_Primitive;
+ begin
+ -- Create an elaboration flag for the target when it does not have
+ -- one.
- --------------------------
- -- Freeze_Node_Location --
- --------------------------
+ Build_Elaboration_Entity;
- function Freeze_Node_Location (FNode : Node_Id) return Source_Ptr is
- Context : constant Node_Id := Parent (FNode);
- Loc : constant Source_Ptr := Sloc (FNode);
+ -- Generate:
+ -- if not Targ_Id'Elaborated then
+ -- raise Program_Error with "access before elaboration";
+ -- end if;
+
+ Insert_ABE_Check_Or_Failure
+ (N => N,
+ Check =>
+ Make_Raise_Program_Error (Loc,
+ Condition =>
+ Make_Op_Not (Loc,
+ Right_Opnd =>
+ Make_Attribute_Reference (Loc,
+ Prefix => New_Occurrence_Of (Targ_Id, Loc),
+ Attribute_Name => Name_Elaborated)),
+ Reason => PE_Access_Before_Elaboration));
+ end Install_Scenario_ABE_Check_Common;
- Prv_Decls : List_Id;
- Vis_Decls : List_Id;
+ ----------------------------------
+ -- Install_Scenario_ABE_Failure --
+ ----------------------------------
+ procedure Install_Scenario_ABE_Failure
+ (N : Node_Id;
+ Targ_Id : Entity_Id;
+ Targ_Rep : Target_Rep_Id;
+ Disable : Scenario_Rep_Id)
+ is
begin
- -- In general, the source location of the freeze node is as close as
- -- possible to the real freeze point, except when the freeze node is
- -- at the "bottom" of a package spec.
+ -- Nothing to do when the scenario does not require an ABE failure
- if Nkind (Context) = N_Package_Specification then
- Prv_Decls := Private_Declarations (Context);
- Vis_Decls := Visible_Declarations (Context);
+ if not ABE_Check_Or_Failure_OK
+ (N => N,
+ Targ_Id => Targ_Id,
+ Unit_Id => Unit (Targ_Rep))
+ then
+ return;
+ end if;
- -- The freeze node appears in the private declarations of the
- -- package.
+ -- Prevent multiple attempts to install the same ABE check
- if Present (Prv_Decls)
- and then List_Containing (FNode) = Prv_Decls
- then
- null;
+ Disable_Elaboration_Checks (Disable);
- -- The freeze node appears in the visible declarations of the
- -- package and there are no private declarations.
+ Install_Scenario_ABE_Failure_Common (N);
+ end Install_Scenario_ABE_Failure;
- elsif Present (Vis_Decls)
- and then List_Containing (FNode) = Vis_Decls
- and then (No (Prv_Decls) or else Is_Empty_List (Prv_Decls))
- then
- null;
+ ----------------------------------
+ -- Install_Scenario_ABE_Failure --
+ ----------------------------------
- -- Otherwise the freeze node is not in the "last" declarative list
- -- of the package. Use the existing source location of the freeze
- -- node.
+ procedure Install_Scenario_ABE_Failure
+ (N : Node_Id;
+ Targ_Id : Entity_Id;
+ Targ_Rep : Target_Rep_Id;
+ Disable : Target_Rep_Id)
+ is
+ begin
+ -- Nothing to do when the scenario does not require an ABE failure
- else
- return Loc;
- end if;
+ if not ABE_Check_Or_Failure_OK
+ (N => N,
+ Targ_Id => Targ_Id,
+ Unit_Id => Unit (Targ_Rep))
+ then
+ return;
+ end if;
- -- The freeze node appears at the "bottom" of the package when it
- -- is in the "last" declarative list and is either the last in the
- -- list or is followed by internal constructs only. In that case
- -- the more appropriate source location is that of the package end
- -- label.
+ -- Prevent multiple attempts to install the same ABE check
- if not Precedes_Source_Construct (FNode) then
- return Sloc (End_Label (Context));
- end if;
- end if;
+ Disable_Elaboration_Checks (Disable);
- return Loc;
- end Freeze_Node_Location;
+ Install_Scenario_ABE_Failure_Common (N);
+ end Install_Scenario_ABE_Failure;
- -------------------------------
- -- Precedes_Source_Construct --
- -------------------------------
+ -----------------------------------------
+ -- Install_Scenario_ABE_Failure_Common --
+ -----------------------------------------
- function Precedes_Source_Construct (N : Node_Id) return Boolean is
- Decl : Node_Id;
+ procedure Install_Scenario_ABE_Failure_Common (N : Node_Id) is
+ Loc : constant Source_Ptr := Sloc (N);
begin
- Decl := Next (N);
- while Present (Decl) loop
- if Comes_From_Source (Decl) then
- return True;
+ -- Generate:
+ -- raise Program_Error with "access before elaboration";
- -- A generated body for a source expression function is treated as
- -- a source construct.
+ Insert_ABE_Check_Or_Failure
+ (N => N,
+ Check =>
+ Make_Raise_Program_Error (Loc,
+ Reason => PE_Access_Before_Elaboration));
+ end Install_Scenario_ABE_Failure_Common;
- elsif Nkind (Decl) = N_Subprogram_Body
- and then Was_Expression_Function (Decl)
- and then Comes_From_Source (Original_Node (Decl))
- then
- return True;
- end if;
+ ----------------------------
+ -- Install_Unit_ABE_Check --
+ ----------------------------
- Next (Decl);
- end loop;
+ procedure Install_Unit_ABE_Check
+ (N : Node_Id;
+ Unit_Id : Entity_Id;
+ Disable : Scenario_Rep_Id)
+ is
+ Spec_Id : constant Entity_Id := Unique_Entity (Unit_Id);
- return False;
- end Precedes_Source_Construct;
+ begin
+ -- Nothing to do when the scenario does not require an ABE check
+
+ if not ABE_Check_Or_Failure_OK
+ (N => N,
+ Targ_Id => Empty,
+ Unit_Id => Spec_Id)
+ then
+ return;
+ end if;
+
+ -- Prevent multiple attempts to install the same ABE check
+
+ Disable_Elaboration_Checks (Disable);
+
+ Install_Unit_ABE_Check_Common
+ (N => N,
+ Unit_Id => Unit_Id);
+ end Install_Unit_ABE_Check;
----------------------------
- -- Suggest_Elaborate_Body --
+ -- Install_Unit_ABE_Check --
----------------------------
- procedure Suggest_Elaborate_Body
- (N : Node_Id;
- Body_Decl : Node_Id;
- Error_Nod : Node_Id)
+ procedure Install_Unit_ABE_Check
+ (N : Node_Id;
+ Unit_Id : Entity_Id;
+ Disable : Target_Rep_Id)
is
- Unt : constant Node_Id := Unit (Cunit (Main_Unit));
- Region : Node_Id;
+ Spec_Id : constant Entity_Id := Unique_Entity (Unit_Id);
begin
- -- The suggestion applies only when the subprogram body resides in a
- -- compilation package body, and a pragma Elaborate_Body would allow
- -- for the node to appear in the early call region of the subprogram
- -- body. This implies that all code from the subprogram body up to
- -- the node is preelaborable.
+ -- Nothing to do when the scenario does not require an ABE check
- if Nkind (Unt) = N_Package_Body then
+ if not ABE_Check_Or_Failure_OK
+ (N => N,
+ Targ_Id => Empty,
+ Unit_Id => Spec_Id)
+ then
+ return;
+ end if;
- -- Find the start of the early call region again assuming that the
- -- package spec has pragma Elaborate_Body. Note that the internal
- -- data structures are intentionally not updated because this is a
- -- speculative search.
+ -- Prevent multiple attempts to install the same ABE check
- Region :=
- Find_Early_Call_Region
- (Body_Decl => Body_Decl,
- Assume_Elab_Body => True,
- Skip_Memoization => True);
+ Disable_Elaboration_Checks (Disable);
- -- If the node appears within the early call region, assuming that
- -- the package spec carries pragma Elaborate_Body, then it is safe
- -- to suggest the pragma.
+ Install_Unit_ABE_Check_Common
+ (N => N,
+ Unit_Id => Unit_Id);
+ end Install_Unit_ABE_Check;
- if Earlier_In_Extended_Unit (Region, N) then
- Error_Msg_Name_1 := Name_Elaborate_Body;
- Error_Msg_NE
- ("\consider adding pragma % in spec of unit &",
- Error_Nod, Defining_Entity (Unt));
- end if;
- end if;
- end Suggest_Elaborate_Body;
+ -----------------------------------
+ -- Install_Unit_ABE_Check_Common --
+ -----------------------------------
- -- Local variables
+ procedure Install_Unit_ABE_Check_Common
+ (N : Node_Id;
+ Unit_Id : Entity_Id)
+ is
+ Loc : constant Source_Ptr := Sloc (N);
+ Spec_Id : constant Entity_Id := Unique_Entity (Unit_Id);
- FNode : constant Node_Id := Freeze_Node (Typ);
- Prims : constant Elist_Id := Direct_Primitive_Operations (Typ);
+ begin
+ -- Generate:
+ -- if not Spec_Id'Elaborated then
+ -- raise Program_Error with "access before elaboration";
+ -- end if;
+
+ Insert_ABE_Check_Or_Failure
+ (N => N,
+ Check =>
+ Make_Raise_Program_Error (Loc,
+ Condition =>
+ Make_Op_Not (Loc,
+ Right_Opnd =>
+ Make_Attribute_Reference (Loc,
+ Prefix => New_Occurrence_Of (Spec_Id, Loc),
+ Attribute_Name => Name_Elaborated)),
+ Reason => PE_Access_Before_Elaboration));
+ end Install_Unit_ABE_Check_Common;
+ end Check_Installer;
- Prim_Elmt : Elmt_Id;
+ ----------------------
+ -- Compilation_Unit --
+ ----------------------
- -- Start of processing for Check_SPARK_Derived_Type
+ function Compilation_Unit (Unit_Id : Entity_Id) return Node_Id is
+ Comp_Unit : Node_Id;
begin
- -- A type should have its freeze node set by the time SPARK scenarios
- -- are being verified.
+ Comp_Unit := Parent (Unit_Id);
- pragma Assert (Present (FNode));
+ -- Handle the case where a concurrent subunit is rewritten as a null
+ -- statement due to expansion activities.
- -- Verify that the freeze node of the derived type is within the early
- -- call region of each overriding primitive body (SPARK RM 7.7(8)).
+ if Nkind (Comp_Unit) = N_Null_Statement
+ and then Nkind_In (Original_Node (Comp_Unit), N_Protected_Body,
+ N_Task_Body)
+ then
+ Comp_Unit := Parent (Comp_Unit);
+ pragma Assert (Nkind (Comp_Unit) = N_Subunit);
- if Present (Prims) then
- Prim_Elmt := First_Elmt (Prims);
- while Present (Prim_Elmt) loop
- Check_Overriding_Primitive
- (Prim => Node (Prim_Elmt),
- FNode => FNode);
+ -- Otherwise use the declaration node of the unit
- Next_Elmt (Prim_Elmt);
- end loop;
+ else
+ Comp_Unit := Parent (Unit_Declaration_Node (Unit_Id));
end if;
- exception
- when Stop_Check =>
- null;
- end Check_SPARK_Derived_Type;
+ -- Handle the case where a subprogram instantiation which acts as a
+ -- compilation unit is expanded into an anonymous package that wraps
+ -- the instantiated subprogram.
+
+ if Nkind (Comp_Unit) = N_Package_Specification
+ and then Nkind_In (Original_Node (Parent (Comp_Unit)),
+ N_Function_Instantiation,
+ N_Procedure_Instantiation)
+ then
+ Comp_Unit := Parent (Parent (Comp_Unit));
+
+ -- Handle the case where the compilation unit is a subunit
+
+ elsif Nkind (Comp_Unit) = N_Subunit then
+ Comp_Unit := Parent (Comp_Unit);
+ end if;
+
+ pragma Assert (Nkind (Comp_Unit) = N_Compilation_Unit);
+
+ return Comp_Unit;
+ end Compilation_Unit;
-------------------------------
- -- Check_SPARK_Instantiation --
+ -- Conditional_ABE_Processor --
-------------------------------
- procedure Check_SPARK_Instantiation (Exp_Inst : Node_Id) is
- Gen_Attrs : Target_Attributes;
- Gen_Id : Entity_Id;
- Inst : Node_Id;
- Inst_Attrs : Instantiation_Attributes;
- Inst_Id : Entity_Id;
+ package body Conditional_ABE_Processor is
- begin
- Extract_Instantiation_Attributes
- (Exp_Inst => Exp_Inst,
- Inst => Inst,
- Inst_Id => Inst_Id,
- Gen_Id => Gen_Id,
- Attrs => Inst_Attrs);
+ -----------------------
+ -- Local subprograms --
+ -----------------------
- Extract_Target_Attributes (Gen_Id, Gen_Attrs);
+ function Is_Conditional_ABE_Scenario (N : Node_Id) return Boolean;
+ pragma Inline (Is_Conditional_ABE_Scenario);
+ -- Determine whether node N is a suitable scenario for conditional ABE
+ -- checks and diagnostics.
+
+ procedure Process_Conditional_ABE_Access_Taken
+ (Attr : Node_Id;
+ Attr_Rep : Scenario_Rep_Id;
+ In_State : Processing_In_State);
+ pragma Inline (Process_Conditional_ABE_Access_Taken);
+ -- Perform ABE checks and diagnostics for attribute reference Attr with
+ -- representation Attr_Rep which takes 'Access of an entry, operator, or
+ -- subprogram. In_State is the current state of the Processing phase.
+
+ procedure Process_Conditional_ABE_Activation
+ (Call : Node_Id;
+ Call_Rep : Scenario_Rep_Id;
+ Obj_Id : Entity_Id;
+ Obj_Rep : Target_Rep_Id;
+ Task_Typ : Entity_Id;
+ Task_Rep : Target_Rep_Id;
+ In_State : Processing_In_State);
+ pragma Inline (Process_Conditional_ABE_Activation);
+ -- Perform common conditional ABE checks and diagnostics for activation
+ -- call Call which activates object Obj_Id of task type Task_Typ. Formal
+ -- Call_Rep denotes the representation of the call. Obj_Rep denotes the
+ -- representation of the object. Task_Rep denotes the representation of
+ -- the task type. In_State is the current state of the Processing phase.
+
+ procedure Process_Conditional_ABE_Call
+ (Call : Node_Id;
+ Call_Rep : Scenario_Rep_Id;
+ In_State : Processing_In_State);
+ pragma Inline (Process_Conditional_ABE_Call);
+ -- Top-level dispatcher for processing of calls. Perform ABE checks and
+ -- diagnostics for call Call with representation Call_Rep. In_State is
+ -- the current state of the Processing phase.
+
+ procedure Process_Conditional_ABE_Call_Ada
+ (Call : Node_Id;
+ Call_Rep : Scenario_Rep_Id;
+ Subp_Id : Entity_Id;
+ Subp_Rep : Target_Rep_Id;
+ In_State : Processing_In_State);
+ pragma Inline (Process_Conditional_ABE_Call_Ada);
+ -- Perform ABE checks and diagnostics for call Call which invokes entry,
+ -- operator, or subprogram Subp_Id using the Ada rules. Call_Rep denotes
+ -- the representation of the call. Subp_Rep denotes the representation
+ -- of the subprogram. In_State is the current state of the Processing
+ -- phase.
+
+ procedure Process_Conditional_ABE_Call_SPARK
+ (Call : Node_Id;
+ Call_Rep : Scenario_Rep_Id;
+ Subp_Id : Entity_Id;
+ Subp_Rep : Target_Rep_Id;
+ In_State : Processing_In_State);
+ pragma Inline (Process_Conditional_ABE_Call_SPARK);
+ -- Perform ABE checks and diagnostics for call Call which invokes entry,
+ -- operator, or subprogram Subp_Id using the SPARK rules. Call_Rep is
+ -- the representation of the call. Subp_Rep denotes the representation
+ -- of the subprogram. In_State is the current state of the Processing
+ -- phase.
+
+ procedure Process_Conditional_ABE_Instantiation
+ (Inst : Node_Id;
+ Inst_Rep : Scenario_Rep_Id;
+ In_State : Processing_In_State);
+ pragma Inline (Process_Conditional_ABE_Instantiation);
+ -- Top-level dispatcher for processing of instantiations. Perform ABE
+ -- checks and diagnostics for instantiation Inst with representation
+ -- Inst_Rep. In_State is the current state of the Processing phase.
+
+ procedure Process_Conditional_ABE_Instantiation_Ada
+ (Inst : Node_Id;
+ Inst_Rep : Scenario_Rep_Id;
+ Gen_Id : Entity_Id;
+ Gen_Rep : Target_Rep_Id;
+ In_State : Processing_In_State);
+ pragma Inline (Process_Conditional_ABE_Instantiation_Ada);
+ -- Perform ABE checks and diagnostics for instantiation Inst of generic
+ -- Gen_Id using the Ada rules. Inst_Rep denotes the representation of
+ -- the instnace. Gen_Rep is the representation of the generic. In_State
+ -- is the current state of the Processing phase.
+
+ procedure Process_Conditional_ABE_Instantiation_SPARK
+ (Inst : Node_Id;
+ Inst_Rep : Scenario_Rep_Id;
+ Gen_Id : Entity_Id;
+ Gen_Rep : Target_Rep_Id;
+ In_State : Processing_In_State);
+ pragma Inline (Process_Conditional_ABE_Instantiation_SPARK);
+ -- Perform ABE checks and diagnostics for instantiation Inst of generic
+ -- Gen_Id using the SPARK rules. Inst_Rep denotes the representation of
+ -- the instnace. Gen_Rep is the representation of the generic. In_State
+ -- is the current state of the Processing phase.
+
+ procedure Process_Conditional_ABE_Variable_Assignment
+ (Asmt : Node_Id;
+ Asmt_Rep : Scenario_Rep_Id;
+ In_State : Processing_In_State);
+ pragma Inline (Process_Conditional_ABE_Variable_Assignment);
+ -- Top-level dispatcher for processing of variable assignments. Perform
+ -- ABE checks and diagnostics for assignment Asmt with representation
+ -- Asmt_Rep. In_State denotes the current state of the Processing phase.
+
+ procedure Process_Conditional_ABE_Variable_Assignment_Ada
+ (Asmt : Node_Id;
+ Asmt_Rep : Scenario_Rep_Id;
+ Var_Id : Entity_Id;
+ Var_Rep : Target_Rep_Id;
+ In_State : Processing_In_State);
+ pragma Inline (Process_Conditional_ABE_Variable_Assignment_Ada);
+ -- Perform ABE checks and diagnostics for assignment statement Asmt that
+ -- modifies the value of variable Var_Id using the Ada rules. Asmt_Rep
+ -- denotes the representation of the assignment. Var_Rep denotes the
+ -- representation of the variable. In_State is the current state of the
+ -- Processing phase.
+
+ procedure Process_Conditional_ABE_Variable_Assignment_SPARK
+ (Asmt : Node_Id;
+ Asmt_Rep : Scenario_Rep_Id;
+ Var_Id : Entity_Id;
+ Var_Rep : Target_Rep_Id;
+ In_State : Processing_In_State);
+ pragma Inline (Process_Conditional_ABE_Variable_Assignment_SPARK);
+ -- Perform ABE checks and diagnostics for assignment statement Asmt that
+ -- modifies the value of variable Var_Id using the SPARK rules. Asmt_Rep
+ -- denotes the representation of the assignment. Var_Rep denotes the
+ -- representation of the variable. In_State is the current state of the
+ -- Processing phase.
+
+ procedure Process_Conditional_ABE_Variable_Reference
+ (Ref : Node_Id;
+ Ref_Rep : Scenario_Rep_Id;
+ In_State : Processing_In_State);
+ pragma Inline (Process_Conditional_ABE_Variable_Reference);
+ -- Perform ABE checks and diagnostics for variable reference Ref with
+ -- representation Ref_Rep. In_State denotes the current state of the
+ -- Processing phase.
+
+ procedure Traverse_Conditional_ABE_Body
+ (N : Node_Id;
+ In_State : Processing_In_State);
+ pragma Inline (Traverse_Conditional_ABE_Body);
+ -- Traverse subprogram body N looking for suitable scenarios that need
+ -- to be processed for conditional ABE checks and diagnostics. In_State
+ -- is the current state of the Processing phase.
+
+ -------------------------------------
+ -- Check_Conditional_ABE_Scenarios --
+ -------------------------------------
+
+ procedure Check_Conditional_ABE_Scenarios
+ (Iter : in out NE_Set.Iterator)
+ is
+ N : Node_Id;
- -- The instantiation and the generic body are both in the main unit
+ begin
+ while NE_Set.Has_Next (Iter) loop
+ NE_Set.Next (Iter, N);
- if Present (Gen_Attrs.Body_Decl)
- and then In_Extended_Main_Code_Unit (Gen_Attrs.Body_Decl)
+ -- Reset the traversed status of all subprogram bodies because the
+ -- current conditional scenario acts as a new DFS traversal root.
- -- If the instantiation appears prior to the generic body, then the
- -- instantiation is illegal (SPARK RM 7.7(6)).
+ Reset_Traversed_Bodies;
- -- IMPORTANT: This check must always be performed even when -gnatd.v
- -- (enforce SPARK elaboration rules in SPARK code) is not specified
- -- because the rule prevents use-before-declaration of objects that
- -- may precede the generic body.
+ Process_Conditional_ABE
+ (N => N,
+ In_State => Conditional_ABE_State);
+ end loop;
+ end Check_Conditional_ABE_Scenarios;
- and then Earlier_In_Extended_Unit (Inst, Gen_Attrs.Body_Decl)
- then
- Error_Msg_NE ("cannot instantiate & before body seen", Inst, Gen_Id);
- end if;
- end Check_SPARK_Instantiation;
+ ---------------------------------
+ -- Is_Conditional_ABE_Scenario --
+ ---------------------------------
- ---------------------------------
- -- Check_SPARK_Model_In_Effect --
- ---------------------------------
+ function Is_Conditional_ABE_Scenario (N : Node_Id) return Boolean is
+ begin
+ return
+ Is_Suitable_Access_Taken (N)
+ or else Is_Suitable_Call (N)
+ or else Is_Suitable_Instantiation (N)
+ or else Is_Suitable_Variable_Assignment (N)
+ or else Is_Suitable_Variable_Reference (N);
+ end Is_Conditional_ABE_Scenario;
- SPARK_Model_Warning_Posted : Boolean := False;
- -- This flag prevents the same SPARK model-related warning from being
- -- emitted multiple times.
+ -----------------------------
+ -- Process_Conditional_ABE --
+ -----------------------------
- procedure Check_SPARK_Model_In_Effect (N : Node_Id) is
- begin
- -- Do not emit the warning multiple times as this creates useless noise
+ procedure Process_Conditional_ABE
+ (N : Node_Id;
+ In_State : Processing_In_State)
+ is
+ Scen : constant Node_Id := Scenario (N);
+ Scen_Rep : Scenario_Rep_Id;
- if SPARK_Model_Warning_Posted then
- null;
+ begin
+ -- Add the current scenario to the stack of active scenarios
- -- SPARK rule verification requires the "strict" static model
+ Push_Active_Scenario (Scen);
- elsif Static_Elaboration_Checks and not Relaxed_Elaboration_Checks then
- null;
+ -- 'Access
- -- Any other combination of models does not guarantee the absence of ABE
- -- problems for SPARK rule verification purposes. Note that there is no
- -- need to check for the legacy ABE mechanism because the legacy code
- -- has its own orthogonal processing for SPARK rules.
+ if Is_Suitable_Access_Taken (Scen) then
+ Process_Conditional_ABE_Access_Taken
+ (Attr => Scen,
+ Attr_Rep => Scenario_Representation_Of (Scen, In_State),
+ In_State => In_State);
- else
- SPARK_Model_Warning_Posted := True;
+ -- Call or task activation
- Error_Msg_N
- ("??SPARK elaboration checks require static elaboration model", N);
+ elsif Is_Suitable_Call (Scen) then
+ Scen_Rep := Scenario_Representation_Of (Scen, In_State);
- if Dynamic_Elaboration_Checks then
- Error_Msg_N ("\dynamic elaboration model is in effect", N);
- else
- pragma Assert (Relaxed_Elaboration_Checks);
- Error_Msg_N ("\relaxed elaboration model is in effect", N);
- end if;
- end if;
- end Check_SPARK_Model_In_Effect;
+ -- Routine Build_Call_Marker creates call markers regardless of
+ -- whether the call occurs within the main unit or not. This way
+ -- the serialization of internal names is kept consistent. Only
+ -- call markers found within the main unit must be processed.
- --------------------------
- -- Check_SPARK_Scenario --
- --------------------------
+ if In_Main_Context (Scen) then
+ Scen_Rep := Scenario_Representation_Of (Scen, In_State);
- procedure Check_SPARK_Scenario (N : Node_Id) is
- begin
- -- Ensure that a suitable elaboration model is in effect for SPARK rule
- -- verification.
+ if Kind (Scen_Rep) = Call_Scenario then
+ Process_Conditional_ABE_Call
+ (Call => Scen,
+ Call_Rep => Scen_Rep,
+ In_State => In_State);
- Check_SPARK_Model_In_Effect (N);
+ else
+ pragma Assert (Kind (Scen_Rep) = Task_Activation_Scenario);
- -- Add the current scenario to the stack of active scenarios
+ Process_Activation
+ (Call => Scen,
+ Call_Rep => Scen_Rep,
+ Processor => Process_Conditional_ABE_Activation'Access,
+ In_State => In_State);
+ end if;
+ end if;
- Push_Active_Scenario (N);
+ -- Instantiation
- if Is_Suitable_SPARK_Derived_Type (N) then
- Check_SPARK_Derived_Type (N);
+ elsif Is_Suitable_Instantiation (Scen) then
+ Process_Conditional_ABE_Instantiation
+ (Inst => Scen,
+ Inst_Rep => Scenario_Representation_Of (Scen, In_State),
+ In_State => In_State);
- elsif Is_Suitable_SPARK_Instantiation (N) then
- Check_SPARK_Instantiation (N);
+ -- Variable assignments
- elsif Is_Suitable_SPARK_Refined_State_Pragma (N) then
- Check_SPARK_Refined_State_Pragma (N);
- end if;
+ elsif Is_Suitable_Variable_Assignment (Scen) then
+ Process_Conditional_ABE_Variable_Assignment
+ (Asmt => Scen,
+ Asmt_Rep => Scenario_Representation_Of (Scen, In_State),
+ In_State => In_State);
- -- Remove the current scenario from the stack of active scenarios once
- -- all ABE diagnostics and checks have been performed.
+ -- Variable references
- Pop_Active_Scenario (N);
- end Check_SPARK_Scenario;
+ elsif Is_Suitable_Variable_Reference (Scen) then
- --------------------------------------
- -- Check_SPARK_Refined_State_Pragma --
- --------------------------------------
+ -- Routine Build_Variable_Reference_Marker makes variable markers
+ -- regardless of whether the reference occurs within the main unit
+ -- or not. This way the serialization of internal names is kept
+ -- consistent. Only variable markers within the main unit must be
+ -- processed.
- procedure Check_SPARK_Refined_State_Pragma (N : Node_Id) is
+ if In_Main_Context (Scen) then
+ Process_Conditional_ABE_Variable_Reference
+ (Ref => Scen,
+ Ref_Rep => Scenario_Representation_Of (Scen, In_State),
+ In_State => In_State);
+ end if;
+ end if;
- -- NOTE: The routines within Check_SPARK_Refined_State_Pragma are
- -- intentionally unnested to avoid deep indentation of code.
+ -- Remove the current scenario from the stack of active scenarios
+ -- once all ABE diagnostics and checks have been performed.
- procedure Check_SPARK_Constituent (Constit_Id : Entity_Id);
- pragma Inline (Check_SPARK_Constituent);
- -- Ensure that a single constituent Constit_Id is elaborated prior to
- -- the main unit.
+ Pop_Active_Scenario (Scen);
+ end Process_Conditional_ABE;
- procedure Check_SPARK_Constituents (Constits : Elist_Id);
- pragma Inline (Check_SPARK_Constituents);
- -- Ensure that all constituents found in list Constits are elaborated
- -- prior to the main unit.
+ ------------------------------------------
+ -- Process_Conditional_ABE_Access_Taken --
+ ------------------------------------------
- procedure Check_SPARK_Initialized_State (State : Node_Id);
- pragma Inline (Check_SPARK_Initialized_State);
- -- Ensure that the constituents of single abstract state State are
- -- elaborated prior to the main unit.
+ procedure Process_Conditional_ABE_Access_Taken
+ (Attr : Node_Id;
+ Attr_Rep : Scenario_Rep_Id;
+ In_State : Processing_In_State)
+ is
+ function Build_Access_Marker (Subp_Id : Entity_Id) return Node_Id;
+ pragma Inline (Build_Access_Marker);
+ -- Create a suitable call marker which invokes subprogram Subp_Id
- procedure Check_SPARK_Initialized_States (Pack_Id : Entity_Id);
- pragma Inline (Check_SPARK_Initialized_States);
- -- Ensure that the constituents of all abstract states which appear in
- -- the Initializes pragma of package Pack_Id are elaborated prior to the
- -- main unit.
+ -------------------------
+ -- Build_Access_Marker --
+ -------------------------
- -----------------------------
- -- Check_SPARK_Constituent --
- -----------------------------
+ function Build_Access_Marker (Subp_Id : Entity_Id) return Node_Id is
+ Marker : Node_Id;
- procedure Check_SPARK_Constituent (Constit_Id : Entity_Id) is
- Prag : Node_Id;
+ begin
+ Marker := Make_Call_Marker (Sloc (Attr));
- begin
- -- Nothing to do for "null" constituents
+ -- Inherit relevant attributes from the attribute
- if Nkind (Constit_Id) = N_Null then
- return;
+ Set_Target (Marker, Subp_Id);
+ Set_Is_Declaration_Level_Node
+ (Marker, Level (Attr_Rep) = Declaration_Level);
+ Set_Is_Dispatching_Call
+ (Marker, False);
+ Set_Is_Elaboration_Checks_OK_Node
+ (Marker, Elaboration_Checks_OK (Attr_Rep));
+ Set_Is_Elaboration_Warnings_OK_Node
+ (Marker, Elaboration_Warnings_OK (Attr_Rep));
+ Set_Is_Source_Call
+ (Marker, Comes_From_Source (Attr));
+ Set_Is_SPARK_Mode_On_Node
+ (Marker, SPARK_Mode_Of (Attr_Rep) = Is_On);
- -- Nothing to do for illegal constituents
+ -- Partially insert the call marker into the tree by setting its
+ -- parent pointer.
- elsif Error_Posted (Constit_Id) then
- return;
- end if;
+ Set_Parent (Marker, Attr);
+
+ return Marker;
+ end Build_Access_Marker;
+
+ -- Local variables
+
+ Root : constant Node_Id := Root_Scenario;
+ Subp_Id : constant Entity_Id := Target (Attr_Rep);
+ Subp_Rep : constant Target_Rep_Id :=
+ Target_Representation_Of (Subp_Id, In_State);
+ Body_Decl : constant Node_Id := Body_Declaration (Subp_Rep);
+
+ New_In_State : Processing_In_State := In_State;
+ -- Each step of the Processing phase constitutes a new state
- Prag := SPARK_Pragma (Constit_Id);
+ -- Start of processing for Process_Conditional_ABE_Access
- -- The check applies only when the constituent is subject to pragma
- -- SPARK_Mode On.
+ begin
+ -- Output relevant information when switch -gnatel (info messages on
+ -- implicit Elaborate[_All] pragmas) is in effect.
- if Present (Prag)
- and then Get_SPARK_Mode_From_Annotation (Prag) = On
+ if Elab_Info_Messages
+ and then not New_In_State.Suppress_Info_Messages
then
- -- An external constituent of an abstract state which appears in
- -- the Initializes pragma of a package spec imposes an Elaborate
- -- requirement on the context of the main unit. Determine whether
- -- the context has a pragma strong enough to meet the requirement.
+ Error_Msg_NE
+ ("info: access to & during elaboration", Attr, Subp_Id);
+ end if;
- -- IMPORTANT: This check is performed only when -gnatd.v (enforce
- -- SPARK elaboration rules in SPARK code) is in effect because the
- -- static model can ensure the prior elaboration of the unit which
- -- contains a constituent by installing implicit Elaborate pragma.
+ -- Warnings are suppressed when a prior scenario is already in that
+ -- mode or when the attribute or the target have warnings suppressed.
+ -- Update the state of the Processing phase to reflect this.
- if Debug_Flag_Dot_V then
- Meet_Elaboration_Requirement
- (N => N,
- Target_Id => Constit_Id,
- Req_Nam => Name_Elaborate);
+ New_In_State.Suppress_Warnings :=
+ New_In_State.Suppress_Warnings
+ or else not Elaboration_Warnings_OK (Attr_Rep)
+ or else not Elaboration_Warnings_OK (Subp_Rep);
- -- Otherwise ensure that the unit with the external constituent is
- -- elaborated prior to the main unit.
+ -- Do not emit any ABE diagnostics when the current or previous
+ -- scenario in this traversal has suppressed elaboration warnings.
- else
- Ensure_Prior_Elaboration
- (N => N,
- Unit_Id => Find_Top_Unit (Constit_Id),
- Prag_Nam => Name_Elaborate,
- State => Initial_State);
- end if;
+ if New_In_State.Suppress_Warnings then
+ null;
+
+ -- Both the attribute and the corresponding subprogram body are in
+ -- the same unit. The body must appear prior to the root scenario
+ -- which started the recursive search. If this is not the case, then
+ -- there is a potential ABE if the access value is used to call the
+ -- subprogram. Emit a warning only when switch -gnatw.f (warnings on
+ -- suspucious 'Access) is in effect.
+
+ elsif Warn_On_Elab_Access
+ and then Present (Body_Decl)
+ and then In_Extended_Main_Code_Unit (Body_Decl)
+ and then Earlier_In_Extended_Unit (Root, Body_Decl)
+ then
+ Error_Msg_Name_1 := Attribute_Name (Attr);
+ Error_Msg_NE
+ ("??% attribute of & before body seen", Attr, Subp_Id);
+ Error_Msg_N ("\possible Program_Error on later references", Attr);
+
+ Output_Active_Scenarios (Attr, New_In_State);
end if;
- end Check_SPARK_Constituent;
- ------------------------------
- -- Check_SPARK_Constituents --
- ------------------------------
+ -- Treat the attribute an an immediate invocation of the target when
+ -- switch -gnatd.o (conservative elaboration order for indirect
+ -- calls) is in effect. This has the following desirable effects:
+ --
+ -- * Ensure that the unit with the corresponding body is elaborated
+ -- prior to the main unit.
+ --
+ -- * Perform conditional ABE checks and diagnostics
+ --
+ -- * Traverse the body of the target (if available)
- procedure Check_SPARK_Constituents (Constits : Elist_Id) is
- Constit_Elmt : Elmt_Id;
+ if Debug_Flag_Dot_O then
+ Process_Conditional_ABE
+ (N => Build_Access_Marker (Subp_Id),
+ In_State => New_In_State);
- begin
- if Present (Constits) then
- Constit_Elmt := First_Elmt (Constits);
- while Present (Constit_Elmt) loop
- Check_SPARK_Constituent (Node (Constit_Elmt));
- Next_Elmt (Constit_Elmt);
- end loop;
+ -- Otherwise ensure that the unit with the corresponding body is
+ -- elaborated prior to the main unit.
+
+ else
+ Ensure_Prior_Elaboration
+ (N => Attr,
+ Unit_Id => Unit (Subp_Rep),
+ Prag_Nam => Name_Elaborate_All,
+ In_State => New_In_State);
end if;
- end Check_SPARK_Constituents;
+ end Process_Conditional_ABE_Access_Taken;
- -----------------------------------
- -- Check_SPARK_Initialized_State --
- -----------------------------------
+ ----------------------------------------
+ -- Process_Conditional_ABE_Activation --
+ ----------------------------------------
- procedure Check_SPARK_Initialized_State (State : Node_Id) is
- Prag : Node_Id;
- State_Id : Entity_Id;
+ procedure Process_Conditional_ABE_Activation
+ (Call : Node_Id;
+ Call_Rep : Scenario_Rep_Id;
+ Obj_Id : Entity_Id;
+ Obj_Rep : Target_Rep_Id;
+ Task_Typ : Entity_Id;
+ Task_Rep : Target_Rep_Id;
+ In_State : Processing_In_State)
+ is
+ pragma Unreferenced (Task_Typ);
+
+ Body_Decl : constant Node_Id := Body_Declaration (Task_Rep);
+ Spec_Decl : constant Node_Id := Spec_Declaration (Task_Rep);
+ Root : constant Node_Id := Root_Scenario;
+ Unit_Id : constant Node_Id := Unit (Task_Rep);
+
+ Check_OK : constant Boolean :=
+ not In_State.Suppress_Checks
+ and then Ghost_Mode_Of (Obj_Rep) /= Is_Ignored
+ and then Ghost_Mode_Of (Task_Rep) /= Is_Ignored
+ and then Elaboration_Checks_OK (Obj_Rep)
+ and then Elaboration_Checks_OK (Task_Rep);
+ -- A run-time ABE check may be installed only when the object and the
+ -- task type have active elaboration checks, and both are not ignored
+ -- Ghost constructs.
+
+ New_In_State : Processing_In_State := In_State;
+ -- Each step of the Processing phase constitutes a new state
begin
- -- Nothing to do for "null" initialization items
+ -- Output relevant information when switch -gnatel (info messages on
+ -- implicit Elaborate[_All] pragmas) is in effect.
- if Nkind (State) = N_Null then
- return;
+ if Elab_Info_Messages
+ and then not New_In_State.Suppress_Info_Messages
+ then
+ Error_Msg_NE
+ ("info: activation of & during elaboration", Call, Obj_Id);
+ end if;
- -- Nothing to do for illegal states
+ -- Nothing to do when the call activates a task whose type is defined
+ -- within an instance and switch -gnatd_i (ignore activations and
+ -- calls to instances for elaboration) is in effect.
- elsif Error_Posted (State) then
+ if Debug_Flag_Underscore_I
+ and then In_External_Instance
+ (N => Call,
+ Target_Decl => Spec_Decl)
+ then
return;
- end if;
-
- State_Id := Entity_Of (State);
- -- Sanitize the state
+ -- Nothing to do when the activation is a guaranteed ABE
- if No (State_Id) then
+ elsif Is_Known_Guaranteed_ABE (Call) then
return;
- elsif Error_Posted (State_Id) then
+ -- Nothing to do when the root scenario appears at the declaration
+ -- level and the task is in the same unit, but outside this context.
+ --
+ -- task type Task_Typ; -- task declaration
+ --
+ -- procedure Proc is
+ -- function A ... is
+ -- begin
+ -- if Some_Condition then
+ -- declare
+ -- T : Task_Typ;
+ -- begin
+ -- <activation call> -- activation site
+ -- end;
+ -- ...
+ -- end A;
+ --
+ -- X : ... := A; -- root scenario
+ -- ...
+ --
+ -- task body Task_Typ is
+ -- ...
+ -- end Task_Typ;
+ --
+ -- In the example above, the context of X is the declarative list of
+ -- Proc. The "elaboration" of X may reach the activation of T whose
+ -- body is defined outside of X's context. The task body is relevant
+ -- only when Proc is invoked, but this happens only during "normal"
+ -- elaboration, therefore the task body must not be considered if
+ -- this is not the case.
+
+ elsif Is_Up_Level_Target
+ (Targ_Decl => Spec_Decl,
+ In_State => New_In_State)
+ then
return;
- elsif Ekind (State_Id) /= E_Abstract_State then
- return;
- end if;
+ -- Nothing to do when the activation is ABE-safe
+ --
+ -- generic
+ -- package Gen is
+ -- task type Task_Typ;
+ -- end Gen;
+ --
+ -- package body Gen is
+ -- task body Task_Typ is
+ -- begin
+ -- ...
+ -- end Task_Typ;
+ -- end Gen;
+ --
+ -- with Gen;
+ -- procedure Main is
+ -- package Nested is
+ -- package Inst is new Gen;
+ -- T : Inst.Task_Typ;
+ -- <activation call> -- safe activation
+ -- end Nested;
+ -- ...
+
+ elsif Is_Safe_Activation (Call, Task_Rep) then
- -- The check is performed only when the abstract state is subject to
- -- SPARK_Mode On.
+ -- Note that the task body must still be examined for any nested
+ -- scenarios.
- Prag := SPARK_Pragma (State_Id);
+ null;
- if Present (Prag)
- and then Get_SPARK_Mode_From_Annotation (Prag) = On
+ -- The activation call and the task body are both in the main unit
+ --
+ -- If the root scenario appears prior to the task body, then this is
+ -- a possible ABE with respect to the root scenario.
+ --
+ -- task type Task_Typ;
+ --
+ -- function A ... is
+ -- begin
+ -- if Some_Condition then
+ -- declare
+ -- package Pack is
+ -- T : Task_Typ;
+ -- end Pack; -- activation of T
+ -- ...
+ -- end A;
+ --
+ -- X : ... := A; -- root scenario
+ --
+ -- task body Task_Typ is -- task body
+ -- ...
+ -- end Task_Typ;
+ --
+ -- Y : ... := A; -- root scenario
+ --
+ -- IMPORTANT: The activation of T is a possible ABE for X, but
+ -- not for Y. Intalling an unconditional ABE raise prior to the
+ -- activation call would be wrong as it will fail for Y as well
+ -- but in Y's case the activation of T is never an ABE.
+
+ elsif Present (Body_Decl)
+ and then In_Extended_Main_Code_Unit (Body_Decl)
then
- Check_SPARK_Constituents (Refinement_Constituents (State_Id));
- end if;
- end Check_SPARK_Initialized_State;
+ if Earlier_In_Extended_Unit (Root, Body_Decl) then
- ------------------------------------
- -- Check_SPARK_Initialized_States --
- ------------------------------------
+ -- Do not emit any ABE diagnostics when a previous scenario in
+ -- this traversal has suppressed elaboration warnings.
- procedure Check_SPARK_Initialized_States (Pack_Id : Entity_Id) is
- Prag : constant Node_Id := Get_Pragma (Pack_Id, Pragma_Initializes);
- Init : Node_Id;
- Inits : Node_Id;
+ if New_In_State.Suppress_Warnings then
+ null;
- begin
- if Present (Prag) then
- Inits := Expression (Get_Argument (Prag, Pack_Id));
+ -- Do not emit any ABE diagnostics when the activation occurs
+ -- in a partial finalization context because this action leads
+ -- to confusing noise.
- -- Avoid processing a "null" initialization list. The only other
- -- alternative is an aggregate.
+ elsif New_In_State.Within_Partial_Finalization then
+ null;
- if Nkind (Inits) = N_Aggregate then
+ -- Otherwise emit the ABE disgnostic
- -- The initialization items appear in list form:
- --
- -- (state1, state2)
-
- if Present (Expressions (Inits)) then
- Init := First (Expressions (Inits));
- while Present (Init) loop
- Check_SPARK_Initialized_State (Init);
- Next (Init);
- end loop;
+ else
+ Error_Msg_Sloc := Sloc (Call);
+ Error_Msg_N
+ ("??task & will be activated # before elaboration of its "
+ & "body", Obj_Id);
+ Error_Msg_N
+ ("\Program_Error may be raised at run time", Obj_Id);
+
+ Output_Active_Scenarios (Obj_Id, New_In_State);
end if;
- -- The initialization items appear in associated form:
- --
- -- (state1 => item1,
- -- state2 => (item2, item3))
-
- if Present (Component_Associations (Inits)) then
- Init := First (Component_Associations (Inits));
- while Present (Init) loop
- Check_SPARK_Initialized_State (Init);
- Next (Init);
- end loop;
+ -- Install a conditional run-time ABE check to verify that the
+ -- task body has been elaborated prior to the activation call.
+
+ if Check_OK then
+ Install_Scenario_ABE_Check
+ (N => Call,
+ Targ_Id => Defining_Entity (Spec_Decl),
+ Targ_Rep => Task_Rep,
+ Disable => Obj_Rep);
+
+ -- Update the state of the Processing phase to indicate that
+ -- no implicit Elaborate[_All] pragma must be generated from
+ -- this point on.
+ --
+ -- task type Task_Typ;
+ --
+ -- function A ... is
+ -- begin
+ -- if Some_Condition then
+ -- declare
+ -- package Pack is
+ -- <ABE check>
+ -- T : Task_Typ;
+ -- end Pack; -- activation of T
+ -- ...
+ -- end A;
+ --
+ -- X : ... := A;
+ --
+ -- task body Task_Typ is
+ -- begin
+ -- External.Subp; -- imparts Elaborate_All
+ -- end Task_Typ;
+ --
+ -- If Some_Condition is True, then the ABE check will fail
+ -- at runtime and the call to External.Subp will never take
+ -- place, rendering the implicit Elaborate_All useless.
+ --
+ -- If the value of Some_Condition is False, then the call
+ -- to External.Subp will never take place, rendering the
+ -- implicit Elaborate_All useless.
+
+ New_In_State.Suppress_Implicit_Pragmas := True;
end if;
end if;
+
+ -- Otherwise the task body is not available in this compilation or
+ -- it resides in an external unit. Install a run-time ABE check to
+ -- verify that the task body has been elaborated prior to the
+ -- activation call when the dynamic model is in effect.
+
+ elsif Check_OK
+ and then New_In_State.Processing = Dynamic_Model_Processing
+ then
+ Install_Unit_ABE_Check
+ (N => Call,
+ Unit_Id => Unit_Id,
+ Disable => Obj_Rep);
end if;
- end Check_SPARK_Initialized_States;
- -- Local variables
+ -- Both the activation call and task type are subject to SPARK_Mode
+ -- On, this triggers the SPARK rules for task activation. Compared
+ -- to calls and instantiations, task activation in SPARK does not
+ -- require the presence of Elaborate[_All] pragmas in case the task
+ -- type is defined outside the main unit. This is because SPARK uses
+ -- a special policy which activates all tasks after the main unit has
+ -- finished its elaboration.
- Pack_Body : constant Node_Id := Find_Related_Package_Or_Body (N);
+ if SPARK_Mode_Of (Call_Rep) = Is_On
+ and then SPARK_Mode_Of (Task_Rep) = Is_On
+ then
+ null;
- -- Start of processing for Check_SPARK_Refined_State_Pragma
+ -- Otherwise the Ada rules are in effect. Ensure that the unit with
+ -- the task body is elaborated prior to the main unit.
- begin
- -- Pragma Refined_State must be associated with a package body
+ else
+ Ensure_Prior_Elaboration
+ (N => Call,
+ Unit_Id => Unit_Id,
+ Prag_Nam => Name_Elaborate_All,
+ In_State => New_In_State);
+ end if;
- pragma Assert
- (Present (Pack_Body) and then Nkind (Pack_Body) = N_Package_Body);
+ Traverse_Conditional_ABE_Body
+ (N => Body_Decl,
+ In_State => New_In_State);
+ end Process_Conditional_ABE_Activation;
- -- Verify that each external contitunent of an abstract state mentioned
- -- in pragma Initializes is properly elaborated.
+ ----------------------------------
+ -- Process_Conditional_ABE_Call --
+ ----------------------------------
- Check_SPARK_Initialized_States (Unique_Defining_Entity (Pack_Body));
- end Check_SPARK_Refined_State_Pragma;
+ procedure Process_Conditional_ABE_Call
+ (Call : Node_Id;
+ Call_Rep : Scenario_Rep_Id;
+ In_State : Processing_In_State)
+ is
+ function In_Initialization_Context (N : Node_Id) return Boolean;
+ pragma Inline (In_Initialization_Context);
+ -- Determine whether arbitrary node N appears within a type init
+ -- proc, primitive [Deep_]Initialize, or a block created for
+ -- initialization purposes.
+
+ function Is_Partial_Finalization_Proc
+ (Subp_Id : Entity_Id) return Boolean;
+ pragma Inline (Is_Partial_Finalization_Proc);
+ -- Determine whether subprogram Subp_Id is a partial finalization
+ -- procedure.
- ----------------------
- -- Compilation_Unit --
- ----------------------
+ -------------------------------
+ -- In_Initialization_Context --
+ -------------------------------
- function Compilation_Unit (Unit_Id : Entity_Id) return Node_Id is
- Comp_Unit : Node_Id;
+ function In_Initialization_Context (N : Node_Id) return Boolean is
+ Par : Node_Id;
+ Spec_Id : Entity_Id;
- begin
- Comp_Unit := Parent (Unit_Id);
+ begin
+ -- Climb the parent chain looking for initialization actions
- -- Handle the case where a concurrent subunit is rewritten as a null
- -- statement due to expansion activities.
+ Par := Parent (N);
+ while Present (Par) loop
- if Nkind (Comp_Unit) = N_Null_Statement
- and then Nkind_In (Original_Node (Comp_Unit), N_Protected_Body,
- N_Task_Body)
- then
- Comp_Unit := Parent (Comp_Unit);
- pragma Assert (Nkind (Comp_Unit) = N_Subunit);
+ -- A block may be part of the initialization actions of a
+ -- default initialized object.
- -- Otherwise use the declaration node of the unit
+ if Nkind (Par) = N_Block_Statement
+ and then Is_Initialization_Block (Par)
+ then
+ return True;
- else
- Comp_Unit := Parent (Unit_Declaration_Node (Unit_Id));
- end if;
+ -- A subprogram body may denote an initialization routine
- -- Handle the case where a subprogram instantiation which acts as a
- -- compilation unit is expanded into an anonymous package that wraps
- -- the instantiated subprogram.
+ elsif Nkind (Par) = N_Subprogram_Body then
+ Spec_Id := Unique_Defining_Entity (Par);
- if Nkind (Comp_Unit) = N_Package_Specification
- and then Nkind_In (Original_Node (Parent (Comp_Unit)),
- N_Function_Instantiation,
- N_Procedure_Instantiation)
- then
- Comp_Unit := Parent (Parent (Comp_Unit));
+ -- The current subprogram body denotes a type init proc or
+ -- primitive [Deep_]Initialize.
- -- Handle the case where the compilation unit is a subunit
+ if Is_Init_Proc (Spec_Id)
+ or else Is_Controlled_Proc (Spec_Id, Name_Initialize)
+ or else Is_TSS (Spec_Id, TSS_Deep_Initialize)
+ then
+ return True;
+ end if;
- elsif Nkind (Comp_Unit) = N_Subunit then
- Comp_Unit := Parent (Comp_Unit);
- end if;
+ -- Prevent the search from going too far
- pragma Assert (Nkind (Comp_Unit) = N_Compilation_Unit);
+ elsif Is_Body_Or_Package_Declaration (Par) then
+ exit;
+ end if;
- return Comp_Unit;
- end Compilation_Unit;
+ Par := Parent (Par);
+ end loop;
- -----------------------
- -- Early_Call_Region --
- -----------------------
+ return False;
+ end In_Initialization_Context;
- function Early_Call_Region (Body_Id : Entity_Id) return Node_Id is
- begin
- pragma Assert (Ekind_In (Body_Id, E_Entry,
- E_Entry_Family,
- E_Function,
- E_Procedure,
- E_Subprogram_Body));
-
- if Early_Call_Regions_In_Use then
- return Early_Call_Regions.Get (Body_Id);
- end if;
+ ----------------------------------
+ -- Is_Partial_Finalization_Proc --
+ ----------------------------------
- return Early_Call_Regions_No_Element;
- end Early_Call_Region;
+ function Is_Partial_Finalization_Proc
+ (Subp_Id : Entity_Id) return Boolean
+ is
+ begin
+ -- To qualify, the subprogram must denote a finalizer procedure
+ -- or primitive [Deep_]Finalize, and the call must appear within
+ -- an initialization context.
- -----------------------------
- -- Early_Call_Regions_Hash --
- -----------------------------
+ return
+ (Is_Controlled_Proc (Subp_Id, Name_Finalize)
+ or else Is_Finalizer_Proc (Subp_Id)
+ or else Is_TSS (Subp_Id, TSS_Deep_Finalize))
+ and then In_Initialization_Context (Call);
+ end Is_Partial_Finalization_Proc;
- function Early_Call_Regions_Hash
- (Key : Entity_Id) return Early_Call_Regions_Index
- is
- begin
- return Early_Call_Regions_Index (Key mod Early_Call_Regions_Max);
- end Early_Call_Regions_Hash;
+ -- Local variables
- -----------------
- -- Elab_Msg_NE --
- -----------------
+ Subp_Id : constant Entity_Id := Target (Call_Rep);
+ Subp_Rep : constant Target_Rep_Id :=
+ Target_Representation_Of (Subp_Id, In_State);
+ Subp_Decl : constant Node_Id := Spec_Declaration (Subp_Rep);
- procedure Elab_Msg_NE
- (Msg : String;
- N : Node_Id;
- Id : Entity_Id;
- Info_Msg : Boolean;
- In_SPARK : Boolean)
- is
- function Prefix return String;
- -- Obtain the prefix of the message
+ SPARK_Rules_On : constant Boolean :=
+ SPARK_Mode_Of (Call_Rep) = Is_On
+ and then SPARK_Mode_Of (Subp_Rep) = Is_On;
- function Suffix return String;
- -- Obtain the suffix of the message
+ New_In_State : Processing_In_State := In_State;
+ -- Each step of the Processing phase constitutes a new state
- ------------
- -- Prefix --
- ------------
+ -- Start of processing for Process_Conditional_ABE_Call
- function Prefix return String is
begin
- if Info_Msg then
- return "info: ";
- else
- return "";
+ -- Output relevant information when switch -gnatel (info messages on
+ -- implicit Elaborate[_All] pragmas) is in effect.
+
+ if Elab_Info_Messages
+ and then not New_In_State.Suppress_Info_Messages
+ then
+ Info_Call
+ (Call => Call,
+ Subp_Id => Subp_Id,
+ Info_Msg => True,
+ In_SPARK => SPARK_Rules_On);
end if;
- end Prefix;
- ------------
- -- Suffix --
- ------------
+ -- Check whether the invocation of an entry clashes with an existing
+ -- restriction. This check is relevant only when the processing was
+ -- started from some library-level scenario.
- function Suffix return String is
- begin
- if In_SPARK then
- return " in SPARK";
- else
- return "";
+ if Is_Protected_Entry (Subp_Id) then
+ Check_Restriction (No_Entry_Calls_In_Elaboration_Code, Call);
+
+ elsif Is_Task_Entry (Subp_Id) then
+ Check_Restriction (No_Entry_Calls_In_Elaboration_Code, Call);
+
+ -- Task entry calls are never processed because the entry being
+ -- invoked does not have a corresponding "body", it has a select.
+
+ return;
end if;
- end Suffix;
- -- Start of processing for Elab_Msg_NE
+ -- Nothing to do when the call invokes a target defined within an
+ -- instance and switch -gnatd_i (ignore activations and calls to
+ -- instances for elaboration) is in effect.
- begin
- Error_Msg_NE (Prefix & Msg & Suffix, N, Id);
- end Elab_Msg_NE;
+ if Debug_Flag_Underscore_I
+ and then In_External_Instance
+ (N => Call,
+ Target_Decl => Subp_Decl)
+ then
+ return;
- ------------------------
- -- Elaboration_Status --
- ------------------------
+ -- Nothing to do when the call is a guaranteed ABE
- function Elaboration_Status
- (Unit_Id : Entity_Id) return Elaboration_Attributes
- is
- begin
- if Elaboration_Statuses_In_Use then
- return Elaboration_Statuses.Get (Unit_Id);
- end if;
+ elsif Is_Known_Guaranteed_ABE (Call) then
+ return;
- return Elaboration_Statuses_No_Element;
- end Elaboration_Status;
+ -- Nothing to do when the root scenario appears at the declaration
+ -- level and the target is in the same unit but outside this context.
+ --
+ -- function B ...; -- target declaration
+ --
+ -- procedure Proc is
+ -- function A ... is
+ -- begin
+ -- if Some_Condition then
+ -- return B; -- call site
+ -- ...
+ -- end A;
+ --
+ -- X : ... := A; -- root scenario
+ -- ...
+ --
+ -- function B ... is
+ -- ...
+ -- end B;
+ --
+ -- In the example above, the context of X is the declarative region
+ -- of Proc. The "elaboration" of X may eventually reach B which is
+ -- defined outside of X's context. B is relevant only when Proc is
+ -- invoked, but this happens only by means of "normal" elaboration,
+ -- therefore B must not be considered if this is not the case.
+
+ elsif Is_Up_Level_Target
+ (Targ_Decl => Subp_Decl,
+ In_State => New_In_State)
+ then
+ return;
+ end if;
- -------------------------------
- -- Elaboration_Statuses_Hash --
- -------------------------------
+ -- Warnings are suppressed when a prior scenario is already in that
+ -- mode, or the call or target have warnings suppressed. Update the
+ -- state of the Processing phase to reflect this.
- function Elaboration_Statuses_Hash
- (Key : Entity_Id) return Elaboration_Statuses_Index
- is
- begin
- return Elaboration_Statuses_Index (Key mod Elaboration_Statuses_Max);
- end Elaboration_Statuses_Hash;
+ New_In_State.Suppress_Warnings :=
+ New_In_State.Suppress_Warnings
+ or else not Elaboration_Warnings_OK (Call_Rep)
+ or else not Elaboration_Warnings_OK (Subp_Rep);
- ------------------------------
- -- Ensure_Prior_Elaboration --
- ------------------------------
+ -- The call occurs in an initial condition context when a prior
+ -- scenario is already in that mode, or when the target is an
+ -- Initial_Condition procedure. Update the state of the Processing
+ -- phase to reflect this.
- procedure Ensure_Prior_Elaboration
- (N : Node_Id;
- Unit_Id : Entity_Id;
- Prag_Nam : Name_Id;
- State : Processing_Attributes)
- is
- begin
- pragma Assert (Nam_In (Prag_Nam, Name_Elaborate, Name_Elaborate_All));
+ New_In_State.Within_Initial_Condition :=
+ New_In_State.Within_Initial_Condition
+ or else Is_Initial_Condition_Proc (Subp_Id);
- -- Nothing to do when the caller has suppressed the generation of
- -- implicit Elaborate[_All] pragmas.
+ -- The call occurs in a partial finalization context when a prior
+ -- scenario is already in that mode, or when the target denotes a
+ -- [Deep_]Finalize primitive or a finalizer within an initialization
+ -- context. Update the state of the Processing phase to reflect this.
- if State.Suppress_Implicit_Pragmas then
- return;
+ New_In_State.Within_Partial_Finalization :=
+ New_In_State.Within_Partial_Finalization
+ or else Is_Partial_Finalization_Proc (Subp_Id);
- -- Nothing to do when the need for prior elaboration came from a partial
- -- finalization routine which occurs in an initialization context. This
- -- behaviour parallels that of the old ABE mechanism.
+ -- The SPARK rules are in effect. Note that -gnatd.v (enforce SPARK
+ -- elaboration rules in SPARK code) is intentionally not taken into
+ -- account here because Process_Conditional_ABE_Call_SPARK has two
+ -- separate modes of operation.
- elsif State.Within_Partial_Finalization then
- return;
+ if SPARK_Rules_On then
+ Process_Conditional_ABE_Call_SPARK
+ (Call => Call,
+ Call_Rep => Call_Rep,
+ Subp_Id => Subp_Id,
+ Subp_Rep => Subp_Rep,
+ In_State => New_In_State);
- -- Nothing to do when the need for prior elaboration came from a task
- -- body and switch -gnatd.y (disable implicit pragma Elaborate_All on
- -- task bodies) is in effect.
+ -- Otherwise the Ada rules are in effect
- elsif Debug_Flag_Dot_Y and then State.Within_Task_Body then
- return;
+ else
+ Process_Conditional_ABE_Call_Ada
+ (Call => Call,
+ Call_Rep => Call_Rep,
+ Subp_Id => Subp_Id,
+ Subp_Rep => Subp_Rep,
+ In_State => New_In_State);
+ end if;
- -- Nothing to do when the unit is elaborated prior to the main unit.
- -- This check must also consider the following cases:
-
- -- * No check is made against the context of the main unit because this
- -- is specific to the elaboration model in effect and requires custom
- -- handling (see Ensure_xxx_Prior_Elaboration).
-
- -- * Unit_Id is subject to pragma Elaborate_Body. An implicit pragma
- -- Elaborate[_All] MUST be generated even though Unit_Id is always
- -- elaborated prior to the main unit. This is a conservative strategy
- -- which ensures that other units withed by Unit_Id will not lead to
- -- an ABE.
-
- -- package A is package body A is
- -- procedure ABE; procedure ABE is ... end ABE;
- -- end A; end A;
-
- -- with A;
- -- package B is package body B is
- -- pragma Elaborate_Body; procedure Proc is
- -- begin
- -- procedure Proc; A.ABE;
- -- package B; end Proc;
- -- end B;
-
- -- with B;
- -- package C is package body C is
- -- ... ...
- -- end C; begin
- -- B.Proc;
- -- end C;
-
- -- In the example above, the elaboration of C invokes B.Proc. B is
- -- subject to pragma Elaborate_Body. If no pragma Elaborate[_All] is
- -- generated for B in C, then the following elaboratio order will lead
- -- to an ABE:
-
- -- spec of A elaborated
- -- spec of B elaborated
- -- body of B elaborated
- -- spec of C elaborated
- -- body of C elaborated <-- calls B.Proc which calls A.ABE
- -- body of A elaborated <-- problem
-
- -- The generation of an implicit pragma Elaborate_All (B) ensures that
- -- the elaboration order mechanism will not pick the above order.
-
- -- An implicit Elaborate is NOT generated when the unit is subject to
- -- Elaborate_Body because both pragmas have the exact same effect.
-
- -- * Unit_Id is the main unit. An implicit pragma Elaborate[_All] MUST
- -- NOT be generated in this case because a unit cannot depend on its
- -- own elaboration. This case is therefore treated as valid prior
- -- elaboration.
-
- elsif Has_Prior_Elaboration
- (Unit_Id => Unit_Id,
- Same_Unit_OK => True,
- Elab_Body_OK => Prag_Nam = Name_Elaborate)
- then
- return;
+ -- Inspect the target body (and barried function) for other suitable
+ -- elaboration scenarios.
- -- Suggest the use of pragma Prag_Nam when the dynamic model is in
- -- effect.
+ Traverse_Conditional_ABE_Body
+ (N => Barrier_Body_Declaration (Subp_Rep),
+ In_State => New_In_State);
- elsif Dynamic_Elaboration_Checks then
- Ensure_Prior_Elaboration_Dynamic
- (N => N,
- Unit_Id => Unit_Id,
- Prag_Nam => Prag_Nam);
+ Traverse_Conditional_ABE_Body
+ (N => Body_Declaration (Subp_Rep),
+ In_State => New_In_State);
+ end Process_Conditional_ABE_Call;
- -- Install an implicit pragma Prag_Nam when the static model is in
- -- effect.
+ --------------------------------------
+ -- Process_Conditional_ABE_Call_Ada --
+ --------------------------------------
- else
- pragma Assert (Static_Elaboration_Checks);
+ procedure Process_Conditional_ABE_Call_Ada
+ (Call : Node_Id;
+ Call_Rep : Scenario_Rep_Id;
+ Subp_Id : Entity_Id;
+ Subp_Rep : Target_Rep_Id;
+ In_State : Processing_In_State)
+ is
+ Body_Decl : constant Node_Id := Body_Declaration (Subp_Rep);
+ Root : constant Node_Id := Root_Scenario;
+ Unit_Id : constant Node_Id := Unit (Subp_Rep);
+
+ Check_OK : constant Boolean :=
+ not In_State.Suppress_Checks
+ and then Ghost_Mode_Of (Call_Rep) /= Is_Ignored
+ and then Ghost_Mode_Of (Subp_Rep) /= Is_Ignored
+ and then Elaboration_Checks_OK (Call_Rep)
+ and then Elaboration_Checks_OK (Subp_Rep);
+ -- A run-time ABE check may be installed only when both the call
+ -- and the target have active elaboration checks, and both are not
+ -- ignored Ghost constructs.
+
+ New_In_State : Processing_In_State := In_State;
+ -- Each step of the Processing phase constitutes a new state
- Ensure_Prior_Elaboration_Static
- (N => N,
- Unit_Id => Unit_Id,
- Prag_Nam => Prag_Nam);
- end if;
- end Ensure_Prior_Elaboration;
+ begin
+ -- Nothing to do for an Ada dispatching call because there are no
+ -- ABE diagnostics for either models. ABE checks for the dynamic
+ -- model are handled by Install_Primitive_Elaboration_Check.
- --------------------------------------
- -- Ensure_Prior_Elaboration_Dynamic --
- --------------------------------------
+ if Is_Dispatching_Call (Call_Rep) then
+ return;
- procedure Ensure_Prior_Elaboration_Dynamic
- (N : Node_Id;
- Unit_Id : Entity_Id;
- Prag_Nam : Name_Id)
- is
- procedure Info_Missing_Pragma;
- pragma Inline (Info_Missing_Pragma);
- -- Output information concerning missing Elaborate or Elaborate_All
- -- pragma with name Prag_Nam for scenario N, which would ensure the
- -- prior elaboration of Unit_Id.
+ -- Nothing to do when the call is ABE-safe
+ --
+ -- generic
+ -- function Gen ...;
+ --
+ -- function Gen ... is
+ -- begin
+ -- ...
+ -- end Gen;
+ --
+ -- with Gen;
+ -- procedure Main is
+ -- function Inst is new Gen;
+ -- X : ... := Inst; -- safe call
+ -- ...
- -------------------------
- -- Info_Missing_Pragma --
- -------------------------
+ elsif Is_Safe_Call (Call, Subp_Id, Subp_Rep) then
+ return;
- procedure Info_Missing_Pragma is
- begin
- -- Internal units are ignored as they cause unnecessary noise
+ -- The call and the target body are both in the main unit
+ --
+ -- If the root scenario appears prior to the target body, then this
+ -- is a possible ABE with respect to the root scenario.
+ --
+ -- function B ...;
+ --
+ -- function A ... is
+ -- begin
+ -- if Some_Condition then
+ -- return B; -- call site
+ -- ...
+ -- end A;
+ --
+ -- X : ... := A; -- root scenario
+ --
+ -- function B ... is -- target body
+ -- ...
+ -- end B;
+ --
+ -- Y : ... := A; -- root scenario
+ --
+ -- IMPORTANT: The call to B from A is a possible ABE for X, but
+ -- not for Y. Installing an unconditional ABE raise prior to the
+ -- call to B would be wrong as it will fail for Y as well, but in
+ -- Y's case the call to B is never an ABE.
- if not In_Internal_Unit (Unit_Id) then
+ elsif Present (Body_Decl)
+ and then In_Extended_Main_Code_Unit (Body_Decl)
+ then
+ if Earlier_In_Extended_Unit (Root, Body_Decl) then
- -- The name of the unit subjected to the elaboration pragma is
- -- fully qualified to improve the clarity of the info message.
+ -- Do not emit any ABE diagnostics when a previous scenario in
+ -- this traversal has suppressed elaboration warnings.
- Error_Msg_Name_1 := Prag_Nam;
- Error_Msg_Qual_Level := Nat'Last;
+ if New_In_State.Suppress_Warnings then
+ null;
- Error_Msg_NE ("info: missing pragma % for unit &", N, Unit_Id);
- Error_Msg_Qual_Level := 0;
- end if;
- end Info_Missing_Pragma;
+ -- Do not emit any ABE diagnostics when the call occurs in a
+ -- partial finalization context because this leads to confusing
+ -- noise.
- -- Local variables
+ elsif New_In_State.Within_Partial_Finalization then
+ null;
- Elab_Attrs : Elaboration_Attributes;
- Level : Enclosing_Level_Kind;
+ -- Otherwise emit the ABE diagnostic
- -- Start of processing for Ensure_Prior_Elaboration_Dynamic
+ else
+ Error_Msg_NE
+ ("??cannot call & before body seen", Call, Subp_Id);
+ Error_Msg_N
+ ("\Program_Error may be raised at run time", Call);
- begin
- Elab_Attrs := Elaboration_Status (Unit_Id);
+ Output_Active_Scenarios (Call, New_In_State);
+ end if;
- -- Nothing to do when the unit is guaranteed prior elaboration by means
- -- of a source Elaborate[_All] pragma.
+ -- Install a conditional run-time ABE check to verify that the
+ -- target body has been elaborated prior to the call.
+
+ if Check_OK then
+ Install_Scenario_ABE_Check
+ (N => Call,
+ Targ_Id => Subp_Id,
+ Targ_Rep => Subp_Rep,
+ Disable => Call_Rep);
+
+ -- Update the state of the Processing phase to indicate that
+ -- no implicit Elaborate[_All] pragma must be generated from
+ -- this point on.
+ --
+ -- function B ...;
+ --
+ -- function A ... is
+ -- begin
+ -- if Some_Condition then
+ -- <ABE check>
+ -- return B;
+ -- ...
+ -- end A;
+ --
+ -- X : ... := A;
+ --
+ -- function B ... is
+ -- External.Subp; -- imparts Elaborate_All
+ -- end B;
+ --
+ -- If Some_Condition is True, then the ABE check will fail
+ -- at runtime and the call to External.Subp will never take
+ -- place, rendering the implicit Elaborate_All useless.
+ --
+ -- If the value of Some_Condition is False, then the call
+ -- to External.Subp will never take place, rendering the
+ -- implicit Elaborate_All useless.
+
+ New_In_State.Suppress_Implicit_Pragmas := True;
+ end if;
+ end if;
- if Present (Elab_Attrs.Source_Pragma) then
- return;
- end if;
+ -- Otherwise the target body is not available in this compilation or
+ -- it resides in an external unit. Install a run-time ABE check to
+ -- verify that the target body has been elaborated prior to the call
+ -- site when the dynamic model is in effect.
- -- Output extra information on a missing Elaborate[_All] pragma when
- -- switch -gnatel (info messages on implicit Elaborate[_All] pragmas
- -- is in effect.
+ elsif Check_OK
+ and then New_In_State.Processing = Dynamic_Model_Processing
+ then
+ Install_Unit_ABE_Check
+ (N => Call,
+ Unit_Id => Unit_Id,
+ Disable => Call_Rep);
+ end if;
- if Elab_Info_Messages then
+ -- Ensure that the unit with the target body is elaborated prior to
+ -- the main unit. The implicit Elaborate[_All] is generated only when
+ -- the call has elaboration checks enabled. This behaviour parallels
+ -- that of the old ABE mechanism.
+
+ if Elaboration_Checks_OK (Call_Rep) then
+ Ensure_Prior_Elaboration
+ (N => Call,
+ Unit_Id => Unit_Id,
+ Prag_Nam => Name_Elaborate_All,
+ In_State => New_In_State);
+ end if;
+ end Process_Conditional_ABE_Call_Ada;
- -- Performance note: parent traversal
+ ----------------------------------------
+ -- Process_Conditional_ABE_Call_SPARK --
+ ----------------------------------------
+
+ procedure Process_Conditional_ABE_Call_SPARK
+ (Call : Node_Id;
+ Call_Rep : Scenario_Rep_Id;
+ Subp_Id : Entity_Id;
+ Subp_Rep : Target_Rep_Id;
+ In_State : Processing_In_State)
+ is
+ pragma Unreferenced (Call_Rep);
- Level := Find_Enclosing_Level (N);
+ Body_Decl : constant Node_Id := Body_Declaration (Subp_Rep);
+ Region : Node_Id;
- -- Declaration-level scenario
+ begin
+ -- Ensure that a suitable elaboration model is in effect for SPARK
+ -- rule verification.
- if (Is_Suitable_Call (N) or else Is_Suitable_Instantiation (N))
- and then Level = Declaration_Level
+ Check_SPARK_Model_In_Effect;
+
+ -- The call and the target body are both in the main unit
+
+ if Present (Body_Decl)
+ and then In_Extended_Main_Code_Unit (Body_Decl)
+ and then Earlier_In_Extended_Unit (Call, Body_Decl)
then
- null;
+ -- Do not emit any ABE diagnostics when a previous scenario in
+ -- this traversal has suppressed elaboration warnings.
- -- Library-level scenario
+ if In_State.Suppress_Warnings then
+ null;
- elsif Level in Library_Level then
- null;
+ -- Do not emit any ABE diagnostics when the call occurs in an
+ -- initial condition context because this leads to incorrect
+ -- diagnostics.
- -- Instantiation library-level scenario
+ elsif In_State.Within_Initial_Condition then
+ null;
- elsif Level = Instantiation then
- null;
+ -- Do not emit any ABE diagnostics when the call occurs in a
+ -- partial finalization context because this leads to confusing
+ -- noise.
- -- Otherwise the scenario does not appear at the proper level and
- -- cannot possibly act as a top-level scenario.
+ elsif In_State.Within_Partial_Finalization then
+ null;
+
+ -- Ensure that a call that textually precedes the subprogram body
+ -- it invokes appears within the early call region of the body.
+ --
+ -- IMPORTANT: This check must always be performed even when switch
+ -- -gnatd.v (enforce SPARK elaboration rules in SPARK code) is not
+ -- specified because the static model cannot guarantee the absence
+ -- of elaboration issues when dispatching calls are involved.
+
+ else
+ Region := Find_Early_Call_Region (Body_Decl);
+
+ if Earlier_In_Extended_Unit (Call, Region) then
+ Error_Msg_NE
+ ("call must appear within early call region of subprogram "
+ & "body & (SPARK RM 7.7(3))",
+ Call, Subp_Id);
+
+ Error_Msg_Sloc := Sloc (Region);
+ Error_Msg_N ("\region starts #", Call);
+
+ Error_Msg_Sloc := Sloc (Body_Decl);
+ Error_Msg_N ("\region ends #", Call);
+
+ Output_Active_Scenarios (Call, In_State);
+ end if;
+ end if;
+ end if;
+
+ -- A call to a source target or to a target which emulates Ada
+ -- or SPARK semantics imposes an Elaborate_All requirement on the
+ -- context of the main unit. Determine whether the context has a
+ -- pragma strong enough to meet the requirement.
+ --
+ -- IMPORTANT: This check must be performed only when switch -gnatd.v
+ -- (enforce SPARK elaboration rules in SPARK code) is active because
+ -- the static model can ensure the prior elaboration of the unit
+ -- which contains a body by installing an implicit Elaborate[_All]
+ -- pragma.
+
+ if Debug_Flag_Dot_V then
+ if Comes_From_Source (Subp_Id)
+ or else Is_Ada_Semantic_Target (Subp_Id)
+ or else Is_SPARK_Semantic_Target (Subp_Id)
+ then
+ Meet_Elaboration_Requirement
+ (N => Call,
+ Targ_Id => Subp_Id,
+ Req_Nam => Name_Elaborate_All,
+ In_State => In_State);
+ end if;
+
+ -- Otherwise ensure that the unit with the target body is elaborated
+ -- prior to the main unit.
else
+ Ensure_Prior_Elaboration
+ (N => Call,
+ Unit_Id => Unit (Subp_Rep),
+ Prag_Nam => Name_Elaborate_All,
+ In_State => In_State);
+ end if;
+ end Process_Conditional_ABE_Call_SPARK;
+
+ -------------------------------------------
+ -- Process_Conditional_ABE_Instantiation --
+ -------------------------------------------
+
+ procedure Process_Conditional_ABE_Instantiation
+ (Inst : Node_Id;
+ Inst_Rep : Scenario_Rep_Id;
+ In_State : Processing_In_State)
+ is
+ Gen_Id : constant Entity_Id := Target (Inst_Rep);
+ Gen_Rep : constant Target_Rep_Id :=
+ Target_Representation_Of (Gen_Id, In_State);
+
+ SPARK_Rules_On : constant Boolean :=
+ SPARK_Mode_Of (Inst_Rep) = Is_On
+ and then SPARK_Mode_Of (Gen_Rep) = Is_On;
+
+ New_In_State : Processing_In_State := In_State;
+ -- Each step of the Processing phase constitutes a new state
+
+ begin
+ -- Output relevant information when switch -gnatel (info messages on
+ -- implicit Elaborate[_All] pragmas) is in effect.
+
+ if Elab_Info_Messages
+ and then not New_In_State.Suppress_Info_Messages
+ then
+ Info_Instantiation
+ (Inst => Inst,
+ Gen_Id => Gen_Id,
+ Info_Msg => True,
+ In_SPARK => SPARK_Rules_On);
+ end if;
+
+ -- Nothing to do when the instantiation is a guaranteed ABE
+
+ if Is_Known_Guaranteed_ABE (Inst) then
+ return;
+
+ -- Nothing to do when the root scenario appears at the declaration
+ -- level and the generic is in the same unit, but outside this
+ -- context.
+ --
+ -- generic
+ -- procedure Gen is ...; -- generic declaration
+ --
+ -- procedure Proc is
+ -- function A ... is
+ -- begin
+ -- if Some_Condition then
+ -- declare
+ -- procedure I is new Gen; -- instantiation site
+ -- ...
+ -- ...
+ -- end A;
+ --
+ -- X : ... := A; -- root scenario
+ -- ...
+ --
+ -- procedure Gen is
+ -- ...
+ -- end Gen;
+ --
+ -- In the example above, the context of X is the declarative region
+ -- of Proc. The "elaboration" of X may eventually reach Gen which
+ -- appears outside of X's context. Gen is relevant only when Proc is
+ -- invoked, but this happens only by means of "normal" elaboration,
+ -- therefore Gen must not be considered if this is not the case.
+
+ elsif Is_Up_Level_Target
+ (Targ_Decl => Spec_Declaration (Gen_Rep),
+ In_State => New_In_State)
+ then
return;
end if;
- Info_Missing_Pragma;
- end if;
- end Ensure_Prior_Elaboration_Dynamic;
+ -- Warnings are suppressed when a prior scenario is already in that
+ -- mode, or when the instantiation has warnings suppressed. Update
+ -- the state of the processing phase to reflect this.
- -------------------------------------
- -- Ensure_Prior_Elaboration_Static --
- -------------------------------------
+ New_In_State.Suppress_Warnings :=
+ New_In_State.Suppress_Warnings
+ or else not Elaboration_Warnings_OK (Inst_Rep);
- procedure Ensure_Prior_Elaboration_Static
- (N : Node_Id;
- Unit_Id : Entity_Id;
- Prag_Nam : Name_Id)
- is
- function Find_With_Clause
- (Items : List_Id;
- Withed_Id : Entity_Id) return Node_Id;
- pragma Inline (Find_With_Clause);
- -- Find a nonlimited with clause in the list of context items Items
- -- that withs unit Withed_Id. Return Empty if no such clause is found.
-
- procedure Info_Implicit_Pragma;
- pragma Inline (Info_Implicit_Pragma);
- -- Output information concerning an implicitly generated Elaborate or
- -- Elaborate_All pragma with name Prag_Nam for scenario N which ensures
- -- the prior elaboration of unit Unit_Id.
+ -- The SPARK rules are in effect
- ----------------------
- -- Find_With_Clause --
- ----------------------
+ if SPARK_Rules_On then
+ Process_Conditional_ABE_Instantiation_SPARK
+ (Inst => Inst,
+ Inst_Rep => Inst_Rep,
+ Gen_Id => Gen_Id,
+ Gen_Rep => Gen_Rep,
+ In_State => New_In_State);
+
+ -- Otherwise the Ada rules are in effect, or SPARK code is allowed to
+ -- violate the SPARK rules.
- function Find_With_Clause
- (Items : List_Id;
- Withed_Id : Entity_Id) return Node_Id
+ else
+ Process_Conditional_ABE_Instantiation_Ada
+ (Inst => Inst,
+ Inst_Rep => Inst_Rep,
+ Gen_Id => Gen_Id,
+ Gen_Rep => Gen_Rep,
+ In_State => New_In_State);
+ end if;
+ end Process_Conditional_ABE_Instantiation;
+
+ -----------------------------------------------
+ -- Process_Conditional_ABE_Instantiation_Ada --
+ -----------------------------------------------
+
+ procedure Process_Conditional_ABE_Instantiation_Ada
+ (Inst : Node_Id;
+ Inst_Rep : Scenario_Rep_Id;
+ Gen_Id : Entity_Id;
+ Gen_Rep : Target_Rep_Id;
+ In_State : Processing_In_State)
is
- Item : Node_Id;
+ Body_Decl : constant Node_Id := Body_Declaration (Gen_Rep);
+ Root : constant Node_Id := Root_Scenario;
+ Unit_Id : constant Entity_Id := Unit (Gen_Rep);
+
+ Check_OK : constant Boolean :=
+ not In_State.Suppress_Checks
+ and then Ghost_Mode_Of (Inst_Rep) /= Is_Ignored
+ and then Ghost_Mode_Of (Gen_Rep) /= Is_Ignored
+ and then Elaboration_Checks_OK (Inst_Rep)
+ and then Elaboration_Checks_OK (Gen_Rep);
+ -- A run-time ABE check may be installed only when both the instance
+ -- and the generic have active elaboration checks and both are not
+ -- ignored Ghost constructs.
+
+ New_In_State : Processing_In_State := In_State;
+ -- Each step of the Processing phase constitutes a new state
begin
- -- Examine the context clauses looking for a suitable with. Note that
- -- limited clauses do not affect the elaboration order.
+ -- Nothing to do when the instantiation is ABE-safe
+ --
+ -- generic
+ -- package Gen is
+ -- ...
+ -- end Gen;
+ --
+ -- package body Gen is
+ -- ...
+ -- end Gen;
+ --
+ -- with Gen;
+ -- procedure Main is
+ -- package Inst is new Gen (ABE); -- safe instantiation
+ -- ...
- Item := First (Items);
- while Present (Item) loop
- if Nkind (Item) = N_With_Clause
- and then not Error_Posted (Item)
- and then not Limited_Present (Item)
- and then Entity (Name (Item)) = Withed_Id
- then
- return Item;
+ if Is_Safe_Instantiation (Inst, Gen_Id, Gen_Rep) then
+ return;
+
+ -- The instantiation and the generic body are both in the main unit
+ --
+ -- If the root scenario appears prior to the generic body, then this
+ -- is a possible ABE with respect to the root scenario.
+ --
+ -- generic
+ -- package Gen is
+ -- ...
+ -- end Gen;
+ --
+ -- function A ... is
+ -- begin
+ -- if Some_Condition then
+ -- declare
+ -- package Inst is new Gen; -- instantiation site
+ -- ...
+ -- end A;
+ --
+ -- X : ... := A; -- root scenario
+ --
+ -- package body Gen is -- generic body
+ -- ...
+ -- end Gen;
+ --
+ -- Y : ... := A; -- root scenario
+ --
+ -- IMPORTANT: The instantiation of Gen is a possible ABE for X,
+ -- but not for Y. Installing an unconditional ABE raise prior to
+ -- the instance site would be wrong as it will fail for Y as well,
+ -- but in Y's case the instantiation of Gen is never an ABE.
+
+ elsif Present (Body_Decl)
+ and then In_Extended_Main_Code_Unit (Body_Decl)
+ then
+ if Earlier_In_Extended_Unit (Root, Body_Decl) then
+
+ -- Do not emit any ABE diagnostics when a previous scenario in
+ -- this traversal has suppressed elaboration warnings.
+
+ if New_In_State.Suppress_Warnings then
+ null;
+
+ -- Do not emit any ABE diagnostics when the instantiation
+ -- occurs in partial finalization context because this leads
+ -- to unwanted noise.
+
+ elsif New_In_State.Within_Partial_Finalization then
+ null;
+
+ -- Otherwise output the diagnostic
+
+ else
+ Error_Msg_NE
+ ("??cannot instantiate & before body seen", Inst, Gen_Id);
+ Error_Msg_N
+ ("\Program_Error may be raised at run time", Inst);
+
+ Output_Active_Scenarios (Inst, New_In_State);
+ end if;
+
+ -- Install a conditional run-time ABE check to verify that the
+ -- generic body has been elaborated prior to the instantiation.
+
+ if Check_OK then
+ Install_Scenario_ABE_Check
+ (N => Inst,
+ Targ_Id => Gen_Id,
+ Targ_Rep => Gen_Rep,
+ Disable => Inst_Rep);
+
+ -- Update the state of the Processing phase to indicate that
+ -- no implicit Elaborate[_All] pragma must be generated from
+ -- this point on.
+ --
+ -- generic
+ -- package Gen is
+ -- ...
+ -- end Gen;
+ --
+ -- function A ... is
+ -- begin
+ -- if Some_Condition then
+ -- <ABE check>
+ -- declare Inst is new Gen;
+ -- ...
+ -- end A;
+ --
+ -- X : ... := A;
+ --
+ -- package body Gen is
+ -- begin
+ -- External.Subp; -- imparts Elaborate_All
+ -- end Gen;
+ --
+ -- If Some_Condition is True, then the ABE check will fail
+ -- at runtime and the call to External.Subp will never take
+ -- place, rendering the implicit Elaborate_All useless.
+ --
+ -- If the value of Some_Condition is False, then the call
+ -- to External.Subp will never take place, rendering the
+ -- implicit Elaborate_All useless.
+
+ New_In_State.Suppress_Implicit_Pragmas := True;
+ end if;
end if;
- Next (Item);
- end loop;
+ -- Otherwise the generic body is not available in this compilation
+ -- or it resides in an external unit. Install a run-time ABE check
+ -- to verify that the generic body has been elaborated prior to the
+ -- instantiation when the dynamic model is in effect.
- return Empty;
- end Find_With_Clause;
+ elsif Check_OK
+ and then New_In_State.Processing = Dynamic_Model_Processing
+ then
+ Install_Unit_ABE_Check
+ (N => Inst,
+ Unit_Id => Unit_Id,
+ Disable => Inst_Rep);
+ end if;
- --------------------------
- -- Info_Implicit_Pragma --
- --------------------------
+ -- Ensure that the unit with the generic body is elaborated prior
+ -- to the main unit. No implicit pragma has to be generated if the
+ -- instantiation has elaboration checks suppressed. This behaviour
+ -- parallels that of the old ABE mechanism.
+
+ if Elaboration_Checks_OK (Inst_Rep) then
+ Ensure_Prior_Elaboration
+ (N => Inst,
+ Unit_Id => Unit_Id,
+ Prag_Nam => Name_Elaborate,
+ In_State => New_In_State);
+ end if;
+ end Process_Conditional_ABE_Instantiation_Ada;
+
+ -------------------------------------------------
+ -- Process_Conditional_ABE_Instantiation_SPARK --
+ -------------------------------------------------
+
+ procedure Process_Conditional_ABE_Instantiation_SPARK
+ (Inst : Node_Id;
+ Inst_Rep : Scenario_Rep_Id;
+ Gen_Id : Entity_Id;
+ Gen_Rep : Target_Rep_Id;
+ In_State : Processing_In_State)
+ is
+ pragma Unreferenced (Inst_Rep);
+
+ Req_Nam : Name_Id;
- procedure Info_Implicit_Pragma is
begin
- -- Internal units are ignored as they cause unnecessary noise
+ -- Ensure that a suitable elaboration model is in effect for SPARK
+ -- rule verification.
- if not In_Internal_Unit (Unit_Id) then
+ Check_SPARK_Model_In_Effect;
- -- The name of the unit subjected to the elaboration pragma is
- -- fully qualified to improve the clarity of the info message.
+ -- A source instantiation imposes an Elaborate[_All] requirement
+ -- on the context of the main unit. Determine whether the context
+ -- has a pragma strong enough to meet the requirement. The check
+ -- is orthogonal to the ABE ramifications of the instantiation.
+ --
+ -- IMPORTANT: This check must be performed only when switch -gnatd.v
+ -- (enforce SPARK elaboration rules in SPARK code) is active because
+ -- the static model can ensure the prior elaboration of the unit
+ -- which contains a body by installing an implicit Elaborate[_All]
+ -- pragma.
+
+ if Debug_Flag_Dot_V then
+ if Nkind (Inst) = N_Package_Instantiation then
+ Req_Nam := Name_Elaborate_All;
+ else
+ Req_Nam := Name_Elaborate;
+ end if;
- Error_Msg_Name_1 := Prag_Nam;
- Error_Msg_Qual_Level := Nat'Last;
+ Meet_Elaboration_Requirement
+ (N => Inst,
+ Targ_Id => Gen_Id,
+ Req_Nam => Req_Nam,
+ In_State => In_State);
- Error_Msg_NE
- ("info: implicit pragma % generated for unit &", N, Unit_Id);
+ -- Otherwise ensure that the unit with the target body is elaborated
+ -- prior to the main unit.
- Error_Msg_Qual_Level := 0;
- Output_Active_Scenarios (N);
+ else
+ Ensure_Prior_Elaboration
+ (N => Inst,
+ Unit_Id => Unit (Gen_Rep),
+ Prag_Nam => Name_Elaborate,
+ In_State => In_State);
end if;
- end Info_Implicit_Pragma;
+ end Process_Conditional_ABE_Instantiation_SPARK;
- -- Local variables
+ -------------------------------------------------
+ -- Process_Conditional_ABE_Variable_Assignment --
+ -------------------------------------------------
- Main_Cunit : constant Node_Id := Cunit (Main_Unit);
- Loc : constant Source_Ptr := Sloc (Main_Cunit);
- Unit_Cunit : constant Node_Id := Compilation_Unit (Unit_Id);
+ procedure Process_Conditional_ABE_Variable_Assignment
+ (Asmt : Node_Id;
+ Asmt_Rep : Scenario_Rep_Id;
+ In_State : Processing_In_State)
+ is
- Clause : Node_Id;
- Elab_Attrs : Elaboration_Attributes;
- Items : List_Id;
+ Var_Id : constant Entity_Id := Target (Asmt_Rep);
+ Var_Rep : constant Target_Rep_Id :=
+ Target_Representation_Of (Var_Id, In_State);
- -- Start of processing for Ensure_Prior_Elaboration_Static
+ SPARK_Rules_On : constant Boolean :=
+ SPARK_Mode_Of (Asmt_Rep) = Is_On
+ and then SPARK_Mode_Of (Var_Rep) = Is_On;
- begin
- Elab_Attrs := Elaboration_Status (Unit_Id);
+ begin
+ -- Output relevant information when switch -gnatel (info messages on
+ -- implicit Elaborate[_All] pragmas) is in effect.
+
+ if Elab_Info_Messages
+ and then not In_State.Suppress_Info_Messages
+ then
+ Elab_Msg_NE
+ (Msg => "assignment to & during elaboration",
+ N => Asmt,
+ Id => Var_Id,
+ Info_Msg => True,
+ In_SPARK => SPARK_Rules_On);
+ end if;
- -- Nothing to do when the unit is guaranteed prior elaboration by means
- -- of a source Elaborate[_All] pragma.
+ -- The SPARK rules are in effect. These rules are applied regardless
+ -- of whether switch -gnatd.v (enforce SPARK elaboration rules in
+ -- SPARK code) is in effect because the static model cannot ensure
+ -- safe assignment of variables.
- if Present (Elab_Attrs.Source_Pragma) then
- return;
+ if SPARK_Rules_On then
+ Process_Conditional_ABE_Variable_Assignment_SPARK
+ (Asmt => Asmt,
+ Asmt_Rep => Asmt_Rep,
+ Var_Id => Var_Id,
+ Var_Rep => Var_Rep,
+ In_State => In_State);
- -- Nothing to do when the unit has an existing implicit Elaborate[_All]
- -- pragma installed by a previous scenario.
+ -- Otherwise the Ada rules are in effect
- elsif Present (Elab_Attrs.With_Clause) then
+ else
+ Process_Conditional_ABE_Variable_Assignment_Ada
+ (Asmt => Asmt,
+ Asmt_Rep => Asmt_Rep,
+ Var_Id => Var_Id,
+ Var_Rep => Var_Rep,
+ In_State => In_State);
+ end if;
+ end Process_Conditional_ABE_Variable_Assignment;
+
+ -----------------------------------------------------
+ -- Process_Conditional_ABE_Variable_Assignment_Ada --
+ -----------------------------------------------------
+
+ procedure Process_Conditional_ABE_Variable_Assignment_Ada
+ (Asmt : Node_Id;
+ Asmt_Rep : Scenario_Rep_Id;
+ Var_Id : Entity_Id;
+ Var_Rep : Target_Rep_Id;
+ In_State : Processing_In_State)
+ is
+ pragma Unreferenced (Asmt_Rep);
- -- The unit is already guaranteed prior elaboration by means of an
- -- implicit Elaborate pragma, however the current scenario imposes
- -- a stronger requirement of Elaborate_All. "Upgrade" the existing
- -- pragma to match this new requirement.
+ Var_Decl : constant Node_Id := Variable_Declaration (Var_Rep);
+ Unit_Id : constant Entity_Id := Unit (Var_Rep);
- if Elaborate_Desirable (Elab_Attrs.With_Clause)
- and then Prag_Nam = Name_Elaborate_All
+ begin
+ -- Emit a warning when an uninitialized variable declared in a
+ -- package spec without a pragma Elaborate_Body is initialized
+ -- by elaboration code within the corresponding body.
+
+ if Is_Elaboration_Warnings_OK_Id (Var_Id)
+ and then not Is_Initialized (Var_Decl)
+ and then not Has_Pragma_Elaborate_Body (Unit_Id)
then
- Set_Elaborate_All_Desirable (Elab_Attrs.With_Clause);
- Set_Elaborate_Desirable (Elab_Attrs.With_Clause, False);
+ -- Do not emit any ABE diagnostics when a previous scenario in
+ -- this traversal has suppressed elaboration warnings.
+
+ if not In_State.Suppress_Warnings then
+ Error_Msg_NE
+ ("??variable & can be accessed by clients before this "
+ & "initialization", Asmt, Var_Id);
+
+ Error_Msg_NE
+ ("\add pragma ""Elaborate_Body"" to spec & to ensure proper "
+ & "initialization", Asmt, Unit_Id);
+
+ Output_Active_Scenarios (Asmt, In_State);
+ end if;
+
+ -- Generate an implicit Elaborate_Body in the spec
+
+ Set_Elaborate_Body_Desirable (Unit_Id);
end if;
+ end Process_Conditional_ABE_Variable_Assignment_Ada;
+
+ -------------------------------------------------------
+ -- Process_Conditional_ABE_Variable_Assignment_SPARK --
+ -------------------------------------------------------
+
+ procedure Process_Conditional_ABE_Variable_Assignment_SPARK
+ (Asmt : Node_Id;
+ Asmt_Rep : Scenario_Rep_Id;
+ Var_Id : Entity_Id;
+ Var_Rep : Target_Rep_Id;
+ In_State : Processing_In_State)
+ is
+ pragma Unreferenced (Asmt_Rep);
- return;
- end if;
+ Var_Decl : constant Node_Id := Variable_Declaration (Var_Rep);
+ Unit_Id : constant Entity_Id := Unit (Var_Rep);
- -- At this point it is known that the unit has no prior elaboration
- -- according to pragmas and hierarchical relationships.
+ begin
+ -- Ensure that a suitable elaboration model is in effect for SPARK
+ -- rule verification.
- Items := Context_Items (Main_Cunit);
+ Check_SPARK_Model_In_Effect;
- if No (Items) then
- Items := New_List;
- Set_Context_Items (Main_Cunit, Items);
- end if;
+ -- Do not emit any ABE diagnostics when a previous scenario in this
+ -- traversal has suppressed elaboration warnings.
- -- Locate the with clause for the unit. Note that there may not be a
- -- clause if the unit is visible through a subunit-body, body-spec, or
- -- spec-parent relationship.
+ if In_State.Suppress_Warnings then
+ null;
- Clause :=
- Find_With_Clause
- (Items => Items,
- Withed_Id => Unit_Id);
+ -- Emit an error when an initialized variable declared in a package
+ -- spec that is missing pragma Elaborate_Body is further modified by
+ -- elaboration code within the corresponding body.
- -- Generate:
- -- with Id;
+ elsif Is_Elaboration_Warnings_OK_Id (Var_Id)
+ and then Is_Initialized (Var_Decl)
+ and then not Has_Pragma_Elaborate_Body (Unit_Id)
+ then
+ Error_Msg_NE
+ ("variable & modified by elaboration code in package body",
+ Asmt, Var_Id);
- -- Note that adding implicit with clauses is safe because analysis,
- -- resolution, and expansion have already taken place and it is not
- -- possible to interfere with visibility.
+ Error_Msg_NE
+ ("\add pragma ""Elaborate_Body"" to spec & to ensure full "
+ & "initialization", Asmt, Unit_Id);
- if No (Clause) then
- Clause :=
- Make_With_Clause (Loc,
- Name => New_Occurrence_Of (Unit_Id, Loc));
+ Output_Active_Scenarios (Asmt, In_State);
+ end if;
+ end Process_Conditional_ABE_Variable_Assignment_SPARK;
- Set_Implicit_With (Clause);
- Set_Library_Unit (Clause, Unit_Cunit);
+ ------------------------------------------------
+ -- Process_Conditional_ABE_Variable_Reference --
+ ------------------------------------------------
- Append_To (Items, Clause);
- end if;
+ procedure Process_Conditional_ABE_Variable_Reference
+ (Ref : Node_Id;
+ Ref_Rep : Scenario_Rep_Id;
+ In_State : Processing_In_State)
+ is
+ Var_Id : constant Entity_Id := Target (Ref);
+ Var_Rep : Target_Rep_Id;
+ Unit_Id : Entity_Id;
- -- Mark the with clause depending on the pragma required
+ begin
+ -- Nothing to do when the variable reference is not a read
- if Prag_Nam = Name_Elaborate then
- Set_Elaborate_Desirable (Clause);
- else
- Set_Elaborate_All_Desirable (Clause);
- end if;
+ if not Is_Read_Reference (Ref_Rep) then
+ return;
+ end if;
- -- The implicit Elaborate[_All] ensures the prior elaboration of the
- -- unit. Include the unit in the elaboration context of the main unit.
+ Var_Rep := Target_Representation_Of (Var_Id, In_State);
+ Unit_Id := Unit (Var_Rep);
- Set_Elaboration_Status
- (Unit_Id => Unit_Id,
- Val => Elaboration_Attributes'(Source_Pragma => Empty,
- With_Clause => Clause));
+ -- Output relevant information when switch -gnatel (info messages on
+ -- implicit Elaborate[_All] pragmas) is in effect.
- -- Output extra information on an implicit Elaborate[_All] pragma when
- -- switch -gnatel (info messages on implicit Elaborate[_All] pragmas is
- -- in effect.
+ if Elab_Info_Messages
+ and then not In_State.Suppress_Info_Messages
+ then
+ Elab_Msg_NE
+ (Msg => "read of variable & during elaboration",
+ N => Ref,
+ Id => Var_Id,
+ Info_Msg => True,
+ In_SPARK => True);
+ end if;
- if Elab_Info_Messages then
- Info_Implicit_Pragma;
- end if;
- end Ensure_Prior_Elaboration_Static;
+ -- Nothing to do when the variable appears within the main unit
+ -- because diagnostics on reads are relevant only for external
+ -- variables.
- -----------------------------
- -- Extract_Assignment_Name --
- -----------------------------
+ if Is_Same_Unit (Unit_Id, Cunit_Entity (Main_Unit)) then
+ null;
- function Extract_Assignment_Name (Asmt : Node_Id) return Node_Id is
- Nam : Node_Id;
+ -- Nothing to do when the variable is already initialized. Note that
+ -- the variable may be further modified by the external unit.
- begin
- Nam := Name (Asmt);
+ elsif Is_Initialized (Variable_Declaration (Var_Rep)) then
+ null;
- -- When the name denotes an array or record component, find the whole
- -- object.
+ -- Nothing to do when the external unit guarantees the initialization
+ -- of the variable by means of pragma Elaborate_Body.
- while Nkind_In (Nam, N_Explicit_Dereference,
- N_Indexed_Component,
- N_Selected_Component,
- N_Slice)
- loop
- Nam := Prefix (Nam);
- end loop;
+ elsif Has_Pragma_Elaborate_Body (Unit_Id) then
+ null;
- return Nam;
- end Extract_Assignment_Name;
+ -- A variable read imposes an Elaborate requirement on the context of
+ -- the main unit. Determine whether the context has a pragma strong
+ -- enough to meet the requirement.
- -----------------------------
- -- Extract_Call_Attributes --
- -----------------------------
+ else
+ Meet_Elaboration_Requirement
+ (N => Ref,
+ Targ_Id => Var_Id,
+ Req_Nam => Name_Elaborate,
+ In_State => In_State);
+ end if;
+ end Process_Conditional_ABE_Variable_Reference;
- procedure Extract_Call_Attributes
- (Call : Node_Id;
- Target_Id : out Entity_Id;
- Attrs : out Call_Attributes)
- is
- From_Source : Boolean;
- In_Declarations : Boolean;
- Is_Dispatching : Boolean;
+ -----------------------------------
+ -- Traverse_Conditional_ABE_Body --
+ -----------------------------------
+ procedure Traverse_Conditional_ABE_Body
+ (N : Node_Id;
+ In_State : Processing_In_State)
+ is
+ begin
+ Traverse_Body
+ (N => N,
+ Requires_Processing => Is_Conditional_ABE_Scenario'Access,
+ Processor => Process_Conditional_ABE'Access,
+ In_State => In_State);
+ end Traverse_Conditional_ABE_Body;
+ end Conditional_ABE_Processor;
+
+ -------------
+ -- Destroy --
+ -------------
+
+ procedure Destroy (NE : in out Node_Or_Entity_Id) is
+ pragma Unreferenced (NE);
begin
- -- Extraction for call markers
+ null;
+ end Destroy;
- if Nkind (Call) = N_Call_Marker then
- Target_Id := Target (Call);
- From_Source := Is_Source_Call (Call);
- In_Declarations := Is_Declaration_Level_Node (Call);
- Is_Dispatching := Is_Dispatching_Call (Call);
+ -----------------
+ -- Diagnostics --
+ -----------------
- -- Extraction for entry calls, requeue, and subprogram calls
+ package body Diagnostics is
- else
- pragma Assert (Nkind_In (Call, N_Entry_Call_Statement,
- N_Function_Call,
- N_Procedure_Call_Statement,
- N_Requeue_Statement));
+ -----------------
+ -- Elab_Msg_NE --
+ -----------------
- Target_Id := Entity (Extract_Call_Name (Call));
- From_Source := Comes_From_Source (Call);
+ procedure Elab_Msg_NE
+ (Msg : String;
+ N : Node_Id;
+ Id : Entity_Id;
+ Info_Msg : Boolean;
+ In_SPARK : Boolean)
+ is
+ function Prefix return String;
+ pragma Inline (Prefix);
+ -- Obtain the prefix of the message
- -- Performance note: parent traversal
+ function Suffix return String;
+ pragma Inline (Suffix);
+ -- Obtain the suffix of the message
- In_Declarations := Find_Enclosing_Level (Call) = Declaration_Level;
- Is_Dispatching :=
- Nkind_In (Call, N_Function_Call, N_Procedure_Call_Statement)
- and then Present (Controlling_Argument (Call));
- end if;
+ ------------
+ -- Prefix --
+ ------------
- -- Obtain the original entry or subprogram which the target may rename
- -- except when the target is an instantiation. In this case the alias
- -- is the internally generated subprogram which appears within the the
- -- anonymous package created for the instantiation. Such an alias is not
- -- a suitable target.
+ function Prefix return String is
+ begin
+ if Info_Msg then
+ return "info: ";
+ else
+ return "";
+ end if;
+ end Prefix;
- if not (Is_Subprogram (Target_Id)
- and then Is_Generic_Instance (Target_Id))
- then
- Target_Id := Get_Renamed_Entity (Target_Id);
- end if;
+ ------------
+ -- Suffix --
+ ------------
- -- Set all attributes
+ function Suffix return String is
+ begin
+ if In_SPARK then
+ return " in SPARK";
+ else
+ return "";
+ end if;
+ end Suffix;
- Attrs.Elab_Checks_OK := Is_Elaboration_Checks_OK_Node (Call);
- Attrs.Elab_Warnings_OK := Is_Elaboration_Warnings_OK_Node (Call);
- Attrs.From_Source := From_Source;
- Attrs.Ghost_Mode_Ignore := Is_Ignored_Ghost_Node (Call);
- Attrs.In_Declarations := In_Declarations;
- Attrs.Is_Dispatching := Is_Dispatching;
- Attrs.SPARK_Mode_On := Is_SPARK_Mode_On_Node (Call);
- end Extract_Call_Attributes;
+ -- Start of processing for Elab_Msg_NE
- -----------------------
- -- Extract_Call_Name --
- -----------------------
+ begin
+ Error_Msg_NE (Prefix & Msg & Suffix, N, Id);
+ end Elab_Msg_NE;
- function Extract_Call_Name (Call : Node_Id) return Node_Id is
- Nam : Node_Id;
+ ---------------
+ -- Info_Call --
+ ---------------
- begin
- Nam := Name (Call);
+ procedure Info_Call
+ (Call : Node_Id;
+ Subp_Id : Entity_Id;
+ Info_Msg : Boolean;
+ In_SPARK : Boolean)
+ is
+ procedure Info_Accept_Alternative;
+ pragma Inline (Info_Accept_Alternative);
+ -- Output information concerning an accept alternative
- -- When the call invokes an entry family, the name appears as an indexed
- -- component.
+ procedure Info_Simple_Call;
+ pragma Inline (Info_Simple_Call);
+ -- Output information concerning the call
- if Nkind (Nam) = N_Indexed_Component then
- Nam := Prefix (Nam);
- end if;
+ procedure Info_Type_Actions (Action : String);
+ pragma Inline (Info_Type_Actions);
+ -- Output information concerning action Action of a type
- -- When the call employs the object.operation form, the name appears as
- -- a selected component.
+ procedure Info_Verification_Call
+ (Pred : String;
+ Id : Entity_Id;
+ Id_Kind : String);
+ pragma Inline (Info_Verification_Call);
+ -- Output information concerning the verification of predicate Pred
+ -- applied to related entity Id with kind Id_Kind.
- if Nkind (Nam) = N_Selected_Component then
- Nam := Selector_Name (Nam);
- end if;
+ -----------------------------
+ -- Info_Accept_Alternative --
+ -----------------------------
- return Nam;
- end Extract_Call_Name;
+ procedure Info_Accept_Alternative is
+ Entry_Id : constant Entity_Id := Receiving_Entry (Subp_Id);
+ pragma Assert (Present (Entry_Id));
- ---------------------------------
- -- Extract_Instance_Attributes --
- ---------------------------------
+ begin
+ Elab_Msg_NE
+ (Msg => "accept for entry & during elaboration",
+ N => Call,
+ Id => Entry_Id,
+ Info_Msg => Info_Msg,
+ In_SPARK => In_SPARK);
+ end Info_Accept_Alternative;
+
+ ----------------------
+ -- Info_Simple_Call --
+ ----------------------
+
+ procedure Info_Simple_Call is
+ begin
+ Elab_Msg_NE
+ (Msg => "call to & during elaboration",
+ N => Call,
+ Id => Subp_Id,
+ Info_Msg => Info_Msg,
+ In_SPARK => In_SPARK);
+ end Info_Simple_Call;
+
+ -----------------------
+ -- Info_Type_Actions --
+ -----------------------
+
+ procedure Info_Type_Actions (Action : String) is
+ Typ : constant Entity_Id := First_Formal_Type (Subp_Id);
+ pragma Assert (Present (Typ));
- procedure Extract_Instance_Attributes
- (Exp_Inst : Node_Id;
- Inst_Body : out Node_Id;
- Inst_Decl : out Node_Id)
- is
- Body_Id : Entity_Id;
+ begin
+ Elab_Msg_NE
+ (Msg => Action & " actions for type & during elaboration",
+ N => Call,
+ Id => Typ,
+ Info_Msg => Info_Msg,
+ In_SPARK => In_SPARK);
+ end Info_Type_Actions;
+
+ ----------------------------
+ -- Info_Verification_Call --
+ ----------------------------
+
+ procedure Info_Verification_Call
+ (Pred : String;
+ Id : Entity_Id;
+ Id_Kind : String)
+ is
+ pragma Assert (Present (Id));
- begin
- -- Assume that the attributes are unavailable
+ begin
+ Elab_Msg_NE
+ (Msg =>
+ "verification of " & Pred & " of " & Id_Kind & " & during "
+ & "elaboration",
+ N => Call,
+ Id => Id,
+ Info_Msg => Info_Msg,
+ In_SPARK => In_SPARK);
+ end Info_Verification_Call;
+
+ -- Start of processing for Info_Call
- Inst_Body := Empty;
- Inst_Decl := Empty;
+ begin
+ -- Do not output anything for targets defined in internal units
+ -- because this creates noise.
- -- Generic package or subprogram spec
+ if not In_Internal_Unit (Subp_Id) then
- if Nkind_In (Exp_Inst, N_Package_Declaration,
- N_Subprogram_Declaration)
- then
- Inst_Decl := Exp_Inst;
- Body_Id := Corresponding_Body (Inst_Decl);
+ -- Accept alternative
- if Present (Body_Id) then
- Inst_Body := Unit_Declaration_Node (Body_Id);
- end if;
+ if Is_Accept_Alternative_Proc (Subp_Id) then
+ Info_Accept_Alternative;
- -- Generic package or subprogram body
+ -- Adjustment
- else
- pragma Assert
- (Nkind_In (Exp_Inst, N_Package_Body, N_Subprogram_Body));
+ elsif Is_TSS (Subp_Id, TSS_Deep_Adjust) then
+ Info_Type_Actions ("adjustment");
- Inst_Body := Exp_Inst;
- Inst_Decl := Unit_Declaration_Node (Corresponding_Spec (Inst_Body));
- end if;
- end Extract_Instance_Attributes;
+ -- Default_Initial_Condition
- --------------------------------------
- -- Extract_Instantiation_Attributes --
- --------------------------------------
+ elsif Is_Default_Initial_Condition_Proc (Subp_Id) then
+ Info_Verification_Call
+ (Pred => "Default_Initial_Condition",
+ Id => First_Formal_Type (Subp_Id),
+ Id_Kind => "type");
- procedure Extract_Instantiation_Attributes
- (Exp_Inst : Node_Id;
- Inst : out Node_Id;
- Inst_Id : out Entity_Id;
- Gen_Id : out Entity_Id;
- Attrs : out Instantiation_Attributes)
- is
- begin
- Inst := Original_Node (Exp_Inst);
- Inst_Id := Defining_Entity (Inst);
+ -- Entries
- -- Traverse a possible chain of renamings to obtain the original generic
- -- being instantiatied.
+ elsif Is_Protected_Entry (Subp_Id) then
+ Info_Simple_Call;
- Gen_Id := Get_Renamed_Entity (Entity (Name (Inst)));
+ -- Task entry calls are never processed because the entry being
+ -- invoked does not have a corresponding "body", it has a select.
- -- Set all attributes
+ elsif Is_Task_Entry (Subp_Id) then
+ null;
- Attrs.Elab_Checks_OK := Is_Elaboration_Checks_OK_Node (Inst);
- Attrs.Elab_Warnings_OK := Is_Elaboration_Warnings_OK_Node (Inst);
- Attrs.Ghost_Mode_Ignore := Is_Ignored_Ghost_Node (Inst);
- Attrs.In_Declarations := Is_Declaration_Level_Node (Inst);
- Attrs.SPARK_Mode_On := Is_SPARK_Mode_On_Node (Inst);
- end Extract_Instantiation_Attributes;
+ -- Finalization
- -------------------------------
- -- Extract_Target_Attributes --
- -------------------------------
+ elsif Is_TSS (Subp_Id, TSS_Deep_Finalize) then
+ Info_Type_Actions ("finalization");
- procedure Extract_Target_Attributes
- (Target_Id : Entity_Id;
- Attrs : out Target_Attributes)
- is
- procedure Extract_Package_Or_Subprogram_Attributes
- (Spec_Id : out Entity_Id;
- Body_Decl : out Node_Id);
- -- Obtain the attributes associated with a package or a subprogram.
- -- Spec_Id is the package or subprogram. Body_Decl is the declaration
- -- of the corresponding package or subprogram body.
-
- procedure Extract_Protected_Entry_Attributes
- (Spec_Id : out Entity_Id;
- Body_Decl : out Node_Id;
- Body_Barf : out Node_Id);
- -- Obtain the attributes associated with a protected entry [family].
- -- Spec_Id is the entity of the protected body subprogram. Body_Decl
- -- is the declaration of Spec_Id's corresponding body. Body_Barf is
- -- the declaration of the barrier function body.
-
- procedure Extract_Protected_Subprogram_Attributes
- (Spec_Id : out Entity_Id;
- Body_Decl : out Node_Id);
- -- Obtain the attributes associated with a protected subprogram. Formal
- -- Spec_Id is the entity of the protected body subprogram. Body_Decl is
- -- the declaration of Spec_Id's corresponding body.
-
- procedure Extract_Task_Entry_Attributes
- (Spec_Id : out Entity_Id;
- Body_Decl : out Node_Id);
- -- Obtain the attributes associated with a task entry [family]. Formal
- -- Spec_Id is the entity of the task body procedure. Body_Decl is the
- -- declaration of Spec_Id's corresponding body.
-
- ----------------------------------------------
- -- Extract_Package_Or_Subprogram_Attributes --
- ----------------------------------------------
-
- procedure Extract_Package_Or_Subprogram_Attributes
- (Spec_Id : out Entity_Id;
- Body_Decl : out Node_Id)
- is
- Body_Id : Entity_Id;
- Init_Id : Entity_Id;
- Spec_Decl : Node_Id;
+ -- Calls to _Finalizer procedures must not appear in the output
+ -- because this creates confusing noise.
- begin
- -- Assume that the body is not available
+ elsif Is_Finalizer_Proc (Subp_Id) then
+ null;
- Body_Decl := Empty;
- Spec_Id := Target_Id;
+ -- Initial_Condition
- -- For body retrieval purposes, the entity of the initial declaration
- -- is that of the spec.
+ elsif Is_Initial_Condition_Proc (Subp_Id) then
+ Info_Verification_Call
+ (Pred => "Initial_Condition",
+ Id => Find_Enclosing_Scope (Call),
+ Id_Kind => "package");
- Init_Id := Spec_Id;
+ -- Initialization
- -- The only exception to the above is a function which returns a
- -- constrained array type in a SPARK-to-C compilation. In this case
- -- the function receives a corresponding procedure which has an out
- -- parameter. The proper body for ABE checks and diagnostics is that
- -- of the procedure.
+ elsif Is_Init_Proc (Subp_Id)
+ or else Is_TSS (Subp_Id, TSS_Deep_Initialize)
+ then
+ Info_Type_Actions ("initialization");
- if Ekind (Init_Id) = E_Function
- and then Rewritten_For_C (Init_Id)
- then
- Init_Id := Corresponding_Procedure (Init_Id);
- end if;
+ -- Invariant
- -- Extract the attributes of the body
+ elsif Is_Invariant_Proc (Subp_Id) then
+ Info_Verification_Call
+ (Pred => "invariants",
+ Id => First_Formal_Type (Subp_Id),
+ Id_Kind => "type");
- Spec_Decl := Unit_Declaration_Node (Init_Id);
+ -- Partial invariant calls must not appear in the output because
+ -- this creates confusing noise.
- -- The initial declaration is a stand alone subprogram body
+ elsif Is_Partial_Invariant_Proc (Subp_Id) then
+ null;
- if Nkind (Spec_Decl) = N_Subprogram_Body then
- Body_Decl := Spec_Decl;
+ -- _Postconditions
- -- Otherwise the package or subprogram has a spec and a completing
- -- body.
+ elsif Is_Postconditions_Proc (Subp_Id) then
+ Info_Verification_Call
+ (Pred => "postconditions",
+ Id => Find_Enclosing_Scope (Call),
+ Id_Kind => "subprogram");
- elsif Nkind_In (Spec_Decl, N_Generic_Package_Declaration,
- N_Generic_Subprogram_Declaration,
- N_Package_Declaration,
- N_Subprogram_Body_Stub,
- N_Subprogram_Declaration)
- then
- Body_Id := Corresponding_Body (Spec_Decl);
+ -- Subprograms must come last because some of the previous cases
+ -- fall under this category.
- if Present (Body_Id) then
- Body_Decl := Unit_Declaration_Node (Body_Id);
+ elsif Ekind (Subp_Id) = E_Function then
+ Info_Simple_Call;
+
+ elsif Ekind (Subp_Id) = E_Procedure then
+ Info_Simple_Call;
+
+ else
+ pragma Assert (False);
+ return;
end if;
end if;
- end Extract_Package_Or_Subprogram_Attributes;
+ end Info_Call;
- ----------------------------------------
- -- Extract_Protected_Entry_Attributes --
- ----------------------------------------
+ ------------------------
+ -- Info_Instantiation --
+ ------------------------
- procedure Extract_Protected_Entry_Attributes
- (Spec_Id : out Entity_Id;
- Body_Decl : out Node_Id;
- Body_Barf : out Node_Id)
+ procedure Info_Instantiation
+ (Inst : Node_Id;
+ Gen_Id : Entity_Id;
+ Info_Msg : Boolean;
+ In_SPARK : Boolean)
is
- Barf_Id : Entity_Id;
- Body_Id : Entity_Id;
+ begin
+ Elab_Msg_NE
+ (Msg => "instantiation of & during elaboration",
+ N => Inst,
+ Id => Gen_Id,
+ Info_Msg => Info_Msg,
+ In_SPARK => In_SPARK);
+ end Info_Instantiation;
+ -----------------------------
+ -- Info_Variable_Reference --
+ -----------------------------
+
+ procedure Info_Variable_Reference
+ (Ref : Node_Id;
+ Var_Id : Entity_Id;
+ Info_Msg : Boolean;
+ In_SPARK : Boolean)
+ is
begin
- -- Assume that the bodies are not available
+ if Is_Read (Ref) then
+ Elab_Msg_NE
+ (Msg => "read of variable & during elaboration",
+ N => Ref,
+ Id => Var_Id,
+ Info_Msg => Info_Msg,
+ In_SPARK => In_SPARK);
+ end if;
+ end Info_Variable_Reference;
+ end Diagnostics;
- Body_Barf := Empty;
- Body_Decl := Empty;
+ ---------------------------------
+ -- Early_Call_Region_Processor --
+ ---------------------------------
- -- When the entry [family] has already been expanded, it carries both
- -- the procedure which emulates the behavior of the entry [family] as
- -- well as the barrier function.
+ package body Early_Call_Region_Processor is
- if Present (Protected_Body_Subprogram (Target_Id)) then
- Spec_Id := Protected_Body_Subprogram (Target_Id);
+ ---------------------
+ -- Data structures --
+ ---------------------
- -- Extract the attributes of the barrier function
+ -- The following map relates early call regions to subprogram bodies
- Barf_Id :=
- Corresponding_Body
- (Unit_Declaration_Node (Barrier_Function (Target_Id)));
+ procedure Destroy (N : in out Node_Id);
+ -- Destroy node N
- if Present (Barf_Id) then
- Body_Barf := Unit_Declaration_Node (Barf_Id);
- end if;
+ package ECR_Map is new Dynamic_Hash_Tables
+ (Key_Type => Entity_Id,
+ Value_Type => Node_Id,
+ No_Value => Empty,
+ Expansion_Threshold => 1.5,
+ Expansion_Factor => 2,
+ Compression_Threshold => 0.3,
+ Compression_Factor => 2,
+ "=" => "=",
+ Destroy_Value => Destroy,
+ Hash => Hash);
- -- Otherwise no expansion took place
+ Early_Call_Regions_Map : ECR_Map.Dynamic_Hash_Table := ECR_Map.Nil;
- else
- Spec_Id := Target_Id;
- end if;
+ -----------------------
+ -- Local subprograms --
+ -----------------------
- -- Extract the attributes of the entry body
+ function Early_Call_Region (Body_Id : Entity_Id) return Node_Id;
+ pragma Inline (Early_Call_Region);
+ -- Obtain the early call region associated with entry or subprogram body
+ -- Body_Id.
- Body_Id := Corresponding_Body (Unit_Declaration_Node (Spec_Id));
+ procedure Set_Early_Call_Region (Body_Id : Entity_Id; Start : Node_Id);
+ pragma Inline (Set_Early_Call_Region);
+ -- Associate an early call region with begins at construct Start with
+ -- entry or subprogram body Body_Id.
- if Present (Body_Id) then
- Body_Decl := Unit_Declaration_Node (Body_Id);
- end if;
- end Extract_Protected_Entry_Attributes;
+ -------------
+ -- Destroy --
+ -------------
- ---------------------------------------------
- -- Extract_Protected_Subprogram_Attributes --
- ---------------------------------------------
+ procedure Destroy (N : in out Node_Id) is
+ pragma Unreferenced (N);
+ begin
+ null;
+ end Destroy;
- procedure Extract_Protected_Subprogram_Attributes
- (Spec_Id : out Entity_Id;
- Body_Decl : out Node_Id)
- is
- Body_Id : Entity_Id;
+ -----------------------
+ -- Early_Call_Region --
+ -----------------------
+ function Early_Call_Region (Body_Id : Entity_Id) return Node_Id is
+ pragma Assert (Present (Body_Id));
begin
- -- Assume that the body is not available
+ return ECR_Map.Get (Early_Call_Regions_Map, Body_Id);
+ end Early_Call_Region;
- Body_Decl := Empty;
+ ------------------------------------------
+ -- Finalize_Early_Call_Region_Processor --
+ ------------------------------------------
- -- When the protected subprogram has already been expanded, it
- -- carries the subprogram which seizes the lock and invokes the
- -- original statements.
+ procedure Finalize_Early_Call_Region_Processor is
+ begin
+ ECR_Map.Destroy (Early_Call_Regions_Map);
+ end Finalize_Early_Call_Region_Processor;
- if Present (Protected_Subprogram (Target_Id)) then
- Spec_Id :=
- Protected_Body_Subprogram (Protected_Subprogram (Target_Id));
+ ----------------------------
+ -- Find_Early_Call_Region --
+ ----------------------------
- -- Otherwise no expansion took place
+ function Find_Early_Call_Region
+ (Body_Decl : Node_Id;
+ Assume_Elab_Body : Boolean := False;
+ Skip_Memoization : Boolean := False) return Node_Id
+ is
+ -- NOTE: The routines within Find_Early_Call_Region are intentionally
+ -- unnested to avoid deep indentation of code.
+
+ ECR_Found : exception;
+ -- This exception is raised when the early call region has been found
+
+ Start : Node_Id := Empty;
+ -- The start of the early call region. This variable is updated by
+ -- the various nested routines. Due to the use of exceptions, the
+ -- variable must be global to the nested routines.
+
+ -- The algorithm implemented in this routine attempts to find the
+ -- early call region of a subprogram body by inspecting constructs
+ -- in reverse declarative order, while navigating the tree. The
+ -- algorithm consists of an Inspection phase and Advancement phase.
+ -- The pseudocode is as follows:
+ --
+ -- loop
+ -- inspection phase
+ -- advancement phase
+ -- end loop
+ --
+ -- The infinite loop is terminated by raising exception ECR_Found.
+ -- The algorithm utilizes two pointers, Curr and Start, to represent
+ -- the current construct to inspect and the start of the early call
+ -- region.
+ --
+ -- IMPORTANT: The algorithm must maintain the following invariant at
+ -- all time for it to function properly:
+ --
+ -- A nested construct is entered only when it contains suitable
+ -- constructs.
+ --
+ -- This guarantees that leaving a nested or encapsulating construct
+ -- functions properly.
+ --
+ -- The Inspection phase determines whether the current construct is
+ -- non-preelaborable, and if it is, the algorithm terminates.
+ --
+ -- The Advancement phase walks the tree in reverse declarative order,
+ -- while entering and leaving nested and encapsulating constructs. It
+ -- may also terminate the elaborithm. There are several special cases
+ -- of advancement.
+ --
+ -- 1) General case:
+ --
+ -- <construct 1>
+ -- ...
+ -- <construct N-1> <- Curr
+ -- <construct N> <- Start
+ -- <subprogram body>
+ --
+ -- In the general case, a declarative or statement list is traversed
+ -- in reverse order where Curr is the lead pointer, and Start is the
+ -- last preelaborable construct.
+ --
+ -- 2) Entering handled bodies
+ --
+ -- package body Nested is <- Curr (2.3)
+ -- <declarations> <- Curr (2.2)
+ -- begin
+ -- <statements> <- Curr (2.1)
+ -- end Nested;
+ -- <construct> <- Start
+ --
+ -- In this case, the algorithm enters a handled body by starting from
+ -- the last statement (2.1), or the last declaration (2.2), or the
+ -- body is consumed (2.3) because it is empty and thus preelaborable.
+ --
+ -- 3) Entering package declarations
+ --
+ -- package Nested is <- Curr (2.3)
+ -- <visible declarations> <- Curr (2.2)
+ -- private
+ -- <private declarations> <- Curr (2.1)
+ -- end Nested;
+ -- <construct> <- Start
+ --
+ -- In this case, the algorithm enters a package declaration by
+ -- starting from the last private declaration (2.1), the last visible
+ -- declaration (2.2), or the package is consumed (2.3) because it is
+ -- empty and thus preelaborable.
+ --
+ -- 4) Transitioning from list to list of the same construct
+ --
+ -- Certain constructs have two eligible lists. The algorithm must
+ -- thus transition from the second to the first list when the second
+ -- list is exhausted.
+ --
+ -- declare <- Curr (4.2)
+ -- <declarations> <- Curr (4.1)
+ -- begin
+ -- <statements> <- Start
+ -- end;
+ --
+ -- In this case, the algorithm has exhausted the second list (the
+ -- statements in the example above), and continues with the last
+ -- declaration (4.1) or the construct is consumed (4.2) because it
+ -- contains only preelaborable code.
+ --
+ -- 5) Transitioning from list to construct
+ --
+ -- tack body Task is <- Curr (5.1)
+ -- <- Curr (Empty)
+ -- <construct 1> <- Start
+ --
+ -- In this case, the algorithm has exhausted a list, Curr is Empty,
+ -- and the owner of the list is consumed (5.1).
+ --
+ -- 6) Transitioning from unit to unit
+ --
+ -- A package body with a spec subject to pragma Elaborate_Body
+ -- extends the possible range of the early call region to the package
+ -- spec.
+ --
+ -- package Pack is <- Curr (6.3)
+ -- pragma Elaborate_Body; <- Curr (6.2)
+ -- <visible declarations> <- Curr (6.2)
+ -- private
+ -- <private declarations> <- Curr (6.1)
+ -- end Pack;
+ --
+ -- package body Pack is <- Curr, Start
+ --
+ -- In this case, the algorithm has reached a package body compilation
+ -- unit whose spec is subject to pragma Elaborate_Body, or the caller
+ -- of the algorithm has specified this behavior. This transition is
+ -- equivalent to 3).
+ --
+ -- 7) Transitioning from unit to termination
+ --
+ -- Reaching a compilation unit always terminates the algorithm as
+ -- there are no more lists to examine. This must take case 6) into
+ -- account.
+ --
+ -- 8) Transitioning from subunit to stub
+ --
+ -- package body Pack is separate; <- Curr (8.1)
+ --
+ -- separate (...)
+ -- package body Pack is <- Curr, Start
+ --
+ -- Reaching a subunit continues the search from the corresponding
+ -- stub (8.1).
+
+ procedure Advance (Curr : in out Node_Id);
+ pragma Inline (Advance);
+ -- Update the Curr and Start pointers depending on their location
+ -- in the tree to the next eligible construct. This routine raises
+ -- ECR_Found.
+
+ procedure Enter_Handled_Body (Curr : in out Node_Id);
+ pragma Inline (Enter_Handled_Body);
+ -- Update the Curr and Start pointers to enter a nested handled body
+ -- if applicable. This routine raises ECR_Found.
+
+ procedure Enter_Package_Declaration (Curr : in out Node_Id);
+ pragma Inline (Enter_Package_Declaration);
+ -- Update the Curr and Start pointers to enter a nested package spec
+ -- if applicable. This routine raises ECR_Found.
+
+ function Find_ECR (N : Node_Id) return Node_Id;
+ pragma Inline (Find_ECR);
+ -- Find an early call region starting from arbitrary node N
+
+ function Has_Suitable_Construct (List : List_Id) return Boolean;
+ pragma Inline (Has_Suitable_Construct);
+ -- Determine whether list List contains a suitable construct for
+ -- inclusion into an early call region.
+
+ procedure Include (N : Node_Id; Curr : out Node_Id);
+ pragma Inline (Include);
+ -- Update the Curr and Start pointers to include arbitrary construct
+ -- N in the early call region. This routine raises ECR_Found.
+
+ function Is_OK_Preelaborable_Construct (N : Node_Id) return Boolean;
+ pragma Inline (Is_OK_Preelaborable_Construct);
+ -- Determine whether arbitrary node N denotes a preelaboration-safe
+ -- construct.
+
+ function Is_Suitable_Construct (N : Node_Id) return Boolean;
+ pragma Inline (Is_Suitable_Construct);
+ -- Determine whether arbitrary node N denotes a suitable construct
+ -- for inclusion into the early call region.
+
+ procedure Transition_Body_Declarations
+ (Bod : Node_Id;
+ Curr : out Node_Id);
+ pragma Inline (Transition_Body_Declarations);
+ -- Update the Curr and Start pointers when construct Bod denotes a
+ -- block statement or a suitable body. This routine raises ECR_Found.
+
+ procedure Transition_Handled_Statements
+ (HSS : Node_Id;
+ Curr : out Node_Id);
+ pragma Inline (Transition_Handled_Statements);
+ -- Update the Curr and Start pointers when node HSS denotes a handled
+ -- sequence of statements. This routine raises ECR_Found.
+
+ procedure Transition_Spec_Declarations
+ (Spec : Node_Id;
+ Curr : out Node_Id);
+ pragma Inline (Transition_Spec_Declarations);
+ -- Update the Curr and Start pointers when construct Spec denotes
+ -- a concurrent definition or a package spec. This routine raises
+ -- ECR_Found.
+
+ procedure Transition_Unit (Unit : Node_Id; Curr : out Node_Id);
+ pragma Inline (Transition_Unit);
+ -- Update the Curr and Start pointers when node Unit denotes a
+ -- potential compilation unit. This routine raises ECR_Found.
+
+ -------------
+ -- Advance --
+ -------------
+
+ procedure Advance (Curr : in out Node_Id) is
+ Context : Node_Id;
- else
- Spec_Id := Target_Id;
- end if;
+ begin
+ -- Curr denotes one of the following cases upon entry into this
+ -- routine:
+ --
+ -- * Empty - There is no current construct when a declarative or
+ -- a statement list has been exhausted. This does not indicate
+ -- that the early call region has been computed as it is still
+ -- possible to transition to another list.
+ --
+ -- * Encapsulator - The current construct wraps declarations
+ -- and/or statements. This indicates that the early call
+ -- region may extend within the nested construct.
+ --
+ -- * Preelaborable - The current construct is preelaborable
+ -- because Find_ECR would not invoke Advance if this was not
+ -- the case.
- -- Extract the attributes of the body
+ -- The current construct is an encapsulator or is preelaborable
- Body_Id := Corresponding_Body (Unit_Declaration_Node (Spec_Id));
+ if Present (Curr) then
- if Present (Body_Id) then
- Body_Decl := Unit_Declaration_Node (Body_Id);
- end if;
- end Extract_Protected_Subprogram_Attributes;
+ -- Enter encapsulators by inspecting their declarations and/or
+ -- statements.
- -----------------------------------
- -- Extract_Task_Entry_Attributes --
- -----------------------------------
+ if Nkind_In (Curr, N_Block_Statement, N_Package_Body) then
+ Enter_Handled_Body (Curr);
- procedure Extract_Task_Entry_Attributes
- (Spec_Id : out Entity_Id;
- Body_Decl : out Node_Id)
- is
- Task_Typ : constant Entity_Id := Non_Private_View (Scope (Target_Id));
- Body_Id : Entity_Id;
+ elsif Nkind (Curr) = N_Package_Declaration then
+ Enter_Package_Declaration (Curr);
- begin
- -- Assume that the body is not available
+ -- Early call regions have a property which can be exploited to
+ -- optimize the algorithm.
+ --
+ -- <preceding subprogram body>
+ -- <preelaborable construct 1>
+ -- ...
+ -- <preelaborable construct N>
+ -- <initiating subprogram body>
+ --
+ -- If a traversal initiated from a subprogram body reaches a
+ -- preceding subprogram body, then both bodies share the same
+ -- early call region.
+ --
+ -- The property results in the following desirable effects:
+ --
+ -- * If the preceding body already has an early call region,
+ -- then the initiating body can reuse it. This minimizes the
+ -- amount of processing performed by the algorithm.
+ --
+ -- * If the preceding body lack an early call region, then the
+ -- algorithm can compute the early call region, and reuse it
+ -- for the initiating body. This processing performs the same
+ -- amount of work, but has the beneficial effect of computing
+ -- the early call regions of all preceding bodies.
- Body_Decl := Empty;
+ elsif Nkind_In (Curr, N_Entry_Body, N_Subprogram_Body) then
+ Start :=
+ Find_Early_Call_Region
+ (Body_Decl => Curr,
+ Assume_Elab_Body => Assume_Elab_Body,
+ Skip_Memoization => Skip_Memoization);
- -- The the task type has already been expanded, it carries the
- -- procedure which emulates the behavior of the task body.
+ raise ECR_Found;
- if Present (Task_Body_Procedure (Task_Typ)) then
- Spec_Id := Task_Body_Procedure (Task_Typ);
+ -- Otherwise current construct is preelaborable. Unpdate the
+ -- early call region to include it.
- -- Otherwise no expansion took place
+ else
+ Include (Curr, Curr);
+ end if;
- else
- Spec_Id := Task_Typ;
- end if;
+ -- Otherwise the current construct is missing, indicating that the
+ -- current list has been exhausted. Depending on the context of
+ -- the list, several transitions are possible.
- -- Extract the attributes of the body
+ else
+ -- The invariant of the algorithm ensures that Curr and Start
+ -- are at the same level of nesting at the point of transition.
+ -- The algorithm can determine which list the traversal came
+ -- from by examining Start.
- Body_Id := Corresponding_Body (Unit_Declaration_Node (Spec_Id));
+ Context := Parent (Start);
- if Present (Body_Id) then
- Body_Decl := Unit_Declaration_Node (Body_Id);
- end if;
- end Extract_Task_Entry_Attributes;
+ -- Attempt the following transitions:
+ --
+ -- private declarations -> visible declarations
+ -- private declarations -> upper level
+ -- private declarations -> terminate
+ -- visible declarations -> upper level
+ -- visible declarations -> terminate
+
+ if Nkind_In (Context, N_Package_Specification,
+ N_Protected_Definition,
+ N_Task_Definition)
+ then
+ Transition_Spec_Declarations (Context, Curr);
- -- Local variables
+ -- Attempt the following transitions:
+ --
+ -- statements -> declarations
+ -- statements -> upper level
+ -- statements -> corresponding package spec (Elab_Body)
+ -- statements -> terminate
- Prag : constant Node_Id := SPARK_Pragma (Target_Id);
- Body_Barf : Node_Id;
- Body_Decl : Node_Id;
- Spec_Id : Entity_Id;
+ elsif Nkind (Context) = N_Handled_Sequence_Of_Statements then
+ Transition_Handled_Statements (Context, Curr);
- -- Start of processing for Extract_Target_Attributes
+ -- Attempt the following transitions:
+ --
+ -- declarations -> upper level
+ -- declarations -> corresponding package spec (Elab_Body)
+ -- declarations -> terminate
+
+ elsif Nkind_In (Context, N_Block_Statement,
+ N_Entry_Body,
+ N_Package_Body,
+ N_Protected_Body,
+ N_Subprogram_Body,
+ N_Task_Body)
+ then
+ Transition_Body_Declarations (Context, Curr);
- begin
- -- Assume that the body of the barrier function is not available
+ -- Otherwise it is not possible to transition. Stop the search
+ -- because there are no more declarations or statements to
+ -- check.
- Body_Barf := Empty;
+ else
+ raise ECR_Found;
+ end if;
+ end if;
+ end Advance;
- -- The target is a protected entry [family]
+ --------------------------
+ -- Enter_Handled_Body --
+ --------------------------
- if Is_Protected_Entry (Target_Id) then
- Extract_Protected_Entry_Attributes
- (Spec_Id => Spec_Id,
- Body_Decl => Body_Decl,
- Body_Barf => Body_Barf);
+ procedure Enter_Handled_Body (Curr : in out Node_Id) is
+ Decls : constant List_Id := Declarations (Curr);
+ HSS : constant Node_Id := Handled_Statement_Sequence (Curr);
+ Stmts : List_Id := No_List;
- -- The target is a protected subprogram
+ begin
+ if Present (HSS) then
+ Stmts := Statements (HSS);
+ end if;
- elsif Is_Protected_Subp (Target_Id)
- or else Is_Protected_Body_Subp (Target_Id)
- then
- Extract_Protected_Subprogram_Attributes
- (Spec_Id => Spec_Id,
- Body_Decl => Body_Decl);
+ -- The handled body has a non-empty statement sequence. The
+ -- construct to inspect is the last statement.
- -- The target is a task entry [family]
+ if Has_Suitable_Construct (Stmts) then
+ Curr := Last (Stmts);
- elsif Is_Task_Entry (Target_Id) then
- Extract_Task_Entry_Attributes
- (Spec_Id => Spec_Id,
- Body_Decl => Body_Decl);
+ -- The handled body lacks statements, but has non-empty
+ -- declarations. The construct to inspect is the last declaration.
- -- Otherwise the target is a package or a subprogram
+ elsif Has_Suitable_Construct (Decls) then
+ Curr := Last (Decls);
- else
- Extract_Package_Or_Subprogram_Attributes
- (Spec_Id => Spec_Id,
- Body_Decl => Body_Decl);
- end if;
+ -- Otherwise the handled body lacks both declarations and
+ -- statements. The construct to inspect is the node which precedes
+ -- the handled body. Update the early call region to include the
+ -- handled body.
- -- Set all attributes
+ else
+ Include (Curr, Curr);
+ end if;
+ end Enter_Handled_Body;
- Attrs.Body_Barf := Body_Barf;
- Attrs.Body_Decl := Body_Decl;
- Attrs.Elab_Checks_OK := Is_Elaboration_Checks_OK_Id (Target_Id);
- Attrs.Elab_Warnings_OK := Is_Elaboration_Warnings_OK_Id (Target_Id);
- Attrs.From_Source := Comes_From_Source (Target_Id);
- Attrs.Ghost_Mode_Ignore := Is_Ignored_Ghost_Entity (Target_Id);
- Attrs.SPARK_Mode_On :=
- Present (Prag) and then Get_SPARK_Mode_From_Annotation (Prag) = On;
- Attrs.Spec_Decl := Unit_Declaration_Node (Spec_Id);
- Attrs.Spec_Id := Spec_Id;
- Attrs.Unit_Id := Find_Top_Unit (Target_Id);
+ -------------------------------
+ -- Enter_Package_Declaration --
+ -------------------------------
- -- At this point certain attributes should always be available
+ procedure Enter_Package_Declaration (Curr : in out Node_Id) is
+ Pack_Spec : constant Node_Id := Specification (Curr);
+ Prv_Decls : constant List_Id := Private_Declarations (Pack_Spec);
+ Vis_Decls : constant List_Id := Visible_Declarations (Pack_Spec);
- pragma Assert (Present (Attrs.Spec_Decl));
- pragma Assert (Present (Attrs.Spec_Id));
- pragma Assert (Present (Attrs.Unit_Id));
- end Extract_Target_Attributes;
+ begin
+ -- The package has a non-empty private declarations. The construct
+ -- to inspect is the last private declaration.
- -----------------------------
- -- Extract_Task_Attributes --
- -----------------------------
+ if Has_Suitable_Construct (Prv_Decls) then
+ Curr := Last (Prv_Decls);
- procedure Extract_Task_Attributes
- (Typ : Entity_Id;
- Attrs : out Task_Attributes)
- is
- Task_Typ : constant Entity_Id := Non_Private_View (Typ);
+ -- The package lacks private declarations, but has non-empty
+ -- visible declarations. In this case the construct to inspect
+ -- is the last visible declaration.
- Body_Decl : Node_Id;
- Body_Id : Entity_Id;
- Prag : Node_Id;
- Spec_Id : Entity_Id;
+ elsif Has_Suitable_Construct (Vis_Decls) then
+ Curr := Last (Vis_Decls);
- begin
- -- Assume that the body of the task procedure is not available
+ -- Otherwise the package lacks any declarations. The construct
+ -- to inspect is the node which precedes the package. Update the
+ -- early call region to include the package declaration.
- Body_Decl := Empty;
+ else
+ Include (Curr, Curr);
+ end if;
+ end Enter_Package_Declaration;
- -- The initial declaration is that of the task body procedure
+ --------------
+ -- Find_ECR --
+ --------------
- Spec_Id := Get_Task_Body_Procedure (Task_Typ);
- Body_Id := Corresponding_Body (Unit_Declaration_Node (Spec_Id));
+ function Find_ECR (N : Node_Id) return Node_Id is
+ Curr : Node_Id;
- if Present (Body_Id) then
- Body_Decl := Unit_Declaration_Node (Body_Id);
- end if;
+ begin
+ -- The early call region starts at N
- Prag := SPARK_Pragma (Task_Typ);
+ Curr := Prev (N);
+ Start := N;
- -- Set all attributes
+ -- Inspect each node in reverse declarative order while going in
+ -- and out of nested and enclosing constructs. Note that the only
+ -- way to terminate this infinite loop is to raise ECR_Found.
- Attrs.Body_Decl := Body_Decl;
- Attrs.Elab_Checks_OK := Is_Elaboration_Checks_OK_Id (Task_Typ);
- Attrs.Elab_Warnings_OK := Is_Elaboration_Warnings_OK_Id (Task_Typ);
- Attrs.Ghost_Mode_Ignore := Is_Ignored_Ghost_Entity (Task_Typ);
- Attrs.SPARK_Mode_On :=
- Present (Prag) and then Get_SPARK_Mode_From_Annotation (Prag) = On;
- Attrs.Spec_Id := Spec_Id;
- Attrs.Task_Decl := Declaration_Node (Task_Typ);
- Attrs.Unit_Id := Find_Top_Unit (Task_Typ);
+ loop
+ -- The current construct is not preelaboration-safe. Terminate
+ -- the traversal.
- -- At this point certain attributes should always be available
+ if Present (Curr)
+ and then not Is_OK_Preelaborable_Construct (Curr)
+ then
+ raise ECR_Found;
+ end if;
- pragma Assert (Present (Attrs.Spec_Id));
- pragma Assert (Present (Attrs.Task_Decl));
- pragma Assert (Present (Attrs.Unit_Id));
- end Extract_Task_Attributes;
+ -- Advance to the next suitable construct. This may terminate
+ -- the traversal by raising ECR_Found.
- -------------------------------------------
- -- Extract_Variable_Reference_Attributes --
- -------------------------------------------
+ Advance (Curr);
+ end loop;
- procedure Extract_Variable_Reference_Attributes
- (Ref : Node_Id;
- Var_Id : out Entity_Id;
- Attrs : out Variable_Attributes)
- is
- function Get_Renamed_Variable (Id : Entity_Id) return Entity_Id;
- -- Obtain the ultimate renamed variable of variable Id
+ exception
+ when ECR_Found =>
+ return Start;
+ end Find_ECR;
- --------------------------
- -- Get_Renamed_Variable --
- --------------------------
+ ----------------------------
+ -- Has_Suitable_Construct --
+ ----------------------------
- function Get_Renamed_Variable (Id : Entity_Id) return Entity_Id is
- Ren_Id : Entity_Id;
+ function Has_Suitable_Construct (List : List_Id) return Boolean is
+ Item : Node_Id;
- begin
- Ren_Id := Id;
- while Present (Renamed_Entity (Ren_Id))
- and then Nkind (Renamed_Entity (Ren_Id)) in N_Entity
- loop
- Ren_Id := Renamed_Entity (Ren_Id);
- end loop;
+ begin
+ -- Examine the list in reverse declarative order, looking for a
+ -- suitable construct.
+
+ if Present (List) then
+ Item := Last (List);
+ while Present (Item) loop
+ if Is_Suitable_Construct (Item) then
+ return True;
+ end if;
- return Ren_Id;
- end Get_Renamed_Variable;
+ Prev (Item);
+ end loop;
+ end if;
- -- Start of processing for Extract_Variable_Reference_Attributes
+ return False;
+ end Has_Suitable_Construct;
- begin
- -- Extraction for variable reference markers
+ -------------
+ -- Include --
+ -------------
- if Nkind (Ref) = N_Variable_Reference_Marker then
- Var_Id := Target (Ref);
+ procedure Include (N : Node_Id; Curr : out Node_Id) is
+ begin
+ Start := N;
- -- Extraction for expanded names and identifiers
+ -- The input node is a compilation unit. This terminates the
+ -- search because there are no more lists to inspect and there are
+ -- no more enclosing constructs to climb up to. The transitions
+ -- are:
+ --
+ -- private declarations -> terminate
+ -- visible declarations -> terminate
+ -- statements -> terminate
+ -- declarations -> terminate
- else
- Var_Id := Entity (Ref);
- end if;
+ if Nkind (Parent (Start)) = N_Compilation_Unit then
+ raise ECR_Found;
- -- Obtain the original variable which the reference mentions
+ -- Otherwise the input node is still within some list
- Var_Id := Get_Renamed_Variable (Var_Id);
- Attrs.Unit_Id := Find_Top_Unit (Var_Id);
+ else
+ Curr := Prev (Start);
+ end if;
+ end Include;
- -- At this point certain attributes should always be available
+ -----------------------------------
+ -- Is_OK_Preelaborable_Construct --
+ -----------------------------------
- pragma Assert (Present (Attrs.Unit_Id));
- end Extract_Variable_Reference_Attributes;
+ function Is_OK_Preelaborable_Construct (N : Node_Id) return Boolean is
+ begin
+ -- Assignment statements are acceptable as long as they were
+ -- produced by the ABE mechanism to update elaboration flags.
- --------------------
- -- Find_Code_Unit --
- --------------------
+ if Nkind (N) = N_Assignment_Statement then
+ return Is_Elaboration_Code (N);
- function Find_Code_Unit (N : Node_Or_Entity_Id) return Entity_Id is
- begin
- return Find_Unit_Entity (Unit (Cunit (Get_Code_Unit (N))));
- end Find_Code_Unit;
+ -- Block statements are acceptable even though they directly
+ -- violate preelaborability. The intention is not to penalize
+ -- the early call region when a block contains only preelaborable
+ -- constructs.
+ --
+ -- declare
+ -- Val : constant Integer := 1;
+ -- begin
+ -- pragma Assert (Val = 1);
+ -- null;
+ -- end;
+ --
+ -- Note that the Advancement phase does enter blocks, and will
+ -- detect any non-preelaborable declarations or statements within.
- ----------------------------
- -- Find_Early_Call_Region --
- ----------------------------
+ elsif Nkind (N) = N_Block_Statement then
+ return True;
+ end if;
- function Find_Early_Call_Region
- (Body_Decl : Node_Id;
- Assume_Elab_Body : Boolean := False;
- Skip_Memoization : Boolean := False) return Node_Id
- is
- -- NOTE: The routines within Find_Early_Call_Region are intentionally
- -- unnested to avoid deep indentation of code.
-
- ECR_Found : exception;
- -- This exception is raised when the early call region has been found
-
- Start : Node_Id := Empty;
- -- The start of the early call region. This variable is updated by the
- -- various nested routines. Due to the use of exceptions, the variable
- -- must be global to the nested routines.
-
- -- The algorithm implemented in this routine attempts to find the early
- -- call region of a subprogram body by inspecting constructs in reverse
- -- declarative order, while navigating the tree. The algorithm consists
- -- of an Inspection phase and an Advancement phase. The pseudocode is as
- -- follows:
- --
- -- loop
- -- inspection phase
- -- advancement phase
- -- end loop
- --
- -- The infinite loop is terminated by raising exception ECR_Found. The
- -- algorithm utilizes two pointers, Curr and Start, to represent the
- -- current construct to inspect and the start of the early call region.
- --
- -- IMPORTANT: The algorithm must maintain the following invariant at all
- -- time for it to function properly - a nested construct is entered only
- -- when it contains suitable constructs. This guarantees that leaving a
- -- nested or encapsulating construct functions properly.
- --
- -- The Inspection phase determines whether the current construct is non-
- -- preelaborable, and if it is, the algorithm terminates.
- --
- -- The Advancement phase walks the tree in reverse declarative order,
- -- while entering and leaving nested and encapsulating constructs. It
- -- may also terminate the elaborithm. There are several special cases
- -- of advancement.
- --
- -- 1) General case:
- --
- -- <construct 1>
- -- ...
- -- <construct N-1> <- Curr
- -- <construct N> <- Start
- -- <subprogram body>
- --
- -- In the general case, a declarative or statement list is traversed in
- -- reverse order where Curr is the lead pointer, and Start indicates the
- -- last preelaborable construct.
- --
- -- 2) Entering handled bodies
- --
- -- package body Nested is <- Curr (2.3)
- -- <declarations> <- Curr (2.2)
- -- begin
- -- <statements> <- Curr (2.1)
- -- end Nested;
- -- <construct> <- Start
- --
- -- In this case, the algorithm enters a handled body by starting from
- -- the last statement (2.1), or the last declaration (2.2), or the body
- -- is consumed (2.3) because it is empty and thus preelaborable.
- --
- -- 3) Entering package declarations
- --
- -- package Nested is <- Curr (2.3)
- -- <visible declarations> <- Curr (2.2)
- -- private
- -- <private declarations> <- Curr (2.1)
- -- end Nested;
- -- <construct> <- Start
- --
- -- In this case, the algorithm enters a package declaration by starting
- -- from the last private declaration (2.1), the last visible declaration
- -- (2.2), or the package is consumed (2.3) because it is empty and thus
- -- preelaborable.
- --
- -- 4) Transitioning from list to list of the same construct
- --
- -- Certain constructs have two eligible lists. The algorithm must thus
- -- transition from the second to the first list when the second list is
- -- exhausted.
- --
- -- declare <- Curr (4.2)
- -- <declarations> <- Curr (4.1)
- -- begin
- -- <statements> <- Start
- -- end;
- --
- -- In this case, the algorithm has exhausted the second list (statements
- -- in the example), and continues with the last declaration (4.1) or the
- -- construct is consumed (4.2) because it contains only preelaborable
- -- code.
- --
- -- 5) Transitioning from list to construct
- --
- -- tack body Task is <- Curr (5.1)
- -- <- Curr (Empty)
- -- <construct 1> <- Start
- --
- -- In this case, the algorithm has exhausted a list, Curr is Empty, and
- -- the owner of the list is consumed (5.1).
- --
- -- 6) Transitioning from unit to unit
- --
- -- A package body with a spec subject to pragma Elaborate_Body extends
- -- the possible range of the early call region to the package spec.
- --
- -- package Pack is <- Curr (6.3)
- -- pragma Elaborate_Body; <- Curr (6.2)
- -- <visible declarations> <- Curr (6.2)
- -- private
- -- <private declarations> <- Curr (6.1)
- -- end Pack;
- --
- -- package body Pack is <- Curr, Start
- --
- -- In this case, the algorithm has reached a package body compilation
- -- unit whose spec is subject to pragma Elaborate_Body, or the caller
- -- of the algorithm has specified this behavior. This transition is
- -- equivalent to 3).
- --
- -- 7) Transitioning from unit to termination
- --
- -- Reaching a compilation unit always terminates the algorithm as there
- -- are no more lists to examine. This must take 6) into account.
- --
- -- 8) Transitioning from subunit to stub
- --
- -- package body Pack is separate; <- Curr (8.1)
- --
- -- separate (...)
- -- package body Pack is <- Curr, Start
- --
- -- Reaching a subunit continues the search from the corresponding stub
- -- (8.1).
-
- procedure Advance (Curr : in out Node_Id);
- pragma Inline (Advance);
- -- Update the Curr and Start pointers depending on their location in the
- -- tree to the next eligible construct. This routine raises ECR_Found.
-
- procedure Enter_Handled_Body (Curr : in out Node_Id);
- pragma Inline (Enter_Handled_Body);
- -- Update the Curr and Start pointers to enter a nested handled body if
- -- applicable. This routine raises ECR_Found.
-
- procedure Enter_Package_Declaration (Curr : in out Node_Id);
- pragma Inline (Enter_Package_Declaration);
- -- Update the Curr and Start pointers to enter a nested package spec if
- -- applicable. This routine raises ECR_Found.
-
- function Find_ECR (N : Node_Id) return Node_Id;
- pragma Inline (Find_ECR);
- -- Find an early call region starting from arbitrary node N
-
- function Has_Suitable_Construct (List : List_Id) return Boolean;
- pragma Inline (Has_Suitable_Construct);
- -- Determine whether list List contains at least one suitable construct
- -- for inclusion into an early call region.
-
- procedure Include (N : Node_Id; Curr : out Node_Id);
- pragma Inline (Include);
- -- Update the Curr and Start pointers to include arbitrary construct N
- -- in the early call region. This routine raises ECR_Found.
-
- function Is_OK_Preelaborable_Construct (N : Node_Id) return Boolean;
- pragma Inline (Is_OK_Preelaborable_Construct);
- -- Determine whether arbitrary node N denotes a preelaboration-safe
- -- construct.
-
- function Is_Suitable_Construct (N : Node_Id) return Boolean;
- pragma Inline (Is_Suitable_Construct);
- -- Determine whether arbitrary node N denotes a suitable construct for
- -- inclusion into the early call region.
-
- procedure Transition_Body_Declarations
- (Bod : Node_Id;
- Curr : out Node_Id);
- pragma Inline (Transition_Body_Declarations);
- -- Update the Curr and Start pointers when construct Bod denotes a block
- -- statement or a suitable body. This routine raises ECR_Found.
-
- procedure Transition_Handled_Statements
- (HSS : Node_Id;
- Curr : out Node_Id);
- pragma Inline (Transition_Handled_Statements);
- -- Update the Curr and Start pointers when node HSS denotes a handled
- -- sequence of statements. This routine raises ECR_Found.
-
- procedure Transition_Spec_Declarations
- (Spec : Node_Id;
- Curr : out Node_Id);
- pragma Inline (Transition_Spec_Declarations);
- -- Update the Curr and Start pointers when construct Spec denotes
- -- a concurrent definition or a package spec. This routine raises
- -- ECR_Found.
-
- procedure Transition_Unit (Unit : Node_Id; Curr : out Node_Id);
- pragma Inline (Transition_Unit);
- -- Update the Curr and Start pointers when node Unit denotes a potential
- -- compilation unit. This routine raises ECR_Found.
+ -- Otherwise the construct must be preelaborable. The check must
+ -- take the syntactic and semantic structure of the construct. DO
+ -- NOT use Is_Preelaborable_Construct here.
- -------------
- -- Advance --
- -------------
+ return not Is_Non_Preelaborable_Construct (N);
+ end Is_OK_Preelaborable_Construct;
- procedure Advance (Curr : in out Node_Id) is
- Context : Node_Id;
+ ---------------------------
+ -- Is_Suitable_Construct --
+ ---------------------------
- begin
- -- Curr denotes one of the following cases upon entry into this
- -- routine:
- --
- -- * Empty - There is no current construct when a declarative or a
- -- statement list has been exhausted. This does not necessarily
- -- indicate that the early call region has been computed as it
- -- may still be possible to transition to another list.
- --
- -- * Encapsulator - The current construct encapsulates declarations
- -- and/or statements. This indicates that the early call region
- -- may extend within the nested construct.
- --
- -- * Preelaborable - The current construct is always preelaborable
- -- because Find_ECR would not invoke Advance if this was not the
- -- case.
+ function Is_Suitable_Construct (N : Node_Id) return Boolean is
+ Context : constant Node_Id := Parent (N);
- -- The current construct is an encapsulator or is preelaborable
+ begin
+ -- An internally-generated statement sequence which contains only
+ -- a single null statement is not a suitable construct because it
+ -- is a byproduct of the parser. Such a null statement should be
+ -- excluded from the early call region because it carries the
+ -- source location of the "end" keyword, and may lead to confusing
+ -- diagnistics.
+
+ if Nkind (N) = N_Null_Statement
+ and then not Comes_From_Source (N)
+ and then Present (Context)
+ and then Nkind (Context) = N_Handled_Sequence_Of_Statements
+ then
+ return False;
+ end if;
- if Present (Curr) then
+ -- Otherwise only constructs which correspond to pure Ada
+ -- constructs are considered suitable.
+
+ case Nkind (N) is
+ when N_Call_Marker
+ | N_Freeze_Entity
+ | N_Freeze_Generic_Entity
+ | N_Implicit_Label_Declaration
+ | N_Itype_Reference
+ | N_Pop_Constraint_Error_Label
+ | N_Pop_Program_Error_Label
+ | N_Pop_Storage_Error_Label
+ | N_Push_Constraint_Error_Label
+ | N_Push_Program_Error_Label
+ | N_Push_Storage_Error_Label
+ | N_SCIL_Dispatch_Table_Tag_Init
+ | N_SCIL_Dispatching_Call
+ | N_SCIL_Membership_Test
+ | N_Variable_Reference_Marker
+ =>
+ return False;
- -- Enter encapsulators by inspecting their declarations and/or
- -- statements.
+ when others =>
+ return True;
+ end case;
+ end Is_Suitable_Construct;
- if Nkind_In (Curr, N_Block_Statement, N_Package_Body) then
- Enter_Handled_Body (Curr);
+ ----------------------------------
+ -- Transition_Body_Declarations --
+ ----------------------------------
- elsif Nkind (Curr) = N_Package_Declaration then
- Enter_Package_Declaration (Curr);
+ procedure Transition_Body_Declarations
+ (Bod : Node_Id;
+ Curr : out Node_Id)
+ is
+ Decls : constant List_Id := Declarations (Bod);
- -- Early call regions have a property which can be exploited to
- -- optimize the algorithm.
- --
- -- <preceding subprogram body>
- -- <preelaborable construct 1>
- -- ...
- -- <preelaborable construct N>
- -- <initiating subprogram body>
- --
- -- If a traversal initiated from a subprogram body reaches a
- -- preceding subprogram body, then both bodies share the same
- -- early call region.
- --
- -- The property results in the following desirable effects:
- --
- -- * If the preceding body already has an early call region, then
- -- the initiating body can reuse it. This minimizes the amount
- -- of processing performed by the algorithm.
+ begin
+ -- The search must come from the declarations of the body
+
+ pragma Assert
+ (Is_Non_Empty_List (Decls)
+ and then List_Containing (Start) = Decls);
+
+ -- The search finished inspecting the declarations. The construct
+ -- to inspect is the node which precedes the handled body, unless
+ -- the body is a compilation unit. The transitions are:
--
- -- * If the preceding body lack an early call region, then the
- -- algorithm can compute the early call region, and reuse it
- -- for the initiating body. This processing performs the same
- -- amount of work, but has the beneficial effect of computing
- -- the early call regions of all preceding bodies.
-
- elsif Nkind_In (Curr, N_Entry_Body, N_Subprogram_Body) then
- Start :=
- Find_Early_Call_Region
- (Body_Decl => Curr,
- Assume_Elab_Body => Assume_Elab_Body,
- Skip_Memoization => Skip_Memoization);
+ -- declarations -> upper level
+ -- declarations -> corresponding package spec (Elab_Body)
+ -- declarations -> terminate
- raise ECR_Found;
+ Transition_Unit (Bod, Curr);
+ end Transition_Body_Declarations;
- -- Otherwise current construct is preelaborable. Unpdate the early
- -- call region to include it.
+ -----------------------------------
+ -- Transition_Handled_Statements --
+ -----------------------------------
- else
- Include (Curr, Curr);
- end if;
+ procedure Transition_Handled_Statements
+ (HSS : Node_Id;
+ Curr : out Node_Id)
+ is
+ Bod : constant Node_Id := Parent (HSS);
+ Decls : constant List_Id := Declarations (Bod);
+ Stmts : constant List_Id := Statements (HSS);
- -- Otherwise the current construct is missing, indicating that the
- -- current list has been exhausted. Depending on the context of the
- -- list, several transitions are possible.
+ begin
+ -- The search must come from the statements of certain bodies or
+ -- statements.
- else
- -- The invariant of the algorithm ensures that Curr and Start are
- -- at the same level of nesting at the point of a transition. The
- -- algorithm can determine which list the traversal came from by
- -- examining Start.
+ pragma Assert (Nkind_In (Bod, N_Block_Statement,
+ N_Entry_Body,
+ N_Package_Body,
+ N_Protected_Body,
+ N_Subprogram_Body,
+ N_Task_Body));
- Context := Parent (Start);
+ -- The search must come from the statements of the handled
+ -- sequence.
- -- Attempt the following transitions:
+ pragma Assert
+ (Is_Non_Empty_List (Stmts)
+ and then List_Containing (Start) = Stmts);
+
+ -- The search finished inspecting the statements. The handled body
+ -- has non-empty declarations. The construct to inspect is the
+ -- last declaration. The transitions are:
--
- -- private declarations -> visible declarations
- -- private declarations -> upper level
- -- private declarations -> terminate
- -- visible declarations -> upper level
- -- visible declarations -> terminate
+ -- statements -> declarations
- if Nkind_In (Context, N_Package_Specification,
- N_Protected_Definition,
- N_Task_Definition)
- then
- Transition_Spec_Declarations (Context, Curr);
+ if Has_Suitable_Construct (Decls) then
+ Curr := Last (Decls);
- -- Attempt the following transitions:
+ -- Otherwise the handled body lacks declarations. The construct to
+ -- inspect is the node which precedes the handled body, unless the
+ -- body is a compilation unit. The transitions are:
--
- -- statements -> declarations
-- statements -> upper level
-- statements -> corresponding package spec (Elab_Body)
-- statements -> terminate
- elsif Nkind (Context) = N_Handled_Sequence_Of_Statements then
- Transition_Handled_Statements (Context, Curr);
+ else
+ Transition_Unit (Bod, Curr);
+ end if;
+ end Transition_Handled_Statements;
+
+ ----------------------------------
+ -- Transition_Spec_Declarations --
+ ----------------------------------
+
+ procedure Transition_Spec_Declarations
+ (Spec : Node_Id;
+ Curr : out Node_Id)
+ is
+ Prv_Decls : constant List_Id := Private_Declarations (Spec);
+ Vis_Decls : constant List_Id := Visible_Declarations (Spec);
+
+ begin
+ pragma Assert (Present (Start) and then Is_List_Member (Start));
- -- Attempt the following transitions:
+ -- The search came from the private declarations and finished
+ -- their inspection.
+
+ if Has_Suitable_Construct (Prv_Decls)
+ and then List_Containing (Start) = Prv_Decls
+ then
+ -- The context has non-empty visible declarations. The node to
+ -- inspect is the last visible declaration. The transitions
+ -- are:
+ --
+ -- private declarations -> visible declarations
+
+ if Has_Suitable_Construct (Vis_Decls) then
+ Curr := Last (Vis_Decls);
+
+ -- Otherwise the context lacks visible declarations. The
+ -- construct to inspect is the node which precedes the context
+ -- unless the context is a compilation unit. The transitions
+ -- are:
+ --
+ -- private declarations -> upper level
+ -- private declarations -> terminate
+
+ else
+ Transition_Unit (Parent (Spec), Curr);
+ end if;
+
+ -- The search came from the visible declarations and finished
+ -- their inspections. The construct to inspect is the node which
+ -- precedes the context, unless the context is a compilaton unit.
+ -- The transitions are:
--
- -- declarations -> upper level
- -- declarations -> corresponding package spec (Elab_Body)
- -- declarations -> terminate
+ -- visible declarations -> upper level
+ -- visible declarations -> terminate
- elsif Nkind_In (Context, N_Block_Statement,
- N_Entry_Body,
- N_Package_Body,
- N_Protected_Body,
- N_Subprogram_Body,
- N_Task_Body)
+ elsif Has_Suitable_Construct (Vis_Decls)
+ and then List_Containing (Start) = Vis_Decls
then
- Transition_Body_Declarations (Context, Curr);
+ Transition_Unit (Parent (Spec), Curr);
- -- Otherwise it is not possible to transition. Stop the search
- -- because there are no more declarations or statements to check.
+ -- At this point both declarative lists are empty, but the
+ -- traversal still came from within the spec. This indicates
+ -- that the invariant of the algorithm has been violated.
else
+ pragma Assert (False);
raise ECR_Found;
end if;
- end if;
- end Advance;
+ end Transition_Spec_Declarations;
- --------------------------
- -- Enter_Handled_Body --
- --------------------------
+ ---------------------
+ -- Transition_Unit --
+ ---------------------
- procedure Enter_Handled_Body (Curr : in out Node_Id) is
- Decls : constant List_Id := Declarations (Curr);
- HSS : constant Node_Id := Handled_Statement_Sequence (Curr);
- Stmts : List_Id := No_List;
+ procedure Transition_Unit
+ (Unit : Node_Id;
+ Curr : out Node_Id)
+ is
+ Context : constant Node_Id := Parent (Unit);
- begin
- if Present (HSS) then
- Stmts := Statements (HSS);
- end if;
+ begin
+ -- The unit is a compilation unit. This terminates the search
+ -- because there are no more lists to inspect and there are no
+ -- more enclosing constructs to climb up to.
+
+ if Nkind (Context) = N_Compilation_Unit then
+
+ -- A package body with a corresponding spec subject to pragma
+ -- Elaborate_Body is an exception to the above. The annotation
+ -- allows the search to continue into the package declaration.
+ -- The transitions are:
+ --
+ -- statements -> corresponding package spec (Elab_Body)
+ -- declarations -> corresponding package spec (Elab_Body)
+
+ if Nkind (Unit) = N_Package_Body
+ and then (Assume_Elab_Body
+ or else Has_Pragma_Elaborate_Body
+ (Corresponding_Spec (Unit)))
+ then
+ Curr := Unit_Declaration_Node (Corresponding_Spec (Unit));
+ Enter_Package_Declaration (Curr);
- -- The handled body has a non-empty statement sequence. The construct
- -- to inspect is the last statement.
+ -- Otherwise terminate the search. The transitions are:
+ --
+ -- private declarations -> terminate
+ -- visible declarations -> terminate
+ -- statements -> terminate
+ -- declarations -> terminate
- if Has_Suitable_Construct (Stmts) then
- Curr := Last (Stmts);
+ else
+ raise ECR_Found;
+ end if;
- -- The handled body lacks statements, but has non-empty declarations.
- -- The construct to inspect is the last declaration.
+ -- The unit is a subunit. The construct to inspect is the node
+ -- which precedes the corresponding stub. Update the early call
+ -- region to include the unit.
- elsif Has_Suitable_Construct (Decls) then
- Curr := Last (Decls);
+ elsif Nkind (Context) = N_Subunit then
+ Start := Unit;
+ Curr := Corresponding_Stub (Context);
- -- Otherwise the handled body lacks both declarations and statements.
- -- The construct to inspect is the node which precedes the handled
- -- body. Update the early call region to include the handled body.
+ -- Otherwise the unit is nested. The construct to inspect is the
+ -- node which precedes the unit. Update the early call region to
+ -- include the unit.
- else
- Include (Curr, Curr);
- end if;
- end Enter_Handled_Body;
+ else
+ Include (Unit, Curr);
+ end if;
+ end Transition_Unit;
- -------------------------------
- -- Enter_Package_Declaration --
- -------------------------------
+ -- Local variables
+
+ Body_Id : constant Entity_Id := Unique_Defining_Entity (Body_Decl);
+ Region : Node_Id;
- procedure Enter_Package_Declaration (Curr : in out Node_Id) is
- Pack_Spec : constant Node_Id := Specification (Curr);
- Prv_Decls : constant List_Id := Private_Declarations (Pack_Spec);
- Vis_Decls : constant List_Id := Visible_Declarations (Pack_Spec);
+ -- Start of processing for Find_Early_Call_Region
begin
- -- The package has a non-empty private declarations. The construct to
- -- inspect is the last private declaration.
+ -- The caller demands the start of the early call region without
+ -- saving or retrieving it to/from internal data structures.
- if Has_Suitable_Construct (Prv_Decls) then
- Curr := Last (Prv_Decls);
+ if Skip_Memoization then
+ Region := Find_ECR (Body_Decl);
- -- The package lacks private declarations, but has non-empty visible
- -- declarations. In this case the construct to inspect is the last
- -- visible declaration.
+ -- Default behavior
- elsif Has_Suitable_Construct (Vis_Decls) then
- Curr := Last (Vis_Decls);
+ else
+ -- Check whether the early call region of the subprogram body is
+ -- available.
- -- Otherwise the package lacks any declarations. The construct to
- -- inspect is the node which precedes the package. Update the early
- -- call region to include the package declaration.
+ Region := Early_Call_Region (Body_Id);
- else
- Include (Curr, Curr);
+ if No (Region) then
+ Region := Find_ECR (Body_Decl);
+
+ -- Associate the early call region with the subprogram body in
+ -- case other scenarios need it.
+
+ Set_Early_Call_Region (Body_Id, Region);
+ end if;
end if;
- end Enter_Package_Declaration;
- --------------
- -- Find_ECR --
- --------------
+ -- A subprogram body must always have an early call region
+
+ pragma Assert (Present (Region));
- function Find_ECR (N : Node_Id) return Node_Id is
- Curr : Node_Id;
+ return Region;
+ end Find_Early_Call_Region;
+ --------------------------------------------
+ -- Initialize_Early_Call_Region_Processor --
+ --------------------------------------------
+
+ procedure Initialize_Early_Call_Region_Processor is
begin
- -- The early call region starts at N
+ Early_Call_Regions_Map := ECR_Map.Create (100);
+ end Initialize_Early_Call_Region_Processor;
- Curr := Prev (N);
- Start := N;
+ ---------------------------
+ -- Set_Early_Call_Region --
+ ---------------------------
- -- Inspect each node in reverse declarative order while going in and
- -- out of nested and enclosing constructs. Note that the only way to
- -- terminate this infinite loop is to raise exception ECR_Found.
+ procedure Set_Early_Call_Region (Body_Id : Entity_Id; Start : Node_Id) is
+ pragma Assert (Present (Body_Id));
+ pragma Assert (Present (Start));
- loop
- -- The current construct is not preelaboration-safe. Terminate the
- -- traversal.
+ begin
+ ECR_Map.Put (Early_Call_Regions_Map, Body_Id, Start);
+ end Set_Early_Call_Region;
+ end Early_Call_Region_Processor;
- if Present (Curr)
- and then not Is_OK_Preelaborable_Construct (Curr)
- then
- raise ECR_Found;
+ ----------------------
+ -- Elaborated_Units --
+ ----------------------
+
+ package body Elaborated_Units is
+
+ -----------
+ -- Types --
+ -----------
+
+ -- The following type idenfities the elaboration attributes of a unit
+
+ type Elaboration_Attributes_Id is new Natural;
+
+ No_Elaboration_Attributes : constant Elaboration_Attributes_Id :=
+ Elaboration_Attributes_Id'First;
+ First_Elaboration_Attributes : constant Elaboration_Attributes_Id :=
+ No_Elaboration_Attributes + 1;
+
+ -- The following type represents the elaboration attributes of a unit
+
+ type Elaboration_Attributes_Record is record
+ Elab_Pragma : Node_Id := Empty;
+ -- This attribute denotes a source Elaborate or Elaborate_All pragma
+ -- which guarantees the prior elaboration of some unit with respect
+ -- to the main unit. The pragma may come from the following contexts:
+ --
+ -- * The main unit
+ -- * The spec of the main unit (if applicable)
+ -- * Any parent spec of the main unit (if applicable)
+ -- * Any parent subunit of the main unit (if applicable)
+ --
+ -- The attribute remains Empty if no such pragma is available. Source
+ -- pragmas play a role in satisfying SPARK elaboration requirements.
+
+ With_Clause : Node_Id := Empty;
+ -- This attribute denotes an internally-generated or a source with
+ -- clause for some unit withed by the main unit. With clauses carry
+ -- flags which represent implicit Elaborate or Elaborate_All pragmas.
+ -- These clauses play a role in supplying elaboration dependencies to
+ -- binde.
+ end record;
+
+ ---------------------
+ -- Data structures --
+ ---------------------
+
+ -- The following table stores all elaboration attributes
+
+ package Elaboration_Attributes is new Table.Table
+ (Table_Index_Type => Elaboration_Attributes_Id,
+ Table_Component_Type => Elaboration_Attributes_Record,
+ Table_Low_Bound => First_Elaboration_Attributes,
+ Table_Initial => 250,
+ Table_Increment => 200,
+ Table_Name => "Elaboration_Attributes");
+
+ procedure Destroy (EA_Id : in out Elaboration_Attributes_Id);
+ -- Destroy elaboration attributes EA_Id
+
+ package UA_Map is new Dynamic_Hash_Tables
+ (Key_Type => Entity_Id,
+ Value_Type => Elaboration_Attributes_Id,
+ No_Value => No_Elaboration_Attributes,
+ Expansion_Threshold => 1.5,
+ Expansion_Factor => 2,
+ Compression_Threshold => 0.3,
+ Compression_Factor => 2,
+ "=" => "=",
+ Destroy_Value => Destroy,
+ Hash => Hash);
+
+ -- The following map relates an elaboration attributes of a unit to the
+ -- unit.
+
+ Unit_To_Attributes_Map : UA_Map.Dynamic_Hash_Table :=
+ UA_Map.Create (250);
+
+ ------------------
+ -- Constructors --
+ ------------------
+
+ function Elaboration_Attributes_Of
+ (Unit_Id : Entity_Id) return Elaboration_Attributes_Id;
+ pragma Inline (Elaboration_Attributes_Of);
+ -- Obtain the elaboration attributes of unit Unit_Id
+
+ -----------------------
+ -- Local subprograms --
+ -----------------------
+
+ function Elab_Pragma (EA_Id : Elaboration_Attributes_Id) return Node_Id;
+ pragma Inline (Elab_Pragma);
+ -- Obtain the Elaborate[_All] pragma of elaboration attributes EA_Id
+
+ procedure Ensure_Prior_Elaboration_Dynamic
+ (N : Node_Id;
+ Unit_Id : Entity_Id;
+ Prag_Nam : Name_Id;
+ In_State : Processing_In_State);
+ pragma Inline (Ensure_Prior_Elaboration_Dynamic);
+ -- Guarantee the elaboration of unit Unit_Id with respect to the main
+ -- unit by suggesting the use of Elaborate[_All] with name Prag_Nam. N
+ -- denotes the related scenario. In_State is the current state of the
+ -- Processing phase.
+
+ procedure Ensure_Prior_Elaboration_Static
+ (N : Node_Id;
+ Unit_Id : Entity_Id;
+ Prag_Nam : Name_Id;
+ In_State : Processing_In_State);
+ pragma Inline (Ensure_Prior_Elaboration_Static);
+ -- Guarantee the elaboration of unit Unit_Id with respect to the main
+ -- unit by installing an implicit Elaborate[_All] pragma with name
+ -- Prag_Nam. N denotes the related scenario. In_State is the current
+ -- state of the Processing phase.
+
+ function Present (EA_Id : Elaboration_Attributes_Id) return Boolean;
+ pragma Inline (Present);
+ -- Determine whether elaboration attributes UA_Id exist
+
+ procedure Set_Elab_Pragma
+ (EA_Id : Elaboration_Attributes_Id;
+ Prag : Node_Id);
+ pragma Inline (Set_Elab_Pragma);
+ -- Set the Elaborate[_All] pragma of elaboration attributes EA_Id to
+ -- Prag.
+
+ procedure Set_With_Clause
+ (EA_Id : Elaboration_Attributes_Id;
+ Clause : Node_Id);
+ pragma Inline (Set_With_Clause);
+ -- Set the with clause of elaboration attributes EA_Id to Clause
+
+ function With_Clause (EA_Id : Elaboration_Attributes_Id) return Node_Id;
+ pragma Inline (With_Clause);
+ -- Obtain the implicit or source with clause of elaboration attributes
+ -- EA_Id.
+
+ ------------------------------
+ -- Collect_Elaborated_Units --
+ ------------------------------
+
+ procedure Collect_Elaborated_Units is
+ procedure Add_Pragma (Prag : Node_Id);
+ pragma Inline (Add_Pragma);
+ -- Determine whether pragma Prag denotes a legal Elaborate[_All]
+ -- pragma. If this is the case, add the related unit to the context.
+ -- For pragma Elaborate_All, include recursively all units withed by
+ -- the related unit.
+
+ procedure Add_Unit
+ (Unit_Id : Entity_Id;
+ Prag : Node_Id;
+ Full_Context : Boolean);
+ pragma Inline (Add_Unit);
+ -- Add unit Unit_Id to the elaboration context. Prag denotes the
+ -- pragma which prompted the inclusion of the unit to the context.
+ -- If flag Full_Context is set, examine the nonlimited clauses of
+ -- unit Unit_Id and add each withed unit to the context.
+
+ procedure Find_Elaboration_Context (Comp_Unit : Node_Id);
+ pragma Inline (Find_Elaboration_Context);
+ -- Examine the context items of compilation unit Comp_Unit for
+ -- suitable elaboration-related pragmas and add all related units
+ -- to the context.
+
+ ----------------
+ -- Add_Pragma --
+ ----------------
+
+ procedure Add_Pragma (Prag : Node_Id) is
+ Prag_Args : constant List_Id :=
+ Pragma_Argument_Associations (Prag);
+ Prag_Nam : constant Name_Id := Pragma_Name (Prag);
+ Unit_Arg : Node_Id;
+
+ begin
+ -- Nothing to do if the pragma is not related to elaboration
+
+ if not Nam_In (Prag_Nam, Name_Elaborate, Name_Elaborate_All) then
+ return;
+
+ -- Nothing to do when the pragma is illegal
+
+ elsif Error_Posted (Prag) then
+ return;
end if;
- -- Advance to the next suitable construct. This may terminate the
- -- traversal by raising ECR_Found.
+ Unit_Arg := Get_Pragma_Arg (First (Prag_Args));
- Advance (Curr);
- end loop;
+ -- The argument of the pragma may appear in package.package form
- exception
- when ECR_Found =>
- return Start;
- end Find_ECR;
+ if Nkind (Unit_Arg) = N_Selected_Component then
+ Unit_Arg := Selector_Name (Unit_Arg);
+ end if;
- ----------------------------
- -- Has_Suitable_Construct --
- ----------------------------
+ Add_Unit
+ (Unit_Id => Entity (Unit_Arg),
+ Prag => Prag,
+ Full_Context => Prag_Nam = Name_Elaborate_All);
+ end Add_Pragma;
- function Has_Suitable_Construct (List : List_Id) return Boolean is
- Item : Node_Id;
+ --------------
+ -- Add_Unit --
+ --------------
- begin
- -- Examine the list in reverse declarative order, looking for a
- -- suitable construct.
+ procedure Add_Unit
+ (Unit_Id : Entity_Id;
+ Prag : Node_Id;
+ Full_Context : Boolean)
+ is
+ Clause : Node_Id;
+ EA_Id : Elaboration_Attributes_Id;
+ Unit_Prag : Node_Id;
- if Present (List) then
- Item := Last (List);
- while Present (Item) loop
- if Is_Suitable_Construct (Item) then
- return True;
+ begin
+ -- Nothing to do when some previous error left a with clause or a
+ -- pragma in a bad state.
+
+ if No (Unit_Id) then
+ return;
+ end if;
+
+ EA_Id := Elaboration_Attributes_Of (Unit_Id);
+ Unit_Prag := Elab_Pragma (EA_Id);
+
+ -- The unit is already included in the context by means of pragma
+ -- Elaborate[_All].
+
+ if Present (Unit_Prag) then
+
+ -- Upgrade an existing pragma Elaborate when the unit is
+ -- subject to Elaborate_All because the new pragma covers a
+ -- larger set of units.
+
+ if Pragma_Name (Unit_Prag) = Name_Elaborate
+ and then Pragma_Name (Prag) = Name_Elaborate_All
+ then
+ Set_Elab_Pragma (EA_Id, Prag);
+
+ -- Otherwise the unit retains its existing pragma and does not
+ -- need to be included in the context again.
+
+ else
+ return;
end if;
- Prev (Item);
- end loop;
- end if;
+ -- Otherwise the current unit is not included in the context
- return False;
- end Has_Suitable_Construct;
+ else
+ Set_Elab_Pragma (EA_Id, Prag);
+ end if;
- -------------
- -- Include --
- -------------
+ -- Includes all units withed by the current one when computing the
+ -- full context.
- procedure Include (N : Node_Id; Curr : out Node_Id) is
- begin
- Start := N;
+ if Full_Context then
- -- The input node is a compilation unit. This terminates the search
- -- because there are no more lists to inspect and there are no more
- -- enclosing constructs to climb up to. The transitions are:
- --
- -- private declarations -> terminate
- -- visible declarations -> terminate
- -- statements -> terminate
- -- declarations -> terminate
+ -- Process all nonlimited with clauses found in the context of
+ -- the current unit. Note that limited clauses do not impose an
+ -- elaboration order.
- if Nkind (Parent (Start)) = N_Compilation_Unit then
- raise ECR_Found;
+ Clause := First (Context_Items (Compilation_Unit (Unit_Id)));
+ while Present (Clause) loop
+ if Nkind (Clause) = N_With_Clause
+ and then not Error_Posted (Clause)
+ and then not Limited_Present (Clause)
+ then
+ Add_Unit
+ (Unit_Id => Entity (Name (Clause)),
+ Prag => Prag,
+ Full_Context => Full_Context);
+ end if;
- -- Otherwise the input node is still within some list
+ Next (Clause);
+ end loop;
+ end if;
+ end Add_Unit;
- else
- Curr := Prev (Start);
- end if;
- end Include;
+ ------------------------------
+ -- Find_Elaboration_Context --
+ ------------------------------
- -----------------------------------
- -- Is_OK_Preelaborable_Construct --
- -----------------------------------
+ procedure Find_Elaboration_Context (Comp_Unit : Node_Id) is
+ pragma Assert (Nkind (Comp_Unit) = N_Compilation_Unit);
- function Is_OK_Preelaborable_Construct (N : Node_Id) return Boolean is
- begin
- -- Assignment statements are acceptable as long as they were produced
- -- by the ABE mechanism to update elaboration flags.
+ Prag : Node_Id;
- if Nkind (N) = N_Assignment_Statement then
- return Is_Elaboration_Code (N);
+ begin
+ -- Process all elaboration-related pragmas found in the context of
+ -- the compilation unit.
+
+ Prag := First (Context_Items (Comp_Unit));
+ while Present (Prag) loop
+ if Nkind (Prag) = N_Pragma then
+ Add_Pragma (Prag);
+ end if;
- -- Block statements are acceptable even though they directly violate
- -- preelaborability. The intention is not to penalize the early call
- -- region when a block contains only preelaborable constructs.
+ Next (Prag);
+ end loop;
+ end Find_Elaboration_Context;
+
+ -- Local variables
+
+ Par_Id : Entity_Id;
+ Unit_Id : Node_Id;
+
+ -- Start of processing for Collect_Elaborated_Units
+
+ begin
+ -- Perform a traversal to examines the context of the main unit. The
+ -- traversal performs the following jumps:
--
- -- declare
- -- Val : constant Integer := 1;
- -- begin
- -- pragma Assert (Val = 1);
- -- null;
- -- end;
+ -- subunit -> parent subunit
+ -- parent subunit -> body
+ -- body -> spec
+ -- spec -> parent spec
+ -- parent spec -> grandparent spec and so on
--
- -- Note that the Advancement phase does enter blocks, and will detect
- -- any non-preelaborable declarations or statements within.
+ -- The traversal relies on units rather than scopes because the scope
+ -- of a subunit is some spec, while this traversal must process the
+ -- body as well. Given that protected and task bodies can also be
+ -- subunits, this complicates the scope approach even further.
- elsif Nkind (N) = N_Block_Statement then
- return True;
- end if;
+ Unit_Id := Unit (Cunit (Main_Unit));
- -- Otherwise the construct must be preelaborable. The check must take
- -- the syntactic and semantic structure of the construct. DO NOT use
- -- Is_Preelaborable_Construct here.
+ -- Perform the following traversals when the main unit is a subunit
+ --
+ -- subunit -> parent subunit
+ -- parent subunit -> body
- return not Is_Non_Preelaborable_Construct (N);
- end Is_OK_Preelaborable_Construct;
+ while Present (Unit_Id) and then Nkind (Unit_Id) = N_Subunit loop
+ Find_Elaboration_Context (Parent (Unit_Id));
- ---------------------------
- -- Is_Suitable_Construct --
- ---------------------------
+ -- Continue the traversal by going to the unit which contains the
+ -- corresponding stub.
- function Is_Suitable_Construct (N : Node_Id) return Boolean is
- Context : constant Node_Id := Parent (N);
+ if Present (Corresponding_Stub (Unit_Id)) then
+ Unit_Id :=
+ Unit (Cunit (Get_Source_Unit (Corresponding_Stub (Unit_Id))));
- begin
- -- An internally-generated statement sequence which contains only a
- -- single null statement is not a suitable construct because it is a
- -- byproduct of the parser. Such a null statement should be excluded
- -- from the early call region because it carries the source location
- -- of the "end" keyword, and may lead to confusing diagnistics.
+ -- Otherwise the subunit may be erroneous or left in a bad state
+
+ else
+ exit;
+ end if;
+ end loop;
+
+ -- Perform the following traversal now that subunits have been taken
+ -- care of, or the main unit is a body.
+ --
+ -- body -> spec
- if Nkind (N) = N_Null_Statement
- and then not Comes_From_Source (N)
- and then Present (Context)
- and then Nkind (Context) = N_Handled_Sequence_Of_Statements
+ if Present (Unit_Id)
+ and then Nkind_In (Unit_Id, N_Package_Body, N_Subprogram_Body)
then
- return False;
+ Find_Elaboration_Context (Parent (Unit_Id));
+
+ -- Continue the traversal by going to the unit which contains the
+ -- corresponding spec.
+
+ if Present (Corresponding_Spec (Unit_Id)) then
+ Unit_Id :=
+ Unit (Cunit (Get_Source_Unit (Corresponding_Spec (Unit_Id))));
+ end if;
end if;
- -- Otherwise only constructs which correspond to pure Ada constructs
- -- are considered suitable.
+ -- Perform the following traversals now that the body has been taken
+ -- care of, or the main unit is a spec.
+ --
+ -- spec -> parent spec
+ -- parent spec -> grandparent spec and so on
+
+ if Present (Unit_Id)
+ and then Nkind_In (Unit_Id, N_Generic_Package_Declaration,
+ N_Generic_Subprogram_Declaration,
+ N_Package_Declaration,
+ N_Subprogram_Declaration)
+ then
+ Find_Elaboration_Context (Parent (Unit_Id));
- case Nkind (N) is
- when N_Call_Marker
- | N_Freeze_Entity
- | N_Freeze_Generic_Entity
- | N_Implicit_Label_Declaration
- | N_Itype_Reference
- | N_Pop_Constraint_Error_Label
- | N_Pop_Program_Error_Label
- | N_Pop_Storage_Error_Label
- | N_Push_Constraint_Error_Label
- | N_Push_Program_Error_Label
- | N_Push_Storage_Error_Label
- | N_SCIL_Dispatch_Table_Tag_Init
- | N_SCIL_Dispatching_Call
- | N_SCIL_Membership_Test
- | N_Variable_Reference_Marker
- =>
- return False;
+ -- Process a potential chain of parent units which ends with the
+ -- main unit spec. The traversal can now safely rely on the scope
+ -- chain.
- when others =>
- return True;
- end case;
- end Is_Suitable_Construct;
+ Par_Id := Scope (Defining_Entity (Unit_Id));
+ while Present (Par_Id) and then Par_Id /= Standard_Standard loop
+ Find_Elaboration_Context (Compilation_Unit (Par_Id));
- ----------------------------------
- -- Transition_Body_Declarations --
- ----------------------------------
+ Par_Id := Scope (Par_Id);
+ end loop;
+ end if;
+ end Collect_Elaborated_Units;
- procedure Transition_Body_Declarations
- (Bod : Node_Id;
- Curr : out Node_Id)
+ -------------
+ -- Destroy --
+ -------------
+
+ procedure Destroy (EA_Id : in out Elaboration_Attributes_Id) is
+ pragma Unreferenced (EA_Id);
+ begin
+ null;
+ end Destroy;
+
+ -----------------
+ -- Elab_Pragma --
+ -----------------
+
+ function Elab_Pragma
+ (EA_Id : Elaboration_Attributes_Id) return Node_Id
is
- Decls : constant List_Id := Declarations (Bod);
+ pragma Assert (Present (EA_Id));
+ begin
+ return Elaboration_Attributes.Table (EA_Id).Elab_Pragma;
+ end Elab_Pragma;
+
+ -------------------------------
+ -- Elaboration_Attributes_Of --
+ -------------------------------
+
+ function Elaboration_Attributes_Of
+ (Unit_Id : Entity_Id) return Elaboration_Attributes_Id
+ is
+ EA_Id : Elaboration_Attributes_Id;
begin
- -- The search must come from the declarations of the body
+ EA_Id := UA_Map.Get (Unit_To_Attributes_Map, Unit_Id);
- pragma Assert
- (Is_Non_Empty_List (Decls)
- and then List_Containing (Start) = Decls);
+ -- The unit lacks elaboration attributes. This indicates that the
+ -- unit is encountered for the first time. Create the elaboration
+ -- attributes for it.
- -- The search finished inspecting the declarations. The construct
- -- to inspect is the node which precedes the handled body, unless
- -- the body is a compilation unit. The transitions are:
- --
- -- declarations -> upper level
- -- declarations -> corresponding package spec (Elab_Body)
- -- declarations -> terminate
+ if not Present (EA_Id) then
+ Elaboration_Attributes.Append
+ ((Elab_Pragma => Empty,
+ With_Clause => Empty));
+ EA_Id := Elaboration_Attributes.Last;
- Transition_Unit (Bod, Curr);
- end Transition_Body_Declarations;
+ -- Associate the elaboration attributes with the unit
- -----------------------------------
- -- Transition_Handled_Statements --
- -----------------------------------
+ UA_Map.Put (Unit_To_Attributes_Map, Unit_Id, EA_Id);
+ end if;
+
+ pragma Assert (Present (EA_Id));
+
+ return EA_Id;
+ end Elaboration_Attributes_Of;
- procedure Transition_Handled_Statements
- (HSS : Node_Id;
- Curr : out Node_Id)
+ ------------------------------
+ -- Ensure_Prior_Elaboration --
+ ------------------------------
+
+ procedure Ensure_Prior_Elaboration
+ (N : Node_Id;
+ Unit_Id : Entity_Id;
+ Prag_Nam : Name_Id;
+ In_State : Processing_In_State)
is
- Bod : constant Node_Id := Parent (HSS);
- Decls : constant List_Id := Declarations (Bod);
- Stmts : constant List_Id := Statements (HSS);
+ pragma Assert (Nam_In (Prag_Nam, Name_Elaborate, Name_Elaborate_All));
begin
- -- The search must come from the statements of certain bodies or
- -- statements.
+ -- Nothing to do when the need for prior elaboration came from a
+ -- partial finalization routine which occurs in an initialization
+ -- context. This behaviour parallels that of the old ABE mechanism.
- pragma Assert (Nkind_In (Bod, N_Block_Statement,
- N_Entry_Body,
- N_Package_Body,
- N_Protected_Body,
- N_Subprogram_Body,
- N_Task_Body));
+ if In_State.Within_Partial_Finalization then
+ return;
- -- The search must come from the statements of the handled sequence
+ -- Nothing to do when the need for prior elaboration came from a task
+ -- body and switch -gnatd.y (disable implicit pragma Elaborate_All on
+ -- task bodies) is in effect.
- pragma Assert
- (Is_Non_Empty_List (Stmts)
- and then List_Containing (Start) = Stmts);
+ elsif Debug_Flag_Dot_Y and then In_State.Within_Task_Body then
+ return;
- -- The search finished inspecting the statements. The handled body
- -- has non-empty declarations. The construct to inspect is the last
- -- declaration. The transitions are:
+ -- Nothing to do when the unit is elaborated prior to the main unit.
+ -- This check must also consider the following cases:
+ --
+ -- * No check is made against the context of the main unit because
+ -- this is specific to the elaboration model in effect and requires
+ -- custom handling (see Ensure_xxx_Prior_Elaboration).
+ --
+ -- * Unit_Id is subject to pragma Elaborate_Body. An implicit pragma
+ -- Elaborate[_All] MUST be generated even though Unit_Id is always
+ -- elaborated prior to the main unit. This conservative strategy
+ -- ensures that other units withed by Unit_Id will not lead to an
+ -- ABE.
+ --
+ -- package A is package body A is
+ -- procedure ABE; procedure ABE is ... end ABE;
+ -- end A; end A;
+ --
+ -- with A;
+ -- package B is package body B is
+ -- pragma Elaborate_Body; procedure Proc is
+ -- begin
+ -- procedure Proc; A.ABE;
+ -- package B; end Proc;
+ -- end B;
--
- -- statements -> declarations
+ -- with B;
+ -- package C is package body C is
+ -- ... ...
+ -- end C; begin
+ -- B.Proc;
+ -- end C;
+ --
+ -- In the example above, the elaboration of C invokes B.Proc. B is
+ -- subject to pragma Elaborate_Body. If no pragma Elaborate[_All]
+ -- is gnerated for B in C, then the following elaboratio order will
+ -- lead to an ABE:
+ --
+ -- spec of A elaborated
+ -- spec of B elaborated
+ -- body of B elaborated
+ -- spec of C elaborated
+ -- body of C elaborated <-- calls B.Proc which calls A.ABE
+ -- body of A elaborated <-- problem
+ --
+ -- The generation of an implicit pragma Elaborate_All (B) ensures
+ -- that the elaboration order mechanism will not pick the above
+ -- order.
+ --
+ -- An implicit Elaborate is NOT generated when the unit is subject
+ -- to Elaborate_Body because both pragmas have the same effect.
+ --
+ -- * Unit_Id is the main unit. An implicit pragma Elaborate[_All]
+ -- MUST NOT be generated in this case because a unit cannot depend
+ -- on its own elaboration. This case is therefore treated as valid
+ -- prior elaboration.
+
+ elsif Has_Prior_Elaboration
+ (Unit_Id => Unit_Id,
+ Same_Unit_OK => True,
+ Elab_Body_OK => Prag_Nam = Name_Elaborate)
+ then
+ return;
+ end if;
- if Has_Suitable_Construct (Decls) then
- Curr := Last (Decls);
+ -- Suggest the use of pragma Prag_Nam when the dynamic model is in
+ -- effect.
- -- Otherwise the handled body lacks declarations. The construct to
- -- inspect is the node which precedes the handled body, unless the
- -- body is a compilation unit. The transitions are:
- --
- -- statements -> upper level
- -- statements -> corresponding package spec (Elab_Body)
- -- statements -> terminate
+ if Dynamic_Elaboration_Checks then
+ Ensure_Prior_Elaboration_Dynamic
+ (N => N,
+ Unit_Id => Unit_Id,
+ Prag_Nam => Prag_Nam,
+ In_State => In_State);
+
+ -- Install an implicit pragma Prag_Nam when the static model is in
+ -- effect.
else
- Transition_Unit (Bod, Curr);
+ pragma Assert (Static_Elaboration_Checks);
+
+ Ensure_Prior_Elaboration_Static
+ (N => N,
+ Unit_Id => Unit_Id,
+ Prag_Nam => Prag_Nam,
+ In_State => In_State);
end if;
- end Transition_Handled_Statements;
+ end Ensure_Prior_Elaboration;
- ----------------------------------
- -- Transition_Spec_Declarations --
- ----------------------------------
+ --------------------------------------
+ -- Ensure_Prior_Elaboration_Dynamic --
+ --------------------------------------
- procedure Transition_Spec_Declarations
- (Spec : Node_Id;
- Curr : out Node_Id)
+ procedure Ensure_Prior_Elaboration_Dynamic
+ (N : Node_Id;
+ Unit_Id : Entity_Id;
+ Prag_Nam : Name_Id;
+ In_State : Processing_In_State)
is
- Prv_Decls : constant List_Id := Private_Declarations (Spec);
- Vis_Decls : constant List_Id := Visible_Declarations (Spec);
+ procedure Info_Missing_Pragma;
+ pragma Inline (Info_Missing_Pragma);
+ -- Output information concerning missing Elaborate or Elaborate_All
+ -- pragma with name Prag_Nam for scenario N, which would ensure the
+ -- prior elaboration of Unit_Id.
- begin
- pragma Assert (Present (Start) and then Is_List_Member (Start));
+ -------------------------
+ -- Info_Missing_Pragma --
+ -------------------------
- -- The search came from the private declarations and finished their
- -- inspection.
+ procedure Info_Missing_Pragma is
+ begin
+ -- Internal units are ignored as they cause unnecessary noise
- if Has_Suitable_Construct (Prv_Decls)
- and then List_Containing (Start) = Prv_Decls
- then
- -- The context has non-empty visible declarations. The node to
- -- inspect is the last visible declaration. The transitions are:
- --
- -- private declarations -> visible declarations
+ if not In_Internal_Unit (Unit_Id) then
- if Has_Suitable_Construct (Vis_Decls) then
- Curr := Last (Vis_Decls);
+ -- The name of the unit subjected to the elaboration pragma is
+ -- fully qualified to improve the clarity of the info message.
- -- Otherwise the context lacks visible declarations. The construct
- -- to inspect is the node which precedes the context unless the
- -- context is a compilation unit. The transitions are:
- --
- -- private declarations -> upper level
- -- private declarations -> terminate
+ Error_Msg_Name_1 := Prag_Nam;
+ Error_Msg_Qual_Level := Nat'Last;
- else
- Transition_Unit (Parent (Spec), Curr);
+ Error_Msg_NE ("info: missing pragma % for unit &", N, Unit_Id);
+ Error_Msg_Qual_Level := 0;
end if;
+ end Info_Missing_Pragma;
- -- The search came from the visible declarations and finished their
- -- inspections. The construct to inspect is the node which precedes
- -- the context, unless the context is a compilaton unit. The
- -- transitions are:
- --
- -- visible declarations -> upper level
- -- visible declarations -> terminate
+ -- Local variables
- elsif Has_Suitable_Construct (Vis_Decls)
- and then List_Containing (Start) = Vis_Decls
- then
- Transition_Unit (Parent (Spec), Curr);
+ EA_Id : constant Elaboration_Attributes_Id :=
+ Elaboration_Attributes_Of (Unit_Id);
+ N_Lvl : Enclosing_Level_Kind;
+ N_Rep : Scenario_Rep_Id;
- -- At this point both declarative lists are empty, but the traversal
- -- still came from within the spec. This indicates that the invariant
- -- of the algorithm has been violated.
+ -- Start of processing for Ensure_Prior_Elaboration_Dynamic
- else
- pragma Assert (False);
- raise ECR_Found;
+ begin
+ -- Nothing to do when the unit is guaranteed prior elaboration by
+ -- means of a source Elaborate[_All] pragma.
+
+ if Present (Elab_Pragma (EA_Id)) then
+ return;
end if;
- end Transition_Spec_Declarations;
- ---------------------
- -- Transition_Unit --
- ---------------------
+ -- Output extra information on a missing Elaborate[_All] pragma when
+ -- switch -gnatel (info messages on implicit Elaborate[_All] pragmas
+ -- is in effect.
- procedure Transition_Unit
- (Unit : Node_Id;
- Curr : out Node_Id)
- is
- Context : constant Node_Id := Parent (Unit);
+ if Elab_Info_Messages
+ and then not In_State.Suppress_Info_Messages
+ then
+ N_Rep := Scenario_Representation_Of (N, In_State);
+ N_Lvl := Level (N_Rep);
- begin
- -- The unit is a compilation unit. This terminates the search because
- -- there are no more lists to inspect and there are no more enclosing
- -- constructs to climb up to.
+ -- Declaration-level scenario
- if Nkind (Context) = N_Compilation_Unit then
+ if (Is_Suitable_Call (N) or else Is_Suitable_Instantiation (N))
+ and then N_Lvl = Declaration_Level
+ then
+ null;
- -- A package body with a corresponding spec subject to pragma
- -- Elaborate_Body is an exception to the above. The annotation
- -- allows the search to continue into the package declaration.
- -- The transitions are:
- --
- -- statements -> corresponding package spec (Elab_Body)
- -- declarations -> corresponding package spec (Elab_Body)
+ -- Library-level scenario
- if Nkind (Unit) = N_Package_Body
- and then (Assume_Elab_Body
- or else Has_Pragma_Elaborate_Body
- (Corresponding_Spec (Unit)))
- then
- Curr := Unit_Declaration_Node (Corresponding_Spec (Unit));
- Enter_Package_Declaration (Curr);
+ elsif N_Lvl in Library_Level then
+ null;
- -- Otherwise terminate the search. The transitions are:
- --
- -- private declarations -> terminate
- -- visible declarations -> terminate
- -- statements -> terminate
- -- declarations -> terminate
+ -- Instantiation library-level scenario
+
+ elsif N_Lvl = Instantiation_Level then
+ null;
+
+ -- Otherwise the scenario does not appear at the proper level
else
- raise ECR_Found;
+ return;
end if;
- -- The unit is a subunit. The construct to inspect is the node which
- -- precedes the corresponding stub. Update the early call region to
- -- include the unit.
+ Info_Missing_Pragma;
+ end if;
+ end Ensure_Prior_Elaboration_Dynamic;
- elsif Nkind (Context) = N_Subunit then
- Start := Unit;
- Curr := Corresponding_Stub (Context);
+ -------------------------------------
+ -- Ensure_Prior_Elaboration_Static --
+ -------------------------------------
- -- Otherwise the unit is nested. The construct to inspect is the node
- -- which precedes the unit. Update the early call region to include
- -- the unit.
+ procedure Ensure_Prior_Elaboration_Static
+ (N : Node_Id;
+ Unit_Id : Entity_Id;
+ Prag_Nam : Name_Id;
+ In_State : Processing_In_State)
+ is
+ function Find_With_Clause
+ (Items : List_Id;
+ Withed_Id : Entity_Id) return Node_Id;
+ pragma Inline (Find_With_Clause);
+ -- Find a nonlimited with clause in the list of context items Items
+ -- that withs unit Withed_Id. Return Empty if no such clause exists.
+
+ procedure Info_Implicit_Pragma;
+ pragma Inline (Info_Implicit_Pragma);
+ -- Output information concerning an implicitly generated Elaborate
+ -- or Elaborate_All pragma with name Prag_Nam for scenario N which
+ -- ensures the prior elaboration of unit Unit_Id.
+
+ ----------------------
+ -- Find_With_Clause --
+ ----------------------
+
+ function Find_With_Clause
+ (Items : List_Id;
+ Withed_Id : Entity_Id) return Node_Id
+ is
+ Item : Node_Id;
- else
- Include (Unit, Curr);
- end if;
- end Transition_Unit;
+ begin
+ -- Examine the context clauses looking for a suitable with. Note
+ -- that limited clauses do not affect the elaboration order.
- -- Local variables
+ Item := First (Items);
+ while Present (Item) loop
+ if Nkind (Item) = N_With_Clause
+ and then not Error_Posted (Item)
+ and then not Limited_Present (Item)
+ and then Entity (Name (Item)) = Withed_Id
+ then
+ return Item;
+ end if;
- Body_Id : constant Entity_Id := Defining_Entity (Body_Decl);
- Region : Node_Id;
+ Next (Item);
+ end loop;
- -- Start of processing for Find_Early_Call_Region
+ return Empty;
+ end Find_With_Clause;
- begin
- -- The caller demands the start of the early call region without saving
- -- or retrieving it to/from internal data structures.
+ --------------------------
+ -- Info_Implicit_Pragma --
+ --------------------------
- if Skip_Memoization then
- Region := Find_ECR (Body_Decl);
+ procedure Info_Implicit_Pragma is
+ begin
+ -- Internal units are ignored as they cause unnecessary noise
- -- Default behavior
+ if not In_Internal_Unit (Unit_Id) then
- else
- -- Check whether the early call region of the subprogram body is
- -- available.
+ -- The name of the unit subjected to the elaboration pragma is
+ -- fully qualified to improve the clarity of the info message.
- Region := Early_Call_Region (Body_Id);
+ Error_Msg_Name_1 := Prag_Nam;
+ Error_Msg_Qual_Level := Nat'Last;
- if No (Region) then
+ Error_Msg_NE
+ ("info: implicit pragma % generated for unit &", N, Unit_Id);
- -- Traverse the declarations in reverse order, starting from the
- -- subprogram body, searching for the nearest non-preelaborable
- -- construct. The early call region starts after this construct
- -- and ends at the subprogram body.
+ Error_Msg_Qual_Level := 0;
+ Output_Active_Scenarios (N, In_State);
+ end if;
+ end Info_Implicit_Pragma;
- Region := Find_ECR (Body_Decl);
+ -- Local variables
- -- Associate the early call region with the subprogram body in
- -- case other scenarios need it.
+ EA_Id : constant Elaboration_Attributes_Id :=
+ Elaboration_Attributes_Of (Unit_Id);
- Set_Early_Call_Region (Body_Id, Region);
- end if;
- end if;
+ Main_Cunit : constant Node_Id := Cunit (Main_Unit);
+ Loc : constant Source_Ptr := Sloc (Main_Cunit);
+ Unit_Cunit : constant Node_Id := Compilation_Unit (Unit_Id);
+ Unit_Prag : constant Node_Id := Elab_Pragma (EA_Id);
+ Unit_With : constant Node_Id := With_Clause (EA_Id);
- -- A subprogram body must always have an early call region
+ Clause : Node_Id;
+ Items : List_Id;
- pragma Assert (Present (Region));
+ -- Start of processing for Ensure_Prior_Elaboration_Static
- return Region;
- end Find_Early_Call_Region;
+ begin
+ -- Nothing to do when the caller has suppressed the generation of
+ -- implicit Elaborate[_All] pragmas.
- ---------------------------
- -- Find_Elaborated_Units --
- ---------------------------
+ if In_State.Suppress_Implicit_Pragmas then
+ return;
- procedure Find_Elaborated_Units is
- procedure Add_Pragma (Prag : Node_Id);
- -- Determine whether pragma Prag denotes a legal Elaborate[_All] pragma.
- -- If this is the case, add the related unit to the elaboration context.
- -- For pragma Elaborate_All, include recursively all units withed by the
- -- related unit.
+ -- Nothing to do when the unit is guaranteed prior elaboration by
+ -- means of a source Elaborate[_All] pragma.
- procedure Add_Unit
- (Unit_Id : Entity_Id;
- Prag : Node_Id;
- Full_Context : Boolean);
- -- Add unit Unit_Id to the elaboration context. Prag denotes the pragma
- -- which prompted the inclusion of the unit to the elaboration context.
- -- If flag Full_Context is set, examine the nonlimited clauses of unit
- -- Unit_Id and add each withed unit to the context.
+ elsif Present (Unit_Prag) then
+ return;
- procedure Find_Elaboration_Context (Comp_Unit : Node_Id);
- -- Examine the context items of compilation unit Comp_Unit for suitable
- -- elaboration-related pragmas and add all related units to the context.
+ -- Nothing to do when the unit has an existing implicit Elaborate or
+ -- Elaborate_All pragma installed by a previous scenario.
- ----------------
- -- Add_Pragma --
- ----------------
+ elsif Present (Unit_With) then
- procedure Add_Pragma (Prag : Node_Id) is
- Prag_Args : constant List_Id := Pragma_Argument_Associations (Prag);
- Prag_Nam : constant Name_Id := Pragma_Name (Prag);
- Unit_Arg : Node_Id;
+ -- The unit is already guaranteed prior elaboration by means of an
+ -- implicit Elaborate pragma, however the current scenario imposes
+ -- a stronger requirement of Elaborate_All. "Upgrade" the existing
+ -- pragma to match this new requirement.
- begin
- -- Nothing to do if the pragma is not related to elaboration
+ if Elaborate_Desirable (Unit_With)
+ and then Prag_Nam = Name_Elaborate_All
+ then
+ Set_Elaborate_All_Desirable (Unit_With);
+ Set_Elaborate_Desirable (Unit_With, False);
+ end if;
- if not Nam_In (Prag_Nam, Name_Elaborate, Name_Elaborate_All) then
return;
+ end if;
- -- Nothing to do when the pragma is illegal
+ -- At this point it is known that the unit has no prior elaboration
+ -- according to pragmas and hierarchical relationships.
- elsif Error_Posted (Prag) then
- return;
+ Items := Context_Items (Main_Cunit);
+
+ if No (Items) then
+ Items := New_List;
+ Set_Context_Items (Main_Cunit, Items);
end if;
- Unit_Arg := Get_Pragma_Arg (First (Prag_Args));
+ -- Locate the with clause for the unit. Note that there may not be a
+ -- clause if the unit is visible through a subunit-body, body-spec,
+ -- or spec-parent relationship.
- -- The argument of the pragma may appear in package.package form
+ Clause :=
+ Find_With_Clause
+ (Items => Items,
+ Withed_Id => Unit_Id);
+
+ -- Generate:
+ -- with Id;
- if Nkind (Unit_Arg) = N_Selected_Component then
- Unit_Arg := Selector_Name (Unit_Arg);
+ -- Note that adding implicit with clauses is safe because analysis,
+ -- resolution, and expansion have already taken place and it is not
+ -- possible to interfere with visibility.
+
+ if No (Clause) then
+ Clause :=
+ Make_With_Clause (Loc,
+ Name => New_Occurrence_Of (Unit_Id, Loc));
+
+ Set_Implicit_With (Clause);
+ Set_Library_Unit (Clause, Unit_Cunit);
+
+ Append_To (Items, Clause);
end if;
- Add_Unit
- (Unit_Id => Entity (Unit_Arg),
- Prag => Prag,
- Full_Context => Prag_Nam = Name_Elaborate_All);
- end Add_Pragma;
+ -- Mark the with clause depending on the pragma required
- --------------
- -- Add_Unit --
- --------------
+ if Prag_Nam = Name_Elaborate then
+ Set_Elaborate_Desirable (Clause);
+ else
+ Set_Elaborate_All_Desirable (Clause);
+ end if;
+
+ -- The implicit Elaborate[_All] ensures the prior elaboration of
+ -- the unit. Include the unit in the elaboration context of the
+ -- main unit.
+
+ Set_With_Clause (EA_Id, Clause);
+
+ -- Output extra information on an implicit Elaborate[_All] pragma
+ -- when switch -gnatel (info messages on implicit Elaborate[_All]
+ -- pragmas is in effect.
+
+ if Elab_Info_Messages then
+ Info_Implicit_Pragma;
+ end if;
+ end Ensure_Prior_Elaboration_Static;
+
+ -------------------------------
+ -- Finalize_Elaborated_Units --
+ -------------------------------
+
+ procedure Finalize_Elaborated_Units is
+ begin
+ UA_Map.Destroy (Unit_To_Attributes_Map);
+ end Finalize_Elaborated_Units;
- procedure Add_Unit
+ ---------------------------
+ -- Has_Prior_Elaboration --
+ ---------------------------
+
+ function Has_Prior_Elaboration
(Unit_Id : Entity_Id;
- Prag : Node_Id;
- Full_Context : Boolean)
+ Context_OK : Boolean := False;
+ Elab_Body_OK : Boolean := False;
+ Same_Unit_OK : Boolean := False) return Boolean
is
- Clause : Node_Id;
- Elab_Attrs : Elaboration_Attributes;
+ EA_Id : constant Elaboration_Attributes_Id :=
+ Elaboration_Attributes_Of (Unit_Id);
+
+ Main_Id : constant Entity_Id := Cunit_Entity (Main_Unit);
+ Unit_Prag : constant Node_Id := Elab_Pragma (EA_Id);
+ Unit_With : constant Node_Id := With_Clause (EA_Id);
begin
- -- Nothing to do when some previous error left a with clause or a
- -- pragma in a bad state.
+ -- A preelaborated unit is always elaborated prior to the main unit
- if No (Unit_Id) then
- return;
+ if Is_Preelaborated_Unit (Unit_Id) then
+ return True;
+
+ -- An internal unit is always elaborated prior to a non-internal main
+ -- unit.
+
+ elsif In_Internal_Unit (Unit_Id)
+ and then not In_Internal_Unit (Main_Id)
+ then
+ return True;
+
+ -- A unit has prior elaboration if it appears within the context
+ -- of the main unit. Consider this case only when requested by the
+ -- caller.
+
+ elsif Context_OK
+ and then (Present (Unit_Prag) or else Present (Unit_With))
+ then
+ return True;
+
+ -- A unit whose body is elaborated together with its spec has prior
+ -- elaboration except with respect to itself. Consider this case only
+ -- when requested by the caller.
+
+ elsif Elab_Body_OK
+ and then Has_Pragma_Elaborate_Body (Unit_Id)
+ and then not Is_Same_Unit (Unit_Id, Main_Id)
+ then
+ return True;
+
+ -- A unit has no prior elaboration with respect to itself, but does
+ -- not require any means of ensuring its own elaboration either.
+ -- Treat this case as valid prior elaboration only when requested by
+ -- the caller.
+
+ elsif Same_Unit_OK and then Is_Same_Unit (Unit_Id, Main_Id) then
+ return True;
end if;
- Elab_Attrs := Elaboration_Status (Unit_Id);
+ return False;
+ end Has_Prior_Elaboration;
- -- The unit is already included in the context by means of pragma
- -- Elaborate[_All].
+ ---------------------------------
+ -- Initialize_Elaborated_Units --
+ ---------------------------------
- if Present (Elab_Attrs.Source_Pragma) then
+ procedure Initialize_Elaborated_Units is
+ begin
+ null;
+ end Initialize_Elaborated_Units;
- -- Upgrade an existing pragma Elaborate when the unit is subject
- -- to Elaborate_All because the new pragma covers a larger set of
- -- units.
+ ----------------------------------
+ -- Meet_Elaboration_Requirement --
+ ----------------------------------
- if Pragma_Name (Elab_Attrs.Source_Pragma) = Name_Elaborate
- and then Pragma_Name (Prag) = Name_Elaborate_All
- then
- Elab_Attrs.Source_Pragma := Prag;
+ procedure Meet_Elaboration_Requirement
+ (N : Node_Id;
+ Targ_Id : Entity_Id;
+ Req_Nam : Name_Id;
+ In_State : Processing_In_State)
+ is
+ pragma Assert (Nam_In (Req_Nam, Name_Elaborate, Name_Elaborate_All));
+
+ Main_Id : constant Entity_Id := Cunit_Entity (Main_Unit);
+ Unit_Id : constant Entity_Id := Find_Top_Unit (Targ_Id);
- -- Otherwise the unit retains its existing pragma and does not
- -- need to be included in the context again.
+ procedure Elaboration_Requirement_Error;
+ pragma Inline (Elaboration_Requirement_Error);
+ -- Emit an error concerning scenario N which has failed to meet the
+ -- elaboration requirement.
+
+ function Find_Preelaboration_Pragma
+ (Prag_Nam : Name_Id) return Node_Id;
+ pragma Inline (Find_Preelaboration_Pragma);
+ -- Traverse the visible declarations of unit Unit_Id and locate a
+ -- source preelaboration-related pragma with name Prag_Nam.
+
+ procedure Info_Requirement_Met (Prag : Node_Id);
+ pragma Inline (Info_Requirement_Met);
+ -- Output information concerning pragma Prag which meets requirement
+ -- Req_Nam.
+
+ -----------------------------------
+ -- Elaboration_Requirement_Error --
+ -----------------------------------
+
+ procedure Elaboration_Requirement_Error is
+ begin
+ if Is_Suitable_Call (N) then
+ Info_Call
+ (Call => N,
+ Subp_Id => Targ_Id,
+ Info_Msg => False,
+ In_SPARK => True);
+
+ elsif Is_Suitable_Instantiation (N) then
+ Info_Instantiation
+ (Inst => N,
+ Gen_Id => Targ_Id,
+ Info_Msg => False,
+ In_SPARK => True);
+
+ elsif Is_Suitable_SPARK_Refined_State_Pragma (N) then
+ Error_Msg_N
+ ("read of refinement constituents during elaboration in "
+ & "SPARK", N);
+
+ elsif Is_Suitable_Variable_Reference (N) then
+ Info_Variable_Reference
+ (Ref => N,
+ Var_Id => Targ_Id,
+ Info_Msg => False,
+ In_SPARK => True);
+
+ -- No other scenario may impose a requirement on the context of
+ -- the main unit.
else
+ pragma Assert (False);
return;
end if;
- -- The current unit is not part of the context. Prepare a new set of
- -- attributes.
+ Error_Msg_Name_1 := Req_Nam;
+ Error_Msg_Node_2 := Unit_Id;
+ Error_Msg_NE ("\\unit & requires pragma % for &", N, Main_Id);
- else
- Elab_Attrs :=
- Elaboration_Attributes'(Source_Pragma => Prag,
- With_Clause => Empty);
- end if;
+ Output_Active_Scenarios (N, In_State);
+ end Elaboration_Requirement_Error;
- -- Add or update the attributes of the unit
+ --------------------------------
+ -- Find_Preelaboration_Pragma --
+ --------------------------------
- Set_Elaboration_Status (Unit_Id, Elab_Attrs);
+ function Find_Preelaboration_Pragma
+ (Prag_Nam : Name_Id) return Node_Id
+ is
+ Spec : constant Node_Id := Parent (Unit_Id);
+ Decl : Node_Id;
- -- Includes all units withed by the current one when computing the
- -- full context.
+ begin
+ -- A preelaboration-related pragma comes from source and appears
+ -- at the top of the visible declarations of a package.
- if Full_Context then
+ if Nkind (Spec) = N_Package_Specification then
+ Decl := First (Visible_Declarations (Spec));
+ while Present (Decl) loop
+ if Comes_From_Source (Decl) then
+ if Nkind (Decl) = N_Pragma
+ and then Pragma_Name (Decl) = Prag_Nam
+ then
+ return Decl;
- -- Process all nonlimited with clauses found in the context of
- -- the current unit. Note that limited clauses do not impose an
- -- elaboration order.
+ -- Otherwise the construct terminates the region where
+ -- the preelaboration-related pragma may appear.
- Clause := First (Context_Items (Compilation_Unit (Unit_Id)));
- while Present (Clause) loop
- if Nkind (Clause) = N_With_Clause
- and then not Error_Posted (Clause)
- and then not Limited_Present (Clause)
- then
- Add_Unit
- (Unit_Id => Entity (Name (Clause)),
- Prag => Prag,
- Full_Context => Full_Context);
- end if;
+ else
+ exit;
+ end if;
+ end if;
- Next (Clause);
- end loop;
- end if;
- end Add_Unit;
+ Next (Decl);
+ end loop;
+ end if;
- ------------------------------
- -- Find_Elaboration_Context --
- ------------------------------
+ return Empty;
+ end Find_Preelaboration_Pragma;
- procedure Find_Elaboration_Context (Comp_Unit : Node_Id) is
- Prag : Node_Id;
+ --------------------------
+ -- Info_Requirement_Met --
+ --------------------------
+
+ procedure Info_Requirement_Met (Prag : Node_Id) is
+ pragma Assert (Present (Prag));
+
+ begin
+ Error_Msg_Name_1 := Req_Nam;
+ Error_Msg_Sloc := Sloc (Prag);
+ Error_Msg_NE
+ ("\\% requirement for unit & met by pragma #", N, Unit_Id);
+ end Info_Requirement_Met;
+
+ -- Local variables
+
+ EA_Id : Elaboration_Attributes_Id;
+ Elab_Nam : Name_Id;
+ Req_Met : Boolean;
+ Unit_Prag : Node_Id;
+
+ -- Start of processing for Meet_Elaboration_Requirement
begin
- pragma Assert (Nkind (Comp_Unit) = N_Compilation_Unit);
+ -- Assume that the requirement has not been met
- -- Process all elaboration-related pragmas found in the context of
- -- the compilation unit.
+ Req_Met := False;
- Prag := First (Context_Items (Comp_Unit));
- while Present (Prag) loop
- if Nkind (Prag) = N_Pragma then
- Add_Pragma (Prag);
- end if;
+ -- If the target is within the main unit, either at the source level
+ -- or through an instantiation, then there is no real requirement to
+ -- meet because the main unit cannot force its own elaboration by
+ -- means of an Elaborate[_All] pragma. Treat this case as valid
+ -- coverage.
- Next (Prag);
- end loop;
- end Find_Elaboration_Context;
+ if In_Extended_Main_Code_Unit (Targ_Id) then
+ Req_Met := True;
- -- Local variables
+ -- Otherwise the target resides in an external unit
- Par_Id : Entity_Id;
- Unt : Node_Id;
+ -- The requirement is met when the target comes from an internal unit
+ -- because such a unit is elaborated prior to a non-internal unit.
- -- Start of processing for Find_Elaborated_Units
+ elsif In_Internal_Unit (Unit_Id)
+ and then not In_Internal_Unit (Main_Id)
+ then
+ Req_Met := True;
- begin
- -- Perform a traversal which examines the context of the main unit and
- -- populates the Elaboration_Context table with all units elaborated
- -- prior to the main unit. The traversal performs the following jumps:
+ -- The requirement is met when the target comes from a preelaborated
+ -- unit. This portion must parallel predicate Is_Preelaborated_Unit.
- -- subunit -> parent subunit
- -- parent subunit -> body
- -- body -> spec
- -- spec -> parent spec
- -- parent spec -> grandparent spec and so on
+ elsif Is_Preelaborated_Unit (Unit_Id) then
+ Req_Met := True;
- -- The traversal relies on units rather than scopes because the scope of
- -- a subunit is some spec, while this traversal must process the body as
- -- well. Given that protected and task bodies can also be subunits, this
- -- complicates the scope approach even further.
+ -- Output extra information when switch -gnatel (info messages on
+ -- implicit Elaborate[_All] pragmas.
- Unt := Unit (Cunit (Main_Unit));
+ if Elab_Info_Messages
+ and then not In_State.Suppress_Info_Messages
+ then
+ if Is_Preelaborated (Unit_Id) then
+ Elab_Nam := Name_Preelaborate;
- -- Perform the following traversals when the main unit is a subunit
+ elsif Is_Pure (Unit_Id) then
+ Elab_Nam := Name_Pure;
- -- subunit -> parent subunit
- -- parent subunit -> body
+ elsif Is_Remote_Call_Interface (Unit_Id) then
+ Elab_Nam := Name_Remote_Call_Interface;
- while Present (Unt) and then Nkind (Unt) = N_Subunit loop
- Find_Elaboration_Context (Parent (Unt));
+ elsif Is_Remote_Types (Unit_Id) then
+ Elab_Nam := Name_Remote_Types;
- -- Continue the traversal by going to the unit which contains the
- -- corresponding stub.
+ else
+ pragma Assert (Is_Shared_Passive (Unit_Id));
+ Elab_Nam := Name_Shared_Passive;
+ end if;
- if Present (Corresponding_Stub (Unt)) then
- Unt := Unit (Cunit (Get_Source_Unit (Corresponding_Stub (Unt))));
+ Info_Requirement_Met (Find_Preelaboration_Pragma (Elab_Nam));
+ end if;
- -- Otherwise the subunit may be erroneous or left in a bad state
+ -- Determine whether the context of the main unit has a pragma strong
+ -- enough to meet the requirement.
else
- exit;
- end if;
- end loop;
+ EA_Id := Elaboration_Attributes_Of (Unit_Id);
+ Unit_Prag := Elab_Pragma (EA_Id);
- -- Perform the following traversal now that subunits have been taken
- -- care of, or the main unit is a body.
+ -- The pragma must be either Elaborate_All or be as strong as the
+ -- requirement.
- -- body -> spec
+ if Present (Unit_Prag)
+ and then Nam_In (Pragma_Name (Unit_Prag), Name_Elaborate_All,
+ Req_Nam)
+ then
+ Req_Met := True;
- if Present (Unt)
- and then Nkind_In (Unt, N_Package_Body, N_Subprogram_Body)
- then
- Find_Elaboration_Context (Parent (Unt));
+ -- Output extra information when switch -gnatel (info messages
+ -- on implicit Elaborate[_All] pragmas.
- -- Continue the traversal by going to the unit which contains the
- -- corresponding spec.
+ if Elab_Info_Messages
+ and then not In_State.Suppress_Info_Messages
+ then
+ Info_Requirement_Met (Unit_Prag);
+ end if;
+ end if;
+ end if;
+
+ -- The requirement was not met by the context of the main unit, issue
+ -- an error.
- if Present (Corresponding_Spec (Unt)) then
- Unt := Unit (Cunit (Get_Source_Unit (Corresponding_Spec (Unt))));
+ if not Req_Met then
+ Elaboration_Requirement_Error;
end if;
- end if;
+ end Meet_Elaboration_Requirement;
- -- Perform the following traversals now that the body has been taken
- -- care of, or the main unit is a spec.
+ -------------
+ -- Present --
+ -------------
- -- spec -> parent spec
- -- parent spec -> grandparent spec and so on
+ function Present (EA_Id : Elaboration_Attributes_Id) return Boolean is
+ begin
+ return EA_Id /= No_Elaboration_Attributes;
+ end Present;
- if Present (Unt)
- and then Nkind_In (Unt, N_Generic_Package_Declaration,
- N_Generic_Subprogram_Declaration,
- N_Package_Declaration,
- N_Subprogram_Declaration)
- then
- Find_Elaboration_Context (Parent (Unt));
+ ---------------------
+ -- Set_Elab_Pragma --
+ ---------------------
- -- Process a potential chain of parent units which ends with the
- -- main unit spec. The traversal can now safely rely on the scope
- -- chain.
+ procedure Set_Elab_Pragma
+ (EA_Id : Elaboration_Attributes_Id;
+ Prag : Node_Id)
+ is
+ pragma Assert (Present (EA_Id));
+ begin
+ Elaboration_Attributes.Table (EA_Id).Elab_Pragma := Prag;
+ end Set_Elab_Pragma;
- Par_Id := Scope (Defining_Entity (Unt));
- while Present (Par_Id) and then Par_Id /= Standard_Standard loop
- Find_Elaboration_Context (Compilation_Unit (Par_Id));
+ ---------------------
+ -- Set_With_Clause --
+ ---------------------
- Par_Id := Scope (Par_Id);
- end loop;
- end if;
- end Find_Elaborated_Units;
+ procedure Set_With_Clause
+ (EA_Id : Elaboration_Attributes_Id;
+ Clause : Node_Id)
+ is
+ pragma Assert (Present (EA_Id));
+ begin
+ Elaboration_Attributes.Table (EA_Id).With_Clause := Clause;
+ end Set_With_Clause;
+
+ -----------------
+ -- With_Clause --
+ -----------------
+
+ function With_Clause
+ (EA_Id : Elaboration_Attributes_Id) return Node_Id
+ is
+ pragma Assert (Present (EA_Id));
+ begin
+ return Elaboration_Attributes.Table (EA_Id).With_Clause;
+ end With_Clause;
+ end Elaborated_Units;
-----------------------------
-- Find_Enclosing_Instance --
-----------------------------
function Find_Enclosing_Instance (N : Node_Id) return Node_Id is
- Par : Node_Id;
- Spec_Id : Entity_Id;
+ Par : Node_Id;
begin
-- Climb the parent chain looking for an enclosing instance spec or body
Par := N;
while Present (Par) loop
-
- -- Generic package or subprogram spec
-
- if Nkind_In (Par, N_Package_Declaration,
+ if Nkind_In (Par, N_Package_Body,
+ N_Package_Declaration,
+ N_Subprogram_Body,
N_Subprogram_Declaration)
- and then Is_Generic_Instance (Defining_Entity (Par))
+ and then Is_Generic_Instance (Unique_Defining_Entity (Par))
then
return Par;
-
- -- Generic package or subprogram body
-
- elsif Nkind_In (Par, N_Package_Body, N_Subprogram_Body) then
- Spec_Id := Corresponding_Spec (Par);
-
- if Present (Spec_Id) and then Is_Generic_Instance (Spec_Id) then
- return Par;
- end if;
end if;
Par := Parent (Par);
@@ -5340,6 +8833,7 @@ package body Sem_Elab is
function Find_Enclosing_Level (N : Node_Id) return Enclosing_Level_Kind is
function Level_Of (Unit : Node_Id) return Enclosing_Level_Kind;
+ pragma Inline (Level_Of);
-- Obtain the corresponding level of unit Unit
--------------
@@ -5351,13 +8845,13 @@ package body Sem_Elab is
begin
if Nkind (Unit) in N_Generic_Instantiation then
- return Instantiation;
+ return Instantiation_Level;
elsif Nkind (Unit) = N_Generic_Package_Declaration then
- return Generic_Package_Spec;
+ return Generic_Spec_Level;
elsif Nkind (Unit) = N_Package_Declaration then
- return Package_Spec;
+ return Library_Spec_Level;
elsif Nkind (Unit) = N_Package_Body then
Spec_Id := Corresponding_Spec (Unit);
@@ -5367,14 +8861,14 @@ package body Sem_Elab is
if Present (Spec_Id)
and then Ekind (Spec_Id) = E_Generic_Package
then
- return Generic_Package_Body;
+ return Generic_Body_Level;
-- Otherwise the body belongs to a non-generic package. This also
-- treats an illegal package body without a corresponding spec as
-- a non-generic package body.
else
- return Package_Body;
+ return Library_Body_Level;
end if;
end if;
@@ -5472,9 +8966,9 @@ package body Sem_Elab is
end if;
-- The current construct is a non-library-level encapsulator which
- -- indicates that the node cannot possibly appear at any level.
- -- Note that this check must come after the declaration-level check
- -- because both predicates share certain nodes.
+ -- indicates that the node cannot possibly appear at any level. Note
+ -- that the check must come after the declaration-level check because
+ -- both predicates share certain nodes.
elsif Is_Non_Library_Level_Encapsulator (Curr) then
Context := Parent (Curr);
@@ -5591,22 +9085,554 @@ package body Sem_Elab is
return Empty;
end First_Formal_Type;
+ ------------------------------
+ -- Guaranteed_ABE_Processor --
+ ------------------------------
+
+ package body Guaranteed_ABE_Processor is
+ function Is_Guaranteed_ABE
+ (N : Node_Id;
+ Target_Decl : Node_Id;
+ Target_Body : Node_Id) return Boolean;
+ pragma Inline (Is_Guaranteed_ABE);
+ -- Determine whether scenario N with a target described by its initial
+ -- declaration Target_Decl and body Target_Decl results in a guaranteed
+ -- ABE.
+
+ procedure Process_Guaranteed_ABE_Activation
+ (Call : Node_Id;
+ Call_Rep : Scenario_Rep_Id;
+ Obj_Id : Entity_Id;
+ Obj_Rep : Target_Rep_Id;
+ Task_Typ : Entity_Id;
+ Task_Rep : Target_Rep_Id;
+ In_State : Processing_In_State);
+ pragma Inline (Process_Guaranteed_ABE_Activation);
+ -- Perform common guaranteed ABE checks and diagnostics for activation
+ -- call Call which activates object Obj_Id of task type Task_Typ. Formal
+ -- Call_Rep denotes the representation of the call. Obj_Rep denotes the
+ -- representation of the object. Task_Rep denotes the representation of
+ -- the task type. In_State is the current state of the Processing phase.
+
+ procedure Process_Guaranteed_ABE_Call
+ (Call : Node_Id;
+ Call_Rep : Scenario_Rep_Id;
+ In_State : Processing_In_State);
+ pragma Inline (Process_Guaranteed_ABE_Call);
+ -- Perform common guaranteed ABE checks and diagnostics for call Call
+ -- with representation Call_Rep. In_State denotes the current state of
+ -- the Processing phase.
+
+ procedure Process_Guaranteed_ABE_Instantiation
+ (Inst : Node_Id;
+ Inst_Rep : Scenario_Rep_Id;
+ In_State : Processing_In_State);
+ pragma Inline (Process_Guaranteed_ABE_Instantiation);
+ -- Perform common guaranteed ABE checks and diagnostics for instance
+ -- Inst with representation Inst_Rep. In_State is the current state of
+ -- the Processing phase.
+
+ -----------------------
+ -- Is_Guaranteed_ABE --
+ -----------------------
+
+ function Is_Guaranteed_ABE
+ (N : Node_Id;
+ Target_Decl : Node_Id;
+ Target_Body : Node_Id) return Boolean
+ is
+ begin
+ -- Avoid cascaded errors if there were previous serious infractions.
+ -- As a result the scenario will not be treated as a guaranteed ABE.
+ -- This behaviour parallels that of the old ABE mechanism.
+
+ if Serious_Errors_Detected > 0 then
+ return False;
+
+ -- The scenario and the target appear in the same context ignoring
+ -- enclosing library levels.
+
+ elsif In_Same_Context (N, Target_Decl) then
+
+ -- The target body has already been encountered. The scenario
+ -- results in a guaranteed ABE if it appears prior to the body.
+
+ if Present (Target_Body) then
+ return Earlier_In_Extended_Unit (N, Target_Body);
+
+ -- Otherwise the body has not been encountered yet. The scenario
+ -- is a guaranteed ABE since the body will appear later. It is
+ -- assumed that the caller has already ensured that the scenario
+ -- is ABE-safe because optional bodies are not considered here.
+
+ else
+ return True;
+ end if;
+ end if;
+
+ return False;
+ end Is_Guaranteed_ABE;
+
+ ----------------------------
+ -- Process_Guaranteed_ABE --
+ ----------------------------
+
+ procedure Process_Guaranteed_ABE
+ (N : Node_Id;
+ In_State : Processing_In_State)
+ is
+ Scen : constant Node_Id := Scenario (N);
+ Scen_Rep : Scenario_Rep_Id;
+
+ begin
+ -- Add the current scenario to the stack of active scenarios
+
+ Push_Active_Scenario (Scen);
+
+ -- Only calls, instantiations, and task activations may result in a
+ -- guaranteed ABE.
+
+ -- Call or task activation
+
+ if Is_Suitable_Call (Scen) then
+ Scen_Rep := Scenario_Representation_Of (Scen, In_State);
+
+ if Kind (Scen_Rep) = Call_Scenario then
+ Process_Guaranteed_ABE_Call
+ (Call => Scen,
+ Call_Rep => Scen_Rep,
+ In_State => In_State);
+
+ else
+ pragma Assert (Kind (Scen_Rep) = Task_Activation_Scenario);
+
+ Process_Activation
+ (Call => Scen,
+ Call_Rep => Scenario_Representation_Of (Scen, In_State),
+ Processor => Process_Guaranteed_ABE_Activation'Access,
+ In_State => In_State);
+ end if;
+
+ -- Instantiation
+
+ elsif Is_Suitable_Instantiation (Scen) then
+ Process_Guaranteed_ABE_Instantiation
+ (Inst => Scen,
+ Inst_Rep => Scenario_Representation_Of (Scen, In_State),
+ In_State => In_State);
+ end if;
+
+ -- Remove the current scenario from the stack of active scenarios
+ -- once all ABE diagnostics and checks have been performed.
+
+ Pop_Active_Scenario (Scen);
+ end Process_Guaranteed_ABE;
+
+ ---------------------------------------
+ -- Process_Guaranteed_ABE_Activation --
+ ---------------------------------------
+
+ procedure Process_Guaranteed_ABE_Activation
+ (Call : Node_Id;
+ Call_Rep : Scenario_Rep_Id;
+ Obj_Id : Entity_Id;
+ Obj_Rep : Target_Rep_Id;
+ Task_Typ : Entity_Id;
+ Task_Rep : Target_Rep_Id;
+ In_State : Processing_In_State)
+ is
+ Spec_Decl : constant Node_Id := Spec_Declaration (Task_Rep);
+
+ Check_OK : constant Boolean :=
+ not In_State.Suppress_Checks
+ and then Ghost_Mode_Of (Obj_Rep) /= Is_Ignored
+ and then Ghost_Mode_Of (Task_Rep) /= Is_Ignored
+ and then Elaboration_Checks_OK (Obj_Rep)
+ and then Elaboration_Checks_OK (Task_Rep);
+ -- A run-time ABE check may be installed only when the object and the
+ -- task type have active elaboration checks, and both are not ignored
+ -- Ghost constructs.
+
+ begin
+ -- Nothing to do when the root scenario appears at the declaration
+ -- level and the task is in the same unit, but outside this context.
+ --
+ -- task type Task_Typ; -- task declaration
+ --
+ -- procedure Proc is
+ -- function A ... is
+ -- begin
+ -- if Some_Condition then
+ -- declare
+ -- T : Task_Typ;
+ -- begin
+ -- <activation call> -- activation site
+ -- end;
+ -- ...
+ -- end A;
+ --
+ -- X : ... := A; -- root scenario
+ -- ...
+ --
+ -- task body Task_Typ is
+ -- ...
+ -- end Task_Typ;
+ --
+ -- In the example above, the context of X is the declarative list
+ -- of Proc. The "elaboration" of X may reach the activation of T
+ -- whose body is defined outside of X's context. The task body is
+ -- relevant only when Proc is invoked, but this happens only in
+ -- "normal" elaboration, therefore the task body must not be
+ -- considered if this is not the case.
+
+ if Is_Up_Level_Target
+ (Targ_Decl => Spec_Decl,
+ In_State => In_State)
+ then
+ return;
+
+ -- Nothing to do when the activation is ABE-safe
+ --
+ -- generic
+ -- package Gen is
+ -- task type Task_Typ;
+ -- end Gen;
+ --
+ -- package body Gen is
+ -- task body Task_Typ is
+ -- begin
+ -- ...
+ -- end Task_Typ;
+ -- end Gen;
+ --
+ -- with Gen;
+ -- procedure Main is
+ -- package Nested is
+ -- package Inst is new Gen;
+ -- T : Inst.Task_Typ;
+ -- end Nested; -- safe activation
+ -- ...
+
+ elsif Is_Safe_Activation (Call, Task_Rep) then
+ return;
+
+ -- An activation call leads to a guaranteed ABE when the activation
+ -- call and the task appear within the same context ignoring library
+ -- levels, and the body of the task has not been seen yet or appears
+ -- after the activation call.
+ --
+ -- procedure Guaranteed_ABE is
+ -- task type Task_Typ;
+ --
+ -- package Nested is
+ -- T : Task_Typ;
+ -- <activation call> -- guaranteed ABE
+ -- end Nested;
+ --
+ -- task body Task_Typ is
+ -- ...
+ -- end Task_Typ;
+ -- ...
+
+ elsif Is_Guaranteed_ABE
+ (N => Call,
+ Target_Decl => Spec_Decl,
+ Target_Body => Body_Declaration (Task_Rep))
+ then
+ if Elaboration_Warnings_OK (Call_Rep) then
+ Error_Msg_Sloc := Sloc (Call);
+ Error_Msg_N
+ ("??task & will be activated # before elaboration of its "
+ & "body", Obj_Id);
+ Error_Msg_N
+ ("\Program_Error will be raised at run time", Obj_Id);
+ end if;
+
+ -- Mark the activation call as a guaranteed ABE
+
+ Set_Is_Known_Guaranteed_ABE (Call);
+
+ -- Install a run-time ABE failue because this activation call will
+ -- always result in an ABE.
+
+ if Check_OK then
+ Install_Scenario_ABE_Failure
+ (N => Call,
+ Targ_Id => Task_Typ,
+ Targ_Rep => Task_Rep,
+ Disable => Obj_Rep);
+ end if;
+ end if;
+ end Process_Guaranteed_ABE_Activation;
+
+ ---------------------------------
+ -- Process_Guaranteed_ABE_Call --
+ ---------------------------------
+
+ procedure Process_Guaranteed_ABE_Call
+ (Call : Node_Id;
+ Call_Rep : Scenario_Rep_Id;
+ In_State : Processing_In_State)
+ is
+ Subp_Id : constant Entity_Id := Target (Call_Rep);
+ Subp_Rep : constant Target_Rep_Id :=
+ Target_Representation_Of (Subp_Id, In_State);
+ Spec_Decl : constant Node_Id := Spec_Declaration (Subp_Rep);
+
+ Check_OK : constant Boolean :=
+ not In_State.Suppress_Checks
+ and then Ghost_Mode_Of (Call_Rep) /= Is_Ignored
+ and then Ghost_Mode_Of (Subp_Rep) /= Is_Ignored
+ and then Elaboration_Checks_OK (Call_Rep)
+ and then Elaboration_Checks_OK (Subp_Rep);
+ -- A run-time ABE check may be installed only when both the call
+ -- and the target have active elaboration checks, and both are not
+ -- ignored Ghost constructs.
+
+ begin
+ -- Nothing to do when the root scenario appears at the declaration
+ -- level and the target is in the same unit but outside this context.
+ --
+ -- function B ...; -- target declaration
+ --
+ -- procedure Proc is
+ -- function A ... is
+ -- begin
+ -- if Some_Condition then
+ -- return B; -- call site
+ -- ...
+ -- end A;
+ --
+ -- X : ... := A; -- root scenario
+ -- ...
+ --
+ -- function B ... is
+ -- ...
+ -- end B;
+ --
+ -- In the example above, the context of X is the declarative region
+ -- of Proc. The "elaboration" of X may eventually reach B which is
+ -- defined outside of X's context. B is relevant only when Proc is
+ -- invoked, but this happens only by means of "normal" elaboration,
+ -- therefore B must not be considered if this is not the case.
+
+ if Is_Up_Level_Target
+ (Targ_Decl => Spec_Decl,
+ In_State => In_State)
+ then
+ return;
+
+ -- Nothing to do when the call is ABE-safe
+ --
+ -- generic
+ -- function Gen ...;
+ --
+ -- function Gen ... is
+ -- begin
+ -- ...
+ -- end Gen;
+ --
+ -- with Gen;
+ -- procedure Main is
+ -- function Inst is new Gen;
+ -- X : ... := Inst; -- safe call
+ -- ...
+
+ elsif Is_Safe_Call (Call, Subp_Id, Subp_Rep) then
+ return;
+
+ -- A call leads to a guaranteed ABE when the call and the target
+ -- appear within the same context ignoring library levels, and the
+ -- body of the target has not been seen yet or appears after the
+ -- call.
+ --
+ -- procedure Guaranteed_ABE is
+ -- function Func ...;
+ --
+ -- package Nested is
+ -- Obj : ... := Func; -- guaranteed ABE
+ -- end Nested;
+ --
+ -- function Func ... is
+ -- ...
+ -- end Func;
+ -- ...
+
+ elsif Is_Guaranteed_ABE
+ (N => Call,
+ Target_Decl => Spec_Decl,
+ Target_Body => Body_Declaration (Subp_Rep))
+ then
+ if Elaboration_Warnings_OK (Call_Rep) then
+ Error_Msg_NE
+ ("??cannot call & before body seen", Call, Subp_Id);
+ Error_Msg_N ("\Program_Error will be raised at run time", Call);
+ end if;
+
+ -- Mark the call as a guarnateed ABE
+
+ Set_Is_Known_Guaranteed_ABE (Call);
+
+ -- Install a run-time ABE failure because the call will always
+ -- result in an ABE.
+
+ if Check_OK then
+ Install_Scenario_ABE_Failure
+ (N => Call,
+ Targ_Id => Subp_Id,
+ Targ_Rep => Subp_Rep,
+ Disable => Call_Rep);
+ end if;
+ end if;
+ end Process_Guaranteed_ABE_Call;
+
+ ------------------------------------------
+ -- Process_Guaranteed_ABE_Instantiation --
+ ------------------------------------------
+
+ procedure Process_Guaranteed_ABE_Instantiation
+ (Inst : Node_Id;
+ Inst_Rep : Scenario_Rep_Id;
+ In_State : Processing_In_State)
+ is
+ Gen_Id : constant Entity_Id := Target (Inst_Rep);
+ Gen_Rep : constant Target_Rep_Id :=
+ Target_Representation_Of (Gen_Id, In_State);
+ Spec_Decl : constant Node_Id := Spec_Declaration (Gen_Rep);
+
+ Check_OK : constant Boolean :=
+ not In_State.Suppress_Checks
+ and then Ghost_Mode_Of (Inst_Rep) /= Is_Ignored
+ and then Ghost_Mode_Of (Gen_Rep) /= Is_Ignored
+ and then Elaboration_Checks_OK (Inst_Rep)
+ and then Elaboration_Checks_OK (Gen_Rep);
+ -- A run-time ABE check may be installed only when both the instance
+ -- and the generic have active elaboration checks and both are not
+ -- ignored Ghost constructs.
+
+ begin
+ -- Nothing to do when the root scenario appears at the declaration
+ -- level and the generic is in the same unit, but outside this
+ -- context.
+ --
+ -- generic
+ -- procedure Gen is ...; -- generic declaration
+ --
+ -- procedure Proc is
+ -- function A ... is
+ -- begin
+ -- if Some_Condition then
+ -- declare
+ -- procedure I is new Gen; -- instantiation site
+ -- ...
+ -- ...
+ -- end A;
+ --
+ -- X : ... := A; -- root scenario
+ -- ...
+ --
+ -- procedure Gen is
+ -- ...
+ -- end Gen;
+ --
+ -- In the example above, the context of X is the declarative region
+ -- of Proc. The "elaboration" of X may eventually reach Gen which
+ -- appears outside of X's context. Gen is relevant only when Proc is
+ -- invoked, but this happens only by means of "normal" elaboration,
+ -- therefore Gen must not be considered if this is not the case.
+
+ if Is_Up_Level_Target
+ (Targ_Decl => Spec_Decl,
+ In_State => In_State)
+ then
+ return;
+
+ -- Nothing to do when the instantiation is ABE-safe
+ --
+ -- generic
+ -- package Gen is
+ -- ...
+ -- end Gen;
+ --
+ -- package body Gen is
+ -- ...
+ -- end Gen;
+ --
+ -- with Gen;
+ -- procedure Main is
+ -- package Inst is new Gen (ABE); -- safe instantiation
+ -- ...
+
+ elsif Is_Safe_Instantiation (Inst, Gen_Id, Gen_Rep) then
+ return;
+
+ -- An instantiation leads to a guaranteed ABE when the instantiation
+ -- and the generic appear within the same context ignoring library
+ -- levels, and the body of the generic has not been seen yet or
+ -- appears after the instantiation.
+ --
+ -- procedure Guaranteed_ABE is
+ -- generic
+ -- procedure Gen;
+ --
+ -- package Nested is
+ -- procedure Inst is new Gen; -- guaranteed ABE
+ -- end Nested;
+ --
+ -- procedure Gen is
+ -- ...
+ -- end Gen;
+ -- ...
+
+ elsif Is_Guaranteed_ABE
+ (N => Inst,
+ Target_Decl => Spec_Decl,
+ Target_Body => Body_Declaration (Gen_Rep))
+ then
+ if Elaboration_Warnings_OK (Inst_Rep) then
+ Error_Msg_NE
+ ("??cannot instantiate & before body seen", Inst, Gen_Id);
+ Error_Msg_N ("\Program_Error will be raised at run time", Inst);
+ end if;
+
+ -- Mark the instantiation as a guarantee ABE. This automatically
+ -- suppresses the instantiation of the generic body.
+
+ Set_Is_Known_Guaranteed_ABE (Inst);
+
+ -- Install a run-time ABE failure because the instantiation will
+ -- always result in an ABE.
+
+ if Check_OK then
+ Install_Scenario_ABE_Failure
+ (N => Inst,
+ Targ_Id => Gen_Id,
+ Targ_Rep => Gen_Rep,
+ Disable => Inst_Rep);
+ end if;
+ end if;
+ end Process_Guaranteed_ABE_Instantiation;
+ end Guaranteed_ABE_Processor;
+
--------------
-- Has_Body --
--------------
function Has_Body (Pack_Decl : Node_Id) return Boolean is
function Find_Corresponding_Body (Spec_Id : Entity_Id) return Node_Id;
+ pragma Inline (Find_Corresponding_Body);
-- Try to locate the corresponding body of spec Spec_Id. If no body is
-- found, return Empty.
function Find_Body
(Spec_Id : Entity_Id;
From : Node_Id) return Node_Id;
+ pragma Inline (Find_Body);
-- Try to locate the corresponding body of spec Spec_Id in the node list
-- which follows arbitrary node From. If no body is found, return Empty.
function Load_Package_Body (Unit_Nam : Unit_Name_Type) return Node_Id;
+ pragma Inline (Load_Package_Body);
-- Attempt to load the body of unit Unit_Nam. If the load failed, return
-- Empty. If the compilation will not generate code, return Empty.
@@ -5823,60 +9849,15 @@ package body Sem_Elab is
end if;
end Has_Body;
- ---------------------------
- -- Has_Prior_Elaboration --
- ---------------------------
-
- function Has_Prior_Elaboration
- (Unit_Id : Entity_Id;
- Context_OK : Boolean := False;
- Elab_Body_OK : Boolean := False;
- Same_Unit_OK : Boolean := False) return Boolean
- is
- Main_Id : constant Entity_Id := Cunit_Entity (Main_Unit);
+ ----------
+ -- Hash --
+ ----------
+ function Hash (NE : Node_Or_Entity_Id) return Bucket_Range_Type is
+ pragma Assert (Present (NE));
begin
- -- A preelaborated unit is always elaborated prior to the main unit
-
- if Is_Preelaborated_Unit (Unit_Id) then
- return True;
-
- -- An internal unit is always elaborated prior to a non-internal main
- -- unit.
-
- elsif In_Internal_Unit (Unit_Id)
- and then not In_Internal_Unit (Main_Id)
- then
- return True;
-
- -- A unit has prior elaboration if it appears within the context of the
- -- main unit. Consider this case only when requested by the caller.
-
- elsif Context_OK
- and then Elaboration_Status (Unit_Id) /= No_Elaboration_Attributes
- then
- return True;
-
- -- A unit whose body is elaborated together with its spec has prior
- -- elaboration except with respect to itself. Consider this case only
- -- when requested by the caller.
-
- elsif Elab_Body_OK
- and then Has_Pragma_Elaborate_Body (Unit_Id)
- and then not Is_Same_Unit (Unit_Id, Main_Id)
- then
- return True;
-
- -- A unit has no prior elaboration with respect to itself, but does not
- -- require any means of ensuring its own elaboration either. Treat this
- -- case as valid prior elaboration only when requested by the caller.
-
- elsif Same_Unit_OK and then Is_Same_Unit (Unit_Id, Main_Id) then
- return True;
- end if;
-
- return False;
- end Has_Prior_Elaboration;
+ return Bucket_Range_Type (NE);
+ end Hash;
--------------------------
-- In_External_Instance --
@@ -5886,26 +9867,23 @@ package body Sem_Elab is
(N : Node_Id;
Target_Decl : Node_Id) return Boolean
is
- Dummy : Node_Id;
+ Inst : Node_Id;
Inst_Body : Node_Id;
- Inst_Decl : Node_Id;
+ Inst_Spec : Node_Id;
begin
- -- Performance note: parent traversal
-
- Inst_Decl := Find_Enclosing_Instance (Target_Decl);
+ Inst := Find_Enclosing_Instance (Target_Decl);
-- The target declaration appears within an instance spec. Visibility is
-- ignored because internally generated primitives for private types may
-- reside in the private declarations and still be invoked from outside.
- if Present (Inst_Decl)
- and then Nkind (Inst_Decl) = N_Package_Declaration
- then
+ if Present (Inst) and then Nkind (Inst) = N_Package_Declaration then
+
-- The scenario comes from the main unit and the instance does not
if In_Extended_Main_Code_Unit (N)
- and then not In_Extended_Main_Code_Unit (Inst_Decl)
+ and then not In_Extended_Main_Code_Unit (Inst)
then
return True;
@@ -5913,16 +9891,14 @@ package body Sem_Elab is
-- body.
else
- Extract_Instance_Attributes
- (Exp_Inst => Inst_Decl,
- Inst_Body => Inst_Body,
- Inst_Decl => Dummy);
-
- -- Performance note: parent traversal
+ Spec_And_Body_From_Node
+ (N => Inst,
+ Spec_Decl => Inst_Spec,
+ Body_Decl => Inst_Body);
return not In_Subtree
(N => N,
- Root1 => Inst_Decl,
+ Root1 => Inst_Spec,
Root2 => Inst_Body);
end if;
end if;
@@ -5962,6 +9938,7 @@ package body Sem_Elab is
Nested_OK : Boolean := False) return Boolean
is
function Find_Enclosing_Context (N : Node_Id) return Node_Id;
+ pragma Inline (Find_Enclosing_Context);
-- Return the nearest enclosing non-library-level or compilation unit
-- node which which encapsulates arbitrary node N. Return Empty is no
-- such context is available.
@@ -5969,6 +9946,7 @@ package body Sem_Elab is
function In_Nested_Context
(Outer : Node_Id;
Inner : Node_Id) return Boolean;
+ pragma Inline (In_Nested_Context);
-- Determine whether arbitrary node Outer encapsulates arbitrary node
-- Inner.
@@ -6084,5123 +10062,5588 @@ package body Sem_Elab is
return False;
end In_Same_Context;
- ------------------
- -- In_Task_Body --
- ------------------
+ ----------------
+ -- Initialize --
+ ----------------
- function In_Task_Body (N : Node_Id) return Boolean is
- Par : Node_Id;
+ procedure Initialize is
+ begin
+ -- Set the soft link which enables Atree.Rewrite to update a scenario
+ -- each time it is transformed into another node.
+
+ Set_Rewriting_Proc (Update_Elaboration_Scenario'Access);
+ end Initialize;
+
+ --------------------------
+ -- Instantiated_Generic --
+ --------------------------
+ function Instantiated_Generic (Inst : Node_Id) return Entity_Id is
begin
- -- Climb the parent chain looking for a task body [procedure]
+ -- Traverse a possible chain of renamings to obtain the original generic
+ -- being instantiatied.
- Par := N;
- while Present (Par) loop
- if Nkind (Par) = N_Task_Body then
- return True;
+ return Get_Renamed_Entity (Entity (Name (Inst)));
+ end Instantiated_Generic;
- elsif Nkind (Par) = N_Subprogram_Body
- and then Is_Task_Body_Procedure (Par)
- then
- return True;
+ -----------------------------
+ -- Internal_Representation --
+ -----------------------------
- -- Prevent the search from going too far. Note that this predicate
- -- shares nodes with the two cases above, and must come last.
+ package body Internal_Representation is
- elsif Is_Body_Or_Package_Declaration (Par) then
- return False;
- end if;
+ -----------
+ -- Types --
+ -----------
- Par := Parent (Par);
- end loop;
+ -- The following type represents the contents of a scenario
- return False;
- end In_Task_Body;
+ type Scenario_Rep_Record is record
+ Elab_Checks_OK : Boolean := False;
+ -- The status of elaboration checks for the scenario
- ----------------
- -- Initialize --
- ----------------
+ Elab_Warnings_OK : Boolean := False;
+ -- The status of elaboration warnings for the scenario
- procedure Initialize is
- begin
- -- Set the soft link which enables Atree.Rewrite to update a top-level
- -- scenario each time it is transformed into another node.
+ GM : Extended_Ghost_Mode := Is_Checked_Or_Not_Specified;
+ -- The Ghost mode of the scenario
- Set_Rewriting_Proc (Update_Elaboration_Scenario'Access);
- end Initialize;
+ Kind : Scenario_Kind := No_Scenario;
+ -- The nature of the scenario
- ---------------
- -- Info_Call --
- ---------------
+ Level : Enclosing_Level_Kind := No_Level;
+ -- The enclosing level where the scenario resides
- procedure Info_Call
- (Call : Node_Id;
- Target_Id : Entity_Id;
- Info_Msg : Boolean;
- In_SPARK : Boolean)
- is
- procedure Info_Accept_Alternative;
- pragma Inline (Info_Accept_Alternative);
- -- Output information concerning an accept alternative
-
- procedure Info_Simple_Call;
- pragma Inline (Info_Simple_Call);
- -- Output information concerning the call
-
- procedure Info_Type_Actions (Action : String);
- pragma Inline (Info_Type_Actions);
- -- Output information concerning action Action of a type
-
- procedure Info_Verification_Call
- (Pred : String;
- Id : Entity_Id;
- Id_Kind : String);
- pragma Inline (Info_Verification_Call);
- -- Output information concerning the verification of predicate Pred
- -- applied to related entity Id with kind Id_Kind.
+ SM : Extended_SPARK_Mode := Is_Off_Or_Not_Specified;
+ -- The SPARK mode of the scenario
- -----------------------------
- -- Info_Accept_Alternative --
- -----------------------------
+ Target : Entity_Id := Empty;
+ -- The target of the scenario
- procedure Info_Accept_Alternative is
- Entry_Id : constant Entity_Id := Receiving_Entry (Target_Id);
+ -- The following attributes are multiplexed and depend on the Kind of
+ -- the scenario. They are mapped as follows:
+ --
+ -- Call_Scenario
+ -- Is_Dispatching_Call (Flag_1)
+ --
+ -- Task_Activation_Scenario
+ -- Activated_Task_Objects (List_1)
+ -- Activated_Task_Type (Field_1)
+ --
+ -- Variable_Reference
+ -- Is_Read_Reference (Flag_1)
- begin
- pragma Assert (Present (Entry_Id));
+ Flag_1 : Boolean := False;
+ Field_1 : Node_Or_Entity_Id := Empty;
+ List_1 : NE_List.Doubly_Linked_List := NE_List.Nil;
+ end record;
- Elab_Msg_NE
- (Msg => "accept for entry & during elaboration",
- N => Call,
- Id => Entry_Id,
- Info_Msg => Info_Msg,
- In_SPARK => In_SPARK);
- end Info_Accept_Alternative;
+ -- The following type represents the contents of a target
- ----------------------
- -- Info_Simple_Call --
- ----------------------
+ type Target_Rep_Record is record
+ Body_Decl : Node_Id := Empty;
+ -- The declaration of the target body
- procedure Info_Simple_Call is
- begin
- Elab_Msg_NE
- (Msg => "call to & during elaboration",
- N => Call,
- Id => Target_Id,
- Info_Msg => Info_Msg,
- In_SPARK => In_SPARK);
- end Info_Simple_Call;
+ Elab_Checks_OK : Boolean := False;
+ -- The status of elaboration checks for the target
- -----------------------
- -- Info_Type_Actions --
- -----------------------
+ Elab_Warnings_OK : Boolean := False;
+ -- The status of elaboration warnings for the target
- procedure Info_Type_Actions (Action : String) is
- Typ : constant Entity_Id := First_Formal_Type (Target_Id);
+ GM : Extended_Ghost_Mode := Is_Checked_Or_Not_Specified;
+ -- The Ghost mode of the target
- begin
- pragma Assert (Present (Typ));
+ Kind : Target_Kind := No_Target;
+ -- The nature of the target
- Elab_Msg_NE
- (Msg => Action & " actions for type & during elaboration",
- N => Call,
- Id => Typ,
- Info_Msg => Info_Msg,
- In_SPARK => In_SPARK);
- end Info_Type_Actions;
+ SM : Extended_SPARK_Mode := Is_Off_Or_Not_Specified;
+ -- The SPARK mode of the target
- ----------------------------
- -- Info_Verification_Call --
- ----------------------------
+ Spec_Decl : Node_Id := Empty;
+ -- The declaration of the target spec
- procedure Info_Verification_Call
- (Pred : String;
- Id : Entity_Id;
- Id_Kind : String)
- is
- begin
- pragma Assert (Present (Id));
+ Unit : Entity_Id := Empty;
+ -- The top unit where the target is declared
- Elab_Msg_NE
- (Msg =>
- "verification of " & Pred & " of " & Id_Kind & " & during "
- & "elaboration",
- N => Call,
- Id => Id,
- Info_Msg => Info_Msg,
- In_SPARK => In_SPARK);
- end Info_Verification_Call;
+ Version : Representation_Kind := No_Representation;
+ -- The version of the target representation
- -- Start of processing for Info_Call
+ -- The following attributes are multiplexed and depend on the Kind of
+ -- the target. They are mapped as follows:
+ --
+ -- Subprogram_Target
+ -- Barrier_Body_Declaration (Field_1)
+ --
+ -- Variable_Target
+ -- Variable_Declaration (Field_1)
- begin
- -- Do not output anything for targets defined in internal units because
- -- this creates noise.
+ Field_1 : Node_Or_Entity_Id := Empty;
+ end record;
- if not In_Internal_Unit (Target_Id) then
+ ---------------------
+ -- Data structures --
+ ---------------------
- -- Accept alternative
+ procedure Destroy (T_Id : in out Target_Rep_Id);
+ -- Destroy a target representation T_Id
+
+ package ETT_Map is new Dynamic_Hash_Tables
+ (Key_Type => Entity_Id,
+ Value_Type => Target_Rep_Id,
+ No_Value => No_Target_Rep,
+ Expansion_Threshold => 1.5,
+ Expansion_Factor => 2,
+ Compression_Threshold => 0.3,
+ Compression_Factor => 2,
+ "=" => "=",
+ Destroy_Value => Destroy,
+ Hash => Hash);
+
+ -- The following map relates target representations to entities
+
+ Entity_To_Target_Map : ETT_Map.Dynamic_Hash_Table :=
+ ETT_Map.Create (500);
+
+ procedure Destroy (S_Id : in out Scenario_Rep_Id);
+ -- Destroy a scenario representation S_Id
+
+ package NTS_Map is new Dynamic_Hash_Tables
+ (Key_Type => Node_Id,
+ Value_Type => Scenario_Rep_Id,
+ No_Value => No_Scenario_Rep,
+ Expansion_Threshold => 1.5,
+ Expansion_Factor => 2,
+ Compression_Threshold => 0.3,
+ Compression_Factor => 2,
+ "=" => "=",
+ Destroy_Value => Destroy,
+ Hash => Hash);
+
+ -- The following map relates scenario representations to nodes
+
+ Node_To_Scenario_Map : NTS_Map.Dynamic_Hash_Table :=
+ NTS_Map.Create (500);
+
+ -- The following table stores all scenario representations
+
+ package Scenario_Reps is new Table.Table
+ (Table_Index_Type => Scenario_Rep_Id,
+ Table_Component_Type => Scenario_Rep_Record,
+ Table_Low_Bound => First_Scenario_Rep,
+ Table_Initial => 1000,
+ Table_Increment => 200,
+ Table_Name => "Scenario_Reps");
+
+ -- The following table stores all target representations
+
+ package Target_Reps is new Table.Table
+ (Table_Index_Type => Target_Rep_Id,
+ Table_Component_Type => Target_Rep_Record,
+ Table_Low_Bound => First_Target_Rep,
+ Table_Initial => 1000,
+ Table_Increment => 200,
+ Table_Name => "Target_Reps");
- if Is_Accept_Alternative_Proc (Target_Id) then
- Info_Accept_Alternative;
+ --------------
+ -- Builders --
+ --------------
- -- Adjustment
+ function Create_Access_Taken_Rep
+ (Attr : Node_Id) return Scenario_Rep_Record;
+ pragma Inline (Create_Access_Taken_Rep);
+ -- Create the representation of 'Access attribute Attr
+
+ function Create_Call_Or_Task_Activation_Rep
+ (Call : Node_Id) return Scenario_Rep_Record;
+ pragma Inline (Create_Call_Or_Task_Activation_Rep);
+ -- Create the representation of call or task activation Call
+
+ function Create_Derived_Type_Rep
+ (Typ_Decl : Node_Id) return Scenario_Rep_Record;
+ pragma Inline (Create_Derived_Type_Rep);
+ -- Create the representation of a derived type described by declaration
+ -- Typ_Decl.
+
+ function Create_Generic_Rep
+ (Gen_Id : Entity_Id) return Target_Rep_Record;
+ pragma Inline (Create_Generic_Rep);
+ -- Create the representation of generic Gen_Id
+
+ function Create_Instantiation_Rep
+ (Inst : Node_Id) return Scenario_Rep_Record;
+ pragma Inline (Create_Instantiation_Rep);
+ -- Create the representation of instantiation Inst
+
+ function Create_Protected_Entry_Rep
+ (PE_Id : Entity_Id) return Target_Rep_Record;
+ pragma Inline (Create_Protected_Entry_Rep);
+ -- Create the representation of protected entry PE_Id
+
+ function Create_Protected_Subprogram_Rep
+ (PS_Id : Entity_Id) return Target_Rep_Record;
+ pragma Inline (Create_Protected_Subprogram_Rep);
+ -- Create the representation of protected subprogram PS_Id
+
+ function Create_Refined_State_Pragma_Rep
+ (Prag : Node_Id) return Scenario_Rep_Record;
+ pragma Inline (Create_Refined_State_Pragma_Rep);
+ -- Create the representation of Refined_State pragma Prag
+
+ function Create_Scenario_Rep
+ (N : Node_Id;
+ In_State : Processing_In_State) return Scenario_Rep_Record;
+ pragma Inline (Create_Scenario_Rep);
+ -- Top level dispatcher. Create the representation of elaboration
+ -- scenario N. In_State is the current state of the Processing phase.
+
+ function Create_Subprogram_Rep
+ (Subp_Id : Entity_Id) return Target_Rep_Record;
+ pragma Inline (Create_Subprogram_Rep);
+ -- Create the representation of entry, operator, or subprogram Subp_Id
+
+ function Create_Target_Rep
+ (Id : Entity_Id;
+ In_State : Processing_In_State) return Target_Rep_Record;
+ pragma Inline (Create_Target_Rep);
+ -- Top level dispatcher. Create the representation of elaboration target
+ -- Id. In_State is the current state of the Processing phase.
+
+ function Create_Task_Entry_Rep
+ (TE_Id : Entity_Id) return Target_Rep_Record;
+ pragma Inline (Create_Task_Entry_Rep);
+ -- Create the representation of task entry TE_Id
+
+ function Create_Task_Rep (Task_Typ : Entity_Id) return Target_Rep_Record;
+ pragma Inline (Create_Task_Rep);
+ -- Create the representation of task type Typ
+
+ function Create_Variable_Assignment_Rep
+ (Asmt : Node_Id) return Scenario_Rep_Record;
+ pragma Inline (Create_Variable_Assignment_Rep);
+ -- Create the representation of variable assignment Asmt
+
+ function Create_Variable_Reference_Rep
+ (Ref : Node_Id) return Scenario_Rep_Record;
+ pragma Inline (Create_Variable_Reference_Rep);
+ -- Create the representation of variable reference Ref
+
+ function Create_Variable_Rep
+ (Var_Id : Entity_Id) return Target_Rep_Record;
+ pragma Inline (Create_Variable_Rep);
+ -- Create the representation of variable Var_Id
- elsif Is_TSS (Target_Id, TSS_Deep_Adjust) then
- Info_Type_Actions ("adjustment");
+ -----------------------
+ -- Local subprograms --
+ -----------------------
- -- Default_Initial_Condition
+ function Ghost_Mode_Of_Entity
+ (Id : Entity_Id) return Extended_Ghost_Mode;
+ pragma Inline (Ghost_Mode_Of_Entity);
+ -- Obtain the extended Ghost mode of arbitrary entity Id
- elsif Is_Default_Initial_Condition_Proc (Target_Id) then
- Info_Verification_Call
- (Pred => "Default_Initial_Condition",
- Id => First_Formal_Type (Target_Id),
- Id_Kind => "type");
+ function Ghost_Mode_Of_Node (N : Node_Id) return Extended_Ghost_Mode;
+ pragma Inline (Ghost_Mode_Of_Node);
+ -- Obtain the extended Ghost mode of arbitrary node N
- -- Entries
+ function Present (S_Id : Scenario_Rep_Id) return Boolean;
+ pragma Inline (Present);
+ -- Determine whether scenario representation S_Id exists
- elsif Is_Protected_Entry (Target_Id) then
- Info_Simple_Call;
+ function Present (T_Id : Target_Rep_Id) return Boolean;
+ pragma Inline (Present);
+ -- Determine whether target representation T_Id exists
- -- Task entry calls are never processed because the entry being
- -- invoked does not have a corresponding "body", it has a select.
+ function SPARK_Mode_Of_Entity
+ (Id : Entity_Id) return Extended_SPARK_Mode;
+ pragma Inline (SPARK_Mode_Of_Entity);
+ -- Obtain the extended SPARK mode of arbitrary entity Id
- elsif Is_Task_Entry (Target_Id) then
- null;
+ function SPARK_Mode_Of_Node (N : Node_Id) return Extended_SPARK_Mode;
+ pragma Inline (SPARK_Mode_Of_Node);
+ -- Obtain the extended SPARK mode of arbitrary node N
- -- Finalization
+ function To_Ghost_Mode
+ (Ignored_Status : Boolean) return Extended_Ghost_Mode;
+ pragma Inline (To_Ghost_Mode);
+ -- Convert a Ghost mode indicated by Ignored_Status into its extended
+ -- equivalent.
- elsif Is_TSS (Target_Id, TSS_Deep_Finalize) then
- Info_Type_Actions ("finalization");
+ function To_SPARK_Mode (On_Status : Boolean) return Extended_SPARK_Mode;
+ pragma Inline (To_SPARK_Mode);
+ -- Convert a SPARK mode indicated by On_Status into its extended
+ -- equivalent.
- -- Calls to _Finalizer procedures must not appear in the output
- -- because this creates confusing noise.
+ function Version (T_Id : Target_Rep_Id) return Representation_Kind;
+ pragma Inline (Version);
+ -- Obtain the version of target representation T_Id
- elsif Is_Finalizer_Proc (Target_Id) then
- null;
+ ----------------------------
+ -- Activated_Task_Objects --
+ ----------------------------
- -- Initial_Condition
+ function Activated_Task_Objects
+ (S_Id : Scenario_Rep_Id) return NE_List.Doubly_Linked_List
+ is
+ pragma Assert (Present (S_Id));
+ pragma Assert (Kind (S_Id) = Task_Activation_Scenario);
- elsif Is_Initial_Condition_Proc (Target_Id) then
- Info_Verification_Call
- (Pred => "Initial_Condition",
- Id => Find_Enclosing_Scope (Call),
- Id_Kind => "package");
+ begin
+ return Scenario_Reps.Table (S_Id).List_1;
+ end Activated_Task_Objects;
- -- Initialization
+ -------------------------
+ -- Activated_Task_Type --
+ -------------------------
- elsif Is_Init_Proc (Target_Id)
- or else Is_TSS (Target_Id, TSS_Deep_Initialize)
- then
- Info_Type_Actions ("initialization");
+ function Activated_Task_Type
+ (S_Id : Scenario_Rep_Id) return Entity_Id
+ is
+ pragma Assert (Present (S_Id));
+ pragma Assert (Kind (S_Id) = Task_Activation_Scenario);
- -- Invariant
+ begin
+ return Scenario_Reps.Table (S_Id).Field_1;
+ end Activated_Task_Type;
- elsif Is_Invariant_Proc (Target_Id) then
- Info_Verification_Call
- (Pred => "invariants",
- Id => First_Formal_Type (Target_Id),
- Id_Kind => "type");
+ ------------------------------
+ -- Barrier_Body_Declaration --
+ ------------------------------
- -- Partial invariant calls must not appear in the output because this
- -- creates confusing noise.
+ function Barrier_Body_Declaration
+ (T_Id : Target_Rep_Id) return Node_Id
+ is
+ pragma Assert (Present (T_Id));
+ pragma Assert (Kind (T_Id) = Subprogram_Target);
- elsif Is_Partial_Invariant_Proc (Target_Id) then
- null;
+ begin
+ return Target_Reps.Table (T_Id).Field_1;
+ end Barrier_Body_Declaration;
- -- _Postconditions
+ ----------------------
+ -- Body_Declaration --
+ ----------------------
- elsif Is_Postconditions_Proc (Target_Id) then
- Info_Verification_Call
- (Pred => "postconditions",
- Id => Find_Enclosing_Scope (Call),
- Id_Kind => "subprogram");
+ function Body_Declaration (T_Id : Target_Rep_Id) return Node_Id is
+ pragma Assert (Present (T_Id));
+ begin
+ return Target_Reps.Table (T_Id).Body_Decl;
+ end Body_Declaration;
- -- Subprograms must come last because some of the previous cases fall
- -- under this category.
+ -----------------------------
+ -- Create_Access_Taken_Rep --
+ -----------------------------
- elsif Ekind (Target_Id) = E_Function then
- Info_Simple_Call;
+ function Create_Access_Taken_Rep
+ (Attr : Node_Id) return Scenario_Rep_Record
+ is
+ Rec : Scenario_Rep_Record;
+
+ begin
+ Rec.Elab_Checks_OK := Is_Elaboration_Checks_OK_Node (Attr);
+ Rec.Elab_Warnings_OK := Is_Elaboration_Warnings_OK_Node (Attr);
+ Rec.GM := Is_Checked_Or_Not_Specified;
+ Rec.SM := SPARK_Mode_Of_Node (Attr);
+ Rec.Kind := Access_Taken_Scenario;
+ Rec.Target := Canonical_Subprogram (Entity (Prefix (Attr)));
+
+ return Rec;
+ end Create_Access_Taken_Rep;
+
+ ----------------------------------------
+ -- Create_Call_Or_Task_Activation_Rep --
+ ----------------------------------------
- elsif Ekind (Target_Id) = E_Procedure then
- Info_Simple_Call;
+ function Create_Call_Or_Task_Activation_Rep
+ (Call : Node_Id) return Scenario_Rep_Record
+ is
+ Subp_Id : constant Entity_Id := Canonical_Subprogram (Target (Call));
+ Kind : Scenario_Kind;
+ Rec : Scenario_Rep_Record;
+ begin
+ if Is_Activation_Proc (Subp_Id) then
+ Kind := Task_Activation_Scenario;
else
- pragma Assert (False);
- null;
+ Kind := Call_Scenario;
end if;
- end if;
- end Info_Call;
- ------------------------
- -- Info_Instantiation --
- ------------------------
+ Rec.Elab_Checks_OK := Is_Elaboration_Checks_OK_Node (Call);
+ Rec.Elab_Warnings_OK := Is_Elaboration_Warnings_OK_Node (Call);
+ Rec.GM := Ghost_Mode_Of_Node (Call);
+ Rec.SM := SPARK_Mode_Of_Node (Call);
+ Rec.Kind := Kind;
+ Rec.Target := Subp_Id;
- procedure Info_Instantiation
- (Inst : Node_Id;
- Gen_Id : Entity_Id;
- Info_Msg : Boolean;
- In_SPARK : Boolean)
- is
- begin
- Elab_Msg_NE
- (Msg => "instantiation of & during elaboration",
- N => Inst,
- Id => Gen_Id,
- Info_Msg => Info_Msg,
- In_SPARK => In_SPARK);
- end Info_Instantiation;
+ -- Scenario-specific attributes
- -----------------------------
- -- Info_Variable_Reference --
- -----------------------------
+ Rec.Flag_1 := Is_Dispatching_Call (Call); -- Dispatching_Call
- procedure Info_Variable_Reference
- (Ref : Node_Id;
- Var_Id : Entity_Id;
- Info_Msg : Boolean;
- In_SPARK : Boolean)
- is
- begin
- if Is_Read (Ref) then
- Elab_Msg_NE
- (Msg => "read of variable & during elaboration",
- N => Ref,
- Id => Var_Id,
- Info_Msg => Info_Msg,
- In_SPARK => In_SPARK);
- end if;
- end Info_Variable_Reference;
+ return Rec;
+ end Create_Call_Or_Task_Activation_Rep;
- --------------------
- -- Insertion_Node --
- --------------------
+ -----------------------------
+ -- Create_Derived_Type_Rep --
+ -----------------------------
- function Insertion_Node (N : Node_Id; Ins_Nod : Node_Id) return Node_Id is
- begin
- -- When the scenario denotes an instantiation, the proper insertion node
- -- is the instance spec. This ensures that the generic actuals will not
- -- be evaluated prior to a potential ABE.
+ function Create_Derived_Type_Rep
+ (Typ_Decl : Node_Id) return Scenario_Rep_Record
+ is
+ Typ : constant Entity_Id := Defining_Entity (Typ_Decl);
+ Rec : Scenario_Rep_Record;
- if Nkind (N) in N_Generic_Instantiation
- and then Present (Instance_Spec (N))
- then
- return Instance_Spec (N);
+ begin
+ Rec.Elab_Checks_OK := False; -- not relevant
+ Rec.Elab_Warnings_OK := False; -- not relevant
+ Rec.GM := Ghost_Mode_Of_Entity (Typ);
+ Rec.SM := SPARK_Mode_Of_Entity (Typ);
+ Rec.Kind := Derived_Type_Scenario;
+ Rec.Target := Typ;
+
+ return Rec;
+ end Create_Derived_Type_Rep;
+
+ ------------------------
+ -- Create_Generic_Rep --
+ ------------------------
+
+ function Create_Generic_Rep
+ (Gen_Id : Entity_Id) return Target_Rep_Record
+ is
+ Rec : Target_Rep_Record;
- -- Otherwise the proper insertion node is the candidate insertion node
+ begin
+ Rec.Kind := Generic_Target;
- else
- return Ins_Nod;
- end if;
- end Insertion_Node;
+ Spec_And_Body_From_Entity
+ (Id => Gen_Id,
+ Body_Decl => Rec.Body_Decl,
+ Spec_Decl => Rec.Spec_Decl);
- -----------------------
- -- Install_ABE_Check --
- -----------------------
+ return Rec;
+ end Create_Generic_Rep;
- procedure Install_ABE_Check
- (N : Node_Id;
- Id : Entity_Id;
- Ins_Nod : Node_Id)
- is
- Check_Ins_Nod : constant Node_Id := Insertion_Node (N, Ins_Nod);
- -- Insert the check prior to this node
+ ------------------------------
+ -- Create_Instantiation_Rep --
+ ------------------------------
- Loc : constant Source_Ptr := Sloc (N);
- Spec_Id : constant Entity_Id := Unique_Entity (Id);
- Unit_Id : constant Entity_Id := Find_Top_Unit (Id);
- Scop_Id : Entity_Id;
+ function Create_Instantiation_Rep
+ (Inst : Node_Id) return Scenario_Rep_Record
+ is
+ Rec : Scenario_Rep_Record;
- begin
- -- Nothing to do when compiling for GNATprove because raise statements
- -- are not supported.
+ begin
+ Rec.Elab_Checks_OK := Is_Elaboration_Checks_OK_Node (Inst);
+ Rec.Elab_Warnings_OK := Is_Elaboration_Warnings_OK_Node (Inst);
+ Rec.GM := Ghost_Mode_Of_Node (Inst);
+ Rec.SM := SPARK_Mode_Of_Node (Inst);
+ Rec.Kind := Instantiation_Scenario;
+ Rec.Target := Instantiated_Generic (Inst);
- if GNATprove_Mode then
- return;
+ return Rec;
+ end Create_Instantiation_Rep;
- -- Nothing to do when the compilation will not produce an executable
+ --------------------------------
+ -- Create_Protected_Entry_Rep --
+ --------------------------------
- elsif Serious_Errors_Detected > 0 then
- return;
+ function Create_Protected_Entry_Rep
+ (PE_Id : Entity_Id) return Target_Rep_Record
+ is
+ Prot_Id : constant Entity_Id := Protected_Body_Subprogram (PE_Id);
- -- Nothing to do for a compilation unit because there is no executable
- -- environment at that level.
+ Barf_Id : Entity_Id;
+ Dummy : Node_Id;
+ Rec : Target_Rep_Record;
+ Spec_Id : Entity_Id;
- elsif Nkind (Parent (Check_Ins_Nod)) = N_Compilation_Unit then
- return;
+ begin
+ -- When the entry [family] has already been expanded, it carries both
+ -- the procedure which emulates the behavior of the entry [family] as
+ -- well as the barrier function.
- -- Nothing to do when the unit is elaborated prior to the main unit.
- -- This check must also consider the following cases:
+ if Present (Prot_Id) then
+ Barf_Id := Barrier_Function (PE_Id);
+ Spec_Id := Prot_Id;
- -- * Id's unit appears in the context of the main unit
+ -- Otherwise no expansion took place
- -- * Id's unit is subject to pragma Elaborate_Body. An ABE check MUST
- -- NOT be generated because Id's unit is always elaborated prior to
- -- the main unit.
+ else
+ Barf_Id := Empty;
+ Spec_Id := PE_Id;
+ end if;
- -- * Id's unit is the main unit. An ABE check MUST be generated in this
- -- case because a conditional ABE may be raised depending on the flow
- -- of execution within the main unit (flag Same_Unit_OK is False).
+ Rec.Kind := Subprogram_Target;
- elsif Has_Prior_Elaboration
- (Unit_Id => Unit_Id,
- Context_OK => True,
- Elab_Body_OK => True)
- then
- return;
- end if;
+ Spec_And_Body_From_Entity
+ (Id => Spec_Id,
+ Body_Decl => Rec.Body_Decl,
+ Spec_Decl => Rec.Spec_Decl);
- -- Prevent multiple scenarios from installing the same ABE check
+ -- Target-specific attributes
- Set_Is_Elaboration_Checks_OK_Node (N, False);
+ if Present (Barf_Id) then
+ Spec_And_Body_From_Entity
+ (Id => Barf_Id,
+ Body_Decl => Rec.Field_1, -- Barrier_Body_Declaration
+ Spec_Decl => Dummy);
+ end if;
- -- Install the nearest enclosing scope of the scenario as there must be
- -- something on the scope stack.
+ return Rec;
+ end Create_Protected_Entry_Rep;
- -- Performance note: parent traversal
+ -------------------------------------
+ -- Create_Protected_Subprogram_Rep --
+ -------------------------------------
- Scop_Id := Find_Enclosing_Scope (Check_Ins_Nod);
- pragma Assert (Present (Scop_Id));
+ function Create_Protected_Subprogram_Rep
+ (PS_Id : Entity_Id) return Target_Rep_Record
+ is
+ Prot_Id : constant Entity_Id := Protected_Body_Subprogram (PS_Id);
+ Rec : Target_Rep_Record;
+ Spec_Id : Entity_Id;
- Push_Scope (Scop_Id);
+ begin
+ -- When the protected subprogram has already been expanded, it
+ -- carries the subprogram which seizes the lock and invokes the
+ -- original statements.
- -- Generate:
- -- if not Spec_Id'Elaborated then
- -- raise Program_Error with "access before elaboration";
- -- end if;
+ if Present (Prot_Id) then
+ Spec_Id := Prot_Id;
- Insert_Action (Check_Ins_Nod,
- Make_Raise_Program_Error (Loc,
- Condition =>
- Make_Op_Not (Loc,
- Right_Opnd =>
- Make_Attribute_Reference (Loc,
- Prefix => New_Occurrence_Of (Spec_Id, Loc),
- Attribute_Name => Name_Elaborated)),
- Reason => PE_Access_Before_Elaboration));
+ -- Otherwise no expansion took place
- Pop_Scope;
- end Install_ABE_Check;
+ else
+ Spec_Id := PS_Id;
+ end if;
- -----------------------
- -- Install_ABE_Check --
- -----------------------
+ Rec.Kind := Subprogram_Target;
- procedure Install_ABE_Check
- (N : Node_Id;
- Target_Id : Entity_Id;
- Target_Decl : Node_Id;
- Target_Body : Node_Id;
- Ins_Nod : Node_Id)
- is
- procedure Build_Elaboration_Entity;
- pragma Inline (Build_Elaboration_Entity);
- -- Create a new elaboration flag for Target_Id, insert it prior to
- -- Target_Decl, and set it after Body_Decl.
+ Spec_And_Body_From_Entity
+ (Id => Spec_Id,
+ Body_Decl => Rec.Body_Decl,
+ Spec_Decl => Rec.Spec_Decl);
- ------------------------------
- -- Build_Elaboration_Entity --
- ------------------------------
+ return Rec;
+ end Create_Protected_Subprogram_Rep;
+
+ -------------------------------------
+ -- Create_Refined_State_Pragma_Rep --
+ -------------------------------------
- procedure Build_Elaboration_Entity is
- Loc : constant Source_Ptr := Sloc (Target_Id);
- Flag_Id : Entity_Id;
+ function Create_Refined_State_Pragma_Rep
+ (Prag : Node_Id) return Scenario_Rep_Record
+ is
+ Rec : Scenario_Rep_Record;
begin
- -- Create the declaration of the elaboration flag. The name carries a
- -- unique counter in case of name overloading.
+ Rec.Elab_Checks_OK := False; -- not relevant
+ Rec.Elab_Warnings_OK := False; -- not relevant
+ Rec.GM :=
+ To_Ghost_Mode (Is_Ignored_Ghost_Pragma (Prag));
+ Rec.SM := Is_Off_Or_Not_Specified;
+ Rec.Kind := Refined_State_Pragma_Scenario;
+ Rec.Target := Empty;
- Flag_Id :=
- Make_Defining_Identifier (Loc,
- Chars => New_External_Name (Chars (Target_Id), 'E', -1));
+ return Rec;
+ end Create_Refined_State_Pragma_Rep;
- Set_Elaboration_Entity (Target_Id, Flag_Id);
- Set_Elaboration_Entity_Required (Target_Id);
+ -------------------------
+ -- Create_Scenario_Rep --
+ -------------------------
- Push_Scope (Scope (Target_Id));
+ function Create_Scenario_Rep
+ (N : Node_Id;
+ In_State : Processing_In_State) return Scenario_Rep_Record
+ is
+ pragma Unreferenced (In_State);
- -- Generate:
- -- Enn : Short_Integer := 0;
+ Rec : Scenario_Rep_Record;
- Insert_Action (Target_Decl,
- Make_Object_Declaration (Loc,
- Defining_Identifier => Flag_Id,
- Object_Definition =>
- New_Occurrence_Of (Standard_Short_Integer, Loc),
- Expression => Make_Integer_Literal (Loc, Uint_0)));
+ begin
+ if Is_Suitable_Access_Taken (N) then
+ Rec := Create_Access_Taken_Rep (N);
- -- Generate:
- -- Enn := 1;
+ elsif Is_Suitable_Call (N) then
+ Rec := Create_Call_Or_Task_Activation_Rep (N);
- Set_Elaboration_Flag (Target_Body, Target_Id);
+ elsif Is_Suitable_Instantiation (N) then
+ Rec := Create_Instantiation_Rep (N);
- Pop_Scope;
- end Build_Elaboration_Entity;
+ elsif Is_Suitable_SPARK_Derived_Type (N) then
+ Rec := Create_Derived_Type_Rep (N);
- -- Local variables
+ elsif Is_Suitable_SPARK_Refined_State_Pragma (N) then
+ Rec := Create_Refined_State_Pragma_Rep (N);
- Target_Unit_Id : constant Entity_Id := Find_Top_Unit (Target_Id);
+ elsif Is_Suitable_Variable_Assignment (N) then
+ Rec := Create_Variable_Assignment_Rep (N);
- -- Start for processing for Install_ABE_Check
+ elsif Is_Suitable_Variable_Reference (N) then
+ Rec := Create_Variable_Reference_Rep (N);
- begin
- -- Nothing to do when compiling for GNATprove because raise statements
- -- are not supported.
+ else
+ pragma Assert (False);
+ return Rec;
+ end if;
- if GNATprove_Mode then
- return;
+ -- Common scenario attributes
- -- Nothing to do when the compilation will not produce an executable
+ Rec.Level := Find_Enclosing_Level (N);
- elsif Serious_Errors_Detected > 0 then
- return;
+ return Rec;
+ end Create_Scenario_Rep;
- -- Nothing to do when the target is a protected subprogram because the
- -- check is associated with the protected body subprogram.
+ ---------------------------
+ -- Create_Subprogram_Rep --
+ ---------------------------
- elsif Is_Protected_Subp (Target_Id) then
- return;
+ function Create_Subprogram_Rep
+ (Subp_Id : Entity_Id) return Target_Rep_Record
+ is
+ Rec : Target_Rep_Record;
+ Spec_Id : Entity_Id;
- -- Nothing to do when the target is elaborated prior to the main unit.
- -- This check must also consider the following cases:
+ begin
+ Spec_Id := Subp_Id;
- -- * The unit of the target appears in the context of the main unit
+ -- The elaboration target denotes an internal function that returns a
+ -- constrained array type in a SPARK-to-C compilation. In this case
+ -- the function receives a corresponding procedure which has an out
+ -- parameter. The proper body for ABE checks and diagnostics is that
+ -- of the procedure.
- -- * The unit of the target is subject to pragma Elaborate_Body. An ABE
- -- check MUST NOT be generated because the unit is always elaborated
- -- prior to the main unit.
+ if Ekind (Spec_Id) = E_Function
+ and then Rewritten_For_C (Spec_Id)
+ then
+ Spec_Id := Corresponding_Procedure (Spec_Id);
+ end if;
- -- * The unit of the target is the main unit. An ABE check MUST be added
- -- in this case because a conditional ABE may be raised depending on
- -- the flow of execution within the main unit (flag Same_Unit_OK is
- -- False).
+ Rec.Kind := Subprogram_Target;
- elsif Has_Prior_Elaboration
- (Unit_Id => Target_Unit_Id,
- Context_OK => True,
- Elab_Body_OK => True)
- then
- return;
+ Spec_And_Body_From_Entity
+ (Id => Spec_Id,
+ Body_Decl => Rec.Body_Decl,
+ Spec_Decl => Rec.Spec_Decl);
- -- Create an elaboration flag for the target when it does not have one
+ return Rec;
+ end Create_Subprogram_Rep;
- elsif No (Elaboration_Entity (Target_Id)) then
- Build_Elaboration_Entity;
- end if;
+ -----------------------
+ -- Create_Target_Rep --
+ -----------------------
- Install_ABE_Check
- (N => N,
- Ins_Nod => Ins_Nod,
- Id => Target_Id);
- end Install_ABE_Check;
+ function Create_Target_Rep
+ (Id : Entity_Id;
+ In_State : Processing_In_State) return Target_Rep_Record
+ is
+ Rec : Target_Rep_Record;
- -------------------------
- -- Install_ABE_Failure --
- -------------------------
+ begin
+ if Is_Generic_Unit (Id) then
+ Rec := Create_Generic_Rep (Id);
- procedure Install_ABE_Failure (N : Node_Id; Ins_Nod : Node_Id) is
- Fail_Ins_Nod : constant Node_Id := Insertion_Node (N, Ins_Nod);
- -- Insert the failure prior to this node
+ elsif Is_Protected_Entry (Id) then
+ Rec := Create_Protected_Entry_Rep (Id);
- Loc : constant Source_Ptr := Sloc (N);
- Scop_Id : Entity_Id;
+ elsif Is_Protected_Subp (Id) then
+ Rec := Create_Protected_Subprogram_Rep (Id);
- begin
- -- Nothing to do when compiling for GNATprove because raise statements
- -- are not supported.
+ elsif Is_Task_Entry (Id) then
+ Rec := Create_Task_Entry_Rep (Id);
- if GNATprove_Mode then
- return;
+ elsif Is_Task_Type (Id) then
+ Rec := Create_Task_Rep (Id);
- -- Nothing to do when the compilation will not produce an executable
+ elsif Ekind_In (Id, E_Constant, E_Variable) then
+ Rec := Create_Variable_Rep (Id);
- elsif Serious_Errors_Detected > 0 then
- return;
+ elsif Ekind_In (Id, E_Entry,
+ E_Function,
+ E_Operator,
+ E_Procedure)
+ then
+ Rec := Create_Subprogram_Rep (Id);
- -- Do not install an ABE check for a compilation unit because there is
- -- no executable environment at that level.
+ else
+ pragma Assert (False);
+ return Rec;
+ end if;
- elsif Nkind (Parent (Fail_Ins_Nod)) = N_Compilation_Unit then
- return;
- end if;
+ -- Common target attributes
+
+ Rec.Elab_Checks_OK := Is_Elaboration_Checks_OK_Id (Id);
+ Rec.Elab_Warnings_OK := Is_Elaboration_Warnings_OK_Id (Id);
+ Rec.GM := Ghost_Mode_Of_Entity (Id);
+ Rec.SM := SPARK_Mode_Of_Entity (Id);
+ Rec.Unit := Find_Top_Unit (Id);
+ Rec.Version := In_State.Representation;
+
+ return Rec;
+ end Create_Target_Rep;
+
+ ---------------------------
+ -- Create_Task_Entry_Rep --
+ ---------------------------
- -- Prevent multiple scenarios from installing the same ABE failure
+ function Create_Task_Entry_Rep
+ (TE_Id : Entity_Id) return Target_Rep_Record
+ is
+ Task_Typ : constant Entity_Id := Non_Private_View (Scope (TE_Id));
+ Task_Body_Id : constant Entity_Id := Task_Body_Procedure (Task_Typ);
- Set_Is_Elaboration_Checks_OK_Node (N, False);
+ Rec : Target_Rep_Record;
+ Spec_Id : Entity_Id;
+
+ begin
+ -- The the task type has already been expanded, it carries the
+ -- procedure which emulates the behavior of the task body.
- -- Install the nearest enclosing scope of the scenario as there must be
- -- something on the scope stack.
+ if Present (Task_Body_Id) then
+ Spec_Id := Task_Body_Id;
- -- Performance note: parent traversal
+ -- Otherwise no expansion took place
- Scop_Id := Find_Enclosing_Scope (Fail_Ins_Nod);
- pragma Assert (Present (Scop_Id));
+ else
+ Spec_Id := TE_Id;
+ end if;
- Push_Scope (Scop_Id);
+ Rec.Kind := Subprogram_Target;
- -- Generate:
- -- raise Program_Error with "access before elaboration";
+ Spec_And_Body_From_Entity
+ (Id => Spec_Id,
+ Body_Decl => Rec.Body_Decl,
+ Spec_Decl => Rec.Spec_Decl);
- Insert_Action (Fail_Ins_Nod,
- Make_Raise_Program_Error (Loc,
- Reason => PE_Access_Before_Elaboration));
+ return Rec;
+ end Create_Task_Entry_Rep;
- Pop_Scope;
- end Install_ABE_Failure;
+ ---------------------
+ -- Create_Task_Rep --
+ ---------------------
- --------------------------------
- -- Is_Accept_Alternative_Proc --
- --------------------------------
+ function Create_Task_Rep
+ (Task_Typ : Entity_Id) return Target_Rep_Record
+ is
+ Task_Body_Id : constant Entity_Id := Task_Body_Procedure (Task_Typ);
- function Is_Accept_Alternative_Proc (Id : Entity_Id) return Boolean is
- begin
- -- To qualify, the entity must denote a procedure with a receiving entry
+ Rec : Target_Rep_Record;
+ Spec_Id : Entity_Id;
- return Ekind (Id) = E_Procedure and then Present (Receiving_Entry (Id));
- end Is_Accept_Alternative_Proc;
+ begin
+ -- The the task type has already been expanded, it carries the
+ -- procedure which emulates the behavior of the task body.
- ------------------------
- -- Is_Activation_Proc --
- ------------------------
+ if Present (Task_Body_Id) then
+ Spec_Id := Task_Body_Id;
- function Is_Activation_Proc (Id : Entity_Id) return Boolean is
- begin
- -- To qualify, the entity must denote one of the runtime procedures in
- -- charge of task activation.
+ -- Otherwise no expansion took place
- if Ekind (Id) = E_Procedure then
- if Restricted_Profile then
- return Is_RTE (Id, RE_Activate_Restricted_Tasks);
else
- return Is_RTE (Id, RE_Activate_Tasks);
+ Spec_Id := Task_Typ;
end if;
- end if;
- return False;
- end Is_Activation_Proc;
+ Rec.Kind := Task_Target;
- ----------------------------
- -- Is_Ada_Semantic_Target --
- ----------------------------
+ Spec_And_Body_From_Entity
+ (Id => Spec_Id,
+ Body_Decl => Rec.Body_Decl,
+ Spec_Decl => Rec.Spec_Decl);
- function Is_Ada_Semantic_Target (Id : Entity_Id) return Boolean is
- begin
- return
- Is_Activation_Proc (Id)
- or else Is_Controlled_Proc (Id, Name_Adjust)
- or else Is_Controlled_Proc (Id, Name_Finalize)
- or else Is_Controlled_Proc (Id, Name_Initialize)
- or else Is_Init_Proc (Id)
- or else Is_Invariant_Proc (Id)
- or else Is_Protected_Entry (Id)
- or else Is_Protected_Subp (Id)
- or else Is_Protected_Body_Subp (Id)
- or else Is_Task_Entry (Id);
- end Is_Ada_Semantic_Target;
+ return Rec;
+ end Create_Task_Rep;
- --------------------------------
- -- Is_Assertion_Pragma_Target --
- --------------------------------
+ ------------------------------------
+ -- Create_Variable_Assignment_Rep --
+ ------------------------------------
- function Is_Assertion_Pragma_Target (Id : Entity_Id) return Boolean is
- begin
- return
- Is_Default_Initial_Condition_Proc (Id)
- or else Is_Initial_Condition_Proc (Id)
- or else Is_Invariant_Proc (Id)
- or else Is_Partial_Invariant_Proc (Id)
- or else Is_Postconditions_Proc (Id);
- end Is_Assertion_Pragma_Target;
+ function Create_Variable_Assignment_Rep
+ (Asmt : Node_Id) return Scenario_Rep_Record
+ is
+ Var_Id : constant Entity_Id := Entity (Assignment_Target (Asmt));
+ Rec : Scenario_Rep_Record;
- ----------------------------
- -- Is_Bodiless_Subprogram --
- ----------------------------
+ begin
+ Rec.Elab_Checks_OK := Is_Elaboration_Checks_OK_Node (Asmt);
+ Rec.Elab_Warnings_OK := Is_Elaboration_Warnings_OK_Id (Var_Id);
+ Rec.GM := Ghost_Mode_Of_Node (Asmt);
+ Rec.SM := SPARK_Mode_Of_Node (Asmt);
+ Rec.Kind := Variable_Assignment_Scenario;
+ Rec.Target := Var_Id;
- function Is_Bodiless_Subprogram (Subp_Id : Entity_Id) return Boolean is
- begin
- -- An abstract subprogram does not have a body
+ return Rec;
+ end Create_Variable_Assignment_Rep;
- if Ekind_In (Subp_Id, E_Function,
- E_Operator,
- E_Procedure)
- and then Is_Abstract_Subprogram (Subp_Id)
- then
- return True;
+ -----------------------------------
+ -- Create_Variable_Reference_Rep --
+ -----------------------------------
- -- A formal subprogram does not have a body
+ function Create_Variable_Reference_Rep
+ (Ref : Node_Id) return Scenario_Rep_Record
+ is
+ Rec : Scenario_Rep_Record;
- elsif Is_Formal_Subprogram (Subp_Id) then
- return True;
+ begin
+ Rec.Elab_Checks_OK := Is_Elaboration_Checks_OK_Node (Ref);
+ Rec.Elab_Warnings_OK := Is_Elaboration_Warnings_OK_Node (Ref);
+ Rec.GM := Ghost_Mode_Of_Node (Ref);
+ Rec.SM := SPARK_Mode_Of_Node (Ref);
+ Rec.Kind := Variable_Reference_Scenario;
+ Rec.Target := Target (Ref);
- -- An imported subprogram may have a body, however it is not known at
- -- compile or bind time where the body resides and whether it will be
- -- elaborated on time.
+ -- Scenario-specific attributes
- elsif Is_Imported (Subp_Id) then
- return True;
- end if;
+ Rec.Flag_1 := Is_Read (Ref); -- Is_Read_Reference
- return False;
- end Is_Bodiless_Subprogram;
+ return Rec;
+ end Create_Variable_Reference_Rep;
- ------------------------
- -- Is_Controlled_Proc --
- ------------------------
+ -------------------------
+ -- Create_Variable_Rep --
+ -------------------------
- function Is_Controlled_Proc
- (Subp_Id : Entity_Id;
- Subp_Nam : Name_Id) return Boolean
- is
- Formal_Id : Entity_Id;
+ function Create_Variable_Rep
+ (Var_Id : Entity_Id) return Target_Rep_Record
+ is
+ Rec : Target_Rep_Record;
- begin
- pragma Assert (Nam_In (Subp_Nam, Name_Adjust,
- Name_Finalize,
- Name_Initialize));
+ begin
+ Rec.Kind := Variable_Target;
- -- To qualify, the subprogram must denote a source procedure with name
- -- Adjust, Finalize, or Initialize where the sole formal is controlled.
+ -- Target-specific attributes
- if Comes_From_Source (Subp_Id)
- and then Ekind (Subp_Id) = E_Procedure
- and then Chars (Subp_Id) = Subp_Nam
- then
- Formal_Id := First_Formal (Subp_Id);
+ Rec.Field_1 := Declaration_Node (Var_Id); -- Variable_Declaration
- return
- Present (Formal_Id)
- and then Is_Controlled (Etype (Formal_Id))
- and then No (Next_Formal (Formal_Id));
- end if;
+ return Rec;
+ end Create_Variable_Rep;
- return False;
- end Is_Controlled_Proc;
+ -------------
+ -- Destroy --
+ -------------
- ---------------------------------------
- -- Is_Default_Initial_Condition_Proc --
- ---------------------------------------
+ procedure Destroy (S_Id : in out Scenario_Rep_Id) is
+ pragma Unreferenced (S_Id);
+ begin
+ null;
+ end Destroy;
- function Is_Default_Initial_Condition_Proc
- (Id : Entity_Id) return Boolean
- is
- begin
- -- To qualify, the entity must denote a Default_Initial_Condition
- -- procedure.
+ -------------
+ -- Destroy --
+ -------------
- return Ekind (Id) = E_Procedure and then Is_DIC_Procedure (Id);
- end Is_Default_Initial_Condition_Proc;
+ procedure Destroy (T_Id : in out Target_Rep_Id) is
+ pragma Unreferenced (T_Id);
+ begin
+ null;
+ end Destroy;
- -----------------------
- -- Is_Finalizer_Proc --
- -----------------------
+ --------------------------------
+ -- Disable_Elaboration_Checks --
+ --------------------------------
- function Is_Finalizer_Proc (Id : Entity_Id) return Boolean is
- begin
- -- To qualify, the entity must denote a _Finalizer procedure
+ procedure Disable_Elaboration_Checks (S_Id : Scenario_Rep_Id) is
+ pragma Assert (Present (S_Id));
+ begin
+ Scenario_Reps.Table (S_Id).Elab_Checks_OK := False;
+ end Disable_Elaboration_Checks;
- return Ekind (Id) = E_Procedure and then Chars (Id) = Name_uFinalizer;
- end Is_Finalizer_Proc;
+ --------------------------------
+ -- Disable_Elaboration_Checks --
+ --------------------------------
- -----------------------
- -- Is_Guaranteed_ABE --
- -----------------------
+ procedure Disable_Elaboration_Checks (T_Id : Target_Rep_Id) is
+ pragma Assert (Present (T_Id));
+ begin
+ Target_Reps.Table (T_Id).Elab_Checks_OK := False;
+ end Disable_Elaboration_Checks;
- function Is_Guaranteed_ABE
- (N : Node_Id;
- Target_Decl : Node_Id;
- Target_Body : Node_Id) return Boolean
- is
- begin
- -- Avoid cascaded errors if there were previous serious infractions.
- -- As a result the scenario will not be treated as a guaranteed ABE.
- -- This behaviour parallels that of the old ABE mechanism.
+ ---------------------------
+ -- Elaboration_Checks_OK --
+ ---------------------------
- if Serious_Errors_Detected > 0 then
- return False;
+ function Elaboration_Checks_OK (S_Id : Scenario_Rep_Id) return Boolean is
+ pragma Assert (Present (S_Id));
+ begin
+ return Scenario_Reps.Table (S_Id).Elab_Checks_OK;
+ end Elaboration_Checks_OK;
- -- The scenario and the target appear within the same context ignoring
- -- enclosing library levels.
+ ---------------------------
+ -- Elaboration_Checks_OK --
+ ---------------------------
- -- Performance note: parent traversal
+ function Elaboration_Checks_OK (T_Id : Target_Rep_Id) return Boolean is
+ pragma Assert (Present (T_Id));
+ begin
+ return Target_Reps.Table (T_Id).Elab_Checks_OK;
+ end Elaboration_Checks_OK;
- elsif In_Same_Context (N, Target_Decl) then
+ -----------------------------
+ -- Elaboration_Warnings_OK --
+ -----------------------------
- -- The target body has already been encountered. The scenario results
- -- in a guaranteed ABE if it appears prior to the body.
+ function Elaboration_Warnings_OK
+ (S_Id : Scenario_Rep_Id) return Boolean
+ is
+ pragma Assert (Present (S_Id));
+ begin
+ return Scenario_Reps.Table (S_Id).Elab_Warnings_OK;
+ end Elaboration_Warnings_OK;
- if Present (Target_Body) then
- return Earlier_In_Extended_Unit (N, Target_Body);
+ -----------------------------
+ -- Elaboration_Warnings_OK --
+ -----------------------------
- -- Otherwise the body has not been encountered yet. The scenario is
- -- a guaranteed ABE since the body will appear later. It is assumed
- -- that the caller has already checked whether the scenario is ABE-
- -- safe as optional bodies are not considered here.
+ function Elaboration_Warnings_OK (T_Id : Target_Rep_Id) return Boolean is
+ pragma Assert (Present (T_Id));
+ begin
+ return Target_Reps.Table (T_Id).Elab_Warnings_OK;
+ end Elaboration_Warnings_OK;
- else
- return True;
- end if;
- end if;
+ --------------------------------------
+ -- Finalize_Internal_Representation --
+ --------------------------------------
- return False;
- end Is_Guaranteed_ABE;
+ procedure Finalize_Internal_Representation is
+ begin
+ ETT_Map.Destroy (Entity_To_Target_Map);
+ NTS_Map.Destroy (Node_To_Scenario_Map);
+ end Finalize_Internal_Representation;
- -------------------------------
- -- Is_Initial_Condition_Proc --
- -------------------------------
+ -------------------
+ -- Ghost_Mode_Of --
+ -------------------
- function Is_Initial_Condition_Proc (Id : Entity_Id) return Boolean is
- begin
- -- To qualify, the entity must denote an Initial_Condition procedure
+ function Ghost_Mode_Of
+ (S_Id : Scenario_Rep_Id) return Extended_Ghost_Mode
+ is
+ pragma Assert (Present (S_Id));
+ begin
+ return Scenario_Reps.Table (S_Id).GM;
+ end Ghost_Mode_Of;
- return
- Ekind (Id) = E_Procedure and then Is_Initial_Condition_Procedure (Id);
- end Is_Initial_Condition_Proc;
+ -------------------
+ -- Ghost_Mode_Of --
+ -------------------
- --------------------
- -- Is_Initialized --
- --------------------
+ function Ghost_Mode_Of
+ (T_Id : Target_Rep_Id) return Extended_Ghost_Mode
+ is
+ pragma Assert (Present (T_Id));
+ begin
+ return Target_Reps.Table (T_Id).GM;
+ end Ghost_Mode_Of;
- function Is_Initialized (Obj_Decl : Node_Id) return Boolean is
- begin
- -- To qualify, the object declaration must have an expression
+ --------------------------
+ -- Ghost_Mode_Of_Entity --
+ --------------------------
- return
- Present (Expression (Obj_Decl)) or else Has_Init_Expression (Obj_Decl);
- end Is_Initialized;
+ function Ghost_Mode_Of_Entity
+ (Id : Entity_Id) return Extended_Ghost_Mode
+ is
+ begin
+ return To_Ghost_Mode (Is_Ignored_Ghost_Entity (Id));
+ end Ghost_Mode_Of_Entity;
- -----------------------
- -- Is_Invariant_Proc --
- -----------------------
+ ------------------------
+ -- Ghost_Mode_Of_Node --
+ ------------------------
- function Is_Invariant_Proc (Id : Entity_Id) return Boolean is
- begin
- -- To qualify, the entity must denote the "full" invariant procedure
+ function Ghost_Mode_Of_Node (N : Node_Id) return Extended_Ghost_Mode is
+ begin
+ return To_Ghost_Mode (Is_Ignored_Ghost_Node (N));
+ end Ghost_Mode_Of_Node;
- return Ekind (Id) = E_Procedure and then Is_Invariant_Procedure (Id);
- end Is_Invariant_Proc;
+ ----------------------------------------
+ -- Initialize_Internal_Representation --
+ ----------------------------------------
- ---------------------------------------
- -- Is_Non_Library_Level_Encapsulator --
- ---------------------------------------
+ procedure Initialize_Internal_Representation is
+ begin
+ null;
+ end Initialize_Internal_Representation;
- function Is_Non_Library_Level_Encapsulator (N : Node_Id) return Boolean is
- begin
- case Nkind (N) is
- when N_Abstract_Subprogram_Declaration
- | N_Aspect_Specification
- | N_Component_Declaration
- | N_Entry_Body
- | N_Entry_Declaration
- | N_Expression_Function
- | N_Formal_Abstract_Subprogram_Declaration
- | N_Formal_Concrete_Subprogram_Declaration
- | N_Formal_Object_Declaration
- | N_Formal_Package_Declaration
- | N_Formal_Type_Declaration
- | N_Generic_Association
- | N_Implicit_Label_Declaration
- | N_Incomplete_Type_Declaration
- | N_Private_Extension_Declaration
- | N_Private_Type_Declaration
- | N_Protected_Body
- | N_Protected_Type_Declaration
- | N_Single_Protected_Declaration
- | N_Single_Task_Declaration
- | N_Subprogram_Body
- | N_Subprogram_Declaration
- | N_Task_Body
- | N_Task_Type_Declaration
- =>
- return True;
+ -------------------------
+ -- Is_Dispatching_Call --
+ -------------------------
- when others =>
- return Is_Generic_Declaration_Or_Body (N);
- end case;
- end Is_Non_Library_Level_Encapsulator;
+ function Is_Dispatching_Call (S_Id : Scenario_Rep_Id) return Boolean is
+ pragma Assert (Present (S_Id));
+ pragma Assert (Kind (S_Id) = Call_Scenario);
- -------------------------------
- -- Is_Partial_Invariant_Proc --
- -------------------------------
+ begin
+ return Scenario_Reps.Table (S_Id).Flag_1;
+ end Is_Dispatching_Call;
- function Is_Partial_Invariant_Proc (Id : Entity_Id) return Boolean is
- begin
- -- To qualify, the entity must denote the "partial" invariant procedure
+ -----------------------
+ -- Is_Read_Reference --
+ -----------------------
- return
- Ekind (Id) = E_Procedure and then Is_Partial_Invariant_Procedure (Id);
- end Is_Partial_Invariant_Proc;
+ function Is_Read_Reference (S_Id : Scenario_Rep_Id) return Boolean is
+ pragma Assert (Present (S_Id));
+ pragma Assert (Kind (S_Id) = Variable_Reference_Scenario);
- ----------------------------
- -- Is_Postconditions_Proc --
- ----------------------------
+ begin
+ return Scenario_Reps.Table (S_Id).Flag_1;
+ end Is_Read_Reference;
- function Is_Postconditions_Proc (Id : Entity_Id) return Boolean is
- begin
- -- To qualify, the entity must denote a _Postconditions procedure
+ ----------
+ -- Kind --
+ ----------
- return
- Ekind (Id) = E_Procedure and then Chars (Id) = Name_uPostconditions;
- end Is_Postconditions_Proc;
+ function Kind (S_Id : Scenario_Rep_Id) return Scenario_Kind is
+ pragma Assert (Present (S_Id));
+ begin
+ return Scenario_Reps.Table (S_Id).Kind;
+ end Kind;
- ---------------------------
- -- Is_Preelaborated_Unit --
- ---------------------------
+ ----------
+ -- Kind --
+ ----------
- function Is_Preelaborated_Unit (Id : Entity_Id) return Boolean is
- begin
- return
- Is_Preelaborated (Id)
- or else Is_Pure (Id)
- or else Is_Remote_Call_Interface (Id)
- or else Is_Remote_Types (Id)
- or else Is_Shared_Passive (Id);
- end Is_Preelaborated_Unit;
+ function Kind (T_Id : Target_Rep_Id) return Target_Kind is
+ pragma Assert (Present (T_Id));
+ begin
+ return Target_Reps.Table (T_Id).Kind;
+ end Kind;
- ------------------------
- -- Is_Protected_Entry --
- ------------------------
+ -----------
+ -- Level --
+ -----------
- function Is_Protected_Entry (Id : Entity_Id) return Boolean is
- begin
- -- To qualify, the entity must denote an entry defined in a protected
- -- type.
+ function Level (S_Id : Scenario_Rep_Id) return Enclosing_Level_Kind is
+ pragma Assert (Present (S_Id));
+ begin
+ return Scenario_Reps.Table (S_Id).Level;
+ end Level;
- return
- Is_Entry (Id)
- and then Is_Protected_Type (Non_Private_View (Scope (Id)));
- end Is_Protected_Entry;
+ -------------
+ -- Present --
+ -------------
- -----------------------
- -- Is_Protected_Subp --
- -----------------------
+ function Present (S_Id : Scenario_Rep_Id) return Boolean is
+ begin
+ return S_Id /= No_Scenario_Rep;
+ end Present;
- function Is_Protected_Subp (Id : Entity_Id) return Boolean is
- begin
- -- To qualify, the entity must denote a subprogram defined within a
- -- protected type.
+ -------------
+ -- Present --
+ -------------
- return
- Ekind_In (Id, E_Function, E_Procedure)
- and then Is_Protected_Type (Non_Private_View (Scope (Id)));
- end Is_Protected_Subp;
+ function Present (T_Id : Target_Rep_Id) return Boolean is
+ begin
+ return T_Id /= No_Target_Rep;
+ end Present;
- ----------------------------
- -- Is_Protected_Body_Subp --
- ----------------------------
+ --------------------------------
+ -- Scenario_Representation_Of --
+ --------------------------------
- function Is_Protected_Body_Subp (Id : Entity_Id) return Boolean is
- begin
- -- To qualify, the entity must denote a subprogram with attribute
- -- Protected_Subprogram set.
+ function Scenario_Representation_Of
+ (N : Node_Id;
+ In_State : Processing_In_State) return Scenario_Rep_Id
+ is
+ S_Id : Scenario_Rep_Id;
- return
- Ekind_In (Id, E_Function, E_Procedure)
- and then Present (Protected_Subprogram (Id));
- end Is_Protected_Body_Subp;
+ begin
+ S_Id := NTS_Map.Get (Node_To_Scenario_Map, N);
- --------------------------------
- -- Is_Recorded_SPARK_Scenario --
- --------------------------------
+ -- The elaboration scenario lacks a representation. This indicates
+ -- that the scenario is encountered for the first time. Create the
+ -- representation of it.
- function Is_Recorded_SPARK_Scenario (N : Node_Id) return Boolean is
- begin
- if Recorded_SPARK_Scenarios_In_Use then
- return Recorded_SPARK_Scenarios.Get (N);
- end if;
+ if not Present (S_Id) then
+ Scenario_Reps.Append (Create_Scenario_Rep (N, In_State));
+ S_Id := Scenario_Reps.Last;
- return Recorded_SPARK_Scenarios_No_Element;
- end Is_Recorded_SPARK_Scenario;
+ -- Associate the internal representation with the elaboration
+ -- scenario.
- ------------------------------------
- -- Is_Recorded_Top_Level_Scenario --
- ------------------------------------
+ NTS_Map.Put (Node_To_Scenario_Map, N, S_Id);
+ end if;
- function Is_Recorded_Top_Level_Scenario (N : Node_Id) return Boolean is
- begin
- if Recorded_Top_Level_Scenarios_In_Use then
- return Recorded_Top_Level_Scenarios.Get (N);
- end if;
+ pragma Assert (Present (S_Id));
- return Recorded_Top_Level_Scenarios_No_Element;
- end Is_Recorded_Top_Level_Scenario;
+ return S_Id;
+ end Scenario_Representation_Of;
- ------------------------
- -- Is_Safe_Activation --
- ------------------------
+ --------------------------------
+ -- Set_Activated_Task_Objects --
+ --------------------------------
- function Is_Safe_Activation
- (Call : Node_Id;
- Task_Decl : Node_Id) return Boolean
- is
- begin
- -- The activation of a task coming from an external instance cannot
- -- cause an ABE because the generic was already instantiated. Note
- -- that the instantiation itself may lead to an ABE.
+ procedure Set_Activated_Task_Objects
+ (S_Id : Scenario_Rep_Id;
+ Task_Objs : NE_List.Doubly_Linked_List)
+ is
+ pragma Assert (Present (S_Id));
+ pragma Assert (Kind (S_Id) = Task_Activation_Scenario);
- return
- In_External_Instance
- (N => Call,
- Target_Decl => Task_Decl);
- end Is_Safe_Activation;
+ begin
+ Scenario_Reps.Table (S_Id).List_1 := Task_Objs;
+ end Set_Activated_Task_Objects;
- ------------------
- -- Is_Safe_Call --
- ------------------
+ -----------------------------
+ -- Set_Activated_Task_Type --
+ -----------------------------
- function Is_Safe_Call
- (Call : Node_Id;
- Target_Attrs : Target_Attributes) return Boolean
- is
- begin
- -- The target is either an abstract subprogram, formal subprogram, or
- -- imported, in which case it does not have a body at compile or bind
- -- time. Assume that the call is ABE-safe.
+ procedure Set_Activated_Task_Type
+ (S_Id : Scenario_Rep_Id;
+ Task_Typ : Entity_Id)
+ is
+ pragma Assert (Present (S_Id));
+ pragma Assert (Kind (S_Id) = Task_Activation_Scenario);
- if Is_Bodiless_Subprogram (Target_Attrs.Spec_Id) then
- return True;
+ begin
+ Scenario_Reps.Table (S_Id).Field_1 := Task_Typ;
+ end Set_Activated_Task_Type;
- -- The target is an instantiation of a generic subprogram. The call
- -- cannot cause an ABE because the generic was already instantiated.
- -- Note that the instantiation itself may lead to an ABE.
+ -------------------
+ -- SPARK_Mode_Of --
+ -------------------
- elsif Is_Generic_Instance (Target_Attrs.Spec_Id) then
- return True;
+ function SPARK_Mode_Of
+ (S_Id : Scenario_Rep_Id) return Extended_SPARK_Mode
+ is
+ pragma Assert (Present (S_Id));
+ begin
+ return Scenario_Reps.Table (S_Id).SM;
+ end SPARK_Mode_Of;
- -- The invocation of a target coming from an external instance cannot
- -- cause an ABE because the generic was already instantiated. Note that
- -- the instantiation itself may lead to an ABE.
+ -------------------
+ -- SPARK_Mode_Of --
+ -------------------
- elsif In_External_Instance
- (N => Call,
- Target_Decl => Target_Attrs.Spec_Decl)
- then
- return True;
+ function SPARK_Mode_Of
+ (T_Id : Target_Rep_Id) return Extended_SPARK_Mode
+ is
+ pragma Assert (Present (T_Id));
+ begin
+ return Target_Reps.Table (T_Id).SM;
+ end SPARK_Mode_Of;
- -- The target is a subprogram body without a previous declaration. The
- -- call cannot cause an ABE because the body has already been seen.
+ --------------------------
+ -- SPARK_Mode_Of_Entity --
+ --------------------------
- elsif Nkind (Target_Attrs.Spec_Decl) = N_Subprogram_Body
- and then No (Corresponding_Spec (Target_Attrs.Spec_Decl))
- then
- return True;
+ function SPARK_Mode_Of_Entity
+ (Id : Entity_Id) return Extended_SPARK_Mode
+ is
+ Prag : constant Node_Id := SPARK_Pragma (Id);
- -- The target is a subprogram body stub without a prior declaration.
- -- The call cannot cause an ABE because the proper body substitutes
- -- the stub.
+ begin
+ return
+ To_SPARK_Mode
+ (Present (Prag)
+ and then Get_SPARK_Mode_From_Annotation (Prag) = On);
+ end SPARK_Mode_Of_Entity;
- elsif Nkind (Target_Attrs.Spec_Decl) = N_Subprogram_Body_Stub
- and then No (Corresponding_Spec_Of_Stub (Target_Attrs.Spec_Decl))
- then
- return True;
+ ------------------------
+ -- SPARK_Mode_Of_Node --
+ ------------------------
- -- Subprogram bodies which wrap attribute references used as actuals
- -- in instantiations are always ABE-safe. These bodies are artifacts
- -- of expansion.
+ function SPARK_Mode_Of_Node (N : Node_Id) return Extended_SPARK_Mode is
+ begin
+ return To_SPARK_Mode (Is_SPARK_Mode_On_Node (N));
+ end SPARK_Mode_Of_Node;
- elsif Present (Target_Attrs.Body_Decl)
- and then Nkind (Target_Attrs.Body_Decl) = N_Subprogram_Body
- and then Was_Attribute_Reference (Target_Attrs.Body_Decl)
- then
- return True;
- end if;
+ ----------------------
+ -- Spec_Declaration --
+ ----------------------
- return False;
- end Is_Safe_Call;
+ function Spec_Declaration (T_Id : Target_Rep_Id) return Node_Id is
+ pragma Assert (Present (T_Id));
+ begin
+ return Target_Reps.Table (T_Id).Spec_Decl;
+ end Spec_Declaration;
- ---------------------------
- -- Is_Safe_Instantiation --
- ---------------------------
+ ------------
+ -- Target --
+ ------------
- function Is_Safe_Instantiation
- (Inst : Node_Id;
- Gen_Attrs : Target_Attributes) return Boolean
- is
- begin
- -- The generic is an intrinsic subprogram in which case it does not
- -- have a body at compile or bind time. Assume that the instantiation
- -- is ABE-safe.
+ function Target (S_Id : Scenario_Rep_Id) return Entity_Id is
+ pragma Assert (Present (S_Id));
+ begin
+ return Scenario_Reps.Table (S_Id).Target;
+ end Target;
- if Is_Bodiless_Subprogram (Gen_Attrs.Spec_Id) then
- return True;
+ ------------------------------
+ -- Target_Representation_Of --
+ ------------------------------
- -- The instantiation of an external nested generic cannot cause an ABE
- -- if the outer generic was already instantiated. Note that the instance
- -- of the outer generic may lead to an ABE.
+ function Target_Representation_Of
+ (Id : Entity_Id;
+ In_State : Processing_In_State) return Target_Rep_Id
+ is
+ T_Id : Target_Rep_Id;
- elsif In_External_Instance
- (N => Inst,
- Target_Decl => Gen_Attrs.Spec_Decl)
- then
- return True;
+ begin
+ T_Id := ETT_Map.Get (Entity_To_Target_Map, Id);
- -- The generic is a package. The instantiation cannot cause an ABE when
- -- the package has no body.
+ -- The elaboration target lacks an internal representation. This
+ -- indicates that the target is encountered for the first time.
+ -- Create the internal representation of it.
- elsif Ekind (Gen_Attrs.Spec_Id) = E_Generic_Package
- and then not Has_Body (Gen_Attrs.Spec_Decl)
- then
- return True;
- end if;
+ if not Present (T_Id) then
+ Target_Reps.Append (Create_Target_Rep (Id, In_State));
+ T_Id := Target_Reps.Last;
- return False;
- end Is_Safe_Instantiation;
+ -- Associate the internal representation with the elaboration
+ -- target.
- ------------------
- -- Is_Same_Unit --
- ------------------
+ ETT_Map.Put (Entity_To_Target_Map, Id, T_Id);
- function Is_Same_Unit
- (Unit_1 : Entity_Id;
- Unit_2 : Entity_Id) return Boolean
- is
- begin
- return Unit_Entity (Unit_1) = Unit_Entity (Unit_2);
- end Is_Same_Unit;
+ -- The Processing phase is working with a partially analyzed tree,
+ -- where various attributes become available as analysis continues.
+ -- This case arrises in the context of guaranteed ABE processing.
+ -- Update the existing representation by including new attributes.
- -----------------
- -- Is_Scenario --
- -----------------
+ elsif In_State.Representation = Inconsistent_Representation then
+ Target_Reps.Table (T_Id) := Create_Target_Rep (Id, In_State);
- function Is_Scenario (N : Node_Id) return Boolean is
- begin
- case Nkind (N) is
- when N_Assignment_Statement
- | N_Attribute_Reference
- | N_Call_Marker
- | N_Entry_Call_Statement
- | N_Expanded_Name
- | N_Function_Call
- | N_Function_Instantiation
- | N_Identifier
- | N_Package_Instantiation
- | N_Procedure_Call_Statement
- | N_Procedure_Instantiation
- | N_Requeue_Statement
- =>
- return True;
+ -- Otherwise the Processing phase imposes a particular representation
+ -- version which is not satisfied by the target. This case arrises
+ -- when the Processing phase switches from guaranteed ABE checks and
+ -- diagnostics to some other mode of operation. Update the existing
+ -- representation to include all attributes.
- when others =>
- return False;
- end case;
- end Is_Scenario;
+ elsif In_State.Representation /= Version (T_Id) then
+ Target_Reps.Table (T_Id) := Create_Target_Rep (Id, In_State);
+ end if;
- ------------------------------
- -- Is_SPARK_Semantic_Target --
- ------------------------------
+ pragma Assert (Present (T_Id));
- function Is_SPARK_Semantic_Target (Id : Entity_Id) return Boolean is
- begin
- return
- Is_Default_Initial_Condition_Proc (Id)
- or else Is_Initial_Condition_Proc (Id);
- end Is_SPARK_Semantic_Target;
+ return T_Id;
+ end Target_Representation_Of;
- ------------------------
- -- Is_Suitable_Access --
- ------------------------
+ -------------------
+ -- To_Ghost_Mode --
+ -------------------
- function Is_Suitable_Access (N : Node_Id) return Boolean is
- Nam : Name_Id;
- Pref : Node_Id;
- Subp_Id : Entity_Id;
+ function To_Ghost_Mode
+ (Ignored_Status : Boolean) return Extended_Ghost_Mode
+ is
+ begin
+ if Ignored_Status then
+ return Is_Ignored;
+ else
+ return Is_Checked_Or_Not_Specified;
+ end if;
+ end To_Ghost_Mode;
- begin
- -- This scenario is relevant only when the static model is in effect
- -- because it is graph-dependent and does not involve any run-time
- -- checks. Allowing it in the dynamic model would create confusing
- -- noise.
+ -------------------
+ -- To_SPARK_Mode --
+ -------------------
- if not Static_Elaboration_Checks then
- return False;
+ function To_SPARK_Mode
+ (On_Status : Boolean) return Extended_SPARK_Mode
+ is
+ begin
+ if On_Status then
+ return Is_On;
+ else
+ return Is_Off_Or_Not_Specified;
+ end if;
+ end To_SPARK_Mode;
- -- Nothing to do when switch -gnatd.U (ignore 'Access) is in effect
+ ----------
+ -- Unit --
+ ----------
- elsif Debug_Flag_Dot_UU then
- return False;
+ function Unit (T_Id : Target_Rep_Id) return Entity_Id is
+ pragma Assert (Present (T_Id));
+ begin
+ return Target_Reps.Table (T_Id).Unit;
+ end Unit;
- -- Nothing to do when the scenario is not an attribute reference
+ --------------------------
+ -- Variable_Declaration --
+ --------------------------
- elsif Nkind (N) /= N_Attribute_Reference then
- return False;
+ function Variable_Declaration (T_Id : Target_Rep_Id) return Node_Id is
+ pragma Assert (Present (T_Id));
+ pragma Assert (Kind (T_Id) = Variable_Target);
- -- Nothing to do for internally-generated attributes because they are
- -- assumed to be ABE safe.
+ begin
+ return Target_Reps.Table (T_Id).Field_1;
+ end Variable_Declaration;
- elsif not Comes_From_Source (N) then
- return False;
- end if;
+ -------------
+ -- Version --
+ -------------
- Nam := Attribute_Name (N);
- Pref := Prefix (N);
+ function Version (T_Id : Target_Rep_Id) return Representation_Kind is
+ pragma Assert (Present (T_Id));
+ begin
+ return Target_Reps.Table (T_Id).Version;
+ end Version;
+ end Internal_Representation;
- -- Sanitize the prefix of the attribute
+ ----------------------
+ -- Invocation_Graph --
+ ----------------------
- if not Is_Entity_Name (Pref) then
- return False;
+ package body Invocation_Graph is
- elsif No (Entity (Pref)) then
- return False;
- end if;
+ -----------
+ -- Types --
+ -----------
- Subp_Id := Entity (Pref);
+ -- The following type represents simplified version of an invocation
+ -- relation.
- if not Is_Subprogram_Or_Entry (Subp_Id) then
- return False;
- end if;
+ type Invoker_Target_Relation is record
+ Invoker : Entity_Id := Empty;
+ Target : Entity_Id := Empty;
+ end record;
- -- Traverse a possible chain of renamings to obtain the original entry
- -- or subprogram which the prefix may rename.
+ -- The following variables define the entities of the dummy elaboration
+ -- procedures used as origins of library level paths.
- Subp_Id := Get_Renamed_Entity (Subp_Id);
+ Elab_Body_Id : Entity_Id := Empty;
+ Elab_Spec_Id : Entity_Id := Empty;
- -- To qualify, the attribute must meet the following prerequisites:
+ ---------------------
+ -- Data structures --
+ ---------------------
- return
+ -- The following set contains all declared invocation constructs. It
+ -- ensures that the same construct is not declared multiple times in
+ -- the ALI file of the main unit.
- -- The prefix must denote a source entry, operator, or subprogram
- -- which is not imported.
+ Saved_Constructs_Set : NE_Set.Membership_Set := NE_Set.Nil;
- Comes_From_Source (Subp_Id)
- and then Is_Subprogram_Or_Entry (Subp_Id)
- and then not Is_Bodiless_Subprogram (Subp_Id)
+ function Hash (Key : Invoker_Target_Relation) return Bucket_Range_Type;
+ -- Obtain the hash value of pair Key
- -- The attribute name must be one of the 'Access forms. Note that
- -- 'Unchecked_Access cannot apply to a subprogram.
+ package IR_Set is new Membership_Sets
+ (Element_Type => Invoker_Target_Relation,
+ "=" => "=",
+ Hash => Hash);
- and then Nam_In (Nam, Name_Access, Name_Unrestricted_Access);
- end Is_Suitable_Access;
+ -- The following set contains all recorded simple invocation relations.
+ -- It ensures that multiple relations involving the same invoker and
+ -- target do not appear in the ALI file of the main unit.
- ----------------------
- -- Is_Suitable_Call --
- ----------------------
+ Saved_Relations_Set : IR_Set.Membership_Set := IR_Set.Nil;
- function Is_Suitable_Call (N : Node_Id) return Boolean is
- begin
- -- Entry and subprogram calls are intentionally ignored because they
- -- may undergo expansion depending on the compilation mode, previous
- -- errors, generic context, etc. Call markers play the role of calls
- -- and provide a uniform foundation for ABE processing.
+ --------------
+ -- Builders --
+ --------------
- return Nkind (N) = N_Call_Marker;
- end Is_Suitable_Call;
+ function Signature_Of (Id : Entity_Id) return Invocation_Signature_Id;
+ pragma Inline (Signature_Of);
+ -- Obtain the invication signature id of arbitrary entity Id
- -------------------------------
- -- Is_Suitable_Instantiation --
- -------------------------------
+ -----------------------
+ -- Local subprograms --
+ -----------------------
- function Is_Suitable_Instantiation (N : Node_Id) return Boolean is
- Orig_N : constant Node_Id := Original_Node (N);
- -- Use the original node in case an instantiation library unit is
- -- rewritten as a package or subprogram.
+ procedure Build_Elaborate_Body_Procedure;
+ pragma Inline (Build_Elaborate_Body_Procedure);
+ -- Create a dummy elaborate body procedure and store its entity in
+ -- Elab_Body_Id.
+
+ procedure Build_Elaborate_Procedure
+ (Proc_Id : out Entity_Id;
+ Proc_Nam : Name_Id;
+ Loc : Source_Ptr);
+ pragma Inline (Build_Elaborate_Procedure);
+ -- Create a dummy elaborate procedure with name Proc_Nam and source
+ -- location Loc. The entity is returned in Proc_Id.
+
+ procedure Build_Elaborate_Spec_Procedure;
+ pragma Inline (Build_Elaborate_Spec_Procedure);
+ -- Create a dummy elaborate spec procedure and store its entity in
+ -- Elab_Spec_Id.
+
+ function Build_Subprogram_Invocation
+ (Subp_Id : Entity_Id) return Node_Id;
+ pragma Inline (Build_Subprogram_Invocation);
+ -- Create a dummy call marker that invokes subprogram Subp_Id
+
+ function Build_Task_Activation
+ (Task_Typ : Entity_Id;
+ In_State : Processing_In_State) return Node_Id;
+ pragma Inline (Build_Task_Activation);
+ -- Create a dummy call marker that activates an anonymous task object of
+ -- type Task_Typ.
+
+ procedure Declare_Invocation_Construct
+ (Constr_Id : Entity_Id;
+ In_State : Processing_In_State);
+ pragma Inline (Declare_Invocation_Construct);
+ -- Declare invocation construct Constr_Id by creating a declaration for
+ -- it in the ALI file of the main unit. In_State is the current state of
+ -- the Processing phase.
+
+ function Invocation_Graph_Recording_OK return Boolean;
+ pragma Inline (Invocation_Graph_Recording_OK);
+ -- Determine whether the invocation graph can be recorded
+
+ function Is_Invocation_Scenario (N : Node_Id) return Boolean;
+ pragma Inline (Is_Invocation_Scenario);
+ -- Determine whether node N is a suitable scenario for invocation graph
+ -- recording purposes.
+
+ function Is_Invocation_Target (Id : Entity_Id) return Boolean;
+ pragma Inline (Is_Invocation_Target);
+ -- Determine whether arbitrary entity Id denotes an invocation target
+
+ function Is_Saved_Construct (Constr : Entity_Id) return Boolean;
+ pragma Inline (Is_Saved_Construct);
+ -- Determine whether invocation construct Constr has already been
+ -- declared in the ALI file of the main unit.
+
+ function Is_Saved_Relation
+ (Rel : Invoker_Target_Relation) return Boolean;
+ pragma Inline (Is_Saved_Relation);
+ -- Determine whether simple invocation relation Rel has already been
+ -- recorded in the ALI file of the main unit.
+
+ procedure Process_Declarations
+ (Decls : List_Id;
+ In_State : Processing_In_State);
+ pragma Inline (Process_Declarations);
+ -- Process declaration list Decls by processing all invocation scenarios
+ -- within it.
+
+ procedure Process_Freeze_Node
+ (Fnode : Node_Id;
+ In_State : Processing_In_State);
+ pragma Inline (Process_Freeze_Node);
+ -- Process freeze node Fnode by processing all invocation scenarios in
+ -- its Actions list.
+
+ procedure Process_Invocation_Activation
+ (Call : Node_Id;
+ Call_Rep : Scenario_Rep_Id;
+ Obj_Id : Entity_Id;
+ Obj_Rep : Target_Rep_Id;
+ Task_Typ : Entity_Id;
+ Task_Rep : Target_Rep_Id;
+ In_State : Processing_In_State);
+ pragma Inline (Process_Invocation_Activation);
+ -- Process activation call Call which activates object Obj_Id of task
+ -- type Task_Typ by processing all invocation scenarios within the task
+ -- body. Call_Rep is the representation of the call. Obj_Rep denotes the
+ -- representation of the object. Task_Rep is the representation of the
+ -- task type. In_State is the current state of the Processing phase.
+
+ procedure Process_Invocation_Body_Scenarios;
+ pragma Inline (Process_Invocation_Body_Scenarios);
+ -- Process all library level body scenarios
+
+ procedure Process_Invocation_Call
+ (Call : Node_Id;
+ Call_Rep : Scenario_Rep_Id;
+ In_State : Processing_In_State);
+ pragma Inline (Process_Invocation_Call);
+ -- Process invocation call scenario Call with representation Call_Rep.
+ -- In_State is the current state of the Processing phase.
+
+ procedure Process_Invocation_Scenario
+ (N : Node_Id;
+ In_State : Processing_In_State);
+ pragma Inline (Process_Invocation_Scenario);
+ -- Process single invocation scenario N. In_State is the current state
+ -- of the Processing phase.
+
+ procedure Process_Invocation_Scenarios
+ (Iter : in out NE_Set.Iterator;
+ In_State : Processing_In_State);
+ pragma Inline (Process_Invocation_Scenarios);
+ -- Process all invocation scenarios obtained via iterator Iter. In_State
+ -- is the current state of the Processing phase.
+
+ procedure Process_Invocation_Spec_Scenarios;
+ pragma Inline (Process_Invocation_Spec_Scenarios);
+ -- Process all library level spec scenarios
+
+ procedure Process_Main_Unit;
+ pragma Inline (Process_Main_Unit);
+ -- Process all invocation scenarios within the main unit
+
+ procedure Process_Package_Declaration
+ (Pack_Decl : Node_Id;
+ In_State : Processing_In_State);
+ pragma Inline (Process_Package_Declaration);
+ -- Process package declaration Pack_Decl by processing all invocation
+ -- scenarios in its visible and private declarations. If the main unit
+ -- contains a generic, the declarations of the body are also examined.
+ -- In_State is the current state of the Processing phase.
+
+ procedure Process_Protected_Type_Declaration
+ (Prot_Decl : Node_Id;
+ In_State : Processing_In_State);
+ pragma Inline (Process_Protected_Type_Declaration);
+ -- Process the declarations of protected type Prot_Decl. In_State is the
+ -- current state of the Processing phase.
+
+ procedure Process_Subprogram_Declaration
+ (Subp_Decl : Node_Id;
+ In_State : Processing_In_State);
+ pragma Inline (Process_Subprogram_Declaration);
+ -- Process subprogram declaration Subp_Decl by processing all invocation
+ -- scenarios within its body. In_State denotes the current state of the
+ -- Processing phase.
+
+ procedure Process_Subprogram_Instantiation
+ (Inst : Node_Id;
+ In_State : Processing_In_State);
+ pragma Inline (Process_Subprogram_Instantiation);
+ -- Process subprogram instantiation Inst. In_State is the current state
+ -- of the Processing phase.
+
+ procedure Process_Task_Type_Declaration
+ (Task_Decl : Node_Id;
+ In_State : Processing_In_State);
+ pragma Inline (Process_Task_Type_Declaration);
+ -- Process task declaration Task_Decl by processing all invocation
+ -- scenarios within its body. In_State is the current state of the
+ -- Processing phase.
+
+ procedure Record_Full_Invocation_Path (In_State : Processing_In_State);
+ pragma Inline (Record_Full_Invocation_Path);
+ -- Record all relations between scenario pairs found in the stack of
+ -- active scenarios. In_State is the current state of the Processing
+ -- phase.
+
+ procedure Record_Invocation_Path (In_State : Processing_In_State);
+ pragma Inline (Record_Invocation_Path);
+ -- Record the invocation relations found within the path represented in
+ -- the active scenario stack. In_State denotes the current state of the
+ -- Processing phase.
+
+ procedure Record_Simple_Invocation_Path (In_State : Processing_In_State);
+ pragma Inline (Record_Simple_Invocation_Path);
+ -- Record a single relation from the start to the end of the stack of
+ -- active scenarios. In_State is the current state of the Processing
+ -- phase.
+
+ procedure Record_Invocation_Relation
+ (Invk_Id : Entity_Id;
+ Targ_Id : Entity_Id;
+ In_State : Processing_In_State);
+ pragma Inline (Record_Invocation_Relation);
+ -- Record an invocation relation with invoker Invk_Id and target Targ_Id
+ -- by creating an entry for it in the ALI file of the main unit. Formal
+ -- In_State denotes the current state of the Processing phase.
+
+ procedure Set_Is_Saved_Construct
+ (Constr : Entity_Id;
+ Val : Boolean := True);
+ pragma Inline (Set_Is_Saved_Construct);
+ -- Mark invocation construct Constr as declared in the ALI file of the
+ -- main unit depending on value Val.
+
+ procedure Set_Is_Saved_Relation
+ (Rel : Invoker_Target_Relation;
+ Val : Boolean := True);
+ pragma Inline (Set_Is_Saved_Relation);
+ -- Mark simple invocation relation Rel as recorded in the ALI file of
+ -- the main unit depending on value Val.
+
+ function Target_Of
+ (Pos : Active_Scenario_Pos;
+ In_State : Processing_In_State) return Entity_Id;
+ pragma Inline (Target_Of);
+ -- Given position within the active scenario stack Pos, obtain the
+ -- target of the indicated scenario. In_State is the current state
+ -- of the Processing phase.
+
+ procedure Traverse_Invocation_Body
+ (N : Node_Id;
+ In_State : Processing_In_State);
+ pragma Inline (Traverse_Invocation_Body);
+ -- Traverse subprogram body N looking for suitable invocation scenarios
+ -- that need to be processed for invocation graph recording purposes.
+ -- In_State is the current state of the Processing phase.
+
+ procedure Write_Invocation_Path (In_State : Processing_In_State);
+ pragma Inline (Write_Invocation_Path);
+ -- Write out a path represented by the active scenario on the stack to
+ -- standard output. In_State denotes the current state of the Processing
+ -- phase.
- begin
- -- To qualify, the instantiation must come from source
+ ------------------------------------
+ -- Build_Elaborate_Body_Procedure --
+ ------------------------------------
- return
- Comes_From_Source (Orig_N)
- and then Nkind (Orig_N) in N_Generic_Instantiation;
- end Is_Suitable_Instantiation;
+ procedure Build_Elaborate_Body_Procedure is
+ Body_Decl : Node_Id;
+ Spec_Decl : Node_Id;
- --------------------------
- -- Is_Suitable_Scenario --
- --------------------------
+ begin
+ -- Nothing to do when a previous call already created the procedure
- function Is_Suitable_Scenario (N : Node_Id) return Boolean is
- begin
- -- NOTE: Derived types and pragma Refined_State are intentionally left
- -- out because they are not executable during elaboration.
+ if Present (Elab_Body_Id) then
+ return;
+ end if;
- return
- Is_Suitable_Access (N)
- or else Is_Suitable_Call (N)
- or else Is_Suitable_Instantiation (N)
- or else Is_Suitable_Variable_Assignment (N)
- or else Is_Suitable_Variable_Reference (N);
- end Is_Suitable_Scenario;
+ Spec_And_Body_From_Entity
+ (Id => Cunit_Entity (Main_Unit),
+ Body_Decl => Body_Decl,
+ Spec_Decl => Spec_Decl);
- ------------------------------------
- -- Is_Suitable_SPARK_Derived_Type --
- ------------------------------------
+ pragma Assert (Present (Body_Decl));
- function Is_Suitable_SPARK_Derived_Type (N : Node_Id) return Boolean is
- Prag : Node_Id;
- Typ : Entity_Id;
+ Build_Elaborate_Procedure
+ (Proc_Id => Elab_Body_Id,
+ Proc_Nam => Name_B,
+ Loc => Sloc (Body_Decl));
+ end Build_Elaborate_Body_Procedure;
- begin
- -- To qualify, the type declaration must denote a derived tagged type
- -- with primitive operations, subject to pragma SPARK_Mode On.
+ -------------------------------
+ -- Build_Elaborate_Procedure --
+ -------------------------------
- if Nkind (N) = N_Full_Type_Declaration
- and then Nkind (Type_Definition (N)) = N_Derived_Type_Definition
- then
- Typ := Defining_Entity (N);
- Prag := SPARK_Pragma (Typ);
+ procedure Build_Elaborate_Procedure
+ (Proc_Id : out Entity_Id;
+ Proc_Nam : Name_Id;
+ Loc : Source_Ptr)
+ is
+ Proc_Decl : Node_Id;
+ pragma Unreferenced (Proc_Decl);
- return
- Is_Tagged_Type (Typ)
- and then Has_Primitive_Operations (Typ)
- and then Present (Prag)
- and then Get_SPARK_Mode_From_Annotation (Prag) = On;
- end if;
+ begin
+ Proc_Id := Make_Defining_Identifier (Loc, Proc_Nam);
- return False;
- end Is_Suitable_SPARK_Derived_Type;
+ -- Partially decorate the elaboration procedure because it will not
+ -- be insertred into the tree and analyzed.
- -------------------------------------
- -- Is_Suitable_SPARK_Instantiation --
- -------------------------------------
+ Set_Ekind (Proc_Id, E_Procedure);
+ Set_Etype (Proc_Id, Standard_Void_Type);
+ Set_Scope (Proc_Id, Unique_Entity (Cunit_Entity (Main_Unit)));
- function Is_Suitable_SPARK_Instantiation (N : Node_Id) return Boolean is
- Gen_Attrs : Target_Attributes;
- Gen_Id : Entity_Id;
- Inst : Node_Id;
- Inst_Attrs : Instantiation_Attributes;
- Inst_Id : Entity_Id;
+ -- Create a dummy declaration for the elaboration procedure. The
+ -- declaration does not need to be syntactically legal, but must
+ -- carry an accurate source location.
- begin
- -- To qualify, both the instantiation and the generic must be subject to
- -- SPARK_Mode On.
+ Proc_Decl :=
+ Make_Subprogram_Body (Loc,
+ Specification =>
+ Make_Procedure_Specification (Loc,
+ Defining_Unit_Name => Proc_Id),
+ Declarations => No_List,
+ Handled_Statement_Sequence => Empty);
+ end Build_Elaborate_Procedure;
- if Is_Suitable_Instantiation (N) then
- Extract_Instantiation_Attributes
- (Exp_Inst => N,
- Inst => Inst,
- Inst_Id => Inst_Id,
- Gen_Id => Gen_Id,
- Attrs => Inst_Attrs);
+ ------------------------------------
+ -- Build_Elaborate_Spec_Procedure --
+ ------------------------------------
- Extract_Target_Attributes (Gen_Id, Gen_Attrs);
+ procedure Build_Elaborate_Spec_Procedure is
+ Body_Decl : Node_Id;
+ Spec_Decl : Node_Id;
- return Inst_Attrs.SPARK_Mode_On and Gen_Attrs.SPARK_Mode_On;
- end if;
+ begin
+ -- Nothing to do when a previous call already created the procedure
- return False;
- end Is_Suitable_SPARK_Instantiation;
+ if Present (Elab_Spec_Id) then
+ return;
+ end if;
- --------------------------------------------
- -- Is_Suitable_SPARK_Refined_State_Pragma --
- --------------------------------------------
+ Spec_And_Body_From_Entity
+ (Id => Cunit_Entity (Main_Unit),
+ Body_Decl => Body_Decl,
+ Spec_Decl => Spec_Decl);
- function Is_Suitable_SPARK_Refined_State_Pragma
- (N : Node_Id) return Boolean
- is
- begin
- -- To qualfy, the pragma must denote Refined_State
+ pragma Assert (Present (Spec_Decl));
- return
- Nkind (N) = N_Pragma
- and then Pragma_Name (N) = Name_Refined_State;
- end Is_Suitable_SPARK_Refined_State_Pragma;
+ Build_Elaborate_Procedure
+ (Proc_Id => Elab_Spec_Id,
+ Proc_Nam => Name_S,
+ Loc => Sloc (Spec_Decl));
+ end Build_Elaborate_Spec_Procedure;
- -------------------------------------
- -- Is_Suitable_Variable_Assignment --
- -------------------------------------
+ ---------------------------------
+ -- Build_Subprogram_Invocation --
+ ---------------------------------
- function Is_Suitable_Variable_Assignment (N : Node_Id) return Boolean is
- N_Unit : Node_Id;
- N_Unit_Id : Entity_Id;
- Nam : Node_Id;
- Var_Decl : Node_Id;
- Var_Id : Entity_Id;
- Var_Unit : Node_Id;
- Var_Unit_Id : Entity_Id;
+ function Build_Subprogram_Invocation
+ (Subp_Id : Entity_Id) return Node_Id
+ is
+ Marker : constant Node_Id := Make_Call_Marker (Sloc (Subp_Id));
+ Subp_Decl : constant Node_Id := Unit_Declaration_Node (Subp_Id);
- begin
- -- This scenario is relevant only when the static model is in effect
- -- because it is graph-dependent and does not involve any run-time
- -- checks. Allowing it in the dynamic model would create confusing
- -- noise.
+ begin
+ -- Create a dummy call marker which invokes the subprogram
- if not Static_Elaboration_Checks then
- return False;
+ Set_Is_Declaration_Level_Node (Marker, False);
+ Set_Is_Dispatching_Call (Marker, False);
+ Set_Is_Elaboration_Checks_OK_Node (Marker, False);
+ Set_Is_Elaboration_Warnings_OK_Node (Marker, False);
+ Set_Is_Ignored_Ghost_Node (Marker, False);
+ Set_Is_Source_Call (Marker, False);
+ Set_Is_SPARK_Mode_On_Node (Marker, False);
- -- Nothing to do when the scenario is not an assignment
+ -- Invoke the uniform canonical entity of the subprogram
- elsif Nkind (N) /= N_Assignment_Statement then
- return False;
+ Set_Target (Marker, Canonical_Subprogram (Subp_Id));
- -- Nothing to do for internally-generated assignments because they are
- -- assumed to be ABE safe.
+ -- Partially insert the marker into the tree
- elsif not Comes_From_Source (N) then
- return False;
+ Set_Parent (Marker, Parent (Subp_Decl));
- -- Assignments are ignored in GNAT mode on the assumption that they are
- -- ABE-safe. This behaviour parallels that of the old ABE mechanism.
+ return Marker;
+ end Build_Subprogram_Invocation;
- elsif GNAT_Mode then
- return False;
- end if;
+ ---------------------------
+ -- Build_Task_Activation --
+ ---------------------------
- Nam := Extract_Assignment_Name (N);
+ function Build_Task_Activation
+ (Task_Typ : Entity_Id;
+ In_State : Processing_In_State) return Node_Id
+ is
+ Loc : constant Source_Ptr := Sloc (Task_Typ);
+ Marker : constant Node_Id := Make_Call_Marker (Loc);
+ Task_Decl : constant Node_Id := Unit_Declaration_Node (Task_Typ);
- -- Sanitize the left hand side of the assignment
+ Activ_Id : Entity_Id;
+ Marker_Rep_Id : Scenario_Rep_Id;
+ Task_Obj : Entity_Id;
+ Task_Objs : NE_List.Doubly_Linked_List;
- if not Is_Entity_Name (Nam) then
- return False;
+ begin
+ -- Create a dummy call marker which activates some tasks
- elsif No (Entity (Nam)) then
- return False;
- end if;
+ Set_Is_Declaration_Level_Node (Marker, False);
+ Set_Is_Dispatching_Call (Marker, False);
+ Set_Is_Elaboration_Checks_OK_Node (Marker, False);
+ Set_Is_Elaboration_Warnings_OK_Node (Marker, False);
+ Set_Is_Ignored_Ghost_Node (Marker, False);
+ Set_Is_Source_Call (Marker, False);
+ Set_Is_SPARK_Mode_On_Node (Marker, False);
- Var_Id := Entity (Nam);
+ -- Invoke the appropriate version of Activate_Tasks
- -- Sanitize the variable
+ if Restricted_Profile then
+ Activ_Id := RTE (RE_Activate_Restricted_Tasks);
+ else
+ Activ_Id := RTE (RE_Activate_Tasks);
+ end if;
- if Var_Id = Any_Id then
- return False;
+ Set_Target (Marker, Activ_Id);
- elsif Ekind (Var_Id) /= E_Variable then
- return False;
- end if;
+ -- Partially insert the marker into the tree
- Var_Decl := Declaration_Node (Var_Id);
+ Set_Parent (Marker, Parent (Task_Decl));
- if Nkind (Var_Decl) /= N_Object_Declaration then
- return False;
- end if;
+ -- Create a dummy task object. Partially decorate the object because
+ -- it will not be inserted into the tree and analyzed.
- N_Unit_Id := Find_Top_Unit (N);
- N_Unit := Unit_Declaration_Node (N_Unit_Id);
+ Task_Obj := Make_Temporary (Loc, 'T');
+ Set_Ekind (Task_Obj, E_Variable);
+ Set_Etype (Task_Obj, Task_Typ);
- Var_Unit_Id := Find_Top_Unit (Var_Decl);
- Var_Unit := Unit_Declaration_Node (Var_Unit_Id);
+ -- Associate the dummy task object with the activation call
- -- To qualify, the assignment must meet the following prerequisites:
+ Task_Objs := NE_List.Create;
+ NE_List.Append (Task_Objs, Task_Obj);
- return
- Comes_From_Source (Var_Id)
+ Marker_Rep_Id := Scenario_Representation_Of (Marker, In_State);
+ Set_Activated_Task_Objects (Marker_Rep_Id, Task_Objs);
+ Set_Activated_Task_Type (Marker_Rep_Id, Task_Typ);
- -- The variable must be declared in the spec of compilation unit U
+ return Marker;
+ end Build_Task_Activation;
- and then Nkind (Var_Unit) = N_Package_Declaration
+ ----------------------------------
+ -- Declare_Invocation_Construct --
+ ----------------------------------
- -- Performance note: parent traversal
+ procedure Declare_Invocation_Construct
+ (Constr_Id : Entity_Id;
+ In_State : Processing_In_State)
+ is
+ function Kind_Of (Id : Entity_Id) return Invocation_Construct_Kind;
+ pragma Inline (Kind_Of);
+ -- Obtain the invocation construct kind of arbitrary entity Id
- and then Find_Enclosing_Level (Var_Decl) = Package_Spec
+ function Placement_Of (Id : Entity_Id) return Body_Placement_Kind;
+ pragma Inline (Placement_Of);
+ -- Obtain the body placement of arbitrary entity Id
- -- The assignment must occur in the body of compilation unit U
+ function Placement_Of_Node (N : Node_Id) return Body_Placement_Kind;
+ pragma Inline (Placement_Of_Node);
+ -- Obtain the body placement of arbitrary node N
- and then Nkind (N_Unit) = N_Package_Body
- and then Present (Corresponding_Body (Var_Unit))
- and then Corresponding_Body (Var_Unit) = N_Unit_Id;
- end Is_Suitable_Variable_Assignment;
+ -------------
+ -- Kind_Of --
+ -------------
- ------------------------------------
- -- Is_Suitable_Variable_Reference --
- ------------------------------------
+ function Kind_Of (Id : Entity_Id) return Invocation_Construct_Kind is
+ begin
+ if Id = Elab_Body_Id then
+ return Elaborate_Body_Procedure;
- function Is_Suitable_Variable_Reference (N : Node_Id) return Boolean is
- begin
- -- Expanded names and identifiers are intentionally ignored because they
- -- be folded, optimized away, etc. Variable references markers play the
- -- role of variable references and provide a uniform foundation for ABE
- -- processing.
+ elsif Id = Elab_Spec_Id then
+ return Elaborate_Spec_Procedure;
- return Nkind (N) = N_Variable_Reference_Marker;
- end Is_Suitable_Variable_Reference;
+ else
+ return Regular_Construct;
+ end if;
+ end Kind_Of;
- ------------------------------------
- -- Is_Synchronous_Suspension_Call --
- ------------------------------------
+ ------------------
+ -- Placement_Of --
+ ------------------
- function Is_Synchronous_Suspension_Call (N : Node_Id) return Boolean is
- Call_Attrs : Call_Attributes;
- Target_Id : Entity_Id;
+ function Placement_Of (Id : Entity_Id) return Body_Placement_Kind is
+ Id_Rep : constant Target_Rep_Id :=
+ Target_Representation_Of (Id, In_State);
+ Body_Decl : constant Node_Id := Body_Declaration (Id_Rep);
+ Spec_Decl : constant Node_Id := Spec_Declaration (Id_Rep);
- begin
- -- To qualify, the call must invoke one of the runtime routines which
- -- perform synchronous suspension.
+ begin
+ -- The entity has a body
- if Is_Suitable_Call (N) then
- Extract_Call_Attributes
- (Call => N,
- Target_Id => Target_Id,
- Attrs => Call_Attrs);
+ if Present (Body_Decl) then
+ return Placement_Of_Node (Body_Decl);
- return
- Is_RTE (Target_Id, RE_Suspend_Until_True)
- or else
- Is_RTE (Target_Id, RE_Wait_For_Release);
- end if;
+ -- Otherwise the entity must have a spec
- return False;
- end Is_Synchronous_Suspension_Call;
+ else
+ pragma Assert (Present (Spec_Decl));
+ return Placement_Of_Node (Spec_Decl);
+ end if;
+ end Placement_Of;
- -------------------
- -- Is_Task_Entry --
- -------------------
+ -----------------------
+ -- Placement_Of_Node --
+ -----------------------
- function Is_Task_Entry (Id : Entity_Id) return Boolean is
- begin
- -- To qualify, the entity must denote an entry defined in a task type
+ function Placement_Of_Node (N : Node_Id) return Body_Placement_Kind is
+ Main_Unit_Id : constant Entity_Id := Cunit_Entity (Main_Unit);
+ N_Unit_Id : constant Entity_Id := Find_Top_Unit (N);
- return
- Is_Entry (Id) and then Is_Task_Type (Non_Private_View (Scope (Id)));
- end Is_Task_Entry;
+ begin
+ -- The node is in the main unit, its placement depends on the main
+ -- unit kind.
- ------------------------
- -- Is_Up_Level_Target --
- ------------------------
+ if N_Unit_Id = Main_Unit_Id then
- function Is_Up_Level_Target (Target_Decl : Node_Id) return Boolean is
- Root : constant Node_Id := Root_Scenario;
+ -- The main unit is a body
- begin
- -- The root appears within the declaratons of a block statement, entry
- -- body, subprogram body, or task body ignoring enclosing packages. The
- -- root is always within the main unit. An up-level target is a notion
- -- applicable only to the static model because scenarios are reached by
- -- means of graph traversal started from a fixed declarative or library
- -- level.
+ if Ekind_In (Main_Unit_Id, E_Package_Body,
+ E_Subprogram_Body)
+ then
+ return In_Body;
- -- Performance note: parent traversal
+ -- The main unit is a stand-alone subprogram body
- if Static_Elaboration_Checks
- and then Find_Enclosing_Level (Root) = Declaration_Level
- then
- -- The target is within the main unit. It acts as an up-level target
- -- when it appears within a context which encloses the root.
+ elsif Ekind_In (Main_Unit_Id, E_Function, E_Procedure)
+ and then Nkind (Unit_Declaration_Node (Main_Unit_Id)) =
+ N_Subprogram_Body
+ then
+ return In_Body;
- -- package body Main_Unit is
- -- function Func ...; -- target
+ -- Otherwise the main unit is a spec
- -- procedure Proc is
- -- X : ... := Func; -- root scenario
+ else
+ return In_Spec;
+ end if;
- if In_Extended_Main_Code_Unit (Target_Decl) then
+ -- Otherwise the node is in the complementary unit of the main
+ -- unit. The main unit is a body, the node is in the spec.
- -- Performance note: parent traversal
+ elsif Ekind_In (Main_Unit_Id, E_Package_Body,
+ E_Subprogram_Body)
+ then
+ return In_Spec;
- return not In_Same_Context (Root, Target_Decl, Nested_OK => True);
+ -- The main unit is a spec, the node is in the body
- -- Otherwise the target is external to the main unit which makes it
- -- an up-level target.
+ else
+ return In_Body;
+ end if;
+ end Placement_Of_Node;
- else
- return True;
- end if;
- end if;
+ -- Local variables
- return False;
- end Is_Up_Level_Target;
+ IC_Rec : Invocation_Construct_Record;
- ---------------------
- -- Is_Visited_Body --
- ---------------------
+ -- Start of processing for Declare_Invocation_Construct
- function Is_Visited_Body (Body_Decl : Node_Id) return Boolean is
- begin
- if Visited_Bodies_In_Use then
- return Visited_Bodies.Get (Body_Decl);
- end if;
+ begin
+ -- Nothing to do when the construct has already been declared in the
+ -- ALI file.
- return Visited_Bodies_No_Element;
- end Is_Visited_Body;
+ if Is_Saved_Construct (Constr_Id) then
+ return;
+ end if;
- -------------------------------
- -- Kill_Elaboration_Scenario --
- -------------------------------
+ -- Mark the construct as declared in the ALI file
- procedure Kill_Elaboration_Scenario (N : Node_Id) is
- procedure Kill_SPARK_Scenario;
- pragma Inline (Kill_SPARK_Scenario);
- -- Eliminate scenario N from table SPARK_Scenarios if it is recorded
- -- there.
+ Set_Is_Saved_Construct (Constr_Id);
- procedure Kill_Top_Level_Scenario;
- pragma Inline (Kill_Top_Level_Scenario);
- -- Eliminate scenario N from table Top_Level_Scenarios if it is recorded
- -- there.
+ IC_Rec.Kind := Kind_Of (Constr_Id);
+ IC_Rec.Placement := Placement_Of (Constr_Id);
+ IC_Rec.Signature := Signature_Of (Constr_Id);
- -------------------------
- -- Kill_SPARK_Scenario --
- -------------------------
+ -- Add the construct in the ALI file
- procedure Kill_SPARK_Scenario is
- package Scenarios renames SPARK_Scenarios;
+ Add_Invocation_Construct
+ (IC_Rec => IC_Rec,
+ Update_Units => False);
+ end Declare_Invocation_Construct;
- begin
- if Is_Recorded_SPARK_Scenario (N) then
+ -------------------------------
+ -- Finalize_Invocation_Graph --
+ -------------------------------
- -- Performance note: list traversal
+ procedure Finalize_Invocation_Graph is
+ begin
+ NE_Set.Destroy (Saved_Constructs_Set);
+ IR_Set.Destroy (Saved_Relations_Set);
+ end Finalize_Invocation_Graph;
- for Index in Scenarios.First .. Scenarios.Last loop
- if Scenarios.Table (Index) = N then
- Scenarios.Table (Index) := Empty;
+ ----------
+ -- Hash --
+ ----------
- -- The SPARK scenario is no longer recorded
+ function Hash (Key : Invoker_Target_Relation) return Bucket_Range_Type is
+ pragma Assert (Present (Key.Invoker));
+ pragma Assert (Present (Key.Target));
- Set_Is_Recorded_SPARK_Scenario (N, False);
- return;
- end if;
- end loop;
+ begin
+ return
+ Hash_Two_Keys
+ (Bucket_Range_Type (Key.Invoker),
+ Bucket_Range_Type (Key.Target));
+ end Hash;
- -- A recorded SPARK scenario must be in the table of recorded
- -- SPARK scenarios.
+ ---------------------------------
+ -- Initialize_Invocation_Graph --
+ ---------------------------------
- pragma Assert (False);
- end if;
- end Kill_SPARK_Scenario;
+ procedure Initialize_Invocation_Graph is
+ begin
+ Saved_Constructs_Set := NE_Set.Create (100);
+ Saved_Relations_Set := IR_Set.Create (200);
+ end Initialize_Invocation_Graph;
- -----------------------------
- -- Kill_Top_Level_Scenario --
- -----------------------------
+ -----------------------------------
+ -- Invocation_Graph_Recording_OK --
+ -----------------------------------
- procedure Kill_Top_Level_Scenario is
- package Scenarios renames Top_Level_Scenarios;
+ function Invocation_Graph_Recording_OK return Boolean is
+ Main_Cunit : constant Node_Id := Cunit (Main_Unit);
begin
- if Is_Recorded_Top_Level_Scenario (N) then
+ -- Nothing to do when switch -gnatd_G (encode invocation graph in ALI
+ -- files) is not in effect.
- -- Performance node: list traversal
+ if not Debug_Flag_Underscore_GG then
+ return False;
- for Index in Scenarios.First .. Scenarios.Last loop
- if Scenarios.Table (Index) = N then
- Scenarios.Table (Index) := Empty;
+ -- Nothing to do when compiling for GNATprove because the invocation
+ -- graph is not needed.
- -- The top-level scenario is no longer recorded
+ elsif GNATprove_Mode then
+ return False;
- Set_Is_Recorded_Top_Level_Scenario (N, False);
- return;
- end if;
- end loop;
+ -- Nothing to do when the compilation will not produce an ALI file
- -- A recorded top-level scenario must be in the table of recorded
- -- top-level scenarios.
+ elsif Serious_Errors_Detected > 0 then
+ return False;
- pragma Assert (False);
- end if;
- end Kill_Top_Level_Scenario;
+ -- Nothing to do when the main unit requires a body. Processing the
+ -- completing body will create the ALI file for the unit and record
+ -- the invocation graph.
- -- Start of processing for Kill_Elaboration_Scenario
+ elsif Body_Required (Main_Cunit) then
+ return False;
+ end if;
- begin
- -- Nothing to do when switch -gnatH (legacy elaboration checking mode
- -- enabled) is in effect because the legacy ABE lechanism does not need
- -- to carry out this action.
+ return True;
+ end Invocation_Graph_Recording_OK;
- if Legacy_Elaboration_Checks then
- return;
- end if;
+ ----------------------------
+ -- Is_Invocation_Scenario --
+ ----------------------------
- -- Eliminate a recorded scenario when it appears within dead code
- -- because it will not be executed at elaboration time.
+ function Is_Invocation_Scenario (N : Node_Id) return Boolean is
+ begin
+ return
+ Is_Suitable_Access_Taken (N)
+ or else Is_Suitable_Call (N)
+ or else Is_Suitable_Instantiation (N);
+ end Is_Invocation_Scenario;
- if Is_Scenario (N) then
- Kill_SPARK_Scenario;
- Kill_Top_Level_Scenario;
- end if;
- end Kill_Elaboration_Scenario;
+ --------------------------
+ -- Is_Invocation_Target --
+ --------------------------
- ----------------------------------
- -- Meet_Elaboration_Requirement --
- ----------------------------------
+ function Is_Invocation_Target (Id : Entity_Id) return Boolean is
+ begin
+ -- To qualify, the entity must either come from source, or denote an
+ -- Ada, bridge, or SPARK target.
- procedure Meet_Elaboration_Requirement
- (N : Node_Id;
- Target_Id : Entity_Id;
- Req_Nam : Name_Id)
- is
- Main_Id : constant Entity_Id := Cunit_Entity (Main_Unit);
- Unit_Id : constant Entity_Id := Find_Top_Unit (Target_Id);
+ return
+ Comes_From_Source (Id)
+ or else Is_Ada_Semantic_Target (Id)
+ or else Is_Bridge_Target (Id)
+ or else Is_SPARK_Semantic_Target (Id);
+ end Is_Invocation_Target;
+
+ ------------------------
+ -- Is_Saved_Construct --
+ ------------------------
+
+ function Is_Saved_Construct (Constr : Entity_Id) return Boolean is
+ pragma Assert (Present (Constr));
+ begin
+ return NE_Set.Contains (Saved_Constructs_Set, Constr);
+ end Is_Saved_Construct;
- function Find_Preelaboration_Pragma
- (Prag_Nam : Name_Id) return Node_Id;
- pragma Inline (Find_Preelaboration_Pragma);
- -- Traverse the visible declarations of unit Unit_Id and locate a source
- -- preelaboration-related pragma with name Prag_Nam.
+ -----------------------
+ -- Is_Saved_Relation --
+ -----------------------
- procedure Info_Requirement_Met (Prag : Node_Id);
- pragma Inline (Info_Requirement_Met);
- -- Output information concerning pragma Prag which meets requirement
- -- Req_Nam.
+ function Is_Saved_Relation
+ (Rel : Invoker_Target_Relation) return Boolean
+ is
+ pragma Assert (Present (Rel.Invoker));
+ pragma Assert (Present (Rel.Target));
- procedure Info_Scenario;
- pragma Inline (Info_Scenario);
- -- Output information concerning scenario N
+ begin
+ return IR_Set.Contains (Saved_Relations_Set, Rel);
+ end Is_Saved_Relation;
- --------------------------------
- -- Find_Preelaboration_Pragma --
- --------------------------------
+ --------------------------
+ -- Process_Declarations --
+ --------------------------
- function Find_Preelaboration_Pragma
- (Prag_Nam : Name_Id) return Node_Id
+ procedure Process_Declarations
+ (Decls : List_Id;
+ In_State : Processing_In_State)
is
- Spec : constant Node_Id := Parent (Unit_Id);
Decl : Node_Id;
begin
- -- A preelaboration-related pragma comes from source and appears at
- -- the top of the visible declarations of a package.
+ Decl := First (Decls);
+ while Present (Decl) loop
- if Nkind (Spec) = N_Package_Specification then
- Decl := First (Visible_Declarations (Spec));
- while Present (Decl) loop
- if Comes_From_Source (Decl) then
- if Nkind (Decl) = N_Pragma
- and then Pragma_Name (Decl) = Prag_Nam
- then
- return Decl;
+ -- Freeze node
- -- Otherwise the construct terminates the region where the
- -- preelaboration-related pragma may appear.
+ if Nkind (Decl) = N_Freeze_Entity then
+ Process_Freeze_Node
+ (Fnode => Decl,
+ In_State => In_State);
- else
- exit;
- end if;
- end if;
+ -- Package (nested)
- Next (Decl);
- end loop;
- end if;
+ elsif Nkind (Decl) = N_Package_Declaration then
+ Process_Package_Declaration
+ (Pack_Decl => Decl,
+ In_State => In_State);
- return Empty;
- end Find_Preelaboration_Pragma;
+ -- Protected type
- --------------------------
- -- Info_Requirement_Met --
- --------------------------
+ elsif Nkind_In (Decl, N_Protected_Type_Declaration,
+ N_Single_Protected_Declaration)
+ then
+ Process_Protected_Type_Declaration
+ (Prot_Decl => Decl,
+ In_State => In_State);
+
+ -- Subprogram or entry
+
+ elsif Nkind_In (Decl, N_Entry_Declaration,
+ N_Subprogram_Declaration)
+ then
+ Process_Subprogram_Declaration
+ (Subp_Decl => Decl,
+ In_State => In_State);
+
+ -- Subprogram body (stand alone)
+
+ elsif Nkind (Decl) = N_Subprogram_Body
+ and then No (Corresponding_Spec (Decl))
+ then
+ Process_Subprogram_Declaration
+ (Subp_Decl => Decl,
+ In_State => In_State);
+
+ -- Subprogram instantiation
+
+ elsif Nkind (Decl) in N_Subprogram_Instantiation then
+ Process_Subprogram_Instantiation
+ (Inst => Decl,
+ In_State => In_State);
+
+ -- Task type
- procedure Info_Requirement_Met (Prag : Node_Id) is
+ elsif Nkind_In (Decl, N_Single_Task_Declaration,
+ N_Task_Type_Declaration)
+ then
+ Process_Task_Type_Declaration
+ (Task_Decl => Decl,
+ In_State => In_State);
+
+ -- Task type (derived)
+
+ elsif Nkind (Decl) = N_Full_Type_Declaration
+ and then Is_Task_Type (Defining_Entity (Decl))
+ then
+ Process_Task_Type_Declaration
+ (Task_Decl => Decl,
+ In_State => In_State);
+ end if;
+
+ Next (Decl);
+ end loop;
+ end Process_Declarations;
+
+ -------------------------
+ -- Process_Freeze_Node --
+ -------------------------
+
+ procedure Process_Freeze_Node
+ (Fnode : Node_Id;
+ In_State : Processing_In_State)
+ is
begin
- pragma Assert (Present (Prag));
+ Process_Declarations
+ (Decls => Actions (Fnode),
+ In_State => In_State);
+ end Process_Freeze_Node;
- Error_Msg_Name_1 := Req_Nam;
- Error_Msg_Sloc := Sloc (Prag);
- Error_Msg_NE
- ("\\% requirement for unit & met by pragma #", N, Unit_Id);
- end Info_Requirement_Met;
+ -----------------------------------
+ -- Process_Invocation_Activation --
+ -----------------------------------
- -------------------
- -- Info_Scenario --
- -------------------
+ procedure Process_Invocation_Activation
+ (Call : Node_Id;
+ Call_Rep : Scenario_Rep_Id;
+ Obj_Id : Entity_Id;
+ Obj_Rep : Target_Rep_Id;
+ Task_Typ : Entity_Id;
+ Task_Rep : Target_Rep_Id;
+ In_State : Processing_In_State)
+ is
+ pragma Unreferenced (Call);
+ pragma Unreferenced (Call_Rep);
+ pragma Unreferenced (Obj_Id);
+ pragma Unreferenced (Obj_Rep);
- procedure Info_Scenario is
begin
- if Is_Suitable_Call (N) then
- Info_Call
- (Call => N,
- Target_Id => Target_Id,
- Info_Msg => False,
- In_SPARK => True);
+ -- Nothing to do when the task type appears within an internal unit
- elsif Is_Suitable_Instantiation (N) then
- Info_Instantiation
- (Inst => N,
- Gen_Id => Target_Id,
- Info_Msg => False,
- In_SPARK => True);
+ if In_Internal_Unit (Task_Typ) then
+ return;
+ end if;
- elsif Is_Suitable_SPARK_Refined_State_Pragma (N) then
- Error_Msg_N
- ("read of refinement constituents during elaboration in SPARK",
- N);
+ -- The task type being activated is within the main unit. Extend the
+ -- DFS traversal into its body.
- elsif Is_Suitable_Variable_Reference (N) then
- Info_Variable_Reference
- (Ref => N,
- Var_Id => Target_Id,
- Info_Msg => False,
- In_SPARK => True);
+ if In_Extended_Main_Code_Unit (Task_Typ) then
+ Traverse_Invocation_Body
+ (N => Body_Declaration (Task_Rep),
+ In_State => In_State);
- -- No other scenario may impose a requirement on the context of the
- -- main unit.
+ -- The task type being activated resides within an external unit
+ --
+ -- Main unit External unit
+ -- +-----------+ +-------------+
+ -- | | | |
+ -- | Start ------------> Task_Typ |
+ -- | | | |
+ -- +-----------+ +-------------+
+ --
+ -- Record the invocation path which originates from Start and reaches
+ -- the task type.
else
- pragma Assert (False);
- null;
+ Record_Invocation_Path (In_State);
end if;
- end Info_Scenario;
-
- -- Local variables
+ end Process_Invocation_Activation;
- Elab_Attrs : Elaboration_Attributes;
- Elab_Nam : Name_Id;
- Req_Met : Boolean;
+ ---------------------------------------
+ -- Process_Invocation_Body_Scenarios --
+ ---------------------------------------
- -- Start of processing for Meet_Elaboration_Requirement
+ procedure Process_Invocation_Body_Scenarios is
+ Iter : NE_Set.Iterator := Iterate_Library_Body_Scenarios;
+ begin
+ Process_Invocation_Scenarios
+ (Iter => Iter,
+ In_State => Invocation_Body_State);
+ end Process_Invocation_Body_Scenarios;
- begin
- pragma Assert (Nam_In (Req_Nam, Name_Elaborate, Name_Elaborate_All));
+ -----------------------------
+ -- Process_Invocation_Call --
+ -----------------------------
- -- Assume that the requirement has not been met
+ procedure Process_Invocation_Call
+ (Call : Node_Id;
+ Call_Rep : Scenario_Rep_Id;
+ In_State : Processing_In_State)
+ is
+ pragma Unreferenced (Call);
- Req_Met := False;
+ Subp_Id : constant Entity_Id := Target (Call_Rep);
+ Subp_Rep : constant Target_Rep_Id :=
+ Target_Representation_Of (Subp_Id, In_State);
- -- Elaboration requirements are verified only when the static model is
- -- in effect because this diagnostic is graph-dependent.
+ begin
+ -- Nothing to do when the subprogram appears within an internal unit
- if not Static_Elaboration_Checks then
- return;
+ if In_Internal_Unit (Subp_Id) then
+ return;
- -- If the target is within the main unit, either at the source level or
- -- through an instantiation, then there is no real requirement to meet
- -- because the main unit cannot force its own elaboration by means of an
- -- Elaborate[_All] pragma. Treat this case as valid coverage.
+ -- Nothing to do for an abstract subprogram because it has no body to
+ -- examine.
- elsif In_Extended_Main_Code_Unit (Target_Id) then
- Req_Met := True;
+ elsif Ekind_In (Subp_Id, E_Function, E_Procedure)
+ and then Is_Abstract_Subprogram (Subp_Id)
+ then
+ return;
- -- Otherwise the target resides in an external unit
+ -- Nothin to do for a formal subprogram because it has no body to
+ -- examine.
- -- The requirement is met when the target comes from an internal unit
- -- because such a unit is elaborated prior to a non-internal unit.
+ elsif Is_Formal_Subprogram (Subp_Id) then
+ return;
+ end if;
- elsif In_Internal_Unit (Unit_Id)
- and then not In_Internal_Unit (Main_Id)
- then
- Req_Met := True;
+ -- The subprogram being called is within the main unit. Extend the
+ -- DFS traversal into its barrier function and body.
- -- The requirement is met when the target comes from a preelaborated
- -- unit. This portion must parallel predicate Is_Preelaborated_Unit.
+ if In_Extended_Main_Code_Unit (Subp_Id) then
+ if Ekind_In (Subp_Id, E_Entry, E_Entry_Family, E_Procedure) then
+ Traverse_Invocation_Body
+ (N => Barrier_Body_Declaration (Subp_Rep),
+ In_State => In_State);
+ end if;
- elsif Is_Preelaborated_Unit (Unit_Id) then
- Req_Met := True;
+ Traverse_Invocation_Body
+ (N => Body_Declaration (Subp_Rep),
+ In_State => In_State);
- -- Output extra information when switch -gnatel (info messages on
- -- implicit Elaborate[_All] pragmas.
+ -- The subprogram being called resides within an external unit
+ --
+ -- Main unit External unit
+ -- +-----------+ +-------------+
+ -- | | | |
+ -- | Start ------------> Subp_Id |
+ -- | | | |
+ -- +-----------+ +-------------+
+ --
+ -- Record the invocation path which originates from Start and reaches
+ -- the subprogram.
- if Elab_Info_Messages then
- if Is_Preelaborated (Unit_Id) then
- Elab_Nam := Name_Preelaborate;
+ else
+ Record_Invocation_Path (In_State);
+ end if;
+ end Process_Invocation_Call;
- elsif Is_Pure (Unit_Id) then
- Elab_Nam := Name_Pure;
+ ---------------------------------
+ -- Process_Invocation_Scenario --
+ ---------------------------------
- elsif Is_Remote_Call_Interface (Unit_Id) then
- Elab_Nam := Name_Remote_Call_Interface;
+ procedure Process_Invocation_Scenario
+ (N : Node_Id;
+ In_State : Processing_In_State)
+ is
+ Scen : constant Node_Id := Scenario (N);
+ Scen_Rep : Scenario_Rep_Id;
- elsif Is_Remote_Types (Unit_Id) then
- Elab_Nam := Name_Remote_Types;
+ begin
+ -- Add the current scenario to the stack of active scenarios
- else
- pragma Assert (Is_Shared_Passive (Unit_Id));
- Elab_Nam := Name_Shared_Passive;
- end if;
+ Push_Active_Scenario (Scen);
- Info_Requirement_Met (Find_Preelaboration_Pragma (Elab_Nam));
- end if;
+ -- Call or task activation
- -- Determine whether the context of the main unit has a pragma strong
- -- enough to meet the requirement.
+ if Is_Suitable_Call (Scen) then
+ Scen_Rep := Scenario_Representation_Of (Scen, In_State);
- else
- Elab_Attrs := Elaboration_Status (Unit_Id);
+ -- Routine Build_Call_Marker creates call markers regardless of
+ -- whether the call occurs within the main unit or not. This way
+ -- the serialization of internal names is kept consistent. Only
+ -- call markers found within the main unit must be processed.
- -- The pragma must be either Elaborate_All or be as strong as the
- -- requirement.
+ if In_Main_Context (Scen) then
+ Scen_Rep := Scenario_Representation_Of (Scen, In_State);
- if Present (Elab_Attrs.Source_Pragma)
- and then Nam_In (Pragma_Name (Elab_Attrs.Source_Pragma),
- Name_Elaborate_All,
- Req_Nam)
- then
- Req_Met := True;
+ if Kind (Scen_Rep) = Call_Scenario then
+ Process_Invocation_Call
+ (Call => Scen,
+ Call_Rep => Scen_Rep,
+ In_State => In_State);
- -- Output extra information when switch -gnatel (info messages on
- -- implicit Elaborate[_All] pragmas.
+ else
+ pragma Assert (Kind (Scen_Rep) = Task_Activation_Scenario);
- if Elab_Info_Messages then
- Info_Requirement_Met (Elab_Attrs.Source_Pragma);
+ Process_Activation
+ (Call => Scen,
+ Call_Rep => Scen_Rep,
+ Processor => Process_Invocation_Activation'Access,
+ In_State => In_State);
+ end if;
end if;
end if;
- end if;
-
- -- The requirement was not met by the context of the main unit, issue an
- -- error.
- if not Req_Met then
- Info_Scenario;
+ -- Remove the current scenario from the stack of active scenarios
+ -- once all invocation constructs and paths have been saved.
- Error_Msg_Name_1 := Req_Nam;
- Error_Msg_Node_2 := Unit_Id;
- Error_Msg_NE ("\\unit & requires pragma % for &", N, Main_Id);
+ Pop_Active_Scenario (Scen);
+ end Process_Invocation_Scenario;
- Output_Active_Scenarios (N);
- end if;
- end Meet_Elaboration_Requirement;
+ ----------------------------------
+ -- Process_Invocation_Scenarios --
+ ----------------------------------
- ----------------------
- -- Non_Private_View --
- ----------------------
+ procedure Process_Invocation_Scenarios
+ (Iter : in out NE_Set.Iterator;
+ In_State : Processing_In_State)
+ is
+ N : Node_Id;
- function Non_Private_View (Typ : Entity_Id) return Entity_Id is
- begin
- if Is_Private_Type (Typ) and then Present (Full_View (Typ)) then
- return Full_View (Typ);
- else
- return Typ;
- end if;
- end Non_Private_View;
+ begin
+ while NE_Set.Has_Next (Iter) loop
+ NE_Set.Next (Iter, N);
- -----------------------------
- -- Output_Active_Scenarios --
- -----------------------------
+ -- Reset the traversed status of all subprogram bodies because the
+ -- current invocation scenario acts as a new DFS traversal root.
- procedure Output_Active_Scenarios (Error_Nod : Node_Id) is
- procedure Output_Access (N : Node_Id);
- -- Emit a specific diagnostic message for 'Access denote by N
+ Reset_Traversed_Bodies;
- procedure Output_Activation_Call (N : Node_Id);
- -- Emit a specific diagnostic message for task activation N
+ Process_Invocation_Scenario (N, In_State);
+ end loop;
+ end Process_Invocation_Scenarios;
- procedure Output_Call (N : Node_Id; Target_Id : Entity_Id);
- -- Emit a specific diagnostic message for call N which invokes target
- -- Target_Id.
+ ---------------------------------------
+ -- Process_Invocation_Spec_Scenarios --
+ ---------------------------------------
- procedure Output_Header;
- -- Emit a specific diagnostic message for the unit of the root scenario
+ procedure Process_Invocation_Spec_Scenarios is
+ Iter : NE_Set.Iterator := Iterate_Library_Spec_Scenarios;
+ begin
+ Process_Invocation_Scenarios
+ (Iter => Iter,
+ In_State => Invocation_Spec_State);
+ end Process_Invocation_Spec_Scenarios;
- procedure Output_Instantiation (N : Node_Id);
- -- Emit a specific diagnostic message for instantiation N
+ -----------------------
+ -- Process_Main_Unit --
+ -----------------------
- procedure Output_SPARK_Refined_State_Pragma (N : Node_Id);
- -- Emit a specific diagnostic message for Refined_State pragma N
+ procedure Process_Main_Unit is
+ Unit_Decl : constant Node_Id := Unit (Cunit (Main_Unit));
+ Spec_Id : Entity_Id;
- procedure Output_Variable_Assignment (N : Node_Id);
- -- Emit a specific diagnostic message for assignment statement N
+ begin
+ -- The main unit is a [generic] package body
- procedure Output_Variable_Reference (N : Node_Id);
- -- Emit a specific diagnostic message for reference N which mentions a
- -- variable.
+ if Nkind (Unit_Decl) = N_Package_Body then
+ Spec_Id := Corresponding_Spec (Unit_Decl);
+ pragma Assert (Present (Spec_Id));
- -------------------
- -- Output_Access --
- -------------------
+ Process_Package_Declaration
+ (Pack_Decl => Unit_Declaration_Node (Spec_Id),
+ In_State => Invocation_Construct_State);
- procedure Output_Access (N : Node_Id) is
- Subp_Id : constant Entity_Id := Entity (Prefix (N));
+ -- The main unit is a [generic] package declaration
- begin
- Error_Msg_Name_1 := Attribute_Name (N);
- Error_Msg_Sloc := Sloc (N);
- Error_Msg_NE ("\\ % of & taken #", Error_Nod, Subp_Id);
- end Output_Access;
+ elsif Nkind (Unit_Decl) = N_Package_Declaration then
+ Process_Package_Declaration
+ (Pack_Decl => Unit_Decl,
+ In_State => Invocation_Construct_State);
- ----------------------------
- -- Output_Activation_Call --
- ----------------------------
+ -- The main unit is a [generic] subprogram body
- procedure Output_Activation_Call (N : Node_Id) is
- function Find_Activator (Call : Node_Id) return Entity_Id;
- -- Find the nearest enclosing construct which houses call Call
+ elsif Nkind (Unit_Decl) = N_Subprogram_Body then
+ Spec_Id := Corresponding_Spec (Unit_Decl);
- --------------------
- -- Find_Activator --
- --------------------
+ -- The body completes a previous declaration
- function Find_Activator (Call : Node_Id) return Entity_Id is
- Par : Node_Id;
+ if Present (Spec_Id) then
+ Process_Subprogram_Declaration
+ (Subp_Decl => Unit_Declaration_Node (Spec_Id),
+ In_State => Invocation_Construct_State);
- begin
- -- Climb the parent chain looking for a package [body] or a
- -- construct with a statement sequence.
+ -- Otherwise the body is stand-alone
- Par := Parent (Call);
- while Present (Par) loop
- if Nkind_In (Par, N_Package_Body, N_Package_Declaration) then
- return Defining_Entity (Par);
+ else
+ Process_Subprogram_Declaration
+ (Subp_Decl => Unit_Decl,
+ In_State => Invocation_Construct_State);
+ end if;
- elsif Nkind (Par) = N_Handled_Sequence_Of_Statements then
- return Defining_Entity (Parent (Par));
- end if;
+ -- The main unit is a subprogram instantiation
- Par := Parent (Par);
- end loop;
+ elsif Nkind (Unit_Decl) in N_Subprogram_Instantiation then
+ Process_Subprogram_Instantiation
+ (Inst => Unit_Decl,
+ In_State => Invocation_Construct_State);
- return Empty;
- end Find_Activator;
+ -- The main unit is an imported subprogram declaration
- -- Local variables
+ elsif Nkind (Unit_Decl) = N_Subprogram_Declaration then
+ Process_Subprogram_Declaration
+ (Subp_Decl => Unit_Decl,
+ In_State => Invocation_Construct_State);
+ end if;
+ end Process_Main_Unit;
- Activator : constant Entity_Id := Find_Activator (N);
+ ---------------------------------
+ -- Process_Package_Declaration --
+ ---------------------------------
- -- Start of processing for Output_Activation_Call
+ procedure Process_Package_Declaration
+ (Pack_Decl : Node_Id;
+ In_State : Processing_In_State)
+ is
+ Body_Id : constant Entity_Id := Corresponding_Body (Pack_Decl);
+ Spec : constant Node_Id := Specification (Pack_Decl);
+ Spec_Id : constant Entity_Id := Defining_Entity (Pack_Decl);
begin
- pragma Assert (Present (Activator));
+ -- Add a declaration for the generic package in the ALI of the main
+ -- unit in case a client unit instantiates it.
- Error_Msg_NE ("\\ local tasks of & activated", Error_Nod, Activator);
- end Output_Activation_Call;
+ if Ekind (Spec_Id) = E_Generic_Package then
+ Declare_Invocation_Construct
+ (Constr_Id => Spec_Id,
+ In_State => In_State);
- -----------------
- -- Output_Call --
- -----------------
+ -- Otherwise inspect the visible and private declarations of the
+ -- package for invocation constructs.
- procedure Output_Call (N : Node_Id; Target_Id : Entity_Id) is
- procedure Output_Accept_Alternative;
- pragma Inline (Output_Accept_Alternative);
- -- Emit a specific diagnostic message concerning an accept
- -- alternative.
+ else
+ Process_Declarations
+ (Decls => Visible_Declarations (Spec),
+ In_State => In_State);
+
+ Process_Declarations
+ (Decls => Private_Declarations (Spec),
+ In_State => In_State);
+
+ -- The package body containst at least one generic unit or an
+ -- inlinable subprogram. Such constructs may grant clients of
+ -- the main unit access to the private enclosing contexts of
+ -- the constructs. Process the main unit body to discover and
+ -- encode relevant invocation constructs and relations that
+ -- may ultimately reach an external unit.
+
+ if Present (Body_Id)
+ and then Save_Invocation_Graph_Of_Body (Cunit (Main_Unit))
+ then
+ Process_Declarations
+ (Decls => Declarations (Unit_Declaration_Node (Body_Id)),
+ In_State => In_State);
+ end if;
+ end if;
+ end Process_Package_Declaration;
- procedure Output_Call (Kind : String);
- pragma Inline (Output_Call);
- -- Emit a specific diagnostic message concerning a call of kind Kind
+ ----------------------------------------
+ -- Process_Protected_Type_Declaration --
+ ----------------------------------------
- procedure Output_Type_Actions (Action : String);
- pragma Inline (Output_Type_Actions);
- -- Emit a specific diagnostic message concerning action Action of a
- -- type.
+ procedure Process_Protected_Type_Declaration
+ (Prot_Decl : Node_Id;
+ In_State : Processing_In_State)
+ is
+ Prot_Def : constant Node_Id := Protected_Definition (Prot_Decl);
- procedure Output_Verification_Call
- (Pred : String;
- Id : Entity_Id;
- Id_Kind : String);
- pragma Inline (Output_Verification_Call);
- -- Emit a specific diagnostic message concerning the verification of
- -- predicate Pred applied to related entity Id with kind Id_Kind.
+ begin
+ if Present (Prot_Def) then
+ Process_Declarations
+ (Decls => Visible_Declarations (Prot_Def),
+ In_State => In_State);
+ end if;
+ end Process_Protected_Type_Declaration;
- -------------------------------
- -- Output_Accept_Alternative --
- -------------------------------
+ ------------------------------------
+ -- Process_Subprogram_Declaration --
+ ------------------------------------
+
+ procedure Process_Subprogram_Declaration
+ (Subp_Decl : Node_Id;
+ In_State : Processing_In_State)
+ is
+ Subp_Id : constant Entity_Id := Defining_Entity (Subp_Decl);
- procedure Output_Accept_Alternative is
- Entry_Id : constant Entity_Id := Receiving_Entry (Target_Id);
+ begin
+ -- Nothing to do when the subprogram is not an invocation target
- begin
- pragma Assert (Present (Entry_Id));
+ if not Is_Invocation_Target (Subp_Id) then
+ return;
+ end if;
- Error_Msg_NE ("\\ entry & selected #", Error_Nod, Entry_Id);
- end Output_Accept_Alternative;
+ -- Add a declaration for the subprogram in the ALI file of the main
+ -- unit in case a client unit calls or instantiates it.
- -----------------
- -- Output_Call --
- -----------------
+ Declare_Invocation_Construct
+ (Constr_Id => Subp_Id,
+ In_State => In_State);
- procedure Output_Call (Kind : String) is
- begin
- Error_Msg_NE ("\\ " & Kind & " & called #", Error_Nod, Target_Id);
- end Output_Call;
+ -- Do not process subprograms without a body because they do not
+ -- contain any invocation scenarios.
- -------------------------
- -- Output_Type_Actions --
- -------------------------
+ if Is_Bodiless_Subprogram (Subp_Id) then
+ null;
- procedure Output_Type_Actions (Action : String) is
- Typ : constant Entity_Id := First_Formal_Type (Target_Id);
+ -- Do not process generic subprograms because generics must not be
+ -- examined.
- begin
- pragma Assert (Present (Typ));
+ elsif Is_Generic_Subprogram (Subp_Id) then
+ null;
- Error_Msg_NE
- ("\\ " & Action & " actions for type & #", Error_Nod, Typ);
- end Output_Type_Actions;
+ -- Otherwise create a dummy scenario which calls the subprogram to
+ -- act as a root for a DFS traversal.
- ------------------------------
- -- Output_Verification_Call --
- ------------------------------
+ else
+ -- Reset the traversed status of all subprogram bodies because the
+ -- subprogram acts as a new DFS traversal root.
- procedure Output_Verification_Call
- (Pred : String;
- Id : Entity_Id;
- Id_Kind : String)
- is
- begin
- pragma Assert (Present (Id));
+ Reset_Traversed_Bodies;
- Error_Msg_NE
- ("\\ " & Pred & " of " & Id_Kind & " & verified #",
- Error_Nod, Id);
- end Output_Verification_Call;
+ Process_Invocation_Scenario
+ (N => Build_Subprogram_Invocation (Subp_Id),
+ In_State => In_State);
+ end if;
+ end Process_Subprogram_Declaration;
- -- Start of processing for Output_Call
+ --------------------------------------
+ -- Process_Subprogram_Instantiation --
+ --------------------------------------
+ procedure Process_Subprogram_Instantiation
+ (Inst : Node_Id;
+ In_State : Processing_In_State)
+ is
begin
- Error_Msg_Sloc := Sloc (N);
+ -- Add a declaration for the instantiation in the ALI file of the
+ -- main unit in case a client unit calls it.
- -- Accept alternative
+ Declare_Invocation_Construct
+ (Constr_Id => Defining_Entity (Inst),
+ In_State => In_State);
+ end Process_Subprogram_Instantiation;
- if Is_Accept_Alternative_Proc (Target_Id) then
- Output_Accept_Alternative;
+ -----------------------------------
+ -- Process_Task_Type_Declaration --
+ -----------------------------------
- -- Adjustment
+ procedure Process_Task_Type_Declaration
+ (Task_Decl : Node_Id;
+ In_State : Processing_In_State)
+ is
+ Task_Typ : constant Entity_Id := Defining_Entity (Task_Decl);
+ Task_Def : Node_Id;
- elsif Is_TSS (Target_Id, TSS_Deep_Adjust) then
- Output_Type_Actions ("adjustment");
+ begin
+ -- Add a declaration for the task type the ALI file of the main unit
+ -- in case a client unit creates a task object and activates it.
- -- Default_Initial_Condition
+ Declare_Invocation_Construct
+ (Constr_Id => Task_Typ,
+ In_State => In_State);
- elsif Is_Default_Initial_Condition_Proc (Target_Id) then
- Output_Verification_Call
- (Pred => "Default_Initial_Condition",
- Id => First_Formal_Type (Target_Id),
- Id_Kind => "type");
+ -- Process the entries of the task type because they represent valid
+ -- entry points into the task body.
- -- Entries
+ if Nkind_In (Task_Decl, N_Single_Task_Declaration,
+ N_Task_Type_Declaration)
+ then
+ Task_Def := Task_Definition (Task_Decl);
- elsif Is_Protected_Entry (Target_Id) then
- Output_Call ("entry");
+ if Present (Task_Def) then
+ Process_Declarations
+ (Decls => Visible_Declarations (Task_Def),
+ In_State => In_State);
+ end if;
+ end if;
- -- Task entry calls are never processed because the entry being
- -- invoked does not have a corresponding "body", it has a select. A
- -- task entry call appears in the stack of active scenarios for the
- -- sole purpose of checking No_Entry_Calls_In_Elaboration_Code and
- -- nothing more.
+ -- Reset the traversed status of all subprogram bodies because the
+ -- task type acts as a new DFS traversal root.
- elsif Is_Task_Entry (Target_Id) then
- null;
+ Reset_Traversed_Bodies;
- -- Finalization
+ -- Create a dummy scenario which activates an anonymous object of the
+ -- task type to acts as a root of a DFS traversal.
- elsif Is_TSS (Target_Id, TSS_Deep_Finalize) then
- Output_Type_Actions ("finalization");
+ Process_Invocation_Scenario
+ (N => Build_Task_Activation (Task_Typ, In_State),
+ In_State => In_State);
+ end Process_Task_Type_Declaration;
- -- Calls to _Finalizer procedures must not appear in the output
- -- because this creates confusing noise.
+ ---------------------------------
+ -- Record_Full_Invocation_Path --
+ ---------------------------------
- elsif Is_Finalizer_Proc (Target_Id) then
- null;
+ procedure Record_Full_Invocation_Path (In_State : Processing_In_State) is
+ package Scenarios renames Active_Scenario_Stack;
- -- Initial_Condition
+ begin
+ -- The path originates from the elaboration of the body. Add an extra
+ -- relation from the elaboration body procedure to the first active
+ -- scenario.
- elsif Is_Initial_Condition_Proc (Target_Id) then
- Output_Verification_Call
- (Pred => "Initial_Condition",
- Id => Find_Enclosing_Scope (N),
- Id_Kind => "package");
+ if In_State.Processing = Invocation_Body_Processing then
+ Build_Elaborate_Body_Procedure;
- -- Initialization
+ Record_Invocation_Relation
+ (Invk_Id => Elab_Body_Id,
+ Targ_Id => Target_Of (Scenarios.First, In_State),
+ In_State => In_State);
- elsif Is_Init_Proc (Target_Id)
- or else Is_TSS (Target_Id, TSS_Deep_Initialize)
- then
- Output_Type_Actions ("initialization");
+ -- The path originates from the elaboration of the spec. Add an extra
+ -- relation from the elaboration spec procedure to the first active
+ -- scenario.
- -- Invariant
+ elsif In_State.Processing = Invocation_Spec_Processing then
+ Build_Elaborate_Spec_Procedure;
- elsif Is_Invariant_Proc (Target_Id) then
- Output_Verification_Call
- (Pred => "invariants",
- Id => First_Formal_Type (Target_Id),
- Id_Kind => "type");
+ Record_Invocation_Relation
+ (Invk_Id => Elab_Spec_Id,
+ Targ_Id => Target_Of (Scenarios.First, In_State),
+ In_State => In_State);
+ end if;
- -- Partial invariant calls must not appear in the output because this
- -- creates confusing noise. Note that a partial invariant is always
- -- invoked by the "full" invariant which is already placed on the
- -- stack.
+ -- Record individual relations formed by pairs of scenarios
- elsif Is_Partial_Invariant_Proc (Target_Id) then
- null;
+ for Index in Scenarios.First .. Scenarios.Last - 1 loop
+ Record_Invocation_Relation
+ (Invk_Id => Target_Of (Index, In_State),
+ Targ_Id => Target_Of (Index + 1, In_State),
+ In_State => In_State);
+ end loop;
+ end Record_Full_Invocation_Path;
- -- _Postconditions
+ -----------------------------
+ -- Record_Invocation_Graph --
+ -----------------------------
- elsif Is_Postconditions_Proc (Target_Id) then
- Output_Verification_Call
- (Pred => "postconditions",
- Id => Find_Enclosing_Scope (N),
- Id_Kind => "subprogram");
+ procedure Record_Invocation_Graph is
+ begin
+ -- Nothing to do when the invocation graph is not recorded
- -- Subprograms must come last because some of the previous cases fall
- -- under this category.
+ if not Invocation_Graph_Recording_OK then
+ return;
+ end if;
- elsif Ekind (Target_Id) = E_Function then
- Output_Call ("function");
+ -- Examine all library level invocation scenarios and perform DFS
+ -- traversals from each one. Encode a path in the ALI file of the
+ -- main unit if it reaches into an external unit.
- elsif Ekind (Target_Id) = E_Procedure then
- Output_Call ("procedure");
+ Process_Invocation_Body_Scenarios;
+ Process_Invocation_Spec_Scenarios;
- else
- pragma Assert (False);
- null;
- end if;
- end Output_Call;
+ -- Examine all invocation constructs within the spec and body of the
+ -- main unit and perform DFS traversals from each one. Encode a path
+ -- in the ALI file of the main unit if it reaches into an external
+ -- unit.
- -------------------
- -- Output_Header --
- -------------------
+ Process_Main_Unit;
+ end Record_Invocation_Graph;
- procedure Output_Header is
- Unit_Id : constant Entity_Id := Find_Top_Unit (Root_Scenario);
+ ----------------------------
+ -- Record_Invocation_Path --
+ ----------------------------
+
+ procedure Record_Invocation_Path (In_State : Processing_In_State) is
+ package Scenarios renames Active_Scenario_Stack;
begin
- if Ekind (Unit_Id) = E_Package then
- Error_Msg_NE ("\\ spec of unit & elaborated", Error_Nod, Unit_Id);
+ -- Save a path when the active scenario stack contains at least one
+ -- invocation scenario.
- elsif Ekind (Unit_Id) = E_Package_Body then
- Error_Msg_NE ("\\ body of unit & elaborated", Error_Nod, Unit_Id);
+ if Scenarios.Last - Scenarios.First < 0 then
+ return;
+ end if;
+
+ -- Register all relations in the path when switch -gnatd_F (encode
+ -- full invocation paths in ALI files) is in effect.
+
+ if Debug_Flag_Underscore_FF then
+ Record_Full_Invocation_Path (In_State);
+
+ -- Otherwise register a single relation
else
- Error_Msg_NE ("\\ in body of unit &", Error_Nod, Unit_Id);
+ Record_Simple_Invocation_Path (In_State);
end if;
- end Output_Header;
- --------------------------
- -- Output_Instantiation --
- --------------------------
+ Write_Invocation_Path (In_State);
+ end Record_Invocation_Path;
- procedure Output_Instantiation (N : Node_Id) is
- procedure Output_Instantiation (Gen_Id : Entity_Id; Kind : String);
- pragma Inline (Output_Instantiation);
- -- Emit a specific diagnostic message concerning an instantiation of
- -- generic unit Gen_Id. Kind denotes the kind of the instantiation.
+ --------------------------------
+ -- Record_Invocation_Relation --
+ --------------------------------
- --------------------------
- -- Output_Instantiation --
- --------------------------
+ procedure Record_Invocation_Relation
+ (Invk_Id : Entity_Id;
+ Targ_Id : Entity_Id;
+ In_State : Processing_In_State)
+ is
+ pragma Assert (Present (Invk_Id));
+ pragma Assert (Present (Targ_Id));
- procedure Output_Instantiation (Gen_Id : Entity_Id; Kind : String) is
+ procedure Get_Invocation_Attributes
+ (Extra : out Entity_Id;
+ Kind : out Invocation_Kind);
+ pragma Inline (Get_Invocation_Attributes);
+ -- Return the additional entity used in error diagnostics in Extra
+ -- and the invocation kind in Kind which pertain to the invocation
+ -- relation with invoker Invk_Id and target Targ_Id.
+
+ -------------------------------
+ -- Get_Invocation_Attributes --
+ -------------------------------
+
+ procedure Get_Invocation_Attributes
+ (Extra : out Entity_Id;
+ Kind : out Invocation_Kind)
+ is
begin
- Error_Msg_NE
- ("\\ " & Kind & " & instantiated as & #", Error_Nod, Gen_Id);
- end Output_Instantiation;
+ -- Accept within a task body
- -- Local variables
+ if Is_Accept_Alternative_Proc (Targ_Id) then
+ Extra := Receiving_Entry (Targ_Id);
+ Kind := Accept_Alternative;
- Inst : Node_Id;
- Inst_Attrs : Instantiation_Attributes;
- Inst_Id : Entity_Id;
- Gen_Id : Entity_Id;
+ -- Activation of a task object
- -- Start of processing for Output_Instantiation
+ elsif Is_Activation_Proc (Targ_Id)
+ or else Is_Task_Type (Targ_Id)
+ then
+ Extra := Empty;
+ Kind := Task_Activation;
- begin
- Extract_Instantiation_Attributes
- (Exp_Inst => N,
- Inst => Inst,
- Inst_Id => Inst_Id,
- Gen_Id => Gen_Id,
- Attrs => Inst_Attrs);
+ -- Controlled adjustment actions
- Error_Msg_Node_2 := Inst_Id;
- Error_Msg_Sloc := Sloc (Inst);
+ elsif Is_Controlled_Proc (Targ_Id, Name_Adjust) then
+ Extra := First_Formal_Type (Targ_Id);
+ Kind := Controlled_Adjustment;
- if Nkind (Inst) = N_Function_Instantiation then
- Output_Instantiation (Gen_Id, "function");
+ -- Controlled finalization actions
- elsif Nkind (Inst) = N_Package_Instantiation then
- Output_Instantiation (Gen_Id, "package");
+ elsif Is_Controlled_Proc (Targ_Id, Name_Finalize)
+ or else Is_Finalizer_Proc (Targ_Id)
+ then
+ Extra := First_Formal_Type (Targ_Id);
+ Kind := Controlled_Finalization;
- elsif Nkind (Inst) = N_Procedure_Instantiation then
- Output_Instantiation (Gen_Id, "procedure");
+ -- Controlled initialization actions
- else
- pragma Assert (False);
- null;
- end if;
- end Output_Instantiation;
+ elsif Is_Controlled_Proc (Targ_Id, Name_Initialize) then
+ Extra := First_Formal_Type (Targ_Id);
+ Kind := Controlled_Initialization;
- ---------------------------------------
- -- Output_SPARK_Refined_State_Pragma --
- ---------------------------------------
+ -- Default_Initial_Condition verification
- procedure Output_SPARK_Refined_State_Pragma (N : Node_Id) is
- begin
- Error_Msg_Sloc := Sloc (N);
- Error_Msg_N ("\\ refinement constituents read #", Error_Nod);
- end Output_SPARK_Refined_State_Pragma;
+ elsif Is_Default_Initial_Condition_Proc (Targ_Id) then
+ Extra := First_Formal_Type (Targ_Id);
+ Kind := Default_Initial_Condition_Verification;
- --------------------------------
- -- Output_Variable_Assignment --
- --------------------------------
+ -- Initialization of object
- procedure Output_Variable_Assignment (N : Node_Id) is
- Var_Id : constant Entity_Id := Entity (Extract_Assignment_Name (N));
+ elsif Is_Init_Proc (Targ_Id) then
+ Extra := First_Formal_Type (Targ_Id);
+ Kind := Type_Initialization;
- begin
- Error_Msg_Sloc := Sloc (N);
- Error_Msg_NE ("\\ variable & assigned #", Error_Nod, Var_Id);
- end Output_Variable_Assignment;
+ -- Initial_Condition verification
- -------------------------------
- -- Output_Variable_Reference --
- -------------------------------
+ elsif Is_Initial_Condition_Proc (Targ_Id) then
+ Extra := First_Formal_Type (Targ_Id);
+ Kind := Initial_Condition_Verification;
- procedure Output_Variable_Reference (N : Node_Id) is
- Dummy : Variable_Attributes;
- Var_Id : Entity_Id;
+ -- Instantiation
- begin
- Extract_Variable_Reference_Attributes
- (Ref => N,
- Var_Id => Var_Id,
- Attrs => Dummy);
+ elsif Is_Generic_Unit (Targ_Id) then
+ Extra := Empty;
+ Kind := Instantiation;
- Error_Msg_Sloc := Sloc (N);
+ -- Internal controlled adjustment actions
- if Is_Read (N) then
- Error_Msg_NE ("\\ variable & read #", Error_Nod, Var_Id);
+ elsif Is_TSS (Targ_Id, TSS_Deep_Adjust) then
+ Extra := First_Formal_Type (Targ_Id);
+ Kind := Internal_Controlled_Adjustment;
- else
- pragma Assert (False);
- null;
- end if;
- end Output_Variable_Reference;
+ -- Internal controlled finalization actions
- -- Local variables
+ elsif Is_TSS (Targ_Id, TSS_Deep_Finalize) then
+ Extra := First_Formal_Type (Targ_Id);
+ Kind := Internal_Controlled_Finalization;
- package Stack renames Scenario_Stack;
+ -- Internal controlled initialization actions
- Dummy : Call_Attributes;
- N : Node_Id;
- Posted : Boolean;
- Target_Id : Entity_Id;
+ elsif Is_TSS (Targ_Id, TSS_Deep_Initialize) then
+ Extra := First_Formal_Type (Targ_Id);
+ Kind := Internal_Controlled_Initialization;
- -- Start of processing for Output_Active_Scenarios
+ -- Invariant verification
- begin
- -- Active scenarios are emitted only when the static model is in effect
- -- because there is an inherent order by which all these scenarios were
- -- reached from the declaration or library level.
+ elsif Is_Invariant_Proc (Targ_Id)
+ or else Is_Partial_Invariant_Proc (Targ_Id)
+ then
+ Extra := First_Formal_Type (Targ_Id);
+ Kind := Invariant_Verification;
- if not Static_Elaboration_Checks then
- return;
- end if;
+ -- Postcondition verification
- Posted := False;
+ elsif Is_Postconditions_Proc (Targ_Id) then
+ Extra := Find_Enclosing_Scope (Targ_Id);
+ Kind := Postcondition_Verification;
- for Index in Stack.First .. Stack.Last loop
- N := Stack.Table (Index);
+ -- Protected entry call
- if not Posted then
- Posted := True;
- Output_Header;
- end if;
+ elsif Is_Protected_Entry (Targ_Id) then
+ Extra := Empty;
+ Kind := Protected_Entry_Call;
- -- 'Access
+ -- Protected subprogram call
- if Nkind (N) = N_Attribute_Reference then
- Output_Access (N);
+ elsif Is_Protected_Subp (Targ_Id) then
+ Extra := Empty;
+ Kind := Protected_Subprogram_Call;
- -- Calls
+ -- Task entry call
- elsif Is_Suitable_Call (N) then
- Extract_Call_Attributes
- (Call => N,
- Target_Id => Target_Id,
- Attrs => Dummy);
+ elsif Is_Task_Entry (Targ_Id) then
+ Extra := Empty;
+ Kind := Task_Entry_Call;
+
+ -- Entry, operator, or subprogram call. This case must come last
+ -- because most invocations above are variations of this case.
+
+ elsif Ekind_In (Targ_Id, E_Entry,
+ E_Function,
+ E_Operator,
+ E_Procedure)
+ then
+ Extra := Empty;
+ Kind := Call;
- if Is_Activation_Proc (Target_Id) then
- Output_Activation_Call (N);
else
- Output_Call (N, Target_Id);
+ pragma Assert (False);
+ Extra := Empty;
+ Kind := No_Invocation;
end if;
+ end Get_Invocation_Attributes;
- -- Instantiations
+ -- Local variables
- elsif Is_Suitable_Instantiation (N) then
- Output_Instantiation (N);
+ Extra : Entity_Id;
+ Extra_Nam : Name_Id;
+ IR_Rec : Invocation_Relation_Record;
+ Kind : Invocation_Kind;
+ Rel : Invoker_Target_Relation;
- -- Pragma Refined_State
+ -- Start of processing for Record_Invocation_Relation
- elsif Is_Suitable_SPARK_Refined_State_Pragma (N) then
- Output_SPARK_Refined_State_Pragma (N);
+ begin
+ Rel.Invoker := Invk_Id;
+ Rel.Target := Targ_Id;
- -- Variable assignments
+ -- Nothing to do when the invocation relation has already been
+ -- recorded in ALI file of the main unit.
+
+ if Is_Saved_Relation (Rel) then
+ return;
+ end if;
- elsif Nkind (N) = N_Assignment_Statement then
- Output_Variable_Assignment (N);
+ -- Mark the relation as recorded in the ALI file
- -- Variable references
+ Set_Is_Saved_Relation (Rel);
- elsif Is_Suitable_Variable_Reference (N) then
- Output_Variable_Reference (N);
+ -- Declare the invoker in the ALI file
+
+ Declare_Invocation_Construct
+ (Constr_Id => Invk_Id,
+ In_State => In_State);
+
+ -- Obtain the invocation-specific attributes of the relation
+ Get_Invocation_Attributes (Extra, Kind);
+
+ -- Certain invocations lack an extra entity used in error diagnostics
+
+ if Present (Extra) then
+ Extra_Nam := Chars (Extra);
else
- pragma Assert (False);
- null;
+ Extra_Nam := No_Name;
end if;
- end loop;
- end Output_Active_Scenarios;
- -------------------------
- -- Pop_Active_Scenario --
- -------------------------
+ IR_Rec.Extra := Extra_Nam;
+ IR_Rec.Invoker := Signature_Of (Invk_Id);
+ IR_Rec.Kind := Kind;
+ IR_Rec.Target := Signature_Of (Targ_Id);
- procedure Pop_Active_Scenario (N : Node_Id) is
- Top : Node_Id renames Scenario_Stack.Table (Scenario_Stack.Last);
+ -- Add the relation in the ALI file
- begin
- pragma Assert (Top = N);
- Scenario_Stack.Decrement_Last;
- end Pop_Active_Scenario;
+ Add_Invocation_Relation
+ (IR_Rec => IR_Rec,
+ Update_Units => False);
+ end Record_Invocation_Relation;
- --------------------------------
- -- Process_Activation_Generic --
- --------------------------------
+ -----------------------------------
+ -- Record_Simple_Invocation_Path --
+ -----------------------------------
- procedure Process_Activation_Generic
- (Call : Node_Id;
- Call_Attrs : Call_Attributes;
- State : Processing_Attributes)
- is
- procedure Process_Task_Object (Obj_Id : Entity_Id; Typ : Entity_Id);
- -- Perform ABE checks and diagnostics for object Obj_Id with type Typ.
- -- Typ may be a task type or a composite type with at least one task
- -- component.
+ procedure Record_Simple_Invocation_Path
+ (In_State : Processing_In_State)
+ is
+ package Scenarios renames Active_Scenario_Stack;
- procedure Process_Task_Objects (List : List_Id);
- -- Perform ABE checks and diagnostics for all task objects found in the
- -- list List.
+ Last_Targ : constant Entity_Id :=
+ Target_Of (Scenarios.Last, In_State);
+ First_Targ : Entity_Id;
- -------------------------
- -- Process_Task_Object --
- -------------------------
+ begin
+ -- The path originates from the elaboration of the body. Add an extra
+ -- relation from the elaboration body procedure to the first active
+ -- scenario.
- procedure Process_Task_Object (Obj_Id : Entity_Id; Typ : Entity_Id) is
- Base_Typ : constant Entity_Id := Base_Type (Typ);
+ if In_State.Processing = Invocation_Body_Processing then
+ Build_Elaborate_Body_Procedure;
+ First_Targ := Elab_Body_Id;
- Comp_Id : Entity_Id;
- Task_Attrs : Task_Attributes;
+ -- The path originates from the elaboration of the spec. Add an extra
+ -- relation from the elaboration spec procedure to the first active
+ -- scenario.
- New_State : Processing_Attributes := State;
- -- Each step of the Processing phase constitutes a new state
+ elsif In_State.Processing = Invocation_Spec_Processing then
+ Build_Elaborate_Spec_Procedure;
+ First_Targ := Elab_Spec_Id;
+
+ else
+ First_Targ := Target_Of (Scenarios.First, In_State);
+ end if;
+
+ -- Record a single relation from the first to the last scenario
+
+ if First_Targ /= Last_Targ then
+ Record_Invocation_Relation
+ (Invk_Id => First_Targ,
+ Targ_Id => Last_Targ,
+ In_State => In_State);
+ end if;
+ end Record_Simple_Invocation_Path;
+
+ ----------------------------
+ -- Set_Is_Saved_Construct --
+ ----------------------------
+
+ procedure Set_Is_Saved_Construct
+ (Constr : Entity_Id;
+ Val : Boolean := True)
+ is
+ pragma Assert (Present (Constr));
begin
- if Is_Task_Type (Typ) then
- Extract_Task_Attributes
- (Typ => Base_Typ,
- Attrs => Task_Attrs);
+ if Val then
+ NE_Set.Insert (Saved_Constructs_Set, Constr);
+ else
+ NE_Set.Delete (Saved_Constructs_Set, Constr);
+ end if;
+ end Set_Is_Saved_Construct;
- -- Warnings are suppressed when a prior scenario is already in
- -- that mode, or when the object, activation call, or task type
- -- have warnings suppressed. Update the state of the Processing
- -- phase to reflect this.
+ ---------------------------
+ -- Set_Is_Saved_Relation --
+ ---------------------------
- New_State.Suppress_Warnings :=
- New_State.Suppress_Warnings
- or else not Is_Elaboration_Warnings_OK_Id (Obj_Id)
- or else not Call_Attrs.Elab_Warnings_OK
- or else not Task_Attrs.Elab_Warnings_OK;
+ procedure Set_Is_Saved_Relation
+ (Rel : Invoker_Target_Relation;
+ Val : Boolean := True)
+ is
+ begin
+ if Val then
+ IR_Set.Insert (Saved_Relations_Set, Rel);
+ else
+ IR_Set.Delete (Saved_Relations_Set, Rel);
+ end if;
+ end Set_Is_Saved_Relation;
- -- Update the state of the Processing phase to indicate that any
- -- further traversal is now within a task body.
+ ------------------
+ -- Signature_Of --
+ ------------------
- New_State.Within_Task_Body := True;
+ function Signature_Of (Id : Entity_Id) return Invocation_Signature_Id is
+ Loc : constant Source_Ptr := Sloc (Id);
- Process_Single_Activation
- (Call => Call,
- Call_Attrs => Call_Attrs,
- Obj_Id => Obj_Id,
- Task_Attrs => Task_Attrs,
- State => New_State);
+ function Instantiation_Locations return Name_Id;
+ pragma Inline (Instantiation_Locations);
+ -- Create a concatenation of all lines and colums of each instance
+ -- where source location Loc appears. Return No_Name if no instances
+ -- exist.
- -- Examine the component type when the object is an array
+ function Qualified_Scope return Name_Id;
+ pragma Inline (Qualified_Scope);
+ -- Obtain the qualified name of Id's scope
- elsif Is_Array_Type (Typ) and then Has_Task (Base_Typ) then
- Process_Task_Object
- (Obj_Id => Obj_Id,
- Typ => Component_Type (Typ));
+ -----------------------------
+ -- Instantiation_Locations --
+ -----------------------------
- -- Examine individual component types when the object is a record
+ function Instantiation_Locations return Name_Id is
+ Buffer : Bounded_String (2052);
+ Inst : Source_Ptr;
+ Loc_Nam : Name_Id;
+ SFI : Source_File_Index;
- elsif Is_Record_Type (Typ) and then Has_Task (Base_Typ) then
- Comp_Id := First_Component (Typ);
- while Present (Comp_Id) loop
- Process_Task_Object
- (Obj_Id => Obj_Id,
- Typ => Etype (Comp_Id));
+ begin
+ SFI := Get_Source_File_Index (Loc);
+ Inst := Instantiation (SFI);
- Next_Component (Comp_Id);
- end loop;
- end if;
- end Process_Task_Object;
+ -- The location is within an instance. Construct a concatenation
+ -- of all lines and colums of each individual instance using the
+ -- following format:
+ --
+ -- line1_column1_line2_column2_ ... _lineN_columnN
- --------------------------
- -- Process_Task_Objects --
- --------------------------
+ if Inst /= No_Location then
+ loop
+ Append (Buffer, Nat (Get_Logical_Line_Number (Inst)));
+ Append (Buffer, '_');
+ Append (Buffer, Nat (Get_Column_Number (Inst)));
- procedure Process_Task_Objects (List : List_Id) is
- Item : Node_Id;
- Item_Id : Entity_Id;
- Item_Typ : Entity_Id;
+ SFI := Get_Source_File_Index (Inst);
+ Inst := Instantiation (SFI);
- begin
- -- Examine the contents of the list looking for an object declaration
- -- of a task type or one that contains a task within.
+ exit when Inst = No_Location;
- Item := First (List);
- while Present (Item) loop
- if Nkind (Item) = N_Object_Declaration then
- Item_Id := Defining_Entity (Item);
- Item_Typ := Etype (Item_Id);
+ Append (Buffer, '_');
+ end loop;
- if Has_Task (Item_Typ) then
- Process_Task_Object
- (Obj_Id => Item_Id,
- Typ => Item_Typ);
- end if;
+ Loc_Nam := Name_Find (Buffer);
+ return Loc_Nam;
+
+ -- Otherwise there no instances are involved
+
+ else
+ return No_Name;
end if;
+ end Instantiation_Locations;
- Next (Item);
- end loop;
- end Process_Task_Objects;
+ ---------------------
+ -- Qualified_Scope --
+ ---------------------
- -- Local variables
+ function Qualified_Scope return Name_Id is
+ Scop : Entity_Id;
- Context : Node_Id;
- Spec : Node_Id;
+ begin
+ Scop := Scope (Id);
- -- Start of processing for Process_Activation_Generic
+ -- The entity appears within an anonymous concurrent type created
+ -- for a single protected or task type declaration. Use the entity
+ -- of the anonymous object as it represents the original scope.
- begin
- -- Nothing to do when the activation is a guaranteed ABE
+ if Is_Concurrent_Type (Scop)
+ and then Present (Anonymous_Object (Scop))
+ then
+ Scop := Anonymous_Object (Scop);
+ end if;
- if Is_Known_Guaranteed_ABE (Call) then
- return;
- end if;
+ return Get_Qualified_Name (Scop);
+ end Qualified_Scope;
- -- Find the proper context of the activation call where all task objects
- -- being activated are declared. This is usually the immediate parent of
- -- the call.
+ -- Start of processing for Signature_Of
- Context := Parent (Call);
+ begin
+ return
+ Invocation_Signature_Of
+ (Column => Nat (Get_Column_Number (Loc)),
+ Line => Nat (Get_Logical_Line_Number (Loc)),
+ Locations => Instantiation_Locations,
+ Name => Chars (Id),
+ Scope => Qualified_Scope);
+ end Signature_Of;
- -- In the case of package bodies, the activation call is in the handled
- -- sequence of statements, but the task objects are in the declaration
- -- list of the body.
+ ---------------
+ -- Target_Of --
+ ---------------
- if Nkind (Context) = N_Handled_Sequence_Of_Statements
- and then Nkind (Parent (Context)) = N_Package_Body
- then
- Context := Parent (Context);
- end if;
+ function Target_Of
+ (Pos : Active_Scenario_Pos;
+ In_State : Processing_In_State) return Entity_Id
+ is
+ package Scenarios renames Active_Scenario_Stack;
- -- Process all task objects defined in both the spec and body when the
- -- activation call precedes the "begin" of a package body.
+ -- Ensure that the position is within the bounds of the active
+ -- scenario stack.
- if Nkind (Context) = N_Package_Body then
- Spec :=
- Specification
- (Unit_Declaration_Node (Corresponding_Spec (Context)));
+ pragma Assert (Scenarios.First <= Pos);
+ pragma Assert (Pos <= Scenarios.Last);
- Process_Task_Objects (Visible_Declarations (Spec));
- Process_Task_Objects (Private_Declarations (Spec));
- Process_Task_Objects (Declarations (Context));
+ Scen_Rep : constant Scenario_Rep_Id :=
+ Scenario_Representation_Of
+ (Scenarios.Table (Pos), In_State);
- -- Process all task objects defined in the spec when the activation call
- -- appears at the end of a package spec.
+ begin
+ -- The true target of an activation call is the current task type
+ -- rather than routine Activate_Tasks.
- elsif Nkind (Context) = N_Package_Specification then
- Process_Task_Objects (Visible_Declarations (Context));
- Process_Task_Objects (Private_Declarations (Context));
+ if Kind (Scen_Rep) = Task_Activation_Scenario then
+ return Activated_Task_Type (Scen_Rep);
+ else
+ return Target (Scen_Rep);
+ end if;
+ end Target_Of;
- -- Otherwise the context of the activation is some construct with a
- -- declarative part. Note that the corresponding record type of a task
- -- type is controlled. Because of this, the finalization machinery must
- -- relocate the task object to the handled statements of the construct
- -- to perform proper finalization in case of an exception. Examine the
- -- statements of the construct rather than the declarations.
+ ------------------------------
+ -- Traverse_Invocation_Body --
+ ------------------------------
- else
- pragma Assert (Nkind (Context) = N_Handled_Sequence_Of_Statements);
+ procedure Traverse_Invocation_Body
+ (N : Node_Id;
+ In_State : Processing_In_State)
+ is
+ begin
+ Traverse_Body
+ (N => N,
+ Requires_Processing => Is_Invocation_Scenario'Access,
+ Processor => Process_Invocation_Scenario'Access,
+ In_State => In_State);
+ end Traverse_Invocation_Body;
- Process_Task_Objects (Statements (Context));
- end if;
- end Process_Activation_Generic;
+ ---------------------------
+ -- Write_Invocation_Path --
+ ---------------------------
- ------------------------------------
- -- Process_Conditional_ABE_Access --
- ------------------------------------
+ procedure Write_Invocation_Path (In_State : Processing_In_State) is
+ procedure Write_Target (Targ_Id : Entity_Id; Is_First : Boolean);
+ pragma Inline (Write_Target);
+ -- Write out invocation target Targ_Id to standard output. Flag
+ -- Is_First should be set when the target is first in a path.
- procedure Process_Conditional_ABE_Access
- (Attr : Node_Id;
- State : Processing_Attributes)
- is
- function Build_Access_Marker (Target_Id : Entity_Id) return Node_Id;
- pragma Inline (Build_Access_Marker);
- -- Create a suitable call marker which invokes target Target_Id
+ -------------
+ -- Targ_Id --
+ -------------
- -------------------------
- -- Build_Access_Marker --
- -------------------------
+ procedure Write_Target (Targ_Id : Entity_Id; Is_First : Boolean) is
+ begin
+ if not Is_First then
+ Write_Str (" --> ");
+ end if;
- function Build_Access_Marker (Target_Id : Entity_Id) return Node_Id is
- Marker : Node_Id;
+ Write_Name (Get_Qualified_Name (Targ_Id));
+ Write_Eol;
+ end Write_Target;
+
+ -- Local variables
+
+ package Scenarios renames Active_Scenario_Stack;
+
+ First_Seen : Boolean := False;
+
+ -- Start of processing for Write_Invocation_Path
begin
- Marker := Make_Call_Marker (Sloc (Attr));
+ -- Nothing to do when flag -gnatd_T (output trace information on
+ -- invocation path recording) is not in effect.
- -- Inherit relevant attributes from the attribute
+ if not Debug_Flag_Underscore_TT then
+ return;
+ end if;
- -- Performance note: parent traversal
+ -- The path originates from the elaboration of the body. Write the
+ -- elaboration body procedure.
- Set_Target (Marker, Target_Id);
- Set_Is_Declaration_Level_Node
- (Marker, Find_Enclosing_Level (Attr) = Declaration_Level);
- Set_Is_Dispatching_Call
- (Marker, False);
- Set_Is_Elaboration_Checks_OK_Node
- (Marker, Is_Elaboration_Checks_OK_Node (Attr));
- Set_Is_Elaboration_Warnings_OK_Node
- (Marker, Is_Elaboration_Warnings_OK_Node (Attr));
- Set_Is_Source_Call
- (Marker, Comes_From_Source (Attr));
- Set_Is_SPARK_Mode_On_Node
- (Marker, Is_SPARK_Mode_On_Node (Attr));
+ if In_State.Processing = Invocation_Body_Processing then
+ Write_Target (Elab_Body_Id, True);
+ First_Seen := True;
- -- Partially insert the call marker into the tree by setting its
- -- parent pointer.
+ -- The path originates from the elaboration of the spec. Write the
+ -- elaboration spec procedure.
- Set_Parent (Marker, Attr);
+ elsif In_State.Processing = Invocation_Spec_Processing then
+ Write_Target (Elab_Spec_Id, True);
+ First_Seen := True;
+ end if;
- return Marker;
- end Build_Access_Marker;
+ -- Write each individual target invoked by its corresponding scenario
+ -- on the active scenario stack.
- -- Local variables
+ for Index in Scenarios.First .. Scenarios.Last loop
+ Write_Target
+ (Targ_Id => Target_Of (Index, In_State),
+ Is_First => Index = Scenarios.First and then not First_Seen);
+ end loop;
- Root : constant Node_Id := Root_Scenario;
- Target_Id : constant Entity_Id := Entity (Prefix (Attr));
+ Write_Eol;
+ end Write_Invocation_Path;
+ end Invocation_Graph;
- Target_Attrs : Target_Attributes;
+ ------------------------
+ -- Is_Safe_Activation --
+ ------------------------
+
+ function Is_Safe_Activation
+ (Call : Node_Id;
+ Task_Rep : Target_Rep_Id) return Boolean
+ is
+ begin
+ -- The activation of a task coming from an external instance cannot
+ -- cause an ABE because the generic was already instantiated. Note
+ -- that the instantiation itself may lead to an ABE.
- New_State : Processing_Attributes := State;
- -- Each step of the Processing phase constitutes a new state
+ return
+ In_External_Instance
+ (N => Call,
+ Target_Decl => Spec_Declaration (Task_Rep));
+ end Is_Safe_Activation;
- -- Start of processing for Process_Conditional_ABE_Access
+ ------------------
+ -- Is_Safe_Call --
+ ------------------
+
+ function Is_Safe_Call
+ (Call : Node_Id;
+ Subp_Id : Entity_Id;
+ Subp_Rep : Target_Rep_Id) return Boolean
+ is
+ Body_Decl : constant Node_Id := Body_Declaration (Subp_Rep);
+ Spec_Decl : constant Node_Id := Spec_Declaration (Subp_Rep);
begin
- -- Output relevant information when switch -gnatel (info messages on
- -- implicit Elaborate[_All] pragmas) is in effect.
+ -- The target is either an abstract subprogram, formal subprogram, or
+ -- imported, in which case it does not have a body at compile or bind
+ -- time. Assume that the call is ABE-safe.
- if Elab_Info_Messages then
- Error_Msg_NE
- ("info: access to & during elaboration", Attr, Target_Id);
- end if;
+ if Is_Bodiless_Subprogram (Subp_Id) then
+ return True;
- Extract_Target_Attributes
- (Target_Id => Target_Id,
- Attrs => Target_Attrs);
+ -- The target is an instantiation of a generic subprogram. The call
+ -- cannot cause an ABE because the generic was already instantiated.
+ -- Note that the instantiation itself may lead to an ABE.
- -- Warnings are suppressed when a prior scenario is already in that
- -- mode, or when the attribute or the target have warnings suppressed.
- -- Update the state of the Processing phase to reflect this.
+ elsif Is_Generic_Instance (Subp_Id) then
+ return True;
- New_State.Suppress_Warnings :=
- New_State.Suppress_Warnings
- or else not Is_Elaboration_Warnings_OK_Node (Attr)
- or else not Target_Attrs.Elab_Warnings_OK;
+ -- The invocation of a target coming from an external instance cannot
+ -- cause an ABE because the generic was already instantiated. Note that
+ -- the instantiation itself may lead to an ABE.
- -- Do not emit any ABE diagnostics when the current or previous scenario
- -- in this traversal has suppressed elaboration warnings.
+ elsif In_External_Instance
+ (N => Call,
+ Target_Decl => Spec_Decl)
+ then
+ return True;
- if New_State.Suppress_Warnings then
- null;
+ -- The target is a subprogram body without a previous declaration. The
+ -- call cannot cause an ABE because the body has already been seen.
- -- Both the attribute and the corresponding body are in the same unit.
- -- The corresponding body must appear prior to the root scenario which
- -- started the recursive search. If this is not the case, then there is
- -- a potential ABE if the access value is used to call the subprogram.
- -- Emit a warning only when switch -gnatw.f (warnings on suspucious
- -- 'Access) is in effect.
-
- elsif Warn_On_Elab_Access
- and then Present (Target_Attrs.Body_Decl)
- and then In_Extended_Main_Code_Unit (Target_Attrs.Body_Decl)
- and then Earlier_In_Extended_Unit (Root, Target_Attrs.Body_Decl)
+ elsif Nkind (Spec_Decl) = N_Subprogram_Body
+ and then No (Corresponding_Spec (Spec_Decl))
then
- Error_Msg_Name_1 := Attribute_Name (Attr);
- Error_Msg_NE ("??% attribute of & before body seen", Attr, Target_Id);
- Error_Msg_N ("\possible Program_Error on later references", Attr);
+ return True;
+
+ -- The target is a subprogram body stub without a prior declaration.
+ -- The call cannot cause an ABE because the proper body substitutes
+ -- the stub.
+
+ elsif Nkind (Spec_Decl) = N_Subprogram_Body_Stub
+ and then No (Corresponding_Spec_Of_Stub (Spec_Decl))
+ then
+ return True;
+
+ -- Subprogram bodies which wrap attribute references used as actuals
+ -- in instantiations are always ABE-safe. These bodies are artifacts
+ -- of expansion.
- Output_Active_Scenarios (Attr);
+ elsif Present (Body_Decl)
+ and then Nkind (Body_Decl) = N_Subprogram_Body
+ and then Was_Attribute_Reference (Body_Decl)
+ then
+ return True;
end if;
- -- Treat the attribute as an immediate invocation of the target when
- -- switch -gnatd.o (conservative elaboration order for indirect calls)
- -- is in effect. Note that the prior elaboration of the unit containing
- -- the target is ensured processing the corresponding call marker.
+ return False;
+ end Is_Safe_Call;
- if Debug_Flag_Dot_O then
- Process_Conditional_ABE
- (N => Build_Access_Marker (Target_Id),
- State => New_State);
+ ---------------------------
+ -- Is_Safe_Instantiation --
+ ---------------------------
- -- Otherwise ensure that the unit with the corresponding body is
- -- elaborated prior to the main unit.
+ function Is_Safe_Instantiation
+ (Inst : Node_Id;
+ Gen_Id : Entity_Id;
+ Gen_Rep : Target_Rep_Id) return Boolean
+ is
+ Spec_Decl : constant Node_Id := Spec_Declaration (Gen_Rep);
- else
- Ensure_Prior_Elaboration
- (N => Attr,
- Unit_Id => Target_Attrs.Unit_Id,
- Prag_Nam => Name_Elaborate_All,
- State => New_State);
+ begin
+ -- The generic is an intrinsic subprogram in which case it does not
+ -- have a body at compile or bind time. Assume that the instantiation
+ -- is ABE-safe.
+
+ if Is_Bodiless_Subprogram (Gen_Id) then
+ return True;
+
+ -- The instantiation of an external nested generic cannot cause an ABE
+ -- if the outer generic was already instantiated. Note that the instance
+ -- of the outer generic may lead to an ABE.
+
+ elsif In_External_Instance
+ (N => Inst,
+ Target_Decl => Spec_Decl)
+ then
+ return True;
+
+ -- The generic is a package. The instantiation cannot cause an ABE when
+ -- the package has no body.
+
+ elsif Ekind (Gen_Id) = E_Generic_Package
+ and then not Has_Body (Spec_Decl)
+ then
+ return True;
end if;
- end Process_Conditional_ABE_Access;
-
- ---------------------------------------------
- -- Process_Conditional_ABE_Activation_Impl --
- ---------------------------------------------
-
- procedure Process_Conditional_ABE_Activation_Impl
- (Call : Node_Id;
- Call_Attrs : Call_Attributes;
- Obj_Id : Entity_Id;
- Task_Attrs : Task_Attributes;
- State : Processing_Attributes)
- is
- Check_OK : constant Boolean :=
- not Is_Ignored_Ghost_Entity (Obj_Id)
- and then not Task_Attrs.Ghost_Mode_Ignore
- and then Is_Elaboration_Checks_OK_Id (Obj_Id)
- and then Task_Attrs.Elab_Checks_OK;
- -- A run-time ABE check may be installed only when the object and the
- -- task type have active elaboration checks, and both are not ignored
- -- Ghost constructs.
- Root : constant Node_Id := Root_Scenario;
+ return False;
+ end Is_Safe_Instantiation;
- New_State : Processing_Attributes := State;
- -- Each step of the Processing phase constitutes a new state
+ ------------------
+ -- Is_Same_Unit --
+ ------------------
+ function Is_Same_Unit
+ (Unit_1 : Entity_Id;
+ Unit_2 : Entity_Id) return Boolean
+ is
begin
- -- Output relevant information when switch -gnatel (info messages on
- -- implicit Elaborate[_All] pragmas) is in effect.
+ return Unit_Entity (Unit_1) = Unit_Entity (Unit_2);
+ end Is_Same_Unit;
- if Elab_Info_Messages then
- Error_Msg_NE
- ("info: activation of & during elaboration", Call, Obj_Id);
- end if;
+ -------------------------------
+ -- Kill_Elaboration_Scenario --
+ -------------------------------
- -- Nothing to do when the call activates a task whose type is defined
- -- within an instance and switch -gnatd_i (ignore activations and calls
- -- to instances for elaboration) is in effect.
+ procedure Kill_Elaboration_Scenario (N : Node_Id) is
+ begin
+ -- Nothing to do when switch -gnatH (legacy elaboration checking mode
+ -- enabled) is in effect because the legacy ABE lechanism does not need
+ -- to carry out this action.
- if Debug_Flag_Underscore_I
- and then In_External_Instance
- (N => Call,
- Target_Decl => Task_Attrs.Task_Decl)
- then
+ if Legacy_Elaboration_Checks then
return;
+ end if;
- -- Nothing to do when the activation is a guaranteed ABE
+ -- Eliminate a recorded scenario when it appears within dead code
+ -- because it will not be executed at elaboration time.
- elsif Is_Known_Guaranteed_ABE (Call) then
- return;
+ if Is_Scenario (N) then
+ Delete_Scenario (N);
+ end if;
+ end Kill_Elaboration_Scenario;
- -- Nothing to do when the root scenario appears at the declaration
- -- level and the task is in the same unit, but outside this context.
- --
- -- task type Task_Typ; -- task declaration
- --
- -- procedure Proc is
- -- function A ... is
- -- begin
- -- if Some_Condition then
- -- declare
- -- T : Task_Typ;
- -- begin
- -- <activation call> -- activation site
- -- end;
- -- ...
- -- end A;
- --
- -- X : ... := A; -- root scenario
- -- ...
- --
- -- task body Task_Typ is
- -- ...
- -- end Task_Typ;
- --
- -- In the example above, the context of X is the declarative list of
- -- Proc. The "elaboration" of X may reach the activation of T whose body
- -- is defined outside of X's context. The task body is relevant only
- -- when Proc is invoked, but this happens only in "normal" elaboration,
- -- therefore the task body must not be considered if this is not the
- -- case.
+ ----------------------
+ -- Non_Private_View --
+ ----------------------
+
+ function Non_Private_View (Typ : Entity_Id) return Entity_Id is
+ begin
+ if Is_Private_Type (Typ) and then Present (Full_View (Typ)) then
+ return Full_View (Typ);
+ else
+ return Typ;
+ end if;
+ end Non_Private_View;
- -- Performance note: parent traversal
+ ---------------------------------
+ -- Record_Elaboration_Scenario --
+ ---------------------------------
- elsif Is_Up_Level_Target (Task_Attrs.Task_Decl) then
- return;
+ procedure Record_Elaboration_Scenario (N : Node_Id) is
+ procedure Check_Preelaborated_Call
+ (Call : Node_Id;
+ Call_Lvl : Enclosing_Level_Kind);
+ pragma Inline (Check_Preelaborated_Call);
+ -- Verify that entry, operator, or subprogram call Call with enclosing
+ -- level Call_Lvl does not appear at the library level of preelaborated
+ -- unit.
- -- Nothing to do when the activation is ABE-safe
- --
- -- generic
- -- package Gen is
- -- task type Task_Typ;
- -- end Gen;
- --
- -- package body Gen is
- -- task body Task_Typ is
- -- begin
- -- ...
- -- end Task_Typ;
- -- end Gen;
- --
- -- with Gen;
- -- procedure Main is
- -- package Nested is
- -- package Inst is new Gen;
- -- T : Inst.Task_Typ;
- -- <activation call> -- safe activation
- -- end Nested;
- -- ...
+ function Find_Code_Unit (Nod : Node_Or_Entity_Id) return Entity_Id;
+ pragma Inline (Find_Code_Unit);
+ -- Return the code unit which contains arbitrary node or entity Nod.
+ -- This is the unit of the file which physically contains the related
+ -- construct denoted by Nod except when Nod is within an instantiation.
+ -- In that case the unit is that of the top-level instantiation.
+
+ function In_Preelaborated_Context (Nod : Node_Id) return Boolean;
+ pragma Inline (In_Preelaborated_Context);
+ -- Determine whether arbitrary node Nod appears within a preelaborated
+ -- context.
+
+ procedure Record_Access_Taken
+ (Attr : Node_Id;
+ Attr_Lvl : Enclosing_Level_Kind);
+ pragma Inline (Record_Access_Taken);
+ -- Record 'Access scenario Attr with enclosing level Attr_Lvl
+
+ procedure Record_Call_Or_Task_Activation
+ (Call : Node_Id;
+ Call_Lvl : Enclosing_Level_Kind);
+ pragma Inline (Record_Call_Or_Task_Activation);
+ -- Record call scenario Call with enclosing level Call_Lvl
+
+ procedure Record_Instantiation
+ (Inst : Node_Id;
+ Inst_Lvl : Enclosing_Level_Kind);
+ pragma Inline (Record_Instantiation);
+ -- Record instantiation scenario Inst with enclosing level Inst_Lvl
+
+ procedure Record_Variable_Assignment
+ (Asmt : Node_Id;
+ Asmt_Lvl : Enclosing_Level_Kind);
+ pragma Inline (Record_Variable_Assignment);
+ -- Record variable assignment scenario Asmt with enclosing level
+ -- Asmt_Lvl.
+
+ procedure Record_Variable_Reference
+ (Ref : Node_Id;
+ Ref_Lvl : Enclosing_Level_Kind);
+ pragma Inline (Record_Variable_Reference);
+ -- Record variable reference scenario Ref with enclosing level Ref_Lvl
- elsif Is_Safe_Activation (Call, Task_Attrs.Task_Decl) then
+ ------------------------------
+ -- Check_Preelaborated_Call --
+ ------------------------------
- -- Note that the task body must still be examined for any nested
- -- scenarios.
+ procedure Check_Preelaborated_Call
+ (Call : Node_Id;
+ Call_Lvl : Enclosing_Level_Kind)
+ is
+ begin
+ -- Nothing to do when the call is internally generated because it is
+ -- assumed that it will never violate preelaboration.
- null;
+ if not Is_Source_Call (Call) then
+ return;
- -- The activation call and the task body are both in the main unit
+ -- Library-level calls are always considered because they are part of
+ -- the associated unit's elaboration actions.
- elsif Present (Task_Attrs.Body_Decl)
- and then In_Extended_Main_Code_Unit (Task_Attrs.Body_Decl)
- then
- -- If the root scenario appears prior to the task body, then this is
- -- a possible ABE with respect to the root scenario.
- --
- -- task type Task_Typ;
- --
- -- function A ... is
- -- begin
- -- if Some_Condition then
- -- declare
- -- package Pack is
- -- T : Task_Typ;
- -- end Pack; -- activation of T
- -- ...
- -- end A;
- --
- -- X : ... := A; -- root scenario
- --
- -- task body Task_Typ is -- task body
- -- ...
- -- end Task_Typ;
- --
- -- Y : ... := A; -- root scenario
- --
- -- IMPORTANT: The activation of T is a possible ABE for X, but
- -- not for Y. Intalling an unconditional ABE raise prior to the
- -- activation call would be wrong as it will fail for Y as well
- -- but in Y's case the activation of T is never an ABE.
+ elsif Call_Lvl in Library_Level then
+ null;
- if Earlier_In_Extended_Unit (Root, Task_Attrs.Body_Decl) then
+ -- Calls at the library level of a generic package body have to be
+ -- checked because they would render an instantiation illegal if the
+ -- template is marked as preelaborated. Note that this does not apply
+ -- to calls at the library level of a generic package spec.
- -- Do not emit any ABE diagnostics when a previous scenario in
- -- this traversal has suppressed elaboration warnings.
+ elsif Call_Lvl = Generic_Body_Level then
+ null;
- if State.Suppress_Warnings then
- null;
+ -- Otherwise the call does not appear at the proper level and must
+ -- not be considered for this check.
- -- Do not emit any ABE diagnostics when the activation occurs in
- -- a partial finalization context because this leads to confusing
- -- noise.
+ else
+ return;
+ end if;
- elsif State.Within_Partial_Finalization then
- null;
+ -- The call appears within a preelaborated unit. Emit a warning only
+ -- for internal uses, otherwise this is an error.
- -- ABE diagnostics are emitted only in the static model because
- -- there is a well-defined order to visiting scenarios. Without
- -- this order diagnostics appear jumbled and result in unwanted
- -- noise.
+ if In_Preelaborated_Context (Call) then
+ Error_Msg_Warn := GNAT_Mode;
+ Error_Msg_N
+ ("<<non-static call not allowed in preelaborated unit", Call);
+ end if;
+ end Check_Preelaborated_Call;
- elsif Static_Elaboration_Checks then
- Error_Msg_Sloc := Sloc (Call);
- Error_Msg_N
- ("??task & will be activated # before elaboration of its "
- & "body", Obj_Id);
- Error_Msg_N
- ("\Program_Error may be raised at run time", Obj_Id);
+ --------------------
+ -- Find_Code_Unit --
+ --------------------
- Output_Active_Scenarios (Obj_Id);
- end if;
+ function Find_Code_Unit (Nod : Node_Or_Entity_Id) return Entity_Id is
+ begin
+ return Find_Unit_Entity (Unit (Cunit (Get_Code_Unit (Nod))));
+ end Find_Code_Unit;
- -- Install a conditional run-time ABE check to verify that the
- -- task body has been elaborated prior to the activation call.
+ ------------------------------
+ -- In_Preelaborated_Context --
+ ------------------------------
- if Check_OK then
- Install_ABE_Check
- (N => Call,
- Ins_Nod => Call,
- Target_Id => Task_Attrs.Spec_Id,
- Target_Decl => Task_Attrs.Task_Decl,
- Target_Body => Task_Attrs.Body_Decl);
+ function In_Preelaborated_Context (Nod : Node_Id) return Boolean is
+ Body_Id : constant Entity_Id := Find_Code_Unit (Nod);
+ Spec_Id : constant Entity_Id := Unique_Entity (Body_Id);
- -- Update the state of the Processing phase to indicate that
- -- no implicit Elaborate[_All] pragmas must be generated from
- -- this point on.
- --
- -- task type Task_Typ;
- --
- -- function A ... is
- -- begin
- -- if Some_Condition then
- -- declare
- -- package Pack is
- -- <ABE check>
- -- T : Task_Typ;
- -- end Pack; -- activation of T
- -- ...
- -- end A;
- --
- -- X : ... := A;
- --
- -- task body Task_Typ is
- -- begin
- -- External.Subp; -- imparts Elaborate_All
- -- end Task_Typ;
- --
- -- If Some_Condition is True, then the ABE check will fail at
- -- runtime and the call to External.Subp will never take place,
- -- rendering the implicit Elaborate_All useless.
- --
- -- If Some_Condition is False, then the call to External.Subp
- -- will never take place, rendering the implicit Elaborate_All
- -- useless.
+ begin
+ -- The node appears within a package body whose corresponding spec is
+ -- subject to pragma Remote_Call_Interface or Remote_Types. This does
+ -- not result in a preelaborated context because the package body may
+ -- be on another machine.
- New_State.Suppress_Implicit_Pragmas := True;
- end if;
+ if Ekind (Body_Id) = E_Package_Body
+ and then Ekind_In (Spec_Id, E_Generic_Package, E_Package)
+ and then (Is_Remote_Call_Interface (Spec_Id)
+ or else Is_Remote_Types (Spec_Id))
+ then
+ return False;
+
+ -- Otherwise the node appears within a preelaborated context when the
+ -- associated unit is preelaborated.
+
+ else
+ return Is_Preelaborated_Unit (Spec_Id);
end if;
+ end In_Preelaborated_Context;
- -- Otherwise the task body is not available in this compilation or it
- -- resides in an external unit. Install a run-time ABE check to verify
- -- that the task body has been elaborated prior to the activation call
- -- when the dynamic model is in effect.
+ -------------------------
+ -- Record_Access_Taken --
+ -------------------------
- elsif Dynamic_Elaboration_Checks and then Check_OK then
- Install_ABE_Check
- (N => Call,
- Ins_Nod => Call,
- Id => Task_Attrs.Unit_Id);
- end if;
+ procedure Record_Access_Taken
+ (Attr : Node_Id;
+ Attr_Lvl : Enclosing_Level_Kind)
+ is
+ begin
+ -- Signal any enclosing local exception handlers that the 'Access may
+ -- raise Program_Error due to a failed ABE check when switch -gnatd.o
+ -- (conservative elaboration order for indirect calls) is in effect.
+ -- Marking the exception handlers ensures proper expansion by both
+ -- the front and back end restriction when No_Exception_Propagation
+ -- is in effect.
- -- Both the activation call and task type are subject to SPARK_Mode
- -- On, this triggers the SPARK rules for task activation. Compared to
- -- calls and instantiations, task activation in SPARK does not require
- -- the presence of Elaborate[_All] pragmas in case the task type is
- -- defined outside the main unit. This is because SPARK utilizes a
- -- special policy which activates all tasks after the main unit has
- -- finished its elaboration.
+ if Debug_Flag_Dot_O then
+ Possible_Local_Raise (Attr, Standard_Program_Error);
+ end if;
- if Call_Attrs.SPARK_Mode_On and Task_Attrs.SPARK_Mode_On then
- null;
+ -- Add 'Access to the appropriate set
- -- Otherwise the Ada rules are in effect. Ensure that the unit with the
- -- task body is elaborated prior to the main unit.
+ if Attr_Lvl = Library_Body_Level then
+ Add_Library_Body_Scenario (Attr);
- else
- Ensure_Prior_Elaboration
+ elsif Attr_Lvl = Library_Spec_Level
+ or else Attr_Lvl = Instantiation_Level
+ then
+ Add_Library_Spec_Scenario (Attr);
+ end if;
+
+ -- 'Access requires a conditional ABE check when the dynamic model is
+ -- in effect.
+
+ Add_Dynamic_ABE_Check_Scenario (Attr);
+ end Record_Access_Taken;
+
+ ------------------------------------
+ -- Record_Call_Or_Task_Activation --
+ ------------------------------------
+
+ procedure Record_Call_Or_Task_Activation
+ (Call : Node_Id;
+ Call_Lvl : Enclosing_Level_Kind)
+ is
+ begin
+ -- Signal any enclosing local exception handlers that the call may
+ -- raise Program_Error due to failed ABE check. Marking the exception
+ -- handlers ensures proper expansion by both the front and back end
+ -- restriction when No_Exception_Propagation is in effect.
+
+ Possible_Local_Raise (Call, Standard_Program_Error);
+
+ -- Perform early detection of guaranteed ABEs in order to suppress
+ -- the instantiation of generic bodies because gigi cannot handle
+ -- certain types of premature instantiations.
+
+ Process_Guaranteed_ABE
(N => Call,
- Unit_Id => Task_Attrs.Unit_Id,
- Prag_Nam => Name_Elaborate_All,
- State => New_State);
- end if;
+ In_State => Guaranteed_ABE_State);
- Traverse_Body
- (N => Task_Attrs.Body_Decl,
- State => New_State);
- end Process_Conditional_ABE_Activation_Impl;
+ -- Add the call or task activation to the appropriate set
- procedure Process_Conditional_ABE_Activation is
- new Process_Activation_Generic (Process_Conditional_ABE_Activation_Impl);
+ if Call_Lvl = Declaration_Level then
+ Add_Declaration_Scenario (Call);
- ----------------------------------
- -- Process_Conditional_ABE_Call --
- ----------------------------------
+ elsif Call_Lvl = Library_Body_Level then
+ Add_Library_Body_Scenario (Call);
- procedure Process_Conditional_ABE_Call
- (Call : Node_Id;
- Call_Attrs : Call_Attributes;
- Target_Id : Entity_Id;
- State : Processing_Attributes)
- is
- function In_Initialization_Context (N : Node_Id) return Boolean;
- -- Determine whether arbitrary node N appears within a type init proc,
- -- primitive [Deep_]Initialize, or a block created for initialization
- -- purposes.
+ elsif Call_Lvl = Library_Spec_Level
+ or else Call_Lvl = Instantiation_Level
+ then
+ Add_Library_Spec_Scenario (Call);
+ end if;
- function Is_Partial_Finalization_Proc return Boolean;
- pragma Inline (Is_Partial_Finalization_Proc);
- -- Determine whether call Call with target Target_Id invokes a partial
- -- finalization procedure.
+ -- A call or a task activation requires a conditional ABE check when
+ -- the dynamic model is in effect.
- -------------------------------
- -- In_Initialization_Context --
- -------------------------------
+ Add_Dynamic_ABE_Check_Scenario (Call);
+ end Record_Call_Or_Task_Activation;
- function In_Initialization_Context (N : Node_Id) return Boolean is
- Par : Node_Id;
- Spec_Id : Entity_Id;
+ --------------------------
+ -- Record_Instantiation --
+ --------------------------
+ procedure Record_Instantiation
+ (Inst : Node_Id;
+ Inst_Lvl : Enclosing_Level_Kind)
+ is
begin
- -- Climb the parent chain looking for initialization actions
+ -- Signal enclosing local exception handlers that instantiation may
+ -- raise Program_Error due to failed ABE check. Marking the exception
+ -- handlers ensures proper expansion by both the front and back end
+ -- restriction when No_Exception_Propagation is in effect.
- Par := Parent (N);
- while Present (Par) loop
+ Possible_Local_Raise (Inst, Standard_Program_Error);
- -- A block may be part of the initialization actions of a default
- -- initialized object.
+ -- Perform early detection of guaranteed ABEs in order to suppress
+ -- the instantiation of generic bodies because gigi cannot handle
+ -- certain types of premature instantiations.
- if Nkind (Par) = N_Block_Statement
- and then Is_Initialization_Block (Par)
- then
- return True;
+ Process_Guaranteed_ABE
+ (N => Inst,
+ In_State => Guaranteed_ABE_State);
- -- A subprogram body may denote an initialization routine
+ -- Add the instantiation to the appropriate set
- elsif Nkind (Par) = N_Subprogram_Body then
- Spec_Id := Unique_Defining_Entity (Par);
+ if Inst_Lvl = Declaration_Level then
+ Add_Declaration_Scenario (Inst);
- -- The current subprogram body denotes a type init proc or
- -- primitive [Deep_]Initialize.
+ elsif Inst_Lvl = Library_Body_Level then
+ Add_Library_Body_Scenario (Inst);
- if Is_Init_Proc (Spec_Id)
- or else Is_Controlled_Proc (Spec_Id, Name_Initialize)
- or else Is_TSS (Spec_Id, TSS_Deep_Initialize)
- then
- return True;
- end if;
+ elsif Inst_Lvl = Library_Spec_Level
+ or else Inst_Lvl = Instantiation_Level
+ then
+ Add_Library_Spec_Scenario (Inst);
+ end if;
- -- Prevent the search from going too far
+ -- Instantiations of generics subject to SPARK_Mode On require
+ -- elaboration-related checks even though the instantiations may
+ -- not appear within elaboration code.
- elsif Is_Body_Or_Package_Declaration (Par) then
- exit;
- end if;
+ if Is_Suitable_SPARK_Instantiation (Inst) then
+ Add_SPARK_Scenario (Inst);
+ end if;
- Par := Parent (Par);
- end loop;
+ -- An instantiation requires a conditional ABE check when the dynamic
+ -- model is in effect.
- return False;
- end In_Initialization_Context;
+ Add_Dynamic_ABE_Check_Scenario (Inst);
+ end Record_Instantiation;
- ----------------------------------
- -- Is_Partial_Finalization_Proc --
- ----------------------------------
+ --------------------------------
+ -- Record_Variable_Assignment --
+ --------------------------------
- function Is_Partial_Finalization_Proc return Boolean is
+ procedure Record_Variable_Assignment
+ (Asmt : Node_Id;
+ Asmt_Lvl : Enclosing_Level_Kind)
+ is
begin
- -- To qualify, the target must denote primitive [Deep_]Finalize or a
- -- finalizer procedure, and the call must appear in an initialization
- -- context.
+ -- Add the variable assignment to the appropriate set
- return
- (Is_Controlled_Proc (Target_Id, Name_Finalize)
- or else Is_Finalizer_Proc (Target_Id)
- or else Is_TSS (Target_Id, TSS_Deep_Finalize))
- and then In_Initialization_Context (Call);
- end Is_Partial_Finalization_Proc;
+ if Asmt_Lvl = Library_Body_Level then
+ Add_Library_Body_Scenario (Asmt);
- -- Local variables
+ elsif Asmt_Lvl = Library_Spec_Level
+ or else Asmt_Lvl = Instantiation_Level
+ then
+ Add_Library_Spec_Scenario (Asmt);
+ end if;
+ end Record_Variable_Assignment;
- SPARK_Rules_On : Boolean;
- Target_Attrs : Target_Attributes;
+ -------------------------------
+ -- Record_Variable_Reference --
+ -------------------------------
- New_State : Processing_Attributes := State;
- -- Each step of the Processing phase constitutes a new state
+ procedure Record_Variable_Reference
+ (Ref : Node_Id;
+ Ref_Lvl : Enclosing_Level_Kind)
+ is
+ begin
+ -- Add the variable reference to the appropriate set
- -- Start of processing for Process_Conditional_ABE_Call
+ if Ref_Lvl = Library_Body_Level then
+ Add_Library_Body_Scenario (Ref);
- begin
- Extract_Target_Attributes
- (Target_Id => Target_Id,
- Attrs => Target_Attrs);
+ elsif Ref_Lvl = Library_Spec_Level
+ or else Ref_Lvl = Instantiation_Level
+ then
+ Add_Library_Spec_Scenario (Ref);
+ end if;
+ end Record_Variable_Reference;
- -- The SPARK rules are in effect when both the call and target are
- -- subject to SPARK_Mode On.
+ -- Local variables
- SPARK_Rules_On :=
- Call_Attrs.SPARK_Mode_On and Target_Attrs.SPARK_Mode_On;
+ Scen : constant Node_Id := Scenario (N);
+ Scen_Lvl : Enclosing_Level_Kind;
- -- Output relevant information when switch -gnatel (info messages on
- -- implicit Elaborate[_All] pragmas) is in effect.
+ -- Start of processing for Record_Elaboration_Scenario
- if Elab_Info_Messages then
- Info_Call
- (Call => Call,
- Target_Id => Target_Id,
- Info_Msg => True,
- In_SPARK => SPARK_Rules_On);
- end if;
+ begin
+ -- Nothing to do when switch -gnatH (legacy elaboration checking mode
+ -- enabled) is in effect because the legacy ABE mechanism does not need
+ -- to carry out this action.
- -- Check whether the invocation of an entry clashes with an existing
- -- restriction.
+ if Legacy_Elaboration_Checks then
+ return;
- if Is_Protected_Entry (Target_Id) then
- Check_Restriction (No_Entry_Calls_In_Elaboration_Code, Call);
+ -- Nothing to do for ASIS because ABE checks and diagnostics are not
+ -- performed in this mode.
- elsif Is_Task_Entry (Target_Id) then
- Check_Restriction (No_Entry_Calls_In_Elaboration_Code, Call);
+ elsif ASIS_Mode then
+ return;
- -- Task entry calls are never processed because the entry being
- -- invoked does not have a corresponding "body", it has a select.
+ -- Nothing to do when the scenario is being preanalyzed
+ elsif Preanalysis_Active then
return;
end if;
- -- Nothing to do when the call invokes a target defined within an
- -- instance and switch -gnatd_i (ignore activations and calls to
- -- instances for elaboration) is in effect.
+ Scen_Lvl := Find_Enclosing_Level (Scen);
- if Debug_Flag_Underscore_I
- and then In_External_Instance
- (N => Call,
- Target_Decl => Target_Attrs.Spec_Decl)
- then
- return;
+ -- Ensure that a library-level call does not appear in a preelaborated
+ -- unit. The check must come before ignoring scenarios within external
+ -- units or inside generics because calls in those context must also be
+ -- verified.
- -- Nothing to do when the call is a guaranteed ABE
+ if Is_Suitable_Call (Scen) then
+ Check_Preelaborated_Call (Scen, Scen_Lvl);
+ end if;
- elsif Is_Known_Guaranteed_ABE (Call) then
- return;
+ -- Nothing to do when the scenario does not appear within the main unit
- -- Nothing to do when the root scenario appears at the declaration level
- -- and the target is in the same unit, but outside this context.
- --
- -- function B ...; -- target declaration
- --
- -- procedure Proc is
- -- function A ... is
- -- begin
- -- if Some_Condition then
- -- return B; -- call site
- -- ...
- -- end A;
- --
- -- X : ... := A; -- root scenario
- -- ...
- --
- -- function B ... is
- -- ...
- -- end B;
- --
- -- In the example above, the context of X is the declarative region of
- -- Proc. The "elaboration" of X may eventually reach B which is defined
- -- outside of X's context. B is relevant only when Proc is invoked, but
- -- this happens only by means of "normal" elaboration, therefore B must
- -- not be considered if this is not the case.
+ if not In_Main_Context (Scen) then
+ return;
- -- Performance note: parent traversal
+ -- Nothing to do when the scenario appears within a generic
- elsif Is_Up_Level_Target (Target_Attrs.Spec_Decl) then
+ elsif Inside_A_Generic then
return;
- end if;
-
- -- Warnings are suppressed when a prior scenario is already in that
- -- mode, or the call or target have warnings suppressed. Update the
- -- state of the Processing phase to reflect this.
- New_State.Suppress_Warnings :=
- New_State.Suppress_Warnings
- or else not Call_Attrs.Elab_Warnings_OK
- or else not Target_Attrs.Elab_Warnings_OK;
+ -- 'Access
- -- The call occurs in an initial condition context when a prior scenario
- -- is already in that mode, or when the target is an Initial_Condition
- -- procedure. Update the state of the Processing phase to reflect this.
+ elsif Is_Suitable_Access_Taken (Scen) then
+ Record_Access_Taken
+ (Attr => Scen,
+ Attr_Lvl => Scen_Lvl);
- New_State.Within_Initial_Condition :=
- New_State.Within_Initial_Condition
- or else Is_Initial_Condition_Proc (Target_Id);
+ -- Call or task activation
- -- The call occurs in a partial finalization context when a prior
- -- scenario is already in that mode, or when the target denotes a
- -- [Deep_]Finalize primitive or a finalizer within an initialization
- -- context. Update the state of the Processing phase to reflect this.
+ elsif Is_Suitable_Call (Scen) then
+ Record_Call_Or_Task_Activation
+ (Call => Scen,
+ Call_Lvl => Scen_Lvl);
- New_State.Within_Partial_Finalization :=
- New_State.Within_Partial_Finalization
- or else Is_Partial_Finalization_Proc;
+ -- Derived type declaration
- -- The SPARK rules are in effect. Note that -gnatd.v (enforce SPARK
- -- elaboration rules in SPARK code) is intentionally not taken into
- -- account here because Process_Conditional_ABE_Call_SPARK has two
- -- separate modes of operation.
+ elsif Is_Suitable_SPARK_Derived_Type (Scen) then
+ Add_SPARK_Scenario (Scen);
- if SPARK_Rules_On then
- Process_Conditional_ABE_Call_SPARK
- (Call => Call,
- Target_Id => Target_Id,
- Target_Attrs => Target_Attrs,
- State => New_State);
+ -- Instantiation
- -- Otherwise the Ada rules are in effect
+ elsif Is_Suitable_Instantiation (Scen) then
+ Record_Instantiation
+ (Inst => Scen,
+ Inst_Lvl => Scen_Lvl);
- else
- Process_Conditional_ABE_Call_Ada
- (Call => Call,
- Call_Attrs => Call_Attrs,
- Target_Id => Target_Id,
- Target_Attrs => Target_Attrs,
- State => New_State);
- end if;
+ -- Refined_State pragma
- -- Inspect the target body (and barried function) for other suitable
- -- elaboration scenarios.
+ elsif Is_Suitable_SPARK_Refined_State_Pragma (Scen) then
+ Add_SPARK_Scenario (Scen);
- Traverse_Body
- (N => Target_Attrs.Body_Barf,
- State => New_State);
+ -- Variable assignment
- Traverse_Body
- (N => Target_Attrs.Body_Decl,
- State => New_State);
- end Process_Conditional_ABE_Call;
+ elsif Is_Suitable_Variable_Assignment (Scen) then
+ Record_Variable_Assignment
+ (Asmt => Scen,
+ Asmt_Lvl => Scen_Lvl);
- --------------------------------------
- -- Process_Conditional_ABE_Call_Ada --
- --------------------------------------
+ -- Variable reference
- procedure Process_Conditional_ABE_Call_Ada
- (Call : Node_Id;
- Call_Attrs : Call_Attributes;
- Target_Id : Entity_Id;
- Target_Attrs : Target_Attributes;
- State : Processing_Attributes)
- is
- Check_OK : constant Boolean :=
- not Call_Attrs.Ghost_Mode_Ignore
- and then not Target_Attrs.Ghost_Mode_Ignore
- and then Call_Attrs.Elab_Checks_OK
- and then Target_Attrs.Elab_Checks_OK;
- -- A run-time ABE check may be installed only when both the call and the
- -- target have active elaboration checks, and both are not ignored Ghost
- -- constructs.
+ elsif Is_Suitable_Variable_Reference (Scen) then
+ Record_Variable_Reference
+ (Ref => Scen,
+ Ref_Lvl => Scen_Lvl);
+ end if;
+ end Record_Elaboration_Scenario;
- Root : constant Node_Id := Root_Scenario;
+ --------------
+ -- Scenario --
+ --------------
- New_State : Processing_Attributes := State;
- -- Each step of the Processing phase constitutes a new state
+ function Scenario (N : Node_Id) return Node_Id is
+ Orig_N : constant Node_Id := Original_Node (N);
begin
- -- Nothing to do for an Ada dispatching call because there are no ABE
- -- diagnostics for either models. ABE checks for the dynamic model are
- -- handled by Install_Primitive_Elaboration_Check.
+ -- An expanded instantiation is rewritten into a spec-body pair where
+ -- N denotes the spec. In this case the original instantiation is the
+ -- proper elaboration scenario.
- if Call_Attrs.Is_Dispatching then
- return;
+ if Nkind (Orig_N) in N_Generic_Instantiation then
+ return Orig_N;
- -- Nothing to do when the call is ABE-safe
- --
- -- generic
- -- function Gen ...;
- --
- -- function Gen ... is
- -- begin
- -- ...
- -- end Gen;
- --
- -- with Gen;
- -- procedure Main is
- -- function Inst is new Gen;
- -- X : ... := Inst; -- safe call
- -- ...
+ -- Otherwise the scenario is already in its proper form
- elsif Is_Safe_Call (Call, Target_Attrs) then
- return;
+ else
+ return N;
+ end if;
+ end Scenario;
- -- The call and the target body are both in the main unit
+ ----------------------
+ -- Scenario_Storage --
+ ----------------------
- elsif Present (Target_Attrs.Body_Decl)
- and then In_Extended_Main_Code_Unit (Target_Attrs.Body_Decl)
- then
- -- If the root scenario appears prior to the target body, then this
- -- is a possible ABE with respect to the root scenario.
- --
- -- function B ...;
- --
- -- function A ... is
- -- begin
- -- if Some_Condition then
- -- return B; -- call site
- -- ...
- -- end A;
- --
- -- X : ... := A; -- root scenario
- --
- -- function B ... is -- target body
- -- ...
- -- end B;
- --
- -- Y : ... := A; -- root scenario
- --
- -- IMPORTANT: The call to B from A is a possible ABE for X, but not
- -- for Y. Installing an unconditional ABE raise prior to the call to
- -- B would be wrong as it will fail for Y as well, but in Y's case
- -- the call to B is never an ABE.
+ package body Scenario_Storage is
- if Earlier_In_Extended_Unit (Root, Target_Attrs.Body_Decl) then
+ ---------------------
+ -- Data structures --
+ ---------------------
- -- Do not emit any ABE diagnostics when a previous scenario in
- -- this traversal has suppressed elaboration warnings.
+ -- The following sets store all scenarios
- if State.Suppress_Warnings then
- null;
+ Declaration_Scenarios : NE_Set.Membership_Set :=
+ NE_Set.Create (1000);
+ Dynamic_ABE_Check_Scenarios : NE_Set.Membership_Set :=
+ NE_Set.Create (500);
+ Library_Body_Scenarios : NE_Set.Membership_Set :=
+ NE_Set.Create (1000);
+ Library_Spec_Scenarios : NE_Set.Membership_Set :=
+ NE_Set.Create (1000);
+ SPARK_Scenarios : NE_Set.Membership_Set :=
+ NE_Set.Create (100);
- -- Do not emit any ABE diagnostics when the call occurs in a
- -- partial finalization context because this leads to confusing
- -- noise.
+ -------------------------------
+ -- Finalize_Scenario_Storage --
+ -------------------------------
- elsif State.Within_Partial_Finalization then
- null;
+ procedure Finalize_Scenario_Storage is
+ begin
+ NE_Set.Destroy (Declaration_Scenarios);
+ NE_Set.Destroy (Dynamic_ABE_Check_Scenarios);
+ NE_Set.Destroy (Library_Body_Scenarios);
+ NE_Set.Destroy (Library_Spec_Scenarios);
+ NE_Set.Destroy (SPARK_Scenarios);
+ end Finalize_Scenario_Storage;
+
+ ---------------------------------
+ -- Initialize_Scenario_Storage --
+ ---------------------------------
+
+ procedure Initialize_Scenario_Storage is
+ begin
+ null;
+ end Initialize_Scenario_Storage;
- -- ABE diagnostics are emitted only in the static model because
- -- there is a well-defined order to visiting scenarios. Without
- -- this order diagnostics appear jumbled and result in unwanted
- -- noise.
+ ------------------------------
+ -- Add_Declaration_Scenario --
+ ------------------------------
- elsif Static_Elaboration_Checks then
- Error_Msg_NE
- ("??cannot call & before body seen", Call, Target_Id);
- Error_Msg_N ("\Program_Error may be raised at run time", Call);
+ procedure Add_Declaration_Scenario (N : Node_Id) is
+ pragma Assert (Present (N));
+ begin
+ NE_Set.Insert (Declaration_Scenarios, N);
+ end Add_Declaration_Scenario;
- Output_Active_Scenarios (Call);
- end if;
+ ------------------------------------
+ -- Add_Dynamic_ABE_Check_Scenario --
+ ------------------------------------
- -- Install a conditional run-time ABE check to verify that the
- -- target body has been elaborated prior to the call.
+ procedure Add_Dynamic_ABE_Check_Scenario (N : Node_Id) is
+ pragma Assert (Present (N));
- if Check_OK then
- Install_ABE_Check
- (N => Call,
- Ins_Nod => Call,
- Target_Id => Target_Attrs.Spec_Id,
- Target_Decl => Target_Attrs.Spec_Decl,
- Target_Body => Target_Attrs.Body_Decl);
+ begin
+ if not Check_Or_Failure_Generation_OK then
+ return;
- -- Update the state of the Processing phase to indicate that
- -- no implicit Elaborate[_All] pragmas must be generated from
- -- this point on.
- --
- -- function B ...;
- --
- -- function A ... is
- -- begin
- -- if Some_Condition then
- -- <ABE check>
- -- return B;
- -- ...
- -- end A;
- --
- -- X : ... := A;
- --
- -- function B ... is
- -- External.Subp; -- imparts Elaborate_All
- -- end B;
- --
- -- If Some_Condition is True, then the ABE check will fail at
- -- runtime and the call to External.Subp will never take place,
- -- rendering the implicit Elaborate_All useless.
- --
- -- If Some_Condition is False, then the call to External.Subp
- -- will never take place, rendering the implicit Elaborate_All
- -- useless.
+ -- Nothing to do if the dynamic model is not in effect
- New_State.Suppress_Implicit_Pragmas := True;
- end if;
+ elsif not Dynamic_Elaboration_Checks then
+ return;
end if;
- -- Otherwise the target body is not available in this compilation or it
- -- resides in an external unit. Install a run-time ABE check to verify
- -- that the target body has been elaborated prior to the call site when
- -- the dynamic model is in effect.
+ NE_Set.Insert (Dynamic_ABE_Check_Scenarios, N);
+ end Add_Dynamic_ABE_Check_Scenario;
- elsif Dynamic_Elaboration_Checks and then Check_OK then
- Install_ABE_Check
- (N => Call,
- Ins_Nod => Call,
- Id => Target_Attrs.Unit_Id);
- end if;
+ -------------------------------
+ -- Add_Library_Body_Scenario --
+ -------------------------------
- -- Ensure that the unit with the target body is elaborated prior to the
- -- main unit. The implicit Elaborate[_All] is generated only when the
- -- call has elaboration checks enabled. This behaviour parallels that of
- -- the old ABE mechanism.
+ procedure Add_Library_Body_Scenario (N : Node_Id) is
+ pragma Assert (Present (N));
+ begin
+ NE_Set.Insert (Library_Body_Scenarios, N);
+ end Add_Library_Body_Scenario;
- if Call_Attrs.Elab_Checks_OK then
- Ensure_Prior_Elaboration
- (N => Call,
- Unit_Id => Target_Attrs.Unit_Id,
- Prag_Nam => Name_Elaborate_All,
- State => New_State);
- end if;
- end Process_Conditional_ABE_Call_Ada;
+ -------------------------------
+ -- Add_Library_Spec_Scenario --
+ -------------------------------
- ----------------------------------------
- -- Process_Conditional_ABE_Call_SPARK --
- ----------------------------------------
+ procedure Add_Library_Spec_Scenario (N : Node_Id) is
+ pragma Assert (Present (N));
+ begin
+ NE_Set.Insert (Library_Spec_Scenarios, N);
+ end Add_Library_Spec_Scenario;
- procedure Process_Conditional_ABE_Call_SPARK
- (Call : Node_Id;
- Target_Id : Entity_Id;
- Target_Attrs : Target_Attributes;
- State : Processing_Attributes)
- is
- Region : Node_Id;
+ ------------------------
+ -- Add_SPARK_Scenario --
+ ------------------------
- begin
- -- Ensure that a suitable elaboration model is in effect for SPARK rule
- -- verification.
+ procedure Add_SPARK_Scenario (N : Node_Id) is
+ pragma Assert (Present (N));
+ begin
+ NE_Set.Insert (SPARK_Scenarios, N);
+ end Add_SPARK_Scenario;
- Check_SPARK_Model_In_Effect (Call);
+ ---------------------
+ -- Delete_Scenario --
+ ---------------------
- -- The call and the target body are both in the main unit
+ procedure Delete_Scenario (N : Node_Id) is
+ pragma Assert (Present (N));
- if Present (Target_Attrs.Body_Decl)
- and then In_Extended_Main_Code_Unit (Target_Attrs.Body_Decl)
- then
- -- If the call appears prior to the target body, then the call must
- -- appear within the early call region of the target body.
- --
- -- function B ...;
- --
- -- X : ... := B; -- call site
- --
- -- <preelaborable construct 1> --+
- -- ... | early call region
- -- <preelaborable construct N> --+
- --
- -- function B ... is -- target body
- -- ...
- -- end B;
- --
- -- When the call to B is not nested within some other scenario, the
- -- call is automatically illegal because it can never appear in the
- -- early call region of B's body. This is equivalent to a guaranteed
- -- ABE.
- --
- -- <preelaborable construct 1> --+
- -- |
- -- function B ...; |
- -- |
- -- function A ... is |
- -- begin | early call region
- -- if Some_Condition then
- -- return B; -- call site
- -- ...
- -- end A; |
- -- |
- -- <preelaborable construct N> --+
- --
- -- function B ... is -- target body
- -- ...
- -- end B;
- --
- -- When the call to B is nested within some other scenario, the call
- -- is always ABE-safe. It is not immediately obvious why this is the
- -- case. The elaboration safety follows from the early call region
- -- rule being applied to ALL calls preceding their associated bodies.
- --
- -- In the example above, the call to B is safe as long as the call to
- -- A is safe. There are several cases to consider:
- --
- -- <call 1 to A>
- -- function B ...;
- --
- -- <call 2 to A>
- -- function A ... is
- -- begin
- -- if Some_Condition then
- -- return B;
- -- ...
- -- end A;
- --
- -- <call 3 to A>
- -- function B ... is
- -- ...
- -- end B;
- --
- -- * Call 1 - This call is either nested within some scenario or not,
- -- which falls under the two general cases outlined above.
- --
- -- * Call 2 - This is the same case as Call 1.
- --
- -- * Call 3 - The placement of this call limits the range of B's
- -- early call region unto call 3, therefore the call to B is no
- -- longer within the early call region of B's body, making it ABE-
- -- unsafe and therefore illegal.
+ begin
+ -- Delete the scenario from whichever set it belongs to
- if Earlier_In_Extended_Unit (Call, Target_Attrs.Body_Decl) then
+ NE_Set.Delete (Declaration_Scenarios, N);
+ NE_Set.Delete (Dynamic_ABE_Check_Scenarios, N);
+ NE_Set.Delete (Library_Body_Scenarios, N);
+ NE_Set.Delete (Library_Spec_Scenarios, N);
+ NE_Set.Delete (SPARK_Scenarios, N);
+ end Delete_Scenario;
- -- Do not emit any ABE diagnostics when a previous scenario in
- -- this traversal has suppressed elaboration warnings.
+ -----------------------------------
+ -- Iterate_Declaration_Scenarios --
+ -----------------------------------
- if State.Suppress_Warnings then
- null;
+ function Iterate_Declaration_Scenarios return NE_Set.Iterator is
+ begin
+ return NE_Set.Iterate (Declaration_Scenarios);
+ end Iterate_Declaration_Scenarios;
- -- Do not emit any ABE diagnostics when the call occurs in an
- -- initial condition context because this leads to incorrect
- -- diagnostics.
+ -----------------------------------------
+ -- Iterate_Dynamic_ABE_Check_Scenarios --
+ -----------------------------------------
- elsif State.Within_Initial_Condition then
- null;
+ function Iterate_Dynamic_ABE_Check_Scenarios return NE_Set.Iterator is
+ begin
+ return NE_Set.Iterate (Dynamic_ABE_Check_Scenarios);
+ end Iterate_Dynamic_ABE_Check_Scenarios;
- -- Do not emit any ABE diagnostics when the call occurs in a
- -- partial finalization context because this leads to confusing
- -- noise.
+ ------------------------------------
+ -- Iterate_Library_Body_Scenarios --
+ ------------------------------------
- elsif State.Within_Partial_Finalization then
- null;
+ function Iterate_Library_Body_Scenarios return NE_Set.Iterator is
+ begin
+ return NE_Set.Iterate (Library_Body_Scenarios);
+ end Iterate_Library_Body_Scenarios;
- -- ABE diagnostics are emitted only in the static model because
- -- there is a well-defined order to visiting scenarios. Without
- -- this order diagnostics appear jumbled and result in unwanted
- -- noise.
+ ------------------------------------
+ -- Iterate_Library_Spec_Scenarios --
+ ------------------------------------
- elsif Static_Elaboration_Checks then
+ function Iterate_Library_Spec_Scenarios return NE_Set.Iterator is
+ begin
+ return NE_Set.Iterate (Library_Spec_Scenarios);
+ end Iterate_Library_Spec_Scenarios;
- -- Ensure that a call which textually precedes the subprogram
- -- body it invokes appears within the early call region of the
- -- subprogram body.
+ -----------------------------
+ -- Iterate_SPARK_Scenarios --
+ -----------------------------
- -- IMPORTANT: This check must always be performed even when
- -- -gnatd.v (enforce SPARK elaboration rules in SPARK code) is
- -- not specified because the static model cannot guarantee the
- -- absence of elaboration issues in the presence of dispatching
- -- calls.
+ function Iterate_SPARK_Scenarios return NE_Set.Iterator is
+ begin
+ return NE_Set.Iterate (SPARK_Scenarios);
+ end Iterate_SPARK_Scenarios;
- Region := Find_Early_Call_Region (Target_Attrs.Body_Decl);
+ ----------------------
+ -- Replace_Scenario --
+ ----------------------
- if Earlier_In_Extended_Unit (Call, Region) then
- Error_Msg_NE
- ("call must appear within early call region of subprogram "
- & "body & (SPARK RM 7.7(3))", Call, Target_Id);
+ procedure Replace_Scenario (Old_N : Node_Id; New_N : Node_Id) is
+ procedure Replace_Scenario_In (Scenarios : NE_Set.Membership_Set);
+ -- Determine whether scenario Old_N is present in set Scenarios, and
+ -- if this is the case it, replace it with New_N.
- Error_Msg_Sloc := Sloc (Region);
- Error_Msg_N ("\region starts #", Call);
+ -------------------------
+ -- Replace_Scenario_In --
+ -------------------------
- Error_Msg_Sloc := Sloc (Target_Attrs.Body_Decl);
- Error_Msg_N ("\region ends #", Call);
+ procedure Replace_Scenario_In (Scenarios : NE_Set.Membership_Set) is
+ begin
+ -- The set is intentionally checked for existance because node
+ -- rewriting may occur after Sem_Elab has verified all scenarios
+ -- and data structures have been destroyed.
- Output_Active_Scenarios (Call);
- end if;
+ if NE_Set.Present (Scenarios)
+ and then NE_Set.Contains (Scenarios, Old_N)
+ then
+ NE_Set.Delete (Scenarios, Old_N);
+ NE_Set.Insert (Scenarios, New_N);
end if;
+ end Replace_Scenario_In;
- -- Otherwise the call appears after the target body. The call is
- -- ABE-safe as a consequence of applying the early call region rule
- -- to ALL calls preceding their associated bodies.
+ -- Start of processing for Replace_Scenario
- else
- null;
- end if;
- end if;
+ begin
+ Replace_Scenario_In (Declaration_Scenarios);
+ Replace_Scenario_In (Dynamic_ABE_Check_Scenarios);
+ Replace_Scenario_In (Library_Body_Scenarios);
+ Replace_Scenario_In (Library_Spec_Scenarios);
+ Replace_Scenario_In (SPARK_Scenarios);
+ end Replace_Scenario;
+ end Scenario_Storage;
- -- A call to a source target or to a target which emulates Ada or SPARK
- -- semantics imposes an Elaborate_All requirement on the context of the
- -- main unit. Determine whether the context has a pragma strong enough
- -- to meet the requirement.
+ ---------------
+ -- Semantics --
+ ---------------
- -- IMPORTANT: This check must be performed only when -gnatd.v (enforce
- -- SPARK elaboration rules in SPARK code) is active because the static
- -- model can ensure the prior elaboration of the unit which contains a
- -- body by installing an implicit Elaborate[_All] pragma.
+ package body Semantics is
- if Debug_Flag_Dot_V then
- if Target_Attrs.From_Source
- or else Is_Ada_Semantic_Target (Target_Id)
- or else Is_SPARK_Semantic_Target (Target_Id)
- then
- Meet_Elaboration_Requirement
- (N => Call,
- Target_Id => Target_Id,
- Req_Nam => Name_Elaborate_All);
- end if;
+ --------------------------------
+ -- Is_Accept_Alternative_Proc --
+ --------------------------------
- -- Otherwise ensure that the unit with the target body is elaborated
- -- prior to the main unit.
+ function Is_Accept_Alternative_Proc (Id : Entity_Id) return Boolean is
+ begin
+ -- To qualify, the entity must denote a procedure with a receiving
+ -- entry.
- else
- Ensure_Prior_Elaboration
- (N => Call,
- Unit_Id => Target_Attrs.Unit_Id,
- Prag_Nam => Name_Elaborate_All,
- State => State);
- end if;
- end Process_Conditional_ABE_Call_SPARK;
+ return
+ Ekind (Id) = E_Procedure and then Present (Receiving_Entry (Id));
+ end Is_Accept_Alternative_Proc;
- -------------------------------------------
- -- Process_Conditional_ABE_Instantiation --
- -------------------------------------------
+ ------------------------
+ -- Is_Activation_Proc --
+ ------------------------
- procedure Process_Conditional_ABE_Instantiation
- (Exp_Inst : Node_Id;
- State : Processing_Attributes)
- is
- Gen_Attrs : Target_Attributes;
- Gen_Id : Entity_Id;
- Inst : Node_Id;
- Inst_Attrs : Instantiation_Attributes;
- Inst_Id : Entity_Id;
+ function Is_Activation_Proc (Id : Entity_Id) return Boolean is
+ begin
+ -- To qualify, the entity must denote one of the runtime procedures
+ -- in charge of task activation.
- SPARK_Rules_On : Boolean;
- -- This flag is set when the SPARK rules are in effect
+ if Ekind (Id) = E_Procedure then
+ if Restricted_Profile then
+ return Is_RTE (Id, RE_Activate_Restricted_Tasks);
+ else
+ return Is_RTE (Id, RE_Activate_Tasks);
+ end if;
+ end if;
- New_State : Processing_Attributes := State;
- -- Each step of the Processing phase constitutes a new state
+ return False;
+ end Is_Activation_Proc;
- begin
- Extract_Instantiation_Attributes
- (Exp_Inst => Exp_Inst,
- Inst => Inst,
- Inst_Id => Inst_Id,
- Gen_Id => Gen_Id,
- Attrs => Inst_Attrs);
+ ----------------------------
+ -- Is_Ada_Semantic_Target --
+ ----------------------------
- Extract_Target_Attributes (Gen_Id, Gen_Attrs);
+ function Is_Ada_Semantic_Target (Id : Entity_Id) return Boolean is
+ begin
+ return
+ Is_Activation_Proc (Id)
+ or else Is_Controlled_Proc (Id, Name_Adjust)
+ or else Is_Controlled_Proc (Id, Name_Finalize)
+ or else Is_Controlled_Proc (Id, Name_Initialize)
+ or else Is_Init_Proc (Id)
+ or else Is_Invariant_Proc (Id)
+ or else Is_Protected_Entry (Id)
+ or else Is_Protected_Subp (Id)
+ or else Is_Protected_Body_Subp (Id)
+ or else Is_Subprogram_Inst (Id)
+ or else Is_Task_Entry (Id);
+ end Is_Ada_Semantic_Target;
- -- The SPARK rules are in effect when both the instantiation and generic
- -- are subject to SPARK_Mode On.
+ --------------------------------
+ -- Is_Assertion_Pragma_Target --
+ --------------------------------
- SPARK_Rules_On := Inst_Attrs.SPARK_Mode_On and Gen_Attrs.SPARK_Mode_On;
+ function Is_Assertion_Pragma_Target (Id : Entity_Id) return Boolean is
+ begin
+ return
+ Is_Default_Initial_Condition_Proc (Id)
+ or else Is_Initial_Condition_Proc (Id)
+ or else Is_Invariant_Proc (Id)
+ or else Is_Partial_Invariant_Proc (Id)
+ or else Is_Postconditions_Proc (Id);
+ end Is_Assertion_Pragma_Target;
- -- Output relevant information when switch -gnatel (info messages on
- -- implicit Elaborate[_All] pragmas) is in effect.
+ ----------------------------
+ -- Is_Bodiless_Subprogram --
+ ----------------------------
- if Elab_Info_Messages then
- Info_Instantiation
- (Inst => Inst,
- Gen_Id => Gen_Id,
- Info_Msg => True,
- In_SPARK => SPARK_Rules_On);
- end if;
+ function Is_Bodiless_Subprogram (Subp_Id : Entity_Id) return Boolean is
+ begin
+ -- An abstract subprogram does not have a body
- -- Nothing to do when the instantiation is a guaranteed ABE
+ if Ekind_In (Subp_Id, E_Function,
+ E_Operator,
+ E_Procedure)
+ and then Is_Abstract_Subprogram (Subp_Id)
+ then
+ return True;
- if Is_Known_Guaranteed_ABE (Inst) then
- return;
+ -- A formal subprogram does not have a body
- -- Nothing to do when the root scenario appears at the declaration level
- -- and the generic is in the same unit, but outside this context.
- --
- -- generic
- -- procedure Gen is ...; -- generic declaration
- --
- -- procedure Proc is
- -- function A ... is
- -- begin
- -- if Some_Condition then
- -- declare
- -- procedure I is new Gen; -- instantiation site
- -- ...
- -- ...
- -- end A;
- --
- -- X : ... := A; -- root scenario
- -- ...
- --
- -- procedure Gen is
- -- ...
- -- end Gen;
- --
- -- In the example above, the context of X is the declarative region of
- -- Proc. The "elaboration" of X may eventually reach Gen which appears
- -- outside of X's context. Gen is relevant only when Proc is invoked,
- -- but this happens only by means of "normal" elaboration, therefore
- -- Gen must not be considered if this is not the case.
+ elsif Is_Formal_Subprogram (Subp_Id) then
+ return True;
- -- Performance note: parent traversal
+ -- An imported subprogram may have a body, however it is not known at
+ -- compile or bind time where the body resides and whether it will be
+ -- elaborated on time.
- elsif Is_Up_Level_Target (Gen_Attrs.Spec_Decl) then
- return;
- end if;
+ elsif Is_Imported (Subp_Id) then
+ return True;
+ end if;
- -- Warnings are suppressed when a prior scenario is already in that
- -- mode, or when the instantiation has warnings suppressed. Update
- -- the state of the processing phase to reflect this.
+ return False;
+ end Is_Bodiless_Subprogram;
- New_State.Suppress_Warnings :=
- New_State.Suppress_Warnings or else not Inst_Attrs.Elab_Warnings_OK;
+ ----------------------
+ -- Is_Bridge_Target --
+ ----------------------
- -- The SPARK rules are in effect
+ function Is_Bridge_Target (Id : Entity_Id) return Boolean is
+ begin
+ return
+ Is_Accept_Alternative_Proc (Id)
+ or else Is_Finalizer_Proc (Id)
+ or else Is_Partial_Invariant_Proc (Id)
+ or else Is_Postconditions_Proc (Id)
+ or else Is_TSS (Id, TSS_Deep_Adjust)
+ or else Is_TSS (Id, TSS_Deep_Finalize)
+ or else Is_TSS (Id, TSS_Deep_Initialize);
+ end Is_Bridge_Target;
- if SPARK_Rules_On then
- Process_Conditional_ABE_Instantiation_SPARK
- (Inst => Inst,
- Gen_Id => Gen_Id,
- Gen_Attrs => Gen_Attrs,
- State => New_State);
+ ------------------------
+ -- Is_Controlled_Proc --
+ ------------------------
- -- Otherwise the Ada rules are in effect, or SPARK code is allowed to
- -- violate the SPARK rules.
+ function Is_Controlled_Proc
+ (Subp_Id : Entity_Id;
+ Subp_Nam : Name_Id) return Boolean
+ is
+ Formal_Id : Entity_Id;
- else
- Process_Conditional_ABE_Instantiation_Ada
- (Exp_Inst => Exp_Inst,
- Inst => Inst,
- Inst_Attrs => Inst_Attrs,
- Gen_Id => Gen_Id,
- Gen_Attrs => Gen_Attrs,
- State => New_State);
- end if;
- end Process_Conditional_ABE_Instantiation;
-
- -----------------------------------------------
- -- Process_Conditional_ABE_Instantiation_Ada --
- -----------------------------------------------
-
- procedure Process_Conditional_ABE_Instantiation_Ada
- (Exp_Inst : Node_Id;
- Inst : Node_Id;
- Inst_Attrs : Instantiation_Attributes;
- Gen_Id : Entity_Id;
- Gen_Attrs : Target_Attributes;
- State : Processing_Attributes)
- is
- Check_OK : constant Boolean :=
- not Inst_Attrs.Ghost_Mode_Ignore
- and then not Gen_Attrs.Ghost_Mode_Ignore
- and then Inst_Attrs.Elab_Checks_OK
- and then Gen_Attrs.Elab_Checks_OK;
- -- A run-time ABE check may be installed only when both the instance and
- -- the generic have active elaboration checks and both are not ignored
- -- Ghost constructs.
+ begin
+ pragma Assert (Nam_In (Subp_Nam, Name_Adjust,
+ Name_Finalize,
+ Name_Initialize));
- Root : constant Node_Id := Root_Scenario;
+ -- To qualify, the subprogram must denote a source procedure with
+ -- name Adjust, Finalize, or Initialize where the sole formal is
+ -- controlled.
- New_State : Processing_Attributes := State;
- -- Each step of the Processing phase constitutes a new state
+ if Comes_From_Source (Subp_Id)
+ and then Ekind (Subp_Id) = E_Procedure
+ and then Chars (Subp_Id) = Subp_Nam
+ then
+ Formal_Id := First_Formal (Subp_Id);
- begin
- -- Nothing to do when the instantiation is ABE-safe
- --
- -- generic
- -- package Gen is
- -- ...
- -- end Gen;
- --
- -- package body Gen is
- -- ...
- -- end Gen;
- --
- -- with Gen;
- -- procedure Main is
- -- package Inst is new Gen (ABE); -- safe instantiation
- -- ...
+ return
+ Present (Formal_Id)
+ and then Is_Controlled (Etype (Formal_Id))
+ and then No (Next_Formal (Formal_Id));
+ end if;
- if Is_Safe_Instantiation (Inst, Gen_Attrs) then
- return;
+ return False;
+ end Is_Controlled_Proc;
- -- The instantiation and the generic body are both in the main unit
+ ---------------------------------------
+ -- Is_Default_Initial_Condition_Proc --
+ ---------------------------------------
- elsif Present (Gen_Attrs.Body_Decl)
- and then In_Extended_Main_Code_Unit (Gen_Attrs.Body_Decl)
- then
- -- If the root scenario appears prior to the generic body, then this
- -- is a possible ABE with respect to the root scenario.
- --
- -- generic
- -- package Gen is
- -- ...
- -- end Gen;
- --
- -- function A ... is
- -- begin
- -- if Some_Condition then
- -- declare
- -- package Inst is new Gen; -- instantiation site
- -- ...
- -- end A;
- --
- -- X : ... := A; -- root scenario
- --
- -- package body Gen is -- generic body
- -- ...
- -- end Gen;
- --
- -- Y : ... := A; -- root scenario
- --
- -- IMPORTANT: The instantiation of Gen is a possible ABE for X, but
- -- not for Y. Installing an unconditional ABE raise prior to the
- -- instance site would be wrong as it will fail for Y as well, but in
- -- Y's case the instantiation of Gen is never an ABE.
+ function Is_Default_Initial_Condition_Proc
+ (Id : Entity_Id) return Boolean
+ is
+ begin
+ -- To qualify, the entity must denote a Default_Initial_Condition
+ -- procedure.
- if Earlier_In_Extended_Unit (Root, Gen_Attrs.Body_Decl) then
+ return Ekind (Id) = E_Procedure and then Is_DIC_Procedure (Id);
+ end Is_Default_Initial_Condition_Proc;
- -- Do not emit any ABE diagnostics when a previous scenario in
- -- this traversal has suppressed elaboration warnings.
+ -----------------------
+ -- Is_Finalizer_Proc --
+ -----------------------
- if State.Suppress_Warnings then
- null;
+ function Is_Finalizer_Proc (Id : Entity_Id) return Boolean is
+ begin
+ -- To qualify, the entity must denote a _Finalizer procedure
- -- Do not emit any ABE diagnostics when the instantiation occurs
- -- in partial finalization context because this leads to unwanted
- -- noise.
+ return Ekind (Id) = E_Procedure and then Chars (Id) = Name_uFinalizer;
+ end Is_Finalizer_Proc;
- elsif State.Within_Partial_Finalization then
- null;
+ -------------------------------
+ -- Is_Initial_Condition_Proc --
+ -------------------------------
- -- ABE diagnostics are emitted only in the static model because
- -- there is a well-defined order to visiting scenarios. Without
- -- this order diagnostics appear jumbled and result in unwanted
- -- noise.
+ function Is_Initial_Condition_Proc (Id : Entity_Id) return Boolean is
+ begin
+ -- To qualify, the entity must denote an Initial_Condition procedure
- elsif Static_Elaboration_Checks then
- Error_Msg_NE
- ("??cannot instantiate & before body seen", Inst, Gen_Id);
- Error_Msg_N ("\Program_Error may be raised at run time", Inst);
+ return
+ Ekind (Id) = E_Procedure
+ and then Is_Initial_Condition_Procedure (Id);
+ end Is_Initial_Condition_Proc;
- Output_Active_Scenarios (Inst);
- end if;
+ --------------------
+ -- Is_Initialized --
+ --------------------
- -- Install a conditional run-time ABE check to verify that the
- -- generic body has been elaborated prior to the instantiation.
+ function Is_Initialized (Obj_Decl : Node_Id) return Boolean is
+ begin
+ -- To qualify, the object declaration must have an expression
- if Check_OK then
- Install_ABE_Check
- (N => Inst,
- Ins_Nod => Exp_Inst,
- Target_Id => Gen_Attrs.Spec_Id,
- Target_Decl => Gen_Attrs.Spec_Decl,
- Target_Body => Gen_Attrs.Body_Decl);
+ return
+ Present (Expression (Obj_Decl))
+ or else Has_Init_Expression (Obj_Decl);
+ end Is_Initialized;
- -- Update the state of the Processing phase to indicate that
- -- no implicit Elaborate[_All] pragmas must be generated from
- -- this point on.
- --
- -- generic
- -- package Gen is
- -- ...
- -- end Gen;
- --
- -- function A ... is
- -- begin
- -- if Some_Condition then
- -- <ABE check>
- -- declare Inst is new Gen;
- -- ...
- -- end A;
- --
- -- X : ... := A;
- --
- -- package body Gen is
- -- begin
- -- External.Subp; -- imparts Elaborate_All
- -- end Gen;
- --
- -- If Some_Condition is True, then the ABE check will fail at
- -- runtime and the call to External.Subp will never take place,
- -- rendering the implicit Elaborate_All useless.
- --
- -- If Some_Condition is False, then the call to External.Subp
- -- will never take place, rendering the implicit Elaborate_All
- -- useless.
+ -----------------------
+ -- Is_Invariant_Proc --
+ -----------------------
- New_State.Suppress_Implicit_Pragmas := True;
- end if;
- end if;
+ function Is_Invariant_Proc (Id : Entity_Id) return Boolean is
+ begin
+ -- To qualify, the entity must denote the "full" invariant procedure
- -- Otherwise the generic body is not available in this compilation or it
- -- resides in an external unit. Install a run-time ABE check to verify
- -- that the generic body has been elaborated prior to the instantiation
- -- when the dynamic model is in effect.
+ return Ekind (Id) = E_Procedure and then Is_Invariant_Procedure (Id);
+ end Is_Invariant_Proc;
- elsif Dynamic_Elaboration_Checks and then Check_OK then
- Install_ABE_Check
- (N => Inst,
- Ins_Nod => Exp_Inst,
- Id => Gen_Attrs.Unit_Id);
- end if;
+ ---------------------------------------
+ -- Is_Non_Library_Level_Encapsulator --
+ ---------------------------------------
- -- Ensure that the unit with the generic body is elaborated prior to
- -- the main unit. No implicit pragma is generated if the instantiation
- -- has elaboration checks suppressed. This behaviour parallels that of
- -- the old ABE mechanism.
+ function Is_Non_Library_Level_Encapsulator
+ (N : Node_Id) return Boolean
+ is
+ begin
+ case Nkind (N) is
+ when N_Abstract_Subprogram_Declaration
+ | N_Aspect_Specification
+ | N_Component_Declaration
+ | N_Entry_Body
+ | N_Entry_Declaration
+ | N_Expression_Function
+ | N_Formal_Abstract_Subprogram_Declaration
+ | N_Formal_Concrete_Subprogram_Declaration
+ | N_Formal_Object_Declaration
+ | N_Formal_Package_Declaration
+ | N_Formal_Type_Declaration
+ | N_Generic_Association
+ | N_Implicit_Label_Declaration
+ | N_Incomplete_Type_Declaration
+ | N_Private_Extension_Declaration
+ | N_Private_Type_Declaration
+ | N_Protected_Body
+ | N_Protected_Type_Declaration
+ | N_Single_Protected_Declaration
+ | N_Single_Task_Declaration
+ | N_Subprogram_Body
+ | N_Subprogram_Declaration
+ | N_Task_Body
+ | N_Task_Type_Declaration
+ =>
+ return True;
- if Inst_Attrs.Elab_Checks_OK then
- Ensure_Prior_Elaboration
- (N => Inst,
- Unit_Id => Gen_Attrs.Unit_Id,
- Prag_Nam => Name_Elaborate,
- State => New_State);
- end if;
- end Process_Conditional_ABE_Instantiation_Ada;
+ when others =>
+ return Is_Generic_Declaration_Or_Body (N);
+ end case;
+ end Is_Non_Library_Level_Encapsulator;
- -------------------------------------------------
- -- Process_Conditional_ABE_Instantiation_SPARK --
- -------------------------------------------------
+ -------------------------------
+ -- Is_Partial_Invariant_Proc --
+ -------------------------------
- procedure Process_Conditional_ABE_Instantiation_SPARK
- (Inst : Node_Id;
- Gen_Id : Entity_Id;
- Gen_Attrs : Target_Attributes;
- State : Processing_Attributes)
- is
- Req_Nam : Name_Id;
+ function Is_Partial_Invariant_Proc (Id : Entity_Id) return Boolean is
+ begin
+ -- To qualify, the entity must denote the "partial" invariant
+ -- procedure.
- begin
- -- Ensure that a suitable elaboration model is in effect for SPARK rule
- -- verification.
+ return
+ Ekind (Id) = E_Procedure
+ and then Is_Partial_Invariant_Procedure (Id);
+ end Is_Partial_Invariant_Proc;
- Check_SPARK_Model_In_Effect (Inst);
+ ----------------------------
+ -- Is_Postconditions_Proc --
+ ----------------------------
- -- A source instantiation imposes an Elaborate[_All] requirement on the
- -- context of the main unit. Determine whether the context has a pragma
- -- strong enough to meet the requirement. The check is orthogonal to the
- -- ABE ramifications of the instantiation.
+ function Is_Postconditions_Proc (Id : Entity_Id) return Boolean is
+ begin
+ -- To qualify, the entity must denote a _Postconditions procedure
- -- IMPORTANT: This check must be performed only when -gnatd.v (enforce
- -- SPARK elaboration rules in SPARK code) is active because the static
- -- model can ensure the prior elaboration of the unit which contains a
- -- body by installing an implicit Elaborate[_All] pragma.
+ return
+ Ekind (Id) = E_Procedure and then Chars (Id) = Name_uPostconditions;
+ end Is_Postconditions_Proc;
- if Debug_Flag_Dot_V then
- if Nkind (Inst) = N_Package_Instantiation then
- Req_Nam := Name_Elaborate_All;
- else
- Req_Nam := Name_Elaborate;
- end if;
+ ---------------------------
+ -- Is_Preelaborated_Unit --
+ ---------------------------
- Meet_Elaboration_Requirement
- (N => Inst,
- Target_Id => Gen_Id,
- Req_Nam => Req_Nam);
+ function Is_Preelaborated_Unit (Id : Entity_Id) return Boolean is
+ begin
+ return
+ Is_Preelaborated (Id)
+ or else Is_Pure (Id)
+ or else Is_Remote_Call_Interface (Id)
+ or else Is_Remote_Types (Id)
+ or else Is_Shared_Passive (Id);
+ end Is_Preelaborated_Unit;
+
+ ------------------------
+ -- Is_Protected_Entry --
+ ------------------------
+
+ function Is_Protected_Entry (Id : Entity_Id) return Boolean is
+ begin
+ -- To qualify, the entity must denote an entry defined in a protected
+ -- type.
- -- Otherwise ensure that the unit with the target body is elaborated
- -- prior to the main unit.
+ return
+ Is_Entry (Id)
+ and then Is_Protected_Type (Non_Private_View (Scope (Id)));
+ end Is_Protected_Entry;
- else
- Ensure_Prior_Elaboration
- (N => Inst,
- Unit_Id => Gen_Attrs.Unit_Id,
- Prag_Nam => Name_Elaborate,
- State => State);
- end if;
- end Process_Conditional_ABE_Instantiation_SPARK;
+ -----------------------
+ -- Is_Protected_Subp --
+ -----------------------
- -------------------------------------------------
- -- Process_Conditional_ABE_Variable_Assignment --
- -------------------------------------------------
+ function Is_Protected_Subp (Id : Entity_Id) return Boolean is
+ begin
+ -- To qualify, the entity must denote a subprogram defined within a
+ -- protected type.
- procedure Process_Conditional_ABE_Variable_Assignment (Asmt : Node_Id) is
- Var_Id : constant Entity_Id := Entity (Extract_Assignment_Name (Asmt));
- Prag : constant Node_Id := SPARK_Pragma (Var_Id);
+ return
+ Ekind_In (Id, E_Function, E_Procedure)
+ and then Is_Protected_Type (Non_Private_View (Scope (Id)));
+ end Is_Protected_Subp;
- SPARK_Rules_On : Boolean;
- -- This flag is set when the SPARK rules are in effect
+ ----------------------------
+ -- Is_Protected_Body_Subp --
+ ----------------------------
- begin
- -- The SPARK rules are in effect when both the assignment and the
- -- variable are subject to SPARK_Mode On.
+ function Is_Protected_Body_Subp (Id : Entity_Id) return Boolean is
+ begin
+ -- To qualify, the entity must denote a subprogram with attribute
+ -- Protected_Subprogram set.
- SPARK_Rules_On :=
- Present (Prag)
- and then Get_SPARK_Mode_From_Annotation (Prag) = On
- and then Is_SPARK_Mode_On_Node (Asmt);
+ return
+ Ekind_In (Id, E_Function, E_Procedure)
+ and then Present (Protected_Subprogram (Id));
+ end Is_Protected_Body_Subp;
- -- Output relevant information when switch -gnatel (info messages on
- -- implicit Elaborate[_All] pragmas) is in effect.
+ -----------------
+ -- Is_Scenario --
+ -----------------
- if Elab_Info_Messages then
- Elab_Msg_NE
- (Msg => "assignment to & during elaboration",
- N => Asmt,
- Id => Var_Id,
- Info_Msg => True,
- In_SPARK => SPARK_Rules_On);
- end if;
+ function Is_Scenario (N : Node_Id) return Boolean is
+ begin
+ case Nkind (N) is
+ when N_Assignment_Statement
+ | N_Attribute_Reference
+ | N_Call_Marker
+ | N_Entry_Call_Statement
+ | N_Expanded_Name
+ | N_Function_Call
+ | N_Function_Instantiation
+ | N_Identifier
+ | N_Package_Instantiation
+ | N_Procedure_Call_Statement
+ | N_Procedure_Instantiation
+ | N_Requeue_Statement
+ =>
+ return True;
- -- The SPARK rules are in effect. These rules are applied regardless of
- -- whether -gnatd.v (enforce SPARK elaboration rules in SPARK code) is
- -- in effect because the static model cannot ensure safe assignment of
- -- variables.
+ when others =>
+ return False;
+ end case;
+ end Is_Scenario;
- if SPARK_Rules_On then
- Process_Conditional_ABE_Variable_Assignment_SPARK
- (Asmt => Asmt,
- Var_Id => Var_Id);
+ ------------------------------
+ -- Is_SPARK_Semantic_Target --
+ ------------------------------
- -- Otherwise the Ada rules are in effect
+ function Is_SPARK_Semantic_Target (Id : Entity_Id) return Boolean is
+ begin
+ return
+ Is_Default_Initial_Condition_Proc (Id)
+ or else Is_Initial_Condition_Proc (Id);
+ end Is_SPARK_Semantic_Target;
- else
- Process_Conditional_ABE_Variable_Assignment_Ada
- (Asmt => Asmt,
- Var_Id => Var_Id);
- end if;
- end Process_Conditional_ABE_Variable_Assignment;
+ ------------------------
+ -- Is_Subprogram_Inst --
+ ------------------------
- -----------------------------------------------------
- -- Process_Conditional_ABE_Variable_Assignment_Ada --
- -----------------------------------------------------
+ function Is_Subprogram_Inst (Id : Entity_Id) return Boolean is
+ begin
+ -- To qualify, the entity must denote a function or a procedure which
+ -- is hidden within an anonymous package, and is a generic instance.
- procedure Process_Conditional_ABE_Variable_Assignment_Ada
- (Asmt : Node_Id;
- Var_Id : Entity_Id)
- is
- Var_Decl : constant Node_Id := Declaration_Node (Var_Id);
- Spec_Id : constant Entity_Id := Find_Top_Unit (Var_Decl);
+ return
+ Ekind_In (Id, E_Function, E_Procedure)
+ and then Is_Hidden (Id)
+ and then Is_Generic_Instance (Id);
+ end Is_Subprogram_Inst;
- begin
- -- Emit a warning when an uninitialized variable declared in a package
- -- spec without a pragma Elaborate_Body is initialized by elaboration
- -- code within the corresponding body.
+ ------------------------------
+ -- Is_Suitable_Access_Taken --
+ ------------------------------
- if Is_Elaboration_Warnings_OK_Id (Var_Id)
- and then not Is_Initialized (Var_Decl)
- and then not Has_Pragma_Elaborate_Body (Spec_Id)
- then
- Error_Msg_NE
- ("??variable & can be accessed by clients before this "
- & "initialization", Asmt, Var_Id);
+ function Is_Suitable_Access_Taken (N : Node_Id) return Boolean is
+ Nam : Name_Id;
+ Pref : Node_Id;
+ Subp_Id : Entity_Id;
- Error_Msg_NE
- ("\add pragma ""Elaborate_Body"" to spec & to ensure proper "
- & "initialization", Asmt, Spec_Id);
+ begin
+ -- Nothing to do when switch -gnatd.U (ignore 'Access) is in effect
- Output_Active_Scenarios (Asmt);
+ if Debug_Flag_Dot_UU then
+ return False;
- -- Generate an implicit Elaborate_Body in the spec
+ -- Nothing to do when the scenario is not an attribute reference
- Set_Elaborate_Body_Desirable (Spec_Id);
- end if;
- end Process_Conditional_ABE_Variable_Assignment_Ada;
+ elsif Nkind (N) /= N_Attribute_Reference then
+ return False;
- -------------------------------------------------------
- -- Process_Conditional_ABE_Variable_Assignment_SPARK --
- -------------------------------------------------------
+ -- Nothing to do for internally-generated attributes because they are
+ -- assumed to be ABE safe.
- procedure Process_Conditional_ABE_Variable_Assignment_SPARK
- (Asmt : Node_Id;
- Var_Id : Entity_Id)
- is
- Var_Decl : constant Node_Id := Declaration_Node (Var_Id);
- Spec_Id : constant Entity_Id := Find_Top_Unit (Var_Decl);
+ elsif not Comes_From_Source (N) then
+ return False;
+ end if;
- begin
- -- Ensure that a suitable elaboration model is in effect for SPARK rule
- -- verification.
+ Nam := Attribute_Name (N);
+ Pref := Prefix (N);
- Check_SPARK_Model_In_Effect (Asmt);
+ -- Sanitize the prefix of the attribute
- -- Emit an error when an initialized variable declared in a package spec
- -- without pragma Elaborate_Body is further modified by elaboration code
- -- within the corresponding body.
+ if not Is_Entity_Name (Pref) then
+ return False;
- if Is_Elaboration_Warnings_OK_Id (Var_Id)
- and then Is_Initialized (Var_Decl)
- and then not Has_Pragma_Elaborate_Body (Spec_Id)
- then
- Error_Msg_NE
- ("variable & modified by elaboration code in package body",
- Asmt, Var_Id);
+ elsif No (Entity (Pref)) then
+ return False;
+ end if;
- Error_Msg_NE
- ("\add pragma ""Elaborate_Body"" to spec & to ensure full "
- & "initialization", Asmt, Spec_Id);
+ Subp_Id := Entity (Pref);
- Output_Active_Scenarios (Asmt);
- end if;
- end Process_Conditional_ABE_Variable_Assignment_SPARK;
+ if not Is_Subprogram_Or_Entry (Subp_Id) then
+ return False;
+ end if;
- ------------------------------------------------
- -- Process_Conditional_ABE_Variable_Reference --
- ------------------------------------------------
+ -- Traverse a possible chain of renamings to obtain the original
+ -- entry or subprogram which the prefix may rename.
- procedure Process_Conditional_ABE_Variable_Reference (Ref : Node_Id) is
- Var_Attrs : Variable_Attributes;
- Var_Id : Entity_Id;
+ Subp_Id := Get_Renamed_Entity (Subp_Id);
- begin
- Extract_Variable_Reference_Attributes
- (Ref => Ref,
- Var_Id => Var_Id,
- Attrs => Var_Attrs);
-
- if Is_Read (Ref) then
- Process_Conditional_ABE_Variable_Reference_Read
- (Ref => Ref,
- Var_Id => Var_Id,
- Attrs => Var_Attrs);
- end if;
- end Process_Conditional_ABE_Variable_Reference;
+ -- To qualify, the attribute must meet the following prerequisites:
- -----------------------------------------------------
- -- Process_Conditional_ABE_Variable_Reference_Read --
- -----------------------------------------------------
+ return
- procedure Process_Conditional_ABE_Variable_Reference_Read
- (Ref : Node_Id;
- Var_Id : Entity_Id;
- Attrs : Variable_Attributes)
- is
- begin
- -- Output relevant information when switch -gnatel (info messages on
- -- implicit Elaborate[_All] pragmas) is in effect.
+ -- The prefix must denote a source entry, operator, or subprogram
+ -- which is not imported.
- if Elab_Info_Messages then
- Elab_Msg_NE
- (Msg => "read of variable & during elaboration",
- N => Ref,
- Id => Var_Id,
- Info_Msg => True,
- In_SPARK => True);
- end if;
+ Comes_From_Source (Subp_Id)
+ and then Is_Subprogram_Or_Entry (Subp_Id)
+ and then not Is_Bodiless_Subprogram (Subp_Id)
- -- Nothing to do when the variable appears within the main unit because
- -- diagnostics on reads are relevant only for external variables.
+ -- The attribute name must be one of the 'Access forms. Note that
+ -- 'Unchecked_Access cannot apply to a subprogram.
- if Is_Same_Unit (Attrs.Unit_Id, Cunit_Entity (Main_Unit)) then
- null;
+ and then Nam_In (Nam, Name_Access, Name_Unrestricted_Access);
+ end Is_Suitable_Access_Taken;
- -- Nothing to do when the variable is already initialized. Note that the
- -- variable may be further modified by the external unit.
+ ----------------------
+ -- Is_Suitable_Call --
+ ----------------------
- elsif Is_Initialized (Declaration_Node (Var_Id)) then
- null;
+ function Is_Suitable_Call (N : Node_Id) return Boolean is
+ begin
+ -- Entry and subprogram calls are intentionally ignored because they
+ -- may undergo expansion depending on the compilation mode, previous
+ -- errors, generic context, etc. Call markers play the role of calls
+ -- and provide a uniform foundation for ABE processing.
- -- Nothing to do when the external unit guarantees the initialization of
- -- the variable by means of pragma Elaborate_Body.
+ return Nkind (N) = N_Call_Marker;
+ end Is_Suitable_Call;
- elsif Has_Pragma_Elaborate_Body (Attrs.Unit_Id) then
- null;
+ -------------------------------
+ -- Is_Suitable_Instantiation --
+ -------------------------------
- -- A variable read imposes an Elaborate requirement on the context of
- -- the main unit. Determine whether the context has a pragma strong
- -- enough to meet the requirement.
+ function Is_Suitable_Instantiation (N : Node_Id) return Boolean is
+ Inst : constant Node_Id := Scenario (N);
- else
- Meet_Elaboration_Requirement
- (N => Ref,
- Target_Id => Var_Id,
- Req_Nam => Name_Elaborate);
- end if;
- end Process_Conditional_ABE_Variable_Reference_Read;
+ begin
+ -- To qualify, the instantiation must come from source
- -----------------------------
- -- Process_Conditional_ABE --
- -----------------------------
+ return
+ Comes_From_Source (Inst)
+ and then Nkind (Inst) in N_Generic_Instantiation;
+ end Is_Suitable_Instantiation;
- -- NOTE: The body of this routine is intentionally out of order because it
- -- invokes an instantiated subprogram (Process_Conditional_ABE_Activation).
- -- Placing the body in alphabetical order will result in a guaranteed ABE.
+ ------------------------------------
+ -- Is_Suitable_SPARK_Derived_Type --
+ ------------------------------------
- procedure Process_Conditional_ABE
- (N : Node_Id;
- State : Processing_Attributes := Initial_State)
- is
- Call_Attrs : Call_Attributes;
- Target_Id : Entity_Id;
+ function Is_Suitable_SPARK_Derived_Type (N : Node_Id) return Boolean is
+ Prag : Node_Id;
+ Typ : Entity_Id;
- begin
- -- Add the current scenario to the stack of active scenarios
+ begin
+ -- To qualify, the type declaration must denote a derived tagged type
+ -- with primitive operations, subject to pragma SPARK_Mode On.
- Push_Active_Scenario (N);
+ if Nkind (N) = N_Full_Type_Declaration
+ and then Nkind (Type_Definition (N)) = N_Derived_Type_Definition
+ then
+ Typ := Defining_Entity (N);
+ Prag := SPARK_Pragma (Typ);
- -- 'Access
+ return
+ Is_Tagged_Type (Typ)
+ and then Has_Primitive_Operations (Typ)
+ and then Present (Prag)
+ and then Get_SPARK_Mode_From_Annotation (Prag) = On;
+ end if;
- if Is_Suitable_Access (N) then
- Process_Conditional_ABE_Access
- (Attr => N,
- State => State);
+ return False;
+ end Is_Suitable_SPARK_Derived_Type;
- -- Activations and calls
+ -------------------------------------
+ -- Is_Suitable_SPARK_Instantiation --
+ -------------------------------------
- elsif Is_Suitable_Call (N) then
+ function Is_Suitable_SPARK_Instantiation (N : Node_Id) return Boolean is
+ Inst : constant Node_Id := Scenario (N);
- -- In general, only calls found within the main unit are processed
- -- because the ALI information supplied to binde is for the main
- -- unit only. However, to preserve the consistency of the tree and
- -- ensure proper serialization of internal names, external calls
- -- also receive corresponding call markers (see Build_Call_Marker).
- -- Regardless of the reason, external calls must not be processed.
+ Gen_Id : Entity_Id;
+ Prag : Node_Id;
- if In_Main_Context (N) then
- Extract_Call_Attributes
- (Call => N,
- Target_Id => Target_Id,
- Attrs => Call_Attrs);
+ begin
+ -- To qualify, both the instantiation and the generic must be subject
+ -- to SPARK_Mode On.
- if Is_Activation_Proc (Target_Id) then
- Process_Conditional_ABE_Activation
- (Call => N,
- Call_Attrs => Call_Attrs,
- State => State);
+ if Is_Suitable_Instantiation (N) then
+ Gen_Id := Instantiated_Generic (Inst);
+ Prag := SPARK_Pragma (Gen_Id);
- else
- Process_Conditional_ABE_Call
- (Call => N,
- Call_Attrs => Call_Attrs,
- Target_Id => Target_Id,
- State => State);
- end if;
+ return
+ Is_SPARK_Mode_On_Node (Inst)
+ and then Present (Prag)
+ and then Get_SPARK_Mode_From_Annotation (Prag) = On;
end if;
- -- Instantiations
+ return False;
+ end Is_Suitable_SPARK_Instantiation;
- elsif Is_Suitable_Instantiation (N) then
- Process_Conditional_ABE_Instantiation
- (Exp_Inst => N,
- State => State);
+ --------------------------------------------
+ -- Is_Suitable_SPARK_Refined_State_Pragma --
+ --------------------------------------------
- -- Variable assignments
+ function Is_Suitable_SPARK_Refined_State_Pragma
+ (N : Node_Id) return Boolean
+ is
+ begin
+ -- To qualfy, the pragma must denote Refined_State
- elsif Is_Suitable_Variable_Assignment (N) then
- Process_Conditional_ABE_Variable_Assignment (N);
+ return
+ Nkind (N) = N_Pragma
+ and then Pragma_Name (N) = Name_Refined_State;
+ end Is_Suitable_SPARK_Refined_State_Pragma;
+
+ -------------------------------------
+ -- Is_Suitable_Variable_Assignment --
+ -------------------------------------
+
+ function Is_Suitable_Variable_Assignment (N : Node_Id) return Boolean is
+ N_Unit : Node_Id;
+ N_Unit_Id : Entity_Id;
+ Nam : Node_Id;
+ Var_Decl : Node_Id;
+ Var_Id : Entity_Id;
+ Var_Unit : Node_Id;
+ Var_Unit_Id : Entity_Id;
- -- Variable references
+ begin
+ -- Nothing to do when the scenario is not an assignment
- elsif Is_Suitable_Variable_Reference (N) then
+ if Nkind (N) /= N_Assignment_Statement then
+ return False;
- -- In general, only variable references found within the main unit
- -- are processed because the ALI information supplied to binde is for
- -- the main unit only. However, to preserve the consistency of the
- -- tree and ensure proper serialization of internal names, external
- -- variable references also receive corresponding variable reference
- -- markers (see Build_Varaible_Reference_Marker). Regardless of the
- -- reason, external variable references must not be processed.
+ -- Nothing to do for internally-generated assignments because they
+ -- are assumed to be ABE safe.
- if In_Main_Context (N) then
- Process_Conditional_ABE_Variable_Reference (N);
- end if;
- end if;
+ elsif not Comes_From_Source (N) then
+ return False;
- -- Remove the current scenario from the stack of active scenarios once
- -- all ABE diagnostics and checks have been performed.
+ -- Assignments are ignored in GNAT mode on the assumption that
+ -- they are ABE-safe. This behaviour parallels that of the old
+ -- ABE mechanism.
- Pop_Active_Scenario (N);
- end Process_Conditional_ABE;
+ elsif GNAT_Mode then
+ return False;
+ end if;
- --------------------------------------------
- -- Process_Guaranteed_ABE_Activation_Impl --
- --------------------------------------------
+ Nam := Assignment_Target (N);
- procedure Process_Guaranteed_ABE_Activation_Impl
- (Call : Node_Id;
- Call_Attrs : Call_Attributes;
- Obj_Id : Entity_Id;
- Task_Attrs : Task_Attributes;
- State : Processing_Attributes)
- is
- pragma Unreferenced (State);
+ -- Sanitize the left hand side of the assignment
- Check_OK : constant Boolean :=
- not Is_Ignored_Ghost_Entity (Obj_Id)
- and then not Task_Attrs.Ghost_Mode_Ignore
- and then Is_Elaboration_Checks_OK_Id (Obj_Id)
- and then Task_Attrs.Elab_Checks_OK;
- -- A run-time ABE check may be installed only when the object and the
- -- task type have active elaboration checks, and both are not ignored
- -- Ghost constructs.
+ if not Is_Entity_Name (Nam) then
+ return False;
- begin
- -- Nothing to do when the root scenario appears at the declaration
- -- level and the task is in the same unit, but outside this context.
- --
- -- task type Task_Typ; -- task declaration
- --
- -- procedure Proc is
- -- function A ... is
- -- begin
- -- if Some_Condition then
- -- declare
- -- T : Task_Typ;
- -- begin
- -- <activation call> -- activation site
- -- end;
- -- ...
- -- end A;
- --
- -- X : ... := A; -- root scenario
- -- ...
- --
- -- task body Task_Typ is
- -- ...
- -- end Task_Typ;
- --
- -- In the example above, the context of X is the declarative list of
- -- Proc. The "elaboration" of X may reach the activation of T whose body
- -- is defined outside of X's context. The task body is relevant only
- -- when Proc is invoked, but this happens only in "normal" elaboration,
- -- therefore the task body must not be considered if this is not the
- -- case.
+ elsif No (Entity (Nam)) then
+ return False;
+ end if;
- -- Performance note: parent traversal
+ Var_Id := Entity (Nam);
- if Is_Up_Level_Target (Task_Attrs.Task_Decl) then
- return;
+ -- Sanitize the variable
- -- Nothing to do when the activation is ABE-safe
- --
- -- generic
- -- package Gen is
- -- task type Task_Typ;
- -- end Gen;
- --
- -- package body Gen is
- -- task body Task_Typ is
- -- begin
- -- ...
- -- end Task_Typ;
- -- end Gen;
- --
- -- with Gen;
- -- procedure Main is
- -- package Nested is
- -- package Inst is new Gen;
- -- T : Inst.Task_Typ;
- -- end Nested; -- safe activation
- -- ...
-
- elsif Is_Safe_Activation (Call, Task_Attrs.Task_Decl) then
- return;
+ if Var_Id = Any_Id then
+ return False;
- -- An activation call leads to a guaranteed ABE when the activation
- -- call and the task appear within the same context ignoring library
- -- levels, and the body of the task has not been seen yet or appears
- -- after the activation call.
- --
- -- procedure Guaranteed_ABE is
- -- task type Task_Typ;
- --
- -- package Nested is
- -- T : Task_Typ;
- -- <activation call> -- guaranteed ABE
- -- end Nested;
- --
- -- task body Task_Typ is
- -- ...
- -- end Task_Typ;
- -- ...
+ elsif Ekind (Var_Id) /= E_Variable then
+ return False;
+ end if;
- -- Performance note: parent traversal
+ Var_Decl := Declaration_Node (Var_Id);
- elsif Is_Guaranteed_ABE
- (N => Call,
- Target_Decl => Task_Attrs.Task_Decl,
- Target_Body => Task_Attrs.Body_Decl)
- then
- if Call_Attrs.Elab_Warnings_OK then
- Error_Msg_Sloc := Sloc (Call);
- Error_Msg_N
- ("??task & will be activated # before elaboration of its body",
- Obj_Id);
- Error_Msg_N ("\Program_Error will be raised at run time", Obj_Id);
+ if Nkind (Var_Decl) /= N_Object_Declaration then
+ return False;
end if;
- -- Mark the activation call as a guaranteed ABE
+ N_Unit_Id := Find_Top_Unit (N);
+ N_Unit := Unit_Declaration_Node (N_Unit_Id);
- Set_Is_Known_Guaranteed_ABE (Call);
+ Var_Unit_Id := Find_Top_Unit (Var_Decl);
+ Var_Unit := Unit_Declaration_Node (Var_Unit_Id);
- -- Install a run-time ABE failue because this activation call will
- -- always result in an ABE.
+ -- To qualify, the assignment must meet the following prerequisites:
- if Check_OK then
- Install_ABE_Failure
- (N => Call,
- Ins_Nod => Call);
- end if;
- end if;
- end Process_Guaranteed_ABE_Activation_Impl;
+ return
+ Comes_From_Source (Var_Id)
- procedure Process_Guaranteed_ABE_Activation is
- new Process_Activation_Generic (Process_Guaranteed_ABE_Activation_Impl);
+ -- The variable must be declared in the spec of compilation unit
+ -- U.
- ---------------------------------
- -- Process_Guaranteed_ABE_Call --
- ---------------------------------
+ and then Nkind (Var_Unit) = N_Package_Declaration
+ and then Find_Enclosing_Level (Var_Decl) = Library_Spec_Level
- procedure Process_Guaranteed_ABE_Call
- (Call : Node_Id;
- Call_Attrs : Call_Attributes;
- Target_Id : Entity_Id)
- is
- Target_Attrs : Target_Attributes;
+ -- The assignment must occur in the body of compilation unit U
- begin
- Extract_Target_Attributes
- (Target_Id => Target_Id,
- Attrs => Target_Attrs);
+ and then Nkind (N_Unit) = N_Package_Body
+ and then Present (Corresponding_Body (Var_Unit))
+ and then Corresponding_Body (Var_Unit) = N_Unit_Id;
+ end Is_Suitable_Variable_Assignment;
- -- Nothing to do when the root scenario appears at the declaration level
- -- and the target is in the same unit, but outside this context.
- --
- -- function B ...; -- target declaration
- --
- -- procedure Proc is
- -- function A ... is
- -- begin
- -- if Some_Condition then
- -- return B; -- call site
- -- ...
- -- end A;
- --
- -- X : ... := A; -- root scenario
- -- ...
- --
- -- function B ... is
- -- ...
- -- end B;
- --
- -- In the example above, the context of X is the declarative region of
- -- Proc. The "elaboration" of X may eventually reach B which is defined
- -- outside of X's context. B is relevant only when Proc is invoked, but
- -- this happens only by means of "normal" elaboration, therefore B must
- -- not be considered if this is not the case.
+ ------------------------------------
+ -- Is_Suitable_Variable_Reference --
+ ------------------------------------
- -- Performance note: parent traversal
+ function Is_Suitable_Variable_Reference (N : Node_Id) return Boolean is
+ begin
+ -- Expanded names and identifiers are intentionally ignored because
+ -- they be folded, optimized away, etc. Variable references markers
+ -- play the role of variable references and provide a uniform
+ -- foundation for ABE processing.
- if Is_Up_Level_Target (Target_Attrs.Spec_Decl) then
- return;
+ return Nkind (N) = N_Variable_Reference_Marker;
+ end Is_Suitable_Variable_Reference;
- -- Nothing to do when the call is ABE-safe
- --
- -- generic
- -- function Gen ...;
- --
- -- function Gen ... is
- -- begin
- -- ...
- -- end Gen;
- --
- -- with Gen;
- -- procedure Main is
- -- function Inst is new Gen;
- -- X : ... := Inst; -- safe call
- -- ...
+ -------------------
+ -- Is_Task_Entry --
+ -------------------
- elsif Is_Safe_Call (Call, Target_Attrs) then
- return;
+ function Is_Task_Entry (Id : Entity_Id) return Boolean is
+ begin
+ -- To qualify, the entity must denote an entry defined in a task type
- -- A call leads to a guaranteed ABE when the call and the target appear
- -- within the same context ignoring library levels, and the body of the
- -- target has not been seen yet or appears after the call.
- --
- -- procedure Guaranteed_ABE is
- -- function Func ...;
- --
- -- package Nested is
- -- Obj : ... := Func; -- guaranteed ABE
- -- end Nested;
- --
- -- function Func ... is
- -- ...
- -- end Func;
- -- ...
+ return
+ Is_Entry (Id) and then Is_Task_Type (Non_Private_View (Scope (Id)));
+ end Is_Task_Entry;
- -- Performance note: parent traversal
+ ------------------------
+ -- Is_Up_Level_Target --
+ ------------------------
- elsif Is_Guaranteed_ABE
- (N => Call,
- Target_Decl => Target_Attrs.Spec_Decl,
- Target_Body => Target_Attrs.Body_Decl)
- then
- if Call_Attrs.Elab_Warnings_OK then
- Error_Msg_NE ("??cannot call & before body seen", Call, Target_Id);
- Error_Msg_N ("\Program_Error will be raised at run time", Call);
- end if;
+ function Is_Up_Level_Target
+ (Targ_Decl : Node_Id;
+ In_State : Processing_In_State) return Boolean
+ is
+ Root : constant Node_Id := Root_Scenario;
+ Root_Rep : constant Scenario_Rep_Id :=
+ Scenario_Representation_Of (Root, In_State);
- -- Mark the call as a guarnateed ABE
+ begin
+ -- The root appears within the declaratons of a block statement,
+ -- entry body, subprogram body, or task body ignoring enclosing
+ -- packages. The root is always within the main unit.
- Set_Is_Known_Guaranteed_ABE (Call);
+ if not In_State.Suppress_Up_Level_Targets
+ and then Level (Root_Rep) = Declaration_Level
+ then
+ -- The target is within the main unit. It acts as an up-level
+ -- target when it appears within a context which encloses the
+ -- root.
+ --
+ -- package body Main_Unit is
+ -- function Func ...; -- target
+ --
+ -- procedure Proc is
+ -- X : ... := Func; -- root scenario
- -- Install a run-time ABE failure because the call will always result
- -- in an ABE. The failure is installed when both the call and target
- -- have enabled elaboration checks, and both are not ignored Ghost
- -- constructs.
+ if In_Extended_Main_Code_Unit (Targ_Decl) then
+ return not In_Same_Context (Root, Targ_Decl, Nested_OK => True);
- if Call_Attrs.Elab_Checks_OK
- and then Target_Attrs.Elab_Checks_OK
- and then not Call_Attrs.Ghost_Mode_Ignore
- and then not Target_Attrs.Ghost_Mode_Ignore
- then
- Install_ABE_Failure
- (N => Call,
- Ins_Nod => Call);
+ -- Otherwise the target is external to the main unit which makes
+ -- it an up-level target.
+
+ else
+ return True;
+ end if;
end if;
- end if;
- end Process_Guaranteed_ABE_Call;
- ------------------------------------------
- -- Process_Guaranteed_ABE_Instantiation --
- ------------------------------------------
+ return False;
+ end Is_Up_Level_Target;
+ end Semantics;
- procedure Process_Guaranteed_ABE_Instantiation (Exp_Inst : Node_Id) is
- Gen_Attrs : Target_Attributes;
- Gen_Id : Entity_Id;
- Inst : Node_Id;
- Inst_Attrs : Instantiation_Attributes;
- Inst_Id : Entity_Id;
+ ---------------------
+ -- SPARK_Processor --
+ ---------------------
- begin
- Extract_Instantiation_Attributes
- (Exp_Inst => Exp_Inst,
- Inst => Inst,
- Inst_Id => Inst_Id,
- Gen_Id => Gen_Id,
- Attrs => Inst_Attrs);
+ package body SPARK_Processor is
- Extract_Target_Attributes (Gen_Id, Gen_Attrs);
+ -----------------------
+ -- Local subprograms --
+ -----------------------
- -- Nothing to do when the root scenario appears at the declaration level
- -- and the generic is in the same unit, but outside this context.
- --
- -- generic
- -- procedure Gen is ...; -- generic declaration
- --
- -- procedure Proc is
- -- function A ... is
- -- begin
- -- if Some_Condition then
- -- declare
- -- procedure I is new Gen; -- instantiation site
- -- ...
- -- ...
- -- end A;
- --
- -- X : ... := A; -- root scenario
- -- ...
- --
- -- procedure Gen is
- -- ...
- -- end Gen;
- --
- -- In the example above, the context of X is the declarative region of
- -- Proc. The "elaboration" of X may eventually reach Gen which appears
- -- outside of X's context. Gen is relevant only when Proc is invoked,
- -- but this happens only by means of "normal" elaboration, therefore
- -- Gen must not be considered if this is not the case.
+ procedure Process_SPARK_Derived_Type
+ (Typ_Decl : Node_Id;
+ Typ_Rep : Scenario_Rep_Id;
+ In_State : Processing_In_State);
+ pragma Inline (Process_SPARK_Derived_Type);
+ -- Verify that the freeze node of a derived type denoted by declaration
+ -- Typ_Decl is within the early call region of each overriding primitive
+ -- body that belongs to the derived type (SPARK RM 7.7(8)). Typ_Rep is
+ -- the representation of the type. In_State denotes the current state of
+ -- the Processing phase.
+
+ procedure Process_SPARK_Instantiation
+ (Inst : Node_Id;
+ Inst_Rep : Scenario_Rep_Id;
+ In_State : Processing_In_State);
+ pragma Inline (Process_SPARK_Instantiation);
+ -- Verify that instanciation Inst does not precede the generic body it
+ -- instantiates (SPARK RM 7.7(6)). Inst_Rep is the representation of the
+ -- instantiation. In_State is the current state of the Processing phase.
+
+ procedure Process_SPARK_Refined_State_Pragma
+ (Prag : Node_Id;
+ Prag_Rep : Scenario_Rep_Id;
+ In_State : Processing_In_State);
+ pragma Inline (Process_SPARK_Refined_State_Pragma);
+ -- Verify that each constituent of Refined_State pragma Prag which
+ -- belongs to abstract state mentioned in pragma Initializes has prior
+ -- elaboration with respect to the main unit (SPARK RM 7.7.1(7)).
+ -- Prag_Rep is the representation of the pragma. In_State denotes the
+ -- current state of the Processing phase.
+
+ procedure Process_SPARK_Scenario
+ (N : Node_Id;
+ In_State : Processing_In_State);
+ pragma Inline (Process_SPARK_Scenario);
+ -- Top-level dispatcher for verifying SPARK scenarios which are not
+ -- always executable during elaboration but still need elaboration-
+ -- related checks. In_State is the current state of the Processing
+ -- phase.
+
+ ---------------------------------
+ -- Check_SPARK_Model_In_Effect --
+ ---------------------------------
+
+ SPARK_Model_Warning_Posted : Boolean := False;
+ -- This flag prevents the same SPARK model-related warning from being
+ -- emitted multiple times.
+
+ procedure Check_SPARK_Model_In_Effect is
+ Spec_Id : constant Entity_Id :=
+ Unique_Entity (Cunit_Entity (Main_Unit));
- -- Performance note: parent traversal
+ begin
+ -- Do not emit the warning multiple times as this creates useless
+ -- noise.
- if Is_Up_Level_Target (Gen_Attrs.Spec_Decl) then
- return;
+ if SPARK_Model_Warning_Posted then
+ null;
- -- Nothing to do when the instantiation is ABE-safe
- --
- -- generic
- -- package Gen is
- -- ...
- -- end Gen;
- --
- -- package body Gen is
- -- ...
- -- end Gen;
- --
- -- with Gen;
- -- procedure Main is
- -- package Inst is new Gen (ABE); -- safe instantiation
- -- ...
+ -- SPARK rule verification requires the "strict" static model
- elsif Is_Safe_Instantiation (Inst, Gen_Attrs) then
- return;
+ elsif Static_Elaboration_Checks
+ and not Relaxed_Elaboration_Checks
+ then
+ null;
- -- An instantiation leads to a guaranteed ABE when the instantiation and
- -- the generic appear within the same context ignoring library levels,
- -- and the body of the generic has not been seen yet or appears after
- -- the instantiation.
- --
- -- procedure Guaranteed_ABE is
- -- generic
- -- procedure Gen;
- --
- -- package Nested is
- -- procedure Inst is new Gen; -- guaranteed ABE
- -- end Nested;
- --
- -- procedure Gen is
- -- ...
- -- end Gen;
- -- ...
+ -- Any other combination of models does not guarantee the absence of
+ -- ABE problems for SPARK rule verification purposes. Note that there
+ -- is no need to check for the presence of the legacy ABE mechanism
+ -- because the legacy code has its own dedicated processing for SPARK
+ -- rules.
- -- Performance note: parent traversal
+ else
+ SPARK_Model_Warning_Posted := True;
- elsif Is_Guaranteed_ABE
- (N => Inst,
- Target_Decl => Gen_Attrs.Spec_Decl,
- Target_Body => Gen_Attrs.Body_Decl)
- then
- if Inst_Attrs.Elab_Warnings_OK then
- Error_Msg_NE
- ("??cannot instantiate & before body seen", Inst, Gen_Id);
- Error_Msg_N ("\Program_Error will be raised at run time", Inst);
+ Error_Msg_N
+ ("??SPARK elaboration checks require static elaboration model",
+ Spec_Id);
+
+ if Dynamic_Elaboration_Checks then
+ Error_Msg_N
+ ("\dynamic elaboration model is in effect", Spec_Id);
+
+ else
+ pragma Assert (Relaxed_Elaboration_Checks);
+ Error_Msg_N
+ ("\relaxed elaboration model is in effect", Spec_Id);
+ end if;
end if;
+ end Check_SPARK_Model_In_Effect;
- -- Mark the instantiation as a guarantee ABE. This automatically
- -- suppresses the instantiation of the generic body.
+ ---------------------------
+ -- Check_SPARK_Scenarios --
+ ---------------------------
- Set_Is_Known_Guaranteed_ABE (Inst);
+ procedure Check_SPARK_Scenarios is
+ Iter : NE_Set.Iterator;
+ N : Node_Id;
- -- Install a run-time ABE failure because the instantiation will
- -- always result in an ABE. The failure is installed when both the
- -- instance and the generic have enabled elaboration checks, and both
- -- are not ignored Ghost constructs.
+ begin
+ Iter := Iterate_SPARK_Scenarios;
+ while NE_Set.Has_Next (Iter) loop
+ NE_Set.Next (Iter, N);
- if Inst_Attrs.Elab_Checks_OK
- and then Gen_Attrs.Elab_Checks_OK
- and then not Inst_Attrs.Ghost_Mode_Ignore
- and then not Gen_Attrs.Ghost_Mode_Ignore
- then
- Install_ABE_Failure
- (N => Inst,
- Ins_Nod => Exp_Inst);
- end if;
- end if;
- end Process_Guaranteed_ABE_Instantiation;
+ Process_SPARK_Scenario
+ (N => N,
+ In_State => SPARK_State);
+ end loop;
+ end Check_SPARK_Scenarios;
- ----------------------------
- -- Process_Guaranteed_ABE --
- ----------------------------
+ --------------------------------
+ -- Process_SPARK_Derived_Type --
+ --------------------------------
- -- NOTE: The body of this routine is intentionally out of order because it
- -- invokes an instantiated subprogram (Process_Guaranteed_ABE_Activation).
- -- Placing the body in alphabetical order will result in a guaranteed ABE.
+ procedure Process_SPARK_Derived_Type
+ (Typ_Decl : Node_Id;
+ Typ_Rep : Scenario_Rep_Id;
+ In_State : Processing_In_State)
+ is
+ pragma Unreferenced (In_State);
+
+ Typ : constant Entity_Id := Target (Typ_Rep);
+
+ Stop_Check : exception;
+ -- This exception is raised when the freeze node violates the
+ -- placement rules.
+
+ procedure Check_Overriding_Primitive
+ (Prim : Entity_Id;
+ FNode : Node_Id);
+ pragma Inline (Check_Overriding_Primitive);
+ -- Verify that freeze node FNode is within the early call region of
+ -- overriding primitive Prim's body.
+
+ function Freeze_Node_Location (FNode : Node_Id) return Source_Ptr;
+ pragma Inline (Freeze_Node_Location);
+ -- Return a more accurate source location associated with freeze node
+ -- FNode.
+
+ function Precedes_Source_Construct (N : Node_Id) return Boolean;
+ pragma Inline (Precedes_Source_Construct);
+ -- Determine whether arbitrary node N appears prior to some source
+ -- construct.
+
+ procedure Suggest_Elaborate_Body
+ (N : Node_Id;
+ Body_Decl : Node_Id;
+ Error_Nod : Node_Id);
+ pragma Inline (Suggest_Elaborate_Body);
+ -- Suggest the use of pragma Elaborate_Body when the pragma will
+ -- allow for node N to appear within the early call region of
+ -- subprogram body Body_Decl. The suggestion is attached to
+ -- Error_Nod as a continuation error.
+
+ --------------------------------
+ -- Check_Overriding_Primitive --
+ --------------------------------
+
+ procedure Check_Overriding_Primitive
+ (Prim : Entity_Id;
+ FNode : Node_Id)
+ is
+ Prim_Decl : constant Node_Id := Unit_Declaration_Node (Prim);
+ Body_Decl : Node_Id;
+ Body_Id : Entity_Id;
+ Region : Node_Id;
- procedure Process_Guaranteed_ABE (N : Node_Id) is
- Call_Attrs : Call_Attributes;
- Target_Id : Entity_Id;
+ begin
+ -- Nothing to do for predefined primitives because they are
+ -- artifacts of tagged type expansion and cannot override source
+ -- primitives.
- begin
- -- Add the current scenario to the stack of active scenarios
+ if Is_Predefined_Dispatching_Operation (Prim) then
+ return;
+ end if;
- Push_Active_Scenario (N);
+ Body_Id := Corresponding_Body (Prim_Decl);
- -- Only calls, instantiations, and task activations may result in a
- -- guaranteed ABE.
+ -- Nothing to do when the primitive does not have a corresponding
+ -- body. This can happen when the unit with the bodies is not the
+ -- main unit subjected to ABE checks.
- if Is_Suitable_Call (N) then
- Extract_Call_Attributes
- (Call => N,
- Target_Id => Target_Id,
- Attrs => Call_Attrs);
+ if No (Body_Id) then
+ return;
- if Is_Activation_Proc (Target_Id) then
- Process_Guaranteed_ABE_Activation
- (Call => N,
- Call_Attrs => Call_Attrs,
- State => Initial_State);
+ -- The primitive overrides a parent or progenitor primitive
- else
- Process_Guaranteed_ABE_Call
- (Call => N,
- Call_Attrs => Call_Attrs,
- Target_Id => Target_Id);
- end if;
+ elsif Present (Overridden_Operation (Prim)) then
- elsif Is_Suitable_Instantiation (N) then
- Process_Guaranteed_ABE_Instantiation (N);
- end if;
+ -- Nothing to do when overriding an interface primitive happens
+ -- by inheriting a non-interface primitive as the check would
+ -- be done on the parent primitive.
- -- Remove the current scenario from the stack of active scenarios once
- -- all ABE diagnostics and checks have been performed.
+ if Present (Alias (Prim)) then
+ return;
+ end if;
- Pop_Active_Scenario (N);
- end Process_Guaranteed_ABE;
+ -- Nothing to do when the primitive is not overriding. The body of
+ -- such a primitive cannot be targeted by a dispatching call which
+ -- is executable during elaboration, and cannot cause an ABE.
- --------------------------
- -- Push_Active_Scenario --
- --------------------------
+ else
+ return;
+ end if;
- procedure Push_Active_Scenario (N : Node_Id) is
- begin
- Scenario_Stack.Append (N);
- end Push_Active_Scenario;
+ Body_Decl := Unit_Declaration_Node (Body_Id);
+ Region := Find_Early_Call_Region (Body_Decl);
- ---------------------------------
- -- Record_Elaboration_Scenario --
- ---------------------------------
+ -- The freeze node appears prior to the early call region of the
+ -- primitive body.
- procedure Record_Elaboration_Scenario (N : Node_Id) is
- Level : Enclosing_Level_Kind;
+ -- IMPORTANT: This check must always be performed even when
+ -- -gnatd.v (enforce SPARK elaboration rules in SPARK code) is not
+ -- specified because the static model cannot guarantee the absence
+ -- of ABEs in the presence of dispatching calls.
- Any_Level_OK : Boolean;
- -- This flag is set when a particular scenario is allowed to appear at
- -- any level.
+ if Earlier_In_Extended_Unit (FNode, Region) then
+ Error_Msg_Node_2 := Prim;
+ Error_Msg_NE
+ ("first freezing point of type & must appear within early "
+ & "call region of primitive body & (SPARK RM 7.7(8))",
+ Typ_Decl, Typ);
- Declaration_Level_OK : Boolean;
- -- This flag is set when a particular scenario is allowed to appear at
- -- the declaration level.
+ Error_Msg_Sloc := Sloc (Region);
+ Error_Msg_N ("\region starts #", Typ_Decl);
- Library_Level_OK : Boolean;
- -- This flag is set when a particular scenario is allowed to appear at
- -- the library level.
+ Error_Msg_Sloc := Sloc (Body_Decl);
+ Error_Msg_N ("\region ends #", Typ_Decl);
- begin
- -- Assume that the scenario cannot appear on any level
+ Error_Msg_Sloc := Freeze_Node_Location (FNode);
+ Error_Msg_N ("\first freezing point #", Typ_Decl);
- Any_Level_OK := False;
- Declaration_Level_OK := False;
- Library_Level_OK := False;
+ -- If applicable, suggest the use of pragma Elaborate_Body in
+ -- the associated package spec.
- -- Nothing to do when switch -gnatH (legacy elaboration checking mode
- -- enabled) is in effect because the legacy ABE mechanism does not need
- -- to carry out this action.
+ Suggest_Elaborate_Body
+ (N => FNode,
+ Body_Decl => Body_Decl,
+ Error_Nod => Typ_Decl);
- if Legacy_Elaboration_Checks then
- return;
+ raise Stop_Check;
+ end if;
+ end Check_Overriding_Primitive;
- -- Nothing to do for ASIS because ABE checks and diagnostics are not
- -- performed in this mode.
+ --------------------------
+ -- Freeze_Node_Location --
+ --------------------------
- elsif ASIS_Mode then
- return;
+ function Freeze_Node_Location (FNode : Node_Id) return Source_Ptr is
+ Context : constant Node_Id := Parent (FNode);
+ Loc : constant Source_Ptr := Sloc (FNode);
- -- Nothing to do when the scenario is being preanalyzed
+ Prv_Decls : List_Id;
+ Vis_Decls : List_Id;
- elsif Preanalysis_Active then
- return;
- end if;
+ begin
+ -- In general, the source location of the freeze node is as close
+ -- as possible to the real freeze point, except when the freeze
+ -- node is at the "bottom" of a package spec.
- -- Ensure that a library-level call does not appear in a preelaborated
- -- unit. The check must come before ignoring scenarios within external
- -- units or inside generics because calls in those context must also be
- -- verified.
+ if Nkind (Context) = N_Package_Specification then
+ Prv_Decls := Private_Declarations (Context);
+ Vis_Decls := Visible_Declarations (Context);
- if Is_Suitable_Call (N) then
- Check_Preelaborated_Call (N);
- end if;
+ -- The freeze node appears in the private declarations of the
+ -- package.
- -- Nothing to do when the scenario does not appear within the main unit
+ if Present (Prv_Decls)
+ and then List_Containing (FNode) = Prv_Decls
+ then
+ null;
- if not In_Main_Context (N) then
- return;
+ -- The freeze node appears in the visible declarations of the
+ -- package and there are no private declarations.
- -- Scenarios within a generic unit are never considered because generics
- -- cannot be elaborated.
+ elsif Present (Vis_Decls)
+ and then List_Containing (FNode) = Vis_Decls
+ and then (No (Prv_Decls) or else Is_Empty_List (Prv_Decls))
+ then
+ null;
- elsif Inside_A_Generic then
- return;
+ -- Otherwise the freeze node is not in the "last" declarative
+ -- list of the package. Use the existing source location of the
+ -- freeze node.
- -- Scenarios which do not fall in one of the elaboration categories
- -- listed below are not considered. The categories are:
+ else
+ return Loc;
+ end if;
- -- 'Access for entries, operators, and subprograms
- -- Assignments to variables
- -- Calls (includes task activation)
- -- Derived types
- -- Instantiations
- -- Pragma Refined_State
- -- Reads of variables
+ -- The freeze node appears at the "bottom" of the package when
+ -- it is in the "last" declarative list and is either the last
+ -- in the list or is followed by internal constructs only. In
+ -- that case the more appropriate source location is that of
+ -- the package end label.
- elsif Is_Suitable_Access (N) then
- Library_Level_OK := True;
+ if not Precedes_Source_Construct (FNode) then
+ return Sloc (End_Label (Context));
+ end if;
+ end if;
- -- Signal any enclosing local exception handlers that the 'Access may
- -- raise Program_Error due to a failed ABE check when switch -gnatd.o
- -- (conservative elaboration order for indirect calls) is in effect.
- -- Marking the exception handlers ensures proper expansion by both
- -- the front and back end restriction when No_Exception_Propagation
- -- is in effect.
+ return Loc;
+ end Freeze_Node_Location;
- if Debug_Flag_Dot_O then
- Possible_Local_Raise (N, Standard_Program_Error);
- end if;
+ -------------------------------
+ -- Precedes_Source_Construct --
+ -------------------------------
- elsif Is_Suitable_Call (N) or else Is_Suitable_Instantiation (N) then
- Declaration_Level_OK := True;
- Library_Level_OK := True;
+ function Precedes_Source_Construct (N : Node_Id) return Boolean is
+ Decl : Node_Id;
- -- Signal any enclosing local exception handlers that the call or
- -- instantiation may raise Program_Error due to a failed ABE check.
- -- Marking the exception handlers ensures proper expansion by both
- -- the front and back end restriction when No_Exception_Propagation
- -- is in effect.
+ begin
+ Decl := Next (N);
+ while Present (Decl) loop
+ if Comes_From_Source (Decl) then
+ return True;
- Possible_Local_Raise (N, Standard_Program_Error);
+ -- A generated body for a source expression function is treated
+ -- as a source construct.
- elsif Is_Suitable_SPARK_Derived_Type (N) then
- Any_Level_OK := True;
+ elsif Nkind (Decl) = N_Subprogram_Body
+ and then Was_Expression_Function (Decl)
+ and then Comes_From_Source (Original_Node (Decl))
+ then
+ return True;
+ end if;
- elsif Is_Suitable_SPARK_Refined_State_Pragma (N) then
- Library_Level_OK := True;
+ Next (Decl);
+ end loop;
- elsif Is_Suitable_Variable_Assignment (N)
- or else Is_Suitable_Variable_Reference (N)
- then
- Library_Level_OK := True;
+ return False;
+ end Precedes_Source_Construct;
- -- Otherwise the input does not denote a suitable scenario
+ ----------------------------
+ -- Suggest_Elaborate_Body --
+ ----------------------------
- else
- return;
- end if;
+ procedure Suggest_Elaborate_Body
+ (N : Node_Id;
+ Body_Decl : Node_Id;
+ Error_Nod : Node_Id)
+ is
+ Unit_Id : constant Node_Id := Unit (Cunit (Main_Unit));
+ Region : Node_Id;
- -- The static model imposes additional restrictions on the placement of
- -- scenarios. In contrast, the dynamic model assumes that every scenario
- -- will be elaborated or invoked at some point.
+ begin
+ -- The suggestion applies only when the subprogram body resides in
+ -- a compilation package body, and a pragma Elaborate_Body would
+ -- allow for the node to appear in the early call region of the
+ -- subprogram body. This implies that all code from the subprogram
+ -- body up to the node is preelaborable.
- if Static_Elaboration_Checks then
+ if Nkind (Unit_Id) = N_Package_Body then
- -- Certain scenarios are allowed to appear at any level. This check
- -- is performed here in order to save on a parent traversal.
+ -- Find the start of the early call region again assuming that
+ -- the package spec has pragma Elaborate_Body. Note that the
+ -- internal data structures are intentionally not updated
+ -- because this is a speculative search.
- if Any_Level_OK then
- null;
+ Region :=
+ Find_Early_Call_Region
+ (Body_Decl => Body_Decl,
+ Assume_Elab_Body => True,
+ Skip_Memoization => True);
- -- Otherwise the scenario must appear at a specific level
+ -- If the node appears within the early call region, assuming
+ -- that the package spec carries pragma Elaborate_Body, then it
+ -- is safe to suggest the pragma.
- else
- -- Performance note: parent traversal
+ if Earlier_In_Extended_Unit (Region, N) then
+ Error_Msg_Name_1 := Name_Elaborate_Body;
+ Error_Msg_NE
+ ("\consider adding pragma % in spec of unit &",
+ Error_Nod, Defining_Entity (Unit_Id));
+ end if;
+ end if;
+ end Suggest_Elaborate_Body;
- Level := Find_Enclosing_Level (N);
+ -- Local variables
- -- Declaration-level scenario
+ FNode : constant Node_Id := Freeze_Node (Typ);
+ Prims : constant Elist_Id := Direct_Primitive_Operations (Typ);
- if Declaration_Level_OK and then Level = Declaration_Level then
- null;
+ Prim_Elmt : Elmt_Id;
- -- Library-level or instantiation scenario
+ -- Start of processing for Process_SPARK_Derived_Type
- elsif Library_Level_OK
- and then Level in Library_Or_Instantiation_Level
- then
- null;
+ begin
+ -- A type should have its freeze node set by the time SPARK scenarios
+ -- are being verified.
- -- Otherwise the scenario does not appear at the proper level and
- -- cannot possibly act as a top-level scenario.
+ pragma Assert (Present (FNode));
- else
- return;
- end if;
+ -- Verify that the freeze node of the derived type is within the
+ -- early call region of each overriding primitive body
+ -- (SPARK RM 7.7(8)).
+
+ if Present (Prims) then
+ Prim_Elmt := First_Elmt (Prims);
+ while Present (Prim_Elmt) loop
+ Check_Overriding_Primitive
+ (Prim => Node (Prim_Elmt),
+ FNode => FNode);
+
+ Next_Elmt (Prim_Elmt);
+ end loop;
end if;
- end if;
- -- Derived types subject to SPARK_Mode On require elaboration-related
- -- checks even though the type may not be declared within elaboration
- -- code. The types are recorded in a separate table which is examined
- -- during the Processing phase. Note that the checks must be delayed
- -- because the bodies of overriding primitives are not available yet.
+ exception
+ when Stop_Check =>
+ null;
+ end Process_SPARK_Derived_Type;
- if Is_Suitable_SPARK_Derived_Type (N) then
- Record_SPARK_Elaboration_Scenario (N);
+ ---------------------------------
+ -- Process_SPARK_Instantiation --
+ ---------------------------------
- -- Nothing left to do for derived types
+ procedure Process_SPARK_Instantiation
+ (Inst : Node_Id;
+ Inst_Rep : Scenario_Rep_Id;
+ In_State : Processing_In_State)
+ is
+ Gen_Id : constant Entity_Id := Target (Inst_Rep);
+ Gen_Rep : constant Target_Rep_Id :=
+ Target_Representation_Of (Gen_Id, In_State);
+ Body_Decl : constant Node_Id := Body_Declaration (Gen_Rep);
- return;
+ begin
+ -- The instantiation and the generic body are both in the main unit
- -- Instantiations of generics both subject to SPARK_Mode On require
- -- elaboration-related checks even though the instantiations may not
- -- appear within elaboration code. The instantiations are recored in
- -- a separate table which is examined during the Procesing phase. Note
- -- that the checks must be delayed because it is not known yet whether
- -- the generic unit has a body or not.
+ if Present (Body_Decl)
+ and then In_Extended_Main_Code_Unit (Body_Decl)
- -- IMPORTANT: A SPARK instantiation is also a normal instantiation which
- -- is subject to common conditional and guaranteed ABE checks.
+ -- If the instantiation appears prior to the generic body, then the
+ -- instantiation is illegal (SPARK RM 7.7(6)).
- elsif Is_Suitable_SPARK_Instantiation (N) then
- Record_SPARK_Elaboration_Scenario (N);
+ -- IMPORTANT: This check must always be performed even when
+ -- -gnatd.v (enforce SPARK elaboration rules in SPARK code) is not
+ -- specified because the rule prevents use-before-declaration of
+ -- objects that may precede the generic body.
- -- External constituents that refine abstract states which appear in
- -- pragma Initializes require elaboration-related checks even though
- -- a Refined_State pragma lacks any elaboration semantic.
+ and then Earlier_In_Extended_Unit (Inst, Body_Decl)
+ then
+ Error_Msg_NE
+ ("cannot instantiate & before body seen", Inst, Gen_Id);
+ end if;
+ end Process_SPARK_Instantiation;
- elsif Is_Suitable_SPARK_Refined_State_Pragma (N) then
- Record_SPARK_Elaboration_Scenario (N);
+ ----------------------------
+ -- Process_SPARK_Scenario --
+ ----------------------------
- -- Nothing left to do for pragma Refined_State
+ procedure Process_SPARK_Scenario
+ (N : Node_Id;
+ In_State : Processing_In_State)
+ is
+ Scen : constant Node_Id := Scenario (N);
- return;
- end if;
+ begin
+ -- Ensure that a suitable elaboration model is in effect for SPARK
+ -- rule verification.
- -- Perform early detection of guaranteed ABEs in order to suppress the
- -- instantiation of generic bodies as gigi cannot handle certain types
- -- of premature instantiations.
+ Check_SPARK_Model_In_Effect;
- Process_Guaranteed_ABE (N);
+ -- Add the current scenario to the stack of active scenarios
- -- At this point all checks have been performed. Record the scenario for
- -- later processing by the ABE phase.
+ Push_Active_Scenario (Scen);
- Top_Level_Scenarios.Append (N);
- Set_Is_Recorded_Top_Level_Scenario (N);
- end Record_Elaboration_Scenario;
+ -- Derived type
- ---------------------------------------
- -- Record_SPARK_Elaboration_Scenario --
- ---------------------------------------
+ if Is_Suitable_SPARK_Derived_Type (Scen) then
+ Process_SPARK_Derived_Type
+ (Typ_Decl => Scen,
+ Typ_Rep => Scenario_Representation_Of (Scen, In_State),
+ In_State => In_State);
- procedure Record_SPARK_Elaboration_Scenario (N : Node_Id) is
- begin
- SPARK_Scenarios.Append (N);
- Set_Is_Recorded_SPARK_Scenario (N);
- end Record_SPARK_Elaboration_Scenario;
+ -- Instantiation
- -----------------------------------
- -- Recorded_SPARK_Scenarios_Hash --
- -----------------------------------
+ elsif Is_Suitable_SPARK_Instantiation (Scen) then
+ Process_SPARK_Instantiation
+ (Inst => Scen,
+ Inst_Rep => Scenario_Representation_Of (Scen, In_State),
+ In_State => In_State);
- function Recorded_SPARK_Scenarios_Hash
- (Key : Node_Id) return Recorded_SPARK_Scenarios_Index
- is
- begin
- return
- Recorded_SPARK_Scenarios_Index (Key mod Recorded_SPARK_Scenarios_Max);
- end Recorded_SPARK_Scenarios_Hash;
+ -- Refined_State pragma
- ---------------------------------------
- -- Recorded_Top_Level_Scenarios_Hash --
- ---------------------------------------
+ elsif Is_Suitable_SPARK_Refined_State_Pragma (Scen) then
+ Process_SPARK_Refined_State_Pragma
+ (Prag => Scen,
+ Prag_Rep => Scenario_Representation_Of (Scen, In_State),
+ In_State => In_State);
+ end if;
- function Recorded_Top_Level_Scenarios_Hash
- (Key : Node_Id) return Recorded_Top_Level_Scenarios_Index
- is
- begin
- return
- Recorded_Top_Level_Scenarios_Index
- (Key mod Recorded_Top_Level_Scenarios_Max);
- end Recorded_Top_Level_Scenarios_Hash;
+ -- Remove the current scenario from the stack of active scenarios
+ -- once all ABE diagnostics and checks have been performed.
- --------------------------
- -- Reset_Visited_Bodies --
- --------------------------
+ Pop_Active_Scenario (Scen);
+ end Process_SPARK_Scenario;
- procedure Reset_Visited_Bodies is
- begin
- if Visited_Bodies_In_Use then
- Visited_Bodies_In_Use := False;
- Visited_Bodies.Reset;
- end if;
- end Reset_Visited_Bodies;
+ ----------------------------------------
+ -- Process_SPARK_Refined_State_Pragma --
+ ----------------------------------------
- -------------------
- -- Root_Scenario --
- -------------------
+ procedure Process_SPARK_Refined_State_Pragma
+ (Prag : Node_Id;
+ Prag_Rep : Scenario_Rep_Id;
+ In_State : Processing_In_State)
+ is
+ pragma Unreferenced (Prag_Rep);
- function Root_Scenario return Node_Id is
- package Stack renames Scenario_Stack;
+ procedure Check_SPARK_Constituent (Constit_Id : Entity_Id);
+ pragma Inline (Check_SPARK_Constituent);
+ -- Ensure that a single constituent Constit_Id is elaborated prior to
+ -- the main unit.
- begin
- -- Ensure that the scenario stack has at least one active scenario in
- -- it. The one at the bottom (index First) is the root scenario.
+ procedure Check_SPARK_Constituents (Constits : Elist_Id);
+ pragma Inline (Check_SPARK_Constituents);
+ -- Ensure that all constituents found in list Constits are elaborated
+ -- prior to the main unit.
- pragma Assert (Stack.Last >= Stack.First);
- return Stack.Table (Stack.First);
- end Root_Scenario;
+ procedure Check_SPARK_Initialized_State (State : Node_Id);
+ pragma Inline (Check_SPARK_Initialized_State);
+ -- Ensure that the constituents of single abstract state State are
+ -- elaborated prior to the main unit.
- ---------------------------
- -- Set_Early_Call_Region --
- ---------------------------
+ procedure Check_SPARK_Initialized_States (Pack_Id : Entity_Id);
+ pragma Inline (Check_SPARK_Initialized_States);
+ -- Ensure that the constituents of all abstract states which appear
+ -- in the Initializes pragma of package Pack_Id are elaborated prior
+ -- to the main unit.
- procedure Set_Early_Call_Region (Body_Id : Entity_Id; Start : Node_Id) is
- begin
- pragma Assert (Ekind_In (Body_Id, E_Entry,
- E_Entry_Family,
- E_Function,
- E_Procedure,
- E_Subprogram_Body));
+ -----------------------------
+ -- Check_SPARK_Constituent --
+ -----------------------------
- Early_Call_Regions_In_Use := True;
- Early_Call_Regions.Set (Body_Id, Start);
- end Set_Early_Call_Region;
+ procedure Check_SPARK_Constituent (Constit_Id : Entity_Id) is
+ SM_Prag : Node_Id;
- ----------------------------
- -- Set_Elaboration_Status --
- ----------------------------
+ begin
+ -- Nothing to do for "null" constituents
- procedure Set_Elaboration_Status
- (Unit_Id : Entity_Id;
- Val : Elaboration_Attributes)
- is
- begin
- Elaboration_Statuses_In_Use := True;
- Elaboration_Statuses.Set (Unit_Id, Val);
- end Set_Elaboration_Status;
+ if Nkind (Constit_Id) = N_Null then
+ return;
- ------------------------------------
- -- Set_Is_Recorded_SPARK_Scenario --
- ------------------------------------
+ -- Nothing to do for illegal constituents
- procedure Set_Is_Recorded_SPARK_Scenario
- (N : Node_Id;
- Val : Boolean := True)
- is
- begin
- Recorded_SPARK_Scenarios_In_Use := True;
- Recorded_SPARK_Scenarios.Set (N, Val);
- end Set_Is_Recorded_SPARK_Scenario;
+ elsif Error_Posted (Constit_Id) then
+ return;
+ end if;
- ----------------------------------------
- -- Set_Is_Recorded_Top_Level_Scenario --
- ----------------------------------------
+ SM_Prag := SPARK_Pragma (Constit_Id);
- procedure Set_Is_Recorded_Top_Level_Scenario
- (N : Node_Id;
- Val : Boolean := True)
- is
- begin
- Recorded_Top_Level_Scenarios_In_Use := True;
- Recorded_Top_Level_Scenarios.Set (N, Val);
- end Set_Is_Recorded_Top_Level_Scenario;
+ -- The check applies only when the constituent is subject to
+ -- pragma SPARK_Mode On.
- -------------------------
- -- Set_Is_Visited_Body --
- -------------------------
+ if Present (SM_Prag)
+ and then Get_SPARK_Mode_From_Annotation (SM_Prag) = On
+ then
+ -- An external constituent of an abstract state which appears
+ -- in the Initializes pragma of a package spec imposes an
+ -- Elaborate requirement on the context of the main unit.
+ -- Determine whether the context has a pragma strong enough to
+ -- meet the requirement.
+
+ -- IMPORTANT: This check is performed only when -gnatd.v
+ -- (enforce SPARK elaboration rules in SPARK code) is in effect
+ -- because the static model can ensure the prior elaboration of
+ -- the unit which contains a constituent by installing implicit
+ -- Elaborate pragma.
+
+ if Debug_Flag_Dot_V then
+ Meet_Elaboration_Requirement
+ (N => Prag,
+ Targ_Id => Constit_Id,
+ Req_Nam => Name_Elaborate,
+ In_State => In_State);
+
+ -- Otherwise ensure that the unit with the external constituent
+ -- is elaborated prior to the main unit.
- procedure Set_Is_Visited_Body (Subp_Body : Node_Id) is
- begin
- Visited_Bodies_In_Use := True;
- Visited_Bodies.Set (Subp_Body, True);
- end Set_Is_Visited_Body;
+ else
+ Ensure_Prior_Elaboration
+ (N => Prag,
+ Unit_Id => Find_Top_Unit (Constit_Id),
+ Prag_Nam => Name_Elaborate,
+ In_State => In_State);
+ end if;
+ end if;
+ end Check_SPARK_Constituent;
- -------------------------------
- -- Static_Elaboration_Checks --
- -------------------------------
+ ------------------------------
+ -- Check_SPARK_Constituents --
+ ------------------------------
- function Static_Elaboration_Checks return Boolean is
- begin
- return not Dynamic_Elaboration_Checks;
- end Static_Elaboration_Checks;
+ procedure Check_SPARK_Constituents (Constits : Elist_Id) is
+ Constit_Elmt : Elmt_Id;
- -------------------
- -- Traverse_Body --
- -------------------
+ begin
+ if Present (Constits) then
+ Constit_Elmt := First_Elmt (Constits);
+ while Present (Constit_Elmt) loop
+ Check_SPARK_Constituent (Node (Constit_Elmt));
+ Next_Elmt (Constit_Elmt);
+ end loop;
+ end if;
+ end Check_SPARK_Constituents;
- procedure Traverse_Body (N : Node_Id; State : Processing_Attributes) is
- procedure Find_And_Process_Nested_Scenarios;
- pragma Inline (Find_And_Process_Nested_Scenarios);
- -- Examine the declarations and statements of subprogram body N for
- -- suitable scenarios.
+ -----------------------------------
+ -- Check_SPARK_Initialized_State --
+ -----------------------------------
- ---------------------------------------
- -- Find_And_Process_Nested_Scenarios --
- ---------------------------------------
+ procedure Check_SPARK_Initialized_State (State : Node_Id) is
+ SM_Prag : Node_Id;
+ State_Id : Entity_Id;
- procedure Find_And_Process_Nested_Scenarios is
- function Is_Potential_Scenario
- (Nod : Node_Id) return Traverse_Result;
- -- Determine whether arbitrary node Nod denotes a suitable scenario.
- -- If it does, save it in the Nested_Scenarios list of the subprogram
- -- body, and process it.
+ begin
+ -- Nothing to do for "null" initialization items
- procedure Traverse_List (List : List_Id);
- pragma Inline (Traverse_List);
- -- Invoke Traverse_Potential_Scenarios on each node in list List
+ if Nkind (State) = N_Null then
+ return;
- procedure Traverse_Potential_Scenarios is
- new Traverse_Proc (Is_Potential_Scenario);
+ -- Nothing to do for illegal states
- ---------------------------
- -- Is_Potential_Scenario --
- ---------------------------
+ elsif Error_Posted (State) then
+ return;
+ end if;
- function Is_Potential_Scenario
- (Nod : Node_Id) return Traverse_Result
- is
- begin
- -- Special cases
+ State_Id := Entity_Of (State);
- -- Skip constructs which do not have elaboration of their own and
- -- need to be elaborated by other means such as invocation, task
- -- activation, etc.
+ -- Sanitize the state
- if Is_Non_Library_Level_Encapsulator (Nod) then
- return Skip;
+ if No (State_Id) then
+ return;
- -- Terminate the traversal of a task body when encountering an
- -- accept or select statement, and
- --
- -- * Entry calls during elaboration are not allowed. In this
- -- case the accept or select statement will cause the task
- -- to block at elaboration time because there are no entry
- -- calls to unblock it.
- --
- -- or
- --
- -- * Switch -gnatd_a (stop elaboration checks on accept or
- -- select statement) is in effect.
+ elsif Error_Posted (State_Id) then
+ return;
- elsif (Debug_Flag_Underscore_A
- or else Restriction_Active
- (No_Entry_Calls_In_Elaboration_Code))
- and then Nkind_In (Original_Node (Nod), N_Accept_Statement,
- N_Selective_Accept)
- then
- return Abandon;
+ elsif Ekind (State_Id) /= E_Abstract_State then
+ return;
+ end if;
- -- Terminate the traversal of a task body when encountering a
- -- suspension call, and
- --
- -- * Entry calls during elaboration are not allowed. In this
- -- case the suspension call emulates an entry call and will
- -- cause the task to block at elaboration time.
- --
- -- or
- --
- -- * Switch -gnatd_s (stop elaboration checks on synchronous
- -- suspension) is in effect.
- --
- -- Note that the guard should not be checking the state of flag
- -- Within_Task_Body because only suspension calls which appear
- -- immediately within the statements of the task are supported.
- -- Flag Within_Task_Body carries over to deeper levels of the
- -- traversal.
+ -- The check is performed only when the abstract state is subject
+ -- to SPARK_Mode On.
- elsif (Debug_Flag_Underscore_S
- or else Restriction_Active
- (No_Entry_Calls_In_Elaboration_Code))
- and then Is_Synchronous_Suspension_Call (Nod)
- and then In_Task_Body (Nod)
+ SM_Prag := SPARK_Pragma (State_Id);
+
+ if Present (SM_Prag)
+ and then Get_SPARK_Mode_From_Annotation (SM_Prag) = On
then
- return Abandon;
+ Check_SPARK_Constituents (Refinement_Constituents (State_Id));
+ end if;
+ end Check_SPARK_Initialized_State;
- -- Certain nodes carry semantic lists which act as repositories
- -- until expansion transforms the node and relocates the contents.
- -- Examine these lists in case expansion is disabled.
+ ------------------------------------
+ -- Check_SPARK_Initialized_States --
+ ------------------------------------
- elsif Nkind_In (Nod, N_And_Then, N_Or_Else) then
- Traverse_List (Actions (Nod));
+ procedure Check_SPARK_Initialized_States (Pack_Id : Entity_Id) is
+ Init_Prag : constant Node_Id :=
+ Get_Pragma (Pack_Id, Pragma_Initializes);
- elsif Nkind_In (Nod, N_Elsif_Part, N_Iteration_Scheme) then
- Traverse_List (Condition_Actions (Nod));
+ Init : Node_Id;
+ Inits : Node_Id;
- elsif Nkind (Nod) = N_If_Expression then
- Traverse_List (Then_Actions (Nod));
- Traverse_List (Else_Actions (Nod));
+ begin
+ if Present (Init_Prag) then
+ Inits := Expression (Get_Argument (Init_Prag, Pack_Id));
- elsif Nkind_In (Nod, N_Component_Association,
- N_Iterated_Component_Association)
- then
- Traverse_List (Loop_Actions (Nod));
+ -- Avoid processing a "null" initialization list. The only
+ -- other alternative is an aggregate.
- -- General case
+ if Nkind (Inits) = N_Aggregate then
- elsif Is_Suitable_Scenario (Nod) then
- Process_Conditional_ABE
- (N => Nod,
- State => State);
- end if;
+ -- The initialization items appear in list form:
+ --
+ -- (state1, state2)
- return OK;
- end Is_Potential_Scenario;
+ if Present (Expressions (Inits)) then
+ Init := First (Expressions (Inits));
+ while Present (Init) loop
+ Check_SPARK_Initialized_State (Init);
+ Next (Init);
+ end loop;
+ end if;
- -------------------
- -- Traverse_List --
- -------------------
+ -- The initialization items appear in associated form:
+ --
+ -- (state1 => item1,
+ -- state2 => (item2, item3))
+
+ if Present (Component_Associations (Inits)) then
+ Init := First (Component_Associations (Inits));
+ while Present (Init) loop
+ Check_SPARK_Initialized_State (Init);
+ Next (Init);
+ end loop;
+ end if;
+ end if;
+ end if;
+ end Check_SPARK_Initialized_States;
- procedure Traverse_List (List : List_Id) is
- Item : Node_Id;
+ -- Local variables
- begin
- Item := First (List);
- while Present (Item) loop
- Traverse_Potential_Scenarios (Item);
- Next (Item);
- end loop;
- end Traverse_List;
+ Pack_Body : constant Node_Id := Find_Related_Package_Or_Body (Prag);
- -- Start of processing for Find_And_Process_Nested_Scenarios
+ -- Start of processing for Process_SPARK_Refined_State_Pragma
begin
- -- Examine the declarations for suitable scenarios
+ -- Pragma Refined_State must be associated with a package body
- Traverse_List (Declarations (N));
+ pragma Assert
+ (Present (Pack_Body) and then Nkind (Pack_Body) = N_Package_Body);
- -- Examine the handled sequence of statements. This also includes any
- -- exceptions handlers.
+ -- Verify that each external contitunent of an abstract state
+ -- mentioned in pragma Initializes is properly elaborated.
- Traverse_Potential_Scenarios (Handled_Statement_Sequence (N));
- end Find_And_Process_Nested_Scenarios;
+ Check_SPARK_Initialized_States (Unique_Defining_Entity (Pack_Body));
+ end Process_SPARK_Refined_State_Pragma;
+ end SPARK_Processor;
- -- Start of processing for Traverse_Body
+ -------------------------------
+ -- Spec_And_Body_From_Entity --
+ -------------------------------
+ procedure Spec_And_Body_From_Entity
+ (Id : Node_Id;
+ Spec_Decl : out Node_Id;
+ Body_Decl : out Node_Id)
+ is
begin
- -- Nothing to do when there is no body
+ Spec_And_Body_From_Node
+ (N => Unit_Declaration_Node (Id),
+ Spec_Decl => Spec_Decl,
+ Body_Decl => Body_Decl);
+ end Spec_And_Body_From_Entity;
- if No (N) then
- return;
+ -----------------------------
+ -- Spec_And_Body_From_Node --
+ -----------------------------
- elsif Nkind (N) /= N_Subprogram_Body then
- return;
- end if;
+ procedure Spec_And_Body_From_Node
+ (N : Node_Id;
+ Spec_Decl : out Node_Id;
+ Body_Decl : out Node_Id)
+ is
+ Body_Id : Entity_Id;
+ Spec_Id : Entity_Id;
- -- Nothing to do if the body was already traversed during the processing
- -- of the same top-level scenario.
+ begin
+ -- Assume that the construct lacks spec and body
- if Is_Visited_Body (N) then
- return;
+ Body_Decl := Empty;
+ Spec_Decl := Empty;
- -- Otherwise mark the body as traversed
+ -- Bodies
- else
- Set_Is_Visited_Body (N);
+ if Nkind_In (N, N_Package_Body,
+ N_Protected_Body,
+ N_Subprogram_Body,
+ N_Task_Body)
+ then
+ Spec_Id := Corresponding_Spec (N);
+
+ -- The body completes a previous declaration
+
+ if Present (Spec_Id) then
+ Spec_Decl := Unit_Declaration_Node (Spec_Id);
+
+ -- Otherwise the body acts as the initial declaration, and is both a
+ -- spec and body. There is no need to look for an optional body.
+
+ else
+ Body_Decl := N;
+ Spec_Decl := N;
+ return;
+ end if;
+
+ -- Declarations
+
+ elsif Nkind_In (N, N_Entry_Declaration,
+ N_Generic_Package_Declaration,
+ N_Generic_Subprogram_Declaration,
+ N_Package_Declaration,
+ N_Protected_Type_Declaration,
+ N_Subprogram_Declaration,
+ N_Task_Type_Declaration)
+ then
+ Spec_Decl := N;
+
+ -- Expression function
+
+ elsif Nkind (N) = N_Expression_Function then
+ Spec_Id := Corresponding_Spec (N);
+ pragma Assert (Present (Spec_Id));
+
+ Spec_Decl := Unit_Declaration_Node (Spec_Id);
+
+ -- Instantiations
+
+ elsif Nkind (N) in N_Generic_Instantiation then
+ Spec_Decl := Instance_Spec (N);
+ pragma Assert (Present (Spec_Decl));
+
+ -- Stubs
+
+ elsif Nkind (N) in N_Body_Stub then
+ Spec_Id := Corresponding_Spec_Of_Stub (N);
+
+ -- The stub completes a previous declaration
+
+ if Present (Spec_Id) then
+ Spec_Decl := Unit_Declaration_Node (Spec_Id);
+
+ -- Otherwise the stub acts as a spec
+
+ else
+ Spec_Decl := N;
+ end if;
end if;
- -- Examine the declarations and statements of the subprogram body for
- -- suitable scenarios, save and process them accordingly.
+ -- Obtain an optional or mandatory body
+
+ if Present (Spec_Decl) then
+ Body_Id := Corresponding_Body (Spec_Decl);
- Find_And_Process_Nested_Scenarios;
- end Traverse_Body;
+ if Present (Body_Id) then
+ Body_Decl := Unit_Declaration_Node (Body_Id);
+ end if;
+ end if;
+ end Spec_And_Body_From_Node;
+
+ -------------------------------
+ -- Static_Elaboration_Checks --
+ -------------------------------
+
+ function Static_Elaboration_Checks return Boolean is
+ begin
+ return not Dynamic_Elaboration_Checks;
+ end Static_Elaboration_Checks;
-----------------
-- Unit_Entity --
@@ -11256,82 +15699,6 @@ package body Sem_Elab is
---------------------------------
procedure Update_Elaboration_Scenario (New_N : Node_Id; Old_N : Node_Id) is
- procedure Update_SPARK_Scenario;
- pragma Inline (Update_SPARK_Scenario);
- -- Update the contents of table SPARK_Scenarios if Old_N is recorded
- -- there.
-
- procedure Update_Top_Level_Scenario;
- pragma Inline (Update_Top_Level_Scenario);
- -- Update the contexts of table Top_Level_Scenarios if Old_N is recorded
- -- there.
-
- ---------------------------
- -- Update_SPARK_Scenario --
- ---------------------------
-
- procedure Update_SPARK_Scenario is
- package Scenarios renames SPARK_Scenarios;
-
- begin
- if Is_Recorded_SPARK_Scenario (Old_N) then
-
- -- Performance note: list traversal
-
- for Index in Scenarios.First .. Scenarios.Last loop
- if Scenarios.Table (Index) = Old_N then
- Scenarios.Table (Index) := New_N;
-
- -- The old SPARK scenario is no longer recorded, but the new
- -- one is.
-
- Set_Is_Recorded_Top_Level_Scenario (Old_N, False);
- Set_Is_Recorded_Top_Level_Scenario (New_N);
- return;
- end if;
- end loop;
-
- -- A recorded SPARK scenario must be in the table of recorded
- -- SPARK scenarios.
-
- pragma Assert (False);
- end if;
- end Update_SPARK_Scenario;
-
- -------------------------------
- -- Update_Top_Level_Scenario --
- -------------------------------
-
- procedure Update_Top_Level_Scenario is
- package Scenarios renames Top_Level_Scenarios;
-
- begin
- if Is_Recorded_Top_Level_Scenario (Old_N) then
-
- -- Performance note: list traversal
-
- for Index in Scenarios.First .. Scenarios.Last loop
- if Scenarios.Table (Index) = Old_N then
- Scenarios.Table (Index) := New_N;
-
- -- The old top-level scenario is no longer recorded, but the
- -- new one is.
-
- Set_Is_Recorded_Top_Level_Scenario (Old_N, False);
- Set_Is_Recorded_Top_Level_Scenario (New_N);
- return;
- end if;
- end loop;
-
- -- A recorded top-level scenario must be in the table of recorded
- -- top-level scenarios.
-
- pragma Assert (False);
- end if;
- end Update_Top_Level_Scenario;
-
- -- Start of processing for Update_Elaboration_Requirement
-
begin
-- Nothing to do when the old and new scenarios are one and the same
@@ -11344,20 +15711,10 @@ package body Sem_Elab is
-- is inserted at the proper place in the tree.
elsif Is_Scenario (Old_N) then
- Update_SPARK_Scenario;
- Update_Top_Level_Scenario;
+ Replace_Scenario (Old_N, New_N);
end if;
end Update_Elaboration_Scenario;
- -------------------------
- -- Visited_Bodies_Hash --
- -------------------------
-
- function Visited_Bodies_Hash (Key : Node_Id) return Visited_Bodies_Index is
- begin
- return Visited_Bodies_Index (Key mod Visited_Bodies_Max);
- end Visited_Bodies_Hash;
-
---------------------------------------------------------------------------
-- --
-- L E G A C Y A C C E S S B E F O R E E L A B O R A T I O N --
diff --git a/gcc/ada/sem_elab.ads b/gcc/ada/sem_elab.ads
index 5d47957..f47d525 100644
--- a/gcc/ada/sem_elab.ads
+++ b/gcc/ada/sem_elab.ads
@@ -30,25 +30,9 @@ with Types; use Types;
package Sem_Elab is
- procedure Build_Call_Marker (N : Node_Id);
- -- Create a call marker for call or requeue statement N and record it for
- -- later processing by the ABE mechanism.
-
- procedure Build_Variable_Reference_Marker
- (N : Node_Id;
- Read : Boolean;
- Write : Boolean);
- -- Create a variable reference marker for arbitrary node N if it mentions a
- -- variable, and record it for later processing by the ABE mechanism. Flag
- -- Read should be set when the reference denotes a read. Flag Write should
- -- be set when the reference denotes a write.
-
- procedure Check_Elaboration_Scenarios;
- -- Examine each scenario recorded during analysis/resolution and apply the
- -- Ada or SPARK elaboration rules taking into account the model in effect.
- -- This processing detects and diagnoses ABE issues, installs conditional
- -- ABE checks or guaranteed ABE failures, and ensures the elaboration of
- -- units.
+ -----------
+ -- Types --
+ -----------
-- The following type classifies the various enclosing levels used in ABE
-- diagnostics.
@@ -64,9 +48,9 @@ package Sem_Elab is
-- package Nested is -- enclosing package ignored
-- X ... -- at declaration level
- Generic_Package_Spec,
- Generic_Package_Body,
- -- A construct is at the "generic library level" when it appears in a
+ Generic_Spec_Level,
+ Generic_Body_Level,
+ -- A construct is at the "generic level" when it appears in a
-- generic package library unit, ignoring enclosing packages. Example:
-- generic
@@ -74,14 +58,14 @@ package Sem_Elab is
-- package Nested is -- enclosing package ignored
-- X ... -- at generic library level
- Instantiation,
+ Instantiation_Level,
-- A construct is at the "instantiation library level" when it appears
-- in a library unit which is also an instantiation. Example:
-- package Inst is new Gen; -- at instantiation level
- Package_Spec,
- Package_Body,
+ Library_Spec_Level,
+ Library_Body_Level,
-- A construct is at the "library level" when it appears in a package
-- library unit, ignoring enclosing packages. Example:
@@ -93,26 +77,46 @@ package Sem_Elab is
-- This value is used to indicate that none of the levels above are in
-- effect.
- subtype Any_Library_Level is Enclosing_Level_Kind range
- Generic_Package_Spec ..
- Package_Body;
-
- subtype Generic_Library_Level is Enclosing_Level_Kind range
- Generic_Package_Spec ..
- Generic_Package_Body;
+ subtype Generic_Level is Enclosing_Level_Kind range
+ Generic_Spec_Level ..
+ Generic_Body_Level;
subtype Library_Level is Enclosing_Level_Kind range
- Package_Spec ..
- Package_Body;
+ Library_Spec_Level ..
+ Library_Body_Level;
subtype Library_Or_Instantiation_Level is Enclosing_Level_Kind range
- Instantiation ..
- Package_Body;
+ Instantiation_Level ..
+ Library_Body_Level;
+
+ procedure Build_Call_Marker (N : Node_Id);
+ pragma Inline (Build_Call_Marker);
+ -- Create a call marker for call or requeue statement N and record it for
+ -- later processing by the ABE mechanism.
+
+ procedure Build_Variable_Reference_Marker
+ (N : Node_Id;
+ Read : Boolean;
+ Write : Boolean);
+ pragma Inline (Build_Variable_Reference_Marker);
+ -- Create a variable reference marker for arbitrary node N if it mentions a
+ -- variable, and record it for later processing by the ABE mechanism. Flag
+ -- Read should be set when the reference denotes a read. Flag Write should
+ -- be set when the reference denotes a write.
+
+ procedure Check_Elaboration_Scenarios;
+ -- Examine each scenario recorded during analysis/resolution and apply the
+ -- Ada or SPARK elaboration rules taking into account the model in effect.
+ -- This processing detects and diagnoses ABE issues, installs conditional
+ -- ABE checks or guaranteed ABE failures, and ensures the elaboration of
+ -- units.
function Find_Enclosing_Level (N : Node_Id) return Enclosing_Level_Kind;
+ pragma Inline (Find_Enclosing_Level);
-- Determine the enclosing level of arbitrary node N
procedure Initialize;
+ pragma Inline (Initialize);
-- Initialize the internal structures of this unit
procedure Kill_Elaboration_Scenario (N : Node_Id);
@@ -121,9 +125,10 @@ package Sem_Elab is
-- dead code.
procedure Record_Elaboration_Scenario (N : Node_Id);
+ pragma Inline (Record_Elaboration_Scenario);
-- Determine whether atribtray node N denotes a scenario which requires
- -- ABE diagnostics or runtime checks. If this is the case, store N into
- -- a table for later processing.
+ -- ABE diagnostics or runtime checks. If this is the case, store N for
+ -- later processing.
---------------------------------------------------------------------------
-- --
diff --git a/gcc/ada/sem_prag.adb b/gcc/ada/sem_prag.adb
index 520650b..b499dbd 100644
--- a/gcc/ada/sem_prag.adb
+++ b/gcc/ada/sem_prag.adb
@@ -9861,6 +9861,17 @@ package body Sem_Prag is
-- Start of processing for Process_Inline
begin
+ -- An inlined subprogram may grant access to its private enclosing
+ -- context depending on the placement of its body. From elaboration
+ -- point of view, the flow of execution may enter this private
+ -- context, and then reach an external unit, thus producing a
+ -- dependency on that external unit. For such a path to be properly
+ -- discovered and encoded in the ALI file of the main unit, let the
+ -- ABE mechanism process the body of the main unit, and encode all
+ -- relevant invocation constructs and the relations between them.
+
+ Mark_Save_Invocation_Graph_Of_Body;
+
Check_No_Identifiers;
Check_At_Least_N_Arguments (1);
@@ -12219,7 +12230,7 @@ package body Sem_Prag is
Check_Ghost_Synchronous;
-- Option Part_Of without an encapsulating state is
- -- illegal (SPARK RM 7.1.4(9)).
+ -- illegal (SPARK RM 7.1.4(8)).
elsif Chars (Opt) = Name_Part_Of then
SPARK_Msg_N
@@ -19349,20 +19360,25 @@ package body Sem_Prag is
-----------------------
-- pragma Machine_Attribute (
- -- [Entity =>] LOCAL_NAME,
- -- [Attribute_Name =>] static_string_EXPRESSION
- -- [, [Info =>] static_EXPRESSION] );
+ -- [Entity =>] LOCAL_NAME,
+ -- [Attribute_Name =>] static_string_EXPRESSION
+ -- [, [Info =>] static_EXPRESSION {, static_EXPRESSION}] );
when Pragma_Machine_Attribute => Machine_Attribute : declare
+ Arg : Node_Id;
Def_Id : Entity_Id;
begin
GNAT_Pragma;
Check_Arg_Order ((Name_Entity, Name_Attribute_Name, Name_Info));
- if Arg_Count = 3 then
+ if Arg_Count >= 3 then
Check_Optional_Identifier (Arg3, Name_Info);
- Check_Arg_Is_OK_Static_Expression (Arg3);
+ Arg := Arg3;
+ while Present (Arg) loop
+ Check_Arg_Is_OK_Static_Expression (Arg);
+ Arg := Next (Arg);
+ end loop;
else
Check_Arg_Count (2);
end if;
@@ -25603,6 +25619,12 @@ package body Sem_Prag is
Ent := Underlying_Type (Ent);
end if;
+ -- The pragma applies to entities with addresses
+
+ if Is_Type (Ent) then
+ Error_Pragma ("pragma applies to objects and subprograms");
+ end if;
+
-- The only processing required is to link this item on to the
-- list of rep items for the given entity. This is accomplished
-- by the call to Rep_Item_Too_Late (when no error is detected
diff --git a/gcc/ada/sem_spark.adb b/gcc/ada/sem_spark.adb
index cfa6df8..b4e816e 100644
--- a/gcc/ada/sem_spark.adb
+++ b/gcc/ada/sem_spark.adb
@@ -42,9 +42,9 @@ with GNAT.Dynamic_HTables; use GNAT.Dynamic_HTables;
package body Sem_SPARK is
- -------------------------------------------------
- -- Handling of Permissions Associated to Paths --
- -------------------------------------------------
+ ---------------------------------------------------
+ -- Handling of Permissions Associated with Paths --
+ ---------------------------------------------------
package Permissions is
Elaboration_Context_Max : constant := 1009;
@@ -52,16 +52,44 @@ package body Sem_SPARK is
type Elaboration_Context_Index is range 0 .. Elaboration_Context_Max - 1;
- function Elaboration_Context_Hash (Key : Entity_Id)
- return Elaboration_Context_Index;
- -- Function to hash any node of the AST
+ function Elaboration_Context_Hash
+ (Key : Entity_Id) return Elaboration_Context_Index;
+ -- The hash function
+
+ -- Permission type associated with paths. These are related to but not
+ -- the same as the states associated with names used in SPARK RM 3.10:
+ -- Unrestricted, Observed, Borrowed, Moved. When ownership rules lead to
+ -- a state change for a name, this may correspond to multiple permission
+ -- changes for the paths corresponding to the name, its prefixes, and
+ -- its extensions. For example, when an object is assigned to, the
+ -- corresponding name gets into state Moved, while the path for the name
+ -- gets permission Write_Only as well as every prefix of the name, and
+ -- every suffix gets permission No_Access.
+
+ type Perm_Kind_Option is
+ (None,
+ -- Special value used when no permission is passed around
+
+ No_Access,
+ -- The path cannot be accessed for reading or writing. This is the
+ -- case for the path of a name in the Borrowed state.
+
+ Read_Only,
+ -- The path can only be accessed for reading. This is the case for
+ -- the path of a name in the Observed state.
+
+ Read_Write,
+ -- The path can be accessed for both reading and writing. This is the
+ -- case for the path of a name in the Unrestricted state.
+
+ Write_Only
+ -- The path can only be accessed for writing. This is the case for
+ -- the path of a name in the Moved state.
+ );
- type Perm_Kind is (Borrowed, Observed, Unrestricted, Moved);
- -- Permission type associated with paths. The Moved permission is
- -- equivalent to the Unrestricted one (same permissions). The Moved is
- -- however used to mark the RHS after a move (which still unrestricted).
- -- This way, we may generate warnings when manipulating the RHS
- -- afterwads since it is set to Null after the assignment.
+ subtype Perm_Kind is Perm_Kind_Option range No_Access .. Write_Only;
+ subtype Read_Perm is Perm_Kind range Read_Only .. Read_Write;
+ subtype Write_Perm is Perm_Kind range Read_Write .. Write_Only;
type Perm_Tree_Wrapper;
@@ -83,34 +111,39 @@ package body Sem_SPARK is
package Perm_Tree_Maps is new Simple_HTable
(Header_Num => Elaboration_Context_Index,
- Key => Node_Id,
+ Key => Entity_Id,
Element => Perm_Tree_Access,
No_Element => null,
Hash => Elaboration_Context_Hash,
Equal => "=");
- -- The instantation of a hash table, with keys being nodes and values
- -- being pointers to trees. This is used to reference easily all
- -- extensions of a Record_Component node (that can have name x, y, ...).
+ -- The instantation of a hash table, with keys being entities and values
+ -- being pointers to permission trees. This is used to define global
+ -- environment permissions (entities in that case are stand-alone
+ -- objects or formal parameters), as well as the permissions for the
+ -- extensions of a Record_Component node (entities in that case are
+ -- record components).
-- The definition of permission trees. This is a tree, which has a
- -- permission at each node, and depending on the type of the node,
- -- can have zero, one, or more children pointed to by an access to tree.
+ -- permission at each node, and depending on the type of the node, can
+ -- have zero, one, or more children reached through an access to tree.
type Perm_Tree (Kind : Path_Kind := Entire_Object) is record
Permission : Perm_Kind;
-- Permission at this level in the path
Is_Node_Deep : Boolean;
- -- Whether this node is of a deep type, to be used when moving the
- -- path.
+ -- Whether this node is of a "deep" type, i.e. an access type or a
+ -- composite type containing access type subcomponents. This
+ -- corresponds to both "observing" and "owning" types in SPARK RM
+ -- 3.10. To be used when moving the path.
case Kind is
-- An entire object is either a leaf (an object which cannot be
-- extended further in a path) or a subtree in folded form (which
-- could later be unfolded further in another kind of node). The
-- field Children_Permission specifies a permission for every
- -- extension of that node if that permission is different from
- -- the node's permission.
+ -- extension of that node if that permission is different from the
+ -- node's permission.
when Entire_Object =>
Children_Permission : Perm_Kind;
@@ -121,20 +154,17 @@ package body Sem_SPARK is
when Reference =>
Get_All : Perm_Tree_Access;
- -- Unfolded path of array type. The permission of the elements is
+ -- Unfolded path of array type. The permission of elements is
-- given in Get_Elem.
when Array_Component =>
Get_Elem : Perm_Tree_Access;
- -- Unfolded path of record type. The permission of the regular
- -- components is given in Component. The permission of unknown
- -- components (for objects of tagged type) is given in
- -- Other_Components.
+ -- Unfolded path of record type. The permission of the components
+ -- is given in Component.
when Record_Component =>
Component : Perm_Tree_Maps.Instance;
- Other_Components : Perm_Tree_Access;
end case;
end record;
@@ -144,9 +174,8 @@ package body Sem_SPARK is
-- We use this wrapper in order to have unconstrained discriminants
type Perm_Env is new Perm_Tree_Maps.Instance;
- -- The definition of a permission environment for the analysis. This
- -- is just a hash table of permission trees, each of them rooted with
- -- an Identifier/Expanded_Name.
+ -- The definition of a permission environment for the analysis. This is
+ -- just a hash table from entities to permission trees.
type Perm_Env_Access is access Perm_Env;
-- Access to permission environments
@@ -166,20 +195,17 @@ package body Sem_SPARK is
-- The type defining the hash table saving the environments at the entry
-- of each loop.
- package Boolean_Variables_Maps is new Simple_HTable
+ package Variable_Maps is new Simple_HTable
(Header_Num => Elaboration_Context_Index,
Key => Entity_Id,
- Element => Boolean,
- No_Element => False,
+ Element => Node_Id,
+ No_Element => Empty,
Hash => Elaboration_Context_Hash,
Equal => "=");
- -- These maps allow tracking the variables that have been declared but
- -- never used anywhere in the source code. Especially, we do not raise
- -- an error if the variable stays write-only and is declared at package
- -- level, because there is no risk that the variable has been moved,
- -- because it has never been used.
- type Initialization_Map is new Boolean_Variables_Maps.Instance;
+ type Variable_Mapping is new Variable_Maps.Instance;
+ -- Mapping from variables to nodes denoting paths that are observed or
+ -- borrowed by the variable.
--------------------
-- Simple Getters --
@@ -195,7 +221,6 @@ package body Sem_SPARK is
function Get_Elem (T : Perm_Tree_Access) return Perm_Tree_Access;
function Is_Node_Deep (T : Perm_Tree_Access) return Boolean;
function Kind (T : Perm_Tree_Access) return Path_Kind;
- function Other_Components (T : Perm_Tree_Access) return Perm_Tree_Access;
function Permission (T : Perm_Tree_Access) return Perm_Kind;
-----------------------
@@ -204,25 +229,24 @@ package body Sem_SPARK is
procedure Copy_Env
(From : Perm_Env;
- To : in out Perm_Env);
+ To : in out Perm_Env);
-- Procedure to copy a permission environment
- procedure Copy_Init_Map
- (From : Initialization_Map;
- To : in out Initialization_Map);
- -- Procedure to copy an initialization map
+ procedure Move_Env (From, To : in out Perm_Env);
+ -- Procedure to move a permission environment. It frees To, moves From
+ -- in To and sets From to Nil.
+
+ procedure Move_Variable_Mapping (From, To : in out Variable_Mapping);
+ -- Move a variable mapping, freeing memory as needed and resetting the
+ -- source mapping.
- procedure Copy_Tree
- (From : Perm_Tree_Access;
- To : Perm_Tree_Access);
+ procedure Copy_Tree (From, To : Perm_Tree_Access);
-- Procedure to copy a permission tree
- procedure Free_Env
- (PE : in out Perm_Env);
+ procedure Free_Env (PE : in out Perm_Env);
-- Procedure to free a permission environment
- procedure Free_Perm_Tree
- (PT : in out Perm_Tree_Access);
+ procedure Free_Tree (PT : in out Perm_Tree_Access);
-- Procedure to free a permission tree
--------------------
@@ -230,8 +254,10 @@ package body Sem_SPARK is
--------------------
procedure Perm_Mismatch
- (Exp_Perm, Act_Perm : Perm_Kind;
- N : Node_Id);
+ (N : Node_Id;
+ Exp_Perm : Perm_Kind;
+ Act_Perm : Perm_Kind;
+ Forbidden_Perm : Boolean := False);
-- Issues a continuation error message about a mismatch between a
-- desired permission Exp_Perm and a permission obtained Act_Perm. N
-- is the node on which the error is reported.
@@ -253,9 +279,7 @@ package body Sem_SPARK is
-- Component --
---------------
- function Component
- (T : Perm_Tree_Access)
- return Perm_Tree_Maps.Instance
+ function Component (T : Perm_Tree_Access) return Perm_Tree_Maps.Instance
is
begin
return T.all.Tree.Component;
@@ -271,7 +295,7 @@ package body Sem_SPARK is
Son : Perm_Tree_Access;
begin
- Reset (To);
+ Free_Env (To);
Key_From := Get_First_Key (From);
while Key_From.Present loop
Comp_From := Get (From, Key_From.K);
@@ -285,34 +309,18 @@ package body Sem_SPARK is
end loop;
end Copy_Env;
- -------------------
- -- Copy_Init_Map --
- -------------------
-
- procedure Copy_Init_Map
- (From : Initialization_Map;
- To : in out Initialization_Map)
- is
- Comp_From : Boolean;
- Key_From : Boolean_Variables_Maps.Key_Option;
-
- begin
- Reset (To);
- Key_From := Get_First_Key (From);
- while Key_From.Present loop
- Comp_From := Get (From, Key_From.K);
- Set (To, Key_From.K, Comp_From);
- Key_From := Get_Next_Key (From);
- end loop;
- end Copy_Init_Map;
-
---------------
-- Copy_Tree --
---------------
- procedure Copy_Tree (From : Perm_Tree_Access; To : Perm_Tree_Access) is
+ procedure Copy_Tree (From, To : Perm_Tree_Access) is
begin
+ -- Copy the direct components of the tree
+
To.all := From.all;
+
+ -- Now reallocate access components for a deep copy of the tree
+
case Kind (From) is
when Entire_Object =>
null;
@@ -332,12 +340,9 @@ package body Sem_SPARK is
Son : Perm_Tree_Access;
Hash_Table : Perm_Tree_Maps.Instance;
begin
- -- We put a new hash table, so that it gets dealiased from the
- -- Component (From) hash table.
+ -- We put a new hash table, so that it gets dealiased from
+ -- the Component (From) hash table.
To.all.Tree.Component := Hash_Table;
- To.all.Tree.Other_Components :=
- new Perm_Tree_Wrapper'(Other_Components (From).all);
- Copy_Tree (Other_Components (From), Other_Components (To));
Key_From := Perm_Tree_Maps.Get_First_Key
(Component (From));
@@ -354,7 +359,6 @@ package body Sem_SPARK is
end loop;
end;
end case;
-
end Copy_Tree;
------------------------------
@@ -377,16 +381,18 @@ package body Sem_SPARK is
begin
CompO := Get_First (PE);
while CompO /= null loop
- Free_Perm_Tree (CompO);
+ Free_Tree (CompO);
CompO := Get_Next (PE);
end loop;
+
+ Reset (PE);
end Free_Env;
- --------------------
- -- Free_Perm_Tree --
- --------------------
+ ---------------
+ -- Free_Tree --
+ ---------------
- procedure Free_Perm_Tree (PT : in out Perm_Tree_Access) is
+ procedure Free_Tree (PT : in out Perm_Tree_Access) is
procedure Free_Perm_Tree_Dealloc is
new Ada.Unchecked_Deallocation
(Perm_Tree_Wrapper, Perm_Tree_Access);
@@ -395,33 +401,32 @@ package body Sem_SPARK is
begin
case Kind (PT) is
when Entire_Object =>
- Free_Perm_Tree_Dealloc (PT);
+ null;
when Reference =>
- Free_Perm_Tree (PT.all.Tree.Get_All);
- Free_Perm_Tree_Dealloc (PT);
+ Free_Tree (PT.all.Tree.Get_All);
when Array_Component =>
- Free_Perm_Tree (PT.all.Tree.Get_Elem);
+ Free_Tree (PT.all.Tree.Get_Elem);
when Record_Component =>
declare
Comp : Perm_Tree_Access;
begin
- Free_Perm_Tree (PT.all.Tree.Other_Components);
Comp := Perm_Tree_Maps.Get_First (Component (PT));
while Comp /= null loop
-- Free every Component subtree
- Free_Perm_Tree (Comp);
+ Free_Tree (Comp);
Comp := Perm_Tree_Maps.Get_Next (Component (PT));
end loop;
end;
- Free_Perm_Tree_Dealloc (PT);
end case;
- end Free_Perm_Tree;
+
+ Free_Perm_Tree_Dealloc (PT);
+ end Free_Tree;
-------------
-- Get_All --
@@ -459,17 +464,27 @@ package body Sem_SPARK is
return T.all.Tree.Kind;
end Kind;
- ----------------------
- -- Other_Components --
- ----------------------
+ --------------
+ -- Move_Env --
+ --------------
- function Other_Components
- (T : Perm_Tree_Access)
- return Perm_Tree_Access
- is
+ procedure Move_Env (From, To : in out Perm_Env) is
begin
- return T.all.Tree.Other_Components;
- end Other_Components;
+ Free_Env (To);
+ To := From;
+ From := Perm_Env (Perm_Tree_Maps.Nil);
+ end Move_Env;
+
+ ---------------------------
+ -- Move_Variable_Mapping --
+ ---------------------------
+
+ procedure Move_Variable_Mapping (From, To : in out Variable_Mapping) is
+ begin
+ Reset (To);
+ To := From;
+ From := Variable_Mapping (Variable_Maps.Nil);
+ end Move_Variable_Mapping;
----------------
-- Permission --
@@ -484,11 +499,27 @@ package body Sem_SPARK is
-- Perm_Mismatch --
-------------------
- procedure Perm_Mismatch (Exp_Perm, Act_Perm : Perm_Kind; N : Node_Id) is
+ procedure Perm_Mismatch
+ (N : Node_Id;
+ Exp_Perm : Perm_Kind;
+ Act_Perm : Perm_Kind;
+ Forbidden_Perm : Boolean := False)
+ is
begin
- Error_Msg_N ("\expected state `"
- & Perm_Kind'Image (Exp_Perm) & "` at least, got `"
- & Perm_Kind'Image (Act_Perm) & "`", N);
+ if Forbidden_Perm then
+ if Exp_Perm = Act_Perm then
+ Error_Msg_N ("\got forbidden state `"
+ & Perm_Kind'Image (Exp_Perm), N);
+ else
+ Error_Msg_N ("\forbidden state `"
+ & Perm_Kind'Image (Exp_Perm) & "`, got `"
+ & Perm_Kind'Image (Act_Perm) & "`", N);
+ end if;
+ else
+ Error_Msg_N ("\expected state `"
+ & Perm_Kind'Image (Exp_Perm) & "` at least, got `"
+ & Perm_Kind'Image (Act_Perm) & "`", N);
+ end if;
end Perm_Mismatch;
end Permissions;
@@ -499,8 +530,9 @@ package body Sem_SPARK is
-- Analysis modes for AST traversal --
--------------------------------------
- -- The different modes for analysis. This allows to checking whether a path
- -- found in the code should be moved, borrowed, or observed.
+ -- The different modes for analysis. This allows checking whether a path
+ -- has the right permission, and also updating permissions when a path is
+ -- moved, borrowed, or observed.
type Checking_Mode is
@@ -508,31 +540,32 @@ package body Sem_SPARK is
-- Default mode
Move,
- -- Regular moving semantics. Checks that paths have Unrestricted
- -- permission. After moving a path, the permission of both it and
- -- its extensions are set to Unrestricted.
+ -- Move semantics. Checks that paths have Read_Write permission. After
+ -- moving a path, its permission and the permission of its prefixes are
+ -- set to Write_Only, while the permission of its extensions is set to
+ -- No_Access.
Assign,
-- Used for the target of an assignment, or an actual parameter with
- -- mode OUT. Checks that paths have Unrestricted permission. After
- -- assigning to a path, its permission is set to Unrestricted.
+ -- mode OUT. Checks that paths have Write_Perm permission. After
+ -- assigning to a path, its permission and the permission of its
+ -- extensions are set to Read_Write. The permission of its prefixes may
+ -- be normalized from Write_Only to Read_Write depending on other
+ -- permissions in the tree (a prefix gets permission Read_Write when all
+ -- its extensions become Read_Write).
Borrow,
- -- Used for the source of an assignement when initializes a stand alone
- -- object of anonymous type, constant, or IN parameter and also OUT
- -- or IN OUT composite object.
- -- In the borrowed state, the access object is completely "dead".
+ -- Borrow semantics. Checks that paths have Read_Write permission. After
+ -- borrowing a path, its permission and the permission of its prefixes
+ -- and extensions are set to No_Access.
Observe
- -- Used for actual IN parameters of a scalar type. Checks that paths
- -- have Read_Perm permission. After checking a path, its permission
- -- is set to Observed.
- --
- -- Also used for formal IN parameters
-
+ -- Observe semantics. Checks that paths have Read_Perm permission. After
+ -- observing a path, its permission and the permission of its prefixes
+ -- and extensions are set to Read_Only.
);
- type Result_Kind is (Folded, Unfolded, Function_Call);
+ type Result_Kind is (Folded, Unfolded);
-- The type declaration to discriminate in the Perm_Or_Tree type
-- The result type of the function Get_Perm_Or_Tree. This returns either a
@@ -542,72 +575,125 @@ package body Sem_SPARK is
type Perm_Or_Tree (R : Result_Kind) is record
case R is
- when Folded => Found_Permission : Perm_Kind;
- when Unfolded => Tree_Access : Perm_Tree_Access;
- when Function_Call => null;
+ when Folded => Found_Permission : Perm_Kind;
+ when Unfolded => Tree_Access : Perm_Tree_Access;
end case;
end record;
+ type Error_Status is (OK, Error);
+
-----------------------
-- Local subprograms --
-----------------------
- -- Checking proceduress for safe pointer usage. These procedures traverse
- -- the AST, check nodes for correct permissions according to SPARK RM
- -- 6.4.2, and update permissions depending on the node kind.
+ function "<=" (P1, P2 : Perm_Kind) return Boolean;
+ function ">=" (P1, P2 : Perm_Kind) return Boolean;
+ function Glb (P1, P2 : Perm_Kind) return Perm_Kind;
+ function Lub (P1, P2 : Perm_Kind) return Perm_Kind;
+
+ procedure Check_Assignment (Target : Node_Or_Entity_Id; Expr : Node_Id);
+ -- Handle assignment as part of an assignment statement or an object
+ -- declaration.
procedure Check_Call_Statement (Call : Node_Id);
procedure Check_Callable_Body (Body_N : Node_Id);
- -- We are not in End_Of_Callee mode, hence we will save the environment
- -- and start from a new one. We will add in the environment all formal
- -- parameters as well as global used during the subprogram, with the
- -- appropriate permissions (unrestricted for borrowed and moved, observed
- -- for observed names).
+ -- Entry point for the analysis of a subprogram or entry body
procedure Check_Declaration (Decl : Node_Id);
- procedure Check_Expression (Expr : Node_Id);
+ procedure Check_Expression (Expr : Node_Id; Mode : Checking_Mode);
+ pragma Precondition (Nkind_In (Expr, N_Index_Or_Discriminant_Constraint,
+ N_Range_Constraint,
+ N_Subtype_Indication)
+ or else Nkind (Expr) in N_Subexpr);
- procedure Check_Globals (N : Node_Id);
- -- This procedure takes a global pragma and checks it
+ procedure Check_Globals (Subp : Entity_Id);
+ -- This procedure takes a subprogram called and checks the permission of
+ -- globals.
+
+ -- Checking proceduress for safe pointer usage. These procedures traverse
+ -- the AST, check nodes for correct permissions according to SPARK RM 3.10,
+ -- and update permissions depending on the node kind. The main procedure
+ -- Check_Node is mutually recursive with the specialized procedures that
+ -- follow.
procedure Check_List (L : List_Id);
-- Calls Check_Node on each element of the list
- procedure Check_Loop_Statement (Loop_N : Node_Id);
+ procedure Check_Loop_Statement (Stmt : Node_Id);
procedure Check_Node (N : Node_Id);
- -- Main traversal procedure to check safe pointer usage. This procedure is
- -- mutually recursive with the specialized procedures that follow.
+ -- Main traversal procedure to check safe pointer usage
procedure Check_Package_Body (Pack : Node_Id);
- procedure Check_Param_In (Formal : Entity_Id; Actual : Node_Id);
- -- This procedure takes a formal and an actual parameter and checks the
- -- permission of every in-mode parameter. This includes Observing and
- -- Borrowing.
+ procedure Check_Package_Spec (Pack : Node_Id);
+
+ procedure Check_Parameter_Or_Global
+ (Expr : Node_Id;
+ Typ : Entity_Id;
+ Kind : Formal_Kind;
+ Subp : Entity_Id;
+ Global_Var : Boolean);
+ -- Check the permission of every actual parameter or global
+
+ procedure Check_Pragma (Prag : Node_Id);
- procedure Check_Param_Out (Formal : Entity_Id; Actual : Node_Id);
- -- This procedure takes a formal and an actual parameter and checks the
- -- state of every out-mode and in out-mode parameter. This includes
- -- Moving and Borrowing.
+ procedure Check_Source_Of_Borrow_Or_Observe
+ (Expr : Node_Id;
+ Status : out Error_Status);
procedure Check_Statement (Stmt : Node_Id);
- function Get_Perm (N : Node_Id) return Perm_Kind;
+ procedure Check_Type (Typ : Entity_Id);
+ -- Check that type Typ is either not deep, or that it is an observing or
+ -- owning type according to SPARK RM 3.10
+
+ function Get_Observed_Or_Borrowed_Expr (Expr : Node_Id) return Node_Id;
+ pragma Precondition (Is_Path_Expression (Expr));
+ -- Return the expression being borrowed/observed when borrowing or
+ -- observing Expr. If Expr is a call to a traversal function, this is
+ -- the first actual, otherwise it is Expr.
+
+ function Get_Perm (N : Node_Or_Entity_Id) return Perm_Kind;
-- The function that takes a name as input and returns a permission
- -- associated to it.
+ -- associated with it.
function Get_Perm_Or_Tree (N : Node_Id) return Perm_Or_Tree;
- -- This function gets a Node_Id and looks recursively to find the
- -- appropriate subtree for that Node_Id. If the tree is folded on
- -- that node, then it returns the permission given at the right level.
+ pragma Precondition (Is_Path_Expression (N));
+ -- This function gets a node and looks recursively to find the appropriate
+ -- subtree for that node. If the tree is folded on that node, then it
+ -- returns the permission given at the right level.
function Get_Perm_Tree (N : Node_Id) return Perm_Tree_Access;
- -- This function gets a Node_Id and looks recursively to find the
- -- appropriate subtree for that Node_Id. If the tree is folded, then
- -- it unrolls the tree up to the appropriate level.
+ pragma Precondition (Is_Path_Expression (N));
+ -- This function gets a node and looks recursively to find the appropriate
+ -- subtree for that node. If the tree is folded, then it unrolls the tree
+ -- up to the appropriate level.
+
+ function Get_Root_Object
+ (Expr : Node_Id;
+ Through_Traversal : Boolean := True) return Entity_Id;
+ pragma Precondition (Is_Path_Expression (Expr));
+ -- Return the root of the path expression Expr, or Empty for an allocator,
+ -- NULL, or a function call. Through_Traversal is True if it should follow
+ -- through calls to traversal functions.
+
+ generic
+ with procedure Handle_Parameter_Or_Global
+ (Expr : Node_Id;
+ Formal_Typ : Entity_Id;
+ Param_Mode : Formal_Kind;
+ Subp : Entity_Id;
+ Global_Var : Boolean);
+ procedure Handle_Globals (Subp : Entity_Id);
+ -- Handling of globals is factored in a generic instantiated below
+
+ function Has_Array_Component (Expr : Node_Id) return Boolean;
+ pragma Precondition (Is_Path_Expression (Expr));
+ -- This function gets a node and looks recursively to determine whether the
+ -- given path has any array component.
procedure Hp (P : Perm_Env);
-- A procedure that outputs the hash table. This function is used only in
@@ -619,18 +705,38 @@ package body Sem_SPARK is
-- A procedure that is called when deep globals or aliased globals are used
-- without any global aspect.
- function Is_Deep (E : Entity_Id) return Boolean;
+ function Is_Deep (Typ : Entity_Id) return Boolean;
-- A function that can tell if a type is deep or not. Returns true if the
-- type passed as argument is deep.
+ function Is_Path_Expression (Expr : Node_Id) return Boolean;
+ -- Return whether Expr corresponds to a path
+
+ function Is_Prefix_Or_Almost (Pref, Expr : Node_Id) return Boolean;
+ -- Determine if the candidate Prefix is indeed a prefix of Expr, or almost
+ -- a prefix, in the sense that they could still refer to overlapping memory
+ -- locations.
+
+ function Is_Traversal_Function (E : Entity_Id) return Boolean;
+
+ function Is_Traversal_Function_Call (Expr : Node_Id) return Boolean;
+
+ function Loop_Of_Exit (N : Node_Id) return Entity_Id;
+ -- A function that takes an exit statement node and returns the entity of
+ -- the loop that this statement is exiting from.
+
+ procedure Merge_Env (Source : in out Perm_Env; Target : in out Perm_Env);
+ -- Merge Target and Source into Target, and then deallocate the Source
+
procedure Perm_Error
- (N : Node_Id;
- Perm : Perm_Kind;
- Found_Perm : Perm_Kind);
+ (N : Node_Id;
+ Perm : Perm_Kind;
+ Found_Perm : Perm_Kind;
+ Forbidden_Perm : Boolean := False);
-- A procedure that is called when the permissions found contradict the
- -- rules established by the RM. This function is called with the node, its
- -- entity and the permission that was expected, and adds an error message
- -- with the appropriate values.
+ -- rules established by the RM. This function is called with the node and
+ -- the permission that was expected, and issues an error message with the
+ -- appropriate values.
procedure Perm_Error_Subprogram_End
(E : Entity_Id;
@@ -638,50 +744,69 @@ package body Sem_SPARK is
Perm : Perm_Kind;
Found_Perm : Perm_Kind);
-- A procedure that is called when the permissions found contradict the
- -- rules established by the RM at the end of subprograms. This function
- -- is called with the node, its entity, the node of the returning function
- -- and the permission that was expected, and adds an error message with the
+ -- rules established by the RM at the end of subprograms. This function is
+ -- called with the node, the node of the returning function, and the
+ -- permission that was expected, and adds an error message with the
-- appropriate values.
- procedure Process_Path (N : Node_Id);
-
- procedure Return_Declarations (L : List_Id);
- -- Check correct permissions on every declared object at the end of a
- -- callee. Used at the end of the body of a callable entity. Checks that
- -- paths of all borrowed formal parameters and global have Unrestricted
- -- permission.
+ procedure Process_Path (Expr : Node_Id; Mode : Checking_Mode);
+ pragma Precondition (Is_Path_Expression (Expr));
+ -- Check correct permission for the path in the checking mode Mode, and
+ -- update permissions of the path and its prefixes/extensions.
procedure Return_Globals (Subp : Entity_Id);
-- Takes a subprogram as input, and checks that all borrowed global items
- -- of the subprogram indeed have RW permission at the end of the subprogram
- -- execution.
-
- procedure Return_The_Global
- (Id : Entity_Id;
- Mode : Formal_Kind;
- Subp : Entity_Id);
- -- Auxiliary procedure to Return_Globals
- -- There is no need to return parameters because they will be reassigned
- -- their state once the subprogram returns. Local variables that have
- -- borrowed, observed, or moved an actual parameter go out of the scope.
+ -- of the subprogram indeed have Read_Write permission at the end of the
+ -- subprogram execution.
+
+ procedure Return_Parameter_Or_Global
+ (Id : Entity_Id;
+ Typ : Entity_Id;
+ Kind : Formal_Kind;
+ Subp : Entity_Id;
+ Global_Var : Boolean);
+ -- Auxiliary procedure to Return_Parameters and Return_Globals
+
+ procedure Return_Parameters (Subp : Entity_Id);
+ -- Takes a subprogram as input, and checks that all out parameters of the
+ -- subprogram indeed have Read_Write permission at the end of the
+ -- subprogram execution.
procedure Set_Perm_Extensions (T : Perm_Tree_Access; P : Perm_Kind);
-- This procedure takes an access to a permission tree and modifies the
-- tree so that any strict extensions of the given tree become of the
-- access specified by parameter P.
- function Set_Perm_Prefixes_Borrow (N : Node_Id) return Perm_Tree_Access;
- -- This function modifies the permissions of a given node_id in the
- -- permission environment as well as in all the prefixes of the path,
- -- given that the path is borrowed with mode out.
+ procedure Set_Perm_Extensions_Move (T : Perm_Tree_Access; E : Entity_Id);
+ -- Set permissions to
+ -- No for any extension with more .all
+ -- W for any deep extension with same number of .all
+ -- RW for any shallow extension with same number of .all
function Set_Perm_Prefixes
- (N : Node_Id;
- New_Perm : Perm_Kind)
- return Perm_Tree_Access;
- -- This function sets the permissions of a given node_id in the
- -- permission environment as well as in all the prefixes of the path
- -- to the one given in parameter (P).
+ (N : Node_Id;
+ Perm : Perm_Kind_Option) return Perm_Tree_Access;
+ pragma Precondition (Is_Path_Expression (N));
+ -- This function modifies the permissions of a given node in the permission
+ -- environment as well as all the prefixes of the path, to the new
+ -- permission Perm. The general rule here is that everybody updates the
+ -- permission of the subtree they are returning.
+
+ procedure Set_Perm_Prefixes_Assign (N : Node_Id);
+ pragma Precondition (Is_Path_Expression (N));
+ -- This procedure takes a name as an input and sets in the permission
+ -- tree the given permission to the given name. The general rule here is
+ -- that everybody updates the permission of the subtree it is returning.
+ -- The permission of the assigned path has been set to RW by the caller.
+ --
+ -- Case where we have to normalize a tree after the correct permissions
+ -- have been assigned already. We look for the right subtree at the given
+ -- path, actualize its permissions, and then call the normalization on its
+ -- parent.
+ --
+ -- Example: We assign x.y and x.z, and then Set_Perm_Prefixes_Assign will
+ -- change the permission of x to RW because all of its components have
+ -- permission RW.
procedure Setup_Globals (Subp : Entity_Id);
-- Takes a subprogram as input, and sets up the environment by adding
@@ -689,7 +814,9 @@ package body Sem_SPARK is
procedure Setup_Parameter_Or_Global
(Id : Entity_Id;
- Mode : Formal_Kind;
+ Typ : Entity_Id;
+ Kind : Formal_Kind;
+ Subp : Entity_Id;
Global_Var : Boolean);
-- Auxiliary procedure to Setup_Parameters and Setup_Globals
@@ -697,15 +824,6 @@ package body Sem_SPARK is
-- Takes a subprogram as input, and sets up the environment by adding
-- formal parameters with appropriate permissions.
- function Has_Ownership_Aspect_True
- (N : Node_Id;
- Msg : String)
- return Boolean;
- -- Takes a node as an input, and finds out whether it has ownership aspect
- -- True or False. This function is recursive whenever the node has a
- -- composite type. Access-to-objects have ownership aspect False if they
- -- have a general access type.
-
----------------------
-- Global Variables --
----------------------
@@ -717,11 +835,13 @@ package body Sem_SPARK is
-- scope. The analysis ensures at each point that this variables contains
-- a valid permission environment with all bindings in scope.
- Current_Checking_Mode : Checking_Mode := Read;
- -- The current analysis mode. This global variable indicates at each point
- -- of the analysis whether the node being analyzed is moved, borrowed,
- -- assigned, read, ... The full list of possible values can be found in
- -- the declaration of type Checking_Mode.
+ Inside_Procedure_Call : Boolean := False;
+ -- Set while checking the actual parameters of a procedure or entry call
+
+ Inside_Elaboration : Boolean := False;
+ -- Set during package spec/body elaboration, during which move and local
+ -- observe/borrow are not allowed. As a result, no other checking is needed
+ -- during elaboration.
Current_Loops_Envs : Env_Backups;
-- This variable contains saves of permission environments at each loop the
@@ -737,378 +857,486 @@ package body Sem_SPARK is
-- restrictive than the saved environment at the beginning of the loop, and
-- the permission environment after the loop is equal to the accumulator.
- Current_Initialization_Map : Initialization_Map;
- -- This variable contains a map that binds each variable of the analyzed
- -- source code to a boolean that becomes true whenever the variable is used
- -- after declaration. Hence we can exclude from analysis variables that
- -- are just declared and never accessed, typically at package declaration.
+ Current_Borrowers : Variable_Mapping;
+ -- Mapping from borrowers to the path borrowed
- --------------------------
- -- Check_Call_Statement --
- --------------------------
+ Current_Observers : Variable_Mapping;
+ -- Mapping from observers to the path observed
- procedure Check_Call_Statement (Call : Node_Id) is
- Saved_Env : Perm_Env;
+ --------------------
+ -- Handle_Globals --
+ --------------------
- procedure Iterate_Call_In is new
- Iterate_Call_Parameters (Check_Param_In);
- procedure Iterate_Call_Out is new
- Iterate_Call_Parameters (Check_Param_Out);
+ -- Generic procedure is defined first so that instantiations can be defined
+ -- anywhere afterwards.
- begin
- -- Save environment, so that the modifications done by analyzing the
- -- parameters are not kept at the end of the call.
-
- Copy_Env (Current_Perm_Env, Saved_Env);
-
- -- We first check the globals then parameters to handle the
- -- No_Parameter_Aliasing Restriction. An out or in-out global is
- -- considered as borrowing while a parameter with the same mode is
- -- a move. This order disallow passing a part of a variable to a
- -- subprogram if it is referenced as a global by the callable (when
- -- writable).
- -- For paremeters, we fisrt check in parameters and then the out ones.
- -- This is to avoid Observing or Borrowing objects that are already
- -- moved. This order is not mandatory but allows to catch runtime
- -- errors like null pointer dereferencement at the analysis time.
-
- Current_Checking_Mode := Read;
- Check_Globals (Get_Pragma (Get_Called_Entity (Call), Pragma_Global));
- Iterate_Call_In (Call);
- Iterate_Call_Out (Call);
-
- -- Restore environment, because after borrowing/observing actual
- -- parameters, they get their permission reverted to the ones before
- -- the call.
-
- Free_Env (Current_Perm_Env);
- Copy_Env (Saved_Env, Current_Perm_Env);
- Free_Env (Saved_Env);
- end Check_Call_Statement;
+ procedure Handle_Globals (Subp : Entity_Id) is
- -------------------------
- -- Check_Callable_Body --
- -------------------------
+ -- Local subprograms
- procedure Check_Callable_Body (Body_N : Node_Id) is
+ procedure Handle_Globals_From_List
+ (First_Item : Node_Id;
+ Kind : Formal_Kind);
+ -- Handle global items from the list starting at Item
+
+ procedure Handle_Globals_Of_Mode (Global_Mode : Name_Id);
+ -- Handle global items for the mode Global_Mode
+
+ ------------------------------
+ -- Handle_Globals_From_List --
+ ------------------------------
+
+ procedure Handle_Globals_From_List
+ (First_Item : Node_Id;
+ Kind : Formal_Kind)
+ is
+ Item : Node_Id := First_Item;
+ E : Entity_Id;
+
+ begin
+ while Present (Item) loop
+ E := Entity (Item);
+
+ -- Ignore abstract states, which play no role in pointer aliasing
- Mode_Before : constant Checking_Mode := Current_Checking_Mode;
- Saved_Env : Perm_Env;
- Saved_Init_Map : Initialization_Map;
- New_Env : Perm_Env;
- Body_Id : constant Entity_Id := Defining_Entity (Body_N);
- Spec_Id : constant Entity_Id := Unique_Entity (Body_Id);
+ if Ekind (E) = E_Abstract_State then
+ null;
+ else
+ Handle_Parameter_Or_Global (Expr => Item,
+ Formal_Typ => Etype (Item),
+ Param_Mode => Kind,
+ Subp => Subp,
+ Global_Var => True);
+ end if;
+
+ Next_Global (Item);
+ end loop;
+ end Handle_Globals_From_List;
+
+ ----------------------------
+ -- Handle_Globals_Of_Mode --
+ ----------------------------
+
+ procedure Handle_Globals_Of_Mode (Global_Mode : Name_Id) is
+ Kind : Formal_Kind;
+
+ begin
+ case Global_Mode is
+ when Name_Input
+ | Name_Proof_In
+ =>
+ Kind := E_In_Parameter;
+
+ when Name_Output =>
+ Kind := E_Out_Parameter;
+
+ when Name_In_Out =>
+ Kind := E_In_Out_Parameter;
+
+ when others =>
+ raise Program_Error;
+ end case;
+
+ -- Check both global items from Global and Refined_Global pragmas
+
+ Handle_Globals_From_List (First_Global (Subp, Global_Mode), Kind);
+ Handle_Globals_From_List
+ (First_Global (Subp, Global_Mode, Refined => True), Kind);
+ end Handle_Globals_Of_Mode;
+
+ -- Start of processing for Handle_Globals
begin
- -- Check if SPARK pragma is not set to Off
+ Handle_Globals_Of_Mode (Name_Proof_In);
+ Handle_Globals_Of_Mode (Name_Input);
+ Handle_Globals_Of_Mode (Name_Output);
+ Handle_Globals_Of_Mode (Name_In_Out);
+ end Handle_Globals;
- if Present (SPARK_Pragma (Defining_Entity (Body_N))) then
- if Get_SPARK_Mode_From_Annotation
- (SPARK_Pragma (Defining_Entity (Body_N, False))) /= Opt.On
- then
- return;
- end if;
- else
- return;
- end if;
+ ----------
+ -- "<=" --
+ ----------
- -- Save environment and put a new one in place
+ function "<=" (P1, P2 : Perm_Kind) return Boolean is
+ begin
+ return P2 >= P1;
+ end "<=";
- Copy_Env (Current_Perm_Env, Saved_Env);
+ ----------
+ -- ">=" --
+ ----------
- -- Save initialization map
+ function ">=" (P1, P2 : Perm_Kind) return Boolean is
+ begin
+ case P2 is
+ when No_Access => return True;
+ when Read_Only => return P1 in Read_Perm;
+ when Write_Only => return P1 in Write_Perm;
+ when Read_Write => return P1 = Read_Write;
+ end case;
+ end ">=";
- Copy_Init_Map (Current_Initialization_Map, Saved_Init_Map);
- Current_Checking_Mode := Read;
- Current_Perm_Env := New_Env;
+ ----------------------
+ -- Check_Assignment --
+ ----------------------
- -- Add formals and globals to the environment with adequate permissions
+ procedure Check_Assignment (Target : Node_Or_Entity_Id; Expr : Node_Id) is
- if Is_Subprogram_Or_Entry (Spec_Id) then
- Setup_Parameters (Spec_Id);
- Setup_Globals (Spec_Id);
- end if;
+ -- Local subprograms
- -- Analyze the body of the function
+ procedure Handle_Borrow
+ (Var : Entity_Id;
+ Expr : Node_Id;
+ Is_Decl : Boolean);
+ -- Update map of current borrowers
- Check_List (Declarations (Body_N));
- Check_Node (Handled_Statement_Sequence (Body_N));
+ procedure Handle_Observe
+ (Var : Entity_Id;
+ Expr : Node_Id;
+ Is_Decl : Boolean);
+ -- Update map of current observers
- -- Check the read-write permissions of borrowed parameters/globals
+ -------------------
+ -- Handle_Borrow --
+ -------------------
- if Ekind_In (Spec_Id, E_Procedure, E_Entry)
- and then not No_Return (Spec_Id)
- then
- Return_Globals (Spec_Id);
- end if;
+ procedure Handle_Borrow
+ (Var : Entity_Id;
+ Expr : Node_Id;
+ Is_Decl : Boolean)
+ is
+ Borrowed : constant Node_Id := Get_Observed_Or_Borrowed_Expr (Expr);
- -- Free the environments
+ begin
+ -- SPARK RM 3.10(8): If the type of the target is an anonymous
+ -- access-to-variable type (an owning access type), the source shall
+ -- be an owning access object [..] whose root object is the target
+ -- object itself.
- Free_Env (Current_Perm_Env);
- Copy_Env (Saved_Env, Current_Perm_Env);
- Free_Env (Saved_Env);
+ -- ??? In fact we could be slightly more permissive in allowing even
+ -- a call to a traversal function of the right form.
- -- Restore initialization map
+ if not Is_Decl
+ and then (Is_Traversal_Function_Call (Expr)
+ or else Get_Root_Object (Borrowed) /= Var)
+ then
+ Error_Msg_NE
+ ("source of assignment must have & as root (SPARK RM 3.10(8)))",
+ Expr, Var);
+ return;
+ end if;
- Copy_Init_Map (Saved_Init_Map, Current_Initialization_Map);
- Reset (Saved_Init_Map);
+ Set (Current_Borrowers, Var, Borrowed);
+ end Handle_Borrow;
- -- The assignment of all out parameters will be done by caller
+ --------------------
+ -- Handle_Observe --
+ --------------------
- Current_Checking_Mode := Mode_Before;
- end Check_Callable_Body;
+ procedure Handle_Observe
+ (Var : Entity_Id;
+ Expr : Node_Id;
+ Is_Decl : Boolean)
+ is
+ Observed : constant Node_Id := Get_Observed_Or_Borrowed_Expr (Expr);
- -----------------------
- -- Check_Declaration --
- -----------------------
+ begin
+ -- ??? We are currently using the same restriction for observers
+ -- as for borrowers. To be seen if the SPARK RM current rule really
+ -- allows more uses.
- procedure Check_Declaration (Decl : Node_Id) is
- Target_Ent : constant Entity_Id := Defining_Identifier (Decl);
- Target_Typ : Node_Id renames Etype (Target_Ent);
+ if not Is_Decl
+ and then (Is_Traversal_Function_Call (Expr)
+ or else Get_Root_Object (Observed) /= Var)
+ then
+ Error_Msg_NE
+ ("source of assignment must have & as root (SPARK RM 3.10(8)))",
+ Expr, Var);
+ return;
+ end if;
- Target_View_Typ : Entity_Id;
+ Set (Current_Observers, Var, Observed);
+ end Handle_Observe;
- Check : Boolean := True;
- begin
- if Present (Full_View (Target_Typ)) then
- Target_View_Typ := Full_View (Target_Typ);
- else
- Target_View_Typ := Target_Typ;
- end if;
+ -- Local variables
- case N_Declaration'(Nkind (Decl)) is
- when N_Full_Type_Declaration =>
- if not Has_Ownership_Aspect_True (Target_Ent, "type declaration")
- then
- Check := False;
- end if;
+ Target_Typ : constant Node_Id := Etype (Target);
+ Is_Decl : constant Boolean := Nkind (Target) = N_Defining_Identifier;
+ Target_Root : Entity_Id;
+ Expr_Root : Entity_Id;
+ Perm : Perm_Kind;
+ Status : Error_Status;
- -- ??? What about component declarations with defaults.
+ -- Start of processing for Check_Assignment
- when N_Object_Declaration =>
- if (Is_Access_Type (Target_View_Typ)
- or else Is_Deep (Target_Typ))
- and then not Has_Ownership_Aspect_True
- (Target_Ent, "Object declaration ")
- then
- Check := False;
- end if;
+ begin
+ Check_Type (Target_Typ);
- if Is_Anonymous_Access_Type (Target_View_Typ)
- and then not Present (Expression (Decl))
- then
+ if Is_Anonymous_Access_Type (Target_Typ) then
+ Check_Source_Of_Borrow_Or_Observe (Expr, Status);
- -- ??? Check the case of default value (AI)
- -- ??? How an anonymous access type can be with default exp?
+ if Status /= OK then
+ return;
+ end if;
- Error_Msg_NE ("? object declaration & has OAF (Anonymous "
- & "access-to-object with no initialization)",
- Decl, Target_Ent);
+ if Is_Decl then
+ Target_Root := Target;
+ else
+ Target_Root := Get_Root_Object (Target);
+ end if;
- -- If it it an initialization
+ Expr_Root := Get_Root_Object (Expr);
- elsif Present (Expression (Decl)) and Check then
+ -- SPARK RM 3.10(8): For an assignment statement where
+ -- the target is a stand-alone object of an anonymous
+ -- access-to-object type
- -- Find out the operation to be done on the right-hand side
+ pragma Assert (Present (Target_Root));
- -- Initializing object, access type
+ -- If the type of the target is an anonymous
+ -- access-to-constant type (an observing access type), the
+ -- source shall be an owning access object denoted by a name
+ -- that is not in the Moved state, and whose root object
+ -- is not in the Moved state and is not declared at a
+ -- statically deeper accessibility level than that of
+ -- the target object.
- if Is_Access_Type (Target_View_Typ) then
+ if Is_Access_Constant (Target_Typ) then
+ Perm := Get_Perm (Expr);
- -- Initializing object, constant access type
+ if Perm = No_Access then
+ Perm_Error (Expr, No_Access, No_Access,
+ Forbidden_Perm => True);
+ return;
+ end if;
- if Is_Constant_Object (Target_Ent) then
+ Perm := Get_Perm (Expr_Root);
- -- Initializing object, constant access to variable type
+ if Perm = No_Access then
+ Perm_Error (Expr, No_Access, No_Access,
+ Forbidden_Perm => True);
+ return;
+ end if;
- if not Is_Access_Constant (Target_View_Typ) then
- Current_Checking_Mode := Borrow;
+ -- ??? check accessibility level
- -- Initializing object, constant access to constant type
+ -- If the type of the target is an anonymous
+ -- access-to-variable type (an owning access type), the
+ -- source shall be an owning access object denoted by a
+ -- name that is in the Unrestricted state, and whose root
+ -- object is the target object itself.
- -- Initializing object,
- -- constant access to constant anonymous type.
+ Check_Expression (Expr, Observe);
+ Handle_Observe (Target_Root, Expr, Is_Decl);
- elsif Is_Anonymous_Access_Type (Target_View_Typ) then
+ else
+ Perm := Get_Perm (Expr);
- -- This is an object declaration so the target
- -- of the assignement is a stand-alone object.
+ if Perm /= Read_Write then
+ Perm_Error (Expr, Read_Write, Perm);
+ return;
+ end if;
- Current_Checking_Mode := Observe;
+ if not Is_Decl then
+ if not Is_Entity_Name (Target) then
+ Error_Msg_N
+ ("target of borrow must be stand-alone variable",
+ Target);
+ return;
- -- Initializing object, constant access to constant
- -- named type.
+ elsif Target_Root /= Expr_Root then
+ Error_Msg_NE
+ ("source of borrow must be variable &",
+ Expr, Target);
+ return;
+ end if;
+ end if;
- else
- -- If named then it is a general access type
- -- Hence, Has_Ownership_Aspec_True is False.
+ Check_Expression (Expr, Borrow);
+ Handle_Borrow (Target_Root, Expr, Is_Decl);
+ end if;
- raise Program_Error;
- end if;
+ elsif Is_Deep (Target_Typ) then
- -- Initializing object, variable access type
+ if Is_Path_Expression (Expr) then
+ Check_Expression (Expr, Move);
+
+ else
+ Error_Msg_N ("expression not allowed as source of move", Expr);
+ return;
+ end if;
- else
- -- Initializing object, variable access to variable type
+ else
+ Check_Expression (Expr, Read);
+ end if;
+ end Check_Assignment;
- if not Is_Access_Constant (Target_View_Typ) then
+ --------------------------
+ -- Check_Call_Statement --
+ --------------------------
- -- Initializing object, variable named access to
- -- variable type.
+ procedure Check_Call_Statement (Call : Node_Id) is
- if not Is_Anonymous_Access_Type (Target_View_Typ) then
- Current_Checking_Mode := Move;
+ Subp : constant Entity_Id := Get_Called_Entity (Call);
- -- Initializing object, variable anonymous access to
- -- variable type.
+ -- Local subprograms
- else
- -- This is an object declaration so the target
- -- object of the assignement is a stand-alone
- -- object.
+ procedure Check_Param (Formal : Entity_Id; Actual : Node_Id);
+ -- Check the permission of every actual parameter
- Current_Checking_Mode := Borrow;
- end if;
+ procedure Update_Param (Formal : Entity_Id; Actual : Node_Id);
+ -- Update the permission of OUT actual parameters
- -- Initializing object, variable access to constant type
+ -----------------
+ -- Check_Param --
+ -----------------
- else
- -- Initializing object,
- -- variable named access to constant type.
+ procedure Check_Param (Formal : Entity_Id; Actual : Node_Id) is
+ begin
+ Check_Parameter_Or_Global
+ (Expr => Actual,
+ Typ => Underlying_Type (Etype (Formal)),
+ Kind => Ekind (Formal),
+ Subp => Subp,
+ Global_Var => False);
+ end Check_Param;
- if not Is_Anonymous_Access_Type (Target_View_Typ) then
- Error_Msg_N ("assignment not allowed, Ownership "
- & "Aspect False (Anonymous Access "
- & "Object)", Decl);
- Check := False;
+ ------------------
+ -- Update_Param --
+ ------------------
- -- Initializing object,
- -- variable anonymous access to constant type.
+ procedure Update_Param (Formal : Entity_Id; Actual : Node_Id) is
+ Mode : constant Entity_Kind := Ekind (Formal);
- else
- -- This is an object declaration so the target
- -- of the assignement is a stand-alone object.
+ begin
+ case Formal_Kind'(Mode) is
+ when E_Out_Parameter =>
+ Check_Expression (Actual, Assign);
- Current_Checking_Mode := Observe;
- end if;
- end if;
- end if;
+ when others =>
+ null;
+ end case;
+ end Update_Param;
- -- Initializing object, composite (deep) type
+ procedure Check_Params is new
+ Iterate_Call_Parameters (Check_Param);
- elsif Is_Deep (Target_Typ) then
+ procedure Update_Params is new
+ Iterate_Call_Parameters (Update_Param);
- -- Initializing object, constant composite type
+ -- Start of processing for Check_Call_Statement
- if Is_Constant_Object (Target_Ent) then
- Current_Checking_Mode := Observe;
+ begin
+ Inside_Procedure_Call := True;
+ Check_Params (Call);
+ Check_Globals (Get_Called_Entity (Call));
- -- Initializing object, variable composite type
+ Inside_Procedure_Call := False;
+ Update_Params (Call);
+ end Check_Call_Statement;
- else
+ -------------------------
+ -- Check_Callable_Body --
+ -------------------------
- -- Initializing object, variable anonymous composite type
+ procedure Check_Callable_Body (Body_N : Node_Id) is
+ Save_In_Elab : constant Boolean := Inside_Elaboration;
+ Body_Id : constant Entity_Id := Defining_Entity (Body_N);
+ Spec_Id : constant Entity_Id := Unique_Entity (Body_Id);
+ Prag : constant Node_Id := SPARK_Pragma (Body_Id);
- if Nkind (Object_Definition (Decl)) =
- N_Constrained_Array_Definition
+ Saved_Env : Perm_Env;
+ Saved_Borrowers : Variable_Mapping;
+ Saved_Observers : Variable_Mapping;
- -- An N_Constrained_Array_Definition is an anonymous
- -- array (to be checked). Record types are always
- -- named and are considered in the else part.
+ begin
+ -- Only SPARK bodies are analyzed
- then
- declare
- Com_Ty : constant Node_Id :=
- Component_Type (Etype (Target_Typ));
- begin
+ if No (Prag)
+ or else Get_SPARK_Mode_From_Annotation (Prag) /= Opt.On
+ then
+ return;
+ end if;
- if Is_Access_Type (Com_Ty) then
+ Inside_Elaboration := False;
- -- If components are of anonymous type
+ -- Save environment and put a new one in place
- if Is_Anonymous_Access_Type (Com_Ty) then
- if Is_Access_Constant (Com_Ty) then
- Current_Checking_Mode := Observe;
+ Move_Env (Current_Perm_Env, Saved_Env);
+ Move_Variable_Mapping (Current_Borrowers, Saved_Borrowers);
+ Move_Variable_Mapping (Current_Observers, Saved_Observers);
- else
- Current_Checking_Mode := Borrow;
- end if;
+ -- Add formals and globals to the environment with adequate permissions
- else
- Current_Checking_Mode := Move;
- end if;
+ if Is_Subprogram_Or_Entry (Spec_Id) then
+ Setup_Parameters (Spec_Id);
+ Setup_Globals (Spec_Id);
+ end if;
- elsif Is_Deep (Com_Ty) then
+ -- Analyze the body of the subprogram
- -- This is certainly named so it is a move
+ Check_List (Declarations (Body_N));
+ Check_Node (Handled_Statement_Sequence (Body_N));
- Current_Checking_Mode := Move;
- end if;
- end;
+ -- Check the read-write permissions of borrowed parameters/globals
- else
- Current_Checking_Mode := Move;
- end if;
- end if;
+ if Ekind_In (Spec_Id, E_Procedure, E_Entry)
+ and then not No_Return (Spec_Id)
+ then
+ Return_Parameters (Spec_Id);
+ Return_Globals (Spec_Id);
+ end if;
- end if;
- end if;
+ -- Restore the saved environment and free the current one
- if Check then
- Check_Node (Expression (Decl));
- end if;
+ Move_Env (Saved_Env, Current_Perm_Env);
+ Move_Variable_Mapping (Saved_Borrowers, Current_Borrowers);
+ Move_Variable_Mapping (Saved_Observers, Current_Observers);
- -- If lhs is not a pointer, we still give it the unrestricted
- -- state which is useless but not harmful.
+ Inside_Elaboration := Save_In_Elab;
+ end Check_Callable_Body;
- declare
- Elem : Perm_Tree_Access;
- Deep : constant Boolean := Is_Deep (Target_Typ);
+ -----------------------
+ -- Check_Declaration --
+ -----------------------
- begin
- -- Note that all declared variables are set to the unrestricted
- -- state.
- --
- -- If variables are not initialized:
- -- unrestricted to every declared object.
- -- Exp:
- -- R : Rec
- -- S : Rec := (...)
- -- R := S
- -- The assignement R := S is not allowed in the new rules
- -- if R is not unrestricted.
- --
- -- If variables are initialized:
- -- If it is a move, then the target is unrestricted
- -- If it is a borrow, then the target is unrestricted
- -- If it is an observe, then the target should be observed
-
- if Current_Checking_Mode = Observe then
- Elem := new Perm_Tree_Wrapper'
- (Tree =>
- (Kind => Entire_Object,
- Is_Node_Deep => Deep,
- Permission => Observed,
- Children_Permission => Observed));
- else
- Elem := new Perm_Tree_Wrapper'
- (Tree =>
- (Kind => Entire_Object,
- Is_Node_Deep => Deep,
- Permission => Unrestricted,
- Children_Permission => Unrestricted));
- end if;
+ procedure Check_Declaration (Decl : Node_Id) is
+ Target : constant Entity_Id := Defining_Identifier (Decl);
+ Target_Typ : constant Node_Id := Etype (Target);
+ Expr : Node_Id;
- -- Create new tree for defining identifier
+ begin
+ case N_Declaration'(Nkind (Decl)) is
+ when N_Full_Type_Declaration =>
+ Check_Type (Target);
- Set (Current_Perm_Env,
- Unique_Entity (Defining_Identifier (Decl)),
- Elem);
- pragma Assert (Get_First (Current_Perm_Env) /= null);
- end;
+ -- ??? What about component declarations with defaults.
when N_Subtype_Declaration =>
- Check_Node (Subtype_Indication (Decl));
+ Check_Expression (Subtype_Indication (Decl), Read);
+
+ when N_Object_Declaration =>
+ Check_Type (Target_Typ);
+
+ Expr := Expression (Decl);
+ if Present (Expr) then
+ Check_Assignment (Target => Target,
+ Expr => Expr);
+ end if;
+
+ if Is_Deep (Target_Typ) then
+ declare
+ Tree : constant Perm_Tree_Access :=
+ new Perm_Tree_Wrapper'
+ (Tree =>
+ (Kind => Entire_Object,
+ Is_Node_Deep => True,
+ Permission => Read_Write,
+ Children_Permission => Read_Write));
+ begin
+ Set (Current_Perm_Env, Target, Tree);
+ end;
+ end if;
when N_Iterator_Specification =>
null;
@@ -1147,318 +1375,401 @@ package body Sem_SPARK is
-- Check_Expression --
----------------------
- procedure Check_Expression (Expr : Node_Id) is
- Mode_Before : constant Checking_Mode := Current_Checking_Mode;
- begin
- case N_Subexpr'(Nkind (Expr)) is
- when N_Procedure_Call_Statement
- | N_Function_Call
- =>
- Check_Call_Statement (Expr);
+ procedure Check_Expression (Expr : Node_Id; Mode : Checking_Mode) is
- when N_Identifier
- | N_Expanded_Name
- =>
- -- Check if identifier is pointing to nothing (On/Off/...)
+ -- Local subprograms
- if not Present (Entity (Expr)) then
- return;
- end if;
+ function Is_Type_Name (Expr : Node_Id) return Boolean;
+ -- Detect when a path expression is in fact a type name
- -- Do not analyze things that are not of object Kind
+ procedure Read_Expression (Expr : Node_Id);
+ -- Most subexpressions are only analyzed in Read mode. This is a
+ -- specialized version of Check_Expression for that case.
- if Ekind (Entity (Expr)) not in Object_Kind then
- return;
- end if;
+ procedure Read_Expression_List (L : List_Id);
+ -- Call Read_Expression on every expression in the list L
- -- Consider as ident
+ procedure Read_Indexes (Expr : Node_Id);
+ pragma Precondition (Is_Path_Expression (Expr));
+ -- When processing a path, the index expressions and function call
+ -- arguments occurring on the path should be analyzed in Read mode.
- Process_Path (Expr);
+ ------------------
+ -- Is_Type_Name --
+ ------------------
- -- Switch to read mode and then check the readability of each operand
+ function Is_Type_Name (Expr : Node_Id) return Boolean is
+ begin
+ return Nkind_In (Expr, N_Expanded_Name, N_Identifier)
+ and then Is_Type (Entity (Expr));
+ end Is_Type_Name;
- when N_Binary_Op =>
- Current_Checking_Mode := Read;
- Check_Node (Left_Opnd (Expr));
- Check_Node (Right_Opnd (Expr));
+ ---------------------
+ -- Read_Expression --
+ ---------------------
- -- Switch to read mode and then check the readability of each operand
+ procedure Read_Expression (Expr : Node_Id) is
+ begin
+ Check_Expression (Expr, Read);
+ end Read_Expression;
- when N_Op_Abs
- | N_Op_Minus
- | N_Op_Not
- | N_Op_Plus
- =>
- Current_Checking_Mode := Read;
- Check_Node (Right_Opnd (Expr));
+ --------------------------
+ -- Read_Expression_List --
+ --------------------------
- -- Forbid all deep expressions for Attribute ???
- -- What about generics? (formal parameters).
+ procedure Read_Expression_List (L : List_Id) is
+ N : Node_Id;
+ begin
+ N := First (L);
+ while Present (N) loop
+ Read_Expression (N);
+ Next (N);
+ end loop;
+ end Read_Expression_List;
- when N_Attribute_Reference =>
- case Attribute_Name (Expr) is
- when Name_Access =>
- Error_Msg_N ("access attribute not allowed", Expr);
+ ------------------
+ -- Read_Indexes --
+ ------------------
- when Name_Last
- | Name_First
- =>
- Current_Checking_Mode := Read;
- Check_Node (Prefix (Expr));
+ procedure Read_Indexes (Expr : Node_Id) is
- when Name_Min =>
- Current_Checking_Mode := Read;
- Check_Node (Prefix (Expr));
+ -- Local subprograms
- when Name_Image =>
- Check_List (Expressions (Expr));
+ procedure Read_Param (Formal : Entity_Id; Actual : Node_Id);
- when Name_Img =>
- Check_Node (Prefix (Expr));
+ ----------------
+ -- Read_Param --
+ ----------------
- when Name_SPARK_Mode =>
- null;
+ procedure Read_Param (Formal : Entity_Id; Actual : Node_Id) is
+ pragma Unreferenced (Formal);
+ begin
+ Read_Expression (Actual);
+ end Read_Param;
- when Name_Value =>
- Current_Checking_Mode := Read;
- Check_Node (Prefix (Expr));
+ procedure Read_Params is new Iterate_Call_Parameters (Read_Param);
- when Name_Update =>
- Check_List (Expressions (Expr));
- Check_Node (Prefix (Expr));
+ -- Start of processing for Read_Indexes
- when Name_Pred
- | Name_Succ
- =>
- Check_List (Expressions (Expr));
- Check_Node (Prefix (Expr));
-
- when Name_Length =>
- Current_Checking_Mode := Read;
- Check_Node (Prefix (Expr));
-
- -- Any Attribute referring to the underlying memory is ignored
- -- in the analysis. This means that taking the address of a
- -- variable makes a silent alias that is not rejected by the
- -- analysis.
-
- when Name_Address
- | Name_Alignment
- | Name_Component_Size
- | Name_First_Bit
- | Name_Last_Bit
- | Name_Size
- | Name_Position
- =>
- null;
+ begin
+ case N_Subexpr'(Nkind (Expr)) is
+ when N_Identifier
+ | N_Expanded_Name
+ | N_Null
+ =>
+ null;
- -- Attributes referring to types (get values from types), hence
- -- no need to check either for borrows or any loans.
+ when N_Explicit_Dereference
+ | N_Selected_Component
+ =>
+ Read_Indexes (Prefix (Expr));
- when Name_Base
- | Name_Val
- =>
- null;
- -- Other attributes that fall out of the scope of the analysis
+ when N_Indexed_Component =>
+ Read_Indexes (Prefix (Expr));
+ Read_Expression_List (Expressions (Expr));
- when others =>
- null;
- end case;
+ when N_Slice =>
+ Read_Indexes (Prefix (Expr));
+ Read_Expression (Discrete_Range (Expr));
- when N_In =>
- Current_Checking_Mode := Read;
- Check_Node (Left_Opnd (Expr));
- Check_Node (Right_Opnd (Expr));
+ when N_Allocator =>
+ Read_Expression (Expression (Expr));
- when N_Not_In =>
- Current_Checking_Mode := Read;
- Check_Node (Left_Opnd (Expr));
- Check_Node (Right_Opnd (Expr));
+ when N_Function_Call =>
+ Read_Params (Expr);
+ Check_Globals (Get_Called_Entity (Expr));
- -- Switch to read mode and then check the readability of each operand
+ when N_Qualified_Expression
+ | N_Type_Conversion
+ | N_Unchecked_Type_Conversion
+ =>
+ Read_Indexes (Expression (Expr));
- when N_And_Then
- | N_Or_Else
- =>
- Current_Checking_Mode := Read;
- Check_Node (Left_Opnd (Expr));
- Check_Node (Right_Opnd (Expr));
+ when others =>
+ raise Program_Error;
+ end case;
+ end Read_Indexes;
- -- Check the arguments of the call
+ -- Start of processing for Check_Expression
- when N_Explicit_Dereference =>
- Process_Path (Expr);
+ begin
+ if Is_Type_Name (Expr) then
+ return;
- -- Copy environment, run on each branch, and then merge
+ elsif Is_Path_Expression (Expr) then
+ Read_Indexes (Expr);
+ Process_Path (Expr, Mode);
+ return;
+ end if;
- when N_If_Expression =>
- declare
- Saved_Env : Perm_Env;
+ -- Expressions that are not path expressions should only be analyzed in
+ -- Read mode.
- -- Accumulator for the different branches
+ pragma Assert (Mode = Read);
- New_Env : Perm_Env;
- Elmt : Node_Id := First (Expressions (Expr));
+ -- Special handling for nodes that may contain evaluated expressions in
+ -- the form of constraints.
+ case Nkind (Expr) is
+ when N_Index_Or_Discriminant_Constraint =>
+ declare
+ Assn : Node_Id := First (Constraints (Expr));
begin
- Current_Checking_Mode := Read;
- Check_Node (Elmt);
- Current_Checking_Mode := Mode_Before;
+ while Present (Assn) loop
+ case Nkind (Assn) is
+ when N_Discriminant_Association =>
+ Read_Expression (Expression (Assn));
- -- Save environment
+ when others =>
+ Read_Expression (Assn);
+ end case;
- Copy_Env (Current_Perm_Env, Saved_Env);
+ Next (Assn);
+ end loop;
+ end;
+ return;
- -- Here we have the original env in saved, current with a fresh
- -- copy, and new aliased.
+ when N_Range_Constraint =>
+ Read_Expression (Range_Expression (Expr));
+ return;
- -- THEN PART
+ when N_Subtype_Indication =>
+ if Present (Constraint (Expr)) then
+ Read_Expression (Constraint (Expr));
+ end if;
+ return;
- Next (Elmt);
- Check_Node (Elmt);
+ when others =>
+ null;
+ end case;
- -- Here the new_environment contains curr env after then block
+ -- At this point Expr can only be a subexpression
- -- ELSE part
- -- Restore environment before if
- Copy_Env (Current_Perm_Env, New_Env);
- Free_Env (Current_Perm_Env);
- Copy_Env (Saved_Env, Current_Perm_Env);
+ case N_Subexpr'(Nkind (Expr)) is
- -- Here new environment contains the environment after then and
- -- current the fresh copy of old one.
+ when N_Binary_Op
+ | N_Membership_Test
+ | N_Short_Circuit
+ =>
+ Read_Expression (Left_Opnd (Expr));
+ Read_Expression (Right_Opnd (Expr));
- Next (Elmt);
- Check_Node (Elmt);
+ when N_Unary_Op =>
+ Read_Expression (Right_Opnd (Expr));
- -- CLEANUP
+ when N_Attribute_Reference =>
+ declare
+ Aname : constant Name_Id := Attribute_Name (Expr);
+ Attr_Id : constant Attribute_Id := Get_Attribute_Id (Aname);
+ Pref : constant Node_Id := Prefix (Expr);
+ Args : constant List_Id := Expressions (Expr);
- Copy_Env (New_Env, Current_Perm_Env);
- Free_Env (New_Env);
- Free_Env (Saved_Env);
- end;
+ begin
+ case Attr_Id is
+
+ -- The following attributes take either no arguments, or
+ -- arguments that do not refer to evaluated expressions
+ -- (like Length or Loop_Entry), hence only the prefix
+ -- needs to be read.
+
+ when Attribute_Address
+ | Attribute_Alignment
+ | Attribute_Callable
+ | Attribute_Component_Size
+ | Attribute_Constrained
+ | Attribute_First
+ | Attribute_First_Bit
+ | Attribute_Last
+ | Attribute_Last_Bit
+ | Attribute_Length
+ | Attribute_Loop_Entry
+ | Attribute_Object_Size
+ | Attribute_Position
+ | Attribute_Size
+ | Attribute_Terminated
+ | Attribute_Valid
+ | Attribute_Value_Size
+ =>
+ Read_Expression (Pref);
+
+ -- The following attributes take a type name as prefix,
+ -- hence only the arguments need to be read.
+
+ when Attribute_Ceiling
+ | Attribute_Floor
+ | Attribute_Max
+ | Attribute_Min
+ | Attribute_Mod
+ | Attribute_Pos
+ | Attribute_Pred
+ | Attribute_Remainder
+ | Attribute_Rounding
+ | Attribute_Succ
+ | Attribute_Truncation
+ | Attribute_Val
+ | Attribute_Value
+ =>
+ Read_Expression_List (Args);
- when N_Indexed_Component =>
- Process_Path (Expr);
+ -- Attributes Image and Img either take a type name as
+ -- prefix with an expression in argument, or the expression
+ -- directly as prefix. Adapt to each case.
- -- Analyze the expression that is getting qualified
+ when Attribute_Image
+ | Attribute_Img
+ =>
+ if No (Args) then
+ Read_Expression (Pref);
+ else
+ Read_Expression_List (Args);
+ end if;
- when N_Qualified_Expression =>
- Check_Node (Expression (Expr));
+ -- Attribute Update takes expressions as both prefix and
+ -- arguments, so both need to be read.
- when N_Quantified_Expression =>
- declare
- Saved_Env : Perm_Env;
+ when Attribute_Update =>
+ Read_Expression (Pref);
+ Read_Expression_List (Args);
- begin
- Copy_Env (Current_Perm_Env, Saved_Env);
- Current_Checking_Mode := Read;
- Check_Node (Iterator_Specification (Expr));
- Check_Node (Loop_Parameter_Specification (Expr));
+ -- Attribute Modulus does not reference the evaluated
+ -- expression, so it can be ignored for this analysis.
- Check_Node (Condition (Expr));
- Free_Env (Current_Perm_Env);
- Copy_Env (Saved_Env, Current_Perm_Env);
- Free_Env (Saved_Env);
+ when Attribute_Modulus =>
+ null;
+
+ -- Postconditions should not be analyzed
+
+ when Attribute_Old
+ | Attribute_Result
+ =>
+ raise Program_Error;
+
+ when others =>
+ Error_Msg_Name_1 := Aname;
+ Error_Msg_N ("attribute % not allowed in SPARK", Expr);
+ end case;
end;
- -- Analyze the list of associations in the aggregate
- when N_Aggregate =>
- Check_List (Expressions (Expr));
- Check_List (Component_Associations (Expr));
+ when N_Range =>
+ Read_Expression (Low_Bound (Expr));
+ Read_Expression (High_Bound (Expr));
- when N_Allocator =>
- Check_Node (Expression (Expr));
+ when N_If_Expression =>
+ Read_Expression_List (Expressions (Expr));
when N_Case_Expression =>
declare
- Saved_Env : Perm_Env;
-
- -- Accumulator for the different branches
-
- New_Env : Perm_Env;
- Elmt : Node_Id := First (Alternatives (Expr));
+ Cases : constant List_Id := Alternatives (Expr);
+ Cur_Case : Node_Id := First (Cases);
begin
- Current_Checking_Mode := Read;
- Check_Node (Expression (Expr));
- Current_Checking_Mode := Mode_Before;
+ while Present (Cur_Case) loop
+ Read_Expression (Expression (Cur_Case));
+ Next (Cur_Case);
+ end loop;
- -- Save environment
+ Read_Expression (Expression (Expr));
+ end;
- Copy_Env (Current_Perm_Env, Saved_Env);
+ when N_Qualified_Expression
+ | N_Type_Conversion
+ | N_Unchecked_Type_Conversion
+ =>
+ Read_Expression (Expression (Expr));
- -- Here we have the original env in saved, current with a fresh
- -- copy, and new aliased.
+ when N_Quantified_Expression =>
+ declare
+ For_In_Spec : constant Node_Id :=
+ Loop_Parameter_Specification (Expr);
+ For_Of_Spec : constant Node_Id :=
+ Iterator_Specification (Expr);
+ For_Of_Spec_Typ : Node_Id;
- -- First alternative
+ begin
+ if Present (For_In_Spec) then
+ Read_Expression (Discrete_Subtype_Definition (For_In_Spec));
+ else
+ Read_Expression (Name (For_Of_Spec));
+ For_Of_Spec_Typ := Subtype_Indication (For_Of_Spec);
+ if Present (For_Of_Spec_Typ) then
+ Read_Expression (For_Of_Spec_Typ);
+ end if;
+ end if;
- Check_Node (Elmt);
- Next (Elmt);
- Copy_Env (Current_Perm_Env, New_Env);
- Free_Env (Current_Perm_Env);
+ Read_Expression (Condition (Expr));
+ end;
- -- Other alternatives
+ when N_Aggregate =>
+ declare
+ Assocs : constant List_Id := Component_Associations (Expr);
+ Assoc : Node_Id := First (Assocs);
+ CL : List_Id;
+ Choice : Node_Id;
- while Present (Elmt) loop
+ begin
+ while Present (Assoc) loop
+
+ -- An array aggregate with a single component association
+ -- may have a nonstatic choice expression that needs to be
+ -- analyzed. This can only occur for a single choice that
+ -- is not the OTHERS one.
+
+ if Is_Array_Type (Etype (Expr)) then
+ CL := Choices (Assoc);
+ if List_Length (CL) = 1 then
+ Choice := First (CL);
+ if Nkind (Choice) /= N_Others_Choice then
+ Read_Expression (Choice);
+ end if;
+ end if;
+ end if;
- -- Restore environment
+ -- The expression in the component association also needs to
+ -- be analyzed.
- Copy_Env (Saved_Env, Current_Perm_Env);
- Check_Node (Elmt);
- Next (Elmt);
+ Read_Expression (Expression (Assoc));
+ Next (Assoc);
end loop;
- -- CLEANUP
- Copy_Env (Saved_Env, Current_Perm_Env);
- Free_Env (New_Env);
- Free_Env (Saved_Env);
+ Read_Expression_List (Expressions (Expr));
end;
- -- Analyze the list of associates in the aggregate as well as the
- -- ancestor part.
when N_Extension_Aggregate =>
- Check_Node (Ancestor_Part (Expr));
- Check_List (Expressions (Expr));
-
- when N_Range =>
- Check_Node (Low_Bound (Expr));
- Check_Node (High_Bound (Expr));
-
- -- We arrived at a path. Process it.
-
- when N_Selected_Component =>
- Process_Path (Expr);
+ Read_Expression (Ancestor_Part (Expr));
+ Read_Expression_List (Expressions (Expr));
- when N_Slice =>
- Process_Path (Expr);
-
- when N_Type_Conversion =>
- Check_Node (Expression (Expr));
+ when N_Character_Literal
+ | N_Numeric_Or_String_Literal
+ | N_Operator_Symbol
+ | N_Raise_Expression
+ | N_Raise_xxx_Error
+ =>
+ null;
- when N_Unchecked_Type_Conversion =>
- Check_Node (Expression (Expr));
+ when N_Delta_Aggregate
+ | N_Target_Name
+ =>
+ Error_Msg_N ("unsupported construct in SPARK", Expr);
- -- Checking should not be called directly on these nodes
+ -- Procedure calls are handled in Check_Node
- when N_Target_Name =>
+ when N_Procedure_Call_Statement =>
raise Program_Error;
- -- Unsupported constructs in SPARK
-
- when N_Delta_Aggregate =>
- Error_Msg_N ("unsupported construct in SPARK", Expr);
-
- -- Ignored constructs for pointer checking
+ -- Path expressions are handled before this point
- when N_Character_Literal
+ when N_Allocator
+ | N_Expanded_Name
+ | N_Explicit_Dereference
+ | N_Function_Call
+ | N_Identifier
+ | N_Indexed_Component
| N_Null
- | N_Numeric_Or_String_Literal
- | N_Operator_Symbol
- | N_Raise_Expression
- | N_Raise_xxx_Error
+ | N_Selected_Component
+ | N_Slice
=>
- null;
+ raise Program_Error;
+
-- The following nodes are never generated in GNATprove mode
when N_Expression_With_Actions
@@ -1469,171 +1780,344 @@ package body Sem_SPARK is
end case;
end Check_Expression;
- -------------------
- -- Check_Globals --
- -------------------
+ ----------------
+ -- Check_List --
+ ----------------
- procedure Check_Globals (N : Node_Id) is
+ procedure Check_List (L : List_Id) is
+ N : Node_Id;
begin
- if Nkind (N) = N_Empty then
- return;
- end if;
+ N := First (L);
+ while Present (N) loop
+ Check_Node (N);
+ Next (N);
+ end loop;
+ end Check_List;
- declare
- pragma Assert (List_Length (Pragma_Argument_Associations (N)) = 1);
- PAA : constant Node_Id := First (Pragma_Argument_Associations (N));
- pragma Assert (Nkind (PAA) = N_Pragma_Argument_Association);
- Row : Node_Id;
- The_Mode : Name_Id;
- RHS : Node_Id;
-
- procedure Process (Mode : Name_Id; The_Global : Entity_Id);
- procedure Process (Mode : Name_Id; The_Global : Node_Id) is
- Ident_Elt : constant Entity_Id :=
- Unique_Entity (Entity (The_Global));
- Mode_Before : constant Checking_Mode := Current_Checking_Mode;
+ --------------------------
+ -- Check_Loop_Statement --
+ --------------------------
+ procedure Check_Loop_Statement (Stmt : Node_Id) is
+
+ -- Local Subprograms
+
+ procedure Check_Is_Less_Restrictive_Env
+ (Exiting_Env : Perm_Env;
+ Entry_Env : Perm_Env);
+ -- This procedure checks that the Exiting_Env environment is less
+ -- restrictive than the Entry_Env environment.
+
+ procedure Check_Is_Less_Restrictive_Tree
+ (New_Tree : Perm_Tree_Access;
+ Orig_Tree : Perm_Tree_Access;
+ E : Entity_Id);
+ -- Auxiliary procedure to check that the tree New_Tree is less
+ -- restrictive than the tree Orig_Tree for the entity E.
+
+ procedure Perm_Error_Loop_Exit
+ (E : Entity_Id;
+ Loop_Id : Node_Id;
+ Perm : Perm_Kind;
+ Found_Perm : Perm_Kind);
+ -- A procedure that is called when the permissions found contradict
+ -- the rules established by the RM at the exit of loops. This function
+ -- is called with the entity, the node of the enclosing loop, the
+ -- permission that was expected, and the permission found, and issues
+ -- an appropriate error message.
+
+ -----------------------------------
+ -- Check_Is_Less_Restrictive_Env --
+ -----------------------------------
+
+ procedure Check_Is_Less_Restrictive_Env
+ (Exiting_Env : Perm_Env;
+ Entry_Env : Perm_Env)
+ is
+ Comp_Entry : Perm_Tree_Maps.Key_Option;
+ Iter_Entry, Iter_Exit : Perm_Tree_Access;
+
+ begin
+ Comp_Entry := Get_First_Key (Entry_Env);
+ while Comp_Entry.Present loop
+ Iter_Entry := Get (Entry_Env, Comp_Entry.K);
+ pragma Assert (Iter_Entry /= null);
+ Iter_Exit := Get (Exiting_Env, Comp_Entry.K);
+ pragma Assert (Iter_Exit /= null);
+ Check_Is_Less_Restrictive_Tree
+ (New_Tree => Iter_Exit,
+ Orig_Tree => Iter_Entry,
+ E => Comp_Entry.K);
+ Comp_Entry := Get_Next_Key (Entry_Env);
+ end loop;
+ end Check_Is_Less_Restrictive_Env;
+
+ ------------------------------------
+ -- Check_Is_Less_Restrictive_Tree --
+ ------------------------------------
+
+ procedure Check_Is_Less_Restrictive_Tree
+ (New_Tree : Perm_Tree_Access;
+ Orig_Tree : Perm_Tree_Access;
+ E : Entity_Id)
+ is
+ -- Local subprograms
+
+ procedure Check_Is_Less_Restrictive_Tree_Than
+ (Tree : Perm_Tree_Access;
+ Perm : Perm_Kind;
+ E : Entity_Id);
+ -- Auxiliary procedure to check that the tree N is less restrictive
+ -- than the given permission P.
+
+ procedure Check_Is_More_Restrictive_Tree_Than
+ (Tree : Perm_Tree_Access;
+ Perm : Perm_Kind;
+ E : Entity_Id);
+ -- Auxiliary procedure to check that the tree N is more restrictive
+ -- than the given permission P.
+
+ -----------------------------------------
+ -- Check_Is_Less_Restrictive_Tree_Than --
+ -----------------------------------------
+
+ procedure Check_Is_Less_Restrictive_Tree_Than
+ (Tree : Perm_Tree_Access;
+ Perm : Perm_Kind;
+ E : Entity_Id)
+ is
begin
- if Ekind (Ident_Elt) = E_Abstract_State then
- return;
+ if not (Permission (Tree) >= Perm) then
+ Perm_Error_Loop_Exit
+ (E, Stmt, Permission (Tree), Perm);
end if;
- case Mode is
- when Name_Input
- | Name_Proof_In
- =>
- Current_Checking_Mode := Observe;
- Check_Node (The_Global);
- when Name_Output
- | Name_In_Out
- =>
- -- ??? Borrow not Move?
- Current_Checking_Mode := Borrow;
- Check_Node (The_Global);
+ case Kind (Tree) is
+ when Entire_Object =>
+ if not (Children_Permission (Tree) >= Perm) then
+ Perm_Error_Loop_Exit
+ (E, Stmt, Children_Permission (Tree), Perm);
- when others =>
- raise Program_Error;
+ end if;
+
+ when Reference =>
+ Check_Is_Less_Restrictive_Tree_Than
+ (Get_All (Tree), Perm, E);
+
+ when Array_Component =>
+ Check_Is_Less_Restrictive_Tree_Than
+ (Get_Elem (Tree), Perm, E);
+
+ when Record_Component =>
+ declare
+ Comp : Perm_Tree_Access;
+ begin
+ Comp := Perm_Tree_Maps.Get_First (Component (Tree));
+ while Comp /= null loop
+ Check_Is_Less_Restrictive_Tree_Than (Comp, Perm, E);
+ Comp :=
+ Perm_Tree_Maps.Get_Next (Component (Tree));
+ end loop;
+ end;
end case;
- Current_Checking_Mode := Mode_Before;
- end Process;
+ end Check_Is_Less_Restrictive_Tree_Than;
- begin
- if Nkind (Expression (PAA)) = N_Null then
+ -----------------------------------------
+ -- Check_Is_More_Restrictive_Tree_Than --
+ -----------------------------------------
- -- global => null
- -- No globals, nothing to do
+ procedure Check_Is_More_Restrictive_Tree_Than
+ (Tree : Perm_Tree_Access;
+ Perm : Perm_Kind;
+ E : Entity_Id)
+ is
+ begin
+ if not (Perm >= Permission (Tree)) then
+ Perm_Error_Loop_Exit
+ (E, Stmt, Permission (Tree), Perm);
+ end if;
- return;
+ case Kind (Tree) is
+ when Entire_Object =>
+ if not (Perm >= Children_Permission (Tree)) then
+ Perm_Error_Loop_Exit
+ (E, Stmt, Children_Permission (Tree), Perm);
+ end if;
- elsif Nkind_In (Expression (PAA), N_Identifier, N_Expanded_Name) then
+ when Reference =>
+ Check_Is_More_Restrictive_Tree_Than
+ (Get_All (Tree), Perm, E);
- -- global => foo
- -- A single input
+ when Array_Component =>
+ Check_Is_More_Restrictive_Tree_Than
+ (Get_Elem (Tree), Perm, E);
- Process (Name_Input, Expression (PAA));
+ when Record_Component =>
+ declare
+ Comp : Perm_Tree_Access;
+ begin
+ Comp := Perm_Tree_Maps.Get_First (Component (Tree));
+ while Comp /= null loop
+ Check_Is_More_Restrictive_Tree_Than (Comp, Perm, E);
+ Comp :=
+ Perm_Tree_Maps.Get_Next (Component (Tree));
+ end loop;
+ end;
+ end case;
+ end Check_Is_More_Restrictive_Tree_Than;
- elsif Nkind (Expression (PAA)) = N_Aggregate
- and then Expressions (Expression (PAA)) /= No_List
- then
- -- global => (foo, bar)
- -- Inputs
-
- RHS := First (Expressions (Expression (PAA)));
- while Present (RHS) loop
- case Nkind (RHS) is
- when N_Identifier
- | N_Expanded_Name
- =>
- Process (Name_Input, RHS);
+ -- Start of processing for Check_Is_Less_Restrictive_Tree
- when N_Numeric_Or_String_Literal =>
- Process (Name_Input, Original_Node (RHS));
+ begin
+ if not (Permission (New_Tree) <= Permission (Orig_Tree)) then
+ Perm_Error_Loop_Exit
+ (E => E,
+ Loop_Id => Stmt,
+ Perm => Permission (New_Tree),
+ Found_Perm => Permission (Orig_Tree));
+ end if;
- when others =>
- raise Program_Error;
+ case Kind (New_Tree) is
+
+ -- Potentially folded tree. We check the other tree Orig_Tree to
+ -- check whether it is folded or not. If folded we just compare
+ -- their Permission and Children_Permission, if not, then we
+ -- look at the Children_Permission of the folded tree against
+ -- the unfolded tree Orig_Tree.
+
+ when Entire_Object =>
+ case Kind (Orig_Tree) is
+ when Entire_Object =>
+ if not (Children_Permission (New_Tree) <=
+ Children_Permission (Orig_Tree))
+ then
+ Perm_Error_Loop_Exit
+ (E, Stmt,
+ Children_Permission (New_Tree),
+ Children_Permission (Orig_Tree));
+ end if;
+
+ when Reference =>
+ Check_Is_More_Restrictive_Tree_Than
+ (Get_All (Orig_Tree), Children_Permission (New_Tree), E);
+
+ when Array_Component =>
+ Check_Is_More_Restrictive_Tree_Than
+ (Get_Elem (Orig_Tree), Children_Permission (New_Tree), E);
+
+ when Record_Component =>
+ declare
+ Comp : Perm_Tree_Access;
+ begin
+ Comp := Perm_Tree_Maps.Get_First
+ (Component (Orig_Tree));
+ while Comp /= null loop
+ Check_Is_More_Restrictive_Tree_Than
+ (Comp, Children_Permission (New_Tree), E);
+ Comp := Perm_Tree_Maps.Get_Next
+ (Component (Orig_Tree));
+ end loop;
+ end;
end case;
- RHS := Next (RHS);
- end loop;
- elsif Nkind (Expression (PAA)) = N_Aggregate
- and then Component_Associations (Expression (PAA)) /= No_List
- then
- -- global => (mode => foo,
- -- mode => (bar, baz))
- -- A mixture of things
+ when Reference =>
+ case Kind (Orig_Tree) is
+ when Entire_Object =>
+ Check_Is_Less_Restrictive_Tree_Than
+ (Get_All (New_Tree), Children_Permission (Orig_Tree), E);
- declare
- CA : constant List_Id :=
- Component_Associations (Expression (PAA));
- begin
- Row := First (CA);
- while Present (Row) loop
- pragma Assert (List_Length (Choices (Row)) = 1);
- The_Mode := Chars (First (Choices (Row)));
- RHS := Expression (Row);
-
- case Nkind (RHS) is
- when N_Aggregate =>
- RHS := First (Expressions (RHS));
- while Present (RHS) loop
- case Nkind (RHS) is
- when N_Numeric_Or_String_Literal =>
- Process (The_Mode, Original_Node (RHS));
-
- when others =>
- Process (The_Mode, RHS);
- end case;
- RHS := Next (RHS);
- end loop;
+ when Reference =>
+ Check_Is_Less_Restrictive_Tree
+ (Get_All (New_Tree), Get_All (Orig_Tree), E);
- when N_Identifier
- | N_Expanded_Name
- =>
- Process (The_Mode, RHS);
+ when others =>
+ raise Program_Error;
+ end case;
- when N_Null =>
- null;
+ when Array_Component =>
+ case Kind (Orig_Tree) is
+ when Entire_Object =>
+ Check_Is_Less_Restrictive_Tree_Than
+ (Get_Elem (New_Tree), Children_Permission (Orig_Tree), E);
- when N_Numeric_Or_String_Literal =>
- Process (The_Mode, Original_Node (RHS));
+ when Array_Component =>
+ Check_Is_Less_Restrictive_Tree
+ (Get_Elem (New_Tree), Get_Elem (Orig_Tree), E);
- when others =>
- raise Program_Error;
- end case;
- Row := Next (Row);
- end loop;
- end;
+ when others =>
+ raise Program_Error;
+ end case;
- else
- raise Program_Error;
- end if;
- end;
- end Check_Globals;
+ when Record_Component =>
+ declare
+ CompN : Perm_Tree_Access;
+ begin
+ CompN :=
+ Perm_Tree_Maps.Get_First (Component (New_Tree));
+ case Kind (Orig_Tree) is
+ when Entire_Object =>
+ while CompN /= null loop
+ Check_Is_Less_Restrictive_Tree_Than
+ (CompN, Children_Permission (Orig_Tree), E);
+
+ CompN :=
+ Perm_Tree_Maps.Get_Next (Component (New_Tree));
+ end loop;
- ----------------
- -- Check_List --
- ----------------
+ when Record_Component =>
+ declare
- procedure Check_List (L : List_Id) is
- N : Node_Id;
- begin
- N := First (L);
- while Present (N) loop
- Check_Node (N);
- Next (N);
- end loop;
- end Check_List;
+ KeyO : Perm_Tree_Maps.Key_Option;
+ CompO : Perm_Tree_Access;
+ begin
+ KeyO := Perm_Tree_Maps.Get_First_Key
+ (Component (Orig_Tree));
+ while KeyO.Present loop
+ pragma Assert (CompO /= null);
+
+ Check_Is_Less_Restrictive_Tree (CompN, CompO, E);
+
+ KeyO := Perm_Tree_Maps.Get_Next_Key
+ (Component (Orig_Tree));
+ CompN := Perm_Tree_Maps.Get
+ (Component (New_Tree), KeyO.K);
+ CompO := Perm_Tree_Maps.Get
+ (Component (Orig_Tree), KeyO.K);
+ end loop;
+ end;
- --------------------------
- -- Check_Loop_Statement --
- --------------------------
+ when others =>
+ raise Program_Error;
+ end case;
+ end;
+ end case;
+ end Check_Is_Less_Restrictive_Tree;
- procedure Check_Loop_Statement (Loop_N : Node_Id) is
+ --------------------------
+ -- Perm_Error_Loop_Exit --
+ --------------------------
+
+ procedure Perm_Error_Loop_Exit
+ (E : Entity_Id;
+ Loop_Id : Node_Id;
+ Perm : Perm_Kind;
+ Found_Perm : Perm_Kind)
+ is
+ begin
+ Error_Msg_Node_2 := Loop_Id;
+ Error_Msg_N ("insufficient permission for & when exiting loop &", E);
+ Perm_Mismatch (Exp_Perm => Perm,
+ Act_Perm => Found_Perm,
+ N => Loop_Id);
+ end Perm_Error_Loop_Exit;
-- Local variables
- Loop_Name : constant Entity_Id := Entity (Identifier (Loop_N));
+ Loop_Name : constant Entity_Id := Entity (Identifier (Stmt));
Loop_Env : constant Perm_Env_Access := new Perm_Env;
+ Scheme : constant Node_Id := Iteration_Scheme (Stmt);
+
+ -- Start of processing for Check_Loop_Statement
begin
-- Save environment prior to the loop
@@ -1650,7 +2134,7 @@ package body Sem_SPARK is
-- Otherwise, the loop exit environment remains empty until it is
-- populated by analyzing exit statements.
- if Present (Iteration_Scheme (Loop_N)) then
+ if Present (Iteration_Scheme (Stmt)) then
declare
Exit_Env : constant Perm_Env_Access := new Perm_Env;
@@ -1662,8 +2146,41 @@ package body Sem_SPARK is
-- Analyze loop
- Check_Node (Iteration_Scheme (Loop_N));
- Check_List (Statements (Loop_N));
+ if Present (Scheme) then
+
+ -- Case of a WHILE loop
+
+ if Present (Condition (Scheme)) then
+ Check_Expression (Condition (Scheme), Read);
+
+ -- Case of a FOR loop
+
+ else
+ declare
+ Param_Spec : constant Node_Id :=
+ Loop_Parameter_Specification (Scheme);
+ Iter_Spec : constant Node_Id := Iterator_Specification (Scheme);
+ begin
+ if Present (Param_Spec) then
+ Check_Expression
+ (Discrete_Subtype_Definition (Param_Spec), Read);
+ else
+ Check_Expression (Name (Iter_Spec), Read);
+ if Present (Subtype_Indication (Iter_Spec)) then
+ Check_Expression (Subtype_Indication (Iter_Spec), Read);
+ end if;
+ end if;
+ end;
+ end if;
+ end if;
+
+ Check_List (Statements (Stmt));
+
+ -- Check that environment gets less restrictive at end of loop
+
+ Check_Is_Less_Restrictive_Env
+ (Exiting_Env => Current_Perm_Env,
+ Entry_Env => Loop_Env.all);
-- Set environment to the one for exiting the loop
@@ -1697,24 +2214,20 @@ package body Sem_SPARK is
----------------
procedure Check_Node (N : Node_Id) is
- Mode_Before : constant Checking_Mode := Current_Checking_Mode;
begin
case Nkind (N) is
when N_Declaration =>
Check_Declaration (N);
- when N_Subexpr =>
- Check_Expression (N);
-
- when N_Subtype_Indication =>
- Check_Node (Constraint (N));
-
when N_Body_Stub =>
Check_Node (Get_Body_From_Stub (N));
when N_Statement_Other_Than_Procedure_Call =>
Check_Statement (N);
+ when N_Procedure_Call_Statement =>
+ Check_Call_Statement (N);
+
when N_Package_Body =>
Check_Package_Body (N);
@@ -1728,124 +2241,13 @@ package body Sem_SPARK is
Check_List (Declarations (N));
when N_Package_Declaration =>
- declare
- Spec : constant Node_Id := Specification (N);
-
- begin
- Current_Checking_Mode := Read;
- Check_List (Visible_Declarations (Spec));
- Check_List (Private_Declarations (Spec));
-
- Return_Declarations (Visible_Declarations (Spec));
- Return_Declarations (Private_Declarations (Spec));
- end;
-
- when N_Iteration_Scheme =>
- Current_Checking_Mode := Read;
- Check_Node (Condition (N));
- Check_Node (Iterator_Specification (N));
- Check_Node (Loop_Parameter_Specification (N));
-
- when N_Case_Expression_Alternative =>
- Current_Checking_Mode := Read;
- Check_List (Discrete_Choices (N));
- Current_Checking_Mode := Mode_Before;
- Check_Node (Expression (N));
-
- when N_Case_Statement_Alternative =>
- Current_Checking_Mode := Read;
- Check_List (Discrete_Choices (N));
- Current_Checking_Mode := Mode_Before;
- Check_List (Statements (N));
-
- when N_Component_Association =>
- Check_Node (Expression (N));
+ Check_Package_Spec (N);
when N_Handled_Sequence_Of_Statements =>
Check_List (Statements (N));
- when N_Parameter_Association =>
- Check_Node (Explicit_Actual_Parameter (N));
-
- when N_Range_Constraint =>
- Check_Node (Range_Expression (N));
-
- when N_Index_Or_Discriminant_Constraint =>
- Check_List (Constraints (N));
-
- -- Checking should not be called directly on these nodes
-
- when N_Abortable_Part
- | N_Accept_Alternative
- | N_Access_Definition
- | N_Access_Function_Definition
- | N_Access_Procedure_Definition
- | N_Access_To_Object_Definition
- | N_Aspect_Specification
- | N_Compilation_Unit
- | N_Compilation_Unit_Aux
- | N_Component_Clause
- | N_Component_Definition
- | N_Component_List
- | N_Constrained_Array_Definition
- | N_Contract
- | N_Decimal_Fixed_Point_Definition
- | N_Defining_Character_Literal
- | N_Defining_Identifier
- | N_Defining_Operator_Symbol
- | N_Defining_Program_Unit_Name
- | N_Delay_Alternative
- | N_Derived_Type_Definition
- | N_Designator
- | N_Discriminant_Specification
- | N_Elsif_Part
- | N_Entry_Body_Formal_Part
- | N_Enumeration_Type_Definition
- | N_Entry_Call_Alternative
- | N_Entry_Index_Specification
- | N_Error
- | N_Exception_Handler
- | N_Floating_Point_Definition
- | N_Formal_Decimal_Fixed_Point_Definition
- | N_Formal_Derived_Type_Definition
- | N_Formal_Discrete_Type_Definition
- | N_Formal_Floating_Point_Definition
- | N_Formal_Incomplete_Type_Definition
- | N_Formal_Modular_Type_Definition
- | N_Formal_Ordinary_Fixed_Point_Definition
- | N_Formal_Private_Type_Definition
- | N_Formal_Signed_Integer_Type_Definition
- | N_Generic_Association
- | N_Mod_Clause
- | N_Modular_Type_Definition
- | N_Ordinary_Fixed_Point_Definition
- | N_Package_Specification
- | N_Parameter_Specification
- | N_Pragma_Argument_Association
- | N_Protected_Definition
- | N_Push_Pop_xxx_Label
- | N_Real_Range_Specification
- | N_Record_Definition
- | N_SCIL_Dispatch_Table_Tag_Init
- | N_SCIL_Dispatching_Call
- | N_SCIL_Membership_Test
- | N_Signed_Integer_Type_Definition
- | N_Subunit
- | N_Task_Definition
- | N_Terminate_Alternative
- | N_Triggering_Alternative
- | N_Unconstrained_Array_Definition
- | N_Unused_At_Start
- | N_Unused_At_End
- | N_Variant
- | N_Variant_Part
- =>
- raise Program_Error;
-
- -- Unsupported constructs in SPARK
-
- when N_Iterated_Component_Association =>
- Error_Msg_N ("unsupported construct in SPARK", N);
+ when N_Pragma =>
+ Check_Pragma (N);
-- Ignored constructs for pointer checking
@@ -1877,7 +2279,6 @@ package body Sem_SPARK is
| N_Others_Choice
| N_Package_Instantiation
| N_Package_Renaming_Declaration
- | N_Pragma
| N_Procedure_Instantiation
| N_Record_Representation_Clause
| N_Subprogram_Declaration
@@ -1890,19 +2291,16 @@ package body Sem_SPARK is
| N_Variable_Reference_Marker
| N_Discriminant_Association
- -- ??? check whether we should do sth special for
- -- N_Discriminant_Association, or maybe raise a program error.
+ -- ??? check whether we should do something special for
+ -- N_Discriminant_Association, or maybe raise Program_Error.
=>
null;
- -- The following nodes are rewritten by semantic analysis
- when N_Single_Protected_Declaration
- | N_Single_Task_Declaration
- =>
+ -- Checking should not be called directly on these nodes
+
+ when others =>
raise Program_Error;
end case;
-
- Current_Checking_Mode := Mode_Before;
end Check_Node;
------------------------
@@ -1910,179 +2308,207 @@ package body Sem_SPARK is
------------------------
procedure Check_Package_Body (Pack : Node_Id) is
- Saved_Env : Perm_Env;
- CorSp : Node_Id;
+ Save_In_Elab : constant Boolean := Inside_Elaboration;
+ Spec : constant Node_Id :=
+ Package_Specification (Corresponding_Spec (Pack));
+ Prag : constant Node_Id := SPARK_Pragma (Defining_Entity (Pack));
+ Saved_Env : Perm_Env;
begin
- if Present (SPARK_Pragma (Defining_Entity (Pack, False))) then
- if Get_SPARK_Mode_From_Annotation
- (SPARK_Pragma (Defining_Entity (Pack))) /= Opt.On
- then
- return;
- end if;
- else
+ -- Only SPARK bodies are analyzed
+
+ if No (Prag)
+ or else Get_SPARK_Mode_From_Annotation (Prag) /= Opt.On
+ then
return;
end if;
- CorSp := Parent (Corresponding_Spec (Pack));
- while Nkind (CorSp) /= N_Package_Specification loop
- CorSp := Parent (CorSp);
- end loop;
+ Inside_Elaboration := True;
+
+ -- Save environment and put a new one in place
- Check_List (Visible_Declarations (CorSp));
+ Move_Env (Current_Perm_Env, Saved_Env);
- -- Save environment
+ -- Reanalyze package spec to have its variables in the environment
- Copy_Env (Current_Perm_Env, Saved_Env);
- Check_List (Private_Declarations (CorSp));
+ Check_List (Visible_Declarations (Spec));
+ Check_List (Private_Declarations (Spec));
- -- Set mode to Read, and then analyze declarations and statements
+ -- Check declarations and statements in the special mode for elaboration
- Current_Checking_Mode := Read;
Check_List (Declarations (Pack));
Check_Node (Handled_Statement_Sequence (Pack));
- -- Check RW for every stateful variable (i.e. in declarations)
-
- Return_Declarations (Private_Declarations (CorSp));
- Return_Declarations (Visible_Declarations (CorSp));
- Return_Declarations (Declarations (Pack));
+ -- Restore the saved environment and free the current one
- -- Restore previous environment (i.e. delete every nonvisible
- -- declaration) from environment.
+ Move_Env (Saved_Env, Current_Perm_Env);
- Free_Env (Current_Perm_Env);
- Copy_Env (Saved_Env, Current_Perm_Env);
+ Inside_Elaboration := Save_In_Elab;
end Check_Package_Body;
- --------------------
- -- Check_Param_In --
- --------------------
+ ------------------------
+ -- Check_Package_Spec --
+ ------------------------
+
+ procedure Check_Package_Spec (Pack : Node_Id) is
+ Save_In_Elab : constant Boolean := Inside_Elaboration;
+ Spec : constant Node_Id := Specification (Pack);
+ Saved_Env : Perm_Env;
- procedure Check_Param_In (Formal : Entity_Id; Actual : Node_Id) is
- Mode : constant Entity_Kind := Ekind (Formal);
- Mode_Before : constant Checking_Mode := Current_Checking_Mode;
begin
- case Formal_Kind'(Mode) is
+ Inside_Elaboration := True;
- -- Formal IN parameter
+ -- Save environment and put a new one in place
- when E_In_Parameter =>
+ Move_Env (Current_Perm_Env, Saved_Env);
- -- Formal IN parameter, access type
+ -- Check declarations in the special mode for elaboration
- if Is_Access_Type (Etype (Formal)) then
+ Check_List (Visible_Declarations (Spec));
+ Check_List (Private_Declarations (Spec));
- -- Formal IN parameter, access to variable type
+ -- Restore the saved environment and free the current one
- if not Is_Access_Constant (Etype (Formal)) then
+ Move_Env (Saved_Env, Current_Perm_Env);
- -- Formal IN parameter, named/anonymous access-to-variable
- -- type.
- --
- -- In SPARK, IN access-to-variable is an observe operation
- -- for a function, and a borrow operation for a procedure.
+ Inside_Elaboration := Save_In_Elab;
+ end Check_Package_Spec;
- if Ekind (Scope (Formal)) = E_Function then
- Current_Checking_Mode := Observe;
- Check_Node (Actual);
- else
- Current_Checking_Mode := Borrow;
- Check_Node (Actual);
- end if;
+ -------------------------------
+ -- Check_Parameter_Or_Global --
+ -------------------------------
- -- Formal IN parameter, access-to-constant type
- -- Formal IN parameter, access-to-named-constant type
+ procedure Check_Parameter_Or_Global
+ (Expr : Node_Id;
+ Typ : Entity_Id;
+ Kind : Formal_Kind;
+ Subp : Entity_Id;
+ Global_Var : Boolean)
+ is
+ Mode : Checking_Mode;
+ Status : Error_Status;
+
+ begin
+ if not Global_Var
+ and then Is_Anonymous_Access_Type (Typ)
+ then
+ Check_Source_Of_Borrow_Or_Observe (Expr, Status);
- elsif not Is_Anonymous_Access_Type (Etype (Formal)) then
- Error_Msg_N ("assignment not allowed, Ownership Aspect"
- & " False (Named general access type)",
- Formal);
+ if Status /= OK then
+ return;
+ end if;
+ end if;
- -- Formal IN parameter, access to anonymous constant type
+ case Kind is
+ when E_In_Parameter =>
- else
- Current_Checking_Mode := Observe;
- Check_Node (Actual);
- end if;
+ -- Inputs of functions have R permission only
- -- Formal IN parameter, composite type
+ if Ekind (Subp) = E_Function then
+ Mode := Read;
- elsif Is_Deep (Etype (Formal)) then
+ -- Input global variables have R permission only
- -- Composite formal types should be named
- -- Formal IN parameter, composite named type
+ elsif Global_Var then
+ Mode := Read;
- Current_Checking_Mode := Observe;
- Check_Node (Actual);
- end if;
+ -- Anonymous access to constant is an observe
- when E_Out_Parameter
- | E_In_Out_Parameter
- =>
- null;
- end case;
+ elsif Is_Anonymous_Access_Type (Typ)
+ and then Is_Access_Constant (Typ)
+ then
+ Mode := Observe;
- Current_Checking_Mode := Mode_Before;
- end Check_Param_In;
+ -- Other access types are a borrow
- ----------------------
- -- Check_Param_Out --
- ----------------------
+ elsif Is_Access_Type (Typ) then
+ Mode := Borrow;
- procedure Check_Param_Out (Formal : Entity_Id; Actual : Node_Id) is
- Mode : constant Entity_Kind := Ekind (Formal);
- Mode_Before : constant Checking_Mode := Current_Checking_Mode;
+ -- Deep types other than access types define an observe
- begin
- case Formal_Kind'(Mode) is
+ elsif Is_Deep (Typ) then
+ Mode := Observe;
- -- Formal OUT/IN OUT parameter
+ -- Otherwise the variable is read
- when E_Out_Parameter
- | E_In_Out_Parameter
- =>
+ else
+ Mode := Read;
+ end if;
- -- Formal OUT/IN OUT parameter, access type
+ when E_Out_Parameter =>
+ Mode := Assign;
- if Is_Access_Type (Etype (Formal)) then
+ when E_In_Out_Parameter =>
+ Mode := Move;
+ end case;
- -- Formal OUT/IN OUT parameter, access to variable type
+ Check_Expression (Expr, Mode);
+ end Check_Parameter_Or_Global;
- if not Is_Access_Constant (Etype (Formal)) then
+ procedure Check_Globals_Inst is
+ new Handle_Globals (Check_Parameter_Or_Global);
- -- Cannot have anonymous out access parameter
- -- Formal out/in out parameter, access to named variable
- -- type.
+ procedure Check_Globals (Subp : Entity_Id) renames Check_Globals_Inst;
- Current_Checking_Mode := Move;
- Check_Node (Actual);
+ ------------------
+ -- Check_Pragma --
+ ------------------
- -- Formal out/in out parameter, access to constant type
+ procedure Check_Pragma (Prag : Node_Id) is
+ Prag_Id : constant Pragma_Id := Get_Pragma_Id (Prag);
+ Arg1 : constant Node_Id :=
+ First (Pragma_Argument_Associations (Prag));
+ Arg2 : Node_Id;
- else
- Error_Msg_N ("assignment not allowed, Ownership Aspect False"
- & " (Named general access type)", Formal);
+ begin
+ if Present (Arg1) then
+ Arg2 := Next (Arg1);
+ end if;
- end if;
+ case Prag_Id is
+ when Pragma_Check =>
+ declare
+ Expr : constant Node_Id := Expression (Arg2);
+ begin
+ Check_Expression (Expr, Read);
+ end;
- -- Formal out/in out parameter, composite type
+ -- There is no need to check contracts, as these can only access
+ -- inputs and outputs of the subprogram. Inputs are checked
+ -- independently for R permission. Outputs are checked
+ -- independently to have RW permission on exit.
- elsif Is_Deep (Etype (Formal)) then
+ when Pragma_Contract_Cases
+ | Pragma_Postcondition
+ | Pragma_Precondition
+ | Pragma_Refined_Post
+ =>
+ null;
- -- Composite formal types should be named
- -- Formal out/in out Parameter, Composite Named type.
+ -- The same holds for the initial condition after package
+ -- elaboration, for the different reason that library-level
+ -- variables can only be left in RW state after elaboration.
- Current_Checking_Mode := Borrow;
- Check_Node (Actual);
- end if;
+ when Pragma_Initial_Condition =>
+ null;
- when E_In_Parameter =>
+ -- These pragmas should have been rewritten and/or removed in
+ -- GNATprove mode.
+
+ when Pragma_Assert
+ | Pragma_Assert_And_Cut
+ | Pragma_Assume
+ | Pragma_Compile_Time_Error
+ | Pragma_Compile_Time_Warning
+ | Pragma_Debug
+ | Pragma_Loop_Invariant
+ =>
+ raise Program_Error;
+
+ when others =>
null;
end case;
-
- Current_Checking_Mode := Mode_Before;
- end Check_Param_Out;
+ end Check_Pragma;
-------------------------
-- Check_Safe_Pointers --
@@ -2121,19 +2547,18 @@ package body Sem_SPARK is
Reset (Current_Loops_Envs);
Reset (Current_Loops_Accumulators);
Reset (Current_Perm_Env);
- Reset (Current_Initialization_Map);
end Initialize;
-- Local variables
Prag : Node_Id;
-
-- SPARK_Mode pragma in application
-- Start of processing for Check_Safe_Pointers
begin
Initialize;
+
case Nkind (N) is
when N_Compilation_Unit =>
Check_Safe_Pointers (Unit (N));
@@ -2143,10 +2568,9 @@ package body Sem_SPARK is
| N_Subprogram_Body
=>
Prag := SPARK_Pragma (Defining_Entity (N));
+
if Present (Prag) then
- if Get_SPARK_Mode_From_Annotation (Prag) = Opt.Off then
- return;
- else
+ if Get_SPARK_Mode_From_Annotation (Prag) = Opt.On then
Check_Node (N);
end if;
@@ -2163,428 +2587,361 @@ package body Sem_SPARK is
end case;
end Check_Safe_Pointers;
- ---------------------
- -- Check_Statement --
- ---------------------
+ ---------------------------------------
+ -- Check_Source_Of_Borrow_Or_Observe --
+ ---------------------------------------
- procedure Check_Statement (Stmt : Node_Id) is
- Mode_Before : constant Checking_Mode := Current_Checking_Mode;
- State_N : Perm_Kind;
- Check : Boolean := True;
- St_Name : Node_Id;
- Ty_St_Name : Node_Id;
+ procedure Check_Source_Of_Borrow_Or_Observe
+ (Expr : Node_Id;
+ Status : out Error_Status)
+ is
+ Root : Entity_Id;
- function Get_Root (Comp_Stmt : Node_Id) return Node_Id;
- -- Return the root of the name given as input
+ begin
+ if Is_Path_Expression (Expr) then
+ Root := Get_Root_Object (Expr);
+ else
+ Root := Empty;
+ end if;
- function Get_Root (Comp_Stmt : Node_Id) return Node_Id is
- begin
- case Nkind (Comp_Stmt) is
- when N_Identifier
- | N_Expanded_Name
- => return Comp_Stmt;
+ Status := OK;
- when N_Type_Conversion
- | N_Unchecked_Type_Conversion
- | N_Qualified_Expression
- =>
- return Get_Root (Expression (Comp_Stmt));
+ -- SPARK RM 3.10(3): If the target of an assignment operation is an
+ -- object of an anonymous access-to-object type (including copy-in for
+ -- a parameter), then the source shall be a name denoting a part of a
+ -- stand-alone object, a part of a parameter, or a call to a traversal
+ -- function.
- when N_Parameter_Specification =>
- return Get_Root (Defining_Identifier (Comp_Stmt));
+ if No (Root) then
+ if Nkind (Expr) = N_Function_Call then
+ Error_Msg_N
+ ("incorrect borrow or observe (SPARK RM 3.10(3))", Expr);
+ Error_Msg_N
+ ("\function called must be a traversal function", Expr);
+ else
+ Error_Msg_N
+ ("incorrect borrow or observe (SPARK RM 3.10(3))", Expr);
+ Error_Msg_N
+ ("\expression must be part of stand-alone object or parameter",
+ Expr);
+ end if;
- when N_Selected_Component
- | N_Indexed_Component
- | N_Slice
- | N_Explicit_Dereference
- =>
- return Get_Root (Prefix (Comp_Stmt));
+ Status := Error;
+ end if;
+ end Check_Source_Of_Borrow_Or_Observe;
- when others =>
- raise Program_Error;
- end case;
- end Get_Root;
+ ---------------------
+ -- Check_Statement --
+ ---------------------
+ procedure Check_Statement (Stmt : Node_Id) is
begin
case N_Statement_Other_Than_Procedure_Call'(Nkind (Stmt)) is
+
+ -- An entry call is handled like other calls
+
when N_Entry_Call_Statement =>
Check_Call_Statement (Stmt);
- -- Move right-hand side first, and then assign left-hand side
+ -- An assignment may correspond to a move, a borrow, or an observe
when N_Assignment_Statement =>
+ declare
+ Target : constant Node_Id := Name (Stmt);
+ begin
+ Check_Assignment (Target => Target,
+ Expr => Expression (Stmt));
- St_Name := Name (Stmt);
- Ty_St_Name := Etype (Name (Stmt));
-
- -- Check that is not a *general* access type
-
- if Has_Ownership_Aspect_True (St_Name, "assigning to") then
-
- -- Assigning to access type
-
- if Is_Access_Type (Ty_St_Name) then
-
- -- Assigning to access to variable type
-
- if not Is_Access_Constant (Ty_St_Name) then
-
- -- Assigning to named access to variable type
-
- if not Is_Anonymous_Access_Type (Ty_St_Name) then
- Current_Checking_Mode := Move;
-
- -- Assigning to anonymous access to variable type
-
- else
- -- Target /= source root
-
- if Nkind_In (Expression (Stmt), N_Allocator, N_Null)
- or else Entity (St_Name) /=
- Entity (Get_Root (Expression (Stmt)))
- then
- Error_Msg_N ("assignment not allowed, anonymous "
- & "access Object with Different Root",
- Stmt);
- Check := False;
-
- -- Target = source root
-
- else
- -- Here we do nothing on the source nor on the
- -- target. However, we check the the legality rule:
- -- "The source shall be an owning access object
- -- denoted by a name that is not in the observed
- -- state".
-
- State_N := Get_Perm (Expression (Stmt));
- if State_N = Observed then
- Error_Msg_N ("assignment not allowed, Anonymous "
- & "access object with the same root"
- & " but source Observed", Stmt);
- Check := False;
- end if;
- end if;
- end if;
-
- -- else access-to-constant
-
- -- Assigning to anonymous access-to-constant type
-
- elsif Is_Anonymous_Access_Type (Ty_St_Name) then
-
- -- ??? Check the follwing condition. We may have to
- -- add that the root is in the observed state too.
-
- State_N := Get_Perm (Expression (Stmt));
- if State_N /= Observed then
- Error_Msg_N ("assignment not allowed, anonymous "
- & "access-to-constant object not in "
- & "the observed state)", Stmt);
- Check := False;
-
- else
- Error_Msg_N ("?here check accessibility level cited in"
- & " the second legality rule of assign",
- Stmt);
- Check := False;
- end if;
-
- -- Assigning to named access-to-constant type:
- -- This case should have been detected when checking
- -- Has_Onwership_Aspect_True (Name (Stmt), "msg").
-
- else
- raise Program_Error;
- end if;
-
- -- Assigning to composite (deep) type.
-
- elsif Is_Deep (Ty_St_Name) then
- if Ekind_In (Ty_St_Name,
- E_Record_Type,
- E_Record_Subtype)
- then
- declare
- Elmt : Entity_Id :=
- First_Component_Or_Discriminant (Ty_St_Name);
-
- begin
- while Present (Elmt) loop
- if Is_Anonymous_Access_Type (Etype (Elmt)) or
- Ekind (Elmt) = E_General_Access_Type
- then
- Error_Msg_N ("assignment not allowed, Ownership "
- & "Aspect False (Components have "
- & "Ownership Aspect False)", Stmt);
- Check := False;
- exit;
- end if;
-
- Next_Component_Or_Discriminant (Elmt);
- end loop;
- end;
-
- -- Record types are always named so this is a move
-
- if Check then
- Current_Checking_Mode := Move;
- end if;
-
- elsif Ekind_In (Ty_St_Name,
- E_Array_Type,
- E_Array_Subtype)
- and then Check
- then
- Current_Checking_Mode := Move;
- end if;
-
- -- Now handle legality rules of using a borrowed, observed,
- -- or moved name as a prefix in an assignment.
-
- else
- if Nkind_In (St_Name,
- N_Attribute_Reference,
- N_Expanded_Name,
- N_Explicit_Dereference,
- N_Indexed_Component,
- N_Reference,
- N_Selected_Component,
- N_Slice)
- then
-
- if Is_Access_Type (Etype (Prefix (St_Name))) or
- Is_Deep (Etype (Prefix (St_Name)))
- then
-
- -- We set the Check variable to True so that we can
- -- Check_Node of the expression and the name first
- -- under the assumption of Current_Checking_Mode =
- -- Read => nothing to be done for the RHS if the
- -- following check on the expression fails, and
- -- Current_Checking_Mode := Assign => the name should
- -- not be borrowed or observed so that we can use it
- -- as a prefix in the target of an assignement.
- --
- -- Note that we do not need to check the OA here
- -- because we are allowed to read and write "through"
- -- an object of OAF (example: traversing a DS).
-
- Check := True;
- end if;
- end if;
-
- if Nkind_In (Expression (Stmt),
- N_Attribute_Reference,
- N_Expanded_Name,
- N_Explicit_Dereference,
- N_Indexed_Component,
- N_Reference,
- N_Selected_Component,
- N_Slice)
- then
+ -- ??? We need a rule that forbids targets of assignment for
+ -- which the path is not known, for example when there is a
+ -- function call involved (which includes calls to traversal
+ -- functions). Otherwise there is no way to update the
+ -- corresponding path permission.
- if Is_Access_Type (Etype (Prefix (Expression (Stmt))))
- or else Is_Deep (Etype (Prefix (Expression (Stmt))))
- then
- Current_Checking_Mode := Observe;
- Check := True;
- end if;
- end if;
+ if No (Get_Root_Object
+ (Target, Through_Traversal => False))
+ then
+ Error_Msg_N ("illegal target for assignment", Target);
+ return;
end if;
- if Check then
- Check_Node (Expression (Stmt));
- Current_Checking_Mode := Assign;
- Check_Node (St_Name);
- end if;
- end if;
+ Check_Expression (Target, Assign);
+ end;
when N_Block_Statement =>
- declare
- Saved_Env : Perm_Env;
- begin
- -- Save environment
-
- Copy_Env (Current_Perm_Env, Saved_Env);
+ Check_List (Declarations (Stmt));
+ Check_Node (Handled_Statement_Sequence (Stmt));
- -- Analyze declarations and Handled_Statement_Sequences
+ -- Remove local borrowers and observers
- Current_Checking_Mode := Read;
- Check_List (Declarations (Stmt));
- Check_Node (Handled_Statement_Sequence (Stmt));
-
- -- Restore environment
+ declare
+ Decl : Node_Id := First (Declarations (Stmt));
+ Var : Entity_Id;
+ begin
+ while Present (Decl) loop
+ if Nkind (Decl) = N_Object_Declaration then
+ Var := Defining_Identifier (Decl);
+ Remove (Current_Borrowers, Var);
+ Remove (Current_Observers, Var);
+ end if;
- Free_Env (Current_Perm_Env);
- Copy_Env (Saved_Env, Current_Perm_Env);
+ Next (Decl);
+ end loop;
end;
when N_Case_Statement =>
declare
+ Alt : Node_Id;
Saved_Env : Perm_Env;
-
- -- Accumulator for the different branches
-
- New_Env : Perm_Env;
- Elmt : Node_Id := First (Alternatives (Stmt));
+ -- Copy of environment for analysis of the different cases
+ New_Env : Perm_Env;
+ -- Accumulator for the different cases
begin
- Current_Checking_Mode := Read;
- Check_Node (Expression (Stmt));
- Current_Checking_Mode := Mode_Before;
+ Check_Expression (Expression (Stmt), Read);
-- Save environment
Copy_Env (Current_Perm_Env, Saved_Env);
- -- Here we have the original env in saved, current with a fresh
- -- copy, and new aliased.
-
-- First alternative
- Check_Node (Elmt);
- Next (Elmt);
- Copy_Env (Current_Perm_Env, New_Env);
- Free_Env (Current_Perm_Env);
+ Alt := First (Alternatives (Stmt));
+ Check_List (Statements (Alt));
+ Next (Alt);
+
+ -- Cleanup
+
+ Move_Env (Current_Perm_Env, New_Env);
-- Other alternatives
- while Present (Elmt) loop
+ while Present (Alt) loop
-- Restore environment
Copy_Env (Saved_Env, Current_Perm_Env);
- Check_Node (Elmt);
- Next (Elmt);
+
+ -- Next alternative
+
+ Check_List (Statements (Alt));
+ Next (Alt);
+
+ -- Merge Current_Perm_Env into New_Env
+
+ Merge_Env (Source => Current_Perm_Env, Target => New_Env);
end loop;
- Copy_Env (Saved_Env, Current_Perm_Env);
- Free_Env (New_Env);
+ Move_Env (New_Env, Current_Perm_Env);
Free_Env (Saved_Env);
end;
- when N_Delay_Relative_Statement =>
- Check_Node (Expression (Stmt));
-
- when N_Delay_Until_Statement =>
- Check_Node (Expression (Stmt));
+ when N_Delay_Relative_Statement
+ | N_Delay_Until_Statement
+ =>
+ Check_Expression (Expression (Stmt), Read);
when N_Loop_Statement =>
Check_Loop_Statement (Stmt);
- -- If deep type expression, then move, else read
-
when N_Simple_Return_Statement =>
- case Nkind (Expression (Stmt)) is
- when N_Empty =>
+ declare
+ Subp : constant Entity_Id :=
+ Return_Applies_To (Return_Statement_Entity (Stmt));
+ Expr : constant Node_Id := Expression (Stmt);
+ begin
+ if Present (Expression (Stmt)) then
declare
- -- ??? This does not take into account the fact that
- -- a simple return inside an extended return statement
- -- applies to the extended return statement.
- Subp : constant Entity_Id :=
- Return_Applies_To (Return_Statement_Entity (Stmt));
+ Return_Typ : constant Entity_Id :=
+ Etype (Expression (Stmt));
+
begin
- Return_Globals (Subp);
- end;
+ -- SPARK RM 3.10(5): A return statement that applies
+ -- to a traversal function that has an anonymous
+ -- access-to-constant (respectively, access-to-variable)
+ -- result type, shall return either the literal null
+ -- or an access object denoted by a direct or indirect
+ -- observer (respectively, borrower) of the traversed
+ -- parameter.
+
+ if Is_Anonymous_Access_Type (Return_Typ) then
+ pragma Assert (Is_Traversal_Function (Subp));
+
+ if Nkind (Expr) /= N_Null then
+ declare
+ Expr_Root : constant Entity_Id :=
+ Get_Root_Object (Expr);
+ Param : constant Entity_Id :=
+ First_Formal (Subp);
+ begin
+ if Param /= Expr_Root then
+ Error_Msg_NE
+ ("returned value must be rooted in "
+ & "traversed parameter & "
+ & "(SPARK RM 3.10(5))",
+ Stmt, Param);
+ end if;
+ end;
+ end if;
- when others =>
- if Is_Deep (Etype (Expression (Stmt))) then
- Current_Checking_Mode := Move;
- else
- Check := False;
- end if;
+ -- Move expression to caller
- if Check then
- Check_Node (Expression (Stmt));
- end if;
- end case;
+ elsif Is_Deep (Return_Typ) then
+
+ if Is_Path_Expression (Expr) then
+ Check_Expression (Expr, Move);
+
+ else
+ Error_Msg_N
+ ("expression not allowed as source of move",
+ Expr);
+ return;
+ end if;
+
+ else
+ Check_Expression (Expr, Read);
+ end if;
+
+ if Ekind_In (Subp, E_Procedure, E_Entry)
+ and then not No_Return (Subp)
+ then
+ Return_Parameters (Subp);
+ Return_Globals (Subp);
+ end if;
+ end;
+ end if;
+ end;
when N_Extended_Return_Statement =>
- Check_List (Return_Object_Declarations (Stmt));
- Check_Node (Handled_Statement_Sequence (Stmt));
- Return_Declarations (Return_Object_Declarations (Stmt));
declare
- -- ??? This does not take into account the fact that a simple
- -- return inside an extended return statement applies to the
- -- extended return statement.
- Subp : constant Entity_Id :=
+ Subp : constant Entity_Id :=
Return_Applies_To (Return_Statement_Entity (Stmt));
+ Decls : constant List_Id := Return_Object_Declarations (Stmt);
+ Decl : constant Node_Id := Last (Decls);
+ Obj : constant Entity_Id := Defining_Identifier (Decl);
+ Perm : Perm_Kind;
begin
- Return_Globals (Subp);
+ -- SPARK RM 3.10(5): return statement of traversal function
+
+ if Is_Traversal_Function (Subp) then
+ Error_Msg_N
+ ("extended return cannot apply to a traversal function",
+ Stmt);
+ end if;
+
+ Check_List (Return_Object_Declarations (Stmt));
+ Check_Node (Handled_Statement_Sequence (Stmt));
+
+ Perm := Get_Perm (Obj);
+
+ if Perm /= Read_Write then
+ Perm_Error (Decl, Read_Write, Perm);
+ end if;
+
+ if Ekind_In (Subp, E_Procedure, E_Entry)
+ and then not No_Return (Subp)
+ then
+ Return_Parameters (Subp);
+ Return_Globals (Subp);
+ end if;
end;
- -- Nothing to do when exiting a loop. No merge needed
+ -- On loop exit, merge the current permission environment with the
+ -- accumulator for the given loop.
when N_Exit_Statement =>
- null;
+ declare
+ Loop_Name : constant Entity_Id := Loop_Of_Exit (Stmt);
+ Saved_Accumulator : constant Perm_Env_Access :=
+ Get (Current_Loops_Accumulators, Loop_Name);
+ Environment_Copy : constant Perm_Env_Access :=
+ new Perm_Env;
+ begin
+ Copy_Env (Current_Perm_Env, Environment_Copy.all);
- -- Copy environment, run on each branch
+ if Saved_Accumulator = null then
+ Set (Current_Loops_Accumulators,
+ Loop_Name, Environment_Copy);
+ else
+ Merge_Env (Source => Environment_Copy.all,
+ Target => Saved_Accumulator.all);
+ -- ??? Either free Environment_Copy, or change the type
+ -- of loop accumulators to directly store permission
+ -- environments.
+ end if;
+ end;
+
+ -- On branches, analyze each branch independently on a fresh copy of
+ -- the permission environment, then merge the resulting permission
+ -- environments.
when N_If_Statement =>
declare
Saved_Env : Perm_Env;
-
+ New_Env : Perm_Env;
-- Accumulator for the different branches
- New_Env : Perm_Env;
-
begin
- Check_Node (Condition (Stmt));
+ Check_Expression (Condition (Stmt), Read);
-- Save environment
Copy_Env (Current_Perm_Env, Saved_Env);
- -- Here we have the original env in saved, current with a fresh
- -- copy.
-
- -- THEN PART
+ -- THEN branch
Check_List (Then_Statements (Stmt));
- Copy_Env (Current_Perm_Env, New_Env);
- Free_Env (Current_Perm_Env);
+ Move_Env (Current_Perm_Env, New_Env);
- -- Here the new_environment contains curr env after then block
-
- -- ELSIF part
+ -- ELSIF branches
declare
- Elmt : Node_Id;
-
+ Branch : Node_Id;
begin
- Elmt := First (Elsif_Parts (Stmt));
- while Present (Elmt) loop
+ Branch := First (Elsif_Parts (Stmt));
+ while Present (Branch) loop
- -- Transfer into accumulator, and restore from save
+ -- Restore current permission environment
Copy_Env (Saved_Env, Current_Perm_Env);
- Check_Node (Condition (Elmt));
- Check_List (Then_Statements (Stmt));
- Next (Elmt);
+ Check_Expression (Condition (Branch), Read);
+ Check_List (Then_Statements (Branch));
+
+ -- Merge current permission environment
+
+ Merge_Env (Source => Current_Perm_Env, Target => New_Env);
+ Next (Branch);
end loop;
end;
- -- ELSE part
+ -- ELSE branch
- -- Restore environment before if
+ -- Restore current permission environment
Copy_Env (Saved_Env, Current_Perm_Env);
-
- -- Here new environment contains the environment after then and
- -- current the fresh copy of old one.
-
Check_List (Else_Statements (Stmt));
- -- CLEANUP
+ -- Merge current permission environment
- Copy_Env (Saved_Env, Current_Perm_Env);
+ Merge_Env (Source => Current_Perm_Env, Target => New_Env);
+
+ -- Cleanup
- Free_Env (New_Env);
+ Move_Env (New_Env, Current_Perm_Env);
Free_Env (Saved_Env);
end;
+ -- We should ideally ignore the branch after raising an exception,
+ -- so that it is not taken into account in merges. For now, just
+ -- propagate the current environment.
+
+ when N_Raise_Statement =>
+ null;
+
+ when N_Null_Statement =>
+ null;
+
-- Unsupported constructs in SPARK
when N_Abort_Statement
@@ -2599,13 +2956,6 @@ package body Sem_SPARK is
=>
Error_Msg_N ("unsupported construct in SPARK", Stmt);
- -- Ignored constructs for pointer checking
-
- when N_Null_Statement
- | N_Raise_Statement
- =>
- null;
-
-- The following nodes are never generated in GNATprove mode
when N_Compound_Statement
@@ -2615,28 +2965,149 @@ package body Sem_SPARK is
end case;
end Check_Statement;
+ ----------------
+ -- Check_Type --
+ ----------------
+
+ procedure Check_Type (Typ : Entity_Id) is
+ Check_Typ : constant Entity_Id := Underlying_Type (Typ);
+
+ begin
+ case Type_Kind'(Ekind (Check_Typ)) is
+ when Access_Kind =>
+ case Access_Kind'(Ekind (Underlying_Type (Check_Typ))) is
+ when E_Access_Type
+ | E_Anonymous_Access_Type
+ =>
+ null;
+ when E_Access_Subtype =>
+ Check_Type (Base_Type (Check_Typ));
+ when E_Access_Attribute_Type =>
+ Error_Msg_N ("access attribute not allowed in SPARK",
+ Check_Typ);
+ when E_Allocator_Type =>
+ Error_Msg_N ("missing type resolution", Check_Typ);
+ when E_General_Access_Type =>
+ Error_Msg_NE
+ ("general access type & not allowed in SPARK",
+ Check_Typ, Check_Typ);
+ when Access_Subprogram_Kind =>
+ Error_Msg_NE
+ ("access to subprogram type & not allowed in SPARK",
+ Check_Typ, Check_Typ);
+ end case;
+
+ when E_Array_Type
+ | E_Array_Subtype
+ =>
+ Check_Type (Component_Type (Check_Typ));
+
+ when Record_Kind =>
+ if Is_Deep (Check_Typ)
+ and then (Is_Tagged_Type (Check_Typ)
+ or else Is_Class_Wide_Type (Check_Typ))
+ then
+ Error_Msg_NE
+ ("tagged type & cannot be owning in SPARK",
+ Check_Typ, Check_Typ);
+
+ else
+ declare
+ Comp : Entity_Id;
+ begin
+ Comp := First_Component_Or_Discriminant (Check_Typ);
+ while Present (Comp) loop
+ Check_Type (Etype (Comp));
+ Next_Component_Or_Discriminant (Comp);
+ end loop;
+ end;
+ end if;
+
+ when Scalar_Kind
+ | E_String_Literal_Subtype
+ | Protected_Kind
+ | Task_Kind
+ | Incomplete_Kind
+ | E_Exception_Type
+ | E_Subprogram_Type
+ =>
+ null;
+
+ -- The following should not arise as underlying types
+
+ when E_Private_Type
+ | E_Private_Subtype
+ | E_Limited_Private_Type
+ | E_Limited_Private_Subtype
+ =>
+ raise Program_Error;
+ end case;
+ end Check_Type;
+
+ -----------------------------------
+ -- Get_Observed_Or_Borrowed_Expr --
+ -----------------------------------
+
+ function Get_Observed_Or_Borrowed_Expr (Expr : Node_Id) return Node_Id is
+ begin
+ if Is_Traversal_Function_Call (Expr) then
+ return First_Actual (Expr);
+ else
+ return Expr;
+ end if;
+ end Get_Observed_Or_Borrowed_Expr;
+
--------------
-- Get_Perm --
--------------
- function Get_Perm (N : Node_Id) return Perm_Kind is
- Tree_Or_Perm : constant Perm_Or_Tree := Get_Perm_Or_Tree (N);
-
+ function Get_Perm (N : Node_Or_Entity_Id) return Perm_Kind is
begin
- case Tree_Or_Perm.R is
- when Folded =>
- return Tree_Or_Perm.Found_Permission;
+ -- Special case for the object declared in an extended return statement
- when Unfolded =>
- pragma Assert (Tree_Or_Perm.Tree_Access /= null);
- return Permission (Tree_Or_Perm.Tree_Access);
+ if Nkind (N) = N_Defining_Identifier then
+ declare
+ C : constant Perm_Tree_Access :=
+ Get (Current_Perm_Env, Unique_Entity (N));
+ begin
+ pragma Assert (C /= null);
+ return Permission (C);
+ end;
- -- We encoutered a function call, hence the memory area is fresh,
- -- which means that the association permission is RW.
+ -- The expression is a call to a traversal function
- when Function_Call =>
- return Unrestricted;
- end case;
+ elsif Is_Traversal_Function_Call (N) then
+ declare
+ Callee : constant Entity_Id := Get_Called_Entity (N);
+ begin
+ if Is_Access_Constant (Etype (Callee)) then
+ return Read_Only;
+ else
+ return Read_Write;
+ end if;
+ end;
+
+ -- The expression is directly rooted in an object
+
+ elsif Present (Get_Root_Object (N, Through_Traversal => False)) then
+ declare
+ Tree_Or_Perm : constant Perm_Or_Tree := Get_Perm_Or_Tree (N);
+ begin
+ case Tree_Or_Perm.R is
+ when Folded =>
+ return Tree_Or_Perm.Found_Permission;
+
+ when Unfolded =>
+ pragma Assert (Tree_Or_Perm.Tree_Access /= null);
+ return Permission (Tree_Or_Perm.Tree_Access);
+ end case;
+ end;
+
+ -- The expression is a function call, an allocation, or null
+
+ else
+ return Read_Write;
+ end if;
end Get_Perm;
----------------------
@@ -2647,625 +3118,801 @@ package body Sem_SPARK is
begin
case Nkind (N) is
- -- Base identifier. Normally those are the roots of the trees stored
- -- in the permission environment.
-
- when N_Defining_Identifier =>
- raise Program_Error;
-
- when N_Identifier
- | N_Expanded_Name
+ when N_Expanded_Name
+ | N_Identifier
=>
declare
- P : constant Entity_Id := Entity (N);
C : constant Perm_Tree_Access :=
- Get (Current_Perm_Env, Unique_Entity (P));
+ Get (Current_Perm_Env, Unique_Entity (Entity (N)));
+ begin
+ pragma Assert (C /= null);
+ return (R => Unfolded, Tree_Access => C);
+ end;
+ -- For a non-terminal path, we get the permission tree of its
+ -- prefix, and then get the subtree associated with the extension,
+ -- if unfolded. If folded, we return the permission associated with
+ -- children.
+
+ when N_Explicit_Dereference
+ | N_Indexed_Component
+ | N_Selected_Component
+ | N_Slice
+ =>
+ declare
+ C : constant Perm_Or_Tree := Get_Perm_Or_Tree (Prefix (N));
begin
- -- Setting the initialization map to True, so that this
- -- variable cannot be ignored anymore when looking at end
- -- of elaboration of package.
+ case C.R is
- Set (Current_Initialization_Map, Unique_Entity (P), True);
- if C = null then
- -- No null possible here, there are no parents for the path.
- -- This means we are using a global variable without adding
- -- it in environment with a global aspect.
+ -- Some earlier prefix was already folded, return the
+ -- permission found.
- Illegal_Global_Usage (N);
+ when Folded =>
+ return C;
- else
- return (R => Unfolded, Tree_Access => C);
- end if;
+ when Unfolded =>
+ case Kind (C.Tree_Access) is
+
+ -- If the prefix tree is already folded, return the
+ -- children permission.
+
+ when Entire_Object =>
+ return (R => Folded,
+ Found_Permission =>
+ Children_Permission (C.Tree_Access));
+
+ when Reference =>
+ pragma Assert (Nkind (N) = N_Explicit_Dereference);
+ return (R => Unfolded,
+ Tree_Access => Get_All (C.Tree_Access));
+
+ when Record_Component =>
+ pragma Assert (Nkind (N) = N_Selected_Component);
+ declare
+ Comp : constant Entity_Id :=
+ Entity (Selector_Name (N));
+ D : constant Perm_Tree_Access :=
+ Perm_Tree_Maps.Get
+ (Component (C.Tree_Access), Comp);
+ begin
+ pragma Assert (D /= null);
+ return (R => Unfolded,
+ Tree_Access => D);
+ end;
+
+ when Array_Component =>
+ pragma Assert (Nkind (N) = N_Indexed_Component
+ or else
+ Nkind (N) = N_Slice);
+ pragma Assert (Get_Elem (C.Tree_Access) /= null);
+ return (R => Unfolded,
+ Tree_Access => Get_Elem (C.Tree_Access));
+ end case;
+ end case;
end;
- when N_Type_Conversion
+ when N_Qualified_Expression
+ | N_Type_Conversion
| N_Unchecked_Type_Conversion
- | N_Qualified_Expression
=>
return Get_Perm_Or_Tree (Expression (N));
- -- Happening when we try to get the permission of a variable that
- -- is a formal parameter. We get instead the defining identifier
- -- associated with the parameter (which is the one that has been
- -- stored for indexing).
-
- when N_Parameter_Specification =>
- return Get_Perm_Or_Tree (Defining_Identifier (N));
-
- -- We get the permission tree of its prefix, and then get either the
- -- subtree associated with that specific selection, or if we have a
- -- leaf that folds its children, we take the children's permission
- -- and return it using the discriminant Folded.
+ when others =>
+ raise Program_Error;
+ end case;
+ end Get_Perm_Or_Tree;
- when N_Selected_Component =>
- declare
- C : constant Perm_Or_Tree := Get_Perm_Or_Tree (Prefix (N));
+ -------------------
+ -- Get_Perm_Tree --
+ -------------------
- begin
- case C.R is
- when Folded
- | Function_Call
- =>
- return C;
+ function Get_Perm_Tree (N : Node_Id) return Perm_Tree_Access is
+ begin
+ return Set_Perm_Prefixes (N, None);
+ end Get_Perm_Tree;
- when Unfolded =>
- pragma Assert (C.Tree_Access /= null);
- pragma Assert (Kind (C.Tree_Access) = Entire_Object
- or else
- Kind (C.Tree_Access) = Record_Component);
-
- if Kind (C.Tree_Access) = Record_Component then
- declare
- Selected_Component : constant Entity_Id :=
- Entity (Selector_Name (N));
- Selected_C : constant Perm_Tree_Access :=
- Perm_Tree_Maps.Get
- (Component (C.Tree_Access), Selected_Component);
-
- begin
- if Selected_C = null then
- return (R => Unfolded,
- Tree_Access =>
- Other_Components (C.Tree_Access));
+ ---------------------
+ -- Get_Root_Object --
+ ---------------------
- else
- return (R => Unfolded,
- Tree_Access => Selected_C);
- end if;
- end;
+ function Get_Root_Object
+ (Expr : Node_Id;
+ Through_Traversal : Boolean := True) return Entity_Id
+ is
+ begin
+ case Nkind (Expr) is
+ when N_Expanded_Name
+ | N_Identifier
+ =>
+ return Entity (Expr);
- elsif Kind (C.Tree_Access) = Entire_Object then
- return (R => Folded,
- Found_Permission =>
- Children_Permission (C.Tree_Access));
+ when N_Explicit_Dereference
+ | N_Indexed_Component
+ | N_Selected_Component
+ | N_Slice
+ =>
+ return Get_Root_Object (Prefix (Expr), Through_Traversal);
- else
- raise Program_Error;
- end if;
- end case;
- end;
- -- We get the permission tree of its prefix, and then get either the
- -- subtree associated with that specific selection, or if we have a
- -- leaf that folds its children, we take the children's permission
- -- and return it using the discriminant Folded.
+ -- There is no root object for an allocator or NULL
- when N_Indexed_Component
- | N_Slice
+ when N_Allocator
+ | N_Null
=>
- declare
- C : constant Perm_Or_Tree := Get_Perm_Or_Tree (Prefix (N));
+ return Empty;
- begin
- case C.R is
- when Folded
- | Function_Call
- =>
- return C;
+ -- In the case of a call to a traversal function, the root object is
+ -- the root of the traversed parameter. Otherwise there is no root
+ -- object.
- when Unfolded =>
- pragma Assert (C.Tree_Access /= null);
- pragma Assert (Kind (C.Tree_Access) = Entire_Object
- or else
- Kind (C.Tree_Access) = Array_Component);
+ when N_Function_Call =>
+ if Through_Traversal
+ and then Is_Traversal_Function_Call (Expr)
+ then
+ return Get_Root_Object (First_Actual (Expr), Through_Traversal);
+ else
+ return Empty;
+ end if;
- if Kind (C.Tree_Access) = Array_Component then
- pragma Assert (Get_Elem (C.Tree_Access) /= null);
- return (R => Unfolded,
- Tree_Access => Get_Elem (C.Tree_Access));
+ when N_Qualified_Expression
+ | N_Type_Conversion
+ | N_Unchecked_Type_Conversion
+ =>
+ return Get_Root_Object (Expression (Expr), Through_Traversal);
- elsif Kind (C.Tree_Access) = Entire_Object then
- return (R => Folded, Found_Permission =>
- Children_Permission (C.Tree_Access));
+ when others =>
+ raise Program_Error;
+ end case;
+ end Get_Root_Object;
- else
- raise Program_Error;
- end if;
- end case;
- end;
- -- We get the permission tree of its prefix, and then get either the
- -- subtree associated with that specific selection, or if we have a
- -- leaf that folds its children, we take the children's permission
- -- and return it using the discriminant Folded.
+ ---------
+ -- Glb --
+ ---------
- when N_Explicit_Dereference =>
- declare
- C : constant Perm_Or_Tree := Get_Perm_Or_Tree (Prefix (N));
+ function Glb (P1, P2 : Perm_Kind) return Perm_Kind
+ is
+ begin
+ case P1 is
+ when No_Access =>
+ return No_Access;
+
+ when Read_Only =>
+ case P2 is
+ when No_Access
+ | Write_Only
+ =>
+ return No_Access;
- begin
- case C.R is
- when Folded
- | Function_Call
- =>
- return C;
+ when Read_Perm =>
+ return Read_Only;
+ end case;
- when Unfolded =>
- pragma Assert (C.Tree_Access /= null);
- pragma Assert (Kind (C.Tree_Access) = Entire_Object
- or else
- Kind (C.Tree_Access) = Reference);
+ when Write_Only =>
+ case P2 is
+ when No_Access
+ | Read_Only
+ =>
+ return No_Access;
- if Kind (C.Tree_Access) = Reference then
- if Get_All (C.Tree_Access) = null then
+ when Write_Perm =>
+ return Write_Only;
+ end case;
- -- Hash_Table_Error
+ when Read_Write =>
+ return P2;
+ end case;
+ end Glb;
- raise Program_Error;
+ -------------------------
+ -- Has_Array_Component --
+ -------------------------
- else
- return
- (R => Unfolded,
- Tree_Access => Get_All (C.Tree_Access));
- end if;
+ function Has_Array_Component (Expr : Node_Id) return Boolean is
+ begin
+ case Nkind (Expr) is
+ when N_Expanded_Name
+ | N_Identifier
+ =>
+ return False;
- elsif Kind (C.Tree_Access) = Entire_Object then
- return (R => Folded, Found_Permission =>
- Children_Permission (C.Tree_Access));
+ when N_Explicit_Dereference
+ | N_Selected_Component
+ =>
+ return Has_Array_Component (Prefix (Expr));
- else
- raise Program_Error;
- end if;
- end case;
- end;
- -- The name contains a function call, hence the given path is always
- -- new. We do not have to check for anything.
+ when N_Indexed_Component
+ | N_Slice
+ =>
+ return True;
- when N_Function_Call =>
- return (R => Function_Call);
+ when N_Allocator
+ | N_Null
+ | N_Function_Call
+ =>
+ return False;
+
+ when N_Qualified_Expression
+ | N_Type_Conversion
+ | N_Unchecked_Type_Conversion
+ =>
+ return Has_Array_Component (Expression (Expr));
when others =>
raise Program_Error;
end case;
- end Get_Perm_Or_Tree;
+ end Has_Array_Component;
- -------------------
- -- Get_Perm_Tree --
- -------------------
+ --------
+ -- Hp --
+ --------
+
+ procedure Hp (P : Perm_Env) is
+ Elem : Perm_Tree_Maps.Key_Option;
- function Get_Perm_Tree (N : Node_Id) return Perm_Tree_Access is
begin
- case Nkind (N) is
+ Elem := Get_First_Key (P);
+ while Elem.Present loop
+ Print_Node_Briefly (Elem.K);
+ Elem := Get_Next_Key (P);
+ end loop;
+ end Hp;
- -- Base identifier. Normally those are the roots of the trees stored
- -- in the permission environment.
+ --------------------------
+ -- Illegal_Global_Usage --
+ --------------------------
- when N_Defining_Identifier =>
- raise Program_Error;
+ procedure Illegal_Global_Usage (N : Node_Or_Entity_Id) is
+ begin
+ Error_Msg_NE ("cannot use global variable & of deep type", N, N);
+ Error_Msg_N ("\without prior declaration in a Global aspect", N);
+ Errout.Finalize (Last_Call => True);
+ Errout.Output_Messages;
+ Exit_Program (E_Errors);
+ end Illegal_Global_Usage;
- when N_Identifier
- | N_Expanded_Name
+ -------------
+ -- Is_Deep --
+ -------------
+
+ function Is_Deep (Typ : Entity_Id) return Boolean is
+ begin
+ case Type_Kind'(Ekind (Underlying_Type (Typ))) is
+ when Access_Kind =>
+ return True;
+
+ when E_Array_Type
+ | E_Array_Subtype
=>
- declare
- P : constant Node_Id := Entity (N);
- C : constant Perm_Tree_Access :=
- Get (Current_Perm_Env, Unique_Entity (P));
+ return Is_Deep (Component_Type (Typ));
+ when Record_Kind =>
+ declare
+ Comp : Entity_Id;
begin
- -- Setting the initialization map to True, so that this
- -- variable cannot be ignored anymore when looking at end
- -- of elaboration of package.
+ Comp := First_Component_Or_Discriminant (Typ);
+ while Present (Comp) loop
+ if Is_Deep (Etype (Comp)) then
+ return True;
+ end if;
+ Next_Component_Or_Discriminant (Comp);
+ end loop;
+ end;
+ return False;
- Set (Current_Initialization_Map, Unique_Entity (P), True);
- if C = null then
- -- No null possible here, there are no parents for the path.
- -- This means we are using a global variable without adding
- -- it in environment with a global aspect.
+ when Scalar_Kind
+ | E_String_Literal_Subtype
+ | Protected_Kind
+ | Task_Kind
+ | Incomplete_Kind
+ | E_Exception_Type
+ | E_Subprogram_Type
+ =>
+ return False;
- Illegal_Global_Usage (N);
+ -- The following should not arise as underlying types
- else
- return C;
- end if;
- end;
+ when E_Private_Type
+ | E_Private_Subtype
+ | E_Limited_Private_Type
+ | E_Limited_Private_Subtype
+ =>
+ raise Program_Error;
+ end case;
+ end Is_Deep;
- when N_Type_Conversion
- | N_Unchecked_Type_Conversion
- | N_Qualified_Expression
+ ------------------------
+ -- Is_Path_Expression --
+ ------------------------
+
+ function Is_Path_Expression (Expr : Node_Id) return Boolean is
+ begin
+ case Nkind (Expr) is
+ when N_Expanded_Name
+ | N_Explicit_Dereference
+ | N_Identifier
+ | N_Indexed_Component
+ | N_Selected_Component
+ | N_Slice
=>
- return Get_Perm_Tree (Expression (N));
+ return True;
- when N_Parameter_Specification =>
- return Get_Perm_Tree (Defining_Identifier (N));
+ -- Special value NULL corresponds to an empty path
- -- We get the permission tree of its prefix, and then get either the
- -- subtree associated with that specific selection, or if we have a
- -- leaf that folds its children, we unroll it in one step.
+ when N_Null =>
+ return True;
- when N_Selected_Component =>
- declare
- C : constant Perm_Tree_Access := Get_Perm_Tree (Prefix (N));
+ -- Object returned by a allocator or function call corresponds to
+ -- a path.
- begin
- if C = null then
+ when N_Allocator
+ | N_Function_Call
+ =>
+ return True;
- -- If null then it means we went through a function call
+ when N_Qualified_Expression
+ | N_Type_Conversion
+ | N_Unchecked_Type_Conversion
+ =>
+ return Is_Path_Expression (Expression (Expr));
- return null;
- end if;
+ when others =>
+ return False;
+ end case;
+ end Is_Path_Expression;
- pragma Assert (Kind (C) = Entire_Object
- or else Kind (C) = Record_Component);
+ -------------------------
+ -- Is_Prefix_Or_Almost --
+ -------------------------
- if Kind (C) = Record_Component then
+ function Is_Prefix_Or_Almost (Pref, Expr : Node_Id) return Boolean is
- -- The tree is unfolded. We just return the subtree.
+ type Expr_Array is array (Positive range <>) of Node_Id;
+ -- Sequence of expressions that make up a path
- declare
- Selected_Component : constant Entity_Id :=
- Entity (Selector_Name (N));
- Selected_C : constant Perm_Tree_Access :=
- Perm_Tree_Maps.Get
- (Component (C), Selected_Component);
+ function Get_Expr_Array (Expr : Node_Id) return Expr_Array;
+ pragma Precondition (Is_Path_Expression (Expr));
+ -- Return the sequence of expressions that make up a path
- begin
- if Selected_C = null then
- return Other_Components (C);
- end if;
- return Selected_C;
- end;
+ --------------------
+ -- Get_Expr_Array --
+ --------------------
- elsif Kind (C) = Entire_Object then
- declare
- -- Expand the tree. Replace the node with
- -- Record_Component.
+ function Get_Expr_Array (Expr : Node_Id) return Expr_Array is
+ begin
+ case Nkind (Expr) is
+ when N_Expanded_Name
+ | N_Identifier
+ =>
+ return Expr_Array'(1 => Expr);
- Elem : Node_Id;
+ when N_Explicit_Dereference
+ | N_Indexed_Component
+ | N_Selected_Component
+ | N_Slice
+ =>
+ return Get_Expr_Array (Prefix (Expr)) & Expr;
- -- Create the unrolled nodes
+ when N_Qualified_Expression
+ | N_Type_Conversion
+ | N_Unchecked_Type_Conversion
+ =>
+ return Get_Expr_Array (Expression (Expr));
- Son : Perm_Tree_Access;
+ when others =>
+ raise Program_Error;
+ end case;
+ end Get_Expr_Array;
- Child_Perm : constant Perm_Kind :=
- Children_Permission (C);
+ -- Local variables
- begin
- -- We change the current node from Entire_Object to
- -- Record_Component with same permission and an empty
- -- hash table as component list.
+ Prefix_Path : constant Expr_Array := Get_Expr_Array (Pref);
+ Expr_Path : constant Expr_Array := Get_Expr_Array (Expr);
- C.all.Tree :=
- (Kind => Record_Component,
- Is_Node_Deep => Is_Node_Deep (C),
- Permission => Permission (C),
- Component => Perm_Tree_Maps.Nil,
- Other_Components =>
- new Perm_Tree_Wrapper'
- (Tree =>
- (Kind => Entire_Object,
- -- Is_Node_Deep is true, to be conservative
- Is_Node_Deep => True,
- Permission => Child_Perm,
- Children_Permission => Child_Perm)
- )
- );
-
- -- We fill the hash table with all sons of the record,
- -- with basic Entire_Objects nodes.
-
- Elem := First_Component_Or_Discriminant
- (Etype (Prefix (N)));
-
- while Present (Elem) loop
- Son := new Perm_Tree_Wrapper'
- (Tree =>
- (Kind => Entire_Object,
- Is_Node_Deep => Is_Deep (Etype (Elem)),
- Permission => Child_Perm,
- Children_Permission => Child_Perm));
+ Prefix_Root : constant Node_Id := Prefix_Path (1);
+ Expr_Root : constant Node_Id := Expr_Path (1);
- Perm_Tree_Maps.Set
- (C.all.Tree.Component, Elem, Son);
- Next_Component_Or_Discriminant (Elem);
- end loop;
- -- we return the tree to the sons, so that the recursion
- -- can continue.
+ Common_Len : constant Positive :=
+ Positive'Min (Prefix_Path'Length, Expr_Path'Length);
- declare
- Selected_Component : constant Entity_Id :=
- Entity (Selector_Name (N));
+ -- Start of processing for Is_Prefix_Or_Almost
- Selected_C : constant Perm_Tree_Access :=
- Perm_Tree_Maps.Get
- (Component (C), Selected_Component);
+ begin
+ if Entity (Prefix_Root) /= Entity (Expr_Root) then
+ return False;
+ end if;
- begin
- pragma Assert (Selected_C /= null);
- return Selected_C;
- end;
- end;
- else
+ for J in 2 .. Common_Len loop
+ declare
+ Prefix_Elt : constant Node_Id := Prefix_Path (J);
+ Expr_Elt : constant Node_Id := Expr_Path (J);
+ begin
+ case Nkind (Prefix_Elt) is
+ when N_Explicit_Dereference =>
+ if Nkind (Expr_Elt) /= N_Explicit_Dereference then
+ return False;
+ end if;
+
+ when N_Selected_Component =>
+ if Nkind (Expr_Elt) /= N_Selected_Component
+ or else Entity (Selector_Name (Prefix_Elt))
+ /= Entity (Selector_Name (Expr_Elt))
+ then
+ return False;
+ end if;
+
+ when N_Indexed_Component
+ | N_Slice
+ =>
+ if not Nkind_In (Expr_Elt, N_Indexed_Component, N_Slice) then
+ return False;
+ end if;
+
+ when others =>
raise Program_Error;
- end if;
- end;
- -- We set the permission tree of its prefix, and then we extract from
- -- the returned pointer the subtree. If folded, we unroll the tree at
- -- one step.
+ end case;
+ end;
+ end loop;
- when N_Indexed_Component
- | N_Slice
- =>
- declare
- C : constant Perm_Tree_Access := Get_Perm_Tree (Prefix (N));
+ -- If the expression path is longer than the prefix one, then at this
+ -- point the prefix property holds.
- begin
- if C = null then
- -- If null then we went through a function call
+ if Expr_Path'Length > Prefix_Path'Length then
+ return True;
- return null;
- end if;
- pragma Assert (Kind (C) = Entire_Object
- or else Kind (C) = Array_Component);
+ -- Otherwise check if none of the remaining path elements in the
+ -- candidate prefix involve a dereference.
- if Kind (C) = Array_Component then
+ else
+ for J in Common_Len + 1 .. Prefix_Path'Length loop
+ if Nkind (Prefix_Path (J)) = N_Explicit_Dereference then
+ return False;
+ end if;
+ end loop;
- -- The tree is unfolded. We just return the elem subtree
+ return True;
+ end if;
+ end Is_Prefix_Or_Almost;
- pragma Assert (Get_Elem (C) = null);
- return Get_Elem (C);
+ ---------------------------
+ -- Is_Traversal_Function --
+ ---------------------------
- elsif Kind (C) = Entire_Object then
- declare
- -- Expand the tree. Replace node with Array_Component.
+ function Is_Traversal_Function (E : Entity_Id) return Boolean is
+ begin
+ return Ekind (E) = E_Function
- Son : Perm_Tree_Access;
+ -- A function is said to be a traversal function if the result type of
+ -- the function is an anonymous access-to-object type,
- begin
- Son := new Perm_Tree_Wrapper'
- (Tree =>
- (Kind => Entire_Object,
- Is_Node_Deep => Is_Node_Deep (C),
- Permission => Children_Permission (C),
- Children_Permission => Children_Permission (C)));
+ and then Is_Anonymous_Access_Type (Etype (E))
- -- We change the current node from Entire_Object
- -- to Array_Component with same permission and the
- -- previously defined son.
+ -- the function has at least one formal parameter,
- C.all.Tree := (Kind => Array_Component,
- Is_Node_Deep => Is_Node_Deep (C),
- Permission => Permission (C),
- Get_Elem => Son);
- return Get_Elem (C);
- end;
- else
- raise Program_Error;
- end if;
- end;
- -- We get the permission tree of its prefix, and then get either the
- -- subtree associated with that specific selection, or if we have a
- -- leaf that folds its children, we unroll the tree.
+ and then Present (First_Formal (E))
- when N_Explicit_Dereference =>
- declare
- C : Perm_Tree_Access;
+ -- and the function's first parameter is of an access type.
- begin
- C := Get_Perm_Tree (Prefix (N));
+ and then Is_Access_Type (Etype (First_Formal (E)));
+ end Is_Traversal_Function;
- if C = null then
+ --------------------------------
+ -- Is_Traversal_Function_Call --
+ --------------------------------
- -- If null, we went through a function call
+ function Is_Traversal_Function_Call (Expr : Node_Id) return Boolean is
+ begin
+ return Nkind (Expr) = N_Function_Call
+ and then Present (Get_Called_Entity (Expr))
+ and then Is_Traversal_Function (Get_Called_Entity (Expr));
+ end Is_Traversal_Function_Call;
- return null;
- end if;
+ ------------------
+ -- Loop_Of_Exit --
+ ------------------
- pragma Assert (Kind (C) = Entire_Object
- or else Kind (C) = Reference);
+ function Loop_Of_Exit (N : Node_Id) return Entity_Id is
+ Nam : Node_Id := Name (N);
+ Stmt : Node_Id := N;
+ begin
+ if No (Nam) then
+ while Present (Stmt) loop
+ Stmt := Parent (Stmt);
+ if Nkind (Stmt) = N_Loop_Statement then
+ Nam := Identifier (Stmt);
+ exit;
+ end if;
+ end loop;
+ end if;
+ return Entity (Nam);
+ end Loop_Of_Exit;
- if Kind (C) = Reference then
+ ---------
+ -- Lub --
+ ---------
- -- The tree is unfolded. We return the elem subtree
+ function Lub (P1, P2 : Perm_Kind) return Perm_Kind is
+ begin
+ case P1 is
+ when No_Access =>
+ return P2;
+
+ when Read_Only =>
+ case P2 is
+ when No_Access
+ | Read_Only
+ =>
+ return Read_Only;
- if Get_All (C) = null then
+ when Write_Perm =>
+ return Read_Write;
+ end case;
- -- Hash_Table_Error
+ when Write_Only =>
+ case P2 is
+ when No_Access
+ | Write_Only
+ =>
+ return Write_Only;
- raise Program_Error;
- end if;
- return Get_All (C);
+ when Read_Perm =>
+ return Read_Write;
+ end case;
- elsif Kind (C) = Entire_Object then
- declare
- -- Expand the tree. Replace the node with Reference.
+ when Read_Write =>
+ return Read_Write;
+ end case;
+ end Lub;
- Son : Perm_Tree_Access;
+ ---------------
+ -- Merge_Env --
+ ---------------
- begin
- Son := new Perm_Tree_Wrapper'
- (Tree =>
- (Kind => Entire_Object,
- Is_Node_Deep => Is_Deep (Etype (N)),
- Permission => Children_Permission (C),
- Children_Permission => Children_Permission (C)));
+ procedure Merge_Env (Source : in out Perm_Env; Target : in out Perm_Env) is
- -- We change the current node from Entire_Object to
- -- Reference with same permission and the previous son.
+ -- Local subprograms
- pragma Assert (Is_Node_Deep (C));
- C.all.Tree := (Kind => Reference,
- Is_Node_Deep => Is_Node_Deep (C),
- Permission => Permission (C),
- Get_All => Son);
- return Get_All (C);
- end;
- else
- raise Program_Error;
- end if;
- end;
- -- No permission tree for function calls
+ procedure Apply_Glb_Tree
+ (A : Perm_Tree_Access;
+ P : Perm_Kind);
- when N_Function_Call =>
- return null;
+ procedure Merge_Trees
+ (Target : Perm_Tree_Access;
+ Source : Perm_Tree_Access);
- when others =>
- raise Program_Error;
- end case;
- end Get_Perm_Tree;
+ --------------------
+ -- Apply_Glb_Tree --
+ --------------------
- --------
- -- Hp --
- --------
+ procedure Apply_Glb_Tree
+ (A : Perm_Tree_Access;
+ P : Perm_Kind)
+ is
+ begin
+ A.all.Tree.Permission := Glb (Permission (A), P);
- procedure Hp (P : Perm_Env) is
- Elem : Perm_Tree_Maps.Key_Option;
+ case Kind (A) is
+ when Entire_Object =>
+ A.all.Tree.Children_Permission :=
+ Glb (Children_Permission (A), P);
- begin
- Elem := Get_First_Key (P);
- while Elem.Present loop
- Print_Node_Briefly (Elem.K);
- Elem := Get_Next_Key (P);
- end loop;
- end Hp;
+ when Reference =>
+ Apply_Glb_Tree (Get_All (A), P);
- --------------------------
- -- Illegal_Global_Usage --
- --------------------------
+ when Array_Component =>
+ Apply_Glb_Tree (Get_Elem (A), P);
- procedure Illegal_Global_Usage (N : Node_Or_Entity_Id) is
- begin
- Error_Msg_NE ("cannot use global variable & of deep type", N, N);
- Error_Msg_N ("\without prior declaration in a Global aspect", N);
- Errout.Finalize (Last_Call => True);
- Errout.Output_Messages;
- Exit_Program (E_Errors);
- end Illegal_Global_Usage;
+ when Record_Component =>
+ declare
+ Comp : Perm_Tree_Access;
+ begin
+ Comp := Perm_Tree_Maps.Get_First (Component (A));
+ while Comp /= null loop
+ Apply_Glb_Tree (Comp, P);
+ Comp := Perm_Tree_Maps.Get_Next (Component (A));
+ end loop;
+ end;
+ end case;
+ end Apply_Glb_Tree;
- -------------
- -- Is_Deep --
- -------------
+ -----------------
+ -- Merge_Trees --
+ -----------------
- function Is_Deep (E : Entity_Id) return Boolean is
- function Is_Private_Entity_Mode_Off (E : Entity_Id) return Boolean;
- function Is_Private_Entity_Mode_Off (E : Entity_Id) return Boolean is
- Decl : Node_Id;
- Pack_Decl : Node_Id;
+ procedure Merge_Trees
+ (Target : Perm_Tree_Access;
+ Source : Perm_Tree_Access)
+ is
+ Perm : constant Perm_Kind :=
+ Glb (Permission (Target), Permission (Source));
begin
- if Is_Itype (E) then
- Decl := Associated_Node_For_Itype (E);
- else
- Decl := Parent (E);
- end if;
+ pragma Assert (Is_Node_Deep (Target) = Is_Node_Deep (Source));
+ Target.all.Tree.Permission := Perm;
- Pack_Decl := Parent (Parent (Decl));
+ case Kind (Target) is
+ when Entire_Object =>
+ declare
+ Child_Perm : constant Perm_Kind :=
+ Children_Permission (Target);
- if Nkind (Pack_Decl) /= N_Package_Declaration then
- return False;
- end if;
+ begin
+ case Kind (Source) is
+ when Entire_Object =>
+ Target.all.Tree.Children_Permission :=
+ Glb (Child_Perm, Children_Permission (Source));
+
+ when Reference =>
+ Copy_Tree (Source, Target);
+ Target.all.Tree.Permission := Perm;
+ Apply_Glb_Tree (Get_All (Target), Child_Perm);
+
+ when Array_Component =>
+ Copy_Tree (Source, Target);
+ Target.all.Tree.Permission := Perm;
+ Apply_Glb_Tree (Get_Elem (Target), Child_Perm);
+
+ when Record_Component =>
+ Copy_Tree (Source, Target);
+ Target.all.Tree.Permission := Perm;
+ declare
+ Comp : Perm_Tree_Access;
- return
- Present (SPARK_Aux_Pragma (Defining_Entity (Pack_Decl)))
- and then Get_SPARK_Mode_From_Annotation
- (SPARK_Aux_Pragma (Defining_Entity (Pack_Decl))) = Off;
- end Is_Private_Entity_Mode_Off;
+ begin
+ Comp :=
+ Perm_Tree_Maps.Get_First (Component (Target));
+ while Comp /= null loop
+ -- Apply glb tree on every component subtree
+
+ Apply_Glb_Tree (Comp, Child_Perm);
+ Comp := Perm_Tree_Maps.Get_Next
+ (Component (Target));
+ end loop;
+ end;
+ end case;
+ end;
- begin
- pragma Assert (Is_Type (E));
- case Ekind (E) is
- when Scalar_Kind =>
- return False;
+ when Reference =>
+ case Kind (Source) is
+ when Entire_Object =>
+ Apply_Glb_Tree (Get_All (Target),
+ Children_Permission (Source));
- when Access_Kind =>
- return True;
+ when Reference =>
+ Merge_Trees (Get_All (Target), Get_All (Source));
- -- Just check the depth of its component type
+ when others =>
+ raise Program_Error;
- when E_Array_Type
- | E_Array_Subtype
- =>
- return Is_Deep (Component_Type (E));
+ end case;
- when E_String_Literal_Subtype =>
- return False;
+ when Array_Component =>
+ case Kind (Source) is
+ when Entire_Object =>
+ Apply_Glb_Tree (Get_Elem (Target),
+ Children_Permission (Source));
- -- Per RM 8.11 for class-wide types
+ when Array_Component =>
+ Merge_Trees (Get_Elem (Target), Get_Elem (Source));
- when E_Class_Wide_Subtype
- | E_Class_Wide_Type
- =>
- return True;
+ when others =>
+ raise Program_Error;
- -- ??? What about hidden components
+ end case;
- when E_Record_Type
- | E_Record_Subtype
- =>
- declare
- Elmt : Entity_Id;
+ when Record_Component =>
+ case Kind (Source) is
+ when Entire_Object =>
+ declare
+ Child_Perm : constant Perm_Kind :=
+ Children_Permission (Source);
- begin
- Elmt := First_Component_Or_Discriminant (E);
- while Present (Elmt) loop
- if Is_Deep (Etype (Elmt)) then
- return True;
- else
- Next_Component_Or_Discriminant (Elmt);
- end if;
- end loop;
- return False;
- end;
+ Comp : Perm_Tree_Access;
- when Private_Kind =>
- if Is_Private_Entity_Mode_Off (E) then
- return False;
- else
- if Present (Full_View (E)) then
- return Is_Deep (Full_View (E));
- else
- return True;
- end if;
- end if;
+ begin
+ Comp := Perm_Tree_Maps.Get_First
+ (Component (Target));
+ while Comp /= null loop
+ -- Apply glb tree on every component subtree
+
+ Apply_Glb_Tree (Comp, Child_Perm);
+ Comp :=
+ Perm_Tree_Maps.Get_Next (Component (Target));
+ end loop;
+ end;
- when E_Incomplete_Type
- | E_Incomplete_Subtype
- =>
- return True;
+ when Record_Component =>
+ declare
+ Key_Source : Perm_Tree_Maps.Key_Option;
+ CompTarget : Perm_Tree_Access;
+ CompSource : Perm_Tree_Access;
- -- No problem with synchronized types
+ begin
+ Key_Source := Perm_Tree_Maps.Get_First_Key
+ (Component (Source));
- when E_Protected_Type
- | E_Protected_Subtype
- | E_Task_Subtype
- | E_Task_Type
- =>
- return False;
+ while Key_Source.Present loop
+ CompSource := Perm_Tree_Maps.Get
+ (Component (Source), Key_Source.K);
+ CompTarget := Perm_Tree_Maps.Get
+ (Component (Target), Key_Source.K);
- when E_Exception_Type =>
- return False;
+ pragma Assert (CompSource /= null);
+ Merge_Trees (CompTarget, CompSource);
- when others =>
- raise Program_Error;
- end case;
- end Is_Deep;
+ Key_Source := Perm_Tree_Maps.Get_Next_Key
+ (Component (Source));
+ end loop;
+ end;
+
+ when others =>
+ raise Program_Error;
+ end case;
+ end case;
+ end Merge_Trees;
+
+ -- Local variables
+
+ CompTarget : Perm_Tree_Access;
+ CompSource : Perm_Tree_Access;
+ KeyTarget : Perm_Tree_Maps.Key_Option;
+
+ -- Start of processing for Merge_Env
+
+ begin
+ KeyTarget := Get_First_Key (Target);
+ -- Iterate over every tree of the environment in the target, and merge
+ -- it with the source if there is such a similar one that exists. If
+ -- there is none, then skip.
+ while KeyTarget.Present loop
+
+ CompSource := Get (Source, KeyTarget.K);
+ CompTarget := Get (Target, KeyTarget.K);
+
+ pragma Assert (CompTarget /= null);
+
+ if CompSource /= null then
+ Merge_Trees (CompTarget, CompSource);
+ Remove (Source, KeyTarget.K);
+ end if;
+
+ KeyTarget := Get_Next_Key (Target);
+ end loop;
+
+ -- Iterate over every tree of the environment of the source. And merge
+ -- again. If there is not any tree of the target then just copy the tree
+ -- from source to target.
+ declare
+ KeySource : Perm_Tree_Maps.Key_Option;
+ begin
+ KeySource := Get_First_Key (Source);
+ while KeySource.Present loop
+
+ CompSource := Get (Source, KeySource.K);
+ CompTarget := Get (Target, KeySource.K);
+
+ if CompTarget = null then
+ CompTarget := new Perm_Tree_Wrapper'(CompSource.all);
+ Copy_Tree (CompSource, CompTarget);
+ Set (Target, KeySource.K, CompTarget);
+ else
+ Merge_Trees (CompTarget, CompSource);
+ end if;
+
+ KeySource := Get_Next_Key (Source);
+ end loop;
+ end;
+
+ Free_Env (Source);
+ end Merge_Env;
----------------
-- Perm_Error --
----------------
procedure Perm_Error
- (N : Node_Id;
- Perm : Perm_Kind;
- Found_Perm : Perm_Kind)
+ (N : Node_Id;
+ Perm : Perm_Kind;
+ Found_Perm : Perm_Kind;
+ Forbidden_Perm : Boolean := False)
is
procedure Set_Root_Object
(Path : Node_Id;
@@ -3328,7 +3975,7 @@ package body Sem_SPARK is
Error_Msg_NE ("insufficient permission for &", N, Root);
end if;
- Perm_Mismatch (Perm, Found_Perm, N);
+ Perm_Mismatch (N, Perm, Found_Perm, Forbidden_Perm);
end Perm_Error;
-------------------------------
@@ -3345,364 +3992,441 @@ package body Sem_SPARK is
Error_Msg_Node_2 := Subp;
Error_Msg_NE ("insufficient permission for & when returning from &",
Subp, E);
- Perm_Mismatch (Perm, Found_Perm, Subp);
+ Perm_Mismatch (Subp, Perm, Found_Perm);
end Perm_Error_Subprogram_End;
------------------
-- Process_Path --
------------------
- procedure Process_Path (N : Node_Id) is
- Root : constant Entity_Id := Get_Enclosing_Object (N);
- State_N : Perm_Kind;
+ procedure Process_Path (Expr : Node_Id; Mode : Checking_Mode) is
+
+ procedure Check_Not_Borrowed (Expr : Node_Id; Root : Entity_Id);
+ -- Check expression Expr originating in Root was not borrowed
+
+ procedure Check_Not_Observed (Expr : Node_Id; Root : Entity_Id);
+ -- Check expression Expr originating in Root was not observed
+
+ ------------------------
+ -- Check_Not_Borrowed --
+ ------------------------
+
+ procedure Check_Not_Borrowed (Expr : Node_Id; Root : Entity_Id) is
+ begin
+ -- An expression without root object cannot be borrowed
+
+ if No (Root) then
+ return;
+ end if;
+
+ -- Otherwise, try to match the expression with one of the borrowed
+ -- expressions.
+
+ declare
+ Key : Variable_Maps.Key_Option :=
+ Get_First_Key (Current_Borrowers);
+ Var : Entity_Id;
+ Borrowed : Node_Id;
+
+ begin
+ while Key.Present loop
+ Var := Key.K;
+ Borrowed := Get (Current_Borrowers, Var);
+
+ if Is_Prefix_Or_Almost (Pref => Borrowed, Expr => Expr) then
+ Error_Msg_Sloc := Sloc (Borrowed);
+ Error_Msg_N ("expression was borrowed #", Expr);
+ end if;
+
+ Key := Get_Next_Key (Current_Borrowers);
+ end loop;
+ end;
+ end Check_Not_Borrowed;
+
+ ------------------------
+ -- Check_Not_Observed --
+ ------------------------
+
+ procedure Check_Not_Observed (Expr : Node_Id; Root : Entity_Id) is
+ begin
+ -- An expression without root object cannot be observed
+
+ if No (Root) then
+ return;
+ end if;
+
+ -- Otherwise, try to match the expression with one of the observed
+ -- expressions.
+
+ declare
+ Key : Variable_Maps.Key_Option :=
+ Get_First_Key (Current_Observers);
+ Var : Entity_Id;
+ Observed : Node_Id;
+
+ begin
+ while Key.Present loop
+ Var := Key.K;
+ Observed := Get (Current_Observers, Var);
+
+ if Is_Prefix_Or_Almost (Pref => Observed, Expr => Expr) then
+ Error_Msg_Sloc := Sloc (Observed);
+ Error_Msg_N ("expression was observed #", Expr);
+ end if;
+
+ Key := Get_Next_Key (Current_Observers);
+ end loop;
+ end;
+ end Check_Not_Observed;
+
+ -- Local variables
+
+ Expr_Type : constant Entity_Id := Etype (Expr);
+ Root : Entity_Id := Get_Root_Object (Expr);
+ Perm : Perm_Kind_Option;
+
+ -- Start of processing for Process_Path
+
begin
- -- We ignore if yielding to synchronized
+ -- Nothing to do if the root type is not deep, or the path is not rooted
+ -- in an object.
- if Present (Root)
- and then Is_Synchronized_Object (Root)
+ if not Present (Root)
+ or else not Is_Deep (Etype (Root))
then
return;
end if;
- State_N := Get_Perm (N);
+ -- Identify the root type for the path
- case Current_Checking_Mode is
+ Root := Unique_Entity (Root);
- -- Check permission R, do nothing
+ -- Except during elaboration, the root object should have been declared
+ -- and entered into the current permission environment.
- when Read =>
+ if not Inside_Elaboration
+ and then Get (Current_Perm_Env, Root) = null
+ then
+ Illegal_Global_Usage (Expr);
+ end if;
- -- This condition should be removed when removing the read
- -- checking mode.
+ -- During elaboration, only the validity of operations is checked, no
+ -- need to compute the permission of Expr.
- return;
+ if Inside_Elaboration then
+ Perm := None;
+ else
+ Perm := Get_Perm (Expr);
+ end if;
- when Move =>
+ -- Check permissions
+
+ case Mode is
+
+ when Read =>
- -- The rhs object in an assignment statement (including copy in
- -- and copy back) should be in the Unrestricted or Moved state.
- -- Otherwise the move is not allowed.
- -- This applies to both stand-alone and composite objects.
- -- If the state of the source is Moved, then a warning message
- -- is prompt to make the user aware of reading a nullified
- -- object.
+ -- No checking needed during elaboration
- if State_N /= Unrestricted and State_N /= Moved then
- Perm_Error (N, Unrestricted, State_N);
+ if Inside_Elaboration then
return;
end if;
- -- In the AI, after moving a path nothing to do since the rhs
- -- object was in the Unrestricted state and it shall be
- -- refreshed to Unrestricted. The object should be nullified
- -- however. To avoid moving again a name that has already been
- -- moved, in this implementation we set the state of the moved
- -- object to "Moved". This shall be used to prompt a warning
- -- when manipulating a null pointer and also to implement
- -- the no aliasing parameter restriction.
-
- if State_N = Moved then
- Error_Msg_N ("?the source or one of its extensions has"
- & " already been moved", N);
+ -- Check path is readable
+
+ if Perm not in Read_Perm then
+ Perm_Error (Expr, Read_Only, Perm);
+ return;
end if;
- declare
- -- Set state to Moved to the path and any of its prefixes
+ when Move =>
- Tree : constant Perm_Tree_Access :=
- Set_Perm_Prefixes (N, Moved);
+ -- Forbidden on deep path during elaboration, otherwise no
+ -- checking needed.
- begin
- if Tree = null then
+ if Inside_Elaboration then
+ if Is_Deep (Expr_Type)
+ and then not Inside_Procedure_Call
+ and then Present (Get_Root_Object (Expr))
+ then
+ Error_Msg_N ("illegal move during elaboration", Expr);
+ end if;
- -- We went through a function call, no permission to
- -- modify.
+ return;
+ end if;
- return;
+ -- For deep path, check RW permission, otherwise R permission
+
+ if not Is_Deep (Expr_Type) then
+ if Perm not in Read_Perm then
+ Perm_Error (Expr, Read_Only, Perm);
end if;
+ return;
+ end if;
- -- Set state to Moved on any strict extension of the path
+ -- SPARK RM 3.10(1): At the point of a move operation the state of
+ -- the source object (if any) shall be Unrestricted.
- Set_Perm_Extensions (Tree, Moved);
- end;
+ if Perm /= Read_Write then
+ Perm_Error (Expr, Read_Write, Perm);
+ return;
+ end if;
when Assign =>
- -- The lhs object in an assignment statement (including copy in
- -- and copy back) should be in the Unrestricted state.
- -- Otherwise the move is not allowed.
- -- This applies to both stand-alone and composite objects.
+ -- No checking needed during elaboration
- if State_N /= Unrestricted and State_N /= Moved then
- Perm_Error (N, Unrestricted, State_N);
+ if Inside_Elaboration then
return;
end if;
- -- After assigning to a path nothing to do since it was in the
- -- Unrestricted state and it would be refreshed to
- -- Unrestricted.
+ -- For assignment, check W permission
+
+ if Perm not in Write_Perm then
+ Perm_Error (Expr, Write_Only, Perm);
+ return;
+ end if;
when Borrow =>
- -- Borrowing is only allowed on Unrestricted objects.
+ -- Forbidden during elaboration
- if State_N /= Unrestricted and State_N /= Moved then
- Perm_Error (N, Unrestricted, State_N);
- end if;
+ if Inside_Elaboration then
+ if not Inside_Procedure_Call then
+ Error_Msg_N ("illegal borrow during elaboration", Expr);
+ end if;
- if State_N = Moved then
- Error_Msg_N ("?the source or one of its extensions has"
- & " already been moved", N);
+ return;
end if;
- declare
- -- Set state to Borrowed to the path and any of its prefixes
+ -- For borrowing, check RW permission
- Tree : constant Perm_Tree_Access :=
- Set_Perm_Prefixes (N, Borrowed);
+ if Perm /= Read_Write then
+ Perm_Error (Expr, Read_Write, Perm);
+ return;
+ end if;
- begin
- if Tree = null then
+ when Observe =>
- -- We went through a function call, no permission to
- -- modify.
+ -- Forbidden during elaboration
- return;
+ if Inside_Elaboration then
+ if not Inside_Procedure_Call then
+ Error_Msg_N ("illegal observe during elaboration", Expr);
end if;
- -- Set state to Borrowed on any strict extension of the path
+ return;
+ end if;
- Set_Perm_Extensions (Tree, Borrowed);
- end;
+ -- For borrowing, check R permission
- when Observe =>
- if State_N /= Unrestricted
- and then State_N /= Observed
- then
- Perm_Error (N, Observed, State_N);
+ if Perm not in Read_Perm then
+ Perm_Error (Expr, Read_Only, Perm);
+ return;
end if;
+ end case;
- declare
- -- Set permission to Observed on the path and any of its
- -- prefixes if it is of a deep type. Actually, some operation
- -- like reading from an object of access type is considered as
- -- observe while it should not affect the permissions of
- -- the considered tree.
+ -- Check path was not borrowed
- Tree : Perm_Tree_Access;
+ Check_Not_Borrowed (Expr, Root);
- begin
- if Is_Deep (Etype (N)) then
- Tree := Set_Perm_Prefixes (N, Observed);
- else
- Tree := null;
- end if;
+ -- For modes that require W permission, check path was not observed
- if Tree = null then
+ case Mode is
+ when Read | Observe =>
+ null;
+ when Assign | Move | Borrow =>
+ Check_Not_Observed (Expr, Root);
+ end case;
- -- We went through a function call, no permission to
- -- modify.
+ -- Do not update permission environment when handling calls
- return;
- end if;
+ if Inside_Procedure_Call then
+ return;
+ end if;
- -- Set permissions to No on any strict extension of the path
+ -- Update the permissions
- Set_Perm_Extensions (Tree, Observed);
- end;
- end case;
- end Process_Path;
+ case Mode is
- -------------------------
- -- Return_Declarations --
- -------------------------
+ when Read =>
+ null;
- procedure Return_Declarations (L : List_Id) is
- procedure Return_Declaration (Decl : Node_Id);
- -- Check correct permissions for every declared object
+ when Move =>
- ------------------------
- -- Return_Declaration --
- ------------------------
+ -- SPARK RM 3.10(1): After a move operation, the state of the
+ -- source object (if any) becomes Moved.
- procedure Return_Declaration (Decl : Node_Id) is
- begin
- if Nkind (Decl) = N_Object_Declaration then
+ if Present (Get_Root_Object (Expr)) then
+ declare
+ Tree : constant Perm_Tree_Access :=
+ Set_Perm_Prefixes (Expr, Write_Only);
+ begin
+ pragma Assert (Tree /= null);
+ Set_Perm_Extensions_Move (Tree, Etype (Expr));
+ end;
+ end if;
- -- Check RW for object declared, unless the object has never been
- -- initialized.
+ when Assign =>
+
+ -- If there is no root object, or the tree has an array component,
+ -- then the permissions do not get modified by the assignment.
- if Get (Current_Initialization_Map,
- Unique_Entity (Defining_Identifier (Decl))) = False
+ if No (Get_Root_Object (Expr))
+ or else Has_Array_Component (Expr)
then
return;
end if;
- declare
- Elem : constant Perm_Tree_Access :=
- Get (Current_Perm_Env,
- Unique_Entity (Defining_Identifier (Decl)));
+ -- Set permission RW for the path and its extensions
+ declare
+ Tree : constant Perm_Tree_Access := Get_Perm_Tree (Expr);
begin
- if Elem = null then
+ Tree.all.Tree.Permission := Read_Write;
+ Set_Perm_Extensions (Tree, Read_Write);
- -- Here we are on a declaration. Hence it should have been
- -- added in the environment when analyzing this node with
- -- mode Read. Hence it is not possible to find a null
- -- pointer here.
-
- -- Hash_Table_Error
-
- raise Program_Error;
- end if;
+ -- Normalize the permission tree
- if Permission (Elem) /= Unrestricted then
- Perm_Error (Decl, Unrestricted, Permission (Elem));
- end if;
+ Set_Perm_Prefixes_Assign (Expr);
end;
- end if;
- end Return_Declaration;
- -- Local Variables
-
- N : Node_Id;
- -- Start of processing for Return_Declarations
+ -- Borrowing and observing of paths is handled by the variables
+ -- Current_Borrowers and Current_Observers.
- begin
- N := First (L);
- while Present (N) loop
- Return_Declaration (N);
- Next (N);
- end loop;
- end Return_Declarations;
+ when Borrow | Observe =>
+ null;
+ end case;
+ end Process_Path;
--------------------
-- Return_Globals --
--------------------
procedure Return_Globals (Subp : Entity_Id) is
- procedure Return_Globals_From_List
- (First_Item : Node_Id;
- Kind : Formal_Kind);
- -- Return global items from the list starting at Item
- procedure Return_Globals_Of_Mode (Global_Mode : Name_Id);
- -- Return global items for the mode Global_Mode
+ procedure Return_Global
+ (Expr : Node_Id;
+ Typ : Entity_Id;
+ Kind : Formal_Kind;
+ Subp : Entity_Id;
+ Global_Var : Boolean);
+ -- Proxy procedure to return globals, to adjust for the type of first
+ -- parameter expected by Return_Parameter_Or_Global.
- ------------------------------
- -- Return_Globals_From_List --
- ------------------------------
+ -------------------
+ -- Return_Global --
+ -------------------
- procedure Return_Globals_From_List
- (First_Item : Node_Id;
- Kind : Formal_Kind)
+ procedure Return_Global
+ (Expr : Node_Id;
+ Typ : Entity_Id;
+ Kind : Formal_Kind;
+ Subp : Entity_Id;
+ Global_Var : Boolean)
is
- Item : Node_Id := First_Item;
- E : Entity_Id;
-
begin
- while Present (Item) loop
- E := Entity (Item);
+ Return_Parameter_Or_Global
+ (Id => Entity (Expr),
+ Typ => Typ,
+ Kind => Kind,
+ Subp => Subp,
+ Global_Var => Global_Var);
+ end Return_Global;
- -- Ignore abstract states, which play no role in pointer aliasing
-
- if Ekind (E) = E_Abstract_State then
- null;
- else
- Return_The_Global (E, Kind, Subp);
- end if;
- Next_Global (Item);
- end loop;
- end Return_Globals_From_List;
-
- ----------------------------
- -- Return_Globals_Of_Mode --
- ----------------------------
-
- procedure Return_Globals_Of_Mode (Global_Mode : Name_Id) is
- Kind : Formal_Kind;
-
- begin
- case Global_Mode is
- when Name_Input
- | Name_Proof_In
- =>
- Kind := E_In_Parameter;
- when Name_Output =>
- Kind := E_Out_Parameter;
- when Name_In_Out =>
- Kind := E_In_Out_Parameter;
- when others =>
- raise Program_Error;
- end case;
-
- -- Return both global items from Global and Refined_Global pragmas
-
- Return_Globals_From_List (First_Global (Subp, Global_Mode), Kind);
- Return_Globals_From_List
- (First_Global (Subp, Global_Mode, Refined => True), Kind);
- end Return_Globals_Of_Mode;
+ procedure Return_Globals_Inst is new Handle_Globals (Return_Global);
-- Start of processing for Return_Globals
begin
- Return_Globals_Of_Mode (Name_Proof_In);
- Return_Globals_Of_Mode (Name_Input);
- Return_Globals_Of_Mode (Name_Output);
- Return_Globals_Of_Mode (Name_In_Out);
+ Return_Globals_Inst (Subp);
end Return_Globals;
--------------------------------
-- Return_Parameter_Or_Global --
--------------------------------
- procedure Return_The_Global
- (Id : Entity_Id;
- Mode : Formal_Kind;
- Subp : Entity_Id)
+ procedure Return_Parameter_Or_Global
+ (Id : Entity_Id;
+ Typ : Entity_Id;
+ Kind : Formal_Kind;
+ Subp : Entity_Id;
+ Global_Var : Boolean)
is
- Elem : constant Perm_Tree_Access := Get (Current_Perm_Env, Id);
- pragma Assert (Elem /= null);
-
begin
- -- Observed IN parameters and globals need not return a permission to
- -- the caller.
+ -- Shallow parameters and globals need not be considered
+
+ if not Is_Deep (Typ) then
+ return;
- if Mode = E_In_Parameter
+ elsif Kind = E_In_Parameter then
- -- Check this for read-only globals.
+ -- Input global variables are observed only
- then
- if Permission (Elem) /= Unrestricted
- and then Permission (Elem) /= Observed
+ if Global_Var then
+ return;
+
+ -- Anonymous access to constant is an observe
+
+ elsif Is_Anonymous_Access_Type (Typ)
+ and then Is_Access_Constant (Typ)
then
- Perm_Error_Subprogram_End
- (E => Id,
- Subp => Subp,
- Perm => Observed,
- Found_Perm => Permission (Elem));
+ return;
+
+ -- Deep types other than access types define an observe
+
+ elsif not Is_Access_Type (Typ) then
+ return;
end if;
+ end if;
- -- All globals of mode out or in/out should return with mode
- -- Unrestricted.
+ -- All other parameters and globals should return with mode RW to the
+ -- caller.
- else
- if Permission (Elem) /= Unrestricted then
+ declare
+ Tree : constant Perm_Tree_Access := Get (Current_Perm_Env, Id);
+ begin
+ if Permission (Tree) /= Read_Write then
Perm_Error_Subprogram_End
(E => Id,
Subp => Subp,
- Perm => Unrestricted,
- Found_Perm => Permission (Elem));
+ Perm => Read_Write,
+ Found_Perm => Permission (Tree));
end if;
- end if;
- end Return_The_Global;
+ end;
+ end Return_Parameter_Or_Global;
+
+ -----------------------
+ -- Return_Parameters --
+ -----------------------
+
+ procedure Return_Parameters (Subp : Entity_Id) is
+ Formal : Entity_Id;
+ begin
+ Formal := First_Formal (Subp);
+ while Present (Formal) loop
+ Return_Parameter_Or_Global
+ (Id => Formal,
+ Typ => Underlying_Type (Etype (Formal)),
+ Kind => Ekind (Formal),
+ Subp => Subp,
+ Global_Var => False);
+ Next_Formal (Formal);
+ end loop;
+ end Return_Parameters;
-------------------------
-- Set_Perm_Extensions --
-------------------------
procedure Set_Perm_Extensions (T : Perm_Tree_Access; P : Perm_Kind) is
+
procedure Free_Perm_Tree_Children (T : Perm_Tree_Access);
+ -- Free the permission tree of children if any, prio to replacing T
+
+ -----------------------------
+ -- Free_Perm_Tree_Children --
+ -----------------------------
+
procedure Free_Perm_Tree_Children (T : Perm_Tree_Access) is
begin
case Kind (T) is
@@ -3710,740 +4434,474 @@ package body Sem_SPARK is
null;
when Reference =>
- Free_Perm_Tree (T.all.Tree.Get_All);
+ Free_Tree (T.all.Tree.Get_All);
when Array_Component =>
- Free_Perm_Tree (T.all.Tree.Get_Elem);
-
- -- Free every Component subtree
+ Free_Tree (T.all.Tree.Get_Elem);
when Record_Component =>
declare
- Comp : Perm_Tree_Access;
+ Hashtbl : Perm_Tree_Maps.Instance := Component (T);
+ Comp : Perm_Tree_Access;
begin
- Comp := Perm_Tree_Maps.Get_First (Component (T));
+ Comp := Perm_Tree_Maps.Get_First (Hashtbl);
while Comp /= null loop
- Free_Perm_Tree (Comp);
- Comp := Perm_Tree_Maps.Get_Next (Component (T));
+ Free_Tree (Comp);
+ Comp := Perm_Tree_Maps.Get_Next (Hashtbl);
end loop;
- Free_Perm_Tree (T.all.Tree.Other_Components);
+ Perm_Tree_Maps.Reset (Hashtbl);
end;
end case;
end Free_Perm_Tree_Children;
- Son : constant Perm_Tree :=
- Perm_Tree'
- (Kind => Entire_Object,
- Is_Node_Deep => Is_Node_Deep (T),
- Permission => Permission (T),
- Children_Permission => P);
+ -- Start of processing for Set_Perm_Extensions
begin
Free_Perm_Tree_Children (T);
- T.all.Tree := Son;
+ T.all.Tree := Perm_Tree'(Kind => Entire_Object,
+ Is_Node_Deep => Is_Node_Deep (T),
+ Permission => Permission (T),
+ Children_Permission => P);
end Set_Perm_Extensions;
------------------------------
- -- Set_Perm_Prefixes --
+ -- Set_Perm_Extensions_Move --
------------------------------
- function Set_Perm_Prefixes
- (N : Node_Id;
- New_Perm : Perm_Kind)
- return Perm_Tree_Access
+ procedure Set_Perm_Extensions_Move
+ (T : Perm_Tree_Access;
+ E : Entity_Id)
is
begin
+ -- Shallow extensions are set to RW
- case Nkind (N) is
-
- when N_Identifier
- | N_Expanded_Name
- | N_Defining_Identifier
- =>
- if Nkind (N) = N_Defining_Identifier
- and then New_Perm = Borrowed
- then
- raise Program_Error;
- end if;
-
- declare
- P : Node_Id;
- C : Perm_Tree_Access;
-
- begin
- if Nkind (N) = N_Defining_Identifier then
- P := N;
- else
- P := Entity (N);
- end if;
-
- C := Get (Current_Perm_Env, Unique_Entity (P));
- pragma Assert (C /= null);
-
- -- Setting the initialization map to True, so that this
- -- variable cannot be ignored anymore when looking at end
- -- of elaboration of package.
-
- Set (Current_Initialization_Map, Unique_Entity (P), True);
- if New_Perm = Observed
- and then C = null
- then
-
- -- No null possible here, there are no parents for the path.
- -- This means we are using a global variable without adding
- -- it in environment with a global aspect.
-
- Illegal_Global_Usage (N);
- end if;
-
- C.all.Tree.Permission := New_Perm;
- return C;
- end;
-
- when N_Type_Conversion
- | N_Unchecked_Type_Conversion
- | N_Qualified_Expression
- =>
- return Set_Perm_Prefixes (Expression (N), New_Perm);
-
- when N_Parameter_Specification =>
- raise Program_Error;
-
- -- We set the permission tree of its prefix, and then we extract
- -- our subtree from the returned pointer and assign an adequate
- -- permission to it, if unfolded. If folded, we unroll the tree
- -- in one step.
-
- when N_Selected_Component =>
- declare
- C : constant Perm_Tree_Access :=
- Set_Perm_Prefixes (Prefix (N), New_Perm);
-
- begin
- if C = null then
+ if not Is_Node_Deep (T) then
+ Set_Perm_Extensions (T, Read_Write);
+ return;
+ end if;
- -- We went through a function call, do nothing
+ -- Deep extensions are set to W before .all and NO afterwards
- return null;
- end if;
+ T.all.Tree.Permission := Write_Only;
- pragma Assert (Kind (C) = Entire_Object
- or else Kind (C) = Record_Component);
+ case T.all.Tree.Kind is
- if Kind (C) = Record_Component then
- -- The tree is unfolded. We just modify the permission and
- -- return the record subtree.
+ -- For a folded tree of composite type, unfold the tree for better
+ -- precision.
+ when Entire_Object =>
+ case Ekind (E) is
+ when E_Array_Type
+ | E_Array_Subtype
+ =>
declare
- Selected_Component : constant Entity_Id :=
- Entity (Selector_Name (N));
-
- Selected_C : Perm_Tree_Access :=
- Perm_Tree_Maps.Get
- (Component (C), Selected_Component);
-
+ C : constant Perm_Tree_Access :=
+ new Perm_Tree_Wrapper'
+ (Tree =>
+ (Kind => Entire_Object,
+ Is_Node_Deep => Is_Node_Deep (T),
+ Permission => Read_Write,
+ Children_Permission => Read_Write));
begin
- if Selected_C = null then
- Selected_C := Other_Components (C);
- end if;
-
- pragma Assert (Selected_C /= null);
- Selected_C.all.Tree.Permission := New_Perm;
- return Selected_C;
+ Set_Perm_Extensions_Move (C, Component_Type (E));
+ T.all.Tree := (Kind => Array_Component,
+ Is_Node_Deep => Is_Node_Deep (T),
+ Permission => Write_Only,
+ Get_Elem => C);
end;
- elsif Kind (C) = Entire_Object then
+ when Record_Kind =>
declare
- -- Expand the tree. Replace the node with
- -- Record_Component.
-
- Elem : Node_Id;
-
- -- Create an empty hash table
-
+ C : Perm_Tree_Access;
+ Comp : Entity_Id;
Hashtbl : Perm_Tree_Maps.Instance;
- -- We create the unrolled nodes, that will all have same
- -- permission than parent.
-
- Son : Perm_Tree_Access;
- Children_Perm : constant Perm_Kind :=
- Children_Permission (C);
-
begin
- -- We change the current node from Entire_Object to
- -- Record_Component with same permission and an empty
- -- hash table as component list.
-
- C.all.Tree :=
- (Kind => Record_Component,
- Is_Node_Deep => Is_Node_Deep (C),
- Permission => Permission (C),
- Component => Hashtbl,
- Other_Components =>
- new Perm_Tree_Wrapper'
+ Comp := First_Component_Or_Discriminant (E);
+ while Present (Comp) loop
+ C := new Perm_Tree_Wrapper'
(Tree =>
- (Kind => Entire_Object,
- Is_Node_Deep => True,
- Permission => Children_Perm,
- Children_Permission => Children_Perm)
- ));
+ (Kind => Entire_Object,
+ Is_Node_Deep => Is_Deep (Etype (Comp)),
+ Permission => Read_Write,
+ Children_Permission => Read_Write));
+ Set_Perm_Extensions_Move (C, Etype (Comp));
+ Perm_Tree_Maps.Set (Hashtbl, Comp, C);
+ Next_Component_Or_Discriminant (Comp);
+ end loop;
- -- We fill the hash table with all sons of the record,
- -- with basic Entire_Objects nodes.
+ T.all.Tree :=
+ (Kind => Record_Component,
+ Is_Node_Deep => Is_Node_Deep (T),
+ Permission => Write_Only,
+ Component => Hashtbl);
+ end;
- Elem := First_Component_Or_Discriminant
- (Etype (Prefix (N)));
+ -- Otherwise, extensions are set to NO
- while Present (Elem) loop
- Son := new Perm_Tree_Wrapper'
- (Tree =>
- (Kind => Entire_Object,
- Is_Node_Deep => Is_Deep (Etype (Elem)),
- Permission => Children_Perm,
- Children_Permission => Children_Perm));
+ when others =>
+ Set_Perm_Extensions (T, No_Access);
+ end case;
- Perm_Tree_Maps.Set (C.all.Tree.Component, Elem, Son);
- Next_Component_Or_Discriminant (Elem);
- end loop;
- -- Now we set the right field to Borrowed, and then we
- -- return the tree to the sons, so that the recursion can
- -- continue.
+ when Reference =>
+ Set_Perm_Extensions (T, No_Access);
- declare
- Selected_Component : constant Entity_Id :=
- Entity (Selector_Name (N));
- Selected_C : Perm_Tree_Access :=
- Perm_Tree_Maps.Get
- (Component (C), Selected_Component);
+ when Array_Component =>
+ Set_Perm_Extensions_Move (Get_Elem (T), Component_Type (E));
- begin
- if Selected_C = null then
- Selected_C := Other_Components (C);
- end if;
+ when Record_Component =>
+ declare
+ C : Perm_Tree_Access;
+ Comp : Entity_Id;
- pragma Assert (Selected_C /= null);
- Selected_C.all.Tree.Permission := New_Perm;
- return Selected_C;
- end;
- end;
- else
- raise Program_Error;
- end if;
+ begin
+ Comp := First_Component_Or_Discriminant (E);
+ while Present (Comp) loop
+ C := Perm_Tree_Maps.Get (Component (T), Comp);
+ pragma Assert (C /= null);
+ Set_Perm_Extensions_Move (C, Etype (Comp));
+ Next_Component_Or_Discriminant (Comp);
+ end loop;
end;
+ end case;
+ end Set_Perm_Extensions_Move;
- -- We set the permission tree of its prefix, and then we extract
- -- from the returned pointer the subtree and assign an adequate
- -- permission to it, if unfolded. If folded, we unroll the tree in
- -- one step.
+ -----------------------
+ -- Set_Perm_Prefixes --
+ -----------------------
- when N_Indexed_Component
- | N_Slice
+ function Set_Perm_Prefixes
+ (N : Node_Id;
+ Perm : Perm_Kind_Option) return Perm_Tree_Access
+ is
+ begin
+ case Nkind (N) is
+ when N_Expanded_Name
+ | N_Identifier
=>
declare
- C : constant Perm_Tree_Access :=
- Set_Perm_Prefixes (Prefix (N), New_Perm);
+ E : constant Entity_Id := Unique_Entity (Entity (N));
+ C : constant Perm_Tree_Access := Get (Current_Perm_Env, E);
+ pragma Assert (C /= null);
begin
- if C = null then
-
- -- We went through a function call, do nothing
-
- return null;
+ if Perm /= None then
+ C.all.Tree.Permission := Glb (Perm, Permission (C));
end if;
- pragma Assert (Kind (C) = Entire_Object
- or else Kind (C) = Array_Component);
-
- if Kind (C) = Array_Component then
-
- -- The tree is unfolded. We just modify the permission and
- -- return the elem subtree.
-
- pragma Assert (Get_Elem (C) /= null);
- C.all.Tree.Get_Elem.all.Tree.Permission := New_Perm;
- return Get_Elem (C);
-
- elsif Kind (C) = Entire_Object then
- declare
- -- Expand the tree. Replace node with Array_Component.
-
- Son : Perm_Tree_Access;
-
- begin
- Son := new Perm_Tree_Wrapper'
- (Tree =>
- (Kind => Entire_Object,
- Is_Node_Deep => Is_Node_Deep (C),
- Permission => New_Perm,
- Children_Permission => Children_Permission (C)));
-
- -- Children_Permission => Children_Permission (C)
- -- this line should be checked maybe New_Perm
- -- instead of Children_Permission (C)
-
- -- We change the current node from Entire_Object
- -- to Array_Component with same permission and the
- -- previously defined son.
-
- C.all.Tree := (Kind => Array_Component,
- Is_Node_Deep => Is_Node_Deep (C),
- Permission => New_Perm,
- Get_Elem => Son);
- return Get_Elem (C);
- end;
- else
- raise Program_Error;
- end if;
+ return C;
end;
- -- We set the permission tree of its prefix, and then we extract
- -- from the returned pointer the subtree and assign an adequate
- -- permission to it, if unfolded. If folded, we unroll the tree
- -- at one step.
+ -- For a non-terminal path, we set the permission tree of its prefix,
+ -- and then we extract from the returned pointer the subtree and
+ -- assign an adequate permission to it, if unfolded. If folded,
+ -- we unroll the tree one level.
when N_Explicit_Dereference =>
declare
C : constant Perm_Tree_Access :=
- Set_Perm_Prefixes (Prefix (N), New_Perm);
-
- begin
- if C = null then
-
- -- We went through a function call. Do nothing.
-
- return null;
- end if;
-
+ Set_Perm_Prefixes (Prefix (N), Perm);
+ pragma Assert (C /= null);
pragma Assert (Kind (C) = Entire_Object
or else Kind (C) = Reference);
+ begin
+ -- The tree is already unfolded. Replace the permission of the
+ -- dereference.
if Kind (C) = Reference then
+ declare
+ D : constant Perm_Tree_Access := Get_All (C);
+ pragma Assert (D /= null);
- -- The tree is unfolded. We just modify the permission and
- -- return the elem subtree.
-
- pragma Assert (Get_All (C) /= null);
- C.all.Tree.Get_All.all.Tree.Permission := New_Perm;
- return Get_All (C);
+ begin
+ if Perm /= None then
+ D.all.Tree.Permission := Glb (Perm, Permission (D));
+ end if;
- elsif Kind (C) = Entire_Object then
- declare
- -- Expand the tree. Replace the node with Reference.
+ return D;
+ end;
- Son : Perm_Tree_Access;
+ -- The tree is folded. Expand it.
+ else
+ declare
+ pragma Assert (Kind (C) = Entire_Object);
+
+ Child_P : constant Perm_Kind := Children_Permission (C);
+ D : constant Perm_Tree_Access :=
+ new Perm_Tree_Wrapper'
+ (Tree =>
+ (Kind => Entire_Object,
+ Is_Node_Deep => Is_Deep (Etype (N)),
+ Permission => Child_P,
+ Children_Permission => Child_P));
begin
- Son := new Perm_Tree_Wrapper'
- (Tree =>
- (Kind => Entire_Object,
- Is_Node_Deep => Is_Deep (Etype (N)),
- Permission => New_Perm,
- Children_Permission => Children_Permission (C)));
-
- -- We change the current node from Entire_Object to
- -- Reference with Borrowed and the previous son.
+ if Perm /= None then
+ D.all.Tree.Permission := Perm;
+ end if;
- pragma Assert (Is_Node_Deep (C));
C.all.Tree := (Kind => Reference,
Is_Node_Deep => Is_Node_Deep (C),
- Permission => New_Perm,
- Get_All => Son);
- return Get_All (C);
+ Permission => Permission (C),
+ Get_All => D);
+ return D;
end;
-
- else
- raise Program_Error;
end if;
end;
- when N_Function_Call =>
- return null;
-
- when others =>
- raise Program_Error;
- end case;
- end Set_Perm_Prefixes;
-
- ------------------------------
- -- Set_Perm_Prefixes_Borrow --
- ------------------------------
-
- function Set_Perm_Prefixes_Borrow (N : Node_Id) return Perm_Tree_Access
- is
- begin
- pragma Assert (Current_Checking_Mode = Borrow);
- case Nkind (N) is
-
- when N_Identifier
- | N_Expanded_Name
- =>
- declare
- P : constant Node_Id := Entity (N);
- C : constant Perm_Tree_Access :=
- Get (Current_Perm_Env, Unique_Entity (P));
- pragma Assert (C /= null);
-
- begin
- -- Setting the initialization map to True, so that this
- -- variable cannot be ignored anymore when looking at end
- -- of elaboration of package.
-
- Set (Current_Initialization_Map, Unique_Entity (P), True);
- C.all.Tree.Permission := Borrowed;
- return C;
- end;
-
- when N_Type_Conversion
- | N_Unchecked_Type_Conversion
- | N_Qualified_Expression
- =>
- return Set_Perm_Prefixes_Borrow (Expression (N));
-
- when N_Parameter_Specification
- | N_Defining_Identifier
- =>
- raise Program_Error;
-
- -- We set the permission tree of its prefix, and then we extract
- -- our subtree from the returned pointer and assign an adequate
- -- permission to it, if unfolded. If folded, we unroll the tree
- -- in one step.
-
when N_Selected_Component =>
declare
C : constant Perm_Tree_Access :=
- Set_Perm_Prefixes_Borrow (Prefix (N));
-
- begin
- if C = null then
-
- -- We went through a function call, do nothing
-
- return null;
- end if;
-
- -- The permission of the returned node should be No
-
- pragma Assert (Permission (C) = Borrowed);
+ Set_Perm_Prefixes (Prefix (N), Perm);
+ pragma Assert (C /= null);
pragma Assert (Kind (C) = Entire_Object
or else Kind (C) = Record_Component);
+ begin
+ -- The tree is already unfolded. Replace the permission of the
+ -- component.
if Kind (C) = Record_Component then
-
- -- The tree is unfolded. We just modify the permission and
- -- return the record subtree.
-
declare
- Selected_Component : constant Entity_Id :=
- Entity (Selector_Name (N));
- Selected_C : Perm_Tree_Access :=
- Perm_Tree_Maps.Get
- (Component (C), Selected_Component);
+ Comp : constant Entity_Id := Entity (Selector_Name (N));
+ D : constant Perm_Tree_Access :=
+ Perm_Tree_Maps.Get (Component (C), Comp);
+ pragma Assert (D /= null);
begin
- if Selected_C = null then
- Selected_C := Other_Components (C);
+ if Perm /= None then
+ D.all.Tree.Permission := Glb (Perm, Permission (D));
end if;
- pragma Assert (Selected_C /= null);
- Selected_C.all.Tree.Permission := Borrowed;
- return Selected_C;
+ return D;
end;
- elsif Kind (C) = Entire_Object then
- declare
- -- Expand the tree. Replace the node with
- -- Record_Component.
-
- Elem : Node_Id;
+ -- The tree is folded. Expand it.
- -- Create an empty hash table
+ else
+ declare
+ pragma Assert (Kind (C) = Entire_Object);
+ D : Perm_Tree_Access;
+ D_This : Perm_Tree_Access;
+ Comp : Node_Id;
+ P : Perm_Kind;
+ Child_P : constant Perm_Kind := Children_Permission (C);
Hashtbl : Perm_Tree_Maps.Instance;
-
- -- We create the unrolled nodes, that will all have same
- -- permission than parent.
-
- Son : Perm_Tree_Access;
- ChildrenPerm : constant Perm_Kind :=
- Children_Permission (C);
+ -- Create an empty hash table
begin
- -- We change the current node from Entire_Object to
- -- Record_Component with same permission and an empty
- -- hash table as component list.
-
- C.all.Tree :=
- (Kind => Record_Component,
- Is_Node_Deep => Is_Node_Deep (C),
- Permission => Permission (C),
- Component => Hashtbl,
- Other_Components =>
- new Perm_Tree_Wrapper'
- (Tree =>
- (Kind => Entire_Object,
- Is_Node_Deep => True,
- Permission => ChildrenPerm,
- Children_Permission => ChildrenPerm)
- ));
-
- -- We fill the hash table with all sons of the record,
- -- with basic Entire_Objects nodes.
+ Comp :=
+ First_Component_Or_Discriminant (Etype (Prefix (N)));
- Elem := First_Component_Or_Discriminant
- (Etype (Prefix (N)));
+ while Present (Comp) loop
+ if Perm /= None
+ and then Comp = Entity (Selector_Name (N))
+ then
+ P := Perm;
+ else
+ P := Child_P;
+ end if;
- while Present (Elem) loop
- Son := new Perm_Tree_Wrapper'
+ D := new Perm_Tree_Wrapper'
(Tree =>
(Kind => Entire_Object,
- Is_Node_Deep => Is_Deep (Etype (Elem)),
- Permission => ChildrenPerm,
- Children_Permission => ChildrenPerm));
- Perm_Tree_Maps.Set (C.all.Tree.Component, Elem, Son);
- Next_Component_Or_Discriminant (Elem);
- end loop;
+ Is_Node_Deep => Is_Deep (Etype (Comp)),
+ Permission => P,
+ Children_Permission => Child_P));
+ Perm_Tree_Maps.Set (Hashtbl, Comp, D);
- -- Now we set the right field to Borrowed, and then we
- -- return the tree to the sons, so that the recursion can
- -- continue.
-
- declare
- Selected_Component : constant Entity_Id :=
- Entity (Selector_Name (N));
- Selected_C : Perm_Tree_Access := Perm_Tree_Maps.Get
- (Component (C), Selected_Component);
+ -- Store the tree to return for this component
- begin
- if Selected_C = null then
- Selected_C := Other_Components (C);
+ if Comp = Entity (Selector_Name (N)) then
+ D_This := D;
end if;
- pragma Assert (Selected_C /= null);
- Selected_C.all.Tree.Permission := Borrowed;
- return Selected_C;
- end;
- end;
+ Next_Component_Or_Discriminant (Comp);
+ end loop;
- else
- raise Program_Error;
+ C.all.Tree := (Kind => Record_Component,
+ Is_Node_Deep => Is_Node_Deep (C),
+ Permission => Permission (C),
+ Component => Hashtbl);
+ return D_This;
+ end;
end if;
end;
- -- We set the permission tree of its prefix, and then we extract
- -- from the returned pointer the subtree and assign an adequate
- -- permission to it, if unfolded. If folded, we unroll the tree in
- -- one step.
-
when N_Indexed_Component
| N_Slice
=>
declare
C : constant Perm_Tree_Access :=
- Set_Perm_Prefixes_Borrow (Prefix (N));
-
- begin
- if C = null then
-
- -- We went through a function call, do nothing
-
- return null;
- end if;
-
- pragma Assert (Permission (C) = Borrowed);
+ Set_Perm_Prefixes (Prefix (N), Perm);
+ pragma Assert (C /= null);
pragma Assert (Kind (C) = Entire_Object
or else Kind (C) = Array_Component);
+ begin
+ -- The tree is already unfolded. Replace the permission of the
+ -- component.
if Kind (C) = Array_Component then
+ declare
+ D : constant Perm_Tree_Access := Get_Elem (C);
+ pragma Assert (D /= null);
- -- The tree is unfolded. We just modify the permission and
- -- return the elem subtree.
-
- pragma Assert (Get_Elem (C) /= null);
- C.all.Tree.Get_Elem.all.Tree.Permission := Borrowed;
- return Get_Elem (C);
+ begin
+ if Perm /= None then
+ D.all.Tree.Permission := Glb (Perm, Permission (D));
+ end if;
- elsif Kind (C) = Entire_Object then
- declare
- -- Expand the tree. Replace node with Array_Component.
+ return D;
+ end;
- Son : Perm_Tree_Access;
+ -- The tree is folded. Expand it.
+ else
+ declare
+ pragma Assert (Kind (C) = Entire_Object);
+
+ Child_P : constant Perm_Kind := Children_Permission (C);
+ D : constant Perm_Tree_Access :=
+ new Perm_Tree_Wrapper'
+ (Tree =>
+ (Kind => Entire_Object,
+ Is_Node_Deep => Is_Node_Deep (C),
+ Permission => Child_P,
+ Children_Permission => Child_P));
begin
- Son := new Perm_Tree_Wrapper'
- (Tree =>
- (Kind => Entire_Object,
- Is_Node_Deep => Is_Node_Deep (C),
- Permission => Borrowed,
- Children_Permission => Children_Permission (C)));
-
- -- We change the current node from Entire_Object
- -- to Array_Component with same permission and the
- -- previously defined son.
+ if Perm /= None then
+ D.all.Tree.Permission := Perm;
+ end if;
C.all.Tree := (Kind => Array_Component,
Is_Node_Deep => Is_Node_Deep (C),
- Permission => Borrowed,
- Get_Elem => Son);
- return Get_Elem (C);
+ Permission => Permission (C),
+ Get_Elem => D);
+ return D;
end;
-
- else
- raise Program_Error;
end if;
end;
- -- We set the permission tree of its prefix, and then we extract
- -- from the returned pointer the subtree and assign an adequate
- -- permission to it, if unfolded. If folded, we unroll the tree
- -- at one step.
-
- when N_Explicit_Dereference =>
- declare
- C : constant Perm_Tree_Access :=
- Set_Perm_Prefixes_Borrow (Prefix (N));
+ when N_Qualified_Expression
+ | N_Type_Conversion
+ | N_Unchecked_Type_Conversion
+ =>
+ return Set_Perm_Prefixes (Expression (N), Perm);
- begin
- if C = null then
+ when others =>
+ raise Program_Error;
+ end case;
+ end Set_Perm_Prefixes;
- -- We went through a function call. Do nothing.
+ ------------------------------
+ -- Set_Perm_Prefixes_Assign --
+ ------------------------------
- return null;
- end if;
+ procedure Set_Perm_Prefixes_Assign (N : Node_Id) is
+ C : constant Perm_Tree_Access := Get_Perm_Tree (N);
- -- The permission of the returned node should be No
+ begin
+ case Kind (C) is
+ when Entire_Object =>
+ pragma Assert (Children_Permission (C) = Read_Write);
+ C.all.Tree.Permission := Read_Write;
- pragma Assert (Permission (C) = Borrowed);
- pragma Assert (Kind (C) = Entire_Object
- or else Kind (C) = Reference);
+ when Reference =>
+ C.all.Tree.Permission :=
+ Lub (Permission (C), Permission (Get_All (C)));
- if Kind (C) = Reference then
+ when Array_Component =>
+ null;
- -- The tree is unfolded. We just modify the permission and
- -- return the elem subtree.
+ when Record_Component =>
+ declare
+ Comp : Perm_Tree_Access;
+ Perm : Perm_Kind := Read_Write;
- pragma Assert (Get_All (C) /= null);
- C.all.Tree.Get_All.all.Tree.Permission := Borrowed;
- return Get_All (C);
+ begin
+ -- We take the Glb of all the descendants, and then update the
+ -- permission of the node with it.
- elsif Kind (C) = Entire_Object then
- declare
- -- Expand the tree. Replace the node with Reference.
+ Comp := Perm_Tree_Maps.Get_First (Component (C));
+ while Comp /= null loop
+ Perm := Glb (Perm, Permission (Comp));
+ Comp := Perm_Tree_Maps.Get_Next (Component (C));
+ end loop;
- Son : Perm_Tree_Access;
+ C.all.Tree.Permission := Lub (Permission (C), Perm);
+ end;
+ end case;
- begin
- Son := new Perm_Tree_Wrapper'
- (Tree =>
- (Kind => Entire_Object,
- Is_Node_Deep => Is_Deep (Etype (N)),
- Permission => Borrowed,
- Children_Permission => Children_Permission (C)));
+ case Nkind (N) is
- -- We change the current node from Entire_Object to
- -- Reference with Borrowed and the previous son.
+ -- Base identifier end recursion
- pragma Assert (Is_Node_Deep (C));
- C.all.Tree := (Kind => Reference,
- Is_Node_Deep => Is_Node_Deep (C),
- Permission => Borrowed,
- Get_All => Son);
- return Get_All (C);
- end;
+ when N_Expanded_Name
+ | N_Identifier
+ =>
+ null;
- else
- raise Program_Error;
- end if;
- end;
+ when N_Explicit_Dereference
+ | N_Indexed_Component
+ | N_Selected_Component
+ | N_Slice
+ =>
+ Set_Perm_Prefixes_Assign (Prefix (N));
- when N_Function_Call =>
- return null;
+ when N_Qualified_Expression
+ | N_Type_Conversion
+ | N_Unchecked_Type_Conversion
+ =>
+ Set_Perm_Prefixes_Assign (Expression (N));
when others =>
raise Program_Error;
end case;
- end Set_Perm_Prefixes_Borrow;
+ end Set_Perm_Prefixes_Assign;
-------------------
-- Setup_Globals --
-------------------
procedure Setup_Globals (Subp : Entity_Id) is
- procedure Setup_Globals_From_List
- (First_Item : Node_Id;
- Kind : Formal_Kind);
- -- Set up global items from the list starting at Item
- procedure Setup_Globals_Of_Mode (Global_Mode : Name_Id);
- -- Set up global items for the mode Global_Mode
+ procedure Setup_Global
+ (Expr : Node_Id;
+ Typ : Entity_Id;
+ Kind : Formal_Kind;
+ Subp : Entity_Id;
+ Global_Var : Boolean);
+ -- Proxy procedure to set up globals, to adjust for the type of first
+ -- parameter expected by Setup_Parameter_Or_Global.
- -----------------------------
- -- Setup_Globals_From_List --
- -----------------------------
+ ------------------
+ -- Setup_Global --
+ ------------------
- procedure Setup_Globals_From_List
- (First_Item : Node_Id;
- Kind : Formal_Kind)
+ procedure Setup_Global
+ (Expr : Node_Id;
+ Typ : Entity_Id;
+ Kind : Formal_Kind;
+ Subp : Entity_Id;
+ Global_Var : Boolean)
is
- Item : Node_Id := First_Item;
- E : Entity_Id;
-
- begin
- while Present (Item) loop
- E := Entity (Item);
-
- -- Ignore abstract states, which play no role in pointer aliasing
-
- if Ekind (E) = E_Abstract_State then
- null;
- else
- Setup_Parameter_Or_Global (E, Kind, Global_Var => True);
- end if;
- Next_Global (Item);
- end loop;
- end Setup_Globals_From_List;
-
- ---------------------------
- -- Setup_Globals_Of_Mode --
- ---------------------------
-
- procedure Setup_Globals_Of_Mode (Global_Mode : Name_Id) is
- Kind : Formal_Kind;
-
begin
- case Global_Mode is
- when Name_Input
- | Name_Proof_In
- =>
- Kind := E_In_Parameter;
-
- when Name_Output =>
- Kind := E_Out_Parameter;
-
- when Name_In_Out =>
- Kind := E_In_Out_Parameter;
-
- when others =>
- raise Program_Error;
- end case;
-
- -- Set up both global items from Global and Refined_Global pragmas
+ Setup_Parameter_Or_Global
+ (Id => Entity (Expr),
+ Typ => Typ,
+ Kind => Kind,
+ Subp => Subp,
+ Global_Var => Global_Var);
+ end Setup_Global;
- Setup_Globals_From_List (First_Global (Subp, Global_Mode), Kind);
- Setup_Globals_From_List
- (First_Global (Subp, Global_Mode, Refined => True), Kind);
- end Setup_Globals_Of_Mode;
+ procedure Setup_Globals_Inst is new Handle_Globals (Setup_Global);
-- Start of processing for Setup_Globals
begin
- Setup_Globals_Of_Mode (Name_Proof_In);
- Setup_Globals_Of_Mode (Name_Input);
- Setup_Globals_Of_Mode (Name_Output);
- Setup_Globals_Of_Mode (Name_In_Out);
+ Setup_Globals_Inst (Subp);
end Setup_Globals;
-------------------------------
@@ -4452,178 +4910,110 @@ package body Sem_SPARK is
procedure Setup_Parameter_Or_Global
(Id : Entity_Id;
- Mode : Formal_Kind;
+ Typ : Entity_Id;
+ Kind : Formal_Kind;
+ Subp : Entity_Id;
Global_Var : Boolean)
is
- Elem : Perm_Tree_Access;
- View_Typ : Entity_Id;
+ Perm : Perm_Kind_Option;
begin
- if Present (Full_View (Etype (Id))) then
- View_Typ := Full_View (Etype (Id));
- else
- View_Typ := Etype (Id);
- end if;
+ case Kind is
+ when E_In_Parameter =>
- Elem := new Perm_Tree_Wrapper'
- (Tree =>
- (Kind => Entire_Object,
- Is_Node_Deep => Is_Deep (Etype (Id)),
- Permission => Unrestricted,
- Children_Permission => Unrestricted));
+ -- Shallow parameters and globals need not be considered
- case Mode is
+ if not Is_Deep (Typ) then
+ Perm := None;
- -- All out and in out parameters are considered to be unrestricted.
- -- They are whether borrowed or moved. Ada Rules would restrict
- -- these permissions further. For example an in parameter cannot
- -- be written.
+ -- Inputs of functions have R permission only
- -- In the following we deal with in parameters that can be observed.
- -- We only consider the observing cases.
+ elsif Ekind (Subp) = E_Function then
+ Perm := Read_Only;
- when E_In_Parameter =>
+ -- Input global variables have R permission only
- -- Handling global variables as IN parameters here.
- -- Remove the following condition once it's decided how globals
- -- should be considered. ???
- --
- -- In SPARK, IN access-to-variable is an observe operation for
- -- a function, and a borrow operation for a procedure.
-
- if not Global_Var then
- if (Is_Access_Type (View_Typ)
- and then Is_Access_Constant (View_Typ)
- and then Is_Anonymous_Access_Type (View_Typ))
- or else
- (Is_Access_Type (View_Typ)
- and then Ekind (Scope (Id)) = E_Function)
- or else
- (not Is_Access_Type (View_Typ)
- and then Is_Deep (View_Typ)
- and then not Is_Anonymous_Access_Type (View_Typ))
- then
- Elem.all.Tree.Permission := Observed;
- Elem.all.Tree.Children_Permission := Observed;
+ elsif Global_Var then
+ Perm := Read_Only;
- else
- Elem.all.Tree.Permission := Unrestricted;
- Elem.all.Tree.Children_Permission := Unrestricted;
- end if;
+ -- Anonymous access to constant is an observe
+
+ elsif Is_Anonymous_Access_Type (Typ)
+ and then Is_Access_Constant (Typ)
+ then
+ Perm := Read_Only;
+
+ -- Other access types are a borrow
+
+ elsif Is_Access_Type (Typ) then
+ Perm := Read_Write;
+
+ -- Deep types other than access types define an observe
else
- Elem.all.Tree.Permission := Observed;
- Elem.all.Tree.Children_Permission := Observed;
+ Perm := Read_Only;
end if;
- -- When out or in/out formal or global parameters, we set them to
- -- the Unrestricted state. "We want to be able to assume that all
- -- relevant writable globals are unrestricted when a subprogram
- -- starts executing". Formal parameters of mode out or in/out
- -- are whether Borrowers or the targets of a move operation:
- -- they start theirs lives in the subprogram as Unrestricted.
+ when E_Out_Parameter
+ | E_In_Out_Parameter
+ =>
+ -- Shallow parameters and globals need not be considered
+
+ if not Is_Deep (Typ) then
+ Perm := None;
- when others =>
- Elem.all.Tree.Permission := Unrestricted;
- Elem.all.Tree.Children_Permission := Unrestricted;
+ -- Functions cannot have outputs in SPARK
+
+ elsif Ekind (Subp) = E_Function then
+ if Kind = E_Out_Parameter then
+ Error_Msg_N ("function with OUT parameter is not "
+ & "allowed in SPARK", Id);
+ else
+ Error_Msg_N ("function with `IN OUT` parameter is not "
+ & "allowed in SPARK", Id);
+ end if;
+
+ return;
+
+ -- Deep types define a borrow or a move
+
+ else
+ Perm := Read_Write;
+ end if;
end case;
- Set (Current_Perm_Env, Id, Elem);
+ if Perm /= None then
+ declare
+ Tree : constant Perm_Tree_Access :=
+ new Perm_Tree_Wrapper'
+ (Tree =>
+ (Kind => Entire_Object,
+ Is_Node_Deep => Is_Deep (Etype (Id)),
+ Permission => Perm,
+ Children_Permission => Perm));
+ begin
+ Set (Current_Perm_Env, Id, Tree);
+ end;
+ end if;
end Setup_Parameter_Or_Global;
----------------------
-- Setup_Parameters --
----------------------
- procedure Setup_Parameters (Subp : Entity_Id) is Formal : Entity_Id;
+ procedure Setup_Parameters (Subp : Entity_Id) is
+ Formal : Entity_Id;
begin
Formal := First_Formal (Subp);
while Present (Formal) loop
Setup_Parameter_Or_Global
- (Formal, Ekind (Formal), Global_Var => False);
+ (Id => Formal,
+ Typ => Underlying_Type (Etype (Formal)),
+ Kind => Ekind (Formal),
+ Subp => Subp,
+ Global_Var => False);
Next_Formal (Formal);
end loop;
end Setup_Parameters;
- -------------------------------
- -- Has_Ownership_Aspect_True --
- -------------------------------
-
- function Has_Ownership_Aspect_True
- (N : Entity_Id;
- Msg : String)
- return Boolean
- is
- begin
- case Ekind (Etype (N)) is
- when Access_Kind =>
- if Ekind (Etype (N)) = E_General_Access_Type then
- Error_Msg_NE (Msg & " & not allowed " &
- "(Named General Access type)", N, N);
- return False;
-
- else
- return True;
- end if;
-
- when E_Array_Type
- | E_Array_Subtype
- =>
- declare
- Com_Ty : constant Node_Id := Component_Type (Etype (N));
- Ret : Boolean := Has_Ownership_Aspect_True (Com_Ty, "");
-
- begin
- if Nkind (Parent (N)) = N_Full_Type_Declaration and
- Is_Anonymous_Access_Type (Com_Ty)
- then
- Ret := False;
- end if;
-
- if not Ret then
- Error_Msg_NE (Msg & " & not allowed "
- & "(Components of Named General Access type or"
- & " Anonymous type)", N, N);
- end if;
- return Ret;
- end;
-
- -- ??? What about hidden components
-
- when E_Record_Type
- | E_Record_Subtype
- =>
- declare
- Elmt : Entity_Id;
- Elmt_T_Perm : Boolean := True;
- Elmt_Perm, Elmt_Anonym : Boolean;
-
- begin
- Elmt := First_Component_Or_Discriminant (Etype (N));
- while Present (Elmt) loop
- Elmt_Perm := Has_Ownership_Aspect_True (Elmt,
- "type of component");
- Elmt_Anonym := Is_Anonymous_Access_Type (Etype (Elmt));
- if Elmt_Anonym then
- Error_Msg_NE
- ("type of component & not allowed"
- & " (Components of Anonymous type)", Elmt, Elmt);
- end if;
- Elmt_T_Perm := Elmt_T_Perm and Elmt_Perm and not Elmt_Anonym;
- Next_Component_Or_Discriminant (Elmt);
- end loop;
- if not Elmt_T_Perm then
- Error_Msg_NE
- (Msg & " & not allowed (One or "
- & "more components have Ownership Aspect False)",
- N, N);
- end if;
- return Elmt_T_Perm;
- end;
-
- when others =>
- return True;
- end case;
-
- end Has_Ownership_Aspect_True;
end Sem_SPARK;
diff --git a/gcc/ada/sem_spark.ads b/gcc/ada/sem_spark.ads
index e83b661..ee4126a 100644
--- a/gcc/ada/sem_spark.ads
+++ b/gcc/ada/sem_spark.ads
@@ -23,9 +23,9 @@
-- --
------------------------------------------------------------------------------
--- This package implements an anti-aliasing analysis for access types. The
--- rules that are enforced are defined in the anti-aliasing section of the
--- SPARK RM 6.4.2
+-- This package implements an ownership analysis for access types. The rules
+-- that are enforced are defined in section 3.10 of the SPARK Reference
+-- Manual.
--
-- Check_Safe_Pointers is called by Gnat1drv, when GNATprove mode is
-- activated. It does an analysis of the source code, looking for code that is
@@ -138,6 +138,6 @@ package Sem_SPARK is
procedure Check_Safe_Pointers (N : Node_Id);
-- The entry point of this package. It analyzes a node and reports errors
- -- when there are violations of aliasing rules.
+ -- when there are violations of ownership rules.
end Sem_SPARK;
diff --git a/gcc/ada/sem_util.adb b/gcc/ada/sem_util.adb
index 16c6711..77eefdc 100644
--- a/gcc/ada/sem_util.adb
+++ b/gcc/ada/sem_util.adb
@@ -6721,33 +6721,26 @@ package body Sem_Util is
-- Enclosing_Generic_Body --
----------------------------
- function Enclosing_Generic_Body
- (N : Node_Id) return Node_Id
- is
- P : Node_Id;
- Decl : Node_Id;
- Spec : Node_Id;
+ function Enclosing_Generic_Body (N : Node_Id) return Node_Id is
+ Par : Node_Id;
+ Spec_Id : Entity_Id;
begin
- P := Parent (N);
- while Present (P) loop
- if Nkind (P) = N_Package_Body
- or else Nkind (P) = N_Subprogram_Body
- then
- Spec := Corresponding_Spec (P);
-
- if Present (Spec) then
- Decl := Unit_Declaration_Node (Spec);
+ Par := Parent (N);
+ while Present (Par) loop
+ if Nkind_In (Par, N_Package_Body, N_Subprogram_Body) then
+ Spec_Id := Corresponding_Spec (Par);
- if Nkind (Decl) = N_Generic_Package_Declaration
- or else Nkind (Decl) = N_Generic_Subprogram_Declaration
- then
- return P;
- end if;
+ if Present (Spec_Id)
+ and then Nkind_In (Unit_Declaration_Node (Spec_Id),
+ N_Generic_Package_Declaration,
+ N_Generic_Subprogram_Declaration)
+ then
+ return Par;
end if;
end if;
- P := Parent (P);
+ Par := Parent (Par);
end loop;
return Empty;
@@ -6757,38 +6750,34 @@ package body Sem_Util is
-- Enclosing_Generic_Unit --
----------------------------
- function Enclosing_Generic_Unit
- (N : Node_Id) return Node_Id
- is
- P : Node_Id;
- Decl : Node_Id;
- Spec : Node_Id;
+ function Enclosing_Generic_Unit (N : Node_Id) return Node_Id is
+ Par : Node_Id;
+ Spec_Decl : Node_Id;
+ Spec_Id : Entity_Id;
begin
- P := Parent (N);
- while Present (P) loop
- if Nkind (P) = N_Generic_Package_Declaration
- or else Nkind (P) = N_Generic_Subprogram_Declaration
+ Par := Parent (N);
+ while Present (Par) loop
+ if Nkind_In (Par, N_Generic_Package_Declaration,
+ N_Generic_Subprogram_Declaration)
then
- return P;
+ return Par;
- elsif Nkind (P) = N_Package_Body
- or else Nkind (P) = N_Subprogram_Body
- then
- Spec := Corresponding_Spec (P);
+ elsif Nkind_In (Par, N_Package_Body, N_Subprogram_Body) then
+ Spec_Id := Corresponding_Spec (Par);
- if Present (Spec) then
- Decl := Unit_Declaration_Node (Spec);
+ if Present (Spec_Id) then
+ Spec_Decl := Unit_Declaration_Node (Spec_Id);
- if Nkind (Decl) = N_Generic_Package_Declaration
- or else Nkind (Decl) = N_Generic_Subprogram_Declaration
+ if Nkind_In (Spec_Decl, N_Generic_Package_Declaration,
+ N_Generic_Subprogram_Declaration)
then
- return Decl;
+ return Spec_Decl;
end if;
end if;
end if;
- P := Parent (P);
+ Par := Parent (Par);
end loop;
return Empty;
@@ -7579,6 +7568,18 @@ package body Sem_Util is
end loop;
end Examine_Array_Bounds;
+ -------------------
+ -- Exceptions_OK --
+ -------------------
+
+ function Exceptions_OK return Boolean is
+ begin
+ return
+ not (Restriction_Active (No_Exception_Handlers) or else
+ Restriction_Active (No_Exception_Propagation) or else
+ Restriction_Active (No_Exceptions));
+ end Exceptions_OK;
+
--------------------------
-- Explain_Limited_Type --
--------------------------
@@ -9201,12 +9202,12 @@ package body Sem_Util is
Next_Entity (Func);
end loop;
- -- If not found, no way to resolve remaining primitives.
+ -- If not found, no way to resolve remaining primitives
if Cursor = Any_Type then
Error_Msg_N
- ("primitive operation for Iterable type must appear "
- & "in the same list of declarations as the type", Aspect);
+ ("primitive operation for Iterable type must appear in the same "
+ & "list of declarations as the type", Aspect);
end if;
return Cursor;
@@ -10737,7 +10738,7 @@ package body Sem_Util is
-- Asynch_Writers Effective_Writes
--
-- Note that both forms of External have higher precedence than
- -- Synchronous (SPARK RM 7.1.4(10)).
+ -- Synchronous (SPARK RM 7.1.4(9)).
elsif Has_Synchronous then
return Nam_In (Property, Name_Async_Readers, Name_Async_Writers);
@@ -18900,6 +18901,44 @@ package body Sem_Util is
end if;
end Mark_Elaboration_Attributes;
+ ----------------------------------------
+ -- Mark_Save_Invocation_Graph_Of_Body --
+ ----------------------------------------
+
+ procedure Mark_Save_Invocation_Graph_Of_Body is
+ Main : constant Node_Id := Cunit (Main_Unit);
+ Main_Unit : constant Node_Id := Unit (Main);
+ Aux_Id : Entity_Id;
+
+ begin
+ Set_Save_Invocation_Graph_Of_Body (Main);
+
+ -- Assume that the main unit does not have a complimentary unit
+
+ Aux_Id := Empty;
+
+ -- Obtain the complimentary unit of the main unit
+
+ if Nkind_In (Main_Unit, N_Generic_Package_Declaration,
+ N_Generic_Subprogram_Declaration,
+ N_Package_Declaration,
+ N_Subprogram_Declaration)
+ then
+ Aux_Id := Corresponding_Body (Main_Unit);
+
+ elsif Nkind_In (Main_Unit, N_Package_Body,
+ N_Subprogram_Body,
+ N_Subprogram_Renaming_Declaration)
+ then
+ Aux_Id := Corresponding_Spec (Main_Unit);
+ end if;
+
+ if Present (Aux_Id) then
+ Set_Save_Invocation_Graph_Of_Body
+ (Parent (Unit_Declaration_Node (Aux_Id)));
+ end if;
+ end Mark_Save_Invocation_Graph_Of_Body;
+
----------------------------------
-- Matching_Static_Array_Bounds --
----------------------------------
diff --git a/gcc/ada/sem_util.ads b/gcc/ada/sem_util.ads
index 4e4d4ba..3f8d2e7 100644
--- a/gcc/ada/sem_util.ads
+++ b/gcc/ada/sem_util.ads
@@ -708,6 +708,10 @@ package Sem_Util is
-- If no suitable entity is available, return Empty. This routine carries
-- out actions that are tied to SPARK semantics.
+ function Exceptions_OK return Boolean;
+ -- Determine whether exceptions are allowed to be caught, propagated, or
+ -- raised.
+
procedure Explain_Limited_Type (T : Entity_Id; N : Node_Id);
-- This procedure is called after issuing a message complaining about an
-- inappropriate use of limited type T. If useful, it adds additional
@@ -2182,6 +2186,10 @@ package Sem_Util is
-- Modes - Save the Ghost and SPARK modes in effect (if applicable)
-- Warnings - Save the status of Elab_Warnings
+ procedure Mark_Save_Invocation_Graph_Of_Body;
+ -- Notify the body of the main unit that the invocation constructs and
+ -- relations expressed within it must be recorded by the ABE mechanism.
+
function Matching_Static_Array_Bounds
(L_Typ : Node_Id;
R_Typ : Node_Id) return Boolean;
diff --git a/gcc/ada/sem_warn.adb b/gcc/ada/sem_warn.adb
index dda94d2..7e13aa5 100644
--- a/gcc/ada/sem_warn.adb
+++ b/gcc/ada/sem_warn.adb
@@ -632,9 +632,16 @@ package body Sem_Warn is
Expression := Condition (Iter);
- -- For iteration, do not process, since loop will always terminate
-
- elsif Present (Loop_Parameter_Specification (Iter)) then
+ -- For Loop_Parameter_Specification, do not process, since loop
+ -- will always terminate. For Iterator_Specification, also do not
+ -- process. Either it will always terminate (e.g. "for X of
+ -- Some_Array ..."), or we can't tell if it's going to terminate
+ -- without looking at the iterator, so any warning here would be
+ -- noise.
+
+ elsif Present (Loop_Parameter_Specification (Iter))
+ or else Present (Iterator_Specification (Iter))
+ then
return;
end if;
end if;
diff --git a/gcc/ada/sinfo.adb b/gcc/ada/sinfo.adb
index 2464b97..d24938c 100644
--- a/gcc/ada/sinfo.adb
+++ b/gcc/ada/sinfo.adb
@@ -1913,7 +1913,8 @@ package body Sinfo is
or else NT (N).Nkind = N_Package_Instantiation
or else NT (N).Nkind = N_Procedure_Call_Statement
or else NT (N).Nkind = N_Procedure_Instantiation
- or else NT (N).Nkind = N_Requeue_Statement);
+ or else NT (N).Nkind = N_Requeue_Statement
+ or else NT (N).Nkind = N_Variable_Reference_Marker);
return Flag1 (N);
end Is_Elaboration_Checks_OK_Node;
@@ -1932,12 +1933,15 @@ package body Sinfo is
or else NT (N).Nkind = N_Attribute_Reference
or else NT (N).Nkind = N_Call_Marker
or else NT (N).Nkind = N_Entry_Call_Statement
+ or else NT (N).Nkind = N_Expanded_Name
or else NT (N).Nkind = N_Function_Call
or else NT (N).Nkind = N_Function_Instantiation
+ or else NT (N).Nkind = N_Identifier
or else NT (N).Nkind = N_Package_Instantiation
or else NT (N).Nkind = N_Procedure_Call_Statement
or else NT (N).Nkind = N_Procedure_Instantiation
- or else NT (N).Nkind = N_Requeue_Statement);
+ or else NT (N).Nkind = N_Requeue_Statement
+ or else NT (N).Nkind = N_Variable_Reference_Marker);
return Flag3 (N);
end Is_Elaboration_Warnings_OK_Node;
@@ -2130,7 +2134,7 @@ package body Sinfo is
begin
pragma Assert (False
or else NT (N).Nkind = N_Variable_Reference_Marker);
- return Flag1 (N);
+ return Flag4 (N);
end Is_Read;
function Is_Source_Call
@@ -2156,7 +2160,8 @@ package body Sinfo is
or else NT (N).Nkind = N_Package_Instantiation
or else NT (N).Nkind = N_Procedure_Call_Statement
or else NT (N).Nkind = N_Procedure_Instantiation
- or else NT (N).Nkind = N_Requeue_Statement);
+ or else NT (N).Nkind = N_Requeue_Statement
+ or else NT (N).Nkind = N_Variable_Reference_Marker);
return Flag2 (N);
end Is_SPARK_Mode_On_Node;
@@ -2216,7 +2221,7 @@ package body Sinfo is
begin
pragma Assert (False
or else NT (N).Nkind = N_Variable_Reference_Marker);
- return Flag2 (N);
+ return Flag5 (N);
end Is_Write;
function Iteration_Scheme
@@ -3091,6 +3096,14 @@ package body Sinfo is
return Flag18 (N);
end Rounded_Result;
+ function Save_Invocation_Graph_Of_Body
+ (N : Node_Id) return Boolean is
+ begin
+ pragma Assert (False
+ or else NT (N).Nkind = N_Compilation_Unit);
+ return Flag1 (N);
+ end Save_Invocation_Graph_Of_Body;
+
function SCIL_Controlling_Tag
(N : Node_Id) return Node_Id is
begin
@@ -5387,7 +5400,8 @@ package body Sinfo is
or else NT (N).Nkind = N_Package_Instantiation
or else NT (N).Nkind = N_Procedure_Call_Statement
or else NT (N).Nkind = N_Procedure_Instantiation
- or else NT (N).Nkind = N_Requeue_Statement);
+ or else NT (N).Nkind = N_Requeue_Statement
+ or else NT (N).Nkind = N_Variable_Reference_Marker);
Set_Flag1 (N, Val);
end Set_Is_Elaboration_Checks_OK_Node;
@@ -5406,12 +5420,15 @@ package body Sinfo is
or else NT (N).Nkind = N_Attribute_Reference
or else NT (N).Nkind = N_Call_Marker
or else NT (N).Nkind = N_Entry_Call_Statement
+ or else NT (N).Nkind = N_Expanded_Name
or else NT (N).Nkind = N_Function_Call
or else NT (N).Nkind = N_Function_Instantiation
+ or else NT (N).Nkind = N_Identifier
or else NT (N).Nkind = N_Package_Instantiation
or else NT (N).Nkind = N_Procedure_Call_Statement
or else NT (N).Nkind = N_Procedure_Instantiation
- or else NT (N).Nkind = N_Requeue_Statement);
+ or else NT (N).Nkind = N_Requeue_Statement
+ or else NT (N).Nkind = N_Variable_Reference_Marker);
Set_Flag3 (N, Val);
end Set_Is_Elaboration_Warnings_OK_Node;
@@ -5604,7 +5621,7 @@ package body Sinfo is
begin
pragma Assert (False
or else NT (N).Nkind = N_Variable_Reference_Marker);
- Set_Flag1 (N, Val);
+ Set_Flag4 (N, Val);
end Set_Is_Read;
procedure Set_Is_Source_Call
@@ -5630,7 +5647,8 @@ package body Sinfo is
or else NT (N).Nkind = N_Package_Instantiation
or else NT (N).Nkind = N_Procedure_Call_Statement
or else NT (N).Nkind = N_Procedure_Instantiation
- or else NT (N).Nkind = N_Requeue_Statement);
+ or else NT (N).Nkind = N_Requeue_Statement
+ or else NT (N).Nkind = N_Variable_Reference_Marker);
Set_Flag2 (N, Val);
end Set_Is_SPARK_Mode_On_Node;
@@ -5692,7 +5710,7 @@ package body Sinfo is
begin
pragma Assert (False
or else NT (N).Nkind = N_Variable_Reference_Marker);
- Set_Flag2 (N, Val);
+ Set_Flag5 (N, Val);
end Set_Is_Write;
procedure Set_Iteration_Scheme
@@ -6567,6 +6585,14 @@ package body Sinfo is
Set_Flag18 (N, Val);
end Set_Rounded_Result;
+ procedure Set_Save_Invocation_Graph_Of_Body
+ (N : Node_Id; Val : Boolean := True) is
+ begin
+ pragma Assert (False
+ or else NT (N).Nkind = N_Compilation_Unit);
+ Set_Flag1 (N, Val);
+ end Set_Save_Invocation_Graph_Of_Body;
+
procedure Set_SCIL_Controlling_Tag
(N : Node_Id; Val : Node_Id) is
begin
diff --git a/gcc/ada/sinfo.ads b/gcc/ada/sinfo.ads
index b0f992b..b1e57bf 100644
--- a/gcc/ada/sinfo.ads
+++ b/gcc/ada/sinfo.ads
@@ -1762,6 +1762,7 @@ package Sinfo is
-- procedure call statement
-- procedure instantiation
-- requeue statement
+ -- variable reference marker
--
-- Set when the node appears within a context which allows the generation
-- of run-time ABE checks. This flag detemines whether the ABE Processing
@@ -1778,12 +1779,15 @@ package Sinfo is
-- attribute reference
-- call marker
-- entry call statement
+ -- expanded name
-- function call
-- function instantiation
+ -- identifier
-- package instantiation
-- procedure call statement
-- procedure instantiation
-- requeue statement
+ -- variable reference marker
--
-- Set when the node appears within a context where elaboration warnings
-- are enabled. This flag determines whether the ABE processing phase
@@ -1941,7 +1945,7 @@ package Sinfo is
-- the resolution of accidental overloading of binary or unary operators
-- which may occur in instances.
- -- Is_Read (Flag1-Sem)
+ -- Is_Read (Flag4-Sem)
-- Present in variable reference markers. Set when the original variable
-- reference constitues a read of the variable.
@@ -1950,13 +1954,25 @@ package Sinfo is
-- source.
-- Is_SPARK_Mode_On_Node (Flag2-Sem)
- -- Present in nodes which represent an elaboration scenario. Those are
- -- assignment statement, attribute reference, call marker, entry call
- -- statement, expanded name, function call, identifier, instantiation,
- -- procedure call statement, and requeue statement nodes. Set when the
- -- node appears within a context subject to SPARK_Mode On. This flag
- -- determines when the SPARK model of elaboration be activated by the
- -- ABE Processing phase.
+ -- Present in the following nodes:
+ --
+ -- assignment statement
+ -- attribute reference
+ -- call marker
+ -- entry call statement
+ -- expanded name
+ -- function call
+ -- function instantiation
+ -- identifier
+ -- package instantiation
+ -- procedure call statement
+ -- procedure instantiation
+ -- requeue statement
+ -- variable reference marker
+ --
+ -- Set when the node appears within a context subject to SPARK_Mode On.
+ -- This flag determines when the SPARK model of elaboration be activated
+ -- by the ABE Processing phase.
-- Is_Static_Coextension (Flag14-Sem)
-- Present in N_Allocator nodes. Set if the allocator is a coextension
@@ -1989,7 +2005,7 @@ package Sinfo is
-- indicate that the construct is a task master (i.e. has declared tasks
-- or declares an access to a task type).
- -- Is_Write (Flag2-Sem)
+ -- Is_Write (Flag5-Sem)
-- Present in variable reference markers. Set when the original variable
-- reference constitues a write of the variable.
@@ -2328,6 +2344,11 @@ package Sinfo is
-- are the result of expansion of rounded fixed-point divide, conversion
-- and multiplication operations.
+ -- Save_Invocation_Graph_Of_Body (Flag1-Sem)
+ -- Present in compilation unit nodes. Set when the elaboration mechanism
+ -- must record all invocation constructs and invocation relations within
+ -- the body of the compilation unit.
+ --
-- SCIL_Entity (Node4-Sem)
-- Present in SCIL nodes. References the specific tagged type associated
-- with the SCIL node (for an N_SCIL_Dispatching_Call node, this is
@@ -2606,6 +2627,7 @@ package Sinfo is
-- Original_Discriminant (Node2-Sem)
-- Is_Elaboration_Checks_OK_Node (Flag1-Sem)
-- Is_SPARK_Mode_On_Node (Flag2-Sem)
+ -- Is_Elaboration_Warnings_OK_Node (Flag3-Sem)
-- Has_Private_View (Flag11-Sem) (set in generic units)
-- Redundant_Use (Flag13-Sem)
-- Atomic_Sync_Required (Flag14-Sem)
@@ -2857,7 +2879,7 @@ package Sinfo is
-- Einfo.
-- Note: N_Defining_Identifier is an extended node whose fields are
- -- deliberately layed out to match the layout of fields in an ordinary
+ -- deliberately laid out to match the layout of fields in an ordinary
-- N_Identifier node allowing for easy alteration of an identifier
-- node into a defining identifier node. For details, see procedure
-- Sinfo.CN.Change_Identifier_To_Defining_Identifier.
@@ -3204,8 +3226,8 @@ package Sinfo is
-- in package Einfo.
-- Note: N_Defining_Character_Literal is an extended node whose fields
- -- are deliberate layed out to match the layout of fields in an ordinary
- -- N_Character_Literal node allowing for easy alteration of a character
+ -- are deliberately laid out to match layout of fields in an ordinary
+ -- N_Character_Literal node, allowing for easy alteration of a character
-- literal node into a defining character literal node. For details, see
-- Sinfo.CN.Change_Character_Literal_To_Defining_Character_Literal.
@@ -5429,7 +5451,7 @@ package Sinfo is
-- in package Einfo.
-- Note: N_Defining_Operator_Symbol is an extended node whose fields
- -- are deliberately layed out to match the layout of fields in an
+ -- are deliberately laid out to match the layout of fields in an
-- ordinary N_Operator_Symbol node allowing for easy alteration of
-- an operator symbol node into a defining operator symbol node.
-- See Sinfo.CN.Change_Operator_Symbol_To_Defining_Operator_Symbol
@@ -6634,17 +6656,18 @@ package Sinfo is
-- N_Compilation_Unit
-- Sloc points to first token of defining unit name
- -- Library_Unit (Node4-Sem) corresponding/parent spec/body
-- Context_Items (List1) context items and pragmas preceding unit
-- Private_Present (Flag15) set if library unit has private keyword
-- Unit (Node2) library item or subunit
-- Aux_Decls_Node (Node5) points to the N_Compilation_Unit_Aux node
- -- Has_No_Elaboration_Code (Flag17-Sem)
- -- Body_Required (Flag13-Sem) set for spec if body is required
- -- Acts_As_Spec (Flag4-Sem) flag for subprogram body with no spec
- -- Context_Pending (Flag16-Sem)
-- First_Inlined_Subprogram (Node3-Sem)
+ -- Library_Unit (Node4-Sem) corresponding/parent spec/body
+ -- Save_Invocation_Graph_Of_Body (Flag1-Sem)
+ -- Acts_As_Spec (Flag4-Sem) flag for subprogram body with no spec
+ -- Body_Required (Flag13-Sem) set for spec if body is required
-- Has_Pragma_Suppress_All (Flag14-Sem)
+ -- Context_Pending (Flag16-Sem)
+ -- Has_No_Elaboration_Code (Flag17-Sem)
-- N_Compilation_Unit_Aux
-- Sloc is a copy of the Sloc from the N_Compilation_Unit node
@@ -8035,7 +8058,7 @@ package Sinfo is
-- of this node, leaving the N_Selected_Component node used only when
-- the prefix is a record or protected type.
- -- The fields of the N_Expanded_Name node are layed out identically
+ -- The fields of the N_Expanded_Name node are laid out identically
-- to those of the N_Selected_Component node, allowing conversion of
-- an expanded name node to a selected component node to be done
-- easily, see Sinfo.CN.Change_Selected_Component_To_Expanded_Name.
@@ -8051,6 +8074,7 @@ package Sinfo is
-- Associated_Node (Node4-Sem)
-- Is_Elaboration_Checks_OK_Node (Flag1-Sem)
-- Is_SPARK_Mode_On_Node (Flag2-Sem)
+ -- Is_Elaboration_Warnings_OK_Node (Flag3-Sem)
-- Has_Private_View (Flag11-Sem) set in generic units
-- Redundant_Use (Flag13-Sem)
-- Atomic_Sync_Required (Flag14-Sem)
@@ -8576,8 +8600,11 @@ package Sinfo is
-- N_Variable_Reference_Marker
-- Sloc points to Sloc of original variable reference
-- Target (Node1-Sem)
- -- Is_Read (Flag1-Sem)
- -- Is_Write (Flag2-Sem)
+ -- Is_Elaboration_Checks_OK_Node (Flag1-Sem)
+ -- Is_SPARK_Mode_On_Node (Flag2-Sem)
+ -- Is_Elaboration_Warnings_OK_Node (Flag3-Sem)
+ -- Is_Read (Flag4-Sem)
+ -- Is_Write (Flag5-Sem)
-----------
-- Empty --
@@ -9868,7 +9895,7 @@ package Sinfo is
(N : Node_Id) return Boolean; -- Flag4
function Is_Read
- (N : Node_Id) return Boolean; -- Flag1
+ (N : Node_Id) return Boolean; -- Flag4
function Is_Source_Call
(N : Node_Id) return Boolean; -- Flag4
@@ -9895,7 +9922,7 @@ package Sinfo is
(N : Node_Id) return Boolean; -- Flag5
function Is_Write
- (N : Node_Id) return Boolean; -- Flag2
+ (N : Node_Id) return Boolean; -- Flag5
function Iteration_Scheme
(N : Node_Id) return Node_Id; -- Node2
@@ -10164,6 +10191,9 @@ package Sinfo is
function Rounded_Result
(N : Node_Id) return Boolean; -- Flag18
+ function Save_Invocation_Graph_Of_Body
+ (N : Node_Id) return Boolean; -- Flag1
+
function SCIL_Controlling_Tag
(N : Node_Id) return Node_Id; -- Node5
@@ -10972,7 +11002,7 @@ package Sinfo is
(N : Node_Id; Val : Boolean := True); -- Flag4
procedure Set_Is_Read
- (N : Node_Id; Val : Boolean := True); -- Flag1
+ (N : Node_Id; Val : Boolean := True); -- Flag4
procedure Set_Is_Source_Call
(N : Node_Id; Val : Boolean := True); -- Flag4
@@ -10999,7 +11029,7 @@ package Sinfo is
(N : Node_Id; Val : Boolean := True); -- Flag5
procedure Set_Is_Write
- (N : Node_Id; Val : Boolean := True); -- Flag2
+ (N : Node_Id; Val : Boolean := True); -- Flag5
procedure Set_Iteration_Scheme
(N : Node_Id; Val : Node_Id); -- Node2
@@ -11268,6 +11298,9 @@ package Sinfo is
procedure Set_Rounded_Result
(N : Node_Id; Val : Boolean := True); -- Flag18
+ procedure Set_Save_Invocation_Graph_Of_Body
+ (N : Node_Id; Val : Boolean := True); -- Flag1
+
procedure Set_SCIL_Controlling_Tag
(N : Node_Id; Val : Node_Id); -- Node5
@@ -13566,6 +13599,7 @@ package Sinfo is
pragma Inline (Reverse_Present);
pragma Inline (Right_Opnd);
pragma Inline (Rounded_Result);
+ pragma Inline (Save_Invocation_Graph_Of_Body);
pragma Inline (SCIL_Controlling_Tag);
pragma Inline (SCIL_Entity);
pragma Inline (SCIL_Tag_Value);
@@ -13930,6 +13964,7 @@ package Sinfo is
pragma Inline (Set_Reverse_Present);
pragma Inline (Set_Right_Opnd);
pragma Inline (Set_Rounded_Result);
+ pragma Inline (Set_Save_Invocation_Graph_Of_Body);
pragma Inline (Set_SCIL_Controlling_Tag);
pragma Inline (Set_SCIL_Entity);
pragma Inline (Set_SCIL_Tag_Value);
diff --git a/gcc/ada/style.ads b/gcc/ada/style.ads
index b1684a7..0e75389 100644
--- a/gcc/ada/style.ads
+++ b/gcc/ada/style.ads
@@ -125,6 +125,9 @@ package Style is
-- Called with Scan_Ptr pointing to the first minus sign of a comment.
-- Intended for checking any specific rules for comment placement/format.
+ procedure Check_Defining_Identifier_Casing
+ renames Style_Inst.Check_Defining_Identifier_Casing;
+
procedure Check_Dot_Dot
renames Style_Inst.Check_Dot_Dot;
-- Called after scanning out dot dot to check spacing
@@ -219,4 +222,5 @@ package Style is
-- lower case letters. On entry Token_Ptr points to the keyword token.
-- This is not used for keywords appearing as attribute designators,
-- where instead Check_Attribute_Name (True) is called.
+
end Style;
diff --git a/gcc/ada/styleg.adb b/gcc/ada/styleg.adb
index 56526d8..375664b 100644
--- a/gcc/ada/styleg.adb
+++ b/gcc/ada/styleg.adb
@@ -610,6 +610,31 @@ package body Styleg is
end if;
end Check_Comment;
+ --------------------------------------
+ -- Check_Defining_Identifier_Casing --
+ --------------------------------------
+
+ procedure Check_Defining_Identifier_Casing is
+ begin
+ if Style_Check_Mixed_Case_Decls then
+ case Determine_Token_Casing is
+ when All_Lower_Case
+ | All_Upper_Case
+ =>
+ Error_Msg_SC -- CODEFIX
+ ("(style) bad capitalization, mixed case required");
+
+ -- The Unknown case is something like A_B_C, which is both all
+ -- caps and mixed case.
+
+ when Mixed_Case
+ | Unknown
+ =>
+ null; -- OK
+ end case;
+ end if;
+ end Check_Defining_Identifier_Casing;
+
-------------------
-- Check_Dot_Dot --
-------------------
diff --git a/gcc/ada/styleg.ads b/gcc/ada/styleg.ads
index d93121f..f176c02 100644
--- a/gcc/ada/styleg.ads
+++ b/gcc/ada/styleg.ads
@@ -91,6 +91,11 @@ package Styleg is
-- Called with Scan_Ptr pointing to the first minus sign of a comment.
-- Intended for checking any specific rules for comment placement/format.
+ procedure Check_Defining_Identifier_Casing;
+ -- The current token is an identifier that will be a defining
+ -- identifier. Check that it is mixed case, if the appropriate
+ -- switch is set.
+
procedure Check_Dot_Dot;
-- Called after scanning out dot dot to check spacing
diff --git a/gcc/ada/stylesw.adb b/gcc/ada/stylesw.adb
index 549f826..929e2d7 100644
--- a/gcc/ada/stylesw.adb
+++ b/gcc/ada/stylesw.adb
@@ -79,6 +79,7 @@ package body Stylesw is
Style_Check_Boolean_And_Or := False;
Style_Check_Comments := False;
Style_Check_DOS_Line_Terminator := False;
+ Style_Check_Mixed_Case_Decls := False;
Style_Check_End_Labels := False;
Style_Check_Form_Feeds := False;
Style_Check_Horizontal_Tabs := False;
@@ -168,6 +169,7 @@ package body Stylesw is
end if;
Add ('d', Style_Check_DOS_Line_Terminator);
+ Add ('D', Style_Check_Mixed_Case_Decls);
Add ('e', Style_Check_End_Labels);
Add ('f', Style_Check_Form_Feeds);
Add ('h', Style_Check_Horizontal_Tabs);
@@ -336,6 +338,9 @@ package body Stylesw is
when 'd' =>
Style_Check_DOS_Line_Terminator := True;
+ when 'D' =>
+ Style_Check_Mixed_Case_Decls := True;
+
when 'e' =>
Style_Check_End_Labels := True;
@@ -503,6 +508,9 @@ package body Stylesw is
when 'd' =>
Style_Check_DOS_Line_Terminator := False;
+ when 'D' =>
+ Style_Check_Mixed_Case_Decls := False;
+
when 'e' =>
Style_Check_End_Labels := False;
diff --git a/gcc/ada/stylesw.ads b/gcc/ada/stylesw.ads
index d82fcb1..de1f92d 100644
--- a/gcc/ada/stylesw.ads
+++ b/gcc/ada/stylesw.ads
@@ -113,6 +113,10 @@ package Stylesw is
-- the line terminator must be a single LF, without an associated CR (e.g.
-- DOS line terminator sequence CR/LF not allowed).
+ Style_Check_Mixed_Case_Decls : Boolean := False;
+ -- This can be set True by using the -gnatyD switch. If it is True, then
+ -- declared identifiers must be in Mixed_Case.
+
Style_Check_End_Labels : Boolean := False;
-- This can be set True by using the -gnatye switch. If it is True, then
-- optional END labels must always be present.
diff --git a/gcc/ada/switch-b.adb b/gcc/ada/switch-b.adb
index 2f8831b..dc62ec2 100644
--- a/gcc/ada/switch-b.adb
+++ b/gcc/ada/switch-b.adb
@@ -51,6 +51,9 @@ package body Switch.B is
-- Used for -d and -D to scan stack size including handling k/m. S is
-- set to 'd' or 'D' to indicate the switch being scanned.
+ procedure Scan_Debug_Switches;
+ -- Scan out debug switches
+
---------------------------
-- Get_Optional_Filename --
---------------------------
@@ -114,6 +117,70 @@ package body Switch.B is
return Result;
end Get_Stack_Size;
+ -------------------------
+ -- Scan_Debug_Switches --
+ -------------------------
+
+ procedure Scan_Debug_Switches is
+ Dot : Boolean := False;
+ Underscore : Boolean := False;
+
+ begin
+ while Ptr <= Max loop
+ C := Switch_Chars (Ptr);
+
+ -- Binder debug flags come in the following forms:
+ --
+ -- letter
+ -- . letter
+ -- _ letter
+ --
+ -- digit
+ -- . digit
+ -- _ digit
+ --
+ -- Note that the processing of switch -d aleady takes care of the
+ -- case where the first flag is a digit (default stack size).
+
+ if C in '1' .. '9' or else
+ C in 'a' .. 'z' or else
+ C in 'A' .. 'Z'
+ then
+ -- . letter
+ -- . digit
+
+ if Dot then
+ Set_Dotted_Debug_Flag (C);
+ Dot := False;
+
+ -- _ letter
+ -- _ digit
+
+ elsif Underscore then
+ Set_Underscored_Debug_Flag (C);
+ Underscore := False;
+
+ -- letter
+ -- digit
+
+ else
+ Set_Debug_Flag (C);
+ end if;
+
+ elsif C = '.' then
+ Dot := True;
+
+ elsif C = '_' then
+ Underscore := True;
+
+ else
+ Bad_Switch (Switch_Chars);
+ end if;
+
+ Ptr := Ptr + 1;
+ end loop;
+ end Scan_Debug_Switches;
+
-- Start of processing for Scan_Binder_Switches
begin
@@ -170,7 +237,6 @@ package body Switch.B is
-- Processing for d switch
when 'd' =>
-
if Ptr = Max then
Bad_Switch (Switch_Chars);
end if;
@@ -189,26 +255,7 @@ package body Switch.B is
-- Case where character after -d is not digit (debug flags)
else
- -- Note: for the debug switch, the remaining characters in this
- -- switch field must all be debug flags, since all valid switch
- -- characters are also valid debug characters. This switch is
- -- not documented on purpose because it is only used by the
- -- implementors.
-
- -- Loop to scan out debug flags
-
- loop
- C := Switch_Chars (Ptr);
-
- if C in 'a' .. 'z' or else C in 'A' .. 'Z' then
- Set_Debug_Flag (C);
- else
- Bad_Switch (Switch_Chars);
- end if;
-
- Ptr := Ptr + 1;
- exit when Ptr > Max;
- end loop;
+ Scan_Debug_Switches;
end if;
-- Processing for D switch
@@ -294,6 +341,12 @@ package body Switch.B is
Debugger_Level := 2;
end if;
+ -- Processing for G switch
+
+ when 'G' =>
+ Ptr := Ptr + 1;
+ Generate_C_Code := True;
+
-- Processing for h switch
when 'h' =>
diff --git a/gcc/ada/sysdep.c b/gcc/ada/sysdep.c
index 21a29bf..0fbc606 100644
--- a/gcc/ada/sysdep.c
+++ b/gcc/ada/sysdep.c
@@ -1066,4 +1066,3 @@ __gnat_name_case_equivalence ()
return 1;
#endif
}
-
diff --git a/gcc/ada/uintp.adb b/gcc/ada/uintp.adb
index a1d0a2e..61e9f3d 100644
--- a/gcc/ada/uintp.adb
+++ b/gcc/ada/uintp.adb
@@ -1492,6 +1492,49 @@ package body Uintp is
end;
end UI_From_Int;
+ ----------------------
+ -- UI_From_Integral --
+ ----------------------
+
+ function UI_From_Integral (Input : In_T) return Uint is
+ begin
+ -- If in range of our normal conversion function, use it so we can use
+ -- direct access and our cache.
+
+ if In_T'Size <= Int'Size
+ or else Input in In_T (Int'First) .. In_T (Int'Last)
+ then
+ return UI_From_Int (Int (Input));
+
+ else
+ -- For values of larger magnitude, compute digits into a vector and
+ -- call Vector_To_Uint.
+
+ declare
+ Max_For_In_T : constant Int := 3 * In_T'Size / Int'Size;
+ Our_Base : constant In_T := In_T (Base);
+ Temp_Integer : In_T := Input;
+ -- Base is defined so that 3 Uint digits is sufficient to hold the
+ -- largest possible Int value.
+
+ U : Uint;
+ V : UI_Vector (1 .. Max_For_In_T);
+
+ begin
+ for J in reverse V'Range loop
+ V (J) := Int (abs (Temp_Integer rem Our_Base));
+ Temp_Integer := Temp_Integer / Our_Base;
+ end loop;
+
+ U := Vector_To_Uint (V, Input < 0);
+ Uints_Min := Uints.Last;
+ Udigits_Min := Udigits.Last;
+
+ return U;
+ end;
+ end if;
+ end UI_From_Integral;
+
------------
-- UI_GCD --
------------
@@ -2324,50 +2367,4 @@ package body Uintp is
return Uint_0;
end Vector_To_Uint;
- ----------------------
- -- UI_From_Integral --
- ----------------------
-
- function UI_From_Integral (Input : In_T) return Uint is
- U : Uint;
-
- begin
- -- If in range of our normal conversion function, use it so we can
- -- use direct access and our cache.
-
- if In_T'Size <= Int'Size
- or else Input in In_T (Int'First) .. In_T (Int'Last)
- then
- return UI_From_Int (Int (Input));
-
- else
- -- pragma Warnings (Off);
-
- -- For values of larger magnitude, compute digits into a vector
- -- and call Vector_To_Uint.
-
- declare
- Max_For_In_T : constant Int := 3 * In_T'Size / Int'Size;
- Our_Base : constant In_T := In_T (Base);
- Temp_Integer : In_T := Input;
- -- Base is defined so that 3 Uint digits is sufficient to hold the
- -- largest possible Int value.
-
- V : UI_Vector (1 .. Max_For_In_T);
-
- begin
- for J in reverse V'Range loop
- V (J) := Int (abs (Temp_Integer rem Our_Base));
- Temp_Integer := Temp_Integer / Our_Base;
- end loop;
-
- U := Vector_To_Uint (V, Input < 0);
- Uints_Min := Uints.Last;
- Udigits_Min := Udigits.Last;
- return U;
- end;
-
- -- pragma Warnings (On);
- end if;
- end UI_From_Integral;
end Uintp;
diff --git a/gcc/ada/uintp.ads b/gcc/ada/uintp.ads
index a09f326..d8342ba 100644
--- a/gcc/ada/uintp.ads
+++ b/gcc/ada/uintp.ads
@@ -251,9 +251,9 @@ package Uintp is
generic
type In_T is range <>;
function UI_From_Integral (Input : In_T) return Uint;
- -- Likewise, but converts from any integer type.
- -- Must not be applied to biased types (instantiation will provide
- -- a warning if actual is a biased type).
+ -- Likewise, but converts from any integer type. Must not be applied to
+ -- biased types (instantiation will provide a warning if actual is a biased
+ -- type).
function UI_From_CC (Input : Char_Code) return Uint;
-- Converts Char_Code value to universal integer form
diff --git a/gcc/alias.c b/gcc/alias.c
index b64e3ea..eece84a 100644
--- a/gcc/alias.c
+++ b/gcc/alias.c
@@ -39,6 +39,7 @@ along with GCC; see the file COPYING3. If not see
#include "cfganal.h"
#include "rtl-iter.h"
#include "cgraph.h"
+#include "ipa-utils.h"
/* The aliasing API provided here solves related but different problems:
@@ -307,18 +308,6 @@ ao_ref_from_mem (ao_ref *ref, const_rtx mem)
&& TREE_CODE (TMR_BASE (base)) == SSA_NAME)))
return false;
- /* If this is a reference based on a partitioned decl replace the
- base with a MEM_REF of the pointer representative we
- created during stack slot partitioning. */
- if (VAR_P (base)
- && ! is_global_var (base)
- && cfun->gimple_df->decls_to_pointers != NULL)
- {
- tree *namep = cfun->gimple_df->decls_to_pointers->get (base);
- if (namep)
- ref->base = build_simple_mem_ref (*namep);
- }
-
ref->ref_alias_set = MEM_ALIAS_SET (mem);
/* If MEM_OFFSET or MEM_SIZE are unknown what we got from MEM_EXPR
@@ -1020,6 +1009,14 @@ get_alias_set (tree t)
}
p = TYPE_MAIN_VARIANT (p);
+ /* In LTO for C++ programs we can turn in complete types to complete
+ using ODR name lookup. */
+ if (in_lto_p && TYPE_STRUCTURAL_EQUALITY_P (p) && odr_type_p (p))
+ {
+ p = prevailing_odr_type (p);
+ gcc_checking_assert (TYPE_MAIN_VARIANT (p) == p);
+ }
+
/* Make void * compatible with char * and also void **.
Programs are commonly violating TBAA by this.
diff --git a/gcc/asan.c b/gcc/asan.c
index 3b800b2..605d04f 100644
--- a/gcc/asan.c
+++ b/gcc/asan.c
@@ -1713,8 +1713,8 @@ asan_emit_allocas_unpoison (rtx top, rtx bot, rtx_insn *before)
rtx ret = init_one_libfunc ("__asan_allocas_unpoison");
top = convert_memory_address (ptr_mode, top);
bot = convert_memory_address (ptr_mode, bot);
- ret = emit_library_call_value (ret, NULL_RTX, LCT_NORMAL, ptr_mode,
- top, ptr_mode, bot, ptr_mode);
+ emit_library_call (ret, LCT_NORMAL, ptr_mode,
+ top, ptr_mode, bot, ptr_mode);
do_pending_stack_adjust ();
rtx_insn *insns = get_insns ();
diff --git a/gcc/attribs.c b/gcc/attribs.c
index 4441922..8e54016 100644
--- a/gcc/attribs.c
+++ b/gcc/attribs.c
@@ -340,7 +340,7 @@ lookup_attribute_spec (const_tree name)
Please read the comments of cxx11_attribute_p to understand the
format of attributes. */
-static tree
+tree
get_attribute_namespace (const_tree attr)
{
if (cxx11_attribute_p (attr))
@@ -469,7 +469,6 @@ tree
decl_attributes (tree *node, tree attributes, int flags,
tree last_decl /* = NULL_TREE */)
{
- tree a;
tree returned_attrs = NULL_TREE;
if (TREE_TYPE (*node) == error_mark_node || attributes == error_mark_node)
@@ -548,22 +547,23 @@ decl_attributes (tree *node, tree attributes, int flags,
/* Note that attributes on the same declaration are not necessarily
in the same order as in the source. */
- for (a = attributes; a; a = TREE_CHAIN (a))
+ for (tree attr = attributes; attr; attr = TREE_CHAIN (attr))
{
- tree ns = get_attribute_namespace (a);
- tree name = get_attribute_name (a);
- tree args = TREE_VALUE (a);
+ tree ns = get_attribute_namespace (attr);
+ tree name = get_attribute_name (attr);
+ tree args = TREE_VALUE (attr);
tree *anode = node;
const struct attribute_spec *spec
= lookup_scoped_attribute_spec (ns, name);
int fn_ptr_quals = 0;
tree fn_ptr_tmp = NULL_TREE;
+ const bool cxx11_attr_p = cxx11_attribute_p (attr);
if (spec == NULL)
{
if (!(flags & (int) ATTR_FLAG_BUILT_IN))
{
- if (ns == NULL_TREE || !cxx11_attribute_p (a))
+ if (ns == NULL_TREE || !cxx11_attr_p)
warning (OPT_Wattributes, "%qE attribute directive ignored",
name);
else
@@ -584,7 +584,7 @@ decl_attributes (tree *node, tree attributes, int flags,
gcc_assert (is_attribute_p (spec->name, name));
if (TYPE_P (*node)
- && cxx11_attribute_p (a)
+ && cxx11_attr_p
&& !(flags & ATTR_FLAG_TYPE_IN_PLACE))
{
/* This is a c++11 attribute that appertains to a
@@ -707,8 +707,7 @@ decl_attributes (tree *node, tree attributes, int flags,
if (spec->handler != NULL)
{
- int cxx11_flag =
- cxx11_attribute_p (a) ? ATTR_FLAG_CXX11 : 0;
+ int cxx11_flag = (cxx11_attr_p ? ATTR_FLAG_CXX11 : 0);
/* Pass in an array of the current declaration followed
by the last pushed/merged declaration if one exists.
@@ -756,17 +755,23 @@ decl_attributes (tree *node, tree attributes, int flags,
if (a == NULL_TREE)
{
/* This attribute isn't already in the list. */
+ tree r;
+ /* Preserve the C++11 form. */
+ if (cxx11_attr_p)
+ r = tree_cons (build_tree_list (ns, name), args, old_attrs);
+ else
+ r = tree_cons (name, args, old_attrs);
+
if (DECL_P (*anode))
- DECL_ATTRIBUTES (*anode) = tree_cons (name, args, old_attrs);
+ DECL_ATTRIBUTES (*anode) = r;
else if (flags & (int) ATTR_FLAG_TYPE_IN_PLACE)
{
- TYPE_ATTRIBUTES (*anode) = tree_cons (name, args, old_attrs);
+ TYPE_ATTRIBUTES (*anode) = r;
/* If this is the main variant, also push the attributes
out to the other variants. */
if (*anode == TYPE_MAIN_VARIANT (*anode))
{
- tree variant;
- for (variant = *anode; variant;
+ for (tree variant = *anode; variant;
variant = TYPE_NEXT_VARIANT (variant))
{
if (TYPE_ATTRIBUTES (variant) == old_attrs)
@@ -780,9 +785,7 @@ decl_attributes (tree *node, tree attributes, int flags,
}
}
else
- *anode = build_type_attribute_variant (*anode,
- tree_cons (name, args,
- old_attrs));
+ *anode = build_type_attribute_variant (*anode, r);
}
}
diff --git a/gcc/attribs.h b/gcc/attribs.h
index 83ecbbb..23a7321 100644
--- a/gcc/attribs.h
+++ b/gcc/attribs.h
@@ -35,6 +35,7 @@ extern tree decl_attributes (tree *, tree, int, tree = NULL_TREE);
extern bool cxx11_attribute_p (const_tree);
extern tree get_attribute_name (const_tree);
+extern tree get_attribute_namespace (const_tree);
extern void apply_tm_attr (tree, tree);
extern tree make_attribute (const char *, const char *, tree);
diff --git a/gcc/bb-reorder.c b/gcc/bb-reorder.c
index e4ae8b8..0ac3914 100644
--- a/gcc/bb-reorder.c
+++ b/gcc/bb-reorder.c
@@ -1032,7 +1032,7 @@ connect_better_edge_p (const_edge e, bool src_index_p, int best_len,
else if (e->count () < cur_best_edge->count ())
/* The edge has lower probability than the temporary best edge. */
is_better_edge = false;
- if (e->probability > cur_best_edge->probability)
+ else if (e->probability > cur_best_edge->probability)
/* The edge has higher probability than the temporary best edge. */
is_better_edge = true;
else if (e->probability < cur_best_edge->probability)
@@ -1357,8 +1357,8 @@ connect_traces (int n_traces, struct trace *traces)
static bool
copy_bb_p (const_basic_block bb, int code_may_grow)
{
- int size = 0;
- int max_size = uncond_jump_length;
+ unsigned int size = 0;
+ unsigned int max_size = uncond_jump_length;
rtx_insn *insn;
if (EDGE_COUNT (bb->preds) < 2)
@@ -1376,7 +1376,11 @@ copy_bb_p (const_basic_block bb, int code_may_grow)
FOR_BB_INSNS (bb, insn)
{
if (INSN_P (insn))
- size += get_attr_min_length (insn);
+ {
+ size += get_attr_min_length (insn);
+ if (size > max_size)
+ break;
+ }
}
if (size <= max_size)
@@ -1385,7 +1389,7 @@ copy_bb_p (const_basic_block bb, int code_may_grow)
if (dump_file)
{
fprintf (dump_file,
- "Block %d can't be copied because its size = %d.\n",
+ "Block %d can't be copied because its size = %u.\n",
bb->index, size);
}
@@ -1397,7 +1401,7 @@ copy_bb_p (const_basic_block bb, int code_may_grow)
int
get_uncond_jump_length (void)
{
- int length;
+ unsigned int length;
start_sequence ();
rtx_code_label *label = emit_label (gen_label_rtx ());
@@ -1405,6 +1409,7 @@ get_uncond_jump_length (void)
length = get_attr_min_length (jump);
end_sequence ();
+ gcc_assert (length < INT_MAX);
return length;
}
diff --git a/gcc/brig/ChangeLog b/gcc/brig/ChangeLog
index a1cc326..1fdc0f1 100644
--- a/gcc/brig/ChangeLog
+++ b/gcc/brig/ChangeLog
@@ -1,3 +1,12 @@
+2019-05-16 Martin Sebor <msebor@redhat.com>
+
+ * brigfrontend/brig-control-handler.cc
+ (brig_directive_control_handler::operator): Remove trailing newline
+ from a diagnostic.
+ * brigfrontend/brig-module-handler.cc
+ (brig_directive_module_handler::operator): Remove a duplicated space
+ from a diagnostic.
+
2019-01-01 Jakub Jelinek <jakub@redhat.com>
Update copyright years.
diff --git a/gcc/brig/brig-lang.c b/gcc/brig/brig-lang.c
index 91c7cfa..1c3a3b0 100644
--- a/gcc/brig/brig-lang.c
+++ b/gcc/brig/brig-lang.c
@@ -864,10 +864,12 @@ brig_build_c_type_nodes (void)
for (i = 0; i < NUM_INT_N_ENTS; i++)
if (int_n_enabled_p[i])
{
- char name[50];
+ char name[50], altname[50];
sprintf (name, "__int%d unsigned", int_n_data[i].bitsize);
+ sprintf (altname, "__int%d__ unsigned", int_n_data[i].bitsize);
- if (strcmp (name, SIZE_TYPE) == 0)
+ if (strcmp (name, SIZE_TYPE) == 0
+ || strcmp (altname, SIZE_TYPE) == 0)
{
intmax_type_node = int_n_trees[i].signed_type;
uintmax_type_node = int_n_trees[i].unsigned_type;
diff --git a/gcc/brig/brigfrontend/brig-control-handler.cc b/gcc/brig/brigfrontend/brig-control-handler.cc
index 3803931..4374c46 100644
--- a/gcc/brig/brigfrontend/brig-control-handler.cc
+++ b/gcc/brig/brigfrontend/brig-control-handler.cc
@@ -102,7 +102,7 @@ brig_directive_control_handler::operator () (const BrigBase *base)
/* Unimplemented. */
break;
default:
- sorry ("Unsupported control directive %x.\n", inst->control);
+ sorry ("Unsupported control directive %x.", inst->control);
}
return base->byteCount;
}
diff --git a/gcc/brig/brigfrontend/brig-module-handler.cc b/gcc/brig/brigfrontend/brig-module-handler.cc
index 58a65d65..e1551b9 100644
--- a/gcc/brig/brigfrontend/brig-module-handler.cc
+++ b/gcc/brig/brigfrontend/brig-module-handler.cc
@@ -28,10 +28,10 @@ brig_directive_module_handler::operator () (const BrigBase *base)
const BrigDirectiveModule* mod = (const BrigDirectiveModule*)base;
m_parent.m_module_name = m_parent.get_string (mod->name).substr (1);
if (mod->hsailMajor != 1 || mod->hsailMinor != 0)
- fatal_error (UNKNOWN_LOCATION, PHSA_ERROR_PREFIX_INCOMPATIBLE_MODULE " "
+ fatal_error (UNKNOWN_LOCATION, PHSA_ERROR_PREFIX_INCOMPATIBLE_MODULE
"HSAIL version not supported. HSAIL 1.0 required.");
if (mod->machineModel != BRIG_MACHINE_LARGE)
- fatal_error (UNKNOWN_LOCATION, PHSA_ERROR_PREFIX_INCOMPATIBLE_MODULE " "
+ fatal_error (UNKNOWN_LOCATION, PHSA_ERROR_PREFIX_INCOMPATIBLE_MODULE
"Only HSA 'large' machine model supported.");
/* Do not check for the profile as the runtime conformance suite tests
with 'full' profile BRIGs even though they don't use any full profile
diff --git a/gcc/bt-load.c b/gcc/bt-load.c
index a7d9d53..f68879ca 100644
--- a/gcc/bt-load.c
+++ b/gcc/bt-load.c
@@ -1169,7 +1169,6 @@ move_btr_def (basic_block new_def_bb, int btr, btr_def *def, bitmap live_range,
if (def->other_btr_uses_before_def)
{
- insp = BB_END (b);
for (insp = BB_END (b); ! INSN_P (insp); insp = PREV_INSN (insp))
gcc_assert (insp != BB_HEAD (b));
diff --git a/gcc/builtin-attrs.def b/gcc/builtin-attrs.def
index 204141f..39d1395 100644
--- a/gcc/builtin-attrs.def
+++ b/gcc/builtin-attrs.def
@@ -118,6 +118,7 @@ DEF_ATTR_IDENT (ATTR_TM_REGPARM, "*tm regparm")
DEF_ATTR_IDENT (ATTR_TM_TMPURE, "transaction_pure")
DEF_ATTR_IDENT (ATTR_RETURNS_TWICE, "returns_twice")
DEF_ATTR_IDENT (ATTR_RETURNS_NONNULL, "returns_nonnull")
+DEF_ATTR_IDENT (ATTR_WARN_UNUSED_RESULT, "warn_unused_result")
DEF_ATTR_TREE_LIST (ATTR_NOVOPS_LIST, ATTR_NOVOPS, ATTR_NULL, ATTR_NULL)
@@ -157,8 +158,10 @@ DEF_ATTR_TREE_LIST (ATTR_CONST_NORETURN_NOTHROW_LEAF_COLD_LIST, ATTR_COLD,\
ATTR_NULL, ATTR_CONST_NORETURN_NOTHROW_LEAF_LIST)
DEF_ATTR_TREE_LIST (ATTR_MALLOC_NOTHROW_LIST, ATTR_MALLOC, \
ATTR_NULL, ATTR_NOTHROW_LIST)
-DEF_ATTR_TREE_LIST (ATTR_MALLOC_NOTHROW_LEAF_LIST, ATTR_MALLOC, \
+DEF_ATTR_TREE_LIST (ATTR_WARN_UNUSED_RESULT_NOTHROW_LEAF_LIST, ATTR_WARN_UNUSED_RESULT, \
ATTR_NULL, ATTR_NOTHROW_LEAF_LIST)
+DEF_ATTR_TREE_LIST (ATTR_MALLOC_WARN_UNUSED_RESULT_NOTHROW_LEAF_LIST, ATTR_MALLOC, \
+ ATTR_NULL, ATTR_WARN_UNUSED_RESULT_NOTHROW_LEAF_LIST)
DEF_ATTR_TREE_LIST (ATTR_SENTINEL_NOTHROW_LIST, ATTR_SENTINEL, \
ATTR_NULL, ATTR_NOTHROW_LIST)
DEF_ATTR_TREE_LIST (ATTR_SENTINEL_NOTHROW_LEAF_LIST, ATTR_SENTINEL, \
@@ -170,24 +173,26 @@ DEF_ATTR_TREE_LIST (ATTR_COLD_CONST_NORETURN_NOTHROW_LEAF_LIST, ATTR_CONST,\
with _SIZE_1, or second argument with _SIZE_2, specifies the size
of the allocated object. */
DEF_ATTR_TREE_LIST (ATTR_MALLOC_SIZE_1_NOTHROW_LIST, ATTR_ALLOC_SIZE, \
- ATTR_LIST_1, ATTR_MALLOC_NOTHROW_LIST)
-DEF_ATTR_TREE_LIST (ATTR_ALLOC_SIZE_2_NOTHROW_LIST, ATTR_ALLOC_SIZE, \
- ATTR_LIST_2, ATTR_MALLOC_NOTHROW_LIST)
-DEF_ATTR_TREE_LIST (ATTR_MALLOC_SIZE_1_NOTHROW_LEAF_LIST, ATTR_ALLOC_SIZE, \
- ATTR_LIST_1, ATTR_MALLOC_NOTHROW_LEAF_LIST)
+ ATTR_LIST_1, ATTR_MALLOC_NOTHROW_LIST)
+DEF_ATTR_TREE_LIST (ATTR_MALLOC_WARN_UNUSED_RESULT_NOTHROW_LIST, ATTR_WARN_UNUSED_RESULT, \
+ ATTR_NULL, ATTR_MALLOC_NOTHROW_LIST)
+DEF_ATTR_TREE_LIST (ATTR_ALLOC_WARN_UNUSED_RESULT_SIZE_2_NOTHROW_LIST, ATTR_ALLOC_SIZE, \
+ ATTR_LIST_2, ATTR_MALLOC_WARN_UNUSED_RESULT_NOTHROW_LIST)
+DEF_ATTR_TREE_LIST (ATTR_MALLOC_WARN_UNUSED_RESULT_SIZE_1_NOTHROW_LEAF_LIST, ATTR_ALLOC_SIZE, \
+ ATTR_LIST_1, ATTR_MALLOC_WARN_UNUSED_RESULT_NOTHROW_LEAF_LIST)
/* Alloca is just like malloc except that it never returns null. */
-DEF_ATTR_TREE_LIST (ATTR_ALLOCA_SIZE_1_NOTHROW_LEAF_LIST, ATTR_RETURNS_NONNULL,
- ATTR_NULL, ATTR_MALLOC_SIZE_1_NOTHROW_LEAF_LIST)
+DEF_ATTR_TREE_LIST (ATTR_ALLOCA_WARN_UNUSED_RESULT_SIZE_1_NOTHROW_LEAF_LIST, ATTR_RETURNS_NONNULL,
+ ATTR_NULL, ATTR_MALLOC_WARN_UNUSED_RESULT_SIZE_1_NOTHROW_LEAF_LIST)
/* Allocation functions like calloc the product of whose first two arguments
specifies the size of the allocated object. */
-DEF_ATTR_TREE_LIST (ATTR_MALLOC_SIZE_1_2_NOTHROW_LEAF_LIST, ATTR_ALLOC_SIZE, \
- ATTR_LIST_1_2, ATTR_MALLOC_NOTHROW_LEAF_LIST)
+DEF_ATTR_TREE_LIST (ATTR_MALLOC_WARN_UNUSED_RESULT_SIZE_1_2_NOTHROW_LEAF_LIST, ATTR_ALLOC_SIZE, \
+ ATTR_LIST_1_2, ATTR_MALLOC_WARN_UNUSED_RESULT_NOTHROW_LEAF_LIST)
/* Allocation functions like realloc whose second argument specifies
the size of the allocated object. */
-DEF_ATTR_TREE_LIST (ATTR_ALLOC_SIZE_2_NOTHROW_LEAF_LIST, ATTR_ALLOC_SIZE, \
- ATTR_LIST_2, ATTR_NOTHROW_LEAF_LIST)
+DEF_ATTR_TREE_LIST (ATTR_ALLOC_WARN_UNUSED_RESULT_SIZE_2_NOTHROW_LEAF_LIST, ATTR_ALLOC_SIZE, \
+ ATTR_LIST_2, ATTR_WARN_UNUSED_RESULT_NOTHROW_LEAF_LIST)
/* Functions whose pointer parameter(s) are all nonnull. */
DEF_ATTR_TREE_LIST (ATTR_NONNULL_LIST, ATTR_NONNULL, ATTR_NULL, ATTR_NULL)
@@ -290,11 +295,15 @@ DEF_ATTR_TREE_LIST (ATTR_PURE_NOTHROW_NONNULL, ATTR_PURE, ATTR_NULL, \
DEF_ATTR_TREE_LIST (ATTR_PURE_NOTHROW_NONNULL_LEAF, ATTR_PURE, ATTR_NULL, \
ATTR_NOTHROW_NONNULL_LEAF)
/* Nothrow malloc functions whose pointer parameter(s) are all nonnull. */
-DEF_ATTR_TREE_LIST (ATTR_MALLOC_NOTHROW_NONNULL, ATTR_MALLOC, ATTR_NULL, \
+DEF_ATTR_TREE_LIST (ATTR_WARN_UNUSED_RESULT_NOTHROW_NONNULL, ATTR_WARN_UNUSED_RESULT, ATTR_NULL, \
ATTR_NOTHROW_NONNULL)
+DEF_ATTR_TREE_LIST (ATTR_MALLOC_WARN_UNUSED_RESULT_NOTHROW_NONNULL, ATTR_MALLOC, ATTR_NULL, \
+ ATTR_WARN_UNUSED_RESULT_NOTHROW_NONNULL)
/* Nothrow malloc leaf functions whose pointer parameter(s) are all nonnull. */
-DEF_ATTR_TREE_LIST (ATTR_MALLOC_NOTHROW_NONNULL_LEAF, ATTR_MALLOC, ATTR_NULL, \
+DEF_ATTR_TREE_LIST (ATTR_WARN_UNUSED_RESULT_NOTHROW_NONNULL_LEAF, ATTR_WARN_UNUSED_RESULT, ATTR_NULL, \
ATTR_NOTHROW_NONNULL_LEAF)
+DEF_ATTR_TREE_LIST (ATTR_MALLOC_WARN_UNUSED_RESULT_NOTHROW_NONNULL_LEAF, ATTR_MALLOC, ATTR_NULL, \
+ ATTR_WARN_UNUSED_RESULT_NOTHROW_NONNULL_LEAF)
/* Construct a tree for the format attribute (and implicitly nonnull). */
#define DEF_FORMAT_ATTRIBUTE(TYPE, FA, VALUES) \
diff --git a/gcc/builtins.c b/gcc/builtins.c
index d37d73f..e2ba356 100644
--- a/gcc/builtins.c
+++ b/gcc/builtins.c
@@ -981,7 +981,7 @@ expand_builtin_setjmp_setup (rtx buf_addr, rtx receiver_label)
mem = gen_rtx_MEM (Pmode, buf_addr);
set_mem_alias_set (mem, setjmp_alias_set);
- emit_move_insn (mem, targetm.builtin_setjmp_frame_value ());
+ emit_move_insn (mem, hard_frame_pointer_rtx);
mem = gen_rtx_MEM (Pmode, plus_constant (Pmode, buf_addr,
GET_MODE_SIZE (Pmode))),
@@ -1023,31 +1023,6 @@ expand_builtin_setjmp_receiver (rtx receiver_label)
if (chain && REG_P (chain))
emit_clobber (chain);
- /* Now put in the code to restore the frame pointer, and argument
- pointer, if needed. */
- if (! targetm.have_nonlocal_goto ())
- {
- /* First adjust our frame pointer to its actual value. It was
- previously set to the start of the virtual area corresponding to
- the stacked variables when we branched here and now needs to be
- adjusted to the actual hardware fp value.
-
- Assignments to virtual registers are converted by
- instantiate_virtual_regs into the corresponding assignment
- to the underlying register (fp in this case) that makes
- the original assignment true.
- So the following insn will actually be decrementing fp by
- TARGET_STARTING_FRAME_OFFSET. */
- emit_move_insn (virtual_stack_vars_rtx, hard_frame_pointer_rtx);
-
- /* Restoring the frame pointer also modifies the hard frame pointer.
- Mark it used (so that the previous assignment remains live once
- the frame pointer is eliminated) and clobbered (to represent the
- implicit update from the assignment). */
- emit_use (hard_frame_pointer_rtx);
- emit_clobber (hard_frame_pointer_rtx);
- }
-
if (!HARD_FRAME_POINTER_IS_ARG_POINTER && fixed_regs[ARG_POINTER_REGNUM])
{
/* If the argument pointer can be eliminated in favor of the
@@ -1137,15 +1112,20 @@ expand_builtin_longjmp (rtx buf_addr, rtx value)
emit_insn (targetm.gen_nonlocal_goto (value, lab, stack, fp));
else
{
- lab = copy_to_reg (lab);
-
emit_clobber (gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (VOIDmode)));
emit_clobber (gen_rtx_MEM (BLKmode, hard_frame_pointer_rtx));
+ lab = copy_to_reg (lab);
+
/* Restore the frame pointer and stack pointer. We must use a
temporary since the setjmp buffer may be a local. */
fp = copy_to_reg (fp);
emit_stack_restore (SAVE_NONLOCAL, stack);
+
+ /* Ensure the frame pointer move is not optimized. */
+ emit_insn (gen_blockage ());
+ emit_clobber (hard_frame_pointer_rtx);
+ emit_clobber (frame_pointer_rtx);
emit_move_insn (hard_frame_pointer_rtx, fp);
emit_use (hard_frame_pointer_rtx);
@@ -1284,15 +1264,20 @@ expand_builtin_nonlocal_goto (tree exp)
emit_insn (targetm.gen_nonlocal_goto (const0_rtx, r_label, r_sp, r_fp));
else
{
- r_label = copy_to_reg (r_label);
-
emit_clobber (gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (VOIDmode)));
emit_clobber (gen_rtx_MEM (BLKmode, hard_frame_pointer_rtx));
+ r_label = copy_to_reg (r_label);
+
/* Restore the frame pointer and stack pointer. We must use a
temporary since the setjmp buffer may be a local. */
r_fp = copy_to_reg (r_fp);
emit_stack_restore (SAVE_NONLOCAL, r_sp);
+
+ /* Ensure the frame pointer move is not optimized. */
+ emit_insn (gen_blockage ());
+ emit_clobber (hard_frame_pointer_rtx);
+ emit_clobber (frame_pointer_rtx);
emit_move_insn (hard_frame_pointer_rtx, r_fp);
/* USE of hard_frame_pointer_rtx added for consistency;
@@ -1431,7 +1416,7 @@ expand_builtin_prefetch (tree exp)
}
/* Get a MEM rtx for expression EXP which is the address of an operand
- to be used in a string instruction (cmpstrsi, movmemsi, ..). LEN is
+ to be used in a string instruction (cmpstrsi, cpymemsi, ..). LEN is
the maximum length of the block of memory that might be accessed or
NULL if unknown. */
@@ -1653,11 +1638,8 @@ expand_builtin_apply_args_1 (void)
/* Save the structure value address unless this is passed as an
"invisible" first argument. */
if (struct_incoming_value)
- {
- emit_move_insn (adjust_address (registers, Pmode, size),
- copy_to_reg (struct_incoming_value));
- size += GET_MODE_SIZE (Pmode);
- }
+ emit_move_insn (adjust_address (registers, Pmode, size),
+ copy_to_reg (struct_incoming_value));
/* Return the address of the block. */
return copy_addr_to_reg (XEXP (registers, 0));
@@ -1806,7 +1788,6 @@ expand_builtin_apply (rtx function, rtx arguments, rtx argsize)
emit_move_insn (struct_value, value);
if (REG_P (struct_value))
use_reg (&call_fusage, struct_value);
- size += GET_MODE_SIZE (Pmode);
}
/* All arguments and registers used for the call are set up by now! */
@@ -3839,6 +3820,8 @@ expand_builtin_memory_copy_args (tree dest, tree src, tree len,
unsigned HOST_WIDE_INT max_size;
unsigned HOST_WIDE_INT probable_max_size;
+ bool is_move_done;
+
/* If DEST is not a pointer type, call the normal function. */
if (dest_align == 0)
return NULL_RTX;
@@ -3888,11 +3871,22 @@ expand_builtin_memory_copy_args (tree dest, tree src, tree len,
if (CALL_EXPR_TAILCALL (exp)
&& (retmode == RETURN_BEGIN || target == const0_rtx))
method = BLOCK_OP_TAILCALL;
- if (retmode == RETURN_END && target != const0_rtx)
+ bool use_mempcpy_call = (targetm.libc_has_fast_function (BUILT_IN_MEMPCPY)
+ && retmode == RETURN_END
+ && target != const0_rtx);
+ if (use_mempcpy_call)
method = BLOCK_OP_NO_LIBCALL_RET;
dest_addr = emit_block_move_hints (dest_mem, src_mem, len_rtx, method,
expected_align, expected_size,
- min_size, max_size, probable_max_size);
+ min_size, max_size, probable_max_size,
+ use_mempcpy_call, &is_move_done);
+
+ /* Bail out when a mempcpy call would be expanded as libcall and when
+ we have a target that provides a fast implementation
+ of mempcpy routine. */
+ if (!is_move_done)
+ return NULL_RTX;
+
if (dest_addr == pc_rtx)
return NULL_RTX;
@@ -6784,7 +6778,7 @@ expand_builtin_atomic_always_lock_free (tree exp)
if (TREE_CODE (arg0) != INTEGER_CST)
{
- error ("non-constant argument 1 to __atomic_always_lock_free");
+ error ("non-constant argument 1 to %qs", "__atomic_always_lock_free");
return const0_rtx;
}
@@ -6826,7 +6820,7 @@ expand_builtin_atomic_is_lock_free (tree exp)
if (!INTEGRAL_TYPE_P (TREE_TYPE (arg0)))
{
- error ("non-integer argument 1 to __atomic_is_lock_free");
+ error ("non-integer argument 1 to %qs", "__atomic_is_lock_free");
return NULL_RTX;
}
@@ -7124,8 +7118,19 @@ inline_expand_builtin_string_cmp (tree exp, rtx target)
return NULL_RTX;
/* For strncmp, if the length is not a const, not qualify. */
- if (is_ncmp && !tree_fits_uhwi_p (len3_tree))
- return NULL_RTX;
+ if (is_ncmp)
+ {
+ if (!tree_fits_uhwi_p (len3_tree))
+ return NULL_RTX;
+ else
+ len3 = tree_to_uhwi (len3_tree);
+ }
+
+ if (src_str1 != NULL)
+ len1 = strnlen (src_str1, len1) + 1;
+
+ if (src_str2 != NULL)
+ len2 = strnlen (src_str2, len2) + 1;
int const_str_n = 0;
if (!len1)
@@ -7140,7 +7145,7 @@ inline_expand_builtin_string_cmp (tree exp, rtx target)
gcc_checking_assert (const_str_n > 0);
length = (const_str_n == 1) ? len1 : len2;
- if (is_ncmp && (len3 = tree_to_uhwi (len3_tree)) < length)
+ if (is_ncmp && len3 < length)
length = len3;
/* If the length of the comparision is larger than the threshold,
@@ -10224,7 +10229,7 @@ fold_builtin_next_arg (tree exp, bool va_start_p)
if (!stdarg_p (fntype))
{
- error ("%<va_start%> used in function with fixed args");
+ error ("%<va_start%> used in function with fixed arguments");
return true;
}
diff --git a/gcc/builtins.def b/gcc/builtins.def
index c92292a..6d41bdb 100644
--- a/gcc/builtins.def
+++ b/gcc/builtins.def
@@ -288,7 +288,7 @@ DEF_C99_BUILTIN (BUILT_IN_ACOSH, "acosh", BT_FN_DOUBLE_DOUBLE, ATTR_MATHF
DEF_C99_BUILTIN (BUILT_IN_ACOSHF, "acoshf", BT_FN_FLOAT_FLOAT, ATTR_MATHFN_FPROUNDING_ERRNO)
DEF_C99_BUILTIN (BUILT_IN_ACOSHL, "acoshl", BT_FN_LONGDOUBLE_LONGDOUBLE, ATTR_MATHFN_FPROUNDING_ERRNO)
DEF_C99_C90RES_BUILTIN (BUILT_IN_ACOSL, "acosl", BT_FN_LONGDOUBLE_LONGDOUBLE, ATTR_MATHFN_FPROUNDING_ERRNO)
-DEF_C11_BUILTIN (BUILT_IN_ALIGNED_ALLOC, "aligned_alloc", BT_FN_PTR_SIZE_SIZE, ATTR_ALLOC_SIZE_2_NOTHROW_LIST)
+DEF_C11_BUILTIN (BUILT_IN_ALIGNED_ALLOC, "aligned_alloc", BT_FN_PTR_SIZE_SIZE, ATTR_ALLOC_WARN_UNUSED_RESULT_SIZE_2_NOTHROW_LIST)
DEF_LIB_BUILTIN (BUILT_IN_ASIN, "asin", BT_FN_DOUBLE_DOUBLE, ATTR_MATHFN_FPROUNDING_ERRNO)
DEF_C99_C90RES_BUILTIN (BUILT_IN_ASINF, "asinf", BT_FN_FLOAT_FLOAT, ATTR_MATHFN_FPROUNDING_ERRNO)
DEF_C99_BUILTIN (BUILT_IN_ASINH, "asinh", BT_FN_DOUBLE_DOUBLE, ATTR_MATHFN_FPROUNDING)
@@ -702,8 +702,8 @@ DEF_LIB_BUILTIN (BUILT_IN_STRCHR, "strchr", BT_FN_STRING_CONST_STRING_INT
DEF_LIB_BUILTIN (BUILT_IN_STRCMP, "strcmp", BT_FN_INT_CONST_STRING_CONST_STRING, ATTR_PURE_NOTHROW_NONNULL_LEAF)
DEF_LIB_BUILTIN (BUILT_IN_STRCPY, "strcpy", BT_FN_STRING_STRING_CONST_STRING, ATTR_RET1_NOTHROW_NONNULL_LEAF)
DEF_LIB_BUILTIN (BUILT_IN_STRCSPN, "strcspn", BT_FN_SIZE_CONST_STRING_CONST_STRING, ATTR_PURE_NOTHROW_NONNULL_LEAF)
-DEF_EXT_LIB_BUILTIN (BUILT_IN_STRDUP, "strdup", BT_FN_STRING_CONST_STRING, ATTR_MALLOC_NOTHROW_NONNULL_LEAF)
-DEF_EXT_LIB_BUILTIN (BUILT_IN_STRNDUP, "strndup", BT_FN_STRING_CONST_STRING_SIZE, ATTR_MALLOC_NOTHROW_NONNULL_LEAF)
+DEF_EXT_LIB_BUILTIN (BUILT_IN_STRDUP, "strdup", BT_FN_STRING_CONST_STRING, ATTR_MALLOC_WARN_UNUSED_RESULT_NOTHROW_NONNULL_LEAF)
+DEF_EXT_LIB_BUILTIN (BUILT_IN_STRNDUP, "strndup", BT_FN_STRING_CONST_STRING_SIZE, ATTR_MALLOC_WARN_UNUSED_RESULT_NOTHROW_NONNULL_LEAF)
DEF_LIB_BUILTIN (BUILT_IN_STRLEN, "strlen", BT_FN_SIZE_CONST_STRING, ATTR_PURE_NOTHROW_NONNULL_LEAF)
DEF_EXT_LIB_BUILTIN (BUILT_IN_STRNCASECMP, "strncasecmp", BT_FN_INT_CONST_STRING_CONST_STRING_SIZE, ATTR_PURE_NOTHROW_NONNULL_LEAF)
DEF_LIB_BUILTIN (BUILT_IN_STRNCAT, "strncat", BT_FN_STRING_STRING_CONST_STRING_SIZE, ATTR_RET1_NOTHROW_NONNULL_LEAF)
@@ -811,7 +811,7 @@ DEF_GCC_BUILTIN (BUILT_IN_UMULLL_OVERFLOW, "umulll_overflow", BT_FN_BOOL_
DEF_LIB_BUILTIN (BUILT_IN_ABORT, "abort", BT_FN_VOID, ATTR_TMPURE_NORETURN_NOTHROW_LEAF_COLD_LIST)
DEF_LIB_BUILTIN (BUILT_IN_ABS, "abs", BT_FN_INT_INT, ATTR_CONST_NOTHROW_LEAF_LIST)
DEF_GCC_BUILTIN (BUILT_IN_AGGREGATE_INCOMING_ADDRESS, "aggregate_incoming_address", BT_FN_PTR_VAR, ATTR_LEAF_LIST)
-DEF_EXT_LIB_BUILTIN (BUILT_IN_ALLOCA, "alloca", BT_FN_PTR_SIZE, ATTR_ALLOCA_SIZE_1_NOTHROW_LEAF_LIST)
+DEF_EXT_LIB_BUILTIN (BUILT_IN_ALLOCA, "alloca", BT_FN_PTR_SIZE, ATTR_ALLOCA_WARN_UNUSED_RESULT_SIZE_1_NOTHROW_LEAF_LIST)
DEF_GCC_BUILTIN (BUILT_IN_APPLY, "apply", BT_FN_PTR_PTR_FN_VOID_VAR_PTR_SIZE, ATTR_NULL)
DEF_GCC_BUILTIN (BUILT_IN_APPLY_ARGS, "apply_args", BT_FN_PTR_VAR, ATTR_LEAF_LIST)
DEF_GCC_BUILTIN (BUILT_IN_BSWAP16, "bswap16", BT_FN_UINT16_UINT16, ATTR_CONST_NOTHROW_LEAF_LIST)
@@ -819,7 +819,7 @@ DEF_GCC_BUILTIN (BUILT_IN_BSWAP32, "bswap32", BT_FN_UINT32_UINT32, ATTR_C
DEF_GCC_BUILTIN (BUILT_IN_BSWAP64, "bswap64", BT_FN_UINT64_UINT64, ATTR_CONST_NOTHROW_LEAF_LIST)
DEF_EXT_LIB_BUILTIN (BUILT_IN_CLEAR_CACHE, "__clear_cache", BT_FN_VOID_PTR_PTR, ATTR_NOTHROW_LEAF_LIST)
/* [trans-mem]: Adjust BUILT_IN_TM_CALLOC if BUILT_IN_CALLOC is changed. */
-DEF_LIB_BUILTIN (BUILT_IN_CALLOC, "calloc", BT_FN_PTR_SIZE_SIZE, ATTR_MALLOC_SIZE_1_2_NOTHROW_LEAF_LIST)
+DEF_LIB_BUILTIN (BUILT_IN_CALLOC, "calloc", BT_FN_PTR_SIZE_SIZE, ATTR_MALLOC_WARN_UNUSED_RESULT_SIZE_1_2_NOTHROW_LEAF_LIST)
DEF_GCC_BUILTIN (BUILT_IN_CLASSIFY_TYPE, "classify_type", BT_FN_INT_VAR, ATTR_LEAF_LIST)
DEF_GCC_BUILTIN (BUILT_IN_CLZ, "clz", BT_FN_INT_UINT, ATTR_CONST_NOTHROW_LEAF_LIST)
DEF_GCC_BUILTIN (BUILT_IN_CLZIMAX, "clzimax", BT_FN_INT_UINTMAX, ATTR_CONST_NOTHROW_LEAF_LIST)
@@ -896,7 +896,7 @@ DEF_LIB_BUILTIN (BUILT_IN_LABS, "labs", BT_FN_LONG_LONG, ATTR_CONST_NOTHR
DEF_C99_BUILTIN (BUILT_IN_LLABS, "llabs", BT_FN_LONGLONG_LONGLONG, ATTR_CONST_NOTHROW_LEAF_LIST)
DEF_GCC_BUILTIN (BUILT_IN_LONGJMP, "longjmp", BT_FN_VOID_PTR_INT, ATTR_NORETURN_NOTHROW_LIST)
/* [trans-mem]: Adjust BUILT_IN_TM_MALLOC if BUILT_IN_MALLOC is changed. */
-DEF_LIB_BUILTIN (BUILT_IN_MALLOC, "malloc", BT_FN_PTR_SIZE, ATTR_MALLOC_SIZE_1_NOTHROW_LEAF_LIST)
+DEF_LIB_BUILTIN (BUILT_IN_MALLOC, "malloc", BT_FN_PTR_SIZE, ATTR_MALLOC_WARN_UNUSED_RESULT_SIZE_1_NOTHROW_LEAF_LIST)
DEF_GCC_BUILTIN (BUILT_IN_NEXT_ARG, "next_arg", BT_FN_PTR_VAR, ATTR_LEAF_LIST)
DEF_GCC_BUILTIN (BUILT_IN_PARITY, "parity", BT_FN_INT_UINT, ATTR_CONST_NOTHROW_LEAF_LIST)
DEF_GCC_BUILTIN (BUILT_IN_PARITYIMAX, "parityimax", BT_FN_INT_UINTMAX, ATTR_CONST_NOTHROW_LEAF_LIST)
@@ -908,7 +908,7 @@ DEF_GCC_BUILTIN (BUILT_IN_POPCOUNTL, "popcountl", BT_FN_INT_ULONG, ATTR_C
DEF_GCC_BUILTIN (BUILT_IN_POPCOUNTLL, "popcountll", BT_FN_INT_ULONGLONG, ATTR_CONST_NOTHROW_LEAF_LIST)
DEF_EXT_LIB_BUILTIN (BUILT_IN_POSIX_MEMALIGN, "posix_memalign", BT_FN_INT_PTRPTR_SIZE_SIZE, ATTR_NOTHROW_NONNULL_LEAF)
DEF_GCC_BUILTIN (BUILT_IN_PREFETCH, "prefetch", BT_FN_VOID_CONST_PTR_VAR, ATTR_NOVOPS_LEAF_LIST)
-DEF_LIB_BUILTIN (BUILT_IN_REALLOC, "realloc", BT_FN_PTR_PTR_SIZE, ATTR_ALLOC_SIZE_2_NOTHROW_LEAF_LIST)
+DEF_LIB_BUILTIN (BUILT_IN_REALLOC, "realloc", BT_FN_PTR_PTR_SIZE, ATTR_ALLOC_WARN_UNUSED_RESULT_SIZE_2_NOTHROW_LEAF_LIST)
DEF_GCC_BUILTIN (BUILT_IN_RETURN, "return", BT_FN_VOID_PTR, ATTR_NORETURN_NOTHROW_LEAF_LIST)
DEF_GCC_BUILTIN (BUILT_IN_RETURN_ADDRESS, "return_address", BT_FN_PTR_UINT, ATTR_LEAF_LIST)
DEF_GCC_BUILTIN (BUILT_IN_SAVEREGS, "saveregs", BT_FN_PTR_VAR, ATTR_NULL)
diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog
index 59810b8..84d1f2e 100644
--- a/gcc/c-family/ChangeLog
+++ b/gcc/c-family/ChangeLog
@@ -1,3 +1,178 @@
+2019-07-03 Martin Liska <mliska@suse.cz>
+
+ * c-common.c (try_to_locate_new_include_insertion_point): Remove
+ dead assignemts.
+
+2019-07-03 Jakub Jelinek <jakub@redhat.com>
+
+ * c-omp.c (c_omp_split_clauses): Put OMP_CLAUSE_REDUCTION_INSCAN
+ clauses on OMP_FOR rather than OMP_PARALLEL when OMP_FOR is combined
+ with OMP_PARALLEL.
+
+2019-07-02 qing zhao <qing.zhao@oracle.com>
+
+ PR preprocessor/90581
+ * c-opts.c (c_common_handle_option): Handle -fmax-include-depth.
+ * c.opt: Add new option -fmax-include-depth.
+
+2019-06-26 Jason Merrill <jason@redhat.com>
+
+ PR c++/55442 - memory-hog with highly recursive constexpr.
+ * c.opt (fconstexpr-loop-limit): New.
+
+2019-06-25 Jakub Jelinek <jakub@redhat.com>
+
+ PR sanitizer/90954
+ * c-omp.c (c_finish_omp_atomic): Allow tree_invariant_p in addition
+ to SAVE_EXPR in first operand of a COMPOUND_EXPR.
+
+2019-06-24 Jan Hubicka <jh@suse.cz>
+
+ * c-common.c (braced_lists_to_strings): Check that
+ type is array or integer prior checking string flag.
+
+2019-06-21 Matthew Beliveau <mbelivea@redhat.com>
+
+ PR c++/90875 - added -Wswitch-outside-range option
+ * c.opt (Wswitch-outside-range): Added new option.
+ * c-warn.c (c_do_switch_warnings): Use OPT_Wswitch-outside-range.
+
+2019-06-21 Marek Polacek <polacek@redhat.com>
+
+ PR c++/90953 - ICE with -Wmissing-format-attribute.
+ * c-common.c (check_function_arguments_recurse): Use
+ get_attribute_name.
+ (check_missing_format_attribute): Likewise.
+
+2019-06-19 Marek Polacek <polacek@redhat.com>
+
+ PR c++/60364 - noreturn after first decl not diagnosed.
+ * c-attribs.c (handle_noreturn_attribute): No longer static.
+ * c-common.h (handle_noreturn_attribute, attr_noreturn_exclusions):
+ Declare.
+ * c-format.c (check_function_format): Use get_attribute_name.
+
+2019-06-19 Martin Sebor <msebor@redhat.com>
+
+ PR translation/90156
+ * c-format.c (function_format_info::format_type): Adjust type.
+ (function_format_info::is_raw): New member.
+ (decode_format_type): Adjust signature. Handle "raw" diag attributes.
+ (decode_format_attr): Adjust call to decode_format_type.
+ Avoid a redundant call to convert_format_name_to_system_name.
+ Avoid abbreviating the word "arguments" in a diagnostic.
+ (format_warning_substr): New function.
+ (avoid_dollar_number): Quote dollar sign in a diagnostic.
+ (finish_dollar_format_checking): Same.
+ (check_format_info): Same.
+ (struct baltoks_t): New.
+ (c_opers, c_keywords, cxx_keywords, badwords, contrs): New arrays.
+ (maybe_diag_unbalanced_tokens, check_tokens, check_plain): New
+ functions.
+ (check_format_info_main): Call check_plain. Use baltoks_t. Call
+ maybe_diag_unbalanced_tokens.
+ (handle_format_attribute): Spell out the word "arguments" in
+ a diagnostic.
+
+2019-06-11 Matthew Beliveau <mbelivea@redhat.com>
+
+ PR c++/90449 - add -Winaccessible-base option.
+ * c.opt (Winaccessible-base): New option.
+
+2019-06-10 Jakub Jelinek <jakub@redhat.com>
+
+ * c-pragma.h (enum pragma_kind): Add PRAGMA_OMP_SCAN.
+ * c-pragma.c (omp_pragmas_simd): Add #pragma omp scan.
+ * c-omp.c (c_omp_split_clauses): Diagnose inscan reductions on
+ combined/composite constructs where it is not allowed. Copy over
+ OMP_CLAUSE_REDUCTION_INSCAN.
+
+2019-06-05 Martin Sebor <msebor@redhat.com>
+
+ * c-attribs.c (handle_mode_attribute): Adjust quoting and hyphenation.
+ (handle_alias_ifunc_attribute): Same.
+ (handle_copy_attribute): Same.
+ (handle_weakref_attribute): Same.
+ (handle_nonnull_attribute): Same.
+ * c-warn.c (warn_for_sign_compare): Same.
+ (warn_for_restrict): Same.
+ * c.opt: Same.
+
+2019-06-05 Martin Sebor <msebor@redhat.com>
+
+ * c-pragma.c (handle_pragma_weak): Adjust quoting in a diagnostic.
+ * c.opt (-Wformat-diag): Remove a spurious period.
+
+2019-05-29 Jakub Jelinek <jakub@redhat.com>
+
+ PR c/90628
+ * c-common.c (check_builtin_function_arguments)
+ <case BUILTIN_*_OVERFLOW>: Diagnose pointer to const qualified integer
+ as last argument.
+
+2019-05-23 Eric Botcazou <ebotcazou@adacore.com>
+
+ * c-ada-spec.c (compare_node): Compare the DECL_UIDs as a last resort.
+
+2019-05-22 Martin Liska <mliska@suse.cz>
+
+ PR lto/90500
+ * c-attribs.c (handle_copy_attribute): Do not copy
+ target_clones attribute.
+
+2019-05-21 Eric Botcazou <ebotcazou@adacore.com>
+
+ * c-ada-spec.h (enum cpp_operation): Add IS_ASSIGNMENT_OPERATOR.
+ * c-ada-spec.c (print_assignment_operator): New function.
+ (dump_ada_declaration) <FUNCTION_DECL>: Call it do dump explicit copy
+ assignment operators declared as methods and filter out the others.
+
+2019-05-17 Thomas Schwinge <thomas@codesourcery.com>
+
+ PR c/89433
+ * c-attribs.c (c_common_attribute_table): Set min_len to -1 for
+ "omp declare target".
+
+2019-05-16 Martin Sebor <msebor@redhat.com>
+
+ * c-attribs.c (handle_no_sanitize_attribute): Quote identifiers,
+ keywords, operators, and types in diagnostics.
+ (handle_scalar_storage_order_attribute): Same.
+ (handle_mode_attribute): Same.
+ (handle_visibility_attribute): Same.
+ (handle_assume_aligned_attribute): Same.
+ (handle_no_split_stack_attribute): Same.
+ * c-common.c (shorten_compare): Same.
+ (c_common_truthvalue_conversion): Same.
+ (cb_get_source_date_epoch): Same.
+ * c-lex.c (cb_def_pragma): Quote keywords, operators, and types
+ in diagnostics.
+ (interpret_float): Same.
+ * c-omp.c (c_finish_omp_for): Same.
+ * c-opts.c (c_common_post_options): Same.
+ * c-pch.c (c_common_pch_pragma): Same.
+ * c-pragma.c (pop_alignment): Same.
+ (handle_pragma_pack): Same.
+ (apply_pragma_weak): Same.
+ (handle_pragma_weak): Same.
+ (handle_pragma_scalar_storage_order): Same.
+ (handle_pragma_redefine_extname): Same.
+ (add_to_renaming_pragma_list): Same.
+ (maybe_apply_renaming_pragma): Same.
+ (push_visibility): Same.
+ (handle_pragma_visibility): Same.
+ (handle_pragma_optimize): Same.
+ (handle_pragma_message): Same.
+ * c-warn.c (warn_for_omitted_condop): Same.
+ (lvalue_error): Same.
+
+2019-05-15 Richard Biener <rguenther@suse.de>
+
+ PR c/90474
+ * c-common.c (c_common_mark_addressable_vec): Also mark
+ a COMPOUND_LITERAL_EXPR_DECL addressable similar to
+ c_mark_addressable.
+
2019-05-06 Nathan Sidwell <nathan@acm.org>
* c-opts.c (handle_defered_opts): Rename struct deps to struc mkdeps.
diff --git a/gcc/c-family/c-ada-spec.c b/gcc/c-family/c-ada-spec.c
index c85e606..4526850 100644
--- a/gcc/c-family/c-ada-spec.c
+++ b/gcc/c-family/c-ada-spec.c
@@ -679,8 +679,10 @@ compare_node (const void *lp, const void *rp)
{
const_tree lhs = *((const tree *) lp);
const_tree rhs = *((const tree *) rp);
+ const int ret
+ = compare_location (decl_sloc (lhs, true), decl_sloc (rhs, true));
- return compare_location (decl_sloc (lhs, true), decl_sloc (rhs, true));
+ return ret ? ret : DECL_UID (lhs) - DECL_UID (rhs);
}
/* Compare two comments (LP and RP) by their source location. */
@@ -2681,6 +2683,17 @@ print_destructor (pretty_printer *buffer, tree t, tree type)
pp_ada_tree_identifier (buffer, decl_name, t, false);
}
+/* Dump in BUFFER assignment operator spec corresponding to T. */
+
+static void
+print_assignment_operator (pretty_printer *buffer, tree t, tree type)
+{
+ tree decl_name = DECL_NAME (TYPE_NAME (type));
+
+ pp_string (buffer, "Assign_");
+ pp_ada_tree_identifier (buffer, decl_name, t, false);
+}
+
/* Return the name of type T. */
static const char *
@@ -2920,6 +2933,7 @@ dump_ada_declaration (pretty_printer *buffer, tree t, tree type, int spc)
bool is_method = TREE_CODE (TREE_TYPE (t)) == METHOD_TYPE;
tree decl_name = DECL_NAME (t);
bool is_abstract = false;
+ bool is_assignment_operator = false;
bool is_constructor = false;
bool is_destructor = false;
bool is_copy_constructor = false;
@@ -2931,6 +2945,7 @@ dump_ada_declaration (pretty_printer *buffer, tree t, tree type, int spc)
if (cpp_check)
{
is_abstract = cpp_check (t, IS_ABSTRACT);
+ is_assignment_operator = cpp_check (t, IS_ASSIGNMENT_OPERATOR);
is_constructor = cpp_check (t, IS_CONSTRUCTOR);
is_destructor = cpp_check (t, IS_DESTRUCTOR);
is_copy_constructor = cpp_check (t, IS_COPY_CONSTRUCTOR);
@@ -2955,6 +2970,13 @@ dump_ada_declaration (pretty_printer *buffer, tree t, tree type, int spc)
return 0;
}
+ else if (is_assignment_operator)
+ {
+ /* ??? Skip implicit or non-method assignment operators for now. */
+ if (DECL_ARTIFICIAL (t) || !is_method)
+ return 0;
+ }
+
/* If this function has an entry in the vtable, we cannot omit it. */
else if (!DECL_VINDEX (t) && *IDENTIFIER_POINTER (decl_name) == '_')
{
@@ -2977,6 +2999,8 @@ dump_ada_declaration (pretty_printer *buffer, tree t, tree type, int spc)
print_constructor (buffer, t, type);
else if (is_destructor)
print_destructor (buffer, t, type);
+ else if (is_assignment_operator)
+ print_assignment_operator (buffer, t, type);
else
dump_ada_decl_name (buffer, t, false);
diff --git a/gcc/c-family/c-ada-spec.h b/gcc/c-family/c-ada-spec.h
index 5993662..f9ea1bc 100644
--- a/gcc/c-family/c-ada-spec.h
+++ b/gcc/c-family/c-ada-spec.h
@@ -27,6 +27,7 @@ along with GCC; see the file COPYING3. If not see
enum cpp_operation {
HAS_DEPENDENT_TEMPLATE_ARGS,
IS_ABSTRACT,
+ IS_ASSIGNMENT_OPERATOR,
IS_CONSTRUCTOR,
IS_DESTRUCTOR,
IS_COPY_CONSTRUCTOR,
diff --git a/gcc/c-family/c-attribs.c b/gcc/c-family/c-attribs.c
index 93b210e..48819e7 100644
--- a/gcc/c-family/c-attribs.c
+++ b/gcc/c-family/c-attribs.c
@@ -49,7 +49,6 @@ along with GCC; see the file COPYING3. If not see
static tree handle_packed_attribute (tree *, tree, tree, int, bool *);
static tree handle_nocommon_attribute (tree *, tree, tree, int, bool *);
static tree handle_common_attribute (tree *, tree, tree, int, bool *);
-static tree handle_noreturn_attribute (tree *, tree, tree, int, bool *);
static tree handle_hot_attribute (tree *, tree, tree, int, bool *);
static tree handle_cold_attribute (tree *, tree, tree, int, bool *);
static tree handle_no_sanitize_attribute (tree *, tree, tree, int, bool *);
@@ -190,7 +189,7 @@ static const struct attribute_spec::exclusions attr_noinline_exclusions[] =
ATTR_EXCL (NULL, false, false, false),
};
-static const struct attribute_spec::exclusions attr_noreturn_exclusions[] =
+extern const struct attribute_spec::exclusions attr_noreturn_exclusions[] =
{
ATTR_EXCL ("alloc_align", true, true, true),
ATTR_EXCL ("alloc_size", true, true, true),
@@ -437,7 +436,7 @@ const struct attribute_spec c_common_attribute_table[] =
handle_omp_declare_simd_attribute, NULL },
{ "simd", 0, 1, true, false, false, false,
handle_simd_attribute, NULL },
- { "omp declare target", 0, 0, true, false, false, false,
+ { "omp declare target", 0, -1, true, false, false, false,
handle_omp_declare_target_attribute, NULL },
{ "omp declare target link", 0, 0, true, false, false, false,
handle_omp_declare_target_attribute, NULL },
@@ -779,7 +778,7 @@ handle_common_attribute (tree *node, tree name, tree ARG_UNUSED (args),
/* Handle a "noreturn" attribute; arguments as in
struct attribute_spec.handler. */
-static tree
+tree
handle_noreturn_attribute (tree *node, tree name, tree ARG_UNUSED (args),
int ARG_UNUSED (flags), bool *no_add_attrs)
{
@@ -891,7 +890,7 @@ handle_no_sanitize_attribute (tree *node, tree name, tree args, int,
tree id = TREE_VALUE (args);
if (TREE_CODE (id) != STRING_CST)
{
- error ("no_sanitize argument not a string");
+ error ("%qE argument not a string", name);
return NULL_TREE;
}
@@ -1418,8 +1417,8 @@ handle_scalar_storage_order_attribute (tree *node, tree name, tree args,
if (BYTES_BIG_ENDIAN != WORDS_BIG_ENDIAN)
{
- error ("scalar_storage_order is not supported because endianness "
- "is not uniform");
+ error ("%qE attribute is not supported because endianness is not uniform",
+ name);
return NULL_TREE;
}
@@ -1435,8 +1434,8 @@ handle_scalar_storage_order_attribute (tree *node, tree name, tree args,
reverse = BYTES_BIG_ENDIAN;
else
{
- error ("scalar_storage_order argument must be one of \"big-endian\""
- " or \"little-endian\"");
+ error ("attribute %qE argument must be one of %qs or %qs",
+ name, "big-endian", "little-endian");
return NULL_TREE;
}
@@ -1759,9 +1758,9 @@ handle_mode_attribute (tree *node, tree name, tree args,
case MODE_VECTOR_ACCUM:
case MODE_VECTOR_UACCUM:
warning (OPT_Wattributes, "specifying vector types with "
- "__attribute__ ((mode)) is deprecated");
- warning (OPT_Wattributes,
- "use __attribute__ ((vector_size)) instead");
+ "%<__attribute__ ((mode))%> is deprecated");
+ inform (input_location,
+ "use %<__attribute__ ((vector_size))%> instead");
valid_mode = vector_mode_valid_p (mode);
break;
@@ -1821,7 +1820,7 @@ handle_mode_attribute (tree *node, tree name, tree args,
this mode for this type. */
if (TREE_CODE (typefm) != INTEGER_TYPE)
{
- error ("cannot use mode %qs for enumeral types", p);
+ error ("cannot use mode %qs for enumerated types", p);
return NULL_TREE;
}
@@ -2326,12 +2325,8 @@ handle_alias_ifunc_attribute (bool is_alias, tree *node, tree name, tree args,
{
struct symtab_node *n = symtab_node::get (decl);
if (n && n->refuse_visibility_changes)
- {
- if (is_alias)
- error ("%+qD declared alias after being used", decl);
- else
- error ("%+qD declared ifunc after being used", decl);
- }
+ error ("%+qD declared %qs after being used",
+ decl, is_alias ? "alias" : "ifunc");
}
@@ -2486,7 +2481,8 @@ handle_copy_attribute (tree *node, tree name, tree args,
|| is_attribute_p ("noinline", atname)
|| is_attribute_p ("visibility", atname)
|| is_attribute_p ("weak", atname)
- || is_attribute_p ("weakref", atname))
+ || is_attribute_p ("weakref", atname)
+ || is_attribute_p ("target_clones", atname))
continue;
/* Attribute leaf only applies to extern functions.
@@ -2547,7 +2543,7 @@ handle_copy_attribute (tree *node, tree name, tree args,
attribute_spec.handler. */
static tree
-handle_weakref_attribute (tree *node, tree ARG_UNUSED (name), tree args,
+handle_weakref_attribute (tree *node, tree name, tree args,
int flags, bool *no_add_attrs)
{
tree attr = NULL_TREE;
@@ -2566,7 +2562,8 @@ handle_weakref_attribute (tree *node, tree ARG_UNUSED (name), tree args,
if (lookup_attribute ("ifunc", DECL_ATTRIBUTES (*node)))
{
- error ("indirect function %q+D cannot be declared weakref", *node);
+ error ("indirect function %q+D cannot be declared %qE",
+ *node, name);
*no_add_attrs = true;
return NULL_TREE;
}
@@ -2588,7 +2585,8 @@ handle_weakref_attribute (tree *node, tree ARG_UNUSED (name), tree args,
{
if (lookup_attribute ("alias", DECL_ATTRIBUTES (*node)))
error_at (DECL_SOURCE_LOCATION (*node),
- "weakref attribute must appear before alias attribute");
+ "%qE attribute must appear before %qs attribute",
+ name, "alias");
/* Can't call declare_weak because it wants this to be TREE_PUBLIC,
and that isn't supported; and because it wants to add it to
@@ -2600,7 +2598,7 @@ handle_weakref_attribute (tree *node, tree ARG_UNUSED (name), tree args,
{
struct symtab_node *n = symtab_node::get (*node);
if (n && n->refuse_visibility_changes)
- error ("%+qD declared weakref after being used", *node);
+ error ("%+qD declared %qE after being used", *node, name);
}
return NULL_TREE;
@@ -2671,7 +2669,8 @@ handle_visibility_attribute (tree *node, tree name, tree args,
vis = VISIBILITY_PROTECTED;
else
{
- error ("visibility argument must be one of \"default\", \"hidden\", \"protected\" or \"internal\"");
+ error ("attribute %qE argument must be one of %qs, %qs, %qs, or %qs",
+ name, "default", "hidden", "protected", "internal");
vis = VISIBILITY_DEFAULT;
}
@@ -2935,8 +2934,8 @@ handle_assume_aligned_attribute (tree *node, tree name, tree args, int,
/* The misalignment specified by the second argument
must be non-negative and less than the alignment. */
warning (OPT_Wattributes,
- "%qE attribute argument %E is not in the range [0, %E)",
- name, val, align);
+ "%qE attribute argument %E is not in the range [0, %wu]",
+ name, val, tree_to_uhwi (align) - 1);
*no_add_attrs = true;
return NULL_TREE;
}
@@ -3083,7 +3082,7 @@ handle_no_limit_stack_attribute (tree *node, tree name,
else if (DECL_INITIAL (decl))
{
error_at (DECL_SOURCE_LOCATION (decl),
- "can%'t set %qE attribute after definition", name);
+ "cannot set %qE attribute after definition", name);
*no_add_attrs = true;
}
else
@@ -3623,7 +3622,8 @@ handle_nonnull_attribute (tree *node, tree name,
&& (!TYPE_ATTRIBUTES (type)
|| !lookup_attribute ("type generic", TYPE_ATTRIBUTES (type))))
{
- error ("nonnull attribute without arguments on a non-prototype");
+ error ("%qE attribute without arguments on a non-prototype",
+ name);
*no_add_attrs = true;
}
return NULL_TREE;
@@ -3974,7 +3974,7 @@ handle_no_split_stack_attribute (tree *node, tree name,
else if (DECL_INITIAL (decl))
{
error_at (DECL_SOURCE_LOCATION (decl),
- "can%'t set %qE attribute after definition", name);
+ "cannot set %qE attribute after definition", name);
*no_add_attrs = true;
}
@@ -3985,13 +3985,13 @@ handle_no_split_stack_attribute (tree *node, tree name,
struct attribute_spec.handler. */
static tree
-handle_returns_nonnull_attribute (tree *node, tree, tree, int,
+handle_returns_nonnull_attribute (tree *node, tree name, tree, int,
bool *no_add_attrs)
{
// Even without a prototype we still have a return type we can check.
if (TREE_CODE (TREE_TYPE (*node)) != POINTER_TYPE)
{
- error ("returns_nonnull attribute on a function not returning a pointer");
+ error ("%qE attribute on a function not returning a pointer", name);
*no_add_attrs = true;
}
return NULL_TREE;
diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c
index 3c2f7a9..cb92710 100644
--- a/gcc/c-family/c-common.c
+++ b/gcc/c-family/c-common.c
@@ -3063,14 +3063,16 @@ shorten_compare (location_t loc, tree *op0_ptr, tree *op1_ptr,
case GE_EXPR:
if (warn)
warning_at (loc, OPT_Wtype_limits,
- "comparison of unsigned expression >= 0 is always true");
+ "comparison of unsigned expression in %<>= 0%> "
+ "is always true");
value = truthvalue_true_node;
break;
case LT_EXPR:
if (warn)
warning_at (loc, OPT_Wtype_limits,
- "comparison of unsigned expression < 0 is always false");
+ "comparison of unsigned expression in %<< 0%> "
+ "is always false");
value = truthvalue_false_node;
break;
@@ -3379,7 +3381,7 @@ c_common_truthvalue_conversion (location_t location, tree expr)
if (TREE_CODE (TREE_TYPE (expr)) == INTEGER_TYPE
&& !TYPE_UNSIGNED (TREE_TYPE (expr)))
warning_at (EXPR_LOCATION (expr), OPT_Wint_in_bool_context,
- "%<<<%> in boolean context, did you mean %<<%> ?");
+ "%<<<%> in boolean context, did you mean %<<%>?");
break;
case COND_EXPR:
@@ -3395,7 +3397,7 @@ c_common_truthvalue_conversion (location_t location, tree expr)
&& (!integer_onep (val1)
|| !integer_onep (val2)))
warning_at (EXPR_LOCATION (expr), OPT_Wint_in_bool_context,
- "?: using integer constants in boolean context, "
+ "%<?:%> using integer constants in boolean context, "
"the expression will always evaluate to %<true%>");
else if ((TREE_CODE (val1) == INTEGER_CST
&& !integer_zerop (val1)
@@ -3404,7 +3406,7 @@ c_common_truthvalue_conversion (location_t location, tree expr)
&& !integer_zerop (val2)
&& !integer_onep (val2)))
warning_at (EXPR_LOCATION (expr), OPT_Wint_in_bool_context,
- "?: using integer constants in boolean context");
+ "%<?:%> using integer constants in boolean context");
}
/* Distribute the conversion into the arms of a COND_EXPR. */
if (c_dialect_cxx ())
@@ -4022,8 +4024,14 @@ c_common_nodes_and_builtins (void)
sprintf (name, "__int%d", int_n_data[i].bitsize);
record_builtin_type ((enum rid)(RID_FIRST_INT_N + i), name,
int_n_trees[i].signed_type);
+ sprintf (name, "__int%d__", int_n_data[i].bitsize);
+ record_builtin_type ((enum rid)(RID_FIRST_INT_N + i), name,
+ int_n_trees[i].signed_type);
+
sprintf (name, "__int%d unsigned", int_n_data[i].bitsize);
record_builtin_type (RID_MAX, name, int_n_trees[i].unsigned_type);
+ sprintf (name, "__int%d__ unsigned", int_n_data[i].bitsize);
+ record_builtin_type (RID_MAX, name, int_n_trees[i].unsigned_type);
}
if (c_dialect_cxx ())
@@ -5751,7 +5759,7 @@ check_function_arguments_recurse (void (*callback)
for (attrs = TYPE_ATTRIBUTES (type);
attrs;
attrs = TREE_CHAIN (attrs))
- if (is_attribute_p ("format_arg", TREE_PURPOSE (attrs)))
+ if (is_attribute_p ("format_arg", get_attribute_name (attrs)))
{
tree inner_arg;
tree format_num_expr;
@@ -5993,6 +6001,13 @@ check_builtin_function_arguments (location_t loc, vec<location_t> arg_loc,
"has pointer to boolean type", fndecl);
return false;
}
+ else if (TYPE_READONLY (TREE_TYPE (TREE_TYPE (args[2]))))
+ {
+ error_at (ARG_LOCATION (2), "argument 3 in call to function %qE "
+ "has pointer to %<const%> type (%qT)", fndecl,
+ TREE_TYPE (args[2]));
+ return false;
+ }
return true;
}
return false;
@@ -6554,6 +6569,8 @@ c_common_mark_addressable_vec (tree t)
return;
if (!VAR_P (t) || !DECL_HARD_REGISTER (t))
TREE_ADDRESSABLE (t) = 1;
+ if (TREE_CODE (t) == COMPOUND_LITERAL_EXPR)
+ TREE_ADDRESSABLE (COMPOUND_LITERAL_EXPR_DECL (t)) = 1;
}
@@ -7590,13 +7607,13 @@ check_missing_format_attribute (tree ltype, tree rtype)
tree ra;
for (ra = TYPE_ATTRIBUTES (ttr); ra; ra = TREE_CHAIN (ra))
- if (is_attribute_p ("format", TREE_PURPOSE (ra)))
+ if (is_attribute_p ("format", get_attribute_name (ra)))
break;
if (ra)
{
tree la;
for (la = TYPE_ATTRIBUTES (ttl); la; la = TREE_CHAIN (la))
- if (is_attribute_p ("format", TREE_PURPOSE (la)))
+ if (is_attribute_p ("format", get_attribute_name (la)))
break;
return !la;
}
@@ -8257,9 +8274,9 @@ cb_get_source_date_epoch (cpp_reader *pfile ATTRIBUTE_UNUSED)
if (errno != 0 || endptr == source_date_epoch || *endptr != '\0'
|| epoch < 0 || epoch > MAX_SOURCE_DATE_EPOCH)
{
- error_at (input_location, "environment variable SOURCE_DATE_EPOCH must "
+ error_at (input_location, "environment variable %qs must "
"expand to a non-negative integer less than or equal to %wd",
- MAX_SOURCE_DATE_EPOCH);
+ "SOURCE_DATE_EPOCH", MAX_SOURCE_DATE_EPOCH);
return (time_t) -1;
}
@@ -8584,8 +8601,8 @@ try_to_locate_new_include_insertion_point (const char *file, location_t loc)
/* Get ordinary map containing LOC (or its expansion). */
const line_map_ordinary *ord_map_for_loc = NULL;
- loc = linemap_resolve_location (line_table, loc, LRK_MACRO_EXPANSION_POINT,
- &ord_map_for_loc);
+ linemap_resolve_location (line_table, loc, LRK_MACRO_EXPANSION_POINT,
+ &ord_map_for_loc);
gcc_assert (ord_map_for_loc);
for (unsigned int i = 0; i < LINEMAPS_ORDINARY_USED (line_table); i++)
@@ -8836,7 +8853,8 @@ braced_lists_to_strings (tree type, tree ctor)
else
return ctor;
- if (TYPE_STRING_FLAG (ttp))
+ if ((TREE_CODE (ttp) == ARRAY_TYPE || TREE_CODE (ttp) == INTEGER_TYPE)
+ && TYPE_STRING_FLAG (ttp))
return braced_list_to_string (type, ctor);
code = TREE_CODE (ttp);
diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h
index 1cf2cae..5ac6e5e 100644
--- a/gcc/c-family/c-common.h
+++ b/gcc/c-family/c-common.h
@@ -1344,6 +1344,8 @@ extern int tm_attr_to_mask (tree);
extern tree tm_mask_to_attr (int);
extern tree find_tm_attribute (tree);
extern const struct attribute_spec::exclusions attr_cold_hot_exclusions[];
+extern const struct attribute_spec::exclusions attr_noreturn_exclusions[];
+extern tree handle_noreturn_attribute (tree *, tree, tree, int, bool *);
/* In c-format.c. */
extern bool valid_format_string_type_p (tree);
diff --git a/gcc/c-family/c-format.c b/gcc/c-family/c-format.c
index a7f76c1..6363fa4 100644
--- a/gcc/c-family/c-format.c
+++ b/gcc/c-family/c-format.c
@@ -52,7 +52,13 @@ enum format_type { printf_format_type, asm_fprintf_format_type,
struct function_format_info
{
- int format_type; /* type of format (printf, scanf, etc.) */
+ enum format_type format_type; /* type of format (printf, scanf, etc.) */
+ /* IS_RAW is relevant only for GCC diagnostic format functions.
+ It is set for "raw" formatting functions like pp_printf that
+ are not intended to produce complete diagnostics according to
+ GCC guidelines, and clear for others like error and warning
+ whose format string is checked for proper quoting and spelling. */
+ bool is_raw;
unsigned HOST_WIDE_INT format_num; /* number of format argument */
unsigned HOST_WIDE_INT first_arg_num; /* number of first arg (zero for varargs) */
};
@@ -65,7 +71,7 @@ static GTY(()) tree locus;
static bool decode_format_attr (const_tree, tree, tree, function_format_info *,
bool);
-static int decode_format_type (const char *);
+static format_type decode_format_type (const char *, bool * = NULL);
static bool check_format_string (const_tree argument,
unsigned HOST_WIDE_INT format_num,
@@ -111,6 +117,32 @@ format_warning_at_char (location_t fmt_string_loc, tree format_string_cst,
return warned;
}
+
+/* Emit a warning as per format_warning_va, but construct the substring_loc
+ for the substring at offset (POS1, POS2 - 1) within a string constant
+ FORMAT_STRING_CST at FMT_STRING_LOC. */
+
+ATTRIBUTE_GCC_DIAG (6,7)
+static bool
+format_warning_substr (location_t fmt_string_loc, tree format_string_cst,
+ int pos1, int pos2, int opt, const char *gmsgid, ...)
+{
+ va_list ap;
+ va_start (ap, gmsgid);
+ tree string_type = TREE_TYPE (format_string_cst);
+
+ pos2 -= 1;
+
+ substring_loc fmt_loc (fmt_string_loc, string_type, pos1, pos1, pos2);
+ format_string_diagnostic_t diag (fmt_loc, NULL, UNKNOWN_LOCATION, NULL,
+ NULL);
+ bool warned = diag.emit_warning_va (opt, gmsgid, &ap);
+ va_end (ap);
+
+ return warned;
+}
+
+
/* Check that we have a pointer to a string suitable for use as a format.
The default is to check for a char type.
For objective-c dialects, this is extended to include references to string
@@ -320,10 +352,8 @@ decode_format_attr (const_tree fntype, tree atname, tree args,
{
const char *p = IDENTIFIER_POINTER (format_type_id);
- p = convert_format_name_to_system_name (p);
+ info->format_type = decode_format_type (p, &info->is_raw);
- info->format_type = decode_format_type (p);
-
if (!c_dialect_objc ()
&& info->format_type == gcc_objc_string_format_type)
{
@@ -359,7 +389,7 @@ decode_format_attr (const_tree fntype, tree atname, tree args,
if (info->first_arg_num != 0 && info->first_arg_num <= info->format_num)
{
gcc_assert (!validated_p);
- error ("format string argument follows the args to be formatted");
+ error ("format string argument follows the arguments to be formatted");
return false;
}
@@ -674,7 +704,7 @@ static const format_char_info print_char_table[] =
{ "n", 1, STD_C89, { T89_I, T99_SC, T89_S, T89_L, T9L_LL, BADLEN, T99_SST, T99_PD, T99_IM, BADLEN, BADLEN, BADLEN }, "", "W", NULL },
/* C99 conversion specifiers. */
{ "F", 0, STD_C99, { T99_D, BADLEN, BADLEN, T99_D, BADLEN, T99_LD, BADLEN, BADLEN, BADLEN, TEX_D32, TEX_D64, TEX_D128 }, "-wp0 +#'I", "", NULL },
- { "aA", 0, STD_C99, { T99_D, BADLEN, BADLEN, T99_D, BADLEN, T99_LD, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "-wp0 +#", "", NULL },
+ { "aA", 0, STD_C99, { T99_D, BADLEN, BADLEN, T99_D, BADLEN, T99_LD, BADLEN, BADLEN, BADLEN, TEX_D32, TEX_D64, TEX_D128 }, "-wp0 +#", "", NULL },
/* X/Open conversion specifiers. */
{ "C", 0, STD_EXT, { TEX_WI, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "-w", "", NULL },
{ "S", 1, STD_EXT, { TEX_W, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "-wp", "R", NULL },
@@ -847,7 +877,7 @@ static const format_char_info scan_char_table[] =
{ "n", 1, STD_C89, { T89_I, T99_SC, T89_S, T89_L, T9L_LL, BADLEN, T99_SST, T99_PD, T99_IM, BADLEN, BADLEN, BADLEN }, "", "W", NULL },
/* C99 conversion specifiers. */
{ "F", 1, STD_C99, { T99_F, BADLEN, BADLEN, T99_D, BADLEN, T99_LD, BADLEN, BADLEN, BADLEN, TEX_D32, TEX_D64, TEX_D128 }, "*w'", "W", NULL },
- { "aA", 1, STD_C99, { T99_F, BADLEN, BADLEN, T99_D, BADLEN, T99_LD, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "*w'", "W", NULL },
+ { "aA", 1, STD_C99, { T99_F, BADLEN, BADLEN, T99_D, BADLEN, T99_LD, BADLEN, BADLEN, BADLEN, TEX_D32, TEX_D64, TEX_D128 }, "*w'", "W", NULL },
/* X/Open conversion specifiers. */
{ "C", 1, STD_EXT, { TEX_W, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "*mw", "W", NULL },
{ "S", 1, STD_EXT, { TEX_W, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "*amw", "W", NULL },
@@ -1067,27 +1097,55 @@ static void format_type_warning (const substring_loc &fmt_loc,
char conversion_char);
/* Decode a format type from a string, returning the type, or
- format_type_error if not valid, in which case the caller should print an
- error message. */
-static int
-decode_format_type (const char *s)
+ format_type_error if not valid, in which case the caller should
+ print an error message. On success, when IS_RAW is non-null, set
+ *IS_RAW when the format type corresponds to a GCC "raw" diagnostic
+ formatting function and clear it otherwise. */
+static format_type
+decode_format_type (const char *s, bool *is_raw /* = NULL */)
{
- int i;
- int slen;
+ bool is_raw_buf;
+
+ if (!is_raw)
+ is_raw = &is_raw_buf;
+
+ *is_raw = false;
s = convert_format_name_to_system_name (s);
- slen = strlen (s);
- for (i = 0; i < n_format_types; i++)
+
+ size_t slen = strlen (s);
+ for (int i = 0; i < n_format_types; i++)
{
- int alen;
+ /* Check for a match with no underscores. */
if (!strcmp (s, format_types[i].name))
- return i;
- alen = strlen (format_types[i].name);
+ return static_cast<format_type> (i);
+
+ /* Check for leading and trailing underscores. */
+ size_t alen = strlen (format_types[i].name);
if (slen == alen + 4 && s[0] == '_' && s[1] == '_'
&& s[slen - 1] == '_' && s[slen - 2] == '_'
&& !strncmp (s + 2, format_types[i].name, alen))
- return i;
+ return static_cast<format_type>(i);
+
+ /* Check for the "_raw" suffix and no leading underscores. */
+ if (slen == alen + 4
+ && !strncmp (s, format_types[i].name, alen)
+ && !strcmp (s + alen, "_raw"))
+ {
+ *is_raw = true;
+ return static_cast<format_type>(i);
+ }
+
+ /* Check for the "_raw__" suffix and leading underscores. */
+ if (slen == alen + 8 && s[0] == '_' && s[1] == '_'
+ && !strncmp (s + 2, format_types[i].name, alen)
+ && !strcmp (s + 2 + alen, "_raw__"))
+ {
+ *is_raw = true;
+ return static_cast<format_type>(i);
+ }
}
+
return format_type_error;
}
@@ -1110,7 +1168,7 @@ check_function_format (const_tree fntype, tree attrs, int nargs,
/* See if this function has any format attributes. */
for (a = attrs; a; a = TREE_CHAIN (a))
{
- if (is_attribute_p ("format", TREE_PURPOSE (a)))
+ if (is_attribute_p ("format", get_attribute_name (a)))
{
/* Yup; check it. */
function_format_info info;
@@ -1350,7 +1408,8 @@ avoid_dollar_number (const char *format)
format++;
if (*format == '$')
{
- warning (OPT_Wformat_, "$ operand number used after format without operand number");
+ warning (OPT_Wformat_,
+ "%<$%>operand number used after format without operand number");
return true;
}
return false;
@@ -1381,7 +1440,8 @@ finish_dollar_format_checking (format_check_results *res, int pointer_gap_ok)
found_pointer_gap = true;
else
warning_at (res->format_string_loc, OPT_Wformat_,
- "format argument %d unused before used argument %d in $-style format",
+ "format argument %d unused before used argument %d "
+ "in %<$%>-style format",
i + 1, dollar_max_arg_used);
}
}
@@ -1525,7 +1585,8 @@ check_format_info (function_format_info *info, tree params,
}
if (res.number_dollar_extra_args > 0 && res.number_non_literal == 0
&& res.number_other == 0)
- warning_at (loc, OPT_Wformat_extra_args, "unused arguments in $-style format");
+ warning_at (loc, OPT_Wformat_extra_args,
+ "unused arguments in %<$%>-style format");
if (res.number_empty > 0 && res.number_non_literal == 0
&& res.number_other == 0)
warning_at (loc, OPT_Wformat_zero_length, "zero-length %s format string",
@@ -2789,6 +2850,907 @@ check_argument_type (const format_char_info *fci,
return true;
}
+/* Describes "paired tokens" within the format string that are
+ expected to be balanced. */
+
+struct baltoks_t
+{
+ baltoks_t (): singlequote (), doublequote () { }
+
+ typedef auto_vec<const char *> balanced_tokens_t;
+ /* Vectors of pointers to opening brackets ('['), curly brackets ('{'),
+ quoting directives (like GCC "%<"), parentheses, and angle brackets
+ ('<'). Used to detect unbalanced tokens. */
+ balanced_tokens_t brackets;
+ balanced_tokens_t curly;
+ balanced_tokens_t quotdirs;
+ balanced_tokens_t parens;
+ balanced_tokens_t pointy;
+ /* Pointer to the last opening quote. */
+ const char *singlequote;
+ const char *doublequote;
+};
+
+/* Describes a keyword, operator, or other name. */
+
+struct token_t
+{
+ const char *name; /* Keyword/operator name. */
+ unsigned char len; /* Its length. */
+ const char *alt; /* Alternate spelling. */
+};
+
+/* Helper for initializing global token_t arrays below. */
+#define NAME(name) { name, sizeof name - 1, NULL }
+
+/* C/C++ operators that are expected to be quoted within the format
+ string. */
+
+static const token_t c_opers[] =
+ {
+ NAME ("!="), NAME ("%="), NAME ("&&"), NAME ("&="), NAME ("*="),
+ NAME ("++"), NAME ("+="), NAME ("--"), NAME ("-="), NAME ("->"),
+ NAME ("/="), NAME ("<<"), NAME ("<<="), NAME ("<="), NAME ("=="),
+ NAME (">="), NAME (">>="), NAME (">>"), NAME ("?:"), NAME ("^="),
+ NAME ("|="), NAME ("||")
+ };
+
+static const token_t cxx_opers[] =
+ {
+ NAME ("->*"), NAME (".*"), NAME ("::"), NAME ("<=>")
+ };
+
+/* Common C/C++ keywords that are expected to be quoted within the format
+ string. Keywords like auto, inline, or volatile are exccluded because
+ they are sometimes used in common terms like /auto variables/, /inline
+ function/, or /volatile access/ where they should not be quoted. */
+
+static const token_t c_keywords[] =
+ {
+#undef NAME
+#define NAME(name, alt) { name, sizeof name - 1, alt }
+
+ NAME ("alignas", NULL),
+ NAME ("alignof", NULL),
+ NAME ("asm", NULL),
+ NAME ("bool", NULL),
+ NAME ("char", NULL),
+ NAME ("const %", NULL),
+ NAME ("const-qualified", "%<const%>-qualified"),
+ NAME ("float", NULL),
+ NAME ("ifunc", NULL),
+ NAME ("int", NULL),
+ NAME ("long double", NULL),
+ NAME ("long int", NULL),
+ NAME ("long long", NULL),
+ NAME ("malloc", NULL),
+ NAME ("noclone", NULL),
+ NAME ("noinline", NULL),
+ NAME ("nonnull", NULL),
+ NAME ("noreturn", NULL),
+ NAME ("nothrow", NULL),
+ NAME ("offsetof", NULL),
+ NAME ("readonly", "read-only"),
+ NAME ("readwrite", "read-write"),
+ NAME ("restrict %", NULL),
+ NAME ("restrict-qualified", "%<restrict%>-qualified"),
+ NAME ("short int", NULL),
+ NAME ("signed char", NULL),
+ NAME ("signed int", NULL),
+ NAME ("signed long", NULL),
+ NAME ("signed short", NULL),
+ NAME ("sizeof", NULL),
+ NAME ("typeof", NULL),
+ NAME ("unsigned char", NULL),
+ NAME ("unsigned int", NULL),
+ NAME ("unsigned long", NULL),
+ NAME ("unsigned short", NULL),
+ NAME ("volatile %", NULL),
+ NAME ("volatile-qualified", "%<volatile%>-qualified"),
+ NAME ("weakref", NULL),
+ };
+
+static const token_t cxx_keywords[] =
+ {
+ /* C++ only keywords and operators. */
+ NAME ("catch", NULL),
+ NAME ("constexpr if", NULL),
+ NAME ("constexpr", NULL),
+ NAME ("consteval", NULL),
+ NAME ("decltype", NULL),
+ NAME ("nullptr", NULL),
+ NAME ("operator delete", NULL),
+ NAME ("operator new", NULL),
+ NAME ("typeid", NULL),
+ NAME ("typeinfo", NULL)
+ };
+
+/* Blacklisted words such as misspellings that should be avoided in favor
+ of the specified alternatives. */
+static const struct
+{
+ const char *name; /* Bad word. */
+ unsigned char len; /* Its length. */
+ const char *alt; /* Preferred alternative. */
+} badwords[] =
+ {
+ NAME ("arg", "argument"),
+ NAME ("bitfield", "bit-field"),
+ NAME ("builtin function", "built-in function"),
+ NAME ("can not", "cannot"),
+ NAME ("commandline option", "command-line option"),
+ NAME ("commandline", "command line"),
+ NAME ("command line option", "command-line option"),
+ NAME ("decl", "declaration"),
+ NAME ("enumeral", "enumerated"),
+ NAME ("floating point", "floating-point"),
+ NAME ("non-zero", "nonzero"),
+ NAME ("reg", "register"),
+ NAME ("stmt", "statement"),
+ };
+
+/* Common contractions that should be avoided in favor of the specified
+ alternatives. */
+
+static const struct
+{
+ const char *name; /* Contraction. */
+ unsigned char len; /* Its length. */
+ const char *alt; /* Preferred alternative. */
+} contrs[] =
+ {
+ NAME ("can't", "cannot"),
+ NAME ("didn't", "did not"),
+ /* These are commonly abused. Avoid diagnosing them for now.
+ NAME ("isn't", "is not"),
+ NAME ("don't", "is not"),
+ */
+ NAME ("mustn't", "must not"),
+ NAME ("needn't", "need not"),
+ NAME ("should't", "should not"),
+ NAME ("that's", "that is"),
+ NAME ("there's", "there is"),
+ NAME ("they're", "they are"),
+ NAME ("what's", "what is"),
+ NAME ("won't", "will not")
+ };
+
+/* Check for unquoted TOKENS. FORMAT_STRING_LOC is the location of
+ the format string, FORMAT_STRING_CST the format string itself (as
+ a tree), ORIG_FORMAT_CHARS and FORMAT_CHARS are pointers to
+ the beginning of the format string and the character currently
+ being processed, and BALTOKS describes paired "tokens" within
+ the format string that are expected to be balanced.
+ Returns a pointer to the last processed character or null when
+ nothing was done. */
+
+static const char*
+check_tokens (const token_t *tokens, unsigned ntoks,
+ location_t format_string_loc, tree format_string_cst,
+ const char *orig_format_chars, const char *format_chars,
+ baltoks_t &baltoks)
+{
+ /* For brevity. */
+ const int opt = OPT_Wformat_diag;
+ /* Zero-based starting position of a problem sequence. */
+ int fmtchrpos = format_chars - orig_format_chars;
+
+ /* For identifier-like "words," set to the word length. */
+ unsigned wlen = 0;
+ /* Set for an operator, clear for an identifier/word. */
+ bool is_oper = false;
+ bool underscore = false;
+
+ if (format_chars[0] == '_' || ISALPHA (format_chars[0]))
+ {
+ while (format_chars[wlen] == '_' || ISALNUM (format_chars[wlen]))
+ {
+ underscore |= format_chars[wlen] == '_';
+ ++wlen;
+ }
+ }
+ else
+ is_oper = true;
+
+ for (unsigned i = 0; i != ntoks; ++i)
+ {
+ unsigned toklen = tokens[i].len;
+
+ if (toklen < wlen
+ || strncmp (format_chars, tokens[i].name, toklen))
+ continue;
+
+ if (toklen == 2
+ && format_chars - orig_format_chars > 0
+ && (TOUPPER (format_chars[-1]) == 'C'
+ || TOUPPER (format_chars[-1]) == 'G'))
+ return format_chars + toklen - 1; /* Reference to C++ or G++. */
+
+ if (ISPUNCT (format_chars[toklen - 1]))
+ {
+ if (format_chars[toklen - 1] == format_chars[toklen])
+ return NULL; /* Operator followed by another punctuator. */
+ }
+ else if (ISALNUM (format_chars[toklen]))
+ return NULL; /* Keyword prefix for a longer word. */
+
+ if (toklen == 2
+ && format_chars[0] == '-'
+ && format_chars[1] == '-'
+ && ISALNUM (format_chars[2]))
+ return NULL; /* Probably option like --help. */
+
+ /* Allow this ugly warning for the time being. */
+ if (toklen == 2
+ && format_chars - orig_format_chars > 6
+ && !strncmp (format_chars - 7, " count >= width of ", 19))
+ return format_chars + 10;
+
+ /* The token is a type if it ends in an alphabetic character. */
+ bool is_type = (ISALPHA (tokens[i].name[toklen - 1])
+ && strchr (tokens[i].name, ' '));
+
+ /* Backtrack to the last alphabetic character (for tokens whose
+ names end in '%'). */
+ if (!is_oper)
+ while (!ISALPHA (tokens[i].name[toklen - 1]))
+ --toklen;
+
+ if (format_warning_substr (format_string_loc, format_string_cst,
+ fmtchrpos, fmtchrpos + toklen, opt,
+ (is_type
+ ? G_("unquoted type name %<%.*s%> in format")
+ : (is_oper
+ ? G_("unquoted operator %<%.*s%> in format")
+ : G_("unquoted keyword %<%.*s%> in format"))),
+ toklen, format_chars)
+ && tokens[i].alt)
+ inform (format_string_loc, "use %qs instead", tokens[i].alt);
+
+ return format_chars + toklen - 1;
+ }
+
+ /* Diagnose unquoted __attribute__. Consider any parenthesized
+ argument to the attribute to avoid redundant warnings for
+ the double parentheses that might follow. */
+ if (!strncmp (format_chars, "__attribute", sizeof "__attribute" - 1))
+ {
+ unsigned nchars = sizeof "__attribute" - 1;
+ while ('_' == format_chars[nchars])
+ ++nchars;
+
+ for (int i = nchars; format_chars[i]; ++i)
+ if (' ' != format_chars[i])
+ {
+ nchars = i;
+ break;
+ }
+
+ if (format_chars[nchars] == '(')
+ {
+ baltoks.parens.safe_push (format_chars + nchars);
+
+ ++nchars;
+ bool close = false;
+ if (format_chars[nchars] == '(')
+ {
+ baltoks.parens.safe_push (format_chars + nchars);
+ close = true;
+ ++nchars;
+ }
+ for (int i = nchars; format_chars[i]; ++i)
+ if (')' == format_chars[i])
+ {
+ if (baltoks.parens.length () > 0)
+ baltoks.parens.pop ();
+ nchars = i + 1;
+ break;
+ }
+
+ if (close && format_chars[nchars] == ')')
+ {
+ if (baltoks.parens.length () > 0)
+ baltoks.parens.pop ();
+ ++nchars;
+ }
+ }
+
+ format_warning_substr (format_string_loc, format_string_cst,
+ fmtchrpos, fmtchrpos + nchars, opt,
+ "unquoted attribute in format");
+ return format_chars + nchars - 1;
+ }
+
+ /* Diagnose unquoted built-ins. */
+ if (format_chars[0] == '_'
+ && format_chars[1] == '_'
+ && (!strncmp (format_chars + 2, "atomic", sizeof "atomic" - 1)
+ || !strncmp (format_chars + 2, "builtin", sizeof "builtin" - 1)
+ || !strncmp (format_chars + 2, "sync", sizeof "sync" - 1)))
+ {
+ format_warning_substr (format_string_loc, format_string_cst,
+ fmtchrpos, fmtchrpos + wlen, opt,
+ "unquoted name of built-in function %<%.*s%> "
+ "in format",
+ wlen, format_chars);
+ return format_chars + wlen - 1;
+ }
+
+ /* Diagnose unquoted substrings of alphanumeric characters containing
+ underscores. They most likely refer to identifiers and should be
+ quoted. */
+ if (underscore)
+ format_warning_substr (format_string_loc, format_string_cst,
+ format_chars - orig_format_chars,
+ format_chars + wlen - orig_format_chars,
+ opt,
+ "unquoted identifier or keyword %<%.*s%> in format",
+ wlen, format_chars);
+ else
+ {
+ /* Diagnose some common missspellings. */
+ for (unsigned i = 0; i != sizeof badwords / sizeof *badwords; ++i)
+ {
+ unsigned badwlen = strspn (badwords[i].name, " -");
+ if (wlen >= badwlen
+ && (wlen <= badwords[i].len
+ || (wlen == badwords[i].len + 1U
+ && TOUPPER (format_chars[wlen - 1]) == 'S'))
+ && !strncasecmp (format_chars, badwords[i].name, badwords[i].len))
+ {
+ /* Handle singular as well as plural forms of all bad words
+ even though the latter don't necessarily make sense for
+ all of the former (like "can nots"). */
+ badwlen = badwords[i].len;
+ const char *plural = "";
+ if (TOUPPER (format_chars[badwlen]) == 'S')
+ {
+ ++badwlen;
+ plural = "s";
+ }
+
+ format_warning_substr (format_string_loc, format_string_cst,
+ fmtchrpos, fmtchrpos + badwords[i].len,
+ opt,
+ "misspelled term %<%.*s%> in format; "
+ "use %<%s%s%> instead",
+ badwlen, format_chars,
+ badwords[i].alt, plural);
+
+ return format_chars + badwords[i].len - 1;
+ }
+ }
+
+ /* Skip C++/G++. */
+ if (!strncasecmp (format_chars, "c++", 3)
+ || !strncasecmp (format_chars, "g++", 3))
+ return format_chars + 2;
+ }
+
+ return wlen ? format_chars + wlen - 1 : NULL;
+}
+
+/* Check plain text in a format string of a GCC diagnostic function
+ for common quoting, punctuation, and spelling mistakes, and issue
+ -Wformat-diag warnings if they are found. FORMAT_STRING_LOC is
+ the location of the format string, FORMAT_STRING_CST the format
+ string itself (as a tree), ORIG_FORMAT_CHARS and FORMAT_CHARS are
+ pointers to the beginning of the format string and the character
+ currently being processed, and BALTOKS describes paired "tokens"
+ within the format string that are expected to be balanced.
+ Returns a pointer to the last processed character. */
+
+static const char*
+check_plain (location_t format_string_loc, tree format_string_cst,
+ const char *orig_format_chars, const char *format_chars,
+ baltoks_t &baltoks)
+{
+ /* For brevity. */
+ const int opt = OPT_Wformat_diag;
+ /* Zero-based starting position of a problem sequence. */
+ int fmtchrpos = format_chars - orig_format_chars;
+
+ if (*format_chars == '%')
+ {
+ /* Diagnose %<%s%> and suggest using %qs instead. */
+ if (!strncmp (format_chars, "%<%s%>", 6))
+ format_warning_substr (format_string_loc, format_string_cst,
+ fmtchrpos, fmtchrpos + 6, opt,
+ "quoted %qs directive in format; "
+ "use %qs instead", "%s", "%qs");
+ else if (format_chars - orig_format_chars > 2
+ && !strncasecmp (format_chars - 3, "can%'t", 5)
+ && !ISALPHA (format_chars[1]))
+ format_warning_substr (format_string_loc,
+ format_string_cst,
+ fmtchrpos - 3, fmtchrpos + 3, opt,
+ "contraction %<%.*s%> in format; "
+ "use %qs instead",
+ 6, format_chars - 3, "cannot");
+
+ return format_chars;
+ }
+
+ if (baltoks.quotdirs.length ())
+ {
+ /* Skip over all plain text within a quoting directive until
+ the next directive. */
+ while (*format_chars && '%' != *format_chars)
+ ++format_chars;
+
+ return format_chars;
+ }
+
+ /* The length of the problem sequence. */
+ int nchars = 0;
+
+ /* Diagnose any whitespace characters other than <space> but only
+ leading, trailing, and two or more consecutive <space>s. Do
+ this before diagnosing control characters because whitespace
+ is a subset of controls. */
+ const char *other_than_space = NULL;
+ while (ISSPACE (format_chars[nchars]))
+ {
+ if (format_chars[nchars] != ' ' && !other_than_space)
+ other_than_space = format_chars + nchars;
+ ++nchars;
+ }
+
+ if (nchars)
+ {
+ /* This is the most common problem: go the extra mile to describe
+ the problem in as much helpful detail as possible. */
+ if (other_than_space)
+ {
+ format_warning_substr (format_string_loc, format_string_cst,
+ fmtchrpos, fmtchrpos + nchars, opt,
+ "unquoted whitespace character %qc in format",
+ *other_than_space);
+ return format_chars + nchars - 1;
+ }
+
+ if (fmtchrpos == 0)
+ /* Accept strings of leading spaces with no warning. */
+ return format_chars + nchars - 1;
+
+ if (!format_chars[nchars])
+ {
+ format_warning_substr (format_string_loc, format_string_cst,
+ fmtchrpos, fmtchrpos + nchars, opt,
+ "spurious trailing space in format");
+ return format_chars + nchars - 1;
+ }
+
+ if (nchars > 1)
+ {
+ if (nchars == 2
+ && orig_format_chars < format_chars
+ && format_chars[-1] == '.'
+ && format_chars[0] == ' '
+ && format_chars[1] == ' ')
+ {
+ /* A period followed by two spaces. */
+ if (ISUPPER (*orig_format_chars))
+ {
+ /* If the part before the period is a capitalized
+ sentence check to make sure that what follows
+ is also capitalized. */
+ if (ISLOWER (format_chars[2]))
+ format_warning_substr (format_string_loc, format_string_cst,
+ fmtchrpos, fmtchrpos + nchars, opt,
+ "inconsistent capitalization in "
+ "format");
+ }
+ }
+ else
+ format_warning_substr (format_string_loc, format_string_cst,
+ fmtchrpos, fmtchrpos + nchars, opt,
+ "unquoted sequence of %i consecutive "
+ "space characters in format", nchars);
+ return format_chars + nchars - 1;
+ }
+
+ format_chars += nchars;
+ nchars = 0;
+ }
+
+ fmtchrpos = format_chars - orig_format_chars;
+
+ /* Diagnose any unquoted control characters other than the terminating
+ NUL. */
+ while (format_chars[nchars] && ISCNTRL (format_chars[nchars]))
+ ++nchars;
+
+ if (nchars > 1)
+ {
+ format_warning_substr (format_string_loc, format_string_cst,
+ fmtchrpos, fmtchrpos + nchars, opt,
+ "unquoted control characters in format");
+ return format_chars + nchars - 1;
+ }
+ if (nchars)
+ {
+ format_warning_substr (format_string_loc, format_string_cst,
+ fmtchrpos, fmtchrpos + nchars, opt,
+ "unquoted control character %qc in format",
+ *format_chars);
+ return format_chars + nchars - 1;
+ }
+
+ if (ISPUNCT (format_chars[0]))
+ {
+ size_t nelts = sizeof c_opers / sizeof *c_opers;
+ if (const char *ret = check_tokens (c_opers, nelts,
+ format_string_loc, format_string_cst,
+ orig_format_chars, format_chars,
+ baltoks))
+ return ret;
+
+ nelts = c_dialect_cxx () ? sizeof cxx_opers / sizeof *cxx_opers : 0;
+ if (const char *ret = check_tokens (cxx_opers, nelts,
+ format_string_loc, format_string_cst,
+ orig_format_chars, format_chars,
+ baltoks))
+ return ret;
+ }
+
+ if (ISALPHA (format_chars[0]))
+ {
+ size_t nelts = sizeof c_keywords / sizeof *c_keywords;
+ if (const char *ret = check_tokens (c_keywords, nelts,
+ format_string_loc, format_string_cst,
+ orig_format_chars, format_chars,
+ baltoks))
+ return ret;
+
+ nelts = c_dialect_cxx () ? sizeof cxx_keywords / sizeof *cxx_keywords : 0;
+ if (const char *ret = check_tokens (cxx_keywords, nelts,
+ format_string_loc, format_string_cst,
+ orig_format_chars, format_chars,
+ baltoks))
+ return ret;
+ }
+
+ nchars = 0;
+
+ /* Diagnose unquoted options. */
+ if ((format_chars == orig_format_chars
+ || format_chars[-1] == ' ')
+ && format_chars[0] == '-'
+ && ((format_chars[1] == '-'
+ && ISALPHA (format_chars[2]))
+ || ISALPHA (format_chars[1])))
+ {
+ nchars = 1;
+ while (ISALNUM (format_chars[nchars])
+ || '_' == format_chars[nchars]
+ || '-' == format_chars[nchars]
+ || '+' == format_chars[nchars])
+ ++nchars;
+
+ format_warning_substr (format_string_loc, format_string_cst,
+ fmtchrpos, fmtchrpos + nchars, opt,
+ "unquoted option name %<%.*s%> in format",
+ nchars, format_chars);
+ return format_chars + nchars - 1;
+ }
+
+ /* Diagnose leading, trailing, and two or more consecutive punctuation
+ characters. */
+ const char *unbalanced = NULL;
+ while ('%' != format_chars[nchars]
+ && ISPUNCT (format_chars[nchars])
+ && !unbalanced)
+ {
+ switch (format_chars[nchars])
+ {
+ case '[':
+ baltoks.brackets.safe_push (format_chars + nchars);
+ break;
+ case '{':
+ baltoks.curly.safe_push (format_chars + nchars);
+ break;
+ case '(':
+ baltoks.parens.safe_push (format_chars + nchars);
+ break;
+ case '<':
+ baltoks.pointy.safe_push (format_chars + nchars);
+ break;
+
+ case ']':
+ if (baltoks.brackets.length () > 0)
+ baltoks.brackets.pop ();
+ else
+ unbalanced = format_chars + nchars;
+ break;
+ case '}':
+ if (baltoks.curly.length () > 0)
+ baltoks.curly.pop ();
+ else
+ unbalanced = format_chars + nchars;
+ break;
+ case ')':
+ if (baltoks.parens.length () > 0)
+ baltoks.parens.pop ();
+ else
+ unbalanced = format_chars + nchars;
+ break;
+ case '>':
+ if (baltoks.pointy.length () > 0)
+ baltoks.pointy.pop ();
+ else
+ unbalanced = format_chars + nchars;
+ break;
+ }
+
+ ++nchars;
+ }
+
+ if (unbalanced)
+ {
+ format_warning_substr (format_string_loc, format_string_cst,
+ fmtchrpos, fmtchrpos + nchars, opt,
+ "unbalanced punctuation character %qc in format",
+ *unbalanced);
+ return format_chars + nchars - 1;
+ }
+
+ if (nchars)
+ {
+ /* Consider any identifier that follows the pound ('#') sign
+ a preprocessing directive. */
+ if (nchars == 1
+ && format_chars[0] == '#'
+ && ISALPHA (format_chars[1]))
+ {
+ while (ISALNUM (format_chars[nchars])
+ || format_chars[nchars] == '_')
+ ++nchars;
+
+ format_warning_substr (format_string_loc, format_string_cst,
+ fmtchrpos, fmtchrpos + nchars, opt,
+ "unquoted preprocessing directive %<%.*s%> "
+ "in format", nchars, format_chars);
+ return format_chars + nchars - 1;
+ }
+
+ /* Diagnose a bare single quote. */
+ if (nchars == 1
+ && format_chars[0] == '\''
+ && format_chars - orig_format_chars
+ && ISALPHA (format_chars[-1])
+ && ISALPHA (format_chars[1]))
+ {
+ /* Diagnose a subset of contractions that are best avoided. */
+ for (unsigned i = 0; i != sizeof contrs / sizeof *contrs; ++i)
+ {
+ const char *apos = strchr (contrs[i].name, '\'');
+ gcc_assert (apos != NULL);
+ int off = apos - contrs[i].name;
+
+ if (format_chars - orig_format_chars >= off
+ && !strncmp (format_chars - off,
+ contrs[i].name, contrs[i].len))
+ {
+ format_warning_substr (format_string_loc,
+ format_string_cst,
+ fmtchrpos, fmtchrpos + nchars, opt,
+ "contraction %<%.*s%> in format; "
+ "use %qs instead",
+ contrs[i].len, contrs[i].name,
+ contrs[i].alt);
+ return format_chars + nchars - 1;
+ }
+ }
+
+ if (format_warning_substr (format_string_loc, format_string_cst,
+ fmtchrpos, fmtchrpos + nchars, opt,
+ "bare apostrophe %<'%> in format"))
+ inform (format_string_loc,
+ "if avoiding the apostrophe is not feasible, enclose "
+ "it in a pair of %qs and %qs directives instead",
+ "%<", "%>");
+ return format_chars + nchars - 1;
+ }
+
+ /* Diagnose a backtick (grave accent). */
+ if (nchars == 1
+ && format_chars[0] == '`')
+ {
+ if (format_warning_substr (format_string_loc, format_string_cst,
+ fmtchrpos, fmtchrpos + nchars, opt,
+ "grave accent %<`%> in format"))
+ inform (format_string_loc,
+ "use the apostrophe directive %qs instead", "%'");
+ return format_chars + nchars - 1;
+ }
+
+ /* Diagnose a punctuation character after a space. */
+ if (nchars == 1
+ && format_chars - orig_format_chars
+ && format_chars[-1] == ' '
+ && strspn (format_chars, "!?:;.,") == 1)
+ {
+ format_warning_substr (format_string_loc, format_string_cst,
+ fmtchrpos - 1, fmtchrpos, opt,
+ "space followed by punctuation character "
+ "%<%c%>", format_chars[0]);
+ return format_chars;
+ }
+
+ if (nchars == 1)
+ {
+ if (!strncmp (format_chars, "\"%s\"", 4))
+ {
+ if (format_warning_substr (format_string_loc, format_string_cst,
+ fmtchrpos, fmtchrpos + 4, opt,
+ "quoted %qs directive in format",
+ "%s"))
+ inform (format_string_loc, "if using %qs is not feasible, "
+ "use %qs instead", "%qs", "\"%-s\"");
+ }
+
+ if (format_chars[0] == '"')
+ {
+ baltoks.doublequote = baltoks.doublequote ? NULL : format_chars;
+ return format_chars + nchars - 1;
+ }
+ if (format_chars[0] == '\'')
+ {
+ baltoks.singlequote = baltoks.singlequote ? NULL : format_chars;
+ return format_chars + nchars - 1;
+ }
+ }
+
+ if (fmtchrpos == 0)
+ {
+ if (nchars == 1
+ && format_chars[0] == '(')
+ ; /* Text beginning in an open parenthesis. */
+ else if (nchars == 3
+ && !strncmp (format_chars, "...", 3)
+ && format_chars[3])
+ ; /* Text beginning in an ellipsis. */
+ else
+ {
+ format_warning_substr (format_string_loc, format_string_cst,
+ fmtchrpos, fmtchrpos + nchars, opt,
+ "spurious leading punctuation sequence "
+ "%<%.*s%> in format",
+ nchars, format_chars);
+ return format_chars + nchars - 1;
+ }
+ }
+ else if (!format_chars[nchars])
+ {
+ if (nchars == 1
+ && (format_chars[nchars - 1] == ':'
+ || format_chars[nchars - 1] == ')'))
+ ; /* Text ending in a colon or a closing parenthesis. */
+ else if (nchars == 1
+ && ((ISUPPER (*orig_format_chars)
+ && format_chars[nchars - 1] == '.')
+ || strspn (format_chars + nchars - 1, "?])") == 1))
+ ; /* Capitalized sentence terminated by a single period,
+ or text ending in a question mark, closing bracket,
+ or parenthesis. */
+ else if (nchars == 2
+ && format_chars[0] == '?'
+ && format_chars[1] == ')')
+ ; /* A question mark after a closing parenthetical note. */
+ else if (nchars == 2
+ && format_chars[0] == ')'
+ && (format_chars[1] == '?'
+ || format_chars[1] == ';'
+ || format_chars[1] == ':'
+ || (ISUPPER (*orig_format_chars)
+ && format_chars[1] == '.')))
+ ; /* Closing parenthetical note followed by a question mark,
+ semicolon, or colon at the end of the string, or by
+ a period at the end of a capitalized sentence. */
+ else if (nchars == 3
+ && format_chars - orig_format_chars > 0
+ && !strncmp (format_chars, "...", 3))
+ ; /* Text ending in the ellipsis. */
+ else
+ format_warning_substr (format_string_loc, format_string_cst,
+ fmtchrpos, fmtchrpos + nchars, opt,
+ "spurious trailing punctuation sequence "
+ "%<%.*s%> in format",
+ nchars, format_chars);
+
+ return format_chars + nchars - 1;
+ }
+ else if (nchars == 2
+ && format_chars[0] == ')'
+ && (format_chars[1] == ':'
+ || format_chars[1] == ';'
+ || format_chars[1] == ',')
+ && format_chars[2] == ' ')
+ ; /* Closing parenthetical note followed by a colon, semicolon
+ or a comma followed by a space in the middle of the string. */
+ else if (nchars > 1)
+ format_warning_substr (format_string_loc, format_string_cst,
+ fmtchrpos, fmtchrpos + nchars, opt,
+ "unquoted sequence of %i consecutive "
+ "punctuation characters %q.*s in format",
+ nchars, nchars, format_chars);
+ return format_chars + nchars - 1;
+ }
+
+ nchars = 0;
+
+ /* Finally, diagnose any unquoted non-graph, non-punctuation characters
+ other than the terminating NUL. */
+ while (format_chars[nchars]
+ && '%' != format_chars[nchars]
+ && !ISPUNCT (format_chars[nchars])
+ && !ISGRAPH (format_chars[nchars]))
+ ++nchars;
+
+ if (nchars > 1)
+ {
+ format_warning_substr (format_string_loc, format_string_cst,
+ fmtchrpos, fmtchrpos + nchars, opt,
+ "unquoted non-graph characters in format");
+ return format_chars + nchars - 1;
+ }
+ if (nchars)
+ {
+ format_warning_substr (format_string_loc, format_string_cst,
+ fmtchrpos, fmtchrpos + nchars, opt,
+ "unquoted non-graph character %qc in format",
+ *format_chars);
+ return format_chars + nchars - 1;
+ }
+
+ return format_chars;
+}
+
+/* Diagnose unbalanced tokens described by BALTOKS in format string
+ ORIG_FORMAT_CHARS and the corresponding FORMAT_STRING_CST. */
+
+static void
+maybe_diag_unbalanced_tokens (location_t format_string_loc,
+ const char *orig_format_chars,
+ tree format_string_cst,
+ baltoks_t &baltoks)
+{
+ const char *unbalanced = NULL;
+
+ if (baltoks.brackets.length ())
+ unbalanced = baltoks.brackets.pop ();
+ else if (baltoks.curly.length ())
+ unbalanced = baltoks.curly.pop ();
+ else if (baltoks.parens.length ())
+ unbalanced = baltoks.parens.pop ();
+ else if (baltoks.pointy.length ())
+ unbalanced = baltoks.pointy.pop ();
+
+ if (unbalanced)
+ format_warning_at_char (format_string_loc, format_string_cst,
+ unbalanced - orig_format_chars + 1,
+ OPT_Wformat_diag,
+ "unbalanced punctuation character %<%c%> in format",
+ *unbalanced);
+
+ if (baltoks.quotdirs.length ())
+ format_warning_at_char (format_string_loc, format_string_cst,
+ baltoks.quotdirs.pop () - orig_format_chars,
+ OPT_Wformat_,
+ "unterminated quoting directive");
+
+ const char *quote
+ = baltoks.singlequote ? baltoks.singlequote : baltoks.doublequote;
+
+ if (quote)
+ format_warning_at_char (format_string_loc, format_string_cst,
+ quote - orig_format_chars + 1,
+ OPT_Wformat_diag,
+ "unterminated quote character %<%c%> in format",
+ *quote);
+}
+
/* Do the main part of checking a call to a format function. FORMAT_CHARS
is the NUL-terminated format string (which at this point may contain
internal NUL characters); FORMAT_LENGTH is its length (excluding the
@@ -2816,8 +3778,10 @@ check_format_info_main (format_check_results *res,
and it didn't use $; 1 if $ formats are in use. */
int has_operand_number = -1;
- /* Vector of pointers to opening quoting directives (like GCC "%<"). */
- auto_vec<const char*> quotdirs;
+ /* Vectors of pointers to opening quoting directives (like GCC "%<"),
+ opening braces, brackets, and parentheses. Used to detect unbalanced
+ tokens. */
+ baltoks_t baltoks;
/* Pointers to the most recent color directives (like GCC's "%r or %R").
A starting color directive much be terminated before the end of
@@ -2828,10 +3792,26 @@ check_format_info_main (format_check_results *res,
init_dollar_format_checking (info->first_arg_num, first_fillin_param);
+ /* In GCC diagnostic functions check plain directives (substrings within
+ the format string that don't start with %) for quoting and punctuations
+ problems. */
+ bool ck_plain = (!info->is_raw
+ && (info->format_type == gcc_diag_format_type
+ || info->format_type == gcc_tdiag_format_type
+ || info->format_type == gcc_cdiag_format_type
+ || info->format_type == gcc_cxxdiag_format_type));
+
while (*format_chars != 0)
{
- if (*format_chars++ != '%')
+ if (ck_plain)
+ format_chars = check_plain (format_string_loc,
+ format_string_cst,
+ orig_format_chars, format_chars,
+ baltoks);
+
+ if (*format_chars == 0 || *format_chars++ != '%')
continue;
+
if (*format_chars == 0)
{
format_warning_at_char (format_string_loc, format_string_cst,
@@ -2846,6 +3826,8 @@ check_format_info_main (format_check_results *res,
continue;
}
+ /* ARGUMENT_PARSER ctor takes FORMAT_CHARS by reference and calls
+ to ARG_PARSER members may modify the variable. */
flag_chars_t flag_chars;
argument_parser arg_parser (info, format_chars, format_string_cst,
orig_format_chars, format_string_loc,
@@ -2908,7 +3890,7 @@ check_format_info_main (format_check_results *res,
flag_chars.validate (fki, fci, flag_specs, format_chars,
format_string_cst,
format_string_loc, orig_format_chars, format_char,
- quotdirs.length () > 0);
+ baltoks.quotdirs.length () > 0);
const int alloc_flag = flag_chars.get_alloc_flag (fki);
const bool suppressed = flag_chars.assignment_suppression_p (fki);
@@ -2920,17 +3902,17 @@ check_format_info_main (format_check_results *res,
if (quot_begin_p && !quot_end_p)
{
- if (quotdirs.length ())
+ if (baltoks.quotdirs.length ())
format_warning_at_char (format_string_loc, format_string_cst,
format_chars - orig_format_chars,
OPT_Wformat_,
"nested quoting directive");
- quotdirs.safe_push (format_chars);
+ baltoks.quotdirs.safe_push (format_chars);
}
else if (!quot_begin_p && quot_end_p)
{
- if (quotdirs.length ())
- quotdirs.pop ();
+ if (baltoks.quotdirs.length ())
+ baltoks.quotdirs.pop ();
else
format_warning_at_char (format_string_loc, format_string_cst,
format_chars - orig_format_chars,
@@ -2962,7 +3944,7 @@ check_format_info_main (format_check_results *res,
/* Diagnose directives that shouldn't appear in a quoted sequence.
(They are denoted by a double quote in FLAGS2.) */
- if (quotdirs.length ())
+ if (baltoks.quotdirs.length ())
{
if (strchr (fci->flags2, '"'))
format_warning_at_char (format_string_loc, format_string_cst,
@@ -3018,10 +4000,9 @@ check_format_info_main (format_check_results *res,
if (has_operand_number > 0)
finish_dollar_format_checking (res, fki->flags & (int) FMT_FLAG_DOLLAR_GAP_POINTER_OK);
- if (quotdirs.length ())
- format_warning_at_char (format_string_loc, format_string_cst,
- quotdirs.pop () - orig_format_chars,
- OPT_Wformat_, "unterminated quoting directive");
+ maybe_diag_unbalanced_tokens (format_string_loc, orig_format_chars,
+ format_string_cst, baltoks);
+
if (color_begin && !color_end)
format_warning_at_char (format_string_loc, format_string_cst,
color_begin - orig_format_chars,
@@ -4199,7 +5180,7 @@ handle_format_attribute (tree *node, tree atname, tree args,
if (arg_num != info.first_arg_num)
{
if (!(flags & (int) ATTR_FLAG_BUILT_IN))
- error ("args to be formatted is not %<...%>");
+ error ("argument to be formatted is not %<...%>");
*no_add_attrs = true;
return NULL_TREE;
}
diff --git a/gcc/c-family/c-lex.c b/gcc/c-family/c-lex.c
index 0a368a3..851fd70 100644
--- a/gcc/c-family/c-lex.c
+++ b/gcc/c-family/c-lex.c
@@ -258,7 +258,7 @@ cb_def_pragma (cpp_reader *pfile, location_t loc)
name = cpp_token_as_text (pfile, s);
}
- warning_at (fe_loc, OPT_Wunknown_pragmas, "ignoring #pragma %s %s",
+ warning_at (fe_loc, OPT_Wunknown_pragmas, "ignoring %<#pragma %s %s%>",
space, name);
}
}
@@ -818,7 +818,7 @@ interpret_float (const cpp_token *token, unsigned int flags,
if (((flags & CPP_N_HEX) == 0) && ((flags & CPP_N_IMAGINARY) == 0))
{
warning (OPT_Wunsuffixed_float_constants,
- "unsuffixed float constant");
+ "unsuffixed floating constant");
if (float_const_decimal64_p ())
flags |= CPP_N_DFLOAT;
}
diff --git a/gcc/c-family/c-omp.c b/gcc/c-family/c-omp.c
index 16e7198..583305e 100644
--- a/gcc/c-family/c-omp.c
+++ b/gcc/c-family/c-omp.c
@@ -305,7 +305,7 @@ c_finish_omp_atomic (location_t loc, enum tree_code code,
if (TREE_CODE (x) == COMPOUND_EXPR)
{
pre = TREE_OPERAND (x, 0);
- gcc_assert (TREE_CODE (pre) == SAVE_EXPR);
+ gcc_assert (TREE_CODE (pre) == SAVE_EXPR || tree_invariant_p (pre));
x = TREE_OPERAND (x, 1);
}
gcc_assert (TREE_CODE (x) == MODIFY_EXPR);
@@ -974,7 +974,7 @@ c_finish_omp_for (location_t locus, enum tree_code code, tree declv,
{
error_at (elocus,
"increment is not constant 1 or "
- "-1 for != condition");
+ "-1 for %<!=%> condition");
fail = true;
}
}
@@ -992,7 +992,7 @@ c_finish_omp_for (location_t locus, enum tree_code code, tree declv,
{
error_at (elocus,
"increment is not constant 1 or -1 for"
- " != condition");
+ " %<!=%> condition");
fail = true;
}
}
@@ -1634,7 +1634,8 @@ c_omp_split_clauses (location_t loc, enum tree_code code,
break;
/* Reduction is allowed on simd, for, parallel, sections, taskloop
and teams. Duplicate it on all of them, but omit on for or
- sections if parallel is present. If taskloop is combined with
+ sections if parallel is present (unless inscan, in that case
+ omit on parallel). If taskloop is combined with
parallel, omit it on parallel. */
case OMP_CLAUSE_REDUCTION:
if (OMP_CLAUSE_REDUCTION_TASK (clauses))
@@ -1659,6 +1660,18 @@ c_omp_split_clauses (location_t loc, enum tree_code code,
OMP_CLAUSE_REDUCTION_TASK (clauses) = 0;
}
}
+ if (OMP_CLAUSE_REDUCTION_INSCAN (clauses)
+ && ((mask & ((OMP_CLAUSE_MASK_1
+ << PRAGMA_OMP_CLAUSE_DIST_SCHEDULE)
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MAP)))
+ != 0))
+ {
+ error_at (OMP_CLAUSE_LOCATION (clauses),
+ "%<inscan%> %<reduction%> clause on construct other "
+ "than %<for%>, %<simd%>, %<for simd%>, "
+ "%<parallel for%>, %<parallel for simd%>");
+ OMP_CLAUSE_REDUCTION_INSCAN (clauses) = 0;
+ }
if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SCHEDULE)) != 0)
{
if (code == OMP_SIMD)
@@ -1672,6 +1685,8 @@ c_omp_split_clauses (location_t loc, enum tree_code code,
= OMP_CLAUSE_REDUCTION_PLACEHOLDER (clauses);
OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (c)
= OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (clauses);
+ OMP_CLAUSE_REDUCTION_INSCAN (c)
+ = OMP_CLAUSE_REDUCTION_INSCAN (clauses);
OMP_CLAUSE_CHAIN (c) = cclauses[C_OMP_CLAUSE_SPLIT_SIMD];
cclauses[C_OMP_CLAUSE_SPLIT_SIMD] = c;
}
@@ -1687,12 +1702,15 @@ c_omp_split_clauses (location_t loc, enum tree_code code,
= OMP_CLAUSE_REDUCTION_PLACEHOLDER (clauses);
OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (c)
= OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (clauses);
+ OMP_CLAUSE_REDUCTION_INSCAN (c)
+ = OMP_CLAUSE_REDUCTION_INSCAN (clauses);
OMP_CLAUSE_CHAIN (c) = cclauses[C_OMP_CLAUSE_SPLIT_TEAMS];
cclauses[C_OMP_CLAUSE_SPLIT_TEAMS] = c;
s = C_OMP_CLAUSE_SPLIT_PARALLEL;
}
else if ((mask & (OMP_CLAUSE_MASK_1
- << PRAGMA_OMP_CLAUSE_NUM_THREADS)) != 0)
+ << PRAGMA_OMP_CLAUSE_NUM_THREADS)) != 0
+ && !OMP_CLAUSE_REDUCTION_INSCAN (clauses))
s = C_OMP_CLAUSE_SPLIT_PARALLEL;
else
s = C_OMP_CLAUSE_SPLIT_FOR;
@@ -1717,6 +1735,8 @@ c_omp_split_clauses (location_t loc, enum tree_code code,
= OMP_CLAUSE_REDUCTION_PLACEHOLDER (clauses);
OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (c)
= OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (clauses);
+ OMP_CLAUSE_REDUCTION_INSCAN (c)
+ = OMP_CLAUSE_REDUCTION_INSCAN (clauses);
OMP_CLAUSE_CHAIN (c) = cclauses[C_OMP_CLAUSE_SPLIT_TASKLOOP];
cclauses[C_OMP_CLAUSE_SPLIT_TASKLOOP] = c;
}
diff --git a/gcc/c-family/c-opts.c b/gcc/c-family/c-opts.c
index bc7ea17..188da43 100644
--- a/gcc/c-family/c-opts.c
+++ b/gcc/c-family/c-opts.c
@@ -460,6 +460,10 @@ c_common_handle_option (size_t scode, const char *arg, HOST_WIDE_INT value,
cpp_opts->extended_identifiers = value;
break;
+ case OPT_fmax_include_depth_:
+ cpp_opts->max_include_depth = value;
+ break;
+
case OPT_foperator_names:
cpp_opts->operator_names = value;
break;
@@ -1022,8 +1026,8 @@ c_common_post_options (const char **pfilename)
warn_return_type = 1;
if (num_in_fnames > 1)
- error ("too many filenames given. Type %s --help for usage",
- progname);
+ error ("too many filenames given; type %<%s %s%> for usage",
+ progname, "--help");
if (flag_preprocess_only)
{
@@ -1057,7 +1061,7 @@ c_common_post_options (const char **pfilename)
debug formats we warn here and refuse to load any PCH files. */
if (write_symbols != NO_DEBUG && write_symbols != DWARF2_DEBUG)
warning (OPT_Wdeprecated,
- "the \"%s\" debug format cannot be used with "
+ "the %qs debug format cannot be used with "
"pre-compiled headers", debug_type_names[write_symbols]);
}
else if (write_symbols != NO_DEBUG && write_symbols != DWARF2_DEBUG)
diff --git a/gcc/c-family/c-pch.c b/gcc/c-family/c-pch.c
index 316fb84f..2024ae2 100644
--- a/gcc/c-family/c-pch.c
+++ b/gcc/c-family/c-pch.c
@@ -103,7 +103,7 @@ pch_init (void)
f = fopen (pch_file, "w+b");
if (f == NULL)
- fatal_error (input_location, "can%'t create precompiled header %s: %m",
+ fatal_error (input_location, "cannot create precompiled header %s: %m",
pch_file);
pch_outfile = f;
@@ -124,7 +124,7 @@ pch_init (void)
|| fwrite (executable_checksum, 16, 1, f) != 1
|| fwrite (&v, sizeof (v), 1, f) != 1
|| fwrite (target_validity, v.target_data_length, 1, f) != 1)
- fatal_error (input_location, "can%'t write to %s: %m", pch_file);
+ fatal_error (input_location, "cannot write to %s: %m", pch_file);
/* Let the debugging format deal with the PCHness. */
(*debug_hooks->handle_pch) (0);
@@ -182,7 +182,7 @@ c_common_write_pch (void)
if (fseek (pch_outfile, 0, SEEK_SET) != 0
|| fwrite (get_ident (), IDENT_LENGTH, 1, pch_outfile) != 1)
- fatal_error (input_location, "can%'t write %s: %m", pch_file);
+ fatal_error (input_location, "cannot write %s: %m", pch_file);
fclose (pch_outfile);
@@ -208,7 +208,7 @@ c_common_valid_pch (cpp_reader *pfile, const char *name, int fd)
sizeread = read (fd, ident, IDENT_LENGTH + 16);
if (sizeread == -1)
- fatal_error (input_location, "can%'t read %s: %m", name);
+ fatal_error (input_location, "cannot read %s: %m", name);
else if (sizeread != IDENT_LENGTH + 16)
{
if (cpp_get_options (pfile)->warn_invalid_pch)
@@ -249,7 +249,7 @@ c_common_valid_pch (cpp_reader *pfile, const char *name, int fd)
executable, so it ought to be long enough that we can read a
c_pch_validity structure. */
if (read (fd, &v, sizeof (v)) != sizeof (v))
- fatal_error (input_location, "can%'t read %s: %m", name);
+ fatal_error (input_location, "cannot read %s: %m", name);
/* The allowable debug info combinations are that either the PCH file
was built with the same as is being used now, or the PCH file was
@@ -300,7 +300,7 @@ c_common_valid_pch (cpp_reader *pfile, const char *name, int fd)
if ((size_t) read (fd, this_file_data, v.target_data_length)
!= v.target_data_length)
- fatal_error (input_location, "can%'t read %s: %m", name);
+ fatal_error (input_location, "cannot read %s: %m", name);
msg = targetm.pch_valid_p (this_file_data, v.target_data_length);
free (this_file_data);
if (msg != NULL)
@@ -406,9 +406,9 @@ c_common_pch_pragma (cpp_reader *pfile, const char *name)
if (!cpp_get_options (pfile)->preprocessed)
{
- error ("pch_preprocess pragma should only be used "
+ error ("%<pch_preprocess%> pragma should only be used "
"with %<-fpreprocessed%>");
- inform (input_location, "use #include instead");
+ inform (input_location, "use %<#include%> instead");
return;
}
diff --git a/gcc/c-family/c-pragma.c b/gcc/c-family/c-pragma.c
index 6b8ada5..9af713d 100644
--- a/gcc/c-family/c-pragma.c
+++ b/gcc/c-family/c-pragma.c
@@ -91,7 +91,8 @@ pop_alignment (tree id)
align_stack * entry;
if (alignment_stack == NULL)
- GCC_BAD ("#pragma pack (pop) encountered without matching #pragma pack (push)");
+ GCC_BAD ("%<#pragma pack (pop)%> encountered without matching "
+ "%<#pragma pack (push)%>");
/* If we got an identifier, strip away everything above the target
entry so that the next step will restore the state just below it. */
@@ -104,8 +105,9 @@ pop_alignment (tree id)
break;
}
if (entry == NULL)
- warning (OPT_Wpragmas, "\
-#pragma pack(pop, %E) encountered without matching #pragma pack(push, %E)"
+ warning (OPT_Wpragmas,
+ "%<#pragma pack(pop, %E)%> encountered without matching "
+ "%<#pragma pack(push, %E)%>"
, id, id);
}
@@ -197,7 +199,7 @@ handle_pragma_pack (cpp_reader * ARG_UNUSED (dummy))
warning (OPT_Wpragmas, "junk at end of %<#pragma pack%>");
if (flag_pack_struct)
- GCC_BAD ("#pragma pack has no effect with %<-fpack-struct%> - ignored");
+ GCC_BAD ("%<#pragma pack%> has no effect with %<-fpack-struct%> - ignored");
if (action != pop)
switch (align)
@@ -257,7 +259,7 @@ apply_pragma_weak (tree decl, tree value)
&& !DECL_WEAK (decl) /* Don't complain about a redundant #pragma. */
&& DECL_ASSEMBLER_NAME_SET_P (decl)
&& TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl)))
- warning (OPT_Wpragmas, "applying #pragma weak %q+D after first use "
+ warning (OPT_Wpragmas, "applying %<#pragma weak %+D%> after first use "
"results in unspecified behavior", decl);
declare_weak (decl);
@@ -354,12 +356,12 @@ handle_pragma_weak (cpp_reader * ARG_UNUSED (dummy))
value = 0;
if (pragma_lex (&name) != CPP_NAME)
- GCC_BAD ("malformed #pragma weak, ignored");
+ GCC_BAD ("malformed %<#pragma weak%>, ignored");
t = pragma_lex (&x);
if (t == CPP_EQ)
{
if (pragma_lex (&value) != CPP_NAME)
- GCC_BAD ("malformed #pragma weak, ignored");
+ GCC_BAD ("malformed %<#pragma weak%>, ignored");
t = pragma_lex (&x);
}
if (t != CPP_EOF)
@@ -417,7 +419,7 @@ handle_pragma_scalar_storage_order (cpp_reader *ARG_UNUSED(dummy))
if (BYTES_BIG_ENDIAN != WORDS_BIG_ENDIAN)
{
- error ("scalar_storage_order is not supported because endianness "
+ error ("%<scalar_storage_order%> is not supported because endianness "
"is not uniform");
return;
}
@@ -495,9 +497,9 @@ handle_pragma_redefine_extname (cpp_reader * ARG_UNUSED (dummy))
bool found;
if (pragma_lex (&oldname) != CPP_NAME)
- GCC_BAD ("malformed #pragma redefine_extname, ignored");
+ GCC_BAD ("malformed %<#pragma redefine_extname%>, ignored");
if (pragma_lex (&newname) != CPP_NAME)
- GCC_BAD ("malformed #pragma redefine_extname, ignored");
+ GCC_BAD ("malformed %<#pragma redefine_extname%>, ignored");
t = pragma_lex (&x);
if (t != CPP_EOF)
warning (OPT_Wpragmas, "junk at end of %<#pragma redefine_extname%>");
@@ -528,8 +530,8 @@ handle_pragma_redefine_extname (cpp_reader * ARG_UNUSED (dummy))
name = targetm.strip_name_encoding (name);
if (!id_equal (newname, name))
- warning (OPT_Wpragmas, "#pragma redefine_extname ignored due to "
- "conflict with previous rename");
+ warning (OPT_Wpragmas, "%<#pragma redefine_extname%> "
+ "ignored due to conflict with previous rename");
}
else
symtab->change_decl_assembler_name (decl, newname);
@@ -556,8 +558,8 @@ add_to_renaming_pragma_list (tree oldname, tree newname)
if (oldname == p->oldname)
{
if (p->newname != newname)
- warning (OPT_Wpragmas, "#pragma redefine_extname ignored due to "
- "conflict with previous #pragma redefine_extname");
+ warning (OPT_Wpragmas, "%<#pragma redefine_extname%> ignored due to "
+ "conflict with previous %<#pragma redefine_extname%>");
return;
}
@@ -592,7 +594,7 @@ maybe_apply_renaming_pragma (tree decl, tree asmname)
oldname = targetm.strip_name_encoding (oldname);
if (asmname && strcmp (TREE_STRING_POINTER (asmname), oldname))
- warning (OPT_Wpragmas, "asm declaration ignored due to "
+ warning (OPT_Wpragmas, "%<asm%> declaration ignored due to "
"conflict with previous rename");
/* Take any pending redefine_extname off the list. */
@@ -601,8 +603,8 @@ maybe_apply_renaming_pragma (tree decl, tree asmname)
{
/* Only warn if there is a conflict. */
if (!id_equal (p->newname, oldname))
- warning (OPT_Wpragmas, "#pragma redefine_extname ignored due to "
- "conflict with previous rename");
+ warning (OPT_Wpragmas, "%<#pragma redefine_extname%> ignored "
+ "due to conflict with previous rename");
pending_redefine_extname->unordered_remove (ix);
break;
@@ -623,8 +625,8 @@ maybe_apply_renaming_pragma (tree decl, tree asmname)
{
if (strcmp (TREE_STRING_POINTER (asmname),
IDENTIFIER_POINTER (newname)) != 0)
- warning (OPT_Wpragmas, "#pragma redefine_extname ignored due to "
- "conflict with __asm__ declaration");
+ warning (OPT_Wpragmas, "%<#pragma redefine_extname%> ignored "
+ "due to conflict with %<asm%> declaration");
return asmname;
}
@@ -684,7 +686,8 @@ push_visibility (const char *str, int kind)
else if (!strcmp (str, "protected"))
default_visibility = VISIBILITY_PROTECTED;
else
- GCC_BAD ("#pragma GCC visibility push() must specify default, internal, hidden or protected");
+ GCC_BAD ("%<#pragma GCC visibility push()%> must specify %<default%>, "
+ "%<internal%>, %<hidden%> or %<protected%>");
visibility_options.inpragma = 1;
}
@@ -726,7 +729,8 @@ handle_pragma_visibility (cpp_reader *dummy ATTRIBUTE_UNUSED)
action = pop;
}
if (bad == action)
- GCC_BAD ("#pragma GCC visibility must be followed by push or pop");
+ GCC_BAD ("%<#pragma GCC visibility%> must be followed by %<push%> "
+ "or %<pop%>");
else
{
if (pop == action)
@@ -740,7 +744,7 @@ handle_pragma_visibility (cpp_reader *dummy ATTRIBUTE_UNUSED)
GCC_BAD ("missing %<(%> after %<#pragma GCC visibility push%> - ignored");
token = pragma_lex (&x);
if (token != CPP_NAME)
- GCC_BAD ("malformed #pragma GCC visibility push");
+ GCC_BAD ("malformed %<#pragma GCC visibility push%>");
else
push_visibility (IDENTIFIER_POINTER (x), 0);
if (pragma_lex (&x) != CPP_CLOSE_PAREN)
@@ -860,7 +864,7 @@ handle_pragma_target(cpp_reader *ARG_UNUSED(dummy))
if (cfun)
{
- error ("#pragma GCC option is not allowed inside functions");
+ error ("%<#pragma GCC option%> is not allowed inside functions");
return;
}
@@ -906,7 +910,7 @@ handle_pragma_target(cpp_reader *ARG_UNUSED(dummy))
if (token != CPP_EOF)
{
- error ("#pragma GCC target string... is badly formed");
+ error ("%<#pragma GCC target%> string is badly formed");
return;
}
@@ -929,7 +933,7 @@ handle_pragma_optimize (cpp_reader *ARG_UNUSED(dummy))
if (cfun)
{
- error ("#pragma GCC optimize is not allowed inside functions");
+ error ("%<#pragma GCC optimize%> is not allowed inside functions");
return;
}
@@ -974,7 +978,7 @@ handle_pragma_optimize (cpp_reader *ARG_UNUSED(dummy))
if (token != CPP_EOF)
{
- error ("#pragma GCC optimize string... is badly formed");
+ error ("%<#pragma GCC optimize%> string is badly formed");
return;
}
@@ -1147,7 +1151,8 @@ handle_pragma_message (cpp_reader *ARG_UNUSED(dummy))
warning (OPT_Wpragmas, "junk at end of %<#pragma message%>");
if (TREE_STRING_LENGTH (message) > 1)
- inform (input_location, "#pragma message: %s", TREE_STRING_POINTER (message));
+ inform (input_location, "%<#pragma message: %s%>",
+ TREE_STRING_POINTER (message));
}
/* Mark whether the current location is valid for a STDC pragma. */
@@ -1315,6 +1320,7 @@ static const struct omp_pragma_def omp_pragmas_simd[] = {
{ "for", PRAGMA_OMP_FOR },
{ "ordered", PRAGMA_OMP_ORDERED },
{ "parallel", PRAGMA_OMP_PARALLEL },
+ { "scan", PRAGMA_OMP_SCAN },
{ "simd", PRAGMA_OMP_SIMD },
{ "target", PRAGMA_OMP_TARGET },
{ "taskloop", PRAGMA_OMP_TASKLOOP },
diff --git a/gcc/c-family/c-pragma.h b/gcc/c-family/c-pragma.h
index 2bbb279..ed65036 100644
--- a/gcc/c-family/c-pragma.h
+++ b/gcc/c-family/c-pragma.h
@@ -56,6 +56,7 @@ enum pragma_kind {
PRAGMA_OMP_ORDERED,
PRAGMA_OMP_PARALLEL,
PRAGMA_OMP_REQUIRES,
+ PRAGMA_OMP_SCAN,
PRAGMA_OMP_SECTION,
PRAGMA_OMP_SECTIONS,
PRAGMA_OMP_SIMD,
diff --git a/gcc/c-family/c-warn.c b/gcc/c-family/c-warn.c
index f95eba9..b5d09e7 100644
--- a/gcc/c-family/c-warn.c
+++ b/gcc/c-family/c-warn.c
@@ -1460,8 +1460,9 @@ c_do_switch_warnings (splay_tree cases, location_t switch_location,
min_value) >= 0)
{
location_t loc = EXPR_LOCATION ((tree) node->value);
- warning_at (loc, 0, "lower value in case label range"
- " less than minimum value for type");
+ warning_at (loc, OPT_Wswitch_outside_range,
+ "lower value in case label range less than minimum"
+ " value for type");
CASE_LOW ((tree) node->value) = convert (TREE_TYPE (cond),
min_value);
node->key = (splay_tree_key) CASE_LOW ((tree) node->value);
@@ -1474,8 +1475,8 @@ c_do_switch_warnings (splay_tree cases, location_t switch_location,
if (node == NULL || !node->key)
break;
location_t loc = EXPR_LOCATION ((tree) node->value);
- warning_at (loc, 0, "case label value is less than minimum "
- "value for type");
+ warning_at (loc, OPT_Wswitch_outside_range, "case label value is"
+ " less than minimum value for type");
splay_tree_remove (cases, node->key);
}
while (1);
@@ -1491,8 +1492,8 @@ c_do_switch_warnings (splay_tree cases, location_t switch_location,
max_value) > 0)
{
location_t loc = EXPR_LOCATION ((tree) node->value);
- warning_at (loc, 0, "upper value in case label range"
- " exceeds maximum value for type");
+ warning_at (loc, OPT_Wswitch_outside_range, "upper value in case"
+ " label range exceeds maximum value for type");
CASE_HIGH ((tree) node->value)
= convert (TREE_TYPE (cond), max_value);
outside_range_p = true;
@@ -1503,7 +1504,7 @@ c_do_switch_warnings (splay_tree cases, location_t switch_location,
!= NULL)
{
location_t loc = EXPR_LOCATION ((tree) node->value);
- warning_at (loc, 0,
+ warning_at (loc, OPT_Wswitch_outside_range,
"case label value exceeds maximum value for type");
splay_tree_remove (cases, node->key);
outside_range_p = true;
@@ -1663,7 +1664,7 @@ warn_for_omitted_condop (location_t location, tree cond)
|| (TREE_TYPE (cond) != NULL_TREE
&& TREE_CODE (TREE_TYPE (cond)) == BOOLEAN_TYPE))
warning_at (location, OPT_Wparentheses,
- "the omitted middle operand in ?: will always be %<true%>, "
+ "the omitted middle operand in %<?:%> will always be %<true%>, "
"suggest explicit middle operand");
}
@@ -1762,7 +1763,7 @@ lvalue_error (location_t loc, enum lvalue_use use)
error_at (loc, "lvalue required as unary %<&%> operand");
break;
case lv_asm:
- error_at (loc, "lvalue required in asm statement");
+ error_at (loc, "lvalue required in %<asm%> statement");
break;
default:
gcc_unreachable ();
@@ -2232,10 +2233,12 @@ warn_for_sign_compare (location_t location,
{
if (constant == 0)
warning_at (location, OPT_Wsign_compare,
- "promoted ~unsigned is always non-zero");
+ "promoted bitwise complement of an unsigned "
+ "value is always nonzero");
else
warning_at (location, OPT_Wsign_compare,
- "comparison of promoted ~unsigned with constant");
+ "comparison of promoted bitwise complement "
+ "of an unsigned value with constant");
}
}
}
@@ -2245,7 +2248,8 @@ warn_for_sign_compare (location_t location,
&& (TYPE_PRECISION (TREE_TYPE (op1))
< TYPE_PRECISION (result_type)))
warning_at (location, OPT_Wsign_compare,
- "comparison of promoted ~unsigned with unsigned");
+ "comparison of promoted bitwise complement "
+ "of an unsigned value with unsigned");
}
}
@@ -2597,11 +2601,11 @@ warn_for_restrict (unsigned param_pos, tree *argarray, unsigned nargs)
}
return warning_n (&richloc, OPT_Wrestrict, arg_positions.length (),
- "passing argument %i to restrict-qualified parameter"
+ "passing argument %i to %qs-qualified parameter"
" aliases with argument %Z",
- "passing argument %i to restrict-qualified parameter"
+ "passing argument %i to %qs-qualified parameter"
" aliases with arguments %Z",
- param_pos + 1, arg_positions.address (),
+ param_pos + 1, "restrict", arg_positions.address (),
arg_positions.length ());
}
diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt
index 916cc67..4c8b002 100644
--- a/gcc/c-family/c.opt
+++ b/gcc/c-family/c.opt
@@ -562,6 +562,10 @@ Wformat-contains-nul
C ObjC C++ ObjC++ Var(warn_format_contains_nul) Warning LangEnabledBy(C ObjC C++ ObjC++,Wformat=, warn_format >= 1, 0)
Warn about format strings that contain NUL bytes.
+Wformat-diag
+C ObjC C++ ObjC++ Var(warn_format_diag) Warning LangEnabledBy(C ObjC C++ ObjC++,Wformat=, warn_format >= 1, 0)
+Warn about GCC format strings with strings unsuitable for diagnostics.
+
Wformat-extra-args
C ObjC C++ ObjC++ Var(warn_format_extra_args) Warning LangEnabledBy(C ObjC C++ ObjC++,Wformat=, warn_format >= 1, 0)
Warn if passing too many arguments to a function for its format string.
@@ -621,6 +625,10 @@ Wignored-attributes
C C++ Var(warn_ignored_attributes) Init(1) Warning
Warn whenever attributes are ignored.
+Winaccessible-base
+C++ ObjC++ Var(warn_inaccessible_base) Init(1) Warning
+Warn when a base is inaccessible in derived due to ambiguity.
+
Wincompatible-pointer-types
C ObjC Var(warn_incompatible_pointer_types) Init(1) Warning
Warn when there is a conversion between pointers that have incompatible types.
@@ -811,6 +819,10 @@ Wswitch-bool
C ObjC C++ ObjC++ Var(warn_switch_bool) Warning Init(1)
Warn about switches with boolean controlling expression.
+Wswitch-outside-range
+C ObjC C++ ObjC++ Var(warn_switch_outside_range) Warning Init(1)
+Warn about switch values that are outside of the switch's type range.
+
Wtemplates
C++ ObjC++ Var(warn_templates) Warning
Warn on primary template declaration.
@@ -1412,6 +1424,10 @@ fconstexpr-depth=
C++ ObjC++ Joined RejectNegative UInteger Var(max_constexpr_depth) Init(512)
-fconstexpr-depth=<number> Specify maximum constexpr recursion depth.
+fconstexpr-cache-depth=
+C++ ObjC++ Joined RejectNegative UInteger Var(constexpr_cache_depth) Init(8)
+-fconstexpr-cache-depth=<number> Specify maximum constexpr recursion cache depth.
+
fconstexpr-loop-limit=
C++ ObjC++ Joined RejectNegative UInteger Var(constexpr_loop_limit) Init(262144)
-fconstexpr-loop-limit=<number> Specify maximum constexpr loop iteration count.
@@ -1559,6 +1575,10 @@ flax-vector-conversions
C ObjC C++ ObjC++ Var(flag_lax_vector_conversions)
Allow implicit conversions between vectors with differing numbers of subparts and/or differing element types.
+fmax-include-depth=
+C ObjC C++ ObjC++ Joined RejectNegative UInteger
+fmax-include-depth=<number> Set the maximum depth of the nested #include.
+
fms-extensions
C ObjC C++ ObjC++ Var(flag_ms_extensions)
Don't warn about uses of Microsoft extensions.
diff --git a/gcc/c/ChangeLog b/gcc/c/ChangeLog
index cb8bfcb..271ed4ba 100644
--- a/gcc/c/ChangeLog
+++ b/gcc/c/ChangeLog
@@ -1,3 +1,94 @@
+2019-07-01 Richard Biener <rguenther@suse.de>
+
+ * gimple-parser.c (c_parser_gimple_postfix_expression): Handle
+ _Literal (char *) &"foo" for address literals pointing to
+ STRING_CSTs.
+
+2019-06-24 Martin Sebor <msebor@redhat.com>
+
+ * c-typeck.c (build_binary_op): Hyphenate floating-point.
+
+2019-06-10 Jakub Jelinek <jakub@redhat.com>
+
+ * c-parser.c (c_parser_pragma): Reject PRAGMA_OMP_SCAN.
+ (c_parser_omp_clause_reduction): Don't sorry_at on inscan reductions.
+ (c_parser_omp_scan_loop_body): New function.
+ (c_parser_omp_for_loop): Call c_parser_omp_scan_loop_body if there are
+ inscan reduction clauses.
+ * c-typeck.c (c_finish_omp_clauses): Reject mixing inscan with
+ non-inscan reductions on the same construct, or inscan reductions with
+ ordered or schedule clauses, or inscan array reductions.
+
+2019-06-05 Martin Sebor <msebor@redhat.com>
+
+ PR c/90737
+ * c-typeck.c (c_finish_return): Only consider functions returning
+ pointers as candidates for -Wreturn-local-addr.
+
+2019-06-05 Martin Sebor <msebor@redhat.com>
+
+ * c-decl.c (start_decl): Adjust quoting and hyphenation
+ in diagnostics.
+ (finish_decl): Same.
+ (finish_enum): Same.
+ (start_function): Same.
+ (declspecs_add_type): Same.
+ * c-parser.c (warn_for_abs): Same.
+ * c-typeck.c (build_binary_op): Same.
+
+2019-05-17 Thomas Schwinge <thomas@codesourcery.com>
+
+ PR c/89433
+ * c-parser.c (c_finish_oacc_routine): Rework checking if already
+ marked with an OpenACC 'routine' directive.
+
+ PR c/89433
+ * c-parser.c (c_parser_oacc_routine): Normalize order of clauses.
+ (c_finish_oacc_routine): Call oacc_verify_routine_clauses.
+
+ PR c/89433
+ * c-parser.c (c_finish_oacc_routine): Refer to OpenACC 'routine'
+ clauses from "omp declare target" attribute.
+
+2019-05-16 Martin Sebor <msebor@redhat.com>
+
+ * c-decl.c (start_decl): Quote keywords, operators, and
+ types in diagnostics.
+ (finish_decl): Same.
+ * c-parser.c (c_parser_asm_statement): Same.
+ (c_parser_conditional_expression): Same.
+ (c_parser_transaction_cancel): Same.
+ * c-typeck.c (c_common_type): Same.
+ (build_conditional_expr): Same.
+ (digest_init): Same.
+ (process_init_element): Same.
+ (build_binary_op): Same.
+
+2019-05-17 Richard Biener <rguenther@suse.de>
+
+ * gimple-parser.c (c_parser_gimple_statement): Handle __VEC_PERM.
+ (c_parser_gimple_unary_expression): Likewise.
+ (c_parser_gimple_parentized_ternary_expression): New function.
+
+2019-05-16 Richard Biener <rguenther@suse.de>
+
+ * gimple-parser.c (c_parser_gimple_statement): Handle __BIT_INSERT.
+ (c_parser_gimple_unary_expression): Likewise.
+
+2019-05-15 Richard Biener <rguenther@suse.de>
+
+ * gimple-parser.c (c_parser_gimple_postfix_expression): Handle
+ __BIT_FIELD_REF.
+
+2019-05-14 Richard Biener <rguenther@suse.de>
+
+ * gimple-parser.c (c_parser_gimple_statement): Remove
+ questionable auto-promotion to VIEW_CONVERT_EXPR.
+ (c_parser_gimple_typespec): Split out from __MEM parsing.
+ (c_parser_gimple_postfix_expression): Handle __VIEW_CONVERT.
+ * tree-pretty-print.c (dump_generic_node): Dump VIEW_CONVERT_EXPR
+ as __VIEW_CONVERT with -gimple.
+
2019-05-09 Martin Liska <mliska@suse.cz>
* gimple-parser.c (c_parser_gimple_statement): Support __MIN and
diff --git a/gcc/c/c-decl.c b/gcc/c/c-decl.c
index c8e7cd0..cb2f49f 100644
--- a/gcc/c/c-decl.c
+++ b/gcc/c/c-decl.c
@@ -1780,15 +1780,16 @@ diagnose_arglist_conflict (tree newdecl, tree olddecl,
if (TREE_CHAIN (t) == NULL_TREE
&& TYPE_MAIN_VARIANT (type) != void_type_node)
{
- inform (input_location, "a parameter list with an ellipsis can%'t match "
- "an empty parameter name list declaration");
+ inform (input_location, "a parameter list with an ellipsis "
+ "cannot match an empty parameter name list declaration");
break;
}
if (c_type_promotes_to (type) != type)
{
- inform (input_location, "an argument type that has a default promotion can%'t match "
- "an empty parameter name list declaration");
+ inform (input_location, "an argument type that has a default "
+ "promotion cannot match an empty parameter name list "
+ "declaration");
break;
}
}
@@ -4887,7 +4888,7 @@ start_decl (struct c_declarator *declarator, struct c_declspecs *declspecs,
switch (TREE_CODE (decl))
{
case TYPE_DECL:
- error ("typedef %qD is initialized (use __typeof__ instead)", decl);
+ error ("typedef %qD is initialized (use %<__typeof__%> instead)", decl);
initialized = false;
break;
@@ -5012,8 +5013,8 @@ start_decl (struct c_declarator *declarator, struct c_declspecs *declspecs,
&& DECL_DECLARED_INLINE_P (decl)
&& DECL_UNINLINABLE (decl)
&& lookup_attribute ("noinline", DECL_ATTRIBUTES (decl)))
- warning (OPT_Wattributes, "inline function %q+D given attribute noinline",
- decl);
+ warning (OPT_Wattributes, "inline function %q+D given attribute %qs",
+ decl, "noinline");
/* C99 6.7.4p3: An inline definition of a function with external
linkage shall not contain a definition of a modifiable object
@@ -5282,7 +5283,7 @@ finish_decl (tree decl, location_t init_loc, tree init,
&& VAR_P (decl)
&& !C_DECL_REGISTER (decl)
&& !TREE_STATIC (decl))
- warning (0, "ignoring asm-specifier for non-static local "
+ warning (0, "ignoring %<asm%> specifier for non-static local "
"variable %q+D", decl);
else
set_user_assembler_name (decl, asmspec);
@@ -5398,7 +5399,7 @@ finish_decl (tree decl, location_t init_loc, tree init,
type = strip_array_types (type);
if (TREE_READONLY (decl))
warning_at (DECL_SOURCE_LOCATION (decl), OPT_Wc___compat,
- "uninitialized const %qD is invalid in C++", decl);
+ "uninitialized %<const %D%> is invalid in C++", decl);
else if (RECORD_OR_UNION_TYPE_P (type)
&& C_TYPE_FIELDS_READONLY (type))
diagnose_uninitialized_cst_member (decl, type);
@@ -5725,10 +5726,10 @@ warn_variable_length_array (tree name, tree size)
if (name)
pedwarn_c90 (input_location, OPT_Wvla,
"ISO C90 forbids array %qE whose size "
- "can%'t be evaluated", name);
+ "cannot be evaluated", name);
else
pedwarn_c90 (input_location, OPT_Wvla, "ISO C90 forbids array "
- "whose size can%'t be evaluated");
+ "whose size cannot be evaluated");
}
else
{
@@ -8673,7 +8674,7 @@ finish_enum (tree enumtype, tree values, tree attributes)
if (precision > TYPE_PRECISION (enumtype))
{
TYPE_PRECISION (enumtype) = 0;
- error ("specified mode too small for enumeral values");
+ error ("specified mode too small for enumerated values");
}
else
precision = TYPE_PRECISION (enumtype);
@@ -8934,8 +8935,8 @@ start_function (struct c_declspecs *declspecs, struct c_declarator *declarator,
&& DECL_UNINLINABLE (decl1)
&& lookup_attribute ("noinline", DECL_ATTRIBUTES (decl1)))
warning_at (loc, OPT_Wattributes,
- "inline function %qD given attribute noinline",
- decl1);
+ "inline function %qD given attribute %qs",
+ decl1, "noinline");
/* Handle gnu_inline attribute. */
if (declspecs->inline_p
@@ -10636,7 +10637,11 @@ declspecs_add_type (location_t loc, struct c_declspecs *specs,
case RID_INT_N_2:
case RID_INT_N_3:
specs->int_n_idx = i - RID_INT_N_0;
- if (!in_system_header_at (input_location))
+ if (!in_system_header_at (input_location)
+ /* If the INT_N type ends in "__", and so is of the format
+ "__intN__", don't pedwarn. */
+ && (strncmp (IDENTIFIER_POINTER (type)
+ + (IDENTIFIER_LENGTH (type) - 2), "__", 2) != 0))
pedwarn (loc, OPT_Wpedantic,
"ISO C does not support %<__int%d%> types",
int_n_data[specs->int_n_idx].bitsize);
@@ -10940,10 +10945,10 @@ declspecs_add_type (location_t loc, struct c_declspecs *specs,
}
if (!targetm.decimal_float_supported_p ())
error_at (loc,
- ("decimal floating point not supported "
+ ("decimal floating-point not supported "
"for this target"));
pedwarn (loc, OPT_Wpedantic,
- "ISO C does not support decimal floating point");
+ "ISO C does not support decimal floating-point");
return specs;
case RID_FRACT:
case RID_ACCUM:
diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c
index 3aa8512..9850872 100644
--- a/gcc/c/c-parser.c
+++ b/gcc/c/c-parser.c
@@ -157,6 +157,11 @@ c_parse_init (void)
id = get_identifier (name);
C_SET_RID_CODE (id, RID_FIRST_INT_N + i);
C_IS_RESERVED_WORD (id) = 1;
+
+ sprintf (name, "__int%d__", int_n_data[i].bitsize);
+ id = get_identifier (name);
+ C_SET_RID_CODE (id, RID_FIRST_INT_N + i);
+ C_IS_RESERVED_WORD (id) = 1;
}
}
@@ -6401,7 +6406,7 @@ c_parser_asm_statement (c_parser *parser)
case RID_VOLATILE:
if (volatile_loc)
{
- error_at (loc, "duplicate asm qualifier %qE", token->value);
+ error_at (loc, "duplicate %<asm%> qualifier %qE", token->value);
inform (volatile_loc, "first seen here");
}
else
@@ -6412,7 +6417,7 @@ c_parser_asm_statement (c_parser *parser)
case RID_INLINE:
if (inline_loc)
{
- error_at (loc, "duplicate asm qualifier %qE", token->value);
+ error_at (loc, "duplicate %<asm%> qualifier %qE", token->value);
inform (inline_loc, "first seen here");
}
else
@@ -6423,7 +6428,7 @@ c_parser_asm_statement (c_parser *parser)
case RID_GOTO:
if (goto_loc)
{
- error_at (loc, "duplicate asm qualifier %qE", token->value);
+ error_at (loc, "duplicate %<asm%> qualifier %qE", token->value);
inform (goto_loc, "first seen here");
}
else
@@ -6433,7 +6438,7 @@ c_parser_asm_statement (c_parser *parser)
case RID_CONST:
case RID_RESTRICT:
- error_at (loc, "%qE is not an asm qualifier", token->value);
+ error_at (loc, "%qE is not a valid %<asm%> qualifier", token->value);
c_parser_consume_token (parser);
continue;
@@ -6791,7 +6796,7 @@ c_parser_conditional_expression (c_parser *parser, struct c_expr *after,
location_t middle_loc = c_parser_peek_token (parser)->location;
pedwarn (middle_loc, OPT_Wpedantic,
- "ISO C forbids omitting the middle term of a ?: expression");
+ "ISO C forbids omitting the middle term of a %<?:%> expression");
if (TREE_CODE (cond.value) == EXCESS_PRECISION_EXPR)
{
eptype = TREE_TYPE (cond.value);
@@ -9420,7 +9425,7 @@ warn_for_abs (location_t loc, tree fndecl, tree arg)
if (SCALAR_FLOAT_TYPE_P (atype))
warning_at (loc, OPT_Wabsolute_value,
"using integer absolute value function %qD when "
- "argument is of floating point type %qT",
+ "argument is of floating-point type %qT",
fndecl, atype);
else if (TREE_CODE (atype) == COMPLEX_TYPE)
warning_at (loc, OPT_Wabsolute_value,
@@ -9443,16 +9448,16 @@ warn_for_abs (location_t loc, tree fndecl, tree arg)
{
if (INTEGRAL_TYPE_P (atype))
warning_at (loc, OPT_Wabsolute_value,
- "using floating point absolute value function %qD "
+ "using floating-point absolute value function %qD "
"when argument is of integer type %qT", fndecl, atype);
else if (DECIMAL_FLOAT_TYPE_P (atype))
warning_at (loc, OPT_Wabsolute_value,
- "using floating point absolute value function %qD "
- "when argument is of decimal floating point type %qT",
+ "using floating-point absolute value function %qD "
+ "when argument is of decimal floating-point type %qT",
fndecl, atype);
else if (TREE_CODE (atype) == COMPLEX_TYPE)
warning_at (loc, OPT_Wabsolute_value,
- "using floating point absolute value function %qD when "
+ "using floating-point absolute value function %qD when "
"argument is of complex type %qT", fndecl, atype);
else
gcc_unreachable ();
@@ -9470,7 +9475,7 @@ warn_for_abs (location_t loc, tree fndecl, tree arg)
else if (SCALAR_FLOAT_TYPE_P (atype))
warning_at (loc, OPT_Wabsolute_value,
"using complex absolute value function %qD when "
- "argument is of floating point type %qT",
+ "argument is of floating-point type %qT",
fndecl, atype);
else
gcc_unreachable ();
@@ -9486,17 +9491,17 @@ warn_for_abs (location_t loc, tree fndecl, tree arg)
{
if (INTEGRAL_TYPE_P (atype))
warning_at (loc, OPT_Wabsolute_value,
- "using decimal floating point absolute value "
+ "using decimal floating-point absolute value "
"function %qD when argument is of integer type %qT",
fndecl, atype);
else if (SCALAR_FLOAT_TYPE_P (atype))
warning_at (loc, OPT_Wabsolute_value,
- "using decimal floating point absolute value "
- "function %qD when argument is of floating point "
+ "using decimal floating-point absolute value "
+ "function %qD when argument is of floating-point "
"type %qT", fndecl, atype);
else if (TREE_CODE (atype) == COMPLEX_TYPE)
warning_at (loc, OPT_Wabsolute_value,
- "using decimal floating point absolute value "
+ "using decimal floating-point absolute value "
"function %qD when argument is of complex type %qT",
fndecl, atype);
else
@@ -11494,6 +11499,13 @@ c_parser_pragma (c_parser *parser, enum pragma_context context, bool *if_p)
c_parser_omp_end_declare_target (parser);
return false;
+ case PRAGMA_OMP_SCAN:
+ error_at (c_parser_peek_token (parser)->location,
+ "%<#pragma omp scan%> may only be used in "
+ "a loop construct with %<inscan%> %<reduction%> clause");
+ c_parser_skip_until_found (parser, CPP_PRAGMA_EOL, NULL);
+ return false;
+
case PRAGMA_OMP_SECTION:
error_at (c_parser_peek_token (parser)->location,
"%<#pragma omp section%> may only be used in "
@@ -13558,11 +13570,7 @@ c_parser_omp_clause_reduction (c_parser *parser, enum omp_clause_code kind,
if (strcmp (p, "task") == 0)
task = true;
else if (strcmp (p, "inscan") == 0)
- {
- inscan = true;
- sorry ("%<inscan%> modifier on %<reduction%> clause "
- "not supported yet");
- }
+ inscan = true;
if (task || inscan)
{
c_parser_consume_token (parser);
@@ -15801,6 +15809,9 @@ c_parser_oacc_routine (c_parser *parser, enum pragma_context context)
data.clauses
= c_parser_oacc_all_clauses (parser, OACC_ROUTINE_CLAUSE_MASK,
"#pragma acc routine");
+ /* The clauses are in reverse order; fix that to make later diagnostic
+ emission easier. */
+ data.clauses = nreverse (data.clauses);
if (TREE_CODE (decl) != FUNCTION_DECL)
{
@@ -15815,6 +15826,9 @@ c_parser_oacc_routine (c_parser *parser, enum pragma_context context)
data.clauses
= c_parser_oacc_all_clauses (parser, OACC_ROUTINE_CLAUSE_MASK,
"#pragma acc routine");
+ /* The clauses are in reverse order; fix that to make later diagnostic
+ emission easier. */
+ data.clauses = nreverse (data.clauses);
/* Emit a helpful diagnostic if there's another pragma following this
one. Also don't allow a static assertion declaration, as in the
@@ -15878,33 +15892,39 @@ c_finish_oacc_routine (struct oacc_routine_data *data, tree fndecl,
return;
}
- if (oacc_get_fn_attrib (fndecl))
+ int compatible
+ = oacc_verify_routine_clauses (fndecl, &data->clauses, data->loc,
+ "#pragma acc routine");
+ if (compatible < 0)
{
- error_at (data->loc,
- "%<#pragma acc routine%> already applied to %qD", fndecl);
data->error_seen = true;
return;
}
-
- if (TREE_USED (fndecl) || (!is_defn && DECL_SAVED_TREE (fndecl)))
+ if (compatible > 0)
{
- error_at (data->loc,
- TREE_USED (fndecl)
- ? G_("%<#pragma acc routine%> must be applied before use")
- : G_("%<#pragma acc routine%> must be applied before "
- "definition"));
- data->error_seen = true;
- return;
}
+ else
+ {
+ if (TREE_USED (fndecl) || (!is_defn && DECL_SAVED_TREE (fndecl)))
+ {
+ error_at (data->loc,
+ TREE_USED (fndecl)
+ ? G_("%<#pragma acc routine%> must be applied before use")
+ : G_("%<#pragma acc routine%> must be applied before"
+ " definition"));
+ data->error_seen = true;
+ return;
+ }
- /* Process the routine's dimension clauses. */
- tree dims = oacc_build_routine_dims (data->clauses);
- oacc_replace_fn_attrib (fndecl, dims);
+ /* Set the routine's level of parallelism. */
+ tree dims = oacc_build_routine_dims (data->clauses);
+ oacc_replace_fn_attrib (fndecl, dims);
- /* Add an "omp declare target" attribute. */
- DECL_ATTRIBUTES (fndecl)
- = tree_cons (get_identifier ("omp declare target"),
- NULL_TREE, DECL_ATTRIBUTES (fndecl));
+ /* Add an "omp declare target" attribute. */
+ DECL_ATTRIBUTES (fndecl)
+ = tree_cons (get_identifier ("omp declare target"),
+ data->clauses, DECL_ATTRIBUTES (fndecl));
+ }
/* Remember that we've used this "#pragma acc routine". */
data->fndecl_seen = true;
@@ -16726,6 +16746,71 @@ c_parser_omp_flush (c_parser *parser)
c_finish_omp_flush (loc, mo);
}
+/* OpenMP 5.0:
+
+ scan-loop-body:
+ { structured-block scan-directive structured-block } */
+
+static void
+c_parser_omp_scan_loop_body (c_parser *parser, bool open_brace_parsed)
+{
+ tree substmt;
+ location_t loc;
+ tree clauses = NULL_TREE;
+
+ loc = c_parser_peek_token (parser)->location;
+ if (!open_brace_parsed
+ && !c_parser_require (parser, CPP_OPEN_BRACE, "expected %<{%>"))
+ {
+ /* Avoid skipping until the end of the block. */
+ parser->error = false;
+ return;
+ }
+
+ substmt = c_parser_omp_structured_block (parser, NULL);
+ substmt = build2 (OMP_SCAN, void_type_node, substmt, NULL_TREE);
+ SET_EXPR_LOCATION (substmt, loc);
+ add_stmt (substmt);
+
+ loc = c_parser_peek_token (parser)->location;
+ if (c_parser_peek_token (parser)->pragma_kind == PRAGMA_OMP_SCAN)
+ {
+ enum omp_clause_code clause = OMP_CLAUSE_ERROR;
+
+ c_parser_consume_pragma (parser);
+
+ if (c_parser_next_token_is (parser, CPP_NAME))
+ {
+ const char *p
+ = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
+ if (strcmp (p, "inclusive") == 0)
+ clause = OMP_CLAUSE_INCLUSIVE;
+ else if (strcmp (p, "exclusive") == 0)
+ clause = OMP_CLAUSE_EXCLUSIVE;
+ }
+ if (clause != OMP_CLAUSE_ERROR)
+ {
+ c_parser_consume_token (parser);
+ clauses = c_parser_omp_var_list_parens (parser, clause, NULL_TREE);
+ }
+ else
+ c_parser_error (parser, "expected %<inclusive%> or "
+ "%<exclusive%> clause");
+ c_parser_skip_to_pragma_eol (parser);
+ }
+ else
+ error ("expected %<#pragma omp scan%>");
+
+ clauses = c_finish_omp_clauses (clauses, C_ORT_OMP);
+ substmt = c_parser_omp_structured_block (parser, NULL);
+ substmt = build2 (OMP_SCAN, void_type_node, substmt, clauses);
+ SET_EXPR_LOCATION (substmt, loc);
+ add_stmt (substmt);
+
+ c_parser_skip_until_found (parser, CPP_CLOSE_BRACE,
+ "expected %<}%>");
+}
+
/* Parse the restricted form of loop statements allowed by OpenACC and OpenMP.
The real trick here is to determine the loop control variable early
so that we can push a new decl if necessary to make it private.
@@ -16744,6 +16829,7 @@ c_parser_omp_for_loop (location_t loc, c_parser *parser, enum tree_code code,
int i, collapse = 1, ordered = 0, count, nbraces = 0;
location_t for_loc;
bool tiling = false;
+ bool inscan = false;
vec<tree, va_gc> *for_block = make_tree_vector ();
for (cl = clauses; cl; cl = OMP_CLAUSE_CHAIN (cl))
@@ -16760,6 +16846,10 @@ c_parser_omp_for_loop (location_t loc, c_parser *parser, enum tree_code code,
ordered_cl = cl;
ordered = tree_to_shwi (OMP_CLAUSE_ORDERED_EXPR (cl));
}
+ else if (OMP_CLAUSE_CODE (cl) == OMP_CLAUSE_REDUCTION
+ && OMP_CLAUSE_REDUCTION_INSCAN (cl)
+ && (code == OMP_SIMD || code == OMP_FOR))
+ inscan = true;
if (ordered && ordered < collapse)
{
@@ -16980,7 +17070,9 @@ c_parser_omp_for_loop (location_t loc, c_parser *parser, enum tree_code code,
c_cont_label = NULL_TREE;
body = push_stmt_list ();
- if (open_brace_parsed)
+ if (inscan)
+ c_parser_omp_scan_loop_body (parser, open_brace_parsed);
+ else if (open_brace_parsed)
{
location_t here = c_parser_peek_token (parser)->location;
stmt = c_begin_compound_stmt (true);
@@ -19825,8 +19917,8 @@ c_parser_transaction_cancel (c_parser *parser)
&& !is_tm_may_cancel_outer (current_function_decl))
{
error_at (loc, "outer %<__transaction_cancel%> not "
- "within outer %<__transaction_atomic%>");
- error_at (loc, " or a %<transaction_may_cancel_outer%> function");
+ "within outer %<__transaction_atomic%> or "
+ "a %<transaction_may_cancel_outer%> function");
goto ret_error;
}
}
diff --git a/gcc/c/c-typeck.c b/gcc/c/c-typeck.c
index 4e44375..6419ca9 100644
--- a/gcc/c/c-typeck.c
+++ b/gcc/c/c-typeck.c
@@ -743,17 +743,18 @@ c_common_type (tree t1, tree t2)
{
if (code1 == VECTOR_TYPE || code2 == VECTOR_TYPE)
{
- error ("can%'t mix operands of decimal float and vector types");
+ error ("cannot mix operands of decimal floating and vector types");
return error_mark_node;
}
if (code1 == COMPLEX_TYPE || code2 == COMPLEX_TYPE)
{
- error ("can%'t mix operands of decimal float and complex types");
+ error ("cannot mix operands of decimal floating and complex types");
return error_mark_node;
}
if (code1 == REAL_TYPE && code2 == REAL_TYPE)
{
- error ("can%'t mix operands of decimal float and other float types");
+ error ("cannot mix operands of decimal floating "
+ "and other floating types");
return error_mark_node;
}
}
@@ -5253,13 +5254,13 @@ build_conditional_expr (location_t colon_loc, tree ifexp, bool ifexp_bcp,
/* OK */;
else if (unsigned_op2)
warning_at (op1_loc, OPT_Wsign_compare,
- "operand of ?: changes signedness from "
+ "operand of %<?:%> changes signedness from "
"%qT to %qT due to unsignedness of other "
"operand", TREE_TYPE (orig_op1),
TREE_TYPE (orig_op2));
else
warning_at (op2_loc, OPT_Wsign_compare,
- "operand of ?: changes signedness from "
+ "operand of %<?:%> changes signedness from "
"%qT to %qT due to unsignedness of other "
"operand", TREE_TYPE (orig_op2),
TREE_TYPE (orig_op1));
@@ -7764,13 +7765,13 @@ digest_init (location_t init_loc, tree type, tree init, tree origtype,
that is counted in the length of the constant. */
if (compare_tree_int (TYPE_SIZE_UNIT (type), len - unit) < 0)
pedwarn_init (init_loc, 0,
- ("initializer-string for array of chars "
- "is too long"));
+ ("initializer-string for array of %qT "
+ "is too long"), typ1);
else if (warn_cxx_compat
&& compare_tree_int (TYPE_SIZE_UNIT (type), len) < 0)
warning_at (init_loc, OPT_Wc___compat,
- ("initializer-string for array chars "
- "is too long for C++"));
+ ("initializer-string for array of %qT "
+ "is too long for C++"), typ1);
if (compare_tree_int (TYPE_SIZE_UNIT (type), len) < 0)
{
unsigned HOST_WIDE_INT size
@@ -9888,7 +9889,7 @@ process_init_element (location_t loc, struct c_expr value, bool implicit,
&& integer_zerop (constructor_unfilled_index))
{
if (constructor_stack->replacement_value.value)
- error_init (loc, "excess elements in char array initializer");
+ error_init (loc, "excess elements in %<char%> array initializer");
constructor_stack->replacement_value = value;
return;
}
@@ -10627,7 +10628,8 @@ c_finish_return (location_t loc, tree retval, tree origtype)
if (DECL_P (inner)
&& !DECL_EXTERNAL (inner)
&& !TREE_STATIC (inner)
- && DECL_CONTEXT (inner) == current_function_decl)
+ && DECL_CONTEXT (inner) == current_function_decl
+ && POINTER_TYPE_P (TREE_TYPE (TREE_TYPE (current_function_decl))))
{
if (TREE_CODE (inner) == LABEL_DECL)
warning_at (loc, OPT_Wreturn_local_addr,
@@ -11937,7 +11939,7 @@ build_binary_op (location_t location, enum tree_code code,
if (FLOAT_TYPE_P (type0) || FLOAT_TYPE_P (type1))
warning_at (location,
OPT_Wfloat_equal,
- "comparing floating point with == or != is unsafe");
+ "comparing floating-point with %<==%> or %<!=%> is unsafe");
/* Result of comparison is always int,
but don't convert the args to int! */
build_type = integer_type_node;
@@ -13659,13 +13661,15 @@ c_finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
bool copyprivate_seen = false;
bool linear_variable_step_check = false;
tree *nowait_clause = NULL;
- bool ordered_seen = false;
+ tree ordered_clause = NULL_TREE;
tree schedule_clause = NULL_TREE;
bool oacc_async = false;
tree last_iterators = NULL_TREE;
bool last_iterators_remove = false;
tree *nogroup_seen = NULL;
- bool reduction_seen = false;
+ /* 1 if normal/task reduction has been seen, -1 if inscan reduction
+ has been seen, -2 if mixed inscan/normal reduction diagnosed. */
+ int reduction_seen = 0;
bitmap_obstack_initialize (NULL);
bitmap_initialize (&generic_head, &bitmap_default_obstack);
@@ -13704,7 +13708,17 @@ c_finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
goto check_dup_generic;
case OMP_CLAUSE_REDUCTION:
- reduction_seen = true;
+ if (reduction_seen == 0)
+ reduction_seen = OMP_CLAUSE_REDUCTION_INSCAN (c) ? -1 : 1;
+ else if (reduction_seen != -2
+ && reduction_seen != (OMP_CLAUSE_REDUCTION_INSCAN (c)
+ ? -1 : 1))
+ {
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "%<inscan%> and non-%<inscan%> %<reduction%> clauses "
+ "on the same construct");
+ reduction_seen = -2;
+ }
/* FALLTHRU */
case OMP_CLAUSE_IN_REDUCTION:
case OMP_CLAUSE_TASK_REDUCTION:
@@ -13719,6 +13733,15 @@ c_finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
}
t = OMP_CLAUSE_DECL (c);
+ if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
+ && OMP_CLAUSE_REDUCTION_INSCAN (c))
+ {
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "%<inscan%> %<reduction%> clause with array "
+ "section");
+ remove = true;
+ break;
+ }
}
t = require_complete_type (OMP_CLAUSE_LOCATION (c), t);
if (t == error_mark_node)
@@ -14659,7 +14682,7 @@ c_finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
continue;
case OMP_CLAUSE_ORDERED:
- ordered_seen = true;
+ ordered_clause = c;
pc = &OMP_CLAUSE_CHAIN (c);
continue;
@@ -14686,6 +14709,20 @@ c_finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
pc = &OMP_CLAUSE_CHAIN (c);
continue;
+ case OMP_CLAUSE_INCLUSIVE:
+ case OMP_CLAUSE_EXCLUSIVE:
+ need_complete = true;
+ need_implicitly_determined = true;
+ t = OMP_CLAUSE_DECL (c);
+ if (!VAR_P (t) && TREE_CODE (t) != PARM_DECL)
+ {
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "%qE is not a variable in clause %qs", t,
+ omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
+ remove = true;
+ }
+ break;
+
default:
gcc_unreachable ();
}
@@ -14758,7 +14795,7 @@ c_finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
= OMP_CLAUSE_SAFELEN_EXPR (safelen);
}
- if (ordered_seen
+ if (ordered_clause
&& schedule_clause
&& (OMP_CLAUSE_SCHEDULE_KIND (schedule_clause)
& OMP_CLAUSE_SCHEDULE_NONMONOTONIC))
@@ -14772,7 +14809,23 @@ c_finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
& ~OMP_CLAUSE_SCHEDULE_NONMONOTONIC);
}
- if (linear_variable_step_check)
+ if (reduction_seen < 0 && ordered_clause)
+ {
+ error_at (OMP_CLAUSE_LOCATION (ordered_clause),
+ "%qs clause specified together with %<inscan%> "
+ "%<reduction%> clause", "ordered");
+ reduction_seen = -2;
+ }
+
+ if (reduction_seen < 0 && schedule_clause)
+ {
+ error_at (OMP_CLAUSE_LOCATION (schedule_clause),
+ "%qs clause specified together with %<inscan%> "
+ "%<reduction%> clause", "schedule");
+ reduction_seen = -2;
+ }
+
+ if (linear_variable_step_check || reduction_seen == -2)
for (pc = &clauses, c = clauses; c ; c = *pc)
{
bool remove = false;
@@ -14787,6 +14840,8 @@ c_finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
OMP_CLAUSE_LINEAR_STEP (c));
remove = true;
}
+ else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
+ OMP_CLAUSE_REDUCTION_INSCAN (c) = 0;
if (remove)
*pc = OMP_CLAUSE_CHAIN (c);
diff --git a/gcc/c/gimple-parser.c b/gcc/c/gimple-parser.c
index 99f7647..b2b364c 100644
--- a/gcc/c/gimple-parser.c
+++ b/gcc/c/gimple-parser.c
@@ -724,14 +724,8 @@ c_parser_gimple_statement (gimple_parser &parser, gimple_seq *seq)
&& rhs.value != error_mark_node)
{
enum tree_code code = NOP_EXPR;
- if (VECTOR_TYPE_P (TREE_TYPE (lhs.value)))
- {
- code = VIEW_CONVERT_EXPR;
- rhs.value = build1 (VIEW_CONVERT_EXPR,
- TREE_TYPE (lhs.value), rhs.value);
- }
- else if (FLOAT_TYPE_P (TREE_TYPE (lhs.value))
- && ! FLOAT_TYPE_P (TREE_TYPE (rhs.value)))
+ if (FLOAT_TYPE_P (TREE_TYPE (lhs.value))
+ && ! FLOAT_TYPE_P (TREE_TYPE (rhs.value)))
code = FLOAT_EXPR;
else if (! FLOAT_TYPE_P (TREE_TYPE (lhs.value))
&& FLOAT_TYPE_P (TREE_TYPE (rhs.value)))
@@ -752,7 +746,9 @@ c_parser_gimple_statement (gimple_parser &parser, gimple_seq *seq)
if (strcmp (IDENTIFIER_POINTER (id), "__ABS") == 0
|| strcmp (IDENTIFIER_POINTER (id), "__ABSU") == 0
|| strcmp (IDENTIFIER_POINTER (id), "__MIN") == 0
- || strcmp (IDENTIFIER_POINTER (id), "__MAX") == 0)
+ || strcmp (IDENTIFIER_POINTER (id), "__MAX") == 0
+ || strcmp (IDENTIFIER_POINTER (id), "__BIT_INSERT") == 0
+ || strcmp (IDENTIFIER_POINTER (id), "__VEC_PERM") == 0)
goto build_unary_expr;
break;
}
@@ -1017,6 +1013,38 @@ c_parser_gimple_parentized_binary_expression (gimple_parser &parser,
return ret;
}
+/* Parse a gimple parentized binary expression. */
+
+static c_expr
+c_parser_gimple_parentized_ternary_expression (gimple_parser &parser,
+ location_t op_loc,
+ tree_code code)
+{
+ struct c_expr ret;
+ ret.set_error ();
+
+ c_parser_consume_token (parser);
+ if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
+ return ret;
+ c_expr op1 = c_parser_gimple_postfix_expression (parser);
+ if (!c_parser_require (parser, CPP_COMMA, "expected %<,%>"))
+ return ret;
+ c_expr op2 = c_parser_gimple_postfix_expression (parser);
+ if (!c_parser_require (parser, CPP_COMMA, "expected %<)%>"))
+ return ret;
+ c_expr op3 = c_parser_gimple_postfix_expression (parser);
+ if (!c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>"))
+ return ret;
+
+ if (op1.value != error_mark_node
+ && op2.value != error_mark_node
+ && op3.value != error_mark_node)
+ ret.value = build3_loc (op_loc,
+ code, TREE_TYPE (op1.value),
+ op1.value, op2.value, op3.value);
+ return ret;
+}
+
/* Parse gimple unary expression.
gimple-unary-expression:
@@ -1114,6 +1142,40 @@ c_parser_gimple_unary_expression (gimple_parser &parser)
return c_parser_gimple_parentized_binary_expression (parser,
op_loc,
MAX_EXPR);
+ else if (strcmp (IDENTIFIER_POINTER (id), "__VEC_PERM") == 0)
+ return c_parser_gimple_parentized_ternary_expression
+ (parser, op_loc, VEC_PERM_EXPR);
+ else if (strcmp (IDENTIFIER_POINTER (id), "__BIT_INSERT") == 0)
+ {
+ /* __BIT_INSERT '(' postfix-expression, postfix-expression,
+ integer ')' */
+ location_t loc = c_parser_peek_token (parser)->location;
+ c_parser_consume_token (parser);
+ if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
+ {
+ c_expr op0 = c_parser_gimple_postfix_expression (parser);
+ c_parser_skip_until_found (parser, CPP_COMMA,
+ "expected %<,%>");
+ c_expr op1 = c_parser_gimple_postfix_expression (parser);
+ c_parser_skip_until_found (parser, CPP_COMMA,
+ "expected %<,%>");
+ c_expr op2 = c_parser_gimple_postfix_expression (parser);
+ if (TREE_CODE (op2.value) != INTEGER_CST
+ || !int_fits_type_p (op2.value, bitsizetype))
+ c_parser_error (parser, "expected constant offset");
+ c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
+ "expected %<)%>");
+ if (op0.value != error_mark_node
+ && op1.value != error_mark_node
+ && TREE_CODE (op2.value) == INTEGER_CST)
+ ret.value = build3_loc (loc, BIT_INSERT_EXPR,
+ TREE_TYPE (op0.value),
+ op0.value, op1.value,
+ fold_convert (bitsizetype,
+ op2.value));
+ }
+ return ret;
+ }
else
return c_parser_gimple_postfix_expression (parser);
}
@@ -1247,6 +1309,36 @@ c_parser_gimple_call_internal (gimple_parser &parser)
return expr;
}
+/* Parse '<' type [',' alignment] '>' and return a type on success
+ and NULL_TREE on error. */
+
+static tree
+c_parser_gimple_typespec (gimple_parser &parser)
+{
+ struct c_type_name *type_name = NULL;
+ tree alignment = NULL_TREE;
+ if (c_parser_require (parser, CPP_LESS, "expected %<<%>"))
+ {
+ type_name = c_parser_type_name (parser);
+ /* Optional alignment. */
+ if (c_parser_next_token_is (parser, CPP_COMMA))
+ {
+ c_parser_consume_token (parser);
+ alignment
+ = c_parser_gimple_postfix_expression (parser).value;
+ }
+ c_parser_skip_until_found (parser,
+ CPP_GREATER, "expected %<>%>");
+ }
+ if (!type_name)
+ return NULL_TREE;
+ tree tem;
+ tree type = groktypename (type_name, &tem, NULL);
+ if (alignment)
+ type = build_aligned_type (type, tree_to_uhwi (alignment));
+ return type;
+}
+
/* Parse gimple postfix expression.
gimple-postfix-expression:
@@ -1316,21 +1408,7 @@ c_parser_gimple_postfix_expression (gimple_parser &parser)
[ '+' number ] ')' */
location_t loc = c_parser_peek_token (parser)->location;
c_parser_consume_token (parser);
- struct c_type_name *type_name = NULL;
- tree alignment = NULL_TREE;
- if (c_parser_require (parser, CPP_LESS, "expected %<<%>"))
- {
- type_name = c_parser_type_name (parser);
- /* Optional alignment. */
- if (c_parser_next_token_is (parser, CPP_COMMA))
- {
- c_parser_consume_token (parser);
- alignment
- = c_parser_gimple_postfix_expression (parser).value;
- }
- c_parser_skip_until_found (parser,
- CPP_GREATER, "expected %<>%>");
- }
+ tree type = c_parser_gimple_typespec (parser);
struct c_expr ptr;
ptr.value = error_mark_node;
tree alias_off = NULL_TREE;
@@ -1378,19 +1456,70 @@ c_parser_gimple_postfix_expression (gimple_parser &parser)
c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
"expected %<)%>");
}
- if (! type_name || c_parser_error (parser))
+ if (! type || c_parser_error (parser))
{
c_parser_set_error (parser, false);
return expr;
}
- tree tem = NULL_TREE;
- tree type = groktypename (type_name, &tem, NULL);
- if (alignment)
- type = build_aligned_type (type, tree_to_uhwi (alignment));
expr.value = build2_loc (loc, MEM_REF,
type, ptr.value, alias_off);
break;
}
+ else if (strcmp (IDENTIFIER_POINTER (id), "__VIEW_CONVERT") == 0)
+ {
+ /* __VIEW_CONVERT '<' type-name [ ',' number ] '>'
+ '(' postfix-expression ')' */
+ location_t loc = c_parser_peek_token (parser)->location;
+ c_parser_consume_token (parser);
+ tree type = c_parser_gimple_typespec (parser);
+ if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
+ {
+ c_expr op = c_parser_gimple_postfix_expression (parser);
+ c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
+ "expected %<)%>");
+ if (type && op.value != error_mark_node)
+ expr.value = build1_loc (loc, VIEW_CONVERT_EXPR,
+ type, op.value);
+ }
+ break;
+ }
+ else if (strcmp (IDENTIFIER_POINTER (id), "__BIT_FIELD_REF") == 0)
+ {
+ /* __BIT_FIELD_REF '<' type-name [ ',' number ] '>'
+ '(' postfix-expression, integer, integer ')' */
+ location_t loc = c_parser_peek_token (parser)->location;
+ c_parser_consume_token (parser);
+ tree type = c_parser_gimple_typespec (parser);
+ if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
+ {
+ c_expr op0 = c_parser_gimple_postfix_expression (parser);
+ c_parser_skip_until_found (parser, CPP_COMMA,
+ "expected %<,%>");
+ c_expr op1 = c_parser_gimple_postfix_expression (parser);
+ if (TREE_CODE (op1.value) != INTEGER_CST
+ || !int_fits_type_p (op1.value, bitsizetype))
+ c_parser_error (parser, "expected constant size");
+ c_parser_skip_until_found (parser, CPP_COMMA,
+ "expected %<,%>");
+ c_expr op2 = c_parser_gimple_postfix_expression (parser);
+ if (TREE_CODE (op2.value) != INTEGER_CST
+ || !int_fits_type_p (op2.value, bitsizetype))
+ c_parser_error (parser, "expected constant offset");
+ c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
+ "expected %<)%>");
+ if (type
+ && op0.value != error_mark_node
+ && TREE_CODE (op1.value) == INTEGER_CST
+ && TREE_CODE (op2.value) == INTEGER_CST)
+ expr.value = build3_loc (loc, BIT_FIELD_REF, type,
+ op0.value,
+ fold_convert (bitsizetype,
+ op1.value),
+ fold_convert (bitsizetype,
+ op2.value));
+ }
+ break;
+ }
else if (strcmp (IDENTIFIER_POINTER (id), "_Literal") == 0)
{
/* _Literal '(' type-name ')' ( [ '-' ] constant | constructor ) */
@@ -1467,17 +1596,22 @@ c_parser_gimple_postfix_expression (gimple_parser &parser)
}
else
{
- bool neg_p;
+ bool neg_p, addr_p;
if ((neg_p = c_parser_next_token_is (parser, CPP_MINUS)))
c_parser_consume_token (parser);
+ if ((addr_p = c_parser_next_token_is (parser, CPP_AND)))
+ c_parser_consume_token (parser);
tree val = c_parser_gimple_postfix_expression (parser).value;
if (! val
|| val == error_mark_node
- || ! CONSTANT_CLASS_P (val))
+ || ! CONSTANT_CLASS_P (val)
+ || (addr_p && TREE_CODE (val) != STRING_CST))
{
c_parser_error (parser, "invalid _Literal");
return expr;
}
+ if (addr_p)
+ val = build1 (ADDR_EXPR, type, val);
if (neg_p)
{
val = const_unop (NEGATE_EXPR, TREE_TYPE (val), val);
diff --git a/gcc/calls.c b/gcc/calls.c
index 6b22e7a..6ab138e 100644
--- a/gcc/calls.c
+++ b/gcc/calls.c
@@ -3226,6 +3226,19 @@ can_implement_as_sibling_call_p (tree exp,
return true;
}
+/* Update stack alignment when the parameter is passed in the stack
+ since the outgoing parameter requires extra alignment on the calling
+ function side. */
+
+static void
+update_stack_alignment_for_call (struct locate_and_pad_arg_data *locate)
+{
+ if (crtl->stack_alignment_needed < locate->boundary)
+ crtl->stack_alignment_needed = locate->boundary;
+ if (crtl->preferred_stack_boundary < locate->boundary)
+ crtl->preferred_stack_boundary = locate->boundary;
+}
+
/* Generate all the code for a CALL_EXPR exp
and return an rtx for its value.
Store the value in TARGET (specified as an rtx) if convenient.
@@ -3628,6 +3641,28 @@ expand_call (tree exp, rtx target, int ignore)
|| dbg_cnt (tail_call) == false)
try_tail_call = 0;
+ /* Workaround buggy C/C++ wrappers around Fortran routines with
+ character(len=constant) arguments if the hidden string length arguments
+ are passed on the stack; if the callers forget to pass those arguments,
+ attempting to tail call in such routines leads to stack corruption.
+ Avoid tail calls in functions where at least one such hidden string
+ length argument is passed (partially or fully) on the stack in the
+ caller and the callee needs to pass any arguments on the stack.
+ See PR90329. */
+ if (try_tail_call && maybe_ne (args_size.constant, 0))
+ for (tree arg = DECL_ARGUMENTS (current_function_decl);
+ arg; arg = DECL_CHAIN (arg))
+ if (DECL_HIDDEN_STRING_LENGTH (arg) && DECL_INCOMING_RTL (arg))
+ {
+ subrtx_iterator::array_type array;
+ FOR_EACH_SUBRTX (iter, array, DECL_INCOMING_RTL (arg), NONCONST)
+ if (MEM_P (*iter))
+ {
+ try_tail_call = 0;
+ break;
+ }
+ }
+
/* If the user has marked the function as requiring tail-call
optimization, attempt it. */
if (must_tail_call)
@@ -3681,6 +3716,12 @@ expand_call (tree exp, rtx target, int ignore)
/* Ensure current function's preferred stack boundary is at least
what we need. Stack alignment may also increase preferred stack
boundary. */
+ for (i = 0; i < num_actuals; i++)
+ if (reg_parm_stack_space > 0
+ || args[i].reg == 0
+ || args[i].partial != 0
+ || args[i].pass_on_stack)
+ update_stack_alignment_for_call (&args[i].locate);
if (crtl->preferred_stack_boundary < preferred_stack_boundary)
crtl->preferred_stack_boundary = preferred_stack_boundary;
else
@@ -4939,6 +4980,12 @@ emit_library_call_value_1 (int retval, rtx orgfun, rtx value,
targetm.calls.function_arg_advance (args_so_far, mode, (tree) 0, true);
}
+ for (int i = 0; i < nargs; i++)
+ if (reg_parm_stack_space > 0
+ || argvec[i].reg == 0
+ || argvec[i].partial != 0)
+ update_stack_alignment_for_call (&argvec[i].locate);
+
/* If this machine requires an external definition for library
functions, write one out. */
assemble_external_libcall (fun);
diff --git a/gcc/ccmp.c b/gcc/ccmp.c
index ee8e478..c92fc3d 100644
--- a/gcc/ccmp.c
+++ b/gcc/ccmp.c
@@ -187,12 +187,11 @@ expand_ccmp_next (tree op, tree_code code, rtx prev,
static rtx
expand_ccmp_expr_1 (gimple *g, rtx_insn **prep_seq, rtx_insn **gen_seq)
{
- tree exp = gimple_assign_rhs_to_tree (g);
- tree_code code = TREE_CODE (exp);
+ tree_code code = gimple_assign_rhs_code (g);
basic_block bb = gimple_bb (g);
- tree op0 = TREE_OPERAND (exp, 0);
- tree op1 = TREE_OPERAND (exp, 1);
+ tree op0 = gimple_assign_rhs1 (g);
+ tree op1 = gimple_assign_rhs2 (g);
gimple *gs0 = get_gimple_for_ssa_name (op0);
gimple *gs1 = get_gimple_for_ssa_name (op1);
rtx tmp;
diff --git a/gcc/cfg.c b/gcc/cfg.c
index 94e68c8..983115e 100644
--- a/gcc/cfg.c
+++ b/gcc/cfg.c
@@ -546,9 +546,10 @@ dump_edge_info (FILE *file, edge e, dump_flags_t flags, int do_succ)
DEBUG_FUNCTION void
debug (edge_def &ref)
{
- /* FIXME (crowl): Is this desireable? */
- dump_edge_info (stderr, &ref, TDF_NONE, false);
- dump_edge_info (stderr, &ref, TDF_NONE, true);
+ fprintf (stderr, "<edge (%d -> %d)>\n",
+ ref.src->index, ref.dest->index);
+ dump_edge_info (stderr, &ref, TDF_DETAILS, false);
+ fprintf (stderr, "\n");
}
DEBUG_FUNCTION void
diff --git a/gcc/cfgexpand.c b/gcc/cfgexpand.c
index 3a4bd35..1e84d2c 100644
--- a/gcc/cfgexpand.c
+++ b/gcc/cfgexpand.c
@@ -361,7 +361,7 @@ static bool has_short_buffer;
we can't do with expected alignment of the stack boundary. */
static unsigned int
-align_local_variable (tree decl)
+align_local_variable (tree decl, bool really_expand)
{
unsigned int align;
@@ -370,7 +370,12 @@ align_local_variable (tree decl)
else
{
align = LOCAL_DECL_ALIGNMENT (decl);
- SET_DECL_ALIGN (decl, align);
+ /* Don't change DECL_ALIGN when called from estimated_stack_frame_size.
+ That is done before IPA and could bump alignment based on host
+ backend even for offloaded code which wants different
+ LOCAL_DECL_ALIGNMENT. */
+ if (really_expand)
+ SET_DECL_ALIGN (decl, align);
}
return align / BITS_PER_UNIT;
}
@@ -418,7 +423,7 @@ alloc_stack_frame_space (poly_int64 size, unsigned HOST_WIDE_INT align)
/* Accumulate DECL into STACK_VARS. */
static void
-add_stack_var (tree decl)
+add_stack_var (tree decl, bool really_expand)
{
struct stack_var *v;
@@ -446,7 +451,7 @@ add_stack_var (tree decl)
variables that are simultaneously live. */
if (known_eq (v->size, 0U))
v->size = 1;
- v->alignb = align_local_variable (decl);
+ v->alignb = align_local_variable (decl, really_expand);
/* An alignment of zero can mightily confuse us later. */
gcc_assert (v->alignb != 0);
@@ -1323,7 +1328,7 @@ expand_one_stack_var_1 (tree var)
else
{
size = tree_to_poly_uint64 (DECL_SIZE_UNIT (var));
- byte_align = align_local_variable (var);
+ byte_align = align_local_variable (var, true);
}
/* We handle highly aligned variables in expand_stack_vars. */
@@ -1413,7 +1418,7 @@ expand_one_ssa_partition (tree var)
if (!use_register_for_decl (var))
{
if (defer_stack_allocation (var, true))
- add_stack_var (var);
+ add_stack_var (var, true);
else
expand_one_stack_var_1 (var);
return;
@@ -1695,14 +1700,14 @@ expand_one_var (tree var, bool toplevel, bool really_expand)
}
}
else if (defer_stack_allocation (var, toplevel))
- add_stack_var (origvar);
+ add_stack_var (origvar, really_expand);
else
{
if (really_expand)
{
if (lookup_attribute ("naked",
DECL_ATTRIBUTES (current_function_decl)))
- error ("cannot allocate stack for variable %q+D, naked function.",
+ error ("cannot allocate stack for variable %q+D, naked function",
var);
expand_one_stack_var (origvar);
@@ -2840,7 +2845,8 @@ tree_conflicts_with_clobbers_p (tree t, HARD_REG_SET *clobbered_regs)
if (overlap)
{
- error ("asm-specifier for variable %qE conflicts with asm clobber list",
+ error ("%<asm%> specifier for variable %qE conflicts with "
+ "%<asm%> clobber list",
DECL_NAME (overlap));
/* Reset registerness to stop multiple errors emitted for a single
@@ -3038,7 +3044,6 @@ expand_asm_stmt (gasm *stmt)
}
}
}
- unsigned nclobbers = clobber_rvec.length();
/* First pass over inputs and outputs checks validity and sets
mark_addressable if needed. */
@@ -3262,7 +3267,8 @@ expand_asm_stmt (gasm *stmt)
if (allows_reg && TYPE_MODE (type) != BLKmode)
op = force_reg (TYPE_MODE (type), op);
else if (!allows_mem)
- warning (0, "asm operand %d probably doesn%'t match constraints",
+ warning (0, "%<asm%> operand %d probably does not match "
+ "constraints",
i + noutputs);
else if (MEM_P (op))
{
@@ -3310,7 +3316,7 @@ expand_asm_stmt (gasm *stmt)
gcc_assert (constraints.length() == noutputs + ninputs);
/* But it certainly can adjust the clobbers. */
- nclobbers = clobber_rvec.length();
+ unsigned nclobbers = clobber_rvec.length ();
/* Third pass checks for easy conflicts. */
/* ??? Why are we doing this on trees instead of rtx. */
@@ -3445,11 +3451,13 @@ expand_asm_stmt (gasm *stmt)
tripping over the under-construction body. */
for (unsigned k = 0; k < noutputs; ++k)
if (reg_overlap_mentioned_p (clobbered_reg, output_rvec[k]))
- internal_error ("asm clobber conflict with output operand");
+ internal_error ("%<asm%> clobber conflict with "
+ "output operand");
for (unsigned k = 0; k < ninputs - ninout; ++k)
if (reg_overlap_mentioned_p (clobbered_reg, input_rvec[k]))
- internal_error ("asm clobber conflict with input operand");
+ internal_error ("%<asm%> clobber conflict with "
+ "input operand");
}
XVECEXP (body, 0, i++) = gen_rtx_CLOBBER (VOIDmode, clobbered_reg);
@@ -4378,7 +4386,11 @@ expand_debug_expr (tree exp)
op0 = DECL_RTL_IF_SET (exp);
/* This decl was probably optimized away. */
- if (!op0)
+ if (!op0
+ /* At least label RTXen are sometimes replaced by
+ NOTE_INSN_DELETED_LABEL. Any notes here are not
+ handled by copy_rtx. */
+ || NOTE_P (op0))
{
if (!VAR_P (exp)
|| DECL_EXTERNAL (exp)
@@ -5984,11 +5996,11 @@ construct_init_block (void)
{
first_block = e->dest;
redirect_edge_succ (e, init_block);
- e = make_single_succ_edge (init_block, first_block, flags);
+ make_single_succ_edge (init_block, first_block, flags);
}
else
- e = make_single_succ_edge (init_block, EXIT_BLOCK_PTR_FOR_FN (cfun),
- EDGE_FALLTHRU);
+ make_single_succ_edge (init_block, EXIT_BLOCK_PTR_FOR_FN (cfun),
+ EDGE_FALLTHRU);
update_bb_for_insn (init_block);
return init_block;
@@ -6564,37 +6576,27 @@ pass_expand::execute (function *fun)
split edges which edge insertions might do. */
rebuild_jump_labels (get_insns ());
- FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR_FOR_FN (fun),
- EXIT_BLOCK_PTR_FOR_FN (fun), next_bb)
+ /* If we have a single successor to the entry block, put the pending insns
+ after parm birth, but before NOTE_INSNS_FUNCTION_BEG. */
+ if (single_succ_p (ENTRY_BLOCK_PTR_FOR_FN (fun)))
{
- edge e;
- edge_iterator ei;
- for (ei = ei_start (bb->succs); (e = ei_safe_edge (ei)); )
+ edge e = single_succ_edge (ENTRY_BLOCK_PTR_FOR_FN (fun));
+ if (e->insns.r)
{
- if (e->insns.r)
- {
- rebuild_jump_labels_chain (e->insns.r);
- /* Put insns after parm birth, but before
- NOTE_INSNS_FUNCTION_BEG. */
- if (e->src == ENTRY_BLOCK_PTR_FOR_FN (fun)
- && single_succ_p (ENTRY_BLOCK_PTR_FOR_FN (fun)))
- {
- rtx_insn *insns = e->insns.r;
- e->insns.r = NULL;
- if (NOTE_P (parm_birth_insn)
- && NOTE_KIND (parm_birth_insn) == NOTE_INSN_FUNCTION_BEG)
- emit_insn_before_noloc (insns, parm_birth_insn, e->dest);
- else
- emit_insn_after_noloc (insns, parm_birth_insn, e->dest);
- }
- else
- commit_one_edge_insertion (e);
- }
+ rtx_insn *insns = e->insns.r;
+ e->insns.r = NULL;
+ rebuild_jump_labels_chain (insns);
+ if (NOTE_P (parm_birth_insn)
+ && NOTE_KIND (parm_birth_insn) == NOTE_INSN_FUNCTION_BEG)
+ emit_insn_before_noloc (insns, parm_birth_insn, e->dest);
else
- ei_next (&ei);
+ emit_insn_after_noloc (insns, parm_birth_insn, e->dest);
}
}
+ /* Otherwise, as well as for other edges, take the usual way. */
+ commit_edge_insertions ();
+
/* We're done expanding trees to RTL. */
currently_expanding_to_rtl = 0;
diff --git a/gcc/cfghooks.c b/gcc/cfghooks.c
index a1d603a..76183ec 100644
--- a/gcc/cfghooks.c
+++ b/gcc/cfghooks.c
@@ -32,6 +32,12 @@ along with GCC; see the file COPYING3. If not see
#include "tree-ssa.h"
#include "cfgloop.h"
+/* Disable warnings about missing quoting in GCC diagnostics. */
+#if __GNUC__ >= 10
+# pragma GCC diagnostic push
+# pragma GCC diagnostic ignored "-Wformat-diag"
+#endif
+
/* A pointer to one of the hooks containers. */
static struct cfg_hooks *cfg_hooks;
@@ -253,8 +259,6 @@ verify_flow_info (void)
err = 1;
}
- last_bb_seen = ENTRY_BLOCK_PTR_FOR_FN (cfun);
-
/* Clean up. */
free (last_visited);
free (edge_checksum);
@@ -1491,3 +1495,7 @@ profile_record_account_profile (profile_record *record)
cfg_hooks->account_profile_record (bb, record);
}
}
+
+#if __GNUC__ >= 10
+# pragma GCC diagnostic pop
+#endif
diff --git a/gcc/cfgloop.c b/gcc/cfgloop.c
index e115de6..f64326b 100644
--- a/gcc/cfgloop.c
+++ b/gcc/cfgloop.c
@@ -1363,6 +1363,15 @@ cancel_loop_tree (struct loop *loop)
cancel_loop (loop);
}
+/* Disable warnings about missing quoting in GCC diagnostics for
+ the verification errors. Their format strings don't follow GCC
+ diagnostic conventions and the calls are ultimately followed by
+ a deliberate ICE triggered by a failed assertion. */
+#if __GNUC__ >= 10
+# pragma GCC diagnostic push
+# pragma GCC diagnostic ignored "-Wformat-diag"
+#endif
+
/* Checks that information about loops is correct
-- sizes of loops are all right
-- results of get_loop_body really belong to the loop
@@ -1677,7 +1686,7 @@ verify_loop_structure (void)
if (eloops != 0)
{
- error ("wrong list of exited loops for edge %d->%d",
+ error ("wrong list of exited loops for edge %d->%d",
e->src->index, e->dest->index);
err = 1;
}
@@ -1712,6 +1721,10 @@ verify_loop_structure (void)
free_dominance_info (CDI_DOMINATORS);
}
+#if __GNUC__ >= 10
+# pragma GCC diagnostic pop
+#endif
+
/* Returns latch edge of LOOP. */
edge
loop_latch_edge (const struct loop *loop)
diff --git a/gcc/cfgloop.h b/gcc/cfgloop.h
index e82cd7a..2f8ab10 100644
--- a/gcc/cfgloop.h
+++ b/gcc/cfgloop.h
@@ -174,6 +174,9 @@ struct GTY ((chain_next ("%h.next"))) loop {
of the loop can be safely evaluated concurrently. */
int safelen;
+ /* Preferred vectorization factor for the loop if non-zero. */
+ int simdlen;
+
/* Constraints are generally set by consumers and affect certain
semantics of niter analyzer APIs. Currently the APIs affected are
number_of_iterations_exit* functions and their callers. One typical
diff --git a/gcc/cfgloopmanip.c b/gcc/cfgloopmanip.c
index bfee48e..b5f6a47 100644
--- a/gcc/cfgloopmanip.c
+++ b/gcc/cfgloopmanip.c
@@ -364,7 +364,6 @@ remove_path (edge e, bool *irred_invalidated,
for (i = 0; i < nrem; i++)
{
- bb = rem_bbs[i];
FOR_EACH_EDGE (ae, ei, rem_bbs[i]->succs)
if (ae->dest != EXIT_BLOCK_PTR_FOR_FN (cfun)
&& !bitmap_bit_p (seen, ae->dest->index))
@@ -1016,6 +1015,7 @@ copy_loop_info (struct loop *loop, struct loop *target)
target->nb_iterations_estimate = loop->nb_iterations_estimate;
target->estimate_state = loop->estimate_state;
target->safelen = loop->safelen;
+ target->simdlen = loop->simdlen;
target->constraints = loop->constraints;
target->can_be_parallel = loop->can_be_parallel;
target->warned_aggressive_loop_optimizations
diff --git a/gcc/cfgrtl.c b/gcc/cfgrtl.c
index e06fb8d..4853ce4 100644
--- a/gcc/cfgrtl.c
+++ b/gcc/cfgrtl.c
@@ -62,6 +62,12 @@ along with GCC; see the file COPYING3. If not see
#include "tree-pass.h"
#include "print-rtl.h"
+/* Disable warnings about missing quoting in GCC diagnostics. */
+#if __GNUC__ >= 10
+# pragma GCC diagnostic push
+# pragma GCC diagnostic ignored "-Wformat-diag"
+#endif
+
/* Holds the interesting leading and trailing notes for the function.
Only applicable if the CFG is in cfglayout mode. */
static GTY(()) rtx_insn *cfg_layout_function_footer;
@@ -2099,7 +2105,8 @@ commit_edge_insertions (void)
which will be done by fixup_partitions. */
fixup_partitions ();
- checking_verify_flow_info ();
+ if (!currently_expanding_to_rtl)
+ checking_verify_flow_info ();
FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR_FOR_FN (cfun),
EXIT_BLOCK_PTR_FOR_FN (cfun), next_bb)
@@ -2109,7 +2116,11 @@ commit_edge_insertions (void)
FOR_EACH_EDGE (e, ei, bb->succs)
if (e->insns.r)
- commit_one_edge_insertion (e);
+ {
+ if (currently_expanding_to_rtl)
+ rebuild_jump_labels_chain (e->insns.r);
+ commit_one_edge_insertion (e);
+ }
}
}
@@ -2962,7 +2973,6 @@ rtl_verify_bb_layout (void)
basic_block last_bb_seen = ENTRY_BLOCK_PTR_FOR_FN (cfun), curr_bb = NULL;
num_bb_notes = 0;
- last_bb_seen = ENTRY_BLOCK_PTR_FOR_FN (cfun);
for (x = rtx_first; x; x = NEXT_INSN (x))
{
@@ -5191,3 +5201,7 @@ struct cfg_hooks cfg_layout_rtl_cfg_hooks = {
};
#include "gt-cfgrtl.h"
+
+#if __GNUC__ >= 10
+# pragma GCC diagnostic pop
+#endif
diff --git a/gcc/cgraph.c b/gcc/cgraph.c
index b1b0b4c..d161db9 100644
--- a/gcc/cgraph.c
+++ b/gcc/cgraph.c
@@ -2714,8 +2714,6 @@ bool
cgraph_node::set_pure_flag (bool pure, bool looping)
{
struct set_pure_flag_info info = {pure, looping, false};
- if (!pure)
- looping = false;
call_for_symbol_thunks_and_aliases (set_pure_flag_1, &info, !pure, true);
return info.changed;
}
@@ -3095,6 +3093,15 @@ cgraph_edge::verify_corresponds_to_fndecl (tree decl)
return false;
}
+/* Disable warnings about missing quoting in GCC diagnostics for
+ the verification errors. Their format strings don't follow GCC
+ diagnostic conventions and the calls are ultimately followed by
+ one to internal_error. */
+#if __GNUC__ >= 10
+# pragma GCC diagnostic push
+# pragma GCC diagnostic ignored "-Wformat-diag"
+#endif
+
/* Verify cgraph nodes of given cgraph node. */
DEBUG_FUNCTION void
cgraph_node::verify_node (void)
@@ -3470,6 +3477,10 @@ cgraph_node::verify_cgraph_nodes (void)
node->verify ();
}
+#if __GNUC__ >= 10
+# pragma GCC diagnostic pop
+#endif
+
/* Walk the alias chain to return the function cgraph_node is alias of.
Walk through thunks, too.
When AVAILABILITY is non-NULL, get minimal availability in the chain.
diff --git a/gcc/cgraphunit.c b/gcc/cgraphunit.c
index 8bfbd0b..f4d6688 100644
--- a/gcc/cgraphunit.c
+++ b/gcc/cgraphunit.c
@@ -796,8 +796,8 @@ process_function_and_variable_attributes (cgraph_node *first,
/* redefining extern inline function makes it DECL_UNINLINABLE. */
&& !DECL_UNINLINABLE (decl))
warning_at (DECL_SOURCE_LOCATION (decl), OPT_Wattributes,
- "always_inline function might not be inlinable");
-
+ "%<always_inline%> function might not be inlinable");
+
process_common_attributes (node, decl);
}
for (vnode = symtab->first_variable (); vnode != first_var;
@@ -1790,7 +1790,6 @@ cgraph_node::expand_thunk (bool output_asm_thunks, bool force_gimple_thunk)
&& targetm.asm_out.can_output_mi_thunk (thunk_fndecl, fixed_offset,
virtual_value, alias))
{
- const char *fnname;
tree fn_block;
tree restype = TREE_TYPE (TREE_TYPE (thunk_fndecl));
@@ -1814,7 +1813,6 @@ cgraph_node::expand_thunk (bool output_asm_thunks, bool force_gimple_thunk)
= build_decl (DECL_SOURCE_LOCATION (thunk_fndecl),
RESULT_DECL, 0, restype);
DECL_CONTEXT (DECL_RESULT (thunk_fndecl)) = thunk_fndecl;
- fnname = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (thunk_fndecl));
/* The back end expects DECL_INITIAL to contain a BLOCK, so we
create one. */
@@ -1828,12 +1826,10 @@ cgraph_node::expand_thunk (bool output_asm_thunks, bool force_gimple_thunk)
insn_locations_init ();
set_curr_insn_location (DECL_SOURCE_LOCATION (thunk_fndecl));
prologue_location = curr_insn_location ();
- assemble_start_function (thunk_fndecl, fnname);
targetm.asm_out.output_mi_thunk (asm_out_file, thunk_fndecl,
fixed_offset, virtual_value, alias);
- assemble_end_function (thunk_fndecl, fnname);
insn_locations_finalize ();
init_insn_lengths ();
free_after_compilation (cfun);
diff --git a/gcc/collect-utils.c b/gcc/collect-utils.c
index 1b1b27c..75645b9 100644
--- a/gcc/collect-utils.c
+++ b/gcc/collect-utils.c
@@ -65,7 +65,7 @@ collect_wait (const char *prog, struct pex_obj *pex)
int status;
if (!pex_get_status (pex, 1, &status))
- fatal_error (input_location, "can%'t get program status: %m");
+ fatal_error (input_location, "cannot get program status: %m");
pex_free (pex);
if (response_file && !save_temps)
@@ -180,7 +180,7 @@ collect_execute (const char *prog, char **argv, const char *outname,
pex = pex_init (0, "collect2", NULL);
if (pex == NULL)
- fatal_error (input_location, "pex_init failed: %m");
+ fatal_error (input_location, "%<pex_init%> failed: %m");
errmsg = pex_run (pex, flags, argv[0], argv, outname,
errname, &err);
diff --git a/gcc/collect2.c b/gcc/collect2.c
index eb84f84..d6a7355 100644
--- a/gcc/collect2.c
+++ b/gcc/collect2.c
@@ -701,7 +701,8 @@ maybe_run_lto_and_relink (char **lto_ld_argv, char **object_lst,
size_t num_files;
if (!lto_wrapper)
- fatal_error (input_location, "COLLECT_LTO_WRAPPER must be set");
+ fatal_error (input_location, "environment variable "
+ "%<COLLECT_LTO_WRAPPER%> must be set");
num_lto_c_args++;
@@ -1396,7 +1397,7 @@ main (int argc, char **argv)
stream = fopen (list_filename, "r");
if (stream == NULL)
- fatal_error (input_location, "can%'t open %s: %m",
+ fatal_error (input_location, "cannot open %s: %m",
list_filename);
while (fgets (buf, sizeof buf, stream) != NULL)
@@ -2382,7 +2383,7 @@ is_lto_object_file (const char *prog_name)
return true;
if (errmsg)
- fatal_error (0, "%s: %s\n", errmsg, xstrerror (err));
+ fatal_error (0, "%s: %s", errmsg, xstrerror (err));
return false;
}
@@ -2448,7 +2449,7 @@ scan_prog_file (const char *prog_name, scanpass which_pass,
pex = pex_init (PEX_USE_PIPES, "collect2", NULL);
if (pex == NULL)
- fatal_error (input_location, "pex_init failed: %m");
+ fatal_error (input_location, "%<pex_init%> failed: %m");
errmsg = pex_run (pex, 0, nm_file_name, real_nm_argv, NULL, HOST_BIT_BUCKET,
&err);
@@ -2470,7 +2471,7 @@ scan_prog_file (const char *prog_name, scanpass which_pass,
inf = pex_read_output (pex, 0);
if (inf == NULL)
- fatal_error (input_location, "can%'t open nm output: %m");
+ fatal_error (input_location, "cannot open nm output: %m");
if (debug)
fprintf (stderr, "\nnm output with constructors/destructors.\n");
@@ -2639,7 +2640,7 @@ scan_libraries (const char *prog_name)
inf = pex_read_output (pex, 0);
if (inf == NULL)
- fatal_error (input_location, "can%'t open ldd output: %m");
+ fatal_error (input_location, "cannot open ldd output: %m");
if (debug)
notice ("\nldd output with constructors/destructors.\n");
diff --git a/gcc/combine.c b/gcc/combine.c
index 4de759a..1be922d 100644
--- a/gcc/combine.c
+++ b/gcc/combine.c
@@ -5909,14 +5909,6 @@ combine_simplify_rtx (rtx x, machine_mode op0_mode, int in_dest,
mode, VOIDmode,
cond, cop1),
mode);
- else
- return gen_rtx_IF_THEN_ELSE (mode,
- simplify_gen_relational (cond_code,
- mode,
- VOIDmode,
- cond,
- cop1),
- true_rtx, false_rtx);
code = GET_CODE (x);
op0_mode = VOIDmode;
@@ -6600,7 +6592,6 @@ simplify_if_then_else (rtx x)
|| reg_mentioned_p (true_rtx, false_rtx)
|| rtx_equal_p (false_rtx, XEXP (cond, 0))))
{
- true_code = reversed_comparison_code (cond, NULL);
SUBST (XEXP (x, 0), reversed_comparison (cond, GET_MODE (cond)));
SUBST (XEXP (x, 1), false_rtx);
SUBST (XEXP (x, 2), true_rtx);
diff --git a/gcc/common.opt b/gcc/common.opt
index d342c4f..41514df 100644
--- a/gcc/common.opt
+++ b/gcc/common.opt
@@ -1379,7 +1379,7 @@ Common Report Var(flag_ipa_sra) Init(0) Optimization
Perform interprocedural reduction of aggregates.
feliminate-unused-debug-symbols
-Common Report Var(flag_debug_only_used_symbols)
+Common Report Var(flag_debug_only_used_symbols) Init(1)
Perform unused symbol elimination in debug info.
feliminate-unused-debug-types
@@ -1437,6 +1437,10 @@ ffinite-math-only
Common Report Var(flag_finite_math_only) Optimization SetByCombined
Assume no NaNs or infinities are generated.
+ffinite-loops
+Common Report Var(flag_finite_loops) Optimization
+Assume that loops with an exit will terminate and not loop indefinitely.
+
ffixed-
Common Joined RejectNegative Var(common_deferred_options) Defer
-ffixed-<register> Mark <register> as being unavailable to the compiler.
@@ -1884,12 +1888,12 @@ Specify the algorithm to partition symbols and vars at linktime.
; The initial value of -1 comes from Z_DEFAULT_COMPRESSION in zlib.h.
flto-compression-level=
-Common Joined RejectNegative UInteger Var(flag_lto_compression_level) Init(-1) IntegerRange(0, 9)
--flto-compression-level=<number> Use zlib compression level <number> for IL.
+Common Joined RejectNegative UInteger Var(flag_lto_compression_level) Init(-1) IntegerRange(0, 19)
+-flto-compression-level=<number> Use zlib/zstd compression level <number> for IL.
flto-odr-type-merging
-Common Report Var(flag_lto_odr_type_mering) Init(1)
-Merge C++ types using One Definition Rule.
+Common Ignore
+Does nothing. Preserved for backward compatibility.
flto-report
Common Report Var(flag_lto_report) Init(0)
@@ -2092,6 +2096,10 @@ Common Joined RejectNegative Var(profile_data_prefix)
Set the top-level directory for storing the profile data.
The default is 'pwd'.
+fprofile-note=
+Common Joined RejectNegative Var(profile_note_location)
+Select the name for storing the profile note file.
+
fprofile-correction
Common Report Var(flag_profile_correction)
Enable correction of flow inconsistent profile data input.
diff --git a/gcc/common/config/aarch64/aarch64-common.c b/gcc/common/config/aarch64/aarch64-common.c
index bab3ab3..07c0325 100644
--- a/gcc/common/config/aarch64/aarch64-common.c
+++ b/gcc/common/config/aarch64/aarch64-common.c
@@ -170,9 +170,9 @@ aarch64_handle_option (struct gcc_options *opts,
struct aarch64_option_extension
{
const char *const name;
- const unsigned long flag_canonical;
- const unsigned long flags_on;
- const unsigned long flags_off;
+ const uint64_t flag_canonical;
+ const uint64_t flags_on;
+ const uint64_t flags_off;
const bool is_synthetic;
};
@@ -201,14 +201,14 @@ struct processor_name_to_arch
{
const std::string processor_name;
const enum aarch64_arch arch;
- const unsigned long flags;
+ const uint64_t flags;
};
struct arch_to_arch_name
{
const enum aarch64_arch arch;
const std::string arch_name;
- const unsigned long flags;
+ const uint64_t flags;
};
/* Map processor names to the architecture revision they implement and
@@ -238,7 +238,7 @@ static const struct arch_to_arch_name all_architectures[] =
a copy of the string is created and stored to INVALID_EXTENSION. */
enum aarch64_parse_opt_result
-aarch64_parse_extension (const char *str, unsigned long *isa_flags,
+aarch64_parse_extension (const char *str, uint64_t *isa_flags,
std::string *invalid_extension)
{
/* The extension string is parsed left to right. */
@@ -326,18 +326,21 @@ int opt_ext_cmp (const void* a, const void* b)
turns on as a dependency. As an example +dotprod turns on FL_DOTPROD and
FL_SIMD. As such the set of bits represented by this option is
{FL_DOTPROD, FL_SIMD}. */
- unsigned long total_flags_a = opt_a->flag_canonical & opt_a->flags_on;
- unsigned long total_flags_b = opt_b->flag_canonical & opt_b->flags_on;
+ uint64_t total_flags_a = opt_a->flag_canonical & opt_a->flags_on;
+ uint64_t total_flags_b = opt_b->flag_canonical & opt_b->flags_on;
int popcnt_a = popcount_hwi ((HOST_WIDE_INT)total_flags_a);
int popcnt_b = popcount_hwi ((HOST_WIDE_INT)total_flags_b);
int order = popcnt_b - popcnt_a;
/* If they have the same amount of bits set, give it a more
deterministic ordering by using the value of the bits themselves. */
- if (order == 0)
- return total_flags_b - total_flags_a;
+ if (order != 0)
+ return order;
- return order;
+ if (total_flags_a != total_flags_b)
+ return total_flags_a < total_flags_b ? 1 : -1;
+
+ return 0;
}
/* Implement TARGET_OPTION_INIT_STRUCT. */
@@ -373,9 +376,9 @@ aarch64_option_init_struct (struct gcc_options *opts ATTRIBUTE_UNUSED)
*/
static bool
-aarch64_contains_opt (unsigned long isa_flag_bits, opt_ext *opt)
+aarch64_contains_opt (uint64_t isa_flag_bits, opt_ext *opt)
{
- unsigned long flags_check
+ uint64_t flags_check
= opt->is_synthetic ? opt->flags_on : opt->flag_canonical;
return (isa_flag_bits & flags_check) == flags_check;
@@ -388,13 +391,13 @@ aarch64_contains_opt (unsigned long isa_flag_bits, opt_ext *opt)
that all the "+" flags come before the "+no" flags. */
std::string
-aarch64_get_extension_string_for_isa_flags (unsigned long isa_flags,
- unsigned long default_arch_flags)
+aarch64_get_extension_string_for_isa_flags (uint64_t isa_flags,
+ uint64_t default_arch_flags)
{
const struct aarch64_option_extension *opt = NULL;
std::string outstr = "";
- unsigned long isa_flag_bits = isa_flags;
+ uint64_t isa_flag_bits = isa_flags;
/* Pass one: Minimize the search space by reducing the set of options
to the smallest set that still turns on the same features as before in
@@ -538,7 +541,7 @@ aarch64_rewrite_selected_cpu (const char *name)
|| a_to_an->arch == aarch64_no_arch)
fatal_error (input_location, "unknown value %qs for %<-mcpu%>", name);
- unsigned long extensions = p_to_a->flags;
+ uint64_t extensions = p_to_a->flags;
aarch64_parse_extension (extension_str.c_str (), &extensions, NULL);
std::string outstr = a_to_an->arch_name
diff --git a/gcc/common/config/i386/i386-common.c b/gcc/common/config/i386/i386-common.c
index db5c3f8..a394f87 100644
--- a/gcc/common/config/i386/i386-common.c
+++ b/gcc/common/config/i386/i386-common.c
@@ -100,6 +100,7 @@ along with GCC; see the file COPYING3. If not see
#define OPTION_MASK_ISA_XSAVEC_SET \
(OPTION_MASK_ISA_XSAVEC | OPTION_MASK_ISA_XSAVE_SET)
#define OPTION_MASK_ISA_CLWB_SET OPTION_MASK_ISA_CLWB
+#define OPTION_MASK_ISA_AVX512VP2INTERSECT_SET OPTION_MASK_ISA_AVX512VP2INTERSECT
/* SSE4 includes both SSE4.1 and SSE4.2. -msse4 should be the same
as -msse4.2. */
@@ -156,6 +157,7 @@ along with GCC; see the file COPYING3. If not see
#define OPTION_MASK_ISA_MOVDIR64B_SET OPTION_MASK_ISA_MOVDIR64B
#define OPTION_MASK_ISA_WAITPKG_SET OPTION_MASK_ISA_WAITPKG
#define OPTION_MASK_ISA_CLDEMOTE_SET OPTION_MASK_ISA_CLDEMOTE
+#define OPTION_MASK_ISA_ENQCMD_SET OPTION_MASK_ISA_ENQCMD
/* Define a set of ISAs which aren't available when a given ISA is
disabled. MMX and SSE ISAs are handled separately. */
@@ -238,6 +240,8 @@ along with GCC; see the file COPYING3. If not see
#define OPTION_MASK_ISA_MOVDIR64B_UNSET OPTION_MASK_ISA_MOVDIR64B
#define OPTION_MASK_ISA_WAITPKG_UNSET OPTION_MASK_ISA_WAITPKG
#define OPTION_MASK_ISA_CLDEMOTE_UNSET OPTION_MASK_ISA_CLDEMOTE
+#define OPTION_MASK_ISA_ENQCMD_UNSET OPTION_MASK_ISA_ENQCMD
+#define OPTION_MASK_ISA_AVX512VP2INTERSECT_UNSET OPTION_MASK_ISA_AVX512VP2INTERSECT
/* SSE4 includes both SSE4.1 and SSE4.2. -mno-sse4 should the same
as -mno-sse4.1. */
@@ -280,7 +284,8 @@ along with GCC; see the file COPYING3. If not see
#define OPTION_MASK_ISA2_AVX512F_UNSET \
(OPTION_MASK_ISA_AVX512BF16_UNSET \
| OPTION_MASK_ISA_AVX5124FMAPS_UNSET \
- | OPTION_MASK_ISA_AVX5124VNNIW_UNSET)
+ | OPTION_MASK_ISA_AVX5124VNNIW_UNSET \
+ | OPTION_MASK_ISA_AVX512VP2INTERSECT_UNSET)
#define OPTION_MASK_ISA2_GENERAL_REGS_ONLY_UNSET \
(OPTION_MASK_ISA2_AVX512F_UNSET)
@@ -659,6 +664,19 @@ ix86_handle_option (struct gcc_options *opts,
}
return true;
+ case OPT_menqcmd:
+ if (value)
+ {
+ opts->x_ix86_isa_flags2 |= OPTION_MASK_ISA_ENQCMD_SET;
+ opts->x_ix86_isa_flags2_explicit |= OPTION_MASK_ISA_ENQCMD_SET;
+ }
+ else
+ {
+ opts->x_ix86_isa_flags2 &= ~OPTION_MASK_ISA_ENQCMD_UNSET;
+ opts->x_ix86_isa_flags2_explicit |= OPTION_MASK_ISA_ENQCMD_UNSET;
+ }
+ return true;
+
case OPT_mavx5124fmaps:
if (value)
{
@@ -865,6 +883,23 @@ ix86_handle_option (struct gcc_options *opts,
}
return true;
+ case OPT_mavx512vp2intersect:
+ if (value)
+ {
+ opts->x_ix86_isa_flags2 |= OPTION_MASK_ISA_AVX512VP2INTERSECT_SET;
+ opts->x_ix86_isa_flags2_explicit |=
+ OPTION_MASK_ISA_AVX512VP2INTERSECT_SET;
+ opts->x_ix86_isa_flags |= OPTION_MASK_ISA_AVX512F_SET;
+ opts->x_ix86_isa_flags_explicit |= OPTION_MASK_ISA_AVX512F_SET;
+ }
+ else
+ {
+ opts->x_ix86_isa_flags2 &= ~OPTION_MASK_ISA_AVX512VP2INTERSECT_UNSET;
+ opts->x_ix86_isa_flags2_explicit |=
+ OPTION_MASK_ISA_AVX512VP2INTERSECT_UNSET;
+ }
+ return true;
+
case OPT_mfma:
if (value)
{
diff --git a/gcc/common/config/pru/pru-common.c b/gcc/common/config/pru/pru-common.c
new file mode 100644
index 0000000..7d1e934
--- /dev/null
+++ b/gcc/common/config/pru/pru-common.c
@@ -0,0 +1,36 @@
+/* Common hooks for TI PRU
+ Copyright (C) 2014-2019 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 3, or (at your option)
+any later version.
+
+GCC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3. If not see
+<http://www.gnu.org/licenses/>. */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "diagnostic-core.h"
+#include "tm.h"
+#include "common/common-target.h"
+#include "common/common-target-def.h"
+#include "opts.h"
+#include "flags.h"
+
+#undef TARGET_DEFAULT_TARGET_FLAGS
+#define TARGET_DEFAULT_TARGET_FLAGS (MASK_OPT_LOOP)
+
+#undef TARGET_EXCEPT_UNWIND_INFO
+#define TARGET_EXCEPT_UNWIND_INFO sjlj_except_unwind_info
+
+struct gcc_targetm_common targetm_common = TARGETM_COMMON_INITIALIZER;
diff --git a/gcc/config.gcc b/gcc/config.gcc
index b5a313f..c281c41 100644
--- a/gcc/config.gcc
+++ b/gcc/config.gcc
@@ -247,8 +247,7 @@ md_file=
# Obsolete configurations.
case ${target} in
- *-*-solaris2.10* \
- | spu*-*-* \
+ spu*-*-* \
| tile*-*-* \
)
if test "x$enable_obsolete" != xyes; then
@@ -293,6 +292,7 @@ case ${target} in
| *-*-solaris2 \
| *-*-solaris2.[0-9] \
| *-*-solaris2.[0-9].* \
+ | *-*-solaris2.10* \
| *-*-sysv* \
| vax-*-vms* \
)
@@ -407,7 +407,8 @@ i[34567]86-*-*)
avx512vnnivlintrin.h vaesintrin.h vpclmulqdqintrin.h
avx512vpopcntdqvlintrin.h avx512bitalgintrin.h
pconfigintrin.h wbnoinvdintrin.h movdirintrin.h
- waitpkgintrin.h cldemoteintrin.h avx512bf16vlintrin.h avx512bf16intrin.h"
+ waitpkgintrin.h cldemoteintrin.h avx512bf16vlintrin.h avx512bf16intrin.h
+ enqcmdintrin.h avx512vp2intersectintrin.h avx512vp2intersectvlintrin.h"
;;
x86_64-*-*)
cpu_type=i386
@@ -439,7 +440,8 @@ x86_64-*-*)
avx512vnnivlintrin.h vaesintrin.h vpclmulqdqintrin.h
avx512vpopcntdqvlintrin.h avx512bitalgintrin.h
pconfigintrin.h wbnoinvdintrin.h movdirintrin.h
- waitpkgintrin.h cldemoteintrin.h avx512bf16vlintrin.h avx512bf16intrin.h"
+ waitpkgintrin.h cldemoteintrin.h avx512bf16vlintrin.h avx512bf16intrin.h
+ enqcmdintrin.h avx512vp2intersectintrin.h avx512vp2intersectvlintrin.h"
;;
ia64-*-*)
extra_headers=ia64intrin.h
@@ -497,7 +499,7 @@ or1k*-*-*)
;;
powerpc*-*-*)
cpu_type=rs6000
- extra_objs="rs6000-string.o rs6000-p8swap.o"
+ extra_objs="rs6000-string.o rs6000-p8swap.o rs6000-logue.o"
extra_headers="ppc-asm.h altivec.h htmintrin.h htmxlintrin.h"
extra_headers="${extra_headers} bmi2intrin.h bmiintrin.h"
extra_headers="${extra_headers} xmmintrin.h mm_malloc.h emmintrin.h"
@@ -506,11 +508,15 @@ powerpc*-*-*)
extra_headers="${extra_headers} ppu_intrinsics.h spu2vmx.h vec_types.h si2vmx.h"
extra_headers="${extra_headers} amo.h"
case x$with_cpu in
- xpowerpc64|xdefault64|x6[23]0|x970|xG5|xpower[3456789]|xpower6x|xrs64a|xcell|xa2|xe500mc64|xe5500|xe6500)
+ xpowerpc64|xdefault64|x6[23]0|x970|xG5|xpower[3456789]|xpower6x|xrs64a|xcell|xa2|xe500mc64|xe5500|xe6500|xfuture)
cpu_is_64bit=yes
;;
esac
extra_options="${extra_options} g.opt fused-madd.opt rs6000/rs6000-tables.opt"
+ target_gtfiles="$target_gtfiles \$(srcdir)/config/rs6000/rs6000-logue.c"
+ ;;
+pru-*-*)
+ cpu_type=pru
;;
riscv*)
cpu_type=riscv
@@ -519,7 +525,8 @@ riscv*)
;;
rs6000*-*-*)
extra_options="${extra_options} g.opt fused-madd.opt rs6000/rs6000-tables.opt"
- extra_objs="rs6000-string.o rs6000-p8swap.o"
+ extra_objs="rs6000-string.o rs6000-p8swap.o rs6000-logue.o"
+ target_gtfiles="$target_gtfiles \$(srcdir)/config/rs6000/rs6000-logue.c"
;;
sparc*-*-*)
cpu_type=sparc
@@ -975,7 +982,7 @@ esac
case ${target} in
aarch64*-*-elf | aarch64*-*-fuchsia* | aarch64*-*-rtems*)
tm_file="${tm_file} dbxelf.h elfos.h newlib-stdint.h"
- tm_file="${tm_file} aarch64/aarch64-elf.h aarch64/aarch64-elf-raw.h"
+ tm_file="${tm_file} aarch64/aarch64-elf.h aarch64/aarch64-errata.h aarch64/aarch64-elf-raw.h"
tmake_file="${tmake_file} aarch64/t-aarch64"
case $target in
aarch64-*-elf*)
@@ -1012,13 +1019,19 @@ aarch64*-*-elf | aarch64*-*-fuchsia* | aarch64*-*-rtems*)
;;
aarch64*-*-freebsd*)
tm_file="${tm_file} dbxelf.h elfos.h ${fbsd_tm_file}"
- tm_file="${tm_file} aarch64/aarch64-elf.h aarch64/aarch64-freebsd.h"
+ tm_file="${tm_file} aarch64/aarch64-elf.h aarch64/aarch64-errata.h aarch64/aarch64-freebsd.h"
tmake_file="${tmake_file} aarch64/t-aarch64 aarch64/t-aarch64-freebsd"
tm_defines="${tm_defines} TARGET_DEFAULT_ASYNC_UNWIND_TABLES=1"
;;
+aarch64*-*-netbsd*)
+ tm_file="${tm_file} dbxelf.h elfos.h ${nbsd_tm_file}"
+ tm_file="${tm_file} aarch64/aarch64-elf.h aarch64/aarch64-errata.h aarch64/aarch64-netbsd.h"
+ tmake_file="${tmake_file} aarch64/t-aarch64 aarch64/t-aarch64-netbsd"
+ extra_options="${extra_options} netbsd.opt netbsd-elf.opt"
+ ;;
aarch64*-*-linux*)
tm_file="${tm_file} dbxelf.h elfos.h gnu-user.h linux.h glibc-stdint.h"
- tm_file="${tm_file} aarch64/aarch64-elf.h aarch64/aarch64-linux.h"
+ tm_file="${tm_file} aarch64/aarch64-elf.h aarch64/aarch64-errata.h aarch64/aarch64-linux.h"
tmake_file="${tmake_file} aarch64/t-aarch64 aarch64/t-aarch64-linux"
tm_defines="${tm_defines} TARGET_DEFAULT_ASYNC_UNWIND_TABLES=1"
case $target in
@@ -1157,10 +1170,35 @@ arm*-*-freebsd*) # ARM FreeBSD EABI
with_tls=${with_tls:-gnu}
;;
arm*-*-netbsdelf*)
- tm_file="dbxelf.h elfos.h ${nbsd_tm_file} arm/elf.h arm/aout.h ${tm_file} arm/netbsd-elf.h"
- extra_options="${extra_options} netbsd.opt netbsd-elf.opt"
- tmake_file="${tmake_file} arm/t-arm"
target_cpu_cname="strongarm"
+ tmake_file="${tmake_file} arm/t-arm"
+ tm_file="dbxelf.h elfos.h ${nbsd_tm_file} arm/elf.h"
+ extra_options="${extra_options} netbsd.opt netbsd-elf.opt"
+ case ${target} in
+ arm*eb-*) tm_defines="${tm_defines} TARGET_BIG_ENDIAN_DEFAULT=1" ;;
+ esac
+ case ${target} in
+ arm*-*-netbsdelf-*eabi*)
+ tm_file="$tm_file arm/bpabi.h arm/netbsd-elf.h arm/netbsd-eabi.h"
+ tmake_file="$tmake_file arm/t-bpabi arm/t-netbsdeabi"
+ ;;
+ *)
+ tm_file="$tm_file arm/netbsd-elf.h"
+ tmake_file="$tmake_file arm/t-netbsd"
+ ;;
+ esac
+ tm_file="${tm_file} arm/aout.h arm/arm.h"
+ case ${target} in
+ arm*-*-netbsdelf-*eabihf*)
+ # Hard-float requires at least Arm v5te
+ target_cpu_cname="arm10e"
+ tm_defines="${tm_defines} TARGET_DEFAULT_FLOAT_ABI=ARM_FLOAT_ABI_HARD"
+ ;;
+ esac
+ case ${target} in
+ armv6*) target_cpu_cname="arm1176jzf-s";;
+ armv7*) target_cpu_cname="generic-armv7-a";;
+ esac
;;
arm*-*-linux-*) # ARM GNU/Linux with ELF
tm_file="dbxelf.h elfos.h gnu-user.h linux.h linux-android.h glibc-stdint.h arm/elf.h arm/linux-gas.h arm/linux-elf.h"
@@ -1424,6 +1462,9 @@ amdgcn-*-amdhsa)
extra_programs="${extra_programs} mkoffload\$(exeext)"
tm_file="${tm_file} gcn/offload.h"
fi
+ # Force .init_array support.
+ gcc_cv_initfini_array=yes
+ thread_file=gcn
;;
moxie-*-elf)
gas=yes
@@ -1794,7 +1835,7 @@ i[34567]86-*-rtems*)
tm_file="${tm_file} i386/unix.h i386/att.h dbxelf.h elfos.h i386/i386elf.h i386/rtemself.h rtems.h newlib-stdint.h"
tmake_file="${tmake_file} i386/t-rtems"
;;
-i[34567]86-*-solaris2* | x86_64-*-solaris2.1[0-9]*)
+i[34567]86-*-solaris2* | x86_64-*-solaris2*)
# Set default arch_32 to pentium4, tune_32 to generic like the other
# i386 targets, although config.guess defaults to i386-pc-solaris2*.
with_arch_32=${with_arch_32:-pentium4}
@@ -2586,13 +2627,11 @@ powerpc-*-darwin*)
;;
esac
tmake_file="${tmake_file} t-slibgcc"
- extra_headers=altivec.h
;;
powerpc64-*-darwin*)
extra_options="${extra_options} ${cpu_type}/darwin.opt"
tmake_file="${tmake_file} ${cpu_type}/t-darwin64 t-slibgcc"
tm_file="${tm_file} ${cpu_type}/darwin8.h ${cpu_type}/darwin64.h"
- extra_headers=altivec.h
;;
powerpc*-*-freebsd*)
tm_file="${tm_file} dbxelf.h elfos.h gnu-user.h ${fbsd_tm_file} rs6000/sysv4.h"
@@ -2760,6 +2799,12 @@ powerpcle-*-eabi*)
extra_options="${extra_options} rs6000/sysv4.opt"
use_gcc_stdint=wrap
;;
+pru*-*-*)
+ tm_file="elfos.h newlib-stdint.h ${tm_file}"
+ tmake_file="${tmake_file} pru/t-pru"
+ extra_objs="pru-pragma.o pru-passes.o"
+ use_gcc_stdint=wrap
+ ;;
rs6000-ibm-aix6.* | powerpc-ibm-aix6.*)
tm_file="${tm_file} rs6000/aix.h rs6000/aix61.h rs6000/xcoff.h rs6000/aix-stdint.h"
tmake_file="rs6000/t-aix52 t-slibgcc"
@@ -2797,6 +2842,11 @@ rl78-*-elf*)
rx-*-elf*)
tm_file="dbxelf.h elfos.h newlib-stdint.h ${tm_file}"
tmake_file="${tmake_file} rx/t-rx"
+ extra_options="${extra_options} rx/elf.opt"
+ ;;
+rx-*-linux*)
+ tm_file="elfos.h linux.h glibc-stdint.h rx/linux.h ../../libgcc/config/rx/rx-abi.h"
+ tmake_file="${tmake_file} rx/t-linux"
;;
s390-*-linux*)
tm_file="s390/s390.h dbxelf.h elfos.h gnu-user.h linux.h glibc-stdint.h s390/linux.h"
@@ -3953,12 +4003,13 @@ case "${target}" in
# see if --with-fpu matches any of the supported FPUs
if [ x"$with_fpu" != x ] ; then
+ val=$with_fpu
fpu=`awk -f ${srcdir}/config/arm/parsecpu.awk \
- -v cmd="chkfpu $with_fpu" \
+ -v cmd="chkfpu $val" \
${srcdir}/config/arm/arm-cpus.in`
- if [ "$fpu" = "error"]
+ if [ "$fpu" = "error" ]
then
- echo "Unknown target in --with-$which=$val" 1>&2
+ echo "Unknown target in --with-fpu=$val" 1>&2
exit 1
fi
fi
@@ -4118,7 +4169,7 @@ case "${target}" in
for which in arch tune; do
eval "val=\$with_$which"
case ${val} in
- "" | carrizo | fiji | gfx900 )
+ "" | carrizo | fiji | gfx900 | gfx906 )
# OK
;;
*)
@@ -4914,7 +4965,7 @@ case ${target} in
i[34567]86-*-msdosdjgpp*)
tmake_file="${tmake_file} i386/t-djgpp"
;;
- i[34567]86-*-solaris2* | x86_64-*-solaris2.1[0-9]*)
+ i[34567]86-*-solaris2* | x86_64-*-solaris2*)
;;
i[34567]86-*-cygwin* | x86_64-*-cygwin*)
;;
diff --git a/gcc/config.host b/gcc/config.host
index 816a0f0..82409e3 100644
--- a/gcc/config.host
+++ b/gcc/config.host
@@ -107,7 +107,7 @@ case ${host} in
;;
esac
;;
- arm*-*-freebsd* | arm*-*-linux* | arm*-*-fuchsia*)
+ arm*-*-freebsd* | arm*-*-netbsd* | arm*-*-linux* | arm*-*-fuchsia*)
case ${target} in
arm*-*-*)
host_extra_gcc_objs="driver-arm.o"
@@ -213,7 +213,7 @@ case ${host} in
out_host_hook_obj=host-hpux.o
host_xmake_file="${host_xmake_file} x-hpux"
;;
- i[34567]86-*-solaris2* | x86_64-*-solaris2.1[0-9]*)
+ i[34567]86-*-solaris2* | x86_64-*-solaris2*)
out_host_hook_obj=host-solaris.o
host_xmake_file="${host_xmake_file} x-solaris"
;;
diff --git a/gcc/config.in b/gcc/config.in
index a718cea..13fd795 100644
--- a/gcc/config.in
+++ b/gcc/config.in
@@ -1926,6 +1926,12 @@
#endif
+/* Define if you have a working <zstd.h> header file. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_ZSTD_H
+#endif
+
+
/* Define if isl is in use. */
#ifndef USED_FOR_TARGET
#undef HAVE_isl
diff --git a/gcc/config/aarch64/aarch64-bti-insert.c b/gcc/config/aarch64/aarch64-bti-insert.c
index e519a0f..db8ebb1 100644
--- a/gcc/config/aarch64/aarch64-bti-insert.c
+++ b/gcc/config/aarch64/aarch64-bti-insert.c
@@ -106,7 +106,9 @@ aarch64_pac_insn_p (rtx x)
int unspec_val = XINT (sub, 1);
switch (unspec_val)
{
- case UNSPEC_PACISP:
+ case UNSPEC_PACIASP:
+ /* fall-through. */
+ case UNSPEC_PACIBSP:
return true;
default:
diff --git a/gcc/config/aarch64/aarch64-builtins.c b/gcc/config/aarch64/aarch64-builtins.c
index d7b1b7b..549a6c2 100644
--- a/gcc/config/aarch64/aarch64-builtins.c
+++ b/gcc/config/aarch64/aarch64-builtins.c
@@ -432,6 +432,8 @@ enum aarch64_builtins
/* ARMv8.3-A Pointer Authentication Builtins. */
AARCH64_PAUTH_BUILTIN_AUTIA1716,
AARCH64_PAUTH_BUILTIN_PACIA1716,
+ AARCH64_PAUTH_BUILTIN_AUTIB1716,
+ AARCH64_PAUTH_BUILTIN_PACIB1716,
AARCH64_PAUTH_BUILTIN_XPACLRI,
/* Special cased Armv8.3-A Complex FMA by Lane quad Builtins. */
AARCH64_SIMD_FCMLA_LANEQ_BUILTIN_BASE,
@@ -1051,6 +1053,14 @@ aarch64_init_pauth_hint_builtins (void)
= add_builtin_function ("__builtin_aarch64_pacia1716", ftype_pointer_auth,
AARCH64_PAUTH_BUILTIN_PACIA1716, BUILT_IN_MD, NULL,
NULL_TREE);
+ aarch64_builtin_decls[AARCH64_PAUTH_BUILTIN_AUTIB1716]
+ = add_builtin_function ("__builtin_aarch64_autib1716", ftype_pointer_auth,
+ AARCH64_PAUTH_BUILTIN_AUTIB1716, BUILT_IN_MD, NULL,
+ NULL_TREE);
+ aarch64_builtin_decls[AARCH64_PAUTH_BUILTIN_PACIB1716]
+ = add_builtin_function ("__builtin_aarch64_pacib1716", ftype_pointer_auth,
+ AARCH64_PAUTH_BUILTIN_PACIB1716, BUILT_IN_MD, NULL,
+ NULL_TREE);
aarch64_builtin_decls[AARCH64_PAUTH_BUILTIN_XPACLRI]
= add_builtin_function ("__builtin_aarch64_xpaclri", ftype_pointer_strip,
AARCH64_PAUTH_BUILTIN_XPACLRI, BUILT_IN_MD, NULL,
@@ -1540,6 +1550,8 @@ aarch64_expand_builtin (tree exp,
case AARCH64_PAUTH_BUILTIN_AUTIA1716:
case AARCH64_PAUTH_BUILTIN_PACIA1716:
+ case AARCH64_PAUTH_BUILTIN_AUTIB1716:
+ case AARCH64_PAUTH_BUILTIN_PACIB1716:
case AARCH64_PAUTH_BUILTIN_XPACLRI:
arg0 = CALL_EXPR_ARG (exp, 0);
op0 = force_reg (Pmode, expand_normal (arg0));
@@ -1563,8 +1575,24 @@ aarch64_expand_builtin (tree exp,
{
tree arg1 = CALL_EXPR_ARG (exp, 1);
rtx op1 = force_reg (Pmode, expand_normal (arg1));
- icode = (fcode == AARCH64_PAUTH_BUILTIN_PACIA1716
- ? CODE_FOR_paci1716 : CODE_FOR_auti1716);
+ switch (fcode)
+ {
+ case AARCH64_PAUTH_BUILTIN_AUTIA1716:
+ icode = CODE_FOR_autia1716;
+ break;
+ case AARCH64_PAUTH_BUILTIN_AUTIB1716:
+ icode = CODE_FOR_autib1716;
+ break;
+ case AARCH64_PAUTH_BUILTIN_PACIA1716:
+ icode = CODE_FOR_pacia1716;
+ break;
+ case AARCH64_PAUTH_BUILTIN_PACIB1716:
+ icode = CODE_FOR_pacib1716;
+ break;
+ default:
+ icode = 0;
+ gcc_unreachable ();
+ }
rtx x16_reg = gen_rtx_REG (Pmode, R16_REGNUM);
rtx x17_reg = gen_rtx_REG (Pmode, R17_REGNUM);
diff --git a/gcc/config/aarch64/aarch64-c.c b/gcc/config/aarch64/aarch64-c.c
index 6d5acb0..5af65b1 100644
--- a/gcc/config/aarch64/aarch64-c.c
+++ b/gcc/config/aarch64/aarch64-c.c
@@ -146,6 +146,7 @@ aarch64_update_cpp_builtins (cpp_reader *pfile)
bits = 0;
builtin_define_with_int_value ("__ARM_FEATURE_SVE_BITS", bits);
}
+ aarch64_def_or_undef (TARGET_SVE2, "__ARM_FEATURE_SVE2", pfile);
aarch64_def_or_undef (TARGET_LSE, "__ARM_FEATURE_ATOMICS", pfile);
aarch64_def_or_undef (TARGET_AES, "__ARM_FEATURE_AES", pfile);
diff --git a/gcc/config/aarch64/aarch64-elf-raw.h b/gcc/config/aarch64/aarch64-elf-raw.h
index bbebd0e..8fe7b37 100644
--- a/gcc/config/aarch64/aarch64-elf-raw.h
+++ b/gcc/config/aarch64/aarch64-elf-raw.h
@@ -27,22 +27,6 @@
" crtend%O%s crtn%O%s " \
"%{Ofast|ffast-math|funsafe-math-optimizations:crtfastmath.o%s}"
-#if TARGET_FIX_ERR_A53_835769_DEFAULT
-#define CA53_ERR_835769_SPEC \
- " %{!mno-fix-cortex-a53-835769:--fix-cortex-a53-835769}"
-#else
-#define CA53_ERR_835769_SPEC \
- " %{mfix-cortex-a53-835769:--fix-cortex-a53-835769}"
-#endif
-
-#if TARGET_FIX_ERR_A53_843419_DEFAULT
-#define CA53_ERR_843419_SPEC \
- " %{!mno-fix-cortex-a53-843419:--fix-cortex-a53-843419}"
-#else
-#define CA53_ERR_843419_SPEC \
- " %{mfix-cortex-a53-843419:--fix-cortex-a53-843419}"
-#endif
-
#ifndef LINK_SPEC
#define LINK_SPEC "%{h*} \
%{static:-Bstatic} \
@@ -51,8 +35,7 @@
%{!static:%{rdynamic:-export-dynamic}} \
%{mbig-endian:-EB} %{mlittle-endian:-EL} -X \
-maarch64elf%{mabi=ilp32*:32}%{mbig-endian:b}" \
- CA53_ERR_835769_SPEC \
- CA53_ERR_843419_SPEC
+ AARCH64_ERRATA_LINK_SPEC
#endif
#endif /* GCC_AARCH64_ELF_RAW_H */
diff --git a/gcc/config/aarch64/aarch64-errata.h b/gcc/config/aarch64/aarch64-errata.h
new file mode 100644
index 0000000..8f06253
--- /dev/null
+++ b/gcc/config/aarch64/aarch64-errata.h
@@ -0,0 +1,44 @@
+/* Machine description for AArch64 architecture.
+ Copyright (C) 2009-2019 Free Software Foundation, Inc.
+ Contributed by ARM Ltd.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3, or (at your option)
+ any later version.
+
+ GCC is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GCC; see the file COPYING3. If not see
+ <http://www.gnu.org/licenses/>. */
+
+#ifndef GCC_AARCH64_ERRATA_H
+#define GCC_AARCH64_ERRATA_H
+
+#if TARGET_FIX_ERR_A53_835769_DEFAULT
+#define CA53_ERR_835769_SPEC \
+ " %{!mno-fix-cortex-a53-835769:--fix-cortex-a53-835769}"
+#else
+#define CA53_ERR_835769_SPEC \
+ " %{mfix-cortex-a53-835769:--fix-cortex-a53-835769}"
+#endif
+
+#if TARGET_FIX_ERR_A53_843419_DEFAULT
+#define CA53_ERR_843419_SPEC \
+ " %{!mno-fix-cortex-a53-843419:--fix-cortex-a53-843419}"
+#else
+#define CA53_ERR_843419_SPEC \
+ " %{mfix-cortex-a53-843419:--fix-cortex-a53-843419}"
+#endif
+
+#define AARCH64_ERRATA_LINK_SPEC \
+ CA53_ERR_835769_SPEC \
+ CA53_ERR_843419_SPEC
+
+#endif /* GCC_AARCH64_ERRATA_H */
diff --git a/gcc/config/aarch64/aarch64-freebsd.h b/gcc/config/aarch64/aarch64-freebsd.h
index 899e6f9..7a3e89b 100644
--- a/gcc/config/aarch64/aarch64-freebsd.h
+++ b/gcc/config/aarch64/aarch64-freebsd.h
@@ -46,26 +46,8 @@
-X" SUBTARGET_EXTRA_LINK_SPEC " \
%{mbig-endian:-EB} %{mlittle-endian:-EL}"
-#if TARGET_FIX_ERR_A53_835769_DEFAULT
-#define CA53_ERR_835769_SPEC \
- " %{!mno-fix-cortex-a53-835769:--fix-cortex-a53-835769}"
-#else
-#define CA53_ERR_835769_SPEC \
- " %{mfix-cortex-a53-835769:--fix-cortex-a53-835769}"
-#endif
-
-#ifdef TARGET_FIX_ERR_A53_843419_DEFAULT
-#define CA53_ERR_843419_SPEC \
- " %{!mno-fix-cortex-a53-843419:--fix-cortex-a53-843419}"
-#else
-#define CA53_ERR_843419_SPEC \
- " %{mfix-cortex-a53-843419:--fix-cortex-a53-843419}"
-#endif
-
#undef LINK_SPEC
-#define LINK_SPEC FBSD_TARGET_LINK_SPEC \
- CA53_ERR_835769_SPEC \
- CA53_ERR_843419_SPEC
+#define LINK_SPEC FBSD_TARGET_LINK_SPEC AARCH64_ERRATA_LINK_SPEC
#define GNU_USER_TARGET_MATHFILE_SPEC \
"%{Ofast|ffast-math|funsafe-math-optimizations:crtfastmath.o%s}"
diff --git a/gcc/config/aarch64/aarch64-linux.h b/gcc/config/aarch64/aarch64-linux.h
index 5e8b34d..6ff2163 100644
--- a/gcc/config/aarch64/aarch64-linux.h
+++ b/gcc/config/aarch64/aarch64-linux.h
@@ -46,25 +46,8 @@
%{mbig-endian:-EB} %{mlittle-endian:-EL} \
-maarch64linux%{mabi=ilp32:32}%{mbig-endian:b}"
-#if TARGET_FIX_ERR_A53_835769_DEFAULT
-#define CA53_ERR_835769_SPEC \
- " %{!mno-fix-cortex-a53-835769:--fix-cortex-a53-835769}"
-#else
-#define CA53_ERR_835769_SPEC \
- " %{mfix-cortex-a53-835769:--fix-cortex-a53-835769}"
-#endif
-
-#if TARGET_FIX_ERR_A53_843419_DEFAULT
-#define CA53_ERR_843419_SPEC \
- " %{!mno-fix-cortex-a53-843419:--fix-cortex-a53-843419}"
-#else
-#define CA53_ERR_843419_SPEC \
- " %{mfix-cortex-a53-843419:--fix-cortex-a53-843419}"
-#endif
-
-#define LINK_SPEC LINUX_TARGET_LINK_SPEC \
- CA53_ERR_835769_SPEC \
- CA53_ERR_843419_SPEC
+
+#define LINK_SPEC LINUX_TARGET_LINK_SPEC AARCH64_ERRATA_LINK_SPEC
#define GNU_USER_TARGET_MATHFILE_SPEC \
"%{Ofast|ffast-math|funsafe-math-optimizations:crtfastmath.o%s}"
diff --git a/gcc/config/aarch64/aarch64-modes.def b/gcc/config/aarch64/aarch64-modes.def
index 14c1a43..e034ffc 100644
--- a/gcc/config/aarch64/aarch64-modes.def
+++ b/gcc/config/aarch64/aarch64-modes.def
@@ -33,6 +33,8 @@
CC_MODE (CCFP);
CC_MODE (CCFPE);
CC_MODE (CC_SWP);
+CC_MODE (CC_NZC); /* Only N, Z and C bits of condition flags are valid.
+ (Used with SVE predicate tests.) */
CC_MODE (CC_NZ); /* Only N and Z bits of condition flags are valid. */
CC_MODE (CC_Z); /* Only Z bit of condition flags is valid. */
CC_MODE (CC_C); /* C represents unsigned overflow of a simple addition. */
diff --git a/gcc/config/aarch64/aarch64-netbsd.h b/gcc/config/aarch64/aarch64-netbsd.h
new file mode 100644
index 0000000..e6c9264
--- /dev/null
+++ b/gcc/config/aarch64/aarch64-netbsd.h
@@ -0,0 +1,63 @@
+/* Definitions for AArch64 running NetBSD
+ Copyright (C) 2016-2019 Free Software Foundation, Inc.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3, or (at your option)
+ any later version.
+
+ GCC is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GCC; see the file COPYING3. If not see
+ <http://www.gnu.org/licenses/>. */
+
+#ifndef GCC_AARCH64_NETBSD_H
+#define GCC_AARCH64_NETBSD_H
+
+#define TARGET_LINKER_BIG_EMULATION "aarch64nbsdb"
+#define TARGET_LINKER_LITTLE_EMULATION "aarch64nbsd"
+
+#if TARGET_BIG_ENDIAN_DEFAULT
+#define TARGET_LINKER_EMULATION TARGET_LINKER_BIG_EMULATION
+#else
+#define TARGET_LINKER_EMULATION TARGET_LINKER_LITTLE_EMULATION
+#endif
+
+#undef SUBTARGET_EXTRA_LINK_SPEC
+#define SUBTARGET_EXTRA_LINK_SPEC " -m" TARGET_LINKER_EMULATION
+
+#define NETBSD_ENTRY_POINT "__start"
+
+#define NETBSD_TARGET_LINK_SPEC "%{h*} " \
+ "-X %{mbig-endian:-EB -m " TARGET_LINKER_BIG_EMULATION "} " \
+ "%{mlittle-endian:-EL -m " TARGET_LINKER_LITTLE_EMULATION "} " \
+ "%(netbsd_link_spec)"
+
+#undef LINK_SPEC
+#define LINK_SPEC NETBSD_LINK_SPEC_ELF \
+ NETBSD_TARGET_LINK_SPEC \
+ AARCH64_ERRATA_LINK_SPEC
+
+#undef TARGET_OS_CPP_BUILTINS
+#define TARGET_OS_CPP_BUILTINS() \
+ do \
+ { \
+ NETBSD_OS_CPP_BUILTINS_ELF(); \
+ } \
+ while (0)
+
+#undef SUBTARGET_CPP_SPEC
+#define SUBTARGET_CPP_SPEC NETBSD_CPP_SPEC
+
+#undef EXTRA_SPECS
+#define EXTRA_SPECS \
+ { "asm_cpu_spec", ASM_CPU_SPEC }, \
+ NETBSD_SUBTARGET_EXTRA_SPECS
+
+#endif /* GCC_AARCH64_NETBSD_H */
diff --git a/gcc/config/aarch64/aarch64-option-extensions.def b/gcc/config/aarch64/aarch64-option-extensions.def
index 53dcd03..4b10c62 100644
--- a/gcc/config/aarch64/aarch64-option-extensions.def
+++ b/gcc/config/aarch64/aarch64-option-extensions.def
@@ -57,17 +57,20 @@
/* Enabling "fp" just enables "fp".
Disabling "fp" also disables "simd", "crypto", "fp16", "aes", "sha2",
- "sha3", sm3/sm4 and "sve". */
-AARCH64_OPT_EXTENSION("fp", AARCH64_FL_FP, 0, AARCH64_FL_SIMD | AARCH64_FL_CRYPTO | AARCH64_FL_F16 | AARCH64_FL_AES | AARCH64_FL_SHA2 | AARCH64_FL_SHA3 | AARCH64_FL_SM4 | AARCH64_FL_SVE, false, "fp")
+ "sha3", sm3/sm4, "sve", "sve2", "sve2-aes", "sve2-sha3", "sve2-sm4", and
+ "bitperm". */
+AARCH64_OPT_EXTENSION("fp", AARCH64_FL_FP, 0, AARCH64_FL_SIMD | AARCH64_FL_CRYPTO | AARCH64_FL_F16 | AARCH64_FL_AES | AARCH64_FL_SHA2 | AARCH64_FL_SHA3 | AARCH64_FL_SM4 | AARCH64_FL_SVE | AARCH64_FL_SVE2 | AARCH64_FL_SVE2_AES | AARCH64_FL_SVE2_SHA3 | AARCH64_FL_SVE2_SM4 | AARCH64_FL_SVE2_BITPERM, false, "fp")
/* Enabling "simd" also enables "fp".
Disabling "simd" also disables "crypto", "dotprod", "aes", "sha2", "sha3",
- "sm3/sm4" and "sve". */
-AARCH64_OPT_EXTENSION("simd", AARCH64_FL_SIMD, AARCH64_FL_FP, AARCH64_FL_CRYPTO | AARCH64_FL_DOTPROD | AARCH64_FL_AES | AARCH64_FL_SHA2 | AARCH64_FL_SHA3 | AARCH64_FL_SM4 | AARCH64_FL_SVE, false, "asimd")
+ "sm3/sm4", "sve", "sve2", "sve2-aes", "sve2-sha3", "sve2-sm4", and "bitperm".
+ */
+AARCH64_OPT_EXTENSION("simd", AARCH64_FL_SIMD, AARCH64_FL_FP, AARCH64_FL_CRYPTO | AARCH64_FL_DOTPROD | AARCH64_FL_AES | AARCH64_FL_SHA2 | AARCH64_FL_SHA3 | AARCH64_FL_SM4 | AARCH64_FL_SVE | AARCH64_FL_SVE2 | AARCH64_FL_SVE2_AES | AARCH64_FL_SVE2_SHA3 | AARCH64_FL_SVE2_SM4 | AARCH64_FL_SVE2_BITPERM, false, "asimd")
/* Enabling "crypto" also enables "fp", "simd", "aes" and "sha2".
- Disabling "crypto" disables "crypto", "aes", "sha2", "sha3" and "sm3/sm4". */
-AARCH64_OPT_EXTENSION("crypto", AARCH64_FL_CRYPTO, AARCH64_FL_FP | AARCH64_FL_SIMD | AARCH64_FL_AES | AARCH64_FL_SHA2, AARCH64_FL_AES | AARCH64_FL_SHA2 |AARCH64_FL_SHA3 | AARCH64_FL_SM4, true, "aes pmull sha1 sha2")
+ Disabling "crypto" disables "crypto", "aes", "sha2", "sha3" and "sm3/sm4",
+ "sve2-aes", "sve2-sha3", "sve2-sm4". */
+AARCH64_OPT_EXTENSION("crypto", AARCH64_FL_CRYPTO, AARCH64_FL_FP | AARCH64_FL_SIMD | AARCH64_FL_AES | AARCH64_FL_SHA2, AARCH64_FL_AES | AARCH64_FL_SHA2 | AARCH64_FL_SHA3 | AARCH64_FL_SM4 | AARCH64_FL_SVE2_AES | AARCH64_FL_SVE2_SHA3 | AARCH64_FL_SVE2_SM4, true, "aes pmull sha1 sha2")
/* Enabling or disabling "crc" only changes "crc". */
AARCH64_OPT_EXTENSION("crc", AARCH64_FL_CRC, 0, 0, false, "crc32")
@@ -76,8 +79,9 @@ AARCH64_OPT_EXTENSION("crc", AARCH64_FL_CRC, 0, 0, false, "crc32")
AARCH64_OPT_EXTENSION("lse", AARCH64_FL_LSE, 0, 0, false, "atomics")
/* Enabling "fp16" also enables "fp".
- Disabling "fp16" disables "fp16", "fp16fml" and "sve". */
-AARCH64_OPT_EXTENSION("fp16", AARCH64_FL_F16, AARCH64_FL_FP, AARCH64_FL_F16FML | AARCH64_FL_SVE, false, "fphp asimdhp")
+ Disabling "fp16" disables "fp16", "fp16fml", "sve", "sve2", "sve2-aes",
+ "sve2-sha3", "sve2-sm4", and "bitperm". */
+AARCH64_OPT_EXTENSION("fp16", AARCH64_FL_F16, AARCH64_FL_FP, AARCH64_FL_F16FML | AARCH64_FL_SVE | AARCH64_FL_SVE2 | AARCH64_FL_SVE2_AES | AARCH64_FL_SVE2_SHA3 | AARCH64_FL_SVE2_SM4 | AARCH64_FL_SVE2_BITPERM, false, "fphp asimdhp")
/* Enabling or disabling "rcpc" only changes "rcpc". */
AARCH64_OPT_EXTENSION("rcpc", AARCH64_FL_RCPC, 0, 0, false, "lrcpc")
@@ -91,28 +95,29 @@ AARCH64_OPT_EXTENSION("rdma", AARCH64_FL_RDMA, AARCH64_FL_FP | AARCH64_FL_SIMD,
AARCH64_OPT_EXTENSION("dotprod", AARCH64_FL_DOTPROD, AARCH64_FL_SIMD, 0, false, "asimddp")
/* Enabling "aes" also enables "simd".
- Disabling "aes" just disables "aes". */
-AARCH64_OPT_EXTENSION("aes", AARCH64_FL_AES, AARCH64_FL_SIMD, 0, false, "aes")
+ Disabling "aes" disables "aes" and "sve2-aes'. */
+AARCH64_OPT_EXTENSION("aes", AARCH64_FL_AES, AARCH64_FL_SIMD, AARCH64_FL_SVE2_AES, false, "aes")
/* Enabling "sha2" also enables "simd".
Disabling "sha2" just disables "sha2". */
AARCH64_OPT_EXTENSION("sha2", AARCH64_FL_SHA2, AARCH64_FL_SIMD, 0, false, "sha1 sha2")
/* Enabling "sha3" enables "simd" and "sha2".
- Disabling "sha3" just disables "sha3". */
-AARCH64_OPT_EXTENSION("sha3", AARCH64_FL_SHA3, AARCH64_FL_SIMD | AARCH64_FL_SHA2, 0, false, "sha3 sha512")
+ Disabling "sha3" disables "sha3" and "sve2-sha3". */
+AARCH64_OPT_EXTENSION("sha3", AARCH64_FL_SHA3, AARCH64_FL_SIMD | AARCH64_FL_SHA2, AARCH64_FL_SVE2_SHA3, false, "sha3 sha512")
/* Enabling "sm4" also enables "simd".
- Disabling "sm4" just disables "sm4". */
-AARCH64_OPT_EXTENSION("sm4", AARCH64_FL_SM4, AARCH64_FL_SIMD, 0, false, "sm3 sm4")
+ Disabling "sm4" disables "sm4" and "sve2-sm4". */
+AARCH64_OPT_EXTENSION("sm4", AARCH64_FL_SM4, AARCH64_FL_SIMD, AARCH64_FL_SVE2_SM4, false, "sm3 sm4")
/* Enabling "fp16fml" also enables "fp" and "fp16".
Disabling "fp16fml" just disables "fp16fml". */
AARCH64_OPT_EXTENSION("fp16fml", AARCH64_FL_F16FML, AARCH64_FL_FP | AARCH64_FL_F16, 0, false, "asimdfml")
/* Enabling "sve" also enables "fp16", "fp" and "simd".
- Disabling "sve" just disables "sve". */
-AARCH64_OPT_EXTENSION("sve", AARCH64_FL_SVE, AARCH64_FL_FP | AARCH64_FL_SIMD | AARCH64_FL_F16, 0, false, "sve")
+ Disabling "sve" disables "sve", "sve2", "sve2-aes", "sve2-sha3", "sve2-sm4"
+ and "bitperm". */
+AARCH64_OPT_EXTENSION("sve", AARCH64_FL_SVE, AARCH64_FL_FP | AARCH64_FL_SIMD | AARCH64_FL_F16, AARCH64_FL_SVE2 | AARCH64_FL_SVE2_AES | AARCH64_FL_SVE2_SHA3 | AARCH64_FL_SVE2_SM4 | AARCH64_FL_SVE2_BITPERM, false, "sve")
/* Enabling/Disabling "profile" does not enable/disable any other feature. */
AARCH64_OPT_EXTENSION("profile", AARCH64_FL_PROFILE, 0, 0, false, "")
@@ -132,4 +137,25 @@ AARCH64_OPT_EXTENSION("ssbs", AARCH64_FL_SSBS, 0, 0, false, "")
/* Enabling/Disabling "predres" only changes "predres". */
AARCH64_OPT_EXTENSION("predres", AARCH64_FL_PREDRES, 0, 0, false, "")
+/* Enabling "sve2" also enables "sve", "fp16", "fp", and "simd".
+ Disabling "sve2" disables "sve2", "sve2-aes", "sve2-sha3", "sve2-sm4", and
+ "bitperm". */
+AARCH64_OPT_EXTENSION("sve2", AARCH64_FL_SVE2, AARCH64_FL_SVE | AARCH64_FL_FP | AARCH64_FL_SIMD | AARCH64_FL_F16, AARCH64_FL_SVE2_AES | AARCH64_FL_SVE2_SHA3 | AARCH64_FL_SVE2_SM4 | AARCH64_FL_SVE2_BITPERM, false, "")
+
+/* Enabling "sve2-sm4" also enables "sm4", "simd", "fp16", "fp", "sve", and
+ "sve2". Disabling "sve2-sm4" just disables "sve2-sm4". */
+AARCH64_OPT_EXTENSION("sve2-sm4", AARCH64_FL_SVE2_SM4, AARCH64_FL_SM4 | AARCH64_FL_SIMD | AARCH64_FL_F16 | AARCH64_FL_FP | AARCH64_FL_SVE | AARCH64_FL_SVE2, 0, false, "")
+
+/* Enabling "sve2-aes" also enables "aes", "simd", "fp16", "fp", "sve", and
+ "sve2". Disabling "sve2-aes" just disables "sve2-aes". */
+AARCH64_OPT_EXTENSION("sve2-aes", AARCH64_FL_SVE2_AES, AARCH64_FL_AES | AARCH64_FL_SIMD | AARCH64_FL_F16 | AARCH64_FL_FP | AARCH64_FL_SVE | AARCH64_FL_SVE2, 0, false, "")
+
+/* Enabling "sve2-sha3" also enables "sha3", "simd", "fp16", "fp", "sve", and
+ "sve2". Disabling "sve2-sha3" just disables "sve2-sha3". */
+AARCH64_OPT_EXTENSION("sve2-sha3", AARCH64_FL_SVE2_SHA3, AARCH64_FL_SHA3 | AARCH64_FL_SIMD | AARCH64_FL_F16 | AARCH64_FL_FP | AARCH64_FL_SVE | AARCH64_FL_SVE2, 0, false, "")
+
+/* Enabling "bitperm" also enables "simd", "fp16", "fp", "sve", and "sve2".
+ Disabling "bitperm" just disables "bitperm". */
+AARCH64_OPT_EXTENSION("bitperm", AARCH64_FL_SVE2_BITPERM, AARCH64_FL_SIMD | AARCH64_FL_F16 | AARCH64_FL_FP | AARCH64_FL_SVE | AARCH64_FL_SVE2, 0, false, "")
+
#undef AARCH64_OPT_EXTENSION
diff --git a/gcc/config/aarch64/aarch64-protos.h b/gcc/config/aarch64/aarch64-protos.h
index b6c0d0a..e2f4cc1 100644
--- a/gcc/config/aarch64/aarch64-protos.h
+++ b/gcc/config/aarch64/aarch64-protos.h
@@ -396,8 +396,17 @@ enum simd_immediate_check {
AARCH64_CHECK_MOV = AARCH64_CHECK_ORR | AARCH64_CHECK_BIC
};
+/* The key type that -msign-return-address should use. */
+enum aarch64_key_type {
+ AARCH64_KEY_A,
+ AARCH64_KEY_B
+};
+
+extern enum aarch64_key_type aarch64_ra_sign_key;
+
extern struct tune_params aarch64_tune_params;
+void aarch64_post_cfi_startproc (void);
poly_int64 aarch64_initial_elimination_offset (unsigned, unsigned);
int aarch64_get_condition_code (rtx);
bool aarch64_address_valid_for_prefetch_p (rtx, bool);
@@ -415,18 +424,20 @@ bool aarch64_constant_address_p (rtx);
bool aarch64_emit_approx_div (rtx, rtx, rtx);
bool aarch64_emit_approx_sqrt (rtx, rtx, bool);
void aarch64_expand_call (rtx, rtx, bool);
-bool aarch64_expand_movmem (rtx *);
+bool aarch64_expand_cpymem (rtx *);
bool aarch64_float_const_zero_rtx_p (rtx);
bool aarch64_float_const_rtx_p (rtx);
bool aarch64_function_arg_regno_p (unsigned);
bool aarch64_fusion_enabled_p (enum aarch64_fusion_pairs);
-bool aarch64_gen_movmemqi (rtx *);
+bool aarch64_gen_cpymemqi (rtx *);
bool aarch64_gimple_fold_builtin (gimple_stmt_iterator *);
bool aarch64_is_extend_from_extract (scalar_int_mode, rtx, rtx);
bool aarch64_is_long_call_p (rtx);
bool aarch64_is_noplt_call_p (rtx);
bool aarch64_label_mentioned_p (rtx);
void aarch64_declare_function_name (FILE *, const char*, tree);
+void aarch64_asm_output_alias (FILE *, const tree, const tree);
+void aarch64_asm_output_external (FILE *, tree, const char*);
bool aarch64_legitimate_pic_operand_p (rtx);
bool aarch64_mask_and_shift_for_ubfiz_p (scalar_int_mode, rtx, rtx);
bool aarch64_masks_and_shift_for_bfi_p (scalar_int_mode, unsigned HOST_WIDE_INT,
@@ -509,12 +520,15 @@ const char * aarch64_output_probe_sve_stack_clash (rtx, rtx, rtx, rtx);
void aarch64_err_no_fpadvsimd (machine_mode);
void aarch64_expand_epilogue (bool);
void aarch64_expand_mov_immediate (rtx, rtx, rtx (*) (rtx, rtx) = 0);
+rtx aarch64_ptrue_reg (machine_mode);
+rtx aarch64_pfalse_reg (machine_mode);
void aarch64_emit_sve_pred_move (rtx, rtx, rtx);
void aarch64_expand_sve_mem_move (rtx, rtx, machine_mode);
bool aarch64_maybe_expand_sve_subreg_move (rtx, rtx);
void aarch64_split_sve_subreg_move (rtx, rtx, rtx);
void aarch64_expand_prologue (void);
void aarch64_expand_vector_init (rtx, rtx);
+void aarch64_sve_expand_vector_init (rtx, rtx);
void aarch64_init_cumulative_args (CUMULATIVE_ARGS *, const_tree, rtx,
const_tree, unsigned);
void aarch64_init_expanders (void);
@@ -624,11 +638,10 @@ bool aarch64_handle_option (struct gcc_options *, struct gcc_options *,
const struct cl_decoded_option *, location_t);
const char *aarch64_rewrite_selected_cpu (const char *name);
enum aarch64_parse_opt_result aarch64_parse_extension (const char *,
- unsigned long *,
+ uint64_t *,
std::string *);
void aarch64_get_all_extension_candidates (auto_vec<const char *> *candidates);
-std::string aarch64_get_extension_string_for_isa_flags (unsigned long,
- unsigned long);
+std::string aarch64_get_extension_string_for_isa_flags (uint64_t, uint64_t);
/* Defined in aarch64-d.c */
extern void aarch64_d_target_versions (void);
diff --git a/gcc/config/aarch64/aarch64-simd.md b/gcc/config/aarch64/aarch64-simd.md
index e3852c5..837242c 100644
--- a/gcc/config/aarch64/aarch64-simd.md
+++ b/gcc/config/aarch64/aarch64-simd.md
@@ -19,8 +19,8 @@
;; <http://www.gnu.org/licenses/>.
(define_expand "mov<mode>"
- [(set (match_operand:VALL_F16 0 "nonimmediate_operand" "")
- (match_operand:VALL_F16 1 "general_operand" ""))]
+ [(set (match_operand:VALL_F16 0 "nonimmediate_operand")
+ (match_operand:VALL_F16 1 "general_operand"))]
"TARGET_SIMD"
"
/* Force the operand into a register if it is not an
@@ -39,8 +39,8 @@
)
(define_expand "movmisalign<mode>"
- [(set (match_operand:VALL 0 "nonimmediate_operand" "")
- (match_operand:VALL 1 "general_operand" ""))]
+ [(set (match_operand:VALL 0 "nonimmediate_operand")
+ (match_operand:VALL 1 "general_operand"))]
"TARGET_SIMD"
{
/* This pattern is not permitted to fail during expansion: if both arguments
@@ -652,8 +652,8 @@
[(set_attr "type" "neon_fp_rsqrts_<stype><q>")])
(define_expand "rsqrt<mode>2"
- [(set (match_operand:VALLF 0 "register_operand" "=w")
- (unspec:VALLF [(match_operand:VALLF 1 "register_operand" "w")]
+ [(set (match_operand:VALLF 0 "register_operand")
+ (unspec:VALLF [(match_operand:VALLF 1 "register_operand")]
UNSPEC_RSQRT))]
"TARGET_SIMD"
{
@@ -710,15 +710,15 @@
;; So (ABS:QI (minus:QI 64 -128)) == (ABS:QI (192 or -64 signed)) == 64.
;; Whereas SABD would return 192 (-64 signed) on the above example.
;; Use MINUS ([us]max (op1, op2), [us]min (op1, op2)) instead.
-(define_insn "*aarch64_<su>abd<mode>_3"
+(define_insn "aarch64_<su>abd<mode>_3"
[(set (match_operand:VDQ_BHSI 0 "register_operand" "=w")
(minus:VDQ_BHSI
(USMAX:VDQ_BHSI
(match_operand:VDQ_BHSI 1 "register_operand" "w")
(match_operand:VDQ_BHSI 2 "register_operand" "w"))
- (match_operator 3 "aarch64_<max_opp>"
- [(match_dup 1)
- (match_dup 2)])))]
+ (<max_opp>:VDQ_BHSI
+ (match_dup 1)
+ (match_dup 2))))]
"TARGET_SIMD"
"<su>abd\t%0.<Vtype>, %1.<Vtype>, %2.<Vtype>"
[(set_attr "type" "neon_abd<q>")]
@@ -764,7 +764,16 @@
;; UABAL tmp.8h, op1.16b, op2.16b
;; UADALP op3.4s, tmp.8h
;; MOV op0, op3 // should be eliminated in later passes.
-;; The signed version just uses the signed variants of the above instructions.
+;;
+;; For TARGET_DOTPROD we do:
+;; MOV tmp1.16b, #1 // Can be CSE'd and hoisted out of loops.
+;; UABD tmp2.16b, op1.16b, op2.16b
+;; UDOT op3.4s, tmp2.16b, tmp1.16b
+;; MOV op0, op3 // RA will tie the operands of UDOT appropriately.
+;;
+;; The signed version just uses the signed variants of the above instructions
+;; but for TARGET_DOTPROD still emits a UDOT as the absolute difference is
+;; unsigned.
(define_expand "<sur>sadv16qi"
[(use (match_operand:V4SI 0 "register_operand"))
@@ -773,6 +782,15 @@
(use (match_operand:V4SI 3 "register_operand"))]
"TARGET_SIMD"
{
+ if (TARGET_DOTPROD)
+ {
+ rtx ones = force_reg (V16QImode, CONST1_RTX (V16QImode));
+ rtx abd = gen_reg_rtx (V16QImode);
+ emit_insn (gen_aarch64_<sur>abdv16qi_3 (abd, operands[1], operands[2]));
+ emit_insn (gen_aarch64_udotv16qi (operands[0], operands[3],
+ abd, ones));
+ DONE;
+ }
rtx reduc = gen_reg_rtx (V8HImode);
emit_insn (gen_aarch64_<sur>abdl2v16qi_3 (reduc, operands[1],
operands[2]));
@@ -935,6 +953,21 @@
[(set_attr "type" "neon_ins<q>")]
)
+(define_expand "signbit<mode>2"
+ [(use (match_operand:<V_INT_EQUIV> 0 "register_operand"))
+ (use (match_operand:VDQSF 1 "register_operand"))]
+ "TARGET_SIMD"
+{
+ int shift_amount = GET_MODE_UNIT_BITSIZE (<V_INT_EQUIV>mode) - 1;
+ rtx shift_vector = aarch64_simd_gen_const_vector_dup (<V_INT_EQUIV>mode,
+ shift_amount);
+ operands[1] = lowpart_subreg (<V_INT_EQUIV>mode, operands[1], <MODE>mode);
+
+ emit_insn (gen_aarch64_simd_lshr<v_int_equiv> (operands[0], operands[1],
+ shift_vector));
+ DONE;
+})
+
(define_insn "aarch64_simd_lshr<mode>"
[(set (match_operand:VDQ_I 0 "register_operand" "=w")
(lshiftrt:VDQ_I (match_operand:VDQ_I 1 "register_operand" "w")
@@ -992,9 +1025,9 @@
)
(define_expand "ashl<mode>3"
- [(match_operand:VDQ_I 0 "register_operand" "")
- (match_operand:VDQ_I 1 "register_operand" "")
- (match_operand:SI 2 "general_operand" "")]
+ [(match_operand:VDQ_I 0 "register_operand")
+ (match_operand:VDQ_I 1 "register_operand")
+ (match_operand:SI 2 "general_operand")]
"TARGET_SIMD"
{
int bit_width = GET_MODE_UNIT_SIZE (<MODE>mode) * BITS_PER_UNIT;
@@ -1039,9 +1072,9 @@
)
(define_expand "lshr<mode>3"
- [(match_operand:VDQ_I 0 "register_operand" "")
- (match_operand:VDQ_I 1 "register_operand" "")
- (match_operand:SI 2 "general_operand" "")]
+ [(match_operand:VDQ_I 0 "register_operand")
+ (match_operand:VDQ_I 1 "register_operand")
+ (match_operand:SI 2 "general_operand")]
"TARGET_SIMD"
{
int bit_width = GET_MODE_UNIT_SIZE (<MODE>mode) * BITS_PER_UNIT;
@@ -1086,9 +1119,9 @@
)
(define_expand "ashr<mode>3"
- [(match_operand:VDQ_I 0 "register_operand" "")
- (match_operand:VDQ_I 1 "register_operand" "")
- (match_operand:SI 2 "general_operand" "")]
+ [(match_operand:VDQ_I 0 "register_operand")
+ (match_operand:VDQ_I 1 "register_operand")
+ (match_operand:SI 2 "general_operand")]
"TARGET_SIMD"
{
int bit_width = GET_MODE_UNIT_SIZE (<MODE>mode) * BITS_PER_UNIT;
@@ -1133,9 +1166,9 @@
)
(define_expand "vashl<mode>3"
- [(match_operand:VDQ_I 0 "register_operand" "")
- (match_operand:VDQ_I 1 "register_operand" "")
- (match_operand:VDQ_I 2 "register_operand" "")]
+ [(match_operand:VDQ_I 0 "register_operand")
+ (match_operand:VDQ_I 1 "register_operand")
+ (match_operand:VDQ_I 2 "register_operand")]
"TARGET_SIMD"
{
emit_insn (gen_aarch64_simd_reg_sshl<mode> (operands[0], operands[1],
@@ -1147,9 +1180,9 @@
;; Negating individual lanes most certainly offsets the
;; gain from vectorization.
(define_expand "vashr<mode>3"
- [(match_operand:VDQ_BHSI 0 "register_operand" "")
- (match_operand:VDQ_BHSI 1 "register_operand" "")
- (match_operand:VDQ_BHSI 2 "register_operand" "")]
+ [(match_operand:VDQ_BHSI 0 "register_operand")
+ (match_operand:VDQ_BHSI 1 "register_operand")
+ (match_operand:VDQ_BHSI 2 "register_operand")]
"TARGET_SIMD"
{
rtx neg = gen_reg_rtx (<MODE>mode);
@@ -1161,9 +1194,9 @@
;; DI vector shift
(define_expand "aarch64_ashr_simddi"
- [(match_operand:DI 0 "register_operand" "=w")
- (match_operand:DI 1 "register_operand" "w")
- (match_operand:SI 2 "aarch64_shift_imm64_di" "")]
+ [(match_operand:DI 0 "register_operand")
+ (match_operand:DI 1 "register_operand")
+ (match_operand:SI 2 "aarch64_shift_imm64_di")]
"TARGET_SIMD"
{
/* An arithmetic shift right by 64 fills the result with copies of the sign
@@ -1177,9 +1210,9 @@
)
(define_expand "vlshr<mode>3"
- [(match_operand:VDQ_BHSI 0 "register_operand" "")
- (match_operand:VDQ_BHSI 1 "register_operand" "")
- (match_operand:VDQ_BHSI 2 "register_operand" "")]
+ [(match_operand:VDQ_BHSI 0 "register_operand")
+ (match_operand:VDQ_BHSI 1 "register_operand")
+ (match_operand:VDQ_BHSI 2 "register_operand")]
"TARGET_SIMD"
{
rtx neg = gen_reg_rtx (<MODE>mode);
@@ -1190,9 +1223,9 @@
})
(define_expand "aarch64_lshr_simddi"
- [(match_operand:DI 0 "register_operand" "=w")
- (match_operand:DI 1 "register_operand" "w")
- (match_operand:SI 2 "aarch64_shift_imm64_di" "")]
+ [(match_operand:DI 0 "register_operand")
+ (match_operand:DI 1 "register_operand")
+ (match_operand:SI 2 "aarch64_shift_imm64_di")]
"TARGET_SIMD"
{
if (INTVAL (operands[2]) == 64)
@@ -1220,9 +1253,9 @@
)
(define_expand "vec_set<mode>"
- [(match_operand:VALL_F16 0 "register_operand" "+w")
- (match_operand:<VEL> 1 "register_operand" "w")
- (match_operand:SI 2 "immediate_operand" "")]
+ [(match_operand:VALL_F16 0 "register_operand")
+ (match_operand:<VEL> 1 "register_operand")
+ (match_operand:SI 2 "immediate_operand")]
"TARGET_SIMD"
{
HOST_WIDE_INT elem = (HOST_WIDE_INT) 1 << INTVAL (operands[2]);
@@ -1361,9 +1394,9 @@
)
(define_expand "<su><maxmin>v2di3"
- [(set (match_operand:V2DI 0 "register_operand" "")
- (MAXMIN:V2DI (match_operand:V2DI 1 "register_operand" "")
- (match_operand:V2DI 2 "register_operand" "")))]
+ [(set (match_operand:V2DI 0 "register_operand")
+ (MAXMIN:V2DI (match_operand:V2DI 1 "register_operand")
+ (match_operand:V2DI 2 "register_operand")))]
"TARGET_SIMD"
{
enum rtx_code cmp_operator;
@@ -1532,8 +1565,8 @@
)
(define_expand "move_hi_quad_<mode>"
- [(match_operand:VQ 0 "register_operand" "")
- (match_operand:<VHALF> 1 "register_operand" "")]
+ [(match_operand:VQ 0 "register_operand")
+ (match_operand:<VHALF> 1 "register_operand")]
"TARGET_SIMD"
{
rtx p = aarch64_simd_vect_par_cnst_half (<MODE>mode, <nunits>, false);
@@ -1558,9 +1591,9 @@
)
(define_expand "vec_pack_trunc_<mode>"
- [(match_operand:<VNARROWD> 0 "register_operand" "")
- (match_operand:VDN 1 "register_operand" "")
- (match_operand:VDN 2 "register_operand" "")]
+ [(match_operand:<VNARROWD> 0 "register_operand")
+ (match_operand:VDN 1 "register_operand")
+ (match_operand:VDN 2 "register_operand")]
"TARGET_SIMD"
{
rtx tempreg = gen_reg_rtx (<VDBL>mode);
@@ -1616,7 +1649,7 @@
)
(define_expand "vec_unpack<su>_hi_<mode>"
- [(match_operand:<VWIDE> 0 "register_operand" "")
+ [(match_operand:<VWIDE> 0 "register_operand")
(ANY_EXTEND:<VWIDE> (match_operand:VQW 1 "register_operand"))]
"TARGET_SIMD"
{
@@ -1628,8 +1661,8 @@
)
(define_expand "vec_unpack<su>_lo_<mode>"
- [(match_operand:<VWIDE> 0 "register_operand" "")
- (ANY_EXTEND:<VWIDE> (match_operand:VQW 1 "register_operand" ""))]
+ [(match_operand:<VWIDE> 0 "register_operand")
+ (ANY_EXTEND:<VWIDE> (match_operand:VQW 1 "register_operand"))]
"TARGET_SIMD"
{
rtx p = aarch64_simd_vect_par_cnst_half (<MODE>mode, <nunits>, false);
@@ -1747,9 +1780,9 @@
)
(define_expand "vec_widen_<su>mult_lo_<mode>"
- [(match_operand:<VWIDE> 0 "register_operand" "")
- (ANY_EXTEND:<VWIDE> (match_operand:VQW 1 "register_operand" ""))
- (ANY_EXTEND:<VWIDE> (match_operand:VQW 2 "register_operand" ""))]
+ [(match_operand:<VWIDE> 0 "register_operand")
+ (ANY_EXTEND:<VWIDE> (match_operand:VQW 1 "register_operand"))
+ (ANY_EXTEND:<VWIDE> (match_operand:VQW 2 "register_operand"))]
"TARGET_SIMD"
{
rtx p = aarch64_simd_vect_par_cnst_half (<MODE>mode, <nunits>, false);
@@ -1774,9 +1807,9 @@
)
(define_expand "vec_widen_<su>mult_hi_<mode>"
- [(match_operand:<VWIDE> 0 "register_operand" "")
- (ANY_EXTEND:<VWIDE> (match_operand:VQW 1 "register_operand" ""))
- (ANY_EXTEND:<VWIDE> (match_operand:VQW 2 "register_operand" ""))]
+ [(match_operand:<VWIDE> 0 "register_operand")
+ (ANY_EXTEND:<VWIDE> (match_operand:VQW 1 "register_operand"))
+ (ANY_EXTEND:<VWIDE> (match_operand:VQW 2 "register_operand"))]
"TARGET_SIMD"
{
rtx p = aarch64_simd_vect_par_cnst_half (<MODE>mode, <nunits>, true);
@@ -1841,9 +1874,9 @@
)
(define_expand "div<mode>3"
- [(set (match_operand:VHSDF 0 "register_operand" "=w")
- (div:VHSDF (match_operand:VHSDF 1 "register_operand" "w")
- (match_operand:VHSDF 2 "register_operand" "w")))]
+ [(set (match_operand:VHSDF 0 "register_operand")
+ (div:VHSDF (match_operand:VHSDF 1 "register_operand")
+ (match_operand:VHSDF 2 "register_operand")))]
"TARGET_SIMD"
{
if (aarch64_emit_approx_div (operands[0], operands[1], operands[2]))
@@ -2178,8 +2211,8 @@
;; other big-endian patterns their behavior is as required.
(define_expand "vec_unpacks_lo_<mode>"
- [(match_operand:<VWIDE> 0 "register_operand" "")
- (match_operand:VQ_HSF 1 "register_operand" "")]
+ [(match_operand:<VWIDE> 0 "register_operand")
+ (match_operand:VQ_HSF 1 "register_operand")]
"TARGET_SIMD"
{
rtx p = aarch64_simd_vect_par_cnst_half (<MODE>mode, <nunits>, false);
@@ -2201,8 +2234,8 @@
)
(define_expand "vec_unpacks_hi_<mode>"
- [(match_operand:<VWIDE> 0 "register_operand" "")
- (match_operand:VQ_HSF 1 "register_operand" "")]
+ [(match_operand:<VWIDE> 0 "register_operand")
+ (match_operand:VQ_HSF 1 "register_operand")]
"TARGET_SIMD"
{
rtx p = aarch64_simd_vect_par_cnst_half (<MODE>mode, <nunits>, true);
@@ -2254,9 +2287,9 @@
)
(define_expand "aarch64_float_truncate_hi_<Vdbl>"
- [(match_operand:<VDBL> 0 "register_operand" "=w")
- (match_operand:VDF 1 "register_operand" "0")
- (match_operand:<VWIDE> 2 "register_operand" "w")]
+ [(match_operand:<VDBL> 0 "register_operand")
+ (match_operand:VDF 1 "register_operand")
+ (match_operand:<VWIDE> 2 "register_operand")]
"TARGET_SIMD"
{
rtx (*gen) (rtx, rtx, rtx) = BYTES_BIG_ENDIAN
@@ -2349,8 +2382,8 @@
;; 'across lanes' add.
(define_expand "reduc_plus_scal_<mode>"
- [(match_operand:<VEL> 0 "register_operand" "=w")
- (unspec:VDQ_I [(match_operand:VDQ_I 1 "register_operand" "w")]
+ [(match_operand:<VEL> 0 "register_operand")
+ (unspec:VDQ_I [(match_operand:VDQ_I 1 "register_operand")]
UNSPEC_ADDV)]
"TARGET_SIMD"
{
@@ -3183,7 +3216,7 @@
;; In this insn, operand 1 should be low, and operand 2 the high part of the
;; dest vector.
-(define_insn "*aarch64_combinez<mode>"
+(define_insn "@aarch64_combinez<mode>"
[(set (match_operand:<VDBL> 0 "register_operand" "=w,w,w")
(vec_concat:<VDBL>
(match_operand:VDC 1 "general_operand" "w,?r,m")
@@ -3197,7 +3230,7 @@
(set_attr "arch" "simd,fp,simd")]
)
-(define_insn "*aarch64_combinez_be<mode>"
+(define_insn "@aarch64_combinez_be<mode>"
[(set (match_operand:<VDBL> 0 "register_operand" "=w,w,w")
(vec_concat:<VDBL>
(match_operand:VDC 2 "aarch64_simd_or_scalar_imm_zero")
@@ -3266,9 +3299,9 @@
(define_expand "aarch64_saddl2<mode>"
- [(match_operand:<VWIDE> 0 "register_operand" "=w")
- (match_operand:VQW 1 "register_operand" "w")
- (match_operand:VQW 2 "register_operand" "w")]
+ [(match_operand:<VWIDE> 0 "register_operand")
+ (match_operand:VQW 1 "register_operand")
+ (match_operand:VQW 2 "register_operand")]
"TARGET_SIMD"
{
rtx p = aarch64_simd_vect_par_cnst_half (<MODE>mode, <nunits>, true);
@@ -3278,9 +3311,9 @@
})
(define_expand "aarch64_uaddl2<mode>"
- [(match_operand:<VWIDE> 0 "register_operand" "=w")
- (match_operand:VQW 1 "register_operand" "w")
- (match_operand:VQW 2 "register_operand" "w")]
+ [(match_operand:<VWIDE> 0 "register_operand")
+ (match_operand:VQW 1 "register_operand")
+ (match_operand:VQW 2 "register_operand")]
"TARGET_SIMD"
{
rtx p = aarch64_simd_vect_par_cnst_half (<MODE>mode, <nunits>, true);
@@ -3290,9 +3323,9 @@
})
(define_expand "aarch64_ssubl2<mode>"
- [(match_operand:<VWIDE> 0 "register_operand" "=w")
- (match_operand:VQW 1 "register_operand" "w")
- (match_operand:VQW 2 "register_operand" "w")]
+ [(match_operand:<VWIDE> 0 "register_operand")
+ (match_operand:VQW 1 "register_operand")
+ (match_operand:VQW 2 "register_operand")]
"TARGET_SIMD"
{
rtx p = aarch64_simd_vect_par_cnst_half (<MODE>mode, <nunits>, true);
@@ -3302,9 +3335,9 @@
})
(define_expand "aarch64_usubl2<mode>"
- [(match_operand:<VWIDE> 0 "register_operand" "=w")
- (match_operand:VQW 1 "register_operand" "w")
- (match_operand:VQW 2 "register_operand" "w")]
+ [(match_operand:<VWIDE> 0 "register_operand")
+ (match_operand:VQW 1 "register_operand")
+ (match_operand:VQW 2 "register_operand")]
"TARGET_SIMD"
{
rtx p = aarch64_simd_vect_par_cnst_half (<MODE>mode, <nunits>, true);
@@ -3327,10 +3360,10 @@
;; <su><addsub>w<q>.
(define_expand "widen_ssum<mode>3"
- [(set (match_operand:<VDBLW> 0 "register_operand" "")
+ [(set (match_operand:<VDBLW> 0 "register_operand")
(plus:<VDBLW> (sign_extend:<VDBLW>
- (match_operand:VQW 1 "register_operand" ""))
- (match_operand:<VDBLW> 2 "register_operand" "")))]
+ (match_operand:VQW 1 "register_operand"))
+ (match_operand:<VDBLW> 2 "register_operand")))]
"TARGET_SIMD"
{
rtx p = aarch64_simd_vect_par_cnst_half (<MODE>mode, <nunits>, false);
@@ -3344,10 +3377,10 @@
)
(define_expand "widen_ssum<mode>3"
- [(set (match_operand:<VWIDE> 0 "register_operand" "")
+ [(set (match_operand:<VWIDE> 0 "register_operand")
(plus:<VWIDE> (sign_extend:<VWIDE>
- (match_operand:VD_BHSI 1 "register_operand" ""))
- (match_operand:<VWIDE> 2 "register_operand" "")))]
+ (match_operand:VD_BHSI 1 "register_operand"))
+ (match_operand:<VWIDE> 2 "register_operand")))]
"TARGET_SIMD"
{
emit_insn (gen_aarch64_saddw<mode> (operands[0], operands[2], operands[1]));
@@ -3355,10 +3388,10 @@
})
(define_expand "widen_usum<mode>3"
- [(set (match_operand:<VDBLW> 0 "register_operand" "")
+ [(set (match_operand:<VDBLW> 0 "register_operand")
(plus:<VDBLW> (zero_extend:<VDBLW>
- (match_operand:VQW 1 "register_operand" ""))
- (match_operand:<VDBLW> 2 "register_operand" "")))]
+ (match_operand:VQW 1 "register_operand"))
+ (match_operand:<VDBLW> 2 "register_operand")))]
"TARGET_SIMD"
{
rtx p = aarch64_simd_vect_par_cnst_half (<MODE>mode, <nunits>, false);
@@ -3372,10 +3405,10 @@
)
(define_expand "widen_usum<mode>3"
- [(set (match_operand:<VWIDE> 0 "register_operand" "")
+ [(set (match_operand:<VWIDE> 0 "register_operand")
(plus:<VWIDE> (zero_extend:<VWIDE>
- (match_operand:VD_BHSI 1 "register_operand" ""))
- (match_operand:<VWIDE> 2 "register_operand" "")))]
+ (match_operand:VD_BHSI 1 "register_operand"))
+ (match_operand:<VWIDE> 2 "register_operand")))]
"TARGET_SIMD"
{
emit_insn (gen_aarch64_uaddw<mode> (operands[0], operands[2], operands[1]));
@@ -3453,9 +3486,9 @@
)
(define_expand "aarch64_saddw2<mode>"
- [(match_operand:<VWIDE> 0 "register_operand" "=w")
- (match_operand:<VWIDE> 1 "register_operand" "w")
- (match_operand:VQW 2 "register_operand" "w")]
+ [(match_operand:<VWIDE> 0 "register_operand")
+ (match_operand:<VWIDE> 1 "register_operand")
+ (match_operand:VQW 2 "register_operand")]
"TARGET_SIMD"
{
rtx p = aarch64_simd_vect_par_cnst_half (<MODE>mode, <nunits>, true);
@@ -3465,9 +3498,9 @@
})
(define_expand "aarch64_uaddw2<mode>"
- [(match_operand:<VWIDE> 0 "register_operand" "=w")
- (match_operand:<VWIDE> 1 "register_operand" "w")
- (match_operand:VQW 2 "register_operand" "w")]
+ [(match_operand:<VWIDE> 0 "register_operand")
+ (match_operand:<VWIDE> 1 "register_operand")
+ (match_operand:VQW 2 "register_operand")]
"TARGET_SIMD"
{
rtx p = aarch64_simd_vect_par_cnst_half (<MODE>mode, <nunits>, true);
@@ -3478,9 +3511,9 @@
(define_expand "aarch64_ssubw2<mode>"
- [(match_operand:<VWIDE> 0 "register_operand" "=w")
- (match_operand:<VWIDE> 1 "register_operand" "w")
- (match_operand:VQW 2 "register_operand" "w")]
+ [(match_operand:<VWIDE> 0 "register_operand")
+ (match_operand:<VWIDE> 1 "register_operand")
+ (match_operand:VQW 2 "register_operand")]
"TARGET_SIMD"
{
rtx p = aarch64_simd_vect_par_cnst_half (<MODE>mode, <nunits>, true);
@@ -3490,9 +3523,9 @@
})
(define_expand "aarch64_usubw2<mode>"
- [(match_operand:<VWIDE> 0 "register_operand" "=w")
- (match_operand:<VWIDE> 1 "register_operand" "w")
- (match_operand:VQW 2 "register_operand" "w")]
+ [(match_operand:<VWIDE> 0 "register_operand")
+ (match_operand:<VWIDE> 1 "register_operand")
+ (match_operand:VQW 2 "register_operand")]
"TARGET_SIMD"
{
rtx p = aarch64_simd_vect_par_cnst_half (<MODE>mode, <nunits>, true);
@@ -4025,10 +4058,10 @@
)
(define_expand "aarch64_sqdmlal2<mode>"
- [(match_operand:<VWIDE> 0 "register_operand" "=w")
- (match_operand:<VWIDE> 1 "register_operand" "w")
- (match_operand:VQ_HSI 2 "register_operand" "w")
- (match_operand:VQ_HSI 3 "register_operand" "w")]
+ [(match_operand:<VWIDE> 0 "register_operand")
+ (match_operand:<VWIDE> 1 "register_operand")
+ (match_operand:VQ_HSI 2 "register_operand")
+ (match_operand:VQ_HSI 3 "register_operand")]
"TARGET_SIMD"
{
rtx p = aarch64_simd_vect_par_cnst_half (<MODE>mode, <nunits>, true);
@@ -4038,10 +4071,10 @@
})
(define_expand "aarch64_sqdmlsl2<mode>"
- [(match_operand:<VWIDE> 0 "register_operand" "=w")
- (match_operand:<VWIDE> 1 "register_operand" "w")
- (match_operand:VQ_HSI 2 "register_operand" "w")
- (match_operand:VQ_HSI 3 "register_operand" "w")]
+ [(match_operand:<VWIDE> 0 "register_operand")
+ (match_operand:<VWIDE> 1 "register_operand")
+ (match_operand:VQ_HSI 2 "register_operand")
+ (match_operand:VQ_HSI 3 "register_operand")]
"TARGET_SIMD"
{
rtx p = aarch64_simd_vect_par_cnst_half (<MODE>mode, <nunits>, true);
@@ -4105,11 +4138,11 @@
)
(define_expand "aarch64_sqdmlal2_lane<mode>"
- [(match_operand:<VWIDE> 0 "register_operand" "=w")
- (match_operand:<VWIDE> 1 "register_operand" "w")
- (match_operand:VQ_HSI 2 "register_operand" "w")
- (match_operand:<VCOND> 3 "register_operand" "<vwx>")
- (match_operand:SI 4 "immediate_operand" "i")]
+ [(match_operand:<VWIDE> 0 "register_operand")
+ (match_operand:<VWIDE> 1 "register_operand")
+ (match_operand:VQ_HSI 2 "register_operand")
+ (match_operand:<VCOND> 3 "register_operand")
+ (match_operand:SI 4 "immediate_operand")]
"TARGET_SIMD"
{
rtx p = aarch64_simd_vect_par_cnst_half (<MODE>mode, <nunits>, true);
@@ -4120,11 +4153,11 @@
})
(define_expand "aarch64_sqdmlal2_laneq<mode>"
- [(match_operand:<VWIDE> 0 "register_operand" "=w")
- (match_operand:<VWIDE> 1 "register_operand" "w")
- (match_operand:VQ_HSI 2 "register_operand" "w")
- (match_operand:<VCONQ> 3 "register_operand" "<vwx>")
- (match_operand:SI 4 "immediate_operand" "i")]
+ [(match_operand:<VWIDE> 0 "register_operand")
+ (match_operand:<VWIDE> 1 "register_operand")
+ (match_operand:VQ_HSI 2 "register_operand")
+ (match_operand:<VCONQ> 3 "register_operand")
+ (match_operand:SI 4 "immediate_operand")]
"TARGET_SIMD"
{
rtx p = aarch64_simd_vect_par_cnst_half (<MODE>mode, <nunits>, true);
@@ -4135,11 +4168,11 @@
})
(define_expand "aarch64_sqdmlsl2_lane<mode>"
- [(match_operand:<VWIDE> 0 "register_operand" "=w")
- (match_operand:<VWIDE> 1 "register_operand" "w")
- (match_operand:VQ_HSI 2 "register_operand" "w")
- (match_operand:<VCOND> 3 "register_operand" "<vwx>")
- (match_operand:SI 4 "immediate_operand" "i")]
+ [(match_operand:<VWIDE> 0 "register_operand")
+ (match_operand:<VWIDE> 1 "register_operand")
+ (match_operand:VQ_HSI 2 "register_operand")
+ (match_operand:<VCOND> 3 "register_operand")
+ (match_operand:SI 4 "immediate_operand")]
"TARGET_SIMD"
{
rtx p = aarch64_simd_vect_par_cnst_half (<MODE>mode, <nunits>, true);
@@ -4150,11 +4183,11 @@
})
(define_expand "aarch64_sqdmlsl2_laneq<mode>"
- [(match_operand:<VWIDE> 0 "register_operand" "=w")
- (match_operand:<VWIDE> 1 "register_operand" "w")
- (match_operand:VQ_HSI 2 "register_operand" "w")
- (match_operand:<VCONQ> 3 "register_operand" "<vwx>")
- (match_operand:SI 4 "immediate_operand" "i")]
+ [(match_operand:<VWIDE> 0 "register_operand")
+ (match_operand:<VWIDE> 1 "register_operand")
+ (match_operand:VQ_HSI 2 "register_operand")
+ (match_operand:<VCONQ> 3 "register_operand")
+ (match_operand:SI 4 "immediate_operand")]
"TARGET_SIMD"
{
rtx p = aarch64_simd_vect_par_cnst_half (<MODE>mode, <nunits>, true);
@@ -4184,10 +4217,10 @@
)
(define_expand "aarch64_sqdmlal2_n<mode>"
- [(match_operand:<VWIDE> 0 "register_operand" "=w")
- (match_operand:<VWIDE> 1 "register_operand" "w")
- (match_operand:VQ_HSI 2 "register_operand" "w")
- (match_operand:<VEL> 3 "register_operand" "w")]
+ [(match_operand:<VWIDE> 0 "register_operand")
+ (match_operand:<VWIDE> 1 "register_operand")
+ (match_operand:VQ_HSI 2 "register_operand")
+ (match_operand:<VEL> 3 "register_operand")]
"TARGET_SIMD"
{
rtx p = aarch64_simd_vect_par_cnst_half (<MODE>mode, <nunits>, true);
@@ -4198,10 +4231,10 @@
})
(define_expand "aarch64_sqdmlsl2_n<mode>"
- [(match_operand:<VWIDE> 0 "register_operand" "=w")
- (match_operand:<VWIDE> 1 "register_operand" "w")
- (match_operand:VQ_HSI 2 "register_operand" "w")
- (match_operand:<VEL> 3 "register_operand" "w")]
+ [(match_operand:<VWIDE> 0 "register_operand")
+ (match_operand:<VWIDE> 1 "register_operand")
+ (match_operand:VQ_HSI 2 "register_operand")
+ (match_operand:<VEL> 3 "register_operand")]
"TARGET_SIMD"
{
rtx p = aarch64_simd_vect_par_cnst_half (<MODE>mode, <nunits>, true);
@@ -4353,9 +4386,9 @@
)
(define_expand "aarch64_sqdmull2<mode>"
- [(match_operand:<VWIDE> 0 "register_operand" "=w")
- (match_operand:VQ_HSI 1 "register_operand" "w")
- (match_operand:VQ_HSI 2 "register_operand" "w")]
+ [(match_operand:<VWIDE> 0 "register_operand")
+ (match_operand:VQ_HSI 1 "register_operand")
+ (match_operand:VQ_HSI 2 "register_operand")]
"TARGET_SIMD"
{
rtx p = aarch64_simd_vect_par_cnst_half (<MODE>mode, <nunits>, true);
@@ -4413,10 +4446,10 @@
)
(define_expand "aarch64_sqdmull2_lane<mode>"
- [(match_operand:<VWIDE> 0 "register_operand" "=w")
- (match_operand:VQ_HSI 1 "register_operand" "w")
- (match_operand:<VCOND> 2 "register_operand" "<vwx>")
- (match_operand:SI 3 "immediate_operand" "i")]
+ [(match_operand:<VWIDE> 0 "register_operand")
+ (match_operand:VQ_HSI 1 "register_operand")
+ (match_operand:<VCOND> 2 "register_operand")
+ (match_operand:SI 3 "immediate_operand")]
"TARGET_SIMD"
{
rtx p = aarch64_simd_vect_par_cnst_half (<MODE>mode, <nunits>, true);
@@ -4427,10 +4460,10 @@
})
(define_expand "aarch64_sqdmull2_laneq<mode>"
- [(match_operand:<VWIDE> 0 "register_operand" "=w")
- (match_operand:VQ_HSI 1 "register_operand" "w")
- (match_operand:<VCONQ> 2 "register_operand" "<vwx>")
- (match_operand:SI 3 "immediate_operand" "i")]
+ [(match_operand:<VWIDE> 0 "register_operand")
+ (match_operand:VQ_HSI 1 "register_operand")
+ (match_operand:<VCONQ> 2 "register_operand")
+ (match_operand:SI 3 "immediate_operand")]
"TARGET_SIMD"
{
rtx p = aarch64_simd_vect_par_cnst_half (<MODE>mode, <nunits>, true);
@@ -4461,9 +4494,9 @@
)
(define_expand "aarch64_sqdmull2_n<mode>"
- [(match_operand:<VWIDE> 0 "register_operand" "=w")
- (match_operand:VQ_HSI 1 "register_operand" "w")
- (match_operand:<VEL> 2 "register_operand" "w")]
+ [(match_operand:<VWIDE> 0 "register_operand")
+ (match_operand:VQ_HSI 1 "register_operand")
+ (match_operand:<VEL> 2 "register_operand")]
"TARGET_SIMD"
{
rtx p = aarch64_simd_vect_par_cnst_half (<MODE>mode, <nunits>, true);
@@ -4865,8 +4898,8 @@
;; sqrt
(define_expand "sqrt<mode>2"
- [(set (match_operand:VHSDF 0 "register_operand" "=w")
- (sqrt:VHSDF (match_operand:VHSDF 1 "register_operand" "w")))]
+ [(set (match_operand:VHSDF 0 "register_operand")
+ (sqrt:VHSDF (match_operand:VHSDF 1 "register_operand")))]
"TARGET_SIMD"
{
if (aarch64_emit_approx_sqrt (operands[0], operands[1], false))
@@ -4919,8 +4952,8 @@
)
(define_expand "vec_load_lanesoi<mode>"
- [(set (match_operand:OI 0 "register_operand" "=w")
- (unspec:OI [(match_operand:OI 1 "aarch64_simd_struct_operand" "Utv")
+ [(set (match_operand:OI 0 "register_operand")
+ (unspec:OI [(match_operand:OI 1 "aarch64_simd_struct_operand")
(unspec:VQ [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
UNSPEC_LD2))]
"TARGET_SIMD"
@@ -4963,8 +4996,8 @@
)
(define_expand "vec_store_lanesoi<mode>"
- [(set (match_operand:OI 0 "aarch64_simd_struct_operand" "=Utv")
- (unspec:OI [(match_operand:OI 1 "register_operand" "w")
+ [(set (match_operand:OI 0 "aarch64_simd_struct_operand")
+ (unspec:OI [(match_operand:OI 1 "register_operand")
(unspec:VQ [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
UNSPEC_ST2))]
"TARGET_SIMD"
@@ -5017,8 +5050,8 @@
)
(define_expand "vec_load_lanesci<mode>"
- [(set (match_operand:CI 0 "register_operand" "=w")
- (unspec:CI [(match_operand:CI 1 "aarch64_simd_struct_operand" "Utv")
+ [(set (match_operand:CI 0 "register_operand")
+ (unspec:CI [(match_operand:CI 1 "aarch64_simd_struct_operand")
(unspec:VQ [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
UNSPEC_LD3))]
"TARGET_SIMD"
@@ -5061,8 +5094,8 @@
)
(define_expand "vec_store_lanesci<mode>"
- [(set (match_operand:CI 0 "aarch64_simd_struct_operand" "=Utv")
- (unspec:CI [(match_operand:CI 1 "register_operand" "w")
+ [(set (match_operand:CI 0 "aarch64_simd_struct_operand")
+ (unspec:CI [(match_operand:CI 1 "register_operand")
(unspec:VQ [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
UNSPEC_ST3))]
"TARGET_SIMD"
@@ -5115,8 +5148,8 @@
)
(define_expand "vec_load_lanesxi<mode>"
- [(set (match_operand:XI 0 "register_operand" "=w")
- (unspec:XI [(match_operand:XI 1 "aarch64_simd_struct_operand" "Utv")
+ [(set (match_operand:XI 0 "register_operand")
+ (unspec:XI [(match_operand:XI 1 "aarch64_simd_struct_operand")
(unspec:VQ [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
UNSPEC_LD4))]
"TARGET_SIMD"
@@ -5159,8 +5192,8 @@
)
(define_expand "vec_store_lanesxi<mode>"
- [(set (match_operand:XI 0 "aarch64_simd_struct_operand" "=Utv")
- (unspec:XI [(match_operand:XI 1 "register_operand" "w")
+ [(set (match_operand:XI 0 "aarch64_simd_struct_operand")
+ (unspec:XI [(match_operand:XI 1 "register_operand")
(unspec:VQ [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
UNSPEC_ST4))]
"TARGET_SIMD"
@@ -5205,8 +5238,8 @@
;; Reload patterns for AdvSIMD register list operands.
(define_expand "mov<mode>"
- [(set (match_operand:VSTRUCT 0 "nonimmediate_operand" "")
- (match_operand:VSTRUCT 1 "general_operand" ""))]
+ [(set (match_operand:VSTRUCT 0 "nonimmediate_operand")
+ (match_operand:VSTRUCT 1 "general_operand"))]
"TARGET_SIMD"
{
if (can_create_pseudo_p ())
@@ -5218,8 +5251,8 @@
(define_expand "aarch64_ld1x3<VALLDIF:mode>"
- [(match_operand:CI 0 "register_operand" "=w")
- (match_operand:DI 1 "register_operand" "r")
+ [(match_operand:CI 0 "register_operand")
+ (match_operand:DI 1 "register_operand")
(unspec:VALLDIF [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
"TARGET_SIMD"
{
@@ -5239,8 +5272,8 @@
)
(define_expand "aarch64_st1x2<VALLDIF:mode>"
- [(match_operand:DI 0 "register_operand" "")
- (match_operand:OI 1 "register_operand" "")
+ [(match_operand:DI 0 "register_operand")
+ (match_operand:OI 1 "register_operand")
(unspec:VALLDIF [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
"TARGET_SIMD"
{
@@ -5260,8 +5293,8 @@
)
(define_expand "aarch64_st1x3<VALLDIF:mode>"
- [(match_operand:DI 0 "register_operand" "")
- (match_operand:CI 1 "register_operand" "")
+ [(match_operand:DI 0 "register_operand")
+ (match_operand:CI 1 "register_operand")
(unspec:VALLDIF [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
"TARGET_SIMD"
{
@@ -5413,8 +5446,8 @@
})
(define_expand "aarch64_ld<VSTRUCT:nregs>r<VALLDIF:mode>"
- [(match_operand:VSTRUCT 0 "register_operand" "=w")
- (match_operand:DI 1 "register_operand" "w")
+ [(match_operand:VSTRUCT 0 "register_operand")
+ (match_operand:DI 1 "register_operand")
(unspec:VALLDIF [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
"TARGET_SIMD"
{
@@ -5488,8 +5521,8 @@
)
(define_expand "aarch64_ld<VSTRUCT:nregs><VDC:mode>"
- [(match_operand:VSTRUCT 0 "register_operand" "=w")
- (match_operand:DI 1 "register_operand" "r")
+ [(match_operand:VSTRUCT 0 "register_operand")
+ (match_operand:DI 1 "register_operand")
(unspec:VDC [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
"TARGET_SIMD"
{
@@ -5516,8 +5549,8 @@
})
(define_expand "aarch64_ld<VSTRUCT:nregs><VQ:mode>"
- [(match_operand:VSTRUCT 0 "register_operand" "=w")
- (match_operand:DI 1 "register_operand" "r")
+ [(match_operand:VSTRUCT 0 "register_operand")
+ (match_operand:DI 1 "register_operand")
(unspec:VQ [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
"TARGET_SIMD"
{
@@ -5529,8 +5562,8 @@
})
(define_expand "aarch64_ld1x2<VQ:mode>"
- [(match_operand:OI 0 "register_operand" "=w")
- (match_operand:DI 1 "register_operand" "r")
+ [(match_operand:OI 0 "register_operand")
+ (match_operand:DI 1 "register_operand")
(unspec:VQ [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
"TARGET_SIMD"
{
@@ -5542,8 +5575,8 @@
})
(define_expand "aarch64_ld1x2<VDC:mode>"
- [(match_operand:OI 0 "register_operand" "=w")
- (match_operand:DI 1 "register_operand" "r")
+ [(match_operand:OI 0 "register_operand")
+ (match_operand:DI 1 "register_operand")
(unspec:VDC [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
"TARGET_SIMD"
{
@@ -5556,10 +5589,10 @@
(define_expand "aarch64_ld<VSTRUCT:nregs>_lane<VALLDIF:mode>"
- [(match_operand:VSTRUCT 0 "register_operand" "=w")
- (match_operand:DI 1 "register_operand" "w")
- (match_operand:VSTRUCT 2 "register_operand" "0")
- (match_operand:SI 3 "immediate_operand" "i")
+ [(match_operand:VSTRUCT 0 "register_operand")
+ (match_operand:DI 1 "register_operand")
+ (match_operand:VSTRUCT 2 "register_operand")
+ (match_operand:SI 3 "immediate_operand")
(unspec:VALLDIF [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
"TARGET_SIMD"
{
@@ -5579,9 +5612,9 @@
;; D-register list.
(define_expand "aarch64_get_dreg<VSTRUCT:mode><VDC:mode>"
- [(match_operand:VDC 0 "register_operand" "=w")
- (match_operand:VSTRUCT 1 "register_operand" "w")
- (match_operand:SI 2 "immediate_operand" "i")]
+ [(match_operand:VDC 0 "register_operand")
+ (match_operand:VSTRUCT 1 "register_operand")
+ (match_operand:SI 2 "immediate_operand")]
"TARGET_SIMD"
{
int part = INTVAL (operands[2]);
@@ -5596,9 +5629,9 @@
;; Q-register list.
(define_expand "aarch64_get_qreg<VSTRUCT:mode><VQ:mode>"
- [(match_operand:VQ 0 "register_operand" "=w")
- (match_operand:VSTRUCT 1 "register_operand" "w")
- (match_operand:SI 2 "immediate_operand" "i")]
+ [(match_operand:VQ 0 "register_operand")
+ (match_operand:VSTRUCT 1 "register_operand")
+ (match_operand:SI 2 "immediate_operand")]
"TARGET_SIMD"
{
int part = INTVAL (operands[2]);
@@ -5837,8 +5870,8 @@
)
(define_expand "aarch64_st<VSTRUCT:nregs><VDC:mode>"
- [(match_operand:DI 0 "register_operand" "r")
- (match_operand:VSTRUCT 1 "register_operand" "w")
+ [(match_operand:DI 0 "register_operand")
+ (match_operand:VSTRUCT 1 "register_operand")
(unspec:VDC [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
"TARGET_SIMD"
{
@@ -5850,8 +5883,8 @@
})
(define_expand "aarch64_st<VSTRUCT:nregs><VQ:mode>"
- [(match_operand:DI 0 "register_operand" "r")
- (match_operand:VSTRUCT 1 "register_operand" "w")
+ [(match_operand:DI 0 "register_operand")
+ (match_operand:VSTRUCT 1 "register_operand")
(unspec:VQ [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
"TARGET_SIMD"
{
@@ -5863,8 +5896,8 @@
})
(define_expand "aarch64_st<VSTRUCT:nregs>_lane<VALLDIF:mode>"
- [(match_operand:DI 0 "register_operand" "r")
- (match_operand:VSTRUCT 1 "register_operand" "w")
+ [(match_operand:DI 0 "register_operand")
+ (match_operand:VSTRUCT 1 "register_operand")
(unspec:VALLDIF [(const_int 0)] UNSPEC_VSTRUCTDUMMY)
(match_operand:SI 2 "immediate_operand")]
"TARGET_SIMD"
@@ -5900,10 +5933,10 @@
;; extend them in arm_neon.h and insert the resulting Q-regs.
(define_expand "aarch64_set_qreg<VSTRUCT:mode><VQ:mode>"
- [(match_operand:VSTRUCT 0 "register_operand" "+w")
- (match_operand:VSTRUCT 1 "register_operand" "0")
- (match_operand:VQ 2 "register_operand" "w")
- (match_operand:SI 3 "immediate_operand" "i")]
+ [(match_operand:VSTRUCT 0 "register_operand")
+ (match_operand:VSTRUCT 1 "register_operand")
+ (match_operand:VQ 2 "register_operand")
+ (match_operand:SI 3 "immediate_operand")]
"TARGET_SIMD"
{
int part = INTVAL (operands[3]);
@@ -5918,7 +5951,16 @@
;; Standard pattern name vec_init<mode><Vel>.
(define_expand "vec_init<mode><Vel>"
- [(match_operand:VALL_F16 0 "register_operand" "")
+ [(match_operand:VALL_F16 0 "register_operand")
+ (match_operand 1 "" "")]
+ "TARGET_SIMD"
+{
+ aarch64_expand_vector_init (operands[0], operands[1]);
+ DONE;
+})
+
+(define_expand "vec_init<mode><Vhalf>"
+ [(match_operand:VQ_NO2E 0 "register_operand")
(match_operand 1 "" "")]
"TARGET_SIMD"
{
@@ -5997,9 +6039,9 @@
;; Standard pattern name vec_extract<mode><Vel>.
(define_expand "vec_extract<mode><Vel>"
- [(match_operand:<VEL> 0 "aarch64_simd_nonimmediate_operand" "")
- (match_operand:VALL_F16 1 "register_operand" "")
- (match_operand:SI 2 "immediate_operand" "")]
+ [(match_operand:<VEL> 0 "aarch64_simd_nonimmediate_operand")
+ (match_operand:VALL_F16 1 "register_operand")
+ (match_operand:SI 2 "immediate_operand")]
"TARGET_SIMD"
{
emit_insn
@@ -6345,11 +6387,11 @@
;; fp16fml
(define_expand "aarch64_fml<f16mac1>l<f16quad>_low<mode>"
- [(set (match_operand:VDQSF 0 "register_operand" "=w")
+ [(set (match_operand:VDQSF 0 "register_operand")
(unspec:VDQSF
- [(match_operand:VDQSF 1 "register_operand" "0")
- (match_operand:<VFMLA_W> 2 "register_operand" "w")
- (match_operand:<VFMLA_W> 3 "register_operand" "w")]
+ [(match_operand:VDQSF 1 "register_operand")
+ (match_operand:<VFMLA_W> 2 "register_operand")
+ (match_operand:<VFMLA_W> 3 "register_operand")]
VFMLA16_LOW))]
"TARGET_F16FML"
{
@@ -6368,11 +6410,11 @@
})
(define_expand "aarch64_fml<f16mac1>l<f16quad>_high<mode>"
- [(set (match_operand:VDQSF 0 "register_operand" "=w")
+ [(set (match_operand:VDQSF 0 "register_operand")
(unspec:VDQSF
- [(match_operand:VDQSF 1 "register_operand" "0")
- (match_operand:<VFMLA_W> 2 "register_operand" "w")
- (match_operand:<VFMLA_W> 3 "register_operand" "w")]
+ [(match_operand:VDQSF 1 "register_operand")
+ (match_operand:<VFMLA_W> 2 "register_operand")
+ (match_operand:<VFMLA_W> 3 "register_operand")]
VFMLA16_HIGH))]
"TARGET_F16FML"
{
@@ -6458,11 +6500,11 @@
)
(define_expand "aarch64_fml<f16mac1>l_lane_lowv2sf"
- [(set (match_operand:V2SF 0 "register_operand" "")
- (unspec:V2SF [(match_operand:V2SF 1 "register_operand" "")
- (match_operand:V4HF 2 "register_operand" "")
- (match_operand:V4HF 3 "register_operand" "")
- (match_operand:SI 4 "aarch64_imm2" "")]
+ [(set (match_operand:V2SF 0 "register_operand")
+ (unspec:V2SF [(match_operand:V2SF 1 "register_operand")
+ (match_operand:V4HF 2 "register_operand")
+ (match_operand:V4HF 3 "register_operand")
+ (match_operand:SI 4 "aarch64_imm2")]
VFMLA16_LOW))]
"TARGET_F16FML"
{
@@ -6479,11 +6521,11 @@
)
(define_expand "aarch64_fml<f16mac1>l_lane_highv2sf"
- [(set (match_operand:V2SF 0 "register_operand" "")
- (unspec:V2SF [(match_operand:V2SF 1 "register_operand" "")
- (match_operand:V4HF 2 "register_operand" "")
- (match_operand:V4HF 3 "register_operand" "")
- (match_operand:SI 4 "aarch64_imm2" "")]
+ [(set (match_operand:V2SF 0 "register_operand")
+ (unspec:V2SF [(match_operand:V2SF 1 "register_operand")
+ (match_operand:V4HF 2 "register_operand")
+ (match_operand:V4HF 3 "register_operand")
+ (match_operand:SI 4 "aarch64_imm2")]
VFMLA16_HIGH))]
"TARGET_F16FML"
{
@@ -6573,11 +6615,11 @@
)
(define_expand "aarch64_fml<f16mac1>lq_laneq_lowv4sf"
- [(set (match_operand:V4SF 0 "register_operand" "")
- (unspec:V4SF [(match_operand:V4SF 1 "register_operand" "")
- (match_operand:V8HF 2 "register_operand" "")
- (match_operand:V8HF 3 "register_operand" "")
- (match_operand:SI 4 "aarch64_lane_imm3" "")]
+ [(set (match_operand:V4SF 0 "register_operand")
+ (unspec:V4SF [(match_operand:V4SF 1 "register_operand")
+ (match_operand:V8HF 2 "register_operand")
+ (match_operand:V8HF 3 "register_operand")
+ (match_operand:SI 4 "aarch64_lane_imm3")]
VFMLA16_LOW))]
"TARGET_F16FML"
{
@@ -6593,11 +6635,11 @@
})
(define_expand "aarch64_fml<f16mac1>lq_laneq_highv4sf"
- [(set (match_operand:V4SF 0 "register_operand" "")
- (unspec:V4SF [(match_operand:V4SF 1 "register_operand" "")
- (match_operand:V8HF 2 "register_operand" "")
- (match_operand:V8HF 3 "register_operand" "")
- (match_operand:SI 4 "aarch64_lane_imm3" "")]
+ [(set (match_operand:V4SF 0 "register_operand")
+ (unspec:V4SF [(match_operand:V4SF 1 "register_operand")
+ (match_operand:V8HF 2 "register_operand")
+ (match_operand:V8HF 3 "register_operand")
+ (match_operand:SI 4 "aarch64_lane_imm3")]
VFMLA16_HIGH))]
"TARGET_F16FML"
{
@@ -6687,11 +6729,11 @@
)
(define_expand "aarch64_fml<f16mac1>l_laneq_lowv2sf"
- [(set (match_operand:V2SF 0 "register_operand" "")
- (unspec:V2SF [(match_operand:V2SF 1 "register_operand" "")
- (match_operand:V4HF 2 "register_operand" "")
- (match_operand:V8HF 3 "register_operand" "")
- (match_operand:SI 4 "aarch64_lane_imm3" "")]
+ [(set (match_operand:V2SF 0 "register_operand")
+ (unspec:V2SF [(match_operand:V2SF 1 "register_operand")
+ (match_operand:V4HF 2 "register_operand")
+ (match_operand:V8HF 3 "register_operand")
+ (match_operand:SI 4 "aarch64_lane_imm3")]
VFMLA16_LOW))]
"TARGET_F16FML"
{
@@ -6708,11 +6750,11 @@
})
(define_expand "aarch64_fml<f16mac1>l_laneq_highv2sf"
- [(set (match_operand:V2SF 0 "register_operand" "")
- (unspec:V2SF [(match_operand:V2SF 1 "register_operand" "")
- (match_operand:V4HF 2 "register_operand" "")
- (match_operand:V8HF 3 "register_operand" "")
- (match_operand:SI 4 "aarch64_lane_imm3" "")]
+ [(set (match_operand:V2SF 0 "register_operand")
+ (unspec:V2SF [(match_operand:V2SF 1 "register_operand")
+ (match_operand:V4HF 2 "register_operand")
+ (match_operand:V8HF 3 "register_operand")
+ (match_operand:SI 4 "aarch64_lane_imm3")]
VFMLA16_HIGH))]
"TARGET_F16FML"
{
@@ -6803,11 +6845,11 @@
)
(define_expand "aarch64_fml<f16mac1>lq_lane_lowv4sf"
- [(set (match_operand:V4SF 0 "register_operand" "")
- (unspec:V4SF [(match_operand:V4SF 1 "register_operand" "")
- (match_operand:V8HF 2 "register_operand" "")
- (match_operand:V4HF 3 "register_operand" "")
- (match_operand:SI 4 "aarch64_imm2" "")]
+ [(set (match_operand:V4SF 0 "register_operand")
+ (unspec:V4SF [(match_operand:V4SF 1 "register_operand")
+ (match_operand:V8HF 2 "register_operand")
+ (match_operand:V4HF 3 "register_operand")
+ (match_operand:SI 4 "aarch64_imm2")]
VFMLA16_LOW))]
"TARGET_F16FML"
{
@@ -6823,11 +6865,11 @@
})
(define_expand "aarch64_fml<f16mac1>lq_lane_highv4sf"
- [(set (match_operand:V4SF 0 "register_operand" "")
- (unspec:V4SF [(match_operand:V4SF 1 "register_operand" "")
- (match_operand:V8HF 2 "register_operand" "")
- (match_operand:V4HF 3 "register_operand" "")
- (match_operand:SI 4 "aarch64_imm2" "")]
+ [(set (match_operand:V4SF 0 "register_operand")
+ (unspec:V4SF [(match_operand:V4SF 1 "register_operand")
+ (match_operand:V8HF 2 "register_operand")
+ (match_operand:V4HF 3 "register_operand")
+ (match_operand:SI 4 "aarch64_imm2")]
VFMLA16_HIGH))]
"TARGET_F16FML"
{
diff --git a/gcc/config/aarch64/aarch64-sve.md b/gcc/config/aarch64/aarch64-sve.md
index e94801d..c4670b6 100644
--- a/gcc/config/aarch64/aarch64-sve.md
+++ b/gcc/config/aarch64/aarch64-sve.md
@@ -72,7 +72,7 @@
head of the file) and increases the addressing choices for
little-endian. */
if ((MEM_P (operands[0]) || MEM_P (operands[1]))
- && can_create_pseudo_p ())
+ && can_create_pseudo_p ())
{
aarch64_expand_sve_mem_move (operands[0], operands[1], <VPRED>mode);
DONE;
@@ -88,7 +88,7 @@
/* Optimize subregs on big-endian targets: we can use REV[BHW]
instead of going through memory. */
if (BYTES_BIG_ENDIAN
- && aarch64_maybe_expand_sve_subreg_move (operands[0], operands[1]))
+ && aarch64_maybe_expand_sve_subreg_move (operands[0], operands[1]))
DONE;
}
)
@@ -100,7 +100,7 @@
(define_insn_and_split "*aarch64_sve_mov<mode>_subreg_be"
[(set (match_operand:SVE_ALL 0 "aarch64_sve_nonimmediate_operand" "=w")
(unspec:SVE_ALL
- [(match_operand:VNx16BI 1 "register_operand" "Upl")
+ [(match_operand:VNx16BI 1 "register_operand" "Upl")
(match_operand 2 "aarch64_any_register_operand" "w")]
UNSPEC_REV_SUBREG))]
"TARGET_SVE && BYTES_BIG_ENDIAN"
@@ -144,10 +144,11 @@
;; Handle big-endian memory reloads. We use byte PTRUE for all modes
;; to try to encourage reuse.
+;; This pattern needs constraints due to TARGET_SECONDARY_RELOAD hook.
(define_expand "aarch64_sve_reload_be"
[(parallel
[(set (match_operand 0)
- (match_operand 1))
+ (match_operand 1))
(clobber (match_operand:VNx16BI 2 "register_operand" "=Upl"))])]
"TARGET_SVE && BYTES_BIG_ENDIAN"
{
@@ -232,7 +233,7 @@
UNSPEC_LD1_GATHER))]
"TARGET_SVE"
{
- operands[5] = force_reg (<VPRED>mode, CONSTM1_RTX (<VPRED>mode));
+ operands[5] = aarch64_ptrue_reg (<VPRED>mode);
}
)
@@ -289,7 +290,7 @@
UNSPEC_ST1_SCATTER))]
"TARGET_SVE"
{
- operands[5] = force_reg (<VPRED>mode, CONSTM1_RTX (<VPRED>mode));
+ operands[5] = aarch64_ptrue_reg (<VPRED>mode);
}
)
@@ -488,7 +489,7 @@
{
/* The last element can be extracted with a LASTB and a false
predicate. */
- rtx sel = force_reg (<VPRED>mode, CONST0_RTX (<VPRED>mode));
+ rtx sel = aarch64_pfalse_reg (<VPRED>mode);
emit_insn (gen_extract_last_<mode> (operands[0], sel, operands[1]));
DONE;
}
@@ -629,7 +630,7 @@
{
if (MEM_P (operands[1]))
{
- rtx ptrue = force_reg (<VPRED>mode, CONSTM1_RTX (<VPRED>mode));
+ rtx ptrue = aarch64_ptrue_reg (<VPRED>mode);
emit_insn (gen_sve_ld1r<mode> (operands[0], ptrue, operands[1],
CONST0_RTX (<MODE>mode)));
DONE;
@@ -744,7 +745,7 @@
UNSPEC_LDN))]
"TARGET_SVE"
{
- operands[2] = force_reg (<VPRED>mode, CONSTM1_RTX (<VPRED>mode));
+ operands[2] = aarch64_ptrue_reg (<VPRED>mode);
}
)
@@ -773,7 +774,7 @@
UNSPEC_STN))]
"TARGET_SVE"
{
- operands[2] = force_reg (<VPRED>mode, CONSTM1_RTX (<VPRED>mode));
+ operands[2] = aarch64_ptrue_reg (<VPRED>mode);
}
)
@@ -863,7 +864,7 @@
"revb\t%0.h, %1/m, %2.h"
)
-(define_insn "*aarch64_sve_rev<mode>"
+(define_insn "@aarch64_sve_rev<mode>"
[(set (match_operand:SVE_ALL 0 "register_operand" "=w")
(unspec:SVE_ALL [(match_operand:SVE_ALL 1 "register_operand" "w")]
UNSPEC_REV))]
@@ -932,7 +933,7 @@
UNSPEC_MERGE_PTRUE))]
"TARGET_SVE"
{
- operands[3] = force_reg (<VPRED>mode, CONSTM1_RTX (<VPRED>mode));
+ operands[3] = aarch64_ptrue_reg (<VPRED>mode);
}
)
@@ -1019,7 +1020,7 @@
UNSPEC_MERGE_PTRUE))]
"TARGET_SVE"
{
- operands[3] = force_reg (<VPRED>mode, CONSTM1_RTX (<VPRED>mode));
+ operands[3] = aarch64_ptrue_reg (<VPRED>mode);
}
)
@@ -1050,7 +1051,7 @@
UNSPEC_MERGE_PTRUE))]
"TARGET_SVE"
{
- operands[3] = force_reg (<VPRED>mode, CONSTM1_RTX (<VPRED>mode));
+ operands[3] = aarch64_ptrue_reg (<VPRED>mode);
}
)
@@ -1080,7 +1081,7 @@
UNSPEC_MERGE_PTRUE))]
"TARGET_SVE"
{
- operands[2] = force_reg (<VPRED>mode, CONSTM1_RTX (<VPRED>mode));
+ operands[2] = aarch64_ptrue_reg (<VPRED>mode);
}
)
@@ -1150,7 +1151,7 @@
(match_dup 3)))]
"TARGET_SVE"
{
- operands[3] = force_reg (<MODE>mode, CONSTM1_RTX (<MODE>mode));
+ operands[3] = aarch64_ptrue_reg (<MODE>mode);
}
)
@@ -1172,16 +1173,15 @@
;; UNSPEC_PTEST_PTRUE is logically redundant, but means that the tested
;; value is structurally equivalent to rhs of the second set.
(define_insn "*<optab><mode>3_cc"
- [(set (reg:CC CC_REGNUM)
- (compare:CC
- (unspec:SI [(match_operand:PRED_ALL 1 "register_operand" "Upa")
- (and:PRED_ALL
- (LOGICAL:PRED_ALL
- (match_operand:PRED_ALL 2 "register_operand" "Upa")
- (match_operand:PRED_ALL 3 "register_operand" "Upa"))
- (match_dup 1))]
- UNSPEC_PTEST_PTRUE)
- (const_int 0)))
+ [(set (reg:CC_NZC CC_REGNUM)
+ (unspec:CC_NZC
+ [(match_operand:PRED_ALL 1 "register_operand" "Upa")
+ (and:PRED_ALL
+ (LOGICAL:PRED_ALL
+ (match_operand:PRED_ALL 2 "register_operand" "Upa")
+ (match_operand:PRED_ALL 3 "register_operand" "Upa"))
+ (match_dup 1))]
+ UNSPEC_PTEST_PTRUE))
(set (match_operand:PRED_ALL 0 "register_operand" "=Upa")
(and:PRED_ALL (LOGICAL:PRED_ALL (match_dup 2) (match_dup 3))
(match_dup 1)))]
@@ -1197,7 +1197,7 @@
(match_dup 2)))]
"TARGET_SVE"
{
- operands[2] = force_reg (<MODE>mode, CONSTM1_RTX (<MODE>mode));
+ operands[2] = aarch64_ptrue_reg (<MODE>mode);
}
)
@@ -1246,7 +1246,7 @@
UNSPEC_MERGE_PTRUE))]
"TARGET_SVE"
{
- operands[3] = force_reg (<VPRED>mode, CONSTM1_RTX (<VPRED>mode));
+ operands[3] = aarch64_ptrue_reg (<VPRED>mode);
}
)
@@ -1320,12 +1320,11 @@
;; the constant. We would use a separate unspec code for PTESTs involving
;; GPs that might not be PTRUEs.
(define_insn "ptest_ptrue<mode>"
- [(set (reg:CC CC_REGNUM)
- (compare:CC
- (unspec:SI [(match_operand:PRED_ALL 0 "register_operand" "Upa")
- (match_operand:PRED_ALL 1 "register_operand" "Upa")]
- UNSPEC_PTEST_PTRUE)
- (const_int 0)))]
+ [(set (reg:CC_NZC CC_REGNUM)
+ (unspec:CC_NZC
+ [(match_operand:PRED_ALL 0 "register_operand" "Upa")
+ (match_operand:PRED_ALL 1 "register_operand" "Upa")]
+ UNSPEC_PTEST_PTRUE))]
"TARGET_SVE"
"ptest\t%0, %1.b"
)
@@ -1337,7 +1336,7 @@
(unspec:PRED_ALL [(match_operand:GPI 1 "aarch64_reg_or_zero" "rZ")
(match_operand:GPI 2 "aarch64_reg_or_zero" "rZ")]
UNSPEC_WHILE_LO))
- (clobber (reg:CC CC_REGNUM))]
+ (clobber (reg:CC_NZC CC_REGNUM))]
"TARGET_SVE"
"whilelo\t%0.<PRED_ALL:Vetype>, %<w>1, %<w>2"
)
@@ -1345,16 +1344,15 @@
;; WHILELO sets the flags in the same way as a PTEST with a PTRUE GP.
;; Handle the case in which both results are useful. The GP operand
;; to the PTEST isn't needed, so we allow it to be anything.
-(define_insn_and_split "while_ult<GPI:mode><PRED_ALL:mode>_cc"
- [(set (reg:CC CC_REGNUM)
- (compare:CC
- (unspec:SI [(match_operand:PRED_ALL 1)
- (unspec:PRED_ALL
- [(match_operand:GPI 2 "aarch64_reg_or_zero" "rZ")
- (match_operand:GPI 3 "aarch64_reg_or_zero" "rZ")]
- UNSPEC_WHILE_LO)]
- UNSPEC_PTEST_PTRUE)
- (const_int 0)))
+(define_insn_and_rewrite "*while_ult<GPI:mode><PRED_ALL:mode>_cc"
+ [(set (reg:CC_NZC CC_REGNUM)
+ (unspec:CC_NZC
+ [(match_operand:PRED_ALL 1)
+ (unspec:PRED_ALL
+ [(match_operand:GPI 2 "aarch64_reg_or_zero" "rZ")
+ (match_operand:GPI 3 "aarch64_reg_or_zero" "rZ")]
+ UNSPEC_WHILE_LO)]
+ UNSPEC_PTEST_PTRUE))
(set (match_operand:PRED_ALL 0 "register_operand" "=Upa")
(unspec:PRED_ALL [(match_dup 2)
(match_dup 3)]
@@ -1364,12 +1362,8 @@
;; Force the compiler to drop the unused predicate operand, so that we
;; don't have an unnecessary PTRUE.
"&& !CONSTANT_P (operands[1])"
- [(const_int 0)]
{
- emit_insn (gen_while_ult<GPI:mode><PRED_ALL:mode>_cc
- (operands[0], CONSTM1_RTX (<MODE>mode),
- operands[2], operands[3]));
- DONE;
+ operands[1] = CONSTM1_RTX (<MODE>mode);
}
)
@@ -1382,7 +1376,7 @@
(match_operand:SVE_I 2 "register_operand" "w, w")
(match_operand:SVE_I 3 "aarch64_sve_cmp_<sve_imm_con>_operand" "<sve_imm_con>, w"))]
UNSPEC_MERGE_PTRUE))
- (clobber (reg:CC CC_REGNUM))]
+ (clobber (reg:CC_NZC CC_REGNUM))]
"TARGET_SVE"
"@
cmp<cmp_op>\t%0.<Vetype>, %1/z, %2.<Vetype>, #%3
@@ -1392,18 +1386,16 @@
;; Integer comparisons predicated with a PTRUE in which only the flags result
;; is interesting.
(define_insn "*cmp<cmp_op><mode>_ptest"
- [(set (reg:CC CC_REGNUM)
- (compare:CC
- (unspec:SI
- [(match_operand:<VPRED> 1 "register_operand" "Upl, Upl")
- (unspec:<VPRED>
- [(match_dup 1)
- (SVE_INT_CMP:<VPRED>
- (match_operand:SVE_I 2 "register_operand" "w, w")
- (match_operand:SVE_I 3 "aarch64_sve_cmp_<sve_imm_con>_operand" "<sve_imm_con>, w"))]
- UNSPEC_MERGE_PTRUE)]
- UNSPEC_PTEST_PTRUE)
- (const_int 0)))
+ [(set (reg:CC_NZC CC_REGNUM)
+ (unspec:CC_NZC
+ [(match_operand:<VPRED> 1 "register_operand" "Upl, Upl")
+ (unspec:<VPRED>
+ [(match_dup 1)
+ (SVE_INT_CMP:<VPRED>
+ (match_operand:SVE_I 2 "register_operand" "w, w")
+ (match_operand:SVE_I 3 "aarch64_sve_cmp_<sve_imm_con>_operand" "<sve_imm_con>, w"))]
+ UNSPEC_MERGE_PTRUE)]
+ UNSPEC_PTEST_PTRUE))
(clobber (match_scratch:<VPRED> 0 "=Upa, Upa"))]
"TARGET_SVE"
"@
@@ -1414,18 +1406,16 @@
;; Integer comparisons predicated with a PTRUE in which both the flag and
;; predicate results are interesting.
(define_insn "*cmp<cmp_op><mode>_cc"
- [(set (reg:CC CC_REGNUM)
- (compare:CC
- (unspec:SI
- [(match_operand:<VPRED> 1 "register_operand" "Upl, Upl")
- (unspec:<VPRED>
- [(match_dup 1)
- (SVE_INT_CMP:<VPRED>
- (match_operand:SVE_I 2 "register_operand" "w, w")
- (match_operand:SVE_I 3 "aarch64_sve_cmp_<sve_imm_con>_operand" "<sve_imm_con>, w"))]
- UNSPEC_MERGE_PTRUE)]
- UNSPEC_PTEST_PTRUE)
- (const_int 0)))
+ [(set (reg:CC_NZC CC_REGNUM)
+ (unspec:CC_NZC
+ [(match_operand:<VPRED> 1 "register_operand" "Upl, Upl")
+ (unspec:<VPRED>
+ [(match_dup 1)
+ (SVE_INT_CMP:<VPRED>
+ (match_operand:SVE_I 2 "register_operand" "w, w")
+ (match_operand:SVE_I 3 "aarch64_sve_cmp_<sve_imm_con>_operand" "<sve_imm_con>, w"))]
+ UNSPEC_MERGE_PTRUE)]
+ UNSPEC_PTEST_PTRUE))
(set (match_operand:<VPRED> 0 "register_operand" "=Upa, Upa")
(unspec:<VPRED>
[(match_dup 1)
@@ -1446,25 +1436,25 @@
(define_insn_and_split "*pred_cmp<cmp_op><mode>_combine"
[(set (match_operand:<VPRED> 0 "register_operand" "=Upa, Upa")
(and:<VPRED>
- (unspec:<VPRED>
- [(match_operand:<VPRED> 1)
- (SVE_INT_CMP:<VPRED>
- (match_operand:SVE_I 2 "register_operand" "w, w")
- (match_operand:SVE_I 3 "aarch64_sve_cmp_<sve_imm_con>_operand" "<sve_imm_con>, w"))]
- UNSPEC_MERGE_PTRUE)
- (match_operand:<VPRED> 4 "register_operand" "Upl, Upl")))
- (clobber (reg:CC CC_REGNUM))]
+ (unspec:<VPRED>
+ [(match_operand:<VPRED> 1)
+ (SVE_INT_CMP:<VPRED>
+ (match_operand:SVE_I 2 "register_operand" "w, w")
+ (match_operand:SVE_I 3 "aarch64_sve_cmp_<sve_imm_con>_operand" "<sve_imm_con>, w"))]
+ UNSPEC_MERGE_PTRUE)
+ (match_operand:<VPRED> 4 "register_operand" "Upl, Upl")))
+ (clobber (reg:CC_NZC CC_REGNUM))]
"TARGET_SVE"
"#"
"&& 1"
[(parallel
[(set (match_dup 0)
- (and:<VPRED>
- (SVE_INT_CMP:<VPRED>
- (match_dup 2)
- (match_dup 3))
- (match_dup 4)))
- (clobber (reg:CC CC_REGNUM))])]
+ (and:<VPRED>
+ (SVE_INT_CMP:<VPRED>
+ (match_dup 2)
+ (match_dup 3))
+ (match_dup 4)))
+ (clobber (reg:CC_NZC CC_REGNUM))])]
)
;; Predicated integer comparisons.
@@ -1475,7 +1465,7 @@
(match_operand:SVE_I 2 "register_operand" "w, w")
(match_operand:SVE_I 3 "aarch64_sve_cmp_<sve_imm_con>_operand" "<sve_imm_con>, w"))
(match_operand:<VPRED> 1 "register_operand" "Upl, Upl")))
- (clobber (reg:CC CC_REGNUM))]
+ (clobber (reg:CC_NZC CC_REGNUM))]
"TARGET_SVE"
"@
cmp<cmp_op>\t%0.<Vetype>, %1/z, %2.<Vetype>, #%3
@@ -1688,7 +1678,7 @@
(match_operator:<VPRED> 1 "comparison_operator"
[(match_operand:SVE_I 2 "register_operand")
(match_operand:SVE_I 3 "nonmemory_operand")]))
- (clobber (reg:CC CC_REGNUM))])]
+ (clobber (reg:CC_NZC CC_REGNUM))])]
"TARGET_SVE"
{
aarch64_expand_sve_vec_cmp_int (operands[0], GET_CODE (operands[1]),
@@ -1706,7 +1696,7 @@
(match_operator:<VPRED> 1 "comparison_operator"
[(match_operand:SVE_I 2 "register_operand")
(match_operand:SVE_I 3 "nonmemory_operand")]))
- (clobber (reg:CC CC_REGNUM))])]
+ (clobber (reg:CC_NZC CC_REGNUM))])]
"TARGET_SVE"
{
aarch64_expand_sve_vec_cmp_int (operands[0], GET_CODE (operands[1]),
@@ -1742,7 +1732,7 @@
(pc)))]
""
{
- rtx ptrue = force_reg (<MODE>mode, CONSTM1_RTX (<MODE>mode));
+ rtx ptrue = aarch64_ptrue_reg (<MODE>mode);
rtx pred;
if (operands[2] == CONST0_RTX (<MODE>mode))
pred = operands[1];
@@ -1753,7 +1743,7 @@
operands[2]));
}
emit_insn (gen_ptest_ptrue<mode> (ptrue, pred));
- operands[1] = gen_rtx_REG (CCmode, CC_REGNUM);
+ operands[1] = gen_rtx_REG (CC_NZCmode, CC_REGNUM);
operands[2] = const0_rtx;
}
)
@@ -1768,7 +1758,7 @@
UNSPEC_MERGE_PTRUE))]
"TARGET_SVE"
{
- operands[3] = force_reg (<VPRED>mode, CONSTM1_RTX (<VPRED>mode));
+ operands[3] = aarch64_ptrue_reg (<VPRED>mode);
}
)
@@ -1797,7 +1787,7 @@
UNSPEC_MERGE_PTRUE))]
"TARGET_SVE"
{
- operands[3] = force_reg (<VPRED>mode, CONSTM1_RTX (<VPRED>mode));
+ operands[3] = aarch64_ptrue_reg (<VPRED>mode);
}
)
@@ -1827,7 +1817,7 @@
UNSPEC_MERGE_PTRUE))]
"TARGET_SVE"
{
- operands[3] = force_reg (<VPRED>mode, CONSTM1_RTX (<VPRED>mode));
+ operands[3] = aarch64_ptrue_reg (<VPRED>mode);
}
)
@@ -1872,41 +1862,6 @@
"TARGET_SVE"
)
-;; Predicated integer operations with select matching the output operand.
-(define_insn "*cond_<optab><mode>_0"
- [(set (match_operand:SVE_I 0 "register_operand" "+w, w, ?&w")
- (unspec:SVE_I
- [(match_operand:<VPRED> 1 "register_operand" "Upl, Upl, Upl")
- (SVE_INT_BINARY:SVE_I
- (match_operand:SVE_I 2 "register_operand" "0, w, w")
- (match_operand:SVE_I 3 "register_operand" "w, 0, w"))
- (match_dup 0)]
- UNSPEC_SEL))]
- "TARGET_SVE"
- "@
- <sve_int_op>\t%0.<Vetype>, %1/m, %0.<Vetype>, %3.<Vetype>
- <sve_int_op_rev>\t%0.<Vetype>, %1/m, %0.<Vetype>, %2.<Vetype>
- movprfx\t%0, %1/m, %2\;<sve_int_op>\t%0.<Vetype>, %1/m, %0.<Vetype>, %3.<Vetype>"
- [(set_attr "movprfx" "*,*,yes")]
-)
-
-(define_insn "*cond_<optab><mode>_0"
- [(set (match_operand:SVE_SDI 0 "register_operand" "+w, w, ?&w")
- (unspec:SVE_SDI
- [(match_operand:<VPRED> 1 "register_operand" "Upl, Upl, Upl")
- (SVE_INT_BINARY_SD:SVE_SDI
- (match_operand:SVE_SDI 2 "register_operand" "0, w, w")
- (match_operand:SVE_SDI 3 "register_operand" "w, 0, w"))
- (match_dup 0)]
- UNSPEC_SEL))]
- "TARGET_SVE"
- "@
- <sve_int_op>\t%0.<Vetype>, %1/m, %0.<Vetype>, %3.<Vetype>
- <sve_int_op_rev>\t%0.<Vetype>, %1/m, %0.<Vetype>, %2.<Vetype>
- movprfx\t%0, %1/m, %2\;<sve_int_op>\t%0.<Vetype>, %1/m, %0.<Vetype>, %3.<Vetype>"
- [(set_attr "movprfx" "*,*,yes")]
-)
-
;; Predicated integer operations with select matching the first operand.
(define_insn "*cond_<optab><mode>_2"
[(set (match_operand:SVE_I 0 "register_operand" "=w, ?&w")
@@ -1973,87 +1928,66 @@
[(set_attr "movprfx" "*,yes")]
)
-;; Predicated integer operations with select matching zero.
-(define_insn "*cond_<optab><mode>_z"
- [(set (match_operand:SVE_I 0 "register_operand" "=&w")
+;; Predicated integer binary operations in which the values of inactive
+;; lanes are distinct from the other inputs.
+(define_insn_and_rewrite "*cond_<optab><mode>_any"
+ [(set (match_operand:SVE_I 0 "register_operand" "=&w, &w, &w, &w, ?&w")
(unspec:SVE_I
- [(match_operand:<VPRED> 1 "register_operand" "Upl")
+ [(match_operand:<VPRED> 1 "register_operand" "Upl, Upl, Upl, Upl, Upl")
(SVE_INT_BINARY:SVE_I
- (match_operand:SVE_I 2 "register_operand" "w")
- (match_operand:SVE_I 3 "register_operand" "w"))
- (match_operand:SVE_I 4 "aarch64_simd_imm_zero")]
+ (match_operand:SVE_I 2 "register_operand" "0, w, w, w, w")
+ (match_operand:SVE_I 3 "register_operand" "w, 0, w, w, w"))
+ (match_operand:SVE_I 4 "aarch64_simd_reg_or_zero" "Dz, Dz, Dz, 0, w")]
UNSPEC_SEL))]
- "TARGET_SVE"
- "movprfx\t%0.<Vetype>, %1/z, %2.<Vetype>\;<sve_int_op>\t%0.<Vetype>, %1/m, %0.<Vetype>, %3.<Vetype>"
+ "TARGET_SVE
+ && !rtx_equal_p (operands[2], operands[4])
+ && !rtx_equal_p (operands[3], operands[4])"
+ "@
+ movprfx\t%0.<Vetype>, %1/z, %0.<Vetype>\;<sve_int_op>\t%0.<Vetype>, %1/m, %0.<Vetype>, %3.<Vetype>
+ movprfx\t%0.<Vetype>, %1/z, %0.<Vetype>\;<sve_int_op_rev>\t%0.<Vetype>, %1/m, %0.<Vetype>, %2.<Vetype>
+ movprfx\t%0.<Vetype>, %1/z, %2.<Vetype>\;<sve_int_op>\t%0.<Vetype>, %1/m, %0.<Vetype>, %3.<Vetype>
+ movprfx\t%0.<Vetype>, %1/m, %2.<Vetype>\;<sve_int_op>\t%0.<Vetype>, %1/m, %0.<Vetype>, %3.<Vetype>
+ #"
+ "&& reload_completed
+ && register_operand (operands[4], <MODE>mode)
+ && !rtx_equal_p (operands[0], operands[4])"
+ {
+ emit_insn (gen_vcond_mask_<mode><vpred> (operands[0], operands[2],
+ operands[4], operands[1]));
+ operands[4] = operands[2] = operands[0];
+ }
[(set_attr "movprfx" "yes")]
)
-(define_insn "*cond_<optab><mode>_z"
- [(set (match_operand:SVE_SDI 0 "register_operand" "=&w")
+(define_insn_and_rewrite "*cond_<optab><mode>_any"
+ [(set (match_operand:SVE_SDI 0 "register_operand" "=&w, &w, &w, &w, ?&w")
(unspec:SVE_SDI
- [(match_operand:<VPRED> 1 "register_operand" "Upl")
+ [(match_operand:<VPRED> 1 "register_operand" "Upl, Upl, Upl, Upl, Upl")
(SVE_INT_BINARY_SD:SVE_SDI
- (match_operand:SVE_SDI 2 "register_operand" "w")
- (match_operand:SVE_SDI 3 "register_operand" "w"))
- (match_operand:SVE_SDI 4 "aarch64_simd_imm_zero")]
+ (match_operand:SVE_SDI 2 "register_operand" "0, w, w, w, w")
+ (match_operand:SVE_SDI 3 "register_operand" "w, 0, w, w, w"))
+ (match_operand:SVE_SDI 4 "aarch64_simd_reg_or_zero" "Dz, Dz, Dz, 0, w")]
UNSPEC_SEL))]
- "TARGET_SVE"
- "movprfx\t%0.<Vetype>, %1/z, %2.<Vetype>\;<sve_int_op>\t%0.<Vetype>, %1/m, %0.<Vetype>, %3.<Vetype>"
+ "TARGET_SVE
+ && !rtx_equal_p (operands[2], operands[4])
+ && !rtx_equal_p (operands[3], operands[4])"
+ "@
+ movprfx\t%0.<Vetype>, %1/z, %0.<Vetype>\;<sve_int_op>\t%0.<Vetype>, %1/m, %0.<Vetype>, %3.<Vetype>
+ movprfx\t%0.<Vetype>, %1/z, %0.<Vetype>\;<sve_int_op_rev>\t%0.<Vetype>, %1/m, %0.<Vetype>, %2.<Vetype>
+ movprfx\t%0.<Vetype>, %1/z, %2.<Vetype>\;<sve_int_op>\t%0.<Vetype>, %1/m, %0.<Vetype>, %3.<Vetype>
+ movprfx\t%0.<Vetype>, %1/m, %2.<Vetype>\;<sve_int_op>\t%0.<Vetype>, %1/m, %0.<Vetype>, %3.<Vetype>
+ #"
+ "&& reload_completed
+ && register_operand (operands[4], <MODE>mode)
+ && !rtx_equal_p (operands[0], operands[4])"
+ {
+ emit_insn (gen_vcond_mask_<mode><vpred> (operands[0], operands[2],
+ operands[4], operands[1]));
+ operands[4] = operands[2] = operands[0];
+ }
[(set_attr "movprfx" "yes")]
)
-;; Synthetic predications with select unmatched.
-(define_insn "*cond_<optab><mode>_any"
- [(set (match_operand:SVE_I 0 "register_operand" "=&w")
- (unspec:SVE_I
- [(match_operand:<VPRED> 1 "register_operand" "Upl")
- (SVE_INT_BINARY:SVE_I
- (match_operand:SVE_I 2 "register_operand" "w")
- (match_operand:SVE_I 3 "register_operand" "w"))
- (match_operand:SVE_I 4 "register_operand" "w")]
- UNSPEC_SEL))]
- "TARGET_SVE"
- "#"
-)
-
-(define_insn "*cond_<optab><mode>_any"
- [(set (match_operand:SVE_SDI 0 "register_operand" "=&w")
- (unspec:SVE_SDI
- [(match_operand:<VPRED> 1 "register_operand" "Upl")
- (SVE_INT_BINARY_SD:SVE_I
- (match_operand:SVE_SDI 2 "register_operand" "w")
- (match_operand:SVE_SDI 3 "register_operand" "w"))
- (match_operand:SVE_SDI 4 "register_operand" "w")]
- UNSPEC_SEL))]
- "TARGET_SVE"
- "#"
-)
-
-(define_split
- [(set (match_operand:SVE_I 0 "register_operand")
- (unspec:SVE_I
- [(match_operand:<VPRED> 1 "register_operand")
- (match_operator:SVE_I 5 "aarch64_sve_any_binary_operator"
- [(match_operand:SVE_I 2 "register_operand")
- (match_operand:SVE_I 3 "register_operand")])
- (match_operand:SVE_I 4 "register_operand")]
- UNSPEC_SEL))]
- "TARGET_SVE && reload_completed
- && !(rtx_equal_p (operands[0], operands[4])
- || rtx_equal_p (operands[2], operands[4])
- || rtx_equal_p (operands[3], operands[4]))"
- ; Not matchable by any one insn or movprfx insn. We need a separate select.
- [(set (match_dup 0)
- (unspec:SVE_I [(match_dup 1) (match_dup 2) (match_dup 4)]
- UNSPEC_SEL))
- (set (match_dup 0)
- (unspec:SVE_I
- [(match_dup 1)
- (match_op_dup 5 [(match_dup 0) (match_dup 3)])
- (match_dup 0)]
- UNSPEC_SEL))]
-)
-
;; Set operand 0 to the last active element in operand 3, or to tied
;; operand 1 if no elements are active.
(define_insn "fold_extract_last_<mode>"
@@ -2077,7 +2011,7 @@
UNSPEC_ADDV))]
"TARGET_SVE"
{
- operands[2] = force_reg (<VPRED>mode, CONSTM1_RTX (<VPRED>mode));
+ operands[2] = aarch64_ptrue_reg (<VPRED>mode);
}
)
@@ -2099,7 +2033,7 @@
UNSPEC_FADDV))]
"TARGET_SVE"
{
- operands[2] = force_reg (<VPRED>mode, CONSTM1_RTX (<VPRED>mode));
+ operands[2] = aarch64_ptrue_reg (<VPRED>mode);
}
)
@@ -2121,7 +2055,7 @@
MAXMINV))]
"TARGET_SVE"
{
- operands[2] = force_reg (<VPRED>mode, CONSTM1_RTX (<VPRED>mode));
+ operands[2] = aarch64_ptrue_reg (<VPRED>mode);
}
)
@@ -2143,7 +2077,7 @@
FMAXMINV))]
"TARGET_SVE"
{
- operands[2] = force_reg (<VPRED>mode, CONSTM1_RTX (<VPRED>mode));
+ operands[2] = aarch64_ptrue_reg (<VPRED>mode);
}
)
@@ -2164,7 +2098,7 @@
BITWISEV))]
"TARGET_SVE"
{
- operands[2] = force_reg (<VPRED>mode, CONSTM1_RTX (<VPRED>mode));
+ operands[2] = aarch64_ptrue_reg (<VPRED>mode);
}
)
@@ -2186,19 +2120,19 @@
UNSPEC_FADDA))]
"TARGET_SVE"
{
- operands[3] = force_reg (<VPRED>mode, CONSTM1_RTX (<VPRED>mode));
+ operands[3] = aarch64_ptrue_reg (<VPRED>mode);
}
)
;; In-order FP reductions predicated with PTRUE.
-(define_insn "*fold_left_plus_<mode>"
+(define_insn "mask_fold_left_plus_<mode>"
[(set (match_operand:<VEL> 0 "register_operand" "=w")
- (unspec:<VEL> [(match_operand:<VPRED> 1 "register_operand" "Upl")
- (match_operand:<VEL> 2 "register_operand" "0")
- (match_operand:SVE_F 3 "register_operand" "w")]
+ (unspec:<VEL> [(match_operand:<VPRED> 3 "register_operand" "Upl")
+ (match_operand:<VEL> 1 "register_operand" "0")
+ (match_operand:SVE_F 2 "register_operand" "w")]
UNSPEC_FADDA))]
"TARGET_SVE"
- "fadda\t%<Vetype>0, %1, %<Vetype>0, %3.<Vetype>"
+ "fadda\t%<Vetype>0, %3, %<Vetype>0, %2.<Vetype>"
)
;; Predicated form of the above in-order reduction.
@@ -2227,7 +2161,7 @@
UNSPEC_MERGE_PTRUE))]
"TARGET_SVE"
{
- operands[3] = force_reg (<VPRED>mode, CONSTM1_RTX (<VPRED>mode));
+ operands[3] = aarch64_ptrue_reg (<VPRED>mode);
}
)
@@ -2263,7 +2197,7 @@
UNSPEC_MERGE_PTRUE))]
"TARGET_SVE"
{
- operands[3] = force_reg (<VPRED>mode, CONSTM1_RTX (<VPRED>mode));
+ operands[3] = aarch64_ptrue_reg (<VPRED>mode);
}
)
@@ -2303,7 +2237,7 @@
UNSPEC_MERGE_PTRUE))]
"TARGET_SVE"
{
- operands[3] = force_reg (<VPRED>mode, CONSTM1_RTX (<VPRED>mode));
+ operands[3] = aarch64_ptrue_reg (<VPRED>mode);
}
)
@@ -2349,7 +2283,7 @@
UNSPEC_MERGE_PTRUE))]
"TARGET_SVE"
{
- operands[4] = force_reg (<VPRED>mode, CONSTM1_RTX (<VPRED>mode));
+ operands[4] = aarch64_ptrue_reg (<VPRED>mode);
}
)
@@ -2382,7 +2316,7 @@
UNSPEC_MERGE_PTRUE))]
"TARGET_SVE"
{
- operands[4] = force_reg (<VPRED>mode, CONSTM1_RTX (<VPRED>mode));
+ operands[4] = aarch64_ptrue_reg (<VPRED>mode);
}
)
@@ -2416,7 +2350,7 @@
UNSPEC_MERGE_PTRUE))]
"TARGET_SVE"
{
- operands[4] = force_reg (<VPRED>mode, CONSTM1_RTX (<VPRED>mode));
+ operands[4] = aarch64_ptrue_reg (<VPRED>mode);
}
)
@@ -2451,7 +2385,7 @@
UNSPEC_MERGE_PTRUE))]
"TARGET_SVE"
{
- operands[4] = force_reg (<VPRED>mode, CONSTM1_RTX (<VPRED>mode));
+ operands[4] = aarch64_ptrue_reg (<VPRED>mode);
}
)
@@ -2484,7 +2418,7 @@
UNSPEC_MERGE_PTRUE))]
"TARGET_SVE"
{
- operands[3] = force_reg (<VPRED>mode, CONSTM1_RTX (<VPRED>mode));
+ operands[3] = aarch64_ptrue_reg (<VPRED>mode);
}
)
@@ -2513,7 +2447,7 @@
UNSPEC_MERGE_PTRUE))]
"TARGET_SVE"
{
- operands[2] = force_reg (<VPRED>mode, CONSTM1_RTX (<VPRED>mode));
+ operands[2] = aarch64_ptrue_reg (<VPRED>mode);
}
)
@@ -2528,6 +2462,19 @@
"<sve_fp_op>\t%0.<Vetype>, %1/m, %2.<Vetype>"
)
+(define_insn "*fabd<mode>3"
+ [(set (match_operand:SVE_F 0 "register_operand" "=w")
+ (unspec:SVE_F
+ [(match_operand:<VPRED> 1 "register_operand" "Upl")
+ (abs:SVE_F
+ (minus:SVE_F
+ (match_operand:SVE_F 2 "register_operand" "0")
+ (match_operand:SVE_F 3 "register_operand" "w")))]
+ UNSPEC_MERGE_PTRUE))]
+ "TARGET_SVE"
+ "fabd\t%0.<Vetype>, %1/m, %2.<Vetype>, %3.<Vetype>"
+)
+
;; Unpredicated FRINTy.
(define_expand "<frint_pattern><mode>2"
[(set (match_operand:SVE_F 0 "register_operand")
@@ -2538,7 +2485,7 @@
UNSPEC_MERGE_PTRUE))]
"TARGET_SVE"
{
- operands[2] = force_reg (<VPRED>mode, CONSTM1_RTX (<VPRED>mode));
+ operands[2] = aarch64_ptrue_reg (<VPRED>mode);
}
)
@@ -2565,7 +2512,7 @@
UNSPEC_MERGE_PTRUE))]
"TARGET_SVE"
{
- operands[2] = force_reg (<VPRED>mode, CONSTM1_RTX (<VPRED>mode));
+ operands[2] = aarch64_ptrue_reg (<VPRED>mode);
}
)
@@ -2616,7 +2563,7 @@
UNSPEC_MERGE_PTRUE))]
"TARGET_SVE"
{
- operands[2] = force_reg (<VPRED>mode, CONSTM1_RTX (<VPRED>mode));
+ operands[2] = aarch64_ptrue_reg (<VPRED>mode);
}
)
@@ -2754,7 +2701,7 @@
? gen_aarch64_sve_zip2<mode>
: gen_aarch64_sve_zip1<mode>)
(temp, operands[1], operands[1]));
- rtx ptrue = force_reg (<VWIDE_PRED>mode, CONSTM1_RTX (<VWIDE_PRED>mode));
+ rtx ptrue = aarch64_ptrue_reg (<VWIDE_PRED>mode);
emit_insn (gen_aarch64_sve_extend<mode><Vwide>2 (operands[0],
ptrue, temp));
DONE;
@@ -2777,10 +2724,10 @@
a ZIP whose first operand is zero. */
rtx temp = gen_reg_rtx (VNx4SImode);
emit_insn ((<hi_lanes_optab>
- ? gen_aarch64_sve_zip2vnx4si
- : gen_aarch64_sve_zip1vnx4si)
+ ? gen_aarch64_sve_zip2vnx4si
+ : gen_aarch64_sve_zip1vnx4si)
(temp, operands[1], operands[1]));
- rtx ptrue = force_reg (VNx2BImode, CONSTM1_RTX (VNx2BImode));
+ rtx ptrue = aarch64_ptrue_reg (VNx2BImode);
emit_insn (gen_aarch64_sve_<FLOATUORS:optab>vnx4sivnx2df2 (operands[0],
ptrue, temp));
DONE;
@@ -2830,7 +2777,7 @@
(unspec:SVE_HSF [(match_dup 4) (match_dup 5)] UNSPEC_UZP1))]
"TARGET_SVE"
{
- operands[3] = force_reg (<VWIDE_PRED>mode, CONSTM1_RTX (<VWIDE_PRED>mode));
+ operands[3] = aarch64_ptrue_reg (<VWIDE_PRED>mode);
operands[4] = gen_reg_rtx (<MODE>mode);
operands[5] = gen_reg_rtx (<MODE>mode);
}
@@ -2852,7 +2799,7 @@
(unspec:VNx4SI [(match_dup 4) (match_dup 5)] UNSPEC_UZP1))]
"TARGET_SVE"
{
- operands[3] = force_reg (VNx2BImode, CONSTM1_RTX (VNx2BImode));
+ operands[3] = aarch64_ptrue_reg (VNx2BImode);
operands[4] = gen_reg_rtx (VNx4SImode);
operands[5] = gen_reg_rtx (VNx4SImode);
}
@@ -2872,25 +2819,6 @@
"TARGET_SVE"
)
-;; Predicated floating-point operations with select matching output.
-(define_insn "*cond_<optab><mode>_0"
- [(set (match_operand:SVE_F 0 "register_operand" "+w, w, ?&w")
- (unspec:SVE_F
- [(match_operand:<VPRED> 1 "register_operand" "Upl, Upl, Upl")
- (unspec:SVE_F
- [(match_operand:SVE_F 2 "register_operand" "0, w, w")
- (match_operand:SVE_F 3 "register_operand" "w, 0, w")]
- SVE_COND_FP_BINARY)
- (match_dup 0)]
- UNSPEC_SEL))]
- "TARGET_SVE"
- "@
- <sve_fp_op>\t%0.<Vetype>, %1/m, %0.<Vetype>, %3.<Vetype>
- <sve_fp_op_rev>\t%0.<Vetype>, %1/m, %0.<Vetype>, %2.<Vetype>
- movprfx\t%0, %1/m, %2\;<sve_fp_op>\t%0.<Vetype>, %1/m, %0.<Vetype>, %3.<Vetype>"
- [(set_attr "movprfx" "*,*,yes")]
-)
-
;; Predicated floating-point operations with select matching first operand.
(define_insn "*cond_<optab><mode>_2"
[(set (match_operand:SVE_F 0 "register_operand" "=w, ?&w")
@@ -2927,48 +2855,36 @@
[(set_attr "movprfx" "*,yes")]
)
-;; Predicated floating-point operations with select matching zero.
-(define_insn "*cond_<optab><mode>_z"
- [(set (match_operand:SVE_F 0 "register_operand" "=&w")
- (unspec:SVE_F
- [(match_operand:<VPRED> 1 "register_operand" "Upl")
- (unspec:SVE_F
- [(match_operand:SVE_F 2 "register_operand" "w")
- (match_operand:SVE_F 3 "register_operand" "w")]
- SVE_COND_FP_BINARY)
- (match_operand:SVE_F 4 "aarch64_simd_imm_zero")]
- UNSPEC_SEL))]
- "TARGET_SVE"
- "movprfx\t%0.<Vetype>, %1/z, %2.<Vetype>\;<sve_fp_op>\t%0.<Vetype>, %1/m, %0.<Vetype>, %3.<Vetype>"
- [(set_attr "movprfx" "yes")]
-)
-
-;; Synthetic predication of floating-point operations with select unmatched.
-(define_insn_and_split "*cond_<optab><mode>_any"
- [(set (match_operand:SVE_F 0 "register_operand" "=&w")
+;; Predicated floating-point binary operations in which the values of
+;; inactive lanes are distinct from the other inputs.
+(define_insn_and_rewrite "*cond_<optab><mode>_any"
+ [(set (match_operand:SVE_F 0 "register_operand" "=&w, &w, &w, &w, ?&w")
(unspec:SVE_F
- [(match_operand:<VPRED> 1 "register_operand" "Upl")
+ [(match_operand:<VPRED> 1 "register_operand" "Upl, Upl, Upl, Upl, Upl")
(unspec:SVE_F
- [(match_operand:SVE_F 2 "register_operand" "w")
- (match_operand:SVE_F 3 "register_operand" "w")]
+ [(match_operand:SVE_F 2 "register_operand" "0, w, w, w, w")
+ (match_operand:SVE_F 3 "register_operand" "w, 0, w, w, w")]
SVE_COND_FP_BINARY)
- (match_operand:SVE_F 4 "register_operand" "w")]
+ (match_operand:SVE_F 4 "aarch64_simd_reg_or_zero" "Dz, Dz, Dz, 0, w")]
UNSPEC_SEL))]
- "TARGET_SVE"
- "#"
+ "TARGET_SVE
+ && !rtx_equal_p (operands[2], operands[4])
+ && !rtx_equal_p (operands[3], operands[4])"
+ "@
+ movprfx\t%0.<Vetype>, %1/z, %0.<Vetype>\;<sve_fp_op>\t%0.<Vetype>, %1/m, %0.<Vetype>, %3.<Vetype>
+ movprfx\t%0.<Vetype>, %1/z, %0.<Vetype>\;<sve_fp_op_rev>\t%0.<Vetype>, %1/m, %0.<Vetype>, %2.<Vetype>
+ movprfx\t%0.<Vetype>, %1/z, %2.<Vetype>\;<sve_fp_op>\t%0.<Vetype>, %1/m, %0.<Vetype>, %3.<Vetype>
+ movprfx\t%0.<Vetype>, %1/m, %2.<Vetype>\;<sve_fp_op>\t%0.<Vetype>, %1/m, %0.<Vetype>, %3.<Vetype>
+ #"
"&& reload_completed
- && !(rtx_equal_p (operands[0], operands[4])
- || rtx_equal_p (operands[2], operands[4])
- || rtx_equal_p (operands[3], operands[4]))"
- ; Not matchable by any one insn or movprfx insn. We need a separate select.
- [(set (match_dup 0)
- (unspec:SVE_F [(match_dup 1) (match_dup 2) (match_dup 4)] UNSPEC_SEL))
- (set (match_dup 0)
- (unspec:SVE_F
- [(match_dup 1)
- (unspec:SVE_F [(match_dup 0) (match_dup 3)] SVE_COND_FP_BINARY)
- (match_dup 0)]
- UNSPEC_SEL))]
+ && register_operand (operands[4], <MODE>mode)
+ && !rtx_equal_p (operands[0], operands[4])"
+ {
+ emit_insn (gen_vcond_mask_<mode><vpred> (operands[0], operands[2],
+ operands[4], operands[1]));
+ operands[4] = operands[2] = operands[0];
+ }
+ [(set_attr "movprfx" "yes")]
)
;; Predicated floating-point ternary operations with select.
@@ -3031,7 +2947,7 @@
;; Predicated floating-point ternary operations in which the value for
;; inactive lanes is distinct from the other inputs.
-(define_insn_and_split "*cond_<optab><mode>_any"
+(define_insn_and_rewrite "*cond_<optab><mode>_any"
[(set (match_operand:SVE_F 0 "register_operand" "=&w, &w, ?&w")
(unspec:SVE_F
[(match_operand:<VPRED> 1 "register_operand" "Upl, Upl, Upl")
@@ -3053,16 +2969,11 @@
"&& reload_completed
&& !CONSTANT_P (operands[5])
&& !rtx_equal_p (operands[0], operands[5])"
- [(set (match_dup 0)
- (unspec:SVE_F [(match_dup 1) (match_dup 4) (match_dup 5)] UNSPEC_SEL))
- (set (match_dup 0)
- (unspec:SVE_F
- [(match_dup 1)
- (unspec:SVE_F [(match_dup 2) (match_dup 3) (match_dup 0)]
- SVE_COND_FP_TERNARY)
- (match_dup 0)]
- UNSPEC_SEL))]
- ""
+ {
+ emit_insn (gen_vcond_mask_<mode><vpred> (operands[0], operands[4],
+ operands[5], operands[1]));
+ operands[5] = operands[4] = operands[0];
+ }
[(set_attr "movprfx" "yes")]
)
@@ -3149,18 +3060,16 @@
[(set_attr "movprfx" "*,yes")]
)
-;; Helper expander for aarch64_<su>abd<mode>_3 to save the callers
-;; the hassle of constructing the other arm of the MINUS.
+;; Unpredicated integer absolute difference.
(define_expand "<su>abd<mode>_3"
[(use (match_operand:SVE_I 0 "register_operand"))
(USMAX:SVE_I (match_operand:SVE_I 1 "register_operand")
(match_operand:SVE_I 2 "register_operand"))]
"TARGET_SVE"
{
- rtx pred = force_reg (<VPRED>mode, CONSTM1_RTX (<VPRED>mode));
- rtx other_arm = gen_rtx_<MAX_OPP> (<MODE>mode, operands[1], operands[2]);
+ rtx pred = aarch64_ptrue_reg (<VPRED>mode);
emit_insn (gen_aarch64_<su>abd<mode>_3 (operands[0], pred, operands[1],
- operands[2], other_arm));
+ operands[2]));
DONE;
}
)
@@ -3174,9 +3083,9 @@
(USMAX:SVE_I
(match_operand:SVE_I 2 "register_operand" "0, w")
(match_operand:SVE_I 3 "register_operand" "w, w"))
- (match_operator 4 "aarch64_<max_opp>"
- [(match_dup 2)
- (match_dup 3)]))]
+ (<max_opp>:SVE_I
+ (match_dup 2)
+ (match_dup 3)))]
UNSPEC_MERGE_PTRUE))]
"TARGET_SVE"
"@
@@ -3209,3 +3118,14 @@
DONE;
}
)
+
+;; Standard pattern name vec_init<mode><Vel>.
+(define_expand "vec_init<mode><Vel>"
+ [(match_operand:SVE_ALL 0 "register_operand")
+ (match_operand 1 "" "")]
+ "TARGET_SVE"
+ {
+ aarch64_sve_expand_vector_init (operands[0], operands[1]);
+ DONE;
+ }
+)
diff --git a/gcc/config/aarch64/aarch64-sve2.md b/gcc/config/aarch64/aarch64-sve2.md
new file mode 100644
index 0000000..d0c235b
--- /dev/null
+++ b/gcc/config/aarch64/aarch64-sve2.md
@@ -0,0 +1,65 @@
+;; Machine description for AArch64 SVE2.
+;; Copyright (C) 2019 Free Software Foundation, Inc.
+;; Contributed by ARM Ltd.
+;;
+;; 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/>.
+
+;; Integer average (floor).
+(define_expand "<u>avg<mode>3_floor"
+ [(set (match_operand:SVE_I 0 "register_operand")
+ (unspec:SVE_I
+ [(match_dup 3)
+ (unspec:SVE_I [(match_operand:SVE_I 1 "register_operand")
+ (match_operand:SVE_I 2 "register_operand")]
+ HADD)]
+ UNSPEC_MERGE_PTRUE))]
+ "TARGET_SVE2"
+ {
+ operands[3] = force_reg (<VPRED>mode, CONSTM1_RTX (<VPRED>mode));
+ }
+)
+
+;; Integer average (rounding).
+(define_expand "<u>avg<mode>3_ceil"
+ [(set (match_operand:SVE_I 0 "register_operand")
+ (unspec:SVE_I
+ [(match_dup 3)
+ (unspec:SVE_I [(match_operand:SVE_I 1 "register_operand")
+ (match_operand:SVE_I 2 "register_operand")]
+ RHADD)]
+ UNSPEC_MERGE_PTRUE))]
+ "TARGET_SVE2"
+ {
+ operands[3] = force_reg (<VPRED>mode, CONSTM1_RTX (<VPRED>mode));
+ }
+)
+
+;; Predicated halving addsub.
+(define_insn "*<sur>h<addsub><mode>"
+ [(set (match_operand:SVE_I 0 "register_operand" "=w, ?&w")
+ (unspec:SVE_I
+ [(match_operand:<VPRED> 1 "register_operand" "Upl, Upl")
+ (unspec:SVE_I [(match_operand:SVE_I 2 "register_operand" "%0, w")
+ (match_operand:SVE_I 3 "register_operand" "w, w")]
+ HADDSUB)]
+ UNSPEC_MERGE_PTRUE))]
+ "TARGET_SVE2"
+ "@
+ <sur>h<addsub>\t%0.<Vetype>, %1/m, %0.<Vetype>, %3.<Vetype>
+ movprfx\t%0, %2\;<sur>h<addsub>\t%0.<Vetype>, %1/m, %0.<Vetype>, %3.<Vetype>"
+ [(set_attr "movprfx" "*,yes")]
+) \ No newline at end of file
diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c
index c3c88c8..5a923ca 100644
--- a/gcc/config/aarch64/aarch64.c
+++ b/gcc/config/aarch64/aarch64.c
@@ -177,7 +177,7 @@ unsigned aarch64_architecture_version;
enum aarch64_processor aarch64_tune = cortexa53;
/* Mask to specify which instruction scheduling options should be used. */
-unsigned long aarch64_tune_flags = 0;
+uint64_t aarch64_tune_flags = 0;
/* Global flag for PC relative loads. */
bool aarch64_pcrelative_literal_loads;
@@ -1139,7 +1139,7 @@ struct processor
enum aarch64_processor sched_core;
enum aarch64_arch arch;
unsigned architecture_version;
- const unsigned long flags;
+ const uint64_t flags;
const struct tune_params *const tune;
};
@@ -1172,6 +1172,8 @@ static const struct processor *selected_arch;
static const struct processor *selected_cpu;
static const struct processor *selected_tune;
+enum aarch64_key_type aarch64_ra_sign_key = AARCH64_KEY_A;
+
/* The current tuning set. */
struct tune_params aarch64_tune_params = generic_tunings;
@@ -1241,6 +1243,7 @@ static enum aarch64_parse_opt_result
aarch64_handle_standard_branch_protection (char* str, char* rest)
{
aarch64_ra_sign_scope = AARCH64_FUNCTION_NON_LEAF;
+ aarch64_ra_sign_key = AARCH64_KEY_A;
aarch64_enable_bti = 1;
if (rest)
{
@@ -1255,6 +1258,7 @@ aarch64_handle_pac_ret_protection (char* str ATTRIBUTE_UNUSED,
char* rest ATTRIBUTE_UNUSED)
{
aarch64_ra_sign_scope = AARCH64_FUNCTION_NON_LEAF;
+ aarch64_ra_sign_key = AARCH64_KEY_A;
return AARCH64_PARSE_OK;
}
@@ -1267,6 +1271,14 @@ aarch64_handle_pac_ret_leaf (char* str ATTRIBUTE_UNUSED,
}
static enum aarch64_parse_opt_result
+aarch64_handle_pac_ret_b_key (char* str ATTRIBUTE_UNUSED,
+ char* rest ATTRIBUTE_UNUSED)
+{
+ aarch64_ra_sign_key = AARCH64_KEY_B;
+ return AARCH64_PARSE_OK;
+}
+
+static enum aarch64_parse_opt_result
aarch64_handle_bti_protection (char* str ATTRIBUTE_UNUSED,
char* rest ATTRIBUTE_UNUSED)
{
@@ -1276,6 +1288,7 @@ aarch64_handle_bti_protection (char* str ATTRIBUTE_UNUSED,
static const struct aarch64_branch_protect_type aarch64_pac_ret_subtypes[] = {
{ "leaf", aarch64_handle_pac_ret_leaf, NULL, 0 },
+ { "b-key", aarch64_handle_pac_ret_b_key, NULL, 0 },
{ NULL, NULL, NULL, 0 }
};
@@ -1295,6 +1308,13 @@ static const char * const aarch64_condition_codes[] =
"hi", "ls", "ge", "lt", "gt", "le", "al", "nv"
};
+/* The preferred condition codes for SVE conditions. */
+static const char *const aarch64_sve_condition_codes[] =
+{
+ "none", "any", "nlast", "last", "first", "nfrst", "vs", "vc",
+ "pmore", "plast", "tcont", "tstop", "gt", "le", "al", "nv"
+};
+
/* Generate code to enable conditional branches in functions over 1 MiB. */
const char *
aarch64_gen_far_branch (rtx * operands, int pos_label, const char * dest,
@@ -2445,6 +2465,24 @@ aarch64_force_temporary (machine_mode mode, rtx x, rtx value)
}
}
+/* Return an all-true predicate register of mode MODE. */
+
+rtx
+aarch64_ptrue_reg (machine_mode mode)
+{
+ gcc_assert (GET_MODE_CLASS (mode) == MODE_VECTOR_BOOL);
+ return force_reg (mode, CONSTM1_RTX (mode));
+}
+
+/* Return an all-false predicate register of mode MODE. */
+
+rtx
+aarch64_pfalse_reg (machine_mode mode)
+{
+ gcc_assert (GET_MODE_CLASS (mode) == MODE_VECTOR_BOOL);
+ return force_reg (mode, CONST0_RTX (mode));
+}
+
/* Return true if we can move VALUE into a register using a single
CNT[BHWD] instruction. */
@@ -3174,7 +3212,7 @@ aarch64_expand_sve_widened_duplicate (rtx dest, scalar_int_mode src_mode,
machine_mode mode = GET_MODE (dest);
unsigned int elem_bytes = GET_MODE_UNIT_SIZE (mode);
machine_mode pred_mode = aarch64_sve_pred_mode (elem_bytes).require ();
- rtx ptrue = force_reg (pred_mode, CONSTM1_RTX (pred_mode));
+ rtx ptrue = aarch64_ptrue_reg (pred_mode);
src = gen_rtx_UNSPEC (mode, gen_rtvec (2, ptrue, src), UNSPEC_LD1RQ);
emit_insn (gen_rtx_SET (dest, src));
return true;
@@ -3435,7 +3473,7 @@ void
aarch64_expand_sve_mem_move (rtx dest, rtx src, machine_mode pred_mode)
{
machine_mode mode = GET_MODE (dest);
- rtx ptrue = force_reg (pred_mode, CONSTM1_RTX (pred_mode));
+ rtx ptrue = aarch64_ptrue_reg (pred_mode);
if (!register_operand (src, mode)
&& !register_operand (dest, mode))
{
@@ -3499,7 +3537,7 @@ aarch64_maybe_expand_sve_subreg_move (rtx dest, rtx src)
return false;
/* Generate *aarch64_sve_mov<mode>_subreg_be. */
- rtx ptrue = force_reg (VNx16BImode, CONSTM1_RTX (VNx16BImode));
+ rtx ptrue = aarch64_ptrue_reg (VNx16BImode);
rtx unspec = gen_rtx_UNSPEC (GET_MODE (dest), gen_rtvec (2, ptrue, src),
UNSPEC_REV_SUBREG);
emit_insn (gen_rtx_SET (dest, unspec));
@@ -4852,7 +4890,7 @@ aarch64_return_address_signing_enabled (void)
gcc_assert (cfun->machine->frame.laid_out);
/* If signing scope is AARCH64_FUNCTION_NON_LEAF, we only sign a leaf function
- if it's LR is pushed onto stack. */
+ if its LR is pushed onto stack. */
return (aarch64_ra_sign_scope == AARCH64_FUNCTION_ALL
|| (aarch64_ra_sign_scope == AARCH64_FUNCTION_NON_LEAF
&& cfun->machine->frame.reg_offset[LR_REGNUM] >= 0));
@@ -5651,7 +5689,17 @@ aarch64_expand_prologue (void)
/* Sign return address for functions. */
if (aarch64_return_address_signing_enabled ())
{
- insn = emit_insn (gen_pacisp ());
+ switch (aarch64_ra_sign_key)
+ {
+ case AARCH64_KEY_A:
+ insn = emit_insn (gen_paciasp ());
+ break;
+ case AARCH64_KEY_B:
+ insn = emit_insn (gen_pacibsp ());
+ break;
+ default:
+ gcc_unreachable ();
+ }
add_reg_note (insn, REG_CFA_TOGGLE_RA_MANGLE, const0_rtx);
RTX_FRAME_RELATED_P (insn) = 1;
}
@@ -5907,13 +5955,23 @@ aarch64_expand_epilogue (bool for_sibcall)
if (aarch64_return_address_signing_enabled ()
&& (for_sibcall || !TARGET_ARMV8_3 || crtl->calls_eh_return))
{
- insn = emit_insn (gen_autisp ());
+ switch (aarch64_ra_sign_key)
+ {
+ case AARCH64_KEY_A:
+ insn = emit_insn (gen_autiasp ());
+ break;
+ case AARCH64_KEY_B:
+ insn = emit_insn (gen_autibsp ());
+ break;
+ default:
+ gcc_unreachable ();
+ }
add_reg_note (insn, REG_CFA_TOGGLE_RA_MANGLE, const0_rtx);
RTX_FRAME_RELATED_P (insn) = 1;
}
/* Stack adjustment for exception handler. */
- if (crtl->calls_eh_return)
+ if (crtl->calls_eh_return && !for_sibcall)
{
/* We need to unwind the stack by the offset computed by
EH_RETURN_STACKADJ_RTX. We have already reset the CFA
@@ -5979,6 +6037,7 @@ aarch64_output_mi_thunk (FILE *file, tree thunk ATTRIBUTE_UNUSED,
int this_regno = R0_REGNUM;
rtx this_rtx, temp0, temp1, addr, funexp;
rtx_insn *insn;
+ const char *fnname = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (thunk));
if (aarch64_bti_enabled ())
emit_insn (gen_bti_c());
@@ -6046,9 +6105,12 @@ aarch64_output_mi_thunk (FILE *file, tree thunk ATTRIBUTE_UNUSED,
insn = get_insns ();
shorten_branches (insn);
+
+ assemble_start_function (thunk, fnname);
final_start_function (insn, file, 1);
final (insn, file, 1);
final_end_function ();
+ assemble_end_function (thunk, fnname);
/* Stop pretending to be a post-reload pass. */
reload_completed = 0;
@@ -6592,7 +6654,7 @@ aarch64_classify_address (struct aarch64_address_info *info,
bool allow_reg_index_p = (!load_store_pair_p
&& (known_lt (GET_MODE_SIZE (mode), 16)
|| vec_flags == VEC_ADVSIMD
- || vec_flags == VEC_SVE_DATA));
+ || vec_flags & VEC_SVE_DATA));
/* For SVE, only accept [Rn], [Rn, Rm, LSL #shift] and
[Rn, #offset, MUL VL]. */
@@ -7346,6 +7408,21 @@ aarch64_get_condition_code_1 (machine_mode mode, enum rtx_code comp_code)
}
break;
+ case E_CC_NZCmode:
+ switch (comp_code)
+ {
+ case NE: return AARCH64_NE; /* = any */
+ case EQ: return AARCH64_EQ; /* = none */
+ case GE: return AARCH64_PL; /* = nfrst */
+ case LT: return AARCH64_MI; /* = first */
+ case GEU: return AARCH64_CS; /* = nlast */
+ case GTU: return AARCH64_HI; /* = pmore */
+ case LEU: return AARCH64_LS; /* = plast */
+ case LTU: return AARCH64_CC; /* = last */
+ default: return -1;
+ }
+ break;
+
case E_CC_NZmode:
switch (comp_code)
{
@@ -7679,7 +7756,10 @@ aarch64_print_operand (FILE *f, rtx x, int code)
gcc_assert (cond_code >= 0);
if (code == 'M')
cond_code = AARCH64_INVERSE_CONDITION_CODE (cond_code);
- fputs (aarch64_condition_codes[cond_code], f);
+ if (GET_MODE (XEXP (x, 0)) == CC_NZCmode)
+ fputs (aarch64_sve_condition_codes[cond_code], f);
+ else
+ fputs (aarch64_condition_codes[cond_code], f);
}
break;
@@ -11039,7 +11119,7 @@ static void initialize_aarch64_code_model (struct gcc_options *);
static enum aarch64_parse_opt_result
aarch64_parse_arch (const char *to_parse, const struct processor **res,
- unsigned long *isa_flags, std::string *invalid_extension)
+ uint64_t *isa_flags, std::string *invalid_extension)
{
const char *ext;
const struct processor *arch;
@@ -11062,7 +11142,7 @@ aarch64_parse_arch (const char *to_parse, const struct processor **res,
if (strlen (arch->name) == len
&& strncmp (arch->name, to_parse, len) == 0)
{
- unsigned long isa_temp = arch->flags;
+ uint64_t isa_temp = arch->flags;
if (ext != NULL)
{
@@ -11094,7 +11174,7 @@ aarch64_parse_arch (const char *to_parse, const struct processor **res,
static enum aarch64_parse_opt_result
aarch64_parse_cpu (const char *to_parse, const struct processor **res,
- unsigned long *isa_flags, std::string *invalid_extension)
+ uint64_t *isa_flags, std::string *invalid_extension)
{
const char *ext;
const struct processor *cpu;
@@ -11116,7 +11196,7 @@ aarch64_parse_cpu (const char *to_parse, const struct processor **res,
{
if (strlen (cpu->name) == len && strncmp (cpu->name, to_parse, len) == 0)
{
- unsigned long isa_temp = cpu->flags;
+ uint64_t isa_temp = cpu->flags;
if (ext != NULL)
@@ -11701,7 +11781,7 @@ aarch64_print_hint_for_extensions (const std::string &str)
static bool
aarch64_validate_mcpu (const char *str, const struct processor **res,
- unsigned long *isa_flags)
+ uint64_t *isa_flags)
{
std::string invalid_extension;
enum aarch64_parse_opt_result parse_res
@@ -11828,9 +11908,9 @@ aarch64_validate_mbranch_protection (const char *const_str)
enum aarch64_parse_opt_result res =
aarch64_parse_branch_protection (const_str, &str);
if (res == AARCH64_PARSE_INVALID_ARG)
- error ("invalid arg %<%s%> for %<-mbranch-protection=%>", str);
+ error ("invalid argument %<%s%> for %<-mbranch-protection=%>", str);
else if (res == AARCH64_PARSE_MISSING_ARG)
- error ("missing arg for %<-mbranch-protection=%>");
+ error ("missing argument for %<-mbranch-protection=%>");
free (str);
return res == AARCH64_PARSE_OK;
}
@@ -11842,7 +11922,7 @@ aarch64_validate_mbranch_protection (const char *const_str)
static bool
aarch64_validate_march (const char *str, const struct processor **res,
- unsigned long *isa_flags)
+ uint64_t *isa_flags)
{
std::string invalid_extension;
enum aarch64_parse_opt_result parse_res
@@ -11957,8 +12037,8 @@ aarch64_convert_sve_vector_bits (aarch64_sve_vector_bits_enum value)
static void
aarch64_override_options (void)
{
- unsigned long cpu_isa = 0;
- unsigned long arch_isa = 0;
+ uint64_t cpu_isa = 0;
+ uint64_t arch_isa = 0;
aarch64_isa_flags = 0;
bool valid_cpu = true;
@@ -12198,7 +12278,7 @@ aarch64_option_print (FILE *file, int indent, struct cl_target_option *ptr)
{
const struct processor *cpu
= aarch64_get_tune_cpu (ptr->x_explicit_tune_core);
- unsigned long isa_flags = ptr->x_aarch64_isa_flags;
+ uint64_t isa_flags = ptr->x_aarch64_isa_flags;
const struct processor *arch = aarch64_get_arch (ptr->x_explicit_arch);
std::string extension
= aarch64_get_extension_string_for_isa_flags (isa_flags, arch->flags);
@@ -12451,7 +12531,7 @@ static bool
aarch64_handle_attr_isa_flags (char *str)
{
enum aarch64_parse_opt_result parse_res;
- unsigned long isa_flags = aarch64_isa_flags;
+ uint64_t isa_flags = aarch64_isa_flags;
/* We allow "+nothing" in the beginning to clear out all architectural
features if the user wants to handpick specific features. */
@@ -14105,7 +14185,7 @@ aarch64_preferred_simd_mode (scalar_mode mode)
/* Return a list of possible vector sizes for the vectorizer
to iterate over. */
static void
-aarch64_autovectorize_vector_sizes (vector_sizes *sizes)
+aarch64_autovectorize_vector_sizes (vector_sizes *sizes, bool)
{
if (TARGET_SVE)
sizes->safe_push (BYTES_PER_SVE_VECTOR);
@@ -15069,6 +15149,45 @@ aarch64_expand_vector_init (rtx target, rtx vals)
rtx v0 = XVECEXP (vals, 0, 0);
bool all_same = true;
+ /* This is a special vec_init<M><N> where N is not an element mode but a
+ vector mode with half the elements of M. We expect to find two entries
+ of mode N in VALS and we must put their concatentation into TARGET. */
+ if (XVECLEN (vals, 0) == 2 && VECTOR_MODE_P (GET_MODE (XVECEXP (vals, 0, 0))))
+ {
+ gcc_assert (known_eq (GET_MODE_SIZE (mode),
+ 2 * GET_MODE_SIZE (GET_MODE (XVECEXP (vals, 0, 0)))));
+ rtx lo = XVECEXP (vals, 0, 0);
+ rtx hi = XVECEXP (vals, 0, 1);
+ machine_mode narrow_mode = GET_MODE (lo);
+ gcc_assert (GET_MODE_INNER (narrow_mode) == inner_mode);
+ gcc_assert (narrow_mode == GET_MODE (hi));
+
+ /* When we want to concatenate a half-width vector with zeroes we can
+ use the aarch64_combinez[_be] patterns. Just make sure that the
+ zeroes are in the right half. */
+ if (BYTES_BIG_ENDIAN
+ && aarch64_simd_imm_zero (lo, narrow_mode)
+ && general_operand (hi, narrow_mode))
+ emit_insn (gen_aarch64_combinez_be (narrow_mode, target, hi, lo));
+ else if (!BYTES_BIG_ENDIAN
+ && aarch64_simd_imm_zero (hi, narrow_mode)
+ && general_operand (lo, narrow_mode))
+ emit_insn (gen_aarch64_combinez (narrow_mode, target, lo, hi));
+ else
+ {
+ /* Else create the two half-width registers and combine them. */
+ if (!REG_P (lo))
+ lo = force_reg (GET_MODE (lo), lo);
+ if (!REG_P (hi))
+ hi = force_reg (GET_MODE (hi), hi);
+
+ if (BYTES_BIG_ENDIAN)
+ std::swap (lo, hi);
+ emit_insn (gen_aarch64_simd_combine (narrow_mode, target, lo, hi));
+ }
+ return;
+ }
+
/* Count the number of variable elements to initialise. */
for (int i = 0; i < n_elts; ++i)
{
@@ -15240,6 +15359,263 @@ aarch64_expand_vector_init (rtx target, rtx vals)
}
}
+/* Emit RTL corresponding to:
+ insr TARGET, ELEM. */
+
+static void
+emit_insr (rtx target, rtx elem)
+{
+ machine_mode mode = GET_MODE (target);
+ scalar_mode elem_mode = GET_MODE_INNER (mode);
+ elem = force_reg (elem_mode, elem);
+
+ insn_code icode = optab_handler (vec_shl_insert_optab, mode);
+ gcc_assert (icode != CODE_FOR_nothing);
+ emit_insn (GEN_FCN (icode) (target, target, elem));
+}
+
+/* Subroutine of aarch64_sve_expand_vector_init for handling
+ trailing constants.
+ This function works as follows:
+ (a) Create a new vector consisting of trailing constants.
+ (b) Initialize TARGET with the constant vector using emit_move_insn.
+ (c) Insert remaining elements in TARGET using insr.
+ NELTS is the total number of elements in original vector while
+ while NELTS_REQD is the number of elements that are actually
+ significant.
+
+ ??? The heuristic used is to do above only if number of constants
+ is at least half the total number of elements. May need fine tuning. */
+
+static bool
+aarch64_sve_expand_vector_init_handle_trailing_constants
+ (rtx target, const rtx_vector_builder &builder, int nelts, int nelts_reqd)
+{
+ machine_mode mode = GET_MODE (target);
+ scalar_mode elem_mode = GET_MODE_INNER (mode);
+ int n_trailing_constants = 0;
+
+ for (int i = nelts_reqd - 1;
+ i >= 0 && aarch64_legitimate_constant_p (elem_mode, builder.elt (i));
+ i--)
+ n_trailing_constants++;
+
+ if (n_trailing_constants >= nelts_reqd / 2)
+ {
+ rtx_vector_builder v (mode, 1, nelts);
+ for (int i = 0; i < nelts; i++)
+ v.quick_push (builder.elt (i + nelts_reqd - n_trailing_constants));
+ rtx const_vec = v.build ();
+ emit_move_insn (target, const_vec);
+
+ for (int i = nelts_reqd - n_trailing_constants - 1; i >= 0; i--)
+ emit_insr (target, builder.elt (i));
+
+ return true;
+ }
+
+ return false;
+}
+
+/* Subroutine of aarch64_sve_expand_vector_init.
+ Works as follows:
+ (a) Initialize TARGET by broadcasting element NELTS_REQD - 1 of BUILDER.
+ (b) Skip trailing elements from BUILDER, which are the same as
+ element NELTS_REQD - 1.
+ (c) Insert earlier elements in reverse order in TARGET using insr. */
+
+static void
+aarch64_sve_expand_vector_init_insert_elems (rtx target,
+ const rtx_vector_builder &builder,
+ int nelts_reqd)
+{
+ machine_mode mode = GET_MODE (target);
+ scalar_mode elem_mode = GET_MODE_INNER (mode);
+
+ struct expand_operand ops[2];
+ enum insn_code icode = optab_handler (vec_duplicate_optab, mode);
+ gcc_assert (icode != CODE_FOR_nothing);
+
+ create_output_operand (&ops[0], target, mode);
+ create_input_operand (&ops[1], builder.elt (nelts_reqd - 1), elem_mode);
+ expand_insn (icode, 2, ops);
+
+ int ndups = builder.count_dups (nelts_reqd - 1, -1, -1);
+ for (int i = nelts_reqd - ndups - 1; i >= 0; i--)
+ emit_insr (target, builder.elt (i));
+}
+
+/* Subroutine of aarch64_sve_expand_vector_init to handle case
+ when all trailing elements of builder are same.
+ This works as follows:
+ (a) Use expand_insn interface to broadcast last vector element in TARGET.
+ (b) Insert remaining elements in TARGET using insr.
+
+ ??? The heuristic used is to do above if number of same trailing elements
+ is at least 3/4 of total number of elements, loosely based on
+ heuristic from mostly_zeros_p. May need fine-tuning. */
+
+static bool
+aarch64_sve_expand_vector_init_handle_trailing_same_elem
+ (rtx target, const rtx_vector_builder &builder, int nelts_reqd)
+{
+ int ndups = builder.count_dups (nelts_reqd - 1, -1, -1);
+ if (ndups >= (3 * nelts_reqd) / 4)
+ {
+ aarch64_sve_expand_vector_init_insert_elems (target, builder,
+ nelts_reqd - ndups + 1);
+ return true;
+ }
+
+ return false;
+}
+
+/* Initialize register TARGET from BUILDER. NELTS is the constant number
+ of elements in BUILDER.
+
+ The function tries to initialize TARGET from BUILDER if it fits one
+ of the special cases outlined below.
+
+ Failing that, the function divides BUILDER into two sub-vectors:
+ v_even = even elements of BUILDER;
+ v_odd = odd elements of BUILDER;
+
+ and recursively calls itself with v_even and v_odd.
+
+ if (recursive call succeeded for v_even or v_odd)
+ TARGET = zip (v_even, v_odd)
+
+ The function returns true if it managed to build TARGET from BUILDER
+ with one of the special cases, false otherwise.
+
+ Example: {a, 1, b, 2, c, 3, d, 4}
+
+ The vector gets divided into:
+ v_even = {a, b, c, d}
+ v_odd = {1, 2, 3, 4}
+
+ aarch64_sve_expand_vector_init(v_odd) hits case 1 and
+ initialize tmp2 from constant vector v_odd using emit_move_insn.
+
+ aarch64_sve_expand_vector_init(v_even) fails since v_even contains
+ 4 elements, so we construct tmp1 from v_even using insr:
+ tmp1 = dup(d)
+ insr tmp1, c
+ insr tmp1, b
+ insr tmp1, a
+
+ And finally:
+ TARGET = zip (tmp1, tmp2)
+ which sets TARGET to {a, 1, b, 2, c, 3, d, 4}. */
+
+static bool
+aarch64_sve_expand_vector_init (rtx target, const rtx_vector_builder &builder,
+ int nelts, int nelts_reqd)
+{
+ machine_mode mode = GET_MODE (target);
+
+ /* Case 1: Vector contains trailing constants. */
+
+ if (aarch64_sve_expand_vector_init_handle_trailing_constants
+ (target, builder, nelts, nelts_reqd))
+ return true;
+
+ /* Case 2: Vector contains leading constants. */
+
+ rtx_vector_builder rev_builder (mode, 1, nelts_reqd);
+ for (int i = 0; i < nelts_reqd; i++)
+ rev_builder.quick_push (builder.elt (nelts_reqd - i - 1));
+ rev_builder.finalize ();
+
+ if (aarch64_sve_expand_vector_init_handle_trailing_constants
+ (target, rev_builder, nelts, nelts_reqd))
+ {
+ emit_insn (gen_aarch64_sve_rev (mode, target, target));
+ return true;
+ }
+
+ /* Case 3: Vector contains trailing same element. */
+
+ if (aarch64_sve_expand_vector_init_handle_trailing_same_elem
+ (target, builder, nelts_reqd))
+ return true;
+
+ /* Case 4: Vector contains leading same element. */
+
+ if (aarch64_sve_expand_vector_init_handle_trailing_same_elem
+ (target, rev_builder, nelts_reqd) && nelts_reqd == nelts)
+ {
+ emit_insn (gen_aarch64_sve_rev (mode, target, target));
+ return true;
+ }
+
+ /* Avoid recursing below 4-elements.
+ ??? The threshold 4 may need fine-tuning. */
+
+ if (nelts_reqd <= 4)
+ return false;
+
+ rtx_vector_builder v_even (mode, 1, nelts);
+ rtx_vector_builder v_odd (mode, 1, nelts);
+
+ for (int i = 0; i < nelts * 2; i += 2)
+ {
+ v_even.quick_push (builder.elt (i));
+ v_odd.quick_push (builder.elt (i + 1));
+ }
+
+ v_even.finalize ();
+ v_odd.finalize ();
+
+ rtx tmp1 = gen_reg_rtx (mode);
+ bool did_even_p = aarch64_sve_expand_vector_init (tmp1, v_even,
+ nelts, nelts_reqd / 2);
+
+ rtx tmp2 = gen_reg_rtx (mode);
+ bool did_odd_p = aarch64_sve_expand_vector_init (tmp2, v_odd,
+ nelts, nelts_reqd / 2);
+
+ if (!did_even_p && !did_odd_p)
+ return false;
+
+ /* Initialize v_even and v_odd using INSR if it didn't match any of the
+ special cases and zip v_even, v_odd. */
+
+ if (!did_even_p)
+ aarch64_sve_expand_vector_init_insert_elems (tmp1, v_even, nelts_reqd / 2);
+
+ if (!did_odd_p)
+ aarch64_sve_expand_vector_init_insert_elems (tmp2, v_odd, nelts_reqd / 2);
+
+ rtvec v = gen_rtvec (2, tmp1, tmp2);
+ emit_set_insn (target, gen_rtx_UNSPEC (mode, v, UNSPEC_ZIP1));
+ return true;
+}
+
+/* Initialize register TARGET from the elements in PARALLEL rtx VALS. */
+
+void
+aarch64_sve_expand_vector_init (rtx target, rtx vals)
+{
+ machine_mode mode = GET_MODE (target);
+ int nelts = XVECLEN (vals, 0);
+
+ rtx_vector_builder v (mode, 1, nelts);
+ for (int i = 0; i < nelts; i++)
+ v.quick_push (XVECEXP (vals, 0, i));
+ v.finalize ();
+
+ /* If neither sub-vectors of v could be initialized specially,
+ then use INSR to insert all elements from v into TARGET.
+ ??? This might not be optimal for vectors with large
+ initializers like 16-element or above.
+ For nelts < 4, it probably isn't useful to handle specially. */
+
+ if (nelts < 4
+ || !aarch64_sve_expand_vector_init (target, v, nelts, nelts))
+ aarch64_sve_expand_vector_init_insert_elems (target, v, nelts);
+}
+
static unsigned HOST_WIDE_INT
aarch64_shift_truncation_mask (machine_mode mode)
{
@@ -15272,6 +15648,19 @@ aarch64_asm_preferred_eh_data_format (int code ATTRIBUTE_UNUSED, int global)
return (global ? DW_EH_PE_indirect : 0) | DW_EH_PE_pcrel | type;
}
+/* Output .variant_pcs for aarch64_vector_pcs function symbols. */
+
+static void
+aarch64_asm_output_variant_pcs (FILE *stream, const tree decl, const char* name)
+{
+ if (aarch64_simd_decl_p (decl))
+ {
+ fprintf (stream, "\t.variant_pcs\t");
+ assemble_name (stream, name);
+ fprintf (stream, "\n");
+ }
+}
+
/* The last .arch and .tune assembly strings that we printed. */
static std::string aarch64_last_printed_arch_string;
static std::string aarch64_last_printed_tune_string;
@@ -15295,7 +15684,7 @@ aarch64_declare_function_name (FILE *stream, const char* name,
const struct processor *this_arch
= aarch64_get_arch (targ_options->x_explicit_arch);
- unsigned long isa_flags = targ_options->x_aarch64_isa_flags;
+ uint64_t isa_flags = targ_options->x_aarch64_isa_flags;
std::string extension
= aarch64_get_extension_string_for_isa_flags (isa_flags,
this_arch->flags);
@@ -15321,11 +15710,46 @@ aarch64_declare_function_name (FILE *stream, const char* name,
aarch64_last_printed_tune_string = this_tune->name;
}
+ aarch64_asm_output_variant_pcs (stream, fndecl, name);
+
/* Don't forget the type directive for ELF. */
ASM_OUTPUT_TYPE_DIRECTIVE (stream, name, "function");
ASM_OUTPUT_LABEL (stream, name);
}
+/* Implement ASM_OUTPUT_DEF_FROM_DECLS. Output .variant_pcs for aliases. */
+
+void
+aarch64_asm_output_alias (FILE *stream, const tree decl, const tree target)
+{
+ const char *name = XSTR (XEXP (DECL_RTL (decl), 0), 0);
+ const char *value = IDENTIFIER_POINTER (target);
+ aarch64_asm_output_variant_pcs (stream, decl, name);
+ ASM_OUTPUT_DEF (stream, name, value);
+}
+
+/* Implement ASM_OUTPUT_EXTERNAL. Output .variant_pcs for undefined
+ function symbol references. */
+
+void
+aarch64_asm_output_external (FILE *stream, tree decl, const char* name)
+{
+ default_elf_asm_output_external (stream, decl, name);
+ aarch64_asm_output_variant_pcs (stream, decl, name);
+}
+
+/* Triggered after a .cfi_startproc directive is emitted into the assembly file.
+ Used to output the .cfi_b_key_frame directive when signing the current
+ function with the B key. */
+
+void
+aarch64_post_cfi_startproc (FILE *f, tree ignored ATTRIBUTE_UNUSED)
+{
+ if (!cfun->is_thunk && aarch64_return_address_signing_enabled ()
+ && aarch64_ra_sign_key == AARCH64_KEY_B)
+ asm_fprintf (f, "\t.cfi_b_key_frame\n");
+}
+
/* Implements TARGET_ASM_FILE_START. Output the assembly header. */
static void
@@ -15336,7 +15760,7 @@ aarch64_start_file (void)
const struct processor *default_arch
= aarch64_get_arch (default_options->x_explicit_arch);
- unsigned long default_isa_flags = default_options->x_aarch64_isa_flags;
+ uint64_t default_isa_flags = default_options->x_aarch64_isa_flags;
std::string extension
= aarch64_get_extension_string_for_isa_flags (default_isa_flags,
default_arch->flags);
@@ -16372,7 +16796,7 @@ aarch64_evpc_rev_local (struct expand_vec_perm_d *d)
rtx src = gen_rtx_UNSPEC (d->vmode, gen_rtvec (1, d->op0), unspec);
if (d->vec_flags == VEC_SVE_DATA)
{
- rtx pred = force_reg (pred_mode, CONSTM1_RTX (pred_mode));
+ rtx pred = aarch64_ptrue_reg (pred_mode);
src = gen_rtx_UNSPEC (d->vmode, gen_rtvec (2, pred, src),
UNSPEC_MERGE_PTRUE);
}
@@ -16660,7 +17084,7 @@ aarch64_emit_sve_ptrue_op_cc (rtx target, rtx ptrue, rtx op)
rtx unspec = gen_rtx_UNSPEC (GET_MODE (target),
gen_rtvec (2, ptrue, op),
UNSPEC_MERGE_PTRUE);
- rtx_insn *insn = emit_insn (gen_set_clobber_cc (target, unspec));
+ rtx_insn *insn = emit_insn (gen_set_clobber_cc_nzc (target, unspec));
set_unique_reg_note (insn, REG_EQUAL, copy_rtx (op));
}
@@ -16720,7 +17144,7 @@ aarch64_expand_sve_vec_cmp_int (rtx target, rtx_code code, rtx op0, rtx op1)
if (!aarch64_sve_cmp_operand_p (code, op1))
op1 = force_reg (data_mode, op1);
- rtx ptrue = force_reg (pred_mode, CONSTM1_RTX (pred_mode));
+ rtx ptrue = aarch64_ptrue_reg (pred_mode);
rtx cond = gen_rtx_fmt_ee (code, pred_mode, op0, op1);
aarch64_emit_sve_ptrue_op_cc (target, ptrue, cond);
}
@@ -16779,7 +17203,7 @@ aarch64_expand_sve_vec_cmp_float (rtx target, rtx_code code,
machine_mode pred_mode = GET_MODE (target);
machine_mode data_mode = GET_MODE (op0);
- rtx ptrue = force_reg (pred_mode, CONSTM1_RTX (pred_mode));
+ rtx ptrue = aarch64_ptrue_reg (pred_mode);
switch (code)
{
case UNORDERED:
@@ -16962,11 +17386,11 @@ aarch64_copy_one_block_and_progress_pointers (rtx *src, rtx *dst,
*dst = aarch64_progress_pointer (*dst);
}
-/* Expand movmem, as if from a __builtin_memcpy. Return true if
+/* Expand cpymem, as if from a __builtin_memcpy. Return true if
we succeed, otherwise return false. */
bool
-aarch64_expand_movmem (rtx *operands)
+aarch64_expand_cpymem (rtx *operands)
{
int n, mode_bits;
rtx dst = operands[0];
@@ -17232,7 +17656,10 @@ aarch64_expand_subvti (rtx op0, rtx low_dest, rtx low_in1,
static unsigned HOST_WIDE_INT
aarch64_asan_shadow_offset (void)
{
- return (HOST_WIDE_INT_1 << 36);
+ if (TARGET_ILP32)
+ return (HOST_WIDE_INT_1 << 29);
+ else
+ return (HOST_WIDE_INT_1 << 36);
}
static rtx
@@ -19337,6 +19764,9 @@ aarch64_libgcc_floating_mode_supported_p
#define TARGET_RUN_TARGET_SELFTESTS selftest::aarch64_run_selftests
#endif /* #if CHECKING_P */
+#undef TARGET_ASM_POST_CFI_STARTPROC
+#define TARGET_ASM_POST_CFI_STARTPROC aarch64_post_cfi_startproc
+
struct gcc_target targetm = TARGET_INITIALIZER;
#include "gt-aarch64.h"
diff --git a/gcc/config/aarch64/aarch64.h b/gcc/config/aarch64/aarch64.h
index 7bd3bf5..92e38a8 100644
--- a/gcc/config/aarch64/aarch64.h
+++ b/gcc/config/aarch64/aarch64.h
@@ -192,6 +192,13 @@ extern unsigned aarch64_architecture_version;
/* Execution and Data Prediction Restriction instructions supported. */
#define AARCH64_FL_PREDRES (1 << 27)
+/* SVE2 instruction supported. */
+#define AARCH64_FL_SVE2 (1 << 28)
+#define AARCH64_FL_SVE2_AES (1 << 29)
+#define AARCH64_FL_SVE2_SM4 (1 << 30)
+#define AARCH64_FL_SVE2_SHA3 (1ULL << 31)
+#define AARCH64_FL_SVE2_BITPERM (1ULL << 32)
+
/* Has FP and SIMD. */
#define AARCH64_FL_FPSIMD (AARCH64_FL_FP | AARCH64_FL_SIMD)
@@ -225,6 +232,7 @@ extern unsigned aarch64_architecture_version;
#define AARCH64_ISA_V8_2 (aarch64_isa_flags & AARCH64_FL_V8_2)
#define AARCH64_ISA_F16 (aarch64_isa_flags & AARCH64_FL_F16)
#define AARCH64_ISA_SVE (aarch64_isa_flags & AARCH64_FL_SVE)
+#define AARCH64_ISA_SVE2 (aarch64_isa_flags & AARCH64_FL_SVE2)
#define AARCH64_ISA_V8_3 (aarch64_isa_flags & AARCH64_FL_V8_3)
#define AARCH64_ISA_DOTPROD (aarch64_isa_flags & AARCH64_FL_DOTPROD)
#define AARCH64_ISA_AES (aarch64_isa_flags & AARCH64_FL_AES)
@@ -270,6 +278,9 @@ extern unsigned aarch64_architecture_version;
/* SVE instructions, enabled through +sve. */
#define TARGET_SVE (AARCH64_ISA_SVE)
+/* SVE2 instructions, enabled through +sve2. */
+#define TARGET_SVE2 (AARCH64_ISA_SVE2)
+
/* ARMv8.3-A features. */
#define TARGET_ARMV8_3 (AARCH64_ISA_V8_3)
@@ -505,6 +516,18 @@ extern unsigned aarch64_architecture_version;
#define ASM_DECLARE_FUNCTION_NAME(STR, NAME, DECL) \
aarch64_declare_function_name (STR, NAME, DECL)
+/* Output assembly strings for alias definition. */
+#define ASM_OUTPUT_DEF_FROM_DECLS(STR, DECL, TARGET) \
+ aarch64_asm_output_alias (STR, DECL, TARGET)
+
+/* Output assembly strings for undefined extern symbols. */
+#undef ASM_OUTPUT_EXTERNAL
+#define ASM_OUTPUT_EXTERNAL(STR, DECL, NAME) \
+ aarch64_asm_output_external (STR, DECL, NAME)
+
+/* Output assembly strings after .cfi_startproc is emitted. */
+#define ASM_POST_CFI_STARTPROC aarch64_post_cfi_startproc
+
/* For EH returns X4 contains the stack adjustment. */
#define EH_RETURN_STACKADJ_RTX gen_rtx_REG (Pmode, R4_REGNUM)
#define EH_RETURN_HANDLER_RTX aarch64_eh_return_handler_rtx ()
@@ -832,7 +855,7 @@ typedef struct
/* MOVE_RATIO dictates when we will use the move_by_pieces infrastructure.
move_by_pieces will continually copy the largest safe chunks. So a
7-byte copy is a 4-byte + 2-byte + byte copy. This proves inefficient
- for both size and speed of copy, so we will instead use the "movmem"
+ for both size and speed of copy, so we will instead use the "cpymem"
standard name to implement the copy. This logic does not apply when
targeting -mstrict-align, so keep a sensible default in that case. */
#define MOVE_RATIO(speed) \
diff --git a/gcc/config/aarch64/aarch64.md b/gcc/config/aarch64/aarch64.md
index 5a18940..4d559c4 100644
--- a/gcc/config/aarch64/aarch64.md
+++ b/gcc/config/aarch64/aarch64.md
@@ -120,13 +120,16 @@
;; Scratch registers used in frame layout.
(IP0_REGNUM 16)
(IP1_REGNUM 17)
+ (FP_REGNUM 29)
(LR_REGNUM 30)
]
)
(define_c_enum "unspec" [
- UNSPEC_AUTI1716
- UNSPEC_AUTISP
+ UNSPEC_AUTIA1716
+ UNSPEC_AUTIB1716
+ UNSPEC_AUTIASP
+ UNSPEC_AUTIBSP
UNSPEC_CASESI
UNSPEC_CRC32B
UNSPEC_CRC32CB
@@ -169,8 +172,10 @@
UNSPEC_LD4_LANE
UNSPEC_MB
UNSPEC_NOP
- UNSPEC_PACI1716
- UNSPEC_PACISP
+ UNSPEC_PACIA1716
+ UNSPEC_PACIB1716
+ UNSPEC_PACIASP
+ UNSPEC_PACIBSP
UNSPEC_PRLG_STK
UNSPEC_REV
UNSPEC_RBIT
@@ -383,8 +388,8 @@
(define_expand "cbranch<mode>4"
[(set (pc) (if_then_else (match_operator 0 "aarch64_comparison_operator"
- [(match_operand:GPI 1 "register_operand" "")
- (match_operand:GPI 2 "aarch64_plus_operand" "")])
+ [(match_operand:GPI 1 "register_operand")
+ (match_operand:GPI 2 "aarch64_plus_operand")])
(label_ref (match_operand 3 "" ""))
(pc)))]
""
@@ -397,8 +402,8 @@
(define_expand "cbranch<mode>4"
[(set (pc) (if_then_else (match_operator 0 "aarch64_comparison_operator"
- [(match_operand:GPF 1 "register_operand" "")
- (match_operand:GPF 2 "aarch64_fp_compare_operand" "")])
+ [(match_operand:GPF 1 "register_operand")
+ (match_operand:GPF 2 "aarch64_fp_compare_operand")])
(label_ref (match_operand 3 "" ""))
(pc)))]
""
@@ -412,7 +417,7 @@
(define_expand "cbranchcc4"
[(set (pc) (if_then_else
(match_operator 0 "aarch64_comparison_operator"
- [(match_operand 1 "cc_register" "")
+ [(match_operand 1 "cc_register")
(match_operand 2 "const0_operand")])
(label_ref (match_operand 3 "" ""))
(pc)))]
@@ -475,9 +480,9 @@
;; csneg x0, x0, x1, mi
(define_expand "mod<mode>3"
- [(match_operand:GPI 0 "register_operand" "")
- (match_operand:GPI 1 "register_operand" "")
- (match_operand:GPI 2 "const_int_operand" "")]
+ [(match_operand:GPI 0 "register_operand")
+ (match_operand:GPI 1 "register_operand")
+ (match_operand:GPI 2 "const_int_operand")]
""
{
HOST_WIDE_INT val = INTVAL (operands[2]);
@@ -530,10 +535,14 @@
(pc)))]
""
{
+ /* GCC's traditional style has been to use "beq" instead of "b.eq", etc.,
+ but the "." is required for SVE conditions. */
+ bool use_dot_p = GET_MODE (operands[1]) == CC_NZCmode;
if (get_attr_length (insn) == 8)
- return aarch64_gen_far_branch (operands, 2, "Lbcond", "b%M0\\t");
+ return aarch64_gen_far_branch (operands, 2, "Lbcond",
+ use_dot_p ? "b.%M0\\t" : "b%M0\\t");
else
- return "b%m0\\t%l2";
+ return use_dot_p ? "b.%m0\\t%l2" : "b%m0\\t%l2";
}
[(set_attr "type" "branch")
(set (attr "length")
@@ -584,9 +593,9 @@
)
(define_expand "casesi"
- [(match_operand:SI 0 "register_operand" "") ; Index
- (match_operand:SI 1 "const_int_operand" "") ; Lower bound
- (match_operand:SI 2 "const_int_operand" "") ; Total range
+ [(match_operand:SI 0 "register_operand") ; Index
+ (match_operand:SI 1 "const_int_operand") ; Lower bound
+ (match_operand:SI 2 "const_int_operand") ; Total range
(match_operand:DI 3 "" "") ; Table label
(match_operand:DI 4 "" "")] ; Out of range label
""
@@ -739,8 +748,12 @@
if (aarch64_return_address_signing_enabled ()
&& TARGET_ARMV8_3
&& !crtl->calls_eh_return)
- return "retaa";
-
+ {
+ if (aarch64_ra_sign_key == AARCH64_KEY_B)
+ return "retab";
+ else
+ return "retaa";
+ }
return "ret";
}
[(set_attr "type" "branch")]
@@ -868,8 +881,8 @@
;; -------------------------------------------------------------------
(define_expand "call"
- [(parallel [(call (match_operand 0 "memory_operand" "")
- (match_operand 1 "general_operand" ""))
+ [(parallel [(call (match_operand 0 "memory_operand")
+ (match_operand 1 "general_operand"))
(use (match_operand 2 "" ""))
(clobber (reg:DI LR_REGNUM))])]
""
@@ -893,8 +906,8 @@
(define_expand "call_value"
[(parallel [(set (match_operand 0 "" "")
- (call (match_operand 1 "memory_operand" "")
- (match_operand 2 "general_operand" "")))
+ (call (match_operand 1 "memory_operand")
+ (match_operand 2 "general_operand")))
(use (match_operand 3 "" ""))
(clobber (reg:DI LR_REGNUM))])]
""
@@ -918,8 +931,8 @@
)
(define_expand "sibcall"
- [(parallel [(call (match_operand 0 "memory_operand" "")
- (match_operand 1 "general_operand" ""))
+ [(parallel [(call (match_operand 0 "memory_operand")
+ (match_operand 1 "general_operand"))
(return)
(use (match_operand 2 "" ""))])]
""
@@ -931,8 +944,8 @@
(define_expand "sibcall_value"
[(parallel [(set (match_operand 0 "" "")
- (call (match_operand 1 "memory_operand" "")
- (match_operand 2 "general_operand" "")))
+ (call (match_operand 1 "memory_operand")
+ (match_operand 2 "general_operand")))
(return)
(use (match_operand 3 "" ""))])]
""
@@ -998,8 +1011,8 @@
;; -------------------------------------------------------------------
(define_expand "mov<mode>"
- [(set (match_operand:SHORT 0 "nonimmediate_operand" "")
- (match_operand:SHORT 1 "general_operand" ""))]
+ [(set (match_operand:SHORT 0 "nonimmediate_operand")
+ (match_operand:SHORT 1 "general_operand"))]
""
"
if (GET_CODE (operands[0]) == MEM && operands[1] != const0_rtx)
@@ -1055,8 +1068,8 @@
)
(define_expand "mov<mode>"
- [(set (match_operand:GPI 0 "nonimmediate_operand" "")
- (match_operand:GPI 1 "general_operand" ""))]
+ [(set (match_operand:GPI 0 "nonimmediate_operand")
+ (match_operand:GPI 1 "general_operand"))]
""
"
if (MEM_P (operands[0]) && CONST_INT_P (operands[1])
@@ -1162,8 +1175,8 @@
)
(define_expand "movti"
- [(set (match_operand:TI 0 "nonimmediate_operand" "")
- (match_operand:TI 1 "general_operand" ""))]
+ [(set (match_operand:TI 0 "nonimmediate_operand")
+ (match_operand:TI 1 "general_operand"))]
""
"
if (GET_CODE (operands[0]) == MEM && operands[1] != const0_rtx)
@@ -1217,8 +1230,8 @@
})
(define_expand "mov<mode>"
- [(set (match_operand:GPF_TF_F16 0 "nonimmediate_operand" "")
- (match_operand:GPF_TF_F16 1 "general_operand" ""))]
+ [(set (match_operand:GPF_TF_F16 0 "nonimmediate_operand")
+ (match_operand:GPF_TF_F16 1 "general_operand"))]
""
{
if (!TARGET_FLOAT)
@@ -1363,17 +1376,17 @@
;; 0 is dst
;; 1 is src
-;; 2 is size of move in bytes
+;; 2 is size of copy in bytes
;; 3 is alignment
-(define_expand "movmemdi"
+(define_expand "cpymemdi"
[(match_operand:BLK 0 "memory_operand")
(match_operand:BLK 1 "memory_operand")
(match_operand:DI 2 "immediate_operand")
(match_operand:DI 3 "immediate_operand")]
"!STRICT_ALIGNMENT"
{
- if (aarch64_expand_movmem (operands))
+ if (aarch64_expand_cpymem (operands))
DONE;
FAIL;
}
@@ -1702,9 +1715,9 @@
(define_expand "add<mode>3"
[(set
- (match_operand:GPI 0 "register_operand" "")
- (plus:GPI (match_operand:GPI 1 "register_operand" "")
- (match_operand:GPI 2 "aarch64_pluslong_or_poly_operand" "")))]
+ (match_operand:GPI 0 "register_operand")
+ (plus:GPI (match_operand:GPI 1 "register_operand")
+ (match_operand:GPI 2 "aarch64_pluslong_or_poly_operand")))]
""
{
/* If operands[1] is a subreg extract the inner RTX. */
@@ -1897,9 +1910,9 @@
})
(define_expand "addti3"
- [(set (match_operand:TI 0 "register_operand" "")
- (plus:TI (match_operand:TI 1 "register_operand" "")
- (match_operand:TI 2 "aarch64_reg_or_imm" "")))]
+ [(set (match_operand:TI 0 "register_operand")
+ (plus:TI (match_operand:TI 1 "register_operand")
+ (match_operand:TI 2 "aarch64_reg_or_imm")))]
""
{
rtx low_dest, op1_low, op2_low, high_dest, op1_high, op2_high;
@@ -1930,9 +1943,9 @@
})
(define_expand "addvti4"
- [(match_operand:TI 0 "register_operand" "")
- (match_operand:TI 1 "register_operand" "")
- (match_operand:TI 2 "aarch64_reg_or_imm" "")
+ [(match_operand:TI 0 "register_operand")
+ (match_operand:TI 1 "register_operand")
+ (match_operand:TI 2 "aarch64_reg_or_imm")
(label_ref (match_operand 3 "" ""))]
""
{
@@ -1964,9 +1977,9 @@
})
(define_expand "uaddvti4"
- [(match_operand:TI 0 "register_operand" "")
- (match_operand:TI 1 "register_operand" "")
- (match_operand:TI 2 "aarch64_reg_or_imm" "")
+ [(match_operand:TI 0 "register_operand")
+ (match_operand:TI 1 "register_operand")
+ (match_operand:TI 2 "aarch64_reg_or_imm")
(label_ref (match_operand 3 "" ""))]
""
{
@@ -2501,9 +2514,9 @@
(plus:<DWI>
(match_dup 4)
(zero_extend:<DWI>
- (match_operand:GPI 1 "register_operand" "")))
+ (match_operand:GPI 1 "register_operand")))
(zero_extend:<DWI>
- (match_operand:GPI 2 "register_operand" "")))
+ (match_operand:GPI 2 "register_operand")))
(match_dup 6)))
(set (match_operand:GPI 0 "register_operand")
(plus:GPI
@@ -2564,9 +2577,9 @@
(plus:<DWI>
(match_dup 3)
(sign_extend:<DWI>
- (match_operand:GPI 1 "register_operand" "")))
+ (match_operand:GPI 1 "register_operand")))
(sign_extend:<DWI>
- (match_operand:GPI 2 "register_operand" "")))
+ (match_operand:GPI 2 "register_operand")))
(sign_extend:<DWI>
(plus:GPI
(plus:GPI (match_dup 4) (match_dup 1))
@@ -2835,9 +2848,9 @@
})
(define_expand "subti3"
- [(set (match_operand:TI 0 "register_operand" "")
- (minus:TI (match_operand:TI 1 "aarch64_reg_or_zero" "")
- (match_operand:TI 2 "register_operand" "")))]
+ [(set (match_operand:TI 0 "register_operand")
+ (minus:TI (match_operand:TI 1 "aarch64_reg_or_zero")
+ (match_operand:TI 2 "register_operand")))]
""
{
rtx low_dest, op1_low, op2_low, high_dest, op1_high, op2_high;
@@ -3285,12 +3298,12 @@
[(set (reg:CC CC_REGNUM)
(compare:CC
(zero_extend:<DWI>
- (match_operand:GPI 1 "aarch64_reg_or_zero" ""))
+ (match_operand:GPI 1 "aarch64_reg_or_zero"))
(plus:<DWI>
(zero_extend:<DWI>
- (match_operand:GPI 2 "register_operand" ""))
+ (match_operand:GPI 2 "register_operand"))
(ltu:<DWI> (reg:CC CC_REGNUM) (const_int 0)))))
- (set (match_operand:GPI 0 "register_operand" "")
+ (set (match_operand:GPI 0 "register_operand")
(minus:GPI
(minus:GPI (match_dup 1) (match_dup 2))
(ltu:GPI (reg:CC CC_REGNUM) (const_int 0))))])]
@@ -3353,16 +3366,16 @@
(compare:CC_V
(minus:<DWI>
(sign_extend:<DWI>
- (match_operand:GPI 1 "aarch64_reg_or_zero" ""))
+ (match_operand:GPI 1 "aarch64_reg_or_zero"))
(plus:<DWI>
(sign_extend:<DWI>
- (match_operand:GPI 2 "register_operand" ""))
+ (match_operand:GPI 2 "register_operand"))
(ltu:<DWI> (reg:CC CC_REGNUM) (const_int 0))))
(sign_extend:<DWI>
(minus:GPI (match_dup 1)
(plus:GPI (ltu:GPI (reg:CC CC_REGNUM) (const_int 0))
(match_dup 2))))))
- (set (match_operand:GPI 0 "register_operand" "")
+ (set (match_operand:GPI 0 "register_operand")
(minus:GPI
(minus:GPI (match_dup 1) (match_dup 2))
(ltu:GPI (reg:CC CC_REGNUM) (const_int 0))))])]
@@ -3475,8 +3488,8 @@
)
(define_expand "abs<mode>2"
- [(match_operand:GPI 0 "register_operand" "")
- (match_operand:GPI 1 "register_operand" "")]
+ [(match_operand:GPI 0 "register_operand")
+ (match_operand:GPI 1 "register_operand")]
""
{
rtx ccreg = aarch64_gen_compare_reg (LT, operands[1], const0_rtx);
@@ -3889,10 +3902,10 @@
;; -------------------------------------------------------------------
(define_expand "cstore<mode>4"
- [(set (match_operand:SI 0 "register_operand" "")
+ [(set (match_operand:SI 0 "register_operand")
(match_operator:SI 1 "aarch64_comparison_operator"
- [(match_operand:GPI 2 "register_operand" "")
- (match_operand:GPI 3 "aarch64_plus_operand" "")]))]
+ [(match_operand:GPI 2 "register_operand")
+ (match_operand:GPI 3 "aarch64_plus_operand")]))]
""
"
operands[2] = aarch64_gen_compare_reg (GET_CODE (operands[1]), operands[2],
@@ -3914,10 +3927,10 @@
(define_expand "cstore<mode>4"
- [(set (match_operand:SI 0 "register_operand" "")
+ [(set (match_operand:SI 0 "register_operand")
(match_operator:SI 1 "aarch64_comparison_operator_mode"
- [(match_operand:GPF 2 "register_operand" "")
- (match_operand:GPF 3 "aarch64_fp_compare_operand" "")]))]
+ [(match_operand:GPF 2 "register_operand")
+ (match_operand:GPF 3 "aarch64_fp_compare_operand")]))]
""
"
operands[2] = aarch64_gen_compare_reg (GET_CODE (operands[1]), operands[2],
@@ -4002,13 +4015,13 @@
)
(define_expand "cmov<mode>6"
- [(set (match_operand:GPI 0 "register_operand" "")
+ [(set (match_operand:GPI 0 "register_operand")
(if_then_else:GPI
(match_operator 1 "aarch64_comparison_operator"
- [(match_operand:GPI 2 "register_operand" "")
- (match_operand:GPI 3 "aarch64_plus_operand" "")])
- (match_operand:GPI 4 "register_operand" "")
- (match_operand:GPI 5 "register_operand" "")))]
+ [(match_operand:GPI 2 "register_operand")
+ (match_operand:GPI 3 "aarch64_plus_operand")])
+ (match_operand:GPI 4 "register_operand")
+ (match_operand:GPI 5 "register_operand")))]
""
"
operands[2] = aarch64_gen_compare_reg (GET_CODE (operands[1]), operands[2],
@@ -4018,13 +4031,13 @@
)
(define_expand "cmov<mode>6"
- [(set (match_operand:GPF 0 "register_operand" "")
+ [(set (match_operand:GPF 0 "register_operand")
(if_then_else:GPF
(match_operator 1 "aarch64_comparison_operator"
- [(match_operand:GPF 2 "register_operand" "")
- (match_operand:GPF 3 "aarch64_fp_compare_operand" "")])
- (match_operand:GPF 4 "register_operand" "")
- (match_operand:GPF 5 "register_operand" "")))]
+ [(match_operand:GPF 2 "register_operand")
+ (match_operand:GPF 3 "aarch64_fp_compare_operand")])
+ (match_operand:GPF 4 "register_operand")
+ (match_operand:GPF 5 "register_operand")))]
""
"
operands[2] = aarch64_gen_compare_reg (GET_CODE (operands[1]), operands[2],
@@ -4102,10 +4115,10 @@
)
(define_expand "mov<mode>cc"
- [(set (match_operand:ALLI 0 "register_operand" "")
- (if_then_else:ALLI (match_operand 1 "aarch64_comparison_operator" "")
- (match_operand:ALLI 2 "register_operand" "")
- (match_operand:ALLI 3 "register_operand" "")))]
+ [(set (match_operand:ALLI 0 "register_operand")
+ (if_then_else:ALLI (match_operand 1 "aarch64_comparison_operator")
+ (match_operand:ALLI 2 "register_operand")
+ (match_operand:ALLI 3 "register_operand")))]
""
{
rtx ccreg;
@@ -4121,10 +4134,10 @@
)
(define_expand "mov<GPF:mode><GPI:mode>cc"
- [(set (match_operand:GPI 0 "register_operand" "")
- (if_then_else:GPI (match_operand 1 "aarch64_comparison_operator" "")
- (match_operand:GPF 2 "register_operand" "")
- (match_operand:GPF 3 "register_operand" "")))]
+ [(set (match_operand:GPI 0 "register_operand")
+ (if_then_else:GPI (match_operand 1 "aarch64_comparison_operator")
+ (match_operand:GPF 2 "register_operand")
+ (match_operand:GPF 3 "register_operand")))]
""
{
rtx ccreg;
@@ -4140,10 +4153,10 @@
)
(define_expand "mov<mode>cc"
- [(set (match_operand:GPF 0 "register_operand" "")
- (if_then_else:GPF (match_operand 1 "aarch64_comparison_operator" "")
- (match_operand:GPF 2 "register_operand" "")
- (match_operand:GPF 3 "register_operand" "")))]
+ [(set (match_operand:GPF 0 "register_operand")
+ (if_then_else:GPF (match_operand 1 "aarch64_comparison_operator")
+ (match_operand:GPF 2 "register_operand")
+ (match_operand:GPF 3 "register_operand")))]
""
{
rtx ccreg;
@@ -4159,10 +4172,10 @@
)
(define_expand "<neg_not_op><mode>cc"
- [(set (match_operand:GPI 0 "register_operand" "")
- (if_then_else:GPI (match_operand 1 "aarch64_comparison_operator" "")
- (NEG_NOT:GPI (match_operand:GPI 2 "register_operand" ""))
- (match_operand:GPI 3 "register_operand" "")))]
+ [(set (match_operand:GPI 0 "register_operand")
+ (if_then_else:GPI (match_operand 1 "aarch64_comparison_operator")
+ (NEG_NOT:GPI (match_operand:GPI 2 "register_operand"))
+ (match_operand:GPI 3 "register_operand")))]
""
{
rtx ccreg;
@@ -5391,7 +5404,7 @@
;; -------------------------------------------------------------------
(define_expand "<optab>"
- [(set (match_operand:DI 0 "register_operand" "=r")
+ [(set (match_operand:DI 0 "register_operand")
(ANY_EXTRACT:DI (match_operand:DI 1 "register_operand")
(match_operand 2
"aarch64_simd_shift_imm_offset_di")
@@ -6241,8 +6254,8 @@
)
(define_expand "sqrt<mode>2"
- [(set (match_operand:GPF_F16 0 "register_operand" "=w")
- (sqrt:GPF_F16 (match_operand:GPF_F16 1 "register_operand" "w")))]
+ [(set (match_operand:GPF_F16 0 "register_operand")
+ (sqrt:GPF_F16 (match_operand:GPF_F16 1 "register_operand")))]
"TARGET_FLOAT"
{
if (aarch64_emit_approx_sqrt (operands[0], operands[1], false))
@@ -6401,6 +6414,7 @@
;; -------------------------------------------------------------------
;; Reload Scalar Floating point modes from constant pool.
;; The AArch64 port doesn't have __int128 constant move support.
+;; The patterns need constraints due to TARGET_SECONDARY_RELOAD hook.
(define_expand "@aarch64_reload_movcp<GPF_TF:mode><P:mode>"
[(set (match_operand:GPF_TF 0 "register_operand" "=w")
(mem:GPF_TF (match_operand 1 "aarch64_constant_pool_symref" "S")))
@@ -6501,9 +6515,9 @@
;; rodata section.
(define_expand "add_losym"
- [(set (match_operand 0 "register_operand" "=r")
- (lo_sum (match_operand 1 "register_operand" "r")
- (match_operand 2 "aarch64_valid_symref" "S")))]
+ [(set (match_operand 0 "register_operand")
+ (lo_sum (match_operand 1 "register_operand")
+ (match_operand 2 "aarch64_valid_symref")))]
""
{
machine_mode mode = GET_MODE (operands[0]);
@@ -6592,9 +6606,9 @@
;; instructions in the TLS stubs, in order to enable linker relaxation.
;; Therefore we treat the stubs as an atomic sequence.
(define_expand "tlsgd_small_<mode>"
- [(parallel [(set (match_operand 0 "register_operand" "")
+ [(parallel [(set (match_operand 0 "register_operand")
(call (mem:DI (match_dup 2)) (const_int 1)))
- (unspec:DI [(match_operand:PTR 1 "aarch64_valid_symref" "")] UNSPEC_GOTSMALLTLS)
+ (unspec:DI [(match_operand:PTR 1 "aarch64_valid_symref")] UNSPEC_GOTSMALLTLS)
(clobber (reg:DI LR_REGNUM))])]
""
{
@@ -6719,7 +6733,8 @@
UNSPEC_TLSDESC))
(clobber (reg:DI LR_REGNUM))
(clobber (reg:CC CC_REGNUM))
- (clobber (match_scratch:DI 1 "=r"))]
+ (clobber (match_scratch:DI 1 "=r"))
+ (use (reg:DI FP_REGNUM))]
"TARGET_TLS_DESC && !TARGET_SVE"
"adrp\\tx0, %A0\;ldr\\t%<w>1, [x0, #%L0]\;add\\t<w>0, <w>0, %L0\;.tlsdesccall\\t%0\;blr\\t%1"
[(set_attr "type" "call")
@@ -6782,7 +6797,8 @@
(clobber (reg:VNx2BI P13_REGNUM))
(clobber (reg:VNx2BI P14_REGNUM))
(clobber (reg:VNx2BI P15_REGNUM))
- (clobber (match_scratch:DI 1 "=r"))]
+ (clobber (match_scratch:DI 1 "=r"))
+ (use (reg:DI FP_REGNUM))]
"TARGET_TLS_DESC && TARGET_SVE"
"adrp\\tx0, %A0\;ldr\\t%<w>1, [x0, #%L0]\;add\\t<w>0, <w>0, %L0\;.tlsdesccall\\t%0\;blr\\t%1"
[(set_attr "type" "call")
@@ -6811,7 +6827,7 @@
[(set (reg:DI R30_REGNUM)
(unspec:DI [(reg:DI R30_REGNUM) (reg:DI SP_REGNUM)] PAUTH_LR_SP))]
""
- "hint\t<pauth_hint_num_a> // <pauth_mnem_prefix>asp";
+ "hint\t<pauth_hint_num> // <pauth_mnem_prefix>sp";
)
;; Signing/Authenticating X17 using X16 as the salt.
@@ -6820,7 +6836,7 @@
[(set (reg:DI R17_REGNUM)
(unspec:DI [(reg:DI R17_REGNUM) (reg:DI R16_REGNUM)] PAUTH_17_16))]
""
- "hint\t<pauth_hint_num_a> // <pauth_mnem_prefix>a1716";
+ "hint\t<pauth_hint_num> // <pauth_mnem_prefix>1716";
)
;; Stripping the signature in R30.
@@ -6875,7 +6891,7 @@
;; Named pattern for expanding thread pointer reference.
(define_expand "get_thread_pointerdi"
- [(match_operand:DI 0 "register_operand" "=r")]
+ [(match_operand:DI 0 "register_operand")]
""
{
rtx tmp = aarch64_load_tp (operands[0]);
@@ -7113,10 +7129,10 @@
)
;; Helper for aarch64.c code.
-(define_expand "set_clobber_cc"
+(define_expand "set_clobber_cc_nzc"
[(parallel [(set (match_operand 0)
(match_operand 1))
- (clobber (reg:CC CC_REGNUM))])])
+ (clobber (reg:CC_NZC CC_REGNUM))])])
;; Hard speculation barrier.
(define_insn "speculation_barrier"
@@ -7132,10 +7148,10 @@
;; tracking enabled. Use the speculation tracker to decide whether to
;; copy operand 1 to the target, or to copy the fail value (operand 2).
(define_expand "@despeculate_copy<ALLI_TI:mode>"
- [(set (match_operand:ALLI_TI 0 "register_operand" "=r")
+ [(set (match_operand:ALLI_TI 0 "register_operand")
(unspec_volatile:ALLI_TI
- [(match_operand:ALLI_TI 1 "register_operand" "r")
- (match_operand:ALLI_TI 2 "aarch64_reg_or_zero" "rZ")
+ [(match_operand:ALLI_TI 1 "register_operand")
+ (match_operand:ALLI_TI 2 "aarch64_reg_or_zero")
(use (reg:DI SPECULATION_TRACKER_REGNUM))
(clobber (reg:CC CC_REGNUM))] UNSPECV_SPECULATION_BARRIER))]
""
@@ -7236,3 +7252,6 @@
;; SVE.
(include "aarch64-sve.md")
+
+;; SVE2.
+(include "aarch64-sve2.md")
diff --git a/gcc/config/aarch64/aarch64.opt b/gcc/config/aarch64/aarch64.opt
index 7719c3b6..2c8b22c 100644
--- a/gcc/config/aarch64/aarch64.opt
+++ b/gcc/config/aarch64/aarch64.opt
@@ -31,7 +31,7 @@ TargetSave
const char *x_aarch64_override_tune_string
TargetVariable
-unsigned long aarch64_isa_flags = 0
+uint64_t aarch64_isa_flags = 0
TargetVariable
unsigned aarch64_enable_bti = 2
diff --git a/gcc/config/aarch64/atomics.md b/gcc/config/aarch64/atomics.md
index b6b5f6b..a679270 100644
--- a/gcc/config/aarch64/atomics.md
+++ b/gcc/config/aarch64/atomics.md
@@ -21,11 +21,11 @@
;; Instruction patterns.
(define_expand "@atomic_compare_and_swap<mode>"
- [(match_operand:SI 0 "register_operand" "") ;; bool out
- (match_operand:ALLI 1 "register_operand" "") ;; val out
- (match_operand:ALLI 2 "aarch64_sync_memory_operand" "") ;; memory
- (match_operand:ALLI 3 "nonmemory_operand" "") ;; expected
- (match_operand:ALLI 4 "aarch64_reg_or_zero" "") ;; desired
+ [(match_operand:SI 0 "register_operand") ;; bool out
+ (match_operand:ALLI 1 "register_operand") ;; val out
+ (match_operand:ALLI 2 "aarch64_sync_memory_operand") ;; memory
+ (match_operand:ALLI 3 "nonmemory_operand") ;; expected
+ (match_operand:ALLI 4 "aarch64_reg_or_zero") ;; desired
(match_operand:SI 5 "const_int_operand") ;; is_weak
(match_operand:SI 6 "const_int_operand") ;; mod_s
(match_operand:SI 7 "const_int_operand")] ;; mod_f
@@ -134,10 +134,10 @@
})
(define_expand "atomic_exchange<mode>"
- [(match_operand:ALLI 0 "register_operand" "")
- (match_operand:ALLI 1 "aarch64_sync_memory_operand" "")
- (match_operand:ALLI 2 "aarch64_reg_or_zero" "")
- (match_operand:SI 3 "const_int_operand" "")]
+ [(match_operand:ALLI 0 "register_operand")
+ (match_operand:ALLI 1 "aarch64_sync_memory_operand")
+ (match_operand:ALLI 2 "aarch64_reg_or_zero")
+ (match_operand:SI 3 "const_int_operand")]
""
{
rtx (*gen) (rtx, rtx, rtx, rtx);
@@ -198,9 +198,9 @@
)
(define_expand "atomic_<atomic_optab><mode>"
- [(match_operand:ALLI 0 "aarch64_sync_memory_operand" "")
+ [(match_operand:ALLI 0 "aarch64_sync_memory_operand")
(atomic_op:ALLI
- (match_operand:ALLI 1 "<atomic_op_operand>" "")
+ (match_operand:ALLI 1 "<atomic_op_operand>")
(match_operand:SI 2 "const_int_operand"))]
""
{
@@ -322,10 +322,10 @@
;; Load-operate-store, returning the original memory data.
(define_expand "atomic_fetch_<atomic_optab><mode>"
- [(match_operand:ALLI 0 "register_operand" "")
- (match_operand:ALLI 1 "aarch64_sync_memory_operand" "")
+ [(match_operand:ALLI 0 "register_operand")
+ (match_operand:ALLI 1 "aarch64_sync_memory_operand")
(atomic_op:ALLI
- (match_operand:ALLI 2 "<atomic_op_operand>" "")
+ (match_operand:ALLI 2 "<atomic_op_operand>")
(match_operand:SI 3 "const_int_operand"))]
""
{
@@ -439,10 +439,10 @@
;; Load-operate-store, returning the updated memory data.
(define_expand "atomic_<atomic_optab>_fetch<mode>"
- [(match_operand:ALLI 0 "register_operand" "")
+ [(match_operand:ALLI 0 "register_operand")
(atomic_op:ALLI
- (match_operand:ALLI 1 "aarch64_sync_memory_operand" "")
- (match_operand:ALLI 2 "<atomic_op_operand>" ""))
+ (match_operand:ALLI 1 "aarch64_sync_memory_operand")
+ (match_operand:ALLI 2 "<atomic_op_operand>"))
(match_operand:SI 3 "const_int_operand")]
""
{
@@ -600,7 +600,7 @@
)
(define_expand "mem_thread_fence"
- [(match_operand:SI 0 "const_int_operand" "")]
+ [(match_operand:SI 0 "const_int_operand")]
""
{
enum memmodel model = memmodel_from_int (INTVAL (operands[0]));
diff --git a/gcc/config/aarch64/driver-aarch64.c b/gcc/config/aarch64/driver-aarch64.c
index 6f16775..ef4f183 100644
--- a/gcc/config/aarch64/driver-aarch64.c
+++ b/gcc/config/aarch64/driver-aarch64.c
@@ -32,7 +32,7 @@ std::string aarch64_get_extension_string_for_isa_flags (unsigned long,
struct aarch64_arch_extension
{
const char *ext;
- unsigned int flag;
+ uint64_t flag;
const char *feat_string;
};
@@ -52,7 +52,7 @@ struct aarch64_core_data
unsigned char implementer_id; /* Exactly 8 bits */
unsigned int part_no; /* 12 bits + 12 bits */
unsigned variant;
- const unsigned long flags;
+ const uint64_t flags;
};
#define AARCH64_BIG_LITTLE(BIG, LITTLE) \
@@ -75,7 +75,7 @@ struct aarch64_arch_driver_info
{
const char* id;
const char* name;
- const unsigned long flags;
+ const uint64_t flags;
};
#define AARCH64_ARCH(NAME, CORE, ARCH_IDENT, ARCH_REV, FLAGS) \
@@ -179,8 +179,8 @@ host_detect_local_cpu (int argc, const char **argv)
unsigned int variants[2] = { ALL_VARIANTS, ALL_VARIANTS };
unsigned int n_variants = 0;
bool processed_exts = false;
- unsigned long extension_flags = 0;
- unsigned long default_flags = 0;
+ uint64_t extension_flags = 0;
+ uint64_t default_flags = 0;
gcc_assert (argc);
diff --git a/gcc/config/aarch64/iterators.md b/gcc/config/aarch64/iterators.md
index 20aa0e9..410423b 100644
--- a/gcc/config/aarch64/iterators.md
+++ b/gcc/config/aarch64/iterators.md
@@ -768,6 +768,7 @@
;; Half modes of all vector modes, in lower-case.
(define_mode_attr Vhalf [(V8QI "v4qi") (V16QI "v8qi")
(V4HI "v2hi") (V8HI "v4hi")
+ (V8HF "v4hf")
(V2SI "si") (V4SI "v2si")
(V2DI "di") (V2SF "sf")
(V4SF "v2sf") (V2DF "df")])
@@ -1214,7 +1215,7 @@
;; Signed and unsigned max operations.
(define_code_iterator USMAX [smax umax])
-;; Code iterator for variants of vector max and min.
+;; Code iterator for plus and minus.
(define_code_iterator ADDSUB [plus minus])
;; Code iterator for variants of vector saturating binary ops.
@@ -1516,9 +1517,11 @@
(define_int_iterator FMAXMIN_UNS [UNSPEC_FMAX UNSPEC_FMIN
UNSPEC_FMAXNM UNSPEC_FMINNM])
-(define_int_iterator PAUTH_LR_SP [UNSPEC_PACISP UNSPEC_AUTISP])
+(define_int_iterator PAUTH_LR_SP [UNSPEC_PACIASP UNSPEC_AUTIASP
+ UNSPEC_PACIBSP UNSPEC_AUTIBSP])
-(define_int_iterator PAUTH_17_16 [UNSPEC_PACI1716 UNSPEC_AUTI1716])
+(define_int_iterator PAUTH_17_16 [UNSPEC_PACIA1716 UNSPEC_AUTIA1716
+ UNSPEC_PACIB1716 UNSPEC_AUTIB1716])
(define_int_iterator VQDMULH [UNSPEC_SQDMULH UNSPEC_SQRDMULH])
@@ -1797,16 +1800,34 @@
(UNSPEC_FCVTZU "fcvtzu")])
;; Pointer authentication mnemonic prefix.
-(define_int_attr pauth_mnem_prefix [(UNSPEC_PACISP "paci")
- (UNSPEC_AUTISP "auti")
- (UNSPEC_PACI1716 "paci")
- (UNSPEC_AUTI1716 "auti")])
-
-;; Pointer authentication HINT number for NOP space instructions using A Key.
-(define_int_attr pauth_hint_num_a [(UNSPEC_PACISP "25")
- (UNSPEC_AUTISP "29")
- (UNSPEC_PACI1716 "8")
- (UNSPEC_AUTI1716 "12")])
+(define_int_attr pauth_mnem_prefix [(UNSPEC_PACIASP "pacia")
+ (UNSPEC_PACIBSP "pacib")
+ (UNSPEC_PACIA1716 "pacia")
+ (UNSPEC_PACIB1716 "pacib")
+ (UNSPEC_AUTIASP "autia")
+ (UNSPEC_AUTIBSP "autib")
+ (UNSPEC_AUTIA1716 "autia")
+ (UNSPEC_AUTIB1716 "autib")])
+
+(define_int_attr pauth_key [(UNSPEC_PACIASP "AARCH64_KEY_A")
+ (UNSPEC_PACIBSP "AARCH64_KEY_B")
+ (UNSPEC_PACIA1716 "AARCH64_KEY_A")
+ (UNSPEC_PACIB1716 "AARCH64_KEY_B")
+ (UNSPEC_AUTIASP "AARCH64_KEY_A")
+ (UNSPEC_AUTIBSP "AARCH64_KEY_B")
+ (UNSPEC_AUTIA1716 "AARCH64_KEY_A")
+ (UNSPEC_AUTIB1716 "AARCH64_KEY_B")])
+
+;; Pointer authentication HINT number for NOP space instructions using A and
+;; B key.
+(define_int_attr pauth_hint_num [(UNSPEC_PACIASP "25")
+ (UNSPEC_PACIBSP "27")
+ (UNSPEC_AUTIASP "29")
+ (UNSPEC_AUTIBSP "31")
+ (UNSPEC_PACIA1716 "8")
+ (UNSPEC_PACIB1716 "10")
+ (UNSPEC_AUTIA1716 "12")
+ (UNSPEC_AUTIB1716 "14")])
(define_int_attr perm_insn [(UNSPEC_ZIP1 "zip") (UNSPEC_ZIP2 "zip")
(UNSPEC_TRN1 "trn") (UNSPEC_TRN2 "trn")
diff --git a/gcc/config/aarch64/predicates.md b/gcc/config/aarch64/predicates.md
index 8e1b784..10100ca 100644
--- a/gcc/config/aarch64/predicates.md
+++ b/gcc/config/aarch64/predicates.md
@@ -323,12 +323,6 @@
(ior (match_operand 0 "register_operand")
(match_operand 0 "const_scalar_int_operand")))
-(define_predicate "aarch64_smin"
- (match_code "smin"))
-
-(define_predicate "aarch64_umin"
- (match_code "umin"))
-
;; True for integer comparisons and for FP comparisons other than LTGT or UNEQ.
(define_special_predicate "aarch64_comparison_operator"
(match_code "eq,ne,le,lt,ge,gt,geu,gtu,leu,ltu,unordered,
diff --git a/gcc/config/aarch64/t-aarch64-netbsd b/gcc/config/aarch64/t-aarch64-netbsd
new file mode 100644
index 0000000..aa447d0
--- /dev/null
+++ b/gcc/config/aarch64/t-aarch64-netbsd
@@ -0,0 +1,21 @@
+# Machine description for AArch64 architecture.
+# Copyright (C) 2016-2019 Free Software Foundation, Inc.
+#
+# This file is part of GCC.
+#
+# GCC is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# GCC is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GCC; see the file COPYING3. If not see
+# <http://www.gnu.org/licenses/>.
+
+LIB1ASMSRC = aarch64/lib1funcs.asm
+LIB1ASMFUNCS = _aarch64_sync_cache_range
diff --git a/gcc/config/alpha/alpha-protos.h b/gcc/config/alpha/alpha-protos.h
index 07c970760..7d34092 100644
--- a/gcc/config/alpha/alpha-protos.h
+++ b/gcc/config/alpha/alpha-protos.h
@@ -21,9 +21,8 @@ extern int alpha_next_sequence_number;
extern void literal_section (void);
extern int zap_mask (HOST_WIDE_INT);
-extern int direct_return (void);
+extern bool direct_return (void);
-extern int alpha_sa_size (void);
extern HOST_WIDE_INT alpha_initial_elimination_offset (unsigned int,
unsigned int);
extern void alpha_expand_prologue (void);
diff --git a/gcc/config/alpha/alpha.c b/gcc/config/alpha/alpha.c
index 984540f..10656be 100644
--- a/gcc/config/alpha/alpha.c
+++ b/gcc/config/alpha/alpha.c
@@ -731,19 +731,6 @@ alpha_vector_mode_supported_p (machine_mode mode)
return mode == V8QImode || mode == V4HImode || mode == V2SImode;
}
-/* Return 1 if this function can directly return via $26. */
-
-int
-direct_return (void)
-{
- return (TARGET_ABI_OSF
- && reload_completed
- && alpha_sa_size () == 0
- && get_frame_size () == 0
- && crtl->outgoing_args_size == 0
- && crtl->args.pretend_args_size == 0);
-}
-
/* Return the TLS model to use for SYMBOL. */
static enum tls_model
@@ -2305,10 +2292,7 @@ alpha_expand_mov_nobwx (machine_mode mode, rtx *operands)
{
if (reload_in_progress)
{
- if (mode == QImode)
- seq = gen_reload_inqi_aligned (operands[0], operands[1]);
- else
- seq = gen_reload_inhi_aligned (operands[0], operands[1]);
+ seq = gen_reload_in_aligned (mode, operands[0], operands[1]);
emit_insn (seq);
}
else
@@ -2391,10 +2375,8 @@ alpha_expand_mov_nobwx (machine_mode mode, rtx *operands)
rtx temp3 = gen_reg_rtx (DImode);
rtx ua = get_unaligned_address (operands[0]);
- if (mode == QImode)
- seq = gen_unaligned_storeqi (ua, operands[1], temp1, temp2, temp3);
- else
- seq = gen_unaligned_storehi (ua, operands[1], temp1, temp2, temp3);
+ seq = gen_unaligned_store
+ (mode, ua, operands[1], temp1, temp2, temp3);
alpha_set_memflags (seq, operands[0]);
emit_insn (seq);
@@ -4362,34 +4344,6 @@ emit_unlikely_jump (rtx cond, rtx label)
add_reg_br_prob_note (insn, profile_probability::very_unlikely ());
}
-/* A subroutine of the atomic operation splitters. Emit a load-locked
- instruction in MODE. */
-
-static void
-emit_load_locked (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;
- emit_insn (fn (reg, mem));
-}
-
-/* A subroutine of the atomic operation splitters. Emit a store-conditional
- instruction in MODE. */
-
-static void
-emit_store_conditional (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;
- emit_insn (fn (res, mem, val));
-}
-
/* Subroutines of the atomic operation splitters. Emit barriers
as needed for the memory MODEL. */
@@ -4461,7 +4415,7 @@ alpha_split_atomic_op (enum rtx_code code, rtx mem, rtx val, rtx before,
if (before == NULL)
before = scratch;
- emit_load_locked (mode, before, mem);
+ emit_insn (gen_load_locked (mode, before, mem));
if (code == NOT)
{
@@ -4476,7 +4430,7 @@ alpha_split_atomic_op (enum rtx_code code, rtx mem, rtx val, rtx before,
emit_insn (gen_rtx_SET (after, copy_rtx (x)));
emit_insn (gen_rtx_SET (scratch, x));
- emit_store_conditional (mode, cond, mem, scratch);
+ emit_insn (gen_store_conditional (mode, cond, mem, scratch));
x = gen_rtx_EQ (DImode, cond, const0_rtx);
emit_unlikely_jump (x, label);
@@ -4515,7 +4469,7 @@ alpha_split_compare_and_swap (rtx operands[])
}
label2 = gen_rtx_LABEL_REF (DImode, gen_label_rtx ());
- emit_load_locked (mode, retval, mem);
+ emit_insn (gen_load_locked (mode, retval, mem));
x = gen_lowpart (DImode, retval);
if (oldval == const0_rtx)
@@ -4532,7 +4486,8 @@ alpha_split_compare_and_swap (rtx operands[])
emit_unlikely_jump (x, label2);
emit_move_insn (cond, newval);
- emit_store_conditional (mode, cond, mem, gen_lowpart (mode, cond));
+ emit_insn (gen_store_conditional
+ (mode, cond, mem, gen_lowpart (mode, cond)));
if (!is_weak)
{
@@ -4555,7 +4510,6 @@ alpha_expand_compare_and_swap_12 (rtx operands[])
rtx cond, dst, mem, oldval, newval, is_weak, mod_s, mod_f;
machine_mode mode;
rtx addr, align, wdst;
- rtx (*gen) (rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx);
cond = operands[0];
dst = operands[1];
@@ -4580,12 +4534,9 @@ alpha_expand_compare_and_swap_12 (rtx operands[])
newval = emit_insxl (mode, newval, addr);
wdst = gen_reg_rtx (DImode);
- if (mode == QImode)
- gen = gen_atomic_compare_and_swapqi_1;
- else
- gen = gen_atomic_compare_and_swaphi_1;
- emit_insn (gen (cond, wdst, mem, oldval, newval, align,
- is_weak, mod_s, mod_f));
+ emit_insn (gen_atomic_compare_and_swap_1
+ (mode, cond, wdst, mem, oldval, newval, align,
+ is_weak, mod_s, mod_f));
emit_move_insn (dst, gen_lowpart (mode, wdst));
}
@@ -4627,7 +4578,7 @@ alpha_split_compare_and_swap_12 (rtx operands[])
}
label2 = gen_rtx_LABEL_REF (DImode, gen_label_rtx ());
- emit_load_locked (DImode, scratch, mem);
+ emit_insn (gen_load_locked (DImode, scratch, mem));
width = GEN_INT (GET_MODE_BITSIZE (mode));
mask = GEN_INT (mode == QImode ? 0xff : 0xffff);
@@ -4651,7 +4602,7 @@ alpha_split_compare_and_swap_12 (rtx operands[])
if (newval != const0_rtx)
emit_insn (gen_iordi3 (cond, cond, newval));
- emit_store_conditional (DImode, cond, mem, cond);
+ emit_insn (gen_store_conditional (DImode, cond, mem, cond));
if (!is_weak)
{
@@ -4691,9 +4642,9 @@ alpha_split_atomic_exchange (rtx operands[])
label = gen_rtx_LABEL_REF (DImode, gen_label_rtx ());
emit_label (XEXP (label, 0));
- emit_load_locked (mode, retval, mem);
+ emit_insn (gen_load_locked (mode, retval, mem));
emit_move_insn (scratch, val);
- emit_store_conditional (mode, cond, mem, scratch);
+ emit_insn (gen_store_conditional (mode, cond, mem, scratch));
x = gen_rtx_EQ (DImode, cond, const0_rtx);
emit_unlikely_jump (x, label);
@@ -4707,7 +4658,6 @@ alpha_expand_atomic_exchange_12 (rtx operands[])
rtx dst, mem, val, model;
machine_mode mode;
rtx addr, align, wdst;
- rtx (*gen) (rtx, rtx, rtx, rtx, rtx);
dst = operands[0];
mem = operands[1];
@@ -4727,11 +4677,7 @@ alpha_expand_atomic_exchange_12 (rtx operands[])
val = emit_insxl (mode, val, addr);
wdst = gen_reg_rtx (DImode);
- if (mode == QImode)
- gen = gen_atomic_exchangeqi_1;
- else
- gen = gen_atomic_exchangehi_1;
- emit_insn (gen (wdst, mem, val, align, model));
+ emit_insn (gen_atomic_exchange_1 (mode, wdst, mem, val, align, model));
emit_move_insn (dst, gen_lowpart (mode, wdst));
}
@@ -4763,7 +4709,7 @@ alpha_split_atomic_exchange_12 (rtx operands[])
label = gen_rtx_LABEL_REF (DImode, gen_label_rtx ());
emit_label (XEXP (label, 0));
- emit_load_locked (DImode, scratch, mem);
+ emit_insn (gen_load_locked (DImode, scratch, mem));
width = GEN_INT (GET_MODE_BITSIZE (mode));
mask = GEN_INT (mode == QImode ? 0xff : 0xffff);
@@ -4772,7 +4718,7 @@ alpha_split_atomic_exchange_12 (rtx operands[])
if (val != const0_rtx)
emit_insn (gen_iordi3 (scratch, scratch, val));
- emit_store_conditional (DImode, scratch, mem, scratch);
+ emit_insn (gen_store_conditional (DImode, scratch, mem, scratch));
x = gen_rtx_EQ (DImode, scratch, const0_rtx);
emit_unlikely_jump (x, label);
@@ -4840,6 +4786,10 @@ struct GTY(()) alpha_links;
struct GTY(()) machine_function
{
+ unsigned HOST_WIDE_INT sa_mask;
+ HOST_WIDE_INT sa_size;
+ HOST_WIDE_INT frame_size;
+
/* For flag_reorder_blocks_and_partition. */
rtx gp_save_rtx;
@@ -7271,83 +7221,59 @@ static int vms_save_fp_regno;
/* Register number used to reference objects off our PV. */
static int vms_base_regno;
-/* Compute register masks for saved registers. */
-
+/* Compute register masks for saved registers, register save area size,
+ and total frame size. */
static void
-alpha_sa_mask (unsigned long *imaskP, unsigned long *fmaskP)
+alpha_compute_frame_layout (void)
{
- unsigned long imask = 0;
- unsigned long fmask = 0;
- unsigned int i;
+ unsigned HOST_WIDE_INT sa_mask = 0;
+ HOST_WIDE_INT frame_size;
+ int sa_size;
/* When outputting a thunk, we don't have valid register life info,
but assemble_start_function wants to output .frame and .mask
directives. */
- if (cfun->is_thunk)
+ if (!cfun->is_thunk)
{
- *imaskP = 0;
- *fmaskP = 0;
- return;
- }
+ if (TARGET_ABI_OPEN_VMS && alpha_procedure_type == PT_STACK)
+ sa_mask |= HOST_WIDE_INT_1U << HARD_FRAME_POINTER_REGNUM;
- if (TARGET_ABI_OPEN_VMS && alpha_procedure_type == PT_STACK)
- imask |= (1UL << HARD_FRAME_POINTER_REGNUM);
+ /* One for every register we have to save. */
+ for (unsigned i = 0; i < FIRST_PSEUDO_REGISTER; i++)
+ if (! fixed_regs[i] && ! call_used_regs[i]
+ && df_regs_ever_live_p (i) && i != REG_RA)
+ sa_mask |= HOST_WIDE_INT_1U << i;
- /* One for every register we have to save. */
- for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
- if (! fixed_regs[i] && ! call_used_regs[i]
- && df_regs_ever_live_p (i) && i != REG_RA)
- {
- if (i < 32)
- imask |= (1UL << i);
- else
- fmask |= (1UL << (i - 32));
- }
-
- /* We need to restore these for the handler. */
- if (crtl->calls_eh_return)
- {
- for (i = 0; ; ++i)
+ /* We need to restore these for the handler. */
+ if (crtl->calls_eh_return)
{
- unsigned regno = EH_RETURN_DATA_REGNO (i);
- if (regno == INVALID_REGNUM)
- break;
- imask |= 1UL << regno;
+ for (unsigned i = 0; ; ++i)
+ {
+ unsigned regno = EH_RETURN_DATA_REGNO (i);
+ if (regno == INVALID_REGNUM)
+ break;
+ sa_mask |= HOST_WIDE_INT_1U << regno;
+ }
}
- }
-
- /* If any register spilled, then spill the return address also. */
- /* ??? This is required by the Digital stack unwind specification
- and isn't needed if we're doing Dwarf2 unwinding. */
- if (imask || fmask || alpha_ra_ever_killed ())
- imask |= (1UL << REG_RA);
-
- *imaskP = imask;
- *fmaskP = fmask;
-}
-
-int
-alpha_sa_size (void)
-{
- unsigned long mask[2];
- int sa_size = 0;
- int i, j;
- alpha_sa_mask (&mask[0], &mask[1]);
+ /* If any register spilled, then spill the return address also. */
+ /* ??? This is required by the Digital stack unwind specification
+ and isn't needed if we're doing Dwarf2 unwinding. */
+ if (sa_mask || alpha_ra_ever_killed ())
+ sa_mask |= HOST_WIDE_INT_1U << REG_RA;
+ }
- for (j = 0; j < 2; ++j)
- for (i = 0; i < 32; ++i)
- if ((mask[j] >> i) & 1)
- sa_size++;
+ sa_size = popcount_hwi(sa_mask);
+ frame_size = get_frame_size ();
if (TARGET_ABI_OPEN_VMS)
{
/* Start with a stack procedure if we make any calls (REG_RA used), or
need a frame pointer, with a register procedure if we otherwise need
at least a slot, and with a null procedure in other cases. */
- if ((mask[0] >> REG_RA) & 1 || frame_pointer_needed)
+ if ((sa_mask >> REG_RA) & 1 || frame_pointer_needed)
alpha_procedure_type = PT_STACK;
- else if (get_frame_size() != 0)
+ else if (frame_size != 0)
alpha_procedure_type = PT_REGISTER;
else
alpha_procedure_type = PT_NULL;
@@ -7371,12 +7297,15 @@ alpha_sa_size (void)
/* If we want to copy PV into FP, we need to find some register
in which to save FP. */
-
vms_save_fp_regno = -1;
if (vms_base_regno == HARD_FRAME_POINTER_REGNUM)
- for (i = 0; i < 32; i++)
- if (! fixed_regs[i] && call_used_regs[i] && ! df_regs_ever_live_p (i))
- vms_save_fp_regno = i;
+ for (unsigned i = 0; i < 32; i++)
+ if (! fixed_regs[i] && call_used_regs[i]
+ && ! df_regs_ever_live_p (i))
+ {
+ vms_save_fp_regno = i;
+ break;
+ }
/* A VMS condition handler requires a stack procedure in our
implementation. (not required by the calling standard). */
@@ -7401,8 +7330,34 @@ alpha_sa_size (void)
if (sa_size & 1)
sa_size++;
}
+ sa_size *= 8;
+
+ if (TARGET_ABI_OPEN_VMS)
+ frame_size = ALPHA_ROUND (sa_size
+ + (alpha_procedure_type == PT_STACK ? 8 : 0)
+ + frame_size
+ + crtl->args.pretend_args_size);
+ else
+ frame_size = (ALPHA_ROUND (crtl->outgoing_args_size)
+ + sa_size
+ + ALPHA_ROUND (frame_size + crtl->args.pretend_args_size));
+
+ cfun->machine->sa_mask = sa_mask;
+ cfun->machine->sa_size = sa_size;
+ cfun->machine->frame_size = frame_size;
+}
+
+#undef TARGET_COMPUTE_FRAME_LAYOUT
+#define TARGET_COMPUTE_FRAME_LAYOUT alpha_compute_frame_layout
- return sa_size * 8;
+/* Return 1 if this function can directly return via $26. */
+
+bool
+direct_return (void)
+{
+ return (TARGET_ABI_OSF
+ && reload_completed
+ && cfun->machine->frame_size == 0);
}
/* Define the offset between two registers, one to be eliminated,
@@ -7414,7 +7369,7 @@ alpha_initial_elimination_offset (unsigned int from,
{
HOST_WIDE_INT ret;
- ret = alpha_sa_size ();
+ ret = cfun->machine->sa_size;
ret += ALPHA_ROUND (crtl->outgoing_args_size);
switch (from)
@@ -7442,9 +7397,6 @@ alpha_initial_elimination_offset (unsigned int from,
static bool
alpha_vms_can_eliminate (const int from ATTRIBUTE_UNUSED, const int to)
{
- /* We need the alpha_procedure_type to decide. Evaluate it now. */
- alpha_sa_size ();
-
switch (alpha_procedure_type)
{
case PT_NULL:
@@ -7474,7 +7426,7 @@ alpha_vms_initial_elimination_offset (unsigned int from, unsigned int to)
on the proper computations and will need the register save area size
in most cases. */
- HOST_WIDE_INT sa_size = alpha_sa_size ();
+ HOST_WIDE_INT sa_size = cfun->machine->sa_size;
/* PT_NULL procedures have no frame of their own and we only allow
elimination to the stack pointer. This is the argument pointer and we
@@ -7706,24 +7658,6 @@ emit_frame_store (unsigned int regno, rtx base_reg,
emit_frame_store_1 (reg, base_reg, frame_bias, base_ofs, reg);
}
-/* Compute the frame size. SIZE is the size of the "naked" frame
- and SA_SIZE is the size of the register save area. */
-
-static HOST_WIDE_INT
-compute_frame_size (HOST_WIDE_INT size, HOST_WIDE_INT sa_size)
-{
- if (TARGET_ABI_OPEN_VMS)
- return ALPHA_ROUND (sa_size
- + (alpha_procedure_type == PT_STACK ? 8 : 0)
- + size
- + crtl->args.pretend_args_size);
- else
- return ALPHA_ROUND (crtl->outgoing_args_size)
- + sa_size
- + ALPHA_ROUND (size
- + crtl->args.pretend_args_size);
-}
-
/* Write function prologue. */
/* On vms we have two kinds of functions:
@@ -7745,22 +7679,17 @@ void
alpha_expand_prologue (void)
{
/* Registers to save. */
- unsigned long imask = 0;
- unsigned long fmask = 0;
+ unsigned HOST_WIDE_INT sa_mask = cfun->machine->sa_mask;
/* Stack space needed for pushing registers clobbered by us. */
- HOST_WIDE_INT sa_size, sa_bias;
+ HOST_WIDE_INT sa_size = cfun->machine->sa_size;
/* Complete stack size needed. */
- HOST_WIDE_INT frame_size;
+ HOST_WIDE_INT frame_size = cfun->machine->frame_size;
/* Probed stack size; it additionally includes the size of
the "reserve region" if any. */
- HOST_WIDE_INT probed_size;
+ HOST_WIDE_INT probed_size, sa_bias;
/* Offset from base reg to register save area. */
HOST_WIDE_INT reg_offset;
rtx sa_reg;
- int i;
-
- sa_size = alpha_sa_size ();
- frame_size = compute_frame_size (get_frame_size (), sa_size);
if (flag_stack_usage_info)
current_function_static_stack_size = frame_size;
@@ -7770,8 +7699,6 @@ alpha_expand_prologue (void)
else
reg_offset = ALPHA_ROUND (crtl->outgoing_args_size);
- alpha_sa_mask (&imask, &fmask);
-
/* Emit an insn to reload GP, if needed. */
if (TARGET_ABI_OSF)
{
@@ -7910,29 +7837,15 @@ alpha_expand_prologue (void)
if (TARGET_ABI_OPEN_VMS && alpha_procedure_type == PT_STACK)
emit_frame_store (REG_PV, stack_pointer_rtx, 0, 0);
- /* Save register RA next. */
- if (imask & (1UL << REG_RA))
+ /* Save register RA next, followed by any other registers
+ that need to be saved. */
+ for (unsigned i = REG_RA; sa_mask != 0; i = ctz_hwi(sa_mask))
{
- emit_frame_store (REG_RA, sa_reg, sa_bias, reg_offset);
- imask &= ~(1UL << REG_RA);
+ emit_frame_store (i, sa_reg, sa_bias, reg_offset);
reg_offset += 8;
+ sa_mask &= ~(HOST_WIDE_INT_1U << i);
}
- /* Now save any other registers required to be saved. */
- for (i = 0; i < 31; i++)
- if (imask & (1UL << i))
- {
- emit_frame_store (i, sa_reg, sa_bias, reg_offset);
- reg_offset += 8;
- }
-
- for (i = 0; i < 31; i++)
- if (fmask & (1UL << i))
- {
- emit_frame_store (i+32, sa_reg, sa_bias, reg_offset);
- reg_offset += 8;
- }
-
if (TARGET_ABI_OPEN_VMS)
{
/* Register frame procedures save the fp. */
@@ -8019,14 +7932,11 @@ void
alpha_start_function (FILE *file, const char *fnname,
tree decl ATTRIBUTE_UNUSED)
{
- unsigned long imask = 0;
- unsigned long fmask = 0;
- /* Stack space needed for pushing registers clobbered by us. */
- HOST_WIDE_INT sa_size;
+ unsigned long imask, fmask;
/* Complete stack size needed. */
- unsigned HOST_WIDE_INT frame_size;
+ HOST_WIDE_INT frame_size = cfun->machine->frame_size;
/* The maximum debuggable frame size. */
- unsigned HOST_WIDE_INT max_frame_size = 1UL << 31;
+ const HOST_WIDE_INT max_frame_size = HOST_WIDE_INT_1 << 31;
/* Offset from base reg to register save area. */
HOST_WIDE_INT reg_offset;
char *entry_label = (char *) alloca (strlen (fnname) + 6);
@@ -8038,15 +7948,14 @@ alpha_start_function (FILE *file, const char *fnname,
#endif
alpha_fnname = fnname;
- sa_size = alpha_sa_size ();
- frame_size = compute_frame_size (get_frame_size (), sa_size);
if (TARGET_ABI_OPEN_VMS)
reg_offset = 8 + 8 * cfun->machine->uses_condition_handler;
else
reg_offset = ALPHA_ROUND (crtl->outgoing_args_size);
- alpha_sa_mask (&imask, &fmask);
+ imask = cfun->machine->sa_mask & 0xffffffffu;
+ fmask = cfun->machine->sa_mask >> 32;
/* Issue function start and label. */
if (TARGET_ABI_OPEN_VMS || !flag_inhibit_size_directive)
@@ -8113,7 +8022,7 @@ alpha_start_function (FILE *file, const char *fnname,
fprintf (file, "\t.frame $%d," HOST_WIDE_INT_PRINT_DEC ",$26,"
HOST_WIDE_INT_PRINT_DEC "\n",
vms_unwind_regno,
- frame_size >= (1UL << 31) ? 0 : frame_size,
+ frame_size >= max_frame_size ? 0 : frame_size,
reg_offset);
else if (!flag_inhibit_size_directive)
fprintf (file, "\t.frame $%d," HOST_WIDE_INT_PRINT_DEC ",$26,%d\n",
@@ -8193,12 +8102,11 @@ void
alpha_expand_epilogue (void)
{
/* Registers to save. */
- unsigned long imask = 0;
- unsigned long fmask = 0;
+ unsigned HOST_WIDE_INT sa_mask = cfun->machine->sa_mask;
/* Stack space needed for pushing registers clobbered by us. */
- HOST_WIDE_INT sa_size;
+ HOST_WIDE_INT sa_size = cfun->machine->sa_size;
/* Complete stack size needed. */
- HOST_WIDE_INT frame_size;
+ HOST_WIDE_INT frame_size = cfun->machine->frame_size;
/* Offset from base reg to register save area. */
HOST_WIDE_INT reg_offset;
int fp_is_frame_pointer, fp_offset;
@@ -8206,10 +8114,6 @@ alpha_expand_epilogue (void)
rtx sp_adj1, sp_adj2, mem, reg, insn;
rtx eh_ofs;
rtx cfa_restores = NULL_RTX;
- int i;
-
- sa_size = alpha_sa_size ();
- frame_size = compute_frame_size (get_frame_size (), sa_size);
if (TARGET_ABI_OPEN_VMS)
{
@@ -8221,8 +8125,6 @@ alpha_expand_epilogue (void)
else
reg_offset = ALPHA_ROUND (crtl->outgoing_args_size);
- alpha_sa_mask (&imask, &fmask);
-
fp_is_frame_pointer
= (TARGET_ABI_OPEN_VMS
? alpha_procedure_type == PT_STACK
@@ -8261,43 +8163,23 @@ alpha_expand_epilogue (void)
}
/* Restore registers in order, excepting a true frame pointer. */
-
- mem = gen_frame_mem (DImode, plus_constant (Pmode, sa_reg, reg_offset));
- reg = gen_rtx_REG (DImode, REG_RA);
- emit_move_insn (reg, mem);
- cfa_restores = alloc_reg_note (REG_CFA_RESTORE, reg, cfa_restores);
-
- reg_offset += 8;
- imask &= ~(1UL << REG_RA);
-
- for (i = 0; i < 31; ++i)
- if (imask & (1UL << i))
- {
- if (i == HARD_FRAME_POINTER_REGNUM && fp_is_frame_pointer)
- fp_offset = reg_offset;
- else
- {
- mem = gen_frame_mem (DImode,
- plus_constant (Pmode, sa_reg,
- reg_offset));
- reg = gen_rtx_REG (DImode, i);
- emit_move_insn (reg, mem);
- cfa_restores = alloc_reg_note (REG_CFA_RESTORE, reg,
- cfa_restores);
- }
- reg_offset += 8;
- }
-
- for (i = 0; i < 31; ++i)
- if (fmask & (1UL << i))
- {
- mem = gen_frame_mem (DFmode, plus_constant (Pmode, sa_reg,
- reg_offset));
- reg = gen_rtx_REG (DFmode, i+32);
- emit_move_insn (reg, mem);
- cfa_restores = alloc_reg_note (REG_CFA_RESTORE, reg, cfa_restores);
- reg_offset += 8;
- }
+ for (unsigned i = REG_RA; sa_mask != 0; i = ctz_hwi(sa_mask))
+ {
+ if (i == HARD_FRAME_POINTER_REGNUM && fp_is_frame_pointer)
+ fp_offset = reg_offset;
+ else
+ {
+ mem = gen_frame_mem (DImode,
+ plus_constant (Pmode, sa_reg,
+ reg_offset));
+ reg = gen_rtx_REG (DImode, i);
+ emit_move_insn (reg, mem);
+ cfa_restores = alloc_reg_note (REG_CFA_RESTORE, reg,
+ cfa_restores);
+ }
+ reg_offset += 8;
+ sa_mask &= ~(HOST_WIDE_INT_1U << i);
+ }
}
if (frame_size || eh_ofs)
@@ -8437,6 +8319,7 @@ alpha_output_mi_thunk_osf (FILE *file, tree thunk_fndecl ATTRIBUTE_UNUSED,
HOST_WIDE_INT delta, HOST_WIDE_INT vcall_offset,
tree function)
{
+ const char *fnname = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (thunk_fndecl));
HOST_WIDE_INT hi, lo;
rtx this_rtx, funexp;
rtx_insn *insn;
@@ -8513,13 +8396,14 @@ alpha_output_mi_thunk_osf (FILE *file, tree thunk_fndecl ATTRIBUTE_UNUSED,
/* Run just enough of rest_of_compilation to get the insns emitted.
There's not really enough bulk here to make other passes such as
- instruction scheduling worth while. Note that use_thunk calls
- assemble_start_function and assemble_end_function. */
+ instruction scheduling worth while. */
insn = get_insns ();
shorten_branches (insn);
+ assemble_start_function (thunk_fndecl, fnname);
final_start_function (insn, file, 1);
final (insn, file, 1);
final_end_function ();
+ assemble_end_function (thunk_fndecl, fnname);
}
#endif /* TARGET_ABI_OSF */
diff --git a/gcc/config/alpha/alpha.h b/gcc/config/alpha/alpha.h
index e200820..68eafe1 100644
--- a/gcc/config/alpha/alpha.h
+++ b/gcc/config/alpha/alpha.h
@@ -759,7 +759,7 @@ do { \
#define MOVE_MAX 8
/* If a memory-to-memory move would take MOVE_RATIO or more simple
- move-instruction pairs, we will do a movmem or libcall instead.
+ move-instruction pairs, we will do a cpymem or libcall instead.
Without byte/word accesses, we want no more than four instructions;
with, several single byte accesses are better. */
diff --git a/gcc/config/alpha/alpha.md b/gcc/config/alpha/alpha.md
index dd340a0..b195eb9 100644
--- a/gcc/config/alpha/alpha.md
+++ b/gcc/config/alpha/alpha.md
@@ -4232,7 +4232,7 @@
;; be the same temporary, if desired. If the address is in a register,
;; operand 2 can be that register.
-(define_expand "unaligned_store<mode>"
+(define_expand "@unaligned_store<mode>"
[(set (match_operand:DI 3 "register_operand")
(mem:DI (and:DI (match_operand:DI 0 "address_operand")
(const_int -8))))
@@ -4417,7 +4417,7 @@
;; always get a proper address for a stack slot during reload_foo
;; expansion, so we must delay our address manipulations until after.
-(define_insn_and_split "reload_in<mode>_aligned"
+(define_insn_and_split "@reload_in<mode>_aligned"
[(set (match_operand:I12MODE 0 "register_operand" "=r")
(match_operand:I12MODE 1 "memory_operand" "m"))]
"!TARGET_BWX && (reload_in_progress || reload_completed)"
@@ -4673,7 +4673,7 @@
;; Argument 2 is the length
;; Argument 3 is the alignment
-(define_expand "movmemqi"
+(define_expand "cpymemqi"
[(parallel [(set (match_operand:BLK 0 "memory_operand")
(match_operand:BLK 1 "memory_operand"))
(use (match_operand:DI 2 "immediate_operand"))
@@ -4686,7 +4686,7 @@
FAIL;
})
-(define_expand "movmemdi"
+(define_expand "cpymemdi"
[(parallel [(set (match_operand:BLK 0 "memory_operand")
(match_operand:BLK 1 "memory_operand"))
(use (match_operand:DI 2 "immediate_operand"))
@@ -4703,7 +4703,7 @@
"TARGET_ABI_OPEN_VMS"
"operands[4] = gen_rtx_SYMBOL_REF (Pmode, \"OTS$MOVE\");")
-(define_insn "*movmemdi_1"
+(define_insn "*cpymemdi_1"
[(set (match_operand:BLK 0 "memory_operand" "=m,m")
(match_operand:BLK 1 "memory_operand" "m,m"))
(use (match_operand:DI 2 "nonmemory_operand" "r,i"))
diff --git a/gcc/config/alpha/sync.md b/gcc/config/alpha/sync.md
index c416ad4..ef08854 100644
--- a/gcc/config/alpha/sync.md
+++ b/gcc/config/alpha/sync.md
@@ -43,7 +43,7 @@
"mb"
[(set_attr "type" "mb")])
-(define_insn "load_locked_<mode>"
+(define_insn "@load_locked_<mode>"
[(set (match_operand:I48MODE 0 "register_operand" "=r")
(unspec_volatile:I48MODE
[(match_operand:I48MODE 1 "memory_operand" "m")]
@@ -52,7 +52,7 @@
"ld<modesuffix>_l %0,%1"
[(set_attr "type" "ld_l")])
-(define_insn "store_conditional_<mode>"
+(define_insn "@store_conditional_<mode>"
[(set (match_operand:DI 0 "register_operand" "=r")
(unspec_volatile:DI [(const_int 0)] UNSPECV_SC))
(set (match_operand:I48MODE 1 "memory_operand" "=m")
@@ -132,7 +132,7 @@
DONE;
})
-(define_insn_and_split "atomic_compare_and_swap<mode>_1"
+(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
@@ -189,7 +189,7 @@
DONE;
})
-(define_insn_and_split "atomic_exchange<mode>_1"
+(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
diff --git a/gcc/config/arc/arc-protos.h b/gcc/config/arc/arc-protos.h
index ac0de6b..74e5247 100644
--- a/gcc/config/arc/arc-protos.h
+++ b/gcc/config/arc/arc-protos.h
@@ -35,7 +35,7 @@ extern void arc_final_prescan_insn (rtx_insn *, rtx *, int);
extern const char *arc_output_libcall (const char *);
extern int arc_output_addsi (rtx *operands, bool, bool);
extern int arc_output_commutative_cond_exec (rtx *operands, bool);
-extern bool arc_expand_movmem (rtx *operands);
+extern bool arc_expand_cpymem (rtx *operands);
extern bool prepare_move_operands (rtx *operands, machine_mode mode);
extern void emit_shift (enum rtx_code, rtx, rtx, rtx);
extern void arc_expand_atomic_op (enum rtx_code, rtx, rtx, rtx, rtx, rtx);
@@ -48,6 +48,10 @@ extern bool arc_is_uncached_mem_p (rtx);
extern bool gen_operands_ldd_std (rtx *operands, bool load, bool commute);
extern bool arc_check_multi (rtx, bool);
extern void arc_adjust_reg_alloc_order (void);
+extern bool arc_check_ior_const (HOST_WIDE_INT );
+extern void arc_split_ior (rtx *);
+extern bool arc_check_mov_const (HOST_WIDE_INT );
+extern bool arc_split_mov_const (rtx *);
#endif /* RTX_CODE */
extern unsigned int arc_compute_frame_size (int);
diff --git a/gcc/config/arc/arc.c b/gcc/config/arc/arc.c
index 2f5753b..5decf91 100644
--- a/gcc/config/arc/arc.c
+++ b/gcc/config/arc/arc.c
@@ -480,7 +480,7 @@ arc_preferred_simd_mode (scalar_mode mode)
TARGET_VECTORIZE_AUTOVECTORIZE_VECTOR_SIZES. */
static void
-arc_autovectorize_vector_sizes (vector_sizes *sizes)
+arc_autovectorize_vector_sizes (vector_sizes *sizes, bool)
{
if (TARGET_PLUS_QMACW)
{
@@ -689,8 +689,6 @@ static rtx arc_legitimize_address_0 (rtx, rtx, machine_mode mode);
#undef TARGET_MODES_TIEABLE_P
#define TARGET_MODES_TIEABLE_P arc_modes_tieable_p
-#undef TARGET_BUILTIN_SETJMP_FRAME_VALUE
-#define TARGET_BUILTIN_SETJMP_FRAME_VALUE arc_builtin_setjmp_frame_value
/* Try to keep the (mov:DF _, reg) as early as possible so
that the d<add/sub/mul>h-lr insns appear together and can
@@ -4223,7 +4221,7 @@ arc_print_operand (FILE *file, rtx x, int code)
case 'z':
if (GET_CODE (x) == CONST_INT)
- fprintf (file, "%d",exact_log2(INTVAL (x)) );
+ fprintf (file, "%d",exact_log2 (INTVAL (x) & 0xffffffff));
else
output_operand_lossage ("invalid operand to %%z code");
@@ -5560,43 +5558,38 @@ arc_rtx_costs (rtx x, machine_mode mode, int outer_code,
case CONST_INT:
{
bool nolimm = false; /* Can we do without long immediate? */
- bool fast = false; /* Is the result available immediately? */
- bool condexec = false; /* Does this allow conditiobnal execution? */
- bool compact = false; /* Is a 16 bit opcode available? */
- /* CONDEXEC also implies that we can have an unconditional
- 3-address operation. */
- nolimm = compact = condexec = false;
+ nolimm = false;
if (UNSIGNED_INT6 (INTVAL (x)))
- nolimm = condexec = compact = true;
+ nolimm = true;
else
{
- if (SMALL_INT (INTVAL (x)))
- nolimm = fast = true;
switch (outer_code)
{
case AND: /* bclr, bmsk, ext[bw] */
if (satisfies_constraint_Ccp (x) /* bclr */
|| satisfies_constraint_C1p (x) /* bmsk */)
- nolimm = fast = condexec = compact = true;
+ nolimm = true;
break;
case IOR: /* bset */
if (satisfies_constraint_C0p (x)) /* bset */
- nolimm = fast = condexec = compact = true;
+ nolimm = true;
break;
case XOR:
if (satisfies_constraint_C0p (x)) /* bxor */
- nolimm = fast = condexec = true;
+ nolimm = true;
break;
case SET:
- if (satisfies_constraint_Crr (x)) /* ror b,u6 */
+ if (UNSIGNED_INT8 (INTVAL (x)))
+ nolimm = true;
+ if (satisfies_constraint_Chi (x))
+ nolimm = true;
+ if (satisfies_constraint_Clo (x))
nolimm = true;
default:
break;
}
}
- /* FIXME: Add target options to attach a small cost if
- condexec / compact is not true. */
if (nolimm)
{
*total = 0;
@@ -5610,7 +5603,7 @@ arc_rtx_costs (rtx x, machine_mode mode, int outer_code,
case CONST:
case LABEL_REF:
case SYMBOL_REF:
- *total = COSTS_N_INSNS (1);
+ *total = speed ? COSTS_N_INSNS (1) : COSTS_N_INSNS (4);
return true;
case CONST_DOUBLE:
@@ -5636,16 +5629,10 @@ arc_rtx_costs (rtx x, machine_mode mode, int outer_code,
case LSHIFTRT:
if (TARGET_BARREL_SHIFTER)
{
- /* If we want to shift a constant, we need a LIMM. */
- /* ??? when the optimizers want to know if a constant should be
- hoisted, they ask for the cost of the constant. OUTER_CODE is
- insufficient context for shifts since we don't know which operand
- we are looking at. */
if (CONSTANT_P (XEXP (x, 0)))
{
- *total += (COSTS_N_INSNS (2)
- + rtx_cost (XEXP (x, 1), mode, (enum rtx_code) code,
- 0, speed));
+ *total += rtx_cost (XEXP (x, 1), mode, (enum rtx_code) code,
+ 0, speed);
return true;
}
*total = COSTS_N_INSNS (1);
@@ -5665,7 +5652,13 @@ arc_rtx_costs (rtx x, machine_mode mode, int outer_code,
case DIV:
case UDIV:
- if (speed)
+ if (GET_MODE_CLASS (mode) == MODE_FLOAT
+ && (TARGET_FP_SP_SQRT || TARGET_FP_DP_SQRT))
+ *total = COSTS_N_INSNS(1);
+ else if (GET_MODE_CLASS (mode) == MODE_INT
+ && TARGET_DIVREM)
+ *total = COSTS_N_INSNS(1);
+ else if (speed)
*total = COSTS_N_INSNS(30);
else
*total = COSTS_N_INSNS(1);
@@ -5678,19 +5671,28 @@ arc_rtx_costs (rtx x, machine_mode mode, int outer_code,
*total= arc_multcost;
/* We do not want synth_mult sequences when optimizing
for size. */
- else if (TARGET_MUL64_SET || TARGET_ARC700_MPY)
+ else if (TARGET_ANY_MPY)
*total = COSTS_N_INSNS (1);
else
*total = COSTS_N_INSNS (2);
return false;
+
case PLUS:
+ if (outer_code == MEM && CONST_INT_P (XEXP (x, 1))
+ && RTX_OK_FOR_OFFSET_P (mode, XEXP (x, 1)))
+ {
+ *total = 0;
+ return true;
+ }
+
if ((GET_CODE (XEXP (x, 0)) == ASHIFT
&& _1_2_3_operand (XEXP (XEXP (x, 0), 1), VOIDmode))
|| (GET_CODE (XEXP (x, 0)) == MULT
&& _2_4_8_operand (XEXP (XEXP (x, 0), 1), VOIDmode)))
{
- *total += (rtx_cost (XEXP (x, 1), mode, PLUS, 0, speed)
- + rtx_cost (XEXP (XEXP (x, 0), 0), mode, PLUS, 1, speed));
+ if (CONSTANT_P (XEXP (x, 1)) && !speed)
+ *total += COSTS_N_INSNS (4);
+ *total += rtx_cost (XEXP (XEXP (x, 0), 0), mode, PLUS, 1, speed);
return true;
}
return false;
@@ -5700,11 +5702,13 @@ arc_rtx_costs (rtx x, machine_mode mode, int outer_code,
|| (GET_CODE (XEXP (x, 1)) == MULT
&& _2_4_8_operand (XEXP (XEXP (x, 1), 1), VOIDmode)))
{
- *total += (rtx_cost (XEXP (x, 0), mode, PLUS, 0, speed)
- + rtx_cost (XEXP (XEXP (x, 1), 0), mode, PLUS, 1, speed));
+ if (CONSTANT_P (XEXP (x, 0)) && !speed)
+ *total += COSTS_N_INSNS (4);
+ *total += rtx_cost (XEXP (XEXP (x, 1), 0), mode, PLUS, 1, speed);
return true;
}
return false;
+
case COMPARE:
{
rtx op0 = XEXP (x, 0);
@@ -5971,130 +5975,47 @@ arc_legitimize_tls_address (rtx addr, enum tls_model model)
}
}
-/* Legitimize a pic address reference in ORIG.
- The return value is the legitimated address.
- If OLDX is non-zero, it is the target to assign the address to first. */
+/* Return true if SYMBOL_REF X binds locally. */
-static rtx
-arc_legitimize_pic_address (rtx orig, rtx oldx)
+static bool
+arc_symbol_binds_local_p (const_rtx x)
{
- rtx addr = orig;
- rtx pat = orig;
- rtx base;
+ return (SYMBOL_REF_DECL (x)
+ ? targetm.binds_local_p (SYMBOL_REF_DECL (x))
+ : SYMBOL_REF_LOCAL_P (x));
+}
- if (oldx == orig)
- oldx = NULL;
+/* Legitimize a pic address reference in ADDR. The return value is
+ the legitimated address. */
- if (GET_CODE (addr) == LABEL_REF)
- ; /* Do nothing. */
- else if (GET_CODE (addr) == SYMBOL_REF)
+static rtx
+arc_legitimize_pic_address (rtx addr)
+{
+ if (!flag_pic)
+ return addr;
+
+ switch (GET_CODE (addr))
{
- enum tls_model model = SYMBOL_REF_TLS_MODEL (addr);
- if (model != 0)
- return arc_legitimize_tls_address (addr, model);
- else if (!flag_pic)
- return orig;
- else if (CONSTANT_POOL_ADDRESS_P (addr) || SYMBOL_REF_LOCAL_P (addr))
- return arc_unspec_offset (addr, ARC_UNSPEC_GOTOFFPC);
+ case SYMBOL_REF:
+ /* TLS symbols are handled in different place. */
+ if (SYMBOL_REF_TLS_MODEL (addr))
+ return addr;
/* This symbol must be referenced via a load from the Global
Offset Table (@GOTPC). */
- pat = arc_unspec_offset (addr, ARC_UNSPEC_GOT);
- pat = gen_const_mem (Pmode, pat);
-
- if (oldx == NULL)
- oldx = gen_reg_rtx (Pmode);
+ if (!arc_symbol_binds_local_p (addr))
+ return gen_const_mem (Pmode, arc_unspec_offset (addr, ARC_UNSPEC_GOT));
- emit_move_insn (oldx, pat);
- pat = oldx;
- }
- else
- {
- if (GET_CODE (addr) == CONST)
- {
- addr = XEXP (addr, 0);
- if (GET_CODE (addr) == UNSPEC)
- {
- /* Check that the unspec is one of the ones we generate? */
- return orig;
- }
- /* fwprop is placing in the REG_EQUIV notes constant pic
- unspecs expressions. Then, loop may use these notes for
- optimizations resulting in complex patterns that are not
- supported by the current implementation. The following
- two if-cases are simplifying the complex patters to
- simpler ones. */
- else if (GET_CODE (addr) == MINUS)
- {
- rtx op0 = XEXP (addr, 0);
- rtx op1 = XEXP (addr, 1);
- gcc_assert (oldx);
- gcc_assert (GET_CODE (op1) == UNSPEC);
-
- emit_move_insn (oldx,
- gen_rtx_CONST (SImode,
- arc_legitimize_pic_address (op1,
- NULL_RTX)));
- emit_insn (gen_rtx_SET (oldx, gen_rtx_MINUS (SImode, op0, oldx)));
- return oldx;
-
- }
- else if (GET_CODE (addr) != PLUS)
- {
- rtx tmp = XEXP (addr, 0);
- enum rtx_code code = GET_CODE (addr);
-
- /* It only works for UNARY operations. */
- gcc_assert (UNARY_P (addr));
- gcc_assert (GET_CODE (tmp) == UNSPEC);
- gcc_assert (oldx);
-
- emit_move_insn
- (oldx,
- gen_rtx_CONST (SImode,
- arc_legitimize_pic_address (tmp,
- NULL_RTX)));
-
- emit_insn (gen_rtx_SET (oldx,
- gen_rtx_fmt_ee (code, SImode,
- oldx, const0_rtx)));
-
- return oldx;
- }
- else
- {
- gcc_assert (GET_CODE (addr) == PLUS);
- if (GET_CODE (XEXP (addr, 0)) == UNSPEC)
- return orig;
- }
- }
-
- if (GET_CODE (addr) == PLUS)
- {
- rtx op0 = XEXP (addr, 0), op1 = XEXP (addr, 1);
-
- base = arc_legitimize_pic_address (op0, oldx);
- pat = arc_legitimize_pic_address (op1,
- base == oldx ? NULL_RTX : oldx);
-
- if (base == op0 && pat == op1)
- return orig;
+ /* Local symb: use @pcl to access it. */
+ /* Fall through. */
+ case LABEL_REF:
+ return arc_unspec_offset (addr, ARC_UNSPEC_GOTOFFPC);
- if (GET_CODE (pat) == CONST_INT)
- pat = plus_constant (Pmode, base, INTVAL (pat));
- else
- {
- if (GET_CODE (pat) == PLUS && CONSTANT_P (XEXP (pat, 1)))
- {
- base = gen_rtx_PLUS (Pmode, base, XEXP (pat, 0));
- pat = XEXP (pat, 1);
- }
- pat = gen_rtx_PLUS (Pmode, base, pat);
- }
- }
+ default:
+ break;
}
- return pat;
+ return addr;
}
/* Output address constant X to FILE, taking PIC into account. */
@@ -6256,28 +6177,6 @@ arc_output_pic_addr_const (FILE * file, rtx x, int code)
}
}
-#define SYMBOLIC_CONST(X) \
-(GET_CODE (X) == SYMBOL_REF \
- || GET_CODE (X) == LABEL_REF \
- || (GET_CODE (X) == CONST && symbolic_reference_mentioned_p (X)))
-
-/* Emit insns to move operands[1] into operands[0]. */
-
-static void
-prepare_pic_move (rtx *operands, machine_mode)
-{
- if (GET_CODE (operands[0]) == MEM && SYMBOLIC_CONST (operands[1])
- && flag_pic)
- operands[1] = force_reg (Pmode, operands[1]);
- else
- {
- rtx temp = (reload_in_progress ? operands[0]
- : flag_pic? gen_reg_rtx (Pmode) : NULL_RTX);
- operands[1] = arc_legitimize_pic_address (operands[1], temp);
- }
-}
-
-
/* The function returning the number of words, at the beginning of an
argument, must be put in registers. The returned value must be
zero for arguments that are passed entirely in registers or that
@@ -7314,6 +7213,7 @@ arc_output_mi_thunk (FILE *file, tree thunk ATTRIBUTE_UNUSED,
HOST_WIDE_INT vcall_offset,
tree function)
{
+ const char *fnname = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (thunk));
int mi_delta = delta;
const char *const mi_op = mi_delta < 0 ? "sub" : "add";
int shift = 0;
@@ -7321,6 +7221,8 @@ arc_output_mi_thunk (FILE *file, tree thunk ATTRIBUTE_UNUSED,
= aggregate_value_p (TREE_TYPE (TREE_TYPE (function)), function) ? 1 : 0;
rtx fnaddr;
+ assemble_start_function (thunk, fnname);
+
if (mi_delta < 0)
mi_delta = - mi_delta;
@@ -7384,6 +7286,7 @@ arc_output_mi_thunk (FILE *file, tree thunk ATTRIBUTE_UNUSED,
fputs ("@plt\n", file);
}
fputc ('\n', file);
+ assemble_end_function (thunk, fnname);
}
/* Return true if a 32 bit "long_call" should be generated for
@@ -8875,7 +8778,7 @@ arc_output_commutative_cond_exec (rtx *operands, bool output_p)
return 8;
}
-/* Helper function of arc_expand_movmem. ADDR points to a chunk of memory.
+/* Helper function of arc_expand_cpymem. ADDR points to a chunk of memory.
Emit code and return an potentially modified address such that offsets
up to SIZE are can be added to yield a legitimate address.
if REUSE is set, ADDR is a register that may be modified. */
@@ -8909,7 +8812,7 @@ force_offsettable (rtx addr, HOST_WIDE_INT size, bool reuse)
offset ranges. Return true on success. */
bool
-arc_expand_movmem (rtx *operands)
+arc_expand_cpymem (rtx *operands)
{
rtx dst = operands[0];
rtx src = operands[1];
@@ -9053,54 +8956,37 @@ prepare_move_operands (rtx *operands, machine_mode mode)
}
}
- if (mode == SImode && SYMBOLIC_CONST (operands[1]))
+ if (GET_CODE (operands[1]) == SYMBOL_REF)
{
- prepare_pic_move (operands, SImode);
-
- /* Disable any REG_EQUALs associated with the symref
- otherwise the optimization pass undoes the work done
- here and references the variable directly. */
+ enum tls_model model = SYMBOL_REF_TLS_MODEL (operands[1]);
+ if (MEM_P (operands[0]) && flag_pic)
+ operands[1] = force_reg (mode, operands[1]);
+ else if (model)
+ operands[1] = arc_legitimize_tls_address (operands[1], model);
}
+ operands[1] = arc_legitimize_pic_address (operands[1]);
+
+ /* Store instructions are limited, they only accept as address an
+ immediate, a register or a register plus a small immediate. */
if (MEM_P (operands[0])
- && !(reload_in_progress || reload_completed))
+ && !move_dest_operand (operands[0], mode))
{
- operands[1] = force_reg (mode, operands[1]);
- if (!move_dest_operand (operands[0], mode))
- {
- rtx addr = copy_to_mode_reg (Pmode, XEXP (operands[0], 0));
- /* This is like change_address_1 (operands[0], mode, 0, 1) ,
- except that we can't use that function because it is static. */
- rtx pat = change_address (operands[0], mode, addr);
- MEM_COPY_ATTRIBUTES (pat, operands[0]);
- operands[0] = pat;
- }
- if (!cse_not_expected)
- {
- rtx pat = XEXP (operands[0], 0);
-
- pat = arc_legitimize_address_0 (pat, pat, mode);
- if (pat)
- {
- pat = change_address (operands[0], mode, pat);
- MEM_COPY_ATTRIBUTES (pat, operands[0]);
- operands[0] = pat;
- }
- }
+ rtx tmp0 = copy_to_mode_reg (Pmode, XEXP (operands[0], 0));
+ rtx tmp1 = change_address (operands[0], mode, tmp0);
+ MEM_COPY_ATTRIBUTES (tmp1, operands[0]);
+ operands[0] = tmp1;
}
- if (MEM_P (operands[1]) && !cse_not_expected)
- {
- rtx pat = XEXP (operands[1], 0);
-
- pat = arc_legitimize_address_0 (pat, pat, mode);
- if (pat)
- {
- pat = change_address (operands[1], mode, pat);
- MEM_COPY_ATTRIBUTES (pat, operands[1]);
- operands[1] = pat;
- }
- }
+ /* Check if it is constant but it is not legitimized. */
+ if (CONSTANT_P (operands[1])
+ && !arc_legitimate_constant_p (mode, operands[1]))
+ operands[1] = force_reg (mode, XEXP (operands[1], 0));
+ else if (MEM_P (operands[0])
+ && ((CONSTANT_P (operands[1])
+ && !satisfies_constraint_Cm3 (operands[1]))
+ || MEM_P (operands[1])))
+ operands[1] = force_reg (mode, operands[1]);
return false;
}
@@ -9572,11 +9458,10 @@ arc_legitimize_address_0 (rtx x, rtx oldx ATTRIBUTE_UNUSED,
{
rtx addr, inner;
- if (flag_pic && SYMBOLIC_CONST (x))
- (x) = arc_legitimize_pic_address (x, 0);
addr = x;
if (GET_CODE (addr) == CONST)
addr = XEXP (addr, 0);
+
if (GET_CODE (addr) == PLUS
&& CONST_INT_P (XEXP (addr, 1))
&& ((GET_CODE (XEXP (addr, 0)) == SYMBOL_REF
@@ -9607,13 +9492,6 @@ arc_legitimize_address_0 (rtx x, rtx oldx ATTRIBUTE_UNUSED,
static rtx
arc_legitimize_address (rtx orig_x, rtx oldx, machine_mode mode)
{
- if (GET_CODE (orig_x) == SYMBOL_REF)
- {
- enum tls_model model = SYMBOL_REF_TLS_MODEL (orig_x);
- if (model != 0)
- return arc_legitimize_tls_address (orig_x, model);
- }
-
rtx new_x = arc_legitimize_address_0 (orig_x, oldx, mode);
if (new_x)
@@ -10444,7 +10322,7 @@ arc_use_by_pieces_infrastructure_p (unsigned HOST_WIDE_INT size,
enum by_pieces_operation op,
bool speed_p)
{
- /* Let the movmem expander handle small block moves. */
+ /* Let the cpymem expander handle small block moves. */
if (op == MOVE_BY_PIECES)
return false;
@@ -10975,28 +10853,6 @@ compact_memory_operand_p (rtx op, machine_mode mode,
return false;
}
-/* Return the frame pointer value to be backed up in the setjmp buffer. */
-
-static rtx
-arc_builtin_setjmp_frame_value (void)
-{
- /* We always want to preserve whatever value is currently in the frame
- pointer register. For frames that are using the frame pointer the new
- value of the frame pointer register will have already been computed
- (as part of the prologue). For frames that are not using the frame
- pointer it is important that we backup whatever value is in the frame
- pointer register, as earlier (more outer) frames may have placed a
- value into the frame pointer register. It might be tempting to try
- and use `frame_pointer_rtx` here, however, this is not what we want.
- For frames that are using the frame pointer this will give the
- correct value. However, for frames that are not using the frame
- pointer this will still give the value that _would_ have been the
- frame pointer value for this frame (if the use of the frame pointer
- had not been removed). We really do want the raw frame pointer
- register value. */
- return gen_raw_REG (Pmode, HARD_FRAME_POINTER_REGNUM);
-}
-
/* Return nonzero if a jli call should be generated for a call from
the current function to DECL. */
@@ -11444,6 +11300,198 @@ arc_memory_move_cost (machine_mode mode,
return (2 * GET_MODE_SIZE (mode));
}
+/* Split an OR instruction into multiple BSET/OR instructions in a
+ attempt to avoid long immediate constants. The next strategies are
+ employed when destination is 'q' reg.
+
+ 1. if there are up to three bits set in the mask, a succession of
+ three bset instruction will be emitted:
+ OR rA, rB, mask ->
+ BSET(_S) rA,rB,mask1/BSET_S rA,rA,mask2/BSET_S rA,rA,mask3
+
+ 2. if the lower 6 bits of the mask is set and there is only one
+ bit set in the upper remaining bits then we will emit one bset and
+ one OR instruction:
+ OR rA, rB, mask -> OR rA,rB,mask1/BSET_S rA,mask2
+
+ 3. otherwise an OR with limm will be emmitted. */
+
+void
+arc_split_ior (rtx *operands)
+{
+ unsigned HOST_WIDE_INT mask, maskx;
+ rtx op1 = operands[1];
+
+ gcc_assert (CONST_INT_P (operands[2]));
+ mask = INTVAL (operands[2]) & 0xffffffff;
+
+ if (__builtin_popcount (mask) > 3 || (mask & 0x3f))
+ {
+ maskx = mask & 0x3f;
+ emit_insn (gen_rtx_SET (operands[0],
+ gen_rtx_IOR (SImode, op1, GEN_INT (maskx))));
+ op1 = operands[0];
+ mask &= ~maskx;
+ }
+
+ switch (__builtin_popcount (mask))
+ {
+ case 3:
+ maskx = 1 << (__builtin_ffs (mask) - 1);
+ emit_insn (gen_rtx_SET (operands[0],
+ gen_rtx_IOR (SImode, op1, GEN_INT (maskx))));
+ mask &= ~maskx;
+ op1 = operands[0];
+ /* FALLTHRU */
+ case 2:
+ maskx = 1 << (__builtin_ffs (mask) - 1);
+ emit_insn (gen_rtx_SET (operands[0],
+ gen_rtx_IOR (SImode, op1, GEN_INT (maskx))));
+ mask &= ~maskx;
+ op1 = operands[0];
+ /* FALLTHRU */
+ case 1:
+ maskx = 1 << (__builtin_ffs (mask) - 1);
+ emit_insn (gen_rtx_SET (operands[0],
+ gen_rtx_IOR (SImode, op1, GEN_INT (maskx))));
+ break;
+ default:
+ break;
+ }
+}
+
+/* Helper to check C0x constraint. */
+
+bool
+arc_check_ior_const (HOST_WIDE_INT ival)
+{
+ unsigned int mask = (unsigned int) (ival & 0xffffffff);
+ if (__builtin_popcount (mask) <= 3)
+ return true;
+ if (__builtin_popcount (mask & ~0x3f) <= 1)
+ return true;
+ return false;
+}
+
+/* Split a mov with long immediate instruction into smaller, size
+ friendly instructions. */
+
+bool
+arc_split_mov_const (rtx *operands)
+{
+ unsigned HOST_WIDE_INT ival;
+ HOST_WIDE_INT shimm;
+ machine_mode mode = GET_MODE (operands[0]);
+
+ /* Manage a constant. */
+ gcc_assert (CONST_INT_P (operands[1]));
+ ival = INTVAL (operands[1]) & 0xffffffff;
+
+ if (SIGNED_INT12 (ival))
+ return false;
+
+ /* 1. Check if we can just rotate limm by 8 but using ROR8. */
+ if (TARGET_BARREL_SHIFTER && TARGET_V2
+ && ((ival & ~0x3f000000) == 0))
+ {
+ shimm = (ival >> 24) & 0x3f;
+ emit_insn (gen_rtx_SET (operands[0],
+ gen_rtx_ROTATERT (mode, GEN_INT (shimm),
+ GEN_INT (8))));
+ return true;
+ }
+ /* 2. Check if we can just shift by 8 to fit into the u6 of LSL8. */
+ if (TARGET_BARREL_SHIFTER && TARGET_V2
+ && ((ival & ~0x3f00) == 0))
+ {
+ shimm = (ival >> 8) & 0x3f;
+ emit_insn (gen_rtx_SET (operands[0],
+ gen_rtx_ASHIFT (mode, GEN_INT (shimm),
+ GEN_INT (8))));
+ return true;
+ }
+
+ /* 3. Check if we can just shift by 16 to fit into the u6 of LSL16. */
+ if (TARGET_BARREL_SHIFTER && TARGET_V2
+ && ((ival & ~0x3f0000) == 0))
+ {
+ shimm = (ival >> 16) & 0x3f;
+ emit_insn (gen_rtx_SET (operands[0],
+ gen_rtx_ASHIFT (mode, GEN_INT (shimm),
+ GEN_INT (16))));
+ return true;
+ }
+
+ /* 4. Check if we can do something like mov_s h,u8 / asl_s ra,h,#nb. */
+ if (((ival >> (__builtin_ffs (ival) - 1)) & 0xffffff00) == 0
+ && TARGET_BARREL_SHIFTER)
+ {
+ HOST_WIDE_INT shift = __builtin_ffs (ival);
+ shimm = (ival >> (shift - 1)) & 0xff;
+ emit_insn (gen_rtx_SET (operands[0], GEN_INT (shimm)));
+ emit_insn (gen_rtx_SET (operands[0],
+ gen_rtx_ASHIFT (mode, operands[0],
+ GEN_INT (shift - 1))));
+ return true;
+ }
+
+ /* 5. Check if we can just rotate the limm, useful when no barrel
+ shifter is present. */
+ if ((ival & ~0x8000001f) == 0)
+ {
+ shimm = (ival * 2 + 1) & 0x3f;
+ emit_insn (gen_rtx_SET (operands[0],
+ gen_rtx_ROTATERT (mode, GEN_INT (shimm),
+ const1_rtx)));
+ return true;
+ }
+
+ /* 6. Check if we can do something with bmask. */
+ if (IS_POWEROF2_P (ival + 1))
+ {
+ emit_insn (gen_rtx_SET (operands[0], constm1_rtx));
+ emit_insn (gen_rtx_SET (operands[0],
+ gen_rtx_AND (mode, operands[0],
+ GEN_INT (ival))));
+ return true;
+ }
+
+ return false;
+}
+
+/* Helper to check Cax constraint. */
+
+bool
+arc_check_mov_const (HOST_WIDE_INT ival)
+{
+ ival = ival & 0xffffffff;
+
+ if ((ival & ~0x8000001f) == 0)
+ return true;
+
+ if (IS_POWEROF2_P (ival + 1))
+ return true;
+
+ /* The next rules requires a barrel shifter. */
+ if (!TARGET_BARREL_SHIFTER)
+ return false;
+
+ if (((ival >> (__builtin_ffs (ival) - 1)) & 0xffffff00) == 0)
+ return true;
+
+ if ((ival & ~0x3f00) == 0)
+ return true;
+
+ if ((ival & ~0x3f0000) == 0)
+ return true;
+
+ if ((ival & ~0x3f000000) == 0)
+ return true;
+
+ return false;
+}
+
+
#undef TARGET_USE_ANCHORS_FOR_SYMBOL_P
#define TARGET_USE_ANCHORS_FOR_SYMBOL_P arc_use_anchors_for_symbol_p
diff --git a/gcc/config/arc/arc.h b/gcc/config/arc/arc.h
index 80dead9..4a9dd07 100644
--- a/gcc/config/arc/arc.h
+++ b/gcc/config/arc/arc.h
@@ -1423,7 +1423,7 @@ do { \
in one reasonably fast instruction. */
#define MOVE_MAX 4
-/* Undo the effects of the movmem pattern presence on STORE_BY_PIECES_P . */
+/* Undo the effects of the cpymem pattern presence on STORE_BY_PIECES_P . */
#define MOVE_RATIO(SPEED) ((SPEED) ? 15 : 3)
/* Define this to be nonzero if shift instructions ignore all but the
diff --git a/gcc/config/arc/arc.md b/gcc/config/arc/arc.md
index ce1004c..b793e5b 100644
--- a/gcc/config/arc/arc.md
+++ b/gcc/config/arc/arc.md
@@ -671,7 +671,9 @@ core_3, archs4x, archs4xd, archs4xd_slow"
[(set (match_operand:QI 0 "move_dest_operand" "=Rcq,Rcq#q, w,Rcq#q, h, w, w,???w,h, w,Rcq, S,!*x, r,r, Ucm,m,???m, m,Usc")
(match_operand:QI 1 "move_src_operand" " cL, cP,Rcq#q, P,hCm1,cL, I,?Rac,i,?i, T,Rcq,Usd,Ucm,m,?Rac,c,?Rac,Cm3,i"))]
"register_operand (operands[0], QImode)
- || register_operand (operands[1], QImode)"
+ || register_operand (operands[1], QImode)
+ || (satisfies_constraint_Cm3 (operands[1])
+ && memory_operand (operands[0], QImode))"
"@
mov%? %0,%1%&
mov%? %0,%1%&
@@ -713,7 +715,9 @@ core_3, archs4x, archs4xd, archs4xd_slow"
/* Don't use a LIMM that we could load with a single insn - we loose
delay-slot filling opportunities. */
&& !satisfies_constraint_I (operands[1])
- && satisfies_constraint_Usc (operands[0]))"
+ && satisfies_constraint_Usc (operands[0]))
+ || (satisfies_constraint_Cm3 (operands[1])
+ && memory_operand (operands[0], HImode))"
"@
mov%? %0,%1%&
mov%? %0,%1%&
@@ -749,66 +753,63 @@ core_3, archs4x, archs4xd, archs4xd_slow"
; In order to allow the ccfsm machinery to do its work, the leading compact
; alternatives say 'canuse' - there is another alternative that will match
; when the condition codes are used.
-; Rcq won't match if the condition is actually used; to avoid a spurious match
-; via q, q is inactivated as constraint there.
-; Likewise, the length of an alternative that might be shifted to conditional
+; The length of an alternative that might be shifted to conditional
; execution must reflect this, lest out-of-range branches are created.
; the iscompact attribute allows the epilogue expander to know for which
; insns it should lengthen the return insn.
-; N.B. operand 1 of alternative 7 expands into pcl,symbol@gotpc .
-(define_insn "*movsi_insn" ; 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
- [(set (match_operand:SI 0 "move_dest_operand" "=Rcq,Rcq#q, w,Rcq#q, h,wl, w, w, w, w, w,???w, ?w, w,Rcq#q, h, wl,Rcq, S, Us<,RcqRck,!*x, r,!*Rsd,!*Rcd,r,Ucm, Usd,m,???m, m,VUsc")
- (match_operand:SI 1 "move_src_operand" " cL, cP,Rcq#q, P,hCm1,cL, I,Crr,Clo,Chi,Cbi,?Rac,Cpc,Clb, ?Cal,Cal,?Cal,Uts,Rcq,RcqRck, Us>,Usd,Ucm, Usd, Ucd,m, w,!*Rzd,c,?Rac,Cm3, C32"))]
+(define_insn_and_split "*movsi_insn" ; 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
+ [(set (match_operand:SI 0 "move_dest_operand" "=q, q,r,q, h,rl, r, r, r, r, ?r, r, q, h, rl, q, S, Us<,RcqRck,!*x, r,!*Rsd,!*Rcd,r,Ucm, Usd,m, m,VUsc")
+ (match_operand:SI 1 "move_src_operand" "rL,rP,q,P,hCm1,rL, I,Clo,Chi,Cbi,Cpc,Clb,Cax,Cal,Cal,Uts,Rcq,RcqRck, Us>,Usd,Ucm, Usd, Ucd,m, r,!*Rzd,r,Cm3, C32"))]
"register_operand (operands[0], SImode)
|| register_operand (operands[1], SImode)
|| (CONSTANT_P (operands[1])
- /* Don't use a LIMM that we could load with a single insn - we loose
- delay-slot filling opportunities. */
- && !satisfies_constraint_I (operands[1])
+ && (!satisfies_constraint_I (operands[1]) || !optimize_size)
&& satisfies_constraint_Usc (operands[0]))
|| (satisfies_constraint_Cm3 (operands[1])
&& memory_operand (operands[0], SImode))"
"@
- mov%? %0,%1%& ;0
- mov%? %0,%1%& ;1
- mov%? %0,%1%& ;2
- mov%? %0,%1%& ;3
- mov%? %0,%1%& ;4
- mov%? %0,%1 ;5
- mov%? %0,%1 ;6
- ror %0,((%1*2+1) & 0x3f) ;7
- movl.cl %0,%1 ;8
- movh.cl %0,%L1>>16 ;9
- * return INTVAL (operands[1]) & 0xffffff ? \"movbi.cl %0,%1 >> %p1,%p1,8;10\" : \"movbi.cl %0,%L1 >> 24,24,8;10\";
- mov%? %0,%1 ;11
- add %0,%1 ;12
- add %0,pcl,%1@pcl ;13
- mov%? %0,%j1 ;14
- mov%? %0,%j1 ;15
- mov%? %0,%j1 ;16
- ld%? %0,%1 ;17
- st%? %1,%0%& ;18
- * return arc_short_long (insn, \"push%? %1%&\", \"st%U0 %1,%0%&\");
- * return arc_short_long (insn, \"pop%? %0%&\", \"ld%U1 %0,%1%&\");
- ld%? %0,%1%& ;21
- xld%U1 %0,%1 ;22
- ld%? %0,%1%& ;23
- ld%? %0,%1%& ;24
- ld%U1%V1 %0,%1 ;25
- xst%U0 %1,%0 ;26
- st%? %1,%0%& ;27
- st%U0%V0 %1,%0 ;28
- st%U0%V0 %1,%0 ;29
- st%U0%V0 %1,%0 ;30
- st%U0%V0 %1,%0 ;31"
- ; 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
- [(set_attr "type" "move, move, move,move,move, move, move,two_cycle_core,shift,shift,shift, move,binary,binary, move, move, move,load,store,store,load,load, load,load,load, load,store,store,store,store,store,store")
- (set_attr "iscompact" "maybe,maybe,maybe,true,true,false,false, false,false,false,false,false, false, false,maybe_limm,maybe_limm,false,true, true, true,true,true,false,true,true,false,false, true,false,false,false,false")
- ; Use default length for iscompact to allow for COND_EXEC. But set length
- ; of Crr to 4.
- (set_attr "length" "*,*,*,*,*,4,4,4,4,4,4,4,8,8,*,*,*,*,*,*,*,*,4,*,4,*,*,*,*,*,*,8")
- (set_attr "predicable" "yes,no,yes,no,no,yes,no,no,no,no,no,yes,no,no,yes,yes,yes,no,no,no,no,no,no,no,no,no,no,no,no,no,no,no")
- (set_attr "cpu_facility" "av1,av1,av1,av2,av2,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,av2,av2,*,*,av2,*,*,av2,*")])
+ mov%?\\t%0,%1 ;0
+ mov%?\\t%0,%1 ;1
+ mov%?\\t%0,%1 ;2
+ mov%?\\t%0,%1 ;3
+ mov%?\\t%0,%1 ;4
+ mov%?\\t%0,%1 ;5
+ mov%?\\t%0,%1 ;6
+ movl.cl\\t %0,%1 ;7
+ movh.cl\\t %0,%L1>>16 ;8
+ * return INTVAL (operands[1]) & 0xffffff ? \"movbi.cl\\t%0,%1 >> %p1,%p1,8;9\" : \"movbi.cl\\t%0,%L1 >> 24,24,8;9\";
+ add\\t%0,%1 ;10
+ add\\t%0,pcl,%1@pcl ;11
+ #
+ mov%?\\t%0,%j1 ;13
+ mov%?\\t%0,%j1 ;14
+ ld%?\\t%0,%1 ;15
+ st%?\\t %1,%0 ;16
+ * return arc_short_long (insn, \"push%?\\t%1%&\", \"st%U0\\t%1,%0%&\");
+ * return arc_short_long (insn, \"pop%?\\t%0%&\", \"ld%U1\\t%0,%1%&\");
+ ld%?\\t%0,%1 ;19
+ xld%U1\\t%0,%1 ;20
+ ld%?\\t%0,%1 ;21
+ ld%?\\t%0,%1 ;22
+ ld%U1%V1\\t%0,%1 ;23
+ xst%U0\\t%1,%0 ;24
+ st%?\\t%1,%0%& ;25
+ st%U0%V0\\t%1,%0 ;26
+ st%U0%V0\\t%1,%0 ;37
+ st%U0%V0\\t%1,%0 ;28"
+ "reload_completed && satisfies_constraint_Cax (operands[1])
+ && register_operand (operands[0], SImode)"
+ [(const_int 0)]
+ "
+ arc_split_mov_const (operands);
+ DONE;
+ "
+ ; 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
+ [(set_attr "type" "move, move, move,move,move, move, move,shift,shift,shift,binary,binary,multi,move, move,load,store,store,load,load, load,load,load, load,store,store,store,store,store")
+ (set_attr "iscompact" "maybe,maybe,maybe,true,true,false,false,false,false,false, false, false,false,true,false,true, true, true,true,true,false,true,true,false,false, true,false,false,false")
+ (set_attr "length" "*,*,*,*,*,4,4,4,4,4,8,8,*,6,*,*,*,*,*,*,4,*,4,*,*,*,*,*,8")
+ (set_attr "predicable" "yes,no,yes,no,no,yes,no,no,no,yes,no,no,no,yes,yes,no,no,no,no,no,no,no,no,no,no,no,no,no,no")
+ (set_attr "cpu_facility" "av1,av1,av1,av2,av2,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,av2,av2,*,*,av2,*,av2,*")])
;; Sometimes generated by the epilogue code. We don't want to
;; recognize these addresses in general, because the limm is costly,
@@ -2303,16 +2304,23 @@ core_3, archs4x, archs4xd, archs4xd_slow"
; ARCv2 has no penalties between mpy and mpyu. So, we use mpy because of its
; short variant. LP_COUNT constraints are still valid.
(define_insn "mulsi3_v2"
- [(set (match_operand:SI 0 "mpy_dest_reg_operand" "=Rcqq,Rcr, r,r,Rcr, r")
- (mult:SI (match_operand:SI 1 "register_operand" "%0, 0, c,0, 0, c")
- (match_operand:SI 2 "nonmemory_operand" " Rcqq, cL,cL,I,Cal,Cal")))]
+ [(set (match_operand:SI 0 "mpy_dest_reg_operand" "=q,q, r, r,r, r, r")
+ (mult:SI (match_operand:SI 1 "register_operand" "%0,q, 0, r,0, 0, c")
+ (match_operand:SI 2 "nonmemory_operand" "q,0,rL,rL,I,Cal,Cal")))]
"TARGET_MULTI"
- "mpy%? %0,%1,%2"
- [(set_attr "length" "*,4,4,4,8,8")
- (set_attr "iscompact" "maybe,false,false,false,false,false")
+ "@
+ mpy%?\\t%0,%1,%2
+ mpy%?\\t%0,%2,%1
+ mpy%?\\t%0,%1,%2
+ mpy%?\\t%0,%1,%2
+ mpy%?\\t%0,%1,%2
+ mpy%?\\t%0,%1,%2
+ mpy%?\\t%0,%1,%2"
+ [(set_attr "length" "*,*,4,4,4,8,8")
+ (set_attr "iscompact" "maybe,maybe,false,false,false,false,false")
(set_attr "type" "umulti")
- (set_attr "predicable" "no,yes,no,no,yes,no")
- (set_attr "cond" "nocond,canuse,nocond,canuse_limm,canuse,nocond")])
+ (set_attr "predicable" "no,no,yes,no,no,yes,no")
+ (set_attr "cond" "nocond,nocond,canuse,nocond,canuse_limm,canuse,nocond")])
(define_expand "mulsidi3"
[(set (match_operand:DI 0 "register_operand" "")
@@ -3216,10 +3224,10 @@ core_3, archs4x, archs4xd, archs4xd_slow"
operands[1] = force_reg (SImode, operands[1]);
")
-(define_insn "andsi3_i"
- [(set (match_operand:SI 0 "dest_reg_operand" "=Rcqq,Rcq,Rcqq,Rcqq,Rcqq,Rcw,Rcw, Rcw,Rcw,Rcw,Rcw, w, w, w, w,Rrq,w,Rcw, w,W")
- (and:SI (match_operand:SI 1 "nonimmediate_operand" "%0,Rcq, 0, 0,Rcqq, 0, c, 0, 0, 0, 0, c, c, c, c,Rrq,0, 0, c,o")
- (match_operand:SI 2 "nonmemory_operand" "Rcqq, 0, C1p, Ccp, Cux, cL, 0,C2pC1p,Ccp,CnL, I,Lc,C2pC1p,Ccp,CnL,Cbf,I,Cal,Cal,Cux")))]
+(define_insn "andsi3_i" ;0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
+ [(set (match_operand:SI 0 "dest_reg_operand" "=q,q, q, q, q, r,r, r, r, r,r, r, r, r, r, q,r, r, r, W")
+ (and:SI (match_operand:SI 1 "nonimmediate_operand" "%0,q, 0, 0, q, 0,r, 0, 0, 0,0, r, r, r, r, q,0, 0, r, o")
+ (match_operand:SI 2 "nonmemory_operand" "q,0,C1p,Ccp,Cux,rL,0,C2pC1p,Ccp,CnL,I,rL,C2pC1p,Ccp,CnL,Cbf,I,Cal,Cal,Cux")))]
"(register_operand (operands[1], SImode)
&& nonmemory_operand (operands[2], SImode))
|| (memory_operand (operands[1], SImode)
@@ -3317,27 +3325,35 @@ core_3, archs4x, archs4xd, archs4xd_slow"
(set_attr "predicable" "no,yes,no,yes,no,no,no")
(set_attr "cond" "canuse,canuse,canuse_limm,canuse,nocond,nocond,nocond")])
-(define_insn "iorsi3"
- [(set (match_operand:SI 0 "dest_reg_operand" "=Rcqq,Rcq,Rcqq,Rcw,Rcw,Rcw,Rcw,w, w,w,Rcw, w")
- (ior:SI (match_operand:SI 1 "nonmemory_operand" "% 0,Rcq, 0, 0, c, 0, 0, c, c,0, 0, c")
- (match_operand:SI 2 "nonmemory_operand" "Rcqq, 0, C0p, cL, 0,C0p, I,cL,C0p,I,Cal,Cal")))]
+(define_insn_and_split "iorsi3"
+ [(set (match_operand:SI 0 "dest_reg_operand" "=q,q, q, r,r, r,r, r, r,r, q, r, r")
+ (ior:SI (match_operand:SI 1 "register_operand" "%0,q, 0, 0,r, 0,0, r, r,0, r, 0, r")
+ (match_operand:SI 2 "nonmemory_operand" "q,0,C0p,rL,0,C0p,I,rL,C0p,I,C0x,Cal,Cal")))]
""
- "*
- switch (which_alternative)
- {
- case 0: case 3: case 6: case 7: case 9: case 10: case 11:
- return \"or%? %0,%1,%2%&\";
- case 1: case 4:
- return \"or%? %0,%2,%1%&\";
- case 2: case 5: case 8:
- return \"bset%? %0,%1,%z2%&\";
- default:
- gcc_unreachable ();
- }"
- [(set_attr "iscompact" "maybe,maybe,maybe,false,false,false,false,false,false,false,false,false")
- (set_attr "length" "*,*,*,4,4,4,4,4,4,4,8,8")
- (set_attr "predicable" "no,no,no,yes,yes,yes,no,no,no,no,yes,no")
- (set_attr "cond" "canuse,canuse,canuse,canuse,canuse,canuse,canuse_limm,nocond,nocond,canuse_limm,canuse,nocond")])
+ "@
+ or%?\\t%0,%1,%2
+ or%?\\t%0,%2,%1
+ bset%?\\t%0,%1,%z2
+ or%?\\t%0,%1,%2
+ or%?\\t%0,%2,%1
+ bset%?\\t%0,%1,%z2
+ or%?\\t%0,%1,%2
+ or%?\\t%0,%1,%2
+ bset%?\\t%0,%1,%z2
+ or%?\\t%0,%1,%2
+ #
+ or%?\\t%0,%1,%2
+ or%?\\t%0,%1,%2"
+ "reload_completed && satisfies_constraint_C0x (operands[2])"
+ [(const_int 0)]
+ "
+ arc_split_ior (operands);
+ DONE;
+ "
+ [(set_attr "iscompact" "maybe,maybe,maybe,false,false,false,false,false,false,false,false,false,false")
+ (set_attr "length" "*,*,*,4,4,4,4,4,4,4,*,8,8")
+ (set_attr "predicable" "no,no,no,yes,yes,yes,no,no,no,no,no,yes,no")
+ (set_attr "cond" "canuse,canuse,canuse,canuse,canuse,canuse,canuse_limm,nocond,nocond,canuse_limm,nocond,canuse,nocond")])
(define_insn "xorsi3"
[(set (match_operand:SI 0 "dest_reg_operand" "=Rcqq,Rcq,Rcw,Rcw,Rcw,Rcw, w, w,w, w, w")
@@ -5110,13 +5126,13 @@ core_3, archs4x, archs4xd, archs4xd_slow"
(set_attr "type" "loop_end")
(set_attr "length" "4,20")])
-(define_expand "movmemsi"
+(define_expand "cpymemsi"
[(match_operand:BLK 0 "" "")
(match_operand:BLK 1 "" "")
(match_operand:SI 2 "nonmemory_operand" "")
(match_operand 3 "immediate_operand" "")]
""
- "if (arc_expand_movmem (operands)) DONE; else FAIL;")
+ "if (arc_expand_cpymem (operands)) DONE; else FAIL;")
;; Close http://gcc.gnu.org/bugzilla/show_bug.cgi?id=35803 if this works
;; to the point that we can generate cmove instructions.
@@ -5972,11 +5988,21 @@ core_3, archs4x, archs4xd, archs4xd_slow"
(match_dup 1)])
(define_insn "*rotrsi3_cnt1"
- [(set (match_operand:SI 0 "dest_reg_operand" "=w")
- (rotatert:SI (match_operand:SI 1 "register_operand" "c")
+ [(set (match_operand:SI 0 "dest_reg_operand" "=r")
+ (rotatert:SI (match_operand:SI 1 "nonmemory_operand" "rL")
(const_int 1)))]
""
- "ror %0,%1%&"
+ "ror\\t%0,%1"
+ [(set_attr "type" "shift")
+ (set_attr "predicable" "no")
+ (set_attr "length" "4")])
+
+(define_insn "*rotrsi3_cnt8"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (rotatert:SI (match_operand:SI 1 "nonmemory_operand" "rL")
+ (const_int 8)))]
+ "TARGET_BARREL_SHIFTER && TARGET_V2"
+ "ror8\\t%0,%1"
[(set_attr "type" "shift")
(set_attr "predicable" "no")
(set_attr "length" "4")])
@@ -5989,8 +6015,31 @@ core_3, archs4x, archs4xd, archs4xd_slow"
"asl%? %0,%1%&"
[(set_attr "type" "shift")
(set_attr "iscompact" "maybe,false")
+ (set_attr "length" "4")
(set_attr "predicable" "no,no")])
+(define_insn "*ashlsi2_cnt8"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (ashift:SI (match_operand:SI 1 "nonmemory_operand" "rL")
+ (const_int 8)))]
+ "TARGET_BARREL_SHIFTER && TARGET_V2"
+ "lsl8\\t%0,%1"
+ [(set_attr "type" "shift")
+ (set_attr "iscompact" "false")
+ (set_attr "length" "4")
+ (set_attr "predicable" "no")])
+
+(define_insn "*ashlsi2_cnt16"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (ashift:SI (match_operand:SI 1 "nonmemory_operand" "rL")
+ (const_int 16)))]
+ "TARGET_BARREL_SHIFTER && TARGET_V2"
+ "lsl16\\t%0,%1"
+ [(set_attr "type" "shift")
+ (set_attr "iscompact" "false")
+ (set_attr "length" "4")
+ (set_attr "predicable" "no")])
+
(define_insn "*lshrsi3_cnt1"
[(set (match_operand:SI 0 "dest_reg_operand" "=Rcqq,w")
(lshiftrt:SI (match_operand:SI 1 "register_operand" "Rcqq,c")
diff --git a/gcc/config/arc/constraints.md b/gcc/config/arc/constraints.md
index 494e479..bbb0b96 100644
--- a/gcc/config/arc/constraints.md
+++ b/gcc/config/arc/constraints.md
@@ -201,7 +201,7 @@
"@internal
power of two"
(and (match_code "const_int")
- (match_test "IS_POWEROF2_P (ival)")))
+ (match_test "IS_POWEROF2_P (ival & 0xffffffff)")))
(define_constraint "C1p"
"@internal
@@ -275,12 +275,6 @@
(and (match_code "const_int")
(match_test "ival == 1 || ival == 2 || ival == 4 || ival == 8")))
-(define_constraint "Crr"
- "@internal
- constant that can be loaded with ror b,u6"
- (and (match_code "const_int")
- (match_test "(ival & ~0x8000001f) == 0 && !arc_ccfsm_cond_exec_p ()")))
-
(define_constraint "Cbi"
"@internal
constant that can be loaded with movbi.cl"
@@ -290,6 +284,20 @@
|| ((ival & 0xffffffffUL) >> exact_log2 (ival & -ival)
<= 0xff)")))
+(define_constraint "C0x"
+ "@internal
+ special const_int pattern used to split ior insns"
+ (and (match_code "const_int")
+ (match_test "optimize_size")
+ (match_test "arc_check_ior_const (ival)")))
+
+(define_constraint "Cax"
+ "@internal
+ special const_int pattern used to split mov insns"
+ (and (match_code "const_int")
+ (match_test "optimize_size")
+ (match_test "arc_check_mov_const (ival)")))
+
;; Floating-point constraints
(define_constraint "G"
diff --git a/gcc/config/arm/arm-fixed.md b/gcc/config/arm/arm-fixed.md
index 6534ed4..fcab40d 100644
--- a/gcc/config/arm/arm-fixed.md
+++ b/gcc/config/arm/arm-fixed.md
@@ -98,9 +98,9 @@
; Note: none of these do any rounding.
(define_expand "mulqq3"
- [(set (match_operand:QQ 0 "s_register_operand" "")
- (mult:QQ (match_operand:QQ 1 "s_register_operand" "")
- (match_operand:QQ 2 "s_register_operand" "")))]
+ [(set (match_operand:QQ 0 "s_register_operand")
+ (mult:QQ (match_operand:QQ 1 "s_register_operand")
+ (match_operand:QQ 2 "s_register_operand")))]
"TARGET_DSP_MULTIPLY && arm_arch_thumb2"
{
rtx tmp1 = gen_reg_rtx (HImode);
@@ -116,9 +116,9 @@
})
(define_expand "mulhq3"
- [(set (match_operand:HQ 0 "s_register_operand" "")
- (mult:HQ (match_operand:HQ 1 "s_register_operand" "")
- (match_operand:HQ 2 "s_register_operand" "")))]
+ [(set (match_operand:HQ 0 "s_register_operand")
+ (mult:HQ (match_operand:HQ 1 "s_register_operand")
+ (match_operand:HQ 2 "s_register_operand")))]
"TARGET_DSP_MULTIPLY && arm_arch_thumb2"
{
rtx tmp = gen_reg_rtx (SImode);
@@ -134,9 +134,9 @@
})
(define_expand "mulsq3"
- [(set (match_operand:SQ 0 "s_register_operand" "")
- (mult:SQ (match_operand:SQ 1 "s_register_operand" "")
- (match_operand:SQ 2 "s_register_operand" "")))]
+ [(set (match_operand:SQ 0 "s_register_operand")
+ (mult:SQ (match_operand:SQ 1 "s_register_operand")
+ (match_operand:SQ 2 "s_register_operand")))]
"TARGET_32BIT"
{
rtx tmp1 = gen_reg_rtx (DImode);
@@ -156,9 +156,9 @@
;; Accumulator multiplies.
(define_expand "mulsa3"
- [(set (match_operand:SA 0 "s_register_operand" "")
- (mult:SA (match_operand:SA 1 "s_register_operand" "")
- (match_operand:SA 2 "s_register_operand" "")))]
+ [(set (match_operand:SA 0 "s_register_operand")
+ (mult:SA (match_operand:SA 1 "s_register_operand")
+ (match_operand:SA 2 "s_register_operand")))]
"TARGET_32BIT"
{
rtx tmp1 = gen_reg_rtx (DImode);
@@ -175,9 +175,9 @@
})
(define_expand "mulusa3"
- [(set (match_operand:USA 0 "s_register_operand" "")
- (mult:USA (match_operand:USA 1 "s_register_operand" "")
- (match_operand:USA 2 "s_register_operand" "")))]
+ [(set (match_operand:USA 0 "s_register_operand")
+ (mult:USA (match_operand:USA 1 "s_register_operand")
+ (match_operand:USA 2 "s_register_operand")))]
"TARGET_32BIT"
{
rtx tmp1 = gen_reg_rtx (DImode);
@@ -317,9 +317,9 @@
(const_int 32)))])
(define_expand "mulha3"
- [(set (match_operand:HA 0 "s_register_operand" "")
- (mult:HA (match_operand:HA 1 "s_register_operand" "")
- (match_operand:HA 2 "s_register_operand" "")))]
+ [(set (match_operand:HA 0 "s_register_operand")
+ (mult:HA (match_operand:HA 1 "s_register_operand")
+ (match_operand:HA 2 "s_register_operand")))]
"TARGET_DSP_MULTIPLY && arm_arch_thumb2"
{
rtx tmp = gen_reg_rtx (SImode);
@@ -333,9 +333,9 @@
})
(define_expand "muluha3"
- [(set (match_operand:UHA 0 "s_register_operand" "")
- (mult:UHA (match_operand:UHA 1 "s_register_operand" "")
- (match_operand:UHA 2 "s_register_operand" "")))]
+ [(set (match_operand:UHA 0 "s_register_operand")
+ (mult:UHA (match_operand:UHA 1 "s_register_operand")
+ (match_operand:UHA 2 "s_register_operand")))]
"TARGET_DSP_MULTIPLY"
{
rtx tmp1 = gen_reg_rtx (SImode);
@@ -353,9 +353,9 @@
})
(define_expand "ssmulha3"
- [(set (match_operand:HA 0 "s_register_operand" "")
- (ss_mult:HA (match_operand:HA 1 "s_register_operand" "")
- (match_operand:HA 2 "s_register_operand" "")))]
+ [(set (match_operand:HA 0 "s_register_operand")
+ (ss_mult:HA (match_operand:HA 1 "s_register_operand")
+ (match_operand:HA 2 "s_register_operand")))]
"TARGET_32BIT && TARGET_DSP_MULTIPLY && arm_arch6"
{
rtx tmp = gen_reg_rtx (SImode);
@@ -373,9 +373,9 @@
})
(define_expand "usmuluha3"
- [(set (match_operand:UHA 0 "s_register_operand" "")
- (us_mult:UHA (match_operand:UHA 1 "s_register_operand" "")
- (match_operand:UHA 2 "s_register_operand" "")))]
+ [(set (match_operand:UHA 0 "s_register_operand")
+ (us_mult:UHA (match_operand:UHA 1 "s_register_operand")
+ (match_operand:UHA 2 "s_register_operand")))]
"TARGET_INT_SIMD"
{
rtx tmp1 = gen_reg_rtx (SImode);
diff --git a/gcc/config/arm/arm-protos.h b/gcc/config/arm/arm-protos.h
index 485bc68..bf2bf1c 100644
--- a/gcc/config/arm/arm-protos.h
+++ b/gcc/config/arm/arm-protos.h
@@ -126,8 +126,8 @@ extern bool offset_ok_for_ldrd_strd (HOST_WIDE_INT);
extern bool operands_ok_ldrd_strd (rtx, rtx, rtx, HOST_WIDE_INT, bool, bool);
extern bool gen_operands_ldrd_strd (rtx *, bool, bool, bool);
extern bool valid_operands_ldrd_strd (rtx *, bool);
-extern int arm_gen_movmemqi (rtx *);
-extern bool gen_movmem_ldrd_strd (rtx *);
+extern int arm_gen_cpymemqi (rtx *);
+extern bool gen_cpymem_ldrd_strd (rtx *);
extern machine_mode arm_select_cc_mode (RTX_CODE, rtx, rtx);
extern machine_mode arm_select_dominance_cc_mode (rtx, rtx,
HOST_WIDE_INT);
@@ -203,7 +203,7 @@ extern void thumb2_final_prescan_insn (rtx_insn *);
extern const char *thumb_load_double_from_address (rtx *);
extern const char *thumb_output_move_mem_multiple (int, rtx *);
extern const char *thumb_call_via_reg (rtx);
-extern void thumb_expand_movmemqi (rtx *);
+extern void thumb_expand_cpymemqi (rtx *);
extern rtx arm_return_addr (int, rtx);
extern void thumb_reload_out_hi (rtx *);
extern void thumb_set_return_address (rtx, rtx);
diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
index 528752a..820502a 100644
--- a/gcc/config/arm/arm.c
+++ b/gcc/config/arm/arm.c
@@ -288,7 +288,7 @@ static bool arm_builtin_support_vector_misalignment (machine_mode mode,
static void arm_conditional_register_usage (void);
static enum flt_eval_method arm_excess_precision (enum excess_precision_type);
static reg_class_t arm_preferred_rename_class (reg_class_t rclass);
-static void arm_autovectorize_vector_sizes (vector_sizes *);
+static void arm_autovectorize_vector_sizes (vector_sizes *, bool);
static int arm_default_branch_cost (bool, bool);
static int arm_cortex_a5_branch_cost (bool, bool);
static int arm_cortex_m_branch_cost (bool, bool);
@@ -14385,7 +14385,7 @@ arm_block_move_unaligned_loop (rtx dest, rtx src, HOST_WIDE_INT length,
core type, optimize_size setting, etc. */
static int
-arm_movmemqi_unaligned (rtx *operands)
+arm_cpymemqi_unaligned (rtx *operands)
{
HOST_WIDE_INT length = INTVAL (operands[2]);
@@ -14422,7 +14422,7 @@ arm_movmemqi_unaligned (rtx *operands)
}
int
-arm_gen_movmemqi (rtx *operands)
+arm_gen_cpymemqi (rtx *operands)
{
HOST_WIDE_INT in_words_to_go, out_words_to_go, last_bytes;
HOST_WIDE_INT srcoffset, dstoffset;
@@ -14436,7 +14436,7 @@ arm_gen_movmemqi (rtx *operands)
return 0;
if (unaligned_access && (INTVAL (operands[3]) & 3) != 0)
- return arm_movmemqi_unaligned (operands);
+ return arm_cpymemqi_unaligned (operands);
if (INTVAL (operands[3]) & 3)
return 0;
@@ -14570,7 +14570,7 @@ arm_gen_movmemqi (rtx *operands)
return 1;
}
-/* Helper for gen_movmem_ldrd_strd. Increase the address of memory rtx
+/* Helper for gen_cpymem_ldrd_strd. Increase the address of memory rtx
by mode size. */
inline static rtx
next_consecutive_mem (rtx mem)
@@ -14585,7 +14585,7 @@ next_consecutive_mem (rtx mem)
/* Copy using LDRD/STRD instructions whenever possible.
Returns true upon success. */
bool
-gen_movmem_ldrd_strd (rtx *operands)
+gen_cpymem_ldrd_strd (rtx *operands)
{
unsigned HOST_WIDE_INT len;
HOST_WIDE_INT align;
@@ -14629,7 +14629,7 @@ gen_movmem_ldrd_strd (rtx *operands)
/* If we cannot generate any LDRD/STRD, try to generate LDM/STM. */
if (!(dst_aligned || src_aligned))
- return arm_gen_movmemqi (operands);
+ return arm_gen_cpymemqi (operands);
/* If the either src or dst is unaligned we'll be accessing it as pairs
of unaligned SImode accesses. Otherwise we can generate DImode
@@ -26395,7 +26395,7 @@ thumb_call_via_reg (rtx reg)
/* Routines for generating rtl. */
void
-thumb_expand_movmemqi (rtx *operands)
+thumb_expand_cpymemqi (rtx *operands)
{
rtx out = copy_to_mode_reg (SImode, XEXP (operands[0], 0));
rtx in = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
@@ -26404,13 +26404,13 @@ thumb_expand_movmemqi (rtx *operands)
while (len >= 12)
{
- emit_insn (gen_movmem12b (out, in, out, in));
+ emit_insn (gen_cpymem12b (out, in, out, in));
len -= 12;
}
if (len >= 8)
{
- emit_insn (gen_movmem8b (out, in, out, in));
+ emit_insn (gen_cpymem8b (out, in, out, in));
len -= 8;
}
@@ -26997,10 +26997,14 @@ static void
arm_output_mi_thunk (FILE *file, tree thunk, HOST_WIDE_INT delta,
HOST_WIDE_INT vcall_offset, tree function)
{
+ const char *fnname = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (thunk));
+
+ assemble_start_function (thunk, fnname);
if (TARGET_32BIT)
arm32_output_mi_thunk (file, thunk, delta, vcall_offset, function);
else
arm_thumb1_mi_thunk (file, thunk, delta, vcall_offset, function);
+ assemble_end_function (thunk, fnname);
}
int
@@ -28347,7 +28351,7 @@ arm_vector_alignment (const_tree type)
}
static void
-arm_autovectorize_vector_sizes (vector_sizes *sizes)
+arm_autovectorize_vector_sizes (vector_sizes *sizes, bool)
{
if (!TARGET_NEON_VECTORIZE_DOUBLE)
{
diff --git a/gcc/config/arm/arm.md b/gcc/config/arm/arm.md
index ae58217..8f4a4c2 100644
--- a/gcc/config/arm/arm.md
+++ b/gcc/config/arm/arm.md
@@ -444,9 +444,9 @@
(define_expand "adddi3"
[(parallel
- [(set (match_operand:DI 0 "s_register_operand" "")
- (plus:DI (match_operand:DI 1 "s_register_operand" "")
- (match_operand:DI 2 "arm_adddi_operand" "")))
+ [(set (match_operand:DI 0 "s_register_operand")
+ (plus:DI (match_operand:DI 1 "s_register_operand")
+ (match_operand:DI 2 "arm_adddi_operand")))
(clobber (reg:CC CC_REGNUM))])]
"TARGET_EITHER"
"
@@ -573,9 +573,9 @@
})
(define_expand "addsi3"
- [(set (match_operand:SI 0 "s_register_operand" "")
- (plus:SI (match_operand:SI 1 "s_register_operand" "")
- (match_operand:SI 2 "reg_or_int_operand" "")))]
+ [(set (match_operand:SI 0 "s_register_operand")
+ (plus:SI (match_operand:SI 1 "s_register_operand")
+ (match_operand:SI 2 "reg_or_int_operand")))]
"TARGET_EITHER"
"
if (TARGET_32BIT && CONST_INT_P (operands[2]))
@@ -1266,26 +1266,26 @@
")
(define_expand "addsf3"
- [(set (match_operand:SF 0 "s_register_operand" "")
- (plus:SF (match_operand:SF 1 "s_register_operand" "")
- (match_operand:SF 2 "s_register_operand" "")))]
+ [(set (match_operand:SF 0 "s_register_operand")
+ (plus:SF (match_operand:SF 1 "s_register_operand")
+ (match_operand:SF 2 "s_register_operand")))]
"TARGET_32BIT && TARGET_HARD_FLOAT"
"
")
(define_expand "adddf3"
- [(set (match_operand:DF 0 "s_register_operand" "")
- (plus:DF (match_operand:DF 1 "s_register_operand" "")
- (match_operand:DF 2 "s_register_operand" "")))]
+ [(set (match_operand:DF 0 "s_register_operand")
+ (plus:DF (match_operand:DF 1 "s_register_operand")
+ (match_operand:DF 2 "s_register_operand")))]
"TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
"
")
(define_expand "subdi3"
[(parallel
- [(set (match_operand:DI 0 "s_register_operand" "")
- (minus:DI (match_operand:DI 1 "s_register_operand" "")
- (match_operand:DI 2 "s_register_operand" "")))
+ [(set (match_operand:DI 0 "s_register_operand")
+ (minus:DI (match_operand:DI 1 "s_register_operand")
+ (match_operand:DI 2 "s_register_operand")))
(clobber (reg:CC CC_REGNUM))])]
"TARGET_EITHER"
"
@@ -1459,9 +1459,9 @@
)
(define_expand "subsi3"
- [(set (match_operand:SI 0 "s_register_operand" "")
- (minus:SI (match_operand:SI 1 "reg_or_int_operand" "")
- (match_operand:SI 2 "s_register_operand" "")))]
+ [(set (match_operand:SI 0 "s_register_operand")
+ (minus:SI (match_operand:SI 1 "reg_or_int_operand")
+ (match_operand:SI 2 "s_register_operand")))]
"TARGET_EITHER"
"
if (CONST_INT_P (operands[1]))
@@ -1562,17 +1562,17 @@
)
(define_expand "subsf3"
- [(set (match_operand:SF 0 "s_register_operand" "")
- (minus:SF (match_operand:SF 1 "s_register_operand" "")
- (match_operand:SF 2 "s_register_operand" "")))]
+ [(set (match_operand:SF 0 "s_register_operand")
+ (minus:SF (match_operand:SF 1 "s_register_operand")
+ (match_operand:SF 2 "s_register_operand")))]
"TARGET_32BIT && TARGET_HARD_FLOAT"
"
")
(define_expand "subdf3"
- [(set (match_operand:DF 0 "s_register_operand" "")
- (minus:DF (match_operand:DF 1 "s_register_operand" "")
- (match_operand:DF 2 "s_register_operand" "")))]
+ [(set (match_operand:DF 0 "s_register_operand")
+ (minus:DF (match_operand:DF 1 "s_register_operand")
+ (match_operand:DF 2 "s_register_operand")))]
"TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
"
")
@@ -1581,9 +1581,9 @@
;; Multiplication insns
(define_expand "mulhi3"
- [(set (match_operand:HI 0 "s_register_operand" "")
- (mult:HI (match_operand:HI 1 "s_register_operand" "")
- (match_operand:HI 2 "s_register_operand" "")))]
+ [(set (match_operand:HI 0 "s_register_operand")
+ (mult:HI (match_operand:HI 1 "s_register_operand")
+ (match_operand:HI 2 "s_register_operand")))]
"TARGET_DSP_MULTIPLY"
"
{
@@ -1595,9 +1595,9 @@
)
(define_expand "mulsi3"
- [(set (match_operand:SI 0 "s_register_operand" "")
- (mult:SI (match_operand:SI 2 "s_register_operand" "")
- (match_operand:SI 1 "s_register_operand" "")))]
+ [(set (match_operand:SI 0 "s_register_operand")
+ (mult:SI (match_operand:SI 2 "s_register_operand")
+ (match_operand:SI 1 "s_register_operand")))]
"TARGET_EITHER"
""
)
@@ -1783,12 +1783,12 @@
)
(define_expand "maddsidi4"
- [(set (match_operand:DI 0 "s_register_operand" "")
+ [(set (match_operand:DI 0 "s_register_operand")
(plus:DI
(mult:DI
- (sign_extend:DI (match_operand:SI 1 "s_register_operand" ""))
- (sign_extend:DI (match_operand:SI 2 "s_register_operand" "")))
- (match_operand:DI 3 "s_register_operand" "")))]
+ (sign_extend:DI (match_operand:SI 1 "s_register_operand"))
+ (sign_extend:DI (match_operand:SI 2 "s_register_operand")))
+ (match_operand:DI 3 "s_register_operand")))]
"TARGET_32BIT"
"")
@@ -1825,10 +1825,10 @@
;; expander and two different starred insns.
(define_expand "mulsidi3"
- [(set (match_operand:DI 0 "s_register_operand" "")
+ [(set (match_operand:DI 0 "s_register_operand")
(mult:DI
- (sign_extend:DI (match_operand:SI 1 "s_register_operand" ""))
- (sign_extend:DI (match_operand:SI 2 "s_register_operand" ""))))]
+ (sign_extend:DI (match_operand:SI 1 "s_register_operand"))
+ (sign_extend:DI (match_operand:SI 2 "s_register_operand"))))]
"TARGET_32BIT"
""
)
@@ -1856,10 +1856,10 @@
)
(define_expand "umulsidi3"
- [(set (match_operand:DI 0 "s_register_operand" "")
+ [(set (match_operand:DI 0 "s_register_operand")
(mult:DI
- (zero_extend:DI (match_operand:SI 1 "s_register_operand" ""))
- (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))))]
+ (zero_extend:DI (match_operand:SI 1 "s_register_operand"))
+ (zero_extend:DI (match_operand:SI 2 "s_register_operand"))))]
"TARGET_32BIT"
""
)
@@ -1887,12 +1887,12 @@
)
(define_expand "umaddsidi4"
- [(set (match_operand:DI 0 "s_register_operand" "")
+ [(set (match_operand:DI 0 "s_register_operand")
(plus:DI
(mult:DI
- (zero_extend:DI (match_operand:SI 1 "s_register_operand" ""))
- (zero_extend:DI (match_operand:SI 2 "s_register_operand" "")))
- (match_operand:DI 3 "s_register_operand" "")))]
+ (zero_extend:DI (match_operand:SI 1 "s_register_operand"))
+ (zero_extend:DI (match_operand:SI 2 "s_register_operand")))
+ (match_operand:DI 3 "s_register_operand")))]
"TARGET_32BIT"
"")
@@ -1924,12 +1924,12 @@
(define_expand "smulsi3_highpart"
[(parallel
- [(set (match_operand:SI 0 "s_register_operand" "")
+ [(set (match_operand:SI 0 "s_register_operand")
(truncate:SI
(lshiftrt:DI
(mult:DI
- (sign_extend:DI (match_operand:SI 1 "s_register_operand" ""))
- (sign_extend:DI (match_operand:SI 2 "s_register_operand" "")))
+ (sign_extend:DI (match_operand:SI 1 "s_register_operand"))
+ (sign_extend:DI (match_operand:SI 2 "s_register_operand")))
(const_int 32))))
(clobber (match_scratch:SI 3 ""))])]
"TARGET_32BIT"
@@ -1968,12 +1968,12 @@
(define_expand "umulsi3_highpart"
[(parallel
- [(set (match_operand:SI 0 "s_register_operand" "")
+ [(set (match_operand:SI 0 "s_register_operand")
(truncate:SI
(lshiftrt:DI
(mult:DI
- (zero_extend:DI (match_operand:SI 1 "s_register_operand" ""))
- (zero_extend:DI (match_operand:SI 2 "s_register_operand" "")))
+ (zero_extend:DI (match_operand:SI 1 "s_register_operand"))
+ (zero_extend:DI (match_operand:SI 2 "s_register_operand")))
(const_int 32))))
(clobber (match_scratch:SI 3 ""))])]
"TARGET_32BIT"
@@ -2152,17 +2152,17 @@
(set_attr "predicable" "yes")])
(define_expand "mulsf3"
- [(set (match_operand:SF 0 "s_register_operand" "")
- (mult:SF (match_operand:SF 1 "s_register_operand" "")
- (match_operand:SF 2 "s_register_operand" "")))]
+ [(set (match_operand:SF 0 "s_register_operand")
+ (mult:SF (match_operand:SF 1 "s_register_operand")
+ (match_operand:SF 2 "s_register_operand")))]
"TARGET_32BIT && TARGET_HARD_FLOAT"
"
")
(define_expand "muldf3"
- [(set (match_operand:DF 0 "s_register_operand" "")
- (mult:DF (match_operand:DF 1 "s_register_operand" "")
- (match_operand:DF 2 "s_register_operand" "")))]
+ [(set (match_operand:DF 0 "s_register_operand")
+ (mult:DF (match_operand:DF 1 "s_register_operand")
+ (match_operand:DF 2 "s_register_operand")))]
"TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
"
")
@@ -2170,16 +2170,16 @@
;; Division insns
(define_expand "divsf3"
- [(set (match_operand:SF 0 "s_register_operand" "")
- (div:SF (match_operand:SF 1 "s_register_operand" "")
- (match_operand:SF 2 "s_register_operand" "")))]
+ [(set (match_operand:SF 0 "s_register_operand")
+ (div:SF (match_operand:SF 1 "s_register_operand")
+ (match_operand:SF 2 "s_register_operand")))]
"TARGET_32BIT && TARGET_HARD_FLOAT"
"")
(define_expand "divdf3"
- [(set (match_operand:DF 0 "s_register_operand" "")
- (div:DF (match_operand:DF 1 "s_register_operand" "")
- (match_operand:DF 2 "s_register_operand" "")))]
+ [(set (match_operand:DF 0 "s_register_operand")
+ (div:DF (match_operand:DF 1 "s_register_operand")
+ (match_operand:DF 2 "s_register_operand")))]
"TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
"")
@@ -2270,9 +2270,9 @@
)
(define_expand "anddi3"
- [(set (match_operand:DI 0 "s_register_operand" "")
- (and:DI (match_operand:DI 1 "s_register_operand" "")
- (match_operand:DI 2 "neon_inv_logic_op2" "")))]
+ [(set (match_operand:DI 0 "s_register_operand")
+ (and:DI (match_operand:DI 1 "s_register_operand")
+ (match_operand:DI 2 "neon_inv_logic_op2")))]
"TARGET_32BIT"
"
if (!TARGET_NEON && !TARGET_IWMMXT)
@@ -2374,9 +2374,9 @@
)
(define_expand "andsi3"
- [(set (match_operand:SI 0 "s_register_operand" "")
- (and:SI (match_operand:SI 1 "s_register_operand" "")
- (match_operand:SI 2 "reg_or_int_operand" "")))]
+ [(set (match_operand:SI 0 "s_register_operand")
+ (and:SI (match_operand:SI 1 "s_register_operand")
+ (match_operand:SI 2 "reg_or_int_operand")))]
"TARGET_EITHER"
"
if (TARGET_32BIT)
@@ -2727,10 +2727,10 @@
;;; this insv pattern, so this pattern needs to be reevalutated.
(define_expand "insv"
- [(set (zero_extract (match_operand 0 "nonimmediate_operand" "")
- (match_operand 1 "general_operand" "")
- (match_operand 2 "general_operand" ""))
- (match_operand 3 "reg_or_int_operand" ""))]
+ [(set (zero_extract (match_operand 0 "nonimmediate_operand")
+ (match_operand 1 "general_operand")
+ (match_operand 2 "general_operand"))
+ (match_operand 3 "reg_or_int_operand"))]
"TARGET_ARM || arm_arch_thumb2"
"
{
@@ -3151,9 +3151,9 @@
)
(define_expand "iordi3"
- [(set (match_operand:DI 0 "s_register_operand" "")
- (ior:DI (match_operand:DI 1 "s_register_operand" "")
- (match_operand:DI 2 "neon_logic_op2" "")))]
+ [(set (match_operand:DI 0 "s_register_operand")
+ (ior:DI (match_operand:DI 1 "s_register_operand")
+ (match_operand:DI 2 "neon_logic_op2")))]
"TARGET_32BIT"
"
if (!TARGET_NEON && !TARGET_IWMMXT)
@@ -3246,9 +3246,9 @@
)
(define_expand "iorsi3"
- [(set (match_operand:SI 0 "s_register_operand" "")
- (ior:SI (match_operand:SI 1 "s_register_operand" "")
- (match_operand:SI 2 "reg_or_int_operand" "")))]
+ [(set (match_operand:SI 0 "s_register_operand")
+ (ior:SI (match_operand:SI 1 "s_register_operand")
+ (match_operand:SI 2 "reg_or_int_operand")))]
"TARGET_EITHER"
"
if (CONST_INT_P (operands[2]))
@@ -3348,9 +3348,9 @@
)
(define_expand "xordi3"
- [(set (match_operand:DI 0 "s_register_operand" "")
- (xor:DI (match_operand:DI 1 "s_register_operand" "")
- (match_operand:DI 2 "arm_xordi_operand" "")))]
+ [(set (match_operand:DI 0 "s_register_operand")
+ (xor:DI (match_operand:DI 1 "s_register_operand")
+ (match_operand:DI 2 "arm_xordi_operand")))]
"TARGET_32BIT"
{
/* The iWMMXt pattern for xordi3 accepts only register operands but we want
@@ -3445,9 +3445,9 @@
)
(define_expand "xorsi3"
- [(set (match_operand:SI 0 "s_register_operand" "")
- (xor:SI (match_operand:SI 1 "s_register_operand" "")
- (match_operand:SI 2 "reg_or_int_operand" "")))]
+ [(set (match_operand:SI 0 "s_register_operand")
+ (xor:SI (match_operand:SI 1 "s_register_operand")
+ (match_operand:SI 2 "reg_or_int_operand")))]
"TARGET_EITHER"
"if (CONST_INT_P (operands[2]))
{
@@ -3686,9 +3686,9 @@
(define_expand "smaxsi3"
[(parallel [
- (set (match_operand:SI 0 "s_register_operand" "")
- (smax:SI (match_operand:SI 1 "s_register_operand" "")
- (match_operand:SI 2 "arm_rhs_operand" "")))
+ (set (match_operand:SI 0 "s_register_operand")
+ (smax:SI (match_operand:SI 1 "s_register_operand")
+ (match_operand:SI 2 "arm_rhs_operand")))
(clobber (reg:CC CC_REGNUM))])]
"TARGET_32BIT"
"
@@ -3746,9 +3746,9 @@
(define_expand "sminsi3"
[(parallel [
- (set (match_operand:SI 0 "s_register_operand" "")
- (smin:SI (match_operand:SI 1 "s_register_operand" "")
- (match_operand:SI 2 "arm_rhs_operand" "")))
+ (set (match_operand:SI 0 "s_register_operand")
+ (smin:SI (match_operand:SI 1 "s_register_operand")
+ (match_operand:SI 2 "arm_rhs_operand")))
(clobber (reg:CC CC_REGNUM))])]
"TARGET_32BIT"
"
@@ -3796,9 +3796,9 @@
(define_expand "umaxsi3"
[(parallel [
- (set (match_operand:SI 0 "s_register_operand" "")
- (umax:SI (match_operand:SI 1 "s_register_operand" "")
- (match_operand:SI 2 "arm_rhs_operand" "")))
+ (set (match_operand:SI 0 "s_register_operand")
+ (umax:SI (match_operand:SI 1 "s_register_operand")
+ (match_operand:SI 2 "arm_rhs_operand")))
(clobber (reg:CC CC_REGNUM))])]
"TARGET_32BIT"
""
@@ -3829,9 +3829,9 @@
(define_expand "uminsi3"
[(parallel [
- (set (match_operand:SI 0 "s_register_operand" "")
- (umin:SI (match_operand:SI 1 "s_register_operand" "")
- (match_operand:SI 2 "arm_rhs_operand" "")))
+ (set (match_operand:SI 0 "s_register_operand")
+ (umin:SI (match_operand:SI 1 "s_register_operand")
+ (match_operand:SI 2 "arm_rhs_operand")))
(clobber (reg:CC CC_REGNUM))])]
"TARGET_32BIT"
""
@@ -4037,9 +4037,9 @@
;; Shift and rotation insns
(define_expand "ashldi3"
- [(set (match_operand:DI 0 "s_register_operand" "")
- (ashift:DI (match_operand:DI 1 "s_register_operand" "")
- (match_operand:SI 2 "general_operand" "")))]
+ [(set (match_operand:DI 0 "s_register_operand")
+ (ashift:DI (match_operand:DI 1 "s_register_operand")
+ (match_operand:SI 2 "general_operand")))]
"TARGET_32BIT"
"
if (TARGET_NEON)
@@ -4079,9 +4079,9 @@
)
(define_expand "ashlsi3"
- [(set (match_operand:SI 0 "s_register_operand" "")
- (ashift:SI (match_operand:SI 1 "s_register_operand" "")
- (match_operand:SI 2 "arm_rhs_operand" "")))]
+ [(set (match_operand:SI 0 "s_register_operand")
+ (ashift:SI (match_operand:SI 1 "s_register_operand")
+ (match_operand:SI 2 "arm_rhs_operand")))]
"TARGET_EITHER"
"
if (CONST_INT_P (operands[2])
@@ -4094,9 +4094,9 @@
)
(define_expand "ashrdi3"
- [(set (match_operand:DI 0 "s_register_operand" "")
- (ashiftrt:DI (match_operand:DI 1 "s_register_operand" "")
- (match_operand:SI 2 "reg_or_int_operand" "")))]
+ [(set (match_operand:DI 0 "s_register_operand")
+ (ashiftrt:DI (match_operand:DI 1 "s_register_operand")
+ (match_operand:SI 2 "reg_or_int_operand")))]
"TARGET_32BIT"
"
if (TARGET_NEON)
@@ -4130,9 +4130,9 @@
)
(define_expand "ashrsi3"
- [(set (match_operand:SI 0 "s_register_operand" "")
- (ashiftrt:SI (match_operand:SI 1 "s_register_operand" "")
- (match_operand:SI 2 "arm_rhs_operand" "")))]
+ [(set (match_operand:SI 0 "s_register_operand")
+ (ashiftrt:SI (match_operand:SI 1 "s_register_operand")
+ (match_operand:SI 2 "arm_rhs_operand")))]
"TARGET_EITHER"
"
if (CONST_INT_P (operands[2])
@@ -4142,9 +4142,9 @@
)
(define_expand "lshrdi3"
- [(set (match_operand:DI 0 "s_register_operand" "")
- (lshiftrt:DI (match_operand:DI 1 "s_register_operand" "")
- (match_operand:SI 2 "reg_or_int_operand" "")))]
+ [(set (match_operand:DI 0 "s_register_operand")
+ (lshiftrt:DI (match_operand:DI 1 "s_register_operand")
+ (match_operand:SI 2 "reg_or_int_operand")))]
"TARGET_32BIT"
"
if (TARGET_NEON)
@@ -4178,9 +4178,9 @@
)
(define_expand "lshrsi3"
- [(set (match_operand:SI 0 "s_register_operand" "")
- (lshiftrt:SI (match_operand:SI 1 "s_register_operand" "")
- (match_operand:SI 2 "arm_rhs_operand" "")))]
+ [(set (match_operand:SI 0 "s_register_operand")
+ (lshiftrt:SI (match_operand:SI 1 "s_register_operand")
+ (match_operand:SI 2 "arm_rhs_operand")))]
"TARGET_EITHER"
"
if (CONST_INT_P (operands[2])
@@ -4193,9 +4193,9 @@
)
(define_expand "rotlsi3"
- [(set (match_operand:SI 0 "s_register_operand" "")
- (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
- (match_operand:SI 2 "reg_or_int_operand" "")))]
+ [(set (match_operand:SI 0 "s_register_operand")
+ (rotatert:SI (match_operand:SI 1 "s_register_operand")
+ (match_operand:SI 2 "reg_or_int_operand")))]
"TARGET_32BIT"
"
if (CONST_INT_P (operands[2]))
@@ -4210,9 +4210,9 @@
)
(define_expand "rotrsi3"
- [(set (match_operand:SI 0 "s_register_operand" "")
- (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
- (match_operand:SI 2 "arm_rhs_operand" "")))]
+ [(set (match_operand:SI 0 "s_register_operand")
+ (rotatert:SI (match_operand:SI 1 "s_register_operand")
+ (match_operand:SI 2 "arm_rhs_operand")))]
"TARGET_EITHER"
"
if (TARGET_32BIT)
@@ -4320,10 +4320,10 @@
;; to reduce register pressure later on.
(define_expand "extzv"
- [(set (match_operand 0 "s_register_operand" "")
- (zero_extract (match_operand 1 "nonimmediate_operand" "")
- (match_operand 2 "const_int_operand" "")
- (match_operand 3 "const_int_operand" "")))]
+ [(set (match_operand 0 "s_register_operand")
+ (zero_extract (match_operand 1 "nonimmediate_operand")
+ (match_operand 2 "const_int_operand")
+ (match_operand 3 "const_int_operand")))]
"TARGET_THUMB1 || arm_arch_thumb2"
"
{
@@ -4401,20 +4401,20 @@
;; Helper for extzv, for the Thumb-1 register-shifts case.
(define_expand "extzv_t1"
- [(set (match_operand:SI 4 "s_register_operand" "")
- (ashift:SI (match_operand:SI 1 "nonimmediate_operand" "")
- (match_operand:SI 2 "const_int_operand" "")))
- (set (match_operand:SI 0 "s_register_operand" "")
+ [(set (match_operand:SI 4 "s_register_operand")
+ (ashift:SI (match_operand:SI 1 "nonimmediate_operand")
+ (match_operand:SI 2 "const_int_operand")))
+ (set (match_operand:SI 0 "s_register_operand")
(lshiftrt:SI (match_dup 4)
- (match_operand:SI 3 "const_int_operand" "")))]
+ (match_operand:SI 3 "const_int_operand")))]
"TARGET_THUMB1"
"")
(define_expand "extv"
- [(set (match_operand 0 "s_register_operand" "")
- (sign_extract (match_operand 1 "nonimmediate_operand" "")
- (match_operand 2 "const_int_operand" "")
- (match_operand 3 "const_int_operand" "")))]
+ [(set (match_operand 0 "s_register_operand")
+ (sign_extract (match_operand 1 "nonimmediate_operand")
+ (match_operand 2 "const_int_operand")
+ (match_operand 3 "const_int_operand")))]
"arm_arch_thumb2"
{
HOST_WIDE_INT width = INTVAL (operands[2]);
@@ -4472,10 +4472,10 @@
; Helper to expand register forms of extv with the proper modes.
(define_expand "extv_regsi"
- [(set (match_operand:SI 0 "s_register_operand" "")
- (sign_extract:SI (match_operand:SI 1 "s_register_operand" "")
- (match_operand 2 "const_int_operand" "")
- (match_operand 3 "const_int_operand" "")))]
+ [(set (match_operand:SI 0 "s_register_operand")
+ (sign_extract:SI (match_operand:SI 1 "s_register_operand")
+ (match_operand 2 "const_int_operand")
+ (match_operand 3 "const_int_operand")))]
""
{
})
@@ -4676,8 +4676,8 @@
(define_expand "negdi2"
[(parallel
- [(set (match_operand:DI 0 "s_register_operand" "")
- (neg:DI (match_operand:DI 1 "s_register_operand" "")))
+ [(set (match_operand:DI 0 "s_register_operand")
+ (neg:DI (match_operand:DI 1 "s_register_operand")))
(clobber (reg:CC CC_REGNUM))])]
"TARGET_EITHER"
{
@@ -4730,8 +4730,8 @@
)
(define_expand "negsi2"
- [(set (match_operand:SI 0 "s_register_operand" "")
- (neg:SI (match_operand:SI 1 "s_register_operand" "")))]
+ [(set (match_operand:SI 0 "s_register_operand")
+ (neg:SI (match_operand:SI 1 "s_register_operand")))]
"TARGET_EITHER"
""
)
@@ -4749,15 +4749,15 @@
)
(define_expand "negsf2"
- [(set (match_operand:SF 0 "s_register_operand" "")
- (neg:SF (match_operand:SF 1 "s_register_operand" "")))]
+ [(set (match_operand:SF 0 "s_register_operand")
+ (neg:SF (match_operand:SF 1 "s_register_operand")))]
"TARGET_32BIT && TARGET_HARD_FLOAT"
""
)
(define_expand "negdf2"
- [(set (match_operand:DF 0 "s_register_operand" "")
- (neg:DF (match_operand:DF 1 "s_register_operand" "")))]
+ [(set (match_operand:DF 0 "s_register_operand")
+ (neg:DF (match_operand:DF 1 "s_register_operand")))]
"TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
"")
@@ -4881,8 +4881,8 @@
(define_expand "abssi2"
[(parallel
- [(set (match_operand:SI 0 "s_register_operand" "")
- (abs:SI (match_operand:SI 1 "s_register_operand" "")))
+ [(set (match_operand:SI 0 "s_register_operand")
+ (abs:SI (match_operand:SI 1 "s_register_operand")))
(clobber (match_dup 2))])]
"TARGET_EITHER"
"
@@ -5010,32 +5010,32 @@
)
(define_expand "abssf2"
- [(set (match_operand:SF 0 "s_register_operand" "")
- (abs:SF (match_operand:SF 1 "s_register_operand" "")))]
+ [(set (match_operand:SF 0 "s_register_operand")
+ (abs:SF (match_operand:SF 1 "s_register_operand")))]
"TARGET_32BIT && TARGET_HARD_FLOAT"
"")
(define_expand "absdf2"
- [(set (match_operand:DF 0 "s_register_operand" "")
- (abs:DF (match_operand:DF 1 "s_register_operand" "")))]
+ [(set (match_operand:DF 0 "s_register_operand")
+ (abs:DF (match_operand:DF 1 "s_register_operand")))]
"TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
"")
(define_expand "sqrtsf2"
- [(set (match_operand:SF 0 "s_register_operand" "")
- (sqrt:SF (match_operand:SF 1 "s_register_operand" "")))]
+ [(set (match_operand:SF 0 "s_register_operand")
+ (sqrt:SF (match_operand:SF 1 "s_register_operand")))]
"TARGET_32BIT && TARGET_HARD_FLOAT"
"")
(define_expand "sqrtdf2"
- [(set (match_operand:DF 0 "s_register_operand" "")
- (sqrt:DF (match_operand:DF 1 "s_register_operand" "")))]
+ [(set (match_operand:DF 0 "s_register_operand")
+ (sqrt:DF (match_operand:DF 1 "s_register_operand")))]
"TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
"")
(define_expand "one_cmpldi2"
- [(set (match_operand:DI 0 "s_register_operand" "")
- (not:DI (match_operand:DI 1 "s_register_operand" "")))]
+ [(set (match_operand:DI 0 "s_register_operand")
+ (not:DI (match_operand:DI 1 "s_register_operand")))]
"TARGET_32BIT"
"
if (!TARGET_NEON && !TARGET_IWMMXT)
@@ -5084,8 +5084,8 @@
)
(define_expand "one_cmplsi2"
- [(set (match_operand:SI 0 "s_register_operand" "")
- (not:SI (match_operand:SI 1 "s_register_operand" "")))]
+ [(set (match_operand:SI 0 "s_register_operand")
+ (not:SI (match_operand:SI 1 "s_register_operand")))]
"TARGET_EITHER"
""
)
@@ -5128,8 +5128,8 @@
;; Fixed <--> Floating conversion insns
(define_expand "floatsihf2"
- [(set (match_operand:HF 0 "general_operand" "")
- (float:HF (match_operand:SI 1 "general_operand" "")))]
+ [(set (match_operand:HF 0 "general_operand")
+ (float:HF (match_operand:SI 1 "general_operand")))]
"TARGET_EITHER"
"
{
@@ -5142,8 +5142,8 @@
)
(define_expand "floatdihf2"
- [(set (match_operand:HF 0 "general_operand" "")
- (float:HF (match_operand:DI 1 "general_operand" "")))]
+ [(set (match_operand:HF 0 "general_operand")
+ (float:HF (match_operand:DI 1 "general_operand")))]
"TARGET_EITHER"
"
{
@@ -5156,22 +5156,22 @@
)
(define_expand "floatsisf2"
- [(set (match_operand:SF 0 "s_register_operand" "")
- (float:SF (match_operand:SI 1 "s_register_operand" "")))]
+ [(set (match_operand:SF 0 "s_register_operand")
+ (float:SF (match_operand:SI 1 "s_register_operand")))]
"TARGET_32BIT && TARGET_HARD_FLOAT"
"
")
(define_expand "floatsidf2"
- [(set (match_operand:DF 0 "s_register_operand" "")
- (float:DF (match_operand:SI 1 "s_register_operand" "")))]
+ [(set (match_operand:DF 0 "s_register_operand")
+ (float:DF (match_operand:SI 1 "s_register_operand")))]
"TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
"
")
(define_expand "fix_trunchfsi2"
- [(set (match_operand:SI 0 "general_operand" "")
- (fix:SI (fix:HF (match_operand:HF 1 "general_operand" ""))))]
+ [(set (match_operand:SI 0 "general_operand")
+ (fix:SI (fix:HF (match_operand:HF 1 "general_operand"))))]
"TARGET_EITHER"
"
{
@@ -5182,8 +5182,8 @@
)
(define_expand "fix_trunchfdi2"
- [(set (match_operand:DI 0 "general_operand" "")
- (fix:DI (fix:HF (match_operand:HF 1 "general_operand" ""))))]
+ [(set (match_operand:DI 0 "general_operand")
+ (fix:DI (fix:HF (match_operand:HF 1 "general_operand"))))]
"TARGET_EITHER"
"
{
@@ -5194,15 +5194,15 @@
)
(define_expand "fix_truncsfsi2"
- [(set (match_operand:SI 0 "s_register_operand" "")
- (fix:SI (fix:SF (match_operand:SF 1 "s_register_operand" ""))))]
+ [(set (match_operand:SI 0 "s_register_operand")
+ (fix:SI (fix:SF (match_operand:SF 1 "s_register_operand"))))]
"TARGET_32BIT && TARGET_HARD_FLOAT"
"
")
(define_expand "fix_truncdfsi2"
- [(set (match_operand:SI 0 "s_register_operand" "")
- (fix:SI (fix:DF (match_operand:DF 1 "s_register_operand" ""))))]
+ [(set (match_operand:SI 0 "s_register_operand")
+ (fix:SI (fix:DF (match_operand:DF 1 "s_register_operand"))))]
"TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
"
")
@@ -5210,9 +5210,9 @@
;; Truncation insns
(define_expand "truncdfsf2"
- [(set (match_operand:SF 0 "s_register_operand" "")
+ [(set (match_operand:SF 0 "s_register_operand")
(float_truncate:SF
- (match_operand:DF 1 "s_register_operand" "")))]
+ (match_operand:DF 1 "s_register_operand")))]
"TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
""
)
@@ -5225,9 +5225,9 @@
;; a single-step instruction.
(define_expand "truncdfhf2"
- [(set (match_operand:HF 0 "s_register_operand" "")
+ [(set (match_operand:HF 0 "s_register_operand")
(float_truncate:HF
- (match_operand:DF 1 "s_register_operand" "")))]
+ (match_operand:DF 1 "s_register_operand")))]
"(TARGET_EITHER && flag_unsafe_math_optimizations)
|| (TARGET_32BIT && TARGET_FP16_TO_DOUBLE)"
{
@@ -5330,8 +5330,8 @@
})
(define_expand "zero_extendhisi2"
- [(set (match_operand:SI 0 "s_register_operand" "")
- (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "")))]
+ [(set (match_operand:SI 0 "s_register_operand")
+ (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand")))]
"TARGET_EITHER"
{
if (TARGET_ARM && !arm_arch4 && MEM_P (operands[1]))
@@ -5392,8 +5392,8 @@
)
(define_expand "zero_extendqisi2"
- [(set (match_operand:SI 0 "s_register_operand" "")
- (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))]
+ [(set (match_operand:SI 0 "s_register_operand")
+ (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand")))]
"TARGET_EITHER"
{
if (TARGET_ARM && !arm_arch6 && !MEM_P (operands[1]))
@@ -5514,8 +5514,8 @@
)
(define_expand "extendhisi2"
- [(set (match_operand:SI 0 "s_register_operand" "")
- (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "")))]
+ [(set (match_operand:SI 0 "s_register_operand")
+ (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand")))]
"TARGET_EITHER"
{
if (TARGET_THUMB1)
@@ -5633,9 +5633,9 @@
(define_expand "extendqihi2"
[(set (match_dup 2)
- (ashift:SI (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "")
+ (ashift:SI (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op")
(const_int 24)))
- (set (match_operand:HI 0 "s_register_operand" "")
+ (set (match_operand:HI 0 "s_register_operand")
(ashiftrt:SI (match_dup 2)
(const_int 24)))]
"TARGET_ARM"
@@ -5665,8 +5665,8 @@
)
(define_expand "extendqisi2"
- [(set (match_operand:SI 0 "s_register_operand" "")
- (sign_extend:SI (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "")))]
+ [(set (match_operand:SI 0 "s_register_operand")
+ (sign_extend:SI (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op")))]
"TARGET_EITHER"
{
if (!arm_arch4 && MEM_P (operands[1]))
@@ -5727,8 +5727,8 @@
)
(define_expand "extendsfdf2"
- [(set (match_operand:DF 0 "s_register_operand" "")
- (float_extend:DF (match_operand:SF 1 "s_register_operand" "")))]
+ [(set (match_operand:DF 0 "s_register_operand")
+ (float_extend:DF (match_operand:SF 1 "s_register_operand")))]
"TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
""
)
@@ -5739,8 +5739,8 @@
;; This is always safe for an extend.
(define_expand "extendhfdf2"
- [(set (match_operand:DF 0 "s_register_operand" "")
- (float_extend:DF (match_operand:HF 1 "s_register_operand" "")))]
+ [(set (match_operand:DF 0 "s_register_operand")
+ (float_extend:DF (match_operand:HF 1 "s_register_operand")))]
"TARGET_EITHER"
{
/* We don't have a direct instruction for this, so go via SFmode. */
@@ -5763,18 +5763,18 @@
;; I don't think these are a good idea on the arm, there just aren't enough
;; registers
;;(define_expand "loadti"
-;; [(set (match_operand:TI 0 "s_register_operand" "")
-;; (mem:TI (match_operand:SI 1 "address_operand" "")))]
+;; [(set (match_operand:TI 0 "s_register_operand")
+;; (mem:TI (match_operand:SI 1 "address_operand")))]
;; "" "")
;;(define_expand "storeti"
-;; [(set (mem:TI (match_operand:TI 0 "address_operand" ""))
-;; (match_operand:TI 1 "s_register_operand" ""))]
+;; [(set (mem:TI (match_operand:TI 0 "address_operand"))
+;; (match_operand:TI 1 "s_register_operand"))]
;; "" "")
;;(define_expand "movti"
-;; [(set (match_operand:TI 0 "general_operand" "")
-;; (match_operand:TI 1 "general_operand" ""))]
+;; [(set (match_operand:TI 0 "general_operand")
+;; (match_operand:TI 1 "general_operand"))]
;; ""
;; "
;;{
@@ -5819,8 +5819,8 @@
;; }")
(define_expand "movdi"
- [(set (match_operand:DI 0 "general_operand" "")
- (match_operand:DI 1 "general_operand" ""))]
+ [(set (match_operand:DI 0 "general_operand")
+ (match_operand:DI 1 "general_operand"))]
"TARGET_EITHER"
"
if (can_create_pseudo_p ())
@@ -5992,8 +5992,8 @@
)
(define_expand "movsi"
- [(set (match_operand:SI 0 "general_operand" "")
- (match_operand:SI 1 "general_operand" ""))]
+ [(set (match_operand:SI 0 "general_operand")
+ (match_operand:SI 1 "general_operand"))]
"TARGET_EITHER"
"
{
@@ -6183,8 +6183,8 @@
;;
;; Note: Update arm.c: legitimize_pic_address() when changing this pattern.
(define_expand "calculate_pic_address"
- [(set (match_operand:SI 0 "register_operand" "")
- (mem:SI (plus:SI (match_operand:SI 1 "register_operand" "")
+ [(set (match_operand:SI 0 "register_operand")
+ (mem:SI (plus:SI (match_operand:SI 1 "register_operand")
(unspec:SI [(match_operand:SI 2 "" "")]
UNSPEC_PIC_SYM))))]
"flag_pic"
@@ -6474,8 +6474,8 @@
)
(define_expand "storehi_single_op"
- [(set (match_operand:HI 0 "memory_operand" "")
- (match_operand:HI 1 "general_operand" ""))]
+ [(set (match_operand:HI 0 "memory_operand")
+ (match_operand:HI 1 "general_operand"))]
"TARGET_32BIT && arm_arch4"
"
if (!s_register_operand (operands[1], HImode))
@@ -6484,8 +6484,8 @@
)
(define_expand "movhi"
- [(set (match_operand:HI 0 "general_operand" "")
- (match_operand:HI 1 "general_operand" ""))]
+ [(set (match_operand:HI 0 "general_operand")
+ (match_operand:HI 1 "general_operand"))]
"TARGET_EITHER"
"
if (TARGET_ARM)
@@ -6709,11 +6709,11 @@
(define_expand "movhi_bigend"
[(set (match_dup 2)
- (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "") 0)
+ (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand") 0)
(const_int 16)))
(set (match_dup 3)
(ashiftrt:SI (match_dup 2) (const_int 16)))
- (set (match_operand:HI 0 "s_register_operand" "")
+ (set (match_operand:HI 0 "s_register_operand")
(match_dup 4))]
"TARGET_ARM"
"
@@ -6766,6 +6766,8 @@
;; We use a DImode scratch because we may occasionally need an additional
;; temporary if the address isn't offsettable -- push_reload doesn't seem
;; to take any notice of the "o" constraints on reload_memory_operand operand.
+;; The reload_in<m> and reload_out<m> patterns require special constraints
+;; to be correctly handled in default_secondary_reload function.
(define_expand "reload_outhi"
[(parallel [(match_operand:HI 0 "arm_reload_memory_operand" "=o")
(match_operand:HI 1 "s_register_operand" "r")
@@ -6793,8 +6795,8 @@
")
(define_expand "movqi"
- [(set (match_operand:QI 0 "general_operand" "")
- (match_operand:QI 1 "general_operand" ""))]
+ [(set (match_operand:QI 0 "general_operand")
+ (match_operand:QI 1 "general_operand"))]
"TARGET_EITHER"
"
/* Everything except mem = const or mem = mem can be done easily */
@@ -6891,8 +6893,8 @@
;; HFmode moves
(define_expand "movhf"
- [(set (match_operand:HF 0 "general_operand" "")
- (match_operand:HF 1 "general_operand" ""))]
+ [(set (match_operand:HF 0 "general_operand")
+ (match_operand:HF 1 "general_operand"))]
"TARGET_EITHER"
"
if (TARGET_32BIT)
@@ -6955,8 +6957,8 @@
)
(define_expand "movsf"
- [(set (match_operand:SF 0 "general_operand" "")
- (match_operand:SF 1 "general_operand" ""))]
+ [(set (match_operand:SF 0 "general_operand")
+ (match_operand:SF 1 "general_operand"))]
"TARGET_EITHER"
"
if (TARGET_32BIT)
@@ -7050,8 +7052,8 @@
)
(define_expand "movdf"
- [(set (match_operand:DF 0 "general_operand" "")
- (match_operand:DF 1 "general_operand" ""))]
+ [(set (match_operand:DF 0 "general_operand")
+ (match_operand:DF 1 "general_operand"))]
"TARGET_EITHER"
"
if (TARGET_32BIT)
@@ -7087,6 +7089,7 @@
;; Reloading a df mode value stored in integer regs to memory can require a
;; scratch reg.
+;; Another reload_out<m> pattern that requires special constraints.
(define_expand "reload_outdf"
[(match_operand:DF 0 "arm_reload_memory_operand" "=o")
(match_operand:DF 1 "s_register_operand" "r")
@@ -7233,10 +7236,10 @@
(define_expand "setmemsi"
- [(match_operand:BLK 0 "general_operand" "")
- (match_operand:SI 1 "const_int_operand" "")
- (match_operand:SI 2 "const_int_operand" "")
- (match_operand:SI 3 "const_int_operand" "")]
+ [(match_operand:BLK 0 "general_operand")
+ (match_operand:SI 1 "const_int_operand")
+ (match_operand:SI 2 "const_int_operand")
+ (match_operand:SI 3 "const_int_operand")]
"TARGET_32BIT"
{
if (arm_gen_setmem (operands))
@@ -7250,11 +7253,11 @@
;; We could let this apply for blocks of less than this, but it clobbers so
;; many registers that there is then probably a better way.
-(define_expand "movmemqi"
- [(match_operand:BLK 0 "general_operand" "")
- (match_operand:BLK 1 "general_operand" "")
- (match_operand:SI 2 "const_int_operand" "")
- (match_operand:SI 3 "const_int_operand" "")]
+(define_expand "cpymemqi"
+ [(match_operand:BLK 0 "general_operand")
+ (match_operand:BLK 1 "general_operand")
+ (match_operand:SI 2 "const_int_operand")
+ (match_operand:SI 3 "const_int_operand")]
""
"
if (TARGET_32BIT)
@@ -7262,12 +7265,12 @@
if (TARGET_LDRD && current_tune->prefer_ldrd_strd
&& !optimize_function_for_size_p (cfun))
{
- if (gen_movmem_ldrd_strd (operands))
+ if (gen_cpymem_ldrd_strd (operands))
DONE;
FAIL;
}
- if (arm_gen_movmemqi (operands))
+ if (arm_gen_cpymemqi (operands))
DONE;
FAIL;
}
@@ -7277,7 +7280,7 @@
|| INTVAL (operands[2]) > 48)
FAIL;
- thumb_expand_movmemqi (operands);
+ thumb_expand_cpymemqi (operands);
DONE;
}
"
@@ -7304,8 +7307,8 @@
(define_expand "cbranchsi4"
[(set (pc) (if_then_else
(match_operator 0 "expandable_comparison_operator"
- [(match_operand:SI 1 "s_register_operand" "")
- (match_operand:SI 2 "nonmemory_operand" "")])
+ [(match_operand:SI 1 "s_register_operand")
+ (match_operand:SI 2 "nonmemory_operand")])
(label_ref (match_operand 3 "" ""))
(pc)))]
"TARGET_EITHER"
@@ -7331,8 +7334,8 @@
(define_expand "cbranchsf4"
[(set (pc) (if_then_else
(match_operator 0 "expandable_comparison_operator"
- [(match_operand:SF 1 "s_register_operand" "")
- (match_operand:SF 2 "vfp_compare_operand" "")])
+ [(match_operand:SF 1 "s_register_operand")
+ (match_operand:SF 2 "vfp_compare_operand")])
(label_ref (match_operand 3 "" ""))
(pc)))]
"TARGET_32BIT && TARGET_HARD_FLOAT"
@@ -7343,8 +7346,8 @@
(define_expand "cbranchdf4"
[(set (pc) (if_then_else
(match_operator 0 "expandable_comparison_operator"
- [(match_operand:DF 1 "s_register_operand" "")
- (match_operand:DF 2 "vfp_compare_operand" "")])
+ [(match_operand:DF 1 "s_register_operand")
+ (match_operand:DF 2 "vfp_compare_operand")])
(label_ref (match_operand 3 "" ""))
(pc)))]
"TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
@@ -7355,8 +7358,8 @@
(define_expand "cbranchdi4"
[(set (pc) (if_then_else
(match_operator 0 "expandable_comparison_operator"
- [(match_operand:DI 1 "s_register_operand" "")
- (match_operand:DI 2 "cmpdi_operand" "")])
+ [(match_operand:DI 1 "s_register_operand")
+ (match_operand:DI 2 "cmpdi_operand")])
(label_ref (match_operand 3 "" ""))
(pc)))]
"TARGET_32BIT"
@@ -7608,7 +7611,7 @@
; scc insns
(define_expand "cstore_cc"
- [(set (match_operand:SI 0 "s_register_operand" "")
+ [(set (match_operand:SI 0 "s_register_operand")
(match_operator:SI 1 "" [(match_operand 2 "" "")
(match_operand 3 "" "")]))]
"TARGET_32BIT"
@@ -7674,10 +7677,10 @@
)
(define_expand "cstoresi4"
- [(set (match_operand:SI 0 "s_register_operand" "")
+ [(set (match_operand:SI 0 "s_register_operand")
(match_operator:SI 1 "expandable_comparison_operator"
- [(match_operand:SI 2 "s_register_operand" "")
- (match_operand:SI 3 "reg_or_int_operand" "")]))]
+ [(match_operand:SI 2 "s_register_operand")
+ (match_operand:SI 3 "reg_or_int_operand")]))]
"TARGET_32BIT || TARGET_THUMB1"
"{
rtx op3, scratch, scratch2;
@@ -7828,30 +7831,30 @@
)
(define_expand "cstoresf4"
- [(set (match_operand:SI 0 "s_register_operand" "")
+ [(set (match_operand:SI 0 "s_register_operand")
(match_operator:SI 1 "expandable_comparison_operator"
- [(match_operand:SF 2 "s_register_operand" "")
- (match_operand:SF 3 "vfp_compare_operand" "")]))]
+ [(match_operand:SF 2 "s_register_operand")
+ (match_operand:SF 3 "vfp_compare_operand")]))]
"TARGET_32BIT && TARGET_HARD_FLOAT"
"emit_insn (gen_cstore_cc (operands[0], operands[1],
operands[2], operands[3])); DONE;"
)
(define_expand "cstoredf4"
- [(set (match_operand:SI 0 "s_register_operand" "")
+ [(set (match_operand:SI 0 "s_register_operand")
(match_operator:SI 1 "expandable_comparison_operator"
- [(match_operand:DF 2 "s_register_operand" "")
- (match_operand:DF 3 "vfp_compare_operand" "")]))]
+ [(match_operand:DF 2 "s_register_operand")
+ (match_operand:DF 3 "vfp_compare_operand")]))]
"TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
"emit_insn (gen_cstore_cc (operands[0], operands[1],
operands[2], operands[3])); DONE;"
)
(define_expand "cstoredi4"
- [(set (match_operand:SI 0 "s_register_operand" "")
+ [(set (match_operand:SI 0 "s_register_operand")
(match_operator:SI 1 "expandable_comparison_operator"
- [(match_operand:DI 2 "s_register_operand" "")
- (match_operand:DI 3 "cmpdi_operand" "")]))]
+ [(match_operand:DI 2 "s_register_operand")
+ (match_operand:DI 3 "cmpdi_operand")]))]
"TARGET_32BIT"
"{
if (!arm_validize_comparison (&operands[1],
@@ -7868,10 +7871,10 @@
;; Conditional move insns
(define_expand "movsicc"
- [(set (match_operand:SI 0 "s_register_operand" "")
- (if_then_else:SI (match_operand 1 "expandable_comparison_operator" "")
- (match_operand:SI 2 "arm_not_operand" "")
- (match_operand:SI 3 "arm_not_operand" "")))]
+ [(set (match_operand:SI 0 "s_register_operand")
+ (if_then_else:SI (match_operand 1 "expandable_comparison_operator")
+ (match_operand:SI 2 "arm_not_operand")
+ (match_operand:SI 3 "arm_not_operand")))]
"TARGET_32BIT"
"
{
@@ -7912,10 +7915,10 @@
)
(define_expand "movsfcc"
- [(set (match_operand:SF 0 "s_register_operand" "")
- (if_then_else:SF (match_operand 1 "arm_cond_move_operator" "")
- (match_operand:SF 2 "s_register_operand" "")
- (match_operand:SF 3 "s_register_operand" "")))]
+ [(set (match_operand:SF 0 "s_register_operand")
+ (if_then_else:SF (match_operand 1 "arm_cond_move_operator")
+ (match_operand:SF 2 "s_register_operand")
+ (match_operand:SF 3 "s_register_operand")))]
"TARGET_32BIT && TARGET_HARD_FLOAT"
"
{
@@ -7934,10 +7937,10 @@
)
(define_expand "movdfcc"
- [(set (match_operand:DF 0 "s_register_operand" "")
- (if_then_else:DF (match_operand 1 "arm_cond_move_operator" "")
- (match_operand:DF 2 "s_register_operand" "")
- (match_operand:DF 3 "s_register_operand" "")))]
+ [(set (match_operand:DF 0 "s_register_operand")
+ (if_then_else:DF (match_operand 1 "arm_cond_move_operator")
+ (match_operand:DF 2 "s_register_operand")
+ (match_operand:DF 3 "s_register_operand")))]
"TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
"
{
@@ -8133,8 +8136,8 @@
)
(define_expand "call"
- [(parallel [(call (match_operand 0 "memory_operand" "")
- (match_operand 1 "general_operand" ""))
+ [(parallel [(call (match_operand 0 "memory_operand")
+ (match_operand 1 "general_operand"))
(use (match_operand 2 "" ""))
(clobber (reg:SI LR_REGNUM))])]
"TARGET_EITHER"
@@ -8172,15 +8175,15 @@
)
(define_expand "call_internal"
- [(parallel [(call (match_operand 0 "memory_operand" "")
- (match_operand 1 "general_operand" ""))
+ [(parallel [(call (match_operand 0 "memory_operand")
+ (match_operand 1 "general_operand"))
(use (match_operand 2 "" ""))
(clobber (reg:SI LR_REGNUM))])])
(define_expand "nonsecure_call_internal"
- [(parallel [(call (unspec:SI [(match_operand 0 "memory_operand" "")]
+ [(parallel [(call (unspec:SI [(match_operand 0 "memory_operand")]
UNSPEC_NONSECURE_MEM)
- (match_operand 1 "general_operand" ""))
+ (match_operand 1 "general_operand"))
(use (match_operand 2 "" ""))
(clobber (reg:SI LR_REGNUM))])]
"use_cmse"
@@ -8221,8 +8224,8 @@
(define_expand "call_value"
[(parallel [(set (match_operand 0 "" "")
- (call (match_operand 1 "memory_operand" "")
- (match_operand 2 "general_operand" "")))
+ (call (match_operand 1 "memory_operand")
+ (match_operand 2 "general_operand")))
(use (match_operand 3 "" ""))
(clobber (reg:SI LR_REGNUM))])]
"TARGET_EITHER"
@@ -8262,16 +8265,16 @@
(define_expand "call_value_internal"
[(parallel [(set (match_operand 0 "" "")
- (call (match_operand 1 "memory_operand" "")
- (match_operand 2 "general_operand" "")))
+ (call (match_operand 1 "memory_operand")
+ (match_operand 2 "general_operand")))
(use (match_operand 3 "" ""))
(clobber (reg:SI LR_REGNUM))])])
(define_expand "nonsecure_call_value_internal"
[(parallel [(set (match_operand 0 "" "")
- (call (unspec:SI [(match_operand 1 "memory_operand" "")]
+ (call (unspec:SI [(match_operand 1 "memory_operand")]
UNSPEC_NONSECURE_MEM)
- (match_operand 2 "general_operand" "")))
+ (match_operand 2 "general_operand")))
(use (match_operand 3 "" ""))
(clobber (reg:SI LR_REGNUM))])]
"use_cmse"
@@ -8361,15 +8364,15 @@
)
(define_expand "sibcall_internal"
- [(parallel [(call (match_operand 0 "memory_operand" "")
- (match_operand 1 "general_operand" ""))
+ [(parallel [(call (match_operand 0 "memory_operand")
+ (match_operand 1 "general_operand"))
(return)
(use (match_operand 2 "" ""))])])
;; We may also be able to do sibcalls for Thumb, but it's much harder...
(define_expand "sibcall"
- [(parallel [(call (match_operand 0 "memory_operand" "")
- (match_operand 1 "general_operand" ""))
+ [(parallel [(call (match_operand 0 "memory_operand")
+ (match_operand 1 "general_operand"))
(return)
(use (match_operand 2 "" ""))])]
"TARGET_32BIT"
@@ -8394,15 +8397,15 @@
(define_expand "sibcall_value_internal"
[(parallel [(set (match_operand 0 "" "")
- (call (match_operand 1 "memory_operand" "")
- (match_operand 2 "general_operand" "")))
+ (call (match_operand 1 "memory_operand")
+ (match_operand 2 "general_operand")))
(return)
(use (match_operand 3 "" ""))])])
(define_expand "sibcall_value"
[(parallel [(set (match_operand 0 "" "")
- (call (match_operand 1 "memory_operand" "")
- (match_operand 2 "general_operand" "")))
+ (call (match_operand 1 "memory_operand")
+ (match_operand 2 "general_operand")))
(return)
(use (match_operand 3 "" ""))])]
"TARGET_32BIT"
@@ -8571,7 +8574,7 @@
[(set (match_dup 1)
(compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
(const_int 0)))
- (set (match_operand:SI 0 "s_register_operand" "")
+ (set (match_operand:SI 0 "s_register_operand")
(if_then_else:SI (eq (match_dup 1) (const_int 0))
(const_int -1)
(const_int 67108860)))] ; 0x03fffffc
@@ -8663,7 +8666,7 @@
)
(define_expand "untyped_return"
- [(match_operand:BLK 0 "memory_operand" "")
+ [(match_operand:BLK 0 "memory_operand")
(match_operand 1 "" "")]
"TARGET_EITHER"
"
@@ -8749,8 +8752,8 @@
;; Named patterns for stack smashing protection.
(define_expand "stack_protect_combined_set"
[(parallel
- [(set (match_operand:SI 0 "memory_operand" "")
- (unspec:SI [(match_operand:SI 1 "guard_operand" "")]
+ [(set (match_operand:SI 0 "memory_operand")
+ (unspec:SI [(match_operand:SI 1 "guard_operand")]
UNSPEC_SP_SET))
(clobber (match_scratch:SI 2 ""))
(clobber (match_scratch:SI 3 ""))])]
@@ -8816,8 +8819,8 @@
[(parallel
[(set (pc)
(if_then_else
- (eq (match_operand:SI 0 "memory_operand" "")
- (unspec:SI [(match_operand:SI 1 "guard_operand" "")]
+ (eq (match_operand:SI 0 "memory_operand")
+ (unspec:SI [(match_operand:SI 1 "guard_operand")]
UNSPEC_SP_TEST))
(label_ref (match_operand 2))
(pc)))
@@ -8905,9 +8908,9 @@
)
(define_expand "casesi"
- [(match_operand:SI 0 "s_register_operand" "") ; index to jump on
- (match_operand:SI 1 "const_int_operand" "") ; lower bound
- (match_operand:SI 2 "const_int_operand" "") ; total range
+ [(match_operand:SI 0 "s_register_operand") ; index to jump on
+ (match_operand:SI 1 "const_int_operand") ; lower bound
+ (match_operand:SI 2 "const_int_operand") ; total range
(match_operand:SI 3 "" "") ; table label
(match_operand:SI 4 "" "")] ; Out of range label
"(TARGET_32BIT || optimize_size || flag_pic) && !target_pure_code"
@@ -8986,7 +8989,7 @@
(define_expand "indirect_jump"
[(set (pc)
- (match_operand:SI 0 "s_register_operand" ""))]
+ (match_operand:SI 0 "s_register_operand"))]
"TARGET_EITHER"
"
/* Thumb-2 doesn't have mov pc, reg. Explicitly set the low bit of the
@@ -11041,9 +11044,9 @@
)
(define_expand "eh_epilogue"
- [(use (match_operand:SI 0 "register_operand" ""))
- (use (match_operand:SI 1 "register_operand" ""))
- (use (match_operand:SI 2 "register_operand" ""))]
+ [(use (match_operand:SI 0 "register_operand"))
+ (use (match_operand:SI 1 "register_operand"))
+ (use (match_operand:SI 2 "register_operand"))]
"TARGET_EITHER"
"
{
@@ -11628,7 +11631,7 @@
;; Patterns for exception handling
(define_expand "eh_return"
- [(use (match_operand 0 "general_operand" ""))]
+ [(use (match_operand 0 "general_operand"))]
"TARGET_EITHER"
"
{
@@ -11702,7 +11705,7 @@
;; For thread pointer builtin
(define_expand "get_thread_pointersi"
- [(match_operand:SI 0 "s_register_operand" "=r")]
+ [(match_operand:SI 0 "s_register_operand")]
""
"
{
@@ -11744,20 +11747,20 @@
)
(define_expand "arm_legacy_rev"
- [(set (match_operand:SI 2 "s_register_operand" "")
- (xor:SI (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
+ [(set (match_operand:SI 2 "s_register_operand")
+ (xor:SI (rotatert:SI (match_operand:SI 1 "s_register_operand")
(const_int 16))
(match_dup 1)))
(set (match_dup 2)
(lshiftrt:SI (match_dup 2)
(const_int 8)))
- (set (match_operand:SI 3 "s_register_operand" "")
+ (set (match_operand:SI 3 "s_register_operand")
(rotatert:SI (match_dup 1)
(const_int 8)))
(set (match_dup 2)
(and:SI (match_dup 2)
(const_int -65281)))
- (set (match_operand:SI 0 "s_register_operand" "")
+ (set (match_operand:SI 0 "s_register_operand")
(xor:SI (match_dup 3)
(match_dup 2)))]
"TARGET_32BIT"
@@ -11766,18 +11769,18 @@
;; Reuse temporaries to keep register pressure down.
(define_expand "thumb_legacy_rev"
- [(set (match_operand:SI 2 "s_register_operand" "")
- (ashift:SI (match_operand:SI 1 "s_register_operand" "")
+ [(set (match_operand:SI 2 "s_register_operand")
+ (ashift:SI (match_operand:SI 1 "s_register_operand")
(const_int 24)))
- (set (match_operand:SI 3 "s_register_operand" "")
+ (set (match_operand:SI 3 "s_register_operand")
(lshiftrt:SI (match_dup 1)
(const_int 24)))
(set (match_dup 3)
(ior:SI (match_dup 3)
(match_dup 2)))
- (set (match_operand:SI 4 "s_register_operand" "")
+ (set (match_operand:SI 4 "s_register_operand")
(const_int 16))
- (set (match_operand:SI 5 "s_register_operand" "")
+ (set (match_operand:SI 5 "s_register_operand")
(rotatert:SI (match_dup 1)
(match_dup 4)))
(set (match_dup 2)
@@ -11792,7 +11795,7 @@
(set (match_dup 5)
(rotatert:SI (match_dup 5)
(match_dup 4)))
- (set (match_operand:SI 0 "s_register_operand" "")
+ (set (match_operand:SI 0 "s_register_operand")
(ior:SI (match_dup 5)
(match_dup 3)))]
"TARGET_THUMB"
@@ -11808,9 +11811,9 @@
;; rsbpl r0, r1, #0
(define_expand "modsi3"
- [(match_operand:SI 0 "register_operand" "")
- (match_operand:SI 1 "register_operand" "")
- (match_operand:SI 2 "const_int_operand" "")]
+ [(match_operand:SI 0 "register_operand")
+ (match_operand:SI 1 "register_operand")
+ (match_operand:SI 2 "const_int_operand")]
"TARGET_32BIT"
{
HOST_WIDE_INT val = INTVAL (operands[2]);
@@ -11869,8 +11872,8 @@
)
(define_expand "bswapsi2"
- [(set (match_operand:SI 0 "s_register_operand" "=r")
- (bswap:SI (match_operand:SI 1 "s_register_operand" "r")))]
+ [(set (match_operand:SI 0 "s_register_operand")
+ (bswap:SI (match_operand:SI 1 "s_register_operand")))]
"TARGET_EITHER && (arm_arch6 || !optimize_size)"
"
if (!arm_arch6)
@@ -11965,8 +11968,8 @@
)
(define_expand "bswaphi2"
- [(set (match_operand:HI 0 "s_register_operand" "=r")
- (bswap:HI (match_operand:HI 1 "s_register_operand" "r")))]
+ [(set (match_operand:HI 0 "s_register_operand")
+ (bswap:HI (match_operand:HI 1 "s_register_operand")))]
"arm_arch6"
""
)
diff --git a/gcc/config/arm/cortex-a57.md b/gcc/config/arm/cortex-a57.md
index 577dc8d..a5f0b10 100644
--- a/gcc/config/arm/cortex-a57.md
+++ b/gcc/config/arm/cortex-a57.md
@@ -236,7 +236,12 @@
neon_store1_4reg, neon_store1_4reg_q,\
neon_store1_one_lane, neon_store1_one_lane_q,\
neon_store2_one_lane, neon_store2_one_lane_q")
- (const_string "neon_store_complex")]
+ (const_string "neon_store_complex")
+;; If it doesn't match any of the above that we want to treat specially but is
+;; still a NEON type, treat it as a basic NEON type. This is better than
+;; dropping it on the floor and making no assumptions about it whatsoever.
+ (eq_attr "is_neon_type" "yes")
+ (const_string "neon_arith_basic")]
(const_string "unknown")))
;; The Cortex-A57 core is modelled as a triple issue pipeline that has
diff --git a/gcc/config/arm/iterators.md b/gcc/config/arm/iterators.md
index eb07c5b..2462b8c 100644
--- a/gcc/config/arm/iterators.md
+++ b/gcc/config/arm/iterators.md
@@ -341,6 +341,8 @@
(define_int_iterator VSUBHN [UNSPEC_VSUBHN UNSPEC_VRSUBHN])
+(define_int_iterator VABAL [UNSPEC_VABAL_S UNSPEC_VABAL_U])
+
(define_int_iterator VABD [UNSPEC_VABD_S UNSPEC_VABD_U])
(define_int_iterator VABDL [UNSPEC_VABDL_S UNSPEC_VABDL_U])
@@ -834,6 +836,7 @@
(UNSPEC_VSUBW_S "s") (UNSPEC_VSUBW_U "u")
(UNSPEC_VHSUB_S "s") (UNSPEC_VHSUB_U "u")
(UNSPEC_VQSUB_S "s") (UNSPEC_VQSUB_U "u")
+ (UNSPEC_VABAL_S "s") (UNSPEC_VABAL_U "u")
(UNSPEC_VABD_S "s") (UNSPEC_VABD_U "u")
(UNSPEC_VABDL_S "s") (UNSPEC_VABDL_U "u")
(UNSPEC_VMAX "s") (UNSPEC_VMAX_U "u")
diff --git a/gcc/config/arm/iwmmxt.md b/gcc/config/arm/iwmmxt.md
index 65f9b32..310019a 100644
--- a/gcc/config/arm/iwmmxt.md
+++ b/gcc/config/arm/iwmmxt.md
@@ -256,55 +256,55 @@
(define_expand "iwmmxt_setwcgr0"
[(set (reg:SI WCGR0)
- (match_operand:SI 0 "register_operand" ""))]
+ (match_operand:SI 0 "register_operand"))]
"TARGET_REALLY_IWMMXT"
{}
)
(define_expand "iwmmxt_setwcgr1"
[(set (reg:SI WCGR1)
- (match_operand:SI 0 "register_operand" ""))]
+ (match_operand:SI 0 "register_operand"))]
"TARGET_REALLY_IWMMXT"
{}
)
(define_expand "iwmmxt_setwcgr2"
[(set (reg:SI WCGR2)
- (match_operand:SI 0 "register_operand" ""))]
+ (match_operand:SI 0 "register_operand"))]
"TARGET_REALLY_IWMMXT"
{}
)
(define_expand "iwmmxt_setwcgr3"
[(set (reg:SI WCGR3)
- (match_operand:SI 0 "register_operand" ""))]
+ (match_operand:SI 0 "register_operand"))]
"TARGET_REALLY_IWMMXT"
{}
)
(define_expand "iwmmxt_getwcgr0"
- [(set (match_operand:SI 0 "register_operand" "")
+ [(set (match_operand:SI 0 "register_operand")
(reg:SI WCGR0))]
"TARGET_REALLY_IWMMXT"
{}
)
(define_expand "iwmmxt_getwcgr1"
- [(set (match_operand:SI 0 "register_operand" "")
+ [(set (match_operand:SI 0 "register_operand")
(reg:SI WCGR1))]
"TARGET_REALLY_IWMMXT"
{}
)
(define_expand "iwmmxt_getwcgr2"
- [(set (match_operand:SI 0 "register_operand" "")
+ [(set (match_operand:SI 0 "register_operand")
(reg:SI WCGR2))]
"TARGET_REALLY_IWMMXT"
{}
)
(define_expand "iwmmxt_getwcgr3"
- [(set (match_operand:SI 0 "register_operand" "")
+ [(set (match_operand:SI 0 "register_operand")
(reg:SI WCGR3))]
"TARGET_REALLY_IWMMXT"
{}
diff --git a/gcc/config/arm/neon.md b/gcc/config/arm/neon.md
index 726b728..4bfe770 100644
--- a/gcc/config/arm/neon.md
+++ b/gcc/config/arm/neon.md
@@ -123,8 +123,8 @@
sub-reg and may ICE if it can't. */
(define_expand "movti"
- [(set (match_operand:TI 0 "nonimmediate_operand" "")
- (match_operand:TI 1 "general_operand" ""))]
+ [(set (match_operand:TI 0 "nonimmediate_operand")
+ (match_operand:TI 1 "general_operand"))]
"TARGET_NEON"
{
if (can_create_pseudo_p ())
@@ -135,8 +135,8 @@
})
(define_expand "mov<mode>"
- [(set (match_operand:VSTRUCT 0 "nonimmediate_operand" "")
- (match_operand:VSTRUCT 1 "general_operand" ""))]
+ [(set (match_operand:VSTRUCT 0 "nonimmediate_operand")
+ (match_operand:VSTRUCT 1 "general_operand"))]
"TARGET_NEON"
{
if (can_create_pseudo_p ())
@@ -392,9 +392,9 @@
)
(define_expand "vec_set<mode>"
- [(match_operand:VDQ 0 "s_register_operand" "")
- (match_operand:<V_elem> 1 "s_register_operand" "")
- (match_operand:SI 2 "immediate_operand" "")]
+ [(match_operand:VDQ 0 "s_register_operand")
+ (match_operand:<V_elem> 1 "s_register_operand")
+ (match_operand:SI 2 "immediate_operand")]
"TARGET_NEON"
{
HOST_WIDE_INT elem = HOST_WIDE_INT_1 << INTVAL (operands[2]);
@@ -471,7 +471,7 @@
)
(define_expand "vec_init<mode><V_elem_l>"
- [(match_operand:VDQ 0 "s_register_operand" "")
+ [(match_operand:VDQ 0 "s_register_operand")
(match_operand 1 "" "")]
"TARGET_NEON"
{
@@ -628,9 +628,9 @@
and disabled for -Os since it increases code size . */
(define_expand "div<mode>3"
- [(set (match_operand:VCVTF 0 "s_register_operand" "=w")
- (div:VCVTF (match_operand:VCVTF 1 "s_register_operand" "w")
- (match_operand:VCVTF 2 "s_register_operand" "w")))]
+ [(set (match_operand:VCVTF 0 "s_register_operand")
+ (div:VCVTF (match_operand:VCVTF 1 "s_register_operand")
+ (match_operand:VCVTF 2 "s_register_operand")))]
"TARGET_NEON && !optimize_size
&& flag_reciprocal_math"
{
@@ -1138,9 +1138,9 @@
)
(define_expand "vashr<mode>3"
- [(set (match_operand:VDQIW 0 "s_register_operand" "")
- (ashiftrt:VDQIW (match_operand:VDQIW 1 "s_register_operand" "")
- (match_operand:VDQIW 2 "imm_rshift_or_reg_neon" "")))]
+ [(set (match_operand:VDQIW 0 "s_register_operand")
+ (ashiftrt:VDQIW (match_operand:VDQIW 1 "s_register_operand")
+ (match_operand:VDQIW 2 "imm_rshift_or_reg_neon")))]
"TARGET_NEON"
{
if (s_register_operand (operands[2], <MODE>mode))
@@ -1155,9 +1155,9 @@
})
(define_expand "vlshr<mode>3"
- [(set (match_operand:VDQIW 0 "s_register_operand" "")
- (lshiftrt:VDQIW (match_operand:VDQIW 1 "s_register_operand" "")
- (match_operand:VDQIW 2 "imm_rshift_or_reg_neon" "")))]
+ [(set (match_operand:VDQIW 0 "s_register_operand")
+ (lshiftrt:VDQIW (match_operand:VDQIW 1 "s_register_operand")
+ (match_operand:VDQIW 2 "imm_rshift_or_reg_neon")))]
"TARGET_NEON"
{
if (s_register_operand (operands[2], <MODE>mode))
@@ -1359,11 +1359,11 @@
;; Widening operations
(define_expand "widen_ssum<mode>3"
- [(set (match_operand:<V_double_width> 0 "s_register_operand" "")
+ [(set (match_operand:<V_double_width> 0 "s_register_operand")
(plus:<V_double_width>
(sign_extend:<V_double_width>
- (match_operand:VQI 1 "s_register_operand" ""))
- (match_operand:<V_double_width> 2 "s_register_operand" "")))]
+ (match_operand:VQI 1 "s_register_operand"))
+ (match_operand:<V_double_width> 2 "s_register_operand")))]
"TARGET_NEON"
{
machine_mode mode = GET_MODE (operands[1]);
@@ -1429,11 +1429,11 @@
)
(define_expand "widen_usum<mode>3"
- [(set (match_operand:<V_double_width> 0 "s_register_operand" "")
+ [(set (match_operand:<V_double_width> 0 "s_register_operand")
(plus:<V_double_width>
(zero_extend:<V_double_width>
- (match_operand:VQI 1 "s_register_operand" ""))
- (match_operand:<V_double_width> 2 "s_register_operand" "")))]
+ (match_operand:VQI 1 "s_register_operand"))
+ (match_operand:<V_double_width> 2 "s_register_operand")))]
"TARGET_NEON"
{
machine_mode mode = GET_MODE (operands[1]);
@@ -1564,8 +1564,8 @@
)
(define_expand "move_hi_quad_<mode>"
- [(match_operand:ANY128 0 "s_register_operand" "")
- (match_operand:<V_HALF> 1 "s_register_operand" "")]
+ [(match_operand:ANY128 0 "s_register_operand")
+ (match_operand:<V_HALF> 1 "s_register_operand")]
"TARGET_NEON"
{
emit_move_insn (simplify_gen_subreg (<V_HALF>mode, operands[0], <MODE>mode,
@@ -1575,8 +1575,8 @@
})
(define_expand "move_lo_quad_<mode>"
- [(match_operand:ANY128 0 "s_register_operand" "")
- (match_operand:<V_HALF> 1 "s_register_operand" "")]
+ [(match_operand:ANY128 0 "s_register_operand")
+ (match_operand:<V_HALF> 1 "s_register_operand")]
"TARGET_NEON"
{
emit_move_insn (simplify_gen_subreg (<V_HALF>mode, operands[0],
@@ -1588,8 +1588,8 @@
;; Reduction operations
(define_expand "reduc_plus_scal_<mode>"
- [(match_operand:<V_elem> 0 "nonimmediate_operand" "")
- (match_operand:VD 1 "s_register_operand" "")]
+ [(match_operand:<V_elem> 0 "nonimmediate_operand")
+ (match_operand:VD 1 "s_register_operand")]
"TARGET_NEON && (!<Is_float_mode> || flag_unsafe_math_optimizations)"
{
rtx vec = gen_reg_rtx (<MODE>mode);
@@ -1601,8 +1601,8 @@
})
(define_expand "reduc_plus_scal_<mode>"
- [(match_operand:<V_elem> 0 "nonimmediate_operand" "")
- (match_operand:VQ 1 "s_register_operand" "")]
+ [(match_operand:<V_elem> 0 "nonimmediate_operand")
+ (match_operand:VQ 1 "s_register_operand")]
"TARGET_NEON && (!<Is_float_mode> || flag_unsafe_math_optimizations)
&& !BYTES_BIG_ENDIAN"
{
@@ -1615,8 +1615,8 @@
})
(define_expand "reduc_plus_scal_v2di"
- [(match_operand:DI 0 "nonimmediate_operand" "=w")
- (match_operand:V2DI 1 "s_register_operand" "")]
+ [(match_operand:DI 0 "nonimmediate_operand")
+ (match_operand:V2DI 1 "s_register_operand")]
"TARGET_NEON && !BYTES_BIG_ENDIAN"
{
rtx vec = gen_reg_rtx (V2DImode);
@@ -1637,8 +1637,8 @@
)
(define_expand "reduc_smin_scal_<mode>"
- [(match_operand:<V_elem> 0 "nonimmediate_operand" "")
- (match_operand:VD 1 "s_register_operand" "")]
+ [(match_operand:<V_elem> 0 "nonimmediate_operand")
+ (match_operand:VD 1 "s_register_operand")]
"TARGET_NEON && (!<Is_float_mode> || flag_unsafe_math_optimizations)"
{
rtx vec = gen_reg_rtx (<MODE>mode);
@@ -1651,8 +1651,8 @@
})
(define_expand "reduc_smin_scal_<mode>"
- [(match_operand:<V_elem> 0 "nonimmediate_operand" "")
- (match_operand:VQ 1 "s_register_operand" "")]
+ [(match_operand:<V_elem> 0 "nonimmediate_operand")
+ (match_operand:VQ 1 "s_register_operand")]
"TARGET_NEON && (!<Is_float_mode> || flag_unsafe_math_optimizations)
&& !BYTES_BIG_ENDIAN"
{
@@ -1665,8 +1665,8 @@
})
(define_expand "reduc_smax_scal_<mode>"
- [(match_operand:<V_elem> 0 "nonimmediate_operand" "")
- (match_operand:VD 1 "s_register_operand" "")]
+ [(match_operand:<V_elem> 0 "nonimmediate_operand")
+ (match_operand:VD 1 "s_register_operand")]
"TARGET_NEON && (!<Is_float_mode> || flag_unsafe_math_optimizations)"
{
rtx vec = gen_reg_rtx (<MODE>mode);
@@ -1678,8 +1678,8 @@
})
(define_expand "reduc_smax_scal_<mode>"
- [(match_operand:<V_elem> 0 "nonimmediate_operand" "")
- (match_operand:VQ 1 "s_register_operand" "")]
+ [(match_operand:<V_elem> 0 "nonimmediate_operand")
+ (match_operand:VQ 1 "s_register_operand")]
"TARGET_NEON && (!<Is_float_mode> || flag_unsafe_math_optimizations)
&& !BYTES_BIG_ENDIAN"
{
@@ -1692,8 +1692,8 @@
})
(define_expand "reduc_umin_scal_<mode>"
- [(match_operand:<V_elem> 0 "nonimmediate_operand" "")
- (match_operand:VDI 1 "s_register_operand" "")]
+ [(match_operand:<V_elem> 0 "nonimmediate_operand")
+ (match_operand:VDI 1 "s_register_operand")]
"TARGET_NEON"
{
rtx vec = gen_reg_rtx (<MODE>mode);
@@ -1705,8 +1705,8 @@
})
(define_expand "reduc_umin_scal_<mode>"
- [(match_operand:<V_elem> 0 "nonimmediate_operand" "")
- (match_operand:VQI 1 "s_register_operand" "")]
+ [(match_operand:<V_elem> 0 "nonimmediate_operand")
+ (match_operand:VQI 1 "s_register_operand")]
"TARGET_NEON && !BYTES_BIG_ENDIAN"
{
rtx step1 = gen_reg_rtx (<V_HALF>mode);
@@ -1718,8 +1718,8 @@
})
(define_expand "reduc_umax_scal_<mode>"
- [(match_operand:<V_elem> 0 "nonimmediate_operand" "")
- (match_operand:VDI 1 "s_register_operand" "")]
+ [(match_operand:<V_elem> 0 "nonimmediate_operand")
+ (match_operand:VDI 1 "s_register_operand")]
"TARGET_NEON"
{
rtx vec = gen_reg_rtx (<MODE>mode);
@@ -1731,8 +1731,8 @@
})
(define_expand "reduc_umax_scal_<mode>"
- [(match_operand:<V_elem> 0 "nonimmediate_operand" "")
- (match_operand:VQI 1 "s_register_operand" "")]
+ [(match_operand:<V_elem> 0 "nonimmediate_operand")
+ (match_operand:VQI 1 "s_register_operand")]
"TARGET_NEON && !BYTES_BIG_ENDIAN"
{
rtx step1 = gen_reg_rtx (<V_HALF>mode);
@@ -1867,13 +1867,13 @@
;; element-wise.
(define_expand "vcond<mode><mode>"
- [(set (match_operand:VDQW 0 "s_register_operand" "")
+ [(set (match_operand:VDQW 0 "s_register_operand")
(if_then_else:VDQW
(match_operator 3 "comparison_operator"
- [(match_operand:VDQW 4 "s_register_operand" "")
- (match_operand:VDQW 5 "nonmemory_operand" "")])
- (match_operand:VDQW 1 "s_register_operand" "")
- (match_operand:VDQW 2 "s_register_operand" "")))]
+ [(match_operand:VDQW 4 "s_register_operand")
+ (match_operand:VDQW 5 "nonmemory_operand")])
+ (match_operand:VDQW 1 "s_register_operand")
+ (match_operand:VDQW 2 "s_register_operand")))]
"TARGET_NEON && (!<Is_float_mode> || flag_unsafe_math_optimizations)"
{
int inverse = 0;
@@ -2032,13 +2032,13 @@
})
(define_expand "vcondu<mode><mode>"
- [(set (match_operand:VDQIW 0 "s_register_operand" "")
+ [(set (match_operand:VDQIW 0 "s_register_operand")
(if_then_else:VDQIW
(match_operator 3 "arm_comparison_operator"
- [(match_operand:VDQIW 4 "s_register_operand" "")
- (match_operand:VDQIW 5 "s_register_operand" "")])
- (match_operand:VDQIW 1 "s_register_operand" "")
- (match_operand:VDQIW 2 "s_register_operand" "")))]
+ [(match_operand:VDQIW 4 "s_register_operand")
+ (match_operand:VDQIW 5 "s_register_operand")])
+ (match_operand:VDQIW 1 "s_register_operand")
+ (match_operand:VDQIW 2 "s_register_operand")))]
"TARGET_NEON"
{
rtx mask;
@@ -2103,9 +2103,9 @@
; good for plain vadd, vaddq.
(define_expand "neon_vadd<mode>"
- [(match_operand:VCVTF 0 "s_register_operand" "=w")
- (match_operand:VCVTF 1 "s_register_operand" "w")
- (match_operand:VCVTF 2 "s_register_operand" "w")]
+ [(match_operand:VCVTF 0 "s_register_operand")
+ (match_operand:VCVTF 1 "s_register_operand")
+ (match_operand:VCVTF 2 "s_register_operand")]
"TARGET_NEON"
{
if (!<Is_float_mode> || flag_unsafe_math_optimizations)
@@ -2250,10 +2250,10 @@
)
(define_expand "neon_vmla<mode>"
- [(match_operand:VDQW 0 "s_register_operand" "=w")
- (match_operand:VDQW 1 "s_register_operand" "0")
- (match_operand:VDQW 2 "s_register_operand" "w")
- (match_operand:VDQW 3 "s_register_operand" "w")]
+ [(match_operand:VDQW 0 "s_register_operand")
+ (match_operand:VDQW 1 "s_register_operand")
+ (match_operand:VDQW 2 "s_register_operand")
+ (match_operand:VDQW 3 "s_register_operand")]
"TARGET_NEON"
{
if (!<Is_float_mode> || flag_unsafe_math_optimizations)
@@ -2741,10 +2741,10 @@
)
(define_expand "neon_vmls<mode>"
- [(match_operand:VDQW 0 "s_register_operand" "=w")
- (match_operand:VDQW 1 "s_register_operand" "0")
- (match_operand:VDQW 2 "s_register_operand" "w")
- (match_operand:VDQW 3 "s_register_operand" "w")]
+ [(match_operand:VDQW 0 "s_register_operand")
+ (match_operand:VDQW 1 "s_register_operand")
+ (match_operand:VDQW 2 "s_register_operand")
+ (match_operand:VDQW 3 "s_register_operand")]
"TARGET_NEON"
{
if (!<Is_float_mode> || flag_unsafe_math_optimizations)
@@ -2849,9 +2849,9 @@
)
(define_expand "neon_vsub<mode>"
- [(match_operand:VCVTF 0 "s_register_operand" "=w")
- (match_operand:VCVTF 1 "s_register_operand" "w")
- (match_operand:VCVTF 2 "s_register_operand" "w")]
+ [(match_operand:VCVTF 0 "s_register_operand")
+ (match_operand:VCVTF 1 "s_register_operand")
+ (match_operand:VCVTF 2 "s_register_operand")]
"TARGET_NEON"
{
if (!<Is_float_mode> || flag_unsafe_math_optimizations)
@@ -2930,10 +2930,10 @@
;; These may expand to an UNSPEC pattern when a floating point mode is used
;; without unsafe math optimizations.
(define_expand "neon_vc<cmp_op><mode>"
- [(match_operand:<V_cmp_result> 0 "s_register_operand" "=w,w")
+ [(match_operand:<V_cmp_result> 0 "s_register_operand")
(neg:<V_cmp_result>
- (COMPARISONS:VDQW (match_operand:VDQW 1 "s_register_operand" "w,w")
- (match_operand:VDQW 2 "reg_or_zero_operand" "w,Dz")))]
+ (COMPARISONS:VDQW (match_operand:VDQW 1 "s_register_operand")
+ (match_operand:VDQW 2 "reg_or_zero_operand")))]
"TARGET_NEON"
{
/* For FP comparisons use UNSPECS unless -funsafe-math-optimizations
@@ -3256,6 +3256,32 @@
[(set_attr "type" "neon_arith_acc<q>")]
)
+(define_expand "<sup>sadv16qi"
+ [(use (match_operand:V4SI 0 "register_operand"))
+ (unspec:V16QI [(use (match_operand:V16QI 1 "register_operand"))
+ (use (match_operand:V16QI 2 "register_operand"))] VABAL)
+ (use (match_operand:V4SI 3 "register_operand"))]
+ "TARGET_NEON"
+ {
+ rtx reduc = gen_reg_rtx (V8HImode);
+ rtx op1_highpart = gen_reg_rtx (V8QImode);
+ rtx op2_highpart = gen_reg_rtx (V8QImode);
+
+ emit_insn (gen_neon_vabdl<sup>v8qi (reduc,
+ gen_lowpart (V8QImode, operands[1]),
+ gen_lowpart (V8QImode, operands[2])));
+
+ emit_insn (gen_neon_vget_highv16qi (op1_highpart, operands[1]));
+ emit_insn (gen_neon_vget_highv16qi (op2_highpart, operands[2]));
+ emit_insn (gen_neon_vabal<sup>v8qi (reduc, reduc,
+ op1_highpart, op2_highpart));
+ emit_insn (gen_neon_vpadal<sup>v8hi (operands[3], operands[3], reduc));
+
+ emit_move_insn (operands[0], operands[3]);
+ DONE;
+ }
+)
+
(define_insn "neon_v<maxmin><sup><mode>"
[(set (match_operand:VDQIW 0 "s_register_operand" "=w")
(unspec:VDQIW [(match_operand:VDQIW 1 "s_register_operand" "w")
@@ -3333,9 +3359,9 @@
)
(define_expand "neon_vpadd<mode>"
- [(match_operand:VD 0 "s_register_operand" "=w")
- (match_operand:VD 1 "s_register_operand" "w")
- (match_operand:VD 2 "s_register_operand" "w")]
+ [(match_operand:VD 0 "s_register_operand")
+ (match_operand:VD 1 "s_register_operand")
+ (match_operand:VD 2 "s_register_operand")]
"TARGET_NEON"
{
emit_insn (gen_neon_vpadd_internal<mode> (operands[0], operands[1],
@@ -3425,8 +3451,8 @@
)
(define_expand "neon_vabs<mode>"
- [(match_operand:VDQW 0 "s_register_operand" "")
- (match_operand:VDQW 1 "s_register_operand" "")]
+ [(match_operand:VDQW 0 "s_register_operand")
+ (match_operand:VDQW 1 "s_register_operand")]
"TARGET_NEON"
{
emit_insn (gen_abs<mode>2 (operands[0], operands[1]));
@@ -3451,8 +3477,8 @@
)
(define_expand "neon_vneg<mode>"
- [(match_operand:VDQW 0 "s_register_operand" "")
- (match_operand:VDQW 1 "s_register_operand" "")]
+ [(match_operand:VDQW 0 "s_register_operand")
+ (match_operand:VDQW 1 "s_register_operand")]
"TARGET_NEON"
{
emit_insn (gen_neg<mode>2 (operands[0], operands[1]));
@@ -3652,8 +3678,8 @@
)
(define_expand "neon_vclz<mode>"
- [(match_operand:VDQIW 0 "s_register_operand" "")
- (match_operand:VDQIW 1 "s_register_operand" "")]
+ [(match_operand:VDQIW 0 "s_register_operand")
+ (match_operand:VDQIW 1 "s_register_operand")]
"TARGET_NEON"
{
emit_insn (gen_clz<mode>2 (operands[0], operands[1]));
@@ -3669,8 +3695,8 @@
)
(define_expand "neon_vcnt<mode>"
- [(match_operand:VE 0 "s_register_operand" "=w")
- (match_operand:VE 1 "s_register_operand" "w")]
+ [(match_operand:VE 0 "s_register_operand")
+ (match_operand:VE 1 "s_register_operand")]
"TARGET_NEON"
{
emit_insn (gen_popcount<mode>2 (operands[0], operands[1]));
@@ -3705,8 +3731,8 @@
)
(define_expand "neon_vmvn<mode>"
- [(match_operand:VDQIW 0 "s_register_operand" "")
- (match_operand:VDQIW 1 "s_register_operand" "")]
+ [(match_operand:VDQIW 0 "s_register_operand")
+ (match_operand:VDQIW 1 "s_register_operand")]
"TARGET_NEON"
{
emit_insn (gen_one_cmpl<mode>2 (operands[0], operands[1]));
@@ -3806,9 +3832,9 @@
)
(define_expand "neon_vget_lane<mode>"
- [(match_operand:<V_ext> 0 "s_register_operand" "")
- (match_operand:VDQW 1 "s_register_operand" "")
- (match_operand:SI 2 "immediate_operand" "")]
+ [(match_operand:<V_ext> 0 "s_register_operand")
+ (match_operand:VDQW 1 "s_register_operand")
+ (match_operand:SI 2 "immediate_operand")]
"TARGET_NEON"
{
if (BYTES_BIG_ENDIAN)
@@ -3836,9 +3862,9 @@
})
(define_expand "neon_vget_laneu<mode>"
- [(match_operand:<V_ext> 0 "s_register_operand" "")
- (match_operand:VDQIW 1 "s_register_operand" "")
- (match_operand:SI 2 "immediate_operand" "")]
+ [(match_operand:<V_ext> 0 "s_register_operand")
+ (match_operand:VDQIW 1 "s_register_operand")
+ (match_operand:SI 2 "immediate_operand")]
"TARGET_NEON"
{
if (BYTES_BIG_ENDIAN)
@@ -3866,9 +3892,9 @@
})
(define_expand "neon_vget_lanedi"
- [(match_operand:DI 0 "s_register_operand" "=r")
- (match_operand:DI 1 "s_register_operand" "w")
- (match_operand:SI 2 "immediate_operand" "")]
+ [(match_operand:DI 0 "s_register_operand")
+ (match_operand:DI 1 "s_register_operand")
+ (match_operand:SI 2 "immediate_operand")]
"TARGET_NEON"
{
emit_move_insn (operands[0], operands[1]);
@@ -3876,9 +3902,9 @@
})
(define_expand "neon_vget_lanev2di"
- [(match_operand:DI 0 "s_register_operand" "")
- (match_operand:V2DI 1 "s_register_operand" "")
- (match_operand:SI 2 "immediate_operand" "")]
+ [(match_operand:DI 0 "s_register_operand")
+ (match_operand:V2DI 1 "s_register_operand")
+ (match_operand:SI 2 "immediate_operand")]
"TARGET_NEON"
{
int lane;
@@ -3905,10 +3931,10 @@ if (BYTES_BIG_ENDIAN)
})
(define_expand "neon_vset_lane<mode>"
- [(match_operand:VDQ 0 "s_register_operand" "=w")
- (match_operand:<V_elem> 1 "s_register_operand" "r")
- (match_operand:VDQ 2 "s_register_operand" "0")
- (match_operand:SI 3 "immediate_operand" "i")]
+ [(match_operand:VDQ 0 "s_register_operand")
+ (match_operand:<V_elem> 1 "s_register_operand")
+ (match_operand:VDQ 2 "s_register_operand")
+ (match_operand:SI 3 "immediate_operand")]
"TARGET_NEON"
{
unsigned int elt = INTVAL (operands[3]);
@@ -3928,10 +3954,10 @@ if (BYTES_BIG_ENDIAN)
; See neon_vget_lanedi comment for reasons operands 2 & 3 are ignored.
(define_expand "neon_vset_lanedi"
- [(match_operand:DI 0 "s_register_operand" "=w")
- (match_operand:DI 1 "s_register_operand" "r")
- (match_operand:DI 2 "s_register_operand" "0")
- (match_operand:SI 3 "immediate_operand" "i")]
+ [(match_operand:DI 0 "s_register_operand")
+ (match_operand:DI 1 "s_register_operand")
+ (match_operand:DI 2 "s_register_operand")
+ (match_operand:SI 3 "immediate_operand")]
"TARGET_NEON"
{
emit_move_insn (operands[0], operands[1]);
@@ -3939,8 +3965,8 @@ if (BYTES_BIG_ENDIAN)
})
(define_expand "neon_vcreate<mode>"
- [(match_operand:VD_RE 0 "s_register_operand" "")
- (match_operand:DI 1 "general_operand" "")]
+ [(match_operand:VD_RE 0 "s_register_operand")
+ (match_operand:DI 1 "general_operand")]
"TARGET_NEON"
{
rtx src = gen_lowpart (<MODE>mode, operands[1]);
@@ -3983,8 +4009,8 @@ if (BYTES_BIG_ENDIAN)
)
(define_expand "neon_vdup_ndi"
- [(match_operand:DI 0 "s_register_operand" "=w")
- (match_operand:DI 1 "s_register_operand" "r")]
+ [(match_operand:DI 0 "s_register_operand")
+ (match_operand:DI 1 "s_register_operand")]
"TARGET_NEON"
{
emit_move_insn (operands[0], operands[1]);
@@ -4048,9 +4074,9 @@ if (BYTES_BIG_ENDIAN)
)
(define_expand "neon_vdup_lane<mode>"
- [(match_operand:VDQW 0 "s_register_operand" "=w")
- (match_operand:<V_double_vector_mode> 1 "s_register_operand" "w")
- (match_operand:SI 2 "immediate_operand" "i")]
+ [(match_operand:VDQW 0 "s_register_operand")
+ (match_operand:<V_double_vector_mode> 1 "s_register_operand")
+ (match_operand:SI 2 "immediate_operand")]
"TARGET_NEON"
{
if (BYTES_BIG_ENDIAN)
@@ -4087,9 +4113,9 @@ if (BYTES_BIG_ENDIAN)
; Scalar index is ignored, since only zero is valid here.
(define_expand "neon_vdup_lanedi"
- [(match_operand:DI 0 "s_register_operand" "=w")
- (match_operand:DI 1 "s_register_operand" "w")
- (match_operand:SI 2 "immediate_operand" "i")]
+ [(match_operand:DI 0 "s_register_operand")
+ (match_operand:DI 1 "s_register_operand")
+ (match_operand:SI 2 "immediate_operand")]
"TARGET_NEON"
{
emit_move_insn (operands[0], operands[1]);
@@ -4098,9 +4124,9 @@ if (BYTES_BIG_ENDIAN)
; Likewise for v2di, as the DImode second operand has only a single element.
(define_expand "neon_vdup_lanev2di"
- [(match_operand:V2DI 0 "s_register_operand" "=w")
- (match_operand:DI 1 "s_register_operand" "w")
- (match_operand:SI 2 "immediate_operand" "i")]
+ [(match_operand:V2DI 0 "s_register_operand")
+ (match_operand:DI 1 "s_register_operand")
+ (match_operand:SI 2 "immediate_operand")]
"TARGET_NEON"
{
emit_insn (gen_neon_vdup_nv2di (operands[0], operands[1]));
@@ -4629,9 +4655,9 @@ if (BYTES_BIG_ENDIAN)
; using vld1_lane, but that hasn't been done yet.
(define_expand "neon_vmul_n<mode>"
- [(match_operand:VMD 0 "s_register_operand" "")
- (match_operand:VMD 1 "s_register_operand" "")
- (match_operand:<V_elem> 2 "s_register_operand" "")]
+ [(match_operand:VMD 0 "s_register_operand")
+ (match_operand:VMD 1 "s_register_operand")
+ (match_operand:<V_elem> 2 "s_register_operand")]
"TARGET_NEON"
{
rtx tmp = gen_reg_rtx (<MODE>mode);
@@ -4642,9 +4668,9 @@ if (BYTES_BIG_ENDIAN)
})
(define_expand "neon_vmul_n<mode>"
- [(match_operand:VMQ 0 "s_register_operand" "")
- (match_operand:VMQ 1 "s_register_operand" "")
- (match_operand:<V_elem> 2 "s_register_operand" "")]
+ [(match_operand:VMQ 0 "s_register_operand")
+ (match_operand:VMQ 1 "s_register_operand")
+ (match_operand:<V_elem> 2 "s_register_operand")]
"TARGET_NEON"
{
rtx tmp = gen_reg_rtx (<V_HALF>mode);
@@ -4668,9 +4694,9 @@ if (BYTES_BIG_ENDIAN)
})
(define_expand "neon_vmulls_n<mode>"
- [(match_operand:<V_widen> 0 "s_register_operand" "")
- (match_operand:VMDI 1 "s_register_operand" "")
- (match_operand:<V_elem> 2 "s_register_operand" "")]
+ [(match_operand:<V_widen> 0 "s_register_operand")
+ (match_operand:VMDI 1 "s_register_operand")
+ (match_operand:<V_elem> 2 "s_register_operand")]
"TARGET_NEON"
{
rtx tmp = gen_reg_rtx (<MODE>mode);
@@ -4681,9 +4707,9 @@ if (BYTES_BIG_ENDIAN)
})
(define_expand "neon_vmullu_n<mode>"
- [(match_operand:<V_widen> 0 "s_register_operand" "")
- (match_operand:VMDI 1 "s_register_operand" "")
- (match_operand:<V_elem> 2 "s_register_operand" "")]
+ [(match_operand:<V_widen> 0 "s_register_operand")
+ (match_operand:VMDI 1 "s_register_operand")
+ (match_operand:<V_elem> 2 "s_register_operand")]
"TARGET_NEON"
{
rtx tmp = gen_reg_rtx (<MODE>mode);
@@ -4694,9 +4720,9 @@ if (BYTES_BIG_ENDIAN)
})
(define_expand "neon_vqdmull_n<mode>"
- [(match_operand:<V_widen> 0 "s_register_operand" "")
- (match_operand:VMDI 1 "s_register_operand" "")
- (match_operand:<V_elem> 2 "s_register_operand" "")]
+ [(match_operand:<V_widen> 0 "s_register_operand")
+ (match_operand:VMDI 1 "s_register_operand")
+ (match_operand:<V_elem> 2 "s_register_operand")]
"TARGET_NEON"
{
rtx tmp = gen_reg_rtx (<MODE>mode);
@@ -4707,9 +4733,9 @@ if (BYTES_BIG_ENDIAN)
})
(define_expand "neon_vqdmulh_n<mode>"
- [(match_operand:VMDI 0 "s_register_operand" "")
- (match_operand:VMDI 1 "s_register_operand" "")
- (match_operand:<V_elem> 2 "s_register_operand" "")]
+ [(match_operand:VMDI 0 "s_register_operand")
+ (match_operand:VMDI 1 "s_register_operand")
+ (match_operand:<V_elem> 2 "s_register_operand")]
"TARGET_NEON"
{
rtx tmp = gen_reg_rtx (<MODE>mode);
@@ -4720,9 +4746,9 @@ if (BYTES_BIG_ENDIAN)
})
(define_expand "neon_vqrdmulh_n<mode>"
- [(match_operand:VMDI 0 "s_register_operand" "")
- (match_operand:VMDI 1 "s_register_operand" "")
- (match_operand:<V_elem> 2 "s_register_operand" "")]
+ [(match_operand:VMDI 0 "s_register_operand")
+ (match_operand:VMDI 1 "s_register_operand")
+ (match_operand:<V_elem> 2 "s_register_operand")]
"TARGET_NEON"
{
rtx tmp = gen_reg_rtx (<MODE>mode);
@@ -4733,9 +4759,9 @@ if (BYTES_BIG_ENDIAN)
})
(define_expand "neon_vqdmulh_n<mode>"
- [(match_operand:VMQI 0 "s_register_operand" "")
- (match_operand:VMQI 1 "s_register_operand" "")
- (match_operand:<V_elem> 2 "s_register_operand" "")]
+ [(match_operand:VMQI 0 "s_register_operand")
+ (match_operand:VMQI 1 "s_register_operand")
+ (match_operand:<V_elem> 2 "s_register_operand")]
"TARGET_NEON"
{
rtx tmp = gen_reg_rtx (<V_HALF>mode);
@@ -4746,9 +4772,9 @@ if (BYTES_BIG_ENDIAN)
})
(define_expand "neon_vqrdmulh_n<mode>"
- [(match_operand:VMQI 0 "s_register_operand" "")
- (match_operand:VMQI 1 "s_register_operand" "")
- (match_operand:<V_elem> 2 "s_register_operand" "")]
+ [(match_operand:VMQI 0 "s_register_operand")
+ (match_operand:VMQI 1 "s_register_operand")
+ (match_operand:<V_elem> 2 "s_register_operand")]
"TARGET_NEON"
{
rtx tmp = gen_reg_rtx (<V_HALF>mode);
@@ -4759,10 +4785,10 @@ if (BYTES_BIG_ENDIAN)
})
(define_expand "neon_vmla_n<mode>"
- [(match_operand:VMD 0 "s_register_operand" "")
- (match_operand:VMD 1 "s_register_operand" "")
- (match_operand:VMD 2 "s_register_operand" "")
- (match_operand:<V_elem> 3 "s_register_operand" "")]
+ [(match_operand:VMD 0 "s_register_operand")
+ (match_operand:VMD 1 "s_register_operand")
+ (match_operand:VMD 2 "s_register_operand")
+ (match_operand:<V_elem> 3 "s_register_operand")]
"TARGET_NEON"
{
rtx tmp = gen_reg_rtx (<MODE>mode);
@@ -4773,10 +4799,10 @@ if (BYTES_BIG_ENDIAN)
})
(define_expand "neon_vmla_n<mode>"
- [(match_operand:VMQ 0 "s_register_operand" "")
- (match_operand:VMQ 1 "s_register_operand" "")
- (match_operand:VMQ 2 "s_register_operand" "")
- (match_operand:<V_elem> 3 "s_register_operand" "")]
+ [(match_operand:VMQ 0 "s_register_operand")
+ (match_operand:VMQ 1 "s_register_operand")
+ (match_operand:VMQ 2 "s_register_operand")
+ (match_operand:<V_elem> 3 "s_register_operand")]
"TARGET_NEON"
{
rtx tmp = gen_reg_rtx (<V_HALF>mode);
@@ -4787,10 +4813,10 @@ if (BYTES_BIG_ENDIAN)
})
(define_expand "neon_vmlals_n<mode>"
- [(match_operand:<V_widen> 0 "s_register_operand" "")
- (match_operand:<V_widen> 1 "s_register_operand" "")
- (match_operand:VMDI 2 "s_register_operand" "")
- (match_operand:<V_elem> 3 "s_register_operand" "")]
+ [(match_operand:<V_widen> 0 "s_register_operand")
+ (match_operand:<V_widen> 1 "s_register_operand")
+ (match_operand:VMDI 2 "s_register_operand")
+ (match_operand:<V_elem> 3 "s_register_operand")]
"TARGET_NEON"
{
rtx tmp = gen_reg_rtx (<MODE>mode);
@@ -4801,10 +4827,10 @@ if (BYTES_BIG_ENDIAN)
})
(define_expand "neon_vmlalu_n<mode>"
- [(match_operand:<V_widen> 0 "s_register_operand" "")
- (match_operand:<V_widen> 1 "s_register_operand" "")
- (match_operand:VMDI 2 "s_register_operand" "")
- (match_operand:<V_elem> 3 "s_register_operand" "")]
+ [(match_operand:<V_widen> 0 "s_register_operand")
+ (match_operand:<V_widen> 1 "s_register_operand")
+ (match_operand:VMDI 2 "s_register_operand")
+ (match_operand:<V_elem> 3 "s_register_operand")]
"TARGET_NEON"
{
rtx tmp = gen_reg_rtx (<MODE>mode);
@@ -4815,10 +4841,10 @@ if (BYTES_BIG_ENDIAN)
})
(define_expand "neon_vqdmlal_n<mode>"
- [(match_operand:<V_widen> 0 "s_register_operand" "")
- (match_operand:<V_widen> 1 "s_register_operand" "")
- (match_operand:VMDI 2 "s_register_operand" "")
- (match_operand:<V_elem> 3 "s_register_operand" "")]
+ [(match_operand:<V_widen> 0 "s_register_operand")
+ (match_operand:<V_widen> 1 "s_register_operand")
+ (match_operand:VMDI 2 "s_register_operand")
+ (match_operand:<V_elem> 3 "s_register_operand")]
"TARGET_NEON"
{
rtx tmp = gen_reg_rtx (<MODE>mode);
@@ -4829,10 +4855,10 @@ if (BYTES_BIG_ENDIAN)
})
(define_expand "neon_vmls_n<mode>"
- [(match_operand:VMD 0 "s_register_operand" "")
- (match_operand:VMD 1 "s_register_operand" "")
- (match_operand:VMD 2 "s_register_operand" "")
- (match_operand:<V_elem> 3 "s_register_operand" "")]
+ [(match_operand:VMD 0 "s_register_operand")
+ (match_operand:VMD 1 "s_register_operand")
+ (match_operand:VMD 2 "s_register_operand")
+ (match_operand:<V_elem> 3 "s_register_operand")]
"TARGET_NEON"
{
rtx tmp = gen_reg_rtx (<MODE>mode);
@@ -4843,10 +4869,10 @@ if (BYTES_BIG_ENDIAN)
})
(define_expand "neon_vmls_n<mode>"
- [(match_operand:VMQ 0 "s_register_operand" "")
- (match_operand:VMQ 1 "s_register_operand" "")
- (match_operand:VMQ 2 "s_register_operand" "")
- (match_operand:<V_elem> 3 "s_register_operand" "")]
+ [(match_operand:VMQ 0 "s_register_operand")
+ (match_operand:VMQ 1 "s_register_operand")
+ (match_operand:VMQ 2 "s_register_operand")
+ (match_operand:<V_elem> 3 "s_register_operand")]
"TARGET_NEON"
{
rtx tmp = gen_reg_rtx (<V_HALF>mode);
@@ -4857,10 +4883,10 @@ if (BYTES_BIG_ENDIAN)
})
(define_expand "neon_vmlsls_n<mode>"
- [(match_operand:<V_widen> 0 "s_register_operand" "")
- (match_operand:<V_widen> 1 "s_register_operand" "")
- (match_operand:VMDI 2 "s_register_operand" "")
- (match_operand:<V_elem> 3 "s_register_operand" "")]
+ [(match_operand:<V_widen> 0 "s_register_operand")
+ (match_operand:<V_widen> 1 "s_register_operand")
+ (match_operand:VMDI 2 "s_register_operand")
+ (match_operand:<V_elem> 3 "s_register_operand")]
"TARGET_NEON"
{
rtx tmp = gen_reg_rtx (<MODE>mode);
@@ -4871,10 +4897,10 @@ if (BYTES_BIG_ENDIAN)
})
(define_expand "neon_vmlslu_n<mode>"
- [(match_operand:<V_widen> 0 "s_register_operand" "")
- (match_operand:<V_widen> 1 "s_register_operand" "")
- (match_operand:VMDI 2 "s_register_operand" "")
- (match_operand:<V_elem> 3 "s_register_operand" "")]
+ [(match_operand:<V_widen> 0 "s_register_operand")
+ (match_operand:<V_widen> 1 "s_register_operand")
+ (match_operand:VMDI 2 "s_register_operand")
+ (match_operand:<V_elem> 3 "s_register_operand")]
"TARGET_NEON"
{
rtx tmp = gen_reg_rtx (<MODE>mode);
@@ -4885,10 +4911,10 @@ if (BYTES_BIG_ENDIAN)
})
(define_expand "neon_vqdmlsl_n<mode>"
- [(match_operand:<V_widen> 0 "s_register_operand" "")
- (match_operand:<V_widen> 1 "s_register_operand" "")
- (match_operand:VMDI 2 "s_register_operand" "")
- (match_operand:<V_elem> 3 "s_register_operand" "")]
+ [(match_operand:<V_widen> 0 "s_register_operand")
+ (match_operand:<V_widen> 1 "s_register_operand")
+ (match_operand:VMDI 2 "s_register_operand")
+ (match_operand:<V_elem> 3 "s_register_operand")]
"TARGET_NEON"
{
rtx tmp = gen_reg_rtx (<MODE>mode);
@@ -4962,10 +4988,10 @@ if (BYTES_BIG_ENDIAN)
)
(define_expand "neon_vbsl<mode>"
- [(set (match_operand:VDQX 0 "s_register_operand" "")
- (unspec:VDQX [(match_operand:<V_cmp_result> 1 "s_register_operand" "")
- (match_operand:VDQX 2 "s_register_operand" "")
- (match_operand:VDQX 3 "s_register_operand" "")]
+ [(set (match_operand:VDQX 0 "s_register_operand")
+ (unspec:VDQX [(match_operand:<V_cmp_result> 1 "s_register_operand")
+ (match_operand:VDQX 2 "s_register_operand")
+ (match_operand:VDQX 3 "s_register_operand")]
UNSPEC_VBSL))]
"TARGET_NEON"
{
@@ -5444,7 +5470,7 @@ if (BYTES_BIG_ENDIAN)
(unspec:VDQWH [(match_operand:VDQWH 1 "s_register_operand")
(match_operand:VDQWH 2 "s_register_operand")]
UNSPEC_VUZP1))
- (set (match_operand:VDQWH 3 "s_register_operand" "")
+ (set (match_operand:VDQWH 3 "s_register_operand")
(unspec:VDQWH [(match_dup 1) (match_dup 2)] UNSPEC_VUZP2))])]
"TARGET_NEON"
""
@@ -5540,8 +5566,8 @@ if (BYTES_BIG_ENDIAN)
;; Special case for DImode. Treat it exactly like a simple load.
(define_expand "neon_vld1_dupdi"
- [(set (match_operand:DI 0 "s_register_operand" "")
- (unspec:DI [(match_operand:DI 1 "neon_struct_operand" "")]
+ [(set (match_operand:DI 0 "s_register_operand")
+ (unspec:DI [(match_operand:DI 1 "neon_struct_operand")]
UNSPEC_VLD1))]
"TARGET_NEON"
""
@@ -6515,7 +6541,7 @@ if (BYTES_BIG_ENDIAN)
)
(define_expand "vec_unpack<US>_hi_<mode>"
- [(match_operand:<V_unpack> 0 "register_operand" "")
+ [(match_operand:<V_unpack> 0 "register_operand")
(SE:<V_unpack> (match_operand:VU 1 "register_operand"))]
"TARGET_NEON && !BYTES_BIG_ENDIAN"
{
@@ -6534,8 +6560,8 @@ if (BYTES_BIG_ENDIAN)
)
(define_expand "vec_unpack<US>_lo_<mode>"
- [(match_operand:<V_unpack> 0 "register_operand" "")
- (SE:<V_unpack> (match_operand:VU 1 "register_operand" ""))]
+ [(match_operand:<V_unpack> 0 "register_operand")
+ (SE:<V_unpack> (match_operand:VU 1 "register_operand"))]
"TARGET_NEON && !BYTES_BIG_ENDIAN"
{
rtvec v = rtvec_alloc (<V_mode_nunits>/2) ;
@@ -6565,9 +6591,9 @@ if (BYTES_BIG_ENDIAN)
)
(define_expand "vec_widen_<US>mult_lo_<mode>"
- [(match_operand:<V_unpack> 0 "register_operand" "")
- (SE:<V_unpack> (match_operand:VU 1 "register_operand" ""))
- (SE:<V_unpack> (match_operand:VU 2 "register_operand" ""))]
+ [(match_operand:<V_unpack> 0 "register_operand")
+ (SE:<V_unpack> (match_operand:VU 1 "register_operand"))
+ (SE:<V_unpack> (match_operand:VU 2 "register_operand"))]
"TARGET_NEON && !BYTES_BIG_ENDIAN"
{
rtvec v = rtvec_alloc (<V_mode_nunits>/2) ;
@@ -6599,9 +6625,9 @@ if (BYTES_BIG_ENDIAN)
)
(define_expand "vec_widen_<US>mult_hi_<mode>"
- [(match_operand:<V_unpack> 0 "register_operand" "")
- (SE:<V_unpack> (match_operand:VU 1 "register_operand" ""))
- (SE:<V_unpack> (match_operand:VU 2 "register_operand" ""))]
+ [(match_operand:<V_unpack> 0 "register_operand")
+ (SE:<V_unpack> (match_operand:VU 1 "register_operand"))
+ (SE:<V_unpack> (match_operand:VU 2 "register_operand"))]
"TARGET_NEON && !BYTES_BIG_ENDIAN"
{
rtvec v = rtvec_alloc (<V_mode_nunits>/2) ;
@@ -6632,9 +6658,9 @@ if (BYTES_BIG_ENDIAN)
)
(define_expand "vec_widen_<US>shiftl_lo_<mode>"
- [(match_operand:<V_unpack> 0 "register_operand" "")
- (SE:<V_unpack> (match_operand:VU 1 "register_operand" ""))
- (match_operand:SI 2 "immediate_operand" "i")]
+ [(match_operand:<V_unpack> 0 "register_operand")
+ (SE:<V_unpack> (match_operand:VU 1 "register_operand"))
+ (match_operand:SI 2 "immediate_operand")]
"TARGET_NEON && !BYTES_BIG_ENDIAN"
{
emit_insn (gen_neon_vec_<US>shiftl_<V_half> (operands[0],
@@ -6645,9 +6671,9 @@ if (BYTES_BIG_ENDIAN)
)
(define_expand "vec_widen_<US>shiftl_hi_<mode>"
- [(match_operand:<V_unpack> 0 "register_operand" "")
- (SE:<V_unpack> (match_operand:VU 1 "register_operand" ""))
- (match_operand:SI 2 "immediate_operand" "i")]
+ [(match_operand:<V_unpack> 0 "register_operand")
+ (SE:<V_unpack> (match_operand:VU 1 "register_operand"))
+ (match_operand:SI 2 "immediate_operand")]
"TARGET_NEON && !BYTES_BIG_ENDIAN"
{
emit_insn (gen_neon_vec_<US>shiftl_<V_half> (operands[0],
@@ -6668,7 +6694,7 @@ if (BYTES_BIG_ENDIAN)
)
(define_expand "vec_unpack<US>_lo_<mode>"
- [(match_operand:<V_double_width> 0 "register_operand" "")
+ [(match_operand:<V_double_width> 0 "register_operand")
(SE:<V_double_width>(match_operand:VDI 1 "register_operand"))]
"TARGET_NEON"
{
@@ -6681,7 +6707,7 @@ if (BYTES_BIG_ENDIAN)
)
(define_expand "vec_unpack<US>_hi_<mode>"
- [(match_operand:<V_double_width> 0 "register_operand" "")
+ [(match_operand:<V_double_width> 0 "register_operand")
(SE:<V_double_width>(match_operand:VDI 1 "register_operand"))]
"TARGET_NEON"
{
@@ -6705,9 +6731,9 @@ if (BYTES_BIG_ENDIAN)
)
(define_expand "vec_widen_<US>mult_hi_<mode>"
- [(match_operand:<V_double_width> 0 "register_operand" "")
- (SE:<V_double_width> (match_operand:VDI 1 "register_operand" ""))
- (SE:<V_double_width> (match_operand:VDI 2 "register_operand" ""))]
+ [(match_operand:<V_double_width> 0 "register_operand")
+ (SE:<V_double_width> (match_operand:VDI 1 "register_operand"))
+ (SE:<V_double_width> (match_operand:VDI 2 "register_operand"))]
"TARGET_NEON"
{
rtx tmpreg = gen_reg_rtx (<V_widen>mode);
@@ -6720,9 +6746,9 @@ if (BYTES_BIG_ENDIAN)
)
(define_expand "vec_widen_<US>mult_lo_<mode>"
- [(match_operand:<V_double_width> 0 "register_operand" "")
- (SE:<V_double_width> (match_operand:VDI 1 "register_operand" ""))
- (SE:<V_double_width> (match_operand:VDI 2 "register_operand" ""))]
+ [(match_operand:<V_double_width> 0 "register_operand")
+ (SE:<V_double_width> (match_operand:VDI 1 "register_operand"))
+ (SE:<V_double_width> (match_operand:VDI 2 "register_operand"))]
"TARGET_NEON"
{
rtx tmpreg = gen_reg_rtx (<V_widen>mode);
@@ -6735,9 +6761,9 @@ if (BYTES_BIG_ENDIAN)
)
(define_expand "vec_widen_<US>shiftl_hi_<mode>"
- [(match_operand:<V_double_width> 0 "register_operand" "")
- (SE:<V_double_width> (match_operand:VDI 1 "register_operand" ""))
- (match_operand:SI 2 "immediate_operand" "i")]
+ [(match_operand:<V_double_width> 0 "register_operand")
+ (SE:<V_double_width> (match_operand:VDI 1 "register_operand"))
+ (match_operand:SI 2 "immediate_operand")]
"TARGET_NEON"
{
rtx tmpreg = gen_reg_rtx (<V_widen>mode);
@@ -6749,9 +6775,9 @@ if (BYTES_BIG_ENDIAN)
)
(define_expand "vec_widen_<US>shiftl_lo_<mode>"
- [(match_operand:<V_double_width> 0 "register_operand" "")
- (SE:<V_double_width> (match_operand:VDI 1 "register_operand" ""))
- (match_operand:SI 2 "immediate_operand" "i")]
+ [(match_operand:<V_double_width> 0 "register_operand")
+ (SE:<V_double_width> (match_operand:VDI 1 "register_operand"))
+ (match_operand:SI 2 "immediate_operand")]
"TARGET_NEON"
{
rtx tmpreg = gen_reg_rtx (<V_widen>mode);
@@ -6789,8 +6815,8 @@ if (BYTES_BIG_ENDIAN)
)
(define_expand "vec_pack_trunc_<mode>"
- [(match_operand:<V_narrow_pack> 0 "register_operand" "")
- (match_operand:VSHFT 1 "register_operand" "")
+ [(match_operand:<V_narrow_pack> 0 "register_operand")
+ (match_operand:VSHFT 1 "register_operand")
(match_operand:VSHFT 2 "register_operand")]
"TARGET_NEON && !BYTES_BIG_ENDIAN"
{
diff --git a/gcc/config/arm/netbsd-eabi.h b/gcc/config/arm/netbsd-eabi.h
new file mode 100644
index 0000000..5524b37
--- /dev/null
+++ b/gcc/config/arm/netbsd-eabi.h
@@ -0,0 +1,105 @@
+/* Definitions of target machine for GNU compiler, NetBSD/arm ELF version.
+ Copyright (C) 2002, 2003, 2004, 2005, 2007 Free Software Foundation, Inc.
+ Contributed by Wasabi Systems, 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/>. */
+
+/* Run-time Target Specification. */
+#undef MULTILIB_DEFAULTS
+#define MULTILIB_DEFAULTS { "mabi=aapcs-linux" }
+
+#define TARGET_LINKER_EABI_SUFFIX_SOFT \
+ "%{!mabi=apcs-gnu:%{!mabi=atpcs:%{mfloat-abi=hard:_eabihf;:_eabi}}}"
+#define TARGET_LINKER_EABI_SUFFIX_HARD \
+ "%{!mabi=apcs-gnu:%{!mabi=atpcs:%{mfloat-abi=soft:_eabi;:_eabihf}}}"
+
+#define TARGET_LINKER_EABI_SUFFIX \
+ (TARGET_DEFAULT_FLOAT_ABI == ARM_FLOAT_ABI_SOFT \
+ ? TARGET_LINKER_EABI_SUFFIX_SOFT \
+ : TARGET_LINKER_EABI_SUFFIX_HARD)
+
+#define TARGET_LINKER_BIG_EMULATION "armelfb_nbsd%(linker_eabi_suffix)"
+#define TARGET_LINKER_LITTLE_EMULATION "armelf_nbsd%(linker_eabi_suffix)"
+
+/* TARGET_BIG_ENDIAN_DEFAULT is set in
+ config.gcc for big endian configurations. */
+#undef TARGET_LINKER_EMULATION
+#if TARGET_BIG_ENDIAN_DEFAULT
+#define TARGET_LINKER_EMULATION TARGET_LINKER_BIG_EMULATION
+#else
+#define TARGET_LINKER_EMULATION TARGET_LINKER_LITTLE_EMULATION
+#endif
+
+#undef ARM_DEFAULT_ABI
+#define ARM_DEFAULT_ABI ARM_ABI_AAPCS_LINUX
+
+#undef ARM_UNWIND_INFO
+#define ARM_UNWIND_INFO 0
+#undef DWARF2_UNWIND_INFO
+#define DWARF2_UNWIND_INFO 1
+
+#undef TARGET_OS_CPP_BUILTINS
+#define TARGET_OS_CPP_BUILTINS() \
+ do \
+ { \
+ if (TARGET_AAPCS_BASED) \
+ TARGET_BPABI_CPP_BUILTINS(); \
+ NETBSD_OS_CPP_BUILTINS_ELF(); \
+ if (DWARF2_UNWIND_INFO) \
+ builtin_define ("__ARM_DWARF_EH__"); \
+ } \
+ while (0)
+
+#undef SUBTARGET_CPP_SPEC
+#define SUBTARGET_CPP_SPEC NETBSD_CPP_SPEC
+
+/*
+ * Override AAPCS types to remain compatible the existing NetBSD types.
+ */
+#undef WCHAR_TYPE
+#define WCHAR_TYPE "int"
+
+#undef SIZE_TYPE
+#define SIZE_TYPE "long unsigned int"
+
+#undef PTRDIFF_TYPE
+#define PTRDIFF_TYPE "long int"
+
+#undef SUBTARGET_EXTRA_ASM_SPEC
+#define SUBTARGET_EXTRA_ASM_SPEC \
+ "%{mabi=apcs-gnu|mabi=atpcs:-meabi=gnu} " \
+ "%{fpic|fpie:-k} " \
+ "%{fPIC|fPIE:-k}"
+
+#undef SUBTARGET_EXTRA_SPECS
+#define SUBTARGET_EXTRA_SPECS \
+ { "subtarget_extra_asm_spec", SUBTARGET_EXTRA_ASM_SPEC }, \
+ { "linker_eabi_suffix", TARGET_LINKER_EABI_SUFFIX }, \
+ { "linker_emulation", TARGET_LINKER_EMULATION }, \
+ { "linker_big_emulation", TARGET_LINKER_BIG_EMULATION }, \
+ { "linker_little_emulation", TARGET_LINKER_LITTLE_EMULATION }, \
+ { "target_fix_v4bx_spec", TARGET_FIX_V4BX_SPEC }, \
+ NETBSD_SUBTARGET_EXTRA_SPECS
+
+#define NETBSD_ENTRY_POINT "__start"
+
+#undef LINK_SPEC
+#define LINK_SPEC \
+ "-X %{mbig-endian:-EB -m %(linker_big_emulation)} " \
+ "%{mlittle-endian:-EL -m %(linker_liitle_emulation)} " \
+ "%{!mbig-endian:%{!mlittle-endian:-m %(linker_emulation)}} " \
+ "%(target_fix_v4bx_spec) %(netbsd_link_spec)"
diff --git a/gcc/config/arm/netbsd-elf.h b/gcc/config/arm/netbsd-elf.h
index 5fcb543..e42a32f 100644
--- a/gcc/config/arm/netbsd-elf.h
+++ b/gcc/config/arm/netbsd-elf.h
@@ -43,6 +43,7 @@
#undef ARM_DEFAULT_ABI
#define ARM_DEFAULT_ABI ARM_ABI_ATPCS
+#undef TARGET_OS_CPP_BUILTINS
#define TARGET_OS_CPP_BUILTINS() \
do \
{ \
@@ -55,7 +56,7 @@
#undef SUBTARGET_EXTRA_ASM_SPEC
#define SUBTARGET_EXTRA_ASM_SPEC \
- "-matpcs %{" FPIE_OR_FPIC_SPEC ":-k}"
+ "%{" FPIE_OR_FPIC_SPEC ":-k}"
/* Default to full VFP if -mfloat-abi=hard is specified. */
#undef SUBTARGET_ASM_FLOAT_SPEC
@@ -87,13 +88,13 @@
/* We don't have any limit on the length as out debugger is GDB. */
#undef DBX_CONTIN_LENGTH
-/* NetBSD does its profiling differently to the Acorn compiler. We
+/* NetBSD does its profiling differently to the Acorn compiler. We
don't need a word following the mcount call; and to skip it
- requires either an assembly stub or use of fomit-frame-pointer when
+ requires either an assembly stub or use of fomit-frame-pointer when
compiling the profiling functions. Since we break Acorn CC
compatibility below a little more won't hurt. */
-
-#undef ARM_FUNCTION_PROFILER
+
+#undef ARM_FUNCTION_PROFILER
#define ARM_FUNCTION_PROFILER(STREAM,LABELNO) \
{ \
asm_fprintf (STREAM, "\tmov\t%Rip, %Rlr\n"); \
@@ -110,22 +111,22 @@
boundary. However this causes problems with bugged NetBSD kernel
code (possibly userland code as well - I have not checked every
binary). The nature of this bugged code is to rely on sizeof()
- returning the correct size of various structures rounded to the
+ returning the correct size of various structures rounded to the
nearest byte (SCSI and ether code are two examples, the vm system
is another). This code breaks when the structure alignment is 32
- as sizeof() will report a word=rounded size. By changing the
+ as sizeof() will report a word=rounded size. By changing the
structure alignment to 8. GCC will conform to what is expected by
NetBSD.
-
+
This has several side effects that should be considered.
1. Structures will only be aligned to the size of the largest member.
i.e. structures containing only bytes will be byte aligned.
- structures containing shorts will be half word aligned.
- structures containing ints will be word aligned.
-
+ structures containing shorts will be half word aligned.
+ structures containing ints will be word aligned.
+
This means structures should be padded to a word boundary if
alignment of 32 is required for byte structures etc.
-
+
2. A potential performance penalty may exist if strings are no longer
word aligned. GCC will not be able to use word load/stores to copy
short strings.
@@ -137,6 +138,8 @@
#undef DEFAULT_STRUCTURE_SIZE_BOUNDARY
#define DEFAULT_STRUCTURE_SIZE_BOUNDARY 8
+#define SYSARCH_ARM_SYNC_ICACHE 0
+
/* Clear the instruction cache from `BEG' to `END'. This makes a
call to the ARM_SYNC_ICACHE architecture specific syscall. */
#define CLEAR_INSN_CACHE(BEG, END) \
@@ -150,6 +153,6 @@ do \
} s; \
s.addr = (unsigned int)(BEG); \
s.len = (END) - (BEG); \
- (void) sysarch (0, &s); \
+ (void) sysarch (SYSARCH_ARM_SYNC_ICACHE, &s); \
} \
while (0)
diff --git a/gcc/config/arm/sync.md b/gcc/config/arm/sync.md
index 0e777a9..3d49aef 100644
--- a/gcc/config/arm/sync.md
+++ b/gcc/config/arm/sync.md
@@ -170,11 +170,11 @@
})
(define_expand "atomic_compare_and_swap<mode>"
- [(match_operand:SI 0 "s_register_operand" "") ;; bool out
- (match_operand:QHSD 1 "s_register_operand" "") ;; val out
- (match_operand:QHSD 2 "mem_noofs_operand" "") ;; memory
- (match_operand:QHSD 3 "general_operand" "") ;; expected
- (match_operand:QHSD 4 "s_register_operand" "") ;; desired
+ [(match_operand:SI 0 "s_register_operand") ;; bool out
+ (match_operand:QHSD 1 "s_register_operand") ;; val out
+ (match_operand:QHSD 2 "mem_noofs_operand") ;; memory
+ (match_operand:QHSD 3 "general_operand") ;; expected
+ (match_operand:QHSD 4 "s_register_operand") ;; desired
(match_operand:SI 5 "const_int_operand") ;; is_weak
(match_operand:SI 6 "const_int_operand") ;; mod_s
(match_operand:SI 7 "const_int_operand")] ;; mod_f
diff --git a/gcc/config/arm/t-rtems b/gcc/config/arm/t-rtems
index c073786..94a2eb7 100644
--- a/gcc/config/arm/t-rtems
+++ b/gcc/config/arm/t-rtems
@@ -17,8 +17,8 @@ MULTILIB_DIRNAMES += eb
MULTILIB_OPTIONS += mthumb
MULTILIB_DIRNAMES += thumb
-MULTILIB_OPTIONS += march=armv5te+fp/march=armv6-m/march=armv7-a/march=armv7-a+simd/march=armv7-r/march=armv7-r+fp/march=armv7-m/march=armv7e-m+fp/march=armv7e-m+fp.dp
-MULTILIB_DIRNAMES += armv5te+fp armv6-m armv7-a armv7-a+simd armv7-r armv7-r+fp armv7-m armv7e-m+fp armv7e-m+fp.dp
+MULTILIB_OPTIONS += march=armv5te+fp/march=armv6-m/march=armv7-a/march=armv7-a+simd/march=armv7-r/march=armv7-r+fp/mcpu=cortex-m3/mcpu=cortex-m4/mcpu=cortex-m4+nofp/mcpu=cortex-m7
+MULTILIB_DIRNAMES += armv5te+fp armv6-m armv7-a armv7-a+simd armv7-r armv7-r+fp cortex-m3 cortex-m4 cortex-m4+nofp cortex-m7
MULTILIB_OPTIONS += mfloat-abi=hard
MULTILIB_DIRNAMES += hard
@@ -31,7 +31,8 @@ MULTILIB_REQUIRED += mthumb/march=armv7-a+simd/mfloat-abi=hard
MULTILIB_REQUIRED += mthumb/march=armv7-a
MULTILIB_REQUIRED += mthumb/march=armv7-r+fp/mfloat-abi=hard
MULTILIB_REQUIRED += mthumb/march=armv7-r
-MULTILIB_REQUIRED += mthumb/march=armv7e-m+fp/mfloat-abi=hard
-MULTILIB_REQUIRED += mthumb/march=armv7e-m+fp.dp/mfloat-abi=hard
-MULTILIB_REQUIRED += mthumb/march=armv7-m
+MULTILIB_REQUIRED += mthumb/mcpu=cortex-m3
+MULTILIB_REQUIRED += mthumb/mcpu=cortex-m4/mfloat-abi=hard
+MULTILIB_REQUIRED += mthumb/mcpu=cortex-m4+nofp
+MULTILIB_REQUIRED += mthumb/mcpu=cortex-m7/mfloat-abi=hard
MULTILIB_REQUIRED += mthumb
diff --git a/gcc/config/arm/thumb1.md b/gcc/config/arm/thumb1.md
index cefd6cf..b142bfc 100644
--- a/gcc/config/arm/thumb1.md
+++ b/gcc/config/arm/thumb1.md
@@ -794,9 +794,9 @@
(set_attr "conds" "clob,nocond,nocond,nocond,nocond,clob,nocond")])
(define_expand "thumb_movhi_clobber"
- [(set (match_operand:HI 0 "memory_operand" "")
- (match_operand:HI 1 "register_operand" ""))
- (clobber (match_operand:DI 2 "register_operand" ""))]
+ [(set (match_operand:HI 0 "memory_operand")
+ (match_operand:HI 1 "register_operand"))
+ (clobber (match_operand:DI 2 "register_operand"))]
"TARGET_THUMB1"
"
if (strict_memory_address_p (HImode, XEXP (operands[0], 0))
@@ -928,7 +928,7 @@
;; Thumb block-move insns
-(define_insn "movmem12b"
+(define_insn "cpymem12b"
[(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
(mem:SI (match_operand:SI 3 "register_operand" "1")))
(set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
@@ -950,7 +950,7 @@
(set_attr "type" "store_12")]
)
-(define_insn "movmem8b"
+(define_insn "cpymem8b"
[(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
(mem:SI (match_operand:SI 3 "register_operand" "1")))
(set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
@@ -977,8 +977,8 @@
(define_expand "cbranchqi4"
[(set (pc) (if_then_else
(match_operator 0 "lt_ge_comparison_operator"
- [(match_operand:QI 1 "memory_operand" "")
- (match_operand:QI 2 "const0_operand" "")])
+ [(match_operand:QI 1 "memory_operand")
+ (match_operand:QI 2 "const0_operand")])
(label_ref (match_operand 3 "" ""))
(pc)))]
"TARGET_THUMB1"
@@ -1616,8 +1616,8 @@
(define_expand "cstoresi_eq0_thumb1"
[(parallel
- [(set (match_operand:SI 0 "s_register_operand" "")
- (eq:SI (match_operand:SI 1 "s_register_operand" "")
+ [(set (match_operand:SI 0 "s_register_operand")
+ (eq:SI (match_operand:SI 1 "s_register_operand")
(const_int 0)))
(clobber (match_dup:SI 2))])]
"TARGET_THUMB1"
@@ -1626,8 +1626,8 @@
(define_expand "cstoresi_ne0_thumb1"
[(parallel
- [(set (match_operand:SI 0 "s_register_operand" "")
- (ne:SI (match_operand:SI 1 "s_register_operand" "")
+ [(set (match_operand:SI 0 "s_register_operand")
+ (ne:SI (match_operand:SI 1 "s_register_operand")
(const_int 0)))
(clobber (match_dup:SI 2))])]
"TARGET_THUMB1"
@@ -1838,8 +1838,8 @@
)
(define_expand "thumb1_casesi_internal_pic"
- [(match_operand:SI 0 "s_register_operand" "")
- (match_operand:SI 1 "thumb1_cmp_operand" "")
+ [(match_operand:SI 0 "s_register_operand")
+ (match_operand:SI 1 "thumb1_cmp_operand")
(match_operand 2 "" "")
(match_operand 3 "" "")]
"TARGET_THUMB1"
@@ -1911,7 +1911,7 @@
;; Miscellaneous Thumb patterns
(define_expand "tablejump"
- [(parallel [(set (pc) (match_operand:SI 0 "register_operand" ""))
+ [(parallel [(set (pc) (match_operand:SI 0 "register_operand"))
(use (label_ref (match_operand 1 "" "")))])]
"TARGET_THUMB1"
"
diff --git a/gcc/config/arm/unspecs.md b/gcc/config/arm/unspecs.md
index 174bcc5..41068ba 100644
--- a/gcc/config/arm/unspecs.md
+++ b/gcc/config/arm/unspecs.md
@@ -200,6 +200,8 @@
UNSPEC_SHA256SU1
UNSPEC_VMULLP64
UNSPEC_LOAD_COUNT
+ UNSPEC_VABAL_S
+ UNSPEC_VABAL_U
UNSPEC_VABD_F
UNSPEC_VABD_S
UNSPEC_VABD_U
diff --git a/gcc/config/arm/vec-common.md b/gcc/config/arm/vec-common.md
index bb7883f..99a430e 100644
--- a/gcc/config/arm/vec-common.md
+++ b/gcc/config/arm/vec-common.md
@@ -21,8 +21,8 @@
;; Vector Moves
(define_expand "mov<mode>"
- [(set (match_operand:VALL 0 "nonimmediate_operand" "")
- (match_operand:VALL 1 "general_operand" ""))]
+ [(set (match_operand:VALL 0 "nonimmediate_operand")
+ (match_operand:VALL 1 "general_operand"))]
"TARGET_NEON
|| (TARGET_REALLY_IWMMXT && VALID_IWMMXT_REG_MODE (<MODE>mode))"
{
@@ -42,9 +42,9 @@
;; patterns separately for IWMMXT and Neon.
(define_expand "add<mode>3"
- [(set (match_operand:VALL 0 "s_register_operand" "")
- (plus:VALL (match_operand:VALL 1 "s_register_operand" "")
- (match_operand:VALL 2 "s_register_operand" "")))]
+ [(set (match_operand:VALL 0 "s_register_operand")
+ (plus:VALL (match_operand:VALL 1 "s_register_operand")
+ (match_operand:VALL 2 "s_register_operand")))]
"(TARGET_NEON && ((<MODE>mode != V2SFmode && <MODE>mode != V4SFmode)
|| flag_unsafe_math_optimizations))
|| (TARGET_REALLY_IWMMXT && VALID_IWMMXT_REG_MODE (<MODE>mode))"
@@ -52,9 +52,9 @@
})
(define_expand "sub<mode>3"
- [(set (match_operand:VALL 0 "s_register_operand" "")
- (minus:VALL (match_operand:VALL 1 "s_register_operand" "")
- (match_operand:VALL 2 "s_register_operand" "")))]
+ [(set (match_operand:VALL 0 "s_register_operand")
+ (minus:VALL (match_operand:VALL 1 "s_register_operand")
+ (match_operand:VALL 2 "s_register_operand")))]
"(TARGET_NEON && ((<MODE>mode != V2SFmode && <MODE>mode != V4SFmode)
|| flag_unsafe_math_optimizations))
|| (TARGET_REALLY_IWMMXT && VALID_IWMMXT_REG_MODE (<MODE>mode))"
@@ -62,9 +62,9 @@
})
(define_expand "mul<mode>3"
- [(set (match_operand:VALLW 0 "s_register_operand" "")
- (mult:VALLW (match_operand:VALLW 1 "s_register_operand" "")
- (match_operand:VALLW 2 "s_register_operand" "")))]
+ [(set (match_operand:VALLW 0 "s_register_operand")
+ (mult:VALLW (match_operand:VALLW 1 "s_register_operand")
+ (match_operand:VALLW 2 "s_register_operand")))]
"(TARGET_NEON && ((<MODE>mode != V2SFmode && <MODE>mode != V4SFmode)
|| flag_unsafe_math_optimizations))
|| (<MODE>mode == V4HImode && TARGET_REALLY_IWMMXT)"
@@ -72,9 +72,9 @@
})
(define_expand "smin<mode>3"
- [(set (match_operand:VALLW 0 "s_register_operand" "")
- (smin:VALLW (match_operand:VALLW 1 "s_register_operand" "")
- (match_operand:VALLW 2 "s_register_operand" "")))]
+ [(set (match_operand:VALLW 0 "s_register_operand")
+ (smin:VALLW (match_operand:VALLW 1 "s_register_operand")
+ (match_operand:VALLW 2 "s_register_operand")))]
"(TARGET_NEON && ((<MODE>mode != V2SFmode && <MODE>mode != V4SFmode)
|| flag_unsafe_math_optimizations))
|| (TARGET_REALLY_IWMMXT && VALID_IWMMXT_REG_MODE (<MODE>mode))"
@@ -82,18 +82,18 @@
})
(define_expand "umin<mode>3"
- [(set (match_operand:VINTW 0 "s_register_operand" "")
- (umin:VINTW (match_operand:VINTW 1 "s_register_operand" "")
- (match_operand:VINTW 2 "s_register_operand" "")))]
+ [(set (match_operand:VINTW 0 "s_register_operand")
+ (umin:VINTW (match_operand:VINTW 1 "s_register_operand")
+ (match_operand:VINTW 2 "s_register_operand")))]
"TARGET_NEON
|| (TARGET_REALLY_IWMMXT && VALID_IWMMXT_REG_MODE (<MODE>mode))"
{
})
(define_expand "smax<mode>3"
- [(set (match_operand:VALLW 0 "s_register_operand" "")
- (smax:VALLW (match_operand:VALLW 1 "s_register_operand" "")
- (match_operand:VALLW 2 "s_register_operand" "")))]
+ [(set (match_operand:VALLW 0 "s_register_operand")
+ (smax:VALLW (match_operand:VALLW 1 "s_register_operand")
+ (match_operand:VALLW 2 "s_register_operand")))]
"(TARGET_NEON && ((<MODE>mode != V2SFmode && <MODE>mode != V4SFmode)
|| flag_unsafe_math_optimizations))
|| (TARGET_REALLY_IWMMXT && VALID_IWMMXT_REG_MODE (<MODE>mode))"
@@ -101,19 +101,19 @@
})
(define_expand "umax<mode>3"
- [(set (match_operand:VINTW 0 "s_register_operand" "")
- (umax:VINTW (match_operand:VINTW 1 "s_register_operand" "")
- (match_operand:VINTW 2 "s_register_operand" "")))]
+ [(set (match_operand:VINTW 0 "s_register_operand")
+ (umax:VINTW (match_operand:VINTW 1 "s_register_operand")
+ (match_operand:VINTW 2 "s_register_operand")))]
"TARGET_NEON
|| (TARGET_REALLY_IWMMXT && VALID_IWMMXT_REG_MODE (<MODE>mode))"
{
})
(define_expand "vec_perm<mode>"
- [(match_operand:VE 0 "s_register_operand" "")
- (match_operand:VE 1 "s_register_operand" "")
- (match_operand:VE 2 "s_register_operand" "")
- (match_operand:VE 3 "s_register_operand" "")]
+ [(match_operand:VE 0 "s_register_operand")
+ (match_operand:VE 1 "s_register_operand")
+ (match_operand:VE 2 "s_register_operand")
+ (match_operand:VE 3 "s_register_operand")]
"TARGET_NEON && !BYTES_BIG_ENDIAN"
{
arm_expand_vec_perm (operands[0], operands[1], operands[2], operands[3]);
diff --git a/gcc/config/avr/avr-protos.h b/gcc/config/avr/avr-protos.h
index dd0babb..31fe3a6 100644
--- a/gcc/config/avr/avr-protos.h
+++ b/gcc/config/avr/avr-protos.h
@@ -82,7 +82,7 @@ extern rtx avr_to_int_mode (rtx);
extern void avr_expand_prologue (void);
extern void avr_expand_epilogue (bool);
-extern bool avr_emit_movmemhi (rtx*);
+extern bool avr_emit_cpymemhi (rtx*);
extern int avr_epilogue_uses (int regno);
extern void avr_output_addr_vec (rtx_insn*, rtx);
@@ -92,7 +92,7 @@ extern const char* avr_out_plus (rtx, rtx*, int* =NULL, int* =NULL, bool =true);
extern const char* avr_out_round (rtx_insn *, rtx*, int* =NULL);
extern const char* avr_out_addto_sp (rtx*, int*);
extern const char* avr_out_xload (rtx_insn *, rtx*, int*);
-extern const char* avr_out_movmem (rtx_insn *, rtx*, int*);
+extern const char* avr_out_cpymem (rtx_insn *, rtx*, int*);
extern const char* avr_out_insert_bits (rtx*, int*);
extern bool avr_popcount_each_byte (rtx, int, int);
extern bool avr_has_nibble_0xf (rtx);
diff --git a/gcc/config/avr/avr.c b/gcc/config/avr/avr.c
index a9f72b3..b97faaf 100644
--- a/gcc/config/avr/avr.c
+++ b/gcc/config/avr/avr.c
@@ -1302,22 +1302,6 @@ avr_build_builtin_va_list (void)
}
-/* Implement `TARGET_BUILTIN_SETJMP_FRAME_VALUE'. */
-/* Actual start of frame is virtual_stack_vars_rtx this is offset from
- frame pointer by +TARGET_STARTING_FRAME_OFFSET.
- Using saved frame = virtual_stack_vars_rtx - TARGET_STARTING_FRAME_OFFSET
- avoids creating add/sub of offset in nonlocal goto and setjmp. */
-
-static rtx
-avr_builtin_setjmp_frame_value (void)
-{
- rtx xval = gen_reg_rtx (Pmode);
- emit_insn (gen_subhi3 (xval, virtual_stack_vars_rtx,
- gen_int_mode (avr_starting_frame_offset (), Pmode)));
- return xval;
-}
-
-
/* Return contents of MEM at frame pointer + stack size + 1 (+2 if 3-byte PC).
This is return address of function. */
@@ -9420,7 +9404,7 @@ avr_adjust_insn_length (rtx_insn *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_CPYMEM: avr_out_cpymem (insn, op, &len); break;
case ADJUST_LEN_XLOAD: avr_out_xload (insn, op, &len); break;
case ADJUST_LEN_SEXT: avr_out_sign_extend (insn, op, &len); break;
@@ -13337,7 +13321,7 @@ avr_emit3_fix_outputs (rtx (*gen)(rtx,rtx,rtx), rtx *op,
}
-/* Worker function for movmemhi expander.
+/* Worker function for cpymemhi expander.
XOP[0] Destination as MEM:BLK
XOP[1] Source " "
XOP[2] # Bytes to copy
@@ -13346,7 +13330,7 @@ avr_emit3_fix_outputs (rtx (*gen)(rtx,rtx,rtx), rtx *op,
Return FALSE if the operand compination is not supported. */
bool
-avr_emit_movmemhi (rtx *xop)
+avr_emit_cpymemhi (rtx *xop)
{
HOST_WIDE_INT count;
machine_mode loop_mode;
@@ -13423,14 +13407,14 @@ avr_emit_movmemhi (rtx *xop)
Do the copy-loop inline. */
rtx (*fun) (rtx, rtx, rtx)
- = QImode == loop_mode ? gen_movmem_qi : gen_movmem_hi;
+ = QImode == loop_mode ? gen_cpymem_qi : gen_cpymem_hi;
insn = fun (xas, loop_reg, loop_reg);
}
else
{
rtx (*fun) (rtx, rtx)
- = QImode == loop_mode ? gen_movmemx_qi : gen_movmemx_hi;
+ = QImode == loop_mode ? gen_cpymemx_qi : gen_cpymemx_hi;
emit_move_insn (gen_rtx_REG (QImode, 23), a_hi8);
@@ -13444,7 +13428,7 @@ avr_emit_movmemhi (rtx *xop)
}
-/* Print assembler for movmem_qi, movmem_hi insns...
+/* Print assembler for cpymem_qi, cpymem_hi insns...
$0 : Address Space
$1, $2 : Loop register
Z : Source address
@@ -13452,7 +13436,7 @@ avr_emit_movmemhi (rtx *xop)
*/
const char*
-avr_out_movmem (rtx_insn *insn ATTRIBUTE_UNUSED, rtx *op, int *plen)
+avr_out_cpymem (rtx_insn *insn ATTRIBUTE_UNUSED, rtx *op, int *plen)
{
addr_space_t as = (addr_space_t) INTVAL (op[0]);
machine_mode loop_mode = GET_MODE (op[1]);
@@ -14672,9 +14656,6 @@ avr_fold_builtin (tree fndecl, int n_args ATTRIBUTE_UNUSED, tree *arg,
#undef TARGET_STRICT_ARGUMENT_NAMING
#define TARGET_STRICT_ARGUMENT_NAMING hook_bool_CUMULATIVE_ARGS_true
-#undef TARGET_BUILTIN_SETJMP_FRAME_VALUE
-#define TARGET_BUILTIN_SETJMP_FRAME_VALUE avr_builtin_setjmp_frame_value
-
#undef TARGET_CONDITIONAL_REGISTER_USAGE
#define TARGET_CONDITIONAL_REGISTER_USAGE avr_conditional_register_usage
diff --git a/gcc/config/avr/avr.md b/gcc/config/avr/avr.md
index f263b69..e85bf49 100644
--- a/gcc/config/avr/avr.md
+++ b/gcc/config/avr/avr.md
@@ -70,7 +70,7 @@
(define_c_enum "unspec"
[UNSPEC_STRLEN
- UNSPEC_MOVMEM
+ UNSPEC_CPYMEM
UNSPEC_INDEX_JMP
UNSPEC_FMUL
UNSPEC_FMULS
@@ -158,7 +158,7 @@
tsthi, tstpsi, tstsi, compare, compare64, call,
mov8, mov16, mov24, mov32, reload_in16, reload_in24, reload_in32,
ufract, sfract, round,
- xload, movmem,
+ xload, cpymem,
ashlqi, ashrqi, lshrqi,
ashlhi, ashrhi, lshrhi,
ashlsi, ashrsi, lshrsi,
@@ -992,20 +992,20 @@
;;=========================================================================
;; move string (like memcpy)
-(define_expand "movmemhi"
+(define_expand "cpymemhi"
[(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" ""))])]
""
{
- if (avr_emit_movmemhi (operands))
+ if (avr_emit_cpymemhi (operands))
DONE;
FAIL;
})
-(define_mode_attr MOVMEM_r_d [(QI "r")
+(define_mode_attr CPYMEM_r_d [(QI "r")
(HI "wd")])
;; $0 : Address Space
@@ -1013,23 +1013,23 @@
;; R30 : source address
;; R26 : destination address
-;; "movmem_qi"
-;; "movmem_hi"
-(define_insn "movmem_<mode>"
+;; "cpymem_qi"
+;; "cpymem_hi"
+(define_insn "cpymem_<mode>"
[(set (mem:BLK (reg:HI REG_X))
(mem:BLK (reg:HI REG_Z)))
(unspec [(match_operand:QI 0 "const_int_operand" "n")]
- UNSPEC_MOVMEM)
- (use (match_operand:QIHI 1 "register_operand" "<MOVMEM_r_d>"))
+ UNSPEC_CPYMEM)
+ (use (match_operand:QIHI 1 "register_operand" "<CPYMEM_r_d>"))
(clobber (reg:HI REG_X))
(clobber (reg:HI REG_Z))
(clobber (reg:QI LPM_REGNO))
(clobber (match_operand:QIHI 2 "register_operand" "=1"))]
""
{
- return avr_out_movmem (insn, operands, NULL);
+ return avr_out_cpymem (insn, operands, NULL);
}
- [(set_attr "adjust_len" "movmem")
+ [(set_attr "adjust_len" "cpymem")
(set_attr "cc" "clobber")])
@@ -1039,14 +1039,14 @@
;; R23:Z : 24-bit source address
;; R26 : 16-bit destination address
-;; "movmemx_qi"
-;; "movmemx_hi"
-(define_insn "movmemx_<mode>"
+;; "cpymemx_qi"
+;; "cpymemx_hi"
+(define_insn "cpymemx_<mode>"
[(set (mem:BLK (reg:HI REG_X))
(mem:BLK (lo_sum:PSI (reg:QI 23)
(reg:HI REG_Z))))
(unspec [(match_operand:QI 0 "const_int_operand" "n")]
- UNSPEC_MOVMEM)
+ UNSPEC_CPYMEM)
(use (reg:QIHI 24))
(clobber (reg:HI REG_X))
(clobber (reg:HI REG_Z))
diff --git a/gcc/config/bfin/bfin-protos.h b/gcc/config/bfin/bfin-protos.h
index 64a1842..7d0f705 100644
--- a/gcc/config/bfin/bfin-protos.h
+++ b/gcc/config/bfin/bfin-protos.h
@@ -81,7 +81,7 @@ extern bool expand_move (rtx *, machine_mode);
extern void bfin_expand_call (rtx, rtx, rtx, rtx, int);
extern bool bfin_longcall_p (rtx, int);
extern bool bfin_dsp_memref_p (rtx);
-extern bool bfin_expand_movmem (rtx, rtx, rtx, rtx);
+extern bool bfin_expand_cpymem (rtx, rtx, rtx, rtx);
extern enum reg_class secondary_input_reload_class (enum reg_class,
machine_mode,
diff --git a/gcc/config/bfin/bfin.c b/gcc/config/bfin/bfin.c
index 97c2c12..319d7e2 100644
--- a/gcc/config/bfin/bfin.c
+++ b/gcc/config/bfin/bfin.c
@@ -3208,7 +3208,7 @@ output_pop_multiple (rtx insn, rtx *operands)
/* Adjust DST and SRC by OFFSET bytes, and generate one move in mode MODE. */
static void
-single_move_for_movmem (rtx dst, rtx src, machine_mode mode, HOST_WIDE_INT offset)
+single_move_for_cpymem (rtx dst, rtx src, machine_mode mode, HOST_WIDE_INT offset)
{
rtx scratch = gen_reg_rtx (mode);
rtx srcmem, dstmem;
@@ -3224,7 +3224,7 @@ single_move_for_movmem (rtx dst, rtx src, machine_mode mode, HOST_WIDE_INT offse
back on a different method. */
bool
-bfin_expand_movmem (rtx dst, rtx src, rtx count_exp, rtx align_exp)
+bfin_expand_cpymem (rtx dst, rtx src, rtx count_exp, rtx align_exp)
{
rtx srcreg, destreg, countreg;
HOST_WIDE_INT align = 0;
@@ -3269,7 +3269,7 @@ bfin_expand_movmem (rtx dst, rtx src, rtx count_exp, rtx align_exp)
{
if ((count & ~3) == 4)
{
- single_move_for_movmem (dst, src, SImode, offset);
+ single_move_for_cpymem (dst, src, SImode, offset);
offset = 4;
}
else if (count & ~3)
@@ -3282,7 +3282,7 @@ bfin_expand_movmem (rtx dst, rtx src, rtx count_exp, rtx align_exp)
}
if (count & 2)
{
- single_move_for_movmem (dst, src, HImode, offset);
+ single_move_for_cpymem (dst, src, HImode, offset);
offset += 2;
}
}
@@ -3290,7 +3290,7 @@ bfin_expand_movmem (rtx dst, rtx src, rtx count_exp, rtx align_exp)
{
if ((count & ~1) == 2)
{
- single_move_for_movmem (dst, src, HImode, offset);
+ single_move_for_cpymem (dst, src, HImode, offset);
offset = 2;
}
else if (count & ~1)
@@ -3304,7 +3304,7 @@ bfin_expand_movmem (rtx dst, rtx src, rtx count_exp, rtx align_exp)
}
if (count & 1)
{
- single_move_for_movmem (dst, src, QImode, offset);
+ single_move_for_cpymem (dst, src, QImode, offset);
}
return true;
}
@@ -4976,10 +4976,12 @@ bfin_output_mi_thunk (FILE *file ATTRIBUTE_UNUSED,
tree thunk ATTRIBUTE_UNUSED, HOST_WIDE_INT delta,
HOST_WIDE_INT vcall_offset, tree function)
{
+ const char *fnname = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (thunk));
rtx xops[3];
/* The this parameter is passed as the first argument. */
rtx this_rtx = gen_rtx_REG (Pmode, REG_R0);
+ assemble_start_function (thunk, fnname);
/* Adjust the this parameter by a fixed constant. */
if (delta)
{
@@ -5034,6 +5036,7 @@ bfin_output_mi_thunk (FILE *file ATTRIBUTE_UNUSED,
xops[0] = XEXP (DECL_RTL (function), 0);
if (1 || !flag_pic || (*targetm.binds_local_p) (function))
output_asm_insn ("jump.l\t%P0", xops);
+ assemble_end_function (thunk, fnname);
}
/* Codes for all the Blackfin builtins. */
diff --git a/gcc/config/bfin/bfin.h b/gcc/config/bfin/bfin.h
index 19b7f81..4aba596 100644
--- a/gcc/config/bfin/bfin.h
+++ b/gcc/config/bfin/bfin.h
@@ -793,7 +793,7 @@ typedef struct {
#define MOVE_MAX UNITS_PER_WORD
/* If a memory-to-memory move would take MOVE_RATIO or more simple
- move-instruction pairs, we will do a movmem or libcall instead. */
+ move-instruction pairs, we will do a cpymem or libcall instead. */
#define MOVE_RATIO(speed) 5
diff --git a/gcc/config/bfin/bfin.md b/gcc/config/bfin/bfin.md
index ac58924..6ac208d 100644
--- a/gcc/config/bfin/bfin.md
+++ b/gcc/config/bfin/bfin.md
@@ -2316,14 +2316,14 @@
(set_attr "length" "16")
(set_attr "seq_insns" "multi")])
-(define_expand "movmemsi"
+(define_expand "cpymemsi"
[(match_operand:BLK 0 "general_operand" "")
(match_operand:BLK 1 "general_operand" "")
(match_operand:SI 2 "const_int_operand" "")
(match_operand:SI 3 "const_int_operand" "")]
""
{
- if (bfin_expand_movmem (operands[0], operands[1], operands[2], operands[3]))
+ if (bfin_expand_cpymem (operands[0], operands[1], operands[2], operands[3]))
DONE;
FAIL;
})
diff --git a/gcc/config/c6x/c6x-protos.h b/gcc/config/c6x/c6x-protos.h
index a657969..8c04c31 100644
--- a/gcc/config/c6x/c6x-protos.h
+++ b/gcc/config/c6x/c6x-protos.h
@@ -35,7 +35,7 @@ extern bool c6x_long_call_p (rtx);
extern void c6x_expand_call (rtx, rtx, bool);
extern rtx c6x_expand_compare (rtx, machine_mode);
extern bool c6x_force_op_for_comparison_p (enum rtx_code, rtx);
-extern bool c6x_expand_movmem (rtx, rtx, rtx, rtx, rtx, rtx);
+extern bool c6x_expand_cpymem (rtx, rtx, rtx, rtx, rtx, rtx);
extern rtx c6x_subword (rtx, bool);
extern void split_di (rtx *, int, rtx *, rtx *);
diff --git a/gcc/config/c6x/c6x.c b/gcc/config/c6x/c6x.c
index 9a07c40..93841e4 100644
--- a/gcc/config/c6x/c6x.c
+++ b/gcc/config/c6x/c6x.c
@@ -769,10 +769,12 @@ c6x_output_mi_thunk (FILE *file ATTRIBUTE_UNUSED,
tree thunk ATTRIBUTE_UNUSED, HOST_WIDE_INT delta,
HOST_WIDE_INT vcall_offset, tree function)
{
+ const char *fnname = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (thunk));
rtx xops[5];
/* The this parameter is passed as the first argument. */
rtx this_rtx = gen_rtx_REG (Pmode, REG_A4);
+ assemble_start_function (thunk, fnname);
c6x_current_insn = NULL;
xops[4] = XEXP (DECL_RTL (function), 0);
@@ -851,6 +853,7 @@ c6x_output_mi_thunk (FILE *file ATTRIBUTE_UNUSED,
output_asm_insn ("nop 4", xops);
output_asm_insn ("add .d1 %2, %1, %2", xops);
}
+ assemble_end_function (thunk, fnname);
}
/* Return true if EXP goes in small data/bss. */
@@ -1683,10 +1686,10 @@ c6x_valid_mask_p (HOST_WIDE_INT val)
return true;
}
-/* Expand a block move for a movmemM pattern. */
+/* Expand a block move for a cpymemM pattern. */
bool
-c6x_expand_movmem (rtx dst, rtx src, rtx count_exp, rtx align_exp,
+c6x_expand_cpymem (rtx dst, rtx src, rtx count_exp, rtx align_exp,
rtx expected_align_exp ATTRIBUTE_UNUSED,
rtx expected_size_exp ATTRIBUTE_UNUSED)
{
diff --git a/gcc/config/c6x/c6x.md b/gcc/config/c6x/c6x.md
index 8218e1d..f9bf9ba 100644
--- a/gcc/config/c6x/c6x.md
+++ b/gcc/config/c6x/c6x.md
@@ -2844,7 +2844,7 @@
;; Block moves
;; -------------------------------------------------------------------------
-(define_expand "movmemsi"
+(define_expand "cpymemsi"
[(use (match_operand:BLK 0 "memory_operand" ""))
(use (match_operand:BLK 1 "memory_operand" ""))
(use (match_operand:SI 2 "nonmemory_operand" ""))
@@ -2853,7 +2853,7 @@
(use (match_operand:SI 5 "const_int_operand" ""))]
""
{
- if (c6x_expand_movmem (operands[0], operands[1], operands[2], operands[3],
+ if (c6x_expand_cpymem (operands[0], operands[1], operands[2], operands[3],
operands[4], operands[5]))
DONE;
else
diff --git a/gcc/config/cris/cris.c b/gcc/config/cris/cris.c
index 95bc004..88de088 100644
--- a/gcc/config/cris/cris.c
+++ b/gcc/config/cris/cris.c
@@ -2764,6 +2764,9 @@ cris_asm_output_mi_thunk (FILE *stream,
HOST_WIDE_INT vcall_offset ATTRIBUTE_UNUSED,
tree funcdecl)
{
+ const char *fnname = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (thunkdecl));
+
+ assemble_start_function (thunkdecl, fnname);
/* Make sure unwind info is emitted for the thunk if needed. */
final_start_function (emit_barrier (), stream, 1);
@@ -2806,6 +2809,7 @@ cris_asm_output_mi_thunk (FILE *stream,
}
final_end_function ();
+ assemble_end_function (thunkdecl, fnname);
}
/* Boilerplate emitted at start of file.
diff --git a/gcc/config/csky/csky.c b/gcc/config/csky/csky.c
index e4ac933..3cfa13e 100644
--- a/gcc/config/csky/csky.c
+++ b/gcc/config/csky/csky.c
@@ -1967,11 +1967,13 @@ csky_output_mi_thunk (FILE *file, tree thunk ATTRIBUTE_UNUSED,
HOST_WIDE_INT vcall_offset,
tree function)
{
+ const char *fnname = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (thunk));
const char *thiz = "a0";
const char *reg0 = "t0";
const char *reg1 = "t1";
int maxoff = 4096; /* Constant range for addi/subi. */
+ assemble_start_function (thunk, fnname);
final_start_function (emit_barrier (), file, 1);
rtx fnaddr = XEXP (DECL_RTL (function), 0);
@@ -2047,6 +2049,7 @@ csky_output_mi_thunk (FILE *file, tree thunk ATTRIBUTE_UNUSED,
fprintf (file, "\n");
final_end_function ();
+ assemble_end_function (thunk, fnname);
}
diff --git a/gcc/config/darwin-c.c b/gcc/config/darwin-c.c
index 8331153..55b60da 100644
--- a/gcc/config/darwin-c.c
+++ b/gcc/config/darwin-c.c
@@ -79,7 +79,7 @@ pop_field_alignment (void)
free (entry);
}
else
- error ("too many #pragma options align=reset");
+ error ("too many %<#pragma options%> align=reset");
}
/* Handlers for Darwin-specific pragmas. */
@@ -463,41 +463,32 @@ static const char *framework_defaults [] =
/* Register the GNU objective-C runtime include path if STDINC. */
void
-darwin_register_objc_includes (const char *sysroot, const char *iprefix,
- int stdinc)
+darwin_register_objc_includes (const char *sysroot ATTRIBUTE_UNUSED,
+ const char *iprefix, int stdinc)
{
- const char *fname;
- size_t len;
- /* We do not do anything if we do not want the standard includes. */
- if (!stdinc)
- return;
-
- fname = GCC_INCLUDE_DIR "-gnu-runtime";
-
- /* Register the GNU OBJC runtime include path if we are compiling OBJC
- with GNU-runtime. */
+ /* If we want standard includes; Register the GNU OBJC runtime include
+ path if we are compiling OBJC with GNU-runtime.
+ This path is compiler-relative, we don't want to prepend the sysroot
+ since it's not expected to find the headers there. */
- if (c_dialect_objc () && !flag_next_runtime)
+ if (stdinc && c_dialect_objc () && !flag_next_runtime)
{
+ const char *fname = GCC_INCLUDE_DIR "-gnu-runtime";
char *str;
- /* See if our directory starts with the standard prefix.
+ size_t len;
+
+ /* See if our directory starts with the standard prefix.
"Translate" them, i.e. replace /usr/local/lib/gcc... with
IPREFIX and search them first. */
- if (iprefix && (len = cpp_GCC_INCLUDE_DIR_len) != 0 && !sysroot
+ if (iprefix && (len = cpp_GCC_INCLUDE_DIR_len) != 0
&& !strncmp (fname, cpp_GCC_INCLUDE_DIR, len))
{
str = concat (iprefix, fname + len, NULL);
- /* FIXME: wrap the headers for C++awareness. */
- add_path (str, INC_SYSTEM, /*c++aware=*/false, false);
+ add_path (str, INC_SYSTEM, /*c++aware=*/true, false);
}
- /* Should this directory start with the sysroot? */
- if (sysroot)
- str = concat (sysroot, fname, NULL);
- else
- str = update_path (fname, "");
-
- add_path (str, INC_SYSTEM, /*c++aware=*/false, false);
+ str = update_path (fname, "");
+ add_path (str, INC_SYSTEM, /*c++aware=*/true, false);
}
}
diff --git a/gcc/config/darwin-driver.c b/gcc/config/darwin-driver.c
index 6a7c859..49716fa 100644
--- a/gcc/config/darwin-driver.c
+++ b/gcc/config/darwin-driver.c
@@ -26,6 +26,91 @@ along with GCC; see the file COPYING3. If not see
#include "opts.h"
#include "diagnostic-core.h"
+/* Validate a version string (either given on the command line or, perhaps
+ as MACOSX_DEPLOYMENT_TARGET).
+
+ The specs %version-compare() function doesn't accept leading '0' on
+ numbers so strip them out. Do sanity checking here too.
+
+ Return:
+ * original string means it was OK and we didn't want to change it.
+ * new string means it was OK but we rewrote it to avoid possible format
+ problems.
+ * NULL means we didn't like what we saw.
+*/
+
+static const char *
+validate_macosx_version_min (const char *version_str)
+{
+ size_t version_len;
+ unsigned long major, minor, tiny = 0;
+ char *end;
+ const char *old_version = version_str;
+ bool need_rewrite = false;
+
+ version_len = strlen (version_str);
+ if (version_len < 4) /* The minimum would be 10.x */
+ return NULL;
+
+ /* Version string must consist of digits and periods only. */
+ if (strspn (version_str, "0123456789.") != version_len)
+ return NULL;
+
+ if (!ISDIGIT (version_str[0]) || !ISDIGIT (version_str[version_len - 1]))
+ return NULL;
+
+ if (version_str[0] == '0')
+ need_rewrite = true;
+
+ major = strtoul (version_str, &end, 10);
+ version_str = end + ((*end == '.') ? 1 : 0);
+
+ if (major != 10) /* So far .. all MacOS 10 ... */
+ return NULL;
+
+ /* Version string components must be present and numeric. */
+ if (!ISDIGIT (version_str[0]))
+ return NULL;
+
+ /* If we have one or more leading zeros on a component, then rewrite the
+ version string. */
+ if (version_str[0] == '0' && version_str[1] != '\0'
+ && version_str[1] != '.')
+ need_rewrite = true;
+
+ minor = strtoul (version_str, &end, 10);
+ version_str = end + ((*end == '.') ? 1 : 0);
+ if (minor > 99)
+ return NULL;
+
+ /* If 'tiny' is present it must be numeric. */
+ if (*end != '\0' && !ISDIGIT (version_str[0]))
+ return NULL;
+
+ /* If we have one or more leading zeros on a component, then rewrite the
+ version string. */
+ if (*end != '\0' && version_str[0] == '0'
+ && version_str[1] != '\0')
+ need_rewrite = true;
+
+ tiny = strtoul (version_str, &end, 10);
+ if (tiny > 99)
+ return NULL;
+
+ /* Version string must contain no more than three tokens. */
+ if (*end != '\0')
+ return NULL;
+
+ if (need_rewrite)
+ {
+ char *new_version;
+ asprintf (&new_version, "10.%lu.%lu", minor, tiny);
+ return new_version;
+ }
+
+ return old_version;
+}
+
#ifndef CROSS_DIRECTORY_STRUCTURE
#include <sys/sysctl.h>
#include "xregex.h"
@@ -114,12 +199,13 @@ darwin_default_min_version (void)
if (new_flag != NULL)
{
- size_t len = strlen (new_flag);
- if (len > 128) { /* Arbitrary limit, number should be like xx.yy.zz */
- warning (0, "couldn%'t understand version %s\n", new_flag);
- return NULL;
- }
- new_flag = xstrndup (new_flag, len);
+ const char *checked = validate_macosx_version_min (new_flag);
+ if (checked == NULL)
+ {
+ warning (0, "couldn%'t understand version %s", new_flag);
+ return NULL;
+ }
+ new_flag = xstrndup (checked, strlen (checked));
}
return new_flag;
}
@@ -175,7 +261,7 @@ darwin_driver_init (unsigned int *decoded_options_count,
if (*decoded_options_count > i) {
memmove (*decoded_options + i,
*decoded_options + i + 1,
- ((*decoded_options_count - i)
+ ((*decoded_options_count - i - 1)
* sizeof (struct cl_decoded_option)));
}
--i;
@@ -209,7 +295,24 @@ darwin_driver_init (unsigned int *decoded_options_count,
case OPT_mmacosx_version_min_:
seen_version_min = true;
- vers_string = xstrndup ((*decoded_options)[i].arg, 32);
+ vers_string =
+ validate_macosx_version_min ((*decoded_options)[i].arg);
+ if (vers_string == NULL)
+ warning (0, "%qs is not valid for %<mmacosx-version-min%>",
+ (*decoded_options)[i].arg);
+ else if (vers_string == (*decoded_options)[i].arg)
+ vers_string = xstrndup ((*decoded_options)[i].arg, 32);
+ /* Now we've examined it, and verified/re-written, put it to
+ one side and append later. */
+ if (*decoded_options_count > i) {
+ memmove (*decoded_options + i,
+ *decoded_options + i + 1,
+ ((*decoded_options_count - i - 1)
+ * sizeof (struct cl_decoded_option)));
+ }
+ --i;
+ --*decoded_options_count;
+ break;
default:
break;
@@ -276,22 +379,20 @@ darwin_driver_init (unsigned int *decoded_options_count,
so that we can figure out the mechanism and source for the sysroot to
be used. */
if (! seen_version_min && *decoded_options_count > 1)
- {
- /* Not set by the User, try to figure it out. */
- vers_string = darwin_default_min_version ();
- if (vers_string != NULL)
- {
- ++*decoded_options_count;
- *decoded_options = XRESIZEVEC (struct cl_decoded_option,
- *decoded_options,
- *decoded_options_count);
- generate_option (OPT_mmacosx_version_min_, vers_string, 1, CL_DRIVER,
- &(*decoded_options)[*decoded_options_count - 1]);
- }
- }
- /* Create and push the major version for assemblers that need it. */
+ /* Not set by the User, try to figure it out. */
+ vers_string = darwin_default_min_version ();
+
+ /* Create and push a cleaned up version, plus the major version for
+ assemblers and other cases that need it. */
if (vers_string != NULL)
{
+ ++*decoded_options_count;
+ *decoded_options = XRESIZEVEC (struct cl_decoded_option,
+ *decoded_options,
+ *decoded_options_count);
+ generate_option (OPT_mmacosx_version_min_, vers_string, 1, CL_DRIVER,
+ &(*decoded_options)[*decoded_options_count - 1]);
+
char *asm_major = NULL;
const char *first_period = strchr(vers_string, '.');
if (first_period != NULL)
diff --git a/gcc/config/darwin.c b/gcc/config/darwin.c
index f62f1c7..ef6e389 100644
--- a/gcc/config/darwin.c
+++ b/gcc/config/darwin.c
@@ -78,12 +78,6 @@ along with GCC; see the file COPYING3. If not see
of MACHO_SYMBOL_STATIC for the code that handles @code{static}
symbol indirection. */
-/* For darwin >= 9 (OSX 10.5) the linker is capable of making the necessary
- branch islands and we no longer need to emit darwin stubs.
- However, if we are generating code for earlier systems (or for use in the
- kernel) the stubs might still be required, and this will be set true. */
-int darwin_emit_branch_islands = false;
-
typedef struct GTY(()) cdtor_record {
rtx symbol;
int priority; /* [con/de]structor priority */
@@ -105,6 +99,10 @@ int generating_for_darwin_version ;
for weak or single-definition items. */
static bool ld_uses_coal_sects = false;
+/* Very old (ld_classic) linkers need a symbol to mark the start of
+ each FDE. */
+static bool ld_needs_eh_markers = false;
+
/* Section names. */
section * darwin_sections[NUM_DARWIN_SECTIONS];
@@ -117,7 +115,7 @@ section * darwin_sections[NUM_DARWIN_SECTIONS];
/* True if we're setting __attribute__ ((ms_struct)). */
int darwin_ms_struct = false;
-/* Earlier versions of Darwin as do not recognize an alignment field in
+/* Earlier versions of Darwin as do not recognize an alignment field in
.comm directives, this should be set for versions that allow it. */
int emit_aligned_common = false;
@@ -129,8 +127,8 @@ output_objc_section_asm_op (const void *directive)
{
static bool been_here = false;
- /* The NeXT ObjC Runtime requires these sections to be present and in
- order in the object. The code below implements this by emitting
+ /* The NeXT ObjC Runtime requires these sections to be present and in
+ order in the object. The code below implements this by emitting
a section header for each ObjC section the first time that an ObjC
section is requested. */
if (! been_here)
@@ -240,7 +238,7 @@ name_needs_quotes (const char *name)
{
int c;
while ((c = *name++) != '\0')
- if (! ISIDNUM (c)
+ if (! ISIDNUM (c)
&& c != '.' && c != '$' && c != '_' )
return 1;
return 0;
@@ -712,8 +710,8 @@ machopic_indirect_data_reference (rtx orig, rtx reg)
ptr_ref = gen_const_mem (Pmode, ptr_ref);
machopic_define_symbol (ptr_ref);
- if (DARWIN_X86
- && reg
+ if (DARWIN_X86
+ && reg
&& MACHO_DYNAMIC_NO_PIC_P)
{
emit_insn (gen_rtx_SET (reg, ptr_ref));
@@ -729,12 +727,12 @@ machopic_indirect_data_reference (rtx orig, rtx reg)
appropriate. */
if (GET_CODE (XEXP (orig, 0)) == PLUS)
return machopic_indirect_data_reference (XEXP (orig, 0), reg);
- else
+ else
return orig;
}
else if (GET_CODE (orig) == MEM)
{
- XEXP (ptr_ref, 0) =
+ XEXP (ptr_ref, 0) =
machopic_indirect_data_reference (XEXP (orig, 0), reg);
return ptr_ref;
}
@@ -790,7 +788,7 @@ machopic_indirect_data_reference (rtx orig, rtx reg)
rtx
machopic_indirect_call_target (rtx target)
{
- if (! darwin_emit_branch_islands)
+ if (! darwin_picsymbol_stubs)
return target;
if (GET_CODE (target) != MEM)
@@ -1264,8 +1262,8 @@ static section *
darwin_mergeable_string_section (tree exp,
unsigned HOST_WIDE_INT align)
{
- /* Darwin's ld expects to see non-writable string literals in the .cstring
- section. Later versions of ld check and complain when CFStrings are
+ /* Darwin's ld expects to see non-writable string literals in the .cstring
+ section. Later versions of ld check and complain when CFStrings are
enabled. Therefore we shall force the strings into .cstring since we
don't support writable ones anyway. */
if ((darwin_constant_cfstrings || flag_merge_constants)
@@ -1298,8 +1296,8 @@ darwin_mergeable_constant_section (tree exp,
machine_mode mode = DECL_MODE (exp);
unsigned int modesize = GET_MODE_BITSIZE (mode);
- if (DARWIN_SECTION_ANCHORS
- && flag_section_anchors
+ if (DARWIN_SECTION_ANCHORS
+ && flag_section_anchors
&& zsize)
return darwin_sections[zobj_const_section];
@@ -1345,14 +1343,14 @@ machopic_reloc_rw_mask (void)
/* We have to deal with ObjC/C++ metadata section placement in the common
code, since it will also be called from LTO.
-
+
Return metadata attributes, if present (searching for ABI=2 first)
Return NULL_TREE if no such attributes are found. */
static tree
is_objc_metadata (tree decl)
{
- if (DECL_P (decl)
+ if (DECL_P (decl)
&& (TREE_CODE (decl) == VAR_DECL || TREE_CODE (decl) == CONST_DECL)
&& DECL_ATTRIBUTES (decl))
{
@@ -1531,11 +1529,11 @@ machopic_select_section (tree decl,
&& !lookup_attribute ("weak_import", DECL_ATTRIBUTES (decl)));
zsize = (DECL_P (decl)
- && (TREE_CODE (decl) == VAR_DECL || TREE_CODE (decl) == CONST_DECL)
+ && (TREE_CODE (decl) == VAR_DECL || TREE_CODE (decl) == CONST_DECL)
&& tree_to_uhwi (DECL_SIZE_UNIT (decl)) == 0);
one = DECL_P (decl)
- && TREE_CODE (decl) == VAR_DECL
+ && TREE_CODE (decl) == VAR_DECL
&& DECL_COMDAT_GROUP (decl);
use_coal = (weak || one) && ld_uses_coal_sects;
@@ -1576,17 +1574,17 @@ machopic_select_section (tree decl,
{
if (ro)
base_section = darwin_sections[const_data_coal_section];
- else
+ else
base_section = darwin_sections[data_coal_section];
}
- else if (DARWIN_SECTION_ANCHORS
+ else if (DARWIN_SECTION_ANCHORS
&& flag_section_anchors
&& zsize)
{
/* If we're doing section anchors, then punt zero-sized objects into
their own sections so that they don't interfere with offset
computation for the remaining vars. This does not need to be done
- for stuff in mergeable sections, since these are ineligible for
+ for stuff in mergeable sections, since these are ineligible for
anchors. */
if (ro)
base_section = darwin_sections[zobj_const_data_section];
@@ -1618,10 +1616,10 @@ machopic_select_section (tree decl,
gcc_unreachable ();
}
- /* Darwin weird special cases.
+ /* Darwin weird special cases.
a) OBJC Meta-data. */
- if (DECL_P (decl)
- && (TREE_CODE (decl) == VAR_DECL
+ if (DECL_P (decl)
+ && (TREE_CODE (decl) == VAR_DECL
|| TREE_CODE (decl) == CONST_DECL)
&& DECL_ATTRIBUTES (decl))
{
@@ -1673,10 +1671,10 @@ machopic_select_section (tree decl,
{
const char *name = IDENTIFIER_POINTER (DECL_NAME (decl));
static bool warned_objc_46 = false;
- /* We shall assert that zero-sized objects are an error in ObjC
+ /* We shall assert that zero-sized objects are an error in ObjC
meta-data. */
gcc_assert (tree_to_uhwi (DECL_SIZE_UNIT (decl)) != 0);
-
+
/* ??? This mechanism for determining the metadata section is
broken when LTO is in use, since the frontend that generated
the data is not identified. We will keep the capability for
@@ -1690,7 +1688,7 @@ machopic_select_section (tree decl,
" and will be removed in 4.7");
warned_objc_46 = true;
}
-
+
if (!strncmp (name, "_OBJC_CLASS_METHODS_", 20))
return darwin_sections[objc_cls_meth_section];
else if (!strncmp (name, "_OBJC_INSTANCE_METHODS_", 23))
@@ -1816,12 +1814,12 @@ sort_cdtor_records (const void * a, const void * b)
return 0;
}
-static void
+static void
finalize_ctors ()
{
unsigned int i;
cdtor_record *elt;
-
+
if (MACHOPIC_INDIRECT)
switch_to_section (darwin_sections[mod_init_section]);
else
@@ -1863,11 +1861,11 @@ darwin_globalize_label (FILE *stream, const char *name)
default_globalize_label (stream, name);
}
-/* This routine returns non-zero if 'name' starts with the special objective-c
- anonymous file-scope static name. It accommodates c++'s mangling of such
+/* This routine returns non-zero if 'name' starts with the special objective-c
+ anonymous file-scope static name. It accommodates c++'s mangling of such
symbols (in this case the symbols will have form _ZL{d}*_OBJC_* d=digit). */
-
-int
+
+int
darwin_label_is_anonymous_local_objc_name (const char *name)
{
const unsigned char *p = (const unsigned char *) name;
@@ -2085,19 +2083,19 @@ darwin_emit_unwind_label (FILE *file, tree decl, int for_eh, int empty)
char buf[32];
static int invok_count = 0;
static tree last_fun_decl = NULL_TREE;
-
- /* We use the linker to emit the .eh labels for Darwin 9 and above. */
- if (! for_eh || generating_for_darwin_version >= 9)
+
+ /* Modern linkers can produce distinct FDEs without compiler support. */
+ if (! for_eh || ! ld_needs_eh_markers)
return;
- /* FIXME: This only works when the eh for all sections of a function is
+ /* FIXME: This only works when the eh for all sections of a function are
emitted at the same time. If that changes, we would need to use a lookup
table of some form to determine what to do. Also, we should emit the
unadorned label for the partition containing the public label for a
function. This is of limited use, probably, since we do not currently
enable partitioning. */
strcpy (buf, ".eh");
- if (decl && TREE_CODE (decl) == FUNCTION_DECL)
+ if (decl && TREE_CODE (decl) == FUNCTION_DECL)
{
if (decl == last_fun_decl)
{
@@ -2193,8 +2191,8 @@ darwin_non_lazy_pcrel (FILE *file, rtx addr)
The machopic_define_symbol calls are telling the machopic subsystem
that the name *is* defined in this module, so it doesn't need to
make them indirect. */
-void
-darwin_asm_declare_object_name (FILE *file,
+void
+darwin_asm_declare_object_name (FILE *file,
const char *nam, tree decl)
{
const char *xname = nam;
@@ -2203,11 +2201,11 @@ darwin_asm_declare_object_name (FILE *file,
weak = (DECL_P (decl)
&& DECL_WEAK (decl)
- && !lookup_attribute ("weak_import",
+ && !lookup_attribute ("weak_import",
DECL_ATTRIBUTES (decl)));
- local_def = DECL_INITIAL (decl) || (TREE_STATIC (decl)
- && (!DECL_COMMON (decl)
+ local_def = DECL_INITIAL (decl) || (TREE_STATIC (decl)
+ && (!DECL_COMMON (decl)
|| !TREE_PUBLIC (decl)));
if (GET_CODE (XEXP (DECL_RTL (decl), 0)) != SYMBOL_REF)
@@ -2225,17 +2223,17 @@ darwin_asm_declare_object_name (FILE *file,
#ifdef DEBUG_DARWIN_MEM_ALLOCATORS
fprintf (file, "# dadon: %s %s (%llu, %u) local %d weak %d"
" stat %d com %d pub %d t-const %d t-ro %d init %lx\n",
- xname, (TREE_CODE (decl) == VAR_DECL?"var":"const"),
- (unsigned long long)size, DECL_ALIGN (decl), local_def,
+ xname, (TREE_CODE (decl) == VAR_DECL?"var":"const"),
+ (unsigned long long)size, DECL_ALIGN (decl), local_def,
DECL_WEAK (decl), TREE_STATIC (decl), DECL_COMMON (decl),
TREE_PUBLIC (decl), TREE_CONSTANT (decl), TREE_READONLY (decl),
- (unsigned long)DECL_INITIAL (decl));
+ (unsigned long)DECL_INITIAL (decl));
#endif
- /* Darwin needs help to support local zero-sized objects.
+ /* Darwin needs help to support local zero-sized objects.
They must be made at least one byte, and the section containing must be
marked as unsuitable for section-anchors (see storage allocators below).
-
+
For non-zero objects this output is handled by varasm.c.
*/
if (!size)
@@ -2256,7 +2254,7 @@ fprintf (file, "# dadon: %s %s (%llu, %u) local %d weak %d"
/* Check that we've correctly picked up the zero-sized item and placed it
properly. */
gcc_assert ((!DARWIN_SECTION_ANCHORS || !flag_section_anchors)
- || (in_section
+ || (in_section
&& (in_section->common.flags & SECTION_NO_ANCHOR)));
}
else
@@ -2277,7 +2275,7 @@ darwin_asm_declare_constant_name (FILE *file, const char *name,
/* Check that we've correctly picked up the zero-sized item and placed it
properly. */
gcc_assert ((!DARWIN_SECTION_ANCHORS || !flag_section_anchors)
- || (in_section
+ || (in_section
&& (in_section->common.flags & SECTION_NO_ANCHOR)));
}
}
@@ -2303,7 +2301,7 @@ darwin_asm_declare_constant_name (FILE *file, const char *name,
/* Emit a chunk of data for items coalesced by the linker. */
static void
darwin_emit_weak_or_comdat (FILE *fp, tree decl, const char *name,
- unsigned HOST_WIDE_INT size,
+ unsigned HOST_WIDE_INT size,
bool use_coal,
unsigned int align)
{
@@ -2325,7 +2323,7 @@ darwin_emit_weak_or_comdat (FILE *fp, tree decl, const char *name,
if (TREE_PUBLIC (decl))
darwin_globalize_label (fp, name);
- /* ... and we let it deal with outputting one byte of zero for them too. */
+ /* ... and we let it deal with outputting one byte of zero for them too. */
darwin_asm_declare_object_name (fp, name, decl);
if (size)
assemble_zeros (size);
@@ -2334,7 +2332,7 @@ darwin_emit_weak_or_comdat (FILE *fp, tree decl, const char *name,
/* Emit a chunk of data for ObjC meta-data that got placed in BSS erroneously. */
static void
darwin_emit_objc_zeroed (FILE *fp, tree decl, const char *name,
- unsigned HOST_WIDE_INT size,
+ unsigned HOST_WIDE_INT size,
unsigned int align, tree meta)
{
section *ocs = data_section;
@@ -2350,14 +2348,14 @@ darwin_emit_objc_zeroed (FILE *fp, tree decl, const char *name,
gcc_assert (size);
fprintf (fp, "\t.align\t%d\n", floor_log2 (align / BITS_PER_UNIT));
- /* ... and we let it deal with outputting one byte of zero for them too. */
+ /* ... and we let it deal with outputting one byte of zero for them too. */
darwin_asm_declare_object_name (fp, name, decl);
assemble_zeros (size);
}
/* This routine emits 'local' storage:
- When Section Anchors are off this routine emits .zerofill commands in
+ When Section Anchors are off this routine emits .zerofill commands in
sections named for their alignment.
When Section Anchors are on, smaller (non-zero-sized) items are placed in
@@ -2366,8 +2364,8 @@ darwin_emit_objc_zeroed (FILE *fp, tree decl, const char *name,
The routine has no checking - it is all assumed to be done by the caller.
*/
static void
-darwin_emit_local_bss (FILE *fp, tree decl, const char *name,
- unsigned HOST_WIDE_INT size,
+darwin_emit_local_bss (FILE *fp, tree decl, const char *name,
+ unsigned HOST_WIDE_INT size,
unsigned int l2align)
{
/* FIXME: We have a fudge to make this work with Java even when the target does
@@ -2395,17 +2393,17 @@ darwin_emit_local_bss (FILE *fp, tree decl, const char *name,
if (l2align)
fprintf (fp, "\t.align\t%u\n", l2align);
- assemble_name (fp, name);
+ assemble_name (fp, name);
fprintf (fp, ":\n\t.space\t" HOST_WIDE_INT_PRINT_UNSIGNED"\n", size);
}
- else
+ else
{
/* When we are on a non-section anchor target, we can get zero-sized
items here. However, all we need to do is to bump them to one byte
and the section alignment will take care of the rest. */
char secnam[64];
unsigned int flags ;
- snprintf (secnam, 64, "__DATA,__%sbss%u", ((size)?"":"zo_"),
+ snprintf (secnam, 64, "__DATA,__%sbss%u", ((size)?"":"zo_"),
(unsigned) l2align);
/* We can't anchor (yet, if ever) in zerofill sections, because we can't
switch to them and emit a label. */
@@ -2431,12 +2429,12 @@ darwin_emit_local_bss (FILE *fp, tree decl, const char *name,
/* Emit a chunk of common. */
static void
darwin_emit_common (FILE *fp, const char *name,
- unsigned HOST_WIDE_INT size, unsigned int align)
+ unsigned HOST_WIDE_INT size, unsigned int align)
{
unsigned HOST_WIDE_INT rounded;
unsigned int l2align;
- /* Earlier systems complain if the alignment exceeds the page size.
+ /* Earlier systems complain if the alignment exceeds the page size.
The magic number is 4096 * 8 - hard-coded for legacy systems. */
if (!emit_aligned_common && (align > 32768UL))
align = 4096UL; /* In units. */
@@ -2447,9 +2445,9 @@ darwin_emit_common (FILE *fp, const char *name,
if (!align)
align = 1;
- /* For earlier toolchains, we need to emit the var as a rounded size to
+ /* For earlier toolchains, we need to emit the var as a rounded size to
tell ld the alignment. */
- if (size < align)
+ if (size < align)
rounded = align;
else
rounded = (size + (align-1)) & ~(align-1);
@@ -2470,7 +2468,7 @@ darwin_emit_common (FILE *fp, const char *name,
fputs ("\t.comm\t", fp);
assemble_name (fp, name);
- fprintf (fp, "," HOST_WIDE_INT_PRINT_UNSIGNED,
+ fprintf (fp, "," HOST_WIDE_INT_PRINT_UNSIGNED,
emit_aligned_common?size:rounded);
if (l2align && emit_aligned_common)
fprintf (fp, ",%u", l2align);
@@ -2492,18 +2490,18 @@ darwin_output_aligned_bss (FILE *fp, tree decl, const char *name,
one = DECL_ONE_ONLY (decl);
weak = (DECL_P (decl)
&& DECL_WEAK (decl)
- && !lookup_attribute ("weak_import",
+ && !lookup_attribute ("weak_import",
DECL_ATTRIBUTES (decl)));
#ifdef DEBUG_DARWIN_MEM_ALLOCATORS
fprintf (fp, "# albss: %s (%lld,%d) ro %d cst %d stat %d com %d"
" pub %d weak %d one %d init %lx\n",
- name, (long long)size, (int)align, TREE_READONLY (decl),
+ name, (long long)size, (int)align, TREE_READONLY (decl),
TREE_CONSTANT (decl), TREE_STATIC (decl), DECL_COMMON (decl),
- pub, weak, one, (unsigned long)DECL_INITIAL (decl));
+ pub, weak, one, (unsigned long)DECL_INITIAL (decl));
#endif
- /* ObjC metadata can get put in BSS because varasm.c decides it's BSS
+ /* ObjC metadata can get put in BSS because varasm.c decides it's BSS
before the target has a chance to comment. */
if ((meta = is_objc_metadata (decl)))
{
@@ -2512,8 +2510,8 @@ fprintf (fp, "# albss: %s (%lld,%d) ro %d cst %d stat %d com %d"
}
/* Check that any initializer is valid. */
- gcc_assert ((DECL_INITIAL (decl) == NULL)
- || (DECL_INITIAL (decl) == error_mark_node)
+ gcc_assert ((DECL_INITIAL (decl) == NULL)
+ || (DECL_INITIAL (decl) == error_mark_node)
|| initializer_zerop (DECL_INITIAL (decl)));
gcc_assert (DECL_SECTION_NAME (decl) == NULL);
@@ -2525,7 +2523,7 @@ fprintf (fp, "# albss: %s (%lld,%d) ro %d cst %d stat %d com %d"
l2align = floor_log2 (align / BITS_PER_UNIT);
gcc_assert (l2align <= L2_MAX_OFILE_ALIGNMENT);
-
+
last_assemble_variable_decl = decl;
/* We would rather not have to check this here - but it seems that we might
@@ -2533,24 +2531,24 @@ fprintf (fp, "# albss: %s (%lld,%d) ro %d cst %d stat %d com %d"
if (one || weak)
{
/* Weak or COMDAT objects are put in mergeable sections. */
- darwin_emit_weak_or_comdat (fp, decl, name, size,
+ darwin_emit_weak_or_comdat (fp, decl, name, size,
ld_uses_coal_sects, DECL_ALIGN (decl));
return;
- }
+ }
/* If this is not public, then emit according to local rules. */
if (!pub)
{
- darwin_emit_local_bss (fp, decl, name, size, l2align);
+ darwin_emit_local_bss (fp, decl, name, size, l2align);
return;
}
/* So we have a public symbol (small item fudge for Java, see above). */
- if ((DARWIN_SECTION_ANCHORS && flag_section_anchors && size < BYTES_ZFILL)
+ if ((DARWIN_SECTION_ANCHORS && flag_section_anchors && size < BYTES_ZFILL)
|| (size && size <= 2))
{
/* Put smaller objects in data, where the section anchors system can get
- them. However, if they are zero-sized punt them to yet a different
+ them. However, if they are zero-sized punt them to yet a different
section (that is not allowed to participate in anchoring). */
if (!size)
{
@@ -2570,7 +2568,7 @@ fprintf (fp, "# albss: %s (%lld,%d) ro %d cst %d stat %d com %d"
assemble_name (fp, name);
fprintf (fp, ":\n\t.space\t" HOST_WIDE_INT_PRINT_UNSIGNED"\n", size);
}
- else
+ else
{
char secnam[64];
unsigned int flags ;
@@ -2600,7 +2598,7 @@ fprintf (fp, "# albss: %s (%lld,%d) ro %d cst %d stat %d com %d"
supports this). */
void
darwin_asm_output_aligned_decl_common (FILE *fp, tree decl, const char *name,
- unsigned HOST_WIDE_INT size,
+ unsigned HOST_WIDE_INT size,
unsigned int align)
{
unsigned int l2align;
@@ -2611,7 +2609,7 @@ darwin_asm_output_aligned_decl_common (FILE *fp, tree decl, const char *name,
if (decl==NULL)
{
#ifdef DEBUG_DARWIN_MEM_ALLOCATORS
-fprintf (fp, "# adcom: %s (%d,%d) decl=0x0\n", name, (int)size, (int)align);
+fprintf (fp, "# adcom: %s (%d,%d) decl=0x0\n", name, (int)size, (int)align);
#endif
darwin_emit_common (fp, name, size, align);
return;
@@ -2620,18 +2618,18 @@ fprintf (fp, "# adcom: %s (%d,%d) decl=0x0\n", name, (int)size, (int)align);
one = DECL_ONE_ONLY (decl);
weak = (DECL_P (decl)
&& DECL_WEAK (decl)
- && !lookup_attribute ("weak_import",
+ && !lookup_attribute ("weak_import",
DECL_ATTRIBUTES (decl)));
#ifdef DEBUG_DARWIN_MEM_ALLOCATORS
fprintf (fp, "# adcom: %s (%lld,%d) ro %d cst %d stat %d com %d pub %d"
" weak %d one %d init %lx\n",
- name, (long long)size, (int)align, TREE_READONLY (decl),
+ name, (long long)size, (int)align, TREE_READONLY (decl),
TREE_CONSTANT (decl), TREE_STATIC (decl), DECL_COMMON (decl),
- TREE_PUBLIC (decl), weak, one, (unsigned long)DECL_INITIAL (decl));
+ TREE_PUBLIC (decl), weak, one, (unsigned long)DECL_INITIAL (decl));
#endif
- /* ObjC metadata can get put in BSS because varasm.c decides it's BSS
+ /* ObjC metadata can get put in BSS because varasm.c decides it's BSS
before the target has a chance to comment. */
if ((meta = is_objc_metadata (decl)))
{
@@ -2647,24 +2645,24 @@ fprintf (fp, "# adcom: %s (%lld,%d) ro %d cst %d stat %d com %d pub %d"
if (one || weak)
{
/* Weak or COMDAT objects are put in mergable sections. */
- darwin_emit_weak_or_comdat (fp, decl, name, size,
+ darwin_emit_weak_or_comdat (fp, decl, name, size,
ld_uses_coal_sects, DECL_ALIGN (decl));
return;
- }
+ }
- /* We should only get here for DECL_COMMON, with a zero init (and, in
+ /* We should only get here for DECL_COMMON, with a zero init (and, in
principle, only for public symbols too - although we deal with local
ones below). */
/* Check the initializer is OK. */
- gcc_assert (DECL_COMMON (decl)
- && ((DECL_INITIAL (decl) == NULL)
- || (DECL_INITIAL (decl) == error_mark_node)
+ gcc_assert (DECL_COMMON (decl)
+ && ((DECL_INITIAL (decl) == NULL)
+ || (DECL_INITIAL (decl) == error_mark_node)
|| initializer_zerop (DECL_INITIAL (decl))));
last_assemble_variable_decl = decl;
- if (!size || !align)
+ if (!size || !align)
align = DECL_ALIGN (decl);
l2align = floor_log2 (align / BITS_PER_UNIT);
@@ -2674,13 +2672,13 @@ fprintf (fp, "# adcom: %s (%lld,%d) ro %d cst %d stat %d com %d pub %d"
if (TREE_PUBLIC (decl) != 0)
darwin_emit_common (fp, name, size, align);
else
- darwin_emit_local_bss (fp, decl, name, size, l2align);
+ darwin_emit_local_bss (fp, decl, name, size, l2align);
}
/* Output a chunk of BSS with alignment specfied. */
void
-darwin_asm_output_aligned_decl_local (FILE *fp, tree decl, const char *name,
- unsigned HOST_WIDE_INT size,
+darwin_asm_output_aligned_decl_local (FILE *fp, tree decl, const char *name,
+ unsigned HOST_WIDE_INT size,
unsigned int align)
{
unsigned long l2align;
@@ -2690,18 +2688,18 @@ darwin_asm_output_aligned_decl_local (FILE *fp, tree decl, const char *name,
one = DECL_ONE_ONLY (decl);
weak = (DECL_P (decl)
&& DECL_WEAK (decl)
- && !lookup_attribute ("weak_import",
+ && !lookup_attribute ("weak_import",
DECL_ATTRIBUTES (decl)));
#ifdef DEBUG_DARWIN_MEM_ALLOCATORS
fprintf (fp, "# adloc: %s (%lld,%d) ro %d cst %d stat %d one %d pub %d"
" weak %d init %lx\n",
- name, (long long)size, (int)align, TREE_READONLY (decl),
+ name, (long long)size, (int)align, TREE_READONLY (decl),
TREE_CONSTANT (decl), TREE_STATIC (decl), one, TREE_PUBLIC (decl),
- weak , (unsigned long)DECL_INITIAL (decl));
+ weak , (unsigned long)DECL_INITIAL (decl));
#endif
- /* ObjC metadata can get put in BSS because varasm.c decides it's BSS
+ /* ObjC metadata can get put in BSS because varasm.c decides it's BSS
before the target has a chance to comment. */
if ((meta = is_objc_metadata (decl)))
{
@@ -2717,16 +2715,16 @@ fprintf (fp, "# adloc: %s (%lld,%d) ro %d cst %d stat %d one %d pub %d"
if (one || weak)
{
/* Weak or COMDAT objects are put in mergable sections. */
- darwin_emit_weak_or_comdat (fp, decl, name, size,
+ darwin_emit_weak_or_comdat (fp, decl, name, size,
ld_uses_coal_sects, DECL_ALIGN (decl));
return;
- }
+ }
/* .. and it should be suitable for placement in local mem. */
gcc_assert(!TREE_PUBLIC (decl) && !DECL_COMMON (decl));
/* .. and any initializer must be all-zero. */
- gcc_assert ((DECL_INITIAL (decl) == NULL)
- || (DECL_INITIAL (decl) == error_mark_node)
+ gcc_assert ((DECL_INITIAL (decl) == NULL)
+ || (DECL_INITIAL (decl) == error_mark_node)
|| initializer_zerop (DECL_INITIAL (decl)));
last_assemble_variable_decl = decl;
@@ -2765,7 +2763,7 @@ darwin_assemble_visibility (tree decl, int vis)
/* vec used by darwin_asm_dwarf_section.
Maybe a hash tab would be better here - but the intention is that this is
- a very short list (fewer than 16 items) and each entry should (ideally,
+ a very short list (fewer than 16 items) and each entry should (ideally,
eventually) only be presented once.
A structure to hold a dwarf debug section used entry. */
@@ -2780,7 +2778,7 @@ dwarf_sect_used_entry;
/* A list of used __DWARF sections. */
static GTY (()) vec<dwarf_sect_used_entry, va_gc> *dwarf_sect_names_table;
-/* This is called when we are asked to assemble a named section and the
+/* This is called when we are asked to assemble a named section and the
name begins with __DWARF,. We keep a list of the section names (without
the __DWARF, prefix) and use this to emit our required start label on the
first switch to each section. */
@@ -2821,7 +2819,7 @@ darwin_asm_dwarf_section (const char *name, unsigned int flags,
if (dwarf_sect_names_table == NULL)
vec_alloc (dwarf_sect_names_table, 16);
else
- for (i = 0;
+ for (i = 0;
dwarf_sect_names_table->iterate (i, &ref);
i++)
{
@@ -2939,12 +2937,10 @@ darwin_file_end (void)
if (flag_objc_abi >= 2)
{
flags = 16;
- output_section_asm_op
- (darwin_sections[objc2_image_info_section]->unnamed.data);
+ switch_to_section (darwin_sections[objc2_image_info_section]);
}
else
- output_section_asm_op
- (darwin_sections[objc_image_info_section]->unnamed.data);
+ switch_to_section (darwin_sections[objc_image_info_section]);
ASM_OUTPUT_ALIGN (asm_out_file, 2);
fputs ("L_OBJC_ImageInfo:\n", asm_out_file);
@@ -3163,9 +3159,9 @@ darwin_override_options (void)
" %<-fnext-runtime%>");
}
- /* Don't emit DWARF3/4 unless specifically selected. This is a
+ /* Don't emit DWARF3/4 unless specifically selected. This is a
workaround for tool bugs. */
- if (!global_options_set.x_dwarf_strict)
+ if (!global_options_set.x_dwarf_strict)
dwarf_strict = 1;
if (!global_options_set.x_dwarf_version)
dwarf_version = 2;
@@ -3178,7 +3174,7 @@ darwin_override_options (void)
global_options_set.x_dwarf_split_debug_info = 0;
}
- /* Do not allow unwind tables to be generated by default for m32.
+ /* Do not allow unwind tables to be generated by default for m32.
fnon-call-exceptions will override this, regardless of what we do. */
if (generating_for_darwin_version < 10
&& !global_options_set.x_flag_asynchronous_unwind_tables
@@ -3212,7 +3208,7 @@ darwin_override_options (void)
/* FIXME: flag_objc_sjlj_exceptions is no longer needed since there is only
one valid choice of exception scheme for each runtime. */
if (!global_options_set.x_flag_objc_sjlj_exceptions)
- global_options.x_flag_objc_sjlj_exceptions =
+ global_options.x_flag_objc_sjlj_exceptions =
flag_next_runtime && !TARGET_64BIT;
/* FIXME: and this could be eliminated then too. */
@@ -3237,7 +3233,7 @@ darwin_override_options (void)
flag_unwind_tables = 0;
flag_asynchronous_unwind_tables = 0;
/* We still need to emit branch islands for kernel context. */
- darwin_emit_branch_islands = true;
+ darwin_picsymbol_stubs = true;
}
if (flag_var_tracking_uninit == 0
@@ -3261,11 +3257,44 @@ darwin_override_options (void)
flag_pic = 2;
}
- /* It is assumed that branch island stubs are needed for earlier systems. */
- if (generating_for_darwin_version < 9)
- darwin_emit_branch_islands = true;
- else
- emit_aligned_common = true; /* Later systems can support aligned common. */
+ /* Linkers >= ld64-62.1 (at least) are capable of making the necessary PIC
+ indirections and we no longer need to emit pic symbol stubs.
+ However, if we are generating code for earlier ones (or for use in the
+ kernel) the stubs might still be required, and this will be set true.
+ If the user sets it on or off - then that takes precedence.
+
+ Linkers that don't need stubs, don't need the EH symbol markers either.
+ */
+
+ if (!global_options_set.x_darwin_picsymbol_stubs)
+ {
+ if (darwin_target_linker)
+ {
+ if (strverscmp (darwin_target_linker, MIN_LD64_OMIT_STUBS) < 0)
+ {
+ darwin_picsymbol_stubs = true;
+ ld_needs_eh_markers = true;
+ }
+ }
+ else if (generating_for_darwin_version < 9)
+ {
+ /* If we don't know the linker version and we're targeting an old
+ system, we know no better than to assume the use of an earlier
+ linker. */
+ darwin_picsymbol_stubs = true;
+ ld_needs_eh_markers = true;
+ }
+ }
+ else if (DARWIN_X86 && darwin_picsymbol_stubs && TARGET_64BIT)
+ {
+ inform (input_location,
+ "%<-mpic-symbol-stubs%> is not required for 64b code (ignored)");
+ darwin_picsymbol_stubs = false;
+ }
+
+ if (generating_for_darwin_version >= 9)
+ /* Later systems can support aligned common. */
+ emit_aligned_common = true;
/* The c_dialect...() macros are not available to us here. */
darwin_running_cxx = (strstr (lang_hooks.name, "C++") != 0);
@@ -3346,7 +3375,7 @@ static GTY (()) hash_table<cfstring_hasher> *cfstring_htab;
static tree
add_builtin_field_decl (tree type, const char *name, tree **chain)
{
- tree field = build_decl (BUILTINS_LOCATION, FIELD_DECL,
+ tree field = build_decl (BUILTINS_LOCATION, FIELD_DECL,
get_identifier (name), type);
if (*chain != NULL)
@@ -3362,9 +3391,9 @@ darwin_init_cfstring_builtins (unsigned builtin_cfstring)
tree cfsfun, fields, pccfstring_ftype_pcchar;
tree *chain = NULL;
- darwin_builtin_cfstring =
+ darwin_builtin_cfstring =
(enum built_in_function) builtin_cfstring;
-
+
/* struct __builtin_CFString {
const int *isa; (will point at
int flags; __CFConstantStringClassReference)
@@ -3372,10 +3401,10 @@ darwin_init_cfstring_builtins (unsigned builtin_cfstring)
long length;
}; */
- pcint_type_node = build_pointer_type
+ pcint_type_node = build_pointer_type
(build_qualified_type (integer_type_node, TYPE_QUAL_CONST));
- pcchar_type_node = build_pointer_type
+ pcchar_type_node = build_pointer_type
(build_qualified_type (char_type_node, TYPE_QUAL_CONST));
cfstring_type_node = (*lang_hooks.types.make_type) (RECORD_TYPE);
@@ -3391,13 +3420,13 @@ darwin_init_cfstring_builtins (unsigned builtin_cfstring)
/* const struct __builtin_CFstring *
__builtin___CFStringMakeConstantString (const char *); */
- ccfstring_type_node = build_qualified_type
+ ccfstring_type_node = build_qualified_type
(cfstring_type_node, TYPE_QUAL_CONST);
pccfstring_type_node = build_pointer_type (ccfstring_type_node);
- pccfstring_ftype_pcchar = build_function_type_list
+ pccfstring_ftype_pcchar = build_function_type_list
(pccfstring_type_node, pcchar_type_node, NULL_TREE);
- cfsfun = build_decl (BUILTINS_LOCATION, FUNCTION_DECL,
+ cfsfun = build_decl (BUILTINS_LOCATION, FUNCTION_DECL,
get_identifier ("__builtin___CFStringMakeConstantString"),
pccfstring_ftype_pcchar);
@@ -3422,7 +3451,7 @@ darwin_init_cfstring_builtins (unsigned builtin_cfstring)
(*lang_hooks.decls.pushdecl) (cfstring_class_reference);
DECL_EXTERNAL (cfstring_class_reference) = 1;
rest_of_decl_compilation (cfstring_class_reference, 0, 0);
-
+
/* Initialize the hash table used to hold the constant CFString objects. */
cfstring_htab = hash_table<cfstring_hasher>::create_ggc (31);
@@ -3430,16 +3459,16 @@ darwin_init_cfstring_builtins (unsigned builtin_cfstring)
}
tree
-darwin_fold_builtin (tree fndecl, int n_args, tree *argp,
+darwin_fold_builtin (tree fndecl, int n_args, tree *argp,
bool ARG_UNUSED (ignore))
{
unsigned int fcode = DECL_FUNCTION_CODE (fndecl);
-
+
if (fcode == darwin_builtin_cfstring)
{
if (!darwin_constant_cfstrings)
{
- error ("built-in function %qD requires the"
+ error ("built-in function %qD requires the"
" %<-mconstant-cfstrings%> flag", fndecl);
return error_mark_node;
}
@@ -3578,12 +3607,12 @@ darwin_build_constant_cfstring (tree str)
/* isa *. */
field = TYPE_FIELDS (ccfstring_type_node);
- CONSTRUCTOR_APPEND_ELT(v, NULL_TREE,
- build1 (ADDR_EXPR, TREE_TYPE (field),
+ CONSTRUCTOR_APPEND_ELT(v, NULL_TREE,
+ build1 (ADDR_EXPR, TREE_TYPE (field),
cfstring_class_reference));
/* flags */
field = DECL_CHAIN (field);
- CONSTRUCTOR_APPEND_ELT(v, NULL_TREE,
+ CONSTRUCTOR_APPEND_ELT(v, NULL_TREE,
build_int_cst (TREE_TYPE (field), 0x000007c8));
/* string *. */
field = DECL_CHAIN (field);
@@ -3607,7 +3636,7 @@ darwin_build_constant_cfstring (tree str)
TREE_LANG_FLAG_4 (constructor) = 1; /* TREE_HAS_CONSTRUCTOR */
/* Create an anonymous global variable for this CFString. */
- var = build_decl (input_location, CONST_DECL,
+ var = build_decl (input_location, CONST_DECL,
NULL, TREE_TYPE (constructor));
DECL_ARTIFICIAL (var) = 1;
TREE_STATIC (var) = 1;
@@ -3641,7 +3670,7 @@ darwin_cfstring_p (tree str)
key.literal = str;
cfstring_descriptor **loc = cfstring_htab->find_slot (&key, NO_INSERT);
-
+
if (loc)
return true;
@@ -3673,7 +3702,7 @@ darwin_function_section (tree decl, enum node_frequency freq,
bool weak = (decl
&& DECL_WEAK (decl)
&& (!DECL_ATTRIBUTES (decl)
- || !lookup_attribute ("weak_import",
+ || !lookup_attribute ("weak_import",
DECL_ATTRIBUTES (decl))));
bool use_coal = weak && ld_uses_coal_sects;
diff --git a/gcc/config/darwin.h b/gcc/config/darwin.h
index 0e253cb..e17bc64 100644
--- a/gcc/config/darwin.h
+++ b/gcc/config/darwin.h
@@ -126,6 +126,24 @@ extern GTY(()) int darwin_ms_struct;
"%{gsplit-dwarf:%ngsplit-dwarf is not supported on this platform} \
%<gsplit-dwarf"
+#if LD64_HAS_EXPORT_DYNAMIC
+#define DARWIN_RDYNAMIC "%{rdynamic:-export_dynamic}"
+#else
+#define DARWIN_RDYNAMIC "%{rdynamic:%nrdynamic is not supported}"
+#endif
+
+/* FIXME: we should check that the linker supports the -pie and -no_pie.
+ options. */
+#define DARWIN_PIE_SPEC \
+"%{pie|fpie|fPIE:\
+ %{mdynamic-no-pic: \
+ %n'-mdynamic-no-pic' overrides '-pie', '-fpie' or '-fPIE'; \
+ :%:version-compare(>= 10.5 mmacosx-version-min= -pie) }} "
+
+#define DARWIN_NOPIE_SPEC \
+"%{no-pie|fno-pie|fno-PIE: \
+ %:version-compare(>= 10.7 mmacosx-version-min= -no_pie) }"
+
#define DARWIN_CC1_SPEC \
"%{findirect-virtual-calls: -fapple-kext} %<findirect-virtual-calls " \
"%{fterminated-vtables: -fapple-kext} %<fterminated-vtables " \
@@ -156,20 +174,31 @@ extern GTY(()) int darwin_ms_struct;
#define CPP_SPEC "%{static:%{!dynamic:-D__STATIC__}}%{!static:-D__DYNAMIC__}" \
" %{pthread:-D_REENTRANT}"
-/* This is mostly a clone of the standard LINK_COMMAND_SPEC, plus
- precomp, libtool, and fat build additions.
+/* This is a fix for PR41260 by passing -no_compact_unwind on darwin10 and
+ later until the assembler, linker and libunwind are able to deal with the
+ output from GCC.
+
+ FIXME: we should check that the linker supports the option.
+*/
+
+#define DARWIN_NOCOMPACT_UNWIND \
+" %:version-compare(>= 10.6 mmacosx-version-min= -no_compact_unwind) "
+
+/* In Darwin linker specs we can put -lcrt0.o and ld will search the library
+ path for crt0.o or -lcrtx.a and it will search for for libcrtx.a. As for
+ other ports, we can also put xxx.{o,a}%s and get the appropriate complete
+ startfile absolute directory. This latter point is important when we want
+ to override ld's rule of .dylib being found ahead of .a and the user wants
+ the convenience library to be linked. */
+
+/* The LINK_COMMAND spec is mostly a clone of the standard LINK_COMMAND_SPEC,
+ plus precomp, libtool, and fat build additions.
In general, random Darwin linker flags should go into LINK_SPEC
instead of LINK_COMMAND_SPEC. The command spec is better for
specifying the handling of options understood by generic Unix
linkers, and for positional arguments like libraries. */
-#if LD64_HAS_EXPORT_DYNAMIC
-#define DARWIN_EXPORT_DYNAMIC " %{rdynamic:-export_dynamic}"
-#else
-#define DARWIN_EXPORT_DYNAMIC " %{rdynamic: %nrdynamic is not supported}"
-#endif
-
#define LINK_COMMAND_SPEC_A \
"%{!fdump=*:%{!fsyntax-only:%{!c:%{!M:%{!MM:%{!E:%{!S:\
%(linker)" \
@@ -190,10 +219,14 @@ extern GTY(()) int darwin_ms_struct;
%{%:sanitize(address): -lasan } \
%{%:sanitize(undefined): -lubsan } \
%(link_ssp) \
- " DARWIN_EXPORT_DYNAMIC " %<rdynamic \
%(link_gcc_c_sequence) \
}}}\
- %{!nostdlib:%{!r:%{!nostartfiles:%E}}} %{T*} %{F*} }}}}}}}"
+ %{!nostdlib:%{!r:%{!nostartfiles:%E}}} %{T*} %{F*} "\
+ DARWIN_PIE_SPEC \
+ DARWIN_NOPIE_SPEC \
+ DARWIN_RDYNAMIC \
+ DARWIN_NOCOMPACT_UNWIND \
+ "}}}}}}} %<pie %<no-pie %<rdynamic "
#define DSYMUTIL "\ndsymutil"
@@ -230,8 +263,6 @@ extern GTY(()) int darwin_ms_struct;
#define STANDARD_STARTFILE_PREFIX_1 ""
#define STANDARD_STARTFILE_PREFIX_2 ""
-#define DARWIN_PIE_SPEC "%{fpie|pie|fPIE:}"
-
/* Please keep the random linker options in alphabetical order (modulo
'Z' and 'no' prefixes). Note that options taking arguments may appear
multiple times on a command line with different arguments each time,
@@ -295,7 +326,6 @@ extern GTY(()) int darwin_ms_struct;
%:version-compare(< 10.5 mmacosx-version-min= -multiply_defined) \
%:version-compare(< 10.5 mmacosx-version-min= suppress)}} \
%{Zmultiplydefinedunused*:-multiply_defined_unused %*} \
- " DARWIN_PIE_SPEC " \
%{prebind} %{noprebind} %{nofixprebinding} %{prebind_all_twolevel_modules} \
%{read_only_relocs} \
%{sectcreate*} %{sectorder*} %{seg1addr*} %{segprot*} \
@@ -327,43 +357,42 @@ extern GTY(()) int darwin_ms_struct;
/* Support -mmacosx-version-min by supplying different (stub) libgcc_s.dylib
libraries to link against, and by not linking against libgcc_s on
- earlier-than-10.3.9.
+ earlier-than-10.3.9. If we need exceptions, prior to 10.3.9, then we have
+ to link the static eh lib, since there's no shared version on the system.
- Note that by default, -lgcc_eh is not linked against! This is
- because in a future version of Darwin the EH frame information may
- be in a new format, or the fallback routine might be changed; if
- you want to explicitly link against the static version of those
- routines, because you know you don't need to unwind through system
- libraries, you need to explicitly say -static-libgcc.
+ Note that by default, except as above, -lgcc_eh is not linked against.
+ This is because,in general, we need to unwind through system libraries that
+ are linked with the shared unwinder in libunwind (or libgcc_s for 10.4/5).
- If it is linked against, it has to be before -lgcc, because it may
+ The static version of the current libgcc unwinder (which differs from the
+ implementation in libunwind.dylib on systems Darwin10 [10.6]+) can be used
+ by specifying -static-libgcc.
+
+ If libgcc_eh is linked against, it has to be before -lgcc, because it might
need symbols from -lgcc. */
+
#undef REAL_LIBGCC_SPEC
#define REAL_LIBGCC_SPEC \
"%{static-libgcc|static: -lgcc_eh -lgcc; \
- shared-libgcc|fexceptions|fgnu-runtime: \
- %:version-compare(!> 10.5 mmacosx-version-min= -lgcc_s.10.4) \
+ shared-libgcc|fexceptions|fobjc-exceptions|fgnu-runtime: \
+ %:version-compare(!> 10.3.9 mmacosx-version-min= -lgcc_eh) \
+ %:version-compare(>< 10.3.9 10.5 mmacosx-version-min= -lgcc_s.10.4) \
%:version-compare(>< 10.5 10.6 mmacosx-version-min= -lgcc_s.10.5) \
- %:version-compare(!> 10.5 mmacosx-version-min= -lgcc_ext.10.4) \
+ %:version-compare(>< 10.3.9 10.5 mmacosx-version-min= -lgcc_ext.10.4) \
%:version-compare(>= 10.5 mmacosx-version-min= -lgcc_ext.10.5) \
-lgcc ; \
:%:version-compare(>< 10.3.9 10.5 mmacosx-version-min= -lgcc_s.10.4) \
%:version-compare(>< 10.5 10.6 mmacosx-version-min= -lgcc_s.10.5) \
- %:version-compare(!> 10.5 mmacosx-version-min= -lgcc_ext.10.4) \
+ %:version-compare(>< 10.3.9 10.5 mmacosx-version-min= -lgcc_ext.10.4) \
%:version-compare(>= 10.5 mmacosx-version-min= -lgcc_ext.10.5) \
-lgcc }"
-/* We specify crt0.o as -lcrt0.o so that ld will search the library path.
-
- crt3.o provides __cxa_atexit on systems that don't have it. Since
- it's only used with C++, which requires passing -shared-libgcc, key
- off that to avoid unnecessarily adding a destructor to every
- powerpc program built. */
+/* We specify crt0.o as -lcrt0.o so that ld will search the library path. */
#undef STARTFILE_SPEC
#define STARTFILE_SPEC \
- "%{Zdynamiclib: %(darwin_dylib1) %{fgnu-tm: -lcrttms.o}} \
- %{!Zdynamiclib:%{Zbundle:%{!static: \
+"%{Zdynamiclib: %(darwin_dylib1) %{fgnu-tm: -lcrttms.o}} \
+ %{!Zdynamiclib:%{Zbundle:%{!static: \
%:version-compare(< 10.6 mmacosx-version-min= -lbundle1.o) \
%{fgnu-tm: -lcrttms.o}}} \
%{!Zbundle:%{pg:%{static:-lgcrt0.o} \
@@ -377,7 +406,7 @@ extern GTY(()) int darwin_ms_struct;
%{!object:%{preload:-lcrt0.o} \
%{!preload: %(darwin_crt1) \
%(darwin_crt2)}}}}}} \
- %{shared-libgcc:%:version-compare(< 10.5 mmacosx-version-min= crt3.o%s)}"
+ %(darwin_crt3)"
/* We want a destructor last in the list. */
#define TM_DESTRUCTOR "%{fgnu-tm: -lcrttme.o}"
@@ -385,18 +414,30 @@ extern GTY(()) int darwin_ms_struct;
#define DARWIN_EXTRA_SPECS \
{ "darwin_crt1", DARWIN_CRT1_SPEC }, \
+ { "darwin_crt2", DARWIN_CRT2_SPEC }, \
+ { "darwin_crt3", DARWIN_CRT3_SPEC }, \
{ "darwin_dylib1", DARWIN_DYLIB1_SPEC },
-#define DARWIN_DYLIB1_SPEC \
- "%:version-compare(!> 10.5 mmacosx-version-min= -ldylib1.o) \
- %:version-compare(>< 10.5 10.6 mmacosx-version-min= -ldylib1.10.5.o)"
-
#define DARWIN_CRT1_SPEC \
"%:version-compare(!> 10.5 mmacosx-version-min= -lcrt1.o) \
%:version-compare(>< 10.5 10.6 mmacosx-version-min= -lcrt1.10.5.o) \
%:version-compare(>< 10.6 10.8 mmacosx-version-min= -lcrt1.10.6.o) \
%{fgnu-tm: -lcrttms.o}"
+#define DARWIN_CRT2_SPEC ""
+
+/* crt3.o provides __cxa_atexit on systems that don't have it (and a fix
+ up for faulty versions on 10.4). Since it's only used with C++, which
+ requires passing -shared-libgcc, key off that to avoid unnecessarily
+ adding a destructor to every program built for 10.4 or earlier. */
+
+#define DARWIN_CRT3_SPEC \
+"%{shared-libgcc:%:version-compare(< 10.5 mmacosx-version-min= crt3.o%s)}"
+
+#define DARWIN_DYLIB1_SPEC \
+ "%:version-compare(!> 10.5 mmacosx-version-min= -ldylib1.o) \
+ %:version-compare(>< 10.5 10.6 mmacosx-version-min= -ldylib1.10.5.o)"
+
#ifdef HAVE_AS_MMACOSX_VERSION_MIN_OPTION
/* Emit macosx version (but only major). */
#define ASM_MMACOSX_VERSION_MIN_SPEC \
@@ -969,8 +1010,12 @@ extern void darwin_driver_init (unsigned int *,struct cl_decoded_option **);
_tested_ version known to support this so far. */
#define MIN_LD64_NO_COAL_SECTS "236.4"
+/* From at least version 62.1, ld64 can build PIC indirection stubs as
+ needed, and there is no need for the compiler to emit them. */
+#define MIN_LD64_OMIT_STUBS "62.1"
+
#ifndef LD64_VERSION
-#define LD64_VERSION "85.2"
+#define LD64_VERSION "62.1"
#else
#define DEF_LD64 LD64_VERSION
#endif
diff --git a/gcc/config/darwin.opt b/gcc/config/darwin.opt
index 22667de..d7e5e7b 100644
--- a/gcc/config/darwin.opt
+++ b/gcc/config/darwin.opt
@@ -18,240 +18,382 @@
; along with GCC; see the file COPYING3. If not see
; <http://www.gnu.org/licenses/>.
-; Various linker options have a -Z added so that they can get to specs
-; processing without interference. Note that an option name with a
-; prefix that matches another option name, that also takes an
-; argument, being mapped to a -Z linker option, needs to be modified
-; so the prefix is different, otherwise a '*' after the shorter option
-; will match with the longer one.
+; We have a lot of Driver options, many of which are obsolete or very very
+; rarely used so, to keep this file easier to manage:
+
+; Please place all Non-driver options first (in alphabetical order), followed
+; by Driver-only options.
+
+; Non-driver options.
+
+dependency-file
+C ObjC C++ ObjC++ Separate Alias(MF) MissingArgError(missing filename after %qs)
+
+fapple-kext
+Target Report C++ Var(flag_apple_kext)
+Generate code for darwin loadable kernel extensions.
+
+iframework
+Target RejectNegative C ObjC C++ ObjC++ Joined Separate
+-iframework <dir> Add <dir> to the end of the system framework include path.
+
+mconstant-cfstrings
+Target Report Var(darwin_constant_cfstrings) Init(1)
+Generate compile-time CFString objects.
+
+Wnonportable-cfstrings
+Target Report Var(darwin_warn_nonportable_cfstrings) Init(1) Warning
+Warn if constant CFString objects contain non-portable characters.
+
+; Use new-style pic stubs if this is true, x86 only so far.
+matt-stubs
+Target Report Var(darwin_macho_att_stub) Init(1)
+Generate AT&T-style stubs for Mach-O.
+
+mdynamic-no-pic
+Target Common Report Mask(MACHO_DYNAMIC_NO_PIC)
+Generate code suitable for executables (NOT shared libs).
+
+mfix-and-continue
+Target Report Var(darwin_fix_and_continue)
+Generate code suitable for fast turn around debugging.
+
+mkernel
+Target Report Var(flag_mkernel)
+Generate code for the kernel or loadable kernel extensions.
+
+; The Init here is for the convenience of GCC developers, so that cc1
+; and cc1plus don't crash if no -mmacosx-version-min is passed. The
+; driver will always pass a -mmacosx-version-min, so in normal use the
+; Init is never used.
+mmacosx-version-min=
+Target RejectNegative Joined Report Var(darwin_macosx_version_min) Init(DEF_MIN_OSX_VERSION)
+The earliest MacOS X version on which this program will run.
+
+; Really, only relevant to PowerPC which has a 4 byte bool by default.
+mone-byte-bool
+Target RejectNegative Report Var(darwin_one_byte_bool)
+Set sizeof(bool) to 1.
+
+mpic-symbol-stubs
+Target Report Var(darwin_picsymbol_stubs) Init(0)
+Force generation of PIC symbol stubs.
+
+; Some code-gen may be improved / adjusted if the linker is sufficiently modern.
+mtarget-linker=
+Target RejectNegative Joined Report Alias(mtarget-linker)
+
+mtarget-linker
+Target RejectNegative Joined Separate Report Var(darwin_target_linker) Init(LD64_VERSION)
+The version of ld64 in use for this toolchain.
+
+; Driver options.
all_load
-Driver Alias(Zall_load)
+Driver RejectNegative Alias(Zall_load)
+Loads all members of archive libraries
allowable_client
-Driver Separate Alias(Zallowable_client)
+Driver RejectNegative Separate Alias(Zallowable_client)
+-allowable_client <name> The output dylib is private to the client(s) named
arch
Driver RejectNegative Separate
+-arch <name> Specify that the output file should be generated for architecture \"name\"
arch_errors_fatal
-Driver Alias(Zarch_errors_fatal)
+Driver RejectNegative Alias(Zarch_errors_fatal)
+Mismatches between file architecture and the \"-arch\" are errors instead of warnings
asm_macosx_version_min=
Driver RejectNegative Joined
+The earliest MacOS X version on which this program will run (formatted for the assembler)
bind_at_load
-Driver Alias(Zbind_at_load)
+Driver RejectNegative Alias(Zbind_at_load)
+Produce an output file that will bind symbols on load, rather than lazily.
bundle
-Driver Alias(Zbundle)
+Driver RejectNegative Alias(Zbundle)
+Produce a Mach-O bundle (file type MH_BUNDLE)
bundle_loader
-Driver Separate Alias(Zbundle_loader)
+Driver RejectNegative Separate Alias(Zbundle_loader)
+-bundle_loader <executable> Treat \"executable\" (that will be loading this bundle) as if it was one of the dynamic libraries the bundle is linked against for symbol resolution
-dead_strip
-Driver Alias(Zdead_strip)
+client_name
+Driver RejectNegative Separate
+-client_name <name> Enable the executable being built to link against a private dylib (using allowable_client)
-dependency-file
-C ObjC C++ ObjC++ Separate Alias(MF) MissingArgError(missing filename after %qs)
+compatibility_version
+Driver RejectNegative Separate
+-compatibility_version <number> Set the minimum version for the client interface. Clients must record a greater number than this or the binding will fail at runtime
+
+current_version
+Driver RejectNegative Separate
+-current_version <number> Set the current version for the library.
+
+dead_strip
+Driver RejectNegative Alias(Zdead_strip)
+Remove code and data that is unreachable from any exported symbol (including the entry point)
dylib_file
Driver Separate Alias(Zdylib_file)
dylinker
-Driver
+Driver RejectNegative
+Produce a Mach-O dylinker (file type MH_DYLINKER), only used for building dyld.
+
+dylinker_install_name
+Driver RejectNegative Separate
+-dylinker_install_name <path> Only used for building dyld.
dynamic
-Driver Alias(Zdynamic)
+Driver RejectNegative Alias(Zdynamic)
+The default (and opposite of -static), implied by user mode executables, shared libraries and bundles.
dynamiclib
-Driver Alias(Zdynamiclib)
+Driver RejectNegative Alias(Zdynamiclib)
+Produce a Mach-O shared library (file type MH_DYLIB), synonym for -shared
exported_symbols_list
-Driver Separate Alias(Zexported_symbols_list)
+Driver RejectNegative Separate Alias(Zexported_symbols_list)
+-exported_symbols_list <filename> Global symbols in \"filename\" will be exported from the linked output file, any symbols not mentioned will be treated as hidden.
filelist
Driver RejectNegative Separate
+Supply a list of objects to be linked from a file, rather than the command line
findirect-virtual-calls
Driver RejectNegative
+Used for generating code for some older kernel revisions.
flat_namespace
Driver RejectNegative Alias(Zflat_namespace)
+Ignore the normal two-level namespace; resolve symbols in command line order and do not record which library provided the resolved symbol.
force_cpusubtype_ALL
Driver RejectNegative Alias(Zforce_cpusubtype_ALL)
+For the assembler (and linker) permit any architecture sub-variant to be used without error.
force_flat_namespace
Driver RejectNegative Alias(Zforce_flat_namespace)
+Set the output object such that, on loading, dyld will ignore any two-level information and resolve symbols in the discovery order for loaded libs.
framework
Driver RejectNegative Separate
+-framework <name> The linker should search for the named framework in the framework search path.
fterminated-vtables
Driver RejectNegative
+Used for generating code for some older kernel revisions.
gfull
Driver RejectNegative
+Abbreviation for \"-g -fno-eliminate-unused-debug-symbols\"
gused
Driver RejectNegative
+Abbreviation for \"-g -feliminate-unused-debug-symbols\"
headerpad_max_install_names
-Driver
+Driver RejectNegative
+Automatically adds space for longer path names in load commands (up to MAXPATHLEN)
image_base
-Driver Separate Alias(Zimage_base)
+Driver RejectNegative Separate Alias(Zimage_base)
+-image_base <address> Choose a base address for a dylib or bundle.
init
-Driver Separate Alias(Zinit)
+Driver RejectNegative Separate Alias(Zinit)
+-init <symbol_name> The symbol \"symbol_name\" will be used as the first initialiser for a dylib.
install_name
-Driver Separate Alias(Zinstall_name)
+Driver RejectNegative Separate Alias(Zinstall_name)
+-install_name <name> Set the install name for a dylib.
keep_private_externs
-Driver
-
-mconstant-cfstrings
-Target Report Var(darwin_constant_cfstrings) Init(1)
-Generate compile-time CFString objects.
+Driver RejectNegative
+Usually \"private extern\" (hidden) symbols are made local when linking, this command suppresses that such that they remain exported.
multi_module
Driver RejectNegative Alias(Zmulti_module)
+(Obsolete after 10.4) Multi modules are ignored at runtime since MacOS 10.4
multiply_defined
Driver RejectNegative Separate Alias(Zmultiply_defined)
+(Obsolete after 10.4) -multiply_defined <treatment> Provided a mechanism for warning about symbols defined in multiple dylibs.
multiply_defined_unused
Driver RejectNegative Separate Alias(Zmultiplydefinedunused)
+(Obsolete after 10.4) -multiply_defined_unused <treatment> Provided a mechanism for warning about symbols defined in the current executable also being defined in linked dylibs.
no_dead_strip_inits_and_terms
-Driver Alias(Zno_dead_strip_inits_and_terms)
+Driver RejectNegative Alias(Zno_dead_strip_inits_and_terms)
+(Obsolete) The linker never dead strips these items, so the option is not needed.
nofixprebinding
-Driver
+Driver RejectNegative
+(Obsolete after 10.3.9) Set MH_NOPREFIXBINDING, in an exectuable.
nomultidefs
-Driver
+Driver RejectNegative
+(Obsolete after 10.4) Set MH_NOMULTIDEFS in an umbrella framework.
noprebind
-Driver
+Driver RejectNegative Negative(prebind)
+(Obsolete) LD_PREBIND is no longer supported.
noseglinkedit
-Driver
+Driver RejectNegative Negative(seglinkedit)
+(Obsolete) This is the default.
object
-Driver
+Driver RejectNegative
+
+pagezero_size
+Driver RejectNegative Separate
+-pagezero_size size Allows setting the page 0 size to 4kb for certain special cases.
prebind
-Driver
+Driver RejectNegative Negative(noprebind)
+(Obsolete) LD_PREBIND is no longer supported.
prebind_all_twolevel_modules
-Driver
+Driver RejectNegative
+(Obsolete) LD_PREBIND is no longer supported.
preload
-Driver
+Driver RejectNegative
+Produces a Mach-O file suitable for embedded/ROM use.
private_bundle
-Driver
+Driver RejectNegative
+(Obsolete) Allowed linking to proceed with \"-flat_namespace\" when a linked bundle contained a symbol also exported from the main executable.
pthread
-Driver
+Driver RejectNegative
rdynamic
-Driver
+Driver RejectNegative
+Synonym for \"-export-dynamic\" for linker versions that support it.
+
+read_only_relocs
+Driver RejectNegative Separate
+-read_only_relocs <treatment> This will allow relocs in read-only pages (not advisable).
+
+sectalign
+Driver RejectNegative Separate Args(3)
+-sectalign <segname> <sectname> <value> Set section \"sectname\" in segment \"segname\" to have alignment \"value\" which must be an integral power of two expressed in hexadecimal form.
+
+sectcreate
+Driver RejectNegative Separate Args(3)
+-sectcreate <segname> <sectname> <file> Create section \"sectname\" in segment \"segname\" from the contents of \"file\".
+
+sectobjectsymbols
+Driver RejectNegative Separate Args(2)
+(Obsolete) -sectobjectsymbols <segname> <sectname> Setting a local symbol at the start of a section is no longer supported.
+
+sectorder
+Driver RejectNegative Separate Args(3)
+(Obsolete) -sectorder <segname> <sectname> orderfile Replaced by a more general option \"-order_file\".
seg_addr_table
-Driver Separate Alias(Zseg_addr_table)
+Driver RejectNegative Separate Alias(Zseg_addr_table)
+-seg_addr_table <file> Specify the base addresses for dynamic libraries, \"file\" contains a line for each library.
+; This is only usable by the ld_classic linker.
seg_addr_table_filename
-Driver Separate Alias(Zfn_seg_addr_table_filename)
+Driver RejectNegative Separate Alias(Zfn_seg_addr_table_filename)
+(Obsolete, ld_classic only) -seg_addr_table_filename <path>
+
+seg1addr
+Driver RejectNegative Separate
+Synonym for \"image_base\"
segaddr
-Driver Separate Args(2) Alias(Zsegaddr)
+Driver RejectNegative Separate Args(2) Alias(Zsegaddr)
+-segaddr <name> <address> Set the base address of segment \"name\" to \"address\" which must be aligned to a page boundary (currently 4kb).
+
+; This is only usable by the ld_classic linker.
+segcreate
+Driver RejectNegative Separate Args(3)
+(Obsolete, ld_classic only) -sectcreate segname sectname file
seglinkedit
-Driver
+Driver RejectNegative Negative(noseglinkedit)
+(Obsolete) Object files with LINKEDIT sections are no longer supported.
+
+segprot
+Driver RejectNegative Separate Args(3)
+-segprot <segname> max_prot init_prot The protection values are \"r\", \"w\", \"x\" or \"-\" the latter meaning \"no access\".
segs_read_only_addr
-Driver Separate Alias(Zsegs_read_only_addr)
+Driver RejectNegative Separate Alias(Zsegs_read_only_addr)
+-segs_read_only_addr address Allows specifying the address of the read only portion of a dylib.
segs_read_write_addr
-Driver Separate Alias(Zsegs_read_write_addr)
+Driver RejectNegative Separate Alias(Zsegs_read_write_addr)
+-segs_read_write_addr address Allows specifying the address of the read/write portion of a dylib.
single_module
-Driver Alias(Zsingle_module)
+Driver RejectNegative Alias(Zsingle_module)
+(Obsolete) This is the default.
+
+sub_library
+Driver RejectNegative Separate
+-sub_library <name> Library named \"name\" will be re-exported (only useful for dylibs).
+
+sub_umbrella
+Driver RejectNegative Separate
+-sub_umbrella <name> Framework named \"name\" will be re-exported (only useful for dylibs).
twolevel_namespace
-Driver
+Driver RejectNegative
+This is the default
twolevel_namespace_hints
-Driver
+Driver RejectNegative
+Specifies content that can speed up dynamic loading when the binaries are unchanged.
umbrella
-Driver Separate Alias(Zumbrella)
+Driver RejectNegative Separate Alias(Zumbrella)
+-umbrella <framework> The specified framework will be re-exported.
+
+undefined
+Driver RejectNegative Separate
+-undefined <treatment> Specify the handling for undefined symbols (default is error).
unexported_symbols_list
-Driver Separate Alias(Zunexported_symbols_list)
+Driver RejectNegative Separate Alias(Zunexported_symbols_list)
+-unexported_symbols_list <filename> Don't export global symbols listed in filename.
weak_reference_mismatches
-Driver Separate Alias(Zweak_reference_mismatches)
+Driver RejectNegative Separate Alias(Zweak_reference_mismatches)
+-weak_reference_mismatches <treatment> Specifies what to do if a symbol import conflicts between file (weak in one and not in another) the default is to treat the symbol as non-weak.
whatsloaded
-Driver
+Driver RejectNegative
+Logs the object files the linker loads
whyload
-Driver
+Driver RejectNegative
+Logs which symbol(s) caused an object to be loaded.
+
+;(Obsolete, ignored) Strip symbols starting with "L", this is the default.
+X
+Driver RejectNegative
y
-Driver Joined
+Driver RejectNegative Joined
+(Obsolete, ignored) Old support similar to whyload.
Mach
-Driver
-
-Wnonportable-cfstrings
-Target Report Var(darwin_warn_nonportable_cfstrings) Init(1) Warning
-Warn if constant CFString objects contain non-portable characters.
-
-; Use new-style pic stubs if this is true, x86 only so far.
-matt-stubs
-Target Report Var(darwin_macho_att_stub) Init(1)
-Generate AT&T-style stubs for Mach-O.
-
-mdynamic-no-pic
-Target Common Report Mask(MACHO_DYNAMIC_NO_PIC)
-Generate code suitable for executables (NOT shared libs).
-
-mfix-and-continue
-Target Report Var(darwin_fix_and_continue)
-Generate code suitable for fast turn around debugging.
-
-; The Init here is for the convenience of GCC developers, so that cc1
-; and cc1plus don't crash if no -mmacosx-version-min is passed. The
-; driver will always pass a -mmacosx-version-min, so in normal use the
-; Init is never used.
-mmacosx-version-min=
-Target Joined Report Var(darwin_macosx_version_min) Init(DEF_MIN_OSX_VERSION)
-The earliest MacOS X version on which this program will run.
-
-mone-byte-bool
-Target RejectNegative Report Var(darwin_one_byte_bool)
-Set sizeof(bool) to 1.
-
-fapple-kext
-Target Report C++ Var(flag_apple_kext)
-Generate code for darwin loadable kernel extensions.
-
-mkernel
-Target Report Var(flag_mkernel)
-Generate code for the kernel or loadable kernel extensions.
-
-iframework
-Target RejectNegative C ObjC C++ ObjC++ Joined Separate
--iframework <dir> Add <dir> to the end of the system framework include path.
+Driver RejectNegative
+(Obsolete and unhandled by ld64, ignored) ld should produce an executable (only handled by ld_classic).
-X
-Driver
+;; These are not "real" options, but placeholders used to hide the real options
+;; from generic options processing... FIXME: they can be eliminated now.
Zall_load
Driver
@@ -343,62 +485,3 @@ Driver Separate
Zweak_reference_mismatches
Driver Separate
-client_name
-Driver Separate
-
-compatibility_version
-Driver Separate
-
-current_version
-Driver Separate
-
-dylinker_install_name
-Driver Separate
-
-pagezero_size
-Driver Separate
-
-read_only_relocs
-Driver Separate
-
-sectalign
-Driver Separate Args(3)
-
-sectcreate
-Driver Separate Args(3)
-
-sectobjectsymbols
-Driver Separate Args(2)
-
-sectorder
-Driver Separate Args(3)
-
-seg1addr
-Driver Separate
-
-segcreate
-Driver Separate Args(3)
-
-segprot
-Driver Separate Args(3)
-
-segs_read_only_addr
-Driver Separate
-
-segs_read_write_addr
-Driver Separate
-
-sub_library
-Driver Separate
-
-sub_umbrella
-Driver Separate
-
-; Certain aspects of code-gen may be improved / adjusted if the version of ld64
-; is sufficiently modern.
-mtarget-linker
-Target RejectNegative Joined Separate Report Var(darwin_target_linker) Init(LD64_VERSION)
-The version of ld64 in use for this toolchain.
-
-undefined
-Driver Separate
diff --git a/gcc/config/darwin10.h b/gcc/config/darwin10.h
index 07a2b46..a6d1eba 100644
--- a/gcc/config/darwin10.h
+++ b/gcc/config/darwin10.h
@@ -18,17 +18,12 @@ 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/>. */
-/* Fix PR41260 by passing -no_compact_unwind on darwin10 and later until
- unwinder in libSystem is fixed to digest new epilog unwinding notes.
+/* Fix PR47558 by linking against libSystem ahead of libgcc_ext. */
- Fix PR47558 by linking against libSystem ahead of libgcc_ext. */
#undef LINK_GCC_C_SEQUENCE_SPEC
#define LINK_GCC_C_SEQUENCE_SPEC \
-"%:version-compare(>= 10.6 mmacosx-version-min= -no_compact_unwind) \
- %{!static:%{!static-libgcc: \
+"%{!static:%{!static-libgcc: \
%:version-compare(>= 10.6 mmacosx-version-min= -lSystem) } } \
- %{fno-pic|fno-PIC|fno-pie|fno-PIE|fapple-kext|mkernel|static|mdynamic-no-pic: \
- %:version-compare(>= 10.7 mmacosx-version-min= -no_pie) } \
%{!nostdlib:%:version-compare(>< 10.6 10.7 mmacosx-version-min= -ld10-uwfef.o)} \
%G %{!nolibc:%L}"
diff --git a/gcc/config/darwin9.h b/gcc/config/darwin9.h
index ca5c517..1fd1604 100644
--- a/gcc/config/darwin9.h
+++ b/gcc/config/darwin9.h
@@ -35,12 +35,6 @@ along with GCC; see the file COPYING3. If not see
/* Tell collect2 to run dsymutil for us as necessary. */
#define COLLECT_RUN_DSYMUTIL 1
-#undef DARWIN_PIE_SPEC
-#define DARWIN_PIE_SPEC \
- "%{fpie|pie|fPIE: \
- %{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.) */
diff --git a/gcc/config/epiphany/epiphany.c b/gcc/config/epiphany/epiphany.c
index 68b9db9..657a888 100644
--- a/gcc/config/epiphany/epiphany.c
+++ b/gcc/config/epiphany/epiphany.c
@@ -2892,11 +2892,13 @@ epiphany_output_mi_thunk (FILE *file, tree thunk ATTRIBUTE_UNUSED,
HOST_WIDE_INT vcall_offset,
tree function)
{
+ const char *fnname = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (thunk));
int this_regno
= aggregate_value_p (TREE_TYPE (TREE_TYPE (function)), function) ? 1 : 0;
const char *this_name = reg_names[this_regno];
const char *fname;
+ assemble_start_function (thunk, fnname);
/* We use IP and R16 as a scratch registers. */
gcc_assert (call_used_regs [GPR_IP]);
gcc_assert (call_used_regs [GPR_16]);
@@ -2954,6 +2956,7 @@ epiphany_output_mi_thunk (FILE *file, tree thunk ATTRIBUTE_UNUSED,
assemble_name (file, fname);
fputc ('\n', file);
}
+ assemble_end_function (thunk, fnname);
}
void
diff --git a/gcc/config/frv/frv.c b/gcc/config/frv/frv.c
index 71bf819..f0c9351 100644
--- a/gcc/config/frv/frv.c
+++ b/gcc/config/frv/frv.c
@@ -1938,11 +1938,14 @@ frv_asm_output_mi_thunk (FILE *file,
HOST_WIDE_INT vcall_offset ATTRIBUTE_UNUSED,
tree function)
{
+ const char *fnname = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (thunk_fndecl));
const char *name_func = XSTR (XEXP (DECL_RTL (function), 0), 0);
const char *name_arg0 = reg_names[FIRST_ARG_REGNUM];
const char *name_jmp = reg_names[JUMP_REGNO];
const char *parallel = (frv_issue_rate () > 1 ? ".p" : "");
+ assemble_start_function (thunk_fndecl, fnname);
+
/* Do the add using an addi if possible. */
if (IN_RANGE (delta, -2048, 2047))
fprintf (file, "\taddi %s,#%d,%s\n", name_arg0, (int) delta, name_arg0);
@@ -2018,6 +2021,7 @@ frv_asm_output_mi_thunk (FILE *file,
/* Jump to the function address. */
fprintf (file, "\tjmpl @(%s,%s)\n", name_jmp, reg_names[GPR_FIRST+0]);
+ assemble_end_function (thunk_fndecl, fnname);
}
diff --git a/gcc/config/frv/frv.md b/gcc/config/frv/frv.md
index 064bf53..6e8db59 100644
--- a/gcc/config/frv/frv.md
+++ b/gcc/config/frv/frv.md
@@ -1887,7 +1887,7 @@
;; Argument 2 is the length
;; Argument 3 is the alignment
-(define_expand "movmemsi"
+(define_expand "cpymemsi"
[(parallel [(set (match_operand:BLK 0 "" "")
(match_operand:BLK 1 "" ""))
(use (match_operand:SI 2 "" ""))
diff --git a/gcc/config/ft32/ft32.md b/gcc/config/ft32/ft32.md
index de23946..9e31f2c 100644
--- a/gcc/config/ft32/ft32.md
+++ b/gcc/config/ft32/ft32.md
@@ -851,7 +851,7 @@
"stpcpy %b1,%b2 # %0 %b1 %b2"
)
-(define_insn "movmemsi"
+(define_insn "cpymemsi"
[(set (match_operand:BLK 0 "memory_operand" "=W,BW")
(match_operand:BLK 1 "memory_operand" "W,BW"))
(use (match_operand:SI 2 "ft32_imm_operand" "KA,KA"))
diff --git a/gcc/config/gcn/gcn-run.c b/gcc/config/gcn/gcn-run.c
index 00a7101..21852d7 100644
--- a/gcc/config/gcn/gcn-run.c
+++ b/gcc/config/gcn/gcn-run.c
@@ -66,7 +66,9 @@ bool debug = false;
hsa_agent_t device = { 0 };
hsa_queue_t *queue = NULL;
-uint64_t kernel = 0;
+uint64_t init_array_kernel = 0;
+uint64_t fini_array_kernel = 0;
+uint64_t main_kernel = 0;
hsa_executable_t executable = { 0 };
hsa_region_t kernargs_region = { 0 };
@@ -427,14 +429,30 @@ load_image (const char *filename)
XHSA (hsa_fns.hsa_executable_freeze_fn (executable, ""),
"Freeze GCN executable");
- /* Locate the "main" function, and read the kernel's properties. */
+ /* Locate the "_init_array" function, and read the kernel's properties. */
hsa_executable_symbol_t symbol;
+ XHSA (hsa_fns.hsa_executable_get_symbol_fn (executable, NULL, "_init_array",
+ device, 0, &symbol),
+ "Find '_init_array' function");
+ XHSA (hsa_fns.hsa_executable_symbol_get_info_fn
+ (symbol, HSA_EXECUTABLE_SYMBOL_INFO_KERNEL_OBJECT, &init_array_kernel),
+ "Extract '_init_array' kernel object kernel object");
+
+ /* Locate the "_fini_array" function, and read the kernel's properties. */
+ XHSA (hsa_fns.hsa_executable_get_symbol_fn (executable, NULL, "_fini_array",
+ device, 0, &symbol),
+ "Find '_fini_array' function");
+ XHSA (hsa_fns.hsa_executable_symbol_get_info_fn
+ (symbol, HSA_EXECUTABLE_SYMBOL_INFO_KERNEL_OBJECT, &fini_array_kernel),
+ "Extract '_fini_array' kernel object kernel object");
+
+ /* Locate the "main" function, and read the kernel's properties. */
XHSA (hsa_fns.hsa_executable_get_symbol_fn (executable, NULL, "main",
device, 0, &symbol),
"Find 'main' function");
XHSA (hsa_fns.hsa_executable_symbol_get_info_fn
- (symbol, HSA_EXECUTABLE_SYMBOL_INFO_KERNEL_OBJECT, &kernel),
- "Extract kernel object");
+ (symbol, HSA_EXECUTABLE_SYMBOL_INFO_KERNEL_OBJECT, &main_kernel),
+ "Extract 'main' kernel object");
XHSA (hsa_fns.hsa_executable_symbol_get_info_fn
(symbol, HSA_EXECUTABLE_SYMBOL_INFO_KERNEL_KERNARG_SEGMENT_SIZE,
&kernarg_segment_size),
@@ -684,7 +702,7 @@ gomp_print_output (struct kernargs *kernargs, bool final)
/* Execute an already-loaded kernel on the device. */
static void
-run (void *kernargs)
+run (uint64_t kernel, void *kernargs)
{
/* A "signal" is used to launch and monitor the kernel. */
hsa_signal_t signal;
@@ -822,14 +840,23 @@ main (int argc, char *argv[])
kernargs->heap_ptr = (int64_t) &kernargs->heap;
kernargs->heap.size = heap_size;
+ /* Run constructors on the GPU. */
+ run (init_array_kernel, kernargs);
+
/* Run the kernel on the GPU. */
- run (kernargs);
+ run (main_kernel, kernargs);
unsigned int return_value =
(unsigned int) kernargs->output_data.return_value;
+ /* Run destructors on the GPU. */
+ run (fini_array_kernel, kernargs);
+
unsigned int upper = (return_value & ~0xffff) >> 16;
if (upper == 0xcafe)
- printf ("Kernel exit value was never set\n");
+ {
+ printf ("Kernel exit value was never set\n");
+ return_value = 0xff;
+ }
else if (upper == 0xffff)
; /* Set by exit. */
else if (upper == 0)
diff --git a/gcc/config/gcn/gcn.c b/gcc/config/gcn/gcn.c
index 1dd2ff2..e528b64 100644
--- a/gcc/config/gcn/gcn.c
+++ b/gcc/config/gcn/gcn.c
@@ -305,9 +305,7 @@ static tree
gcn_handle_amdgpu_hsa_kernel_attribute (tree *node, tree name,
tree args, int, bool *no_add_attrs)
{
- if (FUNC_OR_METHOD_TYPE_P (*node)
- && TREE_CODE (*node) != FIELD_DECL
- && TREE_CODE (*node) != TYPE_DECL)
+ if (!FUNC_OR_METHOD_TYPE_P (*node))
{
warning (OPT_Wattributes, "%qE attribute only applies to functions",
name);
@@ -2826,9 +2824,9 @@ gcn_expand_prologue ()
emit_move_insn (fp_lo, gen_rtx_REG (SImode, 0));
emit_insn (gen_andsi3_scc (fp_hi, gen_rtx_REG (SImode, 1),
gen_int_mode (0xffff, SImode)));
- emit_insn (gen_addsi3_scc (fp_lo, fp_lo, wave_offset));
- emit_insn (gen_addcsi3_scalar_zero (fp_hi, fp_hi,
- gen_rtx_REG (BImode, SCC_REG)));
+ rtx scc = gen_rtx_REG (BImode, SCC_REG);
+ emit_insn (gen_addsi3_scalar_carry (fp_lo, fp_lo, wave_offset, scc));
+ emit_insn (gen_addcsi3_scalar_zero (fp_hi, fp_hi, scc));
if (sp_adjust > 0)
emit_insn (gen_adddi3_scc (sp, fp, gen_int_mode (sp_adjust, DImode)));
@@ -3062,6 +3060,10 @@ gcn_asm_trampoline_template (FILE *f)
static void
gcn_trampoline_init (rtx m_tramp, tree fndecl, rtx chain_value)
{
+ if (TARGET_GCN5_PLUS)
+ sorry ("nested function trampolines not supported on GCN5 due to"
+ " non-executable stacks");
+
emit_block_move (m_tramp, assemble_trampoline_template (),
GEN_INT (TRAMPOLINE_SIZE), BLOCK_OP_NORMAL);
@@ -3161,18 +3163,14 @@ gcn_valid_cvt_p (machine_mode from, machine_mode to, enum gcn_cvt_t op)
|| (to == DFmode && (from == SImode || from == SFmode)));
}
-/* Implement both TARGET_ASM_CONSTRUCTOR and TARGET_ASM_DESTRUCTOR.
+/* Implement TARGET_EMUTLS_VAR_INIT.
- The current loader does not support running code outside "main". This
- hook implementation can be replaced or removed when that changes. */
+ Disable emutls (gthr-gcn.h does not support it, yet). */
-void
-gcn_disable_constructors (rtx symbol, int priority __attribute__ ((unused)))
+tree
+gcn_emutls_var_init (tree, tree decl, tree)
{
- tree d = SYMBOL_REF_DECL (symbol);
- location_t l = d ? DECL_SOURCE_LOCATION (d) : UNKNOWN_LOCATION;
-
- sorry_at (l, "GCN does not support static constructors or destructors");
+ sorry_at (DECL_SOURCE_LOCATION (decl), "TLS is not implemented for GCN.");
}
/* }}} */
@@ -5991,10 +5989,6 @@ print_operand (FILE *file, rtx x, int code)
#define TARGET_ARG_PARTIAL_BYTES gcn_arg_partial_bytes
#undef TARGET_ASM_ALIGNED_DI_OP
#define TARGET_ASM_ALIGNED_DI_OP "\t.8byte\t"
-#undef TARGET_ASM_CONSTRUCTOR
-#define TARGET_ASM_CONSTRUCTOR gcn_disable_constructors
-#undef TARGET_ASM_DESTRUCTOR
-#define TARGET_ASM_DESTRUCTOR gcn_disable_constructors
#undef TARGET_ASM_FILE_START
#define TARGET_ASM_FILE_START output_file_start
#undef TARGET_ASM_FUNCTION_PROLOGUE
@@ -6023,6 +6017,8 @@ print_operand (FILE *file, rtx x, int code)
#define TARGET_CONSTANT_ALIGNMENT gcn_constant_alignment
#undef TARGET_DEBUG_UNWIND_INFO
#define TARGET_DEBUG_UNWIND_INFO gcn_debug_unwind_info
+#undef TARGET_EMUTLS_VAR_INIT
+#define TARGET_EMUTLS_VAR_INIT gcn_emutls_var_init
#undef TARGET_EXPAND_BUILTIN
#define TARGET_EXPAND_BUILTIN gcn_expand_builtin
#undef TARGET_FUNCTION_ARG
diff --git a/gcc/config/gcn/gcn.md b/gcc/config/gcn/gcn.md
index 2b805a7..7e5cf17 100644
--- a/gcc/config/gcn/gcn.md
+++ b/gcc/config/gcn/gcn.md
@@ -784,10 +784,10 @@
if (cfun && cfun->machine && cfun->machine->normal_function)
return "s_setpc_b64\ts[18:19]";
else
- return "s_dcache_wb\;s_endpgm";
+ return "s_waitcnt\tlgkmcnt(0)\;s_dcache_wb\;s_endpgm";
}
[(set_attr "type" "sop1")
- (set_attr "length" "8")])
+ (set_attr "length" "12")])
(define_expand "call"
[(parallel [(call (match_operand 0 "")
@@ -830,18 +830,36 @@
[(set_attr "type" "mult")
(set_attr "length" "32")])
-(define_insn_and_split "movdi_symbol_save_scc"
+(define_insn "movdi_symbol_save_scc"
[(set (match_operand:DI 0 "nonimmediate_operand" "=Sg")
(match_operand:DI 1 "general_operand" "Y"))
(clobber (reg:BI CC_SAVE_REG))]
- "GET_CODE (operands[1]) == SYMBOL_REF || GET_CODE (operands[1]) == LABEL_REF
+ "(GET_CODE (operands[1]) == SYMBOL_REF || GET_CODE (operands[1]) == LABEL_REF)
&& (lra_in_progress || reload_completed)"
- "#"
- "reload_completed"
- [(set (reg:BI CC_SAVE_REG) (reg:BI SCC_REG))
- (parallel [(set (match_dup 0) (match_dup 1))
- (clobber (reg:BI SCC_REG))])
- (set (reg:BI SCC_REG) (reg:BI CC_SAVE_REG))])
+ {
+ /* !!! These sequences clobber CC_SAVE_REG. */
+
+ if (SYMBOL_REF_P (operands[1])
+ && SYMBOL_REF_WEAK (operands[1]))
+ return "; s_mov_b32\ts22, scc is not supported by the assembler.\;"
+ ".long\t0xbe9600fd\;"
+ "s_getpc_b64\t%0\;"
+ "s_add_u32\t%L0, %L0, %1@gotpcrel32@lo+4\;"
+ "s_addc_u32\t%H0, %H0, %1@gotpcrel32@hi+4\;"
+ "s_load_dwordx2\t%0, %0\;"
+ "s_cmpk_lg_u32\ts22, 0\;"
+ "s_waitcnt\tlgkmcnt(0)";
+
+ return "; s_mov_b32\ts22, scc is not supported by the assembler.\;"
+ ".long\t0xbe9600fd\;"
+ "s_getpc_b64\t%0\;"
+ "s_add_u32\t%L0, %L0, %1@rel32@lo+4\;"
+ "s_addc_u32\t%H0, %H0, %1@rel32@hi+4\;"
+ "s_cmpk_lg_u32\ts22, 0";
+ }
+ [(set_attr "type" "mult")
+ (set_attr "length" "40")])
+
(define_insn "gcn_indirect_call"
[(call (mem (match_operand:DI 0 "register_operand" "Sg"))
diff --git a/gcc/config/gcn/gcn.opt b/gcc/config/gcn/gcn.opt
index 2fd3996..bdc878f 100644
--- a/gcc/config/gcn/gcn.opt
+++ b/gcc/config/gcn/gcn.opt
@@ -34,6 +34,9 @@ Enum(gpu_type) String(fiji) Value(PROCESSOR_FIJI)
EnumValue
Enum(gpu_type) String(gfx900) Value(PROCESSOR_VEGA)
+EnumValue
+Enum(gpu_type) String(gfx906) Value(PROCESSOR_VEGA)
+
march=
Target RejectNegative Joined ToLower Enum(gpu_type) Var(gcn_arch) Init(PROCESSOR_CARRIZO)
Specify the name of the target GPU.
diff --git a/gcc/config/gcn/t-gcn-hsa b/gcc/config/gcn/t-gcn-hsa
index 085ba429..1600a58 100644
--- a/gcc/config/gcn/t-gcn-hsa
+++ b/gcc/config/gcn/t-gcn-hsa
@@ -42,8 +42,8 @@ ALL_HOST_OBJS += gcn-run.o
gcn-run$(exeext): gcn-run.o
+$(LINKER) $(ALL_LINKERFLAGS) $(LDFLAGS) -o $@ $< -ldl
-MULTILIB_OPTIONS = march=gfx900
-MULTILIB_DIRNAMES = gcn5
+MULTILIB_OPTIONS = march=gfx900 march=gfx906
+MULTILIB_DIRNAMES = gfx900 gfx906
PASSES_EXTRA += $(srcdir)/config/gcn/gcn-passes.def
gcn-tree.o: $(srcdir)/config/gcn/gcn-tree.c
diff --git a/gcc/config/h8300/h8300.md b/gcc/config/h8300/h8300.md
index eb0ae83..42610fd 100644
--- a/gcc/config/h8300/h8300.md
+++ b/gcc/config/h8300/h8300.md
@@ -474,11 +474,11 @@
(set_attr "length_table" "*,movl")
(set_attr "cc" "set_zn,set_znv")])
-;; Implement block moves using movmd. Defining movmemsi allows the full
+;; Implement block copies using movmd. Defining cpymemsi allows the full
;; range of constant lengths (up to 0x40000 bytes when using movmd.l).
;; See h8sx_emit_movmd for details.
-(define_expand "movmemsi"
+(define_expand "cpymemsi"
[(use (match_operand:BLK 0 "memory_operand" ""))
(use (match_operand:BLK 1 "memory_operand" ""))
(use (match_operand:SI 2 "" ""))
diff --git a/gcc/config/i386/avx512dqintrin.h b/gcc/config/i386/avx512dqintrin.h
index f0c18fb..71c86fc 100644
--- a/gcc/config/i386/avx512dqintrin.h
+++ b/gcc/config/i386/avx512dqintrin.h
@@ -1362,14 +1362,30 @@ extern __inline __mmask8
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
_mm_fpclass_ss_mask (__m128 __A, const int __imm)
{
- return (__mmask8) __builtin_ia32_fpclassss ((__v4sf) __A, __imm);
+ return (__mmask8) __builtin_ia32_fpclassss_mask ((__v4sf) __A, __imm,
+ (__mmask8) -1);
}
extern __inline __mmask8
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
_mm_fpclass_sd_mask (__m128d __A, const int __imm)
{
- return (__mmask8) __builtin_ia32_fpclasssd ((__v2df) __A, __imm);
+ return (__mmask8) __builtin_ia32_fpclasssd_mask ((__v2df) __A, __imm,
+ (__mmask8) -1);
+}
+
+extern __inline __mmask8
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_mask_fpclass_ss_mask (__mmask8 __U, __m128 __A, const int __imm)
+{
+ return (__mmask8) __builtin_ia32_fpclassss_mask ((__v4sf) __A, __imm, __U);
+}
+
+extern __inline __mmask8
+__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
+_mm_mask_fpclass_sd_mask (__mmask8 __U, __m128d __A, const int __imm)
+{
+ return (__mmask8) __builtin_ia32_fpclasssd_mask ((__v2df) __A, __imm, __U);
}
extern __inline __m512i
@@ -2617,11 +2633,21 @@ _mm512_fpclass_ps_mask (__m512 __A, const int __imm)
(__v16si)(__m512i)_mm512_setzero_si512 (),\
(__mmask16)(U)))
-#define _mm_fpclass_ss_mask(X, C) \
- ((__mmask8) __builtin_ia32_fpclassss ((__v4sf) (__m128) (X), (int) (C))) \
+#define _mm_fpclass_ss_mask(X, C) \
+ ((__mmask8) __builtin_ia32_fpclassss_mask ((__v4sf) (__m128) (X), \
+ (int) (C), (__mmask8) (-1))) \
+
+#define _mm_fpclass_sd_mask(X, C) \
+ ((__mmask8) __builtin_ia32_fpclasssd_mask ((__v2df) (__m128d) (X), \
+ (int) (C), (__mmask8) (-1))) \
+
+#define _mm_mask_fpclass_ss_mask(X, C, U) \
+ ((__mmask8) __builtin_ia32_fpclassss_mask ((__v4sf) (__m128) (X), \
+ (int) (C), (__mmask8) (U)))
-#define _mm_fpclass_sd_mask(X, C) \
- ((__mmask8) __builtin_ia32_fpclasssd ((__v2df) (__m128d) (X), (int) (C))) \
+#define _mm_mask_fpclass_sd_mask(X, C, U) \
+ ((__mmask8) __builtin_ia32_fpclasssd_mask ((__v2df) (__m128d) (X), \
+ (int) (C), (__mmask8) (U)))
#define _mm512_mask_fpclass_pd_mask(u, X, C) \
((__mmask8) __builtin_ia32_fpclasspd512_mask ((__v8df) (__m512d) (X), \
diff --git a/gcc/config/i386/avx512vp2intersectintrin.h b/gcc/config/i386/avx512vp2intersectintrin.h
new file mode 100644
index 0000000..60cb52c
--- /dev/null
+++ b/gcc/config/i386/avx512vp2intersectintrin.h
@@ -0,0 +1,35 @@
+#if !defined _IMMINTRIN_H_INCLUDED
+#error "Never use <avx512vp2intersectintrin.h> directly; include <immintrin.h> instead."
+#endif
+
+#ifndef _AVX512VP2INTERSECTINTRIN_H_INCLUDED
+#define _AVX512VP2INTERSECTINTRIN_H_INCLUDED
+
+#if !defined(__AVX512VP2INTERSECT__)
+#pragma GCC push_options
+#pragma GCC target("avx512vp2intersect")
+#define __DISABLE_AVX512VP2INTERSECT__
+#endif /* __AVX512VP2INTERSECT__ */
+
+extern __inline void
+__attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_2intersect_epi32 (__m512i __A, __m512i __B, __mmask16 *__U,
+ __mmask16 *__M)
+{
+ __builtin_ia32_2intersectd512 (__U, __M, (__v16si) __A, (__v16si) __B);
+}
+
+extern __inline void
+__attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_mm512_2intersect_epi64 (__m512i __A, __m512i __B, __mmask8 *__U,
+ __mmask8 *__M)
+{
+ __builtin_ia32_2intersectq512 (__U, __M, (__v8di) __A, (__v8di) __B);
+}
+
+#ifdef __DISABLE_AVX512VP2INTERSECT__
+#undef __DISABLE_AVX512VP2INTERSECT__
+#pragma GCC pop_options
+#endif /* __DISABLE_AVX512VP2INTERSECT__ */
+
+#endif /* _AVX512VP2INTERSECTINTRIN_H_INCLUDED */
diff --git a/gcc/config/i386/avx512vp2intersectvlintrin.h b/gcc/config/i386/avx512vp2intersectvlintrin.h
new file mode 100644
index 0000000..26eee36
--- /dev/null
+++ b/gcc/config/i386/avx512vp2intersectvlintrin.h
@@ -0,0 +1,49 @@
+#if !defined _IMMINTRIN_H_INCLUDED
+#error "Never use <avx512vp2intersectintrin.h> directly; include <immintrin.h> instead."
+#endif
+
+#ifndef _AVX512VP2INTERSECTVLINTRIN_H_INCLUDED
+#define _AVX512VP2INTERSECTVLINTRIN_H_INCLUDED
+
+#if !defined(__AVX512VP2INTERSECT__) || !defined(__AVX512VL__)
+#pragma GCC push_options
+#pragma GCC target("avx512vp2intersect,avx512vl")
+#define __DISABLE_AVX512VP2INTERSECTVL__
+#endif /* __AVX512VP2INTERSECTVL__ */
+
+extern __inline void
+__attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_mm_2intersect_epi32 (__m128i __A, __m128i __B, __mmask8 *__U, __mmask8 *__M)
+{
+ __builtin_ia32_2intersectd128 (__U, __M, (__v4si) __A, (__v4si) __B);
+}
+
+extern __inline void
+__attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_2intersect_epi32 (__m256i __A, __m256i __B, __mmask8 *__U,
+ __mmask8 *__M)
+{
+ __builtin_ia32_2intersectd256 (__U, __M, (__v8si) __A, (__v8si) __B);
+}
+
+extern __inline void
+__attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_mm_2intersect_epi64 (__m128i __A, __m128i __B, __mmask8 *__U, __mmask8 *__M)
+{
+ __builtin_ia32_2intersectq128 (__U, __M, (__v2di) __A, (__v2di) __B);
+}
+
+extern __inline void
+__attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_mm256_2intersect_epi64 (__m256i __A, __m256i __B, __mmask8 *__U,
+ __mmask8 *__M)
+{
+ __builtin_ia32_2intersectq256 (__U, __M, (__v4di) __A, (__v4di) __B);
+}
+
+#ifdef __DISABLE_AVX512VP2INTERSECTVL__
+#undef __DISABLE_AVX512VP2INTERSECTVL__
+#pragma GCC pop_options
+#endif /* __DISABLE_AVX512VP2INTERSECTVL__ */
+
+#endif /* _AVX512VP2INTERSECTVLINTRIN_H_INCLUDED */
diff --git a/gcc/config/i386/constraints.md b/gcc/config/i386/constraints.md
index 16075b4..05ee7c9 100644
--- a/gcc/config/i386/constraints.md
+++ b/gcc/config/i386/constraints.md
@@ -109,7 +109,8 @@
;; and all SSE regs otherwise
;; v any EVEX encodable SSE register for AVX512VL target,
;; otherwise any SSE register
-;; h EVEX encodable SSE register with number factor of four
+;; w any EVEX encodable SSE register for AVX512BW with TARGET_AVX512VL
+;; target.
(define_register_constraint "Yz" "TARGET_SSE ? SSE_FIRST_REG : NO_REGS"
"First SSE register (@code{%xmm0}).")
@@ -146,6 +147,10 @@
"TARGET_AVX512VL ? ALL_SSE_REGS : TARGET_SSE ? SSE_REGS : NO_REGS"
"@internal For AVX512VL, any EVEX encodable SSE register (@code{%xmm0-%xmm31}), otherwise any SSE register.")
+(define_register_constraint "Yw"
+ "TARGET_AVX512BW && TARGET_AVX512VL ? ALL_SSE_REGS : NO_REGS"
+ "@internal Any EVEX encodable SSE register (@code{%xmm0-%xmm31}) for AVX512BW with TARGET_AVX512VL target.")
+
;; We use the B prefix to denote any number of internal operands:
;; f FLAGS_REG
;; g GOT memory operand.
diff --git a/gcc/config/i386/cpuid.h b/gcc/config/i386/cpuid.h
index 8ddd425..6108577 100644
--- a/gcc/config/i386/cpuid.h
+++ b/gcc/config/i386/cpuid.h
@@ -113,11 +113,13 @@
#define bit_RDPID (1 << 22)
#define bit_MOVDIRI (1 << 27)
#define bit_MOVDIR64B (1 << 28)
+#define bit_ENQCMD (1 << 29)
#define bit_CLDEMOTE (1 << 25)
/* %edx */
#define bit_AVX5124VNNIW (1 << 2)
#define bit_AVX5124FMAPS (1 << 3)
+#define bit_AVX512VP2INTERSECT (1 << 8)
#define bit_IBT (1 << 20)
#define bit_PCONFIG (1 << 18)
/* XFEATURE_ENABLED_MASK register bits (%eax == 13, %ecx == 0) */
@@ -187,10 +189,27 @@
#define signature_VORTEX_ecx 0x436f5320
#define signature_VORTEX_edx 0x36387865
+#ifndef __x86_64__
+/* At least one cpu (Winchip 2) does not set %ebx and %ecx
+ for cpuid leaf 1. Forcibly zero the two registers before
+ calling cpuid as a precaution. */
+#define __cpuid(level, a, b, c, d) \
+ do { \
+ if (__builtin_constant_p (level) && (level) != 1) \
+ __asm__ ("cpuid\n\t" \
+ : "=a" (a), "=b" (b), "=c" (c), "=d" (d) \
+ : "0" (level)); \
+ else \
+ __asm__ ("cpuid\n\t" \
+ : "=a" (a), "=b" (b), "=c" (c), "=d" (d) \
+ : "0" (level), "1" (0), "2" (0)); \
+ } while (0)
+#else
#define __cpuid(level, a, b, c, d) \
__asm__ ("cpuid\n\t" \
: "=a" (a), "=b" (b), "=c" (c), "=d" (d) \
: "0" (level))
+#endif
#define __cpuid_count(level, count, a, b, c, d) \
__asm__ ("cpuid\n\t" \
diff --git a/gcc/config/i386/darwin.h b/gcc/config/i386/darwin.h
index d8e72ec..93bd558 100644
--- a/gcc/config/i386/darwin.h
+++ b/gcc/config/i386/darwin.h
@@ -89,14 +89,12 @@ along with GCC; see the file COPYING3. If not see
#undef WCHAR_TYPE_SIZE
#define WCHAR_TYPE_SIZE 32
-/* Generate branch islands stubs if this is true. */
-extern int darwin_emit_branch_islands;
-
-#undef TARGET_MACHO_BRANCH_ISLANDS
-#define TARGET_MACHO_BRANCH_ISLANDS darwin_emit_branch_islands
+/* Generate pic symbol indirection stubs if this is true. */
+#undef TARGET_MACHO_PICSYM_STUBS
+#define TARGET_MACHO_PICSYM_STUBS (darwin_picsymbol_stubs)
/* For compatibility with OSX system tools, use the new style of pic stub
- if this is set. */
+ if this is set (default). */
#undef MACHOPIC_ATT_STUB
#define MACHOPIC_ATT_STUB (darwin_macho_att_stub)
@@ -131,7 +129,9 @@ extern int darwin_emit_branch_islands;
#undef CC1_SPEC
#define CC1_SPEC "%(cc1_cpu) \
%{!mkernel:%{!static:%{!mdynamic-no-pic:-fPIC}}} \
- %{g: %{!fno-eliminate-unused-debug-symbols: -feliminate-unused-debug-symbols }} " \
+ %{g: %{!fno-eliminate-unused-debug-symbols: -feliminate-unused-debug-symbols }} \
+ %{mx32:%eDarwin is not an mx32 platform} \
+ %{mfentry*:%eDarwin does not support -mfentry or associated options}" \
DARWIN_CC1_SPEC
#undef ASM_SPEC
@@ -221,6 +221,18 @@ extern int darwin_emit_branch_islands;
} \
} while (0)
+#ifdef HAVE_GAS_MAX_SKIP_P2ALIGN
+#define ASM_OUTPUT_MAX_SKIP_ALIGN(FILE,LOG,MAX_SKIP) \
+ do { \
+ if ((LOG) != 0) { \
+ if ((MAX_SKIP) == 0 || (MAX_SKIP) >= (1 << (LOG)) - 1) \
+ fprintf ((FILE), "\t.p2align %d\n", (LOG)); \
+ else \
+ fprintf ((FILE), "\t.p2align %d,,%d\n", (LOG), (MAX_SKIP)); \
+ } \
+ } while (0)
+#endif
+
/* Darwin x86 assemblers support the .ident directive. */
#undef TARGET_ASM_OUTPUT_IDENT
@@ -230,7 +242,7 @@ extern int darwin_emit_branch_islands;
#undef FUNCTION_PROFILER
#define FUNCTION_PROFILER(FILE, LABELNO) \
do { \
- if (TARGET_MACHO_BRANCH_ISLANDS \
+ if (TARGET_MACHO_PICSYM_STUBS \
&& MACHOPIC_INDIRECT && !TARGET_64BIT) \
{ \
const char *name = machopic_mcount_stub_name (); \
diff --git a/gcc/config/i386/driver-i386.c b/gcc/config/i386/driver-i386.c
index 22ad5bcf..a9d8981 100644
--- a/gcc/config/i386/driver-i386.c
+++ b/gcc/config/i386/driver-i386.c
@@ -423,7 +423,9 @@ const char *host_detect_local_cpu (int argc, const char **argv)
unsigned int has_shstk = 0;
unsigned int has_avx512vnni = 0, has_vaes = 0;
unsigned int has_vpclmulqdq = 0;
+ unsigned int has_avx512vp2intersect = 0;
unsigned int has_movdiri = 0, has_movdir64b = 0;
+ unsigned int has_enqcmd = 0;
unsigned int has_waitpkg = 0;
unsigned int has_cldemote = 0;
unsigned int has_avx512bf16 = 0;
@@ -526,10 +528,12 @@ const char *host_detect_local_cpu (int argc, const char **argv)
has_avx512bitalg = ecx & bit_AVX512BITALG;
has_movdiri = ecx & bit_MOVDIRI;
has_movdir64b = ecx & bit_MOVDIR64B;
+ has_enqcmd = ecx & bit_ENQCMD;
has_cldemote = ecx & bit_CLDEMOTE;
has_avx5124vnniw = edx & bit_AVX5124VNNIW;
has_avx5124fmaps = edx & bit_AVX5124FMAPS;
+ has_avx512vp2intersect = edx & bit_AVX512VP2INTERSECT;
has_shstk = ecx & bit_SHSTK;
has_pconfig = edx & bit_PCONFIG;
@@ -1141,9 +1145,11 @@ const char *host_detect_local_cpu (int argc, const char **argv)
const char *shstk = has_shstk ? " -mshstk" : " -mno-shstk";
const char *vaes = has_vaes ? " -mvaes" : " -mno-vaes";
const char *vpclmulqdq = has_vpclmulqdq ? " -mvpclmulqdq" : " -mno-vpclmulqdq";
+ const char *avx512vp2intersect = has_avx512vp2intersect ? " -mavx512vp2intersect" : " -mno-avx512vp2intersect";
const char *avx512bitalg = has_avx512bitalg ? " -mavx512bitalg" : " -mno-avx512bitalg";
const char *movdiri = has_movdiri ? " -mmovdiri" : " -mno-movdiri";
const char *movdir64b = has_movdir64b ? " -mmovdir64b" : " -mno-movdir64b";
+ const char *enqcmd = has_enqcmd ? " -menqcmd" : " -mno-enqcmd";
const char *waitpkg = has_waitpkg ? " -mwaitpkg" : " -mno-waitpkg";
const char *cldemote = has_cldemote ? " -mcldemote" : " -mno-cldemote";
const char *ptwrite = has_ptwrite ? " -mptwrite" : " -mno-ptwrite";
@@ -1162,7 +1168,7 @@ const char *host_detect_local_cpu (int argc, const char **argv)
clwb, mwaitx, clzero, pku, rdpid, gfni, shstk,
avx512vbmi2, avx512vnni, vaes, vpclmulqdq,
avx512bitalg, movdiri, movdir64b, waitpkg, cldemote,
- ptwrite, avx512bf16,
+ ptwrite, avx512bf16, enqcmd, avx512vp2intersect,
NULL);
}
diff --git a/gcc/config/i386/enqcmdintrin.h b/gcc/config/i386/enqcmdintrin.h
new file mode 100644
index 0000000..0fb5ece
--- /dev/null
+++ b/gcc/config/i386/enqcmdintrin.h
@@ -0,0 +1,55 @@
+/* Copyright (C) 2019 Free Software Foundation, Inc.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3, or (at your option)
+ any later version.
+
+ GCC is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ Under Section 7 of GPL version 3, you are granted additional
+ permissions described in the GCC Runtime Library Exception, version
+ 3.1, as published by the Free Software Foundation.
+
+ You should have received a copy of the GNU General Public License and
+ a copy of the GCC Runtime Library Exception along with this program;
+ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+#if !defined _IMMINTRIN_H_INCLUDED
+# error "Never use <enqcmdntrin.h> directly; include <x86intrin.h> instead."
+#endif
+
+#ifndef _ENQCMDNTRIN_H_INCLUDED
+#define _ENQCMDNTRIN_H_INCLUDED
+
+#ifndef __ENQCMD__
+#pragma GCC push_options
+#pragma GCC target ("enqcmd")
+#define __DISABLE_ENQCMD__
+#endif /* __ENQCMD__ */
+
+extern __inline int
+__attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_enqcmd (void * __P, const void * __Q)
+{
+ return __builtin_ia32_enqcmd (__P, __Q);
+}
+
+extern __inline int
+__attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_enqcmds (void * __P, const void * __Q)
+{
+ return __builtin_ia32_enqcmds (__P, __Q);
+}
+
+#ifdef __DISABLE_ENQCMD__
+#undef __DISABLE_ENQCMD__
+#pragma GCC pop_options
+#endif /* __DISABLE_ENQCMD__ */
+#endif /* _ENQCMDNTRIN_H_INCLUDED. */
diff --git a/gcc/config/i386/host-mingw32.c b/gcc/config/i386/host-mingw32.c
index f2b56d7..3254d02 100644
--- a/gcc/config/i386/host-mingw32.c
+++ b/gcc/config/i386/host-mingw32.c
@@ -157,10 +157,10 @@ mingw32_gt_pch_use_address (void *addr, size_t size, int fd,
/* Determine the version of Windows we are running on and use a
uniquely-named local object if running > 4. */
GetVersionEx (&version_info);
+
+ char local_object_name[sizeof (OBJECT_NAME_FMT) + sizeof (DWORD) * 2];
if (version_info.dwMajorVersion > 4)
{
- char local_object_name [sizeof (OBJECT_NAME_FMT)
- + sizeof (DWORD) * 2];
snprintf (local_object_name, sizeof (local_object_name),
OBJECT_NAME_FMT "%lx", GetCurrentProcessId());
object_name = local_object_name;
diff --git a/gcc/config/i386/i386-builtin-types.def b/gcc/config/i386/i386-builtin-types.def
index d7b9939..221c0e7 100644
--- a/gcc/config/i386/i386-builtin-types.def
+++ b/gcc/config/i386/i386-builtin-types.def
@@ -533,6 +533,7 @@ DEF_FUNCTION_TYPE (VOID, PFLOAT, V16SF)
DEF_FUNCTION_TYPE (VOID, PINT, INT)
DEF_FUNCTION_TYPE (VOID, PUNSIGNED, UNSIGNED)
DEF_FUNCTION_TYPE (VOID, PVOID, PCVOID)
+DEF_FUNCTION_TYPE (INT, PVOID, PCVOID)
DEF_FUNCTION_TYPE (VOID, PLONGLONG, LONGLONG)
DEF_FUNCTION_TYPE (VOID, PULONGLONG, ULONGLONG)
DEF_FUNCTION_TYPE (VOID, PV2SI, V2SI)
@@ -963,11 +964,9 @@ DEF_FUNCTION_TYPE (V4DI, V4DI, V2DI, V4DI, UQI)
DEF_FUNCTION_TYPE (QI, V8DF, INT)
DEF_FUNCTION_TYPE (QI, V4DF, INT)
DEF_FUNCTION_TYPE (QI, V4DF, V4DF, INT, UQI)
-DEF_FUNCTION_TYPE (QI, V2DF, INT)
DEF_FUNCTION_TYPE (HI, V16SF, INT)
DEF_FUNCTION_TYPE (QI, V8SF, INT)
DEF_FUNCTION_TYPE (QI, V8SF, V8SF, INT, UQI)
-DEF_FUNCTION_TYPE (QI, V4SF, INT)
DEF_FUNCTION_TYPE (QI, V8DF, INT, UQI)
DEF_FUNCTION_TYPE (QI, V4DF, INT, UQI)
DEF_FUNCTION_TYPE (QI, V2DF, INT, UQI)
@@ -976,6 +975,13 @@ DEF_FUNCTION_TYPE (QI, V8SF, INT, UQI)
DEF_FUNCTION_TYPE (QI, V4SF, INT, UQI)
DEF_FUNCTION_TYPE (VOID, PV32QI, V32HI, USI)
+DEF_FUNCTION_TYPE (VOID, PUHI, PUHI, V16SI, V16SI)
+DEF_FUNCTION_TYPE (VOID, PUQI, PUQI, V8SI, V8SI)
+DEF_FUNCTION_TYPE (VOID, PUQI, PUQI, V4SI, V4SI)
+DEF_FUNCTION_TYPE (VOID, PUQI, PUQI, V8DI, V8DI)
+DEF_FUNCTION_TYPE (VOID, PUQI, PUQI, V4DI, V4DI)
+DEF_FUNCTION_TYPE (VOID, PUQI, PUQI, V2DI, V2DI)
+
DEF_FUNCTION_TYPE (V2DI, V2DI, V2DI, UINT, UINT)
DEF_FUNCTION_TYPE (V4HI, HI, HI, HI, HI)
diff --git a/gcc/config/i386/i386-builtin.def b/gcc/config/i386/i386-builtin.def
index e95d5d3..ef45311 100644
--- a/gcc/config/i386/i386-builtin.def
+++ b/gcc/config/i386/i386-builtin.def
@@ -100,7 +100,7 @@ BDESC (0, 0, CODE_FOR_fnstsw, "__builtin_ia32_fnstsw", IX86_BUILTIN_FNSTSW, UNKN
BDESC (0, 0, CODE_FOR_fnclex, "__builtin_ia32_fnclex", IX86_BUILTIN_FNCLEX, UNKNOWN, (int) VOID_FTYPE_VOID)
/* MMX */
-BDESC (OPTION_MASK_ISA_MMX, 0, CODE_FOR_mmx_emms, "__builtin_ia32_emms", IX86_BUILTIN_EMMS, UNKNOWN, (int) VOID_FTYPE_VOID)
+BDESC (OPTION_MASK_ISA_MMX | OPTION_MASK_ISA_SSE2, 0, CODE_FOR_mmx_emms, "__builtin_ia32_emms", IX86_BUILTIN_EMMS, UNKNOWN, (int) VOID_FTYPE_VOID)
/* 3DNow! */
BDESC (OPTION_MASK_ISA_3DNOW, 0, CODE_FOR_mmx_femms, "__builtin_ia32_femms", IX86_BUILTIN_FEMMS, UNKNOWN, (int) VOID_FTYPE_VOID)
@@ -288,6 +288,14 @@ BDESC (OPTION_MASK_ISA_AVX512BW, 0, CODE_FOR_avx512bw_loadv64qi_mask, "__builtin
BDESC (OPTION_MASK_ISA_AVX512BW, 0, CODE_FOR_avx512bw_storev32hi_mask, "__builtin_ia32_storedquhi512_mask", IX86_BUILTIN_STOREDQUHI512_MASK, UNKNOWN, (int) VOID_FTYPE_PSHORT_V32HI_USI)
BDESC (OPTION_MASK_ISA_AVX512BW, 0, CODE_FOR_avx512bw_storev64qi_mask, "__builtin_ia32_storedquqi512_mask", IX86_BUILTIN_STOREDQUQI512_MASK, UNKNOWN, (int) VOID_FTYPE_PCHAR_V64QI_UDI)
+/* AVX512VP2INTERSECT */
+BDESC (0, OPTION_MASK_ISA_AVX512VP2INTERSECT, CODE_FOR_nothing, "__builtin_ia32_2intersectd512", IX86_BUILTIN_2INTERSECTD512, UNKNOWN, (int) VOID_FTYPE_PUHI_PUHI_V16SI_V16SI)
+BDESC (0, OPTION_MASK_ISA_AVX512VP2INTERSECT, CODE_FOR_nothing, "__builtin_ia32_2intersectq512", IX86_BUILTIN_2INTERSECTQ512, UNKNOWN, (int) VOID_FTYPE_PUQI_PUQI_V8DI_V8DI)
+BDESC (0, OPTION_MASK_ISA_AVX512VP2INTERSECT, CODE_FOR_nothing, "__builtin_ia32_2intersectd256", IX86_BUILTIN_2INTERSECTD256, UNKNOWN, (int) VOID_FTYPE_PUQI_PUQI_V8SI_V8SI)
+BDESC (0, OPTION_MASK_ISA_AVX512VP2INTERSECT, CODE_FOR_nothing, "__builtin_ia32_2intersectq256", IX86_BUILTIN_2INTERSECTQ256, UNKNOWN, (int) VOID_FTYPE_PUQI_PUQI_V4DI_V4DI)
+BDESC (0, OPTION_MASK_ISA_AVX512VP2INTERSECT, CODE_FOR_nothing, "__builtin_ia32_2intersectd128", IX86_BUILTIN_2INTERSECTD128, UNKNOWN, (int) VOID_FTYPE_PUQI_PUQI_V4SI_V4SI)
+BDESC (0, OPTION_MASK_ISA_AVX512VP2INTERSECT, CODE_FOR_nothing, "__builtin_ia32_2intersectq128", IX86_BUILTIN_2INTERSECTQ128, UNKNOWN, (int) VOID_FTYPE_PUQI_PUQI_V2DI_V2DI)
+
/* AVX512VL */
BDESC (OPTION_MASK_ISA_AVX512BW | OPTION_MASK_ISA_AVX512VL, 0, CODE_FOR_avx512vl_loadv16hi_mask, "__builtin_ia32_loaddquhi256_mask", IX86_BUILTIN_LOADDQUHI256_MASK, UNKNOWN, (int) V16HI_FTYPE_PCSHORT_V16HI_UHI)
BDESC (OPTION_MASK_ISA_AVX512BW | OPTION_MASK_ISA_AVX512VL, 0, CODE_FOR_avx512vl_loadv8hi_mask, "__builtin_ia32_loaddquhi128_mask", IX86_BUILTIN_LOADDQUHI128_MASK, UNKNOWN, (int) V8HI_FTYPE_PCSHORT_V8HI_UQI)
@@ -434,6 +442,10 @@ BDESC (0, OPTION_MASK_ISA_MOVDIR64B, CODE_FOR_nothing, "__builtin_ia32_movdir64b
BDESC (0, OPTION_MASK_ISA_PTWRITE, CODE_FOR_ptwritesi, "__builtin_ia32_ptwrite32", IX86_BUILTIN_PTWRITE32, UNKNOWN, (int) VOID_FTYPE_UNSIGNED)
BDESC (OPTION_MASK_ISA_64BIT, OPTION_MASK_ISA_PTWRITE, CODE_FOR_ptwritedi, "__builtin_ia32_ptwrite64", IX86_BUILTIN_PTWRITE64, UNKNOWN, (int) VOID_FTYPE_UINT64)
+/* ENQCMD */
+BDESC (0, OPTION_MASK_ISA_ENQCMD, CODE_FOR_nothing, "__builtin_ia32_enqcmd", IX86_BUILTIN_ENQCMD, UNKNOWN, (int) INT_FTYPE_PVOID_PCVOID)
+BDESC (0, OPTION_MASK_ISA_ENQCMD, CODE_FOR_nothing, "__builtin_ia32_enqcmds", IX86_BUILTIN_ENQCMDS, UNKNOWN, (int) INT_FTYPE_PVOID_PCVOID)
+
BDESC_END (SPECIAL_ARGS, ARGS)
/* Builtins with variable number of arguments. */
@@ -446,68 +458,68 @@ BDESC (0, 0, CODE_FOR_rotrqi3, "__builtin_ia32_rorqi", IX86_BUILTIN_RORQI, UNKNO
BDESC (0, 0, CODE_FOR_rotrhi3, "__builtin_ia32_rorhi", IX86_BUILTIN_RORHI, UNKNOWN, (int) UINT16_FTYPE_UINT16_INT)
/* MMX */
-BDESC (OPTION_MASK_ISA_MMX, 0, CODE_FOR_mmx_addv8qi3, "__builtin_ia32_paddb", IX86_BUILTIN_PADDB, UNKNOWN, (int) V8QI_FTYPE_V8QI_V8QI)
-BDESC (OPTION_MASK_ISA_MMX, 0, CODE_FOR_mmx_addv4hi3, "__builtin_ia32_paddw", IX86_BUILTIN_PADDW, UNKNOWN, (int) V4HI_FTYPE_V4HI_V4HI)
-BDESC (OPTION_MASK_ISA_MMX, 0, CODE_FOR_mmx_addv2si3, "__builtin_ia32_paddd", IX86_BUILTIN_PADDD, UNKNOWN, (int) V2SI_FTYPE_V2SI_V2SI)
-BDESC (OPTION_MASK_ISA_MMX, 0, CODE_FOR_mmx_subv8qi3, "__builtin_ia32_psubb", IX86_BUILTIN_PSUBB, UNKNOWN, (int) V8QI_FTYPE_V8QI_V8QI)
-BDESC (OPTION_MASK_ISA_MMX, 0, CODE_FOR_mmx_subv4hi3, "__builtin_ia32_psubw", IX86_BUILTIN_PSUBW, UNKNOWN, (int) V4HI_FTYPE_V4HI_V4HI)
-BDESC (OPTION_MASK_ISA_MMX, 0, CODE_FOR_mmx_subv2si3, "__builtin_ia32_psubd", IX86_BUILTIN_PSUBD, UNKNOWN, (int) V2SI_FTYPE_V2SI_V2SI)
-
-BDESC (OPTION_MASK_ISA_MMX, 0, CODE_FOR_mmx_ssaddv8qi3, "__builtin_ia32_paddsb", IX86_BUILTIN_PADDSB, UNKNOWN, (int) V8QI_FTYPE_V8QI_V8QI)
-BDESC (OPTION_MASK_ISA_MMX, 0, CODE_FOR_mmx_ssaddv4hi3, "__builtin_ia32_paddsw", IX86_BUILTIN_PADDSW, UNKNOWN, (int) V4HI_FTYPE_V4HI_V4HI)
-BDESC (OPTION_MASK_ISA_MMX, 0, CODE_FOR_mmx_sssubv8qi3, "__builtin_ia32_psubsb", IX86_BUILTIN_PSUBSB, UNKNOWN, (int) V8QI_FTYPE_V8QI_V8QI)
-BDESC (OPTION_MASK_ISA_MMX, 0, CODE_FOR_mmx_sssubv4hi3, "__builtin_ia32_psubsw", IX86_BUILTIN_PSUBSW, UNKNOWN, (int) V4HI_FTYPE_V4HI_V4HI)
-BDESC (OPTION_MASK_ISA_MMX, 0, CODE_FOR_mmx_usaddv8qi3, "__builtin_ia32_paddusb", IX86_BUILTIN_PADDUSB, UNKNOWN, (int) V8QI_FTYPE_V8QI_V8QI)
-BDESC (OPTION_MASK_ISA_MMX, 0, CODE_FOR_mmx_usaddv4hi3, "__builtin_ia32_paddusw", IX86_BUILTIN_PADDUSW, UNKNOWN, (int) V4HI_FTYPE_V4HI_V4HI)
-BDESC (OPTION_MASK_ISA_MMX, 0, CODE_FOR_mmx_ussubv8qi3, "__builtin_ia32_psubusb", IX86_BUILTIN_PSUBUSB, UNKNOWN, (int) V8QI_FTYPE_V8QI_V8QI)
-BDESC (OPTION_MASK_ISA_MMX, 0, CODE_FOR_mmx_ussubv4hi3, "__builtin_ia32_psubusw", IX86_BUILTIN_PSUBUSW, UNKNOWN, (int) V4HI_FTYPE_V4HI_V4HI)
-
-BDESC (OPTION_MASK_ISA_MMX, 0, CODE_FOR_mmx_mulv4hi3, "__builtin_ia32_pmullw", IX86_BUILTIN_PMULLW, UNKNOWN, (int) V4HI_FTYPE_V4HI_V4HI)
-BDESC (OPTION_MASK_ISA_MMX, 0, CODE_FOR_mmx_smulv4hi3_highpart, "__builtin_ia32_pmulhw", IX86_BUILTIN_PMULHW, UNKNOWN, (int) V4HI_FTYPE_V4HI_V4HI)
-
-BDESC (OPTION_MASK_ISA_MMX, 0, CODE_FOR_mmx_andv2si3, "__builtin_ia32_pand", IX86_BUILTIN_PAND, UNKNOWN, (int) V2SI_FTYPE_V2SI_V2SI)
-BDESC (OPTION_MASK_ISA_MMX, 0, CODE_FOR_mmx_andnotv2si3, "__builtin_ia32_pandn", IX86_BUILTIN_PANDN, UNKNOWN, (int) V2SI_FTYPE_V2SI_V2SI)
-BDESC (OPTION_MASK_ISA_MMX, 0, CODE_FOR_mmx_iorv2si3, "__builtin_ia32_por", IX86_BUILTIN_POR, UNKNOWN, (int) V2SI_FTYPE_V2SI_V2SI)
-BDESC (OPTION_MASK_ISA_MMX, 0, CODE_FOR_mmx_xorv2si3, "__builtin_ia32_pxor", IX86_BUILTIN_PXOR, UNKNOWN, (int) V2SI_FTYPE_V2SI_V2SI)
-
-BDESC (OPTION_MASK_ISA_MMX, 0, CODE_FOR_mmx_eqv8qi3, "__builtin_ia32_pcmpeqb", IX86_BUILTIN_PCMPEQB, UNKNOWN, (int) V8QI_FTYPE_V8QI_V8QI)
-BDESC (OPTION_MASK_ISA_MMX, 0, CODE_FOR_mmx_eqv4hi3, "__builtin_ia32_pcmpeqw", IX86_BUILTIN_PCMPEQW, UNKNOWN, (int) V4HI_FTYPE_V4HI_V4HI)
-BDESC (OPTION_MASK_ISA_MMX, 0, CODE_FOR_mmx_eqv2si3, "__builtin_ia32_pcmpeqd", IX86_BUILTIN_PCMPEQD, UNKNOWN, (int) V2SI_FTYPE_V2SI_V2SI)
-BDESC (OPTION_MASK_ISA_MMX, 0, CODE_FOR_mmx_gtv8qi3, "__builtin_ia32_pcmpgtb", IX86_BUILTIN_PCMPGTB, UNKNOWN, (int) V8QI_FTYPE_V8QI_V8QI)
-BDESC (OPTION_MASK_ISA_MMX, 0, CODE_FOR_mmx_gtv4hi3, "__builtin_ia32_pcmpgtw", IX86_BUILTIN_PCMPGTW, UNKNOWN, (int) V4HI_FTYPE_V4HI_V4HI)
-BDESC (OPTION_MASK_ISA_MMX, 0, CODE_FOR_mmx_gtv2si3, "__builtin_ia32_pcmpgtd", IX86_BUILTIN_PCMPGTD, UNKNOWN, (int) V2SI_FTYPE_V2SI_V2SI)
-
-BDESC (OPTION_MASK_ISA_MMX, 0, CODE_FOR_mmx_punpckhbw, "__builtin_ia32_punpckhbw", IX86_BUILTIN_PUNPCKHBW, UNKNOWN, (int) V8QI_FTYPE_V8QI_V8QI)
-BDESC (OPTION_MASK_ISA_MMX, 0, CODE_FOR_mmx_punpckhwd, "__builtin_ia32_punpckhwd", IX86_BUILTIN_PUNPCKHWD, UNKNOWN, (int) V4HI_FTYPE_V4HI_V4HI)
-BDESC (OPTION_MASK_ISA_MMX, 0, CODE_FOR_mmx_punpckhdq, "__builtin_ia32_punpckhdq", IX86_BUILTIN_PUNPCKHDQ, UNKNOWN, (int) V2SI_FTYPE_V2SI_V2SI)
-BDESC (OPTION_MASK_ISA_MMX, 0, CODE_FOR_mmx_punpcklbw, "__builtin_ia32_punpcklbw", IX86_BUILTIN_PUNPCKLBW, UNKNOWN, (int) V8QI_FTYPE_V8QI_V8QI)
-BDESC (OPTION_MASK_ISA_MMX, 0, CODE_FOR_mmx_punpcklwd, "__builtin_ia32_punpcklwd", IX86_BUILTIN_PUNPCKLWD, UNKNOWN, (int) V4HI_FTYPE_V4HI_V4HI)
-BDESC (OPTION_MASK_ISA_MMX, 0, CODE_FOR_mmx_punpckldq, "__builtin_ia32_punpckldq", IX86_BUILTIN_PUNPCKLDQ, UNKNOWN, (int) V2SI_FTYPE_V2SI_V2SI)
-
-BDESC (OPTION_MASK_ISA_MMX, 0, CODE_FOR_mmx_packsswb, "__builtin_ia32_packsswb", IX86_BUILTIN_PACKSSWB, UNKNOWN, (int) V8QI_FTYPE_V4HI_V4HI)
-BDESC (OPTION_MASK_ISA_MMX, 0, CODE_FOR_mmx_packssdw, "__builtin_ia32_packssdw", IX86_BUILTIN_PACKSSDW, UNKNOWN, (int) V4HI_FTYPE_V2SI_V2SI)
-BDESC (OPTION_MASK_ISA_MMX, 0, CODE_FOR_mmx_packuswb, "__builtin_ia32_packuswb", IX86_BUILTIN_PACKUSWB, UNKNOWN, (int) V8QI_FTYPE_V4HI_V4HI)
-
-BDESC (OPTION_MASK_ISA_MMX, 0, CODE_FOR_mmx_pmaddwd, "__builtin_ia32_pmaddwd", IX86_BUILTIN_PMADDWD, UNKNOWN, (int) V2SI_FTYPE_V4HI_V4HI)
-
-BDESC (OPTION_MASK_ISA_MMX, 0, CODE_FOR_mmx_ashlv4hi3, "__builtin_ia32_psllwi", IX86_BUILTIN_PSLLWI, UNKNOWN, (int) V4HI_FTYPE_V4HI_SI_COUNT)
-BDESC (OPTION_MASK_ISA_MMX, 0, CODE_FOR_mmx_ashlv2si3, "__builtin_ia32_pslldi", IX86_BUILTIN_PSLLDI, UNKNOWN, (int) V2SI_FTYPE_V2SI_SI_COUNT)
-BDESC (OPTION_MASK_ISA_MMX, 0, CODE_FOR_mmx_ashlv1di3, "__builtin_ia32_psllqi", IX86_BUILTIN_PSLLQI, UNKNOWN, (int) V1DI_FTYPE_V1DI_SI_COUNT)
-BDESC (OPTION_MASK_ISA_MMX, 0, CODE_FOR_mmx_ashlv4hi3, "__builtin_ia32_psllw", IX86_BUILTIN_PSLLW, UNKNOWN, (int) V4HI_FTYPE_V4HI_V4HI_COUNT)
-BDESC (OPTION_MASK_ISA_MMX, 0, CODE_FOR_mmx_ashlv2si3, "__builtin_ia32_pslld", IX86_BUILTIN_PSLLD, UNKNOWN, (int) V2SI_FTYPE_V2SI_V2SI_COUNT)
-BDESC (OPTION_MASK_ISA_MMX, 0, CODE_FOR_mmx_ashlv1di3, "__builtin_ia32_psllq", IX86_BUILTIN_PSLLQ, UNKNOWN, (int) V1DI_FTYPE_V1DI_V1DI_COUNT)
-
-BDESC (OPTION_MASK_ISA_MMX, 0, CODE_FOR_mmx_lshrv4hi3, "__builtin_ia32_psrlwi", IX86_BUILTIN_PSRLWI, UNKNOWN, (int) V4HI_FTYPE_V4HI_SI_COUNT)
-BDESC (OPTION_MASK_ISA_MMX, 0, CODE_FOR_mmx_lshrv2si3, "__builtin_ia32_psrldi", IX86_BUILTIN_PSRLDI, UNKNOWN, (int) V2SI_FTYPE_V2SI_SI_COUNT)
-BDESC (OPTION_MASK_ISA_MMX, 0, CODE_FOR_mmx_lshrv1di3, "__builtin_ia32_psrlqi", IX86_BUILTIN_PSRLQI, UNKNOWN, (int) V1DI_FTYPE_V1DI_SI_COUNT)
-BDESC (OPTION_MASK_ISA_MMX, 0, CODE_FOR_mmx_lshrv4hi3, "__builtin_ia32_psrlw", IX86_BUILTIN_PSRLW, UNKNOWN, (int) V4HI_FTYPE_V4HI_V4HI_COUNT)
-BDESC (OPTION_MASK_ISA_MMX, 0, CODE_FOR_mmx_lshrv2si3, "__builtin_ia32_psrld", IX86_BUILTIN_PSRLD, UNKNOWN, (int) V2SI_FTYPE_V2SI_V2SI_COUNT)
-BDESC (OPTION_MASK_ISA_MMX, 0, CODE_FOR_mmx_lshrv1di3, "__builtin_ia32_psrlq", IX86_BUILTIN_PSRLQ, UNKNOWN, (int) V1DI_FTYPE_V1DI_V1DI_COUNT)
-
-BDESC (OPTION_MASK_ISA_MMX, 0, CODE_FOR_mmx_ashrv4hi3, "__builtin_ia32_psrawi", IX86_BUILTIN_PSRAWI, UNKNOWN, (int) V4HI_FTYPE_V4HI_SI_COUNT)
-BDESC (OPTION_MASK_ISA_MMX, 0, CODE_FOR_mmx_ashrv2si3, "__builtin_ia32_psradi", IX86_BUILTIN_PSRADI, UNKNOWN, (int) V2SI_FTYPE_V2SI_SI_COUNT)
-BDESC (OPTION_MASK_ISA_MMX, 0, CODE_FOR_mmx_ashrv4hi3, "__builtin_ia32_psraw", IX86_BUILTIN_PSRAW, UNKNOWN, (int) V4HI_FTYPE_V4HI_V4HI_COUNT)
-BDESC (OPTION_MASK_ISA_MMX, 0, CODE_FOR_mmx_ashrv2si3, "__builtin_ia32_psrad", IX86_BUILTIN_PSRAD, UNKNOWN, (int) V2SI_FTYPE_V2SI_V2SI_COUNT)
+BDESC (OPTION_MASK_ISA_MMX | OPTION_MASK_ISA_SSE2, 0, CODE_FOR_mmx_addv8qi3, "__builtin_ia32_paddb", IX86_BUILTIN_PADDB, UNKNOWN, (int) V8QI_FTYPE_V8QI_V8QI)
+BDESC (OPTION_MASK_ISA_MMX | OPTION_MASK_ISA_SSE2, 0, CODE_FOR_mmx_addv4hi3, "__builtin_ia32_paddw", IX86_BUILTIN_PADDW, UNKNOWN, (int) V4HI_FTYPE_V4HI_V4HI)
+BDESC (OPTION_MASK_ISA_MMX | OPTION_MASK_ISA_SSE2, 0, CODE_FOR_mmx_addv2si3, "__builtin_ia32_paddd", IX86_BUILTIN_PADDD, UNKNOWN, (int) V2SI_FTYPE_V2SI_V2SI)
+BDESC (OPTION_MASK_ISA_MMX | OPTION_MASK_ISA_SSE2, 0, CODE_FOR_mmx_subv8qi3, "__builtin_ia32_psubb", IX86_BUILTIN_PSUBB, UNKNOWN, (int) V8QI_FTYPE_V8QI_V8QI)
+BDESC (OPTION_MASK_ISA_MMX | OPTION_MASK_ISA_SSE2, 0, CODE_FOR_mmx_subv4hi3, "__builtin_ia32_psubw", IX86_BUILTIN_PSUBW, UNKNOWN, (int) V4HI_FTYPE_V4HI_V4HI)
+BDESC (OPTION_MASK_ISA_MMX | OPTION_MASK_ISA_SSE2, 0, CODE_FOR_mmx_subv2si3, "__builtin_ia32_psubd", IX86_BUILTIN_PSUBD, UNKNOWN, (int) V2SI_FTYPE_V2SI_V2SI)
+
+BDESC (OPTION_MASK_ISA_MMX | OPTION_MASK_ISA_SSE2, 0, CODE_FOR_mmx_ssaddv8qi3, "__builtin_ia32_paddsb", IX86_BUILTIN_PADDSB, UNKNOWN, (int) V8QI_FTYPE_V8QI_V8QI)
+BDESC (OPTION_MASK_ISA_MMX | OPTION_MASK_ISA_SSE2, 0, CODE_FOR_mmx_ssaddv4hi3, "__builtin_ia32_paddsw", IX86_BUILTIN_PADDSW, UNKNOWN, (int) V4HI_FTYPE_V4HI_V4HI)
+BDESC (OPTION_MASK_ISA_MMX | OPTION_MASK_ISA_SSE2, 0, CODE_FOR_mmx_sssubv8qi3, "__builtin_ia32_psubsb", IX86_BUILTIN_PSUBSB, UNKNOWN, (int) V8QI_FTYPE_V8QI_V8QI)
+BDESC (OPTION_MASK_ISA_MMX | OPTION_MASK_ISA_SSE2, 0, CODE_FOR_mmx_sssubv4hi3, "__builtin_ia32_psubsw", IX86_BUILTIN_PSUBSW, UNKNOWN, (int) V4HI_FTYPE_V4HI_V4HI)
+BDESC (OPTION_MASK_ISA_MMX | OPTION_MASK_ISA_SSE2, 0, CODE_FOR_mmx_usaddv8qi3, "__builtin_ia32_paddusb", IX86_BUILTIN_PADDUSB, UNKNOWN, (int) V8QI_FTYPE_V8QI_V8QI)
+BDESC (OPTION_MASK_ISA_MMX | OPTION_MASK_ISA_SSE2, 0, CODE_FOR_mmx_usaddv4hi3, "__builtin_ia32_paddusw", IX86_BUILTIN_PADDUSW, UNKNOWN, (int) V4HI_FTYPE_V4HI_V4HI)
+BDESC (OPTION_MASK_ISA_MMX | OPTION_MASK_ISA_SSE2, 0, CODE_FOR_mmx_ussubv8qi3, "__builtin_ia32_psubusb", IX86_BUILTIN_PSUBUSB, UNKNOWN, (int) V8QI_FTYPE_V8QI_V8QI)
+BDESC (OPTION_MASK_ISA_MMX | OPTION_MASK_ISA_SSE2, 0, CODE_FOR_mmx_ussubv4hi3, "__builtin_ia32_psubusw", IX86_BUILTIN_PSUBUSW, UNKNOWN, (int) V4HI_FTYPE_V4HI_V4HI)
+
+BDESC (OPTION_MASK_ISA_MMX | OPTION_MASK_ISA_SSE2, 0, CODE_FOR_mmx_mulv4hi3, "__builtin_ia32_pmullw", IX86_BUILTIN_PMULLW, UNKNOWN, (int) V4HI_FTYPE_V4HI_V4HI)
+BDESC (OPTION_MASK_ISA_MMX | OPTION_MASK_ISA_SSE2, 0, CODE_FOR_mmx_smulv4hi3_highpart, "__builtin_ia32_pmulhw", IX86_BUILTIN_PMULHW, UNKNOWN, (int) V4HI_FTYPE_V4HI_V4HI)
+
+BDESC (OPTION_MASK_ISA_MMX | OPTION_MASK_ISA_SSE2, 0, CODE_FOR_mmx_andv2si3, "__builtin_ia32_pand", IX86_BUILTIN_PAND, UNKNOWN, (int) V2SI_FTYPE_V2SI_V2SI)
+BDESC (OPTION_MASK_ISA_MMX | OPTION_MASK_ISA_SSE2, 0, CODE_FOR_mmx_andnotv2si3, "__builtin_ia32_pandn", IX86_BUILTIN_PANDN, UNKNOWN, (int) V2SI_FTYPE_V2SI_V2SI)
+BDESC (OPTION_MASK_ISA_MMX | OPTION_MASK_ISA_SSE2, 0, CODE_FOR_mmx_iorv2si3, "__builtin_ia32_por", IX86_BUILTIN_POR, UNKNOWN, (int) V2SI_FTYPE_V2SI_V2SI)
+BDESC (OPTION_MASK_ISA_MMX | OPTION_MASK_ISA_SSE2, 0, CODE_FOR_mmx_xorv2si3, "__builtin_ia32_pxor", IX86_BUILTIN_PXOR, UNKNOWN, (int) V2SI_FTYPE_V2SI_V2SI)
+
+BDESC (OPTION_MASK_ISA_MMX | OPTION_MASK_ISA_SSE2, 0, CODE_FOR_mmx_eqv8qi3, "__builtin_ia32_pcmpeqb", IX86_BUILTIN_PCMPEQB, UNKNOWN, (int) V8QI_FTYPE_V8QI_V8QI)
+BDESC (OPTION_MASK_ISA_MMX | OPTION_MASK_ISA_SSE2, 0, CODE_FOR_mmx_eqv4hi3, "__builtin_ia32_pcmpeqw", IX86_BUILTIN_PCMPEQW, UNKNOWN, (int) V4HI_FTYPE_V4HI_V4HI)
+BDESC (OPTION_MASK_ISA_MMX | OPTION_MASK_ISA_SSE2, 0, CODE_FOR_mmx_eqv2si3, "__builtin_ia32_pcmpeqd", IX86_BUILTIN_PCMPEQD, UNKNOWN, (int) V2SI_FTYPE_V2SI_V2SI)
+BDESC (OPTION_MASK_ISA_MMX | OPTION_MASK_ISA_SSE2, 0, CODE_FOR_mmx_gtv8qi3, "__builtin_ia32_pcmpgtb", IX86_BUILTIN_PCMPGTB, UNKNOWN, (int) V8QI_FTYPE_V8QI_V8QI)
+BDESC (OPTION_MASK_ISA_MMX | OPTION_MASK_ISA_SSE2, 0, CODE_FOR_mmx_gtv4hi3, "__builtin_ia32_pcmpgtw", IX86_BUILTIN_PCMPGTW, UNKNOWN, (int) V4HI_FTYPE_V4HI_V4HI)
+BDESC (OPTION_MASK_ISA_MMX | OPTION_MASK_ISA_SSE2, 0, CODE_FOR_mmx_gtv2si3, "__builtin_ia32_pcmpgtd", IX86_BUILTIN_PCMPGTD, UNKNOWN, (int) V2SI_FTYPE_V2SI_V2SI)
+
+BDESC (OPTION_MASK_ISA_MMX | OPTION_MASK_ISA_SSE2, 0, CODE_FOR_mmx_punpckhbw, "__builtin_ia32_punpckhbw", IX86_BUILTIN_PUNPCKHBW, UNKNOWN, (int) V8QI_FTYPE_V8QI_V8QI)
+BDESC (OPTION_MASK_ISA_MMX | OPTION_MASK_ISA_SSE2, 0, CODE_FOR_mmx_punpckhwd, "__builtin_ia32_punpckhwd", IX86_BUILTIN_PUNPCKHWD, UNKNOWN, (int) V4HI_FTYPE_V4HI_V4HI)
+BDESC (OPTION_MASK_ISA_MMX | OPTION_MASK_ISA_SSE2, 0, CODE_FOR_mmx_punpckhdq, "__builtin_ia32_punpckhdq", IX86_BUILTIN_PUNPCKHDQ, UNKNOWN, (int) V2SI_FTYPE_V2SI_V2SI)
+BDESC (OPTION_MASK_ISA_MMX | OPTION_MASK_ISA_SSE2, 0, CODE_FOR_mmx_punpcklbw, "__builtin_ia32_punpcklbw", IX86_BUILTIN_PUNPCKLBW, UNKNOWN, (int) V8QI_FTYPE_V8QI_V8QI)
+BDESC (OPTION_MASK_ISA_MMX | OPTION_MASK_ISA_SSE2, 0, CODE_FOR_mmx_punpcklwd, "__builtin_ia32_punpcklwd", IX86_BUILTIN_PUNPCKLWD, UNKNOWN, (int) V4HI_FTYPE_V4HI_V4HI)
+BDESC (OPTION_MASK_ISA_MMX | OPTION_MASK_ISA_SSE2, 0, CODE_FOR_mmx_punpckldq, "__builtin_ia32_punpckldq", IX86_BUILTIN_PUNPCKLDQ, UNKNOWN, (int) V2SI_FTYPE_V2SI_V2SI)
+
+BDESC (OPTION_MASK_ISA_MMX | OPTION_MASK_ISA_SSE2, 0, CODE_FOR_mmx_packsswb, "__builtin_ia32_packsswb", IX86_BUILTIN_PACKSSWB, UNKNOWN, (int) V8QI_FTYPE_V4HI_V4HI)
+BDESC (OPTION_MASK_ISA_MMX | OPTION_MASK_ISA_SSE2, 0, CODE_FOR_mmx_packssdw, "__builtin_ia32_packssdw", IX86_BUILTIN_PACKSSDW, UNKNOWN, (int) V4HI_FTYPE_V2SI_V2SI)
+BDESC (OPTION_MASK_ISA_MMX | OPTION_MASK_ISA_SSE2, 0, CODE_FOR_mmx_packuswb, "__builtin_ia32_packuswb", IX86_BUILTIN_PACKUSWB, UNKNOWN, (int) V8QI_FTYPE_V4HI_V4HI)
+
+BDESC (OPTION_MASK_ISA_MMX | OPTION_MASK_ISA_SSE2, 0, CODE_FOR_mmx_pmaddwd, "__builtin_ia32_pmaddwd", IX86_BUILTIN_PMADDWD, UNKNOWN, (int) V2SI_FTYPE_V4HI_V4HI)
+
+BDESC (OPTION_MASK_ISA_MMX | OPTION_MASK_ISA_SSE2, 0, CODE_FOR_mmx_ashlv4hi3, "__builtin_ia32_psllwi", IX86_BUILTIN_PSLLWI, UNKNOWN, (int) V4HI_FTYPE_V4HI_SI_COUNT)
+BDESC (OPTION_MASK_ISA_MMX | OPTION_MASK_ISA_SSE2, 0, CODE_FOR_mmx_ashlv2si3, "__builtin_ia32_pslldi", IX86_BUILTIN_PSLLDI, UNKNOWN, (int) V2SI_FTYPE_V2SI_SI_COUNT)
+BDESC (OPTION_MASK_ISA_MMX | OPTION_MASK_ISA_SSE2, 0, CODE_FOR_mmx_ashlv1di3, "__builtin_ia32_psllqi", IX86_BUILTIN_PSLLQI, UNKNOWN, (int) V1DI_FTYPE_V1DI_SI_COUNT)
+BDESC (OPTION_MASK_ISA_MMX | OPTION_MASK_ISA_SSE2, 0, CODE_FOR_mmx_ashlv4hi3, "__builtin_ia32_psllw", IX86_BUILTIN_PSLLW, UNKNOWN, (int) V4HI_FTYPE_V4HI_V4HI_COUNT)
+BDESC (OPTION_MASK_ISA_MMX | OPTION_MASK_ISA_SSE2, 0, CODE_FOR_mmx_ashlv2si3, "__builtin_ia32_pslld", IX86_BUILTIN_PSLLD, UNKNOWN, (int) V2SI_FTYPE_V2SI_V2SI_COUNT)
+BDESC (OPTION_MASK_ISA_MMX | OPTION_MASK_ISA_SSE2, 0, CODE_FOR_mmx_ashlv1di3, "__builtin_ia32_psllq", IX86_BUILTIN_PSLLQ, UNKNOWN, (int) V1DI_FTYPE_V1DI_V1DI_COUNT)
+
+BDESC (OPTION_MASK_ISA_MMX | OPTION_MASK_ISA_SSE2, 0, CODE_FOR_mmx_lshrv4hi3, "__builtin_ia32_psrlwi", IX86_BUILTIN_PSRLWI, UNKNOWN, (int) V4HI_FTYPE_V4HI_SI_COUNT)
+BDESC (OPTION_MASK_ISA_MMX | OPTION_MASK_ISA_SSE2, 0, CODE_FOR_mmx_lshrv2si3, "__builtin_ia32_psrldi", IX86_BUILTIN_PSRLDI, UNKNOWN, (int) V2SI_FTYPE_V2SI_SI_COUNT)
+BDESC (OPTION_MASK_ISA_MMX | OPTION_MASK_ISA_SSE2, 0, CODE_FOR_mmx_lshrv1di3, "__builtin_ia32_psrlqi", IX86_BUILTIN_PSRLQI, UNKNOWN, (int) V1DI_FTYPE_V1DI_SI_COUNT)
+BDESC (OPTION_MASK_ISA_MMX | OPTION_MASK_ISA_SSE2, 0, CODE_FOR_mmx_lshrv4hi3, "__builtin_ia32_psrlw", IX86_BUILTIN_PSRLW, UNKNOWN, (int) V4HI_FTYPE_V4HI_V4HI_COUNT)
+BDESC (OPTION_MASK_ISA_MMX | OPTION_MASK_ISA_SSE2, 0, CODE_FOR_mmx_lshrv2si3, "__builtin_ia32_psrld", IX86_BUILTIN_PSRLD, UNKNOWN, (int) V2SI_FTYPE_V2SI_V2SI_COUNT)
+BDESC (OPTION_MASK_ISA_MMX | OPTION_MASK_ISA_SSE2, 0, CODE_FOR_mmx_lshrv1di3, "__builtin_ia32_psrlq", IX86_BUILTIN_PSRLQ, UNKNOWN, (int) V1DI_FTYPE_V1DI_V1DI_COUNT)
+
+BDESC (OPTION_MASK_ISA_MMX | OPTION_MASK_ISA_SSE2, 0, CODE_FOR_mmx_ashrv4hi3, "__builtin_ia32_psrawi", IX86_BUILTIN_PSRAWI, UNKNOWN, (int) V4HI_FTYPE_V4HI_SI_COUNT)
+BDESC (OPTION_MASK_ISA_MMX | OPTION_MASK_ISA_SSE2, 0, CODE_FOR_mmx_ashrv2si3, "__builtin_ia32_psradi", IX86_BUILTIN_PSRADI, UNKNOWN, (int) V2SI_FTYPE_V2SI_SI_COUNT)
+BDESC (OPTION_MASK_ISA_MMX | OPTION_MASK_ISA_SSE2, 0, CODE_FOR_mmx_ashrv4hi3, "__builtin_ia32_psraw", IX86_BUILTIN_PSRAW, UNKNOWN, (int) V4HI_FTYPE_V4HI_V4HI_COUNT)
+BDESC (OPTION_MASK_ISA_MMX | OPTION_MASK_ISA_SSE2, 0, CODE_FOR_mmx_ashrv2si3, "__builtin_ia32_psrad", IX86_BUILTIN_PSRAD, UNKNOWN, (int) V2SI_FTYPE_V2SI_V2SI_COUNT)
/* 3DNow! */
BDESC (OPTION_MASK_ISA_3DNOW, 0, CODE_FOR_mmx_pf2id, "__builtin_ia32_pf2id", IX86_BUILTIN_PF2ID, UNKNOWN, (int) V2SI_FTYPE_V2SF)
@@ -818,11 +830,11 @@ BDESC (OPTION_MASK_ISA_SSE3, 0, CODE_FOR_sse3_hsubv2df3, "__builtin_ia32_hsubpd"
/* SSSE3 */
BDESC (OPTION_MASK_ISA_SSSE3, 0, CODE_FOR_absv16qi2, "__builtin_ia32_pabsb128", IX86_BUILTIN_PABSB128, UNKNOWN, (int) V16QI_FTYPE_V16QI)
-BDESC (OPTION_MASK_ISA_SSSE3 | OPTION_MASK_ISA_MMX, 0, CODE_FOR_absv8qi2, "__builtin_ia32_pabsb", IX86_BUILTIN_PABSB, UNKNOWN, (int) V8QI_FTYPE_V8QI)
+BDESC (OPTION_MASK_ISA_SSSE3 | OPTION_MASK_ISA_MMX, 0, CODE_FOR_ssse3_absv8qi2, "__builtin_ia32_pabsb", IX86_BUILTIN_PABSB, UNKNOWN, (int) V8QI_FTYPE_V8QI)
BDESC (OPTION_MASK_ISA_SSSE3, 0, CODE_FOR_absv8hi2, "__builtin_ia32_pabsw128", IX86_BUILTIN_PABSW128, UNKNOWN, (int) V8HI_FTYPE_V8HI)
-BDESC (OPTION_MASK_ISA_SSSE3 | OPTION_MASK_ISA_MMX, 0, CODE_FOR_absv4hi2, "__builtin_ia32_pabsw", IX86_BUILTIN_PABSW, UNKNOWN, (int) V4HI_FTYPE_V4HI)
+BDESC (OPTION_MASK_ISA_SSSE3 | OPTION_MASK_ISA_MMX, 0, CODE_FOR_ssse3_absv4hi2, "__builtin_ia32_pabsw", IX86_BUILTIN_PABSW, UNKNOWN, (int) V4HI_FTYPE_V4HI)
BDESC (OPTION_MASK_ISA_SSSE3, 0, CODE_FOR_absv4si2, "__builtin_ia32_pabsd128", IX86_BUILTIN_PABSD128, UNKNOWN, (int) V4SI_FTYPE_V4SI)
-BDESC (OPTION_MASK_ISA_SSSE3 | OPTION_MASK_ISA_MMX, 0, CODE_FOR_absv2si2, "__builtin_ia32_pabsd", IX86_BUILTIN_PABSD, UNKNOWN, (int) V2SI_FTYPE_V2SI)
+BDESC (OPTION_MASK_ISA_SSSE3 | OPTION_MASK_ISA_MMX, 0, CODE_FOR_ssse3_absv2si2, "__builtin_ia32_pabsd", IX86_BUILTIN_PABSD, UNKNOWN, (int) V2SI_FTYPE_V2SI)
BDESC (OPTION_MASK_ISA_SSSE3, 0, CODE_FOR_ssse3_phaddwv8hi3, "__builtin_ia32_phaddw128", IX86_BUILTIN_PHADDW128, UNKNOWN, (int) V8HI_FTYPE_V8HI_V8HI)
BDESC (OPTION_MASK_ISA_SSSE3 | OPTION_MASK_ISA_MMX, 0, CODE_FOR_ssse3_phaddwv4hi3, "__builtin_ia32_phaddw", IX86_BUILTIN_PHADDW, UNKNOWN, (int) V4HI_FTYPE_V4HI_V4HI)
@@ -2081,10 +2093,10 @@ BDESC (OPTION_MASK_ISA_AVX512VL, 0, CODE_FOR_avx512vl_rorv4si_mask, "__builtin_i
BDESC (OPTION_MASK_ISA_AVX512VL, 0, CODE_FOR_avx512vl_rolv4si_mask, "__builtin_ia32_prold128_mask", IX86_BUILTIN_PROLD128, UNKNOWN, (int) V4SI_FTYPE_V4SI_INT_V4SI_UQI)
BDESC (OPTION_MASK_ISA_AVX512DQ | OPTION_MASK_ISA_AVX512VL, 0, CODE_FOR_avx512dq_fpclassv4df_mask, "__builtin_ia32_fpclasspd256_mask", IX86_BUILTIN_FPCLASSPD256, UNKNOWN, (int) QI_FTYPE_V4DF_INT_UQI)
BDESC (OPTION_MASK_ISA_AVX512DQ | OPTION_MASK_ISA_AVX512VL, 0, CODE_FOR_avx512dq_fpclassv2df_mask, "__builtin_ia32_fpclasspd128_mask", IX86_BUILTIN_FPCLASSPD128, UNKNOWN, (int) QI_FTYPE_V2DF_INT_UQI)
-BDESC (OPTION_MASK_ISA_AVX512DQ, 0, CODE_FOR_avx512dq_vmfpclassv2df, "__builtin_ia32_fpclasssd", IX86_BUILTIN_FPCLASSSD, UNKNOWN, (int) QI_FTYPE_V2DF_INT)
+BDESC (OPTION_MASK_ISA_AVX512DQ, 0, CODE_FOR_avx512dq_vmfpclassv2df_mask, "__builtin_ia32_fpclasssd_mask", IX86_BUILTIN_FPCLASSSD_MASK, UNKNOWN, (int) QI_FTYPE_V2DF_INT_UQI)
BDESC (OPTION_MASK_ISA_AVX512DQ | OPTION_MASK_ISA_AVX512VL, 0, CODE_FOR_avx512dq_fpclassv8sf_mask, "__builtin_ia32_fpclassps256_mask", IX86_BUILTIN_FPCLASSPS256, UNKNOWN, (int) QI_FTYPE_V8SF_INT_UQI)
BDESC (OPTION_MASK_ISA_AVX512DQ | OPTION_MASK_ISA_AVX512VL, 0, CODE_FOR_avx512dq_fpclassv4sf_mask, "__builtin_ia32_fpclassps128_mask", IX86_BUILTIN_FPCLASSPS128, UNKNOWN, (int) QI_FTYPE_V4SF_INT_UQI)
-BDESC (OPTION_MASK_ISA_AVX512DQ, 0, CODE_FOR_avx512dq_vmfpclassv4sf, "__builtin_ia32_fpclassss", IX86_BUILTIN_FPCLASSSS, UNKNOWN, (int) QI_FTYPE_V4SF_INT)
+BDESC (OPTION_MASK_ISA_AVX512DQ, 0, CODE_FOR_avx512dq_vmfpclassv4sf_mask, "__builtin_ia32_fpclassss_mask", IX86_BUILTIN_FPCLASSSS_MASK, UNKNOWN, (int) QI_FTYPE_V4SF_INT_UQI)
BDESC (OPTION_MASK_ISA_AVX512BW | OPTION_MASK_ISA_AVX512VL, 0, CODE_FOR_avx512vl_cvtb2maskv16qi, "__builtin_ia32_cvtb2mask128", IX86_BUILTIN_CVTB2MASK128, UNKNOWN, (int) UHI_FTYPE_V16QI)
BDESC (OPTION_MASK_ISA_AVX512BW | OPTION_MASK_ISA_AVX512VL, 0, CODE_FOR_avx512vl_cvtb2maskv32qi, "__builtin_ia32_cvtb2mask256", IX86_BUILTIN_CVTB2MASK256, UNKNOWN, (int) USI_FTYPE_V32QI)
BDESC (OPTION_MASK_ISA_AVX512BW | OPTION_MASK_ISA_AVX512VL, 0, CODE_FOR_avx512vl_cvtw2maskv8hi, "__builtin_ia32_cvtw2mask128", IX86_BUILTIN_CVTW2MASK128, UNKNOWN, (int) UQI_FTYPE_V8HI)
diff --git a/gcc/config/i386/i386-builtins.c b/gcc/config/i386/i386-builtins.c
index 72bb5d7..9b6a59d 100644
--- a/gcc/config/i386/i386-builtins.c
+++ b/gcc/config/i386/i386-builtins.c
@@ -384,13 +384,13 @@ ix86_add_new_builtins (HOST_WIDE_INT isa, HOST_WIDE_INT isa2)
we're lazy. Add casts to make them fit. */
static const struct builtin_description bdesc_tm[] =
{
- { OPTION_MASK_ISA_MMX, 0, CODE_FOR_nothing, "__builtin__ITM_WM64", (enum ix86_builtins) BUILT_IN_TM_STORE_M64, UNKNOWN, VOID_FTYPE_PV2SI_V2SI },
- { OPTION_MASK_ISA_MMX, 0, CODE_FOR_nothing, "__builtin__ITM_WaRM64", (enum ix86_builtins) BUILT_IN_TM_STORE_WAR_M64, UNKNOWN, VOID_FTYPE_PV2SI_V2SI },
- { OPTION_MASK_ISA_MMX, 0, CODE_FOR_nothing, "__builtin__ITM_WaWM64", (enum ix86_builtins) BUILT_IN_TM_STORE_WAW_M64, UNKNOWN, VOID_FTYPE_PV2SI_V2SI },
- { OPTION_MASK_ISA_MMX, 0, CODE_FOR_nothing, "__builtin__ITM_RM64", (enum ix86_builtins) BUILT_IN_TM_LOAD_M64, UNKNOWN, V2SI_FTYPE_PCV2SI },
- { OPTION_MASK_ISA_MMX, 0, CODE_FOR_nothing, "__builtin__ITM_RaRM64", (enum ix86_builtins) BUILT_IN_TM_LOAD_RAR_M64, UNKNOWN, V2SI_FTYPE_PCV2SI },
- { OPTION_MASK_ISA_MMX, 0, CODE_FOR_nothing, "__builtin__ITM_RaWM64", (enum ix86_builtins) BUILT_IN_TM_LOAD_RAW_M64, UNKNOWN, V2SI_FTYPE_PCV2SI },
- { OPTION_MASK_ISA_MMX, 0, CODE_FOR_nothing, "__builtin__ITM_RfWM64", (enum ix86_builtins) BUILT_IN_TM_LOAD_RFW_M64, UNKNOWN, V2SI_FTYPE_PCV2SI },
+ { OPTION_MASK_ISA_MMX | OPTION_MASK_ISA_SSE2, 0, CODE_FOR_nothing, "__builtin__ITM_WM64", (enum ix86_builtins) BUILT_IN_TM_STORE_M64, UNKNOWN, VOID_FTYPE_PV2SI_V2SI },
+ { OPTION_MASK_ISA_MMX | OPTION_MASK_ISA_SSE2, 0, CODE_FOR_nothing, "__builtin__ITM_WaRM64", (enum ix86_builtins) BUILT_IN_TM_STORE_WAR_M64, UNKNOWN, VOID_FTYPE_PV2SI_V2SI },
+ { OPTION_MASK_ISA_MMX | OPTION_MASK_ISA_SSE2, 0, CODE_FOR_nothing, "__builtin__ITM_WaWM64", (enum ix86_builtins) BUILT_IN_TM_STORE_WAW_M64, UNKNOWN, VOID_FTYPE_PV2SI_V2SI },
+ { OPTION_MASK_ISA_MMX | OPTION_MASK_ISA_SSE2, 0, CODE_FOR_nothing, "__builtin__ITM_RM64", (enum ix86_builtins) BUILT_IN_TM_LOAD_M64, UNKNOWN, V2SI_FTYPE_PCV2SI },
+ { OPTION_MASK_ISA_MMX | OPTION_MASK_ISA_SSE2, 0, CODE_FOR_nothing, "__builtin__ITM_RaRM64", (enum ix86_builtins) BUILT_IN_TM_LOAD_RAR_M64, UNKNOWN, V2SI_FTYPE_PCV2SI },
+ { OPTION_MASK_ISA_MMX | OPTION_MASK_ISA_SSE2, 0, CODE_FOR_nothing, "__builtin__ITM_RaWM64", (enum ix86_builtins) BUILT_IN_TM_LOAD_RAW_M64, UNKNOWN, V2SI_FTYPE_PCV2SI },
+ { OPTION_MASK_ISA_MMX | OPTION_MASK_ISA_SSE2, 0, CODE_FOR_nothing, "__builtin__ITM_RfWM64", (enum ix86_builtins) BUILT_IN_TM_LOAD_RFW_M64, UNKNOWN, V2SI_FTYPE_PCV2SI },
{ OPTION_MASK_ISA_SSE, 0, CODE_FOR_nothing, "__builtin__ITM_WM128", (enum ix86_builtins) BUILT_IN_TM_STORE_M128, UNKNOWN, VOID_FTYPE_PV4SF_V4SF },
{ OPTION_MASK_ISA_SSE, 0, CODE_FOR_nothing, "__builtin__ITM_WaRM128", (enum ix86_builtins) BUILT_IN_TM_STORE_WAR_M128, UNKNOWN, VOID_FTYPE_PV4SF_V4SF },
@@ -408,7 +408,7 @@ static const struct builtin_description bdesc_tm[] =
{ OPTION_MASK_ISA_AVX, 0, CODE_FOR_nothing, "__builtin__ITM_RaWM256", (enum ix86_builtins) BUILT_IN_TM_LOAD_RAW_M256, UNKNOWN, V8SF_FTYPE_PCV8SF },
{ OPTION_MASK_ISA_AVX, 0, CODE_FOR_nothing, "__builtin__ITM_RfWM256", (enum ix86_builtins) BUILT_IN_TM_LOAD_RFW_M256, UNKNOWN, V8SF_FTYPE_PCV8SF },
- { OPTION_MASK_ISA_MMX, 0, CODE_FOR_nothing, "__builtin__ITM_LM64", (enum ix86_builtins) BUILT_IN_TM_LOG_M64, UNKNOWN, VOID_FTYPE_PCVOID },
+ { OPTION_MASK_ISA_MMX | OPTION_MASK_ISA_SSE2, 0, CODE_FOR_nothing, "__builtin__ITM_LM64", (enum ix86_builtins) BUILT_IN_TM_LOG_M64, UNKNOWN, VOID_FTYPE_PCVOID },
{ OPTION_MASK_ISA_SSE, 0, CODE_FOR_nothing, "__builtin__ITM_LM128", (enum ix86_builtins) BUILT_IN_TM_LOG_M128, UNKNOWN, VOID_FTYPE_PCVOID },
{ OPTION_MASK_ISA_AVX, 0, CODE_FOR_nothing, "__builtin__ITM_LM256", (enum ix86_builtins) BUILT_IN_TM_LOG_M256, UNKNOWN, VOID_FTYPE_PCVOID },
};
@@ -1058,14 +1058,17 @@ ix86_init_mmx_sse_builtins (void)
VOID_FTYPE_UNSIGNED, IX86_BUILTIN_XABORT);
/* MMX access to the vec_init patterns. */
- def_builtin_const (OPTION_MASK_ISA_MMX, 0, "__builtin_ia32_vec_init_v2si",
+ def_builtin_const (OPTION_MASK_ISA_MMX | OPTION_MASK_ISA_SSE2, 0,
+ "__builtin_ia32_vec_init_v2si",
V2SI_FTYPE_INT_INT, IX86_BUILTIN_VEC_INIT_V2SI);
- def_builtin_const (OPTION_MASK_ISA_MMX, 0, "__builtin_ia32_vec_init_v4hi",
+ def_builtin_const (OPTION_MASK_ISA_MMX | OPTION_MASK_ISA_SSE2, 0,
+ "__builtin_ia32_vec_init_v4hi",
V4HI_FTYPE_HI_HI_HI_HI,
IX86_BUILTIN_VEC_INIT_V4HI);
- def_builtin_const (OPTION_MASK_ISA_MMX, 0, "__builtin_ia32_vec_init_v8qi",
+ def_builtin_const (OPTION_MASK_ISA_MMX | OPTION_MASK_ISA_SSE2, 0,
+ "__builtin_ia32_vec_init_v8qi",
V8QI_FTYPE_QI_QI_QI_QI_QI_QI_QI_QI,
IX86_BUILTIN_VEC_INIT_V8QI);
@@ -1087,7 +1090,8 @@ ix86_init_mmx_sse_builtins (void)
"__builtin_ia32_vec_ext_v4hi",
HI_FTYPE_V4HI_INT, IX86_BUILTIN_VEC_EXT_V4HI);
- def_builtin_const (OPTION_MASK_ISA_MMX, 0, "__builtin_ia32_vec_ext_v2si",
+ def_builtin_const (OPTION_MASK_ISA_MMX | OPTION_MASK_ISA_SSE2, 0,
+ "__builtin_ia32_vec_ext_v2si",
SI_FTYPE_V2SI_INT, IX86_BUILTIN_VEC_EXT_V2SI);
def_builtin_const (OPTION_MASK_ISA_SSE2, 0, "__builtin_ia32_vec_ext_v16qi",
@@ -1920,6 +1924,7 @@ enum processor_features
F_VPCLMULQDQ,
F_AVX512VNNI,
F_AVX512BITALG,
+ F_AVX512VP2INTERSECT,
F_AVX512BF16,
F_MAX
};
@@ -2066,6 +2071,7 @@ static const _isa_names_table isa_names_table[] =
{"vpclmulqdq", F_VPCLMULQDQ, P_ZERO},
{"avx512vnni", F_AVX512VNNI, P_ZERO},
{"avx512bitalg", F_AVX512BITALG, P_ZERO},
+ {"avx512vp2intersect",F_AVX512VP2INTERSECT, P_ZERO},
{"avx512bf16", F_AVX512BF16, P_ZERO}
};
diff --git a/gcc/config/i386/i386-c.c b/gcc/config/i386/i386-c.c
index 92bf066..ec5f15b 100644
--- a/gcc/config/i386/i386-c.c
+++ b/gcc/config/i386/i386-c.c
@@ -404,6 +404,8 @@ ix86_target_macros_internal (HOST_WIDE_INT isa_flag,
if (isa_flag2 & OPTION_MASK_ISA_WBNOINVD)
def_or_undef (parse_in, "__WBNOINVD__");
+ if (isa_flag2 & OPTION_MASK_ISA_AVX512VP2INTERSECT)
+ def_or_undef (parse_in, "__AVX512VP2INTERSECT__");
if (isa_flag & OPTION_MASK_ISA_MMX)
def_or_undef (parse_in, "__MMX__");
if (isa_flag & OPTION_MASK_ISA_3DNOW)
@@ -550,6 +552,10 @@ ix86_target_macros_internal (HOST_WIDE_INT isa_flag,
def_or_undef (parse_in, "__PTWRITE__");
if (isa_flag2 & OPTION_MASK_ISA_AVX512BF16)
def_or_undef (parse_in, "__AVX512BF16__");
+ if (TARGET_MMX_WITH_SSE)
+ def_or_undef (parse_in, "__MMX_WITH_SSE__");
+ if (isa_flag2 & OPTION_MASK_ISA_ENQCMD)
+ def_or_undef (parse_in, "__ENQCMD__");
if (TARGET_IAMCU)
{
def_or_undef (parse_in, "__iamcu");
diff --git a/gcc/config/i386/i386-expand.c b/gcc/config/i386/i386-expand.c
index b7ce5d0..5d3b74a 100644
--- a/gcc/config/i386/i386-expand.c
+++ b/gcc/config/i386/i386-expand.c
@@ -662,6 +662,137 @@ ix86_expand_vector_move_misalign (machine_mode mode, rtx operands[])
gcc_unreachable ();
}
+/* Move bits 64:95 to bits 32:63. */
+
+void
+ix86_move_vector_high_sse_to_mmx (rtx op)
+{
+ rtx mask = gen_rtx_PARALLEL (VOIDmode,
+ gen_rtvec (4, GEN_INT (0), GEN_INT (2),
+ GEN_INT (0), GEN_INT (0)));
+ rtx dest = lowpart_subreg (V4SImode, op, GET_MODE (op));
+ op = gen_rtx_VEC_SELECT (V4SImode, dest, mask);
+ rtx insn = gen_rtx_SET (dest, op);
+ emit_insn (insn);
+}
+
+/* Split MMX pack with signed/unsigned saturation with SSE/SSE2. */
+
+void
+ix86_split_mmx_pack (rtx operands[], enum rtx_code code)
+{
+ rtx op0 = operands[0];
+ rtx op1 = operands[1];
+ rtx op2 = operands[2];
+
+ machine_mode dmode = GET_MODE (op0);
+ machine_mode smode = GET_MODE (op1);
+ machine_mode inner_dmode = GET_MODE_INNER (dmode);
+ machine_mode inner_smode = GET_MODE_INNER (smode);
+
+ /* Get the corresponding SSE mode for destination. */
+ int nunits = 16 / GET_MODE_SIZE (inner_dmode);
+ machine_mode sse_dmode = mode_for_vector (GET_MODE_INNER (dmode),
+ nunits).require ();
+ machine_mode sse_half_dmode = mode_for_vector (GET_MODE_INNER (dmode),
+ nunits / 2).require ();
+
+ /* Get the corresponding SSE mode for source. */
+ nunits = 16 / GET_MODE_SIZE (inner_smode);
+ machine_mode sse_smode = mode_for_vector (GET_MODE_INNER (smode),
+ nunits).require ();
+
+ /* Generate SSE pack with signed/unsigned saturation. */
+ rtx dest = lowpart_subreg (sse_dmode, op0, GET_MODE (op0));
+ op1 = lowpart_subreg (sse_smode, op1, GET_MODE (op1));
+ op2 = lowpart_subreg (sse_smode, op2, GET_MODE (op2));
+
+ op1 = gen_rtx_fmt_e (code, sse_half_dmode, op1);
+ op2 = gen_rtx_fmt_e (code, sse_half_dmode, op2);
+ rtx insn = gen_rtx_SET (dest, gen_rtx_VEC_CONCAT (sse_dmode,
+ op1, op2));
+ emit_insn (insn);
+
+ ix86_move_vector_high_sse_to_mmx (op0);
+}
+
+/* Split MMX punpcklXX/punpckhXX with SSE punpcklXX. */
+
+void
+ix86_split_mmx_punpck (rtx operands[], bool high_p)
+{
+ rtx op0 = operands[0];
+ rtx op1 = operands[1];
+ rtx op2 = operands[2];
+ machine_mode mode = GET_MODE (op0);
+ rtx mask;
+ /* The corresponding SSE mode. */
+ machine_mode sse_mode, double_sse_mode;
+
+ switch (mode)
+ {
+ case E_V8QImode:
+ sse_mode = V16QImode;
+ double_sse_mode = V32QImode;
+ mask = gen_rtx_PARALLEL (VOIDmode,
+ gen_rtvec (16,
+ GEN_INT (0), GEN_INT (16),
+ GEN_INT (1), GEN_INT (17),
+ GEN_INT (2), GEN_INT (18),
+ GEN_INT (3), GEN_INT (19),
+ GEN_INT (4), GEN_INT (20),
+ GEN_INT (5), GEN_INT (21),
+ GEN_INT (6), GEN_INT (22),
+ GEN_INT (7), GEN_INT (23)));
+ break;
+
+ case E_V4HImode:
+ sse_mode = V8HImode;
+ double_sse_mode = V16HImode;
+ mask = gen_rtx_PARALLEL (VOIDmode,
+ gen_rtvec (8,
+ GEN_INT (0), GEN_INT (8),
+ GEN_INT (1), GEN_INT (9),
+ GEN_INT (2), GEN_INT (10),
+ GEN_INT (3), GEN_INT (11)));
+ break;
+
+ case E_V2SImode:
+ sse_mode = V4SImode;
+ double_sse_mode = V8SImode;
+ mask = gen_rtx_PARALLEL (VOIDmode,
+ gen_rtvec (4,
+ GEN_INT (0), GEN_INT (4),
+ GEN_INT (1), GEN_INT (5)));
+ break;
+
+ default:
+ gcc_unreachable ();
+ }
+
+ /* Generate SSE punpcklXX. */
+ rtx dest = lowpart_subreg (sse_mode, op0, GET_MODE (op0));
+ op1 = lowpart_subreg (sse_mode, op1, GET_MODE (op1));
+ op2 = lowpart_subreg (sse_mode, op2, GET_MODE (op2));
+
+ op1 = gen_rtx_VEC_CONCAT (double_sse_mode, op1, op2);
+ op2 = gen_rtx_VEC_SELECT (sse_mode, op1, mask);
+ rtx insn = gen_rtx_SET (dest, op2);
+ emit_insn (insn);
+
+ if (high_p)
+ {
+ /* Move bits 64:127 to bits 0:63. */
+ mask = gen_rtx_PARALLEL (VOIDmode,
+ gen_rtvec (4, GEN_INT (2), GEN_INT (3),
+ GEN_INT (0), GEN_INT (0)));
+ dest = lowpart_subreg (V4SImode, dest, GET_MODE (dest));
+ op1 = gen_rtx_VEC_SELECT (V4SImode, dest, mask);
+ insn = gen_rtx_SET (dest, op1);
+ emit_insn (insn);
+ }
+}
+
/* Helper function of ix86_fixup_binary_operands to canonicalize
operand order. Returns true if the operands should be swapped. */
@@ -984,7 +1115,7 @@ predict_jump (int prob)
void
ix86_split_idivmod (machine_mode mode, rtx operands[],
- bool signed_p)
+ bool unsigned_p)
{
rtx_code_label *end_label, *qimode_label;
rtx div, mod;
@@ -1000,22 +1131,22 @@ ix86_split_idivmod (machine_mode mode, rtx operands[],
if (GET_MODE (operands[0]) == SImode)
{
if (GET_MODE (operands[1]) == SImode)
- gen_divmod4_1 = signed_p ? gen_divmodsi4_1 : gen_udivmodsi4_1;
+ gen_divmod4_1 = unsigned_p ? gen_udivmodsi4_1 : gen_divmodsi4_1;
else
gen_divmod4_1
- = signed_p ? gen_divmodsi4_zext_2 : gen_udivmodsi4_zext_2;
+ = unsigned_p ? gen_udivmodsi4_zext_2 : gen_divmodsi4_zext_2;
gen_zero_extend = gen_zero_extendqisi2;
}
else
{
gen_divmod4_1
- = signed_p ? gen_divmodsi4_zext_1 : gen_udivmodsi4_zext_1;
+ = unsigned_p ? gen_udivmodsi4_zext_1 : gen_divmodsi4_zext_1;
gen_zero_extend = gen_zero_extendqidi2;
}
gen_test_ccno_1 = gen_testsi_ccno_1;
break;
case E_DImode:
- gen_divmod4_1 = signed_p ? gen_divmoddi4_1 : gen_udivmoddi4_1;
+ gen_divmod4_1 = unsigned_p ? gen_udivmoddi4_1 : gen_divmoddi4_1;
gen_test_ccno_1 = gen_testdi_ccno_1;
gen_zero_extend = gen_zero_extendqidi2;
break;
@@ -1061,15 +1192,15 @@ ix86_split_idivmod (machine_mode mode, rtx operands[],
tmp2 = lowpart_subreg (QImode, operands[3], mode);
emit_insn (gen_udivmodhiqi3 (tmp0, tmp1, tmp2));
- if (signed_p)
+ if (unsigned_p)
{
- div = gen_rtx_DIV (mode, operands[2], operands[3]);
- mod = gen_rtx_MOD (mode, operands[2], operands[3]);
+ div = gen_rtx_UDIV (mode, operands[2], operands[3]);
+ mod = gen_rtx_UMOD (mode, operands[2], operands[3]);
}
else
{
- div = gen_rtx_UDIV (mode, operands[2], operands[3]);
- mod = gen_rtx_UMOD (mode, operands[2], operands[3]);
+ div = gen_rtx_DIV (mode, operands[2], operands[3]);
+ mod = gen_rtx_MOD (mode, operands[2], operands[3]);
}
if (mode == SImode)
{
@@ -1573,10 +1704,11 @@ void
ix86_expand_fp_absneg_operator (enum rtx_code code, machine_mode mode,
rtx operands[])
{
- rtx mask, set, dst, src;
+ rtx set, dst, src;
bool use_sse = false;
bool vector_mode = VECTOR_MODE_P (mode);
machine_mode vmode = mode;
+ rtvec par;
if (vector_mode)
use_sse = true;
@@ -1591,24 +1723,19 @@ ix86_expand_fp_absneg_operator (enum rtx_code code, machine_mode mode,
vmode = V2DFmode;
}
- /* NEG and ABS performed with SSE use bitwise mask operations.
- Create the appropriate mask now. */
- if (use_sse)
- mask = ix86_build_signbit_mask (vmode, vector_mode, code == ABS);
- else
- mask = NULL_RTX;
-
dst = operands[0];
src = operands[1];
set = gen_rtx_fmt_e (code, mode, src);
set = gen_rtx_SET (dst, set);
- if (mask)
+ if (use_sse)
{
- rtx use, clob;
- rtvec par;
+ rtx mask, use, clob;
+ /* NEG and ABS performed with SSE use bitwise mask operations.
+ Create the appropriate mask now. */
+ mask = ix86_build_signbit_mask (vmode, vector_mode, code == ABS);
use = gen_rtx_USE (VOIDmode, mask);
if (vector_mode)
par = gen_rtvec (2, set, use);
@@ -1617,10 +1744,104 @@ ix86_expand_fp_absneg_operator (enum rtx_code code, machine_mode mode,
clob = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (CCmode, FLAGS_REG));
par = gen_rtvec (3, set, use, clob);
}
- emit_insn (gen_rtx_PARALLEL (VOIDmode, par));
}
else
- emit_insn (set);
+ {
+ rtx clob;
+
+ /* Changing of sign for FP values is doable using integer unit too. */
+ clob = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (CCmode, FLAGS_REG));
+ par = gen_rtvec (2, set, clob);
+ }
+
+ emit_insn (gen_rtx_PARALLEL (VOIDmode, par));
+}
+
+/* Deconstruct a floating point ABS or NEG operation
+ with integer registers into integer operations. */
+
+void
+ix86_split_fp_absneg_operator (enum rtx_code code, machine_mode mode,
+ rtx operands[])
+{
+ enum rtx_code absneg_op;
+ rtx dst, set;
+
+ gcc_assert (operands_match_p (operands[0], operands[1]));
+
+ switch (mode)
+ {
+ case E_SFmode:
+ dst = gen_lowpart (SImode, operands[0]);
+
+ if (code == ABS)
+ {
+ set = gen_int_mode (0x7fffffff, SImode);
+ absneg_op = AND;
+ }
+ else
+ {
+ set = gen_int_mode (0x80000000, SImode);
+ absneg_op = XOR;
+ }
+ set = gen_rtx_fmt_ee (absneg_op, SImode, dst, set);
+ break;
+
+ case E_DFmode:
+ if (TARGET_64BIT)
+ {
+ dst = gen_lowpart (DImode, operands[0]);
+ dst = gen_rtx_ZERO_EXTRACT (DImode, dst, const1_rtx, GEN_INT (63));
+
+ if (code == ABS)
+ set = const0_rtx;
+ else
+ set = gen_rtx_NOT (DImode, dst);
+ }
+ else
+ {
+ dst = gen_highpart (SImode, operands[0]);
+
+ if (code == ABS)
+ {
+ set = gen_int_mode (0x7fffffff, SImode);
+ absneg_op = AND;
+ }
+ else
+ {
+ set = gen_int_mode (0x80000000, SImode);
+ absneg_op = XOR;
+ }
+ set = gen_rtx_fmt_ee (absneg_op, SImode, dst, set);
+ }
+ break;
+
+ case E_XFmode:
+ dst = gen_rtx_REG (SImode,
+ REGNO (operands[0]) + (TARGET_64BIT ? 1 : 2));
+ if (code == ABS)
+ {
+ set = GEN_INT (0x7fff);
+ absneg_op = AND;
+ }
+ else
+ {
+ set = GEN_INT (0x8000);
+ absneg_op = XOR;
+ }
+ set = gen_rtx_fmt_ee (absneg_op, SImode, dst, set);
+ break;
+
+ default:
+ gcc_unreachable ();
+ }
+
+ set = gen_rtx_SET (dst, set);
+
+ rtx clob = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (CCmode, FLAGS_REG));
+ rtvec par = gen_rtvec (2, set, clob);
+
+ emit_insn (gen_rtx_PARALLEL (VOIDmode, par));
}
/* Expand a copysign operation. Special case operand 0 being a constant. */
@@ -1629,7 +1850,7 @@ void
ix86_expand_copysign (rtx operands[])
{
machine_mode mode, vmode;
- rtx dest, op0, op1, mask, nmask;
+ rtx dest, op0, op1, mask;
dest = operands[0];
op0 = operands[1];
@@ -1641,13 +1862,15 @@ ix86_expand_copysign (rtx operands[])
vmode = V4SFmode;
else if (mode == DFmode)
vmode = V2DFmode;
- else
+ else if (mode == TFmode)
vmode = mode;
+ else
+ gcc_unreachable ();
+
+ mask = ix86_build_signbit_mask (vmode, 0, 0);
if (CONST_DOUBLE_P (op0))
{
- rtx (*copysign_insn)(rtx, rtx, rtx, rtx);
-
if (real_isneg (CONST_DOUBLE_REAL_VALUE (op0)))
op0 = simplify_unary_operation (ABS, mode, op0, mode);
@@ -1665,32 +1888,14 @@ ix86_expand_copysign (rtx operands[])
else if (op0 != CONST0_RTX (mode))
op0 = force_reg (mode, op0);
- mask = ix86_build_signbit_mask (vmode, 0, 0);
-
- if (mode == SFmode)
- copysign_insn = gen_copysignsf3_const;
- else if (mode == DFmode)
- copysign_insn = gen_copysigndf3_const;
- else
- copysign_insn = gen_copysigntf3_const;
-
- emit_insn (copysign_insn (dest, op0, op1, mask));
+ emit_insn (gen_copysign3_const (mode, dest, op0, op1, mask));
}
else
{
- rtx (*copysign_insn)(rtx, rtx, rtx, rtx, rtx, rtx);
-
- nmask = ix86_build_signbit_mask (vmode, 0, 1);
- mask = ix86_build_signbit_mask (vmode, 0, 0);
+ rtx nmask = ix86_build_signbit_mask (vmode, 0, 1);
- if (mode == SFmode)
- copysign_insn = gen_copysignsf3_var;
- else if (mode == DFmode)
- copysign_insn = gen_copysigndf3_var;
- else
- copysign_insn = gen_copysigntf3_var;
-
- emit_insn (copysign_insn (dest, NULL_RTX, op0, op1, nmask, mask));
+ emit_insn (gen_copysign3_var
+ (mode, dest, NULL_RTX, op0, op1, nmask, mask));
}
}
@@ -1799,7 +2004,6 @@ ix86_split_copysign_var (rtx operands[])
void
ix86_expand_xorsign (rtx operands[])
{
- rtx (*xorsign_insn)(rtx, rtx, rtx, rtx);
machine_mode mode, vmode;
rtx dest, op0, op1, mask;
@@ -1810,21 +2014,15 @@ ix86_expand_xorsign (rtx operands[])
mode = GET_MODE (dest);
if (mode == SFmode)
- {
- xorsign_insn = gen_xorsignsf3_1;
- vmode = V4SFmode;
- }
+ vmode = V4SFmode;
else if (mode == DFmode)
- {
- xorsign_insn = gen_xorsigndf3_1;
- vmode = V2DFmode;
- }
+ vmode = V2DFmode;
else
gcc_unreachable ();
mask = ix86_build_signbit_mask (vmode, 0, 0);
- emit_insn (xorsign_insn (dest, op0, op1, mask));
+ emit_insn (gen_xorsign3_1 (mode, dest, op0, op1, mask));
}
/* Deconstruct an xorsign operation into bit masks. */
@@ -2003,22 +2201,9 @@ ix86_expand_branch (enum rtx_code code, rtx op0, rtx op1, rtx label)
case LT: case LTU: case GE: case GEU:
{
- rtx (*cmp_insn) (rtx, rtx);
- rtx (*sbb_insn) (rtx, rtx, rtx);
bool uns = (code == LTU || code == GEU);
-
- if (TARGET_64BIT)
- {
- cmp_insn = gen_cmpdi_1;
- sbb_insn
- = uns ? gen_subdi3_carry_ccc : gen_subdi3_carry_ccgz;
- }
- else
- {
- cmp_insn = gen_cmpsi_1;
- sbb_insn
- = uns ? gen_subsi3_carry_ccc : gen_subsi3_carry_ccgz;
- }
+ rtx (*sbb_insn) (machine_mode, rtx, rtx, rtx)
+ = uns ? gen_sub3_carry_ccc : gen_sub3_carry_ccgz;
if (!nonimmediate_operand (lo[0], submode))
lo[0] = force_reg (submode, lo[0]);
@@ -2031,11 +2216,12 @@ ix86_expand_branch (enum rtx_code code, rtx op0, rtx op1, rtx label)
|| (!uns && !x86_64_general_operand (hi[1], submode)))
hi[1] = force_reg (submode, hi[1]);
- emit_insn (cmp_insn (lo[0], lo[1]));
- emit_insn (sbb_insn (gen_rtx_SCRATCH (submode), hi[0], hi[1]));
+ emit_insn (gen_cmp_1 (submode, lo[0], lo[1]));
- tmp = gen_rtx_REG (uns ? CCCmode : CCGZmode, FLAGS_REG);
+ tmp = gen_rtx_SCRATCH (submode);
+ emit_insn (sbb_insn (submode, tmp, hi[0], hi[1]));
+ tmp = gen_rtx_REG (uns ? CCCmode : CCGZmode, FLAGS_REG);
ix86_expand_branch (code, tmp, const0_rtx, label);
return;
}
@@ -2627,7 +2813,7 @@ ix86_expand_int_addcc (rtx operands[])
{
enum rtx_code code = GET_CODE (operands[1]);
rtx flags;
- rtx (*insn)(rtx, rtx, rtx, rtx, rtx);
+ rtx (*insn) (machine_mode, rtx, rtx, rtx, rtx, rtx);
rtx compare_op;
rtx val = const0_rtx;
bool fpcmp = false;
@@ -2665,46 +2851,11 @@ ix86_expand_int_addcc (rtx operands[])
/* Construct either adc or sbb insn. */
if ((code == LTU) == (operands[3] == constm1_rtx))
- {
- switch (mode)
- {
- case E_QImode:
- insn = gen_subqi3_carry;
- break;
- case E_HImode:
- insn = gen_subhi3_carry;
- break;
- case E_SImode:
- insn = gen_subsi3_carry;
- break;
- case E_DImode:
- insn = gen_subdi3_carry;
- break;
- default:
- gcc_unreachable ();
- }
- }
+ insn = gen_sub3_carry;
else
- {
- switch (mode)
- {
- case E_QImode:
- insn = gen_addqi3_carry;
- break;
- case E_HImode:
- insn = gen_addhi3_carry;
- break;
- case E_SImode:
- insn = gen_addsi3_carry;
- break;
- case E_DImode:
- insn = gen_adddi3_carry;
- break;
- default:
- gcc_unreachable ();
- }
- }
- emit_insn (insn (operands[0], operands[2], val, flags, compare_op));
+ insn = gen_add3_carry;
+
+ emit_insn (insn (mode, operands[0], operands[2], val, flags, compare_op));
return true;
}
@@ -4082,27 +4233,15 @@ ix86_expand_int_sse_cmp (rtx dest, enum rtx_code code, rtx cop0, rtx cop1,
case E_V2DImode:
{
rtx t1, t2, mask;
- rtx (*gen_sub3) (rtx, rtx, rtx);
- switch (mode)
- {
- case E_V16SImode: gen_sub3 = gen_subv16si3; break;
- case E_V8DImode: gen_sub3 = gen_subv8di3; break;
- case E_V8SImode: gen_sub3 = gen_subv8si3; break;
- case E_V4DImode: gen_sub3 = gen_subv4di3; break;
- case E_V4SImode: gen_sub3 = gen_subv4si3; break;
- case E_V2DImode: gen_sub3 = gen_subv2di3; break;
- default:
- gcc_unreachable ();
- }
/* Subtract (-(INT MAX) - 1) from both operands to make
them signed. */
mask = ix86_build_signbit_mask (mode, true, false);
t1 = gen_reg_rtx (mode);
- emit_insn (gen_sub3 (t1, cop0, mask));
+ emit_insn (gen_sub3_insn (t1, cop0, mask));
t2 = gen_reg_rtx (mode);
- emit_insn (gen_sub3 (t2, cop1, mask));
+ emit_insn (gen_sub3_insn (t2, cop1, mask));
cop0 = t1;
cop1 = t2;
@@ -4118,9 +4257,8 @@ ix86_expand_int_sse_cmp (rtx dest, enum rtx_code code, rtx cop0, rtx cop1,
case E_V8HImode:
/* Perform a parallel unsigned saturating subtraction. */
x = gen_reg_rtx (mode);
- emit_insn (gen_rtx_SET (x, gen_rtx_US_MINUS (mode, cop0,
- cop1)));
-
+ emit_insn (gen_rtx_SET
+ (x, gen_rtx_US_MINUS (mode, cop0, cop1)));
cop0 = x;
cop1 = CONST0_RTX (mode);
code = EQ;
@@ -5249,8 +5387,7 @@ ix86_split_long_move (rtx operands[])
if (nparts == 3)
{
if (TARGET_128BIT_LONG_DOUBLE && mode == XFmode)
- emit_insn (ix86_gen_add3 (stack_pointer_rtx,
- stack_pointer_rtx, GEN_INT (-4)));
+ emit_insn (gen_add2_insn (stack_pointer_rtx, GEN_INT (-4)));
emit_move_insn (part[0][2], part[1][2]);
}
else if (nparts == 4)
@@ -5342,18 +5479,17 @@ ix86_split_long_move (rtx operands[])
static void
ix86_expand_ashl_const (rtx operand, int count, machine_mode mode)
{
- rtx (*insn)(rtx, rtx, rtx);
-
if (count == 1
|| (count * ix86_cost->add <= ix86_cost->shift_const
&& !optimize_insn_for_size_p ()))
{
- insn = mode == DImode ? gen_addsi3 : gen_adddi3;
while (count-- > 0)
- emit_insn (insn (operand, operand, operand));
+ emit_insn (gen_add2_insn (operand, operand));
}
else
{
+ rtx (*insn)(rtx, rtx, rtx);
+
insn = mode == DImode ? gen_ashlsi3 : gen_ashldi3;
emit_insn (insn (operand, operand, GEN_INT (count)));
}
@@ -5365,6 +5501,7 @@ ix86_split_ashl (rtx *operands, rtx scratch, machine_mode mode)
rtx (*gen_ashl3)(rtx, rtx, rtx);
rtx (*gen_shld)(rtx, rtx, rtx);
int half_width = GET_MODE_BITSIZE (mode) >> 1;
+ machine_mode half_mode;
rtx low[2], high[2];
int count;
@@ -5396,6 +5533,7 @@ ix86_split_ashl (rtx *operands, rtx scratch, machine_mode mode)
}
split_double_mode (mode, operands, 1, low, high);
+ half_mode = mode == DImode ? SImode : DImode;
gen_ashl3 = mode == DImode ? gen_ashlsi3 : gen_ashldi3;
@@ -5429,7 +5567,6 @@ ix86_split_ashl (rtx *operands, rtx scratch, machine_mode mode)
pentium4 a bit; no one else seems to care much either way. */
else
{
- machine_mode half_mode;
rtx (*gen_lshr3)(rtx, rtx, rtx);
rtx (*gen_and3)(rtx, rtx, rtx);
rtx (*gen_xor3)(rtx, rtx, rtx);
@@ -5438,7 +5575,6 @@ ix86_split_ashl (rtx *operands, rtx scratch, machine_mode mode)
if (mode == DImode)
{
- half_mode = SImode;
gen_lshr3 = gen_lshrsi3;
gen_and3 = gen_andsi3;
gen_xor3 = gen_xorsi3;
@@ -5446,7 +5582,6 @@ ix86_split_ashl (rtx *operands, rtx scratch, machine_mode mode)
}
else
{
- half_mode = DImode;
gen_lshr3 = gen_lshrdi3;
gen_and3 = gen_anddi3;
gen_xor3 = gen_xordi3;
@@ -5495,19 +5630,12 @@ ix86_split_ashl (rtx *operands, rtx scratch, machine_mode mode)
if (TARGET_CMOVE && scratch)
{
- rtx (*gen_x86_shift_adj_1)(rtx, rtx, rtx, rtx)
- = mode == DImode ? gen_x86_shiftsi_adj_1 : gen_x86_shiftdi_adj_1;
-
ix86_expand_clear (scratch);
- emit_insn (gen_x86_shift_adj_1 (high[0], low[0], operands[2], scratch));
+ emit_insn (gen_x86_shift_adj_1
+ (half_mode, high[0], low[0], operands[2], scratch));
}
else
- {
- rtx (*gen_x86_shift_adj_2)(rtx, rtx, rtx)
- = mode == DImode ? gen_x86_shiftsi_adj_2 : gen_x86_shiftdi_adj_2;
-
- emit_insn (gen_x86_shift_adj_2 (high[0], low[0], operands[2]));
- }
+ emit_insn (gen_x86_shift_adj_2 (half_mode, high[0], low[0], operands[2]));
}
void
@@ -5558,34 +5686,30 @@ ix86_split_ashr (rtx *operands, rtx scratch, machine_mode mode)
}
else
{
+ machine_mode half_mode;
+
gen_shrd = mode == DImode ? gen_x86_shrd : gen_x86_64_shrd;
if (!rtx_equal_p (operands[0], operands[1]))
emit_move_insn (operands[0], operands[1]);
split_double_mode (mode, operands, 1, low, high);
+ half_mode = mode == DImode ? SImode : DImode;
emit_insn (gen_shrd (low[0], high[0], operands[2]));
emit_insn (gen_ashr3 (high[0], high[0], operands[2]));
if (TARGET_CMOVE && scratch)
{
- rtx (*gen_x86_shift_adj_1)(rtx, rtx, rtx, rtx)
- = mode == DImode ? gen_x86_shiftsi_adj_1 : gen_x86_shiftdi_adj_1;
-
emit_move_insn (scratch, high[0]);
emit_insn (gen_ashr3 (scratch, scratch,
GEN_INT (half_width - 1)));
- emit_insn (gen_x86_shift_adj_1 (low[0], high[0], operands[2],
- scratch));
+ emit_insn (gen_x86_shift_adj_1
+ (half_mode, low[0], high[0], operands[2], scratch));
}
else
- {
- rtx (*gen_x86_shift_adj_3)(rtx, rtx, rtx)
- = mode == DImode ? gen_x86_shiftsi_adj_3 : gen_x86_shiftdi_adj_3;
-
- emit_insn (gen_x86_shift_adj_3 (low[0], high[0], operands[2]));
- }
+ emit_insn (gen_x86_shift_adj_3
+ (half_mode, low[0], high[0], operands[2]));
}
}
@@ -5627,32 +5751,28 @@ ix86_split_lshr (rtx *operands, rtx scratch, machine_mode mode)
}
else
{
+ machine_mode half_mode;
+
gen_shrd = mode == DImode ? gen_x86_shrd : gen_x86_64_shrd;
if (!rtx_equal_p (operands[0], operands[1]))
emit_move_insn (operands[0], operands[1]);
split_double_mode (mode, operands, 1, low, high);
+ half_mode = mode == DImode ? SImode : DImode;
emit_insn (gen_shrd (low[0], high[0], operands[2]));
emit_insn (gen_lshr3 (high[0], high[0], operands[2]));
if (TARGET_CMOVE && scratch)
{
- rtx (*gen_x86_shift_adj_1)(rtx, rtx, rtx, rtx)
- = mode == DImode ? gen_x86_shiftsi_adj_1 : gen_x86_shiftdi_adj_1;
-
ix86_expand_clear (scratch);
- emit_insn (gen_x86_shift_adj_1 (low[0], high[0], operands[2],
- scratch));
+ emit_insn (gen_x86_shift_adj_1
+ (half_mode, low[0], high[0], operands[2], scratch));
}
else
- {
- rtx (*gen_x86_shift_adj_2)(rtx, rtx, rtx)
- = mode == DImode ? gen_x86_shiftsi_adj_2 : gen_x86_shiftdi_adj_2;
-
- emit_insn (gen_x86_shift_adj_2 (low[0], high[0], operands[2]));
- }
+ emit_insn (gen_x86_shift_adj_2
+ (half_mode, low[0], high[0], operands[2]));
}
}
@@ -5681,7 +5801,7 @@ counter_mode (rtx count_exp)
static void
-expand_set_or_movmem_via_loop (rtx destmem, rtx srcmem,
+expand_set_or_cpymem_via_loop (rtx destmem, rtx srcmem,
rtx destptr, rtx srcptr, rtx value,
rtx count, machine_mode mode, int unroll,
int expected_size, bool issetmem)
@@ -5834,7 +5954,7 @@ scale_counter (rtx countreg, int scale)
Other arguments have same meaning as for previous function. */
static void
-expand_set_or_movmem_via_rep (rtx destmem, rtx srcmem,
+expand_set_or_cpymem_via_rep (rtx destmem, rtx srcmem,
rtx destptr, rtx srcptr, rtx value, rtx orig_value,
rtx count,
machine_mode mode, bool issetmem)
@@ -6001,7 +6121,7 @@ ix86_expand_aligntest (rtx variable, int value, bool epilogue)
/* Output code to copy at most count & (max_size - 1) bytes from SRC to DEST. */
static void
-expand_movmem_epilogue (rtx destmem, rtx srcmem,
+expand_cpymem_epilogue (rtx destmem, rtx srcmem,
rtx destptr, rtx srcptr, rtx count, int max_size)
{
rtx src, dest;
@@ -6026,7 +6146,7 @@ expand_movmem_epilogue (rtx destmem, rtx srcmem,
{
count = expand_simple_binop (GET_MODE (count), AND, count, GEN_INT (max_size - 1),
count, 1, OPTAB_DIRECT);
- expand_set_or_movmem_via_loop (destmem, srcmem, destptr, srcptr, NULL,
+ expand_set_or_cpymem_via_loop (destmem, srcmem, destptr, srcptr, NULL,
count, QImode, 1, 4, false);
return;
}
@@ -6175,7 +6295,7 @@ expand_setmem_epilogue_via_loop (rtx destmem, rtx destptr, rtx value,
{
count = expand_simple_binop (counter_mode (count), AND, count,
GEN_INT (max_size - 1), count, 1, OPTAB_DIRECT);
- expand_set_or_movmem_via_loop (destmem, NULL, destptr, NULL,
+ expand_set_or_cpymem_via_loop (destmem, NULL, destptr, NULL,
gen_lowpart (QImode, value), count, QImode,
1, max_size / 2, true);
}
@@ -6286,10 +6406,7 @@ expand_setmem_epilogue (rtx destmem, rtx destptr, rtx value, rtx vec_value,
static void
ix86_adjust_counter (rtx countreg, HOST_WIDE_INT value)
{
- rtx (*gen_add)(rtx, rtx, rtx)
- = GET_MODE (countreg) == DImode ? gen_adddi3 : gen_addsi3;
-
- emit_insn (gen_add (countreg, countreg, GEN_INT (-value)));
+ emit_insn (gen_add2_insn (countreg, GEN_INT (-value)));
}
/* Depending on ISSETMEM, copy enough from SRCMEM to DESTMEM or set enough to
@@ -6299,7 +6416,7 @@ ix86_adjust_counter (rtx countreg, HOST_WIDE_INT value)
Return value is updated DESTMEM. */
static rtx
-expand_set_or_movmem_prologue (rtx destmem, rtx srcmem,
+expand_set_or_cpymem_prologue (rtx destmem, rtx srcmem,
rtx destptr, rtx srcptr, rtx value,
rtx vec_value, rtx count, int align,
int desired_alignment, bool issetmem)
@@ -6332,7 +6449,7 @@ expand_set_or_movmem_prologue (rtx destmem, rtx srcmem,
or setmem sequence that is valid for SIZE..2*SIZE-1 bytes
and jump to DONE_LABEL. */
static void
-expand_small_movmem_or_setmem (rtx destmem, rtx srcmem,
+expand_small_cpymem_or_setmem (rtx destmem, rtx srcmem,
rtx destptr, rtx srcptr,
rtx value, rtx vec_value,
rtx count, int size,
@@ -6458,7 +6575,7 @@ expand_small_movmem_or_setmem (rtx destmem, rtx srcmem,
done_label:
*/
static void
-expand_set_or_movmem_prologue_epilogue_by_misaligned_moves (rtx destmem, rtx srcmem,
+expand_set_or_cpymem_prologue_epilogue_by_misaligned_moves (rtx destmem, rtx srcmem,
rtx *destptr, rtx *srcptr,
machine_mode mode,
rtx value, rtx vec_value,
@@ -6499,7 +6616,7 @@ expand_set_or_movmem_prologue_epilogue_by_misaligned_moves (rtx destmem, rtx src
/* Handle sizes > 3. */
for (;size2 > 2; size2 >>= 1)
- expand_small_movmem_or_setmem (destmem, srcmem,
+ expand_small_cpymem_or_setmem (destmem, srcmem,
*destptr, *srcptr,
value, vec_value,
*count,
@@ -6654,7 +6771,7 @@ expand_set_or_movmem_prologue_epilogue_by_misaligned_moves (rtx destmem, rtx src
is returned, but also of SRC, which is passed as a pointer for that
reason. */
static rtx
-expand_set_or_movmem_constant_prologue (rtx dst, rtx *srcp, rtx destreg,
+expand_set_or_cpymem_constant_prologue (rtx dst, rtx *srcp, rtx destreg,
rtx srcreg, rtx value, rtx vec_value,
int desired_align, int align_bytes,
bool issetmem)
@@ -7097,7 +7214,7 @@ ix86_copy_addr_to_reg (rtx addr)
3) Main body: the copying loop itself, copying in SIZE_NEEDED chunks
with specified algorithm. */
bool
-ix86_expand_set_or_movmem (rtx dst, rtx src, rtx count_exp, rtx val_exp,
+ix86_expand_set_or_cpymem (rtx dst, rtx src, rtx count_exp, rtx val_exp,
rtx align_exp, rtx expected_align_exp,
rtx expected_size_exp, rtx min_size_exp,
rtx max_size_exp, rtx probable_max_size_exp,
@@ -7319,7 +7436,7 @@ ix86_expand_set_or_movmem (rtx dst, rtx src, rtx count_exp, rtx val_exp,
if (misaligned_prologue_used)
{
/* Misaligned move prologue handled small blocks by itself. */
- expand_set_or_movmem_prologue_epilogue_by_misaligned_moves
+ expand_set_or_cpymem_prologue_epilogue_by_misaligned_moves
(dst, src, &destreg, &srcreg,
move_mode, promoted_val, vec_promoted_val,
&count_exp,
@@ -7436,7 +7553,7 @@ ix86_expand_set_or_movmem (rtx dst, rtx src, rtx count_exp, rtx val_exp,
dst = change_address (dst, BLKmode, destreg);
if (!issetmem)
src = change_address (src, BLKmode, srcreg);
- dst = expand_set_or_movmem_prologue (dst, src, destreg, srcreg,
+ dst = expand_set_or_cpymem_prologue (dst, src, destreg, srcreg,
promoted_val, vec_promoted_val,
count_exp, align, desired_align,
issetmem);
@@ -7450,7 +7567,7 @@ ix86_expand_set_or_movmem (rtx dst, rtx src, rtx count_exp, rtx val_exp,
{
/* If we know how many bytes need to be stored before dst is
sufficiently aligned, maintain aliasing info accurately. */
- dst = expand_set_or_movmem_constant_prologue (dst, &src, destreg,
+ dst = expand_set_or_cpymem_constant_prologue (dst, &src, destreg,
srcreg,
promoted_val,
vec_promoted_val,
@@ -7509,19 +7626,19 @@ ix86_expand_set_or_movmem (rtx dst, rtx src, rtx count_exp, rtx val_exp,
case loop_1_byte:
case loop:
case unrolled_loop:
- expand_set_or_movmem_via_loop (dst, src, destreg, srcreg, promoted_val,
+ expand_set_or_cpymem_via_loop (dst, src, destreg, srcreg, promoted_val,
count_exp, move_mode, unroll_factor,
expected_size, issetmem);
break;
case vector_loop:
- expand_set_or_movmem_via_loop (dst, src, destreg, srcreg,
+ expand_set_or_cpymem_via_loop (dst, src, destreg, srcreg,
vec_promoted_val, count_exp, move_mode,
unroll_factor, expected_size, issetmem);
break;
case rep_prefix_8_byte:
case rep_prefix_4_byte:
case rep_prefix_1_byte:
- expand_set_or_movmem_via_rep (dst, src, destreg, srcreg, promoted_val,
+ expand_set_or_cpymem_via_rep (dst, src, destreg, srcreg, promoted_val,
val_exp, count_exp, move_mode, issetmem);
break;
}
@@ -7574,7 +7691,7 @@ ix86_expand_set_or_movmem (rtx dst, rtx src, rtx count_exp, rtx val_exp,
vec_promoted_val, count_exp,
epilogue_size_needed);
else
- expand_movmem_epilogue (dst, src, destreg, srcreg, count_exp,
+ expand_cpymem_epilogue (dst, src, destreg, srcreg, count_exp,
epilogue_size_needed);
}
}
@@ -7658,7 +7775,7 @@ ix86_expand_strlensi_unroll_1 (rtx out, rtx src, rtx align_rtx)
QImode, 1, end_0_label);
/* Increment the address. */
- emit_insn (ix86_gen_add3 (out, out, const1_rtx));
+ emit_insn (gen_add2_insn (out, const1_rtx));
/* Not needed with an alignment of 2 */
if (align != 2)
@@ -7668,7 +7785,7 @@ ix86_expand_strlensi_unroll_1 (rtx out, rtx src, rtx align_rtx)
emit_cmp_and_jump_insns (mem, const0_rtx, EQ, NULL, QImode, 1,
end_0_label);
- emit_insn (ix86_gen_add3 (out, out, const1_rtx));
+ emit_insn (gen_add2_insn (out, const1_rtx));
emit_label (align_3_label);
}
@@ -7676,7 +7793,7 @@ ix86_expand_strlensi_unroll_1 (rtx out, rtx src, rtx align_rtx)
emit_cmp_and_jump_insns (mem, const0_rtx, EQ, NULL, QImode, 1,
end_0_label);
- emit_insn (ix86_gen_add3 (out, out, const1_rtx));
+ emit_insn (gen_add2_insn (out, const1_rtx));
}
/* Generate loop to check 4 bytes at a time. It is not a good idea to
@@ -7686,7 +7803,7 @@ ix86_expand_strlensi_unroll_1 (rtx out, rtx src, rtx align_rtx)
mem = change_address (src, SImode, out);
emit_move_insn (scratch, mem);
- emit_insn (ix86_gen_add3 (out, out, GEN_INT (4)));
+ emit_insn (gen_add2_insn (out, GEN_INT (4)));
/* This formula yields a nonzero result iff one of the bytes is zero.
This saves three branches inside loop and many cycles. */
@@ -7740,7 +7857,7 @@ ix86_expand_strlensi_unroll_1 (rtx out, rtx src, rtx align_rtx)
/* Not in the first two. Move two bytes forward. */
emit_insn (gen_lshrsi3 (tmpreg, tmpreg, GEN_INT (16)));
- emit_insn (ix86_gen_add3 (out, out, const2_rtx));
+ emit_insn (gen_add2_insn (out, const2_rtx));
emit_label (end_2_label);
@@ -7751,7 +7868,7 @@ ix86_expand_strlensi_unroll_1 (rtx out, rtx src, rtx align_rtx)
emit_insn (gen_addqi3_cconly_overflow (tmpreg, tmpreg));
tmp = gen_rtx_REG (CCmode, FLAGS_REG);
cmp = gen_rtx_LTU (VOIDmode, tmp, const0_rtx);
- emit_insn (ix86_gen_sub3_carry (out, out, GEN_INT (3), tmp, cmp));
+ emit_insn (gen_sub3_carry (Pmode, out, out, GEN_INT (3), tmp, cmp));
emit_label (end_0_label);
}
@@ -7784,7 +7901,7 @@ if (TARGET_UNROLL_STRLEN
/* strlensi_unroll_1 returns the address of the zero at the end of
the string, like memchr(), so compute the length by subtracting
the start address. */
- emit_insn (ix86_gen_sub3 (out, out, addr));
+ emit_insn (gen_sub2_insn (out, addr));
return true;
}
else
@@ -7807,7 +7924,7 @@ construct_plt_address (rtx symbol)
unspec = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, symbol), UNSPEC_PLTOFF);
emit_move_insn (tmp, gen_rtx_CONST (Pmode, unspec));
- emit_insn (ix86_gen_add3 (tmp, tmp, pic_offset_table_rtx));
+ emit_insn (gen_add2_insn (tmp, pic_offset_table_rtx));
return tmp;
}
@@ -7838,7 +7955,7 @@ ix86_expand_call (rtx retval, rtx fnaddr, rtx callarg1,
if (fndecl
&& (lookup_attribute ("interrupt",
TYPE_ATTRIBUTES (TREE_TYPE (fndecl)))))
- error ("interrupt service routine can%'t be called directly");
+ error ("interrupt service routine cannot be called directly");
}
else
fndecl = NULL_TREE;
@@ -9142,8 +9259,6 @@ ix86_expand_args_builtin (const struct builtin_description *d,
case V4DI_FTYPE_V4DI_INT:
case V2DI_FTYPE_V4DI_INT:
case V4DI_FTYPE_V8DI_INT:
- case QI_FTYPE_V4SF_INT:
- case QI_FTYPE_V2DF_INT:
case UQI_FTYPE_UQI_UQI_CONST:
case UHI_FTYPE_UHI_UQI:
case USI_FTYPE_USI_UQI:
@@ -9877,17 +9992,23 @@ ix86_expand_sse_comi_round (const struct builtin_description *d,
const struct insn_data_d *insn_p = &insn_data[icode];
machine_mode mode0 = insn_p->operand[0].mode;
machine_mode mode1 = insn_p->operand[1].mode;
- enum rtx_code comparison = UNEQ;
- bool need_ucomi = false;
/* See avxintrin.h for values. */
- enum rtx_code comi_comparisons[32] =
+ static const enum rtx_code comparisons[32] =
{
- UNEQ, GT, GE, UNORDERED, LTGT, UNLE, UNLT, ORDERED, UNEQ, UNLT,
- UNLE, LT, LTGT, GE, GT, LT, UNEQ, GT, GE, UNORDERED, LTGT, UNLE,
- UNLT, ORDERED, UNEQ, UNLT, UNLE, LT, LTGT, GE, GT, LT
+ EQ, LT, LE, UNORDERED, NE, UNGE, UNGT, ORDERED,
+ UNEQ, UNLT, UNLE, UNORDERED, LTGT, GE, GT, ORDERED,
+ EQ, LT, LE, UNORDERED, NE, UNGE, UNGT, ORDERED,
+ UNEQ, UNLT, UNLE, UNORDERED, LTGT, GE, GT, ORDERED
};
- bool need_ucomi_values[32] =
+ static const bool ordereds[32] =
+ {
+ true, true, true, false, false, false, false, true,
+ false, false, false, true, true, true, true, false,
+ true, true, true, false, false, false, false, true,
+ false, false, false, true, true, true, true, false
+ };
+ static const bool non_signalings[32] =
{
true, false, false, true, true, false, false, true,
true, false, false, true, true, false, false, true,
@@ -9912,16 +10033,94 @@ ix86_expand_sse_comi_round (const struct builtin_description *d,
return const0_rtx;
}
- comparison = comi_comparisons[INTVAL (op2)];
- need_ucomi = need_ucomi_values[INTVAL (op2)];
-
if (VECTOR_MODE_P (mode0))
op0 = safe_vector_operand (op0, mode0);
if (VECTOR_MODE_P (mode1))
op1 = safe_vector_operand (op1, mode1);
+ enum rtx_code comparison = comparisons[INTVAL (op2)];
+ bool ordered = ordereds[INTVAL (op2)];
+ bool non_signaling = non_signalings[INTVAL (op2)];
+ rtx const_val = const0_rtx;
+
+ bool check_unordered = false;
+ machine_mode mode = CCFPmode;
+ switch (comparison)
+ {
+ case ORDERED:
+ if (!ordered)
+ {
+ /* NB: Use CCSmode/NE for _CMP_TRUE_UQ/_CMP_TRUE_US. */
+ if (!non_signaling)
+ ordered = true;
+ mode = CCSmode;
+ }
+ else
+ {
+ /* NB: Use CCPmode/NE for _CMP_ORD_Q/_CMP_ORD_S. */
+ if (non_signaling)
+ ordered = false;
+ mode = CCPmode;
+ }
+ comparison = NE;
+ break;
+ case UNORDERED:
+ if (ordered)
+ {
+ /* NB: Use CCSmode/EQ for _CMP_FALSE_OQ/_CMP_FALSE_OS. */
+ if (non_signaling)
+ ordered = false;
+ mode = CCSmode;
+ }
+ else
+ {
+ /* NB: Use CCPmode/NE for _CMP_UNORD_Q/_CMP_UNORD_S. */
+ if (!non_signaling)
+ ordered = true;
+ mode = CCPmode;
+ }
+ comparison = EQ;
+ break;
+
+ case LE: /* -> GE */
+ case LT: /* -> GT */
+ case UNGE: /* -> UNLE */
+ case UNGT: /* -> UNLT */
+ std::swap (op0, op1);
+ comparison = swap_condition (comparison);
+ /* FALLTHRU */
+ case GT:
+ case GE:
+ case UNEQ:
+ case UNLT:
+ case UNLE:
+ case LTGT:
+ /* These are supported by CCFPmode. NB: Use ordered/signaling
+ COMI or unordered/non-signaling UCOMI. Both set ZF, PF, CF
+ with NAN operands. */
+ if (ordered == non_signaling)
+ ordered = !ordered;
+ break;
+ case EQ:
+ /* NB: COMI/UCOMI will set ZF with NAN operands. Use CCZmode for
+ _CMP_EQ_OQ/_CMP_EQ_OS. */
+ check_unordered = true;
+ mode = CCZmode;
+ break;
+ case NE:
+ /* NB: COMI/UCOMI will set ZF with NAN operands. Use CCZmode for
+ _CMP_NEQ_UQ/_CMP_NEQ_US. */
+ gcc_assert (!ordered);
+ check_unordered = true;
+ mode = CCZmode;
+ const_val = const1_rtx;
+ break;
+ default:
+ gcc_unreachable ();
+ }
+
target = gen_reg_rtx (SImode);
- emit_move_insn (target, const0_rtx);
+ emit_move_insn (target, const_val);
target = gen_rtx_SUBREG (QImode, target, 0);
if ((optimize && !register_operand (op0, mode0))
@@ -9931,10 +10130,14 @@ ix86_expand_sse_comi_round (const struct builtin_description *d,
|| !insn_p->operand[1].predicate (op1, mode1))
op1 = copy_to_mode_reg (mode1, op1);
- if (need_ucomi)
- icode = icode == CODE_FOR_sse_comi_round
- ? CODE_FOR_sse_ucomi_round
- : CODE_FOR_sse2_ucomi_round;
+ /*
+ 1. COMI: ordered and signaling.
+ 2. UCOMI: unordered and non-signaling.
+ */
+ if (non_signaling)
+ icode = (icode == CODE_FOR_sse_comi_round
+ ? CODE_FOR_sse_ucomi_round
+ : CODE_FOR_sse2_ucomi_round);
pat = GEN_FCN (icode) (op0, op1, op3);
if (! pat)
@@ -9956,11 +10159,42 @@ ix86_expand_sse_comi_round (const struct builtin_description *d,
}
emit_insn (pat);
+
+ rtx_code_label *label = NULL;
+
+ /* NB: For ordered EQ or unordered NE, check ZF alone isn't sufficient
+ with NAN operands. */
+ if (check_unordered)
+ {
+ gcc_assert (comparison == EQ || comparison == NE);
+
+ rtx flag = gen_rtx_REG (CCFPmode, FLAGS_REG);
+ label = gen_label_rtx ();
+ rtx tmp = gen_rtx_fmt_ee (UNORDERED, VOIDmode, flag, const0_rtx);
+ tmp = gen_rtx_IF_THEN_ELSE (VOIDmode, tmp,
+ gen_rtx_LABEL_REF (VOIDmode, label),
+ pc_rtx);
+ emit_jump_insn (gen_rtx_SET (pc_rtx, tmp));
+ }
+
+ /* NB: Set CCFPmode and check a different CCmode which is in subset
+ of CCFPmode. */
+ if (GET_MODE (set_dst) != mode)
+ {
+ gcc_assert (mode == CCAmode || mode == CCCmode
+ || mode == CCOmode || mode == CCPmode
+ || mode == CCSmode || mode == CCZmode);
+ set_dst = gen_rtx_REG (mode, FLAGS_REG);
+ }
+
emit_insn (gen_rtx_SET (gen_rtx_STRICT_LOW_PART (VOIDmode, target),
gen_rtx_fmt_ee (comparison, QImode,
set_dst,
const0_rtx)));
+ if (label)
+ emit_label (label);
+
return SUBREG_REG (target);
}
@@ -10630,7 +10864,8 @@ get_element_number (tree vec_type, tree arg)
if (!tree_fits_uhwi_p (arg)
|| (elt = tree_to_uhwi (arg), elt > max))
{
- error ("selector must be an integer constant in the range 0..%wi", max);
+ error ("selector must be an integer constant in the range "
+ "[0, %wi]", max);
return 0;
}
@@ -10805,6 +11040,25 @@ ix86_expand_builtin (tree exp, rtx target, rtx subtarget,
== (OPTION_MASK_ISA_FMA | OPTION_MASK_ISA_FMA4))
&& (isa & (OPTION_MASK_ISA_FMA | OPTION_MASK_ISA_FMA4)) != 0)
isa |= (OPTION_MASK_ISA_FMA | OPTION_MASK_ISA_FMA4);
+ /* Use SSE/SSE2/SSSE3 to emulate MMX intrinsics in 64-bit mode when
+ MMX is disabled. NB: Since MMX intrinsics are marked with
+ SSE/SSE2/SSSE3, enable them without SSE/SSE2/SSSE3 if MMX is
+ enabled. */
+ if (TARGET_MMX || TARGET_MMX_WITH_SSE)
+ {
+ if (((bisa & (OPTION_MASK_ISA_SSE | OPTION_MASK_ISA_MMX))
+ == (OPTION_MASK_ISA_SSE | OPTION_MASK_ISA_MMX))
+ && (isa & (OPTION_MASK_ISA_SSE | OPTION_MASK_ISA_MMX)) != 0)
+ isa |= (OPTION_MASK_ISA_SSE | OPTION_MASK_ISA_MMX);
+ if (((bisa & (OPTION_MASK_ISA_SSE2 | OPTION_MASK_ISA_MMX))
+ == (OPTION_MASK_ISA_SSE2 | OPTION_MASK_ISA_MMX))
+ && (isa & (OPTION_MASK_ISA_SSE2 | OPTION_MASK_ISA_MMX)) != 0)
+ isa |= (OPTION_MASK_ISA_SSE2 | OPTION_MASK_ISA_MMX);
+ if (((bisa & (OPTION_MASK_ISA_SSSE3 | OPTION_MASK_ISA_MMX))
+ == (OPTION_MASK_ISA_SSSE3 | OPTION_MASK_ISA_MMX))
+ && (isa & (OPTION_MASK_ISA_SSSE3 | OPTION_MASK_ISA_MMX)) != 0)
+ isa |= (OPTION_MASK_ISA_SSSE3 | OPTION_MASK_ISA_MMX);
+ }
if ((bisa & isa) != bisa || (bisa2 & isa2) != bisa2)
{
bool add_abi_p = bisa & OPTION_MASK_ISA_64BIT;
@@ -10916,8 +11170,8 @@ ix86_expand_builtin (tree exp, rtx target, rtx subtarget,
op2 = copy_to_mode_reg (SImode, op2);
emit_insn (fcode == IX86_BUILTIN_MONITOR
- ? ix86_gen_monitor (op0, op1, op2)
- : ix86_gen_monitorx (op0, op1, op2));
+ ? gen_sse3_monitor (Pmode, op0, op1, op2)
+ : gen_monitorx (Pmode, op0, op1, op2));
return 0;
case IX86_BUILTIN_MWAIT:
@@ -10953,12 +11207,7 @@ ix86_expand_builtin (tree exp, rtx target, rtx subtarget,
op0 = expand_normal (arg0);
op0 = ix86_zero_extend_to_Pmode (op0);
-
- insn = (TARGET_64BIT
- ? gen_umonitor_di (op0)
- : gen_umonitor_si (op0));
-
- emit_insn (insn);
+ emit_insn (gen_umonitor (Pmode, op0));
return 0;
case IX86_BUILTIN_UMWAIT:
@@ -11029,7 +11278,7 @@ ix86_expand_builtin (tree exp, rtx target, rtx subtarget,
op0 = expand_normal (arg0);
if (!REG_P (op0))
op0 = ix86_zero_extend_to_Pmode (op0);
- emit_insn (ix86_gen_clzero (op0));
+ emit_insn (gen_clzero (Pmode, op0));
return 0;
case IX86_BUILTIN_CLDEMOTE:
@@ -11090,6 +11339,79 @@ ix86_expand_builtin (tree exp, rtx target, rtx subtarget,
emit_move_insn (target, op0);
return target;
+ case IX86_BUILTIN_2INTERSECTD512:
+ case IX86_BUILTIN_2INTERSECTQ512:
+ case IX86_BUILTIN_2INTERSECTD256:
+ case IX86_BUILTIN_2INTERSECTQ256:
+ case IX86_BUILTIN_2INTERSECTD128:
+ case IX86_BUILTIN_2INTERSECTQ128:
+ arg0 = CALL_EXPR_ARG (exp, 0);
+ arg1 = CALL_EXPR_ARG (exp, 1);
+ arg2 = CALL_EXPR_ARG (exp, 2);
+ arg3 = CALL_EXPR_ARG (exp, 3);
+ op0 = expand_normal (arg0);
+ op1 = expand_normal (arg1);
+ op2 = expand_normal (arg2);
+ op3 = expand_normal (arg3);
+
+ if (!address_operand (op0, VOIDmode))
+ {
+ op0 = convert_memory_address (Pmode, op0);
+ op0 = copy_addr_to_reg (op0);
+ }
+ if (!address_operand (op1, VOIDmode))
+ {
+ op1 = convert_memory_address (Pmode, op1);
+ op1 = copy_addr_to_reg (op1);
+ }
+
+ switch (fcode)
+ {
+ case IX86_BUILTIN_2INTERSECTD512:
+ mode4 = P2HImode;
+ icode = CODE_FOR_avx512vp2intersect_2intersectv16si;
+ break;
+ case IX86_BUILTIN_2INTERSECTQ512:
+ mode4 = P2QImode;
+ icode = CODE_FOR_avx512vp2intersect_2intersectv8di;
+ break;
+ case IX86_BUILTIN_2INTERSECTD256:
+ mode4 = P2QImode;
+ icode = CODE_FOR_avx512vp2intersect_2intersectv8si;
+ break;
+ case IX86_BUILTIN_2INTERSECTQ256:
+ mode4 = P2QImode;
+ icode = CODE_FOR_avx512vp2intersect_2intersectv4di;
+ break;
+ case IX86_BUILTIN_2INTERSECTD128:
+ mode4 = P2QImode;
+ icode = CODE_FOR_avx512vp2intersect_2intersectv4si;
+ break;
+ case IX86_BUILTIN_2INTERSECTQ128:
+ mode4 = P2QImode;
+ icode = CODE_FOR_avx512vp2intersect_2intersectv2di;
+ break;
+ default:
+ gcc_unreachable ();
+ }
+
+ mode2 = insn_data[icode].operand[1].mode;
+ mode3 = insn_data[icode].operand[2].mode;
+ if (!insn_data[icode].operand[1].predicate (op2, mode2))
+ op2 = copy_to_mode_reg (mode2, op2);
+ if (!insn_data[icode].operand[2].predicate (op3, mode3))
+ op3 = copy_to_mode_reg (mode3, op3);
+
+ op4 = gen_reg_rtx (mode4);
+ emit_insn (GEN_FCN (icode) (op4, op2, op3));
+ mode0 = mode4 == P2HImode ? HImode : QImode;
+ emit_move_insn (gen_rtx_MEM (mode0, op0),
+ gen_lowpart (mode0, op4));
+ emit_move_insn (gen_rtx_MEM (mode0, op1),
+ gen_highpart (mode0, op4));
+
+ return 0;
+
case IX86_BUILTIN_RDPMC:
case IX86_BUILTIN_RDTSC:
case IX86_BUILTIN_RDTSCP:
@@ -11163,6 +11485,8 @@ ix86_expand_builtin (tree exp, rtx target, rtx subtarget,
emit_move_insn (target, op0);
return target;
+ case IX86_BUILTIN_ENQCMD:
+ case IX86_BUILTIN_ENQCMDS:
case IX86_BUILTIN_MOVDIR64B:
arg0 = CALL_EXPR_ARG (exp, 0);
@@ -11178,11 +11502,33 @@ ix86_expand_builtin (tree exp, rtx target, rtx subtarget,
}
op1 = gen_rtx_MEM (XImode, op1);
- insn = (TARGET_64BIT
- ? gen_movdir64b_di (op0, op1)
- : gen_movdir64b_si (op0, op1));
- emit_insn (insn);
- return 0;
+ if (fcode == IX86_BUILTIN_MOVDIR64B)
+ {
+ emit_insn (gen_movdir64b (Pmode, op0, op1));
+ return 0;
+ }
+ else
+ {
+ rtx pat;
+
+ target = gen_reg_rtx (SImode);
+ emit_move_insn (target, const0_rtx);
+ target = gen_rtx_SUBREG (QImode, target, 0);
+
+ if (fcode == IX86_BUILTIN_ENQCMD)
+ pat = gen_enqcmd (UNSPECV_ENQCMD, Pmode, op0, op1);
+ else
+ pat = gen_enqcmd (UNSPECV_ENQCMDS, Pmode, op0, op1);
+
+ emit_insn (pat);
+
+ emit_insn (gen_rtx_SET (gen_rtx_STRICT_LOW_PART (VOIDmode, target),
+ gen_rtx_fmt_ee (EQ, QImode,
+ SET_DEST (pat),
+ const0_rtx)));
+
+ return SUBREG_REG (target);
+ }
case IX86_BUILTIN_FXSAVE:
case IX86_BUILTIN_FXRSTOR:
@@ -13941,6 +14287,17 @@ ix86_expand_vector_set (bool mmx_ok, rtx target, rtx val, int elt)
return;
case E_V2DFmode:
+ /* NB: For ELT == 0, use standard scalar operation patterns which
+ preserve the rest of the vector for combiner:
+
+ (vec_merge:V2DF
+ (vec_duplicate:V2DF (reg:DF))
+ (reg:V2DF)
+ (const_int 1))
+ */
+ if (elt == 0)
+ goto do_vec_merge;
+
{
rtx op0, op1;
@@ -14238,6 +14595,7 @@ quarter:
}
else if (use_vec_merge)
{
+do_vec_merge:
tmp = gen_rtx_VEC_DUPLICATE (mode, val);
tmp = gen_rtx_VEC_MERGE (mode, tmp, target,
GEN_INT (HOST_WIDE_INT_1U << elt));
@@ -15533,8 +15891,10 @@ ix86_expand_floorceildf_32 (rtx operand0, rtx operand1, bool do_floor)
x2 -= 1;
Compensate. Ceil:
if (x2 < x)
- x2 -= -1;
- return x2;
+ x2 += 1;
+ if (HONOR_SIGNED_ZEROS (mode))
+ x2 = copysign (x2, x);
+ return x2;
*/
machine_mode mode = GET_MODE (operand0);
rtx xa, TWO52, tmp, one, res, mask;
@@ -15560,17 +15920,16 @@ ix86_expand_floorceildf_32 (rtx operand0, rtx operand1, bool do_floor)
/* xa = copysign (xa, operand1) */
ix86_sse_copysign_to_positive (xa, xa, res, mask);
- /* generate 1.0 or -1.0 */
- one = force_reg (mode,
- const_double_from_real_value (do_floor
- ? dconst1 : dconstm1, mode));
+ /* generate 1.0 */
+ one = force_reg (mode, const_double_from_real_value (dconst1, mode));
/* Compensate: xa = xa - (xa > operand1 ? 1 : 0) */
tmp = ix86_expand_sse_compare_mask (UNGT, xa, res, !do_floor);
emit_insn (gen_rtx_SET (tmp, gen_rtx_AND (mode, one, tmp)));
- /* We always need to subtract here to preserve signed zero. */
- tmp = expand_simple_binop (mode, MINUS,
+ tmp = expand_simple_binop (mode, do_floor ? MINUS : PLUS,
xa, tmp, NULL_RTX, 0, OPTAB_DIRECT);
+ if (!do_floor && HONOR_SIGNED_ZEROS (mode))
+ ix86_sse_copysign_to_positive (tmp, tmp, res, mask);
emit_move_insn (res, tmp);
emit_label (label);
@@ -15693,14 +16052,13 @@ ix86_expand_rounddf_32 (rtx operand0, rtx operand1)
0, OPTAB_DIRECT);
/* Compensate. */
- tmp = gen_reg_rtx (mode);
/* xa2 = xa2 - (dxa > 0.5 ? 1 : 0) */
tmp = ix86_expand_sse_compare_mask (UNGT, dxa, half, false);
- emit_insn (gen_rtx_SET (tmp, gen_rtx_AND (mode, one, tmp)));
+ emit_insn (gen_rtx_SET (tmp, gen_rtx_AND (mode, tmp, one)));
xa2 = expand_simple_binop (mode, MINUS, xa2, tmp, NULL_RTX, 0, OPTAB_DIRECT);
/* xa2 = xa2 + (dxa <= -0.5 ? 1 : 0) */
tmp = ix86_expand_sse_compare_mask (UNGE, mhalf, dxa, false);
- emit_insn (gen_rtx_SET (tmp, gen_rtx_AND (mode, one, tmp)));
+ emit_insn (gen_rtx_SET (tmp, gen_rtx_AND (mode, tmp, one)));
xa2 = expand_simple_binop (mode, PLUS, xa2, tmp, NULL_RTX, 0, OPTAB_DIRECT);
/* res = copysign (xa2, operand1) */
@@ -19421,8 +19779,7 @@ ix86_expand_sse2_mulvxdi3 (rtx op0, rtx op1, rtx op2)
emit_insn (gen_vec_widen_umult_even_v4si (t5,
gen_lowpart (V4SImode, op1),
gen_lowpart (V4SImode, op2)));
- op0 = expand_binop (mode, add_optab, t5, t4, op0, 1, OPTAB_DIRECT);
-
+ force_expand_binop (mode, add_optab, t5, t4, op0, 1, OPTAB_DIRECT);
}
else
{
diff --git a/gcc/config/i386/i386-features.c b/gcc/config/i386/i386-features.c
index 67f45d6..2eac8f7 100644
--- a/gcc/config/i386/i386-features.c
+++ b/gcc/config/i386/i386-features.c
@@ -554,7 +554,7 @@ dimode_scalar_chain::compute_convert_gain ()
fprintf (dump_file, " Instruction conversion gain: %d\n", gain);
EXECUTE_IF_SET_IN_BITMAP (defs_conv, 0, insn_uid, bi)
- cost += DF_REG_DEF_COUNT (insn_uid) * ix86_cost->mmxsse_to_integer;
+ cost += DF_REG_DEF_COUNT (insn_uid) * ix86_cost->sse_to_integer;
if (dump_file)
fprintf (dump_file, " Registers conversion cost: %d\n", cost);
@@ -1911,10 +1911,7 @@ rest_of_insert_endbranch (void)
continue;
}
- if ((LABEL_P (insn) && LABEL_PRESERVE_P (insn))
- || (NOTE_P (insn)
- && NOTE_KIND (insn) == NOTE_INSN_DELETED_LABEL))
- /* TODO. Check /s bit also. */
+ if (LABEL_P (insn) && LABEL_PRESERVE_P (insn))
{
cet_eb = gen_nop_endbr ();
emit_insn_after (cet_eb, insn);
@@ -2447,7 +2444,7 @@ ix86_mangle_function_version_assembler_name (tree decl, tree id)
&& lookup_attribute ("gnu_inline",
DECL_ATTRIBUTES (decl)))
error_at (DECL_SOURCE_LOCATION (decl),
- "function versions cannot be marked as gnu_inline,"
+ "function versions cannot be marked as %<gnu_inline%>,"
" bodies have to be generated");
if (DECL_VIRTUAL_P (decl)
@@ -2584,7 +2581,7 @@ ix86_get_function_versions_dispatcher (void *decl)
#endif
{
error_at (DECL_SOURCE_LOCATION (default_node->decl),
- "multiversioning needs ifunc which is not supported "
+ "multiversioning needs %<ifunc%> which is not supported "
"on this target");
}
diff --git a/gcc/config/i386/i386-modes.def b/gcc/config/i386/i386-modes.def
index d0ae469..e1b86c8 100644
--- a/gcc/config/i386/i386-modes.def
+++ b/gcc/config/i386/i386-modes.def
@@ -101,6 +101,12 @@ VECTOR_MODE (INT, SI, 64); /* V64SI */
INT_MODE (OI, 32);
INT_MODE (XI, 64);
+/* Modes needs a consecutive register pair.
+ Note that Using PARTIAL_INT_MODE but not INT_MODE is to avoid mode promotion
+ issues. */
+PARTIAL_INT_MODE (HI, 16, P2QI);
+PARTIAL_INT_MODE (SI, 32, P2HI);
+
/* Keep the OI and XI modes from confusing the compiler into thinking
that these modes could actually be used for computation. They are
only holders for vectors during data movement. */
diff --git a/gcc/config/i386/i386-options.c b/gcc/config/i386/i386-options.c
index dec8352..6f8851a 100644
--- a/gcc/config/i386/i386-options.c
+++ b/gcc/config/i386/i386-options.c
@@ -199,6 +199,7 @@ ix86_target_string (HOST_WIDE_INT isa, HOST_WIDE_INT isa2,
{ "-mrdpid", OPTION_MASK_ISA_RDPID },
{ "-mpconfig", OPTION_MASK_ISA_PCONFIG },
{ "-mwbnoinvd", OPTION_MASK_ISA_WBNOINVD },
+ { "-mavx512vp2intersect", OPTION_MASK_ISA_AVX512VP2INTERSECT },
{ "-msgx", OPTION_MASK_ISA_SGX },
{ "-mavx5124vnniw", OPTION_MASK_ISA_AVX5124VNNIW },
{ "-mavx5124fmaps", OPTION_MASK_ISA_AVX5124FMAPS },
@@ -210,7 +211,8 @@ ix86_target_string (HOST_WIDE_INT isa, HOST_WIDE_INT isa2,
{ "-mwaitpkg", OPTION_MASK_ISA_WAITPKG },
{ "-mcldemote", OPTION_MASK_ISA_CLDEMOTE },
{ "-mptwrite", OPTION_MASK_ISA_PTWRITE },
- { "-mavx512bf16", OPTION_MASK_ISA_AVX512BF16 }
+ { "-mavx512bf16", OPTION_MASK_ISA_AVX512BF16 },
+ { "-menqcmd", OPTION_MASK_ISA_ENQCMD }
};
static struct ix86_target_opts isa_opts[] =
{
@@ -851,6 +853,7 @@ ix86_valid_target_attribute_inner_p (tree fndecl, tree args, char *p_strings[],
IX86_ATTR_ISA ("avx512vbmi2", OPT_mavx512vbmi2),
IX86_ATTR_ISA ("avx512vnni", OPT_mavx512vnni),
IX86_ATTR_ISA ("avx512bitalg", OPT_mavx512bitalg),
+ IX86_ATTR_ISA ("avx512vp2intersect", OPT_mavx512vp2intersect),
IX86_ATTR_ISA ("avx512vbmi", OPT_mavx512vbmi),
IX86_ATTR_ISA ("avx512ifma", OPT_mavx512ifma),
@@ -921,6 +924,7 @@ ix86_valid_target_attribute_inner_p (tree fndecl, tree args, char *p_strings[],
IX86_ATTR_ISA ("cldemote", OPT_mcldemote),
IX86_ATTR_ISA ("ptwrite", OPT_mptwrite),
IX86_ATTR_ISA ("avx512bf16", OPT_mavx512bf16),
+ IX86_ATTR_ISA ("enqcmd", OPT_menqcmd),
/* enum options */
IX86_ATTR_ENUM ("fpmath=", OPT_mfpmath_),
@@ -1537,6 +1541,7 @@ ix86_init_machine_status (void)
f = ggc_cleared_alloc<machine_function> ();
f->call_abi = ix86_abi;
+ f->stack_frame_required = true;
return f;
}
@@ -2024,6 +2029,10 @@ ix86_option_override_internal (bool main_args_p,
& OPTION_MASK_ISA_AVX512BITALG))
opts->x_ix86_isa_flags |= OPTION_MASK_ISA_AVX512BITALG;
+ if (((processor_alias_table[i].flags & PTA_AVX512VP2INTERSECT) != 0)
+ && !(opts->x_ix86_isa_flags2_explicit
+ & OPTION_MASK_ISA_AVX512VP2INTERSECT))
+ opts->x_ix86_isa_flags2 |= OPTION_MASK_ISA_AVX512VP2INTERSECT;
if (((processor_alias_table[i].flags & PTA_AVX5124VNNIW) != 0)
&& !(opts->x_ix86_isa_flags2_explicit
& OPTION_MASK_ISA_AVX5124VNNIW))
@@ -2551,54 +2560,6 @@ ix86_option_override_internal (bool main_args_p,
if (!TARGET_64BIT_P (opts->x_ix86_isa_flags) && !opts->x_flag_split_stack)
targetm.expand_builtin_va_start = NULL;
- if (TARGET_64BIT_P (opts->x_ix86_isa_flags))
- {
- ix86_gen_leave = gen_leave_rex64;
- if (Pmode == DImode)
- {
- ix86_gen_tls_global_dynamic_64 = gen_tls_global_dynamic_64_di;
- ix86_gen_tls_local_dynamic_base_64
- = gen_tls_local_dynamic_base_64_di;
- }
- else
- {
- ix86_gen_tls_global_dynamic_64 = gen_tls_global_dynamic_64_si;
- ix86_gen_tls_local_dynamic_base_64
- = gen_tls_local_dynamic_base_64_si;
- }
- }
- else
- ix86_gen_leave = gen_leave;
-
- if (Pmode == DImode)
- {
- ix86_gen_add3 = gen_adddi3;
- ix86_gen_sub3 = gen_subdi3;
- ix86_gen_sub3_carry = gen_subdi3_carry;
- ix86_gen_one_cmpl2 = gen_one_cmpldi2;
- ix86_gen_andsp = gen_anddi3;
- ix86_gen_allocate_stack_worker = gen_allocate_stack_worker_probe_di;
- ix86_gen_adjust_stack_and_probe = gen_adjust_stack_and_probedi;
- ix86_gen_probe_stack_range = gen_probe_stack_rangedi;
- ix86_gen_monitor = gen_sse3_monitor_di;
- ix86_gen_monitorx = gen_monitorx_di;
- ix86_gen_clzero = gen_clzero_di;
- }
- else
- {
- ix86_gen_add3 = gen_addsi3;
- ix86_gen_sub3 = gen_subsi3;
- ix86_gen_sub3_carry = gen_subsi3_carry;
- ix86_gen_one_cmpl2 = gen_one_cmplsi2;
- ix86_gen_andsp = gen_andsi3;
- ix86_gen_allocate_stack_worker = gen_allocate_stack_worker_probe_si;
- ix86_gen_adjust_stack_and_probe = gen_adjust_stack_and_probesi;
- ix86_gen_probe_stack_range = gen_probe_stack_rangesi;
- ix86_gen_monitor = gen_sse3_monitor_si;
- ix86_gen_monitorx = gen_monitorx_si;
- ix86_gen_clzero = gen_clzero_si;
- }
-
#ifdef USE_IX86_CLD
/* Use -mcld by default for 32-bit code if configured with --enable-cld. */
if (!TARGET_64BIT_P (opts->x_ix86_isa_flags))
@@ -3462,7 +3423,8 @@ ix86_handle_abi_attribute (tree *node, tree name, tree, int,
{
if (lookup_attribute ("sysv_abi", TYPE_ATTRIBUTES (*node)))
{
- error ("ms_abi and sysv_abi attributes are not compatible");
+ error ("%qs and %qs attributes are not compatible",
+ "ms_abi", "sysv_abi");
}
return NULL_TREE;
@@ -3471,7 +3433,8 @@ ix86_handle_abi_attribute (tree *node, tree name, tree, int,
{
if (lookup_attribute ("ms_abi", TYPE_ATTRIBUTES (*node)))
{
- error ("ms_abi and sysv_abi attributes are not compatible");
+ error ("%qs and %qs attributes are not compatible",
+ "ms_abi", "sysv_abi");
}
return NULL_TREE;
@@ -3582,7 +3545,7 @@ ix86_handle_interrupt_attribute (tree *node, tree, tree, int, bool *)
error ("interrupt service routine can only have a pointer argument "
"and an optional integer argument");
if (! VOID_TYPE_P (return_type))
- error ("interrupt service routine can%'t have non-void return value");
+ error ("interrupt service routine must return %<void%>");
return NULL_TREE;
}
diff --git a/gcc/config/i386/i386-options.h b/gcc/config/i386/i386-options.h
index 817ddda..966eb76 100644
--- a/gcc/config/i386/i386-options.h
+++ b/gcc/config/i386/i386-options.h
@@ -55,21 +55,6 @@ extern tree (*ix86_veclib_handler) (combined_fn, tree, tree);
extern tree ix86_veclibabi_svml (combined_fn, tree, tree);
extern tree ix86_veclibabi_acml (combined_fn, tree, tree);
-extern rtx (*ix86_gen_leave) (void);
-extern rtx (*ix86_gen_add3) (rtx, rtx, rtx);
-extern rtx (*ix86_gen_sub3) (rtx, rtx, rtx);
-extern rtx (*ix86_gen_sub3_carry) (rtx, rtx, rtx, rtx, rtx);
-extern rtx (*ix86_gen_one_cmpl2) (rtx, rtx);
-extern rtx (*ix86_gen_monitor) (rtx, rtx, rtx);
-extern rtx (*ix86_gen_monitorx) (rtx, rtx, rtx);
-extern rtx (*ix86_gen_clzero) (rtx);
-extern rtx (*ix86_gen_andsp) (rtx, rtx, rtx);
-extern rtx (*ix86_gen_allocate_stack_worker) (rtx, rtx);
-extern rtx (*ix86_gen_adjust_stack_and_probe) (rtx, rtx, rtx);
-extern rtx (*ix86_gen_probe_stack_range) (rtx, rtx, rtx);
-extern rtx (*ix86_gen_tls_global_dynamic_64) (rtx, rtx, rtx);
-extern rtx (*ix86_gen_tls_local_dynamic_base_64) (rtx, rtx);
-
enum ix86_function_specific_strings
{
IX86_FUNCTION_SPECIFIC_ARCH,
diff --git a/gcc/config/i386/i386-protos.h b/gcc/config/i386/i386-protos.h
index 597af64..4d6e76d 100644
--- a/gcc/config/i386/i386-protos.h
+++ b/gcc/config/i386/i386-protos.h
@@ -47,6 +47,7 @@ extern void ix86_reset_previous_fndecl (void);
extern bool ix86_using_red_zone (void);
+extern unsigned int ix86_regmode_natural_size (machine_mode);
#ifdef RTX_CODE
extern int standard_80387_constant_p (rtx);
extern const char *standard_80387_constant_opcode (rtx);
@@ -65,7 +66,7 @@ extern int avx_vpermilp_parallel (rtx par, machine_mode mode);
extern int avx_vperm2f128_parallel (rtx par, machine_mode mode);
extern bool ix86_expand_strlen (rtx, rtx, rtx, rtx);
-extern bool ix86_expand_set_or_movmem (rtx, rtx, rtx, rtx, rtx, rtx,
+extern bool ix86_expand_set_or_cpymem (rtx, rtx, rtx, rtx, rtx, rtx,
rtx, rtx, rtx, rtx, bool);
extern bool constant_address_p (rtx);
@@ -121,6 +122,8 @@ extern rtx ix86_expand_adjust_ufix_to_sfix_si (rtx, rtx *);
extern enum ix86_fpcmp_strategy ix86_fp_comparison_strategy (enum rtx_code);
extern void ix86_expand_fp_absneg_operator (enum rtx_code, machine_mode,
rtx[]);
+extern void ix86_split_fp_absneg_operator (enum rtx_code, machine_mode,
+ rtx[]);
extern void ix86_expand_copysign (rtx []);
extern void ix86_split_copysign_const (rtx []);
extern void ix86_split_copysign_var (rtx []);
@@ -200,6 +203,10 @@ extern void ix86_expand_vecop_qihi (enum rtx_code, rtx, rtx, rtx);
extern rtx ix86_split_stack_guard (void);
+extern void ix86_move_vector_high_sse_to_mmx (rtx);
+extern void ix86_split_mmx_pack (rtx[], enum rtx_code);
+extern void ix86_split_mmx_punpck (rtx[], bool);
+
#ifdef TREE_CODE
extern void init_cumulative_args (CUMULATIVE_ARGS *, tree, rtx, tree, int);
#endif /* TREE_CODE */
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index ab1524c..49f49c5 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -349,21 +349,6 @@ enum processor_type ix86_arch;
/* True if processor has SSE prefetch instruction. */
unsigned char x86_prefetch_sse;
-rtx (*ix86_gen_leave) (void);
-rtx (*ix86_gen_add3) (rtx, rtx, rtx);
-rtx (*ix86_gen_sub3) (rtx, rtx, rtx);
-rtx (*ix86_gen_sub3_carry) (rtx, rtx, rtx, rtx, rtx);
-rtx (*ix86_gen_one_cmpl2) (rtx, rtx);
-rtx (*ix86_gen_monitor) (rtx, rtx, rtx);
-rtx (*ix86_gen_monitorx) (rtx, rtx, rtx);
-rtx (*ix86_gen_clzero) (rtx);
-rtx (*ix86_gen_andsp) (rtx, rtx, rtx);
-rtx (*ix86_gen_allocate_stack_worker) (rtx, rtx);
-rtx (*ix86_gen_adjust_stack_and_probe) (rtx, rtx, rtx);
-rtx (*ix86_gen_probe_stack_range) (rtx, rtx, rtx);
-rtx (*ix86_gen_tls_global_dynamic_64) (rtx, rtx, rtx);
-rtx (*ix86_gen_tls_local_dynamic_base_64) (rtx, rtx);
-
/* Preferred alignment for stack boundary in bits. */
unsigned int ix86_preferred_stack_boundary;
@@ -1525,7 +1510,7 @@ ix86_function_type_abi (const_tree fntype)
static int warned;
if (TARGET_X32 && !warned)
{
- error ("X32 does not support ms_abi attribute");
+ error ("X32 does not support %<ms_abi%> attribute");
warned = 1;
}
@@ -1559,7 +1544,8 @@ ix86_function_ms_hook_prologue (const_tree fn)
{
if (decl_function_context (fn) != NULL_TREE)
error_at (DECL_SOURCE_LOCATION (fn),
- "ms_hook_prologue is not compatible with nested function");
+ "%<ms_hook_prologue%> attribute is not compatible "
+ "with nested function");
else
return true;
}
@@ -1656,8 +1642,7 @@ ix86_init_large_pic_reg (unsigned int tmp_regno)
emit_insn (gen_set_rip_rex64 (pic_offset_table_rtx,
label));
emit_insn (gen_set_got_offset_rex64 (tmp_reg, label));
- emit_insn (ix86_gen_add3 (pic_offset_table_rtx,
- pic_offset_table_rtx, tmp_reg));
+ emit_insn (gen_add2_insn (pic_offset_table_rtx, tmp_reg));
const char *name = LABEL_NAME (label);
PUT_CODE (label, NOTE);
NOTE_KIND (label) = NOTE_INSN_DELETED_LABEL;
@@ -2266,7 +2251,7 @@ classify_argument (machine_mode mode, const_tree type,
{
warned = true;
inform (input_location,
- "the ABI of passing union with long double"
+ "the ABI of passing union with %<long double%>"
" has changed in GCC 4.4");
}
return 0;
@@ -2384,7 +2369,7 @@ classify_argument (machine_mode mode, const_tree type,
{
warned = true;
inform (input_location,
- "the ABI of passing structure with complex float"
+ "the ABI of passing structure with %<complex float%>"
" member has changed in GCC 4.4");
}
classes[1] = X86_64_SSESF_CLASS;
@@ -4151,7 +4136,6 @@ ix86_setup_incoming_vararg_bounds (cumulative_args_t cum_v,
CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
CUMULATIVE_ARGS next_cum;
tree fntype;
- int max;
gcc_assert (!no_rtl);
@@ -4167,10 +4151,6 @@ ix86_setup_incoming_vararg_bounds (cumulative_args_t cum_v,
if (stdarg_p (fntype))
ix86_function_arg_advance (pack_cumulative_args (&next_cum), mode, type,
true);
-
- max = cum->regno + cfun->va_list_gpr_size / UNITS_PER_WORD;
- if (max > X86_64_REGPARM_MAX)
- max = X86_64_REGPARM_MAX;
}
@@ -5011,6 +4991,19 @@ ix86_can_use_return_insn_p (void)
&& (frame.nregs + frame.nsseregs) == 0);
}
+/* Return stack frame size. get_frame_size () returns used stack slots
+ during compilation, which may be optimized out later. If stack frame
+ is needed, stack_frame_required should be true. */
+
+static HOST_WIDE_INT
+ix86_get_frame_size (void)
+{
+ if (cfun->machine->stack_frame_required)
+ return get_frame_size ();
+ else
+ return 0;
+}
+
/* Value should be nonzero if functions must have frame pointers.
Zero means the frame pointer need not be set up (and parms may
be accessed via the stack pointer) in functions that seem suitable. */
@@ -5034,7 +5027,7 @@ ix86_frame_pointer_required (void)
/* Win64 SEH, very large frames need a frame-pointer as maximum stack
allocation is 4GB. */
- if (TARGET_64BIT_MS_ABI && get_frame_size () > SEH_MAX_FRAME_SIZE)
+ if (TARGET_64BIT_MS_ABI && ix86_get_frame_size () > SEH_MAX_FRAME_SIZE)
return true;
/* SSE saves require frame-pointer when stack is misaligned. */
@@ -5790,17 +5783,6 @@ ix86_initial_elimination_offset (int from, int to)
}
}
-/* In a dynamically-aligned function, we can't know the offset from
- stack pointer to frame pointer, so we must ensure that setjmp
- eliminates fp against the hard fp (%ebp) rather than trying to
- index from %esp up to the top of the frame across a gap that is
- of unknown (at compile-time) size. */
-static rtx
-ix86_builtin_setjmp_frame_value (void)
-{
- return stack_realign_fp ? hard_frame_pointer_rtx : virtual_stack_vars_rtx;
-}
-
/* Emits a warning for unsupported msabi to sysv pro/epilogues. */
void warn_once_call_ms2sysv_xlogues (const char *feature)
{
@@ -5841,7 +5823,7 @@ ix86_compute_frame_layout (void)
unsigned HOST_WIDE_INT stack_alignment_needed;
HOST_WIDE_INT offset;
unsigned HOST_WIDE_INT preferred_alignment;
- HOST_WIDE_INT size = get_frame_size ();
+ HOST_WIDE_INT size = ix86_get_frame_size ();
HOST_WIDE_INT to_allocate;
/* m->call_ms2sysv is initially enabled in ix86_expand_call for all 64-bit
@@ -6304,7 +6286,6 @@ choose_basereg (HOST_WIDE_INT cfa_offset, rtx &base_reg,
{
base_reg = hard_frame_pointer_rtx;
base_offset = toffset;
- len = tlen;
}
}
}
@@ -6537,34 +6518,29 @@ pro_epilogue_adjust_stack (rtx dest, rtx src, rtx offset,
int style, bool set_cfa)
{
struct machine_function *m = cfun->machine;
+ rtx addend = offset;
rtx insn;
bool add_frame_related_expr = false;
- if (Pmode == SImode)
- insn = gen_pro_epilogue_adjust_stack_si_add (dest, src, offset);
- else if (x86_64_immediate_operand (offset, DImode))
- insn = gen_pro_epilogue_adjust_stack_di_add (dest, src, offset);
- else
+ if (!x86_64_immediate_operand (offset, Pmode))
{
- rtx tmp;
/* r11 is used by indirect sibcall return as well, set before the
epilogue and used after the epilogue. */
if (style)
- tmp = gen_rtx_REG (DImode, R11_REG);
+ addend = gen_rtx_REG (Pmode, R11_REG);
else
{
gcc_assert (src != hard_frame_pointer_rtx
&& dest != hard_frame_pointer_rtx);
- tmp = hard_frame_pointer_rtx;
+ addend = hard_frame_pointer_rtx;
}
- insn = emit_insn (gen_rtx_SET (tmp, offset));
+ emit_insn (gen_rtx_SET (addend, offset));
if (style < 0)
add_frame_related_expr = true;
-
- insn = gen_pro_epilogue_adjust_stack_di_add (dest, src, tmp);
}
- insn = emit_insn (insn);
+ insn = emit_insn (gen_pro_epilogue_adjust_stack_add
+ (Pmode, dest, src, addend));
if (style >= 0)
ix86_add_queued_cfa_restore_notes (insn);
@@ -7064,8 +7040,8 @@ ix86_adjust_stack_and_probe_stack_clash (HOST_WIDE_INT size,
/* Step 3: the loop. */
rtx size_rtx = GEN_INT (rounded_size);
- insn = emit_insn (ix86_gen_adjust_stack_and_probe (sr.reg, sr.reg,
- size_rtx));
+ insn = emit_insn (gen_adjust_stack_and_probe (Pmode, sr.reg, sr.reg,
+ size_rtx));
if (m->fs.cfa_reg == stack_pointer_rtx)
{
m->fs.cfa_offset += rounded_size;
@@ -7218,7 +7194,7 @@ ix86_adjust_stack_and_probe (HOST_WIDE_INT size,
adjusts SP and probes to PROBE_INTERVAL + N * PROBE_INTERVAL for
values of N from 1 until it is equal to ROUNDED_SIZE. */
- emit_insn (ix86_gen_adjust_stack_and_probe (sr.reg, sr.reg, size_rtx));
+ emit_insn (gen_adjust_stack_and_probe (Pmode, sr.reg, sr.reg, size_rtx));
/* Step 4: adjust SP and probe at PROBE_INTERVAL + SIZE if we cannot
@@ -7376,7 +7352,8 @@ ix86_emit_probe_stack_range (HOST_WIDE_INT first, HOST_WIDE_INT size,
probes at FIRST + N * PROBE_INTERVAL for values of N from 1
until it is equal to ROUNDED_SIZE. */
- emit_insn (ix86_gen_probe_stack_range (sr.reg, sr.reg, GEN_INT (-last)));
+ emit_insn
+ (gen_probe_stack_range (Pmode, sr.reg, sr.reg, GEN_INT (-last)));
/* Step 4: probe at FIRST + SIZE if we cannot assert at compile-time
@@ -7435,11 +7412,11 @@ output_probe_stack_range (rtx reg, rtx end)
return "";
}
-/* Return true if stack frame is required. Update STACK_ALIGNMENT
- to the largest alignment, in bits, of stack slot used if stack
- frame is required and CHECK_STACK_SLOT is true. */
+/* Set stack_frame_required to false if stack frame isn't required.
+ Update STACK_ALIGNMENT to the largest alignment, in bits, of stack
+ slot used if stack frame is required and CHECK_STACK_SLOT is true. */
-static bool
+static void
ix86_find_max_used_stack_alignment (unsigned int &stack_alignment,
bool check_stack_slot)
{
@@ -7488,7 +7465,7 @@ ix86_find_max_used_stack_alignment (unsigned int &stack_alignment,
}
}
- return require_stack_frame;
+ cfun->machine->stack_frame_required = require_stack_frame;
}
/* Finalize stack_realign_needed and frame_pointer_needed flags, which
@@ -7518,6 +7495,14 @@ ix86_finalize_stack_frame_flags (void)
return;
}
+ /* It is always safe to compute max_used_stack_alignment. We
+ compute it only if 128-bit aligned load/store may be generated
+ on misaligned stack slot which will lead to segfault. */
+ bool check_stack_slot
+ = (stack_realign || crtl->max_used_stack_slot_alignment >= 128);
+ ix86_find_max_used_stack_alignment (stack_alignment,
+ check_stack_slot);
+
/* If the only reason for frame_pointer_needed is that we conservatively
assumed stack realignment might be needed or -fno-omit-frame-pointer
is used, but in the end nothing that needed the stack alignment had
@@ -7537,12 +7522,11 @@ ix86_finalize_stack_frame_flags (void)
&& flag_exceptions
&& cfun->can_throw_non_call_exceptions)
&& !ix86_frame_pointer_required ()
- && get_frame_size () == 0
+ && ix86_get_frame_size () == 0
&& ix86_nsaved_sseregs () == 0
&& ix86_varargs_gpr_size + ix86_varargs_fpr_size == 0)
{
- if (ix86_find_max_used_stack_alignment (stack_alignment,
- stack_realign))
+ if (cfun->machine->stack_frame_required)
{
/* Stack frame is required. If stack alignment needed is less
than incoming stack boundary, don't realign stack. */
@@ -7630,17 +7614,14 @@ ix86_finalize_stack_frame_flags (void)
recompute_frame_layout_p = true;
}
}
- else if (crtl->max_used_stack_slot_alignment >= 128)
+ else if (crtl->max_used_stack_slot_alignment >= 128
+ && cfun->machine->stack_frame_required)
{
/* We don't need to realign stack. max_used_stack_alignment is
used to decide how stack frame should be aligned. This is
- independent of any psABIs nor 32-bit vs 64-bit. It is always
- safe to compute max_used_stack_alignment. We compute it only
- if 128-bit aligned load/store may be generated on misaligned
- stack slot which will lead to segfault. */
- if (ix86_find_max_used_stack_alignment (stack_alignment, true))
- cfun->machine->max_used_stack_alignment
- = stack_alignment / BITS_PER_UNIT;
+ independent of any psABIs nor 32-bit vs 64-bit. */
+ cfun->machine->max_used_stack_alignment
+ = stack_alignment / BITS_PER_UNIT;
}
if (crtl->stack_realign_needed != stack_realign)
@@ -7742,6 +7723,20 @@ ix86_emit_outlined_ms2sysv_save (const struct ix86_frame &frame)
RTX_FRAME_RELATED_P (insn) = true;
}
+/* Generate and return an insn body to AND X with Y. */
+
+static rtx_insn *
+gen_and2_insn (rtx x, rtx y)
+{
+ enum insn_code icode = optab_handler (and_optab, GET_MODE (x));
+
+ gcc_assert (insn_operand_matches (icode, 0, x));
+ gcc_assert (insn_operand_matches (icode, 1, x));
+ gcc_assert (insn_operand_matches (icode, 2, y));
+
+ return GEN_FCN (icode) (x, x, y);
+}
+
/* Expand the prologue into a bunch of separate insns. */
void
@@ -7787,7 +7782,7 @@ ix86_expand_prologue (void)
/* Check if profiling is active and we shall use profiling before
prologue variant. If so sorry. */
if (crtl->profile && flag_fentry != 0)
- sorry ("ms_hook_prologue attribute isn%'t compatible "
+ sorry ("%<ms_hook_prologue%> attribute is not compatible "
"with %<-mfentry%> for 32-bit");
/* In ix86_asm_output_function_label we emitted:
@@ -7897,9 +7892,8 @@ ix86_expand_prologue (void)
m->fs.cfa_offset = 0;
/* Align the stack. */
- insn = emit_insn (ix86_gen_andsp (stack_pointer_rtx,
- stack_pointer_rtx,
- GEN_INT (-align_bytes)));
+ insn = emit_insn (gen_and2_insn (stack_pointer_rtx,
+ GEN_INT (-align_bytes)));
RTX_FRAME_RELATED_P (insn) = 1;
/* Replicate the return address on the stack so that return
@@ -8003,9 +7997,7 @@ ix86_expand_prologue (void)
GEN_INT (-allocate), -1, false);
/* Align the stack. */
- insn = emit_insn (ix86_gen_andsp (stack_pointer_rtx,
- stack_pointer_rtx,
- GEN_INT (-align_bytes)));
+ emit_insn (gen_and2_insn (stack_pointer_rtx, GEN_INT (-align_bytes)));
m->fs.sp_offset = ROUND_UP (m->fs.sp_offset, align_bytes);
m->fs.sp_realigned_offset = m->fs.sp_offset
- frame.stack_realign_allocate;
@@ -8164,7 +8156,6 @@ ix86_expand_prologue (void)
{
rtx eax = gen_rtx_REG (Pmode, AX_REG);
rtx r10 = NULL;
- rtx (*adjust_stack_insn)(rtx, rtx, rtx);
const bool sp_is_cfa_reg = (m->fs.cfa_reg == stack_pointer_rtx);
bool eax_live = ix86_eax_live_at_start_p ();
bool r10_live = false;
@@ -8185,7 +8176,8 @@ ix86_expand_prologue (void)
RTX_FRAME_RELATED_P (insn) = 1;
add_reg_note (insn, REG_FRAME_RELATED_EXPR,
gen_rtx_SET (stack_pointer_rtx,
- plus_constant (Pmode, stack_pointer_rtx,
+ plus_constant (Pmode,
+ stack_pointer_rtx,
-UNITS_PER_WORD)));
}
}
@@ -8202,21 +8194,18 @@ ix86_expand_prologue (void)
RTX_FRAME_RELATED_P (insn) = 1;
add_reg_note (insn, REG_FRAME_RELATED_EXPR,
gen_rtx_SET (stack_pointer_rtx,
- plus_constant (Pmode, stack_pointer_rtx,
+ plus_constant (Pmode,
+ stack_pointer_rtx,
-UNITS_PER_WORD)));
}
}
emit_move_insn (eax, GEN_INT (allocate));
- emit_insn (ix86_gen_allocate_stack_worker (eax, eax));
+ emit_insn (gen_allocate_stack_worker_probe (Pmode, eax, eax));
/* Use the fact that AX still contains ALLOCATE. */
- adjust_stack_insn = (Pmode == DImode
- ? gen_pro_epilogue_adjust_stack_di_sub
- : gen_pro_epilogue_adjust_stack_si_sub);
-
- insn = emit_insn (adjust_stack_insn (stack_pointer_rtx,
- stack_pointer_rtx, eax));
+ insn = emit_insn (gen_pro_epilogue_adjust_stack_sub
+ (Pmode, stack_pointer_rtx, stack_pointer_rtx, eax));
if (sp_is_cfa_reg || TARGET_SEH)
{
@@ -8257,7 +8246,7 @@ ix86_expand_prologue (void)
/* If we havn't already set up the frame pointer, do so now. */
if (frame_pointer_needed && !m->fs.fp_valid)
{
- insn = ix86_gen_add3 (hard_frame_pointer_rtx, stack_pointer_rtx,
+ insn = gen_add3_insn (hard_frame_pointer_rtx, stack_pointer_rtx,
GEN_INT (frame.stack_pointer_offset
- frame.hard_frame_pointer_offset));
insn = emit_insn (insn);
@@ -8394,8 +8383,9 @@ static void
ix86_emit_leave (rtx_insn *insn)
{
struct machine_function *m = cfun->machine;
+
if (!insn)
- insn = emit_insn (ix86_gen_leave ());
+ insn = emit_insn (gen_leave (word_mode));
ix86_add_queued_cfa_restore_notes (insn);
@@ -9289,7 +9279,7 @@ ix86_expand_split_stack_prologue (void)
scratch_reg = gen_rtx_REG (Pmode, scratch_regno);
if (!TARGET_64BIT || x86_64_immediate_operand (offset, Pmode))
{
- /* We don't use ix86_gen_add3 in this case because it will
+ /* We don't use gen_add in this case because it will
want to split to lea, but when not optimizing the insn
will not be split after this point. */
emit_insn (gen_rtx_SET (scratch_reg,
@@ -9299,8 +9289,7 @@ ix86_expand_split_stack_prologue (void)
else
{
emit_move_insn (scratch_reg, offset);
- emit_insn (ix86_gen_add3 (scratch_reg, scratch_reg,
- stack_pointer_rtx));
+ emit_insn (gen_add2_insn (scratch_reg, stack_pointer_rtx));
}
current = scratch_reg;
}
@@ -9377,7 +9366,7 @@ ix86_expand_split_stack_prologue (void)
LABEL_PRESERVE_P (label) = 1;
emit_insn (gen_set_rip_rex64 (reg10, label));
emit_insn (gen_set_got_offset_rex64 (reg11, label));
- emit_insn (ix86_gen_add3 (reg10, reg10, reg11));
+ emit_insn (gen_add2_insn (reg10, reg11));
x = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, split_stack_fn_large),
UNSPEC_GOT);
x = gen_rtx_CONST (Pmode, x);
@@ -10809,7 +10798,7 @@ legitimize_tls_address (rtx x, enum tls_model model, bool for_mov)
start_sequence ();
emit_call_insn
- (ix86_gen_tls_global_dynamic_64 (rax, x, caddr));
+ (gen_tls_global_dynamic_64 (Pmode, rax, x, caddr));
insns = get_insns ();
end_sequence ();
@@ -10863,7 +10852,7 @@ legitimize_tls_address (rtx x, enum tls_model model, bool for_mov)
start_sequence ();
emit_call_insn
- (ix86_gen_tls_local_dynamic_base_64 (rax, caddr));
+ (gen_tls_local_dynamic_base_64 (Pmode, rax, caddr));
insns = get_insns ();
end_sequence ();
@@ -10952,7 +10941,7 @@ legitimize_tls_address (rtx x, enum tls_model model, bool for_mov)
{
base = get_thread_pointer (Pmode, true);
dest = gen_reg_rtx (Pmode);
- emit_insn (ix86_gen_sub3 (dest, base, off));
+ emit_insn (gen_sub3_insn (dest, base, off));
}
break;
@@ -10972,7 +10961,7 @@ legitimize_tls_address (rtx x, enum tls_model model, bool for_mov)
{
base = get_thread_pointer (Pmode, true);
dest = gen_reg_rtx (Pmode);
- emit_insn (ix86_gen_sub3 (dest, base, off));
+ emit_insn (gen_sub3_insn (dest, base, off));
}
break;
@@ -11456,7 +11445,7 @@ output_pic_addr_const (FILE *file, rtx x, int code)
break;
case SYMBOL_REF:
- if (TARGET_64BIT || ! TARGET_MACHO_BRANCH_ISLANDS)
+ if (TARGET_64BIT || ! TARGET_MACHO_PICSYM_STUBS)
output_addr_const (file, x);
else
{
@@ -15130,6 +15119,20 @@ ix86_nopic_noplt_attribute_p (rtx call_op)
return false;
}
+/* Helper to output the jmp/call. */
+static void
+ix86_output_jmp_thunk_or_indirect (const char *thunk_name, const int regno)
+{
+ if (thunk_name != NULL)
+ {
+ fprintf (asm_out_file, "\tjmp\t");
+ assemble_name (asm_out_file, thunk_name);
+ putc ('\n', asm_out_file);
+ }
+ else
+ output_indirect_thunk (regno);
+}
+
/* Output indirect branch via a call and return thunk. CALL_OP is a
register which contains the branch target. XASM is the assembly
template for CALL_OP. Branch is a tail call if SIBCALL_P is true.
@@ -15168,17 +15171,14 @@ ix86_output_indirect_branch_via_reg (rtx call_op, bool sibcall_p)
thunk_name = NULL;
if (sibcall_p)
- {
- if (thunk_name != NULL)
- fprintf (asm_out_file, "\tjmp\t%s\n", thunk_name);
- else
- output_indirect_thunk (regno);
- }
+ ix86_output_jmp_thunk_or_indirect (thunk_name, regno);
else
{
if (thunk_name != NULL)
{
- fprintf (asm_out_file, "\tcall\t%s\n", thunk_name);
+ fprintf (asm_out_file, "\tcall\t");
+ assemble_name (asm_out_file, thunk_name);
+ putc ('\n', asm_out_file);
return;
}
@@ -15199,10 +15199,7 @@ ix86_output_indirect_branch_via_reg (rtx call_op, bool sibcall_p)
ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, indirectlabel1);
- if (thunk_name != NULL)
- fprintf (asm_out_file, "\tjmp\t%s\n", thunk_name);
- else
- output_indirect_thunk (regno);
+ ix86_output_jmp_thunk_or_indirect (thunk_name, regno);
ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, indirectlabel2);
@@ -15259,10 +15256,7 @@ ix86_output_indirect_branch_via_push (rtx call_op, const char *xasm,
if (sibcall_p)
{
output_asm_insn (push_buf, &call_op);
- if (thunk_name != NULL)
- fprintf (asm_out_file, "\tjmp\t%s\n", thunk_name);
- else
- output_indirect_thunk (regno);
+ ix86_output_jmp_thunk_or_indirect (thunk_name, regno);
}
else
{
@@ -15318,10 +15312,7 @@ ix86_output_indirect_branch_via_push (rtx call_op, const char *xasm,
output_asm_insn (push_buf, &call_op);
- if (thunk_name != NULL)
- fprintf (asm_out_file, "\tjmp\t%s\n", thunk_name);
- else
- output_indirect_thunk (regno);
+ ix86_output_jmp_thunk_or_indirect (thunk_name, regno);
ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, indirectlabel2);
@@ -15420,7 +15411,9 @@ ix86_output_function_return (bool long_p)
indirect_thunk_name (thunk_name, INVALID_REGNUM, need_prefix,
true);
indirect_return_needed |= need_thunk;
- fprintf (asm_out_file, "\tjmp\t%s\n", thunk_name);
+ fprintf (asm_out_file, "\tjmp\t");
+ assemble_name (asm_out_file, thunk_name);
+ putc ('\n', asm_out_file);
}
else
output_indirect_thunk (INVALID_REGNUM);
@@ -15460,7 +15453,9 @@ ix86_output_indirect_function_return (rtx ret_op)
indirect_return_via_cx = true;
indirect_thunks_used |= 1 << CX_REG;
}
- fprintf (asm_out_file, "\tjmp\t%s\n", thunk_name);
+ fprintf (asm_out_file, "\tjmp\t");
+ assemble_name (asm_out_file, thunk_name);
+ putc ('\n', asm_out_file);
}
else
output_indirect_thunk (regno);
@@ -17290,7 +17285,7 @@ ix86_gimple_fold_builtin (gimple_stmt_iterator *gsi)
int n_args = gimple_call_num_args (stmt);
enum ix86_builtins fn_code = (enum ix86_builtins) DECL_FUNCTION_CODE (fndecl);
tree decl = NULL_TREE;
- tree arg0, arg1;
+ tree arg0, arg1, arg2;
enum rtx_code rcode;
unsigned HOST_WIDE_INT count;
bool is_vshift;
@@ -17594,6 +17589,32 @@ ix86_gimple_fold_builtin (gimple_stmt_iterator *gsi)
}
break;
+ case IX86_BUILTIN_SHUFPD:
+ arg2 = gimple_call_arg (stmt, 2);
+ if (TREE_CODE (arg2) == INTEGER_CST)
+ {
+ location_t loc = gimple_location (stmt);
+ unsigned HOST_WIDE_INT imask = TREE_INT_CST_LOW (arg2);
+ arg0 = gimple_call_arg (stmt, 0);
+ arg1 = gimple_call_arg (stmt, 1);
+ tree itype = long_long_integer_type_node;
+ tree vtype = build_vector_type (itype, 2); /* V2DI */
+ tree_vector_builder elts (vtype, 2, 1);
+ /* Ignore bits other than the lowest 2. */
+ elts.quick_push (build_int_cst (itype, imask & 1));
+ imask >>= 1;
+ elts.quick_push (build_int_cst (itype, 2 + (imask & 1)));
+ tree omask = elts.build ();
+ gimple *g = gimple_build_assign (gimple_call_lhs (stmt),
+ VEC_PERM_EXPR,
+ arg0, arg1, omask);
+ gimple_set_location (g, loc);
+ gsi_replace (gsi, g, false);
+ return true;
+ }
+ // Do not error yet, the constant could be propagated later?
+ break;
+
default:
break;
}
@@ -18148,12 +18169,10 @@ ix86_preferred_reload_class (rtx x, reg_class_t regclass)
static reg_class_t
ix86_preferred_output_reload_class (rtx x, reg_class_t regclass)
{
- machine_mode mode = GET_MODE (x);
-
/* Restrict the output reload class to the register bank that we are doing
math on. If we would like not to return a subset of CLASS, reject this
alternative: if reload cannot do this, it will still use its choice. */
- mode = GET_MODE (x);
+ machine_mode mode = GET_MODE (x);
if (SSE_FLOAT_MODE_P (mode) && TARGET_SSE_MATH)
return MAYBE_SSE_CLASS_P (regclass) ? ALL_SSE_REGS : NO_REGS;
@@ -18594,18 +18613,21 @@ ix86_register_move_cost (machine_mode mode, reg_class_t class1_i,
return cost;
}
- /* Moves between SSE/MMX and integer unit are expensive. */
- if (MMX_CLASS_P (class1) != MMX_CLASS_P (class2)
- || SSE_CLASS_P (class1) != SSE_CLASS_P (class2))
+ /* Moves between MMX and non-MMX units require secondary memory. */
+ if (MMX_CLASS_P (class1) != MMX_CLASS_P (class2))
+ gcc_unreachable ();
+
+ /* Moves between SSE and integer units are expensive. */
+ if (SSE_CLASS_P (class1) != SSE_CLASS_P (class2))
/* ??? By keeping returned value relatively high, we limit the number
- of moves between integer and MMX/SSE registers for all targets.
+ of moves between integer and SSE registers for all targets.
Additionally, high value prevents problem with x86_modes_tieable_p(),
- where integer modes in MMX/SSE registers are not tieable
+ where integer modes in SSE registers are not tieable
because of missing QImode and HImode moves to, from or between
MMX/SSE registers. */
- return MAX (8, MMX_CLASS_P (class1) || MMX_CLASS_P (class2)
- ? ix86_cost->mmxsse_to_integer : ix86_cost->ssemmx_to_integer);
+ return MAX (8, SSE_CLASS_P (class1)
+ ? ix86_cost->sse_to_integer : ix86_cost->integer_to_sse);
if (MAYBE_FLOAT_CLASS_P (class1))
return ix86_cost->fp_move;
@@ -18643,11 +18665,23 @@ ix86_hard_regno_nregs (unsigned int regno, machine_mode mode)
}
if (COMPLEX_MODE_P (mode))
return 2;
+ /* Register pair for mask registers. */
+ if (mode == P2QImode || mode == P2HImode)
+ return 2;
if (mode == V64SFmode || mode == V64SImode)
return 4;
return 1;
}
+/* Implement REGMODE_NATURAL_SIZE(MODE). */
+unsigned int
+ix86_regmode_natural_size (machine_mode mode)
+{
+ if (mode == P2HImode || mode == P2QImode)
+ return GET_MODE_SIZE (mode) / 2;
+ return UNITS_PER_WORD;
+}
+
/* Implement TARGET_HARD_REGNO_MODE_OK. */
static bool
@@ -18657,15 +18691,24 @@ ix86_hard_regno_mode_ok (unsigned int regno, machine_mode mode)
if (CC_REGNO_P (regno))
return GET_MODE_CLASS (mode) == MODE_CC;
if (GET_MODE_CLASS (mode) == MODE_CC
- || GET_MODE_CLASS (mode) == MODE_RANDOM
- || GET_MODE_CLASS (mode) == MODE_PARTIAL_INT)
+ || GET_MODE_CLASS (mode) == MODE_RANDOM)
return false;
if (STACK_REGNO_P (regno))
return VALID_FP_MODE_P (mode);
if (MASK_REGNO_P (regno))
- return (VALID_MASK_REG_MODE (mode)
- || (TARGET_AVX512BW
- && VALID_MASK_AVX512BW_MODE (mode)));
+ {
+ /* Register pair only starts at even register number. */
+ if ((mode == P2QImode || mode == P2HImode))
+ return MASK_PAIR_REGNO_P(regno);
+
+ return (VALID_MASK_REG_MODE (mode)
+ || (TARGET_AVX512BW
+ && VALID_MASK_AVX512BW_MODE (mode)));
+ }
+
+ if (GET_MODE_CLASS (mode) == MODE_PARTIAL_INT)
+ return false;
+
if (SSE_REGNO_P (regno))
{
/* We implement the move patterns for all vector modes into and
@@ -18876,7 +18919,8 @@ ix86_set_reg_reg_cost (machine_mode mode)
|| (TARGET_AVX && VALID_AVX256_REG_MODE (mode))
|| (TARGET_SSE2 && VALID_SSE2_REG_MODE (mode))
|| (TARGET_SSE && VALID_SSE_REG_MODE (mode))
- || (TARGET_MMX && VALID_MMX_REG_MODE (mode)))
+ || ((TARGET_MMX || TARGET_MMX_WITH_SSE)
+ && VALID_MMX_REG_MODE (mode)))
units = GET_MODE_SIZE (mode);
}
@@ -19073,7 +19117,8 @@ ix86_rtx_costs (rtx x, machine_mode mode, int outer_code_i, int opno,
rtx mask;
enum rtx_code code = GET_CODE (x);
enum rtx_code outer_code = (enum rtx_code) outer_code_i;
- const struct processor_costs *cost = speed ? ix86_cost : &ix86_size_cost;
+ const struct processor_costs *cost
+ = speed ? ix86_tune_cost : &ix86_size_cost;
int src_cost;
switch (code)
@@ -19752,9 +19797,10 @@ x86_can_output_mi_thunk (const_tree, HOST_WIDE_INT, HOST_WIDE_INT vcall_offset,
*(*this + vcall_offset) should be added to THIS. */
static void
-x86_output_mi_thunk (FILE *file, tree, HOST_WIDE_INT delta,
+x86_output_mi_thunk (FILE *file, tree thunk_fndecl, HOST_WIDE_INT delta,
HOST_WIDE_INT vcall_offset, tree function)
{
+ const char *fnname = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (thunk_fndecl));
rtx this_param = x86_this_parameter (function);
rtx this_reg, tmp, fnaddr;
unsigned int tmp_regno;
@@ -19930,13 +19976,14 @@ x86_output_mi_thunk (FILE *file, tree, HOST_WIDE_INT delta,
}
emit_barrier ();
- /* Emit just enough of rest_of_compilation to get the insns emitted.
- Note that use_thunk calls assemble_start_function et al. */
+ /* Emit just enough of rest_of_compilation to get the insns emitted. */
insn = get_insns ();
shorten_branches (insn);
+ assemble_start_function (thunk_fndecl, fnname);
final_start_function (insn, file, 1);
final (insn, file, 1);
final_end_function ();
+ assemble_end_function (thunk_fndecl, fnname);
}
static void
@@ -20605,7 +20652,7 @@ ix86_vector_mode_supported_p (machine_mode mode)
return true;
if (TARGET_AVX512F && VALID_AVX512F_REG_MODE (mode))
return true;
- if (TARGET_MMX && VALID_MMX_REG_MODE (mode))
+ if ((TARGET_MMX || TARGET_MMX_WITH_SSE) && VALID_MMX_REG_MODE (mode))
return true;
if (TARGET_3DNOW && VALID_MMX_REG_MODE_3DNOW (mode))
return true;
@@ -20645,7 +20692,7 @@ ix86_md_asm_adjust (vec<rtx> &outputs, vec<rtx> &/*inputs*/,
con += 4;
if (strchr (con, ',') != NULL)
{
- error ("alternatives not allowed in asm flag output");
+ error ("alternatives not allowed in %<asm%> flag output");
continue;
}
@@ -20709,7 +20756,7 @@ ix86_md_asm_adjust (vec<rtx> &outputs, vec<rtx> &/*inputs*/,
}
if (code == UNKNOWN)
{
- error ("unknown asm flag output %qs", constraints[i]);
+ error ("unknown %<asm%> flag output %qs", constraints[i]);
continue;
}
if (invert)
@@ -20738,7 +20785,7 @@ ix86_md_asm_adjust (vec<rtx> &outputs, vec<rtx> &/*inputs*/,
machine_mode dest_mode = GET_MODE (dest);
if (!SCALAR_INT_MODE_P (dest_mode))
{
- error ("invalid type for asm flag output");
+ error ("invalid type for %<asm%> flag output");
continue;
}
@@ -21321,7 +21368,7 @@ ix86_preferred_simd_mode (scalar_mode mode)
256bit and 128bit vectors. */
static void
-ix86_autovectorize_vector_sizes (vector_sizes *sizes)
+ix86_autovectorize_vector_sizes (vector_sizes *sizes, bool all)
{
if (TARGET_AVX512F && !TARGET_PREFER_AVX256)
{
@@ -21329,11 +21376,27 @@ ix86_autovectorize_vector_sizes (vector_sizes *sizes)
sizes->safe_push (32);
sizes->safe_push (16);
}
+ else if (TARGET_AVX512F && all)
+ {
+ sizes->safe_push (32);
+ sizes->safe_push (16);
+ sizes->safe_push (64);
+ }
else if (TARGET_AVX && !TARGET_PREFER_AVX128)
{
sizes->safe_push (32);
sizes->safe_push (16);
}
+ else if (TARGET_AVX && all)
+ {
+ sizes->safe_push (16);
+ sizes->safe_push (32);
+ }
+ else if (TARGET_MMX_WITH_SSE)
+ sizes->safe_push (16);
+
+ if (TARGET_MMX_WITH_SSE)
+ sizes->safe_push (8);
}
/* Implemenation of targetm.vectorize.get_mask_mode. */
@@ -21672,13 +21735,15 @@ ix86_memmodel_check (unsigned HOST_WIDE_INT val)
if (val & IX86_HLE_ACQUIRE && !(is_mm_acquire (model) || strong))
{
warning (OPT_Winvalid_memory_model,
- "HLE_ACQUIRE not used with ACQUIRE or stronger memory model");
+ "%<HLE_ACQUIRE%> not used with %<ACQUIRE%> or stronger "
+ "memory model");
return MEMMODEL_SEQ_CST | IX86_HLE_ACQUIRE;
}
if (val & IX86_HLE_RELEASE && !(is_mm_release (model) || strong))
{
warning (OPT_Winvalid_memory_model,
- "HLE_RELEASE not used with RELEASE or stronger memory model");
+ "%<HLE_RELEASE%> not used with %<RELEASE%> or stronger "
+ "memory model");
return MEMMODEL_SEQ_CST | IX86_HLE_RELEASE;
}
return val;
@@ -22708,9 +22773,6 @@ ix86_run_selftests (void)
#undef TARGET_MACHINE_DEPENDENT_REORG
#define TARGET_MACHINE_DEPENDENT_REORG ix86_reorg
-#undef TARGET_BUILTIN_SETJMP_FRAME_VALUE
-#define TARGET_BUILTIN_SETJMP_FRAME_VALUE ix86_builtin_setjmp_frame_value
-
#undef TARGET_BUILD_BUILTIN_VA_LIST
#define TARGET_BUILD_BUILTIN_VA_LIST ix86_build_builtin_va_list
@@ -23050,6 +23112,21 @@ ix86_run_selftests (void)
#define TARGET_GET_MULTILIB_ABI_NAME \
ix86_get_multilib_abi_name
+static bool ix86_libc_has_fast_function (int fcode ATTRIBUTE_UNUSED)
+{
+#ifdef OPTION_GLIBC
+ if (OPTION_GLIBC)
+ return (built_in_function)fcode == BUILT_IN_MEMPCPY;
+ else
+ return false;
+#else
+ return false;
+#endif
+}
+
+#undef TARGET_LIBC_HAS_FAST_FUNCTION
+#define TARGET_LIBC_HAS_FAST_FUNCTION ix86_libc_has_fast_function
+
#if CHECKING_P
#undef TARGET_RUN_TARGET_SELFTESTS
#define TARGET_RUN_TARGET_SELFTESTS selftest::ix86_run_selftests
diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h
index 3fee779..1f70844 100644
--- a/gcc/config/i386/i386.h
+++ b/gcc/config/i386/i386.h
@@ -93,6 +93,8 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
#define TARGET_AVX512VNNI_P(x) TARGET_ISA_AVX512VNNI_P(x)
#define TARGET_AVX512BITALG TARGET_ISA_AVX512BITALG
#define TARGET_AVX512BITALG_P(x) TARGET_ISA_AVX512BITALG_P(x)
+#define TARGET_AVX512VP2INTERSECT TARGET_ISA_AVX512VP2INTERSECT
+#define TARGET_AVX512VP2INTERSECT_P(x) TARGET_ISA_AVX512VP2INTERSECT_P(x)
#define TARGET_FMA TARGET_ISA_FMA
#define TARGET_FMA_P(x) TARGET_ISA_FMA_P(x)
#define TARGET_SSE4A TARGET_ISA_SSE4A
@@ -195,6 +197,8 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
#define TARGET_PTWRITE_P(x) TARGET_ISA_PTWRITE_P(x)
#define TARGET_AVX512BF16 TARGET_ISA_AVX512BF16
#define TARGET_AVX512BF16_P(x) TARGET_ISA_AVX512BF16_P(x)
+#define TARGET_ENQCMD TARGET_ISA_ENQCMD
+#define TARGET_ENQCMD_P(x) TARGET_ISA_ENQCMD_P(x)
#define TARGET_LP64 TARGET_ABI_64
#define TARGET_LP64_P(x) TARGET_ABI_64_P(x)
@@ -203,6 +207,8 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
#define TARGET_16BIT TARGET_CODE16
#define TARGET_16BIT_P(x) TARGET_CODE16_P(x)
+#define TARGET_MMX_WITH_SSE (TARGET_64BIT && TARGET_SSE2)
+
#include "config/vxworks-dummy.h"
#include "config/i386/i386-opts.h"
@@ -272,9 +278,8 @@ struct processor_costs {
const int sse_store[5]; /* cost of storing SSE register
in SImode, DImode and TImode. */
const int sse_unaligned_store[5];/* cost of unaligned store. */
- const int mmxsse_to_integer; /* cost of moving mmxsse register to
- integer. */
- const int ssemmx_to_integer; /* cost of moving integer to mmxsse register. */
+ const int sse_to_integer; /* cost of moving SSE register to integer. */
+ const int integer_to_sse; /* cost of moving integer register to SSE. */
const int gather_static, gather_per_elt; /* Cost of gather load is computed
as static + per_item * nelts. */
const int scatter_static, scatter_per_elt; /* Cost of gather store is
@@ -642,7 +647,7 @@ extern tree x86_mfence;
/* Replace MACH-O, ifdefs by in-line tests, where possible.
(a) Macros defined in config/i386/darwin.h */
#define TARGET_MACHO 0
-#define TARGET_MACHO_BRANCH_ISLANDS 0
+#define TARGET_MACHO_PICSYM_STUBS 0
#define MACHOPIC_ATT_STUB 0
/* (b) Macros defined in config/darwin.h */
#define MACHO_DYNAMIC_NO_PIC_P 0
@@ -1122,6 +1127,8 @@ extern const char *host_detect_local_cpu (int argc, const char **argv);
#define HARD_REGNO_NREGS_WITH_PADDING(REGNO, MODE) ((MODE) == XFmode ? 4 : 8)
+#define REGMODE_NATURAL_SIZE(MODE) ix86_regmode_natural_size (MODE)
+
#define VALID_AVX256_REG_MODE(MODE) \
((MODE) == V32QImode || (MODE) == V16HImode || (MODE) == V8SImode \
|| (MODE) == V4DImode || (MODE) == V2TImode || (MODE) == V8SFmode \
@@ -1506,6 +1513,7 @@ enum reg_class
#define MASK_REG_P(X) (REG_P (X) && MASK_REGNO_P (REGNO (X)))
#define MASK_REGNO_P(N) IN_RANGE ((N), FIRST_MASK_REG, LAST_MASK_REG)
+#define MASK_PAIR_REGNO_P(N) ((((N) - FIRST_MASK_REG) & 1) == 0)
#define MMX_REG_P(X) (REG_P (X) && MMX_REGNO_P (REGNO (X)))
#define MMX_REGNO_P(N) IN_RANGE ((N), FIRST_MMX_REG, LAST_MMX_REG)
@@ -1893,7 +1901,7 @@ typedef struct ix86_args {
? GET_MODE_SIZE (TImode) : UNITS_PER_WORD)
/* If a memory-to-memory move would take MOVE_RATIO or more simple
- move-instruction pairs, we will do a movmem or libcall instead.
+ move-instruction pairs, we will do a cpymem or libcall instead.
Increasing the value will always make code faster, but eventually
incurs high cost in increased code size.
@@ -1945,6 +1953,10 @@ do { \
#define STACK_SAVEAREA_MODE(LEVEL) \
((LEVEL) == SAVE_NONLOCAL ? (TARGET_64BIT ? TImode : DImode) : Pmode)
+/* Specify the machine_mode of the size increment
+ operand of an 'allocate_stack' named pattern. */
+#define STACK_SIZE_MODE Pmode
+
/* A C expression whose value is zero if pointers that need to be extended
from being `POINTER_SIZE' bits wide to `Pmode' are sign-extended and
greater then zero if they are zero-extended and less then zero if the
@@ -2355,6 +2367,7 @@ const wide_int_bitmask PTA_AVX512BITALG (0, HOST_WIDE_INT_1U << 5);
const wide_int_bitmask PTA_RDPID (0, HOST_WIDE_INT_1U << 6);
const wide_int_bitmask PTA_PCONFIG (0, HOST_WIDE_INT_1U << 7);
const wide_int_bitmask PTA_WBNOINVD (0, HOST_WIDE_INT_1U << 8);
+const wide_int_bitmask PTA_AVX512VP2INTERSECT (0, HOST_WIDE_INT_1U << 9);
const wide_int_bitmask PTA_WAITPKG (0, HOST_WIDE_INT_1U << 9);
const wide_int_bitmask PTA_PTWRITE (0, HOST_WIDE_INT_1U << 10);
const wide_int_bitmask PTA_AVX512BF16 (0, HOST_WIDE_INT_1U << 11);
@@ -2752,6 +2765,9 @@ struct GTY(()) machine_function {
/* If true, ENDBR is queued at function entrance. */
BOOL_BITFIELD endbr_queued_at_entrance : 1;
+ /* True if the function needs a stack frame. */
+ BOOL_BITFIELD stack_frame_required : 1;
+
/* The largest alignment, in bytes, of stack slot actually used. */
unsigned int max_used_stack_alignment;
diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md
index 44e4f4a..c401deb 100644
--- a/gcc/config/i386/i386.md
+++ b/gcc/config/i386/i386.md
@@ -295,6 +295,10 @@
UNSPECV_SPECULATION_BARRIER
UNSPECV_PTWRITE
+
+ ;; For ENQCMD and ENQCMDS support
+ UNSPECV_ENQCMD
+ UNSPECV_ENQCMDS
])
;; Constants to represent rounding modes in the ROUND instruction
@@ -790,12 +794,16 @@
;; Used to control the "enabled" attribute on a per-instruction basis.
(define_attr "isa" "base,x64,x64_sse2,x64_sse4,x64_sse4_noavx,x64_avx,nox64,
- sse2,sse2_noavx,sse3,sse4,sse4_noavx,avx,noavx,
+ sse_noavx,sse2,sse2_noavx,sse3,sse4,sse4_noavx,avx,noavx,
avx2,noavx2,bmi,bmi2,fma4,fma,avx512f,noavx512f,
avx512bw,noavx512bw,avx512dq,noavx512dq,
avx512vl,noavx512vl,x64_avx512dq,x64_avx512bw"
(const_string "base"))
+;; Define instruction set of MMX instructions
+(define_attr "mmx_isa" "base,native,sse,sse_noavx,avx"
+ (const_string "base"))
+
(define_attr "enabled" ""
(cond [(eq_attr "isa" "x64") (symbol_ref "TARGET_64BIT")
(eq_attr "isa" "x64_sse2")
@@ -812,6 +820,8 @@
(symbol_ref "TARGET_64BIT && TARGET_AVX512BW")
(eq_attr "isa" "nox64") (symbol_ref "!TARGET_64BIT")
(eq_attr "isa" "sse2") (symbol_ref "TARGET_SSE2")
+ (eq_attr "isa" "sse_noavx")
+ (symbol_ref "TARGET_SSE && !TARGET_AVX")
(eq_attr "isa" "sse2_noavx")
(symbol_ref "TARGET_SSE2 && !TARGET_AVX")
(eq_attr "isa" "sse3") (symbol_ref "TARGET_SSE3")
@@ -834,6 +844,15 @@
(eq_attr "isa" "noavx512dq") (symbol_ref "!TARGET_AVX512DQ")
(eq_attr "isa" "avx512vl") (symbol_ref "TARGET_AVX512VL")
(eq_attr "isa" "noavx512vl") (symbol_ref "!TARGET_AVX512VL")
+
+ (eq_attr "mmx_isa" "native")
+ (symbol_ref "!TARGET_MMX_WITH_SSE")
+ (eq_attr "mmx_isa" "sse")
+ (symbol_ref "TARGET_MMX_WITH_SSE")
+ (eq_attr "mmx_isa" "sse_noavx")
+ (symbol_ref "TARGET_MMX_WITH_SSE && !TARGET_AVX")
+ (eq_attr "mmx_isa" "avx")
+ (symbol_ref "TARGET_MMX_WITH_SSE && TARGET_AVX")
]
(const_int 1)))
@@ -933,12 +952,14 @@
(define_code_iterator any_extend [sign_extend zero_extend])
;; Prefix for insn menmonic.
-(define_code_attr sgnprefix [(sign_extend "i") (zero_extend "")])
-
+(define_code_attr sgnprefix [(sign_extend "i") (zero_extend "")
+ (div "i") (udiv "")])
;; Prefix for define_insn
-(define_code_attr u [(sign_extend "") (zero_extend "u")])
(define_code_attr s [(sign_extend "s") (zero_extend "u")])
-(define_code_attr u_bool [(sign_extend "false") (zero_extend "true")])
+(define_code_attr u [(sign_extend "") (zero_extend "u")
+ (div "") (udiv "u")])
+(define_code_attr u_bool [(sign_extend "false") (zero_extend "true")
+ (div "false") (udiv "true")])
;; Used in signed and unsigned truncations.
(define_code_iterator any_truncate [ss_truncate truncate us_truncate])
@@ -999,10 +1020,11 @@
(HI "TARGET_HIMODE_MATH")
SI])
-;; Math-dependant integer modes with DImode.
-(define_mode_iterator SWIM1248x [(QI "TARGET_QIMODE_MATH")
- (HI "TARGET_HIMODE_MATH")
- SI (DI "(TARGET_STV && TARGET_SSE2) || TARGET_64BIT")])
+;; Math-dependant integer modes with DImode (enabled for 32bit with STV).
+(define_mode_iterator SWIM1248s
+ [(QI "TARGET_QIMODE_MATH")
+ (HI "TARGET_HIMODE_MATH")
+ SI (DI "TARGET_64BIT || (TARGET_STV && TARGET_SSE2)")])
;; Math-dependant single word integer modes without QImode.
(define_mode_iterator SWIM248 [(HI "TARGET_HIMODE_MATH")
@@ -1143,6 +1165,10 @@
;; All x87 floating point modes
(define_mode_iterator X87MODEF [SF DF XF])
+;; All SSE floating point modes
+(define_mode_iterator SSEMODEF [SF DF TF])
+(define_mode_attr ssevecmodef [(SF "V4SF") (DF "V2DF") (TF "TF")])
+
;; SSE instruction suffix for various modes
(define_mode_attr ssemodesuffix
[(SF "ss") (DF "sd")
@@ -1244,7 +1270,7 @@
DONE;
})
-(define_expand "cmp<mode>_1"
+(define_expand "@cmp<mode>_1"
[(set (reg:CC FLAGS_REG)
(compare:CC (match_operand:SWI48 0 "nonimmediate_operand")
(match_operand:SWI48 1 "<general_operand>")))])
@@ -3860,6 +3886,10 @@
(const_string "avx512bw")
]
(const_string "*")))
+ (set (attr "mmx_isa")
+ (if_then_else (eq_attr "alternative" "5,6")
+ (const_string "native")
+ (const_string "*")))
(set (attr "type")
(cond [(eq_attr "alternative" "0,1,2,4")
(const_string "multi")
@@ -4049,45 +4079,6 @@
[(set_attr "isa" "*,avx512dq,avx512dq")
(set_attr "type" "imovx,mskmov,mskmov")
(set_attr "mode" "SI,QI,QI")])
-
-(define_insn_and_split "*zext<mode>_doubleword_and"
- [(set (match_operand:DI 0 "register_operand" "=&<r>")
- (zero_extend:DI (match_operand:SWI12 1 "nonimmediate_operand" "<r>m")))]
- "!TARGET_64BIT && TARGET_STV && TARGET_SSE2
- && TARGET_ZERO_EXTEND_WITH_AND && optimize_function_for_speed_p (cfun)"
- "#"
- "&& reload_completed && GENERAL_REG_P (operands[0])"
- [(set (match_dup 2) (const_int 0))]
-{
- split_double_mode (DImode, &operands[0], 1, &operands[0], &operands[2]);
-
- emit_move_insn (operands[0], const0_rtx);
-
- gcc_assert (!TARGET_PARTIAL_REG_STALL);
- emit_insn (gen_movstrict<mode>
- (gen_lowpart (<MODE>mode, operands[0]), operands[1]));
-})
-
-(define_insn_and_split "*zext<mode>_doubleword"
- [(set (match_operand:DI 0 "register_operand" "=r")
- (zero_extend:DI (match_operand:SWI12 1 "nonimmediate_operand" "<r>m")))]
- "!TARGET_64BIT && TARGET_STV && TARGET_SSE2
- && !(TARGET_ZERO_EXTEND_WITH_AND && optimize_function_for_speed_p (cfun))"
- "#"
- "&& reload_completed && GENERAL_REG_P (operands[0])"
- [(set (match_dup 0) (zero_extend:SI (match_dup 1)))
- (set (match_dup 2) (const_int 0))]
- "split_double_mode (DImode, &operands[0], 1, &operands[0], &operands[2]);")
-
-(define_insn_and_split "*zextsi_doubleword"
- [(set (match_operand:DI 0 "register_operand" "=r")
- (zero_extend:DI (match_operand:SI 1 "nonimmediate_operand" "rm")))]
- "!TARGET_64BIT && TARGET_STV && TARGET_SSE2"
- "#"
- "&& reload_completed && GENERAL_REG_P (operands[0])"
- [(set (match_dup 0) (match_dup 1))
- (set (match_dup 2) (const_int 0))]
- "split_double_mode (DImode, &operands[0], 1, &operands[0], &operands[2]);")
;; Sign extension instructions
@@ -5117,12 +5108,12 @@
})
(define_insn_and_split "floatdi<X87MODEF:mode>2_i387_with_xmm"
- [(set (match_operand:X87MODEF 0 "register_operand" "=f")
+ [(set (match_operand:X87MODEF 0 "register_operand" "=f,f")
(float:X87MODEF
- (match_operand:DI 1 "register_operand" "r")))
- (clobber (match_scratch:V4SI 3 "=x"))
- (clobber (match_scratch:V4SI 4 "=x"))
- (clobber (match_operand:DI 2 "memory_operand" "=m"))]
+ (match_operand:DI 1 "register_operand" "r,r")))
+ (clobber (match_operand:DI 2 "memory_operand" "=m,m"))
+ (clobber (match_scratch:V4SI 3 "=x,x"))
+ (clobber (match_scratch:V4SI 4 "=X,x"))]
"!TARGET_64BIT && TARGET_INTER_UNIT_MOVES_TO_VEC
&& TARGET_80387 && X87_ENABLE_FLOAT (<X87MODEF:MODE>mode, DImode)
&& TARGET_SSE2 && optimize_function_for_speed_p (cfun)"
@@ -5135,14 +5126,21 @@
Assemble the 64-bit DImode value in an xmm register. */
emit_insn (gen_sse2_loadld (operands[3], CONST0_RTX (V4SImode),
gen_lowpart (SImode, operands[1])));
- emit_insn (gen_sse2_loadld (operands[4], CONST0_RTX (V4SImode),
- gen_highpart (SImode, operands[1])));
- emit_insn (gen_vec_interleave_lowv4si (operands[3], operands[3],
- operands[4]));
-
+ if (TARGET_SSE4_1)
+ emit_insn (gen_sse4_1_pinsrd (operands[3], operands[3],
+ gen_highpart (SImode, operands[1]),
+ GEN_INT (2)));
+ else
+ {
+ emit_insn (gen_sse2_loadld (operands[4], CONST0_RTX (V4SImode),
+ gen_highpart (SImode, operands[1])));
+ emit_insn (gen_vec_interleave_lowv4si (operands[3], operands[3],
+ operands[4]));
+ }
operands[3] = gen_lowpart (DImode, operands[3]);
}
- [(set_attr "type" "multi")
+ [(set_attr "isa" "sse4,*")
+ (set_attr "type" "multi")
(set_attr "mode" "<X87MODEF:MODE>")
(set_attr "unit" "i387")
(set_attr "fp_int_src" "true")])
@@ -6507,7 +6505,7 @@
;; Add with carry and subtract with borrow
-(define_insn "add<mode>3_carry"
+(define_insn "@add<mode>3_carry"
[(set (match_operand:SWI 0 "nonimmediate_operand" "=<r>m,<r>")
(plus:SWI
(plus:SWI
@@ -6607,7 +6605,7 @@
(plus:SWI48 (match_dup 1) (match_dup 2)))])]
"ix86_binary_operator_ok (PLUS, <MODE>mode, operands)")
-(define_insn "sub<mode>3_carry"
+(define_insn "@sub<mode>3_carry"
[(set (match_operand:SWI 0 "nonimmediate_operand" "=<r>m,<r>")
(minus:SWI
(minus:SWI
@@ -6669,7 +6667,7 @@
(set_attr "pent_pair" "pu")
(set_attr "mode" "SI")])
-(define_insn "sub<mode>3_carry_ccc"
+(define_insn "@sub<mode>3_carry_ccc"
[(set (reg:CCC FLAGS_REG)
(compare:CCC
(zero_extend:<DWI> (match_operand:DWIH 1 "register_operand" "0"))
@@ -6703,7 +6701,7 @@
;; (compare (match_dup 1) (plus:DWIH (ltu:DWIH ...) (match_dup 2)))
;; result, the overflow flag likewise, but the overflow flag is also
;; set if the (plus:DWIH (ltu:DWIH ...) (match_dup 2)) overflows.
-(define_insn "sub<mode>3_carry_ccgz"
+(define_insn "@sub<mode>3_carry_ccgz"
[(set (reg:CCGZ FLAGS_REG)
(unspec:CCGZ [(match_operand:DWIH 1 "register_operand" "0")
(match_operand:DWIH 2 "x86_64_general_operand" "rme")
@@ -7468,13 +7466,16 @@
;; Divmod instructions.
-(define_expand "divmod<mode>4"
+(define_code_iterator any_div [div udiv])
+(define_code_attr paired_mod [(div "mod") (udiv "umod")])
+
+(define_expand "<u>divmod<mode>4"
[(parallel [(set (match_operand:SWIM248 0 "register_operand")
- (div:SWIM248
+ (any_div:SWIM248
(match_operand:SWIM248 1 "register_operand")
(match_operand:SWIM248 2 "nonimmediate_operand")))
(set (match_operand:SWIM248 3 "register_operand")
- (mod:SWIM248 (match_dup 1) (match_dup 2)))
+ (<paired_mod>:SWIM248 (match_dup 1) (match_dup 2)))
(clobber (reg:CC FLAGS_REG))])])
;; Split with 8bit unsigned divide:
@@ -7484,47 +7485,49 @@
;; use original integer divide
(define_split
[(set (match_operand:SWI48 0 "register_operand")
- (div:SWI48 (match_operand:SWI48 2 "register_operand")
- (match_operand:SWI48 3 "nonimmediate_operand")))
+ (any_div:SWI48 (match_operand:SWI48 2 "register_operand")
+ (match_operand:SWI48 3 "nonimmediate_operand")))
(set (match_operand:SWI48 1 "register_operand")
- (mod:SWI48 (match_dup 2) (match_dup 3)))
+ (<paired_mod>:SWI48 (match_dup 2) (match_dup 3)))
(clobber (reg:CC FLAGS_REG))]
"TARGET_USE_8BIT_IDIV
&& TARGET_QIMODE_MATH
&& can_create_pseudo_p ()
&& !optimize_insn_for_size_p ()"
[(const_int 0)]
- "ix86_split_idivmod (<MODE>mode, operands, true); DONE;")
+ "ix86_split_idivmod (<MODE>mode, operands, <u_bool>); DONE;")
(define_split
[(set (match_operand:DI 0 "register_operand")
(zero_extend:DI
- (div:SI (match_operand:SI 2 "register_operand")
- (match_operand:SI 3 "nonimmediate_operand"))))
+ (any_div:SI (match_operand:SI 2 "register_operand")
+ (match_operand:SI 3 "nonimmediate_operand"))))
(set (match_operand:SI 1 "register_operand")
- (mod:SI (match_dup 2) (match_dup 3)))
+ (<paired_mod>:SI (match_dup 2) (match_dup 3)))
(clobber (reg:CC FLAGS_REG))]
- "TARGET_USE_8BIT_IDIV
+ "TARGET_64BIT
+ && TARGET_USE_8BIT_IDIV
&& TARGET_QIMODE_MATH
&& can_create_pseudo_p ()
&& !optimize_insn_for_size_p ()"
[(const_int 0)]
- "ix86_split_idivmod (SImode, operands, true); DONE;")
+ "ix86_split_idivmod (SImode, operands, <u_bool>); DONE;")
(define_split
[(set (match_operand:DI 1 "register_operand")
(zero_extend:DI
- (mod:SI (match_operand:SI 2 "register_operand")
- (match_operand:SI 3 "nonimmediate_operand"))))
+ (<paired_mod>:SI (match_operand:SI 2 "register_operand")
+ (match_operand:SI 3 "nonimmediate_operand"))))
(set (match_operand:SI 0 "register_operand")
- (div:SI (match_dup 2) (match_dup 3)))
+ (any_div:SI (match_dup 2) (match_dup 3)))
(clobber (reg:CC FLAGS_REG))]
- "TARGET_USE_8BIT_IDIV
+ "TARGET_64BIT
+ && TARGET_USE_8BIT_IDIV
&& TARGET_QIMODE_MATH
&& can_create_pseudo_p ()
&& !optimize_insn_for_size_p ()"
[(const_int 0)]
- "ix86_split_idivmod (SImode, operands, true); DONE;")
+ "ix86_split_idivmod (SImode, operands, <u_bool>); DONE;")
(define_insn_and_split "divmod<mode>4_1"
[(set (match_operand:SWI48 0 "register_operand" "=a")
@@ -7561,6 +7564,28 @@
[(set_attr "type" "multi")
(set_attr "mode" "<MODE>")])
+(define_insn_and_split "udivmod<mode>4_1"
+ [(set (match_operand:SWI48 0 "register_operand" "=a")
+ (udiv:SWI48 (match_operand:SWI48 2 "register_operand" "0")
+ (match_operand:SWI48 3 "nonimmediate_operand" "rm")))
+ (set (match_operand:SWI48 1 "register_operand" "=&d")
+ (umod:SWI48 (match_dup 2) (match_dup 3)))
+ (unspec [(const_int 0)] UNSPEC_DIV_ALREADY_SPLIT)
+ (clobber (reg:CC FLAGS_REG))]
+ ""
+ "#"
+ "reload_completed"
+ [(set (match_dup 1) (const_int 0))
+ (parallel [(set (match_dup 0)
+ (udiv:SWI48 (match_dup 2) (match_dup 3)))
+ (set (match_dup 1)
+ (umod:SWI48 (match_dup 2) (match_dup 3)))
+ (use (match_dup 1))
+ (clobber (reg:CC FLAGS_REG))])]
+ ""
+ [(set_attr "type" "multi")
+ (set_attr "mode" "<MODE>")])
+
(define_insn_and_split "divmodsi4_zext_1"
[(set (match_operand:DI 0 "register_operand" "=a")
(zero_extend:DI
@@ -7572,7 +7597,7 @@
(clobber (reg:CC FLAGS_REG))]
"TARGET_64BIT"
"#"
- "reload_completed"
+ "&& reload_completed"
[(parallel [(set (match_dup 1)
(ashiftrt:SI (match_dup 4) (match_dup 5)))
(clobber (reg:CC FLAGS_REG))])
@@ -7597,6 +7622,29 @@
[(set_attr "type" "multi")
(set_attr "mode" "SI")])
+(define_insn_and_split "udivmodsi4_zext_1"
+ [(set (match_operand:DI 0 "register_operand" "=a")
+ (zero_extend:DI
+ (udiv:SI (match_operand:SI 2 "register_operand" "0")
+ (match_operand:SI 3 "nonimmediate_operand" "rm"))))
+ (set (match_operand:SI 1 "register_operand" "=&d")
+ (umod:SI (match_dup 2) (match_dup 3)))
+ (unspec [(const_int 0)] UNSPEC_DIV_ALREADY_SPLIT)
+ (clobber (reg:CC FLAGS_REG))]
+ "TARGET_64BIT"
+ "#"
+ "&& reload_completed"
+ [(set (match_dup 1) (const_int 0))
+ (parallel [(set (match_dup 0)
+ (zero_extend:DI (udiv:SI (match_dup 2) (match_dup 3))))
+ (set (match_dup 1)
+ (umod:SI (match_dup 2) (match_dup 3)))
+ (use (match_dup 1))
+ (clobber (reg:CC FLAGS_REG))])]
+ ""
+ [(set_attr "type" "multi")
+ (set_attr "mode" "SI")])
+
(define_insn_and_split "divmodsi4_zext_2"
[(set (match_operand:DI 1 "register_operand" "=&d")
(zero_extend:DI
@@ -7608,7 +7656,7 @@
(clobber (reg:CC FLAGS_REG))]
"TARGET_64BIT"
"#"
- "reload_completed"
+ "&& reload_completed"
[(parallel [(set (match_dup 6)
(ashiftrt:SI (match_dup 4) (match_dup 5)))
(clobber (reg:CC FLAGS_REG))])
@@ -7634,6 +7682,29 @@
[(set_attr "type" "multi")
(set_attr "mode" "SI")])
+(define_insn_and_split "udivmodsi4_zext_2"
+ [(set (match_operand:DI 1 "register_operand" "=&d")
+ (zero_extend:DI
+ (umod:SI (match_operand:SI 2 "register_operand" "0")
+ (match_operand:SI 3 "nonimmediate_operand" "rm"))))
+ (set (match_operand:SI 0 "register_operand" "=a")
+ (udiv:SI (match_dup 2) (match_dup 3)))
+ (unspec [(const_int 0)] UNSPEC_DIV_ALREADY_SPLIT)
+ (clobber (reg:CC FLAGS_REG))]
+ "TARGET_64BIT"
+ "#"
+ "&& reload_completed"
+ [(set (match_dup 4) (const_int 0))
+ (parallel [(set (match_dup 1)
+ (zero_extend:DI (umod:SI (match_dup 2) (match_dup 3))))
+ (set (match_dup 0)
+ (udiv:SI (match_dup 2) (match_dup 3)))
+ (use (match_dup 4))
+ (clobber (reg:CC FLAGS_REG))])]
+ "operands[4] = gen_lowpart (SImode, operands[1]);"
+ [(set_attr "type" "multi")
+ (set_attr "mode" "SI")])
+
(define_insn_and_split "*divmod<mode>4"
[(set (match_operand:SWIM248 0 "register_operand" "=a")
(div:SWIM248 (match_operand:SWIM248 2 "register_operand" "0")
@@ -7669,6 +7740,52 @@
[(set_attr "type" "multi")
(set_attr "mode" "<MODE>")])
+(define_insn_and_split "*udivmod<mode>4"
+ [(set (match_operand:SWIM248 0 "register_operand" "=a")
+ (udiv:SWIM248 (match_operand:SWIM248 2 "register_operand" "0")
+ (match_operand:SWIM248 3 "nonimmediate_operand" "rm")))
+ (set (match_operand:SWIM248 1 "register_operand" "=&d")
+ (umod:SWIM248 (match_dup 2) (match_dup 3)))
+ (clobber (reg:CC FLAGS_REG))]
+ ""
+ "#"
+ "reload_completed"
+ [(set (match_dup 1) (const_int 0))
+ (parallel [(set (match_dup 0)
+ (udiv:SWIM248 (match_dup 2) (match_dup 3)))
+ (set (match_dup 1)
+ (umod:SWIM248 (match_dup 2) (match_dup 3)))
+ (use (match_dup 1))
+ (clobber (reg:CC FLAGS_REG))])]
+ ""
+ [(set_attr "type" "multi")
+ (set_attr "mode" "<MODE>")])
+
+;; Optimize division or modulo by constant power of 2, if the constant
+;; materializes only after expansion.
+(define_insn_and_split "*udivmod<mode>4_pow2"
+ [(set (match_operand:SWI48 0 "register_operand" "=r")
+ (udiv:SWI48 (match_operand:SWI48 2 "register_operand" "0")
+ (match_operand:SWI48 3 "const_int_operand" "n")))
+ (set (match_operand:SWI48 1 "register_operand" "=r")
+ (umod:SWI48 (match_dup 2) (match_dup 3)))
+ (clobber (reg:CC FLAGS_REG))]
+ "IN_RANGE (exact_log2 (UINTVAL (operands[3])), 1, 31)"
+ "#"
+ "&& reload_completed"
+ [(set (match_dup 1) (match_dup 2))
+ (parallel [(set (match_dup 0) (lshiftrt:<MODE> (match_dup 2) (match_dup 4)))
+ (clobber (reg:CC FLAGS_REG))])
+ (parallel [(set (match_dup 1) (and:<MODE> (match_dup 1) (match_dup 5)))
+ (clobber (reg:CC FLAGS_REG))])]
+{
+ int v = exact_log2 (UINTVAL (operands[3]));
+ operands[4] = GEN_INT (v);
+ operands[5] = GEN_INT ((HOST_WIDE_INT_1U << v) - 1);
+}
+ [(set_attr "type" "multi")
+ (set_attr "mode" "<MODE>")])
+
(define_insn_and_split "*divmodsi4_zext_1"
[(set (match_operand:DI 0 "register_operand" "=a")
(zero_extend:DI
@@ -7679,7 +7796,7 @@
(clobber (reg:CC FLAGS_REG))]
"TARGET_64BIT"
"#"
- "reload_completed"
+ "&& reload_completed"
[(parallel [(set (match_dup 1)
(ashiftrt:SI (match_dup 4) (match_dup 5)))
(clobber (reg:CC FLAGS_REG))])
@@ -7704,313 +7821,87 @@
[(set_attr "type" "multi")
(set_attr "mode" "SI")])
-(define_insn_and_split "*divmodsi4_zext_2"
- [(set (match_operand:DI 1 "register_operand" "=&d")
- (zero_extend:DI
- (mod:SI (match_operand:SI 2 "register_operand" "0")
- (match_operand:SI 3 "nonimmediate_operand" "rm"))))
- (set (match_operand:SI 0 "register_operand" "=a")
- (div:SI (match_dup 2) (match_dup 3)))
- (clobber (reg:CC FLAGS_REG))]
- "TARGET_64BIT"
- "#"
- "reload_completed"
- [(parallel [(set (match_dup 6)
- (ashiftrt:SI (match_dup 4) (match_dup 5)))
- (clobber (reg:CC FLAGS_REG))])
- (parallel [(set (match_dup 1)
- (zero_extend:DI (mod:SI (match_dup 2) (match_dup 3))))
- (set (match_dup 0)
- (div:SI (match_dup 2) (match_dup 3)))
- (use (match_dup 6))
- (clobber (reg:CC FLAGS_REG))])]
-{
- operands[5] = GEN_INT (GET_MODE_BITSIZE (SImode)-1);
- operands[6] = gen_lowpart (SImode, operands[1]);
-
- if (optimize_function_for_size_p (cfun) || TARGET_USE_CLTD)
- operands[4] = operands[2];
- else
- {
- /* Avoid use of cltd in favor of a mov+shift. */
- emit_move_insn (operands[6], operands[2]);
- operands[4] = operands[6];
- }
-}
- [(set_attr "type" "multi")
- (set_attr "mode" "SI")])
-
-(define_insn "*divmod<mode>4_noext"
- [(set (match_operand:SWIM248 0 "register_operand" "=a")
- (div:SWIM248 (match_operand:SWIM248 2 "register_operand" "0")
- (match_operand:SWIM248 3 "nonimmediate_operand" "rm")))
- (set (match_operand:SWIM248 1 "register_operand" "=d")
- (mod:SWIM248 (match_dup 2) (match_dup 3)))
- (use (match_operand:SWIM248 4 "register_operand" "1"))
- (clobber (reg:CC FLAGS_REG))]
- ""
- "idiv{<imodesuffix>}\t%3"
- [(set_attr "type" "idiv")
- (set_attr "mode" "<MODE>")])
-
-(define_insn "*divmodsi4_noext_zext_1"
+(define_insn_and_split "*udivmodsi4_zext_1"
[(set (match_operand:DI 0 "register_operand" "=a")
(zero_extend:DI
- (div:SI (match_operand:SI 2 "register_operand" "0")
- (match_operand:SI 3 "nonimmediate_operand" "rm"))))
- (set (match_operand:SI 1 "register_operand" "=d")
- (mod:SI (match_dup 2) (match_dup 3)))
- (use (match_operand:SI 4 "register_operand" "1"))
- (clobber (reg:CC FLAGS_REG))]
- "TARGET_64BIT"
- "idiv{l}\t%3"
- [(set_attr "type" "idiv")
- (set_attr "mode" "SI")])
-
-(define_insn "*divmodsi4_noext_zext_2"
- [(set (match_operand:DI 1 "register_operand" "=d")
- (zero_extend:DI
- (mod:SI (match_operand:SI 2 "register_operand" "0")
- (match_operand:SI 3 "nonimmediate_operand" "rm"))))
- (set (match_operand:SI 0 "register_operand" "=a")
- (div:SI (match_dup 2) (match_dup 3)))
- (use (match_operand:SI 4 "register_operand" "1"))
- (clobber (reg:CC FLAGS_REG))]
- "TARGET_64BIT"
- "idiv{l}\t%3"
- [(set_attr "type" "idiv")
- (set_attr "mode" "SI")])
-
-(define_expand "divmodqi4"
- [(parallel [(set (match_operand:QI 0 "register_operand")
- (div:QI
- (match_operand:QI 1 "register_operand")
- (match_operand:QI 2 "nonimmediate_operand")))
- (set (match_operand:QI 3 "register_operand")
- (mod:QI (match_dup 1) (match_dup 2)))
- (clobber (reg:CC FLAGS_REG))])]
- "TARGET_QIMODE_MATH"
-{
- rtx div, mod;
- rtx tmp0, tmp1;
-
- tmp0 = gen_reg_rtx (HImode);
- tmp1 = gen_reg_rtx (HImode);
-
- /* Extend operands[1] to HImode. Generate 8bit divide. Result is in AX. */
- emit_insn (gen_extendqihi2 (tmp1, operands[1]));
- emit_insn (gen_divmodhiqi3 (tmp0, tmp1, operands[2]));
-
- /* Extract remainder from AH. */
- tmp1 = gen_rtx_ZERO_EXTRACT (SImode, tmp0, GEN_INT (8), GEN_INT (8));
- tmp1 = lowpart_subreg (QImode, tmp1, SImode);
- rtx_insn *insn = emit_move_insn (operands[3], tmp1);
-
- mod = gen_rtx_MOD (QImode, operands[1], operands[2]);
- set_unique_reg_note (insn, REG_EQUAL, mod);
-
- /* Extract quotient from AL. */
- insn = emit_move_insn (operands[0], gen_lowpart (QImode, tmp0));
-
- div = gen_rtx_DIV (QImode, operands[1], operands[2]);
- set_unique_reg_note (insn, REG_EQUAL, div);
-
- DONE;
-})
-
-;; Divide AX by r/m8, with result stored in
-;; AL <- Quotient
-;; AH <- Remainder
-;; Change div/mod to HImode and extend the second argument to HImode
-;; so that mode of div/mod matches with mode of arguments. Otherwise
-;; combine may fail.
-(define_insn "divmodhiqi3"
- [(set (match_operand:HI 0 "register_operand" "=a")
- (ior:HI
- (ashift:HI
- (zero_extend:HI
- (truncate:QI
- (mod:HI (match_operand:HI 1 "register_operand" "0")
- (sign_extend:HI
- (match_operand:QI 2 "nonimmediate_operand" "qm")))))
- (const_int 8))
- (zero_extend:HI
- (truncate:QI
- (div:HI (match_dup 1) (sign_extend:HI (match_dup 2)))))))
- (clobber (reg:CC FLAGS_REG))]
- "TARGET_QIMODE_MATH"
- "idiv{b}\t%2"
- [(set_attr "type" "idiv")
- (set_attr "mode" "QI")])
-
-(define_expand "udivmod<mode>4"
- [(parallel [(set (match_operand:SWIM248 0 "register_operand")
- (udiv:SWIM248
- (match_operand:SWIM248 1 "register_operand")
- (match_operand:SWIM248 2 "nonimmediate_operand")))
- (set (match_operand:SWIM248 3 "register_operand")
- (umod:SWIM248 (match_dup 1) (match_dup 2)))
- (clobber (reg:CC FLAGS_REG))])])
-
-;; Split with 8bit unsigned divide:
-;; if (dividend an divisor are in [0-255])
-;; use 8bit unsigned integer divide
-;; else
-;; use original integer divide
-(define_split
- [(set (match_operand:SWI48 0 "register_operand")
- (udiv:SWI48 (match_operand:SWI48 2 "register_operand")
- (match_operand:SWI48 3 "nonimmediate_operand")))
- (set (match_operand:SWI48 1 "register_operand")
- (umod:SWI48 (match_dup 2) (match_dup 3)))
- (clobber (reg:CC FLAGS_REG))]
- "TARGET_USE_8BIT_IDIV
- && TARGET_QIMODE_MATH
- && can_create_pseudo_p ()
- && !optimize_insn_for_size_p ()"
- [(const_int 0)]
- "ix86_split_idivmod (<MODE>mode, operands, false); DONE;")
-
-(define_split
- [(set (match_operand:DI 0 "register_operand")
- (zero_extend:DI
- (udiv:SI (match_operand:SI 2 "register_operand")
- (match_operand:SI 3 "nonimmediate_operand"))))
- (set (match_operand:SI 1 "register_operand")
+ (udiv:SI (match_operand:SI 2 "register_operand" "0")
+ (match_operand:SI 3 "nonimmediate_operand" "rm"))))
+ (set (match_operand:SI 1 "register_operand" "=&d")
(umod:SI (match_dup 2) (match_dup 3)))
(clobber (reg:CC FLAGS_REG))]
- "TARGET_64BIT
- && TARGET_USE_8BIT_IDIV
- && TARGET_QIMODE_MATH
- && can_create_pseudo_p ()
- && !optimize_insn_for_size_p ()"
- [(const_int 0)]
- "ix86_split_idivmod (SImode, operands, false); DONE;")
-
-(define_split
- [(set (match_operand:DI 1 "register_operand")
- (zero_extend:DI
- (umod:SI (match_operand:SI 2 "register_operand")
- (match_operand:SI 3 "nonimmediate_operand"))))
- (set (match_operand:SI 0 "register_operand")
- (udiv:SI (match_dup 2) (match_dup 3)))
- (clobber (reg:CC FLAGS_REG))]
- "TARGET_64BIT
- && TARGET_USE_8BIT_IDIV
- && TARGET_QIMODE_MATH
- && can_create_pseudo_p ()
- && !optimize_insn_for_size_p ()"
- [(const_int 0)]
- "ix86_split_idivmod (SImode, operands, false); DONE;")
-
-(define_insn_and_split "udivmod<mode>4_1"
- [(set (match_operand:SWI48 0 "register_operand" "=a")
- (udiv:SWI48 (match_operand:SWI48 2 "register_operand" "0")
- (match_operand:SWI48 3 "nonimmediate_operand" "rm")))
- (set (match_operand:SWI48 1 "register_operand" "=&d")
- (umod:SWI48 (match_dup 2) (match_dup 3)))
- (unspec [(const_int 0)] UNSPEC_DIV_ALREADY_SPLIT)
- (clobber (reg:CC FLAGS_REG))]
- ""
+ "TARGET_64BIT"
"#"
- "reload_completed"
+ "&& reload_completed"
[(set (match_dup 1) (const_int 0))
(parallel [(set (match_dup 0)
- (udiv:SWI48 (match_dup 2) (match_dup 3)))
+ (zero_extend:DI (udiv:SI (match_dup 2) (match_dup 3))))
(set (match_dup 1)
- (umod:SWI48 (match_dup 2) (match_dup 3)))
+ (umod:SI (match_dup 2) (match_dup 3)))
(use (match_dup 1))
(clobber (reg:CC FLAGS_REG))])]
""
[(set_attr "type" "multi")
- (set_attr "mode" "<MODE>")])
+ (set_attr "mode" "SI")])
-(define_insn_and_split "udivmodsi4_zext_1"
- [(set (match_operand:DI 0 "register_operand" "=a")
+(define_insn_and_split "*udivmodsi4_pow2_zext_1"
+ [(set (match_operand:DI 0 "register_operand" "=r")
(zero_extend:DI
(udiv:SI (match_operand:SI 2 "register_operand" "0")
- (match_operand:SI 3 "nonimmediate_operand" "rm"))))
- (set (match_operand:SI 1 "register_operand" "=&d")
+ (match_operand:SI 3 "const_int_operand" "n"))))
+ (set (match_operand:SI 1 "register_operand" "=r")
(umod:SI (match_dup 2) (match_dup 3)))
- (unspec [(const_int 0)] UNSPEC_DIV_ALREADY_SPLIT)
(clobber (reg:CC FLAGS_REG))]
- "TARGET_64BIT"
+ "TARGET_64BIT
+ && exact_log2 (UINTVAL (operands[3])) > 0"
"#"
- "reload_completed"
- [(set (match_dup 1) (const_int 0))
+ "&& reload_completed"
+ [(set (match_dup 1) (match_dup 2))
(parallel [(set (match_dup 0)
- (zero_extend:DI (udiv:SI (match_dup 2) (match_dup 3))))
- (set (match_dup 1)
- (umod:SI (match_dup 2) (match_dup 3)))
- (use (match_dup 1))
+ (zero_extend:DI (lshiftrt:SI (match_dup 2) (match_dup 4))))
+ (clobber (reg:CC FLAGS_REG))])
+ (parallel [(set (match_dup 1) (and:SI (match_dup 1) (match_dup 5)))
(clobber (reg:CC FLAGS_REG))])]
- ""
+{
+ int v = exact_log2 (UINTVAL (operands[3]));
+ operands[4] = GEN_INT (v);
+ operands[5] = GEN_INT ((HOST_WIDE_INT_1U << v) - 1);
+}
[(set_attr "type" "multi")
(set_attr "mode" "SI")])
-(define_insn_and_split "udivmodsi4_zext_2"
+(define_insn_and_split "*divmodsi4_zext_2"
[(set (match_operand:DI 1 "register_operand" "=&d")
(zero_extend:DI
- (umod:SI (match_operand:SI 2 "register_operand" "0")
- (match_operand:SI 3 "nonimmediate_operand" "rm"))))
+ (mod:SI (match_operand:SI 2 "register_operand" "0")
+ (match_operand:SI 3 "nonimmediate_operand" "rm"))))
(set (match_operand:SI 0 "register_operand" "=a")
- (udiv:SI (match_dup 2) (match_dup 3)))
- (unspec [(const_int 0)] UNSPEC_DIV_ALREADY_SPLIT)
+ (div:SI (match_dup 2) (match_dup 3)))
(clobber (reg:CC FLAGS_REG))]
"TARGET_64BIT"
"#"
- "reload_completed"
- [(set (match_dup 4) (const_int 0))
+ "&& reload_completed"
+ [(parallel [(set (match_dup 6)
+ (ashiftrt:SI (match_dup 4) (match_dup 5)))
+ (clobber (reg:CC FLAGS_REG))])
(parallel [(set (match_dup 1)
- (zero_extend:DI (umod:SI (match_dup 2) (match_dup 3))))
+ (zero_extend:DI (mod:SI (match_dup 2) (match_dup 3))))
(set (match_dup 0)
- (udiv:SI (match_dup 2) (match_dup 3)))
- (use (match_dup 4))
- (clobber (reg:CC FLAGS_REG))])]
- "operands[4] = gen_lowpart (SImode, operands[1]);"
- [(set_attr "type" "multi")
- (set_attr "mode" "SI")])
-
-(define_insn_and_split "*udivmod<mode>4"
- [(set (match_operand:SWIM248 0 "register_operand" "=a")
- (udiv:SWIM248 (match_operand:SWIM248 2 "register_operand" "0")
- (match_operand:SWIM248 3 "nonimmediate_operand" "rm")))
- (set (match_operand:SWIM248 1 "register_operand" "=&d")
- (umod:SWIM248 (match_dup 2) (match_dup 3)))
- (clobber (reg:CC FLAGS_REG))]
- ""
- "#"
- "reload_completed"
- [(set (match_dup 1) (const_int 0))
- (parallel [(set (match_dup 0)
- (udiv:SWIM248 (match_dup 2) (match_dup 3)))
- (set (match_dup 1)
- (umod:SWIM248 (match_dup 2) (match_dup 3)))
- (use (match_dup 1))
+ (div:SI (match_dup 2) (match_dup 3)))
+ (use (match_dup 6))
(clobber (reg:CC FLAGS_REG))])]
- ""
- [(set_attr "type" "multi")
- (set_attr "mode" "<MODE>")])
+{
+ operands[5] = GEN_INT (GET_MODE_BITSIZE (SImode)-1);
+ operands[6] = gen_lowpart (SImode, operands[1]);
-(define_insn_and_split "*udivmodsi4_zext_1"
- [(set (match_operand:DI 0 "register_operand" "=a")
- (zero_extend:DI
- (udiv:SI (match_operand:SI 2 "register_operand" "0")
- (match_operand:SI 3 "nonimmediate_operand" "rm"))))
- (set (match_operand:SI 1 "register_operand" "=&d")
- (umod:SI (match_dup 2) (match_dup 3)))
- (clobber (reg:CC FLAGS_REG))]
- "TARGET_64BIT"
- "#"
- "reload_completed"
- [(set (match_dup 1) (const_int 0))
- (parallel [(set (match_dup 0)
- (zero_extend:DI (udiv:SI (match_dup 2) (match_dup 3))))
- (set (match_dup 1)
- (umod:SI (match_dup 2) (match_dup 3)))
- (use (match_dup 1))
- (clobber (reg:CC FLAGS_REG))])]
- ""
+ if (optimize_function_for_size_p (cfun) || TARGET_USE_CLTD)
+ operands[4] = operands[2];
+ else
+ {
+ /* Avoid use of cltd in favor of a mov+shift. */
+ emit_move_insn (operands[6], operands[2]);
+ operands[4] = operands[6];
+ }
+}
[(set_attr "type" "multi")
(set_attr "mode" "SI")])
@@ -8024,7 +7915,7 @@
(clobber (reg:CC FLAGS_REG))]
"TARGET_64BIT"
"#"
- "reload_completed"
+ "&& reload_completed"
[(set (match_dup 4) (const_int 0))
(parallel [(set (match_dup 1)
(zero_extend:DI (umod:SI (match_dup 2) (match_dup 3))))
@@ -8036,59 +7927,6 @@
[(set_attr "type" "multi")
(set_attr "mode" "SI")])
-;; Optimize division or modulo by constant power of 2, if the constant
-;; materializes only after expansion.
-(define_insn_and_split "*udivmod<mode>4_pow2"
- [(set (match_operand:SWI48 0 "register_operand" "=r")
- (udiv:SWI48 (match_operand:SWI48 2 "register_operand" "0")
- (match_operand:SWI48 3 "const_int_operand" "n")))
- (set (match_operand:SWI48 1 "register_operand" "=r")
- (umod:SWI48 (match_dup 2) (match_dup 3)))
- (clobber (reg:CC FLAGS_REG))]
- "IN_RANGE (INTVAL (operands[3]), 2, HOST_WIDE_INT_UC (0x80000000))
- && (UINTVAL (operands[3]) & (UINTVAL (operands[3]) - 1)) == 0"
- "#"
- "&& 1"
- [(set (match_dup 1) (match_dup 2))
- (parallel [(set (match_dup 0) (lshiftrt:<MODE> (match_dup 2) (match_dup 4)))
- (clobber (reg:CC FLAGS_REG))])
- (parallel [(set (match_dup 1) (and:<MODE> (match_dup 1) (match_dup 5)))
- (clobber (reg:CC FLAGS_REG))])]
-{
- int v = exact_log2 (UINTVAL (operands[3]));
- operands[4] = GEN_INT (v);
- operands[5] = GEN_INT ((HOST_WIDE_INT_1U << v) - 1);
-}
- [(set_attr "type" "multi")
- (set_attr "mode" "<MODE>")])
-
-(define_insn_and_split "*udivmodsi4_pow2_zext_1"
- [(set (match_operand:DI 0 "register_operand" "=r")
- (zero_extend:DI
- (udiv:SI (match_operand:SI 2 "register_operand" "0")
- (match_operand:SI 3 "const_int_operand" "n"))))
- (set (match_operand:SI 1 "register_operand" "=r")
- (umod:SI (match_dup 2) (match_dup 3)))
- (clobber (reg:CC FLAGS_REG))]
- "TARGET_64BIT
- && IN_RANGE (INTVAL (operands[3]), 2, HOST_WIDE_INT_UC (0x80000000))
- && (UINTVAL (operands[3]) & (UINTVAL (operands[3]) - 1)) == 0"
- "#"
- "&& 1"
- [(set (match_dup 1) (match_dup 2))
- (parallel [(set (match_dup 0)
- (zero_extend:DI (lshiftrt:SI (match_dup 2) (match_dup 4))))
- (clobber (reg:CC FLAGS_REG))])
- (parallel [(set (match_dup 1) (and:SI (match_dup 1) (match_dup 5)))
- (clobber (reg:CC FLAGS_REG))])]
-{
- int v = exact_log2 (UINTVAL (operands[3]));
- operands[4] = GEN_INT (v);
- operands[5] = GEN_INT ((HOST_WIDE_INT_1U << v) - 1);
-}
- [(set_attr "type" "multi")
- (set_attr "mode" "SI")])
-
(define_insn_and_split "*udivmodsi4_pow2_zext_2"
[(set (match_operand:DI 1 "register_operand" "=r")
(zero_extend:DI
@@ -8098,10 +7936,9 @@
(umod:SI (match_dup 2) (match_dup 3)))
(clobber (reg:CC FLAGS_REG))]
"TARGET_64BIT
- && IN_RANGE (INTVAL (operands[3]), 2, HOST_WIDE_INT_UC (0x80000000))
- && (UINTVAL (operands[3]) & (UINTVAL (operands[3]) - 1)) == 0"
+ && exact_log2 (UINTVAL (operands[3])) > 0"
"#"
- "&& 1"
+ "&& reload_completed"
[(set (match_dup 1) (match_dup 2))
(parallel [(set (match_dup 0) (lshiftrt:SI (match_dup 2) (match_dup 4)))
(clobber (reg:CC FLAGS_REG))])
@@ -8116,47 +7953,85 @@
[(set_attr "type" "multi")
(set_attr "mode" "SI")])
-(define_insn "*udivmod<mode>4_noext"
+(define_insn "*<u>divmod<mode>4_noext"
[(set (match_operand:SWIM248 0 "register_operand" "=a")
- (udiv:SWIM248 (match_operand:SWIM248 2 "register_operand" "0")
- (match_operand:SWIM248 3 "nonimmediate_operand" "rm")))
+ (any_div:SWIM248
+ (match_operand:SWIM248 2 "register_operand" "0")
+ (match_operand:SWIM248 3 "nonimmediate_operand" "rm")))
(set (match_operand:SWIM248 1 "register_operand" "=d")
- (umod:SWIM248 (match_dup 2) (match_dup 3)))
+ (<paired_mod>:SWIM248 (match_dup 2) (match_dup 3)))
(use (match_operand:SWIM248 4 "register_operand" "1"))
(clobber (reg:CC FLAGS_REG))]
""
- "div{<imodesuffix>}\t%3"
+ "<sgnprefix>div{<imodesuffix>}\t%3"
[(set_attr "type" "idiv")
(set_attr "mode" "<MODE>")])
-(define_insn "*udivmodsi4_noext_zext_1"
+(define_insn "*<u>divmodsi4_noext_zext_1"
[(set (match_operand:DI 0 "register_operand" "=a")
(zero_extend:DI
- (udiv:SI (match_operand:SI 2 "register_operand" "0")
- (match_operand:SI 3 "nonimmediate_operand" "rm"))))
+ (any_div:SI (match_operand:SI 2 "register_operand" "0")
+ (match_operand:SI 3 "nonimmediate_operand" "rm"))))
(set (match_operand:SI 1 "register_operand" "=d")
- (umod:SI (match_dup 2) (match_dup 3)))
+ (<paired_mod>:SI (match_dup 2) (match_dup 3)))
(use (match_operand:SI 4 "register_operand" "1"))
(clobber (reg:CC FLAGS_REG))]
"TARGET_64BIT"
- "div{l}\t%3"
+ "<sgnprefix>div{l}\t%3"
[(set_attr "type" "idiv")
(set_attr "mode" "SI")])
-(define_insn "*udivmodsi4_noext_zext_2"
+(define_insn "*<u>divmodsi4_noext_zext_2"
[(set (match_operand:DI 1 "register_operand" "=d")
(zero_extend:DI
- (umod:SI (match_operand:SI 2 "register_operand" "0")
- (match_operand:SI 3 "nonimmediate_operand" "rm"))))
+ (<paired_mod>:SI (match_operand:SI 2 "register_operand" "0")
+ (match_operand:SI 3 "nonimmediate_operand" "rm"))))
(set (match_operand:SI 0 "register_operand" "=a")
- (udiv:SI (match_dup 2) (match_dup 3)))
+ (any_div:SI (match_dup 2) (match_dup 3)))
(use (match_operand:SI 4 "register_operand" "1"))
(clobber (reg:CC FLAGS_REG))]
"TARGET_64BIT"
- "div{l}\t%3"
+ "<sgnprefix>div{l}\t%3"
[(set_attr "type" "idiv")
(set_attr "mode" "SI")])
+(define_expand "divmodqi4"
+ [(parallel [(set (match_operand:QI 0 "register_operand")
+ (div:QI
+ (match_operand:QI 1 "register_operand")
+ (match_operand:QI 2 "nonimmediate_operand")))
+ (set (match_operand:QI 3 "register_operand")
+ (mod:QI (match_dup 1) (match_dup 2)))
+ (clobber (reg:CC FLAGS_REG))])]
+ "TARGET_QIMODE_MATH"
+{
+ rtx div, mod;
+ rtx tmp0, tmp1;
+
+ tmp0 = gen_reg_rtx (HImode);
+ tmp1 = gen_reg_rtx (HImode);
+
+ /* Extend operands[1] to HImode. Generate 8bit divide. Result is in AX. */
+ emit_insn (gen_extendqihi2 (tmp1, operands[1]));
+ emit_insn (gen_divmodhiqi3 (tmp0, tmp1, operands[2]));
+
+ /* Extract remainder from AH. */
+ tmp1 = gen_rtx_ZERO_EXTRACT (SImode, tmp0, GEN_INT (8), GEN_INT (8));
+ tmp1 = lowpart_subreg (QImode, tmp1, SImode);
+ rtx_insn *insn = emit_move_insn (operands[3], tmp1);
+
+ mod = gen_rtx_MOD (QImode, operands[1], operands[2]);
+ set_unique_reg_note (insn, REG_EQUAL, mod);
+
+ /* Extract quotient from AL. */
+ insn = emit_move_insn (operands[0], gen_lowpart (QImode, tmp0));
+
+ div = gen_rtx_DIV (QImode, operands[1], operands[2]);
+ set_unique_reg_note (insn, REG_EQUAL, div);
+
+ DONE;
+})
+
(define_expand "udivmodqi4"
[(parallel [(set (match_operand:QI 0 "register_operand")
(udiv:QI
@@ -8169,7 +8044,7 @@
{
rtx div, mod;
rtx tmp0, tmp1;
-
+
tmp0 = gen_reg_rtx (HImode);
tmp1 = gen_reg_rtx (HImode);
@@ -8194,22 +8069,28 @@
DONE;
})
-(define_insn "udivmodhiqi3"
+;; Divide AX by r/m8, with result stored in
+;; AL <- Quotient
+;; AH <- Remainder
+;; Change div/mod to HImode and extend the second argument to HImode
+;; so that mode of div/mod matches with mode of arguments. Otherwise
+;; combine may fail.
+(define_insn "<u>divmodhiqi3"
[(set (match_operand:HI 0 "register_operand" "=a")
(ior:HI
(ashift:HI
(zero_extend:HI
(truncate:QI
(mod:HI (match_operand:HI 1 "register_operand" "0")
- (zero_extend:HI
+ (any_extend:HI
(match_operand:QI 2 "nonimmediate_operand" "qm")))))
(const_int 8))
(zero_extend:HI
(truncate:QI
- (div:HI (match_dup 1) (zero_extend:HI (match_dup 2)))))))
+ (div:HI (match_dup 1) (any_extend:HI (match_dup 2)))))))
(clobber (reg:CC FLAGS_REG))]
"TARGET_QIMODE_MATH"
- "div{b}\t%2"
+ "<sgnprefix>div{b}\t%2"
[(set_attr "type" "idiv")
(set_attr "mode" "QI")])
@@ -8477,80 +8358,69 @@
;; it should be done with splitters.
(define_expand "and<mode>3"
- [(set (match_operand:SWIM1248x 0 "nonimmediate_operand")
- (and:SWIM1248x (match_operand:SWIM1248x 1 "nonimmediate_operand")
- (match_operand:SWIM1248x 2 "<general_szext_operand>")))]
+ [(set (match_operand:SWIM1248s 0 "nonimmediate_operand")
+ (and:SWIM1248s (match_operand:SWIM1248s 1 "nonimmediate_operand")
+ (match_operand:SWIM1248s 2 "<general_szext_operand>")))]
""
{
machine_mode mode = <MODE>mode;
- rtx (*insn) (rtx, rtx);
- if (CONST_INT_P (operands[2]) && REG_P (operands[0]))
+ if (<MODE>mode == DImode && !TARGET_64BIT)
+ ;
+ else if (const_int_operand (operands[2], <MODE>mode)
+ && register_operand (operands[0], <MODE>mode)
+ && !(TARGET_ZERO_EXTEND_WITH_AND
+ && optimize_function_for_speed_p (cfun)))
{
- HOST_WIDE_INT ival = INTVAL (operands[2]);
+ unsigned HOST_WIDE_INT ival = UINTVAL (operands[2]);
- if (ival == (HOST_WIDE_INT) 0xffffffff)
+ if (ival == GET_MODE_MASK (SImode))
mode = SImode;
- else if (ival == 0xffff)
+ else if (ival == GET_MODE_MASK (HImode))
mode = HImode;
- else if (ival == 0xff)
+ else if (ival == GET_MODE_MASK (QImode))
mode = QImode;
- }
-
- if (mode == <MODE>mode)
- {
- ix86_expand_binary_operator (AND, <MODE>mode, operands);
- DONE;
}
- if (<MODE>mode == DImode)
- insn = (mode == SImode)
- ? gen_zero_extendsidi2
- : (mode == HImode)
- ? gen_zero_extendhidi2
- : gen_zero_extendqidi2;
- else if (<MODE>mode == SImode)
- insn = (mode == HImode)
- ? gen_zero_extendhisi2
- : gen_zero_extendqisi2;
- else if (<MODE>mode == HImode)
- insn = gen_zero_extendqihi2;
+ if (mode != <MODE>mode)
+ emit_insn (gen_extend_insn
+ (operands[0], gen_lowpart (mode, operands[1]),
+ <MODE>mode, mode, 1));
else
- gcc_unreachable ();
+ ix86_expand_binary_operator (AND, <MODE>mode, operands);
- emit_insn (insn (operands[0], gen_lowpart (mode, operands[1])));
DONE;
})
(define_insn_and_split "*anddi3_doubleword"
- [(set (match_operand:DI 0 "nonimmediate_operand" "=r,rm,r")
+ [(set (match_operand:DI 0 "nonimmediate_operand")
(and:DI
- (match_operand:DI 1 "nonimmediate_operand" "%0,0,0")
- (match_operand:DI 2 "x86_64_szext_general_operand" "Z,re,rm")))
+ (match_operand:DI 1 "nonimmediate_operand")
+ (match_operand:DI 2 "x86_64_szext_general_operand")))
(clobber (reg:CC FLAGS_REG))]
"!TARGET_64BIT && TARGET_STV && TARGET_SSE2
- && ix86_binary_operator_ok (AND, DImode, operands)"
+ && ix86_binary_operator_ok (AND, DImode, operands)
+ && can_create_pseudo_p ()"
"#"
- "&& reload_completed"
+ "&& 1"
[(const_int 0)]
{
split_double_mode (DImode, &operands[0], 3, &operands[0], &operands[3]);
+
if (operands[2] == const0_rtx)
- {
- operands[1] = const0_rtx;
- ix86_expand_move (SImode, &operands[0]);
- }
- else if (operands[2] != constm1_rtx)
- ix86_expand_binary_operator (AND, SImode, &operands[0]);
- else if (operands[5] == constm1_rtx)
- emit_note (NOTE_INSN_DELETED);
+ emit_move_insn (operands[0], const0_rtx);
+ else if (operands[2] == constm1_rtx)
+ emit_move_insn (operands[0], operands[1]);
+ else
+ emit_insn (gen_andsi3 (operands[0], operands[1], operands[2]));
+
if (operands[5] == const0_rtx)
- {
- operands[4] = const0_rtx;
- ix86_expand_move (SImode, &operands[3]);
- }
- else if (operands[5] != constm1_rtx)
- ix86_expand_binary_operator (AND, SImode, &operands[3]);
+ emit_move_insn (operands[3], const0_rtx);
+ else if (operands[5] == constm1_rtx)
+ emit_move_insn (operands[3], operands[4]);
+ else
+ emit_insn (gen_andsi3 (operands[3], operands[4], operands[5]));
+
DONE;
})
@@ -8616,6 +8486,14 @@
operands[2] = shallow_copy_rtx (operands[2]);
PUT_MODE (operands[2], SImode);
}
+ else if (GET_CODE (operands[2]) == CONST)
+ {
+ /* (const:DI (plus:DI (symbol_ref:DI ("...")) (const_int N))) */
+ operands[2] = copy_rtx (operands[2]);
+ PUT_MODE (operands[2], SImode);
+ PUT_MODE (XEXP (operands[2], 0), SImode);
+ PUT_MODE (XEXP (XEXP (operands[2], 0), 0), SImode);
+ }
else
operands[2] = gen_lowpart (SImode, operands[2]);
})
@@ -8692,37 +8570,25 @@
|| REGNO (operands[0]) != REGNO (operands[1]))"
[(const_int 0)]
{
- HOST_WIDE_INT ival = INTVAL (operands[2]);
+ unsigned HOST_WIDE_INT ival = UINTVAL (operands[2]);
machine_mode mode;
- rtx (*insn) (rtx, rtx);
- if (ival == (HOST_WIDE_INT) 0xffffffff)
+ if (ival == GET_MODE_MASK (SImode))
mode = SImode;
- else if (ival == 0xffff)
+ else if (ival == GET_MODE_MASK (HImode))
mode = HImode;
+ else if (ival == GET_MODE_MASK (QImode))
+ mode = QImode;
else
- {
- gcc_assert (ival == 0xff);
- mode = QImode;
- }
+ gcc_unreachable ();
- if (<MODE>mode == DImode)
- insn = (mode == SImode)
- ? gen_zero_extendsidi2
- : (mode == HImode)
- ? gen_zero_extendhidi2
- : gen_zero_extendqidi2;
- else
- {
- if (<MODE>mode != SImode)
- /* Zero extend to SImode to avoid partial register stalls. */
- operands[0] = gen_lowpart (SImode, operands[0]);
+ /* Zero extend to SImode to avoid partial register stalls. */
+ if (<MODE_SIZE> < GET_MODE_SIZE (SImode))
+ operands[0] = gen_lowpart (SImode, operands[0]);
- insn = (mode == HImode)
- ? gen_zero_extendhisi2
- : gen_zero_extendqisi2;
- }
- emit_insn (insn (operands[0], gen_lowpart (mode, operands[1])));
+ emit_insn (gen_extend_insn
+ (operands[0], gen_lowpart (mode, operands[1]),
+ GET_MODE (operands[0]), mode, 1));
DONE;
})
@@ -8991,14 +8857,14 @@
})
(define_insn "*andndi3_doubleword"
- [(set (match_operand:DI 0 "register_operand" "=&r,r,r,&r")
+ [(set (match_operand:DI 0 "register_operand")
(and:DI
- (not:DI (match_operand:DI 1 "register_operand" "r,0,r,0"))
- (match_operand:DI 2 "nonimmediate_operand" "rm,rm,0,rm")))
+ (not:DI (match_operand:DI 1 "register_operand"))
+ (match_operand:DI 2 "nonimmediate_operand")))
(clobber (reg:CC FLAGS_REG))]
- "!TARGET_64BIT && TARGET_STV && TARGET_SSE2"
- "#"
- [(set_attr "isa" "bmi,bmi,bmi,*")])
+ "!TARGET_64BIT && TARGET_STV && TARGET_SSE2
+ && can_create_pseudo_p ()"
+ "#")
(define_split
[(set (match_operand:DI 0 "register_operand")
@@ -9007,7 +8873,7 @@
(match_operand:DI 2 "nonimmediate_operand")))
(clobber (reg:CC FLAGS_REG))]
"!TARGET_64BIT && TARGET_BMI && TARGET_STV && TARGET_SSE2
- && reload_completed"
+ && can_create_pseudo_p ()"
[(parallel [(set (match_dup 0)
(and:SI (not:SI (match_dup 1)) (match_dup 2)))
(clobber (reg:CC FLAGS_REG))])
@@ -9019,20 +8885,25 @@
(define_split
[(set (match_operand:DI 0 "register_operand")
(and:DI
- (not:DI (match_dup 0))
- (match_operand:DI 1 "nonimmediate_operand")))
+ (not:DI (match_operand:DI 1 "register_operand"))
+ (match_operand:DI 2 "nonimmediate_operand")))
(clobber (reg:CC FLAGS_REG))]
"!TARGET_64BIT && !TARGET_BMI && TARGET_STV && TARGET_SSE2
- && reload_completed"
- [(set (match_dup 0) (not:SI (match_dup 0)))
+ && can_create_pseudo_p ()"
+ [(set (match_dup 6) (not:SI (match_dup 1)))
(parallel [(set (match_dup 0)
- (and:SI (match_dup 0) (match_dup 1)))
+ (and:SI (match_dup 6) (match_dup 2)))
(clobber (reg:CC FLAGS_REG))])
- (set (match_dup 2) (not:SI (match_dup 2)))
- (parallel [(set (match_dup 2)
- (and:SI (match_dup 2) (match_dup 3)))
+ (set (match_dup 7) (not:SI (match_dup 4)))
+ (parallel [(set (match_dup 3)
+ (and:SI (match_dup 7) (match_dup 5)))
(clobber (reg:CC FLAGS_REG))])]
- "split_double_mode (DImode, &operands[0], 2, &operands[0], &operands[2]);")
+{
+ operands[6] = gen_reg_rtx (SImode);
+ operands[7] = gen_reg_rtx (SImode);
+
+ split_double_mode (DImode, &operands[0], 3, &operands[0], &operands[3]);
+})
(define_insn "*andn<mode>_1"
[(set (match_operand:SWI48 0 "register_operand" "=r,r")
@@ -9078,51 +8949,51 @@
;; If this is considered useful, it should be done with splitters.
(define_expand "<code><mode>3"
- [(set (match_operand:SWIM1248x 0 "nonimmediate_operand")
- (any_or:SWIM1248x (match_operand:SWIM1248x 1 "nonimmediate_operand")
- (match_operand:SWIM1248x 2 "<general_operand>")))]
+ [(set (match_operand:SWIM1248s 0 "nonimmediate_operand")
+ (any_or:SWIM1248s (match_operand:SWIM1248s 1 "nonimmediate_operand")
+ (match_operand:SWIM1248s 2 "<general_operand>")))]
""
"ix86_expand_binary_operator (<CODE>, <MODE>mode, operands); DONE;")
(define_insn_and_split "*<code>di3_doubleword"
- [(set (match_operand:DI 0 "nonimmediate_operand" "=r,rm,r")
+ [(set (match_operand:DI 0 "nonimmediate_operand")
(any_or:DI
- (match_operand:DI 1 "nonimmediate_operand" "%0,0,0")
- (match_operand:DI 2 "x86_64_szext_general_operand" "Z,re,rm")))
+ (match_operand:DI 1 "nonimmediate_operand")
+ (match_operand:DI 2 "x86_64_szext_general_operand")))
(clobber (reg:CC FLAGS_REG))]
"!TARGET_64BIT && TARGET_STV && TARGET_SSE2
- && ix86_binary_operator_ok (<CODE>, DImode, operands)"
+ && ix86_binary_operator_ok (<CODE>, DImode, operands)
+ && can_create_pseudo_p ()"
"#"
- "&& reload_completed"
+ "&& 1"
[(const_int 0)]
{
split_double_mode (DImode, &operands[0], 3, &operands[0], &operands[3]);
- if (operands[2] == constm1_rtx)
+
+ if (operands[2] == const0_rtx)
+ emit_move_insn (operands[0], operands[1]);
+ else if (operands[2] == constm1_rtx)
{
if (<CODE> == IOR)
- {
- operands[1] = constm1_rtx;
- ix86_expand_move (SImode, &operands[0]);
- }
+ emit_move_insn (operands[0], constm1_rtx);
else
ix86_expand_unary_operator (NOT, SImode, &operands[0]);
}
- else if (operands[2] != const0_rtx)
+ else
ix86_expand_binary_operator (<CODE>, SImode, &operands[0]);
- else if (operands[5] == const0_rtx)
- emit_note (NOTE_INSN_DELETED);
- if (operands[5] == constm1_rtx)
+
+ if (operands[5] == const0_rtx)
+ emit_move_insn (operands[3], operands[4]);
+ else if (operands[5] == constm1_rtx)
{
if (<CODE> == IOR)
- {
- operands[4] = constm1_rtx;
- ix86_expand_move (SImode, &operands[3]);
- }
+ emit_move_insn (operands[3], constm1_rtx);
else
ix86_expand_unary_operator (NOT, SImode, &operands[3]);
}
- else if (operands[5] != const0_rtx)
+ else
ix86_expand_binary_operator (<CODE>, SImode, &operands[3]);
+
DONE;
})
@@ -9567,7 +9438,31 @@
[(set_attr "type" "negnot")
(set_attr "mode" "<MODE>")])
-;; Changing of sign for FP values is doable using integer unit too.
+(define_expand "<code>tf2"
+ [(set (match_operand:TF 0 "register_operand")
+ (absneg:TF (match_operand:TF 1 "register_operand")))]
+ "TARGET_SSE"
+ "ix86_expand_fp_absneg_operator (<CODE>, TFmode, operands); DONE;")
+
+(define_insn "*<code>tf2_1"
+ [(set (match_operand:TF 0 "register_operand" "=x,x,Yv,Yv")
+ (absneg:TF
+ (match_operand:TF 1 "vector_operand" "0,xBm,Yv,m")))
+ (use (match_operand:TF 2 "vector_operand" "xBm,0,Yvm,Yv"))
+ (clobber (reg:CC FLAGS_REG))]
+ "TARGET_SSE"
+ "#"
+ [(set_attr "isa" "noavx,noavx,avx,avx")])
+
+(define_insn "*nabstf2_1"
+ [(set (match_operand:TF 0 "register_operand" "=x,x,Yv,Yv")
+ (neg:TF
+ (abs:TF
+ (match_operand:TF 1 "vector_operand" "0,xBm,Yv,m"))))
+ (use (match_operand:TF 2 "vector_operand" "xBm,0,Yvm,Yv"))]
+ "TARGET_SSE"
+ "#"
+ [(set_attr "isa" "noavx,noavx,avx,avx")])
(define_expand "<code><mode>2"
[(set (match_operand:X87MODEF 0 "register_operand")
@@ -9575,203 +9470,170 @@
"TARGET_80387 || (SSE_FLOAT_MODE_P (<MODE>mode) && TARGET_SSE_MATH)"
"ix86_expand_fp_absneg_operator (<CODE>, <MODE>mode, operands); DONE;")
-(define_insn "*absneg<mode>2"
- [(set (match_operand:MODEF 0 "register_operand" "=Yv,Yv,f,!r")
- (match_operator:MODEF 3 "absneg_operator"
- [(match_operand:MODEF 1 "register_operand" "0,Yv,0,0")]))
- (use (match_operand:<ssevecmode> 2 "nonimmediate_operand" "Yvm,0,X,X"))
+;; Changing of sign for FP values is doable using integer unit too.
+(define_insn "*<code><mode>2_i387_1"
+ [(set (match_operand:X87MODEF 0 "register_operand" "=f,!r")
+ (absneg:X87MODEF
+ (match_operand:X87MODEF 1 "register_operand" "0,0")))
+ (clobber (reg:CC FLAGS_REG))]
+ "TARGET_80387"
+ "#")
+
+(define_split
+ [(set (match_operand:X87MODEF 0 "fp_register_operand")
+ (absneg:X87MODEF (match_operand:X87MODEF 1 "fp_register_operand")))
+ (clobber (reg:CC FLAGS_REG))]
+ "TARGET_80387 && reload_completed"
+ [(set (match_dup 0) (absneg:X87MODEF (match_dup 1)))])
+
+(define_split
+ [(set (match_operand:X87MODEF 0 "general_reg_operand")
+ (absneg:X87MODEF (match_operand:X87MODEF 1 "general_reg_operand")))
+ (clobber (reg:CC FLAGS_REG))]
+ "TARGET_80387 && reload_completed"
+ [(const_int 0)]
+ "ix86_split_fp_absneg_operator (<CODE>, <MODE>mode, operands); DONE;")
+
+(define_insn "*<code><mode>2_1"
+ [(set (match_operand:MODEF 0 "register_operand" "=x,x,Yv,f,!r")
+ (absneg:MODEF
+ (match_operand:MODEF 1 "register_operand" "0,x,Yv,0,0")))
+ (use (match_operand:<ssevecmode> 2 "vector_operand" "xBm,0,Yvm,X,X"))
(clobber (reg:CC FLAGS_REG))]
"TARGET_80387 || (SSE_FLOAT_MODE_P (<MODE>mode) && TARGET_SSE_MATH)"
"#"
- [(set (attr "enabled")
+ [(set_attr "isa" "noavx,noavx,avx,*,*")
+ (set (attr "enabled")
(if_then_else
(match_test ("SSE_FLOAT_MODE_P (<MODE>mode) && TARGET_SSE_MATH"))
(if_then_else
- (eq_attr "alternative" "2")
+ (eq_attr "alternative" "3,4")
(symbol_ref "TARGET_MIX_SSE_I387")
- (symbol_ref "true"))
+ (const_string "*"))
(if_then_else
- (eq_attr "alternative" "2,3")
+ (eq_attr "alternative" "3,4")
(symbol_ref "true")
(symbol_ref "false"))))])
-(define_insn "*absnegxf2_i387"
- [(set (match_operand:XF 0 "register_operand" "=f,!r")
- (match_operator:XF 3 "absneg_operator"
- [(match_operand:XF 1 "register_operand" "0,0")]))
- (use (match_operand 2))
- (clobber (reg:CC FLAGS_REG))]
- "TARGET_80387"
- "#")
-
-(define_expand "<code>tf2"
- [(set (match_operand:TF 0 "register_operand")
- (absneg:TF (match_operand:TF 1 "register_operand")))]
- "TARGET_SSE"
- "ix86_expand_fp_absneg_operator (<CODE>, TFmode, operands); DONE;")
-
-(define_insn "*absnegtf2_sse"
- [(set (match_operand:TF 0 "register_operand" "=Yv,Yv")
- (match_operator:TF 3 "absneg_operator"
- [(match_operand:TF 1 "register_operand" "0,Yv")]))
- (use (match_operand:TF 2 "nonimmediate_operand" "Yvm,0"))
- (clobber (reg:CC FLAGS_REG))]
- "TARGET_SSE"
- "#")
-
-;; Splitters for fp abs and neg.
-
-(define_split
- [(set (match_operand 0 "fp_register_operand")
- (match_operator 1 "absneg_operator" [(match_dup 0)]))
- (use (match_operand 2))
- (clobber (reg:CC FLAGS_REG))]
- "reload_completed"
- [(set (match_dup 0) (match_op_dup 1 [(match_dup 0)]))])
-
(define_split
- [(set (match_operand 0 "sse_reg_operand")
- (match_operator 3 "absneg_operator"
- [(match_operand 1 "register_operand")]))
- (use (match_operand 2 "nonimmediate_operand"))
+ [(set (match_operand:SSEMODEF 0 "sse_reg_operand")
+ (absneg:SSEMODEF
+ (match_operand:SSEMODEF 1 "vector_operand")))
+ (use (match_operand:<ssevecmodef> 2 "vector_operand"))
(clobber (reg:CC FLAGS_REG))]
- "reload_completed"
+ "((SSE_FLOAT_MODE_P (<MODE>mode) && TARGET_SSE_MATH)
+ || (TARGET_SSE && (<MODE>mode == TFmode)))
+ && reload_completed"
[(set (match_dup 0) (match_dup 3))]
{
- machine_mode mode = GET_MODE (operands[0]);
- machine_mode vmode = GET_MODE (operands[2]);
- rtx tmp;
+ machine_mode mode = <MODE>mode;
+ machine_mode vmode = <ssevecmodef>mode;
+ enum rtx_code absneg_op = <CODE> == ABS ? AND : XOR;
operands[0] = lowpart_subreg (vmode, operands[0], mode);
operands[1] = lowpart_subreg (vmode, operands[1], mode);
- if (operands_match_p (operands[0], operands[2]))
- std::swap (operands[1], operands[2]);
- if (GET_CODE (operands[3]) == ABS)
- tmp = gen_rtx_AND (vmode, operands[1], operands[2]);
- else
- tmp = gen_rtx_XOR (vmode, operands[1], operands[2]);
- operands[3] = tmp;
-})
-(define_split
- [(set (match_operand:SF 0 "general_reg_operand")
- (match_operator:SF 1 "absneg_operator" [(match_dup 0)]))
- (use (match_operand:V4SF 2))
- (clobber (reg:CC FLAGS_REG))]
- "reload_completed"
- [(parallel [(set (match_dup 0) (match_dup 1))
- (clobber (reg:CC FLAGS_REG))])]
-{
- rtx tmp;
- operands[0] = gen_lowpart (SImode, operands[0]);
- if (GET_CODE (operands[1]) == ABS)
+ if (TARGET_AVX)
{
- tmp = gen_int_mode (0x7fffffff, SImode);
- tmp = gen_rtx_AND (SImode, operands[0], tmp);
+ if (MEM_P (operands[1]))
+ std::swap (operands[1], operands[2]);
}
else
- {
- tmp = gen_int_mode (0x80000000, SImode);
- tmp = gen_rtx_XOR (SImode, operands[0], tmp);
- }
- operands[1] = tmp;
+ {
+ if (operands_match_p (operands[0], operands[2]))
+ std::swap (operands[1], operands[2]);
+ }
+
+ operands[3]
+ = gen_rtx_fmt_ee (absneg_op, vmode, operands[1], operands[2]);
})
(define_split
- [(set (match_operand:DF 0 "general_reg_operand")
- (match_operator:DF 1 "absneg_operator" [(match_dup 0)]))
+ [(set (match_operand:MODEF 0 "fp_register_operand")
+ (absneg:MODEF (match_operand:MODEF 1 "fp_register_operand")))
(use (match_operand 2))
(clobber (reg:CC FLAGS_REG))]
- "reload_completed"
- [(parallel [(set (match_dup 0) (match_dup 1))
- (clobber (reg:CC FLAGS_REG))])]
-{
- rtx tmp;
- if (TARGET_64BIT)
- {
- tmp = gen_lowpart (DImode, operands[0]);
- tmp = gen_rtx_ZERO_EXTRACT (DImode, tmp, const1_rtx, GEN_INT (63));
- operands[0] = tmp;
-
- if (GET_CODE (operands[1]) == ABS)
- tmp = const0_rtx;
- else
- tmp = gen_rtx_NOT (DImode, tmp);
- }
- else
- {
- operands[0] = gen_highpart (SImode, operands[0]);
- if (GET_CODE (operands[1]) == ABS)
- {
- tmp = gen_int_mode (0x7fffffff, SImode);
- tmp = gen_rtx_AND (SImode, operands[0], tmp);
- }
- else
- {
- tmp = gen_int_mode (0x80000000, SImode);
- tmp = gen_rtx_XOR (SImode, operands[0], tmp);
- }
- }
- operands[1] = tmp;
-})
+ "TARGET_80387 && reload_completed"
+ [(set (match_dup 0) (absneg:MODEF (match_dup 1)))])
(define_split
- [(set (match_operand:XF 0 "general_reg_operand")
- (match_operator:XF 1 "absneg_operator" [(match_dup 0)]))
+ [(set (match_operand:MODEF 0 "general_reg_operand")
+ (absneg:MODEF (match_operand:MODEF 1 "general_reg_operand")))
(use (match_operand 2))
(clobber (reg:CC FLAGS_REG))]
- "reload_completed"
- [(parallel [(set (match_dup 0) (match_dup 1))
- (clobber (reg:CC FLAGS_REG))])]
+ "TARGET_80387 && reload_completed"
+ [(const_int 0)]
+ "ix86_split_fp_absneg_operator (<CODE>, <MODE>mode, operands); DONE;")
+
+(define_insn "*nabs<mode>2_1"
+ [(set (match_operand:MODEF 0 "register_operand" "=x,x,Yv")
+ (neg:MODEF
+ (abs:MODEF
+ (match_operand:MODEF 1 "register_operand" "0,x,Yv"))))
+ (use (match_operand:<ssevecmode> 2 "vector_operand" "xBm,0,Yvm"))]
+ "SSE_FLOAT_MODE_P (<MODE>mode) && TARGET_SSE_MATH"
+ "#"
+ [(set_attr "isa" "noavx,noavx,avx")])
+
+(define_split
+ [(set (match_operand:SSEMODEF 0 "sse_reg_operand")
+ (neg:SSEMODEF
+ (abs:SSEMODEF
+ (match_operand:SSEMODEF 1 "vector_operand"))))
+ (use (match_operand:<ssevecmodef> 2 "vector_operand"))]
+ "((SSE_FLOAT_MODE_P (<MODE>mode) && TARGET_SSE_MATH)
+ || (TARGET_SSE && (<MODE>mode == TFmode)))
+ && reload_completed"
+ [(set (match_dup 0) (match_dup 3))]
{
- rtx tmp;
- operands[0] = gen_rtx_REG (SImode,
- REGNO (operands[0]) + (TARGET_64BIT ? 1 : 2));
- if (GET_CODE (operands[1]) == ABS)
+ machine_mode mode = <MODE>mode;
+ machine_mode vmode = <ssevecmodef>mode;
+
+ operands[0] = lowpart_subreg (vmode, operands[0], mode);
+ operands[1] = lowpart_subreg (vmode, operands[1], mode);
+
+ if (TARGET_AVX)
{
- tmp = GEN_INT (0x7fff);
- tmp = gen_rtx_AND (SImode, operands[0], tmp);
+ if (MEM_P (operands[1]))
+ std::swap (operands[1], operands[2]);
}
else
- {
- tmp = GEN_INT (0x8000);
- tmp = gen_rtx_XOR (SImode, operands[0], tmp);
- }
- operands[1] = tmp;
+ {
+ if (operands_match_p (operands[0], operands[2]))
+ std::swap (operands[1], operands[2]);
+ }
+
+ operands[3]
+ = gen_rtx_fmt_ee (IOR, vmode, operands[1], operands[2]);
})
;; Conditionalize these after reload. If they match before reload, we
;; lose the clobber and ability to use integer instructions.
-(define_insn "*<code><mode>2_1"
+(define_insn "*<code><mode>2_i387"
[(set (match_operand:X87MODEF 0 "register_operand" "=f")
(absneg:X87MODEF (match_operand:X87MODEF 1 "register_operand" "0")))]
- "TARGET_80387
- && (reload_completed
- || !(SSE_FLOAT_MODE_P (<MODE>mode) && TARGET_SSE_MATH))"
+ "TARGET_80387 && reload_completed"
"<absneg_mnemonic>"
[(set_attr "type" "fsgn")
(set_attr "mode" "<MODE>")])
;; Copysign instructions
-(define_mode_iterator CSGNMODE [SF DF TF])
-(define_mode_attr CSGNVMODE [(SF "V4SF") (DF "V2DF") (TF "TF")])
-
(define_expand "copysign<mode>3"
- [(match_operand:CSGNMODE 0 "register_operand")
- (match_operand:CSGNMODE 1 "nonmemory_operand")
- (match_operand:CSGNMODE 2 "register_operand")]
+ [(match_operand:SSEMODEF 0 "register_operand")
+ (match_operand:SSEMODEF 1 "nonmemory_operand")
+ (match_operand:SSEMODEF 2 "register_operand")]
"(SSE_FLOAT_MODE_P (<MODE>mode) && TARGET_SSE_MATH)
|| (TARGET_SSE && (<MODE>mode == TFmode))"
"ix86_expand_copysign (operands); DONE;")
-(define_insn_and_split "copysign<mode>3_const"
- [(set (match_operand:CSGNMODE 0 "register_operand" "=Yv")
- (unspec:CSGNMODE
- [(match_operand:<CSGNVMODE> 1 "nonimm_or_0_operand" "YvmC")
- (match_operand:CSGNMODE 2 "register_operand" "0")
- (match_operand:<CSGNVMODE> 3 "nonimmediate_operand" "Yvm")]
+(define_insn_and_split "@copysign<mode>3_const"
+ [(set (match_operand:SSEMODEF 0 "register_operand" "=Yv")
+ (unspec:SSEMODEF
+ [(match_operand:<ssevecmodef> 1 "nonimm_or_0_operand" "YvmC")
+ (match_operand:SSEMODEF 2 "register_operand" "0")
+ (match_operand:<ssevecmodef> 3 "nonimmediate_operand" "Yvm")]
UNSPEC_COPYSIGN))]
"(SSE_FLOAT_MODE_P (<MODE>mode) && TARGET_SSE_MATH)
|| (TARGET_SSE && (<MODE>mode == TFmode))"
@@ -9780,30 +9642,30 @@
[(const_int 0)]
"ix86_split_copysign_const (operands); DONE;")
-(define_insn "copysign<mode>3_var"
- [(set (match_operand:CSGNMODE 0 "register_operand" "=Yv,Yv,Yv,Yv,Yv")
- (unspec:CSGNMODE
- [(match_operand:CSGNMODE 2 "register_operand" "Yv,0,0,Yv,Yv")
- (match_operand:CSGNMODE 3 "register_operand" "1,1,Yv,1,Yv")
- (match_operand:<CSGNVMODE> 4
+(define_insn "@copysign<mode>3_var"
+ [(set (match_operand:SSEMODEF 0 "register_operand" "=Yv,Yv,Yv,Yv,Yv")
+ (unspec:SSEMODEF
+ [(match_operand:SSEMODEF 2 "register_operand" "Yv,0,0,Yv,Yv")
+ (match_operand:SSEMODEF 3 "register_operand" "1,1,Yv,1,Yv")
+ (match_operand:<ssevecmodef> 4
"nonimmediate_operand" "X,Yvm,Yvm,0,0")
- (match_operand:<CSGNVMODE> 5
+ (match_operand:<ssevecmodef> 5
"nonimmediate_operand" "0,Yvm,1,Yvm,1")]
UNSPEC_COPYSIGN))
- (clobber (match_scratch:<CSGNVMODE> 1 "=Yv,Yv,Yv,Yv,Yv"))]
+ (clobber (match_scratch:<ssevecmodef> 1 "=Yv,Yv,Yv,Yv,Yv"))]
"(SSE_FLOAT_MODE_P (<MODE>mode) && TARGET_SSE_MATH)
|| (TARGET_SSE && (<MODE>mode == TFmode))"
"#")
(define_split
- [(set (match_operand:CSGNMODE 0 "register_operand")
- (unspec:CSGNMODE
- [(match_operand:CSGNMODE 2 "register_operand")
- (match_operand:CSGNMODE 3 "register_operand")
- (match_operand:<CSGNVMODE> 4)
- (match_operand:<CSGNVMODE> 5)]
+ [(set (match_operand:SSEMODEF 0 "register_operand")
+ (unspec:SSEMODEF
+ [(match_operand:SSEMODEF 2 "register_operand")
+ (match_operand:SSEMODEF 3 "register_operand")
+ (match_operand:<ssevecmodef> 4)
+ (match_operand:<ssevecmodef> 5)]
UNSPEC_COPYSIGN))
- (clobber (match_scratch:<CSGNVMODE> 1))]
+ (clobber (match_scratch:<ssevecmodef> 1))]
"((SSE_FLOAT_MODE_P (<MODE>mode) && TARGET_SSE_MATH)
|| (TARGET_SSE && (<MODE>mode == TFmode)))
&& reload_completed"
@@ -9817,7 +9679,7 @@
"SSE_FLOAT_MODE_P (<MODE>mode) && TARGET_SSE_MATH"
"ix86_expand_xorsign (operands); DONE;")
-(define_insn_and_split "xorsign<mode>3_1"
+(define_insn_and_split "@xorsign<mode>3_1"
[(set (match_operand:MODEF 0 "register_operand" "=Yv")
(unspec:MODEF
[(match_operand:MODEF 1 "register_operand" "Yv")
@@ -9833,18 +9695,19 @@
;; One complement instructions
(define_expand "one_cmpl<mode>2"
- [(set (match_operand:SWIM1248x 0 "nonimmediate_operand")
- (not:SWIM1248x (match_operand:SWIM1248x 1 "nonimmediate_operand")))]
+ [(set (match_operand:SWIM1248s 0 "nonimmediate_operand")
+ (not:SWIM1248s (match_operand:SWIM1248s 1 "nonimmediate_operand")))]
""
"ix86_expand_unary_operator (NOT, <MODE>mode, operands); DONE;")
(define_insn_and_split "*one_cmpldi2_doubleword"
- [(set (match_operand:DI 0 "nonimmediate_operand" "=rm")
- (not:DI (match_operand:DI 1 "nonimmediate_operand" "0")))]
+ [(set (match_operand:DI 0 "nonimmediate_operand")
+ (not:DI (match_operand:DI 1 "nonimmediate_operand")))]
"!TARGET_64BIT && TARGET_STV && TARGET_SSE2
- && ix86_unary_operator_ok (NOT, DImode, operands)"
+ && ix86_unary_operator_ok (NOT, DImode, operands)
+ && can_create_pseudo_p ()"
"#"
- "&& reload_completed"
+ "&& 1"
[(set (match_dup 0)
(not:SI (match_dup 1)))
(set (match_dup 2)
@@ -10116,7 +9979,7 @@
(set_attr "amdfam10_decode" "vector")
(set_attr "bdver1_decode" "vector")])
-(define_expand "x86_shift<mode>_adj_1"
+(define_expand "@x86_shift<mode>_adj_1"
[(set (reg:CCZ FLAGS_REG)
(compare:CCZ (and:QI (match_operand:QI 2 "register_operand")
(match_dup 4))
@@ -10132,7 +9995,7 @@
"TARGET_CMOVE"
"operands[4] = GEN_INT (GET_MODE_BITSIZE (<MODE>mode));")
-(define_expand "x86_shift<mode>_adj_2"
+(define_expand "@x86_shift<mode>_adj_2"
[(use (match_operand:SWI48 0 "register_operand"))
(use (match_operand:SWI48 1 "register_operand"))
(use (match_operand:QI 2 "register_operand"))]
@@ -10912,7 +10775,7 @@
(set_attr "modrm" "0,1")
(set_attr "mode" "SI")])
-(define_expand "x86_shift<mode>_adj_3"
+(define_expand "@x86_shift<mode>_adj_3"
[(use (match_operand:SWI48 0 "register_operand"))
(use (match_operand:SWI48 1 "register_operand"))
(use (match_operand:QI 2 "register_operand"))]
@@ -13180,7 +13043,15 @@
[(const_int 0)]
"ix86_expand_epilogue (2); DONE;")
-(define_insn "leave"
+(define_expand "@leave_<mode>"
+ [(parallel
+ [(set (reg:W SP_REG) (plus:W (reg:W BP_REG) (match_dup 0)))
+ (set (reg:W BP_REG) (mem:W (reg:W BP_REG)))
+ (clobber (mem:BLK (scratch)))])]
+ ""
+ "operands[0] = GEN_INT (<MODE_SIZE>);")
+
+(define_insn "*leave"
[(set (reg:SI SP_REG) (plus:SI (reg:SI BP_REG) (const_int 4)))
(set (reg:SI BP_REG) (mem:SI (reg:SI BP_REG)))
(clobber (mem:BLK (scratch)))]
@@ -13188,7 +13059,7 @@
"leave"
[(set_attr "type" "leave")])
-(define_insn "leave_rex64"
+(define_insn "*leave_rex64"
[(set (reg:DI SP_REG) (plus:DI (reg:DI BP_REG) (const_int 8)))
(set (reg:DI BP_REG) (mem:DI (reg:DI BP_REG)))
(clobber (mem:BLK (scratch)))]
@@ -14357,7 +14228,7 @@
[(set_attr "type" "multi")
(set_attr "length" "22")])
-(define_expand "tls_global_dynamic_64_<mode>"
+(define_expand "@tls_global_dynamic_64_<mode>"
[(parallel
[(set (match_operand:P 0 "register_operand")
(call:P
@@ -14451,7 +14322,7 @@
[(set_attr "type" "multi")
(set_attr "length" "22")])
-(define_expand "tls_local_dynamic_base_64_<mode>"
+(define_expand "@tls_local_dynamic_base_64_<mode>"
[(parallel
[(set (match_operand:P 0 "register_operand")
(call:P
@@ -16711,7 +16582,7 @@
(set_attr "length_immediate" "0")
(set_attr "modrm" "0")])
-(define_expand "movmem<mode>"
+(define_expand "cpymem<mode>"
[(use (match_operand:BLK 0 "memory_operand"))
(use (match_operand:BLK 1 "memory_operand"))
(use (match_operand:SWI48 2 "nonmemory_operand"))
@@ -16723,7 +16594,7 @@
(use (match_operand:SI 8 ""))]
""
{
- if (ix86_expand_set_or_movmem (operands[0], operands[1],
+ if (ix86_expand_set_or_cpymem (operands[0], operands[1],
operands[2], NULL, operands[3],
operands[4], operands[5],
operands[6], operands[7],
@@ -16938,7 +16809,7 @@
(use (match_operand:SI 8 ""))]
""
{
- if (ix86_expand_set_or_movmem (operands[0], NULL,
+ if (ix86_expand_set_or_cpymem (operands[0], NULL,
operands[1], operands[2],
operands[3], operands[4],
operands[5], operands[6],
@@ -17135,7 +17006,7 @@
(use (match_operand 4 "immediate_operand"))]
""
{
- rtx addr1, addr2, out, outlow, count, countreg, align;
+ rtx addr1, addr2, countreg, align, out;
if (optimize_insn_for_size_p () && !TARGET_INLINE_ALL_STRINGOPS)
FAIL;
@@ -17159,10 +17030,6 @@
&& TREE_CODE (TREE_OPERAND (TREE_OPERAND (t2, 0), 0)) == STRING_CST)))
FAIL;
- out = operands[0];
- if (!REG_P (out))
- out = gen_reg_rtx (SImode);
-
addr1 = copy_addr_to_reg (XEXP (operands[1], 0));
addr2 = copy_addr_to_reg (XEXP (operands[2], 0));
if (addr1 != XEXP (operands[1], 0))
@@ -17170,17 +17037,16 @@
if (addr2 != XEXP (operands[2], 0))
operands[2] = replace_equiv_address_nv (operands[2], addr2);
- count = operands[3];
- countreg = ix86_zero_extend_to_Pmode (count);
+ countreg = ix86_zero_extend_to_Pmode (operands[3]);
/* %%% Iff we are testing strict equality, we can use known alignment
to good advantage. This may be possible with combine, particularly
once cc0 is dead. */
align = operands[4];
- if (CONST_INT_P (count))
+ if (CONST_INT_P (operands[3]))
{
- if (INTVAL (count) == 0)
+ if (operands[3] == const0_rtx)
{
emit_move_insn (operands[0], const0_rtx);
DONE;
@@ -17190,22 +17056,14 @@
}
else
{
- rtx (*gen_cmp) (rtx, rtx);
-
- gen_cmp = (TARGET_64BIT
- ? gen_cmpdi_1 : gen_cmpsi_1);
-
- emit_insn (gen_cmp (countreg, countreg));
+ emit_insn (gen_cmp_1 (Pmode, countreg, countreg));
emit_insn (gen_cmpstrnqi_1 (addr1, addr2, countreg, align,
operands[1], operands[2]));
}
- outlow = gen_lowpart (QImode, out);
- emit_insn (gen_cmpintqi (outlow));
- emit_move_insn (out, gen_rtx_SIGN_EXTEND (SImode, outlow));
-
- if (operands[0] != out)
- emit_move_insn (operands[0], out);
+ out = gen_lowpart (QImode, operands[0]);
+ emit_insn (gen_cmpintqi (out));
+ emit_move_insn (operands[0], gen_rtx_SIGN_EXTEND (SImode, out));
DONE;
})
@@ -17913,7 +17771,7 @@
;;
;; in proper program order.
-(define_insn "pro_epilogue_adjust_stack_<mode>_add"
+(define_insn "@pro_epilogue_adjust_stack_add_<mode>"
[(set (match_operand:P 0 "register_operand" "=r,r")
(plus:P (match_operand:P 1 "register_operand" "0,r")
(match_operand:P 2 "<nonmemory_operand>" "r<i>,l<i>")))
@@ -17956,7 +17814,7 @@
(const_string "*")))
(set_attr "mode" "<MODE>")])
-(define_insn "pro_epilogue_adjust_stack_<mode>_sub"
+(define_insn "@pro_epilogue_adjust_stack_sub_<mode>"
[(set (match_operand:P 0 "register_operand" "=r")
(minus:P (match_operand:P 1 "register_operand" "0")
(match_operand:P 2 "register_operand" "r")))
@@ -17967,7 +17825,7 @@
[(set_attr "type" "alu")
(set_attr "mode" "<MODE>")])
-(define_insn "allocate_stack_worker_probe_<mode>"
+(define_insn "@allocate_stack_worker_probe_<mode>"
[(set (match_operand:P 0 "register_operand" "=a")
(unspec_volatile:P [(match_operand:P 1 "register_operand" "0")]
UNSPECV_STACK_PROBE))
@@ -17993,15 +17851,9 @@
x = operands[1];
else
{
- rtx (*insn) (rtx, rtx);
-
x = copy_to_mode_reg (Pmode, operands[1]);
- insn = (TARGET_64BIT
- ? gen_allocate_stack_worker_probe_di
- : gen_allocate_stack_worker_probe_si);
-
- emit_insn (insn (x, x));
+ emit_insn (gen_allocate_stack_worker_probe (Pmode, x, x));
}
x = expand_simple_binop (Pmode, MINUS, stack_pointer_rtx, x,
@@ -18018,16 +17870,13 @@
[(match_operand 0 "memory_operand")]
""
{
- rtx (*insn) (rtx, rtx)
- = (GET_MODE (operands[0]) == DImode
- ? gen_probe_stack_di : gen_probe_stack_si);
-
- emit_insn (insn (operands[0], const0_rtx));
+ emit_insn (gen_probe_stack_1
+ (word_mode, operands[0], const0_rtx));
DONE;
})
;; Use OR for stack probes, this is shorter.
-(define_insn "probe_stack_<mode>"
+(define_insn "@probe_stack_1_<mode>"
[(set (match_operand:W 0 "memory_operand" "=m")
(unspec:W [(match_operand:W 1 "const0_operand")]
UNSPEC_PROBE_STACK))
@@ -18038,7 +17887,7 @@
(set_attr "mode" "<MODE>")
(set_attr "length_immediate" "1")])
-(define_insn "adjust_stack_and_probe<mode>"
+(define_insn "@adjust_stack_and_probe_<mode>"
[(set (match_operand:P 0 "register_operand" "=r")
(unspec_volatile:P [(match_operand:P 1 "register_operand" "0")]
UNSPECV_PROBE_STACK_RANGE))
@@ -18050,7 +17899,7 @@
"* return output_adjust_stack_and_probe (operands[0]);"
[(set_attr "type" "multi")])
-(define_insn "probe_stack_range<mode>"
+(define_insn "@probe_stack_range_<mode>"
[(set (match_operand:P 0 "register_operand" "=r")
(unspec_volatile:P [(match_operand:P 1 "register_operand" "0")
(match_operand:P 2 "const_int_operand" "n")]
@@ -19465,7 +19314,7 @@
(match_operand:SI 2 "const_int_operand"))]
"TARGET_3DNOW || TARGET_PREFETCH_SSE || TARGET_PRFCHW || TARGET_PREFETCHWT1"
{
- bool write = INTVAL (operands[1]) != 0;
+ bool write = operands[1] != const0_rtx;
int locality = INTVAL (operands[2]);
gcc_assert (IN_RANGE (locality, 0, 3));
@@ -19530,7 +19379,7 @@
(const_int 3))]
"TARGET_3DNOW || TARGET_PRFCHW || TARGET_PREFETCHWT1"
{
- if (INTVAL (operands[1]) == 0)
+ if (operands[1] == const0_rtx)
return "prefetch\t%a0";
else
return "prefetchw\t%a0";
@@ -19556,17 +19405,12 @@
(match_operand 1 "memory_operand")]
""
{
- rtx (*insn)(rtx, rtx);
-
- insn = (TARGET_LP64
- ? gen_stack_protect_set_di
- : gen_stack_protect_set_si);
-
- emit_insn (insn (operands[0], operands[1]));
+ emit_insn (gen_stack_protect_set_1
+ (ptr_mode, operands[0], operands[1]));
DONE;
})
-(define_insn "stack_protect_set_<mode>"
+(define_insn "@stack_protect_set_1_<mode>"
[(set (match_operand:PTR 0 "memory_operand" "=m")
(unspec:PTR [(match_operand:PTR 1 "memory_operand" "m")]
UNSPEC_SP_SET))
@@ -19584,27 +19428,22 @@
{
rtx flags = gen_rtx_REG (CCZmode, FLAGS_REG);
- rtx (*insn)(rtx, rtx, rtx);
-
- insn = (TARGET_LP64
- ? gen_stack_protect_test_di
- : gen_stack_protect_test_si);
-
- emit_insn (insn (flags, operands[0], operands[1]));
+ emit_insn (gen_stack_protect_test_1
+ (ptr_mode, flags, operands[0], operands[1]));
emit_jump_insn (gen_cbranchcc4 (gen_rtx_EQ (VOIDmode, flags, const0_rtx),
flags, const0_rtx, operands[2]));
DONE;
})
-(define_insn "stack_protect_test_<mode>"
+(define_insn "@stack_protect_test_1_<mode>"
[(set (match_operand:CCZ 0 "flags_reg_operand")
(unspec:CCZ [(match_operand:PTR 1 "memory_operand" "m")
(match_operand:PTR 2 "memory_operand" "m")]
UNSPEC_SP_TEST))
(clobber (match_scratch:PTR 3 "=&r"))]
""
- "mov{<imodesuffix>}\t{%1, %3|%3, %1}\;xor{<imodesuffix>}\t{%2, %3|%3, %2}"
+ "mov{<imodesuffix>}\t{%1, %3|%3, %1}\;sub{<imodesuffix>}\t{%2, %3|%3, %2}"
[(set_attr "type" "multi")])
(define_insn "sse4_2_crc32<mode>"
@@ -19969,7 +19808,7 @@
UNSPECV_LLWP_INTRINSIC)]
"TARGET_LWP")
-(define_insn "*lwp_llwpcb<mode>1"
+(define_insn "*lwp_llwpcb<mode>_1"
[(unspec_volatile [(match_operand:P 0 "register_operand" "r")]
UNSPECV_LLWP_INTRINSIC)]
"TARGET_LWP"
@@ -19982,18 +19821,9 @@
[(set (match_operand 0 "register_operand")
(unspec_volatile [(const_int 0)] UNSPECV_SLWP_INTRINSIC))]
"TARGET_LWP"
-{
- rtx (*insn)(rtx);
-
- insn = (Pmode == DImode
- ? gen_lwp_slwpcbdi
- : gen_lwp_slwpcbsi);
-
- emit_insn (insn (operands[0]));
- DONE;
-})
+ "emit_insn (gen_lwp_slwpcb_1 (Pmode, operands[0])); DONE;")
-(define_insn "lwp_slwpcb<mode>"
+(define_insn "@lwp_slwpcb<mode>_1"
[(set (match_operand:P 0 "register_operand" "=r")
(unspec_volatile:P [(const_int 0)] UNSPECV_SLWP_INTRINSIC))]
"TARGET_LWP"
@@ -20310,7 +20140,7 @@
"mwaitx"
[(set_attr "length" "3")])
-(define_insn "monitorx_<mode>"
+(define_insn "@monitorx_<mode>"
[(unspec_volatile [(match_operand:P 0 "register_operand" "a")
(match_operand:SI 1 "register_operand" "c")
(match_operand:SI 2 "register_operand" "d")]
@@ -20324,7 +20154,7 @@
(symbol_ref ("(Pmode != word_mode) + 3")))])
;; CLZERO
-(define_insn "clzero_<mode>"
+(define_insn "@clzero_<mode>"
[(unspec_volatile [(match_operand: P 0 "register_operand" "a")]
UNSPECV_CLZERO)]
"TARGET_CLZERO"
@@ -20412,7 +20242,7 @@
"movdiri\t{%1, %0|%0, %1}"
[(set_attr "type" "other")])
-(define_insn "movdir64b_<mode>"
+(define_insn "@movdir64b_<mode>"
[(unspec_volatile:XI [(match_operand:P 0 "register_operand" "r")
(match_operand:XI 1 "memory_operand")]
UNSPECV_MOVDIR64B)]
@@ -20420,6 +20250,20 @@
"movdir64b\t{%1, %0|%0, %1}"
[(set_attr "type" "other")])
+;; ENQCMD and ENQCMDS
+
+(define_int_iterator ENQCMD [UNSPECV_ENQCMD UNSPECV_ENQCMDS])
+(define_int_attr enqcmd_sfx [(UNSPECV_ENQCMD "") (UNSPECV_ENQCMDS "s")])
+
+(define_insn "@enqcmd<enqcmd_sfx>_<mode>"
+ [(set (reg:CCZ FLAGS_REG)
+ (unspec_volatile:CCZ [(match_operand:P 0 "register_operand" "r")
+ (match_operand:XI 1 "memory_operand" "m")]
+ ENQCMD))]
+ "TARGET_ENQCMD"
+ "enqcmd<enqcmd_sfx>\t{%1, %0|%0, %1}"
+ [(set_attr "type" "other")])
+
;; WAITPKG
(define_insn "umwait"
@@ -20441,7 +20285,7 @@
"umwait\t%0"
[(set_attr "length" "3")])
-(define_insn "umonitor_<mode>"
+(define_insn "@umonitor_<mode>"
[(unspec_volatile [(match_operand:P 0 "register_operand" "r")]
UNSPECV_UMONITOR)]
"TARGET_WAITPKG"
diff --git a/gcc/config/i386/i386.opt b/gcc/config/i386/i386.opt
index 8f3dcf9..599e799 100644
--- a/gcc/config/i386/i386.opt
+++ b/gcc/config/i386/i386.opt
@@ -749,6 +749,10 @@ mavx512bitalg
Target Report Mask(ISA_AVX512BITALG) Var(ix86_isa_flags) Save
Support MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, AVX, AVX2, AVX512F and AVX512BITALG built-in functions and code generation.
+mavx512vp2intersect
+Target Report Mask(ISA_AVX512VP2INTERSECT) Var(ix86_isa_flags2) Save
+Support AVX512VP2INTERSECT built-in functions and code generation.
+
mfma
Target Report Mask(ISA_FMA) Var(ix86_isa_flags) Save
Support MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, AVX and FMA built-in functions and code generation.
@@ -1106,3 +1110,7 @@ mavx512bf16
Target Report Mask(ISA_AVX512BF16) Var(ix86_isa_flags2) Save
Support MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, AVX, AVX2, AVX512F and
AVX512BF16 built-in functions and code generation.
+
+menqcmd
+Target Report Mask(ISA_ENQCMD) Var(ix86_isa_flags2) Save
+Support ENQCMD built-in functions and code generation. \ No newline at end of file
diff --git a/gcc/config/i386/immintrin.h b/gcc/config/i386/immintrin.h
index d99886a..743aa74 100644
--- a/gcc/config/i386/immintrin.h
+++ b/gcc/config/i386/immintrin.h
@@ -96,6 +96,10 @@
#include <avx512bitalgintrin.h>
+#include <avx512vp2intersectintrin.h>
+
+#include <avx512vp2intersectvlintrin.h>
+
#include <shaintrin.h>
#include <lzcntintrin.h>
@@ -134,6 +138,8 @@
#include <avx512bf16intrin.h>
+#include <enqcmdintrin.h>
+
#include <rdseedintrin.h>
#include <prfchwintrin.h>
diff --git a/gcc/config/i386/mmintrin.h b/gcc/config/i386/mmintrin.h
index 238b3df..c4b2e0c 100644
--- a/gcc/config/i386/mmintrin.h
+++ b/gcc/config/i386/mmintrin.h
@@ -29,7 +29,9 @@
#if defined __x86_64__ && !defined __SSE__ || !defined __MMX__
#pragma GCC push_options
-#ifdef __x86_64__
+#ifdef __MMX_WITH_SSE__
+#pragma GCC target("sse2")
+#elif defined __x86_64__
#pragma GCC target("sse,mmx")
#else
#pragma GCC target("mmx")
@@ -315,7 +317,11 @@ _m_paddd (__m64 __m1, __m64 __m2)
/* Add the 64-bit values in M1 to the 64-bit values in M2. */
#ifndef __SSE2__
#pragma GCC push_options
+#ifdef __MMX_WITH_SSE__
+#pragma GCC target("sse2")
+#else
#pragma GCC target("sse2,mmx")
+#endif
#define __DISABLE_SSE2__
#endif /* __SSE2__ */
@@ -427,7 +433,11 @@ _m_psubd (__m64 __m1, __m64 __m2)
/* Add the 64-bit values in M1 to the 64-bit values in M2. */
#ifndef __SSE2__
#pragma GCC push_options
+#ifdef __MMX_WITH_SSE__
+#pragma GCC target("sse2")
+#else
#pragma GCC target("sse2,mmx")
+#endif
#define __DISABLE_SSE2__
#endif /* __SSE2__ */
diff --git a/gcc/config/i386/mmx.md b/gcc/config/i386/mmx.md
index b566cc8..4c71e66 100644
--- a/gcc/config/i386/mmx.md
+++ b/gcc/config/i386/mmx.md
@@ -45,7 +45,7 @@
;; 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])
+(define_mode_iterator MMXMODEI8 [V8QI V4HI V2SI (V1DI "TARGET_SSE2")])
;; All 8-byte vector modes handled by MMX
(define_mode_iterator MMXMODE [V8QI V4HI V2SI V1DI V2SF])
@@ -70,7 +70,7 @@
(define_expand "mov<mode>"
[(set (match_operand:MMXMODE 0 "nonimmediate_operand")
(match_operand:MMXMODE 1 "nonimmediate_operand"))]
- "TARGET_MMX"
+ "TARGET_MMX || TARGET_MMX_WITH_SSE"
{
ix86_expand_vector_move (<MODE>mode, operands);
DONE;
@@ -81,7 +81,7 @@
"=r ,o ,r,r ,m ,?!y,!y,?!y,m ,r ,?!y,v,v,v,m,r,v,!y,*x")
(match_operand:MMXMODE 1 "nonimm_or_0_operand"
"rCo,rC,C,rm,rC,C ,!y,m ,?!y,?!y,r ,C,v,m,v,v,r,*x,!y"))]
- "TARGET_MMX
+ "(TARGET_MMX || TARGET_MMX_WITH_SSE)
&& !(MEM_P (operands[0]) && MEM_P (operands[1]))"
{
switch (get_attr_type (insn))
@@ -232,19 +232,24 @@
(define_expand "movmisalign<mode>"
[(set (match_operand:MMXMODE 0 "nonimmediate_operand")
(match_operand:MMXMODE 1 "nonimmediate_operand"))]
- "TARGET_MMX"
+ "TARGET_MMX || TARGET_MMX_WITH_SSE"
{
ix86_expand_vector_move (<MODE>mode, operands);
DONE;
})
(define_insn "sse_movntq"
- [(set (match_operand:DI 0 "memory_operand" "=m")
- (unspec:DI [(match_operand:DI 1 "register_operand" "y")]
+ [(set (match_operand:DI 0 "memory_operand" "=m,m")
+ (unspec:DI [(match_operand:DI 1 "register_operand" "y,r")]
UNSPEC_MOVNTQ))]
- "TARGET_SSE || TARGET_3DNOW_A"
- "movntq\t{%1, %0|%0, %1}"
- [(set_attr "type" "mmxmov")
+ "(TARGET_MMX || TARGET_MMX_WITH_SSE)
+ && (TARGET_SSE || TARGET_3DNOW_A)"
+ "@
+ movntq\t{%1, %0|%0, %1}
+ movnti\t{%1, %0|%0, %1}"
+ [(set_attr "isa" "*,x64")
+ (set_attr "mmx_isa" "native,*")
+ (set_attr "type" "mmxmov,ssemov")
(set_attr "mode" "DI")])
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@@ -576,14 +581,27 @@
(set_attr "prefix_extra" "1")
(set_attr "mode" "V2SF")])
-(define_insn "*vec_dupv2sf"
- [(set (match_operand:V2SF 0 "register_operand" "=y")
+(define_insn_and_split "*vec_dupv2sf"
+ [(set (match_operand:V2SF 0 "register_operand" "=y,x,Yv")
(vec_duplicate:V2SF
- (match_operand:SF 1 "register_operand" "0")))]
- "TARGET_MMX"
- "punpckldq\t%0, %0"
- [(set_attr "type" "mmxcvt")
- (set_attr "mode" "DI")])
+ (match_operand:SF 1 "register_operand" "0,0,Yv")))]
+ "TARGET_MMX || TARGET_MMX_WITH_SSE"
+ "@
+ punpckldq\t%0, %0
+ #
+ #"
+ "TARGET_SSE && reload_completed
+ && SSE_REGNO_P (REGNO (operands[0]))"
+ [(set (match_dup 0)
+ (vec_duplicate:V4SF (match_dup 1)))]
+{
+ operands[0] = lowpart_subreg (V4SFmode, operands[0],
+ GET_MODE (operands[0]));
+}
+ [(set_attr "isa" "*,sse_noavx,avx")
+ (set_attr "mmx_isa" "native,*,*")
+ (set_attr "type" "mmxcvt,ssemov,ssemov")
+ (set_attr "mode" "DI,TI,TI")])
(define_insn "*mmx_concatv2sf"
[(set (match_operand:V2SF 0 "register_operand" "=y,y")
@@ -601,9 +619,9 @@
[(match_operand:V2SF 0 "register_operand")
(match_operand:SF 1 "register_operand")
(match_operand 2 "const_int_operand")]
- "TARGET_MMX"
+ "TARGET_MMX || TARGET_MMX_WITH_SSE"
{
- ix86_expand_vector_set (false, operands[0], operands[1],
+ ix86_expand_vector_set (TARGET_MMX_WITH_SSE, operands[0], operands[1],
INTVAL (operands[2]));
DONE;
})
@@ -615,11 +633,13 @@
(vec_select:SF
(match_operand:V2SF 1 "nonimmediate_operand" " xm,x,ym,y,m,m")
(parallel [(const_int 0)])))]
- "TARGET_MMX && !(MEM_P (operands[0]) && MEM_P (operands[1]))"
+ "(TARGET_MMX || TARGET_MMX_WITH_SSE)
+ && !(MEM_P (operands[0]) && MEM_P (operands[1]))"
"#"
"&& reload_completed"
[(set (match_dup 0) (match_dup 1))]
- "operands[1] = gen_lowpart (SFmode, operands[1]);")
+ "operands[1] = gen_lowpart (SFmode, operands[1]);"
+ [(set_attr "mmx_isa" "*,*,native,native,*,*")])
;; Avoid combining registers from different units in a single alternative,
;; see comment above inline_secondary_memory_needed function in i386.c
@@ -628,7 +648,8 @@
(vec_select:SF
(match_operand:V2SF 1 "nonimmediate_operand" " 0,x,x,o,o,o,o")
(parallel [(const_int 1)])))]
- "TARGET_MMX && !(MEM_P (operands[0]) && MEM_P (operands[1]))"
+ "(TARGET_MMX || TARGET_MMX_WITH_SSE)
+ && !(MEM_P (operands[0]) && MEM_P (operands[1]))"
"@
punpckhdq\t%0, %0
%vmovshdup\t{%1, %0|%0, %1}
@@ -638,6 +659,7 @@
#
#"
[(set_attr "isa" "*,sse3,noavx,*,*,*,*")
+ (set_attr "mmx_isa" "native,*,*,native,*,*,*")
(set_attr "type" "mmxcvt,sse,sseshuf1,mmxmov,ssemov,fmov,imov")
(set (attr "length_immediate")
(if_then_else (eq_attr "alternative" "2")
@@ -655,7 +677,7 @@
(vec_select:SF
(match_operand:V2SF 1 "memory_operand")
(parallel [(const_int 1)])))]
- "TARGET_MMX && reload_completed"
+ "(TARGET_MMX || TARGET_MMX_WITH_SSE) && reload_completed"
[(set (match_dup 0) (match_dup 1))]
"operands[1] = adjust_address (operands[1], SFmode, 4);")
@@ -663,19 +685,20 @@
[(match_operand:SF 0 "register_operand")
(match_operand:V2SF 1 "register_operand")
(match_operand 2 "const_int_operand")]
- "TARGET_MMX"
+ "TARGET_MMX || TARGET_MMX_WITH_SSE"
{
- ix86_expand_vector_extract (false, operands[0], operands[1],
- INTVAL (operands[2]));
+ ix86_expand_vector_extract (TARGET_MMX_WITH_SSE, operands[0],
+ operands[1], INTVAL (operands[2]));
DONE;
})
(define_expand "vec_initv2sfsf"
[(match_operand:V2SF 0 "register_operand")
(match_operand 1)]
- "TARGET_SSE"
+ "(TARGET_MMX || TARGET_MMX_WITH_SSE) && TARGET_SSE"
{
- ix86_expand_vector_init (false, operands[0], operands[1]);
+ ix86_expand_vector_init (TARGET_MMX_WITH_SSE, operands[0],
+ operands[1]);
DONE;
})
@@ -688,55 +711,87 @@
(define_expand "mmx_<plusminus_insn><mode>3"
[(set (match_operand:MMXMODEI8 0 "register_operand")
(plusminus:MMXMODEI8
- (match_operand:MMXMODEI8 1 "nonimmediate_operand")
- (match_operand:MMXMODEI8 2 "nonimmediate_operand")))]
- "TARGET_MMX || (TARGET_SSE2 && <MODE>mode == V1DImode)"
+ (match_operand:MMXMODEI8 1 "register_mmxmem_operand")
+ (match_operand:MMXMODEI8 2 "register_mmxmem_operand")))]
+ "TARGET_MMX || TARGET_MMX_WITH_SSE"
+ "ix86_fixup_binary_operands_no_copy (<CODE>, <MODE>mode, operands);")
+
+(define_expand "<plusminus_insn><mode>3"
+ [(set (match_operand:MMXMODEI 0 "register_operand")
+ (plusminus:MMXMODEI
+ (match_operand:MMXMODEI 1 "register_operand")
+ (match_operand:MMXMODEI 2 "register_operand")))]
+ "TARGET_MMX_WITH_SSE"
"ix86_fixup_binary_operands_no_copy (<CODE>, <MODE>mode, operands);")
(define_insn "*mmx_<plusminus_insn><mode>3"
- [(set (match_operand:MMXMODEI8 0 "register_operand" "=y")
+ [(set (match_operand:MMXMODEI8 0 "register_operand" "=y,x,Yv")
(plusminus:MMXMODEI8
- (match_operand:MMXMODEI8 1 "nonimmediate_operand" "<comm>0")
- (match_operand:MMXMODEI8 2 "nonimmediate_operand" "ym")))]
- "(TARGET_MMX || (TARGET_SSE2 && <MODE>mode == V1DImode))
+ (match_operand:MMXMODEI8 1 "register_mmxmem_operand" "<comm>0,0,Yv")
+ (match_operand:MMXMODEI8 2 "register_mmxmem_operand" "ym,x,Yv")))]
+ "(TARGET_MMX || TARGET_MMX_WITH_SSE)
&& ix86_binary_operator_ok (<CODE>, <MODE>mode, operands)"
- "p<plusminus_mnemonic><mmxvecsize>\t{%2, %0|%0, %2}"
- [(set_attr "type" "mmxadd")
- (set_attr "mode" "DI")])
+ "@
+ p<plusminus_mnemonic><mmxvecsize>\t{%2, %0|%0, %2}
+ p<plusminus_mnemonic><mmxvecsize>\t{%2, %0|%0, %2}
+ vp<plusminus_mnemonic><mmxvecsize>\t{%2, %1, %0|%0, %1, %2}"
+ [(set_attr "isa" "*,sse2_noavx,avx")
+ (set_attr "mmx_isa" "native,*,*")
+ (set_attr "type" "mmxadd,sseadd,sseadd")
+ (set_attr "mode" "DI,TI,TI")])
(define_expand "mmx_<plusminus_insn><mode>3"
[(set (match_operand:MMXMODE12 0 "register_operand")
(sat_plusminus:MMXMODE12
- (match_operand:MMXMODE12 1 "nonimmediate_operand")
- (match_operand:MMXMODE12 2 "nonimmediate_operand")))]
- "TARGET_MMX"
+ (match_operand:MMXMODE12 1 "register_mmxmem_operand")
+ (match_operand:MMXMODE12 2 "register_mmxmem_operand")))]
+ "TARGET_MMX || TARGET_MMX_WITH_SSE"
"ix86_fixup_binary_operands_no_copy (<CODE>, <MODE>mode, operands);")
(define_insn "*mmx_<plusminus_insn><mode>3"
- [(set (match_operand:MMXMODE12 0 "register_operand" "=y")
+ [(set (match_operand:MMXMODE12 0 "register_operand" "=y,x,Yv")
(sat_plusminus:MMXMODE12
- (match_operand:MMXMODE12 1 "nonimmediate_operand" "<comm>0")
- (match_operand:MMXMODE12 2 "nonimmediate_operand" "ym")))]
- "TARGET_MMX && ix86_binary_operator_ok (<CODE>, <MODE>mode, operands)"
- "p<plusminus_mnemonic><mmxvecsize>\t{%2, %0|%0, %2}"
- [(set_attr "type" "mmxadd")
- (set_attr "mode" "DI")])
+ (match_operand:MMXMODE12 1 "register_mmxmem_operand" "<comm>0,0,Yv")
+ (match_operand:MMXMODE12 2 "register_mmxmem_operand" "ym,x,Yv")))]
+ "(TARGET_MMX || TARGET_MMX_WITH_SSE)
+ && ix86_binary_operator_ok (<CODE>, <MODE>mode, operands)"
+ "@
+ p<plusminus_mnemonic><mmxvecsize>\t{%2, %0|%0, %2}
+ p<plusminus_mnemonic><mmxvecsize>\t{%2, %0|%0, %2}
+ vp<plusminus_mnemonic><mmxvecsize>\t{%2, %1, %0|%0, %1, %2}"
+ [(set_attr "isa" "*,sse2_noavx,avx")
+ (set_attr "mmx_isa" "native,*,*")
+ (set_attr "type" "mmxadd,sseadd,sseadd")
+ (set_attr "mode" "DI,TI,TI")])
(define_expand "mmx_mulv4hi3"
[(set (match_operand:V4HI 0 "register_operand")
- (mult:V4HI (match_operand:V4HI 1 "nonimmediate_operand")
- (match_operand:V4HI 2 "nonimmediate_operand")))]
- "TARGET_MMX"
+ (mult:V4HI (match_operand:V4HI 1 "register_mmxmem_operand")
+ (match_operand:V4HI 2 "register_mmxmem_operand")))]
+ "TARGET_MMX || TARGET_MMX_WITH_SSE"
+ "ix86_fixup_binary_operands_no_copy (MULT, V4HImode, operands);")
+
+(define_expand "mulv4hi3"
+ [(set (match_operand:V4HI 0 "register_operand")
+ (mult:V4HI (match_operand:V4HI 1 "register_operand")
+ (match_operand:V4HI 2 "register_operand")))]
+ "TARGET_MMX_WITH_SSE"
"ix86_fixup_binary_operands_no_copy (MULT, V4HImode, operands);")
(define_insn "*mmx_mulv4hi3"
- [(set (match_operand:V4HI 0 "register_operand" "=y")
- (mult:V4HI (match_operand:V4HI 1 "nonimmediate_operand" "%0")
- (match_operand:V4HI 2 "nonimmediate_operand" "ym")))]
- "TARGET_MMX && ix86_binary_operator_ok (MULT, V4HImode, operands)"
- "pmullw\t{%2, %0|%0, %2}"
- [(set_attr "type" "mmxmul")
- (set_attr "mode" "DI")])
+ [(set (match_operand:V4HI 0 "register_operand" "=y,x,Yv")
+ (mult:V4HI (match_operand:V4HI 1 "register_mmxmem_operand" "%0,0,Yv")
+ (match_operand:V4HI 2 "register_mmxmem_operand" "ym,x,Yv")))]
+ "(TARGET_MMX || TARGET_MMX_WITH_SSE)
+ && ix86_binary_operator_ok (MULT, V4HImode, operands)"
+ "@
+ pmullw\t{%2, %0|%0, %2}
+ pmullw\t{%2, %0|%0, %2}
+ vpmullw\t{%2, %1, %0|%0, %1, %2}"
+ [(set_attr "isa" "*,sse2_noavx,avx")
+ (set_attr "mmx_isa" "native,*,*")
+ (set_attr "type" "mmxmul,ssemul,ssemul")
+ (set_attr "mode" "DI,TI,TI")])
(define_expand "mmx_smulv4hi3_highpart"
[(set (match_operand:V4HI 0 "register_operand")
@@ -744,27 +799,33 @@
(lshiftrt:V4SI
(mult:V4SI
(sign_extend:V4SI
- (match_operand:V4HI 1 "nonimmediate_operand"))
+ (match_operand:V4HI 1 "register_mmxmem_operand"))
(sign_extend:V4SI
- (match_operand:V4HI 2 "nonimmediate_operand")))
+ (match_operand:V4HI 2 "register_mmxmem_operand")))
(const_int 16))))]
- "TARGET_MMX"
+ "TARGET_MMX || TARGET_MMX_WITH_SSE"
"ix86_fixup_binary_operands_no_copy (MULT, V4HImode, operands);")
(define_insn "*mmx_smulv4hi3_highpart"
- [(set (match_operand:V4HI 0 "register_operand" "=y")
+ [(set (match_operand:V4HI 0 "register_operand" "=y,x,Yv")
(truncate:V4HI
(lshiftrt:V4SI
(mult:V4SI
(sign_extend:V4SI
- (match_operand:V4HI 1 "nonimmediate_operand" "%0"))
+ (match_operand:V4HI 1 "register_mmxmem_operand" "%0,0,Yv"))
(sign_extend:V4SI
- (match_operand:V4HI 2 "nonimmediate_operand" "ym")))
+ (match_operand:V4HI 2 "register_mmxmem_operand" "ym,x,Yv")))
(const_int 16))))]
- "TARGET_MMX && ix86_binary_operator_ok (MULT, V4HImode, operands)"
- "pmulhw\t{%2, %0|%0, %2}"
- [(set_attr "type" "mmxmul")
- (set_attr "mode" "DI")])
+ "(TARGET_MMX || TARGET_MMX_WITH_SSE)
+ && ix86_binary_operator_ok (MULT, V4HImode, operands)"
+ "@
+ pmulhw\t{%2, %0|%0, %2}
+ pmulhw\t{%2, %0|%0, %2}
+ vpmulhw\t{%2, %1, %0|%0, %1, %2}"
+ [(set_attr "isa" "*,sse2_noavx,avx")
+ (set_attr "mmx_isa" "native,*,*")
+ (set_attr "type" "mmxmul,ssemul,ssemul")
+ (set_attr "mode" "DI,TI,TI")])
(define_expand "mmx_umulv4hi3_highpart"
[(set (match_operand:V4HI 0 "register_operand")
@@ -772,28 +833,35 @@
(lshiftrt:V4SI
(mult:V4SI
(zero_extend:V4SI
- (match_operand:V4HI 1 "nonimmediate_operand"))
+ (match_operand:V4HI 1 "register_mmxmem_operand"))
(zero_extend:V4SI
- (match_operand:V4HI 2 "nonimmediate_operand")))
+ (match_operand:V4HI 2 "register_mmxmem_operand")))
(const_int 16))))]
- "TARGET_SSE || TARGET_3DNOW_A"
+ "(TARGET_MMX || TARGET_MMX_WITH_SSE)
+ && (TARGET_SSE || TARGET_3DNOW_A)"
"ix86_fixup_binary_operands_no_copy (MULT, V4HImode, operands);")
(define_insn "*mmx_umulv4hi3_highpart"
- [(set (match_operand:V4HI 0 "register_operand" "=y")
+ [(set (match_operand:V4HI 0 "register_operand" "=y,x,Yv")
(truncate:V4HI
(lshiftrt:V4SI
(mult:V4SI
(zero_extend:V4SI
- (match_operand:V4HI 1 "nonimmediate_operand" "%0"))
+ (match_operand:V4HI 1 "register_mmxmem_operand" "%0,0,Yv"))
(zero_extend:V4SI
- (match_operand:V4HI 2 "nonimmediate_operand" "ym")))
+ (match_operand:V4HI 2 "register_mmxmem_operand" "ym,x,Yv")))
(const_int 16))))]
- "(TARGET_SSE || TARGET_3DNOW_A)
+ "(TARGET_MMX || TARGET_MMX_WITH_SSE)
+ && (TARGET_SSE || TARGET_3DNOW_A)
&& ix86_binary_operator_ok (MULT, V4HImode, operands)"
- "pmulhuw\t{%2, %0|%0, %2}"
- [(set_attr "type" "mmxmul")
- (set_attr "mode" "DI")])
+ "@
+ pmulhuw\t{%2, %0|%0, %2}
+ pmulhuw\t{%2, %0|%0, %2}
+ vpmulhuw\t{%2, %1, %0|%0, %1, %2}"
+ [(set_attr "isa" "*,sse2_noavx,avx")
+ (set_attr "mmx_isa" "native,*,*")
+ (set_attr "type" "mmxmul,ssemul,ssemul")
+ (set_attr "mode" "DI,TI,TI")])
(define_expand "mmx_pmaddwd"
[(set (match_operand:V2SI 0 "register_operand")
@@ -801,11 +869,11 @@
(mult:V2SI
(sign_extend:V2SI
(vec_select:V2HI
- (match_operand:V4HI 1 "nonimmediate_operand")
+ (match_operand:V4HI 1 "register_mmxmem_operand")
(parallel [(const_int 0) (const_int 2)])))
(sign_extend:V2SI
(vec_select:V2HI
- (match_operand:V4HI 2 "nonimmediate_operand")
+ (match_operand:V4HI 2 "register_mmxmem_operand")
(parallel [(const_int 0) (const_int 2)]))))
(mult:V2SI
(sign_extend:V2SI
@@ -814,20 +882,20 @@
(sign_extend:V2SI
(vec_select:V2HI (match_dup 2)
(parallel [(const_int 1) (const_int 3)]))))))]
- "TARGET_MMX"
+ "TARGET_MMX || TARGET_MMX_WITH_SSE"
"ix86_fixup_binary_operands_no_copy (MULT, V4HImode, operands);")
(define_insn "*mmx_pmaddwd"
- [(set (match_operand:V2SI 0 "register_operand" "=y")
+ [(set (match_operand:V2SI 0 "register_operand" "=y,x,Yv")
(plus:V2SI
(mult:V2SI
(sign_extend:V2SI
(vec_select:V2HI
- (match_operand:V4HI 1 "nonimmediate_operand" "%0")
+ (match_operand:V4HI 1 "register_mmxmem_operand" "%0,0,Yv")
(parallel [(const_int 0) (const_int 2)])))
(sign_extend:V2SI
(vec_select:V2HI
- (match_operand:V4HI 2 "nonimmediate_operand" "ym")
+ (match_operand:V4HI 2 "register_mmxmem_operand" "ym,x,Yv")
(parallel [(const_int 0) (const_int 2)]))))
(mult:V2SI
(sign_extend:V2SI
@@ -836,10 +904,16 @@
(sign_extend:V2SI
(vec_select:V2HI (match_dup 2)
(parallel [(const_int 1) (const_int 3)]))))))]
- "TARGET_MMX && ix86_binary_operator_ok (MULT, V4HImode, operands)"
- "pmaddwd\t{%2, %0|%0, %2}"
- [(set_attr "type" "mmxmul")
- (set_attr "mode" "DI")])
+ "(TARGET_MMX || TARGET_MMX_WITH_SSE)
+ && ix86_binary_operator_ok (MULT, V4HImode, operands)"
+ "@
+ pmaddwd\t{%2, %0|%0, %2}
+ pmaddwd\t{%2, %0|%0, %2}
+ vpmaddwd\t{%2, %1, %0|%0, %1, %2}"
+ [(set_attr "isa" "*,sse2_noavx,avx")
+ (set_attr "mmx_isa" "native,*,*")
+ (set_attr "type" "mmxmul,sseiadd,sseiadd")
+ (set_attr "mode" "DI,TI,TI")])
(define_expand "mmx_pmulhrwv4hi3"
[(set (match_operand:V4HI 0 "register_operand")
@@ -881,96 +955,157 @@
(mult:V1DI
(zero_extend:V1DI
(vec_select:V1SI
- (match_operand:V2SI 1 "nonimmediate_operand")
+ (match_operand:V2SI 1 "register_mmxmem_operand")
(parallel [(const_int 0)])))
(zero_extend:V1DI
(vec_select:V1SI
- (match_operand:V2SI 2 "nonimmediate_operand")
+ (match_operand:V2SI 2 "register_mmxmem_operand")
(parallel [(const_int 0)])))))]
- "TARGET_SSE2"
+ "(TARGET_MMX || TARGET_MMX_WITH_SSE) && TARGET_SSE2"
"ix86_fixup_binary_operands_no_copy (MULT, V2SImode, operands);")
(define_insn "*sse2_umulv1siv1di3"
- [(set (match_operand:V1DI 0 "register_operand" "=y")
+ [(set (match_operand:V1DI 0 "register_operand" "=y,x,Yv")
(mult:V1DI
(zero_extend:V1DI
(vec_select:V1SI
- (match_operand:V2SI 1 "nonimmediate_operand" "%0")
+ (match_operand:V2SI 1 "register_mmxmem_operand" "%0,0,Yv")
(parallel [(const_int 0)])))
(zero_extend:V1DI
(vec_select:V1SI
- (match_operand:V2SI 2 "nonimmediate_operand" "ym")
+ (match_operand:V2SI 2 "register_mmxmem_operand" "ym,x,Yv")
(parallel [(const_int 0)])))))]
- "TARGET_SSE2 && ix86_binary_operator_ok (MULT, V2SImode, operands)"
- "pmuludq\t{%2, %0|%0, %2}"
- [(set_attr "type" "mmxmul")
- (set_attr "mode" "DI")])
+ "(TARGET_MMX || TARGET_MMX_WITH_SSE)
+ && TARGET_SSE2
+ && ix86_binary_operator_ok (MULT, V2SImode, operands)"
+ "@
+ pmuludq\t{%2, %0|%0, %2}
+ pmuludq\t{%2, %0|%0, %2}
+ vpmuludq\t{%2, %1, %0|%0, %1, %2}"
+ [(set_attr "isa" "*,sse2_noavx,avx")
+ (set_attr "mmx_isa" "native,*,*")
+ (set_attr "type" "mmxmul,ssemul,ssemul")
+ (set_attr "mode" "DI,TI,TI")])
(define_expand "mmx_<code>v4hi3"
[(set (match_operand:V4HI 0 "register_operand")
(smaxmin:V4HI
- (match_operand:V4HI 1 "nonimmediate_operand")
- (match_operand:V4HI 2 "nonimmediate_operand")))]
- "TARGET_SSE || TARGET_3DNOW_A"
+ (match_operand:V4HI 1 "register_mmxmem_operand")
+ (match_operand:V4HI 2 "register_mmxmem_operand")))]
+ "(TARGET_MMX || TARGET_MMX_WITH_SSE)
+ && (TARGET_SSE || TARGET_3DNOW_A)"
+ "ix86_fixup_binary_operands_no_copy (<CODE>, V4HImode, operands);")
+
+(define_expand "<code>v4hi3"
+ [(set (match_operand:V4HI 0 "register_operand")
+ (smaxmin:V4HI
+ (match_operand:V4HI 1 "register_operand")
+ (match_operand:V4HI 2 "register_operand")))]
+ "TARGET_MMX_WITH_SSE"
"ix86_fixup_binary_operands_no_copy (<CODE>, V4HImode, operands);")
(define_insn "*mmx_<code>v4hi3"
- [(set (match_operand:V4HI 0 "register_operand" "=y")
+ [(set (match_operand:V4HI 0 "register_operand" "=y,x,Yv")
(smaxmin:V4HI
- (match_operand:V4HI 1 "nonimmediate_operand" "%0")
- (match_operand:V4HI 2 "nonimmediate_operand" "ym")))]
- "(TARGET_SSE || TARGET_3DNOW_A)
+ (match_operand:V4HI 1 "register_mmxmem_operand" "%0,0,Yv")
+ (match_operand:V4HI 2 "register_mmxmem_operand" "ym,x,Yv")))]
+ "(TARGET_MMX || TARGET_MMX_WITH_SSE)
+ && (TARGET_SSE || TARGET_3DNOW_A)
&& ix86_binary_operator_ok (<CODE>, V4HImode, operands)"
- "p<maxmin_int>w\t{%2, %0|%0, %2}"
- [(set_attr "type" "mmxadd")
- (set_attr "mode" "DI")])
+ "@
+ p<maxmin_int>w\t{%2, %0|%0, %2}
+ p<maxmin_int>w\t{%2, %0|%0, %2}
+ vp<maxmin_int>w\t{%2, %1, %0|%0, %1, %2}"
+ [(set_attr "isa" "*,sse2_noavx,avx")
+ (set_attr "mmx_isa" "native,*,*")
+ (set_attr "type" "mmxadd,sseiadd,sseiadd")
+ (set_attr "mode" "DI,TI,TI")])
(define_expand "mmx_<code>v8qi3"
[(set (match_operand:V8QI 0 "register_operand")
(umaxmin:V8QI
- (match_operand:V8QI 1 "nonimmediate_operand")
- (match_operand:V8QI 2 "nonimmediate_operand")))]
- "TARGET_SSE || TARGET_3DNOW_A"
+ (match_operand:V8QI 1 "register_mmxmem_operand")
+ (match_operand:V8QI 2 "register_mmxmem_operand")))]
+ "(TARGET_MMX || TARGET_MMX_WITH_SSE)
+ && (TARGET_SSE || TARGET_3DNOW_A)"
+ "ix86_fixup_binary_operands_no_copy (<CODE>, V8QImode, operands);")
+
+(define_expand "<code>v8qi3"
+ [(set (match_operand:V8QI 0 "register_operand")
+ (umaxmin:V8QI
+ (match_operand:V8QI 1 "register_operand")
+ (match_operand:V8QI 2 "register_operand")))]
+ "TARGET_MMX_WITH_SSE"
"ix86_fixup_binary_operands_no_copy (<CODE>, V8QImode, operands);")
(define_insn "*mmx_<code>v8qi3"
- [(set (match_operand:V8QI 0 "register_operand" "=y")
+ [(set (match_operand:V8QI 0 "register_operand" "=y,x,Yv")
(umaxmin:V8QI
- (match_operand:V8QI 1 "nonimmediate_operand" "%0")
- (match_operand:V8QI 2 "nonimmediate_operand" "ym")))]
- "(TARGET_SSE || TARGET_3DNOW_A)
+ (match_operand:V8QI 1 "register_mmxmem_operand" "%0,0,Yv")
+ (match_operand:V8QI 2 "register_mmxmem_operand" "ym,x,Yv")))]
+ "(TARGET_MMX || TARGET_MMX_WITH_SSE)
+ && (TARGET_SSE || TARGET_3DNOW_A)
&& ix86_binary_operator_ok (<CODE>, V8QImode, operands)"
- "p<maxmin_int>b\t{%2, %0|%0, %2}"
- [(set_attr "type" "mmxadd")
- (set_attr "mode" "DI")])
+ "@
+ p<maxmin_int>b\t{%2, %0|%0, %2}
+ p<maxmin_int>b\t{%2, %0|%0, %2}
+ vp<maxmin_int>b\t{%2, %1, %0|%0, %1, %2}"
+ [(set_attr "isa" "*,sse2_noavx,avx")
+ (set_attr "mmx_isa" "native,*,*")
+ (set_attr "type" "mmxadd,sseiadd,sseiadd")
+ (set_attr "mode" "DI,TI,TI")])
(define_insn "mmx_ashr<mode>3"
- [(set (match_operand:MMXMODE24 0 "register_operand" "=y")
+ [(set (match_operand:MMXMODE24 0 "register_operand" "=y,x,Yv")
(ashiftrt:MMXMODE24
- (match_operand:MMXMODE24 1 "register_operand" "0")
- (match_operand:DI 2 "nonmemory_operand" "yN")))]
- "TARGET_MMX"
- "psra<mmxvecsize>\t{%2, %0|%0, %2}"
- [(set_attr "type" "mmxshft")
+ (match_operand:MMXMODE24 1 "register_operand" "0,0,Yv")
+ (match_operand:DI 2 "nonmemory_operand" "yN,xN,YvN")))]
+ "TARGET_MMX || TARGET_MMX_WITH_SSE"
+ "@
+ psra<mmxvecsize>\t{%2, %0|%0, %2}
+ psra<mmxvecsize>\t{%2, %0|%0, %2}
+ vpsra<mmxvecsize>\t{%2, %1, %0|%0, %1, %2}"
+ [(set_attr "isa" "*,sse2_noavx,avx")
+ (set_attr "mmx_isa" "native,*,*")
+ (set_attr "type" "mmxshft,sseishft,sseishft")
(set (attr "length_immediate")
(if_then_else (match_operand 2 "const_int_operand")
(const_string "1")
(const_string "0")))
- (set_attr "mode" "DI")])
+ (set_attr "mode" "DI,TI,TI")])
+
+(define_expand "ashr<mode>3"
+ [(set (match_operand:MMXMODE24 0 "register_operand")
+ (ashiftrt:MMXMODE24
+ (match_operand:MMXMODE24 1 "register_operand")
+ (match_operand:DI 2 "nonmemory_operand")))]
+ "TARGET_MMX_WITH_SSE")
(define_insn "mmx_<shift_insn><mode>3"
- [(set (match_operand:MMXMODE248 0 "register_operand" "=y")
+ [(set (match_operand:MMXMODE248 0 "register_operand" "=y,x,Yv")
(any_lshift:MMXMODE248
- (match_operand:MMXMODE248 1 "register_operand" "0")
- (match_operand:DI 2 "nonmemory_operand" "yN")))]
- "TARGET_MMX"
- "p<vshift><mmxvecsize>\t{%2, %0|%0, %2}"
- [(set_attr "type" "mmxshft")
+ (match_operand:MMXMODE248 1 "register_operand" "0,0,Yv")
+ (match_operand:DI 2 "nonmemory_operand" "yN,xN,YvN")))]
+ "TARGET_MMX || TARGET_MMX_WITH_SSE"
+ "@
+ p<vshift><mmxvecsize>\t{%2, %0|%0, %2}
+ p<vshift><mmxvecsize>\t{%2, %0|%0, %2}
+ vp<vshift><mmxvecsize>\t{%2, %1, %0|%0, %1, %2}"
+ [(set_attr "isa" "*,sse2_noavx,avx")
+ (set_attr "mmx_isa" "native,*,*")
+ (set_attr "type" "mmxshft,sseishft,sseishft")
(set (attr "length_immediate")
(if_then_else (match_operand 2 "const_int_operand")
(const_string "1")
(const_string "0")))
- (set_attr "mode" "DI")])
+ (set_attr "mode" "DI,TI,TI")])
+
+(define_expand "<shift_insn><mode>3"
+ [(set (match_operand:MMXMODE248 0 "register_operand")
+ (any_lshift:MMXMODE248
+ (match_operand:MMXMODE248 1 "register_operand")
+ (match_operand:DI 2 "nonmemory_operand")))]
+ "TARGET_MMX_WITH_SSE")
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
@@ -981,30 +1116,41 @@
(define_expand "mmx_eq<mode>3"
[(set (match_operand:MMXMODEI 0 "register_operand")
(eq:MMXMODEI
- (match_operand:MMXMODEI 1 "nonimmediate_operand")
- (match_operand:MMXMODEI 2 "nonimmediate_operand")))]
- "TARGET_MMX"
+ (match_operand:MMXMODEI 1 "register_mmxmem_operand")
+ (match_operand:MMXMODEI 2 "register_mmxmem_operand")))]
+ "TARGET_MMX || TARGET_MMX_WITH_SSE"
"ix86_fixup_binary_operands_no_copy (EQ, <MODE>mode, operands);")
(define_insn "*mmx_eq<mode>3"
- [(set (match_operand:MMXMODEI 0 "register_operand" "=y")
+ [(set (match_operand:MMXMODEI 0 "register_operand" "=y,x,Yv")
(eq:MMXMODEI
- (match_operand:MMXMODEI 1 "nonimmediate_operand" "%0")
- (match_operand:MMXMODEI 2 "nonimmediate_operand" "ym")))]
- "TARGET_MMX && ix86_binary_operator_ok (EQ, <MODE>mode, operands)"
- "pcmpeq<mmxvecsize>\t{%2, %0|%0, %2}"
- [(set_attr "type" "mmxcmp")
- (set_attr "mode" "DI")])
+ (match_operand:MMXMODEI 1 "register_mmxmem_operand" "%0,0,Yv")
+ (match_operand:MMXMODEI 2 "register_mmxmem_operand" "ym,x,Yv")))]
+ "(TARGET_MMX || TARGET_MMX_WITH_SSE)
+ && ix86_binary_operator_ok (EQ, <MODE>mode, operands)"
+ "@
+ pcmpeq<mmxvecsize>\t{%2, %0|%0, %2}
+ pcmpeq<mmxvecsize>\t{%2, %0|%0, %2}
+ vpcmpeq<mmxvecsize>\t{%2, %1, %0|%0, %1, %2}"
+ [(set_attr "isa" "*,sse2_noavx,avx")
+ (set_attr "mmx_isa" "native,*,*")
+ (set_attr "type" "mmxcmp,ssecmp,ssecmp")
+ (set_attr "mode" "DI,TI,TI")])
(define_insn "mmx_gt<mode>3"
- [(set (match_operand:MMXMODEI 0 "register_operand" "=y")
+ [(set (match_operand:MMXMODEI 0 "register_operand" "=y,x,Yv")
(gt:MMXMODEI
- (match_operand:MMXMODEI 1 "register_operand" "0")
- (match_operand:MMXMODEI 2 "nonimmediate_operand" "ym")))]
- "TARGET_MMX"
- "pcmpgt<mmxvecsize>\t{%2, %0|%0, %2}"
- [(set_attr "type" "mmxcmp")
- (set_attr "mode" "DI")])
+ (match_operand:MMXMODEI 1 "register_operand" "0,0,Yv")
+ (match_operand:MMXMODEI 2 "register_mmxmem_operand" "ym,x,Yv")))]
+ "TARGET_MMX || TARGET_MMX_WITH_SSE"
+ "@
+ pcmpgt<mmxvecsize>\t{%2, %0|%0, %2}
+ pcmpgt<mmxvecsize>\t{%2, %0|%0, %2}
+ vpcmpgt<mmxvecsize>\t{%2, %1, %0|%0, %1, %2}"
+ [(set_attr "isa" "*,sse2_noavx,avx")
+ (set_attr "mmx_isa" "native,*,*")
+ (set_attr "type" "mmxcmp,ssecmp,ssecmp")
+ (set_attr "mode" "DI,TI,TI")])
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
@@ -1013,32 +1159,51 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(define_insn "mmx_andnot<mode>3"
- [(set (match_operand:MMXMODEI 0 "register_operand" "=y")
+ [(set (match_operand:MMXMODEI 0 "register_operand" "=y,x,Yv")
(and:MMXMODEI
- (not:MMXMODEI (match_operand:MMXMODEI 1 "register_operand" "0"))
- (match_operand:MMXMODEI 2 "nonimmediate_operand" "ym")))]
- "TARGET_MMX"
- "pandn\t{%2, %0|%0, %2}"
- [(set_attr "type" "mmxadd")
- (set_attr "mode" "DI")])
+ (not:MMXMODEI (match_operand:MMXMODEI 1 "register_operand" "0,0,Yv"))
+ (match_operand:MMXMODEI 2 "register_mmxmem_operand" "ym,x,Yv")))]
+ "TARGET_MMX || TARGET_MMX_WITH_SSE"
+ "@
+ pandn\t{%2, %0|%0, %2}
+ pandn\t{%2, %0|%0, %2}
+ vpandn\t{%2, %1, %0|%0, %1, %2}"
+ [(set_attr "isa" "*,sse2_noavx,avx")
+ (set_attr "mmx_isa" "native,*,*")
+ (set_attr "type" "mmxadd,sselog,sselog")
+ (set_attr "mode" "DI,TI,TI")])
(define_expand "mmx_<code><mode>3"
[(set (match_operand:MMXMODEI 0 "register_operand")
(any_logic:MMXMODEI
- (match_operand:MMXMODEI 1 "nonimmediate_operand")
- (match_operand:MMXMODEI 2 "nonimmediate_operand")))]
- "TARGET_MMX"
+ (match_operand:MMXMODEI 1 "register_mmxmem_operand")
+ (match_operand:MMXMODEI 2 "register_mmxmem_operand")))]
+ "TARGET_MMX || TARGET_MMX_WITH_SSE"
+ "ix86_fixup_binary_operands_no_copy (<CODE>, <MODE>mode, operands);")
+
+(define_expand "<code><mode>3"
+ [(set (match_operand:MMXMODEI 0 "register_operand")
+ (any_logic:MMXMODEI
+ (match_operand:MMXMODEI 1 "register_operand")
+ (match_operand:MMXMODEI 2 "register_operand")))]
+ "TARGET_MMX_WITH_SSE"
"ix86_fixup_binary_operands_no_copy (<CODE>, <MODE>mode, operands);")
(define_insn "*mmx_<code><mode>3"
- [(set (match_operand:MMXMODEI 0 "register_operand" "=y")
+ [(set (match_operand:MMXMODEI 0 "register_operand" "=y,x,Yv")
(any_logic:MMXMODEI
- (match_operand:MMXMODEI 1 "nonimmediate_operand" "%0")
- (match_operand:MMXMODEI 2 "nonimmediate_operand" "ym")))]
- "TARGET_MMX && ix86_binary_operator_ok (<CODE>, <MODE>mode, operands)"
- "p<logic>\t{%2, %0|%0, %2}"
- [(set_attr "type" "mmxadd")
- (set_attr "mode" "DI")])
+ (match_operand:MMXMODEI 1 "register_mmxmem_operand" "%0,0,Yv")
+ (match_operand:MMXMODEI 2 "register_mmxmem_operand" "ym,x,Yv")))]
+ "(TARGET_MMX || TARGET_MMX_WITH_SSE)
+ && ix86_binary_operator_ok (<CODE>, <MODE>mode, operands)"
+ "@
+ p<logic>\t{%2, %0|%0, %2}
+ p<logic>\t{%2, %0|%0, %2}
+ vp<logic>\t{%2, %1, %0|%0, %1, %2}"
+ [(set_attr "isa" "*,sse2_noavx,avx")
+ (set_attr "mmx_isa" "native,*,*")
+ (set_attr "type" "mmxadd,sselog,sselog")
+ (set_attr "mode" "DI,TI,TI")])
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
@@ -1046,123 +1211,180 @@
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-(define_insn "mmx_packsswb"
- [(set (match_operand:V8QI 0 "register_operand" "=y")
+;; Used in signed and unsigned truncations with saturation.
+(define_code_iterator any_s_truncate [ss_truncate us_truncate])
+;; Instruction suffix for truncations with saturation.
+(define_code_attr s_trunsuffix [(ss_truncate "s") (us_truncate "u")])
+
+(define_insn_and_split "mmx_pack<s_trunsuffix>swb"
+ [(set (match_operand:V8QI 0 "register_operand" "=y,x,Yv")
(vec_concat:V8QI
- (ss_truncate:V4QI
- (match_operand:V4HI 1 "register_operand" "0"))
- (ss_truncate:V4QI
- (match_operand:V4HI 2 "nonimmediate_operand" "ym"))))]
- "TARGET_MMX"
- "packsswb\t{%2, %0|%0, %2}"
- [(set_attr "type" "mmxshft")
- (set_attr "mode" "DI")])
+ (any_s_truncate:V4QI
+ (match_operand:V4HI 1 "register_operand" "0,0,Yv"))
+ (any_s_truncate:V4QI
+ (match_operand:V4HI 2 "register_mmxmem_operand" "ym,x,Yv"))))]
+ "TARGET_MMX || TARGET_MMX_WITH_SSE"
+ "@
+ pack<s_trunsuffix>swb\t{%2, %0|%0, %2}
+ #
+ #"
+ "TARGET_SSE2 && reload_completed
+ && SSE_REGNO_P (REGNO (operands[0]))"
+ [(const_int 0)]
+ "ix86_split_mmx_pack (operands, <any_s_truncate:CODE>); DONE;"
+ [(set_attr "mmx_isa" "native,sse_noavx,avx")
+ (set_attr "type" "mmxshft,sselog,sselog")
+ (set_attr "mode" "DI,TI,TI")])
-(define_insn "mmx_packssdw"
- [(set (match_operand:V4HI 0 "register_operand" "=y")
+(define_insn_and_split "mmx_packssdw"
+ [(set (match_operand:V4HI 0 "register_operand" "=y,x,Yv")
(vec_concat:V4HI
(ss_truncate:V2HI
- (match_operand:V2SI 1 "register_operand" "0"))
+ (match_operand:V2SI 1 "register_operand" "0,0,Yv"))
(ss_truncate:V2HI
- (match_operand:V2SI 2 "nonimmediate_operand" "ym"))))]
- "TARGET_MMX"
- "packssdw\t{%2, %0|%0, %2}"
- [(set_attr "type" "mmxshft")
- (set_attr "mode" "DI")])
-
-(define_insn "mmx_packuswb"
- [(set (match_operand:V8QI 0 "register_operand" "=y")
- (vec_concat:V8QI
- (us_truncate:V4QI
- (match_operand:V4HI 1 "register_operand" "0"))
- (us_truncate:V4QI
- (match_operand:V4HI 2 "nonimmediate_operand" "ym"))))]
- "TARGET_MMX"
- "packuswb\t{%2, %0|%0, %2}"
- [(set_attr "type" "mmxshft")
- (set_attr "mode" "DI")])
+ (match_operand:V2SI 2 "register_mmxmem_operand" "ym,x,Yv"))))]
+ "TARGET_MMX || TARGET_MMX_WITH_SSE"
+ "@
+ packssdw\t{%2, %0|%0, %2}
+ #
+ #"
+ "TARGET_SSE2 && reload_completed
+ && SSE_REGNO_P (REGNO (operands[0]))"
+ [(const_int 0)]
+ "ix86_split_mmx_pack (operands, SS_TRUNCATE); DONE;"
+ [(set_attr "mmx_isa" "native,sse_noavx,avx")
+ (set_attr "type" "mmxshft,sselog,sselog")
+ (set_attr "mode" "DI,TI,TI")])
-(define_insn "mmx_punpckhbw"
- [(set (match_operand:V8QI 0 "register_operand" "=y")
+(define_insn_and_split "mmx_punpckhbw"
+ [(set (match_operand:V8QI 0 "register_operand" "=y,x,Yv")
(vec_select:V8QI
(vec_concat:V16QI
- (match_operand:V8QI 1 "register_operand" "0")
- (match_operand:V8QI 2 "nonimmediate_operand" "ym"))
+ (match_operand:V8QI 1 "register_operand" "0,0,Yv")
+ (match_operand:V8QI 2 "register_mmxmem_operand" "ym,x,Yv"))
(parallel [(const_int 4) (const_int 12)
(const_int 5) (const_int 13)
(const_int 6) (const_int 14)
(const_int 7) (const_int 15)])))]
- "TARGET_MMX"
- "punpckhbw\t{%2, %0|%0, %2}"
- [(set_attr "type" "mmxcvt")
- (set_attr "mode" "DI")])
+ "TARGET_MMX || TARGET_MMX_WITH_SSE"
+ "@
+ punpckhbw\t{%2, %0|%0, %2}
+ #
+ #"
+ "TARGET_SSE2 && reload_completed
+ && SSE_REGNO_P (REGNO (operands[0]))"
+ [(const_int 0)]
+ "ix86_split_mmx_punpck (operands, true); DONE;"
+ [(set_attr "mmx_isa" "native,sse_noavx,avx")
+ (set_attr "type" "mmxcvt,sselog,sselog")
+ (set_attr "mode" "DI,TI,TI")])
-(define_insn "mmx_punpcklbw"
- [(set (match_operand:V8QI 0 "register_operand" "=y")
+(define_insn_and_split "mmx_punpcklbw"
+ [(set (match_operand:V8QI 0 "register_operand" "=y,x,Yv")
(vec_select:V8QI
(vec_concat:V16QI
- (match_operand:V8QI 1 "register_operand" "0")
- (match_operand:V8QI 2 "nonimmediate_operand" "ym"))
+ (match_operand:V8QI 1 "register_operand" "0,0,Yv")
+ (match_operand:V8QI 2 "register_mmxmem_operand" "ym,x,Yv"))
(parallel [(const_int 0) (const_int 8)
(const_int 1) (const_int 9)
(const_int 2) (const_int 10)
(const_int 3) (const_int 11)])))]
- "TARGET_MMX"
- "punpcklbw\t{%2, %0|%0, %k2}"
- [(set_attr "type" "mmxcvt")
- (set_attr "mode" "DI")])
+ "TARGET_MMX || TARGET_MMX_WITH_SSE"
+ "@
+ punpcklbw\t{%2, %0|%0, %k2}
+ #
+ #"
+ "TARGET_SSE2 && reload_completed
+ && SSE_REGNO_P (REGNO (operands[0]))"
+ [(const_int 0)]
+ "ix86_split_mmx_punpck (operands, false); DONE;"
+ [(set_attr "mmx_isa" "native,sse_noavx,avx")
+ (set_attr "type" "mmxcvt,sselog,sselog")
+ (set_attr "mode" "DI,TI,TI")])
-(define_insn "mmx_punpckhwd"
- [(set (match_operand:V4HI 0 "register_operand" "=y")
+(define_insn_and_split "mmx_punpckhwd"
+ [(set (match_operand:V4HI 0 "register_operand" "=y,x,Yv")
(vec_select:V4HI
(vec_concat:V8HI
- (match_operand:V4HI 1 "register_operand" "0")
- (match_operand:V4HI 2 "nonimmediate_operand" "ym"))
+ (match_operand:V4HI 1 "register_operand" "0,0,Yv")
+ (match_operand:V4HI 2 "register_mmxmem_operand" "ym,x,Yv"))
(parallel [(const_int 2) (const_int 6)
(const_int 3) (const_int 7)])))]
- "TARGET_MMX"
- "punpckhwd\t{%2, %0|%0, %2}"
- [(set_attr "type" "mmxcvt")
- (set_attr "mode" "DI")])
+ "TARGET_MMX || TARGET_MMX_WITH_SSE"
+ "@
+ punpckhwd\t{%2, %0|%0, %2}
+ #
+ #"
+ "TARGET_SSE2 && reload_completed
+ && SSE_REGNO_P (REGNO (operands[0]))"
+ [(const_int 0)]
+ "ix86_split_mmx_punpck (operands, true); DONE;"
+ [(set_attr "mmx_isa" "native,sse_noavx,avx")
+ (set_attr "type" "mmxcvt,sselog,sselog")
+ (set_attr "mode" "DI,TI,TI")])
-(define_insn "mmx_punpcklwd"
- [(set (match_operand:V4HI 0 "register_operand" "=y")
+(define_insn_and_split "mmx_punpcklwd"
+ [(set (match_operand:V4HI 0 "register_operand" "=y,x,Yv")
(vec_select:V4HI
(vec_concat:V8HI
- (match_operand:V4HI 1 "register_operand" "0")
- (match_operand:V4HI 2 "nonimmediate_operand" "ym"))
+ (match_operand:V4HI 1 "register_operand" "0,0,Yv")
+ (match_operand:V4HI 2 "register_mmxmem_operand" "ym,x,Yv"))
(parallel [(const_int 0) (const_int 4)
(const_int 1) (const_int 5)])))]
- "TARGET_MMX"
- "punpcklwd\t{%2, %0|%0, %k2}"
- [(set_attr "type" "mmxcvt")
- (set_attr "mode" "DI")])
+ "TARGET_MMX || TARGET_MMX_WITH_SSE"
+ "@
+ punpcklwd\t{%2, %0|%0, %k2}
+ #
+ #"
+ "TARGET_SSE2 && reload_completed
+ && SSE_REGNO_P (REGNO (operands[0]))"
+ [(const_int 0)]
+ "ix86_split_mmx_punpck (operands, false); DONE;"
+ [(set_attr "mmx_isa" "native,sse_noavx,avx")
+ (set_attr "type" "mmxcvt,sselog,sselog")
+ (set_attr "mode" "DI,TI,TI")])
-(define_insn "mmx_punpckhdq"
- [(set (match_operand:V2SI 0 "register_operand" "=y")
+(define_insn_and_split "mmx_punpckhdq"
+ [(set (match_operand:V2SI 0 "register_operand" "=y,x,Yv")
(vec_select:V2SI
(vec_concat:V4SI
- (match_operand:V2SI 1 "register_operand" "0")
- (match_operand:V2SI 2 "nonimmediate_operand" "ym"))
+ (match_operand:V2SI 1 "register_operand" "0,0,Yv")
+ (match_operand:V2SI 2 "register_mmxmem_operand" "ym,x,Yv"))
(parallel [(const_int 1)
(const_int 3)])))]
- "TARGET_MMX"
- "punpckhdq\t{%2, %0|%0, %2}"
- [(set_attr "type" "mmxcvt")
- (set_attr "mode" "DI")])
+ "TARGET_MMX || TARGET_MMX_WITH_SSE"
+ "@
+ punpckhdq\t{%2, %0|%0, %2}
+ #
+ #"
+ "TARGET_SSE2 && reload_completed
+ && SSE_REGNO_P (REGNO (operands[0]))"
+ [(const_int 0)]
+ "ix86_split_mmx_punpck (operands, true); DONE;"
+ [(set_attr "mmx_isa" "native,sse_noavx,avx")
+ (set_attr "type" "mmxcvt,sselog,sselog")
+ (set_attr "mode" "DI,TI,TI")])
-(define_insn "mmx_punpckldq"
- [(set (match_operand:V2SI 0 "register_operand" "=y")
+(define_insn_and_split "mmx_punpckldq"
+ [(set (match_operand:V2SI 0 "register_operand" "=y,x,Yv")
(vec_select:V2SI
(vec_concat:V4SI
- (match_operand:V2SI 1 "register_operand" "0")
- (match_operand:V2SI 2 "nonimmediate_operand" "ym"))
+ (match_operand:V2SI 1 "register_operand" "0,0,Yv")
+ (match_operand:V2SI 2 "register_mmxmem_operand" "ym,x,Yv"))
(parallel [(const_int 0)
(const_int 2)])))]
- "TARGET_MMX"
- "punpckldq\t{%2, %0|%0, %k2}"
- [(set_attr "type" "mmxcvt")
- (set_attr "mode" "DI")])
+ "TARGET_MMX || TARGET_MMX_WITH_SSE"
+ "@
+ punpckldq\t{%2, %0|%0, %k2}
+ #
+ #"
+ "TARGET_SSE2 && reload_completed
+ && SSE_REGNO_P (REGNO (operands[0]))"
+ [(const_int 0)]
+ "ix86_split_mmx_punpck (operands, false); DONE;"
+ [(set_attr "mmx_isa" "native,sse_noavx,avx")
+ (set_attr "type" "mmxcvt,sselog,sselog")
+ (set_attr "mode" "DI,TI,TI")])
(define_expand "mmx_pinsrw"
[(set (match_operand:V4HI 0 "register_operand")
@@ -1171,50 +1393,72 @@
(match_operand:SI 2 "nonimmediate_operand"))
(match_operand:V4HI 1 "register_operand")
(match_operand:SI 3 "const_0_to_3_operand")))]
- "TARGET_SSE || TARGET_3DNOW_A"
+ "(TARGET_MMX || TARGET_MMX_WITH_SSE)
+ && (TARGET_SSE || TARGET_3DNOW_A)"
{
operands[2] = gen_lowpart (HImode, operands[2]);
operands[3] = GEN_INT (1 << INTVAL (operands[3]));
})
(define_insn "*mmx_pinsrw"
- [(set (match_operand:V4HI 0 "register_operand" "=y")
+ [(set (match_operand:V4HI 0 "register_operand" "=y,x,Yv")
(vec_merge:V4HI
(vec_duplicate:V4HI
- (match_operand:HI 2 "nonimmediate_operand" "rm"))
- (match_operand:V4HI 1 "register_operand" "0")
+ (match_operand:HI 2 "nonimmediate_operand" "rm,rm,rm"))
+ (match_operand:V4HI 1 "register_operand" "0,0,Yv")
(match_operand:SI 3 "const_int_operand")))]
- "(TARGET_SSE || TARGET_3DNOW_A)
+ "(TARGET_MMX || TARGET_MMX_WITH_SSE)
+ && (TARGET_SSE || TARGET_3DNOW_A)
&& ((unsigned) exact_log2 (INTVAL (operands[3]))
< GET_MODE_NUNITS (V4HImode))"
{
operands[3] = GEN_INT (exact_log2 (INTVAL (operands[3])));
- if (MEM_P (operands[2]))
- return "pinsrw\t{%3, %2, %0|%0, %2, %3}";
- else
- return "pinsrw\t{%3, %k2, %0|%0, %k2, %3}";
+ switch (which_alternative)
+ {
+ case 2:
+ if (MEM_P (operands[2]))
+ return "vpinsrw\t{%3, %2, %1, %0|%0, %1, %2, %3}";
+ else
+ return "vpinsrw\t{%3, %k2, %1, %0|%0, %1, %k2, %3}";
+ case 1:
+ case 0:
+ if (MEM_P (operands[2]))
+ return "pinsrw\t{%3, %2, %0|%0, %2, %3}";
+ else
+ return "pinsrw\t{%3, %k2, %0|%0, %k2, %3}";
+ default:
+ gcc_unreachable ();
+ }
}
- [(set_attr "type" "mmxcvt")
+ [(set_attr "isa" "*,sse2_noavx,avx")
+ (set_attr "mmx_isa" "native,*,*")
+ (set_attr "type" "mmxcvt,sselog,sselog")
(set_attr "length_immediate" "1")
- (set_attr "mode" "DI")])
+ (set_attr "mode" "DI,TI,TI")])
(define_insn "mmx_pextrw"
- [(set (match_operand:SI 0 "register_operand" "=r")
+ [(set (match_operand:SI 0 "register_operand" "=r,r")
(zero_extend:SI
(vec_select:HI
- (match_operand:V4HI 1 "register_operand" "y")
- (parallel [(match_operand:SI 2 "const_0_to_3_operand" "n")]))))]
- "TARGET_SSE || TARGET_3DNOW_A"
- "pextrw\t{%2, %1, %0|%0, %1, %2}"
- [(set_attr "type" "mmxcvt")
+ (match_operand:V4HI 1 "register_operand" "y,Yv")
+ (parallel [(match_operand:SI 2 "const_0_to_3_operand" "n,n")]))))]
+ "(TARGET_MMX || TARGET_MMX_WITH_SSE)
+ && (TARGET_SSE || TARGET_3DNOW_A)"
+ "@
+ pextrw\t{%2, %1, %0|%0, %1, %2}
+ %vpextrw\t{%2, %1, %0|%0, %1, %2}"
+ [(set_attr "isa" "*,sse2")
+ (set_attr "mmx_isa" "native,*")
+ (set_attr "type" "mmxcvt,sselog1")
(set_attr "length_immediate" "1")
- (set_attr "mode" "DI")])
+ (set_attr "mode" "DI,TI")])
(define_expand "mmx_pshufw"
[(match_operand:V4HI 0 "register_operand")
- (match_operand:V4HI 1 "nonimmediate_operand")
+ (match_operand:V4HI 1 "register_mmxmem_operand")
(match_operand:SI 2 "const_int_operand")]
- "TARGET_SSE || TARGET_3DNOW_A"
+ "(TARGET_MMX || TARGET_MMX_WITH_SSE)
+ && (TARGET_SSE || TARGET_3DNOW_A)"
{
int mask = INTVAL (operands[2]);
emit_insn (gen_mmx_pshufw_1 (operands[0], operands[1],
@@ -1226,14 +1470,15 @@
})
(define_insn "mmx_pshufw_1"
- [(set (match_operand:V4HI 0 "register_operand" "=y")
+ [(set (match_operand:V4HI 0 "register_operand" "=y,Yv")
(vec_select:V4HI
- (match_operand:V4HI 1 "nonimmediate_operand" "ym")
+ (match_operand:V4HI 1 "register_mmxmem_operand" "ym,Yv")
(parallel [(match_operand 2 "const_0_to_3_operand")
(match_operand 3 "const_0_to_3_operand")
(match_operand 4 "const_0_to_3_operand")
(match_operand 5 "const_0_to_3_operand")])))]
- "TARGET_SSE || TARGET_3DNOW_A"
+ "(TARGET_MMX || TARGET_MMX_WITH_SSE)
+ && (TARGET_SSE || TARGET_3DNOW_A)"
{
int mask = 0;
mask |= INTVAL (operands[2]) << 0;
@@ -1242,11 +1487,21 @@
mask |= INTVAL (operands[5]) << 6;
operands[2] = GEN_INT (mask);
- return "pshufw\t{%2, %1, %0|%0, %1, %2}";
+ switch (which_alternative)
+ {
+ case 0:
+ return "pshufw\t{%2, %1, %0|%0, %1, %2}";
+ case 1:
+ return "%vpshuflw\t{%2, %1, %0|%0, %1, %2}";
+ default:
+ gcc_unreachable ();
+ }
}
- [(set_attr "type" "mmxcvt")
+ [(set_attr "isa" "*,sse2")
+ (set_attr "mmx_isa" "native,*")
+ (set_attr "type" "mmxcvt,sselog")
(set_attr "length_immediate" "1")
- (set_attr "mode" "DI")])
+ (set_attr "mode" "DI,TI")])
(define_insn "mmx_pswapdv2si2"
[(set (match_operand:V2SI 0 "register_operand" "=y")
@@ -1259,25 +1514,77 @@
(set_attr "prefix_extra" "1")
(set_attr "mode" "DI")])
-(define_insn "*vec_dupv4hi"
- [(set (match_operand:V4HI 0 "register_operand" "=y")
+(define_insn_and_split "*vec_dupv4hi"
+ [(set (match_operand:V4HI 0 "register_operand" "=y,Yv,Yw")
(vec_duplicate:V4HI
(truncate:HI
- (match_operand:SI 1 "register_operand" "0"))))]
- "TARGET_SSE || TARGET_3DNOW_A"
- "pshufw\t{$0, %0, %0|%0, %0, 0}"
- [(set_attr "type" "mmxcvt")
- (set_attr "length_immediate" "1")
- (set_attr "mode" "DI")])
+ (match_operand:SI 1 "register_operand" "0,Yv,r"))))]
+ "(TARGET_MMX || TARGET_MMX_WITH_SSE)
+ && (TARGET_SSE || TARGET_3DNOW_A)"
+ "@
+ pshufw\t{$0, %0, %0|%0, %0, 0}
+ #
+ #"
+ "TARGET_SSE2 && reload_completed
+ && SSE_REGNO_P (REGNO (operands[0]))"
+ [(const_int 0)]
+{
+ rtx op;
+ operands[0] = lowpart_subreg (V8HImode, operands[0],
+ GET_MODE (operands[0]));
+ if (TARGET_AVX2)
+ {
+ operands[1] = lowpart_subreg (HImode, operands[1],
+ GET_MODE (operands[1]));
+ op = gen_rtx_VEC_DUPLICATE (V8HImode, operands[1]);
+ }
+ else
+ {
+ operands[1] = lowpart_subreg (V8HImode, operands[1],
+ GET_MODE (operands[1]));
+ rtx mask = gen_rtx_PARALLEL (VOIDmode,
+ gen_rtvec (8,
+ GEN_INT (0),
+ GEN_INT (0),
+ GEN_INT (0),
+ GEN_INT (0),
+ GEN_INT (4),
+ GEN_INT (5),
+ GEN_INT (6),
+ GEN_INT (7)));
+
+ op = gen_rtx_VEC_SELECT (V8HImode, operands[1], mask);
+ }
+ emit_insn (gen_rtx_SET (operands[0], op));
+ DONE;
+}
+ [(set_attr "mmx_isa" "native,sse,avx")
+ (set_attr "type" "mmxcvt,sselog1,ssemov")
+ (set_attr "length_immediate" "1,1,0")
+ (set_attr "mode" "DI,TI,TI")])
-(define_insn "*vec_dupv2si"
- [(set (match_operand:V2SI 0 "register_operand" "=y")
+(define_insn_and_split "*vec_dupv2si"
+ [(set (match_operand:V2SI 0 "register_operand" "=y,x,Yv,Yw")
(vec_duplicate:V2SI
- (match_operand:SI 1 "register_operand" "0")))]
- "TARGET_MMX"
- "punpckldq\t%0, %0"
- [(set_attr "type" "mmxcvt")
- (set_attr "mode" "DI")])
+ (match_operand:SI 1 "register_operand" "0,0,Yv,r")))]
+ "TARGET_MMX || TARGET_MMX_WITH_SSE"
+ "@
+ punpckldq\t%0, %0
+ #
+ #
+ #"
+ "TARGET_SSE && reload_completed
+ && SSE_REGNO_P (REGNO (operands[0]))"
+ [(set (match_dup 0)
+ (vec_duplicate:V4SI (match_dup 1)))]
+{
+ operands[0] = lowpart_subreg (V4SImode, operands[0],
+ GET_MODE (operands[0]));
+}
+ [(set_attr "isa" "*,sse_noavx,avx,avx")
+ (set_attr "mmx_isa" "native,*,*,*")
+ (set_attr "type" "mmxcvt,ssemov,ssemov,ssemov")
+ (set_attr "mode" "DI,TI,TI,TI")])
(define_insn "*mmx_concatv2si"
[(set (match_operand:V2SI 0 "register_operand" "=y,y")
@@ -1295,9 +1602,9 @@
[(match_operand:V2SI 0 "register_operand")
(match_operand:SI 1 "register_operand")
(match_operand 2 "const_int_operand")]
- "TARGET_MMX"
+ "TARGET_MMX || TARGET_MMX_WITH_SSE"
{
- ix86_expand_vector_set (false, operands[0], operands[1],
+ ix86_expand_vector_set (TARGET_MMX_WITH_SSE, operands[0], operands[1],
INTVAL (operands[2]));
DONE;
})
@@ -1309,11 +1616,13 @@
(vec_select:SI
(match_operand:V2SI 1 "nonimmediate_operand" "xm,x,ym,y,m")
(parallel [(const_int 0)])))]
- "TARGET_MMX && !(MEM_P (operands[0]) && MEM_P (operands[1]))"
+ "(TARGET_MMX || TARGET_MMX_WITH_SSE)
+ && !(MEM_P (operands[0]) && MEM_P (operands[1]))"
"#"
"&& reload_completed"
[(set (match_dup 0) (match_dup 1))]
- "operands[1] = gen_lowpart (SImode, operands[1]);")
+ "operands[1] = gen_lowpart (SImode, operands[1]);"
+ [(set_attr "mmx_isa" "*,*,native,native,*")])
;; Avoid combining registers from different units in a single alternative,
;; see comment above inline_secondary_memory_needed function in i386.c
@@ -1322,7 +1631,8 @@
(vec_select:SI
(match_operand:V2SI 1 "nonimmediate_operand" " 0,x,x,o,o,o")
(parallel [(const_int 1)])))]
- "TARGET_MMX && !(MEM_P (operands[0]) && MEM_P (operands[1]))"
+ "(TARGET_MMX || TARGET_MMX_WITH_SSE)
+ && !(MEM_P (operands[0]) && MEM_P (operands[1]))"
"@
punpckhdq\t%0, %0
%vpshufd\t{$0xe5, %1, %0|%0, %1, 0xe5}
@@ -1331,6 +1641,7 @@
#
#"
[(set_attr "isa" "*,sse2,noavx,*,*,*")
+ (set_attr "mmx_isa" "native,*,*,native,*,*")
(set_attr "type" "mmxcvt,sseshuf1,sseshuf1,mmxmov,ssemov,imov")
(set (attr "length_immediate")
(if_then_else (eq_attr "alternative" "1,2")
@@ -1344,7 +1655,7 @@
(vec_select:SI
(match_operand:V2SI 1 "memory_operand")
(parallel [(const_int 1)])))]
- "TARGET_MMX && reload_completed"
+ "(TARGET_MMX || TARGET_MMX_WITH_SSE) && reload_completed"
[(set (match_dup 0) (match_dup 1))]
"operands[1] = adjust_address (operands[1], SImode, 4);")
@@ -1361,25 +1672,27 @@
{
operands[1] = adjust_address (operands[1], SImode, INTVAL (operands[2]) * 4);
}
- [(set_attr "isa" "*,sse2,*")])
+ [(set_attr "isa" "*,sse2,*")
+ (set_attr "mmx_isa" "native,*,*")])
(define_expand "vec_extractv2sisi"
[(match_operand:SI 0 "register_operand")
(match_operand:V2SI 1 "register_operand")
(match_operand 2 "const_int_operand")]
- "TARGET_MMX"
+ "TARGET_MMX || TARGET_MMX_WITH_SSE"
{
- ix86_expand_vector_extract (false, operands[0], operands[1],
- INTVAL (operands[2]));
+ ix86_expand_vector_extract (TARGET_MMX_WITH_SSE, operands[0],
+ operands[1], INTVAL (operands[2]));
DONE;
})
(define_expand "vec_initv2sisi"
[(match_operand:V2SI 0 "register_operand")
(match_operand 1)]
- "TARGET_SSE"
+ "(TARGET_MMX || TARGET_MMX_WITH_SSE) && TARGET_SSE"
{
- ix86_expand_vector_init (false, operands[0], operands[1]);
+ ix86_expand_vector_init (TARGET_MMX_WITH_SSE, operands[0],
+ operands[1]);
DONE;
})
@@ -1387,9 +1700,9 @@
[(match_operand:V4HI 0 "register_operand")
(match_operand:HI 1 "register_operand")
(match_operand 2 "const_int_operand")]
- "TARGET_MMX"
+ "TARGET_MMX || TARGET_MMX_WITH_SSE"
{
- ix86_expand_vector_set (false, operands[0], operands[1],
+ ix86_expand_vector_set (TARGET_MMX_WITH_SSE, operands[0], operands[1],
INTVAL (operands[2]));
DONE;
})
@@ -1398,19 +1711,20 @@
[(match_operand:HI 0 "register_operand")
(match_operand:V4HI 1 "register_operand")
(match_operand 2 "const_int_operand")]
- "TARGET_MMX"
+ "TARGET_MMX || TARGET_MMX_WITH_SSE"
{
- ix86_expand_vector_extract (false, operands[0], operands[1],
- INTVAL (operands[2]));
+ ix86_expand_vector_extract (TARGET_MMX_WITH_SSE, operands[0],
+ operands[1], INTVAL (operands[2]));
DONE;
})
(define_expand "vec_initv4hihi"
[(match_operand:V4HI 0 "register_operand")
(match_operand 1)]
- "TARGET_SSE"
+ "(TARGET_MMX || TARGET_MMX_WITH_SSE) && TARGET_SSE"
{
- ix86_expand_vector_init (false, operands[0], operands[1]);
+ ix86_expand_vector_init (TARGET_MMX_WITH_SSE, operands[0],
+ operands[1]);
DONE;
})
@@ -1418,9 +1732,9 @@
[(match_operand:V8QI 0 "register_operand")
(match_operand:QI 1 "register_operand")
(match_operand 2 "const_int_operand")]
- "TARGET_MMX"
+ "TARGET_MMX || TARGET_MMX_WITH_SSE"
{
- ix86_expand_vector_set (false, operands[0], operands[1],
+ ix86_expand_vector_set (TARGET_MMX_WITH_SSE, operands[0], operands[1],
INTVAL (operands[2]));
DONE;
})
@@ -1429,19 +1743,20 @@
[(match_operand:QI 0 "register_operand")
(match_operand:V8QI 1 "register_operand")
(match_operand 2 "const_int_operand")]
- "TARGET_MMX"
+ "TARGET_MMX || TARGET_MMX_WITH_SSE"
{
- ix86_expand_vector_extract (false, operands[0], operands[1],
- INTVAL (operands[2]));
+ ix86_expand_vector_extract (TARGET_MMX_WITH_SSE, operands[0],
+ operands[1], INTVAL (operands[2]));
DONE;
})
(define_expand "vec_initv8qiqi"
[(match_operand:V8QI 0 "register_operand")
(match_operand 1)]
- "TARGET_SSE"
+ "(TARGET_MMX || TARGET_MMX_WITH_SSE) && TARGET_SSE"
{
- ix86_expand_vector_init (false, operands[0], operands[1]);
+ ix86_expand_vector_init (TARGET_MMX_WITH_SSE, operands[0],
+ operands[1]);
DONE;
})
@@ -1458,50 +1773,63 @@
(plus:V8HI
(plus:V8HI
(zero_extend:V8HI
- (match_operand:V8QI 1 "nonimmediate_operand"))
+ (match_operand:V8QI 1 "register_mmxmem_operand"))
(zero_extend:V8HI
- (match_operand:V8QI 2 "nonimmediate_operand")))
+ (match_operand:V8QI 2 "register_mmxmem_operand")))
(const_vector:V8HI [(const_int 1) (const_int 1)
(const_int 1) (const_int 1)
(const_int 1) (const_int 1)
(const_int 1) (const_int 1)]))
(const_int 1))))]
- "TARGET_SSE || TARGET_3DNOW"
+ "(TARGET_MMX || TARGET_MMX_WITH_SSE)
+ && (TARGET_SSE || TARGET_3DNOW)"
"ix86_fixup_binary_operands_no_copy (PLUS, V8QImode, operands);")
(define_insn "*mmx_uavgv8qi3"
- [(set (match_operand:V8QI 0 "register_operand" "=y")
+ [(set (match_operand:V8QI 0 "register_operand" "=y,x,Yv")
(truncate:V8QI
(lshiftrt:V8HI
(plus:V8HI
(plus:V8HI
(zero_extend:V8HI
- (match_operand:V8QI 1 "nonimmediate_operand" "%0"))
+ (match_operand:V8QI 1 "register_mmxmem_operand" "%0,0,Yv"))
(zero_extend:V8HI
- (match_operand:V8QI 2 "nonimmediate_operand" "ym")))
+ (match_operand:V8QI 2 "register_mmxmem_operand" "ym,x,Yv")))
(const_vector:V8HI [(const_int 1) (const_int 1)
(const_int 1) (const_int 1)
(const_int 1) (const_int 1)
(const_int 1) (const_int 1)]))
(const_int 1))))]
- "(TARGET_SSE || TARGET_3DNOW)
+ "(TARGET_MMX || TARGET_MMX_WITH_SSE)
+ && (TARGET_SSE || TARGET_3DNOW)
&& ix86_binary_operator_ok (PLUS, V8QImode, operands)"
{
- /* These two instructions have the same operation, but their encoding
- is different. Prefer the one that is de facto standard. */
- if (TARGET_SSE || TARGET_3DNOW_A)
- return "pavgb\t{%2, %0|%0, %2}";
- else
- return "pavgusb\t{%2, %0|%0, %2}";
+ switch (which_alternative)
+ {
+ case 2:
+ return "vpavgb\t{%2, %1, %0|%0, %1, %2}";
+ case 1:
+ case 0:
+ /* These two instructions have the same operation, but their encoding
+ is different. Prefer the one that is de facto standard. */
+ if (TARGET_SSE || TARGET_3DNOW_A)
+ return "pavgb\t{%2, %0|%0, %2}";
+ else
+ return "pavgusb\t{%2, %0|%0, %2}";
+ default:
+ gcc_unreachable ();
+ }
}
- [(set_attr "type" "mmxshft")
+ [(set_attr "isa" "*,sse2_noavx,avx")
+ (set_attr "mmx_isa" "native,*,*")
+ (set_attr "type" "mmxshft,sseiadd,sseiadd")
(set (attr "prefix_extra")
(if_then_else
(not (ior (match_test "TARGET_SSE")
(match_test "TARGET_3DNOW_A")))
(const_string "1")
(const_string "*")))
- (set_attr "mode" "DI")])
+ (set_attr "mode" "DI,TI,TI")])
(define_expand "mmx_uavgv4hi3"
[(set (match_operand:V4HI 0 "register_operand")
@@ -1510,52 +1838,82 @@
(plus:V4SI
(plus:V4SI
(zero_extend:V4SI
- (match_operand:V4HI 1 "nonimmediate_operand"))
+ (match_operand:V4HI 1 "register_mmxmem_operand"))
(zero_extend:V4SI
- (match_operand:V4HI 2 "nonimmediate_operand")))
+ (match_operand:V4HI 2 "register_mmxmem_operand")))
(const_vector:V4SI [(const_int 1) (const_int 1)
(const_int 1) (const_int 1)]))
(const_int 1))))]
- "TARGET_SSE || TARGET_3DNOW_A"
+ "(TARGET_MMX || TARGET_MMX_WITH_SSE)
+ && (TARGET_SSE || TARGET_3DNOW_A)"
"ix86_fixup_binary_operands_no_copy (PLUS, V4HImode, operands);")
(define_insn "*mmx_uavgv4hi3"
- [(set (match_operand:V4HI 0 "register_operand" "=y")
+ [(set (match_operand:V4HI 0 "register_operand" "=y,x,Yv")
(truncate:V4HI
(lshiftrt:V4SI
(plus:V4SI
(plus:V4SI
(zero_extend:V4SI
- (match_operand:V4HI 1 "nonimmediate_operand" "%0"))
+ (match_operand:V4HI 1 "register_mmxmem_operand" "%0,0,Yv"))
(zero_extend:V4SI
- (match_operand:V4HI 2 "nonimmediate_operand" "ym")))
+ (match_operand:V4HI 2 "register_mmxmem_operand" "ym,x,Yv")))
(const_vector:V4SI [(const_int 1) (const_int 1)
(const_int 1) (const_int 1)]))
(const_int 1))))]
- "(TARGET_SSE || TARGET_3DNOW_A)
+ "(TARGET_MMX || TARGET_MMX_WITH_SSE)
+ && (TARGET_SSE || TARGET_3DNOW_A)
&& ix86_binary_operator_ok (PLUS, V4HImode, operands)"
- "pavgw\t{%2, %0|%0, %2}"
- [(set_attr "type" "mmxshft")
- (set_attr "mode" "DI")])
+ "@
+ pavgw\t{%2, %0|%0, %2}
+ pavgw\t{%2, %0|%0, %2}
+ vpavgw\t{%2, %1, %0|%0, %1, %2}"
+ [(set_attr "isa" "*,sse2_noavx,avx")
+ (set_attr "mmx_isa" "native,*,*")
+ (set_attr "type" "mmxshft,sseiadd,sseiadd")
+ (set_attr "mode" "DI,TI,TI")])
(define_insn "mmx_psadbw"
- [(set (match_operand:V1DI 0 "register_operand" "=y")
- (unspec:V1DI [(match_operand:V8QI 1 "register_operand" "0")
- (match_operand:V8QI 2 "nonimmediate_operand" "ym")]
+ [(set (match_operand:V1DI 0 "register_operand" "=y,x,Yv")
+ (unspec:V1DI [(match_operand:V8QI 1 "register_operand" "0,0,Yv")
+ (match_operand:V8QI 2 "register_mmxmem_operand" "ym,x,Yv")]
UNSPEC_PSADBW))]
- "TARGET_SSE || TARGET_3DNOW_A"
- "psadbw\t{%2, %0|%0, %2}"
- [(set_attr "type" "mmxshft")
- (set_attr "mode" "DI")])
-
-(define_insn "mmx_pmovmskb"
- [(set (match_operand:SI 0 "register_operand" "=r")
- (unspec:SI [(match_operand:V8QI 1 "register_operand" "y")]
+ "(TARGET_MMX || TARGET_MMX_WITH_SSE)
+ && (TARGET_SSE || TARGET_3DNOW_A)"
+ "@
+ psadbw\t{%2, %0|%0, %2}
+ psadbw\t{%2, %0|%0, %2}
+ vpsadbw\t{%2, %1, %0|%0, %1, %2}"
+ [(set_attr "isa" "*,sse2_noavx,avx")
+ (set_attr "mmx_isa" "native,*,*")
+ (set_attr "type" "mmxshft,sseiadd,sseiadd")
+ (set_attr "mode" "DI,TI,TI")])
+
+(define_insn_and_split "mmx_pmovmskb"
+ [(set (match_operand:SI 0 "register_operand" "=r,r")
+ (unspec:SI [(match_operand:V8QI 1 "register_operand" "y,x")]
UNSPEC_MOVMSK))]
- "TARGET_SSE || TARGET_3DNOW_A"
- "pmovmskb\t{%1, %0|%0, %1}"
- [(set_attr "type" "mmxcvt")
- (set_attr "mode" "DI")])
+ "(TARGET_MMX || TARGET_MMX_WITH_SSE)
+ && (TARGET_SSE || TARGET_3DNOW_A)"
+ "@
+ pmovmskb\t{%1, %0|%0, %1}
+ #"
+ "TARGET_SSE2 && reload_completed
+ && SSE_REGNO_P (REGNO (operands[1]))"
+ [(set (match_dup 0)
+ (unspec:SI [(match_dup 1)] UNSPEC_MOVMSK))
+ (set (match_dup 0)
+ (zero_extend:SI (match_dup 2)))]
+{
+ /* Generate SSE pmovmskb and zero-extend from QImode to SImode. */
+ operands[1] = lowpart_subreg (V16QImode, operands[1],
+ GET_MODE (operands[1]));
+ operands[2] = lowpart_subreg (QImode, operands[0],
+ GET_MODE (operands[0]));
+}
+ [(set_attr "mmx_isa" "native,sse")
+ (set_attr "type" "mmxcvt,ssemov")
+ (set_attr "mode" "DI,TI")])
(define_expand "mmx_maskmovq"
[(set (match_operand:V8QI 0 "memory_operand")
@@ -1586,7 +1944,35 @@
[(UNSPECV_EMMS "emms")
(UNSPECV_FEMMS "femms")])
-(define_insn "mmx_<emms>"
+(define_expand "mmx_<emms>"
+ [(parallel
+ [(unspec_volatile [(const_int 0)] EMMS)
+ (clobber (reg:XF ST0_REG))
+ (clobber (reg:XF ST1_REG))
+ (clobber (reg:XF ST2_REG))
+ (clobber (reg:XF ST3_REG))
+ (clobber (reg:XF ST4_REG))
+ (clobber (reg:XF ST5_REG))
+ (clobber (reg:XF ST6_REG))
+ (clobber (reg:XF ST7_REG))
+ (clobber (reg:DI MM0_REG))
+ (clobber (reg:DI MM1_REG))
+ (clobber (reg:DI MM2_REG))
+ (clobber (reg:DI MM3_REG))
+ (clobber (reg:DI MM4_REG))
+ (clobber (reg:DI MM5_REG))
+ (clobber (reg:DI MM6_REG))
+ (clobber (reg:DI MM7_REG))])]
+ "TARGET_MMX || TARGET_MMX_WITH_SSE"
+{
+ if (!TARGET_MMX)
+ {
+ emit_insn (gen_nop ());
+ DONE;
+ }
+})
+
+(define_insn "*mmx_<emms>"
[(unspec_volatile [(const_int 0)] EMMS)
(clobber (reg:XF ST0_REG))
(clobber (reg:XF ST1_REG))
diff --git a/gcc/config/i386/predicates.md b/gcc/config/i386/predicates.md
index 865947d..5e8f671 100644
--- a/gcc/config/i386/predicates.md
+++ b/gcc/config/i386/predicates.md
@@ -49,6 +49,13 @@
(and (match_code "reg")
(match_test "MMX_REGNO_P (REGNO (op))")))
+;; Match register operands, but include memory operands for
+;; !TARGET_MMX_WITH_SSE.
+(define_predicate "register_mmxmem_operand"
+ (ior (match_operand 0 "register_operand")
+ (and (not (match_test "TARGET_MMX_WITH_SSE"))
+ (match_operand 0 "memory_operand"))))
+
;; True if the operand is an SSE register.
(define_predicate "sse_reg_operand"
(and (match_code "reg")
@@ -1397,9 +1404,6 @@
(define_predicate "compare_operator"
(match_code "compare"))
-(define_predicate "absneg_operator"
- (match_code "abs,neg"))
-
;; Return true if OP is a memory operand, aligned to
;; less than its natural alignment.
(define_predicate "misaligned_operand"
diff --git a/gcc/config/i386/sol2.h b/gcc/config/i386/sol2.h
index 5fc4cbc..4ef0ff4 100644
--- a/gcc/config/i386/sol2.h
+++ b/gcc/config/i386/sol2.h
@@ -55,7 +55,8 @@ along with GCC; see the file COPYING3. If not see
#define CPP_SPEC "%(cpp_subtarget)"
#undef CC1_SPEC
-#define CC1_SPEC "%(cc1_cpu) " ASAN_CC1_SPEC
+#define CC1_SPEC "%(cc1_cpu) " ASAN_CC1_SPEC \
+ " %{mx32:%e-mx32 is not supported on Solaris}"
/* GNU as understands --32 and --64, but the native Solaris
assembler requires -xarch=generic or -xarch=generic64 instead. */
@@ -117,11 +118,6 @@ along with GCC; see the file COPYING3. If not see
#undef LOCAL_LABEL_PREFIX
#define LOCAL_LABEL_PREFIX "."
-/* The Solaris 10 FCS as doesn't accept "#" comments, while later versions
- do. */
-#undef ASM_COMMENT_START
-#define ASM_COMMENT_START "/"
-
/* The 32-bit Solaris assembler does not support .quad. Do not use it. */
#ifndef HAVE_AS_IX86_QUAD
#undef ASM_QUAD
@@ -246,7 +242,7 @@ along with GCC; see the file COPYING3. If not see
/* -fsanitize=address is currently only supported for 32-bit. */
#define ASAN_REJECT_SPEC \
- DEF_ARCH64_SPEC("%e:-fsanitize=address is not supported in this configuration")
+ DEF_ARCH64_SPEC("%e-fsanitize=address is not supported in this configuration")
#undef NO_PROFILE_COUNTERS
diff --git a/gcc/config/i386/sse.md b/gcc/config/i386/sse.md
index 11363de..8f50cb1 100644
--- a/gcc/config/i386/sse.md
+++ b/gcc/config/i386/sse.md
@@ -188,6 +188,9 @@
;; For AVX512BITALG support
UNSPEC_VPSHUFBIT
+ ;; For VP2INTERSECT support
+ UNSPEC_VP2INTERSECT
+
;; For AVX512BF16 support
UNSPEC_VCVTNE2PS2BF16
UNSPEC_VCVTNEPS2BF16
@@ -279,6 +282,9 @@
(define_mode_iterator VF1
[(V16SF "TARGET_AVX512F") (V8SF "TARGET_AVX") V4SF])
+(define_mode_iterator VF1_AVX2
+ [(V16SF "TARGET_AVX512F") (V8SF "TARGET_AVX2") V4SF])
+
;; 128- and 256-bit SF vector modes
(define_mode_iterator VF1_128_256
[(V8SF "TARGET_AVX") V4SF])
@@ -592,6 +598,10 @@
(define_mode_attr ssequarterinsnmode
[(V16SF "V4SF") (V8DF "V2DF") (V16SI "TI") (V8DI "TI")])
+(define_mode_attr vecmemsuffix
+ [(V16SF "{z}") (V8SF "{y}") (V4SF "{x}")
+ (V8DF "{z}") (V4DF "{y}") (V2DF "{x}")])
+
(define_mode_attr ssedoublemodelower
[(V16QI "v16hi") (V32QI "v32hi") (V64QI "v64hi")
(V8HI "v8si") (V16HI "v16si") (V32HI "v32si")
@@ -1314,10 +1324,10 @@
;; from there.
(define_insn_and_split "movdi_to_sse"
- [(set (match_operand:V4SI 0 "register_operand" "=?x,x")
- (unspec:V4SI [(match_operand:DI 1 "nonimmediate_operand" "r,m")]
+ [(set (match_operand:V4SI 0 "register_operand" "=x,x,?x")
+ (unspec:V4SI [(match_operand:DI 1 "nonimmediate_operand" "r,m,r")]
UNSPEC_MOVDI_TO_SSE))
- (clobber (match_scratch:V4SI 2 "=&x,X"))]
+ (clobber (match_scratch:V4SI 2 "=X,X,&x"))]
"!TARGET_64BIT && TARGET_SSE2 && TARGET_INTER_UNIT_MOVES_TO_VEC"
"#"
"&& reload_completed"
@@ -1329,18 +1339,26 @@
Assemble the 64-bit DImode value in an xmm register. */
emit_insn (gen_sse2_loadld (operands[0], CONST0_RTX (V4SImode),
gen_lowpart (SImode, operands[1])));
- emit_insn (gen_sse2_loadld (operands[2], CONST0_RTX (V4SImode),
- gen_highpart (SImode, operands[1])));
- emit_insn (gen_vec_interleave_lowv4si (operands[0], operands[0],
- operands[2]));
- }
+ if (TARGET_SSE4_1)
+ emit_insn (gen_sse4_1_pinsrd (operands[0], operands[0],
+ gen_highpart (SImode, operands[1]),
+ GEN_INT (2)));
+ else
+ {
+ emit_insn (gen_sse2_loadld (operands[2], CONST0_RTX (V4SImode),
+ gen_highpart (SImode, operands[1])));
+ emit_insn (gen_vec_interleave_lowv4si (operands[0], operands[0],
+ operands[2]));
+ }
+ }
else if (memory_operand (operands[1], DImode))
emit_insn (gen_vec_concatv2di (gen_lowpart (V2DImode, operands[0]),
operands[1], const0_rtx));
else
gcc_unreachable ();
DONE;
-})
+}
+ [(set_attr "isa" "sse4,*,*")])
(define_split
[(set (match_operand:V4SF 0 "register_operand")
@@ -1705,41 +1723,58 @@
"TARGET_SSE"
"ix86_expand_fp_absneg_operator (<CODE>, <MODE>mode, operands); DONE;")
-(define_insn_and_split "*absneg<mode>2"
+(define_insn_and_split "*<code><mode>2"
[(set (match_operand:VF 0 "register_operand" "=x,x,v,v")
- (match_operator:VF 3 "absneg_operator"
- [(match_operand:VF 1 "vector_operand" "0, xBm,v, m")]))
+ (absneg:VF
+ (match_operand:VF 1 "vector_operand" "0, xBm,v, m")))
(use (match_operand:VF 2 "vector_operand" "xBm,0, vm,v"))]
"TARGET_SSE"
"#"
"&& reload_completed"
- [(const_int 0)]
+ [(set (match_dup 0) (match_dup 3))]
{
- enum rtx_code absneg_op;
- rtx op1, op2;
- rtx t;
+ enum rtx_code absneg_op = <CODE> == ABS ? AND : XOR;
if (TARGET_AVX)
{
if (MEM_P (operands[1]))
- op1 = operands[2], op2 = operands[1];
- else
- op1 = operands[1], op2 = operands[2];
+ std::swap (operands[1], operands[2]);
}
else
+ {
+ if (operands_match_p (operands[0], operands[2]))
+ std::swap (operands[1], operands[2]);
+ }
+
+ operands[3]
+ = gen_rtx_fmt_ee (absneg_op, <MODE>mode, operands[1], operands[2]);
+}
+ [(set_attr "isa" "noavx,noavx,avx,avx")])
+
+(define_insn_and_split "*nabs<mode>2"
+ [(set (match_operand:VF 0 "register_operand" "=x,x,v,v")
+ (neg:VF
+ (abs:VF
+ (match_operand:VF 1 "vector_operand" "0,xBm,v,m"))))
+ (use (match_operand:VF 2 "vector_operand" "xBm,0,vm,v"))]
+ "TARGET_SSE"
+ "#"
+ "&& reload_completed"
+ [(set (match_dup 0) (match_dup 3))]
+{
+ if (TARGET_AVX)
{
- op1 = operands[0];
- if (rtx_equal_p (operands[0], operands[1]))
- op2 = operands[2];
- else
- op2 = operands[1];
+ if (MEM_P (operands[1]))
+ std::swap (operands[1], operands[2]);
}
+ else
+ {
+ if (operands_match_p (operands[0], operands[2]))
+ std::swap (operands[1], operands[2]);
+ }
- absneg_op = GET_CODE (operands[3]) == NEG ? XOR : AND;
- t = gen_rtx_fmt_ee (absneg_op, <MODE>mode, op1, op2);
- t = gen_rtx_SET (operands[0], t);
- emit_insn (t);
- DONE;
+ operands[3]
+ = gen_rtx_fmt_ee (IOR, <MODE>mode, operands[1], operands[2]);
}
[(set_attr "isa" "noavx,noavx,avx,avx")])
@@ -1794,6 +1829,28 @@
(set_attr "type" "sseadd")
(set_attr "mode" "<MODE>")])
+;; Standard scalar operation patterns which preserve the rest of the
+;; vector for combiner.
+(define_insn "*<sse>_vm<plusminus_insn><mode>3"
+ [(set (match_operand:VF_128 0 "register_operand" "=x,v")
+ (vec_merge:VF_128
+ (vec_duplicate:VF_128
+ (plusminus:<ssescalarmode>
+ (vec_select:<ssescalarmode>
+ (match_operand:VF_128 1 "register_operand" "0,v")
+ (parallel [(const_int 0)]))
+ (match_operand:<ssescalarmode> 2 "nonimmediate_operand" "xm,vm")))
+ (match_dup 1)
+ (const_int 1)))]
+ "TARGET_SSE"
+ "@
+ <plusminus_mnemonic><ssescalarmodesuffix>\t{%2, %0|%0, %<iptr>2}
+ v<plusminus_mnemonic><ssescalarmodesuffix>\t{%2, %1, %0|%0, %1, %<iptr>2}"
+ [(set_attr "isa" "noavx,avx")
+ (set_attr "type" "sseadd")
+ (set_attr "prefix" "orig,vex")
+ (set_attr "mode" "<ssescalarmode>")])
+
(define_insn "<sse>_vm<plusminus_insn><mode>3<mask_scalar_name><round_scalar_name>"
[(set (match_operand:VF_128 0 "register_operand" "=x,v")
(vec_merge:VF_128
@@ -1848,6 +1905,29 @@
(set_attr "type" "ssemul")
(set_attr "mode" "<MODE>")])
+;; Standard scalar operation patterns which preserve the rest of the
+;; vector for combiner.
+(define_insn "*<sse>_vm<multdiv_mnemonic><mode>3"
+ [(set (match_operand:VF_128 0 "register_operand" "=x,v")
+ (vec_merge:VF_128
+ (vec_duplicate:VF_128
+ (multdiv:<ssescalarmode>
+ (vec_select:<ssescalarmode>
+ (match_operand:VF_128 1 "register_operand" "0,v")
+ (parallel [(const_int 0)]))
+ (match_operand:<ssescalarmode> 2 "nonimmediate_operand" "xm,vm")))
+ (match_dup 1)
+ (const_int 1)))]
+ "TARGET_SSE"
+ "@
+ <multdiv_mnemonic><ssescalarmodesuffix>\t{%2, %0|%0, %<iptr>2}
+ v<multdiv_mnemonic><ssescalarmodesuffix>\t{%2, %1, %0|%0, %1, %<iptr>2}"
+ [(set_attr "isa" "noavx,avx")
+ (set_attr "type" "sse<multdiv_mnemonic>")
+ (set_attr "prefix" "orig,vex")
+ (set_attr "btver2_decode" "direct,double")
+ (set_attr "mode" "<ssescalarmode>")])
+
(define_insn "<sse>_vm<multdiv_mnemonic><mode>3<mask_scalar_name><round_scalar_name>"
[(set (match_operand:VF_128 0 "register_operand" "=x,v")
(vec_merge:VF_128
@@ -2197,6 +2277,30 @@
(set_attr "prefix" "<mask_prefix3>")
(set_attr "mode" "<MODE>")])
+;; Standard scalar operation patterns which preserve the rest of the
+;; vector for combiner.
+(define_insn "*ieee_<ieee_maxmin><mode>3"
+ [(set (match_operand:VF_128 0 "register_operand" "=x,v")
+ (vec_merge:VF_128
+ (vec_duplicate:VF_128
+ (unspec:<ssescalarmode>
+ [(vec_select:<ssescalarmode>
+ (match_operand:VF_128 1 "register_operand" "0,v")
+ (parallel [(const_int 0)]))
+ (match_operand:<ssescalarmode> 2 "nonimmediate_operand" "xm,vm")]
+ IEEE_MAXMIN))
+ (match_dup 1)
+ (const_int 1)))]
+ "TARGET_SSE"
+ "@
+ <ieee_maxmin><ssescalarmodesuffix>\t{%2, %0|%0, %2}
+ v<ieee_maxmin><ssescalarmodesuffix>\t{%2, %1, %0|%0, %1, %2}"
+ [(set_attr "isa" "noavx,avx")
+ (set_attr "type" "sseadd")
+ (set_attr "btver2_sse_attr" "maxmin")
+ (set_attr "prefix" "orig,vex")
+ (set_attr "mode" "<ssescalarmode>")])
+
(define_insn "<sse>_vm<code><mode>3<mask_scalar_name><round_saeonly_scalar_name>"
[(set (match_operand:VF_128 0 "register_operand" "=x,v")
(vec_merge:VF_128
@@ -3515,6 +3619,15 @@
operands[4] = gen_reg_rtx (<MODE>mode);
})
+(define_expand "signbit<mode>2"
+ [(set (match_operand:<sseintvecmode> 0 "register_operand")
+ (lshiftrt:<sseintvecmode>
+ (subreg:<sseintvecmode>
+ (match_operand:VF1_AVX2 1 "register_operand") 0)
+ (match_dup 2)))]
+ "TARGET_SSE2"
+ "operands[2] = GEN_INT (GET_MODE_UNIT_BITSIZE (<MODE>mode)-1);")
+
;; Also define scalar versions. These are used for abs, neg, and
;; conditional move. Using subregs into vector modes causes register
;; allocation lossage. These patterns do not allow memory operands
@@ -4984,39 +5097,93 @@
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-(define_insn "sse_cvtpi2ps"
- [(set (match_operand:V4SF 0 "register_operand" "=x")
+(define_insn_and_split "sse_cvtpi2ps"
+ [(set (match_operand:V4SF 0 "register_operand" "=x,x,Yv")
(vec_merge:V4SF
(vec_duplicate:V4SF
- (float:V2SF (match_operand:V2SI 2 "nonimmediate_operand" "ym")))
- (match_operand:V4SF 1 "register_operand" "0")
- (const_int 3)))]
- "TARGET_SSE"
- "cvtpi2ps\t{%2, %0|%0, %2}"
- [(set_attr "type" "ssecvt")
+ (float:V2SF (match_operand:V2SI 2 "register_mmxmem_operand" "ym,x,Yv")))
+ (match_operand:V4SF 1 "register_operand" "0,0,Yv")
+ (const_int 3)))
+ (clobber (match_scratch:V4SF 3 "=X,x,Yv"))]
+ "(TARGET_MMX || TARGET_MMX_WITH_SSE) && TARGET_SSE"
+ "@
+ cvtpi2ps\t{%2, %0|%0, %2}
+ #
+ #"
+ "TARGET_SSE2 && reload_completed
+ && SSE_REG_P (operands[2])"
+ [(const_int 0)]
+{
+ rtx op2 = lowpart_subreg (V4SImode, operands[2],
+ GET_MODE (operands[2]));
+ /* Generate SSE2 cvtdq2ps. */
+ emit_insn (gen_floatv4siv4sf2 (operands[3], op2));
+
+ /* Merge operands[3] with operands[0]. */
+ rtx mask, op1;
+ if (TARGET_AVX)
+ {
+ mask = gen_rtx_PARALLEL (VOIDmode,
+ gen_rtvec (4, GEN_INT (0), GEN_INT (1),
+ GEN_INT (6), GEN_INT (7)));
+ op1 = gen_rtx_VEC_CONCAT (V8SFmode, operands[3], operands[1]);
+ op2 = gen_rtx_VEC_SELECT (V4SFmode, op1, mask);
+ emit_insn (gen_rtx_SET (operands[0], op2));
+ }
+ else
+ {
+ /* NB: SSE can only concatenate OP0 and OP3 to OP0. */
+ mask = gen_rtx_PARALLEL (VOIDmode,
+ gen_rtvec (4, GEN_INT (2), GEN_INT (3),
+ GEN_INT (4), GEN_INT (5)));
+ op1 = gen_rtx_VEC_CONCAT (V8SFmode, operands[0], operands[3]);
+ op2 = gen_rtx_VEC_SELECT (V4SFmode, op1, mask);
+ emit_insn (gen_rtx_SET (operands[0], op2));
+
+ /* Swap bits 0:63 with bits 64:127. */
+ mask = gen_rtx_PARALLEL (VOIDmode,
+ gen_rtvec (4, GEN_INT (2), GEN_INT (3),
+ GEN_INT (0), GEN_INT (1)));
+ rtx dest = lowpart_subreg (V4SImode, operands[0],
+ GET_MODE (operands[0]));
+ op1 = gen_rtx_VEC_SELECT (V4SImode, dest, mask);
+ emit_insn (gen_rtx_SET (dest, op1));
+ }
+ DONE;
+}
+ [(set_attr "mmx_isa" "native,sse_noavx,avx")
+ (set_attr "type" "ssecvt")
(set_attr "mode" "V4SF")])
(define_insn "sse_cvtps2pi"
- [(set (match_operand:V2SI 0 "register_operand" "=y")
+ [(set (match_operand:V2SI 0 "register_operand" "=y,Yv")
(vec_select:V2SI
- (unspec:V4SI [(match_operand:V4SF 1 "nonimmediate_operand" "xm")]
+ (unspec:V4SI [(match_operand:V4SF 1 "register_mmxmem_operand" "xm,YvBm")]
UNSPEC_FIX_NOTRUNC)
(parallel [(const_int 0) (const_int 1)])))]
- "TARGET_SSE"
- "cvtps2pi\t{%1, %0|%0, %q1}"
- [(set_attr "type" "ssecvt")
- (set_attr "unit" "mmx")
+ "(TARGET_MMX || TARGET_MMX_WITH_SSE) && TARGET_SSE"
+ "@
+ cvtps2pi\t{%1, %0|%0, %q1}
+ %vcvtps2dq\t{%1, %0|%0, %1}"
+ [(set_attr "isa" "*,sse2")
+ (set_attr "mmx_isa" "native,*")
+ (set_attr "type" "ssecvt")
+ (set_attr "unit" "mmx,*")
(set_attr "mode" "DI")])
(define_insn "sse_cvttps2pi"
- [(set (match_operand:V2SI 0 "register_operand" "=y")
+ [(set (match_operand:V2SI 0 "register_operand" "=y,Yv")
(vec_select:V2SI
- (fix:V4SI (match_operand:V4SF 1 "nonimmediate_operand" "xm"))
+ (fix:V4SI (match_operand:V4SF 1 "register_mmxmem_operand" "xm,YvBm"))
(parallel [(const_int 0) (const_int 1)])))]
- "TARGET_SSE"
- "cvttps2pi\t{%1, %0|%0, %q1}"
- [(set_attr "type" "ssecvt")
- (set_attr "unit" "mmx")
+ "(TARGET_MMX || TARGET_MMX_WITH_SSE) && TARGET_SSE"
+ "@
+ cvttps2pi\t{%1, %0|%0, %q1}
+ %vcvttps2dq\t{%1, %0|%0, %1}"
+ [(set_attr "isa" "*,sse2")
+ (set_attr "mmx_isa" "native,*")
+ (set_attr "type" "ssecvt")
+ (set_attr "unit" "mmx,*")
(set_attr "prefix_rep" "0")
(set_attr "mode" "SF")])
@@ -5332,7 +5499,8 @@
"@
%vcvtdq2pd\t{%1, %0|%0, %1}
cvtpi2pd\t{%1, %0|%0, %1}"
- [(set_attr "type" "ssecvt")
+ [(set_attr "mmx_isa" "*,native")
+ (set_attr "type" "ssecvt")
(set_attr "unit" "*,mmx")
(set_attr "prefix_data16" "*,1")
(set_attr "prefix" "maybe_vex,*")
@@ -5340,13 +5508,14 @@
(define_insn "sse2_cvtpd2pi"
[(set (match_operand:V2SI 0 "register_operand" "=v,?!y")
- (unspec:V2SI [(match_operand:V2DF 1 "nonimmediate_operand" "vBm,xm")]
+ (unspec:V2SI [(match_operand:V2DF 1 "vector_operand" "vBm,xBm")]
UNSPEC_FIX_NOTRUNC))]
"TARGET_SSE2"
"@
* return TARGET_AVX ? \"vcvtpd2dq{x}\t{%1, %0|%0, %1}\" : \"cvtpd2dq\t{%1, %0|%0, %1}\";
cvtpd2pi\t{%1, %0|%0, %1}"
- [(set_attr "type" "ssecvt")
+ [(set_attr "mmx_isa" "*,native")
+ (set_attr "type" "ssecvt")
(set_attr "unit" "*,mmx")
(set_attr "amdfam10_decode" "double")
(set_attr "athlon_decode" "vector")
@@ -5357,12 +5526,13 @@
(define_insn "sse2_cvttpd2pi"
[(set (match_operand:V2SI 0 "register_operand" "=v,?!y")
- (fix:V2SI (match_operand:V2DF 1 "nonimmediate_operand" "vBm,xm")))]
+ (fix:V2SI (match_operand:V2DF 1 "vector_operand" "vBm,xBm")))]
"TARGET_SSE2"
"@
* return TARGET_AVX ? \"vcvttpd2dq{x}\t{%1, %0|%0, %1}\" : \"cvttpd2dq\t{%1, %0|%0, %1}\";
cvttpd2pi\t{%1, %0|%0, %1}"
- [(set_attr "type" "ssecvt")
+ [(set_attr "mmx_isa" "*,native")
+ (set_attr "type" "ssecvt")
(set_attr "unit" "*,mmx")
(set_attr "amdfam10_decode" "double")
(set_attr "athlon_decode" "vector")
@@ -7570,6 +7740,10 @@
(const_string "mmxmov")
]
(const_string "sselog")))
+ (set (attr "mmx_isa")
+ (if_then_else (eq_attr "alternative" "7,8")
+ (const_string "native")
+ (const_string "*")))
(set (attr "prefix_data16")
(if_then_else (eq_attr "alternative" "3,4")
(const_string "1")
@@ -7605,7 +7779,8 @@
movss\t{%1, %0|%0, %1}
punpckldq\t{%2, %0|%0, %2}
movd\t{%1, %0|%0, %1}"
- [(set_attr "type" "sselog,ssemov,mmxcvt,mmxmov")
+ [(set_attr "mmx_isa" "*,*,native,native")
+ (set_attr "type" "sselog,ssemov,mmxcvt,mmxmov")
(set_attr "mode" "V4SF,SF,DI,DI")])
(define_insn "*vec_concatv4sf"
@@ -7811,6 +7986,25 @@
[(set (match_dup 0) (match_dup 1))]
"operands[0] = adjust_address (operands[0], <ssescalarmode>mode, 0);")
+;; Standard scalar operation patterns which preserve the rest of the
+;; vector for combiner.
+(define_insn "vec_setv2df_0"
+ [(set (match_operand:V2DF 0 "register_operand" "=x,v,x,v")
+ (vec_merge:V2DF
+ (vec_duplicate:V2DF
+ (match_operand:DF 2 "nonimmediate_operand" " x,v,m,m"))
+ (match_operand:V2DF 1 "register_operand" " 0,v,0,v")
+ (const_int 1)))]
+ "TARGET_SSE2"
+ "@
+ movsd\t{%2, %0|%0, %2}
+ vmovsd\t{%2, %1, %0|%0, %1, %2}
+ movlpd\t{%2, %0|%0, %2}
+ vmovlpd\t{%2, %1, %0|%0, %1, %2}"
+ [(set_attr "isa" "noavx,avx,noavx,avx")
+ (set_attr "type" "ssemov")
+ (set_attr "mode" "DF")])
+
(define_expand "vec_set<mode>"
[(match_operand:V 0 "register_operand")
(match_operand:<ssescalarmode> 1 "register_operand")
@@ -11658,6 +11852,19 @@
(set_attr "mode" "<sseinsnmode>")])
+(define_expand "vec_shl_<mode>"
+ [(set (match_dup 3)
+ (ashift:V1TI
+ (match_operand:VI_128 1 "register_operand")
+ (match_operand:SI 2 "const_0_to_255_mul_8_operand")))
+ (set (match_operand:VI_128 0 "register_operand") (match_dup 4))]
+ "TARGET_SSE2"
+{
+ operands[1] = gen_lowpart (V1TImode, operands[1]);
+ operands[3] = gen_reg_rtx (V1TImode);
+ operands[4] = gen_lowpart (<MODE>mode, operands[3]);
+})
+
(define_expand "vec_shr_<mode>"
[(set (match_dup 3)
(lshiftrt:V1TI
@@ -13543,15 +13750,29 @@
switch (<MODE>mode)
{
case E_V8DFmode:
- return "vmovapd\t{%2, %x0|%x0, %2}";
+ if (misaligned_operand (operands[2], <ssequartermode>mode))
+ return "vmovupd\t{%2, %x0|%x0, %2}";
+ else
+ return "vmovapd\t{%2, %x0|%x0, %2}";
case E_V16SFmode:
- return "vmovaps\t{%2, %x0|%x0, %2}";
+ if (misaligned_operand (operands[2], <ssequartermode>mode))
+ return "vmovups\t{%2, %x0|%x0, %2}";
+ else
+ return "vmovaps\t{%2, %x0|%x0, %2}";
case E_V8DImode:
- return which_alternative == 2 ? "vmovdqa64\t{%2, %x0|%x0, %2}"
- : "vmovdqa\t{%2, %x0|%x0, %2}";
+ if (misaligned_operand (operands[2], <ssequartermode>mode))
+ return which_alternative == 2 ? "vmovdqu64\t{%2, %x0|%x0, %2}"
+ : "vmovdqu\t{%2, %x0|%x0, %2}";
+ else
+ return which_alternative == 2 ? "vmovdqa64\t{%2, %x0|%x0, %2}"
+ : "vmovdqa\t{%2, %x0|%x0, %2}";
case E_V16SImode:
- return which_alternative == 2 ? "vmovdqa32\t{%2, %x0|%x0, %2}"
- : "vmovdqa\t{%2, %x0|%x0, %2}";
+ if (misaligned_operand (operands[2], <ssequartermode>mode))
+ return which_alternative == 2 ? "vmovdqu32\t{%2, %x0|%x0, %2}"
+ : "vmovdqu\t{%2, %x0|%x0, %2}";
+ else
+ return which_alternative == 2 ? "vmovdqa32\t{%2, %x0|%x0, %2}"
+ : "vmovdqa\t{%2, %x0|%x0, %2}";
default:
gcc_unreachable ();
}
@@ -14905,6 +15126,10 @@
punpckldq\t{%2, %0|%0, %2}
movd\t{%1, %0|%0, %1}"
[(set_attr "isa" "noavx,noavx,avx,avx512dq,noavx,noavx,avx,*,*,*")
+ (set (attr "mmx_isa")
+ (if_then_else (eq_attr "alternative" "8,9")
+ (const_string "native")
+ (const_string "*")))
(set (attr "type")
(cond [(eq_attr "alternative" "7")
(const_string "ssemov")
@@ -14942,6 +15167,7 @@
punpckldq\t{%2, %0|%0, %2}
movd\t{%1, %0|%0, %1}"
[(set_attr "isa" "sse2,sse2,*,*,*,*")
+ (set_attr "mmx_isa" "*,*,*,*,native,native")
(set_attr "type" "sselog,ssemov,sselog,ssemov,mmxcvt,mmxmov")
(set_attr "mode" "TI,TI,V4SF,SF,DI,DI")])
@@ -14971,7 +15197,8 @@
"@
%vmovq\t{%1, %0|%0, %1}
movq2dq\t{%1, %0|%0, %1}"
- [(set_attr "type" "ssemov")
+ [(set_attr "mmx_isa" "*,native")
+ (set_attr "type" "ssemov")
(set_attr "prefix" "maybe_vex,orig")
(set_attr "mode" "TI")])
@@ -15046,6 +15273,7 @@
%vmovq\t{%1, %0|%0, %1}
movq2dq\t{%1, %0|%0, %1}"
[(set_attr "isa" "x64,*,*")
+ (set_attr "mmx_isa" "*,*,native")
(set_attr "type" "ssemov")
(set_attr "prefix_rex" "1,*,*")
(set_attr "prefix" "maybe_vex,maybe_vex,orig")
@@ -15482,7 +15710,7 @@
"mwait"
[(set_attr "length" "3")])
-(define_insn "sse3_monitor_<mode>"
+(define_insn "@sse3_monitor_<mode>"
[(unspec_volatile [(match_operand:P 0 "register_operand" "a")
(match_operand:SI 1 "register_operand" "c")
(match_operand:SI 2 "register_operand" "d")]
@@ -15628,13 +15856,13 @@
(set_attr "prefix" "orig,vex")
(set_attr "mode" "TI")])
-(define_insn "ssse3_ph<plusminus_mnemonic>wv4hi3"
- [(set (match_operand:V4HI 0 "register_operand" "=y")
+(define_insn_and_split "ssse3_ph<plusminus_mnemonic>wv4hi3"
+ [(set (match_operand:V4HI 0 "register_operand" "=y,x,Yv")
(vec_concat:V4HI
(vec_concat:V2HI
(ssse3_plusminus:HI
(vec_select:HI
- (match_operand:V4HI 1 "register_operand" "0")
+ (match_operand:V4HI 1 "register_operand" "0,0,Yv")
(parallel [(const_int 0)]))
(vec_select:HI (match_dup 1) (parallel [(const_int 1)])))
(ssse3_plusminus:HI
@@ -15643,19 +15871,38 @@
(vec_concat:V2HI
(ssse3_plusminus:HI
(vec_select:HI
- (match_operand:V4HI 2 "nonimmediate_operand" "ym")
+ (match_operand:V4HI 2 "register_mmxmem_operand" "ym,x,Yv")
(parallel [(const_int 0)]))
(vec_select:HI (match_dup 2) (parallel [(const_int 1)])))
(ssse3_plusminus:HI
(vec_select:HI (match_dup 2) (parallel [(const_int 2)]))
(vec_select:HI (match_dup 2) (parallel [(const_int 3)]))))))]
- "TARGET_SSSE3"
- "ph<plusminus_mnemonic>w\t{%2, %0|%0, %2}"
- [(set_attr "type" "sseiadd")
+ "(TARGET_MMX || TARGET_MMX_WITH_SSE) && TARGET_SSSE3"
+ "@
+ ph<plusminus_mnemonic>w\t{%2, %0|%0, %2}
+ #
+ #"
+ "TARGET_SSSE3 && reload_completed
+ && SSE_REGNO_P (REGNO (operands[0]))"
+ [(const_int 0)]
+{
+ /* Generate SSE version of the operation. */
+ rtx op0 = lowpart_subreg (V8HImode, operands[0],
+ GET_MODE (operands[0]));
+ rtx op1 = lowpart_subreg (V8HImode, operands[1],
+ GET_MODE (operands[1]));
+ rtx op2 = lowpart_subreg (V8HImode, operands[2],
+ GET_MODE (operands[2]));
+ emit_insn (gen_ssse3_ph<plusminus_mnemonic>wv8hi3 (op0, op1, op2));
+ ix86_move_vector_high_sse_to_mmx (op0);
+ DONE;
+}
+ [(set_attr "mmx_isa" "native,sse_noavx,avx")
+ (set_attr "type" "sseiadd")
(set_attr "atom_unit" "complex")
(set_attr "prefix_extra" "1")
(set (attr "prefix_rex") (symbol_ref "x86_extended_reg_mentioned_p (insn)"))
- (set_attr "mode" "DI")])
+ (set_attr "mode" "DI,TI,TI")])
(define_insn "avx2_ph<plusminus_mnemonic>dv8si3"
[(set (match_operand:V8SI 0 "register_operand" "=x")
@@ -15734,26 +15981,45 @@
(set_attr "prefix" "orig,vex")
(set_attr "mode" "TI")])
-(define_insn "ssse3_ph<plusminus_mnemonic>dv2si3"
- [(set (match_operand:V2SI 0 "register_operand" "=y")
+(define_insn_and_split "ssse3_ph<plusminus_mnemonic>dv2si3"
+ [(set (match_operand:V2SI 0 "register_operand" "=y,x,Yv")
(vec_concat:V2SI
(plusminus:SI
(vec_select:SI
- (match_operand:V2SI 1 "register_operand" "0")
+ (match_operand:V2SI 1 "register_operand" "0,0,Yv")
(parallel [(const_int 0)]))
(vec_select:SI (match_dup 1) (parallel [(const_int 1)])))
(plusminus:SI
(vec_select:SI
- (match_operand:V2SI 2 "nonimmediate_operand" "ym")
+ (match_operand:V2SI 2 "register_mmxmem_operand" "ym,x,Yv")
(parallel [(const_int 0)]))
(vec_select:SI (match_dup 2) (parallel [(const_int 1)])))))]
- "TARGET_SSSE3"
- "ph<plusminus_mnemonic>d\t{%2, %0|%0, %2}"
- [(set_attr "type" "sseiadd")
+ "(TARGET_MMX || TARGET_MMX_WITH_SSE) && TARGET_SSSE3"
+ "@
+ ph<plusminus_mnemonic>d\t{%2, %0|%0, %2}
+ #
+ #"
+ "TARGET_SSSE3 && reload_completed
+ && SSE_REGNO_P (REGNO (operands[0]))"
+ [(const_int 0)]
+{
+ /* Generate SSE version of the operation. */
+ rtx op0 = lowpart_subreg (V4SImode, operands[0],
+ GET_MODE (operands[0]));
+ rtx op1 = lowpart_subreg (V4SImode, operands[1],
+ GET_MODE (operands[1]));
+ rtx op2 = lowpart_subreg (V4SImode, operands[2],
+ GET_MODE (operands[2]));
+ emit_insn (gen_ssse3_ph<plusminus_mnemonic>dv4si3 (op0, op1, op2));
+ ix86_move_vector_high_sse_to_mmx (op0);
+ DONE;
+}
+ [(set_attr "mmx_isa" "native,sse_noavx,avx")
+ (set_attr "type" "sseiadd")
(set_attr "atom_unit" "complex")
(set_attr "prefix_extra" "1")
(set (attr "prefix_rex") (symbol_ref "x86_extended_reg_mentioned_p (insn)"))
- (set_attr "mode" "DI")])
+ (set_attr "mode" "DI,TI,TI")])
(define_insn "avx2_pmaddubsw256"
[(set (match_operand:V16HI 0 "register_operand" "=x,v")
@@ -15904,17 +16170,17 @@
(set_attr "mode" "TI")])
(define_insn "ssse3_pmaddubsw"
- [(set (match_operand:V4HI 0 "register_operand" "=y")
+ [(set (match_operand:V4HI 0 "register_operand" "=y,x,Yv")
(ss_plus:V4HI
(mult:V4HI
(zero_extend:V4HI
(vec_select:V4QI
- (match_operand:V8QI 1 "register_operand" "0")
+ (match_operand:V8QI 1 "register_operand" "0,0,Yv")
(parallel [(const_int 0) (const_int 2)
(const_int 4) (const_int 6)])))
(sign_extend:V4HI
(vec_select:V4QI
- (match_operand:V8QI 2 "nonimmediate_operand" "ym")
+ (match_operand:V8QI 2 "register_mmxmem_operand" "ym,x,Yv")
(parallel [(const_int 0) (const_int 2)
(const_int 4) (const_int 6)]))))
(mult:V4HI
@@ -15926,13 +16192,18 @@
(vec_select:V4QI (match_dup 2)
(parallel [(const_int 1) (const_int 3)
(const_int 5) (const_int 7)]))))))]
- "TARGET_SSSE3"
- "pmaddubsw\t{%2, %0|%0, %2}"
- [(set_attr "type" "sseiadd")
+ "(TARGET_MMX || TARGET_MMX_WITH_SSE) && TARGET_SSSE3"
+ "@
+ pmaddubsw\t{%2, %0|%0, %2}
+ pmaddubsw\t{%2, %0|%0, %2}
+ vpmaddubsw\t{%2, %1, %0|%0, %1, %2}"
+ [(set_attr "isa" "*,noavx,avx")
+ (set_attr "mmx_isa" "native,*,*")
+ (set_attr "type" "sseiadd")
(set_attr "atom_unit" "simul")
(set_attr "prefix_extra" "1")
(set (attr "prefix_rex") (symbol_ref "x86_extended_reg_mentioned_p (insn)"))
- (set_attr "mode" "DI")])
+ (set_attr "mode" "DI,TI,TI")])
(define_mode_iterator PMULHRSW
[V8HI (V16HI "TARGET_AVX2")])
@@ -16015,38 +16286,45 @@
(lshiftrt:V4SI
(mult:V4SI
(sign_extend:V4SI
- (match_operand:V4HI 1 "nonimmediate_operand"))
+ (match_operand:V4HI 1 "register_mmxmem_operand"))
(sign_extend:V4SI
- (match_operand:V4HI 2 "nonimmediate_operand")))
+ (match_operand:V4HI 2 "register_mmxmem_operand")))
(const_int 14))
(match_dup 3))
(const_int 1))))]
- "TARGET_SSSE3"
+ "(TARGET_MMX || TARGET_MMX_WITH_SSE) && TARGET_SSSE3"
{
operands[3] = CONST1_RTX(V4HImode);
ix86_fixup_binary_operands_no_copy (MULT, V4HImode, operands);
})
(define_insn "*ssse3_pmulhrswv4hi3"
- [(set (match_operand:V4HI 0 "register_operand" "=y")
+ [(set (match_operand:V4HI 0 "register_operand" "=y,x,Yv")
(truncate:V4HI
(lshiftrt:V4SI
(plus:V4SI
(lshiftrt:V4SI
(mult:V4SI
(sign_extend:V4SI
- (match_operand:V4HI 1 "nonimmediate_operand" "%0"))
+ (match_operand:V4HI 1 "register_mmxmem_operand" "%0,0,Yv"))
(sign_extend:V4SI
- (match_operand:V4HI 2 "nonimmediate_operand" "ym")))
+ (match_operand:V4HI 2 "register_mmxmem_operand" "ym,x,Yv")))
(const_int 14))
(match_operand:V4HI 3 "const1_operand"))
(const_int 1))))]
- "TARGET_SSSE3 && !(MEM_P (operands[1]) && MEM_P (operands[2]))"
- "pmulhrsw\t{%2, %0|%0, %2}"
- [(set_attr "type" "sseimul")
+ "(TARGET_MMX || TARGET_MMX_WITH_SSE)
+ && TARGET_SSSE3
+ && !(MEM_P (operands[1]) && MEM_P (operands[2]))"
+ "@
+ pmulhrsw\t{%2, %0|%0, %2}
+ pmulhrsw\t{%2, %0|%0, %2}
+ vpmulhrsw\t{%2, %1, %0|%0, %1, %2}"
+ [(set_attr "isa" "*,noavx,avx")
+ (set_attr "mmx_isa" "native,*,*")
+ (set_attr "type" "sseimul")
(set_attr "prefix_extra" "1")
(set (attr "prefix_rex") (symbol_ref "x86_extended_reg_mentioned_p (insn)"))
- (set_attr "mode" "DI")])
+ (set_attr "mode" "DI,TI,TI")])
(define_insn "<ssse3_avx2>_pshufb<mode>3<mask_name>"
[(set (match_operand:VI1_AVX512 0 "register_operand" "=x,x,v")
@@ -16067,17 +16345,46 @@
(set_attr "btver2_decode" "vector")
(set_attr "mode" "<sseinsnmode>")])
-(define_insn "ssse3_pshufbv8qi3"
- [(set (match_operand:V8QI 0 "register_operand" "=y")
- (unspec:V8QI [(match_operand:V8QI 1 "register_operand" "0")
- (match_operand:V8QI 2 "nonimmediate_operand" "ym")]
- UNSPEC_PSHUFB))]
- "TARGET_SSSE3"
- "pshufb\t{%2, %0|%0, %2}";
- [(set_attr "type" "sselog1")
+(define_insn_and_split "ssse3_pshufbv8qi3"
+ [(set (match_operand:V8QI 0 "register_operand" "=y,x,Yv")
+ (unspec:V8QI [(match_operand:V8QI 1 "register_operand" "0,0,Yv")
+ (match_operand:V8QI 2 "register_mmxmem_operand" "ym,x,Yv")]
+ UNSPEC_PSHUFB))
+ (clobber (match_scratch:V4SI 3 "=X,x,Yv"))]
+ "(TARGET_MMX || TARGET_MMX_WITH_SSE) && TARGET_SSSE3"
+ "@
+ pshufb\t{%2, %0|%0, %2}
+ #
+ #"
+ "TARGET_SSSE3 && reload_completed
+ && SSE_REGNO_P (REGNO (operands[0]))"
+ [(set (match_dup 3) (match_dup 5))
+ (set (match_dup 3)
+ (and:V4SI (match_dup 3) (match_dup 2)))
+ (set (match_dup 0)
+ (unspec:V16QI [(match_dup 1) (match_dup 4)] UNSPEC_PSHUFB))]
+{
+ /* Emulate MMX version of pshufb with SSE version by masking out the
+ bit 3 of the shuffle control byte. */
+ operands[0] = lowpart_subreg (V16QImode, operands[0],
+ GET_MODE (operands[0]));
+ operands[1] = lowpart_subreg (V16QImode, operands[1],
+ GET_MODE (operands[1]));
+ operands[2] = lowpart_subreg (V4SImode, operands[2],
+ GET_MODE (operands[2]));
+ operands[4] = lowpart_subreg (V16QImode, operands[3],
+ GET_MODE (operands[3]));
+ rtvec par = gen_rtvec (4, GEN_INT (0xf7f7f7f7),
+ GEN_INT (0xf7f7f7f7),
+ GEN_INT (0xf7f7f7f7),
+ GEN_INT (0xf7f7f7f7));
+ rtx vec_const = gen_rtx_CONST_VECTOR (V4SImode, par);
+ operands[5] = force_const_mem (V4SImode, vec_const);
+}
+ [(set_attr "mmx_isa" "native,sse_noavx,avx")
(set_attr "prefix_extra" "1")
(set (attr "prefix_rex") (symbol_ref "x86_extended_reg_mentioned_p (insn)"))
- (set_attr "mode" "DI")])
+ (set_attr "mode" "DI,TI,TI")])
(define_insn "<ssse3_avx2>_psign<mode>3"
[(set (match_operand:VI124_AVX2 0 "register_operand" "=x,x")
@@ -16097,17 +16404,22 @@
(set_attr "mode" "<sseinsnmode>")])
(define_insn "ssse3_psign<mode>3"
- [(set (match_operand:MMXMODEI 0 "register_operand" "=y")
+ [(set (match_operand:MMXMODEI 0 "register_operand" "=y,x,Yv")
(unspec:MMXMODEI
- [(match_operand:MMXMODEI 1 "register_operand" "0")
- (match_operand:MMXMODEI 2 "nonimmediate_operand" "ym")]
+ [(match_operand:MMXMODEI 1 "register_operand" "0,0,Yv")
+ (match_operand:MMXMODEI 2 "register_mmxmem_operand" "ym,x,Yv")]
UNSPEC_PSIGN))]
- "TARGET_SSSE3"
- "psign<mmxvecsize>\t{%2, %0|%0, %2}";
- [(set_attr "type" "sselog1")
+ "(TARGET_MMX || TARGET_MMX_WITH_SSE) && TARGET_SSSE3"
+ "@
+ psign<mmxvecsize>\t{%2, %0|%0, %2}
+ psign<mmxvecsize>\t{%2, %0|%0, %2}
+ vpsign<mmxvecsize>\t{%2, %1, %0|%0, %1, %2}"
+ [(set_attr "isa" "*,noavx,avx")
+ (set_attr "mmx_isa" "native,*,*")
+ (set_attr "type" "sselog1")
(set_attr "prefix_extra" "1")
(set (attr "prefix_rex") (symbol_ref "x86_extended_reg_mentioned_p (insn)"))
- (set_attr "mode" "DI")])
+ (set_attr "mode" "DI,TI,TI")])
(define_insn "<ssse3_avx2>_palignr<mode>_mask"
[(set (match_operand:VI1_AVX512 0 "register_operand" "=v")
@@ -16162,23 +16474,59 @@
(set_attr "prefix" "orig,vex,evex")
(set_attr "mode" "<sseinsnmode>")])
-(define_insn "ssse3_palignrdi"
- [(set (match_operand:DI 0 "register_operand" "=y")
- (unspec:DI [(match_operand:DI 1 "register_operand" "0")
- (match_operand:DI 2 "nonimmediate_operand" "ym")
- (match_operand:SI 3 "const_0_to_255_mul_8_operand" "n")]
+(define_insn_and_split "ssse3_palignrdi"
+ [(set (match_operand:DI 0 "register_operand" "=y,x,Yv")
+ (unspec:DI [(match_operand:DI 1 "register_operand" "0,0,Yv")
+ (match_operand:DI 2 "register_mmxmem_operand" "ym,x,Yv")
+ (match_operand:SI 3 "const_0_to_255_mul_8_operand" "n,n,n")]
UNSPEC_PALIGNR))]
- "TARGET_SSSE3"
+ "(TARGET_MMX || TARGET_MMX_WITH_SSE) && TARGET_SSSE3"
{
- operands[3] = GEN_INT (INTVAL (operands[3]) / 8);
- return "palignr\t{%3, %2, %0|%0, %2, %3}";
+ switch (which_alternative)
+ {
+ case 0:
+ operands[3] = GEN_INT (INTVAL (operands[3]) / 8);
+ return "palignr\t{%3, %2, %0|%0, %2, %3}";
+ case 1:
+ case 2:
+ return "#";
+ default:
+ gcc_unreachable ();
+ }
}
- [(set_attr "type" "sseishft")
+ "TARGET_SSSE3 && reload_completed
+ && SSE_REGNO_P (REGNO (operands[0]))"
+ [(set (match_dup 0)
+ (lshiftrt:V1TI (match_dup 0) (match_dup 3)))]
+{
+ /* Emulate MMX palignrdi with SSE psrldq. */
+ rtx op0 = lowpart_subreg (V2DImode, operands[0],
+ GET_MODE (operands[0]));
+ if (TARGET_AVX)
+ emit_insn (gen_vec_concatv2di (op0, operands[2], operands[1]));
+ else
+ {
+ /* NB: SSE can only concatenate OP0 and OP1 to OP0. */
+ emit_insn (gen_vec_concatv2di (op0, operands[1], operands[2]));
+ /* Swap bits 0:63 with bits 64:127. */
+ rtx mask = gen_rtx_PARALLEL (VOIDmode,
+ gen_rtvec (4, GEN_INT (2),
+ GEN_INT (3),
+ GEN_INT (0),
+ GEN_INT (1)));
+ rtx op1 = lowpart_subreg (V4SImode, op0, GET_MODE (op0));
+ rtx op2 = gen_rtx_VEC_SELECT (V4SImode, op1, mask);
+ emit_insn (gen_rtx_SET (op1, op2));
+ }
+ operands[0] = lowpart_subreg (V1TImode, op0, GET_MODE (op0));
+}
+ [(set_attr "mmx_isa" "native,sse_noavx,avx")
+ (set_attr "type" "sseishft")
(set_attr "atom_unit" "sishuf")
(set_attr "prefix_extra" "1")
(set_attr "length_immediate" "1")
(set (attr "prefix_rex") (symbol_ref "x86_extended_reg_mentioned_p (insn)"))
- (set_attr "mode" "DI")])
+ (set_attr "mode" "DI,TI,TI")])
;; Mode iterator to handle singularity w/ absence of V2DI and V4DI
;; modes for abs instruction on pre AVX-512 targets.
@@ -16241,17 +16589,26 @@
}
})
-(define_insn "abs<mode>2"
- [(set (match_operand:MMXMODEI 0 "register_operand" "=y")
+(define_insn "ssse3_abs<mode>2"
+ [(set (match_operand:MMXMODEI 0 "register_operand" "=y,Yv")
(abs:MMXMODEI
- (match_operand:MMXMODEI 1 "nonimmediate_operand" "ym")))]
- "TARGET_SSSE3"
- "pabs<mmxvecsize>\t{%1, %0|%0, %1}";
- [(set_attr "type" "sselog1")
+ (match_operand:MMXMODEI 1 "register_mmxmem_operand" "ym,Yv")))]
+ "(TARGET_MMX || TARGET_MMX_WITH_SSE) && TARGET_SSSE3"
+ "@
+ pabs<mmxvecsize>\t{%1, %0|%0, %1}
+ %vpabs<mmxvecsize>\t{%1, %0|%0, %1}"
+ [(set_attr "mmx_isa" "native,*")
+ (set_attr "type" "sselog1")
(set_attr "prefix_rep" "0")
(set_attr "prefix_extra" "1")
(set (attr "prefix_rex") (symbol_ref "x86_extended_reg_mentioned_p (insn)"))
- (set_attr "mode" "DI")])
+ (set_attr "mode" "DI,TI")])
+
+(define_insn "abs<mode>2"
+ [(set (match_operand:MMXMODEI 0 "register_operand")
+ (abs:MMXMODEI
+ (match_operand:MMXMODEI 1 "register_operand")))]
+ "TARGET_MMX_WITH_SSE && TARGET_SSSE3")
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
@@ -20402,9 +20759,11 @@
(define_insn "avx_vec_concat<mode>"
[(set (match_operand:V_256_512 0 "register_operand" "=x,v,x,Yv")
(vec_concat:V_256_512
- (match_operand:<ssehalfvecmode> 1 "register_operand" "x,v,x,v")
+ (match_operand:<ssehalfvecmode> 1 "nonimmediate_operand" "x,v,xm,vm")
(match_operand:<ssehalfvecmode> 2 "nonimm_or_0_operand" "xm,vm,C,C")))]
- "TARGET_AVX"
+ "TARGET_AVX
+ && (operands[2] == CONST0_RTX (<ssehalfvecmode>mode)
+ || !MEM_P (operands[1]))"
{
switch (which_alternative)
{
@@ -20430,27 +20789,63 @@
switch (get_attr_mode (insn))
{
case MODE_V16SF:
- return "vmovaps\t{%1, %t0|%t0, %1}";
+ if (misaligned_operand (operands[1], <ssehalfvecmode>mode))
+ return "vmovups\t{%1, %t0|%t0, %1}";
+ else
+ return "vmovaps\t{%1, %t0|%t0, %1}";
case MODE_V8DF:
- return "vmovapd\t{%1, %t0|%t0, %1}";
+ if (misaligned_operand (operands[1], <ssehalfvecmode>mode))
+ return "vmovupd\t{%1, %t0|%t0, %1}";
+ else
+ return "vmovapd\t{%1, %t0|%t0, %1}";
case MODE_V8SF:
- return "vmovaps\t{%1, %x0|%x0, %1}";
+ if (misaligned_operand (operands[1], <ssehalfvecmode>mode))
+ return "vmovups\t{%1, %x0|%x0, %1}";
+ else
+ return "vmovaps\t{%1, %x0|%x0, %1}";
case MODE_V4DF:
- return "vmovapd\t{%1, %x0|%x0, %1}";
+ if (misaligned_operand (operands[1], <ssehalfvecmode>mode))
+ return "vmovupd\t{%1, %x0|%x0, %1}";
+ else
+ return "vmovapd\t{%1, %x0|%x0, %1}";
case MODE_XI:
- if (which_alternative == 2)
- return "vmovdqa\t{%1, %t0|%t0, %1}";
- else if (GET_MODE_SIZE (<ssescalarmode>mode) == 8)
- return "vmovdqa64\t{%1, %t0|%t0, %1}";
+ if (misaligned_operand (operands[1], <ssehalfvecmode>mode))
+ {
+ if (which_alternative == 2)
+ return "vmovdqu\t{%1, %t0|%t0, %1}";
+ else if (GET_MODE_SIZE (<ssescalarmode>mode) == 8)
+ return "vmovdqu64\t{%1, %t0|%t0, %1}";
+ else
+ return "vmovdqu32\t{%1, %t0|%t0, %1}";
+ }
else
- return "vmovdqa32\t{%1, %t0|%t0, %1}";
+ {
+ if (which_alternative == 2)
+ return "vmovdqa\t{%1, %t0|%t0, %1}";
+ else if (GET_MODE_SIZE (<ssescalarmode>mode) == 8)
+ return "vmovdqa64\t{%1, %t0|%t0, %1}";
+ else
+ return "vmovdqa32\t{%1, %t0|%t0, %1}";
+ }
case MODE_OI:
- if (which_alternative == 2)
- return "vmovdqa\t{%1, %x0|%x0, %1}";
- else if (GET_MODE_SIZE (<ssescalarmode>mode) == 8)
- return "vmovdqa64\t{%1, %x0|%x0, %1}";
+ if (misaligned_operand (operands[1], <ssehalfvecmode>mode))
+ {
+ if (which_alternative == 2)
+ return "vmovdqu\t{%1, %x0|%x0, %1}";
+ else if (GET_MODE_SIZE (<ssescalarmode>mode) == 8)
+ return "vmovdqu64\t{%1, %x0|%x0, %1}";
+ else
+ return "vmovdqu32\t{%1, %x0|%x0, %1}";
+ }
else
- return "vmovdqa32\t{%1, %x0|%x0, %1}";
+ {
+ if (which_alternative == 2)
+ return "vmovdqa\t{%1, %x0|%x0, %1}";
+ else if (GET_MODE_SIZE (<ssescalarmode>mode) == 8)
+ return "vmovdqa64\t{%1, %x0|%x0, %1}";
+ else
+ return "vmovdqa32\t{%1, %x0|%x0, %1}";
+ }
default:
gcc_unreachable ();
}
@@ -21115,26 +21510,26 @@
(define_insn "avx512dq_fpclass<mode><mask_scalar_merge_name>"
[(set (match_operand:<avx512fmaskmode> 0 "register_operand" "=k")
(unspec:<avx512fmaskmode>
- [(match_operand:VF_AVX512VL 1 "register_operand" "v")
+ [(match_operand:VF_AVX512VL 1 "vector_operand" "vm")
(match_operand:QI 2 "const_0_to_255_operand" "n")]
UNSPEC_FPCLASS))]
"TARGET_AVX512DQ"
- "vfpclass<ssemodesuffix>\t{%2, %1, %0<mask_scalar_merge_operand3>|%0<mask_scalar_merge_operand3>, %1, %2}";
+ "vfpclass<ssemodesuffix><vecmemsuffix>\t{%2, %1, %0<mask_scalar_merge_operand3>|%0<mask_scalar_merge_operand3>, %1, %2}";
[(set_attr "type" "sse")
(set_attr "length_immediate" "1")
(set_attr "prefix" "evex")
(set_attr "mode" "<MODE>")])
-(define_insn "avx512dq_vmfpclass<mode>"
+(define_insn "avx512dq_vmfpclass<mode><mask_scalar_merge_name>"
[(set (match_operand:<avx512fmaskmode> 0 "register_operand" "=k")
(and:<avx512fmaskmode>
(unspec:<avx512fmaskmode>
- [(match_operand:VF_128 1 "register_operand" "v")
+ [(match_operand:VF_128 1 "vector_operand" "vm")
(match_operand:QI 2 "const_0_to_255_operand" "n")]
UNSPEC_FPCLASS)
(const_int 1)))]
"TARGET_AVX512DQ"
- "vfpclass<ssescalarmodesuffix>\t{%2, %1, %0|%0, %1, %2}";
+ "vfpclass<ssescalarmodesuffix>\t{%2, %1, %0<mask_scalar_merge_operand3>|%0<mask_scalar_merge_operand3>, %1, %2}";
[(set_attr "type" "sse")
(set_attr "length_immediate" "1")
(set_attr "prefix" "evex")
@@ -21687,21 +22082,21 @@
"vpopcnt<ssemodesuffix>\t{%1, %0<mask_operand2>|%0<mask_operand2>, %1}")
;; Save multiple registers out-of-line.
-(define_insn "save_multiple<mode>"
+(define_insn "*save_multiple<mode>"
[(match_parallel 0 "save_multiple"
[(use (match_operand:P 1 "symbol_operand"))])]
"TARGET_SSE && TARGET_64BIT"
"call\t%P1")
;; Restore multiple registers out-of-line.
-(define_insn "restore_multiple<mode>"
+(define_insn "*restore_multiple<mode>"
[(match_parallel 0 "restore_multiple"
[(use (match_operand:P 1 "symbol_operand"))])]
"TARGET_SSE && TARGET_64BIT"
"call\t%P1")
;; Restore multiple registers out-of-line and return.
-(define_insn "restore_multiple_and_return<mode>"
+(define_insn "*restore_multiple_and_return<mode>"
[(match_parallel 0 "restore_multiple"
[(return)
(use (match_operand:P 1 "symbol_operand"))
@@ -21712,7 +22107,7 @@
;; Restore multiple registers out-of-line when hard frame pointer is used,
;; perform the leave operation prior to returning (from the function).
-(define_insn "restore_multiple_leave_return<mode>"
+(define_insn "*restore_multiple_leave_return<mode>"
[(match_parallel 0 "restore_multiple"
[(return)
(use (match_operand:P 1 "symbol_operand"))
@@ -21731,56 +22126,53 @@
"vpopcnt<ssemodesuffix>\t{%1, %0<mask_operand2>|%0<mask_operand2>, %1}")
(define_insn "vgf2p8affineinvqb_<mode><mask_name>"
- [(set (match_operand:VI1_AVX512F 0 "register_operand" "=x,x,v")
+ [(set (match_operand:VI1_AVX512F 0 "register_operand" "=x,v")
(unspec:VI1_AVX512F
- [(match_operand:VI1_AVX512F 1 "register_operand" "%0,x,v")
- (match_operand:VI1_AVX512F 2 "nonimmediate_operand" "xBm,xm,vm")
- (match_operand:QI 3 "const_0_to_255_operand" "n,n,n")]
+ [(match_operand:VI1_AVX512F 1 "register_operand" "0,v")
+ (match_operand:VI1_AVX512F 2 "vector_operand" "xBm,vm")
+ (match_operand:QI 3 "const_0_to_255_operand" "n,n")]
UNSPEC_GF2P8AFFINEINV))]
"TARGET_GFNI"
"@
gf2p8affineinvqb\t{%3, %2, %0| %0, %2, %3}
- vgf2p8affineinvqb\t{%3, %2, %1, %0<mask_operand4>| %0<mask_operand4>, %1, %2, %3}
vgf2p8affineinvqb\t{%3, %2, %1, %0<mask_operand4>| %0<mask_operand4>, %1, %2, %3}"
- [(set_attr "isa" "noavx,avx,avx512f")
- (set_attr "prefix_data16" "1,*,*")
+ [(set_attr "isa" "noavx,avx")
+ (set_attr "prefix_data16" "1,*")
(set_attr "prefix_extra" "1")
- (set_attr "prefix" "orig,maybe_evex,evex")
+ (set_attr "prefix" "orig,maybe_evex")
(set_attr "mode" "<sseinsnmode>")])
(define_insn "vgf2p8affineqb_<mode><mask_name>"
- [(set (match_operand:VI1_AVX512F 0 "register_operand" "=x,x,v")
+ [(set (match_operand:VI1_AVX512F 0 "register_operand" "=x,v")
(unspec:VI1_AVX512F
- [(match_operand:VI1_AVX512F 1 "register_operand" "%0,x,v")
- (match_operand:VI1_AVX512F 2 "nonimmediate_operand" "xBm,xm,vm")
- (match_operand:QI 3 "const_0_to_255_operand" "n,n,n")]
+ [(match_operand:VI1_AVX512F 1 "register_operand" "0,v")
+ (match_operand:VI1_AVX512F 2 "vector_operand" "xBm,vm")
+ (match_operand:QI 3 "const_0_to_255_operand" "n,n")]
UNSPEC_GF2P8AFFINE))]
"TARGET_GFNI"
"@
gf2p8affineqb\t{%3, %2, %0| %0, %2, %3}
- vgf2p8affineqb\t{%3, %2, %1, %0<mask_operand4>| %0<mask_operand4>, %1, %2, %3}
vgf2p8affineqb\t{%3, %2, %1, %0<mask_operand4>| %0<mask_operand4>, %1, %2, %3}"
- [(set_attr "isa" "noavx,avx,avx512f")
- (set_attr "prefix_data16" "1,*,*")
+ [(set_attr "isa" "noavx,avx")
+ (set_attr "prefix_data16" "1,*")
(set_attr "prefix_extra" "1")
- (set_attr "prefix" "orig,maybe_evex,evex")
+ (set_attr "prefix" "orig,maybe_evex")
(set_attr "mode" "<sseinsnmode>")])
(define_insn "vgf2p8mulb_<mode><mask_name>"
- [(set (match_operand:VI1_AVX512F 0 "register_operand" "=x,x,v")
+ [(set (match_operand:VI1_AVX512F 0 "register_operand" "=x,v")
(unspec:VI1_AVX512F
- [(match_operand:VI1_AVX512F 1 "register_operand" "%0,x,v")
- (match_operand:VI1_AVX512F 2 "nonimmediate_operand" "xBm,xm,vm")]
+ [(match_operand:VI1_AVX512F 1 "register_operand" "%0,v")
+ (match_operand:VI1_AVX512F 2 "vector_operand" "xBm,vm")]
UNSPEC_GF2P8MUL))]
"TARGET_GFNI"
"@
gf2p8mulb\t{%2, %0| %0, %2}
- vgf2p8mulb\t{%2, %1, %0<mask_operand3>| %0<mask_operand3>, %1, %2}
vgf2p8mulb\t{%2, %1, %0<mask_operand3>| %0<mask_operand3>, %1, %2}"
- [(set_attr "isa" "noavx,avx,avx512f")
- (set_attr "prefix_data16" "1,*,*")
+ [(set_attr "isa" "noavx,avx")
+ (set_attr "prefix_data16" "1,*")
(set_attr "prefix_extra" "1")
- (set_attr "prefix" "orig,maybe_evex,evex")
+ (set_attr "prefix" "orig,maybe_evex")
(set_attr "mode" "<sseinsnmode>")])
(define_insn "vpshrd_<mode><mask_name>"
@@ -22199,6 +22591,30 @@
[(set_attr "prefix" "evex")
(set_attr "mode" "<sseinsnmode>")])
+(define_mode_iterator VI48_AVX512VP2VL
+ [V8DI
+ (V4DI "TARGET_AVX512VL") (V2DI "TARGET_AVX512VL")
+ (V8SI "TARGET_AVX512VL") (V4SI "TARGET_AVX512VL")])
+
+(define_insn "avx512vp2intersect_2intersect<mode>"
+ [(set (match_operand:P2QI 0 "register_operand" "=k")
+ (unspec:P2QI
+ [(match_operand:VI48_AVX512VP2VL 1 "register_operand" "v")
+ (match_operand:VI48_AVX512VP2VL 2 "vector_operand" "vm")]
+ UNSPEC_VP2INTERSECT))]
+ "TARGET_AVX512VP2INTERSECT"
+ "vp2intersect<ssemodesuffix>\t{%2, %1, %0|%0, %1, %2}"
+ [(set_attr ("prefix") ("evex"))])
+
+(define_insn "avx512vp2intersect_2intersectv16si"
+ [(set (match_operand:P2HI 0 "register_operand" "=k")
+ (unspec:P2HI [(match_operand:V16SI 1 "register_operand" "v")
+ (match_operand:V16SI 2 "vector_operand" "vm")]
+ UNSPEC_VP2INTERSECT))]
+ "TARGET_AVX512VP2INTERSECT"
+ "vp2intersectd\t{%2, %1, %0|%0, %1, %2}"
+ [(set_attr ("prefix") ("evex"))])
+
(define_mode_iterator BF16 [V32HI (V16HI "TARGET_AVX512VL") (V8HI "TARGET_AVX512VL")])
;; Converting from BF to SF
(define_mode_attr bf16_cvt_2sf
diff --git a/gcc/config/i386/x86-tune-sched.c b/gcc/config/i386/x86-tune-sched.c
index f2402e0..f88e86c 100644
--- a/gcc/config/i386/x86-tune-sched.c
+++ b/gcc/config/i386/x86-tune-sched.c
@@ -27,10 +27,11 @@ along with GCC; see the file COPYING3. If not see
#include "tree.h"
#include "cfghooks.h"
#include "tm_p.h"
+#include "target.h"
#include "insn-config.h"
#include "insn-attr.h"
+#include "insn-opinit.h"
#include "recog.h"
-#include "target.h"
/* Return the maximum number of instructions a cpu can issue. */
@@ -525,6 +526,7 @@ ix86_macro_fusion_pair_p (rtx_insn *condgen, rtx_insn *condjmp)
enum rtx_code ccode;
rtx compare_set = NULL_RTX, test_if, cond;
rtx alu_set = NULL_RTX, addr = NULL_RTX;
+ enum attr_type condgen_type;
if (!any_condjump_p (condjmp))
return false;
@@ -538,15 +540,25 @@ ix86_macro_fusion_pair_p (rtx_insn *condgen, rtx_insn *condjmp)
|| !modified_in_p (cc_reg_1, condgen))
return false;
- if (get_attr_type (condgen) != TYPE_TEST
- && get_attr_type (condgen) != TYPE_ICMP
- && get_attr_type (condgen) != TYPE_INCDEC
- && get_attr_type (condgen) != TYPE_ALU)
+ condgen_type = get_attr_type (condgen);
+ if (condgen_type == TYPE_MULTI
+ && INSN_CODE (condgen) == code_for_stack_protect_test_1 (ptr_mode)
+ && TARGET_FUSE_ALU_AND_BRANCH)
+ {
+ /* stack_protect_test_<mode> ends with a sub, which subtracts
+ a non-rip special memory operand from a GPR. */
+ src = NULL_RTX;
+ alu_set = XVECEXP (PATTERN (condgen), 0, 1);
+ goto handle_stack_protect_test;
+ }
+ else if (condgen_type != TYPE_TEST
+ && condgen_type != TYPE_ICMP
+ && condgen_type != TYPE_INCDEC
+ && condgen_type != TYPE_ALU)
return false;
compare_set = single_set (condgen);
- if (compare_set == NULL_RTX
- && !TARGET_FUSE_ALU_AND_BRANCH)
+ if (compare_set == NULL_RTX && !TARGET_FUSE_ALU_AND_BRANCH)
return false;
if (compare_set == NULL_RTX)
@@ -571,10 +583,8 @@ ix86_macro_fusion_pair_p (rtx_insn *condgen, rtx_insn *condjmp)
/* Macro-fusion for cmp/test MEM-IMM + conditional jmp is not
supported. */
- if ((MEM_P (XEXP (src, 0))
- && CONST_INT_P (XEXP (src, 1)))
- || (MEM_P (XEXP (src, 1))
- && CONST_INT_P (XEXP (src, 0))))
+ if ((MEM_P (XEXP (src, 0)) && CONST_INT_P (XEXP (src, 1)))
+ || (MEM_P (XEXP (src, 1)) && CONST_INT_P (XEXP (src, 0))))
return false;
/* No fusion for RIP-relative address. */
@@ -583,29 +593,27 @@ ix86_macro_fusion_pair_p (rtx_insn *condgen, rtx_insn *condjmp)
else if (MEM_P (XEXP (src, 1)))
addr = XEXP (XEXP (src, 1), 0);
- if (addr) {
- ix86_address parts;
- int ok = ix86_decompose_address (addr, &parts);
- gcc_assert (ok);
+ if (addr)
+ {
+ ix86_address parts;
+ int ok = ix86_decompose_address (addr, &parts);
+ gcc_assert (ok);
- if (ix86_rip_relative_addr_p (&parts))
- return false;
- }
+ if (ix86_rip_relative_addr_p (&parts))
+ return false;
+ }
+ handle_stack_protect_test:
test_if = SET_SRC (pc_set (condjmp));
cond = XEXP (test_if, 0);
ccode = GET_CODE (cond);
/* Check whether conditional jump use Sign or Overflow Flags. */
if (!TARGET_FUSE_CMP_AND_BRANCH_SOFLAGS
- && (ccode == GE
- || ccode == GT
- || ccode == LE
- || ccode == LT))
+ && (ccode == GE || ccode == GT || ccode == LE || ccode == LT))
return false;
/* Return true for TYPE_TEST and TYPE_ICMP. */
- if (get_attr_type (condgen) == TYPE_TEST
- || get_attr_type (condgen) == TYPE_ICMP)
+ if (condgen_type == TYPE_TEST || condgen_type == TYPE_ICMP)
return true;
/* The following is the case that macro-fusion for alu + jmp. */
@@ -619,11 +627,8 @@ ix86_macro_fusion_pair_p (rtx_insn *condgen, rtx_insn *condjmp)
/* Macro-fusion for inc/dec + unsigned conditional jump is not
supported. */
- if (get_attr_type (condgen) == TYPE_INCDEC
- && (ccode == GEU
- || ccode == GTU
- || ccode == LEU
- || ccode == LTU))
+ if (condgen_type == TYPE_INCDEC
+ && (ccode == GEU || ccode == GTU || ccode == LEU || ccode == LTU))
return false;
return true;
diff --git a/gcc/config/i386/xmmintrin.h b/gcc/config/i386/xmmintrin.h
index 5828437..a915f6c 100644
--- a/gcc/config/i386/xmmintrin.h
+++ b/gcc/config/i386/xmmintrin.h
@@ -1165,7 +1165,68 @@ _m_pshufw (__m64 __A, int const __N)
extern __inline void __attribute__((__gnu_inline__, __always_inline__, __artificial__))
_mm_maskmove_si64 (__m64 __A, __m64 __N, char *__P)
{
+#ifdef __MMX_WITH_SSE__
+ /* Emulate MMX maskmovq with SSE2 maskmovdqu and handle unmapped bits
+ 64:127 at address __P. */
+ typedef long long __v2di __attribute__ ((__vector_size__ (16)));
+ typedef char __v16qi __attribute__ ((__vector_size__ (16)));
+ /* Zero-extend __A and __N to 128 bits. */
+ __v2di __A128 = __extension__ (__v2di) { ((__v1di) __A)[0], 0 };
+ __v2di __N128 = __extension__ (__v2di) { ((__v1di) __N)[0], 0 };
+
+ /* Check the alignment of __P. */
+ __SIZE_TYPE__ offset = ((__SIZE_TYPE__) __P) & 0xf;
+ if (offset)
+ {
+ /* If the misalignment of __P > 8, subtract __P by 8 bytes.
+ Otherwise, subtract __P by the misalignment. */
+ if (offset > 8)
+ offset = 8;
+ __P = (char *) (((__SIZE_TYPE__) __P) - offset);
+
+ /* Shift __A128 and __N128 to the left by the adjustment. */
+ switch (offset)
+ {
+ case 1:
+ __A128 = __builtin_ia32_pslldqi128 (__A128, 8);
+ __N128 = __builtin_ia32_pslldqi128 (__N128, 8);
+ break;
+ case 2:
+ __A128 = __builtin_ia32_pslldqi128 (__A128, 2 * 8);
+ __N128 = __builtin_ia32_pslldqi128 (__N128, 2 * 8);
+ break;
+ case 3:
+ __A128 = __builtin_ia32_pslldqi128 (__A128, 3 * 8);
+ __N128 = __builtin_ia32_pslldqi128 (__N128, 3 * 8);
+ break;
+ case 4:
+ __A128 = __builtin_ia32_pslldqi128 (__A128, 4 * 8);
+ __N128 = __builtin_ia32_pslldqi128 (__N128, 4 * 8);
+ break;
+ case 5:
+ __A128 = __builtin_ia32_pslldqi128 (__A128, 5 * 8);
+ __N128 = __builtin_ia32_pslldqi128 (__N128, 5 * 8);
+ break;
+ case 6:
+ __A128 = __builtin_ia32_pslldqi128 (__A128, 6 * 8);
+ __N128 = __builtin_ia32_pslldqi128 (__N128, 6 * 8);
+ break;
+ case 7:
+ __A128 = __builtin_ia32_pslldqi128 (__A128, 7 * 8);
+ __N128 = __builtin_ia32_pslldqi128 (__N128, 7 * 8);
+ break;
+ case 8:
+ __A128 = __builtin_ia32_pslldqi128 (__A128, 8 * 8);
+ __N128 = __builtin_ia32_pslldqi128 (__N128, 8 * 8);
+ break;
+ default:
+ break;
+ }
+ }
+ __builtin_ia32_maskmovdqu ((__v16qi)__A128, (__v16qi)__N128, __P);
+#else
__builtin_ia32_maskmovq ((__v8qi)__A, (__v8qi)__N, __P);
+#endif
}
extern __inline void __attribute__((__gnu_inline__, __always_inline__, __artificial__))
diff --git a/gcc/config/ia64/ia64.c b/gcc/config/ia64/ia64.c
index e8d905e..a2a6c5c 100644
--- a/gcc/config/ia64/ia64.c
+++ b/gcc/config/ia64/ia64.c
@@ -10913,6 +10913,7 @@ ia64_output_mi_thunk (FILE *file, tree thunk ATTRIBUTE_UNUSED,
HOST_WIDE_INT delta, HOST_WIDE_INT vcall_offset,
tree function)
{
+ const char *fnname = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (thunk));
rtx this_rtx, funexp;
rtx_insn *insn;
unsigned int this_parmno;
@@ -11032,15 +11033,16 @@ ia64_output_mi_thunk (FILE *file, tree thunk ATTRIBUTE_UNUSED,
/* Run just enough of rest_of_compilation to get the insns emitted.
There's not really enough bulk here to make other passes such as
- instruction scheduling worth while. Note that use_thunk calls
- assemble_start_function and assemble_end_function. */
+ instruction scheduling worth while. */
emit_all_insn_group_barriers (NULL);
insn = get_insns ();
shorten_branches (insn);
+ assemble_start_function (thunk, fnname);
final_start_function (insn, file, 1);
final (insn, file, 1);
final_end_function ();
+ assemble_end_function (thunk, fnname);
reload_completed = 0;
epilogue_completed = 0;
diff --git a/gcc/config/lm32/lm32.md b/gcc/config/lm32/lm32.md
index c09052c6..91a5fe1 100644
--- a/gcc/config/lm32/lm32.md
+++ b/gcc/config/lm32/lm32.md
@@ -216,7 +216,7 @@
}
}")
-(define_expand "movmemsi"
+(define_expand "cpymemsi"
[(parallel [(set (match_operand:BLK 0 "general_operand" "")
(match_operand:BLK 1 "general_operand" ""))
(use (match_operand:SI 2 "" ""))
diff --git a/gcc/config/m32c/blkmov.md b/gcc/config/m32c/blkmov.md
index d7da439..e5cdc80 100644
--- a/gcc/config/m32c/blkmov.md
+++ b/gcc/config/m32c/blkmov.md
@@ -40,14 +40,14 @@
;; 1 = source (mem:BLK ...)
;; 2 = count
;; 3 = alignment
-(define_expand "movmemhi"
+(define_expand "cpymemhi"
[(match_operand 0 "ap_operand" "")
(match_operand 1 "ap_operand" "")
(match_operand 2 "m32c_r3_operand" "")
(match_operand 3 "" "")
]
""
- "if (m32c_expand_movmemhi(operands)) DONE; FAIL;"
+ "if (m32c_expand_cpymemhi(operands)) DONE; FAIL;"
)
;; We can't use mode iterators for these because M16C uses r1h to extend
@@ -60,7 +60,7 @@
;; 3 = dest (in)
;; 4 = src (in)
;; 5 = count (in)
-(define_insn "movmemhi_bhi_op"
+(define_insn "cpymemhi_bhi_op"
[(set (mem:QI (match_operand:HI 3 "ap_operand" "0"))
(mem:QI (match_operand:HI 4 "ap_operand" "1")))
(set (match_operand:HI 2 "m32c_r3_operand" "=R3w")
@@ -75,7 +75,7 @@
"TARGET_A16"
"mov.b:q\t#0,r1h\n\tsmovf.b\t; %0[0..%2-1]=r1h%1[]"
)
-(define_insn "movmemhi_bpsi_op"
+(define_insn "cpymemhi_bpsi_op"
[(set (mem:QI (match_operand:PSI 3 "ap_operand" "0"))
(mem:QI (match_operand:PSI 4 "ap_operand" "1")))
(set (match_operand:HI 2 "m32c_r3_operand" "=R3w")
@@ -89,7 +89,7 @@
"TARGET_A24"
"smovf.b\t; %0[0..%2-1]=%1[]"
)
-(define_insn "movmemhi_whi_op"
+(define_insn "cpymemhi_whi_op"
[(set (mem:HI (match_operand:HI 3 "ap_operand" "0"))
(mem:HI (match_operand:HI 4 "ap_operand" "1")))
(set (match_operand:HI 2 "m32c_r3_operand" "=R3w")
@@ -104,7 +104,7 @@
"TARGET_A16"
"mov.b:q\t#0,r1h\n\tsmovf.w\t; %0[0..%2-1]=r1h%1[]"
)
-(define_insn "movmemhi_wpsi_op"
+(define_insn "cpymemhi_wpsi_op"
[(set (mem:HI (match_operand:PSI 3 "ap_operand" "0"))
(mem:HI (match_operand:PSI 4 "ap_operand" "1")))
(set (match_operand:HI 2 "m32c_r3_operand" "=R3w")
diff --git a/gcc/config/m32c/m32c-protos.h b/gcc/config/m32c/m32c-protos.h
index 7d4d478..fe926fd 100644
--- a/gcc/config/m32c/m32c-protos.h
+++ b/gcc/config/m32c/m32c-protos.h
@@ -43,7 +43,7 @@ void m32c_emit_eh_epilogue (rtx);
int m32c_expand_cmpstr (rtx *);
int m32c_expand_insv (rtx *);
int m32c_expand_movcc (rtx *);
-int m32c_expand_movmemhi (rtx *);
+int m32c_expand_cpymemhi (rtx *);
int m32c_expand_movstr (rtx *);
void m32c_expand_neg_mulpsi3 (rtx *);
int m32c_expand_setmemhi (rtx *);
diff --git a/gcc/config/m32c/m32c.c b/gcc/config/m32c/m32c.c
index 1a0d0c68..d0d24bb 100644
--- a/gcc/config/m32c/m32c.c
+++ b/gcc/config/m32c/m32c.c
@@ -3592,7 +3592,7 @@ m32c_expand_setmemhi(rtx *operands)
addresses, not [mem] syntax. $0 is the destination (MEM:BLK), $1
is the source (MEM:BLK), and $2 the count (HI). */
int
-m32c_expand_movmemhi(rtx *operands)
+m32c_expand_cpymemhi(rtx *operands)
{
rtx desta, srca, count;
rtx desto, srco, counto;
@@ -3620,9 +3620,9 @@ m32c_expand_movmemhi(rtx *operands)
{
count = copy_to_mode_reg (HImode, GEN_INT (INTVAL (count) / 2));
if (TARGET_A16)
- emit_insn (gen_movmemhi_whi_op (desto, srco, counto, desta, srca, count));
+ emit_insn (gen_cpymemhi_whi_op (desto, srco, counto, desta, srca, count));
else
- emit_insn (gen_movmemhi_wpsi_op (desto, srco, counto, desta, srca, count));
+ emit_insn (gen_cpymemhi_wpsi_op (desto, srco, counto, desta, srca, count));
return 1;
}
@@ -3632,9 +3632,9 @@ m32c_expand_movmemhi(rtx *operands)
count = copy_to_mode_reg (HImode, count);
if (TARGET_A16)
- emit_insn (gen_movmemhi_bhi_op (desto, srco, counto, desta, srca, count));
+ emit_insn (gen_cpymemhi_bhi_op (desto, srco, counto, desta, srca, count));
else
- emit_insn (gen_movmemhi_bpsi_op (desto, srco, counto, desta, srca, count));
+ emit_insn (gen_cpymemhi_bpsi_op (desto, srco, counto, desta, srca, count));
return 1;
}
diff --git a/gcc/config/m32r/m32r.c b/gcc/config/m32r/m32r.c
index 6e79b2a..ac18aa2 100644
--- a/gcc/config/m32r/m32r.c
+++ b/gcc/config/m32r/m32r.c
@@ -2598,7 +2598,7 @@ m32r_expand_block_move (rtx operands[])
to the word after the end of the source block, and dst_reg to point
to the last word of the destination block, provided that the block
is MAX_MOVE_BYTES long. */
- emit_insn (gen_movmemsi_internal (dst_reg, src_reg, at_a_time,
+ emit_insn (gen_cpymemsi_internal (dst_reg, src_reg, at_a_time,
new_dst_reg, new_src_reg));
emit_move_insn (dst_reg, new_dst_reg);
emit_move_insn (src_reg, new_src_reg);
@@ -2612,7 +2612,7 @@ m32r_expand_block_move (rtx operands[])
}
if (leftover)
- emit_insn (gen_movmemsi_internal (dst_reg, src_reg, GEN_INT (leftover),
+ emit_insn (gen_cpymemsi_internal (dst_reg, src_reg, GEN_INT (leftover),
gen_reg_rtx (SImode),
gen_reg_rtx (SImode)));
return 1;
diff --git a/gcc/config/m32r/m32r.md b/gcc/config/m32r/m32r.md
index be57397..e944363 100644
--- a/gcc/config/m32r/m32r.md
+++ b/gcc/config/m32r/m32r.md
@@ -2195,7 +2195,7 @@
;; Argument 2 is the length
;; Argument 3 is the alignment
-(define_expand "movmemsi"
+(define_expand "cpymemsi"
[(parallel [(set (match_operand:BLK 0 "general_operand" "")
(match_operand:BLK 1 "general_operand" ""))
(use (match_operand:SI 2 "immediate_operand" ""))
@@ -2214,7 +2214,7 @@
;; Insn generated by block moves
-(define_insn "movmemsi_internal"
+(define_insn "cpymemsi_internal"
[(set (mem:BLK (match_operand:SI 0 "register_operand" "r")) ;; destination
(mem:BLK (match_operand:SI 1 "register_operand" "r"))) ;; source
(use (match_operand:SI 2 "m32r_block_immediate_operand" "J"));; # bytes to move
diff --git a/gcc/config/m68k/m68k.c b/gcc/config/m68k/m68k.c
index 7a0d6f7..ca89f37 100644
--- a/gcc/config/m68k/m68k.c
+++ b/gcc/config/m68k/m68k.c
@@ -5071,6 +5071,7 @@ m68k_output_mi_thunk (FILE *file, tree thunk ATTRIBUTE_UNUSED,
HOST_WIDE_INT delta, HOST_WIDE_INT vcall_offset,
tree function)
{
+ const char *fnname = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (thunk));
rtx this_slot, offset, addr, mem, tmp;
rtx_insn *insn;
@@ -5147,9 +5148,11 @@ m68k_output_mi_thunk (FILE *file, tree thunk ATTRIBUTE_UNUSED,
/* Run just enough of rest_of_compilation. */
insn = get_insns ();
split_all_insns_noflow ();
+ assemble_start_function (thunk, fnname);
final_start_function (insn, file, 1);
final (insn, file, 1);
final_end_function ();
+ assemble_end_function (thunk, fnname);
/* Clean up the vars set above. */
reload_completed = 0;
diff --git a/gcc/config/mcore/mcore.md b/gcc/config/mcore/mcore.md
index cc84e34..c689351 100644
--- a/gcc/config/mcore/mcore.md
+++ b/gcc/config/mcore/mcore.md
@@ -2552,7 +2552,7 @@
;; Block move - adapted from m88k.md
;; ------------------------------------------------------------------------
-(define_expand "movmemsi"
+(define_expand "cpymemsi"
[(parallel [(set (mem:BLK (match_operand:BLK 0 "" ""))
(mem:BLK (match_operand:BLK 1 "" "")))
(use (match_operand:SI 2 "general_operand" ""))
diff --git a/gcc/config/microblaze/microblaze.c b/gcc/config/microblaze/microblaze.c
index 55c1bec..c2cbe3b 100644
--- a/gcc/config/microblaze/microblaze.c
+++ b/gcc/config/microblaze/microblaze.c
@@ -1250,7 +1250,7 @@ microblaze_block_move_loop (rtx dest, rtx src, HOST_WIDE_INT length)
microblaze_block_move_straight (dest, src, leftover);
}
-/* Expand a movmemsi instruction. */
+/* Expand a cpymemsi instruction. */
bool
microblaze_expand_block_move (rtx dest, rtx src, rtx length, rtx align_rtx)
@@ -3312,6 +3312,7 @@ microblaze_asm_output_mi_thunk (FILE *file, tree thunk_fndecl ATTRIBUTE_UNUSED,
HOST_WIDE_INT delta, HOST_WIDE_INT vcall_offset,
tree function)
{
+ const char *fnname = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (thunk_fndecl));
rtx this_rtx, funexp;
rtx_insn *insn;
@@ -3367,9 +3368,11 @@ microblaze_asm_output_mi_thunk (FILE *file, tree thunk_fndecl ATTRIBUTE_UNUSED,
"borrowed" from rs6000.c. */
insn = get_insns ();
shorten_branches (insn);
+ assemble_start_function (thunk_fndecl, fnname);
final_start_function (insn, file, 1);
final (insn, file, 1);
final_end_function ();
+ assemble_end_function (thunk_fndecl, fnname);
reload_completed = 0;
epilogue_completed = 0;
diff --git a/gcc/config/microblaze/microblaze.md b/gcc/config/microblaze/microblaze.md
index 183afff..1509e43 100644
--- a/gcc/config/microblaze/microblaze.md
+++ b/gcc/config/microblaze/microblaze.md
@@ -1144,7 +1144,7 @@
;; Argument 2 is the length
;; Argument 3 is the alignment
-(define_expand "movmemsi"
+(define_expand "cpymemsi"
[(parallel [(set (match_operand:BLK 0 "general_operand")
(match_operand:BLK 1 "general_operand"))
(use (match_operand:SI 2 ""))
diff --git a/gcc/config/mips/mips.c b/gcc/config/mips/mips.c
index 1de33b2..cbebb45 100644
--- a/gcc/config/mips/mips.c
+++ b/gcc/config/mips/mips.c
@@ -4849,6 +4849,7 @@ mips_split_move (rtx dest, rtx src, enum mips_split_type split_type, rtx insn_)
can forward SRC for DEST. This is most useful if the next insn is a
simple store. */
rtx_insn *insn = (rtx_insn *)insn_;
+ struct mips_address_info addr;
if (insn)
{
rtx_insn *next = next_nonnote_nondebug_insn_bb (insn);
@@ -4856,7 +4857,17 @@ mips_split_move (rtx dest, rtx src, enum mips_split_type split_type, rtx insn_)
{
rtx set = single_set (next);
if (set && SET_SRC (set) == dest)
- validate_change (next, &SET_SRC (set), src, false);
+ {
+ if (MEM_P (src))
+ {
+ rtx tmp = XEXP (src, 0);
+ mips_classify_address (&addr, tmp, GET_MODE (tmp), true);
+ if (REGNO (addr.reg) != REGNO (dest))
+ validate_change (next, &SET_SRC (set), src, false);
+ }
+ else
+ validate_change (next, &SET_SRC (set), src, false);
+ }
}
}
}
@@ -7927,15 +7938,15 @@ mips_use_by_pieces_infrastructure_p (unsigned HOST_WIDE_INT size,
{
if (op == STORE_BY_PIECES)
return mips_store_by_pieces_p (size, align);
- if (op == MOVE_BY_PIECES && HAVE_movmemsi)
+ if (op == MOVE_BY_PIECES && HAVE_cpymemsi)
{
- /* movmemsi is meant to generate code that is at least as good as
- move_by_pieces. However, movmemsi effectively uses a by-pieces
+ /* cpymemsi is meant to generate code that is at least as good as
+ move_by_pieces. However, cpymemsi effectively uses a by-pieces
implementation both for moves smaller than a word and for
word-aligned moves of no more than MIPS_MAX_MOVE_BYTES_STRAIGHT
bytes. We should allow the tree-level optimisers to do such
moves by pieces, as it often exposes other optimization
- opportunities. We might as well continue to use movmemsi at
+ opportunities. We might as well continue to use cpymemsi at
the rtl level though, as it produces better code when
scheduling is disabled (such as at -O). */
if (currently_expanding_to_rtl)
@@ -8154,7 +8165,7 @@ mips_block_move_loop (rtx dest, rtx src, HOST_WIDE_INT length,
emit_insn (gen_nop ());
}
-/* Expand a movmemsi instruction, which copies LENGTH bytes from
+/* Expand a cpymemsi instruction, which copies LENGTH bytes from
memory reference SRC to memory reference DEST. */
bool
@@ -9577,7 +9588,7 @@ mips_dwarf_frame_reg_mode (int regno)
{
machine_mode mode = default_dwarf_frame_reg_mode (regno);
- if (FP_REG_P (regno) && mips_abi == ABI_32 && TARGET_FLOAT64)
+ if (FP_REG_P (regno) && mips_abi == ABI_32 && !TARGET_FLOAT32)
mode = SImode;
return mode;
@@ -13449,7 +13460,7 @@ mips_preferred_simd_mode (scalar_mode mode)
/* Implement TARGET_VECTORIZE_AUTOVECTORIZE_VECTOR_SIZES. */
static void
-mips_autovectorize_vector_sizes (vector_sizes *sizes)
+mips_autovectorize_vector_sizes (vector_sizes *sizes, bool)
{
if (ISA_HAS_MSA)
sizes->safe_push (16);
@@ -16856,6 +16867,19 @@ mips_expand_builtin_insn (enum insn_code icode, unsigned int nops,
std::swap (ops[1], ops[2]);
break;
+ case CODE_FOR_msa_maddv_b:
+ case CODE_FOR_msa_maddv_h:
+ case CODE_FOR_msa_maddv_w:
+ case CODE_FOR_msa_maddv_d:
+ case CODE_FOR_msa_fmadd_w:
+ case CODE_FOR_msa_fmadd_d:
+ case CODE_FOR_msa_fmsub_w:
+ case CODE_FOR_msa_fmsub_d:
+ /* fma(a, b, c) results into (a * b + c), however builtin_msa_fmadd expects
+ it to be (a + b * c). Swap the 1st and 3rd operands. */
+ std::swap (ops[1], ops[3]);
+ break;
+
case CODE_FOR_msa_slli_b:
case CODE_FOR_msa_slli_h:
case CODE_FOR_msa_slli_w:
@@ -19420,6 +19444,7 @@ mips_output_mi_thunk (FILE *file, tree thunk_fndecl ATTRIBUTE_UNUSED,
HOST_WIDE_INT delta, HOST_WIDE_INT vcall_offset,
tree function)
{
+ const char *fnname = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (thunk_fndecl));
rtx this_rtx, temp1, temp2, fnaddr;
rtx_insn *insn;
bool use_sibcall_p;
@@ -19532,9 +19557,11 @@ mips_output_mi_thunk (FILE *file, tree thunk_fndecl ATTRIBUTE_UNUSED,
split_all_insns_noflow ();
mips16_lay_out_constants (true);
shorten_branches (insn);
+ assemble_start_function (thunk_fndecl, fnname);
final_start_function (insn, file, 1);
final (insn, file, 1);
final_end_function ();
+ assemble_end_function (thunk_fndecl, fnname);
/* Clean up the vars set above. Note that final_end_function resets
the global pointer for us. */
@@ -20609,9 +20636,19 @@ mips_final_postscan_insn (FILE *file ATTRIBUTE_UNUSED, rtx_insn *insn,
if (INSN_P (insn)
&& GET_CODE (PATTERN (insn)) == UNSPEC_VOLATILE
&& XINT (PATTERN (insn), 1) == UNSPEC_CONSTTABLE_END)
- mips_set_text_contents_type (asm_out_file, "__pend_",
- INTVAL (XVECEXP (PATTERN (insn), 0, 0)),
- TRUE);
+ {
+ rtx_insn *next_insn = next_real_nondebug_insn (insn);
+ bool code_p = (next_insn != NULL
+ && INSN_P (next_insn)
+ && (GET_CODE (PATTERN (next_insn)) != UNSPEC_VOLATILE
+ || XINT (PATTERN (next_insn), 1) != UNSPEC_CONSTTABLE));
+
+ /* Switch content type depending on whether there is code beyond
+ the constant pool. */
+ mips_set_text_contents_type (asm_out_file, "__pend_",
+ INTVAL (XVECEXP (PATTERN (insn), 0, 0)),
+ code_p);
+ }
}
/* Return the function that is used to expand the <u>mulsidi3 pattern.
diff --git a/gcc/config/mips/mips.h b/gcc/config/mips/mips.h
index 953d82e..a5be7fa3 100644
--- a/gcc/config/mips/mips.h
+++ b/gcc/config/mips/mips.h
@@ -3099,12 +3099,12 @@ while (0)
#define MIPS_MIN_MOVE_MEM_ALIGN 16
/* The maximum number of bytes that can be copied by one iteration of
- a movmemsi loop; see mips_block_move_loop. */
+ a cpymemsi loop; see mips_block_move_loop. */
#define MIPS_MAX_MOVE_BYTES_PER_LOOP_ITER \
(UNITS_PER_WORD * 4)
/* The maximum number of bytes that can be copied by a straight-line
- implementation of movmemsi; see mips_block_move_straight. We want
+ implementation of cpymemsi; see mips_block_move_straight. We want
to make sure that any loop-based implementation will iterate at
least twice. */
#define MIPS_MAX_MOVE_BYTES_STRAIGHT \
@@ -3119,11 +3119,11 @@ while (0)
#define MIPS_CALL_RATIO 8
-/* Any loop-based implementation of movmemsi will have at least
+/* Any loop-based implementation of cpymemsi will have at least
MIPS_MAX_MOVE_BYTES_STRAIGHT / UNITS_PER_WORD memory-to-memory
moves, so allow individual copies of fewer elements.
- When movmemsi is not available, use a value approximating
+ When cpymemsi is not available, use a value approximating
the length of a memcpy call sequence, so that move_by_pieces
will generate inline code if it is shorter than a function call.
Since move_by_pieces_ninsns counts memory-to-memory moves, but
@@ -3131,7 +3131,7 @@ while (0)
value of MIPS_CALL_RATIO to take that into account. */
#define MOVE_RATIO(speed) \
- (HAVE_movmemsi \
+ (HAVE_cpymemsi \
? MIPS_MAX_MOVE_BYTES_STRAIGHT / MOVE_MAX \
: MIPS_CALL_RATIO / 2)
diff --git a/gcc/config/mips/mips.md b/gcc/config/mips/mips.md
index 2ae1f7e..d260cf9 100644
--- a/gcc/config/mips/mips.md
+++ b/gcc/config/mips/mips.md
@@ -5638,7 +5638,7 @@
;; Argument 2 is the length
;; Argument 3 is the alignment
-(define_expand "movmemsi"
+(define_expand "cpymemsi"
[(parallel [(set (match_operand:BLK 0 "general_operand")
(match_operand:BLK 1 "general_operand"))
(use (match_operand:SI 2 ""))
diff --git a/gcc/config/mmix/mmix.c b/gcc/config/mmix/mmix.c
index c2136e2..380ecde 100644
--- a/gcc/config/mmix/mmix.c
+++ b/gcc/config/mmix/mmix.c
@@ -916,7 +916,7 @@ mmix_target_asm_function_epilogue (FILE *stream)
static void
mmix_asm_output_mi_thunk (FILE *stream,
- tree fndecl ATTRIBUTE_UNUSED,
+ tree thunk_fndecl ATTRIBUTE_UNUSED,
HOST_WIDE_INT delta,
HOST_WIDE_INT vcall_offset ATTRIBUTE_UNUSED,
tree func)
@@ -925,6 +925,9 @@ mmix_asm_output_mi_thunk (FILE *stream,
location of structure to return as invisible first argument), you
need to tweak this code too. */
const char *regname = reg_names[MMIX_FIRST_INCOMING_ARG_REGNUM];
+ const char *fnname = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (thunk_fndecl));
+
+ assemble_start_function (thunk_fndecl, fnname);
if (delta >= 0 && delta < 65536)
fprintf (stream, "\tINCL %s,%d\n", regname, (int)delta);
@@ -939,6 +942,7 @@ mmix_asm_output_mi_thunk (FILE *stream,
fprintf (stream, "\tJMP ");
assemble_name (stream, XSTR (XEXP (DECL_RTL (func), 0), 0));
fprintf (stream, "\n");
+ assemble_end_function (thunk_fndecl, fnname);
}
/* FUNCTION_PROFILER. */
diff --git a/gcc/config/mn10300/mn10300.c b/gcc/config/mn10300/mn10300.c
index 51116f5..8fdd1c5 100644
--- a/gcc/config/mn10300/mn10300.c
+++ b/gcc/config/mn10300/mn10300.c
@@ -2585,8 +2585,10 @@ mn10300_asm_output_mi_thunk (FILE * file,
HOST_WIDE_INT vcall_offset,
tree function)
{
+ const char *fnname = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (thunk_fndecl));
const char * _this;
+ assemble_start_function (thunk_fndecl, fnname);
/* Get the register holding the THIS parameter. Handle the case
where there is a hidden first argument for a returned structure. */
if (aggregate_value_p (TREE_TYPE (TREE_TYPE (function)), function))
@@ -2613,6 +2615,7 @@ mn10300_asm_output_mi_thunk (FILE * file,
fputs ("\tjmp ", file);
assemble_name (file, XSTR (XEXP (DECL_RTL (function), 0), 0));
putc ('\n', file);
+ assemble_end_function (thunk_fndecl, fnname);
}
/* Return true if mn10300_output_mi_thunk would be able to output the
diff --git a/gcc/config/msp430/msp430.c b/gcc/config/msp430/msp430.c
index 020e980..365e9eb 100644
--- a/gcc/config/msp430/msp430.c
+++ b/gcc/config/msp430/msp430.c
@@ -3046,6 +3046,7 @@ msp430_expand_helper (rtx *operands, const char *helper_name, bool const_variant
{
rtx c, f;
char *helper_const = NULL;
+ int arg1 = 12;
int arg2 = 13;
int arg1sz = 1;
machine_mode arg0mode = GET_MODE (operands[0]);
@@ -3079,6 +3080,13 @@ msp430_expand_helper (rtx *operands, const char *helper_name, bool const_variant
arg2 = 14;
arg1sz = 2;
}
+ else if (arg1mode == DImode)
+ {
+ /* Shift value in R8:R11, shift amount in R12. */
+ arg1 = 8;
+ arg1sz = 4;
+ arg2 = 12;
+ }
if (const_variants
&& CONST_INT_P (operands[2])
@@ -3091,7 +3099,7 @@ msp430_expand_helper (rtx *operands, const char *helper_name, bool const_variant
snprintf (helper_const, len, "%s_%d", helper_name, (int) INTVAL (operands[2]));
}
- emit_move_insn (gen_rtx_REG (arg1mode, 12),
+ emit_move_insn (gen_rtx_REG (arg1mode, arg1),
operands[1]);
if (!helper_const)
emit_move_insn (gen_rtx_REG (arg2mode, arg2),
@@ -3104,12 +3112,13 @@ msp430_expand_helper (rtx *operands, const char *helper_name, bool const_variant
RTL_CONST_CALL_P (c) = 1;
f = 0;
- use_regs (&f, 12, arg1sz);
+ use_regs (&f, arg1, arg1sz);
if (!helper_const)
use_regs (&f, arg2, 1);
add_function_usage_to (c, f);
emit_move_insn (operands[0],
+ /* Return value will always start in R12. */
gen_rtx_REG (arg0mode, 12));
}
diff --git a/gcc/config/msp430/msp430.h b/gcc/config/msp430/msp430.h
index c0aa8ea..1288b1a 100644
--- a/gcc/config/msp430/msp430.h
+++ b/gcc/config/msp430/msp430.h
@@ -185,9 +185,11 @@ extern const char * msp430_select_hwmult_lib (int, const char **);
/* Layout of Source Language Data Types */
#undef SIZE_TYPE
-#define SIZE_TYPE (TARGET_LARGE ? "__int20 unsigned" : "unsigned int")
+#define SIZE_TYPE (TARGET_LARGE \
+ ? "__int20__ unsigned" \
+ : "unsigned int")
#undef PTRDIFF_TYPE
-#define PTRDIFF_TYPE (TARGET_LARGE ? "__int20" : "int")
+#define PTRDIFF_TYPE (TARGET_LARGE ? "__int20__" : "int")
#undef WCHAR_TYPE
#define WCHAR_TYPE "long int"
#undef WCHAR_TYPE_SIZE
diff --git a/gcc/config/msp430/msp430.md b/gcc/config/msp430/msp430.md
index 344d21d..f6d6889 100644
--- a/gcc/config/msp430/msp430.md
+++ b/gcc/config/msp430/msp430.md
@@ -756,8 +756,9 @@
(match_operand:HI 2 "general_operand")))]
""
{
- if (GET_CODE (operands[1]) == SUBREG
- && REG_P (XEXP (operands[1], 0)))
+ if ((GET_CODE (operands[1]) == SUBREG
+ && REG_P (XEXP (operands[1], 0)))
+ || MEM_P (operands[1]))
operands[1] = force_reg (HImode, operands[1]);
if (msp430x
&& REG_P (operands[0])
@@ -768,7 +769,10 @@
&& INTVAL (operands[2]) == 1)
emit_insn (gen_slli_1 (operands[0], operands[1]));
else
- msp430_expand_helper (operands, \"__mspabi_slli\", true);
+ /* The const variants of mspabi shifts have larger code size than the
+ generic version, so use the generic version if optimizing for
+ size. */
+ msp430_expand_helper (operands, \"__mspabi_slli\", !optimize_size);
DONE;
}
)
@@ -814,10 +818,22 @@
(ashift:SI (match_operand:SI 1 "general_operand")
(match_operand:SI 2 "general_operand")))]
""
- "msp430_expand_helper (operands, \"__mspabi_slll\", true);
+ "msp430_expand_helper (operands, \"__mspabi_slll\", !optimize_size);
DONE;"
)
+(define_expand "ashldi3"
+ [(set (match_operand:DI 0 "nonimmediate_operand")
+ (ashift:DI (match_operand:DI 1 "general_operand")
+ (match_operand:DI 2 "general_operand")))]
+ ""
+ {
+ /* No const_variant for 64-bit shifts. */
+ msp430_expand_helper (operands, \"__mspabi_sllll\", false);
+ DONE;
+ }
+)
+
;;----------
;; signed A >> C
@@ -828,8 +844,9 @@
(match_operand:HI 2 "general_operand")))]
""
{
- if (GET_CODE (operands[1]) == SUBREG
- && REG_P (XEXP (operands[1], 0)))
+ if ((GET_CODE (operands[1]) == SUBREG
+ && REG_P (XEXP (operands[1], 0)))
+ || MEM_P (operands[1]))
operands[1] = force_reg (HImode, operands[1]);
if (msp430x
&& REG_P (operands[0])
@@ -840,7 +857,7 @@
&& INTVAL (operands[2]) == 1)
emit_insn (gen_srai_1 (operands[0], operands[1]));
else
- msp430_expand_helper (operands, \"__mspabi_srai\", true);
+ msp430_expand_helper (operands, \"__mspabi_srai\", !optimize_size);
DONE;
}
)
@@ -902,10 +919,22 @@
(ashiftrt:SI (match_operand:SI 1 "general_operand")
(match_operand:SI 2 "general_operand")))]
""
- "msp430_expand_helper (operands, \"__mspabi_sral\", true);
+ "msp430_expand_helper (operands, \"__mspabi_sral\", !optimize_size);
DONE;"
)
+(define_expand "ashrdi3"
+ [(set (match_operand:DI 0 "nonimmediate_operand")
+ (ashift:DI (match_operand:DI 1 "general_operand")
+ (match_operand:DI 2 "general_operand")))]
+ ""
+ {
+ /* No const_variant for 64-bit shifts. */
+ msp430_expand_helper (operands, \"__mspabi_srall\", false);
+ DONE;
+ }
+)
+
;;----------
;; unsigned A >> C
@@ -916,8 +945,9 @@
(match_operand:HI 2 "general_operand")))]
""
{
- if (GET_CODE (operands[1]) == SUBREG
- && REG_P (XEXP (operands[1], 0)))
+ if ((GET_CODE (operands[1]) == SUBREG
+ && REG_P (XEXP (operands[1], 0)))
+ || MEM_P (operands[1]))
operands[1] = force_reg (HImode, operands[1]);
if (msp430x
&& REG_P (operands[0])
@@ -928,7 +958,7 @@
&& INTVAL (operands[2]) == 1)
emit_insn (gen_srli_1 (operands[0], operands[1]));
else
- msp430_expand_helper (operands, \"__mspabi_srli\", true);
+ msp430_expand_helper (operands, \"__mspabi_srli\", !optimize_size);
DONE;
}
)
@@ -980,10 +1010,22 @@
(lshiftrt:SI (match_operand:SI 1 "general_operand")
(match_operand:SI 2 "general_operand")))]
""
- "msp430_expand_helper (operands, \"__mspabi_srll\", true);
+ "msp430_expand_helper (operands, \"__mspabi_srll\", !optimize_size);
DONE;"
)
+(define_expand "lshrdi3"
+ [(set (match_operand:DI 0 "nonimmediate_operand")
+ (ashift:DI (match_operand:DI 1 "general_operand")
+ (match_operand:DI 2 "general_operand")))]
+ ""
+ {
+ /* No const_variant for 64-bit shifts. */
+ msp430_expand_helper (operands, \"__mspabi_srlll\", false);
+ DONE;
+ }
+)
+
;;------------------------------------------------------------
;; Function Entry/Exit
diff --git a/gcc/config/nds32/nds32-memory-manipulation.c b/gcc/config/nds32/nds32-memory-manipulation.c
index 71b75dc..b3f2cd6 100644
--- a/gcc/config/nds32/nds32-memory-manipulation.c
+++ b/gcc/config/nds32/nds32-memory-manipulation.c
@@ -1,4 +1,4 @@
-/* Auxiliary functions for expand movmem, setmem, cmpmem, load_multiple
+/* Auxiliary functions for expand cpymem, setmem, cmpmem, load_multiple
and store_multiple pattern of Andes NDS32 cpu for GNU compiler
Copyright (C) 2012-2019 Free Software Foundation, Inc.
Contributed by Andes Technology Corporation.
@@ -120,14 +120,14 @@ nds32_emit_mem_move_block (int base_regno, int count,
/* ------------------------------------------------------------------------ */
-/* Auxiliary function for expand movmem pattern. */
+/* Auxiliary function for expand cpymem pattern. */
static bool
-nds32_expand_movmemsi_loop_unknown_size (rtx dstmem, rtx srcmem,
+nds32_expand_cpymemsi_loop_unknown_size (rtx dstmem, rtx srcmem,
rtx size,
rtx alignment)
{
- /* Emit loop version of movmem.
+ /* Emit loop version of cpymem.
andi $size_least_3_bit, $size, #~7
add $dst_end, $dst, $size
@@ -254,7 +254,7 @@ nds32_expand_movmemsi_loop_unknown_size (rtx dstmem, rtx srcmem,
}
static bool
-nds32_expand_movmemsi_loop_known_size (rtx dstmem, rtx srcmem,
+nds32_expand_cpymemsi_loop_known_size (rtx dstmem, rtx srcmem,
rtx size, rtx alignment)
{
rtx dst_base_reg, src_base_reg;
@@ -288,7 +288,7 @@ nds32_expand_movmemsi_loop_known_size (rtx dstmem, rtx srcmem,
if (total_bytes < 8)
{
- /* Emit total_bytes less than 8 loop version of movmem.
+ /* Emit total_bytes less than 8 loop version of cpymem.
add $dst_end, $dst, $size
move $dst_itr, $dst
.Lbyte_mode_loop:
@@ -321,7 +321,7 @@ nds32_expand_movmemsi_loop_known_size (rtx dstmem, rtx srcmem,
}
else if (total_bytes % 8 == 0)
{
- /* Emit multiple of 8 loop version of movmem.
+ /* Emit multiple of 8 loop version of cpymem.
add $dst_end, $dst, $size
move $dst_itr, $dst
@@ -370,7 +370,7 @@ nds32_expand_movmemsi_loop_known_size (rtx dstmem, rtx srcmem,
else
{
/* Handle size greater than 8, and not a multiple of 8. */
- return nds32_expand_movmemsi_loop_unknown_size (dstmem, srcmem,
+ return nds32_expand_cpymemsi_loop_unknown_size (dstmem, srcmem,
size, alignment);
}
@@ -378,19 +378,19 @@ nds32_expand_movmemsi_loop_known_size (rtx dstmem, rtx srcmem,
}
static bool
-nds32_expand_movmemsi_loop (rtx dstmem, rtx srcmem,
+nds32_expand_cpymemsi_loop (rtx dstmem, rtx srcmem,
rtx size, rtx alignment)
{
if (CONST_INT_P (size))
- return nds32_expand_movmemsi_loop_known_size (dstmem, srcmem,
+ return nds32_expand_cpymemsi_loop_known_size (dstmem, srcmem,
size, alignment);
else
- return nds32_expand_movmemsi_loop_unknown_size (dstmem, srcmem,
+ return nds32_expand_cpymemsi_loop_unknown_size (dstmem, srcmem,
size, alignment);
}
static bool
-nds32_expand_movmemsi_unroll (rtx dstmem, rtx srcmem,
+nds32_expand_cpymemsi_unroll (rtx dstmem, rtx srcmem,
rtx total_bytes, rtx alignment)
{
rtx dst_base_reg, src_base_reg;
@@ -533,13 +533,13 @@ nds32_expand_movmemsi_unroll (rtx dstmem, rtx srcmem,
This is auxiliary extern function to help create rtx template.
Check nds32-multiple.md file for the patterns. */
bool
-nds32_expand_movmemsi (rtx dstmem, rtx srcmem, rtx total_bytes, rtx alignment)
+nds32_expand_cpymemsi (rtx dstmem, rtx srcmem, rtx total_bytes, rtx alignment)
{
- if (nds32_expand_movmemsi_unroll (dstmem, srcmem, total_bytes, alignment))
+ if (nds32_expand_cpymemsi_unroll (dstmem, srcmem, total_bytes, alignment))
return true;
if (!optimize_size && optimize > 2)
- return nds32_expand_movmemsi_loop (dstmem, srcmem, total_bytes, alignment);
+ return nds32_expand_cpymemsi_loop (dstmem, srcmem, total_bytes, alignment);
return false;
}
diff --git a/gcc/config/nds32/nds32-multiple.md b/gcc/config/nds32/nds32-multiple.md
index a1e10c0..98d9508 100644
--- a/gcc/config/nds32/nds32-multiple.md
+++ b/gcc/config/nds32/nds32-multiple.md
@@ -3751,14 +3751,14 @@
;; operands[3] is the known shared alignment.
-(define_expand "movmemsi"
+(define_expand "cpymemsi"
[(match_operand:BLK 0 "general_operand" "")
(match_operand:BLK 1 "general_operand" "")
(match_operand:SI 2 "nds32_reg_constant_operand" "")
(match_operand:SI 3 "const_int_operand" "")]
""
{
- if (nds32_expand_movmemsi (operands[0],
+ if (nds32_expand_cpymemsi (operands[0],
operands[1],
operands[2],
operands[3]))
diff --git a/gcc/config/nds32/nds32-protos.h b/gcc/config/nds32/nds32-protos.h
index aaa65d6..7ae1954 100644
--- a/gcc/config/nds32/nds32-protos.h
+++ b/gcc/config/nds32/nds32-protos.h
@@ -78,7 +78,7 @@ extern rtx nds32_di_low_part_subreg(rtx);
extern rtx nds32_expand_load_multiple (int, int, rtx, rtx, bool, rtx *);
extern rtx nds32_expand_store_multiple (int, int, rtx, rtx, bool, rtx *);
-extern bool nds32_expand_movmemsi (rtx, rtx, rtx, rtx);
+extern bool nds32_expand_cpymemsi (rtx, rtx, rtx, rtx);
extern bool nds32_expand_setmem (rtx, rtx, rtx, rtx, rtx, rtx);
extern bool nds32_expand_strlen (rtx, rtx, rtx, rtx);
diff --git a/gcc/config/nds32/nds32.c b/gcc/config/nds32/nds32.c
index fe5c260..eba9812 100644
--- a/gcc/config/nds32/nds32.c
+++ b/gcc/config/nds32/nds32.c
@@ -2227,8 +2227,10 @@ nds32_asm_output_mi_thunk (FILE *file, tree thunk ATTRIBUTE_UNUSED,
HOST_WIDE_INT vcall_offset ATTRIBUTE_UNUSED,
tree function)
{
+ const char *fnname = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (thunk));
int this_regno;
+ assemble_start_function (thunk, fnname);
/* Make sure unwind info is emitted for the thunk if needed. */
final_start_function (emit_barrier (), file, 1);
@@ -2299,6 +2301,7 @@ nds32_asm_output_mi_thunk (FILE *file, tree thunk ATTRIBUTE_UNUSED,
}
final_end_function ();
+ assemble_end_function (thunk, fnname);
}
/* -- Permitting tail calls. */
diff --git a/gcc/config/netbsd-elf.h b/gcc/config/netbsd-elf.h
index e35758b..12ebdd6 100644
--- a/gcc/config/netbsd-elf.h
+++ b/gcc/config/netbsd-elf.h
@@ -73,6 +73,9 @@ along with GCC; see the file COPYING3. If not see
Target-specific code must provide the %(netbsd_entry_point) spec. */
+#define NETBSD_LINK_LD_ELF_SO_SPEC \
+ "%{!dynamic-linker:-dynamic-linker /usr/libexec/ld.elf_so}"
+
#define NETBSD_LINK_SPEC_ELF \
"%{assert*} %{R*} %{rpath*} \
%{shared:-shared} \
@@ -87,6 +90,17 @@ along with GCC; see the file COPYING3. If not see
-dynamic-linker /usr/libexec/ld.elf_so} \
%{static:-static}}"
+/* Provide the standard list of subtarget extra specs for NetBSD targets. */
+#define NETBSD_SUBTARGET_EXTRA_SPECS \
+ { "netbsd_link_ld_elf_so", NETBSD_LINK_LD_ELF_SO_SPEC }, \
+ { "netbsd_cpp_spec", NETBSD_CPP_SPEC }, \
+ { "netbsd_link_spec", NETBSD_LINK_SPEC_ELF }, \
+ { "netbsd_entry_point", NETBSD_ENTRY_POINT }, \
+ { "netbsd_endfile_spec", NETBSD_ENDFILE_SPEC },
+
+#undef SUBTARGET_EXTRA_SPECS
+#define SUBTARGET_EXTRA_SPECS NETBSD_SUBTARGET_EXTRA_SPECS
+
/* Use --as-needed -lgcc_s for eh support. */
#ifdef HAVE_LD_AS_NEEDED
#define USE_LD_AS_NEEDED 1
diff --git a/gcc/config/nios2/nios2.c b/gcc/config/nios2/nios2.c
index 1f00b8a..250c6ac 100644
--- a/gcc/config/nios2/nios2.c
+++ b/gcc/config/nios2/nios2.c
@@ -4469,6 +4469,7 @@ nios2_asm_output_mi_thunk (FILE *file, tree thunk_fndecl ATTRIBUTE_UNUSED,
HOST_WIDE_INT delta, HOST_WIDE_INT vcall_offset,
tree function)
{
+ const char *fnname = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (thunk_fndecl));
rtx this_rtx, funexp;
rtx_insn *insn;
@@ -4518,13 +4519,14 @@ nios2_asm_output_mi_thunk (FILE *file, tree thunk_fndecl ATTRIBUTE_UNUSED,
/* Run just enough of rest_of_compilation to get the insns emitted.
There's not really enough bulk here to make other passes such as
- instruction scheduling worth while. Note that use_thunk calls
- assemble_start_function and assemble_end_function. */
+ instruction scheduling worth while. */
insn = get_insns ();
shorten_branches (insn);
+ assemble_start_function (thunk_fndecl, fnname);
final_start_function (insn, file, 1);
final (insn, file, 1);
final_end_function ();
+ assemble_end_function (thunk_fndecl, fnname);
/* Stop pretending to be a post-reload pass. */
reload_completed = 0;
diff --git a/gcc/config/nvptx/nvptx.c b/gcc/config/nvptx/nvptx.c
index a28099a..c53a1ae 100644
--- a/gcc/config/nvptx/nvptx.c
+++ b/gcc/config/nvptx/nvptx.c
@@ -1475,7 +1475,7 @@ nvptx_output_softstack_switch (FILE *file, bool entering,
fputs (";\n", file);
if (!CONST_INT_P (size) || UINTVAL (align) > GET_MODE_SIZE (DImode))
fprintf (file,
- "\t\tand.u%d %%r%d, %%r%d, -" HOST_WIDE_INT_PRINT_DEC ";\n",
+ "\t\tand.b%d %%r%d, %%r%d, -" HOST_WIDE_INT_PRINT_DEC ";\n",
bits, regno, regno, UINTVAL (align));
}
if (cfun->machine->has_softstack)
@@ -3258,6 +3258,7 @@ nvptx_find_par (bb_insn_map_t *map, parallel *par, basic_block block)
unsigned mask = UINTVAL (XVECEXP (PATTERN (end), 0, 0));
gcc_assert (par->mask == mask);
+ gcc_assert (par->join_block == NULL);
par->join_block = block;
par->join_insn = end;
if (nvptx_needs_shared_bcast (mask))
@@ -3551,7 +3552,7 @@ nvptx_sese_number (int n, int p, int dir, basic_block b,
size_t offset = (dir > 0 ? offsetof (edge_def, dest)
: offsetof (edge_def, src));
edge e;
- edge_iterator (ei);
+ edge_iterator ei;
FOR_EACH_EDGE (e, ei, edges)
{
@@ -3574,7 +3575,7 @@ nvptx_sese_pseudo (basic_block me, bb_sese *sese, int depth, int dir,
vec<edge, va_gc> *edges, size_t offset)
{
edge e;
- edge_iterator (ei);
+ edge_iterator ei;
int hi_back = depth;
pseudo_node_t node_back (0, depth);
int hi_child = depth;
@@ -4402,8 +4403,10 @@ nvptx_single (unsigned mask, basic_block from, basic_block to)
{
rtx_code_label *label = gen_label_rtx ();
rtx pred = cfun->machine->axis_predicate[mode - GOMP_DIM_WORKER];
- rtx_insn **mode_jump = mode == GOMP_DIM_VECTOR ? &vector_jump : &worker_jump;
- rtx_insn **mode_label = mode == GOMP_DIM_VECTOR ? &vector_label : &worker_label;
+ rtx_insn **mode_jump
+ = mode == GOMP_DIM_VECTOR ? &vector_jump : &worker_jump;
+ rtx_insn **mode_label
+ = mode == GOMP_DIM_VECTOR ? &vector_label : &worker_label;
if (!pred)
{
@@ -4437,10 +4440,7 @@ nvptx_single (unsigned mask, basic_block from, basic_block to)
emit_insn_after (gen_exit (), label_insn);
}
- if (mode == GOMP_DIM_VECTOR)
- vector_label = label_insn;
- else
- worker_label = label_insn;
+ *mode_label = label_insn;
}
/* Now deal with propagating the branch condition. */
diff --git a/gcc/config/nvptx/nvptx.md b/gcc/config/nvptx/nvptx.md
index 1a090a47..58a18fe 100644
--- a/gcc/config/nvptx/nvptx.md
+++ b/gcc/config/nvptx/nvptx.md
@@ -745,19 +745,19 @@
;; Calls
-(define_insn "call_insn"
+(define_insn "call_insn_<mode>"
[(match_parallel 2 "call_operation"
- [(call (mem:QI (match_operand 0 "call_insn_operand" "Rs"))
+ [(call (mem:QI (match_operand:P 0 "call_insn_operand" "Rs"))
(match_operand 1))])]
""
{
return nvptx_output_call_insn (insn, NULL_RTX, operands[0]);
})
-(define_insn "call_value_insn"
+(define_insn "call_value_insn_<mode>"
[(match_parallel 3 "call_operation"
[(set (match_operand 0 "nvptx_register_operand" "=R")
- (call (mem:QI (match_operand 1 "call_insn_operand" "Rs"))
+ (call (mem:QI (match_operand:P 1 "call_insn_operand" "Rs"))
(match_operand 2)))])]
""
{
@@ -1025,8 +1025,8 @@
""
{
if (TARGET_SOFT_STACK)
- emit_insn (gen_set_softstack_insn (gen_rtx_REG (Pmode,
- SOFTSTACK_PREV_REGNUM)));
+ emit_insn (gen_set_softstack (Pmode, gen_rtx_REG (Pmode,
+ SOFTSTACK_PREV_REGNUM)));
emit_jump_insn (gen_return ());
DONE;
})
@@ -1059,7 +1059,7 @@
{
emit_move_insn (stack_pointer_rtx,
gen_rtx_MINUS (Pmode, stack_pointer_rtx, operands[1]));
- emit_insn (gen_set_softstack_insn (stack_pointer_rtx));
+ emit_insn (gen_set_softstack (Pmode, stack_pointer_rtx));
emit_move_insn (operands[0], virtual_stack_dynamic_rtx);
DONE;
}
@@ -1071,8 +1071,8 @@
DONE;
})
-(define_insn "set_softstack_insn"
- [(unspec [(match_operand 0 "nvptx_register_operand" "R")]
+(define_insn "@set_softstack_<mode>"
+ [(unspec [(match_operand:P 0 "nvptx_register_operand" "R")]
UNSPEC_SET_SOFTSTACK)]
"TARGET_SOFT_STACK"
{
@@ -1087,7 +1087,7 @@
if (TARGET_SOFT_STACK)
{
emit_move_insn (operands[0], operands[1]);
- emit_insn (gen_set_softstack_insn (operands[0]));
+ emit_insn (gen_set_softstack (Pmode, operands[0]));
}
DONE;
})
@@ -1237,10 +1237,10 @@
;; Patterns for OpenMP SIMD-via-SIMT lowering
-(define_insn "omp_simt_enter_insn"
- [(set (match_operand 0 "nvptx_register_operand" "=R")
- (unspec_volatile [(match_operand 1 "nvptx_nonmemory_operand" "Ri")
- (match_operand 2 "nvptx_nonmemory_operand" "Ri")]
+(define_insn "@omp_simt_enter_<mode>"
+ [(set (match_operand:P 0 "nvptx_register_operand" "=R")
+ (unspec_volatile:P [(match_operand:P 1 "nvptx_nonmemory_operand" "Ri")
+ (match_operand:P 2 "nvptx_nonmemory_operand" "Ri")]
UNSPECV_SIMT_ENTER))]
""
{
@@ -1261,12 +1261,20 @@
cfun->machine->simt_stack_align = MAX (UINTVAL (operands[2]),
cfun->machine->simt_stack_align);
cfun->machine->has_simtreg = true;
- emit_insn (gen_omp_simt_enter_insn (operands[0], operands[1], operands[2]));
+ emit_insn (gen_omp_simt_enter (Pmode, operands[0], operands[1], operands[2]));
DONE;
})
-(define_insn "omp_simt_exit"
- [(unspec_volatile [(match_operand 0 "nvptx_register_operand" "R")]
+(define_expand "omp_simt_exit"
+ [(match_operand 0 "nvptx_register_operand" "R")]
+ ""
+{
+ emit_insn (gen_omp_simt_exit (Pmode, operands[0]));
+ DONE;
+})
+
+(define_insn "@omp_simt_exit_<mode>"
+ [(unspec_volatile [(match_operand:P 0 "nvptx_register_operand" "R")]
UNSPECV_SIMT_EXIT)]
""
{
@@ -1513,7 +1521,7 @@
(define_insn "nvptx_red_partition"
[(set (match_operand:DI 0 "nonimmediate_operand" "=R")
- (unspec_volatile [(match_operand:DI 1 "const_int_operand")]
+ (unspec_volatile:DI [(match_operand:DI 1 "const_int_operand")]
UNSPECV_RED_PART))]
""
{
diff --git a/gcc/config/or1k/or1k.c b/gcc/config/or1k/or1k.c
index fc10fcf..54c9e80 100644
--- a/gcc/config/or1k/or1k.c
+++ b/gcc/config/or1k/or1k.c
@@ -2028,10 +2028,11 @@ or1k_expand_atomic_op_qihi (rtx_code code, rtx mem, rtx val,
(*THIS + VCALL_OFFSET) should be additionally added to THIS. */
static void
-or1k_output_mi_thunk (FILE *file, tree /* thunk_fndecl */,
+or1k_output_mi_thunk (FILE *file, tree thunk_fndecl,
HOST_WIDE_INT delta, HOST_WIDE_INT vcall_offset,
tree function)
{
+ const char *fnname = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (thunk_fndecl));
rtx this_rtx, funexp;
rtx_insn *insn;
@@ -2111,13 +2112,14 @@ or1k_output_mi_thunk (FILE *file, tree /* thunk_fndecl */,
/* Run just enough of rest_of_compilation to get the insns emitted.
There's not really enough bulk here to make other passes such as
- instruction scheduling worth while. Note that use_thunk calls
- assemble_start_function and assemble_end_function. */
+ instruction scheduling worth while. */
insn = get_insns ();
shorten_branches (insn);
+ assemble_start_function (thunk_fndecl, fnname);
final_start_function (insn, file, 1);
final (insn, file, 1);
final_end_function ();
+ assemble_end_function (thunk_fndecl, fnname);
reload_completed = 0;
epilogue_completed = 0;
diff --git a/gcc/config/pa/pa-linux.h b/gcc/config/pa/pa-linux.h
index 0d02ebc..23812e4 100644
--- a/gcc/config/pa/pa-linux.h
+++ b/gcc/config/pa/pa-linux.h
@@ -101,7 +101,7 @@ along with GCC; see the file COPYING3. If not see
/* FIXME: Hacked from the <elfos.h> one so that we avoid multiple
labels in a function declaration (since pa.c seems determined to do
- it differently) */
+ it differently). */
#undef ASM_DECLARE_FUNCTION_NAME
#define ASM_DECLARE_FUNCTION_NAME(FILE, NAME, DECL) \
@@ -109,9 +109,14 @@ along with GCC; see the file COPYING3. If not see
{ \
ASM_OUTPUT_TYPE_DIRECTIVE (FILE, NAME, "function"); \
ASM_DECLARE_RESULT (FILE, DECL_RESULT (DECL)); \
+ pa_output_function_label (FILE); \
} \
while (0)
+/* Output function prologue for linux. */
+#undef TARGET_ASM_FUNCTION_PROLOGUE
+#define TARGET_ASM_FUNCTION_PROLOGUE pa_linux_output_function_prologue
+
/* As well as globalizing the label, we need to encode the label
to ensure a plabel is generated in an indirect call. */
diff --git a/gcc/config/pa/pa-protos.h b/gcc/config/pa/pa-protos.h
index 2504ac8..a62eeb7 100644
--- a/gcc/config/pa/pa-protos.h
+++ b/gcc/config/pa/pa-protos.h
@@ -108,6 +108,7 @@ extern void pa_asm_output_aligned_local (FILE *, const char *,
extern void pa_hpux_asm_output_external (FILE *, tree, const char *);
extern HOST_WIDE_INT pa_initial_elimination_offset (int, int);
extern HOST_WIDE_INT pa_function_arg_size (machine_mode, const_tree);
+extern void pa_output_function_label (FILE *);
extern const int pa_magic_milli[];
diff --git a/gcc/config/pa/pa.c b/gcc/config/pa/pa.c
index 532046c..0d00bf6 100644
--- a/gcc/config/pa/pa.c
+++ b/gcc/config/pa/pa.c
@@ -107,7 +107,7 @@ static int pa_can_combine_p (rtx_insn *, rtx_insn *, rtx_insn *, int, rtx,
static bool forward_branch_p (rtx_insn *);
static void compute_zdepwi_operands (unsigned HOST_WIDE_INT, unsigned *);
static void compute_zdepdi_operands (unsigned HOST_WIDE_INT, unsigned *);
-static int compute_movmem_length (rtx_insn *);
+static int compute_cpymem_length (rtx_insn *);
static int compute_clrmem_length (rtx_insn *);
static bool pa_assemble_integer (rtx, unsigned int, int);
static void remove_useless_addtr_insns (int);
@@ -118,7 +118,8 @@ static void set_reg_plus_d (int, int, HOST_WIDE_INT, int);
static rtx pa_function_value (const_tree, const_tree, bool);
static rtx pa_libcall_value (machine_mode, const_rtx);
static bool pa_function_value_regno_p (const unsigned int);
-static void pa_output_function_prologue (FILE *);
+static void pa_output_function_prologue (FILE *) ATTRIBUTE_UNUSED;
+static void pa_linux_output_function_prologue (FILE *) ATTRIBUTE_UNUSED;
static void update_total_code_bytes (unsigned int);
static void pa_output_function_epilogue (FILE *);
static int pa_adjust_cost (rtx_insn *, int, rtx_insn *, int, unsigned int);
@@ -262,8 +263,6 @@ static size_t n_deferred_plabels = 0;
#undef TARGET_ASM_INTEGER
#define TARGET_ASM_INTEGER pa_assemble_integer
-#undef TARGET_ASM_FUNCTION_PROLOGUE
-#define TARGET_ASM_FUNCTION_PROLOGUE pa_output_function_prologue
#undef TARGET_ASM_FUNCTION_EPILOGUE
#define TARGET_ASM_FUNCTION_EPILOGUE pa_output_function_epilogue
@@ -2986,7 +2985,7 @@ pa_output_block_move (rtx *operands, int size_is_constant ATTRIBUTE_UNUSED)
count insns rather than emit them. */
static int
-compute_movmem_length (rtx_insn *insn)
+compute_cpymem_length (rtx_insn *insn)
{
rtx pat = PATTERN (insn);
unsigned int align = INTVAL (XEXP (XVECEXP (pat, 0, 7), 0));
@@ -3842,16 +3841,10 @@ pa_compute_frame_size (poly_int64 size, int *fregs_live)
& ~(PREFERRED_STACK_BOUNDARY / BITS_PER_UNIT - 1));
}
-/* On HP-PA, move-double insns between fpu and cpu need an 8-byte block
- of memory. If any fpu reg is used in the function, we allocate
- such a block here, at the bottom of the frame, just in case it's needed.
+/* Output function label, and associated .PROC and .CALLINFO statements. */
- If this function is a leaf procedure, then we may choose not
- to do a "save" insn. The decision about whether or not
- to do this is made in regclass.c. */
-
-static void
-pa_output_function_prologue (FILE *file)
+void
+pa_output_function_label (FILE *file)
{
/* The function's label and associated .PROC must never be
separated and must be output *after* any profiling declarations
@@ -3897,7 +3890,22 @@ pa_output_function_prologue (FILE *file)
fprintf (file, ",ENTRY_FR=%d", fr_saved + 11);
fputs ("\n\t.ENTRY\n", file);
+}
+/* Output function prologue. */
+
+static void
+pa_output_function_prologue (FILE *file)
+{
+ pa_output_function_label (file);
+ remove_useless_addtr_insns (0);
+}
+
+/* The label is output by ASM_DECLARE_FUNCTION_NAME on linux. */
+
+static void
+pa_linux_output_function_prologue (FILE *file ATTRIBUTE_UNUSED)
+{
remove_useless_addtr_insns (0);
}
@@ -4569,10 +4577,6 @@ output_deferred_profile_counters (void)
void
hppa_profile_hook (int label_no)
{
- /* We use SImode for the address of the function in both 32 and
- 64-bit code to avoid having to provide DImode versions of the
- lcla2 and load_offset_label_address insn patterns. */
- rtx reg = gen_reg_rtx (SImode);
rtx_code_label *label_rtx = gen_label_rtx ();
int reg_parm_stack_space = REG_PARM_STACK_SPACE (NULL_TREE);
rtx arg_bytes, begin_label_rtx, mcount, sym;
@@ -4604,18 +4608,13 @@ hppa_profile_hook (int label_no)
if (!use_mcount_pcrel_call)
{
/* The address of the function is loaded into %r25 with an instruction-
- relative sequence that avoids the use of relocations. The sequence
- is split so that the load_offset_label_address instruction can
- occupy the delay slot of the call to _mcount. */
+ relative sequence that avoids the use of relocations. We use SImode
+ for the address of the function in both 32 and 64-bit code to avoid
+ having to provide DImode versions of the lcla2 pattern. */
if (TARGET_PA_20)
- emit_insn (gen_lcla2 (reg, label_rtx));
+ emit_insn (gen_lcla2 (gen_rtx_REG (SImode, 25), label_rtx));
else
- emit_insn (gen_lcla1 (reg, label_rtx));
-
- emit_insn (gen_load_offset_label_address (gen_rtx_REG (SImode, 25),
- reg,
- begin_label_rtx,
- label_rtx));
+ emit_insn (gen_lcla1 (gen_rtx_REG (SImode, 25), label_rtx));
}
if (!NO_DEFERRED_PROFILE_COUNTERS)
@@ -5061,7 +5060,7 @@ pa_adjust_insn_length (rtx_insn *insn, int length)
&& GET_CODE (XEXP (XVECEXP (pat, 0, 0), 1)) == MEM
&& GET_MODE (XEXP (XVECEXP (pat, 0, 0), 0)) == BLKmode
&& GET_MODE (XEXP (XVECEXP (pat, 0, 0), 1)) == BLKmode)
- length += compute_movmem_length (insn) - 4;
+ length += compute_cpymem_length (insn) - 4;
/* Block clear pattern. */
else if (NONJUMP_INSN_P (insn)
&& GET_CODE (pat) == PARALLEL
@@ -8369,6 +8368,7 @@ pa_asm_output_mi_thunk (FILE *file, tree thunk_fndecl, HOST_WIDE_INT delta,
HOST_WIDE_INT vcall_offset ATTRIBUTE_UNUSED,
tree function)
{
+ const char *fnname = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (thunk_fndecl));
static unsigned int current_thunk_number;
int val_14 = VAL_14_BITS_P (delta);
unsigned int old_last_address = last_address, nbytes = 0;
@@ -8379,6 +8379,7 @@ pa_asm_output_mi_thunk (FILE *file, tree thunk_fndecl, HOST_WIDE_INT delta,
xoperands[1] = XEXP (DECL_RTL (thunk_fndecl), 0);
xoperands[2] = GEN_INT (delta);
+ assemble_start_function (thunk_fndecl, fnname);
final_start_function (emit_barrier (), file, 1);
/* Output the thunk. We know that the function is in the same
@@ -8596,6 +8597,7 @@ pa_asm_output_mi_thunk (FILE *file, tree thunk_fndecl, HOST_WIDE_INT delta,
if (old_last_address > last_address)
last_address = UINT_MAX;
update_total_code_bytes (nbytes);
+ assemble_end_function (thunk_fndecl, fnname);
}
/* Only direct calls to static functions are allowed to be sibling (tail)
@@ -10008,10 +10010,11 @@ pa_can_change_mode_class (machine_mode from, machine_mode to,
/* There is no way to load QImode or HImode values directly from memory
to a FP register. SImode loads to the FP registers are not zero
extended. On the 64-bit target, this conflicts with the definition
- of LOAD_EXTEND_OP. Thus, we can't allow changing between modes with
- different sizes in the floating-point registers. */
+ of LOAD_EXTEND_OP. Thus, we reject all mode changes in the FP registers
+ except for DImode to SImode on the 64-bit target. It is handled by
+ register renaming in pa_print_operand. */
if (MAYBE_FP_REG_CLASS_P (rclass))
- return false;
+ return TARGET_64BIT && from == DImode && to == SImode;
/* TARGET_HARD_REGNO_MODE_OK places modes with sizes larger than a word
in specific sets of registers. Thus, we cannot allow changing
diff --git a/gcc/config/pa/pa.h b/gcc/config/pa/pa.h
index 146ffa2..561efa5 100644
--- a/gcc/config/pa/pa.h
+++ b/gcc/config/pa/pa.h
@@ -1305,3 +1305,6 @@ do { \
/* Target CPU versions for D. */
#define TARGET_D_CPU_VERSIONS pa_d_target_versions
+
+/* Output default function prologue for hpux. */
+#define TARGET_ASM_FUNCTION_PROLOGUE pa_output_function_prologue
diff --git a/gcc/config/pa/pa.md b/gcc/config/pa/pa.md
index 1b4a524..3867a55 100644
--- a/gcc/config/pa/pa.md
+++ b/gcc/config/pa/pa.md
@@ -3162,9 +3162,9 @@
;; The definition of this insn does not really explain what it does,
;; but it should suffice that anything generated as this insn will be
-;; recognized as a movmemsi operation, and that it will not successfully
+;; recognized as a cpymemsi operation, and that it will not successfully
;; combine with anything.
-(define_expand "movmemsi"
+(define_expand "cpymemsi"
[(parallel [(set (match_operand:BLK 0 "" "")
(match_operand:BLK 1 "" ""))
(clobber (match_dup 4))
@@ -3244,7 +3244,7 @@
;; operands 0 and 1 are both equivalent to symbolic MEMs. Thus, we are
;; forced to internally copy operands 0 and 1 to operands 7 and 8,
;; respectively. We then split or peephole optimize after reload.
-(define_insn "movmemsi_prereload"
+(define_insn "cpymemsi_prereload"
[(set (mem:BLK (match_operand:SI 0 "register_operand" "r,r"))
(mem:BLK (match_operand:SI 1 "register_operand" "r,r")))
(clobber (match_operand:SI 2 "register_operand" "=&r,&r")) ;loop cnt/tmp
@@ -3337,7 +3337,7 @@
}
}")
-(define_insn "movmemsi_postreload"
+(define_insn "cpymemsi_postreload"
[(set (mem:BLK (match_operand:SI 0 "register_operand" "+r,r"))
(mem:BLK (match_operand:SI 1 "register_operand" "+r,r")))
(clobber (match_operand:SI 2 "register_operand" "=&r,&r")) ;loop cnt/tmp
@@ -3352,7 +3352,7 @@
"* return pa_output_block_move (operands, !which_alternative);"
[(set_attr "type" "multi,multi")])
-(define_expand "movmemdi"
+(define_expand "cpymemdi"
[(parallel [(set (match_operand:BLK 0 "" "")
(match_operand:BLK 1 "" ""))
(clobber (match_dup 4))
@@ -3432,7 +3432,7 @@
;; operands 0 and 1 are both equivalent to symbolic MEMs. Thus, we are
;; forced to internally copy operands 0 and 1 to operands 7 and 8,
;; respectively. We then split or peephole optimize after reload.
-(define_insn "movmemdi_prereload"
+(define_insn "cpymemdi_prereload"
[(set (mem:BLK (match_operand:DI 0 "register_operand" "r,r"))
(mem:BLK (match_operand:DI 1 "register_operand" "r,r")))
(clobber (match_operand:DI 2 "register_operand" "=&r,&r")) ;loop cnt/tmp
@@ -3525,7 +3525,7 @@
}
}")
-(define_insn "movmemdi_postreload"
+(define_insn "cpymemdi_postreload"
[(set (mem:BLK (match_operand:DI 0 "register_operand" "+r,r"))
(mem:BLK (match_operand:DI 1 "register_operand" "+r,r")))
(clobber (match_operand:DI 2 "register_operand" "=&r,&r")) ;loop cnt/tmp
@@ -5319,8 +5319,8 @@
(define_insn "umulsidi3"
[(set (match_operand:DI 0 "register_operand" "=f")
- (mult:DI (zero_extend:DI (match_operand:SI 1 "nonimmediate_operand" "f"))
- (zero_extend:DI (match_operand:SI 2 "nonimmediate_operand" "f"))))]
+ (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "f"))
+ (zero_extend:DI (match_operand:SI 2 "register_operand" "f"))))]
"TARGET_PA_11 && ! TARGET_DISABLE_FPREGS && ! TARGET_SOFT_FLOAT"
"xmpyu %1,%2,%0"
[(set_attr "type" "fpmuldbl")
@@ -5328,7 +5328,7 @@
(define_insn ""
[(set (match_operand:DI 0 "register_operand" "=f")
- (mult:DI (zero_extend:DI (match_operand:SI 1 "nonimmediate_operand" "f"))
+ (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "f"))
(match_operand:DI 2 "uint32_operand" "f")))]
"TARGET_PA_11 && ! TARGET_DISABLE_FPREGS && ! TARGET_SOFT_FLOAT && !TARGET_64BIT"
"xmpyu %1,%R2,%0"
@@ -5337,7 +5337,7 @@
(define_insn ""
[(set (match_operand:DI 0 "register_operand" "=f")
- (mult:DI (zero_extend:DI (match_operand:SI 1 "nonimmediate_operand" "f"))
+ (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "f"))
(match_operand:DI 2 "uint32_operand" "f")))]
"TARGET_PA_11 && ! TARGET_DISABLE_FPREGS && ! TARGET_SOFT_FLOAT && TARGET_64BIT"
"xmpyu %1,%2R,%0"
@@ -6904,21 +6904,21 @@
rtx stack = operands[2];
rtx fp = operands[3];
- lab = copy_to_reg (lab);
-
emit_clobber (gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (VOIDmode)));
emit_clobber (gen_rtx_MEM (BLKmode, hard_frame_pointer_rtx));
- /* Restore the frame pointer. The virtual_stack_vars_rtx is saved
- instead of the hard_frame_pointer_rtx in the save area. As a
- result, an extra instruction is needed to adjust for the offset
- of the virtual stack variables and the hard frame pointer. */
- if (GET_CODE (fp) != REG)
- fp = force_reg (Pmode, fp);
- emit_move_insn (hard_frame_pointer_rtx, plus_constant (Pmode, fp, -8));
+ lab = copy_to_reg (lab);
+ /* Restore the stack and frame pointers. */
+ fp = copy_to_reg (fp);
emit_stack_restore (SAVE_NONLOCAL, stack);
+ /* Ensure the frame pointer move is not optimized. */
+ emit_insn (gen_blockage ());
+ emit_clobber (hard_frame_pointer_rtx);
+ emit_clobber (frame_pointer_rtx);
+ emit_move_insn (hard_frame_pointer_rtx, fp);
+
emit_use (hard_frame_pointer_rtx);
emit_use (stack_pointer_rtx);
@@ -8695,23 +8695,24 @@ add,l %2,%3,%3\;bv,n %%r0(%3)"
emit_clobber (gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (VOIDmode)));
emit_clobber (gen_rtx_MEM (BLKmode, hard_frame_pointer_rtx));
- /* Restore the frame pointer. The virtual_stack_vars_rtx is saved
- instead of the hard_frame_pointer_rtx in the save area. We need
- to adjust for the offset between these two values. */
- if (GET_CODE (fp) != REG)
- fp = force_reg (Pmode, fp);
- emit_move_insn (hard_frame_pointer_rtx, plus_constant (Pmode, fp, -8));
-
- /* This bit is the same as expand_builtin_longjmp. */
- emit_stack_restore (SAVE_NONLOCAL, stack);
- emit_use (hard_frame_pointer_rtx);
- emit_use (stack_pointer_rtx);
-
/* Load the label we are jumping through into r1 so that we know
where to look for it when we get back to setjmp's function for
restoring the gp. */
emit_move_insn (pv, lab);
+ /* Restore the stack and frame pointers. */
+ fp = copy_to_reg (fp);
+ emit_stack_restore (SAVE_NONLOCAL, stack);
+
+ /* Ensure the frame pointer move is not optimized. */
+ emit_insn (gen_blockage ());
+ emit_clobber (hard_frame_pointer_rtx);
+ emit_clobber (frame_pointer_rtx);
+ emit_move_insn (hard_frame_pointer_rtx, fp);
+
+ emit_use (hard_frame_pointer_rtx);
+ emit_use (stack_pointer_rtx);
+
/* Prevent the insns above from being scheduled into the delay slot
of the interspace jump because the space register could change. */
emit_insn (gen_blockage ());
diff --git a/gcc/config/pdp11/pdp11.md b/gcc/config/pdp11/pdp11.md
index ce781db..be5ddc4 100644
--- a/gcc/config/pdp11/pdp11.md
+++ b/gcc/config/pdp11/pdp11.md
@@ -26,7 +26,7 @@
UNSPECV_BLOCKAGE
UNSPECV_SETD
UNSPECV_SETI
- UNSPECV_MOVMEM
+ UNSPECV_CPYMEM
])
(define_constants
@@ -664,8 +664,8 @@
[(set_attr "length" "2,2,4,4,2")])
;; Expand a block move. We turn this into a move loop.
-(define_expand "movmemhi"
- [(parallel [(unspec_volatile [(const_int 0)] UNSPECV_MOVMEM)
+(define_expand "cpymemhi"
+ [(parallel [(unspec_volatile [(const_int 0)] UNSPECV_CPYMEM)
(match_operand:BLK 0 "general_operand" "=g")
(match_operand:BLK 1 "general_operand" "g")
(match_operand:HI 2 "immediate_operand" "i")
@@ -694,8 +694,8 @@
}")
;; Expand a block move. We turn this into a move loop.
-(define_insn_and_split "movmemhi1"
- [(unspec_volatile [(const_int 0)] UNSPECV_MOVMEM)
+(define_insn_and_split "cpymemhi1"
+ [(unspec_volatile [(const_int 0)] UNSPECV_CPYMEM)
(match_operand:HI 0 "register_operand" "+r")
(match_operand:HI 1 "register_operand" "+r")
(match_operand:HI 2 "register_operand" "+r")
@@ -707,7 +707,7 @@
""
"#"
"reload_completed"
- [(parallel [(unspec_volatile [(const_int 0)] UNSPECV_MOVMEM)
+ [(parallel [(unspec_volatile [(const_int 0)] UNSPECV_CPYMEM)
(match_dup 0)
(match_dup 1)
(match_dup 2)
@@ -719,8 +719,8 @@
(clobber (reg:CC CC_REGNUM))])]
"")
-(define_insn "movmemhi_nocc"
- [(unspec_volatile [(const_int 0)] UNSPECV_MOVMEM)
+(define_insn "cpymemhi_nocc"
+ [(unspec_volatile [(const_int 0)] UNSPECV_CPYMEM)
(match_operand:HI 0 "register_operand" "+r")
(match_operand:HI 1 "register_operand" "+r")
(match_operand:HI 2 "register_operand" "+r")
diff --git a/gcc/config/pru/alu-zext.md b/gcc/config/pru/alu-zext.md
new file mode 100644
index 0000000..80e24d5
--- /dev/null
+++ b/gcc/config/pru/alu-zext.md
@@ -0,0 +1,181 @@
+;; ALU operations with zero extensions
+;;
+;; Copyright (C) 2015-2019 Free Software Foundation, Inc.
+;; Contributed by Dimitar Dimitrov <dimitar@dinux.eu>
+;;
+;; 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/>.
+
+; All PRU ALU instructions automatically zero-extend their source operands,
+; and zero-extract the result into the destination register. This is
+; described in the machine description by defining a separate pattern
+; for each possible combination of zero_extend and mode for input operands.
+;
+; An unfortunate side effect is that quite a few invalid RTL patterns are
+; generated. For example:
+; ... (zero_extend:SI (match_operand:SI ...)) ...
+; These patterns are harmless since no pass should generate such RTL. This
+; shortcut allows us to keep small and concise machine description patterns.
+
+
+(define_subst_attr "alu2_zext" "alu2_zext_subst" "_z" "_noz")
+
+(define_subst_attr "alu3_zext_op1" "alu3_zext_op1_subst" "_z1" "_noz1")
+(define_subst_attr "alu3_zext_op2" "alu3_zext_op2_subst" "_z2" "_noz2")
+(define_subst_attr "alu3_zext" "alu3_zext_subst" "_z" "_noz")
+
+(define_subst_attr "bitalu_zext" "bitalu_zext_subst" "_z" "_noz")
+
+(define_code_iterator ALUOP3 [plus minus and ior xor umin umax ashift lshiftrt])
+(define_code_iterator ALUOP2 [neg not])
+
+;; Arithmetic Operations
+
+(define_insn "add_impl<EQD:mode><EQS0:mode><EQS1:mode>_<alu3_zext><alu3_zext_op1><alu3_zext_op2>"
+ [(set (match_operand:EQD 0 "register_operand" "=r,r,r")
+ (plus:EQD
+ (zero_extend:EQD
+ (match_operand:EQS0 1 "register_operand" "%r,r,r"))
+ (zero_extend:EQD
+ (match_operand:EQS1 2 "nonmemory_operand" "r,<EQS1:ubyte_constr>,M"))))]
+ ""
+ "@
+ add\\t%0, %1, %2
+ add\\t%0, %1, %u2
+ sub\\t%0, %1, %n2"
+ [(set_attr "type" "alu")])
+
+(define_insn "sub_impl<EQD:mode><EQS0:mode><EQS1:mode>_<alu3_zext><alu3_zext_op1><alu3_zext_op2>"
+ [(set (match_operand:EQD 0 "register_operand" "=r,r")
+ (minus:EQD
+ (zero_extend:EQD
+ (match_operand:EQS0 1 "reg_or_ubyte_operand" "r,<EQS0:ubyte_constr>"))
+ (zero_extend:EQD
+ (match_operand:EQS1 2 "register_operand" "r,r"))))]
+ ""
+ "@
+ sub\\t%0, %1, %2
+ rsb\\t%0, %2, %u1"
+ [(set_attr "type" "alu")])
+
+
+(define_insn "neg_impl<EQD:mode><EQS0:mode>_<alu2_zext>"
+ [(set (match_operand:EQD 0 "register_operand" "=r")
+ (neg:EQD
+ (zero_extend:EQD (match_operand:EQS0 1 "register_operand" "r"))))]
+ ""
+ "rsb\\t%0, %1, 0"
+ [(set_attr "type" "alu")])
+
+
+(define_insn "one_cmpl_impl<EQD:mode><EQS0:mode>_<alu2_zext>"
+ [(set (match_operand:EQD 0 "register_operand" "=r")
+ (not:EQD
+ (zero_extend:EQD (match_operand:EQS0 1 "register_operand" "r"))))]
+ ""
+ "not\\t%0, %1"
+ [(set_attr "type" "alu")])
+
+; Specialized IOR/AND patterns for matching setbit/clearbit instructions.
+;
+; TODO - allow clrbit and setbit to support (1 << REG) constructs
+
+(define_insn "clearbit_<EQD:mode><EQS0:mode>_<bitalu_zext>"
+ [(set (match_operand:EQD 0 "register_operand" "=r")
+ (and:EQD
+ (zero_extend:EQD
+ (match_operand:EQS0 1 "register_operand" "r"))
+ (match_operand:EQD 2 "single_zero_operand" "n")))]
+ ""
+ "clr\\t%0, %1, %V2"
+ [(set_attr "type" "alu")])
+
+(define_insn "setbit_<EQD:mode><EQS0:mode>_<bitalu_zext>"
+ [(set (match_operand:EQD 0 "register_operand" "=r")
+ (ior:EQD
+ (zero_extend:EQD
+ (match_operand:EQS0 1 "register_operand" "r"))
+ (match_operand:EQD 2 "single_one_operand" "n")))]
+ ""
+ "set\\t%0, %1, %T2"
+ [(set_attr "type" "alu")])
+
+; Regular ALU ops
+(define_insn "<code>_impl<EQD:mode><EQS0:mode><EQS1:mode>_<alu3_zext><alu3_zext_op1><alu3_zext_op2>"
+ [(set (match_operand:EQD 0 "register_operand" "=r")
+ (LOGICAL:EQD
+ (zero_extend:EQD
+ (match_operand:EQS0 1 "register_operand" "%r"))
+ (zero_extend:EQD
+ (match_operand:EQS1 2 "reg_or_ubyte_operand" "r<EQS1:ubyte_constr>"))))]
+ ""
+ "<logical_asm>\\t%0, %1, %u2"
+ [(set_attr "type" "alu")])
+
+; Shift ALU ops
+(define_insn "<shift_op>_impl<EQD:mode><EQS0:mode><EQS1:mode>_<alu3_zext><alu3_zext_op1><alu3_zext_op2>"
+ [(set (match_operand:EQD 0 "register_operand" "=r")
+ (SHIFT:EQD
+ (zero_extend:EQD (match_operand:EQS0 1 "register_operand" "r"))
+ (zero_extend:EQD (match_operand:EQS1 2 "shift_operand" "rL"))))]
+ ""
+ "<shift_asm>\\t%0, %1, %2"
+ [(set_attr "type" "alu")])
+
+;; Substitutions
+
+(define_subst "alu2_zext_subst"
+ [(set (match_operand:EQD 0)
+ (ALUOP2:EQD (zero_extend:EQD (match_operand:EQD 1))))]
+ ""
+ [(set (match_dup 0)
+ (ALUOP2:EQD (match_dup 1)))])
+
+(define_subst "bitalu_zext_subst"
+ [(set (match_operand:EQD 0)
+ (ALUOP3:EQD (zero_extend:EQD (match_operand:EQD 1))
+ (match_operand:EQD 2)))]
+ ""
+ [(set (match_dup 0)
+ (ALUOP3:EQD (match_dup 1)
+ (match_dup 2)))])
+
+(define_subst "alu3_zext_subst"
+ [(set (match_operand:EQD 0)
+ (ALUOP3:EQD (zero_extend:EQD (match_operand:EQD 1))
+ (zero_extend:EQD (match_operand:EQD 2))))]
+ ""
+ [(set (match_dup 0)
+ (ALUOP3:EQD (match_dup 1)
+ (match_dup 2)))])
+
+(define_subst "alu3_zext_op1_subst"
+ [(set (match_operand:EQD 0)
+ (ALUOP3:EQD (zero_extend:EQD (match_operand:EQD 1))
+ (zero_extend:EQD (match_operand:EQS1 2))))]
+ ""
+ [(set (match_dup 0)
+ (ALUOP3:EQD (match_dup 1)
+ (zero_extend:EQD (match_dup 2))))])
+
+(define_subst "alu3_zext_op2_subst"
+ [(set (match_operand:EQD 0)
+ (ALUOP3:EQD (zero_extend:EQD (match_operand:EQS0 1))
+ (zero_extend:EQD (match_operand:EQD 2))))]
+ ""
+ [(set (match_dup 0)
+ (ALUOP3:EQD (zero_extend:EQD (match_dup 1))
+ (match_dup 2)))])
diff --git a/gcc/config/pru/constraints.md b/gcc/config/pru/constraints.md
new file mode 100644
index 0000000..c8856d1
--- /dev/null
+++ b/gcc/config/pru/constraints.md
@@ -0,0 +1,108 @@
+;; Constraint definitions for TI PRU.
+;; Copyright (C) 2014-2019 Free Software Foundation, Inc.
+;; Contributed by Dimitar Dimitrov <dimitar@dinux.eu>
+;;
+;; 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/>.
+
+;; We use the following constraint letters for constants:
+;;
+;; I: 0 to 255.
+;; J: 0 to 65535.
+;; L: 0 to 31 (for shift counts).
+;; T: Text segment label. Needed to know when to select %pmem relocation.
+;; Z: Constant integer zero.
+;;
+;; We use the following built-in register classes:
+;;
+;; r: General purpose register (r0..r31).
+;; m: Memory operand.
+;;
+;; The following constraints are intended for internal use only:
+;; Rmd0, Rms0, Rms1: Registers for MUL instruction operands.
+;; Rsib: Jump address register suitable for sibling calls.
+;; M: -255 to 0 (for converting ADD to SUB with suitable UBYTE OP2).
+;; N: -32768 to 32767 (16-bit signed integer).
+;; O: -128 to 127 (8-bit signed integer).
+;; P: 1
+
+;; Register constraints.
+
+(define_register_constraint "Rsib" "SIB_REGS"
+ "@internal
+ A register suitable for an indirect sibcall.")
+
+(define_register_constraint "Rmd0" "MULDST_REGS"
+ "@internal
+ The multiply destination register.")
+
+(define_register_constraint "Rms0" "MULSRC0_REGS"
+ "@internal
+ The multiply source 0 register.")
+
+(define_register_constraint "Rms1" "MULSRC1_REGS"
+ "@internal
+ The multiply source 1 register.")
+
+;; Integer constraints.
+
+(define_constraint "I"
+ "An unsigned 8-bit constant."
+ (and (match_code "const_int")
+ (match_test "UBYTE_INT (ival)")))
+
+(define_constraint "J"
+ "An unsigned 16-bit constant."
+ (and (match_code "const_int")
+ (match_test "UHWORD_INT (ival)")))
+
+(define_constraint "L"
+ "An unsigned 5-bit constant (for shift counts)."
+ (and (match_code "const_int")
+ (match_test "ival >= 0 && ival <= 31")))
+
+(define_constraint "M"
+ "@internal
+ A constant in the range [-255, 0]."
+ (and (match_code "const_int")
+ (match_test "UBYTE_INT (-ival)")))
+
+(define_constraint "N"
+ "@internal
+ A constant in the range [-32768, 32767]."
+ (and (match_code "const_int")
+ (match_test "SHWORD_INT (ival)")))
+
+(define_constraint "O"
+ "@internal
+ A constant in the range [-128, 127]."
+ (and (match_code "const_int")
+ (match_test "SBYTE_INT (ival)")))
+
+(define_constraint "P"
+ "@internal
+ A constant 1."
+ (and (match_code "const_int")
+ (match_test "ival == 1")))
+
+(define_constraint "T"
+ "A text segment (program memory) constant label."
+ (match_test "text_segment_operand (op, VOIDmode)"))
+
+(define_constraint "Z"
+ "An integer constant zero."
+ (and (match_code "const_int")
+ (match_test "ival == 0")))
diff --git a/gcc/config/pru/predicates.md b/gcc/config/pru/predicates.md
new file mode 100644
index 0000000..568d6f3
--- /dev/null
+++ b/gcc/config/pru/predicates.md
@@ -0,0 +1,287 @@
+;; Predicate definitions for TI PRU.
+;; Copyright (C) 2014-2019 Free Software Foundation, Inc.
+;; Contributed by Dimitar Dimitrov <dimitar@dinux.eu>
+;;
+;; 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_predicate "const_1_operand"
+ (and (match_code "const_int")
+ (match_test "INTVAL (op) == 1")))
+
+; Note: Always pass a valid mode!
+(define_predicate "const_ubyte_operand"
+ (match_code "const_int")
+{
+ gcc_assert (mode != VOIDmode);
+ return IN_RANGE (INTVAL (op) & GET_MODE_MASK (mode), 0, 0xff);
+})
+
+(define_predicate "const_uhword_operand"
+ (match_code "const_int")
+{
+ gcc_assert (mode != VOIDmode);
+ return IN_RANGE (INTVAL (op) & GET_MODE_MASK (mode), 0, 0xffff);
+})
+
+; TRUE for comparisons we support.
+(define_predicate "pru_cmp_operator"
+ (match_code "eq,ne,leu,ltu,geu,gtu"))
+
+; TRUE for signed comparisons that need special handling for PRU.
+(define_predicate "pru_signed_cmp_operator"
+ (match_code "ge,gt,le,lt"))
+
+;; FP Comparisons handled by pru_expand_pru_compare.
+(define_predicate "pru_fp_comparison_operator"
+ (match_code "eq,ne,lt,gt,le,ge"))
+
+;; Return true if OP is a constant that contains only one 1 in its
+;; binary representation.
+(define_predicate "single_one_operand"
+ (and (match_code "const_int")
+ (match_test "exact_log2 (INTVAL (op) & GET_MODE_MASK (mode)) >= 0")))
+
+;; Return true if OP is a constant that contains only one 0 in its
+;; binary representation.
+(define_predicate "single_zero_operand"
+ (and (match_code "const_int")
+ (match_test "exact_log2 (~INTVAL (op) & GET_MODE_MASK (mode)) >= 0")))
+
+(define_predicate "pru_muldst_operand"
+ (match_code "subreg,reg")
+{
+ if (register_operand (op, mode))
+ {
+ int regno;
+
+ if (REG_P (op))
+ regno = REGNO (op);
+ else if (GET_CODE (op) == SUBREG && REG_P (SUBREG_REG (op)))
+ regno = REGNO (SUBREG_REG (op));
+ else
+ return 0;
+
+ return REGNO_REG_CLASS (regno) == MULDST_REGS
+ || regno >= FIRST_PSEUDO_REGISTER;
+ }
+ return 0;
+})
+
+(define_predicate "pru_mulsrc0_operand"
+ (match_code "subreg,reg")
+{
+ if (register_operand (op, mode))
+ {
+ int regno;
+
+ if (REG_P (op))
+ regno = REGNO (op);
+ else if (GET_CODE (op) == SUBREG && REG_P (SUBREG_REG (op)))
+ regno = REGNO (SUBREG_REG (op));
+ else
+ return 0;
+
+ return REGNO_REG_CLASS (regno) == MULSRC0_REGNUM
+ || regno >= FIRST_PSEUDO_REGISTER;
+ }
+ return 0;
+})
+
+(define_predicate "pru_mulsrc1_operand"
+ (match_code "subreg,reg")
+{
+ if (register_operand (op, mode))
+ {
+ int regno;
+
+ if (REG_P (op))
+ regno = REGNO (op);
+ else if (GET_CODE (op) == SUBREG && REG_P (SUBREG_REG (op)))
+ regno = REGNO (SUBREG_REG (op));
+ else
+ return 0;
+
+ return REGNO_REG_CLASS (regno) == MULSRC1_REGNUM
+ || regno >= FIRST_PSEUDO_REGISTER;
+ }
+ return 0;
+})
+
+(define_predicate "reg_or_const_int_operand"
+ (ior (match_operand 0 "const_int_operand")
+ (match_operand 0 "register_operand")))
+
+(define_predicate "reg_or_ubyte_operand"
+ (ior (match_operand 0 "const_ubyte_operand")
+ (match_operand 0 "register_operand")))
+
+(define_predicate "reg_or_const_1_operand"
+ (ior (match_operand 0 "const_1_operand")
+ (match_operand 0 "register_operand")))
+
+(define_predicate "const_shift_operand"
+ (and (match_code "const_int")
+ (match_test "SHIFT_INT (INTVAL (op))")))
+
+(define_predicate "shift_operand"
+ (ior (match_operand 0 "const_shift_operand")
+ (match_operand 0 "register_operand")))
+
+(define_predicate "ctable_addr_operand"
+ (and (match_code "const_int")
+ (match_test "pru_get_ctable_base_index (INTVAL (op)) >= 0")))
+
+(define_predicate "ctable_base_operand"
+ (and (match_code "const_int")
+ (match_test "pru_get_ctable_exact_base_index (INTVAL (op)) >= 0")))
+
+;; Ideally we should enforce a restriction to all text labels to fit in
+;; 16bits, as required by the PRU ISA. But for the time being we'll rely on
+;; binutils to catch text segment overflows.
+(define_predicate "call_operand"
+ (ior (match_operand 0 "immediate_operand")
+ (match_operand 0 "register_operand")))
+
+;; Return true if OP is a text segment reference.
+;; This is needed for program memory address expressions. Borrowed from AVR.
+(define_predicate "text_segment_operand"
+ (match_code "code_label,label_ref,symbol_ref,plus,minus")
+{
+ poly_int64 offset;
+ rtx base = strip_offset (op, &offset);
+
+ switch (GET_CODE (base))
+ {
+ case CODE_LABEL:
+ /* Why AVR lists this as a valid option? Let's catch it. */
+ gcc_unreachable ();
+ return false;
+ case LABEL_REF:
+ return true;
+ case SYMBOL_REF:
+ return SYMBOL_REF_FUNCTION_P (base);
+ case PLUS:
+ case MINUS:
+ /* Handle constructs like (&&label1 - &&label2). See pr70460.c. */
+ return text_segment_operand (XEXP (op, 0), VOIDmode);
+ default:
+ return false;
+ }
+})
+
+;; Return true if OP is a load multiple operation. It is known to be a
+;; PARALLEL and the first section will be tested.
+
+(define_special_predicate "load_multiple_operation"
+ (match_code "parallel")
+{
+ machine_mode elt_mode;
+ int count = XVECLEN (op, 0);
+ unsigned int dest_regno;
+ rtx src_addr, base_reg;
+ poly_int64 base_offs;
+ int i;
+
+ /* Perform a quick check so we don't blow up below. */
+ if (GET_CODE (XVECEXP (op, 0, 0)) != SET
+ || GET_CODE (SET_DEST (XVECEXP (op, 0, 0))) != REG
+ || GET_CODE (SET_SRC (XVECEXP (op, 0, 0))) != MEM)
+ return false;
+
+ dest_regno = REGNO (SET_DEST (XVECEXP (op, 0, 0)));
+ src_addr = XEXP (SET_SRC (XVECEXP (op, 0, 0)), 0);
+ elt_mode = GET_MODE (SET_DEST (XVECEXP (op, 0, 0)));
+
+ base_reg = strip_offset (src_addr, &base_offs);
+ if (GET_CODE (base_reg) != REG)
+ return false;
+
+ for (i = 1; i < count; i++)
+ {
+ rtx elt_reg;
+ poly_int64 elt_offs;
+ rtx elt = XVECEXP (op, 0, i);
+
+ if (GET_CODE (elt) != SET
+ || GET_CODE (SET_DEST (elt)) != REG
+ || GET_MODE (SET_DEST (elt)) != elt_mode
+ || REGNO (SET_DEST (elt)) != dest_regno + i * GET_MODE_SIZE (elt_mode)
+ || GET_CODE (SET_SRC (elt)) != MEM
+ || GET_MODE (SET_SRC (elt)) != elt_mode)
+ return false;
+
+ elt_reg = strip_offset (XEXP (SET_SRC (elt), 0), &elt_offs);
+
+ if (GET_CODE (elt_reg) != REG
+ || ! rtx_equal_p (elt_reg, base_reg)
+ || elt_offs != base_offs + i * GET_MODE_SIZE (elt_mode))
+ return false;
+ }
+
+ return true;
+})
+
+;; Return true if OP is a store multiple operation. It is known to be a
+;; PARALLEL and the first section will be tested.
+
+(define_special_predicate "store_multiple_operation"
+ (match_code "parallel")
+{
+ machine_mode elt_mode;
+ int count = XVECLEN (op, 0);
+ unsigned int src_regno;
+ rtx dest_addr, base_reg;
+ poly_int64 base_offs;
+ int i;
+
+ /* Perform a quick check so we don't blow up below. */
+ if (GET_CODE (XVECEXP (op, 0, 0)) != SET
+ || GET_CODE (SET_DEST (XVECEXP (op, 0, 0))) != MEM
+ || GET_CODE (SET_SRC (XVECEXP (op, 0, 0))) != REG)
+ return false;
+
+ src_regno = REGNO (SET_SRC (XVECEXP (op, 0, 0)));
+ dest_addr = XEXP (SET_DEST (XVECEXP (op, 0, 0)), 0);
+ elt_mode = GET_MODE (SET_SRC (XVECEXP (op, 0, 0)));
+
+ base_reg = strip_offset (dest_addr, &base_offs);
+ if (GET_CODE (base_reg) != REG)
+ return false;
+
+ for (i = 1; i < count; i++)
+ {
+ rtx elt_reg;
+ poly_int64 elt_offs;
+ rtx elt = XVECEXP (op, 0, i);
+
+ if (GET_CODE (elt) != SET
+ || GET_CODE (SET_SRC (elt)) != REG
+ || GET_MODE (SET_SRC (elt)) != elt_mode
+ || REGNO (SET_SRC (elt)) != src_regno + i * GET_MODE_SIZE (elt_mode)
+ || GET_CODE (SET_DEST (elt)) != MEM
+ || GET_MODE (SET_DEST (elt)) != elt_mode)
+ return false;
+
+ elt_reg = strip_offset (XEXP (SET_DEST (elt), 0), &elt_offs);
+
+ if (GET_CODE (elt_reg) != REG
+ || ! rtx_equal_p (elt_reg, base_reg)
+ || elt_offs != base_offs + i * GET_MODE_SIZE (elt_mode))
+ return false;
+ }
+ return true;
+})
diff --git a/gcc/config/pru/pru-opts.h b/gcc/config/pru/pru-opts.h
new file mode 100644
index 0000000..70bc147
--- /dev/null
+++ b/gcc/config/pru/pru-opts.h
@@ -0,0 +1,31 @@
+/* Copyright (C) 2017-2019 Free Software Foundation, Inc.
+ Contributed by Dimitar Dimitrov <dimitar@dinux.eu>
+
+ 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/>. */
+
+/* Definitions for option handling for PRU. */
+
+#ifndef GCC_PRU_OPTS_H
+#define GCC_PRU_OPTS_H
+
+/* ABI variant for code generation. */
+enum pru_abi {
+ PRU_ABI_GNU,
+ PRU_ABI_TI
+};
+
+#endif
diff --git a/gcc/config/pru/pru-passes.c b/gcc/config/pru/pru-passes.c
new file mode 100644
index 0000000..8efba54
--- /dev/null
+++ b/gcc/config/pru/pru-passes.c
@@ -0,0 +1,228 @@
+/* PRU target specific passes
+ Copyright (C) 2017-2019 Free Software Foundation, Inc.
+ Dimitar Dimitrov <dimitar@dinux.eu>
+
+ 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 IN_TARGET_CODE 1
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "backend.h"
+#include "context.h"
+#include "tm.h"
+#include "alias.h"
+#include "symtab.h"
+#include "tree.h"
+#include "diagnostic-core.h"
+#include "function.h"
+#include "gimple.h"
+#include "gimple-iterator.h"
+#include "gimple-walk.h"
+#include "gimple-expr.h"
+#include "tree-pass.h"
+
+#include "pru-protos.h"
+
+namespace {
+
+/* Scan the tree to ensure that the compiled code by GCC
+ conforms to the TI ABI specification. If GCC cannot
+ output a conforming code, raise an error. */
+const pass_data pass_data_tiabi_check =
+{
+ GIMPLE_PASS, /* type */
+ "*tiabi_check", /* name */
+ OPTGROUP_NONE, /* optinfo_flags */
+ TV_NONE, /* tv_id */
+ PROP_gimple_any, /* properties_required */
+ 0, /* properties_provided */
+ 0, /* properties_destroyed */
+ 0, /* todo_flags_start */
+ 0, /* todo_flags_finish */
+};
+
+/* Implementation class for the TI ABI compliance-check pass. */
+class pass_tiabi_check : public gimple_opt_pass
+{
+public:
+ pass_tiabi_check (gcc::context *ctxt)
+ : gimple_opt_pass (pass_data_tiabi_check, ctxt)
+ {}
+
+ /* opt_pass methods: */
+ virtual unsigned int execute (function *);
+
+ virtual bool gate (function *fun ATTRIBUTE_UNUSED)
+ {
+ return pru_current_abi == PRU_ABI_TI;
+ }
+
+}; // class pass_tiabi_check
+
+/* Return 1 if type TYPE is a pointer to function type or a
+ structure having a pointer to function type as one of its fields.
+ Otherwise return 0. */
+static bool
+chkp_type_has_function_pointer (const_tree type)
+{
+ bool res = false;
+
+ if (POINTER_TYPE_P (type) && FUNC_OR_METHOD_TYPE_P (TREE_TYPE (type)))
+ res = true;
+ else if (RECORD_OR_UNION_TYPE_P (type))
+ {
+ tree field;
+
+ for (field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field))
+ if (TREE_CODE (field) == FIELD_DECL)
+ res = res || chkp_type_has_function_pointer (TREE_TYPE (field));
+ }
+ else if (TREE_CODE (type) == ARRAY_TYPE)
+ res = chkp_type_has_function_pointer (TREE_TYPE (type));
+
+ return res;
+}
+
+/* Check the function declaration FNTYPE for TI ABI compatibility. */
+static void
+chk_function_decl (const_tree fntype, location_t call_location)
+{
+ /* GCC does not check if the RETURN VALUE pointer is NULL,
+ so do not allow GCC functions with large return values. */
+ if (!VOID_TYPE_P (TREE_TYPE (fntype))
+ && pru_return_in_memory (TREE_TYPE (fntype), fntype))
+ error_at (call_location,
+ "large return values not supported with %<-mabi=ti%> option");
+
+ /* Check this function's arguments. */
+ for (tree p = TYPE_ARG_TYPES (fntype); p; p = TREE_CHAIN (p))
+ {
+ tree arg_type = TREE_VALUE (p);
+ if (chkp_type_has_function_pointer (arg_type))
+ error_at (call_location,
+ "function pointers not supported with %<-mabi=ti%> option");
+ }
+}
+
+/* Callback for walk_gimple_seq that checks TP tree for TI ABI compliance. */
+static tree
+check_op_callback (tree *tp, int *walk_subtrees, void *data)
+{
+ struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
+
+ if (RECORD_OR_UNION_TYPE_P (*tp) || TREE_CODE (*tp) == ENUMERAL_TYPE)
+ {
+ /* Forward declarations have NULL tree type. Skip them. */
+ if (TREE_TYPE (*tp) == NULL)
+ return NULL;
+ }
+
+ /* TODO - why C++ leaves INTEGER_TYPE forward declarations around? */
+ if (TREE_TYPE (*tp) == NULL)
+ return NULL;
+
+ const tree type = TREE_TYPE (*tp);
+
+ /* Direct function calls are allowed, obviously. */
+ gcall *call = dyn_cast <gcall *> (gsi_stmt (wi->gsi));
+ if (call
+ && tp == gimple_call_fn_ptr (call)
+ && gimple_call_fndecl (call))
+ return NULL;
+
+ switch (TREE_CODE (type))
+ {
+ case FUNCTION_TYPE:
+ case METHOD_TYPE:
+ {
+ /* Note: Do not enforce a small return value. It is safe to
+ call any TI ABI function from GCC, since GCC will
+ never pass NULL. */
+
+ /* Check arguments for function pointers. */
+ for (tree p = TYPE_ARG_TYPES (type); p; p = TREE_CHAIN (p))
+ {
+ tree arg_type = TREE_VALUE (p);
+ if (chkp_type_has_function_pointer (arg_type))
+ error_at (gimple_location (wi->stmt), "function pointers "
+ "not supported with %<-mabi=ti%> option");
+ }
+ break;
+ }
+ case RECORD_TYPE:
+ case UNION_TYPE:
+ case QUAL_UNION_TYPE:
+ case POINTER_TYPE:
+ {
+ if (chkp_type_has_function_pointer (type))
+ {
+ error_at (gimple_location (wi->stmt),
+ "function pointers not supported with "
+ "%<-mabi=ti%> option");
+ *walk_subtrees = false;
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ return NULL;
+}
+
+/* Pass implementation. */
+unsigned
+pass_tiabi_check::execute (function *fun)
+{
+ struct walk_stmt_info wi;
+ const_tree fntype = TREE_TYPE (fun->decl);
+
+ gimple_seq body = gimple_body (current_function_decl);
+
+ memset (&wi, 0, sizeof (wi));
+ wi.info = NULL;
+ wi.want_locations = true;
+
+ /* Check the function body. */
+ walk_gimple_seq (body, NULL, check_op_callback, &wi);
+
+ /* Check the function declaration. */
+ chk_function_decl (fntype, fun->function_start_locus);
+
+ return 0;
+}
+
+} // anon namespace
+
+gimple_opt_pass *
+make_pass_tiabi_check (gcc::context *ctxt)
+{
+ return new pass_tiabi_check (ctxt);
+}
+
+/* Register as early as possible. */
+void
+pru_register_abicheck_pass (void)
+{
+ opt_pass *tiabi_check = make_pass_tiabi_check (g);
+ struct register_pass_info tiabi_check_info
+ = { tiabi_check, "*warn_unused_result",
+ 1, PASS_POS_INSERT_AFTER
+ };
+ register_pass (&tiabi_check_info);
+}
diff --git a/gcc/config/pru/pru-pragma.c b/gcc/config/pru/pru-pragma.c
new file mode 100644
index 0000000..8680011
--- /dev/null
+++ b/gcc/config/pru/pru-pragma.c
@@ -0,0 +1,86 @@
+/* PRU target specific pragmas
+ Copyright (C) 2015-2019 Free Software Foundation, Inc.
+ Contributed by Dimitar Dimitrov <dimitar@dinux.eu>
+
+ 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 IN_TARGET_CODE 1
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "tm.h"
+#include "alias.h"
+#include "symtab.h"
+#include "tree.h"
+#include "c-family/c-pragma.h"
+#include "c-family/c-common.h"
+#include "diagnostic-core.h"
+#include "cpplib.h"
+#include "pru-protos.h"
+
+
+/* Implements the "pragma CTABLE_ENTRY" pragma. This pragma takes a
+ CTABLE index and an address, and instructs the compiler that
+ LBCO/SBCO can be used on that base address.
+
+ WARNING: Only immediate constant addresses are currently supported. */
+static void
+pru_pragma_ctable_entry (cpp_reader * reader ATTRIBUTE_UNUSED)
+{
+ tree ctable_index, base_addr;
+ enum cpp_ttype type;
+
+ type = pragma_lex (&ctable_index);
+ if (type == CPP_NUMBER && tree_fits_uhwi_p (ctable_index))
+ {
+ type = pragma_lex (&base_addr);
+ if (type == CPP_NUMBER && tree_fits_uhwi_p (base_addr))
+ {
+ unsigned HOST_WIDE_INT i = tree_to_uhwi (ctable_index);
+ unsigned HOST_WIDE_INT base = tree_to_uhwi (base_addr);
+
+ type = pragma_lex (&base_addr);
+ if (type != CPP_EOF)
+ error ("junk at end of %<#pragma CTABLE_ENTRY%>");
+ else if (i >= ARRAY_SIZE (pru_ctable))
+ error ("%<CTABLE_ENTRY%> index %" HOST_WIDE_INT_PRINT "d"
+ " is not valid", i);
+ else if (pru_ctable[i].valid && pru_ctable[i].base != base)
+ error ("redefinition of %<CTABLE_ENTRY "
+ "%" HOST_WIDE_INT_PRINT "d%>", i);
+ else
+ {
+ if (base & 0xff)
+ warning (0, "%<CTABLE_ENTRY%> base address is not "
+ "a multiple of 256");
+ pru_ctable[i].base = base;
+ pru_ctable[i].valid = true;
+ }
+ return;
+ }
+ }
+ error ("malformed %<#pragma CTABLE_ENTRY%> variable address");
+}
+
+/* Implements REGISTER_TARGET_PRAGMAS. */
+void
+pru_register_pragmas (void)
+{
+ c_register_pragma (NULL, "ctable_entry", pru_pragma_ctable_entry);
+ c_register_pragma (NULL, "CTABLE_ENTRY", pru_pragma_ctable_entry);
+}
diff --git a/gcc/config/pru/pru-protos.h b/gcc/config/pru/pru-protos.h
new file mode 100644
index 0000000..0090521
--- /dev/null
+++ b/gcc/config/pru/pru-protos.h
@@ -0,0 +1,72 @@
+/* Subroutine declarations for TI PRU target support.
+ Copyright (C) 2014-2019 Free Software Foundation, Inc.
+ Contributed by Dimitar Dimitrov <dimitar@dinux.eu>
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+ License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GCC; see the file COPYING3. If not see
+ <http://www.gnu.org/licenses/>. */
+
+#ifndef GCC_PRU_PROTOS_H
+#define GCC_PRU_PROTOS_H
+
+struct pru_ctable_entry {
+ bool valid;
+ unsigned HOST_WIDE_INT base;
+};
+
+extern struct pru_ctable_entry pru_ctable[32];
+
+extern int pru_initial_elimination_offset (int, int);
+extern int pru_can_use_return_insn (void);
+extern void pru_expand_prologue (void);
+extern void pru_expand_epilogue (bool);
+extern void pru_function_profiler (FILE *, int);
+
+void pru_register_pragmas (void);
+
+#ifdef RTX_CODE
+extern rtx pru_get_return_address (int);
+extern int pru_hard_regno_rename_ok (unsigned int, unsigned int);
+
+extern const char *pru_output_sign_extend (rtx *);
+extern const char *pru_output_signed_cbranch (rtx *, bool);
+extern const char *pru_output_signed_cbranch_ubyteop2 (rtx *, bool);
+extern const char *pru_output_signed_cbranch_zeroop2 (rtx *, bool);
+
+extern rtx pru_expand_fp_compare (rtx comparison, machine_mode mode);
+
+extern void pru_emit_doloop (rtx *, int);
+
+extern bool pru_regno_ok_for_base_p (int, bool);
+
+static inline bool
+pru_regno_ok_for_index_p (int regno, bool strict_p)
+{
+ /* Selection logic is the same - PRU instructions are quite orthogonal. */
+ return pru_regno_ok_for_base_p (regno, strict_p);
+}
+
+extern int pru_get_ctable_exact_base_index (unsigned HOST_WIDE_INT caddr);
+extern int pru_get_ctable_base_index (unsigned HOST_WIDE_INT caddr);
+extern int pru_get_ctable_base_offset (unsigned HOST_WIDE_INT caddr);
+
+extern void pru_register_abicheck_pass (void);
+#endif /* RTX_CODE */
+
+#ifdef TREE_CODE
+extern bool pru_return_in_memory (const_tree type, const_tree fntype);
+#endif /* TREE_CODE */
+
+#endif /* GCC_PRU_PROTOS_H */
diff --git a/gcc/config/pru/pru.c b/gcc/config/pru/pru.c
new file mode 100644
index 0000000..c764694
--- /dev/null
+++ b/gcc/config/pru/pru.c
@@ -0,0 +1,3036 @@
+/* Target machine subroutines for TI PRU.
+ Copyright (C) 2014-2019 Free Software Foundation, Inc.
+ Dimitar Dimitrov <dimitar@dinux.eu>
+
+ 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 IN_TARGET_CODE 1
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "backend.h"
+#include "target.h"
+#include "rtl.h"
+#include "tree.h"
+#include "stringpool.h"
+#include "attribs.h"
+#include "df.h"
+#include "memmodel.h"
+#include "tm_p.h"
+#include "optabs.h"
+#include "regs.h"
+#include "emit-rtl.h"
+#include "recog.h"
+#include "diagnostic-core.h"
+#include "output.h"
+#include "insn-attr.h"
+#include "flags.h"
+#include "explow.h"
+#include "calls.h"
+#include "varasm.h"
+#include "expr.h"
+#include "toplev.h"
+#include "langhooks.h"
+#include "cfgrtl.h"
+#include "stor-layout.h"
+#include "dumpfile.h"
+#include "builtins.h"
+#include "pru-protos.h"
+
+/* This file should be included last. */
+#include "target-def.h"
+
+#define INIT_ARRAY_ENTRY_BYTES 2
+
+/* Global PRU CTABLE entries, filled in by pragmas, and used for fast
+ addressing via LBCO/SBCO instructions. */
+struct pru_ctable_entry pru_ctable[32];
+
+/* Forward function declarations. */
+static bool prologue_saved_reg_p (int);
+static void pru_reorg_loop (rtx_insn *);
+
+struct GTY (()) machine_function
+{
+ /* Current frame information, to be filled in by pru_compute_frame_layout
+ with register save masks, and offsets for the current function. */
+
+ /* Mask of registers to save. */
+ HARD_REG_SET save_mask;
+ /* Number of bytes that the entire frame takes up. */
+ int total_size;
+ /* Number of bytes that variables take up. */
+ int var_size;
+ /* Number of bytes that outgoing arguments take up. */
+ int out_args_size;
+ /* Number of bytes needed to store registers in frame. */
+ int save_reg_size;
+ /* Offset from new stack pointer to store registers. */
+ int save_regs_offset;
+ /* True if final frame layout is already calculated. */
+ bool initialized;
+ /* Number of doloop tags used so far. */
+ int doloop_tags;
+ /* True if the last tag was allocated to a doloop_end. */
+ bool doloop_tag_from_end;
+};
+
+/* Stack layout and calling conventions.
+
+ The PRU ABI defines r4 as Argument Pointer. GCC implements the same
+ semantics, but represents it with HARD_FRAME_POINTER_REGNUM and
+ names it FP. The stack layout is shown below:
+
+ ---------------------- high address
+ | incoming args
+ ------call-boundary---
+ | pretend_args ^
+ FP ---------------- | total
+ | save_regs | frame
+ --------------- | size
+ | local vars |
+ --------------- |
+ | outgoing args V
+ SP ---------------------- low address
+
+ */
+
+#define PRU_STACK_ALIGN(LOC) ROUND_UP ((LOC), STACK_BOUNDARY / BITS_PER_UNIT)
+
+/* Implement TARGET_COMPUTE_FRAME_LAYOUT. */
+static void
+pru_compute_frame_layout (void)
+{
+ int regno;
+ HARD_REG_SET *save_mask;
+ int total_size;
+ int var_size;
+ int out_args_size;
+ int save_reg_size;
+
+ gcc_assert (!cfun->machine->initialized);
+
+ save_mask = &cfun->machine->save_mask;
+ CLEAR_HARD_REG_SET (*save_mask);
+
+ var_size = PRU_STACK_ALIGN ((HOST_WIDE_INT) get_frame_size ());
+ out_args_size = PRU_STACK_ALIGN ((HOST_WIDE_INT) crtl->outgoing_args_size);
+ total_size = var_size + out_args_size;
+
+ /* Calculate space needed for gp registers. */
+ save_reg_size = 0;
+ for (regno = 0; regno <= LAST_GP_REGNUM; regno++)
+ if (prologue_saved_reg_p (regno))
+ {
+ SET_HARD_REG_BIT (*save_mask, regno);
+ save_reg_size += 1;
+ }
+
+ save_reg_size = PRU_STACK_ALIGN (save_reg_size);
+ total_size += save_reg_size;
+ total_size += PRU_STACK_ALIGN (crtl->args.pretend_args_size);
+
+ /* Save other computed information. */
+ cfun->machine->total_size = total_size;
+ cfun->machine->var_size = var_size;
+ cfun->machine->out_args_size = out_args_size;
+ cfun->machine->save_reg_size = save_reg_size;
+ cfun->machine->initialized = reload_completed;
+ cfun->machine->save_regs_offset = out_args_size + var_size;
+}
+
+/* Emit efficient RTL equivalent of ADD3 with the given const_int for
+ frame-related registers.
+ op0 - Destination register.
+ op1 - First addendum operand (a register).
+ addendum - Second addendum operand (a constant).
+ kind - Note kind. REG_NOTE_MAX if no note must be added.
+ */
+static rtx
+pru_add3_frame_adjust (rtx op0, rtx op1, int addendum,
+ const enum reg_note kind)
+{
+ rtx insn;
+
+ rtx op0_adjust = gen_rtx_SET (op0, plus_constant (Pmode, op1, addendum));
+
+ if (UBYTE_INT (addendum) || UBYTE_INT (-addendum))
+ insn = emit_insn (op0_adjust);
+ else
+ {
+ /* Help the compiler to cope with an arbitrary integer constant.
+ Reload has finished so we can't expect the compiler to
+ auto-allocate a temporary register. But we know that call-saved
+ registers are not live yet, so we utilize them. */
+ rtx tmpreg = gen_rtx_REG (Pmode, PROLOGUE_TEMP_REGNUM);
+ if (addendum < 0)
+ {
+ emit_insn (gen_rtx_SET (tmpreg, gen_int_mode (-addendum, Pmode)));
+ insn = emit_insn (gen_sub3_insn (op0, op1, tmpreg));
+ }
+ else
+ {
+ emit_insn (gen_rtx_SET (tmpreg, gen_int_mode (addendum, Pmode)));
+ insn = emit_insn (gen_add3_insn (op0, op1, tmpreg));
+ }
+ }
+
+ /* Attach a note indicating what happened. */
+ if (kind != REG_NOTE_MAX)
+ add_reg_note (insn, kind, copy_rtx (op0_adjust));
+
+ RTX_FRAME_RELATED_P (insn) = 1;
+
+ return insn;
+}
+
+/* Add a const_int to the stack pointer register. */
+static rtx
+pru_add_to_sp (int addendum, const enum reg_note kind)
+{
+ return pru_add3_frame_adjust (stack_pointer_rtx, stack_pointer_rtx,
+ addendum, kind);
+}
+
+/* Helper function used during prologue/epilogue. Emits a single LBBO/SBBO
+ instruction for load/store of the next group of consecutive registers. */
+static int
+xbbo_next_reg_cluster (int regno_start, int *sp_offset, bool do_store)
+{
+ int regno, nregs, i;
+ rtx addr;
+ rtx_insn *insn;
+
+ nregs = 0;
+
+ /* Skip the empty slots. */
+ for (; regno_start <= LAST_GP_REGNUM;)
+ if (TEST_HARD_REG_BIT (cfun->machine->save_mask, regno_start))
+ break;
+ else
+ regno_start++;
+
+ /* Find the largest consecutive group of registers to save. */
+ for (regno = regno_start; regno <= LAST_GP_REGNUM;)
+ if (TEST_HARD_REG_BIT (cfun->machine->save_mask, regno))
+ {
+ regno++;
+ nregs++;
+ }
+ else
+ break;
+
+ if (!nregs)
+ return -1;
+
+ gcc_assert (UBYTE_INT (*sp_offset));
+
+ /* Ok, save this bunch. */
+ addr = plus_constant (Pmode, stack_pointer_rtx, *sp_offset);
+
+ if (do_store)
+ insn = targetm.gen_store_multiple (gen_frame_mem (BLKmode, addr),
+ gen_rtx_REG (QImode, regno_start),
+ GEN_INT (nregs));
+ else
+ insn = targetm.gen_load_multiple (gen_rtx_REG (QImode, regno_start),
+ gen_frame_mem (BLKmode, addr),
+ GEN_INT (nregs));
+
+ gcc_assert (reload_completed);
+ gcc_assert (insn);
+ emit_insn (insn);
+
+ /* Tag as frame-related. */
+ RTX_FRAME_RELATED_P (insn) = 1;
+
+ if (!do_store)
+ {
+ /* Tag epilogue unwind notes. */
+ for (i = regno_start; i < (regno_start + nregs); i++)
+ add_reg_note (insn, REG_CFA_RESTORE, gen_rtx_REG (QImode, i));
+ }
+
+ /* Increment and save offset in anticipation of the next register group. */
+ *sp_offset += nregs * UNITS_PER_WORD;
+
+ return regno_start + nregs;
+}
+
+/* Emit function prologue. */
+void
+pru_expand_prologue (void)
+{
+ int regno_start;
+ int total_frame_size;
+ int sp_offset; /* Offset from base_reg to final stack value. */
+ int save_regs_base; /* Offset from base_reg to register save area. */
+ int save_offset; /* Temporary offset to currently saved register group. */
+
+ total_frame_size = cfun->machine->total_size;
+
+ if (flag_stack_usage_info)
+ current_function_static_stack_size = total_frame_size;
+
+ /* Decrement the stack pointer. */
+ if (!UBYTE_INT (total_frame_size))
+ {
+ /* We need an intermediary point, this will point at the spill block. */
+ pru_add_to_sp (cfun->machine->save_regs_offset - total_frame_size,
+ REG_NOTE_MAX);
+ save_regs_base = 0;
+ sp_offset = -cfun->machine->save_regs_offset;
+ }
+ else if (total_frame_size)
+ {
+ pru_add_to_sp (- total_frame_size, REG_NOTE_MAX);
+ save_regs_base = cfun->machine->save_regs_offset;
+ sp_offset = 0;
+ }
+ else
+ save_regs_base = sp_offset = 0;
+
+ regno_start = 0;
+ save_offset = save_regs_base;
+ do
+ regno_start = xbbo_next_reg_cluster (regno_start, &save_offset, true);
+ while (regno_start >= 0);
+
+ /* Set FP before adjusting SP. This way fp_offset has
+ better chance to fit in UBYTE. */
+ if (frame_pointer_needed)
+ {
+ int fp_offset = total_frame_size
+ - crtl->args.pretend_args_size
+ + sp_offset;
+
+ pru_add3_frame_adjust (hard_frame_pointer_rtx, stack_pointer_rtx,
+ fp_offset, REG_NOTE_MAX);
+ }
+
+ if (sp_offset)
+ pru_add_to_sp (sp_offset, REG_FRAME_RELATED_EXPR);
+
+ /* If we are profiling, make sure no instructions are scheduled before
+ the call to mcount. */
+ if (crtl->profile)
+ emit_insn (gen_blockage ());
+}
+
+/* Emit function epilogue. */
+void
+pru_expand_epilogue (bool sibcall_p)
+{
+ int total_frame_size;
+ int sp_adjust, save_offset;
+ int regno_start;
+
+ if (!sibcall_p && pru_can_use_return_insn ())
+ {
+ emit_jump_insn (gen_return ());
+ return;
+ }
+
+ emit_insn (gen_blockage ());
+
+ total_frame_size = cfun->machine->total_size;
+
+ if (frame_pointer_needed)
+ {
+ /* Recover the stack pointer. */
+ pru_add3_frame_adjust (stack_pointer_rtx, hard_frame_pointer_rtx,
+ - cfun->machine->save_reg_size,
+ REG_CFA_ADJUST_CFA);
+
+ save_offset = 0;
+ sp_adjust = total_frame_size - cfun->machine->save_regs_offset;
+ }
+ else if (!UBYTE_INT (total_frame_size))
+ {
+ pru_add_to_sp (cfun->machine->save_regs_offset, REG_CFA_ADJUST_CFA);
+ save_offset = 0;
+ sp_adjust = total_frame_size - cfun->machine->save_regs_offset;
+ }
+ else
+ {
+ save_offset = cfun->machine->save_regs_offset;
+ sp_adjust = total_frame_size;
+ }
+
+ regno_start = 0;
+ do
+ regno_start = xbbo_next_reg_cluster (regno_start, &save_offset, false);
+ while (regno_start >= 0);
+
+ /* Emit a blockage insn here to keep these insns from being moved to
+ an earlier spot in the epilogue.
+
+ This is necessary as we must not cut the stack back before all the
+ restores are finished. */
+ emit_insn (gen_blockage ());
+
+ if (sp_adjust)
+ pru_add_to_sp (sp_adjust, REG_CFA_ADJUST_CFA);
+
+ if (!sibcall_p)
+ emit_jump_insn (gen_simple_return ());
+}
+
+/* Implement RETURN_ADDR_RTX. Note, we do not support moving
+ back to a previous frame. */
+rtx
+pru_get_return_address (int count)
+{
+ if (count != 0)
+ return NULL_RTX;
+
+ /* Return r3.w2. */
+ return get_hard_reg_initial_val (HImode, RA_REGNUM);
+}
+
+/* Implement FUNCTION_PROFILER macro. */
+void
+pru_function_profiler (FILE *file, int labelno ATTRIBUTE_UNUSED)
+{
+ fprintf (file, "\tmov\tr1, ra\n");
+ fprintf (file, "\tcall\t_mcount\n");
+ fprintf (file, "\tmov\tra, r1\n");
+}
+
+/* Dump stack layout. */
+static void
+pru_dump_frame_layout (FILE *file)
+{
+ fprintf (file, "\t%s Current Frame Info\n", ASM_COMMENT_START);
+ fprintf (file, "\t%s total_size = %d\n", ASM_COMMENT_START,
+ cfun->machine->total_size);
+ fprintf (file, "\t%s var_size = %d\n", ASM_COMMENT_START,
+ cfun->machine->var_size);
+ fprintf (file, "\t%s out_args_size = %d\n", ASM_COMMENT_START,
+ cfun->machine->out_args_size);
+ fprintf (file, "\t%s save_reg_size = %d\n", ASM_COMMENT_START,
+ cfun->machine->save_reg_size);
+ fprintf (file, "\t%s initialized = %d\n", ASM_COMMENT_START,
+ cfun->machine->initialized);
+ fprintf (file, "\t%s save_regs_offset = %d\n", ASM_COMMENT_START,
+ cfun->machine->save_regs_offset);
+ fprintf (file, "\t%s is_leaf = %d\n", ASM_COMMENT_START,
+ crtl->is_leaf);
+ fprintf (file, "\t%s frame_pointer_needed = %d\n", ASM_COMMENT_START,
+ frame_pointer_needed);
+ fprintf (file, "\t%s pretend_args_size = %d\n", ASM_COMMENT_START,
+ crtl->args.pretend_args_size);
+}
+
+/* Return true if REGNO should be saved in the prologue. */
+static bool
+prologue_saved_reg_p (int regno)
+{
+ gcc_assert (GP_REG_P (regno));
+
+ if (df_regs_ever_live_p (regno) && !call_used_regs[regno])
+ return true;
+
+ /* 32-bit FP. */
+ if (frame_pointer_needed
+ && regno >= HARD_FRAME_POINTER_REGNUM
+ && regno < HARD_FRAME_POINTER_REGNUM + GET_MODE_SIZE (Pmode))
+ return true;
+
+ /* 16-bit RA. */
+ if (regno == RA_REGNUM && df_regs_ever_live_p (RA_REGNUM))
+ return true;
+ if (regno == RA_REGNUM + 1 && df_regs_ever_live_p (RA_REGNUM + 1))
+ return true;
+
+ return false;
+}
+
+/* Implement TARGET_CAN_ELIMINATE. */
+static bool
+pru_can_eliminate (const int from ATTRIBUTE_UNUSED, const int to)
+{
+ if (to == STACK_POINTER_REGNUM)
+ return !frame_pointer_needed;
+ return true;
+}
+
+/* Implement INITIAL_ELIMINATION_OFFSET macro. */
+int
+pru_initial_elimination_offset (int from, int to)
+{
+ int offset;
+
+ /* Set OFFSET to the offset from the stack pointer. */
+ switch (from)
+ {
+ case FRAME_POINTER_REGNUM:
+ offset = cfun->machine->out_args_size;
+ break;
+
+ case ARG_POINTER_REGNUM:
+ offset = cfun->machine->total_size;
+ offset -= crtl->args.pretend_args_size;
+ break;
+
+ default:
+ gcc_unreachable ();
+ }
+
+ /* If we are asked for the frame pointer offset, then adjust OFFSET
+ by the offset from the frame pointer to the stack pointer. */
+ if (to == HARD_FRAME_POINTER_REGNUM)
+ offset -= cfun->machine->total_size - crtl->args.pretend_args_size;
+
+
+ return offset;
+}
+
+/* Return nonzero if this function is known to have a null epilogue.
+ This allows the optimizer to omit jumps to jumps if no stack
+ was created. */
+int
+pru_can_use_return_insn (void)
+{
+ if (!reload_completed || crtl->profile)
+ return 0;
+
+ return cfun->machine->total_size == 0;
+}
+
+/* Implement TARGET_HARD_REGNO_MODE_OK. */
+
+static bool
+pru_hard_regno_mode_ok (unsigned int regno, machine_mode mode)
+{
+ switch (GET_MODE_SIZE (mode))
+ {
+ case 1: return true;
+ case 2: return (regno % 4) <= 2;
+ case 4: return (regno % 4) == 0;
+ case 8: return (regno % 4) == 0;
+ case 16: return (regno % 4) == 0; /* Not sure why TImode is used. */
+ case 32: return (regno % 4) == 0; /* Not sure why CTImode is used. */
+ default:
+ /* TODO: Find out why VOIDmode and BLKmode are passed. */
+ gcc_assert (mode == BLKmode || mode == VOIDmode);
+ return (regno % 4) == 0;
+ }
+}
+
+/* Implement `TARGET_HARD_REGNO_SCRATCH_OK'.
+ Returns true if REGNO is safe to be allocated as a scratch
+ register (for a define_peephole2) in the current function. */
+
+static bool
+pru_hard_regno_scratch_ok (unsigned int regno)
+{
+ /* Don't allow hard registers that might be part of the frame pointer.
+ Some places in the compiler just test for [HARD_]FRAME_POINTER_REGNUM
+ and don't handle a frame pointer that spans more than one register.
+ TODO: Fix those faulty places. */
+
+ if ((!reload_completed || frame_pointer_needed)
+ && (IN_RANGE (regno, HARD_FRAME_POINTER_REGNUM,
+ HARD_FRAME_POINTER_REGNUM + 3)
+ || IN_RANGE (regno, FRAME_POINTER_REGNUM,
+ FRAME_POINTER_REGNUM + 3)))
+ return false;
+
+ return true;
+}
+
+
+/* Implement TARGET_HARD_REGNO_CALL_PART_CLOBBERED. */
+
+static bool
+pru_hard_regno_call_part_clobbered (rtx_insn *insn ATTRIBUTE_UNUSED,
+ unsigned regno, machine_mode mode)
+{
+ HARD_REG_SET caller_saved_set;
+ HARD_REG_SET callee_saved_set;
+
+ CLEAR_HARD_REG_SET (caller_saved_set);
+ CLEAR_HARD_REG_SET (callee_saved_set);
+
+ /* r0 and r1 are caller saved. */
+ add_range_to_hard_reg_set (&caller_saved_set, 0, 2 * 4);
+
+ add_range_to_hard_reg_set (&caller_saved_set, FIRST_ARG_REGNUM,
+ LAST_ARG_REGNUM + 1 - FIRST_ARG_REGNUM);
+
+ /* Treat SP as callee saved. */
+ add_range_to_hard_reg_set (&callee_saved_set, STACK_POINTER_REGNUM, 4);
+
+ /* r3 to r13 are callee saved. */
+ add_range_to_hard_reg_set (&callee_saved_set, FIRST_CALLEE_SAVED_REGNUM,
+ LAST_CALEE_SAVED_REGNUM + 1
+ - FIRST_CALLEE_SAVED_REGNUM);
+
+ return overlaps_hard_reg_set_p (caller_saved_set, mode, regno)
+ && overlaps_hard_reg_set_p (callee_saved_set, mode, regno);
+}
+
+
+/* Worker function for `HARD_REGNO_RENAME_OK'.
+ Return nonzero if register OLD_REG can be renamed to register NEW_REG. */
+
+int
+pru_hard_regno_rename_ok (unsigned int old_reg,
+ unsigned int new_reg)
+{
+ /* Don't allow hard registers that might be part of the frame pointer.
+ Some places in the compiler just test for [HARD_]FRAME_POINTER_REGNUM
+ and don't care for a frame pointer that spans more than one register.
+ TODO: Fix those faulty places. */
+ if ((!reload_completed || frame_pointer_needed)
+ && (IN_RANGE (old_reg, HARD_FRAME_POINTER_REGNUM,
+ HARD_FRAME_POINTER_REGNUM + 3)
+ || IN_RANGE (old_reg, FRAME_POINTER_REGNUM,
+ FRAME_POINTER_REGNUM + 3)
+ || IN_RANGE (new_reg, HARD_FRAME_POINTER_REGNUM,
+ HARD_FRAME_POINTER_REGNUM + 3)
+ || IN_RANGE (new_reg, FRAME_POINTER_REGNUM,
+ FRAME_POINTER_REGNUM + 3)))
+ return 0;
+
+ return 1;
+}
+
+/* Allocate a chunk of memory for per-function machine-dependent data. */
+static struct machine_function *
+pru_init_machine_status (void)
+{
+ return ggc_cleared_alloc<machine_function> ();
+}
+
+/* Implement TARGET_OPTION_OVERRIDE. */
+static void
+pru_option_override (void)
+{
+#ifdef SUBTARGET_OVERRIDE_OPTIONS
+ SUBTARGET_OVERRIDE_OPTIONS;
+#endif
+
+ /* Check for unsupported options. */
+ if (flag_pic == 1)
+ warning (OPT_fpic, "%<-fpic%> is not supported");
+ if (flag_pic == 2)
+ warning (OPT_fPIC, "%<-fPIC%> is not supported");
+ if (flag_pie == 1)
+ warning (OPT_fpie, "%<-fpie%> is not supported");
+ if (flag_pie == 2)
+ warning (OPT_fPIE, "%<-fPIE%> is not supported");
+
+ /* QBxx conditional branching cannot cope with block reordering. */
+ if (flag_reorder_blocks_and_partition)
+ {
+ inform (input_location, "%<-freorder-blocks-and-partition%> "
+ "not supported on this architecture");
+ flag_reorder_blocks_and_partition = 0;
+ flag_reorder_blocks = 1;
+ }
+
+ /* Function to allocate machine-dependent function status. */
+ init_machine_status = &pru_init_machine_status;
+
+ /* Save the initial options in case the user does function specific
+ options. */
+ target_option_default_node = target_option_current_node
+ = build_target_option_node (&global_options);
+
+ /* Due to difficulties in implementing the TI ABI with GCC,
+ at least check and error-out if GCC cannot compile a
+ compliant output. */
+ pru_register_abicheck_pass ();
+}
+
+/* Compute a (partial) cost for rtx X. Return true if the complete
+ cost has been computed, and false if subexpressions should be
+ scanned. In either case, *TOTAL contains the cost result. */
+static bool
+pru_rtx_costs (rtx x, machine_mode mode,
+ int outer_code, int opno ATTRIBUTE_UNUSED,
+ int *total, bool speed ATTRIBUTE_UNUSED)
+{
+ const int code = GET_CODE (x);
+
+ switch (code)
+ {
+ case CONST_INT:
+ if ((mode == VOIDmode && UBYTE_INT (INTVAL (x)))
+ || (mode != VOIDmode && const_ubyte_operand (x, mode)))
+ {
+ *total = COSTS_N_INSNS (0);
+ return true;
+ }
+ else if ((mode == VOIDmode && UHWORD_INT (INTVAL (x)))
+ || (mode != VOIDmode && const_uhword_operand (x, mode)))
+ {
+ *total = COSTS_N_INSNS (1);
+ return true;
+ }
+ else if (outer_code == MEM && ctable_addr_operand (x, VOIDmode))
+ {
+ *total = COSTS_N_INSNS (0);
+ return true;
+ }
+ else
+ {
+ *total = COSTS_N_INSNS (2);
+ return true;
+ }
+
+ case LABEL_REF:
+ case SYMBOL_REF:
+ case CONST:
+ {
+ *total = COSTS_N_INSNS (1);
+ return true;
+ }
+ case CONST_DOUBLE:
+ {
+ *total = COSTS_N_INSNS (2);
+ return true;
+ }
+ case CONST_WIDE_INT:
+ {
+ /* PRU declares no vector or very large integer types. */
+ gcc_unreachable ();
+ return true;
+ }
+ case SET:
+ {
+ int factor;
+
+ /* A SET doesn't have a mode, so let's look at the SET_DEST to get
+ the mode for the factor. */
+ mode = GET_MODE (SET_DEST (x));
+
+ /* SI move has the same cost as a QI move. Moves larger than
+ 64 bits are costly. */
+ factor = CEIL (GET_MODE_SIZE (mode), GET_MODE_SIZE (SImode));
+ *total = factor * COSTS_N_INSNS (1);
+
+ return false;
+ }
+
+ case MULT:
+ {
+ /* Factor in that "mul" requires fixed registers, which
+ would likely require register moves. */
+ *total = COSTS_N_INSNS (7);
+ return false;
+ }
+ case PLUS:
+ {
+ rtx op0 = XEXP (x, 0);
+ rtx op1 = XEXP (x, 1);
+ machine_mode op1_mode = GET_MODE (op1);
+
+ /* Generic RTL address expressions do not enforce mode for
+ offsets, yet our UBYTE constraint requires it. Fix it here. */
+ if (op1_mode == VOIDmode && CONST_INT_P (op1) && outer_code == MEM)
+ op1_mode = Pmode;
+ if (outer_code == MEM
+ && ((REG_P (op0) && reg_or_ubyte_operand (op1, op1_mode))
+ || ctable_addr_operand (op0, VOIDmode)
+ || ctable_addr_operand (op1, VOIDmode)
+ || (ctable_base_operand (op0, VOIDmode) && REG_P (op1))
+ || (ctable_base_operand (op1, VOIDmode) && REG_P (op0))))
+ {
+ /* CTABLE or REG base addressing - PLUS comes for free. */
+ *total = COSTS_N_INSNS (0);
+ return true;
+ }
+ else
+ {
+ *total = COSTS_N_INSNS (1);
+ return false;
+ }
+ }
+ case SIGN_EXTEND:
+ {
+ *total = COSTS_N_INSNS (3);
+ return false;
+ }
+ case ASHIFTRT:
+ {
+ rtx op1 = XEXP (x, 1);
+ if (const_1_operand (op1, VOIDmode))
+ *total = COSTS_N_INSNS (3);
+ else
+ *total = COSTS_N_INSNS (7);
+ return false;
+ }
+ case ZERO_EXTRACT:
+ {
+ rtx op2 = XEXP (x, 2);
+ if ((outer_code == EQ || outer_code == NE)
+ && CONST_INT_P (op2)
+ && INTVAL (op2) == 1)
+ {
+ /* Branch if bit is set/clear is a single instruction. */
+ *total = COSTS_N_INSNS (0);
+ return true;
+ }
+ else
+ {
+ *total = COSTS_N_INSNS (2);
+ return false;
+ }
+ }
+ case ZERO_EXTEND:
+ {
+ *total = COSTS_N_INSNS (0);
+ return false;
+ }
+
+ default:
+ {
+ /* PRU ALU is 32 bit, despite GCC's UNITS_PER_WORD=1. */
+ int factor = CEIL (GET_MODE_SIZE (mode), GET_MODE_SIZE (SImode));
+ *total = factor * COSTS_N_INSNS (1);
+ return false;
+ }
+ }
+}
+
+static GTY(()) rtx eqdf_libfunc;
+static GTY(()) rtx nedf_libfunc;
+static GTY(()) rtx ledf_libfunc;
+static GTY(()) rtx ltdf_libfunc;
+static GTY(()) rtx gedf_libfunc;
+static GTY(()) rtx gtdf_libfunc;
+static GTY(()) rtx eqsf_libfunc;
+static GTY(()) rtx nesf_libfunc;
+static GTY(()) rtx lesf_libfunc;
+static GTY(()) rtx ltsf_libfunc;
+static GTY(()) rtx gesf_libfunc;
+static GTY(()) rtx gtsf_libfunc;
+
+/* Implement the TARGET_INIT_LIBFUNCS macro. We use this to rename library
+ functions to match the PRU ABI. */
+
+static void
+pru_init_libfuncs (void)
+{
+ /* Double-precision floating-point arithmetic. */
+ set_optab_libfunc (add_optab, DFmode, "__pruabi_addd");
+ set_optab_libfunc (sdiv_optab, DFmode, "__pruabi_divd");
+ set_optab_libfunc (smul_optab, DFmode, "__pruabi_mpyd");
+ set_optab_libfunc (neg_optab, DFmode, "__pruabi_negd");
+ set_optab_libfunc (sub_optab, DFmode, "__pruabi_subd");
+
+ /* Single-precision floating-point arithmetic. */
+ set_optab_libfunc (add_optab, SFmode, "__pruabi_addf");
+ set_optab_libfunc (sdiv_optab, SFmode, "__pruabi_divf");
+ set_optab_libfunc (smul_optab, SFmode, "__pruabi_mpyf");
+ set_optab_libfunc (neg_optab, SFmode, "__pruabi_negf");
+ set_optab_libfunc (sub_optab, SFmode, "__pruabi_subf");
+
+ /* Floating-point comparisons. */
+ eqsf_libfunc = init_one_libfunc ("__pruabi_eqf");
+ nesf_libfunc = init_one_libfunc ("__pruabi_neqf");
+ lesf_libfunc = init_one_libfunc ("__pruabi_lef");
+ ltsf_libfunc = init_one_libfunc ("__pruabi_ltf");
+ gesf_libfunc = init_one_libfunc ("__pruabi_gef");
+ gtsf_libfunc = init_one_libfunc ("__pruabi_gtf");
+ eqdf_libfunc = init_one_libfunc ("__pruabi_eqd");
+ nedf_libfunc = init_one_libfunc ("__pruabi_neqd");
+ ledf_libfunc = init_one_libfunc ("__pruabi_led");
+ ltdf_libfunc = init_one_libfunc ("__pruabi_ltd");
+ gedf_libfunc = init_one_libfunc ("__pruabi_ged");
+ gtdf_libfunc = init_one_libfunc ("__pruabi_gtd");
+
+ /* In PRU ABI, much like other TI processors, floating point
+ comparisons return non-standard values. This quirk is handled
+ by disabling the optab library functions, and handling the
+ comparison during RTL expansion. */
+ set_optab_libfunc (eq_optab, SFmode, NULL);
+ set_optab_libfunc (ne_optab, SFmode, NULL);
+ set_optab_libfunc (gt_optab, SFmode, NULL);
+ set_optab_libfunc (ge_optab, SFmode, NULL);
+ set_optab_libfunc (lt_optab, SFmode, NULL);
+ set_optab_libfunc (le_optab, SFmode, NULL);
+ set_optab_libfunc (eq_optab, DFmode, NULL);
+ set_optab_libfunc (ne_optab, DFmode, NULL);
+ set_optab_libfunc (gt_optab, DFmode, NULL);
+ set_optab_libfunc (ge_optab, DFmode, NULL);
+ set_optab_libfunc (lt_optab, DFmode, NULL);
+ set_optab_libfunc (le_optab, DFmode, NULL);
+
+ /* The isunordered function appears to be supported only by GCC. */
+ set_optab_libfunc (unord_optab, SFmode, "__pruabi_unordf");
+ set_optab_libfunc (unord_optab, DFmode, "__pruabi_unordd");
+
+ /* Floating-point to integer conversions. */
+ set_conv_libfunc (sfix_optab, SImode, DFmode, "__pruabi_fixdi");
+ set_conv_libfunc (ufix_optab, SImode, DFmode, "__pruabi_fixdu");
+ set_conv_libfunc (sfix_optab, DImode, DFmode, "__pruabi_fixdlli");
+ set_conv_libfunc (ufix_optab, DImode, DFmode, "__pruabi_fixdull");
+ set_conv_libfunc (sfix_optab, SImode, SFmode, "__pruabi_fixfi");
+ set_conv_libfunc (ufix_optab, SImode, SFmode, "__pruabi_fixfu");
+ set_conv_libfunc (sfix_optab, DImode, SFmode, "__pruabi_fixflli");
+ set_conv_libfunc (ufix_optab, DImode, SFmode, "__pruabi_fixfull");
+
+ /* Conversions between floating types. */
+ set_conv_libfunc (trunc_optab, SFmode, DFmode, "__pruabi_cvtdf");
+ set_conv_libfunc (sext_optab, DFmode, SFmode, "__pruabi_cvtfd");
+
+ /* Integer to floating-point conversions. */
+ set_conv_libfunc (sfloat_optab, DFmode, SImode, "__pruabi_fltid");
+ set_conv_libfunc (ufloat_optab, DFmode, SImode, "__pruabi_fltud");
+ set_conv_libfunc (sfloat_optab, DFmode, DImode, "__pruabi_fltllid");
+ set_conv_libfunc (ufloat_optab, DFmode, DImode, "__pruabi_fltulld");
+ set_conv_libfunc (sfloat_optab, SFmode, SImode, "__pruabi_fltif");
+ set_conv_libfunc (ufloat_optab, SFmode, SImode, "__pruabi_fltuf");
+ set_conv_libfunc (sfloat_optab, SFmode, DImode, "__pruabi_fltllif");
+ set_conv_libfunc (ufloat_optab, SFmode, DImode, "__pruabi_fltullf");
+
+ /* Long long. */
+ set_optab_libfunc (ashr_optab, DImode, "__pruabi_asrll");
+ set_optab_libfunc (smul_optab, DImode, "__pruabi_mpyll");
+ set_optab_libfunc (ashl_optab, DImode, "__pruabi_lslll");
+ set_optab_libfunc (lshr_optab, DImode, "__pruabi_lsrll");
+
+ set_optab_libfunc (sdiv_optab, SImode, "__pruabi_divi");
+ set_optab_libfunc (udiv_optab, SImode, "__pruabi_divu");
+ set_optab_libfunc (smod_optab, SImode, "__pruabi_remi");
+ set_optab_libfunc (umod_optab, SImode, "__pruabi_remu");
+ set_optab_libfunc (sdivmod_optab, SImode, "__pruabi_divremi");
+ set_optab_libfunc (udivmod_optab, SImode, "__pruabi_divremu");
+ set_optab_libfunc (sdiv_optab, DImode, "__pruabi_divlli");
+ set_optab_libfunc (udiv_optab, DImode, "__pruabi_divull");
+ set_optab_libfunc (smod_optab, DImode, "__pruabi_remlli");
+ set_optab_libfunc (umod_optab, DImode, "__pruabi_remull");
+ set_optab_libfunc (udivmod_optab, DImode, "__pruabi_divremull");
+}
+
+
+/* Emit comparison instruction if necessary, returning the expression
+ that holds the compare result in the proper mode. Return the comparison
+ that should be used in the jump insn. */
+
+rtx
+pru_expand_fp_compare (rtx comparison, machine_mode mode)
+{
+ enum rtx_code code = GET_CODE (comparison);
+ rtx op0 = XEXP (comparison, 0);
+ rtx op1 = XEXP (comparison, 1);
+ rtx cmp;
+ enum rtx_code jump_code = code;
+ machine_mode op_mode = GET_MODE (op0);
+ rtx_insn *insns;
+ rtx libfunc;
+
+ gcc_assert (op_mode == DFmode || op_mode == SFmode);
+
+ /* FP exceptions are not raised by PRU's softfp implementation. So the
+ following transformations are safe. */
+ if (code == UNGE)
+ {
+ code = LT;
+ jump_code = EQ;
+ }
+ else if (code == UNLE)
+ {
+ code = GT;
+ jump_code = EQ;
+ }
+ else
+ jump_code = NE;
+
+ switch (code)
+ {
+ case EQ:
+ libfunc = op_mode == DFmode ? eqdf_libfunc : eqsf_libfunc;
+ break;
+ case NE:
+ libfunc = op_mode == DFmode ? nedf_libfunc : nesf_libfunc;
+ break;
+ case GT:
+ libfunc = op_mode == DFmode ? gtdf_libfunc : gtsf_libfunc;
+ break;
+ case GE:
+ libfunc = op_mode == DFmode ? gedf_libfunc : gesf_libfunc;
+ break;
+ case LT:
+ libfunc = op_mode == DFmode ? ltdf_libfunc : ltsf_libfunc;
+ break;
+ case LE:
+ libfunc = op_mode == DFmode ? ledf_libfunc : lesf_libfunc;
+ break;
+ default:
+ gcc_unreachable ();
+ }
+ start_sequence ();
+
+ cmp = emit_library_call_value (libfunc, 0, LCT_CONST, SImode,
+ op0, op_mode, op1, op_mode);
+ insns = get_insns ();
+ end_sequence ();
+
+ emit_libcall_block (insns, cmp, cmp,
+ gen_rtx_fmt_ee (code, SImode, op0, op1));
+
+ return gen_rtx_fmt_ee (jump_code, mode, cmp, const0_rtx);
+}
+
+/* Return the sign bit position for given OP's mode. */
+static int
+sign_bit_position (const rtx op)
+{
+ const int sz = GET_MODE_SIZE (GET_MODE (op));
+
+ return sz * 8 - 1;
+}
+
+/* Output asm code for sign_extend operation. */
+const char *
+pru_output_sign_extend (rtx *operands)
+{
+ static char buf[512];
+ int bufi;
+ const int dst_sz = GET_MODE_SIZE (GET_MODE (operands[0]));
+ const int src_sz = GET_MODE_SIZE (GET_MODE (operands[1]));
+ char ext_start;
+
+ switch (src_sz)
+ {
+ case 1: ext_start = 'y'; break;
+ case 2: ext_start = 'z'; break;
+ default: gcc_unreachable ();
+ }
+
+ gcc_assert (dst_sz > src_sz);
+
+ /* Note that src and dst can be different parts of the same
+ register, e.g. "r7, r7.w1". */
+ bufi = snprintf (buf, sizeof (buf),
+ "mov\t%%0, %%1\n\t" /* Copy AND make positive. */
+ "qbbc\t.+8, %%0, %d\n\t" /* Check sign bit. */
+ "fill\t%%%c0, %d", /* Make negative. */
+ sign_bit_position (operands[1]),
+ ext_start,
+ dst_sz - src_sz);
+
+ gcc_assert (bufi > 0);
+ gcc_assert ((unsigned int) bufi < sizeof (buf));
+
+ return buf;
+}
+
+/* Branches and compares. */
+
+/* PRU's ALU does not support signed comparison operations. That's why we
+ emulate them. By first checking the sign bit and handling every possible
+ operand sign combination, we can simulate signed comparisons in just
+ 5 instructions. See table below.
+
+.-------------------.---------------------------------------------------.
+| Operand sign bit | Mapping the signed comparison to an unsigned one |
+|---------+---------+------------+------------+------------+------------|
+| OP1.b31 | OP2.b31 | OP1 < OP2 | OP1 <= OP2 | OP1 > OP2 | OP1 >= OP2 |
+|---------+---------+------------+------------+------------+------------|
+| 0 | 0 | OP1 < OP2 | OP1 <= OP2 | OP1 > OP2 | OP1 >= OP2 |
+|---------+---------+------------+------------+------------+------------|
+| 0 | 1 | false | false | true | true |
+|---------+---------+------------+------------+------------+------------|
+| 1 | 0 | true | true | false | false |
+|---------+---------+------------+------------+------------+------------|
+| 1 | 1 | OP1 < OP2 | OP1 <= OP2 | OP1 > OP2 | OP1 >= OP2 |
+`---------'---------'------------'------------'------------+------------'
+
+
+Given the table above, here is an example for a concrete op:
+ LT:
+ qbbc OP1_POS, OP1, 31
+ OP1_NEG: qbbc BRANCH_TAKEN_LABEL, OP2, 31
+ OP1_NEG_OP2_NEG: qblt BRANCH_TAKEN_LABEL, OP2, OP1
+ ; jmp OUT -> can be eliminated because we'll take the
+ ; following branch. OP2.b31 is guaranteed to be 1
+ ; by the time we get here.
+ OP1_POS: qbbs OUT, OP2, 31
+ OP1_POS_OP2_POS: qblt BRANCH_TAKEN_LABEL, OP2, OP1
+#if FAR_JUMP
+ jmp OUT
+BRANCH_TAKEN_LABEL: jmp REAL_BRANCH_TAKEN_LABEL
+#endif
+ OUT:
+
+*/
+
+/* Output asm code for a signed-compare LT/LE conditional branch. */
+static const char *
+pru_output_ltle_signed_cbranch (rtx *operands, bool is_near)
+{
+ static char buf[1024];
+ enum rtx_code code = GET_CODE (operands[0]);
+ rtx op1;
+ rtx op2;
+ const char *cmp_opstr;
+ int bufi = 0;
+
+ op1 = operands[1];
+ op2 = operands[2];
+
+ gcc_assert (GET_CODE (op1) == REG && GET_CODE (op2) == REG);
+
+ /* Determine the comparison operators for positive and negative operands. */
+ if (code == LT)
+ cmp_opstr = "qblt";
+ else if (code == LE)
+ cmp_opstr = "qble";
+ else
+ gcc_unreachable ();
+
+ if (is_near)
+ bufi = snprintf (buf, sizeof (buf),
+ "qbbc\t.+12, %%1, %d\n\t"
+ "qbbc\t%%l3, %%2, %d\n\t" /* OP1_NEG. */
+ "%s\t%%l3, %%2, %%1\n\t" /* OP1_NEG_OP2_NEG. */
+ "qbbs\t.+8, %%2, %d\n\t" /* OP1_POS. */
+ "%s\t%%l3, %%2, %%1", /* OP1_POS_OP2_POS. */
+ sign_bit_position (op1),
+ sign_bit_position (op2),
+ cmp_opstr,
+ sign_bit_position (op2),
+ cmp_opstr);
+ else
+ bufi = snprintf (buf, sizeof (buf),
+ "qbbc\t.+12, %%1, %d\n\t"
+ "qbbc\t.+20, %%2, %d\n\t" /* OP1_NEG. */
+ "%s\t.+16, %%2, %%1\n\t" /* OP1_NEG_OP2_NEG. */
+ "qbbs\t.+16, %%2, %d\n\t" /* OP1_POS. */
+ "%s\t.+8, %%2, %%1\n\t" /* OP1_POS_OP2_POS. */
+ "jmp\t.+8\n\t" /* jmp OUT. */
+ "jmp\t%%%%label(%%l3)", /* BRANCH_TAKEN_LABEL. */
+ sign_bit_position (op1),
+ sign_bit_position (op2),
+ cmp_opstr,
+ sign_bit_position (op2),
+ cmp_opstr);
+
+ gcc_assert (bufi > 0);
+ gcc_assert ((unsigned int) bufi < sizeof (buf));
+
+ return buf;
+}
+
+/* Output asm code for a signed-compare GT/GE conditional branch. */
+static const char *
+pru_output_gtge_signed_cbranch (rtx *operands, bool is_near)
+{
+ static char buf[1024];
+ enum rtx_code code = GET_CODE (operands[0]);
+ rtx op1;
+ rtx op2;
+ const char *cmp_opstr;
+ int bufi = 0;
+
+ op1 = operands[1];
+ op2 = operands[2];
+
+ gcc_assert (GET_CODE (op1) == REG && GET_CODE (op2) == REG);
+
+ /* Determine the comparison operators for positive and negative operands. */
+ if (code == GT)
+ cmp_opstr = "qbgt";
+ else if (code == GE)
+ cmp_opstr = "qbge";
+ else
+ gcc_unreachable ();
+
+ if (is_near)
+ bufi = snprintf (buf, sizeof (buf),
+ "qbbs\t.+12, %%1, %d\n\t"
+ "qbbs\t%%l3, %%2, %d\n\t" /* OP1_POS. */
+ "%s\t%%l3, %%2, %%1\n\t" /* OP1_POS_OP2_POS. */
+ "qbbc\t.+8, %%2, %d\n\t" /* OP1_NEG. */
+ "%s\t%%l3, %%2, %%1", /* OP1_NEG_OP2_NEG. */
+ sign_bit_position (op1),
+ sign_bit_position (op2),
+ cmp_opstr,
+ sign_bit_position (op2),
+ cmp_opstr);
+ else
+ bufi = snprintf (buf, sizeof (buf),
+ "qbbs\t.+12, %%1, %d\n\t"
+ "qbbs\t.+20, %%2, %d\n\t" /* OP1_POS. */
+ "%s\t.+16, %%2, %%1\n\t" /* OP1_POS_OP2_POS. */
+ "qbbc\t.+16, %%2, %d\n\t" /* OP1_NEG. */
+ "%s\t.+8, %%2, %%1\n\t" /* OP1_NEG_OP2_NEG. */
+ "jmp\t.+8\n\t" /* jmp OUT. */
+ "jmp\t%%%%label(%%l3)", /* BRANCH_TAKEN_LABEL. */
+ sign_bit_position (op1),
+ sign_bit_position (op2),
+ cmp_opstr,
+ sign_bit_position (op2),
+ cmp_opstr);
+
+ gcc_assert (bufi > 0);
+ gcc_assert ((unsigned int) bufi < sizeof (buf));
+
+ return buf;
+}
+
+/* Output asm code for a signed-compare conditional branch.
+
+ If IS_NEAR is true, then QBBx instructions may be used for reaching
+ the destination label. Otherwise JMP is used, at the expense of
+ increased code size. */
+const char *
+pru_output_signed_cbranch (rtx *operands, bool is_near)
+{
+ enum rtx_code code = GET_CODE (operands[0]);
+
+ if (code == LT || code == LE)
+ return pru_output_ltle_signed_cbranch (operands, is_near);
+ else if (code == GT || code == GE)
+ return pru_output_gtge_signed_cbranch (operands, is_near);
+ else
+ gcc_unreachable ();
+}
+
+/* Optimized version of pru_output_signed_cbranch for constant second
+ operand. */
+
+const char *
+pru_output_signed_cbranch_ubyteop2 (rtx *operands, bool is_near)
+{
+ static char buf[1024];
+ enum rtx_code code = GET_CODE (operands[0]);
+ int regop_sign_bit_pos = sign_bit_position (operands[1]);
+ const char *cmp_opstr;
+ const char *rcmp_opstr;
+
+ /* We must swap operands due to PRU's demand OP1 to be the immediate. */
+ code = swap_condition (code);
+
+ /* Determine normal and reversed comparison operators for both positive
+ operands. This enables us to go completely unsigned.
+
+ NOTE: We cannot use the R print modifier because we convert signed
+ comparison operators to unsigned ones. */
+ switch (code)
+ {
+ case LT: cmp_opstr = "qblt"; rcmp_opstr = "qbge"; break;
+ case LE: cmp_opstr = "qble"; rcmp_opstr = "qbgt"; break;
+ case GT: cmp_opstr = "qbgt"; rcmp_opstr = "qble"; break;
+ case GE: cmp_opstr = "qbge"; rcmp_opstr = "qblt"; break;
+ default: gcc_unreachable ();
+ }
+
+ /* OP2 is a constant unsigned byte - utilize this info to generate
+ optimized code. We can "remove half" of the op table above because
+ we know that OP2.b31 = 0 (remember that 0 <= OP2 <= 255). */
+ if (code == LT || code == LE)
+ {
+ if (is_near)
+ snprintf (buf, sizeof (buf),
+ "qbbs\t.+8, %%1, %d\n\t"
+ "%s\t%%l3, %%1, %%u2",
+ regop_sign_bit_pos,
+ cmp_opstr);
+ else
+ snprintf (buf, sizeof (buf),
+ "qbbs\t.+12, %%1, %d\n\t"
+ "%s\t.+8, %%1, %%u2\n\t"
+ "jmp\t%%%%label(%%l3)",
+ regop_sign_bit_pos,
+ rcmp_opstr);
+ }
+ else if (code == GT || code == GE)
+ {
+ if (is_near)
+ snprintf (buf, sizeof (buf),
+ "qbbs\t%%l3, %%1, %d\n\t"
+ "%s\t%%l3, %%1, %%u2",
+ regop_sign_bit_pos,
+ cmp_opstr);
+ else
+ snprintf (buf, sizeof (buf),
+ "qbbs\t.+8, %%1, %d\n\t"
+ "%s\t.+8, %%1, %%u2\n\t"
+ "jmp\t%%%%label(%%l3)",
+ regop_sign_bit_pos,
+ rcmp_opstr);
+ }
+ else
+ gcc_unreachable ();
+
+ return buf;
+}
+
+/* Optimized version of pru_output_signed_cbranch_ubyteop2 for constant
+ zero second operand. */
+
+const char *
+pru_output_signed_cbranch_zeroop2 (rtx *operands, bool is_near)
+{
+ static char buf[1024];
+ enum rtx_code code = GET_CODE (operands[0]);
+ int regop_sign_bit_pos = sign_bit_position (operands[1]);
+
+ /* OP2 is a constant zero - utilize this info to simply check the
+ OP1 sign bit when comparing for LT or GE. */
+ if (code == LT)
+ {
+ if (is_near)
+ snprintf (buf, sizeof (buf),
+ "qbbs\t%%l3, %%1, %d\n\t",
+ regop_sign_bit_pos);
+ else
+ snprintf (buf, sizeof (buf),
+ "qbbc\t.+8, %%1, %d\n\t"
+ "jmp\t%%%%label(%%l3)",
+ regop_sign_bit_pos);
+ }
+ else if (code == GE)
+ {
+ if (is_near)
+ snprintf (buf, sizeof (buf),
+ "qbbc\t%%l3, %%1, %d\n\t",
+ regop_sign_bit_pos);
+ else
+ snprintf (buf, sizeof (buf),
+ "qbbs\t.+8, %%1, %d\n\t"
+ "jmp\t%%%%label(%%l3)",
+ regop_sign_bit_pos);
+ }
+ else
+ gcc_unreachable ();
+
+ return buf;
+}
+
+/* Addressing Modes. */
+
+/* Return true if register REGNO is a valid base register.
+ STRICT_P is true if REG_OK_STRICT is in effect. */
+
+bool
+pru_regno_ok_for_base_p (int regno, bool strict_p)
+{
+ if (!HARD_REGISTER_NUM_P (regno) && !strict_p)
+ return true;
+
+ /* The fake registers will be eliminated to either the stack or
+ hard frame pointer, both of which are usually valid base registers.
+ Reload deals with the cases where the eliminated form isn't valid. */
+ return (GP_REG_P (regno)
+ || regno == FRAME_POINTER_REGNUM
+ || regno == ARG_POINTER_REGNUM);
+}
+
+/* Return true if given xbbo constant OFFSET is valid. */
+static bool
+pru_valid_const_ubyte_offset (machine_mode mode, HOST_WIDE_INT offset)
+{
+ bool valid = UBYTE_INT (offset);
+
+ /* Reload can split multi word accesses, so make sure we can address
+ the second word in a DI. */
+ if (valid && GET_MODE_SIZE (mode) > GET_MODE_SIZE (SImode))
+ valid = UBYTE_INT (offset + GET_MODE_SIZE (mode) - 1);
+
+ return valid;
+}
+
+/* Recognize a CTABLE base address. Return CTABLE entry index, or -1 if
+ base was not found in the pragma-filled pru_ctable. */
+int
+pru_get_ctable_exact_base_index (unsigned HOST_WIDE_INT caddr)
+{
+ unsigned int i;
+
+ for (i = 0; i < ARRAY_SIZE (pru_ctable); i++)
+ {
+ if (pru_ctable[i].valid && pru_ctable[i].base == caddr)
+ return i;
+ }
+ return -1;
+}
+
+
+/* Check if the given address can be addressed via CTABLE_BASE + UBYTE_OFFS,
+ and return the base CTABLE index if possible. */
+int
+pru_get_ctable_base_index (unsigned HOST_WIDE_INT caddr)
+{
+ unsigned int i;
+
+ for (i = 0; i < ARRAY_SIZE (pru_ctable); i++)
+ {
+ if (pru_ctable[i].valid && IN_RANGE (caddr,
+ pru_ctable[i].base,
+ pru_ctable[i].base + 0xff))
+ return i;
+ }
+ return -1;
+}
+
+
+/* Return the offset from some CTABLE base for this address. */
+int
+pru_get_ctable_base_offset (unsigned HOST_WIDE_INT caddr)
+{
+ int i;
+
+ i = pru_get_ctable_base_index (caddr);
+ gcc_assert (i >= 0);
+
+ return caddr - pru_ctable[i].base;
+}
+
+/* Return true if the address expression formed by BASE + OFFSET is
+ valid.
+
+ Note that the following address is not handled here:
+ base CTABLE constant base + UBYTE constant offset
+ The constants will be folded. The ctable_addr_operand predicate will take
+ care of the validation. The CTABLE base+offset split will happen during
+ operand printing. */
+static bool
+pru_valid_addr_expr_p (machine_mode mode, rtx base, rtx offset, bool strict_p)
+{
+ if (!strict_p && GET_CODE (base) == SUBREG)
+ base = SUBREG_REG (base);
+ if (!strict_p && GET_CODE (offset) == SUBREG)
+ offset = SUBREG_REG (offset);
+
+ if (REG_P (base)
+ && pru_regno_ok_for_base_p (REGNO (base), strict_p)
+ && ((CONST_INT_P (offset)
+ && pru_valid_const_ubyte_offset (mode, INTVAL (offset)))
+ || (REG_P (offset)
+ && pru_regno_ok_for_index_p (REGNO (offset), strict_p))))
+ /* base register + register offset
+ * OR base register + UBYTE constant offset. */
+ return true;
+ else if (REG_P (base)
+ && pru_regno_ok_for_index_p (REGNO (base), strict_p)
+ && ctable_base_operand (offset, VOIDmode))
+ /* base CTABLE constant base + register offset
+ * Note: GCC always puts the register as a first operand of PLUS. */
+ return true;
+ else
+ return false;
+}
+
+/* Implement TARGET_LEGITIMATE_ADDRESS_P. */
+static bool
+pru_legitimate_address_p (machine_mode mode,
+ rtx operand, bool strict_p)
+{
+ switch (GET_CODE (operand))
+ {
+ /* Direct. */
+ case SYMBOL_REF:
+ case LABEL_REF:
+ case CONST:
+ case CONST_WIDE_INT:
+ return false;
+
+ case CONST_INT:
+ return ctable_addr_operand (operand, VOIDmode);
+
+ /* Register indirect. */
+ case REG:
+ return pru_regno_ok_for_base_p (REGNO (operand), strict_p);
+
+ /* Register indirect with displacement. */
+ case PLUS:
+ {
+ rtx op0 = XEXP (operand, 0);
+ rtx op1 = XEXP (operand, 1);
+
+ return pru_valid_addr_expr_p (mode, op0, op1, strict_p);
+ }
+
+ default:
+ break;
+ }
+ return false;
+}
+
+/* Output assembly language related definitions. */
+
+/* Implement TARGET_ASM_CONSTRUCTOR. */
+static void
+pru_elf_asm_constructor (rtx symbol, int priority)
+{
+ char buf[23];
+ section *s;
+
+ if (priority == DEFAULT_INIT_PRIORITY)
+ snprintf (buf, sizeof (buf), ".init_array");
+ else
+ {
+ /* While priority is known to be in range [0, 65535], so 18 bytes
+ would be enough, the compiler might not know that. To avoid
+ -Wformat-truncation false positive, use a larger size. */
+ snprintf (buf, sizeof (buf), ".init_array.%.5u", priority);
+ }
+ s = get_section (buf, SECTION_WRITE | SECTION_NOTYPE, NULL);
+ switch_to_section (s);
+ assemble_aligned_integer (INIT_ARRAY_ENTRY_BYTES, symbol);
+}
+
+/* Implement TARGET_ASM_DESTRUCTOR. */
+static void
+pru_elf_asm_destructor (rtx symbol, int priority)
+{
+ char buf[23];
+ section *s;
+
+ if (priority == DEFAULT_INIT_PRIORITY)
+ snprintf (buf, sizeof (buf), ".fini_array");
+ else
+ {
+ /* While priority is known to be in range [0, 65535], so 18 bytes
+ would be enough, the compiler might not know that. To avoid
+ -Wformat-truncation false positive, use a larger size. */
+ snprintf (buf, sizeof (buf), ".fini_array.%.5u", priority);
+ }
+ s = get_section (buf, SECTION_WRITE | SECTION_NOTYPE, NULL);
+ switch_to_section (s);
+ assemble_aligned_integer (INIT_ARRAY_ENTRY_BYTES, symbol);
+}
+
+/* Map rtx_code to unsigned PRU branch op suffix. Callers must
+ handle sign comparison themselves for signed operations. */
+static const char *
+pru_comparison_str (enum rtx_code cond)
+{
+ switch (cond)
+ {
+ case NE: return "ne";
+ case EQ: return "eq";
+ case GEU: return "ge";
+ case GTU: return "gt";
+ case LEU: return "le";
+ case LTU: return "lt";
+ default: gcc_unreachable ();
+ }
+}
+
+/* Access some RTX as INT_MODE. If X is a CONST_FIXED we can get
+ the bit representation of X by "casting" it to CONST_INT. */
+
+static rtx
+pru_to_int_mode (rtx x)
+{
+ machine_mode mode = GET_MODE (x);
+
+ return VOIDmode == mode
+ ? x
+ : simplify_gen_subreg (int_mode_for_mode (mode).require (), x, mode, 0);
+}
+
+/* Translate between the MachineDescription notion
+ of 8-bit consecutive registers, to the PRU
+ assembler syntax of REGWORD[.SUBREG]. */
+static const char *
+pru_asm_regname (rtx op)
+{
+ static char canon_reg_names[3][LAST_GP_REGNUM][8];
+ int speci, regi;
+
+ gcc_assert (REG_P (op));
+
+ if (!canon_reg_names[0][0][0])
+ {
+ for (regi = 0; regi < LAST_GP_REGNUM; regi++)
+ for (speci = 0; speci < 3; speci++)
+ {
+ const int sz = (speci == 0) ? 1 : ((speci == 1) ? 2 : 4);
+ if ((regi + sz) > (32 * 4))
+ continue; /* Invalid entry. */
+
+ /* Construct the lookup table. */
+ const char *suffix = "";
+
+ switch ((sz << 8) | (regi % 4))
+ {
+ case (1 << 8) | 0: suffix = ".b0"; break;
+ case (1 << 8) | 1: suffix = ".b1"; break;
+ case (1 << 8) | 2: suffix = ".b2"; break;
+ case (1 << 8) | 3: suffix = ".b3"; break;
+ case (2 << 8) | 0: suffix = ".w0"; break;
+ case (2 << 8) | 1: suffix = ".w1"; break;
+ case (2 << 8) | 2: suffix = ".w2"; break;
+ case (4 << 8) | 0: suffix = ""; break;
+ default:
+ /* Invalid entry. */
+ continue;
+ }
+ sprintf (&canon_reg_names[speci][regi][0],
+ "r%d%s", regi / 4, suffix);
+ }
+ }
+
+ switch (GET_MODE_SIZE (GET_MODE (op)))
+ {
+ case 1: speci = 0; break;
+ case 2: speci = 1; break;
+ case 4: speci = 2; break;
+ case 8: speci = 2; break; /* Existing GCC test cases are not using %F. */
+ default: gcc_unreachable ();
+ }
+ regi = REGNO (op);
+ gcc_assert (regi < LAST_GP_REGNUM);
+ gcc_assert (canon_reg_names[speci][regi][0]);
+
+ return &canon_reg_names[speci][regi][0];
+}
+
+/* Print the operand OP to file stream FILE modified by LETTER.
+ LETTER can be one of:
+
+ b: prints the register byte start (used by LBBO/SBBO).
+ B: prints 'c' or 'b' for CTABLE or REG base in a memory address.
+ F: Full 32-bit register.
+ H: Higher 16-bits of a const_int operand.
+ L: Lower 16-bits of a const_int operand.
+ N: prints next 32-bit register (upper 32bits of a 64bit REG couple).
+ P: prints swapped condition.
+ Q: prints swapped and reversed condition.
+ R: prints reversed condition.
+ S: print operand mode size (but do not print the operand itself).
+ T: print exact_log2 () for const_int operands.
+ u: print QI constant integer as unsigned. No transformation for regs.
+ V: print exact_log2 () of negated const_int operands.
+ w: Lower 32-bits of a const_int operand.
+ W: Upper 32-bits of a const_int operand.
+ y: print the next 8-bit register (regardless of op size).
+ z: print the second next 8-bit register (regardless of op size).
+*/
+static void
+pru_print_operand (FILE *file, rtx op, int letter)
+{
+ switch (letter)
+ {
+ case 'S':
+ fprintf (file, "%d", GET_MODE_SIZE (GET_MODE (op)));
+ return;
+
+ default:
+ break;
+ }
+
+ if (comparison_operator (op, VOIDmode))
+ {
+ enum rtx_code cond = GET_CODE (op);
+ gcc_assert (!pru_signed_cmp_operator (op, VOIDmode));
+
+ switch (letter)
+ {
+ case 0:
+ fprintf (file, "%s", pru_comparison_str (cond));
+ return;
+ case 'P':
+ fprintf (file, "%s", pru_comparison_str (swap_condition (cond)));
+ return;
+ case 'Q':
+ cond = swap_condition (cond);
+ /* Fall through to reverse. */
+ case 'R':
+ fprintf (file, "%s", pru_comparison_str (reverse_condition (cond)));
+ return;
+ }
+ }
+
+ switch (GET_CODE (op))
+ {
+ case REG:
+ if (letter == 0 || letter == 'u')
+ {
+ fprintf (file, "%s", pru_asm_regname (op));
+ return;
+ }
+ else if (letter == 'b')
+ {
+ if (REGNO (op) > LAST_NONIO_GP_REGNUM)
+ {
+ output_operand_lossage ("I/O register operand for '%%%c'",
+ letter);
+ return;
+ }
+ fprintf (file, "r%d.b%d", REGNO (op) / 4, REGNO (op) % 4);
+ return;
+ }
+ else if (letter == 'F' || letter == 'N')
+ {
+ if (REGNO (op) > LAST_NONIO_GP_REGNUM - 1)
+ {
+ output_operand_lossage ("I/O register operand for '%%%c'",
+ letter);
+ return;
+ }
+ if (REGNO (op) % 4 != 0)
+ {
+ output_operand_lossage ("non 32 bit register operand for '%%%c'",
+ letter);
+ return;
+ }
+ fprintf (file, "r%d", REGNO (op) / 4 + (letter == 'N' ? 1 : 0));
+ return;
+ }
+ else if (letter == 'y')
+ {
+ if (REGNO (op) > LAST_NONIO_GP_REGNUM - 1)
+ {
+ output_operand_lossage ("invalid operand for '%%%c'", letter);
+ return;
+ }
+ fprintf (file, "%s", reg_names[REGNO (op) + 1]);
+ return;
+ }
+ else if (letter == 'z')
+ {
+ if (REGNO (op) > LAST_NONIO_GP_REGNUM - 2)
+ {
+ output_operand_lossage ("invalid operand for '%%%c'", letter);
+ return;
+ }
+ fprintf (file, "%s", reg_names[REGNO (op) + 2]);
+ return;
+ }
+ break;
+
+ case CONST_INT:
+ if (letter == 'H')
+ {
+ HOST_WIDE_INT val = INTVAL (op);
+ val = (val >> 16) & 0xFFFF;
+ output_addr_const (file, gen_int_mode (val, SImode));
+ return;
+ }
+ else if (letter == 'L')
+ {
+ HOST_WIDE_INT val = INTVAL (op);
+ val &= 0xFFFF;
+ output_addr_const (file, gen_int_mode (val, SImode));
+ return;
+ }
+ else if (letter == 'T')
+ {
+ /* The predicate should have already validated the 1-high-bit
+ requirement. Use CTZ here to deal with constant's sign
+ extension. */
+ HOST_WIDE_INT val = wi::ctz (INTVAL (op));
+ if (val < 0 || val > 31)
+ {
+ output_operand_lossage ("invalid operand for '%%%c'", letter);
+ return;
+ }
+ output_addr_const (file, gen_int_mode (val, SImode));
+ return;
+ }
+ else if (letter == 'V')
+ {
+ HOST_WIDE_INT val = wi::ctz (~INTVAL (op));
+ if (val < 0 || val > 31)
+ {
+ output_operand_lossage ("invalid operand for '%%%c'", letter);
+ return;
+ }
+ output_addr_const (file, gen_int_mode (val, SImode));
+ return;
+ }
+ else if (letter == 'w')
+ {
+ HOST_WIDE_INT val = INTVAL (op) & 0xffffffff;
+ output_addr_const (file, gen_int_mode (val, SImode));
+ return;
+ }
+ else if (letter == 'W')
+ {
+ HOST_WIDE_INT val = (INTVAL (op) >> 32) & 0xffffffff;
+ output_addr_const (file, gen_int_mode (val, SImode));
+ return;
+ }
+ else if (letter == 'u')
+ {
+ /* Workaround GCC's representation of QI constants in sign-extended
+ form, and PRU's assembler insistence on unsigned constant
+ integers. See the notes about O constraint. */
+ fprintf (file, HOST_WIDE_INT_PRINT_DEC, INTVAL (op) & 0xff);
+ return;
+ }
+ /* Else, fall through. */
+
+ case CONST:
+ case LABEL_REF:
+ case SYMBOL_REF:
+ if (letter == 0)
+ {
+ output_addr_const (file, op);
+ return;
+ }
+ break;
+
+ case CONST_FIXED:
+ {
+ HOST_WIDE_INT ival = INTVAL (pru_to_int_mode (op));
+ if (letter != 0)
+ output_operand_lossage ("unsupported code '%c' for fixed-point:",
+ letter);
+ fprintf (file, HOST_WIDE_INT_PRINT_DEC, ival);
+ return;
+ }
+ break;
+
+ case CONST_DOUBLE:
+ if (letter == 0)
+ {
+ long val;
+
+ if (GET_MODE (op) != SFmode)
+ {
+ output_operand_lossage ("double constants not supported");
+ return;
+ }
+ REAL_VALUE_TO_TARGET_SINGLE (*CONST_DOUBLE_REAL_VALUE (op), val);
+ fprintf (file, "0x%lx", val);
+ return;
+ }
+ else if (letter == 'w' || letter == 'W')
+ {
+ long t[2];
+ REAL_VALUE_TO_TARGET_DOUBLE (*CONST_DOUBLE_REAL_VALUE (op), t);
+ fprintf (file, "0x%lx", t[letter == 'w' ? 0 : 1]);
+ return;
+ }
+ else
+ {
+ output_operand_lossage ("invalid operand for '%%%c'", letter);
+ return;
+ }
+ break;
+
+ case SUBREG:
+ /* Subregs should not appear at so late stage. */
+ gcc_unreachable ();
+ break;
+
+ case MEM:
+ if (letter == 0)
+ {
+ output_address (VOIDmode, op);
+ return;
+ }
+ else if (letter == 'B')
+ {
+ rtx base = XEXP (op, 0);
+ if (GET_CODE (base) == PLUS)
+ {
+ rtx op0 = XEXP (base, 0);
+ rtx op1 = XEXP (base, 1);
+
+ /* PLUS cannot have two constant operands, so first one
+ of them must be a REG, hence we must check for an
+ exact base address. */
+ if (ctable_base_operand (op1, VOIDmode))
+ {
+ fprintf (file, "c");
+ return;
+ }
+ else if (REG_P (op0))
+ {
+ fprintf (file, "b");
+ return;
+ }
+ else
+ gcc_unreachable ();
+ }
+ else if (REG_P (base))
+ {
+ fprintf (file, "b");
+ return;
+ }
+ else if (ctable_addr_operand (base, VOIDmode))
+ {
+ fprintf (file, "c");
+ return;
+ }
+ else
+ gcc_unreachable ();
+ }
+ break;
+
+ case CODE_LABEL:
+ if (letter == 0)
+ {
+ output_addr_const (file, op);
+ return;
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ output_operand_lossage ("unsupported operand %s for code '%c'",
+ GET_RTX_NAME (GET_CODE (op)), letter);
+}
+
+/* Implement TARGET_PRINT_OPERAND_ADDRESS. */
+static void
+pru_print_operand_address (FILE *file, machine_mode mode, rtx op)
+{
+ if (CONSTANT_ADDRESS_P (op) && text_segment_operand (op, VOIDmode))
+ {
+ output_operand_lossage ("unexpected text address:");
+ return;
+ }
+
+ switch (GET_CODE (op))
+ {
+ case CONST:
+ case LABEL_REF:
+ case CONST_WIDE_INT:
+ case SYMBOL_REF:
+ break;
+
+ case CONST_INT:
+ {
+ unsigned HOST_WIDE_INT caddr = INTVAL (op);
+ int base = pru_get_ctable_base_index (caddr);
+ int offs = pru_get_ctable_base_offset (caddr);
+ if (base < 0)
+ {
+ output_operand_lossage ("unsupported constant address:");
+ return;
+ }
+ fprintf (file, "%d, %d", base, offs);
+ return;
+ }
+ break;
+
+ case PLUS:
+ {
+ int base;
+ rtx op0 = XEXP (op, 0);
+ rtx op1 = XEXP (op, 1);
+
+ if (REG_P (op0) && CONST_INT_P (op1)
+ && pru_get_ctable_exact_base_index (INTVAL (op1)) >= 0)
+ {
+ base = pru_get_ctable_exact_base_index (INTVAL (op1));
+ fprintf (file, "%d, %s", base, pru_asm_regname (op0));
+ return;
+ }
+ else if (REG_P (op1) && CONST_INT_P (op0)
+ && pru_get_ctable_exact_base_index (INTVAL (op0)) >= 0)
+ {
+ /* Not a valid RTL. */
+ gcc_unreachable ();
+ }
+ else if (REG_P (op0) && CONSTANT_P (op1))
+ {
+ fprintf (file, "%s, ", pru_asm_regname (op0));
+ output_addr_const (file, op1);
+ return;
+ }
+ else if (REG_P (op1) && CONSTANT_P (op0))
+ {
+ /* Not a valid RTL. */
+ gcc_unreachable ();
+ }
+ else if (REG_P (op1) && REG_P (op0))
+ {
+ fprintf (file, "%s, %s", pru_asm_regname (op0),
+ pru_asm_regname (op1));
+ return;
+ }
+ }
+ break;
+
+ case REG:
+ fprintf (file, "%s, 0", pru_asm_regname (op));
+ return;
+
+ case MEM:
+ {
+ rtx base = XEXP (op, 0);
+ pru_print_operand_address (file, mode, base);
+ return;
+ }
+ default:
+ break;
+ }
+
+ output_operand_lossage ("unsupported memory expression:");
+}
+
+/* Implement TARGET_ASM_FUNCTION_PROLOGUE. */
+static void
+pru_asm_function_prologue (FILE *file)
+{
+ if (flag_verbose_asm || flag_debug_asm)
+ pru_dump_frame_layout (file);
+}
+
+/* Implement `TARGET_ASM_INTEGER'.
+ Target hook for assembling integer objects. PRU version needs
+ special handling for references to pmem. Code copied from AVR. */
+
+static bool
+pru_assemble_integer (rtx x, unsigned int size, int aligned_p)
+{
+ if (size == POINTER_SIZE / BITS_PER_UNIT
+ && aligned_p
+ && text_segment_operand (x, VOIDmode))
+ {
+ fputs ("\t.4byte\t%pmem(", asm_out_file);
+ output_addr_const (asm_out_file, x);
+ fputs (")\n", asm_out_file);
+
+ return true;
+ }
+ else if (size == INIT_ARRAY_ENTRY_BYTES
+ && aligned_p
+ && text_segment_operand (x, VOIDmode))
+ {
+ fputs ("\t.2byte\t%pmem(", asm_out_file);
+ output_addr_const (asm_out_file, x);
+ fputs (")\n", asm_out_file);
+
+ return true;
+ }
+ else
+ {
+ return default_assemble_integer (x, size, aligned_p);
+ }
+}
+
+/* Implement TARGET_ASM_FILE_START. */
+
+static void
+pru_file_start (void)
+{
+ default_file_start ();
+
+ /* Compiler will take care of placing %label, so there is no
+ need to confuse users with this warning. */
+ fprintf (asm_out_file, "\t.set no_warn_regname_label\n");
+}
+
+/* Function argument related. */
+
+/* Return the number of bytes needed for storing an argument with
+ the given MODE and TYPE. */
+static int
+pru_function_arg_size (machine_mode mode, const_tree type)
+{
+ HOST_WIDE_INT param_size;
+
+ if (mode == BLKmode)
+ param_size = int_size_in_bytes (type);
+ else
+ param_size = GET_MODE_SIZE (mode);
+
+ /* Convert to words (round up). */
+ param_size = (UNITS_PER_WORD - 1 + param_size) / UNITS_PER_WORD;
+ gcc_assert (param_size >= 0);
+
+ return param_size;
+}
+
+/* Check if argument with the given size must be
+ passed/returned in a register.
+
+ Reference:
+ https://e2e.ti.com/support/development_tools/compiler/f/343/p/650176/2393029
+
+ Arguments other than 8/16/24/32/64bits are passed on stack. */
+static bool
+pru_arg_in_reg_bysize (size_t sz)
+{
+ return sz == 1 || sz == 2 || sz == 3 || sz == 4 || sz == 8;
+}
+
+/* Helper function to get the starting storage HW register for an argument,
+ or -1 if it must be passed on stack. The cum_v state is not changed. */
+static int
+pru_function_arg_regi (cumulative_args_t cum_v,
+ machine_mode mode, const_tree type,
+ bool named)
+{
+ CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
+ size_t argsize = pru_function_arg_size (mode, type);
+ size_t i, bi;
+ int regi = -1;
+
+ if (!pru_arg_in_reg_bysize (argsize))
+ return -1;
+
+ if (!named)
+ return -1;
+
+ /* Find the first available slot that fits. Yes, that's the PRU ABI. */
+ for (i = 0; regi < 0 && i < ARRAY_SIZE (cum->regs_used); i++)
+ {
+ /* VLAs and vector types are not defined in the PRU ABI. Let's
+ handle them the same as their same-sized counterparts. This way
+ we do not need to treat BLKmode differently, and need only to check
+ the size. */
+ gcc_assert (argsize == 1 || argsize == 2 || argsize == 3
+ || argsize == 4 || argsize == 8);
+
+ /* Ensure SI and DI arguments are stored in full registers only. */
+ if ((argsize >= 4) && (i % 4) != 0)
+ continue;
+
+ /* Structures with size 24 bits are passed starting at a full
+ register boundary. */
+ if (argsize == 3 && (i % 4) != 0)
+ continue;
+
+ /* rX.w0/w1/w2 are OK. But avoid spreading the second byte
+ into a different full register. */
+ if (argsize == 2 && (i % 4) == 3)
+ continue;
+
+ for (bi = 0;
+ bi < argsize && (bi + i) < ARRAY_SIZE (cum->regs_used);
+ bi++)
+ {
+ if (cum->regs_used[bi + i])
+ break;
+ }
+ if (bi == argsize)
+ regi = FIRST_ARG_REGNUM + i;
+ }
+
+ return regi;
+}
+
+/* Mark CUM_V that a function argument will occupy HW register slot starting
+ at REGI. The number of consecutive 8-bit HW registers marked as occupied
+ depends on the MODE and TYPE of the argument. */
+static void
+pru_function_arg_regi_mark_slot (int regi,
+ cumulative_args_t cum_v,
+ machine_mode mode, const_tree type,
+ bool named)
+{
+ CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
+ HOST_WIDE_INT param_size = pru_function_arg_size (mode, type);
+
+ gcc_assert (named);
+
+ /* Mark all byte sub-registers occupied by argument as used. */
+ while (param_size--)
+ {
+ gcc_assert (regi >= FIRST_ARG_REGNUM && regi <= LAST_ARG_REGNUM);
+ gcc_assert (!cum->regs_used[regi - FIRST_ARG_REGNUM]);
+ cum->regs_used[regi - FIRST_ARG_REGNUM] = true;
+ regi++;
+ }
+}
+
+/* Define where to put the arguments to a function. Value is zero to
+ push the argument on the stack, or a hard register in which to
+ store the argument.
+
+ MODE is the argument's machine mode.
+ TYPE is the data type of the argument (as a tree).
+ This is null for libcalls where that information may
+ not be available.
+ CUM is a variable of type CUMULATIVE_ARGS which gives info about
+ the preceding args and about the function being called.
+ NAMED is nonzero if this argument is a named parameter
+ (otherwise it is an extra parameter matching an ellipsis). */
+
+static rtx
+pru_function_arg (cumulative_args_t cum_v, machine_mode mode,
+ const_tree type,
+ bool named)
+{
+ rtx return_rtx = NULL_RTX;
+ int regi = pru_function_arg_regi (cum_v, mode, type, named);
+
+ if (regi >= 0)
+ return_rtx = gen_rtx_REG (mode, regi);
+
+ return return_rtx;
+}
+
+/* Implement TARGET_ARG_PARTIAL_BYTES. PRU never splits any arguments
+ between registers and memory, so we can return 0. */
+
+static int
+pru_arg_partial_bytes (cumulative_args_t cum_v ATTRIBUTE_UNUSED,
+ machine_mode mode ATTRIBUTE_UNUSED,
+ tree type ATTRIBUTE_UNUSED,
+ bool named ATTRIBUTE_UNUSED)
+{
+ return 0;
+}
+
+/* Update the data in CUM to advance over an argument of mode MODE
+ and data type TYPE; TYPE is null for libcalls where that information
+ may not be available. */
+
+static void
+pru_function_arg_advance (cumulative_args_t cum_v, machine_mode mode,
+ const_tree type,
+ bool named)
+{
+ int regi = pru_function_arg_regi (cum_v, mode, type, named);
+
+ if (regi >= 0)
+ pru_function_arg_regi_mark_slot (regi, cum_v, mode, type, named);
+}
+
+/* Implement TARGET_FUNCTION_VALUE. */
+static rtx
+pru_function_value (const_tree ret_type, const_tree fn ATTRIBUTE_UNUSED,
+ bool outgoing ATTRIBUTE_UNUSED)
+{
+ return gen_rtx_REG (TYPE_MODE (ret_type), FIRST_RETVAL_REGNUM);
+}
+
+/* Implement TARGET_LIBCALL_VALUE. */
+static rtx
+pru_libcall_value (machine_mode mode, const_rtx fun ATTRIBUTE_UNUSED)
+{
+ return gen_rtx_REG (mode, FIRST_RETVAL_REGNUM);
+}
+
+/* Implement TARGET_FUNCTION_VALUE_REGNO_P. */
+static bool
+pru_function_value_regno_p (const unsigned int regno)
+{
+ return regno == FIRST_RETVAL_REGNUM;
+}
+
+/* Implement TARGET_RETURN_IN_MEMORY. */
+bool
+pru_return_in_memory (const_tree type, const_tree fntype ATTRIBUTE_UNUSED)
+{
+ bool in_memory = (!pru_arg_in_reg_bysize (int_size_in_bytes (type))
+ || int_size_in_bytes (type) == -1);
+
+ return in_memory;
+}
+
+/* Implement TARGET_CAN_USE_DOLOOP_P. */
+
+static bool
+pru_can_use_doloop_p (const widest_int &, const widest_int &iterations_max,
+ unsigned int loop_depth, bool)
+{
+ /* Considering limitations in the hardware, only use doloop
+ for innermost loops which must be entered from the top. */
+ if (loop_depth > 1)
+ return false;
+ /* PRU internal loop counter is 16bits wide. Remember that iterations_max
+ holds the maximum number of loop latch executions, while PRU loop
+ instruction needs the count of loop body executions. */
+ if (iterations_max == 0 || wi::geu_p (iterations_max, 0xffff))
+ return false;
+
+ return true;
+}
+
+/* NULL if INSN insn is valid within a low-overhead loop.
+ Otherwise return why doloop cannot be applied. */
+
+static const char *
+pru_invalid_within_doloop (const rtx_insn *insn)
+{
+ if (CALL_P (insn))
+ return "Function call in the loop.";
+
+ if (JUMP_P (insn) && INSN_CODE (insn) == CODE_FOR_return)
+ return "Return from a call instruction in the loop.";
+
+ if (NONDEBUG_INSN_P (insn)
+ && INSN_CODE (insn) < 0
+ && (GET_CODE (PATTERN (insn)) == ASM_INPUT
+ || asm_noperands (PATTERN (insn)) >= 0))
+ return "Loop contains asm statement.";
+
+ return NULL;
+}
+
+
+/* Figure out where to put LABEL, which is the label for a repeat loop.
+ The loop ends just before LAST_INSN. If SHARED, insns other than the
+ "repeat" might use LABEL to jump to the loop's continuation point.
+
+ Return the last instruction in the adjusted loop. */
+
+static rtx_insn *
+pru_insert_loop_label_last (rtx_insn *last_insn, rtx_code_label *label,
+ bool shared)
+{
+ rtx_insn *next, *prev;
+ int count = 0, code, icode;
+
+ if (dump_file)
+ fprintf (dump_file, "considering end of repeat loop at insn %d\n",
+ INSN_UID (last_insn));
+
+ /* Set PREV to the last insn in the loop. */
+ prev = PREV_INSN (last_insn);
+
+ /* Set NEXT to the next insn after the loop label. */
+ next = last_insn;
+ if (!shared)
+ while (prev != 0)
+ {
+ code = GET_CODE (prev);
+ if (code == CALL_INSN || code == CODE_LABEL || code == BARRIER)
+ break;
+
+ if (INSN_P (prev))
+ {
+ if (GET_CODE (PATTERN (prev)) == SEQUENCE)
+ prev = as_a <rtx_insn *> (XVECEXP (PATTERN (prev), 0, 1));
+
+ /* Other insns that should not be in the last two opcodes. */
+ icode = recog_memoized (prev);
+ if (icode < 0
+ || icode == CODE_FOR_pruloophi
+ || icode == CODE_FOR_pruloopsi)
+ break;
+
+ count++;
+ next = prev;
+ if (dump_file)
+ print_rtl_single (dump_file, next);
+ if (count == 2)
+ break;
+ }
+ prev = PREV_INSN (prev);
+ }
+
+ /* Insert the nops. */
+ if (dump_file && count < 2)
+ fprintf (dump_file, "Adding %d nop%s inside loop\n\n",
+ 2 - count, count == 1 ? "" : "s");
+
+ for (; count < 2; count++)
+ emit_insn_before (gen_nop (), last_insn);
+
+ /* Insert the label. */
+ emit_label_before (label, last_insn);
+
+ return last_insn;
+}
+
+/* If IS_END is false, expand a canonical doloop_begin RTL into the
+ PRU-specific doloop_begin_internal. Otherwise expand doloop_end to
+ doloop_end_internal. */
+void
+pru_emit_doloop (rtx *operands, int is_end)
+{
+ rtx tag;
+
+ if (cfun->machine->doloop_tags == 0
+ || cfun->machine->doloop_tag_from_end == is_end)
+ {
+ cfun->machine->doloop_tags++;
+ cfun->machine->doloop_tag_from_end = is_end;
+ }
+
+ tag = GEN_INT (cfun->machine->doloop_tags - 1);
+ machine_mode opmode = GET_MODE (operands[0]);
+ if (is_end)
+ {
+ if (opmode == HImode)
+ emit_jump_insn (gen_doloop_end_internalhi (operands[0],
+ operands[1], tag));
+ else if (opmode == SImode)
+ emit_jump_insn (gen_doloop_end_internalsi (operands[0],
+ operands[1], tag));
+ else
+ gcc_unreachable ();
+ }
+ else
+ {
+ if (opmode == HImode)
+ emit_insn (gen_doloop_begin_internalhi (operands[0], operands[0], tag));
+ else if (opmode == SImode)
+ emit_insn (gen_doloop_begin_internalsi (operands[0], operands[0], tag));
+ else
+ gcc_unreachable ();
+ }
+}
+
+
+/* Code for converting doloop_begins and doloop_ends into valid
+ PRU instructions. Idea and code snippets borrowed from mep port.
+
+ A doloop_begin is just a placeholder:
+
+ $count = unspec ($count)
+
+ where $count is initially the number of iterations.
+ doloop_end has the form:
+
+ if (--$count == 0) goto label
+
+ The counter variable is private to the doloop insns, nothing else
+ relies on its value.
+
+ There are three cases, in decreasing order of preference:
+
+ 1. A loop has exactly one doloop_begin and one doloop_end.
+ The doloop_end branches to the first instruction after
+ the doloop_begin.
+
+ In this case we can replace the doloop_begin with a LOOP
+ instruction and remove the doloop_end. I.e.:
+
+ $count1 = unspec ($count1)
+ label:
+ ...
+ if (--$count2 != 0) goto label
+
+ becomes:
+
+ LOOP end_label,$count1
+ label:
+ ...
+ end_label:
+ # end loop
+
+ 2. As for (1), except there are several doloop_ends. One of them
+ (call it X) falls through to a label L. All the others fall
+ through to branches to L.
+
+ In this case, we remove X and replace the other doloop_ends
+ with branches to the LOOP label. For example:
+
+ $count1 = unspec ($count1)
+ label:
+ ...
+ if (--$count1 != 0) goto label
+ end_label:
+ ...
+ if (--$count2 != 0) goto label
+ goto end_label
+
+ becomes:
+
+ LOOP end_label,$count1
+ label:
+ ...
+ end_label:
+ # end repeat
+ ...
+ goto end_label
+
+ 3. The fallback case. Replace doloop_begins with:
+
+ $count = $count
+
+ Replace doloop_ends with the equivalent of:
+
+ $count = $count - 1
+ if ($count != 0) goto loop_label
+
+ */
+
+/* A structure describing one doloop_begin. */
+struct pru_doloop_begin {
+ /* The next doloop_begin with the same tag. */
+ struct pru_doloop_begin *next;
+
+ /* The instruction itself. */
+ rtx_insn *insn;
+
+ /* The initial counter value. */
+ rtx loop_count;
+
+ /* The counter register. */
+ rtx counter;
+};
+
+/* A structure describing a doloop_end. */
+struct pru_doloop_end {
+ /* The next doloop_end with the same loop tag. */
+ struct pru_doloop_end *next;
+
+ /* The instruction itself. */
+ rtx_insn *insn;
+
+ /* The first instruction after INSN when the branch isn't taken. */
+ rtx_insn *fallthrough;
+
+ /* The location of the counter value. Since doloop_end_internal is a
+ jump instruction, it has to allow the counter to be stored anywhere
+ (any non-fixed register). */
+ rtx counter;
+
+ /* The target label (the place where the insn branches when the counter
+ isn't zero). */
+ rtx label;
+
+ /* A scratch register. Only available when COUNTER isn't stored
+ in a general register. */
+ rtx scratch;
+};
+
+
+/* One do-while loop. */
+struct pru_doloop {
+ /* All the doloop_begins for this loop (in no particular order). */
+ struct pru_doloop_begin *begin;
+
+ /* All the doloop_ends. When there is more than one, arrange things
+ so that the first one is the most likely to be X in case (2) above. */
+ struct pru_doloop_end *end;
+};
+
+
+/* Return true if LOOP can be converted into LOOP form
+ (that is, if it matches cases (1) or (2) above). */
+
+static bool
+pru_repeat_loop_p (struct pru_doloop *loop)
+{
+ struct pru_doloop_end *end;
+ rtx_insn *fallthrough;
+
+ /* There must be exactly one doloop_begin and at least one doloop_end. */
+ if (loop->begin == 0 || loop->end == 0 || loop->begin->next != 0)
+ return false;
+
+ /* The first doloop_end (X) must branch back to the insn after
+ the doloop_begin. */
+ if (prev_real_insn (as_a<rtx_insn *> (loop->end->label)) != loop->begin->insn)
+ return false;
+
+ /* Check that the first doloop_end (X) can actually reach
+ doloop_begin () with U8_PCREL relocation for LOOP instruction. */
+ if (get_attr_length (loop->end->insn) != 4)
+ return false;
+
+ /* All the other doloop_ends must branch to the same place as X.
+ When the branch isn't taken, they must jump to the instruction
+ after X. */
+ fallthrough = loop->end->fallthrough;
+ for (end = loop->end->next; end != 0; end = end->next)
+ if (end->label != loop->end->label
+ || !simplejump_p (end->fallthrough)
+ || fallthrough
+ != next_real_insn (JUMP_LABEL_AS_INSN (end->fallthrough)))
+ return false;
+
+ return true;
+}
+
+
+/* The main repeat reorg function. See comment above for details. */
+
+static void
+pru_reorg_loop (rtx_insn *insns)
+{
+ rtx_insn *insn;
+ struct pru_doloop *loops, *loop;
+ struct pru_doloop_begin *begin;
+ struct pru_doloop_end *end;
+ size_t tmpsz;
+
+ /* Quick exit if we haven't created any loops. */
+ if (cfun->machine->doloop_tags == 0)
+ return;
+
+ /* Create an array of pru_doloop structures. */
+ tmpsz = sizeof (loops[0]) * cfun->machine->doloop_tags;
+ loops = (struct pru_doloop *) alloca (tmpsz);
+ memset (loops, 0, sizeof (loops[0]) * cfun->machine->doloop_tags);
+
+ /* Search the function for do-while insns and group them by loop tag. */
+ for (insn = insns; insn; insn = NEXT_INSN (insn))
+ if (INSN_P (insn))
+ switch (recog_memoized (insn))
+ {
+ case CODE_FOR_doloop_begin_internalhi:
+ case CODE_FOR_doloop_begin_internalsi:
+ insn_extract (insn);
+ loop = &loops[INTVAL (recog_data.operand[2])];
+
+ tmpsz = sizeof (struct pru_doloop_begin);
+ begin = (struct pru_doloop_begin *) alloca (tmpsz);
+ begin->next = loop->begin;
+ begin->insn = insn;
+ begin->loop_count = recog_data.operand[1];
+ begin->counter = recog_data.operand[0];
+
+ loop->begin = begin;
+ break;
+
+ case CODE_FOR_doloop_end_internalhi:
+ case CODE_FOR_doloop_end_internalsi:
+ insn_extract (insn);
+ loop = &loops[INTVAL (recog_data.operand[2])];
+
+ tmpsz = sizeof (struct pru_doloop_end);
+ end = (struct pru_doloop_end *) alloca (tmpsz);
+ end->insn = insn;
+ end->fallthrough = next_real_insn (insn);
+ end->counter = recog_data.operand[0];
+ end->label = recog_data.operand[1];
+ end->scratch = recog_data.operand[3];
+
+ /* If this insn falls through to an unconditional jump,
+ give it a lower priority than the others. */
+ if (loop->end != 0 && simplejump_p (end->fallthrough))
+ {
+ end->next = loop->end->next;
+ loop->end->next = end;
+ }
+ else
+ {
+ end->next = loop->end;
+ loop->end = end;
+ }
+ break;
+ }
+
+ /* Convert the insns for each loop in turn. */
+ for (loop = loops; loop < loops + cfun->machine->doloop_tags; loop++)
+ if (pru_repeat_loop_p (loop))
+ {
+ /* Case (1) or (2). */
+ rtx_code_label *repeat_label;
+ rtx label_ref;
+
+ /* Create a new label for the repeat insn. */
+ repeat_label = gen_label_rtx ();
+
+ /* Replace the doloop_begin with a repeat. We get rid
+ of the iteration register because LOOP instruction
+ will utilize an internal for the PRU core LOOP register. */
+ label_ref = gen_rtx_LABEL_REF (VOIDmode, repeat_label);
+ machine_mode loop_mode = GET_MODE (loop->begin->loop_count);
+ if (loop_mode == HImode)
+ emit_insn_before (gen_pruloophi (loop->begin->loop_count, label_ref),
+ loop->begin->insn);
+ else if (loop_mode == SImode)
+ {
+ rtx loop_rtx = gen_pruloopsi (loop->begin->loop_count, label_ref);
+ emit_insn_before (loop_rtx, loop->begin->insn);
+ }
+ else if (loop_mode == VOIDmode)
+ {
+ gcc_assert (CONST_INT_P (loop->begin->loop_count));
+ gcc_assert (UBYTE_INT ( INTVAL (loop->begin->loop_count)));
+ rtx loop_rtx = gen_pruloopsi (loop->begin->loop_count, label_ref);
+ emit_insn_before (loop_rtx, loop->begin->insn);
+ }
+ else
+ gcc_unreachable ();
+ delete_insn (loop->begin->insn);
+
+ /* Insert the repeat label before the first doloop_end.
+ Fill the gap with nops if LOOP insn is less than 2
+ instructions away than loop->end. */
+ pru_insert_loop_label_last (loop->end->insn, repeat_label,
+ loop->end->next != 0);
+
+ /* Emit a pruloop_end (to improve the readability of the output). */
+ emit_insn_before (gen_pruloop_end (), loop->end->insn);
+
+ /* HACK: TODO: This is usually not needed, but is required for
+ a few rare cases where a JUMP that breaks the loop
+ references the LOOP_END address. In other words, since
+ we're missing a real "loop_end" instruction, a loop "break"
+ may accidentally reference the loop end itself, and thus
+ continuing the cycle. */
+ for (insn = NEXT_INSN (loop->end->insn);
+ insn != next_real_insn (loop->end->insn);
+ insn = NEXT_INSN (insn))
+ {
+ if (LABEL_P (insn) && LABEL_NUSES (insn) > 0)
+ emit_insn_before (gen_nop_loop_guard (), loop->end->insn);
+ }
+
+ /* Delete the first doloop_end. */
+ delete_insn (loop->end->insn);
+
+ /* Replace the others with branches to REPEAT_LABEL. */
+ for (end = loop->end->next; end != 0; end = end->next)
+ {
+ rtx_insn *newjmp;
+ newjmp = emit_jump_insn_before (gen_jump (repeat_label), end->insn);
+ JUMP_LABEL (newjmp) = repeat_label;
+ delete_insn (end->insn);
+ delete_insn (end->fallthrough);
+ }
+ }
+ else
+ {
+ /* Case (3). First replace all the doloop_begins with setting
+ the HW register used for loop counter. */
+ for (begin = loop->begin; begin != 0; begin = begin->next)
+ {
+ insn = gen_move_insn (copy_rtx (begin->counter),
+ copy_rtx (begin->loop_count));
+ emit_insn_before (insn, begin->insn);
+ delete_insn (begin->insn);
+ }
+
+ /* Replace all the doloop_ends with decrement-and-branch sequences. */
+ for (end = loop->end; end != 0; end = end->next)
+ {
+ rtx reg;
+
+ start_sequence ();
+
+ /* Load the counter value into a general register. */
+ reg = end->counter;
+ if (!REG_P (reg) || REGNO (reg) > LAST_NONIO_GP_REGNUM)
+ {
+ reg = end->scratch;
+ emit_move_insn (copy_rtx (reg), copy_rtx (end->counter));
+ }
+
+ /* Decrement the counter. */
+ emit_insn (gen_add3_insn (copy_rtx (reg), copy_rtx (reg),
+ constm1_rtx));
+
+ /* Copy it back to its original location. */
+ if (reg != end->counter)
+ emit_move_insn (copy_rtx (end->counter), copy_rtx (reg));
+
+ /* Jump back to the start label. */
+ insn = emit_jump_insn (gen_cbranchsi4 (gen_rtx_NE (VOIDmode, reg,
+ const0_rtx),
+ reg,
+ const0_rtx,
+ end->label));
+
+ JUMP_LABEL (insn) = end->label;
+ LABEL_NUSES (end->label)++;
+
+ /* Emit the whole sequence before the doloop_end. */
+ insn = get_insns ();
+ end_sequence ();
+ emit_insn_before (insn, end->insn);
+
+ /* Delete the doloop_end. */
+ delete_insn (end->insn);
+ }
+ }
+}
+
+/* Implement TARGET_MACHINE_DEPENDENT_REORG. */
+static void
+pru_reorg (void)
+{
+ rtx_insn *insns = get_insns ();
+
+ compute_bb_for_insn ();
+ df_analyze ();
+
+ /* Need correct insn lengths for allowing LOOP instruction
+ emitting due to U8_PCREL limitations. */
+ shorten_branches (get_insns ());
+
+ /* The generic reorg_loops () is not suitable for PRU because
+ it doesn't handle doloop_begin/end tying. And we need our
+ doloop_begin emitted before reload. It is difficult to coalesce
+ UBYTE constant initial loop values into the LOOP insn during
+ machine reorg phase. */
+ pru_reorg_loop (insns);
+
+ df_finish_pass (false);
+}
+
+/* Enumerate all PRU-specific builtins. */
+enum pru_builtin
+{
+ PRU_BUILTIN_DELAY_CYCLES,
+ PRU_BUILTIN_max
+};
+
+static GTY(()) tree pru_builtins [(int) PRU_BUILTIN_max];
+
+/* Implement TARGET_INIT_BUILTINS. */
+
+static void
+pru_init_builtins (void)
+{
+ tree void_ftype_longlong
+ = build_function_type_list (void_type_node,
+ long_long_integer_type_node,
+ NULL);
+
+ pru_builtins[PRU_BUILTIN_DELAY_CYCLES]
+ = add_builtin_function ("__delay_cycles", void_ftype_longlong,
+ PRU_BUILTIN_DELAY_CYCLES, BUILT_IN_MD, NULL,
+ NULL_TREE);
+}
+
+/* Implement TARGET_BUILTIN_DECL. */
+
+static tree
+pru_builtin_decl (unsigned code, bool initialize_p ATTRIBUTE_UNUSED)
+{
+ switch (code)
+ {
+ case PRU_BUILTIN_DELAY_CYCLES:
+ return pru_builtins[code];
+ default:
+ return error_mark_node;
+ }
+}
+
+/* Emit a sequence of one or more delay_cycles_X insns, in order to generate
+ code that delays exactly ARG cycles. */
+
+static rtx
+pru_expand_delay_cycles (rtx arg)
+{
+ HOST_WIDE_INT c, n;
+
+ if (GET_CODE (arg) != CONST_INT)
+ {
+ error ("%<__delay_cycles%> only takes constant arguments");
+ return NULL_RTX;
+ }
+
+ c = INTVAL (arg);
+
+ gcc_assert (HOST_BITS_PER_WIDE_INT > 32);
+ if (c < 0)
+ {
+ error ("%<__delay_cycles%> only takes non-negative cycle counts");
+ return NULL_RTX;
+ }
+
+ emit_insn (gen_delay_cycles_start (arg));
+
+ /* For 32-bit loops, there's 2 + 2x cycles. */
+ if (c > 2 * 0xffff + 1)
+ {
+ n = (c - 2) / 2;
+ c -= (n * 2) + 2;
+ if ((unsigned long long) n > 0xffffffffULL)
+ {
+ error ("%<__delay_cycles%> is limited to 32-bit loop counts");
+ return NULL_RTX;
+ }
+ emit_insn (gen_delay_cycles_2x_plus2_si (GEN_INT (n)));
+ }
+
+ /* For 16-bit loops, there's 1 + 2x cycles. */
+ if (c > 2)
+ {
+ n = (c - 1) / 2;
+ c -= (n * 2) + 1;
+
+ emit_insn (gen_delay_cycles_2x_plus1_hi (GEN_INT (n)));
+ }
+
+ while (c > 0)
+ {
+ emit_insn (gen_delay_cycles_1 ());
+ c -= 1;
+ }
+
+ emit_insn (gen_delay_cycles_end (arg));
+
+ return NULL_RTX;
+}
+
+
+/* Implement TARGET_EXPAND_BUILTIN. Expand an expression EXP that calls
+ a built-in function, with result going to TARGET if that's convenient
+ (and in mode MODE if that's convenient).
+ SUBTARGET may be used as the target for computing one of EXP's operands.
+ IGNORE is nonzero if the value is to be ignored. */
+
+static rtx
+pru_expand_builtin (tree exp, rtx target ATTRIBUTE_UNUSED,
+ rtx subtarget ATTRIBUTE_UNUSED,
+ machine_mode mode ATTRIBUTE_UNUSED,
+ int ignore ATTRIBUTE_UNUSED)
+{
+ tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0);
+ unsigned int fcode = DECL_FUNCTION_CODE (fndecl);
+ rtx arg1 = expand_normal (CALL_EXPR_ARG (exp, 0));
+
+ if (fcode == PRU_BUILTIN_DELAY_CYCLES)
+ return pru_expand_delay_cycles (arg1);
+
+ internal_error ("bad builtin code");
+
+ return NULL_RTX;
+}
+
+/* Remember the last target of pru_set_current_function. */
+static GTY(()) tree pru_previous_fndecl;
+
+/* Establish appropriate back-end context for processing the function
+ FNDECL. The argument might be NULL to indicate processing at top
+ level, outside of any function scope. */
+static void
+pru_set_current_function (tree fndecl)
+{
+ tree old_tree = (pru_previous_fndecl
+ ? DECL_FUNCTION_SPECIFIC_TARGET (pru_previous_fndecl)
+ : NULL_TREE);
+
+ tree new_tree = (fndecl
+ ? DECL_FUNCTION_SPECIFIC_TARGET (fndecl)
+ : NULL_TREE);
+
+ if (fndecl && fndecl != pru_previous_fndecl)
+ {
+ pru_previous_fndecl = fndecl;
+ if (old_tree == new_tree)
+ ;
+
+ else if (new_tree)
+ {
+ cl_target_option_restore (&global_options,
+ TREE_TARGET_OPTION (new_tree));
+ target_reinit ();
+ }
+
+ else if (old_tree)
+ {
+ struct cl_target_option *def
+ = TREE_TARGET_OPTION (target_option_current_node);
+
+ cl_target_option_restore (&global_options, def);
+ target_reinit ();
+ }
+ }
+}
+
+/* Implement TARGET_UNWIND_WORD_MODE.
+
+ Since PRU is really a 32-bit CPU, the default word_mode is not suitable. */
+static scalar_int_mode
+pru_unwind_word_mode (void)
+{
+ return SImode;
+}
+
+
+/* Initialize the GCC target structure. */
+#undef TARGET_ASM_FUNCTION_PROLOGUE
+#define TARGET_ASM_FUNCTION_PROLOGUE pru_asm_function_prologue
+#undef TARGET_ASM_INTEGER
+#define TARGET_ASM_INTEGER pru_assemble_integer
+
+#undef TARGET_ASM_FILE_START
+#define TARGET_ASM_FILE_START pru_file_start
+
+#undef TARGET_INIT_BUILTINS
+#define TARGET_INIT_BUILTINS pru_init_builtins
+#undef TARGET_EXPAND_BUILTIN
+#define TARGET_EXPAND_BUILTIN pru_expand_builtin
+#undef TARGET_BUILTIN_DECL
+#define TARGET_BUILTIN_DECL pru_builtin_decl
+
+#undef TARGET_COMPUTE_FRAME_LAYOUT
+#define TARGET_COMPUTE_FRAME_LAYOUT pru_compute_frame_layout
+
+#undef TARGET_FUNCTION_OK_FOR_SIBCALL
+#define TARGET_FUNCTION_OK_FOR_SIBCALL hook_bool_tree_tree_true
+
+#undef TARGET_CAN_ELIMINATE
+#define TARGET_CAN_ELIMINATE pru_can_eliminate
+
+#undef TARGET_HARD_REGNO_MODE_OK
+#define TARGET_HARD_REGNO_MODE_OK pru_hard_regno_mode_ok
+
+#undef TARGET_HARD_REGNO_SCRATCH_OK
+#define TARGET_HARD_REGNO_SCRATCH_OK pru_hard_regno_scratch_ok
+#undef TARGET_HARD_REGNO_CALL_PART_CLOBBERED
+#define TARGET_HARD_REGNO_CALL_PART_CLOBBERED \
+ pru_hard_regno_call_part_clobbered
+
+#undef TARGET_FUNCTION_ARG
+#define TARGET_FUNCTION_ARG pru_function_arg
+
+#undef TARGET_FUNCTION_ARG_ADVANCE
+#define TARGET_FUNCTION_ARG_ADVANCE pru_function_arg_advance
+
+#undef TARGET_ARG_PARTIAL_BYTES
+#define TARGET_ARG_PARTIAL_BYTES pru_arg_partial_bytes
+
+#undef TARGET_FUNCTION_VALUE
+#define TARGET_FUNCTION_VALUE pru_function_value
+
+#undef TARGET_LIBCALL_VALUE
+#define TARGET_LIBCALL_VALUE pru_libcall_value
+
+#undef TARGET_FUNCTION_VALUE_REGNO_P
+#define TARGET_FUNCTION_VALUE_REGNO_P pru_function_value_regno_p
+
+#undef TARGET_RETURN_IN_MEMORY
+#define TARGET_RETURN_IN_MEMORY pru_return_in_memory
+
+#undef TARGET_MUST_PASS_IN_STACK
+#define TARGET_MUST_PASS_IN_STACK must_pass_in_stack_var_size
+
+#undef TARGET_LEGITIMATE_ADDRESS_P
+#define TARGET_LEGITIMATE_ADDRESS_P pru_legitimate_address_p
+
+#undef TARGET_INIT_LIBFUNCS
+#define TARGET_INIT_LIBFUNCS pru_init_libfuncs
+#undef TARGET_LIBFUNC_GNU_PREFIX
+#define TARGET_LIBFUNC_GNU_PREFIX true
+
+#undef TARGET_RTX_COSTS
+#define TARGET_RTX_COSTS pru_rtx_costs
+
+#undef TARGET_PRINT_OPERAND
+#define TARGET_PRINT_OPERAND pru_print_operand
+
+#undef TARGET_PRINT_OPERAND_ADDRESS
+#define TARGET_PRINT_OPERAND_ADDRESS pru_print_operand_address
+
+#undef TARGET_OPTION_OVERRIDE
+#define TARGET_OPTION_OVERRIDE pru_option_override
+
+#undef TARGET_SET_CURRENT_FUNCTION
+#define TARGET_SET_CURRENT_FUNCTION pru_set_current_function
+
+#undef TARGET_MACHINE_DEPENDENT_REORG
+#define TARGET_MACHINE_DEPENDENT_REORG pru_reorg
+
+#undef TARGET_CAN_USE_DOLOOP_P
+#define TARGET_CAN_USE_DOLOOP_P pru_can_use_doloop_p
+
+#undef TARGET_INVALID_WITHIN_DOLOOP
+#define TARGET_INVALID_WITHIN_DOLOOP pru_invalid_within_doloop
+
+#undef TARGET_UNWIND_WORD_MODE
+#define TARGET_UNWIND_WORD_MODE pru_unwind_word_mode
+
+#undef TARGET_HAVE_SPECULATION_SAFE_VALUE
+#define TARGET_HAVE_SPECULATION_SAFE_VALUE speculation_safe_value_not_needed
+
+struct gcc_target targetm = TARGET_INITIALIZER;
+
+#include "gt-pru.h"
diff --git a/gcc/config/pru/pru.h b/gcc/config/pru/pru.h
new file mode 100644
index 0000000..15fb637
--- /dev/null
+++ b/gcc/config/pru/pru.h
@@ -0,0 +1,573 @@
+/* Definitions of target machine for TI PRU.
+ Copyright (C) 2014-2019 Free Software Foundation, Inc.
+ Contributed by Dimitar Dimitrov <dimitar@dinux.eu>
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+ License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GCC; see the file COPYING3. If not see
+ <http://www.gnu.org/licenses/>. */
+
+#ifndef GCC_PRU_H
+#define GCC_PRU_H
+
+#include "config/pru/pru-opts.h"
+
+/* Define built-in preprocessor macros. */
+#define TARGET_CPU_CPP_BUILTINS() \
+ do \
+ { \
+ builtin_define_std ("__PRU__"); \
+ builtin_define_std ("__pru__"); \
+ builtin_define_std ("__PRU_V3__"); \
+ builtin_define_std ("__LITTLE_ENDIAN__"); \
+ builtin_define_std ("__little_endian__"); \
+ /* Trampolines are disabled for now. */ \
+ builtin_define_std ("NO_TRAMPOLINES"); \
+ } \
+ while (0)
+
+/* TI ABI implementation is not feature-complete enough (e.g. function
+ pointers are not supported), so we cannot list it as a multilib variant.
+ To prevent misuse from users, do not link any of the standard libraries. */
+#define DRIVER_SELF_SPECS \
+ "%{mabi=ti:-nodefaultlibs} " \
+ "%{mmcu=*:-specs=device-specs/%*%s %<mmcu=*} "
+
+#undef CPP_SPEC
+#define CPP_SPEC \
+ "%(cpp_device) " \
+ "%{mabi=ti:-D__PRU_EABI_TI__; :-D__PRU_EABI_GNU__}"
+
+/* Do not relax when in TI ABI mode since TI tools do not always
+ put PRU_S10_PCREL. */
+#undef LINK_SPEC
+#define LINK_SPEC \
+ "%(link_device) " \
+ "%{mabi=ti:--no-relax;:%{mno-relax:--no-relax;:--relax}} " \
+ "%{shared:%eshared is not supported} "
+
+/* CRT0 is carefully maintained to be compatible with both GNU and TI ABIs. */
+#undef STARTFILE_SPEC
+#define STARTFILE_SPEC \
+ "%{!pg:%{minrt:crt0-minrt.o%s}%{!minrt:crt0.o%s}} %{!mabi=ti:-lgcc} "
+
+#undef ENDFILE_SPEC
+#define ENDFILE_SPEC "%{!mabi=ti:-lgloss} "
+
+/* TI ABI mandates that ELF symbols do not start with any prefix. */
+#undef USER_LABEL_PREFIX
+#define USER_LABEL_PREFIX ""
+
+#undef LOCAL_LABEL_PREFIX
+#define LOCAL_LABEL_PREFIX ".L"
+
+/* Storage layout. */
+
+#define DEFAULT_SIGNED_CHAR 0
+#define BITS_BIG_ENDIAN 0
+#define BYTES_BIG_ENDIAN 0
+#define WORDS_BIG_ENDIAN 0
+
+/* PRU is represented in GCC as an 8-bit CPU with fast 16-bit and 32-bit
+ arithmetic. */
+#define BITS_PER_WORD 8
+
+#ifdef IN_LIBGCC2
+/* This is to get correct SI and DI modes in libgcc2.c (32 and 64 bits). */
+#define UNITS_PER_WORD 4
+#else
+/* Width of a word, in units (bytes). */
+#define UNITS_PER_WORD 1
+#endif
+
+#define POINTER_SIZE 32
+#define BIGGEST_ALIGNMENT 8
+#define STRICT_ALIGNMENT 0
+#define FUNCTION_BOUNDARY 8 /* Func pointers are word-addressed. */
+#define PARM_BOUNDARY 8
+#define STACK_BOUNDARY 8
+#define MAX_FIXED_MODE_SIZE 64
+
+#define POINTERS_EXTEND_UNSIGNED 1
+
+/* Layout of source language data types. */
+
+#define INT_TYPE_SIZE 32
+#define SHORT_TYPE_SIZE 16
+#define LONG_TYPE_SIZE 32
+#define LONG_LONG_TYPE_SIZE 64
+#define FLOAT_TYPE_SIZE 32
+#define DOUBLE_TYPE_SIZE 64
+#define LONG_DOUBLE_TYPE_SIZE DOUBLE_TYPE_SIZE
+
+#undef SIZE_TYPE
+#define SIZE_TYPE "unsigned int"
+
+#undef PTRDIFF_TYPE
+#define PTRDIFF_TYPE "int"
+
+
+/* Basic characteristics of PRU registers:
+
+ Regno Name
+ 0 r0 Caller Saved. Also used as a static chain register.
+ 1 r1 Caller Saved. Also used as a temporary by function.
+ profiler and function prologue/epilogue.
+ 2 r2 sp Stack Pointer.
+ 3* r3.w0 ra Return Address (16-bit).
+ 4 r4 fp Frame Pointer, also called Argument Pointer in ABI.
+ 5-13 r5-r13 Callee Saved Registers.
+ 14-29 r14-r29 Register Arguments. Caller Saved Registers.
+ 14-15 r14-r15 Return Location.
+ 30 r30 Special I/O register. Not used by compiler.
+ 31 r31 Special I/O register. Not used by compiler.
+
+ 32 loop_cntr Internal register used as a counter by LOOP insns.
+
+ 33 pc Not an actual register.
+
+ 34 fake_fp Fake Frame Pointer (always eliminated).
+ 35 fake_ap Fake Argument Pointer (always eliminated).
+ 36 First Pseudo Register.
+
+ The definitions for some hard register numbers are located in pru.md.
+ Note that GCC's internal register numbering differs from the conventional
+ register naming in PRU ISA. PRU ISA defines word-based register numbers
+ and sub-register suffixes (e.g. RA is r3.w0). GCC uses linear numbering
+ of 8 bit sub-registers (e.g. RA starts at r12). When outputting assembly,
+ GCC will take into account the RTL operand size (e.g. r12:HI) in order to
+ translate to the conventional PRU ISA format expected by GAS (r3.w0).
+*/
+
+#define FIXED_REGISTERS \
+ { \
+/* 0 */ 0,0,0,0, 0,0,0,0, 1,1,1,1, 1,1,1,1, \
+/* 4 */ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, \
+/* 8 */ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, \
+/* 12 */ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, \
+/* 16 */ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, \
+/* 20 */ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, \
+/* 24 */ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, \
+/* 28 */ 0,0,0,0, 0,0,0,0, 1,1,1,1, 1,1,1,1, \
+/* 32 */ 1,1,1,1, 1,1,1,1, 1,1,1,1, 1,1,1,1 \
+ }
+
+/* Call used == caller saved + fixed regs + args + ret vals. */
+#define CALL_USED_REGISTERS \
+ { \
+/* 0 */ 1,1,1,1, 1,1,1,1, 1,1,1,1, 1,1,1,1, \
+/* 4 */ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, \
+/* 8 */ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, \
+/* 12 */ 0,0,0,0, 0,0,0,0, 1,1,1,1, 1,1,1,1, \
+/* 16 */ 1,1,1,1, 1,1,1,1, 1,1,1,1, 1,1,1,1, \
+/* 20 */ 1,1,1,1, 1,1,1,1, 1,1,1,1, 1,1,1,1, \
+/* 24 */ 1,1,1,1, 1,1,1,1, 1,1,1,1, 1,1,1,1, \
+/* 28 */ 1,1,1,1, 1,1,1,1, 1,1,1,1, 1,1,1,1, \
+/* 32 */ 1,1,1,1, 1,1,1,1, 1,1,1,1, 1,1,1,1 \
+ }
+
+#define PRU_SEQ_R(X) (X) * 4 + 0, (X) * 4 + 1, (X) * 4 + 2, (X) * 4 + 3
+#define REG_ALLOC_ORDER \
+ { \
+ /* Call-clobbered, yet not used for parameters. */ \
+ PRU_SEQ_R (0), PRU_SEQ_R ( 1), \
+ \
+ PRU_SEQ_R (14), PRU_SEQ_R (15), PRU_SEQ_R (16), PRU_SEQ_R (17), \
+ PRU_SEQ_R (18), PRU_SEQ_R (19), PRU_SEQ_R (20), PRU_SEQ_R (21), \
+ PRU_SEQ_R (22), PRU_SEQ_R (23), PRU_SEQ_R (24), PRU_SEQ_R (25), \
+ PRU_SEQ_R (26), PRU_SEQ_R (27), PRU_SEQ_R (28), PRU_SEQ_R (29), \
+ \
+ PRU_SEQ_R ( 5), PRU_SEQ_R ( 6), PRU_SEQ_R ( 7), PRU_SEQ_R ( 8), \
+ PRU_SEQ_R ( 9), PRU_SEQ_R (10), PRU_SEQ_R (11), PRU_SEQ_R (12), \
+ PRU_SEQ_R (13), \
+ \
+ PRU_SEQ_R ( 4), \
+ PRU_SEQ_R ( 2), PRU_SEQ_R ( 3), \
+ \
+ /* I/O and virtual registers. */ \
+ PRU_SEQ_R (30), PRU_SEQ_R (31), PRU_SEQ_R (32), PRU_SEQ_R (33), \
+ PRU_SEQ_R (34), PRU_SEQ_R (35) \
+ }
+
+/* Register Classes. */
+
+enum reg_class
+{
+ NO_REGS,
+ SIB_REGS,
+ LOOPCNTR_REGS,
+ MULDST_REGS,
+ MULSRC0_REGS,
+ MULSRC1_REGS,
+ GP_REGS,
+ ALL_REGS,
+ LIM_REG_CLASSES
+};
+
+#define N_REG_CLASSES (int) LIM_REG_CLASSES
+
+#define REG_CLASS_NAMES \
+ { "NO_REGS", \
+ "SIB_REGS", \
+ "LOOPCNTR_REGS", \
+ "MULDST_REGS", \
+ "MULSRC0_REGS", \
+ "MULSRC1_REGS", \
+ "GP_REGS", \
+ "ALL_REGS" }
+
+#define GENERAL_REGS ALL_REGS
+
+#define REG_CLASS_CONTENTS \
+ { \
+ /* NO_REGS */ { 0, 0, 0, 0, 0}, \
+ /* SIB_REGS */ { 0xf, 0xff000000, ~0, 0xffffff, 0}, \
+ /* LOOPCNTR_REGS */ { 0, 0, 0, 0, 0xf}, \
+ /* MULDST_REGS */ { 0, 0, 0, 0x00000f00, 0}, \
+ /* MULSRC0_REGS */ { 0, 0, 0, 0x000f0000, 0}, \
+ /* MULSRC1_REGS */ { 0, 0, 0, 0x00f00000, 0}, \
+ /* GP_REGS */ { ~0, ~0, ~0, ~0, 0}, \
+ /* ALL_REGS */ { ~0,~0, ~0, ~0, ~0} \
+ }
+
+
+#define GP_REG_P(REGNO) ((unsigned)(REGNO) <= LAST_GP_REGNUM)
+#define REGNO_REG_CLASS(REGNO) \
+ ((REGNO) == MULDST_REGNUM ? MULDST_REGS \
+ : (REGNO) == MULSRC0_REGNUM ? MULSRC0_REGS \
+ : (REGNO) == MULSRC1_REGNUM ? MULSRC1_REGS \
+ : (REGNO) >= FIRST_ARG_REGNUM \
+ && (REGNO) <= LAST_ARG_REGNUM ? SIB_REGS \
+ : (REGNO) == STATIC_CHAIN_REGNUM ? SIB_REGS \
+ : (REGNO) == LOOPCNTR_REGNUM ? LOOPCNTR_REGS \
+ : (REGNO) <= LAST_NONIO_GP_REGNUM ? GP_REGS \
+ : ALL_REGS)
+
+#define CLASS_MAX_NREGS(CLASS, MODE) \
+ ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)
+
+/* Arbitrarily set to a non-argument register. Not defined by TI ABI. */
+#define STATIC_CHAIN_REGNUM 0 /* r0 */
+
+/* Tests for various kinds of constants used in the PRU port. */
+#define SHIFT_INT(X) (IN_RANGE ((X), 0, 31))
+
+#define UHWORD_INT(X) (IN_RANGE ((X), 0, 0xffff))
+#define SHWORD_INT(X) (IN_RANGE ((X), -32768, 32767))
+#define UBYTE_INT(X) (IN_RANGE ((X), 0, 0xff))
+#define SBYTE_INT(X) (IN_RANGE ((X), -128, 127))
+
+/* Say that the epilogue uses the return address register. Note that
+ in the case of sibcalls, the values "used by the epilogue" are
+ considered live at the start of the called function. */
+#define EPILOGUE_USES(REGNO) (epilogue_completed \
+ && (((REGNO) == RA_REGNUM) \
+ || (REGNO) == (RA_REGNUM + 1)))
+
+/* EXIT_IGNORE_STACK should be nonzero if, when returning from a function,
+ the stack pointer does not matter. The value is tested only in
+ functions that have frame pointers.
+ No definition is equivalent to always zero. */
+
+#define EXIT_IGNORE_STACK 1
+
+/* Trampolines are not supported, but put a define to keep the build. */
+#define TRAMPOLINE_SIZE 4
+
+/* Stack layout. */
+#define STACK_GROWS_DOWNWARD 1
+#undef FRAME_GROWS_DOWNWARD
+#define FIRST_PARM_OFFSET(FUNDECL) 0
+
+/* Before the prologue, RA lives in r3.w2. */
+#define INCOMING_RETURN_ADDR_RTX gen_rtx_REG (HImode, RA_REGNUM)
+
+#define RETURN_ADDR_RTX(C,F) pru_get_return_address (C)
+
+#define DWARF_FRAME_RETURN_COLUMN RA_REGNUM
+
+/* The CFA includes the pretend args. */
+#define ARG_POINTER_CFA_OFFSET(FNDECL) \
+ (gcc_assert ((FNDECL) == current_function_decl), \
+ FIRST_PARM_OFFSET (FNDECL) + crtl->args.pretend_args_size)
+
+/* Frame/arg pointer elimination settings. */
+#define ELIMINABLE_REGS \
+{{ ARG_POINTER_REGNUM, STACK_POINTER_REGNUM}, \
+ { ARG_POINTER_REGNUM, HARD_FRAME_POINTER_REGNUM}, \
+ { FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM}, \
+ { FRAME_POINTER_REGNUM, HARD_FRAME_POINTER_REGNUM}}
+
+#define INITIAL_ELIMINATION_OFFSET(FROM, TO, OFFSET) \
+ (OFFSET) = pru_initial_elimination_offset ((FROM), (TO))
+
+#define HARD_REGNO_RENAME_OK(OLD_REG, NEW_REG) \
+ pru_hard_regno_rename_ok (OLD_REG, NEW_REG)
+
+/* Calling convention definitions. */
+#if !defined(IN_LIBGCC2)
+
+#define NUM_ARG_REGS (LAST_ARG_REGNUM - FIRST_ARG_REGNUM + 1)
+
+typedef struct pru_args
+{
+ bool regs_used[NUM_ARG_REGS];
+} CUMULATIVE_ARGS;
+
+#define INIT_CUMULATIVE_ARGS(CUM, FNTYPE, LIBNAME, FNDECL, N_NAMED_ARGS) \
+ do { \
+ memset ((CUM).regs_used, 0, sizeof ((CUM).regs_used)); \
+ } while (0)
+
+#define FUNCTION_ARG_REGNO_P(REGNO) \
+ ((REGNO) >= FIRST_ARG_REGNUM && (REGNO) <= LAST_ARG_REGNUM)
+
+/* Passing function arguments on stack. */
+#define PUSH_ARGS 0
+#define ACCUMULATE_OUTGOING_ARGS 1
+
+/* We define TARGET_RETURN_IN_MEMORY, so set to zero. */
+#define DEFAULT_PCC_STRUCT_RETURN 0
+
+/* Profiling. */
+#define PROFILE_BEFORE_PROLOGUE
+#define NO_PROFILE_COUNTERS 1
+#define FUNCTION_PROFILER(FILE, LABELNO) \
+ pru_function_profiler ((FILE), (LABELNO))
+
+#endif /* IN_LIBGCC2 */
+
+/* Addressing modes. */
+
+#define CONSTANT_ADDRESS_P(X) \
+ (CONSTANT_P (X) && memory_address_p (SImode, X))
+
+#define MAX_REGS_PER_ADDRESS 2
+#define BASE_REG_CLASS ALL_REGS
+#define INDEX_REG_CLASS ALL_REGS
+
+#define REGNO_OK_FOR_BASE_P(REGNO) pru_regno_ok_for_base_p ((REGNO), true)
+#define REGNO_OK_FOR_INDEX_P(REGNO) pru_regno_ok_for_index_p ((REGNO), true)
+
+/* Limited by the insns in pru-ldst-multiple.md. */
+#define MOVE_MAX 8
+#define SLOW_BYTE_ACCESS 1
+
+/* It is as good to call a constant function address as to call an address
+ kept in a register. */
+#define NO_FUNCTION_CSE 1
+
+/* Define output assembler language. */
+
+#define ASM_APP_ON "#APP\n"
+#define ASM_APP_OFF "#NO_APP\n"
+
+#define ASM_COMMENT_START "# "
+
+#define GLOBAL_ASM_OP "\t.global\t"
+
+#define PRU_NAME_R(X) X".b0", X".b1", X".b2", X".b3"
+#define REGISTER_NAMES \
+ { \
+ PRU_NAME_R ("r0"), \
+ PRU_NAME_R ("r1"), \
+ PRU_NAME_R ("r2"), \
+ PRU_NAME_R ("r3"), \
+ PRU_NAME_R ("r4"), \
+ PRU_NAME_R ("r5"), \
+ PRU_NAME_R ("r6"), \
+ PRU_NAME_R ("r7"), \
+ PRU_NAME_R ("r8"), \
+ PRU_NAME_R ("r9"), \
+ PRU_NAME_R ("r10"), \
+ PRU_NAME_R ("r11"), \
+ PRU_NAME_R ("r12"), \
+ PRU_NAME_R ("r13"), \
+ PRU_NAME_R ("r14"), \
+ PRU_NAME_R ("r15"), \
+ PRU_NAME_R ("r16"), \
+ PRU_NAME_R ("r17"), \
+ PRU_NAME_R ("r18"), \
+ PRU_NAME_R ("r19"), \
+ PRU_NAME_R ("r20"), \
+ PRU_NAME_R ("r21"), \
+ PRU_NAME_R ("r22"), \
+ PRU_NAME_R ("r23"), \
+ PRU_NAME_R ("r24"), \
+ PRU_NAME_R ("r25"), \
+ PRU_NAME_R ("r26"), \
+ PRU_NAME_R ("r27"), \
+ PRU_NAME_R ("r28"), \
+ PRU_NAME_R ("r29"), \
+ PRU_NAME_R ("r30"), \
+ PRU_NAME_R ("r31"), \
+ PRU_NAME_R ("loopcntr_reg"), \
+ PRU_NAME_R ("pc"), \
+ PRU_NAME_R ("fake_fp"), \
+ PRU_NAME_R ("fake_ap"), \
+}
+
+#define PRU_OVERLAP_R(X) \
+ { "r" #X , X * 4 , 4 }, \
+ { "r" #X ".w0", X * 4 + 0 , 2 }, \
+ { "r" #X ".w1", X * 4 + 1 , 2 }, \
+ { "r" #X ".w2", X * 4 + 2 , 2 }
+
+#define OVERLAPPING_REGISTER_NAMES \
+ { \
+ /* Aliases. */ \
+ { "sp", 2 * 4, 4 }, \
+ { "ra", 3 * 4, 2 }, \
+ { "fp", 4 * 4, 4 }, \
+ PRU_OVERLAP_R (0), \
+ PRU_OVERLAP_R (1), \
+ PRU_OVERLAP_R (2), \
+ PRU_OVERLAP_R (3), \
+ PRU_OVERLAP_R (4), \
+ PRU_OVERLAP_R (5), \
+ PRU_OVERLAP_R (6), \
+ PRU_OVERLAP_R (7), \
+ PRU_OVERLAP_R (8), \
+ PRU_OVERLAP_R (9), \
+ PRU_OVERLAP_R (10), \
+ PRU_OVERLAP_R (11), \
+ PRU_OVERLAP_R (12), \
+ PRU_OVERLAP_R (13), \
+ PRU_OVERLAP_R (14), \
+ PRU_OVERLAP_R (15), \
+ PRU_OVERLAP_R (16), \
+ PRU_OVERLAP_R (17), \
+ PRU_OVERLAP_R (18), \
+ PRU_OVERLAP_R (19), \
+ PRU_OVERLAP_R (20), \
+ PRU_OVERLAP_R (21), \
+ PRU_OVERLAP_R (22), \
+ PRU_OVERLAP_R (23), \
+ PRU_OVERLAP_R (24), \
+ PRU_OVERLAP_R (25), \
+ PRU_OVERLAP_R (26), \
+ PRU_OVERLAP_R (27), \
+ PRU_OVERLAP_R (28), \
+ PRU_OVERLAP_R (29), \
+ PRU_OVERLAP_R (30), \
+ PRU_OVERLAP_R (31), \
+}
+
+#define ASM_OUTPUT_ADDR_VEC_ELT(FILE, VALUE) \
+ do \
+ { \
+ fputs (integer_asm_op (POINTER_SIZE / BITS_PER_UNIT, TRUE), FILE); \
+ fprintf (FILE, "%%pmem(.L%u)\n", (unsigned) (VALUE)); \
+ } \
+ while (0)
+
+#define ASM_OUTPUT_ADDR_DIFF_ELT(STREAM, BODY, VALUE, REL) \
+ do \
+ { \
+ fputs (integer_asm_op (POINTER_SIZE / BITS_PER_UNIT, TRUE), STREAM); \
+ fprintf (STREAM, "%%pmem(.L%u-.L%u)\n", (unsigned) (VALUE), \
+ (unsigned) (REL)); \
+ } \
+ while (0)
+
+/* Section directives. */
+
+/* Output before read-only data. */
+#define TEXT_SECTION_ASM_OP "\t.section\t.text"
+
+/* Output before writable data. */
+#define DATA_SECTION_ASM_OP "\t.section\t.data"
+
+/* Output before uninitialized data. */
+#define BSS_SECTION_ASM_OP "\t.section\t.bss"
+
+#define CTORS_SECTION_ASM_OP "\t.section\t.init_array,\"aw\",%init_array"
+#define DTORS_SECTION_ASM_OP "\t.section\t.fini_array,\"aw\",%fini_array"
+
+#undef INIT_SECTION_ASM_OP
+#undef FINI_SECTION_ASM_OP
+#define INIT_ARRAY_SECTION_ASM_OP CTORS_SECTION_ASM_OP
+#define FINI_ARRAY_SECTION_ASM_OP DTORS_SECTION_ASM_OP
+
+/* Since we use .init_array/.fini_array we don't need the markers at
+ the start and end of the ctors/dtors arrays. */
+#define CTOR_LIST_BEGIN asm (CTORS_SECTION_ASM_OP)
+#define CTOR_LIST_END /* empty */
+#define DTOR_LIST_BEGIN asm (DTORS_SECTION_ASM_OP)
+#define DTOR_LIST_END /* empty */
+
+#undef TARGET_ASM_CONSTRUCTOR
+#define TARGET_ASM_CONSTRUCTOR pru_elf_asm_constructor
+
+#undef TARGET_ASM_DESTRUCTOR
+#define TARGET_ASM_DESTRUCTOR pru_elf_asm_destructor
+
+#define ASM_OUTPUT_ALIGN(FILE, LOG) \
+ do { \
+ fprintf ((FILE), "%s%d\n", ALIGN_ASM_OP, (LOG)); \
+ } while (0)
+
+#undef ASM_OUTPUT_ALIGNED_COMMON
+#define ASM_OUTPUT_ALIGNED_COMMON(FILE, NAME, SIZE, ALIGN) \
+do \
+ { \
+ fprintf ((FILE), "%s", COMMON_ASM_OP); \
+ assemble_name ((FILE), (NAME)); \
+ fprintf ((FILE), "," HOST_WIDE_INT_PRINT_UNSIGNED ",%u\n", (SIZE), \
+ (ALIGN) / BITS_PER_UNIT); \
+ } \
+while (0)
+
+
+/* This says how to output assembler code to declare an
+ uninitialized internal linkage data object. Under SVR4,
+ the linker seems to want the alignment of data objects
+ to depend on their types. We do exactly that here. */
+
+#undef ASM_OUTPUT_ALIGNED_LOCAL
+#define ASM_OUTPUT_ALIGNED_LOCAL(FILE, NAME, SIZE, ALIGN) \
+do { \
+ switch_to_section (bss_section); \
+ ASM_OUTPUT_TYPE_DIRECTIVE (FILE, NAME, "object"); \
+ if (!flag_inhibit_size_directive) \
+ ASM_OUTPUT_SIZE_DIRECTIVE (FILE, NAME, SIZE); \
+ ASM_OUTPUT_ALIGN ((FILE), exact_log2 ((ALIGN) / BITS_PER_UNIT)); \
+ ASM_OUTPUT_LABEL (FILE, NAME); \
+ ASM_OUTPUT_SKIP ((FILE), (SIZE) ? (SIZE) : 1); \
+} while (0)
+
+/* Misc parameters. */
+
+#define TARGET_SUPPORTS_WIDE_INT 1
+
+#define STORE_FLAG_VALUE 1
+#define Pmode SImode
+#define FUNCTION_MODE Pmode
+
+#define CASE_VECTOR_MODE Pmode
+
+/* Jumps are cheap on PRU. */
+#define LOGICAL_OP_NON_SHORT_CIRCUIT 0
+
+/* Unfortunately the LBBO instruction does not zero-extend data. */
+#undef LOAD_EXTEND_OP
+
+#undef WORD_REGISTER_OPERATIONS
+
+#define HAS_LONG_UNCOND_BRANCH 1
+#define HAS_LONG_COND_BRANCH 1
+
+#define REGISTER_TARGET_PRAGMAS() pru_register_pragmas ()
+
+#endif /* GCC_PRU_H */
diff --git a/gcc/config/pru/pru.md b/gcc/config/pru/pru.md
new file mode 100644
index 0000000..53fa73d
--- /dev/null
+++ b/gcc/config/pru/pru.md
@@ -0,0 +1,1022 @@
+;; Machine Description for TI PRU.
+;; Copyright (C) 2014-2019 Free Software Foundation, Inc.
+;; Contributed by Dimitar Dimitrov <dimitar@dinux.eu>
+;; Based on the NIOS2 GCC port.
+;;
+;; 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/>.
+
+;; Register numbers.
+(define_constants
+ [
+ (FIRST_ARG_REGNUM 56) ; Argument registers.
+ (LAST_ARG_REGNUM 119) ;
+ (FIRST_RETVAL_REGNUM 56) ; Return value registers.
+ (LAST_RETVAL_REGNUM 60) ;
+ (FIRST_CALLEE_SAVED_REGNUM 12) ; Callee saved registers.
+ (LAST_CALEE_SAVED_REGNUM 55) ;
+ (PROLOGUE_TEMP_REGNUM 4) ; Temporary register to use in prologue.
+
+ (RA_REGNUM 14) ; Return address register r3.w2.
+ (FP_REGNUM 16) ; Frame pointer register.
+ (MULDST_REGNUM 104) ; Multiply destination register.
+ (MULSRC0_REGNUM 112) ; Multiply source register.
+ (MULSRC1_REGNUM 116) ; Multiply source register.
+ (LAST_NONIO_GP_REGNUM 119) ; Last non-I/O general purpose register.
+ (LOOPCNTR_REGNUM 128) ; internal LOOP counter register
+ (LAST_GP_REGNUM 132) ; Last general purpose register.
+
+ ;; Target register definitions.
+ (STACK_POINTER_REGNUM 8)
+ (HARD_FRAME_POINTER_REGNUM FP_REGNUM)
+ (PC_REGNUM 132)
+ (FRAME_POINTER_REGNUM 136)
+ (ARG_POINTER_REGNUM 140)
+ (FIRST_PSEUDO_REGISTER 144)
+ ]
+)
+
+;; Enumeration of UNSPECs.
+
+(define_c_enum "unspecv" [
+ UNSPECV_DELAY_CYCLES_START
+ UNSPECV_DELAY_CYCLES_END
+ UNSPECV_DELAY_CYCLES_2X_HI
+ UNSPECV_DELAY_CYCLES_2X_SI
+ UNSPECV_DELAY_CYCLES_1
+
+ UNSPECV_LOOP_BEGIN
+ UNSPECV_LOOP_END
+
+ UNSPECV_BLOCKAGE
+])
+
+; Length of an instruction (in bytes).
+(define_attr "length" "" (const_int 4))
+(define_attr "type"
+ "unknown,complex,control,alu,cond_alu,st,ld,shift"
+ (const_string "complex"))
+
+(define_asm_attributes
+ [(set_attr "length" "4")
+ (set_attr "type" "complex")])
+
+; There is no pipeline, so our scheduling description is simple.
+(define_automaton "pru")
+(define_cpu_unit "cpu" "pru")
+
+(define_insn_reservation "everything" 1 (match_test "true") "cpu")
+
+(include "predicates.md")
+(include "constraints.md")
+
+;; All supported direct move-modes
+(define_mode_iterator MOV8_16_32 [QI QQ UQQ
+ HI HQ UHQ HA UHA
+ SI SQ USQ SA USA SF SD])
+
+(define_mode_iterator MOV8_16 [QI QQ UQQ
+ HI HQ UHQ HA UHA])
+(define_mode_iterator MOV32 [SI SQ USQ SA USA SF SD])
+(define_mode_iterator MOV64 [DI DF DD DQ UDQ])
+(define_mode_iterator QISI [QI HI SI])
+(define_mode_iterator HISI [HI SI])
+(define_mode_iterator SFDF [SF DF])
+
+;; EQS0/1 for extension source 0/1 and EQD for extension destination patterns.
+(define_mode_iterator EQS0 [QI HI SI])
+(define_mode_iterator EQS1 [QI HI SI])
+(define_mode_iterator EQD [QI HI SI])
+
+;; GCC sign-extends its integer constants. Hence 0x80 will be represented
+;; as -128 for QI mode and 128 for HI and SI modes. To cope with this,
+;; use different constraints to match UBYTE in different modes.
+;;
+;; Wherever this iterator is used, the corresponding operand has the 'u'
+;; print format modifier. That is how the QI signedness is cured, and
+;; the generated assembly contains unsigned constants.
+;;
+;; If the pattern has no QI operands, then this iterator need not be used.
+;;
+;; Note that we do not require "uhword_constr" since ALU instructions
+;; can use only UBYTE constants. The MOV patterns are already separately
+;; defined for each size, hence no need for an iterator.
+(define_mode_attr ubyte_constr [(QI "O") (HI "I") (SI "I")])
+
+;; Move instructions
+
+(define_expand "mov<mode>"
+ [(set (match_operand:MOV8_16_32 0 "nonimmediate_operand")
+ (match_operand:MOV8_16_32 1 "general_operand"))]
+ ""
+{
+ /* It helps to split constant loading and memory access
+ early, so that the LDI/LDI32 instructions can be hoisted
+ outside a loop body. */
+ if (MEM_P (operands[0]))
+ operands[1] = force_reg (<MODE>mode, operands[1]);
+})
+
+;; Keep a single pattern for 32 bit MOV operations. LRA requires that the
+;; movXX patterns be unified for any given mode.
+;;
+;; Note: Assume that Program Mem (T constraint) can fit in 16 bits!
+(define_insn "prumov<mode>"
+ [(set (match_operand:MOV32 0 "nonimmediate_operand" "=m,r,r,r,r,r")
+ (match_operand:MOV32 1 "general_operand" "r,m,r,T,J,iF"))]
+ ""
+ "@
+ sb%B0o\\t%b1, %0, %S0
+ lb%B1o\\t%b0, %1, %S1
+ mov\\t%0, %1
+ ldi\\t%0, %%pmem(%1)
+ ldi\\t%0, %1
+ ldi32\\t%0, %1"
+ [(set_attr "type" "st,ld,alu,alu,alu,alu")
+ (set_attr "length" "4,4,4,4,4,8")])
+
+
+;; Separate pattern for 8 and 16 bit moves, since LDI32 pseudo instruction
+;; cannot handle byte and word-sized registers.
+;;
+;; Note: Constraint N is fine for both QI and HI mode, since it is used
+;; in the context of 16 bit constant integer.
+(define_insn "prumov<mode>"
+ [(set (match_operand:MOV8_16 0 "nonimmediate_operand" "=m,r,r,r,r")
+ (match_operand:MOV8_16 1 "general_operand" "r,m,r,T,N"))]
+ ""
+ "@
+ sb%B0o\\t%b1, %0, %S0
+ lb%B1o\\t%b0, %1, %S1
+ mov\\t%0, %1
+ ldi\\t%0, %%pmem(%1)
+ ldi\\t%0, (%1) & 0xffff"
+ [(set_attr "type" "st,ld,alu,alu,alu")
+ (set_attr "length" "4")])
+
+
+; Pmode is 32 bits for PRU so symbolic constants cannot be 64 bits. Hence
+; this pattern handles only numeric constants.
+;
+; Note: Unlike the arithmetics, here we cannot use "&" output modifier.
+; GCC expects to be able to move registers around "no matter what".
+; Forcing DI reg alignment (akin to microblaze's HARD_REGNO_MODE_OK)
+; does not seem efficient, and will violate TI ABI.
+(define_insn "mov<mode>"
+ [(set (match_operand:MOV64 0 "nonimmediate_operand" "=m,r,r,r,r,r")
+ (match_operand:MOV64 1 "general_operand" "r,m,r,T,J,nF"))]
+ ""
+{
+ switch (which_alternative)
+ {
+ case 0:
+ return "sb%B0o\\t%b1, %0, %S0";
+ case 1:
+ return "lb%B1o\\t%b0, %1, %S1";
+ case 2:
+ /* careful with overlapping source and destination regs. */
+ gcc_assert (GP_REG_P (REGNO (operands[0])));
+ gcc_assert (GP_REG_P (REGNO (operands[1])));
+ if (REGNO (operands[0]) == (REGNO (operands[1]) + 4))
+ return "mov\\t%N0, %N1\;mov\\t%F0, %F1";
+ else
+ return "mov\\t%F0, %F1\;mov\\t%N0, %N1";
+ case 3:
+ return "ldi\\t%F0, %%pmem(%1)\;ldi\\t%N0, 0";
+ case 4:
+ return "ldi\\t%F0, %1\;ldi\\t%N0, 0";
+ case 5:
+ return "ldi32\\t%F0, %w1\;ldi32\\t%N0, %W1";
+ default:
+ gcc_unreachable ();
+ }
+}
+ [(set_attr "type" "st,ld,alu,alu,alu,alu")
+ (set_attr "length" "4,4,8,8,8,16")])
+
+;
+; load_multiple pattern(s).
+;
+; ??? Due to reload problems with replacing registers inside match_parallel
+; we currently support load_multiple/store_multiple only after reload.
+;
+; Idea taken from the s390 port.
+
+(define_expand "load_multiple"
+ [(match_par_dup 3 [(set (match_operand 0 "")
+ (match_operand 1 ""))
+ (use (match_operand 2 ""))])]
+ "reload_completed"
+{
+ machine_mode mode;
+ int regno;
+ int count;
+ rtx base_reg;
+ poly_int64 base_offs;
+ int i;
+
+ /* Support only loading a constant number of fixed-point registers from
+ memory. */
+ if (GET_CODE (operands[2]) != CONST_INT
+ || GET_CODE (operands[1]) != MEM
+ || GET_CODE (operands[0]) != REG)
+ FAIL;
+
+ count = INTVAL (operands[2]);
+ regno = REGNO (operands[0]);
+ mode = GET_MODE (operands[0]);
+ if (mode != QImode)
+ FAIL;
+
+ operands[3] = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (count));
+
+ gcc_assert (!can_create_pseudo_p ());
+
+ base_reg = strip_offset (XEXP (operands[1], 0), &base_offs);
+ if (GET_CODE (base_reg) != REG)
+ FAIL;
+
+ for (i = 0; i < count; i++)
+ XVECEXP (operands[3], 0, i)
+ = gen_rtx_SET (gen_rtx_REG (mode, regno + i),
+ change_address (operands[1], mode,
+ plus_constant (Pmode, base_reg,
+ base_offs + i * GET_MODE_SIZE (mode))));
+})
+
+(define_insn "*pru_load_multiple"
+ [(match_parallel 0 "load_multiple_operation"
+ [(set (match_operand:QI 1 "register_operand" "=r")
+ (match_operand:QI 2 "memory_operand" "m"))])]
+ "reload_completed"
+{
+ int nregs = XVECLEN (operands[0], 0);
+ operands[0] = GEN_INT (nregs);
+ return "lb%B2o\\t%b1, %2, %0";
+}
+ [(set_attr "type" "ld")])
+
+;
+; store multiple pattern(s).
+;
+
+(define_expand "store_multiple"
+ [(match_par_dup 3 [(set (match_operand 0 "")
+ (match_operand 1 ""))
+ (use (match_operand 2 ""))])]
+ "reload_completed"
+{
+ machine_mode mode;
+ int regno;
+ int count;
+ rtx base_reg;
+ poly_int64 base_offs;
+ int i;
+
+ /* Support only storing a constant number of fixed-point registers to
+ memory. */
+ if (GET_CODE (operands[2]) != CONST_INT
+ || GET_CODE (operands[0]) != MEM
+ || GET_CODE (operands[1]) != REG)
+ FAIL;
+
+ count = INTVAL (operands[2]);
+ regno = REGNO (operands[1]);
+ mode = GET_MODE (operands[1]);
+ if (mode != QImode)
+ FAIL;
+
+ operands[3] = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (count));
+
+ gcc_assert (!can_create_pseudo_p ());
+
+ base_reg = strip_offset (XEXP (operands[0], 0), &base_offs);
+ if (GET_CODE (base_reg) != REG)
+ FAIL;
+
+ for (i = 0; i < count; i++)
+ XVECEXP (operands[3], 0, i)
+ = gen_rtx_SET (change_address (operands[0], mode,
+ plus_constant (Pmode, base_reg,
+ base_offs + i * GET_MODE_SIZE (mode))),
+ gen_rtx_REG (mode, regno + i));
+})
+
+(define_insn "*pru_store_multiple"
+ [(match_parallel 0 "store_multiple_operation"
+ [(set (match_operand:QI 1 "memory_operand" "=m")
+ (match_operand:QI 2 "register_operand" "r"))])]
+ "reload_completed"
+{
+ int nregs = XVECLEN (operands[0], 0);
+ operands[0] = GEN_INT (nregs);
+ return "sb%B1o\\t%b2, %1, %0";
+}
+ [(set_attr "type" "st")])
+
+;; Zero extension patterns
+;;
+;; Unfortunately we cannot use lbbo to load AND zero-extent a value.
+;; The burst length parameter of the LBBO instruction designates not only
+;; the number of memory data bytes fetched, but also the number of register
+;; byte fields written.
+(define_expand "zero_extend<EQS0:mode><EQD:mode>2"
+ [(set (match_operand:EQD 0 "register_operand")
+ (zero_extend:EQD (match_operand:EQS0 1 "register_operand")))]
+ ""
+ "")
+
+(define_insn "*zero_extend<EQS0:mode><EQD:mode>2"
+ [(set (match_operand:EQD 0 "register_operand" "=r")
+ (zero_extend:EQD (match_operand:EQS0 1 "register_operand" "r")))]
+ ""
+ "mov\\t%0, %1"
+ [(set_attr "type" "alu")])
+
+;; Sign extension patterns. We have to emulate them due to lack of
+;; signed operations in PRU's ALU.
+
+(define_insn "extend<EQS0:mode><EQD:mode>2"
+ [(set (match_operand:EQD 0 "register_operand" "=r")
+ (sign_extend:EQD (match_operand:EQS0 1 "register_operand" "r")))]
+ ""
+{
+ return pru_output_sign_extend (operands);
+}
+ [(set_attr "type" "complex")
+ (set_attr "length" "12")])
+
+;; Bit extraction
+;; We define it solely to allow combine to choose SImode
+;; for word mode when trying to match our cbranch_qbbx_* insn.
+;;
+;; Check how combine.c:make_extraction() uses
+;; get_best_reg_extraction_insn() to select the op size.
+(define_insn "extzv<mode>"
+ [(set (match_operand:QISI 0 "register_operand" "=r")
+ (zero_extract:QISI
+ (match_operand:QISI 1 "register_operand" "r")
+ (match_operand:QISI 2 "const_int_operand" "i")
+ (match_operand:QISI 3 "const_int_operand" "i")))]
+ ""
+ "lsl\\t%0, %1, (%S0 * 8 - %2 - %3)\;lsr\\t%0, %0, (%S0 * 8 - %2)"
+ [(set_attr "type" "complex")
+ (set_attr "length" "8")])
+
+
+
+;; Arithmetic Operations
+
+(define_expand "add<mode>3"
+ [(set (match_operand:QISI 0 "register_operand")
+ (plus:QISI (match_operand:QISI 1 "register_operand")
+ (match_operand:QISI 2 "nonmemory_operand")))]
+ ""
+ "")
+
+(define_insn "adddi3"
+ [(set (match_operand:DI 0 "register_operand" "=&r,&r,&r")
+ (plus:DI (match_operand:DI 1 "register_operand" "%r,r,r")
+ (match_operand:DI 2 "reg_or_ubyte_operand" "r,I,M")))]
+ ""
+ "@
+ add\\t%F0, %F1, %F2\;adc\\t%N0, %N1, %N2
+ add\\t%F0, %F1, %2\;adc\\t%N0, %N1, 0
+ sub\\t%F0, %F1, %n2\;suc\\t%N0, %N1, 0"
+ [(set_attr "type" "alu")
+ (set_attr "length" "8")])
+
+(define_expand "sub<mode>3"
+ [(set (match_operand:QISI 0 "register_operand")
+ (minus:QISI (match_operand:QISI 1 "reg_or_ubyte_operand")
+ (match_operand:QISI 2 "reg_or_ubyte_operand")))]
+ ""
+ "")
+
+(define_insn "subdi3"
+ [(set (match_operand:DI 0 "register_operand" "=&r,&r")
+ (minus:DI (match_operand:DI 1 "reg_or_ubyte_operand" "r,I")
+ (match_operand:DI 2 "register_operand" "r,r")))]
+ ""
+ "@
+ sub\\t%F0, %F1, %F2\;suc\\t%N0, %N1, %N2
+ rsb\\t%F0, %F2, %1\;rsc\\t%N0, %N2, 0"
+ [(set_attr "type" "alu")
+ (set_attr "length" "8")])
+
+;; Negate and ones complement
+
+(define_expand "neg<mode>2"
+ [(set (match_operand:QISI 0 "register_operand")
+ (neg:QISI (match_operand:QISI 1 "register_operand")))]
+ ""
+ "")
+
+(define_expand "one_cmpl<mode>2"
+ [(set (match_operand:QISI 0 "register_operand")
+ (not:QISI (match_operand:QISI 1 "register_operand")))]
+ ""
+ "")
+
+;; Integer logical Operations
+;;
+;; TODO - add optimized cases that exploit the fact that we can get away
+;; with a single machine op for special constants, e.g. UBYTE << (0/8/16/24)
+
+(define_code_iterator LOGICAL [and ior xor umin umax])
+(define_code_attr logical_asm [(and "and") (ior "or") (xor "xor") (umin "min") (umax "max")])
+
+(define_code_iterator LOGICAL_BITOP [and ior xor])
+(define_code_attr logical_bitop_asm [(and "and") (ior "or") (xor "xor")])
+
+(define_expand "<code><mode>3"
+ [(set (match_operand:QISI 0 "register_operand")
+ (LOGICAL:QISI (match_operand:QISI 1 "register_operand")
+ (match_operand:QISI 2 "reg_or_ubyte_operand")))]
+ ""
+ "")
+
+
+;; Shift instructions
+
+(define_code_iterator SHIFT [ashift lshiftrt])
+(define_code_attr shift_op [(ashift "ashl") (lshiftrt "lshr")])
+(define_code_attr shift_asm [(ashift "lsl") (lshiftrt "lsr")])
+
+(define_expand "<shift_op><mode>3"
+ [(set (match_operand:QISI 0 "register_operand")
+ (SHIFT:QISI (match_operand:QISI 1 "register_operand")
+ (match_operand:QISI 2 "shift_operand")))]
+ ""
+ "")
+
+; Expand to a loop of single-position arithmetic shifts, which
+; we can handle. Pseudo code:
+; tmpval = src;
+; QImode cntr = nshifts & 0xff;
+; while (cntr)
+; {
+; tmpval >>= 1;
+; cntr--;
+; }
+; dst = tmpval;
+;
+; Note that the number of shifts is truncated to QImode. This is a fair
+; assumption for a loop-based shifting implementation.
+(define_expand "ashr<mode>3"
+ [(set (match_operand:QISI 0 "register_operand")
+ (ashiftrt:QISI
+ (match_operand:QISI 1 "register_operand")
+ (match_operand:QI 2 "reg_or_const_1_operand")))]
+ ""
+{
+ rtx dst = operands[0];
+ rtx src = operands[1];
+ rtx nshifts = operands[2];
+ rtx_code_label *loop_label;
+ rtx_code_label *ashr_end_label;
+ rtx test, tmpval, cntr;
+
+ if (const_1_operand (nshifts, VOIDmode))
+ {
+ emit_insn (gen_ashr<mode>3_single (dst, src, nshifts));
+ DONE;
+ }
+
+ tmpval = gen_reg_rtx (<MODE>mode);
+ emit_move_insn (tmpval, src);
+
+ cntr = gen_reg_rtx (QImode);
+ emit_move_insn (cntr, nshifts);
+
+ loop_label = gen_label_rtx ();
+ ashr_end_label = gen_label_rtx ();
+
+ emit_label (loop_label);
+ test = gen_rtx_EQ (VOIDmode, cntr, const0_rtx);
+ emit_jump_insn (gen_cbranchqi4 (test, cntr, const0_rtx, ashr_end_label));
+
+ emit_insn (gen_ashr<mode>3_single (tmpval, tmpval, const1_rtx));
+ emit_insn (gen_addqi3 (cntr, cntr, GEN_INT (-1)));
+
+ emit_jump_insn (gen_jump (loop_label));
+ JUMP_LABEL (get_last_insn ()) = loop_label;
+ LABEL_NUSES (loop_label)++;
+ emit_barrier ();
+
+ emit_label (ashr_end_label);
+
+ emit_move_insn (dst, tmpval);
+
+ DONE;
+})
+
+(define_insn "ashr<mode>3_single"
+ [(set (match_operand:QISI 0 "register_operand" "=r")
+ (ashiftrt:QISI
+ (match_operand:QISI 1 "register_operand" "r")
+ (match_operand:QI 2 "const_1_operand" "P")))]
+ ""
+ "lsr\\t%0, %1, 1\;qbbc LSIGN%=, %0, (%S0 * 8) - 2\;set %0, %0, (%S0 * 8) - 1\;LSIGN%=:"
+ [(set_attr "type" "alu")
+ (set_attr "length" "12")])
+
+
+;; Include ALU patterns with zero-extension of operands. That's where
+;; the real insns are defined.
+
+(include "alu-zext.md")
+
+;; DI logical ops could be automatically split into WORD-mode ops in
+;; expand_binop(). But then we'll miss an opportunity to use SI mode
+;; operations, since WORD mode for PRU is QI.
+(define_insn "<code>di3"
+ [(set (match_operand:DI 0 "register_operand" "=&r,&r")
+ (LOGICAL_BITOP:DI
+ (match_operand:DI 1 "register_operand" "%r,r")
+ (match_operand:DI 2 "reg_or_ubyte_operand" "r,I")))]
+ ""
+ "@
+ <logical_bitop_asm>\\t%F0, %F1, %F2\;<logical_bitop_asm>\\t%N0, %N1, %N2
+ <logical_bitop_asm>\\t%F0, %F1, %2\;<logical_bitop_asm>\\t%N0, %N1, 0"
+ [(set_attr "type" "alu")
+ (set_attr "length" "8")])
+
+
+(define_insn "one_cmpldi2"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (not:DI (match_operand:DI 1 "register_operand" "r")))]
+ ""
+{
+ /* careful with overlapping source and destination regs. */
+ gcc_assert (GP_REG_P (REGNO (operands[0])));
+ gcc_assert (GP_REG_P (REGNO (operands[1])));
+ if (REGNO (operands[0]) == (REGNO (operands[1]) + 4))
+ return "not\\t%N0, %N1\;not\\t%F0, %F1";
+ else
+ return "not\\t%F0, %F1\;not\\t%N0, %N1";
+}
+ [(set_attr "type" "alu")
+ (set_attr "length" "8")])
+
+;; Multiply instruction. The nop is required to ensure that Rmd0 and Rms0
+;; registers are sampled and multiplication is executed on those values.
+;; Only after that one cycle can xin obtain the result.
+
+(define_insn "mulsi3"
+ [(set (match_operand:SI 0 "pru_muldst_operand" "=Rmd0")
+ (mult:SI (match_operand:SI 1 "pru_mulsrc0_operand" "%Rms0")
+ (match_operand:SI 2 "pru_mulsrc1_operand" "Rms1")))]
+ ""
+ "nop\;xin\\t0, %0, 4"
+ [(set_attr "type" "alu")
+ (set_attr "length" "8")])
+
+;; Prologue, Epilogue and Return
+
+(define_expand "prologue"
+ [(const_int 1)]
+ ""
+{
+ pru_expand_prologue ();
+ DONE;
+})
+
+(define_expand "epilogue"
+ [(return)]
+ ""
+{
+ pru_expand_epilogue (false);
+ DONE;
+})
+
+(define_expand "sibcall_epilogue"
+ [(return)]
+ ""
+{
+ pru_expand_epilogue (true);
+ DONE;
+})
+
+(define_insn "return"
+ [(simple_return)]
+ "pru_can_use_return_insn ()"
+ "ret")
+
+(define_insn "simple_return"
+ [(simple_return)]
+ ""
+ "ret")
+
+;; Block any insns from being moved before this point, since the
+;; profiling call to mcount can use various registers that aren't
+;; saved or used to pass arguments.
+
+(define_insn "blockage"
+ [(unspec_volatile [(const_int 0)] UNSPECV_BLOCKAGE)]
+ ""
+ ""
+ [(set_attr "type" "unknown")
+ (set_attr "length" "0")])
+
+;; Jumps and calls
+
+(define_insn "indirect_jump"
+ [(set (pc) (match_operand:SI 0 "register_operand" "r"))]
+ ""
+ "jmp\\t%0"
+ [(set_attr "type" "control")])
+
+(define_insn "jump"
+ [(set (pc)
+ (label_ref (match_operand 0)))]
+ ""
+ "jmp\\t%%label(%l0)"
+ [(set_attr "type" "control")])
+
+
+(define_expand "call"
+ [(parallel [(call (match_operand 0 "")
+ (match_operand 1 ""))
+ (clobber (reg:HI RA_REGNUM))])]
+ ""
+ "")
+
+(define_expand "call_value"
+ [(parallel [(set (match_operand 0 "")
+ (call (match_operand 1 "")
+ (match_operand 2 "")))
+ (clobber (reg:HI RA_REGNUM))])]
+ ""
+ "")
+
+(define_insn "*call"
+ [(call (mem:SI (match_operand:SI 0 "call_operand" "i,r"))
+ (match_operand 1))
+ (clobber (reg:HI RA_REGNUM))]
+ ""
+ "@
+ call\\t%%label(%0)
+ call\\t%0"
+ [(set_attr "type" "control")])
+
+(define_insn "*call_value"
+ [(set (match_operand 0)
+ (call (mem:SI (match_operand:SI 1 "call_operand" "i,r"))
+ (match_operand 2)))
+ (clobber (reg:HI RA_REGNUM))]
+ ""
+ "@
+ call\\t%%label(%1)
+ call\\t%1"
+ [(set_attr "type" "control")])
+
+(define_expand "sibcall"
+ [(parallel [(call (match_operand 0 "")
+ (match_operand 1 ""))
+ (return)])]
+ ""
+ "")
+
+(define_expand "sibcall_value"
+ [(parallel [(set (match_operand 0 "")
+ (call (match_operand 1 "")
+ (match_operand 2 "")))
+ (return)])]
+ ""
+ "")
+
+(define_insn "*sibcall"
+ [(call (mem:SI (match_operand:SI 0 "call_operand" "i,Rsib"))
+ (match_operand 1))
+ (return)]
+ "SIBLING_CALL_P (insn)"
+ "@
+ jmp\\t%%label(%0)
+ jmp\\t%0"
+ [(set_attr "type" "control")])
+
+(define_insn "*sibcall_value"
+ [(set (match_operand 0 "register_operand" "")
+ (call (mem:SI (match_operand:SI 1 "call_operand" "i,Rsib"))
+ (match_operand 2)))
+ (return)]
+ "SIBLING_CALL_P (insn)"
+ "@
+ jmp\\t%%label(%1)
+ jmp\\t%1"
+ [(set_attr "type" "control")])
+
+(define_insn "*tablejump"
+ [(set (pc)
+ (match_operand:SI 0 "register_operand" "r"))
+ (use (label_ref (match_operand 1)))]
+ ""
+ "jmp\\t%0"
+ [(set_attr "type" "control")])
+
+;; Expand the cbranch pattern in order to assign different constraints for
+;; signed and unsigned comparisons.
+(define_expand "cbranch<mode>4"
+ [(set (pc)
+ (if_then_else
+ (match_operator 0 "ordered_comparison_operator"
+ [(match_operand:QISI 1 "register_operand")
+ (match_operand:QISI 2 "reg_or_const_int_operand")])
+ (label_ref (match_operand 3 ""))
+ (pc)))]
+ ""
+{
+ /* Ensure our patterns will be able to handle the particular const_int. */
+ if (CONST_INT_P (operands[2]))
+ {
+ HOST_WIDE_INT ival = INTVAL (operands[2]);
+
+ /* For signed comparisons, we cannot play games with the const_int's
+ sign. PRU patterns do not support negative integer constants. */
+ if (pru_signed_cmp_operator (operands[0], VOIDmode) && !UBYTE_INT (ival))
+ {
+ if (can_create_pseudo_p ())
+ operands[2] = force_reg (<MODE>mode, operands[2]);
+ else
+ FAIL;
+ }
+
+ /* For unsigned comparisons, be prepared to handle the QI quirk. */
+ if (pru_cmp_operator (operands[0], VOIDmode)
+ && !const_ubyte_operand (operands[2], <MODE>mode))
+ {
+ if (can_create_pseudo_p ())
+ operands[2] = force_reg (<MODE>mode, operands[2]);
+ else
+ FAIL;
+ }
+ }
+})
+
+(define_insn "cbranch<mode>4_unsigned"
+ [(set (pc)
+ (if_then_else
+ (match_operator 0 "pru_cmp_operator"
+ [(match_operand:QISI 1 "register_operand" "r")
+ (match_operand:QISI 2 "reg_or_ubyte_operand" "r<QISI:ubyte_constr>")])
+ (label_ref (match_operand 3))
+ (pc)))]
+ ""
+{
+ const bool is_near = (get_attr_length (insn) == 4);
+
+ /* PRU comparisons reverse the operand order (OP2 cmp OP1),
+ so swap the condition. */
+ if (is_near)
+ return "qb%P0\t%l3, %1, %u2";
+ else
+ return "qb%Q0\t.+8, %1, %u2\;jmp\t%%label(%l3)";
+}
+ [(set_attr "type" "control")
+ (set (attr "length")
+ (if_then_else
+ (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
+ (le (minus (match_dup 3) (pc)) (const_int 2036)))
+ (const_int 4)
+ (const_int 8)))])
+
+;; Unlike ALU operations, the const_int's sign here is important. So we
+;; cannot use ubyte_constr.
+;;
+;; NOTE: The short branch check has no typo! We must be conservative and
+;; take into account the worst case of having a signed comparison with a
+;; "far taken branch" label, which amounts to 7 instructions.
+(define_insn "cbranch<mode>4_signed"
+ [(set (pc)
+ (if_then_else
+ (match_operator 0 "pru_signed_cmp_operator"
+ [(match_operand:QISI 1 "register_operand" "r,r,r")
+ (match_operand:QISI 2 "reg_or_ubyte_operand" "r,Z,I")])
+ (label_ref (match_operand 3))
+ (pc)))]
+ ""
+{
+ const int length = (get_attr_length (insn));
+ const bool is_near = (length == 20);
+ enum rtx_code code = GET_CODE (operands[0]);
+
+ if (which_alternative == 0)
+ return pru_output_signed_cbranch (operands, is_near);
+ else if (which_alternative == 1 && (code == LT || code == GE))
+ return pru_output_signed_cbranch_zeroop2 (operands, is_near);
+ else
+ return pru_output_signed_cbranch_ubyteop2 (operands, is_near);
+}
+ [(set_attr "type" "control")
+ (set (attr "length")
+ (if_then_else
+ (and (ge (minus (match_dup 3) (pc)) (const_int -2020))
+ (le (minus (match_dup 3) (pc)) (const_int 2016)))
+ (const_int 20)
+ (const_int 28)))])
+
+(define_expand "cbranch<mode>4"
+ [(set (pc)
+ (if_then_else (match_operator 0 "pru_fp_comparison_operator"
+ [(match_operand:SFDF 1 "register_operand")
+ (match_operand:SFDF 2 "register_operand")])
+ (label_ref (match_operand 3 ""))
+ (pc)))]
+ ""
+{
+ rtx t = pru_expand_fp_compare (operands[0], VOIDmode);
+ operands[0] = t;
+ operands[1] = XEXP (t, 0);
+ operands[2] = XEXP (t, 1);
+})
+
+;
+; Bit test branch
+
+(define_code_iterator BIT_TEST [eq ne])
+(define_code_attr qbbx_op [(eq "qbbc") (ne "qbbs")])
+(define_code_attr qbbx_negop [(eq "qbbs") (ne "qbbc")])
+
+(define_insn "cbranch_qbbx_<BIT_TEST:code><EQS0:mode><EQS1:mode><EQD:mode>4"
+ [(set (pc)
+ (if_then_else
+ (BIT_TEST (zero_extract:EQD
+ (match_operand:EQS0 0 "register_operand" "r")
+ (const_int 1)
+ (match_operand:EQS1 1 "reg_or_ubyte_operand" "r<EQS1:ubyte_constr>"))
+ (const_int 0))
+ (label_ref (match_operand 2))
+ (pc)))]
+ ""
+{
+ const int length = (get_attr_length (insn));
+ const bool is_near = (length == 4);
+ if (is_near)
+ return "<BIT_TEST:qbbx_op>\\t%l2, %0, %u1";
+ else
+ return "<BIT_TEST:qbbx_negop>\\t.+8, %0, %u1\;jmp\\t%%label(%l2)";
+}
+ [(set_attr "type" "control")
+ (set (attr "length")
+ (if_then_else
+ (and (ge (minus (match_dup 2) (pc)) (const_int -2048))
+ (le (minus (match_dup 2) (pc)) (const_int 2044)))
+ (const_int 4)
+ (const_int 8)))])
+
+;; ::::::::::::::::::::
+;; ::
+;; :: Low Overhead Looping - idea "borrowed" from MEP
+;; ::
+;; ::::::::::::::::::::
+
+;; This insn is volatile because we'd like it to stay in its original
+;; position, just before the loop header. If it stays there, we might
+;; be able to convert it into a "loop" insn.
+(define_insn "doloop_begin_internal<mode>"
+ [(set (match_operand:HISI 0 "register_operand" "=r")
+ (unspec_volatile:HISI
+ [(match_operand:HISI 1 "reg_or_ubyte_operand" "rI")
+ (match_operand 2 "const_int_operand" "")] UNSPECV_LOOP_BEGIN))]
+ ""
+{
+ gcc_unreachable ();
+})
+
+(define_expand "doloop_begin"
+ [(use (match_operand 0 "register_operand"))
+ (use (match_operand 1 ""))]
+ "TARGET_OPT_LOOP"
+{
+ pru_emit_doloop (operands, 0);
+ DONE;
+})
+
+; Note: "JUMP_INSNs and CALL_INSNs are not allowed to have any output
+; reloads;". Hence this insn must be prepared for a counter that is
+; not a register.
+(define_insn "doloop_end_internal<mode>"
+ [(set (pc)
+ (if_then_else (ne (match_operand:HISI 0 "nonimmediate_operand" "+r,*m")
+ (const_int 1))
+ (label_ref (match_operand 1))
+ (pc)))
+ (set (match_dup 0)
+ (plus:HISI (match_dup 0)
+ (const_int -1)))
+ (unspec [(match_operand 2 "const_int_operand" "")] UNSPECV_LOOP_END)
+ (clobber (match_scratch:HISI 3 "=X,&r"))]
+ ""
+{
+ gcc_unreachable ();
+}
+ ;; Worst case length:
+ ;;
+ ;; lbbo op3_reg, op3_ptr 4'
+ ;; sub <op3_reg>, 1 4
+ ;; qbeq .+8, <op3_reg>, 0 4
+ ;; jmp <op1> 4
+ ;; sbbo op3_reg, op3_ptr 4
+ [(set (attr "length")
+ (if_then_else
+ (and (ge (minus (pc) (match_dup 1)) (const_int 0))
+ (le (minus (pc) (match_dup 1)) (const_int 1020)))
+ (cond [(eq_attr "alternative" "0") (const_int 4)]
+ (const_int 12))
+ (cond [(eq_attr "alternative" "0") (const_int 12)]
+ (const_int 20))))])
+
+(define_expand "doloop_end"
+ [(use (match_operand 0 "nonimmediate_operand"))
+ (use (label_ref (match_operand 1 "")))]
+ "TARGET_OPT_LOOP"
+{
+ if (GET_CODE (operands[0]) == REG && GET_MODE (operands[0]) == QImode)
+ FAIL;
+ pru_emit_doloop (operands, 1);
+ DONE;
+})
+
+(define_insn "pruloop<mode>"
+ [(set (reg:HISI LOOPCNTR_REGNUM)
+ (unspec:HISI [(match_operand:HISI 0 "reg_or_ubyte_operand" "rI")
+ (label_ref (match_operand 1))]
+ UNSPECV_LOOP_BEGIN))]
+ ""
+ "loop\\t%l1, %0")
+
+(define_insn "pruloop_end"
+ [(unspec [(const_int 0)] UNSPECV_LOOP_END)]
+ ""
+ "# loop end"
+ [(set_attr "length" "0")])
+
+
+;; Misc patterns
+
+(define_insn "delay_cycles_start"
+ [(unspec_volatile [(match_operand 0 "immediate_operand" "i")]
+ UNSPECV_DELAY_CYCLES_START)]
+ ""
+ "/* Begin %0 cycle delay. */"
+ [(set_attr "length" "0")])
+
+(define_insn "delay_cycles_end"
+ [(unspec_volatile [(match_operand 0 "immediate_operand" "i")]
+ UNSPECV_DELAY_CYCLES_END)]
+ ""
+ "/* End %0 cycle delay. */"
+ [(set_attr "length" "0")])
+
+
+(define_insn "delay_cycles_2x_plus1_hi"
+ [(unspec_volatile [(match_operand:SI 0 "const_uhword_operand" "J")]
+ UNSPECV_DELAY_CYCLES_2X_HI)
+ (clobber (match_scratch:SI 1 "=&r"))]
+ ""
+ "ldi\\t%1, %0\;sub\\t%1, %1, 1\;qbne\\t.-4, %1, 0"
+ [(set_attr "length" "12")])
+
+
+; Do not use LDI32 here because we do not want
+; to accidentally loose one instruction cycle.
+(define_insn "delay_cycles_2x_plus2_si"
+ [(unspec_volatile [(match_operand:SI 0 "const_int_operand" "n")]
+ UNSPECV_DELAY_CYCLES_2X_SI)
+ (clobber (match_scratch:SI 1 "=&r"))]
+ ""
+ "ldi\\t%1.w0, %L0\;ldi\\t%1.w2, %H0\;sub\\t%1, %1, 1\;qbne\\t.-4, %1, 0"
+ [(set_attr "length" "16")])
+
+(define_insn "delay_cycles_1"
+ [(unspec_volatile [(const_int 0) ] UNSPECV_DELAY_CYCLES_1)]
+ ""
+ "nop\\t# delay_cycles_1"
+)
+
+
+(define_insn "nop"
+ [(const_int 0)]
+ ""
+ "nop"
+ [(set_attr "type" "alu")])
+
+(define_insn "nop_loop_guard"
+ [(const_int 0)]
+ ""
+ "nop\\t# Loop end guard"
+ [(set_attr "type" "alu")])
diff --git a/gcc/config/pru/pru.opt b/gcc/config/pru/pru.opt
new file mode 100644
index 0000000..9bc1474
--- /dev/null
+++ b/gcc/config/pru/pru.opt
@@ -0,0 +1,54 @@
+; Options for the TI PRU port of the compiler.
+; Copyright (C) 2018-2019 Free Software Foundation, Inc.
+; Contributed by Dimitar Dimitrov <dimitar@dinux.eu>
+;
+; 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/>.
+
+HeaderInclude
+config/pru/pru-opts.h
+
+minrt
+Target Report Mask(MINRT) RejectNegative
+Use a minimum runtime (no static initializers or ctors) for memory-constrained
+devices.
+
+mmcu=
+Target RejectNegative Joined
+-mmcu=MCU Select the target System-On-Chip variant that embeds this PRU.
+
+mno-relax
+Target Report RejectNegative
+Make GCC pass the --no-relax command-line option to the linker instead of
+the --relax option.
+
+mloop
+Target Mask(OPT_LOOP)
+Allow (or do not allow) gcc to use the LOOP instruction.
+
+mabi=
+Target RejectNegative Report Joined Enum(pru_abi_t) Var(pru_current_abi) Init(PRU_ABI_GNU) Save
+Select target ABI variant.
+
+Enum
+Name(pru_abi_t) Type(enum pru_abi)
+ABI variant code generation (for use with -mabi= option):
+
+EnumValue
+Enum(pru_abi_t) String(gnu) Value(PRU_ABI_GNU)
+
+EnumValue
+Enum(pru_abi_t) String(ti) Value(PRU_ABI_TI)
diff --git a/gcc/config/pru/t-pru b/gcc/config/pru/t-pru
new file mode 100644
index 0000000..cfb0368
--- /dev/null
+++ b/gcc/config/pru/t-pru
@@ -0,0 +1,31 @@
+# Makefile fragment for building GCC for the TI PRU target.
+# Copyright (C) 2012-2019 Free Software Foundation, Inc.
+# Contributed by Dimitar Dimitrov <dimitar.dinux.eu>
+# Based on the t-nios2
+#
+# 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/>.
+
+# Unfortunately mabi=ti is not feature-complete enough to build newlib.
+# Hence we cannot present mabi=gnu/ti as a multilib option.
+
+pru-pragma.o: $(srcdir)/config/pru/pru-pragma.c $(RTL_H) $(TREE_H) \
+ $(CONFIG_H) $(TM_H) $(srcdir)/config/pru/pru-protos.h
+ $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $<
+
+pru-passes.o: $(srcdir)/config/pru/pru-passes.c $(RTL_H) $(TREE_H) \
+ $(CONFIG_H) $(TM_H) $(srcdir)/config/pru/pru-protos.h
+ $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $<
diff --git a/gcc/config/riscv/freebsd.h b/gcc/config/riscv/freebsd.h
index 13d04cc..bc51662 100644
--- a/gcc/config/riscv/freebsd.h
+++ b/gcc/config/riscv/freebsd.h
@@ -52,3 +52,9 @@ along with GCC; see the file COPYING3. If not see
%{rdynamic:-export-dynamic} \
-dynamic-linker " FBSD_DYNAMIC_LINKER "} \
%{static:-static}}"
+
+#define STARTFILE_PREFIX_SPEC \
+ "/lib" XLEN_SPEC "/" ABI_SPEC "/ " \
+ "/usr/lib" XLEN_SPEC "/" ABI_SPEC "/ " \
+ "/lib/ " \
+ "/usr/lib/ "
diff --git a/gcc/config/riscv/linux.h b/gcc/config/riscv/linux.h
index 58dd18b..07ce80a 100644
--- a/gcc/config/riscv/linux.h
+++ b/gcc/config/riscv/linux.h
@@ -68,3 +68,9 @@ along with GCC; see the file COPYING3. If not see
%{static:-static}}"
#define TARGET_ASM_FILE_END file_end_indicate_exec_stack
+
+#define STARTFILE_PREFIX_SPEC \
+ "/lib" XLEN_SPEC "/" ABI_SPEC "/ " \
+ "/usr/lib" XLEN_SPEC "/" ABI_SPEC "/ " \
+ "/lib/ " \
+ "/usr/lib/ "
diff --git a/gcc/config/riscv/riscv.c b/gcc/config/riscv/riscv.c
index 3f66b9d..8ac09f2 100644
--- a/gcc/config/riscv/riscv.c
+++ b/gcc/config/riscv/riscv.c
@@ -3050,7 +3050,7 @@ riscv_block_move_loop (rtx dest, rtx src, HOST_WIDE_INT length,
emit_insn(gen_nop ());
}
-/* Expand a movmemsi instruction, which copies LENGTH bytes from
+/* Expand a cpymemsi instruction, which copies LENGTH bytes from
memory reference SRC to memory reference DEST. */
bool
@@ -4401,6 +4401,7 @@ riscv_output_mi_thunk (FILE *file, tree thunk_fndecl ATTRIBUTE_UNUSED,
HOST_WIDE_INT delta, HOST_WIDE_INT vcall_offset,
tree function)
{
+ const char *fnname = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (thunk_fndecl));
rtx this_rtx, temp1, temp2, fnaddr;
rtx_insn *insn;
@@ -4460,9 +4461,11 @@ riscv_output_mi_thunk (FILE *file, tree thunk_fndecl ATTRIBUTE_UNUSED,
insn = get_insns ();
split_all_insns_noflow ();
shorten_branches (insn);
+ assemble_start_function (thunk_fndecl, fnname);
final_start_function (insn, file, 1);
final (insn, file, 1);
final_end_function ();
+ assemble_end_function (thunk_fndecl, fnname);
/* Clean up the vars set above. Note that final_end_function resets
the global pointer for us. */
diff --git a/gcc/config/riscv/riscv.h b/gcc/config/riscv/riscv.h
index 4edd2a6..4509d73 100644
--- a/gcc/config/riscv/riscv.h
+++ b/gcc/config/riscv/riscv.h
@@ -840,20 +840,20 @@ while (0)
#undef PTRDIFF_TYPE
#define PTRDIFF_TYPE (POINTER_SIZE == 64 ? "long int" : "int")
-/* The maximum number of bytes copied by one iteration of a movmemsi loop. */
+/* The maximum number of bytes copied by one iteration of a cpymemsi loop. */
#define RISCV_MAX_MOVE_BYTES_PER_LOOP_ITER (UNITS_PER_WORD * 4)
/* The maximum number of bytes that can be copied by a straight-line
- movmemsi implementation. */
+ cpymemsi implementation. */
#define RISCV_MAX_MOVE_BYTES_STRAIGHT (RISCV_MAX_MOVE_BYTES_PER_LOOP_ITER * 3)
/* If a memory-to-memory move would take MOVE_RATIO or more simple
- move-instruction pairs, we will do a movmem or libcall instead.
+ move-instruction pairs, we will do a cpymem or libcall instead.
Do not use move_by_pieces at all when strict alignment is not
in effect but the target has slow unaligned accesses; in this
- case, movmem or libcall is more efficient. */
+ case, cpymem or libcall is more efficient. */
#define MOVE_RATIO(speed) \
(!STRICT_ALIGNMENT && riscv_slow_unaligned_access_p ? 1 : \
@@ -893,12 +893,6 @@ extern unsigned riscv_stack_boundary;
"%{mabi=lp64f:lp64f}" \
"%{mabi=lp64d:lp64d}" \
-#define STARTFILE_PREFIX_SPEC \
- "/lib" XLEN_SPEC "/" ABI_SPEC "/ " \
- "/usr/lib" XLEN_SPEC "/" ABI_SPEC "/ " \
- "/lib/ " \
- "/usr/lib/ "
-
/* ISA constants needed for code generation. */
#define OPCODE_LW 0x2003
#define OPCODE_LD 0x3003
diff --git a/gcc/config/riscv/riscv.md b/gcc/config/riscv/riscv.md
index 8b21c19..309c109 100644
--- a/gcc/config/riscv/riscv.md
+++ b/gcc/config/riscv/riscv.md
@@ -1498,7 +1498,7 @@
DONE;
})
-(define_expand "movmemsi"
+(define_expand "cpymemsi"
[(parallel [(set (match_operand:BLK 0 "general_operand")
(match_operand:BLK 1 "general_operand"))
(use (match_operand:SI 2 ""))
diff --git a/gcc/config/rs6000/altivec.h b/gcc/config/rs6000/altivec.h
index d66ae7c..dafc76a 100644
--- a/gcc/config/rs6000/altivec.h
+++ b/gcc/config/rs6000/altivec.h
@@ -37,10 +37,12 @@
/* If __APPLE_ALTIVEC__ is defined, the compiler supports 'vector',
'pixel' and 'bool' as context-sensitive AltiVec keywords (in
non-AltiVec contexts, they revert to their original meanings,
- if any), so we do not need to define them as macros. */
+ if any), so we do not need to define them as macros. Also,
+ avoid defining them as macros for C++ with strict ANSI, as
+ this is not compatible. */
-#if !defined(__APPLE_ALTIVEC__)
-/* You are allowed to undef these for C++ compatibility. */
+#if !defined(__APPLE_ALTIVEC__) \
+ && (!defined(__STRICT_ANSI__) || !defined(__cplusplus))
#define vector __vector
#define pixel __pixel
#define bool __bool
diff --git a/gcc/config/rs6000/altivec.md b/gcc/config/rs6000/altivec.md
index 4a1150e..3a8cd76 100644
--- a/gcc/config/rs6000/altivec.md
+++ b/gcc/config/rs6000/altivec.md
@@ -256,7 +256,7 @@
* return output_vec_const_move (operands);
#"
[(set_attr "type" "vecstore,vecload,veclogical,store,load,*,veclogical,*,*")
- (set_attr "length" "4,4,4,20,20,20,4,8,32")])
+ (set_attr "length" "*,*,*,20,20,20,*,8,32")])
;; Unlike other altivec moves, allow the GPRs, since a normal use of TImode
;; is for unions. However for plain data movement, slightly favor the vector
@@ -2023,28 +2023,30 @@
;; Slightly prefer vperm, since the target does not overlap the source
(define_insn "altivec_vperm_<mode>_direct"
- [(set (match_operand:VM 0 "register_operand" "=v,?wo")
- (unspec:VM [(match_operand:VM 1 "register_operand" "v,wo")
+ [(set (match_operand:VM 0 "register_operand" "=v,?wa")
+ (unspec:VM [(match_operand:VM 1 "register_operand" "v,wa")
(match_operand:VM 2 "register_operand" "v,0")
- (match_operand:V16QI 3 "register_operand" "v,wo")]
+ (match_operand:V16QI 3 "register_operand" "v,wa")]
UNSPEC_VPERM))]
"TARGET_ALTIVEC"
"@
vperm %0,%1,%2,%3
xxperm %x0,%x1,%x3"
- [(set_attr "type" "vecperm")])
+ [(set_attr "type" "vecperm")
+ (set_attr "isa" "*,p9v")])
(define_insn "altivec_vperm_v8hiv16qi"
- [(set (match_operand:V16QI 0 "register_operand" "=v,?wo")
- (unspec:V16QI [(match_operand:V8HI 1 "register_operand" "v,wo")
+ [(set (match_operand:V16QI 0 "register_operand" "=v,?wa")
+ (unspec:V16QI [(match_operand:V8HI 1 "register_operand" "v,wa")
(match_operand:V8HI 2 "register_operand" "v,0")
- (match_operand:V16QI 3 "register_operand" "v,wo")]
+ (match_operand:V16QI 3 "register_operand" "v,wa")]
UNSPEC_VPERM))]
"TARGET_ALTIVEC"
"@
vperm %0,%1,%2,%3
xxperm %x0,%x1,%x3"
- [(set_attr "type" "vecperm")])
+ [(set_attr "type" "vecperm")
+ (set_attr "isa" "*,p9v")])
(define_expand "altivec_vperm_<mode>_uns"
[(set (match_operand:VM 0 "register_operand")
@@ -2062,16 +2064,17 @@
})
(define_insn "*altivec_vperm_<mode>_uns_internal"
- [(set (match_operand:VM 0 "register_operand" "=v,?wo")
- (unspec:VM [(match_operand:VM 1 "register_operand" "v,wo")
+ [(set (match_operand:VM 0 "register_operand" "=v,?wa")
+ (unspec:VM [(match_operand:VM 1 "register_operand" "v,wa")
(match_operand:VM 2 "register_operand" "v,0")
- (match_operand:V16QI 3 "register_operand" "v,wo")]
+ (match_operand:V16QI 3 "register_operand" "v,wa")]
UNSPEC_VPERM_UNS))]
"TARGET_ALTIVEC"
"@
vperm %0,%1,%2,%3
xxperm %x0,%x1,%x3"
- [(set_attr "type" "vecperm")])
+ [(set_attr "type" "vecperm")
+ (set_attr "isa" "*,p9v")])
(define_expand "vec_permv16qi"
[(set (match_operand:V16QI 0 "register_operand")
@@ -2088,16 +2091,17 @@
})
(define_insn "*altivec_vpermr_<mode>_internal"
- [(set (match_operand:VM 0 "register_operand" "=v,?wo")
- (unspec:VM [(match_operand:VM 1 "register_operand" "v,wo")
+ [(set (match_operand:VM 0 "register_operand" "=v,?wa")
+ (unspec:VM [(match_operand:VM 1 "register_operand" "v,wa")
(match_operand:VM 2 "register_operand" "v,0")
- (match_operand:V16QI 3 "register_operand" "v,wo")]
+ (match_operand:V16QI 3 "register_operand" "v,wa")]
UNSPEC_VPERMR))]
"TARGET_P9_VECTOR"
"@
vpermr %0,%1,%2,%3
xxpermr %x0,%x1,%x3"
- [(set_attr "type" "vecperm")])
+ [(set_attr "type" "vecperm")
+ (set_attr "isa" "*,p9v")])
(define_insn "altivec_vrfip" ; ceil
[(set (match_operand:V4SF 0 "register_operand" "=v")
@@ -3245,28 +3249,30 @@
"")
(define_insn "vperm_v8hiv4si"
- [(set (match_operand:V4SI 0 "register_operand" "=v,?wo")
- (unspec:V4SI [(match_operand:V8HI 1 "register_operand" "v,wo")
+ [(set (match_operand:V4SI 0 "register_operand" "=v,?wa")
+ (unspec:V4SI [(match_operand:V8HI 1 "register_operand" "v,wa")
(match_operand:V4SI 2 "register_operand" "v,0")
- (match_operand:V16QI 3 "register_operand" "v,wo")]
+ (match_operand:V16QI 3 "register_operand" "v,wa")]
UNSPEC_VPERMSI))]
"TARGET_ALTIVEC"
"@
vperm %0,%1,%2,%3
xxperm %x0,%x1,%x3"
- [(set_attr "type" "vecperm")])
+ [(set_attr "type" "vecperm")
+ (set_attr "isa" "*,p9v")])
(define_insn "vperm_v16qiv8hi"
- [(set (match_operand:V8HI 0 "register_operand" "=v,?wo")
- (unspec:V8HI [(match_operand:V16QI 1 "register_operand" "v,wo")
+ [(set (match_operand:V8HI 0 "register_operand" "=v,?wa")
+ (unspec:V8HI [(match_operand:V16QI 1 "register_operand" "v,wa")
(match_operand:V8HI 2 "register_operand" "v,0")
- (match_operand:V16QI 3 "register_operand" "v,wo")]
+ (match_operand:V16QI 3 "register_operand" "v,wa")]
UNSPEC_VPERMHI))]
"TARGET_ALTIVEC"
"@
vperm %0,%1,%2,%3
xxperm %x0,%x1,%x3"
- [(set_attr "type" "vecperm")])
+ [(set_attr "type" "vecperm")
+ (set_attr "isa" "*,p9v")])
(define_expand "vec_unpacku_hi_v16qi"
diff --git a/gcc/config/rs6000/constraints.md b/gcc/config/rs6000/constraints.md
index 27db92b..f047742 100644
--- a/gcc/config/rs6000/constraints.md
+++ b/gcc/config/rs6000/constraints.md
@@ -56,83 +56,23 @@
(define_register_constraint "wa" "rs6000_constraints[RS6000_CONSTRAINT_wa]"
"Any VSX register if the -mvsx option was used or NO_REGS.")
-(define_register_constraint "wb" "rs6000_constraints[RS6000_CONSTRAINT_wb]"
- "Altivec register if the -mpower9-dform option was used or NO_REGS.")
-
;; NOTE: For compatibility, "wc" is reserved to represent individual CR bits.
;; It is currently used for that purpose in LLVM.
-(define_register_constraint "wd" "rs6000_constraints[RS6000_CONSTRAINT_wd]"
- "VSX vector register to hold vector double data or NO_REGS.")
-
(define_register_constraint "we" "rs6000_constraints[RS6000_CONSTRAINT_we]"
"VSX register if the -mpower9-vector -m64 options were used or NO_REGS.")
-(define_register_constraint "wf" "rs6000_constraints[RS6000_CONSTRAINT_wf]"
- "VSX vector register to hold vector float data or NO_REGS.")
-
-(define_register_constraint "wg" "rs6000_constraints[RS6000_CONSTRAINT_wg]"
- "If -mmfpgpr was used, a floating point register or NO_REGS.")
-
-(define_register_constraint "wh" "rs6000_constraints[RS6000_CONSTRAINT_wh]"
- "Floating point register if direct moves are available, or NO_REGS.")
-
-(define_register_constraint "wi" "rs6000_constraints[RS6000_CONSTRAINT_wi]"
- "FP or VSX register to hold 64-bit integers for VSX insns or NO_REGS.")
-
-(define_register_constraint "wj" "rs6000_constraints[RS6000_CONSTRAINT_wj]"
- "FP or VSX register to hold 64-bit integers for direct moves or NO_REGS.")
-
-(define_register_constraint "wk" "rs6000_constraints[RS6000_CONSTRAINT_wk]"
- "FP or VSX register to hold 64-bit doubles for direct moves or NO_REGS.")
-
-(define_register_constraint "wl" "rs6000_constraints[RS6000_CONSTRAINT_wl]"
- "Floating point register if the LFIWAX instruction is enabled or NO_REGS.")
-
-(define_register_constraint "wm" "rs6000_constraints[RS6000_CONSTRAINT_wm]"
- "VSX register if direct move instructions are enabled, or NO_REGS.")
-
;; NO_REGs register constraint, used to merge mov{sd,sf}, since movsd can use
;; direct move directly, and movsf can't to move between the register sets.
-;; There is a mode_attr that resolves to wm for SDmode and wn for SFmode
+;; There is a mode_attr that resolves to wa for SDmode and wn for SFmode
(define_register_constraint "wn" "NO_REGS" "No register (NO_REGS).")
-(define_register_constraint "wo" "rs6000_constraints[RS6000_CONSTRAINT_wo]"
- "VSX register if the -mpower9-vector option was used or NO_REGS.")
-
-(define_register_constraint "wp" "rs6000_constraints[RS6000_CONSTRAINT_wp]"
- "VSX register to use for IEEE 128-bit fp TFmode, or NO_REGS.")
-
-(define_register_constraint "wq" "rs6000_constraints[RS6000_CONSTRAINT_wq]"
- "VSX register to use for IEEE 128-bit fp KFmode, or NO_REGS.")
-
(define_register_constraint "wr" "rs6000_constraints[RS6000_CONSTRAINT_wr]"
"General purpose register if 64-bit instructions are enabled or NO_REGS.")
-(define_register_constraint "ws" "rs6000_constraints[RS6000_CONSTRAINT_ws]"
- "VSX vector register to hold scalar double values or NO_REGS.")
-
-(define_register_constraint "wt" "rs6000_constraints[RS6000_CONSTRAINT_wt]"
- "VSX vector register to hold 128 bit integer or NO_REGS.")
-
-(define_register_constraint "wu" "rs6000_constraints[RS6000_CONSTRAINT_wu]"
- "Altivec register to use for float/32-bit int loads/stores or NO_REGS.")
-
-(define_register_constraint "wv" "rs6000_constraints[RS6000_CONSTRAINT_wv]"
- "Altivec register to use for double loads/stores or NO_REGS.")
-
-(define_register_constraint "ww" "rs6000_constraints[RS6000_CONSTRAINT_ww]"
- "FP or VSX register to perform float operations under -mvsx or NO_REGS.")
-
(define_register_constraint "wx" "rs6000_constraints[RS6000_CONSTRAINT_wx]"
"Floating point register if the STFIWX instruction is enabled or NO_REGS.")
-(define_register_constraint "wy" "rs6000_constraints[RS6000_CONSTRAINT_wy]"
- "FP or VSX register to perform ISA 2.07 float ops or NO_REGS.")
-
-(define_register_constraint "wz" "rs6000_constraints[RS6000_CONSTRAINT_wz]"
- "Floating point register if the LFIWZX instruction is enabled or NO_REGS.")
-
(define_register_constraint "wA" "rs6000_constraints[RS6000_CONSTRAINT_wA]"
"BASE_REGS if 64-bit instructions are enabled or NO_REGS.")
@@ -157,18 +97,6 @@
"Memory operand suitable for power8 GPR load fusion"
(match_operand 0 "fusion_addis_mem_combo_load"))
-(define_register_constraint "wH" "rs6000_constraints[RS6000_CONSTRAINT_wH]"
- "Altivec register to hold 32-bit integers or NO_REGS.")
-
-(define_register_constraint "wI" "rs6000_constraints[RS6000_CONSTRAINT_wI]"
- "FPR register to hold 32-bit integers or NO_REGS.")
-
-(define_register_constraint "wJ" "rs6000_constraints[RS6000_CONSTRAINT_wJ]"
- "FPR register to hold 8/16-bit integers or NO_REGS.")
-
-(define_register_constraint "wK" "rs6000_constraints[RS6000_CONSTRAINT_wK]"
- "Altivec register to hold 8/16-bit integers or NO_REGS.")
-
(define_constraint "wL"
"Int constant that is the element number mfvsrld accesses in a vector."
(and (match_code "const_int")
@@ -252,6 +180,11 @@
(and (match_code "const_int")
(match_test "((- (unsigned HOST_WIDE_INT) ival) + 0x8000) < 0x10000")))
+;; 34-bit signed integer constant
+(define_constraint "eI"
+ "34-bit constant integer that can be loaded with PADDI"
+ (match_operand 0 "cint34_operand"))
+
;; Floating-point constraints. These two are defined so that insn
;; length attributes can be calculated exactly.
diff --git a/gcc/config/rs6000/darwin.h b/gcc/config/rs6000/darwin.h
index 4774d1d..b0b5047 100644
--- a/gcc/config/rs6000/darwin.h
+++ b/gcc/config/rs6000/darwin.h
@@ -54,15 +54,17 @@
do \
{ \
if (!TARGET_64BIT) builtin_define ("__ppc__"); \
+ if (!TARGET_64BIT) builtin_define ("__PPC__"); \
if (TARGET_64BIT) builtin_define ("__ppc64__"); \
+ if (TARGET_64BIT) builtin_define ("__PPC64__"); \
builtin_define ("__POWERPC__"); \
builtin_define ("__NATURAL_ALIGNMENT__"); \
darwin_cpp_builtins (pfile); \
} \
while (0)
-/* Generate branch islands stubs if this is true. */
-extern int darwin_emit_branch_islands;
+/* Generate pic symbol stubs if this is true. */
+extern int darwin_emit_picsym_stub;
#define SUBTARGET_OVERRIDE_OPTIONS darwin_rs6000_override_options ()
@@ -126,9 +128,30 @@ extern int darwin_emit_branch_islands;
%:version-compare(>< 10.5 10.7 mmacosx-version-min= -lcrt1.10.5.o) \
%{fgnu-tm: -lcrttms.o}"
-/* crt2.o is at least partially required for 10.3.x and earlier. */
+/* crt2.o is at least partially required for 10.3.x and earlier.
+ It deals with registration of the unwind frames, where this is not
+ automatically provided by the system. So we need it for any case that
+ might use exceptions. */
+#undef DARWIN_CRT2_SPEC
#define DARWIN_CRT2_SPEC \
- "%{!m64:%:version-compare(!> 10.4 mmacosx-version-min= crt2.o%s)}"
+"%{!m64:%{shared-libgcc|static-libstdc++|fexceptions|fobjc-exceptions|fgnu-runtime: \
+ %:version-compare(!> 10.4 mmacosx-version-min= crt2.o%s) \
+ }}"
+
+/* crt3 deals with providing cxa_atexit on earlier systems (or fixing it up,
+ for broken versions). It's only needed for c++ code, so we can make it
+ conditional on shared-libgcc since that's forced on for c++. */
+#undef DARWIN_CRT3_SPEC
+#define DARWIN_CRT3_SPEC \
+"%{!m64:%{shared-libgcc|static-libstdc++: \
+ %:version-compare(>< 10.4 10.5 mmacosx-version-min= crt3.o%s) \
+ %:version-compare(!> 10.4 mmacosx-version-min= crt3_2.o%s) \
+ }}"
+
+/* The PPC regs save/restore functions are leaves and could, conceivably
+ be used by the tm destructor. */
+#undef ENDFILE_SPEC
+#define ENDFILE_SPEC TM_DESTRUCTOR " -lef_ppc"
#undef SUBTARGET_EXTRA_SPECS
#define SUBTARGET_EXTRA_SPECS \
@@ -398,6 +421,7 @@ extern int darwin_emit_branch_islands;
do \
{ \
DARWIN_REGISTER_TARGET_PRAGMAS(); \
+ targetm.target_option.pragma_parse = rs6000_pragma_target_parse; \
targetm.resolve_overloaded_builtin = altivec_resolve_overloaded_builtin; \
} \
while (0)
diff --git a/gcc/config/rs6000/driver-rs6000.c b/gcc/config/rs6000/driver-rs6000.c
index b290eea..cd6c889 100644
--- a/gcc/config/rs6000/driver-rs6000.c
+++ b/gcc/config/rs6000/driver-rs6000.c
@@ -263,12 +263,10 @@ elf_platform (void)
for (i = 0; i < ARRAY_SIZE (rs6000_supported_cpu_names); i++)
candidates.safe_push (rs6000_supported_cpu_names[i]);
candidates_list_and_hint (cpu, s, candidates);
- fatal_error (
- input_location,
- "Unsupported cpu name returned from kernel for "
- "%<-mcpu=native%>: %s\n"
- "Please use an explicit cpu name. Valid cpu names are: %s",
- cpu, s);
+ error ("unsupported cpu name returned from kernel "
+ "for %<-mcpu=native%>: %s", cpu);
+ fatal_error (input_location, "please use an explicit cpu name; "
+ "valid cpu names are: %s", s);
}
}
return NULL;
@@ -459,6 +457,7 @@ static const struct asm_name asm_names[] = {
{ "630", "-m620" },
{ "970", "-m970" },
{ "G5", "-m970" },
+ { "future", "-mfuture" },
{ NULL, "\
%{mvsx: -mpwr6; \
maltivec: -m970; \
@@ -522,6 +521,7 @@ static const struct asm_name asm_names[] = {
{ "e5500", "-me5500" },
{ "e6500", "-me6500" },
{ "titan", "-mtitan" },
+ { "future", "-mfuture" },
{ NULL, "\
%{mpower9-vector: -mpower9; \
mpower8-vector|mcrypto|mdirect-move|mhtm: -mpower8; \
diff --git a/gcc/config/rs6000/predicates.md b/gcc/config/rs6000/predicates.md
index 2643f1a..45fa40a 100644
--- a/gcc/config/rs6000/predicates.md
+++ b/gcc/config/rs6000/predicates.md
@@ -302,6 +302,16 @@
(and (match_code "const_int")
(match_test "IN_RANGE (INTVAL (op), 0, 15)")))
+;; Return 1 if op is a 34-bit constant integer.
+(define_predicate "cint34_operand"
+ (match_code "const_int")
+{
+ if (!TARGET_PREFIXED_ADDR)
+ return 0;
+
+ return SIGNED_34BIT_OFFSET_P (INTVAL (op), 0);
+})
+
;; Return 1 if op is a register that is not special.
;; Disallow (SUBREG:SF (REG:SI)) and (SUBREG:SI (REG:SF)) on VSX systems where
;; you need to be careful in moving a SFmode to SImode and vice versa due to
@@ -1612,6 +1622,82 @@
return GET_CODE (op) == UNSPEC && XINT (op, 1) == UNSPEC_TOCREL;
})
+;; Return true if the operand is a pc-relative address.
+(define_predicate "pcrel_address"
+ (match_code "label_ref,symbol_ref,const")
+{
+ if (!rs6000_pcrel_p (cfun))
+ return false;
+
+ if (GET_CODE (op) == CONST)
+ op = XEXP (op, 0);
+
+ /* Validate offset. */
+ if (GET_CODE (op) == PLUS)
+ {
+ rtx op0 = XEXP (op, 0);
+ rtx op1 = XEXP (op, 1);
+
+ if (!CONST_INT_P (op1) || !SIGNED_34BIT_OFFSET_P (INTVAL (op1), 0))
+ return false;
+
+ op = op0;
+ }
+
+ if (LABEL_REF_P (op))
+ return true;
+
+ return (SYMBOL_REF_P (op) && SYMBOL_REF_LOCAL_P (op));
+})
+
+;; Return true if the operand is an external symbol whose address can be loaded
+;; into a register using:
+;; PLA reg,label@pcrel@got
+;;
+;; The linker will either optimize this to either a PADDI if the label is
+;; defined locally in another module or a PLD of the address if the label is
+;; defined in another module.
+
+(define_predicate "pcrel_external_address"
+ (match_code "symbol_ref,const")
+{
+ if (!rs6000_pcrel_p (cfun))
+ return false;
+
+ if (GET_CODE (op) == CONST)
+ op = XEXP (op, 0);
+
+ /* Validate offset. */
+ if (GET_CODE (op) == PLUS)
+ {
+ rtx op0 = XEXP (op, 0);
+ rtx op1 = XEXP (op, 1);
+
+ if (!CONST_INT_P (op1) || !SIGNED_34BIT_OFFSET_P (INTVAL (op1), 0))
+ return false;
+
+ op = op0;
+ }
+
+ return (SYMBOL_REF_P (op) && !SYMBOL_REF_LOCAL_P (op));
+})
+
+;; Return 1 if op is a prefixed memory operand.
+(define_predicate "prefixed_mem_operand"
+ (match_code "mem")
+{
+ return rs6000_prefixed_address (XEXP (op, 0), GET_MODE (op));
+})
+
+;; Return 1 if op is a memory operand to an external variable when we
+;; support pc-relative addressing and the PCREL_OPT relocation to
+;; optimize references to it.
+(define_predicate "pcrel_external_mem_operand"
+ (match_code "mem")
+{
+ return pcrel_external_address (XEXP (op, 0), Pmode);
+})
+
;; Match the first insn (addis) in fusing the combination of addis and loads to
;; GPR registers on power8.
(define_predicate "fusion_gpr_addis"
diff --git a/gcc/config/rs6000/rs6000-c.c b/gcc/config/rs6000/rs6000-c.c
index 7c28d4d..7854082 100644
--- a/gcc/config/rs6000/rs6000-c.c
+++ b/gcc/config/rs6000/rs6000-c.c
@@ -47,15 +47,17 @@
whether or not new function declarations receive a longcall
attribute by default. */
+void
+rs6000_pragma_longcall (cpp_reader *pfile ATTRIBUTE_UNUSED)
+{
#define SYNTAX_ERROR(gmsgid) do { \
warning (OPT_Wpragmas, gmsgid); \
- warning (OPT_Wpragmas, "ignoring malformed #pragma longcall"); \
+ warning (OPT_Wpragmas, "ignoring malformed %<#pragma longcall%>"); \
return; \
} while (0)
-void
-rs6000_pragma_longcall (cpp_reader *pfile ATTRIBUTE_UNUSED)
-{
+
+
tree x, n;
/* If we get here, generic code has already scanned the directive
@@ -72,7 +74,7 @@ rs6000_pragma_longcall (cpp_reader *pfile ATTRIBUTE_UNUSED)
SYNTAX_ERROR ("number must be 0 or 1");
if (pragma_lex (&x) != CPP_EOF)
- warning (OPT_Wpragmas, "junk at end of #pragma longcall");
+ warning (OPT_Wpragmas, "junk at end of %<#pragma longcall%>");
rs6000_default_long_calls = (n == integer_one_node);
}
@@ -428,8 +430,6 @@ rs6000_target_modify_macros (bool define_p, HOST_WIDE_INT flags,
rs6000_define_or_undefine_macro (define_p, "_ARCH_PWR5X");
if ((flags & OPTION_MASK_CMPB) != 0)
rs6000_define_or_undefine_macro (define_p, "_ARCH_PWR6");
- if ((flags & OPTION_MASK_MFPGPR) != 0)
- rs6000_define_or_undefine_macro (define_p, "_ARCH_PWR6X");
if ((flags & OPTION_MASK_POPCNTD) != 0)
rs6000_define_or_undefine_macro (define_p, "_ARCH_PWR7");
/* Note that the OPTION_MASK_DIRECT_MOVE flag is automatically
@@ -6140,11 +6140,11 @@ altivec_resolve_overloaded_builtin (location_t loc, tree fndecl,
/* vec_lvsl and vec_lvsr are deprecated for use with LE element order. */
if (fcode == ALTIVEC_BUILTIN_VEC_LVSL && !BYTES_BIG_ENDIAN)
warning (OPT_Wdeprecated,
- "vec_lvsl is deprecated for little endian; use "
+ "%<vec_lvsl%> is deprecated for little endian; use "
"assignment for unaligned loads and stores");
else if (fcode == ALTIVEC_BUILTIN_VEC_LVSR && !BYTES_BIG_ENDIAN)
warning (OPT_Wdeprecated,
- "vec_lvsr is deprecated for little endian; use "
+ "%<vec_lvsr%> is deprecated for little endian; use "
"assignment for unaligned loads and stores");
if (fcode == ALTIVEC_BUILTIN_VEC_MUL)
@@ -6846,7 +6846,7 @@ altivec_resolve_overloaded_builtin (location_t loc, tree fndecl,
{
if (TYPE_READONLY (TREE_TYPE (type))
&& !TYPE_READONLY (TREE_TYPE (decl_type)))
- warning (0, "passing arg %d of %qE discards qualifiers from "
+ warning (0, "passing argument %d of %qE discards qualifiers from "
"pointer target type", n + 1, fndecl);
type = build_pointer_type (build_qualified_type (TREE_TYPE (type),
0));
diff --git a/gcc/config/rs6000/rs6000-cpus.def b/gcc/config/rs6000/rs6000-cpus.def
index d0d69be..972d19f 100644
--- a/gcc/config/rs6000/rs6000-cpus.def
+++ b/gcc/config/rs6000/rs6000-cpus.def
@@ -24,10 +24,9 @@
#define ISA_2_2_MASKS (ISA_2_1_MASKS | OPTION_MASK_POPCNTB)
#define ISA_2_4_MASKS (ISA_2_2_MASKS | OPTION_MASK_FPRND)
- /* For ISA 2.05, do not add MFPGPR, since it isn't in ISA 2.06, and don't add
- ALTIVEC, since in general it isn't a win on power6. In ISA 2.04, fsel,
- fre, fsqrt, etc. were no longer documented as optional. Group masks by
- server and embedded. */
+ /* For ISA 2.05, don't add ALTIVEC, since in general it isn't a win on
+ power6. In ISA 2.04, fsel, fre, fsqrt, etc. were no longer documented
+ as optional. Group masks by server and embedded. */
#define ISA_2_5_MASKS_EMBEDDED (ISA_2_4_MASKS \
| OPTION_MASK_CMPB \
| OPTION_MASK_RECIP_PRECISION \
@@ -56,21 +55,35 @@
| OPTION_MASK_QUAD_MEMORY \
| OPTION_MASK_QUAD_MEMORY_ATOMIC)
+/* ISA masks setting fusion options. */
+#define OTHER_FUSION_MASKS (OPTION_MASK_P8_FUSION \
+ | OPTION_MASK_P8_FUSION_SIGN)
+
/* Add ISEL back into ISA 3.0, since it is supposed to be a win. Do not add
FLOAT128_HW here until we are ready to make -mfloat128 on by default. */
-#define ISA_3_0_MASKS_SERVER (ISA_2_7_MASKS_SERVER \
- | OPTION_MASK_ISEL \
- | OPTION_MASK_MODULO \
- | OPTION_MASK_P9_MINMAX \
- | OPTION_MASK_P9_MISC \
- | OPTION_MASK_P9_VECTOR)
+#define ISA_3_0_MASKS_SERVER ((ISA_2_7_MASKS_SERVER \
+ | OPTION_MASK_ISEL \
+ | OPTION_MASK_MODULO \
+ | OPTION_MASK_P9_MINMAX \
+ | OPTION_MASK_P9_MISC \
+ | OPTION_MASK_P9_VECTOR) \
+ & ~OTHER_FUSION_MASKS)
/* Support for the IEEE 128-bit floating point hardware requires a lot of the
VSX instructions that are part of ISA 3.0. */
#define ISA_3_0_MASKS_IEEE (OPTION_MASK_VSX \
| OPTION_MASK_P8_VECTOR \
- | OPTION_MASK_P9_VECTOR \
- | OPTION_MASK_DIRECT_MOVE)
+ | OPTION_MASK_P9_VECTOR)
+
+/* Support for a future processor's features. Do not enable -mpcrel until it
+ is fully functional. */
+#define ISA_FUTURE_MASKS_SERVER (ISA_3_0_MASKS_SERVER \
+ | OPTION_MASK_FUTURE \
+ | OPTION_MASK_PREFIXED_ADDR)
+
+/* Flags that need to be turned off if -mno-future. */
+#define OTHER_FUTURE_MASKS (OPTION_MASK_PCREL \
+ | OPTION_MASK_PREFIXED_ADDR)
/* Flags that need to be turned off if -mno-power9-vector. */
#define OTHER_P9_VECTOR_MASKS (OPTION_MASK_FLOAT128_HW \
@@ -112,10 +125,10 @@
| OPTION_MASK_FLOAT128_HW \
| OPTION_MASK_FLOAT128_KEYWORD \
| OPTION_MASK_FPRND \
+ | OPTION_MASK_FUTURE \
| OPTION_MASK_HTM \
| OPTION_MASK_ISEL \
| OPTION_MASK_MFCRF \
- | OPTION_MASK_MFPGPR \
| OPTION_MASK_MODULO \
| OPTION_MASK_MULHW \
| OPTION_MASK_NO_UPDATE \
@@ -124,11 +137,13 @@
| OPTION_MASK_P9_MINMAX \
| OPTION_MASK_P9_MISC \
| OPTION_MASK_P9_VECTOR \
+ | OPTION_MASK_PCREL \
| OPTION_MASK_POPCNTB \
| OPTION_MASK_POPCNTD \
| OPTION_MASK_POWERPC64 \
| OPTION_MASK_PPC_GFXOPT \
| OPTION_MASK_PPC_GPOPT \
+ | OPTION_MASK_PREFIXED_ADDR \
| OPTION_MASK_QUAD_MEMORY \
| OPTION_MASK_QUAD_MEMORY_ATOMIC \
| OPTION_MASK_RECIP_PRECISION \
@@ -219,7 +234,7 @@ RS6000_CPU ("power6", PROCESSOR_POWER6, MASK_POWERPC64 | MASK_PPC_GPOPT
| MASK_CMPB | MASK_DFP | MASK_RECIP_PRECISION)
RS6000_CPU ("power6x", PROCESSOR_POWER6, MASK_POWERPC64 | MASK_PPC_GPOPT
| MASK_PPC_GFXOPT | MASK_MFCRF | MASK_POPCNTB | MASK_FPRND
- | MASK_CMPB | MASK_DFP | MASK_MFPGPR | MASK_RECIP_PRECISION)
+ | MASK_CMPB | MASK_DFP | MASK_RECIP_PRECISION)
RS6000_CPU ("power7", PROCESSOR_POWER7, MASK_POWERPC64 | ISA_2_6_MASKS_SERVER)
RS6000_CPU ("power8", PROCESSOR_POWER8, MASK_POWERPC64 | ISA_2_7_MASKS_SERVER)
RS6000_CPU ("power9", PROCESSOR_POWER9, MASK_POWERPC64 | ISA_3_0_MASKS_SERVER)
@@ -227,3 +242,5 @@ RS6000_CPU ("powerpc", PROCESSOR_POWERPC, 0)
RS6000_CPU ("powerpc64", PROCESSOR_POWERPC64, MASK_PPC_GFXOPT | MASK_POWERPC64)
RS6000_CPU ("powerpc64le", PROCESSOR_POWER8, MASK_POWERPC64 | ISA_2_7_MASKS_SERVER)
RS6000_CPU ("rs64", PROCESSOR_RS64A, MASK_PPC_GFXOPT | MASK_POWERPC64)
+RS6000_CPU ("future", PROCESSOR_FUTURE, MASK_POWERPC64
+ | ISA_FUTURE_MASKS_SERVER)
diff --git a/gcc/config/rs6000/rs6000-internal.h b/gcc/config/rs6000/rs6000-internal.h
new file mode 100644
index 0000000..f69fa5d
--- /dev/null
+++ b/gcc/config/rs6000/rs6000-internal.h
@@ -0,0 +1,127 @@
+/* Internal to rs6000 type, variable, and function declarations and
+ definitons shared between the various rs6000 source files.
+ Copyright (C) 1991-2019 Free Software Foundation, Inc.
+ Contributed by Richard Kenner (kenner@vlsi1.ultra.nyu.edu)
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+ License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GCC; see the file COPYING3. If not see
+ <http://www.gnu.org/licenses/>. */
+
+#ifndef GCC_RS6000_INTERNAL_H
+#define GCC_RS6000_INTERNAL_H
+
+/* Structure used to define the rs6000 stack */
+typedef struct rs6000_stack {
+ int reload_completed; /* stack info won't change from here on */
+ int first_gp_reg_save; /* first callee saved GP register used */
+ int first_fp_reg_save; /* first callee saved FP register used */
+ int first_altivec_reg_save; /* first callee saved AltiVec register used */
+ int lr_save_p; /* true if the link reg needs to be saved */
+ int cr_save_p; /* true if the CR reg needs to be saved */
+ unsigned int vrsave_mask; /* mask of vec registers to save */
+ int push_p; /* true if we need to allocate stack space */
+ int calls_p; /* true if the function makes any calls */
+ int world_save_p; /* true if we're saving *everything*:
+ r13-r31, cr, f14-f31, vrsave, v20-v31 */
+ enum rs6000_abi abi; /* which ABI to use */
+ int gp_save_offset; /* offset to save GP regs from initial SP */
+ int fp_save_offset; /* offset to save FP regs from initial SP */
+ int altivec_save_offset; /* offset to save AltiVec regs from initial SP */
+ int lr_save_offset; /* offset to save LR from initial SP */
+ int cr_save_offset; /* offset to save CR from initial SP */
+ int vrsave_save_offset; /* offset to save VRSAVE from initial SP */
+ int varargs_save_offset; /* offset to save the varargs registers */
+ int ehrd_offset; /* offset to EH return data */
+ int ehcr_offset; /* offset to EH CR field data */
+ int reg_size; /* register size (4 or 8) */
+ HOST_WIDE_INT vars_size; /* variable save area size */
+ int parm_size; /* outgoing parameter size */
+ int save_size; /* save area size */
+ int fixed_size; /* fixed size of stack frame */
+ int gp_size; /* size of saved GP registers */
+ int fp_size; /* size of saved FP registers */
+ int altivec_size; /* size of saved AltiVec registers */
+ int cr_size; /* size to hold CR if not in fixed area */
+ int vrsave_size; /* size to hold VRSAVE */
+ int altivec_padding_size; /* size of altivec alignment padding */
+ HOST_WIDE_INT total_size; /* total bytes allocated for stack */
+ int savres_strategy;
+} rs6000_stack_t;
+
+
+extern int need_toc_init;
+extern char toc_label_name[10];
+extern int rs6000_pic_labelno;
+extern section *toc_section;
+
+#ifdef USING_ELFOS_H
+extern const char *rs6000_machine;
+#endif
+
+
+/* The VRSAVE bitmask puts bit %v0 as the most significant bit. */
+#define ALTIVEC_REG_BIT(REGNO) (0x80000000 >> ((REGNO) - FIRST_ALTIVEC_REGNO))
+
+
+/* Declare functions in rs6000-logue.c or called in rs6000.c
+ from rs6000-logue.c */
+
+extern int uses_TOC (void);
+extern bool rs6000_global_entry_point_needed_p (void);
+extern void rs6000_output_function_prologue (FILE *file);
+extern void rs6000_output_function_epilogue (FILE *file);
+extern bool rs6000_function_ok_for_sibcall (tree decl, tree exp);
+extern sbitmap rs6000_get_separate_components (void);
+extern sbitmap rs6000_components_for_bb (basic_block bb);
+extern void rs6000_disqualify_components (sbitmap components, edge e,
+ sbitmap edge_components,
+ bool /*is_prologue*/);
+extern void rs6000_emit_prologue_components (sbitmap components);
+extern void rs6000_emit_epilogue_components (sbitmap components);
+extern void rs6000_set_handled_components (sbitmap components);
+extern rs6000_stack_t * rs6000_stack_info (void);
+extern rtx create_TOC_reference (rtx symbol, rtx largetoc_reg);
+extern rtx rs6000_got_sym (void);
+extern struct machine_function *rs6000_init_machine_status (void);
+extern bool save_reg_p (int reg);
+extern const char * rs6000_machine_from_flags (void);
+extern void emit_asm_machine (void);
+extern bool rs6000_global_entry_point_prologue_needed_p (void);
+extern bool rs6000_keep_leaf_when_profiled (void);
+
+/* Return true if the OFFSET is valid for the quad address instructions that
+ use d-form (register + offset) addressing. */
+
+static inline bool
+quad_address_offset_p (HOST_WIDE_INT offset)
+{
+ return (IN_RANGE (offset, -32768, 32767) && ((offset) & 0xf) == 0);
+}
+
+/* Mach-O (Darwin) support for longcalls, emitted from rs6000-logue.c. */
+
+#if TARGET_MACHO
+
+typedef struct branch_island_d {
+ tree function_name;
+ tree label_name;
+ int line_number;
+ } branch_island;
+
+extern vec<branch_island, va_gc> *branch_islands;
+
+#endif
+
+#endif
diff --git a/gcc/config/rs6000/rs6000-logue.c b/gcc/config/rs6000/rs6000-logue.c
new file mode 100644
index 0000000..3fe6230
--- /dev/null
+++ b/gcc/config/rs6000/rs6000-logue.c
@@ -0,0 +1,5639 @@
+/* Subroutines used to generate function prologues and epilogues
+ on IBM RS/6000.
+ Copyright (C) 1991-2019 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 IN_TARGET_CODE 1
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "backend.h"
+#include "rtl.h"
+#include "tree.h"
+#include "memmodel.h"
+#include "df.h"
+#include "tm_p.h"
+#include "ira.h"
+#include "print-tree.h"
+#include "varasm.h"
+#include "explow.h"
+#include "expr.h"
+#include "output.h"
+#include "tree-pass.h"
+#include "rtx-vector-builder.h"
+#include "predict.h"
+#include "target.h"
+#include "stringpool.h"
+#include "attribs.h"
+#include "except.h"
+#include "langhooks.h"
+#include "optabs.h"
+#include "diagnostic-core.h"
+#include "params.h"
+#include "alias.h"
+#include "rs6000-internal.h"
+#if TARGET_MACHO
+#include "gstab.h" /* for N_SLINE */
+#include "dbxout.h" /* dbxout_ */
+#endif
+
+static int rs6000_ra_ever_killed (void);
+static void is_altivec_return_reg (rtx, void *);
+static bool rs6000_save_toc_in_prologue_p (void);
+
+static rs6000_stack_t stack_info;
+
+
+/* Label number of label created for -mrelocatable, to call to so we can
+ get the address of the GOT section */
+int rs6000_pic_labelno = 0;
+
+
+#ifndef TARGET_PROFILE_KERNEL
+#define TARGET_PROFILE_KERNEL 0
+#endif
+
+
+/* Function to init struct machine_function.
+ This will be called, via a pointer variable,
+ from push_function_context. */
+
+struct machine_function *
+rs6000_init_machine_status (void)
+{
+ stack_info.reload_completed = 0;
+ return ggc_cleared_alloc<machine_function> ();
+}
+
+/* This page contains routines that are used to determine what the
+ function prologue and epilogue code will do and write them out. */
+
+/* Determine whether the REG is really used. */
+
+bool
+save_reg_p (int reg)
+{
+ if (reg == RS6000_PIC_OFFSET_TABLE_REGNUM && !TARGET_SINGLE_PIC_BASE)
+ {
+ /* When calling eh_return, we must return true for all the cases
+ where conditional_register_usage marks the PIC offset reg
+ call used or fixed. */
+ if (crtl->calls_eh_return
+ && ((DEFAULT_ABI == ABI_V4 && flag_pic)
+ || (DEFAULT_ABI == ABI_DARWIN && flag_pic)
+ || (TARGET_TOC && TARGET_MINIMAL_TOC)))
+ return true;
+
+ /* We need to mark the PIC offset register live for the same
+ conditions as it is set up in rs6000_emit_prologue, or
+ otherwise it won't be saved before we clobber it. */
+ if (TARGET_TOC && TARGET_MINIMAL_TOC
+ && !constant_pool_empty_p ())
+ return true;
+
+ if (DEFAULT_ABI == ABI_V4
+ && (flag_pic == 1 || (flag_pic && TARGET_SECURE_PLT))
+ && df_regs_ever_live_p (RS6000_PIC_OFFSET_TABLE_REGNUM))
+ return true;
+
+ if (DEFAULT_ABI == ABI_DARWIN
+ && flag_pic && crtl->uses_pic_offset_table)
+ return true;
+ }
+
+ return !call_used_regs[reg] && df_regs_ever_live_p (reg);
+}
+
+/* Return the first fixed-point register that is required to be
+ saved. 32 if none. */
+
+int
+first_reg_to_save (void)
+{
+ int first_reg;
+
+ /* Find lowest numbered live register. */
+ for (first_reg = 13; first_reg <= 31; first_reg++)
+ if (save_reg_p (first_reg))
+ break;
+
+ return first_reg;
+}
+
+/* Similar, for FP regs. */
+
+int
+first_fp_reg_to_save (void)
+{
+ int first_reg;
+
+ /* Find lowest numbered live register. */
+ for (first_reg = 14 + 32; first_reg <= 63; first_reg++)
+ if (save_reg_p (first_reg))
+ break;
+
+ return first_reg;
+}
+
+/* Similar, for AltiVec regs. */
+
+static int
+first_altivec_reg_to_save (void)
+{
+ int i;
+
+ /* Stack frame remains as is unless we are in AltiVec ABI. */
+ if (! TARGET_ALTIVEC_ABI)
+ return LAST_ALTIVEC_REGNO + 1;
+
+ /* On Darwin, the unwind routines are compiled without
+ TARGET_ALTIVEC, and use save_world to save/restore the
+ altivec registers when necessary. */
+ if (DEFAULT_ABI == ABI_DARWIN && crtl->calls_eh_return
+ && ! TARGET_ALTIVEC)
+ return FIRST_ALTIVEC_REGNO + 20;
+
+ /* Find lowest numbered live register. */
+ for (i = FIRST_ALTIVEC_REGNO + 20; i <= LAST_ALTIVEC_REGNO; ++i)
+ if (save_reg_p (i))
+ break;
+
+ return i;
+}
+
+/* Return a 32-bit mask of the AltiVec registers we need to set in
+ VRSAVE. Bit n of the return value is 1 if Vn is live. The MSB in
+ the 32-bit word is 0. */
+
+static unsigned int
+compute_vrsave_mask (void)
+{
+ unsigned int i, mask = 0;
+
+ /* On Darwin, the unwind routines are compiled without
+ TARGET_ALTIVEC, and use save_world to save/restore the
+ call-saved altivec registers when necessary. */
+ if (DEFAULT_ABI == ABI_DARWIN && crtl->calls_eh_return
+ && ! TARGET_ALTIVEC)
+ mask |= 0xFFF;
+
+ /* First, find out if we use _any_ altivec registers. */
+ for (i = FIRST_ALTIVEC_REGNO; i <= LAST_ALTIVEC_REGNO; ++i)
+ if (df_regs_ever_live_p (i))
+ mask |= ALTIVEC_REG_BIT (i);
+
+ if (mask == 0)
+ return mask;
+
+ /* Next, remove the argument registers from the set. These must
+ be in the VRSAVE mask set by the caller, so we don't need to add
+ them in again. More importantly, the mask we compute here is
+ used to generate CLOBBERs in the set_vrsave insn, and we do not
+ wish the argument registers to die. */
+ for (i = ALTIVEC_ARG_MIN_REG; i < (unsigned) crtl->args.info.vregno; i++)
+ mask &= ~ALTIVEC_REG_BIT (i);
+
+ /* Similarly, remove the return value from the set. */
+ {
+ bool yes = false;
+ diddle_return_value (is_altivec_return_reg, &yes);
+ if (yes)
+ mask &= ~ALTIVEC_REG_BIT (ALTIVEC_ARG_RETURN);
+ }
+
+ return mask;
+}
+
+/* For a very restricted set of circumstances, we can cut down the
+ size of prologues/epilogues by calling our own save/restore-the-world
+ routines. */
+
+static void
+compute_save_world_info (rs6000_stack_t *info)
+{
+ info->world_save_p = 1;
+ info->world_save_p
+ = (WORLD_SAVE_P (info)
+ && DEFAULT_ABI == ABI_DARWIN
+ && !cfun->has_nonlocal_label
+ && info->first_fp_reg_save == FIRST_SAVED_FP_REGNO
+ && info->first_gp_reg_save == FIRST_SAVED_GP_REGNO
+ && info->first_altivec_reg_save == FIRST_SAVED_ALTIVEC_REGNO
+ && info->cr_save_p);
+
+ /* This will not work in conjunction with sibcalls. Make sure there
+ are none. (This check is expensive, but seldom executed.) */
+ if (WORLD_SAVE_P (info))
+ {
+ rtx_insn *insn;
+ for (insn = get_last_insn_anywhere (); insn; insn = PREV_INSN (insn))
+ if (CALL_P (insn) && SIBLING_CALL_P (insn))
+ {
+ info->world_save_p = 0;
+ break;
+ }
+ }
+
+ if (WORLD_SAVE_P (info))
+ {
+ /* Even if we're not touching VRsave, make sure there's room on the
+ stack for it, if it looks like we're calling SAVE_WORLD, which
+ will attempt to save it. */
+ info->vrsave_size = 4;
+
+ /* If we are going to save the world, we need to save the link register too. */
+ info->lr_save_p = 1;
+
+ /* "Save" the VRsave register too if we're saving the world. */
+ if (info->vrsave_mask == 0)
+ info->vrsave_mask = compute_vrsave_mask ();
+
+ /* Because the Darwin register save/restore routines only handle
+ F14 .. F31 and V20 .. V31 as per the ABI, perform a consistency
+ check. */
+ gcc_assert (info->first_fp_reg_save >= FIRST_SAVED_FP_REGNO
+ && (info->first_altivec_reg_save
+ >= FIRST_SAVED_ALTIVEC_REGNO));
+ }
+
+ return;
+}
+
+
+static void
+is_altivec_return_reg (rtx reg, void *xyes)
+{
+ bool *yes = (bool *) xyes;
+ if (REGNO (reg) == ALTIVEC_ARG_RETURN)
+ *yes = true;
+}
+
+
+/* Return whether REG is a global user reg or has been specifed by
+ -ffixed-REG. We should not restore these, and so cannot use
+ lmw or out-of-line restore functions if there are any. We also
+ can't save them (well, emit frame notes for them), because frame
+ unwinding during exception handling will restore saved registers. */
+
+static bool
+fixed_reg_p (int reg)
+{
+ /* Ignore fixed_regs[RS6000_PIC_OFFSET_TABLE_REGNUM] when the
+ backend sets it, overriding anything the user might have given. */
+ if (reg == RS6000_PIC_OFFSET_TABLE_REGNUM
+ && ((DEFAULT_ABI == ABI_V4 && flag_pic)
+ || (DEFAULT_ABI == ABI_DARWIN && flag_pic)
+ || (TARGET_TOC && TARGET_MINIMAL_TOC)))
+ return false;
+
+ return fixed_regs[reg];
+}
+
+/* Determine the strategy for savings/restoring registers. */
+
+enum {
+ SAVE_MULTIPLE = 0x1,
+ SAVE_INLINE_GPRS = 0x2,
+ SAVE_INLINE_FPRS = 0x4,
+ SAVE_NOINLINE_GPRS_SAVES_LR = 0x8,
+ SAVE_NOINLINE_FPRS_SAVES_LR = 0x10,
+ SAVE_INLINE_VRS = 0x20,
+ REST_MULTIPLE = 0x100,
+ REST_INLINE_GPRS = 0x200,
+ REST_INLINE_FPRS = 0x400,
+ REST_NOINLINE_FPRS_DOESNT_RESTORE_LR = 0x800,
+ REST_INLINE_VRS = 0x1000
+};
+
+static int
+rs6000_savres_strategy (rs6000_stack_t *info,
+ bool using_static_chain_p)
+{
+ int strategy = 0;
+
+ /* Select between in-line and out-of-line save and restore of regs.
+ First, all the obvious cases where we don't use out-of-line. */
+ if (crtl->calls_eh_return
+ || cfun->machine->ra_need_lr)
+ strategy |= (SAVE_INLINE_FPRS | REST_INLINE_FPRS
+ | SAVE_INLINE_GPRS | REST_INLINE_GPRS
+ | SAVE_INLINE_VRS | REST_INLINE_VRS);
+
+ if (info->first_gp_reg_save == 32)
+ strategy |= SAVE_INLINE_GPRS | REST_INLINE_GPRS;
+
+ if (info->first_fp_reg_save == 64)
+ strategy |= SAVE_INLINE_FPRS | REST_INLINE_FPRS;
+
+ if (info->first_altivec_reg_save == LAST_ALTIVEC_REGNO + 1)
+ strategy |= SAVE_INLINE_VRS | REST_INLINE_VRS;
+
+ /* Define cutoff for using out-of-line functions to save registers. */
+ if (DEFAULT_ABI == ABI_V4 || TARGET_ELF)
+ {
+ if (!optimize_size)
+ {
+ strategy |= SAVE_INLINE_FPRS | REST_INLINE_FPRS;
+ strategy |= SAVE_INLINE_GPRS | REST_INLINE_GPRS;
+ strategy |= SAVE_INLINE_VRS | REST_INLINE_VRS;
+ }
+ else
+ {
+ /* Prefer out-of-line restore if it will exit. */
+ if (info->first_fp_reg_save > 61)
+ strategy |= SAVE_INLINE_FPRS;
+ if (info->first_gp_reg_save > 29)
+ {
+ if (info->first_fp_reg_save == 64)
+ strategy |= SAVE_INLINE_GPRS;
+ else
+ strategy |= SAVE_INLINE_GPRS | REST_INLINE_GPRS;
+ }
+ if (info->first_altivec_reg_save == LAST_ALTIVEC_REGNO)
+ strategy |= SAVE_INLINE_VRS | REST_INLINE_VRS;
+ }
+ }
+ else if (DEFAULT_ABI == ABI_DARWIN)
+ {
+ if (info->first_fp_reg_save > 60)
+ strategy |= SAVE_INLINE_FPRS | REST_INLINE_FPRS;
+ if (info->first_gp_reg_save > 29)
+ strategy |= SAVE_INLINE_GPRS | REST_INLINE_GPRS;
+ strategy |= SAVE_INLINE_VRS | REST_INLINE_VRS;
+ }
+ else
+ {
+ gcc_checking_assert (DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2);
+ if ((flag_shrink_wrap_separate && optimize_function_for_speed_p (cfun))
+ || info->first_fp_reg_save > 61)
+ strategy |= SAVE_INLINE_FPRS | REST_INLINE_FPRS;
+ strategy |= SAVE_INLINE_GPRS | REST_INLINE_GPRS;
+ strategy |= SAVE_INLINE_VRS | REST_INLINE_VRS;
+ }
+
+ /* Don't bother to try to save things out-of-line if r11 is occupied
+ by the static chain. It would require too much fiddling and the
+ static chain is rarely used anyway. FPRs are saved w.r.t the stack
+ pointer on Darwin, and AIX uses r1 or r12. */
+ if (using_static_chain_p
+ && (DEFAULT_ABI == ABI_V4 || DEFAULT_ABI == ABI_DARWIN))
+ strategy |= ((DEFAULT_ABI == ABI_DARWIN ? 0 : SAVE_INLINE_FPRS)
+ | SAVE_INLINE_GPRS
+ | SAVE_INLINE_VRS);
+
+ /* Don't ever restore fixed regs. That means we can't use the
+ out-of-line register restore functions if a fixed reg is in the
+ range of regs restored. */
+ if (!(strategy & REST_INLINE_FPRS))
+ for (int i = info->first_fp_reg_save; i < 64; i++)
+ if (fixed_regs[i])
+ {
+ strategy |= REST_INLINE_FPRS;
+ break;
+ }
+
+ /* We can only use the out-of-line routines to restore fprs if we've
+ saved all the registers from first_fp_reg_save in the prologue.
+ Otherwise, we risk loading garbage. Of course, if we have saved
+ out-of-line then we know we haven't skipped any fprs. */
+ if ((strategy & SAVE_INLINE_FPRS)
+ && !(strategy & REST_INLINE_FPRS))
+ for (int i = info->first_fp_reg_save; i < 64; i++)
+ if (!save_reg_p (i))
+ {
+ strategy |= REST_INLINE_FPRS;
+ break;
+ }
+
+ /* Similarly, for altivec regs. */
+ if (!(strategy & REST_INLINE_VRS))
+ for (int i = info->first_altivec_reg_save; i < LAST_ALTIVEC_REGNO + 1; i++)
+ if (fixed_regs[i])
+ {
+ strategy |= REST_INLINE_VRS;
+ break;
+ }
+
+ if ((strategy & SAVE_INLINE_VRS)
+ && !(strategy & REST_INLINE_VRS))
+ for (int i = info->first_altivec_reg_save; i < LAST_ALTIVEC_REGNO + 1; i++)
+ if (!save_reg_p (i))
+ {
+ strategy |= REST_INLINE_VRS;
+ break;
+ }
+
+ /* info->lr_save_p isn't yet set if the only reason lr needs to be
+ saved is an out-of-line save or restore. Set up the value for
+ the next test (excluding out-of-line gprs). */
+ bool lr_save_p = (info->lr_save_p
+ || !(strategy & SAVE_INLINE_FPRS)
+ || !(strategy & SAVE_INLINE_VRS)
+ || !(strategy & REST_INLINE_FPRS)
+ || !(strategy & REST_INLINE_VRS));
+
+ if (TARGET_MULTIPLE
+ && !TARGET_POWERPC64
+ && info->first_gp_reg_save < 31
+ && !(flag_shrink_wrap
+ && flag_shrink_wrap_separate
+ && optimize_function_for_speed_p (cfun)))
+ {
+ int count = 0;
+ for (int i = info->first_gp_reg_save; i < 32; i++)
+ if (save_reg_p (i))
+ count++;
+
+ if (count <= 1)
+ /* Don't use store multiple if only one reg needs to be
+ saved. This can occur for example when the ABI_V4 pic reg
+ (r30) needs to be saved to make calls, but r31 is not
+ used. */
+ strategy |= SAVE_INLINE_GPRS | REST_INLINE_GPRS;
+ else
+ {
+ /* Prefer store multiple for saves over out-of-line
+ routines, since the store-multiple instruction will
+ always be smaller. */
+ strategy |= SAVE_INLINE_GPRS | SAVE_MULTIPLE;
+
+ /* The situation is more complicated with load multiple.
+ We'd prefer to use the out-of-line routines for restores,
+ since the "exit" out-of-line routines can handle the
+ restore of LR and the frame teardown. However if doesn't
+ make sense to use the out-of-line routine if that is the
+ only reason we'd need to save LR, and we can't use the
+ "exit" out-of-line gpr restore if we have saved some
+ fprs; In those cases it is advantageous to use load
+ multiple when available. */
+ if (info->first_fp_reg_save != 64 || !lr_save_p)
+ strategy |= REST_INLINE_GPRS | REST_MULTIPLE;
+ }
+ }
+
+ /* Using the "exit" out-of-line routine does not improve code size
+ if using it would require lr to be saved and if only saving one
+ or two gprs. */
+ else if (!lr_save_p && info->first_gp_reg_save > 29)
+ strategy |= SAVE_INLINE_GPRS | REST_INLINE_GPRS;
+
+ /* Don't ever restore fixed regs. */
+ if ((strategy & (REST_INLINE_GPRS | REST_MULTIPLE)) != REST_INLINE_GPRS)
+ for (int i = info->first_gp_reg_save; i < 32; i++)
+ if (fixed_reg_p (i))
+ {
+ strategy |= REST_INLINE_GPRS;
+ strategy &= ~REST_MULTIPLE;
+ break;
+ }
+
+ /* We can only use load multiple or the out-of-line routines to
+ restore gprs if we've saved all the registers from
+ first_gp_reg_save. Otherwise, we risk loading garbage.
+ Of course, if we have saved out-of-line or used stmw then we know
+ we haven't skipped any gprs. */
+ if ((strategy & (SAVE_INLINE_GPRS | SAVE_MULTIPLE)) == SAVE_INLINE_GPRS
+ && (strategy & (REST_INLINE_GPRS | REST_MULTIPLE)) != REST_INLINE_GPRS)
+ for (int i = info->first_gp_reg_save; i < 32; i++)
+ if (!save_reg_p (i))
+ {
+ strategy |= REST_INLINE_GPRS;
+ strategy &= ~REST_MULTIPLE;
+ break;
+ }
+
+ if (TARGET_ELF && TARGET_64BIT)
+ {
+ if (!(strategy & SAVE_INLINE_FPRS))
+ strategy |= SAVE_NOINLINE_FPRS_SAVES_LR;
+ else if (!(strategy & SAVE_INLINE_GPRS)
+ && info->first_fp_reg_save == 64)
+ strategy |= SAVE_NOINLINE_GPRS_SAVES_LR;
+ }
+ else if (TARGET_AIX && !(strategy & REST_INLINE_FPRS))
+ strategy |= REST_NOINLINE_FPRS_DOESNT_RESTORE_LR;
+
+ if (TARGET_MACHO && !(strategy & SAVE_INLINE_FPRS))
+ strategy |= SAVE_NOINLINE_FPRS_SAVES_LR;
+
+ return strategy;
+}
+
+/* Calculate the stack information for the current function. This is
+ complicated by having two separate calling sequences, the AIX calling
+ sequence and the V.4 calling sequence.
+
+ AIX (and Darwin/Mac OS X) stack frames look like:
+ 32-bit 64-bit
+ SP----> +---------------------------------------+
+ | back chain to caller | 0 0
+ +---------------------------------------+
+ | saved CR | 4 8 (8-11)
+ +---------------------------------------+
+ | saved LR | 8 16
+ +---------------------------------------+
+ | reserved for compilers | 12 24
+ +---------------------------------------+
+ | reserved for binders | 16 32
+ +---------------------------------------+
+ | saved TOC pointer | 20 40
+ +---------------------------------------+
+ | Parameter save area (+padding*) (P) | 24 48
+ +---------------------------------------+
+ | Alloca space (A) | 24+P etc.
+ +---------------------------------------+
+ | Local variable space (L) | 24+P+A
+ +---------------------------------------+
+ | Float/int conversion temporary (X) | 24+P+A+L
+ +---------------------------------------+
+ | Save area for AltiVec registers (W) | 24+P+A+L+X
+ +---------------------------------------+
+ | AltiVec alignment padding (Y) | 24+P+A+L+X+W
+ +---------------------------------------+
+ | Save area for VRSAVE register (Z) | 24+P+A+L+X+W+Y
+ +---------------------------------------+
+ | Save area for GP registers (G) | 24+P+A+X+L+X+W+Y+Z
+ +---------------------------------------+
+ | Save area for FP registers (F) | 24+P+A+X+L+X+W+Y+Z+G
+ +---------------------------------------+
+ old SP->| back chain to caller's caller |
+ +---------------------------------------+
+
+ * If the alloca area is present, the parameter save area is
+ padded so that the former starts 16-byte aligned.
+
+ The required alignment for AIX configurations is two words (i.e., 8
+ or 16 bytes).
+
+ The ELFv2 ABI is a variant of the AIX ABI. Stack frames look like:
+
+ SP----> +---------------------------------------+
+ | Back chain to caller | 0
+ +---------------------------------------+
+ | Save area for CR | 8
+ +---------------------------------------+
+ | Saved LR | 16
+ +---------------------------------------+
+ | Saved TOC pointer | 24
+ +---------------------------------------+
+ | Parameter save area (+padding*) (P) | 32
+ +---------------------------------------+
+ | Alloca space (A) | 32+P
+ +---------------------------------------+
+ | Local variable space (L) | 32+P+A
+ +---------------------------------------+
+ | Save area for AltiVec registers (W) | 32+P+A+L
+ +---------------------------------------+
+ | AltiVec alignment padding (Y) | 32+P+A+L+W
+ +---------------------------------------+
+ | Save area for GP registers (G) | 32+P+A+L+W+Y
+ +---------------------------------------+
+ | Save area for FP registers (F) | 32+P+A+L+W+Y+G
+ +---------------------------------------+
+ old SP->| back chain to caller's caller | 32+P+A+L+W+Y+G+F
+ +---------------------------------------+
+
+ * If the alloca area is present, the parameter save area is
+ padded so that the former starts 16-byte aligned.
+
+ V.4 stack frames look like:
+
+ SP----> +---------------------------------------+
+ | back chain to caller | 0
+ +---------------------------------------+
+ | caller's saved LR | 4
+ +---------------------------------------+
+ | Parameter save area (+padding*) (P) | 8
+ +---------------------------------------+
+ | Alloca space (A) | 8+P
+ +---------------------------------------+
+ | Varargs save area (V) | 8+P+A
+ +---------------------------------------+
+ | Local variable space (L) | 8+P+A+V
+ +---------------------------------------+
+ | Float/int conversion temporary (X) | 8+P+A+V+L
+ +---------------------------------------+
+ | Save area for AltiVec registers (W) | 8+P+A+V+L+X
+ +---------------------------------------+
+ | AltiVec alignment padding (Y) | 8+P+A+V+L+X+W
+ +---------------------------------------+
+ | Save area for VRSAVE register (Z) | 8+P+A+V+L+X+W+Y
+ +---------------------------------------+
+ | saved CR (C) | 8+P+A+V+L+X+W+Y+Z
+ +---------------------------------------+
+ | Save area for GP registers (G) | 8+P+A+V+L+X+W+Y+Z+C
+ +---------------------------------------+
+ | Save area for FP registers (F) | 8+P+A+V+L+X+W+Y+Z+C+G
+ +---------------------------------------+
+ old SP->| back chain to caller's caller |
+ +---------------------------------------+
+
+ * If the alloca area is present and the required alignment is
+ 16 bytes, the parameter save area is padded so that the
+ alloca area starts 16-byte aligned.
+
+ The required alignment for V.4 is 16 bytes, or 8 bytes if -meabi is
+ given. (But note below and in sysv4.h that we require only 8 and
+ may round up the size of our stack frame anyways. The historical
+ reason is early versions of powerpc-linux which didn't properly
+ align the stack at program startup. A happy side-effect is that
+ -mno-eabi libraries can be used with -meabi programs.)
+
+ The EABI configuration defaults to the V.4 layout. However,
+ the stack alignment requirements may differ. If -mno-eabi is not
+ given, the required stack alignment is 8 bytes; if -mno-eabi is
+ given, the required alignment is 16 bytes. (But see V.4 comment
+ above.) */
+
+#ifndef ABI_STACK_BOUNDARY
+#define ABI_STACK_BOUNDARY STACK_BOUNDARY
+#endif
+
+rs6000_stack_t *
+rs6000_stack_info (void)
+{
+ /* We should never be called for thunks, we are not set up for that. */
+ gcc_assert (!cfun->is_thunk);
+
+ rs6000_stack_t *info = &stack_info;
+ int reg_size = TARGET_32BIT ? 4 : 8;
+ int ehrd_size;
+ int ehcr_size;
+ int save_align;
+ int first_gp;
+ HOST_WIDE_INT non_fixed_size;
+ bool using_static_chain_p;
+
+ if (reload_completed && info->reload_completed)
+ return info;
+
+ memset (info, 0, sizeof (*info));
+ info->reload_completed = reload_completed;
+
+ /* Select which calling sequence. */
+ info->abi = DEFAULT_ABI;
+
+ /* Calculate which registers need to be saved & save area size. */
+ info->first_gp_reg_save = first_reg_to_save ();
+ /* Assume that we will have to save RS6000_PIC_OFFSET_TABLE_REGNUM,
+ even if it currently looks like we won't. Reload may need it to
+ get at a constant; if so, it will have already created a constant
+ pool entry for it. */
+ if (((TARGET_TOC && TARGET_MINIMAL_TOC)
+ || (flag_pic == 1 && DEFAULT_ABI == ABI_V4)
+ || (flag_pic && DEFAULT_ABI == ABI_DARWIN))
+ && crtl->uses_const_pool
+ && info->first_gp_reg_save > RS6000_PIC_OFFSET_TABLE_REGNUM)
+ first_gp = RS6000_PIC_OFFSET_TABLE_REGNUM;
+ else
+ first_gp = info->first_gp_reg_save;
+
+ info->gp_size = reg_size * (32 - first_gp);
+
+ info->first_fp_reg_save = first_fp_reg_to_save ();
+ info->fp_size = 8 * (64 - info->first_fp_reg_save);
+
+ info->first_altivec_reg_save = first_altivec_reg_to_save ();
+ info->altivec_size = 16 * (LAST_ALTIVEC_REGNO + 1
+ - info->first_altivec_reg_save);
+
+ /* Does this function call anything? */
+ info->calls_p = (!crtl->is_leaf || cfun->machine->ra_needs_full_frame);
+
+ /* Determine if we need to save the condition code registers. */
+ if (save_reg_p (CR2_REGNO)
+ || save_reg_p (CR3_REGNO)
+ || save_reg_p (CR4_REGNO))
+ {
+ info->cr_save_p = 1;
+ if (DEFAULT_ABI == ABI_V4)
+ info->cr_size = reg_size;
+ }
+
+ /* If the current function calls __builtin_eh_return, then we need
+ to allocate stack space for registers that will hold data for
+ the exception handler. */
+ if (crtl->calls_eh_return)
+ {
+ unsigned int i;
+ for (i = 0; EH_RETURN_DATA_REGNO (i) != INVALID_REGNUM; ++i)
+ continue;
+
+ ehrd_size = i * UNITS_PER_WORD;
+ }
+ else
+ ehrd_size = 0;
+
+ /* In the ELFv2 ABI, we also need to allocate space for separate
+ CR field save areas if the function calls __builtin_eh_return. */
+ if (DEFAULT_ABI == ABI_ELFv2 && crtl->calls_eh_return)
+ {
+ /* This hard-codes that we have three call-saved CR fields. */
+ ehcr_size = 3 * reg_size;
+ /* We do *not* use the regular CR save mechanism. */
+ info->cr_save_p = 0;
+ }
+ else
+ ehcr_size = 0;
+
+ /* Determine various sizes. */
+ info->reg_size = reg_size;
+ info->fixed_size = RS6000_SAVE_AREA;
+ info->vars_size = RS6000_ALIGN (get_frame_size (), 8);
+ if (cfun->calls_alloca)
+ info->parm_size =
+ RS6000_ALIGN (crtl->outgoing_args_size + info->fixed_size,
+ STACK_BOUNDARY / BITS_PER_UNIT) - info->fixed_size;
+ else
+ info->parm_size = RS6000_ALIGN (crtl->outgoing_args_size,
+ TARGET_ALTIVEC ? 16 : 8);
+ if (FRAME_GROWS_DOWNWARD)
+ info->vars_size
+ += RS6000_ALIGN (info->fixed_size + info->vars_size + info->parm_size,
+ ABI_STACK_BOUNDARY / BITS_PER_UNIT)
+ - (info->fixed_size + info->vars_size + info->parm_size);
+
+ if (TARGET_ALTIVEC_ABI)
+ info->vrsave_mask = compute_vrsave_mask ();
+
+ if (TARGET_ALTIVEC_VRSAVE && info->vrsave_mask)
+ info->vrsave_size = 4;
+
+ compute_save_world_info (info);
+
+ /* Calculate the offsets. */
+ switch (DEFAULT_ABI)
+ {
+ case ABI_NONE:
+ default:
+ gcc_unreachable ();
+
+ case ABI_AIX:
+ case ABI_ELFv2:
+ case ABI_DARWIN:
+ info->fp_save_offset = -info->fp_size;
+ info->gp_save_offset = info->fp_save_offset - info->gp_size;
+
+ if (TARGET_ALTIVEC_ABI)
+ {
+ info->vrsave_save_offset = info->gp_save_offset - info->vrsave_size;
+
+ /* Align stack so vector save area is on a quadword boundary.
+ The padding goes above the vectors. */
+ if (info->altivec_size != 0)
+ info->altivec_padding_size = info->vrsave_save_offset & 0xF;
+
+ info->altivec_save_offset = info->vrsave_save_offset
+ - info->altivec_padding_size
+ - info->altivec_size;
+ gcc_assert (info->altivec_size == 0
+ || info->altivec_save_offset % 16 == 0);
+
+ /* Adjust for AltiVec case. */
+ info->ehrd_offset = info->altivec_save_offset - ehrd_size;
+ }
+ else
+ info->ehrd_offset = info->gp_save_offset - ehrd_size;
+
+ info->ehcr_offset = info->ehrd_offset - ehcr_size;
+ info->cr_save_offset = reg_size; /* first word when 64-bit. */
+ info->lr_save_offset = 2*reg_size;
+ break;
+
+ case ABI_V4:
+ info->fp_save_offset = -info->fp_size;
+ info->gp_save_offset = info->fp_save_offset - info->gp_size;
+ info->cr_save_offset = info->gp_save_offset - info->cr_size;
+
+ if (TARGET_ALTIVEC_ABI)
+ {
+ info->vrsave_save_offset = info->cr_save_offset - info->vrsave_size;
+
+ /* Align stack so vector save area is on a quadword boundary. */
+ if (info->altivec_size != 0)
+ info->altivec_padding_size = 16 - (-info->vrsave_save_offset % 16);
+
+ info->altivec_save_offset = info->vrsave_save_offset
+ - info->altivec_padding_size
+ - info->altivec_size;
+
+ /* Adjust for AltiVec case. */
+ info->ehrd_offset = info->altivec_save_offset;
+ }
+ else
+ info->ehrd_offset = info->cr_save_offset;
+
+ info->ehrd_offset -= ehrd_size;
+ info->lr_save_offset = reg_size;
+ }
+
+ save_align = (TARGET_ALTIVEC_ABI || DEFAULT_ABI == ABI_DARWIN) ? 16 : 8;
+ info->save_size = RS6000_ALIGN (info->fp_size
+ + info->gp_size
+ + info->altivec_size
+ + info->altivec_padding_size
+ + ehrd_size
+ + ehcr_size
+ + info->cr_size
+ + info->vrsave_size,
+ save_align);
+
+ non_fixed_size = info->vars_size + info->parm_size + info->save_size;
+
+ info->total_size = RS6000_ALIGN (non_fixed_size + info->fixed_size,
+ ABI_STACK_BOUNDARY / BITS_PER_UNIT);
+
+ /* Determine if we need to save the link register. */
+ if (info->calls_p
+ || ((DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2)
+ && crtl->profile
+ && !TARGET_PROFILE_KERNEL)
+ || (DEFAULT_ABI == ABI_V4 && cfun->calls_alloca)
+#ifdef TARGET_RELOCATABLE
+ || (DEFAULT_ABI == ABI_V4
+ && (TARGET_RELOCATABLE || flag_pic > 1)
+ && !constant_pool_empty_p ())
+#endif
+ || rs6000_ra_ever_killed ())
+ info->lr_save_p = 1;
+
+ using_static_chain_p = (cfun->static_chain_decl != NULL_TREE
+ && df_regs_ever_live_p (STATIC_CHAIN_REGNUM)
+ && call_used_regs[STATIC_CHAIN_REGNUM]);
+ info->savres_strategy = rs6000_savres_strategy (info, using_static_chain_p);
+
+ if (!(info->savres_strategy & SAVE_INLINE_GPRS)
+ || !(info->savres_strategy & SAVE_INLINE_FPRS)
+ || !(info->savres_strategy & SAVE_INLINE_VRS)
+ || !(info->savres_strategy & REST_INLINE_GPRS)
+ || !(info->savres_strategy & REST_INLINE_FPRS)
+ || !(info->savres_strategy & REST_INLINE_VRS))
+ info->lr_save_p = 1;
+
+ if (info->lr_save_p)
+ df_set_regs_ever_live (LR_REGNO, true);
+
+ /* Determine if we need to allocate any stack frame:
+
+ For AIX we need to push the stack if a frame pointer is needed
+ (because the stack might be dynamically adjusted), if we are
+ debugging, if we make calls, or if the sum of fp_save, gp_save,
+ and local variables are more than the space needed to save all
+ non-volatile registers: 32-bit: 18*8 + 19*4 = 220 or 64-bit: 18*8
+ + 18*8 = 288 (GPR13 reserved).
+
+ For V.4 we don't have the stack cushion that AIX uses, but assume
+ that the debugger can handle stackless frames. */
+
+ if (info->calls_p)
+ info->push_p = 1;
+
+ else if (DEFAULT_ABI == ABI_V4)
+ info->push_p = non_fixed_size != 0;
+
+ else if (frame_pointer_needed)
+ info->push_p = 1;
+
+ else if (TARGET_XCOFF && write_symbols != NO_DEBUG)
+ info->push_p = 1;
+
+ else
+ info->push_p = non_fixed_size > (TARGET_32BIT ? 220 : 288);
+
+ return info;
+}
+
+static void
+debug_stack_info (rs6000_stack_t *info)
+{
+ const char *abi_string;
+
+ if (! info)
+ info = rs6000_stack_info ();
+
+ fprintf (stderr, "\nStack information for function %s:\n",
+ ((current_function_decl && DECL_NAME (current_function_decl))
+ ? IDENTIFIER_POINTER (DECL_NAME (current_function_decl))
+ : "<unknown>"));
+
+ switch (info->abi)
+ {
+ default: abi_string = "Unknown"; break;
+ case ABI_NONE: abi_string = "NONE"; break;
+ case ABI_AIX: abi_string = "AIX"; break;
+ case ABI_ELFv2: abi_string = "ELFv2"; break;
+ case ABI_DARWIN: abi_string = "Darwin"; break;
+ case ABI_V4: abi_string = "V.4"; break;
+ }
+
+ fprintf (stderr, "\tABI = %5s\n", abi_string);
+
+ if (TARGET_ALTIVEC_ABI)
+ fprintf (stderr, "\tALTIVEC ABI extensions enabled.\n");
+
+ if (info->first_gp_reg_save != 32)
+ fprintf (stderr, "\tfirst_gp_reg_save = %5d\n", info->first_gp_reg_save);
+
+ if (info->first_fp_reg_save != 64)
+ fprintf (stderr, "\tfirst_fp_reg_save = %5d\n", info->first_fp_reg_save);
+
+ if (info->first_altivec_reg_save <= LAST_ALTIVEC_REGNO)
+ fprintf (stderr, "\tfirst_altivec_reg_save = %5d\n",
+ info->first_altivec_reg_save);
+
+ if (info->lr_save_p)
+ fprintf (stderr, "\tlr_save_p = %5d\n", info->lr_save_p);
+
+ if (info->cr_save_p)
+ fprintf (stderr, "\tcr_save_p = %5d\n", info->cr_save_p);
+
+ if (info->vrsave_mask)
+ fprintf (stderr, "\tvrsave_mask = 0x%x\n", info->vrsave_mask);
+
+ if (info->push_p)
+ fprintf (stderr, "\tpush_p = %5d\n", info->push_p);
+
+ if (info->calls_p)
+ fprintf (stderr, "\tcalls_p = %5d\n", info->calls_p);
+
+ if (info->gp_size)
+ fprintf (stderr, "\tgp_save_offset = %5d\n", info->gp_save_offset);
+
+ if (info->fp_size)
+ fprintf (stderr, "\tfp_save_offset = %5d\n", info->fp_save_offset);
+
+ if (info->altivec_size)
+ fprintf (stderr, "\taltivec_save_offset = %5d\n",
+ info->altivec_save_offset);
+
+ if (info->vrsave_size)
+ fprintf (stderr, "\tvrsave_save_offset = %5d\n",
+ info->vrsave_save_offset);
+
+ if (info->lr_save_p)
+ fprintf (stderr, "\tlr_save_offset = %5d\n", info->lr_save_offset);
+
+ if (info->cr_save_p)
+ fprintf (stderr, "\tcr_save_offset = %5d\n", info->cr_save_offset);
+
+ if (info->varargs_save_offset)
+ fprintf (stderr, "\tvarargs_save_offset = %5d\n", info->varargs_save_offset);
+
+ if (info->total_size)
+ fprintf (stderr, "\ttotal_size = " HOST_WIDE_INT_PRINT_DEC"\n",
+ info->total_size);
+
+ if (info->vars_size)
+ fprintf (stderr, "\tvars_size = " HOST_WIDE_INT_PRINT_DEC"\n",
+ info->vars_size);
+
+ if (info->parm_size)
+ fprintf (stderr, "\tparm_size = %5d\n", info->parm_size);
+
+ if (info->fixed_size)
+ fprintf (stderr, "\tfixed_size = %5d\n", info->fixed_size);
+
+ if (info->gp_size)
+ fprintf (stderr, "\tgp_size = %5d\n", info->gp_size);
+
+ if (info->fp_size)
+ fprintf (stderr, "\tfp_size = %5d\n", info->fp_size);
+
+ if (info->altivec_size)
+ fprintf (stderr, "\taltivec_size = %5d\n", info->altivec_size);
+
+ if (info->vrsave_size)
+ fprintf (stderr, "\tvrsave_size = %5d\n", info->vrsave_size);
+
+ if (info->altivec_padding_size)
+ fprintf (stderr, "\taltivec_padding_size= %5d\n",
+ info->altivec_padding_size);
+
+ if (info->cr_size)
+ fprintf (stderr, "\tcr_size = %5d\n", info->cr_size);
+
+ if (info->save_size)
+ fprintf (stderr, "\tsave_size = %5d\n", info->save_size);
+
+ if (info->reg_size != 4)
+ fprintf (stderr, "\treg_size = %5d\n", info->reg_size);
+
+ fprintf (stderr, "\tsave-strategy = %04x\n", info->savres_strategy);
+
+ if (info->abi == ABI_DARWIN)
+ fprintf (stderr, "\tWORLD_SAVE_P = %5d\n", WORLD_SAVE_P(info));
+
+ fprintf (stderr, "\n");
+}
+
+rtx
+rs6000_return_addr (int count, rtx frame)
+{
+ /* We can't use get_hard_reg_initial_val for LR when count == 0 if LR
+ is trashed by the prologue, as it is for PIC on ABI_V4 and Darwin. */
+ if (count != 0
+ || ((DEFAULT_ABI == ABI_V4 || DEFAULT_ABI == ABI_DARWIN) && flag_pic))
+ {
+ cfun->machine->ra_needs_full_frame = 1;
+
+ if (count == 0)
+ /* FRAME is set to frame_pointer_rtx by the generic code, but that
+ is good for loading 0(r1) only when !FRAME_GROWS_DOWNWARD. */
+ frame = stack_pointer_rtx;
+ rtx prev_frame_addr = memory_address (Pmode, frame);
+ rtx prev_frame = copy_to_reg (gen_rtx_MEM (Pmode, prev_frame_addr));
+ rtx lr_save_off = plus_constant (Pmode,
+ prev_frame, RETURN_ADDRESS_OFFSET);
+ rtx lr_save_addr = memory_address (Pmode, lr_save_off);
+ return gen_rtx_MEM (Pmode, lr_save_addr);
+ }
+
+ cfun->machine->ra_need_lr = 1;
+ return get_hard_reg_initial_val (Pmode, LR_REGNO);
+}
+
+/* Helper function for rs6000_function_ok_for_sibcall. */
+
+bool
+rs6000_decl_ok_for_sibcall (tree decl)
+{
+ /* Sibcalls are always fine for the Darwin ABI. */
+ if (DEFAULT_ABI == ABI_DARWIN)
+ return true;
+
+ if (DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2)
+ {
+ /* Under the AIX or ELFv2 ABIs we can't allow calls to non-local
+ functions, because the callee may have a different TOC pointer to
+ the caller and there's no way to ensure we restore the TOC when
+ we return. */
+ if (!decl || DECL_EXTERNAL (decl) || DECL_WEAK (decl)
+ || !(*targetm.binds_local_p) (decl))
+ return false;
+
+ /* Similarly, if the caller preserves the TOC pointer and the callee
+ doesn't (or vice versa), proper TOC setup or restoration will be
+ missed. For example, suppose A, B, and C are in the same binary
+ and A -> B -> C. A and B preserve the TOC pointer but C does not,
+ and B -> C is eligible as a sibcall. A will call B through its
+ local entry point, so A will not restore its TOC itself. B calls
+ C with a sibcall, so it will not restore the TOC. C does not
+ preserve the TOC, so it may clobber r2 with impunity. Returning
+ from C will result in a corrupted TOC for A. */
+ else if (rs6000_fndecl_pcrel_p (decl) != rs6000_pcrel_p (cfun))
+ return false;
+
+ else
+ return true;
+ }
+
+ /* With the secure-plt SYSV ABI we can't make non-local calls when
+ -fpic/PIC because the plt call stubs use r30. */
+ if (DEFAULT_ABI != ABI_V4
+ || (TARGET_SECURE_PLT
+ && flag_pic
+ && (!decl || !((*targetm.binds_local_p) (decl)))))
+ return false;
+
+ return true;
+}
+
+/* Say whether a function is a candidate for sibcall handling or not. */
+
+bool
+rs6000_function_ok_for_sibcall (tree decl, tree exp)
+{
+ tree fntype;
+
+ /* The sibcall epilogue may clobber the static chain register.
+ ??? We could work harder and avoid that, but it's probably
+ not worth the hassle in practice. */
+ if (CALL_EXPR_STATIC_CHAIN (exp))
+ return false;
+
+ if (decl)
+ fntype = TREE_TYPE (decl);
+ else
+ fntype = TREE_TYPE (TREE_TYPE (CALL_EXPR_FN (exp)));
+
+ /* We can't do it if the called function has more vector parameters
+ than the current function; there's nowhere to put the VRsave code. */
+ if (TARGET_ALTIVEC_ABI
+ && TARGET_ALTIVEC_VRSAVE
+ && !(decl && decl == current_function_decl))
+ {
+ function_args_iterator args_iter;
+ tree type;
+ int nvreg = 0;
+
+ /* Functions with vector parameters are required to have a
+ prototype, so the argument type info must be available
+ here. */
+ FOREACH_FUNCTION_ARGS(fntype, type, args_iter)
+ if (TREE_CODE (type) == VECTOR_TYPE
+ && ALTIVEC_OR_VSX_VECTOR_MODE (TYPE_MODE (type)))
+ nvreg++;
+
+ FOREACH_FUNCTION_ARGS(TREE_TYPE (current_function_decl), type, args_iter)
+ if (TREE_CODE (type) == VECTOR_TYPE
+ && ALTIVEC_OR_VSX_VECTOR_MODE (TYPE_MODE (type)))
+ nvreg--;
+
+ if (nvreg > 0)
+ return false;
+ }
+
+ if (rs6000_decl_ok_for_sibcall (decl))
+ {
+ tree attr_list = TYPE_ATTRIBUTES (fntype);
+
+ if (!lookup_attribute ("longcall", attr_list)
+ || lookup_attribute ("shortcall", attr_list))
+ return true;
+ }
+
+ return false;
+}
+
+static int
+rs6000_ra_ever_killed (void)
+{
+ rtx_insn *top;
+ rtx reg;
+ rtx_insn *insn;
+
+ if (cfun->is_thunk)
+ return 0;
+
+ if (cfun->machine->lr_save_state)
+ return cfun->machine->lr_save_state - 1;
+
+ /* regs_ever_live has LR marked as used if any sibcalls are present,
+ but this should not force saving and restoring in the
+ pro/epilogue. Likewise, reg_set_between_p thinks a sibcall
+ clobbers LR, so that is inappropriate. */
+
+ /* Also, the prologue can generate a store into LR that
+ doesn't really count, like this:
+
+ move LR->R0
+ bcl to set PIC register
+ move LR->R31
+ move R0->LR
+
+ When we're called from the epilogue, we need to avoid counting
+ this as a store. */
+
+ push_topmost_sequence ();
+ top = get_insns ();
+ pop_topmost_sequence ();
+ reg = gen_rtx_REG (Pmode, LR_REGNO);
+
+ for (insn = NEXT_INSN (top); insn != NULL_RTX; insn = NEXT_INSN (insn))
+ {
+ if (INSN_P (insn))
+ {
+ if (CALL_P (insn))
+ {
+ if (!SIBLING_CALL_P (insn))
+ return 1;
+ }
+ else if (find_regno_note (insn, REG_INC, LR_REGNO))
+ return 1;
+ else if (set_of (reg, insn) != NULL_RTX
+ && !prologue_epilogue_contains (insn))
+ return 1;
+ }
+ }
+ return 0;
+}
+
+/* Emit instructions needed to load the TOC register.
+ This is only needed when TARGET_TOC, TARGET_MINIMAL_TOC, and there is
+ a constant pool; or for SVR4 -fpic. */
+
+void
+rs6000_emit_load_toc_table (int fromprolog)
+{
+ rtx dest;
+ dest = gen_rtx_REG (Pmode, RS6000_PIC_OFFSET_TABLE_REGNUM);
+
+ if (TARGET_ELF && TARGET_SECURE_PLT && DEFAULT_ABI == ABI_V4 && flag_pic)
+ {
+ char buf[30];
+ rtx lab, tmp1, tmp2, got;
+
+ lab = gen_label_rtx ();
+ ASM_GENERATE_INTERNAL_LABEL (buf, "L", CODE_LABEL_NUMBER (lab));
+ lab = gen_rtx_SYMBOL_REF (Pmode, ggc_strdup (buf));
+ if (flag_pic == 2)
+ {
+ got = gen_rtx_SYMBOL_REF (Pmode, ggc_strdup (toc_label_name));
+ need_toc_init = 1;
+ }
+ else
+ got = rs6000_got_sym ();
+ tmp1 = tmp2 = dest;
+ if (!fromprolog)
+ {
+ tmp1 = gen_reg_rtx (Pmode);
+ tmp2 = gen_reg_rtx (Pmode);
+ }
+ emit_insn (gen_load_toc_v4_PIC_1 (lab));
+ emit_move_insn (tmp1, gen_rtx_REG (Pmode, LR_REGNO));
+ emit_insn (gen_load_toc_v4_PIC_3b (tmp2, tmp1, got, lab));
+ emit_insn (gen_load_toc_v4_PIC_3c (dest, tmp2, got, lab));
+ }
+ else if (TARGET_ELF && DEFAULT_ABI == ABI_V4 && flag_pic == 1)
+ {
+ emit_insn (gen_load_toc_v4_pic_si ());
+ emit_move_insn (dest, gen_rtx_REG (Pmode, LR_REGNO));
+ }
+ else if (TARGET_ELF && DEFAULT_ABI == ABI_V4 && flag_pic == 2)
+ {
+ char buf[30];
+ rtx temp0 = (fromprolog
+ ? gen_rtx_REG (Pmode, 0)
+ : gen_reg_rtx (Pmode));
+
+ if (fromprolog)
+ {
+ rtx symF, symL;
+
+ ASM_GENERATE_INTERNAL_LABEL (buf, "LCF", rs6000_pic_labelno);
+ symF = gen_rtx_SYMBOL_REF (Pmode, ggc_strdup (buf));
+
+ ASM_GENERATE_INTERNAL_LABEL (buf, "LCL", rs6000_pic_labelno);
+ symL = gen_rtx_SYMBOL_REF (Pmode, ggc_strdup (buf));
+
+ emit_insn (gen_load_toc_v4_PIC_1 (symF));
+ emit_move_insn (dest, gen_rtx_REG (Pmode, LR_REGNO));
+ emit_insn (gen_load_toc_v4_PIC_2 (temp0, dest, symL, symF));
+ }
+ else
+ {
+ rtx tocsym, lab;
+
+ tocsym = gen_rtx_SYMBOL_REF (Pmode, ggc_strdup (toc_label_name));
+ need_toc_init = 1;
+ lab = gen_label_rtx ();
+ emit_insn (gen_load_toc_v4_PIC_1b (tocsym, lab));
+ emit_move_insn (dest, gen_rtx_REG (Pmode, LR_REGNO));
+ if (TARGET_LINK_STACK)
+ emit_insn (gen_addsi3 (dest, dest, GEN_INT (4)));
+ emit_move_insn (temp0, gen_rtx_MEM (Pmode, dest));
+ }
+ emit_insn (gen_addsi3 (dest, temp0, dest));
+ }
+ else if (TARGET_ELF && !TARGET_AIX && flag_pic == 0 && TARGET_MINIMAL_TOC)
+ {
+ /* This is for AIX code running in non-PIC ELF32. */
+ rtx realsym = gen_rtx_SYMBOL_REF (Pmode, ggc_strdup (toc_label_name));
+
+ need_toc_init = 1;
+ emit_insn (gen_elf_high (dest, realsym));
+ emit_insn (gen_elf_low (dest, dest, realsym));
+ }
+ else
+ {
+ gcc_assert (DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2);
+
+ if (TARGET_32BIT)
+ emit_insn (gen_load_toc_aix_si (dest));
+ else
+ emit_insn (gen_load_toc_aix_di (dest));
+ }
+}
+
+/* Emit instructions to restore the link register after determining where
+ its value has been stored. */
+
+void
+rs6000_emit_eh_reg_restore (rtx source, rtx scratch)
+{
+ rs6000_stack_t *info = rs6000_stack_info ();
+ rtx operands[2];
+
+ operands[0] = source;
+ operands[1] = scratch;
+
+ if (info->lr_save_p)
+ {
+ rtx frame_rtx = stack_pointer_rtx;
+ HOST_WIDE_INT sp_offset = 0;
+ rtx tmp;
+
+ if (frame_pointer_needed
+ || cfun->calls_alloca
+ || info->total_size > 32767)
+ {
+ tmp = gen_frame_mem (Pmode, frame_rtx);
+ emit_move_insn (operands[1], tmp);
+ frame_rtx = operands[1];
+ }
+ else if (info->push_p)
+ sp_offset = info->total_size;
+
+ tmp = plus_constant (Pmode, frame_rtx,
+ info->lr_save_offset + sp_offset);
+ tmp = gen_frame_mem (Pmode, tmp);
+ emit_move_insn (tmp, operands[0]);
+ }
+ else
+ emit_move_insn (gen_rtx_REG (Pmode, LR_REGNO), operands[0]);
+
+ /* Freeze lr_save_p. We've just emitted rtl that depends on the
+ state of lr_save_p so any change from here on would be a bug. In
+ particular, stop rs6000_ra_ever_killed from considering the SET
+ of lr we may have added just above. */
+ cfun->machine->lr_save_state = info->lr_save_p + 1;
+}
+
+/* This returns nonzero if the current function uses the TOC. This is
+ determined by the presence of (use (unspec ... UNSPEC_TOC)), which
+ is generated by the ABI_V4 load_toc_* patterns.
+ Return 2 instead of 1 if the load_toc_* pattern is in the function
+ partition that doesn't start the function. */
+#if TARGET_ELF
+int
+uses_TOC (void)
+{
+ rtx_insn *insn;
+ int ret = 1;
+
+ for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
+ {
+ if (INSN_P (insn))
+ {
+ rtx pat = PATTERN (insn);
+ int i;
+
+ if (GET_CODE (pat) == PARALLEL)
+ for (i = 0; i < XVECLEN (pat, 0); i++)
+ {
+ rtx sub = XVECEXP (pat, 0, i);
+ if (GET_CODE (sub) == USE)
+ {
+ sub = XEXP (sub, 0);
+ if (GET_CODE (sub) == UNSPEC
+ && XINT (sub, 1) == UNSPEC_TOC)
+ return ret;
+ }
+ }
+ }
+ else if (crtl->has_bb_partition
+ && NOTE_P (insn)
+ && NOTE_KIND (insn) == NOTE_INSN_SWITCH_TEXT_SECTIONS)
+ ret = 2;
+ }
+ return 0;
+}
+#endif
+
+rtx
+create_TOC_reference (rtx symbol, rtx largetoc_reg)
+{
+ rtx tocrel, tocreg, hi;
+
+ if (TARGET_DEBUG_ADDR)
+ {
+ if (SYMBOL_REF_P (symbol))
+ fprintf (stderr, "\ncreate_TOC_reference, (symbol_ref %s)\n",
+ XSTR (symbol, 0));
+ else
+ {
+ fprintf (stderr, "\ncreate_TOC_reference, code %s:\n",
+ GET_RTX_NAME (GET_CODE (symbol)));
+ debug_rtx (symbol);
+ }
+ }
+
+ if (!can_create_pseudo_p ())
+ df_set_regs_ever_live (TOC_REGISTER, true);
+
+ tocreg = gen_rtx_REG (Pmode, TOC_REGISTER);
+ tocrel = gen_rtx_UNSPEC (Pmode, gen_rtvec (2, symbol, tocreg), UNSPEC_TOCREL);
+ if (TARGET_CMODEL == CMODEL_SMALL || can_create_pseudo_p ())
+ return tocrel;
+
+ hi = gen_rtx_HIGH (Pmode, copy_rtx (tocrel));
+ if (largetoc_reg != NULL)
+ {
+ emit_move_insn (largetoc_reg, hi);
+ hi = largetoc_reg;
+ }
+ return gen_rtx_LO_SUM (Pmode, hi, tocrel);
+}
+
+/* Issue assembly directives that create a reference to the given DWARF
+ FRAME_TABLE_LABEL from the current function section. */
+void
+rs6000_aix_asm_output_dwarf_table_ref (char * frame_table_label)
+{
+ fprintf (asm_out_file, "\t.ref %s\n",
+ (* targetm.strip_name_encoding) (frame_table_label));
+}
+
+/* This ties together stack memory (MEM with an alias set of frame_alias_set)
+ and the change to the stack pointer. */
+
+static void
+rs6000_emit_stack_tie (rtx fp, bool hard_frame_needed)
+{
+ rtvec p;
+ int i;
+ rtx regs[3];
+
+ i = 0;
+ regs[i++] = gen_rtx_REG (Pmode, STACK_POINTER_REGNUM);
+ if (hard_frame_needed)
+ regs[i++] = gen_rtx_REG (Pmode, HARD_FRAME_POINTER_REGNUM);
+ if (!(REGNO (fp) == STACK_POINTER_REGNUM
+ || (hard_frame_needed
+ && REGNO (fp) == HARD_FRAME_POINTER_REGNUM)))
+ regs[i++] = fp;
+
+ p = rtvec_alloc (i);
+ while (--i >= 0)
+ {
+ rtx mem = gen_frame_mem (BLKmode, regs[i]);
+ RTVEC_ELT (p, i) = gen_rtx_SET (mem, const0_rtx);
+ }
+
+ emit_insn (gen_stack_tie (gen_rtx_PARALLEL (VOIDmode, p)));
+}
+
+/* Allocate SIZE_INT bytes on the stack using a store with update style insn
+ and set the appropriate attributes for the generated insn. Return the
+ first insn which adjusts the stack pointer or the last insn before
+ the stack adjustment loop.
+
+ SIZE_INT is used to create the CFI note for the allocation.
+
+ SIZE_RTX is an rtx containing the size of the adjustment. Note that
+ since stacks grow to lower addresses its runtime value is -SIZE_INT.
+
+ ORIG_SP contains the backchain value that must be stored at *sp. */
+
+static rtx_insn *
+rs6000_emit_allocate_stack_1 (HOST_WIDE_INT size_int, rtx orig_sp)
+{
+ rtx_insn *insn;
+
+ rtx size_rtx = GEN_INT (-size_int);
+ if (size_int > 32767)
+ {
+ rtx tmp_reg = gen_rtx_REG (Pmode, 0);
+ /* Need a note here so that try_split doesn't get confused. */
+ if (get_last_insn () == NULL_RTX)
+ emit_note (NOTE_INSN_DELETED);
+ insn = emit_move_insn (tmp_reg, size_rtx);
+ try_split (PATTERN (insn), insn, 0);
+ size_rtx = tmp_reg;
+ }
+
+ if (TARGET_32BIT)
+ insn = emit_insn (gen_movsi_update_stack (stack_pointer_rtx,
+ stack_pointer_rtx,
+ size_rtx,
+ orig_sp));
+ else
+ insn = emit_insn (gen_movdi_update_stack (stack_pointer_rtx,
+ stack_pointer_rtx,
+ size_rtx,
+ orig_sp));
+ rtx par = PATTERN (insn);
+ gcc_assert (GET_CODE (par) == PARALLEL);
+ rtx set = XVECEXP (par, 0, 0);
+ gcc_assert (GET_CODE (set) == SET);
+ rtx mem = SET_DEST (set);
+ gcc_assert (MEM_P (mem));
+ MEM_NOTRAP_P (mem) = 1;
+ set_mem_alias_set (mem, get_frame_alias_set ());
+
+ RTX_FRAME_RELATED_P (insn) = 1;
+ add_reg_note (insn, REG_FRAME_RELATED_EXPR,
+ gen_rtx_SET (stack_pointer_rtx,
+ gen_rtx_PLUS (Pmode,
+ stack_pointer_rtx,
+ GEN_INT (-size_int))));
+
+ /* Emit a blockage to ensure the allocation/probing insns are
+ not optimized, combined, removed, etc. Add REG_STACK_CHECK
+ note for similar reasons. */
+ if (flag_stack_clash_protection)
+ {
+ add_reg_note (insn, REG_STACK_CHECK, const0_rtx);
+ emit_insn (gen_blockage ());
+ }
+
+ return insn;
+}
+
+static HOST_WIDE_INT
+get_stack_clash_protection_probe_interval (void)
+{
+ return (HOST_WIDE_INT_1U
+ << PARAM_VALUE (PARAM_STACK_CLASH_PROTECTION_PROBE_INTERVAL));
+}
+
+static HOST_WIDE_INT
+get_stack_clash_protection_guard_size (void)
+{
+ return (HOST_WIDE_INT_1U
+ << PARAM_VALUE (PARAM_STACK_CLASH_PROTECTION_GUARD_SIZE));
+}
+
+/* Allocate ORIG_SIZE bytes on the stack and probe the newly
+ allocated space every STACK_CLASH_PROTECTION_PROBE_INTERVAL bytes.
+
+ COPY_REG, if non-null, should contain a copy of the original
+ stack pointer at exit from this function.
+
+ This is subtly different than the Ada probing in that it tries hard to
+ prevent attacks that jump the stack guard. Thus it is never allowed to
+ allocate more than STACK_CLASH_PROTECTION_PROBE_INTERVAL bytes of stack
+ space without a suitable probe. */
+static rtx_insn *
+rs6000_emit_probe_stack_range_stack_clash (HOST_WIDE_INT orig_size,
+ rtx copy_reg)
+{
+ rtx orig_sp = copy_reg;
+
+ HOST_WIDE_INT probe_interval = get_stack_clash_protection_probe_interval ();
+
+ /* Round the size down to a multiple of PROBE_INTERVAL. */
+ HOST_WIDE_INT rounded_size = ROUND_DOWN (orig_size, probe_interval);
+
+ /* If explicitly requested,
+ or the rounded size is not the same as the original size
+ or the the rounded size is greater than a page,
+ then we will need a copy of the original stack pointer. */
+ if (rounded_size != orig_size
+ || rounded_size > probe_interval
+ || copy_reg)
+ {
+ /* If the caller did not request a copy of the incoming stack
+ pointer, then we use r0 to hold the copy. */
+ if (!copy_reg)
+ orig_sp = gen_rtx_REG (Pmode, 0);
+ emit_move_insn (orig_sp, stack_pointer_rtx);
+ }
+
+ /* There's three cases here.
+
+ One is a single probe which is the most common and most efficiently
+ implemented as it does not have to have a copy of the original
+ stack pointer if there are no residuals.
+
+ Second is unrolled allocation/probes which we use if there's just
+ a few of them. It needs to save the original stack pointer into a
+ temporary for use as a source register in the allocation/probe.
+
+ Last is a loop. This is the most uncommon case and least efficient. */
+ rtx_insn *retval = NULL;
+ if (rounded_size == probe_interval)
+ {
+ retval = rs6000_emit_allocate_stack_1 (probe_interval, stack_pointer_rtx);
+
+ dump_stack_clash_frame_info (PROBE_INLINE, rounded_size != orig_size);
+ }
+ else if (rounded_size <= 8 * probe_interval)
+ {
+ /* The ABI requires using the store with update insns to allocate
+ space and store the backchain into the stack
+
+ So we save the current stack pointer into a temporary, then
+ emit the store-with-update insns to store the saved stack pointer
+ into the right location in each new page. */
+ for (int i = 0; i < rounded_size; i += probe_interval)
+ {
+ rtx_insn *insn
+ = rs6000_emit_allocate_stack_1 (probe_interval, orig_sp);
+
+ /* Save the first stack adjustment in RETVAL. */
+ if (i == 0)
+ retval = insn;
+ }
+
+ dump_stack_clash_frame_info (PROBE_INLINE, rounded_size != orig_size);
+ }
+ else
+ {
+ /* Compute the ending address. */
+ rtx end_addr
+ = copy_reg ? gen_rtx_REG (Pmode, 0) : gen_rtx_REG (Pmode, 12);
+ rtx rs = GEN_INT (-rounded_size);
+ rtx_insn *insn;
+ if (add_operand (rs, Pmode))
+ insn = emit_insn (gen_add3_insn (end_addr, stack_pointer_rtx, rs));
+ else
+ {
+ emit_move_insn (end_addr, GEN_INT (-rounded_size));
+ insn = emit_insn (gen_add3_insn (end_addr, end_addr,
+ stack_pointer_rtx));
+ /* Describe the effect of INSN to the CFI engine. */
+ add_reg_note (insn, REG_FRAME_RELATED_EXPR,
+ gen_rtx_SET (end_addr,
+ gen_rtx_PLUS (Pmode, stack_pointer_rtx,
+ rs)));
+ }
+ RTX_FRAME_RELATED_P (insn) = 1;
+
+ /* Emit the loop. */
+ if (TARGET_64BIT)
+ retval = emit_insn (gen_probe_stack_rangedi (stack_pointer_rtx,
+ stack_pointer_rtx, orig_sp,
+ end_addr));
+ else
+ retval = emit_insn (gen_probe_stack_rangesi (stack_pointer_rtx,
+ stack_pointer_rtx, orig_sp,
+ end_addr));
+ RTX_FRAME_RELATED_P (retval) = 1;
+ /* Describe the effect of INSN to the CFI engine. */
+ add_reg_note (retval, REG_FRAME_RELATED_EXPR,
+ gen_rtx_SET (stack_pointer_rtx, end_addr));
+
+ /* Emit a blockage to ensure the allocation/probing insns are
+ not optimized, combined, removed, etc. Other cases handle this
+ within their call to rs6000_emit_allocate_stack_1. */
+ emit_insn (gen_blockage ());
+
+ dump_stack_clash_frame_info (PROBE_LOOP, rounded_size != orig_size);
+ }
+
+ if (orig_size != rounded_size)
+ {
+ /* Allocate (and implicitly probe) any residual space. */
+ HOST_WIDE_INT residual = orig_size - rounded_size;
+
+ rtx_insn *insn = rs6000_emit_allocate_stack_1 (residual, orig_sp);
+
+ /* If the residual was the only allocation, then we can return the
+ allocating insn. */
+ if (!retval)
+ retval = insn;
+ }
+
+ return retval;
+}
+
+/* Emit the correct code for allocating stack space, as insns.
+ If COPY_REG, make sure a copy of the old frame is left there.
+ The generated code may use hard register 0 as a temporary. */
+
+static rtx_insn *
+rs6000_emit_allocate_stack (HOST_WIDE_INT size, rtx copy_reg, int copy_off)
+{
+ rtx_insn *insn;
+ rtx stack_reg = gen_rtx_REG (Pmode, STACK_POINTER_REGNUM);
+ rtx tmp_reg = gen_rtx_REG (Pmode, 0);
+ rtx todec = gen_int_mode (-size, Pmode);
+
+ if (INTVAL (todec) != -size)
+ {
+ warning (0, "stack frame too large");
+ emit_insn (gen_trap ());
+ return 0;
+ }
+
+ if (crtl->limit_stack)
+ {
+ if (REG_P (stack_limit_rtx)
+ && REGNO (stack_limit_rtx) > 1
+ && REGNO (stack_limit_rtx) <= 31)
+ {
+ rtx_insn *insn
+ = gen_add3_insn (tmp_reg, stack_limit_rtx, GEN_INT (size));
+ gcc_assert (insn);
+ emit_insn (insn);
+ emit_insn (gen_cond_trap (LTU, stack_reg, tmp_reg, const0_rtx));
+ }
+ else if (SYMBOL_REF_P (stack_limit_rtx)
+ && TARGET_32BIT
+ && DEFAULT_ABI == ABI_V4
+ && !flag_pic)
+ {
+ rtx toload = gen_rtx_CONST (VOIDmode,
+ gen_rtx_PLUS (Pmode,
+ stack_limit_rtx,
+ GEN_INT (size)));
+
+ emit_insn (gen_elf_high (tmp_reg, toload));
+ emit_insn (gen_elf_low (tmp_reg, tmp_reg, toload));
+ emit_insn (gen_cond_trap (LTU, stack_reg, tmp_reg,
+ const0_rtx));
+ }
+ else
+ warning (0, "stack limit expression is not supported");
+ }
+
+ if (flag_stack_clash_protection)
+ {
+ if (size < get_stack_clash_protection_guard_size ())
+ dump_stack_clash_frame_info (NO_PROBE_SMALL_FRAME, true);
+ else
+ {
+ rtx_insn *insn = rs6000_emit_probe_stack_range_stack_clash (size,
+ copy_reg);
+
+ /* If we asked for a copy with an offset, then we still need add in
+ the offset. */
+ if (copy_reg && copy_off)
+ emit_insn (gen_add3_insn (copy_reg, copy_reg, GEN_INT (copy_off)));
+ return insn;
+ }
+ }
+
+ if (copy_reg)
+ {
+ if (copy_off != 0)
+ emit_insn (gen_add3_insn (copy_reg, stack_reg, GEN_INT (copy_off)));
+ else
+ emit_move_insn (copy_reg, stack_reg);
+ }
+
+ /* Since we didn't use gen_frame_mem to generate the MEM, grab
+ it now and set the alias set/attributes. The above gen_*_update
+ calls will generate a PARALLEL with the MEM set being the first
+ operation. */
+ insn = rs6000_emit_allocate_stack_1 (size, stack_reg);
+ return insn;
+}
+
+#define PROBE_INTERVAL (1 << STACK_CHECK_PROBE_INTERVAL_EXP)
+
+#if PROBE_INTERVAL > 32768
+#error Cannot use indexed addressing mode for stack probing
+#endif
+
+/* Emit code to probe a range of stack addresses from FIRST to FIRST+SIZE,
+ inclusive. These are offsets from the current stack pointer. */
+
+static void
+rs6000_emit_probe_stack_range (HOST_WIDE_INT first, HOST_WIDE_INT size)
+{
+ /* See if we have a constant small number of probes to generate. If so,
+ that's the easy case. */
+ if (first + size <= 32768)
+ {
+ HOST_WIDE_INT i;
+
+ /* Probe at FIRST + N * PROBE_INTERVAL for values of N from 1 until
+ it exceeds SIZE. If only one probe is needed, this will not
+ generate any code. Then probe at FIRST + SIZE. */
+ for (i = PROBE_INTERVAL; i < size; i += PROBE_INTERVAL)
+ emit_stack_probe (plus_constant (Pmode, stack_pointer_rtx,
+ -(first + i)));
+
+ emit_stack_probe (plus_constant (Pmode, stack_pointer_rtx,
+ -(first + size)));
+ }
+
+ /* Otherwise, do the same as above, but in a loop. Note that we must be
+ extra careful with variables wrapping around because we might be at
+ the very top (or the very bottom) of the address space and we have
+ to be able to handle this case properly; in particular, we use an
+ equality test for the loop condition. */
+ else
+ {
+ HOST_WIDE_INT rounded_size;
+ rtx r12 = gen_rtx_REG (Pmode, 12);
+ rtx r0 = gen_rtx_REG (Pmode, 0);
+
+ /* Sanity check for the addressing mode we're going to use. */
+ gcc_assert (first <= 32768);
+
+ /* Step 1: round SIZE to the previous multiple of the interval. */
+
+ rounded_size = ROUND_DOWN (size, PROBE_INTERVAL);
+
+
+ /* Step 2: compute initial and final value of the loop counter. */
+
+ /* TEST_ADDR = SP + FIRST. */
+ emit_insn (gen_rtx_SET (r12, plus_constant (Pmode, stack_pointer_rtx,
+ -first)));
+
+ /* LAST_ADDR = SP + FIRST + ROUNDED_SIZE. */
+ if (rounded_size > 32768)
+ {
+ emit_move_insn (r0, GEN_INT (-rounded_size));
+ emit_insn (gen_rtx_SET (r0, gen_rtx_PLUS (Pmode, r12, r0)));
+ }
+ else
+ emit_insn (gen_rtx_SET (r0, plus_constant (Pmode, r12,
+ -rounded_size)));
+
+
+ /* Step 3: the loop
+
+ do
+ {
+ TEST_ADDR = TEST_ADDR + PROBE_INTERVAL
+ probe at TEST_ADDR
+ }
+ while (TEST_ADDR != LAST_ADDR)
+
+ probes at FIRST + N * PROBE_INTERVAL for values of N from 1
+ until it is equal to ROUNDED_SIZE. */
+
+ if (TARGET_64BIT)
+ emit_insn (gen_probe_stack_rangedi (r12, r12, stack_pointer_rtx, r0));
+ else
+ emit_insn (gen_probe_stack_rangesi (r12, r12, stack_pointer_rtx, r0));
+
+
+ /* Step 4: probe at FIRST + SIZE if we cannot assert at compile-time
+ that SIZE is equal to ROUNDED_SIZE. */
+
+ if (size != rounded_size)
+ emit_stack_probe (plus_constant (Pmode, r12, rounded_size - size));
+ }
+}
+
+/* Probe a range of stack addresses from REG1 to REG2 inclusive. These are
+ addresses, not offsets. */
+
+static const char *
+output_probe_stack_range_1 (rtx reg1, rtx reg2)
+{
+ static int labelno = 0;
+ char loop_lab[32];
+ rtx xops[2];
+
+ ASM_GENERATE_INTERNAL_LABEL (loop_lab, "LPSRL", labelno++);
+
+ /* Loop. */
+ ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, loop_lab);
+
+ /* TEST_ADDR = TEST_ADDR + PROBE_INTERVAL. */
+ xops[0] = reg1;
+ xops[1] = GEN_INT (-PROBE_INTERVAL);
+ output_asm_insn ("addi %0,%0,%1", xops);
+
+ /* Probe at TEST_ADDR. */
+ xops[1] = gen_rtx_REG (Pmode, 0);
+ output_asm_insn ("stw %1,0(%0)", xops);
+
+ /* Test if TEST_ADDR == LAST_ADDR. */
+ xops[1] = reg2;
+ if (TARGET_64BIT)
+ output_asm_insn ("cmpd 0,%0,%1", xops);
+ else
+ output_asm_insn ("cmpw 0,%0,%1", xops);
+
+ /* Branch. */
+ fputs ("\tbne 0,", asm_out_file);
+ assemble_name_raw (asm_out_file, loop_lab);
+ fputc ('\n', asm_out_file);
+
+ return "";
+}
+
+/* This function is called when rs6000_frame_related is processing
+ SETs within a PARALLEL, and returns whether the REGNO save ought to
+ be marked RTX_FRAME_RELATED_P. The PARALLELs involved are those
+ for out-of-line register save functions, store multiple, and the
+ Darwin world_save. They may contain registers that don't really
+ need saving. */
+
+static bool
+interesting_frame_related_regno (unsigned int regno)
+{
+ /* Saves apparently of r0 are actually saving LR. It doesn't make
+ sense to substitute the regno here to test save_reg_p (LR_REGNO).
+ We *know* LR needs saving, and dwarf2cfi.c is able to deduce that
+ (set (mem) (r0)) is saving LR from a prior (set (r0) (lr)) marked
+ as frame related. */
+ if (regno == 0)
+ return true;
+ /* If we see CR2 then we are here on a Darwin world save. Saves of
+ CR2 signify the whole CR is being saved. This is a long-standing
+ ABI wart fixed by ELFv2. As for r0/lr there is no need to check
+ that CR needs to be saved. */
+ if (regno == CR2_REGNO)
+ return true;
+ /* Omit frame info for any user-defined global regs. If frame info
+ is supplied for them, frame unwinding will restore a user reg.
+ Also omit frame info for any reg we don't need to save, as that
+ bloats frame info and can cause problems with shrink wrapping.
+ Since global regs won't be seen as needing to be saved, both of
+ these conditions are covered by save_reg_p. */
+ return save_reg_p (regno);
+}
+
+/* Probe a range of stack addresses from REG1 to REG3 inclusive. These are
+ addresses, not offsets.
+
+ REG2 contains the backchain that must be stored into *sp at each allocation.
+
+ This is subtly different than the Ada probing above in that it tries hard
+ to prevent attacks that jump the stack guard. Thus, it is never allowed
+ to allocate more than PROBE_INTERVAL bytes of stack space without a
+ suitable probe. */
+
+static const char *
+output_probe_stack_range_stack_clash (rtx reg1, rtx reg2, rtx reg3)
+{
+ static int labelno = 0;
+ char loop_lab[32];
+ rtx xops[3];
+
+ HOST_WIDE_INT probe_interval = get_stack_clash_protection_probe_interval ();
+
+ ASM_GENERATE_INTERNAL_LABEL (loop_lab, "LPSRL", labelno++);
+
+ ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, loop_lab);
+
+ /* This allocates and probes. */
+ xops[0] = reg1;
+ xops[1] = reg2;
+ xops[2] = GEN_INT (-probe_interval);
+ if (TARGET_64BIT)
+ output_asm_insn ("stdu %1,%2(%0)", xops);
+ else
+ output_asm_insn ("stwu %1,%2(%0)", xops);
+
+ /* Jump to LOOP_LAB if TEST_ADDR != LAST_ADDR. */
+ xops[0] = reg1;
+ xops[1] = reg3;
+ if (TARGET_64BIT)
+ output_asm_insn ("cmpd 0,%0,%1", xops);
+ else
+ output_asm_insn ("cmpw 0,%0,%1", xops);
+
+ fputs ("\tbne 0,", asm_out_file);
+ assemble_name_raw (asm_out_file, loop_lab);
+ fputc ('\n', asm_out_file);
+
+ return "";
+}
+
+/* Wrapper around the output_probe_stack_range routines. */
+const char *
+output_probe_stack_range (rtx reg1, rtx reg2, rtx reg3)
+{
+ if (flag_stack_clash_protection)
+ return output_probe_stack_range_stack_clash (reg1, reg2, reg3);
+ else
+ return output_probe_stack_range_1 (reg1, reg3);
+}
+
+/* Add to 'insn' a note which is PATTERN (INSN) but with REG replaced
+ with (plus:P (reg 1) VAL), and with REG2 replaced with REPL2 if REG2
+ is not NULL. It would be nice if dwarf2out_frame_debug_expr could
+ deduce these equivalences by itself so it wasn't necessary to hold
+ its hand so much. Don't be tempted to always supply d2_f_d_e with
+ the actual cfa register, ie. r31 when we are using a hard frame
+ pointer. That fails when saving regs off r1, and sched moves the
+ r31 setup past the reg saves. */
+
+static rtx_insn *
+rs6000_frame_related (rtx_insn *insn, rtx reg, HOST_WIDE_INT val,
+ rtx reg2, rtx repl2)
+{
+ rtx repl;
+
+ if (REGNO (reg) == STACK_POINTER_REGNUM)
+ {
+ gcc_checking_assert (val == 0);
+ repl = NULL_RTX;
+ }
+ else
+ repl = gen_rtx_PLUS (Pmode, gen_rtx_REG (Pmode, STACK_POINTER_REGNUM),
+ GEN_INT (val));
+
+ rtx pat = PATTERN (insn);
+ if (!repl && !reg2)
+ {
+ /* No need for any replacement. Just set RTX_FRAME_RELATED_P. */
+ if (GET_CODE (pat) == PARALLEL)
+ for (int i = 0; i < XVECLEN (pat, 0); i++)
+ if (GET_CODE (XVECEXP (pat, 0, i)) == SET)
+ {
+ rtx set = XVECEXP (pat, 0, i);
+
+ if (!REG_P (SET_SRC (set))
+ || interesting_frame_related_regno (REGNO (SET_SRC (set))))
+ RTX_FRAME_RELATED_P (set) = 1;
+ }
+ RTX_FRAME_RELATED_P (insn) = 1;
+ return insn;
+ }
+
+ /* We expect that 'pat' is either a SET or a PARALLEL containing
+ SETs (and possibly other stuff). In a PARALLEL, all the SETs
+ are important so they all have to be marked RTX_FRAME_RELATED_P.
+ Call simplify_replace_rtx on the SETs rather than the whole insn
+ so as to leave the other stuff alone (for example USE of r12). */
+
+ set_used_flags (pat);
+ if (GET_CODE (pat) == SET)
+ {
+ if (repl)
+ pat = simplify_replace_rtx (pat, reg, repl);
+ if (reg2)
+ pat = simplify_replace_rtx (pat, reg2, repl2);
+ }
+ else if (GET_CODE (pat) == PARALLEL)
+ {
+ pat = shallow_copy_rtx (pat);
+ XVEC (pat, 0) = shallow_copy_rtvec (XVEC (pat, 0));
+
+ for (int i = 0; i < XVECLEN (pat, 0); i++)
+ if (GET_CODE (XVECEXP (pat, 0, i)) == SET)
+ {
+ rtx set = XVECEXP (pat, 0, i);
+
+ if (repl)
+ set = simplify_replace_rtx (set, reg, repl);
+ if (reg2)
+ set = simplify_replace_rtx (set, reg2, repl2);
+ XVECEXP (pat, 0, i) = set;
+
+ if (!REG_P (SET_SRC (set))
+ || interesting_frame_related_regno (REGNO (SET_SRC (set))))
+ RTX_FRAME_RELATED_P (set) = 1;
+ }
+ }
+ else
+ gcc_unreachable ();
+
+ RTX_FRAME_RELATED_P (insn) = 1;
+ add_reg_note (insn, REG_FRAME_RELATED_EXPR, copy_rtx_if_shared (pat));
+
+ return insn;
+}
+
+/* Returns an insn that has a vrsave set operation with the
+ appropriate CLOBBERs. */
+
+static rtx
+generate_set_vrsave (rtx reg, rs6000_stack_t *info, int epiloguep)
+{
+ int nclobs, i;
+ rtx insn, clobs[TOTAL_ALTIVEC_REGS + 1];
+ rtx vrsave = gen_rtx_REG (SImode, VRSAVE_REGNO);
+
+ clobs[0]
+ = gen_rtx_SET (vrsave,
+ gen_rtx_UNSPEC_VOLATILE (SImode,
+ gen_rtvec (2, reg, vrsave),
+ UNSPECV_SET_VRSAVE));
+
+ nclobs = 1;
+
+ /* We need to clobber the registers in the mask so the scheduler
+ does not move sets to VRSAVE before sets of AltiVec registers.
+
+ However, if the function receives nonlocal gotos, reload will set
+ all call saved registers live. We will end up with:
+
+ (set (reg 999) (mem))
+ (parallel [ (set (reg vrsave) (unspec blah))
+ (clobber (reg 999))])
+
+ The clobber will cause the store into reg 999 to be dead, and
+ flow will attempt to delete an epilogue insn. In this case, we
+ need an unspec use/set of the register. */
+
+ for (i = FIRST_ALTIVEC_REGNO; i <= LAST_ALTIVEC_REGNO; ++i)
+ if (info->vrsave_mask & ALTIVEC_REG_BIT (i))
+ {
+ if (!epiloguep || call_used_regs [i])
+ clobs[nclobs++] = gen_hard_reg_clobber (V4SImode, i);
+ else
+ {
+ rtx reg = gen_rtx_REG (V4SImode, i);
+
+ clobs[nclobs++]
+ = gen_rtx_SET (reg,
+ gen_rtx_UNSPEC (V4SImode,
+ gen_rtvec (1, reg), 27));
+ }
+ }
+
+ insn = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (nclobs));
+
+ for (i = 0; i < nclobs; ++i)
+ XVECEXP (insn, 0, i) = clobs[i];
+
+ return insn;
+}
+
+static rtx
+gen_frame_set (rtx reg, rtx frame_reg, int offset, bool store)
+{
+ rtx addr, mem;
+
+ addr = gen_rtx_PLUS (Pmode, frame_reg, GEN_INT (offset));
+ mem = gen_frame_mem (GET_MODE (reg), addr);
+ return gen_rtx_SET (store ? mem : reg, store ? reg : mem);
+}
+
+static rtx
+gen_frame_load (rtx reg, rtx frame_reg, int offset)
+{
+ return gen_frame_set (reg, frame_reg, offset, false);
+}
+
+static rtx
+gen_frame_store (rtx reg, rtx frame_reg, int offset)
+{
+ return gen_frame_set (reg, frame_reg, offset, true);
+}
+
+/* Save a register into the frame, and emit RTX_FRAME_RELATED_P notes.
+ Save REGNO into [FRAME_REG + OFFSET] in mode MODE. */
+
+static rtx_insn *
+emit_frame_save (rtx frame_reg, machine_mode mode,
+ unsigned int regno, int offset, HOST_WIDE_INT frame_reg_to_sp)
+{
+ rtx reg;
+
+ /* Some cases that need register indexed addressing. */
+ gcc_checking_assert (!(TARGET_ALTIVEC_ABI && ALTIVEC_VECTOR_MODE (mode))
+ || (TARGET_VSX && ALTIVEC_OR_VSX_VECTOR_MODE (mode)));
+
+ reg = gen_rtx_REG (mode, regno);
+ rtx_insn *insn = emit_insn (gen_frame_store (reg, frame_reg, offset));
+ return rs6000_frame_related (insn, frame_reg, frame_reg_to_sp,
+ NULL_RTX, NULL_RTX);
+}
+
+/* Emit an offset memory reference suitable for a frame store, while
+ converting to a valid addressing mode. */
+
+static rtx
+gen_frame_mem_offset (machine_mode mode, rtx reg, int offset)
+{
+ return gen_frame_mem (mode, gen_rtx_PLUS (Pmode, reg, GEN_INT (offset)));
+}
+
+#ifndef TARGET_FIX_AND_CONTINUE
+#define TARGET_FIX_AND_CONTINUE 0
+#endif
+
+/* It's really GPR 13 or 14, FPR 14 and VR 20. We need the smallest. */
+#define FIRST_SAVRES_REGISTER FIRST_SAVED_GP_REGNO
+#define LAST_SAVRES_REGISTER 31
+#define N_SAVRES_REGISTERS (LAST_SAVRES_REGISTER - FIRST_SAVRES_REGISTER + 1)
+
+enum {
+ SAVRES_LR = 0x1,
+ SAVRES_SAVE = 0x2,
+ SAVRES_REG = 0x0c,
+ SAVRES_GPR = 0,
+ SAVRES_FPR = 4,
+ SAVRES_VR = 8
+};
+
+static GTY(()) rtx savres_routine_syms[N_SAVRES_REGISTERS][12];
+
+/* Temporary holding space for an out-of-line register save/restore
+ routine name. */
+static char savres_routine_name[30];
+
+/* Return the name for an out-of-line register save/restore routine.
+ We are saving/restoring GPRs if GPR is true. */
+
+static char *
+rs6000_savres_routine_name (int regno, int sel)
+{
+ const char *prefix = "";
+ const char *suffix = "";
+
+ /* Different targets are supposed to define
+ {SAVE,RESTORE}_FP_{PREFIX,SUFFIX} with the idea that the needed
+ routine name could be defined with:
+
+ sprintf (name, "%s%d%s", SAVE_FP_PREFIX, regno, SAVE_FP_SUFFIX)
+
+ This is a nice idea in practice, but in reality, things are
+ complicated in several ways:
+
+ - ELF targets have save/restore routines for GPRs.
+
+ - PPC64 ELF targets have routines for save/restore of GPRs that
+ differ in what they do with the link register, so having a set
+ prefix doesn't work. (We only use one of the save routines at
+ the moment, though.)
+
+ - PPC32 elf targets have "exit" versions of the restore routines
+ that restore the link register and can save some extra space.
+ These require an extra suffix. (There are also "tail" versions
+ of the restore routines and "GOT" versions of the save routines,
+ but we don't generate those at present. Same problems apply,
+ though.)
+
+ We deal with all this by synthesizing our own prefix/suffix and
+ using that for the simple sprintf call shown above. */
+ if (DEFAULT_ABI == ABI_V4)
+ {
+ if (TARGET_64BIT)
+ goto aix_names;
+
+ if ((sel & SAVRES_REG) == SAVRES_GPR)
+ prefix = (sel & SAVRES_SAVE) ? "_savegpr_" : "_restgpr_";
+ else if ((sel & SAVRES_REG) == SAVRES_FPR)
+ prefix = (sel & SAVRES_SAVE) ? "_savefpr_" : "_restfpr_";
+ else if ((sel & SAVRES_REG) == SAVRES_VR)
+ prefix = (sel & SAVRES_SAVE) ? "_savevr_" : "_restvr_";
+ else
+ abort ();
+
+ if ((sel & SAVRES_LR))
+ suffix = "_x";
+ }
+ else if (DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2)
+ {
+#if !defined (POWERPC_LINUX) && !defined (POWERPC_FREEBSD)
+ /* No out-of-line save/restore routines for GPRs on AIX. */
+ gcc_assert (!TARGET_AIX || (sel & SAVRES_REG) != SAVRES_GPR);
+#endif
+
+ aix_names:
+ if ((sel & SAVRES_REG) == SAVRES_GPR)
+ prefix = ((sel & SAVRES_SAVE)
+ ? ((sel & SAVRES_LR) ? "_savegpr0_" : "_savegpr1_")
+ : ((sel & SAVRES_LR) ? "_restgpr0_" : "_restgpr1_"));
+ else if ((sel & SAVRES_REG) == SAVRES_FPR)
+ {
+#if defined (POWERPC_LINUX) || defined (POWERPC_FREEBSD)
+ if ((sel & SAVRES_LR))
+ prefix = ((sel & SAVRES_SAVE) ? "_savefpr_" : "_restfpr_");
+ else
+#endif
+ {
+ prefix = (sel & SAVRES_SAVE) ? SAVE_FP_PREFIX : RESTORE_FP_PREFIX;
+ suffix = (sel & SAVRES_SAVE) ? SAVE_FP_SUFFIX : RESTORE_FP_SUFFIX;
+ }
+ }
+ else if ((sel & SAVRES_REG) == SAVRES_VR)
+ prefix = (sel & SAVRES_SAVE) ? "_savevr_" : "_restvr_";
+ else
+ abort ();
+ }
+
+ if (DEFAULT_ABI == ABI_DARWIN)
+ {
+ /* The Darwin approach is (slightly) different, in order to be
+ compatible with code generated by the system toolchain. There is a
+ single symbol for the start of save sequence, and the code here
+ embeds an offset into that code on the basis of the first register
+ to be saved. */
+ prefix = (sel & SAVRES_SAVE) ? "save" : "rest" ;
+ if ((sel & SAVRES_REG) == SAVRES_GPR)
+ sprintf (savres_routine_name, "*%sGPR%s%s%.0d ; %s r%d-r31", prefix,
+ ((sel & SAVRES_LR) ? "x" : ""), (regno == 13 ? "" : "+"),
+ (regno - 13) * 4, prefix, regno);
+ else if ((sel & SAVRES_REG) == SAVRES_FPR)
+ sprintf (savres_routine_name, "*%sFP%s%.0d ; %s f%d-f31", prefix,
+ (regno == 14 ? "" : "+"), (regno - 14) * 4, prefix, regno);
+ else if ((sel & SAVRES_REG) == SAVRES_VR)
+ sprintf (savres_routine_name, "*%sVEC%s%.0d ; %s v%d-v31", prefix,
+ (regno == 20 ? "" : "+"), (regno - 20) * 8, prefix, regno);
+ else
+ abort ();
+ }
+ else
+ sprintf (savres_routine_name, "%s%d%s", prefix, regno, suffix);
+
+ return savres_routine_name;
+}
+
+/* Return an RTL SYMBOL_REF for an out-of-line register save/restore routine.
+ We are saving/restoring GPRs if GPR is true. */
+
+static rtx
+rs6000_savres_routine_sym (rs6000_stack_t *info, int sel)
+{
+ int regno = ((sel & SAVRES_REG) == SAVRES_GPR
+ ? info->first_gp_reg_save
+ : (sel & SAVRES_REG) == SAVRES_FPR
+ ? info->first_fp_reg_save - 32
+ : (sel & SAVRES_REG) == SAVRES_VR
+ ? info->first_altivec_reg_save - FIRST_ALTIVEC_REGNO
+ : -1);
+ rtx sym;
+ int select = sel;
+
+ /* Don't generate bogus routine names. */
+ gcc_assert (FIRST_SAVRES_REGISTER <= regno
+ && regno <= LAST_SAVRES_REGISTER
+ && select >= 0 && select <= 12);
+
+ sym = savres_routine_syms[regno-FIRST_SAVRES_REGISTER][select];
+
+ if (sym == NULL)
+ {
+ char *name;
+
+ name = rs6000_savres_routine_name (regno, sel);
+
+ sym = savres_routine_syms[regno-FIRST_SAVRES_REGISTER][select]
+ = gen_rtx_SYMBOL_REF (Pmode, ggc_strdup (name));
+ SYMBOL_REF_FLAGS (sym) |= SYMBOL_FLAG_FUNCTION;
+ }
+
+ return sym;
+}
+
+/* Emit a sequence of insns, including a stack tie if needed, for
+ resetting the stack pointer. If UPDT_REGNO is not 1, then don't
+ reset the stack pointer, but move the base of the frame into
+ reg UPDT_REGNO for use by out-of-line register restore routines. */
+
+static rtx
+rs6000_emit_stack_reset (rtx frame_reg_rtx, HOST_WIDE_INT frame_off,
+ unsigned updt_regno)
+{
+ /* If there is nothing to do, don't do anything. */
+ if (frame_off == 0 && REGNO (frame_reg_rtx) == updt_regno)
+ return NULL_RTX;
+
+ rtx updt_reg_rtx = gen_rtx_REG (Pmode, updt_regno);
+
+ /* This blockage is needed so that sched doesn't decide to move
+ the sp change before the register restores. */
+ if (DEFAULT_ABI == ABI_V4)
+ return emit_insn (gen_stack_restore_tie (updt_reg_rtx, frame_reg_rtx,
+ GEN_INT (frame_off)));
+
+ /* If we are restoring registers out-of-line, we will be using the
+ "exit" variants of the restore routines, which will reset the
+ stack for us. But we do need to point updt_reg into the
+ right place for those routines. */
+ if (frame_off != 0)
+ return emit_insn (gen_add3_insn (updt_reg_rtx,
+ frame_reg_rtx, GEN_INT (frame_off)));
+ else
+ return emit_move_insn (updt_reg_rtx, frame_reg_rtx);
+
+ return NULL_RTX;
+}
+
+/* Return the register number used as a pointer by out-of-line
+ save/restore functions. */
+
+static inline unsigned
+ptr_regno_for_savres (int sel)
+{
+ if (DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2)
+ return (sel & SAVRES_REG) == SAVRES_FPR || (sel & SAVRES_LR) ? 1 : 12;
+ return DEFAULT_ABI == ABI_DARWIN && (sel & SAVRES_REG) == SAVRES_FPR ? 1 : 11;
+}
+
+/* Construct a parallel rtx describing the effect of a call to an
+ out-of-line register save/restore routine, and emit the insn
+ or jump_insn as appropriate. */
+
+static rtx_insn *
+rs6000_emit_savres_rtx (rs6000_stack_t *info,
+ rtx frame_reg_rtx, int save_area_offset, int lr_offset,
+ machine_mode reg_mode, int sel)
+{
+ int i;
+ int offset, start_reg, end_reg, n_regs, use_reg;
+ int reg_size = GET_MODE_SIZE (reg_mode);
+ rtx sym;
+ rtvec p;
+ rtx par;
+ rtx_insn *insn;
+
+ offset = 0;
+ start_reg = ((sel & SAVRES_REG) == SAVRES_GPR
+ ? info->first_gp_reg_save
+ : (sel & SAVRES_REG) == SAVRES_FPR
+ ? info->first_fp_reg_save
+ : (sel & SAVRES_REG) == SAVRES_VR
+ ? info->first_altivec_reg_save
+ : -1);
+ end_reg = ((sel & SAVRES_REG) == SAVRES_GPR
+ ? 32
+ : (sel & SAVRES_REG) == SAVRES_FPR
+ ? 64
+ : (sel & SAVRES_REG) == SAVRES_VR
+ ? LAST_ALTIVEC_REGNO + 1
+ : -1);
+ n_regs = end_reg - start_reg;
+ p = rtvec_alloc (3 + ((sel & SAVRES_LR) ? 1 : 0)
+ + ((sel & SAVRES_REG) == SAVRES_VR ? 1 : 0)
+ + n_regs);
+
+ if (!(sel & SAVRES_SAVE) && (sel & SAVRES_LR))
+ RTVEC_ELT (p, offset++) = ret_rtx;
+
+ RTVEC_ELT (p, offset++) = gen_hard_reg_clobber (Pmode, LR_REGNO);
+
+ sym = rs6000_savres_routine_sym (info, sel);
+ RTVEC_ELT (p, offset++) = gen_rtx_USE (VOIDmode, sym);
+
+ use_reg = ptr_regno_for_savres (sel);
+ if ((sel & SAVRES_REG) == SAVRES_VR)
+ {
+ /* Vector regs are saved/restored using [reg+reg] addressing. */
+ RTVEC_ELT (p, offset++) = gen_hard_reg_clobber (Pmode, use_reg);
+ RTVEC_ELT (p, offset++)
+ = gen_rtx_USE (VOIDmode, gen_rtx_REG (Pmode, 0));
+ }
+ else
+ RTVEC_ELT (p, offset++)
+ = gen_rtx_USE (VOIDmode, gen_rtx_REG (Pmode, use_reg));
+
+ for (i = 0; i < end_reg - start_reg; i++)
+ RTVEC_ELT (p, i + offset)
+ = gen_frame_set (gen_rtx_REG (reg_mode, start_reg + i),
+ frame_reg_rtx, save_area_offset + reg_size * i,
+ (sel & SAVRES_SAVE) != 0);
+
+ if ((sel & SAVRES_SAVE) && (sel & SAVRES_LR))
+ RTVEC_ELT (p, i + offset)
+ = gen_frame_store (gen_rtx_REG (Pmode, 0), frame_reg_rtx, lr_offset);
+
+ par = gen_rtx_PARALLEL (VOIDmode, p);
+
+ if (!(sel & SAVRES_SAVE) && (sel & SAVRES_LR))
+ {
+ insn = emit_jump_insn (par);
+ JUMP_LABEL (insn) = ret_rtx;
+ }
+ else
+ insn = emit_insn (par);
+ return insn;
+}
+
+/* Emit prologue code to store CR fields that need to be saved into REG. This
+ function should only be called when moving the non-volatile CRs to REG, it
+ is not a general purpose routine to move the entire set of CRs to REG.
+ Specifically, gen_prologue_movesi_from_cr() does not contain uses of the
+ volatile CRs. */
+
+static void
+rs6000_emit_prologue_move_from_cr (rtx reg)
+{
+ /* Only the ELFv2 ABI allows storing only selected fields. */
+ if (DEFAULT_ABI == ABI_ELFv2 && TARGET_MFCRF)
+ {
+ int i, cr_reg[8], count = 0;
+
+ /* Collect CR fields that must be saved. */
+ for (i = 0; i < 8; i++)
+ if (save_reg_p (CR0_REGNO + i))
+ cr_reg[count++] = i;
+
+ /* If it's just a single one, use mfcrf. */
+ if (count == 1)
+ {
+ rtvec p = rtvec_alloc (1);
+ rtvec r = rtvec_alloc (2);
+ RTVEC_ELT (r, 0) = gen_rtx_REG (CCmode, CR0_REGNO + cr_reg[0]);
+ RTVEC_ELT (r, 1) = GEN_INT (1 << (7 - cr_reg[0]));
+ RTVEC_ELT (p, 0)
+ = gen_rtx_SET (reg,
+ gen_rtx_UNSPEC (SImode, r, UNSPEC_MOVESI_FROM_CR));
+
+ emit_insn (gen_rtx_PARALLEL (VOIDmode, p));
+ return;
+ }
+
+ /* ??? It might be better to handle count == 2 / 3 cases here
+ as well, using logical operations to combine the values. */
+ }
+
+ emit_insn (gen_prologue_movesi_from_cr (reg));
+}
+
+/* Return whether the split-stack arg pointer (r12) is used. */
+
+static bool
+split_stack_arg_pointer_used_p (void)
+{
+ /* If the pseudo holding the arg pointer is no longer a pseudo,
+ then the arg pointer is used. */
+ if (cfun->machine->split_stack_arg_pointer != NULL_RTX
+ && (!REG_P (cfun->machine->split_stack_arg_pointer)
+ || HARD_REGISTER_P (cfun->machine->split_stack_arg_pointer)))
+ return true;
+
+ /* Unfortunately we also need to do some code scanning, since
+ r12 may have been substituted for the pseudo. */
+ rtx_insn *insn;
+ basic_block bb = ENTRY_BLOCK_PTR_FOR_FN (cfun)->next_bb;
+ FOR_BB_INSNS (bb, insn)
+ if (NONDEBUG_INSN_P (insn))
+ {
+ /* A call destroys r12. */
+ if (CALL_P (insn))
+ return false;
+
+ df_ref use;
+ FOR_EACH_INSN_USE (use, insn)
+ {
+ rtx x = DF_REF_REG (use);
+ if (REG_P (x) && REGNO (x) == 12)
+ return true;
+ }
+ df_ref def;
+ FOR_EACH_INSN_DEF (def, insn)
+ {
+ rtx x = DF_REF_REG (def);
+ if (REG_P (x) && REGNO (x) == 12)
+ return false;
+ }
+ }
+ return bitmap_bit_p (DF_LR_OUT (bb), 12);
+}
+
+/* Return whether we need to emit an ELFv2 global entry point prologue. */
+
+bool
+rs6000_global_entry_point_prologue_needed_p (void)
+{
+ /* Only needed for the ELFv2 ABI. */
+ if (DEFAULT_ABI != ABI_ELFv2)
+ return false;
+
+ /* With -msingle-pic-base, we assume the whole program shares the same
+ TOC, so no global entry point prologues are needed anywhere. */
+ if (TARGET_SINGLE_PIC_BASE)
+ return false;
+
+ /* PC-relative functions never generate a global entry point prologue. */
+ if (rs6000_pcrel_p (cfun))
+ return false;
+
+ /* Ensure we have a global entry point for thunks. ??? We could
+ avoid that if the target routine doesn't need a global entry point,
+ but we do not know whether this is the case at this point. */
+ if (cfun->is_thunk)
+ return true;
+
+ /* For regular functions, rs6000_emit_prologue sets this flag if the
+ routine ever uses the TOC pointer. */
+ return cfun->machine->r2_setup_needed;
+}
+
+/* Implement TARGET_SHRINK_WRAP_GET_SEPARATE_COMPONENTS. */
+sbitmap
+rs6000_get_separate_components (void)
+{
+ rs6000_stack_t *info = rs6000_stack_info ();
+
+ if (WORLD_SAVE_P (info))
+ return NULL;
+
+ gcc_assert (!(info->savres_strategy & SAVE_MULTIPLE)
+ && !(info->savres_strategy & REST_MULTIPLE));
+
+ /* Component 0 is the save/restore of LR (done via GPR0).
+ Component 2 is the save of the TOC (GPR2).
+ Components 13..31 are the save/restore of GPR13..GPR31.
+ Components 46..63 are the save/restore of FPR14..FPR31. */
+
+ cfun->machine->n_components = 64;
+
+ sbitmap components = sbitmap_alloc (cfun->machine->n_components);
+ bitmap_clear (components);
+
+ int reg_size = TARGET_32BIT ? 4 : 8;
+ int fp_reg_size = 8;
+
+ /* The GPRs we need saved to the frame. */
+ if ((info->savres_strategy & SAVE_INLINE_GPRS)
+ && (info->savres_strategy & REST_INLINE_GPRS))
+ {
+ int offset = info->gp_save_offset;
+ if (info->push_p)
+ offset += info->total_size;
+
+ for (unsigned regno = info->first_gp_reg_save; regno < 32; regno++)
+ {
+ if (IN_RANGE (offset, -0x8000, 0x7fff)
+ && save_reg_p (regno))
+ bitmap_set_bit (components, regno);
+
+ offset += reg_size;
+ }
+ }
+
+ /* Don't mess with the hard frame pointer. */
+ if (frame_pointer_needed)
+ bitmap_clear_bit (components, HARD_FRAME_POINTER_REGNUM);
+
+ /* Don't mess with the fixed TOC register. */
+ if ((TARGET_TOC && TARGET_MINIMAL_TOC)
+ || (flag_pic == 1 && DEFAULT_ABI == ABI_V4)
+ || (flag_pic && DEFAULT_ABI == ABI_DARWIN))
+ bitmap_clear_bit (components, RS6000_PIC_OFFSET_TABLE_REGNUM);
+
+ /* The FPRs we need saved to the frame. */
+ if ((info->savres_strategy & SAVE_INLINE_FPRS)
+ && (info->savres_strategy & REST_INLINE_FPRS))
+ {
+ int offset = info->fp_save_offset;
+ if (info->push_p)
+ offset += info->total_size;
+
+ for (unsigned regno = info->first_fp_reg_save; regno < 64; regno++)
+ {
+ if (IN_RANGE (offset, -0x8000, 0x7fff) && save_reg_p (regno))
+ bitmap_set_bit (components, regno);
+
+ offset += fp_reg_size;
+ }
+ }
+
+ /* Optimize LR save and restore if we can. This is component 0. Any
+ out-of-line register save/restore routines need LR. */
+ if (info->lr_save_p
+ && !(flag_pic && (DEFAULT_ABI == ABI_V4 || DEFAULT_ABI == ABI_DARWIN))
+ && (info->savres_strategy & SAVE_INLINE_GPRS)
+ && (info->savres_strategy & REST_INLINE_GPRS)
+ && (info->savres_strategy & SAVE_INLINE_FPRS)
+ && (info->savres_strategy & REST_INLINE_FPRS)
+ && (info->savres_strategy & SAVE_INLINE_VRS)
+ && (info->savres_strategy & REST_INLINE_VRS))
+ {
+ int offset = info->lr_save_offset;
+ if (info->push_p)
+ offset += info->total_size;
+ if (IN_RANGE (offset, -0x8000, 0x7fff))
+ bitmap_set_bit (components, 0);
+ }
+
+ /* Optimize saving the TOC. This is component 2. */
+ if (cfun->machine->save_toc_in_prologue)
+ bitmap_set_bit (components, 2);
+
+ return components;
+}
+
+/* Implement TARGET_SHRINK_WRAP_COMPONENTS_FOR_BB. */
+sbitmap
+rs6000_components_for_bb (basic_block bb)
+{
+ rs6000_stack_t *info = rs6000_stack_info ();
+
+ bitmap in = DF_LIVE_IN (bb);
+ bitmap gen = &DF_LIVE_BB_INFO (bb)->gen;
+ bitmap kill = &DF_LIVE_BB_INFO (bb)->kill;
+
+ sbitmap components = sbitmap_alloc (cfun->machine->n_components);
+ bitmap_clear (components);
+
+ /* A register is used in a bb if it is in the IN, GEN, or KILL sets. */
+
+ /* GPRs. */
+ for (unsigned regno = info->first_gp_reg_save; regno < 32; regno++)
+ if (bitmap_bit_p (in, regno)
+ || bitmap_bit_p (gen, regno)
+ || bitmap_bit_p (kill, regno))
+ bitmap_set_bit (components, regno);
+
+ /* FPRs. */
+ for (unsigned regno = info->first_fp_reg_save; regno < 64; regno++)
+ if (bitmap_bit_p (in, regno)
+ || bitmap_bit_p (gen, regno)
+ || bitmap_bit_p (kill, regno))
+ bitmap_set_bit (components, regno);
+
+ /* The link register. */
+ if (bitmap_bit_p (in, LR_REGNO)
+ || bitmap_bit_p (gen, LR_REGNO)
+ || bitmap_bit_p (kill, LR_REGNO))
+ bitmap_set_bit (components, 0);
+
+ /* The TOC save. */
+ if (bitmap_bit_p (in, TOC_REGNUM)
+ || bitmap_bit_p (gen, TOC_REGNUM)
+ || bitmap_bit_p (kill, TOC_REGNUM))
+ bitmap_set_bit (components, 2);
+
+ return components;
+}
+
+/* Implement TARGET_SHRINK_WRAP_DISQUALIFY_COMPONENTS. */
+void
+rs6000_disqualify_components (sbitmap components, edge e,
+ sbitmap edge_components, bool /*is_prologue*/)
+{
+ /* Our LR pro/epilogue code moves LR via R0, so R0 had better not be
+ live where we want to place that code. */
+ if (bitmap_bit_p (edge_components, 0)
+ && bitmap_bit_p (DF_LIVE_IN (e->dest), 0))
+ {
+ if (dump_file)
+ fprintf (dump_file, "Disqualifying LR because GPR0 is live "
+ "on entry to bb %d\n", e->dest->index);
+ bitmap_clear_bit (components, 0);
+ }
+}
+
+/* Implement TARGET_SHRINK_WRAP_EMIT_PROLOGUE_COMPONENTS. */
+void
+rs6000_emit_prologue_components (sbitmap components)
+{
+ rs6000_stack_t *info = rs6000_stack_info ();
+ rtx ptr_reg = gen_rtx_REG (Pmode, frame_pointer_needed
+ ? HARD_FRAME_POINTER_REGNUM
+ : STACK_POINTER_REGNUM);
+
+ machine_mode reg_mode = Pmode;
+ int reg_size = TARGET_32BIT ? 4 : 8;
+ machine_mode fp_reg_mode = TARGET_HARD_FLOAT ? DFmode : SFmode;
+ int fp_reg_size = 8;
+
+ /* Prologue for LR. */
+ if (bitmap_bit_p (components, 0))
+ {
+ rtx lr = gen_rtx_REG (reg_mode, LR_REGNO);
+ rtx reg = gen_rtx_REG (reg_mode, 0);
+ rtx_insn *insn = emit_move_insn (reg, lr);
+ RTX_FRAME_RELATED_P (insn) = 1;
+ add_reg_note (insn, REG_CFA_REGISTER, gen_rtx_SET (reg, lr));
+
+ int offset = info->lr_save_offset;
+ if (info->push_p)
+ offset += info->total_size;
+
+ insn = emit_insn (gen_frame_store (reg, ptr_reg, offset));
+ RTX_FRAME_RELATED_P (insn) = 1;
+ rtx mem = copy_rtx (SET_DEST (single_set (insn)));
+ add_reg_note (insn, REG_CFA_OFFSET, gen_rtx_SET (mem, lr));
+ }
+
+ /* Prologue for TOC. */
+ if (bitmap_bit_p (components, 2))
+ {
+ rtx reg = gen_rtx_REG (reg_mode, TOC_REGNUM);
+ rtx sp_reg = gen_rtx_REG (Pmode, STACK_POINTER_REGNUM);
+ emit_insn (gen_frame_store (reg, sp_reg, RS6000_TOC_SAVE_SLOT));
+ }
+
+ /* Prologue for the GPRs. */
+ int offset = info->gp_save_offset;
+ if (info->push_p)
+ offset += info->total_size;
+
+ for (int i = info->first_gp_reg_save; i < 32; i++)
+ {
+ if (bitmap_bit_p (components, i))
+ {
+ rtx reg = gen_rtx_REG (reg_mode, i);
+ rtx_insn *insn = emit_insn (gen_frame_store (reg, ptr_reg, offset));
+ RTX_FRAME_RELATED_P (insn) = 1;
+ rtx set = copy_rtx (single_set (insn));
+ add_reg_note (insn, REG_CFA_OFFSET, set);
+ }
+
+ offset += reg_size;
+ }
+
+ /* Prologue for the FPRs. */
+ offset = info->fp_save_offset;
+ if (info->push_p)
+ offset += info->total_size;
+
+ for (int i = info->first_fp_reg_save; i < 64; i++)
+ {
+ if (bitmap_bit_p (components, i))
+ {
+ rtx reg = gen_rtx_REG (fp_reg_mode, i);
+ rtx_insn *insn = emit_insn (gen_frame_store (reg, ptr_reg, offset));
+ RTX_FRAME_RELATED_P (insn) = 1;
+ rtx set = copy_rtx (single_set (insn));
+ add_reg_note (insn, REG_CFA_OFFSET, set);
+ }
+
+ offset += fp_reg_size;
+ }
+}
+
+/* Implement TARGET_SHRINK_WRAP_EMIT_EPILOGUE_COMPONENTS. */
+void
+rs6000_emit_epilogue_components (sbitmap components)
+{
+ rs6000_stack_t *info = rs6000_stack_info ();
+ rtx ptr_reg = gen_rtx_REG (Pmode, frame_pointer_needed
+ ? HARD_FRAME_POINTER_REGNUM
+ : STACK_POINTER_REGNUM);
+
+ machine_mode reg_mode = Pmode;
+ int reg_size = TARGET_32BIT ? 4 : 8;
+
+ machine_mode fp_reg_mode = TARGET_HARD_FLOAT ? DFmode : SFmode;
+ int fp_reg_size = 8;
+
+ /* Epilogue for the FPRs. */
+ int offset = info->fp_save_offset;
+ if (info->push_p)
+ offset += info->total_size;
+
+ for (int i = info->first_fp_reg_save; i < 64; i++)
+ {
+ if (bitmap_bit_p (components, i))
+ {
+ rtx reg = gen_rtx_REG (fp_reg_mode, i);
+ rtx_insn *insn = emit_insn (gen_frame_load (reg, ptr_reg, offset));
+ RTX_FRAME_RELATED_P (insn) = 1;
+ add_reg_note (insn, REG_CFA_RESTORE, reg);
+ }
+
+ offset += fp_reg_size;
+ }
+
+ /* Epilogue for the GPRs. */
+ offset = info->gp_save_offset;
+ if (info->push_p)
+ offset += info->total_size;
+
+ for (int i = info->first_gp_reg_save; i < 32; i++)
+ {
+ if (bitmap_bit_p (components, i))
+ {
+ rtx reg = gen_rtx_REG (reg_mode, i);
+ rtx_insn *insn = emit_insn (gen_frame_load (reg, ptr_reg, offset));
+ RTX_FRAME_RELATED_P (insn) = 1;
+ add_reg_note (insn, REG_CFA_RESTORE, reg);
+ }
+
+ offset += reg_size;
+ }
+
+ /* Epilogue for LR. */
+ if (bitmap_bit_p (components, 0))
+ {
+ int offset = info->lr_save_offset;
+ if (info->push_p)
+ offset += info->total_size;
+
+ rtx reg = gen_rtx_REG (reg_mode, 0);
+ rtx_insn *insn = emit_insn (gen_frame_load (reg, ptr_reg, offset));
+
+ rtx lr = gen_rtx_REG (Pmode, LR_REGNO);
+ insn = emit_move_insn (lr, reg);
+ RTX_FRAME_RELATED_P (insn) = 1;
+ add_reg_note (insn, REG_CFA_RESTORE, lr);
+ }
+}
+
+/* Implement TARGET_SHRINK_WRAP_SET_HANDLED_COMPONENTS. */
+void
+rs6000_set_handled_components (sbitmap components)
+{
+ rs6000_stack_t *info = rs6000_stack_info ();
+
+ for (int i = info->first_gp_reg_save; i < 32; i++)
+ if (bitmap_bit_p (components, i))
+ cfun->machine->gpr_is_wrapped_separately[i] = true;
+
+ for (int i = info->first_fp_reg_save; i < 64; i++)
+ if (bitmap_bit_p (components, i))
+ cfun->machine->fpr_is_wrapped_separately[i - 32] = true;
+
+ if (bitmap_bit_p (components, 0))
+ cfun->machine->lr_is_wrapped_separately = true;
+
+ if (bitmap_bit_p (components, 2))
+ cfun->machine->toc_is_wrapped_separately = true;
+}
+
+/* VRSAVE is a bit vector representing which AltiVec registers
+ are used. The OS uses this to determine which vector
+ registers to save on a context switch. We need to save
+ VRSAVE on the stack frame, add whatever AltiVec registers we
+ used in this function, and do the corresponding magic in the
+ epilogue. */
+static void
+emit_vrsave_prologue (rs6000_stack_t *info, int save_regno,
+ HOST_WIDE_INT frame_off, rtx frame_reg_rtx)
+{
+ /* Get VRSAVE into a GPR. */
+ rtx reg = gen_rtx_REG (SImode, save_regno);
+ rtx vrsave = gen_rtx_REG (SImode, VRSAVE_REGNO);
+ if (TARGET_MACHO)
+ emit_insn (gen_get_vrsave_internal (reg));
+ else
+ emit_insn (gen_rtx_SET (reg, vrsave));
+
+ /* Save VRSAVE. */
+ int offset = info->vrsave_save_offset + frame_off;
+ emit_insn (gen_frame_store (reg, frame_reg_rtx, offset));
+
+ /* Include the registers in the mask. */
+ emit_insn (gen_iorsi3 (reg, reg, GEN_INT (info->vrsave_mask)));
+
+ emit_insn (generate_set_vrsave (reg, info, 0));
+}
+
+/* Set up the arg pointer (r12) for -fsplit-stack code. If __morestack was
+ called, it left the arg pointer to the old stack in r29. Otherwise, the
+ arg pointer is the top of the current frame. */
+static void
+emit_split_stack_prologue (rs6000_stack_t *info, rtx_insn *sp_adjust,
+ HOST_WIDE_INT frame_off, rtx frame_reg_rtx)
+{
+ cfun->machine->split_stack_argp_used = true;
+
+ if (sp_adjust)
+ {
+ rtx r12 = gen_rtx_REG (Pmode, 12);
+ rtx sp_reg_rtx = gen_rtx_REG (Pmode, STACK_POINTER_REGNUM);
+ rtx set_r12 = gen_rtx_SET (r12, sp_reg_rtx);
+ emit_insn_before (set_r12, sp_adjust);
+ }
+ else if (frame_off != 0 || REGNO (frame_reg_rtx) != 12)
+ {
+ rtx r12 = gen_rtx_REG (Pmode, 12);
+ if (frame_off == 0)
+ emit_move_insn (r12, frame_reg_rtx);
+ else
+ emit_insn (gen_add3_insn (r12, frame_reg_rtx, GEN_INT (frame_off)));
+ }
+
+ if (info->push_p)
+ {
+ rtx r12 = gen_rtx_REG (Pmode, 12);
+ rtx r29 = gen_rtx_REG (Pmode, 29);
+ rtx cr7 = gen_rtx_REG (CCUNSmode, CR7_REGNO);
+ rtx not_more = gen_label_rtx ();
+ rtx jump;
+
+ jump = gen_rtx_IF_THEN_ELSE (VOIDmode,
+ gen_rtx_GEU (VOIDmode, cr7, const0_rtx),
+ gen_rtx_LABEL_REF (VOIDmode, not_more),
+ pc_rtx);
+ jump = emit_jump_insn (gen_rtx_SET (pc_rtx, jump));
+ JUMP_LABEL (jump) = not_more;
+ LABEL_NUSES (not_more) += 1;
+ emit_move_insn (r12, r29);
+ emit_label (not_more);
+ }
+}
+
+/* Emit function prologue as insns. */
+
+void
+rs6000_emit_prologue (void)
+{
+ rs6000_stack_t *info = rs6000_stack_info ();
+ machine_mode reg_mode = Pmode;
+ int reg_size = TARGET_32BIT ? 4 : 8;
+ machine_mode fp_reg_mode = TARGET_HARD_FLOAT ? DFmode : SFmode;
+ int fp_reg_size = 8;
+ rtx sp_reg_rtx = gen_rtx_REG (Pmode, STACK_POINTER_REGNUM);
+ rtx frame_reg_rtx = sp_reg_rtx;
+ unsigned int cr_save_regno;
+ rtx cr_save_rtx = NULL_RTX;
+ rtx_insn *insn;
+ int strategy;
+ int using_static_chain_p = (cfun->static_chain_decl != NULL_TREE
+ && df_regs_ever_live_p (STATIC_CHAIN_REGNUM)
+ && call_used_regs[STATIC_CHAIN_REGNUM]);
+ int using_split_stack = (flag_split_stack
+ && (lookup_attribute ("no_split_stack",
+ DECL_ATTRIBUTES (cfun->decl))
+ == NULL));
+
+ /* Offset to top of frame for frame_reg and sp respectively. */
+ HOST_WIDE_INT frame_off = 0;
+ HOST_WIDE_INT sp_off = 0;
+ /* sp_adjust is the stack adjusting instruction, tracked so that the
+ insn setting up the split-stack arg pointer can be emitted just
+ prior to it, when r12 is not used here for other purposes. */
+ rtx_insn *sp_adjust = 0;
+
+#if CHECKING_P
+ /* Track and check usage of r0, r11, r12. */
+ int reg_inuse = using_static_chain_p ? 1 << 11 : 0;
+#define START_USE(R) do \
+ { \
+ gcc_assert ((reg_inuse & (1 << (R))) == 0); \
+ reg_inuse |= 1 << (R); \
+ } while (0)
+#define END_USE(R) do \
+ { \
+ gcc_assert ((reg_inuse & (1 << (R))) != 0); \
+ reg_inuse &= ~(1 << (R)); \
+ } while (0)
+#define NOT_INUSE(R) do \
+ { \
+ gcc_assert ((reg_inuse & (1 << (R))) == 0); \
+ } while (0)
+#else
+#define START_USE(R) do {} while (0)
+#define END_USE(R) do {} while (0)
+#define NOT_INUSE(R) do {} while (0)
+#endif
+
+ if (DEFAULT_ABI == ABI_ELFv2
+ && !TARGET_SINGLE_PIC_BASE)
+ {
+ cfun->machine->r2_setup_needed = df_regs_ever_live_p (TOC_REGNUM);
+
+ /* With -mminimal-toc we may generate an extra use of r2 below. */
+ if (TARGET_TOC && TARGET_MINIMAL_TOC
+ && !constant_pool_empty_p ())
+ cfun->machine->r2_setup_needed = true;
+ }
+
+
+ if (flag_stack_usage_info)
+ current_function_static_stack_size = info->total_size;
+
+ if (flag_stack_check == STATIC_BUILTIN_STACK_CHECK)
+ {
+ HOST_WIDE_INT size = info->total_size;
+
+ if (crtl->is_leaf && !cfun->calls_alloca)
+ {
+ if (size > PROBE_INTERVAL && size > get_stack_check_protect ())
+ rs6000_emit_probe_stack_range (get_stack_check_protect (),
+ size - get_stack_check_protect ());
+ }
+ else if (size > 0)
+ rs6000_emit_probe_stack_range (get_stack_check_protect (), size);
+ }
+
+ if (TARGET_FIX_AND_CONTINUE)
+ {
+ /* gdb on darwin arranges to forward a function from the old
+ address by modifying the first 5 instructions of the function
+ to branch to the overriding function. This is necessary to
+ permit function pointers that point to the old function to
+ actually forward to the new function. */
+ emit_insn (gen_nop ());
+ emit_insn (gen_nop ());
+ emit_insn (gen_nop ());
+ emit_insn (gen_nop ());
+ emit_insn (gen_nop ());
+ }
+
+ /* Handle world saves specially here. */
+ if (WORLD_SAVE_P (info))
+ {
+ int i, j, sz;
+ rtx treg;
+ rtvec p;
+ rtx reg0;
+
+ /* save_world expects lr in r0. */
+ reg0 = gen_rtx_REG (Pmode, 0);
+ if (info->lr_save_p)
+ {
+ insn = emit_move_insn (reg0,
+ gen_rtx_REG (Pmode, LR_REGNO));
+ RTX_FRAME_RELATED_P (insn) = 1;
+ }
+
+ /* The SAVE_WORLD and RESTORE_WORLD routines make a number of
+ assumptions about the offsets of various bits of the stack
+ frame. */
+ gcc_assert (info->gp_save_offset == -220
+ && info->fp_save_offset == -144
+ && info->lr_save_offset == 8
+ && info->cr_save_offset == 4
+ && info->push_p
+ && info->lr_save_p
+ && (!crtl->calls_eh_return
+ || info->ehrd_offset == -432)
+ && info->vrsave_save_offset == -224
+ && info->altivec_save_offset == -416);
+
+ treg = gen_rtx_REG (SImode, 11);
+ emit_move_insn (treg, GEN_INT (-info->total_size));
+
+ /* SAVE_WORLD takes the caller's LR in R0 and the frame size
+ in R11. It also clobbers R12, so beware! */
+
+ /* Preserve CR2 for save_world prologues */
+ sz = 5;
+ sz += 32 - info->first_gp_reg_save;
+ sz += 64 - info->first_fp_reg_save;
+ sz += LAST_ALTIVEC_REGNO - info->first_altivec_reg_save + 1;
+ p = rtvec_alloc (sz);
+ j = 0;
+ RTVEC_ELT (p, j++) = gen_hard_reg_clobber (SImode, LR_REGNO);
+ RTVEC_ELT (p, j++) = gen_rtx_USE (VOIDmode,
+ gen_rtx_SYMBOL_REF (Pmode,
+ "*save_world"));
+ /* We do floats first so that the instruction pattern matches
+ properly. */
+ for (i = 0; i < 64 - info->first_fp_reg_save; i++)
+ RTVEC_ELT (p, j++)
+ = gen_frame_store (gen_rtx_REG (TARGET_HARD_FLOAT ? DFmode : SFmode,
+ info->first_fp_reg_save + i),
+ frame_reg_rtx,
+ info->fp_save_offset + frame_off + 8 * i);
+ for (i = 0; info->first_altivec_reg_save + i <= LAST_ALTIVEC_REGNO; i++)
+ RTVEC_ELT (p, j++)
+ = gen_frame_store (gen_rtx_REG (V4SImode,
+ info->first_altivec_reg_save + i),
+ frame_reg_rtx,
+ info->altivec_save_offset + frame_off + 16 * i);
+ for (i = 0; i < 32 - info->first_gp_reg_save; i++)
+ RTVEC_ELT (p, j++)
+ = gen_frame_store (gen_rtx_REG (reg_mode, info->first_gp_reg_save + i),
+ frame_reg_rtx,
+ info->gp_save_offset + frame_off + reg_size * i);
+
+ /* CR register traditionally saved as CR2. */
+ RTVEC_ELT (p, j++)
+ = gen_frame_store (gen_rtx_REG (SImode, CR2_REGNO),
+ frame_reg_rtx, info->cr_save_offset + frame_off);
+ /* Explain about use of R0. */
+ if (info->lr_save_p)
+ RTVEC_ELT (p, j++)
+ = gen_frame_store (reg0,
+ frame_reg_rtx, info->lr_save_offset + frame_off);
+ /* Explain what happens to the stack pointer. */
+ {
+ rtx newval = gen_rtx_PLUS (Pmode, sp_reg_rtx, treg);
+ RTVEC_ELT (p, j++) = gen_rtx_SET (sp_reg_rtx, newval);
+ }
+
+ insn = emit_insn (gen_rtx_PARALLEL (VOIDmode, p));
+ rs6000_frame_related (insn, frame_reg_rtx, sp_off - frame_off,
+ treg, GEN_INT (-info->total_size));
+ sp_off = frame_off = info->total_size;
+ }
+
+ strategy = info->savres_strategy;
+
+ /* For V.4, update stack before we do any saving and set back pointer. */
+ if (! WORLD_SAVE_P (info)
+ && info->push_p
+ && (DEFAULT_ABI == ABI_V4
+ || crtl->calls_eh_return))
+ {
+ bool need_r11 = (!(strategy & SAVE_INLINE_FPRS)
+ || !(strategy & SAVE_INLINE_GPRS)
+ || !(strategy & SAVE_INLINE_VRS));
+ int ptr_regno = -1;
+ rtx ptr_reg = NULL_RTX;
+ int ptr_off = 0;
+
+ if (info->total_size < 32767)
+ frame_off = info->total_size;
+ else if (need_r11)
+ ptr_regno = 11;
+ else if (info->cr_save_p
+ || info->lr_save_p
+ || info->first_fp_reg_save < 64
+ || info->first_gp_reg_save < 32
+ || info->altivec_size != 0
+ || info->vrsave_size != 0
+ || crtl->calls_eh_return)
+ ptr_regno = 12;
+ else
+ {
+ /* The prologue won't be saving any regs so there is no need
+ to set up a frame register to access any frame save area.
+ We also won't be using frame_off anywhere below, but set
+ the correct value anyway to protect against future
+ changes to this function. */
+ frame_off = info->total_size;
+ }
+ if (ptr_regno != -1)
+ {
+ /* Set up the frame offset to that needed by the first
+ out-of-line save function. */
+ START_USE (ptr_regno);
+ ptr_reg = gen_rtx_REG (Pmode, ptr_regno);
+ frame_reg_rtx = ptr_reg;
+ if (!(strategy & SAVE_INLINE_FPRS) && info->fp_size != 0)
+ gcc_checking_assert (info->fp_save_offset + info->fp_size == 0);
+ else if (!(strategy & SAVE_INLINE_GPRS) && info->first_gp_reg_save < 32)
+ ptr_off = info->gp_save_offset + info->gp_size;
+ else if (!(strategy & SAVE_INLINE_VRS) && info->altivec_size != 0)
+ ptr_off = info->altivec_save_offset + info->altivec_size;
+ frame_off = -ptr_off;
+ }
+ sp_adjust = rs6000_emit_allocate_stack (info->total_size,
+ ptr_reg, ptr_off);
+ if (REGNO (frame_reg_rtx) == 12)
+ sp_adjust = 0;
+ sp_off = info->total_size;
+ if (frame_reg_rtx != sp_reg_rtx)
+ rs6000_emit_stack_tie (frame_reg_rtx, false);
+ }
+
+ /* If we use the link register, get it into r0. */
+ if (!WORLD_SAVE_P (info) && info->lr_save_p
+ && !cfun->machine->lr_is_wrapped_separately)
+ {
+ rtx addr, reg, mem;
+
+ reg = gen_rtx_REG (Pmode, 0);
+ START_USE (0);
+ insn = emit_move_insn (reg, gen_rtx_REG (Pmode, LR_REGNO));
+ RTX_FRAME_RELATED_P (insn) = 1;
+
+ if (!(strategy & (SAVE_NOINLINE_GPRS_SAVES_LR
+ | SAVE_NOINLINE_FPRS_SAVES_LR)))
+ {
+ addr = gen_rtx_PLUS (Pmode, frame_reg_rtx,
+ GEN_INT (info->lr_save_offset + frame_off));
+ mem = gen_rtx_MEM (Pmode, addr);
+ /* This should not be of rs6000_sr_alias_set, because of
+ __builtin_return_address. */
+
+ insn = emit_move_insn (mem, reg);
+ rs6000_frame_related (insn, frame_reg_rtx, sp_off - frame_off,
+ NULL_RTX, NULL_RTX);
+ END_USE (0);
+ }
+ }
+
+ /* If we need to save CR, put it into r12 or r11. Choose r12 except when
+ r12 will be needed by out-of-line gpr save. */
+ cr_save_regno = ((DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2)
+ && !(strategy & (SAVE_INLINE_GPRS
+ | SAVE_NOINLINE_GPRS_SAVES_LR))
+ ? 11 : 12);
+ if (!WORLD_SAVE_P (info)
+ && info->cr_save_p
+ && REGNO (frame_reg_rtx) != cr_save_regno
+ && !(using_static_chain_p && cr_save_regno == 11)
+ && !(using_split_stack && cr_save_regno == 12 && sp_adjust))
+ {
+ cr_save_rtx = gen_rtx_REG (SImode, cr_save_regno);
+ START_USE (cr_save_regno);
+ rs6000_emit_prologue_move_from_cr (cr_save_rtx);
+ }
+
+ /* Do any required saving of fpr's. If only one or two to save, do
+ it ourselves. Otherwise, call function. */
+ if (!WORLD_SAVE_P (info) && (strategy & SAVE_INLINE_FPRS))
+ {
+ int offset = info->fp_save_offset + frame_off;
+ for (int i = info->first_fp_reg_save; i < 64; i++)
+ {
+ if (save_reg_p (i)
+ && !cfun->machine->fpr_is_wrapped_separately[i - 32])
+ emit_frame_save (frame_reg_rtx, fp_reg_mode, i, offset,
+ sp_off - frame_off);
+
+ offset += fp_reg_size;
+ }
+ }
+ else if (!WORLD_SAVE_P (info) && info->first_fp_reg_save != 64)
+ {
+ bool lr = (strategy & SAVE_NOINLINE_FPRS_SAVES_LR) != 0;
+ int sel = SAVRES_SAVE | SAVRES_FPR | (lr ? SAVRES_LR : 0);
+ unsigned ptr_regno = ptr_regno_for_savres (sel);
+ rtx ptr_reg = frame_reg_rtx;
+
+ if (REGNO (frame_reg_rtx) == ptr_regno)
+ gcc_checking_assert (frame_off == 0);
+ else
+ {
+ ptr_reg = gen_rtx_REG (Pmode, ptr_regno);
+ NOT_INUSE (ptr_regno);
+ emit_insn (gen_add3_insn (ptr_reg,
+ frame_reg_rtx, GEN_INT (frame_off)));
+ }
+ insn = rs6000_emit_savres_rtx (info, ptr_reg,
+ info->fp_save_offset,
+ info->lr_save_offset,
+ DFmode, sel);
+ rs6000_frame_related (insn, ptr_reg, sp_off,
+ NULL_RTX, NULL_RTX);
+ if (lr)
+ END_USE (0);
+ }
+
+ /* Save GPRs. This is done as a PARALLEL if we are using
+ the store-multiple instructions. */
+ if (!WORLD_SAVE_P (info) && !(strategy & SAVE_INLINE_GPRS))
+ {
+ bool lr = (strategy & SAVE_NOINLINE_GPRS_SAVES_LR) != 0;
+ int sel = SAVRES_SAVE | SAVRES_GPR | (lr ? SAVRES_LR : 0);
+ unsigned ptr_regno = ptr_regno_for_savres (sel);
+ rtx ptr_reg = frame_reg_rtx;
+ bool ptr_set_up = REGNO (ptr_reg) == ptr_regno;
+ int end_save = info->gp_save_offset + info->gp_size;
+ int ptr_off;
+
+ if (ptr_regno == 12)
+ sp_adjust = 0;
+ if (!ptr_set_up)
+ ptr_reg = gen_rtx_REG (Pmode, ptr_regno);
+
+ /* Need to adjust r11 (r12) if we saved any FPRs. */
+ if (end_save + frame_off != 0)
+ {
+ rtx offset = GEN_INT (end_save + frame_off);
+
+ if (ptr_set_up)
+ frame_off = -end_save;
+ else
+ NOT_INUSE (ptr_regno);
+ emit_insn (gen_add3_insn (ptr_reg, frame_reg_rtx, offset));
+ }
+ else if (!ptr_set_up)
+ {
+ NOT_INUSE (ptr_regno);
+ emit_move_insn (ptr_reg, frame_reg_rtx);
+ }
+ ptr_off = -end_save;
+ insn = rs6000_emit_savres_rtx (info, ptr_reg,
+ info->gp_save_offset + ptr_off,
+ info->lr_save_offset + ptr_off,
+ reg_mode, sel);
+ rs6000_frame_related (insn, ptr_reg, sp_off - ptr_off,
+ NULL_RTX, NULL_RTX);
+ if (lr)
+ END_USE (0);
+ }
+ else if (!WORLD_SAVE_P (info) && (strategy & SAVE_MULTIPLE))
+ {
+ rtvec p;
+ int i;
+ p = rtvec_alloc (32 - info->first_gp_reg_save);
+ for (i = 0; i < 32 - info->first_gp_reg_save; i++)
+ RTVEC_ELT (p, i)
+ = gen_frame_store (gen_rtx_REG (reg_mode, info->first_gp_reg_save + i),
+ frame_reg_rtx,
+ info->gp_save_offset + frame_off + reg_size * i);
+ insn = emit_insn (gen_rtx_PARALLEL (VOIDmode, p));
+ rs6000_frame_related (insn, frame_reg_rtx, sp_off - frame_off,
+ NULL_RTX, NULL_RTX);
+ }
+ else if (!WORLD_SAVE_P (info))
+ {
+ int offset = info->gp_save_offset + frame_off;
+ for (int i = info->first_gp_reg_save; i < 32; i++)
+ {
+ if (save_reg_p (i)
+ && !cfun->machine->gpr_is_wrapped_separately[i])
+ emit_frame_save (frame_reg_rtx, reg_mode, i, offset,
+ sp_off - frame_off);
+
+ offset += reg_size;
+ }
+ }
+
+ if (crtl->calls_eh_return)
+ {
+ unsigned int i;
+ rtvec p;
+
+ for (i = 0; ; ++i)
+ {
+ unsigned int regno = EH_RETURN_DATA_REGNO (i);
+ if (regno == INVALID_REGNUM)
+ break;
+ }
+
+ p = rtvec_alloc (i);
+
+ for (i = 0; ; ++i)
+ {
+ unsigned int regno = EH_RETURN_DATA_REGNO (i);
+ if (regno == INVALID_REGNUM)
+ break;
+
+ rtx set
+ = gen_frame_store (gen_rtx_REG (reg_mode, regno),
+ sp_reg_rtx,
+ info->ehrd_offset + sp_off + reg_size * (int) i);
+ RTVEC_ELT (p, i) = set;
+ RTX_FRAME_RELATED_P (set) = 1;
+ }
+
+ insn = emit_insn (gen_blockage ());
+ RTX_FRAME_RELATED_P (insn) = 1;
+ add_reg_note (insn, REG_FRAME_RELATED_EXPR, gen_rtx_PARALLEL (VOIDmode, p));
+ }
+
+ /* In AIX ABI we need to make sure r2 is really saved. */
+ if (TARGET_AIX && crtl->calls_eh_return)
+ {
+ rtx tmp_reg, tmp_reg_si, hi, lo, compare_result, toc_save_done, jump;
+ rtx join_insn, note;
+ rtx_insn *save_insn;
+ long toc_restore_insn;
+
+ tmp_reg = gen_rtx_REG (Pmode, 11);
+ tmp_reg_si = gen_rtx_REG (SImode, 11);
+ if (using_static_chain_p)
+ {
+ START_USE (0);
+ emit_move_insn (gen_rtx_REG (Pmode, 0), tmp_reg);
+ }
+ else
+ START_USE (11);
+ emit_move_insn (tmp_reg, gen_rtx_REG (Pmode, LR_REGNO));
+ /* Peek at instruction to which this function returns. If it's
+ restoring r2, then we know we've already saved r2. We can't
+ unconditionally save r2 because the value we have will already
+ be updated if we arrived at this function via a plt call or
+ toc adjusting stub. */
+ emit_move_insn (tmp_reg_si, gen_rtx_MEM (SImode, tmp_reg));
+ toc_restore_insn = ((TARGET_32BIT ? 0x80410000 : 0xE8410000)
+ + RS6000_TOC_SAVE_SLOT);
+ hi = gen_int_mode (toc_restore_insn & ~0xffff, SImode);
+ emit_insn (gen_xorsi3 (tmp_reg_si, tmp_reg_si, hi));
+ compare_result = gen_rtx_REG (CCUNSmode, CR0_REGNO);
+ validate_condition_mode (EQ, CCUNSmode);
+ lo = gen_int_mode (toc_restore_insn & 0xffff, SImode);
+ emit_insn (gen_rtx_SET (compare_result,
+ gen_rtx_COMPARE (CCUNSmode, tmp_reg_si, lo)));
+ toc_save_done = gen_label_rtx ();
+ jump = gen_rtx_IF_THEN_ELSE (VOIDmode,
+ gen_rtx_EQ (VOIDmode, compare_result,
+ const0_rtx),
+ gen_rtx_LABEL_REF (VOIDmode, toc_save_done),
+ pc_rtx);
+ jump = emit_jump_insn (gen_rtx_SET (pc_rtx, jump));
+ JUMP_LABEL (jump) = toc_save_done;
+ LABEL_NUSES (toc_save_done) += 1;
+
+ save_insn = emit_frame_save (frame_reg_rtx, reg_mode,
+ TOC_REGNUM, frame_off + RS6000_TOC_SAVE_SLOT,
+ sp_off - frame_off);
+
+ emit_label (toc_save_done);
+
+ /* ??? If we leave SAVE_INSN as marked as saving R2, then we'll
+ have a CFG that has different saves along different paths.
+ Move the note to a dummy blockage insn, which describes that
+ R2 is unconditionally saved after the label. */
+ /* ??? An alternate representation might be a special insn pattern
+ containing both the branch and the store. That might let the
+ code that minimizes the number of DW_CFA_advance opcodes better
+ freedom in placing the annotations. */
+ note = find_reg_note (save_insn, REG_FRAME_RELATED_EXPR, NULL);
+ if (note)
+ remove_note (save_insn, note);
+ else
+ note = alloc_reg_note (REG_FRAME_RELATED_EXPR,
+ copy_rtx (PATTERN (save_insn)), NULL_RTX);
+ RTX_FRAME_RELATED_P (save_insn) = 0;
+
+ join_insn = emit_insn (gen_blockage ());
+ REG_NOTES (join_insn) = note;
+ RTX_FRAME_RELATED_P (join_insn) = 1;
+
+ if (using_static_chain_p)
+ {
+ emit_move_insn (tmp_reg, gen_rtx_REG (Pmode, 0));
+ END_USE (0);
+ }
+ else
+ END_USE (11);
+ }
+
+ /* Save CR if we use any that must be preserved. */
+ if (!WORLD_SAVE_P (info) && info->cr_save_p)
+ {
+ rtx addr = gen_rtx_PLUS (Pmode, frame_reg_rtx,
+ GEN_INT (info->cr_save_offset + frame_off));
+ rtx mem = gen_frame_mem (SImode, addr);
+
+ /* If we didn't copy cr before, do so now using r0. */
+ if (cr_save_rtx == NULL_RTX)
+ {
+ START_USE (0);
+ cr_save_rtx = gen_rtx_REG (SImode, 0);
+ rs6000_emit_prologue_move_from_cr (cr_save_rtx);
+ }
+
+ /* Saving CR requires a two-instruction sequence: one instruction
+ to move the CR to a general-purpose register, and a second
+ instruction that stores the GPR to memory.
+
+ We do not emit any DWARF CFI records for the first of these,
+ because we cannot properly represent the fact that CR is saved in
+ a register. One reason is that we cannot express that multiple
+ CR fields are saved; another reason is that on 64-bit, the size
+ of the CR register in DWARF (4 bytes) differs from the size of
+ a general-purpose register.
+
+ This means if any intervening instruction were to clobber one of
+ the call-saved CR fields, we'd have incorrect CFI. To prevent
+ this from happening, we mark the store to memory as a use of
+ those CR fields, which prevents any such instruction from being
+ scheduled in between the two instructions. */
+ rtx crsave_v[9];
+ int n_crsave = 0;
+ int i;
+
+ crsave_v[n_crsave++] = gen_rtx_SET (mem, cr_save_rtx);
+ for (i = 0; i < 8; i++)
+ if (save_reg_p (CR0_REGNO + i))
+ crsave_v[n_crsave++]
+ = gen_rtx_USE (VOIDmode, gen_rtx_REG (CCmode, CR0_REGNO + i));
+
+ insn = emit_insn (gen_rtx_PARALLEL (VOIDmode,
+ gen_rtvec_v (n_crsave, crsave_v)));
+ END_USE (REGNO (cr_save_rtx));
+
+ /* Now, there's no way that dwarf2out_frame_debug_expr is going to
+ understand '(unspec:SI [(reg:CC 68) ...] UNSPEC_MOVESI_FROM_CR)',
+ so we need to construct a frame expression manually. */
+ RTX_FRAME_RELATED_P (insn) = 1;
+
+ /* Update address to be stack-pointer relative, like
+ rs6000_frame_related would do. */
+ addr = gen_rtx_PLUS (Pmode, gen_rtx_REG (Pmode, STACK_POINTER_REGNUM),
+ GEN_INT (info->cr_save_offset + sp_off));
+ mem = gen_frame_mem (SImode, addr);
+
+ if (DEFAULT_ABI == ABI_ELFv2)
+ {
+ /* In the ELFv2 ABI we generate separate CFI records for each
+ CR field that was actually saved. They all point to the
+ same 32-bit stack slot. */
+ rtx crframe[8];
+ int n_crframe = 0;
+
+ for (i = 0; i < 8; i++)
+ if (save_reg_p (CR0_REGNO + i))
+ {
+ crframe[n_crframe]
+ = gen_rtx_SET (mem, gen_rtx_REG (SImode, CR0_REGNO + i));
+
+ RTX_FRAME_RELATED_P (crframe[n_crframe]) = 1;
+ n_crframe++;
+ }
+
+ add_reg_note (insn, REG_FRAME_RELATED_EXPR,
+ gen_rtx_PARALLEL (VOIDmode,
+ gen_rtvec_v (n_crframe, crframe)));
+ }
+ else
+ {
+ /* In other ABIs, by convention, we use a single CR regnum to
+ represent the fact that all call-saved CR fields are saved.
+ We use CR2_REGNO to be compatible with gcc-2.95 on Linux. */
+ rtx set = gen_rtx_SET (mem, gen_rtx_REG (SImode, CR2_REGNO));
+ add_reg_note (insn, REG_FRAME_RELATED_EXPR, set);
+ }
+ }
+
+ /* In the ELFv2 ABI we need to save all call-saved CR fields into
+ *separate* slots if the routine calls __builtin_eh_return, so
+ that they can be independently restored by the unwinder. */
+ if (DEFAULT_ABI == ABI_ELFv2 && crtl->calls_eh_return)
+ {
+ int i, cr_off = info->ehcr_offset;
+ rtx crsave;
+
+ /* ??? We might get better performance by using multiple mfocrf
+ instructions. */
+ crsave = gen_rtx_REG (SImode, 0);
+ emit_insn (gen_prologue_movesi_from_cr (crsave));
+
+ for (i = 0; i < 8; i++)
+ if (!call_used_regs[CR0_REGNO + i])
+ {
+ rtvec p = rtvec_alloc (2);
+ RTVEC_ELT (p, 0)
+ = gen_frame_store (crsave, frame_reg_rtx, cr_off + frame_off);
+ RTVEC_ELT (p, 1)
+ = gen_rtx_USE (VOIDmode, gen_rtx_REG (CCmode, CR0_REGNO + i));
+
+ insn = emit_insn (gen_rtx_PARALLEL (VOIDmode, p));
+
+ RTX_FRAME_RELATED_P (insn) = 1;
+ add_reg_note (insn, REG_FRAME_RELATED_EXPR,
+ gen_frame_store (gen_rtx_REG (SImode, CR0_REGNO + i),
+ sp_reg_rtx, cr_off + sp_off));
+
+ cr_off += reg_size;
+ }
+ }
+
+ /* If we are emitting stack probes, but allocate no stack, then
+ just note that in the dump file. */
+ if (flag_stack_clash_protection
+ && dump_file
+ && !info->push_p)
+ dump_stack_clash_frame_info (NO_PROBE_NO_FRAME, false);
+
+ /* Update stack and set back pointer unless this is V.4,
+ for which it was done previously. */
+ if (!WORLD_SAVE_P (info) && info->push_p
+ && !(DEFAULT_ABI == ABI_V4 || crtl->calls_eh_return))
+ {
+ rtx ptr_reg = NULL;
+ int ptr_off = 0;
+
+ /* If saving altivec regs we need to be able to address all save
+ locations using a 16-bit offset. */
+ if ((strategy & SAVE_INLINE_VRS) == 0
+ || (info->altivec_size != 0
+ && (info->altivec_save_offset + info->altivec_size - 16
+ + info->total_size - frame_off) > 32767)
+ || (info->vrsave_size != 0
+ && (info->vrsave_save_offset
+ + info->total_size - frame_off) > 32767))
+ {
+ int sel = SAVRES_SAVE | SAVRES_VR;
+ unsigned ptr_regno = ptr_regno_for_savres (sel);
+
+ if (using_static_chain_p
+ && ptr_regno == STATIC_CHAIN_REGNUM)
+ ptr_regno = 12;
+ if (REGNO (frame_reg_rtx) != ptr_regno)
+ START_USE (ptr_regno);
+ ptr_reg = gen_rtx_REG (Pmode, ptr_regno);
+ frame_reg_rtx = ptr_reg;
+ ptr_off = info->altivec_save_offset + info->altivec_size;
+ frame_off = -ptr_off;
+ }
+ else if (REGNO (frame_reg_rtx) == 1)
+ frame_off = info->total_size;
+ sp_adjust = rs6000_emit_allocate_stack (info->total_size,
+ ptr_reg, ptr_off);
+ if (REGNO (frame_reg_rtx) == 12)
+ sp_adjust = 0;
+ sp_off = info->total_size;
+ if (frame_reg_rtx != sp_reg_rtx)
+ rs6000_emit_stack_tie (frame_reg_rtx, false);
+ }
+
+ /* Set frame pointer, if needed. */
+ if (frame_pointer_needed)
+ {
+ insn = emit_move_insn (gen_rtx_REG (Pmode, HARD_FRAME_POINTER_REGNUM),
+ sp_reg_rtx);
+ RTX_FRAME_RELATED_P (insn) = 1;
+ }
+
+ /* Save AltiVec registers if needed. Save here because the red zone does
+ not always include AltiVec registers. */
+ if (!WORLD_SAVE_P (info)
+ && info->altivec_size != 0 && (strategy & SAVE_INLINE_VRS) == 0)
+ {
+ int end_save = info->altivec_save_offset + info->altivec_size;
+ int ptr_off;
+ /* Oddly, the vector save/restore functions point r0 at the end
+ of the save area, then use r11 or r12 to load offsets for
+ [reg+reg] addressing. */
+ rtx ptr_reg = gen_rtx_REG (Pmode, 0);
+ int scratch_regno = ptr_regno_for_savres (SAVRES_SAVE | SAVRES_VR);
+ rtx scratch_reg = gen_rtx_REG (Pmode, scratch_regno);
+
+ gcc_checking_assert (scratch_regno == 11 || scratch_regno == 12);
+ NOT_INUSE (0);
+ if (scratch_regno == 12)
+ sp_adjust = 0;
+ if (end_save + frame_off != 0)
+ {
+ rtx offset = GEN_INT (end_save + frame_off);
+
+ emit_insn (gen_add3_insn (ptr_reg, frame_reg_rtx, offset));
+ }
+ else
+ emit_move_insn (ptr_reg, frame_reg_rtx);
+
+ ptr_off = -end_save;
+ insn = rs6000_emit_savres_rtx (info, scratch_reg,
+ info->altivec_save_offset + ptr_off,
+ 0, V4SImode, SAVRES_SAVE | SAVRES_VR);
+ rs6000_frame_related (insn, scratch_reg, sp_off - ptr_off,
+ NULL_RTX, NULL_RTX);
+ if (REGNO (frame_reg_rtx) == REGNO (scratch_reg))
+ {
+ /* The oddity mentioned above clobbered our frame reg. */
+ emit_move_insn (frame_reg_rtx, ptr_reg);
+ frame_off = ptr_off;
+ }
+ }
+ else if (!WORLD_SAVE_P (info)
+ && info->altivec_size != 0)
+ {
+ int i;
+
+ for (i = info->first_altivec_reg_save; i <= LAST_ALTIVEC_REGNO; ++i)
+ if (info->vrsave_mask & ALTIVEC_REG_BIT (i))
+ {
+ rtx areg, savereg, mem;
+ HOST_WIDE_INT offset;
+
+ offset = (info->altivec_save_offset + frame_off
+ + 16 * (i - info->first_altivec_reg_save));
+
+ savereg = gen_rtx_REG (V4SImode, i);
+
+ if (TARGET_P9_VECTOR && quad_address_offset_p (offset))
+ {
+ mem = gen_frame_mem (V4SImode,
+ gen_rtx_PLUS (Pmode, frame_reg_rtx,
+ GEN_INT (offset)));
+ insn = emit_insn (gen_rtx_SET (mem, savereg));
+ areg = NULL_RTX;
+ }
+ else
+ {
+ NOT_INUSE (0);
+ areg = gen_rtx_REG (Pmode, 0);
+ emit_move_insn (areg, GEN_INT (offset));
+
+ /* AltiVec addressing mode is [reg+reg]. */
+ mem = gen_frame_mem (V4SImode,
+ gen_rtx_PLUS (Pmode, frame_reg_rtx, areg));
+
+ /* Rather than emitting a generic move, force use of the stvx
+ instruction, which we always want on ISA 2.07 (power8) systems.
+ In particular we don't want xxpermdi/stxvd2x for little
+ endian. */
+ insn = emit_insn (gen_altivec_stvx_v4si_internal (mem, savereg));
+ }
+
+ rs6000_frame_related (insn, frame_reg_rtx, sp_off - frame_off,
+ areg, GEN_INT (offset));
+ }
+ }
+
+ /* VRSAVE is a bit vector representing which AltiVec registers
+ are used. The OS uses this to determine which vector
+ registers to save on a context switch. We need to save
+ VRSAVE on the stack frame, add whatever AltiVec registers we
+ used in this function, and do the corresponding magic in the
+ epilogue. */
+
+ if (!WORLD_SAVE_P (info) && info->vrsave_size != 0)
+ {
+ /* Get VRSAVE into a GPR. Note that ABI_V4 and ABI_DARWIN might
+ be using r12 as frame_reg_rtx and r11 as the static chain
+ pointer for nested functions. */
+ int save_regno = 12;
+ if ((DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2)
+ && !using_static_chain_p)
+ save_regno = 11;
+ else if (using_split_stack || REGNO (frame_reg_rtx) == 12)
+ {
+ save_regno = 11;
+ if (using_static_chain_p)
+ save_regno = 0;
+ }
+ NOT_INUSE (save_regno);
+
+ emit_vrsave_prologue (info, save_regno, frame_off, frame_reg_rtx);
+ }
+
+ /* If we are using RS6000_PIC_OFFSET_TABLE_REGNUM, we need to set it up. */
+ if (!TARGET_SINGLE_PIC_BASE
+ && ((TARGET_TOC && TARGET_MINIMAL_TOC
+ && !constant_pool_empty_p ())
+ || (DEFAULT_ABI == ABI_V4
+ && (flag_pic == 1 || (flag_pic && TARGET_SECURE_PLT))
+ && df_regs_ever_live_p (RS6000_PIC_OFFSET_TABLE_REGNUM))))
+ {
+ /* If emit_load_toc_table will use the link register, we need to save
+ it. We use R12 for this purpose because emit_load_toc_table
+ can use register 0. This allows us to use a plain 'blr' to return
+ from the procedure more often. */
+ int save_LR_around_toc_setup = (TARGET_ELF
+ && DEFAULT_ABI == ABI_V4
+ && flag_pic
+ && ! info->lr_save_p
+ && EDGE_COUNT (EXIT_BLOCK_PTR_FOR_FN (cfun)->preds) > 0);
+ if (save_LR_around_toc_setup)
+ {
+ rtx lr = gen_rtx_REG (Pmode, LR_REGNO);
+ rtx tmp = gen_rtx_REG (Pmode, 12);
+
+ sp_adjust = 0;
+ insn = emit_move_insn (tmp, lr);
+ RTX_FRAME_RELATED_P (insn) = 1;
+
+ rs6000_emit_load_toc_table (TRUE);
+
+ insn = emit_move_insn (lr, tmp);
+ add_reg_note (insn, REG_CFA_RESTORE, lr);
+ RTX_FRAME_RELATED_P (insn) = 1;
+ }
+ else
+ rs6000_emit_load_toc_table (TRUE);
+ }
+
+#if TARGET_MACHO
+ if (!TARGET_SINGLE_PIC_BASE
+ && DEFAULT_ABI == ABI_DARWIN
+ && flag_pic && crtl->uses_pic_offset_table)
+ {
+ rtx lr = gen_rtx_REG (Pmode, LR_REGNO);
+ rtx src = gen_rtx_SYMBOL_REF (Pmode, MACHOPIC_FUNCTION_BASE_NAME);
+
+ /* Save and restore LR locally around this call (in R0). */
+ if (!info->lr_save_p)
+ emit_move_insn (gen_rtx_REG (Pmode, 0), lr);
+
+ emit_insn (gen_load_macho_picbase (src));
+
+ emit_move_insn (gen_rtx_REG (Pmode,
+ RS6000_PIC_OFFSET_TABLE_REGNUM),
+ lr);
+
+ if (!info->lr_save_p)
+ emit_move_insn (lr, gen_rtx_REG (Pmode, 0));
+ }
+#endif
+
+ /* If we need to, save the TOC register after doing the stack setup.
+ Do not emit eh frame info for this save. The unwinder wants info,
+ conceptually attached to instructions in this function, about
+ register values in the caller of this function. This R2 may have
+ already been changed from the value in the caller.
+ We don't attempt to write accurate DWARF EH frame info for R2
+ because code emitted by gcc for a (non-pointer) function call
+ doesn't save and restore R2. Instead, R2 is managed out-of-line
+ by a linker generated plt call stub when the function resides in
+ a shared library. This behavior is costly to describe in DWARF,
+ both in terms of the size of DWARF info and the time taken in the
+ unwinder to interpret it. R2 changes, apart from the
+ calls_eh_return case earlier in this function, are handled by
+ linux-unwind.h frob_update_context. */
+ if (rs6000_save_toc_in_prologue_p ()
+ && !cfun->machine->toc_is_wrapped_separately)
+ {
+ rtx reg = gen_rtx_REG (reg_mode, TOC_REGNUM);
+ emit_insn (gen_frame_store (reg, sp_reg_rtx, RS6000_TOC_SAVE_SLOT));
+ }
+
+ /* Set up the arg pointer (r12) for -fsplit-stack code. */
+ if (using_split_stack && split_stack_arg_pointer_used_p ())
+ emit_split_stack_prologue (info, sp_adjust, frame_off, frame_reg_rtx);
+}
+
+/* Output .extern statements for the save/restore routines we use. */
+
+static void
+rs6000_output_savres_externs (FILE *file)
+{
+ rs6000_stack_t *info = rs6000_stack_info ();
+
+ if (TARGET_DEBUG_STACK)
+ debug_stack_info (info);
+
+ /* Write .extern for any function we will call to save and restore
+ fp values. */
+ if (info->first_fp_reg_save < 64
+ && !TARGET_MACHO
+ && !TARGET_ELF)
+ {
+ char *name;
+ int regno = info->first_fp_reg_save - 32;
+
+ if ((info->savres_strategy & SAVE_INLINE_FPRS) == 0)
+ {
+ bool lr = (info->savres_strategy & SAVE_NOINLINE_FPRS_SAVES_LR) != 0;
+ int sel = SAVRES_SAVE | SAVRES_FPR | (lr ? SAVRES_LR : 0);
+ name = rs6000_savres_routine_name (regno, sel);
+ fprintf (file, "\t.extern %s\n", name);
+ }
+ if ((info->savres_strategy & REST_INLINE_FPRS) == 0)
+ {
+ bool lr = (info->savres_strategy
+ & REST_NOINLINE_FPRS_DOESNT_RESTORE_LR) == 0;
+ int sel = SAVRES_FPR | (lr ? SAVRES_LR : 0);
+ name = rs6000_savres_routine_name (regno, sel);
+ fprintf (file, "\t.extern %s\n", name);
+ }
+ }
+}
+
+/* Write function prologue. */
+
+void
+rs6000_output_function_prologue (FILE *file)
+{
+ if (!cfun->is_thunk)
+ {
+ rs6000_output_savres_externs (file);
+#ifdef USING_ELFOS_H
+ const char *curr_machine = rs6000_machine_from_flags ();
+ if (rs6000_machine != curr_machine)
+ {
+ rs6000_machine = curr_machine;
+ emit_asm_machine ();
+ }
+#endif
+ }
+
+ /* ELFv2 ABI r2 setup code and local entry point. This must follow
+ immediately after the global entry point label. */
+ if (rs6000_global_entry_point_prologue_needed_p ())
+ {
+ const char *name = XSTR (XEXP (DECL_RTL (current_function_decl), 0), 0);
+ (*targetm.asm_out.internal_label) (file, "LCF", rs6000_pic_labelno);
+
+ if (TARGET_CMODEL != CMODEL_LARGE)
+ {
+ /* In the small and medium code models, we assume the TOC is less
+ 2 GB away from the text section, so it can be computed via the
+ following two-instruction sequence. */
+ char buf[256];
+
+ ASM_GENERATE_INTERNAL_LABEL (buf, "LCF", rs6000_pic_labelno);
+ fprintf (file, "0:\taddis 2,12,.TOC.-");
+ assemble_name (file, buf);
+ fprintf (file, "@ha\n");
+ fprintf (file, "\taddi 2,2,.TOC.-");
+ assemble_name (file, buf);
+ fprintf (file, "@l\n");
+ }
+ else
+ {
+ /* In the large code model, we allow arbitrary offsets between the
+ TOC and the text section, so we have to load the offset from
+ memory. The data field is emitted directly before the global
+ entry point in rs6000_elf_declare_function_name. */
+ char buf[256];
+
+#ifdef HAVE_AS_ENTRY_MARKERS
+ /* If supported by the linker, emit a marker relocation. If the
+ total code size of the final executable or shared library
+ happens to fit into 2 GB after all, the linker will replace
+ this code sequence with the sequence for the small or medium
+ code model. */
+ fprintf (file, "\t.reloc .,R_PPC64_ENTRY\n");
+#endif
+ fprintf (file, "\tld 2,");
+ ASM_GENERATE_INTERNAL_LABEL (buf, "LCL", rs6000_pic_labelno);
+ assemble_name (file, buf);
+ fprintf (file, "-");
+ ASM_GENERATE_INTERNAL_LABEL (buf, "LCF", rs6000_pic_labelno);
+ assemble_name (file, buf);
+ fprintf (file, "(12)\n");
+ fprintf (file, "\tadd 2,2,12\n");
+ }
+
+ fputs ("\t.localentry\t", file);
+ assemble_name (file, name);
+ fputs (",.-", file);
+ assemble_name (file, name);
+ fputs ("\n", file);
+ }
+
+ else if (rs6000_pcrel_p (cfun))
+ {
+ const char *name = XSTR (XEXP (DECL_RTL (current_function_decl), 0), 0);
+ /* All functions compiled to use PC-relative addressing will
+ have a .localentry value of 0 or 1. For now we set it to
+ 1 all the time, indicating that the function may clobber
+ the TOC register r2. Later we may optimize this by setting
+ it to 0 if the function is a leaf and does not clobber r2. */
+ fputs ("\t.localentry\t", file);
+ assemble_name (file, name);
+ fputs (",1\n", file);
+ }
+
+ /* Output -mprofile-kernel code. This needs to be done here instead of
+ in output_function_profile since it must go after the ELFv2 ABI
+ local entry point. */
+ if (TARGET_PROFILE_KERNEL && crtl->profile)
+ {
+ gcc_assert (DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2);
+ gcc_assert (!TARGET_32BIT);
+
+ asm_fprintf (file, "\tmflr %s\n", reg_names[0]);
+
+ /* In the ELFv2 ABI we have no compiler stack word. It must be
+ the resposibility of _mcount to preserve the static chain
+ register if required. */
+ if (DEFAULT_ABI != ABI_ELFv2
+ && cfun->static_chain_decl != NULL)
+ {
+ asm_fprintf (file, "\tstd %s,24(%s)\n",
+ reg_names[STATIC_CHAIN_REGNUM], reg_names[1]);
+ fprintf (file, "\tbl %s\n", RS6000_MCOUNT);
+ asm_fprintf (file, "\tld %s,24(%s)\n",
+ reg_names[STATIC_CHAIN_REGNUM], reg_names[1]);
+ }
+ else
+ fprintf (file, "\tbl %s\n", RS6000_MCOUNT);
+ }
+
+ rs6000_pic_labelno++;
+}
+
+/* -mprofile-kernel code calls mcount before the function prolog,
+ so a profiled leaf function should stay a leaf function. */
+bool
+rs6000_keep_leaf_when_profiled (void)
+{
+ return TARGET_PROFILE_KERNEL;
+}
+
+/* Non-zero if vmx regs are restored before the frame pop, zero if
+ we restore after the pop when possible. */
+#define ALWAYS_RESTORE_ALTIVEC_BEFORE_POP 0
+
+/* Restoring cr is a two step process: loading a reg from the frame
+ save, then moving the reg to cr. For ABI_V4 we must let the
+ unwinder know that the stack location is no longer valid at or
+ before the stack deallocation, but we can't emit a cfa_restore for
+ cr at the stack deallocation like we do for other registers.
+ The trouble is that it is possible for the move to cr to be
+ scheduled after the stack deallocation. So say exactly where cr
+ is located on each of the two insns. */
+
+static rtx
+load_cr_save (int regno, rtx frame_reg_rtx, int offset, bool exit_func)
+{
+ rtx mem = gen_frame_mem_offset (SImode, frame_reg_rtx, offset);
+ rtx reg = gen_rtx_REG (SImode, regno);
+ rtx_insn *insn = emit_move_insn (reg, mem);
+
+ if (!exit_func && DEFAULT_ABI == ABI_V4)
+ {
+ rtx cr = gen_rtx_REG (SImode, CR2_REGNO);
+ rtx set = gen_rtx_SET (reg, cr);
+
+ add_reg_note (insn, REG_CFA_REGISTER, set);
+ RTX_FRAME_RELATED_P (insn) = 1;
+ }
+ return reg;
+}
+
+/* Reload CR from REG. */
+
+static void
+restore_saved_cr (rtx reg, bool using_mfcr_multiple, bool exit_func)
+{
+ int count = 0;
+ int i;
+
+ if (using_mfcr_multiple)
+ {
+ for (i = 0; i < 8; i++)
+ if (save_reg_p (CR0_REGNO + i))
+ count++;
+ gcc_assert (count);
+ }
+
+ if (using_mfcr_multiple && count > 1)
+ {
+ rtx_insn *insn;
+ rtvec p;
+ int ndx;
+
+ p = rtvec_alloc (count);
+
+ ndx = 0;
+ for (i = 0; i < 8; i++)
+ if (save_reg_p (CR0_REGNO + i))
+ {
+ rtvec r = rtvec_alloc (2);
+ RTVEC_ELT (r, 0) = reg;
+ RTVEC_ELT (r, 1) = GEN_INT (1 << (7-i));
+ RTVEC_ELT (p, ndx) =
+ gen_rtx_SET (gen_rtx_REG (CCmode, CR0_REGNO + i),
+ gen_rtx_UNSPEC (CCmode, r, UNSPEC_MOVESI_TO_CR));
+ ndx++;
+ }
+ insn = emit_insn (gen_rtx_PARALLEL (VOIDmode, p));
+ gcc_assert (ndx == count);
+
+ /* For the ELFv2 ABI we generate a CFA_RESTORE for each
+ CR field separately. */
+ if (!exit_func && DEFAULT_ABI == ABI_ELFv2 && flag_shrink_wrap)
+ {
+ for (i = 0; i < 8; i++)
+ if (save_reg_p (CR0_REGNO + i))
+ add_reg_note (insn, REG_CFA_RESTORE,
+ gen_rtx_REG (SImode, CR0_REGNO + i));
+
+ RTX_FRAME_RELATED_P (insn) = 1;
+ }
+ }
+ else
+ for (i = 0; i < 8; i++)
+ if (save_reg_p (CR0_REGNO + i))
+ {
+ rtx insn = emit_insn (gen_movsi_to_cr_one
+ (gen_rtx_REG (CCmode, CR0_REGNO + i), reg));
+
+ /* For the ELFv2 ABI we generate a CFA_RESTORE for each
+ CR field separately, attached to the insn that in fact
+ restores this particular CR field. */
+ if (!exit_func && DEFAULT_ABI == ABI_ELFv2 && flag_shrink_wrap)
+ {
+ add_reg_note (insn, REG_CFA_RESTORE,
+ gen_rtx_REG (SImode, CR0_REGNO + i));
+
+ RTX_FRAME_RELATED_P (insn) = 1;
+ }
+ }
+
+ /* For other ABIs, we just generate a single CFA_RESTORE for CR2. */
+ if (!exit_func && DEFAULT_ABI != ABI_ELFv2
+ && (DEFAULT_ABI == ABI_V4 || flag_shrink_wrap))
+ {
+ rtx_insn *insn = get_last_insn ();
+ rtx cr = gen_rtx_REG (SImode, CR2_REGNO);
+
+ add_reg_note (insn, REG_CFA_RESTORE, cr);
+ RTX_FRAME_RELATED_P (insn) = 1;
+ }
+}
+
+/* Like cr, the move to lr instruction can be scheduled after the
+ stack deallocation, but unlike cr, its stack frame save is still
+ valid. So we only need to emit the cfa_restore on the correct
+ instruction. */
+
+static void
+load_lr_save (int regno, rtx frame_reg_rtx, int offset)
+{
+ rtx mem = gen_frame_mem_offset (Pmode, frame_reg_rtx, offset);
+ rtx reg = gen_rtx_REG (Pmode, regno);
+
+ emit_move_insn (reg, mem);
+}
+
+static void
+restore_saved_lr (int regno, bool exit_func)
+{
+ rtx reg = gen_rtx_REG (Pmode, regno);
+ rtx lr = gen_rtx_REG (Pmode, LR_REGNO);
+ rtx_insn *insn = emit_move_insn (lr, reg);
+
+ if (!exit_func && flag_shrink_wrap)
+ {
+ add_reg_note (insn, REG_CFA_RESTORE, lr);
+ RTX_FRAME_RELATED_P (insn) = 1;
+ }
+}
+
+static rtx
+add_crlr_cfa_restore (const rs6000_stack_t *info, rtx cfa_restores)
+{
+ if (DEFAULT_ABI == ABI_ELFv2)
+ {
+ int i;
+ for (i = 0; i < 8; i++)
+ if (save_reg_p (CR0_REGNO + i))
+ {
+ rtx cr = gen_rtx_REG (SImode, CR0_REGNO + i);
+ cfa_restores = alloc_reg_note (REG_CFA_RESTORE, cr,
+ cfa_restores);
+ }
+ }
+ else if (info->cr_save_p)
+ cfa_restores = alloc_reg_note (REG_CFA_RESTORE,
+ gen_rtx_REG (SImode, CR2_REGNO),
+ cfa_restores);
+
+ if (info->lr_save_p)
+ cfa_restores = alloc_reg_note (REG_CFA_RESTORE,
+ gen_rtx_REG (Pmode, LR_REGNO),
+ cfa_restores);
+ return cfa_restores;
+}
+
+/* Return true if OFFSET from stack pointer can be clobbered by signals.
+ V.4 doesn't have any stack cushion, AIX ABIs have 220 or 288 bytes
+ below stack pointer not cloberred by signals. */
+
+static inline bool
+offset_below_red_zone_p (HOST_WIDE_INT offset)
+{
+ return offset < (DEFAULT_ABI == ABI_V4
+ ? 0
+ : TARGET_32BIT ? -220 : -288);
+}
+
+/* Append CFA_RESTORES to any existing REG_NOTES on the last insn. */
+
+static void
+emit_cfa_restores (rtx cfa_restores)
+{
+ rtx_insn *insn = get_last_insn ();
+ rtx *loc = &REG_NOTES (insn);
+
+ while (*loc)
+ loc = &XEXP (*loc, 1);
+ *loc = cfa_restores;
+ RTX_FRAME_RELATED_P (insn) = 1;
+}
+
+/* Emit function epilogue as insns. */
+
+void
+rs6000_emit_epilogue (enum epilogue_type epilogue_type)
+{
+ HOST_WIDE_INT frame_off = 0;
+ rtx sp_reg_rtx = gen_rtx_REG (Pmode, 1);
+ rtx frame_reg_rtx = sp_reg_rtx;
+ rtx cfa_restores = NULL_RTX;
+ rtx insn;
+ rtx cr_save_reg = NULL_RTX;
+ machine_mode reg_mode = Pmode;
+ int reg_size = TARGET_32BIT ? 4 : 8;
+ machine_mode fp_reg_mode = TARGET_HARD_FLOAT ? DFmode : SFmode;
+ int fp_reg_size = 8;
+ int i;
+ unsigned ptr_regno;
+
+ rs6000_stack_t *info = rs6000_stack_info ();
+
+ if (epilogue_type == EPILOGUE_TYPE_NORMAL && crtl->calls_eh_return)
+ epilogue_type = EPILOGUE_TYPE_EH_RETURN;
+
+ int strategy = info->savres_strategy;
+ bool using_load_multiple = !!(strategy & REST_MULTIPLE);
+ bool restoring_GPRs_inline = !!(strategy & REST_INLINE_GPRS);
+ bool restoring_FPRs_inline = !!(strategy & REST_INLINE_FPRS);
+ if (epilogue_type == EPILOGUE_TYPE_SIBCALL)
+ {
+ restoring_GPRs_inline = true;
+ restoring_FPRs_inline = true;
+ }
+
+ bool using_mtcr_multiple = (rs6000_tune == PROCESSOR_PPC601
+ || rs6000_tune == PROCESSOR_PPC603
+ || rs6000_tune == PROCESSOR_PPC750
+ || optimize_size);
+
+ /* Restore via the backchain when we have a large frame, since this
+ is more efficient than an addis, addi pair. The second condition
+ here will not trigger at the moment; We don't actually need a
+ frame pointer for alloca, but the generic parts of the compiler
+ give us one anyway. */
+ bool use_backchain_to_restore_sp
+ = (info->total_size + (info->lr_save_p ? info->lr_save_offset : 0) > 32767
+ || (cfun->calls_alloca && !frame_pointer_needed));
+
+ bool restore_lr = (info->lr_save_p
+ && (restoring_FPRs_inline
+ || (strategy & REST_NOINLINE_FPRS_DOESNT_RESTORE_LR))
+ && (restoring_GPRs_inline
+ || info->first_fp_reg_save < 64)
+ && !cfun->machine->lr_is_wrapped_separately);
+
+
+ if (WORLD_SAVE_P (info))
+ {
+ gcc_assert (epilogue_type != EPILOGUE_TYPE_SIBCALL);
+
+ /* eh_rest_world_r10 will return to the location saved in the LR
+ stack slot (which is not likely to be our caller.)
+ Input: R10 -- stack adjustment. Clobbers R0, R11, R12, R7, R8.
+ rest_world is similar, except any R10 parameter is ignored.
+ The exception-handling stuff that was here in 2.95 is no
+ longer necessary. */
+
+ rtvec p;
+ p = rtvec_alloc (9
+ + 32 - info->first_gp_reg_save
+ + LAST_ALTIVEC_REGNO + 1 - info->first_altivec_reg_save
+ + 63 + 1 - info->first_fp_reg_save);
+
+ const char *rname;
+ switch (epilogue_type)
+ {
+ case EPILOGUE_TYPE_NORMAL:
+ rname = ggc_strdup ("*rest_world");
+ break;
+
+ case EPILOGUE_TYPE_EH_RETURN:
+ rname = ggc_strdup ("*eh_rest_world_r10");
+ break;
+
+ default:
+ gcc_unreachable ();
+ }
+
+ int j = 0;
+ RTVEC_ELT (p, j++) = ret_rtx;
+ RTVEC_ELT (p, j++)
+ = gen_rtx_USE (VOIDmode, gen_rtx_SYMBOL_REF (Pmode, rname));
+ /* The instruction pattern requires a clobber here;
+ it is shared with the restVEC helper. */
+ RTVEC_ELT (p, j++) = gen_hard_reg_clobber (Pmode, 11);
+
+ {
+ /* CR register traditionally saved as CR2. */
+ rtx reg = gen_rtx_REG (SImode, CR2_REGNO);
+ RTVEC_ELT (p, j++)
+ = gen_frame_load (reg, frame_reg_rtx, info->cr_save_offset);
+ if (flag_shrink_wrap)
+ {
+ cfa_restores = alloc_reg_note (REG_CFA_RESTORE,
+ gen_rtx_REG (Pmode, LR_REGNO),
+ cfa_restores);
+ cfa_restores = alloc_reg_note (REG_CFA_RESTORE, reg, cfa_restores);
+ }
+ }
+
+ int i;
+ for (i = 0; i < 32 - info->first_gp_reg_save; i++)
+ {
+ rtx reg = gen_rtx_REG (reg_mode, info->first_gp_reg_save + i);
+ RTVEC_ELT (p, j++)
+ = gen_frame_load (reg,
+ frame_reg_rtx, info->gp_save_offset + reg_size * i);
+ if (flag_shrink_wrap
+ && save_reg_p (info->first_gp_reg_save + i))
+ cfa_restores = alloc_reg_note (REG_CFA_RESTORE, reg, cfa_restores);
+ }
+ for (i = 0; info->first_altivec_reg_save + i <= LAST_ALTIVEC_REGNO; i++)
+ {
+ rtx reg = gen_rtx_REG (V4SImode, info->first_altivec_reg_save + i);
+ RTVEC_ELT (p, j++)
+ = gen_frame_load (reg,
+ frame_reg_rtx, info->altivec_save_offset + 16 * i);
+ if (flag_shrink_wrap
+ && save_reg_p (info->first_altivec_reg_save + i))
+ cfa_restores = alloc_reg_note (REG_CFA_RESTORE, reg, cfa_restores);
+ }
+ for (i = 0; info->first_fp_reg_save + i <= 63; i++)
+ {
+ rtx reg = gen_rtx_REG (TARGET_HARD_FLOAT ? DFmode : SFmode,
+ info->first_fp_reg_save + i);
+ RTVEC_ELT (p, j++)
+ = gen_frame_load (reg, frame_reg_rtx, info->fp_save_offset + 8 * i);
+ if (flag_shrink_wrap
+ && save_reg_p (info->first_fp_reg_save + i))
+ cfa_restores = alloc_reg_note (REG_CFA_RESTORE, reg, cfa_restores);
+ }
+ RTVEC_ELT (p, j++) = gen_hard_reg_clobber (Pmode, 0);
+ RTVEC_ELT (p, j++) = gen_hard_reg_clobber (SImode, 12);
+ RTVEC_ELT (p, j++) = gen_hard_reg_clobber (SImode, 7);
+ RTVEC_ELT (p, j++) = gen_hard_reg_clobber (SImode, 8);
+ RTVEC_ELT (p, j++)
+ = gen_rtx_USE (VOIDmode, gen_rtx_REG (SImode, 10));
+ insn = emit_jump_insn (gen_rtx_PARALLEL (VOIDmode, p));
+
+ if (flag_shrink_wrap)
+ {
+ REG_NOTES (insn) = cfa_restores;
+ add_reg_note (insn, REG_CFA_DEF_CFA, sp_reg_rtx);
+ RTX_FRAME_RELATED_P (insn) = 1;
+ }
+ return;
+ }
+
+ /* frame_reg_rtx + frame_off points to the top of this stack frame. */
+ if (info->push_p)
+ frame_off = info->total_size;
+
+ /* Restore AltiVec registers if we must do so before adjusting the
+ stack. */
+ if (info->altivec_size != 0
+ && (ALWAYS_RESTORE_ALTIVEC_BEFORE_POP
+ || (DEFAULT_ABI != ABI_V4
+ && offset_below_red_zone_p (info->altivec_save_offset))))
+ {
+ int i;
+ int scratch_regno = ptr_regno_for_savres (SAVRES_VR);
+
+ gcc_checking_assert (scratch_regno == 11 || scratch_regno == 12);
+ if (use_backchain_to_restore_sp)
+ {
+ int frame_regno = 11;
+
+ if ((strategy & REST_INLINE_VRS) == 0)
+ {
+ /* Of r11 and r12, select the one not clobbered by an
+ out-of-line restore function for the frame register. */
+ frame_regno = 11 + 12 - scratch_regno;
+ }
+ frame_reg_rtx = gen_rtx_REG (Pmode, frame_regno);
+ emit_move_insn (frame_reg_rtx,
+ gen_rtx_MEM (Pmode, sp_reg_rtx));
+ frame_off = 0;
+ }
+ else if (frame_pointer_needed)
+ frame_reg_rtx = hard_frame_pointer_rtx;
+
+ if ((strategy & REST_INLINE_VRS) == 0)
+ {
+ int end_save = info->altivec_save_offset + info->altivec_size;
+ int ptr_off;
+ rtx ptr_reg = gen_rtx_REG (Pmode, 0);
+ rtx scratch_reg = gen_rtx_REG (Pmode, scratch_regno);
+
+ if (end_save + frame_off != 0)
+ {
+ rtx offset = GEN_INT (end_save + frame_off);
+
+ emit_insn (gen_add3_insn (ptr_reg, frame_reg_rtx, offset));
+ }
+ else
+ emit_move_insn (ptr_reg, frame_reg_rtx);
+
+ ptr_off = -end_save;
+ insn = rs6000_emit_savres_rtx (info, scratch_reg,
+ info->altivec_save_offset + ptr_off,
+ 0, V4SImode, SAVRES_VR);
+ }
+ else
+ {
+ for (i = info->first_altivec_reg_save; i <= LAST_ALTIVEC_REGNO; ++i)
+ if (info->vrsave_mask & ALTIVEC_REG_BIT (i))
+ {
+ rtx addr, areg, mem, insn;
+ rtx reg = gen_rtx_REG (V4SImode, i);
+ HOST_WIDE_INT offset
+ = (info->altivec_save_offset + frame_off
+ + 16 * (i - info->first_altivec_reg_save));
+
+ if (TARGET_P9_VECTOR && quad_address_offset_p (offset))
+ {
+ mem = gen_frame_mem (V4SImode,
+ gen_rtx_PLUS (Pmode, frame_reg_rtx,
+ GEN_INT (offset)));
+ insn = gen_rtx_SET (reg, mem);
+ }
+ else
+ {
+ areg = gen_rtx_REG (Pmode, 0);
+ emit_move_insn (areg, GEN_INT (offset));
+
+ /* AltiVec addressing mode is [reg+reg]. */
+ addr = gen_rtx_PLUS (Pmode, frame_reg_rtx, areg);
+ mem = gen_frame_mem (V4SImode, addr);
+
+ /* Rather than emitting a generic move, force use of the
+ lvx instruction, which we always want. In particular we
+ don't want lxvd2x/xxpermdi for little endian. */
+ insn = gen_altivec_lvx_v4si_internal (reg, mem);
+ }
+
+ (void) emit_insn (insn);
+ }
+ }
+
+ for (i = info->first_altivec_reg_save; i <= LAST_ALTIVEC_REGNO; ++i)
+ if (((strategy & REST_INLINE_VRS) == 0
+ || (info->vrsave_mask & ALTIVEC_REG_BIT (i)) != 0)
+ && (flag_shrink_wrap
+ || (offset_below_red_zone_p
+ (info->altivec_save_offset
+ + 16 * (i - info->first_altivec_reg_save))))
+ && save_reg_p (i))
+ {
+ rtx reg = gen_rtx_REG (V4SImode, i);
+ cfa_restores = alloc_reg_note (REG_CFA_RESTORE, reg, cfa_restores);
+ }
+ }
+
+ /* Restore VRSAVE if we must do so before adjusting the stack. */
+ if (info->vrsave_size != 0
+ && (ALWAYS_RESTORE_ALTIVEC_BEFORE_POP
+ || (DEFAULT_ABI != ABI_V4
+ && offset_below_red_zone_p (info->vrsave_save_offset))))
+ {
+ rtx reg;
+
+ if (frame_reg_rtx == sp_reg_rtx)
+ {
+ if (use_backchain_to_restore_sp)
+ {
+ frame_reg_rtx = gen_rtx_REG (Pmode, 11);
+ emit_move_insn (frame_reg_rtx,
+ gen_rtx_MEM (Pmode, sp_reg_rtx));
+ frame_off = 0;
+ }
+ else if (frame_pointer_needed)
+ frame_reg_rtx = hard_frame_pointer_rtx;
+ }
+
+ reg = gen_rtx_REG (SImode, 12);
+ emit_insn (gen_frame_load (reg, frame_reg_rtx,
+ info->vrsave_save_offset + frame_off));
+
+ emit_insn (generate_set_vrsave (reg, info, 1));
+ }
+
+ insn = NULL_RTX;
+ /* If we have a large stack frame, restore the old stack pointer
+ using the backchain. */
+ if (use_backchain_to_restore_sp)
+ {
+ if (frame_reg_rtx == sp_reg_rtx)
+ {
+ /* Under V.4, don't reset the stack pointer until after we're done
+ loading the saved registers. */
+ if (DEFAULT_ABI == ABI_V4)
+ frame_reg_rtx = gen_rtx_REG (Pmode, 11);
+
+ insn = emit_move_insn (frame_reg_rtx,
+ gen_rtx_MEM (Pmode, sp_reg_rtx));
+ frame_off = 0;
+ }
+ else if (ALWAYS_RESTORE_ALTIVEC_BEFORE_POP
+ && DEFAULT_ABI == ABI_V4)
+ /* frame_reg_rtx has been set up by the altivec restore. */
+ ;
+ else
+ {
+ insn = emit_move_insn (sp_reg_rtx, frame_reg_rtx);
+ frame_reg_rtx = sp_reg_rtx;
+ }
+ }
+ /* If we have a frame pointer, we can restore the old stack pointer
+ from it. */
+ else if (frame_pointer_needed)
+ {
+ frame_reg_rtx = sp_reg_rtx;
+ if (DEFAULT_ABI == ABI_V4)
+ frame_reg_rtx = gen_rtx_REG (Pmode, 11);
+ /* Prevent reordering memory accesses against stack pointer restore. */
+ else if (cfun->calls_alloca
+ || offset_below_red_zone_p (-info->total_size))
+ rs6000_emit_stack_tie (frame_reg_rtx, true);
+
+ insn = emit_insn (gen_add3_insn (frame_reg_rtx, hard_frame_pointer_rtx,
+ GEN_INT (info->total_size)));
+ frame_off = 0;
+ }
+ else if (info->push_p
+ && DEFAULT_ABI != ABI_V4
+ && epilogue_type != EPILOGUE_TYPE_EH_RETURN)
+ {
+ /* Prevent reordering memory accesses against stack pointer restore. */
+ if (cfun->calls_alloca
+ || offset_below_red_zone_p (-info->total_size))
+ rs6000_emit_stack_tie (frame_reg_rtx, false);
+ insn = emit_insn (gen_add3_insn (sp_reg_rtx, sp_reg_rtx,
+ GEN_INT (info->total_size)));
+ frame_off = 0;
+ }
+ if (insn && frame_reg_rtx == sp_reg_rtx)
+ {
+ if (cfa_restores)
+ {
+ REG_NOTES (insn) = cfa_restores;
+ cfa_restores = NULL_RTX;
+ }
+ add_reg_note (insn, REG_CFA_DEF_CFA, sp_reg_rtx);
+ RTX_FRAME_RELATED_P (insn) = 1;
+ }
+
+ /* Restore AltiVec registers if we have not done so already. */
+ if (!ALWAYS_RESTORE_ALTIVEC_BEFORE_POP
+ && info->altivec_size != 0
+ && (DEFAULT_ABI == ABI_V4
+ || !offset_below_red_zone_p (info->altivec_save_offset)))
+ {
+ int i;
+
+ if ((strategy & REST_INLINE_VRS) == 0)
+ {
+ int end_save = info->altivec_save_offset + info->altivec_size;
+ int ptr_off;
+ rtx ptr_reg = gen_rtx_REG (Pmode, 0);
+ int scratch_regno = ptr_regno_for_savres (SAVRES_VR);
+ rtx scratch_reg = gen_rtx_REG (Pmode, scratch_regno);
+
+ if (end_save + frame_off != 0)
+ {
+ rtx offset = GEN_INT (end_save + frame_off);
+
+ emit_insn (gen_add3_insn (ptr_reg, frame_reg_rtx, offset));
+ }
+ else
+ emit_move_insn (ptr_reg, frame_reg_rtx);
+
+ ptr_off = -end_save;
+ insn = rs6000_emit_savres_rtx (info, scratch_reg,
+ info->altivec_save_offset + ptr_off,
+ 0, V4SImode, SAVRES_VR);
+ if (REGNO (frame_reg_rtx) == REGNO (scratch_reg))
+ {
+ /* Frame reg was clobbered by out-of-line save. Restore it
+ from ptr_reg, and if we are calling out-of-line gpr or
+ fpr restore set up the correct pointer and offset. */
+ unsigned newptr_regno = 1;
+ if (!restoring_GPRs_inline)
+ {
+ bool lr = info->gp_save_offset + info->gp_size == 0;
+ int sel = SAVRES_GPR | (lr ? SAVRES_LR : 0);
+ newptr_regno = ptr_regno_for_savres (sel);
+ end_save = info->gp_save_offset + info->gp_size;
+ }
+ else if (!restoring_FPRs_inline)
+ {
+ bool lr = !(strategy & REST_NOINLINE_FPRS_DOESNT_RESTORE_LR);
+ int sel = SAVRES_FPR | (lr ? SAVRES_LR : 0);
+ newptr_regno = ptr_regno_for_savres (sel);
+ end_save = info->fp_save_offset + info->fp_size;
+ }
+
+ if (newptr_regno != 1 && REGNO (frame_reg_rtx) != newptr_regno)
+ frame_reg_rtx = gen_rtx_REG (Pmode, newptr_regno);
+
+ if (end_save + ptr_off != 0)
+ {
+ rtx offset = GEN_INT (end_save + ptr_off);
+
+ frame_off = -end_save;
+ if (TARGET_32BIT)
+ emit_insn (gen_addsi3_carry (frame_reg_rtx,
+ ptr_reg, offset));
+ else
+ emit_insn (gen_adddi3_carry (frame_reg_rtx,
+ ptr_reg, offset));
+ }
+ else
+ {
+ frame_off = ptr_off;
+ emit_move_insn (frame_reg_rtx, ptr_reg);
+ }
+ }
+ }
+ else
+ {
+ for (i = info->first_altivec_reg_save; i <= LAST_ALTIVEC_REGNO; ++i)
+ if (info->vrsave_mask & ALTIVEC_REG_BIT (i))
+ {
+ rtx addr, areg, mem, insn;
+ rtx reg = gen_rtx_REG (V4SImode, i);
+ HOST_WIDE_INT offset
+ = (info->altivec_save_offset + frame_off
+ + 16 * (i - info->first_altivec_reg_save));
+
+ if (TARGET_P9_VECTOR && quad_address_offset_p (offset))
+ {
+ mem = gen_frame_mem (V4SImode,
+ gen_rtx_PLUS (Pmode, frame_reg_rtx,
+ GEN_INT (offset)));
+ insn = gen_rtx_SET (reg, mem);
+ }
+ else
+ {
+ areg = gen_rtx_REG (Pmode, 0);
+ emit_move_insn (areg, GEN_INT (offset));
+
+ /* AltiVec addressing mode is [reg+reg]. */
+ addr = gen_rtx_PLUS (Pmode, frame_reg_rtx, areg);
+ mem = gen_frame_mem (V4SImode, addr);
+
+ /* Rather than emitting a generic move, force use of the
+ lvx instruction, which we always want. In particular we
+ don't want lxvd2x/xxpermdi for little endian. */
+ insn = gen_altivec_lvx_v4si_internal (reg, mem);
+ }
+
+ (void) emit_insn (insn);
+ }
+ }
+
+ for (i = info->first_altivec_reg_save; i <= LAST_ALTIVEC_REGNO; ++i)
+ if (((strategy & REST_INLINE_VRS) == 0
+ || (info->vrsave_mask & ALTIVEC_REG_BIT (i)) != 0)
+ && (DEFAULT_ABI == ABI_V4 || flag_shrink_wrap)
+ && save_reg_p (i))
+ {
+ rtx reg = gen_rtx_REG (V4SImode, i);
+ cfa_restores = alloc_reg_note (REG_CFA_RESTORE, reg, cfa_restores);
+ }
+ }
+
+ /* Restore VRSAVE if we have not done so already. */
+ if (!ALWAYS_RESTORE_ALTIVEC_BEFORE_POP
+ && info->vrsave_size != 0
+ && (DEFAULT_ABI == ABI_V4
+ || !offset_below_red_zone_p (info->vrsave_save_offset)))
+ {
+ rtx reg;
+
+ reg = gen_rtx_REG (SImode, 12);
+ emit_insn (gen_frame_load (reg, frame_reg_rtx,
+ info->vrsave_save_offset + frame_off));
+
+ emit_insn (generate_set_vrsave (reg, info, 1));
+ }
+
+ /* If we exit by an out-of-line restore function on ABI_V4 then that
+ function will deallocate the stack, so we don't need to worry
+ about the unwinder restoring cr from an invalid stack frame
+ location. */
+ bool exit_func = (!restoring_FPRs_inline
+ || (!restoring_GPRs_inline
+ && info->first_fp_reg_save == 64));
+
+ /* In the ELFv2 ABI we need to restore all call-saved CR fields from
+ *separate* slots if the routine calls __builtin_eh_return, so
+ that they can be independently restored by the unwinder. */
+ if (DEFAULT_ABI == ABI_ELFv2 && crtl->calls_eh_return)
+ {
+ int i, cr_off = info->ehcr_offset;
+
+ for (i = 0; i < 8; i++)
+ if (!call_used_regs[CR0_REGNO + i])
+ {
+ rtx reg = gen_rtx_REG (SImode, 0);
+ emit_insn (gen_frame_load (reg, frame_reg_rtx,
+ cr_off + frame_off));
+
+ insn = emit_insn (gen_movsi_to_cr_one
+ (gen_rtx_REG (CCmode, CR0_REGNO + i), reg));
+
+ if (!exit_func && flag_shrink_wrap)
+ {
+ add_reg_note (insn, REG_CFA_RESTORE,
+ gen_rtx_REG (SImode, CR0_REGNO + i));
+
+ RTX_FRAME_RELATED_P (insn) = 1;
+ }
+
+ cr_off += reg_size;
+ }
+ }
+
+ /* Get the old lr if we saved it. If we are restoring registers
+ out-of-line, then the out-of-line routines can do this for us. */
+ if (restore_lr && restoring_GPRs_inline)
+ load_lr_save (0, frame_reg_rtx, info->lr_save_offset + frame_off);
+
+ /* Get the old cr if we saved it. */
+ if (info->cr_save_p)
+ {
+ unsigned cr_save_regno = 12;
+
+ if (!restoring_GPRs_inline)
+ {
+ /* Ensure we don't use the register used by the out-of-line
+ gpr register restore below. */
+ bool lr = info->gp_save_offset + info->gp_size == 0;
+ int sel = SAVRES_GPR | (lr ? SAVRES_LR : 0);
+ int gpr_ptr_regno = ptr_regno_for_savres (sel);
+
+ if (gpr_ptr_regno == 12)
+ cr_save_regno = 11;
+ gcc_checking_assert (REGNO (frame_reg_rtx) != cr_save_regno);
+ }
+ else if (REGNO (frame_reg_rtx) == 12)
+ cr_save_regno = 11;
+
+ cr_save_reg = load_cr_save (cr_save_regno, frame_reg_rtx,
+ info->cr_save_offset + frame_off,
+ exit_func);
+ }
+
+ /* Set LR here to try to overlap restores below. */
+ if (restore_lr && restoring_GPRs_inline)
+ restore_saved_lr (0, exit_func);
+
+ /* Load exception handler data registers, if needed. */
+ if (epilogue_type == EPILOGUE_TYPE_EH_RETURN)
+ {
+ unsigned int i, regno;
+
+ if (TARGET_AIX)
+ {
+ rtx reg = gen_rtx_REG (reg_mode, 2);
+ emit_insn (gen_frame_load (reg, frame_reg_rtx,
+ frame_off + RS6000_TOC_SAVE_SLOT));
+ }
+
+ for (i = 0; ; ++i)
+ {
+ rtx mem;
+
+ regno = EH_RETURN_DATA_REGNO (i);
+ if (regno == INVALID_REGNUM)
+ break;
+
+ mem = gen_frame_mem_offset (reg_mode, frame_reg_rtx,
+ info->ehrd_offset + frame_off
+ + reg_size * (int) i);
+
+ emit_move_insn (gen_rtx_REG (reg_mode, regno), mem);
+ }
+ }
+
+ /* Restore GPRs. This is done as a PARALLEL if we are using
+ the load-multiple instructions. */
+ if (!restoring_GPRs_inline)
+ {
+ /* We are jumping to an out-of-line function. */
+ rtx ptr_reg;
+ int end_save = info->gp_save_offset + info->gp_size;
+ bool can_use_exit = end_save == 0;
+ int sel = SAVRES_GPR | (can_use_exit ? SAVRES_LR : 0);
+ int ptr_off;
+
+ /* Emit stack reset code if we need it. */
+ ptr_regno = ptr_regno_for_savres (sel);
+ ptr_reg = gen_rtx_REG (Pmode, ptr_regno);
+ if (can_use_exit)
+ rs6000_emit_stack_reset (frame_reg_rtx, frame_off, ptr_regno);
+ else if (end_save + frame_off != 0)
+ emit_insn (gen_add3_insn (ptr_reg, frame_reg_rtx,
+ GEN_INT (end_save + frame_off)));
+ else if (REGNO (frame_reg_rtx) != ptr_regno)
+ emit_move_insn (ptr_reg, frame_reg_rtx);
+ if (REGNO (frame_reg_rtx) == ptr_regno)
+ frame_off = -end_save;
+
+ if (can_use_exit && info->cr_save_p)
+ restore_saved_cr (cr_save_reg, using_mtcr_multiple, true);
+
+ ptr_off = -end_save;
+ rs6000_emit_savres_rtx (info, ptr_reg,
+ info->gp_save_offset + ptr_off,
+ info->lr_save_offset + ptr_off,
+ reg_mode, sel);
+ }
+ else if (using_load_multiple)
+ {
+ rtvec p;
+ p = rtvec_alloc (32 - info->first_gp_reg_save);
+ for (i = 0; i < 32 - info->first_gp_reg_save; i++)
+ RTVEC_ELT (p, i)
+ = gen_frame_load (gen_rtx_REG (reg_mode, info->first_gp_reg_save + i),
+ frame_reg_rtx,
+ info->gp_save_offset + frame_off + reg_size * i);
+ emit_insn (gen_rtx_PARALLEL (VOIDmode, p));
+ }
+ else
+ {
+ int offset = info->gp_save_offset + frame_off;
+ for (i = info->first_gp_reg_save; i < 32; i++)
+ {
+ if (save_reg_p (i)
+ && !cfun->machine->gpr_is_wrapped_separately[i])
+ {
+ rtx reg = gen_rtx_REG (reg_mode, i);
+ emit_insn (gen_frame_load (reg, frame_reg_rtx, offset));
+ }
+
+ offset += reg_size;
+ }
+ }
+
+ if (DEFAULT_ABI == ABI_V4 || flag_shrink_wrap)
+ {
+ /* If the frame pointer was used then we can't delay emitting
+ a REG_CFA_DEF_CFA note. This must happen on the insn that
+ restores the frame pointer, r31. We may have already emitted
+ a REG_CFA_DEF_CFA note, but that's OK; A duplicate is
+ discarded by dwarf2cfi.c/dwarf2out.c, and in any case would
+ be harmless if emitted. */
+ if (frame_pointer_needed)
+ {
+ insn = get_last_insn ();
+ add_reg_note (insn, REG_CFA_DEF_CFA,
+ plus_constant (Pmode, frame_reg_rtx, frame_off));
+ RTX_FRAME_RELATED_P (insn) = 1;
+ }
+
+ /* Set up cfa_restores. We always need these when
+ shrink-wrapping. If not shrink-wrapping then we only need
+ the cfa_restore when the stack location is no longer valid.
+ The cfa_restores must be emitted on or before the insn that
+ invalidates the stack, and of course must not be emitted
+ before the insn that actually does the restore. The latter
+ is why it is a bad idea to emit the cfa_restores as a group
+ on the last instruction here that actually does a restore:
+ That insn may be reordered with respect to others doing
+ restores. */
+ if (flag_shrink_wrap
+ && !restoring_GPRs_inline
+ && info->first_fp_reg_save == 64)
+ cfa_restores = add_crlr_cfa_restore (info, cfa_restores);
+
+ for (i = info->first_gp_reg_save; i < 32; i++)
+ if (save_reg_p (i)
+ && !cfun->machine->gpr_is_wrapped_separately[i])
+ {
+ rtx reg = gen_rtx_REG (reg_mode, i);
+ cfa_restores = alloc_reg_note (REG_CFA_RESTORE, reg, cfa_restores);
+ }
+ }
+
+ if (!restoring_GPRs_inline
+ && info->first_fp_reg_save == 64)
+ {
+ /* We are jumping to an out-of-line function. */
+ if (cfa_restores)
+ emit_cfa_restores (cfa_restores);
+ return;
+ }
+
+ if (restore_lr && !restoring_GPRs_inline)
+ {
+ load_lr_save (0, frame_reg_rtx, info->lr_save_offset + frame_off);
+ restore_saved_lr (0, exit_func);
+ }
+
+ /* Restore fpr's if we need to do it without calling a function. */
+ if (restoring_FPRs_inline)
+ {
+ int offset = info->fp_save_offset + frame_off;
+ for (i = info->first_fp_reg_save; i < 64; i++)
+ {
+ if (save_reg_p (i)
+ && !cfun->machine->fpr_is_wrapped_separately[i - 32])
+ {
+ rtx reg = gen_rtx_REG (fp_reg_mode, i);
+ emit_insn (gen_frame_load (reg, frame_reg_rtx, offset));
+ if (DEFAULT_ABI == ABI_V4 || flag_shrink_wrap)
+ cfa_restores = alloc_reg_note (REG_CFA_RESTORE, reg,
+ cfa_restores);
+ }
+
+ offset += fp_reg_size;
+ }
+ }
+
+ /* If we saved cr, restore it here. Just those that were used. */
+ if (info->cr_save_p)
+ restore_saved_cr (cr_save_reg, using_mtcr_multiple, exit_func);
+
+ /* If this is V.4, unwind the stack pointer after all of the loads
+ have been done, or set up r11 if we are restoring fp out of line. */
+ ptr_regno = 1;
+ if (!restoring_FPRs_inline)
+ {
+ bool lr = (strategy & REST_NOINLINE_FPRS_DOESNT_RESTORE_LR) == 0;
+ int sel = SAVRES_FPR | (lr ? SAVRES_LR : 0);
+ ptr_regno = ptr_regno_for_savres (sel);
+ }
+
+ insn = rs6000_emit_stack_reset (frame_reg_rtx, frame_off, ptr_regno);
+ if (REGNO (frame_reg_rtx) == ptr_regno)
+ frame_off = 0;
+
+ if (insn && restoring_FPRs_inline)
+ {
+ if (cfa_restores)
+ {
+ REG_NOTES (insn) = cfa_restores;
+ cfa_restores = NULL_RTX;
+ }
+ add_reg_note (insn, REG_CFA_DEF_CFA, sp_reg_rtx);
+ RTX_FRAME_RELATED_P (insn) = 1;
+ }
+
+ if (epilogue_type == EPILOGUE_TYPE_EH_RETURN)
+ {
+ rtx sa = EH_RETURN_STACKADJ_RTX;
+ emit_insn (gen_add3_insn (sp_reg_rtx, sp_reg_rtx, sa));
+ }
+
+ if (epilogue_type != EPILOGUE_TYPE_SIBCALL && restoring_FPRs_inline)
+ {
+ if (cfa_restores)
+ {
+ /* We can't hang the cfa_restores off a simple return,
+ since the shrink-wrap code sometimes uses an existing
+ return. This means there might be a path from
+ pre-prologue code to this return, and dwarf2cfi code
+ wants the eh_frame unwinder state to be the same on
+ all paths to any point. So we need to emit the
+ cfa_restores before the return. For -m64 we really
+ don't need epilogue cfa_restores at all, except for
+ this irritating dwarf2cfi with shrink-wrap
+ requirement; The stack red-zone means eh_frame info
+ from the prologue telling the unwinder to restore
+ from the stack is perfectly good right to the end of
+ the function. */
+ emit_insn (gen_blockage ());
+ emit_cfa_restores (cfa_restores);
+ cfa_restores = NULL_RTX;
+ }
+
+ emit_jump_insn (targetm.gen_simple_return ());
+ }
+
+ if (epilogue_type != EPILOGUE_TYPE_SIBCALL && !restoring_FPRs_inline)
+ {
+ bool lr = (strategy & REST_NOINLINE_FPRS_DOESNT_RESTORE_LR) == 0;
+ rtvec p = rtvec_alloc (3 + !!lr + 64 - info->first_fp_reg_save);
+ int elt = 0;
+ RTVEC_ELT (p, elt++) = ret_rtx;
+ if (lr)
+ RTVEC_ELT (p, elt++) = gen_hard_reg_clobber (Pmode, LR_REGNO);
+
+ /* We have to restore more than two FP registers, so branch to the
+ restore function. It will return to our caller. */
+ int i;
+ int reg;
+ rtx sym;
+
+ if (flag_shrink_wrap)
+ cfa_restores = add_crlr_cfa_restore (info, cfa_restores);
+
+ sym = rs6000_savres_routine_sym (info, SAVRES_FPR | (lr ? SAVRES_LR : 0));
+ RTVEC_ELT (p, elt++) = gen_rtx_USE (VOIDmode, sym);
+ reg = (DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2)? 1 : 11;
+ RTVEC_ELT (p, elt++) = gen_rtx_USE (VOIDmode, gen_rtx_REG (Pmode, reg));
+
+ for (i = 0; i < 64 - info->first_fp_reg_save; i++)
+ {
+ rtx reg = gen_rtx_REG (DFmode, info->first_fp_reg_save + i);
+
+ RTVEC_ELT (p, elt++)
+ = gen_frame_load (reg, sp_reg_rtx, info->fp_save_offset + 8 * i);
+ if (flag_shrink_wrap
+ && save_reg_p (info->first_fp_reg_save + i))
+ cfa_restores = alloc_reg_note (REG_CFA_RESTORE, reg, cfa_restores);
+ }
+
+ emit_jump_insn (gen_rtx_PARALLEL (VOIDmode, p));
+ }
+
+ if (cfa_restores)
+ {
+ if (epilogue_type == EPILOGUE_TYPE_SIBCALL)
+ /* Ensure the cfa_restores are hung off an insn that won't
+ be reordered above other restores. */
+ emit_insn (gen_blockage ());
+
+ emit_cfa_restores (cfa_restores);
+ }
+}
+
+#if TARGET_MACHO
+
+/* Generate far-jump branch islands for everything recorded in
+ branch_islands. Invoked immediately after the last instruction of
+ the epilogue has been emitted; the branch islands must be appended
+ to, and contiguous with, the function body. Mach-O stubs are
+ generated in machopic_output_stub(). */
+
+static void
+macho_branch_islands (void)
+{
+ char tmp_buf[512];
+
+ while (!vec_safe_is_empty (branch_islands))
+ {
+ branch_island *bi = &branch_islands->last ();
+ const char *label = IDENTIFIER_POINTER (bi->label_name);
+ const char *name = IDENTIFIER_POINTER (bi->function_name);
+ char name_buf[512];
+ /* Cheap copy of the details from the Darwin ASM_OUTPUT_LABELREF(). */
+ if (name[0] == '*' || name[0] == '&')
+ strcpy (name_buf, name+1);
+ else
+ {
+ name_buf[0] = '_';
+ strcpy (name_buf+1, name);
+ }
+ strcpy (tmp_buf, "\n");
+ strcat (tmp_buf, label);
+#if defined (DBX_DEBUGGING_INFO) || defined (XCOFF_DEBUGGING_INFO)
+ if (write_symbols == DBX_DEBUG || write_symbols == XCOFF_DEBUG)
+ dbxout_stabd (N_SLINE, bi->line_number);
+#endif /* DBX_DEBUGGING_INFO || XCOFF_DEBUGGING_INFO */
+ if (flag_pic)
+ {
+ if (TARGET_LINK_STACK)
+ {
+ char name[32];
+ get_ppc476_thunk_name (name);
+ strcat (tmp_buf, ":\n\tmflr r0\n\tbl ");
+ strcat (tmp_buf, name);
+ strcat (tmp_buf, "\n");
+ strcat (tmp_buf, label);
+ strcat (tmp_buf, "_pic:\n\tmflr r11\n");
+ }
+ else
+ {
+ strcat (tmp_buf, ":\n\tmflr r0\n\tbcl 20,31,");
+ strcat (tmp_buf, label);
+ strcat (tmp_buf, "_pic\n");
+ strcat (tmp_buf, label);
+ strcat (tmp_buf, "_pic:\n\tmflr r11\n");
+ }
+
+ strcat (tmp_buf, "\taddis r11,r11,ha16(");
+ strcat (tmp_buf, name_buf);
+ strcat (tmp_buf, " - ");
+ strcat (tmp_buf, label);
+ strcat (tmp_buf, "_pic)\n");
+
+ strcat (tmp_buf, "\tmtlr r0\n");
+
+ strcat (tmp_buf, "\taddi r12,r11,lo16(");
+ strcat (tmp_buf, name_buf);
+ strcat (tmp_buf, " - ");
+ strcat (tmp_buf, label);
+ strcat (tmp_buf, "_pic)\n");
+
+ strcat (tmp_buf, "\tmtctr r12\n\tbctr\n");
+ }
+ else
+ {
+ strcat (tmp_buf, ":\n\tlis r12,hi16(");
+ strcat (tmp_buf, name_buf);
+ strcat (tmp_buf, ")\n\tori r12,r12,lo16(");
+ strcat (tmp_buf, name_buf);
+ strcat (tmp_buf, ")\n\tmtctr r12\n\tbctr");
+ }
+ output_asm_insn (tmp_buf, 0);
+#if defined (DBX_DEBUGGING_INFO) || defined (XCOFF_DEBUGGING_INFO)
+ if (write_symbols == DBX_DEBUG || write_symbols == XCOFF_DEBUG)
+ dbxout_stabd (N_SLINE, bi->line_number);
+#endif /* DBX_DEBUGGING_INFO || XCOFF_DEBUGGING_INFO */
+ branch_islands->pop ();
+ }
+}
+#endif
+
+/* Write function epilogue. */
+
+void
+rs6000_output_function_epilogue (FILE *file)
+{
+#if TARGET_MACHO
+ macho_branch_islands ();
+
+ {
+ rtx_insn *insn = get_last_insn ();
+ rtx_insn *deleted_debug_label = NULL;
+
+ /* Mach-O doesn't support labels at the end of objects, so if
+ it looks like we might want one, take special action.
+
+ First, collect any sequence of deleted debug labels. */
+ while (insn
+ && NOTE_P (insn)
+ && NOTE_KIND (insn) != NOTE_INSN_DELETED_LABEL)
+ {
+ /* Don't insert a nop for NOTE_INSN_DELETED_DEBUG_LABEL
+ notes only, instead set their CODE_LABEL_NUMBER to -1,
+ otherwise there would be code generation differences
+ in between -g and -g0. */
+ if (NOTE_P (insn) && NOTE_KIND (insn) == NOTE_INSN_DELETED_DEBUG_LABEL)
+ deleted_debug_label = insn;
+ insn = PREV_INSN (insn);
+ }
+
+ /* Second, if we have:
+ label:
+ barrier
+ then this needs to be detected, so skip past the barrier. */
+
+ if (insn && BARRIER_P (insn))
+ insn = PREV_INSN (insn);
+
+ /* Up to now we've only seen notes or barriers. */
+ if (insn)
+ {
+ if (LABEL_P (insn)
+ || (NOTE_P (insn)
+ && NOTE_KIND (insn) == NOTE_INSN_DELETED_LABEL))
+ /* Trailing label: <barrier>. */
+ fputs ("\tnop\n", file);
+ else
+ {
+ /* Lastly, see if we have a completely empty function body. */
+ while (insn && ! INSN_P (insn))
+ insn = PREV_INSN (insn);
+ /* If we don't find any insns, we've got an empty function body;
+ I.e. completely empty - without a return or branch. This is
+ taken as the case where a function body has been removed
+ because it contains an inline __builtin_unreachable(). GCC
+ states that reaching __builtin_unreachable() means UB so we're
+ not obliged to do anything special; however, we want
+ non-zero-sized function bodies. To meet this, and help the
+ user out, let's trap the case. */
+ if (insn == NULL)
+ fputs ("\ttrap\n", file);
+ }
+ }
+ else if (deleted_debug_label)
+ for (insn = deleted_debug_label; insn; insn = NEXT_INSN (insn))
+ if (NOTE_KIND (insn) == NOTE_INSN_DELETED_DEBUG_LABEL)
+ CODE_LABEL_NUMBER (insn) = -1;
+ }
+#endif
+
+ /* Output a traceback table here. See /usr/include/sys/debug.h for info
+ on its format.
+
+ We don't output a traceback table if -finhibit-size-directive was
+ used. The documentation for -finhibit-size-directive reads
+ ``don't output a @code{.size} assembler directive, or anything
+ else that would cause trouble if the function is split in the
+ middle, and the two halves are placed at locations far apart in
+ memory.'' The traceback table has this property, since it
+ includes the offset from the start of the function to the
+ traceback table itself.
+
+ System V.4 Powerpc's (and the embedded ABI derived from it) use a
+ different traceback table. */
+ if ((DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2)
+ && ! flag_inhibit_size_directive
+ && rs6000_traceback != traceback_none && !cfun->is_thunk)
+ {
+ const char *fname = NULL;
+ const char *language_string = lang_hooks.name;
+ int fixed_parms = 0, float_parms = 0, parm_info = 0;
+ int i;
+ int optional_tbtab;
+ rs6000_stack_t *info = rs6000_stack_info ();
+
+ if (rs6000_traceback == traceback_full)
+ optional_tbtab = 1;
+ else if (rs6000_traceback == traceback_part)
+ optional_tbtab = 0;
+ else
+ optional_tbtab = !optimize_size && !TARGET_ELF;
+
+ if (optional_tbtab)
+ {
+ fname = XSTR (XEXP (DECL_RTL (current_function_decl), 0), 0);
+ while (*fname == '.') /* V.4 encodes . in the name */
+ fname++;
+
+ /* Need label immediately before tbtab, so we can compute
+ its offset from the function start. */
+ ASM_OUTPUT_INTERNAL_LABEL_PREFIX (file, "LT");
+ ASM_OUTPUT_LABEL (file, fname);
+ }
+
+ /* The .tbtab pseudo-op can only be used for the first eight
+ expressions, since it can't handle the possibly variable
+ length fields that follow. However, if you omit the optional
+ fields, the assembler outputs zeros for all optional fields
+ anyways, giving each variable length field is minimum length
+ (as defined in sys/debug.h). Thus we cannot use the .tbtab
+ pseudo-op at all. */
+
+ /* An all-zero word flags the start of the tbtab, for debuggers
+ that have to find it by searching forward from the entry
+ point or from the current pc. */
+ fputs ("\t.long 0\n", file);
+
+ /* Tbtab format type. Use format type 0. */
+ fputs ("\t.byte 0,", file);
+
+ /* Language type. Unfortunately, there does not seem to be any
+ official way to discover the language being compiled, so we
+ use language_string.
+ C is 0. Fortran is 1. Ada is 3. C++ is 9.
+ Java is 13. Objective-C is 14. Objective-C++ isn't assigned
+ a number, so for now use 9. LTO, Go, D, and JIT aren't assigned
+ numbers either, so for now use 0. */
+ if (lang_GNU_C ()
+ || ! strcmp (language_string, "GNU GIMPLE")
+ || ! strcmp (language_string, "GNU Go")
+ || ! strcmp (language_string, "GNU D")
+ || ! strcmp (language_string, "libgccjit"))
+ i = 0;
+ else if (! strcmp (language_string, "GNU F77")
+ || lang_GNU_Fortran ())
+ i = 1;
+ else if (! strcmp (language_string, "GNU Ada"))
+ i = 3;
+ else if (lang_GNU_CXX ()
+ || ! strcmp (language_string, "GNU Objective-C++"))
+ i = 9;
+ else if (! strcmp (language_string, "GNU Java"))
+ i = 13;
+ else if (! strcmp (language_string, "GNU Objective-C"))
+ i = 14;
+ else
+ gcc_unreachable ();
+ fprintf (file, "%d,", i);
+
+ /* 8 single bit fields: global linkage (not set for C extern linkage,
+ apparently a PL/I convention?), out-of-line epilogue/prologue, offset
+ from start of procedure stored in tbtab, internal function, function
+ has controlled storage, function has no toc, function uses fp,
+ function logs/aborts fp operations. */
+ /* Assume that fp operations are used if any fp reg must be saved. */
+ fprintf (file, "%d,",
+ (optional_tbtab << 5) | ((info->first_fp_reg_save != 64) << 1));
+
+ /* 6 bitfields: function is interrupt handler, name present in
+ proc table, function calls alloca, on condition directives
+ (controls stack walks, 3 bits), saves condition reg, saves
+ link reg. */
+ /* The `function calls alloca' bit seems to be set whenever reg 31 is
+ set up as a frame pointer, even when there is no alloca call. */
+ fprintf (file, "%d,",
+ ((optional_tbtab << 6)
+ | ((optional_tbtab & frame_pointer_needed) << 5)
+ | (info->cr_save_p << 1)
+ | (info->lr_save_p)));
+
+ /* 3 bitfields: saves backchain, fixup code, number of fpr saved
+ (6 bits). */
+ fprintf (file, "%d,",
+ (info->push_p << 7) | (64 - info->first_fp_reg_save));
+
+ /* 2 bitfields: spare bits (2 bits), number of gpr saved (6 bits). */
+ fprintf (file, "%d,", (32 - first_reg_to_save ()));
+
+ if (optional_tbtab)
+ {
+ /* Compute the parameter info from the function decl argument
+ list. */
+ tree decl;
+ int next_parm_info_bit = 31;
+
+ for (decl = DECL_ARGUMENTS (current_function_decl);
+ decl; decl = DECL_CHAIN (decl))
+ {
+ rtx parameter = DECL_INCOMING_RTL (decl);
+ machine_mode mode = GET_MODE (parameter);
+
+ if (REG_P (parameter))
+ {
+ if (SCALAR_FLOAT_MODE_P (mode))
+ {
+ int bits;
+
+ float_parms++;
+
+ switch (mode)
+ {
+ case E_SFmode:
+ case E_SDmode:
+ bits = 0x2;
+ break;
+
+ case E_DFmode:
+ case E_DDmode:
+ case E_TFmode:
+ case E_TDmode:
+ case E_IFmode:
+ case E_KFmode:
+ bits = 0x3;
+ break;
+
+ default:
+ gcc_unreachable ();
+ }
+
+ /* If only one bit will fit, don't or in this entry. */
+ if (next_parm_info_bit > 0)
+ parm_info |= (bits << (next_parm_info_bit - 1));
+ next_parm_info_bit -= 2;
+ }
+ else
+ {
+ fixed_parms += ((GET_MODE_SIZE (mode)
+ + (UNITS_PER_WORD - 1))
+ / UNITS_PER_WORD);
+ next_parm_info_bit -= 1;
+ }
+ }
+ }
+ }
+
+ /* Number of fixed point parameters. */
+ /* This is actually the number of words of fixed point parameters; thus
+ an 8 byte struct counts as 2; and thus the maximum value is 8. */
+ fprintf (file, "%d,", fixed_parms);
+
+ /* 2 bitfields: number of floating point parameters (7 bits), parameters
+ all on stack. */
+ /* This is actually the number of fp registers that hold parameters;
+ and thus the maximum value is 13. */
+ /* Set parameters on stack bit if parameters are not in their original
+ registers, regardless of whether they are on the stack? Xlc
+ seems to set the bit when not optimizing. */
+ fprintf (file, "%d\n", ((float_parms << 1) | (! optimize)));
+
+ if (optional_tbtab)
+ {
+ /* Optional fields follow. Some are variable length. */
+
+ /* Parameter types, left adjusted bit fields: 0 fixed, 10 single
+ float, 11 double float. */
+ /* There is an entry for each parameter in a register, in the order
+ that they occur in the parameter list. Any intervening arguments
+ on the stack are ignored. If the list overflows a long (max
+ possible length 34 bits) then completely leave off all elements
+ that don't fit. */
+ /* Only emit this long if there was at least one parameter. */
+ if (fixed_parms || float_parms)
+ fprintf (file, "\t.long %d\n", parm_info);
+
+ /* Offset from start of code to tb table. */
+ fputs ("\t.long ", file);
+ ASM_OUTPUT_INTERNAL_LABEL_PREFIX (file, "LT");
+ RS6000_OUTPUT_BASENAME (file, fname);
+ putc ('-', file);
+ rs6000_output_function_entry (file, fname);
+ putc ('\n', file);
+
+ /* Interrupt handler mask. */
+ /* Omit this long, since we never set the interrupt handler bit
+ above. */
+
+ /* Number of CTL (controlled storage) anchors. */
+ /* Omit this long, since the has_ctl bit is never set above. */
+
+ /* Displacement into stack of each CTL anchor. */
+ /* Omit this list of longs, because there are no CTL anchors. */
+
+ /* Length of function name. */
+ if (*fname == '*')
+ ++fname;
+ fprintf (file, "\t.short %d\n", (int) strlen (fname));
+
+ /* Function name. */
+ assemble_string (fname, strlen (fname));
+
+ /* Register for alloca automatic storage; this is always reg 31.
+ Only emit this if the alloca bit was set above. */
+ if (frame_pointer_needed)
+ fputs ("\t.byte 31\n", file);
+
+ fputs ("\t.align 2\n", file);
+ }
+ }
+
+ /* Arrange to define .LCTOC1 label, if not already done. */
+ if (need_toc_init)
+ {
+ need_toc_init = 0;
+ if (!toc_initialized)
+ {
+ switch_to_section (toc_section);
+ switch_to_section (current_function_section ());
+ }
+ }
+}
+
+/* -fsplit-stack support. */
+
+/* A SYMBOL_REF for __morestack. */
+static GTY(()) rtx morestack_ref;
+
+static rtx
+gen_add3_const (rtx rt, rtx ra, long c)
+{
+ if (TARGET_64BIT)
+ return gen_adddi3 (rt, ra, GEN_INT (c));
+ else
+ return gen_addsi3 (rt, ra, GEN_INT (c));
+}
+
+/* Emit -fsplit-stack prologue, which goes before the regular function
+ prologue (at local entry point in the case of ELFv2). */
+
+void
+rs6000_expand_split_stack_prologue (void)
+{
+ rs6000_stack_t *info = rs6000_stack_info ();
+ unsigned HOST_WIDE_INT allocate;
+ long alloc_hi, alloc_lo;
+ rtx r0, r1, r12, lr, ok_label, compare, jump, call_fusage;
+ rtx_insn *insn;
+
+ gcc_assert (flag_split_stack && reload_completed);
+
+ if (!info->push_p)
+ return;
+
+ if (global_regs[29])
+ {
+ error ("%qs uses register r29", "%<-fsplit-stack%>");
+ inform (DECL_SOURCE_LOCATION (global_regs_decl[29]),
+ "conflicts with %qD", global_regs_decl[29]);
+ }
+
+ allocate = info->total_size;
+ if (allocate > (unsigned HOST_WIDE_INT) 1 << 31)
+ {
+ sorry ("Stack frame larger than 2G is not supported for "
+ "%<-fsplit-stack%>");
+ return;
+ }
+ if (morestack_ref == NULL_RTX)
+ {
+ morestack_ref = gen_rtx_SYMBOL_REF (Pmode, "__morestack");
+ SYMBOL_REF_FLAGS (morestack_ref) |= (SYMBOL_FLAG_LOCAL
+ | SYMBOL_FLAG_FUNCTION);
+ }
+
+ r0 = gen_rtx_REG (Pmode, 0);
+ r1 = gen_rtx_REG (Pmode, STACK_POINTER_REGNUM);
+ r12 = gen_rtx_REG (Pmode, 12);
+ emit_insn (gen_load_split_stack_limit (r0));
+ /* Always emit two insns here to calculate the requested stack,
+ so that the linker can edit them when adjusting size for calling
+ non-split-stack code. */
+ alloc_hi = (-allocate + 0x8000) & ~0xffffL;
+ alloc_lo = -allocate - alloc_hi;
+ if (alloc_hi != 0)
+ {
+ emit_insn (gen_add3_const (r12, r1, alloc_hi));
+ if (alloc_lo != 0)
+ emit_insn (gen_add3_const (r12, r12, alloc_lo));
+ else
+ emit_insn (gen_nop ());
+ }
+ else
+ {
+ emit_insn (gen_add3_const (r12, r1, alloc_lo));
+ emit_insn (gen_nop ());
+ }
+
+ compare = gen_rtx_REG (CCUNSmode, CR7_REGNO);
+ emit_insn (gen_rtx_SET (compare, gen_rtx_COMPARE (CCUNSmode, r12, r0)));
+ ok_label = gen_label_rtx ();
+ jump = gen_rtx_IF_THEN_ELSE (VOIDmode,
+ gen_rtx_GEU (VOIDmode, compare, const0_rtx),
+ gen_rtx_LABEL_REF (VOIDmode, ok_label),
+ pc_rtx);
+ insn = emit_jump_insn (gen_rtx_SET (pc_rtx, jump));
+ JUMP_LABEL (insn) = ok_label;
+ /* Mark the jump as very likely to be taken. */
+ add_reg_br_prob_note (insn, profile_probability::very_likely ());
+
+ lr = gen_rtx_REG (Pmode, LR_REGNO);
+ insn = emit_move_insn (r0, lr);
+ RTX_FRAME_RELATED_P (insn) = 1;
+ insn = emit_insn (gen_frame_store (r0, r1, info->lr_save_offset));
+ RTX_FRAME_RELATED_P (insn) = 1;
+
+ insn = emit_call_insn (gen_call (gen_rtx_MEM (SImode, morestack_ref),
+ const0_rtx, const0_rtx));
+ call_fusage = NULL_RTX;
+ use_reg (&call_fusage, r12);
+ /* Say the call uses r0, even though it doesn't, to stop regrename
+ from twiddling with the insns saving lr, trashing args for cfun.
+ The insns restoring lr are similarly protected by making
+ split_stack_return use r0. */
+ use_reg (&call_fusage, r0);
+ add_function_usage_to (insn, call_fusage);
+ /* Indicate that this function can't jump to non-local gotos. */
+ make_reg_eh_region_note_nothrow_nononlocal (insn);
+ emit_insn (gen_frame_load (r0, r1, info->lr_save_offset));
+ insn = emit_move_insn (lr, r0);
+ add_reg_note (insn, REG_CFA_RESTORE, lr);
+ RTX_FRAME_RELATED_P (insn) = 1;
+ emit_insn (gen_split_stack_return ());
+
+ emit_label (ok_label);
+ LABEL_NUSES (ok_label) = 1;
+}
+
+/* We may have to tell the dataflow pass that the split stack prologue
+ is initializing a register. */
+
+void
+rs6000_live_on_entry (bitmap regs)
+{
+ if (flag_split_stack)
+ bitmap_set_bit (regs, 12);
+}
+
+/* Emit -fsplit-stack dynamic stack allocation space check. */
+
+void
+rs6000_split_stack_space_check (rtx size, rtx label)
+{
+ rtx sp = gen_rtx_REG (Pmode, STACK_POINTER_REGNUM);
+ rtx limit = gen_reg_rtx (Pmode);
+ rtx requested = gen_reg_rtx (Pmode);
+ rtx cmp = gen_reg_rtx (CCUNSmode);
+ rtx jump;
+
+ emit_insn (gen_load_split_stack_limit (limit));
+ if (CONST_INT_P (size))
+ emit_insn (gen_add3_insn (requested, sp, GEN_INT (-INTVAL (size))));
+ else
+ {
+ size = force_reg (Pmode, size);
+ emit_move_insn (requested, gen_rtx_MINUS (Pmode, sp, size));
+ }
+ emit_insn (gen_rtx_SET (cmp, gen_rtx_COMPARE (CCUNSmode, requested, limit)));
+ jump = gen_rtx_IF_THEN_ELSE (VOIDmode,
+ gen_rtx_GEU (VOIDmode, cmp, const0_rtx),
+ gen_rtx_LABEL_REF (VOIDmode, label),
+ pc_rtx);
+ jump = emit_jump_insn (gen_rtx_SET (pc_rtx, jump));
+ JUMP_LABEL (jump) = label;
+}
+
+
+/* Return whether we need to always update the saved TOC pointer when we update
+ the stack pointer. */
+
+static bool
+rs6000_save_toc_in_prologue_p (void)
+{
+ return (cfun && cfun->machine && cfun->machine->save_toc_in_prologue);
+}
+
+#include "gt-rs6000-logue.h"
diff --git a/gcc/config/rs6000/rs6000-opts.h b/gcc/config/rs6000/rs6000-opts.h
index 6adbf80..ae877bc 100644
--- a/gcc/config/rs6000/rs6000-opts.h
+++ b/gcc/config/rs6000/rs6000-opts.h
@@ -62,6 +62,8 @@ enum processor_type
PROCESSOR_POWER8,
PROCESSOR_POWER9,
+ PROCESSOR_FUTURE,
+
PROCESSOR_RS64A,
PROCESSOR_MPCCORE,
PROCESSOR_CELL,
diff --git a/gcc/config/rs6000/rs6000-protos.h b/gcc/config/rs6000/rs6000-protos.h
index 8466368..feb1250 100644
--- a/gcc/config/rs6000/rs6000-protos.h
+++ b/gcc/config/rs6000/rs6000-protos.h
@@ -152,6 +152,9 @@ extern rtx rs6000_machopic_legitimize_pic_address (rtx, machine_mode,
extern rtx rs6000_allocate_stack_temp (machine_mode, bool, bool);
extern align_flags rs6000_loop_align (rtx);
extern void rs6000_split_logical (rtx [], enum rtx_code, bool, bool, bool);
+extern bool rs6000_pcrel_p (struct function *);
+extern bool rs6000_fndecl_pcrel_p (const_tree);
+extern bool rs6000_prefixed_address (rtx, machine_mode);
#endif /* RTX_CODE */
#ifdef TREE_CODE
@@ -190,7 +193,7 @@ extern alias_set_type get_TOC_alias_set (void);
extern void rs6000_emit_prologue (void);
extern void rs6000_emit_load_toc_table (int);
extern unsigned int rs6000_dbx_register_number (unsigned int, unsigned int);
-extern void rs6000_emit_epilogue (int);
+extern void rs6000_emit_epilogue (enum epilogue_type);
extern void rs6000_expand_split_stack_prologue (void);
extern void rs6000_split_stack_space_check (rtx, rtx);
extern void rs6000_emit_eh_reg_restore (rtx, rtx);
diff --git a/gcc/config/rs6000/rs6000-string.c b/gcc/config/rs6000/rs6000-string.c
index 560ecba..b939185 100644
--- a/gcc/config/rs6000/rs6000-string.c
+++ b/gcc/config/rs6000/rs6000-string.c
@@ -963,6 +963,7 @@ expand_compare_loop (rtx operands[])
max_bytes = 64;
break;
case PROCESSOR_POWER9:
+ case PROCESSOR_FUTURE:
if (bytes_is_const)
max_bytes = 191;
else
diff --git a/gcc/config/rs6000/rs6000-tables.opt b/gcc/config/rs6000/rs6000-tables.opt
index fa2e66b..911ed09 100644
--- a/gcc/config/rs6000/rs6000-tables.opt
+++ b/gcc/config/rs6000/rs6000-tables.opt
@@ -194,3 +194,6 @@ Enum(rs6000_cpu_opt_value) String(powerpc64le) Value(54)
EnumValue
Enum(rs6000_cpu_opt_value) String(rs64) Value(55)
+EnumValue
+Enum(rs6000_cpu_opt_value) String(future) Value(56)
+
diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c
index 3d1af9f..f59f3a9 100644
--- a/gcc/config/rs6000/rs6000.c
+++ b/gcc/config/rs6000/rs6000.c
@@ -52,7 +52,6 @@
#include "explow.h"
#include "expr.h"
#include "output.h"
-#include "dbxout.h"
#include "common/common-target.h"
#include "langhooks.h"
#include "reload.h"
@@ -75,14 +74,12 @@
#if TARGET_XCOFF
#include "xcoffout.h" /* get declarations of xcoff_*_section_name */
#endif
-#if TARGET_MACHO
-#include "gstab.h" /* for N_SLINE */
-#endif
#include "case-cfn-macros.h"
#include "ppc-auxv.h"
#include "tree-ssa-propagate.h"
#include "tree-vrp.h"
#include "tree-ssanames.h"
+#include "rs6000-internal.h"
/* This file should be included last. */
#include "target-def.h"
@@ -107,85 +104,12 @@
static pad_direction rs6000_function_arg_padding (machine_mode, const_tree);
-/* Structure used to define the rs6000 stack */
-typedef struct rs6000_stack {
- int reload_completed; /* stack info won't change from here on */
- int first_gp_reg_save; /* first callee saved GP register used */
- int first_fp_reg_save; /* first callee saved FP register used */
- int first_altivec_reg_save; /* first callee saved AltiVec register used */
- int lr_save_p; /* true if the link reg needs to be saved */
- int cr_save_p; /* true if the CR reg needs to be saved */
- unsigned int vrsave_mask; /* mask of vec registers to save */
- int push_p; /* true if we need to allocate stack space */
- int calls_p; /* true if the function makes any calls */
- int world_save_p; /* true if we're saving *everything*:
- r13-r31, cr, f14-f31, vrsave, v20-v31 */
- enum rs6000_abi abi; /* which ABI to use */
- int gp_save_offset; /* offset to save GP regs from initial SP */
- int fp_save_offset; /* offset to save FP regs from initial SP */
- int altivec_save_offset; /* offset to save AltiVec regs from initial SP */
- int lr_save_offset; /* offset to save LR from initial SP */
- int cr_save_offset; /* offset to save CR from initial SP */
- int vrsave_save_offset; /* offset to save VRSAVE from initial SP */
- int varargs_save_offset; /* offset to save the varargs registers */
- int ehrd_offset; /* offset to EH return data */
- int ehcr_offset; /* offset to EH CR field data */
- int reg_size; /* register size (4 or 8) */
- HOST_WIDE_INT vars_size; /* variable save area size */
- int parm_size; /* outgoing parameter size */
- int save_size; /* save area size */
- int fixed_size; /* fixed size of stack frame */
- int gp_size; /* size of saved GP registers */
- int fp_size; /* size of saved FP registers */
- int altivec_size; /* size of saved AltiVec registers */
- int cr_size; /* size to hold CR if not in fixed area */
- int vrsave_size; /* size to hold VRSAVE */
- int altivec_padding_size; /* size of altivec alignment padding */
- HOST_WIDE_INT total_size; /* total bytes allocated for stack */
- int savres_strategy;
-} rs6000_stack_t;
-
-/* A C structure for machine-specific, per-function data.
- This is added to the cfun structure. */
-typedef struct GTY(()) machine_function
-{
- /* Flags if __builtin_return_address (n) with n >= 1 was used. */
- int ra_needs_full_frame;
- /* Flags if __builtin_return_address (0) was used. */
- int ra_need_lr;
- /* Cache lr_save_p after expansion of builtin_eh_return. */
- int lr_save_state;
- /* Whether we need to save the TOC to the reserved stack location in the
- function prologue. */
- bool save_toc_in_prologue;
- /* Offset from virtual_stack_vars_rtx to the start of the ABI_V4
- varargs save area. */
- HOST_WIDE_INT varargs_save_offset;
- /* Alternative internal arg pointer for -fsplit-stack. */
- rtx split_stack_arg_pointer;
- bool split_stack_argp_used;
- /* Flag if r2 setup is needed with ELFv2 ABI. */
- bool r2_setup_needed;
- /* The number of components we use for separate shrink-wrapping. */
- int n_components;
- /* The components already handled by separate shrink-wrapping, which should
- not be considered by the prologue and epilogue. */
- bool gpr_is_wrapped_separately[32];
- bool fpr_is_wrapped_separately[32];
- bool lr_is_wrapped_separately;
- bool toc_is_wrapped_separately;
-} machine_function;
-
/* Support targetm.vectorize.builtin_mask_for_load. */
static GTY(()) tree altivec_builtin_mask_for_load;
/* Set to nonzero once AIX common-mode calls have been defined. */
static GTY(()) int common_mode_defined;
-/* Label number of label created for -mrelocatable, to call to so we can
- get the address of the GOT section */
-static int rs6000_pic_labelno;
-
#ifdef USING_ELFOS_H
/* Counter for labels which are to be placed in .fixup. */
int fixuplabelno = 0;
@@ -265,7 +189,9 @@ static GTY(()) section *tls_data_section;
static GTY(()) section *tls_private_data_section;
static GTY(()) section *read_only_private_data_section;
static GTY(()) section *sdata2_section;
-static GTY(()) section *toc_section;
+
+extern GTY(()) section *toc_section;
+section *toc_section = 0;
struct builtin_description
{
@@ -1329,8 +1255,6 @@ static tree (*rs6000_veclib_handler) (combined_fn, tree, tree);
static bool rs6000_debug_legitimate_address_p (machine_mode, rtx, bool);
-static struct machine_function * rs6000_init_machine_status (void);
-static int rs6000_ra_ever_killed (void);
static tree rs6000_handle_longcall_attribute (tree *, tree, tree, int, bool *);
static tree rs6000_handle_altivec_attribute (tree *, tree, tree, int, bool *);
static tree rs6000_handle_struct_attribute (tree *, tree, tree, int, bool *);
@@ -1357,15 +1281,12 @@ static tree builtin_function_type (machine_mode, machine_mode,
enum rs6000_builtins, const char *name);
static void rs6000_common_init_builtins (void);
static void htm_init_builtins (void);
-static rs6000_stack_t *rs6000_stack_info (void);
-static void is_altivec_return_reg (rtx, void *);
int easy_vector_constant (rtx, machine_mode);
static rtx rs6000_debug_legitimize_address (rtx, rtx, machine_mode);
static rtx rs6000_legitimize_tls_address (rtx, enum tls_model);
static rtx rs6000_darwin64_record_arg (CUMULATIVE_ARGS *, const_tree,
bool, bool);
#if TARGET_MACHO
-static void macho_branch_islands (void);
static tree get_prev_label (tree);
#endif
static bool rs6000_mode_dependent_address (const_rtx);
@@ -1385,7 +1306,6 @@ static bool rs6000_debug_secondary_memory_needed (machine_mode,
static bool rs6000_debug_can_change_mode_class (machine_mode,
machine_mode,
reg_class_t);
-static bool rs6000_save_toc_in_prologue_p (void);
static rtx rs6000_internal_arg_pointer (void);
static bool (*rs6000_mode_dependent_address_ptr) (const_rtx)
@@ -1413,7 +1333,6 @@ static bool rs6000_secondary_reload_move (enum rs6000_reg_type,
secondary_reload_info *,
bool);
rtl_opt_pass *make_pass_analyze_swaps (gcc::context*);
-static bool rs6000_keep_leaf_when_profiled () __attribute__ ((unused));
static tree rs6000_fold_builtin (tree, int, tree *, bool);
/* Hash table stuff for keeping track of TOC entries. */
@@ -1531,9 +1450,6 @@ static const struct attribute_spec rs6000_attribute_table[] =
#ifndef TARGET_PROFILE_KERNEL
#define TARGET_PROFILE_KERNEL 0
#endif
-
-/* The VRSAVE bitmask puts bit %v0 as the most significant bit. */
-#define ALTIVEC_REG_BIT(REGNO) (0x80000000 >> ((REGNO) - FIRST_ALTIVEC_REGNO))
/* Initialize the GCC target structure. */
#undef TARGET_ATTRIBUTE_TABLE
@@ -1909,6 +1825,9 @@ static const struct attribute_spec rs6000_attribute_table[] =
#undef TARGET_CAN_USE_DOLOOP_P
#define TARGET_CAN_USE_DOLOOP_P can_use_doloop_if_innermost
+#undef TARGET_PREDICT_DOLOOP_P
+#define TARGET_PREDICT_DOLOOP_P rs6000_predict_doloop_p
+
#undef TARGET_ATOMIC_ASSIGN_EXPAND_FENV
#define TARGET_ATOMIC_ASSIGN_EXPAND_FENV rs6000_atomic_assign_expand_fenv
@@ -2508,67 +2427,19 @@ rs6000_debug_reg_global (void)
"f reg_class = %s\n"
"v reg_class = %s\n"
"wa reg_class = %s\n"
- "wb reg_class = %s\n"
- "wd reg_class = %s\n"
"we reg_class = %s\n"
- "wf reg_class = %s\n"
- "wg reg_class = %s\n"
- "wh reg_class = %s\n"
- "wi reg_class = %s\n"
- "wj reg_class = %s\n"
- "wk reg_class = %s\n"
- "wl reg_class = %s\n"
- "wm reg_class = %s\n"
- "wo reg_class = %s\n"
- "wp reg_class = %s\n"
- "wq reg_class = %s\n"
"wr reg_class = %s\n"
- "ws reg_class = %s\n"
- "wt reg_class = %s\n"
- "wu reg_class = %s\n"
- "wv reg_class = %s\n"
- "ww reg_class = %s\n"
"wx reg_class = %s\n"
- "wy reg_class = %s\n"
- "wz reg_class = %s\n"
"wA reg_class = %s\n"
- "wH reg_class = %s\n"
- "wI reg_class = %s\n"
- "wJ reg_class = %s\n"
- "wK reg_class = %s\n"
"\n",
reg_class_names[rs6000_constraints[RS6000_CONSTRAINT_d]],
reg_class_names[rs6000_constraints[RS6000_CONSTRAINT_f]],
reg_class_names[rs6000_constraints[RS6000_CONSTRAINT_v]],
reg_class_names[rs6000_constraints[RS6000_CONSTRAINT_wa]],
- reg_class_names[rs6000_constraints[RS6000_CONSTRAINT_wb]],
- reg_class_names[rs6000_constraints[RS6000_CONSTRAINT_wd]],
reg_class_names[rs6000_constraints[RS6000_CONSTRAINT_we]],
- reg_class_names[rs6000_constraints[RS6000_CONSTRAINT_wf]],
- reg_class_names[rs6000_constraints[RS6000_CONSTRAINT_wg]],
- reg_class_names[rs6000_constraints[RS6000_CONSTRAINT_wh]],
- reg_class_names[rs6000_constraints[RS6000_CONSTRAINT_wi]],
- reg_class_names[rs6000_constraints[RS6000_CONSTRAINT_wj]],
- reg_class_names[rs6000_constraints[RS6000_CONSTRAINT_wk]],
- reg_class_names[rs6000_constraints[RS6000_CONSTRAINT_wl]],
- reg_class_names[rs6000_constraints[RS6000_CONSTRAINT_wm]],
- reg_class_names[rs6000_constraints[RS6000_CONSTRAINT_wo]],
- reg_class_names[rs6000_constraints[RS6000_CONSTRAINT_wp]],
- reg_class_names[rs6000_constraints[RS6000_CONSTRAINT_wq]],
reg_class_names[rs6000_constraints[RS6000_CONSTRAINT_wr]],
- reg_class_names[rs6000_constraints[RS6000_CONSTRAINT_ws]],
- reg_class_names[rs6000_constraints[RS6000_CONSTRAINT_wt]],
- reg_class_names[rs6000_constraints[RS6000_CONSTRAINT_wu]],
- reg_class_names[rs6000_constraints[RS6000_CONSTRAINT_wv]],
- reg_class_names[rs6000_constraints[RS6000_CONSTRAINT_ww]],
reg_class_names[rs6000_constraints[RS6000_CONSTRAINT_wx]],
- reg_class_names[rs6000_constraints[RS6000_CONSTRAINT_wy]],
- reg_class_names[rs6000_constraints[RS6000_CONSTRAINT_wz]],
- reg_class_names[rs6000_constraints[RS6000_CONSTRAINT_wA]],
- reg_class_names[rs6000_constraints[RS6000_CONSTRAINT_wH]],
- reg_class_names[rs6000_constraints[RS6000_CONSTRAINT_wI]],
- reg_class_names[rs6000_constraints[RS6000_CONSTRAINT_wJ]],
- reg_class_names[rs6000_constraints[RS6000_CONSTRAINT_wK]]);
+ reg_class_names[rs6000_constraints[RS6000_CONSTRAINT_wA]]);
nl = "\n";
for (m = 0; m < NUM_MACHINE_MODES; ++m)
@@ -3176,29 +3047,9 @@ rs6000_init_hard_regno_mode_ok (bool global_init_p)
v - Altivec register.
wa - Any VSX register.
wc - Reserved to represent individual CR bits (used in LLVM).
- wd - Preferred register class for V2DFmode.
- wf - Preferred register class for V4SFmode.
- wg - Float register for power6x move insns.
- wh - FP register for direct move instructions.
- wi - FP or VSX register to hold 64-bit integers for VSX insns.
- wj - FP or VSX register to hold 64-bit integers for direct moves.
- wk - FP or VSX register to hold 64-bit doubles for direct moves.
- wl - Float register if we can do 32-bit signed int loads.
- wm - VSX register for ISA 2.07 direct move operations.
wn - always NO_REGS.
wr - GPR if 64-bit mode is permitted.
- ws - Register class to do ISA 2.06 DF operations.
- wt - VSX register for TImode in VSX registers.
- wu - Altivec register for ISA 2.07 VSX SF/SI load/stores.
- wv - Altivec register for ISA 2.06 VSX DF/DI load/stores.
- ww - Register class to do SF conversions in with VSX operations.
- wx - Float register if we can do 32-bit int stores.
- wy - Register class to do ISA 2.07 SF operations.
- wz - Float register if we can do 32-bit unsigned int loads.
- wH - Altivec register if SImode is allowed in VSX registers.
- wI - Float register if SImode is allowed in VSX registers.
- wJ - Float register if QImode/HImode are allowed in VSX registers.
- wK - Altivec register if QImode/HImode are allowed in VSX registers. */
+ wx - Float register if we can do 32-bit int stores. */
if (TARGET_HARD_FLOAT)
{
@@ -3207,90 +3058,26 @@ rs6000_init_hard_regno_mode_ok (bool global_init_p)
}
if (TARGET_VSX)
- {
- rs6000_constraints[RS6000_CONSTRAINT_wa] = VSX_REGS;
- rs6000_constraints[RS6000_CONSTRAINT_wd] = VSX_REGS; /* V2DFmode */
- rs6000_constraints[RS6000_CONSTRAINT_wf] = VSX_REGS; /* V4SFmode */
- rs6000_constraints[RS6000_CONSTRAINT_ws] = VSX_REGS; /* DFmode */
- rs6000_constraints[RS6000_CONSTRAINT_wv] = ALTIVEC_REGS; /* DFmode */
- rs6000_constraints[RS6000_CONSTRAINT_wi] = VSX_REGS; /* DImode */
- rs6000_constraints[RS6000_CONSTRAINT_wt] = VSX_REGS; /* TImode */
- }
+ rs6000_constraints[RS6000_CONSTRAINT_wa] = VSX_REGS;
/* Add conditional constraints based on various options, to allow us to
collapse multiple insn patterns. */
if (TARGET_ALTIVEC)
rs6000_constraints[RS6000_CONSTRAINT_v] = ALTIVEC_REGS;
- if (TARGET_MFPGPR) /* DFmode */
- rs6000_constraints[RS6000_CONSTRAINT_wg] = FLOAT_REGS;
-
- if (TARGET_LFIWAX)
- rs6000_constraints[RS6000_CONSTRAINT_wl] = FLOAT_REGS; /* DImode */
-
- if (TARGET_DIRECT_MOVE)
- {
- rs6000_constraints[RS6000_CONSTRAINT_wh] = FLOAT_REGS;
- rs6000_constraints[RS6000_CONSTRAINT_wj] /* DImode */
- = rs6000_constraints[RS6000_CONSTRAINT_wi];
- rs6000_constraints[RS6000_CONSTRAINT_wk] /* DFmode */
- = rs6000_constraints[RS6000_CONSTRAINT_ws];
- rs6000_constraints[RS6000_CONSTRAINT_wm] = VSX_REGS;
- }
-
if (TARGET_POWERPC64)
{
rs6000_constraints[RS6000_CONSTRAINT_wr] = GENERAL_REGS;
rs6000_constraints[RS6000_CONSTRAINT_wA] = BASE_REGS;
}
- if (TARGET_P8_VECTOR) /* SFmode */
- {
- rs6000_constraints[RS6000_CONSTRAINT_wu] = ALTIVEC_REGS;
- rs6000_constraints[RS6000_CONSTRAINT_wy] = VSX_REGS;
- rs6000_constraints[RS6000_CONSTRAINT_ww] = VSX_REGS;
- }
- else if (TARGET_VSX)
- rs6000_constraints[RS6000_CONSTRAINT_ww] = FLOAT_REGS;
-
if (TARGET_STFIWX)
rs6000_constraints[RS6000_CONSTRAINT_wx] = FLOAT_REGS; /* DImode */
- if (TARGET_LFIWZX)
- rs6000_constraints[RS6000_CONSTRAINT_wz] = FLOAT_REGS; /* DImode */
-
- if (TARGET_FLOAT128_TYPE)
- {
- rs6000_constraints[RS6000_CONSTRAINT_wq] = VSX_REGS; /* KFmode */
- if (FLOAT128_IEEE_P (TFmode))
- rs6000_constraints[RS6000_CONSTRAINT_wp] = VSX_REGS; /* TFmode */
- }
-
- if (TARGET_P9_VECTOR)
- {
- /* Support for new D-form instructions. */
- rs6000_constraints[RS6000_CONSTRAINT_wb] = ALTIVEC_REGS;
-
- /* Support for ISA 3.0 (power9) vectors. */
- rs6000_constraints[RS6000_CONSTRAINT_wo] = VSX_REGS;
- }
-
/* Support for new direct moves (ISA 3.0 + 64bit). */
if (TARGET_DIRECT_MOVE_128)
rs6000_constraints[RS6000_CONSTRAINT_we] = VSX_REGS;
- /* Support small integers in VSX registers. */
- if (TARGET_P8_VECTOR)
- {
- rs6000_constraints[RS6000_CONSTRAINT_wH] = ALTIVEC_REGS;
- rs6000_constraints[RS6000_CONSTRAINT_wI] = FLOAT_REGS;
- if (TARGET_P9_VECTOR)
- {
- rs6000_constraints[RS6000_CONSTRAINT_wJ] = FLOAT_REGS;
- rs6000_constraints[RS6000_CONSTRAINT_wK] = ALTIVEC_REGS;
- }
- }
-
/* Set up the reload helper and direct move functions. */
if (TARGET_VSX || TARGET_ALTIVEC)
{
@@ -3631,10 +3418,22 @@ darwin_rs6000_override_options (void)
rs6000_isa_flags |= OPTION_MASK_POWERPC64;
warning (0, "%qs requires PowerPC64 architecture, enabling", "-m64");
}
+
+ /* The linkers [ld64] that support 64Bit do not need the JBSR longcall
+ optimisation, and will not work with the most generic case (where the
+ symbol is undefined external, but there is no symbl stub). */
+ if (TARGET_64BIT)
+ rs6000_default_long_calls = 0;
+
+ /* ld_classic is (so far) still used for kernel (static) code, and supports
+ the JBSR longcall / branch islands. */
if (flag_mkernel)
{
rs6000_default_long_calls = 1;
- rs6000_isa_flags |= OPTION_MASK_SOFT_FLOAT;
+
+ /* Allow a kext author to do -mkernel -mhard-float. */
+ if (! (rs6000_isa_flags_explicit & OPTION_MASK_SOFT_FLOAT))
+ rs6000_isa_flags |= OPTION_MASK_SOFT_FLOAT;
}
/* Make -m64 imply -maltivec. Darwin's 64-bit ABI includes
@@ -3829,6 +3628,12 @@ rs6000_option_override_internal (bool global_init_p)
&& !global_options_set.x_flag_asynchronous_unwind_tables)
flag_asynchronous_unwind_tables = 1;
+ /* -fvariable-expansion-in-unroller is a win for POWER whenever the
+ loop unroller is active. It is only checked during unrolling, so
+ we can just set it on by default. */
+ if (!global_options_set.x_flag_variable_expansion_in_unroller)
+ flag_variable_expansion_in_unroller = 1;
+
/* Set the pointer size. */
if (TARGET_64BIT)
{
@@ -4275,7 +4080,7 @@ rs6000_option_override_internal (bool global_init_p)
if (main_target_opt != NULL
&& (main_target_opt->x_rs6000_long_double_type_size
!= default_long_double_size))
- error ("target attribute or pragma changes long double size");
+ error ("target attribute or pragma changes %<long double%> size");
else
rs6000_long_double_type_size = default_long_double_size;
}
@@ -4310,9 +4115,11 @@ rs6000_option_override_internal (bool global_init_p)
{
warned_change_long_double = true;
if (TARGET_IEEEQUAD)
- warning (OPT_Wpsabi, "Using IEEE extended precision long double");
+ warning (OPT_Wpsabi, "Using IEEE extended precision "
+ "%<long double%>");
else
- warning (OPT_Wpsabi, "Using IBM extended precision long double");
+ warning (OPT_Wpsabi, "Using IBM extended precision "
+ "%<long double%>");
}
}
}
@@ -4375,6 +4182,26 @@ rs6000_option_override_internal (bool global_init_p)
rs6000_isa_flags &= ~OPTION_MASK_FLOAT128_HW;
}
+ /* -mprefixed-addr (and hence -mpcrel) requires -mcpu=future. */
+ if (TARGET_PREFIXED_ADDR && !TARGET_FUTURE)
+ {
+ if ((rs6000_isa_flags_explicit & OPTION_MASK_PCREL) != 0)
+ error ("%qs requires %qs", "-mpcrel", "-mcpu=future");
+ else if ((rs6000_isa_flags_explicit & OPTION_MASK_PREFIXED_ADDR) != 0)
+ error ("%qs requires %qs", "-mprefixed-addr", "-mcpu=future");
+
+ rs6000_isa_flags &= ~(OPTION_MASK_PCREL | OPTION_MASK_PREFIXED_ADDR);
+ }
+
+ /* -mpcrel requires prefixed load/store addressing. */
+ if (TARGET_PCREL && !TARGET_PREFIXED_ADDR)
+ {
+ if ((rs6000_isa_flags_explicit & OPTION_MASK_PCREL) != 0)
+ error ("%qs requires %qs", "-mpcrel", "-mprefixed-addr");
+
+ rs6000_isa_flags &= ~OPTION_MASK_PCREL;
+ }
+
/* Print the options after updating the defaults. */
if (TARGET_DEBUG_REG || TARGET_DEBUG_TARGET)
rs6000_print_isa_options (stderr, 0, "after defaults", rs6000_isa_flags);
@@ -4515,6 +4342,7 @@ rs6000_option_override_internal (bool global_init_p)
&& rs6000_tune != PROCESSOR_POWER7
&& rs6000_tune != PROCESSOR_POWER8
&& rs6000_tune != PROCESSOR_POWER9
+ && rs6000_tune != PROCESSOR_FUTURE
&& rs6000_tune != PROCESSOR_PPCA2
&& rs6000_tune != PROCESSOR_CELL
&& rs6000_tune != PROCESSOR_PPC476);
@@ -4528,6 +4356,7 @@ rs6000_option_override_internal (bool global_init_p)
|| rs6000_tune == PROCESSOR_POWER7
|| rs6000_tune == PROCESSOR_POWER8
|| rs6000_tune == PROCESSOR_POWER9
+ || rs6000_tune == PROCESSOR_FUTURE
|| rs6000_tune == PROCESSOR_PPCE500MC
|| rs6000_tune == PROCESSOR_PPCE500MC64
|| rs6000_tune == PROCESSOR_PPCE5500
@@ -4828,6 +4657,7 @@ rs6000_option_override_internal (bool global_init_p)
break;
case PROCESSOR_POWER9:
+ case PROCESSOR_FUTURE:
rs6000_cost = &power9_cost;
break;
@@ -5711,6 +5541,39 @@ rs6000_builtin_md_vectorized_function (tree fndecl, tree type_out,
/* Default CPU string for rs6000*_file_start functions. */
static const char *rs6000_default_cpu;
+#ifdef USING_ELFOS_H
+const char *rs6000_machine;
+
+const char *
+rs6000_machine_from_flags (void)
+{
+ if ((rs6000_isa_flags & (ISA_FUTURE_MASKS_SERVER & ~ISA_3_0_MASKS_SERVER))
+ != 0)
+ return "future";
+ if ((rs6000_isa_flags & (ISA_3_0_MASKS_SERVER & ~ISA_2_7_MASKS_SERVER)) != 0)
+ return "power9";
+ if ((rs6000_isa_flags & (ISA_2_7_MASKS_SERVER & ~ISA_2_6_MASKS_SERVER)) != 0)
+ return "power8";
+ if ((rs6000_isa_flags & (ISA_2_6_MASKS_SERVER & ~ISA_2_5_MASKS_SERVER)) != 0)
+ return "power7";
+ if ((rs6000_isa_flags & (ISA_2_5_MASKS_SERVER & ~ISA_2_4_MASKS)) != 0)
+ return "power6";
+ if ((rs6000_isa_flags & (ISA_2_4_MASKS & ~ISA_2_1_MASKS)) != 0)
+ return "power5";
+ if ((rs6000_isa_flags & ISA_2_1_MASKS) != 0)
+ return "power4";
+ if ((rs6000_isa_flags & OPTION_MASK_POWERPC64) != 0)
+ return "ppc64";
+ return "ppc";
+}
+
+void
+emit_asm_machine (void)
+{
+ fprintf (asm_out_file, "\t.machine %s\n", rs6000_machine);
+}
+#endif
+
/* Do anything needed at the start of the asm file. */
static void
@@ -5776,27 +5639,10 @@ rs6000_file_start (void)
}
#ifdef USING_ELFOS_H
+ rs6000_machine = rs6000_machine_from_flags ();
if (!(rs6000_default_cpu && rs6000_default_cpu[0])
&& !global_options_set.x_rs6000_cpu_index)
- {
- fputs ("\t.machine ", asm_out_file);
- if ((rs6000_isa_flags & OPTION_MASK_MODULO) != 0)
- fputs ("power9\n", asm_out_file);
- else if ((rs6000_isa_flags & OPTION_MASK_DIRECT_MOVE) != 0)
- fputs ("power8\n", asm_out_file);
- else if ((rs6000_isa_flags & OPTION_MASK_POPCNTD) != 0)
- fputs ("power7\n", asm_out_file);
- else if ((rs6000_isa_flags & OPTION_MASK_CMPB) != 0)
- fputs ("power6\n", asm_out_file);
- else if ((rs6000_isa_flags & OPTION_MASK_POPCNTB) != 0)
- fputs ("power5\n", asm_out_file);
- else if ((rs6000_isa_flags & OPTION_MASK_MFCRF) != 0)
- fputs ("power4\n", asm_out_file);
- else if ((rs6000_isa_flags & OPTION_MASK_POWERPC64) != 0)
- fputs ("ppc64\n", asm_out_file);
- else
- fputs ("ppc\n", asm_out_file);
- }
+ emit_asm_machine ();
#endif
if (DEFAULT_ABI == ABI_ELFv2)
@@ -7521,43 +7367,26 @@ gpr_or_gpr_p (rtx op0, rtx op1)
bool
direct_move_p (rtx op0, rtx op1)
{
- int regno0, regno1;
-
if (!REG_P (op0) || !REG_P (op1))
return false;
- if (!TARGET_DIRECT_MOVE && !TARGET_MFPGPR)
+ if (!TARGET_DIRECT_MOVE)
return false;
- regno0 = REGNO (op0);
- regno1 = REGNO (op1);
+ int regno0 = REGNO (op0);
+ int regno1 = REGNO (op1);
if (!HARD_REGISTER_NUM_P (regno0) || !HARD_REGISTER_NUM_P (regno1))
return false;
- if (INT_REGNO_P (regno0))
- return (TARGET_DIRECT_MOVE) ? VSX_REGNO_P (regno1) : FP_REGNO_P (regno1);
-
- else if (INT_REGNO_P (regno1))
- {
- if (TARGET_MFPGPR && FP_REGNO_P (regno0))
- return true;
+ if (INT_REGNO_P (regno0) && VSX_REGNO_P (regno1))
+ return true;
- else if (TARGET_DIRECT_MOVE && VSX_REGNO_P (regno0))
- return true;
- }
+ if (VSX_REGNO_P (regno0) && INT_REGNO_P (regno1))
+ return true;
return false;
}
-/* Return true if the OFFSET is valid for the quad address instructions that
- use d-form (register + offset) addressing. */
-
-static inline bool
-quad_address_offset_p (HOST_WIDE_INT offset)
-{
- return (IN_RANGE (offset, -32768, 32767) && ((offset) & 0xf) == 0);
-}
-
/* Return true if the ADDR is an acceptable address for a quad memory
operation of mode MODE (either LQ/STQ for general purpose registers, or
LXV/STXV for vector registers under ISA 3.0. GPR_P is true if this address
@@ -8525,7 +8354,7 @@ rs6000_tls_get_addr (void)
/* Construct the SYMBOL_REF for TLS GOT references. */
static GTY(()) rtx rs6000_got_symbol;
-static rtx
+rtx
rs6000_got_sym (void)
{
if (!rs6000_got_symbol)
@@ -9175,6 +9004,7 @@ rs6000_reassociation_width (unsigned int opc ATTRIBUTE_UNUSED,
{
case PROCESSOR_POWER8:
case PROCESSOR_POWER9:
+ case PROCESSOR_FUTURE:
if (DECIMAL_FLOAT_MODE_P (mode))
return 1;
if (VECTOR_MODE_P (mode))
@@ -11791,7 +11621,7 @@ rs6000_function_arg (cumulative_args_t cum_v, machine_mode mode,
{
warned = true;
inform (input_location,
- "the ABI of passing homogeneous float aggregates"
+ "the ABI of passing homogeneous %<float%> aggregates"
" has changed in GCC 5");
}
}
@@ -13227,7 +13057,7 @@ rs6000_expand_set_fpscr_drn_builtin (enum insn_code icode, tree exp)
/* Builtin not supported in 32-bit mode. */
fatal_error (input_location,
"%<__builtin_set_fpscr_drn%> is not supported "
- "in 32-bit mode.");
+ "in 32-bit mode");
if (rs6000_isa_flags & OPTION_MASK_SOFT_FLOAT)
{
@@ -14250,7 +14080,7 @@ rs6000_expand_ternop_builtin (enum insn_code icode, tree exp, rtx target)
if (TREE_CODE (arg2) != INTEGER_CST
|| wi::geu_p (wi::to_wide (arg2), 16))
{
- error ("argument 3 must be in the range 0..15");
+ error ("argument 3 must be in the range [0, 15]");
return CONST0_RTX (tmode);
}
}
@@ -14383,7 +14213,7 @@ get_element_number (tree vec_type, tree arg)
if (!tree_fits_uhwi_p (arg)
|| (elt = tree_to_uhwi (arg), elt > max))
{
- error ("selector must be an integer constant in the range 0..%wi", max);
+ error ("selector must be an integer constant in the range [0, %wi]", max);
return 0;
}
@@ -14703,7 +14533,7 @@ altivec_expand_builtin (tree exp, rtx target, bool *expandedp)
if (TREE_CODE (arg1) != INTEGER_CST || TREE_INT_CST_LOW (arg1) > 12)
{
- error ("second argument to %qs must be 0..12", "vec_vextract4b");
+ error ("second argument to %qs must be [0, 12]", "vec_vextract4b");
return expand_call (exp, target, false);
}
break;
@@ -14718,7 +14548,7 @@ altivec_expand_builtin (tree exp, rtx target, bool *expandedp)
if (TREE_CODE (arg2) != INTEGER_CST || TREE_INT_CST_LOW (arg2) > 12)
{
- error ("third argument to %qs must be 0..12", "vec_vinsert4b");
+ error ("third argument to %qs must be [0, 12]", "vec_vinsert4b");
return expand_call (exp, target, false);
}
break;
@@ -19126,12 +18956,6 @@ rs6000_secondary_reload_simple_move (enum rs6000_reg_type to_type,
return true;
}
- /* Power6+: MFTGPR or MFFGPR. */
- else if (TARGET_MFPGPR && TARGET_POWERPC64 && size == 8
- && ((to_type == GPR_REG_TYPE && from_type == FPR_REG_TYPE)
- || (to_type == FPR_REG_TYPE && from_type == GPR_REG_TYPE)))
- return true;
-
/* Move to/from SPR. */
else if ((size == 4 || (TARGET_POWERPC64 && size == 8))
&& ((to_type == GPR_REG_TYPE && from_type == SPR_REG_TYPE)
@@ -20487,19 +20311,6 @@ rs6000_got_register (rtx value ATTRIBUTE_UNUSED)
return pic_offset_table_rtx;
}
-static rs6000_stack_t stack_info;
-
-/* Function to init struct machine_function.
- This will be called, via a pointer variable,
- from push_function_context. */
-
-static struct machine_function *
-rs6000_init_machine_status (void)
-{
- stack_info.reload_completed = 0;
- return ggc_cleared_alloc<machine_function> ();
-}
-
#define INT_P(X) (CONST_INT_P (X) && GET_MODE (X) == VOIDmode)
/* Write out a function code label. */
@@ -20997,7 +20808,7 @@ print_operand (FILE *file, rtx x, int code)
{
const char *name = XSTR (x, 0);
#if TARGET_MACHO
- if (darwin_emit_branch_islands
+ if (darwin_picsymbol_stubs
&& MACHOPIC_INDIRECT
&& machopic_classify_symbol (x) == MACHOPIC_UNDEFINED_FUNCTION)
name = machopic_indirection_name (x, /*stub_p=*/true);
@@ -21126,6 +20937,30 @@ print_operand_address (FILE *file, rtx x)
{
if (REG_P (x))
fprintf (file, "0(%s)", reg_names[ REGNO (x) ]);
+
+ /* Is it a pc-relative address? */
+ else if (pcrel_address (x, Pmode))
+ {
+ HOST_WIDE_INT offset;
+
+ if (GET_CODE (x) == CONST)
+ x = XEXP (x, 0);
+
+ if (GET_CODE (x) == PLUS)
+ {
+ offset = INTVAL (XEXP (x, 1));
+ x = XEXP (x, 0);
+ }
+ else
+ offset = 0;
+
+ output_addr_const (file, x);
+
+ if (offset)
+ fprintf (file, "%+" PRId64, offset);
+
+ fputs ("@pcrel", file);
+ }
else if (SYMBOL_REF_P (x) || GET_CODE (x) == CONST
|| GET_CODE (x) == LABEL_REF)
{
@@ -21317,8 +21152,10 @@ rs6000_call_template_1 (rtx *operands, unsigned int funop, bool sibcall)
(DEFAULT_ABI == ABI_V4 && TARGET_SECURE_PLT && flag_pic == 2
? "+32768" : ""));
- static char str[32]; /* 2 spare */
- if (DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2)
+ static char str[32]; /* 1 spare */
+ if (rs6000_pcrel_p (cfun))
+ sprintf (str, "b%s %s@notoc%s", sibcall ? "" : "l", z, arg);
+ else if (DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2)
sprintf (str, "b%s %s%s%s", sibcall ? "" : "l", z, arg,
sibcall ? "" : "\n\tnop");
else if (DEFAULT_ABI == ABI_V4)
@@ -21383,6 +21220,16 @@ rs6000_indirect_call_template_1 (rtx *operands, unsigned int funop,
/* Currently, funop is either 0 or 1. The maximum string is always
a !speculate 64-bit __tls_get_addr call.
+ ABI_ELFv2, pcrel:
+ . 27 .reloc .,R_PPC64_TLSGD,%2\n\t
+ . 35 .reloc .,R_PPC64_PLTSEQ_NOTOC,%z1\n\t
+ . 9 crset 2\n\t
+ . 27 .reloc .,R_PPC64_TLSGD,%2\n\t
+ . 36 .reloc .,R_PPC64_PLTCALL_NOTOC,%z1\n\t
+ . 8 beq%T1l-
+ .---
+ .142
+
ABI_AIX:
. 9 ld 2,%3\n\t
. 27 .reloc .,R_PPC64_TLSGD,%2\n\t
@@ -21448,23 +21295,31 @@ rs6000_indirect_call_template_1 (rtx *operands, unsigned int funop,
gcc_unreachable ();
}
+ const char *notoc = rs6000_pcrel_p (cfun) ? "_NOTOC" : "";
const char *addend = (DEFAULT_ABI == ABI_V4 && TARGET_SECURE_PLT
&& flag_pic == 2 ? "+32768" : "");
if (!speculate)
{
s += sprintf (s,
- "%s.reloc .,R_PPC%s_PLTSEQ,%%z%u%s\n\t",
- tls, rel64, funop, addend);
+ "%s.reloc .,R_PPC%s_PLTSEQ%s,%%z%u%s\n\t",
+ tls, rel64, notoc, funop, addend);
s += sprintf (s, "crset 2\n\t");
}
s += sprintf (s,
- "%s.reloc .,R_PPC%s_PLTCALL,%%z%u%s\n\t",
- tls, rel64, funop, addend);
+ "%s.reloc .,R_PPC%s_PLTCALL%s,%%z%u%s\n\t",
+ tls, rel64, notoc, funop, addend);
}
else if (!speculate)
s += sprintf (s, "crset 2\n\t");
- if (DEFAULT_ABI == ABI_AIX)
+ if (rs6000_pcrel_p (cfun))
+ {
+ if (speculate)
+ sprintf (s, "b%%T%ul", funop);
+ else
+ sprintf (s, "beq%%T%ul-", funop);
+ }
+ else if (DEFAULT_ABI == ABI_AIX)
{
if (speculate)
sprintf (s,
@@ -21517,64 +21372,72 @@ rs6000_indirect_sibcall_template (rtx *operands, unsigned int funop)
}
#if HAVE_AS_PLTSEQ
-/* Output indirect call insns.
- WHICH is 0 for tocsave, 1 for plt16_ha, 2 for plt16_lo, 3 for mtctr. */
+/* Output indirect call insns. WHICH identifies the type of sequence. */
const char *
rs6000_pltseq_template (rtx *operands, int which)
{
const char *rel64 = TARGET_64BIT ? "64" : "";
- char tls[28];
+ char tls[30];
tls[0] = 0;
if (TARGET_TLS_MARKERS && GET_CODE (operands[3]) == UNSPEC)
{
+ char off = which == RS6000_PLTSEQ_PLT_PCREL34 ? '8' : '4';
if (XINT (operands[3], 1) == UNSPEC_TLSGD)
- sprintf (tls, ".reloc .,R_PPC%s_TLSGD,%%3\n\t",
- rel64);
+ sprintf (tls, ".reloc .-%c,R_PPC%s_TLSGD,%%3\n\t",
+ off, rel64);
else if (XINT (operands[3], 1) == UNSPEC_TLSLD)
- sprintf (tls, ".reloc .,R_PPC%s_TLSLD,%%&\n\t",
- rel64);
+ sprintf (tls, ".reloc .-%c,R_PPC%s_TLSLD,%%&\n\t",
+ off, rel64);
else
gcc_unreachable ();
}
gcc_assert (DEFAULT_ABI == ABI_ELFv2 || DEFAULT_ABI == ABI_V4);
- static char str[96]; /* 15 spare */
- const char *off = WORDS_BIG_ENDIAN ? "+2" : "";
+ static char str[96]; /* 10 spare */
+ char off = WORDS_BIG_ENDIAN ? '2' : '4';
const char *addend = (DEFAULT_ABI == ABI_V4 && TARGET_SECURE_PLT
&& flag_pic == 2 ? "+32768" : "");
switch (which)
{
- case 0:
+ case RS6000_PLTSEQ_TOCSAVE:
sprintf (str,
- "%s.reloc .,R_PPC%s_PLTSEQ,%%z2\n\t"
- "st%s",
- tls, rel64, TARGET_64BIT ? "d 2,24(1)" : "w 2,12(1)");
+ "st%s\n\t"
+ "%s.reloc .-4,R_PPC%s_PLTSEQ,%%z2",
+ TARGET_64BIT ? "d 2,24(1)" : "w 2,12(1)",
+ tls, rel64);
break;
- case 1:
+ case RS6000_PLTSEQ_PLT16_HA:
if (DEFAULT_ABI == ABI_V4 && !flag_pic)
sprintf (str,
- "%s.reloc .%s,R_PPC%s_PLT16_HA,%%z2\n\t"
- "lis %%0,0",
+ "lis %%0,0\n\t"
+ "%s.reloc .-%c,R_PPC%s_PLT16_HA,%%z2",
tls, off, rel64);
else
sprintf (str,
- "%s.reloc .%s,R_PPC%s_PLT16_HA,%%z2%s\n\t"
- "addis %%0,%%1,0",
+ "addis %%0,%%1,0\n\t"
+ "%s.reloc .-%c,R_PPC%s_PLT16_HA,%%z2%s",
tls, off, rel64, addend);
break;
- case 2:
+ case RS6000_PLTSEQ_PLT16_LO:
sprintf (str,
- "%s.reloc .%s,R_PPC%s_PLT16_LO%s,%%z2%s\n\t"
- "l%s %%0,0(%%1)",
- tls, off, rel64, TARGET_64BIT ? "_DS" : "", addend,
- TARGET_64BIT ? "d" : "wz");
+ "l%s %%0,0(%%1)\n\t"
+ "%s.reloc .-%c,R_PPC%s_PLT16_LO%s,%%z2%s",
+ TARGET_64BIT ? "d" : "wz",
+ tls, off, rel64, TARGET_64BIT ? "_DS" : "", addend);
break;
- case 3:
+ case RS6000_PLTSEQ_MTCTR:
sprintf (str,
- "%s.reloc .,R_PPC%s_PLTSEQ,%%z2%s\n\t"
- "mtctr %%1",
+ "mtctr %%1\n\t"
+ "%s.reloc .-4,R_PPC%s_PLTSEQ,%%z2%s",
tls, rel64, addend);
break;
+ case RS6000_PLTSEQ_PLT_PCREL34:
+ sprintf (str,
+ "pl%s %%0,0(0),1\n\t"
+ "%s.reloc .-8,R_PPC%s_PLT_PCREL34_NOTOC,%%z2",
+ TARGET_64BIT ? "d" : "wz",
+ tls, rel64);
+ break;
default:
gcc_unreachable ();
}
@@ -21582,6 +21445,71 @@ rs6000_pltseq_template (rtx *operands, int which)
}
#endif
+/* Helper function to return whether a MODE can do prefixed loads/stores.
+ VOIDmode is used when we are loading the pc-relative address into a base
+ register, but we are not using it as part of a memory operation. As modes
+ add support for prefixed memory, they will be added here. */
+
+static bool
+mode_supports_prefixed_address_p (machine_mode mode)
+{
+ return mode == VOIDmode;
+}
+
+/* Function to return true if ADDR is a valid prefixed memory address that uses
+ mode MODE. */
+
+bool
+rs6000_prefixed_address (rtx addr, machine_mode mode)
+{
+ if (!TARGET_PREFIXED_ADDR || !mode_supports_prefixed_address_p (mode))
+ return false;
+
+ /* Check for PC-relative addresses. */
+ if (pcrel_address (addr, Pmode))
+ return true;
+
+ /* Check for prefixed memory addresses that have a large numeric offset,
+ or an offset that can't be used for a DS/DQ-form memory operation. */
+ if (GET_CODE (addr) == PLUS)
+ {
+ rtx op0 = XEXP (addr, 0);
+ rtx op1 = XEXP (addr, 1);
+
+ if (!base_reg_operand (op0, Pmode) || !CONST_INT_P (op1))
+ return false;
+
+ HOST_WIDE_INT value = INTVAL (op1);
+ if (!SIGNED_34BIT_OFFSET_P (value, 0))
+ return false;
+
+ /* Offset larger than 16-bits? */
+ if (!SIGNED_16BIT_OFFSET_P (value, 0))
+ return true;
+
+ /* DQ instruction (bottom 4 bits must be 0) for vectors. */
+ HOST_WIDE_INT mask;
+ if (GET_MODE_SIZE (mode) >= 16)
+ mask = 15;
+
+ /* DS instruction (bottom 2 bits must be 0). For 32-bit integers, we
+ need to use DS instructions if we are sign-extending the value with
+ LWA. For 32-bit floating point, we need DS instructions to load and
+ store values to the traditional Altivec registers. */
+ else if (GET_MODE_SIZE (mode) >= 4)
+ mask = 3;
+
+ /* QImode/HImode has no restrictions. */
+ else
+ return true;
+
+ /* Return true if we must use a prefixed instruction. */
+ return (value & mask) != 0;
+ }
+
+ return false;
+}
+
#if defined (HAVE_GAS_HIDDEN) && !TARGET_MACHO
/* Emit an assembler directive to set symbol visibility for DECL to
VISIBILITY_TYPE. */
@@ -23765,1257 +23693,6 @@ rs6000_split_multireg_move (rtx dst, rtx src)
}
}
-
-/* This page contains routines that are used to determine what the
- function prologue and epilogue code will do and write them out. */
-
-/* Determine whether the REG is really used. */
-
-static bool
-save_reg_p (int reg)
-{
- if (reg == RS6000_PIC_OFFSET_TABLE_REGNUM && !TARGET_SINGLE_PIC_BASE)
- {
- /* When calling eh_return, we must return true for all the cases
- where conditional_register_usage marks the PIC offset reg
- call used or fixed. */
- if (crtl->calls_eh_return
- && ((DEFAULT_ABI == ABI_V4 && flag_pic)
- || (DEFAULT_ABI == ABI_DARWIN && flag_pic)
- || (TARGET_TOC && TARGET_MINIMAL_TOC)))
- return true;
-
- /* We need to mark the PIC offset register live for the same
- conditions as it is set up in rs6000_emit_prologue, or
- otherwise it won't be saved before we clobber it. */
- if (TARGET_TOC && TARGET_MINIMAL_TOC
- && !constant_pool_empty_p ())
- return true;
-
- if (DEFAULT_ABI == ABI_V4
- && (flag_pic == 1 || (flag_pic && TARGET_SECURE_PLT))
- && df_regs_ever_live_p (RS6000_PIC_OFFSET_TABLE_REGNUM))
- return true;
-
- if (DEFAULT_ABI == ABI_DARWIN
- && flag_pic && crtl->uses_pic_offset_table)
- return true;
- }
-
- return !call_used_regs[reg] && df_regs_ever_live_p (reg);
-}
-
-/* Return the first fixed-point register that is required to be
- saved. 32 if none. */
-
-int
-first_reg_to_save (void)
-{
- int first_reg;
-
- /* Find lowest numbered live register. */
- for (first_reg = 13; first_reg <= 31; first_reg++)
- if (save_reg_p (first_reg))
- break;
-
- return first_reg;
-}
-
-/* Similar, for FP regs. */
-
-int
-first_fp_reg_to_save (void)
-{
- int first_reg;
-
- /* Find lowest numbered live register. */
- for (first_reg = 14 + 32; first_reg <= 63; first_reg++)
- if (save_reg_p (first_reg))
- break;
-
- return first_reg;
-}
-
-/* Similar, for AltiVec regs. */
-
-static int
-first_altivec_reg_to_save (void)
-{
- int i;
-
- /* Stack frame remains as is unless we are in AltiVec ABI. */
- if (! TARGET_ALTIVEC_ABI)
- return LAST_ALTIVEC_REGNO + 1;
-
- /* On Darwin, the unwind routines are compiled without
- TARGET_ALTIVEC, and use save_world to save/restore the
- altivec registers when necessary. */
- if (DEFAULT_ABI == ABI_DARWIN && crtl->calls_eh_return
- && ! TARGET_ALTIVEC)
- return FIRST_ALTIVEC_REGNO + 20;
-
- /* Find lowest numbered live register. */
- for (i = FIRST_ALTIVEC_REGNO + 20; i <= LAST_ALTIVEC_REGNO; ++i)
- if (save_reg_p (i))
- break;
-
- return i;
-}
-
-/* Return a 32-bit mask of the AltiVec registers we need to set in
- VRSAVE. Bit n of the return value is 1 if Vn is live. The MSB in
- the 32-bit word is 0. */
-
-static unsigned int
-compute_vrsave_mask (void)
-{
- unsigned int i, mask = 0;
-
- /* On Darwin, the unwind routines are compiled without
- TARGET_ALTIVEC, and use save_world to save/restore the
- call-saved altivec registers when necessary. */
- if (DEFAULT_ABI == ABI_DARWIN && crtl->calls_eh_return
- && ! TARGET_ALTIVEC)
- mask |= 0xFFF;
-
- /* First, find out if we use _any_ altivec registers. */
- for (i = FIRST_ALTIVEC_REGNO; i <= LAST_ALTIVEC_REGNO; ++i)
- if (df_regs_ever_live_p (i))
- mask |= ALTIVEC_REG_BIT (i);
-
- if (mask == 0)
- return mask;
-
- /* Next, remove the argument registers from the set. These must
- be in the VRSAVE mask set by the caller, so we don't need to add
- them in again. More importantly, the mask we compute here is
- used to generate CLOBBERs in the set_vrsave insn, and we do not
- wish the argument registers to die. */
- for (i = ALTIVEC_ARG_MIN_REG; i < (unsigned) crtl->args.info.vregno; i++)
- mask &= ~ALTIVEC_REG_BIT (i);
-
- /* Similarly, remove the return value from the set. */
- {
- bool yes = false;
- diddle_return_value (is_altivec_return_reg, &yes);
- if (yes)
- mask &= ~ALTIVEC_REG_BIT (ALTIVEC_ARG_RETURN);
- }
-
- return mask;
-}
-
-/* For a very restricted set of circumstances, we can cut down the
- size of prologues/epilogues by calling our own save/restore-the-world
- routines. */
-
-static void
-compute_save_world_info (rs6000_stack_t *info)
-{
- info->world_save_p = 1;
- info->world_save_p
- = (WORLD_SAVE_P (info)
- && DEFAULT_ABI == ABI_DARWIN
- && !cfun->has_nonlocal_label
- && info->first_fp_reg_save == FIRST_SAVED_FP_REGNO
- && info->first_gp_reg_save == FIRST_SAVED_GP_REGNO
- && info->first_altivec_reg_save == FIRST_SAVED_ALTIVEC_REGNO
- && info->cr_save_p);
-
- /* This will not work in conjunction with sibcalls. Make sure there
- are none. (This check is expensive, but seldom executed.) */
- if (WORLD_SAVE_P (info))
- {
- rtx_insn *insn;
- for (insn = get_last_insn_anywhere (); insn; insn = PREV_INSN (insn))
- if (CALL_P (insn) && SIBLING_CALL_P (insn))
- {
- info->world_save_p = 0;
- break;
- }
- }
-
- if (WORLD_SAVE_P (info))
- {
- /* Even if we're not touching VRsave, make sure there's room on the
- stack for it, if it looks like we're calling SAVE_WORLD, which
- will attempt to save it. */
- info->vrsave_size = 4;
-
- /* If we are going to save the world, we need to save the link register too. */
- info->lr_save_p = 1;
-
- /* "Save" the VRsave register too if we're saving the world. */
- if (info->vrsave_mask == 0)
- info->vrsave_mask = compute_vrsave_mask ();
-
- /* Because the Darwin register save/restore routines only handle
- F14 .. F31 and V20 .. V31 as per the ABI, perform a consistency
- check. */
- gcc_assert (info->first_fp_reg_save >= FIRST_SAVED_FP_REGNO
- && (info->first_altivec_reg_save
- >= FIRST_SAVED_ALTIVEC_REGNO));
- }
-
- return;
-}
-
-
-static void
-is_altivec_return_reg (rtx reg, void *xyes)
-{
- bool *yes = (bool *) xyes;
- if (REGNO (reg) == ALTIVEC_ARG_RETURN)
- *yes = true;
-}
-
-
-/* Return whether REG is a global user reg or has been specifed by
- -ffixed-REG. We should not restore these, and so cannot use
- lmw or out-of-line restore functions if there are any. We also
- can't save them (well, emit frame notes for them), because frame
- unwinding during exception handling will restore saved registers. */
-
-static bool
-fixed_reg_p (int reg)
-{
- /* Ignore fixed_regs[RS6000_PIC_OFFSET_TABLE_REGNUM] when the
- backend sets it, overriding anything the user might have given. */
- if (reg == RS6000_PIC_OFFSET_TABLE_REGNUM
- && ((DEFAULT_ABI == ABI_V4 && flag_pic)
- || (DEFAULT_ABI == ABI_DARWIN && flag_pic)
- || (TARGET_TOC && TARGET_MINIMAL_TOC)))
- return false;
-
- return fixed_regs[reg];
-}
-
-/* Determine the strategy for savings/restoring registers. */
-
-enum {
- SAVE_MULTIPLE = 0x1,
- SAVE_INLINE_GPRS = 0x2,
- SAVE_INLINE_FPRS = 0x4,
- SAVE_NOINLINE_GPRS_SAVES_LR = 0x8,
- SAVE_NOINLINE_FPRS_SAVES_LR = 0x10,
- SAVE_INLINE_VRS = 0x20,
- REST_MULTIPLE = 0x100,
- REST_INLINE_GPRS = 0x200,
- REST_INLINE_FPRS = 0x400,
- REST_NOINLINE_FPRS_DOESNT_RESTORE_LR = 0x800,
- REST_INLINE_VRS = 0x1000
-};
-
-static int
-rs6000_savres_strategy (rs6000_stack_t *info,
- bool using_static_chain_p)
-{
- int strategy = 0;
-
- /* Select between in-line and out-of-line save and restore of regs.
- First, all the obvious cases where we don't use out-of-line. */
- if (crtl->calls_eh_return
- || cfun->machine->ra_need_lr)
- strategy |= (SAVE_INLINE_FPRS | REST_INLINE_FPRS
- | SAVE_INLINE_GPRS | REST_INLINE_GPRS
- | SAVE_INLINE_VRS | REST_INLINE_VRS);
-
- if (info->first_gp_reg_save == 32)
- strategy |= SAVE_INLINE_GPRS | REST_INLINE_GPRS;
-
- if (info->first_fp_reg_save == 64)
- strategy |= SAVE_INLINE_FPRS | REST_INLINE_FPRS;
-
- if (info->first_altivec_reg_save == LAST_ALTIVEC_REGNO + 1)
- strategy |= SAVE_INLINE_VRS | REST_INLINE_VRS;
-
- /* Define cutoff for using out-of-line functions to save registers. */
- if (DEFAULT_ABI == ABI_V4 || TARGET_ELF)
- {
- if (!optimize_size)
- {
- strategy |= SAVE_INLINE_FPRS | REST_INLINE_FPRS;
- strategy |= SAVE_INLINE_GPRS | REST_INLINE_GPRS;
- strategy |= SAVE_INLINE_VRS | REST_INLINE_VRS;
- }
- else
- {
- /* Prefer out-of-line restore if it will exit. */
- if (info->first_fp_reg_save > 61)
- strategy |= SAVE_INLINE_FPRS;
- if (info->first_gp_reg_save > 29)
- {
- if (info->first_fp_reg_save == 64)
- strategy |= SAVE_INLINE_GPRS;
- else
- strategy |= SAVE_INLINE_GPRS | REST_INLINE_GPRS;
- }
- if (info->first_altivec_reg_save == LAST_ALTIVEC_REGNO)
- strategy |= SAVE_INLINE_VRS | REST_INLINE_VRS;
- }
- }
- else if (DEFAULT_ABI == ABI_DARWIN)
- {
- if (info->first_fp_reg_save > 60)
- strategy |= SAVE_INLINE_FPRS | REST_INLINE_FPRS;
- if (info->first_gp_reg_save > 29)
- strategy |= SAVE_INLINE_GPRS | REST_INLINE_GPRS;
- strategy |= SAVE_INLINE_VRS | REST_INLINE_VRS;
- }
- else
- {
- gcc_checking_assert (DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2);
- if ((flag_shrink_wrap_separate && optimize_function_for_speed_p (cfun))
- || info->first_fp_reg_save > 61)
- strategy |= SAVE_INLINE_FPRS | REST_INLINE_FPRS;
- strategy |= SAVE_INLINE_GPRS | REST_INLINE_GPRS;
- strategy |= SAVE_INLINE_VRS | REST_INLINE_VRS;
- }
-
- /* Don't bother to try to save things out-of-line if r11 is occupied
- by the static chain. It would require too much fiddling and the
- static chain is rarely used anyway. FPRs are saved w.r.t the stack
- pointer on Darwin, and AIX uses r1 or r12. */
- if (using_static_chain_p
- && (DEFAULT_ABI == ABI_V4 || DEFAULT_ABI == ABI_DARWIN))
- strategy |= ((DEFAULT_ABI == ABI_DARWIN ? 0 : SAVE_INLINE_FPRS)
- | SAVE_INLINE_GPRS
- | SAVE_INLINE_VRS);
-
- /* Don't ever restore fixed regs. That means we can't use the
- out-of-line register restore functions if a fixed reg is in the
- range of regs restored. */
- if (!(strategy & REST_INLINE_FPRS))
- for (int i = info->first_fp_reg_save; i < 64; i++)
- if (fixed_regs[i])
- {
- strategy |= REST_INLINE_FPRS;
- break;
- }
-
- /* We can only use the out-of-line routines to restore fprs if we've
- saved all the registers from first_fp_reg_save in the prologue.
- Otherwise, we risk loading garbage. Of course, if we have saved
- out-of-line then we know we haven't skipped any fprs. */
- if ((strategy & SAVE_INLINE_FPRS)
- && !(strategy & REST_INLINE_FPRS))
- for (int i = info->first_fp_reg_save; i < 64; i++)
- if (!save_reg_p (i))
- {
- strategy |= REST_INLINE_FPRS;
- break;
- }
-
- /* Similarly, for altivec regs. */
- if (!(strategy & REST_INLINE_VRS))
- for (int i = info->first_altivec_reg_save; i < LAST_ALTIVEC_REGNO + 1; i++)
- if (fixed_regs[i])
- {
- strategy |= REST_INLINE_VRS;
- break;
- }
-
- if ((strategy & SAVE_INLINE_VRS)
- && !(strategy & REST_INLINE_VRS))
- for (int i = info->first_altivec_reg_save; i < LAST_ALTIVEC_REGNO + 1; i++)
- if (!save_reg_p (i))
- {
- strategy |= REST_INLINE_VRS;
- break;
- }
-
- /* info->lr_save_p isn't yet set if the only reason lr needs to be
- saved is an out-of-line save or restore. Set up the value for
- the next test (excluding out-of-line gprs). */
- bool lr_save_p = (info->lr_save_p
- || !(strategy & SAVE_INLINE_FPRS)
- || !(strategy & SAVE_INLINE_VRS)
- || !(strategy & REST_INLINE_FPRS)
- || !(strategy & REST_INLINE_VRS));
-
- if (TARGET_MULTIPLE
- && !TARGET_POWERPC64
- && info->first_gp_reg_save < 31
- && !(flag_shrink_wrap
- && flag_shrink_wrap_separate
- && optimize_function_for_speed_p (cfun)))
- {
- int count = 0;
- for (int i = info->first_gp_reg_save; i < 32; i++)
- if (save_reg_p (i))
- count++;
-
- if (count <= 1)
- /* Don't use store multiple if only one reg needs to be
- saved. This can occur for example when the ABI_V4 pic reg
- (r30) needs to be saved to make calls, but r31 is not
- used. */
- strategy |= SAVE_INLINE_GPRS | REST_INLINE_GPRS;
- else
- {
- /* Prefer store multiple for saves over out-of-line
- routines, since the store-multiple instruction will
- always be smaller. */
- strategy |= SAVE_INLINE_GPRS | SAVE_MULTIPLE;
-
- /* The situation is more complicated with load multiple.
- We'd prefer to use the out-of-line routines for restores,
- since the "exit" out-of-line routines can handle the
- restore of LR and the frame teardown. However if doesn't
- make sense to use the out-of-line routine if that is the
- only reason we'd need to save LR, and we can't use the
- "exit" out-of-line gpr restore if we have saved some
- fprs; In those cases it is advantageous to use load
- multiple when available. */
- if (info->first_fp_reg_save != 64 || !lr_save_p)
- strategy |= REST_INLINE_GPRS | REST_MULTIPLE;
- }
- }
-
- /* Using the "exit" out-of-line routine does not improve code size
- if using it would require lr to be saved and if only saving one
- or two gprs. */
- else if (!lr_save_p && info->first_gp_reg_save > 29)
- strategy |= SAVE_INLINE_GPRS | REST_INLINE_GPRS;
-
- /* Don't ever restore fixed regs. */
- if ((strategy & (REST_INLINE_GPRS | REST_MULTIPLE)) != REST_INLINE_GPRS)
- for (int i = info->first_gp_reg_save; i < 32; i++)
- if (fixed_reg_p (i))
- {
- strategy |= REST_INLINE_GPRS;
- strategy &= ~REST_MULTIPLE;
- break;
- }
-
- /* We can only use load multiple or the out-of-line routines to
- restore gprs if we've saved all the registers from
- first_gp_reg_save. Otherwise, we risk loading garbage.
- Of course, if we have saved out-of-line or used stmw then we know
- we haven't skipped any gprs. */
- if ((strategy & (SAVE_INLINE_GPRS | SAVE_MULTIPLE)) == SAVE_INLINE_GPRS
- && (strategy & (REST_INLINE_GPRS | REST_MULTIPLE)) != REST_INLINE_GPRS)
- for (int i = info->first_gp_reg_save; i < 32; i++)
- if (!save_reg_p (i))
- {
- strategy |= REST_INLINE_GPRS;
- strategy &= ~REST_MULTIPLE;
- break;
- }
-
- if (TARGET_ELF && TARGET_64BIT)
- {
- if (!(strategy & SAVE_INLINE_FPRS))
- strategy |= SAVE_NOINLINE_FPRS_SAVES_LR;
- else if (!(strategy & SAVE_INLINE_GPRS)
- && info->first_fp_reg_save == 64)
- strategy |= SAVE_NOINLINE_GPRS_SAVES_LR;
- }
- else if (TARGET_AIX && !(strategy & REST_INLINE_FPRS))
- strategy |= REST_NOINLINE_FPRS_DOESNT_RESTORE_LR;
-
- if (TARGET_MACHO && !(strategy & SAVE_INLINE_FPRS))
- strategy |= SAVE_NOINLINE_FPRS_SAVES_LR;
-
- return strategy;
-}
-
-/* Calculate the stack information for the current function. This is
- complicated by having two separate calling sequences, the AIX calling
- sequence and the V.4 calling sequence.
-
- AIX (and Darwin/Mac OS X) stack frames look like:
- 32-bit 64-bit
- SP----> +---------------------------------------+
- | back chain to caller | 0 0
- +---------------------------------------+
- | saved CR | 4 8 (8-11)
- +---------------------------------------+
- | saved LR | 8 16
- +---------------------------------------+
- | reserved for compilers | 12 24
- +---------------------------------------+
- | reserved for binders | 16 32
- +---------------------------------------+
- | saved TOC pointer | 20 40
- +---------------------------------------+
- | Parameter save area (+padding*) (P) | 24 48
- +---------------------------------------+
- | Alloca space (A) | 24+P etc.
- +---------------------------------------+
- | Local variable space (L) | 24+P+A
- +---------------------------------------+
- | Float/int conversion temporary (X) | 24+P+A+L
- +---------------------------------------+
- | Save area for AltiVec registers (W) | 24+P+A+L+X
- +---------------------------------------+
- | AltiVec alignment padding (Y) | 24+P+A+L+X+W
- +---------------------------------------+
- | Save area for VRSAVE register (Z) | 24+P+A+L+X+W+Y
- +---------------------------------------+
- | Save area for GP registers (G) | 24+P+A+X+L+X+W+Y+Z
- +---------------------------------------+
- | Save area for FP registers (F) | 24+P+A+X+L+X+W+Y+Z+G
- +---------------------------------------+
- old SP->| back chain to caller's caller |
- +---------------------------------------+
-
- * If the alloca area is present, the parameter save area is
- padded so that the former starts 16-byte aligned.
-
- The required alignment for AIX configurations is two words (i.e., 8
- or 16 bytes).
-
- The ELFv2 ABI is a variant of the AIX ABI. Stack frames look like:
-
- SP----> +---------------------------------------+
- | Back chain to caller | 0
- +---------------------------------------+
- | Save area for CR | 8
- +---------------------------------------+
- | Saved LR | 16
- +---------------------------------------+
- | Saved TOC pointer | 24
- +---------------------------------------+
- | Parameter save area (+padding*) (P) | 32
- +---------------------------------------+
- | Alloca space (A) | 32+P
- +---------------------------------------+
- | Local variable space (L) | 32+P+A
- +---------------------------------------+
- | Save area for AltiVec registers (W) | 32+P+A+L
- +---------------------------------------+
- | AltiVec alignment padding (Y) | 32+P+A+L+W
- +---------------------------------------+
- | Save area for GP registers (G) | 32+P+A+L+W+Y
- +---------------------------------------+
- | Save area for FP registers (F) | 32+P+A+L+W+Y+G
- +---------------------------------------+
- old SP->| back chain to caller's caller | 32+P+A+L+W+Y+G+F
- +---------------------------------------+
-
- * If the alloca area is present, the parameter save area is
- padded so that the former starts 16-byte aligned.
-
- V.4 stack frames look like:
-
- SP----> +---------------------------------------+
- | back chain to caller | 0
- +---------------------------------------+
- | caller's saved LR | 4
- +---------------------------------------+
- | Parameter save area (+padding*) (P) | 8
- +---------------------------------------+
- | Alloca space (A) | 8+P
- +---------------------------------------+
- | Varargs save area (V) | 8+P+A
- +---------------------------------------+
- | Local variable space (L) | 8+P+A+V
- +---------------------------------------+
- | Float/int conversion temporary (X) | 8+P+A+V+L
- +---------------------------------------+
- | Save area for AltiVec registers (W) | 8+P+A+V+L+X
- +---------------------------------------+
- | AltiVec alignment padding (Y) | 8+P+A+V+L+X+W
- +---------------------------------------+
- | Save area for VRSAVE register (Z) | 8+P+A+V+L+X+W+Y
- +---------------------------------------+
- | saved CR (C) | 8+P+A+V+L+X+W+Y+Z
- +---------------------------------------+
- | Save area for GP registers (G) | 8+P+A+V+L+X+W+Y+Z+C
- +---------------------------------------+
- | Save area for FP registers (F) | 8+P+A+V+L+X+W+Y+Z+C+G
- +---------------------------------------+
- old SP->| back chain to caller's caller |
- +---------------------------------------+
-
- * If the alloca area is present and the required alignment is
- 16 bytes, the parameter save area is padded so that the
- alloca area starts 16-byte aligned.
-
- The required alignment for V.4 is 16 bytes, or 8 bytes if -meabi is
- given. (But note below and in sysv4.h that we require only 8 and
- may round up the size of our stack frame anyways. The historical
- reason is early versions of powerpc-linux which didn't properly
- align the stack at program startup. A happy side-effect is that
- -mno-eabi libraries can be used with -meabi programs.)
-
- The EABI configuration defaults to the V.4 layout. However,
- the stack alignment requirements may differ. If -mno-eabi is not
- given, the required stack alignment is 8 bytes; if -mno-eabi is
- given, the required alignment is 16 bytes. (But see V.4 comment
- above.) */
-
-#ifndef ABI_STACK_BOUNDARY
-#define ABI_STACK_BOUNDARY STACK_BOUNDARY
-#endif
-
-static rs6000_stack_t *
-rs6000_stack_info (void)
-{
- /* We should never be called for thunks, we are not set up for that. */
- gcc_assert (!cfun->is_thunk);
-
- rs6000_stack_t *info = &stack_info;
- int reg_size = TARGET_32BIT ? 4 : 8;
- int ehrd_size;
- int ehcr_size;
- int save_align;
- int first_gp;
- HOST_WIDE_INT non_fixed_size;
- bool using_static_chain_p;
-
- if (reload_completed && info->reload_completed)
- return info;
-
- memset (info, 0, sizeof (*info));
- info->reload_completed = reload_completed;
-
- /* Select which calling sequence. */
- info->abi = DEFAULT_ABI;
-
- /* Calculate which registers need to be saved & save area size. */
- info->first_gp_reg_save = first_reg_to_save ();
- /* Assume that we will have to save RS6000_PIC_OFFSET_TABLE_REGNUM,
- even if it currently looks like we won't. Reload may need it to
- get at a constant; if so, it will have already created a constant
- pool entry for it. */
- if (((TARGET_TOC && TARGET_MINIMAL_TOC)
- || (flag_pic == 1 && DEFAULT_ABI == ABI_V4)
- || (flag_pic && DEFAULT_ABI == ABI_DARWIN))
- && crtl->uses_const_pool
- && info->first_gp_reg_save > RS6000_PIC_OFFSET_TABLE_REGNUM)
- first_gp = RS6000_PIC_OFFSET_TABLE_REGNUM;
- else
- first_gp = info->first_gp_reg_save;
-
- info->gp_size = reg_size * (32 - first_gp);
-
- info->first_fp_reg_save = first_fp_reg_to_save ();
- info->fp_size = 8 * (64 - info->first_fp_reg_save);
-
- info->first_altivec_reg_save = first_altivec_reg_to_save ();
- info->altivec_size = 16 * (LAST_ALTIVEC_REGNO + 1
- - info->first_altivec_reg_save);
-
- /* Does this function call anything? */
- info->calls_p = (!crtl->is_leaf || cfun->machine->ra_needs_full_frame);
-
- /* Determine if we need to save the condition code registers. */
- if (save_reg_p (CR2_REGNO)
- || save_reg_p (CR3_REGNO)
- || save_reg_p (CR4_REGNO))
- {
- info->cr_save_p = 1;
- if (DEFAULT_ABI == ABI_V4)
- info->cr_size = reg_size;
- }
-
- /* If the current function calls __builtin_eh_return, then we need
- to allocate stack space for registers that will hold data for
- the exception handler. */
- if (crtl->calls_eh_return)
- {
- unsigned int i;
- for (i = 0; EH_RETURN_DATA_REGNO (i) != INVALID_REGNUM; ++i)
- continue;
-
- ehrd_size = i * UNITS_PER_WORD;
- }
- else
- ehrd_size = 0;
-
- /* In the ELFv2 ABI, we also need to allocate space for separate
- CR field save areas if the function calls __builtin_eh_return. */
- if (DEFAULT_ABI == ABI_ELFv2 && crtl->calls_eh_return)
- {
- /* This hard-codes that we have three call-saved CR fields. */
- ehcr_size = 3 * reg_size;
- /* We do *not* use the regular CR save mechanism. */
- info->cr_save_p = 0;
- }
- else
- ehcr_size = 0;
-
- /* Determine various sizes. */
- info->reg_size = reg_size;
- info->fixed_size = RS6000_SAVE_AREA;
- info->vars_size = RS6000_ALIGN (get_frame_size (), 8);
- if (cfun->calls_alloca)
- info->parm_size =
- RS6000_ALIGN (crtl->outgoing_args_size + info->fixed_size,
- STACK_BOUNDARY / BITS_PER_UNIT) - info->fixed_size;
- else
- info->parm_size = RS6000_ALIGN (crtl->outgoing_args_size,
- TARGET_ALTIVEC ? 16 : 8);
- if (FRAME_GROWS_DOWNWARD)
- info->vars_size
- += RS6000_ALIGN (info->fixed_size + info->vars_size + info->parm_size,
- ABI_STACK_BOUNDARY / BITS_PER_UNIT)
- - (info->fixed_size + info->vars_size + info->parm_size);
-
- if (TARGET_ALTIVEC_ABI)
- info->vrsave_mask = compute_vrsave_mask ();
-
- if (TARGET_ALTIVEC_VRSAVE && info->vrsave_mask)
- info->vrsave_size = 4;
-
- compute_save_world_info (info);
-
- /* Calculate the offsets. */
- switch (DEFAULT_ABI)
- {
- case ABI_NONE:
- default:
- gcc_unreachable ();
-
- case ABI_AIX:
- case ABI_ELFv2:
- case ABI_DARWIN:
- info->fp_save_offset = -info->fp_size;
- info->gp_save_offset = info->fp_save_offset - info->gp_size;
-
- if (TARGET_ALTIVEC_ABI)
- {
- info->vrsave_save_offset = info->gp_save_offset - info->vrsave_size;
-
- /* Align stack so vector save area is on a quadword boundary.
- The padding goes above the vectors. */
- if (info->altivec_size != 0)
- info->altivec_padding_size = info->vrsave_save_offset & 0xF;
-
- info->altivec_save_offset = info->vrsave_save_offset
- - info->altivec_padding_size
- - info->altivec_size;
- gcc_assert (info->altivec_size == 0
- || info->altivec_save_offset % 16 == 0);
-
- /* Adjust for AltiVec case. */
- info->ehrd_offset = info->altivec_save_offset - ehrd_size;
- }
- else
- info->ehrd_offset = info->gp_save_offset - ehrd_size;
-
- info->ehcr_offset = info->ehrd_offset - ehcr_size;
- info->cr_save_offset = reg_size; /* first word when 64-bit. */
- info->lr_save_offset = 2*reg_size;
- break;
-
- case ABI_V4:
- info->fp_save_offset = -info->fp_size;
- info->gp_save_offset = info->fp_save_offset - info->gp_size;
- info->cr_save_offset = info->gp_save_offset - info->cr_size;
-
- if (TARGET_ALTIVEC_ABI)
- {
- info->vrsave_save_offset = info->cr_save_offset - info->vrsave_size;
-
- /* Align stack so vector save area is on a quadword boundary. */
- if (info->altivec_size != 0)
- info->altivec_padding_size = 16 - (-info->vrsave_save_offset % 16);
-
- info->altivec_save_offset = info->vrsave_save_offset
- - info->altivec_padding_size
- - info->altivec_size;
-
- /* Adjust for AltiVec case. */
- info->ehrd_offset = info->altivec_save_offset;
- }
- else
- info->ehrd_offset = info->cr_save_offset;
-
- info->ehrd_offset -= ehrd_size;
- info->lr_save_offset = reg_size;
- }
-
- save_align = (TARGET_ALTIVEC_ABI || DEFAULT_ABI == ABI_DARWIN) ? 16 : 8;
- info->save_size = RS6000_ALIGN (info->fp_size
- + info->gp_size
- + info->altivec_size
- + info->altivec_padding_size
- + ehrd_size
- + ehcr_size
- + info->cr_size
- + info->vrsave_size,
- save_align);
-
- non_fixed_size = info->vars_size + info->parm_size + info->save_size;
-
- info->total_size = RS6000_ALIGN (non_fixed_size + info->fixed_size,
- ABI_STACK_BOUNDARY / BITS_PER_UNIT);
-
- /* Determine if we need to save the link register. */
- if (info->calls_p
- || ((DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2)
- && crtl->profile
- && !TARGET_PROFILE_KERNEL)
- || (DEFAULT_ABI == ABI_V4 && cfun->calls_alloca)
-#ifdef TARGET_RELOCATABLE
- || (DEFAULT_ABI == ABI_V4
- && (TARGET_RELOCATABLE || flag_pic > 1)
- && !constant_pool_empty_p ())
-#endif
- || rs6000_ra_ever_killed ())
- info->lr_save_p = 1;
-
- using_static_chain_p = (cfun->static_chain_decl != NULL_TREE
- && df_regs_ever_live_p (STATIC_CHAIN_REGNUM)
- && call_used_regs[STATIC_CHAIN_REGNUM]);
- info->savres_strategy = rs6000_savres_strategy (info, using_static_chain_p);
-
- if (!(info->savres_strategy & SAVE_INLINE_GPRS)
- || !(info->savres_strategy & SAVE_INLINE_FPRS)
- || !(info->savres_strategy & SAVE_INLINE_VRS)
- || !(info->savres_strategy & REST_INLINE_GPRS)
- || !(info->savres_strategy & REST_INLINE_FPRS)
- || !(info->savres_strategy & REST_INLINE_VRS))
- info->lr_save_p = 1;
-
- if (info->lr_save_p)
- df_set_regs_ever_live (LR_REGNO, true);
-
- /* Determine if we need to allocate any stack frame:
-
- For AIX we need to push the stack if a frame pointer is needed
- (because the stack might be dynamically adjusted), if we are
- debugging, if we make calls, or if the sum of fp_save, gp_save,
- and local variables are more than the space needed to save all
- non-volatile registers: 32-bit: 18*8 + 19*4 = 220 or 64-bit: 18*8
- + 18*8 = 288 (GPR13 reserved).
-
- For V.4 we don't have the stack cushion that AIX uses, but assume
- that the debugger can handle stackless frames. */
-
- if (info->calls_p)
- info->push_p = 1;
-
- else if (DEFAULT_ABI == ABI_V4)
- info->push_p = non_fixed_size != 0;
-
- else if (frame_pointer_needed)
- info->push_p = 1;
-
- else if (TARGET_XCOFF && write_symbols != NO_DEBUG)
- info->push_p = 1;
-
- else
- info->push_p = non_fixed_size > (TARGET_32BIT ? 220 : 288);
-
- return info;
-}
-
-static void
-debug_stack_info (rs6000_stack_t *info)
-{
- const char *abi_string;
-
- if (! info)
- info = rs6000_stack_info ();
-
- fprintf (stderr, "\nStack information for function %s:\n",
- ((current_function_decl && DECL_NAME (current_function_decl))
- ? IDENTIFIER_POINTER (DECL_NAME (current_function_decl))
- : "<unknown>"));
-
- switch (info->abi)
- {
- default: abi_string = "Unknown"; break;
- case ABI_NONE: abi_string = "NONE"; break;
- case ABI_AIX: abi_string = "AIX"; break;
- case ABI_ELFv2: abi_string = "ELFv2"; break;
- case ABI_DARWIN: abi_string = "Darwin"; break;
- case ABI_V4: abi_string = "V.4"; break;
- }
-
- fprintf (stderr, "\tABI = %5s\n", abi_string);
-
- if (TARGET_ALTIVEC_ABI)
- fprintf (stderr, "\tALTIVEC ABI extensions enabled.\n");
-
- if (info->first_gp_reg_save != 32)
- fprintf (stderr, "\tfirst_gp_reg_save = %5d\n", info->first_gp_reg_save);
-
- if (info->first_fp_reg_save != 64)
- fprintf (stderr, "\tfirst_fp_reg_save = %5d\n", info->first_fp_reg_save);
-
- if (info->first_altivec_reg_save <= LAST_ALTIVEC_REGNO)
- fprintf (stderr, "\tfirst_altivec_reg_save = %5d\n",
- info->first_altivec_reg_save);
-
- if (info->lr_save_p)
- fprintf (stderr, "\tlr_save_p = %5d\n", info->lr_save_p);
-
- if (info->cr_save_p)
- fprintf (stderr, "\tcr_save_p = %5d\n", info->cr_save_p);
-
- if (info->vrsave_mask)
- fprintf (stderr, "\tvrsave_mask = 0x%x\n", info->vrsave_mask);
-
- if (info->push_p)
- fprintf (stderr, "\tpush_p = %5d\n", info->push_p);
-
- if (info->calls_p)
- fprintf (stderr, "\tcalls_p = %5d\n", info->calls_p);
-
- if (info->gp_size)
- fprintf (stderr, "\tgp_save_offset = %5d\n", info->gp_save_offset);
-
- if (info->fp_size)
- fprintf (stderr, "\tfp_save_offset = %5d\n", info->fp_save_offset);
-
- if (info->altivec_size)
- fprintf (stderr, "\taltivec_save_offset = %5d\n",
- info->altivec_save_offset);
-
- if (info->vrsave_size)
- fprintf (stderr, "\tvrsave_save_offset = %5d\n",
- info->vrsave_save_offset);
-
- if (info->lr_save_p)
- fprintf (stderr, "\tlr_save_offset = %5d\n", info->lr_save_offset);
-
- if (info->cr_save_p)
- fprintf (stderr, "\tcr_save_offset = %5d\n", info->cr_save_offset);
-
- if (info->varargs_save_offset)
- fprintf (stderr, "\tvarargs_save_offset = %5d\n", info->varargs_save_offset);
-
- if (info->total_size)
- fprintf (stderr, "\ttotal_size = " HOST_WIDE_INT_PRINT_DEC"\n",
- info->total_size);
-
- if (info->vars_size)
- fprintf (stderr, "\tvars_size = " HOST_WIDE_INT_PRINT_DEC"\n",
- info->vars_size);
-
- if (info->parm_size)
- fprintf (stderr, "\tparm_size = %5d\n", info->parm_size);
-
- if (info->fixed_size)
- fprintf (stderr, "\tfixed_size = %5d\n", info->fixed_size);
-
- if (info->gp_size)
- fprintf (stderr, "\tgp_size = %5d\n", info->gp_size);
-
- if (info->fp_size)
- fprintf (stderr, "\tfp_size = %5d\n", info->fp_size);
-
- if (info->altivec_size)
- fprintf (stderr, "\taltivec_size = %5d\n", info->altivec_size);
-
- if (info->vrsave_size)
- fprintf (stderr, "\tvrsave_size = %5d\n", info->vrsave_size);
-
- if (info->altivec_padding_size)
- fprintf (stderr, "\taltivec_padding_size= %5d\n",
- info->altivec_padding_size);
-
- if (info->cr_size)
- fprintf (stderr, "\tcr_size = %5d\n", info->cr_size);
-
- if (info->save_size)
- fprintf (stderr, "\tsave_size = %5d\n", info->save_size);
-
- if (info->reg_size != 4)
- fprintf (stderr, "\treg_size = %5d\n", info->reg_size);
-
- fprintf (stderr, "\tsave-strategy = %04x\n", info->savres_strategy);
-
- fprintf (stderr, "\n");
-}
-
-rtx
-rs6000_return_addr (int count, rtx frame)
-{
- /* We can't use get_hard_reg_initial_val for LR when count == 0 if LR
- is trashed by the prologue, as it is for PIC on ABI_V4 and Darwin. */
- if (count != 0
- || ((DEFAULT_ABI == ABI_V4 || DEFAULT_ABI == ABI_DARWIN) && flag_pic))
- {
- cfun->machine->ra_needs_full_frame = 1;
-
- if (count == 0)
- /* FRAME is set to frame_pointer_rtx by the generic code, but that
- is good for loading 0(r1) only when !FRAME_GROWS_DOWNWARD. */
- frame = stack_pointer_rtx;
- rtx prev_frame_addr = memory_address (Pmode, frame);
- rtx prev_frame = copy_to_reg (gen_rtx_MEM (Pmode, prev_frame_addr));
- rtx lr_save_off = plus_constant (Pmode,
- prev_frame, RETURN_ADDRESS_OFFSET);
- rtx lr_save_addr = memory_address (Pmode, lr_save_off);
- return gen_rtx_MEM (Pmode, lr_save_addr);
- }
-
- cfun->machine->ra_need_lr = 1;
- return get_hard_reg_initial_val (Pmode, LR_REGNO);
-}
-
-/* Say whether a function is a candidate for sibcall handling or not. */
-
-static bool
-rs6000_function_ok_for_sibcall (tree decl, tree exp)
-{
- tree fntype;
-
- /* The sibcall epilogue may clobber the static chain register.
- ??? We could work harder and avoid that, but it's probably
- not worth the hassle in practice. */
- if (CALL_EXPR_STATIC_CHAIN (exp))
- return false;
-
- if (decl)
- fntype = TREE_TYPE (decl);
- else
- fntype = TREE_TYPE (TREE_TYPE (CALL_EXPR_FN (exp)));
-
- /* We can't do it if the called function has more vector parameters
- than the current function; there's nowhere to put the VRsave code. */
- if (TARGET_ALTIVEC_ABI
- && TARGET_ALTIVEC_VRSAVE
- && !(decl && decl == current_function_decl))
- {
- function_args_iterator args_iter;
- tree type;
- int nvreg = 0;
-
- /* Functions with vector parameters are required to have a
- prototype, so the argument type info must be available
- here. */
- FOREACH_FUNCTION_ARGS(fntype, type, args_iter)
- if (TREE_CODE (type) == VECTOR_TYPE
- && ALTIVEC_OR_VSX_VECTOR_MODE (TYPE_MODE (type)))
- nvreg++;
-
- FOREACH_FUNCTION_ARGS(TREE_TYPE (current_function_decl), type, args_iter)
- if (TREE_CODE (type) == VECTOR_TYPE
- && ALTIVEC_OR_VSX_VECTOR_MODE (TYPE_MODE (type)))
- nvreg--;
-
- if (nvreg > 0)
- return false;
- }
-
- /* Under the AIX or ELFv2 ABIs we can't allow calls to non-local
- functions, because the callee may have a different TOC pointer to
- the caller and there's no way to ensure we restore the TOC when
- we return. With the secure-plt SYSV ABI we can't make non-local
- calls when -fpic/PIC because the plt call stubs use r30. */
- if (DEFAULT_ABI == ABI_DARWIN
- || ((DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2)
- && decl
- && !DECL_EXTERNAL (decl)
- && !DECL_WEAK (decl)
- && (*targetm.binds_local_p) (decl))
- || (DEFAULT_ABI == ABI_V4
- && (!TARGET_SECURE_PLT
- || !flag_pic
- || (decl
- && (*targetm.binds_local_p) (decl)))))
- {
- tree attr_list = TYPE_ATTRIBUTES (fntype);
-
- if (!lookup_attribute ("longcall", attr_list)
- || lookup_attribute ("shortcall", attr_list))
- return true;
- }
-
- return false;
-}
-
-static int
-rs6000_ra_ever_killed (void)
-{
- rtx_insn *top;
- rtx reg;
- rtx_insn *insn;
-
- if (cfun->is_thunk)
- return 0;
-
- if (cfun->machine->lr_save_state)
- return cfun->machine->lr_save_state - 1;
-
- /* regs_ever_live has LR marked as used if any sibcalls are present,
- but this should not force saving and restoring in the
- pro/epilogue. Likewise, reg_set_between_p thinks a sibcall
- clobbers LR, so that is inappropriate. */
-
- /* Also, the prologue can generate a store into LR that
- doesn't really count, like this:
-
- move LR->R0
- bcl to set PIC register
- move LR->R31
- move R0->LR
-
- When we're called from the epilogue, we need to avoid counting
- this as a store. */
-
- push_topmost_sequence ();
- top = get_insns ();
- pop_topmost_sequence ();
- reg = gen_rtx_REG (Pmode, LR_REGNO);
-
- for (insn = NEXT_INSN (top); insn != NULL_RTX; insn = NEXT_INSN (insn))
- {
- if (INSN_P (insn))
- {
- if (CALL_P (insn))
- {
- if (!SIBLING_CALL_P (insn))
- return 1;
- }
- else if (find_regno_note (insn, REG_INC, LR_REGNO))
- return 1;
- else if (set_of (reg, insn) != NULL_RTX
- && !prologue_epilogue_contains (insn))
- return 1;
- }
- }
- return 0;
-}
-
-/* Emit instructions needed to load the TOC register.
- This is only needed when TARGET_TOC, TARGET_MINIMAL_TOC, and there is
- a constant pool; or for SVR4 -fpic. */
-
-void
-rs6000_emit_load_toc_table (int fromprolog)
-{
- rtx dest;
- dest = gen_rtx_REG (Pmode, RS6000_PIC_OFFSET_TABLE_REGNUM);
-
- if (TARGET_ELF && TARGET_SECURE_PLT && DEFAULT_ABI == ABI_V4 && flag_pic)
- {
- char buf[30];
- rtx lab, tmp1, tmp2, got;
-
- lab = gen_label_rtx ();
- ASM_GENERATE_INTERNAL_LABEL (buf, "L", CODE_LABEL_NUMBER (lab));
- lab = gen_rtx_SYMBOL_REF (Pmode, ggc_strdup (buf));
- if (flag_pic == 2)
- {
- got = gen_rtx_SYMBOL_REF (Pmode, ggc_strdup (toc_label_name));
- need_toc_init = 1;
- }
- else
- got = rs6000_got_sym ();
- tmp1 = tmp2 = dest;
- if (!fromprolog)
- {
- tmp1 = gen_reg_rtx (Pmode);
- tmp2 = gen_reg_rtx (Pmode);
- }
- emit_insn (gen_load_toc_v4_PIC_1 (lab));
- emit_move_insn (tmp1, gen_rtx_REG (Pmode, LR_REGNO));
- emit_insn (gen_load_toc_v4_PIC_3b (tmp2, tmp1, got, lab));
- emit_insn (gen_load_toc_v4_PIC_3c (dest, tmp2, got, lab));
- }
- else if (TARGET_ELF && DEFAULT_ABI == ABI_V4 && flag_pic == 1)
- {
- emit_insn (gen_load_toc_v4_pic_si ());
- emit_move_insn (dest, gen_rtx_REG (Pmode, LR_REGNO));
- }
- else if (TARGET_ELF && DEFAULT_ABI == ABI_V4 && flag_pic == 2)
- {
- char buf[30];
- rtx temp0 = (fromprolog
- ? gen_rtx_REG (Pmode, 0)
- : gen_reg_rtx (Pmode));
-
- if (fromprolog)
- {
- rtx symF, symL;
-
- ASM_GENERATE_INTERNAL_LABEL (buf, "LCF", rs6000_pic_labelno);
- symF = gen_rtx_SYMBOL_REF (Pmode, ggc_strdup (buf));
-
- ASM_GENERATE_INTERNAL_LABEL (buf, "LCL", rs6000_pic_labelno);
- symL = gen_rtx_SYMBOL_REF (Pmode, ggc_strdup (buf));
-
- emit_insn (gen_load_toc_v4_PIC_1 (symF));
- emit_move_insn (dest, gen_rtx_REG (Pmode, LR_REGNO));
- emit_insn (gen_load_toc_v4_PIC_2 (temp0, dest, symL, symF));
- }
- else
- {
- rtx tocsym, lab;
-
- tocsym = gen_rtx_SYMBOL_REF (Pmode, ggc_strdup (toc_label_name));
- need_toc_init = 1;
- lab = gen_label_rtx ();
- emit_insn (gen_load_toc_v4_PIC_1b (tocsym, lab));
- emit_move_insn (dest, gen_rtx_REG (Pmode, LR_REGNO));
- if (TARGET_LINK_STACK)
- emit_insn (gen_addsi3 (dest, dest, GEN_INT (4)));
- emit_move_insn (temp0, gen_rtx_MEM (Pmode, dest));
- }
- emit_insn (gen_addsi3 (dest, temp0, dest));
- }
- else if (TARGET_ELF && !TARGET_AIX && flag_pic == 0 && TARGET_MINIMAL_TOC)
- {
- /* This is for AIX code running in non-PIC ELF32. */
- rtx realsym = gen_rtx_SYMBOL_REF (Pmode, ggc_strdup (toc_label_name));
-
- need_toc_init = 1;
- emit_insn (gen_elf_high (dest, realsym));
- emit_insn (gen_elf_low (dest, dest, realsym));
- }
- else
- {
- gcc_assert (DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2);
-
- if (TARGET_32BIT)
- emit_insn (gen_load_toc_aix_si (dest));
- else
- emit_insn (gen_load_toc_aix_di (dest));
- }
-}
-
-/* Emit instructions to restore the link register after determining where
- its value has been stored. */
-
-void
-rs6000_emit_eh_reg_restore (rtx source, rtx scratch)
-{
- rs6000_stack_t *info = rs6000_stack_info ();
- rtx operands[2];
-
- operands[0] = source;
- operands[1] = scratch;
-
- if (info->lr_save_p)
- {
- rtx frame_rtx = stack_pointer_rtx;
- HOST_WIDE_INT sp_offset = 0;
- rtx tmp;
-
- if (frame_pointer_needed
- || cfun->calls_alloca
- || info->total_size > 32767)
- {
- tmp = gen_frame_mem (Pmode, frame_rtx);
- emit_move_insn (operands[1], tmp);
- frame_rtx = operands[1];
- }
- else if (info->push_p)
- sp_offset = info->total_size;
-
- tmp = plus_constant (Pmode, frame_rtx,
- info->lr_save_offset + sp_offset);
- tmp = gen_frame_mem (Pmode, tmp);
- emit_move_insn (tmp, operands[0]);
- }
- else
- emit_move_insn (gen_rtx_REG (Pmode, LR_REGNO), operands[0]);
-
- /* Freeze lr_save_p. We've just emitted rtl that depends on the
- state of lr_save_p so any change from here on would be a bug. In
- particular, stop rs6000_ra_ever_killed from considering the SET
- of lr we may have added just above. */
- cfun->machine->lr_save_state = info->lr_save_p + 1;
-}
-
static GTY(()) alias_set_type set = -1;
alias_set_type
@@ -25026,4105 +23703,6 @@ get_TOC_alias_set (void)
return set;
}
-/* This returns nonzero if the current function uses the TOC. This is
- determined by the presence of (use (unspec ... UNSPEC_TOC)), which
- is generated by the ABI_V4 load_toc_* patterns.
- Return 2 instead of 1 if the load_toc_* pattern is in the function
- partition that doesn't start the function. */
-#if TARGET_ELF
-static int
-uses_TOC (void)
-{
- rtx_insn *insn;
- int ret = 1;
-
- for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
- {
- if (INSN_P (insn))
- {
- rtx pat = PATTERN (insn);
- int i;
-
- if (GET_CODE (pat) == PARALLEL)
- for (i = 0; i < XVECLEN (pat, 0); i++)
- {
- rtx sub = XVECEXP (pat, 0, i);
- if (GET_CODE (sub) == USE)
- {
- sub = XEXP (sub, 0);
- if (GET_CODE (sub) == UNSPEC
- && XINT (sub, 1) == UNSPEC_TOC)
- return ret;
- }
- }
- }
- else if (crtl->has_bb_partition
- && NOTE_P (insn)
- && NOTE_KIND (insn) == NOTE_INSN_SWITCH_TEXT_SECTIONS)
- ret = 2;
- }
- return 0;
-}
-#endif
-
-rtx
-create_TOC_reference (rtx symbol, rtx largetoc_reg)
-{
- rtx tocrel, tocreg, hi;
-
- if (TARGET_DEBUG_ADDR)
- {
- if (SYMBOL_REF_P (symbol))
- fprintf (stderr, "\ncreate_TOC_reference, (symbol_ref %s)\n",
- XSTR (symbol, 0));
- else
- {
- fprintf (stderr, "\ncreate_TOC_reference, code %s:\n",
- GET_RTX_NAME (GET_CODE (symbol)));
- debug_rtx (symbol);
- }
- }
-
- if (!can_create_pseudo_p ())
- df_set_regs_ever_live (TOC_REGISTER, true);
-
- tocreg = gen_rtx_REG (Pmode, TOC_REGISTER);
- tocrel = gen_rtx_UNSPEC (Pmode, gen_rtvec (2, symbol, tocreg), UNSPEC_TOCREL);
- if (TARGET_CMODEL == CMODEL_SMALL || can_create_pseudo_p ())
- return tocrel;
-
- hi = gen_rtx_HIGH (Pmode, copy_rtx (tocrel));
- if (largetoc_reg != NULL)
- {
- emit_move_insn (largetoc_reg, hi);
- hi = largetoc_reg;
- }
- return gen_rtx_LO_SUM (Pmode, hi, tocrel);
-}
-
-/* Issue assembly directives that create a reference to the given DWARF
- FRAME_TABLE_LABEL from the current function section. */
-void
-rs6000_aix_asm_output_dwarf_table_ref (char * frame_table_label)
-{
- fprintf (asm_out_file, "\t.ref %s\n",
- (* targetm.strip_name_encoding) (frame_table_label));
-}
-
-/* This ties together stack memory (MEM with an alias set of frame_alias_set)
- and the change to the stack pointer. */
-
-static void
-rs6000_emit_stack_tie (rtx fp, bool hard_frame_needed)
-{
- rtvec p;
- int i;
- rtx regs[3];
-
- i = 0;
- regs[i++] = gen_rtx_REG (Pmode, STACK_POINTER_REGNUM);
- if (hard_frame_needed)
- regs[i++] = gen_rtx_REG (Pmode, HARD_FRAME_POINTER_REGNUM);
- if (!(REGNO (fp) == STACK_POINTER_REGNUM
- || (hard_frame_needed
- && REGNO (fp) == HARD_FRAME_POINTER_REGNUM)))
- regs[i++] = fp;
-
- p = rtvec_alloc (i);
- while (--i >= 0)
- {
- rtx mem = gen_frame_mem (BLKmode, regs[i]);
- RTVEC_ELT (p, i) = gen_rtx_SET (mem, const0_rtx);
- }
-
- emit_insn (gen_stack_tie (gen_rtx_PARALLEL (VOIDmode, p)));
-}
-
-/* Allocate SIZE_INT bytes on the stack using a store with update style insn
- and set the appropriate attributes for the generated insn. Return the
- first insn which adjusts the stack pointer or the last insn before
- the stack adjustment loop.
-
- SIZE_INT is used to create the CFI note for the allocation.
-
- SIZE_RTX is an rtx containing the size of the adjustment. Note that
- since stacks grow to lower addresses its runtime value is -SIZE_INT.
-
- ORIG_SP contains the backchain value that must be stored at *sp. */
-
-static rtx_insn *
-rs6000_emit_allocate_stack_1 (HOST_WIDE_INT size_int, rtx orig_sp)
-{
- rtx_insn *insn;
-
- rtx size_rtx = GEN_INT (-size_int);
- if (size_int > 32767)
- {
- rtx tmp_reg = gen_rtx_REG (Pmode, 0);
- /* Need a note here so that try_split doesn't get confused. */
- if (get_last_insn () == NULL_RTX)
- emit_note (NOTE_INSN_DELETED);
- insn = emit_move_insn (tmp_reg, size_rtx);
- try_split (PATTERN (insn), insn, 0);
- size_rtx = tmp_reg;
- }
-
- if (TARGET_32BIT)
- insn = emit_insn (gen_movsi_update_stack (stack_pointer_rtx,
- stack_pointer_rtx,
- size_rtx,
- orig_sp));
- else
- insn = emit_insn (gen_movdi_update_stack (stack_pointer_rtx,
- stack_pointer_rtx,
- size_rtx,
- orig_sp));
- rtx par = PATTERN (insn);
- gcc_assert (GET_CODE (par) == PARALLEL);
- rtx set = XVECEXP (par, 0, 0);
- gcc_assert (GET_CODE (set) == SET);
- rtx mem = SET_DEST (set);
- gcc_assert (MEM_P (mem));
- MEM_NOTRAP_P (mem) = 1;
- set_mem_alias_set (mem, get_frame_alias_set ());
-
- RTX_FRAME_RELATED_P (insn) = 1;
- add_reg_note (insn, REG_FRAME_RELATED_EXPR,
- gen_rtx_SET (stack_pointer_rtx,
- gen_rtx_PLUS (Pmode,
- stack_pointer_rtx,
- GEN_INT (-size_int))));
-
- /* Emit a blockage to ensure the allocation/probing insns are
- not optimized, combined, removed, etc. Add REG_STACK_CHECK
- note for similar reasons. */
- if (flag_stack_clash_protection)
- {
- add_reg_note (insn, REG_STACK_CHECK, const0_rtx);
- emit_insn (gen_blockage ());
- }
-
- return insn;
-}
-
-static HOST_WIDE_INT
-get_stack_clash_protection_probe_interval (void)
-{
- return (HOST_WIDE_INT_1U
- << PARAM_VALUE (PARAM_STACK_CLASH_PROTECTION_PROBE_INTERVAL));
-}
-
-static HOST_WIDE_INT
-get_stack_clash_protection_guard_size (void)
-{
- return (HOST_WIDE_INT_1U
- << PARAM_VALUE (PARAM_STACK_CLASH_PROTECTION_GUARD_SIZE));
-}
-
-/* Allocate ORIG_SIZE bytes on the stack and probe the newly
- allocated space every STACK_CLASH_PROTECTION_PROBE_INTERVAL bytes.
-
- COPY_REG, if non-null, should contain a copy of the original
- stack pointer at exit from this function.
-
- This is subtly different than the Ada probing in that it tries hard to
- prevent attacks that jump the stack guard. Thus it is never allowed to
- allocate more than STACK_CLASH_PROTECTION_PROBE_INTERVAL bytes of stack
- space without a suitable probe. */
-static rtx_insn *
-rs6000_emit_probe_stack_range_stack_clash (HOST_WIDE_INT orig_size,
- rtx copy_reg)
-{
- rtx orig_sp = copy_reg;
-
- HOST_WIDE_INT probe_interval = get_stack_clash_protection_probe_interval ();
-
- /* Round the size down to a multiple of PROBE_INTERVAL. */
- HOST_WIDE_INT rounded_size = ROUND_DOWN (orig_size, probe_interval);
-
- /* If explicitly requested,
- or the rounded size is not the same as the original size
- or the the rounded size is greater than a page,
- then we will need a copy of the original stack pointer. */
- if (rounded_size != orig_size
- || rounded_size > probe_interval
- || copy_reg)
- {
- /* If the caller did not request a copy of the incoming stack
- pointer, then we use r0 to hold the copy. */
- if (!copy_reg)
- orig_sp = gen_rtx_REG (Pmode, 0);
- emit_move_insn (orig_sp, stack_pointer_rtx);
- }
-
- /* There's three cases here.
-
- One is a single probe which is the most common and most efficiently
- implemented as it does not have to have a copy of the original
- stack pointer if there are no residuals.
-
- Second is unrolled allocation/probes which we use if there's just
- a few of them. It needs to save the original stack pointer into a
- temporary for use as a source register in the allocation/probe.
-
- Last is a loop. This is the most uncommon case and least efficient. */
- rtx_insn *retval = NULL;
- if (rounded_size == probe_interval)
- {
- retval = rs6000_emit_allocate_stack_1 (probe_interval, stack_pointer_rtx);
-
- dump_stack_clash_frame_info (PROBE_INLINE, rounded_size != orig_size);
- }
- else if (rounded_size <= 8 * probe_interval)
- {
- /* The ABI requires using the store with update insns to allocate
- space and store the backchain into the stack
-
- So we save the current stack pointer into a temporary, then
- emit the store-with-update insns to store the saved stack pointer
- into the right location in each new page. */
- for (int i = 0; i < rounded_size; i += probe_interval)
- {
- rtx_insn *insn
- = rs6000_emit_allocate_stack_1 (probe_interval, orig_sp);
-
- /* Save the first stack adjustment in RETVAL. */
- if (i == 0)
- retval = insn;
- }
-
- dump_stack_clash_frame_info (PROBE_INLINE, rounded_size != orig_size);
- }
- else
- {
- /* Compute the ending address. */
- rtx end_addr
- = copy_reg ? gen_rtx_REG (Pmode, 0) : gen_rtx_REG (Pmode, 12);
- rtx rs = GEN_INT (-rounded_size);
- rtx_insn *insn;
- if (add_operand (rs, Pmode))
- insn = emit_insn (gen_add3_insn (end_addr, stack_pointer_rtx, rs));
- else
- {
- emit_move_insn (end_addr, GEN_INT (-rounded_size));
- insn = emit_insn (gen_add3_insn (end_addr, end_addr,
- stack_pointer_rtx));
- /* Describe the effect of INSN to the CFI engine. */
- add_reg_note (insn, REG_FRAME_RELATED_EXPR,
- gen_rtx_SET (end_addr,
- gen_rtx_PLUS (Pmode, stack_pointer_rtx,
- rs)));
- }
- RTX_FRAME_RELATED_P (insn) = 1;
-
- /* Emit the loop. */
- if (TARGET_64BIT)
- retval = emit_insn (gen_probe_stack_rangedi (stack_pointer_rtx,
- stack_pointer_rtx, orig_sp,
- end_addr));
- else
- retval = emit_insn (gen_probe_stack_rangesi (stack_pointer_rtx,
- stack_pointer_rtx, orig_sp,
- end_addr));
- RTX_FRAME_RELATED_P (retval) = 1;
- /* Describe the effect of INSN to the CFI engine. */
- add_reg_note (retval, REG_FRAME_RELATED_EXPR,
- gen_rtx_SET (stack_pointer_rtx, end_addr));
-
- /* Emit a blockage to ensure the allocation/probing insns are
- not optimized, combined, removed, etc. Other cases handle this
- within their call to rs6000_emit_allocate_stack_1. */
- emit_insn (gen_blockage ());
-
- dump_stack_clash_frame_info (PROBE_LOOP, rounded_size != orig_size);
- }
-
- if (orig_size != rounded_size)
- {
- /* Allocate (and implicitly probe) any residual space. */
- HOST_WIDE_INT residual = orig_size - rounded_size;
-
- rtx_insn *insn = rs6000_emit_allocate_stack_1 (residual, orig_sp);
-
- /* If the residual was the only allocation, then we can return the
- allocating insn. */
- if (!retval)
- retval = insn;
- }
-
- return retval;
-}
-
-/* Emit the correct code for allocating stack space, as insns.
- If COPY_REG, make sure a copy of the old frame is left there.
- The generated code may use hard register 0 as a temporary. */
-
-static rtx_insn *
-rs6000_emit_allocate_stack (HOST_WIDE_INT size, rtx copy_reg, int copy_off)
-{
- rtx_insn *insn;
- rtx stack_reg = gen_rtx_REG (Pmode, STACK_POINTER_REGNUM);
- rtx tmp_reg = gen_rtx_REG (Pmode, 0);
- rtx todec = gen_int_mode (-size, Pmode);
-
- if (INTVAL (todec) != -size)
- {
- warning (0, "stack frame too large");
- emit_insn (gen_trap ());
- return 0;
- }
-
- if (crtl->limit_stack)
- {
- if (REG_P (stack_limit_rtx)
- && REGNO (stack_limit_rtx) > 1
- && REGNO (stack_limit_rtx) <= 31)
- {
- rtx_insn *insn
- = gen_add3_insn (tmp_reg, stack_limit_rtx, GEN_INT (size));
- gcc_assert (insn);
- emit_insn (insn);
- emit_insn (gen_cond_trap (LTU, stack_reg, tmp_reg, const0_rtx));
- }
- else if (SYMBOL_REF_P (stack_limit_rtx)
- && TARGET_32BIT
- && DEFAULT_ABI == ABI_V4
- && !flag_pic)
- {
- rtx toload = gen_rtx_CONST (VOIDmode,
- gen_rtx_PLUS (Pmode,
- stack_limit_rtx,
- GEN_INT (size)));
-
- emit_insn (gen_elf_high (tmp_reg, toload));
- emit_insn (gen_elf_low (tmp_reg, tmp_reg, toload));
- emit_insn (gen_cond_trap (LTU, stack_reg, tmp_reg,
- const0_rtx));
- }
- else
- warning (0, "stack limit expression is not supported");
- }
-
- if (flag_stack_clash_protection)
- {
- if (size < get_stack_clash_protection_guard_size ())
- dump_stack_clash_frame_info (NO_PROBE_SMALL_FRAME, true);
- else
- {
- rtx_insn *insn = rs6000_emit_probe_stack_range_stack_clash (size,
- copy_reg);
-
- /* If we asked for a copy with an offset, then we still need add in
- the offset. */
- if (copy_reg && copy_off)
- emit_insn (gen_add3_insn (copy_reg, copy_reg, GEN_INT (copy_off)));
- return insn;
- }
- }
-
- if (copy_reg)
- {
- if (copy_off != 0)
- emit_insn (gen_add3_insn (copy_reg, stack_reg, GEN_INT (copy_off)));
- else
- emit_move_insn (copy_reg, stack_reg);
- }
-
- /* Since we didn't use gen_frame_mem to generate the MEM, grab
- it now and set the alias set/attributes. The above gen_*_update
- calls will generate a PARALLEL with the MEM set being the first
- operation. */
- insn = rs6000_emit_allocate_stack_1 (size, stack_reg);
- return insn;
-}
-
-#define PROBE_INTERVAL (1 << STACK_CHECK_PROBE_INTERVAL_EXP)
-
-#if PROBE_INTERVAL > 32768
-#error Cannot use indexed addressing mode for stack probing
-#endif
-
-/* Emit code to probe a range of stack addresses from FIRST to FIRST+SIZE,
- inclusive. These are offsets from the current stack pointer. */
-
-static void
-rs6000_emit_probe_stack_range (HOST_WIDE_INT first, HOST_WIDE_INT size)
-{
- /* See if we have a constant small number of probes to generate. If so,
- that's the easy case. */
- if (first + size <= 32768)
- {
- HOST_WIDE_INT i;
-
- /* Probe at FIRST + N * PROBE_INTERVAL for values of N from 1 until
- it exceeds SIZE. If only one probe is needed, this will not
- generate any code. Then probe at FIRST + SIZE. */
- for (i = PROBE_INTERVAL; i < size; i += PROBE_INTERVAL)
- emit_stack_probe (plus_constant (Pmode, stack_pointer_rtx,
- -(first + i)));
-
- emit_stack_probe (plus_constant (Pmode, stack_pointer_rtx,
- -(first + size)));
- }
-
- /* Otherwise, do the same as above, but in a loop. Note that we must be
- extra careful with variables wrapping around because we might be at
- the very top (or the very bottom) of the address space and we have
- to be able to handle this case properly; in particular, we use an
- equality test for the loop condition. */
- else
- {
- HOST_WIDE_INT rounded_size;
- rtx r12 = gen_rtx_REG (Pmode, 12);
- rtx r0 = gen_rtx_REG (Pmode, 0);
-
- /* Sanity check for the addressing mode we're going to use. */
- gcc_assert (first <= 32768);
-
- /* Step 1: round SIZE to the previous multiple of the interval. */
-
- rounded_size = ROUND_DOWN (size, PROBE_INTERVAL);
-
-
- /* Step 2: compute initial and final value of the loop counter. */
-
- /* TEST_ADDR = SP + FIRST. */
- emit_insn (gen_rtx_SET (r12, plus_constant (Pmode, stack_pointer_rtx,
- -first)));
-
- /* LAST_ADDR = SP + FIRST + ROUNDED_SIZE. */
- if (rounded_size > 32768)
- {
- emit_move_insn (r0, GEN_INT (-rounded_size));
- emit_insn (gen_rtx_SET (r0, gen_rtx_PLUS (Pmode, r12, r0)));
- }
- else
- emit_insn (gen_rtx_SET (r0, plus_constant (Pmode, r12,
- -rounded_size)));
-
-
- /* Step 3: the loop
-
- do
- {
- TEST_ADDR = TEST_ADDR + PROBE_INTERVAL
- probe at TEST_ADDR
- }
- while (TEST_ADDR != LAST_ADDR)
-
- probes at FIRST + N * PROBE_INTERVAL for values of N from 1
- until it is equal to ROUNDED_SIZE. */
-
- if (TARGET_64BIT)
- emit_insn (gen_probe_stack_rangedi (r12, r12, stack_pointer_rtx, r0));
- else
- emit_insn (gen_probe_stack_rangesi (r12, r12, stack_pointer_rtx, r0));
-
-
- /* Step 4: probe at FIRST + SIZE if we cannot assert at compile-time
- that SIZE is equal to ROUNDED_SIZE. */
-
- if (size != rounded_size)
- emit_stack_probe (plus_constant (Pmode, r12, rounded_size - size));
- }
-}
-
-/* Probe a range of stack addresses from REG1 to REG2 inclusive. These are
- addresses, not offsets. */
-
-static const char *
-output_probe_stack_range_1 (rtx reg1, rtx reg2)
-{
- static int labelno = 0;
- char loop_lab[32];
- rtx xops[2];
-
- ASM_GENERATE_INTERNAL_LABEL (loop_lab, "LPSRL", labelno++);
-
- /* Loop. */
- ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, loop_lab);
-
- /* TEST_ADDR = TEST_ADDR + PROBE_INTERVAL. */
- xops[0] = reg1;
- xops[1] = GEN_INT (-PROBE_INTERVAL);
- output_asm_insn ("addi %0,%0,%1", xops);
-
- /* Probe at TEST_ADDR. */
- xops[1] = gen_rtx_REG (Pmode, 0);
- output_asm_insn ("stw %1,0(%0)", xops);
-
- /* Test if TEST_ADDR == LAST_ADDR. */
- xops[1] = reg2;
- if (TARGET_64BIT)
- output_asm_insn ("cmpd 0,%0,%1", xops);
- else
- output_asm_insn ("cmpw 0,%0,%1", xops);
-
- /* Branch. */
- fputs ("\tbne 0,", asm_out_file);
- assemble_name_raw (asm_out_file, loop_lab);
- fputc ('\n', asm_out_file);
-
- return "";
-}
-
-/* This function is called when rs6000_frame_related is processing
- SETs within a PARALLEL, and returns whether the REGNO save ought to
- be marked RTX_FRAME_RELATED_P. The PARALLELs involved are those
- for out-of-line register save functions, store multiple, and the
- Darwin world_save. They may contain registers that don't really
- need saving. */
-
-static bool
-interesting_frame_related_regno (unsigned int regno)
-{
- /* Saves apparently of r0 are actually saving LR. It doesn't make
- sense to substitute the regno here to test save_reg_p (LR_REGNO).
- We *know* LR needs saving, and dwarf2cfi.c is able to deduce that
- (set (mem) (r0)) is saving LR from a prior (set (r0) (lr)) marked
- as frame related. */
- if (regno == 0)
- return true;
- /* If we see CR2 then we are here on a Darwin world save. Saves of
- CR2 signify the whole CR is being saved. This is a long-standing
- ABI wart fixed by ELFv2. As for r0/lr there is no need to check
- that CR needs to be saved. */
- if (regno == CR2_REGNO)
- return true;
- /* Omit frame info for any user-defined global regs. If frame info
- is supplied for them, frame unwinding will restore a user reg.
- Also omit frame info for any reg we don't need to save, as that
- bloats frame info and can cause problems with shrink wrapping.
- Since global regs won't be seen as needing to be saved, both of
- these conditions are covered by save_reg_p. */
- return save_reg_p (regno);
-}
-
-/* Probe a range of stack addresses from REG1 to REG3 inclusive. These are
- addresses, not offsets.
-
- REG2 contains the backchain that must be stored into *sp at each allocation.
-
- This is subtly different than the Ada probing above in that it tries hard
- to prevent attacks that jump the stack guard. Thus, it is never allowed
- to allocate more than PROBE_INTERVAL bytes of stack space without a
- suitable probe. */
-
-static const char *
-output_probe_stack_range_stack_clash (rtx reg1, rtx reg2, rtx reg3)
-{
- static int labelno = 0;
- char loop_lab[32];
- rtx xops[3];
-
- HOST_WIDE_INT probe_interval = get_stack_clash_protection_probe_interval ();
-
- ASM_GENERATE_INTERNAL_LABEL (loop_lab, "LPSRL", labelno++);
-
- ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, loop_lab);
-
- /* This allocates and probes. */
- xops[0] = reg1;
- xops[1] = reg2;
- xops[2] = GEN_INT (-probe_interval);
- if (TARGET_64BIT)
- output_asm_insn ("stdu %1,%2(%0)", xops);
- else
- output_asm_insn ("stwu %1,%2(%0)", xops);
-
- /* Jump to LOOP_LAB if TEST_ADDR != LAST_ADDR. */
- xops[0] = reg1;
- xops[1] = reg3;
- if (TARGET_64BIT)
- output_asm_insn ("cmpd 0,%0,%1", xops);
- else
- output_asm_insn ("cmpw 0,%0,%1", xops);
-
- fputs ("\tbne 0,", asm_out_file);
- assemble_name_raw (asm_out_file, loop_lab);
- fputc ('\n', asm_out_file);
-
- return "";
-}
-
-/* Wrapper around the output_probe_stack_range routines. */
-const char *
-output_probe_stack_range (rtx reg1, rtx reg2, rtx reg3)
-{
- if (flag_stack_clash_protection)
- return output_probe_stack_range_stack_clash (reg1, reg2, reg3);
- else
- return output_probe_stack_range_1 (reg1, reg3);
-}
-
-/* Add to 'insn' a note which is PATTERN (INSN) but with REG replaced
- with (plus:P (reg 1) VAL), and with REG2 replaced with REPL2 if REG2
- is not NULL. It would be nice if dwarf2out_frame_debug_expr could
- deduce these equivalences by itself so it wasn't necessary to hold
- its hand so much. Don't be tempted to always supply d2_f_d_e with
- the actual cfa register, ie. r31 when we are using a hard frame
- pointer. That fails when saving regs off r1, and sched moves the
- r31 setup past the reg saves. */
-
-static rtx_insn *
-rs6000_frame_related (rtx_insn *insn, rtx reg, HOST_WIDE_INT val,
- rtx reg2, rtx repl2)
-{
- rtx repl;
-
- if (REGNO (reg) == STACK_POINTER_REGNUM)
- {
- gcc_checking_assert (val == 0);
- repl = NULL_RTX;
- }
- else
- repl = gen_rtx_PLUS (Pmode, gen_rtx_REG (Pmode, STACK_POINTER_REGNUM),
- GEN_INT (val));
-
- rtx pat = PATTERN (insn);
- if (!repl && !reg2)
- {
- /* No need for any replacement. Just set RTX_FRAME_RELATED_P. */
- if (GET_CODE (pat) == PARALLEL)
- for (int i = 0; i < XVECLEN (pat, 0); i++)
- if (GET_CODE (XVECEXP (pat, 0, i)) == SET)
- {
- rtx set = XVECEXP (pat, 0, i);
-
- if (!REG_P (SET_SRC (set))
- || interesting_frame_related_regno (REGNO (SET_SRC (set))))
- RTX_FRAME_RELATED_P (set) = 1;
- }
- RTX_FRAME_RELATED_P (insn) = 1;
- return insn;
- }
-
- /* We expect that 'pat' is either a SET or a PARALLEL containing
- SETs (and possibly other stuff). In a PARALLEL, all the SETs
- are important so they all have to be marked RTX_FRAME_RELATED_P.
- Call simplify_replace_rtx on the SETs rather than the whole insn
- so as to leave the other stuff alone (for example USE of r12). */
-
- set_used_flags (pat);
- if (GET_CODE (pat) == SET)
- {
- if (repl)
- pat = simplify_replace_rtx (pat, reg, repl);
- if (reg2)
- pat = simplify_replace_rtx (pat, reg2, repl2);
- }
- else if (GET_CODE (pat) == PARALLEL)
- {
- pat = shallow_copy_rtx (pat);
- XVEC (pat, 0) = shallow_copy_rtvec (XVEC (pat, 0));
-
- for (int i = 0; i < XVECLEN (pat, 0); i++)
- if (GET_CODE (XVECEXP (pat, 0, i)) == SET)
- {
- rtx set = XVECEXP (pat, 0, i);
-
- if (repl)
- set = simplify_replace_rtx (set, reg, repl);
- if (reg2)
- set = simplify_replace_rtx (set, reg2, repl2);
- XVECEXP (pat, 0, i) = set;
-
- if (!REG_P (SET_SRC (set))
- || interesting_frame_related_regno (REGNO (SET_SRC (set))))
- RTX_FRAME_RELATED_P (set) = 1;
- }
- }
- else
- gcc_unreachable ();
-
- RTX_FRAME_RELATED_P (insn) = 1;
- add_reg_note (insn, REG_FRAME_RELATED_EXPR, copy_rtx_if_shared (pat));
-
- return insn;
-}
-
-/* Returns an insn that has a vrsave set operation with the
- appropriate CLOBBERs. */
-
-static rtx
-generate_set_vrsave (rtx reg, rs6000_stack_t *info, int epiloguep)
-{
- int nclobs, i;
- rtx insn, clobs[TOTAL_ALTIVEC_REGS + 1];
- rtx vrsave = gen_rtx_REG (SImode, VRSAVE_REGNO);
-
- clobs[0]
- = gen_rtx_SET (vrsave,
- gen_rtx_UNSPEC_VOLATILE (SImode,
- gen_rtvec (2, reg, vrsave),
- UNSPECV_SET_VRSAVE));
-
- nclobs = 1;
-
- /* We need to clobber the registers in the mask so the scheduler
- does not move sets to VRSAVE before sets of AltiVec registers.
-
- However, if the function receives nonlocal gotos, reload will set
- all call saved registers live. We will end up with:
-
- (set (reg 999) (mem))
- (parallel [ (set (reg vrsave) (unspec blah))
- (clobber (reg 999))])
-
- The clobber will cause the store into reg 999 to be dead, and
- flow will attempt to delete an epilogue insn. In this case, we
- need an unspec use/set of the register. */
-
- for (i = FIRST_ALTIVEC_REGNO; i <= LAST_ALTIVEC_REGNO; ++i)
- if (info->vrsave_mask & ALTIVEC_REG_BIT (i))
- {
- if (!epiloguep || call_used_regs [i])
- clobs[nclobs++] = gen_hard_reg_clobber (V4SImode, i);
- else
- {
- rtx reg = gen_rtx_REG (V4SImode, i);
-
- clobs[nclobs++]
- = gen_rtx_SET (reg,
- gen_rtx_UNSPEC (V4SImode,
- gen_rtvec (1, reg), 27));
- }
- }
-
- insn = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (nclobs));
-
- for (i = 0; i < nclobs; ++i)
- XVECEXP (insn, 0, i) = clobs[i];
-
- return insn;
-}
-
-static rtx
-gen_frame_set (rtx reg, rtx frame_reg, int offset, bool store)
-{
- rtx addr, mem;
-
- addr = gen_rtx_PLUS (Pmode, frame_reg, GEN_INT (offset));
- mem = gen_frame_mem (GET_MODE (reg), addr);
- return gen_rtx_SET (store ? mem : reg, store ? reg : mem);
-}
-
-static rtx
-gen_frame_load (rtx reg, rtx frame_reg, int offset)
-{
- return gen_frame_set (reg, frame_reg, offset, false);
-}
-
-static rtx
-gen_frame_store (rtx reg, rtx frame_reg, int offset)
-{
- return gen_frame_set (reg, frame_reg, offset, true);
-}
-
-/* Save a register into the frame, and emit RTX_FRAME_RELATED_P notes.
- Save REGNO into [FRAME_REG + OFFSET] in mode MODE. */
-
-static rtx_insn *
-emit_frame_save (rtx frame_reg, machine_mode mode,
- unsigned int regno, int offset, HOST_WIDE_INT frame_reg_to_sp)
-{
- rtx reg;
-
- /* Some cases that need register indexed addressing. */
- gcc_checking_assert (!(TARGET_ALTIVEC_ABI && ALTIVEC_VECTOR_MODE (mode))
- || (TARGET_VSX && ALTIVEC_OR_VSX_VECTOR_MODE (mode)));
-
- reg = gen_rtx_REG (mode, regno);
- rtx_insn *insn = emit_insn (gen_frame_store (reg, frame_reg, offset));
- return rs6000_frame_related (insn, frame_reg, frame_reg_to_sp,
- NULL_RTX, NULL_RTX);
-}
-
-/* Emit an offset memory reference suitable for a frame store, while
- converting to a valid addressing mode. */
-
-static rtx
-gen_frame_mem_offset (machine_mode mode, rtx reg, int offset)
-{
- return gen_frame_mem (mode, gen_rtx_PLUS (Pmode, reg, GEN_INT (offset)));
-}
-
-#ifndef TARGET_FIX_AND_CONTINUE
-#define TARGET_FIX_AND_CONTINUE 0
-#endif
-
-/* It's really GPR 13 or 14, FPR 14 and VR 20. We need the smallest. */
-#define FIRST_SAVRES_REGISTER FIRST_SAVED_GP_REGNO
-#define LAST_SAVRES_REGISTER 31
-#define N_SAVRES_REGISTERS (LAST_SAVRES_REGISTER - FIRST_SAVRES_REGISTER + 1)
-
-enum {
- SAVRES_LR = 0x1,
- SAVRES_SAVE = 0x2,
- SAVRES_REG = 0x0c,
- SAVRES_GPR = 0,
- SAVRES_FPR = 4,
- SAVRES_VR = 8
-};
-
-static GTY(()) rtx savres_routine_syms[N_SAVRES_REGISTERS][12];
-
-/* Temporary holding space for an out-of-line register save/restore
- routine name. */
-static char savres_routine_name[30];
-
-/* Return the name for an out-of-line register save/restore routine.
- We are saving/restoring GPRs if GPR is true. */
-
-static char *
-rs6000_savres_routine_name (int regno, int sel)
-{
- const char *prefix = "";
- const char *suffix = "";
-
- /* Different targets are supposed to define
- {SAVE,RESTORE}_FP_{PREFIX,SUFFIX} with the idea that the needed
- routine name could be defined with:
-
- sprintf (name, "%s%d%s", SAVE_FP_PREFIX, regno, SAVE_FP_SUFFIX)
-
- This is a nice idea in practice, but in reality, things are
- complicated in several ways:
-
- - ELF targets have save/restore routines for GPRs.
-
- - PPC64 ELF targets have routines for save/restore of GPRs that
- differ in what they do with the link register, so having a set
- prefix doesn't work. (We only use one of the save routines at
- the moment, though.)
-
- - PPC32 elf targets have "exit" versions of the restore routines
- that restore the link register and can save some extra space.
- These require an extra suffix. (There are also "tail" versions
- of the restore routines and "GOT" versions of the save routines,
- but we don't generate those at present. Same problems apply,
- though.)
-
- We deal with all this by synthesizing our own prefix/suffix and
- using that for the simple sprintf call shown above. */
- if (DEFAULT_ABI == ABI_V4)
- {
- if (TARGET_64BIT)
- goto aix_names;
-
- if ((sel & SAVRES_REG) == SAVRES_GPR)
- prefix = (sel & SAVRES_SAVE) ? "_savegpr_" : "_restgpr_";
- else if ((sel & SAVRES_REG) == SAVRES_FPR)
- prefix = (sel & SAVRES_SAVE) ? "_savefpr_" : "_restfpr_";
- else if ((sel & SAVRES_REG) == SAVRES_VR)
- prefix = (sel & SAVRES_SAVE) ? "_savevr_" : "_restvr_";
- else
- abort ();
-
- if ((sel & SAVRES_LR))
- suffix = "_x";
- }
- else if (DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2)
- {
-#if !defined (POWERPC_LINUX) && !defined (POWERPC_FREEBSD)
- /* No out-of-line save/restore routines for GPRs on AIX. */
- gcc_assert (!TARGET_AIX || (sel & SAVRES_REG) != SAVRES_GPR);
-#endif
-
- aix_names:
- if ((sel & SAVRES_REG) == SAVRES_GPR)
- prefix = ((sel & SAVRES_SAVE)
- ? ((sel & SAVRES_LR) ? "_savegpr0_" : "_savegpr1_")
- : ((sel & SAVRES_LR) ? "_restgpr0_" : "_restgpr1_"));
- else if ((sel & SAVRES_REG) == SAVRES_FPR)
- {
-#if defined (POWERPC_LINUX) || defined (POWERPC_FREEBSD)
- if ((sel & SAVRES_LR))
- prefix = ((sel & SAVRES_SAVE) ? "_savefpr_" : "_restfpr_");
- else
-#endif
- {
- prefix = (sel & SAVRES_SAVE) ? SAVE_FP_PREFIX : RESTORE_FP_PREFIX;
- suffix = (sel & SAVRES_SAVE) ? SAVE_FP_SUFFIX : RESTORE_FP_SUFFIX;
- }
- }
- else if ((sel & SAVRES_REG) == SAVRES_VR)
- prefix = (sel & SAVRES_SAVE) ? "_savevr_" : "_restvr_";
- else
- abort ();
- }
-
- if (DEFAULT_ABI == ABI_DARWIN)
- {
- /* The Darwin approach is (slightly) different, in order to be
- compatible with code generated by the system toolchain. There is a
- single symbol for the start of save sequence, and the code here
- embeds an offset into that code on the basis of the first register
- to be saved. */
- prefix = (sel & SAVRES_SAVE) ? "save" : "rest" ;
- if ((sel & SAVRES_REG) == SAVRES_GPR)
- sprintf (savres_routine_name, "*%sGPR%s%s%.0d ; %s r%d-r31", prefix,
- ((sel & SAVRES_LR) ? "x" : ""), (regno == 13 ? "" : "+"),
- (regno - 13) * 4, prefix, regno);
- else if ((sel & SAVRES_REG) == SAVRES_FPR)
- sprintf (savres_routine_name, "*%sFP%s%.0d ; %s f%d-f31", prefix,
- (regno == 14 ? "" : "+"), (regno - 14) * 4, prefix, regno);
- else if ((sel & SAVRES_REG) == SAVRES_VR)
- sprintf (savres_routine_name, "*%sVEC%s%.0d ; %s v%d-v31", prefix,
- (regno == 20 ? "" : "+"), (regno - 20) * 8, prefix, regno);
- else
- abort ();
- }
- else
- sprintf (savres_routine_name, "%s%d%s", prefix, regno, suffix);
-
- return savres_routine_name;
-}
-
-/* Return an RTL SYMBOL_REF for an out-of-line register save/restore routine.
- We are saving/restoring GPRs if GPR is true. */
-
-static rtx
-rs6000_savres_routine_sym (rs6000_stack_t *info, int sel)
-{
- int regno = ((sel & SAVRES_REG) == SAVRES_GPR
- ? info->first_gp_reg_save
- : (sel & SAVRES_REG) == SAVRES_FPR
- ? info->first_fp_reg_save - 32
- : (sel & SAVRES_REG) == SAVRES_VR
- ? info->first_altivec_reg_save - FIRST_ALTIVEC_REGNO
- : -1);
- rtx sym;
- int select = sel;
-
- /* Don't generate bogus routine names. */
- gcc_assert (FIRST_SAVRES_REGISTER <= regno
- && regno <= LAST_SAVRES_REGISTER
- && select >= 0 && select <= 12);
-
- sym = savres_routine_syms[regno-FIRST_SAVRES_REGISTER][select];
-
- if (sym == NULL)
- {
- char *name;
-
- name = rs6000_savres_routine_name (regno, sel);
-
- sym = savres_routine_syms[regno-FIRST_SAVRES_REGISTER][select]
- = gen_rtx_SYMBOL_REF (Pmode, ggc_strdup (name));
- SYMBOL_REF_FLAGS (sym) |= SYMBOL_FLAG_FUNCTION;
- }
-
- return sym;
-}
-
-/* Emit a sequence of insns, including a stack tie if needed, for
- resetting the stack pointer. If UPDT_REGNO is not 1, then don't
- reset the stack pointer, but move the base of the frame into
- reg UPDT_REGNO for use by out-of-line register restore routines. */
-
-static rtx
-rs6000_emit_stack_reset (rtx frame_reg_rtx, HOST_WIDE_INT frame_off,
- unsigned updt_regno)
-{
- /* If there is nothing to do, don't do anything. */
- if (frame_off == 0 && REGNO (frame_reg_rtx) == updt_regno)
- return NULL_RTX;
-
- rtx updt_reg_rtx = gen_rtx_REG (Pmode, updt_regno);
-
- /* This blockage is needed so that sched doesn't decide to move
- the sp change before the register restores. */
- if (DEFAULT_ABI == ABI_V4)
- return emit_insn (gen_stack_restore_tie (updt_reg_rtx, frame_reg_rtx,
- GEN_INT (frame_off)));
-
- /* If we are restoring registers out-of-line, we will be using the
- "exit" variants of the restore routines, which will reset the
- stack for us. But we do need to point updt_reg into the
- right place for those routines. */
- if (frame_off != 0)
- return emit_insn (gen_add3_insn (updt_reg_rtx,
- frame_reg_rtx, GEN_INT (frame_off)));
- else
- return emit_move_insn (updt_reg_rtx, frame_reg_rtx);
-
- return NULL_RTX;
-}
-
-/* Return the register number used as a pointer by out-of-line
- save/restore functions. */
-
-static inline unsigned
-ptr_regno_for_savres (int sel)
-{
- if (DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2)
- return (sel & SAVRES_REG) == SAVRES_FPR || (sel & SAVRES_LR) ? 1 : 12;
- return DEFAULT_ABI == ABI_DARWIN && (sel & SAVRES_REG) == SAVRES_FPR ? 1 : 11;
-}
-
-/* Construct a parallel rtx describing the effect of a call to an
- out-of-line register save/restore routine, and emit the insn
- or jump_insn as appropriate. */
-
-static rtx_insn *
-rs6000_emit_savres_rtx (rs6000_stack_t *info,
- rtx frame_reg_rtx, int save_area_offset, int lr_offset,
- machine_mode reg_mode, int sel)
-{
- int i;
- int offset, start_reg, end_reg, n_regs, use_reg;
- int reg_size = GET_MODE_SIZE (reg_mode);
- rtx sym;
- rtvec p;
- rtx par;
- rtx_insn *insn;
-
- offset = 0;
- start_reg = ((sel & SAVRES_REG) == SAVRES_GPR
- ? info->first_gp_reg_save
- : (sel & SAVRES_REG) == SAVRES_FPR
- ? info->first_fp_reg_save
- : (sel & SAVRES_REG) == SAVRES_VR
- ? info->first_altivec_reg_save
- : -1);
- end_reg = ((sel & SAVRES_REG) == SAVRES_GPR
- ? 32
- : (sel & SAVRES_REG) == SAVRES_FPR
- ? 64
- : (sel & SAVRES_REG) == SAVRES_VR
- ? LAST_ALTIVEC_REGNO + 1
- : -1);
- n_regs = end_reg - start_reg;
- p = rtvec_alloc (3 + ((sel & SAVRES_LR) ? 1 : 0)
- + ((sel & SAVRES_REG) == SAVRES_VR ? 1 : 0)
- + n_regs);
-
- if (!(sel & SAVRES_SAVE) && (sel & SAVRES_LR))
- RTVEC_ELT (p, offset++) = ret_rtx;
-
- RTVEC_ELT (p, offset++) = gen_hard_reg_clobber (Pmode, LR_REGNO);
-
- sym = rs6000_savres_routine_sym (info, sel);
- RTVEC_ELT (p, offset++) = gen_rtx_USE (VOIDmode, sym);
-
- use_reg = ptr_regno_for_savres (sel);
- if ((sel & SAVRES_REG) == SAVRES_VR)
- {
- /* Vector regs are saved/restored using [reg+reg] addressing. */
- RTVEC_ELT (p, offset++) = gen_hard_reg_clobber (Pmode, use_reg);
- RTVEC_ELT (p, offset++)
- = gen_rtx_USE (VOIDmode, gen_rtx_REG (Pmode, 0));
- }
- else
- RTVEC_ELT (p, offset++)
- = gen_rtx_USE (VOIDmode, gen_rtx_REG (Pmode, use_reg));
-
- for (i = 0; i < end_reg - start_reg; i++)
- RTVEC_ELT (p, i + offset)
- = gen_frame_set (gen_rtx_REG (reg_mode, start_reg + i),
- frame_reg_rtx, save_area_offset + reg_size * i,
- (sel & SAVRES_SAVE) != 0);
-
- if ((sel & SAVRES_SAVE) && (sel & SAVRES_LR))
- RTVEC_ELT (p, i + offset)
- = gen_frame_store (gen_rtx_REG (Pmode, 0), frame_reg_rtx, lr_offset);
-
- par = gen_rtx_PARALLEL (VOIDmode, p);
-
- if (!(sel & SAVRES_SAVE) && (sel & SAVRES_LR))
- {
- insn = emit_jump_insn (par);
- JUMP_LABEL (insn) = ret_rtx;
- }
- else
- insn = emit_insn (par);
- return insn;
-}
-
-/* Emit prologue code to store CR fields that need to be saved into REG. This
- function should only be called when moving the non-volatile CRs to REG, it
- is not a general purpose routine to move the entire set of CRs to REG.
- Specifically, gen_prologue_movesi_from_cr() does not contain uses of the
- volatile CRs. */
-
-static void
-rs6000_emit_prologue_move_from_cr (rtx reg)
-{
- /* Only the ELFv2 ABI allows storing only selected fields. */
- if (DEFAULT_ABI == ABI_ELFv2 && TARGET_MFCRF)
- {
- int i, cr_reg[8], count = 0;
-
- /* Collect CR fields that must be saved. */
- for (i = 0; i < 8; i++)
- if (save_reg_p (CR0_REGNO + i))
- cr_reg[count++] = i;
-
- /* If it's just a single one, use mfcrf. */
- if (count == 1)
- {
- rtvec p = rtvec_alloc (1);
- rtvec r = rtvec_alloc (2);
- RTVEC_ELT (r, 0) = gen_rtx_REG (CCmode, CR0_REGNO + cr_reg[0]);
- RTVEC_ELT (r, 1) = GEN_INT (1 << (7 - cr_reg[0]));
- RTVEC_ELT (p, 0)
- = gen_rtx_SET (reg,
- gen_rtx_UNSPEC (SImode, r, UNSPEC_MOVESI_FROM_CR));
-
- emit_insn (gen_rtx_PARALLEL (VOIDmode, p));
- return;
- }
-
- /* ??? It might be better to handle count == 2 / 3 cases here
- as well, using logical operations to combine the values. */
- }
-
- emit_insn (gen_prologue_movesi_from_cr (reg));
-}
-
-/* Return whether the split-stack arg pointer (r12) is used. */
-
-static bool
-split_stack_arg_pointer_used_p (void)
-{
- /* If the pseudo holding the arg pointer is no longer a pseudo,
- then the arg pointer is used. */
- if (cfun->machine->split_stack_arg_pointer != NULL_RTX
- && (!REG_P (cfun->machine->split_stack_arg_pointer)
- || HARD_REGISTER_P (cfun->machine->split_stack_arg_pointer)))
- return true;
-
- /* Unfortunately we also need to do some code scanning, since
- r12 may have been substituted for the pseudo. */
- rtx_insn *insn;
- basic_block bb = ENTRY_BLOCK_PTR_FOR_FN (cfun)->next_bb;
- FOR_BB_INSNS (bb, insn)
- if (NONDEBUG_INSN_P (insn))
- {
- /* A call destroys r12. */
- if (CALL_P (insn))
- return false;
-
- df_ref use;
- FOR_EACH_INSN_USE (use, insn)
- {
- rtx x = DF_REF_REG (use);
- if (REG_P (x) && REGNO (x) == 12)
- return true;
- }
- df_ref def;
- FOR_EACH_INSN_DEF (def, insn)
- {
- rtx x = DF_REF_REG (def);
- if (REG_P (x) && REGNO (x) == 12)
- return false;
- }
- }
- return bitmap_bit_p (DF_LR_OUT (bb), 12);
-}
-
-/* Return whether we need to emit an ELFv2 global entry point prologue. */
-
-static bool
-rs6000_global_entry_point_needed_p (void)
-{
- /* Only needed for the ELFv2 ABI. */
- if (DEFAULT_ABI != ABI_ELFv2)
- return false;
-
- /* With -msingle-pic-base, we assume the whole program shares the same
- TOC, so no global entry point prologues are needed anywhere. */
- if (TARGET_SINGLE_PIC_BASE)
- return false;
-
- /* Ensure we have a global entry point for thunks. ??? We could
- avoid that if the target routine doesn't need a global entry point,
- but we do not know whether this is the case at this point. */
- if (cfun->is_thunk)
- return true;
-
- /* For regular functions, rs6000_emit_prologue sets this flag if the
- routine ever uses the TOC pointer. */
- return cfun->machine->r2_setup_needed;
-}
-
-/* Implement TARGET_SHRINK_WRAP_GET_SEPARATE_COMPONENTS. */
-static sbitmap
-rs6000_get_separate_components (void)
-{
- rs6000_stack_t *info = rs6000_stack_info ();
-
- if (WORLD_SAVE_P (info))
- return NULL;
-
- gcc_assert (!(info->savres_strategy & SAVE_MULTIPLE)
- && !(info->savres_strategy & REST_MULTIPLE));
-
- /* Component 0 is the save/restore of LR (done via GPR0).
- Component 2 is the save of the TOC (GPR2).
- Components 13..31 are the save/restore of GPR13..GPR31.
- Components 46..63 are the save/restore of FPR14..FPR31. */
-
- cfun->machine->n_components = 64;
-
- sbitmap components = sbitmap_alloc (cfun->machine->n_components);
- bitmap_clear (components);
-
- int reg_size = TARGET_32BIT ? 4 : 8;
- int fp_reg_size = 8;
-
- /* The GPRs we need saved to the frame. */
- if ((info->savres_strategy & SAVE_INLINE_GPRS)
- && (info->savres_strategy & REST_INLINE_GPRS))
- {
- int offset = info->gp_save_offset;
- if (info->push_p)
- offset += info->total_size;
-
- for (unsigned regno = info->first_gp_reg_save; regno < 32; regno++)
- {
- if (IN_RANGE (offset, -0x8000, 0x7fff)
- && save_reg_p (regno))
- bitmap_set_bit (components, regno);
-
- offset += reg_size;
- }
- }
-
- /* Don't mess with the hard frame pointer. */
- if (frame_pointer_needed)
- bitmap_clear_bit (components, HARD_FRAME_POINTER_REGNUM);
-
- /* Don't mess with the fixed TOC register. */
- if ((TARGET_TOC && TARGET_MINIMAL_TOC)
- || (flag_pic == 1 && DEFAULT_ABI == ABI_V4)
- || (flag_pic && DEFAULT_ABI == ABI_DARWIN))
- bitmap_clear_bit (components, RS6000_PIC_OFFSET_TABLE_REGNUM);
-
- /* The FPRs we need saved to the frame. */
- if ((info->savres_strategy & SAVE_INLINE_FPRS)
- && (info->savres_strategy & REST_INLINE_FPRS))
- {
- int offset = info->fp_save_offset;
- if (info->push_p)
- offset += info->total_size;
-
- for (unsigned regno = info->first_fp_reg_save; regno < 64; regno++)
- {
- if (IN_RANGE (offset, -0x8000, 0x7fff) && save_reg_p (regno))
- bitmap_set_bit (components, regno);
-
- offset += fp_reg_size;
- }
- }
-
- /* Optimize LR save and restore if we can. This is component 0. Any
- out-of-line register save/restore routines need LR. */
- if (info->lr_save_p
- && !(flag_pic && (DEFAULT_ABI == ABI_V4 || DEFAULT_ABI == ABI_DARWIN))
- && (info->savres_strategy & SAVE_INLINE_GPRS)
- && (info->savres_strategy & REST_INLINE_GPRS)
- && (info->savres_strategy & SAVE_INLINE_FPRS)
- && (info->savres_strategy & REST_INLINE_FPRS)
- && (info->savres_strategy & SAVE_INLINE_VRS)
- && (info->savres_strategy & REST_INLINE_VRS))
- {
- int offset = info->lr_save_offset;
- if (info->push_p)
- offset += info->total_size;
- if (IN_RANGE (offset, -0x8000, 0x7fff))
- bitmap_set_bit (components, 0);
- }
-
- /* Optimize saving the TOC. This is component 2. */
- if (cfun->machine->save_toc_in_prologue)
- bitmap_set_bit (components, 2);
-
- return components;
-}
-
-/* Implement TARGET_SHRINK_WRAP_COMPONENTS_FOR_BB. */
-static sbitmap
-rs6000_components_for_bb (basic_block bb)
-{
- rs6000_stack_t *info = rs6000_stack_info ();
-
- bitmap in = DF_LIVE_IN (bb);
- bitmap gen = &DF_LIVE_BB_INFO (bb)->gen;
- bitmap kill = &DF_LIVE_BB_INFO (bb)->kill;
-
- sbitmap components = sbitmap_alloc (cfun->machine->n_components);
- bitmap_clear (components);
-
- /* A register is used in a bb if it is in the IN, GEN, or KILL sets. */
-
- /* GPRs. */
- for (unsigned regno = info->first_gp_reg_save; regno < 32; regno++)
- if (bitmap_bit_p (in, regno)
- || bitmap_bit_p (gen, regno)
- || bitmap_bit_p (kill, regno))
- bitmap_set_bit (components, regno);
-
- /* FPRs. */
- for (unsigned regno = info->first_fp_reg_save; regno < 64; regno++)
- if (bitmap_bit_p (in, regno)
- || bitmap_bit_p (gen, regno)
- || bitmap_bit_p (kill, regno))
- bitmap_set_bit (components, regno);
-
- /* The link register. */
- if (bitmap_bit_p (in, LR_REGNO)
- || bitmap_bit_p (gen, LR_REGNO)
- || bitmap_bit_p (kill, LR_REGNO))
- bitmap_set_bit (components, 0);
-
- /* The TOC save. */
- if (bitmap_bit_p (in, TOC_REGNUM)
- || bitmap_bit_p (gen, TOC_REGNUM)
- || bitmap_bit_p (kill, TOC_REGNUM))
- bitmap_set_bit (components, 2);
-
- return components;
-}
-
-/* Implement TARGET_SHRINK_WRAP_DISQUALIFY_COMPONENTS. */
-static void
-rs6000_disqualify_components (sbitmap components, edge e,
- sbitmap edge_components, bool /*is_prologue*/)
-{
- /* Our LR pro/epilogue code moves LR via R0, so R0 had better not be
- live where we want to place that code. */
- if (bitmap_bit_p (edge_components, 0)
- && bitmap_bit_p (DF_LIVE_IN (e->dest), 0))
- {
- if (dump_file)
- fprintf (dump_file, "Disqualifying LR because GPR0 is live "
- "on entry to bb %d\n", e->dest->index);
- bitmap_clear_bit (components, 0);
- }
-}
-
-/* Implement TARGET_SHRINK_WRAP_EMIT_PROLOGUE_COMPONENTS. */
-static void
-rs6000_emit_prologue_components (sbitmap components)
-{
- rs6000_stack_t *info = rs6000_stack_info ();
- rtx ptr_reg = gen_rtx_REG (Pmode, frame_pointer_needed
- ? HARD_FRAME_POINTER_REGNUM
- : STACK_POINTER_REGNUM);
-
- machine_mode reg_mode = Pmode;
- int reg_size = TARGET_32BIT ? 4 : 8;
- machine_mode fp_reg_mode = TARGET_HARD_FLOAT ? DFmode : SFmode;
- int fp_reg_size = 8;
-
- /* Prologue for LR. */
- if (bitmap_bit_p (components, 0))
- {
- rtx lr = gen_rtx_REG (reg_mode, LR_REGNO);
- rtx reg = gen_rtx_REG (reg_mode, 0);
- rtx_insn *insn = emit_move_insn (reg, lr);
- RTX_FRAME_RELATED_P (insn) = 1;
- add_reg_note (insn, REG_CFA_REGISTER, gen_rtx_SET (reg, lr));
-
- int offset = info->lr_save_offset;
- if (info->push_p)
- offset += info->total_size;
-
- insn = emit_insn (gen_frame_store (reg, ptr_reg, offset));
- RTX_FRAME_RELATED_P (insn) = 1;
- rtx mem = copy_rtx (SET_DEST (single_set (insn)));
- add_reg_note (insn, REG_CFA_OFFSET, gen_rtx_SET (mem, lr));
- }
-
- /* Prologue for TOC. */
- if (bitmap_bit_p (components, 2))
- {
- rtx reg = gen_rtx_REG (reg_mode, TOC_REGNUM);
- rtx sp_reg = gen_rtx_REG (Pmode, STACK_POINTER_REGNUM);
- emit_insn (gen_frame_store (reg, sp_reg, RS6000_TOC_SAVE_SLOT));
- }
-
- /* Prologue for the GPRs. */
- int offset = info->gp_save_offset;
- if (info->push_p)
- offset += info->total_size;
-
- for (int i = info->first_gp_reg_save; i < 32; i++)
- {
- if (bitmap_bit_p (components, i))
- {
- rtx reg = gen_rtx_REG (reg_mode, i);
- rtx_insn *insn = emit_insn (gen_frame_store (reg, ptr_reg, offset));
- RTX_FRAME_RELATED_P (insn) = 1;
- rtx set = copy_rtx (single_set (insn));
- add_reg_note (insn, REG_CFA_OFFSET, set);
- }
-
- offset += reg_size;
- }
-
- /* Prologue for the FPRs. */
- offset = info->fp_save_offset;
- if (info->push_p)
- offset += info->total_size;
-
- for (int i = info->first_fp_reg_save; i < 64; i++)
- {
- if (bitmap_bit_p (components, i))
- {
- rtx reg = gen_rtx_REG (fp_reg_mode, i);
- rtx_insn *insn = emit_insn (gen_frame_store (reg, ptr_reg, offset));
- RTX_FRAME_RELATED_P (insn) = 1;
- rtx set = copy_rtx (single_set (insn));
- add_reg_note (insn, REG_CFA_OFFSET, set);
- }
-
- offset += fp_reg_size;
- }
-}
-
-/* Implement TARGET_SHRINK_WRAP_EMIT_EPILOGUE_COMPONENTS. */
-static void
-rs6000_emit_epilogue_components (sbitmap components)
-{
- rs6000_stack_t *info = rs6000_stack_info ();
- rtx ptr_reg = gen_rtx_REG (Pmode, frame_pointer_needed
- ? HARD_FRAME_POINTER_REGNUM
- : STACK_POINTER_REGNUM);
-
- machine_mode reg_mode = Pmode;
- int reg_size = TARGET_32BIT ? 4 : 8;
-
- machine_mode fp_reg_mode = TARGET_HARD_FLOAT ? DFmode : SFmode;
- int fp_reg_size = 8;
-
- /* Epilogue for the FPRs. */
- int offset = info->fp_save_offset;
- if (info->push_p)
- offset += info->total_size;
-
- for (int i = info->first_fp_reg_save; i < 64; i++)
- {
- if (bitmap_bit_p (components, i))
- {
- rtx reg = gen_rtx_REG (fp_reg_mode, i);
- rtx_insn *insn = emit_insn (gen_frame_load (reg, ptr_reg, offset));
- RTX_FRAME_RELATED_P (insn) = 1;
- add_reg_note (insn, REG_CFA_RESTORE, reg);
- }
-
- offset += fp_reg_size;
- }
-
- /* Epilogue for the GPRs. */
- offset = info->gp_save_offset;
- if (info->push_p)
- offset += info->total_size;
-
- for (int i = info->first_gp_reg_save; i < 32; i++)
- {
- if (bitmap_bit_p (components, i))
- {
- rtx reg = gen_rtx_REG (reg_mode, i);
- rtx_insn *insn = emit_insn (gen_frame_load (reg, ptr_reg, offset));
- RTX_FRAME_RELATED_P (insn) = 1;
- add_reg_note (insn, REG_CFA_RESTORE, reg);
- }
-
- offset += reg_size;
- }
-
- /* Epilogue for LR. */
- if (bitmap_bit_p (components, 0))
- {
- int offset = info->lr_save_offset;
- if (info->push_p)
- offset += info->total_size;
-
- rtx reg = gen_rtx_REG (reg_mode, 0);
- rtx_insn *insn = emit_insn (gen_frame_load (reg, ptr_reg, offset));
-
- rtx lr = gen_rtx_REG (Pmode, LR_REGNO);
- insn = emit_move_insn (lr, reg);
- RTX_FRAME_RELATED_P (insn) = 1;
- add_reg_note (insn, REG_CFA_RESTORE, lr);
- }
-}
-
-/* Implement TARGET_SHRINK_WRAP_SET_HANDLED_COMPONENTS. */
-static void
-rs6000_set_handled_components (sbitmap components)
-{
- rs6000_stack_t *info = rs6000_stack_info ();
-
- for (int i = info->first_gp_reg_save; i < 32; i++)
- if (bitmap_bit_p (components, i))
- cfun->machine->gpr_is_wrapped_separately[i] = true;
-
- for (int i = info->first_fp_reg_save; i < 64; i++)
- if (bitmap_bit_p (components, i))
- cfun->machine->fpr_is_wrapped_separately[i - 32] = true;
-
- if (bitmap_bit_p (components, 0))
- cfun->machine->lr_is_wrapped_separately = true;
-
- if (bitmap_bit_p (components, 2))
- cfun->machine->toc_is_wrapped_separately = true;
-}
-
-/* VRSAVE is a bit vector representing which AltiVec registers
- are used. The OS uses this to determine which vector
- registers to save on a context switch. We need to save
- VRSAVE on the stack frame, add whatever AltiVec registers we
- used in this function, and do the corresponding magic in the
- epilogue. */
-static void
-emit_vrsave_prologue (rs6000_stack_t *info, int save_regno,
- HOST_WIDE_INT frame_off, rtx frame_reg_rtx)
-{
- /* Get VRSAVE into a GPR. */
- rtx reg = gen_rtx_REG (SImode, save_regno);
- rtx vrsave = gen_rtx_REG (SImode, VRSAVE_REGNO);
- if (TARGET_MACHO)
- emit_insn (gen_get_vrsave_internal (reg));
- else
- emit_insn (gen_rtx_SET (reg, vrsave));
-
- /* Save VRSAVE. */
- int offset = info->vrsave_save_offset + frame_off;
- emit_insn (gen_frame_store (reg, frame_reg_rtx, offset));
-
- /* Include the registers in the mask. */
- emit_insn (gen_iorsi3 (reg, reg, GEN_INT (info->vrsave_mask)));
-
- emit_insn (generate_set_vrsave (reg, info, 0));
-}
-
-/* Set up the arg pointer (r12) for -fsplit-stack code. If __morestack was
- called, it left the arg pointer to the old stack in r29. Otherwise, the
- arg pointer is the top of the current frame. */
-static void
-emit_split_stack_prologue (rs6000_stack_t *info, rtx_insn *sp_adjust,
- HOST_WIDE_INT frame_off, rtx frame_reg_rtx)
-{
- cfun->machine->split_stack_argp_used = true;
-
- if (sp_adjust)
- {
- rtx r12 = gen_rtx_REG (Pmode, 12);
- rtx sp_reg_rtx = gen_rtx_REG (Pmode, STACK_POINTER_REGNUM);
- rtx set_r12 = gen_rtx_SET (r12, sp_reg_rtx);
- emit_insn_before (set_r12, sp_adjust);
- }
- else if (frame_off != 0 || REGNO (frame_reg_rtx) != 12)
- {
- rtx r12 = gen_rtx_REG (Pmode, 12);
- if (frame_off == 0)
- emit_move_insn (r12, frame_reg_rtx);
- else
- emit_insn (gen_add3_insn (r12, frame_reg_rtx, GEN_INT (frame_off)));
- }
-
- if (info->push_p)
- {
- rtx r12 = gen_rtx_REG (Pmode, 12);
- rtx r29 = gen_rtx_REG (Pmode, 29);
- rtx cr7 = gen_rtx_REG (CCUNSmode, CR7_REGNO);
- rtx not_more = gen_label_rtx ();
- rtx jump;
-
- jump = gen_rtx_IF_THEN_ELSE (VOIDmode,
- gen_rtx_GEU (VOIDmode, cr7, const0_rtx),
- gen_rtx_LABEL_REF (VOIDmode, not_more),
- pc_rtx);
- jump = emit_jump_insn (gen_rtx_SET (pc_rtx, jump));
- JUMP_LABEL (jump) = not_more;
- LABEL_NUSES (not_more) += 1;
- emit_move_insn (r12, r29);
- emit_label (not_more);
- }
-}
-
-/* Emit function prologue as insns. */
-
-void
-rs6000_emit_prologue (void)
-{
- rs6000_stack_t *info = rs6000_stack_info ();
- machine_mode reg_mode = Pmode;
- int reg_size = TARGET_32BIT ? 4 : 8;
- machine_mode fp_reg_mode = TARGET_HARD_FLOAT ? DFmode : SFmode;
- int fp_reg_size = 8;
- rtx sp_reg_rtx = gen_rtx_REG (Pmode, STACK_POINTER_REGNUM);
- rtx frame_reg_rtx = sp_reg_rtx;
- unsigned int cr_save_regno;
- rtx cr_save_rtx = NULL_RTX;
- rtx_insn *insn;
- int strategy;
- int using_static_chain_p = (cfun->static_chain_decl != NULL_TREE
- && df_regs_ever_live_p (STATIC_CHAIN_REGNUM)
- && call_used_regs[STATIC_CHAIN_REGNUM]);
- int using_split_stack = (flag_split_stack
- && (lookup_attribute ("no_split_stack",
- DECL_ATTRIBUTES (cfun->decl))
- == NULL));
-
- /* Offset to top of frame for frame_reg and sp respectively. */
- HOST_WIDE_INT frame_off = 0;
- HOST_WIDE_INT sp_off = 0;
- /* sp_adjust is the stack adjusting instruction, tracked so that the
- insn setting up the split-stack arg pointer can be emitted just
- prior to it, when r12 is not used here for other purposes. */
- rtx_insn *sp_adjust = 0;
-
-#if CHECKING_P
- /* Track and check usage of r0, r11, r12. */
- int reg_inuse = using_static_chain_p ? 1 << 11 : 0;
-#define START_USE(R) do \
- { \
- gcc_assert ((reg_inuse & (1 << (R))) == 0); \
- reg_inuse |= 1 << (R); \
- } while (0)
-#define END_USE(R) do \
- { \
- gcc_assert ((reg_inuse & (1 << (R))) != 0); \
- reg_inuse &= ~(1 << (R)); \
- } while (0)
-#define NOT_INUSE(R) do \
- { \
- gcc_assert ((reg_inuse & (1 << (R))) == 0); \
- } while (0)
-#else
-#define START_USE(R) do {} while (0)
-#define END_USE(R) do {} while (0)
-#define NOT_INUSE(R) do {} while (0)
-#endif
-
- if (DEFAULT_ABI == ABI_ELFv2
- && !TARGET_SINGLE_PIC_BASE)
- {
- cfun->machine->r2_setup_needed = df_regs_ever_live_p (TOC_REGNUM);
-
- /* With -mminimal-toc we may generate an extra use of r2 below. */
- if (TARGET_TOC && TARGET_MINIMAL_TOC
- && !constant_pool_empty_p ())
- cfun->machine->r2_setup_needed = true;
- }
-
-
- if (flag_stack_usage_info)
- current_function_static_stack_size = info->total_size;
-
- if (flag_stack_check == STATIC_BUILTIN_STACK_CHECK)
- {
- HOST_WIDE_INT size = info->total_size;
-
- if (crtl->is_leaf && !cfun->calls_alloca)
- {
- if (size > PROBE_INTERVAL && size > get_stack_check_protect ())
- rs6000_emit_probe_stack_range (get_stack_check_protect (),
- size - get_stack_check_protect ());
- }
- else if (size > 0)
- rs6000_emit_probe_stack_range (get_stack_check_protect (), size);
- }
-
- if (TARGET_FIX_AND_CONTINUE)
- {
- /* gdb on darwin arranges to forward a function from the old
- address by modifying the first 5 instructions of the function
- to branch to the overriding function. This is necessary to
- permit function pointers that point to the old function to
- actually forward to the new function. */
- emit_insn (gen_nop ());
- emit_insn (gen_nop ());
- emit_insn (gen_nop ());
- emit_insn (gen_nop ());
- emit_insn (gen_nop ());
- }
-
- /* Handle world saves specially here. */
- if (WORLD_SAVE_P (info))
- {
- int i, j, sz;
- rtx treg;
- rtvec p;
- rtx reg0;
-
- /* save_world expects lr in r0. */
- reg0 = gen_rtx_REG (Pmode, 0);
- if (info->lr_save_p)
- {
- insn = emit_move_insn (reg0,
- gen_rtx_REG (Pmode, LR_REGNO));
- RTX_FRAME_RELATED_P (insn) = 1;
- }
-
- /* The SAVE_WORLD and RESTORE_WORLD routines make a number of
- assumptions about the offsets of various bits of the stack
- frame. */
- gcc_assert (info->gp_save_offset == -220
- && info->fp_save_offset == -144
- && info->lr_save_offset == 8
- && info->cr_save_offset == 4
- && info->push_p
- && info->lr_save_p
- && (!crtl->calls_eh_return
- || info->ehrd_offset == -432)
- && info->vrsave_save_offset == -224
- && info->altivec_save_offset == -416);
-
- treg = gen_rtx_REG (SImode, 11);
- emit_move_insn (treg, GEN_INT (-info->total_size));
-
- /* SAVE_WORLD takes the caller's LR in R0 and the frame size
- in R11. It also clobbers R12, so beware! */
-
- /* Preserve CR2 for save_world prologues */
- sz = 5;
- sz += 32 - info->first_gp_reg_save;
- sz += 64 - info->first_fp_reg_save;
- sz += LAST_ALTIVEC_REGNO - info->first_altivec_reg_save + 1;
- p = rtvec_alloc (sz);
- j = 0;
- RTVEC_ELT (p, j++) = gen_hard_reg_clobber (SImode, LR_REGNO);
- RTVEC_ELT (p, j++) = gen_rtx_USE (VOIDmode,
- gen_rtx_SYMBOL_REF (Pmode,
- "*save_world"));
- /* We do floats first so that the instruction pattern matches
- properly. */
- for (i = 0; i < 64 - info->first_fp_reg_save; i++)
- RTVEC_ELT (p, j++)
- = gen_frame_store (gen_rtx_REG (TARGET_HARD_FLOAT ? DFmode : SFmode,
- info->first_fp_reg_save + i),
- frame_reg_rtx,
- info->fp_save_offset + frame_off + 8 * i);
- for (i = 0; info->first_altivec_reg_save + i <= LAST_ALTIVEC_REGNO; i++)
- RTVEC_ELT (p, j++)
- = gen_frame_store (gen_rtx_REG (V4SImode,
- info->first_altivec_reg_save + i),
- frame_reg_rtx,
- info->altivec_save_offset + frame_off + 16 * i);
- for (i = 0; i < 32 - info->first_gp_reg_save; i++)
- RTVEC_ELT (p, j++)
- = gen_frame_store (gen_rtx_REG (reg_mode, info->first_gp_reg_save + i),
- frame_reg_rtx,
- info->gp_save_offset + frame_off + reg_size * i);
-
- /* CR register traditionally saved as CR2. */
- RTVEC_ELT (p, j++)
- = gen_frame_store (gen_rtx_REG (SImode, CR2_REGNO),
- frame_reg_rtx, info->cr_save_offset + frame_off);
- /* Explain about use of R0. */
- if (info->lr_save_p)
- RTVEC_ELT (p, j++)
- = gen_frame_store (reg0,
- frame_reg_rtx, info->lr_save_offset + frame_off);
- /* Explain what happens to the stack pointer. */
- {
- rtx newval = gen_rtx_PLUS (Pmode, sp_reg_rtx, treg);
- RTVEC_ELT (p, j++) = gen_rtx_SET (sp_reg_rtx, newval);
- }
-
- insn = emit_insn (gen_rtx_PARALLEL (VOIDmode, p));
- rs6000_frame_related (insn, frame_reg_rtx, sp_off - frame_off,
- treg, GEN_INT (-info->total_size));
- sp_off = frame_off = info->total_size;
- }
-
- strategy = info->savres_strategy;
-
- /* For V.4, update stack before we do any saving and set back pointer. */
- if (! WORLD_SAVE_P (info)
- && info->push_p
- && (DEFAULT_ABI == ABI_V4
- || crtl->calls_eh_return))
- {
- bool need_r11 = (!(strategy & SAVE_INLINE_FPRS)
- || !(strategy & SAVE_INLINE_GPRS)
- || !(strategy & SAVE_INLINE_VRS));
- int ptr_regno = -1;
- rtx ptr_reg = NULL_RTX;
- int ptr_off = 0;
-
- if (info->total_size < 32767)
- frame_off = info->total_size;
- else if (need_r11)
- ptr_regno = 11;
- else if (info->cr_save_p
- || info->lr_save_p
- || info->first_fp_reg_save < 64
- || info->first_gp_reg_save < 32
- || info->altivec_size != 0
- || info->vrsave_size != 0
- || crtl->calls_eh_return)
- ptr_regno = 12;
- else
- {
- /* The prologue won't be saving any regs so there is no need
- to set up a frame register to access any frame save area.
- We also won't be using frame_off anywhere below, but set
- the correct value anyway to protect against future
- changes to this function. */
- frame_off = info->total_size;
- }
- if (ptr_regno != -1)
- {
- /* Set up the frame offset to that needed by the first
- out-of-line save function. */
- START_USE (ptr_regno);
- ptr_reg = gen_rtx_REG (Pmode, ptr_regno);
- frame_reg_rtx = ptr_reg;
- if (!(strategy & SAVE_INLINE_FPRS) && info->fp_size != 0)
- gcc_checking_assert (info->fp_save_offset + info->fp_size == 0);
- else if (!(strategy & SAVE_INLINE_GPRS) && info->first_gp_reg_save < 32)
- ptr_off = info->gp_save_offset + info->gp_size;
- else if (!(strategy & SAVE_INLINE_VRS) && info->altivec_size != 0)
- ptr_off = info->altivec_save_offset + info->altivec_size;
- frame_off = -ptr_off;
- }
- sp_adjust = rs6000_emit_allocate_stack (info->total_size,
- ptr_reg, ptr_off);
- if (REGNO (frame_reg_rtx) == 12)
- sp_adjust = 0;
- sp_off = info->total_size;
- if (frame_reg_rtx != sp_reg_rtx)
- rs6000_emit_stack_tie (frame_reg_rtx, false);
- }
-
- /* If we use the link register, get it into r0. */
- if (!WORLD_SAVE_P (info) && info->lr_save_p
- && !cfun->machine->lr_is_wrapped_separately)
- {
- rtx addr, reg, mem;
-
- reg = gen_rtx_REG (Pmode, 0);
- START_USE (0);
- insn = emit_move_insn (reg, gen_rtx_REG (Pmode, LR_REGNO));
- RTX_FRAME_RELATED_P (insn) = 1;
-
- if (!(strategy & (SAVE_NOINLINE_GPRS_SAVES_LR
- | SAVE_NOINLINE_FPRS_SAVES_LR)))
- {
- addr = gen_rtx_PLUS (Pmode, frame_reg_rtx,
- GEN_INT (info->lr_save_offset + frame_off));
- mem = gen_rtx_MEM (Pmode, addr);
- /* This should not be of rs6000_sr_alias_set, because of
- __builtin_return_address. */
-
- insn = emit_move_insn (mem, reg);
- rs6000_frame_related (insn, frame_reg_rtx, sp_off - frame_off,
- NULL_RTX, NULL_RTX);
- END_USE (0);
- }
- }
-
- /* If we need to save CR, put it into r12 or r11. Choose r12 except when
- r12 will be needed by out-of-line gpr save. */
- cr_save_regno = ((DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2)
- && !(strategy & (SAVE_INLINE_GPRS
- | SAVE_NOINLINE_GPRS_SAVES_LR))
- ? 11 : 12);
- if (!WORLD_SAVE_P (info)
- && info->cr_save_p
- && REGNO (frame_reg_rtx) != cr_save_regno
- && !(using_static_chain_p && cr_save_regno == 11)
- && !(using_split_stack && cr_save_regno == 12 && sp_adjust))
- {
- cr_save_rtx = gen_rtx_REG (SImode, cr_save_regno);
- START_USE (cr_save_regno);
- rs6000_emit_prologue_move_from_cr (cr_save_rtx);
- }
-
- /* Do any required saving of fpr's. If only one or two to save, do
- it ourselves. Otherwise, call function. */
- if (!WORLD_SAVE_P (info) && (strategy & SAVE_INLINE_FPRS))
- {
- int offset = info->fp_save_offset + frame_off;
- for (int i = info->first_fp_reg_save; i < 64; i++)
- {
- if (save_reg_p (i)
- && !cfun->machine->fpr_is_wrapped_separately[i - 32])
- emit_frame_save (frame_reg_rtx, fp_reg_mode, i, offset,
- sp_off - frame_off);
-
- offset += fp_reg_size;
- }
- }
- else if (!WORLD_SAVE_P (info) && info->first_fp_reg_save != 64)
- {
- bool lr = (strategy & SAVE_NOINLINE_FPRS_SAVES_LR) != 0;
- int sel = SAVRES_SAVE | SAVRES_FPR | (lr ? SAVRES_LR : 0);
- unsigned ptr_regno = ptr_regno_for_savres (sel);
- rtx ptr_reg = frame_reg_rtx;
-
- if (REGNO (frame_reg_rtx) == ptr_regno)
- gcc_checking_assert (frame_off == 0);
- else
- {
- ptr_reg = gen_rtx_REG (Pmode, ptr_regno);
- NOT_INUSE (ptr_regno);
- emit_insn (gen_add3_insn (ptr_reg,
- frame_reg_rtx, GEN_INT (frame_off)));
- }
- insn = rs6000_emit_savres_rtx (info, ptr_reg,
- info->fp_save_offset,
- info->lr_save_offset,
- DFmode, sel);
- rs6000_frame_related (insn, ptr_reg, sp_off,
- NULL_RTX, NULL_RTX);
- if (lr)
- END_USE (0);
- }
-
- /* Save GPRs. This is done as a PARALLEL if we are using
- the store-multiple instructions. */
- if (!WORLD_SAVE_P (info) && !(strategy & SAVE_INLINE_GPRS))
- {
- bool lr = (strategy & SAVE_NOINLINE_GPRS_SAVES_LR) != 0;
- int sel = SAVRES_SAVE | SAVRES_GPR | (lr ? SAVRES_LR : 0);
- unsigned ptr_regno = ptr_regno_for_savres (sel);
- rtx ptr_reg = frame_reg_rtx;
- bool ptr_set_up = REGNO (ptr_reg) == ptr_regno;
- int end_save = info->gp_save_offset + info->gp_size;
- int ptr_off;
-
- if (ptr_regno == 12)
- sp_adjust = 0;
- if (!ptr_set_up)
- ptr_reg = gen_rtx_REG (Pmode, ptr_regno);
-
- /* Need to adjust r11 (r12) if we saved any FPRs. */
- if (end_save + frame_off != 0)
- {
- rtx offset = GEN_INT (end_save + frame_off);
-
- if (ptr_set_up)
- frame_off = -end_save;
- else
- NOT_INUSE (ptr_regno);
- emit_insn (gen_add3_insn (ptr_reg, frame_reg_rtx, offset));
- }
- else if (!ptr_set_up)
- {
- NOT_INUSE (ptr_regno);
- emit_move_insn (ptr_reg, frame_reg_rtx);
- }
- ptr_off = -end_save;
- insn = rs6000_emit_savres_rtx (info, ptr_reg,
- info->gp_save_offset + ptr_off,
- info->lr_save_offset + ptr_off,
- reg_mode, sel);
- rs6000_frame_related (insn, ptr_reg, sp_off - ptr_off,
- NULL_RTX, NULL_RTX);
- if (lr)
- END_USE (0);
- }
- else if (!WORLD_SAVE_P (info) && (strategy & SAVE_MULTIPLE))
- {
- rtvec p;
- int i;
- p = rtvec_alloc (32 - info->first_gp_reg_save);
- for (i = 0; i < 32 - info->first_gp_reg_save; i++)
- RTVEC_ELT (p, i)
- = gen_frame_store (gen_rtx_REG (reg_mode, info->first_gp_reg_save + i),
- frame_reg_rtx,
- info->gp_save_offset + frame_off + reg_size * i);
- insn = emit_insn (gen_rtx_PARALLEL (VOIDmode, p));
- rs6000_frame_related (insn, frame_reg_rtx, sp_off - frame_off,
- NULL_RTX, NULL_RTX);
- }
- else if (!WORLD_SAVE_P (info))
- {
- int offset = info->gp_save_offset + frame_off;
- for (int i = info->first_gp_reg_save; i < 32; i++)
- {
- if (save_reg_p (i)
- && !cfun->machine->gpr_is_wrapped_separately[i])
- emit_frame_save (frame_reg_rtx, reg_mode, i, offset,
- sp_off - frame_off);
-
- offset += reg_size;
- }
- }
-
- if (crtl->calls_eh_return)
- {
- unsigned int i;
- rtvec p;
-
- for (i = 0; ; ++i)
- {
- unsigned int regno = EH_RETURN_DATA_REGNO (i);
- if (regno == INVALID_REGNUM)
- break;
- }
-
- p = rtvec_alloc (i);
-
- for (i = 0; ; ++i)
- {
- unsigned int regno = EH_RETURN_DATA_REGNO (i);
- if (regno == INVALID_REGNUM)
- break;
-
- rtx set
- = gen_frame_store (gen_rtx_REG (reg_mode, regno),
- sp_reg_rtx,
- info->ehrd_offset + sp_off + reg_size * (int) i);
- RTVEC_ELT (p, i) = set;
- RTX_FRAME_RELATED_P (set) = 1;
- }
-
- insn = emit_insn (gen_blockage ());
- RTX_FRAME_RELATED_P (insn) = 1;
- add_reg_note (insn, REG_FRAME_RELATED_EXPR, gen_rtx_PARALLEL (VOIDmode, p));
- }
-
- /* In AIX ABI we need to make sure r2 is really saved. */
- if (TARGET_AIX && crtl->calls_eh_return)
- {
- rtx tmp_reg, tmp_reg_si, hi, lo, compare_result, toc_save_done, jump;
- rtx join_insn, note;
- rtx_insn *save_insn;
- long toc_restore_insn;
-
- tmp_reg = gen_rtx_REG (Pmode, 11);
- tmp_reg_si = gen_rtx_REG (SImode, 11);
- if (using_static_chain_p)
- {
- START_USE (0);
- emit_move_insn (gen_rtx_REG (Pmode, 0), tmp_reg);
- }
- else
- START_USE (11);
- emit_move_insn (tmp_reg, gen_rtx_REG (Pmode, LR_REGNO));
- /* Peek at instruction to which this function returns. If it's
- restoring r2, then we know we've already saved r2. We can't
- unconditionally save r2 because the value we have will already
- be updated if we arrived at this function via a plt call or
- toc adjusting stub. */
- emit_move_insn (tmp_reg_si, gen_rtx_MEM (SImode, tmp_reg));
- toc_restore_insn = ((TARGET_32BIT ? 0x80410000 : 0xE8410000)
- + RS6000_TOC_SAVE_SLOT);
- hi = gen_int_mode (toc_restore_insn & ~0xffff, SImode);
- emit_insn (gen_xorsi3 (tmp_reg_si, tmp_reg_si, hi));
- compare_result = gen_rtx_REG (CCUNSmode, CR0_REGNO);
- validate_condition_mode (EQ, CCUNSmode);
- lo = gen_int_mode (toc_restore_insn & 0xffff, SImode);
- emit_insn (gen_rtx_SET (compare_result,
- gen_rtx_COMPARE (CCUNSmode, tmp_reg_si, lo)));
- toc_save_done = gen_label_rtx ();
- jump = gen_rtx_IF_THEN_ELSE (VOIDmode,
- gen_rtx_EQ (VOIDmode, compare_result,
- const0_rtx),
- gen_rtx_LABEL_REF (VOIDmode, toc_save_done),
- pc_rtx);
- jump = emit_jump_insn (gen_rtx_SET (pc_rtx, jump));
- JUMP_LABEL (jump) = toc_save_done;
- LABEL_NUSES (toc_save_done) += 1;
-
- save_insn = emit_frame_save (frame_reg_rtx, reg_mode,
- TOC_REGNUM, frame_off + RS6000_TOC_SAVE_SLOT,
- sp_off - frame_off);
-
- emit_label (toc_save_done);
-
- /* ??? If we leave SAVE_INSN as marked as saving R2, then we'll
- have a CFG that has different saves along different paths.
- Move the note to a dummy blockage insn, which describes that
- R2 is unconditionally saved after the label. */
- /* ??? An alternate representation might be a special insn pattern
- containing both the branch and the store. That might let the
- code that minimizes the number of DW_CFA_advance opcodes better
- freedom in placing the annotations. */
- note = find_reg_note (save_insn, REG_FRAME_RELATED_EXPR, NULL);
- if (note)
- remove_note (save_insn, note);
- else
- note = alloc_reg_note (REG_FRAME_RELATED_EXPR,
- copy_rtx (PATTERN (save_insn)), NULL_RTX);
- RTX_FRAME_RELATED_P (save_insn) = 0;
-
- join_insn = emit_insn (gen_blockage ());
- REG_NOTES (join_insn) = note;
- RTX_FRAME_RELATED_P (join_insn) = 1;
-
- if (using_static_chain_p)
- {
- emit_move_insn (tmp_reg, gen_rtx_REG (Pmode, 0));
- END_USE (0);
- }
- else
- END_USE (11);
- }
-
- /* Save CR if we use any that must be preserved. */
- if (!WORLD_SAVE_P (info) && info->cr_save_p)
- {
- rtx addr = gen_rtx_PLUS (Pmode, frame_reg_rtx,
- GEN_INT (info->cr_save_offset + frame_off));
- rtx mem = gen_frame_mem (SImode, addr);
-
- /* If we didn't copy cr before, do so now using r0. */
- if (cr_save_rtx == NULL_RTX)
- {
- START_USE (0);
- cr_save_rtx = gen_rtx_REG (SImode, 0);
- rs6000_emit_prologue_move_from_cr (cr_save_rtx);
- }
-
- /* Saving CR requires a two-instruction sequence: one instruction
- to move the CR to a general-purpose register, and a second
- instruction that stores the GPR to memory.
-
- We do not emit any DWARF CFI records for the first of these,
- because we cannot properly represent the fact that CR is saved in
- a register. One reason is that we cannot express that multiple
- CR fields are saved; another reason is that on 64-bit, the size
- of the CR register in DWARF (4 bytes) differs from the size of
- a general-purpose register.
-
- This means if any intervening instruction were to clobber one of
- the call-saved CR fields, we'd have incorrect CFI. To prevent
- this from happening, we mark the store to memory as a use of
- those CR fields, which prevents any such instruction from being
- scheduled in between the two instructions. */
- rtx crsave_v[9];
- int n_crsave = 0;
- int i;
-
- crsave_v[n_crsave++] = gen_rtx_SET (mem, cr_save_rtx);
- for (i = 0; i < 8; i++)
- if (save_reg_p (CR0_REGNO + i))
- crsave_v[n_crsave++]
- = gen_rtx_USE (VOIDmode, gen_rtx_REG (CCmode, CR0_REGNO + i));
-
- insn = emit_insn (gen_rtx_PARALLEL (VOIDmode,
- gen_rtvec_v (n_crsave, crsave_v)));
- END_USE (REGNO (cr_save_rtx));
-
- /* Now, there's no way that dwarf2out_frame_debug_expr is going to
- understand '(unspec:SI [(reg:CC 68) ...] UNSPEC_MOVESI_FROM_CR)',
- so we need to construct a frame expression manually. */
- RTX_FRAME_RELATED_P (insn) = 1;
-
- /* Update address to be stack-pointer relative, like
- rs6000_frame_related would do. */
- addr = gen_rtx_PLUS (Pmode, gen_rtx_REG (Pmode, STACK_POINTER_REGNUM),
- GEN_INT (info->cr_save_offset + sp_off));
- mem = gen_frame_mem (SImode, addr);
-
- if (DEFAULT_ABI == ABI_ELFv2)
- {
- /* In the ELFv2 ABI we generate separate CFI records for each
- CR field that was actually saved. They all point to the
- same 32-bit stack slot. */
- rtx crframe[8];
- int n_crframe = 0;
-
- for (i = 0; i < 8; i++)
- if (save_reg_p (CR0_REGNO + i))
- {
- crframe[n_crframe]
- = gen_rtx_SET (mem, gen_rtx_REG (SImode, CR0_REGNO + i));
-
- RTX_FRAME_RELATED_P (crframe[n_crframe]) = 1;
- n_crframe++;
- }
-
- add_reg_note (insn, REG_FRAME_RELATED_EXPR,
- gen_rtx_PARALLEL (VOIDmode,
- gen_rtvec_v (n_crframe, crframe)));
- }
- else
- {
- /* In other ABIs, by convention, we use a single CR regnum to
- represent the fact that all call-saved CR fields are saved.
- We use CR2_REGNO to be compatible with gcc-2.95 on Linux. */
- rtx set = gen_rtx_SET (mem, gen_rtx_REG (SImode, CR2_REGNO));
- add_reg_note (insn, REG_FRAME_RELATED_EXPR, set);
- }
- }
-
- /* In the ELFv2 ABI we need to save all call-saved CR fields into
- *separate* slots if the routine calls __builtin_eh_return, so
- that they can be independently restored by the unwinder. */
- if (DEFAULT_ABI == ABI_ELFv2 && crtl->calls_eh_return)
- {
- int i, cr_off = info->ehcr_offset;
- rtx crsave;
-
- /* ??? We might get better performance by using multiple mfocrf
- instructions. */
- crsave = gen_rtx_REG (SImode, 0);
- emit_insn (gen_prologue_movesi_from_cr (crsave));
-
- for (i = 0; i < 8; i++)
- if (!call_used_regs[CR0_REGNO + i])
- {
- rtvec p = rtvec_alloc (2);
- RTVEC_ELT (p, 0)
- = gen_frame_store (crsave, frame_reg_rtx, cr_off + frame_off);
- RTVEC_ELT (p, 1)
- = gen_rtx_USE (VOIDmode, gen_rtx_REG (CCmode, CR0_REGNO + i));
-
- insn = emit_insn (gen_rtx_PARALLEL (VOIDmode, p));
-
- RTX_FRAME_RELATED_P (insn) = 1;
- add_reg_note (insn, REG_FRAME_RELATED_EXPR,
- gen_frame_store (gen_rtx_REG (SImode, CR0_REGNO + i),
- sp_reg_rtx, cr_off + sp_off));
-
- cr_off += reg_size;
- }
- }
-
- /* If we are emitting stack probes, but allocate no stack, then
- just note that in the dump file. */
- if (flag_stack_clash_protection
- && dump_file
- && !info->push_p)
- dump_stack_clash_frame_info (NO_PROBE_NO_FRAME, false);
-
- /* Update stack and set back pointer unless this is V.4,
- for which it was done previously. */
- if (!WORLD_SAVE_P (info) && info->push_p
- && !(DEFAULT_ABI == ABI_V4 || crtl->calls_eh_return))
- {
- rtx ptr_reg = NULL;
- int ptr_off = 0;
-
- /* If saving altivec regs we need to be able to address all save
- locations using a 16-bit offset. */
- if ((strategy & SAVE_INLINE_VRS) == 0
- || (info->altivec_size != 0
- && (info->altivec_save_offset + info->altivec_size - 16
- + info->total_size - frame_off) > 32767)
- || (info->vrsave_size != 0
- && (info->vrsave_save_offset
- + info->total_size - frame_off) > 32767))
- {
- int sel = SAVRES_SAVE | SAVRES_VR;
- unsigned ptr_regno = ptr_regno_for_savres (sel);
-
- if (using_static_chain_p
- && ptr_regno == STATIC_CHAIN_REGNUM)
- ptr_regno = 12;
- if (REGNO (frame_reg_rtx) != ptr_regno)
- START_USE (ptr_regno);
- ptr_reg = gen_rtx_REG (Pmode, ptr_regno);
- frame_reg_rtx = ptr_reg;
- ptr_off = info->altivec_save_offset + info->altivec_size;
- frame_off = -ptr_off;
- }
- else if (REGNO (frame_reg_rtx) == 1)
- frame_off = info->total_size;
- sp_adjust = rs6000_emit_allocate_stack (info->total_size,
- ptr_reg, ptr_off);
- if (REGNO (frame_reg_rtx) == 12)
- sp_adjust = 0;
- sp_off = info->total_size;
- if (frame_reg_rtx != sp_reg_rtx)
- rs6000_emit_stack_tie (frame_reg_rtx, false);
- }
-
- /* Set frame pointer, if needed. */
- if (frame_pointer_needed)
- {
- insn = emit_move_insn (gen_rtx_REG (Pmode, HARD_FRAME_POINTER_REGNUM),
- sp_reg_rtx);
- RTX_FRAME_RELATED_P (insn) = 1;
- }
-
- /* Save AltiVec registers if needed. Save here because the red zone does
- not always include AltiVec registers. */
- if (!WORLD_SAVE_P (info)
- && info->altivec_size != 0 && (strategy & SAVE_INLINE_VRS) == 0)
- {
- int end_save = info->altivec_save_offset + info->altivec_size;
- int ptr_off;
- /* Oddly, the vector save/restore functions point r0 at the end
- of the save area, then use r11 or r12 to load offsets for
- [reg+reg] addressing. */
- rtx ptr_reg = gen_rtx_REG (Pmode, 0);
- int scratch_regno = ptr_regno_for_savres (SAVRES_SAVE | SAVRES_VR);
- rtx scratch_reg = gen_rtx_REG (Pmode, scratch_regno);
-
- gcc_checking_assert (scratch_regno == 11 || scratch_regno == 12);
- NOT_INUSE (0);
- if (scratch_regno == 12)
- sp_adjust = 0;
- if (end_save + frame_off != 0)
- {
- rtx offset = GEN_INT (end_save + frame_off);
-
- emit_insn (gen_add3_insn (ptr_reg, frame_reg_rtx, offset));
- }
- else
- emit_move_insn (ptr_reg, frame_reg_rtx);
-
- ptr_off = -end_save;
- insn = rs6000_emit_savres_rtx (info, scratch_reg,
- info->altivec_save_offset + ptr_off,
- 0, V4SImode, SAVRES_SAVE | SAVRES_VR);
- rs6000_frame_related (insn, scratch_reg, sp_off - ptr_off,
- NULL_RTX, NULL_RTX);
- if (REGNO (frame_reg_rtx) == REGNO (scratch_reg))
- {
- /* The oddity mentioned above clobbered our frame reg. */
- emit_move_insn (frame_reg_rtx, ptr_reg);
- frame_off = ptr_off;
- }
- }
- else if (!WORLD_SAVE_P (info)
- && info->altivec_size != 0)
- {
- int i;
-
- for (i = info->first_altivec_reg_save; i <= LAST_ALTIVEC_REGNO; ++i)
- if (info->vrsave_mask & ALTIVEC_REG_BIT (i))
- {
- rtx areg, savereg, mem;
- HOST_WIDE_INT offset;
-
- offset = (info->altivec_save_offset + frame_off
- + 16 * (i - info->first_altivec_reg_save));
-
- savereg = gen_rtx_REG (V4SImode, i);
-
- if (TARGET_P9_VECTOR && quad_address_offset_p (offset))
- {
- mem = gen_frame_mem (V4SImode,
- gen_rtx_PLUS (Pmode, frame_reg_rtx,
- GEN_INT (offset)));
- insn = emit_insn (gen_rtx_SET (mem, savereg));
- areg = NULL_RTX;
- }
- else
- {
- NOT_INUSE (0);
- areg = gen_rtx_REG (Pmode, 0);
- emit_move_insn (areg, GEN_INT (offset));
-
- /* AltiVec addressing mode is [reg+reg]. */
- mem = gen_frame_mem (V4SImode,
- gen_rtx_PLUS (Pmode, frame_reg_rtx, areg));
-
- /* Rather than emitting a generic move, force use of the stvx
- instruction, which we always want on ISA 2.07 (power8) systems.
- In particular we don't want xxpermdi/stxvd2x for little
- endian. */
- insn = emit_insn (gen_altivec_stvx_v4si_internal (mem, savereg));
- }
-
- rs6000_frame_related (insn, frame_reg_rtx, sp_off - frame_off,
- areg, GEN_INT (offset));
- }
- }
-
- /* VRSAVE is a bit vector representing which AltiVec registers
- are used. The OS uses this to determine which vector
- registers to save on a context switch. We need to save
- VRSAVE on the stack frame, add whatever AltiVec registers we
- used in this function, and do the corresponding magic in the
- epilogue. */
-
- if (!WORLD_SAVE_P (info) && info->vrsave_size != 0)
- {
- /* Get VRSAVE into a GPR. Note that ABI_V4 and ABI_DARWIN might
- be using r12 as frame_reg_rtx and r11 as the static chain
- pointer for nested functions. */
- int save_regno = 12;
- if ((DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2)
- && !using_static_chain_p)
- save_regno = 11;
- else if (using_split_stack || REGNO (frame_reg_rtx) == 12)
- {
- save_regno = 11;
- if (using_static_chain_p)
- save_regno = 0;
- }
- NOT_INUSE (save_regno);
-
- emit_vrsave_prologue (info, save_regno, frame_off, frame_reg_rtx);
- }
-
- /* If we are using RS6000_PIC_OFFSET_TABLE_REGNUM, we need to set it up. */
- if (!TARGET_SINGLE_PIC_BASE
- && ((TARGET_TOC && TARGET_MINIMAL_TOC
- && !constant_pool_empty_p ())
- || (DEFAULT_ABI == ABI_V4
- && (flag_pic == 1 || (flag_pic && TARGET_SECURE_PLT))
- && df_regs_ever_live_p (RS6000_PIC_OFFSET_TABLE_REGNUM))))
- {
- /* If emit_load_toc_table will use the link register, we need to save
- it. We use R12 for this purpose because emit_load_toc_table
- can use register 0. This allows us to use a plain 'blr' to return
- from the procedure more often. */
- int save_LR_around_toc_setup = (TARGET_ELF
- && DEFAULT_ABI == ABI_V4
- && flag_pic
- && ! info->lr_save_p
- && EDGE_COUNT (EXIT_BLOCK_PTR_FOR_FN (cfun)->preds) > 0);
- if (save_LR_around_toc_setup)
- {
- rtx lr = gen_rtx_REG (Pmode, LR_REGNO);
- rtx tmp = gen_rtx_REG (Pmode, 12);
-
- sp_adjust = 0;
- insn = emit_move_insn (tmp, lr);
- RTX_FRAME_RELATED_P (insn) = 1;
-
- rs6000_emit_load_toc_table (TRUE);
-
- insn = emit_move_insn (lr, tmp);
- add_reg_note (insn, REG_CFA_RESTORE, lr);
- RTX_FRAME_RELATED_P (insn) = 1;
- }
- else
- rs6000_emit_load_toc_table (TRUE);
- }
-
-#if TARGET_MACHO
- if (!TARGET_SINGLE_PIC_BASE
- && DEFAULT_ABI == ABI_DARWIN
- && flag_pic && crtl->uses_pic_offset_table)
- {
- rtx lr = gen_rtx_REG (Pmode, LR_REGNO);
- rtx src = gen_rtx_SYMBOL_REF (Pmode, MACHOPIC_FUNCTION_BASE_NAME);
-
- /* Save and restore LR locally around this call (in R0). */
- if (!info->lr_save_p)
- emit_move_insn (gen_rtx_REG (Pmode, 0), lr);
-
- emit_insn (gen_load_macho_picbase (src));
-
- emit_move_insn (gen_rtx_REG (Pmode,
- RS6000_PIC_OFFSET_TABLE_REGNUM),
- lr);
-
- if (!info->lr_save_p)
- emit_move_insn (lr, gen_rtx_REG (Pmode, 0));
- }
-#endif
-
- /* If we need to, save the TOC register after doing the stack setup.
- Do not emit eh frame info for this save. The unwinder wants info,
- conceptually attached to instructions in this function, about
- register values in the caller of this function. This R2 may have
- already been changed from the value in the caller.
- We don't attempt to write accurate DWARF EH frame info for R2
- because code emitted by gcc for a (non-pointer) function call
- doesn't save and restore R2. Instead, R2 is managed out-of-line
- by a linker generated plt call stub when the function resides in
- a shared library. This behavior is costly to describe in DWARF,
- both in terms of the size of DWARF info and the time taken in the
- unwinder to interpret it. R2 changes, apart from the
- calls_eh_return case earlier in this function, are handled by
- linux-unwind.h frob_update_context. */
- if (rs6000_save_toc_in_prologue_p ()
- && !cfun->machine->toc_is_wrapped_separately)
- {
- rtx reg = gen_rtx_REG (reg_mode, TOC_REGNUM);
- emit_insn (gen_frame_store (reg, sp_reg_rtx, RS6000_TOC_SAVE_SLOT));
- }
-
- /* Set up the arg pointer (r12) for -fsplit-stack code. */
- if (using_split_stack && split_stack_arg_pointer_used_p ())
- emit_split_stack_prologue (info, sp_adjust, frame_off, frame_reg_rtx);
-}
-
-/* Output .extern statements for the save/restore routines we use. */
-
-static void
-rs6000_output_savres_externs (FILE *file)
-{
- rs6000_stack_t *info = rs6000_stack_info ();
-
- if (TARGET_DEBUG_STACK)
- debug_stack_info (info);
-
- /* Write .extern for any function we will call to save and restore
- fp values. */
- if (info->first_fp_reg_save < 64
- && !TARGET_MACHO
- && !TARGET_ELF)
- {
- char *name;
- int regno = info->first_fp_reg_save - 32;
-
- if ((info->savres_strategy & SAVE_INLINE_FPRS) == 0)
- {
- bool lr = (info->savres_strategy & SAVE_NOINLINE_FPRS_SAVES_LR) != 0;
- int sel = SAVRES_SAVE | SAVRES_FPR | (lr ? SAVRES_LR : 0);
- name = rs6000_savres_routine_name (regno, sel);
- fprintf (file, "\t.extern %s\n", name);
- }
- if ((info->savres_strategy & REST_INLINE_FPRS) == 0)
- {
- bool lr = (info->savres_strategy
- & REST_NOINLINE_FPRS_DOESNT_RESTORE_LR) == 0;
- int sel = SAVRES_FPR | (lr ? SAVRES_LR : 0);
- name = rs6000_savres_routine_name (regno, sel);
- fprintf (file, "\t.extern %s\n", name);
- }
- }
-}
-
-/* Write function prologue. */
-
-static void
-rs6000_output_function_prologue (FILE *file)
-{
- if (!cfun->is_thunk)
- rs6000_output_savres_externs (file);
-
- /* ELFv2 ABI r2 setup code and local entry point. This must follow
- immediately after the global entry point label. */
- if (rs6000_global_entry_point_needed_p ())
- {
- const char *name = XSTR (XEXP (DECL_RTL (current_function_decl), 0), 0);
-
- (*targetm.asm_out.internal_label) (file, "LCF", rs6000_pic_labelno);
-
- if (TARGET_CMODEL != CMODEL_LARGE)
- {
- /* In the small and medium code models, we assume the TOC is less
- 2 GB away from the text section, so it can be computed via the
- following two-instruction sequence. */
- char buf[256];
-
- ASM_GENERATE_INTERNAL_LABEL (buf, "LCF", rs6000_pic_labelno);
- fprintf (file, "0:\taddis 2,12,.TOC.-");
- assemble_name (file, buf);
- fprintf (file, "@ha\n");
- fprintf (file, "\taddi 2,2,.TOC.-");
- assemble_name (file, buf);
- fprintf (file, "@l\n");
- }
- else
- {
- /* In the large code model, we allow arbitrary offsets between the
- TOC and the text section, so we have to load the offset from
- memory. The data field is emitted directly before the global
- entry point in rs6000_elf_declare_function_name. */
- char buf[256];
-
-#ifdef HAVE_AS_ENTRY_MARKERS
- /* If supported by the linker, emit a marker relocation. If the
- total code size of the final executable or shared library
- happens to fit into 2 GB after all, the linker will replace
- this code sequence with the sequence for the small or medium
- code model. */
- fprintf (file, "\t.reloc .,R_PPC64_ENTRY\n");
-#endif
- fprintf (file, "\tld 2,");
- ASM_GENERATE_INTERNAL_LABEL (buf, "LCL", rs6000_pic_labelno);
- assemble_name (file, buf);
- fprintf (file, "-");
- ASM_GENERATE_INTERNAL_LABEL (buf, "LCF", rs6000_pic_labelno);
- assemble_name (file, buf);
- fprintf (file, "(12)\n");
- fprintf (file, "\tadd 2,2,12\n");
- }
-
- fputs ("\t.localentry\t", file);
- assemble_name (file, name);
- fputs (",.-", file);
- assemble_name (file, name);
- fputs ("\n", file);
- }
-
- /* Output -mprofile-kernel code. This needs to be done here instead of
- in output_function_profile since it must go after the ELFv2 ABI
- local entry point. */
- if (TARGET_PROFILE_KERNEL && crtl->profile)
- {
- gcc_assert (DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2);
- gcc_assert (!TARGET_32BIT);
-
- asm_fprintf (file, "\tmflr %s\n", reg_names[0]);
-
- /* In the ELFv2 ABI we have no compiler stack word. It must be
- the resposibility of _mcount to preserve the static chain
- register if required. */
- if (DEFAULT_ABI != ABI_ELFv2
- && cfun->static_chain_decl != NULL)
- {
- asm_fprintf (file, "\tstd %s,24(%s)\n",
- reg_names[STATIC_CHAIN_REGNUM], reg_names[1]);
- fprintf (file, "\tbl %s\n", RS6000_MCOUNT);
- asm_fprintf (file, "\tld %s,24(%s)\n",
- reg_names[STATIC_CHAIN_REGNUM], reg_names[1]);
- }
- else
- fprintf (file, "\tbl %s\n", RS6000_MCOUNT);
- }
-
- rs6000_pic_labelno++;
-}
-
-/* -mprofile-kernel code calls mcount before the function prolog,
- so a profiled leaf function should stay a leaf function. */
-static bool
-rs6000_keep_leaf_when_profiled ()
-{
- return TARGET_PROFILE_KERNEL;
-}
-
-/* Non-zero if vmx regs are restored before the frame pop, zero if
- we restore after the pop when possible. */
-#define ALWAYS_RESTORE_ALTIVEC_BEFORE_POP 0
-
-/* Restoring cr is a two step process: loading a reg from the frame
- save, then moving the reg to cr. For ABI_V4 we must let the
- unwinder know that the stack location is no longer valid at or
- before the stack deallocation, but we can't emit a cfa_restore for
- cr at the stack deallocation like we do for other registers.
- The trouble is that it is possible for the move to cr to be
- scheduled after the stack deallocation. So say exactly where cr
- is located on each of the two insns. */
-
-static rtx
-load_cr_save (int regno, rtx frame_reg_rtx, int offset, bool exit_func)
-{
- rtx mem = gen_frame_mem_offset (SImode, frame_reg_rtx, offset);
- rtx reg = gen_rtx_REG (SImode, regno);
- rtx_insn *insn = emit_move_insn (reg, mem);
-
- if (!exit_func && DEFAULT_ABI == ABI_V4)
- {
- rtx cr = gen_rtx_REG (SImode, CR2_REGNO);
- rtx set = gen_rtx_SET (reg, cr);
-
- add_reg_note (insn, REG_CFA_REGISTER, set);
- RTX_FRAME_RELATED_P (insn) = 1;
- }
- return reg;
-}
-
-/* Reload CR from REG. */
-
-static void
-restore_saved_cr (rtx reg, int using_mfcr_multiple, bool exit_func)
-{
- int count = 0;
- int i;
-
- if (using_mfcr_multiple)
- {
- for (i = 0; i < 8; i++)
- if (save_reg_p (CR0_REGNO + i))
- count++;
- gcc_assert (count);
- }
-
- if (using_mfcr_multiple && count > 1)
- {
- rtx_insn *insn;
- rtvec p;
- int ndx;
-
- p = rtvec_alloc (count);
-
- ndx = 0;
- for (i = 0; i < 8; i++)
- if (save_reg_p (CR0_REGNO + i))
- {
- rtvec r = rtvec_alloc (2);
- RTVEC_ELT (r, 0) = reg;
- RTVEC_ELT (r, 1) = GEN_INT (1 << (7-i));
- RTVEC_ELT (p, ndx) =
- gen_rtx_SET (gen_rtx_REG (CCmode, CR0_REGNO + i),
- gen_rtx_UNSPEC (CCmode, r, UNSPEC_MOVESI_TO_CR));
- ndx++;
- }
- insn = emit_insn (gen_rtx_PARALLEL (VOIDmode, p));
- gcc_assert (ndx == count);
-
- /* For the ELFv2 ABI we generate a CFA_RESTORE for each
- CR field separately. */
- if (!exit_func && DEFAULT_ABI == ABI_ELFv2 && flag_shrink_wrap)
- {
- for (i = 0; i < 8; i++)
- if (save_reg_p (CR0_REGNO + i))
- add_reg_note (insn, REG_CFA_RESTORE,
- gen_rtx_REG (SImode, CR0_REGNO + i));
-
- RTX_FRAME_RELATED_P (insn) = 1;
- }
- }
- else
- for (i = 0; i < 8; i++)
- if (save_reg_p (CR0_REGNO + i))
- {
- rtx insn = emit_insn (gen_movsi_to_cr_one
- (gen_rtx_REG (CCmode, CR0_REGNO + i), reg));
-
- /* For the ELFv2 ABI we generate a CFA_RESTORE for each
- CR field separately, attached to the insn that in fact
- restores this particular CR field. */
- if (!exit_func && DEFAULT_ABI == ABI_ELFv2 && flag_shrink_wrap)
- {
- add_reg_note (insn, REG_CFA_RESTORE,
- gen_rtx_REG (SImode, CR0_REGNO + i));
-
- RTX_FRAME_RELATED_P (insn) = 1;
- }
- }
-
- /* For other ABIs, we just generate a single CFA_RESTORE for CR2. */
- if (!exit_func && DEFAULT_ABI != ABI_ELFv2
- && (DEFAULT_ABI == ABI_V4 || flag_shrink_wrap))
- {
- rtx_insn *insn = get_last_insn ();
- rtx cr = gen_rtx_REG (SImode, CR2_REGNO);
-
- add_reg_note (insn, REG_CFA_RESTORE, cr);
- RTX_FRAME_RELATED_P (insn) = 1;
- }
-}
-
-/* Like cr, the move to lr instruction can be scheduled after the
- stack deallocation, but unlike cr, its stack frame save is still
- valid. So we only need to emit the cfa_restore on the correct
- instruction. */
-
-static void
-load_lr_save (int regno, rtx frame_reg_rtx, int offset)
-{
- rtx mem = gen_frame_mem_offset (Pmode, frame_reg_rtx, offset);
- rtx reg = gen_rtx_REG (Pmode, regno);
-
- emit_move_insn (reg, mem);
-}
-
-static void
-restore_saved_lr (int regno, bool exit_func)
-{
- rtx reg = gen_rtx_REG (Pmode, regno);
- rtx lr = gen_rtx_REG (Pmode, LR_REGNO);
- rtx_insn *insn = emit_move_insn (lr, reg);
-
- if (!exit_func && flag_shrink_wrap)
- {
- add_reg_note (insn, REG_CFA_RESTORE, lr);
- RTX_FRAME_RELATED_P (insn) = 1;
- }
-}
-
-static rtx
-add_crlr_cfa_restore (const rs6000_stack_t *info, rtx cfa_restores)
-{
- if (DEFAULT_ABI == ABI_ELFv2)
- {
- int i;
- for (i = 0; i < 8; i++)
- if (save_reg_p (CR0_REGNO + i))
- {
- rtx cr = gen_rtx_REG (SImode, CR0_REGNO + i);
- cfa_restores = alloc_reg_note (REG_CFA_RESTORE, cr,
- cfa_restores);
- }
- }
- else if (info->cr_save_p)
- cfa_restores = alloc_reg_note (REG_CFA_RESTORE,
- gen_rtx_REG (SImode, CR2_REGNO),
- cfa_restores);
-
- if (info->lr_save_p)
- cfa_restores = alloc_reg_note (REG_CFA_RESTORE,
- gen_rtx_REG (Pmode, LR_REGNO),
- cfa_restores);
- return cfa_restores;
-}
-
-/* Return true if OFFSET from stack pointer can be clobbered by signals.
- V.4 doesn't have any stack cushion, AIX ABIs have 220 or 288 bytes
- below stack pointer not cloberred by signals. */
-
-static inline bool
-offset_below_red_zone_p (HOST_WIDE_INT offset)
-{
- return offset < (DEFAULT_ABI == ABI_V4
- ? 0
- : TARGET_32BIT ? -220 : -288);
-}
-
-/* Append CFA_RESTORES to any existing REG_NOTES on the last insn. */
-
-static void
-emit_cfa_restores (rtx cfa_restores)
-{
- rtx_insn *insn = get_last_insn ();
- rtx *loc = &REG_NOTES (insn);
-
- while (*loc)
- loc = &XEXP (*loc, 1);
- *loc = cfa_restores;
- RTX_FRAME_RELATED_P (insn) = 1;
-}
-
-/* Emit function epilogue as insns. */
-
-void
-rs6000_emit_epilogue (int sibcall)
-{
- rs6000_stack_t *info;
- int restoring_GPRs_inline;
- int restoring_FPRs_inline;
- int using_load_multiple;
- int using_mtcr_multiple;
- int use_backchain_to_restore_sp;
- int restore_lr;
- int strategy;
- HOST_WIDE_INT frame_off = 0;
- rtx sp_reg_rtx = gen_rtx_REG (Pmode, 1);
- rtx frame_reg_rtx = sp_reg_rtx;
- rtx cfa_restores = NULL_RTX;
- rtx insn;
- rtx cr_save_reg = NULL_RTX;
- machine_mode reg_mode = Pmode;
- int reg_size = TARGET_32BIT ? 4 : 8;
- machine_mode fp_reg_mode = TARGET_HARD_FLOAT ? DFmode : SFmode;
- int fp_reg_size = 8;
- int i;
- bool exit_func;
- unsigned ptr_regno;
-
- info = rs6000_stack_info ();
-
- strategy = info->savres_strategy;
- using_load_multiple = strategy & REST_MULTIPLE;
- restoring_FPRs_inline = sibcall || (strategy & REST_INLINE_FPRS);
- restoring_GPRs_inline = sibcall || (strategy & REST_INLINE_GPRS);
- using_mtcr_multiple = (rs6000_tune == PROCESSOR_PPC601
- || rs6000_tune == PROCESSOR_PPC603
- || rs6000_tune == PROCESSOR_PPC750
- || optimize_size);
- /* Restore via the backchain when we have a large frame, since this
- is more efficient than an addis, addi pair. The second condition
- here will not trigger at the moment; We don't actually need a
- frame pointer for alloca, but the generic parts of the compiler
- give us one anyway. */
- use_backchain_to_restore_sp = (info->total_size + (info->lr_save_p
- ? info->lr_save_offset
- : 0) > 32767
- || (cfun->calls_alloca
- && !frame_pointer_needed));
- restore_lr = (info->lr_save_p
- && (restoring_FPRs_inline
- || (strategy & REST_NOINLINE_FPRS_DOESNT_RESTORE_LR))
- && (restoring_GPRs_inline
- || info->first_fp_reg_save < 64)
- && !cfun->machine->lr_is_wrapped_separately);
-
-
- if (WORLD_SAVE_P (info))
- {
- int i, j;
- char rname[30];
- const char *alloc_rname;
- rtvec p;
-
- /* eh_rest_world_r10 will return to the location saved in the LR
- stack slot (which is not likely to be our caller.)
- Input: R10 -- stack adjustment. Clobbers R0, R11, R12, R7, R8.
- rest_world is similar, except any R10 parameter is ignored.
- The exception-handling stuff that was here in 2.95 is no
- longer necessary. */
-
- p = rtvec_alloc (9
- + 32 - info->first_gp_reg_save
- + LAST_ALTIVEC_REGNO + 1 - info->first_altivec_reg_save
- + 63 + 1 - info->first_fp_reg_save);
-
- strcpy (rname, ((crtl->calls_eh_return) ?
- "*eh_rest_world_r10" : "*rest_world"));
- alloc_rname = ggc_strdup (rname);
-
- j = 0;
- RTVEC_ELT (p, j++) = ret_rtx;
- RTVEC_ELT (p, j++)
- = gen_rtx_USE (VOIDmode, gen_rtx_SYMBOL_REF (Pmode, alloc_rname));
- /* The instruction pattern requires a clobber here;
- it is shared with the restVEC helper. */
- RTVEC_ELT (p, j++) = gen_hard_reg_clobber (Pmode, 11);
-
- {
- /* CR register traditionally saved as CR2. */
- rtx reg = gen_rtx_REG (SImode, CR2_REGNO);
- RTVEC_ELT (p, j++)
- = gen_frame_load (reg, frame_reg_rtx, info->cr_save_offset);
- if (flag_shrink_wrap)
- {
- cfa_restores = alloc_reg_note (REG_CFA_RESTORE,
- gen_rtx_REG (Pmode, LR_REGNO),
- cfa_restores);
- cfa_restores = alloc_reg_note (REG_CFA_RESTORE, reg, cfa_restores);
- }
- }
-
- for (i = 0; i < 32 - info->first_gp_reg_save; i++)
- {
- rtx reg = gen_rtx_REG (reg_mode, info->first_gp_reg_save + i);
- RTVEC_ELT (p, j++)
- = gen_frame_load (reg,
- frame_reg_rtx, info->gp_save_offset + reg_size * i);
- if (flag_shrink_wrap
- && save_reg_p (info->first_gp_reg_save + i))
- cfa_restores = alloc_reg_note (REG_CFA_RESTORE, reg, cfa_restores);
- }
- for (i = 0; info->first_altivec_reg_save + i <= LAST_ALTIVEC_REGNO; i++)
- {
- rtx reg = gen_rtx_REG (V4SImode, info->first_altivec_reg_save + i);
- RTVEC_ELT (p, j++)
- = gen_frame_load (reg,
- frame_reg_rtx, info->altivec_save_offset + 16 * i);
- if (flag_shrink_wrap
- && save_reg_p (info->first_altivec_reg_save + i))
- cfa_restores = alloc_reg_note (REG_CFA_RESTORE, reg, cfa_restores);
- }
- for (i = 0; info->first_fp_reg_save + i <= 63; i++)
- {
- rtx reg = gen_rtx_REG (TARGET_HARD_FLOAT ? DFmode : SFmode,
- info->first_fp_reg_save + i);
- RTVEC_ELT (p, j++)
- = gen_frame_load (reg, frame_reg_rtx, info->fp_save_offset + 8 * i);
- if (flag_shrink_wrap
- && save_reg_p (info->first_fp_reg_save + i))
- cfa_restores = alloc_reg_note (REG_CFA_RESTORE, reg, cfa_restores);
- }
- RTVEC_ELT (p, j++) = gen_hard_reg_clobber (Pmode, 0);
- RTVEC_ELT (p, j++) = gen_hard_reg_clobber (SImode, 12);
- RTVEC_ELT (p, j++) = gen_hard_reg_clobber (SImode, 7);
- RTVEC_ELT (p, j++) = gen_hard_reg_clobber (SImode, 8);
- RTVEC_ELT (p, j++)
- = gen_rtx_USE (VOIDmode, gen_rtx_REG (SImode, 10));
- insn = emit_jump_insn (gen_rtx_PARALLEL (VOIDmode, p));
-
- if (flag_shrink_wrap)
- {
- REG_NOTES (insn) = cfa_restores;
- add_reg_note (insn, REG_CFA_DEF_CFA, sp_reg_rtx);
- RTX_FRAME_RELATED_P (insn) = 1;
- }
- return;
- }
-
- /* frame_reg_rtx + frame_off points to the top of this stack frame. */
- if (info->push_p)
- frame_off = info->total_size;
-
- /* Restore AltiVec registers if we must do so before adjusting the
- stack. */
- if (info->altivec_size != 0
- && (ALWAYS_RESTORE_ALTIVEC_BEFORE_POP
- || (DEFAULT_ABI != ABI_V4
- && offset_below_red_zone_p (info->altivec_save_offset))))
- {
- int i;
- int scratch_regno = ptr_regno_for_savres (SAVRES_VR);
-
- gcc_checking_assert (scratch_regno == 11 || scratch_regno == 12);
- if (use_backchain_to_restore_sp)
- {
- int frame_regno = 11;
-
- if ((strategy & REST_INLINE_VRS) == 0)
- {
- /* Of r11 and r12, select the one not clobbered by an
- out-of-line restore function for the frame register. */
- frame_regno = 11 + 12 - scratch_regno;
- }
- frame_reg_rtx = gen_rtx_REG (Pmode, frame_regno);
- emit_move_insn (frame_reg_rtx,
- gen_rtx_MEM (Pmode, sp_reg_rtx));
- frame_off = 0;
- }
- else if (frame_pointer_needed)
- frame_reg_rtx = hard_frame_pointer_rtx;
-
- if ((strategy & REST_INLINE_VRS) == 0)
- {
- int end_save = info->altivec_save_offset + info->altivec_size;
- int ptr_off;
- rtx ptr_reg = gen_rtx_REG (Pmode, 0);
- rtx scratch_reg = gen_rtx_REG (Pmode, scratch_regno);
-
- if (end_save + frame_off != 0)
- {
- rtx offset = GEN_INT (end_save + frame_off);
-
- emit_insn (gen_add3_insn (ptr_reg, frame_reg_rtx, offset));
- }
- else
- emit_move_insn (ptr_reg, frame_reg_rtx);
-
- ptr_off = -end_save;
- insn = rs6000_emit_savres_rtx (info, scratch_reg,
- info->altivec_save_offset + ptr_off,
- 0, V4SImode, SAVRES_VR);
- }
- else
- {
- for (i = info->first_altivec_reg_save; i <= LAST_ALTIVEC_REGNO; ++i)
- if (info->vrsave_mask & ALTIVEC_REG_BIT (i))
- {
- rtx addr, areg, mem, insn;
- rtx reg = gen_rtx_REG (V4SImode, i);
- HOST_WIDE_INT offset
- = (info->altivec_save_offset + frame_off
- + 16 * (i - info->first_altivec_reg_save));
-
- if (TARGET_P9_VECTOR && quad_address_offset_p (offset))
- {
- mem = gen_frame_mem (V4SImode,
- gen_rtx_PLUS (Pmode, frame_reg_rtx,
- GEN_INT (offset)));
- insn = gen_rtx_SET (reg, mem);
- }
- else
- {
- areg = gen_rtx_REG (Pmode, 0);
- emit_move_insn (areg, GEN_INT (offset));
-
- /* AltiVec addressing mode is [reg+reg]. */
- addr = gen_rtx_PLUS (Pmode, frame_reg_rtx, areg);
- mem = gen_frame_mem (V4SImode, addr);
-
- /* Rather than emitting a generic move, force use of the
- lvx instruction, which we always want. In particular we
- don't want lxvd2x/xxpermdi for little endian. */
- insn = gen_altivec_lvx_v4si_internal (reg, mem);
- }
-
- (void) emit_insn (insn);
- }
- }
-
- for (i = info->first_altivec_reg_save; i <= LAST_ALTIVEC_REGNO; ++i)
- if (((strategy & REST_INLINE_VRS) == 0
- || (info->vrsave_mask & ALTIVEC_REG_BIT (i)) != 0)
- && (flag_shrink_wrap
- || (offset_below_red_zone_p
- (info->altivec_save_offset
- + 16 * (i - info->first_altivec_reg_save))))
- && save_reg_p (i))
- {
- rtx reg = gen_rtx_REG (V4SImode, i);
- cfa_restores = alloc_reg_note (REG_CFA_RESTORE, reg, cfa_restores);
- }
- }
-
- /* Restore VRSAVE if we must do so before adjusting the stack. */
- if (info->vrsave_size != 0
- && (ALWAYS_RESTORE_ALTIVEC_BEFORE_POP
- || (DEFAULT_ABI != ABI_V4
- && offset_below_red_zone_p (info->vrsave_save_offset))))
- {
- rtx reg;
-
- if (frame_reg_rtx == sp_reg_rtx)
- {
- if (use_backchain_to_restore_sp)
- {
- frame_reg_rtx = gen_rtx_REG (Pmode, 11);
- emit_move_insn (frame_reg_rtx,
- gen_rtx_MEM (Pmode, sp_reg_rtx));
- frame_off = 0;
- }
- else if (frame_pointer_needed)
- frame_reg_rtx = hard_frame_pointer_rtx;
- }
-
- reg = gen_rtx_REG (SImode, 12);
- emit_insn (gen_frame_load (reg, frame_reg_rtx,
- info->vrsave_save_offset + frame_off));
-
- emit_insn (generate_set_vrsave (reg, info, 1));
- }
-
- insn = NULL_RTX;
- /* If we have a large stack frame, restore the old stack pointer
- using the backchain. */
- if (use_backchain_to_restore_sp)
- {
- if (frame_reg_rtx == sp_reg_rtx)
- {
- /* Under V.4, don't reset the stack pointer until after we're done
- loading the saved registers. */
- if (DEFAULT_ABI == ABI_V4)
- frame_reg_rtx = gen_rtx_REG (Pmode, 11);
-
- insn = emit_move_insn (frame_reg_rtx,
- gen_rtx_MEM (Pmode, sp_reg_rtx));
- frame_off = 0;
- }
- else if (ALWAYS_RESTORE_ALTIVEC_BEFORE_POP
- && DEFAULT_ABI == ABI_V4)
- /* frame_reg_rtx has been set up by the altivec restore. */
- ;
- else
- {
- insn = emit_move_insn (sp_reg_rtx, frame_reg_rtx);
- frame_reg_rtx = sp_reg_rtx;
- }
- }
- /* If we have a frame pointer, we can restore the old stack pointer
- from it. */
- else if (frame_pointer_needed)
- {
- frame_reg_rtx = sp_reg_rtx;
- if (DEFAULT_ABI == ABI_V4)
- frame_reg_rtx = gen_rtx_REG (Pmode, 11);
- /* Prevent reordering memory accesses against stack pointer restore. */
- else if (cfun->calls_alloca
- || offset_below_red_zone_p (-info->total_size))
- rs6000_emit_stack_tie (frame_reg_rtx, true);
-
- insn = emit_insn (gen_add3_insn (frame_reg_rtx, hard_frame_pointer_rtx,
- GEN_INT (info->total_size)));
- frame_off = 0;
- }
- else if (info->push_p
- && DEFAULT_ABI != ABI_V4
- && !crtl->calls_eh_return)
- {
- /* Prevent reordering memory accesses against stack pointer restore. */
- if (cfun->calls_alloca
- || offset_below_red_zone_p (-info->total_size))
- rs6000_emit_stack_tie (frame_reg_rtx, false);
- insn = emit_insn (gen_add3_insn (sp_reg_rtx, sp_reg_rtx,
- GEN_INT (info->total_size)));
- frame_off = 0;
- }
- if (insn && frame_reg_rtx == sp_reg_rtx)
- {
- if (cfa_restores)
- {
- REG_NOTES (insn) = cfa_restores;
- cfa_restores = NULL_RTX;
- }
- add_reg_note (insn, REG_CFA_DEF_CFA, sp_reg_rtx);
- RTX_FRAME_RELATED_P (insn) = 1;
- }
-
- /* Restore AltiVec registers if we have not done so already. */
- if (!ALWAYS_RESTORE_ALTIVEC_BEFORE_POP
- && info->altivec_size != 0
- && (DEFAULT_ABI == ABI_V4
- || !offset_below_red_zone_p (info->altivec_save_offset)))
- {
- int i;
-
- if ((strategy & REST_INLINE_VRS) == 0)
- {
- int end_save = info->altivec_save_offset + info->altivec_size;
- int ptr_off;
- rtx ptr_reg = gen_rtx_REG (Pmode, 0);
- int scratch_regno = ptr_regno_for_savres (SAVRES_VR);
- rtx scratch_reg = gen_rtx_REG (Pmode, scratch_regno);
-
- if (end_save + frame_off != 0)
- {
- rtx offset = GEN_INT (end_save + frame_off);
-
- emit_insn (gen_add3_insn (ptr_reg, frame_reg_rtx, offset));
- }
- else
- emit_move_insn (ptr_reg, frame_reg_rtx);
-
- ptr_off = -end_save;
- insn = rs6000_emit_savres_rtx (info, scratch_reg,
- info->altivec_save_offset + ptr_off,
- 0, V4SImode, SAVRES_VR);
- if (REGNO (frame_reg_rtx) == REGNO (scratch_reg))
- {
- /* Frame reg was clobbered by out-of-line save. Restore it
- from ptr_reg, and if we are calling out-of-line gpr or
- fpr restore set up the correct pointer and offset. */
- unsigned newptr_regno = 1;
- if (!restoring_GPRs_inline)
- {
- bool lr = info->gp_save_offset + info->gp_size == 0;
- int sel = SAVRES_GPR | (lr ? SAVRES_LR : 0);
- newptr_regno = ptr_regno_for_savres (sel);
- end_save = info->gp_save_offset + info->gp_size;
- }
- else if (!restoring_FPRs_inline)
- {
- bool lr = !(strategy & REST_NOINLINE_FPRS_DOESNT_RESTORE_LR);
- int sel = SAVRES_FPR | (lr ? SAVRES_LR : 0);
- newptr_regno = ptr_regno_for_savres (sel);
- end_save = info->fp_save_offset + info->fp_size;
- }
-
- if (newptr_regno != 1 && REGNO (frame_reg_rtx) != newptr_regno)
- frame_reg_rtx = gen_rtx_REG (Pmode, newptr_regno);
-
- if (end_save + ptr_off != 0)
- {
- rtx offset = GEN_INT (end_save + ptr_off);
-
- frame_off = -end_save;
- if (TARGET_32BIT)
- emit_insn (gen_addsi3_carry (frame_reg_rtx,
- ptr_reg, offset));
- else
- emit_insn (gen_adddi3_carry (frame_reg_rtx,
- ptr_reg, offset));
- }
- else
- {
- frame_off = ptr_off;
- emit_move_insn (frame_reg_rtx, ptr_reg);
- }
- }
- }
- else
- {
- for (i = info->first_altivec_reg_save; i <= LAST_ALTIVEC_REGNO; ++i)
- if (info->vrsave_mask & ALTIVEC_REG_BIT (i))
- {
- rtx addr, areg, mem, insn;
- rtx reg = gen_rtx_REG (V4SImode, i);
- HOST_WIDE_INT offset
- = (info->altivec_save_offset + frame_off
- + 16 * (i - info->first_altivec_reg_save));
-
- if (TARGET_P9_VECTOR && quad_address_offset_p (offset))
- {
- mem = gen_frame_mem (V4SImode,
- gen_rtx_PLUS (Pmode, frame_reg_rtx,
- GEN_INT (offset)));
- insn = gen_rtx_SET (reg, mem);
- }
- else
- {
- areg = gen_rtx_REG (Pmode, 0);
- emit_move_insn (areg, GEN_INT (offset));
-
- /* AltiVec addressing mode is [reg+reg]. */
- addr = gen_rtx_PLUS (Pmode, frame_reg_rtx, areg);
- mem = gen_frame_mem (V4SImode, addr);
-
- /* Rather than emitting a generic move, force use of the
- lvx instruction, which we always want. In particular we
- don't want lxvd2x/xxpermdi for little endian. */
- insn = gen_altivec_lvx_v4si_internal (reg, mem);
- }
-
- (void) emit_insn (insn);
- }
- }
-
- for (i = info->first_altivec_reg_save; i <= LAST_ALTIVEC_REGNO; ++i)
- if (((strategy & REST_INLINE_VRS) == 0
- || (info->vrsave_mask & ALTIVEC_REG_BIT (i)) != 0)
- && (DEFAULT_ABI == ABI_V4 || flag_shrink_wrap)
- && save_reg_p (i))
- {
- rtx reg = gen_rtx_REG (V4SImode, i);
- cfa_restores = alloc_reg_note (REG_CFA_RESTORE, reg, cfa_restores);
- }
- }
-
- /* Restore VRSAVE if we have not done so already. */
- if (!ALWAYS_RESTORE_ALTIVEC_BEFORE_POP
- && info->vrsave_size != 0
- && (DEFAULT_ABI == ABI_V4
- || !offset_below_red_zone_p (info->vrsave_save_offset)))
- {
- rtx reg;
-
- reg = gen_rtx_REG (SImode, 12);
- emit_insn (gen_frame_load (reg, frame_reg_rtx,
- info->vrsave_save_offset + frame_off));
-
- emit_insn (generate_set_vrsave (reg, info, 1));
- }
-
- /* If we exit by an out-of-line restore function on ABI_V4 then that
- function will deallocate the stack, so we don't need to worry
- about the unwinder restoring cr from an invalid stack frame
- location. */
- exit_func = (!restoring_FPRs_inline
- || (!restoring_GPRs_inline
- && info->first_fp_reg_save == 64));
-
- /* In the ELFv2 ABI we need to restore all call-saved CR fields from
- *separate* slots if the routine calls __builtin_eh_return, so
- that they can be independently restored by the unwinder. */
- if (DEFAULT_ABI == ABI_ELFv2 && crtl->calls_eh_return)
- {
- int i, cr_off = info->ehcr_offset;
-
- for (i = 0; i < 8; i++)
- if (!call_used_regs[CR0_REGNO + i])
- {
- rtx reg = gen_rtx_REG (SImode, 0);
- emit_insn (gen_frame_load (reg, frame_reg_rtx,
- cr_off + frame_off));
-
- insn = emit_insn (gen_movsi_to_cr_one
- (gen_rtx_REG (CCmode, CR0_REGNO + i), reg));
-
- if (!exit_func && flag_shrink_wrap)
- {
- add_reg_note (insn, REG_CFA_RESTORE,
- gen_rtx_REG (SImode, CR0_REGNO + i));
-
- RTX_FRAME_RELATED_P (insn) = 1;
- }
-
- cr_off += reg_size;
- }
- }
-
- /* Get the old lr if we saved it. If we are restoring registers
- out-of-line, then the out-of-line routines can do this for us. */
- if (restore_lr && restoring_GPRs_inline)
- load_lr_save (0, frame_reg_rtx, info->lr_save_offset + frame_off);
-
- /* Get the old cr if we saved it. */
- if (info->cr_save_p)
- {
- unsigned cr_save_regno = 12;
-
- if (!restoring_GPRs_inline)
- {
- /* Ensure we don't use the register used by the out-of-line
- gpr register restore below. */
- bool lr = info->gp_save_offset + info->gp_size == 0;
- int sel = SAVRES_GPR | (lr ? SAVRES_LR : 0);
- int gpr_ptr_regno = ptr_regno_for_savres (sel);
-
- if (gpr_ptr_regno == 12)
- cr_save_regno = 11;
- gcc_checking_assert (REGNO (frame_reg_rtx) != cr_save_regno);
- }
- else if (REGNO (frame_reg_rtx) == 12)
- cr_save_regno = 11;
-
- cr_save_reg = load_cr_save (cr_save_regno, frame_reg_rtx,
- info->cr_save_offset + frame_off,
- exit_func);
- }
-
- /* Set LR here to try to overlap restores below. */
- if (restore_lr && restoring_GPRs_inline)
- restore_saved_lr (0, exit_func);
-
- /* Load exception handler data registers, if needed. */
- if (crtl->calls_eh_return)
- {
- unsigned int i, regno;
-
- if (TARGET_AIX)
- {
- rtx reg = gen_rtx_REG (reg_mode, 2);
- emit_insn (gen_frame_load (reg, frame_reg_rtx,
- frame_off + RS6000_TOC_SAVE_SLOT));
- }
-
- for (i = 0; ; ++i)
- {
- rtx mem;
-
- regno = EH_RETURN_DATA_REGNO (i);
- if (regno == INVALID_REGNUM)
- break;
-
- mem = gen_frame_mem_offset (reg_mode, frame_reg_rtx,
- info->ehrd_offset + frame_off
- + reg_size * (int) i);
-
- emit_move_insn (gen_rtx_REG (reg_mode, regno), mem);
- }
- }
-
- /* Restore GPRs. This is done as a PARALLEL if we are using
- the load-multiple instructions. */
- if (!restoring_GPRs_inline)
- {
- /* We are jumping to an out-of-line function. */
- rtx ptr_reg;
- int end_save = info->gp_save_offset + info->gp_size;
- bool can_use_exit = end_save == 0;
- int sel = SAVRES_GPR | (can_use_exit ? SAVRES_LR : 0);
- int ptr_off;
-
- /* Emit stack reset code if we need it. */
- ptr_regno = ptr_regno_for_savres (sel);
- ptr_reg = gen_rtx_REG (Pmode, ptr_regno);
- if (can_use_exit)
- rs6000_emit_stack_reset (frame_reg_rtx, frame_off, ptr_regno);
- else if (end_save + frame_off != 0)
- emit_insn (gen_add3_insn (ptr_reg, frame_reg_rtx,
- GEN_INT (end_save + frame_off)));
- else if (REGNO (frame_reg_rtx) != ptr_regno)
- emit_move_insn (ptr_reg, frame_reg_rtx);
- if (REGNO (frame_reg_rtx) == ptr_regno)
- frame_off = -end_save;
-
- if (can_use_exit && info->cr_save_p)
- restore_saved_cr (cr_save_reg, using_mtcr_multiple, true);
-
- ptr_off = -end_save;
- rs6000_emit_savres_rtx (info, ptr_reg,
- info->gp_save_offset + ptr_off,
- info->lr_save_offset + ptr_off,
- reg_mode, sel);
- }
- else if (using_load_multiple)
- {
- rtvec p;
- p = rtvec_alloc (32 - info->first_gp_reg_save);
- for (i = 0; i < 32 - info->first_gp_reg_save; i++)
- RTVEC_ELT (p, i)
- = gen_frame_load (gen_rtx_REG (reg_mode, info->first_gp_reg_save + i),
- frame_reg_rtx,
- info->gp_save_offset + frame_off + reg_size * i);
- emit_insn (gen_rtx_PARALLEL (VOIDmode, p));
- }
- else
- {
- int offset = info->gp_save_offset + frame_off;
- for (i = info->first_gp_reg_save; i < 32; i++)
- {
- if (save_reg_p (i)
- && !cfun->machine->gpr_is_wrapped_separately[i])
- {
- rtx reg = gen_rtx_REG (reg_mode, i);
- emit_insn (gen_frame_load (reg, frame_reg_rtx, offset));
- }
-
- offset += reg_size;
- }
- }
-
- if (DEFAULT_ABI == ABI_V4 || flag_shrink_wrap)
- {
- /* If the frame pointer was used then we can't delay emitting
- a REG_CFA_DEF_CFA note. This must happen on the insn that
- restores the frame pointer, r31. We may have already emitted
- a REG_CFA_DEF_CFA note, but that's OK; A duplicate is
- discarded by dwarf2cfi.c/dwarf2out.c, and in any case would
- be harmless if emitted. */
- if (frame_pointer_needed)
- {
- insn = get_last_insn ();
- add_reg_note (insn, REG_CFA_DEF_CFA,
- plus_constant (Pmode, frame_reg_rtx, frame_off));
- RTX_FRAME_RELATED_P (insn) = 1;
- }
-
- /* Set up cfa_restores. We always need these when
- shrink-wrapping. If not shrink-wrapping then we only need
- the cfa_restore when the stack location is no longer valid.
- The cfa_restores must be emitted on or before the insn that
- invalidates the stack, and of course must not be emitted
- before the insn that actually does the restore. The latter
- is why it is a bad idea to emit the cfa_restores as a group
- on the last instruction here that actually does a restore:
- That insn may be reordered with respect to others doing
- restores. */
- if (flag_shrink_wrap
- && !restoring_GPRs_inline
- && info->first_fp_reg_save == 64)
- cfa_restores = add_crlr_cfa_restore (info, cfa_restores);
-
- for (i = info->first_gp_reg_save; i < 32; i++)
- if (save_reg_p (i)
- && !cfun->machine->gpr_is_wrapped_separately[i])
- {
- rtx reg = gen_rtx_REG (reg_mode, i);
- cfa_restores = alloc_reg_note (REG_CFA_RESTORE, reg, cfa_restores);
- }
- }
-
- if (!restoring_GPRs_inline
- && info->first_fp_reg_save == 64)
- {
- /* We are jumping to an out-of-line function. */
- if (cfa_restores)
- emit_cfa_restores (cfa_restores);
- return;
- }
-
- if (restore_lr && !restoring_GPRs_inline)
- {
- load_lr_save (0, frame_reg_rtx, info->lr_save_offset + frame_off);
- restore_saved_lr (0, exit_func);
- }
-
- /* Restore fpr's if we need to do it without calling a function. */
- if (restoring_FPRs_inline)
- {
- int offset = info->fp_save_offset + frame_off;
- for (i = info->first_fp_reg_save; i < 64; i++)
- {
- if (save_reg_p (i)
- && !cfun->machine->fpr_is_wrapped_separately[i - 32])
- {
- rtx reg = gen_rtx_REG (fp_reg_mode, i);
- emit_insn (gen_frame_load (reg, frame_reg_rtx, offset));
- if (DEFAULT_ABI == ABI_V4 || flag_shrink_wrap)
- cfa_restores = alloc_reg_note (REG_CFA_RESTORE, reg,
- cfa_restores);
- }
-
- offset += fp_reg_size;
- }
- }
-
- /* If we saved cr, restore it here. Just those that were used. */
- if (info->cr_save_p)
- restore_saved_cr (cr_save_reg, using_mtcr_multiple, exit_func);
-
- /* If this is V.4, unwind the stack pointer after all of the loads
- have been done, or set up r11 if we are restoring fp out of line. */
- ptr_regno = 1;
- if (!restoring_FPRs_inline)
- {
- bool lr = (strategy & REST_NOINLINE_FPRS_DOESNT_RESTORE_LR) == 0;
- int sel = SAVRES_FPR | (lr ? SAVRES_LR : 0);
- ptr_regno = ptr_regno_for_savres (sel);
- }
-
- insn = rs6000_emit_stack_reset (frame_reg_rtx, frame_off, ptr_regno);
- if (REGNO (frame_reg_rtx) == ptr_regno)
- frame_off = 0;
-
- if (insn && restoring_FPRs_inline)
- {
- if (cfa_restores)
- {
- REG_NOTES (insn) = cfa_restores;
- cfa_restores = NULL_RTX;
- }
- add_reg_note (insn, REG_CFA_DEF_CFA, sp_reg_rtx);
- RTX_FRAME_RELATED_P (insn) = 1;
- }
-
- if (crtl->calls_eh_return)
- {
- rtx sa = EH_RETURN_STACKADJ_RTX;
- emit_insn (gen_add3_insn (sp_reg_rtx, sp_reg_rtx, sa));
- }
-
- if (!sibcall && restoring_FPRs_inline)
- {
- if (cfa_restores)
- {
- /* We can't hang the cfa_restores off a simple return,
- since the shrink-wrap code sometimes uses an existing
- return. This means there might be a path from
- pre-prologue code to this return, and dwarf2cfi code
- wants the eh_frame unwinder state to be the same on
- all paths to any point. So we need to emit the
- cfa_restores before the return. For -m64 we really
- don't need epilogue cfa_restores at all, except for
- this irritating dwarf2cfi with shrink-wrap
- requirement; The stack red-zone means eh_frame info
- from the prologue telling the unwinder to restore
- from the stack is perfectly good right to the end of
- the function. */
- emit_insn (gen_blockage ());
- emit_cfa_restores (cfa_restores);
- cfa_restores = NULL_RTX;
- }
-
- emit_jump_insn (targetm.gen_simple_return ());
- }
-
- if (!sibcall && !restoring_FPRs_inline)
- {
- bool lr = (strategy & REST_NOINLINE_FPRS_DOESNT_RESTORE_LR) == 0;
- rtvec p = rtvec_alloc (3 + !!lr + 64 - info->first_fp_reg_save);
- int elt = 0;
- RTVEC_ELT (p, elt++) = ret_rtx;
- if (lr)
- RTVEC_ELT (p, elt++) = gen_hard_reg_clobber (Pmode, LR_REGNO);
-
- /* We have to restore more than two FP registers, so branch to the
- restore function. It will return to our caller. */
- int i;
- int reg;
- rtx sym;
-
- if (flag_shrink_wrap)
- cfa_restores = add_crlr_cfa_restore (info, cfa_restores);
-
- sym = rs6000_savres_routine_sym (info, SAVRES_FPR | (lr ? SAVRES_LR : 0));
- RTVEC_ELT (p, elt++) = gen_rtx_USE (VOIDmode, sym);
- reg = (DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2)? 1 : 11;
- RTVEC_ELT (p, elt++) = gen_rtx_USE (VOIDmode, gen_rtx_REG (Pmode, reg));
-
- for (i = 0; i < 64 - info->first_fp_reg_save; i++)
- {
- rtx reg = gen_rtx_REG (DFmode, info->first_fp_reg_save + i);
-
- RTVEC_ELT (p, elt++)
- = gen_frame_load (reg, sp_reg_rtx, info->fp_save_offset + 8 * i);
- if (flag_shrink_wrap
- && save_reg_p (info->first_fp_reg_save + i))
- cfa_restores = alloc_reg_note (REG_CFA_RESTORE, reg, cfa_restores);
- }
-
- emit_jump_insn (gen_rtx_PARALLEL (VOIDmode, p));
- }
-
- if (cfa_restores)
- {
- if (sibcall)
- /* Ensure the cfa_restores are hung off an insn that won't
- be reordered above other restores. */
- emit_insn (gen_blockage ());
-
- emit_cfa_restores (cfa_restores);
- }
-}
-
-/* Write function epilogue. */
-
-static void
-rs6000_output_function_epilogue (FILE *file)
-{
-#if TARGET_MACHO
- macho_branch_islands ();
-
- {
- rtx_insn *insn = get_last_insn ();
- rtx_insn *deleted_debug_label = NULL;
-
- /* Mach-O doesn't support labels at the end of objects, so if
- it looks like we might want one, take special action.
-
- First, collect any sequence of deleted debug labels. */
- while (insn
- && NOTE_P (insn)
- && NOTE_KIND (insn) != NOTE_INSN_DELETED_LABEL)
- {
- /* Don't insert a nop for NOTE_INSN_DELETED_DEBUG_LABEL
- notes only, instead set their CODE_LABEL_NUMBER to -1,
- otherwise there would be code generation differences
- in between -g and -g0. */
- if (NOTE_P (insn) && NOTE_KIND (insn) == NOTE_INSN_DELETED_DEBUG_LABEL)
- deleted_debug_label = insn;
- insn = PREV_INSN (insn);
- }
-
- /* Second, if we have:
- label:
- barrier
- then this needs to be detected, so skip past the barrier. */
-
- if (insn && BARRIER_P (insn))
- insn = PREV_INSN (insn);
-
- /* Up to now we've only seen notes or barriers. */
- if (insn)
- {
- if (LABEL_P (insn)
- || (NOTE_P (insn)
- && NOTE_KIND (insn) == NOTE_INSN_DELETED_LABEL))
- /* Trailing label: <barrier>. */
- fputs ("\tnop\n", file);
- else
- {
- /* Lastly, see if we have a completely empty function body. */
- while (insn && ! INSN_P (insn))
- insn = PREV_INSN (insn);
- /* If we don't find any insns, we've got an empty function body;
- I.e. completely empty - without a return or branch. This is
- taken as the case where a function body has been removed
- because it contains an inline __builtin_unreachable(). GCC
- states that reaching __builtin_unreachable() means UB so we're
- not obliged to do anything special; however, we want
- non-zero-sized function bodies. To meet this, and help the
- user out, let's trap the case. */
- if (insn == NULL)
- fputs ("\ttrap\n", file);
- }
- }
- else if (deleted_debug_label)
- for (insn = deleted_debug_label; insn; insn = NEXT_INSN (insn))
- if (NOTE_KIND (insn) == NOTE_INSN_DELETED_DEBUG_LABEL)
- CODE_LABEL_NUMBER (insn) = -1;
- }
-#endif
-
- /* Output a traceback table here. See /usr/include/sys/debug.h for info
- on its format.
-
- We don't output a traceback table if -finhibit-size-directive was
- used. The documentation for -finhibit-size-directive reads
- ``don't output a @code{.size} assembler directive, or anything
- else that would cause trouble if the function is split in the
- middle, and the two halves are placed at locations far apart in
- memory.'' The traceback table has this property, since it
- includes the offset from the start of the function to the
- traceback table itself.
-
- System V.4 Powerpc's (and the embedded ABI derived from it) use a
- different traceback table. */
- if ((DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2)
- && ! flag_inhibit_size_directive
- && rs6000_traceback != traceback_none && !cfun->is_thunk)
- {
- const char *fname = NULL;
- const char *language_string = lang_hooks.name;
- int fixed_parms = 0, float_parms = 0, parm_info = 0;
- int i;
- int optional_tbtab;
- rs6000_stack_t *info = rs6000_stack_info ();
-
- if (rs6000_traceback == traceback_full)
- optional_tbtab = 1;
- else if (rs6000_traceback == traceback_part)
- optional_tbtab = 0;
- else
- optional_tbtab = !optimize_size && !TARGET_ELF;
-
- if (optional_tbtab)
- {
- fname = XSTR (XEXP (DECL_RTL (current_function_decl), 0), 0);
- while (*fname == '.') /* V.4 encodes . in the name */
- fname++;
-
- /* Need label immediately before tbtab, so we can compute
- its offset from the function start. */
- ASM_OUTPUT_INTERNAL_LABEL_PREFIX (file, "LT");
- ASM_OUTPUT_LABEL (file, fname);
- }
-
- /* The .tbtab pseudo-op can only be used for the first eight
- expressions, since it can't handle the possibly variable
- length fields that follow. However, if you omit the optional
- fields, the assembler outputs zeros for all optional fields
- anyways, giving each variable length field is minimum length
- (as defined in sys/debug.h). Thus we cannot use the .tbtab
- pseudo-op at all. */
-
- /* An all-zero word flags the start of the tbtab, for debuggers
- that have to find it by searching forward from the entry
- point or from the current pc. */
- fputs ("\t.long 0\n", file);
-
- /* Tbtab format type. Use format type 0. */
- fputs ("\t.byte 0,", file);
-
- /* Language type. Unfortunately, there does not seem to be any
- official way to discover the language being compiled, so we
- use language_string.
- C is 0. Fortran is 1. Ada is 3. C++ is 9.
- Java is 13. Objective-C is 14. Objective-C++ isn't assigned
- a number, so for now use 9. LTO, Go, D, and JIT aren't assigned
- numbers either, so for now use 0. */
- if (lang_GNU_C ()
- || ! strcmp (language_string, "GNU GIMPLE")
- || ! strcmp (language_string, "GNU Go")
- || ! strcmp (language_string, "GNU D")
- || ! strcmp (language_string, "libgccjit"))
- i = 0;
- else if (! strcmp (language_string, "GNU F77")
- || lang_GNU_Fortran ())
- i = 1;
- else if (! strcmp (language_string, "GNU Ada"))
- i = 3;
- else if (lang_GNU_CXX ()
- || ! strcmp (language_string, "GNU Objective-C++"))
- i = 9;
- else if (! strcmp (language_string, "GNU Java"))
- i = 13;
- else if (! strcmp (language_string, "GNU Objective-C"))
- i = 14;
- else
- gcc_unreachable ();
- fprintf (file, "%d,", i);
-
- /* 8 single bit fields: global linkage (not set for C extern linkage,
- apparently a PL/I convention?), out-of-line epilogue/prologue, offset
- from start of procedure stored in tbtab, internal function, function
- has controlled storage, function has no toc, function uses fp,
- function logs/aborts fp operations. */
- /* Assume that fp operations are used if any fp reg must be saved. */
- fprintf (file, "%d,",
- (optional_tbtab << 5) | ((info->first_fp_reg_save != 64) << 1));
-
- /* 6 bitfields: function is interrupt handler, name present in
- proc table, function calls alloca, on condition directives
- (controls stack walks, 3 bits), saves condition reg, saves
- link reg. */
- /* The `function calls alloca' bit seems to be set whenever reg 31 is
- set up as a frame pointer, even when there is no alloca call. */
- fprintf (file, "%d,",
- ((optional_tbtab << 6)
- | ((optional_tbtab & frame_pointer_needed) << 5)
- | (info->cr_save_p << 1)
- | (info->lr_save_p)));
-
- /* 3 bitfields: saves backchain, fixup code, number of fpr saved
- (6 bits). */
- fprintf (file, "%d,",
- (info->push_p << 7) | (64 - info->first_fp_reg_save));
-
- /* 2 bitfields: spare bits (2 bits), number of gpr saved (6 bits). */
- fprintf (file, "%d,", (32 - first_reg_to_save ()));
-
- if (optional_tbtab)
- {
- /* Compute the parameter info from the function decl argument
- list. */
- tree decl;
- int next_parm_info_bit = 31;
-
- for (decl = DECL_ARGUMENTS (current_function_decl);
- decl; decl = DECL_CHAIN (decl))
- {
- rtx parameter = DECL_INCOMING_RTL (decl);
- machine_mode mode = GET_MODE (parameter);
-
- if (REG_P (parameter))
- {
- if (SCALAR_FLOAT_MODE_P (mode))
- {
- int bits;
-
- float_parms++;
-
- switch (mode)
- {
- case E_SFmode:
- case E_SDmode:
- bits = 0x2;
- break;
-
- case E_DFmode:
- case E_DDmode:
- case E_TFmode:
- case E_TDmode:
- case E_IFmode:
- case E_KFmode:
- bits = 0x3;
- break;
-
- default:
- gcc_unreachable ();
- }
-
- /* If only one bit will fit, don't or in this entry. */
- if (next_parm_info_bit > 0)
- parm_info |= (bits << (next_parm_info_bit - 1));
- next_parm_info_bit -= 2;
- }
- else
- {
- fixed_parms += ((GET_MODE_SIZE (mode)
- + (UNITS_PER_WORD - 1))
- / UNITS_PER_WORD);
- next_parm_info_bit -= 1;
- }
- }
- }
- }
-
- /* Number of fixed point parameters. */
- /* This is actually the number of words of fixed point parameters; thus
- an 8 byte struct counts as 2; and thus the maximum value is 8. */
- fprintf (file, "%d,", fixed_parms);
-
- /* 2 bitfields: number of floating point parameters (7 bits), parameters
- all on stack. */
- /* This is actually the number of fp registers that hold parameters;
- and thus the maximum value is 13. */
- /* Set parameters on stack bit if parameters are not in their original
- registers, regardless of whether they are on the stack? Xlc
- seems to set the bit when not optimizing. */
- fprintf (file, "%d\n", ((float_parms << 1) | (! optimize)));
-
- if (optional_tbtab)
- {
- /* Optional fields follow. Some are variable length. */
-
- /* Parameter types, left adjusted bit fields: 0 fixed, 10 single
- float, 11 double float. */
- /* There is an entry for each parameter in a register, in the order
- that they occur in the parameter list. Any intervening arguments
- on the stack are ignored. If the list overflows a long (max
- possible length 34 bits) then completely leave off all elements
- that don't fit. */
- /* Only emit this long if there was at least one parameter. */
- if (fixed_parms || float_parms)
- fprintf (file, "\t.long %d\n", parm_info);
-
- /* Offset from start of code to tb table. */
- fputs ("\t.long ", file);
- ASM_OUTPUT_INTERNAL_LABEL_PREFIX (file, "LT");
- RS6000_OUTPUT_BASENAME (file, fname);
- putc ('-', file);
- rs6000_output_function_entry (file, fname);
- putc ('\n', file);
-
- /* Interrupt handler mask. */
- /* Omit this long, since we never set the interrupt handler bit
- above. */
-
- /* Number of CTL (controlled storage) anchors. */
- /* Omit this long, since the has_ctl bit is never set above. */
-
- /* Displacement into stack of each CTL anchor. */
- /* Omit this list of longs, because there are no CTL anchors. */
-
- /* Length of function name. */
- if (*fname == '*')
- ++fname;
- fprintf (file, "\t.short %d\n", (int) strlen (fname));
-
- /* Function name. */
- assemble_string (fname, strlen (fname));
-
- /* Register for alloca automatic storage; this is always reg 31.
- Only emit this if the alloca bit was set above. */
- if (frame_pointer_needed)
- fputs ("\t.byte 31\n", file);
-
- fputs ("\t.align 2\n", file);
- }
- }
-
- /* Arrange to define .LCTOC1 label, if not already done. */
- if (need_toc_init)
- {
- need_toc_init = 0;
- if (!toc_initialized)
- {
- switch_to_section (toc_section);
- switch_to_section (current_function_section ());
- }
- }
-}
-
-/* -fsplit-stack support. */
-
-/* A SYMBOL_REF for __morestack. */
-static GTY(()) rtx morestack_ref;
-
-static rtx
-gen_add3_const (rtx rt, rtx ra, long c)
-{
- if (TARGET_64BIT)
- return gen_adddi3 (rt, ra, GEN_INT (c));
- else
- return gen_addsi3 (rt, ra, GEN_INT (c));
-}
-
-/* Emit -fsplit-stack prologue, which goes before the regular function
- prologue (at local entry point in the case of ELFv2). */
-
-void
-rs6000_expand_split_stack_prologue (void)
-{
- rs6000_stack_t *info = rs6000_stack_info ();
- unsigned HOST_WIDE_INT allocate;
- long alloc_hi, alloc_lo;
- rtx r0, r1, r12, lr, ok_label, compare, jump, call_fusage;
- rtx_insn *insn;
-
- gcc_assert (flag_split_stack && reload_completed);
-
- if (!info->push_p)
- return;
-
- if (global_regs[29])
- {
- error ("%qs uses register r29", "%<-fsplit-stack%>");
- inform (DECL_SOURCE_LOCATION (global_regs_decl[29]),
- "conflicts with %qD", global_regs_decl[29]);
- }
-
- allocate = info->total_size;
- if (allocate > (unsigned HOST_WIDE_INT) 1 << 31)
- {
- sorry ("Stack frame larger than 2G is not supported for "
- "%<-fsplit-stack%>");
- return;
- }
- if (morestack_ref == NULL_RTX)
- {
- morestack_ref = gen_rtx_SYMBOL_REF (Pmode, "__morestack");
- SYMBOL_REF_FLAGS (morestack_ref) |= (SYMBOL_FLAG_LOCAL
- | SYMBOL_FLAG_FUNCTION);
- }
-
- r0 = gen_rtx_REG (Pmode, 0);
- r1 = gen_rtx_REG (Pmode, STACK_POINTER_REGNUM);
- r12 = gen_rtx_REG (Pmode, 12);
- emit_insn (gen_load_split_stack_limit (r0));
- /* Always emit two insns here to calculate the requested stack,
- so that the linker can edit them when adjusting size for calling
- non-split-stack code. */
- alloc_hi = (-allocate + 0x8000) & ~0xffffL;
- alloc_lo = -allocate - alloc_hi;
- if (alloc_hi != 0)
- {
- emit_insn (gen_add3_const (r12, r1, alloc_hi));
- if (alloc_lo != 0)
- emit_insn (gen_add3_const (r12, r12, alloc_lo));
- else
- emit_insn (gen_nop ());
- }
- else
- {
- emit_insn (gen_add3_const (r12, r1, alloc_lo));
- emit_insn (gen_nop ());
- }
-
- compare = gen_rtx_REG (CCUNSmode, CR7_REGNO);
- emit_insn (gen_rtx_SET (compare, gen_rtx_COMPARE (CCUNSmode, r12, r0)));
- ok_label = gen_label_rtx ();
- jump = gen_rtx_IF_THEN_ELSE (VOIDmode,
- gen_rtx_GEU (VOIDmode, compare, const0_rtx),
- gen_rtx_LABEL_REF (VOIDmode, ok_label),
- pc_rtx);
- insn = emit_jump_insn (gen_rtx_SET (pc_rtx, jump));
- JUMP_LABEL (insn) = ok_label;
- /* Mark the jump as very likely to be taken. */
- add_reg_br_prob_note (insn, profile_probability::very_likely ());
-
- lr = gen_rtx_REG (Pmode, LR_REGNO);
- insn = emit_move_insn (r0, lr);
- RTX_FRAME_RELATED_P (insn) = 1;
- insn = emit_insn (gen_frame_store (r0, r1, info->lr_save_offset));
- RTX_FRAME_RELATED_P (insn) = 1;
-
- insn = emit_call_insn (gen_call (gen_rtx_MEM (SImode, morestack_ref),
- const0_rtx, const0_rtx));
- call_fusage = NULL_RTX;
- use_reg (&call_fusage, r12);
- /* Say the call uses r0, even though it doesn't, to stop regrename
- from twiddling with the insns saving lr, trashing args for cfun.
- The insns restoring lr are similarly protected by making
- split_stack_return use r0. */
- use_reg (&call_fusage, r0);
- add_function_usage_to (insn, call_fusage);
- /* Indicate that this function can't jump to non-local gotos. */
- make_reg_eh_region_note_nothrow_nononlocal (insn);
- emit_insn (gen_frame_load (r0, r1, info->lr_save_offset));
- insn = emit_move_insn (lr, r0);
- add_reg_note (insn, REG_CFA_RESTORE, lr);
- RTX_FRAME_RELATED_P (insn) = 1;
- emit_insn (gen_split_stack_return ());
-
- emit_label (ok_label);
- LABEL_NUSES (ok_label) = 1;
-}
-
/* Return the internal arg pointer used for function incoming
arguments. When -fsplit-stack, the arg pointer is r12 so we need
to copy it to a pseudo in order for it to be preserved over calls
@@ -29172,33 +23750,6 @@ rs6000_live_on_entry (bitmap regs)
bitmap_set_bit (regs, 12);
}
-/* Emit -fsplit-stack dynamic stack allocation space check. */
-
-void
-rs6000_split_stack_space_check (rtx size, rtx label)
-{
- rtx sp = gen_rtx_REG (Pmode, STACK_POINTER_REGNUM);
- rtx limit = gen_reg_rtx (Pmode);
- rtx requested = gen_reg_rtx (Pmode);
- rtx cmp = gen_reg_rtx (CCUNSmode);
- rtx jump;
-
- emit_insn (gen_load_split_stack_limit (limit));
- if (CONST_INT_P (size))
- emit_insn (gen_add3_insn (requested, sp, GEN_INT (-INTVAL (size))));
- else
- {
- size = force_reg (Pmode, size);
- emit_move_insn (requested, gen_rtx_MINUS (Pmode, sp, size));
- }
- emit_insn (gen_rtx_SET (cmp, gen_rtx_COMPARE (CCUNSmode, requested, limit)));
- jump = gen_rtx_IF_THEN_ELSE (VOIDmode,
- gen_rtx_GEU (VOIDmode, cmp, const0_rtx),
- gen_rtx_LABEL_REF (VOIDmode, label),
- pc_rtx);
- jump = emit_jump_insn (gen_rtx_SET (pc_rtx, jump));
- JUMP_LABEL (jump) = label;
-}
/* A C compound statement that outputs the assembler code for a thunk
function, used to implement C++ virtual function calls with
@@ -29237,6 +23788,7 @@ rs6000_output_mi_thunk (FILE *file, tree thunk_fndecl ATTRIBUTE_UNUSED,
HOST_WIDE_INT delta, HOST_WIDE_INT vcall_offset,
tree function)
{
+ const char *fnname = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (thunk_fndecl));
rtx this_rtx, funexp;
rtx_insn *insn;
@@ -29306,13 +23858,14 @@ rs6000_output_mi_thunk (FILE *file, tree thunk_fndecl ATTRIBUTE_UNUSED,
/* Run just enough of rest_of_compilation to get the insns emitted.
There's not really enough bulk here to make other passes such as
- instruction scheduling worth while. Note that use_thunk calls
- assemble_start_function and assemble_end_function. */
+ instruction scheduling worth while. */
insn = get_insns ();
shorten_branches (insn);
+ assemble_start_function (thunk_fndecl, fnname);
final_start_function (insn, file, 1);
final (insn, file, 1);
final_end_function ();
+ assemble_end_function (thunk_fndecl, fnname);
reload_completed = 0;
epilogue_completed = 0;
@@ -30223,7 +24776,8 @@ rs6000_adjust_cost (rtx_insn *insn, int dep_type, rtx_insn *dep_insn, int cost,
some cycles later. */
/* Separate a load from a narrower, dependent store. */
- if ((rs6000_sched_groups || rs6000_tune == PROCESSOR_POWER9)
+ if ((rs6000_sched_groups || rs6000_tune == PROCESSOR_POWER9
+ || rs6000_tune == PROCESSOR_FUTURE)
&& GET_CODE (PATTERN (insn)) == SET
&& GET_CODE (PATTERN (dep_insn)) == SET
&& MEM_P (XEXP (PATTERN (insn), 1))
@@ -30261,6 +24815,7 @@ rs6000_adjust_cost (rtx_insn *insn, int dep_type, rtx_insn *dep_insn, int cost,
|| rs6000_tune == PROCESSOR_POWER7
|| rs6000_tune == PROCESSOR_POWER8
|| rs6000_tune == PROCESSOR_POWER9
+ || rs6000_tune == PROCESSOR_FUTURE
|| rs6000_tune == PROCESSOR_CELL)
&& recog_memoized (dep_insn)
&& (INSN_CODE (dep_insn) >= 0))
@@ -30840,6 +25395,7 @@ rs6000_issue_rate (void)
case PROCESSOR_POWER8:
return 7;
case PROCESSOR_POWER9:
+ case PROCESSOR_FUTURE:
return 6;
default:
return 1;
@@ -32597,12 +27153,18 @@ rs6000_longcall_ref (rtx call_ref, rtx arg)
if (TARGET_PLTSEQ)
{
rtx base = const0_rtx;
- int regno;
- if (DEFAULT_ABI == ABI_ELFv2)
+ int regno = 12;
+ if (rs6000_pcrel_p (cfun))
{
- base = gen_rtx_REG (Pmode, TOC_REGISTER);
- regno = 12;
+ rtx reg = gen_rtx_REG (Pmode, regno);
+ rtx u = gen_rtx_UNSPEC (Pmode, gen_rtvec (3, base, call_ref, arg),
+ UNSPEC_PLT_PCREL);
+ emit_insn (gen_rtx_SET (reg, u));
+ return reg;
}
+
+ if (DEFAULT_ABI == ABI_ELFv2)
+ base = gen_rtx_REG (Pmode, TOC_REGISTER);
else
{
if (flag_pic)
@@ -32889,14 +27451,7 @@ rs6000_fatal_bad_address (rtx op)
#if TARGET_MACHO
-typedef struct branch_island_d {
- tree function_name;
- tree label_name;
- int line_number;
-} branch_island;
-
-
-static vec<branch_island, va_gc> *branch_islands;
+vec<branch_island, va_gc> *branch_islands;
/* Remember to generate a branch island for far calls to the given
function. */
@@ -32909,91 +27464,6 @@ add_compiler_branch_island (tree label_name, tree function_name,
vec_safe_push (branch_islands, bi);
}
-/* Generate far-jump branch islands for everything recorded in
- branch_islands. Invoked immediately after the last instruction of
- the epilogue has been emitted; the branch islands must be appended
- to, and contiguous with, the function body. Mach-O stubs are
- generated in machopic_output_stub(). */
-
-static void
-macho_branch_islands (void)
-{
- char tmp_buf[512];
-
- while (!vec_safe_is_empty (branch_islands))
- {
- branch_island *bi = &branch_islands->last ();
- const char *label = IDENTIFIER_POINTER (bi->label_name);
- const char *name = IDENTIFIER_POINTER (bi->function_name);
- char name_buf[512];
- /* Cheap copy of the details from the Darwin ASM_OUTPUT_LABELREF(). */
- if (name[0] == '*' || name[0] == '&')
- strcpy (name_buf, name+1);
- else
- {
- name_buf[0] = '_';
- strcpy (name_buf+1, name);
- }
- strcpy (tmp_buf, "\n");
- strcat (tmp_buf, label);
-#if defined (DBX_DEBUGGING_INFO) || defined (XCOFF_DEBUGGING_INFO)
- if (write_symbols == DBX_DEBUG || write_symbols == XCOFF_DEBUG)
- dbxout_stabd (N_SLINE, bi->line_number);
-#endif /* DBX_DEBUGGING_INFO || XCOFF_DEBUGGING_INFO */
- if (flag_pic)
- {
- if (TARGET_LINK_STACK)
- {
- char name[32];
- get_ppc476_thunk_name (name);
- strcat (tmp_buf, ":\n\tmflr r0\n\tbl ");
- strcat (tmp_buf, name);
- strcat (tmp_buf, "\n");
- strcat (tmp_buf, label);
- strcat (tmp_buf, "_pic:\n\tmflr r11\n");
- }
- else
- {
- strcat (tmp_buf, ":\n\tmflr r0\n\tbcl 20,31,");
- strcat (tmp_buf, label);
- strcat (tmp_buf, "_pic\n");
- strcat (tmp_buf, label);
- strcat (tmp_buf, "_pic:\n\tmflr r11\n");
- }
-
- strcat (tmp_buf, "\taddis r11,r11,ha16(");
- strcat (tmp_buf, name_buf);
- strcat (tmp_buf, " - ");
- strcat (tmp_buf, label);
- strcat (tmp_buf, "_pic)\n");
-
- strcat (tmp_buf, "\tmtlr r0\n");
-
- strcat (tmp_buf, "\taddi r12,r11,lo16(");
- strcat (tmp_buf, name_buf);
- strcat (tmp_buf, " - ");
- strcat (tmp_buf, label);
- strcat (tmp_buf, "_pic)\n");
-
- strcat (tmp_buf, "\tmtctr r12\n\tbctr\n");
- }
- else
- {
- strcat (tmp_buf, ":\nlis r12,hi16(");
- strcat (tmp_buf, name_buf);
- strcat (tmp_buf, ")\n\tori r12,r12,lo16(");
- strcat (tmp_buf, name_buf);
- strcat (tmp_buf, ")\n\tmtctr r12\n\tbctr");
- }
- output_asm_insn (tmp_buf, 0);
-#if defined (DBX_DEBUGGING_INFO) || defined (XCOFF_DEBUGGING_INFO)
- if (write_symbols == DBX_DEBUG || write_symbols == XCOFF_DEBUG)
- dbxout_stabd (N_SLINE, bi->line_number);
-#endif /* DBX_DEBUGGING_INFO || XCOFF_DEBUGGING_INFO */
- branch_islands->pop ();
- }
-}
-
/* NO_PREVIOUS_DEF checks in the link list whether the function name is
already there or not. */
@@ -33032,7 +27502,7 @@ machopic_output_stub (FILE *file, const char *symb, const char *stub)
unsigned int length;
char *symbol_name, *lazy_ptr_name;
char *local_label_0;
- static int label = 0;
+ static unsigned label = 0;
/* Lose our funky encoding stuff so it doesn't contaminate the stub. */
symb = (*targetm.strip_name_encoding) (symb);
@@ -33058,8 +27528,8 @@ machopic_output_stub (FILE *file, const char *symb, const char *stub)
fprintf (file, "\t.indirect_symbol %s\n", symbol_name);
label++;
- local_label_0 = XALLOCAVEC (char, sizeof ("\"L00000000000$spb\""));
- sprintf (local_label_0, "\"L%011d$spb\"", label);
+ local_label_0 = XALLOCAVEC (char, 16);
+ sprintf (local_label_0, "L%u$spb", label);
fprintf (file, "\tmflr r0\n");
if (TARGET_LINK_STACK)
@@ -33356,7 +27826,8 @@ rs6000_elf_declare_function_name (FILE *file, const char *name, tree decl)
ASM_OUTPUT_TYPE_DIRECTIVE (file, name, "function");
ASM_DECLARE_RESULT (file, DECL_RESULT (decl));
- if (TARGET_CMODEL == CMODEL_LARGE && rs6000_global_entry_point_needed_p ())
+ if (TARGET_CMODEL == CMODEL_LARGE
+ && rs6000_global_entry_point_prologue_needed_p ())
{
char buf[256];
@@ -34686,8 +29157,15 @@ rs6000_register_move_cost (machine_mode mode,
{
if (TARGET_DIRECT_MOVE)
{
- if (rs6000_tune == PROCESSOR_POWER9)
- ret = 2 * hard_regno_nregs (FIRST_GPR_REGNO, mode);
+ /* Keep the cost for direct moves above that for within
+ a register class even if the actual processor cost is
+ comparable. We do this because a direct move insn
+ can't be a nop, whereas with ideal register
+ allocation a move within the same class might turn
+ out to be a nop. */
+ if (rs6000_tune == PROCESSOR_POWER9
+ || rs6000_tune == PROCESSOR_FUTURE)
+ ret = 3 * hard_regno_nregs (FIRST_GPR_REGNO, mode);
else
ret = 4 * hard_regno_nregs (FIRST_GPR_REGNO, mode);
/* SFmode requires a conversion when moving between gprs
@@ -36288,14 +30766,16 @@ static struct rs6000_opt_mask const rs6000_opt_masks[] =
{ "float128", OPTION_MASK_FLOAT128_KEYWORD, false, true },
{ "float128-hardware", OPTION_MASK_FLOAT128_HW, false, true },
{ "fprnd", OPTION_MASK_FPRND, false, true },
+ { "future", OPTION_MASK_FUTURE, false, true },
{ "hard-dfp", OPTION_MASK_DFP, false, true },
{ "htm", OPTION_MASK_HTM, false, true },
{ "isel", OPTION_MASK_ISEL, false, true },
{ "mfcrf", OPTION_MASK_MFCRF, false, true },
- { "mfpgpr", OPTION_MASK_MFPGPR, false, true },
+ { "mfpgpr", 0, false, true },
{ "modulo", OPTION_MASK_MODULO, false, true },
{ "mulhw", OPTION_MASK_MULHW, false, true },
{ "multiple", OPTION_MASK_MULTIPLE, false, true },
+ { "pcrel", OPTION_MASK_PCREL, false, true },
{ "popcntb", OPTION_MASK_POPCNTB, false, true },
{ "popcntd", OPTION_MASK_POPCNTD, false, true },
{ "power8-fusion", OPTION_MASK_P8_FUSION, false, true },
@@ -36306,6 +30786,7 @@ static struct rs6000_opt_mask const rs6000_opt_masks[] =
{ "power9-vector", OPTION_MASK_P9_VECTOR, false, true },
{ "powerpc-gfxopt", OPTION_MASK_PPC_GFXOPT, false, true },
{ "powerpc-gpopt", OPTION_MASK_PPC_GPOPT, false, true },
+ { "prefixed-addr", OPTION_MASK_PREFIXED_ADDR, false, true },
{ "quad-memory", OPTION_MASK_QUAD_MEMORY, false, true },
{ "quad-memory-atomic", OPTION_MASK_QUAD_MEMORY_ATOMIC, false, true },
{ "recip-precision", OPTION_MASK_RECIP_PRECISION, false, true },
@@ -37052,6 +31533,7 @@ rs6000_disable_incompatible_switches (void)
const HOST_WIDE_INT dep_flags; /* flags that depend on this option. */
const char *const name; /* name of the switch. */
} flags[] = {
+ { OPTION_MASK_FUTURE, OTHER_FUTURE_MASKS, "future" },
{ OPTION_MASK_P9_VECTOR, OTHER_P9_VECTOR_MASKS, "power9-vector" },
{ OPTION_MASK_P8_VECTOR, OTHER_P8_VECTOR_MASKS, "power8-vector" },
{ OPTION_MASK_VSX, OTHER_VSX_VECTOR_MASKS, "vsx" },
@@ -37234,7 +31716,7 @@ rs6000_get_function_versions_dispatcher (void *decl)
#ifndef TARGET_LIBC_PROVIDES_HWCAP_IN_TCB
error_at (DECL_SOURCE_LOCATION (default_node->decl),
- "target_clones attribute needs GLIBC (2.23 and newer) that "
+ "%<target_clones%> attribute needs GLIBC (2.23 and newer) that "
"exports hardware capability bits");
#else
@@ -37618,7 +32100,16 @@ rs6000_force_indexed_or_indirect_mem (rtx x)
addr = reg;
}
- x = replace_equiv_address (x, force_reg (Pmode, addr));
+ if (GET_CODE (addr) == PLUS)
+ {
+ rtx op0 = XEXP (addr, 0);
+ rtx op1 = XEXP (addr, 1);
+ op0 = force_reg (Pmode, op0);
+ op1 = force_reg (Pmode, op1);
+ x = replace_equiv_address (x, gen_rtx_PLUS (Pmode, op0, op1));
+ }
+ else
+ x = replace_equiv_address (x, force_reg (Pmode, addr));
}
return x;
@@ -37701,37 +32192,36 @@ rs6000_call_aix (rtx value, rtx func_desc, rtx tlsarg, rtx cookie)
if (!SYMBOL_REF_P (func)
|| (DEFAULT_ABI == ABI_AIX && !SYMBOL_REF_FUNCTION_P (func)))
{
- /* Save the TOC into its reserved slot before the call,
- and prepare to restore it after the call. */
- rtx stack_toc_offset = GEN_INT (RS6000_TOC_SAVE_SLOT);
- rtx stack_toc_unspec = gen_rtx_UNSPEC (Pmode,
- gen_rtvec (1, stack_toc_offset),
- UNSPEC_TOCSLOT);
- toc_restore = gen_rtx_SET (toc_reg, stack_toc_unspec);
-
- /* Can we optimize saving the TOC in the prologue or
- do we need to do it at every call? */
- if (TARGET_SAVE_TOC_INDIRECT && !cfun->calls_alloca)
- cfun->machine->save_toc_in_prologue = true;
- else
+ if (!rs6000_pcrel_p (cfun))
{
- rtx stack_ptr = gen_rtx_REG (Pmode, STACK_POINTER_REGNUM);
- rtx stack_toc_mem = gen_frame_mem (Pmode,
- gen_rtx_PLUS (Pmode, stack_ptr,
- stack_toc_offset));
- MEM_VOLATILE_P (stack_toc_mem) = 1;
- if (is_pltseq_longcall)
+ /* Save the TOC into its reserved slot before the call,
+ and prepare to restore it after the call. */
+ rtx stack_toc_offset = GEN_INT (RS6000_TOC_SAVE_SLOT);
+ rtx stack_toc_unspec = gen_rtx_UNSPEC (Pmode,
+ gen_rtvec (1, stack_toc_offset),
+ UNSPEC_TOCSLOT);
+ toc_restore = gen_rtx_SET (toc_reg, stack_toc_unspec);
+
+ /* Can we optimize saving the TOC in the prologue or
+ do we need to do it at every call? */
+ if (TARGET_SAVE_TOC_INDIRECT && !cfun->calls_alloca)
+ cfun->machine->save_toc_in_prologue = true;
+ else
{
- /* Use USPEC_PLTSEQ here to emit every instruction in an
- inline PLT call sequence with a reloc, enabling the
- linker to edit the sequence back to a direct call
- when that makes sense. */
- rtvec v = gen_rtvec (3, toc_reg, func_desc, tlsarg);
- rtx mark_toc_reg = gen_rtx_UNSPEC (Pmode, v, UNSPEC_PLTSEQ);
- emit_insn (gen_rtx_SET (stack_toc_mem, mark_toc_reg));
+ rtx stack_ptr = gen_rtx_REG (Pmode, STACK_POINTER_REGNUM);
+ rtx stack_toc_mem = gen_frame_mem (Pmode,
+ gen_rtx_PLUS (Pmode, stack_ptr,
+ stack_toc_offset));
+ MEM_VOLATILE_P (stack_toc_mem) = 1;
+ if (is_pltseq_longcall)
+ {
+ rtvec v = gen_rtvec (3, toc_reg, func_desc, tlsarg);
+ rtx mark_toc_reg = gen_rtx_UNSPEC (Pmode, v, UNSPEC_PLTSEQ);
+ emit_insn (gen_rtx_SET (stack_toc_mem, mark_toc_reg));
+ }
+ else
+ emit_move_insn (stack_toc_mem, toc_reg);
}
- else
- emit_move_insn (stack_toc_mem, toc_reg);
}
if (DEFAULT_ABI == ABI_ELFv2)
@@ -37808,10 +32298,12 @@ rs6000_call_aix (rtx value, rtx func_desc, rtx tlsarg, rtx cookie)
}
else
{
- /* Direct calls use the TOC: for local calls, the callee will
- assume the TOC register is set; for non-local calls, the
- PLT stub needs the TOC register. */
- abi_reg = toc_reg;
+ /* No TOC register needed for calls from PC-relative callers. */
+ if (!rs6000_pcrel_p (cfun))
+ /* Direct calls use the TOC: for local calls, the callee will
+ assume the TOC register is set; for non-local calls, the
+ PLT stub needs the TOC register. */
+ abi_reg = toc_reg;
func_addr = func;
}
@@ -37861,7 +32353,9 @@ rs6000_sibcall_aix (rtx value, rtx func_desc, rtx tlsarg, rtx cookie)
insn = emit_call_insn (insn);
/* Note use of the TOC register. */
- use_reg (&CALL_INSN_FUNCTION_USAGE (insn), gen_rtx_REG (Pmode, TOC_REGNUM));
+ if (!rs6000_pcrel_p (cfun))
+ use_reg (&CALL_INSN_FUNCTION_USAGE (insn),
+ gen_rtx_REG (Pmode, TOC_REGNUM));
}
/* Expand code to perform a call under the SYSV4 ABI. */
@@ -38042,7 +32536,8 @@ rs6000_call_darwin_1 (rtx value, rtx func_desc, rtx tlsarg,
if ((cookie_val & CALL_LONG) != 0
&& GET_CODE (func_desc) == SYMBOL_REF)
{
- if (darwin_emit_branch_islands && TARGET_32BIT)
+ /* FIXME: the longcall opt should not hang off picsymbol stubs. */
+ if (darwin_picsymbol_stubs && TARGET_32BIT)
make_island = true; /* Do nothing yet, retain the CALL_LONG flag. */
else
{
@@ -38125,14 +32620,32 @@ rs6000_sibcall_darwin (rtx value ATTRIBUTE_UNUSED, rtx func_desc ATTRIBUTE_UNUSE
#endif
}
+/* Return whether we should generate PC-relative code for FNDECL. */
+bool
+rs6000_fndecl_pcrel_p (const_tree fndecl)
+{
+ if (DEFAULT_ABI != ABI_ELFv2)
+ return false;
+
+ struct cl_target_option *opts = target_opts_for_fn (fndecl);
-/* Return whether we need to always update the saved TOC pointer when we update
- the stack pointer. */
+ return ((opts->x_rs6000_isa_flags & OPTION_MASK_PCREL) != 0
+ && TARGET_CMODEL == CMODEL_MEDIUM);
+}
-static bool
-rs6000_save_toc_in_prologue_p (void)
+/* Return whether we should generate PC-relative code for *FN. */
+bool
+rs6000_pcrel_p (struct function *fn)
{
- return (cfun && cfun->machine && cfun->machine->save_toc_in_prologue);
+ if (DEFAULT_ABI != ABI_ELFv2)
+ return false;
+
+ /* Optimize usual case. */
+ if (fn == cfun)
+ return ((rs6000_isa_flags & OPTION_MASK_PCREL) != 0
+ && TARGET_CMODEL == CMODEL_MEDIUM);
+
+ return rs6000_fndecl_pcrel_p (fn->decl);
}
#ifdef HAVE_GAS_HIDDEN
@@ -39279,7 +33792,27 @@ rs6000_mangle_decl_assembler_name (tree decl, tree id)
return id;
}
-
+/* Predict whether the given loop in gimple will be transformed in the RTL
+ doloop_optimize pass. */
+
+static bool
+rs6000_predict_doloop_p (struct loop *loop)
+{
+ gcc_assert (loop);
+
+ /* On rs6000, targetm.can_use_doloop_p is actually
+ can_use_doloop_if_innermost. Just ensure the loop is innermost. */
+ if (loop->inner != NULL)
+ {
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ fprintf (dump_file, "Predict doloop failure due to"
+ " loop nesting.\n");
+ return false;
+ }
+
+ return true;
+}
+
struct gcc_target targetm = TARGET_INITIALIZER;
#include "gt-rs6000.h"
diff --git a/gcc/config/rs6000/rs6000.h b/gcc/config/rs6000/rs6000.h
index 68ef491..9193d9e 100644
--- a/gcc/config/rs6000/rs6000.h
+++ b/gcc/config/rs6000/rs6000.h
@@ -70,6 +70,12 @@
#define PPC405_ERRATUM77 0
#endif
+#if CHECKING_P
+#define ASM_OPT_ANY ""
+#else
+#define ASM_OPT_ANY " -many"
+#endif
+
/* Common ASM definitions used by ASM_SPEC among the various targets for
handling -mcpu=xxx switches. There is a parallel list in driver-rs6000.c to
provide the default assembler options if the user uses -mcpu=native, so if
@@ -132,13 +138,14 @@
mcpu=e5500: -me5500; \
mcpu=e6500: -me6500; \
mcpu=titan: -mtitan; \
+ mcpu=future: -mfuture; \
!mcpu*: %{mpower9-vector: -mpower9; \
mpower8-vector|mcrypto|mdirect-move|mhtm: -mpower8; \
mvsx: -mpower7; \
mpowerpc64: -mppc64;: %(asm_default)}; \
:%eMissing -mcpu option in ASM_CPU_SPEC?\n} \
-%{mvsx: -mvsx -maltivec; maltivec: -maltivec} \
--many"
+%{mvsx: -mvsx -maltivec; maltivec: -maltivec}" \
+ASM_OPT_ANY
#define CPP_DEFAULT_SPEC ""
@@ -446,7 +453,7 @@ extern int rs6000_vector_align[];
#define TARGET_FCTIWUZ TARGET_POPCNTD
#define TARGET_CTZ TARGET_MODULO
#define TARGET_EXTSWSLI (TARGET_MODULO && TARGET_POWERPC64)
-#define TARGET_MADDLD (TARGET_MODULO && TARGET_POWERPC64)
+#define TARGET_MADDLD TARGET_MODULO
#define TARGET_XSCVDPSPN (TARGET_DIRECT_MOVE || TARGET_P8_VECTOR)
#define TARGET_XSCVSPDPN (TARGET_DIRECT_MOVE || TARGET_P8_VECTOR)
@@ -502,7 +509,6 @@ extern int rs6000_vector_align[];
#define MASK_HTM OPTION_MASK_HTM
#define MASK_ISEL OPTION_MASK_ISEL
#define MASK_MFCRF OPTION_MASK_MFCRF
-#define MASK_MFPGPR OPTION_MASK_MFPGPR
#define MASK_MULHW OPTION_MASK_MULHW
#define MASK_MULTIPLE OPTION_MASK_MULTIPLE
#define MASK_NO_UPDATE OPTION_MASK_NO_UPDATE
@@ -518,6 +524,7 @@ extern int rs6000_vector_align[];
#define MASK_STRICT_ALIGN OPTION_MASK_STRICT_ALIGN
#define MASK_UPDATE OPTION_MASK_UPDATE
#define MASK_VSX OPTION_MASK_VSX
+#define MASK_FUTURE OPTION_MASK_FUTURE
#ifndef IN_LIBGCC2
#define MASK_POWERPC64 OPTION_MASK_POWERPC64
@@ -1249,34 +1256,10 @@ enum r6000_reg_class_enum {
RS6000_CONSTRAINT_f, /* fpr registers for single values */
RS6000_CONSTRAINT_v, /* Altivec registers */
RS6000_CONSTRAINT_wa, /* Any VSX register */
- RS6000_CONSTRAINT_wb, /* Altivec register if ISA 3.0 vector. */
- RS6000_CONSTRAINT_wd, /* VSX register for V2DF */
RS6000_CONSTRAINT_we, /* VSX register if ISA 3.0 vector. */
- RS6000_CONSTRAINT_wf, /* VSX register for V4SF */
- RS6000_CONSTRAINT_wg, /* FPR register for -mmfpgpr */
- RS6000_CONSTRAINT_wh, /* FPR register for direct moves. */
- RS6000_CONSTRAINT_wi, /* FPR/VSX register to hold DImode */
- RS6000_CONSTRAINT_wj, /* FPR/VSX register for DImode direct moves. */
- RS6000_CONSTRAINT_wk, /* FPR/VSX register for DFmode direct moves. */
- RS6000_CONSTRAINT_wl, /* FPR register for LFIWAX */
- RS6000_CONSTRAINT_wm, /* VSX register for direct move */
- RS6000_CONSTRAINT_wo, /* VSX register for power9 vector. */
- RS6000_CONSTRAINT_wp, /* VSX reg for IEEE 128-bit fp TFmode. */
- RS6000_CONSTRAINT_wq, /* VSX reg for IEEE 128-bit fp KFmode. */
RS6000_CONSTRAINT_wr, /* GPR register if 64-bit */
- RS6000_CONSTRAINT_ws, /* VSX register for DF */
- RS6000_CONSTRAINT_wt, /* VSX register for TImode */
- RS6000_CONSTRAINT_wu, /* Altivec register for float load/stores. */
- RS6000_CONSTRAINT_wv, /* Altivec register for double load/stores. */
- RS6000_CONSTRAINT_ww, /* FP or VSX register for vsx float ops. */
RS6000_CONSTRAINT_wx, /* FPR register for STFIWX */
- RS6000_CONSTRAINT_wy, /* VSX register for SF */
- RS6000_CONSTRAINT_wz, /* FPR register for LFIWZX */
RS6000_CONSTRAINT_wA, /* BASE_REGS if 64-bit. */
- RS6000_CONSTRAINT_wH, /* Altivec register for 32-bit integers. */
- RS6000_CONSTRAINT_wI, /* VSX register for 32-bit integers. */
- RS6000_CONSTRAINT_wJ, /* VSX register for 8/16-bit integers. */
- RS6000_CONSTRAINT_wK, /* Altivec register for 16/32-bit integers. */
RS6000_CONSTRAINT_MAX
};
@@ -1496,6 +1479,15 @@ extern enum reg_class rs6000_constraints[RS6000_CONSTRAINT_MAX];
#define CALL_LONG 0x00000008 /* always call indirect */
#define CALL_LIBCALL 0x00000010 /* libcall */
+/* Identify PLT sequence for rs6000_pltseq_template. */
+enum rs6000_pltseq_enum {
+ RS6000_PLTSEQ_TOCSAVE,
+ RS6000_PLTSEQ_PLT16_HA,
+ RS6000_PLTSEQ_PLT16_LO,
+ RS6000_PLTSEQ_MTCTR,
+ RS6000_PLTSEQ_PLT_PCREL34
+};
+
#define IS_V4_FP_ARGS(OP) \
((INTVAL (OP) & (CALL_V4_CLEAR_FP_ARGS | CALL_V4_SET_FP_ARGS)) != 0)
@@ -2494,8 +2486,56 @@ enum rs6000_builtin_type_index
extern GTY(()) tree rs6000_builtin_types[RS6000_BTI_MAX];
extern GTY(()) tree rs6000_builtin_decls[RS6000_BUILTIN_COUNT];
+#ifndef USED_FOR_TARGET
+/* A C structure for machine-specific, per-function data.
+ This is added to the cfun structure. */
+typedef struct GTY(()) machine_function
+{
+ /* Flags if __builtin_return_address (n) with n >= 1 was used. */
+ int ra_needs_full_frame;
+ /* Flags if __builtin_return_address (0) was used. */
+ int ra_need_lr;
+ /* Cache lr_save_p after expansion of builtin_eh_return. */
+ int lr_save_state;
+ /* Whether we need to save the TOC to the reserved stack location in the
+ function prologue. */
+ bool save_toc_in_prologue;
+ /* Offset from virtual_stack_vars_rtx to the start of the ABI_V4
+ varargs save area. */
+ HOST_WIDE_INT varargs_save_offset;
+ /* Alternative internal arg pointer for -fsplit-stack. */
+ rtx split_stack_arg_pointer;
+ bool split_stack_argp_used;
+ /* Flag if r2 setup is needed with ELFv2 ABI. */
+ bool r2_setup_needed;
+ /* The number of components we use for separate shrink-wrapping. */
+ int n_components;
+ /* The components already handled by separate shrink-wrapping, which should
+ not be considered by the prologue and epilogue. */
+ bool gpr_is_wrapped_separately[32];
+ bool fpr_is_wrapped_separately[32];
+ bool lr_is_wrapped_separately;
+ bool toc_is_wrapped_separately;
+} machine_function;
+#endif
+
+
#define TARGET_SUPPORTS_WIDE_INT 1
#if (GCC_VERSION >= 3000)
#pragma GCC poison TARGET_FLOAT128 OPTION_MASK_FLOAT128 MASK_FLOAT128
#endif
+
+/* Whether a given VALUE is a valid 16- or 34-bit signed offset. EXTRA is the
+ amount that we can't touch at the high end of the range (typically if the
+ address is split into smaller addresses, the extra covers the addresses
+ which might be generated when the insn is split). */
+#define SIGNED_16BIT_OFFSET_P(VALUE, EXTRA) \
+ IN_RANGE (VALUE, \
+ -(HOST_WIDE_INT_1 << 15), \
+ (HOST_WIDE_INT_1 << 15) - 1 - (EXTRA))
+
+#define SIGNED_34BIT_OFFSET_P(VALUE, EXTRA) \
+ IN_RANGE (VALUE, \
+ -(HOST_WIDE_INT_1 << 33), \
+ (HOST_WIDE_INT_1 << 33) - 1 - (EXTRA))
diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md
index 8da7aba..503f91a 100644
--- a/gcc/config/rs6000/rs6000.md
+++ b/gcc/config/rs6000/rs6000.md
@@ -147,6 +147,7 @@
UNSPEC_PLTSEQ
UNSPEC_PLT16_HA
UNSPEC_PLT16_LO
+ UNSPEC_PLT_PCREL
])
;;
@@ -174,6 +175,8 @@
UNSPECV_SPEC_BARRIER ; Speculation barrier
])
+; The three different kinds of epilogue.
+(define_enum "epilogue_type" [normal sibcall eh_return])
;; Define an insn type attribute. This is used in function unit delay
;; computations.
@@ -259,10 +262,56 @@
ppc750,ppc7400,ppc7450,
ppc403,ppc405,ppc440,ppc476,
ppc8540,ppc8548,ppce300c2,ppce300c3,ppce500mc,ppce500mc64,ppce5500,ppce6500,
- power4,power5,power6,power7,power8,power9,
+ power4,power5,power6,power7,power8,power9,future,
rs64a,mpccore,cell,ppca2,titan"
(const (symbol_ref "(enum attr_cpu) rs6000_tune")))
+;; The ISA we implement.
+(define_attr "isa" "any,p5,p6,p7,p7v,p8v,p9v,p9kf,p9tf,fut"
+ (const_string "any"))
+
+;; Is this alternative enabled for the current CPU/ISA/etc.?
+(define_attr "enabled" ""
+ (cond
+ [(eq_attr "isa" "any")
+ (const_int 1)
+
+ (and (eq_attr "isa" "p5")
+ (match_test "TARGET_POPCNTB"))
+ (const_int 1)
+
+ (and (eq_attr "isa" "p6")
+ (match_test "TARGET_CMPB"))
+ (const_int 1)
+
+ (and (eq_attr "isa" "p7")
+ (match_test "TARGET_POPCNTD"))
+ (const_int 1)
+
+ (and (eq_attr "isa" "p7v")
+ (match_test "TARGET_VSX"))
+ (const_int 1)
+
+ (and (eq_attr "isa" "p8v")
+ (match_test "TARGET_P8_VECTOR"))
+ (const_int 1)
+
+ (and (eq_attr "isa" "p9v")
+ (match_test "TARGET_P9_VECTOR"))
+ (const_int 1)
+
+ (and (eq_attr "isa" "p9kf")
+ (match_test "TARGET_FLOAT128_TYPE"))
+ (const_int 1)
+
+ (and (eq_attr "isa" "p9tf")
+ (match_test "FLOAT128_VECTOR_P (TFmode)"))
+ (const_int 1)
+
+ (and (eq_attr "isa" "fut")
+ (match_test "TARGET_FUTURE"))
+ (const_int 1)
+ ] (const_int 0)))
;; If this instruction is microcoded on the CELL processor
; The default for load extended, the recorded instructions and rotate/shifts by a variable is always microcoded
@@ -433,16 +482,16 @@
(TD "wn")])
; Definitions for 64-bit VSX
-(define_mode_attr f64_vsx [(DF "ws") (DD "wn")])
+(define_mode_attr f64_vsx [(DF "wa") (DD "wn")])
; Definitions for 64-bit direct move
-(define_mode_attr f64_dm [(DF "wk") (DD "wh")])
+(define_mode_attr f64_dm [(DF "wa") (DD "d")])
; Definitions for 64-bit use of altivec registers
-(define_mode_attr f64_av [(DF "wv") (DD "wn")])
+(define_mode_attr f64_av [(DF "v") (DD "wn")])
; Definitions for 64-bit access to ISA 3.0 (power9) vector
-(define_mode_attr f64_p9 [(DF "wb") (DD "wn")])
+(define_mode_attr f64_p9 [(DF "v") (DD "wn")])
; These modes do not fit in integer registers in 32-bit mode.
(define_mode_iterator DIFD [DI DF DD])
@@ -450,13 +499,19 @@
; Iterator for reciprocal estimate instructions
(define_mode_iterator RECIPF [SF DF V4SF V2DF])
-; Iterator for just SF/DF
+; SFmode or DFmode.
(define_mode_iterator SFDF [SF DF])
-; Like SFDF, but a different name to match conditional move where the
-; comparison operands may be a different mode than the input operands.
+; And again, for when we need two FP modes in a pattern.
(define_mode_iterator SFDF2 [SF DF])
+; A generic s/d attribute, for sp/dp for example.
+(define_mode_attr sd [(SF "s") (DF "d")
+ (V4SF "s") (V2DF "d")])
+
+; "s" or nothing, for fmuls/fmul for example.
+(define_mode_attr s [(SF "s") (DF "")])
+
; Iterator for 128-bit floating point that uses the IBM double-double format
(define_mode_iterator IBM128 [(IF "FLOAT128_IBM_P (IFmode)")
(TF "FLOAT128_IBM_P (TFmode)")])
@@ -477,12 +532,6 @@
; Iterator for ISA 3.0 supported floating point types
(define_mode_iterator FP_ISA3 [SF DF])
-; SF/DF suffix for traditional floating instructions
-(define_mode_attr Ftrad [(SF "s") (DF "")])
-
-; SF/DF suffix for VSX instructions
-(define_mode_attr Fvsx [(SF "sp") (DF "dp")])
-
; SF/DF constraint for arithmetic on traditional floating point registers
(define_mode_attr Ff [(SF "f") (DF "d") (DI "d")])
@@ -490,18 +539,10 @@
; ISA 2.06 (power7). This includes instructions that normally target DF mode,
; but are used on SFmode, since internally SFmode values are kept in the DFmode
; format.
-(define_mode_attr Fv [(SF "ww") (DF "ws") (DI "wi")])
-
-; SF/DF constraint for arithmetic on VSX registers. This is intended to be
-; used for DFmode instructions added in ISA 2.06 (power7) and SFmode
-; instructions added in ISA 2.07 (power8)
-(define_mode_attr Fv2 [(SF "wy") (DF "ws") (DI "wi")])
+(define_mode_attr Fv [(SF "wa") (DF "wa") (DI "wa")])
-; SF/DF constraint for arithmetic on altivec registers
-(define_mode_attr Fa [(SF "wu") (DF "wv")])
-
-; s/d suffix for things like sdiv/ddiv
-(define_mode_attr Fs [(SF "s") (DF "d")])
+; Which isa is needed for those float instructions?
+(define_mode_attr Fisa [(SF "p8v") (DF "*") (DI "*")])
; FRE/FRES support
(define_mode_attr Ffre [(SF "fres") (DF "fre")])
@@ -590,11 +631,11 @@
(DI "Y")])
(define_mode_attr rreg [(SF "f")
- (DF "ws")
+ (DF "wa")
(TF "f")
(TD "f")
- (V4SF "wf")
- (V2DF "wd")])
+ (V4SF "wa")
+ (V2DF "wa")])
(define_mode_attr rreg2 [(SF "f")
(DF "d")])
@@ -620,7 +661,7 @@
;; either.
;; Mode attribute for boolean operation register constraints for output
-(define_mode_attr BOOL_REGS_OUTPUT [(TI "&r,r,r,wt,v")
+(define_mode_attr BOOL_REGS_OUTPUT [(TI "&r,r,r,wa,v")
(PTI "&r,r,r")
(V16QI "wa,v,&?r,?r,?r")
(V8HI "wa,v,&?r,?r,?r")
@@ -631,7 +672,7 @@
(V1TI "wa,v,&?r,?r,?r")])
;; Mode attribute for boolean operation register constraints for operand1
-(define_mode_attr BOOL_REGS_OP1 [(TI "r,0,r,wt,v")
+(define_mode_attr BOOL_REGS_OP1 [(TI "r,0,r,wa,v")
(PTI "r,0,r")
(V16QI "wa,v,r,0,r")
(V8HI "wa,v,r,0,r")
@@ -642,7 +683,7 @@
(V1TI "wa,v,r,0,r")])
;; Mode attribute for boolean operation register constraints for operand2
-(define_mode_attr BOOL_REGS_OP2 [(TI "r,r,0,wt,v")
+(define_mode_attr BOOL_REGS_OP2 [(TI "r,r,0,wa,v")
(PTI "r,r,0")
(V16QI "wa,v,r,r,0")
(V8HI "wa,v,r,r,0")
@@ -655,7 +696,7 @@
;; Mode attribute for boolean operation register constraints for operand1
;; for one_cmpl. To simplify things, we repeat the constraint where 0
;; is used for operand1 or operand2
-(define_mode_attr BOOL_REGS_UNARY [(TI "r,0,0,wt,v")
+(define_mode_attr BOOL_REGS_UNARY [(TI "r,0,0,wa,v")
(PTI "r,0,0")
(V16QI "wa,v,r,0,0")
(V8HI "wa,v,r,0,0")
@@ -691,15 +732,16 @@
;; complex forms. Basic data transfer is done later.
(define_insn "zero_extendqi<mode>2"
- [(set (match_operand:EXTQI 0 "gpc_reg_operand" "=r,r,^wJwK,^wK")
- (zero_extend:EXTQI (match_operand:QI 1 "reg_or_mem_operand" "m,r,Z,wK")))]
+ [(set (match_operand:EXTQI 0 "gpc_reg_operand" "=r,r,^wa,^v")
+ (zero_extend:EXTQI (match_operand:QI 1 "reg_or_mem_operand" "m,r,Z,v")))]
""
"@
lbz%U1%X1 %0,%1
rlwinm %0,%1,0,0xff
lxsibzx %x0,%y1
vextractub %0,%1,7"
- [(set_attr "type" "load,shift,fpload,vecperm")])
+ [(set_attr "type" "load,shift,fpload,vecperm")
+ (set_attr "isa" "*,*,p9v,p9v")])
(define_insn_and_split "*zero_extendqi<mode>2_dot"
[(set (match_operand:CC 2 "cc_reg_operand" "=x,?y")
@@ -744,15 +786,16 @@
(define_insn "zero_extendhi<mode>2"
- [(set (match_operand:EXTHI 0 "gpc_reg_operand" "=r,r,^wJwK,^wK")
- (zero_extend:EXTHI (match_operand:HI 1 "reg_or_mem_operand" "m,r,Z,wK")))]
+ [(set (match_operand:EXTHI 0 "gpc_reg_operand" "=r,r,^wa,^v")
+ (zero_extend:EXTHI (match_operand:HI 1 "reg_or_mem_operand" "m,r,Z,v")))]
""
"@
lhz%U1%X1 %0,%1
rlwinm %0,%1,0,0xffff
lxsihzx %x0,%y1
vextractuh %0,%1,6"
- [(set_attr "type" "load,shift,fpload,vecperm")])
+ [(set_attr "type" "load,shift,fpload,vecperm")
+ (set_attr "isa" "*,*,p9v,p9v")])
(define_insn_and_split "*zero_extendhi<mode>2_dot"
[(set (match_operand:CC 2 "cc_reg_operand" "=x,?y")
@@ -797,8 +840,8 @@
(define_insn "zero_extendsi<mode>2"
- [(set (match_operand:EXTSI 0 "gpc_reg_operand" "=r,r,wz,wu,wj,r,wJwK")
- (zero_extend:EXTSI (match_operand:SI 1 "reg_or_mem_operand" "m,r,Z,Z,r,wIwH,wJwK")))]
+ [(set (match_operand:EXTSI 0 "gpc_reg_operand" "=r,r,d,wa,wa,r,wa")
+ (zero_extend:EXTSI (match_operand:SI 1 "reg_or_mem_operand" "m,r,Z,Z,r,wa,wa")))]
""
"@
lwz%U1%X1 %0,%1
@@ -808,7 +851,8 @@
mtvsrwz %x0,%1
mfvsrwz %0,%x1
xxextractuw %x0,%x1,4"
- [(set_attr "type" "load,shift,fpload,fpload,mffgpr,mftgpr,vecexts")])
+ [(set_attr "type" "load,shift,fpload,fpload,mffgpr,mftgpr,vecexts")
+ (set_attr "isa" "*,*,p7,p8v,p8v,p8v,p9v")])
(define_insn_and_split "*zero_extendsi<mode>2_dot"
[(set (match_operand:CC 2 "cc_reg_operand" "=x,?y")
@@ -853,13 +897,14 @@
(define_insn "extendqi<mode>2"
- [(set (match_operand:EXTQI 0 "gpc_reg_operand" "=r,?*wK")
- (sign_extend:EXTQI (match_operand:QI 1 "gpc_reg_operand" "r,?*wK")))]
+ [(set (match_operand:EXTQI 0 "gpc_reg_operand" "=r,?*v")
+ (sign_extend:EXTQI (match_operand:QI 1 "gpc_reg_operand" "r,?*v")))]
""
"@
extsb %0,%1
vextsb2d %0,%1"
- [(set_attr "type" "exts,vecperm")])
+ [(set_attr "type" "exts,vecperm")
+ (set_attr "isa" "*,p9v")])
(define_insn_and_split "*extendqi<mode>2_dot"
[(set (match_operand:CC 2 "cc_reg_operand" "=x,?y")
@@ -910,8 +955,8 @@
"")
(define_insn "*extendhi<mode>2"
- [(set (match_operand:EXTHI 0 "gpc_reg_operand" "=r,r,?*wK,?*wK")
- (sign_extend:EXTHI (match_operand:HI 1 "reg_or_mem_operand" "m,r,Z,wK")))]
+ [(set (match_operand:EXTHI 0 "gpc_reg_operand" "=r,r,?*v,?*v")
+ (sign_extend:EXTHI (match_operand:HI 1 "reg_or_mem_operand" "m,r,Z,v")))]
""
"@
lha%U1%X1 %0,%1
@@ -920,7 +965,8 @@
vextsh2d %0,%1"
[(set_attr "type" "load,exts,fpload,vecperm")
(set_attr "sign_extend" "yes")
- (set_attr "length" "4,4,8,4")])
+ (set_attr "length" "*,*,8,*")
+ (set_attr "isa" "*,*,p9v,p9v")])
(define_split
[(set (match_operand:EXTHI 0 "altivec_register_operand")
@@ -979,10 +1025,9 @@
(define_insn "extendsi<mode>2"
[(set (match_operand:EXTSI 0 "gpc_reg_operand"
- "=r, r, wl, wu, wj, wK, wH, wr")
-
+ "=r, r, d, wa, wa, v, v, wr")
(sign_extend:EXTSI (match_operand:SI 1 "lwa_operand"
- "YZ, r, Z, Z, r, wK, wH, ?wIwH")))]
+ "YZ, r, Z, Z, r, v, v, ?wa")))]
""
"@
lwa%U1%X1 %0,%1
@@ -995,7 +1040,8 @@
#"
[(set_attr "type" "load,exts,fpload,fpload,mffgpr,vecexts,vecperm,mftgpr")
(set_attr "sign_extend" "yes")
- (set_attr "length" "4,4,4,4,4,4,8,8")])
+ (set_attr "length" "*,*,*,*,*,*,8,8")
+ (set_attr "isa" "*,*,p6,p8v,p8v,p9v,p8v,p8v")])
(define_split
[(set (match_operand:EXTSI 0 "int_reg_operand")
@@ -2203,7 +2249,7 @@
[(set_attr "type" "add")])
-(define_insn "neg<mode>2"
+(define_insn "@neg<mode>2"
[(set (match_operand:GPR 0 "gpc_reg_operand" "=r")
(neg:GPR (match_operand:GPR 1 "gpc_reg_operand" "r")))]
""
@@ -2428,9 +2474,9 @@
[(set_attr "type" "store")])
(define_insn_and_split "bswaphi2_reg"
- [(set (match_operand:HI 0 "gpc_reg_operand" "=&r,wo")
+ [(set (match_operand:HI 0 "gpc_reg_operand" "=&r,wa")
(bswap:HI
- (match_operand:HI 1 "gpc_reg_operand" "r,wo")))
+ (match_operand:HI 1 "gpc_reg_operand" "r,wa")))
(clobber (match_scratch:SI 2 "=&r,X"))]
""
"@
@@ -2453,14 +2499,15 @@
operands[4] = simplify_gen_subreg (SImode, operands[1], HImode, 0);
}
[(set_attr "length" "12,4")
- (set_attr "type" "*,vecperm")])
+ (set_attr "type" "*,vecperm")
+ (set_attr "isa" "*,p9v")])
;; We are always BITS_BIG_ENDIAN, so the bit positions below in
;; zero_extract insns do not change for -mlittle.
(define_insn_and_split "bswapsi2_reg"
- [(set (match_operand:SI 0 "gpc_reg_operand" "=&r,wo")
+ [(set (match_operand:SI 0 "gpc_reg_operand" "=&r,wa")
(bswap:SI
- (match_operand:SI 1 "gpc_reg_operand" "r,wo")))]
+ (match_operand:SI 1 "gpc_reg_operand" "r,wa")))]
""
"@
#
@@ -2483,7 +2530,8 @@
(const_int -256))))]
""
[(set_attr "length" "12,4")
- (set_attr "type" "*,vecperm")])
+ (set_attr "type" "*,vecperm")
+ (set_attr "isa" "*,p9v")])
;; On systems with LDBRX/STDBRX generate the loads/stores directly, just like
;; we do for L{H,W}BRX and ST{H,W}BRX above. If not, we have to generate more
@@ -2548,11 +2596,12 @@
[(set_attr "type" "store")])
(define_insn "bswapdi2_xxbrd"
- [(set (match_operand:DI 0 "gpc_reg_operand" "=wo")
- (bswap:DI (match_operand:DI 1 "gpc_reg_operand" "wo")))]
+ [(set (match_operand:DI 0 "gpc_reg_operand" "=wa")
+ (bswap:DI (match_operand:DI 1 "gpc_reg_operand" "wa")))]
"TARGET_P9_VECTOR"
"xxbrd %x0,%x1"
- [(set_attr "type" "vecperm")])
+ [(set_attr "type" "vecperm")
+ (set_attr "isa" "p9v")])
(define_insn "bswapdi2_reg"
[(set (match_operand:DI 0 "gpc_reg_operand" "=&r")
@@ -3013,11 +3062,11 @@
DONE;
})
-(define_insn "*maddld4"
- [(set (match_operand:DI 0 "gpc_reg_operand" "=r")
- (plus:DI (mult:DI (match_operand:DI 1 "gpc_reg_operand" "r")
- (match_operand:DI 2 "gpc_reg_operand" "r"))
- (match_operand:DI 3 "gpc_reg_operand" "r")))]
+(define_insn "*maddld<mode>4"
+ [(set (match_operand:GPR 0 "gpc_reg_operand" "=r")
+ (plus:GPR (mult:GPR (match_operand:GPR 1 "gpc_reg_operand" "r")
+ (match_operand:GPR 2 "gpc_reg_operand" "r"))
+ (match_operand:GPR 3 "gpc_reg_operand" "r")))]
"TARGET_MADDLD"
"maddld %0,%1,%2,%3"
[(set_attr "type" "mul")])
@@ -4594,14 +4643,15 @@
"")
(define_insn "*add<mode>3_fpr"
- [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<Ff>,<Fv2>")
- (plus:SFDF (match_operand:SFDF 1 "gpc_reg_operand" "%<Ff>,<Fv2>")
- (match_operand:SFDF 2 "gpc_reg_operand" "<Ff>,<Fv2>")))]
+ [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<Ff>,wa")
+ (plus:SFDF (match_operand:SFDF 1 "gpc_reg_operand" "%<Ff>,wa")
+ (match_operand:SFDF 2 "gpc_reg_operand" "<Ff>,wa")))]
"TARGET_HARD_FLOAT"
"@
- fadd<Ftrad> %0,%1,%2
- xsadd<Fvsx> %x0,%x1,%x2"
- [(set_attr "type" "fp")])
+ fadd<s> %0,%1,%2
+ xsadd<sd>p %x0,%x1,%x2"
+ [(set_attr "type" "fp")
+ (set_attr "isa" "*,<Fisa>")])
(define_expand "sub<mode>3"
[(set (match_operand:SFDF 0 "gpc_reg_operand")
@@ -4611,14 +4661,15 @@
"")
(define_insn "*sub<mode>3_fpr"
- [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<Ff>,<Fv2>")
- (minus:SFDF (match_operand:SFDF 1 "gpc_reg_operand" "<Ff>,<Fv2>")
- (match_operand:SFDF 2 "gpc_reg_operand" "<Ff>,<Fv2>")))]
+ [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<Ff>,wa")
+ (minus:SFDF (match_operand:SFDF 1 "gpc_reg_operand" "<Ff>,wa")
+ (match_operand:SFDF 2 "gpc_reg_operand" "<Ff>,wa")))]
"TARGET_HARD_FLOAT"
"@
- fsub<Ftrad> %0,%1,%2
- xssub<Fvsx> %x0,%x1,%x2"
- [(set_attr "type" "fp")])
+ fsub<s> %0,%1,%2
+ xssub<sd>p %x0,%x1,%x2"
+ [(set_attr "type" "fp")
+ (set_attr "isa" "*,<Fisa>")])
(define_expand "mul<mode>3"
[(set (match_operand:SFDF 0 "gpc_reg_operand")
@@ -4628,14 +4679,15 @@
"")
(define_insn "*mul<mode>3_fpr"
- [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<Ff>,<Fv2>")
- (mult:SFDF (match_operand:SFDF 1 "gpc_reg_operand" "%<Ff>,<Fv2>")
- (match_operand:SFDF 2 "gpc_reg_operand" "<Ff>,<Fv2>")))]
+ [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<Ff>,wa")
+ (mult:SFDF (match_operand:SFDF 1 "gpc_reg_operand" "%<Ff>,wa")
+ (match_operand:SFDF 2 "gpc_reg_operand" "<Ff>,wa")))]
"TARGET_HARD_FLOAT"
"@
- fmul<Ftrad> %0,%1,%2
- xsmul<Fvsx> %x0,%x1,%x2"
- [(set_attr "type" "dmul")])
+ fmul<s> %0,%1,%2
+ xsmul<sd>p %x0,%x1,%x2"
+ [(set_attr "type" "dmul")
+ (set_attr "isa" "*,<Fisa>")])
(define_expand "div<mode>3"
[(set (match_operand:SFDF 0 "gpc_reg_operand")
@@ -4653,23 +4705,25 @@
})
(define_insn "*div<mode>3_fpr"
- [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<Ff>,<Fv2>")
- (div:SFDF (match_operand:SFDF 1 "gpc_reg_operand" "<Ff>,<Fv2>")
- (match_operand:SFDF 2 "gpc_reg_operand" "<Ff>,<Fv2>")))]
+ [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<Ff>,wa")
+ (div:SFDF (match_operand:SFDF 1 "gpc_reg_operand" "<Ff>,wa")
+ (match_operand:SFDF 2 "gpc_reg_operand" "<Ff>,wa")))]
"TARGET_HARD_FLOAT"
"@
- fdiv<Ftrad> %0,%1,%2
- xsdiv<Fvsx> %x0,%x1,%x2"
- [(set_attr "type" "<Fs>div")])
+ fdiv<s> %0,%1,%2
+ xsdiv<sd>p %x0,%x1,%x2"
+ [(set_attr "type" "<sd>div")
+ (set_attr "isa" "*,<Fisa>")])
(define_insn "*sqrt<mode>2_internal"
- [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<Ff>,<Fv2>")
- (sqrt:SFDF (match_operand:SFDF 1 "gpc_reg_operand" "<Ff>,<Fv2>")))]
+ [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<Ff>,wa")
+ (sqrt:SFDF (match_operand:SFDF 1 "gpc_reg_operand" "<Ff>,wa")))]
"TARGET_HARD_FLOAT && TARGET_PPC_GPOPT"
"@
- fsqrt<Ftrad> %0,%1
- xssqrt<Fvsx> %x0,%x1"
- [(set_attr "type" "<Fs>sqrt")])
+ fsqrt<s> %0,%1
+ xssqrt<sd>p %x0,%x1"
+ [(set_attr "type" "<sd>sqrt")
+ (set_attr "isa" "*,<Fisa>")])
(define_expand "sqrt<mode>2"
[(set (match_operand:SFDF 0 "gpc_reg_operand")
@@ -4689,36 +4743,39 @@
})
;; Floating point reciprocal approximation
-(define_insn "fre<Fs>"
- [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<Ff>,<Fv2>")
- (unspec:SFDF [(match_operand:SFDF 1 "gpc_reg_operand" "<Ff>,<Fv2>")]
+(define_insn "fre<sd>"
+ [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<Ff>,wa")
+ (unspec:SFDF [(match_operand:SFDF 1 "gpc_reg_operand" "<Ff>,wa")]
UNSPEC_FRES))]
"TARGET_<FFRE>"
"@
- fre<Ftrad> %0,%1
- xsre<Fvsx> %x0,%x1"
- [(set_attr "type" "fp")])
+ fre<s> %0,%1
+ xsre<sd>p %x0,%x1"
+ [(set_attr "type" "fp")
+ (set_attr "isa" "*,<Fisa>")])
(define_insn "*rsqrt<mode>2"
- [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<Ff>,<Fv2>")
- (unspec:SFDF [(match_operand:SFDF 1 "gpc_reg_operand" "<Ff>,<Fv2>")]
+ [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<Ff>,wa")
+ (unspec:SFDF [(match_operand:SFDF 1 "gpc_reg_operand" "<Ff>,wa")]
UNSPEC_RSQRT))]
"RS6000_RECIP_HAVE_RSQRTE_P (<MODE>mode)"
"@
- frsqrte<Ftrad> %0,%1
- xsrsqrte<Fvsx> %x0,%x1"
- [(set_attr "type" "fp")])
+ frsqrte<s> %0,%1
+ xsrsqrte<sd>p %x0,%x1"
+ [(set_attr "type" "fp")
+ (set_attr "isa" "*,<Fisa>")])
;; Floating point comparisons
(define_insn "*cmp<mode>_fpr"
[(set (match_operand:CCFP 0 "cc_reg_operand" "=y,y")
- (compare:CCFP (match_operand:SFDF 1 "gpc_reg_operand" "<Ff>,<Fv2>")
- (match_operand:SFDF 2 "gpc_reg_operand" "<Ff>,<Fv2>")))]
+ (compare:CCFP (match_operand:SFDF 1 "gpc_reg_operand" "<Ff>,wa")
+ (match_operand:SFDF 2 "gpc_reg_operand" "<Ff>,wa")))]
"TARGET_HARD_FLOAT"
"@
fcmpu %0,%1,%2
xscmpudp %0,%x1,%x2"
- [(set_attr "type" "fpcompare")])
+ [(set_attr "type" "fpcompare")
+ (set_attr "isa" "*,<Fisa>")])
;; Floating point conversions
(define_expand "extendsfdf2"
@@ -4731,8 +4788,8 @@
})
(define_insn_and_split "*extendsfdf2_fpr"
- [(set (match_operand:DF 0 "gpc_reg_operand" "=d,?d,d,ws,?ws,wu,wb")
- (float_extend:DF (match_operand:SF 1 "reg_or_mem_operand" "0,f,m,0,wy,Z,wY")))]
+ [(set (match_operand:DF 0 "gpc_reg_operand" "=d,?d,d,wa,?wa,wa,v")
+ (float_extend:DF (match_operand:SF 1 "reg_or_mem_operand" "0,f,m,0,wa,Z,wY")))]
"TARGET_HARD_FLOAT && !HONOR_SNANS (SFmode)"
"@
#
@@ -4748,16 +4805,18 @@
emit_note (NOTE_INSN_DELETED);
DONE;
}
- [(set_attr "type" "fp,fpsimple,fpload,fp,fpsimple,fpload,fpload")])
+ [(set_attr "type" "fp,fpsimple,fpload,fp,fpsimple,fpload,fpload")
+ (set_attr "isa" "*,*,*,*,p8v,p8v,p9v")])
(define_insn "*extendsfdf2_snan"
- [(set (match_operand:DF 0 "gpc_reg_operand" "=d,ws")
- (float_extend:DF (match_operand:SF 1 "gpc_reg_operand" "f,wy")))]
+ [(set (match_operand:DF 0 "gpc_reg_operand" "=d,wa")
+ (float_extend:DF (match_operand:SF 1 "gpc_reg_operand" "f,wa")))]
"TARGET_HARD_FLOAT && HONOR_SNANS (SFmode)"
"@
frsp %0,%1
xsrsp %x0,%x1"
- [(set_attr "type" "fp")])
+ [(set_attr "type" "fp")
+ (set_attr "isa" "*,p8v")])
(define_expand "truncdfsf2"
[(set (match_operand:SF 0 "gpc_reg_operand")
@@ -4766,13 +4825,14 @@
"")
(define_insn "*truncdfsf2_fpr"
- [(set (match_operand:SF 0 "gpc_reg_operand" "=f,wy")
- (float_truncate:SF (match_operand:DF 1 "gpc_reg_operand" "d,ws")))]
+ [(set (match_operand:SF 0 "gpc_reg_operand" "=f,wa")
+ (float_truncate:SF (match_operand:DF 1 "gpc_reg_operand" "d,wa")))]
"TARGET_HARD_FLOAT"
"@
frsp %0,%1
xsrsp %x0,%x1"
- [(set_attr "type" "fp")])
+ [(set_attr "type" "fp")
+ (set_attr "isa" "*,p8v")])
;; This expander is here to avoid FLOAT_WORDS_BIGENDIAN tests in
;; builtins.c and optabs.c that are not correct for IBM long double
@@ -4797,13 +4857,7 @@
rtx tmp = gen_reg_rtx (DImode);
rtx dest_di = gen_lowpart (DImode, dest);
- if (<MODE>mode == KFmode)
- emit_insn (gen_signbitkf2_dm (tmp, src));
- else if (<MODE>mode == TFmode)
- emit_insn (gen_signbittf2_dm (tmp, src));
- else
- gcc_unreachable ();
-
+ emit_insn (gen_signbit2_dm (<MODE>mode, tmp, src));
emit_insn (gen_lshrdi3 (dest_di, tmp, GEN_INT (63)));
DONE;
}
@@ -4833,7 +4887,7 @@
;; After register allocation, if the _Float128 had originally been in GPRs, the
;; split allows the post reload phases to eliminate the move, and do the shift
;; directly with the register that contains the signbit.
-(define_insn_and_split "signbit<mode>2_dm"
+(define_insn_and_split "@signbit<mode>2_dm"
[(set (match_operand:DI 0 "gpc_reg_operand" "=r,r")
(unspec:DI [(match_operand:SIGNBIT 1 "gpc_reg_operand" "wa,r")]
UNSPEC_SIGNBIT))]
@@ -5000,23 +5054,13 @@
;; leave out the mode in operand 4 and use one pattern, but reload can
;; change the mode underneath our feet and then gets confused trying
;; to reload the value.
-(define_insn "isel_signed_<mode>"
- [(set (match_operand:GPR 0 "gpc_reg_operand" "=r,r")
- (if_then_else:GPR
- (match_operator 1 "scc_comparison_operator"
- [(match_operand:CC 4 "cc_reg_operand" "y,y")
- (const_int 0)])
- (match_operand:GPR 2 "reg_or_zero_operand" "O,b")
- (match_operand:GPR 3 "gpc_reg_operand" "r,r")))]
- "TARGET_ISEL"
- "isel %0,%2,%3,%j1"
- [(set_attr "type" "isel")])
-
-(define_insn "isel_unsigned_<mode>"
+(define_mode_iterator CCEITHER [CC CCUNS])
+(define_mode_attr un [(CC "") (CCUNS "un")])
+(define_insn "isel_<un>signed_<GPR:mode>"
[(set (match_operand:GPR 0 "gpc_reg_operand" "=r,r")
(if_then_else:GPR
(match_operator 1 "scc_comparison_operator"
- [(match_operand:CCUNS 4 "cc_reg_operand" "y,y")
+ [(match_operand:CCEITHER 4 "cc_reg_operand" "y,y")
(const_int 0)])
(match_operand:GPR 2 "reg_or_zero_operand" "O,b")
(match_operand:GPR 3 "gpc_reg_operand" "r,r")))]
@@ -5028,26 +5072,11 @@
;; isel can handle reversed comparisons so long as the operands are
;; registers.
-(define_insn "*isel_reversed_signed_<mode>"
+(define_insn "*isel_reversed_<un>signed_<GPR:mode>"
[(set (match_operand:GPR 0 "gpc_reg_operand" "=r,r")
(if_then_else:GPR
(match_operator 1 "scc_rev_comparison_operator"
- [(match_operand:CC 4 "cc_reg_operand" "y,y")
- (const_int 0)])
- (match_operand:GPR 2 "gpc_reg_operand" "r,r")
- (match_operand:GPR 3 "reg_or_zero_operand" "O,b")))]
- "TARGET_ISEL"
-{
- PUT_CODE (operands[1], reverse_condition (GET_CODE (operands[1])));
- return "isel %0,%3,%2,%j1";
-}
- [(set_attr "type" "isel")])
-
-(define_insn "*isel_reversed_unsigned_<mode>"
- [(set (match_operand:GPR 0 "gpc_reg_operand" "=r,r")
- (if_then_else:GPR
- (match_operator 1 "scc_rev_comparison_operator"
- [(match_operand:CCUNS 4 "cc_reg_operand" "y,y")
+ [(match_operand:CCEITHER 4 "cc_reg_operand" "y,y")
(const_int 0)])
(match_operand:GPR 2 "gpc_reg_operand" "r,r")
(match_operand:GPR 3 "reg_or_zero_operand" "O,b")))]
@@ -5179,8 +5208,8 @@
; We don't define lfiwax/lfiwzx with the normal definition, because we
; don't want to support putting SImode in FPR registers.
(define_insn "lfiwax"
- [(set (match_operand:DI 0 "gpc_reg_operand" "=d,wj,wj,wK")
- (unspec:DI [(match_operand:SI 1 "reg_or_indexed_operand" "Z,Z,r,wK")]
+ [(set (match_operand:DI 0 "gpc_reg_operand" "=d,wa,wa,v")
+ (unspec:DI [(match_operand:SI 1 "reg_or_indexed_operand" "Z,Z,r,v")]
UNSPEC_LFIWAX))]
"TARGET_HARD_FLOAT && TARGET_LFIWAX"
"@
@@ -5188,7 +5217,8 @@
lxsiwax %x0,%y1
mtvsrwa %x0,%1
vextsw2d %0,%1"
- [(set_attr "type" "fpload,fpload,mffgpr,vecexts")])
+ [(set_attr "type" "fpload,fpload,mffgpr,vecexts")
+ (set_attr "isa" "*,p8v,p8v,p9v")])
; This split must be run before register allocation because it allocates the
; memory slot that is needed to move values to/from the FPR. We don't allocate
@@ -5196,9 +5226,9 @@
; not be needed and also in case the insns are deleted as dead code.
(define_insn_and_split "floatsi<mode>2_lfiwax"
- [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<Fv>")
- (float:SFDF (match_operand:SI 1 "nonimmediate_operand" "r")))
- (clobber (match_scratch:DI 2 "=wi"))]
+ [(set (match_operand:SFDF 0 "gpc_reg_operand" "=d,<Fv>")
+ (float:SFDF (match_operand:SI 1 "nonimmediate_operand" "r,r")))
+ (clobber (match_scratch:DI 2 "=d,wa"))]
"TARGET_HARD_FLOAT && TARGET_LFIWAX
&& <SI_CONVERT_FP> && can_create_pseudo_p ()"
"#"
@@ -5209,8 +5239,7 @@
rtx src = operands[1];
rtx tmp;
- if (!MEM_P (src) && TARGET_POWERPC64
- && (TARGET_MFPGPR || TARGET_DIRECT_MOVE))
+ if (!MEM_P (src) && TARGET_POWERPC64 && TARGET_DIRECT_MOVE)
tmp = convert_to_mode (DImode, src, false);
else
{
@@ -5236,11 +5265,11 @@
(set_attr "type" "fpload")])
(define_insn_and_split "floatsi<mode>2_lfiwax_mem"
- [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<Fv>")
+ [(set (match_operand:SFDF 0 "gpc_reg_operand" "=d,<Fv>")
(float:SFDF
(sign_extend:DI
- (match_operand:SI 1 "indexed_or_indirect_operand" "Z"))))
- (clobber (match_scratch:DI 2 "=wi"))]
+ (match_operand:SI 1 "indexed_or_indirect_operand" "Z,Z"))))
+ (clobber (match_scratch:DI 2 "=d,wa"))]
"TARGET_HARD_FLOAT && TARGET_LFIWAX && <SI_CONVERT_FP>"
"#"
""
@@ -5260,8 +5289,8 @@
(set_attr "type" "fpload")])
(define_insn "lfiwzx"
- [(set (match_operand:DI 0 "gpc_reg_operand" "=d,wj,wj,wJwK")
- (unspec:DI [(match_operand:SI 1 "reg_or_indexed_operand" "Z,Z,r,wJwK")]
+ [(set (match_operand:DI 0 "gpc_reg_operand" "=d,wa,wa,wa")
+ (unspec:DI [(match_operand:SI 1 "reg_or_indexed_operand" "Z,Z,r,wa")]
UNSPEC_LFIWZX))]
"TARGET_HARD_FLOAT && TARGET_LFIWZX"
"@
@@ -5269,12 +5298,13 @@
lxsiwzx %x0,%y1
mtvsrwz %x0,%1
xxextractuw %x0,%x1,4"
- [(set_attr "type" "fpload,fpload,mftgpr,vecexts")])
+ [(set_attr "type" "fpload,fpload,mftgpr,vecexts")
+ (set_attr "isa" "*,p8v,p8v,p9v")])
(define_insn_and_split "floatunssi<mode>2_lfiwzx"
- [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<Fv>")
- (unsigned_float:SFDF (match_operand:SI 1 "nonimmediate_operand" "r")))
- (clobber (match_scratch:DI 2 "=wi"))]
+ [(set (match_operand:SFDF 0 "gpc_reg_operand" "=d,<Fv>")
+ (unsigned_float:SFDF (match_operand:SI 1 "nonimmediate_operand" "r,r")))
+ (clobber (match_scratch:DI 2 "=d,wa"))]
"TARGET_HARD_FLOAT && TARGET_LFIWZX && <SI_CONVERT_FP>"
"#"
""
@@ -5284,8 +5314,7 @@
rtx src = operands[1];
rtx tmp;
- if (!MEM_P (src) && TARGET_POWERPC64
- && (TARGET_MFPGPR || TARGET_DIRECT_MOVE))
+ if (!MEM_P (src) && TARGET_POWERPC64 && TARGET_DIRECT_MOVE)
tmp = convert_to_mode (DImode, src, true);
else
{
@@ -5311,11 +5340,11 @@
(set_attr "type" "fpload")])
(define_insn_and_split "floatunssi<mode>2_lfiwzx_mem"
- [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<Fv>")
+ [(set (match_operand:SFDF 0 "gpc_reg_operand" "=d,<Fv>")
(unsigned_float:SFDF
(zero_extend:DI
- (match_operand:SI 1 "indexed_or_indirect_operand" "Z"))))
- (clobber (match_scratch:DI 2 "=wi"))]
+ (match_operand:SI 1 "indexed_or_indirect_operand" "Z,Z"))))
+ (clobber (match_scratch:DI 2 "=d,wa"))]
"TARGET_HARD_FLOAT && TARGET_LFIWZX && <SI_CONVERT_FP>"
"#"
""
@@ -5513,10 +5542,10 @@
(define_insn_and_split "*float<QHI:mode><FP_ISA3:mode>2_internal"
[(set (match_operand:FP_ISA3 0 "vsx_register_operand" "=<Fv>,<Fv>,<Fv>")
(float:FP_ISA3
- (match_operand:QHI 1 "reg_or_indexed_operand" "wK,r,Z")))
- (clobber (match_scratch:DI 2 "=wK,wi,wK"))
+ (match_operand:QHI 1 "reg_or_indexed_operand" "v,r,Z")))
+ (clobber (match_scratch:DI 2 "=v,wa,v"))
(clobber (match_scratch:DI 3 "=X,r,X"))
- (clobber (match_scratch:<QHI:MODE> 4 "=X,X,wK"))]
+ (clobber (match_scratch:<QHI:MODE> 4 "=X,X,v"))]
"TARGET_P9_VECTOR && TARGET_DIRECT_MOVE && TARGET_POWERPC64"
"#"
"&& reload_completed"
@@ -5548,7 +5577,8 @@
emit_insn (gen_floatdi<FP_ISA3:mode>2 (result, di));
DONE;
-})
+}
+ [(set_attr "isa" "p9v,*,p9v")])
(define_expand "floatuns<QHI:mode><FP_ISA3:mode>2"
[(parallel [(set (match_operand:FP_ISA3 0 "vsx_register_operand")
@@ -5565,8 +5595,8 @@
(define_insn_and_split "*floatuns<QHI:mode><FP_ISA3:mode>2_internal"
[(set (match_operand:FP_ISA3 0 "vsx_register_operand" "=<Fv>,<Fv>,<Fv>")
(unsigned_float:FP_ISA3
- (match_operand:QHI 1 "reg_or_indexed_operand" "wK,r,Z")))
- (clobber (match_scratch:DI 2 "=wK,wi,wJwK"))
+ (match_operand:QHI 1 "reg_or_indexed_operand" "v,r,Z")))
+ (clobber (match_scratch:DI 2 "=v,wa,wa"))
(clobber (match_scratch:DI 3 "=X,r,X"))]
"TARGET_P9_VECTOR && TARGET_DIRECT_MOVE && TARGET_POWERPC64"
"#"
@@ -5593,7 +5623,8 @@
emit_insn (gen_floatdi<FP_ISA3:mode>2 (result, di));
DONE;
-})
+}
+ [(set_attr "isa" "p9v,*,p9v")])
(define_expand "fix_trunc<mode>si2"
[(set (match_operand:SI 0 "gpc_reg_operand")
@@ -5644,7 +5675,7 @@
emit_insn (gen_stfiwx (dest, tmp));
DONE;
}
- else if (TARGET_POWERPC64 && (TARGET_MFPGPR || TARGET_DIRECT_MOVE) && !MEM_P (dest))
+ else if (TARGET_POWERPC64 && TARGET_DIRECT_MOVE && !MEM_P (dest))
{
dest = gen_lowpart (DImode, dest);
emit_move_insn (dest, tmp);
@@ -5691,7 +5722,7 @@
"")
(define_insn "*fix_trunc<mode>di2_fctidz"
- [(set (match_operand:DI 0 "gpc_reg_operand" "=d,wi")
+ [(set (match_operand:DI 0 "gpc_reg_operand" "=d,wa")
(fix:DI (match_operand:SFDF 1 "gpc_reg_operand" "<Ff>,<Fv>")))]
"TARGET_HARD_FLOAT && TARGET_FCFID"
"@
@@ -5706,9 +5737,9 @@
;; register allocation prevents the register allocator from doing a direct move
;; of the SImode value to a GPR, and then a store/load.
(define_insn_and_split "fix<uns>_trunc<SFDF:mode><QHI:mode>2"
- [(set (match_operand:<QHI:MODE> 0 "gpc_reg_operand" "=wJ,wJwK,r")
- (any_fix:QHI (match_operand:SFDF 1 "gpc_reg_operand" "wJ,wJwK,wa")))
- (clobber (match_scratch:SI 2 "=X,X,wi"))]
+ [(set (match_operand:<QHI:MODE> 0 "gpc_reg_operand" "=d,wa,r")
+ (any_fix:QHI (match_operand:SFDF 1 "gpc_reg_operand" "d,wa,wa")))
+ (clobber (match_scratch:SI 2 "=X,X,wa"))]
"TARGET_DIRECT_MOVE"
"@
fctiw<u>z %0,%1
@@ -5722,8 +5753,9 @@
{
operands[3] = gen_rtx_REG (SImode, REGNO (operands[0]));
}
- [(set_attr "length" "4,4,8")
- (set_attr "type" "fp")])
+ [(set_attr "type" "fp")
+ (set_attr "length" "4,4,8")
+ (set_attr "isa" "p9v,p9v,*")])
(define_insn "*fix<uns>_trunc<SFDF:mode>si2_p8"
[(set (match_operand:SI 0 "gpc_reg_operand" "=d,wa")
@@ -5791,7 +5823,7 @@
emit_insn (gen_stfiwx (dest, tmp));
DONE;
}
- else if (TARGET_POWERPC64 && (TARGET_MFPGPR || TARGET_DIRECT_MOVE))
+ else if (TARGET_POWERPC64 && TARGET_DIRECT_MOVE)
{
dest = gen_lowpart (DImode, dest);
emit_move_insn (dest, tmp);
@@ -5809,7 +5841,7 @@
(set_attr "type" "fp")])
(define_insn "fixuns_trunc<mode>di2"
- [(set (match_operand:DI 0 "gpc_reg_operand" "=d,wi")
+ [(set (match_operand:DI 0 "gpc_reg_operand" "=d,wa")
(unsigned_fix:DI (match_operand:SFDF 1 "gpc_reg_operand" "<Ff>,<Fv>")))]
"TARGET_HARD_FLOAT && TARGET_FCTIDUZ"
"@
@@ -5944,7 +5976,7 @@
;; because the first makes it clear that operand 0 is not live
;; before the instruction.
(define_insn "fctiwz_<mode>"
- [(set (match_operand:DI 0 "gpc_reg_operand" "=d,wi")
+ [(set (match_operand:DI 0 "gpc_reg_operand" "=d,wa")
(unspec:DI [(fix:SI
(match_operand:SFDF 1 "gpc_reg_operand" "<Ff>,<Fv>"))]
UNSPEC_FCTIWZ))]
@@ -5955,7 +5987,7 @@
[(set_attr "type" "fp")])
(define_insn "fctiwuz_<mode>"
- [(set (match_operand:DI 0 "gpc_reg_operand" "=d,wi")
+ [(set (match_operand:DI 0 "gpc_reg_operand" "=d,wa")
(unspec:DI [(unsigned_fix:SI
(match_operand:SFDF 1 "gpc_reg_operand" "<Ff>,<Fv>"))]
UNSPEC_FCTIWUZ))]
@@ -5969,8 +6001,8 @@
;; since the friz instruction does not truncate the value if the floating
;; point value is < LONG_MIN or > LONG_MAX.
(define_insn "*friz"
- [(set (match_operand:DF 0 "gpc_reg_operand" "=d,ws")
- (float:DF (fix:DI (match_operand:DF 1 "gpc_reg_operand" "d,ws"))))]
+ [(set (match_operand:DF 0 "gpc_reg_operand" "=d,wa")
+ (float:DF (fix:DI (match_operand:DF 1 "gpc_reg_operand" "d,wa"))))]
"TARGET_HARD_FLOAT && TARGET_FPRND
&& flag_unsafe_math_optimizations && !flag_trapping_math && TARGET_FRIZ"
"@
@@ -6119,17 +6151,16 @@
})
; An UNSPEC is used so we don't have to support SImode in FP registers.
-; The 'wu' constraint is used for the 2nd alternative to ensure stxsiwx
-; is only generated for Power8 or later.
(define_insn "stfiwx"
[(set (match_operand:SI 0 "memory_operand" "=Z,Z")
- (unspec:SI [(match_operand:DI 1 "gpc_reg_operand" "d,wu")]
+ (unspec:SI [(match_operand:DI 1 "gpc_reg_operand" "d,wa")]
UNSPEC_STFIWX))]
"TARGET_PPC_GFXOPT"
"@
stfiwx %1,%y0
stxsiwx %x1,%y0"
- [(set_attr "type" "fpstore")])
+ [(set_attr "type" "fpstore")
+ (set_attr "isa" "*,p8v")])
;; If we don't have a direct conversion to single precision, don't enable this
;; conversion for 32-bit without fast math, because we don't have the insn to
@@ -6166,8 +6197,8 @@
})
(define_insn "floatdidf2"
- [(set (match_operand:DF 0 "gpc_reg_operand" "=d,ws")
- (float:DF (match_operand:DI 1 "gpc_reg_operand" "d,wi")))]
+ [(set (match_operand:DF 0 "gpc_reg_operand" "=d,wa")
+ (float:DF (match_operand:DI 1 "gpc_reg_operand" "d,wa")))]
"TARGET_FCFID && TARGET_HARD_FLOAT"
"@
fcfid %0,%1
@@ -6180,9 +6211,9 @@
; hit. We will split after reload to avoid the trip through the GPRs
(define_insn_and_split "*floatdidf2_mem"
- [(set (match_operand:DF 0 "gpc_reg_operand" "=d,ws")
+ [(set (match_operand:DF 0 "gpc_reg_operand" "=d,wa")
(float:DF (match_operand:DI 1 "memory_operand" "m,Z")))
- (clobber (match_scratch:DI 2 "=d,wi"))]
+ (clobber (match_scratch:DI 2 "=d,wa"))]
"TARGET_HARD_FLOAT && TARGET_FCFID"
"#"
"&& reload_completed"
@@ -6200,8 +6231,8 @@
"")
(define_insn "*floatunsdidf2_fcfidu"
- [(set (match_operand:DF 0 "gpc_reg_operand" "=d,ws")
- (unsigned_float:DF (match_operand:DI 1 "gpc_reg_operand" "d,wi")))]
+ [(set (match_operand:DF 0 "gpc_reg_operand" "=d,wa")
+ (unsigned_float:DF (match_operand:DI 1 "gpc_reg_operand" "d,wa")))]
"TARGET_HARD_FLOAT && TARGET_FCFIDU"
"@
fcfidu %0,%1
@@ -6209,9 +6240,9 @@
[(set_attr "type" "fp")])
(define_insn_and_split "*floatunsdidf2_mem"
- [(set (match_operand:DF 0 "gpc_reg_operand" "=d,ws")
+ [(set (match_operand:DF 0 "gpc_reg_operand" "=d,wa")
(unsigned_float:DF (match_operand:DI 1 "memory_operand" "m,Z")))
- (clobber (match_scratch:DI 2 "=d,wi"))]
+ (clobber (match_scratch:DI 2 "=d,wa"))]
"TARGET_HARD_FLOAT && (TARGET_FCFIDU || VECTOR_UNIT_VSX_P (DFmode))"
"#"
"&& reload_completed"
@@ -6243,18 +6274,19 @@
})
(define_insn "floatdisf2_fcfids"
- [(set (match_operand:SF 0 "gpc_reg_operand" "=f,wy")
- (float:SF (match_operand:DI 1 "gpc_reg_operand" "d,wi")))]
+ [(set (match_operand:SF 0 "gpc_reg_operand" "=f,wa")
+ (float:SF (match_operand:DI 1 "gpc_reg_operand" "d,wa")))]
"TARGET_HARD_FLOAT && TARGET_FCFIDS"
"@
fcfids %0,%1
xscvsxdsp %x0,%x1"
- [(set_attr "type" "fp")])
+ [(set_attr "type" "fp")
+ (set_attr "isa" "*,p8v")])
(define_insn_and_split "*floatdisf2_mem"
- [(set (match_operand:SF 0 "gpc_reg_operand" "=f,wy,wy")
+ [(set (match_operand:SF 0 "gpc_reg_operand" "=f,wa,wa")
(float:SF (match_operand:DI 1 "memory_operand" "m,m,Z")))
- (clobber (match_scratch:DI 2 "=d,d,wi"))]
+ (clobber (match_scratch:DI 2 "=d,d,wa"))]
"TARGET_HARD_FLOAT && TARGET_FCFIDS"
"#"
"&& reload_completed"
@@ -6264,7 +6296,8 @@
emit_insn (gen_floatdisf2_fcfids (operands[0], operands[2]));
DONE;
}
- [(set_attr "length" "8")])
+ [(set_attr "length" "8")
+ (set_attr "isa" "*,p8v,p8v")])
;; This is not IEEE compliant if rounding mode is "round to nearest".
;; If the DI->DF conversion is inexact, then it's possible to suffer
@@ -6322,18 +6355,19 @@
"")
(define_insn "floatunsdisf2_fcfidus"
- [(set (match_operand:SF 0 "gpc_reg_operand" "=f,wu")
- (unsigned_float:SF (match_operand:DI 1 "gpc_reg_operand" "d,wi")))]
+ [(set (match_operand:SF 0 "gpc_reg_operand" "=f,wa")
+ (unsigned_float:SF (match_operand:DI 1 "gpc_reg_operand" "d,wa")))]
"TARGET_HARD_FLOAT && TARGET_FCFIDUS"
"@
fcfidus %0,%1
xscvuxdsp %x0,%x1"
- [(set_attr "type" "fp")])
+ [(set_attr "type" "fp")
+ (set_attr "isa" "*,p8v")])
(define_insn_and_split "*floatunsdisf2_mem"
- [(set (match_operand:SF 0 "gpc_reg_operand" "=f,wy,wy")
+ [(set (match_operand:SF 0 "gpc_reg_operand" "=f,wa,wa")
(unsigned_float:SF (match_operand:DI 1 "memory_operand" "m,m,Z")))
- (clobber (match_scratch:DI 2 "=d,d,wi"))]
+ (clobber (match_scratch:DI 2 "=d,d,wa"))]
"TARGET_HARD_FLOAT && TARGET_FCFIDUS"
"#"
"&& reload_completed"
@@ -6343,8 +6377,9 @@
emit_insn (gen_floatunsdisf2_fcfidus (operands[0], operands[2]));
DONE;
}
- [(set_attr "length" "8")
- (set_attr "type" "fpload")])
+ [(set_attr "type" "fpload")
+ (set_attr "length" "8")
+ (set_attr "isa" "*,p8v,p8v")])
;; Define the TImode operations that can be done in a small number
;; of instructions. The & constraints are to prevent the register
@@ -6830,19 +6865,17 @@
;; MF%1 MT%0 NOP
(define_insn "*movsi_internal1"
[(set (match_operand:SI 0 "nonimmediate_operand"
- "=r, r, r, wI, wH,
+ "=r, r, r, d, v,
m, Z, Z, r, r,
- r, wIwH, wJwK, wJwK, wu,
- wJwK, wH, wK, wIwH, r,
+ r, wa, wa, wa, v,
+ wa, v, v, wa, r,
r, *h, *h")
-
(match_operand:SI 1 "input_operand"
"r, U, m, Z, Z,
- r, wI, wH, I, L,
- n, wIwH, O, wM, wB,
- O, wM, wS, r, wIwH,
+ r, d, v, I, L,
+ n, wa, O, wM, wB,
+ O, wM, wS, r, wa,
*h, r, 0"))]
-
"gpc_reg_operand (operands[0], SImode)
|| gpc_reg_operand (operands[1], SImode)"
"@
@@ -6875,13 +6908,18 @@
*, veclogical, vecsimple, vecsimple, vecsimple,
veclogical, veclogical, vecsimple, mffgpr, mftgpr,
*, *, *")
-
(set_attr "length"
- "4, 4, 4, 4, 4,
- 4, 4, 4, 4, 4,
- 8, 4, 4, 4, 4,
- 4, 4, 8, 4, 4,
- 4, 4, 4")])
+ "*, *, *, *, *,
+ *, *, *, *, *,
+ 8, *, *, *, *,
+ *, *, 8, *, *,
+ *, *, *")
+ (set_attr "isa"
+ "*, *, *, p8v, p8v,
+ *, p8v, p8v, *, *,
+ *, p8v, p9v, p9v, p8v,
+ p9v, p8v, p9v, p8v, p8v,
+ *, *, *")])
;; Like movsi, but adjust a SF value to be used in a SI context, i.e.
;; (set (reg:SI ...) (subreg:SI (reg:SF ...) 0))
@@ -6904,21 +6942,18 @@
(define_insn_and_split "movsi_from_sf"
[(set (match_operand:SI 0 "nonimmediate_operand"
- "=r, r, ?*wI, ?*wH, m,
- m, wY, Z, r, ?*wIwH,
- wIwH")
-
+ "=r, r, ?*d, ?*v, m,
+ m, wY, Z, r, ?*wa,
+ wa")
(unspec:SI [(match_operand:SF 1 "input_operand"
"r, m, Z, Z, r,
- f, wb, wu, wIwH, wIwH,
+ f, v, wa, wa, wa,
r")]
UNSPEC_SI_FROM_SF))
-
(clobber (match_scratch:V4SF 2
"=X, X, X, X, X,
- X, X, X, wIwH, X,
+ X, X, X, wa, X,
X"))]
-
"TARGET_NO_SF_SUBREG
&& (register_operand (operands[0], SImode)
|| register_operand (operands[1], SFmode))"
@@ -6953,11 +6988,14 @@
"*, load, fpload, fpload, store,
fpstore, fpstore, fpstore, mftgpr, fp,
mffgpr")
-
(set_attr "length"
- "4, 4, 4, 4, 4,
- 4, 4, 4, 8, 4,
- 4")])
+ "*, *, *, *, *,
+ *, *, *, 8, *,
+ *")
+ (set_attr "isa"
+ "*, *, p8v, p8v, *,
+ *, p9v, p8v, p8v, p8v,
+ p8v")])
;; movsi_from_sf with zero extension
;;
@@ -6966,19 +7004,16 @@
(define_insn_and_split "*movdi_from_sf_zero_ext"
[(set (match_operand:DI 0 "gpc_reg_operand"
- "=r, r, ?*wI, ?*wH, r,
- ?wK, wIwH")
-
+ "=r, r, ?*d, ?*v, r,
+ ?v, wa")
(zero_extend:DI
(unspec:SI [(match_operand:SF 1 "input_operand"
- "r, m, Z, Z, wIwH,
- wIwH, r")]
+ "r, m, Z, Z, wa,
+ wa, r")]
UNSPEC_SI_FROM_SF)))
-
(clobber (match_scratch:V4SF 2
"=X, X, X, X, wa,
- wIwH, X"))]
-
+ wa, X"))]
"TARGET_DIRECT_MOVE_64BIT
&& (register_operand (operands[0], DImode)
|| register_operand (operands[1], SImode))"
@@ -7007,10 +7042,12 @@
[(set_attr "type"
"*, load, fpload, fpload, two,
two, mffgpr")
-
(set_attr "length"
- "4, 4, 4, 4, 8,
- 8, 4")])
+ "*, *, *, *, 8,
+ 8, *")
+ (set_attr "isa"
+ "*, *, p8v, p8v, p8v,
+ p9v, p8v")])
;; Like movsi_from_sf, but combine a convert from DFmode to SFmode before
;; moving it to SImode. We cannot do a SFmode store without having to do the
@@ -7104,15 +7141,13 @@
;; MTVSRWZ MF%1 MT%1 NOP
(define_insn "*mov<mode>_internal"
[(set (match_operand:QHI 0 "nonimmediate_operand"
- "=r, r, wJwK, m, Z, r,
- wJwK, wJwK, wJwK, wK, ?wK, r,
- wJwK, r, *c*l, *h")
-
+ "=r, r, wa, m, Z, r,
+ wa, wa, wa, v, ?v, r,
+ wa, r, *c*l, *h")
(match_operand:QHI 1 "input_operand"
- "r, m, Z, r, wJwK, i,
- wJwK, O, wM, wB, wS, wJwK,
+ "r, m, Z, r, wa, i,
+ wa, O, wM, wB, wS, wa,
r, *h, r, 0"))]
-
"gpc_reg_operand (operands[0], <MODE>mode)
|| gpc_reg_operand (operands[1], <MODE>mode)"
"@
@@ -7136,11 +7171,14 @@
"*, load, fpload, store, fpstore, *,
vecsimple, vecperm, vecperm, vecperm, vecperm, mftgpr,
mffgpr, mfjmpr, mtjmpr, *")
-
(set_attr "length"
- "4, 4, 4, 4, 4, 4,
- 4, 4, 4, 4, 8, 4,
- 4, 4, 4, 4")])
+ "*, *, *, *, *, *,
+ *, *, *, *, 8, *,
+ *, *, *, *")
+ (set_attr "isa"
+ "*, *, p9v, *, p9v, *,
+ p9v, p9v, p9v, p9v, p9v, p9v,
+ p9v, *, *, *")])
;; Here is how to move condition codes around. When we store CC data in
@@ -7187,7 +7225,7 @@
(const_string "mtjmpr")
(const_string "load")
(const_string "store")])
- (set_attr "length" "4,4,12,4,4,8,4,4,4,4,4,4")])
+ (set_attr "length" "*,*,12,*,*,8,*,*,*,*,*,*")])
;; For floating-point, we normally deal with the floating-point registers
;; unless -msoft-float is used. The sole exception is that parameter passing
@@ -7242,12 +7280,12 @@
(define_insn "movsf_hardfloat"
[(set (match_operand:SF 0 "nonimmediate_operand"
- "=!r, f, wb, wu, m, wY,
- Z, m, ww, !r, f, ww,
+ "=!r, f, v, wa, m, wY,
+ Z, m, wa, !r, f, wa,
!r, *c*l, !r, *h")
(match_operand:SF 1 "input_operand"
- "m, m, wY, Z, f, wb,
- wu, r, j, j, f, ww,
+ "m, m, wY, Z, f, v,
+ wa, r, j, j, f, wa,
r, r, *h, 0"))]
"(register_operand (operands[0], SFmode)
|| register_operand (operands[1], SFmode))
@@ -7274,16 +7312,20 @@
[(set_attr "type"
"load, fpload, fpload, fpload, fpstore, fpstore,
fpstore, store, veclogical, integer, fpsimple, fpsimple,
- *, mtjmpr, mfjmpr, *")])
+ *, mtjmpr, mfjmpr, *")
+ (set_attr "isa"
+ "*, *, p9v, p8v, *, p9v,
+ p8v, *, *, *, *, *,
+ *, *, *, *")])
;; LWZ LFIWZX STW STFIWX MTVSRWZ MFVSRWZ
;; FMR MR MT%0 MF%1 NOP
(define_insn "movsd_hardfloat"
[(set (match_operand:SD 0 "nonimmediate_operand"
- "=!r, wz, m, Z, ?wh, ?r,
+ "=!r, d, m, Z, ?d, ?r,
f, !r, *c*l, !r, *h")
(match_operand:SD 1 "input_operand"
- "m, Z, r, wx, r, wh,
+ "m, Z, r, wx, r, d,
f, r, r, *h, 0"))]
"(register_operand (operands[0], SDmode)
|| register_operand (operands[1], SDmode))
@@ -7302,7 +7344,10 @@
nop"
[(set_attr "type"
"load, fpload, store, fpstore, mffgpr, mftgpr,
- fpsimple, *, mtjmpr, mfjmpr, *")])
+ fpsimple, *, mtjmpr, mfjmpr, *")
+ (set_attr "isa"
+ "*, p7, *, *, p8v, p8v,
+ *, *, *, *, *")])
;; MR MT%0 MF%0 LWZ STW LI
;; LIS G-const. F/n-const NOP
@@ -7331,11 +7376,11 @@
nop"
[(set_attr "type"
"*, mtjmpr, mfjmpr, load, store, *,
- *, *, *, *")
+ *, *, *, *")
(set_attr "length"
- "4, 4, 4, 4, 4, 4,
- 4, 4, 8, 4")])
+ "*, *, *, *, *, *,
+ *, *, 8, *")])
;; Like movsf, but adjust a SI value to be used in a SF context, i.e.
;; (set (reg:SF ...) (subreg:SF (reg:SI ...) 0))
@@ -7356,18 +7401,15 @@
;; STXSIWX GPR->VSX VSX->GPR GPR->GPR
(define_insn_and_split "movsf_from_si"
[(set (match_operand:SF 0 "nonimmediate_operand"
- "=!r, f, wb, wu, m, Z,
- Z, wy, ?r, !r")
-
+ "=!r, f, v, wa, m, Z,
+ Z, wa, ?r, !r")
(unspec:SF [(match_operand:SI 1 "input_operand"
"m, m, wY, Z, r, f,
- wu, r, wy, r")]
+ wa, r, wa, r")]
UNSPEC_SF_FROM_SI))
-
(clobber (match_scratch:DI 2
"=X, X, X, X, X, X,
X, r, X, X"))]
-
"TARGET_NO_SF_SUBREG
&& (register_operand (operands[0], SFmode)
|| register_operand (operands[1], SImode))"
@@ -7400,11 +7442,14 @@
DONE;
}
[(set_attr "length"
- "4, 4, 4, 4, 4, 4,
- 4, 12, 4, 4")
+ "*, *, *, *, *, *,
+ *, 12, *, *")
(set_attr "type"
"load, fpload, fpload, fpload, store, fpstore,
- fpstore, vecfloat, mffgpr, *")])
+ fpstore, vecfloat, mffgpr, *")
+ (set_attr "isa"
+ "*, *, p9v, p8v, *, *,
+ p8v, p8v, p8v, *")])
;; Move 64-bit binary/decimal floating point
@@ -7508,12 +7553,10 @@
"=m, d, d, <f64_p9>, wY,
<f64_av>, Z, <f64_vsx>, <f64_vsx>, !r,
Y, r, !r")
-
(match_operand:FMOVE64 1 "input_operand"
"d, m, d, wY, <f64_p9>,
Z, <f64_av>, <f64_vsx>, <zero_fp>, <zero_fp>,
r, Y, r"))]
-
"! TARGET_POWERPC64 && TARGET_HARD_FLOAT
&& (gpc_reg_operand (operands[0], <MODE>mode)
|| gpc_reg_operand (operands[1], <MODE>mode))"
@@ -7535,12 +7578,15 @@
"fpstore, fpload, fpsimple, fpload, fpstore,
fpload, fpstore, veclogical, veclogical, two,
store, load, two")
-
(set_attr "size" "64")
(set_attr "length"
- "4, 4, 4, 4, 4,
- 4, 4, 4, 4, 8,
- 8, 8, 8")])
+ "*, *, *, *, *,
+ *, *, *, *, 8,
+ 8, 8, 8")
+ (set_attr "isa"
+ "*, *, *, p9v, p9v,
+ p7v, p7v, *, *, *,
+ *, *, *")])
;; STW LWZ MR G-const H-const F-const
@@ -7567,21 +7613,19 @@
;; STFD LFD FMR LXSD STXSD
;; LXSDX STXSDX XXLOR XXLXOR LI 0
;; STD LD MR MT{CTR,LR} MF{CTR,LR}
-;; NOP MFTGPR MFFGPR MFVSRD MTVSRD
+;; NOP MFVSRD MTVSRD
(define_insn "*mov<mode>_hardfloat64"
[(set (match_operand:FMOVE64 0 "nonimmediate_operand"
"=m, d, d, <f64_p9>, wY,
<f64_av>, Z, <f64_vsx>, <f64_vsx>, !r,
YZ, r, !r, *c*l, !r,
- *h, r, wg, r, <f64_dm>")
-
+ *h, r, <f64_dm>")
(match_operand:FMOVE64 1 "input_operand"
"d, m, d, wY, <f64_p9>,
Z, <f64_av>, <f64_vsx>, <zero_fp>, <zero_fp>,
r, YZ, r, r, *h,
- 0, wg, r, <f64_dm>, r"))]
-
+ 0, <f64_dm>, r"))]
"TARGET_POWERPC64 && TARGET_HARD_FLOAT
&& (gpc_reg_operand (operands[0], <MODE>mode)
|| gpc_reg_operand (operands[1], <MODE>mode))"
@@ -7602,18 +7646,19 @@
mt%0 %1
mf%1 %0
nop
- mftgpr %0,%1
- mffgpr %0,%1
mfvsrd %0,%x1
mtvsrd %x0,%1"
[(set_attr "type"
"fpstore, fpload, fpsimple, fpload, fpstore,
fpload, fpstore, veclogical, veclogical, integer,
store, load, *, mtjmpr, mfjmpr,
- *, mftgpr, mffgpr, mftgpr, mffgpr")
-
+ *, mftgpr, mffgpr")
(set_attr "size" "64")
- (set_attr "length" "4")])
+ (set_attr "isa"
+ "*, *, *, p9v, p9v,
+ p7v, p7v, *, *, *,
+ *, *, *, *, *,
+ *, p8v, p8v")])
;; STD LD MR MT<SPR> MF<SPR> G-const
;; H-const F-const Special
@@ -7645,8 +7690,8 @@
*, *, *")
(set_attr "length"
- "4, 4, 4, 4, 4, 8,
- 12, 16, 4")])
+ "*, *, *, *, *, 8,
+ 12, 16, *")])
(define_expand "mov<mode>"
[(set (match_operand:FMOVE128 0 "general_operand")
@@ -7666,8 +7711,8 @@
;; problematical. Don't allow direct move for this case.
(define_insn_and_split "*mov<mode>_64bit_dm"
- [(set (match_operand:FMOVE128_FPR 0 "nonimmediate_operand" "=m,d,d,d,Y,r,r,r,wh")
- (match_operand:FMOVE128_FPR 1 "input_operand" "d,m,d,<zero_fp>,r,<zero_fp>Y,r,wh,r"))]
+ [(set (match_operand:FMOVE128_FPR 0 "nonimmediate_operand" "=m,d,d,d,Y,r,r,r,d")
+ (match_operand:FMOVE128_FPR 1 "input_operand" "d,m,d,<zero_fp>,r,<zero_fp>Y,r,d,r"))]
"TARGET_HARD_FLOAT && TARGET_POWERPC64 && FLOAT128_2REG_P (<MODE>mode)
&& (<MODE>mode != TDmode || WORDS_BIG_ENDIAN)
&& (gpc_reg_operand (operands[0], <MODE>mode)
@@ -7676,7 +7721,8 @@
"&& reload_completed"
[(pc)]
{ rs6000_split_multireg_move (operands[0], operands[1]); DONE; }
- [(set_attr "length" "8,8,8,8,12,12,8,8,8")])
+ [(set_attr "length" "8,8,8,8,12,12,8,8,8")
+ (set_attr "isa" "*,*,*,*,*,*,*,p8v,p8v")])
(define_insn_and_split "*movtd_64bit_nodm"
[(set (match_operand:TD 0 "nonimmediate_operand" "=m,d,d,Y,r,r")
@@ -7729,7 +7775,7 @@
(const_string "8")
(const_string "16"))])])
-(define_expand "extenddf<mode>2"
+(define_expand "@extenddf<mode>2"
[(set (match_operand:FLOAT128 0 "gpc_reg_operand")
(float_extend:FLOAT128 (match_operand:DF 1 "gpc_reg_operand")))]
"TARGET_HARD_FLOAT && TARGET_LONG_DOUBLE_128"
@@ -7737,31 +7783,20 @@
if (FLOAT128_IEEE_P (<MODE>mode))
rs6000_expand_float128_convert (operands[0], operands[1], false);
else if (TARGET_VSX)
- {
- if (<MODE>mode == TFmode)
- emit_insn (gen_extenddftf2_vsx (operands[0], operands[1]));
- else if (<MODE>mode == IFmode)
- emit_insn (gen_extenddfif2_vsx (operands[0], operands[1]));
- else
- gcc_unreachable ();
- }
- else
+ emit_insn (gen_extenddf2_vsx (<MODE>mode, operands[0], operands[1]));
+ else
{
rtx zero = gen_reg_rtx (DFmode);
rs6000_emit_move (zero, CONST0_RTX (DFmode), DFmode);
- if (<MODE>mode == TFmode)
- emit_insn (gen_extenddftf2_fprs (operands[0], operands[1], zero));
- else if (<MODE>mode == IFmode)
- emit_insn (gen_extenddfif2_fprs (operands[0], operands[1], zero));
- else
- gcc_unreachable ();
+ emit_insn (gen_extenddf2_fprs (<MODE>mode,
+ operands[0], operands[1], zero));
}
DONE;
})
;; Allow memory operands for the source to be created by the combiner.
-(define_insn_and_split "extenddf<mode>2_fprs"
+(define_insn_and_split "@extenddf<mode>2_fprs"
[(set (match_operand:IBM128 0 "gpc_reg_operand" "=d,d,&d")
(float_extend:IBM128
(match_operand:DF 1 "nonimmediate_operand" "d,m,d")))
@@ -7780,10 +7815,10 @@
operands[4] = simplify_gen_subreg (DFmode, operands[0], <MODE>mode, lo_word);
})
-(define_insn_and_split "extenddf<mode>2_vsx"
+(define_insn_and_split "@extenddf<mode>2_vsx"
[(set (match_operand:IBM128 0 "gpc_reg_operand" "=d,d")
(float_extend:IBM128
- (match_operand:DF 1 "nonimmediate_operand" "ws,m")))]
+ (match_operand:DF 1 "nonimmediate_operand" "wa,m")))]
"TARGET_LONG_DOUBLE_128 && TARGET_VSX && FLOAT128_IBM_P (<MODE>mode)"
"#"
"&& reload_completed"
@@ -7887,12 +7922,7 @@
{
rtx tmp = gen_reg_rtx (DFmode);
expand_float (tmp, op1, false);
- if (<MODE>mode == TFmode)
- emit_insn (gen_extenddftf2 (op0, tmp));
- else if (<MODE>mode == IFmode)
- emit_insn (gen_extenddfif2 (op0, tmp));
- else
- gcc_unreachable ();
+ emit_insn (gen_extenddf2 (<MODE>mode, op0, tmp));
DONE;
}
})
@@ -7923,17 +7953,13 @@
{
if (FLOAT128_IEEE_P (<MODE>mode))
rs6000_expand_float128_convert (op0, op1, false);
- else if (<MODE>mode == TFmode)
- emit_insn (gen_fix_trunctfsi2_fprs (op0, op1));
- else if (<MODE>mode == IFmode)
- emit_insn (gen_fix_truncifsi2_fprs (op0, op1));
else
- gcc_unreachable ();
+ emit_insn (gen_fix_truncsi2_fprs (<MODE>mode, op0, op1));
DONE;
}
})
-(define_expand "fix_trunc<mode>si2_fprs"
+(define_expand "@fix_trunc<mode>si2_fprs"
[(parallel [(set (match_operand:SI 0 "gpc_reg_operand")
(fix:SI (match_operand:IBM128 1 "gpc_reg_operand")))
(clobber (match_dup 2))
@@ -8042,23 +8068,10 @@
if (FLOAT128_IEEE_P (<MODE>mode))
{
if (TARGET_FLOAT128_HW)
- {
- if (<MODE>mode == TFmode)
- emit_insn (gen_negtf2_hw (operands[0], operands[1]));
- else if (<MODE>mode == KFmode)
- emit_insn (gen_negkf2_hw (operands[0], operands[1]));
- else
- gcc_unreachable ();
- }
+ emit_insn (gen_neg2_hw (<MODE>mode, operands[0], operands[1]));
else if (TARGET_FLOAT128_TYPE)
- {
- if (<MODE>mode == TFmode)
- emit_insn (gen_ieee_128bit_vsx_negtf2 (operands[0], operands[1]));
- else if (<MODE>mode == KFmode)
- emit_insn (gen_ieee_128bit_vsx_negkf2 (operands[0], operands[1]));
- else
- gcc_unreachable ();
- }
+ emit_insn (gen_ieee_128bit_vsx_neg2 (<MODE>mode,
+ operands[0], operands[1]));
else
{
rtx libfunc = optab_libfunc (neg_optab, <MODE>mode);
@@ -8098,22 +8111,13 @@
{
if (TARGET_FLOAT128_HW)
{
- if (<MODE>mode == TFmode)
- emit_insn (gen_abstf2_hw (operands[0], operands[1]));
- else if (<MODE>mode == KFmode)
- emit_insn (gen_abskf2_hw (operands[0], operands[1]));
- else
- FAIL;
+ emit_insn (gen_abs2_hw (<MODE>mode, operands[0], operands[1]));
DONE;
}
else if (TARGET_FLOAT128_TYPE)
{
- if (<MODE>mode == TFmode)
- emit_insn (gen_ieee_128bit_vsx_abstf2 (operands[0], operands[1]));
- else if (<MODE>mode == KFmode)
- emit_insn (gen_ieee_128bit_vsx_abskf2 (operands[0], operands[1]));
- else
- FAIL;
+ emit_insn (gen_ieee_128bit_vsx_abs2 (<MODE>mode,
+ operands[0], operands[1]));
DONE;
}
else
@@ -8121,17 +8125,12 @@
}
label = gen_label_rtx ();
- if (<MODE>mode == TFmode)
- emit_insn (gen_abstf2_internal (operands[0], operands[1], label));
- else if (<MODE>mode == IFmode)
- emit_insn (gen_absif2_internal (operands[0], operands[1], label));
- else
- FAIL;
+ emit_insn (gen_abs2_internal (<MODE>mode, operands[0], operands[1], label));
emit_label (label);
DONE;
})
-(define_expand "abs<mode>2_internal"
+(define_expand "@abs<mode>2_internal"
[(set (match_operand:IBM128 0 "gpc_reg_operand")
(match_operand:IBM128 1 "gpc_reg_operand"))
(set (match_dup 3) (match_dup 5))
@@ -8180,7 +8179,7 @@
;; twiddle the sign bit. Later GCSE passes can then combine multiple uses of
;; neg/abs to create the constant just once.
-(define_insn_and_split "ieee_128bit_vsx_neg<mode>2"
+(define_insn_and_split "@ieee_128bit_vsx_neg<mode>2"
[(set (match_operand:IEEE128 0 "register_operand" "=wa")
(neg:IEEE128 (match_operand:IEEE128 1 "register_operand" "wa")))
(clobber (match_scratch:V16QI 2 "=v"))]
@@ -8209,7 +8208,7 @@
[(set_attr "type" "veclogical")])
;; IEEE 128-bit absolute value
-(define_insn_and_split "ieee_128bit_vsx_abs<mode>2"
+(define_insn_and_split "@ieee_128bit_vsx_abs<mode>2"
[(set (match_operand:IEEE128 0 "register_operand" "=wa")
(abs:IEEE128 (match_operand:IEEE128 1 "register_operand" "wa")))
(clobber (match_scratch:V16QI 2 "=v"))]
@@ -8632,9 +8631,9 @@
(define_insn_and_split "reload_gpr_from_vsxsf"
[(set (match_operand:SF 0 "register_operand" "=r")
- (unspec:SF [(match_operand:SF 1 "register_operand" "ww")]
+ (unspec:SF [(match_operand:SF 1 "register_operand" "wa")]
UNSPEC_P8V_RELOAD_FROM_VSX))
- (clobber (match_operand:V4SF 2 "register_operand" "=wIwH"))]
+ (clobber (match_operand:V4SF 2 "register_operand" "=wa"))]
"TARGET_POWERPC64 && TARGET_DIRECT_MOVE"
"#"
"&& reload_completed"
@@ -8651,8 +8650,8 @@
DONE;
}
[(set_attr "length" "8")
- (set_attr "type" "two")])
-
+ (set_attr "type" "two")
+ (set_attr "isa" "p8v")])
;; Next come the multi-word integer load and store and the load and store
;; multiple insns.
@@ -8670,16 +8669,14 @@
(define_insn "*movdi_internal32"
[(set (match_operand:DI 0 "nonimmediate_operand"
"=Y, r, r, m, ^d, ^d,
- r, wY, Z, ^wb, $wv, ^wi,
- wo, wo, wv, wi, *i, wv,
- wv")
-
+ r, wY, Z, ^v, $v, ^wa,
+ wa, wa, v, wa, *i, v,
+ v")
(match_operand:DI 1 "input_operand"
"r, Y, r, ^d, m, ^d,
- IJKnF, ^wb, $wv, wY, Z, ^wi,
+ IJKnF, ^v, $v, wY, Z, ^wa,
Oj, wM, OjwM, Oj, wM, wS,
wB"))]
-
"! TARGET_POWERPC64
&& (gpc_reg_operand (operands[0], DImode)
|| gpc_reg_operand (operands[1], DImode))"
@@ -8710,10 +8707,15 @@
vecsimple")
(set_attr "size" "64")
(set_attr "length"
- "8, 8, 8, 4, 4, 4,
- 16, 4, 4, 4, 4, 4,
- 4, 4, 4, 4, 4, 8,
- 4")])
+ "8, 8, 8, *, *, *,
+ 16, *, *, *, *, *,
+ *, *, *, *, *, 8,
+ *")
+ (set_attr "isa"
+ "*, *, *, *, *, *,
+ *, p9v, p7v, p9v, p7v, *,
+ p9v, p9v, p7v, *, *, p7v,
+ p7v")])
(define_split
[(set (match_operand:DI 0 "gpc_reg_operand")
@@ -8746,22 +8748,20 @@
;; FPR store FPR load FPR move AVX store AVX store AVX load
;; AVX load VSX move P9 0 P9 -1 AVX 0/-1 VSX 0
;; VSX -1 P9 const AVX const From SPR To SPR SPR<->SPR
-;; FPR->GPR GPR->FPR VSX->GPR GPR->VSX
+;; VSX->GPR GPR->VSX
(define_insn "*movdi_internal64"
[(set (match_operand:DI 0 "nonimmediate_operand"
"=YZ, r, r, r, r, r,
- m, ^d, ^d, wY, Z, $wb,
- $wv, ^wi, wo, wo, wv, wi,
- wi, wv, wv, r, *h, *h,
- ?r, ?wg, ?r, ?wj")
-
+ m, ^d, ^d, wY, Z, $v,
+ $v, ^wa, wa, wa, v, wa,
+ wa, v, v, r, *h, *h,
+ ?r, ?wa")
(match_operand:DI 1 "input_operand"
"r, YZ, r, I, L, nF,
- ^d, m, ^d, ^wb, $wv, wY,
- Z, ^wi, Oj, wM, OjwM, Oj,
+ ^d, m, ^d, ^v, $v, wY,
+ Z, ^wa, Oj, wM, OjwM, Oj,
wM, wS, wB, *h, r, 0,
- wg, r, wj, r"))]
-
+ wa, r"))]
"TARGET_POWERPC64
&& (gpc_reg_operand (operands[0], DImode)
|| gpc_reg_operand (operands[1], DImode))"
@@ -8790,8 +8790,6 @@
mf%1 %0
mt%0 %1
nop
- mftgpr %0,%1
- mffgpr %0,%1
mfvsrd %0,%x1
mtvsrd %x0,%1"
[(set_attr "type"
@@ -8799,15 +8797,20 @@
fpstore, fpload, fpsimple, fpstore, fpstore, fpload,
fpload, veclogical, vecsimple, vecsimple, vecsimple, veclogical,
veclogical, vecsimple, vecsimple, mfjmpr, mtjmpr, *,
- mftgpr, mffgpr, mftgpr, mffgpr")
-
+ mftgpr, mffgpr")
(set_attr "size" "64")
(set_attr "length"
- "4, 4, 4, 4, 4, 20,
- 4, 4, 4, 4, 4, 4,
- 4, 4, 4, 4, 4, 4,
- 4, 8, 4, 4, 4, 4,
- 4, 4, 4, 4")])
+ "*, *, *, *, *, 20,
+ *, *, *, *, *, *,
+ *, *, *, *, *, *,
+ *, 8, *, *, *, *,
+ *, *")
+ (set_attr "isa"
+ "*, *, *, *, *, *,
+ *, *, *, p9v, p7v, p9v,
+ p7v, *, p9v, p9v, p7v, *,
+ *, p7v, p7v, *, *, *,
+ p8v, p8v")])
; Some DImode loads are best done as a load of -1 followed by a mask
; instruction.
@@ -9057,7 +9060,7 @@
;; Argument 2 is the length
;; Argument 3 is the alignment
-(define_expand "movmemsi"
+(define_expand "cpymemsi"
[(parallel [(set (match_operand:BLK 0 "")
(match_operand:BLK 1 ""))
(use (match_operand:SI 2 ""))
@@ -9319,8 +9322,8 @@
&& (!avoiding_indexed_address_p (<MODE>mode)
|| !gpc_reg_operand (operands[2], Pmode))"
"@
- lf<Fs>ux %3,%0,%2
- lf<Fs>u %3,%2(%0)"
+ lf<sd>ux %3,%0,%2
+ lf<sd>u %3,%2(%0)"
[(set_attr "type" "fpload")
(set_attr "update" "yes")
(set_attr "indexed" "yes,no")
@@ -9336,8 +9339,8 @@
&& (!avoiding_indexed_address_p (<MODE>mode)
|| !gpc_reg_operand (operands[2], Pmode))"
"@
- stf<Fs>ux %3,%0,%2
- stf<Fs>u %3,%2(%0)"
+ stf<sd>ux %3,%0,%2
+ stf<sd>u %3,%2(%0)"
[(set_attr "type" "fpstore")
(set_attr "update" "yes")
(set_attr "indexed" "yes,no")
@@ -9760,10 +9763,7 @@
{
operands[1] = force_reg (Pmode, operands[1]);
neg_op0 = gen_reg_rtx (Pmode);
- if (TARGET_32BIT)
- emit_insn (gen_negsi2 (neg_op0, operands[1]));
- else
- emit_insn (gen_negdi2 (neg_op0, operands[1]));
+ emit_insn (gen_neg2 (Pmode, neg_op0, operands[1]));
}
else
neg_op0 = GEN_INT (-INTVAL (operands[1]));
@@ -10150,7 +10150,7 @@
"TARGET_PLTSEQ
&& DEFAULT_ABI == ABI_ELFv2"
{
- return rs6000_pltseq_template (operands, 0);
+ return rs6000_pltseq_template (operands, RS6000_PLTSEQ_TOCSAVE);
})
(define_insn "*pltseq_plt16_ha_<mode>"
@@ -10161,7 +10161,7 @@
UNSPEC_PLT16_HA))]
"TARGET_PLTSEQ"
{
- return rs6000_pltseq_template (operands, 1);
+ return rs6000_pltseq_template (operands, RS6000_PLTSEQ_PLT16_HA);
})
(define_insn "*pltseq_plt16_lo_<mode>"
@@ -10172,7 +10172,7 @@
UNSPEC_PLT16_LO))]
"TARGET_PLTSEQ"
{
- return rs6000_pltseq_template (operands, 2);
+ return rs6000_pltseq_template (operands, RS6000_PLTSEQ_PLT16_LO);
}
[(set_attr "type" "load")])
@@ -10184,8 +10184,22 @@
UNSPEC_PLTSEQ))]
"TARGET_PLTSEQ"
{
- return rs6000_pltseq_template (operands, 3);
+ return rs6000_pltseq_template (operands, RS6000_PLTSEQ_MTCTR);
})
+
+(define_insn "*pltseq_plt_pcrel<mode>"
+ [(set (match_operand:P 0 "gpc_reg_operand" "=r")
+ (unspec:P [(match_operand:P 1 "" "")
+ (match_operand:P 2 "symbol_ref_operand" "s")
+ (match_operand:P 3 "" "")]
+ UNSPEC_PLT_PCREL))]
+ "HAVE_AS_PLTSEQ && TARGET_TLS_MARKERS
+ && rs6000_pcrel_p (cfun)"
+{
+ return rs6000_pltseq_template (operands, RS6000_PLTSEQ_PLT_PCREL34);
+}
+ [(set_attr "type" "load")
+ (set_attr "length" "12")])
;; Call and call_value insns
;; For the purposes of expanding calls, Darwin is very similar to SYSV.
@@ -10501,7 +10515,11 @@
(match_operand 1))
(clobber (reg:P LR_REGNO))]
"DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2"
- "bl %z0"
+{
+ if (rs6000_pcrel_p (cfun))
+ return "bl %z0@notoc";
+ return "bl %z0";
+}
[(set_attr "type" "branch")])
(define_insn "*call_value_local_aix<mode>"
@@ -10511,7 +10529,11 @@
(clobber (reg:P LR_REGNO))]
"(DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2)
&& !IS_NOMARK_TLSGETADDR (operands[2])"
- "bl %z1"
+{
+ if (rs6000_pcrel_p (cfun))
+ return "bl %z1@notoc";
+ return "bl %z1";
+}
[(set_attr "type" "branch")])
;; Call to AIX abi function which may be in another module.
@@ -10526,7 +10548,10 @@
return rs6000_call_template (operands, 0);
}
[(set_attr "type" "branch")
- (set_attr "length" "8")])
+ (set (attr "length")
+ (if_then_else (match_test "rs6000_pcrel_p (cfun)")
+ (const_int 4)
+ (const_int 8)))])
(define_insn "*call_value_nonlocal_aix<mode>"
[(set (match_operand 0 "" "")
@@ -10542,11 +10567,14 @@
}
[(set_attr "type" "branch")
(set (attr "length")
- (if_then_else (match_test "IS_NOMARK_TLSGETADDR (operands[2])")
- (if_then_else (match_test "TARGET_CMODEL != CMODEL_SMALL")
- (const_int 16)
- (const_int 12))
- (const_int 8)))])
+ (plus (if_then_else (match_test "IS_NOMARK_TLSGETADDR (operands[2])")
+ (if_then_else (match_test "TARGET_CMODEL != CMODEL_SMALL")
+ (const_int 8)
+ (const_int 4))
+ (const_int 0))
+ (if_then_else (match_test "rs6000_pcrel_p (cfun)")
+ (const_int 4)
+ (const_int 8))))])
;; Call to indirect functions with the AIX abi using a 3 word descriptor.
;; Operand0 is the addresss of the function to call
@@ -10619,6 +10647,21 @@
(const_string "12")
(const_string "8")))])
+(define_insn "*call_indirect_pcrel<mode>"
+ [(call (mem:SI (match_operand:P 0 "indirect_call_operand" "c,*l,X"))
+ (match_operand 1))
+ (clobber (reg:P LR_REGNO))]
+ "rs6000_pcrel_p (cfun)"
+{
+ return rs6000_indirect_call_template (operands, 0);
+}
+ [(set_attr "type" "jmpreg")
+ (set (attr "length")
+ (if_then_else (and (match_test "!rs6000_speculate_indirect_jumps")
+ (match_test "which_alternative != 1"))
+ (const_string "8")
+ (const_string "4")))])
+
(define_insn "*call_value_indirect_elfv2<mode>"
[(set (match_operand 0 "" "")
(call (mem:SI (match_operand:P 1 "indirect_call_operand" "c,*l,X"))
@@ -10647,6 +10690,31 @@
(const_string "12")
(const_string "8"))))])
+(define_insn "*call_value_indirect_pcrel<mode>"
+ [(set (match_operand 0 "" "")
+ (call (mem:SI (match_operand:P 1 "indirect_call_operand" "c,*l,X"))
+ (match_operand:P 2 "unspec_tls" "")))
+ (clobber (reg:P LR_REGNO))]
+ "rs6000_pcrel_p (cfun)"
+{
+ if (IS_NOMARK_TLSGETADDR (operands[2]))
+ rs6000_output_tlsargs (operands);
+
+ return rs6000_indirect_call_template (operands, 1);
+}
+ [(set_attr "type" "jmpreg")
+ (set (attr "length")
+ (plus
+ (if_then_else (match_test "IS_NOMARK_TLSGETADDR (operands[2])")
+ (if_then_else (match_test "TARGET_CMODEL != CMODEL_SMALL")
+ (const_int 8)
+ (const_int 4))
+ (const_int 0))
+ (if_then_else (and (match_test "!rs6000_speculate_indirect_jumps")
+ (match_test "which_alternative != 1"))
+ (const_string "8")
+ (const_string "4"))))])
+
;; Call subroutine returning any type.
(define_expand "untyped_call"
[(parallel [(call (match_operand 0 "")
@@ -10941,7 +11009,7 @@
{
if (!TARGET_SCHED_PROLOG)
emit_insn (gen_blockage ());
- rs6000_emit_epilogue (TRUE);
+ rs6000_emit_epilogue (EPILOGUE_TYPE_SIBCALL);
DONE;
})
@@ -12304,10 +12372,7 @@
{
if (!rs6000_speculate_indirect_jumps) {
rtx ccreg = gen_reg_rtx (CCmode);
- if (Pmode == DImode)
- emit_jump_insn (gen_indirect_jumpdi_nospec (operands[0], ccreg));
- else
- emit_jump_insn (gen_indirect_jumpsi_nospec (operands[0], ccreg));
+ emit_jump_insn (gen_indirect_jump_nospec (Pmode, operands[0], ccreg));
DONE;
}
})
@@ -12319,7 +12384,7 @@
"b%T0"
[(set_attr "type" "jmpreg")])
-(define_insn "indirect_jump<mode>_nospec"
+(define_insn "@indirect_jump<mode>_nospec"
[(set (pc) (match_operand:P 0 "register_operand" "c,*l"))
(clobber (match_operand:CC 1 "cc_reg_operand" "=y,y"))]
"!rs6000_speculate_indirect_jumps"
@@ -12463,22 +12528,14 @@
(use (match_operand 1))] ; label
""
{
- if (TARGET_64BIT)
- {
- if (GET_MODE (operands[0]) != DImode)
- FAIL;
- emit_jump_insn (gen_ctrdi (operands[0], operands[1]));
- }
- else
- {
- if (GET_MODE (operands[0]) != SImode)
- FAIL;
- emit_jump_insn (gen_ctrsi (operands[0], operands[1]));
- }
+ if (GET_MODE (operands[0]) != Pmode)
+ FAIL;
+
+ emit_jump_insn (gen_ctr (Pmode, operands[0], operands[1]));
DONE;
})
-(define_expand "ctr<mode>"
+(define_expand "@ctr<mode>"
[(parallel [(set (pc)
(if_then_else (ne (match_operand:P 0 "register_operand")
(const_int 1))
@@ -12510,7 +12567,7 @@
(const_int 1))
(label_ref (match_operand 0))
(pc)))
- (set (match_operand:P 2 "nonimmediate_operand" "=1,*r,m,*d*wi*c*l")
+ (set (match_operand:P 2 "nonimmediate_operand" "=1,*r,m,*d*wa*c*l")
(plus:P (match_dup 1)
(const_int -1)))
(clobber (match_scratch:CC 3 "=X,&x,&x,&x"))
@@ -12586,7 +12643,7 @@
(const_int 0)]))
(label_ref (match_operand 0))
(pc)))
- (set (match_operand:P 2 "nonimmediate_operand" "=1,*r,m,*d*wi*c*l")
+ (set (match_operand:P 2 "nonimmediate_operand" "=1,*r,m,*d*wa*c*l")
(plus:P (match_dup 1)
(const_int -1)))
(clobber (match_scratch:P 5 "=X,X,&r,r"))
@@ -12881,7 +12938,7 @@
{
if (!TARGET_SCHED_PROLOG)
emit_insn (gen_blockage ());
- rs6000_emit_epilogue (FALSE);
+ rs6000_emit_epilogue (EPILOGUE_TYPE_NORMAL);
DONE;
})
@@ -13089,24 +13146,16 @@
[(use (match_operand 0 "general_operand"))]
""
{
- if (TARGET_32BIT)
- emit_insn (gen_eh_set_lr_si (operands[0]));
- else
- emit_insn (gen_eh_set_lr_di (operands[0]));
+ emit_insn (gen_eh_set_lr (Pmode, operands[0]));
DONE;
})
; We can't expand this before we know where the link register is stored.
-(define_insn "eh_set_lr_<mode>"
- [(unspec_volatile [(match_operand:P 0 "register_operand" "r")]
- UNSPECV_EH_RR)
+(define_insn_and_split "@eh_set_lr_<mode>"
+ [(unspec_volatile [(match_operand:P 0 "register_operand" "r")] UNSPECV_EH_RR)
(clobber (match_scratch:P 1 "=&b"))]
""
- "#")
-
-(define_split
- [(unspec_volatile [(match_operand 0 "register_operand")] UNSPECV_EH_RR)
- (clobber (match_scratch 1))]
+ "#"
"reload_completed"
[(const_int 0)]
{
@@ -13235,17 +13284,18 @@
"")
(define_insn "*fma<mode>4_fpr"
- [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<Ff>,<Fv2>,<Fv2>")
+ [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<Ff>,wa,wa")
(fma:SFDF
- (match_operand:SFDF 1 "gpc_reg_operand" "%<Ff>,<Fv2>,<Fv2>")
- (match_operand:SFDF 2 "gpc_reg_operand" "<Ff>,<Fv2>,0")
- (match_operand:SFDF 3 "gpc_reg_operand" "<Ff>,0,<Fv2>")))]
+ (match_operand:SFDF 1 "gpc_reg_operand" "%<Ff>,wa,wa")
+ (match_operand:SFDF 2 "gpc_reg_operand" "<Ff>,wa,0")
+ (match_operand:SFDF 3 "gpc_reg_operand" "<Ff>,0,wa")))]
"TARGET_HARD_FLOAT"
"@
- fmadd<Ftrad> %0,%1,%2,%3
- xsmadda<Fvsx> %x0,%x1,%x2
- xsmaddm<Fvsx> %x0,%x1,%x3"
- [(set_attr "type" "fp")])
+ fmadd<s> %0,%1,%2,%3
+ xsmadda<sd>p %x0,%x1,%x2
+ xsmaddm<sd>p %x0,%x1,%x3"
+ [(set_attr "type" "fp")
+ (set_attr "isa" "*,<Fisa>,<Fisa>")])
; Altivec only has fma and nfms.
(define_expand "fms<mode>4"
@@ -13258,17 +13308,18 @@
"")
(define_insn "*fms<mode>4_fpr"
- [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<Ff>,<Fv2>,<Fv2>")
+ [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<Ff>,wa,wa")
(fma:SFDF
- (match_operand:SFDF 1 "gpc_reg_operand" "<Ff>,<Fv2>,<Fv2>")
- (match_operand:SFDF 2 "gpc_reg_operand" "<Ff>,<Fv2>,0")
- (neg:SFDF (match_operand:SFDF 3 "gpc_reg_operand" "<Ff>,0,<Fv2>"))))]
+ (match_operand:SFDF 1 "gpc_reg_operand" "<Ff>,wa,wa")
+ (match_operand:SFDF 2 "gpc_reg_operand" "<Ff>,wa,0")
+ (neg:SFDF (match_operand:SFDF 3 "gpc_reg_operand" "<Ff>,0,wa"))))]
"TARGET_HARD_FLOAT"
"@
- fmsub<Ftrad> %0,%1,%2,%3
- xsmsuba<Fvsx> %x0,%x1,%x2
- xsmsubm<Fvsx> %x0,%x1,%x3"
- [(set_attr "type" "fp")])
+ fmsub<s> %0,%1,%2,%3
+ xsmsuba<sd>p %x0,%x1,%x2
+ xsmsubm<sd>p %x0,%x1,%x3"
+ [(set_attr "type" "fp")
+ (set_attr "isa" "*,<Fisa>,<Fisa>")])
;; If signed zeros are ignored, -(a * b - c) = -a * b + c.
(define_expand "fnma<mode>4"
@@ -13304,18 +13355,19 @@
"")
(define_insn "*nfma<mode>4_fpr"
- [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<Ff>,<Fv2>,<Fv2>")
+ [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<Ff>,wa,wa")
(neg:SFDF
(fma:SFDF
- (match_operand:SFDF 1 "gpc_reg_operand" "<Ff>,<Fv2>,<Fv2>")
- (match_operand:SFDF 2 "gpc_reg_operand" "<Ff>,<Fv2>,0")
- (match_operand:SFDF 3 "gpc_reg_operand" "<Ff>,0,<Fv2>"))))]
+ (match_operand:SFDF 1 "gpc_reg_operand" "<Ff>,wa,wa")
+ (match_operand:SFDF 2 "gpc_reg_operand" "<Ff>,wa,0")
+ (match_operand:SFDF 3 "gpc_reg_operand" "<Ff>,0,wa"))))]
"TARGET_HARD_FLOAT"
"@
- fnmadd<Ftrad> %0,%1,%2,%3
- xsnmadda<Fvsx> %x0,%x1,%x2
- xsnmaddm<Fvsx> %x0,%x1,%x3"
- [(set_attr "type" "fp")])
+ fnmadd<s> %0,%1,%2,%3
+ xsnmadda<sd>p %x0,%x1,%x2
+ xsnmaddm<sd>p %x0,%x1,%x3"
+ [(set_attr "type" "fp")
+ (set_attr "isa" "*,<Fisa>,<Fisa>")])
; Not an official optab name, but used from builtins.
(define_expand "nfms<mode>4"
@@ -13329,20 +13381,20 @@
"")
(define_insn "*nfmssf4_fpr"
- [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<Ff>,<Fv2>,<Fv2>")
+ [(set (match_operand:SFDF 0 "gpc_reg_operand" "=<Ff>,wa,wa")
(neg:SFDF
(fma:SFDF
- (match_operand:SFDF 1 "gpc_reg_operand" "<Ff>,<Fv2>,<Fv2>")
- (match_operand:SFDF 2 "gpc_reg_operand" "<Ff>,<Fv2>,0")
+ (match_operand:SFDF 1 "gpc_reg_operand" "<Ff>,wa,wa")
+ (match_operand:SFDF 2 "gpc_reg_operand" "<Ff>,wa,0")
(neg:SFDF
- (match_operand:SFDF 3 "gpc_reg_operand" "<Ff>,0,<Fv2>")))))]
+ (match_operand:SFDF 3 "gpc_reg_operand" "<Ff>,0,wa")))))]
"TARGET_HARD_FLOAT"
"@
- fnmsub<Ftrad> %0,%1,%2,%3
- xsnmsuba<Fvsx> %x0,%x1,%x2
- xsnmsubm<Fvsx> %x0,%x1,%x3"
- [(set_attr "type" "fp")])
-
+ fnmsub<s> %0,%1,%2,%3
+ xsnmsuba<sd>p %x0,%x1,%x2
+ xsnmsubm<sd>p %x0,%x1,%x3"
+ [(set_attr "type" "fp")
+ (set_attr "isa" "*,<Fisa>,<Fisa>")])
(define_expand "rs6000_get_timebase"
[(use (match_operand:DI 0 "gpc_reg_operand"))]
@@ -13831,7 +13883,7 @@
[(set_attr "type" "veccomplex")
(set_attr "length" "8")])
-(define_insn "neg<mode>2_hw"
+(define_insn "@neg<mode>2_hw"
[(set (match_operand:IEEE128 0 "altivec_register_operand" "=v")
(neg:IEEE128
(match_operand:IEEE128 1 "altivec_register_operand" "v")))]
@@ -13841,7 +13893,7 @@
(set_attr "size" "128")])
-(define_insn "abs<mode>2_hw"
+(define_insn "@abs<mode>2_hw"
[(set (match_operand:IEEE128 0 "altivec_register_operand" "=v")
(abs:IEEE128
(match_operand:IEEE128 1 "altivec_register_operand" "v")))]
@@ -13966,7 +14018,7 @@
;; the KFmode -> DFmode conversion using round to odd rather than the normal
;; conversion
(define_insn_and_split "trunc<mode>sf2_hw"
- [(set (match_operand:SF 0 "vsx_register_operand" "=wy")
+ [(set (match_operand:SF 0 "vsx_register_operand" "=wa")
(float_truncate:SF
(match_operand:IEEE128 1 "altivec_register_operand" "v")))
(clobber (match_scratch:DF 2 "=v"))]
@@ -13983,7 +14035,8 @@
operands[2] = gen_reg_rtx (DFmode);
}
[(set_attr "type" "vecfloat")
- (set_attr "length" "8")])
+ (set_attr "length" "8")
+ (set_attr "isa" "p8v")])
;; Conversion between IEEE 128-bit and integer types
diff --git a/gcc/config/rs6000/rs6000.opt b/gcc/config/rs6000/rs6000.opt
index f4b5c91..342a349 100644
--- a/gcc/config/rs6000/rs6000.opt
+++ b/gcc/config/rs6000/rs6000.opt
@@ -144,9 +144,12 @@ mcmpb
Target Report Mask(CMPB) Var(rs6000_isa_flags)
Use PowerPC V2.05 compare bytes instruction.
+;; This option existed in the past, but now is always off.
+mno-mfpgpr
+Target RejectNegative Undocumented Ignore
+
mmfpgpr
-Target Report Mask(MFPGPR) Var(rs6000_isa_flags)
-Use extended PowerPC V2.05 move floating point to/from GPR instructions.
+Target RejectNegative Undocumented Deprecated
maltivec
Target Report Mask(ALTIVEC) Var(rs6000_isa_flags)
@@ -569,3 +572,15 @@ long rs6000_stack_protector_guard_offset = 0
;; branches via the CTR.
mspeculate-indirect-jumps
Target Undocumented Var(rs6000_speculate_indirect_jumps) Init(1) Save
+
+mfuture
+Target Report Mask(FUTURE) Var(rs6000_isa_flags)
+Use instructions for a future architecture.
+
+mprefixed-addr
+Target Undocumented Mask(PREFIXED_ADDR) Var(rs6000_isa_flags)
+Generate (do not generate) prefixed memory instructions.
+
+mpcrel
+Target Report Mask(PCREL) Var(rs6000_isa_flags)
+Generate (do not generate) pc-relative memory addressing.
diff --git a/gcc/config/rs6000/t-rs6000 b/gcc/config/rs6000/t-rs6000
index 7d5727f..c689d51 100644
--- a/gcc/config/rs6000/t-rs6000
+++ b/gcc/config/rs6000/t-rs6000
@@ -39,6 +39,10 @@ rs6000-d.o: $(srcdir)/config/rs6000/rs6000-d.c
$(COMPILE) $<
$(POSTCOMPILE)
+rs6000-logue.o: $(srcdir)/config/rs6000/rs6000-logue.c
+ $(COMPILE) $<
+ $(POSTCOMPILE)
+
$(srcdir)/config/rs6000/rs6000-tables.opt: $(srcdir)/config/rs6000/genopt.sh \
$(srcdir)/config/rs6000/rs6000-cpus.def
$(SHELL) $(srcdir)/config/rs6000/genopt.sh $(srcdir)/config/rs6000 > \
diff --git a/gcc/config/rs6000/vsx.md b/gcc/config/rs6000/vsx.md
index 80434d1..c33b45a 100644
--- a/gcc/config/rs6000/vsx.md
+++ b/gcc/config/rs6000/vsx.md
@@ -93,82 +93,35 @@
(V1TI "vd2")
(TI "vd2")])
-;; Map into the appropriate suffix based on the type
-(define_mode_attr VSs [(V16QI "sp")
- (V8HI "sp")
- (V4SI "sp")
- (V4SF "sp")
- (V2DF "dp")
- (V2DI "dp")
- (DF "dp")
- (SF "sp")
- (TF "dp")
- (KF "dp")
- (V1TI "dp")
- (TI "dp")])
-
;; Map the register class used
(define_mode_attr VSr [(V16QI "v")
(V8HI "v")
(V4SI "v")
- (V4SF "wf")
- (V2DI "wd")
- (V2DF "wd")
- (DI "wi")
- (DF "ws")
- (SF "ww")
- (TF "wp")
- (KF "wq")
- (V1TI "v")
- (TI "wt")])
-
-;; Map the register class used for float<->int conversions (floating point side)
-;; VSr2 is the preferred register class, VSr3 is any register class that will
-;; hold the data
-(define_mode_attr VSr2 [(V2DF "wd")
- (V4SF "wf")
- (DF "ws")
- (SF "ww")
- (DI "wi")
- (KF "wq")
- (TF "wp")])
-
-(define_mode_attr VSr3 [(V2DF "wa")
- (V4SF "wa")
- (DF "ws")
- (SF "ww")
- (DI "wi")
- (KF "wq")
- (TF "wp")])
-
-;; Map the register class for sp<->dp float conversions, destination
-(define_mode_attr VSr4 [(SF "ws")
- (DF "f")
- (V2DF "wd")
- (V4SF "v")])
-
-;; Map the register class for sp<->dp float conversions, source
-(define_mode_attr VSr5 [(SF "ws")
- (DF "f")
- (V2DF "v")
- (V4SF "wd")])
-
-;; The VSX register class that a type can occupy, even if it is not the
-;; preferred register class (VSr is the preferred register class that will get
-;; allocated first).
-(define_mode_attr VSa [(V16QI "wa")
- (V8HI "wa")
- (V4SI "wa")
(V4SF "wa")
(V2DI "wa")
(V2DF "wa")
- (DI "wi")
- (DF "ws")
- (SF "ww")
- (V1TI "wa")
- (TI "wt")
- (TF "wp")
- (KF "wq")])
+ (DI "wa")
+ (DF "wa")
+ (SF "wa")
+ (TF "wa")
+ (KF "wa")
+ (V1TI "v")
+ (TI "wa")])
+
+;; What value we need in the "isa" field, to make the IEEE QP float work.
+(define_mode_attr VSisa [(V16QI "*")
+ (V8HI "*")
+ (V4SI "*")
+ (V4SF "*")
+ (V2DI "*")
+ (V2DF "*")
+ (DI "*")
+ (DF "*")
+ (SF "*")
+ (V1TI "*")
+ (TI "*")
+ (TF "p9tf")
+ (KF "p9kf")])
;; A mode attribute to disparage use of GPR registers, except for scalar
;; integer modes.
@@ -236,29 +189,6 @@
(V4SF "vecfdiv")
(DF "ddiv")])
-;; Appropriate type for sqrt ops. For now, just lump the vector sqrt with
-;; the scalar sqrt
-(define_mode_attr VStype_sqrt [(V2DF "dsqrt")
- (V4SF "ssqrt")
- (DF "dsqrt")])
-
-;; Iterator and modes for sp<->dp conversions
-;; Because scalar SF values are represented internally as double, use the
-;; V4SF type to represent this than SF.
-(define_mode_iterator VSX_SPDP [DF V4SF V2DF])
-
-(define_mode_attr VS_spdp_res [(DF "V4SF")
- (V4SF "V2DF")
- (V2DF "V4SF")])
-
-(define_mode_attr VS_spdp_insn [(DF "xscvdpsp")
- (V4SF "xvcvspdp")
- (V2DF "xvcvdpsp")])
-
-(define_mode_attr VS_spdp_type [(DF "fp")
- (V4SF "vecdouble")
- (V2DF "vecdouble")])
-
;; Map the scalar mode for a vector type
(define_mode_attr VS_scalar [(V1TI "TI")
(V2DF "DF")
@@ -275,16 +205,6 @@
(V2DF "V4DF")
(V1TI "V2TI")])
-;; Map register class for 64-bit element in 128-bit vector for direct moves
-;; to/from gprs
-(define_mode_attr VS_64dm [(V2DF "wk")
- (V2DI "wj")])
-
-;; Map register class for 64-bit element in 128-bit vector for normal register
-;; to register moves
-(define_mode_attr VS_64reg [(V2DF "ws")
- (V2DI "wi")])
-
;; Iterators for loading constants with xxspltib
(define_mode_iterator VSINT_84 [V4SI V2DI DI SI])
(define_mode_iterator VSINT_842 [V8HI V4SI V2DI])
@@ -439,7 +359,7 @@
;; The patterns for LE permuted loads and stores come before the general
;; VSX moves so they match first.
(define_insn_and_split "*vsx_le_perm_load_<mode>"
- [(set (match_operand:VSX_D 0 "vsx_register_operand" "=<VSa>")
+ [(set (match_operand:VSX_D 0 "vsx_register_operand" "=wa")
(match_operand:VSX_D 1 "indexed_or_indirect_operand" "Z"))]
"!BYTES_BIG_ENDIAN && TARGET_VSX && !TARGET_P9_VECTOR"
"#"
@@ -487,7 +407,7 @@
(set_attr "length" "8")])
(define_insn_and_split "*vsx_le_perm_load_<mode>"
- [(set (match_operand:VSX_W 0 "vsx_register_operand" "=<VSa>")
+ [(set (match_operand:VSX_W 0 "vsx_register_operand" "=wa")
(match_operand:VSX_W 1 "indexed_or_indirect_operand" "Z"))]
"!BYTES_BIG_ENDIAN && TARGET_VSX && !TARGET_P9_VECTOR"
"#"
@@ -654,7 +574,7 @@
(define_insn "*vsx_le_perm_store_<mode>"
[(set (match_operand:VSX_D 0 "indexed_or_indirect_operand" "=Z")
- (match_operand:VSX_D 1 "vsx_register_operand" "+<VSa>"))]
+ (match_operand:VSX_D 1 "vsx_register_operand" "+wa"))]
"!BYTES_BIG_ENDIAN && TARGET_VSX && !TARGET_P9_VECTOR"
"#"
[(set_attr "type" "vecstore")
@@ -724,7 +644,7 @@
(define_insn "*vsx_le_perm_store_<mode>"
[(set (match_operand:VSX_W 0 "indexed_or_indirect_operand" "=Z")
- (match_operand:VSX_W 1 "vsx_register_operand" "+<VSa>"))]
+ (match_operand:VSX_W 1 "vsx_register_operand" "+wa"))]
"!BYTES_BIG_ENDIAN && TARGET_VSX && !TARGET_P9_VECTOR"
"#"
[(set_attr "type" "vecstore")
@@ -991,9 +911,9 @@
;; special V1TI container class, which it is not appropriate to use vec_select
;; for the type.
(define_insn "*vsx_le_permute_<mode>"
- [(set (match_operand:VSX_TI 0 "nonimmediate_operand" "=<VSa>,<VSa>,Z,&r,&r,Q")
+ [(set (match_operand:VSX_TI 0 "nonimmediate_operand" "=wa,wa,Z,&r,&r,Q")
(rotate:VSX_TI
- (match_operand:VSX_TI 1 "input_operand" "<VSa>,Z,<VSa>,r,Q,r")
+ (match_operand:VSX_TI 1 "input_operand" "wa,Z,wa,r,Q,r")
(const_int 64)))]
"!BYTES_BIG_ENDIAN && TARGET_VSX && !TARGET_P9_VECTOR"
"@
@@ -1003,14 +923,14 @@
mr %0,%L1\;mr %L0,%1
ld%U1%X1 %0,%L1\;ld%U1%X1 %L0,%1
std%U0%X0 %L1,%0\;std%U0%X0 %1,%L0"
- [(set_attr "length" "4,4,4,8,8,8")
+ [(set_attr "length" "*,*,*,8,8,8")
(set_attr "type" "vecperm,vecload,vecstore,*,load,store")])
(define_insn_and_split "*vsx_le_undo_permute_<mode>"
- [(set (match_operand:VSX_TI 0 "vsx_register_operand" "=<VSa>,<VSa>")
+ [(set (match_operand:VSX_TI 0 "vsx_register_operand" "=wa,wa")
(rotate:VSX_TI
(rotate:VSX_TI
- (match_operand:VSX_TI 1 "vsx_register_operand" "0,<VSa>")
+ (match_operand:VSX_TI 1 "vsx_register_operand" "0,wa")
(const_int 64))
(const_int 64)))]
"!BYTES_BIG_ENDIAN && TARGET_VSX"
@@ -1030,7 +950,7 @@
(set_attr "type" "veclogical")])
(define_insn_and_split "*vsx_le_perm_load_<mode>"
- [(set (match_operand:VSX_LE_128 0 "vsx_register_operand" "=<VSa>,r")
+ [(set (match_operand:VSX_LE_128 0 "vsx_register_operand" "=wa,r")
(match_operand:VSX_LE_128 1 "memory_operand" "Z,Q"))]
"!BYTES_BIG_ENDIAN && TARGET_VSX && !TARGET_P9_VECTOR"
"@
@@ -1047,17 +967,19 @@
DONE;
}
[(set_attr "type" "vecload,load")
- (set_attr "length" "8,8")])
+ (set_attr "length" "8,8")
+ (set_attr "isa" "<VSisa>,*")])
(define_insn "*vsx_le_perm_store_<mode>"
[(set (match_operand:VSX_LE_128 0 "memory_operand" "=Z,Q")
- (match_operand:VSX_LE_128 1 "vsx_register_operand" "+<VSa>,r"))]
+ (match_operand:VSX_LE_128 1 "vsx_register_operand" "+wa,r"))]
"!BYTES_BIG_ENDIAN && TARGET_VSX && !TARGET_P9_VECTOR"
"@
#
#"
[(set_attr "type" "vecstore,store")
- (set_attr "length" "12,8")])
+ (set_attr "length" "12,8")
+ (set_attr "isa" "<VSisa>,*")])
(define_split
[(set (match_operand:VSX_LE_128 0 "memory_operand")
@@ -1208,12 +1130,12 @@
;; VSX 0/-1 VMX const GPR const LVX (VMX) STVX (VMX)
(define_insn "vsx_mov<mode>_64bit"
[(set (match_operand:VSX_M 0 "nonimmediate_operand"
- "=ZwO, <VSa>, <VSa>, r, we, ?wQ,
- ?&r, ??r, ??Y, <??r>, wo, v,
- ?<VSa>, v, <??r>, wZ, v")
+ "=ZwO, wa, wa, r, we, ?wQ,
+ ?&r, ??r, ??Y, <??r>, wa, v,
+ ?wa, v, <??r>, wZ, v")
(match_operand:VSX_M 1 "input_operand"
- "<VSa>, ZwO, <VSa>, we, r, r,
+ "wa, ZwO, wa, we, r, r,
wQ, Y, r, r, wE, jwM,
?jwM, W, <nW>, v, wZ"))]
@@ -1227,23 +1149,26 @@
"vecstore, vecload, vecsimple, mffgpr, mftgpr, load,
store, load, store, *, vecsimple, vecsimple,
vecsimple, *, *, vecstore, vecload")
-
(set_attr "length"
- "4, 4, 4, 8, 4, 8,
- 8, 8, 8, 8, 4, 4,
- 4, 20, 8, 4, 4")])
+ "*, *, *, 8, *, 8,
+ 8, 8, 8, 8, *, *,
+ *, 20, 8, *, *")
+ (set_attr "isa"
+ "<VSisa>, <VSisa>, <VSisa>, *, *, *,
+ *, *, *, *, p9v, *,
+ <VSisa>, *, *, *, *")])
;; VSX store VSX load VSX move GPR load GPR store GPR move
;; XXSPLTIB VSPLTISW VSX 0/-1 VMX const GPR const
;; LVX (VMX) STVX (VMX)
(define_insn "*vsx_mov<mode>_32bit"
[(set (match_operand:VSX_M 0 "nonimmediate_operand"
- "=ZwO, <VSa>, <VSa>, ??r, ??Y, <??r>,
- wo, v, ?<VSa>, v, <??r>,
+ "=ZwO, wa, wa, ??r, ??Y, <??r>,
+ wa, v, ?wa, v, <??r>,
wZ, v")
(match_operand:VSX_M 1 "input_operand"
- "<VSa>, ZwO, <VSa>, Y, r, r,
+ "wa, ZwO, wa, Y, r, r,
wE, jwM, ?jwM, W, <nW>,
v, wZ"))]
@@ -1257,11 +1182,14 @@
"vecstore, vecload, vecsimple, load, store, *,
vecsimple, vecsimple, vecsimple, *, *,
vecstore, vecload")
-
(set_attr "length"
- "4, 4, 4, 16, 16, 16,
- 4, 4, 4, 20, 16,
- 4, 4")])
+ "*, *, *, 16, 16, 16,
+ *, *, *, 20, 16,
+ *, *")
+ (set_attr "isa"
+ "<VSisa>, <VSisa>, <VSisa>, *, *, *,
+ p9v, *, <VSisa>, *, *,
+ *, *")])
;; Explicit load/store expanders for the builtin functions
(define_expand "vsx_load_<mode>"
@@ -1603,27 +1531,27 @@
;; instructions are now combined with the insn for the traditional floating
;; point unit.
(define_insn "*vsx_add<mode>3"
- [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?<VSa>")
- (plus:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,<VSa>")
- (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>,<VSa>")))]
+ [(set (match_operand:VSX_F 0 "vsx_register_operand" "=wa")
+ (plus:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "wa")
+ (match_operand:VSX_F 2 "vsx_register_operand" "wa")))]
"VECTOR_UNIT_VSX_P (<MODE>mode)"
- "xvadd<VSs> %x0,%x1,%x2"
+ "xvadd<sd>p %x0,%x1,%x2"
[(set_attr "type" "<VStype_simple>")])
(define_insn "*vsx_sub<mode>3"
- [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?<VSa>")
- (minus:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,<VSa>")
- (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>,<VSa>")))]
+ [(set (match_operand:VSX_F 0 "vsx_register_operand" "=wa>")
+ (minus:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "wa")
+ (match_operand:VSX_F 2 "vsx_register_operand" "wa")))]
"VECTOR_UNIT_VSX_P (<MODE>mode)"
- "xvsub<VSs> %x0,%x1,%x2"
+ "xvsub<sd>p %x0,%x1,%x2"
[(set_attr "type" "<VStype_simple>")])
(define_insn "*vsx_mul<mode>3"
- [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?<VSa>")
- (mult:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,<VSa>")
- (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>,<VSa>")))]
+ [(set (match_operand:VSX_F 0 "vsx_register_operand" "=wa")
+ (mult:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "wa")
+ (match_operand:VSX_F 2 "vsx_register_operand" "wa")))]
"VECTOR_UNIT_VSX_P (<MODE>mode)"
- "xvmul<VSs> %x0,%x1,%x2"
+ "xvmul<sd>p %x0,%x1,%x2"
[(set_attr "type" "<VStype_simple>")])
; Emulate vector with scalar for vec_mul in V2DImode
@@ -1667,11 +1595,11 @@
[(set_attr "type" "mul")])
(define_insn "*vsx_div<mode>3"
- [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?<VSa>")
- (div:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,<VSa>")
- (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>,<VSa>")))]
+ [(set (match_operand:VSX_F 0 "vsx_register_operand" "=wa")
+ (div:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "wa")
+ (match_operand:VSX_F 2 "vsx_register_operand" "wa")))]
"VECTOR_UNIT_VSX_P (<MODE>mode)"
- "xvdiv<VSs> %x0,%x1,%x2"
+ "xvdiv<sd>p %x0,%x1,%x2"
[(set_attr "type" "<VStype_div>")])
; Emulate vector with scalar for vec_div in V2DImode
@@ -1798,74 +1726,74 @@
})
(define_insn "*vsx_tdiv<mode>3_internal"
- [(set (match_operand:CCFP 0 "cc_reg_operand" "=x,x")
- (unspec:CCFP [(match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,<VSa>")
- (match_operand:VSX_B 2 "vsx_register_operand" "<VSr>,<VSa>")]
+ [(set (match_operand:CCFP 0 "cc_reg_operand" "=x")
+ (unspec:CCFP [(match_operand:VSX_B 1 "vsx_register_operand" "wa")
+ (match_operand:VSX_B 2 "vsx_register_operand" "wa")]
UNSPEC_VSX_TDIV))]
"VECTOR_UNIT_VSX_P (<MODE>mode)"
- "x<VSv>tdiv<VSs> %0,%x1,%x2"
+ "x<VSv>tdiv<sd>p %0,%x1,%x2"
[(set_attr "type" "<VStype_simple>")])
(define_insn "vsx_fre<mode>2"
- [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?<VSa>")
- (unspec:VSX_F [(match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,<VSa>")]
+ [(set (match_operand:VSX_F 0 "vsx_register_operand" "=wa")
+ (unspec:VSX_F [(match_operand:VSX_F 1 "vsx_register_operand" "wa")]
UNSPEC_FRES))]
"VECTOR_UNIT_VSX_P (<MODE>mode)"
- "xvre<VSs> %x0,%x1"
+ "xvre<sd>p %x0,%x1"
[(set_attr "type" "<VStype_simple>")])
(define_insn "*vsx_neg<mode>2"
- [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?<VSa>")
- (neg:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,<VSa>")))]
+ [(set (match_operand:VSX_F 0 "vsx_register_operand" "=wa")
+ (neg:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "wa")))]
"VECTOR_UNIT_VSX_P (<MODE>mode)"
- "xvneg<VSs> %x0,%x1"
+ "xvneg<sd>p %x0,%x1"
[(set_attr "type" "<VStype_simple>")])
(define_insn "*vsx_abs<mode>2"
- [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?<VSa>")
- (abs:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,<VSa>")))]
+ [(set (match_operand:VSX_F 0 "vsx_register_operand" "=wa")
+ (abs:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "wa")))]
"VECTOR_UNIT_VSX_P (<MODE>mode)"
- "xvabs<VSs> %x0,%x1"
+ "xvabs<sd>p %x0,%x1"
[(set_attr "type" "<VStype_simple>")])
(define_insn "vsx_nabs<mode>2"
- [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?<VSa>")
+ [(set (match_operand:VSX_F 0 "vsx_register_operand" "=wa")
(neg:VSX_F
(abs:VSX_F
- (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,<VSa>"))))]
+ (match_operand:VSX_F 1 "vsx_register_operand" "wa"))))]
"VECTOR_UNIT_VSX_P (<MODE>mode)"
- "xvnabs<VSs> %x0,%x1"
+ "xvnabs<sd>p %x0,%x1"
[(set_attr "type" "<VStype_simple>")])
(define_insn "vsx_smax<mode>3"
- [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?<VSa>")
- (smax:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,<VSa>")
- (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>,<VSa>")))]
+ [(set (match_operand:VSX_F 0 "vsx_register_operand" "=wa")
+ (smax:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "wa")
+ (match_operand:VSX_F 2 "vsx_register_operand" "wa")))]
"VECTOR_UNIT_VSX_P (<MODE>mode)"
- "xvmax<VSs> %x0,%x1,%x2"
+ "xvmax<sd>p %x0,%x1,%x2"
[(set_attr "type" "<VStype_simple>")])
(define_insn "*vsx_smin<mode>3"
- [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?<VSa>")
- (smin:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,<VSa>")
- (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>,<VSa>")))]
+ [(set (match_operand:VSX_F 0 "vsx_register_operand" "=wa")
+ (smin:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "wa")
+ (match_operand:VSX_F 2 "vsx_register_operand" "wa")))]
"VECTOR_UNIT_VSX_P (<MODE>mode)"
- "xvmin<VSs> %x0,%x1,%x2"
+ "xvmin<sd>p %x0,%x1,%x2"
[(set_attr "type" "<VStype_simple>")])
(define_insn "*vsx_sqrt<mode>2"
- [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?<VSa>")
- (sqrt:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,<VSa>")))]
+ [(set (match_operand:VSX_F 0 "vsx_register_operand" "=wa")
+ (sqrt:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "wa")))]
"VECTOR_UNIT_VSX_P (<MODE>mode)"
- "xvsqrt<VSs> %x0,%x1"
- [(set_attr "type" "<VStype_sqrt>")])
+ "xvsqrt<sd>p %x0,%x1"
+ [(set_attr "type" "<sd>sqrt")])
(define_insn "*vsx_rsqrte<mode>2"
- [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?<VSa>")
- (unspec:VSX_F [(match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,<VSa>")]
+ [(set (match_operand:VSX_F 0 "vsx_register_operand" "=wa")
+ (unspec:VSX_F [(match_operand:VSX_F 1 "vsx_register_operand" "wa")]
UNSPEC_RSQRT))]
"VECTOR_UNIT_VSX_P (<MODE>mode)"
- "xvrsqrte<VSs> %x0,%x1"
+ "xvrsqrte<sd>p %x0,%x1"
[(set_attr "type" "<VStype_simple>")])
;; *tsqrt* returning the fg flag
@@ -1895,11 +1823,11 @@
})
(define_insn "*vsx_tsqrt<mode>2_internal"
- [(set (match_operand:CCFP 0 "cc_reg_operand" "=x,x")
- (unspec:CCFP [(match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,<VSa>")]
+ [(set (match_operand:CCFP 0 "cc_reg_operand" "=x")
+ (unspec:CCFP [(match_operand:VSX_B 1 "vsx_register_operand" "wa")]
UNSPEC_VSX_TSQRT))]
"VECTOR_UNIT_VSX_P (<MODE>mode)"
- "x<VSv>tsqrt<VSs> %0,%x1"
+ "x<VSv>tsqrt<sd>p %0,%x1"
[(set_attr "type" "<VStype_simple>")])
;; Fused vector multiply/add instructions. Support the classical Altivec
@@ -1908,120 +1836,108 @@
;; multiply.
(define_insn "*vsx_fmav4sf4"
- [(set (match_operand:V4SF 0 "vsx_register_operand" "=wf,wf,?wa,?wa,v")
+ [(set (match_operand:V4SF 0 "vsx_register_operand" "=wa,wa,v")
(fma:V4SF
- (match_operand:V4SF 1 "vsx_register_operand" "%wf,wf,wa,wa,v")
- (match_operand:V4SF 2 "vsx_register_operand" "wf,0,wa,0,v")
- (match_operand:V4SF 3 "vsx_register_operand" "0,wf,0,wa,v")))]
+ (match_operand:V4SF 1 "vsx_register_operand" "%wa,wa,v")
+ (match_operand:V4SF 2 "vsx_register_operand" "wa,0,v")
+ (match_operand:V4SF 3 "vsx_register_operand" "0,wa,v")))]
"VECTOR_UNIT_VSX_P (V4SFmode)"
"@
xvmaddasp %x0,%x1,%x2
xvmaddmsp %x0,%x1,%x3
- xvmaddasp %x0,%x1,%x2
- xvmaddmsp %x0,%x1,%x3
vmaddfp %0,%1,%2,%3"
[(set_attr "type" "vecfloat")])
(define_insn "*vsx_fmav2df4"
- [(set (match_operand:V2DF 0 "vsx_register_operand" "=wd,wd,?wa,?wa")
+ [(set (match_operand:V2DF 0 "vsx_register_operand" "=wa,wa")
(fma:V2DF
- (match_operand:V2DF 1 "vsx_register_operand" "%wd,wd,wa,wa")
- (match_operand:V2DF 2 "vsx_register_operand" "wd,0,wa,0")
- (match_operand:V2DF 3 "vsx_register_operand" "0,wd,0,wa")))]
+ (match_operand:V2DF 1 "vsx_register_operand" "%wa,wa")
+ (match_operand:V2DF 2 "vsx_register_operand" "wa,0")
+ (match_operand:V2DF 3 "vsx_register_operand" "0,wa")))]
"VECTOR_UNIT_VSX_P (V2DFmode)"
"@
xvmaddadp %x0,%x1,%x2
- xvmaddmdp %x0,%x1,%x3
- xvmaddadp %x0,%x1,%x2
xvmaddmdp %x0,%x1,%x3"
[(set_attr "type" "vecdouble")])
(define_insn "*vsx_fms<mode>4"
- [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,<VSr>,?<VSa>,?<VSa>")
+ [(set (match_operand:VSX_F 0 "vsx_register_operand" "=wa,wa")
(fma:VSX_F
- (match_operand:VSX_F 1 "vsx_register_operand" "%<VSr>,<VSr>,<VSa>,<VSa>")
- (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>,0,<VSa>,0")
+ (match_operand:VSX_F 1 "vsx_register_operand" "%wa,wa")
+ (match_operand:VSX_F 2 "vsx_register_operand" "wa,0")
(neg:VSX_F
- (match_operand:VSX_F 3 "vsx_register_operand" "0,<VSr>,0,<VSa>"))))]
+ (match_operand:VSX_F 3 "vsx_register_operand" "0,wa"))))]
"VECTOR_UNIT_VSX_P (<MODE>mode)"
"@
- xvmsuba<VSs> %x0,%x1,%x2
- xvmsubm<VSs> %x0,%x1,%x3
- xvmsuba<VSs> %x0,%x1,%x2
- xvmsubm<VSs> %x0,%x1,%x3"
+ xvmsuba<sd>p %x0,%x1,%x2
+ xvmsubm<sd>p %x0,%x1,%x3"
[(set_attr "type" "<VStype_mul>")])
(define_insn "*vsx_nfma<mode>4"
- [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,<VSr>,?<VSa>,?<VSa>")
+ [(set (match_operand:VSX_F 0 "vsx_register_operand" "=wa,wa")
(neg:VSX_F
(fma:VSX_F
- (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,<VSr>,<VSa>,<VSa>")
- (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>,0,<VSa>,0")
- (match_operand:VSX_F 3 "vsx_register_operand" "0,<VSr>,0,<VSa>"))))]
+ (match_operand:VSX_F 1 "vsx_register_operand" "wa,wa")
+ (match_operand:VSX_F 2 "vsx_register_operand" "wa,0")
+ (match_operand:VSX_F 3 "vsx_register_operand" "0,wa"))))]
"VECTOR_UNIT_VSX_P (<MODE>mode)"
"@
- xvnmadda<VSs> %x0,%x1,%x2
- xvnmaddm<VSs> %x0,%x1,%x3
- xvnmadda<VSs> %x0,%x1,%x2
- xvnmaddm<VSs> %x0,%x1,%x3"
+ xvnmadda<sd>p %x0,%x1,%x2
+ xvnmaddm<sd>p %x0,%x1,%x3"
[(set_attr "type" "<VStype_mul>")])
(define_insn "*vsx_nfmsv4sf4"
- [(set (match_operand:V4SF 0 "vsx_register_operand" "=wf,wf,?wa,?wa,v")
+ [(set (match_operand:V4SF 0 "vsx_register_operand" "=wa,wa,v")
(neg:V4SF
(fma:V4SF
- (match_operand:V4SF 1 "vsx_register_operand" "%wf,wf,wa,wa,v")
- (match_operand:V4SF 2 "vsx_register_operand" "wf,0,wa,0,v")
+ (match_operand:V4SF 1 "vsx_register_operand" "%wa,wa,v")
+ (match_operand:V4SF 2 "vsx_register_operand" "wa,0,v")
(neg:V4SF
- (match_operand:V4SF 3 "vsx_register_operand" "0,wf,0,wa,v")))))]
+ (match_operand:V4SF 3 "vsx_register_operand" "0,wa,v")))))]
"VECTOR_UNIT_VSX_P (V4SFmode)"
"@
xvnmsubasp %x0,%x1,%x2
xvnmsubmsp %x0,%x1,%x3
- xvnmsubasp %x0,%x1,%x2
- xvnmsubmsp %x0,%x1,%x3
vnmsubfp %0,%1,%2,%3"
[(set_attr "type" "vecfloat")])
(define_insn "*vsx_nfmsv2df4"
- [(set (match_operand:V2DF 0 "vsx_register_operand" "=wd,wd,?wa,?wa")
+ [(set (match_operand:V2DF 0 "vsx_register_operand" "=wa,wa")
(neg:V2DF
(fma:V2DF
- (match_operand:V2DF 1 "vsx_register_operand" "%wd,wd,wa,wa")
- (match_operand:V2DF 2 "vsx_register_operand" "wd,0,wa,0")
+ (match_operand:V2DF 1 "vsx_register_operand" "%wa,wa")
+ (match_operand:V2DF 2 "vsx_register_operand" "wa,0")
(neg:V2DF
- (match_operand:V2DF 3 "vsx_register_operand" "0,wd,0,wa")))))]
+ (match_operand:V2DF 3 "vsx_register_operand" "0,wa")))))]
"VECTOR_UNIT_VSX_P (V2DFmode)"
"@
xvnmsubadp %x0,%x1,%x2
- xvnmsubmdp %x0,%x1,%x3
- xvnmsubadp %x0,%x1,%x2
xvnmsubmdp %x0,%x1,%x3"
[(set_attr "type" "vecdouble")])
;; Vector conditional expressions (no scalar version for these instructions)
(define_insn "vsx_eq<mode>"
- [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?<VSa>")
- (eq:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,<VSa>")
- (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>,<VSa>")))]
+ [(set (match_operand:VSX_F 0 "vsx_register_operand" "=wa")
+ (eq:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "wa")
+ (match_operand:VSX_F 2 "vsx_register_operand" "wa")))]
"VECTOR_UNIT_VSX_P (<MODE>mode)"
- "xvcmpeq<VSs> %x0,%x1,%x2"
+ "xvcmpeq<sd>p %x0,%x1,%x2"
[(set_attr "type" "<VStype_simple>")])
(define_insn "vsx_gt<mode>"
- [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?<VSa>")
- (gt:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,<VSa>")
- (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>,<VSa>")))]
+ [(set (match_operand:VSX_F 0 "vsx_register_operand" "=wa")
+ (gt:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "wa")
+ (match_operand:VSX_F 2 "vsx_register_operand" "wa")))]
"VECTOR_UNIT_VSX_P (<MODE>mode)"
- "xvcmpgt<VSs> %x0,%x1,%x2"
+ "xvcmpgt<sd>p %x0,%x1,%x2"
[(set_attr "type" "<VStype_simple>")])
(define_insn "*vsx_ge<mode>"
- [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?<VSa>")
- (ge:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,<VSa>")
- (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>,<VSa>")))]
+ [(set (match_operand:VSX_F 0 "vsx_register_operand" "=wa")
+ (ge:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "wa")
+ (match_operand:VSX_F 2 "vsx_register_operand" "wa")))]
"VECTOR_UNIT_VSX_P (<MODE>mode)"
- "xvcmpge<VSs> %x0,%x1,%x2"
+ "xvcmpge<sd>p %x0,%x1,%x2"
[(set_attr "type" "<VStype_simple>")])
;; Compare vectors producing a vector result and a predicate, setting CR6 to
@@ -2029,74 +1945,76 @@
(define_insn "*vsx_eq_<mode>_p"
[(set (reg:CC CR6_REGNO)
(unspec:CC
- [(eq:CC (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,?<VSa>")
- (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>,?<VSa>"))]
+ [(eq:CC (match_operand:VSX_F 1 "vsx_register_operand" "wa")
+ (match_operand:VSX_F 2 "vsx_register_operand" "wa"))]
UNSPEC_PREDICATE))
- (set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?<VSa>")
+ (set (match_operand:VSX_F 0 "vsx_register_operand" "=wa")
(eq:VSX_F (match_dup 1)
(match_dup 2)))]
"VECTOR_UNIT_VSX_P (<MODE>mode)"
- "xvcmpeq<VSs>. %x0,%x1,%x2"
+ "xvcmpeq<sd>p. %x0,%x1,%x2"
[(set_attr "type" "<VStype_simple>")])
(define_insn "*vsx_gt_<mode>_p"
[(set (reg:CC CR6_REGNO)
(unspec:CC
- [(gt:CC (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,?<VSa>")
- (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>,?<VSa>"))]
+ [(gt:CC (match_operand:VSX_F 1 "vsx_register_operand" "wa")
+ (match_operand:VSX_F 2 "vsx_register_operand" "wa"))]
UNSPEC_PREDICATE))
- (set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?<VSa>")
+ (set (match_operand:VSX_F 0 "vsx_register_operand" "=wa")
(gt:VSX_F (match_dup 1)
(match_dup 2)))]
"VECTOR_UNIT_VSX_P (<MODE>mode)"
- "xvcmpgt<VSs>. %x0,%x1,%x2"
+ "xvcmpgt<sd>p. %x0,%x1,%x2"
[(set_attr "type" "<VStype_simple>")])
(define_insn "*vsx_ge_<mode>_p"
[(set (reg:CC CR6_REGNO)
(unspec:CC
- [(ge:CC (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,?<VSa>")
- (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>,?<VSa>"))]
+ [(ge:CC (match_operand:VSX_F 1 "vsx_register_operand" "wa")
+ (match_operand:VSX_F 2 "vsx_register_operand" "wa"))]
UNSPEC_PREDICATE))
- (set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?<VSa>")
+ (set (match_operand:VSX_F 0 "vsx_register_operand" "=wa")
(ge:VSX_F (match_dup 1)
(match_dup 2)))]
"VECTOR_UNIT_VSX_P (<MODE>mode)"
- "xvcmpge<VSs>. %x0,%x1,%x2"
+ "xvcmpge<sd>p. %x0,%x1,%x2"
[(set_attr "type" "<VStype_simple>")])
;; Vector select
(define_insn "*vsx_xxsel<mode>"
- [(set (match_operand:VSX_L 0 "vsx_register_operand" "=<VSr>,?<VSa>")
+ [(set (match_operand:VSX_L 0 "vsx_register_operand" "=<VSr>,?wa")
(if_then_else:VSX_L
- (ne:CC (match_operand:VSX_L 1 "vsx_register_operand" "<VSr>,<VSa>")
+ (ne:CC (match_operand:VSX_L 1 "vsx_register_operand" "<VSr>,wa")
(match_operand:VSX_L 4 "zero_constant" ""))
- (match_operand:VSX_L 2 "vsx_register_operand" "<VSr>,<VSa>")
- (match_operand:VSX_L 3 "vsx_register_operand" "<VSr>,<VSa>")))]
+ (match_operand:VSX_L 2 "vsx_register_operand" "<VSr>,wa")
+ (match_operand:VSX_L 3 "vsx_register_operand" "<VSr>,wa")))]
"VECTOR_MEM_VSX_P (<MODE>mode)"
"xxsel %x0,%x3,%x2,%x1"
- [(set_attr "type" "vecmove")])
+ [(set_attr "type" "vecmove")
+ (set_attr "isa" "<VSisa>")])
(define_insn "*vsx_xxsel<mode>_uns"
- [(set (match_operand:VSX_L 0 "vsx_register_operand" "=<VSr>,?<VSa>")
+ [(set (match_operand:VSX_L 0 "vsx_register_operand" "=<VSr>,?wa")
(if_then_else:VSX_L
- (ne:CCUNS (match_operand:VSX_L 1 "vsx_register_operand" "<VSr>,<VSa>")
+ (ne:CCUNS (match_operand:VSX_L 1 "vsx_register_operand" "<VSr>,wa")
(match_operand:VSX_L 4 "zero_constant" ""))
- (match_operand:VSX_L 2 "vsx_register_operand" "<VSr>,<VSa>")
- (match_operand:VSX_L 3 "vsx_register_operand" "<VSr>,<VSa>")))]
+ (match_operand:VSX_L 2 "vsx_register_operand" "<VSr>,wa")
+ (match_operand:VSX_L 3 "vsx_register_operand" "<VSr>,wa")))]
"VECTOR_MEM_VSX_P (<MODE>mode)"
"xxsel %x0,%x3,%x2,%x1"
- [(set_attr "type" "vecmove")])
+ [(set_attr "type" "vecmove")
+ (set_attr "isa" "<VSisa>")])
;; Copy sign
(define_insn "vsx_copysign<mode>3"
- [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?<VSa>")
+ [(set (match_operand:VSX_F 0 "vsx_register_operand" "=wa")
(unspec:VSX_F
- [(match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,<VSa>")
- (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>,<VSa>")]
+ [(match_operand:VSX_F 1 "vsx_register_operand" "wa")
+ (match_operand:VSX_F 2 "vsx_register_operand" "wa")]
UNSPEC_COPYSIGN))]
"VECTOR_UNIT_VSX_P (<MODE>mode)"
- "xvcpsgn<VSs> %x0,%x2,%x1"
+ "xvcpsgn<sd>p %x0,%x2,%x1"
[(set_attr "type" "<VStype_simple>")])
;; For the conversions, limit the register class for the integer value to be
@@ -2106,79 +2024,79 @@
;; Don't use vsx_register_operand here, use gpc_reg_operand to match rs6000.md
;; in allowing virtual registers.
(define_insn "vsx_float<VSi><mode>2"
- [(set (match_operand:VSX_F 0 "gpc_reg_operand" "=<VSr>,?<VSa>")
- (float:VSX_F (match_operand:<VSI> 1 "gpc_reg_operand" "<VSr2>,<VSr3>")))]
+ [(set (match_operand:VSX_F 0 "gpc_reg_operand" "=wa")
+ (float:VSX_F (match_operand:<VSI> 1 "gpc_reg_operand" "wa")))]
"VECTOR_UNIT_VSX_P (<MODE>mode)"
- "xvcvsx<VSc><VSs> %x0,%x1"
+ "xvcvsx<VSc><sd>p %x0,%x1"
[(set_attr "type" "<VStype_simple>")])
(define_insn "vsx_floatuns<VSi><mode>2"
- [(set (match_operand:VSX_F 0 "gpc_reg_operand" "=<VSr>,?<VSa>")
- (unsigned_float:VSX_F (match_operand:<VSI> 1 "gpc_reg_operand" "<VSr2>,<VSr3>")))]
+ [(set (match_operand:VSX_F 0 "gpc_reg_operand" "=wa")
+ (unsigned_float:VSX_F (match_operand:<VSI> 1 "gpc_reg_operand" "wa")))]
"VECTOR_UNIT_VSX_P (<MODE>mode)"
- "xvcvux<VSc><VSs> %x0,%x1"
+ "xvcvux<VSc><sd>p %x0,%x1"
[(set_attr "type" "<VStype_simple>")])
(define_insn "vsx_fix_trunc<mode><VSi>2"
- [(set (match_operand:<VSI> 0 "gpc_reg_operand" "=<VSr2>,?<VSr3>")
- (fix:<VSI> (match_operand:VSX_F 1 "gpc_reg_operand" "<VSr>,<VSa>")))]
+ [(set (match_operand:<VSI> 0 "gpc_reg_operand" "=wa")
+ (fix:<VSI> (match_operand:VSX_F 1 "gpc_reg_operand" "wa")))]
"VECTOR_UNIT_VSX_P (<MODE>mode)"
- "x<VSv>cv<VSs>sx<VSc>s %x0,%x1"
+ "x<VSv>cv<sd>psx<VSc>s %x0,%x1"
[(set_attr "type" "<VStype_simple>")])
(define_insn "vsx_fixuns_trunc<mode><VSi>2"
- [(set (match_operand:<VSI> 0 "gpc_reg_operand" "=<VSr2>,?<VSr3>")
- (unsigned_fix:<VSI> (match_operand:VSX_F 1 "gpc_reg_operand" "<VSr>,<VSa>")))]
+ [(set (match_operand:<VSI> 0 "gpc_reg_operand" "=wa")
+ (unsigned_fix:<VSI> (match_operand:VSX_F 1 "gpc_reg_operand" "wa")))]
"VECTOR_UNIT_VSX_P (<MODE>mode)"
- "x<VSv>cv<VSs>ux<VSc>s %x0,%x1"
+ "x<VSv>cv<sd>pux<VSc>s %x0,%x1"
[(set_attr "type" "<VStype_simple>")])
;; Math rounding functions
-(define_insn "vsx_x<VSv>r<VSs>i"
- [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?<VSa>")
- (unspec:VSX_B [(match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,<VSa>")]
+(define_insn "vsx_x<VSv>r<sd>pi"
+ [(set (match_operand:VSX_B 0 "vsx_register_operand" "=wa")
+ (unspec:VSX_B [(match_operand:VSX_B 1 "vsx_register_operand" "wa")]
UNSPEC_VSX_ROUND_I))]
"VECTOR_UNIT_VSX_P (<MODE>mode)"
- "x<VSv>r<VSs>i %x0,%x1"
+ "x<VSv>r<sd>pi %x0,%x1"
[(set_attr "type" "<VStype_simple>")])
-(define_insn "vsx_x<VSv>r<VSs>ic"
- [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?<VSa>")
- (unspec:VSX_B [(match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,<VSa>")]
+(define_insn "vsx_x<VSv>r<sd>pic"
+ [(set (match_operand:VSX_B 0 "vsx_register_operand" "=wa")
+ (unspec:VSX_B [(match_operand:VSX_B 1 "vsx_register_operand" "wa")]
UNSPEC_VSX_ROUND_IC))]
"VECTOR_UNIT_VSX_P (<MODE>mode)"
- "x<VSv>r<VSs>ic %x0,%x1"
+ "x<VSv>r<sd>pic %x0,%x1"
[(set_attr "type" "<VStype_simple>")])
(define_insn "vsx_btrunc<mode>2"
- [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?<VSa>")
- (fix:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,<VSa>")))]
+ [(set (match_operand:VSX_F 0 "vsx_register_operand" "=wa")
+ (fix:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "wa")))]
"VECTOR_UNIT_VSX_P (<MODE>mode)"
- "xvr<VSs>iz %x0,%x1"
+ "xvr<sd>piz %x0,%x1"
[(set_attr "type" "<VStype_simple>")])
(define_insn "*vsx_b2trunc<mode>2"
- [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?<VSa>")
- (unspec:VSX_B [(match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,<VSa>")]
+ [(set (match_operand:VSX_B 0 "vsx_register_operand" "=wa")
+ (unspec:VSX_B [(match_operand:VSX_B 1 "vsx_register_operand" "wa")]
UNSPEC_FRIZ))]
"VECTOR_UNIT_VSX_P (<MODE>mode)"
- "x<VSv>r<VSs>iz %x0,%x1"
+ "x<VSv>r<sd>piz %x0,%x1"
[(set_attr "type" "<VStype_simple>")])
(define_insn "vsx_floor<mode>2"
- [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?<VSa>")
- (unspec:VSX_F [(match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,<VSa>")]
+ [(set (match_operand:VSX_F 0 "vsx_register_operand" "=wa")
+ (unspec:VSX_F [(match_operand:VSX_F 1 "vsx_register_operand" "wa")]
UNSPEC_FRIM))]
"VECTOR_UNIT_VSX_P (<MODE>mode)"
- "xvr<VSs>im %x0,%x1"
+ "xvr<sd>pim %x0,%x1"
[(set_attr "type" "<VStype_simple>")])
(define_insn "vsx_ceil<mode>2"
- [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?<VSa>")
- (unspec:VSX_F [(match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,<VSa>")]
+ [(set (match_operand:VSX_F 0 "vsx_register_operand" "=wa")
+ (unspec:VSX_F [(match_operand:VSX_F 1 "vsx_register_operand" "wa")]
UNSPEC_FRIP))]
"VECTOR_UNIT_VSX_P (<MODE>mode)"
- "xvr<VSs>ip %x0,%x1"
+ "xvr<sd>pip %x0,%x1"
[(set_attr "type" "<VStype_simple>")])
@@ -2188,17 +2106,33 @@
;; Don't use xscvspdp and xscvdpsp for scalar conversions, since the normal
;; scalar single precision instructions internally use the double format.
;; Prefer the altivec registers, since we likely will need to do a vperm
-(define_insn "vsx_<VS_spdp_insn>"
- [(set (match_operand:<VS_spdp_res> 0 "vsx_register_operand" "=<VSr4>,?<VSa>")
- (unspec:<VS_spdp_res> [(match_operand:VSX_SPDP 1 "vsx_register_operand" "<VSr5>,<VSa>")]
+(define_insn "vsx_xscvdpsp"
+ [(set (match_operand:V4SF 0 "vsx_register_operand" "=f,?wa")
+ (unspec:V4SF [(match_operand:DF 1 "vsx_register_operand" "f,wa")]
UNSPEC_VSX_CVSPDP))]
- "VECTOR_UNIT_VSX_P (<MODE>mode)"
- "<VS_spdp_insn> %x0,%x1"
- [(set_attr "type" "<VS_spdp_type>")])
+ "VECTOR_UNIT_VSX_P (DFmode)"
+ "xscvdpsp %x0,%x1"
+ [(set_attr "type" "fp")])
+
+(define_insn "vsx_xvcvspdp"
+ [(set (match_operand:V2DF 0 "vsx_register_operand" "=v,?wa")
+ (unspec:V2DF [(match_operand:V4SF 1 "vsx_register_operand" "wa,wa")]
+ UNSPEC_VSX_CVSPDP))]
+ "VECTOR_UNIT_VSX_P (V4SFmode)"
+ "xvcvspdp %x0,%x1"
+ [(set_attr "type" "vecdouble")])
+
+(define_insn "vsx_xvcvdpsp"
+ [(set (match_operand:V4SF 0 "vsx_register_operand" "=wa,?wa")
+ (unspec:V4SF [(match_operand:V2DF 1 "vsx_register_operand" "v,wa")]
+ UNSPEC_VSX_CVSPDP))]
+ "VECTOR_UNIT_VSX_P (V2DFmode)"
+ "xvcvdpsp %x0,%x1"
+ [(set_attr "type" "vecdouble")])
;; xscvspdp, represent the scalar SF type as V4SF
(define_insn "vsx_xscvspdp"
- [(set (match_operand:DF 0 "vsx_register_operand" "=ws")
+ [(set (match_operand:DF 0 "vsx_register_operand" "=wa")
(unspec:DF [(match_operand:V4SF 1 "vsx_register_operand" "wa")]
UNSPEC_VSX_CVSPDP))]
"VECTOR_UNIT_VSX_P (V4SFmode)"
@@ -2207,7 +2141,7 @@
;; Same as vsx_xscvspdp, but use SF as the type
(define_insn "vsx_xscvspdp_scalar2"
- [(set (match_operand:SF 0 "vsx_register_operand" "=ww")
+ [(set (match_operand:SF 0 "vsx_register_operand" "=wa")
(unspec:SF [(match_operand:V4SF 1 "vsx_register_operand" "wa")]
UNSPEC_VSX_CVSPDP))]
"VECTOR_UNIT_VSX_P (V4SFmode)"
@@ -2227,7 +2161,7 @@
;; format of scalars is actually DF.
(define_insn "vsx_xscvdpsp_scalar"
[(set (match_operand:V4SF 0 "vsx_register_operand" "=wa")
- (unspec:V4SF [(match_operand:SF 1 "vsx_register_operand" "ww")]
+ (unspec:V4SF [(match_operand:SF 1 "vsx_register_operand" "wa")]
UNSPEC_VSX_CVSPDP))]
"VECTOR_UNIT_VSX_P (V4SFmode)"
"xscvdpsp %x0,%x1"
@@ -2235,15 +2169,15 @@
;; ISA 2.07 xscvdpspn/xscvspdpn that does not raise an error on signalling NaNs
(define_insn "vsx_xscvdpspn"
- [(set (match_operand:V4SF 0 "vsx_register_operand" "=ww")
- (unspec:V4SF [(match_operand:DF 1 "vsx_register_operand" "ws")]
+ [(set (match_operand:V4SF 0 "vsx_register_operand" "=wa")
+ (unspec:V4SF [(match_operand:DF 1 "vsx_register_operand" "wa")]
UNSPEC_VSX_CVDPSPN))]
"TARGET_XSCVDPSPN"
"xscvdpspn %x0,%x1"
[(set_attr "type" "fp")])
(define_insn "vsx_xscvspdpn"
- [(set (match_operand:DF 0 "vsx_register_operand" "=ws")
+ [(set (match_operand:DF 0 "vsx_register_operand" "=wa")
(unspec:DF [(match_operand:V4SF 1 "vsx_register_operand" "wa")]
UNSPEC_VSX_CVSPDPN))]
"TARGET_XSCVSPDPN"
@@ -2252,7 +2186,7 @@
(define_insn "vsx_xscvdpspn_scalar"
[(set (match_operand:V4SF 0 "vsx_register_operand" "=wa")
- (unspec:V4SF [(match_operand:SF 1 "vsx_register_operand" "ww")]
+ (unspec:V4SF [(match_operand:SF 1 "vsx_register_operand" "wa")]
UNSPEC_VSX_CVDPSPN))]
"TARGET_XSCVDPSPN"
"xscvdpspn %x0,%x1"
@@ -2403,7 +2337,7 @@
(define_insn "vsx_xvcvdpsxws"
[(set (match_operand:V4SI 0 "vsx_register_operand" "=v,?wa")
- (unspec:V4SI [(match_operand:V2DF 1 "vsx_register_operand" "wd,wa")]
+ (unspec:V4SI [(match_operand:V2DF 1 "vsx_register_operand" "wa,wa")]
UNSPEC_VSX_CVDPSXWS))]
"VECTOR_UNIT_VSX_P (V2DFmode)"
"xvcvdpsxws %x0,%x1"
@@ -2411,31 +2345,31 @@
(define_insn "vsx_xvcvdpuxws"
[(set (match_operand:V4SI 0 "vsx_register_operand" "=v,?wa")
- (unspec:V4SI [(match_operand:V2DF 1 "vsx_register_operand" "wd,wa")]
+ (unspec:V4SI [(match_operand:V2DF 1 "vsx_register_operand" "wa,wa")]
UNSPEC_VSX_CVDPUXWS))]
"VECTOR_UNIT_VSX_P (V2DFmode)"
"xvcvdpuxws %x0,%x1"
[(set_attr "type" "vecdouble")])
(define_insn "vsx_xvcvsxdsp"
- [(set (match_operand:V4SF 0 "vsx_register_operand" "=wd,?wa")
- (unspec:V4SF [(match_operand:V2DI 1 "vsx_register_operand" "wf,wa")]
+ [(set (match_operand:V4SF 0 "vsx_register_operand" "=wa")
+ (unspec:V4SF [(match_operand:V2DI 1 "vsx_register_operand" "wa")]
UNSPEC_VSX_CVSXDSP))]
"VECTOR_UNIT_VSX_P (V2DFmode)"
"xvcvsxdsp %x0,%x1"
[(set_attr "type" "vecfloat")])
(define_insn "vsx_xvcvuxdsp"
- [(set (match_operand:V4SF 0 "vsx_register_operand" "=wd,?wa")
- (unspec:V4SF [(match_operand:V2DI 1 "vsx_register_operand" "wf,wa")]
+ [(set (match_operand:V4SF 0 "vsx_register_operand" "=wa")
+ (unspec:V4SF [(match_operand:V2DI 1 "vsx_register_operand" "wa")]
UNSPEC_VSX_CVUXDSP))]
"VECTOR_UNIT_VSX_P (V2DFmode)"
"xvcvuxdsp %x0,%x1"
[(set_attr "type" "vecdouble")])
(define_insn "vsx_xvcdpsp"
- [(set (match_operand:V4SF 0 "vsx_register_operand" "=wd,?wa")
- (unspec:V4SF [(match_operand:V2DF 1 "vsx_register_operand" "wf,wa")]
+ [(set (match_operand:V4SF 0 "vsx_register_operand" "=wa")
+ (unspec:V4SF [(match_operand:V2DF 1 "vsx_register_operand" "wa")]
UNSPEC_VSX_XVCDPSP))]
"VECTOR_UNIT_VSX_P (V2DFmode)"
"xvcvdpsp %x0,%x1"
@@ -2444,15 +2378,15 @@
;; Convert from 32-bit to 64-bit types
;; Provide both vector and scalar targets
(define_insn "vsx_xvcvsxwdp"
- [(set (match_operand:V2DF 0 "vsx_register_operand" "=wd,?wa")
- (unspec:V2DF [(match_operand:V4SI 1 "vsx_register_operand" "wf,wa")]
+ [(set (match_operand:V2DF 0 "vsx_register_operand" "=wa")
+ (unspec:V2DF [(match_operand:V4SI 1 "vsx_register_operand" "wa")]
UNSPEC_VSX_CVSXWDP))]
"VECTOR_UNIT_VSX_P (V2DFmode)"
"xvcvsxwdp %x0,%x1"
[(set_attr "type" "vecdouble")])
(define_insn "vsx_xvcvsxwdp_df"
- [(set (match_operand:DF 0 "vsx_register_operand" "=ws")
+ [(set (match_operand:DF 0 "vsx_register_operand" "=wa")
(unspec:DF [(match_operand:V4SI 1 "vsx_register_operand" "wa")]
UNSPEC_VSX_CVSXWDP))]
"TARGET_VSX"
@@ -2460,15 +2394,15 @@
[(set_attr "type" "vecdouble")])
(define_insn "vsx_xvcvuxwdp"
- [(set (match_operand:V2DF 0 "vsx_register_operand" "=wd,?wa")
- (unspec:V2DF [(match_operand:V4SI 1 "vsx_register_operand" "wf,wa")]
+ [(set (match_operand:V2DF 0 "vsx_register_operand" "=wa")
+ (unspec:V2DF [(match_operand:V4SI 1 "vsx_register_operand" "wa")]
UNSPEC_VSX_CVUXWDP))]
"VECTOR_UNIT_VSX_P (V2DFmode)"
"xvcvuxwdp %x0,%x1"
[(set_attr "type" "vecdouble")])
(define_insn "vsx_xvcvuxwdp_df"
- [(set (match_operand:DF 0 "vsx_register_operand" "=ws")
+ [(set (match_operand:DF 0 "vsx_register_operand" "=wa")
(unspec:DF [(match_operand:V4SI 1 "vsx_register_operand" "wa")]
UNSPEC_VSX_CVUXWDP))]
"TARGET_VSX"
@@ -2477,7 +2411,7 @@
(define_insn "vsx_xvcvspsxds"
[(set (match_operand:V2DI 0 "vsx_register_operand" "=v,?wa")
- (unspec:V2DI [(match_operand:V4SF 1 "vsx_register_operand" "wd,wa")]
+ (unspec:V2DI [(match_operand:V4SF 1 "vsx_register_operand" "wa,wa")]
UNSPEC_VSX_CVSPSXDS))]
"VECTOR_UNIT_VSX_P (V2DFmode)"
"xvcvspsxds %x0,%x1"
@@ -2485,7 +2419,7 @@
(define_insn "vsx_xvcvspuxds"
[(set (match_operand:V2DI 0 "vsx_register_operand" "=v,?wa")
- (unspec:V2DI [(match_operand:V4SF 1 "vsx_register_operand" "wd,wa")]
+ (unspec:V2DI [(match_operand:V4SF 1 "vsx_register_operand" "wa,wa")]
UNSPEC_VSX_CVSPUXDS))]
"VECTOR_UNIT_VSX_P (V2DFmode)"
"xvcvspuxds %x0,%x1"
@@ -2830,10 +2764,10 @@
;; since the xvrdpiz instruction does not truncate the value if the floating
;; point value is < LONG_MIN or > LONG_MAX.
(define_insn "*vsx_float_fix_v2df2"
- [(set (match_operand:V2DF 0 "vsx_register_operand" "=wd,?wa")
+ [(set (match_operand:V2DF 0 "vsx_register_operand" "=wa,?wa")
(float:V2DF
(fix:V2DI
- (match_operand:V2DF 1 "vsx_register_operand" "wd,?wa"))))]
+ (match_operand:V2DF 1 "vsx_register_operand" "wa,?wa"))))]
"TARGET_HARD_FLOAT
&& VECTOR_UNIT_VSX_P (V2DFmode) && flag_unsafe_math_optimizations
&& !flag_trapping_math && TARGET_FRIZ"
@@ -2946,8 +2880,8 @@
(define_insn "vsx_concat_v2sf"
[(set (match_operand:V2DF 0 "vsx_register_operand" "=wa")
(unspec:V2DF
- [(match_operand:SF 1 "vsx_register_operand" "ww")
- (match_operand:SF 2 "vsx_register_operand" "ww")]
+ [(match_operand:SF 1 "vsx_register_operand" "wa")
+ (match_operand:SF 2 "vsx_register_operand" "wa")]
UNSPEC_VSX_CONCAT))]
"VECTOR_MEM_VSX_P (V2DFmode)"
{
@@ -2999,18 +2933,18 @@
;; xxpermdi for little endian loads and stores. We need several of
;; these since the form of the PARALLEL differs by mode.
(define_insn "*vsx_xxpermdi2_le_<mode>"
- [(set (match_operand:VSX_D 0 "vsx_register_operand" "=<VSa>")
+ [(set (match_operand:VSX_D 0 "vsx_register_operand" "=wa")
(vec_select:VSX_D
- (match_operand:VSX_D 1 "vsx_register_operand" "<VSa>")
+ (match_operand:VSX_D 1 "vsx_register_operand" "wa")
(parallel [(const_int 1) (const_int 0)])))]
"!BYTES_BIG_ENDIAN && VECTOR_MEM_VSX_P (<MODE>mode)"
"xxpermdi %x0,%x1,%x1,2"
[(set_attr "type" "vecperm")])
(define_insn "*vsx_xxpermdi4_le_<mode>"
- [(set (match_operand:VSX_W 0 "vsx_register_operand" "=<VSa>")
+ [(set (match_operand:VSX_W 0 "vsx_register_operand" "=wa")
(vec_select:VSX_W
- (match_operand:VSX_W 1 "vsx_register_operand" "<VSa>")
+ (match_operand:VSX_W 1 "vsx_register_operand" "wa")
(parallel [(const_int 2) (const_int 3)
(const_int 0) (const_int 1)])))]
"!BYTES_BIG_ENDIAN && VECTOR_MEM_VSX_P (<MODE>mode)"
@@ -3048,7 +2982,7 @@
;; lxvd2x for little endian loads. We need several of
;; these since the form of the PARALLEL differs by mode.
(define_insn "*vsx_lxvd2x2_le_<mode>"
- [(set (match_operand:VSX_D 0 "vsx_register_operand" "=<VSa>")
+ [(set (match_operand:VSX_D 0 "vsx_register_operand" "=wa")
(vec_select:VSX_D
(match_operand:VSX_D 1 "memory_operand" "Z")
(parallel [(const_int 1) (const_int 0)])))]
@@ -3057,7 +2991,7 @@
[(set_attr "type" "vecload")])
(define_insn "*vsx_lxvd2x4_le_<mode>"
- [(set (match_operand:VSX_W 0 "vsx_register_operand" "=<VSa>")
+ [(set (match_operand:VSX_W 0 "vsx_register_operand" "=wa")
(vec_select:VSX_W
(match_operand:VSX_W 1 "memory_operand" "Z")
(parallel [(const_int 2) (const_int 3)
@@ -3099,7 +3033,7 @@
(define_insn "*vsx_stxvd2x2_le_<mode>"
[(set (match_operand:VSX_D 0 "memory_operand" "=Z")
(vec_select:VSX_D
- (match_operand:VSX_D 1 "vsx_register_operand" "<VSa>")
+ (match_operand:VSX_D 1 "vsx_register_operand" "wa")
(parallel [(const_int 1) (const_int 0)])))]
"!BYTES_BIG_ENDIAN && VECTOR_MEM_VSX_P (<MODE>mode) && !TARGET_P9_VECTOR"
"stxvd2x %x1,%y0"
@@ -3108,7 +3042,7 @@
(define_insn "*vsx_stxvd2x4_le_<mode>"
[(set (match_operand:VSX_W 0 "memory_operand" "=Z")
(vec_select:VSX_W
- (match_operand:VSX_W 1 "vsx_register_operand" "<VSa>")
+ (match_operand:VSX_W 1 "vsx_register_operand" "wa")
(parallel [(const_int 2) (const_int 3)
(const_int 0) (const_int 1)])))]
"!BYTES_BIG_ENDIAN && VECTOR_MEM_VSX_P (<MODE>mode) && !TARGET_P9_VECTOR"
@@ -3196,13 +3130,11 @@
;; register was picked. Limit the scalar value to FPRs for now.
(define_insn "vsx_extract_<mode>"
- [(set (match_operand:<VS_scalar> 0 "gpc_reg_operand" "=d, d, wr, wr")
-
+ [(set (match_operand:<VS_scalar> 0 "gpc_reg_operand" "=d, d, wr, wr")
(vec_select:<VS_scalar>
- (match_operand:VSX_D 1 "gpc_reg_operand" "<VSa>, <VSa>, wm, wo")
-
+ (match_operand:VSX_D 1 "gpc_reg_operand" "wa, wa, wa, wa")
(parallel
- [(match_operand:QI 2 "const_0_to_1_operand" "wD, n, wD, n")])))]
+ [(match_operand:QI 2 "const_0_to_1_operand" "wD, n, wD, n")])))]
"VECTOR_MEM_VSX_P (<MODE>mode)"
{
int element = INTVAL (operands[2]);
@@ -3248,11 +3180,12 @@
else
gcc_unreachable ();
}
- [(set_attr "type" "veclogical,mftgpr,mftgpr,vecperm")])
+ [(set_attr "type" "veclogical,mftgpr,mftgpr,vecperm")
+ (set_attr "isa" "*,*,p8v,p9v")])
;; Optimize extracting a single scalar element from memory.
(define_insn_and_split "*vsx_extract_<P:mode>_<VSX_D:mode>_load"
- [(set (match_operand:<VS_scalar> 0 "register_operand" "=<VSX_D:VS_64reg>,wr")
+ [(set (match_operand:<VS_scalar> 0 "register_operand" "=wa,wr")
(vec_select:<VSX_D:VS_scalar>
(match_operand:VSX_D 1 "memory_operand" "m,m")
(parallel [(match_operand:QI 2 "const_0_to_1_operand" "n,n")])))
@@ -3273,14 +3206,15 @@
(define_insn "*vsx_extract_<mode>_store"
[(set (match_operand:<VS_scalar> 0 "memory_operand" "=m,Z,wY")
(vec_select:<VS_scalar>
- (match_operand:VSX_D 1 "register_operand" "d,wv,wb")
+ (match_operand:VSX_D 1 "register_operand" "d,v,v")
(parallel [(match_operand:QI 2 "vsx_scalar_64bit" "wD,wD,wD")])))]
"VECTOR_MEM_VSX_P (<MODE>mode)"
"@
stfd%U0%X0 %1,%0
stxsdx %x1,%y0
stxsd %1,%0"
- [(set_attr "type" "fpstore")])
+ [(set_attr "type" "fpstore")
+ (set_attr "isa" "*,p7v,p9v")])
;; Variable V2DI/V2DF extract shift
(define_insn "vsx_vslo_<mode>"
@@ -3294,7 +3228,7 @@
;; Variable V2DI/V2DF extract
(define_insn_and_split "vsx_extract_<mode>_var"
- [(set (match_operand:<VS_scalar> 0 "gpc_reg_operand" "=v,<VSa>,r")
+ [(set (match_operand:<VS_scalar> 0 "gpc_reg_operand" "=v,wa,r")
(unspec:<VS_scalar> [(match_operand:VSX_D 1 "input_operand" "v,m,m")
(match_operand:DI 2 "gpc_reg_operand" "r,r,r")]
UNSPEC_VSX_EXTRACT))
@@ -3312,7 +3246,7 @@
;; Extract a SF element from V4SF
(define_insn_and_split "vsx_extract_v4sf"
- [(set (match_operand:SF 0 "vsx_register_operand" "=ww")
+ [(set (match_operand:SF 0 "vsx_register_operand" "=wa")
(vec_select:SF
(match_operand:V4SF 1 "vsx_register_operand" "wa")
(parallel [(match_operand:QI 2 "u5bit_cint_operand" "n")])))
@@ -3345,7 +3279,7 @@
(set_attr "type" "fp")])
(define_insn_and_split "*vsx_extract_v4sf_<mode>_load"
- [(set (match_operand:SF 0 "register_operand" "=f,wv,wb,?r")
+ [(set (match_operand:SF 0 "register_operand" "=f,v,v,?r")
(vec_select:SF
(match_operand:V4SF 1 "memory_operand" "m,Z,m,m")
(parallel [(match_operand:QI 2 "const_0_to_3_operand" "n,n,n,n")])))
@@ -3359,11 +3293,12 @@
operands[3], SFmode);
}
[(set_attr "type" "fpload,fpload,fpload,load")
- (set_attr "length" "8")])
+ (set_attr "length" "8")
+ (set_attr "isa" "*,p7v,p9v,*")])
;; Variable V4SF extract
(define_insn_and_split "vsx_extract_v4sf_var"
- [(set (match_operand:SF 0 "gpc_reg_operand" "=ww,ww,?r")
+ [(set (match_operand:SF 0 "gpc_reg_operand" "=wa,wa,?r")
(unspec:SF [(match_operand:V4SF 1 "input_operand" "v,m,m")
(match_operand:DI 2 "gpc_reg_operand" "r,r,r")]
UNSPEC_VSX_EXTRACT))
@@ -3455,11 +3390,11 @@
})
(define_insn "vsx_xxpermdi2_<mode>_1"
- [(set (match_operand:VSX_D 0 "vsx_register_operand" "=wd")
+ [(set (match_operand:VSX_D 0 "vsx_register_operand" "=wa")
(vec_select:VSX_D
(vec_concat:<VS_double>
- (match_operand:VSX_D 1 "vsx_register_operand" "wd")
- (match_operand:VSX_D 2 "vsx_register_operand" "wd"))
+ (match_operand:VSX_D 1 "vsx_register_operand" "wa")
+ (match_operand:VSX_D 2 "vsx_register_operand" "wa"))
(parallel [(match_operand 3 "const_0_to_1_operand" "")
(match_operand 4 "const_2_to_3_operand" "")])))]
"VECTOR_MEM_VSX_P (<MODE>mode)"
@@ -3516,7 +3451,7 @@
(define_insn "vsx_extract_<mode>_p9"
[(set (match_operand:<VS_scalar> 0 "gpc_reg_operand" "=r,<VSX_EX>")
(vec_select:<VS_scalar>
- (match_operand:VSX_EXTRACT_I 1 "gpc_reg_operand" "wK,<VSX_EX>")
+ (match_operand:VSX_EXTRACT_I 1 "gpc_reg_operand" "v,<VSX_EX>")
(parallel [(match_operand:QI 2 "<VSX_EXTRACT_PREDICATE>" "n,n")])))
(clobber (match_scratch:SI 3 "=r,X"))]
"VECTOR_MEM_VSX_P (<MODE>mode) && TARGET_VEXTRACTUB"
@@ -3541,7 +3476,8 @@
return "vextractu<wd> %0,%1,%2";
}
}
- [(set_attr "type" "vecsimple")])
+ [(set_attr "type" "vecsimple")
+ (set_attr "isa" "p9v,*")])
(define_split
[(set (match_operand:<VS_scalar> 0 "int_reg_operand")
@@ -3571,7 +3507,7 @@
[(set (match_operand:DI 0 "gpc_reg_operand" "=r,<VSX_EX>")
(zero_extend:DI
(vec_select:<VS_scalar>
- (match_operand:VSX_EXTRACT_I 1 "gpc_reg_operand" "wK,<VSX_EX>")
+ (match_operand:VSX_EXTRACT_I 1 "gpc_reg_operand" "v,<VSX_EX>")
(parallel [(match_operand:QI 2 "const_int_operand" "n,n")]))))
(clobber (match_scratch:SI 3 "=r,X"))]
"VECTOR_MEM_VSX_P (<MODE>mode) && TARGET_VEXTRACTUB"
@@ -3584,7 +3520,8 @@
(clobber (match_dup 3))])]
{
operands[4] = gen_rtx_REG (<VS_scalar>mode, REGNO (operands[0]));
-})
+}
+ [(set_attr "isa" "p9v,*")])
;; Optimize stores to use the ISA 3.0 scalar store instructions
(define_insn_and_split "*vsx_extract_<mode>_store_p9"
@@ -3606,11 +3543,11 @@
(match_dup 3))])
(define_insn_and_split "*vsx_extract_si"
- [(set (match_operand:SI 0 "nonimmediate_operand" "=r,wHwI,Z")
+ [(set (match_operand:SI 0 "nonimmediate_operand" "=r,wa,Z")
(vec_select:SI
- (match_operand:V4SI 1 "gpc_reg_operand" "wJv,wJv,wJv")
+ (match_operand:V4SI 1 "gpc_reg_operand" "v,v,v")
(parallel [(match_operand:QI 2 "const_0_to_3_operand" "n,n,n")])))
- (clobber (match_scratch:V4SI 3 "=wJv,wJv,wJv"))]
+ (clobber (match_scratch:V4SI 3 "=v,v,v"))]
"VECTOR_MEM_VSX_P (V4SImode) && TARGET_DIRECT_MOVE_64BIT && !TARGET_P9_VECTOR"
"#"
"&& reload_completed"
@@ -3653,7 +3590,8 @@
DONE;
}
[(set_attr "type" "mftgpr,vecperm,fpstore")
- (set_attr "length" "8")])
+ (set_attr "length" "8")
+ (set_attr "isa" "*,p8v,*")])
(define_insn_and_split "*vsx_extract_<mode>_p8"
[(set (match_operand:<VS_scalar> 0 "nonimmediate_operand" "=r")
@@ -3724,7 +3662,7 @@
(define_insn_and_split "vsx_extract_<mode>_var"
[(set (match_operand:<VS_scalar> 0 "gpc_reg_operand" "=r,r,r")
(unspec:<VS_scalar>
- [(match_operand:VSX_EXTRACT_I 1 "input_operand" "wK,v,m")
+ [(match_operand:VSX_EXTRACT_I 1 "input_operand" "v,v,m")
(match_operand:DI 2 "gpc_reg_operand" "r,r,r")]
UNSPEC_VSX_EXTRACT))
(clobber (match_scratch:DI 3 "=r,r,&b"))
@@ -3737,13 +3675,14 @@
rs6000_split_vec_extract_var (operands[0], operands[1], operands[2],
operands[3], operands[4]);
DONE;
-})
+}
+ [(set_attr "isa" "p9v,*,*")])
(define_insn_and_split "*vsx_extract_<mode>_<VS_scalar>mode_var"
[(set (match_operand:<VS_scalar> 0 "gpc_reg_operand" "=r,r,r")
(zero_extend:<VS_scalar>
(unspec:<VSX_EXTRACT_I:VS_scalar>
- [(match_operand:VSX_EXTRACT_I 1 "input_operand" "wK,v,m")
+ [(match_operand:VSX_EXTRACT_I 1 "input_operand" "v,v,m")
(match_operand:DI 2 "gpc_reg_operand" "r,r,r")]
UNSPEC_VSX_EXTRACT)))
(clobber (match_scratch:DI 3 "=r,r,&b"))
@@ -3758,13 +3697,14 @@
operands[1], operands[2],
operands[3], operands[4]);
DONE;
-})
+}
+ [(set_attr "isa" "p9v,*,*")])
;; VSX_EXTRACT optimizations
;; Optimize double d = (double) vec_extract (vi, <n>)
;; Get the element into the top position and use XVCVSWDP/XVCVUWDP
(define_insn_and_split "*vsx_extract_si_<uns>float_df"
- [(set (match_operand:DF 0 "gpc_reg_operand" "=ws")
+ [(set (match_operand:DF 0 "gpc_reg_operand" "=wa")
(any_float:DF
(vec_select:SI
(match_operand:V4SI 1 "gpc_reg_operand" "v")
@@ -3805,13 +3745,13 @@
;; not double. First convert the value to double, and then to the desired
;; type.
(define_insn_and_split "*vsx_extract_si_<uns>float_<mode>"
- [(set (match_operand:VSX_EXTRACT_FL 0 "gpc_reg_operand" "=ww")
+ [(set (match_operand:VSX_EXTRACT_FL 0 "gpc_reg_operand" "=wa")
(any_float:VSX_EXTRACT_FL
(vec_select:SI
(match_operand:V4SI 1 "gpc_reg_operand" "v")
(parallel [(match_operand:QI 2 "const_0_to_3_operand" "n")]))))
(clobber (match_scratch:V4SI 3 "=v"))
- (clobber (match_scratch:DF 4 "=ws"))]
+ (clobber (match_scratch:DF 4 "=wa"))]
"VECTOR_MEM_VSX_P (V4SImode) && TARGET_DIRECT_MOVE_64BIT"
"#"
"&& 1"
@@ -3866,7 +3806,7 @@
;; 128-bit hardware types) and <vtype> is vector char, vector unsigned char,
;; vector short or vector unsigned short.
(define_insn_and_split "*vsx_ext_<VSX_EXTRACT_I:VS_scalar>_fl_<FL_CONV:mode>"
- [(set (match_operand:FL_CONV 0 "gpc_reg_operand" "=<FL_CONV:VSr3>")
+ [(set (match_operand:FL_CONV 0 "gpc_reg_operand" "=wa")
(float:FL_CONV
(vec_select:<VSX_EXTRACT_I:VS_scalar>
(match_operand:VSX_EXTRACT_I 1 "gpc_reg_operand" "v")
@@ -3887,10 +3827,11 @@
(float:<FL_CONV:MODE> (match_dup 4)))]
{
operands[4] = gen_rtx_REG (DImode, REGNO (operands[3]));
-})
+}
+ [(set_attr "isa" "<VSisa>")])
(define_insn_and_split "*vsx_ext_<VSX_EXTRACT_I:VS_scalar>_ufl_<FL_CONV:mode>"
- [(set (match_operand:FL_CONV 0 "gpc_reg_operand" "=<FL_CONV:VSr3>")
+ [(set (match_operand:FL_CONV 0 "gpc_reg_operand" "=wa")
(unsigned_float:FL_CONV
(vec_select:<VSX_EXTRACT_I:VS_scalar>
(match_operand:VSX_EXTRACT_I 1 "gpc_reg_operand" "v")
@@ -3909,7 +3850,8 @@
(float:<FL_CONV:MODE> (match_dup 4)))]
{
operands[4] = gen_rtx_REG (DImode, REGNO (operands[3]));
-})
+}
+ [(set_attr "isa" "<VSisa>")])
;; V4SI/V8HI/V16QI set operation on ISA 3.0
(define_insn "vsx_set_<mode>_p9"
@@ -3939,10 +3881,10 @@
[(set (match_operand:V4SF 0 "gpc_reg_operand" "=wa")
(unspec:V4SF
[(match_operand:V4SF 1 "gpc_reg_operand" "0")
- (match_operand:SF 2 "gpc_reg_operand" "ww")
+ (match_operand:SF 2 "gpc_reg_operand" "wa")
(match_operand:QI 3 "const_0_to_3_operand" "n")]
UNSPEC_VSX_SET))
- (clobber (match_scratch:SI 4 "=&wJwK"))]
+ (clobber (match_scratch:SI 4 "=&wa"))]
"VECTOR_MEM_VSX_P (V4SFmode) && TARGET_P9_VECTOR && TARGET_POWERPC64"
"#"
"&& reload_completed"
@@ -3967,7 +3909,8 @@
operands[8] = gen_rtx_REG (V4SImode, reg_or_subregno (operands[0]));
}
[(set_attr "type" "vecperm")
- (set_attr "length" "12")])
+ (set_attr "length" "12")
+ (set_attr "isa" "p9v")])
;; Special case setting 0.0f to a V4SF element
(define_insn_and_split "*vsx_set_v4sf_p9_zero"
@@ -3977,7 +3920,7 @@
(match_operand:SF 2 "zero_fp_constant" "j")
(match_operand:QI 3 "const_0_to_3_operand" "n")]
UNSPEC_VSX_SET))
- (clobber (match_scratch:SI 4 "=&wJwK"))]
+ (clobber (match_scratch:SI 4 "=&wa"))]
"VECTOR_MEM_VSX_P (V4SFmode) && TARGET_P9_VECTOR && TARGET_POWERPC64"
"#"
"&& reload_completed"
@@ -3992,7 +3935,8 @@
operands[5] = gen_rtx_REG (V4SImode, reg_or_subregno (operands[0]));
}
[(set_attr "type" "vecperm")
- (set_attr "length" "8")])
+ (set_attr "length" "8")
+ (set_attr "isa" "p9v")])
;; Optimize x = vec_insert (vec_extract (v2, n), v1, m) if n is the element
;; that is in the default scalar position (1 for big endian, 2 for little
@@ -4034,7 +3978,7 @@
[(match_operand:QI 3 "const_0_to_3_operand" "n")]))
(match_operand:QI 4 "const_0_to_3_operand" "n")]
UNSPEC_VSX_SET))
- (clobber (match_scratch:SI 5 "=&wJwK"))]
+ (clobber (match_scratch:SI 5 "=&wa"))]
"VECTOR_MEM_VSX_P (V4SFmode) && VECTOR_MEM_VSX_P (V4SImode)
&& TARGET_P9_VECTOR && TARGET_POWERPC64
&& (INTVAL (operands[3]) != (BYTES_BIG_ENDIAN ? 1 : 2))"
@@ -4057,7 +4001,8 @@
operands[7] = gen_lowpart (V4SImode, operands[0]);
operands[8] = gen_lowpart (V4SImode, operands[1]);
}
- [(set_attr "type" "vecperm")])
+ [(set_attr "type" "vecperm")
+ (set_attr "isa" "p9v")])
;; Expanders for builtins
(define_expand "vsx_mergel_<mode>"
@@ -4106,17 +4051,17 @@
})
(define_insn "vsx_splat_<mode>_reg"
- [(set (match_operand:VSX_D 0 "vsx_register_operand" "=<VSX_D:VSa>,we")
+ [(set (match_operand:VSX_D 0 "vsx_register_operand" "=wa,we")
(vec_duplicate:VSX_D
- (match_operand:<VS_scalar> 1 "gpc_reg_operand" "<VSX_D:VS_64reg>,b")))]
+ (match_operand:<VS_scalar> 1 "gpc_reg_operand" "wa,b")))]
"VECTOR_MEM_VSX_P (<MODE>mode)"
"@
xxpermdi %x0,%x1,%x1,0
mtvsrdd %x0,%1,%1"
[(set_attr "type" "vecperm")])
-(define_insn "vsx_splat_<VSX_D:mode>_mem"
- [(set (match_operand:VSX_D 0 "vsx_register_operand" "=<VSX_D:VSa>")
+(define_insn "vsx_splat_<mode>_mem"
+ [(set (match_operand:VSX_D 0 "vsx_register_operand" "=wa")
(vec_duplicate:VSX_D
(match_operand:<VSX_D:VS_scalar> 1 "memory_operand" "Z")))]
"VECTOR_MEM_VSX_P (<MODE>mode)"
@@ -4141,18 +4086,19 @@
[(set (match_operand:V4SI 0 "vsx_register_operand" "=wa,we")
(vec_duplicate:V4SI
(truncate:SI
- (match_operand:DI 1 "gpc_reg_operand" "wj,r"))))]
+ (match_operand:DI 1 "gpc_reg_operand" "wa,r"))))]
"VECTOR_MEM_VSX_P (V4SImode) && TARGET_DIRECT_MOVE_64BIT"
"@
xxspltw %x0,%x1,1
mtvsrws %x0,%1"
- [(set_attr "type" "vecperm")])
+ [(set_attr "type" "vecperm")
+ (set_attr "isa" "p8v,*")])
;; V4SF splat (ISA 3.0)
(define_insn_and_split "vsx_splat_v4sf"
[(set (match_operand:V4SF 0 "vsx_register_operand" "=wa,wa,wa")
(vec_duplicate:V4SF
- (match_operand:SF 1 "splat_input_operand" "Z,wy,r")))]
+ (match_operand:SF 1 "splat_input_operand" "Z,wa,r")))]
"TARGET_P9_VECTOR"
"@
lxvwsx %x0,%y1
@@ -4166,14 +4112,15 @@
(const_int 0)] UNSPEC_VSX_XXSPLTW))]
""
[(set_attr "type" "vecload,vecperm,mftgpr")
- (set_attr "length" "4,8,4")])
+ (set_attr "length" "*,8,*")
+ (set_attr "isa" "*,p8v,*")])
;; V4SF/V4SI splat from a vector element
(define_insn "vsx_xxspltw_<mode>"
- [(set (match_operand:VSX_W 0 "vsx_register_operand" "=<VSa>")
+ [(set (match_operand:VSX_W 0 "vsx_register_operand" "=wa")
(vec_duplicate:VSX_W
(vec_select:<VS_scalar>
- (match_operand:VSX_W 1 "vsx_register_operand" "<VSa>")
+ (match_operand:VSX_W 1 "vsx_register_operand" "wa")
(parallel
[(match_operand:QI 2 "u5bit_cint_operand" "n")]))))]
"VECTOR_MEM_VSX_P (<MODE>mode)"
@@ -4186,8 +4133,8 @@
[(set_attr "type" "vecperm")])
(define_insn "vsx_xxspltw_<mode>_direct"
- [(set (match_operand:VSX_W 0 "vsx_register_operand" "=<VSa>")
- (unspec:VSX_W [(match_operand:VSX_W 1 "vsx_register_operand" "<VSa>")
+ [(set (match_operand:VSX_W 0 "vsx_register_operand" "=wa")
+ (unspec:VSX_W [(match_operand:VSX_W 1 "vsx_register_operand" "wa")
(match_operand:QI 2 "u5bit_cint_operand" "i")]
UNSPEC_VSX_XXSPLTW))]
"VECTOR_MEM_VSX_P (<MODE>mode)"
@@ -4222,11 +4169,11 @@
;; V4SF/V4SI interleave
(define_insn "vsx_xxmrghw_<mode>"
- [(set (match_operand:VSX_W 0 "vsx_register_operand" "=wf,?<VSa>")
+ [(set (match_operand:VSX_W 0 "vsx_register_operand" "=wa")
(vec_select:VSX_W
(vec_concat:<VS_double>
- (match_operand:VSX_W 1 "vsx_register_operand" "wf,<VSa>")
- (match_operand:VSX_W 2 "vsx_register_operand" "wf,<VSa>"))
+ (match_operand:VSX_W 1 "vsx_register_operand" "wa")
+ (match_operand:VSX_W 2 "vsx_register_operand" "wa"))
(parallel [(const_int 0) (const_int 4)
(const_int 1) (const_int 5)])))]
"VECTOR_MEM_VSX_P (<MODE>mode)"
@@ -4239,11 +4186,11 @@
[(set_attr "type" "vecperm")])
(define_insn "vsx_xxmrglw_<mode>"
- [(set (match_operand:VSX_W 0 "vsx_register_operand" "=wf,?<VSa>")
+ [(set (match_operand:VSX_W 0 "vsx_register_operand" "=wa")
(vec_select:VSX_W
(vec_concat:<VS_double>
- (match_operand:VSX_W 1 "vsx_register_operand" "wf,<VSa>")
- (match_operand:VSX_W 2 "vsx_register_operand" "wf,?<VSa>"))
+ (match_operand:VSX_W 1 "vsx_register_operand" "wa")
+ (match_operand:VSX_W 2 "vsx_register_operand" "wa"))
(parallel [(const_int 2) (const_int 6)
(const_int 3) (const_int 7)])))]
"VECTOR_MEM_VSX_P (<MODE>mode)"
@@ -4257,30 +4204,31 @@
;; Shift left double by word immediate
(define_insn "vsx_xxsldwi_<mode>"
- [(set (match_operand:VSX_L 0 "vsx_register_operand" "=<VSa>")
- (unspec:VSX_L [(match_operand:VSX_L 1 "vsx_register_operand" "<VSa>")
- (match_operand:VSX_L 2 "vsx_register_operand" "<VSa>")
+ [(set (match_operand:VSX_L 0 "vsx_register_operand" "=wa")
+ (unspec:VSX_L [(match_operand:VSX_L 1 "vsx_register_operand" "wa")
+ (match_operand:VSX_L 2 "vsx_register_operand" "wa")
(match_operand:QI 3 "u5bit_cint_operand" "i")]
UNSPEC_VSX_SLDWI))]
"VECTOR_MEM_VSX_P (<MODE>mode)"
"xxsldwi %x0,%x1,%x2,%3"
- [(set_attr "type" "vecperm")])
+ [(set_attr "type" "vecperm")
+ (set_attr "isa" "<VSisa>")])
;; Vector reduction insns and splitters
(define_insn_and_split "vsx_reduc_<VEC_reduc_name>_v2df"
- [(set (match_operand:V2DF 0 "vfloat_operand" "=&wd,&?wa,wd,?wa")
+ [(set (match_operand:V2DF 0 "vfloat_operand" "=&wa,wa")
(VEC_reduc:V2DF
(vec_concat:V2DF
(vec_select:DF
- (match_operand:V2DF 1 "vfloat_operand" "wd,wa,wd,wa")
+ (match_operand:V2DF 1 "vfloat_operand" "wa,wa")
(parallel [(const_int 1)]))
(vec_select:DF
(match_dup 1)
(parallel [(const_int 0)])))
(match_dup 1)))
- (clobber (match_scratch:V2DF 2 "=0,0,&wd,&wa"))]
+ (clobber (match_scratch:V2DF 2 "=0,&wa"))]
"VECTOR_UNIT_VSX_P (V2DFmode)"
"#"
""
@@ -4297,12 +4245,12 @@
(set_attr "type" "veccomplex")])
(define_insn_and_split "vsx_reduc_<VEC_reduc_name>_v4sf"
- [(set (match_operand:V4SF 0 "vfloat_operand" "=wf,?wa")
+ [(set (match_operand:V4SF 0 "vfloat_operand" "=wa")
(VEC_reduc:V4SF
(unspec:V4SF [(const_int 0)] UNSPEC_REDUC)
- (match_operand:V4SF 1 "vfloat_operand" "wf,wa")))
- (clobber (match_scratch:V4SF 2 "=&wf,&wa"))
- (clobber (match_scratch:V4SF 3 "=&wf,&wa"))]
+ (match_operand:V4SF 1 "vfloat_operand" "wa")))
+ (clobber (match_scratch:V4SF 2 "=&wa"))
+ (clobber (match_scratch:V4SF 3 "=&wa"))]
"VECTOR_UNIT_VSX_P (V4SFmode)"
"#"
""
@@ -4338,19 +4286,19 @@
;; to the top element of the V2DF array without doing an extract.
(define_insn_and_split "*vsx_reduc_<VEC_reduc_name>_v2df_scalar"
- [(set (match_operand:DF 0 "vfloat_operand" "=&ws,&?ws,ws,?ws")
+ [(set (match_operand:DF 0 "vfloat_operand" "=&wa,wa")
(vec_select:DF
(VEC_reduc:V2DF
(vec_concat:V2DF
(vec_select:DF
- (match_operand:V2DF 1 "vfloat_operand" "wd,wa,wd,wa")
+ (match_operand:V2DF 1 "vfloat_operand" "wa,wa")
(parallel [(const_int 1)]))
(vec_select:DF
(match_dup 1)
(parallel [(const_int 0)])))
(match_dup 1))
(parallel [(const_int 1)])))
- (clobber (match_scratch:DF 2 "=0,0,&wd,&wa"))]
+ (clobber (match_scratch:DF 2 "=0,&wa"))]
"BYTES_BIG_ENDIAN && VECTOR_UNIT_VSX_P (V2DFmode)"
"#"
""
@@ -4369,15 +4317,15 @@
(set_attr "type" "veccomplex")])
(define_insn_and_split "*vsx_reduc_<VEC_reduc_name>_v4sf_scalar"
- [(set (match_operand:SF 0 "vfloat_operand" "=f,?f")
+ [(set (match_operand:SF 0 "vfloat_operand" "=f")
(vec_select:SF
(VEC_reduc:V4SF
(unspec:V4SF [(const_int 0)] UNSPEC_REDUC)
- (match_operand:V4SF 1 "vfloat_operand" "wf,wa"))
+ (match_operand:V4SF 1 "vfloat_operand" "wa"))
(parallel [(const_int 3)])))
- (clobber (match_scratch:V4SF 2 "=&wf,&wa"))
- (clobber (match_scratch:V4SF 3 "=&wf,&wa"))
- (clobber (match_scratch:V4SF 4 "=0,0"))]
+ (clobber (match_scratch:V4SF 2 "=&wa"))
+ (clobber (match_scratch:V4SF 3 "=&wa"))
+ (clobber (match_scratch:V4SF 4 "=0"))]
"BYTES_BIG_ENDIAN && VECTOR_UNIT_VSX_P (V4SFmode)"
"#"
""
@@ -4626,7 +4574,7 @@
;; (The lt bit is set if operand 1 is negative. The eq bit is set
;; if any of the conditions tested by operand 2 are satisfied.
;; The gt and unordered bits are cleared to zero.)
-(define_expand "xststdc<Fvsx>"
+(define_expand "xststdc<sd>p"
[(set (match_dup 3)
(compare:CCFP
(unspec:SFDF
@@ -4661,7 +4609,7 @@
})
;; The VSX Scalar Test Negative Double- and Single-Precision
-(define_expand "xststdcneg<Fvsx>"
+(define_expand "xststdcneg<sd>p"
[(set (match_dup 2)
(compare:CCFP
(unspec:SFDF
@@ -4690,7 +4638,7 @@
"xststdcqp %0,%1,%2"
[(set_attr "type" "fpcompare")])
-(define_insn "*xststdc<Fvsx>"
+(define_insn "*xststdc<sd>p"
[(set (match_operand:CCFP 0 "" "=y")
(compare:CCFP
(unspec:SFDF [(match_operand:SFDF 1 "vsx_register_operand" "wa")
@@ -4698,51 +4646,51 @@
UNSPEC_VSX_STSTDC)
(match_operand:SI 3 "zero_constant" "j")))]
"TARGET_P9_VECTOR"
- "xststdc<Fvsx> %0,%x1,%2"
+ "xststdc<sd>p %0,%x1,%2"
[(set_attr "type" "fpcompare")])
;; VSX Vector Extract Exponent Double and Single Precision
-(define_insn "xvxexp<VSs>"
+(define_insn "xvxexp<sd>p"
[(set (match_operand:VSX_F 0 "vsx_register_operand" "=wa")
(unspec:VSX_F
[(match_operand:VSX_F 1 "vsx_register_operand" "wa")]
UNSPEC_VSX_VXEXP))]
"TARGET_P9_VECTOR"
- "xvxexp<VSs> %x0,%x1"
+ "xvxexp<sd>p %x0,%x1"
[(set_attr "type" "vecsimple")])
;; VSX Vector Extract Significand Double and Single Precision
-(define_insn "xvxsig<VSs>"
+(define_insn "xvxsig<sd>p"
[(set (match_operand:VSX_F 0 "vsx_register_operand" "=wa")
(unspec:VSX_F
[(match_operand:VSX_F 1 "vsx_register_operand" "wa")]
UNSPEC_VSX_VXSIG))]
"TARGET_P9_VECTOR"
- "xvxsig<VSs> %x0,%x1"
+ "xvxsig<sd>p %x0,%x1"
[(set_attr "type" "vecsimple")])
;; VSX Vector Insert Exponent Double and Single Precision
-(define_insn "xviexp<VSs>"
+(define_insn "xviexp<sd>p"
[(set (match_operand:VSX_F 0 "vsx_register_operand" "=wa")
(unspec:VSX_F
[(match_operand:VSX_F 1 "vsx_register_operand" "wa")
(match_operand:VSX_F 2 "vsx_register_operand" "wa")]
UNSPEC_VSX_VIEXP))]
"TARGET_P9_VECTOR"
- "xviexp<VSs> %x0,%x1,%x2"
+ "xviexp<sd>p %x0,%x1,%x2"
[(set_attr "type" "vecsimple")])
;; VSX Vector Test Data Class Double and Single Precision
;; The corresponding elements of the result vector are all ones
;; if any of the conditions tested by operand 3 are satisfied.
-(define_insn "xvtstdc<VSs>"
+(define_insn "xvtstdc<sd>p"
[(set (match_operand:<VSI> 0 "vsx_register_operand" "=wa")
(unspec:<VSI>
[(match_operand:VSX_F 1 "vsx_register_operand" "wa")
(match_operand:SI 2 "u7bit_cint_operand" "n")]
UNSPEC_VSX_VTSTDC))]
"TARGET_P9_VECTOR"
- "xvtstdc<VSs> %x0,%x1,%2"
+ "xvtstdc<sd>p %x0,%x1,%2"
[(set_attr "type" "vecsimple")])
;; ISA 3.0 String Operations Support
diff --git a/gcc/config/rx/elf.opt b/gcc/config/rx/elf.opt
new file mode 100644
index 0000000..907e030
--- /dev/null
+++ b/gcc/config/rx/elf.opt
@@ -0,0 +1,44 @@
+; Command line options for the Renesas RX port of GCC.
+; Copyright (C) 2008, 2009, 2010 Free Software Foundation, Inc.
+; Contributed by Red Hat.
+;
+; This file is part of GCC.
+;
+; GCC is free software; you can redistribute it and/or modify it under
+; the terms of the GNU General Public License as published by the Free
+; Software Foundation; either version 3, or (at your option) any later
+; version.
+;
+; GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+; WARRANTY; without even the implied warranty of MERCHANTABILITY or
+; FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+; for more details.
+;
+; 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/>.
+;---------------------------------------------------
+
+; elf target extra options
+
+msim
+Target
+Use the simulator runtime.
+
+;---------------------------------------------------
+
+mas100-syntax
+Target Mask(AS100_SYNTAX) Report
+Generate assembler output that is compatible with the Renesas AS100 assembler. This may restrict some of the compiler's capabilities. The default is to generate GAS compatable syntax.
+
+;---------------------------------------------------
+
+mint-register=
+Target RejectNegative Joined UInteger Var(rx_interrupt_registers) Init(0)
+Specifies the number of registers to reserve for interrupt handlers.
+
+;---------------------------------------------------
+
+msave-acc-in-interrupts
+Target Mask(SAVE_ACC_REGISTER)
+Specifies whether interrupt functions should save and restore the accumulator register.
diff --git a/gcc/config/rx/linux.h b/gcc/config/rx/linux.h
new file mode 100644
index 0000000..9ee484a
--- /dev/null
+++ b/gcc/config/rx/linux.h
@@ -0,0 +1,231 @@
+/* GCC backend definitions for the rx-linux
+ Copyright (C) 2019 Yoshinori Sato
+ Based on rx.h
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+ License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GCC; see the file COPYING3. If not see
+ <http://www.gnu.org/licenses/>. */
+
+
+#include "config/rx/rx.h"
+
+#undef TARGET_CPU_CPP_BUILTINS
+#define TARGET_CPU_CPP_BUILTINS() \
+ do \
+ { \
+ builtin_define ("__RX__"); \
+ builtin_assert ("cpu=RX"); \
+ if (rx_cpu_type == RX610) \
+ builtin_assert ("machine=RX610"); \
+ else \
+ builtin_assert ("machine=RX600"); \
+ \
+ if (TARGET_BIG_ENDIAN_DATA) \
+ builtin_define ("__RX_BIG_ENDIAN__"); \
+ else \
+ builtin_define ("__RX_LITTLE_ENDIAN__");\
+ \
+ if (TARGET_64BIT_DOUBLES) \
+ builtin_define ("__RX_64BIT_DOUBLES__");\
+ else \
+ builtin_define ("__RX_32BIT_DOUBLES__");\
+ \
+ if (ALLOW_RX_FPU_INSNS) \
+ builtin_define ("__RX_FPU_INSNS__"); \
+ \
+ } \
+ while (0)
+
+#undef CC1_SPEC
+#define CC1_SPEC "\
+ %{mcpu=rx200:%{fpu:%erx200 cpu does not have FPU hardware}}"
+
+#undef ASM_SPEC
+#define ASM_SPEC "\
+%{mbig-endian-data:-mbig-endian-data} \
+%{m64bit-doubles:-m64bit-doubles} \
+%{!m64bit-doubles:-m32bit-doubles} \
+%{msmall-data-limit*:-msmall-data-limit} \
+%{mrelax:-relax} \
+"
+
+#undef DATA_SECTION_ASM_OP
+#define DATA_SECTION_ASM_OP \
+ "\t.section .data,\"aw\",@progbits\n\t.p2align 2"
+
+#undef SDATA_SECTION_ASM_OP
+#define SDATA_SECTION_ASM_OP \
+ "\t.section .data2,\"aw\",@progbits\n\t.p2align 1"
+
+#undef READONLY_DATA_SECTION_ASM_OP
+#define READONLY_DATA_SECTION_ASM_OP \
+ "\t.section .rodata,\"a\",@progbits\n\t.p2align 2"
+
+#undef BSS_SECTION_ASM_OP
+#define BSS_SECTION_ASM_OP \
+ "\t.section .bss\n\t.p2align 2"
+
+#undef SBSS_SECTION_ASM_OP
+#define SBSS_SECTION_ASM_OP \
+ "\t.section .bss2\n\t.p2align 1"
+
+/* The following definitions are conditional depending upon whether the
+ compiler is being built or crtstuff.c is being compiled by the built
+ compiler. */
+#undef TEXT_SECTION_ASM_OP
+#define TEXT_SECTION_ASM_OP \
+ "\t.section .text,\"ax\""
+#undef CTORS_SECTION_ASM_OP
+#define CTORS_SECTION_ASM_OP \
+ "\t.section\t.init_array,\"aw\",@init_array"
+#undef DTORS_SECTION_ASM_OP
+#define DTORS_SECTION_ASM_OP \
+ "\t.section\t.fini_array,\"aw\",@fini_array"
+#undef INIT_ARRAY_SECTION_ASM_OP
+#define INIT_ARRAY_SECTION_ASM_OP \
+ "\t.section\t.init_array,\"aw\",@init_array"
+#undef FINI_ARRAY_SECTION_ASM_OP
+#define FINI_ARRAY_SECTION_ASM_OP \
+ "\t.section\t.fini_array,\"aw\",@fini_array"
+
+#undef GLOBAL_ASM_OP
+#define GLOBAL_ASM_OP "\t.global\t"
+#undef USER_LABEL_PREFIX
+
+#undef ASM_OUTPUT_ALIGN
+#define ASM_OUTPUT_ALIGN(STREAM, LOG) \
+ do \
+ { \
+ if ((LOG) == 0) \
+ break; \
+ fprintf (STREAM, "\t.balign %d\n", 1 << (LOG)); \
+ } \
+ while (0)
+
+#undef ASM_OUTPUT_ADDR_VEC_ELT
+#define ASM_OUTPUT_ADDR_VEC_ELT(FILE, VALUE) \
+ fprintf (FILE, "\t.long .L%d\n", VALUE)
+
+/* This is how to output an element of a case-vector that is relative.
+ Note: The local label referenced by the "1b" below is emitted by
+ the tablejump insn. */
+
+#undef ASM_OUTPUT_ADDR_DIFF_ELT
+#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, BODY, VALUE, REL) \
+ fprintf (FILE, "\t.long .L%d - 1b\n", VALUE)
+
+#undef ASM_OUTPUT_SIZE_DIRECTIVE
+#define ASM_OUTPUT_SIZE_DIRECTIVE(STREAM, NAME, SIZE) \
+ do \
+ { \
+ HOST_WIDE_INT size_ = (SIZE); \
+ \
+ fputs (SIZE_ASM_OP, STREAM); \
+ assemble_name (STREAM, NAME); \
+ fprintf (STREAM, ", " HOST_WIDE_INT_PRINT_DEC "\n", size_); \
+ } \
+ while (0)
+
+#undef ASM_OUTPUT_MEASURED_SIZE
+#define ASM_OUTPUT_MEASURED_SIZE(STREAM, NAME) \
+ do \
+ { \
+ fputs (SIZE_ASM_OP, STREAM); \
+ assemble_name (STREAM, NAME); \
+ fputs (", .-", STREAM); \
+ assemble_name (STREAM, NAME); \
+ putc ('\n', STREAM); \
+ } \
+ while (0)
+
+#undef ASM_OUTPUT_TYPE_DIRECTIVE
+#define ASM_OUTPUT_TYPE_DIRECTIVE(STREAM, NAME, TYPE) \
+ do \
+ { \
+ fputs (TYPE_ASM_OP, STREAM); \
+ assemble_name (STREAM, NAME); \
+ fputs (", ", STREAM); \
+ fprintf (STREAM, TYPE_OPERAND_FMT, TYPE); \
+ putc ('\n', STREAM); \
+ } \
+ while (0)
+
+#undef ASM_GENERATE_INTERNAL_LABEL
+#define ASM_GENERATE_INTERNAL_LABEL(LABEL, PREFIX, NUM) \
+ do \
+ { \
+ sprintf (LABEL, "*.%s%u", PREFIX, (unsigned) (NUM)); \
+ } \
+ while (0)
+
+#undef ASM_OUTPUT_EXTERNAL
+#define ASM_OUTPUT_EXTERNAL(FILE, DECL, NAME) \
+ do \
+ { \
+ default_elf_asm_output_external (FILE, DECL, NAME); \
+ } \
+ while (0)
+
+#undef ASM_OUTPUT_ALIGNED_COMMON
+#define ASM_OUTPUT_ALIGNED_COMMON(FILE, NAME, SIZE, ALIGN) \
+ do \
+ { \
+ fprintf ((FILE), "%s", COMMON_ASM_OP); \
+ assemble_name ((FILE), (NAME)); \
+ fprintf ((FILE), "," HOST_WIDE_INT_PRINT_UNSIGNED ",%u\n", \
+ (SIZE), (ALIGN) / BITS_PER_UNIT); \
+ } \
+ while (0)
+
+#undef SKIP_ASM_OP
+#define SKIP_ASM_OP "\t.zero\t"
+
+#undef ASM_OUTPUT_LIMITED_STRING
+#define ASM_OUTPUT_LIMITED_STRING(FILE, STR) \
+ do \
+ { \
+ const unsigned char *_limited_str = \
+ (const unsigned char *) (STR); \
+ unsigned ch; \
+ \
+ fprintf ((FILE), "\t.string\t\""); \
+ \
+ for (; (ch = *_limited_str); _limited_str++) \
+ { \
+ int escape; \
+ \
+ switch (escape = ESCAPES[ch]) \
+ { \
+ case 0: \
+ putc (ch, (FILE)); \
+ break; \
+ case 1: \
+ fprintf ((FILE), "\\%03o", ch); \
+ break; \
+ default: \
+ putc ('\\', (FILE)); \
+ putc (escape, (FILE)); \
+ break; \
+ } \
+ } \
+ \
+ fprintf ((FILE), "\"\n"); \
+ } \
+ while (0)
+
+#undef PREFERRED_DEBUGGING_TYPE
+
+#undef TARGET_AS100_SYNTAX
+#define TARGET_AS100_SYNTAX 0
diff --git a/gcc/config/rx/rx.c b/gcc/config/rx/rx.c
index f70e8f3..0695f3b 100644
--- a/gcc/config/rx/rx.c
+++ b/gcc/config/rx/rx.c
@@ -1438,10 +1438,14 @@ bit_count (unsigned int x)
return (x + (x >> 16)) & 0x3f;
}
+#if defined(TARGET_SAVE_ACC_REGISTER)
#define MUST_SAVE_ACC_REGISTER \
(TARGET_SAVE_ACC_REGISTER \
&& (is_interrupt_func (NULL_TREE) \
|| is_fast_interrupt_func (NULL_TREE)))
+#else
+#define MUST_SAVE_ACC_REGISTER 0
+#endif
/* Returns either the lowest numbered and highest numbered registers that
occupy the call-saved area of the stack frame, if the registers are
diff --git a/gcc/config/rx/rx.h b/gcc/config/rx/rx.h
index b50b48f..672e087 100644
--- a/gcc/config/rx/rx.h
+++ b/gcc/config/rx/rx.h
@@ -408,7 +408,9 @@ typedef unsigned int CUMULATIVE_ARGS;
#define GLOBAL_ASM_OP \
(TARGET_AS100_SYNTAX ? "\t.GLB\t" : "\t.global\t")
#define ASM_COMMENT_START " ;"
+#undef ASM_APP_ON
#define ASM_APP_ON ""
+#undef ASM_APP_OFF
#define ASM_APP_OFF ""
#define LOCAL_LABEL_PREFIX "L"
#undef USER_LABEL_PREFIX
diff --git a/gcc/config/rx/rx.md b/gcc/config/rx/rx.md
index 2790882..9df73e6 100644
--- a/gcc/config/rx/rx.md
+++ b/gcc/config/rx/rx.md
@@ -46,7 +46,7 @@
(UNSPEC_CONST 13)
(UNSPEC_MOVSTR 20)
- (UNSPEC_MOVMEM 21)
+ (UNSPEC_CPYMEM 21)
(UNSPEC_SETMEM 22)
(UNSPEC_STRLEN 23)
(UNSPEC_CMPSTRN 24)
@@ -2449,13 +2449,13 @@
(set_attr "timings" "1111")] ;; The timing is a guesstimate.
)
-(define_expand "movmemsi"
+(define_expand "cpymemsi"
[(parallel
[(set (match_operand:BLK 0 "memory_operand") ;; Dest
(match_operand:BLK 1 "memory_operand")) ;; Source
(use (match_operand:SI 2 "register_operand")) ;; Length in bytes
(match_operand 3 "immediate_operand") ;; Align
- (unspec_volatile:BLK [(reg:SI 1) (reg:SI 2) (reg:SI 3)] UNSPEC_MOVMEM)]
+ (unspec_volatile:BLK [(reg:SI 1) (reg:SI 2) (reg:SI 3)] UNSPEC_CPYMEM)]
)]
"rx_allow_string_insns"
{
@@ -2486,16 +2486,16 @@
emit_move_insn (len, force_operand (operands[2], NULL_RTX));
operands[0] = replace_equiv_address_nv (operands[0], addr1);
operands[1] = replace_equiv_address_nv (operands[1], addr2);
- emit_insn (gen_rx_movmem ());
+ emit_insn (gen_rx_cpymem ());
DONE;
}
)
-(define_insn "rx_movmem"
+(define_insn "rx_cpymem"
[(set (mem:BLK (reg:SI 1))
(mem:BLK (reg:SI 2)))
(use (reg:SI 3))
- (unspec_volatile:BLK [(reg:SI 1) (reg:SI 2) (reg:SI 3)] UNSPEC_MOVMEM)
+ (unspec_volatile:BLK [(reg:SI 1) (reg:SI 2) (reg:SI 3)] UNSPEC_CPYMEM)
(clobber (reg:SI 1))
(clobber (reg:SI 2))
(clobber (reg:SI 3))]
diff --git a/gcc/config/rx/rx.opt b/gcc/config/rx/rx.opt
index 50814a1..4e80c86 100644
--- a/gcc/config/rx/rx.opt
+++ b/gcc/config/rx/rx.opt
@@ -82,18 +82,6 @@ Maximum size of global and static variables which can be placed into the small d
;---------------------------------------------------
-msim
-Target
-Use the simulator runtime.
-
-;---------------------------------------------------
-
-mas100-syntax
-Target Mask(AS100_SYNTAX) Report
-Generate assembler output that is compatible with the Renesas AS100 assembler. This may restrict some of the compiler's capabilities. The default is to generate GAS compatible syntax.
-
-;---------------------------------------------------
-
mrelax
Target
Enable linker relaxation.
diff --git a/gcc/config/rx/t-linux b/gcc/config/rx/t-linux
new file mode 100644
index 0000000..0975b26
--- /dev/null
+++ b/gcc/config/rx/t-linux
@@ -0,0 +1,34 @@
+# Makefile fragment for building GCC for the rx-linux.
+# Copyright (C) 2019 Yoshinori Sato
+# Based on t-rx
+#
+# This file is part of GCC.
+#
+# GCC is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published
+# by the Free Software Foundation; either version 3, or (at your
+# option) any later version.
+#
+# GCC is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
+# the GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public
+# License along with GCC; see the file COPYING3. If not see
+# <http://www.gnu.org/licenses/>.
+
+# Enable multilibs:
+
+MULTILIB_OPTIONS =
+MULTILIB_DIRNAMES =
+
+MULTILIB_MATCHES = nofpu=mnofpu nofpu=mcpu?rx200 nofpu=mcpu?RX200
+
+MULTILIB_EXCEPTIONS =
+MULTILIB_EXTRA_OPTS =
+
+LIBGCC = stmp-multilib
+INSTALL_LIBGCC = install-multilib
+
+EXTRA_MULTILIB_PARTS = crtbegin.o crtend.o
diff --git a/gcc/config/s390/s390-builtins.def b/gcc/config/s390/s390-builtins.def
index fbf7d9f..cfc6965 100644
--- a/gcc/config/s390/s390-builtins.def
+++ b/gcc/config/s390/s390-builtins.def
@@ -2079,15 +2079,17 @@ OB_DEF_VAR (s390_vec_sld_dbl, s390_vsldb, 0,
B_DEF (s390_vsldb, vec_sldv16qi, 0, B_VX, O3_U4, BT_FN_UV16QI_UV16QI_UV16QI_INT)
OB_DEF (s390_vec_sldw, s390_vec_sldw_s8, s390_vec_sldw_dbl, B_VX, BT_FN_OV4SI_OV4SI_OV4SI_INT)
-OB_DEF_VAR (s390_vec_sldw_s8, s390_vsldb, 0, O3_U4, BT_OV_V16QI_V16QI_V16QI_INT)
-OB_DEF_VAR (s390_vec_sldw_u8, s390_vsldb, 0, O3_U4, BT_OV_UV16QI_UV16QI_UV16QI_INT)
-OB_DEF_VAR (s390_vec_sldw_s16, s390_vsldb, 0, O3_U4, BT_OV_V8HI_V8HI_V8HI_INT)
-OB_DEF_VAR (s390_vec_sldw_u16, s390_vsldb, 0, O3_U4, BT_OV_UV8HI_UV8HI_UV8HI_INT)
-OB_DEF_VAR (s390_vec_sldw_s32, s390_vsldb, 0, O3_U4, BT_OV_V4SI_V4SI_V4SI_INT)
-OB_DEF_VAR (s390_vec_sldw_u32, s390_vsldb, 0, O3_U4, BT_OV_UV4SI_UV4SI_UV4SI_INT)
-OB_DEF_VAR (s390_vec_sldw_s64, s390_vsldb, 0, O3_U4, BT_OV_V2DI_V2DI_V2DI_INT)
-OB_DEF_VAR (s390_vec_sldw_u64, s390_vsldb, 0, O3_U4, BT_OV_UV2DI_UV2DI_UV2DI_INT)
-OB_DEF_VAR (s390_vec_sldw_dbl, s390_vsldb, B_DEP, O3_U4, BT_OV_V2DF_V2DF_V2DF_INT)
+OB_DEF_VAR (s390_vec_sldw_s8, s390_vsldw, 0, O3_U4, BT_OV_V16QI_V16QI_V16QI_INT)
+OB_DEF_VAR (s390_vec_sldw_u8, s390_vsldw, 0, O3_U4, BT_OV_UV16QI_UV16QI_UV16QI_INT)
+OB_DEF_VAR (s390_vec_sldw_s16, s390_vsldw, 0, O3_U4, BT_OV_V8HI_V8HI_V8HI_INT)
+OB_DEF_VAR (s390_vec_sldw_u16, s390_vsldw, 0, O3_U4, BT_OV_UV8HI_UV8HI_UV8HI_INT)
+OB_DEF_VAR (s390_vec_sldw_s32, s390_vsldw, 0, O3_U4, BT_OV_V4SI_V4SI_V4SI_INT)
+OB_DEF_VAR (s390_vec_sldw_u32, s390_vsldw, 0, O3_U4, BT_OV_UV4SI_UV4SI_UV4SI_INT)
+OB_DEF_VAR (s390_vec_sldw_s64, s390_vsldw, 0, O3_U4, BT_OV_V2DI_V2DI_V2DI_INT)
+OB_DEF_VAR (s390_vec_sldw_u64, s390_vsldw, 0, O3_U4, BT_OV_UV2DI_UV2DI_UV2DI_INT)
+OB_DEF_VAR (s390_vec_sldw_dbl, s390_vsldw, B_DEP, O3_U4, BT_OV_V2DF_V2DF_V2DF_INT)
+
+B_DEF (s390_vsldw, vec_sldwv16qi, 0, B_VX, O3_U4, BT_FN_UV16QI_UV16QI_UV16QI_INT)
OB_DEF (s390_vec_sral, s390_vec_sral_u8q, s390_vec_sral_b64s, B_VX, BT_FN_OV4SI_OV4SI_OV4SI)
OB_DEF_VAR (s390_vec_sral_u8q, s390_vsra, 0, 0, BT_OV_UV16QI_UV16QI_UV16QI)
diff --git a/gcc/config/s390/s390-protos.h b/gcc/config/s390/s390-protos.h
index aa04479..b162b26 100644
--- a/gcc/config/s390/s390-protos.h
+++ b/gcc/config/s390/s390-protos.h
@@ -104,7 +104,7 @@ extern void s390_reload_symref_address (rtx , rtx , rtx , bool);
extern void s390_expand_plus_operand (rtx, rtx, rtx);
extern void emit_symbolic_move (rtx *);
extern void s390_load_address (rtx, rtx);
-extern bool s390_expand_movmem (rtx, rtx, rtx);
+extern bool s390_expand_cpymem (rtx, rtx, rtx);
extern void s390_expand_setmem (rtx, rtx, rtx);
extern bool s390_expand_cmpmem (rtx, rtx, rtx, rtx);
extern void s390_expand_vec_strlen (rtx, rtx, rtx);
diff --git a/gcc/config/s390/s390.c b/gcc/config/s390/s390.c
index fc4571d..5ec26a059 100644
--- a/gcc/config/s390/s390.c
+++ b/gcc/config/s390/s390.c
@@ -5394,7 +5394,7 @@ legitimize_reload_address (rtx ad, machine_mode mode ATTRIBUTE_UNUSED,
/* Emit code to move LEN bytes from DST to SRC. */
bool
-s390_expand_movmem (rtx dst, rtx src, rtx len)
+s390_expand_cpymem (rtx dst, rtx src, rtx len)
{
/* When tuning for z10 or higher we rely on the Glibc functions to
do the right thing. Only for constant lengths below 64k we will
@@ -5419,14 +5419,14 @@ s390_expand_movmem (rtx dst, rtx src, rtx len)
{
rtx newdst = adjust_address (dst, BLKmode, o);
rtx newsrc = adjust_address (src, BLKmode, o);
- emit_insn (gen_movmem_short (newdst, newsrc,
+ emit_insn (gen_cpymem_short (newdst, newsrc,
GEN_INT (l > 256 ? 255 : l - 1)));
}
}
else if (TARGET_MVCLE)
{
- emit_insn (gen_movmem_long (dst, src, convert_to_mode (Pmode, len, 1)));
+ emit_insn (gen_cpymem_long (dst, src, convert_to_mode (Pmode, len, 1)));
}
else
@@ -5488,7 +5488,7 @@ s390_expand_movmem (rtx dst, rtx src, rtx len)
emit_insn (prefetch);
}
- emit_insn (gen_movmem_short (dst, src, GEN_INT (255)));
+ emit_insn (gen_cpymem_short (dst, src, GEN_INT (255)));
s390_load_address (dst_addr,
gen_rtx_PLUS (Pmode, dst_addr, GEN_INT (256)));
s390_load_address (src_addr,
@@ -5505,7 +5505,7 @@ s390_expand_movmem (rtx dst, rtx src, rtx len)
emit_jump (loop_start_label);
emit_label (loop_end_label);
- emit_insn (gen_movmem_short (dst, src,
+ emit_insn (gen_cpymem_short (dst, src,
convert_to_mode (Pmode, count, 1)));
emit_label (end_label);
}
@@ -5557,7 +5557,7 @@ s390_expand_setmem (rtx dst, rtx len, rtx val)
if (l > 1)
{
rtx newdstp1 = adjust_address (dst, BLKmode, o + 1);
- emit_insn (gen_movmem_short (newdstp1, newdst,
+ emit_insn (gen_cpymem_short (newdstp1, newdst,
GEN_INT (l > 257 ? 255 : l - 2)));
}
}
@@ -5664,7 +5664,7 @@ s390_expand_setmem (rtx dst, rtx len, rtx val)
/* Set the first byte in the block to the value and use an
overlapping mvc for the block. */
emit_move_insn (adjust_address (dst, QImode, 0), val);
- emit_insn (gen_movmem_short (dstp1, dst, GEN_INT (254)));
+ emit_insn (gen_cpymem_short (dstp1, dst, GEN_INT (254)));
}
s390_load_address (dst_addr,
gen_rtx_PLUS (Pmode, dst_addr, GEN_INT (256)));
@@ -5688,7 +5688,7 @@ s390_expand_setmem (rtx dst, rtx len, rtx val)
emit_move_insn (adjust_address (dst, QImode, 0), val);
/* execute only uses the lowest 8 bits of count that's
exactly what we need here. */
- emit_insn (gen_movmem_short (dstp1, dst,
+ emit_insn (gen_cpymem_short (dstp1, dst,
convert_to_mode (Pmode, count, 1)));
}
@@ -6330,7 +6330,7 @@ s390_expand_insv (rtx dest, rtx op1, rtx op2, rtx src)
dest = adjust_address (dest, BLKmode, 0);
set_mem_size (dest, size);
- s390_expand_movmem (dest, src_mem, GEN_INT (size));
+ s390_expand_cpymem (dest, src_mem, GEN_INT (size));
return true;
}
@@ -12864,9 +12864,11 @@ s390_output_mi_thunk (FILE *file, tree thunk ATTRIBUTE_UNUSED,
HOST_WIDE_INT delta, HOST_WIDE_INT vcall_offset,
tree function)
{
+ const char *fnname = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (thunk));
rtx op[10];
int nonlocal = 0;
+ assemble_start_function (thunk, fnname);
/* Make sure unwind info is emitted for the thunk if needed. */
final_start_function (emit_barrier (), file, 1);
@@ -13120,6 +13122,7 @@ s390_output_mi_thunk (FILE *file, tree thunk ATTRIBUTE_UNUSED,
}
}
final_end_function ();
+ assemble_end_function (thunk, fnname);
}
/* Output either an indirect jump or a an indirect call
diff --git a/gcc/config/s390/s390.md b/gcc/config/s390/s390.md
index 714d8b0..d06aea9 100644
--- a/gcc/config/s390/s390.md
+++ b/gcc/config/s390/s390.md
@@ -3196,17 +3196,17 @@
;
-; movmemM instruction pattern(s).
+; cpymemM instruction pattern(s).
;
-(define_expand "movmem<mode>"
+(define_expand "cpymem<mode>"
[(set (match_operand:BLK 0 "memory_operand" "") ; destination
(match_operand:BLK 1 "memory_operand" "")) ; source
(use (match_operand:GPR 2 "general_operand" "")) ; count
(match_operand 3 "" "")]
""
{
- if (s390_expand_movmem (operands[0], operands[1], operands[2]))
+ if (s390_expand_cpymem (operands[0], operands[1], operands[2]))
DONE;
else
FAIL;
@@ -3215,7 +3215,7 @@
; Move a block that is up to 256 bytes in length.
; The block length is taken as (operands[2] % 256) + 1.
-(define_expand "movmem_short"
+(define_expand "cpymem_short"
[(parallel
[(set (match_operand:BLK 0 "memory_operand" "")
(match_operand:BLK 1 "memory_operand" ""))
@@ -3225,7 +3225,7 @@
""
"operands[3] = gen_rtx_SCRATCH (Pmode);")
-(define_insn "*movmem_short"
+(define_insn "*cpymem_short"
[(set (match_operand:BLK 0 "memory_operand" "=Q,Q,Q,Q")
(match_operand:BLK 1 "memory_operand" "Q,Q,Q,Q"))
(use (match_operand 2 "nonmemory_operand" "n,a,a,a"))
@@ -3293,7 +3293,7 @@
; Move a block of arbitrary length.
-(define_expand "movmem_long"
+(define_expand "cpymem_long"
[(parallel
[(clobber (match_dup 2))
(clobber (match_dup 3))
@@ -3327,7 +3327,7 @@
operands[3] = reg1;
})
-(define_insn "*movmem_long"
+(define_insn "*cpymem_long"
[(clobber (match_operand:<DBL> 0 "register_operand" "=d"))
(clobber (match_operand:<DBL> 1 "register_operand" "=d"))
(set (mem:BLK (subreg:P (match_operand:<DBL> 2 "register_operand" "0") 0))
@@ -3340,7 +3340,7 @@
[(set_attr "length" "8")
(set_attr "type" "vs")])
-(define_insn "*movmem_long_31z"
+(define_insn "*cpymem_long_31z"
[(clobber (match_operand:TI 0 "register_operand" "=d"))
(clobber (match_operand:TI 1 "register_operand" "=d"))
(set (mem:BLK (subreg:SI (match_operand:TI 2 "register_operand" "0") 4))
diff --git a/gcc/config/s390/vector.md b/gcc/config/s390/vector.md
index a2c1012..140ef47 100644
--- a/gcc/config/s390/vector.md
+++ b/gcc/config/s390/vector.md
@@ -981,7 +981,7 @@
(VEC_SHIFTS:VI (match_operand:VI 1 "register_operand" "v")
(match_operand:SI 2 "nonmemory_operand" "an")))]
"TARGET_VX"
- "<vec_shifts_mnem><bhfgq>\t%v0,%v1,%Y2"
+ "<vec_shifts_mnem><bhfgq>\t%v0,%v1,<addr_style_op_ops>"
[(set_attr "op_type" "VRS")])
; Shift each element by corresponding vector element
diff --git a/gcc/config/sh/sh.c b/gcc/config/sh/sh.c
index 8dc79a7..dfaeab5 100644
--- a/gcc/config/sh/sh.c
+++ b/gcc/config/sh/sh.c
@@ -8646,7 +8646,7 @@ sh2a_function_vector_p (tree func)
return false;
for (tree list = SH_ATTRIBUTES (func); list; list = TREE_CHAIN (list))
- if (is_attribute_p ("function_vector", TREE_PURPOSE (list)))
+ if (is_attribute_p ("function_vector", get_attribute_name (list)))
return true;
return false;
@@ -10796,6 +10796,7 @@ sh_output_mi_thunk (FILE *file, tree thunk_fndecl ATTRIBUTE_UNUSED,
HOST_WIDE_INT delta, HOST_WIDE_INT vcall_offset,
tree function)
{
+ const char *fnname = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (thunk_fndecl));
CUMULATIVE_ARGS cum;
int structure_value_byref = 0;
rtx this_rtx, this_value, sibcall, funexp;
@@ -10939,8 +10940,7 @@ sh_output_mi_thunk (FILE *file, tree thunk_fndecl ATTRIBUTE_UNUSED,
emit_barrier ();
/* Run just enough of rest_of_compilation to do scheduling and get
- the insns emitted. Note that use_thunk calls
- assemble_start_function and assemble_end_function. */
+ the insns emitted. */
insns = get_insns ();
@@ -10953,9 +10953,11 @@ sh_output_mi_thunk (FILE *file, tree thunk_fndecl ATTRIBUTE_UNUSED,
sh_reorg ();
shorten_branches (insns);
+ assemble_start_function (thunk_fndecl, fnname);
final_start_function (insns, file, 1);
final (insns, file, 1);
final_end_function ();
+ assemble_end_function (thunk_fndecl, fnname);
reload_completed = 0;
epilogue_completed = 0;
diff --git a/gcc/config/sh/sh.md b/gcc/config/sh/sh.md
index 8354377..ed70e34 100644
--- a/gcc/config/sh/sh.md
+++ b/gcc/config/sh/sh.md
@@ -8906,7 +8906,7 @@
;; String/block move insn.
-(define_expand "movmemsi"
+(define_expand "cpymemsi"
[(parallel [(set (mem:BLK (match_operand:BLK 0))
(mem:BLK (match_operand:BLK 1)))
(use (match_operand:SI 2 "nonmemory_operand"))
diff --git a/gcc/config/sol2.h b/gcc/config/sol2.h
index ed9e49b..f308be4 100644
--- a/gcc/config/sol2.h
+++ b/gcc/config/sol2.h
@@ -260,9 +260,9 @@ along with GCC; see the file COPYING3. If not see
/* Error out on -fsanitize=thread|leak. */
#define LIBTSAN_EARLY_SPEC "\
- %e:-fsanitize=thread is not supported in this configuration"
+ %e-fsanitize=thread is not supported in this configuration"
#define LIBLSAN_EARLY_SPEC "\
- %e:-fsanitize=leak is not supported in this configuration"
+ %e-fsanitize=leak is not supported in this configuration"
/* We don't use the standard svr4 STARTFILE_SPEC because it's wrong for us. */
#undef STARTFILE_SPEC
diff --git a/gcc/config/sparc/driver-sparc.c b/gcc/config/sparc/driver-sparc.c
index 510528e..77172c2 100644
--- a/gcc/config/sparc/driver-sparc.c
+++ b/gcc/config/sparc/driver-sparc.c
@@ -134,19 +134,8 @@ host_detect_local_cpu (int argc, const char **argv)
&& ksp->ks_type == KSTAT_TYPE_NAMED)
brand = (kstat_named_t *)
kstat_data_lookup (ksp, CONST_CAST2 (char *, const char *, "brand"));
- /* "brand" was only introduced in Solaris 10. */
- if (brand == NULL)
- brand = (kstat_named_t *)
- kstat_data_lookup (ksp, CONST_CAST2 (char *, const char *,
- "implementation"));
- /* KSTAT_DATA_STRING was introduced in Solaris 9. */
-#ifdef KSTAT_DATA_STRING
if (brand != NULL && brand->data_type == KSTAT_DATA_STRING)
buf = KSTAT_NAMED_STR_PTR (brand);
-#else
- if (brand != NULL && brand->data_type == KSTAT_DATA_CHAR)
- buf = brand->value.c;
-#endif
}
kstat_close (kc);
diff --git a/gcc/config/sparc/sparc.c b/gcc/config/sparc/sparc.c
index 93479ab..0227a53 100644
--- a/gcc/config/sparc/sparc.c
+++ b/gcc/config/sparc/sparc.c
@@ -679,7 +679,6 @@ static void sparc_output_dwarf_dtprel (FILE *, int, rtx) ATTRIBUTE_UNUSED;
static void sparc_file_end (void);
static bool sparc_frame_pointer_required (void);
static bool sparc_can_eliminate (const int, const int);
-static rtx sparc_builtin_setjmp_frame_value (void);
static void sparc_conditional_register_usage (void);
static bool sparc_use_pseudo_pic_reg (void);
static void sparc_init_pic_reg (void);
@@ -878,9 +877,6 @@ char sparc_hard_reg_printed[8];
#undef TARGET_FRAME_POINTER_REQUIRED
#define TARGET_FRAME_POINTER_REQUIRED sparc_frame_pointer_required
-#undef TARGET_BUILTIN_SETJMP_FRAME_VALUE
-#define TARGET_BUILTIN_SETJMP_FRAME_VALUE sparc_builtin_setjmp_frame_value
-
#undef TARGET_CAN_ELIMINATE
#define TARGET_CAN_ELIMINATE sparc_can_eliminate
@@ -12277,6 +12273,7 @@ sparc_output_mi_thunk (FILE *file, tree thunk_fndecl ATTRIBUTE_UNUSED,
HOST_WIDE_INT delta, HOST_WIDE_INT vcall_offset,
tree function)
{
+ const char *fnname = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (thunk_fndecl));
rtx this_rtx, funexp;
rtx_insn *insn;
unsigned int int_arg_first;
@@ -12461,13 +12458,14 @@ sparc_output_mi_thunk (FILE *file, tree thunk_fndecl ATTRIBUTE_UNUSED,
/* Run just enough of rest_of_compilation to get the insns emitted.
There's not really enough bulk here to make other passes such as
- instruction scheduling worth while. Note that use_thunk calls
- assemble_start_function and assemble_end_function. */
+ instruction scheduling worth while. */
insn = get_insns ();
shorten_branches (insn);
+ assemble_start_function (thunk_fndecl, fnname);
final_start_function (insn, file, 1);
final (insn, file, 1);
final_end_function ();
+ assemble_end_function (thunk_fndecl, fnname);
reload_completed = 0;
epilogue_completed = 0;
@@ -13001,14 +12999,6 @@ sparc_can_eliminate (const int from ATTRIBUTE_UNUSED, const int to)
return to == HARD_FRAME_POINTER_REGNUM || !sparc_frame_pointer_required ();
}
-/* Return the hard frame pointer directly to bypass the stack bias. */
-
-static rtx
-sparc_builtin_setjmp_frame_value (void)
-{
- return hard_frame_pointer_rtx;
-}
-
/* If !TARGET_FPU, then make the fp registers and fp cc regs fixed so that
they won't be allocated. */
diff --git a/gcc/config/sparc/sparc.h b/gcc/config/sparc/sparc.h
index 015065f..2dd765b 100644
--- a/gcc/config/sparc/sparc.h
+++ b/gcc/config/sparc/sparc.h
@@ -1412,7 +1412,7 @@ do { \
#define MOVE_MAX 8
/* If a memory-to-memory move would take MOVE_RATIO or more simple
- move-instruction pairs, we will do a movmem or libcall instead. */
+ move-instruction pairs, we will do a cpymem or libcall instead. */
#define MOVE_RATIO(speed) ((speed) ? 8 : 3)
diff --git a/gcc/config/sparc/sparc.md b/gcc/config/sparc/sparc.md
index a1bf557..7af62d5 100644
--- a/gcc/config/sparc/sparc.md
+++ b/gcc/config/sparc/sparc.md
@@ -7381,7 +7381,7 @@ visl")
""
{
rtx i7 = gen_rtx_REG (Pmode, RETURN_ADDR_REGNUM);
- rtx r_label = copy_to_reg (operands[1]);
+ rtx r_label = operands[1];
rtx r_sp = adjust_address (operands[2], Pmode, 0);
rtx r_fp = operands[3];
rtx r_i7 = adjust_address (operands[2], Pmode, GET_MODE_SIZE (Pmode));
@@ -7394,9 +7394,18 @@ visl")
emit_clobber (gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (VOIDmode)));
emit_clobber (gen_rtx_MEM (BLKmode, hard_frame_pointer_rtx));
- /* Restore frame pointer for containing function. */
- emit_move_insn (hard_frame_pointer_rtx, r_fp);
+ r_label = copy_to_reg (r_label);
+
+ /* Restore the frame pointer and stack pointer. We must use a
+ temporary since the setjmp buffer may be a local. */
+ r_fp = copy_to_reg (r_fp);
emit_stack_restore (SAVE_NONLOCAL, r_sp);
+ r_i7 = copy_to_reg (r_i7);
+
+ /* Ensure the frame pointer move is not optimized. */
+ emit_insn (gen_blockage ());
+ emit_clobber (hard_frame_pointer_rtx);
+ emit_move_insn (hard_frame_pointer_rtx, r_fp);
emit_move_insn (i7, r_i7);
/* USE of hard_frame_pointer_rtx added for consistency;
@@ -7405,8 +7414,7 @@ visl")
emit_use (stack_pointer_rtx);
emit_use (i7);
- emit_jump_insn (gen_indirect_jump (r_label));
- emit_barrier ();
+ emit_indirect_jump (r_label);
DONE;
})
diff --git a/gcc/config/spu/spu.c b/gcc/config/spu/spu.c
index 8d7439e..613d301 100644
--- a/gcc/config/spu/spu.c
+++ b/gcc/config/spu/spu.c
@@ -7043,8 +7043,10 @@ spu_output_mi_thunk (FILE *file, tree thunk ATTRIBUTE_UNUSED,
HOST_WIDE_INT delta, HOST_WIDE_INT vcall_offset,
tree function)
{
+ const char *fnname = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (thunk));
rtx op[8];
+ assemble_start_function (thunk, fnname);
/* Make sure unwind info is emitted for the thunk if needed. */
final_start_function (emit_barrier (), file, 1);
@@ -7116,6 +7118,7 @@ spu_output_mi_thunk (FILE *file, tree thunk ATTRIBUTE_UNUSED,
output_asm_insn ("br\t%0", op);
final_end_function ();
+ assemble_end_function (thunk, fnname);
}
/* Canonicalize a comparison from one we don't have to one we do have. */
diff --git a/gcc/config/stormy16/stormy16.c b/gcc/config/stormy16/stormy16.c
index b1769ce..bd55110 100644
--- a/gcc/config/stormy16/stormy16.c
+++ b/gcc/config/stormy16/stormy16.c
@@ -1512,8 +1512,10 @@ xstormy16_asm_output_mi_thunk (FILE *file,
HOST_WIDE_INT vcall_offset ATTRIBUTE_UNUSED,
tree function)
{
+ const char *fnname = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (thunk_fndecl));
int regnum = FIRST_ARGUMENT_REGISTER;
+ assemble_start_function (thunk_fndecl, fnname);
/* There might be a hidden first argument for a returned structure. */
if (aggregate_value_p (TREE_TYPE (TREE_TYPE (function)), function))
regnum += 1;
@@ -1522,6 +1524,7 @@ xstormy16_asm_output_mi_thunk (FILE *file,
fputs ("\tjmpf ", file);
assemble_name (file, XSTR (XEXP (DECL_RTL (function), 0), 0));
putc ('\n', file);
+ assemble_end_function (thunk_fndecl, fnname);
}
/* The purpose of this function is to override the default behavior of
diff --git a/gcc/config/tilegx/tilegx.c b/gcc/config/tilegx/tilegx.c
index 82226da..6da9139 100644
--- a/gcc/config/tilegx/tilegx.c
+++ b/gcc/config/tilegx/tilegx.c
@@ -4920,6 +4920,7 @@ tilegx_output_mi_thunk (FILE *file, tree thunk_fndecl ATTRIBUTE_UNUSED,
HOST_WIDE_INT delta, HOST_WIDE_INT vcall_offset,
tree function)
{
+ const char *fnname = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (thunk_fndecl));
rtx this_rtx, funexp, addend;
rtx_insn *insn;
@@ -4992,17 +4993,18 @@ tilegx_output_mi_thunk (FILE *file, tree thunk_fndecl ATTRIBUTE_UNUSED,
/* Run just enough of rest_of_compilation to get the insns emitted.
There's not really enough bulk here to make other passes such as
- instruction scheduling worth while. Note that use_thunk calls
- assemble_start_function and assemble_end_function.
+ instruction scheduling worth while.
We don't currently bundle, but the instruciton sequence is all
serial except for the tail call, so we're only wasting one cycle.
*/
insn = get_insns ();
shorten_branches (insn);
+ assemble_start_function (thunk_fndecl, fnname);
final_start_function (insn, file, 1);
final (insn, file, 1);
final_end_function ();
+ assemble_end_function (thunk_fndecl, fnname);
/* Stop pretending to be a post-reload pass. */
reload_completed = 0;
diff --git a/gcc/config/tilepro/tilepro.c b/gcc/config/tilepro/tilepro.c
index c8d69d3..f86461f 100644
--- a/gcc/config/tilepro/tilepro.c
+++ b/gcc/config/tilepro/tilepro.c
@@ -4368,6 +4368,7 @@ tilepro_asm_output_mi_thunk (FILE *file, tree thunk_fndecl ATTRIBUTE_UNUSED,
HOST_WIDE_INT delta, HOST_WIDE_INT vcall_offset,
tree function)
{
+ const char *fnname = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (thunk_fndecl));
rtx this_rtx, funexp;
rtx_insn *insn;
@@ -4415,17 +4416,18 @@ tilepro_asm_output_mi_thunk (FILE *file, tree thunk_fndecl ATTRIBUTE_UNUSED,
/* Run just enough of rest_of_compilation to get the insns emitted.
There's not really enough bulk here to make other passes such as
- instruction scheduling worth while. Note that use_thunk calls
- assemble_start_function and assemble_end_function.
+ instruction scheduling worth while.
We don't currently bundle, but the instruciton sequence is all
serial except for the tail call, so we're only wasting one cycle.
*/
insn = get_insns ();
shorten_branches (insn);
+ assemble_start_function (thunk_fndecl, fnname);
final_start_function (insn, file, 1);
final (insn, file, 1);
final_end_function ();
+ assemble_end_function (thunk_fndecl, fnname);
/* Stop pretending to be a post-reload pass. */
reload_completed = 0;
diff --git a/gcc/config/vax/vax-protos.h b/gcc/config/vax/vax-protos.h
index a76cf02..a85cf36 100644
--- a/gcc/config/vax/vax-protos.h
+++ b/gcc/config/vax/vax-protos.h
@@ -31,7 +31,6 @@ extern void vax_expand_addsub_di_operands (rtx *, enum rtx_code);
extern const char * vax_output_int_move (rtx, rtx *, machine_mode);
extern const char * vax_output_int_add (rtx_insn *, rtx *, machine_mode);
extern const char * vax_output_int_subtract (rtx_insn *, rtx *, machine_mode);
-extern const char * vax_output_movmemsi (rtx, rtx *);
#endif /* RTX_CODE */
#ifdef REAL_VALUE_TYPE
diff --git a/gcc/config/vax/vax.c b/gcc/config/vax/vax.c
index fe21fae..9559ffb 100644
--- a/gcc/config/vax/vax.c
+++ b/gcc/config/vax/vax.c
@@ -59,7 +59,6 @@ static rtx vax_function_arg (cumulative_args_t, machine_mode,
static void vax_function_arg_advance (cumulative_args_t, machine_mode,
const_tree, bool);
static rtx vax_struct_value_rtx (tree, int);
-static rtx vax_builtin_setjmp_frame_value (void);
static void vax_asm_trampoline_template (FILE *);
static void vax_trampoline_init (rtx, tree, rtx);
static poly_int64 vax_return_pops_args (tree, tree, poly_int64);
@@ -99,9 +98,6 @@ static HOST_WIDE_INT vax_starting_frame_offset (void);
#undef TARGET_STRUCT_VALUE_RTX
#define TARGET_STRUCT_VALUE_RTX vax_struct_value_rtx
-#undef TARGET_BUILTIN_SETJMP_FRAME_VALUE
-#define TARGET_BUILTIN_SETJMP_FRAME_VALUE vax_builtin_setjmp_frame_value
-
#undef TARGET_LRA_P
#define TARGET_LRA_P hook_bool_void_false
@@ -1049,11 +1045,15 @@ vax_output_mi_thunk (FILE * file,
HOST_WIDE_INT vcall_offset ATTRIBUTE_UNUSED,
tree function)
{
+ const char *fnname = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (thunk));
+
+ assemble_start_function (thunk, fnname);
fprintf (file, "\t.word 0x0ffc\n\taddl2 $" HOST_WIDE_INT_PRINT_DEC, delta);
asm_fprintf (file, ",4(%Rap)\n");
fprintf (file, "\tjmp ");
assemble_name (file, XSTR (XEXP (DECL_RTL (function), 0), 0));
fprintf (file, "+2\n");
+ assemble_end_function (thunk, fnname);
}
static rtx
@@ -1063,12 +1063,6 @@ vax_struct_value_rtx (tree fntype ATTRIBUTE_UNUSED,
return gen_rtx_REG (Pmode, VAX_STRUCT_VALUE_REGNUM);
}
-static rtx
-vax_builtin_setjmp_frame_value (void)
-{
- return hard_frame_pointer_rtx;
-}
-
/* Worker function for NOTICE_UPDATE_CC. */
void
diff --git a/gcc/config/vax/vax.h b/gcc/config/vax/vax.h
index a6a8227..e7137dc 100644
--- a/gcc/config/vax/vax.h
+++ b/gcc/config/vax/vax.h
@@ -430,7 +430,7 @@ enum reg_class { NO_REGS, ALL_REGS, LIM_REG_CLASSES };
#define MOVE_MAX 8
/* If a memory-to-memory move would take MOVE_RATIO or more simple
- move-instruction pairs, we will do a movmem or libcall instead. */
+ move-instruction pairs, we will do a cpymem or libcall instead. */
#define MOVE_RATIO(speed) ((speed) ? 6 : 3)
#define CLEAR_RATIO(speed) ((speed) ? 6 : 2)
diff --git a/gcc/config/vax/vax.md b/gcc/config/vax/vax.md
index bfeae7f..298f339 100644
--- a/gcc/config/vax/vax.md
+++ b/gcc/config/vax/vax.md
@@ -206,8 +206,8 @@
}")
;; This is here to accept 4 arguments and pass the first 3 along
-;; to the movmemhi1 pattern that really does the work.
-(define_expand "movmemhi"
+;; to the cpymemhi1 pattern that really does the work.
+(define_expand "cpymemhi"
[(set (match_operand:BLK 0 "general_operand" "=g")
(match_operand:BLK 1 "general_operand" "g"))
(use (match_operand:HI 2 "general_operand" "g"))
@@ -215,7 +215,7 @@
""
"
{
- emit_insn (gen_movmemhi1 (operands[0], operands[1], operands[2]));
+ emit_insn (gen_cpymemhi1 (operands[0], operands[1], operands[2]));
DONE;
}")
@@ -224,7 +224,7 @@
;; that anything generated as this insn will be recognized as one
;; and that it won't successfully combine with anything.
-(define_insn "movmemhi1"
+(define_insn "cpymemhi1"
[(set (match_operand:BLK 0 "memory_operand" "=o")
(match_operand:BLK 1 "memory_operand" "o"))
(use (match_operand:HI 2 "general_operand" "g"))
diff --git a/gcc/config/visium/visium.h b/gcc/config/visium/visium.h
index 817e7dc..c9376b2 100644
--- a/gcc/config/visium/visium.h
+++ b/gcc/config/visium/visium.h
@@ -1138,8 +1138,8 @@ do \
always make code faster, but eventually incurs high cost in
increased code size.
- Since we have a movmemsi pattern, the default MOVE_RATIO is 2, which
- is too low given that movmemsi will invoke a libcall. */
+ Since we have a cpymemsi pattern, the default MOVE_RATIO is 2, which
+ is too low given that cpymemsi will invoke a libcall. */
#define MOVE_RATIO(speed) ((speed) ? 9 : 3)
/* `CLEAR_RATIO (SPEED)`
diff --git a/gcc/config/visium/visium.md b/gcc/config/visium/visium.md
index f535441..e146b89 100644
--- a/gcc/config/visium/visium.md
+++ b/gcc/config/visium/visium.md
@@ -3006,7 +3006,7 @@
;; Argument 2 is the length
;; Argument 3 is the alignment
-(define_expand "movmemsi"
+(define_expand "cpymemsi"
[(parallel [(set (match_operand:BLK 0 "memory_operand" "")
(match_operand:BLK 1 "memory_operand" ""))
(use (match_operand:SI 2 "general_operand" ""))
diff --git a/gcc/config/xtensa/xtensa.c b/gcc/config/xtensa/xtensa.c
index 19bd616..2b97fa2 100644
--- a/gcc/config/xtensa/xtensa.c
+++ b/gcc/config/xtensa/xtensa.c
@@ -2739,7 +2739,7 @@ xtensa_frame_pointer_required (void)
This seems wrong but maybe it's necessary for other architectures.
This function is derived from the i386 code. */
- if (cfun->machine->accesses_prev_frame)
+ if (cfun->machine->accesses_prev_frame || cfun->has_nonlocal_label)
return true;
return false;
@@ -2865,7 +2865,8 @@ xtensa_expand_prologue (void)
gen_rtx_SET (mem, reg));
}
}
- if (total_size > 1024)
+ if (total_size > 1024
+ || (!callee_save_size && total_size > 128))
{
rtx tmp_reg = gen_rtx_REG (Pmode, A9_REG);
emit_move_insn (tmp_reg, GEN_INT (total_size -
diff --git a/gcc/config/xtensa/xtensa.md b/gcc/config/xtensa/xtensa.md
index 362e5ff..d1448a0 100644
--- a/gcc/config/xtensa/xtensa.md
+++ b/gcc/config/xtensa/xtensa.md
@@ -1026,7 +1026,7 @@
;; Block moves
-(define_expand "movmemsi"
+(define_expand "cpymemsi"
[(parallel [(set (match_operand:BLK 0 "" "")
(match_operand:BLK 1 "" ""))
(use (match_operand:SI 2 "arith_operand" ""))
diff --git a/gcc/configure b/gcc/configure
index 947d263..8c9f774 100755
--- a/gcc/configure
+++ b/gcc/configure
@@ -782,6 +782,8 @@ manext
LIBICONV_DEP
LTLIBICONV
LIBICONV
+ZSTD_LIB
+ZSTD_INCLUDE
DL_LIB
LDEXP_LIB
EXTRA_GCC_LIBS
@@ -959,6 +961,9 @@ with_pkgversion
with_bugurl
enable_languages
with_multilib_list
+with_zstd
+with_zstd_include
+with_zstd_lib
enable_rpath
with_libiconv_prefix
enable_sjlj_exceptions
@@ -1783,6 +1788,12 @@ Optional Packages:
--with-pkgversion=PKG Use PKG in the version string in place of "GCC"
--with-bugurl=URL Direct users to URL to report a bug
--with-multilib-list select multilibs (AArch64, SH and x86-64 only)
+ --with-zstd=PATH specify prefix directory for installed zstd library.
+ Equivalent to --with-zstd-include=PATH/include plus
+ --with-zstd-lib=PATH/lib
+ --with-zstd-include=PATH
+ specify directory for installed zstd include files
+ --with-zstd-lib=PATH specify directory for the installed zstd library
--with-gnu-ld assume the C compiler uses GNU ld default=no
--with-libiconv-prefix[=DIR] search for libiconv in DIR/include and DIR/lib
--without-libiconv-prefix don't search for libiconv in includedir and libdir
@@ -6739,7 +6750,7 @@ ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
loose_warn=
save_CXXFLAGS="$CXXFLAGS"
-for real_option in -W -Wall -Wno-narrowing -Wwrite-strings -Wcast-qual $wf_opt; do
+for real_option in -W -Wall -Wno-narrowing -Wwrite-strings -Wcast-qual -Wno-error=format-diag $wf_opt; do
# Do the check with the no- prefix removed since gcc silently
# accepts any -Wno-* option on purpose
case $real_option in
@@ -6797,7 +6808,7 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu
c_loose_warn=
save_CFLAGS="$CFLAGS"
-for real_option in -Wstrict-prototypes -Wmissing-prototypes; do
+for real_option in -Wstrict-prototypes -Wmissing-prototypes -Wno-error=format-diag; do
# Do the check with the no- prefix removed since gcc silently
# accepts any -Wno-* option on purpose
case $real_option in
@@ -9838,6 +9849,154 @@ $as_echo "#define HAVE_INTTYPES_H 1" >>confdefs.h
fi
+# Look for the ZSTD package.
+ZSTD_INCLUDE=
+ZSTD_LIB=
+
+
+ZSTD_CPPFLAGS=
+ZSTD_LDFLAGS=
+
+# Check whether --with-zstd was given.
+if test "${with_zstd+set}" = set; then :
+ withval=$with_zstd;
+fi
+
+
+# Check whether --with-zstd-include was given.
+if test "${with_zstd_include+set}" = set; then :
+ withval=$with_zstd_include;
+fi
+
+
+# Check whether --with-zstd-lib was given.
+if test "${with_zstd_lib+set}" = set; then :
+ withval=$with_zstd_lib;
+fi
+
+case "x$with_zstd" in
+ x) ;;
+ xno)
+ ZSTD_INCLUDE=no
+ ZSTD_LIB=no
+ ;;
+ *) ZSTD_INCLUDE=$with_zstd/include
+ ZSTD_LIB=$with_zstd/lib
+ ;;
+esac
+if test "x$with_zstd_include" != x; then
+ ZSTD_INCLUDE=$with_zstd_include
+fi
+if test "x$with_zstd_lib" != x; then
+ ZSTD_LIB=$with_zstd_lib
+fi
+if test "x$ZSTD_INCLUDE" != x \
+ && test "x$ZSTD_INCLUDE" != xno; then
+ ZSTD_CPPFLAGS=-I$ZSTD_INCLUDE
+fi
+if test "x$ZSTD_LIB" != x \
+ && test "x$ZSTD_LIB" != xno; then
+ ZSTD_LDFLAGS=-L$ZSTD_LIB
+fi
+
+CXXFLAGS="$CXXFLAGS $ZSTD_CPPFLAGS"
+LDFLAGS="$LDFLAGS $ZSTD_LDFLAGS"
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for zstd.h" >&5
+$as_echo_n "checking for zstd.h... " >&6; }
+if ${gcc_cv_header_zstd_h+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <zstd.h>
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+ gcc_cv_header_zstd_h=yes
+else
+ gcc_cv_header_zstd_h=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_header_zstd_h" >&5
+$as_echo "$gcc_cv_header_zstd_h" >&6; }
+if test $gcc_cv_header_zstd_h = yes; then
+
+$as_echo "#define HAVE_ZSTD_H 1" >>confdefs.h
+
+fi
+
+# LTO can use zstd compression algorithm
+save_LIBS="$LIBS"
+LIBS=
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing ZSTD_compress" >&5
+$as_echo_n "checking for library containing ZSTD_compress... " >&6; }
+if ${ac_cv_search_ZSTD_compress+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_func_search_save_LIBS=$LIBS
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char ZSTD_compress ();
+int
+main ()
+{
+return ZSTD_compress ();
+ ;
+ return 0;
+}
+_ACEOF
+for ac_lib in '' zstd; do
+ if test -z "$ac_lib"; then
+ ac_res="none required"
+ else
+ ac_res=-l$ac_lib
+ LIBS="-l$ac_lib $ac_func_search_save_LIBS"
+ fi
+ if ac_fn_cxx_try_link "$LINENO"; then :
+ ac_cv_search_ZSTD_compress=$ac_res
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext
+ if ${ac_cv_search_ZSTD_compress+:} false; then :
+ break
+fi
+done
+if ${ac_cv_search_ZSTD_compress+:} false; then :
+
+else
+ ac_cv_search_ZSTD_compress=no
+fi
+rm conftest.$ac_ext
+LIBS=$ac_func_search_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_ZSTD_compress" >&5
+$as_echo "$ac_cv_search_ZSTD_compress" >&6; }
+ac_res=$ac_cv_search_ZSTD_compress
+if test "$ac_res" != no; then :
+ test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
+
+fi
+
+ZSTD_LIB="$LIBS"
+LIBS="$save_LIBS"
+
+
for ac_func in times clock kill getrlimit setrlimit atoq \
@@ -12197,7 +12356,7 @@ if test "${enable_frame_pointer+set}" = set; then :
else
case $target_os in
-linux* | gnu* | darwin[8912]*)
+linux* | gnu* | darwin[8912]* | cygwin* | mingw*)
# Enable -fomit-frame-pointer by default for these systems with DWARF2.
enable_frame_pointer=no
;;
@@ -18655,7 +18814,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF
-#line 18658 "configure"
+#line 18817 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@@ -18761,7 +18920,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF
-#line 18764 "configure"
+#line 18923 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@@ -23069,17 +23228,13 @@ if test $in_tree_ld != yes ; then
#
# ld: Software Generation Utilities - Solaris Link Editors: 5.11-1.1701:onnv-ab196087-6931056-03/25/10
#
- # In Solaris 11.4, this was changed to
- #
- # ld: Solaris ELF Utilities: 11.4-1.3123
- #
# ld and ld.so.1 are guaranteed to be updated in lockstep, so ld version
# numbers can be used in ld.so.1 feature checks even if a different
# linker is configured.
ld_ver=`$gcc_cv_ld -V 2>&1`
- if echo "$ld_ver" | $EGREP 'Solaris Link Editors|Solaris ELF Utilities' > /dev/null; then
+ if echo "$ld_ver" | grep 'Solaris Link Editors' > /dev/null; then
ld_vers=`echo $ld_ver | sed -n \
- -e 's,^.*: \(5\|1[0-9]\)\.[0-9][0-9]*-\([0-9]\.[0-9][0-9]*\).*$,\2,p'`
+ -e 's,^.*: 5\.[0-9][0-9]*-\([0-9]\.[0-9][0-9]*\).*$,\1,p'`
ld_vers_major=`expr "$ld_vers" : '\([0-9]*\)'`
ld_vers_minor=`expr "$ld_vers" : '[0-9]*\.\([0-9]*\)'`
fi
@@ -23140,7 +23295,7 @@ else
hppa64*-*-hpux* | ia64*-*-hpux*)
gcc_cv_ld_hidden=yes
;;
- *-*-solaris2.1[0-9]*)
+ *-*-solaris2*)
# Support for .hidden in Sun ld appeared in Solaris 9 FCS, but
# .symbolic was only added in Solaris 9 12/02.
gcc_cv_ld_hidden=yes
@@ -23931,14 +24086,6 @@ $as_echo "$gcc_cv_as_shf_merge" >&6; }
fi
-case "$target" in
- i?86-*-solaris2.10* | x86_64-*-solaris2.10*)
- # SHF_MERGE support in Solaris 10/x86 ld is broken.
- if test x"$gnu_ld" = xno; then
- gcc_cv_as_shf_merge=no
- fi
- ;;
-esac
cat >>confdefs.h <<_ACEOF
#define HAVE_GAS_SHF_MERGE `if test $gcc_cv_as_shf_merge = yes; then echo 1; else echo 0; fi`
@@ -23947,13 +24094,6 @@ _ACEOF
gcc_cv_ld_aligned_shf_merge=yes
case "$target" in
- # While Solaris 10/SPARC ld isn't affected, disable to avoid problems
- # relinking on Solaris 11 < 11.4.
- sparc*-*-solaris2.10*)
- if test x"$gnu_ld" = xno; then
- gcc_cv_ld_aligned_shf_merge=no
- fi
- ;;
# SHF_MERGE support is broken in Solaris ld up to Solaris 11.3/SPARC for
# alignment > 1.
sparc*-*-solaris2.11*)
@@ -24084,7 +24224,7 @@ $as_echo "$gcc_cv_as_comdat_group_percent" >&6; }
foo:
'
;;
- i?86-*-solaris2* | x86_64-*-solaris2.1[0-9]*)
+ i?86-*-solaris2* | x86_64-*-solaris2*)
conftest_s='
.group foo,.text%foo,#comdat
.section .text%foo, "ax", @progbits
@@ -24394,7 +24534,7 @@ foo: .long 25
;;
i[34567]86-*-* | x86_64-*-*)
case "$target" in
- i[34567]86-*-solaris2.* | x86_64-*-solaris2.1[0-9]*)
+ i[34567]86-*-solaris2.* | x86_64-*-solaris2.*)
on_solaris=yes
;;
*)
@@ -29447,11 +29587,7 @@ fi
$as_echo_n "checking dl_iterate_phdr in target C library... " >&6; }
gcc_cv_target_dl_iterate_phdr=unknown
case "$target" in
- # Restrict to Solaris 11+. While most of the Solaris 11 linker changes
- # were backported to Solaris 10 Update 10, dl_iterate_phdr only lives in
- # libdl there, both complicating its use and breaking compatibility
- # between Solaris 10 updates.
- *-*-solaris2.1[1-9]*)
+ *-*-solaris2*)
# <link.h> needs both a dl_iterate_phdr declaration and support for
# compilation with largefile support.
if grep dl_iterate_phdr $target_header_dir/link.h > /dev/null 2>&1 \
diff --git a/gcc/configure.ac b/gcc/configure.ac
index bfcdf52..137d5b4 100644
--- a/gcc/configure.ac
+++ b/gcc/configure.ac
@@ -483,10 +483,11 @@ AS_IF([test $enable_build_format_warnings = no],
[wf_opt=-Wno-format],[wf_opt=])
ACX_PROG_CXX_WARNING_OPTS(
m4_quote(m4_do([-W -Wall -Wno-narrowing -Wwrite-strings ],
- [-Wcast-qual $wf_opt])), [loose_warn])
+ [-Wcast-qual -Wno-error=format-diag $wf_opt])),
+ [loose_warn])
ACX_PROG_CC_WARNING_OPTS(
- m4_quote(m4_do([-Wstrict-prototypes -Wmissing-prototypes])),
- [c_loose_warn])
+ m4_quote(m4_do([-Wstrict-prototypes -Wmissing-prototypes ],
+ [-Wno-error=format-diag])), [c_loose_warn])
ACX_PROG_CXX_WARNING_OPTS(
m4_quote(m4_do([-Wmissing-format-attribute ],
[-Woverloaded-virtual])), [strict_warn])
@@ -1257,6 +1258,72 @@ if test $gcc_cv_header_inttypes_h = yes; then
[Define if you have a working <inttypes.h> header file.])
fi
+# Look for the ZSTD package.
+ZSTD_INCLUDE=
+ZSTD_LIB=
+AC_SUBST(ZSTD_INCLUDE)
+AC_SUBST(ZSTD_LIB)
+ZSTD_CPPFLAGS=
+ZSTD_LDFLAGS=
+AC_ARG_WITH(zstd,
+ [AS_HELP_STRING([--with-zstd=PATH],
+ [specify prefix directory for installed zstd library.
+ Equivalent to --with-zstd-include=PATH/include
+ plus --with-zstd-lib=PATH/lib])])
+AC_ARG_WITH(zstd-include,
+ [AS_HELP_STRING([--with-zstd-include=PATH],
+ [specify directory for installed zstd include files])])
+AC_ARG_WITH(zstd-lib,
+ [AS_HELP_STRING([--with-zstd-lib=PATH],
+ [specify directory for the installed zstd library])])
+case "x$with_zstd" in
+ x) ;;
+ xno)
+ ZSTD_INCLUDE=no
+ ZSTD_LIB=no
+ ;;
+ *) ZSTD_INCLUDE=$with_zstd/include
+ ZSTD_LIB=$with_zstd/lib
+ ;;
+esac
+if test "x$with_zstd_include" != x; then
+ ZSTD_INCLUDE=$with_zstd_include
+fi
+if test "x$with_zstd_lib" != x; then
+ ZSTD_LIB=$with_zstd_lib
+fi
+if test "x$ZSTD_INCLUDE" != x \
+ && test "x$ZSTD_INCLUDE" != xno; then
+ ZSTD_CPPFLAGS=-I$ZSTD_INCLUDE
+fi
+if test "x$ZSTD_LIB" != x \
+ && test "x$ZSTD_LIB" != xno; then
+ ZSTD_LDFLAGS=-L$ZSTD_LIB
+fi
+
+CXXFLAGS="$CXXFLAGS $ZSTD_CPPFLAGS"
+LDFLAGS="$LDFLAGS $ZSTD_LDFLAGS"
+
+AC_MSG_CHECKING(for zstd.h)
+AC_CACHE_VAL(gcc_cv_header_zstd_h,
+[AC_COMPILE_IFELSE([AC_LANG_PROGRAM(
+[[#include <zstd.h>]])],
+ [gcc_cv_header_zstd_h=yes],
+ [gcc_cv_header_zstd_h=no])])
+AC_MSG_RESULT($gcc_cv_header_zstd_h)
+if test $gcc_cv_header_zstd_h = yes; then
+ AC_DEFINE(HAVE_ZSTD_H, 1,
+ [Define if you have a working <zstd.h> header file.])
+fi
+
+# LTO can use zstd compression algorithm
+save_LIBS="$LIBS"
+LIBS=
+AC_SEARCH_LIBS(ZSTD_compress, zstd)
+ZSTD_LIB="$LIBS"
+LIBS="$save_LIBS"
+AC_SUBST(ZSTD_LIB)
+
dnl Disabled until we have a complete test for buggy enum bitfields.
dnl gcc_AC_C_ENUM_BF_UNSIGNED
@@ -1884,7 +1951,7 @@ AC_ARG_ENABLE(frame-pointer,
[enable -fno-omit-frame-pointer by default for x86])], [],
[
case $target_os in
-linux* | gnu* | darwin[[8912]]*)
+linux* | gnu* | darwin[[8912]]* | cygwin* | mingw*)
# Enable -fomit-frame-pointer by default for these systems with DWARF2.
enable_frame_pointer=no
;;
@@ -2683,17 +2750,13 @@ if test $in_tree_ld != yes ; then
#
# ld: Software Generation Utilities - Solaris Link Editors: 5.11-1.1701:onnv-ab196087-6931056-03/25/10
#
- # In Solaris 11.4, this was changed to
- #
- # ld: Solaris ELF Utilities: 11.4-1.3123
- #
# ld and ld.so.1 are guaranteed to be updated in lockstep, so ld version
# numbers can be used in ld.so.1 feature checks even if a different
# linker is configured.
ld_ver=`$gcc_cv_ld -V 2>&1`
- if echo "$ld_ver" | $EGREP 'Solaris Link Editors|Solaris ELF Utilities' > /dev/null; then
+ if echo "$ld_ver" | grep 'Solaris Link Editors' > /dev/null; then
ld_vers=`echo $ld_ver | sed -n \
- -e 's,^.*: \(5\|1[0-9]\)\.[0-9][0-9]*-\([0-9]\.[0-9][0-9]*\).*$,\2,p'`
+ -e 's,^.*: 5\.[0-9][0-9]*-\([0-9]\.[0-9][0-9]*\).*$,\1,p'`
ld_vers_major=`expr "$ld_vers" : '\([0-9]*\)'`
ld_vers_minor=`expr "$ld_vers" : '[0-9]*\.\([0-9]*\)'`
fi
@@ -2751,7 +2814,7 @@ else
hppa64*-*-hpux* | ia64*-*-hpux*)
gcc_cv_ld_hidden=yes
;;
- *-*-solaris2.1[0-9]*)
+ *-*-solaris2*)
# Support for .hidden in Sun ld appeared in Solaris 9 FCS, but
# .symbolic was only added in Solaris 9 12/02.
gcc_cv_ld_hidden=yes
@@ -3075,27 +3138,12 @@ if test $gcc_cv_as_shf_merge = no; then
[elf,2,12,0], [--fatal-warnings],
[.section .rodata.str, "aMS", %progbits, 1])
fi
-case "$target" in
- i?86-*-solaris2.10* | x86_64-*-solaris2.10*)
- # SHF_MERGE support in Solaris 10/x86 ld is broken.
- if test x"$gnu_ld" = xno; then
- gcc_cv_as_shf_merge=no
- fi
- ;;
-esac
AC_DEFINE_UNQUOTED(HAVE_GAS_SHF_MERGE,
[`if test $gcc_cv_as_shf_merge = yes; then echo 1; else echo 0; fi`],
[Define 0/1 if your assembler supports marking sections with SHF_MERGE flag.])
gcc_cv_ld_aligned_shf_merge=yes
case "$target" in
- # While Solaris 10/SPARC ld isn't affected, disable to avoid problems
- # relinking on Solaris 11 < 11.4.
- sparc*-*-solaris2.10*)
- if test x"$gnu_ld" = xno; then
- gcc_cv_ld_aligned_shf_merge=no
- fi
- ;;
# SHF_MERGE support is broken in Solaris ld up to Solaris 11.3/SPARC for
# alignment > 1.
sparc*-*-solaris2.11*)
@@ -3141,7 +3189,7 @@ else
foo:
'
;;
- i?86-*-solaris2* | x86_64-*-solaris2.1[[0-9]]*)
+ i?86-*-solaris2* | x86_64-*-solaris2*)
conftest_s='
.group foo,.text%foo,#comdat
.section .text%foo, "ax", @progbits
@@ -3364,7 +3412,7 @@ foo: .long 25
;;
i[34567]86-*-* | x86_64-*-*)
case "$target" in
- i[34567]86-*-solaris2.* | x86_64-*-solaris2.1[0-9]*)
+ i[34567]86-*-solaris2.* | x86_64-*-solaris2.*)
on_solaris=yes
;;
*)
@@ -6097,11 +6145,7 @@ fi
AC_MSG_CHECKING(dl_iterate_phdr in target C library)
gcc_cv_target_dl_iterate_phdr=unknown
case "$target" in
- # Restrict to Solaris 11+. While most of the Solaris 11 linker changes
- # were backported to Solaris 10 Update 10, dl_iterate_phdr only lives in
- # libdl there, both complicating its use and breaking compatibility
- # between Solaris 10 updates.
- *-*-solaris2.1[[1-9]]*)
+ *-*-solaris2*)
# <link.h> needs both a dl_iterate_phdr declaration and support for
# compilation with largefile support.
if grep dl_iterate_phdr $target_header_dir/link.h > /dev/null 2>&1 \
diff --git a/gcc/convert.c b/gcc/convert.c
index 32d4755..a8f2bd0 100644
--- a/gcc/convert.c
+++ b/gcc/convert.c
@@ -235,7 +235,7 @@ convert_to_real_1 (tree type, tree expr, bool fold_p)
(T1) sqrtT4 ((T4) exprT3)
, where T1 is TYPE, T2 is ITYPE, T3 is TREE_TYPE (ARG0),
- and T4 is NEWTYPE. All those types are of floating point types.
+ and T4 is NEWTYPE. All those types are of floating-point types.
T4 (NEWTYPE) should be narrower than T2 (ITYPE). This conversion
is safe only if P1 >= P2*2+2, where P1 and P2 are precisions of
T2 and T4. See the following URL for a reference:
@@ -415,11 +415,11 @@ convert_to_real_1 (tree type, tree expr, bool fold_p)
case POINTER_TYPE:
case REFERENCE_TYPE:
- error ("pointer value used where a floating point value was expected");
+ error ("pointer value used where a floating-point was expected");
return convert_to_real_1 (type, integer_zero_node, fold_p);
default:
- error ("aggregate value used where a float was expected");
+ error ("aggregate value used where a floating-point was expected");
return convert_to_real_1 (type, integer_zero_node, fold_p);
}
}
@@ -1029,7 +1029,7 @@ convert_to_integer_1 (tree type, tree expr, bool dofold)
case VECTOR_TYPE:
if (!tree_int_cst_equal (TYPE_SIZE (type), TYPE_SIZE (TREE_TYPE (expr))))
{
- error ("can%'t convert a vector of type %qT"
+ error ("cannot convert a vector of type %qT"
" to type %qT which has different size",
TREE_TYPE (expr), type);
return error_mark_node;
@@ -1166,7 +1166,7 @@ convert_to_vector (tree type, tree expr)
case VECTOR_TYPE:
if (!tree_int_cst_equal (TYPE_SIZE (type), TYPE_SIZE (TREE_TYPE (expr))))
{
- error ("can%'t convert a value of type %qT"
+ error ("cannot convert a value of type %qT"
" to vector type %qT which has different size",
TREE_TYPE (expr), type);
return error_mark_node;
@@ -1174,7 +1174,7 @@ convert_to_vector (tree type, tree expr)
return build1 (VIEW_CONVERT_EXPR, type, expr);
default:
- error ("can%'t convert value to a vector");
+ error ("cannot convert value to a vector");
return error_mark_node;
}
}
diff --git a/gcc/coverage.c b/gcc/coverage.c
index 1ffefd5..960ff7e 100644
--- a/gcc/coverage.c
+++ b/gcc/coverage.c
@@ -1255,9 +1255,14 @@ coverage_init (const char *filename)
/* Name of bbg file. */
if (flag_test_coverage && !flag_compare_debug)
{
- bbg_file_name = XNEWVEC (char, len + strlen (GCOV_NOTE_SUFFIX) + 1);
- memcpy (bbg_file_name, filename, len);
- strcpy (bbg_file_name + len, GCOV_NOTE_SUFFIX);
+ if (profile_note_location)
+ bbg_file_name = xstrdup (profile_note_location);
+ else
+ {
+ bbg_file_name = XNEWVEC (char, len + strlen (GCOV_NOTE_SUFFIX) + 1);
+ memcpy (bbg_file_name, filename, len);
+ strcpy (bbg_file_name + len, GCOV_NOTE_SUFFIX);
+ }
if (!gcov_open (bbg_file_name, -1))
{
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 2544e48..7031d8d 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,830 @@
+2019-07-03 Martin Liska <mliska@suse.cz>
+
+ * call.c (build_new_op_1): Remove
+ dead assignemts.
+ * typeck.c (cp_build_binary_op): Likewise.
+
+2019-06-27 Jason Merrill <jason@redhat.com>
+
+ PR c++/55442 - memory-hog with highly recursive constexpr.
+ * constexpr.c (push_cx_call_context): Return depth.
+ (cxx_eval_call_expression): Don't cache past constexpr_cache_depth.
+
+2019-06-27 Jan Hubicka <jh@suse.cz>
+
+ * class.c (layout_class_type): Set TYPE_CXX_ODR_P for as-base
+ type copy.
+
+2019-06-27 Martin Liska <mliska@suse.cz>
+
+ * class.c (adjust_clone_args): Remove obviously
+ dead assignments.
+ (dump_class_hierarchy_r): Likewise.
+ * decl.c (check_initializer): Likewise.
+ * parser.c (cp_parser_lambda_expression): Likewise.
+ * pt.c (unify_bound_ttp_args): Likewise.
+ (convert_template_argument): Likewise.
+ * rtti.c (build_headof): Likewise.
+ * typeck.c (convert_for_initialization): Likewise.
+
+2019-06-25 Jason Merrill <jason@redhat.com>
+
+ PR c++/70462 - unnecessary base ctor variant with final.
+ * optimize.c (populate_clone_array): Skip base variant if
+ CLASSTYPE_FINAL.
+ (maybe_clone_body): We don't need an alias if we are only defining
+ one clone.
+
+ * class.c (resolves_to_fixed_type_p): Check CLASSTYPE_FINAL.
+
+2019-06-25 Jakub Jelinek <jakub@redhat.com>
+
+ PR c++/90969
+ * constexpr.c (cxx_eval_array_reference): Don't look through VCE from
+ vector type if lval.
+
+2019-06-24 Jan Hubicka <jh@suse.cz>
+
+ * lex.c (cxx_make_type): Set TYPE_CXX_ODR_P.
+
+2019-06-24 Jason Merrill <jason@redhat.com>
+
+ * class.c (layout_class_type): Don't use a separate
+ CLASSTYPE_AS_BASE if it's the same size.
+
+2019-06-23 Marek Polacek <polacek@redhat.com>
+
+ * call.c (convert_default_arg): Use DEFERRED_PARSE instead of
+ DEFAULT_ARG.
+ * cp-objcp-common.c (cp_tree_size): Likewise. Use tree_deferred_parse
+ instead of tree_default_arg.
+ * cp-tree.def: Rename DEFAULT_ARG to DEFERRED_PARSE.
+ * cp-tree.h: Rename DEFARG_TOKENS to DEFPARSE_TOKENS. Rename
+ DEFARG_INSTANTIATIONS to DEFPARSE_INSTANTIATIONS. Rename
+ tree_default_arg to tree_deferred_parse.
+ (UNPARSED_NOEXCEPT_SPEC_P): Use DEFERRED_PARSE instead of DEFAULT_ARG.
+ (cp_tree_node_structure_enum): Rename TS_CP_DEFAULT_ARG to
+ TS_CP_DEFERRED_PARSE.
+ (lang_tree_node): Rename tree_default_arg to tree_deferred_parse.
+ Rename default_arg to deferred_parse. Use TS_CP_DEFERRED_PARSE instead
+ of TS_CP_DEFAULT_ARG.
+ (defarg_location): Remove declaration.
+ (defparse_location): Add declaration.
+ * decl.c (grokfndecl): Use DEFERRED_PARSE instead of DEFAULT_ARG.
+ Call defparse_location instead of defarg_location.
+ (check_default_argument): Use DEFERRED_PARSE instead of DEFAULT_ARG.
+ (cp_tree_node_structure): Likewise. Use TS_CP_DEFERRED_PARSE instead
+ of TS_CP_DEFAULT_ARG.
+ * decl2.c (grokfield): Use DEFERRED_PARSE instead of DEFAULT_ARG.
+ * error.c (dump_expr): Likewise.
+ (location_of): Likewise.
+ * init.c (get_nsdmi): Likewise.
+ * parser.c (cp_parser_save_noexcept): Likewise. Use DEFPARSE_TOKENS
+ instead of DEFARG_TOKENS.
+ (cp_parser_late_noexcept_specifier): Likewise.
+ (cp_parser_late_parse_one_default_arg): Use DEFPARSE_TOKENS instead
+ of DEFARG_TOKENS.
+ (cp_parser_late_parsing_default_args): Use DEFERRED_PARSE instead of
+ DEFAULT_ARG. Use DEFPARSE_INSTANTIATIONS instead of
+ DEFARG_INSTANTIATIONS.
+ (cp_parser_cache_defarg): Use DEFERRED_PARSE instead of DEFAULT_ARG.
+ Use DEFPARSE_TOKENS instead of DEFARG_TOKENS. Use
+ DEFPARSE_INSTANTIATIONS instead of DEFARG_INSTANTIATIONS.
+ (defparse_location): Renamed from defarg_location.
+ * pt.c (tsubst_default_argument): Use DEFERRED_PARSE instead of
+ DEFAULT_ARG.
+ (tsubst_arg_types): Likewise.
+ (dependent_type_p_r): Likewise.
+ * tree.c (cp_tree_equal): Likewise.
+ (cp_walk_subtrees): Likewise.
+ * typeck.c (convert_arguments): Likewise.
+
+2019-06-22 Marek Polacek <polacek@redhat.com>
+
+ PR c++/86476 - noexcept-specifier is a complete-class context.
+ PR c++/52869
+ * cp-tree.def (DEFAULT_ARG): Update commentary.
+ * cp-tree.h (UNPARSED_NOEXCEPT_SPEC_P): New macro.
+ (tree_default_arg): Use tree_base instead of tree_common.
+ (do_push_parm_decls, maybe_check_overriding_exception_spec): Declare.
+ * decl.c (do_push_parm_decls): New function, broken out of...
+ (store_parm_decls): ...here. Call it.
+ * except.c (nothrow_spec_p): Accept DEFAULT_ARG in the assert.
+ * parser.c (cp_parser_noexcept_specification_opt,
+ cp_parser_late_noexcept_specifier, noexcept_override_late_checks):
+ Forward-declare.
+ (unparsed_noexcepts): New macro.
+ (push_unparsed_function_queues): Update initializer.
+ (cp_parser_direct_declarator): Pass FRIEND_P to
+ cp_parser_exception_specification_opt.
+ (inject_parm_decls): New.
+ (pop_injected_parms): New.
+ (cp_parser_class_specifier_1): Implement delayed parsing of
+ noexcept-specifiers.
+ (cp_parser_save_noexcept): New.
+ (cp_parser_late_noexcept_specifier): New.
+ (noexcept_override_late_checks): New.
+ (cp_parser_noexcept_specification_opt): Add FRIEND_P parameter. Call
+ cp_parser_save_noexcept instead of the normal processing if needed.
+ (cp_parser_exception_specification_opt): Add FRIEND_P parameter and
+ pass it to cp_parser_noexcept_specification_opt.
+ (cp_parser_save_member_function_body): Fix comment.
+ (cp_parser_save_default_args): Maybe save the noexcept-specifier to
+ post process.
+ (cp_parser_transaction): Update call to
+ cp_parser_noexcept_specification_opt.
+ (cp_parser_transaction_expression): Likewise.
+ * parser.h (cp_unparsed_functions_entry): Add new field to carry
+ a noexcept-specifier.
+ * pt.c (dependent_type_p_r): Handle unparsed noexcept expression.
+ * search.c (maybe_check_overriding_exception_spec): New function, broken
+ out of...
+ (check_final_overrider): ...here. Call
+ maybe_check_overriding_exception_spec.
+ * tree.c (canonical_eh_spec): Handle UNPARSED_NOEXCEPT_SPEC_P.
+ (cp_tree_equal): Handle DEFAULT_ARG.
+
+ PR c++/90881 - bogus -Wunused-value in unevaluated context.
+ * cvt.c (convert_to_void): Don't emit unused warnings in
+ an unevaluated context.
+
+2019-06-22 Paolo Carlini <paolo.carlini@oracle.com>
+
+ * decl.c (grokdeclarator): Use id_loc, typespec_loc, and
+ locations[ds_storage_class] in a few additional places.
+
+2019-06-21 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/90909
+ Revert:
+ 2019-05-21 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/67184
+ PR c++/69445
+ * call.c (build_over_call): Devirtualize when the final overrider
+ comes from the base.
+
+2019-06-21 Marek Polacek <polacek@redhat.com>
+
+ PR c++/61490 - qualified-id in friend function definition.
+ * decl.c (grokdeclarator): Diagnose qualified-id in friend function
+ definition. Improve location for diagnostics of friend functions.
+
+ PR c++/60223 - ICE with T{} in non-deduced context.
+ * pt.c (unify): Allow COMPOUND_LITERAL_P in a non-deduced context.
+
+ PR c++/64235 - missing syntax error with invalid alignas.
+ * parser.c (cp_parser_std_attribute_spec): Commit to tentative parse
+ if there's a missing close paren.
+
+ PR c++/90490 - fix decltype issues in noexcept-specifier.
+ * except.c (build_noexcept_spec): Call
+ instantiate_non_dependent_expr_sfinae before
+ build_converted_constant_expr instead of calling
+ instantiate_non_dependent_expr after it. Add
+ processing_template_decl_sentinel.
+
+2019-06-21 Jakub Jelinek <jakub@redhat.com>
+
+ PR c++/90950
+ * semantics.c (finish_omp_clauses): Don't reject references to
+ incomplete types if processing_template_decl.
+
+2019-06-19 Marek Polacek <polacek@redhat.com>
+
+ PR c++/60364 - noreturn after first decl not diagnosed.
+ * decl.c (duplicate_decls): Give an error when a function is
+ declared [[noreturn]] after its first declaration.
+ * parser.c (cp_parser_std_attribute): Don't treat C++11 noreturn
+ attribute as equivalent to GNU's.
+ * tree.c (std_attribute_table): Add noreturn.
+
+2019-06-19 Jakub Jelinek <jakub@redhat.com>
+
+ * cp-gimplify.c (cp_genericize_r): Handle OMP_CLAUSE_{IN,EX}CLUSIVE
+ like OMP_CLAUSE_SHARED.
+
+2019-06-18 Jason Merrill <jason@redhat.com>
+
+ * constexpr.c (cxx_eval_store_expression): Delay target evaluation.
+
+2019-06-18 Jason Merrill <jason@redhat.com>
+
+ * constexpr.c (eval_and_check_array_index): Split out from...
+ (cxx_eval_array_reference): ...here.
+ (cxx_eval_store_expression): Use it here, too.
+ (diag_array_subscript): Take location. Strip location wrapper.
+
+2019-06-18 Jason Merrill <jason@redhat.com>
+
+ * constexpr.c (cxx_eval_constant_expression): Handle conversion from
+ and then to the same type.
+
+2019-06-18 Jason Merrill <jason@redhat.com>
+
+ * constexpr.c (unshare_constructor): Add MEM_STAT_DECL.
+
+2019-06-17 Jakub Jelinek <jakub@redhat.com>
+
+ * semantics.c (finish_omp_clauses): For OMP_CLAUSE_REDUCTION_INSCAN
+ set need_copy_assignment.
+
+2019-06-17 Marek Polacek <polacek@redhat.com>
+
+ PR c++/83820 - excessive attribute arguments not detected.
+ * parser.c (cp_parser_std_attribute): Detect excessive arguments.
+
+2019-06-17 Nathan Sidwell <nathan@acm.org>
+
+ PR c++/90754
+ * name-lookup.c (lookup_type_scope_1): Calll qualify_lookup before
+ checking context.
+
+2019-06-14 Marek Polacek <polacek@redhat.com>
+
+ PR c++/90884 - stray note with -Wctor-dtor-privacy.
+ * class.c (maybe_warn_about_overly_private_class): Guard the call to
+ inform.
+
+2019-06-12 Jason Merrill <jason@redhat.com>
+
+ PR c++/85552 - wrong instantiation of dtor for DMI.
+ * typeck2.c (digest_nsdmi_init): Set tf_no_cleanup for direct-init.
+
+2019-06-13 Paolo Carlini <paolo.carlini@oracle.com>
+
+ * decl.c (grokdeclarator): Use id_loc in five additional places
+ in the last part of the function.
+
+2019-06-13 Paolo Carlini <paolo.carlini@oracle.com>
+
+ * decl.c (grokdeclarator): Move further up the declaration of
+ id_loc, use it immediately, update its value after the loop
+ over declarator, use it again in the final part of function;
+ improve locations of error messages about multiple data types
+ and conflicting specifiers.
+
+2019-06-13 Richard Biener <rguenther@suse.de>
+
+ PR c++/90801
+ * typeck2.c (split_nonconstant_init_1): Properly count
+ num_split_elts, optimize single constructor elt removal.
+
+2019-06-12 Marek Polacek <polacek@redhat.com>
+
+ PR c++/66999 - 'this' captured by reference.
+ * parser.c (cp_parser_lambda_introducer): Reject `&this'. Use
+ cp_lexer_nth_token_is instead of cp_lexer_peek_nth_token.
+
+ PR c++/90825 - endless recursion when evaluating sizeof.
+ PR c++/90832 - endless recursion when evaluating sizeof.
+ * constexpr.c (cxx_eval_constant_expression): Don't recurse on the
+ result of fold_sizeof_expr if is returns a SIZEOF_EXPR.
+ * typeck.c (cxx_sizeof_expr): Only return a SIZEOF_EXPR if the operand
+ is instantiation-dependent.
+
+ PR c++/90736 - bogus error with alignof.
+ * constexpr.c (adjust_temp_type): Use cv_unqualified type.
+
+2019-06-11 Matthew Beliveau <mbelivea@redhat.com>
+
+ PR c++/90449 - add -Winaccessible-base option.
+ * class.c (warn_about_ambiguous_bases): Changed name to:
+ maybe_warn_about_inaccessible_bases.
+ (maybe_warn_about_inaccessible_bases): Implemented new
+ Winaccessible-base warning option for both direct and virtual
+ base warnings.
+ (layout_class_type): Call to warn_about_ambiguous_bases changed to fit
+ new name.
+
+2019-06-11 Richard Biener <rguenther@suse.de>
+
+ PR c++/90801
+ * typeck2.c (split_nonconstant_init_1): Avoid ordered remove
+ from CONSTRUCTOR by marking to remove elements and doing all
+ of them in a O(n) scan.
+
+2019-06-11 Jakub Jelinek <jakub@redhat.com>
+
+ PR c++/90810
+ * init.c (constant_value_1): Handle VECTOR_CST DECL_INITIAL for
+ !DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P decls like CONSTRUCTOR.
+
+2019-06-11 Martin Liska <mliska@suse.cz>
+
+ PR c++/87847
+ * pt.c (init_template_processing): Disable hash table
+ sanitization for decl_specializations and type_specializations.
+
+2019-06-10 Jason Merrill <jason@redhat.com>
+
+ * constexpr.c (free_constructor): New.
+ (cxx_eval_call_expression): Free parameter value CONSTRUCTORs.
+
+ * constexpr.c (unshare_constructor): Only unshare if T is itself a
+ CONSTRUCTOR.
+ (cxx_eval_call_expression): Don't call it on the result here.
+
+ Reduce constexpr_call memory consumption.
+ * constexpr.c (cxx_bind_parameters_in_call): Use TREE_VEC rather
+ than TREE_LIST.
+ (constexpr_call_hasher::equal, cxx_bind_parameters_in_call)
+ (cxx_eval_call_expression): Adjust.
+
+2019-06-10 Jakub Jelinek <jakub@redhat.com>
+
+ * parser.c (cp_parser_omp_clause_reduction): Don't sorry_at on inscan
+ reductions.
+ (cp_parser_omp_scan_loop_body): New function.
+ (cp_parser_omp_for_loop): Call cp_parser_omp_scan_loop_body if there
+ are inscan reduction clauses.
+ (cp_parser_pragma): Reject PRAGMA_OMP_SCAN.
+ * semantics.c (finish_omp_clauses): Reject mixing inscan with
+ non-inscan reductions on the same construct, or inscan reductions with
+ ordered or schedule clauses, or inscan array reductions.
+ * pt.c (tsubst_omp_clauses): Handle OMP_CLAUSE_{IN,EX}CLUSIVE.
+ (tsubst_expr): Handle OMP_SCAN.
+
+2019-06-07 Jason Merrill <jason@redhat.com>
+
+ * constexpr.c (cxx_eval_constant_expression): Call
+ STRIP_ANY_LOCATION_WRAPPER early.
+ [CONVERT_EXPR]: Don't build anything for conversion to void.
+ [ADDR_EXPR]: ggc_free unused ADDR_EXPR.
+
+2019-06-05 Martin Sebor <msebor@redhat.com>
+
+ PR c/90737
+ * typeck.c (maybe_warn_about_returning_address_of_local): Only
+ consider functions returning pointers as candidates for
+ -Wreturn-local-addr.
+
+2019-06-05 Paolo Carlini <paolo.carlini@oracle.com>
+
+ * decl.c (smallest_type_location): New.
+ (check_special_function_return_type): Use it.
+ (grokdeclarator): Lkewise.
+
+2019-06-05 Paolo Carlini <paolo.carlini@oracle.com>
+
+ * decl.c (grokdeclarator): Use locations[ds_friend]
+ in one place.
+
+2019-06-05 Martin Sebor <msebor@redhat.com>
+
+ * call.c (build_conditional_expr_1): Adjust quoting and hyphenation.
+ (convert_like_real): Same.
+ (convert_arg_to_ellipsis): Same.
+ * constexpr.c (diag_array_subscript): Same.
+ * constraint.cc (diagnose_trait_expression): Same.
+ * cvt.c (ocp_convert): Same.
+ * decl.c (start_decl): Same.
+ (check_for_uninitialized_const_var): Same.
+ (grokfndecl): Same.
+ (check_special_function_return_type): Same.
+ (finish_enum_value_list): Same.
+ (start_preparsed_function): Same.
+ * parser.c (cp_parser_decl_specifier_seq): Same.
+ * typeck.c (cp_build_binary_op): Same.
+ (build_static_cast_1): Same.
+
+2019-06-04 Nina Dinka Ranns <dinka.ranns@gmail.com>
+
+ PR c++/63149 - Wrong auto deduction from braced-init-list.
+ * pt.c (listify_autos): use non cv qualified auto_node in
+ std::initializer_list<auto>.
+
+2019-06-04 Paolo Carlini <paolo.carlini@oracle.com>
+
+ * decl.c (grokdeclarator): Use declarator->id_loc in two
+ additional places.
+
+2019-06-04 Nathan Sidwell <nathan@acm.org>
+
+ * name-lookup.c (lookup_type_scope_1): Reimplement, handle local
+ and namespace scopes separately.
+
+2019-06-04 Harald van Dijk <harald@gigawatt.nl>
+
+ PR c++/60531 - Wrong error about unresolved overloaded function
+ * typeck.c (cp_build_binary_op): See if overload can be resolved.
+ (cp_build_unary_op): Ditto.
+
+2019-06-04 Jason Merrill <jason@redhat.com>
+
+ Reduce accumulated garbage in constexpr evaluation.
+ * constexpr.c (cxx_eval_call_expression): ggc_free any bindings we
+ don't save.
+ (cxx_eval_increment_expression): ggc_free the MODIFY_EXPR after
+ evaluating it.
+
+2019-06-04 Jakub Jelinek <jakub@redhat.com>
+
+ * cp-tree.h (CP_OMP_CLAUSE_INFO): Allow for any clauses up to _condvar_
+ instead of only up to linear.
+
+2019-06-03 Paolo Carlini <paolo.carlini@oracle.com>
+
+ * parser.c (cp_parser_unqualified_id): Use build_min_nt_loc in
+ five places.
+
+2019-06-01 Ville Voutilainen <ville.voutilainen@gmail.com>
+
+ PR c++/85254
+ * class.c (fixup_type_variants): Handle CLASSTYPE_FINAL.
+
+2019-05-31 Nathan Sidwell <nathan@acm.org>
+
+ * cp-tree.h (IDENTIFIER_LAMBDA_P): New.
+ (TYPE_ANON_P): New.
+ (LAMBDA_TYPE_P, TYPE_UNNAMED_P): Likewise.
+ (LAMBDANAME_PREFIX, LAMBDANAME_FORMAT): Delete.
+ (make_lambda_name): Don't declare.
+ * error.c (dump_aggr_type): Check for lambdas before other
+ anonymous names.
+ * lambda.c (begin_lambda_type): Use make_anon_name.
+ * cp-lang.c (cxx_dwarf_name): Lambda names smell anonymous.
+ * mangle.c (write_local_name): Likewise.
+ * name-lookup.c (lambda_cnt, make_lambda_name): Delete.
+
+2019-05-30 Marek Polacek <polacek@redhat.com>
+
+ * cp-tree.h (TYPE_HAS_NONTRIVIAL_DESTRUCTOR): Fix a typo.
+
+2019-05-31 Paolo Carlini <paolo.carlini@oracle.com>
+
+ * decl.c (grokdeclarator): Use declarator->id_loc in five
+ error_at calls.
+
+2019-05-29 Jakub Jelinek <jakub@redhat.com>
+
+ PR c++/90598
+ * tree.c (lvalue_kind): Return clk_none for expressions with
+ with VOID_TYPE_P.
+
+2019-05-29 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/89875
+ * parser.c (cp_parser_sizeof_operand): When the type-id production
+ did not work out commit to the tentative parse.
+
+2019-05-29 Jakub Jelinek <jakub@redhat.com>
+
+ P1091R3 - Extending structured bindings to be more like var decls
+ P1381R1 - Reference capture of structured bindings
+ * decl.c (cp_maybe_mangle_decomp): Handle TREE_STATIC decls even at
+ function scope.
+ (cp_finish_decomp): Copy over various decl properties from decl to
+ v[i] in the tuple case.
+ (grokdeclarator): Allow static, thread_local and __thread for C++2a
+ and use pedwarn instead of error for older standard revisions.
+ Make other structured binding diagnostic messages more i18n friendly.
+
+2019-05-28 Nathan Sidwell <nathan@acm.org>
+
+ * decl.c (duplicate_decls): Assert a template newdecl has no
+ specializations.
+
+2019-05-28 Marek Polacek <polacek@redhat.com>
+
+ PR c++/90548 - ICE with generic lambda and empty pack.
+ * pt.c (tsubst_copy_and_build): Handle pack expansion properly.
+
+2019-05-28 Nathan Sidwell <nathan@acm.org>
+
+ * cp-tree.h (make_anon_name): Drop declaration.
+ (TYPE_UNNAMED_P): Use IDENTIFIER_ANON_P.
+ * cp-lang.c (cxx_dwarf_name): Likewise.
+ * class.c (find_flexarrays): Likewise.
+ * decl.c (name_unnamed_type, xref_tag_1): Likewise.
+ * error.c (dump_aggr_type): Likewise.
+ * pt.c (push_template_decl_real): Likewise.
+ * name-lookup.c (consider_binding_level): Likewise.
+ (anon_cnt, make_anon_name): Delete.
+
+2019-05-25 Marek Polacek <polacek@redhat.com>
+
+ PR c++/90572 - wrong disambiguation in friend declaration.
+ * parser.c (cp_parser_constructor_declarator_p): Don't allow missing
+ typename for friend declarations.
+
+2019-05-23 Jonathan Wakely <jwakely@redhat.com>
+
+ * cp-tree.h (CP_AGGREGATE_TYPE_P): Fix whitespace.
+
+ * init.c (std_placement_new_fn_p): Remove outdated TODO comment that
+ was resolved by r254694.
+
+2019-05-22 Jason Merrill <jason@redhat.com>
+
+ PR c++/20408 - unnecessary code for empty struct.
+ * call.c (build_call_a): Use simple_empty_class_p.
+
+ PR c++/86485 - -Wmaybe-unused with empty class ?:
+ * cp-gimplify.c (simple_empty_class_p): Also true for MODIFY_EXPR.
+
+2019-05-21 Paolo Carlini <paolo.carlini@oracle.com>
+
+ * parser.c (cp_parser_template_declaration_after_parameters): Use
+ DECL_SOURCE_LOCATION in literal operator template errors.
+
+2019-05-21 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/67184
+ PR c++/69445
+ * call.c (build_over_call): Devirtualize when the final overrider
+ comes from the base.
+
+2019-05-21 Nathan Sidwell <nathan@acm.org>
+
+ * name-lookup.c (do_nonmember_using_decl): Drop INSERT_P
+ parameter. Document.
+ (finish_nonmember_using_decl): Adjust do_nonmember_using_decl
+ calls. Remove stray FIXME comment.
+
+ * name-lookup.h (struct cp_binding_level): Drop usings field.
+ (finish_namespace_using_decl, finish_local_using_decl): Replace with ...
+ (finish_nonmember_using_decl): ... this.
+ * name-lookup.c (push_using_decl_1, push_using_decl):
+ (do_nonmember_using_decl): ... here. Add INSERT_P arg. Reimplement.
+ (validate_nonmember_using_decl, finish_namespace_using_decl)
+ (finish_local_using_decl): Replace with ...
+ (finish_nonmember_using_decl): ... this. Drop DECL parm.
+ * parser.c (cp_parser_using_declaration): Don't do lookup here.
+ * pt.c (tsubst_expr): Do not do using decl lookup here.
+
+2019-05-21 Eric Botcazou <ebotcazou@adacore.com>
+
+ * decl2.c (cpp_check) <IS_ASSIGNMENT_OPERATOR>: New case.
+
+2019-05-20 Marek Polacek <polacek@redhat.com>
+
+ CWG 2094 - volatile scalars are trivially copyable.
+ PR c++/85679
+ * tree.c (trivially_copyable_p): Don't check CP_TYPE_VOLATILE_P for
+ scalar types.
+
+2019-05-20 Marek Polacek <polacek@redhat.com>
+
+ * pt.c (convert_template_argument): Add a diagnostic for the
+ [temp.arg]/2 ambiguity case.
+
+ * name-lookup.c (finish_using_directive): Don't issue inform() if the
+ warning didn't trigger. Add quoting. Tweak the inform message.
+
+2019-05-20 Paolo Carlini <paolo.carlini@oracle.com>
+
+ * cp-tree.h: Remove remnants of CONV_NONCONVERTING.
+
+2019-05-20 Nathan Sidwell <nathan@acm.org>
+
+ * name-lookup.c (finish_namespace_using_directive)
+ (finish_local_using_directive): Merge to ...
+ (finish_using_directive): ... here. Handle both contexts.
+ * name-lookup.h (finish_namespace_using_directive)
+ (finish_local_using_directive): Replace with ...
+ (finish_using_directive): ... this.
+ * parser.c (cp_parser_using_directive): Adjust.
+ * pt.c (tsubst_expr): Likewise.
+
+ * cp-tree.h (struct lang_decl_ns): Remove usings field.
+ (DECL_NAMESPACE_USING): Delete.
+ * name-lookup.c (name_lookup::search_usings): Use namespace's
+ binding scope.
+ (name_lookup::queue_namespae): Likewise.
+ (finish_namespace_using_directive, push_namespace): Likewise.
+ (has_using_namespace_std_directive): Just search the entire
+ binding stack.
+
+2019-05-20 Jonathan Wakely <jwakely@redhat.com>
+
+ PR c++/90532 Ensure __is_constructible(T[]) is false
+ * method.c (is_xible_helper): Return error_mark_node for construction
+ of an array of unknown bound.
+
+2019-05-17 Thomas Schwinge <thomas@codesourcery.com>
+
+ PR c++/89433
+ * parser.c (cp_finalize_oacc_routine): Rework checking if already
+ marked with an OpenACC 'routine' directive.
+
+ PR c++/89433
+ * parser.c (cp_parser_oacc_routine)
+ (cp_parser_late_parsing_oacc_routine): Normalize order of clauses.
+ (cp_finalize_oacc_routine): Call oacc_verify_routine_clauses.
+
+ PR c++/89433
+ * parser.c (cp_finalize_oacc_routine): Refer to OpenACC 'routine'
+ clauses from "omp declare target" attribute.
+
+2019-05-16 Martin Sebor <msebor@redhat.com>
+
+ * call.c (print_z_candidate): Wrap diagnostic text in a gettext
+ macro. Adjust.
+ (print_z_candidates): Same.
+ (build_conditional_expr_1): Quote keywords, operators, and types
+ in diagnostics.
+ (build_op_delete_call): Same.
+ (maybe_print_user_conv_context): Wrap diagnostic text in a gettext
+ macro.
+ (convert_like_real): Same.
+ (convert_arg_to_ellipsis): Quote keywords, operators, and types
+ in diagnostics.
+ (build_over_call): Same.
+ (joust): Break up an overlong line. Wrap diagnostic text in a gettext
+ macro.
+ * constexpr.c (cxx_eval_check_shift_p): Spell out >= in English.
+ (cxx_eval_constant_expression): Quote keywords, operators, and types
+ in diagnostics.
+ (potential_constant_expression_1): Same.
+ * cp-gimplify.c (cp_genericize_r): Same.
+ * cvt.c (maybe_warn_nodiscard): Quote keywords, operators, and types
+ in diagnostics.
+ (type_promotes_to): Same.
+ * decl.c (check_previous_goto_1): Same.
+ (check_goto): Same.
+ (start_decl): Same.
+ (cp_finish_decl): Avoid parenthesizing a sentence for consistency.
+ (grok_op_properties): Quote keywords, operators, and types
+ in diagnostics.
+ * decl2.c (grokfield): Same.
+ (coerce_delete_type): Same.
+ * except.c (is_admissible_throw_operand_or_catch_parameter): Same.
+ * friend.c (do_friend): Quote C++ tokens.
+ * init.c (build_new_1): Quote keywords, operators, and types
+ in diagnostics.
+ (build_vec_delete_1): Same.
+ (build_delete): Same.
+ * lex.c (parse_strconst_pragma): Same.
+ (handle_pragma_implementation): Same.
+ (unqualified_fn_lookup_error): Same.
+ * mangle.c (write_type): Same.
+ * method.c (defaulted_late_check): Avoid two consecutive punctuators.
+ * name-lookup.c (cp_binding_level_debug): Remove a trailing newline.
+ (pop_everything): Same.
+ * parser.c (cp_lexer_start_debugging): Quote a macro name.
+ in a diagnostic
+ (cp_lexer_stop_debugging): Same.
+ (cp_parser_userdef_numeric_literal): Quote a C++ header name
+ in a diagnostic.
+ (cp_parser_nested_name_specifier_opt): Quote keywords, operators,
+ and types in diagnostics.
+ (cp_parser_question_colon_clause): Same.
+ (cp_parser_asm_definition): Same.
+ (cp_parser_init_declarator): Same.
+ (cp_parser_template_declaration_after_parameters): Avoid capitalizing
+ a sentence in a diagnostic.
+ (cp_parser_omp_declare_reduction): Quote keywords, operators, and types
+ in diagnostics.
+ (cp_parser_transaction): Same.
+ * pt.c (maybe_process_partial_specialization): Replace second call
+ to permerror with inform for consistency with other uses.
+ (expand_integer_pack): Quote keywords, operators, and types
+ in diagnostics.
+ * rtti.c (get_typeid): Quote keywords, operators, and types
+ in diagnostics.
+ (build_dynamic_cast_1): Same.
+ * semantics.c (finish_asm_stmt): Same.
+ (finish_label_decl): Same.
+ (finish_bases): Same.
+ (finish_offsetof): Same.
+ (cp_check_omp_declare_reduction): Same.
+ (finish_decltype_type): Same.
+ * tree.c (handle_init_priority_attribute): Same. Add detail
+ to diagnostics.
+ (maybe_warn_zero_as_null_pointer_constant): Same.
+ * typeck.c (cp_build_binary_op): Quote keywords, operators, and types
+ in diagnostics.
+ (cp_build_unary_op): Same.
+ (check_for_casting_away_constness): Same.
+ (build_static_cast): Same.
+ (build_const_cast_1): Same.
+ (maybe_warn_about_returning_address_of_local): Same.
+ (check_return_expr): Same.
+ * typeck2.c (abstract_virtuals_error_sfinae): Same.
+ (digest_init_r): Replace a tab with spaces in a diagnostic.
+ (build_functional_cast): Quote keywords, operators, and types
+ in diagnostics.
+
+2019-05-15 Jakub Jelinek <jakub@redhat.com>
+
+ PR debug/90197
+ * cp-gimplify.c (genericize_cp_loop): Emit a DEBUG_BEGIN_STMT
+ before the condition (or if missing or constant non-zero at the end
+ of the loop. Emit a DEBUG_BEGIN_STMT before the increment expression
+ if any. Don't call protected_set_expr_location on incr if it already
+ has a location.
+
+2019-05-15 Marek Polacek <polacek@redhat.com>
+
+ CWG 2096 - constraints on literal unions.
+ * class.c (check_field_decls): Initialize booleans directly. A union
+ is literal if at least one of its non-static data members is of
+ non-volatile literal type.
+
+2019-05-15 Paolo Carlini <paolo.carlini@oracle.com>
+
+ * cp-tree.h (REFERENCE_VLA_OK): Remove.
+ * lambda.c (build_capture_proxy): Remove use of the above.
+
+2019-05-15 Paolo Carlini <paolo.carlini@oracle.com>
+
+ * call.c (perform_overload_resolution, build_new_method_call_1):
+ Use OVL_P; remove redundant TEMPLATE_DECL checks.
+ * decl.c (grokfndecl): Likewise.
+ * mangle.c (write_expression): Likewise.
+ * parser.c (cp_parser_template_id): Likewise.
+ * pt.c (resolve_overloaded_unification, type_dependent_expression_p):
+ Likewise.
+ * search.c (build_baselink): Likewise.
+ * tree.c (is_overloaded_fn, dependent_name, maybe_get_fns): Likewise.
+
+2019-05-14 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR preprocessor/90382
+ * decl.c (grokdeclarator): Fix value assigned to typespec_loc, use
+ min_location.
+
+2019-05-13 Jason Merrill <jason@redhat.com>
+
+ Use releasing_vec more broadly.
+ * cp-tree.h (struct releasing_vec): Replace get_ref method with
+ operator&.
+ (vec_safe_push, vec_safe_reserve, vec_safe_length, vec_safe_splice):
+ Forwarding functions for releasing_vec.
+ (release_tree_vector): Declare but don't define.
+ * call.c (build_op_delete_call, build_temp, call_copy_ctor)
+ (perform_direct_initialization_if_possible): Use releasing_vec.
+ * constexpr.c (cxx_eval_vec_init_1, cxx_eval_store_expression):
+ Likewise.
+ * cp-gimplify.c (cp_fold): Likewise.
+ * cvt.c (force_rvalue, ocp_convert): Likewise.
+ * decl.c (get_tuple_decomp_init): Likewise.
+ * except.c (build_throw): Likewise.
+ * init.c (perform_member_init, expand_default_init): Likewise.
+ * method.c (do_build_copy_assign, locate_fn_flags): Likewise.
+ * parser.c (cp_parser_userdef_char_literal)
+ (cp_parser_userdef_numeric_literal)
+ (cp_parser_userdef_string_literal)
+ (cp_parser_perform_range_for_lookup)
+ (cp_parser_range_for_member_function, cp_parser_omp_for_loop)
+ (cp_parser_omp_for_loop_init): Likewise.
+ * pt.c (tsubst_copy_and_build, do_class_deduction): Likewise.
+ * semantics.c (calculate_direct_bases, calculate_bases)
+ (finish_omp_barrier, finish_omp_flush, finish_omp_taskwait)
+ (finish_omp_taskyield, finish_omp_cancel)
+ (finish_omp_cancellation_point): Likewise.
+ * tree.c (build_vec_init_elt, strip_typedefs, strip_typedefs_expr)
+ (build_min_non_dep_op_overload): Likewise.
+ * typeck.c (build_function_call_vec, cp_build_function_call_nary)
+ (cp_build_modify_expr): Likewise.
+ * typeck2.c (build_functional_cast): Likewise.
+
+2019-05-11 Paolo Carlini <paolo.carlini@oracle.com>
+
+ * typeck.c (cp_build_function_call_vec): When mark_used fails
+ unconditionally return error_mark_node.
+
+2019-05-10 Paolo Carlini <paolo.carlini@oracle.com>
+
+ * decl.c (grokvardecl): Use an accurate location in error message
+ about main as a global variable.
+
+2019-05-10 Paolo Carlini <paolo.carlini@oracle.com>
+
+ * call.c (build_call_a): Use FUNC_OR_METHOD_TYPE_P.
+ * cp-gimplify.c (cp_fold): Likewise.
+ * cp-objcp-common.c (cp_type_dwarf_attribute): Likewise.
+ * cp-tree.h (TYPE_OBJ_P, TYPE_PTROBV_P): Likewise.
+ * cvt.c (perform_qualification_conversions): Likewise.
+ * decl.c (grokdeclarator): Likewise.
+ * decl2.c (build_memfn_type): Likewise.
+ * mangle.c (canonicalize_for_substitution, write_type): Likewise.
+ * parser.c (cp_parser_omp_declare_reduction): Likewise.
+ * pt.c (check_explicit_specialization, uses_deducible_template_parms,
+ check_cv_quals_for_unify, dependent_type_p_r): Likewise.
+ * rtti.c (ptr_initializer): Likewise.
+ * semantics.c (finish_asm_stmt, finish_offsetof,
+ cp_check_omp_declare_reduction): Likewise.
+ * tree.c (cp_build_qualified_type_real,
+ cp_build_type_attribute_variant, cxx_type_hash_eq,
+ cxx_copy_lang_qualifiers, cp_free_lang_data): Likewise.
+ * typeck.c (structural_comptypes, convert_arguments,
+ cp_build_addr_expr_1, unary_complex_lvalue, cp_build_c_cast,
+ cp_build_modify_expr, comp_ptr_ttypes_real, type_memfn_rqual):
+ Likewise.
+
+2019-05-10 Marek Polacek <polacek@redhat.com>
+
+ PR c++/78010 - bogus -Wsuggest-override warning on final function.
+ * class.c (check_for_override): Don't warn for final functions.
+
+2019-05-10 Jakub Jelinek <jakub@redhat.com>
+
+ PR pch/90326
+ * config-lang.in (gtfiles): Remove c-family/c-lex.c, add
+ c-family/c-cppbuiltin.c.
+
2019-05-09 Paolo Carlini <paolo.carlini@oracle.com>
PR c++/90382
diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index 20db297..0709325 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -357,8 +357,7 @@ build_call_a (tree function, int n, tree *argarray)
gcc_assert (TYPE_PTR_P (TREE_TYPE (function)));
fntype = TREE_TYPE (TREE_TYPE (function));
- gcc_assert (TREE_CODE (fntype) == FUNCTION_TYPE
- || TREE_CODE (fntype) == METHOD_TYPE);
+ gcc_assert (FUNC_OR_METHOD_TYPE_P (fntype));
result_type = TREE_TYPE (fntype);
/* An rvalue has no cv-qualifiers. */
if (SCALAR_TYPE_P (result_type) || VOID_TYPE_P (result_type))
@@ -394,7 +393,7 @@ build_call_a (tree function, int n, tree *argarray)
{
tree arg = CALL_EXPR_ARG (function, i);
if (is_empty_class (TREE_TYPE (arg))
- && ! TREE_ADDRESSABLE (TREE_TYPE (arg)))
+ && simple_empty_class_p (TREE_TYPE (arg), arg, INIT_EXPR))
{
tree t = build0 (EMPTY_CLASS_EXPR, TREE_TYPE (arg));
arg = build2 (COMPOUND_EXPR, TREE_TYPE (t), arg, t);
@@ -3604,7 +3603,7 @@ print_z_candidate (location_t loc, const char *msgstr,
{
const char *msg = (msgstr == NULL
? ""
- : ACONCAT ((msgstr, " ", NULL)));
+ : ACONCAT ((_(msgstr), " ", NULL)));
tree fn = candidate->fn;
if (flag_new_inheriting_ctors)
fn = strip_inheriting_ctors (fn);
@@ -3614,24 +3613,24 @@ print_z_candidate (location_t loc, const char *msgstr,
{
cloc = loc;
if (candidate->num_convs == 3)
- inform (cloc, "%s%<%D(%T, %T, %T)%> <built-in>", msg, fn,
+ inform (cloc, "%s%<%D(%T, %T, %T)%> (built-in)", msg, fn,
candidate->convs[0]->type,
candidate->convs[1]->type,
candidate->convs[2]->type);
else if (candidate->num_convs == 2)
- inform (cloc, "%s%<%D(%T, %T)%> <built-in>", msg, fn,
+ inform (cloc, "%s%<%D(%T, %T)%> (built-in)", msg, fn,
candidate->convs[0]->type,
candidate->convs[1]->type);
else
- inform (cloc, "%s%<%D(%T)%> <built-in>", msg, fn,
+ inform (cloc, "%s%<%D(%T)%> (built-in)", msg, fn,
candidate->convs[0]->type);
}
else if (TYPE_P (fn))
- inform (cloc, "%s%qT <conversion>", msg, fn);
+ inform (cloc, "%s%qT (conversion)", msg, fn);
else if (candidate->viable == -1)
- inform (cloc, "%s%#qD <near match>", msg, fn);
+ inform (cloc, "%s%#qD (near match)", msg, fn);
else if (DECL_DELETED_FN (fn))
- inform (cloc, "%s%#qD <deleted>", msg, fn);
+ inform (cloc, "%s%#qD (deleted)", msg, fn);
else
inform (cloc, "%s%#qD", msg, fn);
if (fn != candidate->fn)
@@ -3764,7 +3763,7 @@ print_z_candidates (location_t loc, struct z_candidate *candidates)
}
for (; candidates; candidates = candidates->next)
- print_z_candidate (loc, "candidate:", candidates);
+ print_z_candidate (loc, N_("candidate:"), candidates);
}
/* USER_SEQ is a user-defined conversion sequence, beginning with a
@@ -4384,10 +4383,7 @@ perform_overload_resolution (tree fn,
*any_viable_p = true;
/* Check FN. */
- gcc_assert (TREE_CODE (fn) == FUNCTION_DECL
- || TREE_CODE (fn) == TEMPLATE_DECL
- || TREE_CODE (fn) == OVERLOAD
- || TREE_CODE (fn) == TEMPLATE_ID_EXPR);
+ gcc_assert (OVL_P (fn) || TREE_CODE (fn) == TEMPLATE_ID_EXPR);
if (TREE_CODE (fn) == TEMPLATE_ID_EXPR)
{
@@ -5007,7 +5003,8 @@ build_conditional_expr_1 (const op_location_t &loc,
{
if (complain & tf_error)
pedwarn (loc, OPT_Wpedantic,
- "ISO C++ forbids omitting the middle term of a ?: expression");
+ "ISO C++ forbids omitting the middle term of "
+ "a %<?:%> expression");
if ((complain & tf_warning) && !truth_value_p (TREE_CODE (arg1)))
warn_for_omitted_condop (loc, arg1);
@@ -5070,7 +5067,7 @@ build_conditional_expr_1 (const op_location_t &loc,
{
if (complain & tf_error)
error_at (loc, "inferred scalar type %qT is not an integer or "
- "floating point type of the same size as %qT", stype,
+ "floating-point type of the same size as %qT", stype,
COMPARISON_CLASS_P (arg1)
? TREE_TYPE (TREE_TYPE (TREE_OPERAND (arg1, 0)))
: ctype);
@@ -5280,7 +5277,8 @@ build_conditional_expr_1 (const op_location_t &loc,
{
if (complain & tf_error)
{
- error_at (loc, "operands to ?: have different types %qT and %qT",
+ error_at (loc, "operands to %<?:%> have different types "
+ "%qT and %qT",
arg2_type, arg3_type);
if (conv2 && !conv2->bad_p && conv3 && !conv3->bad_p)
inform (loc, " and each type can be converted to the other");
@@ -5396,7 +5394,7 @@ build_conditional_expr_1 (const op_location_t &loc,
if (!any_viable_p)
{
if (complain & tf_error)
- error_at (loc, "operands to ?: have different types %qT and %qT",
+ error_at (loc, "operands to %<?:%> have different types %qT and %qT",
arg2_type, arg3_type);
return error_mark_node;
}
@@ -5488,8 +5486,8 @@ build_conditional_expr_1 (const op_location_t &loc,
/* Two enumerators from the same enumeration can have different
types when the enumeration is still being defined. */;
else if (complain & tf_warning)
- warning_at (loc, OPT_Wenum_compare, "enumeral mismatch in "
- "conditional expression: %qT vs %qT",
+ warning_at (loc, OPT_Wenum_compare, "enumerated mismatch "
+ "in conditional expression: %qT vs %qT",
arg2_type, arg3_type);
}
else if (extra_warnings
@@ -5500,8 +5498,8 @@ build_conditional_expr_1 (const op_location_t &loc,
type_promotes_to (arg3_type)))))
{
if (complain & tf_warning)
- warning_at (loc, OPT_Wextra, "enumeral and non-enumeral type in "
- "conditional expression");
+ warning_at (loc, OPT_Wextra, "enumerated and non-enumerated "
+ "type in conditional expression");
}
arg2 = perform_implicit_conversion (result_type, arg2, complain);
@@ -5543,7 +5541,7 @@ build_conditional_expr_1 (const op_location_t &loc,
if (!result_type)
{
if (complain & tf_error)
- error_at (loc, "operands to ?: have different types %qT and %qT",
+ error_at (loc, "operands to %<?:%> have different types %qT and %qT",
arg2_type, arg3_type);
return error_mark_node;
}
@@ -6169,7 +6167,7 @@ build_new_op_1 (const op_location_t &loc, enum tree_code code, int flags,
conv = cand->convs[2];
if (conv->kind == ck_ref_bind)
conv = next_conversion (conv);
- arg3 = convert_like (conv, arg3, complain);
+ convert_like (conv, arg3, complain);
}
}
@@ -6493,10 +6491,10 @@ build_op_delete_call (enum tree_code code, tree addr, tree size,
{
const char *const msg1
= G_("exception cleanup for this placement new selects "
- "non-placement operator delete");
+ "non-placement %<operator delete%>");
const char *const msg2
= G_("%qD is a usual (non-placement) deallocation "
- "function in C++14 (or with -fsized-deallocation)");
+ "function in C++14 (or with %<-fsized-deallocation%>)");
/* But if the class has an operator delete (void *), then that is
the usual deallocation function, so we shouldn't complain
@@ -6672,7 +6670,7 @@ build_op_delete_call (enum tree_code code, tree addr, tree size,
}
tree ret;
- vec<tree, va_gc> *args = make_tree_vector ();
+ releasing_vec args;
args->quick_push (addr);
if (destroying)
args->quick_push (destroying);
@@ -6684,7 +6682,6 @@ build_op_delete_call (enum tree_code code, tree addr, tree size,
args->quick_push (al);
}
ret = cp_build_function_call_vec (fn, &args, complain);
- release_tree_vector (args);
return ret;
}
}
@@ -6788,7 +6785,6 @@ build_temp (tree expr, tree type, int flags,
diagnostic_t *diagnostic_kind, tsubst_flags_t complain)
{
int savew, savee;
- vec<tree, va_gc> *args;
*diagnostic_kind = DK_UNSPECIFIED;
@@ -6802,10 +6798,9 @@ build_temp (tree expr, tree type, int flags,
return get_target_expr_sfinae (expr, complain);
savew = warningcount + werrorcount, savee = errorcount;
- args = make_tree_vector_single (expr);
+ releasing_vec args (make_tree_vector_single (expr));
expr = build_special_member_call (NULL_TREE, complete_ctor_identifier,
&args, type, flags, complain);
- release_tree_vector (args);
if (warningcount + werrorcount > savew)
*diagnostic_kind = DK_WARNING;
else if (errorcount > savee)
@@ -6896,7 +6891,7 @@ maybe_print_user_conv_context (conversion *convs)
for (conversion *t = convs; t; t = next_conversion (t))
if (t->kind == ck_user)
{
- print_z_candidate (0, " after user-defined conversion:",
+ print_z_candidate (0, N_(" after user-defined conversion:"),
t->cand);
break;
}
@@ -7009,7 +7004,7 @@ convert_like_real (conversion *convs, tree expr, tree fn, int argnum,
"from %qH to %qI", TREE_TYPE (expr),
totype);
if (complained)
- print_z_candidate (loc, "candidate is:", t->cand);
+ print_z_candidate (loc, N_("candidate is:"), t->cand);
expr = convert_like_real (t, expr, fn, argnum,
/*issue_conversion_warnings=*/false,
/*c_cast_p=*/false,
@@ -7385,7 +7380,7 @@ convert_like_real (conversion *convs, tree expr, tree fn, int argnum,
/* If the reference is volatile or non-const, we
cannot create a temporary. */
if (lvalue & clk_bitfield)
- error_at (loc, "cannot bind bitfield %qE to %qT",
+ error_at (loc, "cannot bind bit-field %qE to %qT",
expr, ref_type);
else if (lvalue & clk_packed)
error_at (loc, "cannot bind packed field %qE to %qT",
@@ -7492,8 +7487,8 @@ convert_arg_to_ellipsis (tree arg, tsubst_flags_t complain)
/* [expr.call]
If the argument has integral or enumeration type that is subject
- to the integral promotions (_conv.prom_), or a floating point
- type that is subject to the floating point promotion
+ to the integral promotions (_conv.prom_), or a floating-point
+ type that is subject to the floating-point promotion
(_conv.fpprom_), the value of the argument is converted to the
promoted type before the call. */
if (TREE_CODE (arg_type) == REAL_TYPE
@@ -7521,8 +7516,9 @@ convert_arg_to_ellipsis (tree arg, tsubst_flags_t complain)
if (abi_version_crosses (6)
&& TYPE_MODE (TREE_TYPE (prom)) != TYPE_MODE (arg_type)
&& (complain & tf_warning))
- warning_at (loc, OPT_Wabi, "scoped enum %qT passed through ... as "
- "%qT before %<-fabi-version=6%>, %qT after", arg_type,
+ warning_at (loc, OPT_Wabi, "scoped enum %qT passed through %<...%>"
+ "as %qT before %<-fabi-version=6%>, %qT after",
+ arg_type,
TREE_TYPE (prom), ENUM_UNDERLYING_TYPE (arg_type));
if (!abi_version_at_least (6))
arg = prom;
@@ -7678,7 +7674,7 @@ convert_default_arg (tree type, tree arg, tree fn, int parmnum,
/* If the ARG is an unparsed default argument expression, the
conversion cannot be performed. */
- if (TREE_CODE (arg) == DEFAULT_ARG)
+ if (TREE_CODE (arg) == DEFERRED_PARSE)
{
if (complain & tf_error)
error ("call to %qD uses the default argument for parameter %P, which "
@@ -7898,10 +7894,9 @@ call_copy_ctor (tree a, tsubst_flags_t complain)
tree copy = get_copy_ctor (ctype, complain);
copy = build_baselink (binfo, binfo, copy, NULL_TREE);
tree ob = build_dummy_object (ctype);
- vec<tree, va_gc>* args = make_tree_vector_single (a);
+ releasing_vec args (make_tree_vector_single (a));
tree r = build_new_method_call (ob, copy, &args, NULL_TREE,
LOOKUP_NORMAL, NULL, complain);
- release_tree_vector (args);
return r;
}
@@ -8601,8 +8596,8 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain)
if (is_std_init_list (type)
&& conv_binds_ref_to_prvalue (convs[1]))
warning_at (loc, OPT_Winit_list_lifetime,
- "assignment from temporary initializer_list does not "
- "extend the lifetime of the underlying array");
+ "assignment from temporary %<initializer_list%> does "
+ "not extend the lifetime of the underlying array");
arg = cp_build_fold_indirect_ref (arg);
val = build2 (MODIFY_EXPR, TREE_TYPE (to), to, arg);
}
@@ -9610,9 +9605,7 @@ build_new_method_call_1 (tree instance, tree fns, vec<tree, va_gc> **args,
fns = TREE_OPERAND (fns, 0);
template_only = 1;
}
- gcc_assert (TREE_CODE (fns) == FUNCTION_DECL
- || TREE_CODE (fns) == TEMPLATE_DECL
- || TREE_CODE (fns) == OVERLOAD);
+ gcc_assert (OVL_P (fns));
fn = OVL_FIRST (fns);
name = DECL_NAME (fn);
@@ -10750,7 +10743,8 @@ joust (struct z_candidate *cand1, struct z_candidate *cand2, bool warn,
&& warning (OPT_Wconversion, " for conversion from %qH to %qI",
source, w->second_conv->type))
{
- inform (input_location, " because conversion sequence for the argument is better");
+ inform (input_location, " because conversion sequence "
+ "for the argument is better");
}
}
else
@@ -11036,8 +11030,8 @@ tweak:
"though the worst conversion for the first is "
"better than the worst conversion for the second:"))
{
- print_z_candidate (input_location, _("candidate 1:"), w);
- print_z_candidate (input_location, _("candidate 2:"), l);
+ print_z_candidate (input_location, N_("candidate 1:"), w);
+ print_z_candidate (input_location, N_("candidate 2:"), l);
}
}
else
@@ -11284,10 +11278,9 @@ perform_direct_initialization_if_possible (tree type,
ill-formed. */
if (CLASS_TYPE_P (type))
{
- vec<tree, va_gc> *args = make_tree_vector_single (expr);
+ releasing_vec args (make_tree_vector_single (expr));
expr = build_special_member_call (NULL_TREE, complete_ctor_identifier,
&args, type, LOOKUP_NORMAL, complain);
- release_tree_vector (args);
return build_cplus_new (type, expr, complain);
}
diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index 712169c..73291b3 100644
--- a/gcc/cp/class.c
+++ b/gcc/cp/class.c
@@ -199,7 +199,7 @@ static int walk_subobject_offsets (tree, subobject_offset_fn,
static int layout_conflict_p (tree, tree, splay_tree, int);
static int splay_tree_compare_integer_csts (splay_tree_key k1,
splay_tree_key k2);
-static void warn_about_ambiguous_bases (tree);
+static void maybe_warn_about_inaccessible_bases (tree);
static bool type_requires_array_cookie (tree);
static bool base_derived_from (tree, tree);
static int empty_base_at_nonzero_offset_p (tree, tree, splay_tree);
@@ -1907,6 +1907,7 @@ fixup_type_variants (tree t)
= TYPE_HAS_NONTRIVIAL_DESTRUCTOR (t);
TYPE_POLYMORPHIC_P (variants) = TYPE_POLYMORPHIC_P (t);
+ CLASSTYPE_FINAL (variants) = CLASSTYPE_FINAL (t);
TYPE_BINFO (variants) = TYPE_BINFO (t);
@@ -2149,10 +2150,10 @@ maybe_warn_about_overly_private_class (tree t)
if (!nonprivate_ctor)
{
- warning (OPT_Wctor_dtor_privacy,
- "%q#T only defines private constructors and has no friends",
- t);
- if (copy_or_move)
+ bool w = warning (OPT_Wctor_dtor_privacy,
+ "%q#T only defines private constructors and has "
+ "no friends", t);
+ if (w && copy_or_move)
inform (DECL_SOURCE_LOCATION (copy_or_move),
"%q#D is public, but requires an existing %q#T object",
copy_or_move, t);
@@ -2780,7 +2781,9 @@ check_for_override (tree decl, tree ctype)
{
DECL_VINDEX (decl) = decl;
overrides_found = true;
- if (warn_override && !DECL_OVERRIDE_P (decl)
+ if (warn_override
+ && !DECL_OVERRIDE_P (decl)
+ && !DECL_FINAL_P (decl)
&& !DECL_DESTRUCTOR_P (decl))
warning_at (DECL_SOURCE_LOCATION (decl), OPT_Wsuggest_override,
"%qD can be marked override", decl);
@@ -3401,18 +3404,19 @@ check_field_decls (tree t, tree *access_decls,
{
tree *field;
tree *next;
- bool has_pointers;
- bool any_default_members;
int cant_pack = 0;
int field_access = -1;
/* Assume there are no access declarations. */
*access_decls = NULL_TREE;
/* Assume this class has no pointer members. */
- has_pointers = false;
+ bool has_pointers = false;
/* Assume none of the members of this class have default
initializations. */
- any_default_members = false;
+ bool any_default_members = false;
+ /* Assume none of the non-static data members are of non-volatile literal
+ type. */
+ bool found_nv_literal_p = false;
for (field = &TYPE_FIELDS (t); *field; field = next)
{
@@ -3496,13 +3500,19 @@ check_field_decls (tree t, tree *access_decls,
if (TREE_PRIVATE (x) || TREE_PROTECTED (x))
CLASSTYPE_NON_AGGREGATE (t) = 1;
- /* If at least one non-static data member is non-literal, the whole
- class becomes non-literal. Per Core/1453, volatile non-static
- data members and base classes are also not allowed.
+ /* If it is not a union and at least one non-static data member is
+ non-literal, the whole class becomes non-literal. Per Core/1453,
+ volatile non-static data members and base classes are also not allowed.
+ If it is a union, we might set CLASSTYPE_LITERAL_P after we've seen all
+ members.
Note: if the type is incomplete we will complain later on. */
- if (COMPLETE_TYPE_P (type)
- && (!literal_type_p (type) || CP_TYPE_VOLATILE_P (type)))
- CLASSTYPE_LITERAL_P (t) = false;
+ if (COMPLETE_TYPE_P (type))
+ {
+ if (!literal_type_p (type) || CP_TYPE_VOLATILE_P (type))
+ CLASSTYPE_LITERAL_P (t) = false;
+ else
+ found_nv_literal_p = true;
+ }
/* A standard-layout class is a class that:
...
@@ -3675,6 +3685,11 @@ check_field_decls (tree t, tree *access_decls,
"field %q#D with same name as class", x);
}
+ /* Per CWG 2096, a type is a literal type if it is a union, and at least
+ one of its non-static data members is of non-volatile literal type. */
+ if (TREE_CODE (t) == UNION_TYPE && found_nv_literal_p)
+ CLASSTYPE_LITERAL_P (t) = true;
+
/* Effective C++ rule 11: if a class has dynamic memory held by pointers,
it should also define a copy constructor and an assignment operator to
implement the correct copy semantic (deep vs shallow, etc.). As it is
@@ -4703,8 +4718,6 @@ adjust_clone_args (tree decl)
tree orig_decl_parms = TYPE_ARG_TYPES (TREE_TYPE (decl));
tree decl_parms, clone_parms;
- clone_parms = orig_clone_parms;
-
/* Skip the 'this' parameter. */
orig_clone_parms = TREE_CHAIN (orig_clone_parms);
orig_decl_parms = TREE_CHAIN (orig_decl_parms);
@@ -6003,7 +6016,7 @@ end_of_class (tree t, bool include_virtuals_p)
subobjects of U. */
static void
-warn_about_ambiguous_bases (tree t)
+maybe_warn_about_inaccessible_bases (tree t)
{
int i;
vec<tree, va_gc> *vbases;
@@ -6011,6 +6024,10 @@ warn_about_ambiguous_bases (tree t)
tree binfo;
tree base_binfo;
+ /* If not checking for warning then return early. */
+ if (!warn_inaccessible_base)
+ return;
+
/* If there are no repeated bases, nothing can be ambiguous. */
if (!CLASSTYPE_REPEATED_BASE_P (t))
return;
@@ -6022,8 +6039,8 @@ warn_about_ambiguous_bases (tree t)
basetype = BINFO_TYPE (base_binfo);
if (!uniquely_derived_from_p (basetype, t))
- warning (0, "direct base %qT inaccessible in %qT due to ambiguity",
- basetype, t);
+ warning (OPT_Winaccessible_base, "direct base %qT inaccessible "
+ "in %qT due to ambiguity", basetype, t);
}
/* Check for ambiguous virtual bases. */
@@ -6034,8 +6051,8 @@ warn_about_ambiguous_bases (tree t)
basetype = BINFO_TYPE (binfo);
if (!uniquely_derived_from_p (basetype, t))
- warning (OPT_Wextra, "virtual base %qT inaccessible in %qT due "
- "to ambiguity", basetype, t);
+ warning (OPT_Winaccessible_base, "virtual base %qT inaccessible in "
+ "%qT due to ambiguity", basetype, t);
}
}
@@ -6376,6 +6393,7 @@ layout_class_type (tree t, tree *virtuals_p)
SET_TYPE_ALIGN (base_t, rli->record_align);
TYPE_USER_ALIGN (base_t) = TYPE_USER_ALIGN (t);
TYPE_TYPELESS_STORAGE (base_t) = TYPE_TYPELESS_STORAGE (t);
+ TYPE_CXX_ODR_P (base_t) = TYPE_CXX_ODR_P (t);
/* Copy the non-static data members of T. This will include its
direct non-virtual bases & vtable. */
@@ -6434,6 +6452,12 @@ layout_class_type (tree t, tree *virtuals_p)
/* Let the back end lay out the type. */
finish_record_layout (rli, /*free_p=*/true);
+ /* If we didn't end up needing an as-base type, don't use it. */
+ if (CLASSTYPE_AS_BASE (t) != t
+ && tree_int_cst_equal (TYPE_SIZE (t),
+ TYPE_SIZE (CLASSTYPE_AS_BASE (t))))
+ CLASSTYPE_AS_BASE (t) = t;
+
if (TYPE_SIZE_UNIT (t)
&& TREE_CODE (TYPE_SIZE_UNIT (t)) == INTEGER_CST
&& !TREE_OVERFLOW (TYPE_SIZE_UNIT (t))
@@ -6441,7 +6465,7 @@ layout_class_type (tree t, tree *virtuals_p)
error ("size of type %qT is too large (%qE bytes)", t, TYPE_SIZE_UNIT (t));
/* Warn about bases that can't be talked about due to ambiguity. */
- warn_about_ambiguous_bases (t);
+ maybe_warn_about_inaccessible_bases (t);
/* Now that we're done with layout, give the base fields the real types. */
for (field = TYPE_FIELDS (t); field; field = DECL_CHAIN (field))
@@ -6571,7 +6595,7 @@ find_flexarrays (tree t, flexmems_t *fmem, bool base_p,
if (TREE_CODE (fld) == TYPE_DECL
&& DECL_IMPLICIT_TYPEDEF_P (fld)
&& CLASS_TYPE_P (TREE_TYPE (fld))
- && anon_aggrname_p (DECL_NAME (fld)))
+ && IDENTIFIER_ANON_P (DECL_NAME (fld)))
{
/* Check the nested unnamed type referenced via a typedef
independently of FMEM (since it's not a data member of
@@ -7452,10 +7476,12 @@ resolves_to_fixed_type_p (tree instance, int* nonnull)
}
fixed = fixed_type_or_null (instance, nonnull, &cdtorp);
- if (fixed == NULL_TREE)
- return 0;
if (INDIRECT_TYPE_P (t))
t = TREE_TYPE (t);
+ if (CLASS_TYPE_P (t) && CLASSTYPE_FINAL (t))
+ return 1;
+ if (fixed == NULL_TREE)
+ return 0;
if (!same_type_ignoring_top_level_qualifiers_p (t, fixed))
return 0;
return cdtorp ? -1 : 1;
@@ -8522,7 +8548,6 @@ dump_class_hierarchy_r (FILE *stream,
tree base_binfo;
int i;
- indented = maybe_indent_hierarchy (stream, indent, 0);
fprintf (stream, "%s (0x" HOST_WIDE_INT_PRINT_HEX ") ",
type_as_string (BINFO_TYPE (binfo), TFF_PLAIN_IDENTIFIER),
(HOST_WIDE_INT) (uintptr_t) binfo);
@@ -8543,7 +8568,6 @@ dump_class_hierarchy_r (FILE *stream,
fprintf (stream, " virtual");
fprintf (stream, "\n");
- indented = 0;
if (BINFO_PRIMARY_P (binfo))
{
indented = maybe_indent_hierarchy (stream, indent + 3, indented);
diff --git a/gcc/cp/config-lang.in b/gcc/cp/config-lang.in
index beeab9b..4526d1a 100644
--- a/gcc/cp/config-lang.in
+++ b/gcc/cp/config-lang.in
@@ -37,7 +37,7 @@ gtfiles="\
\$(srcdir)/c-family/c-pragma.h \$(srcdir)/cp/decl.h \
\$(srcdir)/cp/parser.h \
\$(srcdir)/c-family/c-common.c \$(srcdir)/c-family/c-format.c \
-\$(srcdir)/c-family/c-lex.c \$(srcdir)/c-family/c-pragma.c \
+\$(srcdir)/c-family/c-cppbuiltin.c \$(srcdir)/c-family/c-pragma.c \
\$(srcdir)/cp/call.c \$(srcdir)/cp/class.c \$(srcdir)/cp/constexpr.c \
\$(srcdir)/cp/cp-gimplify.c \
\$(srcdir)/cp/cp-lang.c \$(srcdir)/cp/cp-objcp-common.c \
diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c
index 9c13f0d..d11e7af 100644
--- a/gcc/cp/constexpr.c
+++ b/gcc/cp/constexpr.c
@@ -974,12 +974,7 @@ explain_invalid_constexpr_fn (tree fun)
struct GTY((for_user)) constexpr_call {
/* Description of the constexpr function definition. */
constexpr_fundef *fundef;
- /* Parameter bindings environment. A TREE_LIST where each TREE_PURPOSE
- is a parameter _DECL and the TREE_VALUE is the value of the parameter.
- Note: This arrangement is made to accommodate the use of
- iterative_hash_template_arg (see pt.c). If you change this
- representation, also change the hash calculation in
- cxx_eval_call_expression. */
+ /* Parameter bindings environment. A TREE_VEC of arguments. */
tree bindings;
/* Result of the call.
NULL means the call is being evaluated.
@@ -1069,8 +1064,6 @@ constexpr_call_hasher::hash (constexpr_call *info)
bool
constexpr_call_hasher::equal (constexpr_call *lhs, constexpr_call *rhs)
{
- tree lhs_bindings;
- tree rhs_bindings;
if (lhs == rhs)
return true;
if (lhs->hash != rhs->hash)
@@ -1079,19 +1072,7 @@ constexpr_call_hasher::equal (constexpr_call *lhs, constexpr_call *rhs)
return false;
if (!constexpr_fundef_hasher::equal (lhs->fundef, rhs->fundef))
return false;
- lhs_bindings = lhs->bindings;
- rhs_bindings = rhs->bindings;
- while (lhs_bindings != NULL && rhs_bindings != NULL)
- {
- tree lhs_arg = TREE_VALUE (lhs_bindings);
- tree rhs_arg = TREE_VALUE (rhs_bindings);
- gcc_assert (same_type_p (TREE_TYPE (lhs_arg), TREE_TYPE (rhs_arg)));
- if (!cp_tree_equal (lhs_arg, rhs_arg))
- return false;
- lhs_bindings = TREE_CHAIN (lhs_bindings);
- rhs_bindings = TREE_CHAIN (rhs_bindings);
- }
- return lhs_bindings == rhs_bindings;
+ return cp_tree_equal (lhs->bindings, rhs->bindings);
}
/* Initialize the constexpr call table, if needed. */
@@ -1337,31 +1318,62 @@ adjust_temp_type (tree type, tree temp)
if (TREE_CODE (temp) == EMPTY_CLASS_EXPR)
return build0 (EMPTY_CLASS_EXPR, type);
gcc_assert (scalarish_type_p (type));
- return cp_fold_convert (type, temp);
+ /* Now we know we're dealing with a scalar, and a prvalue of non-class
+ type is cv-unqualified. */
+ return cp_fold_convert (cv_unqualified (type), temp);
}
-/* Callback for walk_tree used by unshare_constructor. */
+/* If T is a CONSTRUCTOR, return an unshared copy of T and any
+ sub-CONSTRUCTORs. Otherwise return T.
-static tree
-find_constructor (tree *tp, int *walk_subtrees, void *)
+ We use this whenever we initialize an object as a whole, whether it's a
+ parameter, a local variable, or a subobject, so that subsequent
+ modifications don't affect other places where it was used. */
+
+tree
+unshare_constructor (tree t MEM_STAT_DECL)
{
- if (TYPE_P (*tp))
- *walk_subtrees = 0;
- if (TREE_CODE (*tp) == CONSTRUCTOR)
- return *tp;
- return NULL_TREE;
+ if (!t || TREE_CODE (t) != CONSTRUCTOR)
+ return t;
+ auto_vec <tree*, 4> ptrs;
+ ptrs.safe_push (&t);
+ while (!ptrs.is_empty ())
+ {
+ tree *p = ptrs.pop ();
+ tree n = copy_node (*p PASS_MEM_STAT);
+ CONSTRUCTOR_ELTS (n) = vec_safe_copy (CONSTRUCTOR_ELTS (*p) PASS_MEM_STAT);
+ *p = n;
+ vec<constructor_elt, va_gc> *v = CONSTRUCTOR_ELTS (n);
+ constructor_elt *ce;
+ for (HOST_WIDE_INT i = 0; vec_safe_iterate (v, i, &ce); ++i)
+ if (TREE_CODE (ce->value) == CONSTRUCTOR)
+ ptrs.safe_push (&ce->value);
+ }
+ return t;
}
-/* If T is a CONSTRUCTOR or an expression that has a CONSTRUCTOR node as a
- subexpression, return an unshared copy of T. Otherwise return T. */
+/* If T is a CONSTRUCTOR, ggc_free T and any sub-CONSTRUCTORs. */
-tree
-unshare_constructor (tree t)
+static void
+free_constructor (tree t)
{
- tree ctor = walk_tree (&t, find_constructor, NULL, NULL);
- if (ctor != NULL_TREE)
- return unshare_expr (t);
- return t;
+ if (!t || TREE_CODE (t) != CONSTRUCTOR)
+ return;
+ releasing_vec ctors;
+ vec_safe_push (ctors, t);
+ while (!ctors->is_empty ())
+ {
+ tree c = ctors->pop ();
+ if (vec<constructor_elt, va_gc> *elts = CONSTRUCTOR_ELTS (c))
+ {
+ constructor_elt *ce;
+ for (HOST_WIDE_INT i = 0; vec_safe_iterate (elts, i, &ce); ++i)
+ if (TREE_CODE (ce->value) == CONSTRUCTOR)
+ vec_safe_push (ctors, ce->value);
+ ggc_free (elts);
+ }
+ ggc_free (c);
+ }
}
/* Subroutine of cxx_eval_call_expression.
@@ -1380,7 +1392,10 @@ cxx_bind_parameters_in_call (const constexpr_ctx *ctx, tree t,
tree fun = new_call->fundef->decl;
tree parms = new_call->fundef->parms;
int i;
- tree *p = &new_call->bindings;
+ /* We don't record ellipsis args below. */
+ int nparms = list_length (parms);
+ int nbinds = nargs < nparms ? nargs : nparms;
+ tree binds = new_call->bindings = make_tree_vec (nbinds);
for (i = 0; i < nargs; ++i)
{
tree x, arg;
@@ -1409,7 +1424,8 @@ cxx_bind_parameters_in_call (const constexpr_ctx *ctx, tree t,
if (!*non_constant_p)
{
- /* Don't share a CONSTRUCTOR that might be changed. */
+ /* Unsharing here isn't necessary for correctness, but it
+ significantly improves memory performance for some reason. */
arg = unshare_constructor (arg);
/* Make sure the binding has the same type as the parm. But
only for constant args. */
@@ -1417,8 +1433,7 @@ cxx_bind_parameters_in_call (const constexpr_ctx *ctx, tree t,
arg = adjust_temp_type (type, arg);
if (!TREE_CONSTANT (arg))
*non_constant_args = true;
- *p = build_tree_list (parms, arg);
- p = &TREE_CHAIN (*p);
+ TREE_VEC_ELT (binds, i) = arg;
}
parms = TREE_CHAIN (parms);
}
@@ -1432,16 +1447,17 @@ static vec<tree> call_stack;
static int call_stack_tick;
static int last_cx_error_tick;
-static bool
+static int
push_cx_call_context (tree call)
{
++call_stack_tick;
if (!EXPR_HAS_LOCATION (call))
SET_EXPR_LOCATION (call, input_location);
call_stack.safe_push (call);
- if (call_stack.length () > (unsigned) max_constexpr_depth)
+ int len = call_stack.length ();
+ if (len > max_constexpr_depth)
return false;
- return true;
+ return len;
}
static void
@@ -1572,7 +1588,7 @@ cxx_eval_call_expression (const constexpr_ctx *ctx, tree t,
tree fun = get_function_named_in_call (t);
constexpr_call new_call
= { NULL, NULL, NULL, 0, ctx->manifestly_const_eval };
- bool depth_ok;
+ int depth_ok;
if (fun == NULL_TREE)
return cxx_eval_internal_function (ctx, t, lval,
@@ -1733,6 +1749,26 @@ cxx_eval_call_expression (const constexpr_ctx *ctx, tree t,
bool non_constant_args = false;
cxx_bind_parameters_in_call (ctx, t, &new_call,
non_constant_p, overflow_p, &non_constant_args);
+
+ /* We build up the bindings list before we know whether we already have this
+ call cached. If we don't end up saving these bindings, ggc_free them when
+ this function exits. */
+ struct free_bindings
+ {
+ tree &bindings;
+ bool do_free;
+ free_bindings (tree &b): bindings (b), do_free(true) { }
+ void preserve () { do_free = false; }
+ ~free_bindings () {
+ if (do_free)
+ {
+ for (int i = 0; i < TREE_VEC_LENGTH (bindings); ++i)
+ free_constructor (TREE_VEC_ELT (bindings, i));
+ ggc_free (bindings);
+ }
+ }
+ } fb (new_call.bindings);
+
if (*non_constant_p)
return t;
@@ -1756,13 +1792,20 @@ cxx_eval_call_expression (const constexpr_ctx *ctx, tree t,
entry = *slot;
if (entry == NULL)
{
- /* We need to keep a pointer to the entry, not just the slot, as the
- slot can move in the call to cxx_eval_builtin_function_call. */
- *slot = entry = ggc_alloc<constexpr_call> ();
- *entry = new_call;
+ /* Only cache up to constexpr_cache_depth to limit memory use. */
+ if (depth_ok < constexpr_cache_depth)
+ {
+ /* We need to keep a pointer to the entry, not just the slot, as
+ the slot can move during evaluation of the body. */
+ *slot = entry = ggc_alloc<constexpr_call> ();
+ *entry = new_call;
+ fb.preserve ();
+ }
}
- /* Calls that are in progress have their result set to NULL,
- so that we can detect circular dependencies. */
+ /* Calls that are in progress have their result set to NULL, so that we
+ can detect circular dependencies. Now that we only cache up to
+ constexpr_cache_depth this won't catch circular dependencies that
+ start deeper, but they'll hit the recursion or ops limit. */
else if (entry->result == NULL)
{
if (!ctx->quiet)
@@ -1799,6 +1842,7 @@ cxx_eval_call_expression (const constexpr_ctx *ctx, tree t,
else
{
tree body, parms, res;
+ releasing_vec ctors;
/* Reuse or create a new unshared copy of this function's body. */
tree copy = get_fundef_copy (new_call.fundef);
@@ -1809,15 +1853,14 @@ cxx_eval_call_expression (const constexpr_ctx *ctx, tree t,
/* Associate the bindings with the remapped parms. */
tree bound = new_call.bindings;
tree remapped = parms;
- while (bound)
+ for (int i = 0; i < TREE_VEC_LENGTH (bound); ++i)
{
- tree oparm = TREE_PURPOSE (bound);
- tree arg = TREE_VALUE (bound);
- gcc_assert (DECL_NAME (remapped) == DECL_NAME (oparm));
+ tree arg = TREE_VEC_ELT (bound, i);
/* Don't share a CONSTRUCTOR that might be changed. */
arg = unshare_constructor (arg);
+ if (TREE_CODE (arg) == CONSTRUCTOR)
+ vec_safe_push (ctors, arg);
ctx->values->put (remapped, arg);
- bound = TREE_CHAIN (bound);
remapped = DECL_CHAIN (remapped);
}
/* Add the RESULT_DECL to the values map, too. */
@@ -1882,6 +1925,14 @@ cxx_eval_call_expression (const constexpr_ctx *ctx, tree t,
for (tree parm = parms; parm; parm = TREE_CHAIN (parm))
ctx->values->remove (parm);
+ /* Free any parameter CONSTRUCTORs we aren't returning directly. */
+ while (!ctors->is_empty ())
+ {
+ tree c = ctors->pop ();
+ if (c != result)
+ free_constructor (c);
+ }
+
/* Make the unshared function copy we used available for re-use. */
save_fundef_copy (fun, copy);
}
@@ -1901,7 +1952,7 @@ cxx_eval_call_expression (const constexpr_ctx *ctx, tree t,
clear_no_implicit_zero (result);
pop_cx_call_context ();
- return unshare_constructor (result);
+ return result;
}
/* FIXME speed this up, it's taking 16% of compile time on sieve testcase. */
@@ -2020,9 +2071,9 @@ cxx_eval_check_shift_p (location_t loc, const constexpr_ctx *ctx,
if (compare_tree_int (rhs, uprec) >= 0)
{
if (!ctx->quiet)
- permerror (loc, "right operand of shift expression %q+E is >= than "
- "the precision of the left operand",
- build2_loc (loc, code, type, lhs, rhs));
+ permerror (loc, "right operand of shift expression %q+E is greater "
+ "than or equal to the precision %wu of the left operand",
+ build2_loc (loc, code, type, lhs, rhs), uprec);
return (!flag_permissive || ctx->quiet);
}
@@ -2444,7 +2495,7 @@ find_array_ctor_elt (tree ary, tree dindex, bool insert)
an out-of-bounds subscript INDEX into the expression ARRAY. */
static void
-diag_array_subscript (const constexpr_ctx *ctx, tree array, tree index)
+diag_array_subscript (location_t loc, const constexpr_ctx *ctx, tree array, tree index)
{
if (!ctx->quiet)
{
@@ -2453,22 +2504,23 @@ diag_array_subscript (const constexpr_ctx *ctx, tree array, tree index)
/* Convert the unsigned array subscript to a signed integer to avoid
printing huge numbers for small negative values. */
tree sidx = fold_convert (ssizetype, index);
+ STRIP_ANY_LOCATION_WRAPPER (array);
if (DECL_P (array))
{
if (TYPE_DOMAIN (arraytype))
- error ("array subscript value %qE is outside the bounds "
- "of array %qD of type %qT", sidx, array, arraytype);
+ error_at (loc, "array subscript value %qE is outside the bounds "
+ "of array %qD of type %qT", sidx, array, arraytype);
else
- error ("non-zero array subscript %qE is used with array %qD of "
- "type %qT with unknown bounds", sidx, array, arraytype);
+ error_at (loc, "nonzero array subscript %qE is used with array %qD of "
+ "type %qT with unknown bounds", sidx, array, arraytype);
inform (DECL_SOURCE_LOCATION (array), "declared here");
}
else if (TYPE_DOMAIN (arraytype))
- error ("array subscript value %qE is outside the bounds "
- "of array type %qT", sidx, arraytype);
+ error_at (loc, "array subscript value %qE is outside the bounds "
+ "of array type %qT", sidx, arraytype);
else
- error ("non-zero array subscript %qE is used with array of type %qT "
- "with unknown bounds", sidx, arraytype);
+ error_at (loc, "nonzero array subscript %qE is used with array of type %qT "
+ "with unknown bounds", sidx, arraytype);
}
}
@@ -2519,83 +2571,98 @@ extract_string_elt (tree string, unsigned chars_per_elt, unsigned index)
return r;
}
-/* Subroutine of cxx_eval_constant_expression.
- Attempt to reduce a reference to an array slot. */
+/* Subroutine of cxx_eval_array_reference. T is an ARRAY_REF; evaluate the
+ subscript, diagnose any problems with it, and return the result. */
static tree
-cxx_eval_array_reference (const constexpr_ctx *ctx, tree t,
- bool lval,
- bool *non_constant_p, bool *overflow_p)
+eval_and_check_array_index (const constexpr_ctx *ctx,
+ tree t, bool allow_one_past,
+ bool *non_constant_p, bool *overflow_p)
{
- tree oldary = TREE_OPERAND (t, 0);
- tree ary = cxx_eval_constant_expression (ctx, oldary,
- lval,
- non_constant_p, overflow_p);
- tree index, oldidx;
- HOST_WIDE_INT i = 0;
- tree elem_type = NULL_TREE;
- unsigned len = 0, elem_nchars = 1;
- if (*non_constant_p)
- return t;
- oldidx = TREE_OPERAND (t, 1);
- index = cxx_eval_constant_expression (ctx, oldidx,
- false,
- non_constant_p, overflow_p);
+ location_t loc = cp_expr_loc_or_loc (t, input_location);
+ tree ary = TREE_OPERAND (t, 0);
+ t = TREE_OPERAND (t, 1);
+ tree index = cxx_eval_constant_expression (ctx, t, false,
+ non_constant_p, overflow_p);
VERIFY_CONSTANT (index);
- if (!lval)
- {
- elem_type = TREE_TYPE (TREE_TYPE (ary));
- if (TREE_CODE (ary) == VIEW_CONVERT_EXPR
- && VECTOR_TYPE_P (TREE_TYPE (TREE_OPERAND (ary, 0)))
- && TREE_TYPE (t) == TREE_TYPE (TREE_TYPE (TREE_OPERAND (ary, 0))))
- ary = TREE_OPERAND (ary, 0);
- if (TREE_CODE (ary) == CONSTRUCTOR)
- len = CONSTRUCTOR_NELTS (ary);
- else if (TREE_CODE (ary) == STRING_CST)
- {
- elem_nchars = (TYPE_PRECISION (elem_type)
- / TYPE_PRECISION (char_type_node));
- len = (unsigned) TREE_STRING_LENGTH (ary) / elem_nchars;
- }
- else if (TREE_CODE (ary) == VECTOR_CST)
- /* We don't create variable-length VECTOR_CSTs. */
- len = VECTOR_CST_NELTS (ary).to_constant ();
- else
- {
- /* We can't do anything with other tree codes, so use
- VERIFY_CONSTANT to complain and fail. */
- VERIFY_CONSTANT (ary);
- gcc_unreachable ();
- }
- if (!tree_fits_shwi_p (index)
- || (i = tree_to_shwi (index)) < 0)
- {
- diag_array_subscript (ctx, ary, index);
- *non_constant_p = true;
- return t;
- }
+ if (!tree_fits_shwi_p (index)
+ || tree_int_cst_sgn (index) < 0)
+ {
+ diag_array_subscript (loc, ctx, ary, index);
+ *non_constant_p = true;
+ return t;
}
tree nelts = get_array_or_vector_nelts (ctx, TREE_TYPE (ary), non_constant_p,
overflow_p);
VERIFY_CONSTANT (nelts);
- if ((lval
- ? !tree_int_cst_le (index, nelts)
- : !tree_int_cst_lt (index, nelts))
- || tree_int_cst_sgn (index) < 0)
+ if (allow_one_past
+ ? !tree_int_cst_le (index, nelts)
+ : !tree_int_cst_lt (index, nelts))
{
- diag_array_subscript (ctx, ary, index);
+ diag_array_subscript (loc, ctx, ary, index);
*non_constant_p = true;
return t;
}
+ return index;
+}
+
+/* Subroutine of cxx_eval_constant_expression.
+ Attempt to reduce a reference to an array slot. */
+
+static tree
+cxx_eval_array_reference (const constexpr_ctx *ctx, tree t,
+ bool lval,
+ bool *non_constant_p, bool *overflow_p)
+{
+ tree oldary = TREE_OPERAND (t, 0);
+ tree ary = cxx_eval_constant_expression (ctx, oldary,
+ lval,
+ non_constant_p, overflow_p);
+ if (*non_constant_p)
+ return t;
+ if (!lval
+ && TREE_CODE (ary) == VIEW_CONVERT_EXPR
+ && VECTOR_TYPE_P (TREE_TYPE (TREE_OPERAND (ary, 0)))
+ && TREE_TYPE (t) == TREE_TYPE (TREE_TYPE (TREE_OPERAND (ary, 0))))
+ ary = TREE_OPERAND (ary, 0);
+
+ tree oldidx = TREE_OPERAND (t, 1);
+ tree index = eval_and_check_array_index (ctx, t, lval,
+ non_constant_p, overflow_p);
+ if (*non_constant_p)
+ return t;
+
if (lval && ary == oldary && index == oldidx)
return t;
else if (lval)
return build4 (ARRAY_REF, TREE_TYPE (t), ary, index, NULL, NULL);
+ unsigned len = 0, elem_nchars = 1;
+ tree elem_type = TREE_TYPE (TREE_TYPE (ary));
+ if (TREE_CODE (ary) == CONSTRUCTOR)
+ len = CONSTRUCTOR_NELTS (ary);
+ else if (TREE_CODE (ary) == STRING_CST)
+ {
+ elem_nchars = (TYPE_PRECISION (elem_type)
+ / TYPE_PRECISION (char_type_node));
+ len = (unsigned) TREE_STRING_LENGTH (ary) / elem_nchars;
+ }
+ else if (TREE_CODE (ary) == VECTOR_CST)
+ /* We don't create variable-length VECTOR_CSTs. */
+ len = VECTOR_CST_NELTS (ary).to_constant ();
+ else
+ {
+ /* We can't do anything with other tree codes, so use
+ VERIFY_CONSTANT to complain and fail. */
+ VERIFY_CONSTANT (ary);
+ gcc_unreachable ();
+ }
+
bool found;
+ HOST_WIDE_INT i = 0;
if (TREE_CODE (ary) == CONSTRUCTOR)
{
HOST_WIDE_INT ix = find_array_ctor_elt (ary, index);
@@ -2604,7 +2671,10 @@ cxx_eval_array_reference (const constexpr_ctx *ctx, tree t,
i = ix;
}
else
- found = (i < len);
+ {
+ i = tree_to_shwi (index);
+ found = (i < len);
+ }
if (found)
{
@@ -3113,11 +3183,10 @@ cxx_eval_vec_init_1 (const constexpr_ctx *ctx, tree atype, tree init,
}
else if (!init)
{
- vec<tree, va_gc> *argvec = make_tree_vector ();
+ releasing_vec argvec;
init = build_special_member_call (NULL_TREE, complete_ctor_identifier,
&argvec, elttype, LOOKUP_NORMAL,
complain);
- release_tree_vector (argvec);
init = build_aggr_init_expr (elttype, init);
pre_init = true;
}
@@ -3686,61 +3755,22 @@ cxx_eval_store_expression (const constexpr_ctx *ctx, tree t,
if (*non_constant_p)
return t;
}
- target = cxx_eval_constant_expression (ctx, target,
- true,
- non_constant_p, overflow_p);
- if (*non_constant_p)
- return t;
- /* cxx_eval_array_reference for lval = true allows references one past
- end of array, because it does not know if it is just taking address
- (which is valid), or actual dereference. Here we know it is
- a dereference, so diagnose it here. */
- for (tree probe = target; probe; )
+ bool evaluated = false;
+ if (lval)
{
- switch (TREE_CODE (probe))
- {
- case ARRAY_REF:
- tree nelts, ary;
- ary = TREE_OPERAND (probe, 0);
- nelts = get_array_or_vector_nelts (ctx, TREE_TYPE (ary),
+ /* If we want to return a reference to the target, we need to evaluate it
+ as a whole; otherwise, only evaluate the innermost piece to avoid
+ building up unnecessary *_REFs. */
+ target = cxx_eval_constant_expression (ctx, target, true,
non_constant_p, overflow_p);
- VERIFY_CONSTANT (nelts);
- gcc_assert (TREE_CODE (nelts) == INTEGER_CST
- && TREE_CODE (TREE_OPERAND (probe, 1)) == INTEGER_CST);
- if (wi::to_widest (TREE_OPERAND (probe, 1)) == wi::to_widest (nelts))
- {
- diag_array_subscript (ctx, ary, TREE_OPERAND (probe, 1));
- *non_constant_p = true;
- return t;
- }
- /* FALLTHRU */
-
- case BIT_FIELD_REF:
- case COMPONENT_REF:
- probe = TREE_OPERAND (probe, 0);
- continue;
-
- default:
- probe = NULL_TREE;
- continue;
- }
- }
-
- if (!same_type_ignoring_top_level_qualifiers_p (TREE_TYPE (target), type))
- {
- /* For initialization of an empty base, the original target will be
- *(base*)this, which the above evaluation resolves to the object
- argument, which has the derived type rather than the base type. In
- this situation, just evaluate the initializer and return, since
- there's no actual data to store. */
- gcc_assert (is_empty_class (type));
- return cxx_eval_constant_expression (ctx, init, false,
- non_constant_p, overflow_p);
+ evaluated = true;
+ if (*non_constant_p)
+ return t;
}
- /* And then find the underlying variable. */
- vec<tree,va_gc> *refs = make_tree_vector();
+ /* Find the underlying variable. */
+ releasing_vec refs;
tree object = NULL_TREE;
for (tree probe = target; object == NULL_TREE; )
{
@@ -3749,13 +3779,34 @@ cxx_eval_store_expression (const constexpr_ctx *ctx, tree t,
case BIT_FIELD_REF:
case COMPONENT_REF:
case ARRAY_REF:
- vec_safe_push (refs, TREE_OPERAND (probe, 1));
- vec_safe_push (refs, TREE_TYPE (probe));
- probe = TREE_OPERAND (probe, 0);
+ {
+ tree ob = TREE_OPERAND (probe, 0);
+ tree elt = TREE_OPERAND (probe, 1);
+ if (TREE_CODE (probe) == ARRAY_REF)
+ {
+ elt = eval_and_check_array_index (ctx, probe, false,
+ non_constant_p, overflow_p);
+ if (*non_constant_p)
+ return t;
+ }
+ vec_safe_push (refs, elt);
+ vec_safe_push (refs, TREE_TYPE (probe));
+ probe = ob;
+ }
break;
default:
- object = probe;
+ if (evaluated)
+ object = probe;
+ else
+ {
+ probe = cxx_eval_constant_expression (ctx, probe, true,
+ non_constant_p, overflow_p);
+ evaluated = true;
+ if (*non_constant_p)
+ return t;
+ }
+ break;
}
}
@@ -3784,7 +3835,7 @@ cxx_eval_store_expression (const constexpr_ctx *ctx, tree t,
type = TREE_TYPE (object);
bool no_zero_init = true;
- vec<tree,va_gc> *ctors = make_tree_vector ();
+ releasing_vec ctors;
while (!refs->is_empty())
{
if (*valp == NULL_TREE)
@@ -3897,7 +3948,6 @@ cxx_eval_store_expression (const constexpr_ctx *ctx, tree t,
}
valp = &cep->value;
}
- release_tree_vector (refs);
if (!preeval)
{
@@ -3912,7 +3962,7 @@ cxx_eval_store_expression (const constexpr_ctx *ctx, tree t,
new_ctx.object = target;
init = cxx_eval_constant_expression (&new_ctx, init, false,
non_constant_p, overflow_p);
- if (target == object)
+ if (ctors->is_empty())
/* The hash table might have moved since the get earlier. */
valp = ctx->values->get (object);
}
@@ -3925,6 +3975,17 @@ cxx_eval_store_expression (const constexpr_ctx *ctx, tree t,
{
/* An outer ctx->ctor might be pointing to *valp, so replace
its contents. */
+ if (!same_type_ignoring_top_level_qualifiers_p (TREE_TYPE (init),
+ TREE_TYPE (*valp)))
+ {
+ /* For initialization of an empty base, the original target will be
+ *(base*)this, evaluation of which resolves to the object
+ argument, which has the derived type rather than the base type. In
+ this situation, just evaluate the initializer and return, since
+ there's no actual data to store. */
+ gcc_assert (is_empty_class (TREE_TYPE (init)) && !lval);
+ return init;
+ }
CONSTRUCTOR_ELTS (*valp) = CONSTRUCTOR_ELTS (init);
TREE_CONSTANT (*valp) = TREE_CONSTANT (init);
TREE_SIDE_EFFECTS (*valp) = TREE_SIDE_EFFECTS (init);
@@ -3941,14 +4002,13 @@ cxx_eval_store_expression (const constexpr_ctx *ctx, tree t,
bool c = TREE_CONSTANT (init);
bool s = TREE_SIDE_EFFECTS (init);
if (!c || s)
- FOR_EACH_VEC_SAFE_ELT (ctors, i, elt)
+ FOR_EACH_VEC_ELT (*ctors, i, elt)
{
if (!c)
TREE_CONSTANT (elt) = false;
if (s)
TREE_SIDE_EFFECTS (elt) = true;
}
- release_tree_vector (ctors);
if (*non_constant_p)
return t;
@@ -4005,6 +4065,7 @@ cxx_eval_increment_expression (const constexpr_ctx *ctx, tree t,
tree store = build2 (MODIFY_EXPR, type, op, mod);
cxx_eval_constant_expression (ctx, store,
true, non_constant_p, overflow_p);
+ ggc_free (store);
/* And the value of the expression. */
if (code == PREINCREMENT_EXPR || code == PREDECREMENT_EXPR)
@@ -4360,9 +4421,6 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t,
bool *non_constant_p, bool *overflow_p,
tree *jump_target /* = NULL */)
{
- constexpr_ctx new_ctx;
- tree r = t;
-
if (jump_target && *jump_target)
{
/* If we are jumping, ignore all statements/expressions except those
@@ -4393,6 +4451,9 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t,
*non_constant_p = true;
return t;
}
+
+ STRIP_ANY_LOCATION_WRAPPER (t);
+
if (CONSTANT_CLASS_P (t))
{
if (TREE_OVERFLOW (t))
@@ -4417,19 +4478,21 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t,
}
/* Avoid excessively long constexpr evaluations. */
- if (!location_wrapper_p (t)
- && ++*ctx->constexpr_ops_count >= constexpr_ops_limit)
+ if (++*ctx->constexpr_ops_count >= constexpr_ops_limit)
{
if (!ctx->quiet)
error_at (cp_expr_loc_or_loc (t, input_location),
"%<constexpr%> evaluation operation count exceeds limit of "
- "%wd (use -fconstexpr-ops-limit= to increase the limit)",
+ "%wd (use %<-fconstexpr-ops-limit=%> to increase the limit)",
constexpr_ops_limit);
*ctx->constexpr_ops_count = INTTYPE_MINIMUM (HOST_WIDE_INT);
*non_constant_p = true;
return t;
}
+ constexpr_ctx new_ctx;
+ tree r = t;
+
tree_code tcode = TREE_CODE (t);
switch (tcode)
{
@@ -4730,7 +4793,10 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t,
/* This function does more aggressive folding than fold itself. */
r = build_fold_addr_expr_with_type (op, TREE_TYPE (t));
if (TREE_CODE (r) == ADDR_EXPR && TREE_OPERAND (r, 0) == oldop)
- return t;
+ {
+ ggc_free (r);
+ return t;
+ }
break;
}
@@ -4763,9 +4829,19 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t,
break;
case SIZEOF_EXPR:
- r = cxx_eval_constant_expression (ctx, fold_sizeof_expr (t), lval,
- non_constant_p, overflow_p,
- jump_target);
+ r = fold_sizeof_expr (t);
+ /* In a template, fold_sizeof_expr may merely create a new SIZEOF_EXPR,
+ which could lead to an infinite recursion. */
+ if (TREE_CODE (r) != SIZEOF_EXPR)
+ r = cxx_eval_constant_expression (ctx, r, lval,
+ non_constant_p, overflow_p,
+ jump_target);
+ else
+ {
+ *non_constant_p = true;
+ gcc_assert (ctx->quiet);
+ }
+
break;
case COMPOUND_EXPR:
@@ -4960,7 +5036,7 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t,
{
if (!ctx->quiet)
error_at (cp_expr_loc_or_loc (t, input_location),
- "a reinterpret_cast is not a constant expression");
+ "%<reinterpret_cast%> is not a constant expression");
*non_constant_p = true;
return t;
}
@@ -4977,6 +5053,10 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t,
if (*non_constant_p)
return t;
tree type = TREE_TYPE (t);
+
+ if (VOID_TYPE_P (type))
+ return void_node;
+
if (TREE_CODE (op) == PTRMEM_CST
&& !TYPE_PTRMEM_P (type))
op = cplus_expand_constant (op);
@@ -5037,10 +5117,16 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t,
conversion. */
return fold (t);
+ tree sop;
+
/* Handle an array's bounds having been deduced after we built
the wrapping expression. */
if (same_type_ignoring_tlq_and_bounds_p (type, TREE_TYPE (op)))
r = op;
+ else if (sop = tree_strip_nop_conversions (op),
+ sop != op && (same_type_ignoring_tlq_and_bounds_p
+ (type, TREE_TYPE (sop))))
+ r = sop;
else if (tcode == UNARY_PLUS_EXPR)
r = fold_convert (TREE_TYPE (t), op);
else
@@ -6119,7 +6205,7 @@ potential_constant_expression_1 (tree t, bool want_rval, bool strict, bool now,
if (REINTERPRET_CAST_P (t))
{
if (flags & tf_error)
- error_at (loc, "a reinterpret_cast is not a constant expression");
+ error_at (loc, "%<reinterpret_cast%> is not a constant expression");
return false;
}
/* FALLTHRU */
@@ -6138,7 +6224,8 @@ potential_constant_expression_1 (tree t, bool want_rval, bool strict, bool now,
&& !integer_zerop (from))
{
if (flags & tf_error)
- error_at (loc, "reinterpret_cast from integer to pointer");
+ error_at (loc,
+ "%<reinterpret_cast%> from integer to pointer");
return false;
}
}
@@ -6392,7 +6479,8 @@ potential_constant_expression_1 (tree t, bool want_rval, bool strict, bool now,
/* In C++2a virtual calls can be constexpr, don't give up yet. */
return true;
else if (flags & tf_error)
- error_at (loc, "virtual functions cannot be constexpr before C++2a");
+ error_at (loc,
+ "virtual functions cannot be %<constexpr%> before C++2a");
return false;
case TYPEID_EXPR:
@@ -6404,7 +6492,7 @@ potential_constant_expression_1 (tree t, bool want_rval, bool strict, bool now,
&& TYPE_POLYMORPHIC_P (TREE_TYPE (e)))
{
if (flags & tf_error)
- error_at (loc, "typeid-expression is not a constant expression "
+ error_at (loc, "%<typeid%> is not a constant expression "
"because %qE is of polymorphic type", e);
return false;
}
diff --git a/gcc/cp/constraint.cc b/gcc/cp/constraint.cc
index 9884eb0..ed39ecc 100644
--- a/gcc/cp/constraint.cc
+++ b/gcc/cp/constraint.cc
@@ -2693,13 +2693,13 @@ diagnose_trait_expression (location_t loc, tree, tree cur, tree args)
switch (TRAIT_EXPR_KIND (expr))
{
case CPTK_HAS_NOTHROW_ASSIGN:
- inform (loc, " %qT is not nothrow copy assignable", t1);
+ inform (loc, " %qT is not %<nothrow%> copy assignable", t1);
break;
case CPTK_HAS_NOTHROW_CONSTRUCTOR:
- inform (loc, " %qT is not nothrow default constructible", t1);
+ inform (loc, " %qT is not %<nothrow%> default constructible", t1);
break;
case CPTK_HAS_NOTHROW_COPY:
- inform (loc, " %qT is not nothrow copy constructible", t1);
+ inform (loc, " %qT is not %<nothrow%> copy constructible", t1);
break;
case CPTK_HAS_TRIVIAL_ASSIGN:
inform (loc, " %qT is not trivially copy assignable", t1);
diff --git a/gcc/cp/cp-gimplify.c b/gcc/cp/cp-gimplify.c
index 26be1fd1..bce01f5 100644
--- a/gcc/cp/cp-gimplify.c
+++ b/gcc/cp/cp-gimplify.c
@@ -241,8 +241,10 @@ genericize_cp_loop (tree *stmt_p, location_t start_locus, tree cond, tree body,
tree blab, clab;
tree exit = NULL;
tree stmt_list = NULL;
+ tree debug_begin = NULL;
- protected_set_expr_location (incr, start_locus);
+ if (EXPR_LOCATION (incr) == UNKNOWN_LOCATION)
+ protected_set_expr_location (incr, start_locus);
cp_walk_tree (&cond, cp_genericize_r, data, NULL);
cp_walk_tree (&incr, cp_genericize_r, data, NULL);
@@ -253,6 +255,13 @@ genericize_cp_loop (tree *stmt_p, location_t start_locus, tree cond, tree body,
cp_walk_tree (&body, cp_genericize_r, data, NULL);
*walk_subtrees = 0;
+ if (MAY_HAVE_DEBUG_MARKER_STMTS
+ && (!cond || !integer_zerop (cond)))
+ {
+ debug_begin = build0 (DEBUG_BEGIN_STMT, void_type_node);
+ SET_EXPR_LOCATION (debug_begin, cp_expr_loc_or_loc (cond, start_locus));
+ }
+
if (cond && TREE_CODE (cond) != INTEGER_CST)
{
/* If COND is constant, don't bother building an exit. If it's false,
@@ -265,10 +274,24 @@ genericize_cp_loop (tree *stmt_p, location_t start_locus, tree cond, tree body,
}
if (exit && cond_is_first)
- append_to_statement_list (exit, &stmt_list);
+ {
+ append_to_statement_list (debug_begin, &stmt_list);
+ debug_begin = NULL_TREE;
+ append_to_statement_list (exit, &stmt_list);
+ }
append_to_statement_list (body, &stmt_list);
finish_bc_block (&stmt_list, bc_continue, clab);
- append_to_statement_list (incr, &stmt_list);
+ if (incr)
+ {
+ if (MAY_HAVE_DEBUG_MARKER_STMTS)
+ {
+ tree d = build0 (DEBUG_BEGIN_STMT, void_type_node);
+ SET_EXPR_LOCATION (d, cp_expr_loc_or_loc (incr, start_locus));
+ append_to_statement_list (d, &stmt_list);
+ }
+ append_to_statement_list (incr, &stmt_list);
+ }
+ append_to_statement_list (debug_begin, &stmt_list);
if (exit && !cond_is_first)
append_to_statement_list (exit, &stmt_list);
@@ -570,20 +593,21 @@ gimplify_must_not_throw_expr (tree *expr_p, gimple_seq *pre_p)
non-empty CONSTRUCTORs get reduced properly, and we leave the
return slot optimization alone because it isn't a copy. */
-static bool
-simple_empty_class_p (tree type, tree op)
+bool
+simple_empty_class_p (tree type, tree op, tree_code code)
{
+ if (TREE_CODE (op) == COMPOUND_EXPR)
+ return simple_empty_class_p (type, TREE_OPERAND (op, 1), code);
return
- ((TREE_CODE (op) == COMPOUND_EXPR
- && simple_empty_class_p (type, TREE_OPERAND (op, 1)))
- || TREE_CODE (op) == EMPTY_CLASS_EXPR
+ (TREE_CODE (op) == EMPTY_CLASS_EXPR
+ || code == MODIFY_EXPR
|| is_gimple_lvalue (op)
|| INDIRECT_REF_P (op)
|| (TREE_CODE (op) == CONSTRUCTOR
- && CONSTRUCTOR_NELTS (op) == 0
- && !TREE_CLOBBER_P (op))
+ && CONSTRUCTOR_NELTS (op) == 0)
|| (TREE_CODE (op) == CALL_EXPR
&& !CALL_EXPR_RETURN_SLOT_OPT (op)))
+ && !TREE_CLOBBER_P (op)
&& is_really_empty_class (type, /*ignore_vptr*/true);
}
@@ -692,7 +716,7 @@ cp_gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p)
TREE_OPERAND (*expr_p, 1) = build1 (VIEW_CONVERT_EXPR,
TREE_TYPE (op0), op1);
- else if (simple_empty_class_p (TREE_TYPE (op0), op1))
+ else if (simple_empty_class_p (TREE_TYPE (op0), op1, code))
{
/* Remove any copies of empty classes. Also drop volatile
variables on the RHS to avoid infinite recursion from
@@ -1214,6 +1238,8 @@ cp_genericize_r (tree *stmt_p, int *walk_subtrees, void *data)
case OMP_CLAUSE_FIRSTPRIVATE:
case OMP_CLAUSE_COPYIN:
case OMP_CLAUSE_COPYPRIVATE:
+ case OMP_CLAUSE_INCLUSIVE:
+ case OMP_CLAUSE_EXCLUSIVE:
/* Don't dereference an invisiref in OpenMP clauses. */
if (is_invisiref_parm (OMP_CLAUSE_DECL (stmt)))
*walk_subtrees = 0;
@@ -1466,10 +1492,10 @@ cp_genericize_r (tree *stmt_p, int *walk_subtrees, void *data)
{
auto_diagnostic_group d;
if (warning_at (loc, OPT_Wterminate,
- "throw will always call terminate()")
+ "%<throw%> will always call %<terminate%>")
&& cxx_dialect >= cxx11
&& DECL_DESTRUCTOR_P (current_function_decl))
- inform (loc, "in C++11 destructors default to noexcept");
+ inform (loc, "in C++11 destructors default to %<noexcept%>");
}
}
else
@@ -1481,8 +1507,8 @@ cp_genericize_r (tree *stmt_p, int *walk_subtrees, void *data)
&& (get_defaulted_eh_spec (current_function_decl)
== empty_except_spec))
warning_at (loc, OPT_Wc__11_compat,
- "in C++11 this throw will terminate because "
- "destructors default to noexcept");
+ "in C++11 this %<throw%> will call %<terminate%> "
+ "because destructors default to %<noexcept%>");
}
}
break;
@@ -2324,8 +2350,7 @@ cp_fold (tree x)
/* Cope with user tricks that amount to offsetof. */
if (op0 != error_mark_node
- && TREE_CODE (TREE_TYPE (op0)) != FUNCTION_TYPE
- && TREE_CODE (TREE_TYPE (op0)) != METHOD_TYPE)
+ && !FUNC_OR_METHOD_TYPE_P (TREE_TYPE (op0)))
{
tree val = get_base_address (op0);
if (val
@@ -2655,7 +2680,7 @@ cp_fold (tree x)
case TREE_VEC:
{
bool changed = false;
- vec<tree, va_gc> *vec = make_tree_vector ();
+ releasing_vec vec;
int i, n = TREE_VEC_LENGTH (x);
vec_safe_reserve (vec, n);
@@ -2674,8 +2699,6 @@ cp_fold (tree x)
TREE_VEC_ELT (r, i) = (*vec)[i];
x = r;
}
-
- release_tree_vector (vec);
}
break;
diff --git a/gcc/cp/cp-lang.c b/gcc/cp/cp-lang.c
index 9dc3659..be34871 100644
--- a/gcc/cp/cp-lang.c
+++ b/gcc/cp/cp-lang.c
@@ -109,8 +109,7 @@ cxx_dwarf_name (tree t, int verbosity)
{
gcc_assert (DECL_P (t));
- if (DECL_NAME (t)
- && (anon_aggrname_p (DECL_NAME (t)) || LAMBDA_TYPE_P (t)))
+ if (DECL_NAME (t) && IDENTIFIER_ANON_P (DECL_NAME (t)))
return NULL;
if (verbosity >= 2)
return decl_as_dwarf_string (t,
diff --git a/gcc/cp/cp-objcp-common.c b/gcc/cp/cp-objcp-common.c
index bfd3fa6..21d162e 100644
--- a/gcc/cp/cp-objcp-common.c
+++ b/gcc/cp/cp-objcp-common.c
@@ -67,7 +67,7 @@ cp_tree_size (enum tree_code code)
case PTRMEM_CST: return sizeof (ptrmem_cst);
case BASELINK: return sizeof (tree_baselink);
case TEMPLATE_PARM_INDEX: return sizeof (template_parm_index);
- case DEFAULT_ARG: return sizeof (tree_default_arg);
+ case DEFERRED_PARSE: return sizeof (tree_deferred_parse);
case DEFERRED_NOEXCEPT: return sizeof (tree_deferred_noexcept);
case OVERLOAD: return sizeof (tree_overload);
case STATIC_ASSERT: return sizeof (tree_static_assert);
@@ -248,16 +248,14 @@ cp_type_dwarf_attribute (const_tree type, int attr)
switch (attr)
{
case DW_AT_reference:
- if ((TREE_CODE (type) == FUNCTION_TYPE
- || TREE_CODE (type) == METHOD_TYPE)
+ if (FUNC_OR_METHOD_TYPE_P (type)
&& FUNCTION_REF_QUALIFIED (type)
&& !FUNCTION_RVALUE_QUALIFIED (type))
return 1;
break;
case DW_AT_rvalue_reference:
- if ((TREE_CODE (type) == FUNCTION_TYPE
- || TREE_CODE (type) == METHOD_TYPE)
+ if (FUNC_OR_METHOD_TYPE_P (type)
&& FUNCTION_REF_QUALIFIED (type)
&& FUNCTION_RVALUE_QUALIFIED (type))
return 1;
diff --git a/gcc/cp/cp-tree.def b/gcc/cp/cp-tree.def
index 03c105b..4db1d31 100644
--- a/gcc/cp/cp-tree.def
+++ b/gcc/cp/cp-tree.def
@@ -207,10 +207,11 @@ DEFTREECODE (USING_DECL, "using_decl", tcc_declaration, 0)
/* A using directive. The operand is USING_STMT_NAMESPACE. */
DEFTREECODE (USING_STMT, "using_stmt", tcc_statement, 1)
-/* An un-parsed default argument. Holds a vector of input tokens and
+/* An un-parsed operand. Holds a vector of input tokens and
a vector of places where the argument was instantiated before
- parsing had occurred. */
-DEFTREECODE (DEFAULT_ARG, "default_arg", tcc_exceptional, 0)
+ parsing had occurred. This is used for default arguments, delayed
+ NSDMIs, and noexcept-specifier parsing. */
+DEFTREECODE (DEFERRED_PARSE, "deferred_parse", tcc_exceptional, 0)
/* An uninstantiated/unevaluated noexcept-specification. For the
uninstantiated case, DEFERRED_NOEXCEPT_PATTERN is the pattern from the
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index f253857..a1849f6 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -482,7 +482,6 @@ extern GTY(()) tree cp_global_trees[CPTI_MAX];
5: CLASS_TYPE_P (in RECORD_TYPE and UNION_TYPE)
ENUM_FIXED_UNDERLYING_TYPE_P (in ENUMERAL_TYPE)
AUTO_IS_DECLTYPE (in TEMPLATE_TYPE_PARM)
- REFERENCE_VLA_OK (in REFERENCE_TYPE)
6: TYPE_DEPENDENT_P_VALID
Usage of DECL_LANG_FLAG_?:
@@ -735,7 +734,7 @@ struct GTY(()) tree_overload {
/* Iterator for a 1 dimensional overload. Permits iterating over the
outer level of a 2-d overload when explicitly enabled. */
-class ovl_iterator
+class ovl_iterator
{
tree ovl;
const bool allow_inner; /* Only used when checking. */
@@ -890,15 +889,25 @@ struct releasing_vec
vec_t *operator-> () const { return v; }
vec_t *get() const { return v; }
operator vec_t *() const { return v; }
- tree& operator[] (unsigned i) const { return (*v)[i]; }
+ vec_t ** operator& () { return &v; }
- /* Necessary for use with vec** and vec*& interfaces. */
- vec_t *&get_ref () { return v; }
+ /* Breaks pointer/value consistency for convenience. */
+ tree& operator[] (unsigned i) const { return (*v)[i]; }
~releasing_vec() { release_tree_vector (v); }
private:
vec_t *v;
};
+/* Forwarding functions for vec_safe_* that might reallocate. */
+inline tree* vec_safe_push (releasing_vec& r, const tree &t CXX_MEM_STAT_INFO)
+{ return vec_safe_push (*&r, t PASS_MEM_STAT); }
+inline bool vec_safe_reserve (releasing_vec& r, unsigned n, bool e = false CXX_MEM_STAT_INFO)
+{ return vec_safe_reserve (*&r, n, e PASS_MEM_STAT); }
+inline unsigned vec_safe_length (releasing_vec &r)
+{ return r->length(); }
+inline void vec_safe_splice (releasing_vec &r, vec<tree, va_gc> *p CXX_MEM_STAT_INFO)
+{ vec_safe_splice (*&r, p PASS_MEM_STAT); }
+void release_tree_vector (releasing_vec &); // cause link error
struct GTY(()) tree_template_decl {
struct tree_decl_common common;
@@ -1173,15 +1182,15 @@ enum cp_identifier_kind {
#define C_TYPE_FIELDS_READONLY(TYPE) \
(LANG_TYPE_CLASS_CHECK (TYPE)->fields_readonly)
-/* The tokens stored in the default argument. */
+/* The tokens stored in the unparsed operand. */
-#define DEFARG_TOKENS(NODE) \
- (((struct tree_default_arg *)DEFAULT_ARG_CHECK (NODE))->tokens)
-#define DEFARG_INSTANTIATIONS(NODE) \
- (((struct tree_default_arg *)DEFAULT_ARG_CHECK (NODE))->instantiations)
+#define DEFPARSE_TOKENS(NODE) \
+ (((struct tree_deferred_parse *)DEFERRED_PARSE_CHECK (NODE))->tokens)
+#define DEFPARSE_INSTANTIATIONS(NODE) \
+ (((struct tree_deferred_parse *)DEFERRED_PARSE_CHECK (NODE))->instantiations)
-struct GTY (()) tree_default_arg {
- struct tree_common common;
+struct GTY (()) tree_deferred_parse {
+ struct tree_base base;
struct cp_token_cache *tokens;
vec<tree, va_gc> *instantiations;
};
@@ -1197,6 +1206,9 @@ struct GTY (()) tree_default_arg {
#define UNEVALUATED_NOEXCEPT_SPEC_P(NODE) \
(DEFERRED_NOEXCEPT_SPEC_P (NODE) \
&& DEFERRED_NOEXCEPT_PATTERN (TREE_PURPOSE (NODE)) == NULL_TREE)
+#define UNPARSED_NOEXCEPT_SPEC_P(NODE) \
+ ((NODE) && (TREE_PURPOSE (NODE)) \
+ && (TREE_CODE (TREE_PURPOSE (NODE)) == DEFERRED_PARSE))
struct GTY (()) tree_deferred_noexcept {
struct tree_base base;
@@ -1284,13 +1296,20 @@ enum cp_trait_kind
struct GTY (()) tree_trait_expr {
struct tree_common common;
tree type1;
- tree type2;
+ tree type2;
enum cp_trait_kind kind;
};
+/* Identifiers used for lambda types are almost anonymous. Use this
+ spare flag to distinguish them (they also have the anonymous flag). */
+#define IDENTIFIER_LAMBDA_P(NODE) \
+ (IDENTIFIER_NODE_CHECK(NODE)->base.protected_flag)
+
/* Based off of TYPE_UNNAMED_P. */
-#define LAMBDA_TYPE_P(NODE) \
- (CLASS_TYPE_P (NODE) && CLASSTYPE_LAMBDA_EXPR (NODE))
+#define LAMBDA_TYPE_P(NODE) \
+ (TREE_CODE (NODE) == RECORD_TYPE \
+ && TYPE_LINKAGE_IDENTIFIER (NODE) \
+ && IDENTIFIER_LAMBDA_P (TYPE_LINKAGE_IDENTIFIER (NODE)))
/* Test if FUNCTION_DECL is a lambda function. */
#define LAMBDA_FUNCTION_P(FNDECL) \
@@ -1570,7 +1589,7 @@ enum cp_tree_node_structure_enum {
TS_CP_OVERLOAD,
TS_CP_BASELINK,
TS_CP_TEMPLATE_DECL,
- TS_CP_DEFAULT_ARG,
+ TS_CP_DEFERRED_PARSE,
TS_CP_DEFERRED_NOEXCEPT,
TS_CP_STATIC_ASSERT,
TS_CP_ARGUMENT_PACK_SELECT,
@@ -1591,10 +1610,10 @@ union GTY((desc ("cp_tree_node_structure (&%h)"),
struct tree_overload GTY ((tag ("TS_CP_OVERLOAD"))) overload;
struct tree_baselink GTY ((tag ("TS_CP_BASELINK"))) baselink;
struct tree_template_decl GTY ((tag ("TS_CP_TEMPLATE_DECL"))) template_decl;
- struct tree_default_arg GTY ((tag ("TS_CP_DEFAULT_ARG"))) default_arg;
+ struct tree_deferred_parse GTY ((tag ("TS_CP_DEFERRED_PARSE"))) deferred_parse;
struct tree_deferred_noexcept GTY ((tag ("TS_CP_DEFERRED_NOEXCEPT"))) deferred_noexcept;
struct lang_identifier GTY ((tag ("TS_CP_IDENTIFIER"))) identifier;
- struct tree_static_assert GTY ((tag ("TS_CP_STATIC_ASSERT")))
+ struct tree_static_assert GTY ((tag ("TS_CP_STATIC_ASSERT")))
static_assertion;
struct tree_argument_pack_select GTY ((tag ("TS_CP_ARGUMENT_PACK_SELECT")))
argument_pack_select;
@@ -1926,9 +1945,15 @@ enum languages { lang_c, lang_cplusplus };
#define TYPE_NAME_STRING(NODE) (IDENTIFIER_POINTER (TYPE_IDENTIFIER (NODE)))
#define TYPE_NAME_LENGTH(NODE) (IDENTIFIER_LENGTH (TYPE_IDENTIFIER (NODE)))
-/* Nonzero if NODE has no name for linkage purposes. */
-#define TYPE_UNNAMED_P(NODE) \
- (OVERLOAD_TYPE_P (NODE) && anon_aggrname_p (TYPE_LINKAGE_IDENTIFIER (NODE)))
+/* Any kind of anonymous type. */
+#define TYPE_ANON_P(NODE) \
+ (TYPE_LINKAGE_IDENTIFIER (NODE) \
+ && IDENTIFIER_ANON_P (TYPE_LINKAGE_IDENTIFIER (NODE)))
+
+/* Nonzero if NODE, a TYPE, has no name for linkage purposes. */
+#define TYPE_UNNAMED_P(NODE) \
+ (TYPE_ANON_P (NODE) \
+ && !IDENTIFIER_LAMBDA_P (TYPE_LINKAGE_IDENTIFIER (NODE)))
/* The _DECL for this _TYPE. */
#define TYPE_MAIN_DECL(NODE) (TYPE_STUB_DECL (TYPE_MAIN_VARIANT (NODE)))
@@ -2659,9 +2684,7 @@ struct GTY(()) lang_decl_ns {
struct lang_decl_base base;
cp_binding_level *level;
- /* using directives and inline children. These need to be va_gc,
- because of PCH. */
- vec<tree, va_gc> *usings;
+ /* Inline children. These need to be va_gc, because of PCH. */
vec<tree, va_gc> *inlinees;
/* Hash table of bound decls. It'd be nice to have this inline, but
@@ -3250,10 +3273,6 @@ struct GTY(()) lang_decl {
#define DECL_NAMESPACE_INLINE_P(NODE) \
TREE_LANG_FLAG_0 (NAMESPACE_DECL_CHECK (NODE))
-/* In a NAMESPACE_DECL, a vector of using directives. */
-#define DECL_NAMESPACE_USING(NODE) \
- (LANG_DECL_NS_CHECK (NODE)->usings)
-
/* In a NAMESPACE_DECL, a vector of inline namespaces. */
#define DECL_NAMESPACE_INLINEES(NODE) \
(LANG_DECL_NS_CHECK (NODE)->inlinees)
@@ -3661,7 +3680,7 @@ struct GTY(()) lang_decl {
select. */
#define ARGUMENT_PACK_SELECT_INDEX(NODE) \
(((struct tree_argument_pack_select *)ARGUMENT_PACK_SELECT_CHECK (NODE))->index)
-
+
#define FOLD_EXPR_CHECK(NODE) \
TREE_CHECK4 (NODE, UNARY_LEFT_FOLD_EXPR, UNARY_RIGHT_FOLD_EXPR, \
BINARY_LEFT_FOLD_EXPR, BINARY_RIGHT_FOLD_EXPR)
@@ -3704,11 +3723,6 @@ struct GTY(()) lang_decl {
&& TREE_TYPE (TREE_OPERAND (NODE, 0)) \
&& TYPE_REF_P (TREE_TYPE (TREE_OPERAND ((NODE), 0))))
-/* True if NODE is a REFERENCE_TYPE which is OK to instantiate to be a
- reference to VLA type, because it's used for VLA capture. */
-#define REFERENCE_VLA_OK(NODE) \
- (TYPE_LANG_FLAG_5 (REFERENCE_TYPE_CHECK (NODE)))
-
#define NEW_EXPR_USE_GLOBAL(NODE) \
TREE_LANG_FLAG_0 (NEW_EXPR_CHECK (NODE))
#define DELETE_EXPR_USE_GLOBAL(NODE) \
@@ -4066,7 +4080,7 @@ more_aggr_init_expr_args_p (const aggr_init_expr_arg_iterator *iter)
/* [basic.fundamental]
Integral and floating types are collectively called arithmetic
- types.
+ types.
As a GNU extension, we also accept complex types.
@@ -4084,7 +4098,7 @@ more_aggr_init_expr_args_p (const aggr_init_expr_arg_iterator *iter)
Arithmetic types, enumeration types, pointer types,
pointer-to-member types, and std::nullptr_t are collectively called
scalar types.
-
+
Keep these checks in ascending code order. */
#define SCALAR_TYPE_P(TYPE) \
(TYPE_PTRDATAMEM_P (TYPE) \
@@ -4104,7 +4118,7 @@ more_aggr_init_expr_args_p (const aggr_init_expr_arg_iterator *iter)
Scoped enumeration types are different from normal (unscoped)
enumeration types in several ways:
-
+
- The enumerators of a scoped enumeration type are only available
within the scope of the enumeration type and not in the
enclosing scope. For example, the Red color can be referred to
@@ -4168,7 +4182,7 @@ more_aggr_init_expr_args_p (const aggr_init_expr_arg_iterator *iter)
checks in ascending code order. */
#define CP_AGGREGATE_TYPE_P(TYPE) \
(TREE_CODE (TYPE) == VECTOR_TYPE \
- ||TREE_CODE (TYPE) == ARRAY_TYPE \
+ || TREE_CODE (TYPE) == ARRAY_TYPE \
|| (CLASS_TYPE_P (TYPE) && !CLASSTYPE_NON_AGGREGATE (TYPE)))
/* Nonzero for a class type means that the class type has a
@@ -4297,7 +4311,7 @@ more_aggr_init_expr_args_p (const aggr_init_expr_arg_iterator *iter)
/* Nonzero for _TYPE node means that this type does not have a trivial
destructor. Therefore, destroying an object of this type will
involve a call to a destructor. This can apply to objects of
- ARRAY_TYPE is the type of the elements needs a destructor. */
+ ARRAY_TYPE if the type of the elements needs a destructor. */
#define TYPE_HAS_NONTRIVIAL_DESTRUCTOR(NODE) \
(TYPE_LANG_FLAG_4 (NODE))
@@ -4342,8 +4356,7 @@ more_aggr_init_expr_args_p (const aggr_init_expr_arg_iterator *iter)
#define TYPE_OBJ_P(NODE) \
(!TYPE_REF_P (NODE) \
&& !VOID_TYPE_P (NODE) \
- && TREE_CODE (NODE) != FUNCTION_TYPE \
- && TREE_CODE (NODE) != METHOD_TYPE)
+ && !FUNC_OR_METHOD_TYPE_P (NODE))
/* Returns true if NODE is a pointer to an object. Keep these checks
in ascending tree code order. */
@@ -4359,8 +4372,7 @@ more_aggr_init_expr_args_p (const aggr_init_expr_arg_iterator *iter)
void. Keep these checks in ascending tree code order. */
#define TYPE_PTROBV_P(NODE) \
(TYPE_PTR_P (NODE) \
- && !(TREE_CODE (TREE_TYPE (NODE)) == FUNCTION_TYPE \
- || TREE_CODE (TREE_TYPE (NODE)) == METHOD_TYPE))
+ && !FUNC_OR_METHOD_TYPE_P (TREE_TYPE (NODE)))
/* Returns true if NODE is a pointer to function type. */
#define TYPE_PTRFN_P(NODE) \
@@ -4569,7 +4581,7 @@ more_aggr_init_expr_args_p (const aggr_init_expr_arg_iterator *iter)
parameter). The TREE_PURPOSE is the default value, if any. The
TEMPLATE_PARM_INDEX for the parameter is available as the
DECL_INITIAL (for a PARM_DECL) or as the TREE_TYPE (for a
- TYPE_DECL).
+ TYPE_DECL).
FIXME: CONST_CAST_TREE is a hack that hopefully will go away after
tree is converted to C++ class hiearchy. */
@@ -4721,18 +4733,18 @@ more_aggr_init_expr_args_p (const aggr_init_expr_arg_iterator *iter)
template <> int min<int> (int, int),
3=explicit instantiation, e.g.:
-
+
template int min<int> (int, int);
Note that NODE will be marked as a specialization even if the
template it is instantiating is not a primary template. For
example, given:
- template <typename T> struct O {
+ template <typename T> struct O {
void f();
- struct I {};
+ struct I {};
};
-
+
both O<int>::f and O<int>::I will be marked as instantiations.
If DECL_USE_TEMPLATE is nonzero, then DECL_TEMPLATE_INFO will also
@@ -4915,7 +4927,7 @@ more_aggr_init_expr_args_p (const aggr_init_expr_arg_iterator *iter)
See semantics.c for details. */
#define CP_OMP_CLAUSE_INFO(NODE) \
TREE_TYPE (OMP_CLAUSE_RANGE_CHECK (NODE, OMP_CLAUSE_PRIVATE, \
- OMP_CLAUSE_LINEAR))
+ OMP_CLAUSE__CONDTEMP_))
/* Nonzero if this transaction expression's body contains statements. */
#define TRANSACTION_EXPR_IS_STMT(NODE) \
@@ -5361,9 +5373,6 @@ extern GTY(()) vec<tree, va_gc> *keyed_classes;
#endif /* NO_DOLLAR_IN_LABEL */
#endif /* NO_DOT_IN_LABEL */
-#define LAMBDANAME_PREFIX "__lambda"
-#define LAMBDANAME_FORMAT LAMBDANAME_PREFIX "%d"
-
#define UDLIT_OP_ANSI_PREFIX "operator\"\""
#define UDLIT_OP_ANSI_FORMAT UDLIT_OP_ANSI_PREFIX "%s"
#define UDLIT_OP_MANGLED_PREFIX "li"
@@ -5507,9 +5516,8 @@ enum overload_flags { NO_SPECIAL = 0, DTOR_FLAG, TYPENAME_FLAG };
#define CONV_CONST 4
#define CONV_REINTERPRET 8
#define CONV_PRIVATE 16
-/* #define CONV_NONCONVERTING 32 */
-#define CONV_FORCE_TEMP 64
-#define CONV_FOLD 128
+#define CONV_FORCE_TEMP 32
+#define CONV_FOLD 64
#define CONV_OLD_CONVERT (CONV_IMPLICIT | CONV_STATIC | CONV_CONST \
| CONV_REINTERPRET)
#define CONV_C_CAST (CONV_IMPLICIT | CONV_STATIC | CONV_CONST \
@@ -5858,6 +5866,9 @@ struct cp_decl_specifier_seq {
BOOL_BITFIELD gnu_thread_keyword_p : 1;
/* True iff the type is a decltype. */
BOOL_BITFIELD decltype_p : 1;
+ /* True iff the alternate "__intN__" form of the __intN type has been
+ used. */
+ BOOL_BITFIELD int_n_alt: 1;
};
/* The various kinds of declarators. */
@@ -6355,7 +6366,6 @@ extern tree strip_fnptr_conv (tree);
/* in name-lookup.c */
extern void maybe_push_cleanup_level (tree);
-extern tree make_anon_name (void);
extern tree maybe_push_decl (tree);
extern tree current_decl_namespace (void);
@@ -6371,7 +6381,6 @@ extern void note_break_stmt (void);
extern bool note_iteration_stmt_body_start (void);
extern void note_iteration_stmt_body_end (bool);
extern void determine_local_discriminator (tree);
-extern tree make_lambda_name (void);
extern int decls_match (tree, tree, bool = true);
extern bool maybe_version_functions (tree, tree, bool);
extern tree duplicate_decls (tree, tree, bool);
@@ -6464,6 +6473,7 @@ extern bool check_array_designated_initializer (constructor_elt *,
unsigned HOST_WIDE_INT);
extern bool check_for_uninitialized_const_var (tree, bool, tsubst_flags_t);
extern tree build_explicit_specifier (tree, tsubst_flags_t);
+extern void do_push_parm_decls (tree, tree, tree *);
/* in decl2.c */
extern void record_mangling (tree, bool);
@@ -6697,7 +6707,7 @@ extern void cp_finish_omp_range_for (tree, tree);
extern bool parsing_nsdmi (void);
extern bool parsing_default_capturing_generic_lambda_in_template (void);
extern void inject_this_parameter (tree, cp_cv_quals);
-extern location_t defarg_location (tree);
+extern location_t defparse_location (tree);
extern void maybe_show_extern_c_location (void);
extern bool literal_integer_zerop (const_tree);
@@ -6737,7 +6747,7 @@ extern void append_type_to_template_for_access_check (tree, tree, tree,
extern tree convert_generic_types_to_packs (tree, int, int);
extern tree splice_late_return_type (tree, tree);
extern bool is_auto (const_tree);
-extern tree process_template_parm (tree, location_t, tree,
+extern tree process_template_parm (tree, location_t, tree,
bool, bool);
extern tree end_template_parm_list (tree);
extern void end_template_parm_list (void);
@@ -6929,6 +6939,7 @@ extern tree copied_binfo (tree, tree);
extern tree original_binfo (tree, tree);
extern int shared_member_p (tree);
extern bool any_dependent_bases_p (tree = current_nonlambda_class_type ());
+extern bool maybe_check_overriding_exception_spec (tree, tree);
/* The representation of a deferred access check. */
@@ -7393,7 +7404,7 @@ extern tree cp_build_unary_op (enum tree_code, tree, bool,
tsubst_flags_t);
extern tree genericize_compound_lvalue (tree);
extern tree unary_complex_lvalue (enum tree_code, tree);
-extern tree build_x_conditional_expr (location_t, tree, tree, tree,
+extern tree build_x_conditional_expr (location_t, tree, tree, tree,
tsubst_flags_t);
extern tree build_x_compound_expr_from_list (tree, expr_list_kind,
tsubst_flags_t);
@@ -7438,7 +7449,7 @@ extern void expand_ptrmemfunc_cst (tree, tree *, tree *);
extern tree type_after_usual_arithmetic_conversions (tree, tree);
extern tree common_pointer_type (tree, tree);
extern tree composite_pointer_type (tree, tree, tree, tree,
- composite_pointer_operation,
+ composite_pointer_operation,
tsubst_flags_t);
extern tree merge_types (tree, tree);
extern tree strip_array_domain (tree);
@@ -7586,6 +7597,7 @@ extern tree cp_fully_fold_init (tree);
extern void clear_fold_cache (void);
extern tree lookup_hotness_attribute (tree);
extern tree process_stmt_hotness_attribute (tree, location_t);
+extern bool simple_empty_class_p (tree, tree, tree_code);
/* in name-lookup.c */
extern tree strip_using_decl (tree);
@@ -7721,7 +7733,7 @@ extern void explain_invalid_constexpr_fn (tree);
extern vec<tree> cx_error_context (void);
extern tree fold_sizeof_expr (tree);
extern void clear_cv_and_fold_caches (void);
-extern tree unshare_constructor (tree);
+extern tree unshare_constructor (tree CXX_MEM_STAT_INFO);
/* In cp-ubsan.c */
extern void cp_ubsan_maybe_instrument_member_call (tree);
diff --git a/gcc/cp/cvt.c b/gcc/cp/cvt.c
index 3b8656c..23d2aab 100644
--- a/gcc/cp/cvt.c
+++ b/gcc/cp/cvt.c
@@ -88,7 +88,7 @@ cp_convert_to_pointer (tree type, tree expr, bool dofold,
if (!COMPLETE_TYPE_P (intype))
{
if (complain & tf_error)
- error_at (loc, "can%'t convert from incomplete type %qH to %qI",
+ error_at (loc, "cannot convert from incomplete type %qH to %qI",
intype, type);
return error_mark_node;
}
@@ -562,10 +562,9 @@ force_rvalue (tree expr, tsubst_flags_t complain)
tree type = TREE_TYPE (expr);
if (MAYBE_CLASS_TYPE_P (type) && TREE_CODE (expr) != TARGET_EXPR)
{
- vec<tree, va_gc> *args = make_tree_vector_single (expr);
+ releasing_vec args (make_tree_vector_single (expr));
expr = build_special_member_call (NULL_TREE, complete_ctor_identifier,
&args, type, LOOKUP_NORMAL, complain);
- release_tree_vector (args);
expr = build_cplus_new (type, expr, complain);
}
else
@@ -884,7 +883,7 @@ ocp_convert (tree type, tree expr, int convtype, int flags,
return rval;
else if (complain & tf_error)
error_at (loc,
- "%q#T used where a floating point value was expected",
+ "%q#T used where a floating-point value was expected",
TREE_TYPE (e));
}
if (code == REAL_TYPE)
@@ -925,12 +924,11 @@ ocp_convert (tree type, tree expr, int convtype, int flags,
ctor = build_user_type_conversion (type, ctor, flags, complain);
else
{
- vec<tree, va_gc> *ctor_vec = make_tree_vector_single (ctor);
+ releasing_vec ctor_vec (make_tree_vector_single (ctor));
ctor = build_special_member_call (NULL_TREE,
complete_ctor_identifier,
&ctor_vec,
type, flags, complain);
- release_tree_vector (ctor_vec);
}
if (ctor)
return build_cplus_new (type, ctor, complain);
@@ -1062,14 +1060,14 @@ maybe_warn_nodiscard (tree expr, impl_conv_void implicit)
auto_diagnostic_group d;
if (warning_at (loc, OPT_Wunused_result,
"ignoring return value of %qD, "
- "declared with attribute warn_unused_result",
+ "declared with attribute %<warn_unused_result%>",
fn))
inform (DECL_SOURCE_LOCATION (fn), "declared here");
}
else
warning_at (loc, OPT_Wunused_result,
"ignoring return value of function "
- "declared with attribute warn_unused_result");
+ "declared with attribute %<warn_unused_result%>");
}
}
@@ -1520,7 +1518,8 @@ convert_to_void (tree expr, impl_conv_void implicit, tsubst_flags_t complain)
if (implicit != ICV_CAST
&& warn_unused_value
&& !TREE_NO_WARNING (expr)
- && !processing_template_decl)
+ && !processing_template_decl
+ && !cp_unevaluated_operand)
{
/* The middle end does not warn about expressions that have
been explicitly cast to void, so we must do so here. */
@@ -1822,7 +1821,7 @@ build_expr_type_conversion (int desires, tree expr, bool complain)
if (TREE_CODE (cand) == TEMPLATE_DECL)
{
if (complain)
- error ("default type conversion can%'t deduce template"
+ error ("default type conversion cannot deduce template"
" argument for %qD", cand);
return error_mark_node;
}
@@ -1922,7 +1921,7 @@ type_promotes_to (tree type)
{
if (abi_version_crosses (6)
&& TYPE_MODE (prom) != TYPE_MODE (type))
- warning (OPT_Wabi, "scoped enum %qT passed through ... as "
+ warning (OPT_Wabi, "scoped enum %qT passed through %<...%> as "
"%qT before %<-fabi-version=6%>, %qT after",
type, prom, ENUM_UNDERLYING_TYPE (type));
if (!abi_version_at_least (6))
@@ -1996,8 +1995,7 @@ perform_qualification_conversions (tree type, tree expr)
bool
tx_safe_fn_type_p (tree t)
{
- if (TREE_CODE (t) != FUNCTION_TYPE
- && TREE_CODE (t) != METHOD_TYPE)
+ if (!FUNC_OR_METHOD_TYPE_P (t))
return false;
return !!lookup_attribute ("transaction_safe", TYPE_ATTRIBUTES (t));
}
diff --git a/gcc/cp/cxx-pretty-print.c b/gcc/cp/cxx-pretty-print.c
index a0088a2..038f300 100644
--- a/gcc/cp/cxx-pretty-print.c
+++ b/gcc/cp/cxx-pretty-print.c
@@ -3023,7 +3023,6 @@ pp_cxx_constraint (cxx_pretty_printer *pp, tree t)
}
}
-
typedef c_pretty_print_fn pp_fun;
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 36014dc..bb9d19a 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -1922,10 +1922,29 @@ duplicate_decls (tree newdecl, tree olddecl, bool newdecl_is_friend)
if (TREE_CODE (newdecl) == FUNCTION_DECL)
{
- if (merge_attr && diagnose_mismatched_attributes (olddecl, newdecl))
- inform (olddecl_loc, DECL_INITIAL (olddecl)
- ? G_("previous definition of %qD here")
- : G_("previous declaration of %qD here"), olddecl);
+ if (merge_attr)
+ {
+ if (diagnose_mismatched_attributes (olddecl, newdecl))
+ inform (olddecl_loc, DECL_INITIAL (olddecl)
+ ? G_("previous definition of %qD here")
+ : G_("previous declaration of %qD here"), olddecl);
+
+ /* [dcl.attr.noreturn]: The first declaration of a function shall
+ specify the noreturn attribute if any declaration of that function
+ specifies the noreturn attribute. */
+ tree a;
+ if (TREE_THIS_VOLATILE (newdecl)
+ && !TREE_THIS_VOLATILE (olddecl)
+ /* This applies to [[noreturn]] only, not its GNU variants. */
+ && (a = lookup_attribute ("noreturn", DECL_ATTRIBUTES (newdecl)))
+ && cxx11_attribute_p (a)
+ && get_attribute_namespace (a) == NULL_TREE)
+ {
+ error_at (newdecl_loc, "function %qD declared %<[[noreturn]]%> "
+ "but its first declaration was not", newdecl);
+ inform (olddecl_loc, "previous declaration of %qD", olddecl);
+ }
+ }
/* Now that functions must hold information normally held
by field decls, there is extra work to do so that
@@ -2025,9 +2044,10 @@ duplicate_decls (tree newdecl, tree olddecl, bool newdecl_is_friend)
tree old_result = DECL_TEMPLATE_RESULT (olddecl);
tree new_result = DECL_TEMPLATE_RESULT (newdecl);
TREE_TYPE (olddecl) = TREE_TYPE (old_result);
- DECL_TEMPLATE_SPECIALIZATIONS (olddecl)
- = chainon (DECL_TEMPLATE_SPECIALIZATIONS (olddecl),
- DECL_TEMPLATE_SPECIALIZATIONS (newdecl));
+
+ /* The new decl should not already have gathered any
+ specializations. */
+ gcc_assert (!DECL_TEMPLATE_SPECIALIZATIONS (newdecl));
DECL_ATTRIBUTES (old_result)
= (*targetm.merge_decl_attributes) (old_result, new_result);
@@ -3228,32 +3248,32 @@ check_previous_goto_1 (tree decl, cp_binding_level* level, tree names,
{
case sk_try:
if (!saw_eh)
- inf = N_("enters try block");
+ inf = G_(" enters %<try%> block");
saw_eh = true;
break;
case sk_catch:
if (!saw_eh)
- inf = N_("enters catch block");
+ inf = G_(" enters %<catch%> block");
saw_eh = true;
break;
case sk_omp:
if (!saw_omp)
- inf = N_("enters OpenMP structured block");
+ inf = G_(" enters OpenMP structured block");
saw_omp = true;
break;
case sk_transaction:
if (!saw_tm)
- inf = N_("enters synchronized or atomic statement");
+ inf = G_(" enters synchronized or atomic statement");
saw_tm = true;
break;
case sk_block:
if (!saw_cxif && level_for_constexpr_if (b->level_chain))
{
- inf = N_("enters constexpr if statement");
+ inf = G_(" enters %<constexpr if%> statement");
loc = EXPR_LOCATION (b->level_chain->this_entity);
saw_cxif = true;
}
@@ -3269,7 +3289,7 @@ check_previous_goto_1 (tree decl, cp_binding_level* level, tree names,
complained = identify_goto (decl, input_location, locus, DK_ERROR);
identified = 2;
if (complained)
- inform (loc, " %s", inf);
+ inform (loc, inf);
}
}
@@ -3364,7 +3384,7 @@ check_goto (tree decl)
identified = 2;
}
if (complained)
- inform (DECL_SOURCE_LOCATION (bad), " enters catch block");
+ inform (DECL_SOURCE_LOCATION (bad), " enters %<catch%> block");
saw_catch = true;
}
else if (complained)
@@ -3382,13 +3402,13 @@ check_goto (tree decl)
if (complained)
{
if (ent->in_try_scope)
- inform (input_location, " enters try block");
+ inform (input_location, " enters %<try%> block");
else if (ent->in_catch_scope && !saw_catch)
- inform (input_location, " enters catch block");
+ inform (input_location, " enters %<catch%> block");
else if (ent->in_transaction_scope)
inform (input_location, " enters synchronized or atomic statement");
else if (ent->in_constexpr_if)
- inform (input_location, " enters %<constexpr%> if statement");
+ inform (input_location, " enters %<constexpr if%> statement");
}
if (ent->in_omp_scope)
@@ -5078,7 +5098,8 @@ start_decl (const cp_declarator *declarator,
&& TREE_CODE (decl) == TYPE_DECL)
{
error_at (DECL_SOURCE_LOCATION (decl),
- "typedef %qD is initialized (use decltype instead)", decl);
+ "typedef %qD is initialized (use %qs instead)",
+ decl, "decltype");
return error_mark_node;
}
@@ -5129,7 +5150,7 @@ start_decl (const cp_declarator *declarator,
&& DECL_UNINLINABLE (decl)
&& lookup_attribute ("noinline", DECL_ATTRIBUTES (decl)))
warning_at (DECL_SOURCE_LOCATION (decl), 0,
- "inline function %qD given attribute noinline", decl);
+ "inline function %qD given attribute %qs", decl, "noinline");
if (TYPE_P (context) && COMPLETE_TYPE_P (complete_type (context)))
{
@@ -5701,7 +5722,7 @@ check_for_uninitialized_const_var (tree decl, bool constexpr_context_p,
{
if (complain & tf_error)
show_notes = permerror (DECL_SOURCE_LOCATION (decl),
- "uninitialized const %qD", decl);
+ "uninitialized %<const %D%>", decl);
}
else
{
@@ -6380,7 +6401,7 @@ build_aggr_init_full_exprs (tree decl, tree init, int flags)
static tree
check_initializer (tree decl, tree init, int flags, vec<tree, va_gc> **cleanups)
{
- tree type = TREE_TYPE (decl);
+ tree type;
tree init_code = NULL;
tree core_type;
@@ -7020,8 +7041,8 @@ cp_finish_decl (tree decl, tree init, bool init_const_expr_p,
return;
if (TREE_CODE (type) == FUNCTION_TYPE)
{
- error ("initializer for %<decltype(auto) %D%> has function type "
- "(did you forget the %<()%> ?)", decl);
+ error ("initializer for %<decltype(auto) %D%> has function type; "
+ "did you forget the %<()%>?", decl);
TREE_TYPE (decl) = error_mark_node;
return;
}
@@ -7590,7 +7611,7 @@ get_tuple_decomp_init (tree decl, unsigned i)
}
else
{
- vec<tree,va_gc> *args = make_tree_vector_single (e);
+ releasing_vec args (make_tree_vector_single (e));
fns = lookup_template_function (get__identifier, targs);
fns = perform_koenig_lookup (fns, args, tf_warning_or_error);
return finish_call_expr (fns, &args, /*novirt*/false,
@@ -7624,7 +7645,7 @@ cp_maybe_mangle_decomp (tree decl, tree first, unsigned int count)
{
if (!processing_template_decl
&& !error_operand_p (decl)
- && DECL_NAMESPACE_SCOPE_P (decl))
+ && TREE_STATIC (decl))
{
auto_vec<tree, 16> v;
v.safe_grow (count);
@@ -7855,8 +7876,27 @@ cp_finish_decomp (tree decl, tree first, unsigned int count)
DECL_HAS_VALUE_EXPR_P (v[i]) = 0;
}
if (!processing_template_decl)
- cp_finish_decl (v[i], init, /*constexpr*/false,
- /*asm*/NULL_TREE, LOOKUP_NORMAL);
+ {
+ TREE_PUBLIC (v[i]) = TREE_PUBLIC (decl);
+ TREE_STATIC (v[i]) = TREE_STATIC (decl);
+ DECL_COMMON (v[i]) = DECL_COMMON (decl);
+ DECL_COMDAT (v[i]) = DECL_COMDAT (decl);
+ if (TREE_STATIC (v[i]))
+ {
+ CP_DECL_THREAD_LOCAL_P (v[i])
+ = CP_DECL_THREAD_LOCAL_P (decl);
+ set_decl_tls_model (v[i], DECL_TLS_MODEL (decl));
+ if (DECL_ONE_ONLY (decl))
+ make_decl_one_only (v[i], cxx_comdat_group (v[i]));
+ if (TREE_PUBLIC (decl))
+ DECL_WEAK (v[i]) = DECL_WEAK (decl);
+ DECL_VISIBILITY (v[i]) = DECL_VISIBILITY (decl);
+ DECL_VISIBILITY_SPECIFIED (v[i])
+ = DECL_VISIBILITY_SPECIFIED (decl);
+ }
+ cp_finish_decl (v[i], init, /*constexpr*/false,
+ /*asm*/NULL_TREE, LOOKUP_NORMAL);
+ }
}
/* Ignore reads from the underlying decl performed during initialization
of the individual variables. If those will be read, we'll mark
@@ -8918,16 +8958,14 @@ grokfndecl (tree ctype,
the information in the TEMPLATE_ID_EXPR. */
SET_DECL_IMPLICIT_INSTANTIATION (decl);
- gcc_assert (identifier_p (fns)
- || TREE_CODE (fns) == OVERLOAD
- || TREE_CODE (fns) == FUNCTION_DECL);
+ gcc_assert (identifier_p (fns) || OVL_P (fns));
DECL_TEMPLATE_INFO (decl) = build_template_info (fns, args);
for (t = TYPE_ARG_TYPES (TREE_TYPE (decl)); t; t = TREE_CHAIN (t))
if (TREE_PURPOSE (t)
- && TREE_CODE (TREE_PURPOSE (t)) == DEFAULT_ARG)
+ && TREE_CODE (TREE_PURPOSE (t)) == DEFERRED_PARSE)
{
- error_at (defarg_location (TREE_PURPOSE (t)),
+ error_at (defparse_location (TREE_PURPOSE (t)),
"default arguments are not allowed in declaration "
"of friend template specialization %qD",
decl);
@@ -9129,7 +9167,7 @@ grokfndecl (tree ctype,
else if (long_double_p)
{
if (cpp_interpret_float_suffix (parse_in, suffix, strlen (suffix)))
- warning_at (location, 0, "floating point suffix %qs"
+ warning_at (location, 0, "floating-point suffix %qs"
" shadowed by implementation", suffix);
}
/* 17.6.3.3.5 */
@@ -9477,7 +9515,8 @@ grokvardecl (tree type,
if (DECL_NAME (decl)
&& MAIN_NAME_P (DECL_NAME (decl))
&& scope == global_namespace)
- error ("cannot declare %<::main%> to be a global variable");
+ error_at (DECL_SOURCE_LOCATION (decl),
+ "cannot declare %<::main%> to be a global variable");
/* Check that the variable can be safely declared as a concept.
Note that this also forbids explicit specializations. */
@@ -10091,6 +10130,15 @@ smallest_type_quals_location (int type_quals, const location_t* locations)
return loc;
}
+/* Returns the smallest among the latter and locations[ds_type_spec]. */
+
+static location_t
+smallest_type_location (int type_quals, const location_t* locations)
+{
+ location_t loc = smallest_type_quals_location (type_quals, locations);
+ return min_location (loc, locations[ds_type_spec]);
+}
+
/* Check that it's OK to declare a function with the indicated TYPE
and TYPE_QUALS. SFK indicates the kind of special function (if any)
that this function is. OPTYPE is the type given in a conversion
@@ -10109,7 +10157,8 @@ check_special_function_return_type (special_function_kind sfk,
{
case sfk_constructor:
if (type)
- error ("return type specification for constructor invalid");
+ error_at (smallest_type_location (type_quals, locations),
+ "return type specification for constructor invalid");
else if (type_quals != TYPE_UNQUALIFIED)
error_at (smallest_type_quals_location (type_quals, locations),
"qualifiers are not allowed on constructor declaration");
@@ -10122,7 +10171,8 @@ check_special_function_return_type (special_function_kind sfk,
case sfk_destructor:
if (type)
- error ("return type specification for destructor invalid");
+ error_at (smallest_type_location (type_quals, locations),
+ "return type specification for destructor invalid");
else if (type_quals != TYPE_UNQUALIFIED)
error_at (smallest_type_quals_location (type_quals, locations),
"qualifiers are not allowed on destructor declaration");
@@ -10137,7 +10187,8 @@ check_special_function_return_type (special_function_kind sfk,
case sfk_conversion:
if (type)
- error ("return type specified for %<operator %T%>", optype);
+ error_at (smallest_type_location (type_quals, locations),
+ "return type specified for %<operator %T%>", optype);
else if (type_quals != TYPE_UNQUALIFIED)
error_at (smallest_type_quals_location (type_quals, locations),
"qualifiers are not allowed on declaration of "
@@ -10148,7 +10199,8 @@ check_special_function_return_type (special_function_kind sfk,
case sfk_deduction_guide:
if (type)
- error ("return type specified for deduction guide");
+ error_at (smallest_type_location (type_quals, locations),
+ "return type specified for deduction guide");
else if (type_quals != TYPE_UNQUALIFIED)
error_at (smallest_type_quals_location (type_quals, locations),
"qualifiers are not allowed on declaration of "
@@ -10164,7 +10216,7 @@ check_special_function_return_type (special_function_kind sfk,
for (int i = 0; i < ds_last; ++i)
if (i != ds_explicit && locations[i])
error_at (locations[i],
- "decl-specifier in declaration of deduction guide");
+ "%<decl-specifier%> in declaration of deduction guide");
break;
default:
@@ -10233,15 +10285,12 @@ name_unnamed_type (tree type, tree decl)
/* Replace the anonymous name with the real name everywhere. */
for (tree t = TYPE_MAIN_VARIANT (type); t; t = TYPE_NEXT_VARIANT (t))
- {
- if (anon_aggrname_p (TYPE_IDENTIFIER (t)))
- /* We do not rename the debug info representing the
- unnamed tagged type because the standard says in
- [dcl.typedef] that the naming applies only for
- linkage purposes. */
- /*debug_hooks->set_name (t, decl);*/
- TYPE_NAME (t) = decl;
- }
+ if (IDENTIFIER_ANON_P (TYPE_IDENTIFIER (t)))
+ /* We do not rename the debug info representing the unnamed
+ tagged type because the standard says in [dcl.typedef] that
+ the naming applies only for linkage purposes. */
+ /*debug_hooks->set_name (t, decl);*/
+ TYPE_NAME (t) = decl;
if (TYPE_LANG_SPECIFIC (type))
TYPE_WAS_UNNAMED (type) = 1;
@@ -10319,6 +10368,7 @@ grokdeclarator (const cp_declarator *declarator,
tree type = NULL_TREE;
int longlong = 0;
int explicit_intN = 0;
+ int int_n_alt = 0;
int virtualp, explicitp, friendp, inlinep, staticp;
int explicit_int = 0;
int explicit_char = 0;
@@ -10392,6 +10442,7 @@ grokdeclarator (const cp_declarator *declarator,
long_p = decl_spec_seq_has_spec_p (declspecs, ds_long);
longlong = decl_spec_seq_has_spec_p (declspecs, ds_long_long);
explicit_intN = declspecs->explicit_intN_p;
+ int_n_alt = declspecs->int_n_alt;
thread_p = decl_spec_seq_has_spec_p (declspecs, ds_thread);
// Was concept_p specified? Note that ds_concept
@@ -10421,13 +10472,15 @@ grokdeclarator (const cp_declarator *declarator,
if (initialized > 1)
funcdef_flag = true;
- location_t typespec_loc = smallest_type_quals_location (type_quals,
- declspecs->locations);
- if (typespec_loc == UNKNOWN_LOCATION)
- typespec_loc = declspecs->locations[ds_type_spec];
+ location_t typespec_loc = smallest_type_location (type_quals,
+ declspecs->locations);
if (typespec_loc == UNKNOWN_LOCATION)
typespec_loc = input_location;
+ location_t id_loc = declarator ? declarator->id_loc : input_location;
+ if (id_loc == UNKNOWN_LOCATION)
+ id_loc = input_location;
+
/* Look inside a declarator for the name being declared
and get it as a string, for an error message. */
for (id_declarator = declarator;
@@ -10592,7 +10645,7 @@ grokdeclarator (const cp_declarator *declarator,
D1 ( parameter-declaration-clause) ... */
if (funcdef_flag && innermost_code != cdk_function)
{
- error ("function definition does not declare parameters");
+ error_at (id_loc, "function definition does not declare parameters");
return error_mark_node;
}
@@ -10600,7 +10653,7 @@ grokdeclarator (const cp_declarator *declarator,
&& innermost_code != cdk_function
&& ! (ctype && !declspecs->any_specifiers_p))
{
- error ("declaration of %qD as non-function", dname);
+ error_at (id_loc, "declaration of %qD as non-function", dname);
return error_mark_node;
}
@@ -10609,7 +10662,7 @@ grokdeclarator (const cp_declarator *declarator,
if (UDLIT_OPER_P (dname)
&& innermost_code != cdk_function)
{
- error ("declaration of %qD as non-function", dname);
+ error_at (id_loc, "declaration of %qD as non-function", dname);
return error_mark_node;
}
@@ -10617,12 +10670,12 @@ grokdeclarator (const cp_declarator *declarator,
{
if (typedef_p)
{
- error ("declaration of %qD as %<typedef%>", dname);
+ error_at (id_loc, "declaration of %qD as %<typedef%>", dname);
return error_mark_node;
}
else if (decl_context == PARM || decl_context == CATCHPARM)
{
- error ("declaration of %qD as parameter", dname);
+ error_at (id_loc, "declaration of %qD as parameter", dname);
return error_mark_node;
}
}
@@ -10672,13 +10725,16 @@ grokdeclarator (const cp_declarator *declarator,
issue an error message. */
if (declspecs->multiple_types_p)
{
- error ("two or more data types in declaration of %qs", name);
+ error_at (typespec_loc,
+ "two or more data types in declaration of %qs", name);
return error_mark_node;
}
if (declspecs->conflicting_specifiers_p)
{
- error ("conflicting specifiers in declaration of %qs", name);
+ error_at (min_location (declspecs->locations[ds_typedef],
+ declspecs->locations[ds_storage_class]),
+ "conflicting specifiers in declaration of %qs", name);
return error_mark_node;
}
@@ -10762,13 +10818,14 @@ grokdeclarator (const cp_declarator *declarator,
else if (in_system_header_at (input_location) || flag_ms_extensions)
/* Allow it, sigh. */;
else if (! is_main)
- permerror (input_location, "ISO C++ forbids declaration of %qs with no type", name);
+ permerror (id_loc, "ISO C++ forbids declaration of %qs with no type",
+ name);
else if (pedantic)
- pedwarn (input_location, OPT_Wpedantic,
+ pedwarn (id_loc, OPT_Wpedantic,
"ISO C++ forbids declaration of %qs with no type", name);
else
- warning (OPT_Wreturn_type,
- "ISO C++ forbids declaration of %qs with no type", name);
+ warning_at (id_loc, OPT_Wreturn_type,
+ "ISO C++ forbids declaration of %qs with no type", name);
if (type_was_error_mark_node && template_parm_flag)
/* FIXME we should be able to propagate the error_mark_node as is
@@ -10788,7 +10845,9 @@ grokdeclarator (const cp_declarator *declarator,
int_n_data[declspecs->int_n_idx].bitsize);
explicit_intN = false;
}
- else if (pedantic && ! in_system_header_at (input_location))
+ /* Don't pedwarn if the alternate "__intN__" form has been used instead
+ of "__intN". */
+ else if (!int_n_alt && pedantic && ! in_system_header_at (input_location))
pedwarn (input_location, OPT_Wpedantic,
"ISO C++ does not support %<__int%d%> for %qs",
int_n_data[declspecs->int_n_idx].bitsize, name);
@@ -11069,40 +11128,43 @@ grokdeclarator (const cp_declarator *declarator,
? declarator->declarator->id_loc : declarator->id_loc);
if (inlinep)
error_at (declspecs->locations[ds_inline],
- "structured binding declaration cannot be %<inline%>");
+ "structured binding declaration cannot be %qs", "inline");
if (typedef_p)
error_at (declspecs->locations[ds_typedef],
- "structured binding declaration cannot be %<typedef%>");
+ "structured binding declaration cannot be %qs", "typedef");
if (constexpr_p)
error_at (declspecs->locations[ds_constexpr], "structured "
- "binding declaration cannot be %<constexpr%>");
- if (thread_p)
- error_at (declspecs->locations[ds_thread],
- "structured binding declaration cannot be %qs",
- declspecs->gnu_thread_keyword_p
- ? "__thread" : "thread_local");
+ "binding declaration cannot be %qs", "constexpr");
+ if (thread_p && cxx_dialect < cxx2a)
+ pedwarn (declspecs->locations[ds_thread], 0,
+ "structured binding declaration can be %qs only in "
+ "%<-std=c++2a%> or %<-std=gnu++2a%>",
+ declspecs->gnu_thread_keyword_p
+ ? "__thread" : "thread_local");
if (concept_p)
error_at (declspecs->locations[ds_concept],
- "structured binding declaration cannot be %<concept%>");
+ "structured binding declaration cannot be %qs", "concept");
switch (storage_class)
{
case sc_none:
break;
case sc_register:
- error_at (loc, "structured binding declaration cannot be "
- "%<register%>");
+ error_at (loc, "structured binding declaration cannot be %qs",
+ "register");
break;
case sc_static:
- error_at (loc, "structured binding declaration cannot be "
- "%<static%>");
+ if (cxx_dialect < cxx2a)
+ pedwarn (loc, 0,
+ "structured binding declaration can be %qs only in "
+ "%<-std=c++2a%> or %<-std=gnu++2a%>", "static");
break;
case sc_extern:
- error_at (loc, "structured binding declaration cannot be "
- "%<extern%>");
+ error_at (loc, "structured binding declaration cannot be %qs",
+ "extern");
break;
case sc_mutable:
- error_at (loc, "structured binding declaration cannot be "
- "%<mutable%>");
+ error_at (loc, "structured binding declaration cannot be %qs",
+ "mutable");
break;
case sc_auto:
error_at (loc, "structured binding declaration cannot be "
@@ -11128,12 +11190,12 @@ grokdeclarator (const cp_declarator *declarator,
inlinep = 0;
typedef_p = 0;
constexpr_p = 0;
- thread_p = 0;
concept_p = 0;
- storage_class = sc_none;
- staticp = 0;
- declspecs->storage_class = sc_none;
- declspecs->locations[ds_thread] = UNKNOWN_LOCATION;
+ if (storage_class != sc_static)
+ {
+ storage_class = sc_none;
+ declspecs->storage_class = sc_none;
+ }
}
/* Static anonymous unions are dealt with here. */
@@ -11194,7 +11256,8 @@ grokdeclarator (const cp_declarator *declarator,
else if (toplevel_bindings_p ())
{
if (storage_class == sc_auto)
- error ("top-level declaration of %qs specifies %<auto%>", name);
+ error_at (declspecs->locations[ds_storage_class],
+ "top-level declaration of %qs specifies %<auto%>", name);
}
else if (thread_p
&& storage_class != sc_extern
@@ -11567,13 +11630,29 @@ grokdeclarator (const cp_declarator *declarator,
friendp = 0;
}
if (decl_context == NORMAL)
- error ("friend declaration not in class definition");
+ error_at (declarator->id_loc,
+ "friend declaration not in class definition");
if (current_function_decl && funcdef_flag)
{
- error ("can%'t define friend function %qs in a local "
- "class definition", name);
+ error_at (declarator->id_loc,
+ "cannot define friend function %qs in a local "
+ "class definition", name);
friendp = 0;
}
+ /* [class.friend]/6: A function can be defined in a friend
+ declaration if the function name is unqualified. */
+ if (funcdef_flag && in_namespace)
+ {
+ if (in_namespace == global_namespace)
+ error_at (declarator->id_loc,
+ "friend function definition %qs cannot have "
+ "a name qualified with %<::%>", name);
+ else
+ error_at (declarator->id_loc,
+ "friend function definition %qs cannot have "
+ "a name qualified with %<%D::%>", name,
+ in_namespace);
+ }
}
else if (ctype && sfk == sfk_conversion)
{
@@ -11825,6 +11904,8 @@ grokdeclarator (const cp_declarator *declarator,
}
}
+ id_loc = declarator ? declarator->id_loc : input_location;
+
/* A `constexpr' specifier used in an object declaration declares
the object as `const'. */
if (constexpr_p && innermost_code != cdk_function)
@@ -11840,8 +11921,7 @@ grokdeclarator (const cp_declarator *declarator,
}
if (unqualified_id && TREE_CODE (unqualified_id) == TEMPLATE_ID_EXPR
- && TREE_CODE (type) != FUNCTION_TYPE
- && TREE_CODE (type) != METHOD_TYPE
+ && !FUNC_OR_METHOD_TYPE_P (type)
&& !variable_template_p (TREE_OPERAND (unqualified_id, 0)))
{
error ("template-id %qD used as a declarator",
@@ -11869,13 +11949,13 @@ grokdeclarator (const cp_declarator *declarator,
{
if (friendp)
{
- permerror (input_location, "member functions are implicitly "
- "friends of their class");
+ permerror (declspecs->locations[ds_friend],
+ "member functions are implicitly "
+ "friends of their class");
friendp = 0;
}
else
- permerror (declarator->id_loc,
- "extra qualification %<%T::%> on member %qs",
+ permerror (id_loc, "extra qualification %<%T::%> on member %qs",
ctype, name);
}
else if (/* If the qualifying type is already complete, then we
@@ -11904,19 +11984,19 @@ grokdeclarator (const cp_declarator *declarator,
if (current_class_type
&& (!friendp || funcdef_flag || initialized))
{
- error (funcdef_flag || initialized
- ? G_("cannot define member function %<%T::%s%> "
- "within %qT")
- : G_("cannot declare member function %<%T::%s%> "
- "within %qT"),
- ctype, name, current_class_type);
+ error_at (id_loc, funcdef_flag || initialized
+ ? G_("cannot define member function %<%T::%s%> "
+ "within %qT")
+ : G_("cannot declare member function %<%T::%s%> "
+ "within %qT"),
+ ctype, name, current_class_type);
return error_mark_node;
}
}
else if (typedef_p && current_class_type)
{
- error ("cannot declare member %<%T::%s%> within %qT",
- ctype, name, current_class_type);
+ error_at (id_loc, "cannot declare member %<%T::%s%> within %qT",
+ ctype, name, current_class_type);
return error_mark_node;
}
}
@@ -11963,9 +12043,11 @@ grokdeclarator (const cp_declarator *declarator,
&& variably_modified_type_p (type, NULL_TREE))
{
if (decl_context == FIELD)
- error ("data member may not have variably modified type %qT", type);
+ error_at (id_loc,
+ "data member may not have variably modified type %qT", type);
else
- error ("parameter may not have variably modified type %qT", type);
+ error_at (id_loc,
+ "parameter may not have variably modified type %qT", type);
type = error_mark_node;
}
@@ -12003,8 +12085,7 @@ grokdeclarator (const cp_declarator *declarator,
name);
storage_class = sc_none;
}
- else if (TREE_CODE (type) == FUNCTION_TYPE
- || TREE_CODE (type) == METHOD_TYPE)
+ else if (FUNC_OR_METHOD_TYPE_P (type))
{
error_at (sloc, "function %qs cannot be declared %<mutable%>",
name);
@@ -12030,8 +12111,6 @@ grokdeclarator (const cp_declarator *declarator,
}
}
- location_t loc = declarator ? declarator->id_loc : input_location;
-
/* If this is declaring a typedef name, return a TYPE_DECL. */
if (typedef_p && decl_context != TYPENAME)
{
@@ -12072,14 +12151,14 @@ grokdeclarator (const cp_declarator *declarator,
if (id_declarator && declarator->u.id.qualifying_scope)
{
- error ("typedef name may not be a nested-name-specifier");
+ error_at (id_loc, "typedef name may not be a nested-name-specifier");
type = error_mark_node;
}
if (decl_context == FIELD)
- decl = build_lang_decl_loc (loc, TYPE_DECL, unqualified_id, type);
+ decl = build_lang_decl_loc (id_loc, TYPE_DECL, unqualified_id, type);
else
- decl = build_decl (loc, TYPE_DECL, unqualified_id, type);
+ decl = build_decl (id_loc, TYPE_DECL, unqualified_id, type);
if (decl_context != FIELD)
{
@@ -12096,7 +12175,7 @@ grokdeclarator (const cp_declarator *declarator,
}
else if (current_class_type
&& constructor_name_p (unqualified_id, current_class_type))
- permerror (input_location, "ISO C++ forbids nested type %qD with same name "
+ permerror (id_loc, "ISO C++ forbids nested type %qD with same name "
"as enclosing class",
unqualified_id);
@@ -12254,7 +12333,7 @@ grokdeclarator (const cp_declarator *declarator,
/* Only functions may be declared using an operator-function-id. */
if (dname && IDENTIFIER_ANY_OP_P (dname))
{
- error ("declaration of %qD as non-function", dname);
+ error_at (id_loc, "declaration of %qD as non-function", dname);
return error_mark_node;
}
@@ -12285,9 +12364,10 @@ grokdeclarator (const cp_declarator *declarator,
&& !(cxx_dialect >= cxx17 && template_parm_flag))
{
if (cxx_dialect >= cxx14)
- error ("%<auto%> parameter not permitted in this context");
+ error_at (typespec_loc,
+ "%<auto%> parameter not permitted in this context");
else
- error ("parameter declared %<auto%>");
+ error_at (typespec_loc, "parameter declared %<auto%>");
type = error_mark_node;
}
@@ -12364,8 +12444,8 @@ grokdeclarator (const cp_declarator *declarator,
if (in_system_header_at (input_location))
/* Do not warn on flexible array members in system
headers because glibc uses them. */;
- else if (name && declarator)
- pedwarn (declarator->id_loc, OPT_Wpedantic,
+ else if (name)
+ pedwarn (id_loc, OPT_Wpedantic,
"ISO C++ forbids flexible array member %qs", name);
else
pedwarn (input_location, OPT_Wpedantic,
@@ -12517,7 +12597,7 @@ grokdeclarator (const cp_declarator *declarator,
initialized == SD_DELETED, sfk,
funcdef_flag, late_return_type_p,
template_count, in_namespace,
- attrlist, declarator->id_loc);
+ attrlist, id_loc);
decl = set_virt_specifiers (decl, virt_specifiers);
if (decl == NULL_TREE)
return error_mark_node;
@@ -12550,8 +12630,7 @@ grokdeclarator (const cp_declarator *declarator,
{
if (unqualified_id)
{
- error_at (declarator->id_loc,
- "field %qD has incomplete type %qT",
+ error_at (id_loc, "field %qD has incomplete type %qT",
unqualified_id, type);
cxx_incomplete_type_inform (strip_array_types (type));
}
@@ -12566,8 +12645,8 @@ grokdeclarator (const cp_declarator *declarator,
{
if (friendp)
{
- if (unqualified_id && declarator)
- error_at (declarator->id_loc,
+ if (unqualified_id)
+ error_at (id_loc,
"%qE is neither function nor member function; "
"cannot be declared friend", unqualified_id);
else
@@ -12611,7 +12690,7 @@ grokdeclarator (const cp_declarator *declarator,
{
/* C++ allows static class members. All other work
for this is done by grokfield. */
- decl = build_lang_decl_loc (loc, VAR_DECL,
+ decl = build_lang_decl_loc (id_loc, VAR_DECL,
unqualified_id, type);
set_linkage_for_static_data_member (decl);
if (concept_p)
@@ -12659,7 +12738,7 @@ grokdeclarator (const cp_declarator *declarator,
unqualified_id);
constexpr_p = false;
}
- decl = build_decl (loc, FIELD_DECL, unqualified_id, type);
+ decl = build_decl (id_loc, FIELD_DECL, unqualified_id, type);
DECL_NONADDRESSABLE_P (decl) = bitfield;
if (bitfield && !unqualified_id)
{
@@ -12694,8 +12773,7 @@ grokdeclarator (const cp_declarator *declarator,
declspecs->locations);
}
}
- else if (TREE_CODE (type) == FUNCTION_TYPE
- || TREE_CODE (type) == METHOD_TYPE)
+ else if (FUNC_OR_METHOD_TYPE_P (type))
{
tree original_name;
int publicp = 0;
@@ -12710,9 +12788,12 @@ grokdeclarator (const cp_declarator *declarator,
// FIXME:gcc_assert (original_name == dname);
if (storage_class == sc_auto)
- error ("storage class %<auto%> invalid for function %qs", name);
+ error_at (declspecs->locations[ds_storage_class],
+ "storage class %<auto%> invalid for function %qs", name);
else if (storage_class == sc_register)
- error ("storage class %<register%> invalid for function %qs", name);
+ error_at (declspecs->locations[ds_storage_class],
+ "storage class %<register%> invalid for function %qs",
+ name);
else if (thread_p)
{
if (declspecs->gnu_thread_keyword_p)
@@ -12778,7 +12859,7 @@ grokdeclarator (const cp_declarator *declarator,
funcdef_flag,
late_return_type_p,
template_count, in_namespace, attrlist,
- declarator->id_loc);
+ id_loc);
if (decl == NULL_TREE)
return error_mark_node;
@@ -12825,7 +12906,7 @@ grokdeclarator (const cp_declarator *declarator,
concept_p,
template_count,
ctype ? ctype : in_namespace,
- loc);
+ id_loc);
if (decl == NULL_TREE)
return error_mark_node;
@@ -12871,7 +12952,7 @@ grokdeclarator (const cp_declarator *declarator,
if (innermost_code == cdk_decomp)
{
gcc_assert (declarator && declarator->kind == cdk_decomp);
- DECL_SOURCE_LOCATION (decl) = declarator->id_loc;
+ DECL_SOURCE_LOCATION (decl) = id_loc;
DECL_ARTIFICIAL (decl) = 1;
fit_decomposition_lang_decl (decl, NULL_TREE);
}
@@ -13012,8 +13093,8 @@ check_default_argument (tree decl, tree arg, tsubst_flags_t complain)
tree var;
tree decl_type;
- if (TREE_CODE (arg) == DEFAULT_ARG)
- /* We get a DEFAULT_ARG when looking at an in-class declaration
+ if (TREE_CODE (arg) == DEFERRED_PARSE)
+ /* We get a DEFERRED_PARSE when looking at an in-class declaration
with a default argument. Ignore the argument for now; we'll
deal with it after the class is complete. */
return arg;
@@ -13616,7 +13697,7 @@ grok_op_properties (tree decl, bool complain)
if (operator_code == COND_EXPR)
{
/* 13.4.0.3 */
- error_at (loc, "ISO C++ prohibits overloading operator ?:");
+ error_at (loc, "ISO C++ prohibits overloading %<operator ?:%>");
return false;
}
@@ -14064,7 +14145,7 @@ xref_tag_1 (enum tag_types tag_code, tree name,
/* In case of anonymous name, xref_tag is only called to
make type node and push name. Name lookup is not required. */
tree t = NULL_TREE;
- if (scope != ts_lambda && !anon_aggrname_p (name))
+ if (scope != ts_lambda && !IDENTIFIER_ANON_P (name))
t = lookup_and_check_tag (tag_code, name, scope, template_header_p);
if (t == error_mark_node)
@@ -14726,7 +14807,7 @@ finish_enum_value_list (tree enumtype)
if (TYPE_PRECISION (enumtype))
{
if (precision > TYPE_PRECISION (enumtype))
- error ("specified mode too small for enumeral values");
+ error ("specified mode too small for enumerated values");
else
{
use_short_enum = true;
@@ -15255,7 +15336,7 @@ start_preparsed_function (tree decl1, tree attrs, int flags)
if (DECL_DECLARED_INLINE_P (decl1)
&& lookup_attribute ("noinline", attrs))
warning_at (DECL_SOURCE_LOCATION (decl1), 0,
- "inline function %qD given attribute noinline", decl1);
+ "inline function %qD given attribute %qs", decl1, "noinline");
/* Handle gnu_inline attribute. */
if (GNU_INLINE_P (decl1))
@@ -15684,6 +15765,39 @@ use_eh_spec_block (tree fn)
&& !DECL_DEFAULTED_FN (fn));
}
+/* Helper function to push ARGS into the current lexical scope. DECL
+ is the function declaration. NONPARMS is used to handle enum
+ constants. */
+
+void
+do_push_parm_decls (tree decl, tree args, tree *nonparms)
+{
+ /* If we're doing semantic analysis, then we'll call pushdecl
+ for each of these. We must do them in reverse order so that
+ they end in the correct forward order. */
+ args = nreverse (args);
+
+ tree next;
+ for (tree parm = args; parm; parm = next)
+ {
+ next = DECL_CHAIN (parm);
+ if (TREE_CODE (parm) == PARM_DECL)
+ pushdecl (parm);
+ else if (nonparms)
+ {
+ /* If we find an enum constant or a type tag, put it aside for
+ the moment. */
+ TREE_CHAIN (parm) = NULL_TREE;
+ *nonparms = chainon (*nonparms, parm);
+ }
+ }
+
+ /* Get the decls in their original chain order and record in the
+ function. This is all and only the PARM_DECLs that were
+ pushed into scope by the loop above. */
+ DECL_ARGUMENTS (decl) = get_local_decls ();
+}
+
/* Store the parameter declarations into the current function declaration.
This is called after parsing the parameter declarations, before
digesting the body of the function.
@@ -15694,7 +15808,6 @@ static void
store_parm_decls (tree current_function_parms)
{
tree fndecl = current_function_decl;
- tree parm;
/* This is a chain of any other decls that came in among the parm
declarations. If a parm is declared with enum {foo, bar} x;
@@ -15709,35 +15822,12 @@ store_parm_decls (tree current_function_parms)
and complain if any redundant old-style parm decls were written. */
tree specparms = current_function_parms;
- tree next;
/* Must clear this because it might contain TYPE_DECLs declared
at class level. */
current_binding_level->names = NULL;
- /* If we're doing semantic analysis, then we'll call pushdecl
- for each of these. We must do them in reverse order so that
- they end in the correct forward order. */
- specparms = nreverse (specparms);
-
- for (parm = specparms; parm; parm = next)
- {
- next = DECL_CHAIN (parm);
- if (TREE_CODE (parm) == PARM_DECL)
- pushdecl (parm);
- else
- {
- /* If we find an enum constant or a type tag,
- put it aside for the moment. */
- TREE_CHAIN (parm) = NULL_TREE;
- nonparms = chainon (nonparms, parm);
- }
- }
-
- /* Get the decls in their original chain order and record in the
- function. This is all and only the PARM_DECLs that were
- pushed into scope by the loop above. */
- DECL_ARGUMENTS (fndecl) = get_local_decls ();
+ do_push_parm_decls (fndecl, specparms, &nonparms);
}
else
DECL_ARGUMENTS (fndecl) = NULL_TREE;
@@ -16575,7 +16665,7 @@ cp_tree_node_structure (union lang_tree_node * t)
{
switch (TREE_CODE (&t->generic))
{
- case DEFAULT_ARG: return TS_CP_DEFAULT_ARG;
+ case DEFERRED_PARSE: return TS_CP_DEFERRED_PARSE;
case DEFERRED_NOEXCEPT: return TS_CP_DEFERRED_NOEXCEPT;
case IDENTIFIER_NODE: return TS_CP_IDENTIFIER;
case OVERLOAD: return TS_CP_OVERLOAD;
diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c
index 6f23ee1..206f04c 100644
--- a/gcc/cp/decl2.c
+++ b/gcc/cp/decl2.c
@@ -158,8 +158,7 @@ build_memfn_type (tree fntype, tree ctype, cp_cv_quals quals,
if (fntype == error_mark_node || ctype == error_mark_node)
return error_mark_node;
- gcc_assert (TREE_CODE (fntype) == FUNCTION_TYPE
- || TREE_CODE (fntype) == METHOD_TYPE);
+ gcc_assert (FUNC_OR_METHOD_TYPE_P (fntype));
cp_cv_quals type_quals = quals & ~TYPE_QUAL_RESTRICT;
ctype = cp_build_qualified_type (ctype, type_quals);
@@ -831,7 +830,8 @@ grokfield (const cp_declarator *declarator,
if (TREE_CODE (value) == TYPE_DECL && init)
{
error_at (cp_expr_loc_or_loc (init, DECL_SOURCE_LOCATION (value)),
- "typedef %qD is initialized (use decltype instead)", value);
+ "typedef %qD is initialized (use %qs instead)",
+ value, "decltype");
init = NULL_TREE;
}
@@ -920,7 +920,7 @@ grokfield (const cp_declarator *declarator,
DECL_DECLARED_INLINE_P (value) = 1;
}
}
- else if (TREE_CODE (init) == DEFAULT_ARG)
+ else if (TREE_CODE (init) == DEFERRED_PARSE)
error ("invalid initializer for member function %qD", value);
else if (TREE_CODE (TREE_TYPE (value)) == METHOD_TYPE)
{
@@ -1773,12 +1773,13 @@ coerce_delete_type (tree decl, location_t loc)
else
/* A destroying operator delete shall be a class member function named
operator delete. */
- error_at (loc, "destroying operator delete must be a member function");
+ error_at (loc,
+ "destroying %<operator delete%> must be a member function");
const ovl_op_info_t *op = IDENTIFIER_OVL_OP_INFO (DECL_NAME (decl));
if (op->flags & OVL_OP_FLAG_VEC)
- error_at (loc, "operator delete[] cannot be a destroying delete");
+ error_at (loc, "%<operator delete[]%> cannot be a destroying delete");
if (!usual_deallocation_fn_p (decl))
- error_at (loc, "destroying operator delete must be a usual "
+ error_at (loc, "destroying %<operator delete%> must be a usual "
"deallocation function");
}
@@ -4248,6 +4249,8 @@ cpp_check (tree t, cpp_operation op)
}
case IS_ABSTRACT:
return DECL_PURE_VIRTUAL_P (t);
+ case IS_ASSIGNMENT_OPERATOR:
+ return DECL_ASSIGNMENT_OPERATOR_P (t);
case IS_CONSTRUCTOR:
return DECL_CONSTRUCTOR_P (t);
case IS_DESTRUCTOR:
diff --git a/gcc/cp/error.c b/gcc/cp/error.c
index 4a0aed2..baeba7e 100644
--- a/gcc/cp/error.c
+++ b/gcc/cp/error.c
@@ -738,14 +738,7 @@ dump_aggr_type (cxx_pretty_printer *pp, tree t, int flags)
name = DECL_NAME (name);
}
- if (name == 0 || anon_aggrname_p (name))
- {
- if (flags & TFF_CLASS_KEY_OR_ENUM)
- pp_string (pp, M_("<unnamed>"));
- else
- pp_printf (pp, M_("<unnamed %s>"), variety);
- }
- else if (LAMBDA_TYPE_P (t))
+ if (LAMBDA_TYPE_P (t))
{
/* A lambda's "type" is essentially its signature. */
pp_string (pp, M_("<lambda"));
@@ -755,8 +748,16 @@ dump_aggr_type (cxx_pretty_printer *pp, tree t, int flags)
flags);
pp_greater (pp);
}
+ else if (!name || IDENTIFIER_ANON_P (name))
+ {
+ if (flags & TFF_CLASS_KEY_OR_ENUM)
+ pp_string (pp, M_("<unnamed>"));
+ else
+ pp_printf (pp, M_("<unnamed %s>"), variety);
+ }
else
pp_cxx_tree_identifier (pp, name);
+
if (tmplate)
dump_template_parms (pp, TYPE_TEMPLATE_INFO (t),
!CLASSTYPE_USE_TEMPLATE (t),
@@ -2660,7 +2661,7 @@ dump_expr (cxx_pretty_printer *pp, tree t, int flags)
dump_expr (pp, TREE_OPERAND (t, 0), flags);
break;
- case DEFAULT_ARG:
+ case DEFERRED_PARSE:
pp_string (pp, M_("<unparsed>"));
break;
@@ -3049,8 +3050,8 @@ location_of (tree t)
if (DECL_P (t))
return DECL_SOURCE_LOCATION (t);
- if (TREE_CODE (t) == DEFAULT_ARG)
- return defarg_location (t);
+ if (TREE_CODE (t) == DEFERRED_PARSE)
+ return defparse_location (t);
return cp_expr_loc_or_loc (t, input_location);
}
diff --git a/gcc/cp/except.c b/gcc/cp/except.c
index afc2610..1f87c5a 100644
--- a/gcc/cp/except.c
+++ b/gcc/cp/except.c
@@ -756,7 +756,6 @@ build_throw (tree exp)
if (CLASS_TYPE_P (temp_type))
{
int flags = LOOKUP_NORMAL | LOOKUP_ONLYCONVERTING;
- vec<tree, va_gc> *exp_vec;
bool converted = false;
/* Under C++0x [12.8/16 class.copy], a thrown lvalue is sometimes
@@ -767,12 +766,11 @@ build_throw (tree exp)
&& !CP_TYPE_VOLATILE_P (TREE_TYPE (exp)))
{
tree moved = move (exp);
- exp_vec = make_tree_vector_single (moved);
+ releasing_vec exp_vec (make_tree_vector_single (moved));
moved = (build_special_member_call
(object, complete_ctor_identifier, &exp_vec,
TREE_TYPE (object), flags|LOOKUP_PREFER_RVALUE,
tf_none));
- release_tree_vector (exp_vec);
if (moved != error_mark_node)
{
exp = moved;
@@ -783,11 +781,10 @@ build_throw (tree exp)
/* Call the copy constructor. */
if (!converted)
{
- exp_vec = make_tree_vector_single (exp);
+ releasing_vec exp_vec (make_tree_vector_single (exp));
exp = (build_special_member_call
(object, complete_ctor_identifier, &exp_vec,
TREE_TYPE (object), flags, tf_warning_or_error));
- release_tree_vector (exp_vec);
}
if (exp == error_mark_node)
@@ -939,7 +936,7 @@ is_admissible_throw_operand_or_catch_parameter (tree t, bool is_throw)
&& TYPE_REF_P (type)
&& TYPE_REF_IS_RVALUE (type))
{
- error ("cannot declare catch parameter to be of rvalue "
+ error ("cannot declare %<catch%> parameter to be of rvalue "
"reference type %qT", type);
return false;
}
@@ -1248,6 +1245,7 @@ nothrow_spec_p (const_tree spec)
|| TREE_VALUE (spec)
|| spec == noexcept_false_spec
|| TREE_PURPOSE (spec) == error_mark_node
+ || UNPARSED_NOEXCEPT_SPEC_P (spec)
|| processing_template_decl);
return false;
@@ -1288,8 +1286,10 @@ build_noexcept_spec (tree expr, tsubst_flags_t complain)
if (TREE_CODE (expr) != DEFERRED_NOEXCEPT
&& !value_dependent_expression_p (expr))
{
+ expr = instantiate_non_dependent_expr_sfinae (expr, complain);
+ /* Don't let convert_like_real create more template codes. */
+ processing_template_decl_sentinel s;
expr = build_converted_constant_bool_expr (expr, complain);
- expr = instantiate_non_dependent_expr (expr);
expr = cxx_constant_value (expr);
}
if (TREE_CODE (expr) == INTEGER_CST)
diff --git a/gcc/cp/friend.c b/gcc/cp/friend.c
index 2429cd4c..4ea4bbc 100644
--- a/gcc/cp/friend.c
+++ b/gcc/cp/friend.c
@@ -638,9 +638,10 @@ do_friend (tree ctype, tree declarator, tree decl,
"%q#D declares a non-template function", decl);
if (! explained && warned)
{
- inform (input_location, "(if this is not what you intended, make sure "
- "the function template has already been declared "
- "and add <> after the function name here) ");
+ inform (input_location, "(if this is not what you intended, "
+ "make sure the function template has already been "
+ "declared and add %<<>%> after the function name "
+ "here)");
explained = 1;
}
}
diff --git a/gcc/cp/init.c b/gcc/cp/init.c
index 79a93a2..d0f73ff 100644
--- a/gcc/cp/init.c
+++ b/gcc/cp/init.c
@@ -564,7 +564,7 @@ get_nsdmi (tree member, bool in_ctor, tsubst_flags_t complain)
location_t expr_loc
= cp_expr_loc_or_loc (init, DECL_SOURCE_LOCATION (member));
tree *slot;
- if (TREE_CODE (init) == DEFAULT_ARG)
+ if (TREE_CODE (init) == DEFERRED_PARSE)
/* Unparsed. */;
else if (nsdmi_inst && (slot = nsdmi_inst->get (member)))
init = *slot;
@@ -629,7 +629,7 @@ get_nsdmi (tree member, bool in_ctor, tsubst_flags_t complain)
else
init = DECL_INITIAL (member);
- if (init && TREE_CODE (init) == DEFAULT_ARG)
+ if (init && TREE_CODE (init) == DEFERRED_PARSE)
{
if (complain & tf_error)
{
@@ -847,7 +847,7 @@ perform_member_init (tree member, tree init)
reference member in a constructor’s ctor-initializer (12.6.2)
persists until the constructor exits." */
unsigned i; tree t;
- vec<tree, va_gc> *cleanups = make_tree_vector ();
+ releasing_vec cleanups;
if (TREE_CODE (init) == TREE_LIST)
init = build_x_compound_expr_from_list (init, ELK_MEM_INIT,
tf_warning_or_error);
@@ -871,7 +871,6 @@ perform_member_init (tree member, tree init)
finish_expr_stmt (init);
FOR_EACH_VEC_ELT (*cleanups, i, t)
push_cleanup (decl, t, false);
- release_tree_vector (cleanups);
}
else if (type_build_ctor_call (type)
|| (init && CLASS_TYPE_P (strip_array_types (type))))
@@ -1952,7 +1951,7 @@ expand_default_init (tree binfo, tree true_exp, tree exp, tree init, int flags,
tree elt; unsigned i;
/* Unshare the arguments for the second call. */
- vec<tree, va_gc> *parms2 = make_tree_vector ();
+ releasing_vec parms2;
FOR_EACH_VEC_SAFE_ELT (parms, i, elt)
{
elt = break_out_target_exprs (elt);
@@ -1962,7 +1961,6 @@ expand_default_init (tree binfo, tree true_exp, tree exp, tree init, int flags,
&parms2, binfo, flags,
complain);
complete = fold_build_cleanup_point_expr (void_type_node, complete);
- release_tree_vector (parms2);
base = build_special_member_call (exp, base_ctor_identifier,
&parms, binfo, flags,
@@ -2341,8 +2339,11 @@ constant_value_1 (tree decl, bool strict_p, bool return_aggregate_cst_ok_p)
|| TREE_CODE (init) == STRING_CST)))
break;
/* Don't return a CONSTRUCTOR for a variable with partial run-time
- initialization, since it doesn't represent the entire value. */
- if (TREE_CODE (init) == CONSTRUCTOR
+ initialization, since it doesn't represent the entire value.
+ Similarly for VECTOR_CSTs created by cp_folding those
+ CONSTRUCTORs. */
+ if ((TREE_CODE (init) == CONSTRUCTOR
+ || TREE_CODE (init) == VECTOR_CST)
&& !DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (decl))
break;
/* If the variable has a dynamic initializer, don't use its
@@ -2850,8 +2851,7 @@ malloc_alignment ()
}
/* Determine whether an allocation function is a namespace-scope
- non-replaceable placement new function. See DR 1748.
- TODO: Enable in all standard modes. */
+ non-replaceable placement new function. See DR 1748. */
static bool
std_placement_new_fn_p (tree alloc_fn)
{
@@ -3007,7 +3007,7 @@ build_new_1 (vec<tree, va_gc> **placement, tree type, tree nelts,
pedwarn (cp_expr_loc_or_loc (outer_nelts, input_location), OPT_Wvla,
typedef_variant_p (orig_type)
? G_("non-constant array new length must be specified "
- "directly, not by typedef")
+ "directly, not by %<typedef%>")
: G_("non-constant array new length must be specified "
"without parentheses around the type-id"));
}
@@ -3018,13 +3018,13 @@ build_new_1 (vec<tree, va_gc> **placement, tree type, tree nelts,
if (VOID_TYPE_P (elt_type))
{
if (complain & tf_error)
- error ("invalid type %<void%> for new");
+ error ("invalid type %<void%> for %<new%>");
return error_mark_node;
}
if (is_std_init_list (elt_type))
warning (OPT_Winit_list_lifetime,
- "%<new%> of initializer_list does not "
+ "%<new%> of %<initializer_list%> does not "
"extend the lifetime of the underlying array");
if (abstract_virtuals_error_sfinae (ACU_NEW, elt_type, complain))
@@ -3869,11 +3869,11 @@ build_vec_delete_1 (tree base, tree maxindex, tree type,
auto_diagnostic_group d;
if (warning (OPT_Wdelete_incomplete,
"possible problem detected in invocation of "
- "delete [] operator:"))
+ "operator %<delete []%>"))
{
cxx_incomplete_type_diagnostic (base, type, DK_WARNING);
inform (input_location, "neither the destructor nor the "
- "class-specific operator delete [] will be called, "
+ "class-specific operator %<delete []%> will be called, "
"even if they are declared when the class is defined");
}
}
@@ -4755,14 +4755,14 @@ build_delete (tree otype, tree addr, special_function_kind auto_delete,
{
auto_diagnostic_group d;
if (warning (OPT_Wdelete_incomplete,
- "possible problem detected in invocation of "
- "delete operator:"))
+ "possible problem detected in invocation of "
+ "%<operator delete%>"))
{
cxx_incomplete_type_diagnostic (addr, type, DK_WARNING);
inform (input_location,
- "neither the destructor nor the class-specific "
- "operator delete will be called, even if they "
- "are declared when the class is defined");
+ "neither the destructor nor the class-specific "
+ "%<operator delete%> will be called, even if "
+ "they are declared when the class is defined");
}
}
}
diff --git a/gcc/cp/lambda.c b/gcc/cp/lambda.c
index 9366418..758773b 100644
--- a/gcc/cp/lambda.c
+++ b/gcc/cp/lambda.c
@@ -128,22 +128,15 @@ build_lambda_object (tree lambda_expr)
tree
begin_lambda_type (tree lambda)
{
- tree type;
+ /* Lambda names are nearly but not quite anonymous. */
+ tree name = make_anon_name ();
+ IDENTIFIER_LAMBDA_P (name) = true;
- {
- /* Unique name. This is just like an unnamed class, but we cannot use
- make_anon_name because of certain checks against TYPE_UNNAMED_P. */
- tree name;
- name = make_lambda_name ();
-
- /* Create the new RECORD_TYPE for this lambda. */
- type = xref_tag (/*tag_code=*/record_type,
- name,
- /*scope=*/ts_lambda,
- /*template_header_p=*/false);
- if (type == error_mark_node)
- return error_mark_node;
- }
+ /* Create the new RECORD_TYPE for this lambda. */
+ tree type = xref_tag (/*tag_code=*/record_type, name,
+ /*scope=*/ts_lambda, /*template_header_p=*/false);
+ if (type == error_mark_node)
+ return error_mark_node;
/* Designate it as a struct so that we can use aggregate initialization. */
CLASSTYPE_DECLARED_CLASS (type) = false;
@@ -420,7 +413,6 @@ build_capture_proxy (tree member, tree init)
type = build_cplus_array_type (TREE_TYPE (TREE_TYPE (ptr)),
build_index_type (max));
type = build_reference_type (type);
- REFERENCE_VLA_OK (type) = true;
object = convert (type, ptr);
}
diff --git a/gcc/cp/lex.c b/gcc/cp/lex.c
index 369ecc0..5bfb1e5 100644
--- a/gcc/cp/lex.c
+++ b/gcc/cp/lex.c
@@ -262,6 +262,11 @@ init_reswords (void)
id = get_identifier (name);
C_SET_RID_CODE (id, RID_FIRST_INT_N + i);
set_identifier_kind (id, cik_keyword);
+
+ sprintf (name, "__int%d__", int_n_data[i].bitsize);
+ id = get_identifier (name);
+ C_SET_RID_CODE (id, RID_FIRST_INT_N + i);
+ set_identifier_kind (id, cik_keyword);
}
}
@@ -385,14 +390,14 @@ parse_strconst_pragma (const char* name, int opt)
if (t == CPP_STRING)
{
if (pragma_lex (&x) != CPP_EOF)
- warning (0, "junk at end of #pragma %s", name);
+ warning (0, "junk at end of %<#pragma %s%>", name);
return result;
}
if (t == CPP_EOF && opt)
return NULL_TREE;
- error ("invalid #pragma %s", name);
+ error ("invalid %<#pragma %s%>", name);
return error_mark_node;
}
@@ -400,7 +405,7 @@ static void
handle_pragma_vtable (cpp_reader* /*dfile*/)
{
parse_strconst_pragma ("vtable", 0);
- sorry ("#pragma vtable no longer supported");
+ sorry ("%<#pragma vtable%> no longer supported");
}
static void
@@ -472,7 +477,7 @@ handle_pragma_implementation (cpp_reader* /*dfile*/)
{
filename = TREE_STRING_POINTER (fname);
if (cpp_included_before (parse_in, filename, input_location))
- warning (0, "#pragma implementation for %qs appears after "
+ warning (0, "%<#pragma implementation%> for %qs appears after "
"file is included", filename);
}
@@ -568,8 +573,8 @@ unqualified_fn_lookup_error (cp_expr name_expr)
if (!hint)
{
inform (loc, "(if you use %<-fpermissive%>, G++ will accept your "
- "code, but allowing the use of an undeclared name is "
- "deprecated)");
+ "code, but allowing the use of an undeclared name is "
+ "deprecated)");
hint = true;
}
}
@@ -884,6 +889,9 @@ cxx_make_type (enum tree_code code MEM_STAT_DECL)
CLASSTYPE_INTERFACE_ONLY (t) = finfo->interface_only;
}
+ if (code == RECORD_TYPE || code == UNION_TYPE)
+ TYPE_CXX_ODR_P (t) = 1;
+
return t;
}
diff --git a/gcc/cp/mangle.c b/gcc/cp/mangle.c
index 4b22123..4d6f580 100644
--- a/gcc/cp/mangle.c
+++ b/gcc/cp/mangle.c
@@ -414,8 +414,7 @@ canonicalize_for_substitution (tree node)
else
node = cp_build_qualified_type (TYPE_MAIN_VARIANT (node),
cp_type_quals (node));
- if (TREE_CODE (node) == FUNCTION_TYPE
- || TREE_CODE (node) == METHOD_TYPE)
+ if (FUNC_OR_METHOD_TYPE_P (node))
{
node = build_ref_qualified_type (node, type_memfn_rqual (orig));
tree r = canonical_eh_spec (TYPE_RAISES_EXCEPTIONS (orig));
@@ -2005,8 +2004,7 @@ write_local_name (tree function, const tree local_entity,
write_name (entity, /*ignore_local_scope=*/1);
if (DECL_DISCRIMINATOR_P (local_entity)
&& !(TREE_CODE (local_entity) == TYPE_DECL
- && (LAMBDA_TYPE_P (TREE_TYPE (local_entity))
- || TYPE_UNNAMED_P (TREE_TYPE (local_entity)))))
+ && TYPE_ANON_P (TREE_TYPE (local_entity))))
write_discriminator (discriminator_for_local_entity (local_entity));
}
}
@@ -2070,8 +2068,7 @@ write_type (tree type)
t = cp_build_type_attribute_variant (t, attrs);
}
gcc_assert (t != type);
- if (TREE_CODE (t) == FUNCTION_TYPE
- || TREE_CODE (t) == METHOD_TYPE)
+ if (FUNC_OR_METHOD_TYPE_P (t))
{
t = build_ref_qualified_type (t, type_memfn_rqual (type));
if (flag_noexcept_type)
@@ -2102,8 +2099,7 @@ write_type (tree type)
/* See through any typedefs. */
type = TYPE_MAIN_VARIANT (type);
- if (TREE_CODE (type) == FUNCTION_TYPE
- || TREE_CODE (type) == METHOD_TYPE)
+ if (FUNC_OR_METHOD_TYPE_P (type))
type = cxx_copy_lang_qualifiers (type, type_orig);
/* According to the C++ ABI, some library classes are passed the
@@ -2308,11 +2304,11 @@ write_type (tree type)
break;
case TYPEOF_TYPE:
- sorry ("mangling typeof, use decltype instead");
+ sorry ("mangling %<typeof%>, use %<decltype%> instead");
break;
case UNDERLYING_TYPE:
- sorry ("mangling __underlying_type");
+ sorry ("mangling %<__underlying_type%>");
break;
case LANG_TYPE:
@@ -3281,8 +3277,7 @@ write_expression (tree expr)
/* Mangle a dependent name as the name, not whatever happens to
be the first function in the overload set. */
- if ((TREE_CODE (fn) == FUNCTION_DECL
- || TREE_CODE (fn) == OVERLOAD)
+ if (OVL_P (fn)
&& type_dependent_expression_p_push (expr))
fn = OVL_NAME (fn);
diff --git a/gcc/cp/method.c b/gcc/cp/method.c
index 9ebc99e..53fa85b 100644
--- a/gcc/cp/method.c
+++ b/gcc/cp/method.c
@@ -790,7 +790,6 @@ do_build_copy_assign (tree fndecl)
BINFO_BASE_ITERATE (binfo, i, base_binfo); i++)
{
tree converted_parm;
- vec<tree, va_gc> *parmvec;
/* We must convert PARM directly to the base class
explicitly since the base class may be ambiguous. */
@@ -799,7 +798,7 @@ do_build_copy_assign (tree fndecl)
if (move_p)
converted_parm = move (converted_parm);
/* Call the base class assignment operator. */
- parmvec = make_tree_vector_single (converted_parm);
+ releasing_vec parmvec (make_tree_vector_single (converted_parm));
finish_expr_stmt
(build_special_member_call (current_class_ref,
assign_op_identifier,
@@ -807,7 +806,6 @@ do_build_copy_assign (tree fndecl)
base_binfo,
flags,
tf_warning_or_error));
- release_tree_vector (parmvec);
}
/* Assign to each of the non-static data members. */
@@ -828,13 +826,13 @@ do_build_copy_assign (tree fndecl)
if (CP_TYPE_CONST_P (expr_type))
{
- error ("non-static const member %q#D, can%'t use default "
+ error ("non-static const member %q#D, cannot use default "
"assignment operator", field);
continue;
}
else if (TYPE_REF_P (expr_type))
{
- error ("non-static reference member %q#D, can%'t use "
+ error ("non-static reference member %q#D, cannot use "
"default assignment operator", field);
continue;
}
@@ -993,7 +991,6 @@ locate_fn_flags (tree type, tree name, tree argtype, int flags,
tsubst_flags_t complain)
{
tree ob, fn, fns, binfo, rval;
- vec<tree, va_gc> *args;
if (TYPE_P (type))
binfo = TYPE_BINFO (type);
@@ -1004,7 +1001,7 @@ locate_fn_flags (tree type, tree name, tree argtype, int flags,
}
ob = build_stub_object (cp_build_reference_type (type, false));
- args = make_tree_vector ();
+ releasing_vec args;
if (argtype)
{
if (TREE_CODE (argtype) == TREE_LIST)
@@ -1027,7 +1024,6 @@ locate_fn_flags (tree type, tree name, tree argtype, int flags,
fns = lookup_fnfields (binfo, name, 0);
rval = build_new_method_call (ob, fns, &args, binfo, flags, &fn, complain);
- release_tree_vector (args);
if (fn && rval == error_mark_node)
return rval;
else
@@ -1205,6 +1201,8 @@ is_xible_helper (enum tree_code code, tree to, tree from, bool trivial)
expr = assignable_expr (to, from);
else if (trivial && from && TREE_CHAIN (from))
return error_mark_node; // only 0- and 1-argument ctors can be trivial
+ else if (TREE_CODE (to) == ARRAY_TYPE && !TYPE_DOMAIN (to))
+ return error_mark_node; // can't construct an array of unknown bound
else
expr = constructible_expr (to, from);
return expr;
@@ -1340,13 +1338,13 @@ walk_field_subobs (tree fields, special_function_kind sfk, tree fnname,
if (CP_TYPE_CONST_P (mem_type) && !CLASS_TYPE_P (mem_type))
{
if (diag)
- error ("non-static const member %q#D, can%'t use default "
+ error ("non-static const member %q#D, cannot use default "
"assignment operator", field);
}
else if (TYPE_REF_P (mem_type))
{
if (diag)
- error ("non-static reference member %q#D, can%'t use "
+ error ("non-static reference member %q#D, cannot use "
"default assignment operator", field);
}
else
@@ -2252,8 +2250,8 @@ defaulted_late_check (tree fn)
if (!CLASSTYPE_TEMPLATE_INSTANTIATION (ctx))
{
error ("explicitly defaulted function %q+D cannot be declared "
- "as %<constexpr%> because the implicit declaration is not "
- "%<constexpr%>:", fn);
+ "%qs because the implicit declaration is not %qs:",
+ fn, "constexpr", "constexpr");
explain_implicit_non_constexpr (fn);
}
DECL_DECLARED_CONSTEXPR_P (fn) = false;
diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c
index 89d85f6..f4c34ed 100644
--- a/gcc/cp/name-lookup.c
+++ b/gcc/cp/name-lookup.c
@@ -589,7 +589,7 @@ name_lookup::search_usings (tree scope)
return true;
bool found = false;
- if (vec<tree, va_gc> *usings = DECL_NAMESPACE_USING (scope))
+ if (vec<tree, va_gc> *usings = NAMESPACE_LEVEL (scope)->using_directives)
for (unsigned ix = usings->length (); ix--;)
found |= search_qualified ((*usings)[ix], true);
@@ -651,7 +651,7 @@ name_lookup::queue_namespace (using_queue *queue, int depth, tree scope)
queue = queue_namespace (queue, depth, (*inlinees)[ix]);
/* Queue its using targets. */
- queue = queue_usings (queue, depth, DECL_NAMESPACE_USING (scope));
+ queue = queue_usings (queue, depth, NAMESPACE_LEVEL (scope)->using_directives);
return queue;
}
@@ -3270,10 +3270,10 @@ cp_binding_level_debug (cp_binding_level *scope, int line, const char *action)
{
const char *desc = cp_binding_level_descriptor (scope);
if (scope->this_entity)
- verbatim ("%s %<%s(%E)%> %p %d\n", action, desc,
+ verbatim ("%s %<%s(%E)%> %p %d", action, desc,
scope->this_entity, (void *) scope, line);
else
- verbatim ("%s %s %p %d\n", action, desc, (void *) scope, line);
+ verbatim ("%s %s %p %d", action, desc, (void *) scope, line);
}
/* A chain of binding_level structures awaiting reuse. */
@@ -3797,74 +3797,6 @@ constructor_name_p (tree name, tree type)
return false;
}
-/* Counter used to create anonymous type names. */
-
-static GTY(()) int anon_cnt;
-
-/* Return an IDENTIFIER which can be used as a name for
- unnamed structs and unions. */
-
-tree
-make_anon_name (void)
-{
- char buf[32];
-
- sprintf (buf, anon_aggrname_format (), anon_cnt++);
- return get_identifier (buf);
-}
-
-/* This code is practically identical to that for creating
- anonymous names, but is just used for lambdas instead. This isn't really
- necessary, but it's convenient to avoid treating lambdas like other
- unnamed types. */
-
-static GTY(()) int lambda_cnt = 0;
-
-tree
-make_lambda_name (void)
-{
- char buf[32];
-
- sprintf (buf, LAMBDANAME_FORMAT, lambda_cnt++);
- return get_identifier (buf);
-}
-
-/* Insert another USING_DECL into the current binding level, returning
- this declaration. If this is a redeclaration, do nothing, and
- return NULL_TREE if this not in namespace scope (in namespace
- scope, a using decl might extend any previous bindings). */
-
-static tree
-push_using_decl_1 (tree scope, tree name)
-{
- tree decl;
-
- gcc_assert (TREE_CODE (scope) == NAMESPACE_DECL);
- gcc_assert (identifier_p (name));
- for (decl = current_binding_level->usings; decl; decl = DECL_CHAIN (decl))
- if (USING_DECL_SCOPE (decl) == scope && DECL_NAME (decl) == name)
- break;
- if (decl)
- return namespace_bindings_p () ? decl : NULL_TREE;
- decl = build_lang_decl (USING_DECL, name, NULL_TREE);
- USING_DECL_SCOPE (decl) = scope;
- DECL_CHAIN (decl) = current_binding_level->usings;
- current_binding_level->usings = decl;
- return decl;
-}
-
-/* Wrapper for push_using_decl_1. */
-
-static tree
-push_using_decl (tree scope, tree name)
-{
- tree ret;
- timevar_start (TV_NAME_LOOKUP);
- ret = push_using_decl_1 (scope, name);
- timevar_stop (TV_NAME_LOOKUP);
- return ret;
-}
-
/* Same as pushdecl, but define X in binding-level LEVEL. We rely on the
caller to set DECL_CONTEXT properly.
@@ -3918,91 +3850,20 @@ pushdecl_outermost_localscope (tree x)
return ret;
}
-/* Check a non-member using-declaration. Return the name and scope
- being used, and the USING_DECL, or NULL_TREE on failure. */
-
-static tree
-validate_nonmember_using_decl (tree decl, tree scope, tree name)
-{
- /* [namespace.udecl]
- A using-declaration for a class member shall be a
- member-declaration. */
- if (TYPE_P (scope))
- {
- error ("%qT is not a namespace or unscoped enum", scope);
- return NULL_TREE;
- }
- else if (scope == error_mark_node)
- return NULL_TREE;
-
- if (TREE_CODE (decl) == TEMPLATE_ID_EXPR)
- {
- /* 7.3.3/5
- A using-declaration shall not name a template-id. */
- error ("a using-declaration cannot specify a template-id. "
- "Try %<using %D%>", name);
- return NULL_TREE;
- }
-
- if (TREE_CODE (decl) == NAMESPACE_DECL)
- {
- error ("namespace %qD not allowed in using-declaration", decl);
- return NULL_TREE;
- }
-
- if (TREE_CODE (decl) == SCOPE_REF)
- {
- /* It's a nested name with template parameter dependent scope.
- This can only be using-declaration for class member. */
- error ("%qT is not a namespace", TREE_OPERAND (decl, 0));
- return NULL_TREE;
- }
-
- decl = OVL_FIRST (decl);
-
- /* Make a USING_DECL. */
- tree using_decl = push_using_decl (scope, name);
-
- if (using_decl == NULL_TREE
- && at_function_scope_p ()
- && VAR_P (decl))
- /* C++11 7.3.3/10. */
- error ("%qD is already declared in this scope", name);
-
- return using_decl;
-}
-
-/* Process a local-scope or namespace-scope using declaration. SCOPE
- is the nominated scope to search for NAME. VALUE_P and TYPE_P
- point to the binding for NAME in the current scope and are
- updated. */
+/* Process a local-scope or namespace-scope using declaration. LOOKUP
+ is the result of qualified lookup (both value & type are
+ significant). FN_SCOPE_P indicates if we're at function-scope (as
+ opposed to namespace-scope). *VALUE_P and *TYPE_P are the current
+ bindings, which are altered to reflect the newly brought in
+ declarations. */
-static void
-do_nonmember_using_decl (tree scope, tree name, tree *value_p, tree *type_p)
+static bool
+do_nonmember_using_decl (name_lookup &lookup, bool fn_scope_p,
+ tree *value_p, tree *type_p)
{
- name_lookup lookup (name, 0);
-
- if (!qualified_namespace_lookup (scope, &lookup))
- {
- error ("%qD not declared", name);
- return;
- }
- else if (TREE_CODE (lookup.value) == TREE_LIST)
- {
- error ("reference to %qD is ambiguous", name);
- print_candidates (lookup.value);
- lookup.value = NULL_TREE;
- }
-
- if (lookup.type && TREE_CODE (lookup.type) == TREE_LIST)
- {
- error ("reference to %qD is ambiguous", name);
- print_candidates (lookup.type);
- lookup.type = NULL_TREE;
- }
-
tree value = *value_p;
tree type = *type_p;
+ bool failed = false;
/* Shift the old and new bindings around so we're comparing class and
enumeration names to each other. */
@@ -4018,79 +3879,92 @@ do_nonmember_using_decl (tree scope, tree name, tree *value_p, tree *type_p)
lookup.value = NULL_TREE;
}
- if (lookup.value && lookup.value != value)
+ if (!lookup.value)
+ /* Nothing. */;
+ else if (OVL_P (lookup.value) && (!value || OVL_P (value)))
{
- /* Check for using functions. */
- if (OVL_P (lookup.value) && (!value || OVL_P (value)))
+ for (lkp_iterator usings (lookup.value); usings; ++usings)
{
- for (lkp_iterator usings (lookup.value); usings; ++usings)
- {
- tree new_fn = *usings;
+ tree new_fn = *usings;
+
+ /* [namespace.udecl]
- /* [namespace.udecl]
+ If a function declaration in namespace scope or block
+ scope has the same name and the same parameter types as a
+ function introduced by a using declaration the program is
+ ill-formed. */
+ bool found = false;
+ for (ovl_iterator old (value); !found && old; ++old)
+ {
+ tree old_fn = *old;
- If a function declaration in namespace scope or block
- scope has the same name and the same parameter types as a
- function introduced by a using declaration the program is
- ill-formed. */
- bool found = false;
- for (ovl_iterator old (value); !found && old; ++old)
+ if (new_fn == old_fn)
{
- tree old_fn = *old;
-
- if (new_fn == old_fn)
- /* The function already exists in the current
- namespace. */
- found = true;
- else if (old.using_p ())
- continue; /* This is a using decl. */
- else if (old.hidden_p () && !DECL_HIDDEN_FRIEND_P (old_fn))
- continue; /* This is an anticipated builtin. */
- else if (!matching_fn_p (new_fn, old_fn))
- continue; /* Parameters do not match. */
- else if (decls_match (new_fn, old_fn))
- found = true;
- else
- {
- diagnose_name_conflict (new_fn, old_fn);
- found = true;
- }
+ /* The function already exists in the current
+ namespace. */
+ found = true;
+ break;
+ }
+ else if (old.using_p ())
+ continue; /* This is a using decl. */
+ else if (old.hidden_p () && !DECL_HIDDEN_FRIEND_P (old_fn))
+ continue; /* This is an anticipated builtin. */
+ else if (!matching_fn_p (new_fn, old_fn))
+ continue; /* Parameters do not match. */
+ else if (decls_match (new_fn, old_fn))
+ {
+ /* Extern "C" in different namespaces. */
+ found = true;
+ break;
+ }
+ else
+ {
+ diagnose_name_conflict (new_fn, old_fn);
+ failed = true;
+ found = true;
+ break;
}
-
- if (!found)
- /* Unlike the overload case we don't drop anticipated
- builtins here. They don't cause a problem, and
- we'd like to match them with a future
- declaration. */
- value = ovl_insert (new_fn, value, true);
}
+
+ if (!found)
+ /* Unlike the decl-pushing case we don't drop anticipated
+ builtins here. They don't cause a problem, and we'd
+ like to match them with a future declaration. */
+ value = ovl_insert (new_fn, value, true);
}
- else if (value
- /* Ignore anticipated builtins. */
- && !anticipated_builtin_p (value)
- && !decls_match (lookup.value, value))
- diagnose_name_conflict (lookup.value, value);
- else
- value = lookup.value;
}
+ else if (value
+ /* Ignore anticipated builtins. */
+ && !anticipated_builtin_p (value)
+ && (fn_scope_p || !decls_match (lookup.value, value)))
+ {
+ diagnose_name_conflict (lookup.value, value);
+ failed = true;
+ }
+ else
+ value = lookup.value;
if (lookup.type && lookup.type != type)
{
if (type && !decls_match (lookup.type, type))
- diagnose_name_conflict (lookup.type, type);
+ {
+ diagnose_name_conflict (lookup.type, type);
+ failed = true;
+ }
else
type = lookup.type;
}
- /* If bind->value is empty, shift any class or enumeration name back. */
+ /* If value is empty, shift any class or enumeration name back. */
if (!value)
{
value = type;
type = NULL_TREE;
}
-
*value_p = value;
*type_p = type;
+
+ return failed;
}
/* Returns true if ANCESTOR encloses DESCENDANT, including matching.
@@ -5120,84 +4994,114 @@ pushdecl_namespace_level (tree x, bool is_friend)
return t;
}
-/* Process a using-declaration appearing in namespace scope. */
+/* Process a using declaration in non-class scope. */
void
-finish_namespace_using_decl (tree decl, tree scope, tree name)
+finish_nonmember_using_decl (tree scope, tree name)
{
- tree orig_decl = decl;
+ gcc_checking_assert (current_binding_level->kind != sk_class);
+ gcc_checking_assert (identifier_p (name));
- gcc_checking_assert (current_binding_level->kind == sk_namespace
- && !processing_template_decl);
- decl = validate_nonmember_using_decl (decl, scope, name);
- if (decl == NULL_TREE)
- return;
+ name_lookup lookup (name, 0);
- tree *slot = find_namespace_slot (current_namespace, name, true);
- tree val = slot ? MAYBE_STAT_DECL (*slot) : NULL_TREE;
- tree type = slot ? MAYBE_STAT_TYPE (*slot) : NULL_TREE;
- do_nonmember_using_decl (scope, name, &val, &type);
- if (STAT_HACK_P (*slot))
+ if (TREE_CODE (scope) != NAMESPACE_DECL)
{
- STAT_DECL (*slot) = val;
- STAT_TYPE (*slot) = type;
+ error ("%qE is not a namespace or unscoped enum", scope);
+ return;
}
- else if (type)
- *slot = stat_hack (val, type);
- else
- *slot = val;
- /* Emit debug info. */
- cp_emit_debug_info_for_using (orig_decl, current_namespace);
-}
+ qualified_namespace_lookup (scope, &lookup);
-/* Process a using-declaration at function scope. */
+ if (!lookup.value)
+ {
+ error ("%qD has not been declared in %qE", name, scope);
+ return;
+ }
-void
-finish_local_using_decl (tree decl, tree scope, tree name)
-{
- tree orig_decl = decl;
+ if (TREE_CODE (lookup.value) == TREE_LIST
+ /* But we can (independently) have ambiguous implicit typedefs. */
+ || (lookup.type && TREE_CODE (lookup.type) == TREE_LIST))
+ {
+ error ("reference to %qD is ambiguous", name);
+ print_candidates (TREE_CODE (lookup.value) == TREE_LIST
+ ? lookup.value : lookup.type);
+ return;
+ }
- gcc_checking_assert (current_binding_level->kind != sk_class
- && current_binding_level->kind != sk_namespace);
- decl = validate_nonmember_using_decl (decl, scope, name);
- if (decl == NULL_TREE)
- return;
+ if (TREE_CODE (lookup.value) == NAMESPACE_DECL)
+ {
+ error ("using-declaration may not name namespace %qD", lookup.value);
+ return;
+ }
- add_decl_expr (decl);
+ /* Emit debug info. */
+ if (!processing_template_decl)
+ cp_emit_debug_info_for_using (lookup.value,
+ current_binding_level->this_entity);
- cxx_binding *binding = find_local_binding (current_binding_level, name);
- tree value = binding ? binding->value : NULL_TREE;
- tree type = binding ? binding->type : NULL_TREE;
+ if (current_binding_level->kind == sk_namespace)
+ {
+ tree *slot = find_namespace_slot (current_namespace, name, true);
- do_nonmember_using_decl (scope, name, &value, &type);
+ tree value = MAYBE_STAT_DECL (*slot);
+ tree type = MAYBE_STAT_TYPE (*slot);
- if (!value)
- ;
- else if (binding && value == binding->value)
- ;
- else if (binding && binding->value && TREE_CODE (value) == OVERLOAD)
- {
- update_local_overload (IDENTIFIER_BINDING (name), value);
- IDENTIFIER_BINDING (name)->value = value;
- }
- else
- /* Install the new binding. */
- push_local_binding (name, value, true);
+ do_nonmember_using_decl (lookup, false, &value, &type);
- if (!type)
- ;
- else if (binding && type == binding->type)
- ;
+ if (STAT_HACK_P (*slot))
+ {
+ STAT_DECL (*slot) = value;
+ STAT_TYPE (*slot) = type;
+ }
+ else if (type)
+ *slot = stat_hack (value, type);
+ else
+ *slot = value;
+ }
else
{
- push_local_binding (name, type, true);
- set_identifier_type_value (name, type);
+ tree using_decl = build_lang_decl (USING_DECL, name, NULL_TREE);
+ USING_DECL_SCOPE (using_decl) = scope;
+ add_decl_expr (using_decl);
+
+ cxx_binding *binding = find_local_binding (current_binding_level, name);
+ tree value = NULL;
+ tree type = NULL;
+ if (binding)
+ {
+ value = binding->value;
+ type = binding->type;
+ }
+
+ /* DR 36 questions why using-decls at function scope may not be
+ duplicates. Disallow it, as C++11 claimed and PR 20420
+ implemented. */
+ do_nonmember_using_decl (lookup, true, &value, &type);
+
+ if (!value)
+ ;
+ else if (binding && value == binding->value)
+ ;
+ else if (binding && binding->value && TREE_CODE (value) == OVERLOAD)
+ {
+ update_local_overload (IDENTIFIER_BINDING (name), value);
+ IDENTIFIER_BINDING (name)->value = value;
+ }
+ else
+ /* Install the new binding. */
+ push_local_binding (name, value, true);
+
+ if (!type)
+ ;
+ else if (binding && type == binding->type)
+ ;
+ else
+ {
+ push_local_binding (name, type, true);
+ set_identifier_type_value (name, type);
+ }
}
- /* Emit debug info. */
- if (!processing_template_decl)
- cp_emit_debug_info_for_using (orig_decl, current_scope ());
}
/* Return the declarations that are members of the namespace NS. */
@@ -5272,21 +5176,11 @@ has_using_namespace_std_directive_p ()
{
/* Look at local using-directives. */
for (cp_binding_level *level = current_binding_level;
- level->kind != sk_namespace;
+ level;
level = level->level_chain)
if (using_directives_contain_std_p (level->using_directives))
return true;
- /* Look at this namespace and its ancestors. */
- for (tree scope = current_namespace; scope; scope = CP_DECL_CONTEXT (scope))
- {
- if (using_directives_contain_std_p (DECL_NAMESPACE_USING (scope)))
- return true;
-
- if (scope == global_namespace)
- break;
- }
-
return false;
}
@@ -6056,7 +5950,7 @@ consider_binding_level (tree name, best_match <tree, const char *> &bm,
/* Don't suggest names that are for anonymous aggregate types, as
they are an implementation detail generated by the compiler. */
- if (anon_aggrname_p (suggestion))
+ if (IDENTIFIER_ANON_P (suggestion))
continue;
const char *suggestion_str = IDENTIFIER_POINTER (suggestion);
@@ -6566,81 +6460,66 @@ lookup_name_prefer_type (tree name, int prefer_type)
static tree
lookup_type_scope_1 (tree name, tag_scope scope)
{
- cxx_binding *iter = NULL;
- tree val = NULL_TREE;
- cp_binding_level *level = NULL;
-
- /* Look in non-namespace scope first. */
- if (current_binding_level->kind != sk_namespace)
- iter = outer_binding (name, NULL, /*class_p=*/ true);
- for (; iter; iter = outer_binding (name, iter, /*class_p=*/ true))
- {
- /* Check if this is the kind of thing we're looking for.
- If SCOPE is TS_CURRENT, also make sure it doesn't come from
- base class. For ITER->VALUE, we can simply use
- INHERITED_VALUE_BINDING_P. For ITER->TYPE, we have to use
- our own check.
-
- We check ITER->TYPE before ITER->VALUE in order to handle
- typedef struct C {} C;
- correctly. */
-
- if (qualify_lookup (iter->type, LOOKUP_PREFER_TYPES)
- && (scope != ts_current
- || LOCAL_BINDING_P (iter)
- || DECL_CONTEXT (iter->type) == iter->scope->this_entity))
- val = iter->type;
- else if ((scope != ts_current
- || !INHERITED_VALUE_BINDING_P (iter))
- && qualify_lookup (iter->value, LOOKUP_PREFER_TYPES))
- val = iter->value;
-
- if (val)
- break;
- }
+ cp_binding_level *b = current_binding_level;
- /* Look in namespace scope. */
- if (val)
- level = iter->scope;
- else
- {
- tree ns = current_decl_namespace ();
+ if (b->kind != sk_namespace)
+ /* Look in non-namespace scopes. */
+ for (cxx_binding *iter = NULL;
+ (iter = outer_binding (name, iter, /*class_p=*/ true)); )
+ {
+ /* First check we're supposed to be looking in this scope --
+ if we're not, we're done. */
+ for (; b != iter->scope; b = b->level_chain)
+ if (!(b->kind == sk_cleanup
+ || b->kind == sk_template_parms
+ || b->kind == sk_function_parms
+ || (b->kind == sk_class
+ && scope == ts_within_enclosing_non_class)))
+ return NULL_TREE;
+
+ /* Check if this is the kind of thing we're looking for. If
+ SCOPE is TS_CURRENT, also make sure it doesn't come from
+ base class. For ITER->VALUE, we can simply use
+ INHERITED_VALUE_BINDING_P. For ITER->TYPE, we have to
+ use our own check.
+
+ We check ITER->TYPE before ITER->VALUE in order to handle
+ typedef struct C {} C;
+ correctly. */
+ if (tree type = iter->type)
+ if (qualify_lookup (type, LOOKUP_PREFER_TYPES)
+ && (scope != ts_current
+ || LOCAL_BINDING_P (iter)
+ || DECL_CONTEXT (type) == iter->scope->this_entity))
+ return type;
+
+ if (qualify_lookup (iter->value, LOOKUP_PREFER_TYPES)
+ && (scope != ts_current
+ || !INHERITED_VALUE_BINDING_P (iter)))
+ return iter->value;
+ }
- if (tree *slot = find_namespace_slot (ns, name))
- {
- /* If this is the kind of thing we're looking for, we're done. */
- if (tree type = MAYBE_STAT_TYPE (*slot))
- if (qualify_lookup (type, LOOKUP_PREFER_TYPES))
- val = type;
- if (!val)
- {
- if (tree decl = MAYBE_STAT_DECL (*slot))
- if (qualify_lookup (decl, LOOKUP_PREFER_TYPES))
- val = decl;
- }
- level = NAMESPACE_LEVEL (ns);
- }
- }
+ /* Now check if we can look in namespace scope. */
+ for (; b->kind != sk_namespace; b = b->level_chain)
+ if (!(b->kind == sk_cleanup
+ || b->kind == sk_template_parms
+ || b->kind == sk_function_parms
+ || (b->kind == sk_class
+ && scope == ts_within_enclosing_non_class)))
+ return NULL_TREE;
- /* Type found, check if it is in the allowed scopes, ignoring cleanup
- and template parameter scopes. */
- if (val)
+ /* Look in the innermost namespace. */
+ tree ns = b->this_entity;
+ if (tree *slot = find_namespace_slot (ns, name))
{
- cp_binding_level *b = current_binding_level;
- while (b)
- {
- if (level == b)
- return val;
+ /* If this is the kind of thing we're looking for, we're done. */
+ if (tree type = MAYBE_STAT_TYPE (*slot))
+ if (qualify_lookup (type, LOOKUP_PREFER_TYPES))
+ return type;
- if (b->kind == sk_cleanup || b->kind == sk_template_parms
- || b->kind == sk_function_parms)
- b = b->level_chain;
- else if (b->kind == sk_class
- && scope == ts_within_enclosing_non_class)
- b = b->level_chain;
- else
- break;
- }
+ if (tree decl = MAYBE_STAT_DECL (*slot))
+ if (qualify_lookup (decl, LOOKUP_PREFER_TYPES))
+ return decl;
}
return NULL_TREE;
@@ -7244,54 +7123,38 @@ emit_debug_info_using_namespace (tree from, tree target, bool implicit)
implicit);
}
-/* Process a namespace-scope using directive. */
+/* Process a using directive. */
void
-finish_namespace_using_directive (tree target, tree attribs)
+finish_using_directive (tree target, tree attribs)
{
- gcc_checking_assert (namespace_bindings_p ());
if (target == error_mark_node)
return;
- add_using_namespace (DECL_NAMESPACE_USING (current_namespace),
- ORIGINAL_NAMESPACE (target));
- emit_debug_info_using_namespace (current_namespace,
- ORIGINAL_NAMESPACE (target), false);
-
- if (attribs == error_mark_node)
- return;
-
- for (tree a = attribs; a; a = TREE_CHAIN (a))
- {
- tree name = get_attribute_name (a);
- if (is_attribute_p ("strong", name))
- {
- warning (0, "strong using directive no longer supported");
- if (CP_DECL_CONTEXT (target) == current_namespace)
- inform (DECL_SOURCE_LOCATION (target),
- "you may use an inline namespace instead");
- }
- else
- warning (OPT_Wattributes, "%qD attribute directive ignored", name);
- }
-}
-
-/* Process a function-scope using-directive. */
-
-void
-finish_local_using_directive (tree target, tree attribs)
-{
- gcc_checking_assert (local_bindings_p ());
- if (target == error_mark_node)
- return;
-
- if (attribs)
- warning (OPT_Wattributes, "attributes ignored on local using directive");
-
- add_stmt (build_stmt (input_location, USING_STMT, target));
+ if (current_binding_level->kind != sk_namespace)
+ add_stmt (build_stmt (input_location, USING_STMT, target));
+ else
+ emit_debug_info_using_namespace (current_binding_level->this_entity,
+ ORIGINAL_NAMESPACE (target), false);
add_using_namespace (current_binding_level->using_directives,
ORIGINAL_NAMESPACE (target));
+
+ if (attribs != error_mark_node)
+ for (tree a = attribs; a; a = TREE_CHAIN (a))
+ {
+ tree name = get_attribute_name (a);
+ if (current_binding_level->kind == sk_namespace
+ && is_attribute_p ("strong", name))
+ {
+ if (warning (0, "%<strong%> using directive no longer supported")
+ && CP_DECL_CONTEXT (target) == current_namespace)
+ inform (DECL_SOURCE_LOCATION (target),
+ "you can use an inline namespace instead");
+ }
+ else
+ warning (OPT_Wattributes, "%qD attribute directive ignored", name);
+ }
}
/* Pushes X into the global namespace. */
@@ -7404,7 +7267,7 @@ push_namespace (tree name, bool make_inline)
SET_DECL_ASSEMBLER_NAME (ns, anon_identifier);
if (!make_inline)
- add_using_namespace (DECL_NAMESPACE_USING (current_namespace),
+ add_using_namespace (current_binding_level->using_directives,
ns);
}
else if (TREE_PUBLIC (current_namespace))
@@ -7499,7 +7362,7 @@ void
pop_everything (void)
{
if (ENABLE_SCOPE_CHECKING)
- verbatim ("XXX entering pop_everything ()\n");
+ verbatim ("XXX entering %<pop_everything ()%>");
while (!namespace_bindings_p ())
{
if (current_binding_level->kind == sk_class)
@@ -7508,7 +7371,7 @@ pop_everything (void)
poplevel (0, 0, 0);
}
if (ENABLE_SCOPE_CHECKING)
- verbatim ("XXX leaving pop_everything ()\n");
+ verbatim ("XXX leaving %<pop_everything ()%>");
}
/* Emit debugging information for using declarations and directives.
diff --git a/gcc/cp/name-lookup.h b/gcc/cp/name-lookup.h
index 311654a..b44687e 100644
--- a/gcc/cp/name-lookup.h
+++ b/gcc/cp/name-lookup.h
@@ -1,4 +1,4 @@
-/* Declarations for C++ name lookup routines.
+/* Declarations for -*- C++ -*- name lookup routines.
Copyright (C) 2003-2019 Free Software Foundation, Inc.
Contributed by Gabriel Dos Reis <gdr@integrable-solutions.net>
@@ -176,9 +176,6 @@ struct GTY(()) cp_binding_level {
are wrapped in TREE_LISTs; the TREE_VALUE is the OVERLOAD. */
tree names;
- /* A list of USING_DECL nodes. */
- tree usings;
-
/* Using directives. */
vec<tree, va_gc> *using_directives;
@@ -315,10 +312,8 @@ extern tree innermost_non_namespace_value (tree);
extern cxx_binding *outer_binding (tree, cxx_binding *, bool);
extern void cp_emit_debug_info_for_using (tree, tree);
-extern void finish_namespace_using_decl (tree, tree, tree);
-extern void finish_local_using_decl (tree, tree, tree);
-extern void finish_namespace_using_directive (tree, tree);
-extern void finish_local_using_directive (tree, tree);
+extern void finish_nonmember_using_decl (tree scope, tree name);
+extern void finish_using_directive (tree target, tree attribs);
extern tree pushdecl (tree, bool is_friend = false);
extern tree pushdecl_outermost_localscope (tree);
extern tree pushdecl_top_level (tree, bool is_friend = false);
diff --git a/gcc/cp/optimize.c b/gcc/cp/optimize.c
index aace7de..0774857 100644
--- a/gcc/cp/optimize.c
+++ b/gcc/cp/optimize.c
@@ -247,15 +247,19 @@ populate_clone_array (tree fn, tree *fns)
fns[1] = NULL_TREE;
fns[2] = NULL_TREE;
- /* Look for the complete destructor which may be used to build the
- delete destructor. */
+ tree ctx = DECL_CONTEXT (fn);
+
FOR_EACH_CLONE (clone, fn)
if (DECL_NAME (clone) == complete_dtor_identifier
|| DECL_NAME (clone) == complete_ctor_identifier)
fns[1] = clone;
else if (DECL_NAME (clone) == base_dtor_identifier
|| DECL_NAME (clone) == base_ctor_identifier)
- fns[0] = clone;
+ {
+ /* We don't need to define the base variants for a final class. */
+ if (!CLASSTYPE_FINAL (ctx))
+ fns[0] = clone;
+ }
else if (DECL_NAME (clone) == deleting_dtor_identifier)
fns[2] = clone;
else
@@ -480,7 +484,7 @@ maybe_clone_body (tree fn)
/* Remember if we can't have multiple clones for some reason. We need to
check this before we remap local static initializers in clone_body. */
- if (!tree_versionable_function_p (fn))
+ if (!tree_versionable_function_p (fn) && fns[0] && fns[1])
need_alias = true;
/* We know that any clones immediately follow FN in the TYPE_FIELDS
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 12beadf..1281410 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -247,6 +247,12 @@ static void cp_lexer_stop_debugging
static cp_token_cache *cp_token_cache_new
(cp_token *, cp_token *);
+static tree cp_parser_noexcept_specification_opt
+ (cp_parser *, bool, bool *, bool, bool);
+static tree cp_parser_late_noexcept_specifier
+ (cp_parser *, tree);
+static void noexcept_override_late_checks
+ (tree, tree);
static void cp_parser_initial_pragma
(cp_token *);
@@ -818,7 +824,7 @@ cp_lexer_get_preprocessor_token (cp_lexer *lexer, cp_token *token)
{
/* Warn about the C++0x keyword (but still treat it as
an identifier). */
- warning (OPT_Wc__11_compat,
+ warning (OPT_Wc__11_compat,
"identifier %qE is a keyword in C++11",
token->u.value);
@@ -963,7 +969,7 @@ cp_keyword_starts_decl_specifier_p (enum rid keyword)
case RID_FLOAT:
case RID_DOUBLE:
case RID_VOID:
- /* GNU extensions. */
+ /* GNU extensions. */
case RID_ATTRIBUTE:
case RID_TYPEOF:
/* C++0x extensions. */
@@ -1308,7 +1314,7 @@ cp_lexer_start_debugging (cp_lexer* lexer)
{
if (!LEXER_DEBUGGING_ENABLED_P)
fatal_error (input_location,
- "LEXER_DEBUGGING_ENABLED_P is not set to true");
+ "%<LEXER_DEBUGGING_ENABLED_P%> is not set to true");
lexer->debugging_p = true;
cp_lexer_debug_stream = stderr;
@@ -1321,7 +1327,7 @@ cp_lexer_stop_debugging (cp_lexer* lexer)
{
if (!LEXER_DEBUGGING_ENABLED_P)
fatal_error (input_location,
- "LEXER_DEBUGGING_ENABLED_P is not set to true");
+ "%<LEXER_DEBUGGING_ENABLED_P%> is not set to true");
lexer->debugging_p = false;
cp_lexer_debug_stream = NULL;
@@ -1640,7 +1646,7 @@ make_array_declarator (cp_declarator *element, tree bounds)
/* Determine whether the declarator we've seen so far can be a
parameter pack, when followed by an ellipsis. */
-static bool
+static bool
declarator_can_be_parameter_pack (cp_declarator *declarator)
{
if (declarator && declarator->parameter_pack_p)
@@ -1721,7 +1727,7 @@ function_declarator_p (const cp_declarator *declarator)
}
return false;
}
-
+
/* The parser. */
/* Overview
@@ -1974,11 +1980,14 @@ cp_parser_context_new (cp_parser_context* next)
parser->unparsed_queues->last ().nsdmis
#define unparsed_classes \
parser->unparsed_queues->last ().classes
+#define unparsed_noexcepts \
+ parser->unparsed_queues->last ().noexcepts
static void
push_unparsed_function_queues (cp_parser *parser)
{
- cp_unparsed_functions_entry e = {NULL, make_tree_vector (), NULL, NULL};
+ cp_unparsed_functions_entry e = { NULL, make_tree_vector (), NULL, NULL,
+ NULL };
vec_safe_push (parser->unparsed_queues, e);
}
@@ -2164,7 +2173,7 @@ static tree cp_parser_simple_type_specifier
(cp_parser *, cp_decl_specifier_seq *, cp_parser_flags);
static tree cp_parser_type_name
(cp_parser *, bool);
-static tree cp_parser_nonclass_name
+static tree cp_parser_nonclass_name
(cp_parser* parser);
static tree cp_parser_elaborated_type_specifier
(cp_parser *, bool, bool);
@@ -2242,7 +2251,7 @@ static tree cp_parser_parameter_declaration_list
(cp_parser *, cp_parser_flags);
static cp_parameter_declarator *cp_parser_parameter_declaration
(cp_parser *, cp_parser_flags, bool, bool *);
-static tree cp_parser_default_argument
+static tree cp_parser_default_argument
(cp_parser *, bool);
static void cp_parser_function_body
(cp_parser *, bool);
@@ -2361,7 +2370,7 @@ static tree cp_parser_exception_declaration
static tree cp_parser_throw_expression
(cp_parser *);
static tree cp_parser_exception_specification_opt
- (cp_parser *);
+ (cp_parser *, bool = false);
static tree cp_parser_type_id_list
(cp_parser *);
@@ -2482,9 +2491,9 @@ static tree cp_parser_objc_statement
(cp_parser *);
static bool cp_parser_objc_valid_prefix_attributes
(cp_parser *, tree *);
-static void cp_parser_objc_at_property_declaration
+static void cp_parser_objc_at_property_declaration
(cp_parser *) ;
-static void cp_parser_objc_at_synthesize_declaration
+static void cp_parser_objc_at_synthesize_declaration
(cp_parser *) ;
static void cp_parser_objc_at_dynamic_declaration
(cp_parser *) ;
@@ -2988,7 +2997,7 @@ cp_parser_name_lookup_error (cp_parser* parser,
break;
default:
gcc_unreachable ();
-
+
}
}
else if (parser->scope == global_namespace)
@@ -3087,7 +3096,7 @@ cp_parser_check_for_definition_in_return_type (cp_declarator *declarator,
{
error_at (type_location,
"new types may not be defined in a return type");
- inform (type_location,
+ inform (type_location,
"(perhaps a semicolon is missing after the definition of %qT)",
type);
}
@@ -3360,7 +3369,7 @@ cp_parser_diagnose_invalid_type_name (cp_parser *parser, tree id,
if (TREE_CODE (field) == TYPE_DECL
&& DECL_NAME (field) == id)
{
- inform (location,
+ inform (location,
"(perhaps %<typename %T::%E%> was intended)",
BINFO_TYPE (b), id);
break;
@@ -4345,18 +4354,16 @@ cp_parser_userdef_char_literal (cp_parser *parser)
/* Build up a call to the user-defined operator */
/* Lookup the name we got back from the id-expression. */
- vec<tree, va_gc> *args = make_tree_vector ();
+ releasing_vec args;
vec_safe_push (args, value);
decl = lookup_literal_operator (name, args);
if (!decl || decl == error_mark_node)
{
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, &args, false, true, tf_warning_or_error);
- release_tree_vector (args);
return result;
}
@@ -4443,11 +4450,10 @@ cp_parser_userdef_numeric_literal (cp_parser *parser)
tree num_string = USERDEF_LITERAL_NUM_STRING (literal);
tree name = cp_literal_operator_id (IDENTIFIER_POINTER (suffix_id));
tree decl, result;
- vec<tree, va_gc> *args;
/* Look for a literal operator taking the exact type of numeric argument
as the literal value. */
- args = make_tree_vector ();
+ releasing_vec args;
vec_safe_push (args, value);
decl = lookup_literal_operator (name, args);
if (decl && decl != error_mark_node)
@@ -4472,30 +4478,26 @@ cp_parser_userdef_numeric_literal (cp_parser *parser)
"floating literal truncated to zero");
}
- release_tree_vector (args);
return result;
}
- release_tree_vector (args);
/* If the numeric argument didn't work, look for a raw literal
operator taking a const char* argument consisting of the number
in string format. */
- args = make_tree_vector ();
+ args->truncate (0);
vec_safe_push (args, num_string);
decl = lookup_literal_operator (name, args);
if (decl && decl != error_mark_node)
{
result = finish_call_expr (decl, &args, false, true,
tf_warning_or_error);
- release_tree_vector (args);
return result;
}
- release_tree_vector (args);
/* If the raw literal didn't work, look for a non-type template
function with parameter pack char.... Call the function with
template parameter characters representing the number. */
- args = make_tree_vector ();
+ args->truncate (0);
decl = lookup_literal_operator (name, args);
if (decl && decl != error_mark_node)
{
@@ -4509,12 +4511,9 @@ cp_parser_userdef_numeric_literal (cp_parser *parser)
decl = lookup_template_function (decl, tmpl_args);
result = finish_call_expr (decl, &args, false, true,
tf_warning_or_error);
- release_tree_vector (args);
return result;
}
- release_tree_vector (args);
-
/* In C++14 the standard library defines complex number suffixes that
conflict with GNU extensions. Prefer them if <complex> is #included. */
bool ext = cpp_get_options (parse_in)->ext_numeric_literals;
@@ -4547,7 +4546,7 @@ cp_parser_userdef_numeric_literal (cp_parser *parser)
else if (i14)
{
inform (token->location, "add %<using namespace std::complex_literals%> "
- "(from <complex>) to enable the C++14 user-defined literal "
+ "(from %<<complex>%>) to enable the C++14 user-defined literal "
"suffixes");
if (ext)
inform (token->location, "or use %<j%> instead of %<i%> for the "
@@ -4602,8 +4601,7 @@ cp_parser_userdef_string_literal (tree literal)
/* Build up a call to the user-defined operator. */
/* Lookup the name we got back from the id-expression. */
- releasing_vec rargs;
- vec<tree, va_gc> *&args = rargs.get_ref();
+ releasing_vec args;
vec_safe_push (args, value);
vec_safe_push (args, build_int_cst (size_type_node, len));
decl = lookup_literal_operator (name, args);
@@ -4657,7 +4655,7 @@ static void
cp_parser_translation_unit (cp_parser* parser)
{
gcc_checking_assert (!cp_error_declarator);
-
+
/* Create the declarator obstack. */
gcc_obstack_init (&declarator_obstack);
/* Create the error declarator. */
@@ -4673,7 +4671,7 @@ cp_parser_translation_unit (cp_parser* parser)
for (;;)
{
cp_token *token = cp_lexer_peek_token (parser->lexer);
-
+
/* If we're entering or exiting a region that's implicitly
extern "C", modify the lang context appropriately. */
if (implicit_extern_c
@@ -5123,14 +5121,14 @@ cp_parser_fold_expression (cp_parser *parser, tree expr1)
__builtin_offsetof ( type-id , offsetof-expression )
C++ Extensions:
- __has_nothrow_assign ( type-id )
+ __has_nothrow_assign ( type-id )
__has_nothrow_constructor ( type-id )
__has_nothrow_copy ( type-id )
- __has_trivial_assign ( type-id )
+ __has_trivial_assign ( type-id )
__has_trivial_constructor ( type-id )
__has_trivial_copy ( type-id )
__has_trivial_destructor ( type-id )
- __has_virtual_destructor ( type-id )
+ __has_virtual_destructor ( type-id )
__is_abstract ( type-id )
__is_base_of ( type-id , type-id )
__is_class ( type-id )
@@ -5518,10 +5516,10 @@ cp_parser_primary_expression (cp_parser *parser,
case RID_HAS_NOTHROW_ASSIGN:
case RID_HAS_NOTHROW_CONSTRUCTOR:
- case RID_HAS_NOTHROW_COPY:
+ case RID_HAS_NOTHROW_COPY:
case RID_HAS_TRIVIAL_ASSIGN:
case RID_HAS_TRIVIAL_CONSTRUCTOR:
- case RID_HAS_TRIVIAL_COPY:
+ case RID_HAS_TRIVIAL_COPY:
case RID_HAS_TRIVIAL_DESTRUCTOR:
case RID_HAS_UNIQUE_OBJ_REPRESENTATIONS:
case RID_HAS_VIRTUAL_DESTRUCTOR:
@@ -6063,7 +6061,7 @@ cp_parser_unqualified_id (cp_parser* parser,
&& constructor_name_p (token->u.value, scope))))
{
cp_lexer_consume_token (parser->lexer);
- return cp_expr (build_nt (BIT_NOT_EXPR, scope), loc);
+ return build_min_nt_loc (loc, BIT_NOT_EXPR, scope);
}
/* ~auto means the destructor of whatever the object is. */
@@ -6074,7 +6072,7 @@ cp_parser_unqualified_id (cp_parser* parser,
"%<~auto%> only available with "
"%<-std=c++14%> or %<-std=gnu++14%>");
cp_lexer_consume_token (parser->lexer);
- return cp_expr (build_nt (BIT_NOT_EXPR, make_auto (), loc));
+ return build_min_nt_loc (loc, BIT_NOT_EXPR, make_auto ());
}
/* If there was an explicit qualification (S::~T), first look
@@ -6164,8 +6162,8 @@ cp_parser_unqualified_id (cp_parser* parser,
time. */
type_decl = cp_parser_identifier (parser);
if (type_decl != error_mark_node)
- type_decl = build_nt (BIT_NOT_EXPR, type_decl);
- return cp_expr (type_decl, loc);
+ type_decl = build_min_nt_loc (loc, BIT_NOT_EXPR, type_decl);
+ return type_decl;
}
}
/* If an error occurred, assume that the name of the
@@ -6173,7 +6171,7 @@ cp_parser_unqualified_id (cp_parser* parser,
class. That allows us to keep parsing after running
into ill-formed destructor names. */
if (type_decl == error_mark_node && scope)
- return build_nt (BIT_NOT_EXPR, scope);
+ return build_min_nt_loc (loc, BIT_NOT_EXPR, scope);
else if (type_decl == error_mark_node)
return error_mark_node;
@@ -6200,7 +6198,7 @@ cp_parser_unqualified_id (cp_parser* parser,
"typedef-name %qD used as destructor declarator",
type_decl);
- return cp_expr (build_nt (BIT_NOT_EXPR, TREE_TYPE (type_decl), loc));
+ return build_min_nt_loc (loc, BIT_NOT_EXPR, TREE_TYPE (type_decl));
}
case CPP_KEYWORD:
@@ -6411,7 +6409,7 @@ cp_parser_nested_name_specifier_opt (cp_parser *parser,
== CPP_SCOPE))
{
token = cp_lexer_consume_token (parser->lexer);
- error_at (token->location, "decltype evaluates to %qT, "
+ error_at (token->location, "%<decltype%> evaluates to %qT, "
"which is not a class or enumeration type",
token->u.tree_check_value->value);
parser->scope = error_mark_node;
@@ -6689,7 +6687,7 @@ cp_parser_qualifying_entity (cp_parser *parser,
saved_object_scope = parser->object_scope;
/* Try for a class-name first. If the SAVED_SCOPE is a type, then
there is no need to look for a namespace-name. */
- only_class_p = template_keyword_p
+ only_class_p = template_keyword_p
|| (saved_scope && TYPE_P (saved_scope) && cxx_dialect == cxx98);
if (!only_class_p)
cp_parser_parse_tentatively (parser);
@@ -6736,7 +6734,7 @@ cp_parser_compound_literal_p (cp_parser *parser)
= (cp_parser_skip_to_closing_parenthesis (parser, false, false,
/*consume_paren=*/true)
&& cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE));
-
+
/* Roll back the tokens we skipped. */
cp_lexer_rollback_tokens (parser->lexer);
@@ -6886,7 +6884,7 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p,
break;
case RID_REINTCAST:
postfix_expression
- = build_reinterpret_cast (type, expression,
+ = build_reinterpret_cast (type, expression,
tf_warning_or_error);
break;
case RID_CONSTCAST:
@@ -7768,7 +7766,7 @@ cp_parser_postfix_dot_deref_expression (cp_parser *parser,
(name, parser->scope, scope);
postfix_expression
= finish_class_member_access_expr (postfix_expression, name,
- template_p,
+ template_p,
tf_warning_or_error);
/* Build a location e.g.:
ptr->access_expr
@@ -8689,7 +8687,7 @@ cp_parser_new_expression (cp_parser* parser)
{
error_at (token->location,
"array bound forbidden after parenthesized type-id");
- inform (token->location,
+ inform (token->location,
"try removing the parentheses around the type-id");
cp_parser_direct_new_declarator (parser);
}
@@ -8863,7 +8861,7 @@ cp_parser_new_declarator_opt (cp_parser* parser)
{
enum tree_code code;
tree type, std_attributes = NULL_TREE;
- cp_cv_quals cv_quals;
+ cp_cv_quals cv_quals;
/* We don't know if there's a ptr-operator next, or not. */
cp_parser_parse_tentatively (parser);
@@ -9347,7 +9345,7 @@ cp_parser_cast_expression (cp_parser *parser, bool address_p, bool cast_p,
return expr;
}
}
- else
+ else
cp_parser_abort_tentative_parse (parser);
}
@@ -9682,7 +9680,7 @@ cp_parser_question_colon_clause (cp_parser* parser, cp_expr logical_or_expr)
&& token->type == CPP_COLON)
{
pedwarn (token->location, OPT_Wpedantic,
- "ISO C++ does not allow ?: with omitted middle operand");
+ "ISO C++ does not allow %<?:%> with omitted middle operand");
/* Implicit true clause. */
expr = NULL_TREE;
c_inhibit_evaluation_warnings +=
@@ -10318,7 +10316,7 @@ cp_parser_trait_expr (cp_parser* parser, enum rid keyword)
if (binary)
{
cp_parser_require (parser, CPP_COMMA, RT_COMMA);
-
+
{
type_id_in_expr_sentinel s (parser);
type2 = cp_parser_type_id (parser);
@@ -10480,7 +10478,7 @@ cp_parser_lambda_expression (cp_parser* parser)
if (ok)
maybe_add_lambda_conv_op (type);
- type = finish_struct (type, /*attributes=*/NULL_TREE);
+ finish_struct (type, /*attributes=*/NULL_TREE);
parser->num_template_parameter_lists = saved_num_template_parameter_lists;
parser->in_statement = in_statement;
@@ -10537,7 +10535,8 @@ cp_parser_lambda_introducer (cp_parser* parser, tree lambda_expr)
/* Record default capture mode. "[&" "[=" "[&," "[=," */
if (cp_lexer_next_token_is (parser->lexer, CPP_AND)
- && cp_lexer_peek_nth_token (parser->lexer, 2)->type != CPP_NAME)
+ && !cp_lexer_nth_token_is (parser->lexer, 2, CPP_NAME)
+ && !cp_lexer_nth_token_is_keyword (parser->lexer, 2, RID_THIS))
LAMBDA_EXPR_DEFAULT_CAPTURE_MODE (lambda_expr) = CPLD_REFERENCE;
else if (cp_lexer_next_token_is (parser->lexer, CPP_EQ))
LAMBDA_EXPR_DEFAULT_CAPTURE_MODE (lambda_expr) = CPLD_COPY;
@@ -10620,6 +10619,17 @@ cp_parser_lambda_introducer (cp_parser* parser, tree lambda_expr)
continue;
}
+ /* But reject `&this'. */
+ if (cp_lexer_next_token_is (parser->lexer, CPP_AND)
+ && cp_lexer_nth_token_is_keyword (parser->lexer, 2, RID_THIS))
+ {
+ error_at (cp_lexer_peek_token (parser->lexer)->location,
+ "%<this%> cannot be captured by reference");
+ cp_lexer_consume_token (parser->lexer);
+ cp_lexer_consume_token (parser->lexer);
+ continue;
+ }
+
bool init_pack_expansion = false;
location_t ellipsis_loc = UNKNOWN_LOCATION;
if (cp_lexer_next_token_is (parser->lexer, CPP_ELLIPSIS))
@@ -11217,7 +11227,7 @@ cp_parser_statement (cp_parser* parser, tree in_statement_expr,
}
cp_parser_declaration_statement (parser);
return;
-
+
case RID_TRANSACTION_ATOMIC:
case RID_TRANSACTION_RELAXED:
case RID_SYNCHRONIZED:
@@ -11639,12 +11649,12 @@ cp_parser_statement_seq_opt (cp_parser* parser, tree in_statement_expr)
|| token->type == CPP_PRAGMA_EOL
|| (token->type == CPP_KEYWORD && token->keyword == RID_AT_END))
break;
-
+
/* If we are in a compound statement and find 'else' then
something went wrong. */
else if (token->type == CPP_KEYWORD && token->keyword == RID_ELSE)
{
- if (parser->in_statement & IN_IF_STMT)
+ if (parser->in_statement & IN_IF_STMT)
break;
else
{
@@ -12082,7 +12092,7 @@ cp_parser_condition (cp_parser* parser)
if (cp_lexer_next_token_is_not (parser->lexer, CPP_EQ)
&& cp_lexer_next_token_is_not (parser->lexer, CPP_OPEN_BRACE))
cp_parser_simulate_error (parser);
-
+
/* If we did see an `=' or '{', then we are looking at a declaration
for sure. */
if (cp_parser_parse_definitely (parser))
@@ -12539,8 +12549,7 @@ cp_parser_perform_range_for_lookup (tree range, tree *begin, tree *end)
else
{
/* Use global functions with ADL. */
- vec<tree, va_gc> *vec;
- vec = make_tree_vector ();
+ releasing_vec vec;
vec_safe_push (vec, range);
@@ -12552,8 +12561,6 @@ cp_parser_perform_range_for_lookup (tree range, tree *begin, tree *end)
tf_warning_or_error);
*end = finish_call_expr (member_end, &vec, false, true,
tf_warning_or_error);
-
- release_tree_vector (vec);
}
/* Last common checks. */
@@ -12601,19 +12608,17 @@ static tree
cp_parser_range_for_member_function (tree range, tree identifier)
{
tree member, res;
- vec<tree, va_gc> *vec;
member = finish_class_member_access_expr (range, identifier,
false, tf_warning_or_error);
if (member == error_mark_node)
return error_mark_node;
- vec = make_tree_vector ();
+ releasing_vec vec;
res = finish_call_expr (member, &vec,
/*disallow_virtual=*/false,
/*koenig_p=*/false,
tf_warning_or_error);
- release_tree_vector (vec);
return res;
}
@@ -12852,7 +12857,7 @@ cp_parser_jump_statement (cp_parser* parser)
switch (keyword)
{
case RID_BREAK:
- in_statement = parser->in_statement & ~IN_IF_STMT;
+ in_statement = parser->in_statement & ~IN_IF_STMT;
switch (in_statement)
{
case 0:
@@ -14045,7 +14050,7 @@ cp_parser_decl_specifier_seq (cp_parser* parser,
GNU Extension:
thread */
case RID_AUTO:
- if (cxx_dialect == cxx98)
+ if (cxx_dialect == cxx98)
{
/* Consume the token. */
cp_lexer_consume_token (parser->lexer);
@@ -14091,7 +14096,7 @@ cp_parser_decl_specifier_seq (cp_parser* parser,
if (found_decl_spec
&& (flags & CP_PARSER_FLAGS_ONLY_TYPE_OR_CONSTEXPR)
&& token->keyword != RID_CONSTEXPR)
- error ("decl-specifier invalid in condition");
+ error ("%<decl-specifier%> invalid in condition");
if (found_decl_spec
&& (flags & CP_PARSER_FLAGS_ONLY_MUTABLE_OR_CONSTEXPR)
@@ -14416,12 +14421,12 @@ cp_parser_linkage_specification (cp_parser* parser)
/* Parse a static_assert-declaration.
static_assert-declaration:
- static_assert ( constant-expression , string-literal ) ;
+ static_assert ( constant-expression , string-literal ) ;
static_assert ( constant-expression ) ; (C++17)
If MEMBER_P, this static_assert is a class member. */
-static void
+static void
cp_parser_static_assert(cp_parser *parser, bool member_p)
{
cp_expr condition;
@@ -14434,7 +14439,7 @@ cp_parser_static_assert(cp_parser *parser, bool member_p)
token_loc = cp_lexer_peek_token (parser->lexer)->location;
/* Look for the `static_assert' keyword. */
- if (!cp_parser_require_keyword (parser, RID_STATIC_ASSERT,
+ if (!cp_parser_require_keyword (parser, RID_STATIC_ASSERT,
RT_STATIC_ASSERT))
return;
@@ -14449,7 +14454,7 @@ cp_parser_static_assert(cp_parser *parser, bool member_p)
/* Parse the constant-expression. Allow a non-constant expression
here in order to give better diagnostics in finish_static_assert. */
- condition =
+ condition =
cp_parser_constant_expression (parser,
/*allow_non_constant_p=*/true,
/*non_constant_p=*/&dummy);
@@ -14458,7 +14463,7 @@ cp_parser_static_assert(cp_parser *parser, bool member_p)
{
if (cxx_dialect < cxx17)
pedwarn (input_location, OPT_Wpedantic,
- "static_assert without a message "
+ "%<static_assert%> without a message "
"only available with %<-std=c++17%> or %<-std=gnu++17%>");
/* Eat the ')' */
cp_lexer_consume_token (parser->lexer);
@@ -14472,14 +14477,14 @@ cp_parser_static_assert(cp_parser *parser, bool member_p)
cp_parser_require (parser, CPP_COMMA, RT_COMMA);
/* Parse the string-literal message. */
- message = cp_parser_string_literal (parser,
+ message = cp_parser_string_literal (parser,
/*translate=*/false,
/*wide_ok=*/true);
/* A `)' completes the static assertion. */
if (!parens.require_close (parser))
- cp_parser_skip_to_closing_parenthesis (parser,
- /*recovering=*/true,
+ cp_parser_skip_to_closing_parenthesis (parser,
+ /*recovering=*/true,
/*or_comma=*/false,
/*consume_paren=*/true);
}
@@ -14494,7 +14499,7 @@ cp_parser_static_assert(cp_parser *parser, bool member_p)
if (assert_loc == UNKNOWN_LOCATION)
assert_loc = token_loc;
- /* Complete the static assertion, which may mean either processing
+ /* Complete the static assertion, which may mean either processing
the static assert now or saving it for template instantiation. */
finish_static_assert (condition, message, assert_loc, member_p);
}
@@ -14568,7 +14573,7 @@ cp_parser_decltype_expr (cp_parser *parser,
id_expression_or_member_access_p = true;
}
- if (expr
+ if (expr
&& expr != error_mark_node
&& cp_lexer_peek_token (parser->lexer)->type == CPP_CLOSE_PAREN)
/* We have an id-expression. */
@@ -14588,7 +14593,7 @@ cp_parser_decltype_expr (cp_parser *parser,
/*cast_p=*/false, /*decltype*/true,
/*member_access_only_p=*/true, NULL);
- if (expr
+ if (expr
&& expr != error_mark_node
&& cp_lexer_peek_token (parser->lexer)->type == CPP_CLOSE_PAREN)
/* We have an id-expression. */
@@ -14647,7 +14652,7 @@ cp_parser_decltype (cp_parser *parser)
push_deferring_access_checks (dk_deferred);
tree expr = NULL_TREE;
-
+
if (cxx_dialect >= cxx14
&& cp_lexer_next_token_is_keyword (parser->lexer, RID_AUTO))
/* decltype (auto) */
@@ -14732,7 +14737,7 @@ cp_parser_decltype (cp_parser *parser)
cp_lexer_purge_tokens_after (parser->lexer, start_token);
pop_to_parent_deferring_access_checks ();
-
+
return expr;
}
@@ -15104,7 +15109,7 @@ cp_parser_mem_initializer_id (cp_parser* parser)
/* `typename' is not allowed in this context ([temp.res]). */
if (cp_lexer_next_token_is_keyword (parser->lexer, RID_TYPENAME))
{
- error_at (token->location,
+ error_at (token->location,
"keyword %<typename%> not allowed in this context (a qualified "
"member initializer is implicitly a type)");
cp_lexer_consume_token (parser->lexer);
@@ -15634,7 +15639,7 @@ cp_parser_template_parameter_list (cp_parser* parser)
/* Parse the template-parameter. */
parm_loc = cp_lexer_peek_token (parser->lexer)->location;
- parameter = cp_parser_template_parameter (parser,
+ parameter = cp_parser_template_parameter (parser,
&is_non_type,
&is_parameter_pack);
/* Add it to the list. */
@@ -16495,10 +16500,7 @@ cp_parser_template_id (cp_parser *parser,
{
/* If it's not a class-template or a template-template, it should be
a function-template. */
- gcc_assert ((DECL_FUNCTION_TEMPLATE_P (templ)
- || TREE_CODE (templ) == OVERLOAD
- || TREE_CODE (templ) == FUNCTION_DECL
- || BASELINK_P (templ)));
+ gcc_assert (OVL_P (templ) || BASELINK_P (templ));
template_id = lookup_template_function (templ, arguments);
if (TREE_CODE (template_id) == TEMPLATE_ID_EXPR)
@@ -16914,7 +16916,7 @@ cp_parser_template_argument (cp_parser* parser)
Here 'X()' is a valid type-id of a function type, but the user just
wanted to write the expression "X() >> 5". Thus, we remember that we
found a valid type-id, but we still try to parse the argument as an
- expression to see what happens.
+ expression to see what happens.
In C++0x, the '>>' will be considered two separate '>'
tokens. */
@@ -17540,7 +17542,7 @@ cp_parser_type_specifier (cp_parser* parser,
simple-type-specifier:
auto
- decltype ( expression )
+ decltype ( expression )
char16_t
char32_t
__underlying_type ( type-id )
@@ -17620,6 +17622,12 @@ cp_parser_simple_type_specifier (cp_parser* parser,
{
decl_specs->explicit_intN_p = true;
decl_specs->int_n_idx = idx;
+ /* Check if the alternate "__intN__" form has been used instead of
+ "__intN". */
+ if (strncmp (IDENTIFIER_POINTER (token->u.value)
+ + (IDENTIFIER_LENGTH (token->u.value) - 2),
+ "__", 2) == 0)
+ decl_specs->int_n_alt = true;
}
type = int_n_trees [idx].signed_type;
break;
@@ -18028,12 +18036,12 @@ cp_parser_type_name (cp_parser* parser, bool typename_keyword_p)
/*is_declaration=*/false);
/* Note that this must be an instantiation of an alias template
because [temp.names]/6 says:
-
+
A template-id that names an alias template specialization
is a type-name.
Whereas [temp.names]/7 says:
-
+
A simple-template-id that names a class template
specialization is a class-name.
@@ -18184,7 +18192,7 @@ cp_parser_nonclass_name (cp_parser* parser)
type_decl = cp_parser_lookup_name_simple (parser, identifier, token->location);
type_decl = strip_using_decl (type_decl);
-
+
/* If we found an overload set, then it may refer to a concept-name. */
if (tree decl = cp_parser_maybe_concept_name (parser, type_decl))
type_decl = decl;
@@ -18222,7 +18230,7 @@ cp_parser_nonclass_name (cp_parser* parser)
else if (type_decl != error_mark_node
&& !parser->scope)
maybe_note_name_used_in_class (identifier, type_decl);
-
+
return type_decl;
}
@@ -18387,7 +18395,7 @@ cp_parser_elaborated_type_specifier (cp_parser* parser,
/* If the `typename' keyword is in effect and DECL is not a type
decl, then type is non existent. */
else if (tag_type == typename_type && TREE_CODE (decl) != TYPE_DECL)
- ;
+ ;
else if (TREE_CODE (decl) == TYPE_DECL)
{
type = check_elaborated_type_specifier (tag_type, decl,
@@ -18402,7 +18410,7 @@ cp_parser_elaborated_type_specifier (cp_parser* parser,
check_unqualified_spec_or_inst (type, token->location);
}
else if (decl == error_mark_node)
- type = error_mark_node;
+ type = error_mark_node;
}
if (!type)
@@ -18650,7 +18658,7 @@ cp_parser_elaborated_type_specifier (cp_parser* parser,
enum-key identifier enum-base [opt] ;
GNU Extensions:
- enum-key attributes[opt] identifier [opt] enum-base [opt]
+ enum-key attributes[opt] identifier [opt] enum-base [opt]
{ enumerator-list [opt] }attributes[opt]
enum-key attributes[opt] identifier [opt] enum-base [opt]
{ enumerator-list, }attributes[opt] [C++0x]
@@ -19229,7 +19237,7 @@ cp_parser_namespace_definition (cp_parser* parser)
for (;;)
{
identifier = NULL_TREE;
-
+
bool nested_inline_p = cp_lexer_next_token_is_keyword (parser->lexer,
RID_INLINE);
if (nested_inline_p && nested_definition_count != 0)
@@ -19263,7 +19271,7 @@ cp_parser_namespace_definition (cp_parser* parser)
is_inline |= nested_inline_p;
break;
}
-
+
if (!nested_definition_count && cxx_dialect < cxx17)
pedwarn (input_location, OPT_Wpedantic,
"nested namespace definitions only available with "
@@ -19282,7 +19290,7 @@ cp_parser_namespace_definition (cp_parser* parser)
if (nested_definition_count && !identifier)
cp_parser_error (parser, "namespace name required");
-
+
if (nested_definition_count && attribs)
error_at (token->location,
"a nested namespace definition cannot have attributes");
@@ -19348,7 +19356,7 @@ cp_parser_namespace_alias_definition (cp_parser* parser)
return;
/* Look for the `=' token. */
if (!cp_parser_uncommitted_to_tentative_parse_p (parser)
- && cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE))
+ && cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE))
{
error_at (token->location, "%<namespace%> definition is not allowed here");
/* Skip the definition. */
@@ -19398,15 +19406,15 @@ cp_parser_qualified_namespace_specifier (cp_parser* parser)
using-declaration:
using typename [opt] :: [opt] nested-name-specifier unqualified-id ;
- using :: unqualified-id ;
+ using :: unqualified-id ;
access-declaration:
- qualified-id ;
+ qualified-id ;
*/
static bool
-cp_parser_using_declaration (cp_parser* parser,
+cp_parser_using_declaration (cp_parser* parser,
bool access_declaration_p)
{
cp_token *token;
@@ -19427,7 +19435,7 @@ cp_parser_using_declaration (cp_parser* parser,
{
/* Look for the `using' keyword. */
cp_parser_require_keyword (parser, RID_USING, RT_USING);
-
+
again:
/* Peek at the next token. */
token = cp_lexer_peek_token (parser->lexer);
@@ -19538,24 +19546,7 @@ cp_parser_using_declaration (cp_parser* parser,
finish_member_declaration (decl);
}
else
- {
- decl = cp_parser_lookup_name_simple (parser,
- identifier,
- token->location);
- if (decl == error_mark_node)
- cp_parser_name_lookup_error (parser, identifier,
- decl, NLE_NULL,
- token->location);
- else if (check_for_bare_parameter_packs (decl))
- {
- cp_parser_require (parser, CPP_SEMICOLON, RT_SEMICOLON);
- return false;
- }
- else if (!at_namespace_scope_p ())
- finish_local_using_decl (decl, qscope, identifier);
- else
- finish_namespace_using_decl (decl, qscope, identifier);
- }
+ finish_nonmember_using_decl (qscope, identifier);
}
if (!access_declaration_p
@@ -19756,10 +19747,7 @@ cp_parser_using_directive (cp_parser* parser)
attribs = cp_parser_attributes_opt (parser);
/* Update the symbol table. */
- if (namespace_bindings_p ())
- finish_namespace_using_directive (namespace_decl, attribs);
- else
- finish_local_using_directive (namespace_decl, attribs);
+ finish_using_directive (namespace_decl, attribs);
/* Look for the final `;'. */
cp_parser_require (parser, CPP_SEMICOLON, RT_SEMICOLON);
@@ -19837,14 +19825,15 @@ cp_parser_asm_definition (cp_parser* parser)
case RID_VOLATILE:
if (volatile_loc)
{
- error_at (loc, "duplicate asm qualifier %qT", token->u.value);
+ error_at (loc, "duplicate %<asm%> qualifier %qT",
+ token->u.value);
inform (volatile_loc, "first seen here");
}
else
{
if (!parser->in_function_body)
- warning_at (loc, 0, "asm qualifier %qT ignored outside of "
- "function body", token->u.value);
+ warning_at (loc, 0, "%<asm%> qualifier %qT ignored "
+ "outside of function body", token->u.value);
volatile_loc = loc;
}
cp_lexer_consume_token (parser->lexer);
@@ -19853,7 +19842,8 @@ cp_parser_asm_definition (cp_parser* parser)
case RID_INLINE:
if (inline_loc)
{
- error_at (loc, "duplicate asm qualifier %qT", token->u.value);
+ error_at (loc, "duplicate %<asm%> qualifier %qT",
+ token->u.value);
inform (inline_loc, "first seen here");
}
else
@@ -19866,7 +19856,8 @@ cp_parser_asm_definition (cp_parser* parser)
case RID_GOTO:
if (goto_loc)
{
- error_at (loc, "duplicate asm qualifier %qT", token->u.value);
+ error_at (loc, "duplicate %<asm%> qualifier %qT",
+ token->u.value);
inform (goto_loc, "first seen here");
}
else
@@ -19878,7 +19869,7 @@ cp_parser_asm_definition (cp_parser* parser)
case RID_CONST:
case RID_RESTRICT:
- error_at (loc, "%qT is not an asm qualifier", token->u.value);
+ error_at (loc, "%qT is not an %<asm%> qualifier", token->u.value);
cp_lexer_consume_token (parser->lexer);
continue;
@@ -19894,7 +19885,7 @@ cp_parser_asm_definition (cp_parser* parser)
if (!parser->in_function_body && (inline_p || goto_p))
{
- error_at (first_loc, "asm qualifier outside of function body");
+ error_at (first_loc, "%<asm%> qualifier outside of function body");
inline_p = goto_p = false;
}
@@ -20276,7 +20267,7 @@ cp_parser_init_declarator (cp_parser* parser,
on a function-definition. */
if (asm_specification)
error_at (asm_spec_start_token->location,
- "an asm-specification is not allowed "
+ "an %<asm%> specification is not allowed "
"on a function-definition");
if (attributes)
error_at (attributes_start_token->location,
@@ -20539,7 +20530,7 @@ cp_parser_init_declarator (cp_parser* parser,
/* Core issue #226 (C++0x only): A default template-argument
shall not be specified in a friend class template
declaration. */
- check_default_tmpl_args (decl, current_template_parms, /*is_primary=*/true,
+ check_default_tmpl_args (decl, current_template_parms, /*is_primary=*/true,
/*is_partial=*/false, /*is_friend_decl=*/1);
if (!friend_p && pushed_scope)
@@ -20840,7 +20831,7 @@ cp_parser_direct_declarator (cp_parser* parser,
tree tx_qual = cp_parser_tx_qualifier_opt (parser);
/* And the exception-specification. */
exception_specification
- = cp_parser_exception_specification_opt (parser);
+ = cp_parser_exception_specification_opt (parser, friend_p);
attrs = cp_parser_std_attribute_spec_seq (parser);
@@ -21879,7 +21870,7 @@ cp_parser_type_id_1 (cp_parser *parser, cp_parser_flags flags,
return error_mark_node;
}
}
-
+
return groktypename (&type_specifier_seq, abstract_declarator,
is_template_arg);
}
@@ -22484,7 +22475,7 @@ cp_parser_parameter_declaration (cp_parser *parser,
/* Consume the `...'. */
cp_lexer_consume_token (parser->lexer);
maybe_warn_variadic_templates ();
-
+
/* Build a pack expansion type */
if (template_parm_p)
template_parameter_pack_p = true;
@@ -22538,11 +22529,11 @@ cp_parser_parameter_declaration (cp_parser *parser,
|| (decl_specifiers.type
&& PACK_EXPANSION_P (decl_specifiers.type)))
{
- /* Find the name of the parameter pack. */
+ /* Find the name of the parameter pack. */
cp_declarator *id_declarator = declarator;
while (id_declarator && id_declarator->kind != cdk_id)
id_declarator = id_declarator->declarator;
-
+
if (id_declarator && id_declarator->kind == cdk_id)
error_at (declarator_token_start->location,
template_parm_p
@@ -22833,7 +22824,7 @@ cp_parser_initializer_clause (cp_parser* parser, bool* non_constant_p)
production is used). The TREE_TYPE for the CONSTRUCTOR will be
NULL_TREE. There is no way to detect whether or not the optional
trailing `,' was provided. NON_CONSTANT_P is as for
- cp_parser_initializer. */
+ cp_parser_initializer. */
static cp_expr
cp_parser_braced_list (cp_parser* parser, bool* non_constant_p)
@@ -22934,7 +22925,7 @@ cp_parser_array_designator_p (cp_parser *parser)
bool array_designator_p
= (cp_parser_skip_to_closing_square_bracket (parser)
&& cp_lexer_next_token_is (parser->lexer, CPP_EQ));
-
+
/* Roll back the tokens we skipped. */
cp_lexer_rollback_tokens (parser->lexer);
@@ -23322,7 +23313,7 @@ cp_parser_class_name (cp_parser *parser,
/* In Objective-C 2.0, a classname followed by '.' starts a
dot-syntax expression, and it's not a type-name. */
|| (c_dialect_objc ()
- && cp_lexer_peek_token (parser->lexer)->type == CPP_DOT
+ && cp_lexer_peek_token (parser->lexer)->type == CPP_DOT
&& objc_is_class_name (decl)))
decl = error_mark_node;
@@ -23334,6 +23325,34 @@ cp_parser_class_name (cp_parser *parser,
return decl;
}
+/* Make sure that any member-function parameters are in scope.
+ For instance, a function's noexcept-specifier can use the function's
+ parameters:
+
+ struct S {
+ void fn (int p) noexcept(noexcept(p));
+ };
+
+ so we need to make sure name lookup can find them. This is used
+ when we delay parsing of the noexcept-specifier. */
+
+static void
+inject_parm_decls (tree decl)
+{
+ begin_scope (sk_function_parms, decl);
+ tree args = DECL_ARGUMENTS (decl);
+
+ do_push_parm_decls (decl, args, /*nonparms=*/NULL);
+}
+
+/* Undo the effects of inject_parm_decls. */
+
+static void
+pop_injected_parms (void)
+{
+ pop_bindings_and_leave_scope ();
+}
+
/* Parse a class-specifier.
class-specifier:
@@ -23644,6 +23663,60 @@ cp_parser_class_specifier_1 (cp_parser* parser)
vec_safe_truncate (unparsed_classes, 0);
after_nsdmi_defaulted_late_checks (type);
+ /* If there are noexcept-specifiers that have not yet been processed,
+ take care of them now. */
+ class_type = NULL_TREE;
+ pushed_scope = NULL_TREE;
+ FOR_EACH_VEC_SAFE_ELT (unparsed_noexcepts, ix, decl)
+ {
+ tree ctx = DECL_CONTEXT (decl);
+ if (class_type != ctx)
+ {
+ if (pushed_scope)
+ pop_scope (pushed_scope);
+ class_type = ctx;
+ pushed_scope = push_scope (class_type);
+ }
+
+ tree spec = TYPE_RAISES_EXCEPTIONS (TREE_TYPE (decl));
+ spec = TREE_PURPOSE (spec);
+
+ /* Make sure that any template parameters are in scope. */
+ maybe_begin_member_template_processing (decl);
+
+ /* Make sure that any member-function parameters are in scope. */
+ inject_parm_decls (decl);
+
+ /* 'this' is not allowed in static member functions. */
+ unsigned char local_variables_forbidden_p
+ = parser->local_variables_forbidden_p;
+ if (DECL_THIS_STATIC (decl))
+ parser->local_variables_forbidden_p |= THIS_FORBIDDEN;
+
+ /* Now we can parse the noexcept-specifier. */
+ spec = cp_parser_late_noexcept_specifier (parser, spec);
+
+ if (spec != error_mark_node)
+ TREE_TYPE (decl) = build_exception_variant (TREE_TYPE (decl), spec);
+
+ /* Restore the state of local_variables_forbidden_p. */
+ parser->local_variables_forbidden_p = local_variables_forbidden_p;
+
+ /* The finish_struct call above performed various override checking,
+ but it skipped unparsed noexcept-specifier operands. Now that we
+ have resolved them, check again. */
+ noexcept_override_late_checks (type, decl);
+
+ /* Remove any member-function parameters from the symbol table. */
+ pop_injected_parms ();
+
+ /* Remove any template parameters from the symbol table. */
+ maybe_end_member_template_processing ();
+ }
+ vec_safe_truncate (unparsed_noexcepts, 0);
+ if (pushed_scope)
+ pop_scope (pushed_scope);
+
/* Now parse the body of the functions. */
if (flag_openmp)
{
@@ -24223,7 +24296,7 @@ cp_parser_type_parameter_key (cp_parser* parser)
if (pedantic && tag_type == typename_type && cxx_dialect < cxx17)
/* typename is not allowed in a template template parameter
by the standard until C++17. */
- pedwarn (token->location, OPT_Wpedantic,
+ pedwarn (token->location, OPT_Wpedantic,
"ISO C++ forbids typename key in template template parameter;"
" use %<-std=c++17%> or %<-std=gnu++17%>");
}
@@ -24312,7 +24385,7 @@ cp_parser_member_specification_opt (cp_parser* parser)
member-declarator:
declarator attributes [opt] pure-specifier [opt]
declarator attributes [opt] constant-initializer [opt]
- identifier [opt] attributes [opt] : constant-expression
+ identifier [opt] attributes [opt] : constant-expression
C++0x Extensions:
@@ -24623,7 +24696,7 @@ cp_parser_member_declaration (cp_parser* parser)
}
}
else
- {
+ {
/* Look for attributes that apply to the bitfield after
the `:' token and width. This is where GCC used to
parse attributes in the past, pedwarn if there is
@@ -25199,6 +25272,89 @@ cp_parser_base_specifier (cp_parser* parser)
/* Exception handling [gram.exception] */
+/* Save the tokens that make up the noexcept-specifier for a member-function.
+ Returns a DEFERRED_PARSE. */
+
+static tree
+cp_parser_save_noexcept (cp_parser *parser)
+{
+ cp_token *first = parser->lexer->next_token;
+ /* We want everything up to, including, the final ')'. */
+ cp_parser_cache_group (parser, CPP_CLOSE_PAREN, /*depth=*/0);
+ cp_token *last = parser->lexer->next_token;
+
+ /* As with default arguments and NSDMIs, make use of DEFERRED_PARSE
+ to carry the information we will need. */
+ tree expr = make_node (DEFERRED_PARSE);
+ /* Save away the noexcept-specifier; we will process it when the
+ class is complete. */
+ DEFPARSE_TOKENS (expr) = cp_token_cache_new (first, last);
+ expr = build_tree_list (expr, NULL_TREE);
+ return expr;
+}
+
+/* Used for late processing of noexcept-specifiers of member-functions.
+ DEFAULT_ARG is the unparsed operand of a noexcept-specifier which
+ we saved for later; parse it now. */
+
+static tree
+cp_parser_late_noexcept_specifier (cp_parser *parser, tree default_arg)
+{
+ /* Make sure we've gotten something that hasn't been parsed yet. */
+ gcc_assert (TREE_CODE (default_arg) == DEFERRED_PARSE);
+
+ push_unparsed_function_queues (parser);
+
+ /* Push the saved tokens for the noexcept-specifier onto the parser's
+ lexer stack. */
+ cp_token_cache *tokens = DEFPARSE_TOKENS (default_arg);
+ cp_parser_push_lexer_for_tokens (parser, tokens);
+
+ /* Parse the cached noexcept-specifier. */
+ tree parsed_arg
+ = cp_parser_noexcept_specification_opt (parser,
+ /*require_constexpr=*/true,
+ /*consumed_expr=*/NULL,
+ /*return_cond=*/false,
+ /*friend_p=*/false);
+
+ /* Revert to the main lexer. */
+ cp_parser_pop_lexer (parser);
+
+ /* Restore the queue. */
+ pop_unparsed_function_queues (parser);
+
+ /* And we're done. */
+ return parsed_arg;
+}
+
+/* Perform late checking of overriding function with respect to their
+ noexcept-specifiers. TYPE is the class and FNDECL is the function
+ that potentially overrides some virtual function with the same
+ signature. */
+
+static void
+noexcept_override_late_checks (tree type, tree fndecl)
+{
+ tree binfo = TYPE_BINFO (type);
+ tree base_binfo;
+
+ if (DECL_STATIC_FUNCTION_P (fndecl))
+ return;
+
+ for (int i = 0; BINFO_BASE_ITERATE (binfo, i, base_binfo); ++i)
+ {
+ tree basetype = BINFO_TYPE (base_binfo);
+
+ if (!TYPE_POLYMORPHIC_P (basetype))
+ continue;
+
+ tree fn = look_for_overrides_here (basetype, fndecl);
+ if (fn)
+ maybe_check_overriding_exception_spec (fndecl, fn);
+ }
+}
+
/* Parse an (optional) noexcept-specification.
noexcept-specification:
@@ -25209,13 +25365,15 @@ cp_parser_base_specifier (cp_parser* parser)
expression if parentheses follow noexcept, or return BOOLEAN_TRUE_NODE if
there are no parentheses. CONSUMED_EXPR will be set accordingly.
Otherwise, returns a noexcept specification unless RETURN_COND is true,
- in which case a boolean condition is returned instead. */
+ in which case a boolean condition is returned instead. If FRIEND_P is true,
+ the function with this noexcept-specification had the `friend' specifier. */
static tree
cp_parser_noexcept_specification_opt (cp_parser* parser,
bool require_constexpr,
bool* consumed_expr,
- bool return_cond)
+ bool return_cond,
+ bool friend_p)
{
cp_token *token;
const char *saved_message;
@@ -25227,6 +25385,27 @@ cp_parser_noexcept_specification_opt (cp_parser* parser,
if (cp_parser_is_keyword (token, RID_NOEXCEPT))
{
tree expr;
+
+ /* [class.mem]/6 says that a noexcept-specifer (within the
+ member-specification of the class) is a complete-class context of
+ a class. So, if the noexcept-specifier has the optional expression,
+ just save the tokens, and reparse this after we're done with the
+ class. */
+ const bool literal_p
+ = ((cp_lexer_nth_token_is (parser->lexer, 3, CPP_NUMBER)
+ || cp_lexer_nth_token_is (parser->lexer, 3, CPP_KEYWORD))
+ && cp_lexer_nth_token_is (parser->lexer, 4, CPP_CLOSE_PAREN));
+
+ if (cp_lexer_nth_token_is (parser->lexer, 2, CPP_OPEN_PAREN)
+ /* No need to delay parsing for a number literal or true/false. */
+ && !literal_p
+ && at_class_scope_p ()
+ /* Don't delay parsing for friend member functions. */
+ && !friend_p
+ && TYPE_BEING_DEFINED (current_class_type)
+ && !LAMBDA_TYPE_P (current_class_type))
+ return cp_parser_save_noexcept (parser);
+
cp_lexer_consume_token (parser->lexer);
if (cp_lexer_peek_token (parser->lexer)->type == CPP_OPEN_PAREN)
@@ -25297,10 +25476,11 @@ cp_parser_noexcept_specification_opt (cp_parser* parser,
throw ( type-id-list [opt] )
Returns a TREE_LIST representing the exception-specification. The
- TREE_VALUE of each node is a type. */
+ TREE_VALUE of each node is a type. If FRIEND_P is true, the function
+ with this noexcept-specification had the `friend' specifier. */
static tree
-cp_parser_exception_specification_opt (cp_parser* parser)
+cp_parser_exception_specification_opt (cp_parser* parser, bool friend_p)
{
cp_token *token;
tree type_id_list;
@@ -25310,8 +25490,12 @@ cp_parser_exception_specification_opt (cp_parser* parser)
token = cp_lexer_peek_token (parser->lexer);
/* Is it a noexcept-specification? */
- type_id_list = cp_parser_noexcept_specification_opt (parser, true, NULL,
- false);
+ type_id_list
+ = cp_parser_noexcept_specification_opt (parser,
+ /*require_constexpr=*/true,
+ /*consumed_expr=*/NULL,
+ /*return_cond=*/false,
+ friend_p);
if (type_id_list != NULL_TREE)
return type_id_list;
@@ -25698,8 +25882,8 @@ cp_parser_asm_operand_list (cp_parser* parser)
/* Look for the `)'. */
parens.require_close (parser);
- if (name == error_mark_node
- || string_literal == error_mark_node
+ if (name == error_mark_node
+ || string_literal == error_mark_node
|| expression == error_mark_node)
invalid_operands = true;
@@ -25982,7 +26166,7 @@ cp_parser_gnu_attribute_list (cp_parser* parser, bool exactly_one /* = false */)
/* Save away the identifier that indicates which attribute
this is. */
- identifier = (token->type == CPP_KEYWORD)
+ identifier = (token->type == CPP_KEYWORD)
/* For keywords, use the canonical spelling, not the
parsed identifier. */
? ridpointers[(int) token->keyword]
@@ -25999,9 +26183,9 @@ cp_parser_gnu_attribute_list (cp_parser* parser, bool exactly_one /* = false */)
vec<tree, va_gc> *vec;
int attr_flag = (attribute_takes_identifier_p (identifier)
? id_attr : normal_attr);
- vec = cp_parser_parenthesized_expression_list
- (parser, attr_flag, /*cast_p=*/false,
- /*allow_expansion_p=*/false,
+ vec = cp_parser_parenthesized_expression_list
+ (parser, attr_flag, /*cast_p=*/false,
+ /*allow_expansion_p=*/false,
/*non_constant_p=*/NULL);
if (vec == NULL)
arguments = error_mark_node;
@@ -26145,11 +26329,11 @@ cp_parser_std_attribute (cp_parser *parser, tree attr_ns)
attr_id = canonicalize_attr_name (attr_id);
attribute = build_tree_list (build_tree_list (NULL_TREE, attr_id),
NULL_TREE);
- /* C++11 noreturn attribute is equivalent to GNU's. */
- if (is_attribute_p ("noreturn", attr_id))
- TREE_PURPOSE (TREE_PURPOSE (attribute)) = gnu_identifier;
+ /* We used to treat C++11 noreturn attribute as equivalent to GNU's,
+ but no longer: we have to be able to tell [[noreturn]] and
+ __attribute__((noreturn)) apart. */
/* C++14 deprecated attribute is equivalent to GNU's. */
- else if (is_attribute_p ("deprecated", attr_id))
+ if (is_attribute_p ("deprecated", attr_id))
TREE_PURPOSE (TREE_PURPOSE (attribute)) = gnu_identifier;
/* C++17 fallthrough attribute is equivalent to GNU's. */
else if (is_attribute_p ("fallthrough", attr_id))
@@ -26173,6 +26357,20 @@ cp_parser_std_attribute (cp_parser *parser, tree attr_ns)
vec<tree, va_gc> *vec;
int attr_flag = normal_attr;
+ /* Maybe we don't expect to see any arguments for this attribute. */
+ const attribute_spec *as
+ = lookup_attribute_spec (TREE_PURPOSE (attribute));
+ if (as && as->max_length == 0)
+ {
+ error_at (token->location, "%qE attribute does not take any arguments",
+ attr_id);
+ cp_parser_skip_to_closing_parenthesis (parser,
+ /*recovering=*/true,
+ /*or_comma=*/false,
+ /*consume_paren=*/true);
+ return error_mark_node;
+ }
+
if (attr_ns == gnu_identifier
&& attribute_takes_identifier_p (attr_id))
/* A GNU attribute that takes an identifier in parameter. */
@@ -26381,6 +26579,12 @@ cp_parser_std_attribute_spec (cp_parser *parser)
if (alignas_expr == error_mark_node)
return error_mark_node;
+ /* Missing ')' means the code cannot possibly be valid; go ahead
+ and commit to make sure we issue a hard error. */
+ if (cp_parser_uncommitted_to_tentative_parse_p (parser)
+ && cp_lexer_next_token_is_not (parser->lexer, CPP_CLOSE_PAREN))
+ cp_parser_commit_to_tentative_parse (parser);
+
if (!parens.require_close (parser))
return error_mark_node;
@@ -27334,7 +27538,7 @@ cp_parser_check_declarator_template_parameters (cp_parser* parser,
template_id_p = true;
}
- return cp_parser_check_template_parameters
+ return cp_parser_check_template_parameters
(parser, num_templates, template_id_p, declarator_location,
declarator);
}
@@ -27386,14 +27590,14 @@ cp_parser_check_template_parameters (cp_parser* parser,
{
if (declarator && !current_function_decl)
error_at (location, "specializing member %<%T::%E%> "
- "requires %<template<>%> syntax",
+ "requires %<template<>%> syntax",
declarator->u.id.qualifying_scope,
declarator->u.id.unqualified_name);
else if (declarator)
error_at (location, "invalid declaration of %<%T::%E%>",
declarator->u.id.qualifying_scope,
declarator->u.id.unqualified_name);
- else
+ else
error_at (location, "too few template-parameter-lists");
return false;
}
@@ -27629,9 +27833,19 @@ cp_parser_constructor_declarator_p (cp_parser *parser, cp_parser_flags flags,
parser->num_template_parameter_lists = 0;
/* Look for the type-specifier. It's not optional, but its typename
- might be. */
+ might be. Unless this is a friend declaration; we don't want to
+ treat
+
+ friend S (T::fn)(int);
+
+ as a constructor, but with P0634, we might assume a type when
+ looking for the type-specifier. It is actually a function named
+ `T::fn' that takes one parameter (of type `int') and returns a
+ value of type `S'. Constructors can be friends, but they must
+ use a qualified name. */
cp_parser_type_specifier (parser,
- (flags & ~CP_PARSER_FLAGS_OPTIONAL),
+ (friend_p ? CP_PARSER_FLAGS_NONE
+ : (flags & ~CP_PARSER_FLAGS_OPTIONAL)),
/*decl_specs=*/NULL,
/*is_declarator=*/true,
/*declares_class_or_enum=*/NULL,
@@ -27931,14 +28145,16 @@ cp_parser_template_declaration_after_parameters (cp_parser* parser,
if (!ok)
{
if (cxx_dialect > cxx17)
- error ("literal operator template %qD has invalid parameter list;"
- " Expected non-type template parameter pack <char...> "
- "or single non-type parameter of class type",
- decl);
+ error_at (DECL_SOURCE_LOCATION (decl), "literal operator "
+ "template %qD has invalid parameter list; expected "
+ "non-type template parameter pack %<<char...>%> or "
+ "single non-type parameter of class type",
+ decl);
else
- error ("literal operator template %qD has invalid parameter list."
- " Expected non-type template parameter pack <char...>",
- decl);
+ error_at (DECL_SOURCE_LOCATION (decl), "literal operator "
+ "template %qD has invalid parameter list; expected "
+ "non-type template parameter pack %<<char...>%>",
+ decl);
}
}
@@ -28427,7 +28643,7 @@ cp_parser_save_member_function_body (cp_parser* parser,
return error_mark_node;
}
- /* Remember it, if there default args to post process. */
+ /* Remember it, if there are default args to post process. */
cp_parser_save_default_args (parser, fn);
/* Save away the tokens that make up the body of the
@@ -28508,7 +28724,7 @@ cp_parser_save_member_function_body (cp_parser* parser,
}
/* Save the tokens that make up the in-class initializer for a non-static
- data member. Returns a DEFAULT_ARG. */
+ data member. Returns a DEFERRED_PARSE. */
static tree
cp_parser_save_nsdmi (cp_parser* parser)
@@ -28720,6 +28936,11 @@ cp_parser_save_default_args (cp_parser* parser, tree decl)
vec_safe_push (unparsed_funs_with_default_args, entry);
break;
}
+
+ /* Remember if there is a noexcept-specifier to post process. */
+ tree spec = TYPE_RAISES_EXCEPTIONS (TREE_TYPE (decl));
+ if (UNPARSED_NOEXCEPT_SPEC_P (spec))
+ vec_safe_push (unparsed_noexcepts, decl);
}
/* DEFAULT_ARG contains the saved tokens for the initializer of DECL,
@@ -28740,7 +28961,7 @@ cp_parser_late_parse_one_default_arg (cp_parser *parser, tree decl,
/* Push the saved tokens for the default argument onto the parser's
lexer stack. */
- tokens = DEFARG_TOKENS (default_arg);
+ tokens = DEFPARSE_TOKENS (default_arg);
cp_parser_push_lexer_for_tokens (parser, tokens);
start_lambda_scope (decl);
@@ -28807,7 +29028,7 @@ cp_parser_late_parsing_nsdmi (cp_parser *parser, tree field)
}
/* FN is a FUNCTION_DECL which may contains a parameter with an
- unparsed DEFAULT_ARG. Parse the default args now. This function
+ unparsed DEFERRED_PARSE. Parse the default args now. This function
assumes that the current scope is the scope in which the default
argument should be processed. */
@@ -28845,7 +29066,7 @@ cp_parser_late_parsing_default_args (cp_parser *parser, tree fn)
if (!default_arg)
continue;
- if (TREE_CODE (default_arg) != DEFAULT_ARG)
+ if (TREE_CODE (default_arg) != DEFERRED_PARSE)
/* This can happen for a friend declaration for a function
already declared with default arguments. */
continue;
@@ -28857,7 +29078,7 @@ cp_parser_late_parsing_default_args (cp_parser *parser, tree fn)
TREE_PURPOSE (parm) = parsed_arg;
/* Update any instantiations we've already created. */
- for (insts = DEFARG_INSTANTIATIONS (default_arg), ix = 0;
+ for (insts = DEFPARSE_INSTANTIATIONS (default_arg), ix = 0;
vec_safe_iterate (insts, ix, &copy); ix++)
TREE_PURPOSE (copy) = parsed_arg;
}
@@ -28966,6 +29187,8 @@ cp_parser_sizeof_operand (cp_parser* parser, enum rid keyword)
{
tree type = NULL_TREE;
+ tentative_firewall firewall (parser);
+
/* We can't be sure yet whether we're looking at a type-id or an
expression. */
cp_parser_parse_tentatively (parser);
@@ -28993,11 +29216,15 @@ cp_parser_sizeof_operand (cp_parser* parser, enum rid keyword)
/* If all went well, then we're done. */
if (cp_parser_parse_definitely (parser))
expr = type;
- }
+ else
+ {
+ /* Commit to the tentative_firewall so we get syntax errors. */
+ cp_parser_commit_to_tentative_parse (parser);
- /* If the type-id production did not work out, then we must be
- looking at the unary-expression production. */
- if (!expr)
+ expr = cp_parser_unary_expression (parser);
+ }
+ }
+ else
expr = cp_parser_unary_expression (parser);
/* Go back to evaluating expressions. */
@@ -29080,8 +29307,8 @@ cp_parser_set_storage_class (cp_parser *parser,
decl_specs->storage_class = storage_class;
set_and_check_decl_spec_loc (decl_specs, ds_storage_class, token);
- /* A storage class specifier cannot be applied alongside a typedef
- specifier. If there is a typedef specifier present then set
+ /* A storage class specifier cannot be applied alongside a typedef
+ specifier. If there is a typedef specifier present then set
conflicting_specifiers_p which will trigger an error later
on in grokdeclarator. */
if (decl_spec_seq_has_spec_p (decl_specs, ds_typedef))
@@ -29188,7 +29415,7 @@ set_and_check_decl_spec_loc (cp_decl_specifier_seq *decl_specs,
{
decl_specs->locations[ds_long_long] = location;
pedwarn_cxx98 (location,
- OPT_Wlong_long,
+ OPT_Wlong_long,
"ISO C++ 1998 does not support %<long long%>");
}
}
@@ -29616,7 +29843,7 @@ cp_parser_next_token_ends_template_argument_p (cp_parser *parser)
cp_token *token;
token = cp_lexer_peek_token (parser->lexer);
- return (token->type == CPP_COMMA
+ return (token->type == CPP_COMMA
|| token->type == CPP_GREATER
|| token->type == CPP_ELLIPSIS
|| ((cxx_dialect != cxx98) && token->type == CPP_RSHIFT));
@@ -30018,22 +30245,22 @@ cp_parser_cache_defarg (cp_parser *parser, bool nsdmi)
token = cp_lexer_consume_token (parser->lexer);
}
- /* Create a DEFAULT_ARG to represent the unparsed default
+ /* Create a DEFERRED_PARSE to represent the unparsed default
argument. */
- default_argument = make_node (DEFAULT_ARG);
- DEFARG_TOKENS (default_argument)
+ default_argument = make_node (DEFERRED_PARSE);
+ DEFPARSE_TOKENS (default_argument)
= cp_token_cache_new (first_token, token);
- DEFARG_INSTANTIATIONS (default_argument) = NULL;
+ DEFPARSE_INSTANTIATIONS (default_argument) = NULL;
return default_argument;
}
-/* A location to use for diagnostics about an unparsed DEFAULT_ARG. */
+/* A location to use for diagnostics about an unparsed DEFERRED_PARSE. */
location_t
-defarg_location (tree default_argument)
+defparse_location (tree default_argument)
{
- cp_token_cache *tokens = DEFARG_TOKENS (default_argument);
+ cp_token_cache *tokens = DEFPARSE_TOKENS (default_argument);
location_t start = tokens->first->location;
location_t end = tokens->last->location;
return make_location (start, start, end);
@@ -30301,7 +30528,7 @@ cp_parser_objc_message_receiver (cp_parser* parser)
if (cp_parser_parse_definitely (parser))
return objc_get_class_reference (rcv);
-
+
cp_parser_error (parser, "objective-c++ message receiver expected");
return error_mark_node;
}
@@ -30402,7 +30629,7 @@ cp_parser_objc_encode_expression (cp_parser* parser)
if (!type)
{
- error_at (token->location,
+ error_at (token->location,
"%<@encode%> must specify a type as an argument");
return error_mark_node;
}
@@ -30584,7 +30811,7 @@ cp_parser_objc_identifier_list (cp_parser* parser)
identifier = cp_parser_identifier (parser);
if (identifier == error_mark_node)
- return error_mark_node;
+ return error_mark_node;
list = build_tree_list (NULL_TREE, identifier);
sep = cp_lexer_peek_token (parser->lexer);
@@ -30600,7 +30827,7 @@ cp_parser_objc_identifier_list (cp_parser* parser)
identifier));
sep = cp_lexer_peek_token (parser->lexer);
}
-
+
return list;
}
@@ -30639,11 +30866,11 @@ cp_parser_objc_class_declaration (cp_parser* parser)
while (true)
{
tree id;
-
+
id = cp_parser_identifier (parser);
if (id == error_mark_node)
break;
-
+
objc_declare_class (id);
if (cp_lexer_next_token_is (parser->lexer, CPP_COMMA))
@@ -30767,7 +30994,7 @@ cp_parser_objc_typename (cp_parser* parser)
if (cp_lexer_next_token_is_not (parser->lexer, CPP_CLOSE_PAREN))
{
cp_type = cp_parser_type_id (parser);
-
+
/* If the type could not be parsed, an error has already
been produced. For error recovery, behave as if it had
not been specified, which will use the default type
@@ -30899,7 +31126,7 @@ cp_parser_objc_method_keyword_params (cp_parser* parser, tree* attributes)
if (cp_lexer_next_token_is (parser->lexer, CPP_SEMICOLON)
|| cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE))
return params;
- cp_parser_error (parser,
+ cp_parser_error (parser,
"method attributes must be specified at the end");
return error_mark_node;
}
@@ -30915,7 +31142,7 @@ cp_parser_objc_method_keyword_params (cp_parser* parser, tree* attributes)
/* Parse the non-keyword Objective-C params. */
static tree
-cp_parser_objc_method_tail_params_opt (cp_parser* parser, bool *ellipsisp,
+cp_parser_objc_method_tail_params_opt (cp_parser* parser, bool *ellipsisp,
tree* attributes)
{
tree params = make_node (TREE_LIST);
@@ -30960,12 +31187,12 @@ cp_parser_objc_method_tail_params_opt (cp_parser* parser, bool *ellipsisp,
|| cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE))
return params;
}
- else
- /* We have an error, but parse the attributes, so that we can
+ else
+ /* We have an error, but parse the attributes, so that we can
carry on. */
*attributes = cp_parser_attributes_opt (parser);
- cp_parser_error (parser,
+ cp_parser_error (parser,
"method attributes must be specified at the end");
return error_mark_node;
}
@@ -31042,11 +31269,11 @@ cp_parser_objc_method_signature (cp_parser* parser, tree* attributes)
static bool
cp_parser_objc_method_maybe_bad_prefix_attributes (cp_parser* parser)
{
- tree tattr;
+ tree tattr;
cp_lexer_save_tokens (parser->lexer);
tattr = cp_parser_attributes_opt (parser);
gcc_assert (tattr) ;
-
+
/* If the attributes are followed by a method introducer, this is not allowed.
Dump the attributes and flag the situation. */
if (cp_lexer_next_token_is (parser->lexer, CPP_PLUS)
@@ -31056,7 +31283,7 @@ cp_parser_objc_method_maybe_bad_prefix_attributes (cp_parser* parser)
/* Otherwise, the attributes introduce some interstitial code, possibly so
rewind to allow that check. */
cp_lexer_rollback_tokens (parser->lexer);
- return false;
+ return false;
}
/* Parse an Objective-C method prototype list. */
@@ -31088,10 +31315,10 @@ cp_parser_objc_method_prototype_list (cp_parser* parser)
}
else if (token->keyword == RID_AT_PROPERTY)
cp_parser_objc_at_property_declaration (parser);
- else if (token->keyword == RID_ATTRIBUTE
+ else if (token->keyword == RID_ATTRIBUTE
&& cp_parser_objc_method_maybe_bad_prefix_attributes(parser))
- warning_at (cp_lexer_peek_token (parser->lexer)->location,
- OPT_Wattributes,
+ warning_at (cp_lexer_peek_token (parser->lexer)->location,
+ OPT_Wattributes,
"prefix attributes are ignored for methods");
else
/* Allow for interspersed non-ObjC++ code. */
@@ -31144,7 +31371,7 @@ cp_parser_objc_method_definition_list (cp_parser* parser)
cp_lexer_consume_token (parser->lexer);
ptk = cp_lexer_peek_token (parser->lexer);
- if (!(ptk->type == CPP_PLUS || ptk->type == CPP_MINUS
+ if (!(ptk->type == CPP_PLUS || ptk->type == CPP_MINUS
|| ptk->type == CPP_EOF || ptk->keyword == RID_AT_END))
{
perform_deferred_access_checks (tf_warning_or_error);
@@ -31163,7 +31390,7 @@ cp_parser_objc_method_definition_list (cp_parser* parser)
cp_parser_objc_at_synthesize_declaration (parser);
else if (token->keyword == RID_AT_DYNAMIC)
cp_parser_objc_at_dynamic_declaration (parser);
- else if (token->keyword == RID_ATTRIBUTE
+ else if (token->keyword == RID_ATTRIBUTE
&& cp_parser_objc_method_maybe_bad_prefix_attributes(parser))
warning_at (token->location, OPT_Wattributes,
"prefix attributes are ignored for methods");
@@ -31195,7 +31422,7 @@ cp_parser_objc_class_ivars (cp_parser* parser)
cp_lexer_consume_token (parser->lexer); /* Eat '{'. */
token = cp_lexer_peek_token (parser->lexer);
- while (token->type != CPP_CLOSE_BRACE
+ while (token->type != CPP_CLOSE_BRACE
&& token->keyword != RID_AT_END && token->type != CPP_EOF)
{
cp_decl_specifier_seq declspecs;
@@ -31215,7 +31442,7 @@ cp_parser_objc_class_ivars (cp_parser* parser)
/* auto, register, static, extern, mutable. */
if (declspecs.storage_class != sc_none)
{
- cp_parser_error (parser, "invalid type for instance variable");
+ cp_parser_error (parser, "invalid type for instance variable");
declspecs.storage_class = sc_none;
}
@@ -31225,7 +31452,7 @@ cp_parser_objc_class_ivars (cp_parser* parser)
cp_parser_error (parser, "invalid type for instance variable");
declspecs.locations[ds_thread] = 0;
}
-
+
/* typedef. */
if (decl_spec_seq_has_spec_p (&declspecs, ds_typedef))
{
@@ -31325,10 +31552,10 @@ cp_parser_objc_class_ivars (cp_parser* parser)
cp_parser_error (parser, "expected %<}%>");
/* Do not consume the RID_AT_END, so it will be read again as terminating
- the @interface of @implementation. */
+ the @interface of @implementation. */
if (token->keyword != RID_AT_END && token->type != CPP_EOF)
cp_lexer_consume_token (parser->lexer); /* Eat '}'. */
-
+
/* For historical reasons, we accept an optional semicolon. */
if (cp_lexer_next_token_is (parser->lexer, CPP_SEMICOLON))
cp_lexer_consume_token (parser->lexer);
@@ -31360,13 +31587,13 @@ cp_parser_objc_protocol_declaration (cp_parser* parser, tree attributes)
while (true)
{
tree id;
-
+
id = cp_parser_identifier (parser);
if (id == error_mark_node)
break;
-
+
objc_declare_protocol (id, attributes);
-
+
if(cp_lexer_next_token_is (parser->lexer, CPP_COMMA))
cp_lexer_consume_token (parser->lexer);
else
@@ -31388,7 +31615,7 @@ cp_parser_objc_protocol_declaration (cp_parser* parser, tree attributes)
/* Parse an Objective-C superclass or category. */
static void
-cp_parser_objc_superclass_or_category (cp_parser *parser,
+cp_parser_objc_superclass_or_category (cp_parser *parser,
bool iface_p,
tree *super,
tree *categ, bool *is_class_extension)
@@ -31583,7 +31810,7 @@ cp_parser_objc_declaration (cp_parser* parser, tree attributes)
Returns NULL_TREE.
PS: This function is identical to c_parser_objc_try_catch_finally_statement
- for C. Keep them in sync. */
+ for C. Keep them in sync. */
static tree
cp_parser_objc_try_catch_finally_statement (cp_parser *parser)
@@ -31648,7 +31875,7 @@ cp_parser_objc_try_catch_finally_statement (cp_parser *parser)
going. */
if (cp_lexer_next_token_is (parser->lexer, CPP_CLOSE_PAREN))
cp_lexer_consume_token (parser->lexer);
-
+
/* If these is no immediate closing parenthesis, the user
probably doesn't know that parenthesis are required at
all (ie, they typed "@catch NSException *e"). So, just
@@ -31750,9 +31977,9 @@ cp_parser_objc_statement (cp_parser * parser)
return error_mark_node;
}
-/* If we are compiling ObjC++ and we see an __attribute__ we neeed to
+/* If we are compiling ObjC++ and we see an __attribute__ we neeed to
look ahead to see if an objc keyword follows the attributes. This
- is to detect the use of prefix attributes on ObjC @interface and
+ is to detect the use of prefix attributes on ObjC @interface and
@protocol. */
static bool
@@ -31767,7 +31994,7 @@ cp_parser_objc_valid_prefix_attributes (cp_parser* parser, tree *attrib)
return true;
}
cp_lexer_rollback_tokens (parser->lexer);
- return false;
+ return false;
}
/* This routine is a minimal replacement for
@@ -31804,14 +32031,14 @@ cp_parser_objc_struct_declaration (cp_parser *parser)
cp_parser_error (parser, "invalid type for property");
declspecs.storage_class = sc_none;
}
-
+
/* thread_local. */
if (decl_spec_seq_has_spec_p (&declspecs, ds_thread))
{
cp_parser_error (parser, "invalid type for property");
declspecs.locations[ds_thread] = 0;
}
-
+
/* typedef. */
if (decl_spec_seq_has_spec_p (&declspecs, ds_typedef))
{
@@ -31848,7 +32075,7 @@ cp_parser_objc_struct_declaration (cp_parser *parser)
if (decl == error_mark_node || decl == NULL_TREE)
return error_mark_node;
-
+
/* Reset PREFIX_ATTRIBUTES. */
if (attributes != error_mark_node)
{
@@ -31903,7 +32130,7 @@ cp_parser_objc_struct_declaration (cp_parser *parser)
PS: This function is identical to
c_parser_objc_at_property_declaration for C. Keep them in sync. */
-static void
+static void
cp_parser_objc_at_property_declaration (cp_parser *parser)
{
/* The following variables hold the attributes of the properties as
@@ -32054,7 +32281,7 @@ cp_parser_objc_at_property_declaration (cp_parser *parser)
/* Comma-separated properties are chained together in
reverse order; add them one by one. */
properties = nreverse (properties);
-
+
for (; properties; properties = TREE_CHAIN (properties))
objc_add_property_declaration (loc, copy_node (properties),
property_readonly, property_readwrite,
@@ -32062,7 +32289,7 @@ cp_parser_objc_at_property_declaration (cp_parser *parser)
property_copy, property_nonatomic,
property_getter_ident, property_setter_ident);
}
-
+
cp_parser_consume_semicolon_at_end_of_statement (parser);
}
@@ -32086,7 +32313,7 @@ cp_parser_objc_at_property_declaration (cp_parser *parser)
PS: This function is identical to c_parser_objc_at_synthesize_declaration
for C. Keep them in sync.
*/
-static void
+static void
cp_parser_objc_at_synthesize_declaration (cp_parser *parser)
{
tree list = NULL_TREE;
@@ -32137,7 +32364,7 @@ cp_parser_objc_at_synthesize_declaration (cp_parser *parser)
PS: This function is identical to c_parser_objc_at_dynamic_declaration
for C. Keep them in sync.
*/
-static void
+static void
cp_parser_objc_at_dynamic_declaration (cp_parser *parser)
{
tree list = NULL_TREE;
@@ -32920,7 +33147,7 @@ cp_parser_oacc_clause_tile (cp_parser *parser, location_t clause_loc, tree list)
{
if (tile && !cp_parser_require (parser, CPP_COMMA, RT_COMMA))
return list;
-
+
if (cp_lexer_next_token_is (parser->lexer, CPP_MULT)
&& (cp_lexer_nth_token_is (parser->lexer, 2, CPP_COMMA)
|| cp_lexer_nth_token_is (parser->lexer, 2, CPP_CLOSE_PAREN)))
@@ -33791,11 +34018,7 @@ cp_parser_omp_clause_reduction (cp_parser *parser, enum omp_clause_code kind,
if (strcmp (p, "task") == 0)
task = true;
else if (strcmp (p, "inscan") == 0)
- {
- inscan = true;
- sorry ("%<inscan%> modifier on %<reduction%> clause "
- "not supported yet");
- }
+ inscan = true;
if (task || inscan)
{
cp_lexer_consume_token (parser->lexer);
@@ -34249,7 +34472,7 @@ cp_parser_omp_clause_lastprivate (cp_parser *parser, tree list)
linear ( modifier ( variable-list ) : expression ) */
static tree
-cp_parser_omp_clause_linear (cp_parser *parser, tree list,
+cp_parser_omp_clause_linear (cp_parser *parser, tree list,
bool declare_simd)
{
tree nlist, c, step = integer_one_node;
@@ -36430,7 +36653,7 @@ cp_parser_omp_for_incr (cp_parser *parser, tree decl)
static tree
cp_parser_omp_for_loop_init (cp_parser *parser,
tree &this_pre_body,
- vec<tree, va_gc> *&for_block,
+ releasing_vec &for_block,
tree &init,
tree &orig_init,
tree &decl,
@@ -36477,10 +36700,10 @@ cp_parser_omp_for_loop_init (cp_parser *parser,
attributes = cp_parser_attributes_opt (parser);
asm_specification = cp_parser_asm_specification_opt (parser);
- if (declarator == cp_error_declarator)
+ if (declarator == cp_error_declarator)
cp_parser_skip_to_end_of_statement (parser);
- else
+ else
{
tree pushed_scope, auto_node;
@@ -36492,7 +36715,7 @@ cp_parser_omp_for_loop_init (cp_parser *parser,
auto_node = type_uses_auto (TREE_TYPE (decl));
if (cp_lexer_next_token_is_not (parser->lexer, CPP_EQ))
{
- if (cp_lexer_next_token_is (parser->lexer,
+ if (cp_lexer_next_token_is (parser->lexer,
CPP_OPEN_PAREN))
error ("parenthesized initialization is not allowed in "
"OpenMP %<for%> loop");
@@ -36523,7 +36746,7 @@ cp_parser_omp_for_loop_init (cp_parser *parser,
&& !type_dependent_expression_p (decl))
goto non_class;
}
-
+
cp_finish_decl (decl, init, !is_non_constant_init,
asm_specification,
LOOKUP_ONLYCONVERTING);
@@ -36583,7 +36806,7 @@ cp_parser_omp_for_loop_init (cp_parser *parser,
pop_scope (pushed_scope);
}
}
- else
+ else
{
cp_id_kind idk;
/* If parsing a type specifier sequence failed, then
@@ -36838,6 +37061,63 @@ cp_finish_omp_range_for (tree orig, tree begin)
cp_finish_decomp (decl, decomp_first_name, decomp_cnt);
}
+/* OpenMP 5.0:
+
+ scan-loop-body:
+ { structured-block scan-directive structured-block } */
+
+static void
+cp_parser_omp_scan_loop_body (cp_parser *parser)
+{
+ tree substmt, clauses = NULL_TREE;
+
+ matching_braces braces;
+ if (!braces.require_open (parser))
+ return;
+
+ substmt = cp_parser_omp_structured_block (parser, NULL);
+ substmt = build2 (OMP_SCAN, void_type_node, substmt, NULL_TREE);
+ add_stmt (substmt);
+
+ cp_token *tok = cp_lexer_peek_token (parser->lexer);
+ if (cp_parser_pragma_kind (tok) == PRAGMA_OMP_SCAN)
+ {
+ enum omp_clause_code clause = OMP_CLAUSE_ERROR;
+
+ cp_lexer_consume_token (parser->lexer);
+
+ if (cp_lexer_next_token_is (parser->lexer, CPP_NAME))
+ {
+ tree id = cp_lexer_peek_token (parser->lexer)->u.value;
+ const char *p = IDENTIFIER_POINTER (id);
+ if (strcmp (p, "inclusive") == 0)
+ clause = OMP_CLAUSE_INCLUSIVE;
+ else if (strcmp (p, "exclusive") == 0)
+ clause = OMP_CLAUSE_EXCLUSIVE;
+ }
+ if (clause != OMP_CLAUSE_ERROR)
+ {
+ cp_lexer_consume_token (parser->lexer);
+ clauses = cp_parser_omp_var_list (parser, clause, NULL_TREE);
+ }
+ else
+ cp_parser_error (parser, "expected %<inclusive%> or "
+ "%<exclusive%> clause");
+
+ cp_parser_require_pragma_eol (parser, tok);
+ }
+ else
+ error ("expected %<#pragma omp scan%>");
+
+ clauses = finish_omp_clauses (clauses, C_ORT_OMP);
+ substmt = cp_parser_omp_structured_block (parser, NULL);
+ substmt = build2_loc (tok->location, OMP_SCAN, void_type_node, substmt,
+ clauses);
+ add_stmt (substmt);
+
+ braces.require_close (parser);
+}
+
/* Parse the restricted form of the for statement allowed by OpenMP. */
static tree
@@ -36851,9 +37131,10 @@ cp_parser_omp_for_loop (cp_parser *parser, enum tree_code code, tree clauses,
location_t loc_first;
bool collapse_err = false;
int i, collapse = 1, ordered = 0, count, nbraces = 0;
- vec<tree, va_gc> *for_block = make_tree_vector ();
+ releasing_vec for_block;
auto_vec<tree, 4> orig_inits;
bool tiling = false;
+ bool inscan = false;
for (cl = clauses; cl; cl = OMP_CLAUSE_CHAIN (cl))
if (OMP_CLAUSE_CODE (cl) == OMP_CLAUSE_COLLAPSE)
@@ -36869,6 +37150,10 @@ cp_parser_omp_for_loop (cp_parser *parser, enum tree_code code, tree clauses,
ordered_cl = cl;
ordered = tree_to_shwi (OMP_CLAUSE_ORDERED_EXPR (cl));
}
+ else if (OMP_CLAUSE_CODE (cl) == OMP_CLAUSE_REDUCTION
+ && OMP_CLAUSE_REDUCTION_INSCAN (cl)
+ && (code == OMP_SIMD || code == OMP_FOR))
+ inscan = true;
if (ordered && ordered < collapse)
{
@@ -37197,7 +37482,10 @@ cp_parser_omp_for_loop (cp_parser *parser, enum tree_code code, tree clauses,
}
else
body = push_stmt_list ();
- cp_parser_statement (parser, NULL_TREE, false, if_p);
+ if (inscan)
+ cp_parser_omp_scan_loop_body (parser);
+ else
+ cp_parser_statement (parser, NULL_TREE, false, if_p);
if (orig_declv)
body = finish_omp_structured_block (body);
else
@@ -37240,7 +37528,6 @@ cp_parser_omp_for_loop (cp_parser *parser, enum tree_code code, tree clauses,
else
add_stmt (t);
}
- release_tree_vector (for_block);
return ret;
}
@@ -39568,7 +39855,7 @@ cp_parser_omp_declare_reduction (cp_parser *parser, cp_token *pragma_tok,
cp_token_cache *cp;
int errs;
void *p;
-
+
/* Get the high-water mark for the DECLARATOR_OBSTACK. */
p = obstack_alloc (&declarator_obstack, 0);
@@ -39646,8 +39933,7 @@ cp_parser_omp_declare_reduction (cp_parser *parser, cp_token *pragma_tok,
|| id_equal (orig_reduc_id, "max")))))
error_at (loc, "predeclared arithmetic type %qT in "
"%<#pragma omp declare reduction%>", type);
- else if (TREE_CODE (type) == FUNCTION_TYPE
- || TREE_CODE (type) == METHOD_TYPE
+ else if (FUNC_OR_METHOD_TYPE_P (type)
|| TREE_CODE (type) == ARRAY_TYPE)
error_at (loc, "function or array type %qT in "
"%<#pragma omp declare reduction%>", type);
@@ -39655,8 +39941,8 @@ cp_parser_omp_declare_reduction (cp_parser *parser, cp_token *pragma_tok,
error_at (loc, "reference type %qT in "
"%<#pragma omp declare reduction%>", type);
else if (TYPE_QUALS_NO_ADDR_SPACE (type))
- error_at (loc, "const, volatile or __restrict qualified type %qT in "
- "%<#pragma omp declare reduction%>", type);
+ error_at (loc, "%<const%>, %<volatile%> or %<__restrict%>-qualified "
+ "type %qT in %<#pragma omp declare reduction%>", type);
else
types.safe_push (type);
@@ -40154,6 +40440,9 @@ cp_parser_oacc_routine (cp_parser *parser, cp_token *pragma_tok,
= cp_parser_oacc_all_clauses (parser, OACC_ROUTINE_CLAUSE_MASK,
"#pragma acc routine",
cp_lexer_peek_token (parser->lexer));
+ /* The clauses are in reverse order; fix that to make later diagnostic
+ emission easier. */
+ data.clauses = nreverse (data.clauses);
if (decl && is_overloaded_fn (decl)
&& (TREE_CODE (decl) != FUNCTION_DECL
@@ -40250,6 +40539,9 @@ cp_parser_late_parsing_oacc_routine (cp_parser *parser, tree attrs)
parser->oacc_routine->clauses
= cp_parser_oacc_all_clauses (parser, OACC_ROUTINE_CLAUSE_MASK,
"#pragma acc routine", pragma_tok);
+ /* The clauses are in reverse order; fix that to make later diagnostic
+ emission easier. */
+ parser->oacc_routine->clauses = nreverse (parser->oacc_routine->clauses);
cp_parser_pop_lexer (parser);
/* Later, cp_finalize_oacc_routine will process the clauses, and then set
fndecl_seen. */
@@ -40284,33 +40576,42 @@ cp_finalize_oacc_routine (cp_parser *parser, tree fndecl, bool is_defn)
return;
}
- if (oacc_get_fn_attrib (fndecl))
+ int compatible
+ = oacc_verify_routine_clauses (fndecl, &parser->oacc_routine->clauses,
+ parser->oacc_routine->loc,
+ "#pragma acc routine");
+ if (compatible < 0)
{
- error_at (parser->oacc_routine->loc,
- "%<#pragma acc routine%> already applied to %qD", fndecl);
parser->oacc_routine = NULL;
return;
}
-
- if (TREE_USED (fndecl) || (!is_defn && DECL_SAVED_TREE (fndecl)))
+ if (compatible > 0)
{
- error_at (parser->oacc_routine->loc,
- TREE_USED (fndecl)
- ? G_("%<#pragma acc routine%> must be applied before use")
- : G_("%<#pragma acc routine%> must be applied before "
- "definition"));
- parser->oacc_routine = NULL;
- return;
}
+ else
+ {
+ if (TREE_USED (fndecl) || (!is_defn && DECL_SAVED_TREE (fndecl)))
+ {
+ error_at (parser->oacc_routine->loc,
+ TREE_USED (fndecl)
+ ? G_("%<#pragma acc routine%> must be applied before"
+ " use")
+ : G_("%<#pragma acc routine%> must be applied before"
+ " definition"));
+ parser->oacc_routine = NULL;
+ return;
+ }
- /* Process the routine's dimension clauses. */
- tree dims = oacc_build_routine_dims (parser->oacc_routine->clauses);
- oacc_replace_fn_attrib (fndecl, dims);
+ /* Set the routine's level of parallelism. */
+ tree dims = oacc_build_routine_dims (parser->oacc_routine->clauses);
+ oacc_replace_fn_attrib (fndecl, dims);
- /* Add an "omp declare target" attribute. */
- DECL_ATTRIBUTES (fndecl)
- = tree_cons (get_identifier ("omp declare target"),
- NULL_TREE, DECL_ATTRIBUTES (fndecl));
+ /* Add an "omp declare target" attribute. */
+ DECL_ATTRIBUTES (fndecl)
+ = tree_cons (get_identifier ("omp declare target"),
+ parser->oacc_routine->clauses,
+ DECL_ATTRIBUTES (fndecl));
+ }
/* Don't unset parser->oacc_routine here: we may still need it to
diagnose wrong usage. But, remember that we've used this "#pragma acc
@@ -40507,11 +40808,15 @@ cp_parser_transaction (cp_parser *parser, cp_token *token)
else if (keyword == RID_ATOMIC_CANCEL)
{
/* cancel-and-throw is unimplemented. */
- sorry ("atomic_cancel");
+ sorry ("%<atomic_cancel%>");
noex = NULL_TREE;
}
else
- noex = cp_parser_noexcept_specification_opt (parser, true, NULL, true);
+ noex = cp_parser_noexcept_specification_opt (parser,
+ /*require_constexpr=*/true,
+ /*consumed_expr=*/NULL,
+ /*return_cond=*/true,
+ /*friend_p=*/false);
/* Keep track if we're in the lexical scope of an outer transaction. */
new_in = this_in | (old_in & TM_STMT_ATTR_OUTER);
@@ -40571,8 +40876,11 @@ cp_parser_transaction_expression (cp_parser *parser, enum rid keyword)
parser->in_transaction = this_in;
/* Parse a noexcept specification. */
- noex = cp_parser_noexcept_specification_opt (parser, false, &noex_expr,
- true);
+ noex = cp_parser_noexcept_specification_opt (parser,
+ /*require_constexpr=*/false,
+ &noex_expr,
+ /*return_cond=*/true,
+ /*friend_p=*/false);
if (!noex || !noex_expr
|| cp_lexer_peek_token (parser->lexer)->type == CPP_OPEN_PAREN)
@@ -41049,8 +41357,14 @@ cp_parser_pragma (cp_parser *parser, enum pragma_context context, bool *if_p)
cp_parser_omp_end_declare_target (parser, pragma_tok);
return false;
+ case PRAGMA_OMP_SCAN:
+ error_at (pragma_tok->location,
+ "%<#pragma omp scan%> may only be used in "
+ "a loop construct with %<inscan%> %<reduction%> clause");
+ break;
+
case PRAGMA_OMP_SECTION:
- error_at (pragma_tok->location,
+ error_at (pragma_tok->location,
"%<#pragma omp section%> may only be used in "
"%<#pragma omp sections%> construct");
break;
diff --git a/gcc/cp/parser.h b/gcc/cp/parser.h
index c03a9d8..2890788 100644
--- a/gcc/cp/parser.h
+++ b/gcc/cp/parser.h
@@ -166,6 +166,9 @@ struct GTY(()) cp_unparsed_functions_entry {
/* Nested classes go in this vector, so that we can do some final
processing after parsing any NSDMIs. */
vec<tree, va_gc> *classes;
+
+ /* Functions with noexcept-specifiers that require post-processing. */
+ vec<tree, va_gc> *noexcepts;
};
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index d6976e0..c5161a7 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -1058,10 +1058,11 @@ maybe_process_partial_specialization (tree type)
if (current_namespace
!= decl_namespace_context (tmpl))
{
- permerror (input_location,
- "specializing %q#T in different namespace", type);
- permerror (DECL_SOURCE_LOCATION (tmpl),
- " from definition of %q#D", tmpl);
+ if (permerror (input_location,
+ "specialization of %qD in different namespace",
+ type))
+ inform (DECL_SOURCE_LOCATION (tmpl),
+ "from definition of %q#D", tmpl);
}
/* Check for invalid specialization after instantiation:
@@ -2237,10 +2238,10 @@ determine_specialization (tree template_id,
/* Skip the "this" parameter and, for constructors of
classes with virtual bases, the VTT parameter. A
full specialization of a constructor will have a VTT
- parameter, but a template never will. */
- decl_arg_types
+ parameter, but a template never will. */
+ decl_arg_types
= skip_artificial_parms_for (decl, decl_arg_types);
- fn_arg_types
+ fn_arg_types
= skip_artificial_parms_for (fn, fn_arg_types);
/* Function templates cannot be specializations; there are
@@ -2906,14 +2907,13 @@ check_explicit_specialization (tree declarator,
if ((specialization || member_specialization)
/* This doesn't apply to variable templates. */
- && (TREE_CODE (TREE_TYPE (decl)) == FUNCTION_TYPE
- || TREE_CODE (TREE_TYPE (decl)) == METHOD_TYPE))
+ && FUNC_OR_METHOD_TYPE_P (TREE_TYPE (decl)))
{
tree t = TYPE_ARG_TYPES (TREE_TYPE (decl));
for (; t; t = TREE_CHAIN (t))
if (TREE_PURPOSE (t))
{
- permerror (input_location,
+ permerror (input_location,
"default argument specified in explicit specialization");
break;
}
@@ -3303,18 +3303,18 @@ comp_template_parms (const_tree parms1, const_tree parms2)
/* Determine whether PARM is a parameter pack. */
-bool
+bool
template_parameter_pack_p (const_tree parm)
{
/* Determine if we have a non-type template parameter pack. */
if (TREE_CODE (parm) == PARM_DECL)
- return (DECL_TEMPLATE_PARM_P (parm)
+ return (DECL_TEMPLATE_PARM_P (parm)
&& TEMPLATE_PARM_PARAMETER_PACK (DECL_INITIAL (parm)));
if (TREE_CODE (parm) == TEMPLATE_PARM_INDEX)
return TEMPLATE_PARM_PARAMETER_PACK (parm);
/* If this is a list of template parameters, we could get a
- TYPE_DECL or a TEMPLATE_DECL. */
+ TYPE_DECL or a TEMPLATE_DECL. */
if (TREE_CODE (parm) == TYPE_DECL || TREE_CODE (parm) == TEMPLATE_DECL)
parm = TREE_TYPE (parm);
@@ -3366,7 +3366,7 @@ function_parameter_expanded_from_pack_p (tree param_decl, tree pack)
/* Determine whether ARGS describes a variadic template args list,
i.e., one that is terminated by a template argument pack. */
-static bool
+static bool
template_args_variadic_p (tree args)
{
int nargs;
@@ -3607,7 +3607,8 @@ expand_integer_pack (tree call, tree args, tsubst_flags_t complain,
{
if ((complain & tf_error)
&& hi != error_mark_node)
- error ("argument to __integer_pack must be between 0 and %d", max);
+ error ("argument to %<__integer_pack%> must be between 0 and %d",
+ max);
return error_mark_node;
}
@@ -3639,7 +3640,7 @@ expand_builtin_pack_call (tree call, tree args, tsubst_flags_t complain,
}
/* Structure used to track the progress of find_parameter_packs_r. */
-struct find_parameter_pack_data
+struct find_parameter_pack_data
{
/* TREE_LIST that will contain all of the parameter packs found by
the traversal. */
@@ -3660,7 +3661,7 @@ static tree
find_parameter_packs_r (tree *tp, int *walk_subtrees, void* data)
{
tree t = *tp;
- struct find_parameter_pack_data* ppd =
+ struct find_parameter_pack_data* ppd =
(struct find_parameter_pack_data*)data;
bool parameter_pack_p = false;
@@ -3745,22 +3746,22 @@ find_parameter_packs_r (tree *tp, int *walk_subtrees, void* data)
}
if (TYPE_P (t))
- cp_walk_tree (&TYPE_CONTEXT (t),
+ cp_walk_tree (&TYPE_CONTEXT (t),
&find_parameter_packs_r, ppd, ppd->visited);
/* This switch statement will return immediately if we don't find a
parameter pack. */
- switch (TREE_CODE (t))
+ switch (TREE_CODE (t))
{
case TEMPLATE_PARM_INDEX:
return NULL_TREE;
case BOUND_TEMPLATE_TEMPLATE_PARM:
/* Check the template itself. */
- cp_walk_tree (&TREE_TYPE (TYPE_TI_TEMPLATE (t)),
+ cp_walk_tree (&TREE_TYPE (TYPE_TI_TEMPLATE (t)),
&find_parameter_packs_r, ppd, ppd->visited);
/* Check the template arguments. */
- cp_walk_tree (&TYPE_TI_ARGS (t), &find_parameter_packs_r, ppd,
+ cp_walk_tree (&TYPE_TI_ARGS (t), &find_parameter_packs_r, ppd,
ppd->visited);
*walk_subtrees = 0;
return NULL_TREE;
@@ -3801,26 +3802,26 @@ find_parameter_packs_r (tree *tp, int *walk_subtrees, void* data)
cp_walk_tree (&TREE_TYPE (t),
&find_parameter_packs_r, ppd, ppd->visited);
return NULL_TREE;
-
+
case TYPENAME_TYPE:
cp_walk_tree (&TYPENAME_TYPE_FULLNAME (t), &find_parameter_packs_r,
ppd, ppd->visited);
*walk_subtrees = 0;
return NULL_TREE;
-
+
case TYPE_PACK_EXPANSION:
case EXPR_PACK_EXPANSION:
*walk_subtrees = 0;
return NULL_TREE;
case INTEGER_TYPE:
- cp_walk_tree (&TYPE_MAX_VALUE (t), &find_parameter_packs_r,
+ cp_walk_tree (&TYPE_MAX_VALUE (t), &find_parameter_packs_r,
ppd, ppd->visited);
*walk_subtrees = 0;
return NULL_TREE;
case IDENTIFIER_NODE:
- cp_walk_tree (&TREE_TYPE (t), &find_parameter_packs_r, ppd,
+ cp_walk_tree (&TREE_TYPE (t), &find_parameter_packs_r, ppd,
ppd->visited);
*walk_subtrees = 0;
return NULL_TREE;
@@ -3893,7 +3894,7 @@ uses_parameter_packs (tree t)
expansion. If all goes well, the resulting node will be an
EXPR_PACK_EXPANSION, TYPE_PACK_EXPANSION, or TREE_LIST,
respectively. */
-tree
+tree
make_pack_expansion (tree arg, tsubst_flags_t complain)
{
tree result;
@@ -3935,7 +3936,7 @@ make_pack_expansion (tree arg, tsubst_flags_t complain)
ppd.parameter_packs = &parameter_packs;
ppd.type_pack_expansion_p = false;
gcc_assert (TYPE_P (TREE_PURPOSE (arg)));
- cp_walk_tree (&TREE_PURPOSE (arg), &find_parameter_packs_r,
+ cp_walk_tree (&TREE_PURPOSE (arg), &find_parameter_packs_r,
&ppd, ppd.visited);
if (parameter_packs == NULL_TREE)
@@ -4032,11 +4033,11 @@ make_pack_expansion (tree arg, tsubst_flags_t complain)
where "args" is a parameter pack. check_for_bare_parameter_packs
should not be called for the subexpressions args, h(args),
g(h(args)), or f(g(h(args))), because we would produce erroneous
- error messages.
+ error messages.
Returns TRUE and emits an error if there were bare parameter packs,
returns FALSE otherwise. */
-bool
+bool
check_for_bare_parameter_packs (tree t, location_t loc /* = UNKNOWN_LOCATION */)
{
tree parameter_packs = NULL_TREE;
@@ -4059,7 +4060,7 @@ check_for_bare_parameter_packs (tree t, location_t loc /* = UNKNOWN_LOCATION */)
cp_walk_tree (&t, &find_parameter_packs_r, &ppd, ppd.visited);
delete ppd.visited;
- if (parameter_packs)
+ if (parameter_packs)
{
if (loc == UNKNOWN_LOCATION)
loc = cp_expr_loc_or_loc (t, input_location);
@@ -4082,7 +4083,7 @@ check_for_bare_parameter_packs (tree t, location_t loc /* = UNKNOWN_LOCATION */)
if (name)
inform (loc, " %qD", name);
else
- inform (loc, " <anonymous>");
+ inform (loc, " %s", "<anonymous>");
parameter_packs = TREE_CHAIN (parameter_packs);
}
@@ -4297,7 +4298,7 @@ reduce_template_parm_level (tree index, tree type, int levels, tree args,
TEMPLATE_PARM_ORIG_LEVEL (index),
decl, type);
TEMPLATE_PARM_DESCENDANTS (index) = t;
- TEMPLATE_PARM_PARAMETER_PACK (t)
+ TEMPLATE_PARM_PARAMETER_PACK (t)
= TEMPLATE_PARM_PARAMETER_PACK (index);
/* Template template parameters need this. */
@@ -4390,7 +4391,7 @@ process_template_parm (tree list, location_t parm_loc, tree parm,
processing_template_decl,
decl, TREE_TYPE (parm));
- TEMPLATE_PARM_PARAMETER_PACK (DECL_INITIAL (parm))
+ TEMPLATE_PARM_PARAMETER_PACK (DECL_INITIAL (parm))
= is_parameter_pack;
}
else
@@ -4899,7 +4900,7 @@ process_partial_specialization (tree decl)
The type of a template parameter corresponding to a specialized
non-type argument shall not be dependent on a parameter of the
- specialization.
+ specialization.
Also, we verify that pack expansions only occur at the
end of the argument list. */
@@ -5278,7 +5279,7 @@ check_default_tmpl_args (tree decl, tree parms, bool is_primary,
error ("parameter pack %q+D must be at the end of the"
" template parameter list", TREE_VALUE (parm));
- TREE_VALUE (TREE_VEC_ELT (inner_parms, i))
+ TREE_VALUE (TREE_VEC_ELT (inner_parms, i))
= error_mark_node;
no_errors = false;
}
@@ -5287,7 +5288,7 @@ check_default_tmpl_args (tree decl, tree parms, bool is_primary,
}
if (((cxx_dialect == cxx98) && TREE_CODE (decl) != TYPE_DECL)
- || is_partial
+ || is_partial
|| !is_primary
|| is_friend_decl)
/* For an ordinary class template, default template arguments are
@@ -5496,11 +5497,11 @@ push_template_decl_real (tree decl, bool is_friend)
if (is_primary)
{
warning (OPT_Wtemplates, "template %qD declared", decl);
-
+
if (DECL_CLASS_SCOPE_P (decl))
member_template_p = true;
if (TREE_CODE (decl) == TYPE_DECL
- && anon_aggrname_p (DECL_NAME (decl)))
+ && IDENTIFIER_ANON_P (DECL_NAME (decl)))
{
error ("template class without a name");
return error_mark_node;
@@ -6243,7 +6244,7 @@ convert_nontype_argument_function (tree type, tree expr,
fn_no_ptr = TREE_OPERAND (fn_no_ptr, 0);
if (BASELINK_P (fn_no_ptr))
fn_no_ptr = BASELINK_FUNCTIONS (fn_no_ptr);
-
+
/* [temp.arg.nontype]/1
A template-argument for a non-type, non-template template-parameter
@@ -6566,7 +6567,7 @@ unify_template_deduction_failure (bool explain_p, tree parm, tree arg)
{
if (explain_p)
inform (input_location,
- " can%'t deduce a template for %qT from non-template type %qT",
+ " cannot deduce a template for %qT from non-template type %qT",
parm, arg);
return unify_invalid (explain_p);
}
@@ -7227,10 +7228,10 @@ coerce_template_template_parm (tree parm,
if (arg == NULL_TREE || error_operand_p (arg)
|| parm == NULL_TREE || error_operand_p (parm))
return 0;
-
+
if (TREE_CODE (arg) != TREE_CODE (parm))
return 0;
-
+
switch (TREE_CODE (parm))
{
case TEMPLATE_DECL:
@@ -7240,23 +7241,23 @@ coerce_template_template_parm (tree parm,
{
tree parmparm = DECL_INNERMOST_TEMPLATE_PARMS (parm);
tree argparm = DECL_INNERMOST_TEMPLATE_PARMS (arg);
-
+
if (!coerce_template_template_parms
(parmparm, argparm, complain, in_decl, outer_args))
return 0;
}
/* Fall through. */
-
+
case TYPE_DECL:
if (TEMPLATE_TYPE_PARAMETER_PACK (TREE_TYPE (arg))
&& !TEMPLATE_TYPE_PARAMETER_PACK (TREE_TYPE (parm)))
/* Argument is a parameter pack but parameter is not. */
return 0;
break;
-
+
case PARM_DECL:
/* The tsubst call is used to handle cases such as
-
+
template <int> class C {};
template <class T, template <T> class TT> class D {};
D<int, C> d;
@@ -7269,12 +7270,12 @@ coerce_template_template_parm (tree parm,
&& !same_type_p (t, TREE_TYPE (arg)))
return 0;
}
-
+
if (TEMPLATE_PARM_PARAMETER_PACK (DECL_INITIAL (arg))
&& !TEMPLATE_PARM_PARAMETER_PACK (DECL_INITIAL (parm)))
/* Argument is a parameter pack but parameter is not. */
return 0;
-
+
break;
default:
@@ -7456,8 +7457,7 @@ unify_bound_ttp_args (tree tparms, tree targs, tree parm, tree& arg,
{
/* In keeping with P0522R0, adjust P's template arguments
to apply to A's template; then flatten it again. */
- tree nparmvec = parmvec;
- nparmvec = coerce_ttp_args_for_tta (arg, parmvec, tf_none);
+ tree nparmvec = coerce_ttp_args_for_tta (arg, parmvec, tf_none);
nparmvec = expand_template_argument_pack (nparmvec);
if (unify (tparms, targs, nparmvec, argvec,
@@ -7595,7 +7595,7 @@ coerce_template_template_parms (tree parm_parms,
if (TREE_VEC_ELT (parm_parms, nparms - 1) != error_mark_node)
{
parm = TREE_VALUE (TREE_VEC_ELT (parm_parms, nparms - 1));
-
+
if (error_operand_p (parm))
return 0;
@@ -7606,17 +7606,17 @@ coerce_template_template_parms (tree parm_parms,
if (TEMPLATE_TYPE_PARAMETER_PACK (TREE_TYPE (parm)))
variadic_p = 1;
break;
-
+
case PARM_DECL:
if (TEMPLATE_PARM_PARAMETER_PACK (DECL_INITIAL (parm)))
variadic_p = 1;
break;
-
+
default:
gcc_unreachable ();
}
}
-
+
if (nargs != nparms
&& !(variadic_p && nargs >= nparms - 1))
return 0;
@@ -7652,9 +7652,9 @@ coerce_template_template_parms (tree parm_parms,
{
if (TREE_VEC_ELT (arg_parms, i) == error_mark_node)
continue;
-
+
arg = TREE_VALUE (TREE_VEC_ELT (arg_parms, i));
-
+
if (!coerce_template_template_parm (parm, arg, complain, in_decl,
outer_args))
return 0;
@@ -7672,7 +7672,7 @@ coerce_template_template_parms (tree parm_parms,
routine can only be called after all template arguments have been
deduced. It will return TRUE if all of the template template
parameter bindings are okay, FALSE otherwise. */
-bool
+bool
template_template_parm_bindings_ok_p (tree tparms, tree targs)
{
int i, ntparms = TREE_VEC_LENGTH (tparms);
@@ -7884,7 +7884,6 @@ convert_template_argument (tree parm,
invalid, but static members are OK. In any
case, grab the underlying fields/functions
and issue an error later if required. */
- orig_arg = TREE_VALUE (arg);
TREE_TYPE (arg) = unknown_type_node;
}
@@ -7917,7 +7916,7 @@ convert_template_argument (tree parm,
}
}
- is_tmpl_type =
+ is_tmpl_type =
((TREE_CODE (arg) == TEMPLATE_DECL
&& TREE_CODE (DECL_TEMPLATE_RESULT (arg)) == TYPE_DECL)
|| (requires_tmpl_type && TREE_CODE (arg) == TYPE_ARGUMENT_PACK)
@@ -7962,10 +7961,22 @@ convert_template_argument (tree parm,
"parameter list for %qD",
i + 1, in_decl);
if (is_type)
- inform (input_location,
- " expected a constant of type %qT, got %qT",
- TREE_TYPE (parm),
- (DECL_P (arg) ? DECL_NAME (arg) : orig_arg));
+ {
+ /* The template argument is a type, but we're expecting
+ an expression. */
+ inform (input_location,
+ " expected a constant of type %qT, got %qT",
+ TREE_TYPE (parm),
+ (DECL_P (arg) ? DECL_NAME (arg) : orig_arg));
+ /* [temp.arg]/2: "In a template-argument, an ambiguity
+ between a type-id and an expression is resolved to a
+ type-id, regardless of the form of the corresponding
+ template-parameter." So give the user a clue. */
+ if (TREE_CODE (arg) == FUNCTION_TYPE)
+ inform (input_location, " ambiguous template argument "
+ "for non-type template parameter is treated as "
+ "function type");
+ }
else if (requires_tmpl_type)
inform (input_location,
" expected a class template, got %qE", orig_arg);
@@ -8259,7 +8270,7 @@ coerce_template_parameter_pack (tree parms,
error ("template argument %d is invalid", arg_idx + 1);
}
else
- arg = convert_template_argument (actual_parm,
+ arg = convert_template_argument (actual_parm,
arg, new_args, complain, parm_idx,
in_decl);
if (arg == error_mark_node)
@@ -8463,7 +8474,7 @@ coerce_template_parms (tree parms,
/* Get the Ith template parameter. */
parm = TREE_VEC_ELT (parms, parm_idx);
-
+
if (parm == error_mark_node)
{
TREE_VEC_ELT (new_inner_args, arg_idx) = error_mark_node;
@@ -8482,7 +8493,7 @@ coerce_template_parms (tree parms,
{
/* Some arguments will be placed in the
template parameter pack PARM. */
- arg = coerce_template_parameter_pack (parms, parm_idx, args,
+ arg = coerce_template_parameter_pack (parms, parm_idx, args,
inner_args, arg_idx,
new_args, &lost,
in_decl, complain);
@@ -8516,7 +8527,7 @@ coerce_template_parms (tree parms,
fixed_pack_adjust += pack_adjust;
}
}
-
+
continue;
}
else if (arg)
@@ -8586,7 +8597,7 @@ coerce_template_parms (tree parms,
}
else
arg = convert_template_argument (TREE_VALUE (parm),
- arg, new_args, complain,
+ arg, new_args, complain,
parm_idx, in_decl);
if (arg == error_mark_node)
@@ -9952,7 +9963,7 @@ for_each_template_parm_r (tree *tp, int *walk_subtrees, void *d)
case UNDERLYING_TYPE:
if (pfd->include_nondeduced_p
&& for_each_template_parm (TYPE_VALUES_RAW (t), fn, data,
- pfd->visited,
+ pfd->visited,
pfd->include_nondeduced_p,
pfd->any_fn))
return error_mark_node;
@@ -11235,10 +11246,10 @@ instantiate_class_template_1 (tree type)
if (TREE_CODE (t) == STATIC_ASSERT)
{
tree condition;
-
+
++c_inhibit_evaluation_warnings;
condition =
- tsubst_expr (STATIC_ASSERT_CONDITION (t), args,
+ tsubst_expr (STATIC_ASSERT_CONDITION (t), args,
tf_warning_or_error, NULL_TREE,
/*integral_constant_expression_p=*/true);
--c_inhibit_evaluation_warnings;
@@ -12174,7 +12185,7 @@ tsubst_pack_expansion (tree t, tree args, tsubst_flags_t complain,
packs used in the expansion expression. While we're at it,
compute the number of arguments to be expanded and make sure it
is consistent. */
- for (pack = PACK_EXPANSION_PARAMETER_PACKS (t); pack;
+ for (pack = PACK_EXPANSION_PARAMETER_PACKS (t); pack;
pack = TREE_CHAIN (pack))
{
tree parm_pack = TREE_VALUE (pack);
@@ -12262,7 +12273,7 @@ tsubst_pack_expansion (tree t, tree args, tsubst_flags_t complain,
orig_arg = arg_pack;
if (arg_pack && TREE_CODE (arg_pack) == ARGUMENT_PACK_SELECT)
arg_pack = ARGUMENT_PACK_SELECT_FROM_PACK (arg_pack);
-
+
if (arg_pack && !ARGUMENT_PACK_P (arg_pack))
/* This can only happen if we forget to expand an argument
pack somewhere else. Just return an error, silently. */
@@ -12417,7 +12428,7 @@ tsubst_pack_expansion (tree t, tree args, tsubst_flags_t complain,
continue;
template_parm_level_and_index (parm, &level, &idx);
-
+
/* Update the corresponding argument. */
if (TMPL_ARGS_HAVE_MULTIPLE_LEVELS (args))
TREE_VEC_ELT (TREE_VEC_ELT (args, level -1 ), idx) =
@@ -12432,7 +12443,7 @@ tsubst_pack_expansion (tree t, tree args, tsubst_flags_t complain,
delete local_specializations;
local_specializations = saved_local_specializations;
}
-
+
/* If the dependent pack arguments were such that we end up with only a
single pack expansion again, there's no need to keep it in a TREE_VEC. */
if (len == 1 && TREE_CODE (result) == TREE_VEC
@@ -12801,7 +12812,7 @@ tsubst_default_argument (tree fn, int parmnum, tree type, tree arg,
int errs = errorcount + sorrycount;
/* This can happen in invalid code. */
- if (TREE_CODE (arg) == DEFAULT_ARG)
+ if (TREE_CODE (arg) == DEFERRED_PARSE)
return arg;
tree parm = FUNCTION_FIRST_USER_PARM (fn);
@@ -13755,7 +13766,7 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
/* T is a static data member or namespace-scope entity.
We have to substitute into namespace-scope variables
(not just variable templates) because of cases like:
-
+
template <class T> void f() { extern T t; }
where the entity referenced is not known until
@@ -13816,7 +13827,7 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
spec = retrieve_local_specialization (t);
}
/* If we already have the specialization we need, there is
- nothing more to do. */
+ nothing more to do. */
if (spec)
{
r = spec;
@@ -13872,7 +13883,7 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
void g() { f x; }
declares a function, not a variable. However:
-
+
typedef void f();
template <typename T> void g() { T t; }
template void g<f>();
@@ -14041,7 +14052,7 @@ tsubst_arg_types (tree arg_types,
while (i > 0) {
--i;
-
+
if (expanded_args)
type = TREE_VEC_ELT (expanded_args, i);
else if (!type)
@@ -14062,7 +14073,7 @@ tsubst_arg_types (tree arg_types,
/* DR 657. */
if (abstract_virtuals_error_sfinae (ACU_PARM, type, complain))
return error_mark_node;
-
+
/* Do array-to-pointer, function-to-pointer conversion, and ignore
top-level qualifiers as required. */
type = cv_unqualified (type_decays_to (type));
@@ -14079,7 +14090,7 @@ tsubst_arg_types (tree arg_types,
default_arg = tsubst_copy_and_build (default_arg, args, complain, in_decl,
false/*fn*/, false/*constexpr*/);
- if (default_arg && TREE_CODE (default_arg) == DEFAULT_ARG)
+ if (default_arg && TREE_CODE (default_arg) == DEFERRED_PARSE)
{
/* We've instantiated a template before its default arguments
have been parsed. This can happen for a nested template
@@ -14087,13 +14098,14 @@ tsubst_arg_types (tree arg_types,
argument in a call of this function. */
remaining_arg_types =
tree_cons (default_arg, type, remaining_arg_types);
- vec_safe_push (DEFARG_INSTANTIATIONS(default_arg), remaining_arg_types);
+ vec_safe_push (DEFPARSE_INSTANTIATIONS (default_arg),
+ remaining_arg_types);
}
else
- remaining_arg_types =
+ remaining_arg_types =
hash_tree_cons (default_arg, type, remaining_arg_types);
}
-
+
return remaining_arg_types;
}
@@ -14314,7 +14326,7 @@ tsubst_exception_specification (tree fntype,
/* We're substituting into a member template, so
we got a TYPE_PACK_EXPANSION back. Add that
expansion and move on. */
- gcc_assert (TREE_CODE (expanded_specs)
+ gcc_assert (TREE_CODE (expanded_specs)
== TYPE_PACK_EXPANSION);
new_specs = add_exception_specifier (new_specs,
expanded_specs,
@@ -14523,7 +14535,7 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
r = NULL_TREE;
gcc_assert (TREE_VEC_LENGTH (args) > 0);
- template_parm_level_and_index (t, &level, &idx);
+ template_parm_level_and_index (t, &level, &idx);
levels = TMPL_ARGS_DEPTH (args);
if (level <= levels
@@ -14560,7 +14572,7 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
gcc_assert (TYPE_P (arg));
quals = cp_type_quals (arg) | cp_type_quals (t);
-
+
return cp_build_qualified_type_real
(arg, quals, complain | tf_ignore_bad_quals);
}
@@ -15555,7 +15567,7 @@ tsubst_copy (tree t, tree args, tsubst_flags_t complain, tree in_decl)
mangling. */
DECL_CONTEXT (r) = DECL_CONTEXT (t);
}
-
+
if (TREE_CODE (r) == ARGUMENT_PACK_SELECT)
r = argument_pack_select_arg (r);
if (!mark_used (r, complain) && !(complain & tf_error))
@@ -16310,6 +16322,8 @@ tsubst_omp_clauses (tree clauses, enum c_omp_region_type ort,
case OMP_CLAUSE_NONTEMPORAL:
case OMP_CLAUSE_USE_DEVICE_PTR:
case OMP_CLAUSE_IS_DEVICE_PTR:
+ case OMP_CLAUSE_INCLUSIVE:
+ case OMP_CLAUSE_EXCLUSIVE:
OMP_CLAUSE_DECL (nc)
= tsubst_omp_clause_decl (OMP_CLAUSE_DECL (oc), args, complain,
in_decl, iterator_cache);
@@ -16339,7 +16353,7 @@ tsubst_omp_clauses (tree clauses, enum c_omp_region_type ort,
case OMP_CLAUSE_ASYNC:
case OMP_CLAUSE_WAIT:
OMP_CLAUSE_OPERAND (nc, 0)
- = tsubst_expr (OMP_CLAUSE_OPERAND (oc, 0), args, complain,
+ = tsubst_expr (OMP_CLAUSE_OPERAND (oc, 0), args, complain,
in_decl, /*integral_constant_expression_p=*/false);
break;
case OMP_CLAUSE_REDUCTION:
@@ -16430,6 +16444,8 @@ tsubst_omp_clauses (tree clauses, enum c_omp_region_type ort,
case OMP_CLAUSE_TASK_REDUCTION:
case OMP_CLAUSE_USE_DEVICE_PTR:
case OMP_CLAUSE_IS_DEVICE_PTR:
+ case OMP_CLAUSE_INCLUSIVE:
+ case OMP_CLAUSE_EXCLUSIVE:
/* tsubst_expr on SCOPE_REF results in returning
finish_non_static_data_member result. Undo that here. */
if (TREE_CODE (OMP_CLAUSE_DECL (oc)) == SCOPE_REF
@@ -17042,8 +17058,7 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl,
break;
case USING_STMT:
- finish_local_using_directive (USING_STMT_NAMESPACE (t),
- /*attribs=*/NULL_TREE);
+ finish_using_directive (USING_STMT_NAMESPACE (t), /*attribs=*/NULL_TREE);
break;
case DECL_EXPR:
@@ -17060,13 +17075,7 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl,
tree name = DECL_NAME (decl);
scope = tsubst (scope, args, complain, in_decl);
- decl = lookup_qualified_name (scope, name,
- /*is_type_p=*/false,
- /*complain=*/false);
- if (decl == error_mark_node || TREE_CODE (decl) == TREE_LIST)
- qualified_name_lookup_error (scope, name, decl, input_location);
- else
- finish_local_using_decl (decl, scope, name);
+ finish_nonmember_using_decl (scope, name);
}
else if (is_capture_proxy (decl)
&& !DECL_TEMPLATE_INSTANTIATION (current_function_decl))
@@ -17633,6 +17642,7 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl,
case OMP_TEAMS:
case OMP_CRITICAL:
case OMP_TASKGROUP:
+ case OMP_SCAN:
r = push_omp_privatization_clauses (TREE_CODE (t) == OMP_TEAMS
&& OMP_TEAMS_COMBINED (t));
tmp = tsubst_omp_clauses (OMP_CLAUSES (t), C_ORT_OMP, args, complain,
@@ -18465,7 +18475,7 @@ tsubst_copy_and_build (tree t,
complain|decltype_flag));
case FIX_TRUNC_EXPR:
- gcc_unreachable ();
+ gcc_unreachable ();
case ADDR_EXPR:
op1 = TREE_OPERAND (t, 0);
@@ -18559,7 +18569,7 @@ tsubst_copy_and_build (tree t,
|| ARGUMENT_PACK_P (TREE_OPERAND (t, 0)))
RETURN (tsubst_copy (t, args, complain, in_decl));
/* Fall through */
-
+
case ALIGNOF_EXPR:
{
tree r;
@@ -18751,7 +18761,6 @@ tsubst_copy_and_build (tree t,
case CALL_EXPR:
{
tree function;
- vec<tree, va_gc> *call_args;
unsigned int nargs, i;
bool qualified_p;
bool koenig_p;
@@ -18819,7 +18828,7 @@ tsubst_copy_and_build (tree t,
}
nargs = call_expr_nargs (t);
- call_args = make_tree_vector ();
+ releasing_vec call_args;
for (i = 0; i < nargs; ++i)
{
tree arg = CALL_EXPR_ARG (t, i);
@@ -18856,6 +18865,9 @@ tsubst_copy_and_build (tree t,
the thunk template for a generic lambda. */
if (CALL_FROM_THUNK_P (t))
{
+ /* Now that we've expanded any packs, the number of call args
+ might be different. */
+ unsigned int cargs = call_args->length ();
tree thisarg = NULL_TREE;
if (TREE_CODE (function) == COMPONENT_REF)
{
@@ -18869,7 +18881,7 @@ tsubst_copy_and_build (tree t,
/* We aren't going to do normal overload resolution, so force the
template-id to resolve. */
function = resolve_nondeduced_context (function, complain);
- for (unsigned i = 0; i < nargs; ++i)
+ for (unsigned i = 0; i < cargs; ++i)
{
/* In a thunk, pass through args directly, without any
conversions. */
@@ -18880,12 +18892,18 @@ tsubst_copy_and_build (tree t,
}
if (thisarg)
{
- /* Shift the other args over to make room. */
- tree last = (*call_args)[nargs - 1];
- vec_safe_push (call_args, last);
- for (int i = nargs-1; i > 0; --i)
- (*call_args)[i] = (*call_args)[i-1];
- (*call_args)[0] = thisarg;
+ /* If there are no other args, just push 'this'. */
+ if (cargs == 0)
+ vec_safe_push (call_args, thisarg);
+ else
+ {
+ /* Otherwise, shift the other args over to make room. */
+ tree last = (*call_args)[cargs - 1];
+ vec_safe_push (call_args, last);
+ for (int i = cargs - 1; i > 0; --i)
+ (*call_args)[i] = (*call_args)[i - 1];
+ (*call_args)[0] = thisarg;
+ }
}
ret = build_call_a (function, call_args->length (),
call_args->address ());
@@ -18895,7 +18913,6 @@ tsubst_copy_and_build (tree t,
if (CLASS_TYPE_P (TREE_TYPE (ret)))
CALL_EXPR_RETURN_SLOT_OPT (ret) = true;
- release_tree_vector (call_args);
RETURN (ret);
}
@@ -18928,10 +18945,7 @@ tsubst_copy_and_build (tree t,
(function, args, complain, in_decl, true,
integral_constant_expression_p));
if (unq == error_mark_node)
- {
- release_tree_vector (call_args);
- RETURN (error_mark_node);
- }
+ RETURN (error_mark_node);
if (unq != function)
{
@@ -18986,10 +19000,7 @@ tsubst_copy_and_build (tree t,
"%qD declared here, later in the "
"translation unit", fn);
if (in_lambda)
- {
- release_tree_vector (call_args);
- RETURN (error_mark_node);
- }
+ RETURN (error_mark_node);
}
function = unq;
@@ -18999,7 +19010,6 @@ tsubst_copy_and_build (tree t,
{
if (complain & tf_error)
unqualified_name_lookup_error (function);
- release_tree_vector (call_args);
RETURN (error_mark_node);
}
}
@@ -19008,10 +19018,7 @@ tsubst_copy_and_build (tree t,
if (function != NULL_TREE
&& DECL_P (function)
&& !mark_used (function, complain) && !(complain & tf_error))
- {
- release_tree_vector (call_args);
- RETURN (error_mark_node);
- }
+ RETURN (error_mark_node);
/* Put back tf_decltype for the actual call. */
complain |= decltype_flag;
@@ -19049,10 +19056,7 @@ tsubst_copy_and_build (tree t,
complain, in_decl),
complain);
if (TREE_CODE (ret) == VIEW_CONVERT_EXPR)
- {
- release_tree_vector (call_args);
- RETURN (ret);
- }
+ RETURN (ret);
break;
default:
@@ -19095,8 +19099,6 @@ tsubst_copy_and_build (tree t,
koenig_p,
complain);
- release_tree_vector (call_args);
-
if (ret != error_mark_node)
{
bool op = CALL_EXPR_OPERATOR_SYNTAX (t);
@@ -19209,7 +19211,7 @@ tsubst_copy_and_build (tree t,
RETURN (tree_cons (purposevec, valuevec, chain));
}
-
+
/* Convert the argument vectors into a TREE_LIST */
i = len;
while (i > 0)
@@ -19219,7 +19221,7 @@ tsubst_copy_and_build (tree t,
purpose = purposevec ? TREE_VEC_ELT (purposevec, i)
: NULL_TREE;
value
- = valuevec ? convert_from_reference (TREE_VEC_ELT (valuevec, i))
+ = valuevec ? convert_from_reference (TREE_VEC_ELT (valuevec, i))
: NULL_TREE;
/* Build the list (backwards). */
@@ -19521,7 +19523,7 @@ tsubst_copy_and_build (tree t,
type2 = RECUR (type2);
else if (type2)
type2 = tsubst (type2, args, complain, in_decl);
-
+
RETURN (finish_trait_expr (TRAIT_EXPR_KIND (t), type1, type2));
}
@@ -20667,8 +20669,7 @@ uses_deducible_template_parms (tree type)
/* type (T)
T()
T(T) */
- if (TREE_CODE (type) == FUNCTION_TYPE
- || TREE_CODE (type) == METHOD_TYPE)
+ if (FUNC_OR_METHOD_TYPE_P (type))
{
if (uses_deducible_template_parms (TREE_TYPE (type)))
return true;
@@ -20900,7 +20901,7 @@ type_unification_real (tree tparms,
return 1;
}
- if (parms
+ if (parms
&& parms != void_list_node
&& TREE_CODE (TREE_VALUE (parms)) == TYPE_PACK_EXPANSION)
{
@@ -20908,7 +20909,7 @@ type_unification_real (tree tparms,
tree argvec;
tree parmvec = make_tree_vec (1);
- /* Allocate a TREE_VEC and copy in all of the arguments */
+ /* Allocate a TREE_VEC and copy in all of the arguments */
argvec = make_tree_vec (nargs - ia);
for (i = 0; ia < nargs; ++ia, ++i)
TREE_VEC_ELT (argvec, i) = args[ia];
@@ -20997,7 +20998,7 @@ type_unification_real (tree tparms,
/* Core issue #226 (C++0x) [temp.deduct]:
If a template argument has not been deduced, its
- default template argument, if any, is used.
+ default template argument, if any, is used.
When we are in C++98 mode, TREE_PURPOSE will either
be NULL_TREE or ERROR_MARK_NODE, so we do not need
@@ -21212,8 +21213,7 @@ resolve_overloaded_unification (tree tparms,
if (good != 1)
good = ok;
}
- else if (TREE_CODE (arg) != OVERLOAD
- && TREE_CODE (arg) != FUNCTION_DECL)
+ else if (!OVL_P (arg))
/* If ARG is, for example, "(0, &f)" then its type will be unknown
-- but the deduction does not succeed because the expression is
not just the function on its own. */
@@ -21646,8 +21646,7 @@ check_cv_quals_for_unify (int strict, tree arg, tree parm)
It is ok when we're allowing additional CV qualifiers
at the outer level [14.8.2.1]/3,1st bullet. */
if ((TYPE_REF_P (arg)
- || TREE_CODE (arg) == FUNCTION_TYPE
- || TREE_CODE (arg) == METHOD_TYPE)
+ || FUNC_OR_METHOD_TYPE_P (arg))
&& (parm_quals & (TYPE_QUAL_CONST | TYPE_QUAL_VOLATILE)))
return 0;
@@ -21668,7 +21667,7 @@ check_cv_quals_for_unify (int strict, tree arg, tree parm)
}
/* Determines the LEVEL and INDEX for the template parameter PARM. */
-void
+void
template_parm_level_and_index (tree parm, int* level, int* index)
{
if (TREE_CODE (parm) == TEMPLATE_TYPE_PARM
@@ -21701,11 +21700,11 @@ template_parm_level_and_index (tree parm, int* level, int* index)
lists. */
static int
-unify_pack_expansion (tree tparms, tree targs, tree packed_parms,
+unify_pack_expansion (tree tparms, tree targs, tree packed_parms,
tree packed_args, unification_kind_t strict,
bool subr, bool explain_p)
{
- tree parm
+ tree parm
= TREE_VEC_ELT (packed_parms, TREE_VEC_LENGTH (packed_parms) - 1);
tree pattern = PACK_EXPANSION_PATTERN (parm);
tree pack, packs = NULL_TREE;
@@ -21721,7 +21720,7 @@ unify_pack_expansion (tree tparms, tree targs, tree packed_parms,
/* Determine the parameter packs we will be deducing from the
pattern, and record their current deductions. */
- for (pack = PACK_EXPANSION_PARAMETER_PACKS (parm);
+ for (pack = PACK_EXPANSION_PARAMETER_PACKS (parm);
pack; pack = TREE_CHAIN (pack))
{
tree parm_pack = TREE_VALUE (pack);
@@ -21742,7 +21741,7 @@ unify_pack_expansion (tree tparms, tree targs, tree packed_parms,
packs = tree_cons (parm_pack, TMPL_ARG (targs, level, idx), packs);
TREE_TYPE (packs) = make_tree_vec (len - start);
}
-
+
/* Loop through all of the arguments that have not yet been
unified and unify each with the pattern. */
for (i = start; i < len; i++)
@@ -22786,7 +22785,9 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict,
/* An unresolved overload is a nondeduced context. */
if (is_overloaded_fn (parm) || type_unknown_p (parm))
return unify_success (explain_p);
- gcc_assert (EXPR_P (parm) || TREE_CODE (parm) == TRAIT_EXPR);
+ gcc_assert (EXPR_P (parm)
+ || COMPOUND_LITERAL_P (parm)
+ || TREE_CODE (parm) == TRAIT_EXPR);
expr:
/* We must be looking at an expression. This can happen with
something like:
@@ -22794,15 +22795,19 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict,
template <int I>
void foo(S<I>, S<I + 2>);
- This is a "nondeduced context":
+ or
+
+ template<typename T>
+ void foo(A<T, T{}>);
+
+ This is a "non-deduced context":
[deduct.type]
- The nondeduced contexts are:
+ The non-deduced contexts are:
- --A type that is a template-id in which one or more of
- the template-arguments is an expression that references
- a template-parameter.
+ --A non-type template argument or an array bound in which
+ a subexpression references a template parameter.
In these cases, we assume deduction succeeded, but don't
actually infer any unifications. */
@@ -23305,7 +23310,7 @@ get_bindings (tree fn, tree decl, tree explicit_args, bool check_rettype)
gcc_assert (decl != DECL_TEMPLATE_RESULT (fn));
/* Never do unification on the 'this' parameter. */
- decl_arg_types = skip_artificial_parms_for (decl,
+ decl_arg_types = skip_artificial_parms_for (decl,
TYPE_ARG_TYPES (decl_type));
nargs = list_length (decl_arg_types);
@@ -23837,7 +23842,7 @@ do_decl_instantiation (tree decl, tree storage)
else if (storage == ridpointers[(int) RID_EXTERN])
{
if (!in_system_header_at (input_location) && (cxx_dialect == cxx98))
- pedwarn (input_location, OPT_Wpedantic,
+ pedwarn (input_location, OPT_Wpedantic,
"ISO C++ 1998 forbids the use of %<extern%> on explicit "
"instantiations");
extern_p = 1;
@@ -23923,12 +23928,12 @@ do_type_instantiation (tree t, tree storage, tsubst_flags_t complain)
if (storage == ridpointers[(int) RID_EXTERN])
{
if (cxx_dialect == cxx98)
- pedwarn (input_location, OPT_Wpedantic,
+ pedwarn (input_location, OPT_Wpedantic,
"ISO C++ 1998 forbids the use of %<extern%> on "
"explicit instantiations");
}
else
- pedwarn (input_location, OPT_Wpedantic,
+ pedwarn (input_location, OPT_Wpedantic,
"ISO C++ forbids the use of %qE"
" on explicit instantiations", storage);
}
@@ -24092,7 +24097,7 @@ regenerate_decl_from_template (tree decl, tree tmpl, tree args)
{
tree parm_type;
tree attributes;
-
+
if (DECL_NAME (decl_parm) != DECL_NAME (pattern_parm))
DECL_NAME (decl_parm) = DECL_NAME (pattern_parm);
parm_type = tsubst (TREE_TYPE (pattern_parm), args, tf_error,
@@ -24124,7 +24129,7 @@ regenerate_decl_from_template (tree decl, tree tmpl, tree args)
{
tree parm_type;
tree attributes;
-
+
if (DECL_NAME (decl_parm) != DECL_NAME (pattern_parm))
/* Rename the parameter to include the index. */
DECL_NAME (decl_parm) =
@@ -24953,7 +24958,7 @@ tsubst_initializer_list (tree t, tree argvec)
NULL_TREE);
if (expanded_bases == error_mark_node)
continue;
-
+
/* We'll be building separate TREE_LISTs of arguments for
each base. */
len = TREE_VEC_LENGTH (expanded_bases);
@@ -24986,7 +24991,7 @@ tsubst_initializer_list (tree t, tree argvec)
/* Expand the argument. */
SET_PACK_EXPANSION_PATTERN (expr, TREE_VALUE (arg));
- expanded_exprs
+ expanded_exprs
= tsubst_pack_expansion (expr, argvec,
tf_warning_or_error,
NULL_TREE);
@@ -24997,8 +25002,8 @@ tsubst_initializer_list (tree t, tree argvec)
corresponding TREE_LIST in EXPANDED_ARGUMENTS. */
for (i = 0; i < len; i++)
{
- TREE_VEC_ELT (expanded_arguments, i) =
- tree_cons (NULL_TREE,
+ TREE_VEC_ELT (expanded_arguments, i) =
+ tree_cons (NULL_TREE,
TREE_VEC_ELT (expanded_exprs, i),
TREE_VEC_ELT (expanded_arguments, i));
}
@@ -25009,7 +25014,7 @@ tsubst_initializer_list (tree t, tree argvec)
since we built them backwards. */
for (i = 0; i < len; i++)
{
- TREE_VEC_ELT (expanded_arguments, i) =
+ TREE_VEC_ELT (expanded_arguments, i) =
nreverse (TREE_VEC_ELT (expanded_arguments, i));
}
}
@@ -25290,8 +25295,7 @@ dependent_type_p_r (tree type)
(type)));
else if (INDIRECT_TYPE_P (type))
return dependent_type_p (TREE_TYPE (type));
- else if (TREE_CODE (type) == FUNCTION_TYPE
- || TREE_CODE (type) == METHOD_TYPE)
+ else if (FUNC_OR_METHOD_TYPE_P (type))
{
tree arg_type;
@@ -25308,8 +25312,9 @@ dependent_type_p_r (tree type)
if (tree noex = TREE_PURPOSE (spec))
/* Treat DEFERRED_NOEXCEPT as non-dependent, since it doesn't
affect overload resolution and treating it as dependent breaks
- things. */
+ things. Same for an unparsed noexcept expression. */
if (TREE_CODE (noex) != DEFERRED_NOEXCEPT
+ && TREE_CODE (noex) != DEFERRED_PARSE
&& value_dependent_expression_p (noex))
return true;
return false;
@@ -25621,11 +25626,11 @@ value_dependent_expression_p (tree expression)
{
tree values = ARGUMENT_PACK_ARGS (expression);
int i, len = TREE_VEC_LENGTH (values);
-
+
for (i = 0; i < len; ++i)
if (value_dependent_expression_p (TREE_VEC_ELT (values, i)))
return true;
-
+
return false;
}
@@ -25971,8 +25976,7 @@ type_dependent_expression_p (tree expression)
return true;
}
- gcc_assert (TREE_CODE (expression) == OVERLOAD
- || TREE_CODE (expression) == FUNCTION_DECL);
+ gcc_assert (OVL_P (expression));
for (lkp_iterator iter (expression); iter; ++iter)
if (type_dependent_expression_p (*iter))
@@ -26558,7 +26562,7 @@ resolve_typename_type (tree type, bool only_current_p)
tf_warning_or_error);
result = NULL_TREE;
-
+
/* For a TYPENAME_TYPE like "typename X::template Y<T>", we want to
find a TEMPLATE_DECL. Otherwise, we want to find a TYPE_DECL. */
tree fullname = TYPENAME_TYPE_FULLNAME (type);
@@ -26597,7 +26601,7 @@ resolve_typename_type (tree type, bool only_current_p)
if (result == error_mark_node)
result = NULL_TREE;
}
-
+
/* Leave the SCOPE. */
if (pushed_scope)
pop_scope (pushed_scope);
@@ -26605,7 +26609,7 @@ resolve_typename_type (tree type, bool only_current_p)
/* If we failed to resolve it, return the original typename. */
if (!result)
return type;
-
+
/* If lookup found a typename type, resolve that too. */
if (TREE_CODE (result) == TYPENAME_TYPE && !TYPENAME_IS_RESOLVING_P (result))
{
@@ -26615,7 +26619,7 @@ resolve_typename_type (tree type, bool only_current_p)
result = resolve_typename_type (result, only_current_p);
TYPENAME_IS_RESOLVING_P (result) = 0;
}
-
+
/* Qualify the resulting type. */
quals = cp_type_quals (type);
if (quals)
@@ -26822,7 +26826,7 @@ listify (tree arg)
tree std_init_list = get_namespace_binding (std_node, init_list_identifier);
if (!std_init_list || !DECL_CLASS_TEMPLATE_P (std_init_list))
- {
+ {
gcc_rich_location richloc (input_location);
maybe_add_include_fixit (&richloc, "<initializer_list>", false);
error_at (&richloc,
@@ -26843,7 +26847,7 @@ listify (tree arg)
static tree
listify_autos (tree type, tree auto_node)
{
- tree init_auto = listify (auto_node);
+ tree init_auto = listify (strip_top_quals (auto_node));
tree argvec = make_tree_vec (1);
TREE_VEC_ELT (argvec, 0) = init_auto;
if (processing_template_decl)
@@ -27318,7 +27322,8 @@ do_class_deduction (tree ptype, tree tmpl, tree init, int flags,
bool try_list_ctor = false;
- vec<tree,va_gc> *args;
+ releasing_vec rv_args = NULL;
+ vec<tree,va_gc> *&args = *&rv_args;
if (init == NULL_TREE
|| TREE_CODE (init) == TREE_LIST)
args = make_tree_vector_from_list (init);
@@ -27491,8 +27496,6 @@ do_class_deduction (tree ptype, tree tmpl, tree init, int flags,
"for copy-initialization");
}
- release_tree_vector (args);
-
return cp_build_qualified_type (TREE_TYPE (call), cp_type_quals (ptype));
}
@@ -28319,8 +28322,9 @@ declare_integer_pack (void)
void
init_template_processing (void)
{
- decl_specializations = hash_table<spec_hasher>::create_ggc (37);
- type_specializations = hash_table<spec_hasher>::create_ggc (37);
+ /* FIXME: enable sanitization (PR87847) */
+ decl_specializations = hash_table<spec_hasher>::create_ggc (37, false);
+ type_specializations = hash_table<spec_hasher>::create_ggc (37, false);
if (cxx_dialect >= cxx11)
declare_integer_pack ();
diff --git a/gcc/cp/repo.c b/gcc/cp/repo.c
index 5588e6a..4c44a07 100644
--- a/gcc/cp/repo.c
+++ b/gcc/cp/repo.c
@@ -218,7 +218,7 @@ reopen_repo_file_for_write (void)
if (repo_file == 0)
{
- error ("can%'t create repository information file %qs", repo_name);
+ error ("cannot create repository information file %qs", repo_name);
flag_use_repository = 0;
}
diff --git a/gcc/cp/rtti.c b/gcc/cp/rtti.c
index 3ca2b5e..eb1b062 100644
--- a/gcc/cp/rtti.c
+++ b/gcc/cp/rtti.c
@@ -209,8 +209,8 @@ build_headof (tree exp)
offset = build_vtbl_ref (cp_build_fold_indirect_ref (exp),
index);
- type = cp_build_qualified_type (ptr_type_node,
- cp_type_quals (TREE_TYPE (exp)));
+ cp_build_qualified_type (ptr_type_node,
+ cp_type_quals (TREE_TYPE (exp)));
return fold_build_pointer_plus (exp, offset);
}
@@ -512,7 +512,7 @@ get_typeid (tree type, tsubst_flags_t complain)
|| type_memfn_rqual (type) != REF_QUAL_NONE))
{
if (complain & tf_error)
- error ("typeid of qualified function type %qT", type);
+ error ("%<typeid%> of qualified function type %qT", type);
return error_mark_node;
}
@@ -693,8 +693,8 @@ build_dynamic_cast_1 (tree type, tree expr, tsubst_flags_t complain)
{
tree expr = throw_bad_cast ();
if (complain & tf_warning)
- warning (0, "dynamic_cast of %q#D to %q#T can never succeed",
- old_expr, type);
+ warning (0, "%<dynamic_cast<%#T>(%#D)%> can never succeed",
+ type, old_expr);
/* Bash it to the expected type. */
TREE_TYPE (expr) = type;
return expr;
@@ -708,8 +708,8 @@ build_dynamic_cast_1 (tree type, tree expr, tsubst_flags_t complain)
&& TREE_CODE (TREE_TYPE (op)) == RECORD_TYPE)
{
if (complain & tf_warning)
- warning (0, "dynamic_cast of %q#D to %q#T can never succeed",
- op, type);
+ warning (0, "%<dynamic_cast<%#T>(%#D)%> can never succeed",
+ type, op);
retval = build_int_cst (type, 0);
return retval;
}
@@ -798,7 +798,7 @@ build_dynamic_cast_1 (tree type, tree expr, tsubst_flags_t complain)
fail:
if (complain & tf_error)
- error ("cannot dynamic_cast %qE (of type %q#T) to type %q#T (%s)",
+ error ("cannot %<dynamic_cast%> %qE (of type %q#T) to type %q#T (%s)",
old_expr, TREE_TYPE (old_expr), type, errstr);
return error_mark_node;
}
@@ -1015,8 +1015,7 @@ ptr_initializer (tinfo_s *ti, tree target)
to = tx_unsafe_fn_variant (to);
}
if (flag_noexcept_type
- && (TREE_CODE (to) == FUNCTION_TYPE
- || TREE_CODE (to) == METHOD_TYPE)
+ && FUNC_OR_METHOD_TYPE_P (to)
&& TYPE_NOTHROW_P (to))
{
flags |= 0x40;
diff --git a/gcc/cp/search.c b/gcc/cp/search.c
index 4c3fffd..372c442 100644
--- a/gcc/cp/search.c
+++ b/gcc/cp/search.c
@@ -1058,10 +1058,7 @@ build_baselink (tree binfo, tree access_binfo, tree functions, tree optype)
{
tree baselink;
- gcc_assert (TREE_CODE (functions) == FUNCTION_DECL
- || TREE_CODE (functions) == TEMPLATE_DECL
- || TREE_CODE (functions) == TEMPLATE_ID_EXPR
- || TREE_CODE (functions) == OVERLOAD);
+ gcc_assert (OVL_P (functions) || TREE_CODE (functions) == TEMPLATE_ID_EXPR);
gcc_assert (!optype || TYPE_P (optype));
gcc_assert (TREE_TYPE (functions));
@@ -1863,6 +1860,39 @@ locate_field_accessor (tree basetype_path, tree field_decl, bool const_p)
NULL, &lfd);
}
+/* Check throw specifier of OVERRIDER is at least as strict as
+ the one of BASEFN. */
+
+bool
+maybe_check_overriding_exception_spec (tree overrider, tree basefn)
+{
+ maybe_instantiate_noexcept (basefn);
+ maybe_instantiate_noexcept (overrider);
+ tree base_throw = TYPE_RAISES_EXCEPTIONS (TREE_TYPE (basefn));
+ tree over_throw = TYPE_RAISES_EXCEPTIONS (TREE_TYPE (overrider));
+
+ if (DECL_INVALID_OVERRIDER_P (overrider))
+ return true;
+
+ /* Can't check this yet. Pretend this is fine and let
+ noexcept_override_late_checks check this later. */
+ if (UNPARSED_NOEXCEPT_SPEC_P (base_throw)
+ || UNPARSED_NOEXCEPT_SPEC_P (over_throw))
+ return true;
+
+ if (!comp_except_specs (base_throw, over_throw, ce_derived))
+ {
+ auto_diagnostic_group d;
+ error ("looser exception specification on overriding virtual function "
+ "%q+#F", overrider);
+ inform (DECL_SOURCE_LOCATION (basefn),
+ "overridden function is %q#F", basefn);
+ DECL_INVALID_OVERRIDER_P (overrider) = 1;
+ return false;
+ }
+ return true;
+}
+
/* Check that virtual overrider OVERRIDER is acceptable for base function
BASEFN. Issue diagnostic, and return zero, if unacceptable. */
@@ -1873,7 +1903,6 @@ check_final_overrider (tree overrider, tree basefn)
tree base_type = TREE_TYPE (basefn);
tree over_return = fndecl_declared_return_type (overrider);
tree base_return = fndecl_declared_return_type (basefn);
- tree over_throw, base_throw;
int fail = 0;
@@ -1957,21 +1986,8 @@ check_final_overrider (tree overrider, tree basefn)
return 0;
}
- /* Check throw specifier is at least as strict. */
- maybe_instantiate_noexcept (basefn);
- maybe_instantiate_noexcept (overrider);
- base_throw = TYPE_RAISES_EXCEPTIONS (TREE_TYPE (basefn));
- over_throw = TYPE_RAISES_EXCEPTIONS (TREE_TYPE (overrider));
-
- if (!comp_except_specs (base_throw, over_throw, ce_derived))
- {
- auto_diagnostic_group d;
- error ("looser throw specifier for %q+#F", overrider);
- inform (DECL_SOURCE_LOCATION (basefn),
- "overridden function is %q#F", basefn);
- DECL_INVALID_OVERRIDER_P (overrider) = 1;
- return 0;
- }
+ if (!maybe_check_overriding_exception_spec (overrider, basefn))
+ return 0;
/* Check for conflicting type attributes. But leave transaction_safe for
set_one_vmethod_tm_attributes. */
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index 93bd8fb..4f71ac7 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -686,7 +686,7 @@ finish_expr_stmt (tree expr)
expr = convert_to_void (expr, ICV_STATEMENT, tf_warning_or_error);
}
else if (!type_dependent_expression_p (expr))
- convert_to_void (build_non_dependent_expr (expr), ICV_STATEMENT,
+ convert_to_void (build_non_dependent_expr (expr), ICV_STATEMENT,
tf_warning_or_error);
if (check_for_bare_parameter_packs (expr))
@@ -906,7 +906,7 @@ finish_return_stmt (tree expr)
{
if (warn_sequence_point)
verify_sequence_points (expr);
-
+
if (DECL_DESTRUCTOR_P (current_function_decl)
|| (DECL_CONSTRUCTOR_P (current_function_decl)
&& targetm.cxx.cdtor_returns_this ()))
@@ -1527,8 +1527,7 @@ finish_asm_stmt (int volatile_p, tree string, tree output_operands,
|| CP_TYPE_CONST_P (TREE_TYPE (operand))
/* Functions are not modifiable, even though they are
lvalues. */
- || TREE_CODE (TREE_TYPE (operand)) == FUNCTION_TYPE
- || TREE_CODE (TREE_TYPE (operand)) == METHOD_TYPE
+ || FUNC_OR_METHOD_TYPE_P (TREE_TYPE (operand))
/* If it's an aggregate and any field is const, then it is
effectively const. */
|| (CLASS_TYPE_P (TREE_TYPE (operand))
@@ -1571,7 +1570,7 @@ finish_asm_stmt (int volatile_p, tree string, tree output_operands,
{
constraint = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (t)));
bool constraint_parsed
- = parse_input_constraint (&constraint, i, ninputs, noutputs, 0,
+ = parse_input_constraint (&constraint, i, ninputs, noutputs, 0,
oconstraints, &allows_mem, &allows_reg);
/* If the operand is going to end up in memory, don't call
decay_conversion. */
@@ -1586,7 +1585,7 @@ finish_asm_stmt (int volatile_p, tree string, tree output_operands,
resolve the overloading. */
if (TREE_TYPE (operand) == unknown_type_node)
{
- error ("type of asm operand %qE could not be determined",
+ error ("type of %<asm%> operand %qE could not be determined",
TREE_VALUE (t));
operand = error_mark_node;
}
@@ -1668,7 +1667,7 @@ finish_label_decl (tree name)
{
if (!at_function_scope_p ())
{
- error ("__label__ declarations are only allowed in function scopes");
+ error ("%<__label__%> declarations are only allowed in function scopes");
return;
}
@@ -2021,7 +2020,7 @@ check_accessibility_of_qualified_id (tree decl,
its bases. */
qualifying_type = currently_open_derived_class (scope);
- if (qualifying_type
+ if (qualifying_type
/* It is possible for qualifying type to be a TEMPLATE_TYPE_PARM
or similar in a default argument value. */
&& CLASS_TYPE_P (qualifying_type)
@@ -3005,7 +3004,7 @@ finish_template_template_parm (tree aggr, tree identifier)
gcc_assert (DECL_TEMPLATE_PARMS (tmpl));
- check_default_tmpl_args (decl, DECL_TEMPLATE_PARMS (tmpl),
+ check_default_tmpl_args (decl, DECL_TEMPLATE_PARMS (tmpl),
/*is_primary=*/true, /*is_partial=*/false,
/*is_friend=*/0);
@@ -3380,7 +3379,7 @@ baselink_for_fns (tree fns)
tree scope;
tree cl;
- if (BASELINK_P (fns)
+ if (BASELINK_P (fns)
|| error_operand_p (fns))
return fns;
@@ -3869,7 +3868,7 @@ finish_id_expression_1 (tree id_expression,
if (DECL_P (decl) && DECL_NONLOCAL (decl)
&& DECL_CLASS_SCOPE_P (decl))
{
- tree context = context_for_name_lookup (decl);
+ tree context = context_for_name_lookup (decl);
if (context != current_class_type)
{
tree path = currently_open_derived_class (context);
@@ -3993,7 +3992,7 @@ calculate_direct_bases (tree type, tsubst_flags_t complain)
|| !NON_UNION_CLASS_TYPE_P (type))
return make_tree_vec (0);
- vec<tree, va_gc> *vector = make_tree_vector ();
+ releasing_vec vector;
vec<tree, va_gc> *base_binfos = BINFO_BASE_BINFOS (TYPE_BINFO (type));
tree binfo;
unsigned i;
@@ -4013,7 +4012,6 @@ calculate_direct_bases (tree type, tsubst_flags_t complain)
for (i = 0; i < vector->length (); ++i)
TREE_VEC_ELT (bases_vec, i) = BINFO_TYPE ((*vector)[i]);
- release_tree_vector (vector);
return bases_vec;
}
@@ -4059,27 +4057,24 @@ calculate_bases (tree type, tsubst_flags_t complain)
|| !NON_UNION_CLASS_TYPE_P (type))
return make_tree_vec (0);
- vec<tree, va_gc> *vector = make_tree_vector ();
+ releasing_vec vector;
tree bases_vec = NULL_TREE;
unsigned i;
vec<tree, va_gc> *vbases;
- vec<tree, va_gc> *nonvbases;
tree binfo;
/* First go through virtual base classes */
for (vbases = CLASSTYPE_VBASECLASSES (type), i = 0;
vec_safe_iterate (vbases, i, &binfo); i++)
{
- vec<tree, va_gc> *vbase_bases
+ releasing_vec vbase_bases
= calculate_bases_helper (BINFO_TYPE (binfo));
vec_safe_splice (vector, vbase_bases);
- release_tree_vector (vbase_bases);
}
/* Now for the non-virtual bases */
- nonvbases = calculate_bases_helper (type);
+ releasing_vec nonvbases = calculate_bases_helper (type);
vec_safe_splice (vector, nonvbases);
- release_tree_vector (nonvbases);
/* Note that during error recovery vector->length can even be zero. */
if (vector->length () > 1)
@@ -4093,7 +4088,6 @@ calculate_bases (tree type, tsubst_flags_t complain)
else
bases_vec = make_tree_vec (0);
- release_tree_vector (vector);
return bases_vec;
}
@@ -4105,7 +4099,7 @@ finish_bases (tree type, bool direct)
if (!processing_template_decl)
{
/* Parameter packs can only be used in templates */
- error ("Parameter pack __bases only valid in template declaration");
+ error ("parameter pack %<__bases%> only valid in template declaration");
return error_mark_node;
}
@@ -4141,8 +4135,7 @@ finish_offsetof (tree object_ptr, tree expr, location_t loc)
TREE_OPERAND (expr, 2));
return error_mark_node;
}
- if (TREE_CODE (TREE_TYPE (expr)) == FUNCTION_TYPE
- || TREE_CODE (TREE_TYPE (expr)) == METHOD_TYPE
+ if (FUNC_OR_METHOD_TYPE_P (TREE_TYPE (expr))
|| TREE_TYPE (expr) == unknown_type_node)
{
while (TREE_CODE (expr) == COMPONENT_REF
@@ -4171,7 +4164,7 @@ finish_offsetof (tree object_ptr, tree expr, location_t loc)
&& CLASS_TYPE_P (TREE_TYPE (TREE_TYPE (object_ptr)))
&& CLASSTYPE_NON_STD_LAYOUT (TREE_TYPE (TREE_TYPE (object_ptr)))
&& cp_unevaluated_operand == 0)
- warning_at (loc, OPT_Winvalid_offsetof, "offsetof within "
+ warning_at (loc, OPT_Winvalid_offsetof, "%<offsetof%> within "
"non-standard-layout type %qT is conditionally-supported",
TREE_TYPE (TREE_TYPE (object_ptr)));
return fold_offsetof (expr);
@@ -5538,8 +5531,7 @@ cp_check_omp_declare_reduction (tree udr)
return;
}
}
- else if (TREE_CODE (type) == FUNCTION_TYPE
- || TREE_CODE (type) == METHOD_TYPE
+ else if (FUNC_OR_METHOD_TYPE_P (type)
|| TREE_CODE (type) == ARRAY_TYPE)
{
error_at (loc, "function or array type %qT in "
@@ -5554,8 +5546,8 @@ cp_check_omp_declare_reduction (tree udr)
}
else if (TYPE_QUALS_NO_ADDR_SPACE (type))
{
- error_at (loc, "const, volatile or __restrict qualified type %qT in "
- "%<#pragma omp declare reduction%>", type);
+ error_at (loc, "%<const%>, %<volatile%> or %<__restrict%>-qualified "
+ "type %qT in %<#pragma omp declare reduction%>", type);
return;
}
@@ -6134,10 +6126,13 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
bool branch_seen = false;
bool copyprivate_seen = false;
bool ordered_seen = false;
+ bool schedule_seen = false;
bool oacc_async = false;
tree last_iterators = NULL_TREE;
bool last_iterators_remove = false;
- bool reduction_seen = false;
+ /* 1 if normal/task reduction has been seen, -1 if inscan reduction
+ has been seen, -2 if mixed inscan/normal reduction diagnosed. */
+ int reduction_seen = 0;
bitmap_obstack_initialize (NULL);
bitmap_initialize (&generic_head, &bitmap_default_obstack);
@@ -6172,7 +6167,17 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
field_ok = ((ort & C_ORT_OMP_DECLARE_SIMD) == C_ORT_OMP);
goto check_dup_generic;
case OMP_CLAUSE_REDUCTION:
- reduction_seen = true;
+ if (reduction_seen == 0)
+ reduction_seen = OMP_CLAUSE_REDUCTION_INSCAN (c) ? -1 : 1;
+ else if (reduction_seen != -2
+ && reduction_seen != (OMP_CLAUSE_REDUCTION_INSCAN (c)
+ ? -1 : 1))
+ {
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "%<inscan%> and non-%<inscan%> %<reduction%> clauses "
+ "on the same construct");
+ reduction_seen = -2;
+ }
/* FALLTHRU */
case OMP_CLAUSE_IN_REDUCTION:
case OMP_CLAUSE_TASK_REDUCTION:
@@ -6185,6 +6190,15 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
remove = true;
break;
}
+ if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
+ && OMP_CLAUSE_REDUCTION_INSCAN (c))
+ {
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "%<inscan%> %<reduction%> clause with array "
+ "section");
+ remove = true;
+ break;
+ }
if (TREE_CODE (t) == TREE_LIST)
{
while (TREE_CODE (t) == TREE_LIST)
@@ -6692,6 +6706,8 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
}
OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (c) = t;
}
+ if (!remove)
+ schedule_seen = true;
break;
case OMP_CLAUSE_SIMDLEN:
@@ -7591,6 +7607,37 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
branch_seen = true;
break;
+ case OMP_CLAUSE_INCLUSIVE:
+ case OMP_CLAUSE_EXCLUSIVE:
+ t = omp_clause_decl_field (OMP_CLAUSE_DECL (c));
+ if (!t)
+ t = OMP_CLAUSE_DECL (c);
+ if (t == current_class_ptr)
+ {
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "%<this%> allowed in OpenMP only in %<declare simd%>"
+ " clauses");
+ remove = true;
+ break;
+ }
+ if (!VAR_P (t)
+ && TREE_CODE (t) != PARM_DECL
+ && TREE_CODE (t) != FIELD_DECL)
+ {
+ if (processing_template_decl && TREE_CODE (t) != OVERLOAD)
+ break;
+ if (DECL_P (t))
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "%qD is not a variable in clause %qs", t,
+ omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
+ else
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "%qE is not a variable in clause %qs", t,
+ omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
+ remove = true;
+ }
+ break;
+
default:
gcc_unreachable ();
}
@@ -7601,6 +7648,9 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
pc = &OMP_CLAUSE_CHAIN (c);
}
+ if (reduction_seen < 0 && (ordered_seen || schedule_seen))
+ reduction_seen = -2;
+
for (pc = &clauses, c = clauses; c ; c = *pc)
{
enum omp_clause_code c_kind = OMP_CLAUSE_CODE (c);
@@ -7636,8 +7686,16 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
need_implicitly_determined = true;
break;
case OMP_CLAUSE_REDUCTION:
+ if (reduction_seen == -2)
+ OMP_CLAUSE_REDUCTION_INSCAN (c) = 0;
+ if (OMP_CLAUSE_REDUCTION_INSCAN (c))
+ need_copy_assignment = true;
+ need_implicitly_determined = true;
+ break;
case OMP_CLAUSE_IN_REDUCTION:
case OMP_CLAUSE_TASK_REDUCTION:
+ case OMP_CLAUSE_INCLUSIVE:
+ case OMP_CLAUSE_EXCLUSIVE:
need_implicitly_determined = true;
break;
case OMP_CLAUSE_LINEAR:
@@ -7688,6 +7746,10 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
(OMP_CLAUSE_SCHEDULE_KIND (c)
& ~OMP_CLAUSE_SCHEDULE_NONMONOTONIC);
}
+ if (reduction_seen == -2)
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "%qs clause specified together with %<inscan%> "
+ "%<reduction%> clause", "schedule");
pc = &OMP_CLAUSE_CHAIN (c);
continue;
case OMP_CLAUSE_NOGROUP:
@@ -7701,6 +7763,13 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
}
pc = &OMP_CLAUSE_CHAIN (c);
continue;
+ case OMP_CLAUSE_ORDERED:
+ if (reduction_seen == -2)
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "%qs clause specified together with %<inscan%> "
+ "%<reduction%> clause", "ordered");
+ pc = &OMP_CLAUSE_CHAIN (c);
+ continue;
case OMP_CLAUSE_NOWAIT:
if (copyprivate_seen)
{
@@ -7762,7 +7831,8 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
t = require_complete_type (t);
if (t == error_mark_node)
remove = true;
- else if (TYPE_REF_P (TREE_TYPE (t))
+ else if (!processing_template_decl
+ && TYPE_REF_P (TREE_TYPE (t))
&& !complete_type_or_else (TREE_TYPE (TREE_TYPE (t)), t))
remove = true;
}
@@ -7962,7 +8032,7 @@ restore_omp_privatization_clauses (vec<tree> &save)
save.release ();
return;
}
-
+
omp_private_member_map = new hash_map <tree, tree>;
while (!save.is_empty ())
{
@@ -8976,7 +9046,7 @@ finish_omp_atomic (location_t loc, enum tree_code code, enum tree_code opcode,
{
if (opcode == NOP_EXPR)
stmt = build2 (MODIFY_EXPR, void_type_node, orig_lhs, orig_rhs);
- else
+ else
stmt = build2 (opcode, void_type_node, orig_lhs, orig_rhs);
if (orig_rhs1)
stmt = build_min_nt_loc (EXPR_LOCATION (orig_rhs1),
@@ -9005,9 +9075,8 @@ void
finish_omp_barrier (void)
{
tree fn = builtin_decl_explicit (BUILT_IN_GOMP_BARRIER);
- vec<tree, va_gc> *vec = make_tree_vector ();
+ releasing_vec vec;
tree stmt = finish_call_expr (fn, &vec, false, false, tf_warning_or_error);
- release_tree_vector (vec);
finish_expr_stmt (stmt);
}
@@ -9050,14 +9119,13 @@ void
finish_omp_flush (int mo)
{
tree fn = builtin_decl_explicit (BUILT_IN_SYNC_SYNCHRONIZE);
- vec<tree, va_gc> *vec = make_tree_vector ();
+ releasing_vec vec;
if (mo != MEMMODEL_LAST)
{
fn = builtin_decl_explicit (BUILT_IN_ATOMIC_THREAD_FENCE);
vec->quick_push (build_int_cst (integer_type_node, mo));
}
tree stmt = finish_call_expr (fn, &vec, false, false, tf_warning_or_error);
- release_tree_vector (vec);
finish_expr_stmt (stmt);
}
@@ -9065,9 +9133,8 @@ void
finish_omp_taskwait (void)
{
tree fn = builtin_decl_explicit (BUILT_IN_GOMP_TASKWAIT);
- vec<tree, va_gc> *vec = make_tree_vector ();
+ releasing_vec vec;
tree stmt = finish_call_expr (fn, &vec, false, false, tf_warning_or_error);
- release_tree_vector (vec);
finish_expr_stmt (stmt);
}
@@ -9075,9 +9142,8 @@ void
finish_omp_taskyield (void)
{
tree fn = builtin_decl_explicit (BUILT_IN_GOMP_TASKYIELD);
- vec<tree, va_gc> *vec = make_tree_vector ();
+ releasing_vec vec;
tree stmt = finish_call_expr (fn, &vec, false, false, tf_warning_or_error);
- release_tree_vector (vec);
finish_expr_stmt (stmt);
}
@@ -9100,7 +9166,7 @@ finish_omp_cancel (tree clauses)
"%<parallel%>, %<for%>, %<sections%> or %<taskgroup%> clauses");
return;
}
- vec<tree, va_gc> *vec = make_tree_vector ();
+ releasing_vec vec;
tree ifc = omp_find_clause (clauses, OMP_CLAUSE_IF);
if (ifc != NULL_TREE)
{
@@ -9134,7 +9200,6 @@ finish_omp_cancel (tree clauses)
vec->quick_push (build_int_cst (integer_type_node, mask));
vec->quick_push (ifc);
tree stmt = finish_call_expr (fn, &vec, false, false, tf_warning_or_error);
- release_tree_vector (vec);
finish_expr_stmt (stmt);
}
@@ -9157,10 +9222,9 @@ finish_omp_cancellation_point (tree clauses)
"%<parallel%>, %<for%>, %<sections%> or %<taskgroup%> clauses");
return;
}
- vec<tree, va_gc> *vec
+ releasing_vec vec
= make_tree_vector_single (build_int_cst (integer_type_node, mask));
tree stmt = finish_call_expr (fn, &vec, false, false, tf_warning_or_error);
- release_tree_vector (vec);
finish_expr_stmt (stmt);
}
@@ -9253,8 +9317,8 @@ init_cp_semantics (void)
CONDITION and the message text MESSAGE. LOCATION is the location
of the static assertion in the source code. When MEMBER_P, this
static assertion is a member of a class. */
-void
-finish_static_assert (tree condition, tree message, location_t location,
+void
+finish_static_assert (tree condition, tree message, location_t location,
bool member_p)
{
tsubst_flags_t complain = tf_warning_or_error;
@@ -9280,7 +9344,7 @@ finish_static_assert (tree condition, tree message, location_t location,
STATIC_ASSERT_SOURCE_LOCATION (assertion) = location;
if (member_p)
- maybe_add_class_template_decl_list (current_class_type,
+ maybe_add_class_template_decl_list (current_class_type,
assertion,
/*friend_p=*/0);
else
@@ -9298,12 +9362,12 @@ finish_static_assert (tree condition, tree message, location_t location,
if (TREE_CODE (condition) == INTEGER_CST && !integer_zerop (condition))
/* Do nothing; the condition is satisfied. */
;
- else
+ else
{
location_t saved_loc = input_location;
input_location = location;
- if (TREE_CODE (condition) == INTEGER_CST
+ if (TREE_CODE (condition) == INTEGER_CST
&& integer_zerop (condition))
{
int sz = TREE_INT_CST_LOW (TYPE_SIZE_UNIT
@@ -9348,7 +9412,7 @@ finish_decltype_type (tree expr, bool id_expression_or_member_access_p,
&& TYPE_P (TREE_OPERAND (expr, 0))))
{
if (complain & tf_error)
- error ("argument to decltype must be an expression");
+ error ("argument to %<decltype%> must be an expression");
return error_mark_node;
}
@@ -9376,7 +9440,7 @@ finish_decltype_type (tree expr, bool id_expression_or_member_access_p,
if (type_unknown_p (expr))
{
if (complain & tf_error)
- error ("decltype cannot resolve address of overloaded function");
+ error ("%<decltype%> cannot resolve address of overloaded function");
return error_mark_node;
}
@@ -9518,7 +9582,7 @@ finish_decltype_type (tree expr, bool id_expression_or_member_access_p,
return type;
}
-/* Called from trait_expr_value to evaluate either __has_nothrow_assign or
+/* Called from trait_expr_value to evaluate either __has_nothrow_assign or
__has_nothrow_copy, depending on assign_p. Returns true iff all
the copy {ctor,assign} fns are nothrow. */
@@ -9579,7 +9643,7 @@ trait_expr_value (cp_trait_kind kind, tree type1, tree type2)
case CPTK_HAS_NOTHROW_CONSTRUCTOR:
type1 = strip_array_types (type1);
- return (trait_expr_value (CPTK_HAS_TRIVIAL_CONSTRUCTOR, type1, type2)
+ return (trait_expr_value (CPTK_HAS_TRIVIAL_CONSTRUCTOR, type1, type2)
|| (CLASS_TYPE_P (type1)
&& (t = locate_ctor (type1))
&& maybe_instantiate_noexcept (t)
diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c
index 718eed3..37e24a1 100644
--- a/gcc/cp/tree.c
+++ b/gcc/cp/tree.c
@@ -83,6 +83,10 @@ lvalue_kind (const_tree ref)
if (ref == current_class_ptr)
return clk_none;
+ /* Expressions with cv void type are prvalues. */
+ if (TREE_TYPE (ref) && VOID_TYPE_P (TREE_TYPE (ref)))
+ return clk_none;
+
switch (TREE_CODE (ref))
{
case SAVE_EXPR:
@@ -698,7 +702,6 @@ static tree
build_vec_init_elt (tree type, tree init, tsubst_flags_t complain)
{
tree inner_type = strip_array_types (type);
- vec<tree, va_gc> *argvec;
if (integer_zerop (array_type_nelts_total (type))
|| !CLASS_TYPE_P (inner_type))
@@ -711,7 +714,7 @@ build_vec_init_elt (tree type, tree init, tsubst_flags_t complain)
|| (same_type_ignoring_top_level_qualifiers_p
(type, TREE_TYPE (init))));
- argvec = make_tree_vector ();
+ releasing_vec argvec;
if (init)
{
tree init_type = strip_array_types (TREE_TYPE (init));
@@ -723,7 +726,6 @@ build_vec_init_elt (tree type, tree init, tsubst_flags_t complain)
init = build_special_member_call (NULL_TREE, complete_ctor_identifier,
&argvec, inner_type, LOOKUP_NORMAL,
complain);
- release_tree_vector (argvec);
/* For a trivial constructor, build_over_call creates a TARGET_EXPR. But
we don't want one here because we aren't creating a temporary. */
@@ -1308,8 +1310,7 @@ cp_build_qualified_type_real (tree type,
(in CD1) we always ignore extra cv-quals on functions. */
if (type_quals & (TYPE_QUAL_CONST | TYPE_QUAL_VOLATILE)
&& (TYPE_REF_P (type)
- || TREE_CODE (type) == FUNCTION_TYPE
- || TREE_CODE (type) == METHOD_TYPE))
+ || FUNC_OR_METHOD_TYPE_P (type)))
{
if (TYPE_REF_P (type))
bad_quals |= type_quals & (TYPE_QUAL_CONST | TYPE_QUAL_VOLATILE);
@@ -1452,7 +1453,7 @@ strip_typedefs (tree t, bool *remove_attributes)
if (TREE_CODE (t) == TREE_LIST)
{
bool changed = false;
- vec<tree,va_gc> *vec = make_tree_vector ();
+ releasing_vec vec;
tree r = t;
for (; t; t = TREE_CHAIN (t))
{
@@ -1464,7 +1465,6 @@ strip_typedefs (tree t, bool *remove_attributes)
}
if (changed)
r = build_tree_list_vec (vec);
- release_tree_vector (vec);
return r;
}
@@ -1752,7 +1752,7 @@ strip_typedefs_expr (tree t, bool *remove_attributes)
case TREE_LIST:
{
- vec<tree, va_gc> *vec = make_tree_vector ();
+ releasing_vec vec;
bool changed = false;
tree it;
for (it = t; it; it = TREE_CHAIN (it))
@@ -1771,14 +1771,13 @@ strip_typedefs_expr (tree t, bool *remove_attributes)
}
else
r = t;
- release_tree_vector (vec);
return r;
}
case TREE_VEC:
{
bool changed = false;
- vec<tree, va_gc> *vec = make_tree_vector ();
+ releasing_vec vec;
n = TREE_VEC_LENGTH (t);
vec_safe_reserve (vec, n);
for (i = 0; i < n; ++i)
@@ -1799,7 +1798,6 @@ strip_typedefs_expr (tree t, bool *remove_attributes)
}
else
r = t;
- release_tree_vector (vec);
return r;
}
@@ -2387,8 +2385,7 @@ is_overloaded_fn (tree x)
|| (TREE_CODE (x) == OVERLOAD && !OVL_SINGLE_P (x)))
return 2;
- return (TREE_CODE (x) == FUNCTION_DECL
- || TREE_CODE (x) == OVERLOAD);
+ return OVL_P (x);
}
/* X is the CALL_EXPR_FN of a CALL_EXPR. If X represents a dependent name
@@ -2402,7 +2399,7 @@ dependent_name (tree x)
return x;
if (TREE_CODE (x) == TEMPLATE_ID_EXPR)
x = TREE_OPERAND (x, 0);
- if (TREE_CODE (x) == OVERLOAD || TREE_CODE (x) == FUNCTION_DECL)
+ if (OVL_P (x))
return OVL_NAME (x);
return NULL_TREE;
}
@@ -2434,8 +2431,7 @@ maybe_get_fns (tree from)
if (TREE_CODE (from) == TEMPLATE_ID_EXPR)
from = TREE_OPERAND (from, 0);
- if (TREE_CODE (from) == OVERLOAD
- || TREE_CODE (from) == FUNCTION_DECL)
+ if (OVL_P (from))
return from;
return NULL;
@@ -2550,6 +2546,7 @@ canonical_eh_spec (tree raises)
if (raises == NULL_TREE)
return raises;
else if (DEFERRED_NOEXCEPT_SPEC_P (raises)
+ || UNPARSED_NOEXCEPT_SPEC_P (raises)
|| uses_template_parms (raises)
|| uses_template_parms (TREE_PURPOSE (raises)))
/* Keep a dependent or deferred exception specification. */
@@ -3356,7 +3353,6 @@ build_min_non_dep_op_overload (enum tree_code op,
va_list p;
int nargs, expected_nargs;
tree fn, call;
- vec<tree, va_gc> *args;
non_dep = extract_call_expr (non_dep);
@@ -3370,7 +3366,7 @@ build_min_non_dep_op_overload (enum tree_code op,
expected_nargs += 1;
gcc_assert (nargs == expected_nargs);
- args = make_tree_vector ();
+ releasing_vec args;
va_start (p, overload);
if (TREE_CODE (TREE_TYPE (overload)) == FUNCTION_TYPE)
@@ -3400,7 +3396,6 @@ build_min_non_dep_op_overload (enum tree_code op,
va_end (p);
call = build_min_non_dep_call_vec (non_dep, fn, args);
- release_tree_vector (args);
tree call_expr = extract_call_expr (call);
KOENIG_LOOKUP_P (call_expr) = KOENIG_LOOKUP_P (non_dep);
@@ -3662,6 +3657,7 @@ cp_tree_equal (tree t1, tree t2)
case IDENTIFIER_NODE:
case SSA_NAME:
case USING_DECL:
+ case DEFERRED_PARSE:
return false;
case BASELINK:
@@ -4108,7 +4104,8 @@ trivially_copyable_p (const_tree t)
&& !TYPE_HAS_COMPLEX_MOVE_ASSIGN (t)
&& TYPE_HAS_TRIVIAL_DESTRUCTOR (t));
else
- return !CP_TYPE_VOLATILE_P (t) && scalarish_type_p (t);
+ /* CWG 2094 makes volatile-qualified scalars trivially copyable again. */
+ return scalarish_type_p (t);
}
/* Returns 1 iff type T is a trivial type, as defined in [basic.types] and
@@ -4458,6 +4455,8 @@ const struct attribute_spec std_attribute_table[] =
handle_likeliness_attribute, attr_cold_hot_exclusions },
{ "unlikely", 0, 0, false, false, false, false,
handle_likeliness_attribute, attr_cold_hot_exclusions },
+ { "noreturn", 0, 0, true, false, false, false,
+ handle_noreturn_attribute, attr_noreturn_exclusions },
{ NULL, 0, 0, false, false, false, false, NULL, NULL }
};
@@ -4482,7 +4481,7 @@ handle_init_priority_attribute (tree* node,
if (!initp_expr || TREE_CODE (initp_expr) != INTEGER_CST)
{
- error ("requested init_priority is not an integer constant");
+ error ("requested %<init_priority%> is not an integer constant");
cxx_constant_value (initp_expr);
*no_add_attrs = true;
return NULL_TREE;
@@ -4512,7 +4511,8 @@ handle_init_priority_attribute (tree* node,
if (pri > MAX_INIT_PRIORITY || pri <= 0)
{
- error ("requested init_priority is out of range");
+ error ("requested %<init_priority%> %i is out of range [0, %i]",
+ pri, MAX_INIT_PRIORITY);
*no_add_attrs = true;
return NULL_TREE;
}
@@ -4522,7 +4522,8 @@ handle_init_priority_attribute (tree* node,
if (pri <= MAX_RESERVED_INIT_PRIORITY)
{
warning
- (0, "requested init_priority is reserved for internal use");
+ (0, "requested %<init_priority%> %i is reserved for internal use",
+ pri);
}
if (SUPPORTS_INIT_PRIORITY)
@@ -4725,8 +4726,7 @@ cp_build_type_attribute_variant (tree type, tree attributes)
tree new_type;
new_type = build_type_attribute_variant (type, attributes);
- if (TREE_CODE (new_type) == FUNCTION_TYPE
- || TREE_CODE (new_type) == METHOD_TYPE)
+ if (FUNC_OR_METHOD_TYPE_P (new_type))
gcc_checking_assert (cxx_type_hash_eq (type, new_type));
/* Making a new main variant of a class type is broken. */
@@ -4741,8 +4741,7 @@ cp_build_type_attribute_variant (tree type, tree attributes)
bool
cxx_type_hash_eq (const_tree typea, const_tree typeb)
{
- gcc_assert (TREE_CODE (typea) == FUNCTION_TYPE
- || TREE_CODE (typea) == METHOD_TYPE);
+ gcc_assert (FUNC_OR_METHOD_TYPE_P (typea));
if (type_memfn_rqual (typea) != type_memfn_rqual (typeb))
return false;
@@ -4759,7 +4758,7 @@ tree
cxx_copy_lang_qualifiers (const_tree typea, const_tree typeb)
{
tree type = CONST_CAST_TREE (typea);
- if (TREE_CODE (type) == FUNCTION_TYPE || TREE_CODE (type) == METHOD_TYPE)
+ if (FUNC_OR_METHOD_TYPE_P (type))
type = build_cp_fntype_variant (type, type_memfn_rqual (typeb),
TYPE_RAISES_EXCEPTIONS (typeb),
TYPE_HAS_LATE_RETURN_TYPE (typeb));
@@ -4789,7 +4788,7 @@ cp_walk_subtrees (tree *tp, int *walk_subtrees_p, walk_tree_fn func,
result = NULL_TREE;
switch (code)
{
- case DEFAULT_ARG:
+ case DEFERRED_PARSE:
case TEMPLATE_TEMPLATE_PARM:
case BOUND_TEMPLATE_TEMPLATE_PARM:
case UNBOUND_CLASS_TEMPLATE:
@@ -5371,8 +5370,7 @@ cp_fix_function_decl_p (tree decl)
void
cp_free_lang_data (tree t)
{
- if (TREE_CODE (t) == METHOD_TYPE
- || TREE_CODE (t) == FUNCTION_TYPE)
+ if (FUNC_OR_METHOD_TYPE_P (t))
{
/* Default args are not interesting anymore. */
tree argtypes = TYPE_ARG_TYPES (t);
@@ -5490,7 +5488,7 @@ maybe_warn_zero_as_null_pointer_constant (tree expr, location_t loc)
void
lang_check_failed (const char* file, int line, const char* function)
{
- internal_error ("lang_* check: failed in %s, at %s:%d",
+ internal_error ("%<lang_*%> check: failed in %s, at %s:%d",
function, trim_filename (file), line);
}
#endif /* ENABLE_TREE_CHECKING */
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index 06f485a..7709595 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -1262,8 +1262,7 @@ structural_comptypes (tree t1, tree t2, int strict)
return false;
/* Need to check this before TYPE_MAIN_VARIANT.
FIXME function qualifiers should really change the main variant. */
- if (TREE_CODE (t1) == FUNCTION_TYPE
- || TREE_CODE (t1) == METHOD_TYPE)
+ if (FUNC_OR_METHOD_TYPE_P (t1))
{
if (type_memfn_rqual (t1) != type_memfn_rqual (t2))
return false;
@@ -1691,7 +1690,7 @@ cxx_sizeof_expr (tree e, tsubst_flags_t complain)
if (e == error_mark_node)
return error_mark_node;
- if (processing_template_decl)
+ if (instantiation_dependent_uneval_expression_p (e))
{
e = build_min (SIZEOF_EXPR, size_type_node, e);
TREE_SIDE_EFFECTS (e) = 0;
@@ -3757,14 +3756,12 @@ build_function_call_vec (location_t /*loc*/, vec<location_t> /*arg_loc*/,
static tree
cp_build_function_call (tree function, tree params, tsubst_flags_t complain)
{
- vec<tree, va_gc> *vec;
tree ret;
- vec = make_tree_vector ();
+ releasing_vec vec;
for (; params != NULL_TREE; params = TREE_CHAIN (params))
vec_safe_push (vec, TREE_VALUE (params));
ret = cp_build_function_call_vec (function, &vec, complain);
- release_tree_vector (vec);
return ret;
}
@@ -3773,17 +3770,15 @@ cp_build_function_call (tree function, tree params, tsubst_flags_t complain)
tree
cp_build_function_call_nary (tree function, tsubst_flags_t complain, ...)
{
- vec<tree, va_gc> *vec;
va_list args;
tree ret, t;
- vec = make_tree_vector ();
+ releasing_vec vec;
va_start (args, complain);
for (t = va_arg (args, tree); t != NULL_TREE; t = va_arg (args, tree))
vec_safe_push (vec, t);
va_end (args);
ret = cp_build_function_call_vec (function, &vec, complain);
- release_tree_vector (vec);
return ret;
}
@@ -3837,7 +3832,7 @@ cp_build_function_call_vec (tree function, vec<tree, va_gc> **params,
return error_mark_node;
}
- if (!mark_used (function, complain) && !(complain & tf_error))
+ if (!mark_used (function, complain))
return error_mark_node;
fndecl = function;
@@ -4037,8 +4032,7 @@ convert_arguments (tree typelist, vec<tree, va_gc> **values, tree fndecl,
if (type == 0 || !TYPE_REF_P (type))
{
if (TREE_CODE (TREE_TYPE (val)) == ARRAY_TYPE
- || TREE_CODE (TREE_TYPE (val)) == FUNCTION_TYPE
- || TREE_CODE (TREE_TYPE (val)) == METHOD_TYPE)
+ || FUNC_OR_METHOD_TYPE_P (TREE_TYPE (val)))
val = decay_conversion (val, complain);
}
@@ -4110,7 +4104,7 @@ convert_arguments (tree typelist, vec<tree, va_gc> **values, tree fndecl,
provide default arguments in a language conformant
manner. */
if (fndecl && TREE_PURPOSE (typetail)
- && TREE_CODE (TREE_PURPOSE (typetail)) != DEFAULT_ARG)
+ && TREE_CODE (TREE_PURPOSE (typetail)) != DEFERRED_PARSE)
{
for (; typetail != void_list_node; ++i)
{
@@ -4402,10 +4396,6 @@ cp_build_binary_op (const op_location_t &location,
/* True if both operands have arithmetic type. */
bool arithmetic_types_p;
- /* Apply default conversions. */
- op0 = orig_op0;
- op1 = orig_op1;
-
/* Remember whether we're doing / or %. */
bool doing_div_or_mod = false;
@@ -4415,6 +4405,10 @@ cp_build_binary_op (const op_location_t &location,
/* Tree holding instrumentation expression. */
tree instrument_expr = NULL_TREE;
+ /* Apply default conversions. */
+ op0 = resolve_nondeduced_context (orig_op0, complain);
+ op1 = resolve_nondeduced_context (orig_op1, complain);
+
if (code == TRUTH_AND_EXPR || code == TRUTH_ANDIF_EXPR
|| code == TRUTH_OR_EXPR || code == TRUTH_ORIF_EXPR
|| code == TRUTH_XOR_EXPR)
@@ -4893,7 +4887,7 @@ cp_build_binary_op (const op_location_t &location,
&& c_inhibit_evaluation_warnings == 0
&& (FLOAT_TYPE_P (type0) || FLOAT_TYPE_P (type1)))
warning (OPT_Wfloat_equal,
- "comparing floating point with == or != is unsafe");
+ "comparing floating-point with %<==%> or %<!=%> is unsafe");
if (complain & tf_warning)
{
tree stripped_orig_op0 = tree_strip_any_location_wrapper (orig_op0);
@@ -5224,7 +5218,6 @@ cp_build_binary_op (const op_location_t &location,
}
result_type = build_opaque_vector_type (intt,
TYPE_VECTOR_SUBPARTS (type0));
- converted = 1;
return build_vec_cmp (resultcode, result_type, op0, op1);
}
build_type = boolean_type_node;
@@ -5294,7 +5287,7 @@ cp_build_binary_op (const op_location_t &location,
if (code0 != REAL_TYPE || code1 != REAL_TYPE)
{
if (complain & tf_error)
- error ("unordered comparison on non-floating point argument");
+ error ("unordered comparison on non-floating-point argument");
return error_mark_node;
}
common = 1;
@@ -6022,8 +6015,7 @@ cp_build_addr_expr_1 (tree arg, bool strict_lvalue, tsubst_flags_t complain)
/* Anything not already handled and not a true memory reference
is an error. */
- if (TREE_CODE (argtype) != FUNCTION_TYPE
- && TREE_CODE (argtype) != METHOD_TYPE)
+ if (!FUNC_OR_METHOD_TYPE_P (argtype))
{
cp_lvalue_kind kind = lvalue_kind (arg);
if (kind == clk_none)
@@ -6223,11 +6215,13 @@ cp_build_unary_op (enum tree_code code, tree xarg, bool noconvert,
if (!arg || error_operand_p (arg))
return error_mark_node;
+ arg = resolve_nondeduced_context (arg, complain);
+
if ((invalid_op_diag
= targetm.invalid_unary_op ((code == UNARY_PLUS_EXPR
? CONVERT_EXPR
: code),
- TREE_TYPE (xarg))))
+ TREE_TYPE (arg))))
{
if (complain & tf_error)
error (invalid_op_diag);
@@ -6281,7 +6275,7 @@ cp_build_unary_op (enum tree_code code, tree xarg, bool noconvert,
if (TREE_CODE (TREE_TYPE (arg)) == BOOLEAN_TYPE
&& (complain & tf_warning)
&& warning_at (location, OPT_Wbool_operation,
- "%<~%> on an expression of type bool"))
+ "%<~%> on an expression of type %<bool%>"))
inform (location, "did you mean to use logical not (%<!%>)?");
arg = cp_perform_integral_promotions (arg, complain);
}
@@ -6600,8 +6594,7 @@ unary_complex_lvalue (enum tree_code code, tree arg)
return arg;
}
- if (TREE_CODE (TREE_TYPE (arg)) == FUNCTION_TYPE
- || TREE_CODE (TREE_TYPE (arg)) == METHOD_TYPE
+ if (FUNC_OR_METHOD_TYPE_P (TREE_TYPE (arg))
|| TREE_CODE (arg) == OFFSET_REF)
return NULL_TREE;
@@ -6950,13 +6943,15 @@ check_for_casting_away_constness (tree src_type, tree dest_type,
case STATIC_CAST_EXPR:
if (complain & tf_error)
- error ("static_cast from type %qT to type %qT casts away qualifiers",
+ error ("%<static_cast%> from type %qT to type %qT casts away "
+ "qualifiers",
src_type, dest_type);
return true;
case REINTERPRET_CAST_EXPR:
if (complain & tf_error)
- error ("reinterpret_cast from type %qT to type %qT casts away qualifiers",
+ error ("%<reinterpret_cast%> from type %qT to type %qT casts away "
+ "qualifiers",
src_type, dest_type);
return true;
@@ -7243,8 +7238,8 @@ build_static_cast_1 (tree type, tree expr, bool c_cast_p,
conversion does not cast away constness (_expr.const.cast_), and
the following additional rules for specific cases: */
/* For reference, the conversions not excluded are: integral
- promotions, floating point promotion, integral conversions,
- floating point conversions, floating-integral conversions,
+ promotions, floating-point promotion, integral conversions,
+ floating-point conversions, floating-integral conversions,
pointer conversions, and pointer to member conversions. */
/* DR 128
@@ -7409,7 +7404,7 @@ build_static_cast (tree type, tree oexpr, tsubst_flags_t complain)
if (complain & tf_error)
{
- error ("invalid static_cast from type %qT to type %qT",
+ error ("invalid %<static_cast%> from type %qT to type %qT",
TREE_TYPE (expr), type);
if ((TYPE_PTR_P (type) || TYPE_REF_P (type))
&& CLASS_TYPE_P (TREE_TYPE (type))
@@ -7746,7 +7741,7 @@ build_const_cast_1 (tree dst_type, tree expr, tsubst_flags_t complain,
if (!INDIRECT_TYPE_P (dst_type) && !TYPE_PTRDATAMEM_P (dst_type))
{
if (complain & tf_error)
- error ("invalid use of const_cast with type %qT, "
+ error ("invalid use of %<const_cast%> with type %qT, "
"which is not a pointer, "
"reference, nor a pointer-to-data-member type", dst_type);
return error_mark_node;
@@ -7755,8 +7750,9 @@ build_const_cast_1 (tree dst_type, tree expr, tsubst_flags_t complain,
if (TREE_CODE (TREE_TYPE (dst_type)) == FUNCTION_TYPE)
{
if (complain & tf_error)
- error ("invalid use of const_cast with type %qT, which is a pointer "
- "or reference to a function type", dst_type);
+ error ("invalid use of %<const_cast%> with type %qT, "
+ "which is a pointer or reference to a function type",
+ dst_type);
return error_mark_node;
}
@@ -7796,7 +7792,8 @@ build_const_cast_1 (tree dst_type, tree expr, tsubst_flags_t complain,
else
{
if (complain & tf_error)
- error ("invalid const_cast of an rvalue of type %qT to type %qT",
+ error ("invalid %<const_cast%> of an rvalue of type %qT "
+ "to type %qT",
src_type, dst_type);
return error_mark_node;
}
@@ -7865,7 +7862,7 @@ build_const_cast_1 (tree dst_type, tree expr, tsubst_flags_t complain,
}
if (complain & tf_error)
- error ("invalid const_cast from type %qT to type %qT",
+ error ("invalid %<const_cast%> from type %qT to type %qT",
src_type, dst_type);
return error_mark_node;
}
@@ -7974,8 +7971,7 @@ cp_build_c_cast (tree type, tree expr, tsubst_flags_t complain)
}
}
- if (TREE_CODE (type) == FUNCTION_TYPE
- || TREE_CODE (type) == METHOD_TYPE)
+ if (FUNC_OR_METHOD_TYPE_P (type))
{
if (complain & tf_error)
error ("invalid cast to function type %qT", type);
@@ -8228,11 +8224,10 @@ cp_build_modify_expr (location_t loc, tree lhs, enum tree_code modifycode,
/* Do the default thing. */;
else
{
- vec<tree, va_gc> *rhs_vec = make_tree_vector_single (rhs);
+ releasing_vec rhs_vec = make_tree_vector_single (rhs);
result = build_special_member_call (lhs, complete_ctor_identifier,
&rhs_vec, lhstype, LOOKUP_NORMAL,
complain);
- release_tree_vector (rhs_vec);
if (result == NULL_TREE)
return error_mark_node;
goto ret;
@@ -8328,8 +8323,7 @@ cp_build_modify_expr (location_t loc, tree lhs, enum tree_code modifycode,
&& (TREE_READONLY (lhs) || CP_TYPE_CONST_P (lhstype)
/* Functions are not modifiable, even though they are
lvalues. */
- || TREE_CODE (TREE_TYPE (lhs)) == FUNCTION_TYPE
- || TREE_CODE (TREE_TYPE (lhs)) == METHOD_TYPE
+ || FUNC_OR_METHOD_TYPE_P (TREE_TYPE (lhs))
/* If it's an aggregate and any field is const, then it is
effectively const. */
|| (CLASS_TYPE_P (lhstype)
@@ -9194,8 +9188,6 @@ convert_for_initialization (tree exp, tree type, tree rhs, int flags,
if (exp == error_mark_node)
return error_mark_node;
- rhstype = non_reference (rhstype);
-
type = complete_type (type);
if (DIRECT_INIT_EXPR_P (type, rhs))
@@ -9271,7 +9263,7 @@ maybe_warn_about_returning_address_of_local (tree retval)
"returning reference to temporary");
else if (is_std_init_list (valtype))
warning_at (loc, OPT_Winit_list_lifetime,
- "returning temporary initializer_list does not extend "
+ "returning temporary %<initializer_list%> does not extend "
"the lifetime of the underlying array");
return true;
}
@@ -9309,14 +9301,15 @@ maybe_warn_about_returning_address_of_local (tree retval)
whats_returned);
else if (is_std_init_list (valtype))
w = warning_at (loc, OPT_Winit_list_lifetime,
- "returning local initializer_list variable %qD "
+ "returning local %<initializer_list%> variable %qD "
"does not extend the lifetime of the underlying array",
whats_returned);
- else if (TREE_CODE (whats_returned) == LABEL_DECL)
+ else if (POINTER_TYPE_P (valtype)
+ && TREE_CODE (whats_returned) == LABEL_DECL)
w = warning_at (loc, OPT_Wreturn_local_addr,
"address of label %qD returned",
whats_returned);
- else
+ else if (POINTER_TYPE_P (valtype))
w = warning_at (loc, OPT_Wreturn_local_addr,
"address of local variable %qD returned",
whats_returned);
@@ -9665,7 +9658,7 @@ check_return_expr (tree retval, bool *no_warning)
&& ! flag_check_new
&& retval && null_ptr_cst_p (retval))
warning (0, "%<operator new%> must not return NULL unless it is "
- "declared %<throw()%> (or -fcheck-new is in effect)");
+ "declared %<throw()%> (or %<-fcheck-new%> is in effect)");
/* Effective C++ rule 15. See also start_function. */
if (warn_ecpp
@@ -9852,7 +9845,7 @@ comp_ptr_ttypes_real (tree to, tree from, int constp)
/* Const and volatile mean something different for function types,
so the usual checks are not appropriate. */
- if (TREE_CODE (to) != FUNCTION_TYPE && TREE_CODE (to) != METHOD_TYPE)
+ if (!FUNC_OR_METHOD_TYPE_P (to))
{
if (!at_least_as_qualified_p (to, from))
return 0;
@@ -10028,8 +10021,7 @@ cp_type_quals (const_tree type)
cp_ref_qualifier
type_memfn_rqual (const_tree type)
{
- gcc_assert (TREE_CODE (type) == FUNCTION_TYPE
- || TREE_CODE (type) == METHOD_TYPE);
+ gcc_assert (FUNC_OR_METHOD_TYPE_P (type));
if (!FUNCTION_REF_QUALIFIED (type))
return REF_QUAL_NONE;
diff --git a/gcc/cp/typeck2.c b/gcc/cp/typeck2.c
index df002a1..e8627dd 100644
--- a/gcc/cp/typeck2.c
+++ b/gcc/cp/typeck2.c
@@ -360,7 +360,7 @@ abstract_virtuals_error_sfinae (tree decl, tree type, abstract_class_use use,
"be used in throw-expression", type);
break;
case ACU_CATCH:
- error ("cannot declare catch parameter to be of abstract "
+ error ("cannot declare %<catch%> parameter to be of abstract "
"class type %qT", type);
break;
default:
@@ -380,7 +380,7 @@ abstract_virtuals_error_sfinae (tree decl, tree type, abstract_class_use use,
FOR_EACH_VEC_ELT (*pure, ix, fn)
if (! DECL_CLONED_FUNCTION_P (fn)
|| DECL_COMPLETE_DESTRUCTOR_P (fn))
- inform (DECL_SOURCE_LOCATION (fn), "\t%#qD", fn);
+ inform (DECL_SOURCE_LOCATION (fn), " %#qD", fn);
/* Now truncate the vector. This leaves it non-null, so we know
there are pure virtuals, but empty so we don't list them out
@@ -603,7 +603,7 @@ cxx_incomplete_type_error (location_t loc, const_tree value, const_tree type)
static bool
split_nonconstant_init_1 (tree dest, tree init)
{
- unsigned HOST_WIDE_INT idx;
+ unsigned HOST_WIDE_INT idx, tidx = HOST_WIDE_INT_M1U;
tree field_index, value;
tree type = TREE_TYPE (dest);
tree inner_type = NULL;
@@ -657,23 +657,23 @@ split_nonconstant_init_1 (tree dest, tree init)
if (!split_nonconstant_init_1 (sub, value))
complete_p = false;
else
- CONSTRUCTOR_ELTS (init)->ordered_remove (idx--);
- num_split_elts++;
+ {
+ /* Mark element for removal. */
+ CONSTRUCTOR_ELT (init, idx)->index = NULL_TREE;
+ if (idx < tidx)
+ tidx = idx;
+ num_split_elts++;
+ }
}
else if (!initializer_constant_valid_p (value, inner_type))
{
tree code;
tree sub;
- /* FIXME: Ordered removal is O(1) so the whole function is
- worst-case quadratic. This could be fixed using an aside
- bitmap to record which elements must be removed and remove
- them all at the same time. Or by merging
- split_non_constant_init into process_init_constructor_array,
- that is separating constants from non-constants while building
- the vector. */
- CONSTRUCTOR_ELTS (init)->ordered_remove (idx);
- --idx;
+ /* Mark element for removal. */
+ CONSTRUCTOR_ELT (init, idx)->index = NULL_TREE;
+ if (idx < tidx)
+ tidx = idx;
if (TREE_CODE (field_index) == RANGE_EXPR)
{
@@ -711,6 +711,22 @@ split_nonconstant_init_1 (tree dest, tree init)
num_split_elts++;
}
}
+ if (num_split_elts == 1)
+ CONSTRUCTOR_ELTS (init)->ordered_remove (tidx);
+ else if (num_split_elts > 1)
+ {
+ /* Perform the delayed ordered removal of non-constant elements
+ we split out. */
+ for (idx = tidx; idx < CONSTRUCTOR_NELTS (init); ++idx)
+ if (CONSTRUCTOR_ELT (init, idx)->index == NULL_TREE)
+ ;
+ else
+ {
+ *CONSTRUCTOR_ELT (init, tidx) = *CONSTRUCTOR_ELT (init, idx);
+ ++tidx;
+ }
+ vec_safe_truncate (CONSTRUCTOR_ELTS (init), tidx);
+ }
break;
case VECTOR_TYPE:
@@ -1164,8 +1180,8 @@ digest_init_r (tree type, tree init, int nested, int flags,
be invalid. */
if (size < TREE_STRING_LENGTH (stripped_init))
{
- permerror (loc, "initializer-string for array "
- "of chars is too long");
+ permerror (loc, "initializer-string for %qT is too long",
+ type);
init = build_string (size,
TREE_STRING_POINTER (stripped_init));
@@ -1293,7 +1309,10 @@ digest_nsdmi_init (tree decl, tree init, tsubst_flags_t complain)
tree type = TREE_TYPE (decl);
int flags = LOOKUP_IMPLICIT;
if (DIRECT_LIST_INIT_P (init))
- flags = LOOKUP_NORMAL;
+ {
+ flags = LOOKUP_NORMAL;
+ complain |= tf_no_cleanup;
+ }
if (BRACE_ENCLOSED_INITIALIZER_P (init)
&& CP_AGGREGATE_TYPE_P (type))
init = reshape_init (type, init, complain);
@@ -2173,7 +2192,6 @@ build_functional_cast (tree exp, tree parms, tsubst_flags_t complain)
/* The type to which we are casting. */
tree type;
- vec<tree, va_gc> *parmvec;
if (error_operand_p (exp) || parms == error_mark_node)
return error_mark_node;
@@ -2216,7 +2234,7 @@ build_functional_cast (tree exp, tree parms, tsubst_flags_t complain)
if (type == error_mark_node)
{
if (complain & tf_error)
- error ("cannot deduce template arguments for %qT from ()",
+ error ("cannot deduce template arguments for %qT from %<()%>",
anode);
return error_mark_node;
}
@@ -2295,12 +2313,11 @@ build_functional_cast (tree exp, tree parms, tsubst_flags_t complain)
}
/* Call the constructor. */
- parmvec = make_tree_vector ();
+ releasing_vec parmvec;
for (; parms != NULL_TREE; parms = TREE_CHAIN (parms))
vec_safe_push (parmvec, TREE_VALUE (parms));
exp = build_special_member_call (NULL_TREE, complete_ctor_identifier,
&parmvec, type, LOOKUP_NORMAL, complain);
- release_tree_vector (parmvec);
if (exp == error_mark_node)
return error_mark_node;
diff --git a/gcc/cse.c b/gcc/cse.c
index 6c9cda1..35840a6d 100644
--- a/gcc/cse.c
+++ b/gcc/cse.c
@@ -6512,7 +6512,7 @@ cse_dump_path (struct cse_basic_block_data *data, int nsets, FILE *f)
fprintf (f, ";; Following path with %d sets: ", nsets);
for (path_entry = 0; path_entry < data->path_size; path_entry++)
fprintf (f, "%d ", (data->path[path_entry].bb)->index);
- fputc ('\n', dump_file);
+ fputc ('\n', f);
fflush (f);
}
diff --git a/gcc/cselib.c b/gcc/cselib.c
index 84c17c2..7b0545e 100644
--- a/gcc/cselib.c
+++ b/gcc/cselib.c
@@ -2518,13 +2518,12 @@ cselib_record_sets (rtx_insn *insn)
int n_sets = 0;
int i;
struct cselib_set sets[MAX_SETS];
- rtx body = PATTERN (insn);
rtx cond = 0;
int n_sets_before_autoinc;
int n_strict_low_parts = 0;
struct cselib_record_autoinc_data data;
- body = PATTERN (insn);
+ rtx body = PATTERN (insn);
if (GET_CODE (body) == COND_EXEC)
{
cond = COND_EXEC_TEST (body);
@@ -2858,9 +2857,14 @@ cselib_init (int record_what)
}
used_regs = XNEWVEC (unsigned int, cselib_nregs);
n_used_regs = 0;
- cselib_hash_table = new hash_table<cselib_hasher> (31);
+ /* FIXME: enable sanitization (PR87845) */
+ cselib_hash_table
+ = new hash_table<cselib_hasher> (31, /* ggc */ false,
+ /* sanitize_eq_and_hash */ false);
if (cselib_preserve_constants)
- cselib_preserved_hash_table = new hash_table<cselib_hasher> (31);
+ cselib_preserved_hash_table
+ = new hash_table<cselib_hasher> (31, /* ggc */ false,
+ /* sanitize_eq_and_hash */ false);
next_uid = 1;
}
diff --git a/gcc/d/ChangeLog b/gcc/d/ChangeLog
index d5b5367..51d1721 100644
--- a/gcc/d/ChangeLog
+++ b/gcc/d/ChangeLog
@@ -1,3 +1,50 @@
+2019-06-16 Iain Buclaw <ibuclaw@gdcproject.org>
+
+ PR d/90559
+ * d-target.cc (Target::_init): Reduce max static data size to INT_MAX.
+
+2019-06-16 Iain Buclaw <ibuclaw@gdcproject.org>
+
+ PR d/90651
+ * typeinfo.cc (object_module): New variable.
+ (make_frontend_typeinfo): Update signature. Set temporary on
+ generated TypeInfo classes.
+ (create_tinfo_types): Set object_module. Move generation of front-end
+ typeinfo into ...
+ (create_frontend_tinfo_types): ... New function.
+ (layout_typeinfo): Call create_frontend_tinfo_types.
+ (layout_classinfo): Likewise.
+ (layout_cpp_typeinfo): Likewise.
+ (create_typeinfo): Likewise.
+
+2019-06-11 Richard Biener <rguenthe@suse.de>
+
+ d/90778
+ * toir.cc (pop_label): Only queue labels in a vector.
+ (cmp_labels): Label decl comparator.
+ (pop_binding_level): Pop labels in DECL_UID order to avoid
+ debug info differences.
+
+2019-05-24 Nathan Sidwell <nathan@acm.org>
+
+ * types.cc (fixup_anonymous_offset): Use IDENTIFIER_ANON_P.
+ (layout_aggregate_members): Use make_anon_name.
+
+2019-05-16 Martin Sebor <msebor@redhat.com>
+
+ * d-builtins.cc (d_init_builtins): Quote keywords, operators,
+ and types in diagnostics.
+ * d-codegen.cc (get_array_length): Same. Replace can't with cannot.
+ * d-convert.cc (convert_expr): Same.
+ * d-frontend.cc (getTypeInfoType): Quote an option name in
+ a diagnostic.
+ * d-lang.cc (d_handle_option): Same.
+ (d_parse_file): Same.
+ * decl.cc: Remove a trailing period from a diagnostic.
+ * expr.cc: Use a directive for an apostrophe.
+ * toir.cc: Quote keywords, operators, and types in diagnostics.
+ * typeinfo.cc (build_typeinfo): Quote an option name in a diagnostic.
+
2019-04-25 Johannes Pfau <johannespfau@gmail.com>
* config-lang.in: Do not add target_libs if phobos is disabled.
diff --git a/gcc/d/d-builtins.cc b/gcc/d/d-builtins.cc
index 3dbdafb..3ebee72 100644
--- a/gcc/d/d-builtins.cc
+++ b/gcc/d/d-builtins.cc
@@ -1117,7 +1117,7 @@ d_init_builtins (void)
Type::tvalist = build_frontend_type (va_list_type_node);
if (!Type::tvalist)
{
- error ("cannot represent built-in va_list type in D");
+ error ("cannot represent built-in %<va_list%> type in D");
gcc_unreachable ();
}
diff --git a/gcc/d/d-codegen.cc b/gcc/d/d-codegen.cc
index 2abff92..1971064 100644
--- a/gcc/d/d-codegen.cc
+++ b/gcc/d/d-codegen.cc
@@ -316,7 +316,7 @@ get_array_length (tree exp, Type *type)
return d_array_length (exp);
default:
- error ("can't determine the length of a %qs", type->toChars ());
+ error ("cannot determine the length of a %qs", type->toChars ());
return error_mark_node;
}
}
diff --git a/gcc/d/d-convert.cc b/gcc/d/d-convert.cc
index e9aa457..b020eab 100644
--- a/gcc/d/d-convert.cc
+++ b/gcc/d/d-convert.cc
@@ -376,7 +376,7 @@ convert_expr (tree exp, Type *etype, Type *totype)
}
else
{
- error ("can't convert a delegate expression to %qs",
+ error ("cannot convert a delegate expression to %qs",
totype->toChars ());
return error_mark_node;
}
@@ -392,7 +392,7 @@ convert_expr (tree exp, Type *etype, Type *totype)
}
else
{
- error ("can't convert struct %qs to %qs",
+ error ("cannot convert struct %qs to %qs",
etype->toChars (), totype->toChars ());
return error_mark_node;
}
@@ -475,7 +475,7 @@ convert_expr (tree exp, Type *etype, Type *totype)
if ((dim * esize) % tsize != 0)
{
- error ("cannot cast %qs to %qs since sizes don't line up",
+ error ("cannot cast %qs to %qs since sizes do not line up",
etype->toChars (), totype->toChars ());
return error_mark_node;
}
diff --git a/gcc/d/d-frontend.cc b/gcc/d/d-frontend.cc
index ccd5f50..77b6f22 100644
--- a/gcc/d/d-frontend.cc
+++ b/gcc/d/d-frontend.cc
@@ -625,7 +625,7 @@ getTypeInfoType (Loc loc, Type *type, Scope *sc)
if (!warned)
{
error_at (make_location_t (loc),
- "%<object.TypeInfo%> cannot be used with -fno-rtti");
+ "%<object.TypeInfo%> cannot be used with %<-fno-rtti%>");
warned = 1;
}
}
diff --git a/gcc/d/d-lang.cc b/gcc/d/d-lang.cc
index 62a8ddd..f23f719 100644
--- a/gcc/d/d-lang.cc
+++ b/gcc/d/d-lang.cc
@@ -449,7 +449,7 @@ d_handle_option (size_t scode, const char *arg, HOST_WIDE_INT value,
break;
}
- error ("bad argument for -fdebug %qs", arg);
+ error ("bad argument for %<-fdebug%>: %qs", arg);
break;
case OPT_fdoc:
@@ -497,7 +497,7 @@ d_handle_option (size_t scode, const char *arg, HOST_WIDE_INT value,
case OPT_fmodule_file_:
global.params.modFileAliasStrings->push (arg);
if (!strchr (arg, '='))
- error ("bad argument for -fmodule-file %qs", arg);
+ error ("bad argument for %<-fmodule-file%>: %qs", arg);
break;
case OPT_fmoduleinfo:
@@ -588,7 +588,7 @@ d_handle_option (size_t scode, const char *arg, HOST_WIDE_INT value,
break;
}
- error ("bad argument for -fversion %qs", arg);
+ error ("bad argument for %<-fversion%>: %qs", arg);
break;
case OPT_H:
@@ -1011,7 +1011,7 @@ d_parse_file (void)
/* In this mode, the first file name is supposed to be a duplicate
of one of the input files. */
if (d_option.fonly && strcmp (d_option.fonly, main_input_filename) != 0)
- error ("-fonly= argument is different from first input file name");
+ error ("%<-fonly=%> argument is different from first input file name");
for (size_t i = 0; i < num_in_fnames; i++)
{
diff --git a/gcc/d/d-target.cc b/gcc/d/d-target.cc
index e0cfbaf..8d85534 100644
--- a/gcc/d/d-target.cc
+++ b/gcc/d/d-target.cc
@@ -140,8 +140,9 @@ Target::_init (void)
/* Size of run-time TypeInfo object. */
Target::classinfosize = 19 * Target::ptrsize;
- /* Allow data sizes up to half of the address space. */
- Target::maxStaticDataSize = tree_to_shwi (TYPE_MAX_VALUE (ptrdiff_type_node));
+ /* Much of the dmd front-end uses ints for sizes and offsets, and cannot
+ handle any larger data type without some pervasive rework. */
+ Target::maxStaticDataSize = tree_to_shwi (TYPE_MAX_VALUE (integer_type_node));
/* Define what type to use for size_t, ptrdiff_t. */
if (POINTER_SIZE == 64)
diff --git a/gcc/d/decl.cc b/gcc/d/decl.cc
index 4972364..bcce245 100644
--- a/gcc/d/decl.cc
+++ b/gcc/d/decl.cc
@@ -463,7 +463,7 @@ public:
fd2->toPrettyChars ());
inform (make_location_t (d->loc),
"use %<alias %s = %s.%s;%> to introduce base class "
- "overload set.", fd->toChars (),
+ "overload set", fd->toChars (),
fd->parent->toChars (), fd->toChars ());
}
else
diff --git a/gcc/d/dmd/MERGE b/gcc/d/dmd/MERGE
index b81cfc6..d208aea 100644
--- a/gcc/d/dmd/MERGE
+++ b/gcc/d/dmd/MERGE
@@ -1,4 +1,4 @@
-423758078f8fcd945815a5294806915a8a01d392
+792f0fdf249b21531dc91690024827f4f9ecbb97
The first line of this file holds the git revision number of the last
merge done from the dlang/dmd repository.
diff --git a/gcc/d/dmd/attrib.c b/gcc/d/dmd/attrib.c
index a668638..6cd715c 100644
--- a/gcc/d/dmd/attrib.c
+++ b/gcc/d/dmd/attrib.c
@@ -667,7 +667,8 @@ Dsymbol *AlignDeclaration::syntaxCopy(Dsymbol *s)
{
assert(!s);
return new AlignDeclaration(loc,
- ealign->syntaxCopy(), Dsymbol::arraySyntaxCopy(decl));
+ ealign ? ealign->syntaxCopy() : NULL,
+ Dsymbol::arraySyntaxCopy(decl));
}
Scope *AlignDeclaration::newScope(Scope *sc)
diff --git a/gcc/d/dmd/blockexit.c b/gcc/d/dmd/blockexit.c
index e9d3f10..c3b60b8 100644
--- a/gcc/d/dmd/blockexit.c
+++ b/gcc/d/dmd/blockexit.c
@@ -496,6 +496,8 @@ int blockExit(Statement *s, FuncDeclaration *func, bool mustNotThrow)
}
};
+ if (!s)
+ return BEfallthru;
BlockExit be(func, mustNotThrow);
s->accept(&be);
return be.result;
diff --git a/gcc/d/dmd/clone.c b/gcc/d/dmd/clone.c
index d9a9055..45b4e00 100644
--- a/gcc/d/dmd/clone.c
+++ b/gcc/d/dmd/clone.c
@@ -841,12 +841,7 @@ FuncDeclaration *buildPostBlit(StructDeclaration *sd, Scope *sc)
{
// __ArrayPostblit((cast(S*)this.v.ptr)[0 .. n])
- uinteger_t n = 1;
- while (tv->ty == Tsarray)
- {
- n *= ((TypeSArray *)tv)->dim->toUInteger();
- tv = tv->nextOf()->toBasetype();
- }
+ uinteger_t n = tv->numberOfElems(loc);
if (n == 0)
continue;
@@ -898,12 +893,7 @@ FuncDeclaration *buildPostBlit(StructDeclaration *sd, Scope *sc)
{
// __ArrayDtor((cast(S*)this.v.ptr)[0 .. n])
- uinteger_t n = 1;
- while (tv->ty == Tsarray)
- {
- n *= ((TypeSArray *)tv)->dim->toUInteger();
- tv = tv->nextOf()->toBasetype();
- }
+ uinteger_t n = tv->numberOfElems(loc);
//if (n == 0)
// continue;
@@ -1049,12 +1039,7 @@ FuncDeclaration *buildDtor(AggregateDeclaration *ad, Scope *sc)
{
// __ArrayDtor((cast(S*)this.v.ptr)[0 .. n])
- uinteger_t n = 1;
- while (tv->ty == Tsarray)
- {
- n *= ((TypeSArray *)tv)->dim->toUInteger();
- tv = tv->nextOf()->toBasetype();
- }
+ uinteger_t n = tv->numberOfElems(loc);
if (n == 0)
continue;
diff --git a/gcc/d/dmd/dclass.c b/gcc/d/dmd/dclass.c
index 572b3e2..bbe2f8a 100644
--- a/gcc/d/dmd/dclass.c
+++ b/gcc/d/dmd/dclass.c
@@ -481,7 +481,7 @@ void ClassDeclaration::semantic(Scope *sc)
baseClass = tc->sym;
b->sym = baseClass;
- if (tc->sym->_scope && tc->sym->baseok < BASEOKdone)
+ if (tc->sym->baseok < BASEOKdone)
resolveBase(this, sc, scx, tc->sym); // Try to resolve forward reference
if (tc->sym->baseok < BASEOKdone)
{
@@ -533,7 +533,7 @@ void ClassDeclaration::semantic(Scope *sc)
b->sym = tc->sym;
- if (tc->sym->_scope && tc->sym->baseok < BASEOKdone)
+ if (tc->sym->baseok < BASEOKdone)
resolveBase(this, sc, scx, tc->sym); // Try to resolve forward reference
if (tc->sym->baseok < BASEOKdone)
{
@@ -918,10 +918,10 @@ bool ClassDeclaration::isBaseOf(ClassDeclaration *cd, int *poffset)
{
/* cd->baseClass might not be set if cd is forward referenced.
*/
- if (!cd->baseClass && cd->_scope && !cd->isInterfaceDeclaration())
+ if (!cd->baseClass && cd->semanticRun < PASSsemanticdone && !cd->isInterfaceDeclaration())
{
cd->semantic(NULL);
- if (!cd->baseClass && cd->_scope)
+ if (!cd->baseClass && cd->semanticRun < PASSsemanticdone)
cd->error("base class is forward referenced by %s", toChars());
}
@@ -1574,7 +1574,7 @@ void InterfaceDeclaration::semantic(Scope *sc)
b->sym = tc->sym;
- if (tc->sym->_scope && tc->sym->baseok < BASEOKdone)
+ if (tc->sym->baseok < BASEOKdone)
resolveBase(this, sc, scx, tc->sym); // Try to resolve forward reference
if (tc->sym->baseok < BASEOKdone)
{
diff --git a/gcc/d/dmd/declaration.c b/gcc/d/dmd/declaration.c
index d0911e2..0018d95 100644
--- a/gcc/d/dmd/declaration.c
+++ b/gcc/d/dmd/declaration.c
@@ -830,6 +830,11 @@ VarDeclaration::VarDeclaration(Loc loc, Type *type, Identifier *id, Initializer
this->sequenceNumber = ++nextSequenceNumber;
}
+VarDeclaration *VarDeclaration::create(Loc loc, Type *type, Identifier *id, Initializer *init)
+{
+ return new VarDeclaration(loc, type, id, init);
+}
+
Dsymbol *VarDeclaration::syntaxCopy(Dsymbol *s)
{
//printf("VarDeclaration::syntaxCopy(%s)\n", toChars());
@@ -860,6 +865,11 @@ void VarDeclaration::semantic(Scope *sc)
_scope = NULL;
}
+ if (!sc)
+ return;
+
+ semanticRun = PASSsemantic;
+
/* Pick up storage classes from context, but except synchronized,
* override, abstract, and final.
*/
@@ -1033,6 +1043,7 @@ void VarDeclaration::semantic(Scope *sc)
else if (isAliasThisTuple(e))
{
VarDeclaration *v = copyToTemp(0, "__tup", e);
+ v->semantic(sc);
VarExp *ve = new VarExp(loc, v);
ve->type = e->type;
@@ -1434,7 +1445,7 @@ Lnomatch:
if (!e)
{
error("is not a static and cannot have static initializer");
- return;
+ e = new ErrorExp();
}
}
ei = new ExpInitializer(_init->loc, e);
diff --git a/gcc/d/dmd/declaration.h b/gcc/d/dmd/declaration.h
index 16da7ea..e3444a7 100644
--- a/gcc/d/dmd/declaration.h
+++ b/gcc/d/dmd/declaration.h
@@ -265,6 +265,7 @@ public:
IntRange *range; // if !NULL, the variable is known to be within the range
VarDeclaration(Loc loc, Type *t, Identifier *id, Initializer *init);
+ static VarDeclaration *create(Loc loc, Type *t, Identifier *id, Initializer *init);
Dsymbol *syntaxCopy(Dsymbol *);
void semantic(Scope *sc);
void setFieldOffset(AggregateDeclaration *ad, unsigned *poffset, bool isunion);
diff --git a/gcc/d/dmd/denum.c b/gcc/d/dmd/denum.c
index fbca54b..ff261bc 100644
--- a/gcc/d/dmd/denum.c
+++ b/gcc/d/dmd/denum.c
@@ -110,6 +110,9 @@ void EnumDeclaration::semantic(Scope *sc)
_scope = NULL;
}
+ if (!sc)
+ return;
+
parent = sc->parent;
type = type->semantic(loc, sc);
diff --git a/gcc/d/dmd/dimport.c b/gcc/d/dmd/dimport.c
index 3d899f0..5f7d7fd 100644
--- a/gcc/d/dmd/dimport.c
+++ b/gcc/d/dmd/dimport.c
@@ -197,12 +197,18 @@ void Import::importAll(Scope *sc)
void Import::semantic(Scope *sc)
{
//printf("Import::semantic('%s') %s\n", toPrettyChars(), id->toChars());
+ if (semanticRun > PASSinit)
+ return;
if (_scope)
{
sc = _scope;
_scope = NULL;
}
+ if (!sc)
+ return;
+
+ semanticRun = PASSsemantic;
// Load if not already done so
if (!mod)
@@ -291,6 +297,8 @@ void Import::semantic(Scope *sc)
sc = sc->pop();
}
+ semanticRun = PASSsemanticdone;
+
// object self-imports itself, so skip that (Bugzilla 7547)
// don't list pseudo modules __entrypoint.d, __main.d (Bugzilla 11117, 11164)
if (global.params.moduleDeps != NULL &&
diff --git a/gcc/d/dmd/dinterpret.c b/gcc/d/dmd/dinterpret.c
index acca4e8..a1658bb 100644
--- a/gcc/d/dmd/dinterpret.c
+++ b/gcc/d/dmd/dinterpret.c
@@ -2085,9 +2085,9 @@ public:
if (v->ident == Id::ctfe)
return new IntegerExp(loc, 1, Type::tbool);
- if (!v->originalType && v->_scope) // semantic() not yet run
+ if (!v->originalType && v->semanticRun < PASSsemanticdone) // semantic() not yet run
{
- v->semantic (v->_scope);
+ v->semantic(NULL);
if (v->type->ty == Terror)
return CTFEExp::cantexp;
}
@@ -6053,9 +6053,16 @@ public:
result = (*se->elements)[i];
if (!result)
{
- e->error("Internal Compiler Error: null field %s", v->toChars());
- result = CTFEExp::cantexp;
- return;
+ // https://issues.dlang.org/show_bug.cgi?id=19897
+ // Zero-length fields don't have an initializer.
+ if (v->type->size() == 0)
+ result = voidInitLiteral(e->type, v).copy();
+ else
+ {
+ e->error("Internal Compiler Error: null field %s", v->toChars());
+ result = CTFEExp::cantexp;
+ return;
+ }
}
if (result->op == TOKvoid)
{
diff --git a/gcc/d/dmd/dmodule.c b/gcc/d/dmd/dmodule.c
index 1f6fd9f..bf1c0c1 100644
--- a/gcc/d/dmd/dmodule.c
+++ b/gcc/d/dmd/dmodule.c
@@ -679,7 +679,8 @@ void Module::importAll(Scope *)
// If it isn't there, some compiler rewrites, like
// classinst == classinst -> .object.opEquals(classinst, classinst)
// would fail inside object.d.
- if (members->dim == 0 || ((*members)[0])->ident != Id::object)
+ if (members->dim == 0 || ((*members)[0])->ident != Id::object ||
+ (*members)[0]->isImport() == NULL)
{
Import *im = new Import(Loc(), NULL, Id::object, NULL, 0);
members->shift(im);
diff --git a/gcc/d/dmd/dstruct.c b/gcc/d/dmd/dstruct.c
index 1338e1f..22da0a3 100644
--- a/gcc/d/dmd/dstruct.c
+++ b/gcc/d/dmd/dstruct.c
@@ -116,7 +116,7 @@ void semanticTypeInfo(Scope *sc, Type *t)
// Bugzilla 15149, if the typeid operand type comes from a
// result of auto function, it may be yet speculative.
- unSpeculative(sc, sd);
+ // unSpeculative(sc, sd);
}
/* Step 2: If the TypeInfo generation requires sd.semantic3, run it later.
@@ -324,6 +324,7 @@ void AggregateDeclaration::semantic3(Scope *sc)
if (sd)
sd->semanticTypeInfoMembers();
+ semanticRun = PASSsemantic3done;
}
/***************************************
@@ -359,7 +360,7 @@ bool AggregateDeclaration::determineFields()
AggregateDeclaration *ad = ((SV *)param)->agg;
- if (v->_scope)
+ if (v->semanticRun < PASSsemanticdone)
v->semantic(NULL);
// Note: Aggregate fields or size could have determined during v->semantic.
if (ad->sizeok != SIZEOKnone)
diff --git a/gcc/d/dmd/dtemplate.c b/gcc/d/dmd/dtemplate.c
index 0173ee4..b5e3662 100644
--- a/gcc/d/dmd/dtemplate.c
+++ b/gcc/d/dmd/dtemplate.c
@@ -685,6 +685,7 @@ void TemplateDeclaration::semantic(Scope *sc)
/* BUG: should check:
* o no virtual functions or non-static data members of classes
*/
+ semanticRun = PASSsemanticdone;
}
const char *TemplateDeclaration::kind() const
@@ -2169,12 +2170,14 @@ void functionResolve(Match *m, Dsymbol *dstart, Loc loc, Scope *sc,
if (tiargs && tiargs->dim > 0)
return 0;
- if (fd->semanticRun == PASSinit && fd->_scope)
+ // constructors need a valid scope in order to detect semantic errors
+ if (!fd->isCtorDeclaration() &&
+ fd->semanticRun < PASSsemanticdone)
{
Ungag ungag = fd->ungagSpeculative();
- fd->semantic(fd->_scope);
+ fd->semantic(NULL);
}
- if (fd->semanticRun == PASSinit)
+ if (fd->semanticRun < PASSsemanticdone)
{
::error(loc, "forward reference to template %s", fd->toChars());
return 1;
diff --git a/gcc/d/dmd/expression.c b/gcc/d/dmd/expression.c
index af762eb..c674392 100644
--- a/gcc/d/dmd/expression.c
+++ b/gcc/d/dmd/expression.c
@@ -516,9 +516,9 @@ static bool checkPropertyCall(Expression *e)
tf = (TypeFunction *)ce->f->type;
/* If a forward reference to ce->f, try to resolve it
*/
- if (!tf->deco && ce->f->_scope)
+ if (!tf->deco && ce->f->semanticRun < PASSsemanticdone)
{
- ce->f->semantic(ce->f->_scope);
+ ce->f->semantic(NULL);
tf = (TypeFunction *)ce->f->type;
}
}
@@ -1125,6 +1125,8 @@ bool arrayExpressionToCommonType(Scope *sc, Expressions *exps, Type **pt)
Type *t0 = NULL;
Expression *e0 = NULL; // dead-store to prevent spurious warning
size_t j0 = ~0; // dead-store to prevent spurious warning
+ bool foundType = false;
+
for (size_t i = 0; i < exps->dim; i++)
{
Expression *e = (*exps)[i];
@@ -1140,6 +1142,7 @@ bool arrayExpressionToCommonType(Scope *sc, Expressions *exps, Type **pt)
}
if (e->op == TOKtype)
{
+ foundType = true; // do not break immediately, there might be more errors
e->checkValue(); // report an error "type T has no value"
t0 = Type::terror;
continue;
@@ -1158,7 +1161,7 @@ bool arrayExpressionToCommonType(Scope *sc, Expressions *exps, Type **pt)
e = doCopyOrMove(sc, e);
- if (t0 && !t0->equals(e->type))
+ if (!foundType && t0 && !t0->equals(e->type))
{
/* This applies ?: to merge the types. It's backwards;
* ?: should call this function to merge types.
diff --git a/gcc/d/dmd/expressionsem.c b/gcc/d/dmd/expressionsem.c
index 19b7ccb..c23e332 100644
--- a/gcc/d/dmd/expressionsem.c
+++ b/gcc/d/dmd/expressionsem.c
@@ -75,6 +75,7 @@ Expression *semantic(Expression *e, Scope *sc);
Expression *semanticY(DotIdExp *exp, Scope *sc, int flag);
Expression *semanticY(DotTemplateInstanceExp *exp, Scope *sc, int flag);
StringExp *semanticString(Scope *sc, Expression *exp, const char *s);
+Initializer *semantic(Initializer *init, Scope *sc, Type *t, NeedInterpret needInterpret);
/****************************************
* Preprocess arguments to function.
@@ -396,6 +397,7 @@ public:
// Create the magic __ctfe bool variable
VarDeclaration *vd = new VarDeclaration(exp->loc, Type::tbool, Id::ctfe, NULL);
vd->storage_class |= STCtemp;
+ vd->semanticRun = PASSsemanticdone;
Expression *e = new VarExp(exp->loc, vd);
e = semantic(e, sc);
result = e;
@@ -1226,6 +1228,23 @@ public:
exp->error("no constructor for %s", cd->toChars());
return setError();
}
+
+ // https://issues.dlang.org/show_bug.cgi?id=19941
+ // Run semantic on all field initializers to resolve any forward
+ // references. This is the same as done for structs in sd->fill().
+ for (ClassDeclaration *c = cd; c; c = c->baseClass)
+ {
+ for (size_t i = 0; i < c->fields.dim; i++)
+ {
+ VarDeclaration *v = c->fields[i];
+ if (v->inuse || v->_scope == NULL || v->_init == NULL ||
+ v->_init->isVoidInitializer())
+ continue;
+ v->inuse++;
+ v->_init = semantic(v->_init, v->_scope, v->type, INITinterpret);
+ v->inuse--;
+ }
+ }
}
}
else if (tb->ty == Tstruct)
@@ -1423,7 +1442,10 @@ public:
void visit(VarExp *e)
{
- if (FuncDeclaration *fd = e->var->isFuncDeclaration())
+ VarDeclaration *vd = e->var->isVarDeclaration();
+ FuncDeclaration *fd = e->var->isFuncDeclaration();
+
+ if (fd)
{
//printf("L%d fd = %s\n", __LINE__, f->toChars());
if (!fd->functionSemantic())
@@ -1434,7 +1456,14 @@ public:
e->type = e->var->type;
if (e->type && !e->type->deco)
+ {
+ Declaration *decl = e->var->isDeclaration();
+ if (decl)
+ decl->inuse++;
e->type = e->type->semantic(e->loc, sc);
+ if (decl)
+ decl->inuse--;
+ }
/* Fix for 1161 doesn't work because it causes protection
* problems when instantiating imported templates passing private
@@ -1442,7 +1471,7 @@ public:
*/
//checkAccess(e->loc, sc, NULL, e->var);
- if (VarDeclaration *vd = e->var->isVarDeclaration())
+ if (vd)
{
if (vd->checkNestedReference(sc, e->loc))
return setError();
@@ -1450,7 +1479,7 @@ public:
// the purity violation error is redundant.
//checkPurity(sc, vd);
}
- else if (FuncDeclaration *fd = e->var->isFuncDeclaration())
+ else if (fd)
{
// TODO: If fd isn't yet resolved its overload, the checkNestedReference
// call would cause incorrect validation.
@@ -1806,11 +1835,19 @@ public:
Expression *e;
if (ea && ta->toBasetype()->ty == Tclass)
{
- /* Get the dynamic type, which is .classinfo
- */
- ea = semantic(ea, sc);
- e = new TypeidExp(ea->loc, ea);
- e->type = Type::typeinfoclass->type;
+ if (!Type::typeinfoclass)
+ {
+ error(exp->loc, "`object.TypeInfo_Class` could not be found, but is implicitly used");
+ e = new ErrorExp();
+ }
+ else
+ {
+ /* Get the dynamic type, which is .classinfo
+ */
+ ea = semantic(ea, sc);
+ e = new TypeidExp(ea->loc, ea);
+ e->type = Type::typeinfoclass->type;
+ }
}
else if (ta->ty == Terror)
{
@@ -1936,8 +1973,8 @@ public:
ClassDeclaration *cd = ((TypeClass *)e->targ)->sym;
Parameters *args = new Parameters;
args->reserve(cd->baseclasses->dim);
- if (cd->_scope && !cd->symtab)
- cd->semantic(cd->_scope);
+ if (cd->semanticRun < PASSsemanticdone)
+ cd->semantic(NULL);
for (size_t i = 0; i < cd->baseclasses->dim; i++)
{
BaseClass *b = (*cd->baseclasses)[i];
@@ -2185,6 +2222,9 @@ public:
}
if (exp->e1->op == TOKslice || exp->e1->type->ty == Tarray || exp->e1->type->ty == Tsarray)
{
+ if (checkNonAssignmentArrayOp(exp->e1))
+ return setError();
+
if (exp->e1->op == TOKslice)
((SliceExp *)exp->e1)->arrayop = true;
@@ -5822,16 +5862,8 @@ public:
if (exp->op != TOKassign)
{
// If multidimensional static array, treat as one large array
- dinteger_t dim = ((TypeSArray *)t1)->dim->toInteger();
- Type *t = t1;
- while (1)
- {
- t = t->nextOf()->toBasetype();
- if (t->ty != Tsarray)
- break;
- dim *= ((TypeSArray *)t)->dim->toInteger();
- e1x->type = t->nextOf()->sarrayOf(dim);
- }
+ dinteger_t dim = t1->numberOfElems(exp->loc);
+ e1x->type = t1->baseElemOf()->sarrayOf(dim);
}
SliceExp *sle = new SliceExp(e1x->loc, e1x, NULL, NULL);
sle->arrayop = true;
@@ -6232,6 +6264,9 @@ public:
assert(exp->e1->type && exp->e2->type);
if (exp->e1->op == TOKslice || exp->e1->type->ty == Tarray || exp->e1->type->ty == Tsarray)
{
+ if (checkNonAssignmentArrayOp(exp->e1))
+ return setError();
+
// T[] ^^= ...
if (exp->e2->implicitConvTo(exp->e1->type->nextOf()))
{
diff --git a/gcc/d/dmd/func.c b/gcc/d/dmd/func.c
index 568decc..11e4b2f 100644
--- a/gcc/d/dmd/func.c
+++ b/gcc/d/dmd/func.c
@@ -471,6 +471,9 @@ void FuncDeclaration::semantic(Scope *sc)
_scope = NULL;
}
+ if (!sc || errors)
+ return;
+
parent = sc->parent;
Dsymbol *parent = toParent();
@@ -932,6 +935,7 @@ void FuncDeclaration::semantic(Scope *sc)
case -2:
// can't determine because of forward references
+ errors = true;
return;
default:
@@ -1049,6 +1053,7 @@ void FuncDeclaration::semantic(Scope *sc)
case -2:
// can't determine because of forward references
+ errors = true;
return;
default:
@@ -1520,6 +1525,18 @@ void FuncDeclaration::semantic3(Scope *sc)
{
if (f->linkage == LINKd)
{
+ // Variadic arguments depend on Typeinfo being defined
+ if (!global.params.useTypeInfo || !Type::dtypeinfo || !Type::typeinfotypelist)
+ {
+ if (!global.params.useTypeInfo)
+ error("D-style variadic functions cannot be used with -betterC");
+ else if (!Type::typeinfotypelist)
+ error("`object.TypeInfo_Tuple` could not be found, but is implicitly used in D-style variadic functions");
+ else
+ error("`object.TypeInfo` could not be found, but is implicitly used in D-style variadic functions");
+ fatal();
+ }
+
// Declare _arguments[]
v_arguments = new VarDeclaration(Loc(), Type::typeinfotypelist->type, Id::_arguments_typeinfo, NULL);
v_arguments->storage_class |= STCtemp | STCparameter;
diff --git a/gcc/d/dmd/intrange.c b/gcc/d/dmd/intrange.c
index 940385c..e0e2472 100644
--- a/gcc/d/dmd/intrange.c
+++ b/gcc/d/dmd/intrange.c
@@ -278,7 +278,7 @@ IntRange IntRange::fromType(Type *type)
IntRange IntRange::fromType(Type *type, bool isUnsigned)
{
- if (!type->isintegral())
+ if (!type->isintegral() || type->toBasetype()->ty == Tvector)
return widest();
uinteger_t mask = type->sizemask();
@@ -404,7 +404,7 @@ IntRange& IntRange::castDchar()
IntRange& IntRange::cast(Type *type)
{
- if (!type->isintegral())
+ if (!type->isintegral() || type->toBasetype()->ty == Tvector)
return *this;
else if (!type->isunsigned())
return castSigned(type->sizemask());
@@ -416,7 +416,7 @@ IntRange& IntRange::cast(Type *type)
IntRange& IntRange::castUnsigned(Type *type)
{
- if (!type->isintegral())
+ if (!type->isintegral() || type->toBasetype()->ty == Tvector)
return castUnsigned(UINT64_MAX);
else if (type->toBasetype()->ty == Tdchar)
return castDchar();
diff --git a/gcc/d/dmd/mtype.c b/gcc/d/dmd/mtype.c
index d0e7396..b76b5ba 100644
--- a/gcc/d/dmd/mtype.c
+++ b/gcc/d/dmd/mtype.c
@@ -2517,6 +2517,33 @@ void Type::checkComplexTransition(Loc loc)
}
}
+/*******************************************
+ * Compute number of elements for a (possibly multidimensional) static array,
+ * or 1 for other types.
+ * Params:
+ * loc = for error message
+ * Returns:
+ * number of elements, uint.max on overflow
+ */
+unsigned Type::numberOfElems(const Loc &loc)
+{
+ //printf("Type::numberOfElems()\n");
+ uinteger_t n = 1;
+ Type *tb = this;
+ while ((tb = tb->toBasetype())->ty == Tsarray)
+ {
+ bool overflow = false;
+ n = mulu(n, ((TypeSArray *)tb)->dim->toUInteger(), overflow);
+ if (overflow || n >= UINT32_MAX)
+ {
+ error(loc, "static array `%s` size overflowed to %llu", toChars(), (unsigned long long)n);
+ return UINT32_MAX;
+ }
+ tb = ((TypeSArray *)tb)->next;
+ }
+ return (unsigned)n;
+}
+
/****************************************
* Return the mask that an integral type will
* fit into.
@@ -3900,25 +3927,17 @@ Type *TypeSArray::syntaxCopy()
d_uns64 TypeSArray::size(Loc loc)
{
//printf("TypeSArray::size()\n");
- dinteger_t sz;
- if (!dim)
- return Type::size(loc);
- sz = dim->toInteger();
-
+ uinteger_t n = numberOfElems(loc);
+ uinteger_t elemsize = baseElemOf()->size();
+ bool overflow = false;
+ uinteger_t sz = mulu(n, elemsize, overflow);
+ if (overflow || sz >= UINT32_MAX)
{
- bool overflow = false;
-
- sz = mulu(next->size(), sz, overflow);
- if (overflow)
- goto Loverflow;
+ if (elemsize != SIZE_INVALID && n != UINT32_MAX)
+ error(loc, "static array `%s` size overflowed to %lld", toChars(), (long long)sz);
+ return SIZE_INVALID;
}
- if (sz > UINT32_MAX)
- goto Loverflow;
return sz;
-
-Loverflow:
- error(loc, "static array %s size overflowed to %lld", toChars(), (long long)sz);
- return SIZE_INVALID;
}
unsigned TypeSArray::alignsize()
@@ -4134,8 +4153,7 @@ Type *TypeSArray::semantic(Loc loc, Scope *sc)
* when the bottom of element type is opaque.
*/
}
- else if (tbn->isintegral() ||
- tbn->isfloating() ||
+ else if (tbn->isTypeBasic() ||
tbn->ty == Tpointer ||
tbn->ty == Tarray ||
tbn->ty == Tsarray ||
@@ -4468,6 +4486,8 @@ Expression *TypeDArray::dotExp(Scope *sc, Expression *e, Identifier *ident, int
}
if (e->op == TOKnull)
return new IntegerExp(e->loc, 0, Type::tsize_t);
+ if (checkNonAssignmentArrayOp(e))
+ return new ErrorExp();
e = new ArrayLengthExp(e->loc, e);
e->type = Type::tsize_t;
return e;
@@ -4652,7 +4672,7 @@ Type *TypeAArray::semantic(Loc loc, Scope *sc)
/* AA's need typeid(index).equals() and getHash(). Issue error if not correctly set up.
*/
StructDeclaration *sd = ((TypeStruct *)tbase)->sym;
- if (sd->_scope)
+ if (sd->semanticRun < PASSsemanticdone)
sd->semantic(NULL);
// duplicate a part of StructDeclaration::semanticTypeInfoMembers
@@ -4719,7 +4739,7 @@ Type *TypeAArray::semantic(Loc loc, Scope *sc)
else if (tbase->ty == Tclass && !((TypeClass *)tbase)->sym->isInterfaceDeclaration())
{
ClassDeclaration *cd = ((TypeClass *)tbase)->sym;
- if (cd->_scope)
+ if (cd->semanticRun < PASSsemanticdone)
cd->semantic(NULL);
if (!ClassDeclaration::object)
@@ -5316,7 +5336,7 @@ int Type::covariant(Type *t, StorageClass *pstc, bool fix17349)
// If t1n is forward referenced:
ClassDeclaration *cd = ((TypeClass *)t1n)->sym;
- if (cd->_scope)
+ if (cd->semanticRun < PASSsemanticdone && !cd->isBaseInfoComplete())
cd->semantic(NULL);
if (!cd->isBaseInfoComplete())
{
@@ -5428,6 +5448,13 @@ Type *TypeFunction::semantic(Loc loc, Scope *sc)
bool errors = false;
+ if (inuse > 500)
+ {
+ inuse = 0;
+ ::error(loc, "recursive type");
+ return Type::terror;
+ }
+
/* Copy in order to not mess up original.
* This can produce redundant copies if inferring return type,
* as semantic() will get called again on this.
@@ -5512,9 +5539,9 @@ Type *TypeFunction::semantic(Loc loc, Scope *sc)
for (size_t i = 0; i < dim; i++)
{
Parameter *fparam = Parameter::getNth(tf->parameters, i);
- tf->inuse++;
+ inuse++;
fparam->type = fparam->type->semantic(loc, argsc);
- if (tf->inuse == 1) tf->inuse--;
+ inuse--;
if (fparam->type->ty == Terror)
{
@@ -5756,13 +5783,6 @@ Type *TypeFunction::semantic(Loc loc, Scope *sc)
}
tf->iswild = wildparams;
- if (tf->inuse)
- {
- error(loc, "recursive type");
- tf->inuse = 0;
- errors = true;
- }
-
if (tf->isproperty && (tf->varargs || Parameter::dim(tf->parameters) > 2))
{
error(loc, "properties can only have zero, one, or two parameter");
@@ -6734,6 +6754,10 @@ void TypeQualified::resolveHelper(Loc loc, Scope *sc,
goto L3;
if (VarDeclaration *v = s->isVarDeclaration())
{
+ // https://issues.dlang.org/show_bug.cgi?id=19913
+ // v->type would be null if it is a forward referenced member.
+ if (v->type == NULL)
+ v->semantic(sc);
if (v->storage_class & (STCconst | STCimmutable | STCmanifest) ||
v->type->isConst() || v->type->isImmutable())
{
@@ -7420,8 +7444,8 @@ Expression *TypeEnum::dotExp(Scope *sc, Expression *e, Identifier *ident, int fl
if (ident == Id::_mangleof)
return getProperty(e->loc, ident, flag & 1);
- if (sym->_scope)
- sym->semantic(sym->_scope);
+ if (sym->semanticRun < PASSsemanticdone)
+ sym->semantic(NULL);
if (!sym->members)
{
if (sym->isSpecial())
@@ -7890,8 +7914,8 @@ L1:
return e;
}
}
- if (d->semanticRun == PASSinit && d->_scope)
- d->semantic(d->_scope);
+ if (d->semanticRun == PASSinit)
+ d->semantic(NULL);
checkAccess(e->loc, sc, e, d);
VarExp *ve = new VarExp(e->loc, d);
if (d->isVarDeclaration() && d->needThis())
@@ -8344,7 +8368,12 @@ L1:
if (ident == Id::classinfo)
{
- assert(Type::typeinfoclass);
+ if (!Type::typeinfoclass)
+ {
+ error(e->loc, "`object.TypeInfo_Class` could not be found, but is implicitly used");
+ return new ErrorExp();
+ }
+
Type *t = Type::typeinfoclass->type;
if (e->op == TOKtype || e->op == TOKdottype)
{
@@ -8414,7 +8443,7 @@ L1:
if (ident == Id::outer && sym->vthis)
{
- if (sym->vthis->_scope)
+ if (sym->vthis->semanticRun == PASSinit)
sym->vthis->semantic(NULL);
if (ClassDeclaration *cdp = sym->toParent2()->isClassDeclaration())
@@ -8641,8 +8670,8 @@ L1:
}
}
//printf("e = %s, d = %s\n", e->toChars(), d->toChars());
- if (d->semanticRun == PASSinit && d->_scope)
- d->semantic(d->_scope);
+ if (d->semanticRun == PASSinit)
+ d->semantic(NULL);
checkAccess(e->loc, sc, e, d);
VarExp *ve = new VarExp(e->loc, d);
if (d->isVarDeclaration() && d->needThis())
@@ -8698,9 +8727,9 @@ MATCH TypeClass::implicitConvTo(Type *to)
if (cdto)
{
//printf("TypeClass::implicitConvTo(to = '%s') %s, isbase = %d %d\n", to->toChars(), toChars(), cdto->isBaseInfoComplete(), sym->isBaseInfoComplete());
- if (cdto->_scope && !cdto->isBaseInfoComplete())
+ if (cdto->semanticRun < PASSsemanticdone && !cdto->isBaseInfoComplete())
cdto->semantic(NULL);
- if (sym->_scope && !sym->isBaseInfoComplete())
+ if (sym->semanticRun < PASSsemanticdone && !sym->isBaseInfoComplete())
sym->semantic(NULL);
if (cdto->isBaseOf(sym, NULL) && MODimplicitConv(mod, to->mod))
{
diff --git a/gcc/d/dmd/mtype.h b/gcc/d/dmd/mtype.h
index f1e357a..aab0d03 100644
--- a/gcc/d/dmd/mtype.h
+++ b/gcc/d/dmd/mtype.h
@@ -332,6 +332,7 @@ public:
virtual Type *nextOf();
Type *baseElemOf();
uinteger_t sizemask();
+ unsigned numberOfElems(const Loc &loc);
virtual bool needsDestruction();
virtual bool needsNested();
void checkComplexTransition(Loc loc);
diff --git a/gcc/d/dmd/optimize.c b/gcc/d/dmd/optimize.c
index b382d0a..2e702ba 100644
--- a/gcc/d/dmd/optimize.c
+++ b/gcc/d/dmd/optimize.c
@@ -34,8 +34,8 @@ Expression *expandVar(int result, VarDeclaration *v)
Expression *e = NULL;
if (!v)
return e;
- if (!v->originalType && v->_scope) // semantic() not yet run
- v->semantic (v->_scope);
+ if (!v->originalType && v->semanticRun < PASSsemanticdone) // semantic() not yet run
+ v->semantic(NULL);
if (v->isConst() || v->isImmutable() || v->storage_class & STCmanifest)
{
diff --git a/gcc/d/dmd/statement.c b/gcc/d/dmd/statement.c
index 2d3a112..450b3f4 100644
--- a/gcc/d/dmd/statement.c
+++ b/gcc/d/dmd/statement.c
@@ -1312,7 +1312,7 @@ Statement *OnScopeStatement::syntaxCopy()
return new OnScopeStatement(loc, tok, statement->syntaxCopy());
}
-Statement *OnScopeStatement::scopeCode(Scope *, Statement **sentry, Statement **sexception, Statement **sfinally)
+Statement *OnScopeStatement::scopeCode(Scope *sc, Statement **sentry, Statement **sexception, Statement **sfinally)
{
//printf("OnScopeStatement::scopeCode()\n");
//print();
@@ -1340,6 +1340,7 @@ Statement *OnScopeStatement::scopeCode(Scope *, Statement **sentry, Statement **
* sfinally: if (!x) statement;
*/
VarDeclaration *v = copyToTemp(0, "__os", new IntegerExp(Loc(), 0, Type::tbool));
+ v->semantic(sc);
*sentry = new ExpStatement(loc, v);
Expression *e = new IntegerExp(Loc(), 1, Type::tbool);
diff --git a/gcc/d/dmd/statementsem.c b/gcc/d/dmd/statementsem.c
index 64cc42d..cc2b63e 100644
--- a/gcc/d/dmd/statementsem.c
+++ b/gcc/d/dmd/statementsem.c
@@ -95,6 +95,8 @@ public:
s->exp = semantic(s->exp, sc);
s->exp = resolveProperties(sc, s->exp);
s->exp = s->exp->addDtorHook(sc);
+ if (checkNonAssignmentArrayOp(s->exp))
+ s->exp = new ErrorExp();
if (FuncDeclaration *f = isFuncAddress(s->exp))
{
if (f->checkForwardRef(s->exp->loc))
@@ -370,6 +372,8 @@ public:
ds->condition = semantic(ds->condition, sc);
ds->condition = resolveProperties(sc, ds->condition);
+ if (checkNonAssignmentArrayOp(ds->condition))
+ ds->condition = new ErrorExp();
ds->condition = ds->condition->optimize(WANTvalue);
ds->condition = checkGC(sc, ds->condition);
@@ -440,6 +444,8 @@ public:
fs->condition = semantic(fs->condition, sc);
fs->condition = resolveProperties(sc, fs->condition);
+ if (checkNonAssignmentArrayOp(fs->condition))
+ fs->condition = new ErrorExp();
fs->condition = fs->condition->optimize(WANTvalue);
fs->condition = checkGC(sc, fs->condition);
fs->condition = fs->condition->toBoolean(sc);
@@ -450,6 +456,8 @@ public:
((CommaExp *)fs->increment)->allowCommaExp = true;
fs->increment = semantic(fs->increment, sc);
fs->increment = resolveProperties(sc, fs->increment);
+ if (checkNonAssignmentArrayOp(fs->increment))
+ fs->increment = new ErrorExp();
fs->increment = fs->increment->optimize(WANTvalue);
fs->increment = checkGC(sc, fs->increment);
}
@@ -765,16 +773,48 @@ public:
goto Lerror2;
}
+ // Finish semantic on all foreach parameter types.
+ for (size_t i = 0; i < dim; i++)
+ {
+ Parameter *p = (*fs->parameters)[i];
+ p->type = p->type->semantic(loc, sc2);
+ p->type = p->type->addStorageClass(p->storageClass);
+ }
+
+ tn = tab->nextOf()->toBasetype();
+
+ if (dim == 2)
+ {
+ Type *tindex = (*fs->parameters)[0]->type;
+ if (!tindex->isintegral())
+ {
+ fs->error("foreach: key cannot be of non-integral type `%s`",
+ tindex->toChars());
+ goto Lerror2;
+ }
+ /* What cases to deprecate implicit conversions for:
+ * 1. foreach aggregate is a dynamic array
+ * 2. foreach body is lowered to _aApply (see special case below).
+ */
+ Type *tv = (*fs->parameters)[1]->type->toBasetype();
+ if ((tab->ty == Tarray ||
+ (tn->ty != tv->ty &&
+ (tn->ty == Tchar || tn->ty == Twchar || tn->ty == Tdchar) &&
+ (tv->ty == Tchar || tv->ty == Twchar || tv->ty == Tdchar))) &&
+ !Type::tsize_t->implicitConvTo(tindex))
+ {
+ fs->deprecation("foreach: loop index implicitly converted from `size_t` to `%s`",
+ tindex->toChars());
+ }
+ }
+
/* Look for special case of parsing char types out of char type
* array.
*/
- tn = tab->nextOf()->toBasetype();
if (tn->ty == Tchar || tn->ty == Twchar || tn->ty == Tdchar)
{
int i = (dim == 1) ? 0 : 1; // index of value
Parameter *p = (*fs->parameters)[i];
- p->type = p->type->semantic(loc, sc2);
- p->type = p->type->addStorageClass(p->storageClass);
tnv = p->type->toBasetype();
if (tnv->ty != tn->ty &&
(tnv->ty == Tchar || tnv->ty == Twchar || tnv->ty == Tdchar))
@@ -801,8 +841,6 @@ public:
{
// Declare parameterss
Parameter *p = (*fs->parameters)[i];
- p->type = p->type->semantic(loc, sc2);
- p->type = p->type->addStorageClass(p->storageClass);
VarDeclaration *var;
if (dim == 2 && i == 0)
@@ -900,6 +938,10 @@ public:
fs->key = new VarDeclaration(loc, Type::tsize_t, idkey, NULL);
fs->key->storage_class |= STCtemp;
}
+ else if (fs->key->type->ty != Tsize_t)
+ {
+ tmp_length = new CastExp(loc, tmp_length, fs->key->type);
+ }
if (fs->op == TOKforeach_reverse)
fs->key->_init = new ExpInitializer(loc, tmp_length);
else
@@ -1032,6 +1074,7 @@ public:
else
{
r = copyToTemp(0, "__r", fs->aggr);
+ r->semantic(sc);
init = new ExpStatement(loc, r);
if (vinit)
init = new CompoundStatement(loc, new ExpStatement(loc, vinit), init);
@@ -1064,6 +1107,7 @@ public:
else
{
VarDeclaration *vd = copyToTemp(STCref, "__front", einit);
+ vd->semantic(sc);
makeargs = new ExpStatement(loc, vd);
Type *tfront = NULL;
@@ -1723,6 +1767,8 @@ public:
ifs->condition = resolveProperties(sc, ifs->condition);
ifs->condition = ifs->condition->addDtorHook(sc);
}
+ if (checkNonAssignmentArrayOp(ifs->condition))
+ ifs->condition = new ErrorExp();
ifs->condition = checkGC(sc, ifs->condition);
// Convert to boolean after declaring prm so this works:
@@ -1971,6 +2017,8 @@ public:
break;
}
}
+ if (checkNonAssignmentArrayOp(ss->condition))
+ ss->condition = new ErrorExp();
ss->condition = ss->condition->optimize(WANTvalue);
ss->condition = checkGC(sc, ss->condition);
if (ss->condition->op == TOKerror)
@@ -1989,7 +2037,7 @@ public:
ss->_body = semantic(ss->_body, sc);
sc->noctor--;
- if (conditionError || ss->_body->isErrorStatement())
+ if (conditionError || (ss->_body && ss->_body->isErrorStatement()))
goto Lerror;
// Resolve any goto case's with exp
@@ -2065,7 +2113,7 @@ public:
{
ss->hasNoDefault = 1;
- if (!ss->isFinal && !ss->_body->isErrorStatement())
+ if (!ss->isFinal && (!ss->_body || !ss->_body->isErrorStatement()))
ss->error("switch statement without a default; use 'final switch' or add 'default: assert(0);' or add 'default: break;'");
// Generate runtime error if the default is hit
@@ -2940,6 +2988,7 @@ public:
* try { body } finally { _d_monitorexit(tmp); }
*/
VarDeclaration *tmp = copyToTemp(0, "__sync", ss->exp);
+ tmp->semantic(sc);
Statements *cs = new Statements();
cs->push(new ExpStatement(ss->loc, tmp));
@@ -3087,6 +3136,7 @@ public:
* }
*/
VarDeclaration *tmp = copyToTemp(0, "__withtmp", ws->exp);
+ tmp->semantic(sc);
ExpStatement *es = new ExpStatement(ws->loc, tmp);
ws->exp = new VarExp(ws->loc, tmp);
Statement *ss = new ScopeStatement(ws->loc, new CompoundStatement(ws->loc, es, ws), ws->endloc);
@@ -3480,12 +3530,18 @@ public:
}
s->semantic(sc);
- Module::addDeferredSemantic2(s); // Bugzilla 14666
- sc->insert(s);
-
- for (size_t j = 0; j < s->aliasdecls.dim; j++)
+ // https://issues.dlang.org/show_bug.cgi?id=19942
+ // If the module that's being imported doesn't exist, don't add it to the symbol table
+ // for the current scope.
+ if (s->mod != NULL)
{
- sc->insert(s->aliasdecls[j]);
+ Module::addDeferredSemantic2(s); // Bugzilla 14666
+ sc->insert(s);
+
+ for (size_t j = 0; j < s->aliasdecls.dim; j++)
+ {
+ sc->insert(s->aliasdecls[j]);
+ }
}
}
result = imps;
diff --git a/gcc/d/dmd/traits.c b/gcc/d/dmd/traits.c
index 1d5f3fc..2430383 100644
--- a/gcc/d/dmd/traits.c
+++ b/gcc/d/dmd/traits.c
@@ -671,8 +671,8 @@ Expression *semanticTraits(TraitsExp *e, Scope *sc)
e->error("argument %s has no protection", o->toChars());
return new ErrorExp();
}
- if (s->_scope)
- s->semantic(s->_scope);
+ if (s->semanticRun == PASSinit)
+ s->semantic(NULL);
const char *protName = protectionToChars(s->prot().kind); // TODO: How about package(names)
assert(protName);
@@ -1240,7 +1240,7 @@ Expression *semanticTraits(TraitsExp *e, Scope *sc)
ClassDeclaration *cd = sds->isClassDeclaration();
if (cd && e->ident == Id::allMembers)
{
- if (cd->_scope)
+ if (cd->semanticRun < PASSsemanticdone)
cd->semantic(NULL); // Bugzilla 13668: Try to resolve forward reference
struct PushBaseMembers
diff --git a/gcc/d/expr.cc b/gcc/d/expr.cc
index 6497619..826c32a 100644
--- a/gcc/d/expr.cc
+++ b/gcc/d/expr.cc
@@ -1522,7 +1522,7 @@ public:
}
else
{
- error ("don't know how to delete %qs", e->e1->toChars ());
+ error ("don%'t know how to delete %qs", e->e1->toChars ());
this->result_ = error_mark_node;
}
}
diff --git a/gcc/d/toir.cc b/gcc/d/toir.cc
index f1b2e09..4c4d639 100644
--- a/gcc/d/toir.cc
+++ b/gcc/d/toir.cc
@@ -65,10 +65,10 @@ pop_binding_label (Statement * const &, d_label_entry *ent, binding_level *bl)
}
/* At the end of a function, all labels declared within the function
- go out of scope. BLOCK is the top-level block for the function. */
+ go out of scope. Queue them in LABELS. */
bool
-pop_label (Statement * const &s, d_label_entry *ent, tree block)
+pop_label (Statement * const &, d_label_entry *ent, vec<tree> &labels)
{
if (!ent->bc_label)
{
@@ -77,13 +77,10 @@ pop_label (Statement * const &s, d_label_entry *ent, tree block)
if (DECL_NAME (ent->label))
{
gcc_assert (DECL_INITIAL (ent->label) != NULL_TREE);
- DECL_CHAIN (ent->label) = BLOCK_VARS (block);
- BLOCK_VARS (block) = ent->label;
+ labels.safe_push (ent->label);
}
}
- d_function_chain->labels->remove (s);
-
return true;
}
@@ -103,6 +100,14 @@ push_binding_level (level_kind kind)
current_binding_level = new_level;
}
+static int
+cmp_labels (const void *p1, const void *p2)
+{
+ const tree *l1 = (const tree *)p1;
+ const tree *l2 = (const tree *)p2;
+ return DECL_UID (*l1) - DECL_UID (*l2);
+}
+
tree
pop_binding_level (void)
{
@@ -125,7 +130,17 @@ pop_binding_level (void)
/* Pop all the labels declared in the function. */
if (d_function_chain->labels)
- d_function_chain->labels->traverse<tree, &pop_label> (block);
+ {
+ auto_vec<tree> labels;
+ d_function_chain->labels->traverse<vec<tree> &, &pop_label> (labels);
+ d_function_chain->labels->empty ();
+ labels.qsort (cmp_labels);
+ for (unsigned i = 0; i < labels.length (); ++i)
+ {
+ DECL_CHAIN (labels[i]) = BLOCK_VARS (block);
+ BLOCK_VARS (block) = labels[i];
+ }
+ }
}
else
{
@@ -367,9 +382,11 @@ public:
}
if (ent->in_try_scope)
- error_at (make_location_t (from->loc), "cannot goto into try block");
+ error_at (make_location_t (from->loc),
+ "cannot %<goto%> into %<try%> block");
else if (ent->in_catch_scope)
- error_at (make_location_t (from->loc), "cannot goto into catch block");
+ error_at (make_location_t (from->loc),
+ "cannot %<goto%> into %<catch%> block");
}
/* Check that a previously seen jump to a newly defined label is valid.
@@ -391,21 +408,21 @@ public:
{
location = make_location_t (fwdref->statement->loc);
if (b->kind == level_try)
- error_at (location, "cannot goto into try block");
+ error_at (location, "cannot %<goto%> into %<try%> block");
else
- error_at (location, "cannot goto into catch block");
+ error_at (location, "cannot %<goto%> into %<catch%> block");
}
else if (s->isCaseStatement ())
{
location = make_location_t (s->loc);
error_at (location, "case cannot be in different "
- "try block level from switch");
+ "%<try%> block level from %<switch%>");
}
else if (s->isDefaultStatement ())
{
location = make_location_t (s->loc);
error_at (location, "default cannot be in different "
- "try block level from switch");
+ "%<try%> block level from %<switch%>");
}
else
gcc_unreachable ();
@@ -1125,8 +1142,8 @@ public:
static int warned = 0;
if (!warned)
{
- error_at (make_location_t (s->loc), "exception handling disabled, "
- "use -fexceptions to enable");
+ error_at (make_location_t (s->loc), "exception handling disabled; "
+ "use %<-fexceptions%> to enable");
warned = 1;
}
}
diff --git a/gcc/d/typeinfo.cc b/gcc/d/typeinfo.cc
index bbd3961..25bdb42 100644
--- a/gcc/d/typeinfo.cc
+++ b/gcc/d/typeinfo.cc
@@ -185,28 +185,36 @@ make_internal_typeinfo (tinfo_kind tk, Identifier *ident, ...)
va_end (ap);
}
-/* Helper for create_tinfo_types. Creates a typeinfo class declaration
- incase one wasn't supplied by reading `object.d'. */
+/* Reference to the `object` module, where all TypeInfo is defined. */
+
+static Module *object_module;
+
+/* Helper for create_frontend_tinfo_types. Creates a typeinfo class
+ declaration incase one wasn't supplied by reading `object.d'. */
static void
-make_frontend_typeinfo (Module *mod, Identifier *ident,
- ClassDeclaration *base = NULL)
+make_frontend_typeinfo (Identifier *ident, ClassDeclaration *base = NULL)
{
if (!base)
base = Type::dtypeinfo;
+ gcc_assert (object_module);
+
/* Create object module in order to complete the semantic. */
- if (!mod->_scope)
- mod->importAll (NULL);
+ if (!object_module->_scope)
+ object_module->importAll (NULL);
/* Assignment of global typeinfo variables is managed by the ClassDeclaration
constructor, so only need to new the declaration here. */
- Loc loc = (mod->md) ? mod->md->loc : mod->loc;
+ Loc loc = (object_module->md) ? object_module->md->loc : object_module->loc;
ClassDeclaration *tinfo = ClassDeclaration::create (loc, ident, NULL, NULL,
true);
- tinfo->parent = mod;
- tinfo->semantic (mod->_scope);
+ tinfo->parent = object_module;
+ tinfo->semantic (object_module->_scope);
tinfo->baseClass = base;
+ /* This is a compiler generated class, and shouldn't be mistaken for being
+ the type declared in the runtime library. */
+ tinfo->storage_class |= STCtemp;
}
/* Make sure the required builtin types exist for generating the TypeInfo
@@ -227,69 +235,78 @@ create_tinfo_types (Module *mod)
ptr_type_node, d_uint_type, ptr_type_node,
array_type_node, ptr_type_node, ptr_type_node, NULL);
+ object_module = mod;
+}
+
+/* Same as create_tinfo_types, but builds all front-end TypeInfo variable
+ definitions. */
+
+static void
+create_frontend_tinfo_types (void)
+{
/* If there's no Object class defined, then neither can TypeInfo be. */
- if (ClassDeclaration::object == NULL)
+ if (object_module == NULL || ClassDeclaration::object == NULL)
return;
/* Create all frontend TypeInfo classes declarations. We rely on all
existing, even if only just as stubs. */
if (!Type::dtypeinfo)
- make_frontend_typeinfo (mod, Identifier::idPool ("TypeInfo"),
+ make_frontend_typeinfo (Identifier::idPool ("TypeInfo"),
ClassDeclaration::object);
if (!Type::typeinfoclass)
- make_frontend_typeinfo (mod, Identifier::idPool ("TypeInfo_Class"));
+ make_frontend_typeinfo (Identifier::idPool ("TypeInfo_Class"));
if (!Type::typeinfointerface)
- make_frontend_typeinfo (mod, Identifier::idPool ("TypeInfo_Interface"));
+ make_frontend_typeinfo (Identifier::idPool ("TypeInfo_Interface"));
if (!Type::typeinfostruct)
- make_frontend_typeinfo (mod, Identifier::idPool ("TypeInfo_Struct"));
+ make_frontend_typeinfo (Identifier::idPool ("TypeInfo_Struct"));
if (!Type::typeinfopointer)
- make_frontend_typeinfo (mod, Identifier::idPool ("TypeInfo_Pointer"));
+ make_frontend_typeinfo (Identifier::idPool ("TypeInfo_Pointer"));
if (!Type::typeinfoarray)
- make_frontend_typeinfo (mod, Identifier::idPool ("TypeInfo_Array"));
+ make_frontend_typeinfo (Identifier::idPool ("TypeInfo_Array"));
if (!Type::typeinfostaticarray)
- make_frontend_typeinfo (mod, Identifier::idPool ("TypeInfo_StaticArray"));
+ make_frontend_typeinfo (Identifier::idPool ("TypeInfo_StaticArray"));
if (!Type::typeinfoassociativearray)
- make_frontend_typeinfo (mod, Identifier::idPool ("TypeInfo_AssociativeArray"));
+ make_frontend_typeinfo (Identifier::idPool ("TypeInfo_AssociativeArray"));
if (!Type::typeinfoenum)
- make_frontend_typeinfo (mod, Identifier::idPool ("TypeInfo_Enum"));
+ make_frontend_typeinfo (Identifier::idPool ("TypeInfo_Enum"));
if (!Type::typeinfofunction)
- make_frontend_typeinfo (mod, Identifier::idPool ("TypeInfo_Function"));
+ make_frontend_typeinfo (Identifier::idPool ("TypeInfo_Function"));
if (!Type::typeinfodelegate)
- make_frontend_typeinfo (mod, Identifier::idPool ("TypeInfo_Delegate"));
+ make_frontend_typeinfo (Identifier::idPool ("TypeInfo_Delegate"));
if (!Type::typeinfotypelist)
- make_frontend_typeinfo (mod, Identifier::idPool ("TypeInfo_Tuple"));
+ make_frontend_typeinfo (Identifier::idPool ("TypeInfo_Tuple"));
if (!Type::typeinfoconst)
- make_frontend_typeinfo (mod, Identifier::idPool ("TypeInfo_Const"));
+ make_frontend_typeinfo (Identifier::idPool ("TypeInfo_Const"));
if (!Type::typeinfoinvariant)
- make_frontend_typeinfo (mod, Identifier::idPool ("TypeInfo_Invariant"),
+ make_frontend_typeinfo (Identifier::idPool ("TypeInfo_Invariant"),
Type::typeinfoconst);
if (!Type::typeinfoshared)
- make_frontend_typeinfo (mod, Identifier::idPool ("TypeInfo_Shared"),
+ make_frontend_typeinfo (Identifier::idPool ("TypeInfo_Shared"),
Type::typeinfoconst);
if (!Type::typeinfowild)
- make_frontend_typeinfo (mod, Identifier::idPool ("TypeInfo_Wild"),
+ make_frontend_typeinfo (Identifier::idPool ("TypeInfo_Wild"),
Type::typeinfoconst);
if (!Type::typeinfovector)
- make_frontend_typeinfo (mod, Identifier::idPool ("TypeInfo_Vector"));
+ make_frontend_typeinfo (Identifier::idPool ("TypeInfo_Vector"));
if (!ClassDeclaration::cpp_type_info_ptr)
- make_frontend_typeinfo (mod, Identifier::idPool ("__cpp_type_info_ptr"),
+ make_frontend_typeinfo (Identifier::idPool ("__cpp_type_info_ptr"),
ClassDeclaration::object);
}
@@ -1132,6 +1149,9 @@ public:
tree
layout_typeinfo (TypeInfoDeclaration *d)
{
+ if (!Type::dtypeinfo)
+ create_frontend_tinfo_types ();
+
tree type = TREE_TYPE (get_typeinfo_decl (d));
TypeInfoVisitor v = TypeInfoVisitor (type);
d->accept (&v);
@@ -1144,6 +1164,9 @@ layout_typeinfo (TypeInfoDeclaration *d)
tree
layout_classinfo (ClassDeclaration *cd)
{
+ if (!Type::dtypeinfo)
+ create_frontend_tinfo_types ();
+
TypeInfoClassDeclaration *d = TypeInfoClassDeclaration::create (cd->type);
tree type = TREE_TYPE (get_classinfo_decl (cd));
TypeInfoVisitor v = TypeInfoVisitor (type);
@@ -1350,7 +1373,7 @@ build_typeinfo (const Loc &loc, Type *type)
if (!warned)
{
error_at (make_location_t (loc),
- "%<object.TypeInfo%> cannot be used with -fno-rtti");
+ "%<object.TypeInfo%> cannot be used with %<-fno-rtti%>");
warned = 1;
}
}
@@ -1366,6 +1389,9 @@ build_typeinfo (const Loc &loc, Type *type)
void
layout_cpp_typeinfo (ClassDeclaration *cd)
{
+ if (!Type::dtypeinfo)
+ create_frontend_tinfo_types ();
+
gcc_assert (cd->isCPPclass ());
tree decl = get_cpp_typeinfo_decl (cd);
@@ -1434,6 +1460,9 @@ get_cpp_typeinfo_decl (ClassDeclaration *decl)
void
create_typeinfo (Type *type, Module *mod)
{
+ if (!Type::dtypeinfo)
+ create_frontend_tinfo_types ();
+
/* Do this since not all Type's are merged. */
Type *t = type->merge2 ();
Identifier *ident;
diff --git a/gcc/d/types.cc b/gcc/d/types.cc
index cdbfbb7..8f0aa37 100644
--- a/gcc/d/types.cc
+++ b/gcc/d/types.cc
@@ -239,7 +239,7 @@ fixup_anonymous_offset (tree fields, tree offset)
/* Traverse all nested anonymous aggregates to update their offset.
Set the anonymous decl offset to its first member. */
tree ftype = TREE_TYPE (fields);
- if (TYPE_NAME (ftype) && anon_aggrname_p (TYPE_IDENTIFIER (ftype)))
+ if (TYPE_NAME (ftype) && IDENTIFIER_ANON_P (TYPE_IDENTIFIER (ftype)))
{
tree vfields = TYPE_FIELDS (ftype);
fixup_anonymous_offset (vfields, offset);
@@ -324,12 +324,7 @@ layout_aggregate_members (Dsymbols *members, tree context, bool inherited_p)
AnonDeclaration *ad = sym->isAnonDeclaration ();
if (ad != NULL)
{
- /* Use a counter to create anonymous type names. */
- static int anon_cnt = 0;
- char buf[32];
- sprintf (buf, anon_aggrname_format (), anon_cnt++);
-
- tree ident = get_identifier (buf);
+ tree ident = make_anon_name ();
tree type = make_node (ad->isunion ? UNION_TYPE : RECORD_TYPE);
ANON_AGGR_TYPE_P (type) = 1;
d_keep (type);
diff --git a/gcc/dbgcnt.def b/gcc/dbgcnt.def
index dd874c5..230072f 100644
--- a/gcc/dbgcnt.def
+++ b/gcc/dbgcnt.def
@@ -195,3 +195,4 @@ DEBUG_COUNTER (tree_sra)
DEBUG_COUNTER (vect_loop)
DEBUG_COUNTER (vect_slp)
DEBUG_COUNTER (dom_unreachable_edges)
+DEBUG_COUNTER (match)
diff --git a/gcc/defaults.h b/gcc/defaults.h
index b753425..af7ea18 100644
--- a/gcc/defaults.h
+++ b/gcc/defaults.h
@@ -1318,10 +1318,10 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
#endif
/* If a memory-to-memory move would take MOVE_RATIO or more simple
- move-instruction sequences, we will do a movmem or libcall instead. */
+ move-instruction sequences, we will do a cpymem or libcall instead. */
#ifndef MOVE_RATIO
-#if defined (HAVE_movmemqi) || defined (HAVE_movmemhi) || defined (HAVE_movmemsi) || defined (HAVE_movmemdi) || defined (HAVE_movmemti)
+#if defined (HAVE_cpymemqi) || defined (HAVE_cpymemhi) || defined (HAVE_cpymemsi) || defined (HAVE_cpymemdi) || defined (HAVE_cpymemti)
#define MOVE_RATIO(speed) 2
#else
/* If we are optimizing for space (-Os), cut down the default move ratio. */
@@ -1342,7 +1342,7 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
#endif
/* If a memory set (to value other than zero) operation would take
- SET_RATIO or more simple move-instruction sequences, we will do a movmem
+ SET_RATIO or more simple move-instruction sequences, we will do a setmem
or libcall instead. */
#ifndef SET_RATIO
#define SET_RATIO(speed) MOVE_RATIO (speed)
diff --git a/gcc/df-scan.c b/gcc/df-scan.c
index 08d7af3..81e221e 100644
--- a/gcc/df-scan.c
+++ b/gcc/df-scan.c
@@ -229,7 +229,6 @@ void
df_scan_alloc (bitmap all_blocks ATTRIBUTE_UNUSED)
{
struct df_scan_problem_data *problem_data;
- unsigned int insn_num = get_max_uid () + 1;
basic_block bb;
/* Given the number of pools, this is really faster than tearing
@@ -257,7 +256,6 @@ df_scan_alloc (bitmap all_blocks ATTRIBUTE_UNUSED)
bitmap_obstack_initialize (&problem_data->reg_bitmaps);
bitmap_obstack_initialize (&problem_data->insn_bitmaps);
- insn_num += insn_num / 4;
df_grow_reg_info ();
df_grow_insn_info ();
@@ -3601,23 +3599,13 @@ df_update_entry_block_defs (void)
auto_bitmap refs (&df_bitmap_obstack);
df_get_entry_block_def_set (refs);
- if (df->entry_block_defs)
+ gcc_assert (df->entry_block_defs);
+ if (!bitmap_equal_p (df->entry_block_defs, refs))
{
- if (!bitmap_equal_p (df->entry_block_defs, refs))
- {
- struct df_scan_bb_info *bb_info = df_scan_get_bb_info (ENTRY_BLOCK);
- df_ref_chain_delete_du_chain (bb_info->artificial_defs);
- df_ref_chain_delete (bb_info->artificial_defs);
- bb_info->artificial_defs = NULL;
- changed = true;
- }
- }
- else
- {
- struct df_scan_problem_data *problem_data
- = (struct df_scan_problem_data *) df_scan->problem_data;
- gcc_unreachable ();
- df->entry_block_defs = BITMAP_ALLOC (&problem_data->reg_bitmaps);
+ struct df_scan_bb_info *bb_info = df_scan_get_bb_info (ENTRY_BLOCK);
+ df_ref_chain_delete_du_chain (bb_info->artificial_defs);
+ df_ref_chain_delete (bb_info->artificial_defs);
+ bb_info->artificial_defs = NULL;
changed = true;
}
@@ -3775,23 +3763,13 @@ df_update_exit_block_uses (void)
auto_bitmap refs (&df_bitmap_obstack);
df_get_exit_block_use_set (refs);
- if (df->exit_block_uses)
+ gcc_assert (df->exit_block_uses);
+ if (!bitmap_equal_p (df->exit_block_uses, refs))
{
- if (!bitmap_equal_p (df->exit_block_uses, refs))
- {
- struct df_scan_bb_info *bb_info = df_scan_get_bb_info (EXIT_BLOCK);
- df_ref_chain_delete_du_chain (bb_info->artificial_uses);
- df_ref_chain_delete (bb_info->artificial_uses);
- bb_info->artificial_uses = NULL;
- changed = true;
- }
- }
- else
- {
- struct df_scan_problem_data *problem_data
- = (struct df_scan_problem_data *) df_scan->problem_data;
- gcc_unreachable ();
- df->exit_block_uses = BITMAP_ALLOC (&problem_data->reg_bitmaps);
+ struct df_scan_bb_info *bb_info = df_scan_get_bb_info (EXIT_BLOCK);
+ df_ref_chain_delete_du_chain (bb_info->artificial_uses);
+ df_ref_chain_delete (bb_info->artificial_uses);
+ bb_info->artificial_uses = NULL;
changed = true;
}
diff --git a/gcc/diagnostic-format-json.cc b/gcc/diagnostic-format-json.cc
index 0355210..53c3b63 100644
--- a/gcc/diagnostic-format-json.cc
+++ b/gcc/diagnostic-format-json.cc
@@ -24,6 +24,7 @@ along with GCC; see the file COPYING3. If not see
#include "coretypes.h"
#include "diagnostic.h"
#include "json.h"
+#include "selftest.h"
/* The top-level JSON array of pending diagnostics. */
@@ -45,7 +46,8 @@ json_from_expanded_location (location_t loc)
{
expanded_location exploc = expand_location (loc);
json::object *result = new json::object ();
- result->set ("file", new json::string (exploc.file));
+ if (exploc.file)
+ result->set ("file", new json::string (exploc.file));
result->set ("line", new json::number (exploc.line));
result->set ("column", new json::number (exploc.column));
return result;
@@ -66,9 +68,11 @@ json_from_location_range (const location_range *loc_range, unsigned range_idx)
json::object *result = new json::object ();
result->set ("caret", json_from_expanded_location (caret_loc));
- if (start_loc != caret_loc)
+ if (start_loc != caret_loc
+ && start_loc != UNKNOWN_LOCATION)
result->set ("start", json_from_expanded_location (start_loc));
- if (finish_loc != caret_loc)
+ if (finish_loc != caret_loc
+ && finish_loc != UNKNOWN_LOCATION)
result->set ("finish", json_from_expanded_location (finish_loc));
if (loc_range->m_label)
@@ -262,3 +266,53 @@ diagnostic_output_format_init (diagnostic_context *context,
break;
}
}
+
+#if CHECKING_P
+
+namespace selftest {
+
+/* We shouldn't call json_from_expanded_location on UNKNOWN_LOCATION,
+ but verify that we handle this gracefully. */
+
+static void
+test_unknown_location ()
+{
+ delete json_from_expanded_location (UNKNOWN_LOCATION);
+}
+
+/* Verify that we gracefully handle attempts to serialize bad
+ compound locations. */
+
+static void
+test_bad_endpoints ()
+{
+ location_t bad_endpoints
+ = make_location (BUILTINS_LOCATION,
+ UNKNOWN_LOCATION, UNKNOWN_LOCATION);
+
+ location_range loc_range;
+ loc_range.m_loc = bad_endpoints;
+ loc_range.m_range_display_kind = SHOW_RANGE_WITH_CARET;
+ loc_range.m_label = NULL;
+
+ json::object *obj = json_from_location_range (&loc_range, 0);
+ /* We should have a "caret" value, but no "start" or "finish" values. */
+ ASSERT_TRUE (obj != NULL);
+ ASSERT_TRUE (obj->get ("caret") != NULL);
+ ASSERT_TRUE (obj->get ("start") == NULL);
+ ASSERT_TRUE (obj->get ("finish") == NULL);
+ delete obj;
+}
+
+/* Run all of the selftests within this file. */
+
+void
+diagnostic_format_json_cc_tests ()
+{
+ test_unknown_location ();
+ test_bad_endpoints ();
+}
+
+} // namespace selftest
+
+#endif /* #if CHECKING_P */
diff --git a/gcc/diagnostic-show-locus.c b/gcc/diagnostic-show-locus.c
index 205ee56..89074be 100644
--- a/gcc/diagnostic-show-locus.c
+++ b/gcc/diagnostic-show-locus.c
@@ -39,6 +39,13 @@ along with GCC; see the file COPYING3. If not see
# include <sys/ioctl.h>
#endif
+/* Disable warnings about quoting issues in the pp_xxx calls below
+ that (intentionally) don't follow GCC diagnostic conventions. */
+#if __GNUC__ >= 10
+# pragma GCC diagnostic push
+# pragma GCC diagnostic ignored "-Wformat-diag"
+#endif
+
/* Classes for rendering source code and diagnostics, within an
anonymous namespace.
The work is done by "class layout", which embeds and uses
@@ -3740,3 +3747,7 @@ diagnostic_show_locus_c_tests ()
} // namespace selftest
#endif /* #if CHECKING_P */
+
+#if __GNUC__ >= 10
+# pragma GCC diagnostic pop
+#endif
diff --git a/gcc/diagnostic.c b/gcc/diagnostic.c
index be6b657..4761b43 100644
--- a/gcc/diagnostic.c
+++ b/gcc/diagnostic.c
@@ -43,6 +43,13 @@ along with GCC; see the file COPYING3. If not see
# include <sys/ioctl.h>
#endif
+/* Disable warnings about quoting issues in the pp_xxx calls below
+ that (intentionally) don't follow GCC diagnostic conventions. */
+#if __GNUC__ >= 10
+# pragma GCC diagnostic push
+# pragma GCC diagnostic ignored "-Wformat-diag"
+#endif
+
#define pedantic_warning_kind(DC) \
((DC)->pedantic_errors ? DK_ERROR : DK_WARNING)
#define permissive_error_kind(DC) ((DC)->permissive ? DK_WARNING : DK_ERROR)
@@ -1861,3 +1868,7 @@ diagnostic_c_tests ()
} // namespace selftest
#endif /* #if CHECKING_P */
+
+#if __GNUC__ >= 10
+# pragma GCC diagnostic pop
+#endif
diff --git a/gcc/doc/cppopts.texi b/gcc/doc/cppopts.texi
index 48c574f..61e22cd 100644
--- a/gcc/doc/cppopts.texi
+++ b/gcc/doc/cppopts.texi
@@ -261,6 +261,10 @@ enabled by default for C99 (and later C standard versions) and C++.
@opindex fno-canonical-system-headers
When preprocessing, do not shorten system header paths with canonicalization.
+@item -fmax-include-depth=@var{depth}
+@opindex fmax-include-depth
+Set the maximum depth of the nested #include. The default is 200.
+
@item -ftabstop=@var{width}
@opindex ftabstop
Set the distance between tab stops. This helps the preprocessor report
diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi
index e8563fd..f2619e1 100644
--- a/gcc/doc/extend.texi
+++ b/gcc/doc/extend.texi
@@ -2749,7 +2749,8 @@ or variable) must match the kind of symbol to which the argument refers.
The @code{copy} attribute copies only syntactic and semantic attributes
but not attributes that affect a symbol's linkage or visibility such as
@code{alias}, @code{visibility}, or @code{weak}. The @code{deprecated}
-attribute is also not copied. @xref{Common Type Attributes}.
+and @code{target_clones} attribute are also not copied.
+@xref{Common Type Attributes}.
@xref{Common Variable Attributes}.
For example, the @var{StrongAlias} macro below makes use of the @code{alias}
@@ -3214,9 +3215,9 @@ marked symbols.
@item no_sanitize ("@var{sanitize_option}")
@cindex @code{no_sanitize} function attribute
The @code{no_sanitize} attribute on functions is used
-to inform the compiler that it should not do sanitization of all options
+to inform the compiler that it should not do sanitization of any option
mentioned in @var{sanitize_option}. A list of values acceptable by
-@option{-fsanitize} option can be provided.
+the @option{-fsanitize} option can be provided.
@smallexample
void __attribute__ ((no_sanitize ("alignment", "object-size")))
@@ -4139,7 +4140,8 @@ void f () __attribute__ ((interrupt ("ilink1")));
@end smallexample
Permissible values for this parameter are: @w{@code{ilink1}} and
-@w{@code{ilink2}}.
+@w{@code{ilink2}} for ARCv1 architecture, and @w{@code{ilink}} and
+@w{@code{firq}} for ARCv2 architecture.
@item long_call
@itemx medium_call
@@ -4182,6 +4184,17 @@ This attribute allows one to mark secure-code functions that are
callable from normal mode. The location of the secure call function
into the @code{sjli} table needs to be passed as argument.
+@item naked
+@cindex @code{naked} function attribute, ARC
+This attribute allows the compiler to construct the requisite function
+declaration, while allowing the body of the function to be assembly
+code. The specified function will not have prologue/epilogue
+sequences generated by the compiler. Only basic @code{asm} statements
+can safely be included in naked functions (@pxref{Basic Asm}). While
+using extended @code{asm} or a mixture of basic @code{asm} and C code
+may appear to work, they cannot be depended upon to work reliably and
+are not supported.
+
@end table
@node ARM Function Attributes
@@ -5431,13 +5444,6 @@ Generate code that uses (does not use) the move from condition
register field instruction implemented on the POWER4 processor and
other processors that support the PowerPC V2.01 architecture.
-@item mfpgpr
-@itemx no-mfpgpr
-@cindex @code{target("mfpgpr")} function attribute, PowerPC
-Generate code that uses (does not use) the FP move to/from general
-purpose register instructions implemented on the POWER6X processor and
-other processors that support the extended PowerPC V2.05 architecture.
-
@item mulhw
@itemx no-mulhw
@cindex @code{target("mulhw")} function attribute, PowerPC
@@ -10829,7 +10835,7 @@ evaluates to the empty string.
backward compatibility with old versions of GCC.
In C, @code{__PRETTY_FUNCTION__} is yet another name for
-@code{__func__}, except that at file (or, in C++, namespace scope),
+@code{__func__}, except that at file scope (or, in C++, namespace scope),
it evaluates to the string @code{"top level"}. In addition, in C++,
@code{__PRETTY_FUNCTION__} contains the signature of the function as
well as its bare name. For example, this program:
@@ -16878,8 +16884,8 @@ enabling the @option{-mpowerpc64}, @option{-mpowerpc-gpopt},
@option{-mpowerpc-gfxopt}, @option{-mmfcrf}, @option{-mpopcntb},
@option{-mfprnd}, @option{-mcmpb}, @option{-mhard-dfp}, and
@option{-mrecip-precision} options. Specify the
-@option{-maltivec} and @option{-mfpgpr} options explicitly in
-combination with the above options if they are desired.
+@option{-maltivec} option explicitly in
+combination with the above options if desired.
The following functions require option @option{-mcmpb}.
@smallexample
@@ -23045,6 +23051,7 @@ information.
* ARM Pragmas::
* M32C Pragmas::
* MeP Pragmas::
+* PRU Pragmas::
* RS/6000 and PowerPC Pragmas::
* S/390 Pragmas::
* Darwin Pragmas::
@@ -23196,6 +23203,26 @@ extern int foo ();
@end table
+@node PRU Pragmas
+@subsection PRU Pragmas
+
+@table @code
+
+@item ctable_entry @var{index} @var{constant_address}
+@cindex pragma, ctable_entry
+Specifies that the PRU CTABLE entry given by @var{index} has the value
+@var{constant_address}. This enables GCC to emit LBCO/SBCO instructions
+when the load/store address is known and can be addressed with some CTABLE
+entry. For example:
+
+@smallexample
+/* will compile to "sbco Rx, 2, 0x10, 4" */
+#pragma ctable_entry 2 0x4802a000
+*(unsigned int *)0x4802a010 = val;
+@end smallexample
+
+@end table
+
@node RS/6000 and PowerPC Pragmas
@subsection RS/6000 and PowerPC Pragmas
diff --git a/gcc/doc/generic.texi b/gcc/doc/generic.texi
index 15f6cfe..67f7ad5 100644
--- a/gcc/doc/generic.texi
+++ b/gcc/doc/generic.texi
@@ -43,7 +43,6 @@ seems inelegant.
* Functions:: Function bodies, linkage, and other aspects.
* Language-dependent trees:: Topics and trees specific to language front ends.
* C and C++ Trees:: Trees specific to C and C++.
-* Java Trees:: Trees specific to Java.
@end menu
@c ---------------------------------------------------------------------
@@ -3544,7 +3543,3 @@ In either case, the expression is void.
@end table
-
-
-@node Java Trees
-@section Java Trees
diff --git a/gcc/doc/install.texi b/gcc/doc/install.texi
index 911875f..852aa8f 100644
--- a/gcc/doc/install.texi
+++ b/gcc/doc/install.texi
@@ -2,7 +2,6 @@
@c @ifnothtml
@c %**start of header
@setfilename gccinstall.info
-@settitle Installing GCC
@setchapternewpage odd
@c %**end of header
@c @end ifnothtml
@@ -397,6 +396,12 @@ built together with GCC. Alternatively, the @option{--with-isl} configure
option should be used if isl is not installed in your default library
search path.
+@item zstd Library.
+
+Necessary to build GCC with zstd compression used for LTO bytecode.
+The library is searched in your default library patch search.
+Alternatively, the @option{--with-zstd} configure option should be used.
+
@end table
@heading Tools/packages necessary for modifying GCC
@@ -1285,6 +1290,11 @@ assumptions made by the configure test are incorrect.
Specify that the target does not support TLS.
This is an alias for @option{--enable-tls=no}.
+@item --disable-tm-clone-registry
+Disable TM clone registry in libgcc. It is enabled in libgcc by default.
+This option helps to reduce code size for embedded targets which do
+not use transactional memory.
+
@item --with-cpu=@var{cpu}
@itemx --with-cpu-32=@var{cpu}
@itemx --with-cpu-64=@var{cpu}
@@ -3270,7 +3280,7 @@ information have to.
@item
@uref{#alpha-x-x,,alpha*-*-*}
@item
-@uref{#amd64-x-solaris210,,amd64-*-solaris2.10}
+@uref{#amd64-x-solaris2,,amd64-*-solaris2*}
@item
@uref{#arm-x-eabi,,arm-*-eabi}
@item
@@ -3294,7 +3304,7 @@ information have to.
@item
@uref{#ix86-x-linux,,i?86-*-linux*}
@item
-@uref{#ix86-x-solaris210,,i?86-*-solaris2.10}
+@uref{#ix86-x-solaris2,,i?86-*-solaris2*}
@item
@uref{#ia64-x-linux,,ia64-*-linux}
@item
@@ -3370,8 +3380,6 @@ information have to.
@item
@uref{#sparc-sun-solaris2,,sparc-sun-solaris2*}
@item
-@uref{#sparc-sun-solaris210,,sparc-sun-solaris2.10}
-@item
@uref{#sparc-x-linux,,sparc-*-linux*}
@item
@uref{#sparc64-x-solaris2,,sparc64-*-solaris2*}
@@ -3392,7 +3400,7 @@ information have to.
@item
@uref{#x86-64-x-x,,x86_64-*-*, amd64-*-*}
@item
-@uref{#x86-64-x-solaris210,,x86_64-*-solaris2.1[0-9]*}
+@uref{#x86-64-x-solaris2,,x86_64-*-solaris2*}
@item
@uref{#xtensa-x-elf,,xtensa*-*-elf}
@item
@@ -3474,9 +3482,9 @@ shared libraries.
@html
<hr />
@end html
-@anchor{amd64-x-solaris210}
-@heading amd64-*-solaris2.1[0-9]*
-This is a synonym for @samp{x86_64-*-solaris2.1[0-9]*}.
+@anchor{amd64-x-solaris2}
+@heading amd64-*-solaris2*
+This is a synonym for @samp{x86_64-*-solaris2*}.
@html
<hr />
@@ -3911,32 +3919,29 @@ found on @uref{http://www.bitwizard.nl/sig11/,,www.bitwizard.nl}.
@html
<hr />
@end html
-@anchor{ix86-x-solaris210}
-@heading i?86-*-solaris2.10
-Use this for Solaris 10 or later on x86 and x86-64 systems. Starting
-with GCC 4.7, there is also a 64-bit @samp{amd64-*-solaris2.1[0-9]*} or
-@samp{x86_64-*-solaris2.1[0-9]*} configuration that corresponds to
+@anchor{ix86-x-solaris2}
+@heading i?86-*-solaris2*
+Use this for Solaris 11 or later on x86 and x86-64 systems. Starting
+with GCC 4.7, there is also a 64-bit @samp{amd64-*-solaris2*} or
+@samp{x86_64-*-solaris2*} configuration that corresponds to
@samp{sparcv9-sun-solaris2*}.
It is recommended that you configure GCC to use the GNU assembler. The
-versions included in Solaris 10, from GNU binutils 2.15 (in
-@file{/usr/sfw/bin/gas}), and Solaris 11, from GNU binutils 2.19 or
+versions included in Solaris 11, from GNU binutils 2.19 or
newer (also available as @file{/usr/bin/gas} and
@file{/usr/gnu/bin/as}), work fine. The current version, from GNU
-binutils 2.29, is known to work, but the version from GNU binutils 2.26
+binutils 2.32, is known to work, but the version from GNU binutils 2.26
must be avoided. Recent versions of the Solaris assembler in
@file{/usr/ccs/bin/as} work almost as well, though.
@c FIXME: as patch requirements?
For linking, the Solaris linker, is preferred. If you want to use the GNU
-linker instead, note that due to a packaging bug the version in Solaris
-10, from GNU binutils 2.15 (in @file{/usr/sfw/bin/gld}), cannot be used,
-while the version in Solaris 11, from GNU binutils 2.19 or newer (also
-in @file{/usr/gnu/bin/ld} and @file{/usr/bin/gld}), works, as does the
-latest version, from GNU binutils 2.29.
+linker instead, the version in Solaris 11, from GNU binutils 2.19 or
+newer (also in @file{/usr/gnu/bin/ld} and @file{/usr/bin/gld}), works,
+as does the latest version, from GNU binutils 2.32.
To use GNU @command{as}, configure with the options
-@option{--with-gnu-as --with-as=@//usr/@/sfw/@/bin/@/gas}. It may be necessary
+@option{--with-gnu-as --with-as=@//usr/@/gnu/@/bin/@/as}. It may be necessary
to configure with @option{--without-gnu-ld --with-ld=@//usr/@/ccs/@/bin/@/ld} to
guarantee use of Sun @command{ld}.
@c FIXME: why --without-gnu-ld --with-ld?
@@ -4512,16 +4517,11 @@ supported as cross-compilation target only.
@c alone is too unspecific and must be avoided.
@anchor{x-x-solaris2}
@heading *-*-solaris2*
-Support for Solaris 10 has been obsoleted in GCC 9, but can still be
-enabled by configuring with @option{--enable-obsolete}. Support will be
-removed in GCC 10. Support for Solaris 9 has been removed in GCC 5.
-Support for Solaris 8 has been removed in GCC 4.8. Support for Solaris
-7 has been removed in GCC 4.6.
-
-Sun does not ship a C compiler with Solaris 2 before Solaris 10, though
-you can download the Sun Studio compilers for free. In Solaris 10 and
-11, GCC 3.4.3 is available as @command{/usr/sfw/bin/gcc}. Solaris 11
-also provides GCC 4.5.2, 4.7.3, and 4.8.2 as
+Support for Solaris 10 has been removed in GCC 10. Support for Solaris
+9 has been removed in GCC 5. Support for Solaris 8 has been removed in
+GCC 4.8. Support for Solaris 7 has been removed in GCC 4.6.
+
+Solaris 11 provides GCC 4.5.2, 4.7.3, and 4.8.2 as
@command{/usr/gcc/4.5/bin/gcc} or similar. Alternatively,
you can install a pre-built GCC to bootstrap and install GCC. See the
@uref{binaries.html,,binaries page} for details.
@@ -4540,21 +4540,8 @@ and proceed as described in @uref{configure.html,,the configure instructions}.
In addition we strongly recommend specifying an absolute path to invoke
@command{@var{srcdir}/configure}.
-Solaris 10 comes with a number of optional OS packages. Some of these
-are needed to use GCC fully, namely @code{SUNWarc},
-@code{SUNWbtool}, @code{SUNWesu}, @code{SUNWhea}, @code{SUNWlibm},
-@code{SUNWsprot}, and @code{SUNWtoo}. If you did not install all
-optional packages when installing Solaris 10, you will need to verify that
-the packages that GCC needs are installed.
-To check whether an optional package is installed, use
-the @command{pkginfo} command. To add an optional package, use the
-@command{pkgadd} command. For further details, see the Solaris 10
-documentation.
-
-Starting with Solaris 11, the package management has changed, so you
-need to check for @code{system/header}, @code{system/linker}, and
-@code{developer/assembler} packages. Checking for and installing
-packages is done with the @command{pkg} command now.
+In Solaris 11, you need to check for @code{system/header},
+@code{system/linker}, and @code{developer/assembler} packages.
Trying to use the linker and other tools in
@file{/usr/ucb} to install GCC has been observed to cause trouble.
@@ -4567,20 +4554,18 @@ have @file{/usr/xpg4/bin} in your @env{PATH}, we recommend that you place
We recommend the use of the Solaris assembler or the GNU assembler, in
conjunction with the Solaris linker. The GNU @command{as}
-versions included in Solaris 10, from GNU binutils 2.15 (in
-@file{/usr/sfw/bin/gas}), and Solaris 11,
+versions included in Solaris 11,
from GNU binutils 2.19 or newer (also in @file{/usr/bin/gas} and
@file{/usr/gnu/bin/as}), are known to work.
-The current version, from GNU binutils 2.29,
+The current version, from GNU binutils 2.32,
is known to work as well. Note that your mileage may vary
if you use a combination of the GNU tools and the Solaris tools: while the
combination GNU @command{as} + Sun @command{ld} should reasonably work,
the reverse combination Sun @command{as} + GNU @command{ld} may fail to
build or cause memory corruption at runtime in some cases for C++ programs.
@c FIXME: still?
-GNU @command{ld} usually works as well, although the version included in
-Solaris 10 cannot be used due to several bugs. Again, the current
-version (2.29) is known to work, but generally lacks platform specific
+GNU @command{ld} usually works as well. Again, the current
+version (2.32) is known to work, but generally lacks platform specific
features, so better stay with Solaris @command{ld}. To use the LTO linker
plugin (@option{-fuse-linker-plugin}) with GNU @command{ld}, GNU
binutils @emph{must} be configured with @option{--enable-largefile}.
@@ -4591,13 +4576,6 @@ GNU binutils. @samp{libstdc++} symbol versioning will be disabled if no
appropriate version is found. Solaris @command{c++filt} from the Solaris
Studio compilers does @emph{not} work.
-Sun bug 4927647 sometimes causes random spurious testsuite failures
-related to missing diagnostic output. This bug doesn't affect GCC
-itself, rather it is a kernel bug triggered by the @command{expect}
-program which is used only by the GCC testsuite driver. When the bug
-causes the @command{expect} program to miss anticipated output, extra
-testsuite failures appear.
-
@html
<hr />
@end html
@@ -4644,22 +4622,6 @@ not that of GMP or MPFR or MPC). For example on a Solaris 9 system:
@html
<hr />
@end html
-@anchor{sparc-sun-solaris210}
-@heading sparc-sun-solaris2.10
-There is a bug in older versions of the Sun assembler which breaks
-thread-local storage (TLS). A typical error message is
-
-@smallexample
-ld: fatal: relocation error: R_SPARC_TLS_LE_HIX22: file /var/tmp//ccamPA1v.o:
- symbol <unknown>: bad symbol type SECT: symbol type must be TLS
-@end smallexample
-
-@noindent
-This bug is fixed in Sun patch 118683-03 or later.
-
-@html
-<hr />
-@end html
@anchor{sparc-x-linux}
@heading sparc-*-linux*
@@ -4772,8 +4734,8 @@ both 64-bit x86-64 and 32-bit x86 code (via the @option{-m32} switch).
@html
<hr />
@end html
-@anchor{x86-64-x-solaris210}
-@heading x86_64-*-solaris2.1[0-9]*
+@anchor{x86-64-x-solaris2}
+@heading x86_64-*-solaris2*
GCC also supports the x86-64 architecture implemented by the AMD64
processor (@samp{amd64-*-*} is an alias for @samp{x86_64-*-*}) on
Solaris 10 or later. Unlike other systems, without special options a
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index 8e4a8a8..73d16b5 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -209,8 +209,9 @@ in the following sections.
@xref{C++ Dialect Options,,Options Controlling C++ Dialect}.
@gccoptlist{-fabi-version=@var{n} -fno-access-control @gol
-faligned-new=@var{n} -fargs-in-order=@var{n} -fchar8_t -fcheck-new @gol
--fconstexpr-depth=@var{n} -fconstexpr-loop-limit=@var{n} @gol
--fconstexpr-ops-limit=@var{n} -fno-elide-constructors @gol
+-fconstexpr-depth=@var{n} -fconstexpr-cache-depth=@var{n} @gol
+-fconstexpr-loop-limit=@var{n} -fconstexpr-ops-limit=@var{n} @gol
+-fno-elide-constructors @gol
-fno-enforce-eh-specs @gol
-fno-gnu-keywords @gol
-fno-implicit-templates @gol
@@ -317,6 +318,7 @@ Objective-C and Objective-C++ Dialects}.
-Wignored-qualifiers -Wignored-attributes -Wincompatible-pointer-types @gol
-Wimplicit -Wimplicit-fallthrough -Wimplicit-fallthrough=@var{n} @gol
-Wimplicit-function-declaration -Wimplicit-int @gol
+-Winaccessible-base @gol
-Winit-self -Winline -Wno-int-conversion -Wint-in-bool-context @gol
-Wno-int-to-pointer-cast -Winvalid-memory-model -Wno-invalid-offsetof @gol
-Winvalid-pch -Wlarger-than=@var{byte-size} @gol
@@ -388,7 +390,7 @@ Objective-C and Objective-C++ Dialects}.
-fno-eliminate-unused-debug-types @gol
-femit-struct-debug-baseonly -femit-struct-debug-reduced @gol
-femit-struct-debug-detailed@r{[}=@var{spec-list}@r{]} @gol
--feliminate-unused-debug-symbols -femit-class-debug-always @gol
+-fno-eliminate-unused-debug-symbols -femit-class-debug-always @gol
-fno-merge-debug-strings -fno-dwarf2-cfi-asm @gol
-fvar-tracking -fvar-tracking-assignments}
@@ -412,6 +414,7 @@ Objective-C and Objective-C++ Dialects}.
-fdevirtualize-at-ltrans -fdse @gol
-fearly-inlining -fipa-sra -fexpensive-optimizations -ffat-lto-objects @gol
-ffast-math -ffinite-math-only -ffloat-store -fexcess-precision=@var{style} @gol
+-ffinite-loops @gol
-fforward-propagate -ffp-contract=@var{style} -ffunction-sections @gol
-fgcse -fgcse-after-reload -fgcse-las -fgcse-lm -fgraphite-identity @gol
-fgcse-sm -fhoist-adjacent-loads -fif-conversion @gol
@@ -490,8 +493,8 @@ Objective-C and Objective-C++ Dialects}.
@gccoptlist{-p -pg -fprofile-arcs --coverage -ftest-coverage @gol
-fprofile-abs-path @gol
-fprofile-dir=@var{path} -fprofile-generate -fprofile-generate=@var{path} @gol
--fprofile-update=@var{method} -fprofile-filter-files=@var{regex} @gol
--fprofile-exclude-files=@var{regex} @gol
+-fprofile-note=@var{path} -fprofile-update=@var{method} @gol
+-fprofile-filter-files=@var{regex} -fprofile-exclude-files=@var{regex} @gol
-fsanitize=@var{style} -fsanitize-recover -fsanitize-recover=@var{style} @gol
-fasan-shadow-offset=@var{number} -fsanitize-sections=@var{s1},@var{s2},... @gol
-fsanitize-undefined-trap-on-error -fbounds-check @gol
@@ -515,6 +518,7 @@ Objective-C and Objective-C++ Dialects}.
-fdebug-cpp -fdirectives-only -fdollars-in-identifiers @gol
-fexec-charset=@var{charset} -fextended-identifiers @gol
-finput-charset=@var{charset} -fmacro-prefix-map=@var{old}=@var{new} @gol
+-fmax-include-depth=@var{depth} @gol
-fno-canonical-system-headers -fpch-deps -fpch-preprocess @gol
-fpreprocessed -ftabstop=@var{width} -ftrack-macro-expansion @gol
-fwide-exec-charset=@var{charset} -fworking-directory @gol
@@ -632,7 +636,8 @@ Objective-C and Objective-C++ Dialects}.
-mlow-precision-recip-sqrt -mlow-precision-sqrt -mlow-precision-div @gol
-mpc-relative-literal-loads @gol
-msign-return-address=@var{scope} @gol
--mbranch-protection=@var{none}|@var{standard}|@var{pac-ret}[+@var{leaf}]|@var{bti} @gol
+-mbranch-protection=@var{none}|@var{standard}|@var{pac-ret}[+@var{leaf}
++@var{b-key}]|@var{bti} @gol
-march=@var{name} -mcpu=@var{name} -mtune=@var{name} @gol
-moverride=@var{string} -mverbose-cost-dump @gol
-mstack-protector-guard=@var{guard} -mstack-protector-guard-reg=@var{sysreg} @gol
@@ -1043,6 +1048,10 @@ Objective-C and Objective-C++ Dialects}.
@emph{PowerPC Options}
See RS/6000 and PowerPC Options.
+@emph{PRU Options}
+@gccoptlist{-mmcu=@var{mcu} -minrt -mno-relax -mloop @gol
+-mabi=@var{variant} @gol}
+
@emph{RISC-V Options}
@gccoptlist{-mbranch-cost=@var{N-instruction} @gol
-mplt -mno-plt @gol
@@ -1075,7 +1084,7 @@ See RS/6000 and PowerPC Options.
-mpowerpc-gfxopt -mno-powerpc-gfxopt @gol
-mmfcrf -mno-mfcrf -mpopcntb -mno-popcntb -mpopcntd -mno-popcntd @gol
-mfprnd -mno-fprnd @gol
--mcmpb -mno-cmpb -mmfpgpr -mno-mfpgpr -mhard-dfp -mno-hard-dfp @gol
+-mcmpb -mno-cmpb -mhard-dfp -mno-hard-dfp @gol
-mfull-toc -mminimal-toc -mno-fp-in-toc -mno-sum-in-toc @gol
-m64 -m32 -mxl-compat -mno-xl-compat -mpe @gol
-malign-power -malign-natural @gol
@@ -1121,7 +1130,7 @@ See RS/6000 and PowerPC Options.
-mfloat128 -mno-float128 -mfloat128-hardware -mno-float128-hardware @gol
-mgnu-attribute -mno-gnu-attribute @gol
-mstack-protector-guard=@var{guard} -mstack-protector-guard-reg=@var{reg} @gol
--mstack-protector-guard-offset=@var{offset}}
+-mstack-protector-guard-offset=@var{offset} -mpcrel -mno-pcrel}
@emph{RX Options}
@gccoptlist{-m64bit-doubles -m32bit-doubles -fpu -nofpu@gol
@@ -1274,10 +1283,10 @@ See RS/6000 and PowerPC Options.
-msse4a -m3dnow -m3dnowa -mpopcnt -mabm -mbmi -mtbm -mfma4 -mxop @gol
-madx -mlzcnt -mbmi2 -mfxsr -mxsave -mxsaveopt -mrtm -mhle -mlwp @gol
-mmwaitx -mclzero -mpku -mthreads -mgfni -mvaes -mwaitpkg @gol
--mshstk -mmanual-endbr -mforce-indirect-call -mavx512vbmi2 -mavx512bf16 @gol
+-mshstk -mmanual-endbr -mforce-indirect-call -mavx512vbmi2 -mavx512bf16 -menqcmd @gol
-mvpclmulqdq -mavx512bitalg -mmovdiri -mmovdir64b -mavx512vpopcntdq @gol
-mavx5124fmaps -mavx512vnni -mavx5124vnniw -mprfchw -mrdpid @gol
--mrdseed -msgx @gol
+-mrdseed -msgx -mavx512vp2intersect@gol
-mcldemote -mms-bitfields -mno-align-stringops -minline-all-stringops @gol
-minline-stringops-dynamically -mstringop-strategy=@var{alg} @gol
-mmemcpy-strategy=@var{strategy} -mmemset-strategy=@var{strategy} @gol
@@ -2237,7 +2246,7 @@ Some cases of unnamed fields in structures and unions are only
accepted with this option. @xref{Unnamed Fields,,Unnamed struct/union
fields within structs/unions}, for details.
-Note that this option is off for all targets but x86
+Note that this option is off for all targets except for x86
targets using ms-abi.
@item -fplan9-extensions
@@ -2520,6 +2529,17 @@ to @var{n}. A limit is needed to detect endless recursion during
constant expression evaluation. The minimum specified by the standard
is 512.
+@item -fconstexpr-cache-depth=@var{n}
+@opindex fconstexpr-cache-depth
+Set the maximum level of nested evaluation depth for C++11 constexpr
+functions that will be cached to @var{n}. This is a heuristic that
+trades off compilation speed (when the cache avoids repeated
+calculations) against memory consumption (when the cache grows very
+large from highly recursive evaluations). The default is 8. Very few
+users are likely to want to adjust it, but if your code does heavy
+constexpr calculations you might want to experiment to find which
+value works best for you.
+
@item -fconstexpr-loop-limit=@var{n}
@opindex fconstexpr-loop-limit
Set the maximum number of iterations for a loop in C++14 constexpr functions
@@ -4330,8 +4350,10 @@ without this option, certain GNU extensions and traditional C and C++
features are supported as well. With this option, they are rejected.
@option{-Wpedantic} does not cause warning messages for use of the
-alternate keywords whose names begin and end with @samp{__}. Pedantic
-warnings are also disabled in the expression that follows
+alternate keywords whose names begin and end with @samp{__}. This alternate
+format can also be used to disable warnings for non-ISO @samp{__intN} types,
+i.e. @samp{__intN__}.
+Pedantic warnings are also disabled in the expression that follows
@code{__extension__}. However, only system header files should use
these escape routes; application programs should avoid them.
@xref{Alternate Keywords}.
@@ -4799,6 +4821,22 @@ is only active when @option{-fdelete-null-pointer-checks} is active,
which is enabled by optimizations in most targets. The precision of
the warnings depends on the optimization options used.
+@item -Winaccessible-base @r{(C++, Objective-C++ only)}
+@opindex Winaccessible-base
+@opindex Wno-inaccessible-base
+Warn when a base class is inaccessible in a class derived from it due to
+ambiguity. The warning is enabled by default. Note the warning for virtual
+bases is enabled by the @option{-Wextra} option.
+@smallexample
+@group
+struct A @{ int a; @};
+
+struct B : A @{ @};
+
+struct C : B, A @{ @};
+@end group
+@end smallexample
+
@item -Winit-self @r{(C, C++, Objective-C and Objective-C++ only)}
@opindex Winit-self
@opindex Wno-init-self
@@ -5367,6 +5405,13 @@ switch ((int) (a == 4))
@end smallexample
This warning is enabled by default for C and C++ programs.
+@item -Wswitch-outside-range
+@opindex Wswitch-outside-range
+@opindex Wno-switch-outside-range
+Warn whenever a @code{switch} case has a value that is outside of its
+respective type range. This warning is enabled by default for
+C and C++ programs.
+
@item -Wswitch-unreachable
@opindex Wswitch-unreachable
@opindex Wno-switch-unreachable
@@ -5963,8 +6008,9 @@ Warn about types with virtual methods where code quality would be improved
if the type were declared with the C++11 @code{final} specifier,
or, if possible,
declared in an anonymous namespace. This allows GCC to more aggressively
-devirtualize the polymorphic calls. This warning is more effective with link
-time optimization, where the information about the class hierarchy graph is
+devirtualize the polymorphic calls. This warning is more effective with
+link-time optimization,
+where the information about the class hierarchy graph is
more complete.
@item -Wsuggest-final-methods
@@ -6114,8 +6160,8 @@ false positives and is deactivated by default.
@item -Wattribute-alias=@var{n}
@itemx -Wno-attribute-alias
-@opindex -Wattribute-alias
-@opindex -Wno-attribute-alias
+@opindex Wattribute-alias
+@opindex Wno-attribute-alias
Warn about declarations using the @code{alias} and similar attributes whose
target is incompatible with the type of the alias.
@xref{Function Attributes,,Declaring Attributes of Functions}.
@@ -7356,7 +7402,7 @@ Do not warn about compile-time overflow in constant expressions.
@opindex Wno-odr
@opindex Wodr
Warn about One Definition Rule violations during link-time optimization.
-Requires @option{-flto-odr-type-merging} to be enabled. Enabled by default.
+Enabled by default.
@item -Wopenmp-simd
@opindex Wopenmp-simd
@@ -7827,10 +7873,11 @@ confusion with @option{-gdwarf-@var{level}}.
Instead use an additional @option{-g@var{level}} option to change the
debug level for DWARF.
-@item -feliminate-unused-debug-symbols
+@item -fno-eliminate-unused-debug-symbols
@opindex feliminate-unused-debug-symbols
-Produce debugging information in stabs format (if that is supported),
-for only symbols that are actually used.
+@opindex fno-eliminate-unused-debug-symbols
+By default, no debug information is produced for symbols that are not actually
+used. Use this option if you want debug information for all symbols.
@item -femit-class-debug-always
@opindex femit-class-debug-always
@@ -8280,6 +8327,7 @@ also turns on the following optimization flags:
-fdelete-null-pointer-checks @gol
-fdevirtualize -fdevirtualize-speculatively @gol
-fexpensive-optimizations @gol
+-ffinite-loops @gol
-fgcse -fgcse-lm @gol
-fhoist-adjacent-loads @gol
-finline-small-functions @gol
@@ -9501,6 +9549,15 @@ that may set @code{errno} but are otherwise free of side effects. This flag is
enabled by default at @option{-O2} and higher if @option{-Os} is not also
specified.
+@item -ffinite-loops
+@opindex ffinite-loops
+@opindex fno-finite-loops
+Assume that a loop with an exit will eventually take the exit and not loop
+indefinitely. This allows the compiler to remove loops that otherwise have
+no side-effects, not considering eventual endless looping as such.
+
+This option is enabled by default at @option{-O2}.
+
@item -ftree-dominator-opts
@opindex ftree-dominator-opts
Perform a variety of simple scalar cleanups (constant/copy
@@ -9806,6 +9863,9 @@ This optimization is enabled by default.
With this option, the compiler creates multiple copies of some
local variables when unrolling a loop, which can result in superior code.
+This optimization is enabled by default for PowerPC targets, but disabled
+by default otherwise.
+
@item -fpartial-inlining
@opindex fpartial-inlining
Inline parts of functions. This option has any effect only
@@ -10351,12 +10411,6 @@ The value @samp{one} specifies that exactly one partition should be
used while the value @samp{none} bypasses partitioning and executes
the link-time optimization step directly from the WPA phase.
-@item -flto-odr-type-merging
-@opindex flto-odr-type-merging
-Enable streaming of mangled types names of C++ types and their unification
-at link time. This increases size of LTO object files, but enables
-diagnostics about One Definition Rule violations.
-
@item -flto-compression-level=@var{n}
@opindex flto-compression-level
This option specifies the level of compression used for intermediate
@@ -11889,6 +11943,16 @@ The smallest number of different values for which it is best to use a
jump-table instead of a tree of conditional branches. If the value is
0, use the default for the machine.
+@item jump-table-max-growth-ratio-for-size
+The maximum code size growth ratio when expanding
+into a jump table (in percent). The parameter is used when
+optimizing for size.
+
+@item jump-table-max-growth-ratio-for-speed
+The maximum code size growth ratio when expanding
+into a jump table (in percent). The parameter is used when
+optimizing for speed.
+
@item tree-reassoc-width
Set the maximum number of instructions executed in parallel in
reassociated tree. This parameter overrides target dependent
@@ -12128,9 +12192,6 @@ will not try to thread through its block.
Maximum number of nested calls to search for control dependencies
during uninitialized variable analysis.
-@item indir-call-topn-profile
-Track top N target addresses in indirect-call profile.
-
@item max-once-peeled-insns
The maximum number of insns of a peeled loop that rolls only once.
@@ -12343,6 +12404,11 @@ the profile feedback data files. See @option{-fprofile-dir}.
To optimize the program based on the collected profile information, use
@option{-fprofile-use}. @xref{Optimize Options}, for more information.
+@item -fprofile-note=@var{path}
+@opindex fprofile-note
+
+If @var{path} is specified, GCC saves gcno filename into @var{path} location.
+
@item -fprofile-update=@var{method}
@opindex fprofile-update
@@ -13131,45 +13197,49 @@ Options}.
@item -flinker-output=@var{type}
@opindex flinker-output
-This option controls the code generation of the link time optimizer. By
-default the linker output is determined by the linker plugin automatically. For
-debugging the compiler and in the case of incremental linking to non-lto object
-file is desired, it may be useful to control the type manually.
-
-If @var{type} is @samp{exec} the code generation is configured to produce static
-binary. In this case @option{-fpic} and @option{-fpie} are both disabled.
-
-If @var{type} is @samp{dyn} the code generation is configured to produce shared
-library. In this case @option{-fpic} or @option{-fPIC} is preserved, but not
-enabled automatically. This makes it possible to build shared libraries without
-position independent code on architectures this is possible, i.e.@: on x86.
-
-If @var{type} is @samp{pie} the code generation is configured to produce
-@option{-fpie} executable. This result in similar optimizations as @samp{exec}
-except that @option{-fpie} is not disabled if specified at compilation time.
-
-If @var{type} is @samp{rel} the compiler assumes that incremental linking is
+This option controls code generation of the link-time optimizer. By
+default the linker output is automatically determined by the linker
+plugin. For debugging the compiler and if incremental linking with a
+non-LTO object file is desired, it may be useful to control the type
+manually.
+
+If @var{type} is @samp{exec}, code generation produces a static
+binary. In this case @option{-fpic} and @option{-fpie} are both
+disabled.
+
+If @var{type} is @samp{dyn}, code generation produces a shared
+library. In this case @option{-fpic} or @option{-fPIC} is preserved,
+but not enabled automatically. This allows to build shared libraries
+without position-independent code on architectures where this is
+possible, i.e.@: on x86.
+
+If @var{type} is @samp{pie}, code generation produces an @option{-fpie}
+executable. This results in similar optimizations as @samp{exec}
+except that @option{-fpie} is not disabled if specified at compilation
+time.
+
+If @var{type} is @samp{rel}, the compiler assumes that incremental linking is
done. The sections containing intermediate code for link-time optimization are
merged, pre-optimized, and output to the resulting object file. In addition, if
-@option{-ffat-lto-objects} is specified the binary code is produced for future
-non-lto linking. The object file produced by incremental linking will be smaller
-than a static library produced from the same object files. At link-time the
-result of incremental linking will also load faster to compiler than a static
-library assuming that majority of objects in the library are used.
-
-Finally @samp{nolto-rel} configure compiler to for incremental linking where
-code generation is forced, final binary is produced and the intermediate code
-for later link-time optimization is stripped. When multiple object files are
-linked together the resulting code will be optimized better than with link time
-optimizations disabled (for example, the cross-module inlining will happen),
-most of benefits of whole program optimizations are however lost.
-
-During the incremental link (by @option{-r}) the linker plugin will default to
+@option{-ffat-lto-objects} is specified, binary code is produced for future
+non-LTO linking. The object file produced by incremental linking is smaller
+than a static library produced from the same object files. At link time the
+result of incremental linking also loads faster than a static
+library assuming that the majority of objects in the library are used.
+
+Finally @samp{nolto-rel} configures the compiler for incremental linking where
+code generation is forced, a final binary is produced, and the intermediate
+code for later link-time optimization is stripped. When multiple object files
+are linked together the resulting code is better optimized than with
+link-time optimizations disabled (for example, cross-module inlining
+happens), but most of benefits of whole program optimizations are lost.
+
+During the incremental link (by @option{-r}) the linker plugin defaults to
@option{rel}. With current interfaces to GNU Binutils it is however not
-possible to link incrementally LTO objects and non-LTO objects into a single
-mixed object file. In the case any of object files in incremental link cannot
-be used for link-time optimization the linker plugin will output warning and
-use @samp{nolto-rel}. To maintain the whole program optimization it is
+possible to incrementally link LTO objects and non-LTO objects into a single
+mixed object file. If any of object files in incremental link cannot
+be used for link-time optimization, the linker plugin issues a warning and
+uses @samp{nolto-rel}. To maintain whole program optimization, it is
recommended to link such objects into static library instead. Alternatively it
is possible to use H.J. Lu's binutils with support for mixed objects.
@@ -15316,8 +15386,8 @@ Disabled by default.
@item -flto-report-wpa
@opindex flto-report-wpa
-Like @option{-flto-report}, but only print for the WPA phase of Link
-Time Optimization.
+Like @option{-flto-report}, but only print for the WPA phase of link-time
+optimization.
@item -fmem-report
@opindex fmem-report
@@ -15564,6 +15634,7 @@ platform.
* PDP-11 Options::
* picoChip Options::
* PowerPC Options::
+* PRU Options::
* RISC-V Options::
* RL78 Options::
* RS/6000 and PowerPC Options::
@@ -15886,7 +15957,7 @@ functions, and @samp{all}, which enables pointer signing for all functions. The
default value is @samp{none}. This option has been deprecated by
-mbranch-protection.
-@item -mbranch-protection=@var{none}|@var{standard}|@var{pac-ret}[+@var{leaf}]|@var{bti}
+@item -mbranch-protection=@var{none}|@var{standard}|@var{pac-ret}[+@var{leaf}+@var{b-key}]|@var{bti}
@opindex mbranch-protection
Select the branch protection features to use.
@samp{none} is the default and turns off all types of branch protection.
@@ -15897,7 +15968,8 @@ level.
level: signing functions that save the return address to memory (non-leaf
functions will practically always do this) using the a-key. The optional
argument @samp{leaf} can be used to extend the signing to include leaf
-functions.
+functions. The optional argument @samp{b-key} can be used to sign the functions
+with the B-key instead of the A-key.
@samp{bti} turns on branch target identification mechanism.
@item -msve-vector-bits=@var{bits}
@@ -15998,6 +16070,17 @@ generation. This option is enabled by default for @option{-march=armv8.5-a}.
Enable the Armv8-a Execution and Data Prediction Restriction instructions.
This option is only to enable the extension at the assembler level and does
not affect code generation. This option is enabled by default for
+@item sve2
+Enable the Armv8-a Scalable Vector Extension 2. This also enables SVE
+instructions.
+@item bitperm
+Enable SVE2 bitperm instructions. This also enables SVE2 instructions.
+@item sve2-sm4
+Enable SVE2 sm4 instructions. This also enables SVE2 instructions.
+@item sve2-aes
+Enable SVE2 aes instructions. This also enables SVE2 instructions.
+@item sve2-sha3
+Enable SVE2 sha3 instructions. This also enables SVE2 instructions.
@option{-march=armv8.5-a}.
@end table
@@ -16192,6 +16275,9 @@ Compile for GCN3 Fiji devices (gfx803).
@item gfx900
Compile for GCN5 Vega 10 devices (gfx900).
+@item gfx906
+Compile for GCN5 Vega 20 devices (gfx906).
+
@end table
@item -mstack-size=@var{bytes}
@@ -23724,6 +23810,66 @@ these warnings.
These are listed under @xref{RS/6000 and PowerPC Options}.
+@node PRU Options
+@subsection PRU Options
+@cindex PRU Options
+
+These command-line options are defined for PRU target:
+
+@table @gcctabopt
+@item -minrt
+@opindex minrt
+Link with a minimum runtime environment, with no support for static
+initializers and constructors. Using this option can significantly reduce
+the size of the final ELF binary. Beware that the compiler could still
+generate code with static initializers and constructors. It is up to the
+programmer to ensure that the source program will not use those features.
+
+@item -mmcu=@var{mcu}
+@opindex mmcu
+Specify the PRU MCU variant to use. Check Newlib for the exact list of
+supported MCUs.
+
+@item -mno-relax
+@opindex mno-relax
+Make GCC pass the @option{--no-relax} command-line option to the linker
+instead of the @option{--relax} option.
+
+@item -mloop
+@opindex mloop
+Allow (or do not allow) GCC to use the LOOP instruction.
+
+@item -mabi=@var{variant}
+@opindex mabi
+Specify the ABI variant to output code for. @option{-mabi=ti} selects the
+unmodified TI ABI while @option{-mabi=gnu} selects a GNU variant that copes
+more naturally with certain GCC assumptions. These are the differences:
+
+@table @samp
+@item Function Pointer Size
+TI ABI specifies that function (code) pointers are 16-bit, whereas GNU
+supports only 32-bit data and code pointers.
+
+@item Optional Return Value Pointer
+Function return values larger than 64 bits are passed by using a hidden
+pointer as the first argument of the function. TI ABI, though, mandates that
+the pointer can be NULL in case the caller is not using the returned value.
+GNU always passes and expects a valid return value pointer.
+
+@end table
+
+The current @option{-mabi=ti} implementation simply raises a compile error
+when any of the above code constructs is detected. As a consequence
+the standard C library cannot be built and it is omitted when linking with
+@option{-mabi=ti}.
+
+Relaxation is a GNU feature and for safety reasons is disabled when using
+@option{-mabi=ti}. The TI toolchain does not emit relocations for QBBx
+instructions, so the GNU linker cannot adjust them when shortening adjacent
+LDI32 pseudo instructions.
+
+@end table
+
@node RISC-V Options
@subsection RISC-V Options
@cindex RISC-V Options
@@ -23986,8 +24132,6 @@ These @samp{-m} options are defined for the IBM RS/6000 and PowerPC:
@need 800
@itemx -mcmpb
@itemx -mno-cmpb
-@itemx -mmfpgpr
-@itemx -mno-mfpgpr
@itemx -mhard-dfp
@itemx -mno-hard-dfp
@opindex mpowerpc-gpopt
@@ -24006,8 +24150,6 @@ These @samp{-m} options are defined for the IBM RS/6000 and PowerPC:
@opindex mno-fprnd
@opindex mcmpb
@opindex mno-cmpb
-@opindex mmfpgpr
-@opindex mno-mfpgpr
@opindex mhard-dfp
@opindex mno-hard-dfp
You use these options to specify which instructions are available on the
@@ -24041,10 +24183,6 @@ processors that support the PowerPC V2.03 architecture.
The @option{-mcmpb} option allows GCC to generate the compare bytes
instruction implemented on the POWER6 processor and other processors
that support the PowerPC V2.05 architecture.
-The @option{-mmfpgpr} option allows GCC to generate the FP move to/from
-general-purpose register instructions implemented on the POWER6X
-processor and other processors that support the extended PowerPC V2.05
-architecture.
The @option{-mhard-dfp} option allows GCC to generate the decimal
floating-point instructions implemented on some POWER processors.
@@ -24067,8 +24205,8 @@ Supported values for @var{cpu_type} are @samp{401}, @samp{403},
@samp{e6500}, @samp{ec603e}, @samp{G3}, @samp{G4}, @samp{G5},
@samp{titan}, @samp{power3}, @samp{power4}, @samp{power5}, @samp{power5+},
@samp{power6}, @samp{power6x}, @samp{power7}, @samp{power8},
-@samp{power9}, @samp{powerpc}, @samp{powerpc64}, @samp{powerpc64le},
-@samp{rs64}, and @samp{native}.
+@samp{power9}, @samp{future}, @samp{powerpc}, @samp{powerpc64},
+@samp{powerpc64le}, @samp{rs64}, and @samp{native}.
@option{-mcpu=powerpc}, @option{-mcpu=powerpc64}, and
@option{-mcpu=powerpc64le} specify pure 32-bit PowerPC (either
@@ -25074,6 +25212,13 @@ which register to use as base register for reading the canary, and from what
offset from that base register. The default for those is as specified in the
relevant ABI. @option{-mstack-protector-guard-symbol=@var{symbol}} overrides
the offset with a symbol reference to a canary in the TLS block.
+
+@item -mpcrel
+@itemx -mno-pcrel
+@opindex mpcrel
+@opindex mno-pcrel
+Generate (do not generate) pc-relative addressing when the option
+@option{-mcpu=future} is used.
@end table
@node RX Options
@@ -27355,34 +27500,34 @@ instruction set extensions.)
@item bdver1
CPUs based on AMD Family 15h cores with x86-64 instruction set support. (This
-supersets FMA4, AVX, XOP, LWP, AES, PCL_MUL, CX16, MMX, SSE, SSE2, SSE3, SSE4A,
+supersets FMA4, AVX, XOP, LWP, AES, PCLMUL, CX16, MMX, SSE, SSE2, SSE3, SSE4A,
SSSE3, SSE4.1, SSE4.2, ABM and 64-bit instruction set extensions.)
@item bdver2
AMD Family 15h core based CPUs with x86-64 instruction set support. (This
-supersets BMI, TBM, F16C, FMA, FMA4, AVX, XOP, LWP, AES, PCL_MUL, CX16, MMX,
+supersets BMI, TBM, F16C, FMA, FMA4, AVX, XOP, LWP, AES, PCLMUL, CX16, MMX,
SSE, SSE2, SSE3, SSE4A, SSSE3, SSE4.1, SSE4.2, ABM and 64-bit instruction set
extensions.)
@item bdver3
AMD Family 15h core based CPUs with x86-64 instruction set support. (This
supersets BMI, TBM, F16C, FMA, FMA4, FSGSBASE, AVX, XOP, LWP, AES,
-PCL_MUL, CX16, MMX, SSE, SSE2, SSE3, SSE4A, SSSE3, SSE4.1, SSE4.2, ABM and
+PCLMUL, CX16, MMX, SSE, SSE2, SSE3, SSE4A, SSSE3, SSE4.1, SSE4.2, ABM and
64-bit instruction set extensions.
@item bdver4
AMD Family 15h core based CPUs with x86-64 instruction set support. (This
supersets BMI, BMI2, TBM, F16C, FMA, FMA4, FSGSBASE, AVX, AVX2, XOP, LWP,
-AES, PCL_MUL, CX16, MOVBE, MMX, SSE, SSE2, SSE3, SSE4A, SSSE3, SSE4.1,
+AES, PCLMUL, CX16, MOVBE, MMX, SSE, SSE2, SSE3, SSE4A, SSSE3, SSE4.1,
SSE4.2, ABM and 64-bit instruction set extensions.
@item znver1
AMD Family 17h core based CPUs with x86-64 instruction set support. (This
supersets BMI, BMI2, F16C, FMA, FSGSBASE, AVX, AVX2, ADCX, RDSEED, MWAITX,
-SHA, CLZERO, AES, PCL_MUL, CX16, MOVBE, MMX, SSE, SSE2, SSE3, SSE4A, SSSE3,
+SHA, CLZERO, AES, PCLMUL, CX16, MOVBE, MMX, SSE, SSE2, SSE3, SSE4A, SSSE3,
SSE4.1, SSE4.2, ABM, XSAVEC, XSAVES, CLFLUSHOPT, POPCNT, and 64-bit
instruction set extensions.
@item znver2
AMD Family 17h core based CPUs with x86-64 instruction set support. (This
supersets BMI, BMI2, ,CLWB, F16C, FMA, FSGSBASE, AVX, AVX2, ADCX, RDSEED,
-MWAITX, SHA, CLZERO, AES, PCL_MUL, CX16, MOVBE, MMX, SSE, SSE2, SSE3, SSE4A,
+MWAITX, SHA, CLZERO, AES, PCLMUL, CX16, MOVBE, MMX, SSE, SSE2, SSE3, SSE4A,
SSSE3, SSE4.1, SSE4.2, ABM, XSAVEC, XSAVES, CLFLUSHOPT, POPCNT, and 64-bit
instruction set extensions.)
@@ -27394,7 +27539,7 @@ instruction set extensions.)
@item btver2
CPUs based on AMD Family 16h cores with x86-64 instruction set support. This
-includes MOVBE, F16C, BMI, AVX, PCL_MUL, AES, SSE4.2, SSE4.1, CX16, ABM,
+includes MOVBE, F16C, BMI, AVX, PCLMUL, AES, SSE4.2, SSE4.1, CX16, ABM,
SSE4A, SSSE3, SSE3, SSE2, SSE, MMX and 64-bit instruction set extensions.
@item winchip-c6
@@ -27774,12 +27919,10 @@ the system libraries and startup modules.
@item -mvect8-ret-in-mem
@opindex mvect8-ret-in-mem
Return 8-byte vectors in memory instead of MMX registers. This is the
-default on Solaris@tie{}8 and 9 and VxWorks to match the ABI of the Sun
-Studio compilers until version 12. Later compiler versions (starting
-with Studio 12 Update@tie{}1) follow the ABI used by other x86 targets, which
-is the default on Solaris@tie{}10 and later. @emph{Only} use this option if
-you need to remain compatible with existing code produced by those
-previous compiler versions or older versions of GCC@.
+default on VxWorks to match the ABI of the Sun Studio compilers until
+version 12. @emph{Only} use this option if you need to remain
+compatible with existing code produced by those previous compiler
+versions or older versions of GCC@.
@item -mpc32
@itemx -mpc64
@@ -28065,9 +28208,15 @@ preferred alignment to @option{-mpreferred-stack-boundary=2}.
@itemx -mmovdir64b
@opindex mmovdir64b
@need 200
+@itemx -menqcmd
+@opindex menqcmd
+@need 200
@itemx -mavx512vpopcntdq
@opindex mavx512vpopcntdq
@need 200
+@itemx -mavx512vp2intersect
+@opindex mavx512vp2intersect
+@need 200
@itemx -mavx5124fmaps
@opindex mavx5124fmaps
@need 200
@@ -28086,8 +28235,8 @@ AES, PCLMUL, CLFLUSHOPT, CLWB, FSGSBASE, PTWRITE, RDRND, F16C, FMA, PCONFIG,
WBNOINVD, FMA4, PREFETCHW, RDPID, PREFETCHWT1, RDSEED, SGX, XOP, LWP,
3DNow!@:, enhanced 3DNow!@:, POPCNT, ABM, ADX, BMI, BMI2, LZCNT, FXSR, XSAVE,
XSAVEOPT, XSAVEC, XSAVES, RTM, HLE, TBM, MWAITX, CLZERO, PKU, AVX512VBMI2,
-GFNI, VAES, WAITPKG, VPCLMULQDQ, AVX512BITALG, MOVDIRI, MOVDIR64B, AVX512BF16
-AVX512VPOPCNTDQ, AVX5124FMAPS, AVX512VNNI, AVX5124VNNIW, or CLDEMOTE
+GFNI, VAES, WAITPKG, VPCLMULQDQ, AVX512BITALG, MOVDIRI, MOVDIR64B, AVX512BF16,
+ENQCMD, AVX512VPOPCNTDQ, AVX5124FMAPS, AVX512VNNI, AVX5124VNNIW, or CLDEMOTE
extended instruction sets. Each has a corresponding @option{-mno-} option to
disable use of these instructions.
@@ -29232,7 +29381,7 @@ Like @samp{%g}, except if @option{-pipe} is in effect. In that case
all. These are the two most common ways to instruct a program that it
should read from standard input or write to standard output. If you
need something more elaborate you can use an @samp{%@{pipe:@code{X}@}}
-construct: see for example @file{f/lang-specs.h}.
+construct: see for example @file{gcc/fortran/lang-specs.h}.
@item %.@var{SUFFIX}
Substitutes @var{.SUFFIX} for the suffixes of a matched switch's args
diff --git a/gcc/doc/loop.texi b/gcc/doc/loop.texi
index 255eabc..a753713 100644
--- a/gcc/doc/loop.texi
+++ b/gcc/doc/loop.texi
@@ -86,10 +86,7 @@ the direction of traversal and the set of loops visited. Each loop is
guaranteed to be visited exactly once, regardless of the changes to the
loop tree, and the loops may be removed during the traversal. The newly
created loops are never traversed, if they need to be visited, this
-must be done separately after their creation. The @code{FOR_EACH_LOOP}
-macro allocates temporary variables. If the @code{FOR_EACH_LOOP} loop
-were ended using break or goto, they would not be released;
-@code{FOR_EACH_LOOP_BREAK} macro must be used instead.
+must be done separately after their creation.
Each basic block contains the reference to the innermost loop it belongs
to (@code{loop_father}). For this reason, it is only possible to have
diff --git a/gcc/doc/md.texi b/gcc/doc/md.texi
index 30612a6..b1fcc38 100644
--- a/gcc/doc/md.texi
+++ b/gcc/doc/md.texi
@@ -3196,11 +3196,8 @@ Altivec vector register
@item wa
Any VSX register if the @option{-mvsx} option was used or NO_REGS.
-When using any of the register constraints (@code{wa}, @code{wd},
-@code{wf}, @code{wg}, @code{wh}, @code{wi}, @code{wj}, @code{wk},
-@code{wl}, @code{wm}, @code{wo}, @code{wp}, @code{wq}, @code{ws},
-@code{wt}, @code{wu}, @code{wv}, @code{ww}, or @code{wy})
-that take VSX registers, you must use @code{%x<n>} in the template so
+When using the register constraint @code{wa}
+that takes VSX registers, you must use @code{%x<n>} in the template so
that the correct register is used. Otherwise the register number
output in the assembly file will be incorrect if an Altivec register
is an operand of a VSX instruction that expects VSX register
@@ -3246,79 +3243,19 @@ asm ("xsaddqp %x0,%x1,%x2"
@noindent
is incorrect.
-@item wb
-Altivec register if @option{-mcpu=power9} is used or NO_REGS.
-
-@item wd
-VSX vector register to hold vector double data or NO_REGS.
-
@item we
VSX register if the @option{-mcpu=power9} and @option{-m64} options
were used or NO_REGS.
-@item wf
-VSX vector register to hold vector float data or NO_REGS.
-
-@item wg
-If @option{-mmfpgpr} was used, a floating point register or NO_REGS.
-
-@item wh
-Floating point register if direct moves are available, or NO_REGS.
-
-@item wi
-FP or VSX register to hold 64-bit integers for VSX insns or NO_REGS.
-
-@item wj
-FP or VSX register to hold 64-bit integers for direct moves or NO_REGS.
-
-@item wk
-FP or VSX register to hold 64-bit doubles for direct moves or NO_REGS.
-
-@item wl
-Floating point register if the LFIWAX instruction is enabled or NO_REGS.
-
-@item wm
-VSX register if direct move instructions are enabled, or NO_REGS.
-
@item wn
No register (NO_REGS).
-@item wo
-VSX register to use for ISA 3.0 vector instructions, or NO_REGS.
-
-@item wp
-VSX register to use for IEEE 128-bit floating point TFmode, or NO_REGS.
-
-@item wq
-VSX register to use for IEEE 128-bit floating point, or NO_REGS.
-
@item wr
General purpose register if 64-bit instructions are enabled or NO_REGS.
-@item ws
-VSX vector register to hold scalar double values or NO_REGS.
-
-@item wt
-VSX vector register to hold 128 bit integer or NO_REGS.
-
-@item wu
-Altivec register to use for float/32-bit int loads/stores or NO_REGS.
-
-@item wv
-Altivec register to use for double loads/stores or NO_REGS.
-
-@item ww
-FP or VSX register to perform float operations under @option{-mvsx} or NO_REGS.
-
@item wx
Floating point register if the STFIWX instruction is enabled or NO_REGS.
-@item wy
-FP or VSX register to perform ISA 2.07 float ops or NO_REGS.
-
-@item wz
-Floating point register if the LFIWZX instruction is enabled or NO_REGS.
-
@item wA
Address base register if 64-bit instructions are enabled or NO_REGS.
@@ -3337,18 +3274,6 @@ Memory operand suitable for power8 GPR load fusion
@item wG
Memory operand suitable for TOC fusion memory references.
-@item wH
-Altivec register if @option{-mvsx-small-integer}.
-
-@item wI
-Floating point register if @option{-mvsx-small-integer}.
-
-@item wJ
-FP register if @option{-mvsx-small-integer} and @option{-mpower9-vector}.
-
-@item wK
-Altivec register if @option{-mvsx-small-integer} and @option{-mpower9-vector}.
-
@item wL
Int constant that is the element number that the MFVSRLD instruction.
targets.
@@ -3409,6 +3334,9 @@ Zero
@item P
Constant whose negation is a signed 16-bit constant
+@item eI
+Signed 34-bit integer constant if prefixed instructions are supported.
+
@item G
Floating point constant that can be loaded into a register with one
instruction per word
@@ -3472,6 +3400,25 @@ Vector constant that is all zeros.
@end table
+@item PRU---@file{config/pru/constraints.md}
+@table @code
+@item I
+An unsigned 8-bit integer constant.
+
+@item J
+An unsigned 16-bit integer constant.
+
+@item L
+An unsigned 5-bit integer constant (for shift counts).
+
+@item T
+A text segment (program memory) constant label.
+
+@item Z
+Integer constant zero.
+
+@end table
+
@item RL78---@file{config/rl78/constraints.md}
@table @code
@@ -5470,6 +5417,11 @@ mode @var{m} and the scalars have the mode appropriate for one
element of @var{m}. The operation is strictly in-order: there is
no reassociation.
+@cindex @code{mask_fold_left_plus_@var{m}} instruction pattern
+@item @code{mask_fold_left_plus_@var{m}}
+Like @samp{fold_left_plus_@var{m}}, but takes an additional mask operand
+(operand 3) that specifies which elements of the source vector should be added.
+
@cindex @code{sdot_prod@var{m}} instruction pattern
@item @samp{sdot_prod@var{m}}
@cindex @code{udot_prod@var{m}} instruction pattern
@@ -5507,6 +5459,14 @@ in operand 2. Store the result in vector output operand 0. Operands
0 and 1 have mode @var{m} and operand 2 has the mode appropriate for
one element of @var{m}.
+@cindex @code{vec_shl_@var{m}} instruction pattern
+@item @samp{vec_shl_@var{m}}
+Whole vector left shift in bits, i.e.@: away from element 0.
+Operand 1 is a vector to be shifted.
+Operand 2 is an integer shift amount in bits.
+Operand 0 is where the resulting shifted vector is stored.
+The output and input vectors should have the same modes.
+
@cindex @code{vec_shr_@var{m}} instruction pattern
@item @samp{vec_shr_@var{m}}
Whole vector right shift in bits, i.e.@: towards element 0.
@@ -6240,13 +6200,50 @@ This pattern is not allowed to @code{FAIL}.
@item @samp{one_cmpl@var{m}2}
Store the bitwise-complement of operand 1 into operand 0.
+@cindex @code{cpymem@var{m}} instruction pattern
+@item @samp{cpymem@var{m}}
+Block copy instruction. The destination and source blocks of memory
+are the first two operands, and both are @code{mem:BLK}s with an
+address in mode @code{Pmode}.
+
+The number of bytes to copy is the third operand, in mode @var{m}.
+Usually, you specify @code{Pmode} for @var{m}. However, if you can
+generate better code knowing the range of valid lengths is smaller than
+those representable in a full Pmode pointer, you should provide
+a pattern with a
+mode corresponding to the range of values you can handle efficiently
+(e.g., @code{QImode} for values in the range 0--127; note we avoid numbers
+that appear negative) and also a pattern with @code{Pmode}.
+
+The fourth operand is the known shared alignment of the source and
+destination, in the form of a @code{const_int} rtx. Thus, if the
+compiler knows that both source and destination are word-aligned,
+it may provide the value 4 for this operand.
+
+Optional operands 5 and 6 specify expected alignment and size of block
+respectively. The expected alignment differs from alignment in operand 4
+in a way that the blocks are not required to be aligned according to it in
+all cases. This expected alignment is also in bytes, just like operand 4.
+Expected size, when unknown, is set to @code{(const_int -1)}.
+
+Descriptions of multiple @code{cpymem@var{m}} patterns can only be
+beneficial if the patterns for smaller modes have fewer restrictions
+on their first, second and fourth operands. Note that the mode @var{m}
+in @code{cpymem@var{m}} does not impose any restriction on the mode of
+individually copied data units in the block.
+
+The @code{cpymem@var{m}} patterns need not give special consideration
+to the possibility that the source and destination strings might
+overlap. These patterns are used to do inline expansion of
+@code{__builtin_memcpy}.
+
@cindex @code{movmem@var{m}} instruction pattern
@item @samp{movmem@var{m}}
Block move instruction. The destination and source blocks of memory
are the first two operands, and both are @code{mem:BLK}s with an
address in mode @code{Pmode}.
-The number of bytes to move is the third operand, in mode @var{m}.
+The number of bytes to copy is the third operand, in mode @var{m}.
Usually, you specify @code{Pmode} for @var{m}. However, if you can
generate better code knowing the range of valid lengths is smaller than
those representable in a full Pmode pointer, you should provide
@@ -6270,10 +6267,11 @@ Descriptions of multiple @code{movmem@var{m}} patterns can only be
beneficial if the patterns for smaller modes have fewer restrictions
on their first, second and fourth operands. Note that the mode @var{m}
in @code{movmem@var{m}} does not impose any restriction on the mode of
-individually moved data units in the block.
+individually copied data units in the block.
-These patterns need not give special consideration to the possibility
-that the source and destination strings might overlap.
+The @code{movmem@var{m}} patterns must correctly handle the case where
+the source and destination strings overlap. These patterns are used to
+do inline expansion of @code{__builtin_memmove}.
@cindex @code{movstr} instruction pattern
@item @samp{movstr}
@@ -6294,7 +6292,7 @@ given as a @code{mem:BLK} whose address is in mode @code{Pmode}. The
number of bytes to set is the second operand, in mode @var{m}. The value to
initialize the memory with is the third operand. Targets that only support the
clearing of memory should reject any value that is not the constant 0. See
-@samp{movmem@var{m}} for a discussion of the choice of mode.
+@samp{cpymem@var{m}} for a discussion of the choice of mode.
The fourth operand is the known alignment of the destination, in the form
of a @code{const_int} rtx. Thus, if the compiler knows that the
@@ -6312,13 +6310,13 @@ Operand 9 is the probable maximal size (i.e.@: we cannot rely on it for
correctness, but it can be used for choosing proper code sequence for a
given size).
-The use for multiple @code{setmem@var{m}} is as for @code{movmem@var{m}}.
+The use for multiple @code{setmem@var{m}} is as for @code{cpymem@var{m}}.
@cindex @code{cmpstrn@var{m}} instruction pattern
@item @samp{cmpstrn@var{m}}
String compare instruction, with five operands. Operand 0 is the output;
it has mode @var{m}. The remaining four operands are like the operands
-of @samp{movmem@var{m}}. The two memory blocks specified are compared
+of @samp{cpymem@var{m}}. The two memory blocks specified are compared
byte by byte in lexicographic order starting at the beginning of each
string. The instruction is not allowed to prefetch more than one byte
at a time since either string may end in the first byte and reading past
@@ -8537,6 +8535,119 @@ functionality as two separate @code{define_insn} and @code{define_split}
patterns. It exists for compactness, and as a maintenance tool to prevent
having to ensure the two patterns' templates match.
+@findex define_insn_and_rewrite
+It is sometimes useful to have a @code{define_insn_and_split}
+that replaces specific operands of an instruction but leaves the
+rest of the instruction pattern unchanged. You can do this directly
+with a @code{define_insn_and_split}, but it requires a
+@var{new-insn-pattern-1} that repeats most of the original @var{insn-pattern}.
+There is also the complication that an implicit @code{parallel} in
+@var{insn-pattern} must become an explicit @code{parallel} in
+@var{new-insn-pattern-1}, which is easy to overlook.
+A simpler alternative is to use @code{define_insn_and_rewrite}, which
+is a form of @code{define_insn_and_split} that automatically generates
+@var{new-insn-pattern-1} by replacing each @code{match_operand}
+in @var{insn-pattern} with a corresponding @code{match_dup}, and each
+@code{match_operator} in the pattern with a corresponding @code{match_op_dup}.
+The arguments are otherwise identical to @code{define_insn_and_split}:
+
+@smallexample
+(define_insn_and_rewrite
+ [@var{insn-pattern}]
+ "@var{condition}"
+ "@var{output-template}"
+ "@var{split-condition}"
+ "@var{preparation-statements}"
+ [@var{insn-attributes}])
+@end smallexample
+
+The @code{match_dup}s and @code{match_op_dup}s in the new
+instruction pattern use any new operand values that the
+@var{preparation-statements} store in the @code{operands} array,
+as for a normal @code{define_insn_and_split}. @var{preparation-statements}
+can also emit additional instructions before the new instruction.
+They can even emit an entirely different sequence of instructions and
+use @code{DONE} to avoid emitting a new form of the original
+instruction.
+
+The split in a @code{define_insn_and_rewrite} is only intended
+to apply to existing instructions that match @var{insn-pattern}.
+@var{split-condition} must therefore start with @code{&&},
+so that the split condition applies on top of @var{condition}.
+
+Here is an example from the AArch64 SVE port, in which operand 1 is
+known to be equivalent to an all-true constant and isn't used by the
+output template:
+
+@smallexample
+(define_insn_and_rewrite "*while_ult<GPI:mode><PRED_ALL:mode>_cc"
+ [(set (reg:CC CC_REGNUM)
+ (compare:CC
+ (unspec:SI [(match_operand:PRED_ALL 1)
+ (unspec:PRED_ALL
+ [(match_operand:GPI 2 "aarch64_reg_or_zero" "rZ")
+ (match_operand:GPI 3 "aarch64_reg_or_zero" "rZ")]
+ UNSPEC_WHILE_LO)]
+ UNSPEC_PTEST_PTRUE)
+ (const_int 0)))
+ (set (match_operand:PRED_ALL 0 "register_operand" "=Upa")
+ (unspec:PRED_ALL [(match_dup 2)
+ (match_dup 3)]
+ UNSPEC_WHILE_LO))]
+ "TARGET_SVE"
+ "whilelo\t%0.<PRED_ALL:Vetype>, %<w>2, %<w>3"
+ ;; Force the compiler to drop the unused predicate operand, so that we
+ ;; don't have an unnecessary PTRUE.
+ "&& !CONSTANT_P (operands[1])"
+ @{
+ operands[1] = CONSTM1_RTX (<MODE>mode);
+ @}
+)
+@end smallexample
+
+The splitter in this case simply replaces operand 1 with the constant
+value that it is known to have. The equivalent @code{define_insn_and_split}
+would be:
+
+@smallexample
+(define_insn_and_split "*while_ult<GPI:mode><PRED_ALL:mode>_cc"
+ [(set (reg:CC CC_REGNUM)
+ (compare:CC
+ (unspec:SI [(match_operand:PRED_ALL 1)
+ (unspec:PRED_ALL
+ [(match_operand:GPI 2 "aarch64_reg_or_zero" "rZ")
+ (match_operand:GPI 3 "aarch64_reg_or_zero" "rZ")]
+ UNSPEC_WHILE_LO)]
+ UNSPEC_PTEST_PTRUE)
+ (const_int 0)))
+ (set (match_operand:PRED_ALL 0 "register_operand" "=Upa")
+ (unspec:PRED_ALL [(match_dup 2)
+ (match_dup 3)]
+ UNSPEC_WHILE_LO))]
+ "TARGET_SVE"
+ "whilelo\t%0.<PRED_ALL:Vetype>, %<w>2, %<w>3"
+ ;; Force the compiler to drop the unused predicate operand, so that we
+ ;; don't have an unnecessary PTRUE.
+ "&& !CONSTANT_P (operands[1])"
+ [(parallel
+ [(set (reg:CC CC_REGNUM)
+ (compare:CC
+ (unspec:SI [(match_dup 1)
+ (unspec:PRED_ALL [(match_dup 2)
+ (match_dup 3)]
+ UNSPEC_WHILE_LO)]
+ UNSPEC_PTEST_PTRUE)
+ (const_int 0)))
+ (set (match_dup 0)
+ (unspec:PRED_ALL [(match_dup 2)
+ (match_dup 3)]
+ UNSPEC_WHILE_LO))])]
+ @{
+ operands[1] = CONSTM1_RTX (<MODE>mode);
+ @}
+)
+@end smallexample
+
@end ifset
@ifset INTERNALS
@node Including Patterns
@@ -10979,6 +11090,27 @@ Other attributes are defined using:
(define_code_attr @var{name} [(@var{code1} "@var{value1}") @dots{} (@var{coden} "@var{valuen}")])
@end smallexample
+Instruction patterns can use code attributes as rtx codes, which can be
+useful if two sets of codes act in tandem. For example, the following
+@code{define_insn} defines two patterns, one calculating a signed absolute
+difference and another calculating an unsigned absolute difference:
+
+@smallexample
+(define_code_iterator any_max [smax umax])
+(define_code_attr paired_min [(smax "smin") (umax "umin")])
+(define_insn @dots{}
+ [(set (match_operand:SI 0 @dots{})
+ (minus:SI (any_max:SI (match_operand:SI 1 @dots{})
+ (match_operand:SI 2 @dots{}))
+ (<paired_min>:SI (match_dup 1) (match_dup 2))))]
+ @dots{})
+@end smallexample
+
+The signed version of the instruction uses @code{smax} and @code{smin}
+while the unsigned version uses @code{umax} and @code{umin}. There
+are no versions that pair @code{smax} with @code{umin} or @code{umax}
+with @code{smin}.
+
Here's an example of code iterators in action, taken from the MIPS port:
@smallexample
diff --git a/gcc/doc/rtl.texi b/gcc/doc/rtl.texi
index f5f2de7..0814b66 100644
--- a/gcc/doc/rtl.texi
+++ b/gcc/doc/rtl.texi
@@ -3341,7 +3341,7 @@ that the register is live. You should think twice before adding
instead. The @code{use} RTX is most commonly useful to describe that
a fixed register is implicitly used in an insn. It is also safe to use
in patterns where the compiler knows for other reasons that the result
-of the whole pattern is variable, such as @samp{movmem@var{m}} or
+of the whole pattern is variable, such as @samp{cpymem@var{m}} or
@samp{call} patterns.
During the reload phase, an insn that has a @code{use} as pattern
diff --git a/gcc/doc/sourcebuild.texi b/gcc/doc/sourcebuild.texi
index cf12d74..6a66515 100644
--- a/gcc/doc/sourcebuild.texi
+++ b/gcc/doc/sourcebuild.texi
@@ -1357,6 +1357,9 @@ Target has @code{int} that is at 32 bits or longer.
@item int16
Target has @code{int} that is 16 bits or shorter.
+@item longlong64
+Target has 64-bit @code{long long}.
+
@item long_neq_int
Target has @code{int} and @code{long} with different sizes.
@@ -2043,6 +2046,9 @@ Target supports compiling @code{avx512f} instructions.
@item avx512f_runtime
Target supports the execution of @code{avx512f} instructions.
+@item avx512vp2intersect
+Target supports the execution of @code{avx512vp2intersect} instructions.
+
@item cell_hw
Test system can execute AltiVec and Cell PPU instructions.
@@ -2382,6 +2388,10 @@ Target supports compiling @code{aes} instructions.
@item fma4
Target supports compiling @code{fma4} instructions.
+@item mfentry
+Target supports the @code{-mfentry} option that alters the
+position of profiling calls such that they precede the prologue.
+
@item ms_hook_prologue
Target supports attribute @code{ms_hook_prologue}.
diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi
index 8c8978b..14c1ea6 100644
--- a/gcc/doc/tm.texi
+++ b/gcc/doc/tm.texi
@@ -5594,6 +5594,11 @@ This hook determines whether a function from a class of functions
@var{fn_class} is present at the runtime.
@end deftypefn
+@deftypefn {Target Hook} bool TARGET_LIBC_HAS_FAST_FUNCTION (int @var{fcode})
+This hook determines whether a function from a class of functions
+@var{fn_class} has a fast implementation.
+@end deftypefn
+
@defmac NEXT_OBJC_RUNTIME
Set this macro to 1 to use the "NeXT" Objective-C message sending conventions
by default. This calling convention involves passing the object, the selector
@@ -6016,11 +6021,13 @@ against lower halves of vectors recursively until the specified mode is
reached. The default is @var{mode} which means no splitting.
@end deftypefn
-@deftypefn {Target Hook} void TARGET_VECTORIZE_AUTOVECTORIZE_VECTOR_SIZES (vector_sizes *@var{sizes})
+@deftypefn {Target Hook} void TARGET_VECTORIZE_AUTOVECTORIZE_VECTOR_SIZES (vector_sizes *@var{sizes}, bool @var{all})
If the mode returned by @code{TARGET_VECTORIZE_PREFERRED_SIMD_MODE} is not
the only one that is worth considering, this hook should add all suitable
vector sizes to @var{sizes}, in order of decreasing preference. The first
one should be the size of @code{TARGET_VECTORIZE_PREFERRED_SIMD_MODE}.
+If @var{all} is true, add suitable vector sizes even when they are generally
+not expected to be worthwhile.
The hook does not need to do anything if the vector returned by
@code{TARGET_VECTORIZE_PREFERRED_SIMD_MODE} is the only one relevant
@@ -6654,7 +6661,7 @@ two areas of memory, or to set, clear or store to memory, for example
when copying a @code{struct}. The @code{by_pieces} infrastructure
implements such memory operations as a sequence of load, store or move
insns. Alternate strategies are to expand the
-@code{movmem} or @code{setmem} optabs, to emit a library call, or to emit
+@code{cpymem} or @code{setmem} optabs, to emit a library call, or to emit
unit-by-unit, loop-based operations.
This target hook should return true if, for a memory operation with a
@@ -6673,7 +6680,7 @@ optimized for speed rather than size.
Returning true for higher values of @var{size} can improve code generation
for speed if the target does not provide an implementation of the
-@code{movmem} or @code{setmem} standard names, if the @code{movmem} or
+@code{cpymem} or @code{setmem} standard names, if the @code{cpymem} or
@code{setmem} implementation would be more expensive than a sequence of
insns, or if the overhead of a library call would dominate that of
the body of the memory operation.
@@ -11603,6 +11610,14 @@ function version at run-time for a given set of function versions.
body must be generated.
@end deftypefn
+@deftypefn {Target Hook} bool TARGET_PREDICT_DOLOOP_P (struct loop *@var{loop})
+Return true if we can predict it is possible to use a low-overhead loop
+for a particular loop. The parameter @var{loop} is a pointer to the loop.
+This target hook is required only when the target supports low-overhead
+loops, and will help ivopts to make some decisions.
+The default version of this hook returns false.
+@end deftypefn
+
@deftypefn {Target Hook} bool TARGET_CAN_USE_DOLOOP_P (const widest_int @var{&iterations}, const widest_int @var{&iterations_max}, unsigned int @var{loop_depth}, bool @var{entered_at_top})
Return true if it is possible to use low-overhead loops (@code{doloop_end}
and @code{doloop_begin}) for a particular loop. @var{iterations} gives the
diff --git a/gcc/doc/tm.texi.in b/gcc/doc/tm.texi.in
index fe1194e..b4d57b8 100644
--- a/gcc/doc/tm.texi.in
+++ b/gcc/doc/tm.texi.in
@@ -3991,6 +3991,8 @@ macro, a reasonable default is used.
@hook TARGET_LIBC_HAS_FUNCTION
+@hook TARGET_LIBC_HAS_FAST_FUNCTION
+
@defmac NEXT_OBJC_RUNTIME
Set this macro to 1 to use the "NeXT" Objective-C message sending conventions
by default. This calling convention involves passing the object, the selector
@@ -7942,6 +7944,8 @@ to by @var{ce_info}.
@hook TARGET_GENERATE_VERSION_DISPATCHER_BODY
+@hook TARGET_PREDICT_DOLOOP_P
+
@hook TARGET_CAN_USE_DOLOOP_P
@hook TARGET_INVALID_WITHIN_DOLOOP
diff --git a/gcc/dojump.c b/gcc/dojump.c
index 8626689..bac37a3 100644
--- a/gcc/dojump.c
+++ b/gcc/dojump.c
@@ -668,8 +668,6 @@ do_jump_by_parts_greater_rtx (scalar_int_mode mode, int unsignedp, rtx op0,
code = LE;
if_true_label = if_false_label;
if_false_label = drop_through_label;
- drop_through_if_true = false;
- drop_through_if_false = true;
prob = prob.invert ();
}
diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c
index 5b1a32b..2c4cc6c 100644
--- a/gcc/dwarf2out.c
+++ b/gcc/dwarf2out.c
@@ -1115,7 +1115,7 @@ dwarf2out_begin_prologue (unsigned int line ATTRIBUTE_UNUSED,
function anymore. */
if (personality && current_unit_personality != personality)
sorry ("multiple EH personalities are supported only with assemblers "
- "supporting .cfi_personality directive");
+ "supporting %<.cfi_personality%> directive");
}
}
@@ -8576,11 +8576,12 @@ break_out_comdat_types (dw_die_ref die)
/* Break out nested types into their own type units. */
break_out_comdat_types (c);
- /* Create a new type unit DIE as the root for the new tree, and
- add it to the list of comdat types. */
+ /* Create a new type unit DIE as the root for the new tree. */
unit = new_die (DW_TAG_type_unit, NULL, NULL);
add_AT_unsigned (unit, DW_AT_language,
get_AT_unsigned (comp_unit_die (), DW_AT_language));
+
+ /* Add the new unit's type DIE into the comdat type list. */
type_node = ggc_cleared_alloc<comdat_type_node> ();
type_node->root_die = unit;
type_node->next = comdat_type_list;
@@ -11195,7 +11196,8 @@ add_top_level_skeleton_die_attrs (dw_die_ref die)
if (comp_dir != NULL)
add_skeleton_AT_string (die, DW_AT_comp_dir, comp_dir);
add_AT_pubnames (die);
- add_AT_lineptr (die, dwarf_AT (DW_AT_addr_base), debug_addr_section_label);
+ if (addr_index_table != NULL && addr_index_table->size () > 0)
+ add_AT_lineptr (die, dwarf_AT (DW_AT_addr_base), debug_addr_section_label);
}
/* Output skeleton debug sections that point to the dwo file. */
@@ -14509,11 +14511,10 @@ const_ok_for_output_1 (rtx rtl)
"non-delegitimized UNSPEC %s (%d) found in variable location",
((XINT (rtl, 1) >= 0 && XINT (rtl, 1) < NUM_UNSPEC_VALUES)
? unspec_strings[XINT (rtl, 1)] : "unknown"),
- XINT (rtl, 1));
#else
"non-delegitimized UNSPEC %d found in variable location",
- XINT (rtl, 1));
#endif
+ XINT (rtl, 1));
expansion_failed (NULL_TREE, rtl,
"UNSPEC hasn't been delegitimized.\n");
return false;
@@ -17906,6 +17907,8 @@ resolve_args_picking_1 (dw_loc_descr_ref loc, unsigned initial_frame_offset,
case DW_OP_push_object_address:
case DW_OP_call_frame_cfa:
case DW_OP_GNU_variable_value:
+ case DW_OP_GNU_addr_index:
+ case DW_OP_GNU_const_index:
++frame_offset_;
break;
@@ -20843,6 +20846,7 @@ add_scalar_info (dw_die_ref die, enum dwarf_attribute attr, tree value,
if (decl_die != NULL)
{
if (get_AT (decl_die, DW_AT_location)
+ || get_AT (decl_die, DW_AT_data_member_location)
|| get_AT (decl_die, DW_AT_const_value))
{
add_AT_die_ref (die, attr, decl_die);
@@ -21848,8 +21852,8 @@ gen_array_type_die (tree type, dw_die_ref context_die)
/* Emit DW_TAG_string_type for Fortran character types (with kind 1 only, as
DW_TAG_string_type doesn't have DW_AT_type attribute). */
- if (TYPE_STRING_FLAG (type)
- && TREE_CODE (type) == ARRAY_TYPE
+ if (TREE_CODE (type) == ARRAY_TYPE
+ && TYPE_STRING_FLAG (type)
&& is_fortran ()
&& TYPE_MODE (TREE_TYPE (type)) == TYPE_MODE (char_type_node))
{
@@ -25161,19 +25165,20 @@ gen_member_die (tree type, dw_die_ref context_die)
context_die);
}
- /* Now output info about the data members and type members. */
+ /* Now output info about the members. */
for (member = TYPE_FIELDS (type); member; member = DECL_CHAIN (member))
{
+ /* Ignore clones. */
+ if (DECL_ABSTRACT_ORIGIN (member))
+ continue;
+
struct vlr_context vlr_ctx = { type, NULL_TREE };
bool static_inline_p
- = (TREE_STATIC (member)
+ = (VAR_P (member)
+ && TREE_STATIC (member)
&& (lang_hooks.decls.decl_dwarf_attribute (member, DW_AT_inline)
!= -1));
- /* Ignore clones. */
- if (DECL_ABSTRACT_ORIGIN (member))
- continue;
-
/* If we thought we were generating minimal debug info for TYPE
and then changed our minds, some of the member declarations
may have already been defined. Don't define them again, but
@@ -25183,11 +25188,14 @@ gen_member_die (tree type, dw_die_ref context_die)
{
/* Handle inline static data members, which only have in-class
declarations. */
- dw_die_ref ref = NULL;
+ bool splice = true;
+
+ dw_die_ref ref = NULL;
if (child->die_tag == DW_TAG_variable
&& child->die_parent == comp_unit_die ())
{
ref = get_AT_ref (child, DW_AT_specification);
+
/* For C++17 inline static data members followed by redundant
out of class redeclaration, we might get here with
child being the DIE created for the out of class
@@ -25206,17 +25214,17 @@ gen_member_die (tree type, dw_die_ref context_die)
ref = NULL;
static_inline_p = false;
}
- }
- if (child->die_tag == DW_TAG_variable
- && child->die_parent == comp_unit_die ()
- && ref == NULL)
- {
- reparent_child (child, context_die);
- if (dwarf_version < 5)
- child->die_tag = DW_TAG_member;
+ if (!ref)
+ {
+ reparent_child (child, context_die);
+ if (dwarf_version < 5)
+ child->die_tag = DW_TAG_member;
+ splice = false;
+ }
}
- else
+
+ if (splice)
splice_child_die (context_die, child);
}
@@ -27670,11 +27678,8 @@ dwarf2out_inline_entry (tree block)
if (cur_line_info_table)
ied->view = cur_line_info_table->view;
- char label[MAX_ARTIFICIAL_LABEL_BYTES];
-
- ASM_GENERATE_INTERNAL_LABEL (label, BLOCK_INLINE_ENTRY_LABEL,
- BLOCK_NUMBER (block));
- ASM_OUTPUT_LABEL (asm_out_file, label);
+ ASM_OUTPUT_DEBUG_LABEL (asm_out_file, BLOCK_INLINE_ENTRY_LABEL,
+ BLOCK_NUMBER (block));
}
/* Called from finalize_size_functions for size functions so that their body
@@ -29105,6 +29110,30 @@ output_addr_table (void)
return;
switch_to_section (debug_addr_section);
+ /* GNU DebugFission https://gcc.gnu.org/wiki/DebugFission
+ which GCC uses to implement -gsplit-dwarf as DWARF GNU extension
+ before DWARF5, didn't have a header for .debug_addr units.
+ DWARF5 specifies a small header when address tables are used. */
+ if (dwarf_version >= 5)
+ {
+ unsigned int last_idx = 0;
+ unsigned long addrs_length;
+
+ addr_index_table->traverse_noresize
+ <unsigned int *, count_index_addrs> (&last_idx);
+ addrs_length = last_idx * DWARF2_ADDR_SIZE + 4;
+
+ if (DWARF_INITIAL_LENGTH_SIZE - DWARF_OFFSET_SIZE == 4)
+ dw2_asm_output_data (4, 0xffffffff,
+ "Escape value for 64-bit DWARF extension");
+ dw2_asm_output_data (DWARF_OFFSET_SIZE, addrs_length,
+ "Length of Address Unit");
+ dw2_asm_output_data (2, 5, "DWARF addr version");
+ dw2_asm_output_data (1, DWARF2_ADDR_SIZE, "Size of Address");
+ dw2_asm_output_data (1, 0, "Size of Segment Descriptor");
+ }
+ ASM_OUTPUT_LABEL (asm_out_file, debug_addr_section_label);
+
addr_index_table
->traverse_noresize<unsigned int *, output_addr_table_entry> (&index);
}
@@ -29416,9 +29445,16 @@ prune_unused_types_walk (dw_die_ref die)
break;
/* premark_used_variables marks external variables --- don't mark
- them here. */
+ them here. But function-local externals are always considered
+ used. */
if (get_AT (die, DW_AT_external))
- return;
+ {
+ for (c = die->die_parent; c; c = c->die_parent)
+ if (c->die_tag == DW_TAG_subprogram)
+ break;
+ if (!c)
+ return;
+ }
}
/* FALLTHROUGH */
@@ -31620,30 +31656,6 @@ dwarf2out_finish (const char *filename)
ranges_section_label);
}
- switch_to_section (debug_addr_section);
- /* GNU DebugFission https://gcc.gnu.org/wiki/DebugFission
- which GCC uses to implement -gsplit-dwarf as DWARF GNU extension
- before DWARF5, didn't have a header for .debug_addr units.
- DWARF5 specifies a small header when address tables are used. */
- if (dwarf_version >= 5)
- {
- unsigned int last_idx = 0;
- unsigned long addrs_length;
-
- addr_index_table->traverse_noresize
- <unsigned int *, count_index_addrs> (&last_idx);
- addrs_length = last_idx * DWARF2_ADDR_SIZE + 4;
-
- if (DWARF_INITIAL_LENGTH_SIZE - DWARF_OFFSET_SIZE == 4)
- dw2_asm_output_data (4, 0xffffffff,
- "Escape value for 64-bit DWARF extension");
- dw2_asm_output_data (DWARF_OFFSET_SIZE, addrs_length,
- "Length of Address Unit");
- dw2_asm_output_data (2, 5, "DWARF addr version");
- dw2_asm_output_data (1, DWARF2_ADDR_SIZE, "Size of Address");
- dw2_asm_output_data (1, 0, "Size of Segment Descriptor");
- }
- ASM_OUTPUT_LABEL (asm_out_file, debug_addr_section_label);
output_addr_table ();
}
diff --git a/gcc/early-remat.c b/gcc/early-remat.c
index 122891c..0396f16 100644
--- a/gcc/early-remat.c
+++ b/gcc/early-remat.c
@@ -1123,7 +1123,6 @@ early_remat::record_equiv_candidates (unsigned int cand1_index,
ec->representative = cand1_index;
cand1->equiv_class = ec;
}
- cand1 = &m_candidates[ec->representative];
cand2->equiv_class = ec;
bitmap_set_bit (ec->members, cand2_index);
if (cand2_index > ec->representative)
diff --git a/gcc/edit-context.c b/gcc/edit-context.c
index d3246ab..93d1066 100644
--- a/gcc/edit-context.c
+++ b/gcc/edit-context.c
@@ -1639,7 +1639,7 @@ static void
test_applying_fixits_unreadable_file ()
{
const char *filename = "this-does-not-exist.txt";
- line_table_test ltt ();
+ line_table_test ltt;
linemap_add (line_table, LC_ENTER, false, filename, 1);
location_t loc = linemap_position_for_column (line_table, 1);
@@ -1670,7 +1670,7 @@ test_applying_fixits_line_out_of_range ()
const char *old_content = "One-liner file\n";
temp_source_file tmp (SELFTEST_LOCATION, ".txt", old_content);
const char *filename = tmp.get_filename ();
- line_table_test ltt ();
+ line_table_test ltt;
linemap_add (line_table, LC_ENTER, false, filename, 2);
/* Try to insert a string in line 2. */
diff --git a/gcc/emit-rtl.c b/gcc/emit-rtl.c
index 15dffa5..e265fa6 100644
--- a/gcc/emit-rtl.c
+++ b/gcc/emit-rtl.c
@@ -61,6 +61,9 @@ along with GCC; see the file COPYING3. If not see
#include "opts.h"
#include "predict.h"
#include "rtx-vector-builder.h"
+#include "gimple.h"
+#include "gimple-ssa.h"
+#include "gimplify.h"
struct target_rtl default_target_rtl;
#if SWITCHABLE_TARGET
@@ -2128,6 +2131,27 @@ set_mem_attributes_minus_bitpos (rtx ref, tree t, int objectp,
apply_bitpos = bitpos;
}
+ /* If this is a reference based on a partitioned decl replace the
+ base with a MEM_REF of the pointer representative we created
+ during stack slot partitioning. */
+ if (attrs.expr
+ && VAR_P (base)
+ && ! is_global_var (base)
+ && cfun->gimple_df->decls_to_pointers != NULL)
+ {
+ tree *namep = cfun->gimple_df->decls_to_pointers->get (base);
+ if (namep)
+ {
+ attrs.expr = unshare_expr (attrs.expr);
+ tree *orig_base = &attrs.expr;
+ while (handled_component_p (*orig_base))
+ orig_base = &TREE_OPERAND (*orig_base, 0);
+ tree aptrt = reference_alias_ptr_type (*orig_base);
+ *orig_base = build2 (MEM_REF, TREE_TYPE (*orig_base), *namep,
+ build_int_cst (aptrt, 0));
+ }
+ }
+
/* Compute the alignment. */
unsigned int obj_align;
unsigned HOST_WIDE_INT obj_bitpos;
@@ -3993,7 +4017,7 @@ try_split (rtx pat, rtx_insn *trial, int last)
before = PREV_INSN (trial);
after = NEXT_INSN (trial);
- tem = emit_insn_after_setloc (seq, trial, INSN_LOCATION (trial));
+ emit_insn_after_setloc (seq, trial, INSN_LOCATION (trial));
delete_insn (trial);
diff --git a/gcc/except.c b/gcc/except.c
index e760c44..edaeeb4 100644
--- a/gcc/except.c
+++ b/gcc/except.c
@@ -3412,7 +3412,7 @@ verify_eh_tree (struct function *fun)
count_r++;
else
{
- error ("region_array is corrupted for region %i", r->index);
+ error ("%<region_array%> is corrupted for region %i", r->index);
err = true;
}
}
@@ -3425,7 +3425,7 @@ verify_eh_tree (struct function *fun)
count_lp++;
else
{
- error ("lp_array is corrupted for lp %i", lp->index);
+ error ("%<lp_array%> is corrupted for lp %i", lp->index);
err = true;
}
}
@@ -3437,7 +3437,7 @@ verify_eh_tree (struct function *fun)
{
if ((*fun->eh->region_array)[r->index] != r)
{
- error ("region_array is corrupted for region %i", r->index);
+ error ("%<region_array%> is corrupted for region %i", r->index);
err = true;
}
if (r->outer != outer)
@@ -3456,7 +3456,7 @@ verify_eh_tree (struct function *fun)
{
if ((*fun->eh->lp_array)[lp->index] != lp)
{
- error ("lp_array is corrupted for lp %i", lp->index);
+ error ("%<lp_array%> is corrupted for lp %i", lp->index);
err = true;
}
if (lp->region != r)
@@ -3493,19 +3493,19 @@ verify_eh_tree (struct function *fun)
}
if (count_r != nvisited_r)
{
- error ("region_array does not match region_tree");
+ error ("%<region_array%> does not match %<region_tree%>");
err = true;
}
if (count_lp != nvisited_lp)
{
- error ("lp_array does not match region_tree");
+ error ("%<lp_array%> does not match %<region_tree%>");
err = true;
}
if (err)
{
dump_eh_tree (stderr, fun);
- internal_error ("verify_eh_tree failed");
+ internal_error ("%qs failed", __func__);
}
}
diff --git a/gcc/expr.c b/gcc/expr.c
index fa15b7e..4acf250 100644
--- a/gcc/expr.c
+++ b/gcc/expr.c
@@ -73,7 +73,7 @@ along with GCC; see the file COPYING3. If not see
int cse_not_expected;
static bool block_move_libcall_safe_for_call_parm (void);
-static bool emit_block_move_via_movmem (rtx, rtx, rtx, unsigned, unsigned, HOST_WIDE_INT,
+static bool emit_block_move_via_cpymem (rtx, rtx, rtx, unsigned, unsigned, HOST_WIDE_INT,
unsigned HOST_WIDE_INT, unsigned HOST_WIDE_INT,
unsigned HOST_WIDE_INT);
static void emit_block_move_via_loop (rtx, rtx, rtx, unsigned);
@@ -1561,12 +1561,16 @@ emit_block_move_hints (rtx x, rtx y, rtx size, enum block_op_methods method,
unsigned int expected_align, HOST_WIDE_INT expected_size,
unsigned HOST_WIDE_INT min_size,
unsigned HOST_WIDE_INT max_size,
- unsigned HOST_WIDE_INT probable_max_size)
+ unsigned HOST_WIDE_INT probable_max_size,
+ bool bail_out_libcall, bool *is_move_done)
{
int may_use_call;
rtx retval = 0;
unsigned int align;
+ if (is_move_done)
+ *is_move_done = true;
+
gcc_assert (size);
if (CONST_INT_P (size) && INTVAL (size) == 0)
return 0;
@@ -1620,7 +1624,7 @@ emit_block_move_hints (rtx x, rtx y, rtx size, enum block_op_methods method,
if (CONST_INT_P (size) && can_move_by_pieces (INTVAL (size), align))
move_by_pieces (x, y, INTVAL (size), align, RETURN_BEGIN);
- else if (emit_block_move_via_movmem (x, y, size, align,
+ else if (emit_block_move_via_cpymem (x, y, size, align,
expected_align, expected_size,
min_size, max_size, probable_max_size))
;
@@ -1628,6 +1632,13 @@ emit_block_move_hints (rtx x, rtx y, rtx size, enum block_op_methods method,
&& ADDR_SPACE_GENERIC_P (MEM_ADDR_SPACE (x))
&& ADDR_SPACE_GENERIC_P (MEM_ADDR_SPACE (y)))
{
+ if (bail_out_libcall)
+ {
+ if (is_move_done)
+ *is_move_done = false;
+ return retval;
+ }
+
if (may_use_call < 0)
return pc_rtx;
@@ -1711,11 +1722,11 @@ block_move_libcall_safe_for_call_parm (void)
return true;
}
-/* A subroutine of emit_block_move. Expand a movmem pattern;
+/* A subroutine of emit_block_move. Expand a cpymem pattern;
return true if successful. */
static bool
-emit_block_move_via_movmem (rtx x, rtx y, rtx size, unsigned int align,
+emit_block_move_via_cpymem (rtx x, rtx y, rtx size, unsigned int align,
unsigned int expected_align, HOST_WIDE_INT expected_size,
unsigned HOST_WIDE_INT min_size,
unsigned HOST_WIDE_INT max_size,
@@ -1744,7 +1755,7 @@ emit_block_move_via_movmem (rtx x, rtx y, rtx size, unsigned int align,
FOR_EACH_MODE_IN_CLASS (mode_iter, MODE_INT)
{
scalar_int_mode mode = mode_iter.require ();
- enum insn_code code = direct_optab_handler (movmem_optab, mode);
+ enum insn_code code = direct_optab_handler (cpymem_optab, mode);
if (code != CODE_FOR_nothing
/* We don't need MODE to be narrower than BITS_PER_HOST_WIDE_INT
@@ -10882,12 +10893,12 @@ expand_expr_real_1 (tree exp, rtx target, machine_mode tmode,
if (MEM_P (op0) && REG_P (XEXP (op0, 0)))
mark_reg_pointer (XEXP (op0, 0), MEM_ALIGN (op0));
- /* If the result has a record type and the extraction is done in
+ /* If the result has aggregate type and the extraction is done in
an integral mode, then the field may be not aligned on a byte
boundary; in this case, if it has reverse storage order, it
needs to be extracted as a scalar field with reverse storage
order and put back into memory order afterwards. */
- if (TREE_CODE (type) == RECORD_TYPE
+ if (AGGREGATE_TYPE_P (type)
&& GET_MODE_CLASS (ext_mode) == MODE_INT)
reversep = TYPE_REVERSE_STORAGE_ORDER (type);
@@ -10897,13 +10908,13 @@ expand_expr_real_1 (tree exp, rtx target, machine_mode tmode,
? NULL_RTX : target),
ext_mode, ext_mode, reversep, alt_rtl);
- /* If the result has a record type and the mode of OP0 is an
+ /* If the result has aggregate type and the mode of OP0 is an
integral mode then, if BITSIZE is narrower than this mode
and this is for big-endian data, we must put the field
into the high-order bits. And we must also put it back
into memory order if it has been previously reversed. */
scalar_int_mode op0_mode;
- if (TREE_CODE (type) == RECORD_TYPE
+ if (AGGREGATE_TYPE_P (type)
&& is_int_mode (GET_MODE (op0), &op0_mode))
{
HOST_WIDE_INT size = GET_MODE_BITSIZE (op0_mode);
diff --git a/gcc/expr.h b/gcc/expr.h
index 17c3962..6eb70bf 100644
--- a/gcc/expr.h
+++ b/gcc/expr.h
@@ -114,7 +114,9 @@ extern rtx emit_block_move_hints (rtx, rtx, rtx, enum block_op_methods,
unsigned int, HOST_WIDE_INT,
unsigned HOST_WIDE_INT,
unsigned HOST_WIDE_INT,
- unsigned HOST_WIDE_INT);
+ unsigned HOST_WIDE_INT,
+ bool bail_out_libcall = false,
+ bool *is_move_done = NULL);
extern rtx emit_block_cmp_hints (rtx, rtx, rtx, tree, rtx, bool,
by_pieces_constfn, void *);
extern bool emit_storent_insn (rtx to, rtx from);
diff --git a/gcc/fold-const.c b/gcc/fold-const.c
index c425772..0ca472d 100644
--- a/gcc/fold-const.c
+++ b/gcc/fold-const.c
@@ -3508,10 +3508,10 @@ operand_equal_p (const_tree arg0, const_tree arg1, unsigned int flags)
positives for GENERIC. */
|| (c0->index
&& (TREE_CODE (c0->index) != INTEGER_CST
- || !compare_tree_int (c0->index, i)))
+ || compare_tree_int (c0->index, i)))
|| (c1->index
&& (TREE_CODE (c1->index) != INTEGER_CST
- || !compare_tree_int (c1->index, i))))
+ || compare_tree_int (c1->index, i))))
return 0;
}
return 1;
@@ -6475,8 +6475,12 @@ extract_muldiv_1 (tree t, tree c, enum tree_code code, tree wide_type,
apply the distributive law to commute the multiply and addition
if the multiplication of the constants doesn't overflow
and overflow is defined. With undefined overflow
- op0 * c might overflow, while (op0 + orig_op1) * c doesn't. */
- if (code == MULT_EXPR && TYPE_OVERFLOW_WRAPS (ctype))
+ op0 * c might overflow, while (op0 + orig_op1) * c doesn't.
+ But fold_plusminus_mult_expr would factor back any power-of-two
+ value so do not distribute in the first place in this case. */
+ if (code == MULT_EXPR
+ && TYPE_OVERFLOW_WRAPS (ctype)
+ && !(tree_fits_shwi_p (c) && pow2p_hwi (absu_hwi (tree_to_shwi (c)))))
return fold_build2 (tcode, ctype,
fold_build2 (code, ctype,
fold_convert (ctype, op0),
@@ -6718,15 +6722,21 @@ fold_real_zero_addition_p (const_tree type, const_tree addend, int negate)
return false;
/* Don't allow the fold with -fsignaling-nans. */
- if (HONOR_SNANS (element_mode (type)))
+ if (HONOR_SNANS (type))
return false;
/* Allow the fold if zeros aren't signed, or their sign isn't important. */
- if (!HONOR_SIGNED_ZEROS (element_mode (type)))
+ if (!HONOR_SIGNED_ZEROS (type))
return true;
+ /* There is no case that is safe for all rounding modes. */
+ if (HONOR_SIGN_DEPENDENT_ROUNDING (type))
+ return false;
+
/* In a vector or complex, we would need to check the sign of all zeros. */
- if (TREE_CODE (addend) != REAL_CST)
+ if (TREE_CODE (addend) == VECTOR_CST)
+ addend = uniform_vector_p (addend);
+ if (!addend || TREE_CODE (addend) != REAL_CST)
return false;
/* Treat x + -0 as x - 0 and x - -0 as x + 0. */
@@ -6735,9 +6745,8 @@ fold_real_zero_addition_p (const_tree type, const_tree addend, int negate)
/* The mode has signed zeros, and we have to honor their sign.
In this situation, there is only one case we can return true for.
- X - 0 is the same as X unless rounding towards -infinity is
- supported. */
- return negate && !HONOR_SIGN_DEPENDENT_ROUNDING (element_mode (type));
+ X - 0 is the same as X with default rounding. */
+ return negate;
}
/* Subroutine of match.pd that optimizes comparisons of a division by
@@ -7124,14 +7133,13 @@ fold_plusminus_mult_expr (location_t loc, enum tree_code code, tree type,
/* No identical multiplicands; see if we can find a common
power-of-two factor in non-power-of-two multiplies. This
can help in multi-dimensional array access. */
- else if (tree_fits_shwi_p (arg01)
- && tree_fits_shwi_p (arg11))
+ else if (tree_fits_shwi_p (arg01) && tree_fits_shwi_p (arg11))
{
- HOST_WIDE_INT int01, int11, tmp;
+ HOST_WIDE_INT int01 = tree_to_shwi (arg01);
+ HOST_WIDE_INT int11 = tree_to_shwi (arg11);
+ HOST_WIDE_INT tmp;
bool swap = false;
tree maybe_same;
- int01 = tree_to_shwi (arg01);
- int11 = tree_to_shwi (arg11);
/* Move min of absolute values to int11. */
if (absu_hwi (int01) < absu_hwi (int11))
@@ -7144,7 +7152,10 @@ fold_plusminus_mult_expr (location_t loc, enum tree_code code, tree type,
else
maybe_same = arg11;
- if (exact_log2 (absu_hwi (int11)) > 0 && int01 % int11 == 0
+ const unsigned HOST_WIDE_INT factor = absu_hwi (int11);
+ if (factor > 1
+ && pow2p_hwi (factor)
+ && (int01 & (factor - 1)) == 0
/* The remainder should not be a constant, otherwise we
end up folding i * 4 + 2 to (i * 2 + 1) * 2 which has
increased the number of multiplications necessary. */
@@ -9015,7 +9026,7 @@ vec_cst_ctor_to_array (tree arg, unsigned int nelts, tree *elts)
selector. Return the folded VECTOR_CST or CONSTRUCTOR if successful,
NULL_TREE otherwise. */
-static tree
+tree
fold_vec_perm (tree type, tree arg0, tree arg1, const vec_perm_indices &sel)
{
unsigned int i;
@@ -11763,7 +11774,10 @@ fold_ternary_loc (location_t loc, enum tree_code code, tree type,
return NULL_TREE;
case VEC_PERM_EXPR:
- if (TREE_CODE (arg2) == VECTOR_CST)
+ /* Perform constant folding of BIT_INSERT_EXPR. */
+ if (TREE_CODE (arg2) == VECTOR_CST
+ && TREE_CODE (op0) == VECTOR_CST
+ && TREE_CODE (op1) == VECTOR_CST)
{
/* Build a vector of integers from the tree mask. */
vec_perm_builder builder;
@@ -11774,61 +11788,7 @@ fold_ternary_loc (location_t loc, enum tree_code code, tree type,
poly_uint64 nelts = TYPE_VECTOR_SUBPARTS (type);
bool single_arg = (op0 == op1);
vec_perm_indices sel (builder, single_arg ? 1 : 2, nelts);
-
- /* Check for cases that fold to OP0 or OP1 in their original
- element order. */
- if (sel.series_p (0, 1, 0, 1))
- return op0;
- if (sel.series_p (0, 1, nelts, 1))
- return op1;
-
- if (!single_arg)
- {
- if (sel.all_from_input_p (0))
- op1 = op0;
- else if (sel.all_from_input_p (1))
- {
- op0 = op1;
- sel.rotate_inputs (1);
- }
- }
-
- if ((TREE_CODE (op0) == VECTOR_CST
- || TREE_CODE (op0) == CONSTRUCTOR)
- && (TREE_CODE (op1) == VECTOR_CST
- || TREE_CODE (op1) == CONSTRUCTOR))
- {
- tree t = fold_vec_perm (type, op0, op1, sel);
- if (t != NULL_TREE)
- return t;
- }
-
- bool changed = (op0 == op1 && !single_arg);
-
- /* Generate a canonical form of the selector. */
- if (arg2 == op2 && sel.encoding () != builder)
- {
- /* Some targets are deficient and fail to expand a single
- argument permutation while still allowing an equivalent
- 2-argument version. */
- if (sel.ninputs () == 2
- || can_vec_perm_const_p (TYPE_MODE (type), sel, false))
- op2 = vec_perm_indices_to_tree (TREE_TYPE (arg2), sel);
- else
- {
- vec_perm_indices sel2 (builder, 2, nelts);
- if (can_vec_perm_const_p (TYPE_MODE (type), sel2, false))
- op2 = vec_perm_indices_to_tree (TREE_TYPE (arg2), sel2);
- else
- /* Not directly supported with either encoding,
- so use the preferred form. */
- op2 = vec_perm_indices_to_tree (TREE_TYPE (arg2), sel);
- }
- changed = true;
- }
-
- if (changed)
- return build3_loc (loc, VEC_PERM_EXPR, type, op0, op1, op2);
+ return fold_vec_perm (type, op0, op1, sel);
}
return NULL_TREE;
@@ -13844,6 +13804,28 @@ fold_read_from_constant_string (tree exp)
return NULL;
}
+/* Folds a read from vector element at IDX of vector ARG. */
+
+tree
+fold_read_from_vector (tree arg, poly_uint64 idx)
+{
+ unsigned HOST_WIDE_INT i;
+ if (known_lt (idx, TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg)))
+ && known_ge (idx, 0u)
+ && idx.is_constant (&i))
+ {
+ if (TREE_CODE (arg) == VECTOR_CST)
+ return VECTOR_CST_ELT (arg, i);
+ else if (TREE_CODE (arg) == CONSTRUCTOR)
+ {
+ if (i >= CONSTRUCTOR_NELTS (arg))
+ return build_zero_cst (TREE_TYPE (TREE_TYPE (arg)));
+ return CONSTRUCTOR_ELT (arg, i)->value;
+ }
+ }
+ return NULL_TREE;
+}
+
/* Return the tree for neg (ARG0) when ARG0 is known to be either
an integer constant, real, or fixed-point constant.
diff --git a/gcc/fold-const.h b/gcc/fold-const.h
index 049fee9..2a69bf9 100644
--- a/gcc/fold-const.h
+++ b/gcc/fold-const.h
@@ -100,6 +100,10 @@ extern tree fold_bit_and_mask (tree, tree, enum tree_code,
tree, enum tree_code, tree, tree,
tree, enum tree_code, tree, tree, tree *);
extern tree fold_read_from_constant_string (tree);
+extern tree fold_read_from_vector (tree, poly_uint64);
+#if GCC_VEC_PERN_INDICES_H
+extern tree fold_vec_perm (tree, tree, tree, const vec_perm_indices &);
+#endif
extern bool wide_int_binop (wide_int &res, enum tree_code,
const wide_int &arg1, const wide_int &arg2,
signop, wi::overflow_type *);
diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog
index c910af4..a163a1d 100644
--- a/gcc/fortran/ChangeLog
+++ b/gcc/fortran/ChangeLog
@@ -1,8 +1,389 @@
+2019-07-03 Martin Liska <mliska@suse.cz>
+
+ * check.c (gfc_check_c_funloc): Remove
+ dead assignemts.
+ * decl.c (variable_decl): Likewise.
+ * resolve.c (resolve_typebound_function): Likewise.
+ * simplify.c (gfc_simplify_matmul): Likewise.
+ (gfc_simplify_scan): Likewise.
+ * trans-array.c (gfc_could_be_alias): Likewise.
+ * trans-common.c (add_equivalences): Likewise.
+ * trans-expr.c (trans_class_vptr_len_assignment): Likewise.
+ (gfc_trans_array_constructor_copy): Likewise.
+ (gfc_trans_assignment_1): Likewise.
+ * trans-intrinsic.c (conv_intrinsic_atomic_op): Likewise.
+ * trans-openmp.c (gfc_omp_finish_clause): Likewise.
+ * trans-types.c (gfc_get_array_descriptor_base): Likewise.
+ * trans.c (gfc_build_final_call): Likewise.
+
+2019-06-27 Steven G. Kargl <kargl@gcc.gnu.org>
+
+ PR fortran/90987
+ * gfortran.dg/common_1.f: new test.
+ * gfortran.dg/common_26.f90: Ditto.
+
+2019-06-26 Steven G. Kargl <kargl@gcc.gnu.org>
+
+ PR Fortran/90988
+ ChangeLog forgotten with revision 272667
+ * decl.c (access_attr_decl): Use temporary variable to reduce
+ unreadability of code. Normalize jumping to return.
+ (gfc_match_protected): Fix parsing error. Add comments to
+ explain code. Remove dead code.
+ (gfc_match_private): Use temporary variable to reduce unreadability
+ of code. Fix parsing error. Move code to test for blank PRIVATE.
+ Remove dead code.
+ (gfc_match_public): Move code to test for blank PUBLIC. Fix
+ parsing error. Remove dead code.
+
+2019-06-24 Jan Hubicka <jh@suse.cz>
+
+ * trans-expr.c (gfc_conv_substring): Check that
+ type is array or integer prior checking string flag.
+ (gfc_conv_string_parameter): Likewise.
+ * trans-openmp.c (gfc_omp_scalar_p): Likewise.
+ * trans.c (gfc_build_array_ref): Likewise.
+
+2019-06-22 Jerry DeLisle <jvdelisle@gcc.gnu.org>
+
+ PR fortran/89782
+ * io.c (gfc_resolve_dt): Check that internal units are not
+ character PARAMETER.
+
+2019-06-21 Steven G. Kargl <kargl@gcc.gnu.org>
+
+ PR fortran/67884
+ * resolve.c (deferred_requirements) : Check only the result variable.
+ (resolve_fl_procedure): Check deferred requirements on functions.
+
+2019-06-21 Steven G. Kargl <kargl@gcc.gnu.org>
+
+ PR fortran/51991
+ * decl.c (gfc_match_save): If SAVE was not seen, return MATCH_NO
+ instead issuing an error message and returning MATCH_ERROR.
+
+2019-06-20 Steven G. Kargl <kargl@gcc.gnu.org>
+
+ PR fortran/77632
+ * /decl.c (variable_decl): Mark a variable that is a target in pointer
+ initialization when in PROGRAM, MODULE, or SUBMODULE scope with an
+ implicit save.
+
+2019-06-20 Steven G. Kargl <kargl@gcc.gnu.org>
+
+ PR fortran/86587
+ * symbol.c (verify_bind_c_derived_type): Remove erroneous error
+ checking for BIND(C) and PRIVATE attributes.
+
+2019-06-20 Thomas Koenig <tkoenig@gcc.gnu.org>
+
+ PR fortran/90937
+ * trans-types.c (get_formal_from_actual_arglist): Get symbol from
+ current namespace so it will be freed later. If symbol is of type
+ character, get an empty character length.
+
+2019-06-19 Steven G. Kargl <kargl@gcc.gnu.org>
+
+ PR fortran/69499
+ * match.c (gfc_match_select_type): SELECT TYPE is an executable
+ statement, and cannot appear in MODULE or SUBMODULE scope.
+
+2019-06-19 Steven G. Kargl <kargl@gcc.gnu.org>
+
+ PR fortran/69398
+ * decl.c (attr_decl): Check for duplicate DIMENSION attribute for a
+ CLASS entity.
+
+2019-06-19 Steven G. Kargl <kargl@gcc.gnu.org>
+
+ PR fortran/87907
+ * resolve.c (resolve_contained_fntype): Do not dereference a NULL
+ pointer.
+
+2019-06-19 Jim MacArthur <jim.macarthur@codethink.co.uk>
+ Mark Eggleston <mark.eggleston@codethink.com>
+
+ PR fortran/89103
+ * gfortran.texi: Add -fdec-blank-format-item
+ * invoke.texi: Add option to list of options.
+ * invoke.texi: Add to section on Commas in FORMAT specifications.
+ * io.c (check_format): At FMT_RPAREN goto finished if
+ -fdec-blank-format-item otherwise set error string.
+ * lang.opt: Add new option.
+ * options.c (set_dec_flags): Add SET_BITFLAG for
+ flag_dec_format_defaults.
+
+2019-06-18 Julian Brown <julian@codesourcery.com>
+
+ PR fortran/90921
+ * trans-decl.c (finish_oacc_declare): Reset module_oacc_clauses
+ before scanning each namespace.
+
+2019-06-18 Thomas Schwinge <thomas@codesourcery.com>
+
+ PR fortran/85221
+ * trans-decl.c (add_attributes_to_decl): Handle OpenACC 'declare'
+ directive.
+
+2019-06-16 Thomas Koenig <tkoenig@gcc.gnu.org>
+
+ * dump_parse_tree (debug): Add verison for formal arglist.
+ Do not crash when a gfc_expr is NULL.
+
+2019-06-15 Steven G. Kargl <kargl@gcc.gnu.org>
+
+ * decl.c (gfc_match_derived_decl): Dummy argument cannot be a derived
+ type.
+
+2019-06-14 Steven G. Kargl <kargl@gcc.gnu.org>
+
+ * arith.c (arith_power): Rework overflow of an integer to an integer
+ exponent.
+
+2019-06-14 Harald Anlauf <anlauf@gmx.de>
+
+ PR fortran/90577
+ PR fortran/90578
+ * trans-intrinsic.c (gfc_conv_intrinsic_shift): Properly
+ distinguish logical/arithmetic shifts.
+ * intrinsic.texi: Update documentation for SHIFTR/SHIFTL/SHIFTA
+ (Fortran 2008) and LSHIFT/RSHIFT (GNU extensions).
+
+2019-06-14 Steven G. Kargl <kargl@gcc.gnu.org>
+
+ PR fortran/89646
+ * dependency.c (gfc_check_argument_var_dependency): Suppress spurious
+ warnings by comparing variable names.
+
+2019-06-13 Steven G. Kargl <kargl@gcc.gnu.org>
+
+ PR fortran/68544
+ * resolve.c (is_dt_name): New function to compare symbol name against
+ list of derived types.
+ (resolve_actual_arglist): Use it to find wrong code.
+
+2019-06-13 Steven G. Kargl <kargl@gcc.gnu.org>
+
+ PR fortran/89344
+ * expr.c (gfc_check_vardef_context): Check for INTENT(IN) variable
+ in SELECT TYPE construct.
+
+2019-06-13 Steven G. Kargl <kargl@gcc.gnu.org>
+
+ PR fortran/88810
+ * dependency.c (gfc_dep_resolver): Re-arrange code to make the logic
+ a bit more transparent. Fix 2 nearby formatting issues.
+
+2019-06-13 Jakub Jelinek <jakub@redhat.com>
+
+ * io.c (check_format): Use G_(...) instead of _(...) for error values,
+ append " in format string at %L" to all strings but unexpected_element,
+ use error as gfc_error formating string instead of
+ "%s in format string at %L". Formatting fixes.
+
+2019-06-12 Steven G. Kargl <kargl@gcc.gnu.org>
+
+ * gfortran.h (gfc_free_dt_list): Remove prototype.
+
+2019-06-12 Steven G. Kargl <kargl@gcc.gnu.org>
+
+ PR fortran/90002
+ * array.c (gfc_free_array_spec): When freeing an array-spec, avoid
+ an ICE for assumed-shape coarrays.
+
+2019-06-08 Paul Thomas <pault@gcc.gnu.org>
+
+ PR fortran/90786
+ * trans-expr.c (pointer_assignment_is_proc_pointer) Remove as
+ it is very simple and only called from one place.
+ (gfc_trans_pointer_assignment): Rename non_proc_pointer_assign
+ as non_proc_ptr_assign. Assign to it directly, rather than call
+ to above, deleted function and use gfc_expr_attr instead of
+ only checking the reference chain.
+
+2019-06-08 Thomas Koenig <tkoenig@gcc.gnu.org>
+ Tomáš Trnka <trnka@scm.com>
+
+ PR fortran/90744
+ * trans-types.c (get_formal_from_actual_arglist): Unset typespec
+ flags which make no sense for procedures without explicit
+ interface.
+
+2019-06-02 Thomas Koenig <tkoenig@gcc.gnu.org>
+
+ PR fortran/90539
+ * trans-expr.c (gfc_conv_subref_array_arg): If the size of the
+ expression can be determined to be one, treat it as contiguous.
+ Set likelyhood of presence of an actual argument according to
+ PRED_FORTRAN_ABSENT_DUMMY and likelyhood of being contiguous
+ according to PRED_FORTRAN_CONTIGUOUS.
+
+2019-05-30 Thomas Koenig <tkoenig@gcc.gnu.org>
+
+ * gfc-internals.texi (Translating to GENERIC): New chapter.
+
+2019-05-30 Marek Polacek <polacek@redhat.com>
+
+ * lang.opt (ftail-call-workaround): Fix a typo.
+
+2019-05-30 Jakub Jelinek <jakub@redhat.com>
+
+ * lang.opt (ftail-call-workaround=): Fix a typo - lenghts to lengths.
+
+2019-05-29 Thomas Koenig <tkoenig@gcc.gnu.org>
+
+ PR fortran/90539
+ * gfortran.h (gfc_has_dimen_vector_ref): Add prototype.
+ * trans.h (gfc_conv_subref_array_arg): Add argument check_contiguous.
+ (gfc_conv_is_contiguous_expr): Add prototype.
+ * frontend-passes.c (has_dimen_vector_ref): Remove prototype,
+ rename to
+ (gfc_has_dimen_vector_ref): New function name.
+ (matmul_temp_args): Use gfc_has_dimen_vector_ref.
+ (inline_matmul_assign): Likewise.
+ * trans-array.c (gfc_conv_array_parameter): Also check for absence
+ of a vector subscript before calling gfc_conv_subref_array_arg.
+ Pass additional argument to gfc_conv_subref_array_arg.
+ * trans-expr.c (gfc_conv_subref_array_arg): Add argument
+ check_contiguous. If that is true, check if the argument
+ is contiguous and do not repack in that case.
+ * trans-intrinsic.c (gfc_conv_intrinsic_is_contiguous): Split
+ away most of the work into, and call
+ (gfc_conv_intrinsic_is_coniguous_expr): New function.
+
+2019-05-29 Jakub Jelinek <jakub@redhat.com>
+
+ PR fortran/90329
+ * lang.opt (fbroken-callers): Remove.
+ (ftail-call-workaround, ftail-call-workaround=): New options.
+ * gfortran.h (struct gfc_namespace): Add implicit_interface_calls.
+ * interface.c (gfc_procedure_use): Set implicit_interface_calls
+ for calls to implicit interface procedures.
+ * trans-decl.c (create_function_arglist): Use flag_tail_call_workaround
+ instead of flag_broken_callers. If it is not 2, also require
+ sym->ns->implicit_interface_calls.
+ * invoke.texi (fbroken-callers): Remove documentation.
+ (ftail-call-workaround, ftail-call-workaround=): Document.
+
+2019-05-26 Thomas Koenig <tkoenig@gcc.gnu.org>
+
+ PR fortran/90539
+ * trans-types.c (get_formal_from_actual_arglist): Set rank
+ and lower bound for assumed size arguments.
+
+2019-05-22 Andrew Stubbs <ams@codesourcery.com>
+
+ * trans-stmt.c (gfc_trans_critical): Use size_type_node for
+ gfor_fndecl_caf_lock and gfor_fndecl_caf_unlock calls.
+ (gfc_trans_allocate): Use size_type_node for gfor_fndecl_caf_sync_all
+ call.
+
+2019-05-22 Jeff Law <law@redhat.com>
+ Mark Eggleston <mark.eggleston@codethink.com>
+
+ PR fortran/89100
+ * gfortran.texi: Add Default widths for F, G and I format
+ descriptors to Extensions section.
+ * invoke.texi: Add -fdec-format-defaults
+ * io.c (check_format): Use default widths for i, f and g when
+ flag_dec_format_defaults is enabled.
+ * lang.opt: Add new option.
+ * options.c (set_dec_flags): Add SET_BITFLAG for
+ flag_dec_format_defaults.
+
+2019-05-21 Janne Blomqvist <jb@gcc.gnu.org>
+
+ PR libfortran/90038
+ * intrinsic.texi (EXECUTE_COMMAND_LINE): Explain new
+ wait=.false. implementation.
+
+2019-05-20 Mark Eggleston <markeggleston@codethink.com>
+
+ * gfortran.texi: Remove reference to the ASSIGN statement, capitalise
+ complex, state that padding is with spaces and modify the Hollerith
+ constant examples.
+
+2019-05-19 Paul Thomas <pault@gcc.gnu.org>
+
+ PR fortran/90498
+ * trans-stmt.c (trans_associate_var) Do not use the saved
+ descriptor if the expression is a COMPONENT_REF.
+
+2019-05-19 Thomas Koenig <tkoenig@gcc.gnu.org>
+
+ PR fortran/90329
+ * invoke.texi: Document -fbroken-callers.
+ * lang.opt: Add -fbroken-callers.
+ * trans-decl.c (create_function_arglist): Only set
+ DECL_HIDDEN_STRING_LENGTH if flag_broken_callers is set.
+
+2019-05-17 Thomas Schwinge <thomas@codesourcery.com>
+
+ PR fortran/89433
+ * f95-lang.c (gfc_attribute_table): Set min_len to -1 for "omp
+ declare target".
+ * trans-decl.c (add_attributes_to_decl): Refer to OpenACC
+ 'routine' clauses from "omp declare target" attribute.
+
+2019-05-16 Martin Sebor <msebor@redhat.com>
+
+ * gfortranspec.c (append_arg): Spell out the word "argument."
+
+2019-05-16 Jakub Jelinek <jakub@redhat.com>
+
+ PR fortran/90329
+ * trans-decl.c (create_function_arglist): Set
+ DECL_HIDDEN_STRING_LENGTH on hidden string length PARM_DECLs if
+ len is constant.
+
+2019-05-15 Janne Blomqvist <jb@gcc.gnu.org>
+
+ * parse.c (gfc_parse_file): Remove translation string markers.
+
+2019-05-12 Janne Blomqvist <jb@gcc.gnu.org>
+
+ * dump-parse-tree.c (get_c_type_name): Use macros for complex type
+ names.
+ * parse.c (gfc_parse_file): Define complex macros, add CPP support
+ when printing C prototypes.
+
+2019-05-10 Thomas Koenig <tkoenig@gcc.gnu.org>
+
+ PR fortran/61968
+ * interface.c (compare_actual_formal): Do not create a vtab if
+ the actual argument is assumed type.
+
+2019-05-10 Paul Thomas <pault@gcc.gnu.org>
+
+ PR fortran/90093
+ * trans-decl.c (convert_CFI_desc): Test that the dummy is
+ present before doing any of the conversions.
+
+ PR fortran/90352
+ * decl.c (gfc_verify_c_interop_param): Restore the error for
+ charlen > 1 actual arguments passed to bind(C) procs.
+ Clean up trailing white space.
+
+ PR fortran/90355
+ * trans-array.c (gfc_trans_create_temp_array): Set the 'span'
+ field to the element length for all types.
+ (gfc_conv_expr_descriptor): The force_no_tmp flag is used to
+ prevent temporary creation, especially for substrings.
+ * trans-decl.c (gfc_trans_deferred_vars): Rather than assert
+ that the backend decl for the string length is non-null, use it
+ as a condition before calling gfc_trans_vla_type_sizes.
+ * trans-expr.c (gfc_conv_gfc_desc_to_cfi_desc): 'force_no_tmp'
+ is set before calling gfc_conv_expr_descriptor.
+ * trans.c (get_array_span): Move the code for extracting 'span'
+ from gfc_build_array_ref to this function. This is specific to
+ descriptors that are component and indirect references.
+ * trans.h : Add the force_no_tmp flag bitfield to gfc_se.
+
2019-05-08 Thomas Koenig <tkoenig@gcc.gnu.org>
PR fortran/90351
PR fortran/90329
- * gfortran.dg/dump-parse-tree.c: Include version.h.
+ * dump-parse-tree.c: Include version.h.
(gfc_dump_external_c_prototypes): New function.
(get_c_type_name): Select "char" as a name for a simple char.
Adjust to handling external functions. Also handle complex.
diff --git a/gcc/fortran/arith.c b/gcc/fortran/arith.c
index f2d311c..a4f8795 100644
--- a/gcc/fortran/arith.c
+++ b/gcc/fortran/arith.c
@@ -848,8 +848,6 @@ arith_power (gfc_expr *op1, gfc_expr *op2, gfc_expr **resultp)
{
case BT_INTEGER:
{
- int power;
-
/* First, we simplify the cases of op1 == 1, 0 or -1. */
if (mpz_cmp_si (op1->value.integer, 1) == 0)
{
@@ -884,29 +882,36 @@ arith_power (gfc_expr *op1, gfc_expr *op2, gfc_expr **resultp)
"exponent of integer has zero "
"result at %L", &result->where);
}
- else if (gfc_extract_int (op2, &power))
+ else
{
- /* If op2 doesn't fit in an int, the exponentiation will
- overflow, because op2 > 0 and abs(op1) > 1. */
- mpz_t max;
- int i;
- i = gfc_validate_kind (BT_INTEGER, result->ts.kind, false);
-
- if (flag_range_check)
- rc = ARITH_OVERFLOW;
-
- /* Still, we want to give the same value as the
- processor. */
- mpz_init (max);
- mpz_add_ui (max, gfc_integer_kinds[i].huge, 1);
- mpz_mul_ui (max, max, 2);
- mpz_powm (result->value.integer, op1->value.integer,
- op2->value.integer, max);
- mpz_clear (max);
+ /* We have abs(op1) > 1 and op2 > 1.
+ If op2 > bit_size(op1), we'll have an out-of-range
+ result. */
+ int k, power;
+
+ k = gfc_validate_kind (BT_INTEGER, op1->ts.kind, false);
+ power = gfc_integer_kinds[k].bit_size;
+ if (mpz_cmp_si (op2->value.integer, power) < 0)
+ {
+ gfc_extract_int (op2, &power);
+ mpz_pow_ui (result->value.integer, op1->value.integer,
+ power);
+ rc = gfc_range_check (result);
+ if (rc == ARITH_OVERFLOW)
+ gfc_error_now ("Result of exponentiation at %L "
+ "exceeds the range of %s", &op1->where,
+ gfc_typename (&(op1->ts)));
+ }
+ else
+ {
+ /* Provide a nonsense value to propagate up. */
+ mpz_set (result->value.integer,
+ gfc_integer_kinds[k].huge);
+ mpz_add_ui (result->value.integer,
+ result->value.integer, 1);
+ rc = ARITH_OVERFLOW;
+ }
}
- else
- mpz_pow_ui (result->value.integer, op1->value.integer,
- power);
}
break;
diff --git a/gcc/fortran/array.c b/gcc/fortran/array.c
index 96732ecd..0aee220 100644
--- a/gcc/fortran/array.c
+++ b/gcc/fortran/array.c
@@ -324,10 +324,22 @@ gfc_free_array_spec (gfc_array_spec *as)
if (as == NULL)
return;
- for (i = 0; i < as->rank + as->corank; i++)
+ if (as->corank == 0)
{
- gfc_free_expr (as->lower[i]);
- gfc_free_expr (as->upper[i]);
+ for (i = 0; i < as->rank; i++)
+ {
+ gfc_free_expr (as->lower[i]);
+ gfc_free_expr (as->upper[i]);
+ }
+ }
+ else
+ {
+ int n = as->rank + as->corank - (as->cotype == AS_EXPLICIT ? 1 : 0);
+ for (i = 0; i < n; i++)
+ {
+ gfc_free_expr (as->lower[i]);
+ gfc_free_expr (as->upper[i]);
+ }
}
free (as);
diff --git a/gcc/fortran/check.c b/gcc/fortran/check.c
index a04f0d6..9580180 100644
--- a/gcc/fortran/check.c
+++ b/gcc/fortran/check.c
@@ -4884,17 +4884,13 @@ gfc_check_c_funloc (gfc_expr *x)
if (attr.function && !attr.proc_pointer && x->expr_type == EXPR_VARIABLE
&& x->symtree->n.sym == x->symtree->n.sym->result)
- {
- gfc_namespace *ns = gfc_current_ns;
-
- for (ns = gfc_current_ns; ns; ns = ns->parent)
- if (x->symtree->n.sym == ns->proc_name)
- {
- gfc_error ("Function result %qs at %L is invalid as X argument "
- "to C_FUNLOC", x->symtree->n.sym->name, &x->where);
- return false;
- }
- }
+ for (gfc_namespace *ns = gfc_current_ns; ns; ns = ns->parent)
+ if (x->symtree->n.sym == ns->proc_name)
+ {
+ gfc_error ("Function result %qs at %L is invalid as X argument "
+ "to C_FUNLOC", x->symtree->n.sym->name, &x->where);
+ return false;
+ }
if (attr.flavor != FL_PROCEDURE)
{
diff --git a/gcc/fortran/decl.c b/gcc/fortran/decl.c
index 66f1094..3d29091 100644
--- a/gcc/fortran/decl.c
+++ b/gcc/fortran/decl.c
@@ -406,7 +406,7 @@ match_data_constant (gfc_expr **result)
contains the right constant expression. Check here. */
if ((*result)->symtree == NULL
&& (*result)->expr_type == EXPR_CONSTANT
- && ((*result)->ts.type == BT_INTEGER
+ && ((*result)->ts.type == BT_INTEGER
|| (*result)->ts.type == BT_REAL))
return m;
@@ -1493,19 +1493,18 @@ gfc_verify_c_interop_param (gfc_symbol *sym)
/* Character strings are only C interoperable if they have a
length of 1. */
- if (sym->ts.type == BT_CHARACTER)
+ if (sym->ts.type == BT_CHARACTER && !sym->attr.dimension)
{
gfc_charlen *cl = sym->ts.u.cl;
if (!cl || !cl->length || cl->length->expr_type != EXPR_CONSTANT
|| mpz_cmp_si (cl->length->value.integer, 1) != 0)
{
- if (!gfc_notify_std (GFC_STD_F2018,
- "Character argument %qs at %L "
- "must be length 1 because "
- "procedure %qs is BIND(C)",
- sym->name, &sym->declared_at,
- sym->ns->proc_name->name))
- retval = false;
+ gfc_error ("Character argument %qs at %L "
+ "must be length 1 because "
+ "procedure %qs is BIND(C)",
+ sym->name, &sym->declared_at,
+ sym->ns->proc_name->name);
+ retval = false;
}
}
@@ -2456,7 +2455,6 @@ variable_decl (int elem)
/* %FILL components are given invalid fortran names. */
snprintf (name, GFC_MAX_SYMBOL_LEN + 1, "%%FILL%u", fill_id++);
- m = MATCH_YES;
}
var_locus = gfc_current_locus;
@@ -2780,6 +2778,16 @@ variable_decl (int elem)
m = match_pointer_init (&initializer, 0);
if (m != MATCH_YES)
goto cleanup;
+
+ /* The target of a pointer initialization must have the SAVE
+ attribute. A variable in PROGRAM, MODULE, or SUBMODULE scope
+ is implicit SAVEd. Explicitly, set the SAVE_IMPLICIT value. */
+ if (initializer->expr_type == EXPR_VARIABLE
+ && initializer->symtree->n.sym->attr.save == SAVE_NONE
+ && (gfc_current_state () == COMP_PROGRAM
+ || gfc_current_state () == COMP_MODULE
+ || gfc_current_state () == COMP_SUBMODULE))
+ initializer->symtree->n.sym->attr.save = SAVE_IMPLICIT;
}
else if (gfc_match_char ('=') == MATCH_YES)
{
@@ -6074,7 +6082,7 @@ static bool
in_module_or_interface(void)
{
if (gfc_current_state () == COMP_MODULE
- || gfc_current_state () == COMP_SUBMODULE
+ || gfc_current_state () == COMP_SUBMODULE
|| gfc_current_state () == COMP_INTERFACE)
return true;
@@ -6085,7 +6093,7 @@ in_module_or_interface(void)
gfc_state_data *p;
for (p = gfc_state_stack->previous; p ; p = p->previous)
{
- if (p->state == COMP_MODULE || p->state == COMP_SUBMODULE
+ if (p->state == COMP_MODULE || p->state == COMP_SUBMODULE
|| p->state == COMP_INTERFACE)
return true;
}
@@ -6304,7 +6312,7 @@ gfc_match_formal_arglist (gfc_symbol *progname, int st_flag,
}
if (gfc_match_char (')') == MATCH_YES)
- {
+ {
if (typeparam)
{
gfc_error_now ("A type parameter list is required at %C");
@@ -7489,7 +7497,7 @@ gfc_match_entry (void)
if (!gfc_add_is_bind_c (&(entry->attr), entry->name,
&(entry->declared_at), 1))
return MATCH_ERROR;
-
+
}
if (!gfc_current_ns->parent
@@ -8373,6 +8381,15 @@ attr_decl1 (void)
to the first component, or '_data' field. */
if (sym->ts.type == BT_CLASS && sym->ts.u.derived->attr.is_class)
{
+ /* gfc_set_array_spec sets sym->attr not CLASS_DATA(sym)->attr. Check
+ for duplicate attribute here. */
+ if (CLASS_DATA(sym)->attr.dimension == 1 && as)
+ {
+ gfc_error ("Duplicate DIMENSION attribute at %C");
+ m = MATCH_ERROR;
+ goto cleanup;
+ }
+
if (!gfc_copy_attr (&CLASS_DATA(sym)->attr, &current_attr, &var_locus))
{
m = MATCH_ERROR;
@@ -8770,6 +8787,7 @@ access_attr_decl (gfc_statement st)
gfc_symbol *sym, *dt_sym;
gfc_intrinsic_op op;
match m;
+ gfc_access access = (st == ST_PUBLIC) ? ACCESS_PUBLIC : ACCESS_PRIVATE;
if (gfc_match (" ::") == MATCH_NO && gfc_match_space () == MATCH_NO)
goto done;
@@ -8780,7 +8798,7 @@ access_attr_decl (gfc_statement st)
if (m == MATCH_NO)
goto syntax;
if (m == MATCH_ERROR)
- return MATCH_ERROR;
+ goto done;
switch (type)
{
@@ -8800,18 +8818,12 @@ access_attr_decl (gfc_statement st)
&& sym->attr.flavor == FL_UNKNOWN)
sym->attr.flavor = FL_PROCEDURE;
- if (!gfc_add_access (&sym->attr,
- (st == ST_PUBLIC)
- ? ACCESS_PUBLIC : ACCESS_PRIVATE,
- sym->name, NULL))
- return MATCH_ERROR;
+ if (!gfc_add_access (&sym->attr, access, sym->name, NULL))
+ goto done;
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))
- return MATCH_ERROR;
+ && !gfc_add_access (&dt_sym->attr, access, sym->name, NULL))
+ goto done;
break;
@@ -8820,17 +8832,14 @@ access_attr_decl (gfc_statement st)
{
gfc_intrinsic_op other_op;
- gfc_current_ns->operator_access[op] =
- (st == ST_PUBLIC) ? ACCESS_PUBLIC : ACCESS_PRIVATE;
+ gfc_current_ns->operator_access[op] = access;
/* Handle the case if there is another op with the same
function, for INTRINSIC_EQ vs. INTRINSIC_EQ_OS and so on. */
other_op = gfc_equivalent_op (op);
if (other_op != INTRINSIC_NONE)
- gfc_current_ns->operator_access[other_op] =
- (st == ST_PUBLIC) ? ACCESS_PUBLIC : ACCESS_PRIVATE;
-
+ gfc_current_ns->operator_access[other_op] = access;
}
else
{
@@ -8846,8 +8855,7 @@ access_attr_decl (gfc_statement st)
if (uop->access == ACCESS_UNKNOWN)
{
- uop->access = (st == ST_PUBLIC)
- ? ACCESS_PUBLIC : ACCESS_PRIVATE;
+ uop->access = access;
}
else
{
@@ -8880,6 +8888,13 @@ gfc_match_protected (void)
{
gfc_symbol *sym;
match m;
+ char c;
+
+ /* PROTECTED has already been seen, but must be followed by whitespace
+ or ::. */
+ c = gfc_peek_ascii_char ();
+ if (!gfc_is_whitespace (c) && c != ':')
+ return MATCH_NO;
if (!gfc_current_ns->proc_name
|| gfc_current_ns->proc_name->attr.flavor != FL_MODULE)
@@ -8890,14 +8905,12 @@ gfc_match_protected (void)
}
+ gfc_match (" ::");
+
if (!gfc_notify_std (GFC_STD_F2003, "PROTECTED statement at %C"))
return MATCH_ERROR;
- if (gfc_match (" ::") == MATCH_NO && gfc_match_space () == MATCH_NO)
- {
- return MATCH_ERROR;
- }
-
+ /* PROTECTED has an entity-list. */
if (gfc_match_eos () == MATCH_YES)
goto syntax;
@@ -8940,39 +8953,46 @@ syntax:
match
gfc_match_private (gfc_statement *st)
{
+ gfc_state_data *prev;
+ char c;
if (gfc_match ("private") != MATCH_YES)
return MATCH_NO;
- if (gfc_current_state () != COMP_MODULE
- && !(gfc_current_state () == COMP_DERIVED
- && gfc_state_stack->previous
- && gfc_state_stack->previous->state == COMP_MODULE)
- && !(gfc_current_state () == COMP_DERIVED_CONTAINS
- && gfc_state_stack->previous && gfc_state_stack->previous->previous
- && gfc_state_stack->previous->previous->state == COMP_MODULE))
- {
- gfc_error ("PRIVATE statement at %C is only allowed in the "
- "specification part of a module");
- return MATCH_ERROR;
- }
-
- if (gfc_current_state () == COMP_DERIVED)
+ /* Try matching PRIVATE without an access-list. */
+ if (gfc_match_eos () == MATCH_YES)
{
- if (gfc_match_eos () == MATCH_YES)
+ prev = gfc_state_stack->previous;
+ if (gfc_current_state () != COMP_MODULE
+ && !(gfc_current_state () == COMP_DERIVED
+ && prev && prev->state == COMP_MODULE)
+ && !(gfc_current_state () == COMP_DERIVED_CONTAINS
+ && prev->previous && prev->previous->state == COMP_MODULE))
{
- *st = ST_PRIVATE;
- return MATCH_YES;
+ gfc_error ("PRIVATE statement at %C is only allowed in the "
+ "specification part of a module");
+ return MATCH_ERROR;
}
- gfc_syntax_error (ST_PRIVATE);
- return MATCH_ERROR;
+ *st = ST_PRIVATE;
+ return MATCH_YES;
}
- if (gfc_match_eos () == MATCH_YES)
+ /* At this point, PRIVATE must be followed by whitespace or ::. */
+ c = gfc_peek_ascii_char ();
+ if (!gfc_is_whitespace (c) && c != ':')
+ return MATCH_NO;
+
+ prev = gfc_state_stack->previous;
+ if (gfc_current_state () != COMP_MODULE
+ && !(gfc_current_state () == COMP_DERIVED
+ && prev && prev->state == COMP_MODULE)
+ && !(gfc_current_state () == COMP_DERIVED_CONTAINS
+ && prev->previous && prev->previous->state == COMP_MODULE))
{
- *st = ST_PRIVATE;
- return MATCH_YES;
+ gfc_error ("PRIVATE statement at %C is only allowed in the "
+ "specification part of a module");
+ return MATCH_ERROR;
}
*st = ST_ATTR_DECL;
@@ -8983,10 +9003,30 @@ gfc_match_private (gfc_statement *st)
match
gfc_match_public (gfc_statement *st)
{
+ char c;
if (gfc_match ("public") != MATCH_YES)
return MATCH_NO;
+ /* Try matching PUBLIC without an access-list. */
+ if (gfc_match_eos () == MATCH_YES)
+ {
+ if (gfc_current_state () != COMP_MODULE)
+ {
+ gfc_error ("PUBLIC statement at %C is only allowed in the "
+ "specification part of a module");
+ return MATCH_ERROR;
+ }
+
+ *st = ST_PUBLIC;
+ return MATCH_YES;
+ }
+
+ /* At this point, PUBLIC must be followed by whitespace or ::. */
+ c = gfc_peek_ascii_char ();
+ if (!gfc_is_whitespace (c) && c != ':')
+ return MATCH_NO;
+
if (gfc_current_state () != COMP_MODULE)
{
gfc_error ("PUBLIC statement at %C is only allowed in the "
@@ -8994,12 +9034,6 @@ gfc_match_public (gfc_statement *st)
return MATCH_ERROR;
}
- if (gfc_match_eos () == MATCH_YES)
- {
- *st = ST_PUBLIC;
- return MATCH_YES;
- }
-
*st = ST_ATTR_DECL;
return access_attr_decl (ST_PUBLIC);
}
@@ -9284,8 +9318,13 @@ gfc_match_save (void)
return MATCH_YES;
syntax:
- gfc_error ("Syntax error in SAVE statement at %C");
- return MATCH_ERROR;
+ if (gfc_current_ns->seen_save)
+ {
+ gfc_error ("Syntax error in SAVE statement at %C");
+ return MATCH_ERROR;
+ }
+ else
+ return MATCH_NO;
}
@@ -10194,6 +10233,13 @@ gfc_match_derived_decl (void)
&& !gfc_add_function (&gensym->attr, gensym->name, NULL))
return MATCH_ERROR;
+ if (gensym->attr.dummy)
+ {
+ gfc_error ("Dummy argument %qs at %L cannot be a derived type at %C",
+ name, &gensym->declared_at);
+ return MATCH_ERROR;
+ }
+
sym = gfc_find_dt_in_generic (gensym);
if (sym && (sym->components != NULL || sym->attr.zero_comp))
diff --git a/gcc/fortran/dependency.c b/gcc/fortran/dependency.c
index ae0f803..be330e2 100644
--- a/gcc/fortran/dependency.c
+++ b/gcc/fortran/dependency.c
@@ -979,10 +979,14 @@ gfc_check_argument_var_dependency (gfc_expr *var, sym_intent intent,
If a dependency is found in the case
elemental == ELEM_CHECK_VARIABLE, we will generate
a temporary, so we don't need to bother the user. */
- gfc_warning (0, "INTENT(%s) actual argument at %L might "
- "interfere with actual argument at %L.",
- intent == INTENT_OUT ? "OUT" : "INOUT",
- &var->where, &expr->where);
+
+ if (var->expr_type == EXPR_VARIABLE
+ && expr->expr_type == EXPR_VARIABLE
+ && strcmp(var->symtree->name, expr->symtree->name) == 0)
+ gfc_warning (0, "INTENT(%s) actual argument at %L might "
+ "interfere with actual argument at %L.",
+ intent == INTENT_OUT ? "OUT" : "INOUT",
+ &var->where, &expr->where);
}
return 0;
}
@@ -2141,7 +2145,7 @@ gfc_dep_resolver (gfc_ref *lref, gfc_ref *rref, gfc_reverse *reverse)
/* Index for the reverse array. */
m = -1;
- for (n=0; n < lref->u.ar.dimen; n++)
+ for (n = 0; n < lref->u.ar.dimen; n++)
{
/* Handle dependency when either of array reference is vector
subscript. There is no dependency if the vector indices
@@ -2163,7 +2167,8 @@ gfc_dep_resolver (gfc_ref *lref, gfc_ref *rref, gfc_reverse *reverse)
if (lref->u.ar.dimen_type[n] == DIMEN_RANGE
&& rref->u.ar.dimen_type[n] == DIMEN_RANGE)
- this_dep = check_section_vs_section (&lref->u.ar, &rref->u.ar, n);
+ this_dep = check_section_vs_section (&lref->u.ar,
+ &rref->u.ar, n);
else if (lref->u.ar.dimen_type[n] == DIMEN_ELEMENT
&& rref->u.ar.dimen_type[n] == DIMEN_RANGE)
this_dep = gfc_check_element_vs_section (lref, rref, n);
@@ -2196,35 +2201,38 @@ gfc_dep_resolver (gfc_ref *lref, gfc_ref *rref, gfc_reverse *reverse)
if (rref->u.ar.dimen_type[n] == DIMEN_RANGE
&& lref->u.ar.dimen_type[n] == DIMEN_RANGE)
{
- /* Set reverse if backward dependence and not inhibited. */
- if (reverse && reverse[m] == GFC_ENABLE_REVERSE)
- reverse[m] = (this_dep == GFC_DEP_BACKWARD) ?
- GFC_REVERSE_SET : reverse[m];
-
- /* Set forward if forward dependence and not inhibited. */
- if (reverse && reverse[m] == GFC_ENABLE_REVERSE)
- reverse[m] = (this_dep == GFC_DEP_FORWARD) ?
- GFC_FORWARD_SET : reverse[m];
-
- /* Flag up overlap if dependence not compatible with
- the overall state of the expression. */
- if (reverse && reverse[m] == GFC_REVERSE_SET
- && this_dep == GFC_DEP_FORWARD)
- {
- reverse[m] = GFC_INHIBIT_REVERSE;
- this_dep = GFC_DEP_OVERLAP;
- }
- else if (reverse && reverse[m] == GFC_FORWARD_SET
- && this_dep == GFC_DEP_BACKWARD)
+ if (reverse)
{
- reverse[m] = GFC_INHIBIT_REVERSE;
- this_dep = GFC_DEP_OVERLAP;
+ /* Reverse if backward dependence and not inhibited. */
+ if (reverse[m] == GFC_ENABLE_REVERSE
+ && this_dep == GFC_DEP_BACKWARD)
+ reverse[m] = GFC_REVERSE_SET;
+
+ /* Forward if forward dependence and not inhibited. */
+ if (reverse[m] == GFC_ENABLE_REVERSE
+ && this_dep == GFC_DEP_FORWARD)
+ reverse[m] = GFC_FORWARD_SET;
+
+ /* Flag up overlap if dependence not compatible with
+ the overall state of the expression. */
+ if (reverse[m] == GFC_REVERSE_SET
+ && this_dep == GFC_DEP_FORWARD)
+ {
+ reverse[m] = GFC_INHIBIT_REVERSE;
+ this_dep = GFC_DEP_OVERLAP;
+ }
+ else if (reverse[m] == GFC_FORWARD_SET
+ && this_dep == GFC_DEP_BACKWARD)
+ {
+ reverse[m] = GFC_INHIBIT_REVERSE;
+ this_dep = GFC_DEP_OVERLAP;
+ }
}
/* If no intention of reversing or reversing is explicitly
inhibited, convert backward dependence to overlap. */
- if ((reverse == NULL && this_dep == GFC_DEP_BACKWARD)
- || (reverse != NULL && reverse[m] == GFC_INHIBIT_REVERSE))
+ if ((!reverse && this_dep == GFC_DEP_BACKWARD)
+ || (reverse && reverse[m] == GFC_INHIBIT_REVERSE))
this_dep = GFC_DEP_OVERLAP;
}
diff --git a/gcc/fortran/dump-parse-tree.c b/gcc/fortran/dump-parse-tree.c
index 54af5df..4cff805 100644
--- a/gcc/fortran/dump-parse-tree.c
+++ b/gcc/fortran/dump-parse-tree.c
@@ -66,6 +66,19 @@ void debug (symbol_attribute *attr)
dumpfile = tmp;
}
+void debug (gfc_formal_arglist *formal)
+{
+ FILE *tmp = dumpfile;
+ dumpfile = stderr;
+ for (; formal; formal = formal->next)
+ {
+ fputc ('\n', dumpfile);
+ show_symbol (formal->sym);
+ }
+ fputc ('\n', dumpfile);
+ dumpfile = tmp;
+}
+
void debug (symbol_attribute attr)
{
debug (&attr);
@@ -75,9 +88,15 @@ void debug (gfc_expr *e)
{
FILE *tmp = dumpfile;
dumpfile = stderr;
- show_expr (e);
- fputc (' ', dumpfile);
- show_typespec (&e->ts);
+ if (e != NULL)
+ {
+ show_expr (e);
+ fputc (' ', dumpfile);
+ show_typespec (&e->ts);
+ }
+ else
+ fputs ("() ", dumpfile);
+
fputc ('\n', dumpfile);
dumpfile = tmp;
}
@@ -3143,11 +3162,11 @@ get_c_type_name (gfc_typespec *ts, gfc_array_spec *as, const char **pre,
else if (strcmp (*type_name, "size_t") == 0)
*type_name = "ssize_t";
else if (strcmp (*type_name, "float_complex") == 0)
- *type_name = "float complex";
+ *type_name = "__GFORTRAN_FLOAT_COMPLEX";
else if (strcmp (*type_name, "double_complex") == 0)
- *type_name = "double complex";
+ *type_name = "__GFORTRAN_DOUBLE_COMPLEX";
else if (strcmp (*type_name, "long_double_complex") == 0)
- *type_name = "long double complex";
+ *type_name = "__GFORTRAN_LONG_DOUBLE_COMPLEX";
ret = T_OK;
}
@@ -3166,11 +3185,11 @@ get_c_type_name (gfc_typespec *ts, gfc_array_spec *as, const char **pre,
else if (strcmp (*type_name, "size_t") == 0)
*type_name = "ssize_t";
else if (strcmp (*type_name, "float_complex") == 0)
- *type_name = "float complex";
+ *type_name = "__GFORTRAN_FLOAT_COMPLEX";
else if (strcmp (*type_name, "double_complex") == 0)
- *type_name = "double complex";
+ *type_name = "__GFORTRAN_DOUBLE_COMPLEX";
else if (strcmp (*type_name, "long_double_complex") == 0)
- *type_name = "long double complex";
+ *type_name = "__GFORTRAN_LONG_DOUBLE_COMPLEX";
ret = T_WARN;
break;
diff --git a/gcc/fortran/expr.c b/gcc/fortran/expr.c
index 474e9ec..ec9e328 100644
--- a/gcc/fortran/expr.c
+++ b/gcc/fortran/expr.c
@@ -5713,6 +5713,9 @@ gfc_is_simply_contiguous (gfc_expr *expr, bool strict, bool permit_element)
gfc_ref *ref, *part_ref = NULL;
gfc_symbol *sym;
+ if (expr->expr_type == EXPR_ARRAY)
+ return true;
+
if (expr->expr_type == EXPR_FUNCTION)
{
if (expr->value.function.esym)
@@ -6086,7 +6089,12 @@ gfc_check_vardef_context (gfc_expr* e, bool pointer, bool alloc_obj,
check_intentin = false;
}
}
- if (check_intentin && sym->attr.intent == INTENT_IN)
+
+ if (check_intentin
+ && (sym->attr.intent == INTENT_IN
+ || (sym->attr.select_type_temporary && sym->assoc
+ && sym->assoc->target && sym->assoc->target->symtree
+ && sym->assoc->target->symtree->n.sym->attr.intent == INTENT_IN)))
{
if (pointer && is_pointer)
{
@@ -6098,10 +6106,12 @@ gfc_check_vardef_context (gfc_expr* e, bool pointer, bool alloc_obj,
}
if (!pointer && !is_pointer && !sym->attr.pointer)
{
+ const char *name = sym->attr.select_type_temporary
+ ? sym->assoc->target->symtree->name : sym->name;
if (context)
gfc_error ("Dummy argument %qs with INTENT(IN) in variable"
" definition context (%s) at %L",
- sym->name, context, &e->where);
+ name, context, &e->where);
return false;
}
}
diff --git a/gcc/fortran/f95-lang.c b/gcc/fortran/f95-lang.c
index 3e3d304..6b9f490 100644
--- a/gcc/fortran/f95-lang.c
+++ b/gcc/fortran/f95-lang.c
@@ -91,7 +91,7 @@ static const struct attribute_spec gfc_attribute_table[] =
{
/* { name, min_len, max_len, decl_req, type_req, fn_type_req,
affects_type_identity, handler, exclude } */
- { "omp declare target", 0, 0, true, false, false, false,
+ { "omp declare target", 0, -1, true, false, false, false,
gfc_handle_omp_declare_target_attribute, NULL },
{ "omp declare target link", 0, 0, true, false, false, false,
gfc_handle_omp_declare_target_attribute, NULL },
diff --git a/gcc/fortran/frontend-passes.c b/gcc/fortran/frontend-passes.c
index d4264da..87df504 100644
--- a/gcc/fortran/frontend-passes.c
+++ b/gcc/fortran/frontend-passes.c
@@ -54,7 +54,6 @@ static gfc_code * create_do_loop (gfc_expr *, gfc_expr *, gfc_expr *,
static gfc_expr* check_conjg_transpose_variable (gfc_expr *, bool *,
bool *);
static int call_external_blas (gfc_code **, int *, void *);
-static bool has_dimen_vector_ref (gfc_expr *);
static int matmul_temp_args (gfc_code **, int *,void *data);
static int index_interchange (gfc_code **, int*, void *);
@@ -2868,7 +2867,7 @@ matmul_temp_args (gfc_code **c, int *walk_subtrees ATTRIBUTE_UNUSED,
{
if (matrix_a->expr_type == EXPR_VARIABLE
&& (gfc_check_dependency (matrix_a, expr1, true)
- || has_dimen_vector_ref (matrix_a)))
+ || gfc_has_dimen_vector_ref (matrix_a)))
a_tmp = true;
}
else
@@ -2881,7 +2880,7 @@ matmul_temp_args (gfc_code **c, int *walk_subtrees ATTRIBUTE_UNUSED,
{
if (matrix_b->expr_type == EXPR_VARIABLE
&& (gfc_check_dependency (matrix_b, expr1, true)
- || has_dimen_vector_ref (matrix_b)))
+ || gfc_has_dimen_vector_ref (matrix_b)))
b_tmp = true;
}
else
@@ -3681,8 +3680,8 @@ scalarized_expr (gfc_expr *e_in, gfc_expr **index, int count_index)
/* Helper function to check for a dimen vector as subscript. */
-static bool
-has_dimen_vector_ref (gfc_expr *e)
+bool
+gfc_has_dimen_vector_ref (gfc_expr *e)
{
gfc_array_ref *ar;
int i;
@@ -3838,8 +3837,8 @@ inline_matmul_assign (gfc_code **c, int *walk_subtrees,
if (matrix_b == NULL)
return 0;
- if (has_dimen_vector_ref (expr1) || has_dimen_vector_ref (matrix_a)
- || has_dimen_vector_ref (matrix_b))
+ if (gfc_has_dimen_vector_ref (expr1) || gfc_has_dimen_vector_ref (matrix_a)
+ || gfc_has_dimen_vector_ref (matrix_b))
return 0;
/* We do not handle data dependencies yet. */
diff --git a/gcc/fortran/gfc-internals.texi b/gcc/fortran/gfc-internals.texi
index d65d5de..2c30aa6 100644
--- a/gcc/fortran/gfc-internals.texi
+++ b/gcc/fortran/gfc-internals.texi
@@ -119,6 +119,8 @@ not accurately reflect the status of the most recent GNU Fortran compiler.
* Frontend Data Structures::
Data structures used by the frontend
* Object Orientation:: Internals of Fortran 2003 OOP features.
+* Translating to GENERIC::
+ Generating the intermediate language for later stages.
* LibGFortran:: The LibGFortran Runtime Library.
* GNU Free Documentation License::
How you can copy and share this manual.
@@ -724,6 +726,147 @@ operator call is replaced with an internally generated @code{GENERIC}
type-bound procedure call to the respective definition and that call is
further processed.
+@c ---------------------------------------------------------------------
+@c - Translating to GENERIC
+@c ---------------------------------------------------------------------
+
+@node Translating to GENERIC
+@chapter Generating the intermediate language for later stages.
+
+This chapter deals with the transformation of gfortran's frontend data
+structures to the intermediate language used by the later stages of
+the compiler, the so-called middle end.
+
+Data structures relating to this are found in the source files
+@file{trans*.h} and @file{trans-*.c}.
+
+@menu
+* Basic Data Structures:: Basic data structures.
+* Converting Expressions:: Converting expressions to tree.
+* Translating Statements:: Translating statements.
+* Accessing Declarations:: Accessing declarations.
+@end menu
+
+@node Basic Data Structures
+@section Basic data structures
+
+Gfortran creates GENERIC as an intermediate language for the
+middle-end. Details about GENERIC can be found in the GCC manual.
+
+The basic data structure of GENERIC is a @code{tree}. Everything in
+GENERIC is a @code{tree}, including types and statements. Fortunately
+for the gfortran programmer, @code{tree} variables are
+garbage-collected, so doing memory management for them is not
+necessary.
+
+@code{tree} expressions are built using functions such as, for
+example, @code{fold_build2_loc}. For two tree variables @code{a} and
+@code{b}, both of which have the type @code{gfc_arry_index_type},
+calculation @code{c = a * b} would be done by
+
+@smallexample
+c = fold_build2_loc (input_location, MULT_EXPR,
+ gfc_array_index_type, a, b);
+@end smallexample
+
+The types have to agree, otherwise internal compiler errors will occur
+at a later stage. Expressions can be converted to a different type
+using @code{fold_convert}.
+
+Accessing individual members in the @code{tree} structures should not
+be done. Rather, access should be done via macros.
+
+One basic data structure is the @code{stmtblock_t} struct. This is
+used for holding a list of statements, expressed as @code{tree}
+expressions. If a block is created using @code{gfc_start_block}, it
+has its own scope for variables; if it is created using
+@code{gfc_init_block}, it does not have its own scope.
+
+It is possible to
+@itemize @bullet
+@item Add an expression to the end of a block using
+ @code{gfc_add_expr_to_block}
+@item Add an expression to the beginning of a block using
+ @code{void gfc_prepend_expr_to_block}
+@item Make a block into a single @code{tree} using
+ @code{gfc_finish_block}. For example, this is needed to put the
+ contents of a block into the @code{if} or @code{else} branch of
+ a @code{COND_EXPR}.
+@end itemize
+
+Variables are also @code{tree} expressions, they can be created using
+@code{gfc_create_var}. Assigning to a variable can be done with
+@code{gfc_add_modify}.
+
+An example: Creating a default integer type variable in the current
+scope with the prefix ``everything'' in the @code{stmt_block}
+@code{block} and assigning the value 42 would be
+
+@smallexample
+tree var, *block;
+/* Initialize block somewhere here. */
+var = gfc_create_var (integer_type_node, "everything");
+gfc_add_modify (block, var, build_int_cst (integer_type_node, 42));
+@end smallexample
+
+@node Converting Expressions
+@section Converting Expressons to tree
+
+Converting expressions to @code{tree} is done by functions called
+@code{gfc_conv_*}.
+
+The central data structure for a GENERIC expression is the
+@code{gfc_se} structure. Its @code{expr} member is a @code{tree} that
+holds the value of the expression. A @code{gfc_se} structure is
+initialized using @code{gfc_init_se}; it needs to be embedded in an
+outer @code{gfc_se}.
+
+Evaluating Fortran expressions often require things to be done before
+and after evaluation of the expression, for example code for the
+allocation of a temporary variable and its subsequent deallocation.
+Therefore, @code{gfc_se} contains the members @code{pre} and
+@code{post}, which point to @code{stmt_block} blocks for code that
+needs to be executed before and after evaluation of the expression.
+
+When using a local @code{gfc_se} to convert some expression, it is
+often necessary to add the generated @code{pre} and @code{post} blocks
+to the @code{pre} or @code{post} blocks of the outer @code{gfc_se}.
+Code like this (lifted from @file{trans-expr.c}) is fairly common:
+
+@smallexample
+gfc_se cont_se;
+tree cont_var;
+
+/* cont_var = is_contiguous (expr); . */
+gfc_init_se (&cont_se, parmse);
+gfc_conv_is_contiguous_expr (&cont_se, expr);
+gfc_add_block_to_block (&se->pre, &(&cont_se)->pre);
+gfc_add_modify (&se->pre, cont_var, cont_se.expr);
+gfc_add_block_to_block (&se->pre, &(&cont_se)->post);
+@end smallexample
+
+Conversion functions which need a @code{gfc_se} structure will have a
+corresponding argument.
+
+@code{gfc_se} also contains pointers to a @code{gfc_ss} and a
+@code{gfc_loopinfo} structure. These are needed by the scalarizer.
+
+@node Translating Statements
+@section Translating statements
+Translating statements to @code{tree} is done by functions called
+@code{gfc_trans_*}. These functions usually get passed a
+@code{gfc_code} structure, evaluate any expressions and then
+return a @code{tree} structure.
+
+@node Accessing Declarations
+@section Accessing declarations
+
+@code{gfc_symbol}, @code{gfc_charlen} and other front-end structures
+contain a @code{backend_decl} variable, which contains the @code{tree}
+used for accessing that entity in the middle-end.
+
+Accessing declarations is usually done by functions called
+@code{gfc_get*}.
@c ---------------------------------------------------------------------
@c LibGFortran
diff --git a/gcc/fortran/gfortran.h b/gcc/fortran/gfortran.h
index 0de375c..b1f7bd0 100644
--- a/gcc/fortran/gfortran.h
+++ b/gcc/fortran/gfortran.h
@@ -1866,6 +1866,9 @@ typedef struct gfc_namespace
/* Set to 1 for !$ACC ROUTINE namespaces. */
unsigned oacc_routine:1;
+
+ /* Set to 1 if there are any calls to procedures with implicit interface. */
+ unsigned implicit_interface_calls:1;
}
gfc_namespace;
@@ -3114,8 +3117,6 @@ void gfc_traverse_user_op (gfc_namespace *, void (*)(gfc_user_op *));
void gfc_save_all (gfc_namespace *);
void gfc_enforce_clean_symbol_state (void);
-void gfc_free_dt_list (void);
-
gfc_gsymbol *gfc_get_gsymbol (const char *, bool bind_c);
gfc_gsymbol *gfc_find_gsymbol (gfc_gsymbol *, const char *);
@@ -3532,6 +3533,7 @@ typedef int (*walk_expr_fn_t) (gfc_expr **, int *, void *);
int gfc_dummy_code_callback (gfc_code **, int *, void *);
int gfc_expr_walker (gfc_expr **, walk_expr_fn_t, void *);
int gfc_code_walker (gfc_code **, walk_code_fn_t, walk_expr_fn_t, void *);
+bool gfc_has_dimen_vector_ref (gfc_expr *e);
/* simplify.c */
diff --git a/gcc/fortran/gfortran.texi b/gcc/fortran/gfortran.texi
index 76c1f2d..c887e7d 100644
--- a/gcc/fortran/gfortran.texi
+++ b/gcc/fortran/gfortran.texi
@@ -1576,6 +1576,7 @@ additional compatibility extensions along with those enabled by
* X format descriptor without count field::
* Commas in FORMAT specifications::
* Missing period in FORMAT specifications::
+* Default widths for F@comma{} G and I format descriptors::
* I/O item lists::
* @code{Q} exponent-letter::
* BOZ literal constants::
@@ -1760,11 +1761,16 @@ When omitted, the count is implicitly assumed to be one.
To support legacy codes, GNU Fortran allows the comma separator
to be omitted immediately before and after character string edit
-descriptors in @code{FORMAT} statements.
+descriptors in @code{FORMAT} statements. A comma with no following format
+decriptor is permited if the @option{-fdec-blank-format-item} is given on
+the command line. This is considered non-conforming code and is
+discouraged.
@smallexample
PRINT 10, 2, 3
10 FORMAT ('FOO='I1' BAR='I2)
+ print 20, 5, 6
+20 FORMAT (I3, I3,)
@end smallexample
@@ -1782,6 +1788,22 @@ discouraged.
10 FORMAT ('F4')
@end smallexample
+@node Default widths for F@comma{} G and I format descriptors
+@subsection Default widths for @code{F}, @code{G} and @code{I} format descriptors
+
+To support legacy codes, GNU Fortran allows width to be omitted from format
+specifications if and only if @option{-fdec-format-defaults} is given on the
+command line. Default widths will be used. This is considered non-conforming
+code and is discouraged.
+
+@smallexample
+ REAL :: value1
+ INTEGER :: value2
+ WRITE(*,10) value1, value1, value2
+10 FORMAT ('F, G, I')
+@end smallexample
+
+
@node I/O item lists
@subsection I/O item lists
@cindex I/O item lists
@@ -1901,13 +1923,13 @@ in I/O operations.
@cindex Hollerith constants
GNU Fortran supports Hollerith constants in assignments, function
-arguments, and @code{DATA} and @code{ASSIGN} statements. A Hollerith
-constant is written as a string of characters preceded by an integer
-constant indicating the character count, and the letter @code{H} or
-@code{h}, and stored in bytewise fashion in a numeric (@code{INTEGER},
-@code{REAL}, or @code{complex}) or @code{LOGICAL} variable. The
-constant will be padded or truncated to fit the size of the variable in
-which it is stored.
+arguments, and @code{DATA} statements. A Hollerith constant is written
+as a string of characters preceded by an integer constant indicating the
+character count, and the letter @code{H} or @code{h}, and stored in
+bytewise fashion in a numeric (@code{INTEGER}, @code{REAL}, or
+@code{COMPLEX}) or @code{LOGICAL} variable. The constant will be padded
+with spaces or truncated to fit the size of the variable in which it is
+stored.
Examples of valid uses of Hollerith constants:
@smallexample
@@ -1917,11 +1939,13 @@ Examples of valid uses of Hollerith constants:
call foo (4h abc)
@end smallexample
-Invalid Hollerith constants examples:
+Examples of Hollerith constants:
@smallexample
integer*4 a
+ a = 0H ! Invalid, at least one character is needed.
+ a = 4HAB12 ! Valid
a = 8H12345678 ! Valid, but the Hollerith constant will be truncated.
- a = 0H ! At least one character is needed.
+ a = 3Hxyz ! Valid, but the Hollerith constant will be padded.
@end smallexample
In general, Hollerith constants were used to provide a rudimentary
diff --git a/gcc/fortran/gfortranspec.c b/gcc/fortran/gfortranspec.c
index 33e6e57..5b0fe4d 100644
--- a/gcc/fortran/gfortranspec.c
+++ b/gcc/fortran/gfortranspec.c
@@ -143,7 +143,7 @@ append_arg (const struct cl_decoded_option *arg)
}
if (g77_newargc == newargsize)
- fatal_error (input_location, "overflowed output arg list for %qs",
+ fatal_error (input_location, "overflowed output argument list for %qs",
arg->orig_option_with_args_text);
g77_new_decoded_options[g77_newargc++] = *arg;
diff --git a/gcc/fortran/interface.c b/gcc/fortran/interface.c
index 5b8a0f9..3f91f6b 100644
--- a/gcc/fortran/interface.c
+++ b/gcc/fortran/interface.c
@@ -2989,7 +2989,8 @@ compare_actual_formal (gfc_actual_arglist **ap, gfc_formal_arglist *formal,
polymorphic formal arguments. */
if (UNLIMITED_POLY (f->sym)
&& a->expr->ts.type != BT_DERIVED
- && a->expr->ts.type != BT_CLASS)
+ && a->expr->ts.type != BT_CLASS
+ && a->expr->ts.type != BT_ASSUMED)
gfc_find_vtab (&a->expr->ts);
if (a->expr->expr_type == EXPR_NULL
@@ -3685,6 +3686,7 @@ gfc_procedure_use (gfc_symbol *sym, gfc_actual_arglist **ap, locus *where)
gfc_warning (OPT_Wimplicit_procedure,
"Procedure %qs called at %L is not explicitly declared",
sym->name, where);
+ gfc_find_proc_namespace (sym->ns)->implicit_interface_calls = 1;
}
if (sym->attr.if_source == IFSRC_UNKNOWN)
diff --git a/gcc/fortran/intrinsic.texi b/gcc/fortran/intrinsic.texi
index ee857c6..f390761 100644
--- a/gcc/fortran/intrinsic.texi
+++ b/gcc/fortran/intrinsic.texi
@@ -5596,12 +5596,12 @@ end program atomic
@code{EXECUTE_COMMAND_LINE} runs a shell command, synchronously or
asynchronously.
-The @code{COMMAND} argument is passed to the shell and executed, using
-the C library's @code{system} call. (The shell is @code{sh} on Unix
-systems, and @code{cmd.exe} on Windows.) If @code{WAIT} is present
-and has the value false, the execution of the command is asynchronous
-if the system supports it; otherwise, the command is executed
-synchronously.
+The @code{COMMAND} argument is passed to the shell and executed (The
+shell is @code{sh} on Unix systems, and @code{cmd.exe} on Windows.).
+If @code{WAIT} is present and has the value false, the execution of
+the command is asynchronous if the system supports it; otherwise, the
+command is executed synchronously using the C library's @code{system}
+call.
The three last arguments allow the user to get status information. After
synchronous execution, @code{EXITSTAT} contains the integer exit code of
@@ -5613,6 +5613,10 @@ Note that the @code{system} function need not be thread-safe. It is
the responsibility of the user to ensure that @code{system} is not
called concurrently.
+For asynchronous execution on supported targets, the POSIX
+@code{posix_spawn} or @code{fork} functions are used. Also, a signal
+handler for the @code{SIGCHLD} signal is installed.
+
@item @emph{Standard}:
Fortran 2008 and later
@@ -9685,10 +9689,10 @@ The return value is a @code{INTEGER(4)} variable.
@table @asis
@item @emph{Description}:
@code{LSHIFT} returns a value corresponding to @var{I} with all of the
-bits shifted left by @var{SHIFT} places. If the absolute value of
-@var{SHIFT} is greater than @code{BIT_SIZE(I)}, the value is undefined.
-Bits shifted out from the left end are lost; zeros are shifted in from
-the opposite end.
+bits shifted left by @var{SHIFT} places. @var{SHIFT} shall be
+nonnegative and less than or equal to @code{BIT_SIZE(I)}, otherwise
+the result value is undefined. Bits shifted out from the left end are
+lost; zeros are shifted in from the opposite end.
This function has been superseded by the @code{ISHFT} intrinsic, which
is standard in Fortran 95 and later, and the @code{SHIFTL} intrinsic,
@@ -12240,11 +12244,12 @@ The value returned is equal to
@table @asis
@item @emph{Description}:
@code{RSHIFT} returns a value corresponding to @var{I} with all of the
-bits shifted right by @var{SHIFT} places. If the absolute value of
-@var{SHIFT} is greater than @code{BIT_SIZE(I)}, the value is undefined.
-Bits shifted out from the right end are lost. The fill is arithmetic: the
-bits shifted in from the left end are equal to the leftmost bit, which in
-two's complement representation is the sign bit.
+bits shifted right by @var{SHIFT} places. @var{SHIFT} shall be
+nonnegative and less than or equal to @code{BIT_SIZE(I)}, otherwise
+the result value is undefined. Bits shifted out from the right end
+are lost. The fill is arithmetic: the bits shifted in from the left
+end are equal to the leftmost bit, which in two's complement
+representation is the sign bit.
This function has been superseded by the @code{SHIFTA} intrinsic, which
is standard in Fortran 2008 and later.
@@ -12779,11 +12784,12 @@ END PROGRAM
@table @asis
@item @emph{Description}:
@code{SHIFTA} returns a value corresponding to @var{I} with all of the
-bits shifted right by @var{SHIFT} places. If the absolute value of
-@var{SHIFT} is greater than @code{BIT_SIZE(I)}, the value is undefined.
-Bits shifted out from the right end are lost. The fill is arithmetic: the
-bits shifted in from the left end are equal to the leftmost bit, which in
-two's complement representation is the sign bit.
+bits shifted right by @var{SHIFT} places. @var{SHIFT} that be
+nonnegative and less than or equal to @code{BIT_SIZE(I)}, otherwise
+the result value is undefined. Bits shifted out from the right end
+are lost. The fill is arithmetic: the bits shifted in from the left
+end are equal to the leftmost bit, which in two's complement
+representation is the sign bit.
@item @emph{Standard}:
Fortran 2008 and later
@@ -12819,10 +12825,10 @@ The return value is of type @code{INTEGER} and of the same kind as
@table @asis
@item @emph{Description}:
@code{SHIFTL} returns a value corresponding to @var{I} with all of the
-bits shifted left by @var{SHIFT} places. If the absolute value of
-@var{SHIFT} is greater than @code{BIT_SIZE(I)}, the value is undefined.
-Bits shifted out from the left end are lost, and bits shifted in from
-the right end are set to 0.
+bits shifted left by @var{SHIFT} places. @var{SHIFT} shall be
+nonnegative and less than or equal to @code{BIT_SIZE(I)}, otherwise
+the result value is undefined. Bits shifted out from the left end are
+lost, and bits shifted in from the right end are set to 0.
@item @emph{Standard}:
Fortran 2008 and later
@@ -12858,10 +12864,10 @@ The return value is of type @code{INTEGER} and of the same kind as
@table @asis
@item @emph{Description}:
@code{SHIFTR} returns a value corresponding to @var{I} with all of the
-bits shifted right by @var{SHIFT} places. If the absolute value of
-@var{SHIFT} is greater than @code{BIT_SIZE(I)}, the value is undefined.
-Bits shifted out from the right end are lost, and bits shifted in from
-the left end are set to 0.
+bits shifted right by @var{SHIFT} places. @var{SHIFT} shall be
+nonnegative and less than or equal to @code{BIT_SIZE(I)}, otherwise
+the result value is undefined. Bits shifted out from the right end
+are lost, and bits shifted in from the left end are set to 0.
@item @emph{Standard}:
Fortran 2008 and later
diff --git a/gcc/fortran/invoke.texi b/gcc/fortran/invoke.texi
index efc7aea..2b08ac4 100644
--- a/gcc/fortran/invoke.texi
+++ b/gcc/fortran/invoke.texi
@@ -117,16 +117,16 @@ by type. Explanations are in the following sections.
@item Fortran Language Options
@xref{Fortran Dialect Options,,Options controlling Fortran dialect}.
@gccoptlist{-fall-intrinsics -fbackslash -fcray-pointer -fd-lines-as-code @gol
--fd-lines-as-comments @gol
--fdec -fdec-structure -fdec-intrinsic-ints -fdec-static -fdec-math @gol
--fdec-include -fdefault-double-8 -fdefault-integer-8 -fdefault-real-8 @gol
--fdefault-real-10 -fdefault-real-16 -fdollar-ok -ffixed-line-length-@var{n} @gol
--ffixed-line-length-none -fpad-source -ffree-form -ffree-line-length-@var{n} @gol
--ffree-line-length-none -fimplicit-none -finteger-4-integer-8 @gol
--fmax-identifier-length -fmodule-private -ffixed-form -fno-range-check @gol
--fopenacc -fopenmp -freal-4-real-10 -freal-4-real-16 -freal-4-real-8 @gol
--freal-8-real-10 -freal-8-real-16 -freal-8-real-4 -std=@var{std}
--ftest-forall-temp
+-fd-lines-as-comments -fdec -fdec-structure -fdec-intrinsic-ints @gol
+-fdec-static -fdec-math -fdec-include -fdec-format-defaults @gol
+-fdec-blank-format-item -fdefault-double-8 -fdefault-integer-8 @gol
+-fdefault-real-8 -fdefault-real-10 -fdefault-real-16 -fdollar-ok @gol
+-ffixed-line-length-@var{n} -ffixed-line-length-none -fpad-source @gol
+-ffree-form -ffree-line-length-@var{n} -ffree-line-length-none @gol
+-fimplicit-none -finteger-4-integer-8 -fmax-identifier-length @gol
+-fmodule-private -ffixed-form -fno-range-check -fopenacc -fopenmp @gol
+-freal-4-real-10 -freal-4-real-16 -freal-4-real-8 -freal-8-real-10 @gol
+-freal-8-real-16 -freal-8-real-4 -std=@var{std} -ftest-forall-temp
}
@item Preprocessing Options
@@ -181,7 +181,8 @@ and warnings}.
@item Code Generation Options
@xref{Code Gen Options,,Options for code generation conventions}.
@gccoptlist{-faggressive-function-elimination -fblas-matmul-limit=@var{n} @gol
--fbounds-check -fcheck-array-temporaries @gol
+-fbounds-check -ftail-call-workaround -ftail-call-workaround=@var{n} @gol
+-fcheck-array-temporaries @gol
-fcheck=@var{<all|array-temps|bounds|do|mem|pointer|recursion>} @gol
-fcoarray=@var{<none|single|lib>} -fexternal-blas -ff2c
-ffrontend-loop-interchange @gol
@@ -283,6 +284,16 @@ Enable parsing of INCLUDE as a statement in addition to parsing it as
INCLUDE line. When parsed as INCLUDE statement, INCLUDE does not have to
be on a single line and can use line continuations.
+@item -fdec-format-defaults
+@opindex @code{fdec-format-defaults}
+Enable format specifiers F, G and I to be used without width specifiers,
+default widths will be used instead.
+
+@item -fdec-blank-format-item
+@opindex @code{fdec-blank-format-item}
+Enable a blank format item at the end of a format specification i.e. nothing
+following the final comma.
+
@item -fdollar-ok
@opindex @code{fdollar-ok}
@cindex @code{$}
@@ -1617,6 +1628,39 @@ warnings for generated array temporaries.
@c Note: This option is also referred in gcc's manpage
Deprecated alias for @option{-fcheck=bounds}.
+@item -ftail-call-workaround
+@itemx -ftail-call-workaround=@var{n}
+@opindex @code{tail-call-workaround}
+Some C interfaces to Fortran codes violate the gfortran ABI by
+omitting the hidden character length arguments as described in
+@xref{Argument passing conventions}. This can lead to crashes
+because pushing arguments for tail calls can overflow the stack.
+
+To provide a workaround for existing binary packages, this option
+disables tail call optimization for gfortran procedures with character
+arguments. With @option{-ftail-call-workaround=2} tail call optimization
+is disabled in all gfortran procedures with character arguments,
+with @option{-ftail-call-workaround=1} or equivalent
+@option{-ftail-call-workaround} only in gfortran procedures with character
+arguments that call implicitly prototyped procedures.
+
+Using this option can lead to problems including crashes due to
+insufficient stack space.
+
+It is @emph{very strongly} recommended to fix the code in question.
+The @option{-fc-prototypes-external} option can be used to generate
+prototypes which conform to gfortran's ABI, for inclusion in the
+source code.
+
+Support for this option will likely be withdrawn in a future release
+of gfortran.
+
+The negative form, @option{-fno-tail-call-workaround} or equivalent
+@option{-ftail-call-workaround=0}, can be used to disable this option.
+
+Default is currently @option{-ftail-call-workaround}, this will change
+in future releases.
+
@item -fcheck-array-temporaries
@opindex @code{fcheck-array-temporaries}
Deprecated alias for @option{-fcheck=array-temps}.
diff --git a/gcc/fortran/io.c b/gcc/fortran/io.c
index 9828897..cd21c6b 100644
--- a/gcc/fortran/io.c
+++ b/gcc/fortran/io.c
@@ -596,12 +596,16 @@ token_to_string (format_token t)
static bool
check_format (bool is_input)
{
- const char *posint_required = _("Positive width required");
- const char *nonneg_required = _("Nonnegative width required");
- const char *unexpected_element = _("Unexpected element %qc in format "
- "string at %L");
- const char *unexpected_end = _("Unexpected end of format string");
- const char *zero_width = _("Zero width in format descriptor");
+ const char *posint_required
+ = G_("Positive width required in format string at %L");
+ const char *nonneg_required
+ = G_("Nonnegative width required in format string at %L");
+ const char *unexpected_element
+ = G_("Unexpected element %qc in format string at %L");
+ const char *unexpected_end
+ = G_("Unexpected end of format string in format string at %L");
+ const char *zero_width
+ = G_("Zero width in format descriptor in format string at %L");
const char *error = NULL;
format_token t, u;
@@ -621,7 +625,7 @@ check_format (bool is_input)
goto fail;
if (t != FMT_LPAREN)
{
- error = _("Missing leading left parenthesis");
+ error = G_("Missing leading left parenthesis in format string at %L");
goto syntax;
}
@@ -650,7 +654,8 @@ format_item_1:
level++;
goto format_item;
}
- error = _("Left parenthesis required after %<*%>");
+ error = G_("Left parenthesis required after %<*%> in format string "
+ "at %L");
goto syntax;
case FMT_POSINT:
@@ -681,7 +686,7 @@ format_item_1:
goto fail;
if (t != FMT_P)
{
- error = _("Expected P edit descriptor");
+ error = G_("Expected P edit descriptor in format string at %L");
goto syntax;
}
@@ -689,7 +694,8 @@ format_item_1:
case FMT_P:
/* P requires a prior number. */
- error = _("P descriptor requires leading scale factor");
+ error = G_("P descriptor requires leading scale factor in format "
+ "string at %L");
goto syntax;
case FMT_X:
@@ -756,6 +762,15 @@ format_item_1:
error = unexpected_end;
goto syntax;
+ case FMT_RPAREN:
+ if (flag_dec_blank_format_item)
+ goto finished;
+ else
+ {
+ error = G_("Missing item in format string at %L");
+ goto syntax;
+ }
+
default:
error = unexpected_element;
goto syntax;
@@ -783,7 +798,8 @@ data_desc:
&& t != FMT_F && t != FMT_E && t != FMT_EN && t != FMT_ES
&& t != FMT_D && t != FMT_G && t != FMT_RPAREN && t != FMT_SLASH)
{
- error = _("Comma required after P descriptor");
+ error = G_("Comma required after P descriptor in format string "
+ "at %L");
goto syntax;
}
if (t != FMT_COMMA)
@@ -794,10 +810,11 @@ data_desc:
if (t == FMT_ERROR)
goto fail;
}
- if (t != FMT_F && t != FMT_E && t != FMT_EN && t != FMT_ES && t != FMT_D
- && t != FMT_G && t != FMT_RPAREN && t != FMT_SLASH)
+ if (t != FMT_F && t != FMT_E && t != FMT_EN && t != FMT_ES
+ && t != FMT_D && t != FMT_G && t != FMT_RPAREN && t != FMT_SLASH)
{
- error = _("Comma required after P descriptor");
+ error = G_("Comma required after P descriptor in format string "
+ "at %L");
goto syntax;
}
}
@@ -811,7 +828,8 @@ data_desc:
t = format_lex ();
if (t != FMT_POSINT)
{
- error = _("Positive width required with T descriptor");
+ error = G_("Positive width required with T descriptor in format "
+ "string at %L");
goto syntax;
}
break;
@@ -894,7 +912,8 @@ data_desc:
u = format_lex ();
if (u == FMT_E)
{
- error = _("E specifier not allowed with g0 descriptor");
+ error = G_("E specifier not allowed with g0 descriptor in "
+ "format string at %L");
goto syntax;
}
saved_token = u;
@@ -903,6 +922,13 @@ data_desc:
if (u != FMT_POSINT)
{
+ if (flag_dec_format_defaults)
+ {
+ /* Assume a default width based on the variable size. */
+ saved_token = u;
+ break;
+ }
+
format_locus.nextc += format_string_pos;
gfc_error ("Positive width required in format "
"specifier %s at %L", token_to_string (t),
@@ -954,9 +980,7 @@ data_desc:
if (u == FMT_ERROR)
goto fail;
if (u != FMT_E)
- {
- saved_token = u;
- }
+ saved_token = u;
else
{
u = format_lex ();
@@ -964,7 +988,8 @@ data_desc:
goto fail;
if (u != FMT_POSINT)
{
- error = _("Positive exponent width required");
+ error = G_("Positive exponent width required in format string "
+ "at %L");
goto syntax;
}
}
@@ -1010,7 +1035,8 @@ data_desc:
goto dtio_vlist;
if (t != FMT_RPAREN)
{
- error = _("Right parenthesis expected at %C");
+ error = G_("Right parenthesis expected at %C in format string "
+ "at %L");
goto syntax;
}
goto between_desc;
@@ -1027,6 +1053,13 @@ data_desc:
goto fail;
if (t != FMT_ZERO && t != FMT_POSINT)
{
+ if (flag_dec_format_defaults)
+ {
+ /* Assume the default width is expected here and continue lexing. */
+ value = 0; /* It doesn't matter what we set the value to here. */
+ saved_token = t;
+ break;
+ }
error = nonneg_required;
goto syntax;
}
@@ -1044,7 +1077,8 @@ data_desc:
/* Warn if -std=legacy, otherwise error. */
if (gfc_option.warn_std != 0)
{
- error = _("Period required in format specifier");
+ error = G_("Period required in format specifier in format "
+ "string at %L");
goto syntax;
}
if (mode != MODE_FORMAT)
@@ -1096,8 +1130,17 @@ data_desc:
goto fail;
if (t != FMT_ZERO && t != FMT_POSINT)
{
- error = nonneg_required;
- goto syntax;
+ if (flag_dec_format_defaults)
+ {
+ /* Assume the default width is expected here and continue lexing. */
+ value = 0; /* It doesn't matter what we set the value to here. */
+ saved_token = t;
+ }
+ else
+ {
+ error = nonneg_required;
+ goto syntax;
+ }
}
else if (is_input && t == FMT_ZERO)
{
@@ -1109,9 +1152,7 @@ data_desc:
if (t == FMT_ERROR)
goto fail;
if (t != FMT_PERIOD)
- {
- saved_token = t;
- }
+ saved_token = t;
else
{
t = format_lex ();
@@ -1239,7 +1280,7 @@ syntax:
if (error == unexpected_element)
gfc_error (error, error_element, &format_locus);
else
- gfc_error ("%s in format string at %L", error, &format_locus);
+ gfc_error (error, &format_locus);
fail:
rv = false;
@@ -3287,6 +3328,14 @@ gfc_resolve_dt (gfc_dt *dt, locus *loc)
return false;
}
+ if (e->symtree && e->symtree->n.sym->attr.flavor == FL_PARAMETER
+ && e->ts.type == BT_CHARACTER)
+ {
+ gfc_error ("UNIT specification at %L must "
+ "not be a character PARAMETER", &e->where);
+ return false;
+ }
+
if (gfc_resolve_expr (e)
&& (e->ts.type != BT_INTEGER
&& (e->ts.type != BT_CHARACTER || e->expr_type != EXPR_VARIABLE)))
@@ -4368,8 +4417,8 @@ get_io_list:
}
/* See if we want to use defaults for missing exponents in real transfers
- and other DEC runtime extensions. */
- if (flag_dec)
+ and other DEC runtime extensions. */
+ if (flag_dec_format_defaults)
dt->dec_ext = 1;
/* A full IO statement has been matched. Check the constraints. spec_end is
diff --git a/gcc/fortran/lang.opt b/gcc/fortran/lang.opt
index be722d7..88674cb 100644
--- a/gcc/fortran/lang.opt
+++ b/gcc/fortran/lang.opt
@@ -444,10 +444,18 @@ fdec
Fortran Var(flag_dec)
Enable all DEC language extensions.
+fdec-blank-format-item
+Fortran Var(flag_dec_blank_format_item)
+Enable the use of blank format items in format strings.
+
fdec-include
Fortran Var(flag_dec_include)
Enable legacy parsing of INCLUDE as statement.
+fdec-format-defaults
+Fortran Var(flag_dec_format_defaults)
+Enable default widths for i, f and g format specifiers.
+
fdec-intrinsic-ints
Fortran Var(flag_dec_intrinsic_ints)
Enable kind-specific variants of integer intrinsic functions.
@@ -758,6 +766,13 @@ fsign-zero
Fortran Var(flag_sign_zero) Init(1)
Apply negative sign to zero values.
+ftail-call-workaround
+Fortran Alias(ftail-call-workaround=,1,0)
+
+ftail-call-workaround=
+Fortran RejectNegative Joined UInteger IntegerRange(0, 2) Var(flag_tail_call_workaround) Init(1)
+Disallow tail call optimization when a calling routine may have omitted character lengths.
+
funderscoring
Fortran Var(flag_underscoring) Init(1)
Append underscores to externally visible names.
diff --git a/gcc/fortran/match.c b/gcc/fortran/match.c
index 69698e5..0f3b213 100644
--- a/gcc/fortran/match.c
+++ b/gcc/fortran/match.c
@@ -5115,6 +5115,14 @@ gfc_match_common (void)
gfc_array_spec *as;
gfc_equiv *e1, *e2;
match m;
+ char c;
+
+ /* COMMON has been matched. In free form source code, the next character
+ needs to be whitespace or '/'. Check that here. Fixed form source
+ code needs to be checked below. */
+ c = gfc_peek_ascii_char ();
+ if (gfc_current_form == FORM_FREE && !gfc_is_whitespace (c) && c != '/')
+ return MATCH_NO;
as = NULL;
@@ -5279,10 +5287,24 @@ gfc_match_common (void)
gfc_gobble_whitespace ();
if (gfc_match_eos () == MATCH_YES)
goto done;
- if (gfc_peek_ascii_char () == '/')
+ c = gfc_peek_ascii_char ();
+ if (c == '/')
break;
- if (gfc_match_char (',') != MATCH_YES)
- goto syntax;
+ if (c != ',')
+ {
+ /* In Fixed form source code, gfortran can end up here for an
+ expression of the form COMMONI = RHS. This may not be an
+ error, so return MATCH_NO. */
+ if (gfc_current_form == FORM_FIXED && c == '=')
+ {
+ gfc_free_array_spec (as);
+ return MATCH_NO;
+ }
+ goto syntax;
+ }
+ else
+ gfc_match_char (',');
+
gfc_gobble_whitespace ();
if (gfc_peek_ascii_char () == '/')
break;
@@ -6219,6 +6241,13 @@ gfc_match_select_type (void)
if (m != MATCH_YES)
return m;
+ if (gfc_current_state() == COMP_MODULE
+ || gfc_current_state() == COMP_SUBMODULE)
+ {
+ gfc_error ("SELECT TYPE at %C cannot appear in this scope");
+ return MATCH_ERROR;
+ }
+
gfc_current_ns = gfc_build_block_ns (ns);
m = gfc_match (" %n => %e", name, &expr2);
if (m == MATCH_YES)
diff --git a/gcc/fortran/options.c b/gcc/fortran/options.c
index 02970d5..3bc79ef 100644
--- a/gcc/fortran/options.c
+++ b/gcc/fortran/options.c
@@ -74,6 +74,8 @@ set_dec_flags (int value)
SET_BITFLAG (flag_dec_static, value, value);
SET_BITFLAG (flag_dec_math, value, value);
SET_BITFLAG (flag_dec_include, value, value);
+ SET_BITFLAG (flag_dec_format_defaults, value, value);
+ SET_BITFLAG (flag_dec_blank_format_item, value, value);
}
/* Finalize DEC flags. */
diff --git a/gcc/fortran/parse.c b/gcc/fortran/parse.c
index 9d69359..8947299 100644
--- a/gcc/fortran/parse.c
+++ b/gcc/fortran/parse.c
@@ -6331,6 +6331,24 @@ done:
}
/* Dump C prototypes. */
+ if (flag_c_prototypes || flag_c_prototypes_external)
+ {
+ fprintf (stdout,
+ "#include <stddef.h>\n"
+ "#ifdef __cplusplus\n"
+ "#include <complex>\n"
+ "#define __GFORTRAN_FLOAT_COMPLEX std::complex<float>\n"
+ "#define __GFORTRAN_DOUBLE_COMPLEX std::complex<double>\n"
+ "#define __GFORTRAN_LONG_DOUBLE_COMPLEX std::complex<long double>\n"
+ "extern \"C\" {\n"
+ "#else\n"
+ "#define __GFORTRAN_FLOAT_COMPLEX float _Complex\n"
+ "#define __GFORTRAN_DOUBLE_COMPLEX double _Complex\n"
+ "#define __GFORTRAN_LONG_DOUBLE_COMPLEX long double _Complex\n"
+ "#endif\n\n");
+ }
+
+ /* First dump BIND(C) prototypes. */
if (flag_c_prototypes)
{
for (gfc_current_ns = gfc_global_ns_list; gfc_current_ns;
@@ -6342,6 +6360,9 @@ done:
if (flag_c_prototypes_external)
gfc_dump_external_c_prototypes (stdout);
+ if (flag_c_prototypes || flag_c_prototypes_external)
+ fprintf (stdout, "\n#ifdef __cplusplus\n}\n#endif\n");
+
/* Do the translation. */
translate_all_program_units (gfc_global_ns_list);
diff --git a/gcc/fortran/resolve.c b/gcc/fortran/resolve.c
index 8232deb..c82e8f2 100644
--- a/gcc/fortran/resolve.c
+++ b/gcc/fortran/resolve.c
@@ -583,6 +583,9 @@ resolve_contained_fntype (gfc_symbol *sym, gfc_namespace *ns)
|| sym->attr.entry_master)
return;
+ if (!sym->result)
+ return;
+
/* Try to find out of what the return type is. */
if (sym->result->ts.type == BT_UNKNOWN && sym->result->ts.interface == NULL)
{
@@ -1862,6 +1865,25 @@ resolve_procedure_expression (gfc_expr* expr)
}
+/* Check that name is not a derived type. */
+
+static bool
+is_dt_name (const char *name)
+{
+ gfc_symbol *dt_list, *dt_first;
+
+ dt_list = dt_first = gfc_derived_types;
+ for (; dt_list; dt_list = dt_list->dt_next)
+ {
+ if (strcmp(dt_list->name, name) == 0)
+ return true;
+ if (dt_first == dt_list->dt_next)
+ break;
+ }
+ return false;
+}
+
+
/* Resolve an actual argument list. Most of the time, this is just
resolving the expressions in the list.
The exception is that we sometimes have to decide whether arguments
@@ -1923,6 +1945,13 @@ resolve_actual_arglist (gfc_actual_arglist *arg, procedure_type ptype,
sym = e->symtree->n.sym;
+ if (sym->attr.flavor == FL_PROCEDURE && is_dt_name (sym->name))
+ {
+ gfc_error ("Derived type %qs is used as an actual "
+ "argument at %L", sym->name, &e->where);
+ goto cleanup;
+ }
+
if (sym->attr.flavor == FL_PROCEDURE
|| sym->attr.intrinsic
|| sym->attr.external)
@@ -6544,7 +6573,6 @@ resolve_typebound_function (gfc_expr* e)
}
c = gfc_find_component (declared, "_data", true, true, NULL);
- declared = c->ts.u.derived;
/* Treat the call as if it is a typebound procedure, in order to roll
out the correct name for the specific function. */
@@ -12359,6 +12387,10 @@ deferred_requirements (gfc_symbol *sym)
|| sym->attr.associate_var
|| sym->attr.omp_udr_artificial_var))
{
+ /* If a function has a result variable, only check the variable. */
+ if (sym->result && sym->name != sym->result->name)
+ return true;
+
gfc_error ("Entity %qs at %L has a deferred type parameter and "
"requires either the POINTER or ALLOCATABLE attribute",
sym->name, &sym->declared_at);
@@ -12569,6 +12601,10 @@ resolve_fl_procedure (gfc_symbol *sym, int mp_flag)
&& !resolve_fl_var_and_proc (sym, mp_flag))
return false;
+ /* Constraints on deferred type parameter. */
+ if (!deferred_requirements (sym))
+ return false;
+
if (sym->ts.type == BT_CHARACTER)
{
gfc_charlen *cl = sym->ts.u.cl;
diff --git a/gcc/fortran/simplify.c b/gcc/fortran/simplify.c
index 6c1f4bd..2d20913 100644
--- a/gcc/fortran/simplify.c
+++ b/gcc/fortran/simplify.c
@@ -4714,7 +4714,7 @@ gfc_simplify_matmul (gfc_expr *matrix_a, gfc_expr *matrix_b)
else
gcc_unreachable();
- offset_a = offset_b = 0;
+ offset_b = 0;
for (col = 0; col < result_columns; ++col)
{
offset_a = 0;
@@ -6999,20 +6999,17 @@ gfc_simplify_scan (gfc_expr *e, gfc_expr *c, gfc_expr *b, gfc_expr *kind)
indx = 0;
}
else
- {
- i = 0;
- for (indx = len; indx > 0; indx--)
- {
- for (i = 0; i < lenc; i++)
- {
- if (c->value.character.string[i]
- == e->value.character.string[indx - 1])
- break;
- }
- if (i < lenc)
- break;
- }
- }
+ for (indx = len; indx > 0; indx--)
+ {
+ for (i = 0; i < lenc; i++)
+ {
+ if (c->value.character.string[i]
+ == e->value.character.string[indx - 1])
+ break;
+ }
+ if (i < lenc)
+ break;
+ }
}
result = gfc_get_int_expr (k, &e->where, indx);
diff --git a/gcc/fortran/symbol.c b/gcc/fortran/symbol.c
index ec75322..f427363 100644
--- a/gcc/fortran/symbol.c
+++ b/gcc/fortran/symbol.c
@@ -4529,16 +4529,6 @@ verify_bind_c_derived_type (gfc_symbol *derived_sym)
curr_comp = curr_comp->next;
} while (curr_comp != NULL);
-
- /* Make sure we don't have conflicts with the attributes. */
- if (derived_sym->attr.access == ACCESS_PRIVATE)
- {
- gfc_error ("Derived type %qs at %L cannot be declared with both "
- "PRIVATE and BIND(C) attributes", derived_sym->name,
- &(derived_sym->declared_at));
- retval = false;
- }
-
if (derived_sym->attr.sequence != 0)
{
gfc_error ("Derived type %qs at %L cannot have the SEQUENCE "
diff --git a/gcc/fortran/trans-array.c b/gcc/fortran/trans-array.c
index 55879af..1ab0361 100644
--- a/gcc/fortran/trans-array.c
+++ b/gcc/fortran/trans-array.c
@@ -1239,6 +1239,7 @@ gfc_trans_create_temp_array (stmtblock_t * pre, stmtblock_t * post, gfc_ss * ss,
tree nelem;
tree cond;
tree or_expr;
+ tree elemsize;
tree class_expr = NULL_TREE;
int n, dim, tmp_dim;
int total_dim = 0;
@@ -1333,15 +1334,6 @@ gfc_trans_create_temp_array (stmtblock_t * pre, stmtblock_t * post, gfc_ss * ss,
tmp = gfc_conv_descriptor_dtype (desc);
gfc_add_modify (pre, tmp, gfc_get_dtype (TREE_TYPE (desc)));
- /* Also set the span for derived types, since they can be used in
- component references to arrays of this type. */
- if (TREE_CODE (eltype) == RECORD_TYPE)
- {
- tmp = TYPE_SIZE_UNIT (eltype);
- tmp = fold_convert (gfc_array_index_type, tmp);
- gfc_conv_descriptor_span_set (pre, desc, tmp);
- }
-
/*
Fill in the bounds and stride. This is a packed array, so:
@@ -1413,22 +1405,21 @@ gfc_trans_create_temp_array (stmtblock_t * pre, stmtblock_t * post, gfc_ss * ss,
}
}
+ if (class_expr == NULL_TREE)
+ elemsize = fold_convert (gfc_array_index_type,
+ TYPE_SIZE_UNIT (gfc_get_element_type (type)));
+ else
+ elemsize = gfc_class_vtab_size_get (class_expr);
+
/* Get the size of the array. */
if (size && !callee_alloc)
{
- tree elemsize;
/* If or_expr is true, then the extent in at least one
dimension is zero and the size is set to zero. */
size = fold_build3_loc (input_location, COND_EXPR, gfc_array_index_type,
or_expr, gfc_index_zero_node, size);
nelem = size;
- if (class_expr == NULL_TREE)
- elemsize = fold_convert (gfc_array_index_type,
- TYPE_SIZE_UNIT (gfc_get_element_type (type)));
- else
- elemsize = gfc_class_vtab_size_get (class_expr);
-
size = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
size, elemsize);
}
@@ -1438,6 +1429,10 @@ gfc_trans_create_temp_array (stmtblock_t * pre, stmtblock_t * post, gfc_ss * ss,
size = NULL_TREE;
}
+ /* Set the span. */
+ tmp = fold_convert (gfc_array_index_type, elemsize);
+ gfc_conv_descriptor_span_set (pre, desc, tmp);
+
gfc_trans_allocate_array_storage (pre, post, info, size, nelem, initial,
dynamic, dealloc);
@@ -4799,8 +4794,6 @@ gfc_could_be_alias (gfc_ss * lss, gfc_ss * rss)
lsym_pointer = lsym->attr.pointer;
lsym_target = lsym->attr.target;
- lsym_pointer = lsym->attr.pointer;
- lsym_target = lsym->attr.target;
for (rref = rexpr->ref; rref != rss->info->data.array.ref; rref = rref->next)
{
@@ -7248,6 +7241,8 @@ gfc_conv_expr_descriptor (gfc_se *se, gfc_expr *expr)
if (se->force_tmp)
need_tmp = 1;
+ else if (se->force_no_tmp)
+ need_tmp = 0;
if (need_tmp)
full = 0;
@@ -7869,6 +7864,23 @@ array_parameter_size (tree desc, gfc_expr *expr, tree *size)
*size, fold_convert (gfc_array_index_type, elem));
}
+/* Helper function - return true if the argument is a pointer. */
+
+static bool
+is_pointer (gfc_expr *e)
+{
+ gfc_symbol *sym;
+
+ if (e->expr_type != EXPR_VARIABLE || e->symtree == NULL)
+ return false;
+
+ sym = e->symtree->n.sym;
+ if (sym == NULL)
+ return false;
+
+ return sym->attr.pointer || sym->attr.proc_pointer;
+}
+
/* Convert an array for passing as an actual parameter. */
void
@@ -8120,6 +8132,20 @@ gfc_conv_array_parameter (gfc_se * se, gfc_expr * expr, bool g77,
"Creating array temporary at %L", &expr->where);
}
+ /* When optmizing, we can use gfc_conv_subref_array_arg for
+ making the packing and unpacking operation visible to the
+ optimizers. */
+
+ if (g77 && optimize && !optimize_size && expr->expr_type == EXPR_VARIABLE
+ && !is_pointer (expr) && ! gfc_has_dimen_vector_ref (expr)
+ && (fsym == NULL || fsym->ts.type != BT_ASSUMED))
+ {
+ gfc_conv_subref_array_arg (se, expr, g77,
+ fsym ? fsym->attr.intent : INTENT_INOUT,
+ false, fsym, proc_name, sym, true);
+ return;
+ }
+
ptr = build_call_expr_loc (input_location,
gfor_fndecl_in_pack, 1, desc);
diff --git a/gcc/fortran/trans-common.c b/gcc/fortran/trans-common.c
index debdbd9..9fc23ff 100644
--- a/gcc/fortran/trans-common.c
+++ b/gcc/fortran/trans-common.c
@@ -1007,10 +1007,8 @@ static void
add_equivalences (bool *saw_equiv)
{
segment_info *f;
- bool seen_one, more;
+ bool more = TRUE;
- seen_one = false;
- more = TRUE;
while (more)
{
more = FALSE;
@@ -1019,7 +1017,7 @@ add_equivalences (bool *saw_equiv)
if (!f->sym->equiv_built)
{
f->sym->equiv_built = 1;
- seen_one = find_equivalence (f);
+ bool seen_one = find_equivalence (f);
if (seen_one)
{
*saw_equiv = true;
diff --git a/gcc/fortran/trans-decl.c b/gcc/fortran/trans-decl.c
index a0e1f6a..64ce4bb 100644
--- a/gcc/fortran/trans-decl.c
+++ b/gcc/fortran/trans-decl.c
@@ -1400,12 +1400,7 @@ add_attributes_to_decl (symbol_attribute sym_attr, tree list)
list = chainon (list, attr);
}
- if (sym_attr.omp_declare_target_link)
- list = tree_cons (get_identifier ("omp declare target link"),
- NULL_TREE, list);
- else if (sym_attr.omp_declare_target)
- list = tree_cons (get_identifier ("omp declare target"),
- NULL_TREE, list);
+ tree clauses = NULL_TREE;
if (sym_attr.oacc_routine_lop != OACC_ROUTINE_LOP_NONE)
{
@@ -1430,11 +1425,25 @@ add_attributes_to_decl (symbol_attribute sym_attr, tree list)
gcc_unreachable ();
}
tree c = build_omp_clause (UNKNOWN_LOCATION, code);
+ OMP_CLAUSE_CHAIN (c) = clauses;
+ clauses = c;
- tree dims = oacc_build_routine_dims (c);
+ tree dims = oacc_build_routine_dims (clauses);
list = oacc_replace_fn_attrib_attr (list, dims);
}
+ if (sym_attr.omp_declare_target_link
+ || sym_attr.oacc_declare_link)
+ list = tree_cons (get_identifier ("omp declare target link"),
+ NULL_TREE, list);
+ else if (sym_attr.omp_declare_target
+ || sym_attr.oacc_declare_create
+ || sym_attr.oacc_declare_copyin
+ || sym_attr.oacc_declare_deviceptr
+ || sym_attr.oacc_declare_device_resident)
+ list = tree_cons (get_identifier ("omp declare target"),
+ clauses, list);
+
return list;
}
@@ -2513,6 +2522,17 @@ create_function_arglist (gfc_symbol * sym)
TREE_READONLY (length) = 1;
gfc_finish_decl (length);
+ /* Marking the length DECL_HIDDEN_STRING_LENGTH will lead
+ to tail calls being disabled. Only do that if we
+ potentially have broken callers. */
+ if (flag_tail_call_workaround
+ && f->sym->ts.u.cl
+ && f->sym->ts.u.cl->length
+ && f->sym->ts.u.cl->length->expr_type == EXPR_CONSTANT
+ && (flag_tail_call_workaround == 2
+ || f->sym->ns->implicit_interface_calls))
+ DECL_HIDDEN_STRING_LENGTH (length) = 1;
+
/* Remember the passed value. */
if (!f->sym->ts.u.cl || f->sym->ts.u.cl->passed_length)
{
@@ -4278,8 +4298,10 @@ convert_CFI_desc (gfc_wrapped_block * block, gfc_symbol *sym)
tree CFI_desc_ptr;
tree dummy_ptr;
tree tmp;
+ tree present;
tree incoming;
tree outgoing;
+ stmtblock_t outer_block;
stmtblock_t tmpblock;
/* dummy_ptr will be the pointer to the passed array descriptor,
@@ -4303,6 +4325,12 @@ convert_CFI_desc (gfc_wrapped_block * block, gfc_symbol *sym)
gfc_desc_ptr = gfc_create_var (tmp, "gfc_desc_ptr");
CFI_desc_ptr = gfc_create_var (pvoid_type_node, "CFI_desc_ptr");
+ /* Fix the condition for the presence of the argument. */
+ gfc_init_block (&outer_block);
+ present = fold_build2_loc (input_location, NE_EXPR,
+ logical_type_node, dummy_ptr,
+ build_int_cst (TREE_TYPE (dummy_ptr), 0));
+
gfc_init_block (&tmpblock);
/* Pointer to the gfc descriptor. */
gfc_add_modify (&tmpblock, gfc_desc_ptr,
@@ -4318,16 +4346,43 @@ convert_CFI_desc (gfc_wrapped_block * block, gfc_symbol *sym)
/* Set the dummy pointer to point to the gfc_descriptor. */
gfc_add_modify (&tmpblock, dummy_ptr,
fold_convert (TREE_TYPE (dummy_ptr), gfc_desc_ptr));
- incoming = gfc_finish_block (&tmpblock);
- gfc_init_block (&tmpblock);
+ /* The hidden string length is not passed to bind(C) procedures so set
+ it from the descriptor element length. */
+ if (sym->ts.type == BT_CHARACTER
+ && sym->ts.u.cl->backend_decl
+ && VAR_P (sym->ts.u.cl->backend_decl))
+ {
+ tmp = build_fold_indirect_ref_loc (input_location, dummy_ptr);
+ tmp = gfc_conv_descriptor_elem_len (tmp);
+ gfc_add_modify (&tmpblock, sym->ts.u.cl->backend_decl,
+ fold_convert (TREE_TYPE (sym->ts.u.cl->backend_decl),
+ tmp));
+ }
+
+ /* Check that the argument is present before executing the above. */
+ incoming = build3_v (COND_EXPR, present,
+ gfc_finish_block (&tmpblock),
+ build_empty_stmt (input_location));
+ gfc_add_expr_to_block (&outer_block, incoming);
+ incoming = gfc_finish_block (&outer_block);
+
+
/* Convert the gfc descriptor back to the CFI type before going
- out of scope. */
+ out of scope, if the CFI type was present at entry. */
+ gfc_init_block (&outer_block);
+ gfc_init_block (&tmpblock);
+
tmp = gfc_build_addr_expr (ppvoid_type_node, CFI_desc_ptr);
outgoing = build_call_expr_loc (input_location,
gfor_fndecl_gfc_to_cfi, 2, tmp, gfc_desc_ptr);
gfc_add_expr_to_block (&tmpblock, outgoing);
- outgoing = gfc_finish_block (&tmpblock);
+
+ outgoing = build3_v (COND_EXPR, present,
+ gfc_finish_block (&tmpblock),
+ build_empty_stmt (input_location));
+ gfc_add_expr_to_block (&outer_block, outgoing);
+ outgoing = gfc_finish_block (&outer_block);
/* Add the lot to the procedure init and finally blocks. */
gfc_add_init_cleanup (block, incoming, outgoing);
@@ -4923,9 +4978,9 @@ gfc_trans_deferred_vars (gfc_symbol * proc_sym, gfc_wrapped_block * block)
for (f = gfc_sym_get_dummy_args (proc_sym); f; f = f->next)
{
- if (f->sym && f->sym->tlink == NULL && f->sym->ts.type == BT_CHARACTER)
+ if (f->sym && f->sym->tlink == NULL && f->sym->ts.type == BT_CHARACTER
+ && f->sym->ts.u.cl->backend_decl)
{
- gcc_assert (f->sym->ts.u.cl->backend_decl != NULL);
if (TREE_CODE (f->sym->ts.u.cl->backend_decl) == PARM_DECL)
gfc_trans_vla_type_sizes (f->sym, &tmpblock);
}
@@ -6436,6 +6491,7 @@ finish_oacc_declare (gfc_namespace *ns, gfc_symbol *sym, bool block)
gfc_omp_clauses *omp_clauses = NULL;
gfc_omp_namelist *n, *p;
+ module_oacc_clauses = NULL;
gfc_traverse_ns (ns, find_module_oacc_declare_clauses);
if (module_oacc_clauses && sym->attr.flavor == FL_PROGRAM)
@@ -6447,7 +6503,6 @@ finish_oacc_declare (gfc_namespace *ns, gfc_symbol *sym, bool block)
new_oc->clauses = module_oacc_clauses;
ns->oacc_declare = new_oc;
- module_oacc_clauses = NULL;
}
if (!ns->oacc_declare)
diff --git a/gcc/fortran/trans-expr.c b/gcc/fortran/trans-expr.c
index 21535ac..a4e8351 100644
--- a/gcc/fortran/trans-expr.c
+++ b/gcc/fortran/trans-expr.c
@@ -2309,7 +2309,9 @@ gfc_conv_substring (gfc_se * se, gfc_ref * ref, int kind,
start.expr = gfc_evaluate_now (start.expr, &se->pre);
/* Change the start of the string. */
- if (TYPE_STRING_FLAG (TREE_TYPE (se->expr)))
+ if ((TREE_CODE (TREE_TYPE (se->expr)) == ARRAY_TYPE
+ || TREE_CODE (TREE_TYPE (se->expr)) == INTEGER_TYPE)
+ && TYPE_STRING_FLAG (TREE_TYPE (se->expr)))
tmp = se->expr;
else
tmp = build_fold_indirect_ref_loc (input_location,
@@ -4576,8 +4578,10 @@ gfc_apply_interface_mapping (gfc_interface_mapping * mapping,
an actual argument derived type array is copied and then returned
after the function call. */
void
-gfc_conv_subref_array_arg (gfc_se * parmse, gfc_expr * expr, int g77,
- sym_intent intent, bool formal_ptr)
+gfc_conv_subref_array_arg (gfc_se *se, gfc_expr * expr, int g77,
+ sym_intent intent, bool formal_ptr,
+ const gfc_symbol *fsym, const char *proc_name,
+ gfc_symbol *sym, bool check_contiguous)
{
gfc_se lse;
gfc_se rse;
@@ -4594,6 +4598,36 @@ gfc_conv_subref_array_arg (gfc_se * parmse, gfc_expr * expr, int g77,
stmtblock_t body;
int n;
int dimen;
+ gfc_se work_se;
+ gfc_se *parmse;
+ bool pass_optional;
+
+ pass_optional = fsym && fsym->attr.optional && sym && sym->attr.optional;
+
+ if (pass_optional || check_contiguous)
+ {
+ gfc_init_se (&work_se, NULL);
+ parmse = &work_se;
+ }
+ else
+ parmse = se;
+
+ if (gfc_option.rtcheck & GFC_RTCHECK_ARRAY_TEMPS)
+ {
+ /* We will create a temporary array, so let us warn. */
+ char * msg;
+
+ if (fsym && proc_name)
+ msg = xasprintf ("An array temporary was created for argument "
+ "'%s' of procedure '%s'", fsym->name, proc_name);
+ else
+ msg = xasprintf ("An array temporary was created");
+
+ tmp = build_int_cst (logical_type_node, 1);
+ gfc_trans_runtime_check (false, true, tmp, &parmse->pre,
+ &expr->where, msg);
+ free (msg);
+ }
gfc_init_se (&lse, NULL);
gfc_init_se (&rse, NULL);
@@ -4848,6 +4882,168 @@ class_array_fcn:
else
parmse->expr = gfc_build_addr_expr (NULL_TREE, parmse->expr);
+ /* Basically make this into
+
+ if (present)
+ {
+ if (contiguous)
+ {
+ pointer = a;
+ }
+ else
+ {
+ parmse->pre();
+ pointer = parmse->expr;
+ }
+ }
+ else
+ pointer = NULL;
+
+ foo (pointer);
+ if (present && !contiguous)
+ se->post();
+
+ */
+
+ if (pass_optional || check_contiguous)
+ {
+ tree type;
+ stmtblock_t else_block;
+ tree pre_stmts, post_stmts;
+ tree pointer;
+ tree else_stmt;
+ tree present_var = NULL_TREE;
+ tree cont_var = NULL_TREE;
+ tree post_cond;
+
+ type = TREE_TYPE (parmse->expr);
+ pointer = gfc_create_var (type, "arg_ptr");
+
+ if (check_contiguous)
+ {
+ gfc_se cont_se, array_se;
+ stmtblock_t if_block, else_block;
+ tree if_stmt, else_stmt;
+ mpz_t size;
+ bool size_set;
+
+ cont_var = gfc_create_var (boolean_type_node, "contiguous");
+
+ /* If the size is known to be one at compile-time, set
+ cont_var to true unconditionally. This may look
+ inelegant, but we're only doing this during
+ optimization, so the statements will be optimized away,
+ and this saves complexity here. */
+
+ size_set = gfc_array_size (expr, &size);
+ if (size_set && mpz_cmp_ui (size, 1) == 0)
+ {
+ gfc_add_modify (&se->pre, cont_var,
+ build_one_cst (boolean_type_node));
+ }
+ else
+ {
+ /* cont_var = is_contiguous (expr); . */
+ gfc_init_se (&cont_se, parmse);
+ gfc_conv_is_contiguous_expr (&cont_se, expr);
+ gfc_add_block_to_block (&se->pre, &(&cont_se)->pre);
+ gfc_add_modify (&se->pre, cont_var, cont_se.expr);
+ gfc_add_block_to_block (&se->pre, &(&cont_se)->post);
+ }
+
+ if (size_set)
+ mpz_clear (size);
+
+ /* arrayse->expr = descriptor of a. */
+ gfc_init_se (&array_se, se);
+ gfc_conv_expr_descriptor (&array_se, expr);
+ gfc_add_block_to_block (&se->pre, &(&array_se)->pre);
+ gfc_add_block_to_block (&se->pre, &(&array_se)->post);
+
+ /* if_stmt = { pointer = &a[0]; } . */
+ gfc_init_block (&if_block);
+ tmp = gfc_conv_array_data (array_se.expr);
+ tmp = fold_convert (type, tmp);
+ gfc_add_modify (&if_block, pointer, tmp);
+ if_stmt = gfc_finish_block (&if_block);
+
+ /* else_stmt = { parmse->pre(); pointer = parmse->expr; } . */
+ gfc_init_block (&else_block);
+ gfc_add_block_to_block (&else_block, &parmse->pre);
+ gfc_add_modify (&else_block, pointer, parmse->expr);
+ else_stmt = gfc_finish_block (&else_block);
+
+ /* And put the above into an if statement. */
+ pre_stmts = fold_build3_loc (input_location, COND_EXPR, void_type_node,
+ gfc_likely (cont_var,
+ PRED_FORTRAN_CONTIGUOUS),
+ if_stmt, else_stmt);
+ }
+ else
+ {
+ /* pointer = pramse->expr; . */
+ gfc_add_modify (&parmse->pre, pointer, parmse->expr);
+ pre_stmts = gfc_finish_block (&parmse->pre);
+ }
+
+ if (pass_optional)
+ {
+ present_var = gfc_create_var (boolean_type_node, "present");
+
+ /* present_var = present(sym); . */
+ tmp = gfc_conv_expr_present (sym);
+ tmp = fold_convert (boolean_type_node, tmp);
+ gfc_add_modify (&se->pre, present_var, tmp);
+
+ /* else_stmt = { pointer = NULL; } . */
+ gfc_init_block (&else_block);
+ gfc_add_modify (&else_block, pointer, build_int_cst (type, 0));
+ else_stmt = gfc_finish_block (&else_block);
+
+ tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node,
+ gfc_likely (present_var,
+ PRED_FORTRAN_ABSENT_DUMMY),
+ pre_stmts, else_stmt);
+ gfc_add_expr_to_block (&se->pre, tmp);
+ }
+ else
+ gfc_add_expr_to_block (&se->pre, pre_stmts);
+
+ post_stmts = gfc_finish_block (&parmse->post);
+
+ /* Put together the post stuff, plus the optional
+ deallocation. */
+ if (check_contiguous)
+ {
+ /* !cont_var. */
+ tmp = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node,
+ cont_var,
+ build_zero_cst (boolean_type_node));
+ tmp = gfc_unlikely (tmp, PRED_FORTRAN_CONTIGUOUS);
+
+ if (pass_optional)
+ {
+ tree present_likely = gfc_likely (present_var,
+ PRED_FORTRAN_ABSENT_DUMMY);
+ post_cond = fold_build2_loc (input_location, TRUTH_ANDIF_EXPR,
+ boolean_type_node, present_likely,
+ tmp);
+ }
+ else
+ post_cond = tmp;
+ }
+ else
+ {
+ gcc_assert (pass_optional);
+ post_cond = present_var;
+ }
+
+ tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node, post_cond,
+ post_stmts, build_empty_stmt (input_location));
+ gfc_add_expr_to_block (&se->post, tmp);
+ se->expr = pointer;
+ }
+
return;
}
@@ -5006,6 +5202,7 @@ gfc_conv_gfc_desc_to_cfi_desc (gfc_se *parmse, gfc_expr *e, gfc_symbol *fsym)
if (e->rank != 0)
{
+ parmse->force_no_tmp = 1;
if (fsym->attr.contiguous
&& !gfc_is_simply_contiguous (e, false, true))
gfc_conv_subref_array_arg (parmse, e, false, fsym->attr.intent,
@@ -8715,7 +8912,6 @@ trans_class_vptr_len_assignment (stmtblock_t *block, gfc_expr * le,
from_len = rse->string_length;
else if (re->ts.type == BT_CHARACTER && re->ts.u.cl->length)
{
- from_len = gfc_get_expr_charlen (re);
gfc_init_se (&se, NULL);
gfc_conv_expr (&se, re->ts.u.cl->length);
gfc_add_block_to_block (block, &se.pre);
@@ -8784,23 +8980,6 @@ trans_caf_token_assign (gfc_se *lse, gfc_se *rse, gfc_expr *expr1,
}
}
-/* Indentify class valued proc_pointer assignments. */
-
-static bool
-pointer_assignment_is_proc_pointer (gfc_expr * expr1, gfc_expr * expr2)
-{
- gfc_ref * ref;
-
- ref = expr1->ref;
- while (ref && ref->next)
- ref = ref->next;
-
- return ref && ref->type == REF_COMPONENT
- && ref->u.c.component->attr.proc_pointer
- && expr2->expr_type == EXPR_VARIABLE
- && expr2->symtree->n.sym->attr.flavor == FL_PROCEDURE;
-}
-
/* Do everything that is needed for a CLASS function expr2. */
@@ -8853,7 +9032,7 @@ gfc_trans_pointer_assignment (gfc_expr * expr1, gfc_expr * expr2)
tree desc;
tree tmp;
tree expr1_vptr = NULL_TREE;
- bool scalar, non_proc_pointer_assign;
+ bool scalar, non_proc_ptr_assign;
gfc_ss *ss;
gfc_start_block (&block);
@@ -8861,7 +9040,9 @@ gfc_trans_pointer_assignment (gfc_expr * expr1, gfc_expr * expr2)
gfc_init_se (&lse, NULL);
/* Usually testing whether this is not a proc pointer assignment. */
- non_proc_pointer_assign = !pointer_assignment_is_proc_pointer (expr1, expr2);
+ non_proc_ptr_assign = !(gfc_expr_attr (expr1).proc_pointer
+ && expr2->expr_type == EXPR_VARIABLE
+ && expr2->symtree->n.sym->attr.flavor == FL_PROCEDURE);
/* Check whether the expression is a scalar or not; we cannot use
expr1->rank as it can be nonzero for proc pointers. */
@@ -8871,7 +9052,7 @@ gfc_trans_pointer_assignment (gfc_expr * expr1, gfc_expr * expr2)
gfc_free_ss_chain (ss);
if (expr1->ts.type == BT_DERIVED && expr2->ts.type == BT_CLASS
- && expr2->expr_type != EXPR_FUNCTION && non_proc_pointer_assign)
+ && expr2->expr_type != EXPR_FUNCTION && non_proc_ptr_assign)
{
gfc_add_data_component (expr2);
/* The following is required as gfc_add_data_component doesn't
@@ -8891,7 +9072,7 @@ gfc_trans_pointer_assignment (gfc_expr * expr1, gfc_expr * expr2)
else
gfc_conv_expr (&rse, expr2);
- if (non_proc_pointer_assign && expr1->ts.type == BT_CLASS)
+ if (non_proc_ptr_assign && expr1->ts.type == BT_CLASS)
{
trans_class_vptr_len_assignment (&block, expr1, expr2, &rse, NULL,
NULL);
@@ -9299,7 +9480,9 @@ gfc_conv_string_parameter (gfc_se * se)
return;
}
- if (TYPE_STRING_FLAG (TREE_TYPE (se->expr)))
+ if ((TREE_CODE (TREE_TYPE (se->expr)) == ARRAY_TYPE
+ || TREE_CODE (TREE_TYPE (se->expr)) == INTEGER_TYPE)
+ && TYPE_STRING_FLAG (TREE_TYPE (se->expr)))
{
if (TREE_CODE (se->expr) != INDIRECT_REF)
{
@@ -9987,10 +10170,6 @@ gfc_trans_array_constructor_copy (gfc_expr * expr1, gfc_expr * expr2)
stype = gfc_typenode_for_spec (&expr2->ts);
src = gfc_build_constant_array_constructor (expr2, stype);
- stype = TREE_TYPE (src);
- if (POINTER_TYPE_P (stype))
- stype = TREE_TYPE (stype);
-
return gfc_build_memcpy_call (dst, src, len);
}
@@ -10740,7 +10919,6 @@ gfc_trans_assignment_1 (gfc_expr * expr1, gfc_expr * expr2, bool init_flag,
&& (gfc_is_class_array_function (expr2)
|| gfc_is_alloc_class_scalar_function (expr2)))
{
- tmp = rse.expr;
tmp = gfc_nullify_alloc_comp (expr1->ts.u.derived, rse.expr, 0);
gfc_prepend_expr_to_block (&rse.post, tmp);
if (lss != gfc_ss_terminator && rss == gfc_ss_terminator)
diff --git a/gcc/fortran/trans-intrinsic.c b/gcc/fortran/trans-intrinsic.c
index e0a4c67..a7ebc41 100644
--- a/gcc/fortran/trans-intrinsic.c
+++ b/gcc/fortran/trans-intrinsic.c
@@ -2832,6 +2832,17 @@ static void
gfc_conv_intrinsic_is_contiguous (gfc_se * se, gfc_expr * expr)
{
gfc_expr *arg;
+ arg = expr->value.function.actual->expr;
+ gfc_conv_is_contiguous_expr (se, arg);
+ se->expr = fold_convert (gfc_typenode_for_spec (&expr->ts), se->expr);
+}
+
+/* This function does the work for gfc_conv_intrinsic_is_contiguous,
+ plus it can be called directly. */
+
+void
+gfc_conv_is_contiguous_expr (gfc_se *se, gfc_expr *arg)
+{
gfc_ss *ss;
gfc_se argse;
tree desc, tmp, stride, extent, cond;
@@ -2839,8 +2850,6 @@ gfc_conv_intrinsic_is_contiguous (gfc_se * se, gfc_expr * expr)
tree fncall0;
gfc_array_spec *as;
- arg = expr->value.function.actual->expr;
-
if (arg->ts.type == BT_CLASS)
gfc_add_class_array_ref (arg);
@@ -2878,7 +2887,7 @@ gfc_conv_intrinsic_is_contiguous (gfc_se * se, gfc_expr * expr)
cond = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node,
stride, build_int_cst (TREE_TYPE (stride), 1));
- for (i = 0; i < expr->value.function.actual->expr->rank - 1; i++)
+ for (i = 0; i < arg->rank - 1; i++)
{
tmp = gfc_conv_descriptor_lbound_get (desc, gfc_rank_cst[i]);
extent = gfc_conv_descriptor_ubound_get (desc, gfc_rank_cst[i]);
@@ -2896,7 +2905,7 @@ gfc_conv_intrinsic_is_contiguous (gfc_se * se, gfc_expr * expr)
cond = fold_build2_loc (input_location, TRUTH_AND_EXPR,
boolean_type_node, cond, tmp);
}
- se->expr = convert (gfc_typenode_for_spec (&expr->ts), cond);
+ se->expr = cond;
}
}
@@ -6337,6 +6346,7 @@ gfc_conv_intrinsic_shift (gfc_se * se, gfc_expr * expr, bool right_shift,
bool arithmetic)
{
tree args[2], type, num_bits, cond;
+ tree bigshift;
gfc_conv_intrinsic_function_args (se, expr, args, 2);
@@ -6356,6 +6366,18 @@ gfc_conv_intrinsic_shift (gfc_se * se, gfc_expr * expr, bool right_shift,
if (!arithmetic)
se->expr = fold_convert (type, se->expr);
+ if (!arithmetic)
+ bigshift = build_int_cst (type, 0);
+ else
+ {
+ tree nonneg = fold_build2_loc (input_location, GE_EXPR,
+ logical_type_node, args[0],
+ build_int_cst (TREE_TYPE (args[0]), 0));
+ bigshift = fold_build3_loc (input_location, COND_EXPR, type, nonneg,
+ build_int_cst (type, 0),
+ build_int_cst (type, -1));
+ }
+
/* The Fortran standard allows shift widths <= BIT_SIZE(I), whereas
gcc requires a shift width < BIT_SIZE(I), so we have to catch this
special case. */
@@ -6364,7 +6386,7 @@ gfc_conv_intrinsic_shift (gfc_se * se, gfc_expr * expr, bool right_shift,
args[1], num_bits);
se->expr = fold_build3_loc (input_location, COND_EXPR, type, cond,
- build_int_cst (type, 0), se->expr);
+ bigshift, se->expr);
}
/* ISHFT (I, SHIFT) = (abs (shift) >= BIT_SIZE (i))
@@ -10949,7 +10971,6 @@ conv_intrinsic_atomic_op (gfc_code *code)
fn = (built_in_function) ((int) fn
+ exact_log2 (tree_to_uhwi (TYPE_SIZE_UNIT (tmp)))
+ 1);
- tmp = builtin_decl_explicit (fn);
tree itype = TREE_TYPE (TREE_TYPE (atom));
tmp = builtin_decl_explicit (fn);
diff --git a/gcc/fortran/trans-openmp.c b/gcc/fortran/trans-openmp.c
index 0eb5956..8eae7bc 100644
--- a/gcc/fortran/trans-openmp.c
+++ b/gcc/fortran/trans-openmp.c
@@ -1199,7 +1199,6 @@ gfc_omp_finish_clause (tree c, gimple_seq *pre_p)
{
OMP_CLAUSE_CHAIN (c4) = OMP_CLAUSE_CHAIN (last);
OMP_CLAUSE_CHAIN (last) = c4;
- last = c4;
}
}
@@ -1222,7 +1221,8 @@ gfc_omp_scalar_p (tree decl)
|| GFC_CLASS_TYPE_P (type))
return false;
}
- if (TYPE_STRING_FLAG (type))
+ if ((TREE_CODE (type) == ARRAY_TYPE || TREE_CODE (type) == INTEGER_TYPE)
+ && TYPE_STRING_FLAG (type))
return false;
if (INTEGRAL_TYPE_P (type)
|| SCALAR_FLOAT_TYPE_P (type)
diff --git a/gcc/fortran/trans-stmt.c b/gcc/fortran/trans-stmt.c
index b9966ed..7c36563 100644
--- a/gcc/fortran/trans-stmt.c
+++ b/gcc/fortran/trans-stmt.c
@@ -1576,12 +1576,13 @@ gfc_trans_critical (gfc_code *code)
if (flag_coarray == GFC_FCOARRAY_LIB)
{
+ tree zero_size = build_zero_cst (size_type_node);
token = gfc_get_symbol_decl (code->resolved_sym);
token = GFC_TYPE_ARRAY_CAF_TOKEN (TREE_TYPE (token));
tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_lock, 7,
- token, integer_zero_node, integer_one_node,
+ token, zero_size, integer_one_node,
null_pointer_node, null_pointer_node,
- null_pointer_node, integer_zero_node);
+ null_pointer_node, zero_size);
gfc_add_expr_to_block (&block, tmp);
/* It guarantees memory consistency within the same segment */
@@ -1601,10 +1602,11 @@ gfc_trans_critical (gfc_code *code)
if (flag_coarray == GFC_FCOARRAY_LIB)
{
+ tree zero_size = build_zero_cst (size_type_node);
tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_unlock, 6,
- token, integer_zero_node, integer_one_node,
+ token, zero_size, integer_one_node,
null_pointer_node, null_pointer_node,
- integer_zero_node);
+ zero_size);
gfc_add_expr_to_block (&block, tmp);
/* It guarantees memory consistency within the same segment */
@@ -1858,7 +1860,8 @@ trans_associate_var (gfc_symbol *sym, gfc_wrapped_block *block)
{
if (e->symtree
&& DECL_LANG_SPECIFIC (e->symtree->n.sym->backend_decl)
- && GFC_DECL_SAVED_DESCRIPTOR (e->symtree->n.sym->backend_decl))
+ && GFC_DECL_SAVED_DESCRIPTOR (e->symtree->n.sym->backend_decl)
+ && TREE_CODE (target_expr) != COMPONENT_REF)
/* Use the original class descriptor stored in the saved
descriptor to get the target_expr. */
target_expr =
@@ -6771,9 +6774,10 @@ gfc_trans_allocate (gfc_code * code)
if (needs_caf_sync)
{
/* Add a sync all after the allocation has been executed. */
+ tree zero_size = build_zero_cst (size_type_node);
tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_sync_all,
3, null_pointer_node, null_pointer_node,
- integer_zero_node);
+ zero_size);
gfc_add_expr_to_block (&post, tmp);
}
diff --git a/gcc/fortran/trans-types.c b/gcc/fortran/trans-types.c
index 22410b5..e1033b3 100644
--- a/gcc/fortran/trans-types.c
+++ b/gcc/fortran/trans-types.c
@@ -1817,11 +1817,11 @@ gfc_get_array_descriptor_base (int dimen, int codimen, bool restricted)
TYPE_NAMELESS (fat_type) = 1;
/* Add the data member as the first element of the descriptor. */
- decl = gfc_add_field_to_struct_1 (fat_type,
- get_identifier ("data"),
- (restricted
- ? prvoid_type_node
- : ptr_type_node), &chain);
+ gfc_add_field_to_struct_1 (fat_type,
+ get_identifier ("data"),
+ (restricted
+ ? prvoid_type_node
+ : ptr_type_node), &chain);
/* Add the base component. */
decl = gfc_add_field_to_struct_1 (fat_type,
@@ -2997,7 +2997,7 @@ get_formal_from_actual_arglist (gfc_symbol *sym, gfc_actual_arglist *actual_args
if (a->expr)
{
snprintf (name, GFC_MAX_SYMBOL_LEN, "_formal_%d", var_num ++);
- gfc_get_symbol (name, NULL, &s);
+ gfc_get_symbol (name, gfc_current_ns, &s);
if (a->expr->ts.type == BT_PROCEDURE)
{
s->attr.flavor = FL_PROCEDURE;
@@ -3005,11 +3005,22 @@ get_formal_from_actual_arglist (gfc_symbol *sym, gfc_actual_arglist *actual_args
else
{
s->ts = a->expr->ts;
+
+ if (s->ts.type == BT_CHARACTER)
+ s->ts.u.cl = gfc_get_charlen ();
+
+ s->ts.deferred = 0;
+ s->ts.is_iso_c = 0;
+ s->ts.is_c_interop = 0;
s->attr.flavor = FL_VARIABLE;
if (a->expr->rank > 0)
{
s->attr.dimension = 1;
s->as = gfc_get_array_spec ();
+ s->as->rank = 1;
+ s->as->lower[0] = gfc_get_int_expr (gfc_index_integer_kind,
+ &a->expr->where, 1);
+ s->as->upper[0] = NULL;
s->as->type = AS_ASSUMED_SIZE;
}
}
diff --git a/gcc/fortran/trans.c b/gcc/fortran/trans.c
index 022ceb9..303abd9 100644
--- a/gcc/fortran/trans.c
+++ b/gcc/fortran/trans.c
@@ -290,6 +290,16 @@ get_array_span (tree type, tree decl)
{
tree span;
+ /* Component references are guaranteed to have a reliable value for
+ 'span'. Likewise indirect references since they emerge from the
+ conversion of a CFI descriptor or the hidden dummy descriptor. */
+ if (TREE_CODE (decl) == COMPONENT_REF
+ && GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (decl)))
+ return gfc_conv_descriptor_span_get (decl);
+ else if (TREE_CODE (decl) == INDIRECT_REF
+ && GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (decl)))
+ return gfc_conv_descriptor_span_get (decl);
+
/* Return the span for deferred character length array references. */
if (type && TREE_CODE (type) == ARRAY_TYPE
&& TYPE_MAX_VALUE (TYPE_DOMAIN (type)) != NULL_TREE
@@ -352,9 +362,6 @@ get_array_span (tree type, tree decl)
else
span = NULL_TREE;
}
- else if (TREE_CODE (decl) == INDIRECT_REF
- && GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (decl)))
- span = gfc_conv_descriptor_span_get (decl);
else
span = NULL_TREE;
@@ -399,12 +406,7 @@ gfc_build_array_ref (tree base, tree offset, tree decl, tree vptr)
if (vptr)
span = gfc_vptr_size_get (vptr);
else if (decl)
- {
- if (TREE_CODE (decl) == COMPONENT_REF)
- span = gfc_conv_descriptor_span_get (decl);
- else
- span = get_array_span (type, decl);
- }
+ span = get_array_span (type, decl);
/* If a non-null span has been generated reference the element with
pointer arithmetic. */
@@ -416,7 +418,8 @@ gfc_build_array_ref (tree base, tree offset, tree decl, tree vptr)
tmp = gfc_build_addr_expr (pvoid_type_node, base);
tmp = fold_build_pointer_plus_loc (input_location, tmp, offset);
tmp = fold_convert (build_pointer_type (type), tmp);
- if (!TYPE_STRING_FLAG (type))
+ if ((TREE_CODE (type) != INTEGER_TYPE && TREE_CODE (type) != ARRAY_TYPE)
+ || !TYPE_STRING_FLAG (type))
tmp = build_fold_indirect_ref_loc (input_location, tmp);
return tmp;
}
@@ -1011,9 +1014,6 @@ gfc_build_final_call (gfc_typespec ts, gfc_expr *final_wrapper, gfc_expr *var,
gfc_add_block_to_block (&block, &se.pre);
gcc_assert (se.post.head == NULL_TREE);
array = se.expr;
- if (TREE_CODE (array) == ADDR_EXPR
- && POINTER_TYPE_P (TREE_TYPE (TREE_OPERAND (array, 0))))
- tmp = TREE_OPERAND (array, 0);
if (!gfc_is_coarray (array_expr))
{
diff --git a/gcc/fortran/trans.h b/gcc/fortran/trans.h
index 9d9ac22..0305d33 100644
--- a/gcc/fortran/trans.h
+++ b/gcc/fortran/trans.h
@@ -91,6 +91,9 @@ typedef struct gfc_se
args alias. */
unsigned force_tmp:1;
+ /* If set, will pass subref descriptors without a temporary. */
+ unsigned force_no_tmp:1;
+
/* Unconditionally calculate offset for array segments and constant
arrays in gfc_conv_expr_descriptor. */
unsigned use_offset:1;
@@ -529,7 +532,13 @@ int gfc_is_intrinsic_libcall (gfc_expr *);
int gfc_conv_procedure_call (gfc_se *, gfc_symbol *, gfc_actual_arglist *,
gfc_expr *, vec<tree, va_gc> *);
-void gfc_conv_subref_array_arg (gfc_se *, gfc_expr *, int, sym_intent, bool);
+void gfc_conv_subref_array_arg (gfc_se *, gfc_expr *, int, sym_intent, bool,
+ const gfc_symbol *fsym = NULL,
+ const char *proc_name = NULL,
+ gfc_symbol *sym = NULL,
+ bool check_contiguous = false);
+
+void gfc_conv_is_contiguous_expr (gfc_se *, gfc_expr *);
/* Generate code for a scalar assignment. */
tree gfc_trans_scalar_assign (gfc_se *, gfc_se *, gfc_typespec, bool, bool,
diff --git a/gcc/function.c b/gcc/function.c
index c6e862b..a957679 100644
--- a/gcc/function.c
+++ b/gcc/function.c
@@ -2912,7 +2912,11 @@ assign_parm_setup_block (struct assign_parm_data_all *all,
size_stored = CEIL_ROUND (size, UNITS_PER_WORD);
if (stack_parm == 0)
{
- SET_DECL_ALIGN (parm, MAX (DECL_ALIGN (parm), BITS_PER_WORD));
+ HOST_WIDE_INT parm_align
+ = (STRICT_ALIGNMENT
+ ? MAX (DECL_ALIGN (parm), BITS_PER_WORD) : DECL_ALIGN (parm));
+
+ SET_DECL_ALIGN (parm, parm_align);
if (DECL_ALIGN (parm) > MAX_SUPPORTED_STACK_ALIGNMENT)
{
rtx allocsize = gen_int_mode (size_stored, Pmode);
@@ -4017,13 +4021,6 @@ locate_and_pad_parm (machine_mode passed_mode, tree type, int in_regs,
}
}
- /* Remember if the outgoing parameter requires extra alignment on the
- calling function side. */
- if (crtl->stack_alignment_needed < boundary)
- crtl->stack_alignment_needed = boundary;
- if (crtl->preferred_stack_boundary < boundary)
- crtl->preferred_stack_boundary = boundary;
-
if (ARGS_GROW_DOWNWARD)
{
locate->slot_offset.constant = -initial_offset_ptr->constant;
@@ -5138,7 +5135,7 @@ expand_function_start (tree subr)
r_save = expand_expr (t_save, NULL_RTX, VOIDmode, EXPAND_WRITE);
gcc_assert (GET_MODE (r_save) == Pmode);
- emit_move_insn (r_save, targetm.builtin_setjmp_frame_value ());
+ emit_move_insn (r_save, hard_frame_pointer_rtx);
update_nonlocal_goto_save_area ();
}
diff --git a/gcc/function.h b/gcc/function.h
index cef093c..bfe9919 100644
--- a/gcc/function.h
+++ b/gcc/function.h
@@ -327,6 +327,9 @@ struct GTY(()) function {
either as a subroutine or builtin. */
unsigned int calls_alloca : 1;
+ /* Nonzero if function being compiled can call __builtin_eh_return. */
+ unsigned int calls_eh_return : 1;
+
/* Nonzero if function being compiled receives nonlocal gotos
from nested functions. */
unsigned int has_nonlocal_label : 1;
diff --git a/gcc/fwprop.c b/gcc/fwprop.c
index cf2c9de..45703fe 100644
--- a/gcc/fwprop.c
+++ b/gcc/fwprop.c
@@ -680,7 +680,7 @@ propagate_rtx (rtx x, machine_mode mode, rtx old_rtx, rtx new_rtx,
|| CONSTANT_P (new_rtx)
|| (GET_CODE (new_rtx) == SUBREG
&& REG_P (SUBREG_REG (new_rtx))
- && !paradoxical_subreg_p (mode, GET_MODE (SUBREG_REG (new_rtx)))))
+ && !paradoxical_subreg_p (new_rtx)))
flags |= PR_CAN_APPEAR;
if (!varying_mem_p (new_rtx))
flags |= PR_HANDLE_MEM;
diff --git a/gcc/gcc.c b/gcc/gcc.c
index a1003a5..0c0a686 100644
--- a/gcc/gcc.c
+++ b/gcc/gcc.c
@@ -3068,7 +3068,8 @@ execute (void)
if (!wrapper_string)
{
string = find_a_file (&exec_prefixes, commands[0].prog, X_OK, false);
- commands[0].argv[0] = (string) ? string : commands[0].argv[0];
+ if (string)
+ commands[0].argv[0] = string;
}
for (n_commands = 1, i = 0; argbuf.iterate (i, &arg); i++)
@@ -3077,8 +3078,7 @@ execute (void)
#if defined (__MSDOS__) || defined (OS2) || defined (VMS)
fatal_error (input_location, "%<-pipe%> not supported");
#endif
- argbuf[i] = 0; /* Termination of
- command args. */
+ argbuf[i] = 0; /* Termination of command args. */
commands[n_commands].prog = argbuf[i + 1];
commands[n_commands].argv
= &(argbuf.address ())[i + 1];
@@ -3198,7 +3198,7 @@ execute (void)
? PEX_RECORD_TIMES : 0),
progname, temp_filename);
if (pex == NULL)
- fatal_error (input_location, "pex_init failed: %m");
+ fatal_error (input_location, "%<pex_init%> failed: %m");
for (i = 0; i < n_commands; i++)
{
@@ -3769,7 +3769,7 @@ driver_wrong_lang_callback (const struct cl_decoded_option *decoded,
const struct cl_option *option = &cl_options[decoded->opt_index];
if (option->cl_reject_driver)
- error ("unrecognized command line option %qs",
+ error ("unrecognized command-line option %qs",
decoded->orig_option_with_args_text);
else
save_switch (decoded->canonical_option[0],
@@ -6138,7 +6138,8 @@ eval_spec_function (const char *func, const char *args,
alloc_args ();
if (do_spec_2 (args, soft_matched_part) < 0)
- fatal_error (input_location, "error in args to spec function %qs", func);
+ fatal_error (input_location, "error in arguments to spec function %qs",
+ func);
/* argbuf_index is an index for the next argument to be inserted, and
so contains the count of the args already inserted. */
@@ -6790,6 +6791,11 @@ print_configuration (FILE *file)
#endif
fnotice (file, "Thread model: %s\n", thrmod);
+ fnotice (file, "Supported LTO compression algorithms: zlib");
+#ifdef HAVE_ZSTD_H
+ fnotice (file, " zstd");
+#endif
+ fnotice (file, "\n");
/* compiler_version is truncated at the first space when initialized
from version string, so truncate version_string at the first space
@@ -6923,11 +6929,11 @@ run_attempt (const char **new_argv, const char *out_temp,
pex = pex_init (PEX_USE_PIPES, new_argv[0], NULL);
if (!pex)
- fatal_error (input_location, "pex_init failed: %m");
+ fatal_error (input_location, "%<pex_init%> failed: %m");
errmsg = pex_run (pex, pex_flags, new_argv[0],
- CONST_CAST2 (char *const *, const char **, &new_argv[1]), out_temp,
- err_temp, &err);
+ CONST_CAST2 (char *const *, const char **, &new_argv[1]),
+ out_temp, err_temp, &err);
if (errmsg != NULL)
{
errno = err;
@@ -7614,7 +7620,8 @@ driver::set_up_specs () const
&& do_spec_2 (sysroot_suffix_spec, NULL) == 0)
{
if (argbuf.length () > 1)
- error ("spec failure: more than one arg to SYSROOT_SUFFIX_SPEC");
+ error ("spec failure: more than one argument to "
+ "%<SYSROOT_SUFFIX_SPEC%>");
else if (argbuf.length () == 1)
target_sysroot_suffix = xstrdup (argbuf.last ());
}
@@ -7638,7 +7645,8 @@ driver::set_up_specs () const
&& do_spec_2 (sysroot_hdrs_suffix_spec, NULL) == 0)
{
if (argbuf.length () > 1)
- error ("spec failure: more than one arg to SYSROOT_HEADERS_SUFFIX_SPEC");
+ error ("spec failure: more than one argument "
+ "to %<SYSROOT_HEADERS_SUFFIX_SPEC%>");
else if (argbuf.length () == 1)
target_sysroot_hdrs_suffix = xstrdup (argbuf.last ());
}
@@ -7843,11 +7851,11 @@ driver::handle_unrecognized_options ()
{
const char *hint = m_option_proposer.suggest_option (switches[i].part1);
if (hint)
- error ("unrecognized command line option %<-%s%>;"
+ error ("unrecognized command-line option %<-%s%>;"
" did you mean %<-%s%>?",
switches[i].part1, hint);
else
- error ("unrecognized command line option %<-%s%>",
+ error ("unrecognized command-line option %<-%s%>",
switches[i].part1);
}
}
@@ -9797,7 +9805,7 @@ compare_debug_auxbase_opt_spec_function (int arg,
len = strlen (argv[0]);
if (len < 3 || strcmp (argv[0] + len - 3, ".gk") != 0)
fatal_error (input_location, "argument to %%:compare-debug-auxbase-opt "
- "does not end in .gk");
+ "does not end in %<.gk%>");
if (debug_auxbase_opt)
return debug_auxbase_opt;
diff --git a/gcc/gcov-counter.def b/gcc/gcov-counter.def
index 3a0e620..1a2cbb2 100644
--- a/gcc/gcov-counter.def
+++ b/gcc/gcov-counter.def
@@ -36,10 +36,10 @@ DEF_GCOV_COUNTER(GCOV_COUNTER_V_INTERVAL, "interval", _add)
DEF_GCOV_COUNTER(GCOV_COUNTER_V_POW2, "pow2", _add)
/* The most common value of expression. */
-DEF_GCOV_COUNTER(GCOV_COUNTER_V_SINGLE, "single", _single)
+DEF_GCOV_COUNTER(GCOV_COUNTER_V_TOPN, "topn", _topn)
/* The most common indirect address. */
-DEF_GCOV_COUNTER(GCOV_COUNTER_V_INDIR, "indirect_call", _single)
+DEF_GCOV_COUNTER(GCOV_COUNTER_V_INDIR, "indirect_call", _topn)
/* Compute average value passed to the counter. */
DEF_GCOV_COUNTER(GCOV_COUNTER_AVERAGE, "average", _add)
@@ -49,6 +49,3 @@ DEF_GCOV_COUNTER(GCOV_COUNTER_IOR, "ior", _ior)
/* Time profile collecting first run of a function */
DEF_GCOV_COUNTER(GCOV_TIME_PROFILER, "time_profiler", _time_profile)
-
-/* Top N value tracking for indirect calls. */
-DEF_GCOV_COUNTER(GCOV_COUNTER_ICALL_TOPNV, "indirect_call_topn", _icall_topn)
diff --git a/gcc/gcov-io.h b/gcc/gcov-io.h
index 9edb292..7df578f 100644
--- a/gcc/gcov-io.h
+++ b/gcc/gcov-io.h
@@ -266,11 +266,11 @@ GCOV_COUNTERS
#define GCOV_N_VALUE_COUNTERS \
(GCOV_LAST_VALUE_COUNTER - GCOV_FIRST_VALUE_COUNTER + 1)
-/* The number of hottest callees to be tracked. */
-#define GCOV_ICALL_TOPN_VAL 2
+/* Number of top N value histogram. */
+#define GCOV_TOPN_VALUES 4
-/* The number of counter entries per icall callsite. */
-#define GCOV_ICALL_TOPN_NCOUNTS (1 + GCOV_ICALL_TOPN_VAL * 4)
+/* Total number of single value counters. */
+#define GCOV_TOPN_VALUES_COUNTERS (2 * GCOV_TOPN_VALUES + 1)
/* Convert a counter index to a tag. */
#define GCOV_TAG_FOR_COUNTER(COUNT) \
diff --git a/gcc/gcov-tool.c b/gcc/gcov-tool.c
index 5bb1cca..ce96db0 100644
--- a/gcc/gcov-tool.c
+++ b/gcc/gcov-tool.c
@@ -70,7 +70,7 @@ unlink_gcda_file (const char *name,
ret = remove (name);
if (ret)
- fatal_error (input_location, "error in removing %s\n", name);
+ fatal_error (input_location, "error in removing %s", name);
return ret;
}
@@ -188,7 +188,7 @@ static const struct option merge_options[] =
/* Print merge usage and exit. */
-static void
+static void ATTRIBUTE_NORETURN
merge_usage (void)
{
fnotice (stderr, "Merge subcomand usage:");
@@ -220,7 +220,7 @@ do_merge (int argc, char **argv)
case 'w':
sscanf (optarg, "%d,%d", &w1, &w2);
if (w1 < 0 || w2 < 0)
- fatal_error (input_location, "weights need to be non-negative\n");
+ fatal_error (input_location, "weights need to be non-negative");
break;
default:
merge_usage ();
@@ -284,7 +284,7 @@ static const struct option rewrite_options[] =
/* Print profile rewrite usage and exit. */
-static void
+static void ATTRIBUTE_NORETURN
rewrite_usage (void)
{
fnotice (stderr, "Rewrite subcommand usage:");
@@ -355,7 +355,7 @@ do_rewrite (int argc, char **argv)
}
if (scale < 0.0)
- fatal_error (input_location, "scale needs to be non-negative\n");
+ fatal_error (input_location, "scale needs to be non-negative");
if (normalize_val != 0)
{
diff --git a/gcc/gcov.c b/gcc/gcov.c
index 1fc37a0..b06a671 100644
--- a/gcc/gcov.c
+++ b/gcc/gcov.c
@@ -676,27 +676,11 @@ bool function_info::group_line_p (unsigned n, unsigned src_idx)
typedef vector<arc_info *> arc_vector_t;
typedef vector<const block_info *> block_vector_t;
-/* Enum with types of loop in CFG. */
-
-enum loop_type
-{
- NO_LOOP = 0,
- LOOP = 1,
- NEGATIVE_LOOP = 3
-};
-
-/* Loop_type operator that merges two values: A and B. */
-
-inline loop_type& operator |= (loop_type& a, loop_type b)
-{
- return a = static_cast<loop_type> (a | b);
-}
-
/* Handle cycle identified by EDGES, where the function finds minimum cs_count
and subtract the value from all counts. The subtracted value is added
to COUNT. Returns type of loop. */
-static loop_type
+static void
handle_cycle (const arc_vector_t &edges, int64_t &count)
{
/* Find the minimum edge of the cycle, and reduce all nodes in the cycle by
@@ -712,7 +696,7 @@ handle_cycle (const arc_vector_t &edges, int64_t &count)
for (unsigned i = 0; i < edges.size (); i++)
edges[i]->cs_count -= cycle_count;
- return cycle_count < 0 ? NEGATIVE_LOOP : LOOP;
+ gcc_assert (cycle_count > 0);
}
/* Unblock a block U from BLOCKED. Apart from that, iterate all blocks
@@ -738,17 +722,28 @@ unblock (const block_info *u, block_vector_t &blocked,
unblock (*it, blocked, block_lists);
}
+/* Return true when PATH contains a zero cycle arc count. */
+
+static bool
+path_contains_zero_cycle_arc (arc_vector_t &path)
+{
+ for (unsigned i = 0; i < path.size (); i++)
+ if (path[i]->cs_count == 0)
+ return true;
+ return false;
+}
+
/* Find circuit going to block V, PATH is provisional seen cycle.
BLOCKED is vector of blocked vertices, BLOCK_LISTS contains vertices
blocked by a block. COUNT is accumulated count of the current LINE.
Returns what type of loop it contains. */
-static loop_type
+static bool
circuit (block_info *v, arc_vector_t &path, block_info *start,
block_vector_t &blocked, vector<block_vector_t> &block_lists,
line_info &linfo, int64_t &count)
{
- loop_type result = NO_LOOP;
+ bool loop_found = false;
/* Add v to the block list. */
gcc_assert (find (blocked.begin (), blocked.end (), v) == blocked.end ());
@@ -758,26 +753,35 @@ circuit (block_info *v, arc_vector_t &path, block_info *start,
for (arc_info *arc = v->succ; arc; arc = arc->succ_next)
{
block_info *w = arc->dst;
- if (w < start || !linfo.has_block (w))
+ if (w < start
+ || arc->cs_count == 0
+ || !linfo.has_block (w))
continue;
path.push_back (arc);
if (w == start)
- /* Cycle has been found. */
- result |= handle_cycle (path, count);
- else if (find (blocked.begin (), blocked.end (), w) == blocked.end ())
- result |= circuit (w, path, start, blocked, block_lists, linfo, count);
+ {
+ /* Cycle has been found. */
+ handle_cycle (path, count);
+ loop_found = true;
+ }
+ else if (!path_contains_zero_cycle_arc (path)
+ && find (blocked.begin (), blocked.end (), w) == blocked.end ())
+ loop_found |= circuit (w, path, start, blocked, block_lists, linfo,
+ count);
path.pop_back ();
}
- if (result != NO_LOOP)
+ if (loop_found)
unblock (v, blocked, block_lists);
else
for (arc_info *arc = v->succ; arc; arc = arc->succ_next)
{
block_info *w = arc->dst;
- if (w < start || !linfo.has_block (w))
+ if (w < start
+ || arc->cs_count == 0
+ || !linfo.has_block (w))
continue;
size_t index
@@ -788,14 +792,13 @@ circuit (block_info *v, arc_vector_t &path, block_info *start,
list.push_back (v);
}
- return result;
+ return loop_found;
}
-/* Find cycles for a LINFO. If HANDLE_NEGATIVE_CYCLES is set and the line
- contains a negative loop, then perform the same function once again. */
+/* Find cycles for a LINFO. */
static gcov_type
-get_cycles_count (line_info &linfo, bool handle_negative_cycles = true)
+get_cycles_count (line_info &linfo)
{
/* Note that this algorithm works even if blocks aren't in sorted order.
Each iteration of the circuit detection is completely independent
@@ -803,7 +806,7 @@ get_cycles_count (line_info &linfo, bool handle_negative_cycles = true)
Therefore, operating on a permuted order (i.e., non-sorted) only
has the effect of permuting the output cycles. */
- loop_type result = NO_LOOP;
+ bool loop_found = false;
gcov_type count = 0;
for (vector<block_info *>::iterator it = linfo.blocks.begin ();
it != linfo.blocks.end (); it++)
@@ -811,14 +814,10 @@ get_cycles_count (line_info &linfo, bool handle_negative_cycles = true)
arc_vector_t path;
block_vector_t blocked;
vector<block_vector_t > block_lists;
- result |= circuit (*it, path, *it, blocked, block_lists, linfo,
- count);
+ loop_found |= circuit (*it, path, *it, blocked, block_lists, linfo,
+ count);
}
- /* If we have a negative cycle, repeat the find_cycles routine. */
- if (result == NEGATIVE_LOOP && handle_negative_cycles)
- count += get_cycles_count (linfo, false);
-
return count;
}
diff --git a/gcc/gcse.c b/gcc/gcse.c
index 7fbdd67..ff2771b 100644
--- a/gcc/gcse.c
+++ b/gcc/gcse.c
@@ -4004,7 +4004,8 @@ gcse_or_cprop_is_too_expensive (const char *pass)
if (memory_request > MAX_GCSE_MEMORY)
{
warning (OPT_Wdisabled_optimization,
- "%s: %d basic blocks and %d registers; increase --param max-gcse-memory above %d",
+ "%s: %d basic blocks and %d registers; "
+ "increase %<--param max-gcse-memory%> above %d",
pass, n_basic_blocks_for_fn (cfun), max_reg_num (),
memory_request);
diff --git a/gcc/gdbhooks.py b/gcc/gdbhooks.py
index 7b1a7be..191a5e2 100644
--- a/gcc/gdbhooks.py
+++ b/gcc/gdbhooks.py
@@ -222,6 +222,9 @@ class TreePrinter:
# extern const enum tree_code_class tree_code_type[];
# #define TREE_CODE_CLASS(CODE) tree_code_type[(int) (CODE)]
+ if val_TREE_CODE == 0xa5a5:
+ return '<ggc_freed 0x%x>' % intptr(self.gdbval)
+
val_tree_code_type = gdb.parse_and_eval('tree_code_type')
val_tclass = val_tree_code_type[val_TREE_CODE]
@@ -521,11 +524,11 @@ class GdbPrettyPrinters(gdb.printing.PrettyPrinter):
def __init__(self, name):
super(GdbPrettyPrinters, self).__init__(name, [])
- def add_printer_for_types(self, name, class_, types):
- self.subprinters.append(GdbSubprinterTypeList(name, class_, types))
+ def add_printer_for_types(self, types, name, class_):
+ self.subprinters.append(GdbSubprinterTypeList(types, name, class_))
- def add_printer_for_regex(self, name, class_, regex):
- self.subprinters.append(GdbSubprinterRegex(name, class_, regex))
+ def add_printer_for_regex(self, regex, name, class_):
+ self.subprinters.append(GdbSubprinterRegex(regex, name, class_))
def __call__(self, gdbval):
type_ = gdbval.type.unqualified()
@@ -540,7 +543,7 @@ class GdbPrettyPrinters(gdb.printing.PrettyPrinter):
def build_pretty_printer():
pp = GdbPrettyPrinters('gcc')
- pp.add_printer_for_types(['tree'],
+ pp.add_printer_for_types(['tree', 'const_tree'],
'tree', TreePrinter)
pp.add_printer_for_types(['cgraph_node *', 'varpool_node *', 'symtab_node *'],
'symtab_node', SymtabNodePrinter)
diff --git a/gcc/gdbinit.in b/gcc/gdbinit.in
index e16c3c8..440fd25 100644
--- a/gcc/gdbinit.in
+++ b/gcc/gdbinit.in
@@ -113,7 +113,7 @@ Works only when an inferior is executing.
end
define ptc
-output (enum tree_code) $.common.code
+output (enum tree_code) $.base.code
echo \n
end
@@ -201,6 +201,14 @@ document pcfun
Print current function.
end
+define trt
+print ($.typed.type)
+end
+
+document trt
+Print TREE_TYPE of the tree node that is $
+end
+
define break-on-diagnostic
break diagnostic_show_locus
end
diff --git a/gcc/generic-match-head.c b/gcc/generic-match-head.c
index a46f375..b54e035 100644
--- a/gcc/generic-match-head.c
+++ b/gcc/generic-match-head.c
@@ -27,6 +27,7 @@ along with GCC; see the file COPYING3. If not see
#include "gimple.h"
#include "ssa.h"
#include "cgraph.h"
+#include "vec-perm-indices.h"
#include "fold-const.h"
#include "stor-layout.h"
#include "tree-dfa.h"
@@ -34,7 +35,7 @@ along with GCC; see the file COPYING3. If not see
#include "case-cfn-macros.h"
#include "gimplify.h"
#include "optabs-tree.h"
-
+#include "dbgcnt.h"
/* Routine to determine if the types T1 and T2 are effectively
the same for GENERIC. If T1 or T2 is not a type, the test
diff --git a/gcc/genmatch.c b/gcc/genmatch.c
index 7b9b09c..109bd9e 100644
--- a/gcc/genmatch.c
+++ b/gcc/genmatch.c
@@ -3310,6 +3310,10 @@ dt_simplify::gen_1 (FILE *f, int indent, bool gimple, operand *result)
}
}
+ if (s->kind == simplify::SIMPLIFY)
+ fprintf_indent (f, indent, "if (__builtin_expect (!dbg_cnt (match), 0)) return %s;\n",
+ gimple ? "false" : "NULL_TREE");
+
fprintf_indent (f, indent, "if (__builtin_expect (dump_file && (dump_flags & TDF_FOLDING), 0)) "
"fprintf (dump_file, \"%s ",
s->kind == simplify::SIMPLIFY
diff --git a/gcc/gensupport.c b/gcc/gensupport.c
index 31a67d5..0150346 100644
--- a/gcc/gensupport.c
+++ b/gcc/gensupport.c
@@ -70,8 +70,8 @@ struct queue_elem
rtx data;
file_location loc;
struct queue_elem *next;
- /* In a DEFINE_INSN that came from a DEFINE_INSN_AND_SPLIT, SPLIT
- points to the generated DEFINE_SPLIT. */
+ /* In a DEFINE_INSN that came from a DEFINE_INSN_AND_SPLIT or
+ DEFINE_INSN_AND_REWRITE, SPLIT points to the generated DEFINE_SPLIT. */
struct queue_elem *split;
};
@@ -485,6 +485,63 @@ remove_constraints (rtx part)
}
}
+/* Recursively replace MATCH_OPERANDs with MATCH_DUPs and MATCH_OPERATORs
+ with MATCH_OP_DUPs in X. */
+
+static rtx
+replace_operands_with_dups (rtx x)
+{
+ if (x == 0)
+ return x;
+
+ rtx newx;
+ if (GET_CODE (x) == MATCH_OPERAND)
+ {
+ newx = rtx_alloc (MATCH_DUP);
+ XINT (newx, 0) = XINT (x, 0);
+ }
+ else if (GET_CODE (x) == MATCH_OPERATOR)
+ {
+ newx = rtx_alloc (MATCH_OP_DUP);
+ XINT (newx, 0) = XINT (x, 0);
+ XVEC (newx, 1) = XVEC (x, 2);
+ }
+ else
+ newx = shallow_copy_rtx (x);
+
+ const char *format_ptr = GET_RTX_FORMAT (GET_CODE (x));
+ for (int i = 0; i < GET_RTX_LENGTH (GET_CODE (x)); i++)
+ switch (*format_ptr++)
+ {
+ case 'e':
+ case 'u':
+ XEXP (newx, i) = replace_operands_with_dups (XEXP (x, i));
+ break;
+ case 'E':
+ if (XVEC (x, i) != NULL)
+ {
+ XVEC (newx, i) = rtvec_alloc (XVECLEN (x, i));
+ for (int j = 0; j < XVECLEN (x, i); j++)
+ XVECEXP (newx, i, j)
+ = replace_operands_with_dups (XVECEXP (x, i, j));
+ }
+ break;
+ }
+ return newx;
+}
+
+/* Convert matching pattern VEC from a DEFINE_INSN_AND_REWRITE into
+ a sequence that should be generated by the splitter. */
+
+static rtvec
+gen_rewrite_sequence (rtvec vec)
+{
+ rtvec new_vec = rtvec_alloc (1);
+ rtx x = add_implicit_parallel (vec);
+ RTVEC_ELT (new_vec, 0) = replace_operands_with_dups (x);
+ return new_vec;
+}
+
/* Process a top level rtx in some way, queuing as appropriate. */
static void
@@ -527,6 +584,7 @@ process_rtx (rtx desc, file_location loc)
break;
case DEFINE_INSN_AND_SPLIT:
+ case DEFINE_INSN_AND_REWRITE:
{
const char *split_cond;
rtx split;
@@ -534,6 +592,7 @@ process_rtx (rtx desc, file_location loc)
int i;
struct queue_elem *insn_elem;
struct queue_elem *split_elem;
+ int split_code = (GET_CODE (desc) == DEFINE_INSN_AND_REWRITE ? 5 : 6);
/* Create a split with values from the insn_and_split. */
split = rtx_alloc (DEFINE_SPLIT);
@@ -555,12 +614,17 @@ process_rtx (rtx desc, file_location loc)
split_cond = rtx_reader_ptr->join_c_conditions (XSTR (desc, 2),
split_cond + 2);
}
+ else if (GET_CODE (desc) == DEFINE_INSN_AND_REWRITE)
+ error_at (loc, "the rewrite condition must start with `&&'");
XSTR (split, 1) = split_cond;
- XVEC (split, 2) = XVEC (desc, 5);
- XSTR (split, 3) = XSTR (desc, 6);
+ if (GET_CODE (desc) == DEFINE_INSN_AND_REWRITE)
+ XVEC (split, 2) = gen_rewrite_sequence (XVEC (desc, 1));
+ else
+ XVEC (split, 2) = XVEC (desc, 5);
+ XSTR (split, 3) = XSTR (desc, split_code);
/* Fix up the DEFINE_INSN. */
- attr = XVEC (desc, 7);
+ attr = XVEC (desc, split_code + 1);
PUT_CODE (desc, DEFINE_INSN);
XVEC (desc, 4) = attr;
diff --git a/gcc/ggc-common.c b/gcc/ggc-common.c
index 0d1e5bf..6fb5a3d 100644
--- a/gcc/ggc-common.c
+++ b/gcc/ggc-common.c
@@ -382,7 +382,7 @@ write_pch_globals (const struct ggc_root_tab * const *tab,
{
if (fwrite (&ptr, sizeof (void *), 1, state->f)
!= 1)
- fatal_error (input_location, "can%'t write PCH file: %m");
+ fatal_error (input_location, "cannot write PCH file: %m");
}
else
{
@@ -390,7 +390,7 @@ write_pch_globals (const struct ggc_root_tab * const *tab,
saving_htab->find_with_hash (ptr, POINTER_HASH (ptr));
if (fwrite (&new_ptr->new_addr, sizeof (void *), 1, state->f)
!= 1)
- fatal_error (input_location, "can%'t write PCH file: %m");
+ fatal_error (input_location, "cannot write PCH file: %m");
}
}
}
@@ -459,7 +459,7 @@ gt_pch_save (FILE *f)
for (rt = gt_pch_scalar_rtab; *rt; rt++)
for (rti = *rt; rti->base != NULL; rti++)
if (fwrite (rti->base, rti->stride, 1, f) != 1)
- fatal_error (input_location, "can%'t write PCH file: %m");
+ fatal_error (input_location, "cannot write PCH file: %m");
/* Write out all the global pointers, after translation. */
write_pch_globals (gt_ggc_rtab, &state);
@@ -470,17 +470,17 @@ gt_pch_save (FILE *f)
long o;
o = ftell (state.f) + sizeof (mmi);
if (o == -1)
- fatal_error (input_location, "can%'t get position in PCH file: %m");
+ fatal_error (input_location, "cannot get position in PCH file: %m");
mmi.offset = mmap_offset_alignment - o % mmap_offset_alignment;
if (mmi.offset == mmap_offset_alignment)
mmi.offset = 0;
mmi.offset += o;
}
if (fwrite (&mmi, sizeof (mmi), 1, state.f) != 1)
- fatal_error (input_location, "can%'t write PCH file: %m");
+ fatal_error (input_location, "cannot write PCH file: %m");
if (mmi.offset != 0
&& fseek (state.f, mmi.offset, SEEK_SET) != 0)
- fatal_error (input_location, "can%'t write padding to PCH file: %m");
+ fatal_error (input_location, "cannot write padding to PCH file: %m");
ggc_pch_prepare_write (state.d, state.f);
@@ -602,7 +602,7 @@ gt_pch_restore (FILE *f)
for (rt = gt_pch_scalar_rtab; *rt; rt++)
for (rti = *rt; rti->base != NULL; rti++)
if (fread (rti->base, rti->stride, 1, f) != 1)
- fatal_error (input_location, "can%'t read PCH file: %m");
+ fatal_error (input_location, "cannot read PCH file: %m");
/* Read in all the global pointers, in 6 easy loops. */
for (rt = gt_ggc_rtab; *rt; rt++)
@@ -610,10 +610,10 @@ gt_pch_restore (FILE *f)
for (i = 0; i < rti->nelt; i++)
if (fread ((char *)rti->base + rti->stride * i,
sizeof (void *), 1, f) != 1)
- fatal_error (input_location, "can%'t read PCH file: %m");
+ fatal_error (input_location, "cannot read PCH file: %m");
if (fread (&mmi, sizeof (mmi), 1, f) != 1)
- fatal_error (input_location, "can%'t read PCH file: %m");
+ fatal_error (input_location, "cannot read PCH file: %m");
result = host_hooks.gt_pch_use_address (mmi.preferred_base, mmi.size,
fileno (f), mmi.offset);
@@ -623,10 +623,10 @@ gt_pch_restore (FILE *f)
{
if (fseek (f, mmi.offset, SEEK_SET) != 0
|| fread (mmi.preferred_base, mmi.size, 1, f) != 1)
- fatal_error (input_location, "can%'t read PCH file: %m");
+ fatal_error (input_location, "cannot read PCH file: %m");
}
else if (fseek (f, mmi.offset + mmi.size, SEEK_SET) != 0)
- fatal_error (input_location, "can%'t read PCH file: %m");
+ fatal_error (input_location, "cannot read PCH file: %m");
ggc_pch_read (f, mmi.preferred_base);
@@ -1014,5 +1014,5 @@ ggc_prune_overhead_list (void)
(*it).second.first->m_collected += (*it).second.second;
delete ggc_mem_desc.m_reverse_object_map;
- ggc_mem_desc.m_reverse_object_map = new map_t (13, false, false);
+ ggc_mem_desc.m_reverse_object_map = new map_t (13, false, false, false);
}
diff --git a/gcc/ggc-page.c b/gcc/ggc-page.c
index 143986b..a95ff46 100644
--- a/gcc/ggc-page.c
+++ b/gcc/ggc-page.c
@@ -943,8 +943,8 @@ alloc_page (unsigned order)
if (GGC_DEBUG_LEVEL >= 2)
fprintf (G.debug_file,
"Allocating page at %p, object size=%lu, data %p-%p\n",
- (void *) entry, (unsigned long) OBJECT_SIZE (order), page,
- page + entry_size - 1);
+ (void *) entry, (unsigned long) OBJECT_SIZE (order),
+ (void *) page, (void *) (page + entry_size - 1));
return entry;
}
@@ -977,7 +977,7 @@ free_page (page_entry *entry)
if (GGC_DEBUG_LEVEL >= 2)
fprintf (G.debug_file,
"Deallocating page at %p, data %p-%p\n", (void *) entry,
- entry->page, entry->page + entry->bytes - 1);
+ (void *) entry->page, (void *) (entry->page + entry->bytes - 1));
/* Mark the page as inaccessible. Discard the handle to avoid handle
leak. */
@@ -2455,7 +2455,7 @@ ggc_pch_write_object (struct ggc_pch_data *d,
}
if (fwrite (x, size, 1, f) != 1)
- fatal_error (input_location, "can%'t write PCH file: %m");
+ fatal_error (input_location, "cannot write PCH file: %m");
/* If SIZE is not the same as OBJECT_SIZE(order), then we need to pad the
object out to OBJECT_SIZE(order). This happens for strings. */
@@ -2471,13 +2471,13 @@ ggc_pch_write_object (struct ggc_pch_data *d,
if (padding <= sizeof (emptyBytes))
{
if (fwrite (emptyBytes, 1, padding, f) != padding)
- fatal_error (input_location, "can%'t write PCH file");
+ fatal_error (input_location, "cannot write PCH file");
}
else
{
/* Larger than our buffer? Just default to fseek. */
if (fseek (f, padding, SEEK_CUR) != 0)
- fatal_error (input_location, "can%'t write PCH file");
+ fatal_error (input_location, "cannot write PCH file");
}
}
@@ -2486,14 +2486,14 @@ ggc_pch_write_object (struct ggc_pch_data *d,
&& fseek (f, ROUND_UP_VALUE (d->d.totals[order] * OBJECT_SIZE (order),
G.pagesize),
SEEK_CUR) != 0)
- fatal_error (input_location, "can%'t write PCH file: %m");
+ fatal_error (input_location, "cannot write PCH file: %m");
}
void
ggc_pch_finish (struct ggc_pch_data *d, FILE *f)
{
if (fwrite (&d->d, sizeof (d->d), 1, f) != 1)
- fatal_error (input_location, "can%'t write PCH file: %m");
+ fatal_error (input_location, "cannot write PCH file: %m");
free (d);
}
@@ -2585,7 +2585,7 @@ ggc_pch_read (FILE *f, void *addr)
/* Allocate the appropriate page-table entries for the pages read from
the PCH file. */
if (fread (&d, sizeof (d), 1, f) != 1)
- fatal_error (input_location, "can%'t read PCH file: %m");
+ fatal_error (input_location, "cannot read PCH file: %m");
for (i = 0; i < NUM_ORDERS; i++)
{
diff --git a/gcc/gimple-fold.c b/gcc/gimple-fold.c
index 1b10bae..118718a 100644
--- a/gcc/gimple-fold.c
+++ b/gcc/gimple-fold.c
@@ -684,10 +684,10 @@ size_must_be_zero_p (tree size)
/* Compute the value of SSIZE_MAX, the largest positive value that
can be stored in ssize_t, the signed counterpart of size_t. */
wide_int ssize_max = wi::lshift (wi::one (prec), prec - 1) - 1;
- value_range valid_range (VR_RANGE,
- build_int_cst (type, 0),
- wide_int_to_tree (type, ssize_max));
- value_range vr;
+ value_range_base valid_range (VR_RANGE,
+ build_int_cst (type, 0),
+ wide_int_to_tree (type, ssize_max));
+ value_range_base vr;
get_range_info (size, vr);
vr.intersect (&valid_range);
return vr.zero_p ();
@@ -1672,30 +1672,16 @@ get_range_strlen (tree arg, bitmap *visited,
}
}
-/* Determine the minimum and maximum value or string length that ARG
- refers to and store each in the first two elements of MINMAXLEN.
- For expressions that point to strings of unknown lengths that are
- character arrays, use the upper bound of the array as the maximum
- length. For example, given an expression like 'x ? array : "xyz"'
- and array declared as 'char array[8]', MINMAXLEN[0] will be set
- to 0 and MINMAXLEN[1] to 7, the longest string that could be
- stored in array.
- Return true if the range of the string lengths has been obtained
- from the upper bound of an array at the end of a struct. Such
- an array may hold a string that's longer than its upper bound
- due to it being used as a poor-man's flexible array member.
-
- STRICT is true if it will handle PHIs and COND_EXPRs conservatively
- and false if PHIs and COND_EXPRs are to be handled optimistically,
- if we can determine string length minimum and maximum; it will use
- the minimum from the ones where it can be determined.
- STRICT false should be only used for warning code.
- When non-null, clear *NONSTR if ARG refers to a constant array
- that is known not be nul-terminated. Otherwise set it to
- the declaration of the constant non-terminated array.
-
- ELTSIZE is 1 for normal single byte character strings, and 2 or
- 4 for wide characer strings. ELTSIZE is by default 1. */
+/* Try to obtain the range of the lengths of the string(s) referenced
+ by ARG, or the size of the largest array ARG refers to if the range
+ of lengths cannot be determined, and store all in *PDATA. ELTSIZE
+ is the expected size of the string element in bytes: 1 for char and
+ some power of 2 for wide characters.
+ Return true if the range [PDATA->MINLEN, PDATA->MAXLEN] is suitable
+ for optimization. Returning false means that a nonzero PDATA->MINLEN
+ doesn't reflect the true lower bound of the range when PDATA->MAXLEN
+ is -1 (in that case, the actual range is indeterminate, i.e.,
+ [0, PTRDIFF_MAX - 2]. */
bool
get_range_strlen (tree arg, c_strlen_data *pdata, unsigned eltsize)
@@ -2557,7 +2543,15 @@ gimple_fold_builtin_memchr (gimple_stmt_iterator *gsi)
const char *r = (const char *)memchr (p1, c, MIN (length, string_length));
if (r == NULL)
{
- if (length <= string_length)
+ tree mem_size, offset_node;
+ string_constant (arg1, &offset_node, &mem_size, NULL);
+ unsigned HOST_WIDE_INT offset = (offset_node == NULL_TREE)
+ ? 0 : tree_to_uhwi (offset_node);
+ /* MEM_SIZE is the size of the array the string literal
+ is stored in. */
+ unsigned HOST_WIDE_INT string_size = tree_to_uhwi (mem_size) - offset;
+ gcc_checking_assert (string_length <= string_size);
+ if (length <= string_size)
{
replace_call_with_value (gsi, build_int_cst (ptr_type_node, 0));
return true;
@@ -7329,6 +7323,7 @@ arith_code_with_undefined_signed_overflow (tree_code code)
{
switch (code)
{
+ case ABS_EXPR:
case PLUS_EXPR:
case MINUS_EXPR:
case MULT_EXPR:
@@ -7361,12 +7356,15 @@ rewrite_to_defined_overflow (gimple *stmt)
tree lhs = gimple_assign_lhs (stmt);
tree type = unsigned_type_for (TREE_TYPE (lhs));
gimple_seq stmts = NULL;
- for (unsigned i = 1; i < gimple_num_ops (stmt); ++i)
- {
- tree op = gimple_op (stmt, i);
- op = gimple_convert (&stmts, type, op);
- gimple_set_op (stmt, i, op);
- }
+ if (gimple_assign_rhs_code (stmt) == ABS_EXPR)
+ gimple_assign_set_rhs_code (stmt, ABSU_EXPR);
+ else
+ for (unsigned i = 1; i < gimple_num_ops (stmt); ++i)
+ {
+ tree op = gimple_op (stmt, i);
+ op = gimple_convert (&stmts, type, op);
+ gimple_set_op (stmt, i, op);
+ }
gimple_assign_set_lhs (stmt, make_ssa_name (type, stmt));
if (gimple_assign_rhs_code (stmt) == POINTER_PLUS_EXPR)
gimple_assign_set_rhs_code (stmt, PLUS_EXPR);
diff --git a/gcc/gimple-loop-versioning.cc b/gcc/gimple-loop-versioning.cc
index 2f7cda9..fe27300 100644
--- a/gcc/gimple-loop-versioning.cc
+++ b/gcc/gimple-loop-versioning.cc
@@ -1488,7 +1488,7 @@ loop_versioning::prune_loop_conditions (struct loop *loop, vr_values *vrs)
{
tree name = ssa_name (i);
value_range *vr = vrs->get_value_range (name);
- if (vr && !range_includes_p (vr, 1))
+ if (vr && !vr->may_contain_p (build_one_cst (TREE_TYPE (name))))
{
if (dump_enabled_p ())
dump_printf_loc (MSG_NOTE, find_loop_location (loop),
diff --git a/gcc/gimple-low.c b/gcc/gimple-low.c
index 1ae3db0..961b7f4 100644
--- a/gcc/gimple-low.c
+++ b/gcc/gimple-low.c
@@ -336,6 +336,7 @@ lower_stmt (gimple_stmt_iterator *gsi, struct lower_data *data)
case GIMPLE_OMP_MASTER:
case GIMPLE_OMP_TASKGROUP:
case GIMPLE_OMP_ORDERED:
+ case GIMPLE_OMP_SCAN:
case GIMPLE_OMP_CRITICAL:
case GIMPLE_OMP_RETURN:
case GIMPLE_OMP_ATOMIC_LOAD:
diff --git a/gcc/gimple-match-head.c b/gcc/gimple-match-head.c
index bbbc0f2..df9f0c5 100644
--- a/gcc/gimple-match-head.c
+++ b/gcc/gimple-match-head.c
@@ -27,6 +27,7 @@ along with GCC; see the file COPYING3. If not see
#include "gimple.h"
#include "ssa.h"
#include "cgraph.h"
+#include "vec-perm-indices.h"
#include "fold-const.h"
#include "fold-const-call.h"
#include "stor-layout.h"
@@ -41,7 +42,7 @@ along with GCC; see the file COPYING3. If not see
#include "gimplify.h"
#include "optabs-tree.h"
#include "tree-eh.h"
-
+#include "dbgcnt.h"
/* Forward declarations of the private auto-generated matchers.
They expect valueized operands in canonical order and do not
diff --git a/gcc/gimple-pretty-print.c b/gcc/gimple-pretty-print.c
index 58212c4..45e7260 100644
--- a/gcc/gimple-pretty-print.c
+++ b/gcc/gimple-pretty-print.c
@@ -43,6 +43,13 @@ along with GCC; see the file COPYING3. If not see
#include "asan.h"
#include "cfgloop.h"
+/* Disable warnings about quoting issues in the pp_xxx calls below
+ that (intentionally) don't follow GCC diagnostic conventions. */
+#if __GNUC__ >= 10
+# pragma GCC diagnostic push
+# pragma GCC diagnostic ignored "-Wformat-diag"
+#endif
+
#define INDENT(SPACE) \
do { int i; for (i = 0; i < SPACE; i++) pp_space (buffer); } while (0)
@@ -529,13 +536,19 @@ dump_ternary_rhs (pretty_printer *buffer, gassign *gs, int spc,
break;
case VEC_PERM_EXPR:
- pp_string (buffer, "VEC_PERM_EXPR <");
+ if (flags & TDF_GIMPLE)
+ pp_string (buffer, "__VEC_PERM (");
+ else
+ pp_string (buffer, "VEC_PERM_EXPR <");
dump_generic_node (buffer, gimple_assign_rhs1 (gs), spc, flags, false);
pp_string (buffer, ", ");
dump_generic_node (buffer, gimple_assign_rhs2 (gs), spc, flags, false);
pp_string (buffer, ", ");
dump_generic_node (buffer, gimple_assign_rhs3 (gs), spc, flags, false);
- pp_greater (buffer);
+ if (flags & TDF_GIMPLE)
+ pp_right_paren (buffer);
+ else
+ pp_greater (buffer);
break;
case REALIGN_LOAD_EXPR:
@@ -567,21 +580,39 @@ dump_ternary_rhs (pretty_printer *buffer, gassign *gs, int spc,
break;
case BIT_INSERT_EXPR:
- pp_string (buffer, "BIT_INSERT_EXPR <");
- dump_generic_node (buffer, gimple_assign_rhs1 (gs), spc, flags, false);
- pp_string (buffer, ", ");
- dump_generic_node (buffer, gimple_assign_rhs2 (gs), spc, flags, false);
- pp_string (buffer, ", ");
- dump_generic_node (buffer, gimple_assign_rhs3 (gs), spc, flags, false);
- pp_string (buffer, " (");
- if (INTEGRAL_TYPE_P (TREE_TYPE (gimple_assign_rhs2 (gs))))
- pp_decimal_int (buffer,
- TYPE_PRECISION (TREE_TYPE (gimple_assign_rhs2 (gs))));
+ if (flags & TDF_GIMPLE)
+ {
+ pp_string (buffer, "__BIT_INSERT (");
+ dump_generic_node (buffer, gimple_assign_rhs1 (gs), spc,
+ flags | TDF_SLIM, false);
+ pp_string (buffer, ", ");
+ dump_generic_node (buffer, gimple_assign_rhs2 (gs), spc,
+ flags | TDF_SLIM, false);
+ pp_string (buffer, ", ");
+ dump_generic_node (buffer, gimple_assign_rhs3 (gs), spc,
+ flags | TDF_SLIM, false);
+ pp_right_paren (buffer);
+ }
else
- dump_generic_node (buffer,
- TYPE_SIZE (TREE_TYPE (gimple_assign_rhs2 (gs))),
- spc, flags, false);
- pp_string (buffer, " bits)>");
+ {
+ pp_string (buffer, "BIT_INSERT_EXPR <");
+ dump_generic_node (buffer, gimple_assign_rhs1 (gs),
+ spc, flags, false);
+ pp_string (buffer, ", ");
+ dump_generic_node (buffer, gimple_assign_rhs2 (gs),
+ spc, flags, false);
+ pp_string (buffer, ", ");
+ dump_generic_node (buffer, gimple_assign_rhs3 (gs),
+ spc, flags, false);
+ if (INTEGRAL_TYPE_P (TREE_TYPE (gimple_assign_rhs2 (gs))))
+ {
+ pp_string (buffer, " (");
+ pp_decimal_int (buffer, TYPE_PRECISION
+ (TREE_TYPE (gimple_assign_rhs2 (gs))));
+ pp_string (buffer, " bits)");
+ }
+ pp_greater (buffer);
+ }
break;
default:
@@ -1772,9 +1803,6 @@ dump_gimple_omp_block (pretty_printer *buffer, gimple *gs, int spc,
case GIMPLE_OMP_MASTER:
pp_string (buffer, "#pragma omp master");
break;
- case GIMPLE_OMP_TASKGROUP:
- pp_string (buffer, "#pragma omp taskgroup");
- break;
case GIMPLE_OMP_SECTION:
pp_string (buffer, "#pragma omp section");
break;
@@ -1853,6 +1881,34 @@ dump_gimple_omp_ordered (pretty_printer *buffer, gomp_ordered *gs,
}
}
+/* Dump a GIMPLE_OMP_SCAN tuple on the pretty_printer BUFFER. */
+
+static void
+dump_gimple_omp_scan (pretty_printer *buffer, gomp_scan *gs,
+ int spc, dump_flags_t flags)
+{
+ if (flags & TDF_RAW)
+ dump_gimple_fmt (buffer, spc, flags, "%G <%+BODY <%S> >", gs,
+ gimple_omp_body (gs));
+ else
+ {
+ if (gimple_omp_scan_clauses (gs))
+ {
+ pp_string (buffer, "#pragma omp scan");
+ dump_omp_clauses (buffer, gimple_omp_scan_clauses (gs), spc, flags);
+ }
+ if (!gimple_seq_empty_p (gimple_omp_body (gs)))
+ {
+ newline_and_indent (buffer, spc + 2);
+ pp_left_brace (buffer);
+ pp_newline (buffer);
+ dump_gimple_seq (buffer, gimple_omp_body (gs), spc + 4, flags);
+ newline_and_indent (buffer, spc + 2);
+ pp_right_brace (buffer);
+ }
+ }
+}
+
/* Dump a GIMPLE_OMP_RETURN tuple on the pretty_printer BUFFER. */
static void
@@ -2625,6 +2681,11 @@ pp_gimple_stmt_1 (pretty_printer *buffer, gimple *gs, int spc,
flags);
break;
+ case GIMPLE_OMP_SCAN:
+ dump_gimple_omp_scan (buffer, as_a <gomp_scan *> (gs), spc,
+ flags);
+ break;
+
case GIMPLE_OMP_CRITICAL:
dump_gimple_omp_critical (buffer, as_a <gomp_critical *> (gs), spc,
flags);
@@ -2958,3 +3019,7 @@ percent_G_format (text_info *text)
tree block = gimple_block (stmt);
percent_K_format (text, gimple_location (stmt), block);
}
+
+#if __GNUC__ >= 10
+# pragma GCC diagnostic pop
+#endif
diff --git a/gcc/gimple-ssa-evrp-analyze.c b/gcc/gimple-ssa-evrp-analyze.c
index bb4e2d6..4c68af8 100644
--- a/gcc/gimple-ssa-evrp-analyze.c
+++ b/gcc/gimple-ssa-evrp-analyze.c
@@ -210,9 +210,10 @@ evrp_range_analyzer::record_ranges_from_incoming_edge (basic_block bb)
getting first [64, +INF] and then ~[0, 0] from
conditions like (s & 0x3cc0) == 0). */
value_range *old_vr = get_value_range (vrs[i].first);
- value_range tem (old_vr->kind (), old_vr->min (), old_vr->max ());
+ value_range_base tem (old_vr->kind (), old_vr->min (),
+ old_vr->max ());
tem.intersect (vrs[i].second);
- if (tem.equal_p (*old_vr, /*ignore_equivs=*/true))
+ if (tem.equal_p (*old_vr))
continue;
push_value_range (vrs[i].first, vrs[i].second);
if (is_fallthru
diff --git a/gcc/gimple-ssa-evrp.c b/gcc/gimple-ssa-evrp.c
index 96da79b..5b99388 100644
--- a/gcc/gimple-ssa-evrp.c
+++ b/gcc/gimple-ssa-evrp.c
@@ -111,8 +111,8 @@ evrp_dom_walker::before_dom_children (basic_block bb)
value_range *vr = evrp_range_analyzer.get_value_range (lhs);
/* Mark PHIs whose lhs we fully propagate for removal. */
- tree val = value_range_constant_singleton (vr);
- if (val && may_propagate_copy (lhs, val))
+ tree val;
+ if (vr->singleton_p (&val) && may_propagate_copy (lhs, val))
{
stmts_to_remove.safe_push (phi);
continue;
@@ -162,7 +162,7 @@ evrp_dom_walker::before_dom_children (basic_block bb)
value_range *vr = evrp_range_analyzer.get_value_range (output);
/* Mark stmts whose output we fully propagate for removal. */
- if ((val = value_range_constant_singleton (vr))
+ if (vr->singleton_p (&val)
&& may_propagate_copy (output, val)
&& !stmt_could_throw_p (cfun, stmt)
&& !gimple_has_side_effects (stmt))
@@ -175,6 +175,8 @@ evrp_dom_walker::before_dom_children (basic_block bb)
/* Try folding stmts with the VR discovered. */
bool did_replace = evrp_folder.replace_uses_in (stmt);
+ gimple_stmt_iterator prev_gsi = gsi;
+ gsi_prev (&prev_gsi);
if (fold_stmt (&gsi, follow_single_use_edges)
|| did_replace)
{
@@ -191,6 +193,21 @@ evrp_dom_walker::before_dom_children (basic_block bb)
if (did_replace)
{
+ /* If we wound up generating new stmts during folding
+ drop all their defs to VARYING. We can't easily
+ process them because we've already instantiated
+ ranges on uses on STMT that only hold after it. */
+ if (gsi_end_p (prev_gsi))
+ prev_gsi = gsi_start_bb (bb);
+ else
+ gsi_next (&prev_gsi);
+ while (gsi_stmt (prev_gsi) != gsi_stmt (gsi))
+ {
+ evrp_range_analyzer.get_vr_values ()
+ ->set_defs_to_varying (gsi_stmt (prev_gsi));
+ gsi_next (&prev_gsi);
+ }
+
/* If we cleaned up EH information from the statement,
remove EH edges. */
if (maybe_clean_or_replace_eh_stmt (old_stmt, stmt))
@@ -227,8 +244,8 @@ evrp_dom_walker::before_dom_children (basic_block bb)
|| virtual_operand_p (arg))
continue;
value_range *vr = evrp_range_analyzer.get_value_range (arg);
- tree val = value_range_constant_singleton (vr);
- if (val && may_propagate_copy (arg, val))
+ tree val;
+ if (vr->singleton_p (&val) && may_propagate_copy (arg, val))
propagate_value (use_p, val);
}
}
diff --git a/gcc/gimple-ssa-nonnull-compare.c b/gcc/gimple-ssa-nonnull-compare.c
index e6e9ffa..a944991 100644
--- a/gcc/gimple-ssa-nonnull-compare.c
+++ b/gcc/gimple-ssa-nonnull-compare.c
@@ -99,7 +99,7 @@ do_warn_nonnull_compare (function *fun, tree arg)
? integer_zerop (op) : integer_minus_onep (op))
&& !gimple_no_warning_p (stmt))
warning_at (loc, OPT_Wnonnull_compare,
- "nonnull argument %qD compared to NULL", arg);
+ "%<nonnull%> argument %qD compared to NULL", arg);
}
}
diff --git a/gcc/gimple-ssa-sprintf.c b/gcc/gimple-ssa-sprintf.c
index 80b0bf8..a0934bc 100644
--- a/gcc/gimple-ssa-sprintf.c
+++ b/gcc/gimple-ssa-sprintf.c
@@ -1019,10 +1019,12 @@ build_intmax_type_nodes (tree *pintmax, tree *puintmax)
for (int i = 0; i < NUM_INT_N_ENTS; i++)
if (int_n_enabled_p[i])
{
- char name[50];
+ char name[50], altname[50];
sprintf (name, "__int%d unsigned", int_n_data[i].bitsize);
+ sprintf (altname, "__int%d__ unsigned", int_n_data[i].bitsize);
- if (strcmp (name, UINTMAX_TYPE) == 0)
+ if (strcmp (name, UINTMAX_TYPE) == 0
+ || strcmp (altname, UINTMAX_TYPE) == 0)
{
*pintmax = int_n_trees[i].signed_type;
*puintmax = int_n_trees[i].unsigned_type;
diff --git a/gcc/gimple-ssa-strength-reduction.c b/gcc/gimple-ssa-strength-reduction.c
index 937a877..bfda44a 100644
--- a/gcc/gimple-ssa-strength-reduction.c
+++ b/gcc/gimple-ssa-strength-reduction.c
@@ -418,7 +418,7 @@ static bool legal_cast_p_1 (tree, tree);
static slsr_cand_t
lookup_cand (cand_idx idx)
{
- return cand_vec[idx - 1];
+ return cand_vec[idx];
}
/* Helper for hashing a candidate chain header. */
@@ -688,7 +688,7 @@ alloc_cand_and_find_basis (enum cand_kind kind, gimple *gs, tree base,
c->cand_type = ctype;
c->stride_type = stype;
c->kind = kind;
- c->cand_num = cand_vec.length () + 1;
+ c->cand_num = cand_vec.length ();
c->next_interp = 0;
c->first_interp = c->cand_num;
c->dependent = 0;
@@ -933,10 +933,7 @@ backtrace_base_for_ref (tree *pbase)
return base_cand->index;
}
- if (base_cand->next_interp)
- base_cand = lookup_cand (base_cand->next_interp);
- else
- base_cand = NULL;
+ base_cand = lookup_cand (base_cand->next_interp);
}
return 0;
@@ -1124,10 +1121,7 @@ create_mul_ssa_cand (gimple *gs, tree base_in, tree stride_in, bool speed)
+ stmt_cost (base_cand->cand_stmt, speed));
}
- if (base_cand->next_interp)
- base_cand = lookup_cand (base_cand->next_interp);
- else
- base_cand = NULL;
+ base_cand = lookup_cand (base_cand->next_interp);
}
if (!base)
@@ -1214,10 +1208,7 @@ create_mul_imm_cand (gimple *gs, tree base_in, tree stride_in, bool speed)
+ stmt_cost (base_cand->cand_stmt, speed));
}
- if (base_cand->next_interp)
- base_cand = lookup_cand (base_cand->next_interp);
- else
- base_cand = NULL;
+ base_cand = lookup_cand (base_cand->next_interp);
}
if (!base)
@@ -1320,10 +1311,7 @@ create_add_ssa_cand (gimple *gs, tree base_in, tree addend_in,
+ stmt_cost (addend_cand->cand_stmt, speed));
}
- if (addend_cand->next_interp)
- addend_cand = lookup_cand (addend_cand->next_interp);
- else
- addend_cand = NULL;
+ addend_cand = lookup_cand (addend_cand->next_interp);
}
while (base_cand && !base && base_cand->kind != CAND_PHI)
@@ -1371,18 +1359,12 @@ create_add_ssa_cand (gimple *gs, tree base_in, tree addend_in,
savings = (subtrahend_cand->dead_savings
+ stmt_cost (subtrahend_cand->cand_stmt, speed));
}
-
- if (subtrahend_cand->next_interp)
- subtrahend_cand = lookup_cand (subtrahend_cand->next_interp);
- else
- subtrahend_cand = NULL;
+
+ subtrahend_cand = lookup_cand (subtrahend_cand->next_interp);
}
}
- if (base_cand->next_interp)
- base_cand = lookup_cand (base_cand->next_interp);
- else
- base_cand = NULL;
+ base_cand = lookup_cand (base_cand->next_interp);
}
if (!base)
@@ -1446,10 +1428,7 @@ create_add_imm_cand (gimple *gs, tree base_in, const widest_int &index_in,
+ stmt_cost (base_cand->cand_stmt, speed));
}
- if (base_cand->next_interp)
- base_cand = lookup_cand (base_cand->next_interp);
- else
- base_cand = NULL;
+ base_cand = lookup_cand (base_cand->next_interp);
}
if (!base)
@@ -1652,10 +1631,7 @@ slsr_process_cast (gimple *gs, tree rhs1, bool speed)
if (first_cand != c)
c->first_interp = first_cand->cand_num;
- if (base_cand->next_interp)
- base_cand = lookup_cand (base_cand->next_interp);
- else
- base_cand = NULL;
+ base_cand = lookup_cand (base_cand->next_interp);
}
}
else
@@ -1719,10 +1695,7 @@ slsr_process_copy (gimple *gs, tree rhs1, bool speed)
if (first_cand != c)
c->first_interp = first_cand->cand_num;
- if (base_cand->next_interp)
- base_cand = lookup_cand (base_cand->next_interp);
- else
- base_cand = NULL;
+ base_cand = lookup_cand (base_cand->next_interp);
}
}
else
@@ -1933,7 +1906,8 @@ dump_cand_vec (void)
fprintf (dump_file, "\nStrength reduction candidate vector:\n\n");
FOR_EACH_VEC_ELT (cand_vec, i, c)
- dump_candidate (c);
+ if (c != NULL)
+ dump_candidate (c);
}
/* Callback used to dump the candidate chains hash table. */
@@ -2181,7 +2155,7 @@ replace_mult_candidate (slsr_cand_t c, tree basis_name, widest_int bump)
while (cc)
{
cc->cand_stmt = copy_stmt;
- cc = cc->next_interp ? lookup_cand (cc->next_interp) : NULL;
+ cc = lookup_cand (cc->next_interp);
}
if (dump_file && (dump_flags & TDF_DETAILS))
stmt_to_print = copy_stmt;
@@ -2214,7 +2188,7 @@ replace_mult_candidate (slsr_cand_t c, tree basis_name, widest_int bump)
while (cc)
{
cc->cand_stmt = gsi_stmt (gsi);
- cc = cc->next_interp ? lookup_cand (cc->next_interp) : NULL;
+ cc = lookup_cand (cc->next_interp);
}
if (dump_file && (dump_flags & TDF_DETAILS))
stmt_to_print = gsi_stmt (gsi);
@@ -3654,7 +3628,7 @@ replace_rhs_if_not_dup (enum tree_code new_code, tree new_rhs1, tree new_rhs2,
while (cc)
{
cc->cand_stmt = gsi_stmt (gsi);
- cc = cc->next_interp ? lookup_cand (cc->next_interp) : NULL;
+ cc = lookup_cand (cc->next_interp);
}
if (dump_file && (dump_flags & TDF_DETAILS))
@@ -3770,7 +3744,7 @@ replace_one_candidate (slsr_cand_t c, unsigned i, tree basis_name)
while (cc)
{
cc->cand_stmt = gsi_stmt (gsi);
- cc = cc->next_interp ? lookup_cand (cc->next_interp) : NULL;
+ cc = lookup_cand (cc->next_interp);
}
if (dump_file && (dump_flags & TDF_DETAILS))
@@ -3796,7 +3770,7 @@ replace_one_candidate (slsr_cand_t c, unsigned i, tree basis_name)
while (cc)
{
cc->cand_stmt = copy_stmt;
- cc = cc->next_interp ? lookup_cand (cc->next_interp) : NULL;
+ cc = lookup_cand (cc->next_interp);
}
if (dump_file && (dump_flags & TDF_DETAILS))
@@ -3812,7 +3786,7 @@ replace_one_candidate (slsr_cand_t c, unsigned i, tree basis_name)
while (cc)
{
cc->cand_stmt = cast_stmt;
- cc = cc->next_interp ? lookup_cand (cc->next_interp) : NULL;
+ cc = lookup_cand (cc->next_interp);
}
if (dump_file && (dump_flags & TDF_DETAILS))
@@ -3902,8 +3876,10 @@ analyze_candidates_and_replace (void)
/* Each candidate that has a null basis and a non-null
dependent is the root of a tree of related statements.
Analyze each tree to determine a subset of those
- statements that can be replaced with maximum benefit. */
- FOR_EACH_VEC_ELT (cand_vec, i, c)
+ statements that can be replaced with maximum benefit.
+
+ Note the first NULL element is skipped. */
+ FOR_EACH_VEC_ELT_FROM (cand_vec, i, c, 1)
{
slsr_cand_t first_dep;
@@ -4010,8 +3986,9 @@ pass_strength_reduction::execute (function *fun)
/* Create the obstack where candidates will reside. */
gcc_obstack_init (&cand_obstack);
- /* Allocate the candidate vector. */
+ /* Allocate the candidate vector and initialize the first NULL element. */
cand_vec.create (128);
+ cand_vec.safe_push (NULL);
/* Allocate the mapping from statements to candidate indices. */
stmt_cand_map = new hash_map<gimple *, slsr_cand_t>;
diff --git a/gcc/gimple-walk.c b/gcc/gimple-walk.c
index 29f33b0..2b8f1e0b 100644
--- a/gcc/gimple-walk.c
+++ b/gcc/gimple-walk.c
@@ -336,6 +336,16 @@ walk_gimple_op (gimple *stmt, walk_tree_fn callback_op,
}
break;
+ case GIMPLE_OMP_SCAN:
+ {
+ gomp_scan *scan_stmt = as_a <gomp_scan *> (stmt);
+ ret = walk_tree (gimple_omp_scan_clauses_ptr (scan_stmt),
+ callback_op, wi, pset);
+ if (ret)
+ return ret;
+ }
+ break;
+
case GIMPLE_OMP_FOR:
ret = walk_tree (gimple_omp_for_clauses_ptr (stmt), callback_op, wi,
pset);
@@ -650,6 +660,7 @@ walk_gimple_stmt (gimple_stmt_iterator *gsi, walk_stmt_fn callback_stmt,
case GIMPLE_OMP_MASTER:
case GIMPLE_OMP_TASKGROUP:
case GIMPLE_OMP_ORDERED:
+ case GIMPLE_OMP_SCAN:
case GIMPLE_OMP_SECTION:
case GIMPLE_OMP_PARALLEL:
case GIMPLE_OMP_TASK:
diff --git a/gcc/gimple.c b/gcc/gimple.c
index 8fae60f..63c8d5e 100644
--- a/gcc/gimple.c
+++ b/gcc/gimple.c
@@ -1108,6 +1108,25 @@ gimple_build_omp_return (bool wait_p)
}
+/* Build a GIMPLE_OMP_SCAN statement.
+
+ BODY is the sequence of statements to be executed by the scan
+ construct.
+ CLAUSES are any of the construct's clauses. */
+
+gomp_scan *
+gimple_build_omp_scan (gimple_seq body, tree clauses)
+{
+ gomp_scan *p
+ = as_a <gomp_scan *> (gimple_alloc (GIMPLE_OMP_SCAN, 0));
+ gimple_omp_scan_set_clauses (p, clauses);
+ if (body)
+ gimple_omp_set_body (p, body);
+
+ return p;
+}
+
+
/* Build a GIMPLE_OMP_SECTIONS statement.
BODY is a sequence of section statements.
@@ -1943,6 +1962,12 @@ gimple_copy (gimple *stmt)
gimple_omp_ordered_set_clauses (as_a <gomp_ordered *> (copy), t);
goto copy_omp_body;
+ case GIMPLE_OMP_SCAN:
+ t = gimple_omp_scan_clauses (as_a <gomp_scan *> (stmt));
+ t = unshare_expr (t);
+ gimple_omp_scan_set_clauses (as_a <gomp_scan *> (copy), t);
+ goto copy_omp_body;
+
case GIMPLE_OMP_TASKGROUP:
t = unshare_expr (gimple_omp_taskgroup_clauses (stmt));
gimple_omp_taskgroup_set_clauses (copy, t);
diff --git a/gcc/gimple.def b/gcc/gimple.def
index 78e3467..dd64419 100644
--- a/gcc/gimple.def
+++ b/gcc/gimple.def
@@ -331,6 +331,11 @@ DEFGSCODE(GIMPLE_OMP_TASK, "gimple_omp_task", GSS_OMP_TASK)
/* OMP_RETURN marks the end of an OpenMP directive. */
DEFGSCODE(GIMPLE_OMP_RETURN, "gimple_omp_return", GSS_OMP_ATOMIC_STORE_LAYOUT)
+/* GIMPLE_OMP_SCAN <BODY, CLAUSES> represents #pragma omp scan
+ BODY is the sequence of statements inside the single section.
+ CLAUSES is an OMP_CLAUSE chain holding the associated clauses. */
+DEFGSCODE(GIMPLE_OMP_SCAN, "gimple_omp_scan", GSS_OMP_SINGLE_LAYOUT)
+
/* OMP_SECTION <BODY> represents #pragma omp section.
BODY is the sequence of statements in the section body. */
DEFGSCODE(GIMPLE_OMP_SECTION, "gimple_omp_section", GSS_OMP)
diff --git a/gcc/gimple.h b/gcc/gimple.h
index 8b5c9e2..47070e7 100644
--- a/gcc/gimple.h
+++ b/gcc/gimple.h
@@ -741,7 +741,8 @@ struct GTY((tag("GSS_OMP_CONTINUE")))
tree control_use;
};
-/* GIMPLE_OMP_SINGLE, GIMPLE_OMP_ORDERED, GIMPLE_OMP_TASKGROUP. */
+/* GIMPLE_OMP_SINGLE, GIMPLE_OMP_ORDERED, GIMPLE_OMP_TASKGROUP,
+ GIMPLE_OMP_SCAN. */
struct GTY((tag("GSS_OMP_SINGLE_LAYOUT")))
gimple_statement_omp_single_layout : public gimple_statement_omp
@@ -773,6 +774,13 @@ struct GTY((tag("GSS_OMP_SINGLE_LAYOUT")))
stmt->code == GIMPLE_OMP_ORDERED. */
};
+struct GTY((tag("GSS_OMP_SINGLE_LAYOUT")))
+ gomp_scan : public gimple_statement_omp_single_layout
+{
+ /* No extra fields; adds invariant:
+ stmt->code == GIMPLE_OMP_SCAN. */
+};
+
/* GIMPLE_OMP_ATOMIC_LOAD.
Note: This is based on gimple, not g_s_omp, because g_s_omp
@@ -1115,6 +1123,14 @@ is_a_helper <gomp_ordered *>::test (gimple *gs)
template <>
template <>
inline bool
+is_a_helper <gomp_scan *>::test (gimple *gs)
+{
+ return gs->code == GIMPLE_OMP_SCAN;
+}
+
+template <>
+template <>
+inline bool
is_a_helper <gomp_for *>::test (gimple *gs)
{
return gs->code == GIMPLE_OMP_FOR;
@@ -1333,6 +1349,14 @@ is_a_helper <const gomp_ordered *>::test (const gimple *gs)
template <>
template <>
inline bool
+is_a_helper <const gomp_scan *>::test (const gimple *gs)
+{
+ return gs->code == GIMPLE_OMP_SCAN;
+}
+
+template <>
+template <>
+inline bool
is_a_helper <const gomp_for *>::test (const gimple *gs)
{
return gs->code == GIMPLE_OMP_FOR;
@@ -1475,6 +1499,7 @@ gimple *gimple_build_omp_taskgroup (gimple_seq, tree);
gomp_continue *gimple_build_omp_continue (tree, tree);
gomp_ordered *gimple_build_omp_ordered (gimple_seq, tree);
gimple *gimple_build_omp_return (bool);
+gomp_scan *gimple_build_omp_scan (gimple_seq, tree);
gomp_sections *gimple_build_omp_sections (gimple_seq, tree);
gimple *gimple_build_omp_sections_switch (void);
gomp_single *gimple_build_omp_single (gimple_seq, tree);
@@ -4946,6 +4971,35 @@ gimple_omp_ordered_set_clauses (gomp_ordered *ord_stmt, tree clauses)
}
+/* Return the clauses associated with OMP_SCAN statement SCAN_STMT. */
+
+static inline tree
+gimple_omp_scan_clauses (const gomp_scan *scan_stmt)
+{
+ return scan_stmt->clauses;
+}
+
+
+/* Return a pointer to the clauses associated with OMP scan statement
+ ORD_STMT. */
+
+static inline tree *
+gimple_omp_scan_clauses_ptr (gomp_scan *scan_stmt)
+{
+ return &scan_stmt->clauses;
+}
+
+
+/* Set CLAUSES to be the clauses associated with OMP scan statement
+ ORD_STMT. */
+
+static inline void
+gimple_omp_scan_set_clauses (gomp_scan *scan_stmt, tree clauses)
+{
+ scan_stmt->clauses = clauses;
+}
+
+
/* Return the clauses associated with OMP_TASKGROUP statement GS. */
static inline tree
@@ -6379,6 +6433,7 @@ gimple_return_set_retval (greturn *gs, tree retval)
case GIMPLE_OMP_TASKGROUP: \
case GIMPLE_OMP_ORDERED: \
case GIMPLE_OMP_CRITICAL: \
+ case GIMPLE_OMP_SCAN: \
case GIMPLE_OMP_RETURN: \
case GIMPLE_OMP_ATOMIC_LOAD: \
case GIMPLE_OMP_ATOMIC_STORE: \
diff --git a/gcc/gimplify.c b/gcc/gimplify.c
index b6c6085..9e5e423 100644
--- a/gcc/gimplify.c
+++ b/gcc/gimplify.c
@@ -65,53 +65,63 @@ along with GCC; see the file COPYING3. If not see
#include "attribs.h"
#include "asan.h"
#include "dbgcnt.h"
+#include "omp-offload.h"
+#include "context.h"
/* Hash set of poisoned variables in a bind expr. */
static hash_set<tree> *asan_poisoned_variables = NULL;
enum gimplify_omp_var_data
{
- GOVD_SEEN = 1,
- GOVD_EXPLICIT = 2,
- GOVD_SHARED = 4,
- GOVD_PRIVATE = 8,
- GOVD_FIRSTPRIVATE = 16,
- GOVD_LASTPRIVATE = 32,
- GOVD_REDUCTION = 64,
- GOVD_LOCAL = 128,
- GOVD_MAP = 256,
- GOVD_DEBUG_PRIVATE = 512,
- GOVD_PRIVATE_OUTER_REF = 1024,
- GOVD_LINEAR = 2048,
- GOVD_ALIGNED = 4096,
+ GOVD_SEEN = 0x000001,
+ GOVD_EXPLICIT = 0x000002,
+ GOVD_SHARED = 0x000004,
+ GOVD_PRIVATE = 0x000008,
+ GOVD_FIRSTPRIVATE = 0x000010,
+ GOVD_LASTPRIVATE = 0x000020,
+ GOVD_REDUCTION = 0x000040,
+ GOVD_LOCAL = 0x00080,
+ GOVD_MAP = 0x000100,
+ GOVD_DEBUG_PRIVATE = 0x000200,
+ GOVD_PRIVATE_OUTER_REF = 0x000400,
+ GOVD_LINEAR = 0x000800,
+ GOVD_ALIGNED = 0x001000,
/* Flag for GOVD_MAP: don't copy back. */
- GOVD_MAP_TO_ONLY = 8192,
+ GOVD_MAP_TO_ONLY = 0x002000,
/* Flag for GOVD_LINEAR or GOVD_LASTPRIVATE: no outer reference. */
- GOVD_LINEAR_LASTPRIVATE_NO_OUTER = 16384,
+ GOVD_LINEAR_LASTPRIVATE_NO_OUTER = 0x004000,
- GOVD_MAP_0LEN_ARRAY = 32768,
+ GOVD_MAP_0LEN_ARRAY = 0x008000,
/* Flag for GOVD_MAP, if it is always, to or always, tofrom mapping. */
- GOVD_MAP_ALWAYS_TO = 65536,
+ GOVD_MAP_ALWAYS_TO = 0x010000,
/* Flag for shared vars that are or might be stored to in the region. */
- GOVD_WRITTEN = 131072,
+ GOVD_WRITTEN = 0x020000,
/* Flag for GOVD_MAP, if it is a forced mapping. */
- GOVD_MAP_FORCE = 262144,
+ GOVD_MAP_FORCE = 0x040000,
/* Flag for GOVD_MAP: must be present already. */
- GOVD_MAP_FORCE_PRESENT = 524288,
+ GOVD_MAP_FORCE_PRESENT = 0x080000,
/* Flag for GOVD_MAP: only allocate. */
- GOVD_MAP_ALLOC_ONLY = 1048576,
+ GOVD_MAP_ALLOC_ONLY = 0x100000,
/* Flag for GOVD_MAP: only copy back. */
- GOVD_MAP_FROM_ONLY = 2097152,
+ GOVD_MAP_FROM_ONLY = 0x200000,
- GOVD_NONTEMPORAL = 4194304,
+ GOVD_NONTEMPORAL = 0x400000,
+
+ /* Flag for GOVD_LASTPRIVATE: conditional modifier. */
+ GOVD_LASTPRIVATE_CONDITIONAL = 0x800000,
+
+ GOVD_CONDTEMP = 0x1000000,
+
+ /* Flag for GOVD_REDUCTION: inscan seen in {in,ex}clusive clause. */
+ GOVD_REDUCTION_INSCAN = 0x2000000,
GOVD_DATA_SHARE_CLASS = (GOVD_SHARED | GOVD_PRIVATE | GOVD_FIRSTPRIVATE
| GOVD_LASTPRIVATE | GOVD_REDUCTION | GOVD_LINEAR
@@ -202,6 +212,7 @@ struct gimplify_omp_ctx
struct gimplify_omp_ctx *outer_context;
splay_tree variables;
hash_set<tree> *privatized_types;
+ tree clauses;
/* Iteration variables in an OMP_FOR. */
vec<tree> loop_iter_var;
location_t location;
@@ -1314,17 +1325,45 @@ gimplify_bind_expr (tree *expr_p, gimple_seq *pre_p)
struct gimplify_omp_ctx *ctx = gimplify_omp_ctxp;
/* Mark variable as local. */
- if (ctx && ctx->region_type != ORT_NONE && !DECL_EXTERNAL (t)
- && (! DECL_SEEN_IN_BIND_EXPR_P (t)
- || splay_tree_lookup (ctx->variables,
- (splay_tree_key) t) == NULL))
+ if (ctx && ctx->region_type != ORT_NONE && !DECL_EXTERNAL (t))
{
- if (ctx->region_type == ORT_SIMD
- && TREE_ADDRESSABLE (t)
- && !TREE_STATIC (t))
- omp_add_variable (ctx, t, GOVD_PRIVATE | GOVD_SEEN);
- else
- omp_add_variable (ctx, t, GOVD_LOCAL | GOVD_SEEN);
+ if (! DECL_SEEN_IN_BIND_EXPR_P (t)
+ || splay_tree_lookup (ctx->variables,
+ (splay_tree_key) t) == NULL)
+ {
+ if (ctx->region_type == ORT_SIMD
+ && TREE_ADDRESSABLE (t)
+ && !TREE_STATIC (t))
+ omp_add_variable (ctx, t, GOVD_PRIVATE | GOVD_SEEN);
+ else
+ omp_add_variable (ctx, t, GOVD_LOCAL | GOVD_SEEN);
+ }
+ /* Static locals inside of target construct or offloaded
+ routines need to be "omp declare target". */
+ if (TREE_STATIC (t))
+ for (; ctx; ctx = ctx->outer_context)
+ if ((ctx->region_type & ORT_TARGET) != 0)
+ {
+ if (!lookup_attribute ("omp declare target",
+ DECL_ATTRIBUTES (t)))
+ {
+ tree id = get_identifier ("omp declare target");
+ DECL_ATTRIBUTES (t)
+ = tree_cons (id, NULL_TREE, DECL_ATTRIBUTES (t));
+ varpool_node *node = varpool_node::get (t);
+ if (node)
+ {
+ node->offloadable = 1;
+ if (ENABLE_OFFLOADING && !DECL_EXTERNAL (t))
+ {
+ g->have_offload = true;
+ if (!in_lto_p)
+ vec_safe_push (offload_vars, t);
+ }
+ }
+ }
+ break;
+ }
}
DECL_SEEN_IN_BIND_EXPR_P (t) = 1;
@@ -2081,6 +2120,8 @@ collect_fallthrough_labels (gimple_stmt_iterator *gsi_p,
}
else if (gimple_call_internal_p (gsi_stmt (*gsi_p), IFN_ASAN_MARK))
;
+ else if (gimple_code (gsi_stmt (*gsi_p)) == GIMPLE_PREDICT)
+ ;
else if (!is_gimple_debug (gsi_stmt (*gsi_p)))
prev = gsi_stmt (*gsi_p);
gsi_next (gsi_p);
@@ -3297,6 +3338,10 @@ gimplify_call_expr (tree *expr_p, gimple_seq *pre_p, bool want_value)
break;
}
+ case BUILT_IN_EH_RETURN:
+ cfun->calls_eh_return = true;
+ break;
+
default:
;
}
@@ -5482,6 +5527,7 @@ is_gimple_stmt (tree t)
case OMP_SIMD:
case OMP_DISTRIBUTE:
case OACC_LOOP:
+ case OMP_SCAN:
case OMP_SECTIONS:
case OMP_SECTION:
case OMP_SINGLE:
@@ -6177,7 +6223,7 @@ gimplify_asm_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p)
fb_lvalue | fb_mayfail);
if (tret == GS_ERROR)
{
- error ("invalid lvalue in asm output %d", i);
+ error ("invalid lvalue in %<asm%> output %d", i);
ret = tret;
}
@@ -6662,6 +6708,7 @@ gimplify_target_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p)
}
if (asan_poisoned_variables
&& DECL_ALIGN (temp) <= MAX_SUPPORTED_STACK_ALIGNMENT
+ && !TREE_STATIC (temp)
&& dbg_cnt (asan_use_after_scope)
&& !gimplify_omp_ctxp)
{
@@ -8046,7 +8093,7 @@ gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p,
struct gimplify_omp_ctx *ctx, *outer_ctx;
tree c;
hash_map<tree, tree> *struct_map_to_clause = NULL;
- tree *prev_list_p = NULL;
+ tree *prev_list_p = NULL, *orig_list_p = list_p;
int handled_depend_iterators = -1;
int nowait = -1;
@@ -8108,13 +8155,13 @@ gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p,
case OMP_DISTRIBUTE:
error_at (OMP_CLAUSE_LOCATION (c),
"conditional %<lastprivate%> clause on "
- "%<distribute%> construct");
+ "%qs construct", "distribute");
OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (c) = 0;
break;
case OMP_TASKLOOP:
error_at (OMP_CLAUSE_LOCATION (c),
"conditional %<lastprivate%> clause on "
- "%<taskloop%> construct");
+ "%qs construct", "taskloop");
OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (c) = 0;
break;
default:
@@ -8134,9 +8181,7 @@ gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p,
OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (c) = 0;
}
if (OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (c))
- sorry_at (OMP_CLAUSE_LOCATION (c),
- "%<conditional%> modifier on %<lastprivate%> clause "
- "not supported yet");
+ flags |= GOVD_LASTPRIVATE_CONDITIONAL;
if (outer_ctx
&& (outer_ctx->region_type == ORT_COMBINED_PARALLEL
|| ((outer_ctx->region_type & ORT_COMBINED_TEAMS)
@@ -8233,6 +8278,36 @@ gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p,
OMP_CLAUSE_REDUCTION_TASK (c) = 0;
}
}
+ if (OMP_CLAUSE_REDUCTION_INSCAN (c))
+ switch (code)
+ {
+ case OMP_SECTIONS:
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "%<inscan%> %<reduction%> clause on "
+ "%qs construct", "sections");
+ OMP_CLAUSE_REDUCTION_INSCAN (c) = 0;
+ break;
+ case OMP_PARALLEL:
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "%<inscan%> %<reduction%> clause on "
+ "%qs construct", "parallel");
+ OMP_CLAUSE_REDUCTION_INSCAN (c) = 0;
+ break;
+ case OMP_TEAMS:
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "%<inscan%> %<reduction%> clause on "
+ "%qs construct", "teams");
+ OMP_CLAUSE_REDUCTION_INSCAN (c) = 0;
+ break;
+ case OMP_TASKLOOP:
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "%<inscan%> %<reduction%> clause on "
+ "%qs construct", "taskloop");
+ OMP_CLAUSE_REDUCTION_INSCAN (c) = 0;
+ break;
+ default:
+ break;
+ }
/* FALLTHRU */
case OMP_CLAUSE_IN_REDUCTION:
case OMP_CLAUSE_TASK_REDUCTION:
@@ -9050,7 +9125,10 @@ gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p,
" or private in outer context", DECL_NAME (decl));
}
do_notice:
- if ((region_type & ORT_TASKLOOP) == ORT_TASKLOOP
+ if (((region_type & ORT_TASKLOOP) == ORT_TASKLOOP
+ || (region_type == ORT_WORKSHARE
+ && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
+ && OMP_CLAUSE_REDUCTION_INSCAN (c)))
&& outer_ctx
&& outer_ctx->region_type == ORT_COMBINED_PARALLEL
&& (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
@@ -9281,6 +9359,36 @@ gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p,
ctx->default_kind = OMP_CLAUSE_DEFAULT_KIND (c);
break;
+ case OMP_CLAUSE_INCLUSIVE:
+ case OMP_CLAUSE_EXCLUSIVE:
+ decl = OMP_CLAUSE_DECL (c);
+ {
+ splay_tree_node n = splay_tree_lookup (outer_ctx->variables,
+ (splay_tree_key) decl);
+ if (n == NULL || (n->value & GOVD_REDUCTION) == 0)
+ {
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "%qD specified in %qs clause but not in %<inscan%> "
+ "%<reduction%> clause on the containing construct",
+ decl, omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
+ remove = true;
+ }
+ else
+ {
+ n->value |= GOVD_REDUCTION_INSCAN;
+ if (outer_ctx->region_type == ORT_SIMD
+ && outer_ctx->outer_context
+ && outer_ctx->outer_context->region_type == ORT_WORKSHARE)
+ {
+ n = splay_tree_lookup (outer_ctx->outer_context->variables,
+ (splay_tree_key) decl);
+ if (n && (n->value & GOVD_REDUCTION) != 0)
+ n->value |= GOVD_REDUCTION_INSCAN;
+ }
+ }
+ }
+ break;
+
default:
gcc_unreachable ();
}
@@ -9296,6 +9404,7 @@ gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p,
list_p = &OMP_CLAUSE_CHAIN (c);
}
+ ctx->clauses = *orig_list_p;
gimplify_omp_ctxp = ctx;
if (struct_map_to_clause)
delete struct_map_to_clause;
@@ -9439,6 +9548,9 @@ gimplify_adjust_omp_clauses_1 (splay_tree_node n, void *data)
tree clause;
bool private_debug;
+ if (gimplify_omp_ctxp->region_type == ORT_COMBINED_PARALLEL
+ && (flags & GOVD_LASTPRIVATE_CONDITIONAL) != 0)
+ flags = GOVD_SHARED | GOVD_SEEN | GOVD_WRITTEN;
if (flags & (GOVD_EXPLICIT | GOVD_LOCAL))
return 0;
if ((flags & GOVD_SEEN) == 0)
@@ -9504,6 +9616,11 @@ gimplify_adjust_omp_clauses_1 (splay_tree_node n, void *data)
code = OMP_CLAUSE_LASTPRIVATE;
else if (flags & (GOVD_ALIGNED | GOVD_NONTEMPORAL))
return 0;
+ else if (flags & GOVD_CONDTEMP)
+ {
+ code = OMP_CLAUSE__CONDTEMP_;
+ gimple_add_tmp_var (decl);
+ }
else
gcc_unreachable ();
@@ -9665,7 +9782,9 @@ gimplify_adjust_omp_clauses (gimple_seq *pre_p, gimple_seq body, tree *list_p,
enum tree_code code)
{
struct gimplify_omp_ctx *ctx = gimplify_omp_ctxp;
+ tree *orig_list_p = list_p;
tree c, decl;
+ bool has_inscan_reductions = false;
if (body)
{
@@ -9681,6 +9800,34 @@ gimplify_adjust_omp_clauses (gimple_seq *pre_p, gimple_seq body, tree *list_p,
omp_find_stores_op, &wi);
}
}
+
+ if (ctx->region_type == ORT_WORKSHARE
+ && ctx->outer_context
+ && ctx->outer_context->region_type == ORT_COMBINED_PARALLEL)
+ {
+ for (c = ctx->outer_context->clauses; c; c = OMP_CLAUSE_CHAIN (c))
+ if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
+ && OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (c))
+ {
+ decl = OMP_CLAUSE_DECL (c);
+ splay_tree_node n
+ = splay_tree_lookup (ctx->outer_context->variables,
+ (splay_tree_key) decl);
+ gcc_checking_assert (!splay_tree_lookup (ctx->variables,
+ (splay_tree_key) decl));
+ omp_add_variable (ctx, decl, n->value);
+ tree c2 = copy_node (c);
+ OMP_CLAUSE_CHAIN (c2) = *list_p;
+ *list_p = c2;
+ if ((n->value & GOVD_FIRSTPRIVATE) == 0)
+ continue;
+ c2 = build_omp_clause (OMP_CLAUSE_LOCATION (c),
+ OMP_CLAUSE_FIRSTPRIVATE);
+ OMP_CLAUSE_DECL (c2) = decl;
+ OMP_CLAUSE_CHAIN (c2) = *list_p;
+ *list_p = c2;
+ }
+ }
while ((c = *list_p) != NULL)
{
splay_tree_node n;
@@ -9707,6 +9854,10 @@ gimplify_adjust_omp_clauses (gimple_seq *pre_p, gimple_seq body, tree *list_p,
decl = OMP_CLAUSE_DECL (c);
n = splay_tree_lookup (ctx->variables, (splay_tree_key) decl);
remove = !(n->value & GOVD_SEEN);
+ if ((n->value & GOVD_LASTPRIVATE_CONDITIONAL) != 0
+ && code == OMP_PARALLEL
+ && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
+ remove = true;
if (! remove)
{
bool shared = OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED;
@@ -9755,6 +9906,8 @@ gimplify_adjust_omp_clauses (gimple_seq *pre_p, gimple_seq body, tree *list_p,
&& DECL_P (decl)
&& omp_shared_to_firstprivate_optimizable_decl_p (decl))
omp_mark_stores (gimplify_omp_ctxp->outer_context, decl);
+ if (OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (c) && code == OMP_PARALLEL)
+ remove = true;
break;
case OMP_CLAUSE_ALIGNED:
@@ -9835,7 +9988,7 @@ gimplify_adjust_omp_clauses (gimple_seq *pre_p, gimple_seq body, tree *list_p,
{
warning_at (OMP_CLAUSE_LOCATION (c), 0,
"incompatible data clause with reduction "
- "on %qE; promoting to present_or_copy",
+ "on %qE; promoting to %<present_or_copy%>",
DECL_NAME (t));
OMP_CLAUSE_SET_MAP_KIND (c, GOMP_MAP_TOFROM);
}
@@ -9972,6 +10125,21 @@ gimplify_adjust_omp_clauses (gimple_seq *pre_p, gimple_seq body, tree *list_p,
break;
case OMP_CLAUSE_REDUCTION:
+ if (OMP_CLAUSE_REDUCTION_INSCAN (c))
+ {
+ decl = OMP_CLAUSE_DECL (c);
+ n = splay_tree_lookup (ctx->variables, (splay_tree_key) decl);
+ if ((n->value & GOVD_REDUCTION_INSCAN) == 0)
+ {
+ remove = true;
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "%qD specified in %<inscan%> %<reduction%> clause "
+ "but not in %<scan%> directive clause", decl);
+ break;
+ }
+ has_inscan_reductions = true;
+ }
+ /* FALLTHRU */
case OMP_CLAUSE_IN_REDUCTION:
case OMP_CLAUSE_TASK_REDUCTION:
decl = OMP_CLAUSE_DECL (c);
@@ -10053,6 +10221,8 @@ gimplify_adjust_omp_clauses (gimple_seq *pre_p, gimple_seq body, tree *list_p,
case OMP_CLAUSE_TILE:
case OMP_CLAUSE_IF_PRESENT:
case OMP_CLAUSE_FINALIZE:
+ case OMP_CLAUSE_INCLUSIVE:
+ case OMP_CLAUSE_EXCLUSIVE:
break;
default:
@@ -10071,6 +10241,18 @@ gimplify_adjust_omp_clauses (gimple_seq *pre_p, gimple_seq body, tree *list_p,
data.pre_p = pre_p;
splay_tree_foreach (ctx->variables, gimplify_adjust_omp_clauses_1, &data);
+ if (has_inscan_reductions)
+ for (c = *orig_list_p; c; c = OMP_CLAUSE_CHAIN (c))
+ if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
+ && !OMP_CLAUSE_LINEAR_NO_COPYIN (c))
+ {
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "%<inscan%> %<reduction%> clause used together with "
+ "%<linear%> clause for a variable other than loop "
+ "iterator");
+ break;
+ }
+
gimplify_omp_ctxp = ctx->outer_context;
delete_omp_context (ctx);
}
@@ -10765,7 +10947,22 @@ gimplify_omp_for (tree *expr_p, gimple_seq *pre_p)
1 + (TREE_VEC_LENGTH (OMP_FOR_INIT (for_stmt))
!= 1));
if (n != NULL && (n->value & GOVD_DATA_SHARE_CLASS) != 0)
- omp_notice_variable (gimplify_omp_ctxp, decl, true);
+ {
+ omp_notice_variable (gimplify_omp_ctxp, decl, true);
+ if (n->value & GOVD_LASTPRIVATE_CONDITIONAL)
+ for (tree c3 = omp_find_clause (OMP_FOR_CLAUSES (for_stmt),
+ OMP_CLAUSE_LASTPRIVATE);
+ c3; c3 = omp_find_clause (OMP_CLAUSE_CHAIN (c3),
+ OMP_CLAUSE_LASTPRIVATE))
+ if (OMP_CLAUSE_DECL (c3) == decl)
+ {
+ warning_at (OMP_CLAUSE_LOCATION (c3), 0,
+ "conditional %<lastprivate%> on loop "
+ "iterator %qD ignored", decl);
+ OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (c3) = 0;
+ n->value &= ~GOVD_LASTPRIVATE_CONDITIONAL;
+ }
+ }
else if (TREE_VEC_LENGTH (OMP_FOR_INIT (for_stmt)) == 1)
{
c = build_omp_clause (input_location, OMP_CLAUSE_LINEAR);
@@ -11000,7 +11197,24 @@ gimplify_omp_for (tree *expr_p, gimple_seq *pre_p)
}
}
else if (omp_is_private (gimplify_omp_ctxp, decl, 0))
- omp_notice_variable (gimplify_omp_ctxp, decl, true);
+ {
+ omp_notice_variable (gimplify_omp_ctxp, decl, true);
+ splay_tree_node n = splay_tree_lookup (gimplify_omp_ctxp->variables,
+ (splay_tree_key) decl);
+ if (n && (n->value & GOVD_LASTPRIVATE_CONDITIONAL))
+ for (tree c3 = omp_find_clause (OMP_FOR_CLAUSES (for_stmt),
+ OMP_CLAUSE_LASTPRIVATE);
+ c3; c3 = omp_find_clause (OMP_CLAUSE_CHAIN (c3),
+ OMP_CLAUSE_LASTPRIVATE))
+ if (OMP_CLAUSE_DECL (c3) == decl)
+ {
+ warning_at (OMP_CLAUSE_LOCATION (c3), 0,
+ "conditional %<lastprivate%> on loop "
+ "iterator %qD ignored", decl);
+ OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (c3) = 0;
+ n->value &= ~GOVD_LASTPRIVATE_CONDITIONAL;
+ }
+ }
else
omp_add_variable (gimplify_omp_ctxp, decl, GOVD_PRIVATE | GOVD_SEEN);
@@ -11434,6 +11648,58 @@ gimplify_omp_for (tree *expr_p, gimple_seq *pre_p)
}
else
gimplify_seq_add_stmt (pre_p, gfor);
+
+ if (TREE_CODE (orig_for_stmt) == OMP_FOR)
+ {
+ struct gimplify_omp_ctx *ctx = gimplify_omp_ctxp;
+ unsigned lastprivate_conditional = 0;
+ while (ctx
+ && (ctx->region_type == ORT_TARGET_DATA
+ || ctx->region_type == ORT_TASKGROUP))
+ ctx = ctx->outer_context;
+ if (ctx && (ctx->region_type & ORT_PARALLEL) != 0)
+ for (tree c = gimple_omp_for_clauses (gfor);
+ c; c = OMP_CLAUSE_CHAIN (c))
+ if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
+ && OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (c))
+ ++lastprivate_conditional;
+ if (lastprivate_conditional)
+ {
+ struct omp_for_data fd;
+ omp_extract_for_data (gfor, &fd, NULL);
+ tree type = build_array_type_nelts (unsigned_type_for (fd.iter_type),
+ lastprivate_conditional);
+ tree var = create_tmp_var_raw (type);
+ tree c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__CONDTEMP_);
+ OMP_CLAUSE_DECL (c) = var;
+ OMP_CLAUSE_CHAIN (c) = gimple_omp_for_clauses (gfor);
+ gimple_omp_for_set_clauses (gfor, c);
+ omp_add_variable (ctx, var, GOVD_CONDTEMP | GOVD_SEEN);
+ }
+ }
+ else if (TREE_CODE (orig_for_stmt) == OMP_SIMD)
+ {
+ unsigned lastprivate_conditional = 0;
+ for (tree c = gimple_omp_for_clauses (gfor); c; c = OMP_CLAUSE_CHAIN (c))
+ if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
+ && OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (c))
+ ++lastprivate_conditional;
+ if (lastprivate_conditional)
+ {
+ struct omp_for_data fd;
+ omp_extract_for_data (gfor, &fd, NULL);
+ tree type = unsigned_type_for (fd.iter_type);
+ while (lastprivate_conditional--)
+ {
+ tree c = build_omp_clause (UNKNOWN_LOCATION,
+ OMP_CLAUSE__CONDTEMP_);
+ OMP_CLAUSE_DECL (c) = create_tmp_var (type);
+ OMP_CLAUSE_CHAIN (c) = gimple_omp_for_clauses (gfor);
+ gimple_omp_for_set_clauses (gfor, c);
+ }
+ }
+ }
+
if (ret != GS_ALL_DONE)
return GS_ERROR;
*expr_p = NULL_TREE;
@@ -12988,6 +13254,7 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
case OMP_MASTER:
case OMP_ORDERED:
case OMP_CRITICAL:
+ case OMP_SCAN:
{
gimple_seq body = NULL;
gimple *g;
@@ -13014,6 +13281,14 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
OMP_CRITICAL_NAME (*expr_p),
OMP_CRITICAL_CLAUSES (*expr_p));
break;
+ case OMP_SCAN:
+ gimplify_scan_omp_clauses (&OMP_SCAN_CLAUSES (*expr_p),
+ pre_p, ORT_WORKSHARE, OMP_SCAN);
+ gimplify_adjust_omp_clauses (pre_p, body,
+ &OMP_SCAN_CLAUSES (*expr_p),
+ OMP_SCAN);
+ g = gimple_build_omp_scan (body, OMP_SCAN_CLAUSES (*expr_p));
+ break;
default:
gcc_unreachable ();
}
@@ -13378,6 +13653,7 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
&& code != OMP_TASKGROUP
&& code != OMP_ORDERED
&& code != OMP_PARALLEL
+ && code != OMP_SCAN
&& code != OMP_SECTIONS
&& code != OMP_SECTION
&& code != OMP_SINGLE);
diff --git a/gcc/ginclude/float.h b/gcc/ginclude/float.h
index 9ebae05..4767d7b 100644
--- a/gcc/ginclude/float.h
+++ b/gcc/ginclude/float.h
@@ -210,7 +210,8 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
#endif /* C99 */
-#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 201112L
+#if (defined (__STDC_VERSION__) && __STDC_VERSION__ >= 201112L) \
+ || (defined (__cplusplus) && __cplusplus >= 201703L)
/* Versions of DECIMAL_DIG for each floating-point type. */
#undef FLT_DECIMAL_DIG
#undef DBL_DECIMAL_DIG
diff --git a/gcc/go/ChangeLog b/gcc/go/ChangeLog
index 10c2b69..60d1187 100644
--- a/gcc/go/ChangeLog
+++ b/gcc/go/ChangeLog
@@ -1,3 +1,21 @@
+2019-07-02 Cherry Zhang <cherryyz@google.com>
+
+ * go-gcc.cc (Gcc_backend::Gcc_backend): Define __builtin_memset.
+
+2019-06-21 Cherry Zhang <cherryyz@google.com>
+
+ * go-gcc.cc (Gcc_backend::Gcc_backend): Define math/bits
+ builtins.
+
+2019-05-30 Jim Wilson <jimw@sifive.com>
+
+ * go-gcc.cc (Gcc_backend::Gcc_backend): Add BUILT_IN_ATOMIC_FETCH_AND_1
+ and BUILT_IN_ATOMIC_FETCH_OR_1.
+
+2019-05-16 Cherry Zhang <cherryyz@google.com>
+
+ * go-gcc.cc (Gcc_backend::Gcc_backend): Define atomic builtins.
+
2019-05-08 Cherry Zhang <cherryyz@google.com>
* go-gcc.cc (Gcc_backend::Gcc_backend): Define memmove builtin.
diff --git a/gcc/go/go-gcc.cc b/gcc/go/go-gcc.cc
index e0e4333..d9fc1a7 100644
--- a/gcc/go/go-gcc.cc
+++ b/gcc/go/go-gcc.cc
@@ -613,7 +613,16 @@ Gcc_backend::Gcc_backend()
NULL_TREE),
false, false);
- // Used by runtime/internal/sys.
+ // We use __builtin_memset for zeroing data.
+ this->define_builtin(BUILT_IN_MEMSET, "__builtin_memset", "memset",
+ build_function_type_list(void_type_node,
+ ptr_type_node,
+ integer_type_node,
+ size_type_node,
+ NULL_TREE),
+ false, false);
+
+ // Used by runtime/internal/sys and math/bits.
this->define_builtin(BUILT_IN_CTZ, "__builtin_ctz", "ctz",
build_function_type_list(integer_type_node,
unsigned_type_node,
@@ -624,6 +633,31 @@ Gcc_backend::Gcc_backend()
long_long_unsigned_type_node,
NULL_TREE),
true, false);
+ this->define_builtin(BUILT_IN_CLZ, "__builtin_clz", "clz",
+ build_function_type_list(integer_type_node,
+ unsigned_type_node,
+ NULL_TREE),
+ true, false);
+ this->define_builtin(BUILT_IN_CLZLL, "__builtin_clzll", "clzll",
+ build_function_type_list(integer_type_node,
+ long_long_unsigned_type_node,
+ NULL_TREE),
+ true, false);
+ this->define_builtin(BUILT_IN_POPCOUNT, "__builtin_popcount", "popcount",
+ build_function_type_list(integer_type_node,
+ unsigned_type_node,
+ NULL_TREE),
+ true, false);
+ this->define_builtin(BUILT_IN_POPCOUNTLL, "__builtin_popcountll", "popcountll",
+ build_function_type_list(integer_type_node,
+ long_long_unsigned_type_node,
+ NULL_TREE),
+ true, false);
+ this->define_builtin(BUILT_IN_BSWAP16, "__builtin_bswap16", "bswap16",
+ build_function_type_list(uint16_type_node,
+ uint16_type_node,
+ NULL_TREE),
+ true, false);
this->define_builtin(BUILT_IN_BSWAP32, "__builtin_bswap32", "bswap32",
build_function_type_list(uint32_type_node,
uint32_type_node,
@@ -776,6 +810,113 @@ Gcc_backend::Gcc_backend()
this->define_builtin(BUILT_IN_UNREACHABLE, "__builtin_unreachable", NULL,
build_function_type(void_type_node, void_list_node),
true, true);
+
+ // We provide some atomic functions.
+ t = build_function_type_list(uint32_type_node,
+ ptr_type_node,
+ integer_type_node,
+ NULL_TREE);
+ this->define_builtin(BUILT_IN_ATOMIC_LOAD_4, "__atomic_load_4", NULL,
+ t, false, false);
+
+ t = build_function_type_list(uint64_type_node,
+ ptr_type_node,
+ integer_type_node,
+ NULL_TREE);
+ this->define_builtin(BUILT_IN_ATOMIC_LOAD_8, "__atomic_load_8", NULL,
+ t, false, false);
+
+ t = build_function_type_list(void_type_node,
+ ptr_type_node,
+ uint32_type_node,
+ integer_type_node,
+ NULL_TREE);
+ this->define_builtin(BUILT_IN_ATOMIC_STORE_4, "__atomic_store_4", NULL,
+ t, false, false);
+
+ t = build_function_type_list(void_type_node,
+ ptr_type_node,
+ uint64_type_node,
+ integer_type_node,
+ NULL_TREE);
+ this->define_builtin(BUILT_IN_ATOMIC_STORE_8, "__atomic_store_8", NULL,
+ t, false, false);
+
+ t = build_function_type_list(uint32_type_node,
+ ptr_type_node,
+ uint32_type_node,
+ integer_type_node,
+ NULL_TREE);
+ this->define_builtin(BUILT_IN_ATOMIC_EXCHANGE_4, "__atomic_exchange_4", NULL,
+ t, false, false);
+
+ t = build_function_type_list(uint64_type_node,
+ ptr_type_node,
+ uint64_type_node,
+ integer_type_node,
+ NULL_TREE);
+ this->define_builtin(BUILT_IN_ATOMIC_EXCHANGE_8, "__atomic_exchange_8", NULL,
+ t, false, false);
+
+ t = build_function_type_list(boolean_type_node,
+ ptr_type_node,
+ ptr_type_node,
+ uint32_type_node,
+ boolean_type_node,
+ integer_type_node,
+ integer_type_node,
+ NULL_TREE);
+ this->define_builtin(BUILT_IN_ATOMIC_COMPARE_EXCHANGE_4,
+ "__atomic_compare_exchange_4", NULL,
+ t, false, false);
+
+ t = build_function_type_list(boolean_type_node,
+ ptr_type_node,
+ ptr_type_node,
+ uint64_type_node,
+ boolean_type_node,
+ integer_type_node,
+ integer_type_node,
+ NULL_TREE);
+ this->define_builtin(BUILT_IN_ATOMIC_COMPARE_EXCHANGE_8,
+ "__atomic_compare_exchange_8", NULL,
+ t, false, false);
+
+ t = build_function_type_list(uint32_type_node,
+ ptr_type_node,
+ uint32_type_node,
+ integer_type_node,
+ NULL_TREE);
+ this->define_builtin(BUILT_IN_ATOMIC_ADD_FETCH_4, "__atomic_add_fetch_4", NULL,
+ t, false, false);
+
+ t = build_function_type_list(uint64_type_node,
+ ptr_type_node,
+ uint64_type_node,
+ integer_type_node,
+ NULL_TREE);
+ this->define_builtin(BUILT_IN_ATOMIC_ADD_FETCH_8, "__atomic_add_fetch_8", NULL,
+ t, false, false);
+
+ t = build_function_type_list(unsigned_char_type_node,
+ ptr_type_node,
+ unsigned_char_type_node,
+ integer_type_node,
+ NULL_TREE);
+ this->define_builtin(BUILT_IN_ATOMIC_AND_FETCH_1, "__atomic_and_fetch_1", NULL,
+ t, false, false);
+ this->define_builtin(BUILT_IN_ATOMIC_FETCH_AND_1, "__atomic_fetch_and_1", NULL,
+ t, false, false);
+
+ t = build_function_type_list(unsigned_char_type_node,
+ ptr_type_node,
+ unsigned_char_type_node,
+ integer_type_node,
+ NULL_TREE);
+ this->define_builtin(BUILT_IN_ATOMIC_OR_FETCH_1, "__atomic_or_fetch_1", NULL,
+ t, false, false);
+ this->define_builtin(BUILT_IN_ATOMIC_FETCH_OR_1, "__atomic_fetch_or_1", NULL,
+ t, false, false);
}
// Get an unnamed integer type.
diff --git a/gcc/go/gofrontend/MERGE b/gcc/go/gofrontend/MERGE
index f6f28a3..7ca79c8 100644
--- a/gcc/go/gofrontend/MERGE
+++ b/gcc/go/gofrontend/MERGE
@@ -1,4 +1,4 @@
-9c8581187b1c1a30036263728370f31cb846a274
+bf66d40bc7adb438dcfac85d73bfa7b17217eed9
The first line of this file holds the git revision number of the last
merge done from the gofrontend repository.
diff --git a/gcc/go/gofrontend/ast-dump.cc b/gcc/go/gofrontend/ast-dump.cc
index 94066ca..b20f7e4 100644
--- a/gcc/go/gofrontend/ast-dump.cc
+++ b/gcc/go/gofrontend/ast-dump.cc
@@ -200,7 +200,8 @@ Ast_dump_context::dump(Gogo* gogo, const char* basename)
if (out.fail())
{
go_error_at(Linemap::unknown_location(),
- "cannot open %s:%m, -fgo-dump-ast ignored", dumpname.c_str());
+ "cannot open %s:%m; %<-fgo-dump-ast%> ignored",
+ dumpname.c_str());
return;
}
diff --git a/gcc/go/gofrontend/escape.cc b/gcc/go/gofrontend/escape.cc
index e1c9809..4cfb480 100644
--- a/gcc/go/gofrontend/escape.cc
+++ b/gcc/go/gofrontend/escape.cc
@@ -964,9 +964,9 @@ Gogo::analyze_escape()
{
done = false;
if (this->debug_escape_level() > 2)
- go_inform((*n)->location(), "Reflooding %s %s",
- debug_function_name((*n)->state(context, NULL)->fn).c_str(),
- (*n)->ast_format(this).c_str());
+ go_debug((*n)->location(), "Reflooding %s %s",
+ debug_function_name((*n)->state(context, NULL)->fn).c_str(),
+ (*n)->ast_format(this).c_str());
escapes[*n] = (*n)->encoding();
this->propagate_escape(context, *n);
}
@@ -990,9 +990,9 @@ Gogo::analyze_escape()
{
Node::Escape_state* state = (*n)->state(context, NULL);
if ((*n)->encoding() == Node::ESCAPE_NONE)
- go_inform((*n)->location(), "%s %s does not escape",
- strip_packed_prefix(this, debug_function_name(state->fn)).c_str(),
- (*n)->ast_format(this).c_str());
+ go_debug((*n)->location(), "%s %s does not escape",
+ strip_packed_prefix(this, debug_function_name(state->fn)).c_str(),
+ (*n)->ast_format(this).c_str());
}
}
delete context;
@@ -1333,9 +1333,9 @@ Escape_analysis_assign::statement(Block*, size_t*, Statement* s)
{
Node* n = Node::make_node(s);
std::string fn_name = this->context_->current_function_name();
- go_inform(s->location(), "[%d] %s esc: %s",
- this->context_->loop_depth(), fn_name.c_str(),
- n->ast_format(gogo).c_str());
+ go_debug(s->location(), "[%d] %s esc: %s",
+ this->context_->loop_depth(), fn_name.c_str(),
+ n->ast_format(gogo).c_str());
}
switch (s->classification())
@@ -1495,9 +1495,9 @@ move_to_heap(Gogo* gogo, Expression *expr)
{
Node* n = Node::make_node(expr);
if (gogo->debug_escape_level() != 0)
- go_inform(n->definition_location(),
- "moved to heap: %s",
- n->ast_format(gogo).c_str());
+ go_debug(n->definition_location(),
+ "moved to heap: %s",
+ n->ast_format(gogo).c_str());
if (gogo->compiling_runtime() && gogo->package_name() == "runtime")
go_error_at(expr->location(),
"%s escapes to heap, not allowed in runtime",
@@ -1519,8 +1519,8 @@ Escape_analysis_assign::expression(Expression** pexpr)
&& n->is_big(this->context_))
{
if (debug_level > 1)
- go_inform((*pexpr)->location(), "%s too large for stack",
- n->ast_format(gogo).c_str());
+ go_debug((*pexpr)->location(), "%s too large for stack",
+ n->ast_format(gogo).c_str());
move_to_heap(gogo, *pexpr);
n->set_encoding(Node::ESCAPE_HEAP);
(*pexpr)->address_taken(true);
@@ -1534,9 +1534,9 @@ Escape_analysis_assign::expression(Expression** pexpr)
{
Node* n = Node::make_node(*pexpr);
std::string fn_name = this->context_->current_function_name();
- go_inform((*pexpr)->location(), "[%d] %s esc: %s",
- this->context_->loop_depth(), fn_name.c_str(),
- n->ast_format(gogo).c_str());
+ go_debug((*pexpr)->location(), "[%d] %s esc: %s",
+ this->context_->loop_depth(), fn_name.c_str(),
+ n->ast_format(gogo).c_str());
}
switch ((*pexpr)->classification())
@@ -1566,8 +1566,8 @@ Escape_analysis_assign::expression(Expression** pexpr)
Node* appended = Node::make_node(call->args()->back());
this->assign_deref(this->context_->sink(), appended);
if (debug_level > 2)
- go_inform((*pexpr)->location(),
- "special treatment of append(slice1, slice2...)");
+ go_debug((*pexpr)->location(),
+ "special treatment of append(slice1, slice2...)");
}
else
{
@@ -1622,6 +1622,16 @@ Escape_analysis_assign::expression(Expression** pexpr)
}
break;
+ case Runtime::MAPASSIGN_FAST32PTR:
+ case Runtime::MAPASSIGN_FAST64PTR:
+ case Runtime::MAPASSIGN_FASTSTR:
+ {
+ // Map key escapes. The last argument is the key.
+ Node* key_node = Node::make_node(call->args()->back());
+ this->assign(this->context_->sink(), key_node);
+ }
+ break;
+
case Runtime::IFACEE2T2:
case Runtime::IFACEI2T2:
{
@@ -1950,9 +1960,9 @@ Escape_analysis_assign::call(Call_expression* call)
++p)
{
if (debug_level > 2)
- go_inform(call->location(),
- "esccall:: indirect call <- %s, untracked",
- (*p)->ast_format(gogo).c_str());
+ go_debug(call->location(),
+ "esccall:: indirect call <- %s, untracked",
+ (*p)->ast_format(gogo).c_str());
this->assign(this->context_->sink(), *p);
}
@@ -1977,8 +1987,8 @@ Escape_analysis_assign::call(Call_expression* call)
&& !fntype->is_tagged())
{
if (debug_level > 2)
- go_inform(call->location(), "esccall:: %s in recursive group",
- call_node->ast_format(gogo).c_str());
+ go_debug(call->location(), "esccall:: %s in recursive group",
+ call_node->ast_format(gogo).c_str());
Function* f = fn->named_object()->func_value();
const Bindings* callee_bindings = f->block()->bindings();
@@ -2049,8 +2059,8 @@ Escape_analysis_assign::call(Call_expression* call)
for (; p != arg_nodes.end(); ++p)
{
if (debug_level > 2)
- go_inform(call->location(), "esccall:: ... <- %s, untracked",
- (*p)->ast_format(gogo).c_str());
+ go_debug(call->location(), "esccall:: ... <- %s, untracked",
+ (*p)->ast_format(gogo).c_str());
this->assign(this->context_->sink(), *p);
}
}
@@ -2059,8 +2069,8 @@ Escape_analysis_assign::call(Call_expression* call)
}
if (debug_level > 2)
- go_inform(call->location(), "esccall:: %s not recursive",
- call_node->ast_format(gogo).c_str());
+ go_debug(call->location(), "esccall:: %s not recursive",
+ call_node->ast_format(gogo).c_str());
Node::Escape_state* call_state = call_node->state(this->context_, NULL);
if (!call_state->retvals.empty())
@@ -2136,8 +2146,8 @@ Escape_analysis_assign::call(Call_expression* call)
for (; p != arg_nodes.end(); ++p)
{
if (debug_level > 2)
- go_inform(call->location(), "esccall:: ... <- %s, untracked",
- (*p)->ast_format(gogo).c_str());
+ go_debug(call->location(), "esccall:: ... <- %s, untracked",
+ (*p)->ast_format(gogo).c_str());
this->assign(this->context_->sink(), *p);
}
}
@@ -2155,13 +2165,13 @@ Escape_analysis_assign::assign(Node* dst, Node* src)
Gogo* gogo = this->context_->gogo();
int debug_level = gogo->debug_escape_level();
if (debug_level > 1)
- go_inform(dst->location(), "[%d] %s escassign: %s(%s)[%s] = %s(%s)[%s]",
- this->context_->loop_depth(),
- strip_packed_prefix(gogo, this->context_->current_function_name()).c_str(),
- dst->ast_format(gogo).c_str(), dst->details().c_str(),
- dst->op_format().c_str(),
- src->ast_format(gogo).c_str(), src->details().c_str(),
- src->op_format().c_str());
+ go_debug(dst->location(), "[%d] %s escassign: %s(%s)[%s] = %s(%s)[%s]",
+ this->context_->loop_depth(),
+ strip_packed_prefix(gogo, this->context_->current_function_name()).c_str(),
+ dst->ast_format(gogo).c_str(), dst->details().c_str(),
+ dst->op_format().c_str(),
+ src->ast_format(gogo).c_str(), src->details().c_str(),
+ src->op_format().c_str());
if (dst->is_indirect())
// Lose track of the dereference.
@@ -2407,9 +2417,11 @@ Escape_analysis_assign::assign(Node* dst, Node* src)
Type* tt = tce->type();
if ((ft->is_string_type() && tt->is_slice_type())
|| (ft->is_slice_type() && tt->is_string_type())
- || (ft->integer_type() != NULL && tt->is_string_type()))
+ || (ft->integer_type() != NULL && tt->is_string_type())
+ || tt->interface_type() != NULL)
{
- // string([]byte), string([]rune), []byte(string), []rune(string), string(rune)
+ // string([]byte), string([]rune), []byte(string), []rune(string), string(rune),
+ // interface(T)
this->flows(dst, src);
break;
}
@@ -2625,9 +2637,9 @@ Escape_analysis_assign::assign_from_note(std::string* note,
}
if (this->context_->gogo()->debug_escape_level() > 2)
- go_inform(src->location(), "assignfromtag:: src=%s em=%s",
- src->ast_format(context_->gogo()).c_str(),
- Escape_note::make_tag(enc).c_str());
+ go_debug(src->location(), "assignfromtag:: src=%s em=%s",
+ src->ast_format(context_->gogo()).c_str(),
+ Escape_note::make_tag(enc).c_str());
if (enc == Node::ESCAPE_UNKNOWN)
{
@@ -2695,8 +2707,8 @@ Escape_analysis_assign::flows(Node* dst, Node* src)
Gogo* gogo = this->context_->gogo();
if (gogo->debug_escape_level() > 2)
- go_inform(Linemap::unknown_location(), "flows:: %s <- %s",
- dst->ast_format(gogo).c_str(), src->ast_format(gogo).c_str());
+ go_debug(Linemap::unknown_location(), "flows:: %s <- %s",
+ dst->ast_format(gogo).c_str(), src->ast_format(gogo).c_str());
if (dst_state->flows.empty())
this->context_->add_dst(dst);
@@ -2761,15 +2773,8 @@ Gogo::assign_connectivity(Escape_context* context, Named_object* fn)
if (!p->type()->has_pointer())
continue;
- // External function? Parameters must escape unless //go:noescape is set.
- // TODO(cmang): Implement //go:noescape directive.
- if (fn->package() != NULL)
- param_node->set_encoding(Node::ESCAPE_HEAP);
- else
- {
- param_node->set_encoding(Node::ESCAPE_NONE);
- context->track(param_node);
- }
+ param_node->set_encoding(Node::ESCAPE_NONE);
+ context->track(param_node);
}
Escape_analysis_loop el;
@@ -2859,18 +2864,18 @@ Escape_analysis_flood::flood(Level level, Node* dst, Node* src,
Gogo* gogo = this->context_->gogo();
int debug_level = gogo->debug_escape_level();
if (debug_level > 1)
- go_inform(Linemap::unknown_location(),
- "escwalk: level:{%d %d} depth:%d "
- "op=%s %s(%s) "
- "scope:%s[%d] "
- "extraloopdepth=%d",
- level.value(), level.suffix_value(), this->context_->pdepth(),
- src->op_format().c_str(),
- src->ast_format(gogo).c_str(),
- src->details().c_str(),
- debug_function_name(src_state->fn).c_str(),
- src_state->loop_depth,
- extra_loop_depth);
+ go_debug(Linemap::unknown_location(),
+ "escwalk: level:{%d %d} depth:%d "
+ "op=%s %s(%s) "
+ "scope:%s[%d] "
+ "extraloopdepth=%d",
+ level.value(), level.suffix_value(), this->context_->pdepth(),
+ src->op_format().c_str(),
+ src->ast_format(gogo).c_str(),
+ src->details().c_str(),
+ debug_function_name(src_state->fn).c_str(),
+ src_state->loop_depth,
+ extra_loop_depth);
this->context_->increase_pdepth();
@@ -2906,17 +2911,17 @@ Escape_analysis_flood::flood(Level level, Node* dst, Node* src,
if (debug_level != 0)
{
if (debug_level == 1)
- go_inform(src->definition_location(),
- "leaking param: %s to result %s level=%d",
- src->ast_format(gogo).c_str(),
- dst->ast_format(gogo).c_str(),
- level.value());
+ go_debug(src->definition_location(),
+ "leaking param: %s to result %s level=%d",
+ src->ast_format(gogo).c_str(),
+ dst->ast_format(gogo).c_str(),
+ level.value());
else
- go_inform(src->definition_location(),
- "leaking param: %s to result %s level={%d %d}",
- src->ast_format(gogo).c_str(),
- dst->ast_format(gogo).c_str(),
- level.value(), level.suffix_value());
+ go_debug(src->definition_location(),
+ "leaking param: %s to result %s level={%d %d}",
+ src->ast_format(gogo).c_str(),
+ dst->ast_format(gogo).c_str(),
+ level.value(), level.suffix_value());
}
if ((src->encoding() & ESCAPE_MASK) != Node::ESCAPE_RETURN)
@@ -2954,8 +2959,8 @@ Escape_analysis_flood::flood(Level level, Node* dst, Node* src,
Node::ESCAPE_NONE);
src->set_encoding(enc);
if (debug_level != 0)
- go_inform(src->definition_location(), "mark escaped content: %s",
- src->ast_format(gogo).c_str());
+ go_debug(src->definition_location(), "mark escaped content: %s",
+ src->ast_format(gogo).c_str());
}
// A src object leaks if its value or address is assigned to a dst object
@@ -2979,14 +2984,14 @@ Escape_analysis_flood::flood(Level level, Node* dst, Node* src,
Node::ESCAPE_NONE);
src->set_encoding(enc);
if (debug_level != 0 && osrcesc != src->encoding())
- go_inform(src->definition_location(), "leaking param content: %s",
- src->ast_format(gogo).c_str());
+ go_debug(src->definition_location(), "leaking param content: %s",
+ src->ast_format(gogo).c_str());
}
else
{
if (debug_level != 0)
- go_inform(src->definition_location(), "leaking param: %s",
- src->ast_format(gogo).c_str());
+ go_debug(src->definition_location(), "leaking param: %s",
+ src->ast_format(gogo).c_str());
src->set_encoding(Node::ESCAPE_HEAP);
}
}
@@ -2996,8 +3001,8 @@ Escape_analysis_flood::flood(Level level, Node* dst, Node* src,
if (e->enclosed_var_expression() != NULL)
{
if (src_leaks && debug_level != 0)
- go_inform(src->location(), "leaking closure reference %s",
- src->ast_format(gogo).c_str());
+ go_debug(src->location(), "leaking closure reference %s",
+ src->ast_format(gogo).c_str());
Node* enclosed_node =
Node::make_node(e->enclosed_var_expression()->variable());
@@ -3025,15 +3030,15 @@ Escape_analysis_flood::flood(Level level, Node* dst, Node* src,
{
move_to_heap(gogo, underlying);
if (debug_level > 1)
- go_inform(src->location(),
- "%s escapes to heap, level={%d %d}, "
- "dst.eld=%d, src.eld=%d",
- src->ast_format(gogo).c_str(), level.value(),
- level.suffix_value(), dst_state->loop_depth,
- mod_loop_depth);
+ go_debug(src->location(),
+ "%s escapes to heap, level={%d %d}, "
+ "dst.eld=%d, src.eld=%d",
+ src->ast_format(gogo).c_str(), level.value(),
+ level.suffix_value(), dst_state->loop_depth,
+ mod_loop_depth);
else if (debug_level > 0)
- go_inform(src->location(), "%s escapes to heap",
- src->ast_format(gogo).c_str());
+ go_debug(src->location(), "%s escapes to heap",
+ src->ast_format(gogo).c_str());
}
this->flood(level.decrease(), dst,
@@ -3063,8 +3068,8 @@ Escape_analysis_flood::flood(Level level, Node* dst, Node* src,
{
src->set_encoding(Node::ESCAPE_HEAP);
if (debug_level != 0 && osrcesc != src->encoding())
- go_inform(src->location(), "%s escapes to heap",
- src->ast_format(gogo).c_str());
+ go_debug(src->location(), "%s escapes to heap",
+ src->ast_format(gogo).c_str());
extra_loop_depth = mod_loop_depth;
}
}
@@ -3095,8 +3100,8 @@ Escape_analysis_flood::flood(Level level, Node* dst, Node* src,
{
src->set_encoding(Node::ESCAPE_HEAP);
if (debug_level != 0 && osrcesc != src->encoding())
- go_inform(src->location(), "%s escapes to heap",
- src->ast_format(gogo).c_str());
+ go_debug(src->location(), "%s escapes to heap",
+ src->ast_format(gogo).c_str());
extra_loop_depth = mod_loop_depth;
}
break;
@@ -3114,11 +3119,11 @@ Escape_analysis_flood::flood(Level level, Node* dst, Node* src,
// This can only happen with functions returning a single result.
go_assert(src_state->retvals.size() == 1);
if (debug_level > 2)
- go_inform(src->location(), "[%d] dst %s escwalk replace src: %s with %s",
- this->context_->loop_depth(),
- dst->ast_format(gogo).c_str(),
- src->ast_format(gogo).c_str(),
- src_state->retvals[0]->ast_format(gogo).c_str());
+ go_debug(src->location(), "[%d] dst %s escwalk replace src: %s with %s",
+ this->context_->loop_depth(),
+ dst->ast_format(gogo).c_str(),
+ src->ast_format(gogo).c_str(),
+ src_state->retvals[0]->ast_format(gogo).c_str());
src = src_state->retvals[0];
src_state = src->state(this->context_, NULL);
}
@@ -3128,8 +3133,8 @@ Escape_analysis_flood::flood(Level level, Node* dst, Node* src,
// Calls to Runtime::NEW get lowered into an allocation expression.
src->set_encoding(Node::ESCAPE_HEAP);
if (debug_level != 0 && osrcesc != src->encoding())
- go_inform(src->location(), "%s escapes to heap",
- src->ast_format(gogo).c_str());
+ go_debug(src->location(), "%s escapes to heap",
+ src->ast_format(gogo).c_str());
extra_loop_depth = mod_loop_depth;
}
else if ((e->map_literal() != NULL
@@ -3140,8 +3145,8 @@ Escape_analysis_flood::flood(Level level, Node* dst, Node* src,
{
src->set_encoding(Node::ESCAPE_HEAP);
if (debug_level != 0 && osrcesc != src->encoding())
- go_inform(src->location(), "%s escapes to heap",
- src->ast_format(gogo).c_str());
+ go_debug(src->location(), "%s escapes to heap",
+ src->ast_format(gogo).c_str());
extra_loop_depth = mod_loop_depth;
}
else if (e->conversion_expression() != NULL && src_leaks)
@@ -3151,14 +3156,24 @@ Escape_analysis_flood::flood(Level level, Node* dst, Node* src,
Type* tt = tce->type();
if ((ft->is_string_type() && tt->is_slice_type())
|| (ft->is_slice_type() && tt->is_string_type())
- || (ft->integer_type() != NULL && tt->is_string_type()))
+ || (ft->integer_type() != NULL && tt->is_string_type())
+ || tt->interface_type() != NULL)
{
- // string([]byte), string([]rune), []byte(string), []rune(string), string(rune)
+ // string([]byte), string([]rune), []byte(string), []rune(string), string(rune),
+ // interface(T)
src->set_encoding(Node::ESCAPE_HEAP);
if (debug_level != 0 && osrcesc != src->encoding())
- go_inform(src->location(), "%s escapes to heap",
- src->ast_format(gogo).c_str());
+ go_debug(src->location(), "%s escapes to heap",
+ src->ast_format(gogo).c_str());
extra_loop_depth = mod_loop_depth;
+ if (tt->interface_type() != NULL
+ && ft->has_pointer()
+ && !ft->is_direct_iface_type())
+ // We're converting from a non-direct interface type.
+ // The interface will hold a heap copy of the data
+ // Flow the data to heap. See issue 29353.
+ this->flood(level, this->context_->sink(),
+ Node::make_node(tce->expr()), -1);
}
}
else if (e->array_index_expression() != NULL
@@ -3261,10 +3276,10 @@ Gogo::propagate_escape(Escape_context* context, Node* dst)
Node::Escape_state* state = dst->state(context, NULL);
Gogo* gogo = context->gogo();
if (gogo->debug_escape_level() > 1)
- go_inform(Linemap::unknown_location(), "escflood:%d: dst %s scope:%s[%d]",
- context->flood_id(), dst->ast_format(gogo).c_str(),
- debug_function_name(state->fn).c_str(),
- state->loop_depth);
+ go_debug(Linemap::unknown_location(), "escflood:%d: dst %s scope:%s[%d]",
+ context->flood_id(), dst->ast_format(gogo).c_str(),
+ debug_function_name(state->fn).c_str(),
+ state->loop_depth);
Escape_analysis_flood eaf(context);
for (std::set<Node*>::const_iterator p = state->flows.begin();
@@ -3297,9 +3312,6 @@ Escape_analysis_tag::tag(Named_object* fn)
{
// External functions are assumed unsafe
// unless //go:noescape is given before the declaration.
- if (fn->package() != NULL)
- return;
-
if (fn->is_function_declaration())
{
Function_declaration* fdcl = fn->func_declaration_value();
diff --git a/gcc/go/gofrontend/export.cc b/gcc/go/gofrontend/export.cc
index 066455a..cb778a0 100644
--- a/gcc/go/gofrontend/export.cc
+++ b/gcc/go/gofrontend/export.cc
@@ -6,14 +6,14 @@
#include "go-system.h"
-#include "go-sha1.h"
#include "go-c.h"
-
+#include "go-diagnostics.h"
+#include "go-sha1.h"
#include "gogo.h"
#include "types.h"
+#include "expressions.h"
#include "statements.h"
#include "export.h"
-
#include "go-linemap.h"
#include "backend.h"
@@ -41,14 +41,6 @@ const char Export::v2_magic[Export::magic_len] =
const int Export::checksum_len;
-// Constructor.
-
-Export::Export(Stream* stream)
- : stream_(stream), type_index_(1), packages_()
-{
- go_assert(Export::checksum_len == Go_sha1_helper::checksum_len);
-}
-
// Type hash table operations, treating aliases as distinct.
class Type_hash_alias_identical
@@ -80,24 +72,345 @@ class Type_alias_identical
}
};
-// Mapping from Type objects to a constant index. This would be nicer
-// as a field in Export, but then export.h would have to #include
-// types.h.
-
+// Mapping from Type objects to a constant index.
typedef Unordered_map_hash(const Type*, int, Type_hash_alias_identical,
- Type_alias_identical) Type_refs;
+ Type_alias_identical) Type_refs;
-static Type_refs type_refs;
+// Implementation object for class Export. Hidden implementation avoids
+// having to #include types.h in export.h, or use a static map.
-// A functor to sort Named_object pointers by name.
+struct Export_impl {
+ Type_refs type_refs;
+};
-struct Sort_bindings
+// Constructor.
+
+Export::Export(Stream* stream)
+ : stream_(stream), type_index_(1), packages_(), impl_(new Export_impl)
{
- bool
- operator()(const Named_object* n1, const Named_object* n2) const
- { return n1->name() < n2->name(); }
+ go_assert(Export::checksum_len == Go_sha1_helper::checksum_len);
+}
+
+// Destructor.
+
+Export::~Export()
+{
+ delete this->impl_;
+}
+
+// A traversal class to collect functions and global variables
+// referenced by inlined functions, and also to gather up
+// referenced types that need to be included in the exports.
+
+class Collect_export_references : public Traverse
+{
+ public:
+ Collect_export_references(Export* exp,
+ Unordered_set(Named_object*)* exports,
+ Unordered_set(const Package*)* imports)
+ : Traverse(traverse_expressions
+ | traverse_types),
+ exp_(exp), exports_(exports), imports_(imports),
+ inline_fcn_worklist_(NULL)
+ { }
+
+ // Initial entry point; performs a walk to expand the exports set.
+ void
+ expand_exports(std::vector<Named_object*>* inlinable_functions);
+
+ // Second entry point (called after the method above), to find
+ // all types referenced by exports.
+ void
+ prepare_types();
+
+ protected:
+ // Override of parent class method.
+ int
+ expression(Expression**);
+
+ // Override of parent class method.
+ int
+ type(Type* type);
+
+ // Traverse the components of a function type.
+ void
+ traverse_function_type(Function_type*);
+
+ // Traverse the methods of a named type, and register its package.
+ void
+ traverse_named_type(Named_type*);
+
+ private:
+ // The exporter.
+ Export* exp_;
+ // The set of named objects to export.
+ Unordered_set(Named_object*)* exports_;
+ // Set containing all directly and indirectly imported packages.
+ Unordered_set(const Package*)* imports_;
+ // Functions we've already traversed and don't need to visit again.
+ Unordered_set(Named_object*) checked_functions_;
+ // Worklist of functions we are exporting with inline bodies that need
+ // to be checked.
+ std::vector<Named_object*>* inline_fcn_worklist_;
};
+void
+Collect_export_references::expand_exports(std::vector<Named_object*>* fcns)
+{
+ this->inline_fcn_worklist_ = fcns;
+ while (!this->inline_fcn_worklist_->empty())
+ {
+ Named_object* no = this->inline_fcn_worklist_->back();
+ this->inline_fcn_worklist_->pop_back();
+ std::pair<Unordered_set(Named_object*)::iterator, bool> ins =
+ this->checked_functions_.insert(no);
+ if (ins.second)
+ {
+ // This traversal may add new objects to this->exports_ and new
+ // functions to this->inline_fcn_worklist_.
+ no->func_value()->block()->traverse(this);
+ }
+ }
+ this->inline_fcn_worklist_ = NULL;
+}
+
+int
+Collect_export_references::expression(Expression** pexpr)
+{
+ const Expression* expr = *pexpr;
+
+ const Var_expression* ve = expr->var_expression();
+ if (ve != NULL)
+ {
+ Named_object* no = ve->named_object();
+ if (no->is_variable() && no->var_value()->is_global())
+ {
+ const Package* var_package = no->package();
+ if (var_package != NULL)
+ this->imports_->insert(var_package);
+
+ this->exports_->insert(no);
+ no->var_value()->set_is_referenced_by_inline();
+ }
+ return TRAVERSE_CONTINUE;
+ }
+
+ const Func_expression* fe = expr->func_expression();
+ if (fe != NULL)
+ {
+ Named_object* no = fe->named_object();
+
+ const Package* func_package = fe->named_object()->package();
+ if (func_package != NULL)
+ this->imports_->insert(func_package);
+
+ if (no->is_function_declaration()
+ && no->func_declaration_value()->type()->is_builtin())
+ return TRAVERSE_CONTINUE;
+
+ if (this->inline_fcn_worklist_ != NULL)
+ {
+ std::pair<Unordered_set(Named_object*)::iterator, bool> ins =
+ this->exports_->insert(no);
+
+ if (no->is_function())
+ no->func_value()->set_is_referenced_by_inline();
+
+ // If ins.second is false then this object was already in
+ // exports_, in which case it was already added to
+ // check_inline_refs_ the first time we added it to exports_, so
+ // we don't need to add it again.
+ if (ins.second
+ && no->is_function()
+ && no->func_value()->export_for_inlining())
+ this->inline_fcn_worklist_->push_back(no);
+ }
+
+ return TRAVERSE_CONTINUE;
+ }
+
+ return TRAVERSE_CONTINUE;
+}
+
+// Collect up the set of types mentioned in things we're exporting, and collect
+// all the packages encountered during type traversal, to make sure we can
+// declare things referered to indirectly (for example, in the body of an
+// exported inline function from another package).
+
+void
+Collect_export_references::prepare_types()
+{
+ // Iterate through the exported objects and traverse any types encountered.
+ for (Unordered_set(Named_object*)::iterator p = this->exports_->begin();
+ p != this->exports_->end();
+ ++p)
+ {
+ Named_object* no = *p;
+ switch (no->classification())
+ {
+ case Named_object::NAMED_OBJECT_CONST:
+ {
+ Type* t = no->const_value()->type();
+ if (t != NULL && !t->is_abstract())
+ Type::traverse(t, this);
+ }
+ break;
+
+ case Named_object::NAMED_OBJECT_TYPE:
+ Type::traverse(no->type_value()->real_type(), this);
+ this->traverse_named_type(no->type_value());
+ break;
+
+ case Named_object::NAMED_OBJECT_VAR:
+ Type::traverse(no->var_value()->type(), this);
+ break;
+
+ case Named_object::NAMED_OBJECT_FUNC:
+ {
+ Function* fn = no->func_value();
+ this->traverse_function_type(fn->type());
+ if (fn->export_for_inlining())
+ fn->block()->traverse(this);
+ }
+ break;
+
+ case Named_object::NAMED_OBJECT_FUNC_DECLARATION:
+ this->traverse_function_type(no->func_declaration_value()->type());
+ break;
+
+ default:
+ // We shouldn't see anything else. If we do we'll give an
+ // error later when we try to actually export it.
+ break;
+ }
+ }
+}
+
+// Record referenced type, record package imports, and make sure we traverse
+// methods of named types.
+
+int
+Collect_export_references::type(Type* type)
+{
+ // Skip forwarders; don't try to give them a type index.
+ if (type->forward_declaration_type() != NULL)
+ return TRAVERSE_CONTINUE;
+
+ // Skip the void type, which we'll see when exporting
+ // unsafe.Pointer. The void type is not itself exported, because
+ // Pointer_type::do_export checks for it.
+ if (type->is_void_type())
+ return TRAVERSE_SKIP_COMPONENTS;
+
+ // Skip abstract types. We should never see these in real code,
+ // only in things like const declarations.
+ if (type->is_abstract())
+ return TRAVERSE_SKIP_COMPONENTS;
+
+ // For interfaces make sure that embedded methods are sorted, since the
+ // comparison function we use for indexing types relies on it (this call has
+ // to happen before the record_type call below).
+ if (type->classification() == Type::TYPE_INTERFACE)
+ {
+ Interface_type* it = type->interface_type();
+ if (it != NULL)
+ it->sort_embedded();
+ }
+
+ if (!this->exp_->record_type(type))
+ {
+ // We've already seen this type.
+ return TRAVERSE_SKIP_COMPONENTS;
+ }
+
+ // At this stage of compilation traversing interface types traverses
+ // the final list of methods, but we export the locally defined
+ // methods. If there is an embedded interface type we need to make
+ // sure to export that. Check classification, rather than calling
+ // the interface_type method, because we want to handle named types
+ // below.
+ if (type->classification() == Type::TYPE_INTERFACE)
+ {
+ Interface_type* it = type->interface_type();
+ const Typed_identifier_list* methods = it->local_methods();
+ if (methods != NULL)
+ {
+ for (Typed_identifier_list::const_iterator p = methods->begin();
+ p != methods->end();
+ ++p)
+ {
+ if (p->name().empty())
+ Type::traverse(p->type(), this);
+ else
+ this->traverse_function_type(p->type()->function_type());
+ }
+ }
+ return TRAVERSE_SKIP_COMPONENTS;
+ }
+
+ Named_type* nt = type->named_type();
+ if (nt != NULL)
+ this->traverse_named_type(nt);
+
+ return TRAVERSE_CONTINUE;
+}
+
+void
+Collect_export_references::traverse_named_type(Named_type* nt)
+{
+ const Package* package = nt->named_object()->package();
+ if (package != NULL)
+ this->imports_->insert(package);
+
+ // We have to traverse the methods of named types, because we are
+ // going to export them. This is not done by ordinary type
+ // traversal.
+ const Bindings* methods = nt->local_methods();
+ if (methods != NULL)
+ {
+ for (Bindings::const_definitions_iterator pm =
+ methods->begin_definitions();
+ pm != methods->end_definitions();
+ ++pm)
+ {
+ Function* fn = (*pm)->func_value();
+ this->traverse_function_type(fn->type());
+ if (fn->export_for_inlining())
+ fn->block()->traverse(this);
+ }
+
+ for (Bindings::const_declarations_iterator pm =
+ methods->begin_declarations();
+ pm != methods->end_declarations();
+ ++pm)
+ {
+ Named_object* mno = pm->second;
+ if (mno->is_function_declaration())
+ this->traverse_function_type(mno->func_declaration_value()->type());
+ }
+ }
+}
+
+// Traverse the types in a function type. We don't need the function
+// type itself, just the receiver, parameter, and result types.
+
+void
+Collect_export_references::traverse_function_type(Function_type* type)
+{
+ go_assert(type != NULL);
+ if (this->remember_type(type))
+ return;
+ const Typed_identifier* receiver = type->receiver();
+ if (receiver != NULL)
+ Type::traverse(receiver->type(), this);
+ const Typed_identifier_list* parameters = type->parameters();
+ if (parameters != NULL)
+ parameters->traverse(this);
+ const Typed_identifier_list* results = type->results();
+ if (results != NULL)
+ results->traverse(this);
+}
+
// Return true if we should export NO.
static bool
@@ -135,6 +448,54 @@ should_export(Named_object* no)
return true;
}
+// A functor to sort Named_object pointers by name.
+
+struct Sort_bindings
+{
+ bool
+ operator()(const Named_object* n1, const Named_object* n2) const
+ {
+ if (n1->package() != n2->package())
+ {
+ if (n1->package() == NULL)
+ return true;
+ if (n2->package() == NULL)
+ return false;
+ return n1->package()->pkgpath() < n2->package()->pkgpath();
+ }
+
+ return n1->name() < n2->name();
+ }
+};
+
+// A functor to sort types for export.
+
+struct Sort_types
+{
+ bool
+ operator()(const Type* t1, const Type* t2) const
+ {
+ const Named_type* nt1 = t1->named_type();
+ const Named_type* nt2 = t2->named_type();
+ if (nt1 != NULL)
+ {
+ if (nt2 != NULL)
+ {
+ Sort_bindings sb;
+ return sb(nt1->named_object(), nt2->named_object());
+ }
+ else
+ return true;
+ }
+ else if (nt2 != NULL)
+ return false;
+ if (t1->classification() != t2->classification())
+ return t1->classification() < t2->classification();
+ Gogo* gogo = go_get_gogo();
+ return gogo->type_descriptor_name(t1, NULL).compare(gogo->type_descriptor_name(t2, NULL)) < 0;
+ }
+};
+
// Export those identifiers marked for exporting.
void
@@ -153,17 +514,42 @@ Export::export_globals(const std::string& package_name,
if (saw_errors())
return;
- // Export the symbols in sorted order. That will reduce cases where
- // irrelevant changes to the source code affect the exported
- // interface.
- std::vector<Named_object*> exports;
- exports.reserve(bindings->size_definitions());
+ // EXPORTS is the set of objects to export. CHECK_INLINE_REFS is a
+ // list of exported function with inline bodies that need to be
+ // checked for references to other objects. Every function on
+ // CHECK_INLINE_REFS is also on EXPORTS.
+ Unordered_set(Named_object*) exports;
+ std::vector<Named_object*> check_inline_refs;
for (Bindings::const_definitions_iterator p = bindings->begin_definitions();
p != bindings->end_definitions();
++p)
- if (should_export(*p))
- exports.push_back(*p);
+ {
+ if (should_export(*p))
+ {
+ exports.insert(*p);
+
+ if ((*p)->is_function()
+ && (*p)->func_value()->export_for_inlining())
+ check_inline_refs.push_back(*p);
+ else if ((*p)->is_type())
+ {
+ const Bindings* methods = (*p)->type_value()->local_methods();
+ if (methods != NULL)
+ {
+ for (Bindings::const_definitions_iterator pm =
+ methods->begin_definitions();
+ pm != methods->end_definitions();
+ ++pm)
+ {
+ Function* fn = (*pm)->func_value();
+ if (fn->export_for_inlining())
+ check_inline_refs.push_back(*pm);
+ }
+ }
+ }
+ }
+ }
for (Bindings::const_declarations_iterator p =
bindings->begin_declarations();
@@ -174,15 +560,45 @@ Export::export_globals(const std::string& package_name,
// supporting C code. We do not export type declarations.
if (p->second->is_function_declaration()
&& should_export(p->second))
- exports.push_back(p->second);
+ exports.insert(p->second);
}
- std::sort(exports.begin(), exports.end(), Sort_bindings());
+ // Track all imported packages mentioned in export data.
+ Unordered_set(const Package*) all_imports;
+
+ Collect_export_references collect(this, &exports, &all_imports);
+
+ // Walk the set of inlinable routine bodies collected above. This
+ // can potentially expand the exports set.
+ collect.expand_exports(&check_inline_refs);
+
+ // Export the symbols in sorted order. That will reduce cases where
+ // irrelevant changes to the source code affect the exported
+ // interface.
+ std::vector<Named_object*> sorted_exports;
+ sorted_exports.reserve(exports.size());
+
+ for (Unordered_set(Named_object*)::const_iterator p = exports.begin();
+ p != exports.end();
+ ++p)
+ {
+ sorted_exports.push_back(*p);
+
+ const Package* pkg = (*p)->package();
+ if (pkg != NULL)
+ all_imports.insert(pkg);
+ }
+
+ std::sort(sorted_exports.begin(), sorted_exports.end(), Sort_bindings());
+
+ // Collect up the set of types mentioned in things we're exporting,
+ // and any packages that may be referred to indirectly.
+ collect.prepare_types();
// Assign indexes to all exported types and types referenced by
- // exported types, and collect all packages mentioned.
- Unordered_set(const Package*) type_imports;
- int unexported_type_index = this->prepare_types(&exports, &type_imports);
+ // things we're exporting. Return value is index of first non-exported
+ // type.
+ int unexported_type_index = this->assign_type_indices(sorted_exports);
// Although the export data is readable, at least this version is,
// it is conceptually a binary format. Start with a four byte
@@ -210,7 +626,7 @@ Export::export_globals(const std::string& package_name,
this->write_packages(packages);
- this->write_imports(imports, type_imports);
+ this->write_imports(imports, all_imports);
this->write_imported_init_fns(package_name, import_init_fn,
imported_init_fns);
@@ -223,8 +639,8 @@ Export::export_globals(const std::string& package_name,
this->write_types(unexported_type_index);
// Write out the non-type export data.
- for (std::vector<Named_object*>::const_iterator p = exports.begin();
- p != exports.end();
+ for (std::vector<Named_object*>::const_iterator p = sorted_exports.begin();
+ p != sorted_exports.end();
++p)
{
if (!(*p)->is_type())
@@ -247,175 +663,53 @@ Export::export_globals(const std::string& package_name,
this->stream_->write_checksum(s);
}
-// Traversal class to find referenced types.
-
-class Find_types_to_prepare : public Traverse
-{
- public:
- Find_types_to_prepare(Export* exp,
- Unordered_set(const Package*)* imports)
- : Traverse(traverse_types),
- exp_(exp), imports_(imports)
- { }
-
- int
- type(Type* type);
-
- // Traverse the components of a function type.
- void
- traverse_function(Function_type*);
-
- // Traverse the methods of a named type, and register its package.
- void
- traverse_named_type(Named_type*);
+// Record a type in the "to be indexed" set. Return true if the type
+// was not already in the set, false otherwise.
- private:
- // Exporters.
- Export* exp_;
- // List of packages we are building.
- Unordered_set(const Package*)* imports_;
-};
-
-// Set type index of referenced type, record package imports, and make
-// sure we traverse methods of named types.
-
-int
-Find_types_to_prepare::type(Type* type)
+bool
+Export::record_type(Type* type)
{
- // Skip forwarders; don't try to give them a type index.
- if (type->forward_declaration_type() != NULL)
- return TRAVERSE_CONTINUE;
-
- // Skip the void type, which we'll see when exporting
- // unsafe.Pointer. The void type is not itself exported, because
- // Pointer_type::do_export checks for it.
- if (type->is_void_type())
- return TRAVERSE_SKIP_COMPONENTS;
-
- // Skip abstract types. We should never see these in real code,
- // only in things like const declarations.
- if (type->is_abstract())
- return TRAVERSE_SKIP_COMPONENTS;
-
- // For interfaces make sure that embedded methods are sorted, since the
- // comparison function we use for indexing types relies on it (this call has
- // to happen before the set_type_index call below).
- if (type->classification() == Type::TYPE_INTERFACE)
- {
- Interface_type* it = type->interface_type();
- if (it != NULL)
- it->sort_embedded();
- }
+ type = type->forwarded();
- if (!this->exp_->set_type_index(type))
+ std::pair<Type_refs::iterator, bool> ins =
+ this->impl_->type_refs.insert(std::make_pair(type, 0));
+ if (!ins.second)
{
// We've already seen this type.
- return TRAVERSE_SKIP_COMPONENTS;
- }
-
- // At this stage of compilation traversing interface types traverses
- // the final list of methods, but we export the locally defined
- // methods. If there is an embedded interface type we need to make
- // sure to export that. Check classification, rather than calling
- // the interface_type method, because we want to handle named types
- // below.
- if (type->classification() == Type::TYPE_INTERFACE)
- {
- Interface_type* it = type->interface_type();
- const Typed_identifier_list* methods = it->local_methods();
- if (methods != NULL)
- {
- for (Typed_identifier_list::const_iterator p = methods->begin();
- p != methods->end();
- ++p)
- {
- if (p->name().empty())
- Type::traverse(p->type(), this);
- else
- this->traverse_function(p->type()->function_type());
- }
- }
- return TRAVERSE_SKIP_COMPONENTS;
+ return false;
}
+ ins.first->second = 0;
- Named_type* nt = type->named_type();
- if (nt != NULL)
- this->traverse_named_type(nt);
-
- return TRAVERSE_CONTINUE;
-}
-
-// Traverse the types in a function type. We don't need the function
-// type itself, just the receiver, parameter, and result types.
-
-void
-Find_types_to_prepare::traverse_function(Function_type* type)
-{
- go_assert(type != NULL);
- if (this->remember_type(type))
- return;
- const Typed_identifier* receiver = type->receiver();
- if (receiver != NULL)
- Type::traverse(receiver->type(), this);
- const Typed_identifier_list* parameters = type->parameters();
- if (parameters != NULL)
- parameters->traverse(this);
- const Typed_identifier_list* results = type->results();
- if (results != NULL)
- results->traverse(this);
+ return true;
}
-// Traverse the methods of a named type, and record its package.
+// Assign the specified type an index.
void
-Find_types_to_prepare::traverse_named_type(Named_type* nt)
+Export::set_type_index(const Type* type)
{
- const Package* package = nt->named_object()->package();
- if (package != NULL)
- this->imports_->insert(package);
-
- // We have to traverse the methods of named types, because we are
- // going to export them. This is not done by ordinary type
- // traversal.
- const Bindings* methods = nt->local_methods();
- if (methods != NULL)
- {
- for (Bindings::const_definitions_iterator pm =
- methods->begin_definitions();
- pm != methods->end_definitions();
- ++pm)
- {
- Function* fn = (*pm)->func_value();
- this->traverse_function(fn->type());
- if (fn->export_for_inlining())
- fn->block()->traverse(this);
- }
-
- for (Bindings::const_declarations_iterator pm =
- methods->begin_declarations();
- pm != methods->end_declarations();
- ++pm)
- {
- Named_object* mno = pm->second;
- if (mno->is_function_declaration())
- this->traverse_function(mno->func_declaration_value()->type());
- }
- }
+ type = type->forwarded();
+ std::pair<Type_refs::iterator, bool> ins =
+ this->impl_->type_refs.insert(std::make_pair(type, 0));
+ go_assert(!ins.second);
+ int index = this->type_index_;
+ ++this->type_index_;
+ go_assert(ins.first->second == 0);
+ ins.first->second = index;
}
-// Prepare to export types by assigning a type index to every exported
-// type and every type referenced by an exported type. Also collect
-// all the packages we see in types, so that if we refer to any types
-// from indirectly imported packages we can tell the importer about
-// the package. This returns the number of exported types.
+// This helper assigns type indices to all types mentioned directly or
+// indirectly in the things we're exporting. Actual exported types are given
+// indices according to where the appear on the sorted exports list; all other
+// types appear afterwards. Return value is the total number of exported types
+// plus 1, e.g. the index of the 1st non-exported type.
int
-Export::prepare_types(const std::vector<Named_object*>* exports,
- Unordered_set(const Package*)* imports)
+Export::assign_type_indices(const std::vector<Named_object*>& sorted_exports)
{
// Assign indexes to all the exported types.
- for (std::vector<Named_object*>::const_iterator p = exports->begin();
- p != exports->end();
+ for (std::vector<Named_object*>::const_iterator p = sorted_exports.begin();
+ p != sorted_exports.end();
++p)
{
if (!(*p)->is_type())
@@ -423,85 +717,34 @@ Export::prepare_types(const std::vector<Named_object*>* exports,
Interface_type* it = (*p)->type_value()->interface_type();
if (it != NULL)
it->sort_embedded();
+ this->record_type((*p)->type_value());
this->set_type_index((*p)->type_value());
}
-
int ret = this->type_index_;
- // Use a single instance of the traversal class because traversal
- // classes keep track of which types they've already seen. That
- // lets us avoid type reference loops.
- Find_types_to_prepare find(this, imports);
-
- // Traverse all the exported objects and assign indexes to all types.
- for (std::vector<Named_object*>::const_iterator p = exports->begin();
- p != exports->end();
+ // Collect export-referenced, non-builtin types.
+ std::vector<const Type*> types;
+ types.reserve(this->impl_->type_refs.size());
+ for (Type_refs::const_iterator p = this->impl_->type_refs.begin();
+ p != this->impl_->type_refs.end();
++p)
{
- Named_object* no = *p;
- switch (no->classification())
- {
- case Named_object::NAMED_OBJECT_CONST:
- {
- Type* t = no->const_value()->type();
- if (t != NULL && !t->is_abstract())
- Type::traverse(t, &find);
- }
- break;
-
- case Named_object::NAMED_OBJECT_TYPE:
- Type::traverse(no->type_value()->real_type(), &find);
- find.traverse_named_type(no->type_value());
- break;
-
- case Named_object::NAMED_OBJECT_VAR:
- Type::traverse(no->var_value()->type(), &find);
- break;
-
- case Named_object::NAMED_OBJECT_FUNC:
- {
- Function* fn = no->func_value();
- find.traverse_function(fn->type());
- if (fn->export_for_inlining())
- fn->block()->traverse(&find);
- }
- break;
-
- case Named_object::NAMED_OBJECT_FUNC_DECLARATION:
- find.traverse_function(no->func_declaration_value()->type());
- break;
-
- default:
- // We shouldn't see anything else. If we do we'll give an
- // error later when we try to actually export it.
- break;
- }
+ const Type* t = p->first;
+ if (p->second != 0)
+ continue;
+ types.push_back(t);
}
- return ret;
-}
+ // Sort the types.
+ std::sort(types.begin(), types.end(), Sort_types());
-// Give a type an index if it doesn't already have one. Return true
-// if we set the type index, false if it was already known.
-
-bool
-Export::set_type_index(Type* type)
-{
- type = type->forwarded();
-
- std::pair<Type_refs::iterator, bool> ins =
- type_refs.insert(std::make_pair(type, 0));
- if (!ins.second)
- {
- // We've already seen this type.
- return false;
- }
-
- int index = this->type_index_;
- ++this->type_index_;
- ins.first->second = index;
+ // Assign numbers to the sorted list.
+ for (std::vector<const Type *>::const_iterator p = types.begin();
+ p != types.end();
+ ++p)
+ this->set_type_index((*p));
- return true;
+ return ret;
}
// Sort packages.
@@ -576,7 +819,7 @@ import_compare(const std::pair<std::string, Package*>& a,
void
Export::write_imports(const std::map<std::string, Package*>& imports,
- const Unordered_set(const Package*)& type_imports)
+ const Unordered_set(const Package*)& all_imports)
{
// Sort the imports for more consistent output.
Unordered_set(const Package*) seen;
@@ -591,6 +834,7 @@ Export::write_imports(const std::map<std::string, Package*>& imports,
std::sort(sorted_imports.begin(), sorted_imports.end(), import_compare);
+ int package_index = 1;
for (std::vector<std::pair<std::string, Package*> >::const_iterator p =
sorted_imports.begin();
p != sorted_imports.end();
@@ -604,14 +848,15 @@ Export::write_imports(const std::map<std::string, Package*>& imports,
this->write_string(p->first);
this->write_c_string("\"\n");
- this->packages_.insert(p->second);
+ this->packages_[p->second] = package_index;
+ package_index++;
}
// Write out a separate list of indirectly imported packages.
std::vector<const Package*> indirect_imports;
for (Unordered_set(const Package*)::const_iterator p =
- type_imports.begin();
- p != type_imports.end();
+ all_imports.begin();
+ p != all_imports.end();
++p)
{
if (seen.find(*p) == seen.end())
@@ -631,6 +876,9 @@ Export::write_imports(const std::map<std::string, Package*>& imports,
this->write_c_string(" ");
this->write_string((*p)->pkgpath());
this->write_c_string("\n");
+
+ this->packages_[*p] = package_index;
+ package_index++;
}
}
@@ -661,6 +909,8 @@ Export::populate_init_graph(Init_graph* init_graph,
++p)
{
const Import_init* ii = *p;
+ if (ii->is_dummy())
+ continue;
std::map<std::string, unsigned>::const_iterator srcit =
init_idx.find(ii->init_name());
go_assert(srcit != init_idx.end());
@@ -759,7 +1009,7 @@ Export::write_imported_init_fns(const std::string& package_name,
// Now add edges from the local init function to each of the
// imported fcns.
- if (!import_init_fn.empty())
+ if (!import_init_fn.empty() && import_init_fn[0] != '~')
{
unsigned src = 0;
go_assert(init_idx[import_init_fn] == 0);
@@ -768,6 +1018,8 @@ Export::write_imported_init_fns(const std::string& package_name,
++p)
{
const Import_init* ii = *p;
+ if (ii->is_dummy())
+ continue;
unsigned sink = init_idx[ii->init_name()];
add_init_graph_edge(&init_graph, src, sink);
}
@@ -861,8 +1113,8 @@ Export::write_types(int unexported_type_index)
{
// Map from type index to type.
std::vector<const Type*> types(static_cast<size_t>(this->type_index_));
- for (Type_refs::const_iterator p = type_refs.begin();
- p != type_refs.end();
+ for (Type_refs::const_iterator p = this->impl_->type_refs.begin();
+ p != this->impl_->type_refs.end();
++p)
{
if (p->second >= 0)
@@ -983,14 +1235,27 @@ Export::write_unsigned(unsigned value)
this->write_c_string(buf);
}
+// Return the index of a package.
+
+int
+Export::package_index(const Package* pkg) const
+{
+ Unordered_map(const Package *, int)::const_iterator p =
+ this->packages_.find(pkg);
+ go_assert(p != this->packages_.end());
+ int index = p->second;
+ go_assert(index != 0);
+ return index;
+}
+
// Return the index of a type.
int
Export::type_index(const Type* type)
{
type = type->forwarded();
- Type_refs::const_iterator p = type_refs.find(type);
- go_assert(p != type_refs.end());
+ Type_refs::const_iterator p = this->impl_->type_refs.find(type);
+ go_assert(p != this->impl_->type_refs.end());
int index = p->second;
go_assert(index != 0);
return index;
@@ -1068,7 +1333,7 @@ Export::register_builtin_type(Gogo* gogo, const char* name, Builtin_code code)
Named_object* named_object = gogo->lookup_global(name);
go_assert(named_object != NULL && named_object->is_type());
std::pair<Type_refs::iterator, bool> ins =
- type_refs.insert(std::make_pair(named_object->type_value(), code));
+ this->impl_->type_refs.insert(std::make_pair(named_object->type_value(), code));
go_assert(ins.second);
// We also insert the underlying type. We can see the underlying
@@ -1076,7 +1341,7 @@ Export::register_builtin_type(Gogo* gogo, const char* name, Builtin_code code)
// fails--we expect duplications here, and it doesn't matter when
// they occur.
Type* real_type = named_object->type_value()->real_type();
- type_refs.insert(std::make_pair(real_type, code));
+ this->impl_->type_refs.insert(std::make_pair(real_type, code));
}
// Class Export::Stream.
@@ -1133,3 +1398,56 @@ Stream_to_section::do_write(const char* bytes, size_t length)
{
this->backend_->write_export_data (bytes, length);
}
+
+// Class Export_function_body.
+
+// Record a temporary statement.
+
+unsigned int
+Export_function_body::record_temporary(const Temporary_statement* temp)
+{
+ unsigned int ret = this->next_temporary_index_;
+ if (ret > 0x7fffffff)
+ go_error_at(temp->location(),
+ "too many temporary statements in export data");
+ ++this->next_temporary_index_;
+ std::pair<const Temporary_statement*, unsigned int> val(temp, ret);
+ std::pair<Unordered_map(const Temporary_statement*, unsigned int)::iterator,
+ bool> ins = this->temporary_indexes_.insert(val);
+ go_assert(ins.second);
+ return ret;
+}
+
+// Return the index of a temporary statement.
+
+unsigned int
+Export_function_body::temporary_index(const Temporary_statement* temp)
+{
+ Unordered_map(const Temporary_statement*, unsigned int)::const_iterator p =
+ this->temporary_indexes_.find(temp);
+ go_assert(p != this->temporary_indexes_.end());
+ return p->second;
+}
+
+// Return the index of an unnamed label. If it doesn't already have
+// an index, give it one.
+
+unsigned int
+Export_function_body::unnamed_label_index(const Unnamed_label* label)
+{
+ unsigned int next = this->next_label_index_;
+ std::pair<const Unnamed_label*, unsigned int> val(label, next);
+ std::pair<Unordered_map(const Unnamed_label*, unsigned int)::iterator,
+ bool> ins =
+ this->label_indexes_.insert(val);
+ if (!ins.second)
+ return ins.first->second;
+ else
+ {
+ if (next > 0x7fffffff)
+ go_error_at(label->location(),
+ "too many unnamed labels in export data");
+ ++this->next_label_index_;
+ return next;
+ }
+}
diff --git a/gcc/go/gofrontend/export.h b/gcc/go/gofrontend/export.h
index 69fbd6e..1af386c1 100644
--- a/gcc/go/gofrontend/export.h
+++ b/gcc/go/gofrontend/export.h
@@ -20,6 +20,9 @@ class Type;
class Package;
class Import_init_set;
class Backend;
+class Temporary_statement;
+class Unnamed_label;
+struct Export_impl;
// Codes used for the builtin types. These are all negative to make
// them easily distinct from the codes assigned by Export::write_type.
@@ -119,6 +122,7 @@ class Export : public String_dump
};
Export(Stream*);
+ ~Export();
// Size of export data magic string (which includes version number).
static const int magic_len = 4;
@@ -156,9 +160,15 @@ class Export : public String_dump
const Import_init_set& imported_init_fns,
const Bindings* bindings);
- // Set the index of a type.
+ // Record a type that is mentioned in export data. Return value is
+ // TRUE for newly visited types, FALSE for types that have been seen
+ // previously.
bool
- set_type_index(Type*);
+ record_type(Type*);
+
+ // Assign type indices to types mentioned in export data.
+ int
+ assign_type_indices(const std::vector<Named_object*>& sorted_exports);
// Write a string to the export stream.
void
@@ -201,15 +211,14 @@ class Export : public String_dump
void
write_unsigned(unsigned);
+ // Return the index of a package.
+ int
+ package_index(const Package* p) const;
+
private:
Export(const Export&);
Export& operator=(const Export&);
- // Prepare types for exporting.
- int
- prepare_types(const std::vector<Named_object*>* exports,
- Unordered_set(const Package*)* imports);
-
// Write out all known packages.
void
write_packages(const std::map<std::string, Package*>& packages);
@@ -250,12 +259,18 @@ class Export : public String_dump
int
type_index(const Type*);
+ // Set the index of a type.
+ void
+ set_type_index(const Type*);
+
// The stream to which we are writing data.
Stream* stream_;
// Index number of next type.
int type_index_;
// Packages we have written out.
- Unordered_set(const Package*) packages_;
+ Unordered_map(const Package*, int) packages_;
+ // Hidden implementation-specific state.
+ Export_impl* impl_;
};
// An export streamer that puts the export stream in a named section.
@@ -303,7 +318,9 @@ class Export_function_body : public String_dump
{
public:
Export_function_body(Export* exp, int indent)
- : exp_(exp), type_context_(NULL), indent_(indent)
+ : exp_(exp), body_(), type_context_(NULL), next_temporary_index_(0),
+ temporary_indexes_(), next_label_index_(0), label_indexes_(),
+ indent_(indent)
{ }
// Write a character to the body.
@@ -354,6 +371,24 @@ class Export_function_body : public String_dump
decrement_indent()
{ --this->indent_; }
+ // Return the index of a package.
+ int
+ package_index(const Package* p) const
+ { return this->exp_->package_index(p); }
+
+ // Record a temporary statement and return its index.
+ unsigned int
+ record_temporary(const Temporary_statement*);
+
+ // Return the index of a temporary statement.
+ unsigned int
+ temporary_index(const Temporary_statement*);
+
+ // Return the index of an unnamed label. If it doesn't already have
+ // an index, give it one.
+ unsigned int
+ unnamed_label_index(const Unnamed_label*);
+
// Return a reference to the completed body.
const std::string&
body() const
@@ -366,6 +401,14 @@ class Export_function_body : public String_dump
std::string body_;
// Current type context. Used to avoid duplicate type conversions.
Type* type_context_;
+ // Index to give to next temporary statement.
+ unsigned int next_temporary_index_;
+ // Map temporary statements to indexes.
+ Unordered_map(const Temporary_statement*, unsigned int) temporary_indexes_;
+ // Index to give to the next unnamed label.
+ unsigned int next_label_index_;
+ // Map unnamed labels to indexes.
+ Unordered_map(const Unnamed_label*, unsigned int) label_indexes_;
// Current indentation level: the number of spaces before each statement.
int indent_;
};
diff --git a/gcc/go/gofrontend/expressions.cc b/gcc/go/gofrontend/expressions.cc
index 2c1286c..abc4bba 100644
--- a/gcc/go/gofrontend/expressions.cc
+++ b/gcc/go/gofrontend/expressions.cc
@@ -87,6 +87,27 @@ Expression::do_export(Export_function_body*) const
go_unreachable();
}
+// Write a name to the export data.
+
+void
+Expression::export_name(Export_function_body* efb, const Named_object* no)
+{
+ if (no->package() != NULL)
+ {
+ char buf[50];
+ snprintf(buf, sizeof buf, "<p%d>", efb->package_index(no->package()));
+ efb->write_c_string(buf);
+ }
+
+ if (!Gogo::is_hidden_name(no->name()))
+ efb->write_string(no->name());
+ else
+ {
+ efb->write_c_string(".");
+ efb->write_string(Gogo::unpack_hidden_name(no->name()));
+ }
+}
+
// Give an error saying that the value of the expression is not used.
void
@@ -184,11 +205,10 @@ Expression::convert_for_assignment(Gogo*, Type* lhs_type,
NULL);
if (!are_identical && lhs_type->interface_type() != NULL)
{
- if (rhs_type->interface_type() == NULL)
- return Expression::convert_type_to_interface(lhs_type, rhs, location);
- else
- return Expression::convert_interface_to_interface(lhs_type, rhs, false,
- location);
+ // Type to interface conversions have been made explicit early.
+ go_assert(rhs_type->interface_type() != NULL);
+ return Expression::convert_interface_to_interface(lhs_type, rhs, false,
+ location);
}
else if (!are_identical && rhs_type->interface_type() != NULL)
return Expression::convert_interface_to_type(lhs_type, rhs, location);
@@ -231,11 +251,12 @@ Expression::convert_for_assignment(Gogo*, Type* lhs_type,
}
// Return an expression for a conversion from a non-interface type to an
-// interface type.
+// interface type. If ON_STACK is true, it can allocate the storage on
+// stack.
Expression*
Expression::convert_type_to_interface(Type* lhs_type, Expression* rhs,
- Location location)
+ bool on_stack, Location location)
{
Interface_type* lhs_interface_type = lhs_type->interface_type();
bool lhs_is_empty = lhs_interface_type->is_empty();
@@ -302,9 +323,14 @@ Expression::convert_type_to_interface(Type* lhs_type, Expression* rhs,
{
// We are assigning a non-pointer value to the interface; the
// interface gets a copy of the value in the heap if it escapes.
- // TODO(cmang): Associate escape state state of RHS with newly
- // created OBJ.
- obj = Expression::make_heap_expression(rhs, location);
+ if (rhs->is_constant())
+ obj = Expression::make_unary(OPERATOR_AND, rhs, location);
+ else
+ {
+ obj = Expression::make_heap_expression(rhs, location);
+ if (on_stack)
+ obj->heap_expression()->set_allocate_on_stack();
+ }
}
return Expression::make_interface_value(lhs_type, first_field, obj, location);
@@ -460,9 +486,11 @@ Expression::convert_interface_to_type(Type *lhs_type, Expression* rhs,
// We are going to evaluate RHS multiple times.
go_assert(rhs->is_variable());
- // Call a function to check that the type is valid. The function
- // will panic with an appropriate runtime type error if the type is
- // not valid.
+ // Build an expression to check that the type is valid. It will
+ // panic with an appropriate runtime type error if the type is not
+ // valid.
+ // (lhs_type != rhs_type ? panicdottype(lhs_type, rhs_type, inter_type) :
+ // nil /*dummy*/)
Expression* lhs_type_expr = Expression::make_type_descriptor(lhs_type,
location);
Expression* rhs_descriptor =
@@ -472,11 +500,18 @@ Expression::convert_interface_to_type(Type *lhs_type, Expression* rhs,
Expression* rhs_inter_expr = Expression::make_type_descriptor(rhs_type,
location);
- Expression* check_iface = Runtime::make_call(Runtime::ASSERTI2T,
- location, 3, lhs_type_expr,
- rhs_descriptor, rhs_inter_expr);
+ Expression* cond = Expression::make_binary(OPERATOR_NOTEQ, lhs_type_expr,
+ rhs_descriptor, location);
+ rhs_descriptor = Expression::get_interface_type_descriptor(rhs);
+ Expression* panic = Runtime::make_call(Runtime::PANICDOTTYPE, location,
+ 3, lhs_type_expr->copy(),
+ rhs_descriptor,
+ rhs_inter_expr);
+ Expression* nil = Expression::make_nil(location);
+ Expression* check = Expression::make_conditional(cond, panic, nil,
+ location);
- // If the call succeeds, pull out the value.
+ // If the conversion succeeds, pull out the value.
Expression* obj = Expression::make_interface_info(rhs, INTERFACE_INFO_OBJECT,
location);
@@ -491,7 +526,7 @@ Expression::convert_interface_to_type(Type *lhs_type, Expression* rhs,
obj = Expression::make_dereference(obj, NIL_CHECK_NOT_NEEDED,
location);
}
- return Expression::make_compound(check_iface, obj, location);
+ return Expression::make_compound(check, obj, location);
}
// Convert an expression to its backend representation. This is implemented by
@@ -842,29 +877,16 @@ Var_expression::do_address_taken(bool escapes)
}
}
-// The cost to inline a variable reference. We currently only support
-// references to parameters.
-
-int
-Var_expression::do_inlining_cost() const
-{
- if (this->variable_->is_variable())
- {
- if (this->variable_->var_value()->is_parameter())
- return 1;
- }
- else if (this->variable_->is_result_variable())
- return 1;
-
- return 0x100000;
-}
-
// Export a reference to a variable.
void
Var_expression::do_export(Export_function_body* efb) const
{
- efb->write_string(Gogo::unpack_hidden_name(this->variable_->name()));
+ Named_object* no = this->variable_;
+ if (no->is_result_variable() || !no->var_value()->is_global())
+ efb->write_string(Gogo::unpack_hidden_name(no->name()));
+ else
+ Expression::export_name(efb, no);
}
// Get the backend representation for a reference to a variable.
@@ -1012,6 +1034,57 @@ Temporary_reference_expression::do_address_taken(bool)
this->statement_->set_is_address_taken();
}
+// Export a reference to a temporary.
+
+void
+Temporary_reference_expression::do_export(Export_function_body* efb) const
+{
+ unsigned int idx = efb->temporary_index(this->statement_);
+ char buf[50];
+ snprintf(buf, sizeof buf, "$t%u", idx);
+ efb->write_c_string(buf);
+}
+
+// Import a reference to a temporary.
+
+Expression*
+Temporary_reference_expression::do_import(Import_function_body* ifb,
+ Location loc)
+{
+ std::string id = ifb->read_identifier();
+ go_assert(id[0] == '$' && id[1] == 't');
+ const char *p = id.c_str();
+ char *end;
+ long idx = strtol(p + 2, &end, 10);
+ if (*end != '\0' || idx > 0x7fffffff)
+ {
+ if (!ifb->saw_error())
+ go_error_at(loc,
+ ("invalid export data for %qs: "
+ "invalid temporary reference index at %lu"),
+ ifb->name().c_str(),
+ static_cast<unsigned long>(ifb->off()));
+ ifb->set_saw_error();
+ return Expression::make_error(loc);
+ }
+
+ Temporary_statement* temp =
+ ifb->temporary_statement(static_cast<unsigned int>(idx));
+ if (temp == NULL)
+ {
+ if (!ifb->saw_error())
+ go_error_at(loc,
+ ("invalid export data for %qs: "
+ "undefined temporary reference index at %lu"),
+ ifb->name().c_str(),
+ static_cast<unsigned long>(ifb->off()));
+ ifb->set_saw_error();
+ return Expression::make_error(loc);
+ }
+
+ return Expression::make_temporary_reference(temp, loc);
+}
+
// Get a backend expression referring to the variable.
Bexpression*
@@ -1052,6 +1125,7 @@ Temporary_reference_expression*
Expression::make_temporary_reference(Temporary_statement* statement,
Location location)
{
+ statement->add_use();
return new Temporary_reference_expression(statement, location);
}
@@ -1273,7 +1347,8 @@ Func_expression::get_code_pointer(Gogo* gogo, Named_object* no, Location loc)
if (fntype->is_builtin())
{
go_error_at(loc,
- "invalid use of special builtin function %qs; must be called",
+ ("invalid use of special built-in function %qs; "
+ "must be called"),
no->message_name().c_str());
return gogo->backend()->error_expression();
}
@@ -1312,7 +1387,7 @@ Func_expression::do_get_backend(Translate_context* context)
if (no->func_declaration_value()->type()->is_builtin())
{
go_error_at(this->location(),
- ("invalid use of special builtin function %qs; "
+ ("invalid use of special built-in function %qs; "
"must be called"),
no->message_name().c_str());
return gogo->backend()->error_expression();
@@ -1342,6 +1417,29 @@ Func_expression::do_get_backend(Translate_context* context)
return gogo->backend()->convert_expression(btype, bexpr, this->location());
}
+// The cost of inlining a function reference.
+
+int
+Func_expression::do_inlining_cost() const
+{
+ // FIXME: We don't inline references to nested functions.
+ if (this->closure_ != NULL)
+ return 0x100000;
+ if (this->function_->is_function()
+ && this->function_->func_value()->enclosing() != NULL)
+ return 0x100000;
+
+ return 1;
+}
+
+// Export a reference to a function.
+
+void
+Func_expression::do_export(Export_function_body* efb) const
+{
+ Expression::export_name(efb, this->function_);
+}
+
// Ast dump for function.
void
@@ -1676,6 +1774,13 @@ class Boolean_expression : public Expression
{ return this->val_ == false; }
bool
+ do_boolean_constant_value(bool* val) const
+ {
+ *val = this->val_;
+ return true;
+ }
+
+ bool
do_is_static_initializer() const
{ return true; }
@@ -3044,6 +3149,9 @@ class Const_expression : public Expression
bool
do_string_constant_value(std::string* val) const;
+ bool
+ do_boolean_constant_value(bool* val) const;
+
Type*
do_type();
@@ -3162,6 +3270,21 @@ Const_expression::do_string_constant_value(std::string* val) const
return ok;
}
+bool
+Const_expression::do_boolean_constant_value(bool* val) const
+{
+ if (this->seen_)
+ return false;
+
+ Expression* e = this->constant_->const_value()->expr();
+
+ this->seen_ = true;
+ bool ok = e->boolean_constant_value(val);
+ this->seen_ = false;
+
+ return ok;
+}
+
// Return the type of the const reference.
Type*
@@ -3625,6 +3748,17 @@ Type_conversion_expression::do_flatten(Gogo*, Named_object*,
inserter->insert(temp);
this->expr_ = Expression::make_temporary_reference(temp, this->location());
}
+
+ // For interface conversion and string to/from slice conversions,
+ // decide if we can allocate on stack.
+ if (this->type()->interface_type() != NULL
+ || this->type()->is_string_type()
+ || this->expr_->type()->is_string_type())
+ {
+ Node* n = Node::make_node(this);
+ if ((n->encoding() & ESCAPE_MASK) == Node::ESCAPE_NONE)
+ this->no_escape_ = true;
+ }
return this;
}
@@ -3745,6 +3879,16 @@ Type_conversion_expression::do_string_constant_value(std::string* val) const
return false;
}
+// Return the constant boolean value if there is one.
+
+bool
+Type_conversion_expression::do_boolean_constant_value(bool* val) const
+{
+ if (!this->type_->is_boolean_type())
+ return false;
+ return this->expr_->boolean_constant_value(val);
+}
+
// Determine the resulting type of the conversion.
void
@@ -3813,11 +3957,19 @@ Type_conversion_expression::do_get_backend(Translate_context* context)
return gogo->backend()->convert_expression(btype, bexpr, loc);
}
else if (type->interface_type() != NULL
+ && expr_type->interface_type() == NULL)
+ {
+ Expression* conversion =
+ Expression::convert_type_to_interface(type, this->expr_,
+ this->no_escape_, loc);
+ return conversion->get_backend(context);
+ }
+ else if (type->interface_type() != NULL
|| expr_type->interface_type() != NULL)
{
Expression* conversion =
Expression::convert_for_assignment(gogo, type, this->expr_,
- this->location());
+ loc);
return conversion->get_backend(context);
}
else if (type->is_string_type()
@@ -3826,19 +3978,40 @@ Type_conversion_expression::do_get_backend(Translate_context* context)
mpz_t intval;
Numeric_constant nc;
if (this->expr_->numeric_constant_value(&nc)
- && nc.to_int(&intval)
- && mpz_fits_ushort_p(intval))
+ && nc.to_int(&intval))
{
std::string s;
- Lex::append_char(mpz_get_ui(intval), true, &s, loc);
+ unsigned int x;
+ if (mpz_fits_uint_p(intval))
+ x = mpz_get_ui(intval);
+ else
+ {
+ char* s = mpz_get_str(NULL, 16, intval);
+ go_warning_at(loc, 0,
+ "unicode code point 0x%s out of range in string", s);
+ x = 0xfffd;
+ }
+ Lex::append_char(x, true, &s, loc);
mpz_clear(intval);
Expression* se = Expression::make_string(s, loc);
return se->get_backend(context);
}
+ Expression* buf;
+ if (this->no_escape_)
+ {
+ Type* byte_type = Type::lookup_integer_type("uint8");
+ Expression* buflen =
+ Expression::make_integer_ul(4, NULL, loc);
+ Type* array_type = Type::make_array_type(byte_type, buflen);
+ buf = Expression::make_allocation(array_type, loc);
+ buf->allocation_expression()->set_allocate_on_stack();
+ buf->allocation_expression()->set_no_zero();
+ }
+ else
+ buf = Expression::make_nil(loc);
Expression* i2s_expr =
- Runtime::make_call(Runtime::INTSTRING, loc, 2,
- Expression::make_nil(loc), this->expr_);
+ Runtime::make_call(Runtime::INTSTRING, loc, 2, buf, this->expr_);
return Expression::make_cast(type, i2s_expr, loc)->get_backend(context);
}
else if (type->is_string_type() && expr_type->is_slice_type())
@@ -3854,7 +4027,7 @@ Type_conversion_expression::do_get_backend(Translate_context* context)
if (this->no_copy_)
{
if (gogo->debug_optimization())
- go_inform(loc, "no copy string([]byte)");
+ go_debug(loc, "no copy string([]byte)");
Expression* ptr = Expression::make_slice_info(this->expr_,
SLICE_INFO_VALUE_POINTER,
loc);
@@ -3871,7 +4044,21 @@ Type_conversion_expression::do_get_backend(Translate_context* context)
go_assert(e->integer_type()->is_rune());
code = Runtime::SLICERUNETOSTRING;
}
- return Runtime::make_call(code, loc, 2, Expression::make_nil(loc),
+
+ Expression* buf;
+ if (this->no_escape_)
+ {
+ Type* byte_type = Type::lookup_integer_type("uint8");
+ Expression* buflen =
+ Expression::make_integer_ul(tmp_string_buf_size, NULL, loc);
+ Type* array_type = Type::make_array_type(byte_type, buflen);
+ buf = Expression::make_allocation(array_type, loc);
+ buf->allocation_expression()->set_allocate_on_stack();
+ buf->allocation_expression()->set_no_zero();
+ }
+ else
+ buf = Expression::make_nil(loc);
+ return Runtime::make_call(code, loc, 2, buf,
this->expr_)->get_backend(context);
}
else if (type->is_slice_type() && expr_type->is_string_type())
@@ -3887,9 +4074,20 @@ Type_conversion_expression::do_get_backend(Translate_context* context)
go_assert(e->integer_type()->is_rune());
code = Runtime::STRINGTOSLICERUNE;
}
- Expression* s2a = Runtime::make_call(code, loc, 2,
- Expression::make_nil(loc),
- this->expr_);
+
+ Expression* buf;
+ if (this->no_escape_)
+ {
+ Expression* buflen =
+ Expression::make_integer_ul(tmp_string_buf_size, NULL, loc);
+ Type* array_type = Type::make_array_type(e, buflen);
+ buf = Expression::make_allocation(array_type, loc);
+ buf->allocation_expression()->set_allocate_on_stack();
+ buf->allocation_expression()->set_no_zero();
+ }
+ else
+ buf = Expression::make_nil(loc);
+ Expression* s2a = Runtime::make_call(code, loc, 2, buf, this->expr_);
return Expression::make_unsafe_cast(type, s2a, loc)->get_backend(context);
}
else if (type->is_numeric_type())
@@ -4597,6 +4795,20 @@ Unary_expression::do_numeric_constant_value(Numeric_constant* nc) const
nc, &issued_error);
}
+// Return the boolean constant value of a unary expression, if it has one.
+
+bool
+Unary_expression::do_boolean_constant_value(bool* val) const
+{
+ if (this->op_ == OPERATOR_NOT
+ && this->expr_->boolean_constant_value(val))
+ {
+ *val = !*val;
+ return true;
+ }
+ return false;
+}
+
// Return the type of a unary expression.
Type*
@@ -4862,6 +5074,18 @@ Unary_expression::do_get_backend(Translate_context* context)
false, btype, loc, bexpr);
bexpr = gogo->backend()->var_expression(decl, loc);
}
+ else if (this->expr_->is_constant())
+ {
+ std::string var_name(gogo->initializer_name());
+ std::string asm_name(go_selectively_encode_id(var_name));
+ Bvariable* decl =
+ gogo->backend()->implicit_variable(var_name, asm_name, btype,
+ true, true, false, 0);
+ gogo->backend()->implicit_variable_set_init(decl, var_name, btype,
+ true, true, false,
+ bexpr);
+ bexpr = gogo->backend()->var_expression(decl, loc);
+ }
go_assert(!this->create_temp_ || this->expr_->is_variable());
ret = gogo->backend()->address_expression(bexpr, loc);
@@ -5975,7 +6199,8 @@ Binary_expression::lower_compare_to_memcmp(Gogo*, Statement_inserter* inserter)
TYPE_INFO_SIZE);
Expression* call = Runtime::make_call(Runtime::MEMCMP, loc, 3, a1, a2, len);
- Expression* zero = Expression::make_integer_ul(0, NULL, loc);
+ Type* int32_type = Type::lookup_integer_type("int32");
+ Expression* zero = Expression::make_integer_ul(0, int32_type, loc);
return Expression::make_binary(this->op_, call, zero, loc);
}
@@ -6001,10 +6226,27 @@ Binary_expression::do_flatten(Gogo* gogo, Named_object*,
bool is_idiv_op = ((this->op_ == OPERATOR_DIV &&
left_type->integer_type() != NULL)
|| this->op_ == OPERATOR_MOD);
+ bool is_string_op = (left_type->is_string_type()
+ && this->right_->type()->is_string_type());
+
+ if (is_string_op)
+ {
+ // Mark string([]byte) operands to reuse the backing store.
+ // String comparison does not keep the reference, so it is safe.
+ Type_conversion_expression* lce =
+ this->left_->conversion_expression();
+ if (lce != NULL && lce->expr()->type()->is_slice_type())
+ lce->set_no_copy(true);
+ Type_conversion_expression* rce =
+ this->right_->conversion_expression();
+ if (rce != NULL && rce->expr()->type()->is_slice_type())
+ rce->set_no_copy(true);
+ }
if (is_shift_op
|| (is_idiv_op
- && (gogo->check_divide_by_zero() || gogo->check_divide_overflow())))
+ && (gogo->check_divide_by_zero() || gogo->check_divide_overflow()))
+ || is_string_op)
{
if (!this->left_->is_variable() && !this->left_->is_constant())
{
@@ -6062,6 +6304,86 @@ Binary_expression::do_numeric_constant_value(Numeric_constant* nc) const
this->location(), nc, &issued_error);
}
+// Return the boolean constant value, if it has one.
+
+bool
+Binary_expression::do_boolean_constant_value(bool* val) const
+{
+ bool is_comparison = false;
+ switch (this->op_)
+ {
+ case OPERATOR_EQEQ:
+ case OPERATOR_NOTEQ:
+ case OPERATOR_LT:
+ case OPERATOR_LE:
+ case OPERATOR_GT:
+ case OPERATOR_GE:
+ is_comparison = true;
+ break;
+ case OPERATOR_ANDAND:
+ case OPERATOR_OROR:
+ break;
+ default:
+ return false;
+ }
+
+ Numeric_constant left_nc, right_nc;
+ if (is_comparison
+ && this->left_->numeric_constant_value(&left_nc)
+ && this->right_->numeric_constant_value(&right_nc))
+ return Binary_expression::compare_constant(this->op_, &left_nc,
+ &right_nc,
+ this->location(),
+ val);
+
+ std::string left_str, right_str;
+ if (is_comparison
+ && this->left_->string_constant_value(&left_str)
+ && this->right_->string_constant_value(&right_str))
+ {
+ *val = Binary_expression::cmp_to_bool(this->op_,
+ left_str.compare(right_str));
+ return true;
+ }
+
+ bool left_bval;
+ if (this->left_->boolean_constant_value(&left_bval))
+ {
+ if (this->op_ == OPERATOR_ANDAND && !left_bval)
+ {
+ *val = false;
+ return true;
+ }
+ else if (this->op_ == OPERATOR_OROR && left_bval)
+ {
+ *val = true;
+ return true;
+ }
+
+ bool right_bval;
+ if (this->right_->boolean_constant_value(&right_bval))
+ {
+ switch (this->op_)
+ {
+ case OPERATOR_EQEQ:
+ *val = (left_bval == right_bval);
+ return true;
+ case OPERATOR_NOTEQ:
+ *val = (left_bval != right_bval);
+ return true;
+ case OPERATOR_ANDAND:
+ case OPERATOR_OROR:
+ *val = right_bval;
+ return true;
+ default:
+ go_unreachable();
+ }
+ }
+ }
+
+ return false;
+}
+
// Note that the value is being discarded.
bool
@@ -6856,6 +7178,12 @@ Binary_expression::do_import(Import_expression* imp, Location loc)
op = OPERATOR_BITCLEAR;
imp->advance(4);
}
+ else if (imp->match_c_string(")"))
+ {
+ // Not a binary operator after all.
+ imp->advance(1);
+ return left;
+ }
else
{
go_error_at(imp->location(), "unrecognized binary operator");
@@ -6906,19 +7234,42 @@ Expression::comparison(Translate_context* context, Type* result_type,
if (left_type->is_string_type() && right_type->is_string_type())
{
- // Mark string([]byte) operands to reuse the backing store.
- // String comparison does not keep the reference, so it is safe.
- Type_conversion_expression* lce = left->conversion_expression();
- if (lce != NULL && lce->expr()->type()->is_slice_type())
- lce->set_no_copy(true);
- Type_conversion_expression* rce = right->conversion_expression();
- if (rce != NULL && rce->expr()->type()->is_slice_type())
- rce->set_no_copy(true);
+ go_assert(left->is_variable() || left->is_constant());
+ go_assert(right->is_variable() || right->is_constant());
if (op == OPERATOR_EQEQ || op == OPERATOR_NOTEQ)
{
- left = Runtime::make_call(Runtime::EQSTRING, location, 2,
- left, right);
+ // (l.len == r.len
+ // ? (l.ptr == r.ptr ? true : memcmp(l.ptr, r.ptr, r.len) == 0)
+ // : false)
+ Expression* llen = Expression::make_string_info(left,
+ STRING_INFO_LENGTH,
+ location);
+ Expression* rlen = Expression::make_string_info(right,
+ STRING_INFO_LENGTH,
+ location);
+ Expression* leneq = Expression::make_binary(OPERATOR_EQEQ, llen, rlen,
+ location);
+ Expression* lptr = Expression::make_string_info(left->copy(),
+ STRING_INFO_DATA,
+ location);
+ Expression* rptr = Expression::make_string_info(right->copy(),
+ STRING_INFO_DATA,
+ location);
+ Expression* ptreq = Expression::make_binary(OPERATOR_EQEQ, lptr, rptr,
+ location);
+ Expression* btrue = Expression::make_boolean(true, location);
+ Expression* call = Runtime::make_call(Runtime::MEMCMP, location, 3,
+ lptr->copy(), rptr->copy(),
+ rlen->copy());
+ Type* int32_type = Type::lookup_integer_type("int32");
+ Expression* zero = Expression::make_integer_ul(0, int32_type, location);
+ Expression* cmp = Expression::make_binary(OPERATOR_EQEQ, call, zero,
+ location);
+ Expression* cond = Expression::make_conditional(ptreq, btrue, cmp,
+ location);
+ Expression* bfalse = Expression::make_boolean(false, location);
+ left = Expression::make_conditional(leneq, cond, bfalse, location);
right = Expression::make_boolean(true, location);
}
else
@@ -7142,63 +7493,77 @@ String_concat_expression::do_check_types(Gogo*)
Expression*
String_concat_expression::do_flatten(Gogo*, Named_object*,
- Statement_inserter*)
+ Statement_inserter* inserter)
{
if (this->is_error_expression())
return this;
Location loc = this->location();
Type* type = this->type();
- Expression* nil_arg = Expression::make_nil(loc);
- Expression* call;
- switch (this->exprs_->size())
- {
- case 0: case 1:
- go_unreachable();
- case 2: case 3: case 4: case 5:
- {
- Expression* len = Expression::make_integer_ul(this->exprs_->size(),
- NULL, loc);
- Array_type* arg_type = Type::make_array_type(type, len);
- arg_type->set_is_array_incomparable();
- Expression* arg =
- Expression::make_array_composite_literal(arg_type, this->exprs_,
- loc);
- Runtime::Function code;
- switch (this->exprs_->size())
- {
- default:
- go_unreachable();
- case 2:
- code = Runtime::CONCATSTRING2;
- break;
- case 3:
- code = Runtime::CONCATSTRING3;
- break;
- case 4:
- code = Runtime::CONCATSTRING4;
- break;
- case 5:
- code = Runtime::CONCATSTRING5;
- break;
- }
- call = Runtime::make_call(code, loc, 2, nil_arg, arg);
- }
- break;
-
- default:
- {
- Type* arg_type = Type::make_array_type(type, NULL);
- Slice_construction_expression* sce =
- Expression::make_slice_composite_literal(arg_type, this->exprs_,
- loc);
- sce->set_storage_does_not_escape();
- call = Runtime::make_call(Runtime::CONCATSTRINGS, loc, 2, nil_arg,
- sce);
- }
- break;
+ // Mark string([]byte) operands to reuse the backing store.
+ // runtime.concatstrings does not keep the reference.
+ //
+ // Note: in the gc runtime, if all but one inputs are empty,
+ // concatstrings returns the only nonempty input without copy.
+ // So it is not safe to reuse the backing store if it is a
+ // string([]byte) conversion. So the gc compiler does the
+ // no-copy optimization only when there is at least one
+ // constant nonempty input. Currently the gccgo runtime
+ // doesn't do this, so we don't do the check.
+ for (Expression_list::iterator p = this->exprs_->begin();
+ p != this->exprs_->end();
+ ++p)
+ {
+ Type_conversion_expression* tce = (*p)->conversion_expression();
+ if (tce != NULL)
+ tce->set_no_copy(true);
}
+ Expression* buf = NULL;
+ Node* n = Node::make_node(this);
+ if ((n->encoding() & ESCAPE_MASK) == Node::ESCAPE_NONE)
+ {
+ size_t size = 0;
+ for (Expression_list::iterator p = this->exprs_->begin();
+ p != this->exprs_->end();
+ ++p)
+ {
+ std::string s;
+ if ((*p)->string_constant_value(&s))
+ size += s.length();
+ }
+ // Make a buffer on stack if the result does not escape.
+ // But don't do this if we know it won't fit.
+ if (size < (size_t)tmp_string_buf_size)
+ {
+ Type* byte_type = Type::lookup_integer_type("uint8");
+ Expression* buflen =
+ Expression::make_integer_ul(tmp_string_buf_size, NULL, loc);
+ Expression::make_integer_ul(tmp_string_buf_size, NULL, loc);
+ Type* array_type = Type::make_array_type(byte_type, buflen);
+ buf = Expression::make_allocation(array_type, loc);
+ buf->allocation_expression()->set_allocate_on_stack();
+ buf->allocation_expression()->set_no_zero();
+ }
+ }
+ if (buf == NULL)
+ buf = Expression::make_nil(loc);
+ go_assert(this->exprs_->size() > 1);
+ Expression* len =
+ Expression::make_integer_ul(this->exprs_->size(), NULL, loc);
+ Array_type* array_type = Type::make_array_type(type, len);
+ array_type->set_is_array_incomparable();
+ Expression* array =
+ Expression::make_array_composite_literal(array_type, this->exprs_,
+ loc);
+ Temporary_statement* ts =
+ Statement::make_temporary(array_type, array, loc);
+ inserter->insert(ts);
+ Expression* ref = Expression::make_temporary_reference(ts, loc);
+ ref = Expression::make_unary(OPERATOR_AND, ref, loc);
+ Expression* call =
+ Runtime::make_call(Runtime::CONCATSTRINGS, loc, 3, buf,
+ ref, len->copy());
return Expression::make_cast(type, call, loc);
}
@@ -7769,63 +8134,33 @@ Builtin_call_expression::do_lower(Gogo*, Named_object* function,
case BUILTIN_DELETE:
{
- // Lower to a runtime function call.
- const Expression_list* args = this->args();
- if (args == NULL || args->size() < 2)
- this->report_error(_("not enough arguments"));
- else if (args->size() > 2)
- this->report_error(_("too many arguments"));
- else if (args->front()->type()->map_type() == NULL)
- this->report_error(_("argument 1 must be a map"));
- else
- {
- // Since this function returns no value it must appear in
- // a statement by itself, so we don't have to worry about
- // order of evaluation of values around it. Evaluate the
- // map first to get order of evaluation right.
- Map_type* mt = args->front()->type()->map_type();
- Temporary_statement* map_temp =
- Statement::make_temporary(mt, args->front(), loc);
- inserter->insert(map_temp);
-
- Temporary_statement* key_temp =
- Statement::make_temporary(mt->key_type(), args->back(), loc);
- inserter->insert(key_temp);
-
- Expression* e1 = Expression::make_type_descriptor(mt, loc);
- Expression* e2 = Expression::make_temporary_reference(map_temp,
- loc);
- Expression* e3 = Expression::make_temporary_reference(key_temp,
- loc);
-
- // If the call to delete is deferred, and is in a loop,
- // then the loop will only have a single instance of the
- // temporary variable. Passing the address of the
- // temporary variable here means that the deferred call
- // will see the last value in the loop, not the current
- // value. So for this unusual case copy the value into
- // the heap.
- if (!this->is_deferred())
- e3 = Expression::make_unary(OPERATOR_AND, e3, loc);
- else
- {
- Expression* a = Expression::make_allocation(mt->key_type(),
- loc);
- Temporary_statement* atemp =
- Statement::make_temporary(NULL, a, loc);
- inserter->insert(atemp);
-
- a = Expression::make_temporary_reference(atemp, loc);
- a = Expression::make_dereference(a, NIL_CHECK_NOT_NEEDED, loc);
- Statement* s = Statement::make_assignment(a, e3, loc);
- inserter->insert(s);
-
- e3 = Expression::make_temporary_reference(atemp, loc);
- }
-
- return Runtime::make_call(Runtime::MAPDELETE, this->location(),
- 3, e1, e2, e3);
- }
+ const Expression_list* args = this->args();
+ if (args == NULL || args->size() < 2)
+ this->report_error(_("not enough arguments"));
+ else if (args->size() > 2)
+ this->report_error(_("too many arguments"));
+ else if (args->front()->type()->map_type() == NULL)
+ this->report_error(_("argument 1 must be a map"));
+ else
+ {
+ Type* key_type =
+ args->front()->type()->map_type()->key_type();
+ Expression_list::iterator pa = this->args()->begin();
+ pa++;
+ Type* arg_type = (*pa)->type();
+ std::string reason;
+ if (!Type::are_assignable(key_type, arg_type, &reason))
+ {
+ if (reason.empty())
+ go_error_at(loc, "argument 2 has incompatible type");
+ else
+ go_error_at(loc, "argument 2 has incompatible type (%s)",
+ reason.c_str());
+ this->set_is_error();
+ }
+ else if (!Type::are_identical(key_type, arg_type, 0, NULL))
+ *pa = Expression::make_cast(key_type, *pa, loc);
+ }
}
break;
@@ -7861,6 +8196,12 @@ Expression*
Builtin_call_expression::do_flatten(Gogo* gogo, Named_object* function,
Statement_inserter* inserter)
{
+ if (this->is_error_expression())
+ {
+ go_assert(saw_errors());
+ return this;
+ }
+
Location loc = this->location();
switch (this->code_)
@@ -8004,6 +8345,96 @@ Builtin_call_expression::do_flatten(Gogo* gogo, Named_object* function,
}
}
break;
+
+ case BUILTIN_DELETE:
+ {
+ // Lower to a runtime function call.
+ const Expression_list* args = this->args();
+
+ // Since this function returns no value it must appear in
+ // a statement by itself, so we don't have to worry about
+ // order of evaluation of values around it. Evaluate the
+ // map first to get order of evaluation right.
+ Map_type* mt = args->front()->type()->map_type();
+ Temporary_statement* map_temp =
+ Statement::make_temporary(mt, args->front(), loc);
+ inserter->insert(map_temp);
+
+ Temporary_statement* key_temp =
+ Statement::make_temporary(mt->key_type(), args->back(), loc);
+ inserter->insert(key_temp);
+
+ Expression* e1 = Expression::make_type_descriptor(mt, loc);
+ Expression* e2 = Expression::make_temporary_reference(map_temp,
+ loc);
+ Expression* e3 = Expression::make_temporary_reference(key_temp,
+ loc);
+
+ Runtime::Function code;
+ switch (mt->algorithm(gogo))
+ {
+ case Map_type::MAP_ALG_FAST32:
+ case Map_type::MAP_ALG_FAST32PTR:
+ {
+ code = Runtime::MAPDELETE_FAST32;
+ Type* uint32_type = Type::lookup_integer_type("uint32");
+ Type* uint32_ptr_type = Type::make_pointer_type(uint32_type);
+ e3 = Expression::make_unary(OPERATOR_AND, e3, loc);
+ e3 = Expression::make_unsafe_cast(uint32_ptr_type, e3,
+ loc);
+ e3 = Expression::make_dereference(e3,
+ Expression::NIL_CHECK_NOT_NEEDED,
+ loc);
+ break;
+ }
+ case Map_type::MAP_ALG_FAST64:
+ case Map_type::MAP_ALG_FAST64PTR:
+ {
+ code = Runtime::MAPDELETE_FAST64;
+ Type* uint64_type = Type::lookup_integer_type("uint64");
+ Type* uint64_ptr_type = Type::make_pointer_type(uint64_type);
+ e3 = Expression::make_unary(OPERATOR_AND, e3, loc);
+ e3 = Expression::make_unsafe_cast(uint64_ptr_type, e3,
+ loc);
+ e3 = Expression::make_dereference(e3,
+ Expression::NIL_CHECK_NOT_NEEDED,
+ loc);
+ break;
+ }
+ case Map_type::MAP_ALG_FASTSTR:
+ code = Runtime::MAPDELETE_FASTSTR;
+ break;
+ default:
+ code = Runtime::MAPDELETE;
+
+ // If the call to delete is deferred, and is in a loop,
+ // then the loop will only have a single instance of the
+ // temporary variable. Passing the address of the
+ // temporary variable here means that the deferred call
+ // will see the last value in the loop, not the current
+ // value. So for this unusual case copy the value into
+ // the heap.
+ if (!this->is_deferred())
+ e3 = Expression::make_unary(OPERATOR_AND, e3, loc);
+ else
+ {
+ Expression* a = Expression::make_allocation(mt->key_type(),
+ loc);
+ Temporary_statement* atemp =
+ Statement::make_temporary(NULL, a, loc);
+ inserter->insert(atemp);
+
+ a = Expression::make_temporary_reference(atemp, loc);
+ a = Expression::make_dereference(a, NIL_CHECK_NOT_NEEDED, loc);
+ Statement* s = Statement::make_assignment(a, e3, loc);
+ inserter->insert(s);
+
+ e3 = Expression::make_temporary_reference(atemp, loc);
+ }
+ }
+
+ return Runtime::make_call(code, loc, 3, e1, e2, e3);
+ }
}
return this;
@@ -8036,7 +8467,7 @@ Builtin_call_expression::lower_make(Statement_inserter* inserter)
if (!type->in_heap())
go_error_at(first_arg->location(),
- "can't make slice of go:notinheap type");
+ "cannot make slice of go:notinheap type");
bool is_slice = false;
bool is_map = false;
@@ -8261,23 +8692,87 @@ Builtin_call_expression::flatten_append(Gogo* gogo, Named_object* function,
Temporary_statement* l2tmp = NULL;
Expression_list* add = NULL;
Expression* len2;
+ Call_expression* makecall = NULL;
if (this->is_varargs())
{
go_assert(args->size() == 2);
- // s2tmp := s2
- s2tmp = Statement::make_temporary(NULL, args->back(), loc);
- inserter->insert(s2tmp);
+ std::pair<Call_expression*, Temporary_statement*> p =
+ Expression::find_makeslice_call(args->back());
+ makecall = p.first;
+ if (makecall != NULL)
+ {
+ // We are handling
+ // append(s, make([]T, len[, cap])...))
+ // which has already been lowered to
+ // append(s, runtime.makeslice(T, len, cap)).
+ // We will optimize this to directly zeroing the tail,
+ // instead of allocating a new slice then copy.
+
+ // Retrieve the length. Cannot reference s2 as we will remove
+ // the makeslice call.
+ Expression* len_arg = makecall->args()->at(1);
+ len_arg = Expression::make_cast(int_type, len_arg, loc);
+ l2tmp = Statement::make_temporary(int_type, len_arg, loc);
+ inserter->insert(l2tmp);
+
+ Expression* cap_arg = makecall->args()->at(2);
+ cap_arg = Expression::make_cast(int_type, cap_arg, loc);
+ Temporary_statement* c2tmp =
+ Statement::make_temporary(int_type, cap_arg, loc);
+ inserter->insert(c2tmp);
+
+ // Check bad len/cap here.
+ // if len2 < 0 { panicmakeslicelen(); }
+ len2 = Expression::make_temporary_reference(l2tmp, loc);
+ Expression* zero = Expression::make_integer_ul(0, int_type, loc);
+ Expression* cond = Expression::make_binary(OPERATOR_LT, len2,
+ zero, loc);
+ Expression* arg =
+ Expression::make_integer_ul(RUNTIME_ERROR_MAKE_SLICE_LEN_OUT_OF_BOUNDS,
+ NULL, loc);
+ Expression* call = Runtime::make_call(Runtime::RUNTIME_ERROR,
+ loc, 1, arg);
+ cond = Expression::make_conditional(cond, call, zero->copy(), loc);
+ gogo->lower_expression(function, inserter, &cond);
+ gogo->flatten_expression(function, inserter, &cond);
+ Statement* s = Statement::make_statement(cond, false);
+ inserter->insert(s);
+
+ // if cap2 < 0 { panicmakeslicecap(); }
+ Expression* cap2 = Expression::make_temporary_reference(c2tmp, loc);
+ cond = Expression::make_binary(OPERATOR_LT, cap2,
+ zero->copy(), loc);
+ arg = Expression::make_integer_ul(RUNTIME_ERROR_MAKE_SLICE_CAP_OUT_OF_BOUNDS,
+ NULL, loc);
+ call = Runtime::make_call(Runtime::RUNTIME_ERROR, loc, 1, arg);
+ cond = Expression::make_conditional(cond, call, zero->copy(), loc);
+ gogo->lower_expression(function, inserter, &cond);
+ gogo->flatten_expression(function, inserter, &cond);
+ s = Statement::make_statement(cond, false);
+ inserter->insert(s);
+
+ // Remove the original makeslice call.
+ Temporary_statement* ts = p.second;
+ if (ts != NULL && ts->uses() == 1)
+ ts->set_init(Expression::make_nil(loc));
+ }
+ else
+ {
+ // s2tmp := s2
+ s2tmp = Statement::make_temporary(NULL, args->back(), loc);
+ inserter->insert(s2tmp);
- // l2tmp := len(s2tmp)
- lenref = Expression::make_func_reference(lenfn, NULL, loc);
- call_args = new Expression_list();
- call_args->push_back(Expression::make_temporary_reference(s2tmp, loc));
- len = Expression::make_call(lenref, call_args, false, loc);
- gogo->lower_expression(function, inserter, &len);
- gogo->flatten_expression(function, inserter, &len);
- l2tmp = Statement::make_temporary(int_type, len, loc);
- inserter->insert(l2tmp);
+ // l2tmp := len(s2tmp)
+ lenref = Expression::make_func_reference(lenfn, NULL, loc);
+ call_args = new Expression_list();
+ call_args->push_back(Expression::make_temporary_reference(s2tmp, loc));
+ len = Expression::make_call(lenref, call_args, false, loc);
+ gogo->lower_expression(function, inserter, &len);
+ gogo->flatten_expression(function, inserter, &len);
+ l2tmp = Statement::make_temporary(int_type, len, loc);
+ inserter->insert(l2tmp);
+ }
// len2 = l2tmp
len2 = Expression::make_temporary_reference(l2tmp, loc);
@@ -8397,52 +8892,98 @@ Builtin_call_expression::flatten_append(Gogo* gogo, Named_object* function,
inserter->insert(assign);
}
+ Type* uintptr_type = Type::lookup_integer_type("uintptr");
+
if (this->is_varargs())
{
- if (element_type->has_pointer())
- {
- // copy(s1tmp[l1tmp:], s2tmp)
- a1 = Expression::make_temporary_reference(s1tmp, loc);
- ref = Expression::make_temporary_reference(l1tmp, loc);
- Expression* nil = Expression::make_nil(loc);
- a1 = Expression::make_array_index(a1, ref, nil, NULL, loc);
- a1->array_index_expression()->set_needs_bounds_check(false);
-
- a2 = Expression::make_temporary_reference(s2tmp, loc);
-
- Named_object* copyfn = gogo->lookup_global("copy");
- Expression* copyref = Expression::make_func_reference(copyfn, NULL, loc);
- call_args = new Expression_list();
- call_args->push_back(a1);
- call_args->push_back(a2);
- call = Expression::make_call(copyref, call_args, false, loc);
- }
- else
+ if (makecall != NULL)
{
- // memmove(&s1tmp[l1tmp], s2tmp.ptr, l2tmp*sizeof(elem))
+ // memclr(&s1tmp[l1tmp], l2tmp*sizeof(elem))
a1 = Expression::make_temporary_reference(s1tmp, loc);
ref = Expression::make_temporary_reference(l1tmp, loc);
a1 = Expression::make_array_index(a1, ref, NULL, NULL, loc);
a1->array_index_expression()->set_needs_bounds_check(false);
a1 = Expression::make_unary(OPERATOR_AND, a1, loc);
- a2 = Expression::make_temporary_reference(s2tmp, loc);
- a2 = (a2->type()->is_string_type()
- ? Expression::make_string_info(a2,
- STRING_INFO_DATA,
- loc)
- : Expression::make_slice_info(a2,
- SLICE_INFO_VALUE_POINTER,
- loc));
-
- Type* uintptr_type = Type::lookup_integer_type("uintptr");
ref = Expression::make_temporary_reference(l2tmp, loc);
ref = Expression::make_cast(uintptr_type, ref, loc);
- a3 = Expression::make_type_info(element_type, TYPE_INFO_SIZE);
- a3 = Expression::make_binary(OPERATOR_MULT, a3, ref, loc);
+ a2 = Expression::make_type_info(element_type, TYPE_INFO_SIZE);
+ a2 = Expression::make_binary(OPERATOR_MULT, a2, ref, loc);
+
+ if (element_type->has_pointer())
+ call = Runtime::make_call(Runtime::MEMCLRHASPTR, loc, 2, a1, a2);
+ else
+ {
+ Type* int32_type = Type::lookup_integer_type("int32");
+ Expression* zero =
+ Expression::make_integer_ul(0, int32_type, loc);
+ call = Runtime::make_call(Runtime::BUILTIN_MEMSET, loc, 3, a1,
+ zero, a2);
+ }
- call = Runtime::make_call(Runtime::BUILTIN_MEMMOVE, loc, 3,
- a1, a2, a3);
+ if (element_type->has_pointer())
+ {
+ // For a slice containing pointers, growslice already zeroed
+ // the memory. We only need to zero in non-growing case.
+ // Note: growslice does not zero the memory in non-pointer case.
+ Expression* left =
+ Expression::make_temporary_reference(ntmp, loc);
+ left = Expression::make_cast(uint_type, left, loc);
+ Expression* right =
+ Expression::make_temporary_reference(c1tmp, loc);
+ right = Expression::make_cast(uint_type, right, loc);
+ Expression* cond =
+ Expression::make_binary(OPERATOR_GT, left, right, loc);
+ Expression* zero = Expression::make_integer_ul(0, int_type, loc);
+ call = Expression::make_conditional(cond, call, zero, loc);
+ }
+ }
+ else
+ {
+ if (element_type->has_pointer())
+ {
+ // copy(s1tmp[l1tmp:], s2tmp)
+ a1 = Expression::make_temporary_reference(s1tmp, loc);
+ ref = Expression::make_temporary_reference(l1tmp, loc);
+ Expression* nil = Expression::make_nil(loc);
+ a1 = Expression::make_array_index(a1, ref, nil, NULL, loc);
+ a1->array_index_expression()->set_needs_bounds_check(false);
+
+ a2 = Expression::make_temporary_reference(s2tmp, loc);
+
+ Named_object* copyfn = gogo->lookup_global("copy");
+ Expression* copyref = Expression::make_func_reference(copyfn, NULL, loc);
+ call_args = new Expression_list();
+ call_args->push_back(a1);
+ call_args->push_back(a2);
+ call = Expression::make_call(copyref, call_args, false, loc);
+ }
+ else
+ {
+ // memmove(&s1tmp[l1tmp], s2tmp.ptr, l2tmp*sizeof(elem))
+ a1 = Expression::make_temporary_reference(s1tmp, loc);
+ ref = Expression::make_temporary_reference(l1tmp, loc);
+ a1 = Expression::make_array_index(a1, ref, NULL, NULL, loc);
+ a1->array_index_expression()->set_needs_bounds_check(false);
+ a1 = Expression::make_unary(OPERATOR_AND, a1, loc);
+
+ a2 = Expression::make_temporary_reference(s2tmp, loc);
+ a2 = (a2->type()->is_string_type()
+ ? Expression::make_string_info(a2,
+ STRING_INFO_DATA,
+ loc)
+ : Expression::make_slice_info(a2,
+ SLICE_INFO_VALUE_POINTER,
+ loc));
+
+ ref = Expression::make_temporary_reference(l2tmp, loc);
+ ref = Expression::make_cast(uintptr_type, ref, loc);
+ a3 = Expression::make_type_info(element_type, TYPE_INFO_SIZE);
+ a3 = Expression::make_binary(OPERATOR_MULT, a3, ref, loc);
+
+ call = Runtime::make_call(Runtime::BUILTIN_MEMMOVE, loc, 3,
+ a1, a2, a3);
+ }
}
gogo->lower_expression(function, inserter, &call);
gogo->flatten_expression(function, inserter, &call);
@@ -8466,6 +9007,10 @@ Builtin_call_expression::flatten_append(Gogo* gogo, Named_object* function,
lhs->array_index_expression()->set_needs_bounds_check(false);
gogo->lower_expression(function, inserter, &lhs);
gogo->flatten_expression(function, inserter, &lhs);
+ Expression* elem = *pa;
+ if (!Type::are_identical(element_type, elem->type(), 0, NULL)
+ && element_type->interface_type() != NULL)
+ elem = Expression::make_cast(element_type, elem, loc);
// The flatten pass runs after the write barrier pass, so we
// need to insert a write barrier here if necessary.
// However, if ASSIGN_LHS is not NULL, we have been called
@@ -8473,12 +9018,12 @@ Builtin_call_expression::flatten_append(Gogo* gogo, Named_object* function,
Statement* assign;
if (assign_lhs != NULL
|| !gogo->assign_needs_write_barrier(lhs))
- assign = Statement::make_assignment(lhs, *pa, loc);
+ assign = Statement::make_assignment(lhs, elem, loc);
else
{
Function* f = function == NULL ? NULL : function->func_value();
assign = gogo->assign_with_write_barrier(f, NULL, inserter,
- lhs, *pa, loc);
+ lhs, elem, loc);
}
inserter->insert(assign);
}
@@ -9307,7 +9852,7 @@ Builtin_call_expression::do_check_types(Gogo*)
{
if (this->code_ == BUILTIN_PRINT)
go_warning_at(this->location(), 0,
- "no arguments for builtin function %<%s%>",
+ "no arguments for built-in function %<%s%>",
(this->code_ == BUILTIN_PRINT
? "print"
: "println"));
@@ -9449,7 +9994,7 @@ Builtin_call_expression::do_check_types(Gogo*)
Type* element_type = slice_type->array_type()->element_type();
if (!element_type->in_heap())
go_error_at(args->front()->location(),
- "can't append to slice of go:notinheap type");
+ "cannot append to slice of go:notinheap type");
if (this->is_varargs())
{
if (!args->back()->type()->is_slice_type()
@@ -9840,7 +10385,7 @@ Builtin_call_expression::do_get_backend(Translate_context* context)
Type::make_empty_interface_type(Linemap::predeclared_location());
Expression* nil = Expression::make_nil(location);
- nil = Expression::convert_for_assignment(gogo, empty, nil, location);
+ nil = Expression::make_interface_value(empty, nil, nil, location);
// We need to handle a deferred call to recover specially,
// because it changes whether it can recover a panic or not.
@@ -9929,38 +10474,85 @@ void
Builtin_call_expression::do_export(Export_function_body* efb) const
{
Numeric_constant nc;
- if (!this->numeric_constant_value(&nc))
+ if (this->numeric_constant_value(&nc))
{
- go_error_at(this->location(), "value is not constant");
- return;
- }
+ if (nc.is_int())
+ {
+ mpz_t val;
+ nc.get_int(&val);
+ Integer_expression::export_integer(efb, val);
+ mpz_clear(val);
+ }
+ else if (nc.is_float())
+ {
+ mpfr_t fval;
+ nc.get_float(&fval);
+ Float_expression::export_float(efb, fval);
+ mpfr_clear(fval);
+ }
+ else if (nc.is_complex())
+ {
+ mpc_t cval;
+ nc.get_complex(&cval);
+ Complex_expression::export_complex(efb, cval);
+ mpc_clear(cval);
+ }
+ else
+ go_unreachable();
- if (nc.is_int())
- {
- mpz_t val;
- nc.get_int(&val);
- Integer_expression::export_integer(efb, val);
- mpz_clear(val);
+ // A trailing space lets us reliably identify the end of the number.
+ efb->write_c_string(" ");
}
- else if (nc.is_float())
- {
- mpfr_t fval;
- nc.get_float(&fval);
- Float_expression::export_float(efb, fval);
- mpfr_clear(fval);
- }
- else if (nc.is_complex())
+ else
{
- mpc_t cval;
- nc.get_complex(&cval);
- Complex_expression::export_complex(efb, cval);
- mpc_clear(cval);
+ const char *s = NULL;
+ switch (this->code_)
+ {
+ default:
+ go_unreachable();
+ case BUILTIN_APPEND:
+ s = "append";
+ break;
+ case BUILTIN_COPY:
+ s = "copy";
+ break;
+ case BUILTIN_LEN:
+ s = "len";
+ break;
+ case BUILTIN_CAP:
+ s = "cap";
+ break;
+ case BUILTIN_DELETE:
+ s = "delete";
+ break;
+ case BUILTIN_PRINT:
+ s = "print";
+ break;
+ case BUILTIN_PRINTLN:
+ s = "println";
+ break;
+ case BUILTIN_PANIC:
+ s = "panic";
+ break;
+ case BUILTIN_RECOVER:
+ s = "recover";
+ break;
+ case BUILTIN_CLOSE:
+ s = "close";
+ break;
+ case BUILTIN_REAL:
+ s = "real";
+ break;
+ case BUILTIN_IMAG:
+ s = "imag";
+ break;
+ case BUILTIN_COMPLEX:
+ s = "complex";
+ break;
+ }
+ efb->write_c_string(s);
+ this->export_arguments(efb);
}
- else
- go_unreachable();
-
- // A trailing space lets us reliably identify the end of the number.
- efb->write_c_string(" ");
}
// Class Call_expression.
@@ -10232,42 +10824,6 @@ Call_expression::do_lower(Gogo* gogo, Named_object* function,
bme->location());
}
- // Handle a couple of special runtime functions. In the runtime
- // package, getcallerpc returns the PC of the caller, and
- // getcallersp returns the frame pointer of the caller. Implement
- // these by turning them into calls to GCC builtin functions. We
- // could implement them in normal code, but then we would have to
- // explicitly unwind the stack. These functions are intended to be
- // efficient. Note that this technique obviously only works for
- // direct calls, but that is the only way they are used.
- if (gogo->compiling_runtime() && gogo->package_name() == "runtime")
- {
- Func_expression* fe = this->fn_->func_expression();
- if (fe != NULL
- && fe->named_object()->is_function_declaration()
- && fe->named_object()->package() == NULL)
- {
- std::string n = Gogo::unpack_hidden_name(fe->named_object()->name());
- if ((this->args_ == NULL || this->args_->size() == 0)
- && n == "getcallerpc")
- {
- static Named_object* builtin_return_address;
- int arg = 0;
- return this->lower_to_builtin(&builtin_return_address,
- "__builtin_return_address",
- &arg);
- }
- else if ((this->args_ == NULL || this->args_->size() == 0)
- && n == "getcallersp")
- {
- static Named_object* builtin_dwarf_cfa;
- return this->lower_to_builtin(&builtin_dwarf_cfa,
- "__builtin_dwarf_cfa",
- NULL);
- }
- }
- }
-
// If this is a call to an imported function for which we have an
// inlinable function body, add it to the list of functions to give
// to the backend as inlining opportunities.
@@ -10381,31 +10937,6 @@ Call_expression::lower_varargs(Gogo* gogo, Named_object* function,
this->varargs_are_lowered_ = true;
}
-// Return a call to __builtin_return_address or __builtin_dwarf_cfa.
-
-Expression*
-Call_expression::lower_to_builtin(Named_object** pno, const char* name,
- int* arg)
-{
- if (*pno == NULL)
- *pno = Gogo::declare_builtin_rf_address(name, arg != NULL);
-
- Location loc = this->location();
-
- Expression* fn = Expression::make_func_reference(*pno, NULL, loc);
- Expression_list *args = new Expression_list();
- if (arg != NULL)
- {
- Expression* a = Expression::make_integer_ul(*arg, NULL, loc);
- args->push_back(a);
- }
- Expression* call = Expression::make_call(fn, args, false, loc);
-
- // The builtin functions return void*, but the Go functions return uintptr.
- Type* uintptr_type = Type::lookup_integer_type("uintptr");
- return Expression::make_cast(uintptr_type, call, loc);
-}
-
// Flatten a call with multiple results into a temporary.
Expression*
@@ -10471,9 +11002,644 @@ Call_expression::do_flatten(Gogo* gogo, Named_object*,
this->args_ = args;
}
+ // Lower to compiler intrinsic if possible.
+ Func_expression* fe = this->fn_->func_expression();
+ if (!this->is_concurrent_ && !this->is_deferred_
+ && fe != NULL
+ && (fe->named_object()->is_function_declaration()
+ || fe->named_object()->is_function()))
+ {
+ Expression* ret = this->intrinsify(gogo, inserter);
+ if (ret != NULL)
+ return ret;
+ }
+
return this;
}
+// Lower a call to a compiler intrinsic if possible.
+// Returns NULL if it is not an intrinsic.
+
+Expression*
+Call_expression::intrinsify(Gogo* gogo,
+ Statement_inserter* inserter)
+{
+ Func_expression* fe = this->fn_->func_expression();
+ Named_object* no = fe->named_object();
+ std::string name = Gogo::unpack_hidden_name(no->name());
+ std::string package = (no->package() != NULL
+ ? no->package()->pkgpath()
+ : gogo->pkgpath());
+ Location loc = this->location();
+
+ Type* int_type = Type::lookup_integer_type("int");
+ Type* int32_type = Type::lookup_integer_type("int32");
+ Type* int64_type = Type::lookup_integer_type("int64");
+ Type* uint_type = Type::lookup_integer_type("uint");
+ Type* uint32_type = Type::lookup_integer_type("uint32");
+ Type* uint64_type = Type::lookup_integer_type("uint64");
+ Type* uintptr_type = Type::lookup_integer_type("uintptr");
+ Type* pointer_type = Type::make_pointer_type(Type::make_void_type());
+
+ int int_size = int_type->named_type()->real_type()->integer_type()->bits() / 8;
+ int ptr_size = uintptr_type->named_type()->real_type()->integer_type()->bits() / 8;
+
+ if (package == "sync/atomic")
+ {
+ // sync/atomic functions and runtime/internal/atomic functions
+ // are very similar. In order not to duplicate code, we just
+ // redirect to the latter and let the code below to handle them.
+ // In case there is no equivalent functions (slight variance
+ // in types), we just make an artificial name (begin with '$').
+ // Note: no StorePointer, SwapPointer, and CompareAndSwapPointer,
+ // as they need write barriers.
+ if (name == "LoadInt32")
+ name = "$Loadint32";
+ else if (name == "LoadInt64")
+ name = "Loadint64";
+ else if (name == "LoadUint32")
+ name = "Load";
+ else if (name == "LoadUint64")
+ name = "Load64";
+ else if (name == "LoadUintptr")
+ name = "Loaduintptr";
+ else if (name == "LoadPointer")
+ name = "Loadp";
+ else if (name == "StoreInt32")
+ name = "$Storeint32";
+ else if (name == "StoreInt64")
+ name = "$Storeint64";
+ else if (name == "StoreUint32")
+ name = "Store";
+ else if (name == "StoreUint64")
+ name = "Store64";
+ else if (name == "StoreUintptr")
+ name = "Storeuintptr";
+ else if (name == "AddInt32")
+ name = "$Xaddint32";
+ else if (name == "AddInt64")
+ name = "Xaddint64";
+ else if (name == "AddUint32")
+ name = "Xadd";
+ else if (name == "AddUint64")
+ name = "Xadd64";
+ else if (name == "AddUintptr")
+ name = "Xadduintptr";
+ else if (name == "SwapInt32")
+ name = "$Xchgint32";
+ else if (name == "SwapInt64")
+ name = "$Xchgint64";
+ else if (name == "SwapUint32")
+ name = "Xchg";
+ else if (name == "SwapUint64")
+ name = "Xchg64";
+ else if (name == "SwapUintptr")
+ name = "Xchguintptr";
+ else if (name == "CompareAndSwapInt32")
+ name = "$Casint32";
+ else if (name == "CompareAndSwapInt64")
+ name = "$Casint64";
+ else if (name == "CompareAndSwapUint32")
+ name = "Cas";
+ else if (name == "CompareAndSwapUint64")
+ name = "Cas64";
+ else if (name == "CompareAndSwapUintptr")
+ name = "Casuintptr";
+ else
+ return NULL;
+
+ package = "runtime/internal/atomic";
+ }
+
+ if (package == "runtime/internal/sys")
+ {
+ // runtime/internal/sys functions and math/bits functions
+ // are very similar. In order not to duplicate code, we just
+ // redirect to the latter and let the code below to handle them.
+ if (name == "Bswap32")
+ name = "ReverseBytes32";
+ else if (name == "Bswap64")
+ name = "ReverseBytes64";
+ else if (name == "Ctz32")
+ name = "TrailingZeros32";
+ else if (name == "Ctz64")
+ name = "TrailingZeros64";
+ else
+ return NULL;
+
+ package = "math/bits";
+ }
+
+ if (package == "runtime")
+ {
+ // Handle a couple of special runtime functions. In the runtime
+ // package, getcallerpc returns the PC of the caller, and
+ // getcallersp returns the frame pointer of the caller. Implement
+ // these by turning them into calls to GCC builtin functions. We
+ // could implement them in normal code, but then we would have to
+ // explicitly unwind the stack. These functions are intended to be
+ // efficient. Note that this technique obviously only works for
+ // direct calls, but that is the only way they are used.
+ if (name == "getcallerpc"
+ && (this->args_ == NULL || this->args_->size() == 0))
+ {
+ Expression* arg = Expression::make_integer_ul(0, uint32_type, loc);
+ Expression* call =
+ Runtime::make_call(Runtime::BUILTIN_RETURN_ADDRESS, loc,
+ 1, arg);
+ // The builtin functions return void*, but the Go functions return uintptr.
+ return Expression::make_cast(uintptr_type, call, loc);
+ }
+ else if (name == "getcallersp"
+ && (this->args_ == NULL || this->args_->size() == 0))
+
+ {
+ Expression* call =
+ Runtime::make_call(Runtime::BUILTIN_DWARF_CFA, loc, 0);
+ // The builtin functions return void*, but the Go functions return uintptr.
+ return Expression::make_cast(uintptr_type, call, loc);
+ }
+ }
+ else if (package == "math/bits")
+ {
+ if ((name == "ReverseBytes16" || name == "ReverseBytes32"
+ || name == "ReverseBytes64" || name == "ReverseBytes")
+ && this->args_ != NULL && this->args_->size() == 1)
+ {
+ Runtime::Function code;
+ if (name == "ReverseBytes16")
+ code = Runtime::BUILTIN_BSWAP16;
+ else if (name == "ReverseBytes32")
+ code = Runtime::BUILTIN_BSWAP32;
+ else if (name == "ReverseBytes64")
+ code = Runtime::BUILTIN_BSWAP64;
+ else if (name == "ReverseBytes")
+ code = (int_size == 8 ? Runtime::BUILTIN_BSWAP64 : Runtime::BUILTIN_BSWAP32);
+ else
+ go_unreachable();
+ Expression* arg = this->args_->front();
+ Expression* call = Runtime::make_call(code, loc, 1, arg);
+ if (name == "ReverseBytes")
+ return Expression::make_cast(uint_type, call, loc);
+ return call;
+ }
+ else if ((name == "TrailingZeros8" || name == "TrailingZeros16")
+ && this->args_ != NULL && this->args_->size() == 1)
+ {
+ // GCC does not have a ctz8 or ctz16 intrinsic. We do
+ // ctz32(0x100 | arg) or ctz32(0x10000 | arg).
+ Expression* arg = this->args_->front();
+ arg = Expression::make_cast(uint32_type, arg, loc);
+ unsigned long mask = (name == "TrailingZeros8" ? 0x100 : 0x10000);
+ Expression* c = Expression::make_integer_ul(mask, uint32_type, loc);
+ arg = Expression::make_binary(OPERATOR_OR, arg, c, loc);
+ Expression* call = Runtime::make_call(Runtime::BUILTIN_CTZ, loc, 1, arg);
+ return Expression::make_cast(int_type, call, loc);
+ }
+ else if ((name == "TrailingZeros32"
+ || (name == "TrailingZeros" && int_size == 4))
+ && this->args_ != NULL && this->args_->size() == 1)
+ {
+ Expression* arg = this->args_->front();
+ if (!arg->is_variable())
+ {
+ Temporary_statement* ts = Statement::make_temporary(uint32_type, arg, loc);
+ inserter->insert(ts);
+ arg = Expression::make_temporary_reference(ts, loc);
+ }
+ // arg == 0 ? 32 : __builtin_ctz(arg)
+ Expression* zero = Expression::make_integer_ul(0, uint32_type, loc);
+ Expression* cmp = Expression::make_binary(OPERATOR_EQEQ, arg, zero, loc);
+ Expression* c32 = Expression::make_integer_ul(32, int_type, loc);
+ Expression* call = Runtime::make_call(Runtime::BUILTIN_CTZ, loc, 1, arg->copy());
+ call = Expression::make_cast(int_type, call, loc);
+ return Expression::make_conditional(cmp, c32, call, loc);
+ }
+ else if ((name == "TrailingZeros64"
+ || (name == "TrailingZeros" && int_size == 8))
+ && this->args_ != NULL && this->args_->size() == 1)
+ {
+ Expression* arg = this->args_->front();
+ if (!arg->is_variable())
+ {
+ Temporary_statement* ts = Statement::make_temporary(uint64_type, arg, loc);
+ inserter->insert(ts);
+ arg = Expression::make_temporary_reference(ts, loc);
+ }
+ // arg == 0 ? 64 : __builtin_ctzll(arg)
+ Expression* zero = Expression::make_integer_ul(0, uint64_type, loc);
+ Expression* cmp = Expression::make_binary(OPERATOR_EQEQ, arg, zero, loc);
+ Expression* c64 = Expression::make_integer_ul(64, int_type, loc);
+ Expression* call = Runtime::make_call(Runtime::BUILTIN_CTZLL, loc, 1, arg->copy());
+ call = Expression::make_cast(int_type, call, loc);
+ return Expression::make_conditional(cmp, c64, call, loc);
+ }
+ else if ((name == "LeadingZeros8" || name == "LeadingZeros16"
+ || name == "Len8" || name == "Len16")
+ && this->args_ != NULL && this->args_->size() == 1)
+ {
+ // GCC does not have a clz8 ir clz16 intrinsic. We do
+ // clz32(arg<<24 | 0xffffff) or clz32(arg<<16 | 0xffff).
+ Expression* arg = this->args_->front();
+ arg = Expression::make_cast(uint32_type, arg, loc);
+ unsigned long shift =
+ ((name == "LeadingZeros8" || name == "Len8") ? 24 : 16);
+ Expression* c = Expression::make_integer_ul(shift, uint32_type, loc);
+ arg = Expression::make_binary(OPERATOR_LSHIFT, arg, c, loc);
+ unsigned long mask =
+ ((name == "LeadingZeros8" || name == "Len8") ? 0xffffff : 0xffff);
+ c = Expression::make_integer_ul(mask, uint32_type, loc);
+ arg = Expression::make_binary(OPERATOR_OR, arg, c, loc);
+ Expression* call = Runtime::make_call(Runtime::BUILTIN_CLZ, loc, 1, arg);
+ call = Expression::make_cast(int_type, call, loc);
+ // len = width - clz
+ if (name == "Len8")
+ {
+ c = Expression::make_integer_ul(8, int_type, loc);
+ return Expression::make_binary(OPERATOR_MINUS, c, call, loc);
+ }
+ else if (name == "Len16")
+ {
+ c = Expression::make_integer_ul(16, int_type, loc);
+ return Expression::make_binary(OPERATOR_MINUS, c, call, loc);
+ }
+ return call;
+ }
+ else if ((name == "LeadingZeros32" || name == "Len32"
+ || ((name == "LeadingZeros" || name == "Len") && int_size == 4))
+ && this->args_ != NULL && this->args_->size() == 1)
+ {
+ Expression* arg = this->args_->front();
+ if (!arg->is_variable())
+ {
+ Temporary_statement* ts = Statement::make_temporary(uint32_type, arg, loc);
+ inserter->insert(ts);
+ arg = Expression::make_temporary_reference(ts, loc);
+ }
+ // arg == 0 ? 32 : __builtin_clz(arg)
+ Expression* zero = Expression::make_integer_ul(0, uint32_type, loc);
+ Expression* cmp = Expression::make_binary(OPERATOR_EQEQ, arg, zero, loc);
+ Expression* c32 = Expression::make_integer_ul(32, int_type, loc);
+ Expression* call = Runtime::make_call(Runtime::BUILTIN_CLZ, loc, 1, arg->copy());
+ call = Expression::make_cast(int_type, call, loc);
+ Expression* cond = Expression::make_conditional(cmp, c32, call, loc);
+ // len = 32 - clz
+ if (name == "Len32" || name == "Len")
+ return Expression::make_binary(OPERATOR_MINUS, c32->copy(), cond, loc);
+ return cond;
+ }
+ else if ((name == "LeadingZeros64" || name == "Len64"
+ || ((name == "LeadingZeros" || name == "Len") && int_size == 8))
+ && this->args_ != NULL && this->args_->size() == 1)
+ {
+ Expression* arg = this->args_->front();
+ if (!arg->is_variable())
+ {
+ Temporary_statement* ts = Statement::make_temporary(uint64_type, arg, loc);
+ inserter->insert(ts);
+ arg = Expression::make_temporary_reference(ts, loc);
+ }
+ // arg == 0 ? 64 : __builtin_clzll(arg)
+ Expression* zero = Expression::make_integer_ul(0, uint64_type, loc);
+ Expression* cmp = Expression::make_binary(OPERATOR_EQEQ, arg, zero, loc);
+ Expression* c64 = Expression::make_integer_ul(64, int_type, loc);
+ Expression* call = Runtime::make_call(Runtime::BUILTIN_CLZLL, loc, 1, arg->copy());
+ call = Expression::make_cast(int_type, call, loc);
+ Expression* cond = Expression::make_conditional(cmp, c64, call, loc);
+ // len = 64 - clz
+ if (name == "Len64" || name == "Len")
+ return Expression::make_binary(OPERATOR_MINUS, c64->copy(), cond, loc);
+ return cond;
+ }
+ else if ((name == "OnesCount8" || name == "OnesCount16"
+ || name == "OnesCount32" || name == "OnesCount64"
+ || name == "OnesCount")
+ && this->args_ != NULL && this->args_->size() == 1)
+ {
+ Runtime::Function code;
+ if (name == "OnesCount64")
+ code = Runtime::BUILTIN_POPCOUNTLL;
+ else if (name == "OnesCount")
+ code = (int_size == 8 ? Runtime::BUILTIN_POPCOUNTLL : Runtime::BUILTIN_POPCOUNT);
+ else
+ code = Runtime::BUILTIN_POPCOUNT;
+ Expression* arg = this->args_->front();
+ Expression* call = Runtime::make_call(code, loc, 1, arg);
+ return Expression::make_cast(int_type, call, loc);
+ }
+ }
+ else if (package == "runtime/internal/atomic")
+ {
+ int memorder = __ATOMIC_SEQ_CST;
+
+ if ((name == "Load" || name == "Load64" || name == "Loadint64" || name == "Loadp"
+ || name == "Loaduint" || name == "Loaduintptr" || name == "LoadAcq"
+ || name == "$Loadint32")
+ && this->args_ != NULL && this->args_->size() == 1)
+ {
+ if (int_size < 8 && (name == "Load64" || name == "Loadint64"))
+ // On 32-bit architectures we need to check alignment.
+ // Not intrinsify for now.
+ return NULL;
+
+ Runtime::Function code;
+ Type* res_type;
+ if (name == "Load")
+ {
+ code = Runtime::ATOMIC_LOAD_4;
+ res_type = uint32_type;
+ }
+ else if (name == "Load64")
+ {
+ code = Runtime::ATOMIC_LOAD_8;
+ res_type = uint64_type;
+ }
+ else if (name == "$Loadint32")
+ {
+ code = Runtime::ATOMIC_LOAD_4;
+ res_type = int32_type;
+ }
+ else if (name == "Loadint64")
+ {
+ code = Runtime::ATOMIC_LOAD_8;
+ res_type = int64_type;
+ }
+ else if (name == "Loaduint")
+ {
+ code = (int_size == 8
+ ? Runtime::ATOMIC_LOAD_8
+ : Runtime::ATOMIC_LOAD_4);
+ res_type = uint_type;
+ }
+ else if (name == "Loaduintptr")
+ {
+ code = (ptr_size == 8
+ ? Runtime::ATOMIC_LOAD_8
+ : Runtime::ATOMIC_LOAD_4);
+ res_type = uintptr_type;
+ }
+ else if (name == "Loadp")
+ {
+ code = (ptr_size == 8
+ ? Runtime::ATOMIC_LOAD_8
+ : Runtime::ATOMIC_LOAD_4);
+ res_type = pointer_type;
+ }
+ else if (name == "LoadAcq")
+ {
+ code = Runtime::ATOMIC_LOAD_4;
+ res_type = uint32_type;
+ memorder = __ATOMIC_ACQUIRE;
+ }
+ else
+ go_unreachable();
+ Expression* a1 = this->args_->front();
+ Expression* a2 = Expression::make_integer_ul(memorder, int32_type, loc);
+ Expression* call = Runtime::make_call(code, loc, 2, a1, a2);
+ return Expression::make_unsafe_cast(res_type, call, loc);
+ }
+
+ if ((name == "Store" || name == "Store64" || name == "StorepNoWB"
+ || name == "Storeuintptr" || name == "StoreRel"
+ || name == "$Storeint32" || name == "$Storeint64")
+ && this->args_ != NULL && this->args_->size() == 2)
+ {
+ if (int_size < 8 && (name == "Store64" || name == "$Storeint64"))
+ return NULL;
+
+ Runtime::Function code;
+ Expression* a1 = this->args_->at(0);
+ Expression* a2 = this->args_->at(1);
+ if (name == "Store")
+ code = Runtime::ATOMIC_STORE_4;
+ else if (name == "Store64")
+ code = Runtime::ATOMIC_STORE_8;
+ else if (name == "$Storeint32")
+ code = Runtime::ATOMIC_STORE_4;
+ else if (name == "$Storeint64")
+ code = Runtime::ATOMIC_STORE_8;
+ else if (name == "Storeuintptr")
+ code = (ptr_size == 8 ? Runtime::ATOMIC_STORE_8 : Runtime::ATOMIC_STORE_4);
+ else if (name == "StorepNoWB")
+ {
+ code = (ptr_size == 8 ? Runtime::ATOMIC_STORE_8 : Runtime::ATOMIC_STORE_4);
+ a2 = Expression::make_unsafe_cast(uintptr_type, a2, loc);
+ a2 = Expression::make_cast(uint64_type, a2, loc);
+ }
+ else if (name == "StoreRel")
+ {
+ code = Runtime::ATOMIC_STORE_4;
+ memorder = __ATOMIC_RELEASE;
+ }
+ else
+ go_unreachable();
+ Expression* a3 = Expression::make_integer_ul(memorder, int32_type, loc);
+ return Runtime::make_call(code, loc, 3, a1, a2, a3);
+ }
+
+ if ((name == "Xchg" || name == "Xchg64" || name == "Xchguintptr"
+ || name == "$Xchgint32" || name == "$Xchgint64")
+ && this->args_ != NULL && this->args_->size() == 2)
+ {
+ if (int_size < 8 && (name == "Xchg64" || name == "Xchgint64"))
+ return NULL;
+
+ Runtime::Function code;
+ Type* res_type;
+ if (name == "Xchg")
+ {
+ code = Runtime::ATOMIC_EXCHANGE_4;
+ res_type = uint32_type;
+ }
+ else if (name == "Xchg64")
+ {
+ code = Runtime::ATOMIC_EXCHANGE_8;
+ res_type = uint64_type;
+ }
+ else if (name == "$Xchgint32")
+ {
+ code = Runtime::ATOMIC_EXCHANGE_4;
+ res_type = int32_type;
+ }
+ else if (name == "$Xchgint64")
+ {
+ code = Runtime::ATOMIC_EXCHANGE_8;
+ res_type = int64_type;
+ }
+ else if (name == "Xchguintptr")
+ {
+ code = (ptr_size == 8
+ ? Runtime::ATOMIC_EXCHANGE_8
+ : Runtime::ATOMIC_EXCHANGE_4);
+ res_type = uintptr_type;
+ }
+ else
+ go_unreachable();
+ Expression* a1 = this->args_->at(0);
+ Expression* a2 = this->args_->at(1);
+ Expression* a3 = Expression::make_integer_ul(memorder, int32_type, loc);
+ Expression* call = Runtime::make_call(code, loc, 3, a1, a2, a3);
+ return Expression::make_cast(res_type, call, loc);
+ }
+
+ if ((name == "Cas" || name == "Cas64" || name == "Casuintptr"
+ || name == "Casp1" || name == "CasRel"
+ || name == "$Casint32" || name == "$Casint64")
+ && this->args_ != NULL && this->args_->size() == 3)
+ {
+ if (int_size < 8 && (name == "Cas64" || name == "$Casint64"))
+ return NULL;
+
+ Runtime::Function code;
+ Expression* a1 = this->args_->at(0);
+
+ // Builtin cas takes a pointer to the old value.
+ // Store it in a temporary and take the address.
+ Expression* a2 = this->args_->at(1);
+ Temporary_statement* ts = Statement::make_temporary(NULL, a2, loc);
+ inserter->insert(ts);
+ a2 = Expression::make_temporary_reference(ts, loc);
+ a2 = Expression::make_unary(OPERATOR_AND, a2, loc);
+
+ Expression* a3 = this->args_->at(2);
+ if (name == "Cas")
+ code = Runtime::ATOMIC_COMPARE_EXCHANGE_4;
+ else if (name == "Cas64")
+ code = Runtime::ATOMIC_COMPARE_EXCHANGE_8;
+ else if (name == "$Casint32")
+ code = Runtime::ATOMIC_COMPARE_EXCHANGE_4;
+ else if (name == "$Casint64")
+ code = Runtime::ATOMIC_COMPARE_EXCHANGE_8;
+ else if (name == "Casuintptr")
+ code = (ptr_size == 8
+ ? Runtime::ATOMIC_COMPARE_EXCHANGE_8
+ : Runtime::ATOMIC_COMPARE_EXCHANGE_4);
+ else if (name == "Casp1")
+ {
+ code = (ptr_size == 8
+ ? Runtime::ATOMIC_COMPARE_EXCHANGE_8
+ : Runtime::ATOMIC_COMPARE_EXCHANGE_4);
+ a3 = Expression::make_unsafe_cast(uintptr_type, a3, loc);
+ a3 = Expression::make_cast(uint64_type, a3, loc);
+ }
+ else if (name == "CasRel")
+ {
+ code = Runtime::ATOMIC_COMPARE_EXCHANGE_4;
+ memorder = __ATOMIC_RELEASE;
+ }
+ else
+ go_unreachable();
+ Expression* a4 = Expression::make_boolean(false, loc);
+ Expression* a5 = Expression::make_integer_ul(memorder, int32_type, loc);
+ Expression* a6 = Expression::make_integer_ul(__ATOMIC_RELAXED, int32_type, loc);
+ return Runtime::make_call(code, loc, 6, a1, a2, a3, a4, a5, a6);
+ }
+
+ if ((name == "Xadd" || name == "Xadd64" || name == "Xaddint64"
+ || name == "Xadduintptr" || name == "$Xaddint32")
+ && this->args_ != NULL && this->args_->size() == 2)
+ {
+ if (int_size < 8 && (name == "Xadd64" || name == "Xaddint64"))
+ return NULL;
+
+ Runtime::Function code;
+ Type* res_type;
+ if (name == "Xadd")
+ {
+ code = Runtime::ATOMIC_ADD_FETCH_4;
+ res_type = uint32_type;
+ }
+ else if (name == "Xadd64")
+ {
+ code = Runtime::ATOMIC_ADD_FETCH_8;
+ res_type = uint64_type;
+ }
+ else if (name == "$Xaddint32")
+ {
+ code = Runtime::ATOMIC_ADD_FETCH_4;
+ res_type = int32_type;
+ }
+ else if (name == "Xaddint64")
+ {
+ code = Runtime::ATOMIC_ADD_FETCH_8;
+ res_type = int64_type;
+ }
+ else if (name == "Xadduintptr")
+ {
+ code = (ptr_size == 8
+ ? Runtime::ATOMIC_ADD_FETCH_8
+ : Runtime::ATOMIC_ADD_FETCH_4);
+ res_type = uintptr_type;
+ }
+ else
+ go_unreachable();
+ Expression* a1 = this->args_->at(0);
+ Expression* a2 = this->args_->at(1);
+ Expression* a3 = Expression::make_integer_ul(memorder, int32_type, loc);
+ Expression* call = Runtime::make_call(code, loc, 3, a1, a2, a3);
+ return Expression::make_cast(res_type, call, loc);
+ }
+
+ if ((name == "And8" || name == "Or8")
+ && this->args_ != NULL && this->args_->size() == 2)
+ {
+ Runtime::Function code;
+ if (name == "And8")
+ code = Runtime::ATOMIC_AND_FETCH_1;
+ else if (name == "Or8")
+ code = Runtime::ATOMIC_OR_FETCH_1;
+ else
+ go_unreachable();
+ Expression* a1 = this->args_->at(0);
+ Expression* a2 = this->args_->at(1);
+ Expression* a3 = Expression::make_integer_ul(memorder, int32_type, loc);
+ return Runtime::make_call(code, loc, 3, a1, a2, a3);
+ }
+ }
+
+ return NULL;
+}
+
+// Make implicit type conversions explicit.
+
+void
+Call_expression::do_add_conversions()
+{
+ // Skip call that requires a thunk. We generate conversions inside the thunk.
+ if (this->is_concurrent_ || this->is_deferred_)
+ return;
+
+ if (this->args_ == NULL || this->args_->empty())
+ return;
+
+ Function_type* fntype = this->get_function_type();
+ if (fntype == NULL)
+ {
+ go_assert(saw_errors());
+ return;
+ }
+ if (fntype->parameters() == NULL || fntype->parameters()->empty())
+ return;
+
+ Location loc = this->location();
+ Expression_list::iterator pa = this->args_->begin();
+ Typed_identifier_list::const_iterator pp = fntype->parameters()->begin();
+ bool is_interface_method =
+ this->fn_->interface_field_reference_expression() != NULL;
+ if (!is_interface_method && fntype->is_method())
+ {
+ // Skip the receiver argument, which cannot be interface.
+ pa++;
+ }
+ for (; pa != this->args_->end(); ++pa, ++pp)
+ {
+ Type* pt = pp->type();
+ if (!Type::are_identical(pt, (*pa)->type(), 0, NULL)
+ && pt->interface_type() != NULL)
+ *pa = Expression::make_cast(pt, *pa, loc);
+ }
+}
+
// Get the function type. This can return NULL in error cases.
Function_type*
@@ -10905,6 +12071,16 @@ Call_expression::do_get_backend(Translate_context* context)
else
has_closure_arg = true;
+ Expression* first_arg = NULL;
+ if (!is_interface_method && fntype->is_method())
+ {
+ first_arg = this->args_->front();
+ if (first_arg->type()->points_to() == NULL
+ && first_arg->type()->is_direct_iface_type())
+ first_arg = Expression::unpack_direct_iface(first_arg,
+ first_arg->location());
+ }
+
int nargs;
std::vector<Bexpression*> fn_args;
if (this->args_ == NULL || this->args_->empty())
@@ -10921,7 +12097,7 @@ Call_expression::do_get_backend(Translate_context* context)
&& this->args_->size() == 1);
nargs = 1;
fn_args.resize(1);
- fn_args[0] = this->args_->front()->get_backend(context);
+ fn_args[0] = first_arg->get_backend(context);
}
else
{
@@ -10936,7 +12112,7 @@ Call_expression::do_get_backend(Translate_context* context)
Expression_list::const_iterator pe = this->args_->begin();
if (!is_interface_method && fntype->is_method())
{
- fn_args[i] = (*pe)->get_backend(context);
+ fn_args[i] = first_arg->get_backend(context);
++pe;
++i;
}
@@ -11030,7 +12206,55 @@ Call_expression::do_get_backend(Translate_context* context)
return this->call_;
}
-// Dump ast representation for a call expressin.
+// The cost of inlining a call expression.
+
+int
+Call_expression::do_inlining_cost() const
+{
+ Func_expression* fn = this->fn_->func_expression();
+
+ // FIXME: We don't yet support all kinds of calls.
+ if (fn != NULL && fn->closure() != NULL)
+ return 0x100000;
+ if (this->fn_->interface_field_reference_expression())
+ return 0x100000;
+ if (this->get_function_type()->is_method())
+ return 0x100000;
+
+ return 5;
+}
+
+// Export a call expression.
+
+void
+Call_expression::do_export(Export_function_body* efb) const
+{
+ this->fn_->export_expression(efb);
+ this->export_arguments(efb);
+}
+
+// Export call expression arguments.
+
+void
+Call_expression::export_arguments(Export_function_body* efb) const
+{
+ efb->write_c_string("(");
+ if (this->args_ != NULL && !this->args_->empty())
+ {
+ Expression_list::const_iterator pa = this->args_->begin();
+ (*pa)->export_expression(efb);
+ for (pa++; pa != this->args_->end(); pa++)
+ {
+ efb->write_c_string(", ");
+ (*pa)->export_expression(efb);
+ }
+ if (this->is_varargs_)
+ efb->write_c_string("...");
+ }
+ efb->write_c_string(")");
+}
+
+// Dump ast representation for a call expression.
void
Call_expression::do_dump_expression(Ast_dump_context* ast_dump_context) const
@@ -11837,6 +13061,38 @@ Array_index_expression::do_get_backend(Translate_context* context)
return ret;
}
+// Export an array index expression.
+
+void
+Array_index_expression::do_export(Export_function_body* efb) const
+{
+ efb->write_c_string("(");
+ this->array_->export_expression(efb);
+ efb->write_c_string(")[");
+
+ Type* old_context = efb->type_context();
+ efb->set_type_context(Type::lookup_integer_type("int"));
+
+ this->start_->export_expression(efb);
+ if (this->end_ == NULL)
+ go_assert(this->cap_ == NULL);
+ else
+ {
+ efb->write_c_string(":");
+ if (!this->end_->is_nil_expression())
+ this->end_->export_expression(efb);
+ if (this->cap_ != NULL)
+ {
+ efb->write_c_string(":");
+ this->cap_->export_expression(efb);
+ }
+ }
+
+ efb->set_type_context(old_context);
+
+ efb->write_c_string("]");
+}
+
// Dump ast representation for an array index expression.
void
@@ -12019,11 +13275,6 @@ Bexpression*
String_index_expression::do_get_backend(Translate_context* context)
{
Location loc = this->location();
- Expression* string_arg = this->string_;
- if (this->string_->type()->points_to() != NULL)
- string_arg = Expression::make_dereference(this->string_,
- NIL_CHECK_NOT_NEEDED, loc);
-
Expression* bad_index = Expression::check_bounds(this->start_, loc);
int code = (this->end_ == NULL
@@ -12047,23 +13298,27 @@ String_index_expression::do_get_backend(Translate_context* context)
return context->backend()->error_expression();
}
+ go_assert(this->string_->is_variable());
+ go_assert(this->start_->is_variable());
+
Expression* start = Expression::make_cast(int_type, this->start_, loc);
Bfunction* bfn = context->function()->func_value()->get_decl();
+ Expression* length =
+ Expression::make_string_info(this->string_, STRING_INFO_LENGTH, loc);
+ Expression* bytes =
+ Expression::make_string_info(this->string_, STRING_INFO_DATA, loc);
+
+ Bexpression* bstart = start->get_backend(context);
+ Bexpression* ptr = bytes->get_backend(context);
+
if (this->end_ == NULL)
{
- Expression* length =
- Expression::make_string_info(this->string_, STRING_INFO_LENGTH, loc);
-
Expression* start_too_large =
Expression::make_binary(OPERATOR_GE, start, length, loc);
bad_index = Expression::make_binary(OPERATOR_OROR, start_too_large,
bad_index, loc);
- Expression* bytes =
- Expression::make_string_info(this->string_, STRING_INFO_DATA, loc);
- Bexpression* bstart = start->get_backend(context);
- Bexpression* ptr = bytes->get_backend(context);
ptr = gogo->backend()->pointer_offset_expression(ptr, bstart, loc);
Btype* ubtype = Type::lookup_integer_type("uint8")->get_backend(gogo);
Bexpression* index =
@@ -12078,25 +13333,83 @@ String_index_expression::do_get_backend(Translate_context* context)
Expression* end = NULL;
if (this->end_->is_nil_expression())
- end = Expression::make_integer_sl(-1, int_type, loc);
+ end = length;
else
{
+ go_assert(this->end_->is_variable());
Expression* bounds_check = Expression::check_bounds(this->end_, loc);
bad_index =
Expression::make_binary(OPERATOR_OROR, bounds_check, bad_index, loc);
end = Expression::make_cast(int_type, this->end_, loc);
+
+ Expression* end_too_large =
+ Expression::make_binary(OPERATOR_GT, end, length, loc);
+ bad_index = Expression::make_binary(OPERATOR_OROR, end_too_large,
+ bad_index, loc);
}
+ Expression* start_too_large =
+ Expression::make_binary(OPERATOR_GT, start->copy(), end->copy(), loc);
+ bad_index = Expression::make_binary(OPERATOR_OROR, start_too_large,
+ bad_index, loc);
- Expression* strslice = Runtime::make_call(Runtime::STRING_SLICE, loc, 3,
- string_arg, start, end);
- Bexpression* bstrslice = strslice->get_backend(context);
+ end = end->copy();
+ Bexpression* bend = end->get_backend(context);
+ Bexpression* new_length =
+ gogo->backend()->binary_expression(OPERATOR_MINUS, bend, bstart, loc);
+
+ // If the new length is zero, don't change pointer. Otherwise we can
+ // get a pointer to the next object in memory, keeping it live
+ // unnecessarily. When the length is zero, the actual pointer
+ // value doesn't matter.
+ Btype* int_btype = int_type->get_backend(gogo);
+ Bexpression* zero =
+ Expression::make_integer_ul(0, int_type, loc)->get_backend(context);
+ Bexpression* cond =
+ gogo->backend()->binary_expression(OPERATOR_EQEQ, new_length, zero,
+ loc);
+ Bexpression* offset =
+ gogo->backend()->conditional_expression(bfn, int_btype, cond, zero,
+ bstart, loc);
+
+ ptr = gogo->backend()->pointer_offset_expression(ptr, offset, loc);
+
+ Btype* str_btype = this->type()->get_backend(gogo);
+ std::vector<Bexpression*> init;
+ init.push_back(ptr);
+ init.push_back(new_length);
+ Bexpression* bstrslice =
+ gogo->backend()->constructor_expression(str_btype, init, loc);
- Btype* str_btype = strslice->type()->get_backend(gogo);
Bexpression* index_error = bad_index->get_backend(context);
return gogo->backend()->conditional_expression(bfn, str_btype, index_error,
crash, bstrslice, loc);
}
+// Export a string index expression.
+
+void
+String_index_expression::do_export(Export_function_body* efb) const
+{
+ efb->write_c_string("(");
+ this->string_->export_expression(efb);
+ efb->write_c_string(")[");
+
+ Type* old_context = efb->type_context();
+ efb->set_type_context(Type::lookup_integer_type("int"));
+
+ this->start_->export_expression(efb);
+ if (this->end_ != NULL)
+ {
+ efb->write_c_string(":");
+ if (!this->end_->is_nil_expression())
+ this->end_->export_expression(efb);
+ }
+
+ efb->set_type_context(old_context);
+
+ efb->write_c_string("]");
+}
+
// Dump ast representation for a string index expression.
void
@@ -12158,6 +13471,13 @@ Map_index_expression::do_flatten(Gogo* gogo, Named_object*,
return Expression::make_error(loc);
}
+ // Avoid copy for string([]byte) conversions used in map keys.
+ // mapaccess doesn't keep the reference, so this is safe.
+ Type_conversion_expression* ce = this->index_->conversion_expression();
+ if (ce != NULL && ce->type()->is_string_type()
+ && ce->expr()->type()->is_slice_type())
+ ce->set_no_copy(true);
+
if (!Type::are_identical(mt->key_type(), this->index_->type(),
Type::COMPARE_ERRORS | Type::COMPARE_TAGS,
NULL))
@@ -12243,6 +13563,21 @@ Map_index_expression::do_check_types(Gogo*)
}
}
+// Add explicit type conversions.
+
+void
+Map_index_expression::do_add_conversions()
+{
+ Map_type* mt = this->get_map_type();
+ if (mt == NULL)
+ return;
+ Type* lt = mt->key_type();
+ Type* rt = this->index_->type();
+ if (!Type::are_identical(lt, rt, 0, NULL)
+ && lt->interface_type() != NULL)
+ this->index_ = Expression::make_cast(lt, this->index_, this->location());
+}
+
// Get the backend representation for a map index.
Bexpression*
@@ -12287,20 +13622,54 @@ Map_index_expression::get_value_pointer(Gogo* gogo)
this->index_,
loc);
+ Expression* type_expr = Expression::make_type_descriptor(type, loc);
Expression* zero = type->fat_zero_value(gogo);
-
Expression* map_index;
-
if (zero == NULL)
- map_index =
- Runtime::make_call(Runtime::MAPACCESS1, loc, 3,
- Expression::make_type_descriptor(type, loc),
- map_ref, index_ptr);
+ {
+ Runtime::Function code;
+ Expression* key;
+ switch (type->algorithm(gogo))
+ {
+ case Map_type::MAP_ALG_FAST32:
+ case Map_type::MAP_ALG_FAST32PTR:
+ {
+ Type* uint32_type = Type::lookup_integer_type("uint32");
+ Type* uint32_ptr_type = Type::make_pointer_type(uint32_type);
+ key = Expression::make_unsafe_cast(uint32_ptr_type, index_ptr,
+ loc);
+ key = Expression::make_dereference(key, NIL_CHECK_NOT_NEEDED,
+ loc);
+ code = Runtime::MAPACCESS1_FAST32;
+ break;
+ }
+ case Map_type::MAP_ALG_FAST64:
+ case Map_type::MAP_ALG_FAST64PTR:
+ {
+ Type* uint64_type = Type::lookup_integer_type("uint64");
+ Type* uint64_ptr_type = Type::make_pointer_type(uint64_type);
+ key = Expression::make_unsafe_cast(uint64_ptr_type, index_ptr,
+ loc);
+ key = Expression::make_dereference(key, NIL_CHECK_NOT_NEEDED,
+ loc);
+ code = Runtime::MAPACCESS1_FAST64;
+ break;
+ }
+ case Map_type::MAP_ALG_FASTSTR:
+ key = this->index_;
+ code = Runtime::MAPACCESS1_FASTSTR;
+ break;
+ default:
+ key = index_ptr;
+ code = Runtime::MAPACCESS1;
+ break;
+ }
+ map_index = Runtime::make_call(code, loc, 3,
+ type_expr, map_ref, key);
+ }
else
- map_index =
- Runtime::make_call(Runtime::MAPACCESS1_FAT, loc, 4,
- Expression::make_type_descriptor(type, loc),
- map_ref, index_ptr, zero);
+ map_index = Runtime::make_call(Runtime::MAPACCESS1_FAT, loc, 4,
+ type_expr, map_ref, index_ptr, zero);
Type* val_type = type->val_type();
this->value_pointer_ =
@@ -12311,6 +13680,25 @@ Map_index_expression::get_value_pointer(Gogo* gogo)
return this->value_pointer_;
}
+// Export a map index expression.
+
+void
+Map_index_expression::do_export(Export_function_body* efb) const
+{
+ efb->write_c_string("(");
+ this->map_->export_expression(efb);
+ efb->write_c_string(")[");
+
+ Type* old_context = efb->type_context();
+ efb->set_type_context(this->get_map_type()->key_type());
+
+ this->index_->export_expression(efb);
+
+ efb->set_type_context(old_context);
+
+ efb->write_c_string("]");
+}
+
// Dump ast representation for a map index expression
void
@@ -13112,7 +14500,7 @@ void
Allocation_expression::do_check_types(Gogo*)
{
if (!this->type_->in_heap())
- go_error_at(this->location(), "can't heap allocate go:notinheap type");
+ go_error_at(this->location(), "cannot heap allocate go:notinheap type");
}
// Make a copy of an allocation expression.
@@ -13125,6 +14513,8 @@ Allocation_expression::do_copy()
this->location());
if (this->allocate_on_stack_)
alloc->set_allocate_on_stack();
+ if (this->no_zero_)
+ alloc->set_no_zero();
return alloc;
}
@@ -13150,10 +14540,12 @@ Allocation_expression::do_get_backend(Translate_context* context)
Named_object* fn = context->function();
go_assert(fn != NULL);
Bfunction* fndecl = fn->func_value()->get_or_make_decl(gogo, fn);
- Bexpression* zero = gogo->backend()->zero_expression(btype);
+ Bexpression* init = (this->no_zero_
+ ? NULL
+ : gogo->backend()->zero_expression(btype));
Bvariable* temp =
gogo->backend()->temporary_variable(fndecl, context->bblock(), btype,
- zero, true, loc, &decl);
+ init, true, loc, &decl);
Bexpression* ret = gogo->backend()->var_expression(temp, loc);
ret = gogo->backend()->address_expression(ret, loc);
ret = gogo->backend()->compound_expression(decl, ret, loc);
@@ -13443,6 +14835,33 @@ Struct_construction_expression::do_flatten(Gogo*, Named_object*,
return this;
}
+// Make implicit type conversions explicit.
+
+void
+Struct_construction_expression::do_add_conversions()
+{
+ if (this->vals() == NULL)
+ return;
+
+ Location loc = this->location();
+ const Struct_field_list* fields = this->type_->struct_type()->fields();
+ Expression_list::iterator pv = this->vals()->begin();
+ for (Struct_field_list::const_iterator pf = fields->begin();
+ pf != fields->end();
+ ++pf, ++pv)
+ {
+ if (pv == this->vals()->end())
+ break;
+ if (*pv != NULL)
+ {
+ Type* ft = pf->type();
+ if (!Type::are_identical(ft, (*pv)->type(), 0, NULL)
+ && ft->interface_type() != NULL)
+ *pv = Expression::make_cast(ft, *pv, loc);
+ }
+ }
+}
+
// Return the backend representation for constructing a struct.
Bexpression*
@@ -13691,6 +15110,26 @@ Array_construction_expression::do_flatten(Gogo*, Named_object*,
return this;
}
+// Make implicit type conversions explicit.
+
+void
+Array_construction_expression::do_add_conversions()
+{
+ if (this->vals() == NULL)
+ return;
+
+ Type* et = this->type_->array_type()->element_type();
+ if (et->interface_type() == NULL)
+ return;
+
+ Location loc = this->location();
+ for (Expression_list::iterator pv = this->vals()->begin();
+ pv != this->vals()->end();
+ ++pv)
+ if (!Type::are_identical(et, (*pv)->type(), 0, NULL))
+ *pv = Expression::make_cast(et, *pv, loc);
+}
+
// Get a constructor expression for the array values.
Bexpression*
@@ -14214,6 +15653,37 @@ Map_construction_expression::do_copy()
this->location());
}
+// Make implicit type conversions explicit.
+
+void
+Map_construction_expression::do_add_conversions()
+{
+ if (this->vals_ == NULL || this->vals_->empty())
+ return;
+
+ Map_type* mt = this->type_->map_type();
+ Type* kt = mt->key_type();
+ Type* vt = mt->val_type();
+ bool key_is_interface = (kt->interface_type() != NULL);
+ bool val_is_interface = (vt->interface_type() != NULL);
+ if (!key_is_interface && !val_is_interface)
+ return;
+
+ Location loc = this->location();
+ for (Expression_list::iterator pv = this->vals_->begin();
+ pv != this->vals_->end();
+ ++pv)
+ {
+ if (key_is_interface &&
+ !Type::are_identical(kt, (*pv)->type(), 0, NULL))
+ *pv = Expression::make_cast(kt, *pv, loc);
+ ++pv;
+ if (val_is_interface &&
+ !Type::are_identical(vt, (*pv)->type(), 0, NULL))
+ *pv = Expression::make_cast(vt, *pv, loc);
+ }
+}
+
// Return the backend representation for constructing a map.
Bexpression*
@@ -15282,17 +16752,43 @@ Heap_expression::do_get_backend(Translate_context* context)
&edecl);
Bexpression* btempref = gogo->backend()->var_expression(btemp,
loc);
- Bexpression* addr = gogo->backend()->address_expression(btempref, loc);
-
- Expression* td = Expression::make_type_descriptor(etype, loc);
- Type* etype_ptr = Type::make_pointer_type(etype);
space = gogo->backend()->var_expression(space_temp, loc);
+ Type* etype_ptr = Type::make_pointer_type(etype);
Expression* elhs = Expression::make_backend(space, etype_ptr, loc);
- Expression* erhs = Expression::make_backend(addr, etype_ptr, loc);
- Expression* call = Runtime::make_call(Runtime::TYPEDMEMMOVE, loc, 3,
- td, elhs, erhs);
- Bexpression* bcall = call->get_backend(context);
- Bstatement* s = gogo->backend()->expression_statement(fndecl, bcall);
+ Expression* erhs;
+ Expression* call;
+ if (etype->is_direct_iface_type())
+ {
+ // Single pointer.
+ Type* uintptr_type = Type::lookup_integer_type("uintptr");
+ erhs = Expression::make_backend(btempref, etype, loc);
+ erhs = Expression::unpack_direct_iface(erhs, loc);
+ erhs = Expression::make_unsafe_cast(uintptr_type, erhs, loc);
+ call = Runtime::make_call(Runtime::GCWRITEBARRIER, loc, 2,
+ elhs, erhs);
+ }
+ else
+ {
+ Expression* td = Expression::make_type_descriptor(etype, loc);
+ Bexpression* addr =
+ gogo->backend()->address_expression(btempref, loc);
+ erhs = Expression::make_backend(addr, etype_ptr, loc);
+ call = Runtime::make_call(Runtime::TYPEDMEMMOVE, loc, 3,
+ td, elhs, erhs);
+ }
+ Statement* cs = Statement::make_statement(call, false);
+
+ space = gogo->backend()->var_expression(space_temp, loc);
+ Bexpression* ref =
+ gogo->backend()->indirect_expression(expr_btype, space, true, loc);
+ Expression* eref = Expression::make_backend(ref, etype, loc);
+ btempref = gogo->backend()->var_expression(btemp, loc);
+ erhs = Expression::make_backend(btempref, etype, loc);
+ Statement* as = Statement::make_assignment(eref, erhs, loc);
+
+ as = gogo->check_write_barrier(context->block(), as, cs);
+ Bstatement* s = as->get_backend(context);
+
assn = gogo->backend()->compound_statement(edecl, s);
}
decl = gogo->backend()->compound_statement(decl, assn);
@@ -15416,6 +16912,15 @@ Receive_expression::do_get_backend(Translate_context* context)
return Expression::make_compound(recv, recv_ref, loc)->get_backend(context);
}
+// Export a receive expression.
+
+void
+Receive_expression::do_export(Export_function_body* efb) const
+{
+ efb->write_c_string("<-");
+ this->channel_->export_expression(efb);
+}
+
// Dump ast representation for a receive expression.
void
@@ -15425,6 +16930,16 @@ Receive_expression::do_dump_expression(Ast_dump_context* ast_dump_context) const
ast_dump_context->dump_expression(channel_);
}
+// Import a receive expression.
+
+Expression*
+Receive_expression::do_import(Import_expression* imp, Location loc)
+{
+ imp->require_c_string("<-");
+ Expression* expr = Expression::import_expression(imp, loc);
+ return Expression::make_receive(expr, loc);
+}
+
// Make a receive expression.
Receive_expression*
@@ -15944,6 +17459,45 @@ Expression::make_slice_value(Type* at, Expression* valmem, Expression* len,
return new Slice_value_expression(at, valmem, len, cap, location);
}
+// Look through the expression of a Slice_value_expression's valmem to
+// find an call to makeslice. If found, return the call expression and
+// the containing temporary statement (if any).
+
+std::pair<Call_expression*, Temporary_statement*>
+Expression::find_makeslice_call(Expression* expr)
+{
+ Unsafe_type_conversion_expression* utce =
+ expr->unsafe_conversion_expression();
+ if (utce != NULL)
+ expr = utce->expr();
+
+ Slice_value_expression* sve = expr->slice_value_expression();
+ if (sve == NULL)
+ return std::make_pair<Call_expression*, Temporary_statement*>(NULL, NULL);
+ expr = sve->valmem();
+
+ utce = expr->unsafe_conversion_expression();
+ if (utce != NULL)
+ expr = utce->expr();
+
+ Temporary_reference_expression* tre = expr->temporary_reference_expression();
+ Temporary_statement* ts = (tre != NULL ? tre->statement() : NULL);
+ if (ts != NULL && ts->init() != NULL && !ts->assigned()
+ && !ts->is_address_taken())
+ expr = ts->init();
+
+ Call_expression* call = expr->call_expression();
+ if (call == NULL)
+ return std::make_pair<Call_expression*, Temporary_statement*>(NULL, NULL);
+
+ Func_expression* fe = call->fn()->func_expression();
+ if (fe != NULL
+ && fe->runtime_code() == Runtime::MAKESLICE)
+ return std::make_pair(call, ts);
+
+ return std::make_pair<Call_expression*, Temporary_statement*>(NULL, NULL);
+}
+
// An expression that evaluates to some characteristic of a non-empty interface.
// This is used to access the method table or underlying object of an interface.
@@ -16758,6 +18312,71 @@ Expression::make_backend(Bexpression* bexpr, Type* type, Location location)
Expression*
Expression::import_expression(Import_expression* imp, Location loc)
{
+ Expression* expr = Expression::import_expression_without_suffix(imp, loc);
+ while (true)
+ {
+ if (imp->match_c_string("("))
+ {
+ imp->advance(1);
+ Expression_list* args = new Expression_list();
+ bool is_varargs = false;
+ while (!imp->match_c_string(")"))
+ {
+ Expression* arg = Expression::import_expression(imp, loc);
+ if (arg->is_error_expression())
+ return arg;
+ args->push_back(arg);
+ if (imp->match_c_string(")"))
+ break;
+ else if (imp->match_c_string("...)"))
+ {
+ imp->advance(3);
+ is_varargs = true;
+ break;
+ }
+ imp->require_c_string(", ");
+ }
+ imp->require_c_string(")");
+ expr = Expression::make_call(expr, args, is_varargs, loc);
+ expr->call_expression()->set_varargs_are_lowered();
+ }
+ else if (imp->match_c_string("["))
+ {
+ imp->advance(1);
+ Expression* start = Expression::import_expression(imp, loc);
+ Expression* end = NULL;
+ Expression* cap = NULL;
+ if (imp->match_c_string(":"))
+ {
+ imp->advance(1);
+ int c = imp->peek_char();
+ if (c == ':' || c == ']')
+ end = Expression::make_nil(loc);
+ else
+ end = Expression::import_expression(imp, loc);
+ if (imp->match_c_string(":"))
+ {
+ imp->advance(1);
+ cap = Expression::import_expression(imp, loc);
+ }
+ }
+ imp->require_c_string("]");
+ expr = Expression::make_index(expr, start, end, cap, loc);
+ }
+ else
+ break;
+ }
+
+ return expr;
+}
+
+// Import an expression without considering a suffix (function
+// arguments, index operations, etc.).
+
+Expression*
+Expression::import_expression_without_suffix(Import_expression* imp,
+ Location loc)
+{
int c = imp->peek_char();
if (c == '+' || c == '-' || c == '!' || c == '^' || c == '&' || c == '*')
return Unary_expression::do_import(imp, loc);
@@ -16776,6 +18395,8 @@ Expression::import_expression(Import_expression* imp, Location loc)
// This handles integers, floats and complex constants.
return Integer_expression::do_import(imp, loc);
}
+ else if (imp->match_c_string("<-"))
+ return Receive_expression::do_import(imp, loc);
else if (imp->match_c_string("$nil")
|| (imp->version() < EXPORT_FORMAT_V3
&& imp->match_c_string("nil")))
@@ -16793,26 +18414,73 @@ Expression::import_expression(Import_expression* imp, Location loc)
}
if (ifb->saw_error())
return Expression::make_error(loc);
- std::string id = ifb->read_identifier();
- if (id.empty())
+
+ if (ifb->match_c_string("$t"))
+ return Temporary_reference_expression::do_import(ifb, loc);
+
+ return Expression::import_identifier(ifb, loc);
+}
+
+// Import an identifier in an expression. This is a reference to a
+// variable or function.
+
+Expression*
+Expression::import_identifier(Import_function_body* ifb, Location loc)
+{
+ std::string id;
+ Package* pkg;
+ bool is_exported;
+ if (!Import::read_qualified_identifier(ifb, &id, &pkg, &is_exported))
{
if (!ifb->saw_error())
- go_error_at(imp->location(),
- "import error: expected identifier at %lu",
+ go_error_at(ifb->location(),
+ "import error for %qs: bad qualified identifier at %lu",
+ ifb->name().c_str(),
static_cast<unsigned long>(ifb->off()));
ifb->set_saw_error();
return Expression::make_error(loc);
}
- Named_object* var = ifb->block()->bindings()->lookup(id);
- if (var == NULL)
+
+ Named_object* no = NULL;
+ if (pkg == NULL && is_exported)
+ no = ifb->block()->bindings()->lookup(id);
+ if (no == NULL)
+ {
+ const Package* ipkg = pkg;
+ if (ipkg == NULL)
+ ipkg = ifb->function()->package();
+ if (!is_exported)
+ id = '.' + ipkg->pkgpath() + '.' + id;
+ no = ipkg->bindings()->lookup(id);
+ }
+ if (no == NULL)
+ no = ifb->gogo()->lookup_global(id.c_str());
+
+ if (no == NULL)
+ {
+ if (!ifb->saw_error())
+ go_error_at(ifb->location(),
+ "import error for %qs: lookup of %qs failed",
+ ifb->name().c_str(), id.c_str());
+ ifb->set_saw_error();
+ return Expression::make_error(loc);
+ }
+
+ if (no->is_variable() || no->is_result_variable())
+ return Expression::make_var_reference(no, loc);
+ else if (no->is_function() || no->is_function_declaration())
+ return Expression::make_func_reference(no, NULL, loc);
+ else
{
if (!ifb->saw_error())
- go_error_at(imp->location(), "import error: lookup of %qs failed",
- id.c_str());
+ go_error_at(ifb->location(),
+ ("import error for %qs: "
+ "unexpected type of identifier %qs (%d)"),
+ ifb->name().c_str(),
+ id.c_str(), no->classification());
ifb->set_saw_error();
return Expression::make_error(loc);
}
- return Expression::make_var_reference(var, loc);
}
// Class Expression_list.
@@ -17406,7 +19074,7 @@ Numeric_constant::check_int_type(Integer_type* type, bool issue_error,
if (issue_error)
{
go_error_at(location,
- "floating point constant truncated to integer");
+ "floating-point constant truncated to integer");
this->set_invalid();
}
return false;
@@ -17494,7 +19162,8 @@ Numeric_constant::check_float_type(Float_type* type, bool issue_error,
if (issue_error)
{
this->set_invalid();
- go_error_at(location, "complex constant truncated to float");
+ go_error_at(location,
+ "complex constant truncated to floating-point");
}
return false;
}
@@ -17559,7 +19228,7 @@ Numeric_constant::check_float_type(Float_type* type, bool issue_error,
if (!ret && issue_error)
{
- go_error_at(location, "floating point constant overflow");
+ go_error_at(location, "floating-point constant overflow");
this->set_invalid();
}
@@ -17721,4 +19390,3 @@ Numeric_constant::hash(unsigned int seed) const
return (static_cast<unsigned int>(val) + seed) * PRIME;
}
-
diff --git a/gcc/go/gofrontend/expressions.h b/gcc/go/gofrontend/expressions.h
index 2cca824..2c6a080 100644
--- a/gcc/go/gofrontend/expressions.h
+++ b/gcc/go/gofrontend/expressions.h
@@ -237,7 +237,7 @@ class Expression
// Make an expression that evaluates to some characteristic of an string.
// For simplicity, the enum values must match the field indexes in the
- // underlying struct.
+ // underlying struct. This returns an lvalue.
enum String_info
{
// The underlying data in the string.
@@ -448,7 +448,7 @@ class Expression
// Make an expression that evaluates to some characteristic of a
// slice. For simplicity, the enum values must match the field indexes
- // in the underlying struct.
+ // in the underlying struct. This returns an lvalue.
enum Slice_info
{
// The underlying data of the slice.
@@ -469,7 +469,7 @@ class Expression
// Make an expression that evaluates to some characteristic of an
// interface. For simplicity, the enum values must match the field indexes
- // in the underlying struct.
+ // in the underlying struct. This returns an lvalue.
enum Interface_info
{
// The type descriptor of an empty interface.
@@ -581,6 +581,12 @@ class Expression
string_constant_value(std::string* val) const
{ return this->do_string_constant_value(val); }
+ // If this is not a constant expression with boolean type, return
+ // false. If it is one, return true, and set VAL to the value.
+ bool
+ boolean_constant_value(bool* val) const
+ { return this->do_boolean_constant_value(val); }
+
// This is called if the value of this expression is being
// discarded. This issues warnings about computed values being
// unused. This returns true if all is well, false if it issued an
@@ -934,6 +940,11 @@ class Expression
flatten(Gogo* gogo, Named_object* function, Statement_inserter* inserter)
{ return this->do_flatten(gogo, function, inserter); }
+ // Make implicit type conversions explicit.
+ void
+ add_conversions()
+ { this->do_add_conversions(); }
+
// Determine the real type of an expression with abstract integer,
// floating point, or complex type. TYPE_CONTEXT describes the
// expected type.
@@ -1019,6 +1030,13 @@ class Expression
Expression* rhs, bool for_type_guard,
Location);
+ // Return an expression for a conversion from a non-interface type to an
+ // interface type. If ON_STACK is true, it can allocate the storage on
+ // stack.
+ static Expression*
+ convert_type_to_interface(Type* lhs_type, Expression* rhs,
+ bool on_stack, Location);
+
// Return a backend expression implementing the comparison LEFT OP RIGHT.
// TYPE is the type of both sides.
static Bexpression*
@@ -1051,6 +1069,21 @@ class Expression
static Expression*
pack_direct_iface(Type*, Expression*, Location);
+ // Return an expression of the underlying pointer for a direct interface
+ // type (the opposite of pack_direct_iface).
+ static Expression*
+ unpack_direct_iface(Expression*, Location);
+
+ // Return an expression representing the type descriptor field of an
+ // interface.
+ static Expression*
+ get_interface_type_descriptor(Expression*);
+
+ // Look through the expression of a Slice_value_expression's valmem to
+ // find an call to makeslice.
+ static std::pair<Call_expression*, Temporary_statement*>
+ find_makeslice_call(Expression*);
+
// Dump an expression to a dump constext.
void
dump_expression(Ast_dump_context*) const;
@@ -1070,6 +1103,10 @@ class Expression
do_flatten(Gogo*, Named_object*, Statement_inserter*)
{ return this; }
+ // Make implicit type conversions explicit.
+ virtual void
+ do_add_conversions()
+ { }
// Return whether this is a constant expression.
virtual bool
@@ -1099,6 +1136,12 @@ class Expression
do_string_constant_value(std::string*) const
{ return false; }
+ // Return whether this is a constant expression of boolean type, and
+ // set VAL to the value.
+ virtual bool
+ do_boolean_constant_value(bool*) const
+ { return false; }
+
// Called by the parser if the value is being discarded.
virtual bool
do_discarding_value();
@@ -1175,6 +1218,10 @@ class Expression
void
report_error(const char*);
+ // Write a name to export data.
+ static void
+ export_name(Export_function_body* efb, const Named_object*);
+
// Child class implements dumping to a dump context.
virtual void
do_dump_expression(Ast_dump_context*) const = 0;
@@ -1215,16 +1262,13 @@ class Expression
}
static Expression*
- convert_type_to_interface(Type*, Expression*, Location);
-
- static Expression*
- unpack_direct_iface(Expression*, Location);
+ convert_interface_to_type(Type*, Expression*, Location);
static Expression*
- get_interface_type_descriptor(Expression*);
+ import_identifier(Import_function_body*, Location);
static Expression*
- convert_interface_to_type(Type*, Expression*, Location);
+ import_expression_without_suffix(Import_expression*, Location);
// The expression classification.
Expression_classification classification_;
@@ -1390,7 +1434,8 @@ class Var_expression : public Expression
{ return this; }
int
- do_inlining_cost() const;
+ do_inlining_cost() const
+ { return 1; }
void
do_export(Export_function_body*) const;
@@ -1500,6 +1545,9 @@ class Temporary_reference_expression : public Expression
set_is_lvalue()
{ this->is_lvalue_ = true; }
+ static Expression*
+ do_import(Import_function_body*, Location);
+
protected:
Type*
do_type();
@@ -1512,6 +1560,13 @@ class Temporary_reference_expression : public Expression
do_copy()
{ return make_temporary_reference(this->statement_, this->location()); }
+ int
+ do_inlining_cost() const
+ { return 1; }
+
+ void
+ do_export(Export_function_body*) const;
+
bool
do_is_addressable() const
{ return true; }
@@ -1674,7 +1729,7 @@ class Type_conversion_expression : public Expression
Location location)
: Expression(EXPRESSION_CONVERSION, location),
type_(type), expr_(expr), may_convert_function_types_(false),
- no_copy_(false)
+ no_copy_(false), no_escape_(false)
{ }
// Return the type to which we are converting.
@@ -1730,6 +1785,9 @@ class Type_conversion_expression : public Expression
bool
do_string_constant_value(std::string*) const;
+ bool
+ do_boolean_constant_value(bool*) const;
+
Type*
do_type()
{ return this->type_; }
@@ -1766,6 +1824,9 @@ class Type_conversion_expression : public Expression
// True if a string([]byte) conversion can reuse the backing store
// without copying. Only used in string([]byte) conversion.
bool no_copy_;
+ // True if a conversion does not escape. Used in type-to-interface
+ // conversions and slice-to/from-string conversions.
+ bool no_escape_;
};
// An unsafe type conversion, used to pass values to builtin functions.
@@ -1920,6 +1981,9 @@ class Unary_expression : public Expression
bool
do_numeric_constant_value(Numeric_constant*) const;
+ bool
+ do_boolean_constant_value(bool*) const;
+
Type*
do_type();
@@ -2075,6 +2139,9 @@ class Binary_expression : public Expression
do_numeric_constant_value(Numeric_constant*) const;
bool
+ do_boolean_constant_value(bool*) const;
+
+ bool
do_discarding_value();
Type*
@@ -2377,6 +2444,12 @@ class Call_expression : public Expression
virtual Bexpression*
do_get_backend(Translate_context*);
+ int
+ do_inlining_cost() const;
+
+ void
+ do_export(Export_function_body*) const;
+
virtual bool
do_is_recover_call() const;
@@ -2400,14 +2473,20 @@ class Call_expression : public Expression
determining_types();
void
+ export_arguments(Export_function_body*) const;
+
+ void
do_dump_expression(Ast_dump_context*) const;
+ void
+ do_add_conversions();
+
private:
bool
check_argument_type(int, const Type*, const Type*, Location, bool);
Expression*
- lower_to_builtin(Named_object**, const char*, int*);
+ intrinsify(Gogo*, Statement_inserter*);
Expression*
interface_method_function(Interface_field_reference_expression*,
@@ -2536,6 +2615,10 @@ class Builtin_call_expression : public Call_expression
Bexpression*
do_get_backend(Translate_context*);
+ int
+ do_inlining_cost() const
+ { return 1; }
+
void
do_export(Export_function_body*) const;
@@ -2710,6 +2793,12 @@ class Func_expression : public Expression
Bexpression*
do_get_backend(Translate_context*);
+ int
+ do_inlining_cost() const;
+
+ void
+ do_export(Export_function_body*) const;
+
void
do_dump_expression(Ast_dump_context*) const;
@@ -3001,6 +3090,13 @@ class Array_index_expression : public Expression
Bexpression*
do_get_backend(Translate_context*);
+ int
+ do_inlining_cost() const
+ { return this->end_ != NULL ? 2 : 1; }
+
+ void
+ do_export(Export_function_body*) const;
+
void
do_dump_expression(Ast_dump_context*) const;
@@ -3039,6 +3135,18 @@ class String_index_expression : public Expression
string() const
{ return this->string_; }
+ // Return the index of a simple index expression, or the start index
+ // of a slice expression.
+ Expression*
+ start() const
+ { return this->start_; }
+
+ // Return the end index of a slice expression. This is NULL for a
+ // simple index expression.
+ Expression*
+ end() const
+ { return this->end_; }
+
protected:
int
do_traverse(Traverse*);
@@ -3073,6 +3181,13 @@ class String_index_expression : public Expression
Bexpression*
do_get_backend(Translate_context*);
+ int
+ do_inlining_cost() const
+ { return this->end_ != NULL ? 2 : 1; }
+
+ void
+ do_export(Export_function_body*) const;
+
void
do_dump_expression(Ast_dump_context*) const;
@@ -3159,9 +3274,19 @@ class Map_index_expression : public Expression
Bexpression*
do_get_backend(Translate_context*);
+ int
+ do_inlining_cost() const
+ { return 5; }
+
+ void
+ do_export(Export_function_body*) const;
+
void
do_dump_expression(Ast_dump_context*) const;
+ void
+ do_add_conversions();
+
private:
// The map we are looking into.
Expression* map_;
@@ -3449,13 +3574,19 @@ class Allocation_expression : public Expression
public:
Allocation_expression(Type* type, Location location)
: Expression(EXPRESSION_ALLOCATION, location),
- type_(type), allocate_on_stack_(false)
+ type_(type), allocate_on_stack_(false),
+ no_zero_(false)
{ }
void
set_allocate_on_stack()
{ this->allocate_on_stack_ = true; }
+ // Mark that the allocated memory doesn't need zeroing.
+ void
+ set_no_zero()
+ { this->no_zero_ = true; }
+
protected:
int
do_traverse(Traverse*);
@@ -3484,6 +3615,8 @@ class Allocation_expression : public Expression
Type* type_;
// Whether or not this is a stack allocation.
bool allocate_on_stack_;
+ // Whether we don't need to zero the allocated memory.
+ bool no_zero_;
};
// A general composite literal. This is lowered to a type specific
@@ -3648,6 +3781,9 @@ class Struct_construction_expression : public Expression,
void
do_dump_expression(Ast_dump_context*) const;
+ void
+ do_add_conversions();
+
private:
// The type of the struct to construct.
Type* type_;
@@ -3721,6 +3857,9 @@ protected:
virtual void
dump_slice_storage_expression(Ast_dump_context*) const { }
+ void
+ do_add_conversions();
+
private:
// The type of the array to construct.
Type* type_;
@@ -3844,6 +3983,9 @@ class Map_construction_expression : public Expression
void
do_dump_expression(Ast_dump_context*) const;
+ void
+ do_add_conversions();
+
private:
// The type of the map to construct.
Type* type_;
@@ -3982,6 +4124,9 @@ class Receive_expression : public Expression
channel()
{ return this->channel_; }
+ static Expression*
+ do_import(Import_expression*, Location);
+
protected:
int
do_traverse(Traverse* traverse)
@@ -4010,6 +4155,10 @@ class Receive_expression : public Expression
return Expression::make_receive(this->channel_->copy(), this->location());
}
+ int
+ do_inlining_cost() const
+ { return 1; }
+
bool
do_must_eval_in_order() const
{ return true; }
@@ -4018,6 +4167,9 @@ class Receive_expression : public Expression
do_get_backend(Translate_context*);
void
+ do_export(Export_function_body*) const;
+
+ void
do_dump_expression(Ast_dump_context*) const;
private:
@@ -4410,4 +4562,8 @@ class Numeric_constant
Type* type_;
};
+// Temporary buffer size for string conversions.
+// Also known to the runtime as tmpStringBufSize in runtime/string.go.
+static const int tmp_string_buf_size = 32;
+
#endif // !defined(GO_EXPRESSIONS_H)
diff --git a/gcc/go/gofrontend/go-diagnostics.cc b/gcc/go/gofrontend/go-diagnostics.cc
index 21e45b3..4a091e3 100644
--- a/gcc/go/gofrontend/go-diagnostics.cc
+++ b/gcc/go/gofrontend/go-diagnostics.cc
@@ -175,3 +175,25 @@ go_inform(const Location location, const char* fmt, ...)
go_be_inform(location, expand_message(fmt, ap));
va_end(ap);
}
+
+// go_debug uses normal printf formatting, not GCC diagnostic formatting.
+
+void
+go_debug(const Location location, const char* fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ char* mbuf = NULL;
+ int nwr = vasprintf(&mbuf, fmt, ap);
+ va_end(ap);
+ if (nwr == -1)
+ {
+ go_be_error_at(Linemap::unknown_location(),
+ "memory allocation failed in vasprintf");
+ go_assert(0);
+ }
+ std::string rval = std::string(mbuf);
+ free(mbuf);
+ go_be_inform(location, rval);
+}
diff --git a/gcc/go/gofrontend/go-diagnostics.h b/gcc/go/gofrontend/go-diagnostics.h
index 70c97cb..a687553 100644
--- a/gcc/go/gofrontend/go-diagnostics.h
+++ b/gcc/go/gofrontend/go-diagnostics.h
@@ -15,6 +15,12 @@
#define GO_ATTRIBUTE_GCC_DIAG(m, n)
#endif
+#if __GNUC__ >= 3
+#define GO_ATTRIBUTE_PRINTF(m, n) __attribute__ ((__format__ (__printf__, m, n))) __attribute__ ((__nonnull__ (m)))
+#else
+#define GO_ATTRIBUTE_PRINTF(m, n)
+#endif
+
// These declarations define the interface through which the frontend
// reports errors and warnings. These functions accept printf-like
// format specifiers (e.g. %d, %f, %s, etc), with the following additional
@@ -41,6 +47,12 @@ extern void go_fatal_error(const Location, const char* fmt, ...)
extern void go_inform(const Location, const char* fmt, ...)
GO_ATTRIBUTE_GCC_DIAG(2,3);
+// go_debug is used to report a debugging message at a location. This
+// uses standard printf formatting.
+
+extern void go_debug(const Location, const char* fmt, ...)
+ GO_ATTRIBUTE_PRINTF(2, 3);
+
// These interfaces provide a way for the front end to ask for
// the open/close quote characters it should use when formatting
// diagnostics (warnings, errors).
diff --git a/gcc/go/gofrontend/go.cc b/gcc/go/gofrontend/go.cc
index 183664a..12205bd 100644
--- a/gcc/go/gofrontend/go.cc
+++ b/gcc/go/gofrontend/go.cc
@@ -92,7 +92,7 @@ go_parse_input_files(const char** filenames, unsigned int filename_count,
p != linknames->end();
++p)
go_error_at(p->second.loc,
- ("//go:linkname only allowed in Go files that "
+ ("%<//go:linkname%> only allowed in Go files that "
"import \"unsafe\""));
}
all_linknames.insert(linknames->begin(), linknames->end());
@@ -142,6 +142,13 @@ go_parse_input_files(const char** filenames, unsigned int filename_count,
if (only_check_syntax)
return;
+ // Do simple deadcode elimination.
+ ::gogo->remove_deadcode();
+
+ // Make implicit type conversions explicit.
+ ::gogo->add_conversions();
+
+ // Analyze the program flow for escape information.
::gogo->analyze_escape();
// Export global identifiers as appropriate.
diff --git a/gcc/go/gofrontend/gogo.cc b/gcc/go/gofrontend/gogo.cc
index 9f18e14..fcf9a93 100644
--- a/gcc/go/gofrontend/gogo.cc
+++ b/gcc/go/gofrontend/gogo.cc
@@ -64,6 +64,7 @@ Gogo::Gogo(Backend* backend, Linemap* linemap, int, int pointer_size)
named_types_are_converted_(false),
analysis_sets_(),
gc_roots_(),
+ type_descriptors_(),
imported_inlinable_functions_(),
imported_inline_functions_()
{
@@ -551,7 +552,7 @@ Gogo::import_package(const std::string& filename,
if (package->pkgpath() == this->pkgpath())
go_error_at(location,
("imported package uses same package path as package "
- "being compiled (see -fgo-pkgpath option)"));
+ "being compiled (see %<-fgo-pkgpath%> option)"));
this->imports_.insert(std::make_pair(filename, package));
}
@@ -723,6 +724,9 @@ Gogo::init_imports(std::vector<Bstatement*>& init_stmts, Bfunction *bfunction)
p != this->imported_init_fns_.end();
++p)
{
+ // Don't include dummy inits. They are not real functions.
+ if ((*p)->is_dummy())
+ continue;
if ((*p)->priority() < 0)
go_error_at(Linemap::unknown_location(),
"internal error: failed to set init priority for %s",
@@ -903,6 +907,148 @@ Gogo::register_gc_vars(const std::vector<Named_object*>& var_gc,
init_stmts.push_back(this->backend()->expression_statement(init_bfn, bcall));
}
+// Build the list of type descriptors defined in this package. This is to help
+// the reflect package to find compiler-generated types.
+
+// type typeDescriptorList struct {
+// count int
+// types [...]unsafe.Pointer
+// }
+
+static Struct_type*
+type_descriptor_list_type(unsigned long len)
+{
+ Location builtin_loc = Linemap::predeclared_location();
+ Type* int_type = Type::lookup_integer_type("int");
+ Type* ptr_type = Type::make_pointer_type(Type::make_void_type());
+ // Avoid creating zero-length type.
+ unsigned long nelems = (len != 0 ? len : 1);
+ Expression* len_expr = Expression::make_integer_ul(nelems, NULL,
+ builtin_loc);
+ Array_type* array_type = Type::make_array_type(ptr_type, len_expr);
+ array_type->set_is_array_incomparable();
+ Struct_type* list_type =
+ Type::make_builtin_struct_type(2, "count", int_type,
+ "types", array_type);
+ return list_type;
+}
+
+void
+Gogo::build_type_descriptor_list()
+{
+ // Create the list type
+ Location builtin_loc = Linemap::predeclared_location();
+ unsigned long len = this->type_descriptors_.size();
+ Struct_type* list_type = type_descriptor_list_type(len);
+ Btype* bt = list_type->get_backend(this);
+ Btype* bat = list_type->field(1)->type()->get_backend(this);
+
+ // Create the variable
+ std::string name = this->type_descriptor_list_symbol(this->pkgpath_symbol());
+ Bvariable* bv = this->backend()->implicit_variable(name, name, bt,
+ false, true, false,
+ 0);
+
+ // Build the initializer
+ std::vector<unsigned long> indexes;
+ std::vector<Bexpression*> vals;
+ std::vector<Type*>::iterator p = this->type_descriptors_.begin();
+ for (unsigned long i = 0; i < len; ++i, ++p)
+ {
+ Bexpression* bexpr = (*p)->type_descriptor_pointer(this,
+ builtin_loc);
+ indexes.push_back(i);
+ vals.push_back(bexpr);
+ }
+ Bexpression* barray =
+ this->backend()->array_constructor_expression(bat, indexes, vals,
+ builtin_loc);
+
+ Translate_context context(this, NULL, NULL, NULL);
+ std::vector<Bexpression*> fields;
+ Expression* len_expr = Expression::make_integer_ul(len, NULL,
+ builtin_loc);
+ fields.push_back(len_expr->get_backend(&context));
+ fields.push_back(barray);
+ Bexpression* binit =
+ this->backend()->constructor_expression(bt, fields, builtin_loc);
+
+ this->backend()->implicit_variable_set_init(bv, name, bt, false,
+ true, false, binit);
+}
+
+// Register the type descriptors with the runtime. This is to help
+// the reflect package to find compiler-generated types.
+
+void
+Gogo::register_type_descriptors(std::vector<Bstatement*>& init_stmts,
+ Bfunction* init_bfn)
+{
+ // Create the list type
+ Location builtin_loc = Linemap::predeclared_location();
+ Struct_type* list_type = type_descriptor_list_type(1);
+ Btype* bt = list_type->get_backend(this);
+
+ // Collect type lists from transitive imports.
+ std::vector<std::string> list_names;
+ for (Import_init_set::iterator it = this->imported_init_fns_.begin();
+ it != this->imported_init_fns_.end();
+ ++it)
+ {
+ std::string pkgpath =
+ this->pkgpath_from_init_fn_name((*it)->init_name());
+ list_names.push_back(this->type_descriptor_list_symbol(pkgpath));
+ }
+ // Add the main package itself.
+ list_names.push_back(this->type_descriptor_list_symbol("main"));
+
+ // Build a list of lists.
+ std::vector<unsigned long> indexes;
+ std::vector<Bexpression*> vals;
+ unsigned long i = 0;
+ for (std::vector<std::string>::iterator p = list_names.begin();
+ p != list_names.end();
+ ++p)
+ {
+ Bvariable* bv =
+ this->backend()->implicit_variable_reference(*p, *p, bt);
+ Bexpression* bexpr = this->backend()->var_expression(bv, builtin_loc);
+ bexpr = this->backend()->address_expression(bexpr, builtin_loc);
+
+ indexes.push_back(i);
+ vals.push_back(bexpr);
+ i++;
+ }
+ Expression* len_expr = Expression::make_integer_ul(i, NULL, builtin_loc);
+ Type* list_ptr_type = Type::make_pointer_type(list_type);
+ Type* list_array_type = Type::make_array_type(list_ptr_type, len_expr);
+ Btype* bat = list_array_type->get_backend(this);
+ Bexpression* barray =
+ this->backend()->array_constructor_expression(bat, indexes, vals,
+ builtin_loc);
+
+ // Create a variable holding the list.
+ std::string name = this->typelists_symbol();
+ Bvariable* bv = this->backend()->implicit_variable(name, name, bat,
+ true, true, false,
+ 0);
+ this->backend()->implicit_variable_set_init(bv, name, bat, true, true,
+ false, barray);
+
+ // Build the call in main package's init function.
+ Translate_context context(this, NULL, NULL, NULL);
+ Bexpression* bexpr = this->backend()->var_expression(bv, builtin_loc);
+ bexpr = this->backend()->address_expression(bexpr, builtin_loc);
+ Type* array_ptr_type = Type::make_pointer_type(list_array_type);
+ Expression* expr = Expression::make_backend(bexpr, array_ptr_type,
+ builtin_loc);
+ expr = Runtime::make_call(Runtime::REGISTER_TYPE_DESCRIPTORS,
+ builtin_loc, 2, len_expr->copy(), expr);
+ Bexpression* bcall = expr->get_backend(&context);
+ init_stmts.push_back(this->backend()->expression_statement(init_bfn,
+ bcall));
+}
+
// Build the decl for the initialization function.
Named_object*
@@ -1411,7 +1557,6 @@ Gogo::write_globals()
{
init_fndecl = this->initialization_function_decl();
init_bfn = init_fndecl->func_value()->get_or_make_decl(this, init_fndecl);
- this->init_imports(init_stmts, init_bfn);
}
// A list of variable initializations.
@@ -1585,6 +1730,22 @@ Gogo::write_globals()
++p)
(*p)->get_backend(this, const_decls, type_decls, func_decls);
+ // Build the list of type descriptors.
+ this->build_type_descriptor_list();
+
+ if (this->is_main_package())
+ {
+ // Register the type descriptor lists, so that at run time
+ // the reflect package can find compiler-created types, and
+ // deduplicate if the same type is created with reflection.
+ // This needs to be done before calling any package's init
+ // function, as it may create type through reflection.
+ this->register_type_descriptors(init_stmts, init_bfn);
+
+ // Initialize imported packages.
+ this->init_imports(init_stmts, init_bfn);
+ }
+
// Register global variables with the garbage collector.
this->register_gc_vars(var_gc, init_stmts, init_bfn);
@@ -2376,7 +2537,7 @@ Gogo::add_linkname(const std::string& go_name, bool is_exported,
else
go_error_at(loc,
("%s is not a function; "
- "//go:linkname is only supported for functions"),
+ "%<//go:linkname%> is only supported for functions"),
go_name.c_str());
}
@@ -2996,6 +3157,131 @@ Gogo::lower_constant(Named_object* no)
lower.constant(no, false);
}
+// Make implicit type conversions explicit. Currently only does for
+// interface conversions, so the escape analysis can see them and
+// optimize.
+
+class Add_conversions : public Traverse
+{
+ public:
+ Add_conversions()
+ : Traverse(traverse_statements
+ | traverse_expressions)
+ { }
+
+ int
+ statement(Block*, size_t* pindex, Statement*);
+
+ int
+ expression(Expression**);
+};
+
+// Add explicit conversions in a statement.
+
+int
+Add_conversions::statement(Block*, size_t*, Statement* sorig)
+{
+ sorig->add_conversions();
+ return TRAVERSE_CONTINUE;
+}
+
+// Add explicit conversions in an expression.
+
+int
+Add_conversions::expression(Expression** pexpr)
+{
+ (*pexpr)->add_conversions();
+ return TRAVERSE_CONTINUE;
+}
+
+void
+Gogo::add_conversions()
+{
+ Add_conversions add_conversions;
+ this->traverse(&add_conversions);
+}
+
+void
+Gogo::add_conversions_in_block(Block *b)
+{
+ Add_conversions add_conversions;
+ b->traverse(&add_conversions);
+}
+
+// Traversal class for simple deadcode elimination.
+
+class Remove_deadcode : public Traverse
+{
+ public:
+ Remove_deadcode()
+ : Traverse(traverse_statements
+ | traverse_expressions)
+ { }
+
+ int
+ statement(Block*, size_t* pindex, Statement*);
+
+ int
+ expression(Expression**);
+};
+
+// Remove deadcode in a statement.
+
+int
+Remove_deadcode::statement(Block* block, size_t* pindex, Statement* sorig)
+{
+ Location loc = sorig->location();
+ If_statement* ifs = sorig->if_statement();
+ if (ifs != NULL)
+ {
+ // Remove the dead branch of an if statement.
+ bool bval;
+ if (ifs->condition()->boolean_constant_value(&bval))
+ {
+ Statement* s;
+ if (bval)
+ s = Statement::make_block_statement(ifs->then_block(),
+ loc);
+ else
+ if (ifs->else_block() != NULL)
+ s = Statement::make_block_statement(ifs->else_block(),
+ loc);
+ else
+ // Make a dummy statement.
+ s = Statement::make_statement(Expression::make_boolean(false, loc),
+ true);
+
+ block->replace_statement(*pindex, s);
+ }
+ }
+ return TRAVERSE_CONTINUE;
+}
+
+// Remove deadcode in an expression.
+
+int
+Remove_deadcode::expression(Expression** pexpr)
+{
+ // Discard the right arm of a shortcut expression of constant value.
+ Binary_expression* be = (*pexpr)->binary_expression();
+ bool bval;
+ if (be != NULL
+ && be->boolean_constant_value(&bval)
+ && (be->op() == OPERATOR_ANDAND
+ || be->op() == OPERATOR_OROR))
+ *pexpr = Expression::make_boolean(bval, be->location());
+ return TRAVERSE_CONTINUE;
+}
+
+// Remove deadcode.
+
+void
+Gogo::remove_deadcode()
+{
+ Remove_deadcode remove_deadcode;
+ this->traverse(&remove_deadcode);
+}
+
// Traverse the tree to create function descriptors as needed.
class Create_function_descriptors : public Traverse
@@ -3419,7 +3705,7 @@ Check_types_traverse::variable(Named_object* named_object)
if (fntype->is_builtin())
{
go_error_at(init->location(),
- "invalid use of special builtin function %qs; "
+ "invalid use of special built-in function %qs; "
"must be called",
no->message_name().c_str());
}
@@ -4515,11 +4801,6 @@ Build_recover_thunks::function(Named_object* orig_no)
Expression*
Build_recover_thunks::can_recover_arg(Location location)
{
- static Named_object* builtin_return_address;
- if (builtin_return_address == NULL)
- builtin_return_address =
- Gogo::declare_builtin_rf_address("__builtin_return_address", true);
-
Type* uintptr_type = Type::lookup_integer_type("uintptr");
static Named_object* can_recover;
if (can_recover == NULL)
@@ -4538,20 +4819,15 @@ Build_recover_thunks::can_recover_arg(Location location)
can_recover->func_declaration_value()->set_asm_name("runtime.canrecover");
}
- Expression* fn = Expression::make_func_reference(builtin_return_address,
- NULL, location);
-
Expression* zexpr = Expression::make_integer_ul(0, NULL, location);
- Expression_list *args = new Expression_list();
- args->push_back(zexpr);
-
- Expression* call = Expression::make_call(fn, args, false, location);
+ Expression* call = Runtime::make_call(Runtime::BUILTIN_RETURN_ADDRESS,
+ location, 1, zexpr);
call = Expression::make_unsafe_cast(uintptr_type, call, location);
- args = new Expression_list();
+ Expression_list* args = new Expression_list();
args->push_back(call);
- fn = Expression::make_func_reference(can_recover, NULL, location);
+ Expression* fn = Expression::make_func_reference(can_recover, NULL, location);
return Expression::make_call(fn, args, false, location);
}
@@ -4571,33 +4847,6 @@ Gogo::build_recover_thunks()
this->traverse(&build_recover_thunks);
}
-// Return a declaration for __builtin_return_address or
-// __builtin_dwarf_cfa.
-
-Named_object*
-Gogo::declare_builtin_rf_address(const char* name, bool hasarg)
-{
- const Location bloc = Linemap::predeclared_location();
-
- Typed_identifier_list* param_types = new Typed_identifier_list();
- if (hasarg)
- {
- Type* uint32_type = Type::lookup_integer_type("uint32");
- param_types->push_back(Typed_identifier("l", uint32_type, bloc));
- }
-
- Typed_identifier_list* return_types = new Typed_identifier_list();
- Type* voidptr_type = Type::make_pointer_type(Type::make_void_type());
- return_types->push_back(Typed_identifier("", voidptr_type, bloc));
-
- Function_type* fntype = Type::make_function_type(NULL, param_types,
- return_types, bloc);
- Named_object* ret = Named_object::make_function_declaration(name, NULL,
- fntype, bloc);
- ret->func_declaration_value()->set_asm_name(name);
- return ret;
-}
-
// Build a call to the runtime error function.
Expression*
@@ -4896,6 +5145,9 @@ Mark_inline_candidates::type(Type* t)
void
Gogo::do_exports()
{
+ if (saw_errors())
+ return;
+
// Mark any functions whose body should be exported for inlining by
// other packages.
Mark_inline_candidates mic;
@@ -4918,6 +5170,14 @@ Gogo::do_exports()
else
prefix = "go";
+ std::string init_fn_name;
+ if (this->is_main_package())
+ init_fn_name = "";
+ else if (this->need_init_fn_)
+ init_fn_name = this->get_init_fn_name();
+ else
+ init_fn_name = this->dummy_init_fn_name();
+
Export exp(&stream);
exp.register_builtin_types(this);
exp.export_globals(this->package_name(),
@@ -4925,9 +5185,7 @@ Gogo::do_exports()
pkgpath,
this->packages_,
this->imports_,
- (this->need_init_fn_ && !this->is_main_package()
- ? this->get_init_fn_name()
- : ""),
+ init_fn_name,
this->imported_init_fns_,
this->package_->bindings());
@@ -5168,7 +5426,7 @@ Function::Function(Function_type* type, Named_object* enclosing, Block* block,
calls_recover_(false), is_recover_thunk_(false), has_recover_thunk_(false),
calls_defer_retaddr_(false), is_type_specific_function_(false),
in_unique_section_(false), export_for_inlining_(false),
- is_inline_only_(false)
+ is_inline_only_(false), is_referenced_by_inline_(false)
{
}
@@ -5520,23 +5778,24 @@ Function::defer_stack(Location location)
// Export the function.
void
-Function::export_func(Export* exp, const std::string& name) const
+Function::export_func(Export* exp, const Named_object* no) const
{
Block* block = NULL;
if (this->export_for_inlining())
block = this->block_;
- Function::export_func_with_type(exp, name, this->type_, this->results_,
+ Function::export_func_with_type(exp, no, this->type_, this->results_,
this->is_method() && this->nointerface(),
- block, this->location_);
+ this->asm_name(), block, this->location_);
}
// Export a function with a type.
void
-Function::export_func_with_type(Export* exp, const std::string& name,
+Function::export_func_with_type(Export* exp, const Named_object* no,
const Function_type* fntype,
Function::Results* result_vars,
- bool nointerface, Block* block, Location loc)
+ bool nointerface, const std::string& asm_name,
+ Block* block, Location loc)
{
exp->write_c_string("func ");
@@ -5546,6 +5805,13 @@ Function::export_func_with_type(Export* exp, const std::string& name,
exp->write_c_string("/*nointerface*/ ");
}
+ if (!asm_name.empty())
+ {
+ exp->write_c_string("/*asm ");
+ exp->write_string(asm_name);
+ exp->write_c_string(" */ ");
+ }
+
if (fntype->is_method())
{
exp->write_c_string("(");
@@ -5557,7 +5823,21 @@ Function::export_func_with_type(Export* exp, const std::string& name,
exp->write_c_string(") ");
}
- exp->write_string(name);
+ if (no->package() != NULL && !fntype->is_method())
+ {
+ char buf[50];
+ snprintf(buf, sizeof buf, "<p%d>", exp->package_index(no->package()));
+ exp->write_c_string(buf);
+ }
+
+ const std::string& name(no->name());
+ if (!Gogo::is_hidden_name(name))
+ exp->write_string(name);
+ else
+ {
+ exp->write_c_string(".");
+ exp->write_string(Gogo::unpack_hidden_name(name));
+ }
exp->write_c_string(" (");
const Typed_identifier_list* parameters = fntype->parameters();
@@ -5663,23 +5943,45 @@ Function::export_func_with_type(Export* exp, const std::string& name,
// Import a function.
-void
+bool
Function::import_func(Import* imp, std::string* pname,
+ Package** ppkg, bool* pis_exported,
Typed_identifier** preceiver,
Typed_identifier_list** pparameters,
Typed_identifier_list** presults,
bool* is_varargs,
bool* nointerface,
+ std::string* asm_name,
std::string* body)
{
imp->require_c_string("func ");
*nointerface = false;
- if (imp->match_c_string("/*"))
+ while (imp->match_c_string("/*"))
{
- imp->require_c_string("/*nointerface*/ ");
- *nointerface = true;
+ imp->advance(2);
+ if (imp->match_c_string("nointerface"))
+ {
+ imp->require_c_string("nointerface*/ ");
+ *nointerface = true;
+ }
+ else if (imp->match_c_string("asm"))
+ {
+ imp->require_c_string("asm ");
+ *asm_name = imp->read_identifier();
+ imp->require_c_string(" */ ");
+ }
+ else
+ {
+ go_error_at(imp->location(),
+ "import error at %d: unrecognized function comment",
+ imp->pos());
+ return false;
+ }
+ }
+ if (*nointerface)
+ {
// Only a method can be nointerface.
go_assert(imp->peek_char() == '(');
}
@@ -5697,7 +5999,13 @@ Function::import_func(Import* imp, std::string* pname,
imp->require_c_string(") ");
}
- *pname = imp->read_identifier();
+ if (!Import::read_qualified_identifier(imp, pname, ppkg, pis_exported))
+ {
+ go_error_at(imp->location(),
+ "import error at %d: bad function name in export data",
+ imp->pos());
+ return false;
+ }
Typed_identifier_list* parameters;
*is_varargs = false;
@@ -5798,11 +6106,13 @@ Function::import_func(Import* imp, std::string* pname,
{
go_error_at(imp->location(), "invalid inline function length %s",
lenstr.c_str());
- return;
+ return false;
}
*body = imp->read(static_cast<size_t>(llen));
}
+
+ return true;
}
// Get the backend representation.
@@ -5815,7 +6125,10 @@ Function::get_or_make_decl(Gogo* gogo, Named_object* no)
unsigned int flags = 0;
bool is_init_fn = false;
if (no->package() != NULL)
- ;
+ {
+ // Functions defined in other packages must be visible.
+ flags |= Backend::function_is_visible;
+ }
else if (this->enclosing_ != NULL || Gogo::is_thunk(no))
;
else if (Gogo::unpack_hidden_name(no->name()) == "init"
@@ -5863,6 +6176,11 @@ Function::get_or_make_decl(Gogo* gogo, Named_object* no)
else
asm_name = gogo->function_asm_name(no->name(), no->package(), rtype);
+ // If an inline body refers to this function, then it
+ // needs to be visible in the symbol table.
+ if (this->is_referenced_by_inline_)
+ flags |= Backend::function_is_visible;
+
// If a function calls the predeclared recover function, we
// can't inline it, because recover behaves differently in a
// function passed directly to defer. If this is a recover
@@ -5943,7 +6261,8 @@ Function_declaration::get_or_make_decl(Gogo* gogo, Named_object* no)
}
if (this->asm_name_ == "runtime.gopanic"
- || this->asm_name_ == "__go_runtime_error")
+ || this->asm_name_ == "__go_runtime_error"
+ || this->asm_name_ == "runtime.panicdottype")
flags |= Backend::function_does_not_return;
}
@@ -6023,7 +6342,7 @@ Function::build(Gogo* gogo, Named_object* named_function)
// Variables that need to be declared for this function and their
// initial values.
std::vector<Bvariable*> vars;
- std::vector<Bexpression*> var_inits;
+ std::vector<Expression*> var_inits;
std::vector<Statement*> var_decls_stmts;
for (Bindings::const_definitions_iterator p =
this->block_->bindings()->begin_definitions();
@@ -6038,9 +6357,10 @@ Function::build(Gogo* gogo, Named_object* named_function)
// We always pass the receiver to a method as a pointer. If
// the receiver is declared as a non-pointer type, then we
- // copy the value into a local variable.
+ // copy the value into a local variable. For direct interface
+ // type we pack the pointer into the type.
if ((*p)->var_value()->is_receiver()
- && !(*p)->var_value()->type()->is_direct_iface_type())
+ && (*p)->var_value()->type()->points_to() == NULL)
{
std::string name = (*p)->name() + ".pointer";
Type* var_type = (*p)->var_value()->type();
@@ -6052,15 +6372,20 @@ Function::build(Gogo* gogo, Named_object* named_function)
parm_bvar = parm_no->get_backend_variable(gogo, named_function);
vars.push_back(bvar);
- Expression* parm_ref =
+
+ Expression* parm_ref =
Expression::make_var_reference(parm_no, loc);
- parm_ref =
- Expression::make_dereference(parm_ref,
- Expression::NIL_CHECK_NEEDED,
- loc);
- if ((*p)->var_value()->is_in_heap())
- parm_ref = Expression::make_heap_expression(parm_ref, loc);
- var_inits.push_back(parm_ref->get_backend(&context));
+ Type* recv_type = (*p)->var_value()->type();
+ if (recv_type->is_direct_iface_type())
+ parm_ref = Expression::pack_direct_iface(recv_type, parm_ref, loc);
+ else
+ parm_ref =
+ Expression::make_dereference(parm_ref,
+ Expression::NIL_CHECK_NEEDED,
+ loc);
+ if ((*p)->var_value()->is_in_heap())
+ parm_ref = Expression::make_heap_expression(parm_ref, loc);
+ var_inits.push_back(parm_ref);
}
else if ((*p)->var_value()->is_in_heap())
{
@@ -6077,7 +6402,7 @@ Function::build(Gogo* gogo, Named_object* named_function)
Expression* var_ref =
Expression::make_var_reference(parm_no, loc);
var_ref = Expression::make_heap_expression(var_ref, loc);
- var_inits.push_back(var_ref->get_backend(&context));
+ var_inits.push_back(var_ref);
}
param_vars.push_back(parm_bvar);
}
@@ -6086,15 +6411,15 @@ Function::build(Gogo* gogo, Named_object* named_function)
Bvariable* bvar = (*p)->get_backend_variable(gogo, named_function);
Type* type = (*p)->result_var_value()->type();
- Bexpression* init;
+ Expression* init;
if (!(*p)->result_var_value()->is_in_heap())
{
Btype* btype = type->get_backend(gogo);
- init = gogo->backend()->zero_expression(btype);
+ Bexpression* binit = gogo->backend()->zero_expression(btype);
+ init = Expression::make_backend(binit, type, loc);
}
else
- init = Expression::make_allocation(type,
- loc)->get_backend(&context);
+ init = Expression::make_allocation(type, loc);
vars.push_back(bvar);
var_inits.push_back(init);
@@ -6167,13 +6492,16 @@ Function::build(Gogo* gogo, Named_object* named_function)
Bblock* code_block = this->block_->get_backend(&context);
// Initialize variables if necessary.
+ Translate_context icontext(gogo, named_function, this->block_,
+ var_decls);
std::vector<Bstatement*> init;
go_assert(vars.size() == var_inits.size());
for (size_t i = 0; i < vars.size(); ++i)
{
+ Bexpression* binit = var_inits[i]->get_backend(&icontext);
Bstatement* init_stmt =
gogo->backend()->init_statement(this->fndecl_, vars[i],
- var_inits[i]);
+ binit);
init.push_back(init_stmt);
}
Bstatement* var_init = gogo->backend()->statement_list(init);
@@ -6635,7 +6963,12 @@ Block::import_block(Block* set, Import_function_body *ifb, Location loc)
if (at_end)
{
- off = nl + 1;
+ // An if statement can have an "else" following the "}", in
+ // which case we want to leave the offset where it is, just
+ // after the "}". We don't get the block ending location
+ // quite right for if statements.
+ if (body.compare(off, 6, " else ") != 0)
+ off = nl + 1;
break;
}
@@ -6958,6 +7291,8 @@ Function_declaration::import_function_body(Gogo* gogo, Named_object* no)
Named_type* rtype = fntype->receiver()->type()->deref()->named_type();
go_assert(rtype != NULL);
no = rtype->add_method(no->name(), fn);
+ const Package* package = rtype->named_object()->package();
+ package->bindings()->add_method(no);
}
Import_function_body ifb(gogo, this->imp_, no, body, nl + 1, outer, indent);
@@ -6966,6 +7301,7 @@ Function_declaration::import_function_body(Gogo* gogo, Named_object* no)
return;
gogo->lower_block(no, outer);
+ outer->determine_types();
gogo->add_imported_inline_function(no);
}
@@ -6995,7 +7331,8 @@ Variable::Variable(Type* type, Expression* init, bool is_global,
type_from_init_tuple_(false), type_from_range_index_(false),
type_from_range_value_(false), type_from_chan_element_(false),
is_type_switch_var_(false), determined_type_(false),
- in_unique_section_(false), toplevel_decl_(NULL)
+ in_unique_section_(false), is_referenced_by_inline_(false),
+ toplevel_decl_(NULL)
{
go_assert(type != NULL || init != NULL);
go_assert(!is_parameter || init == NULL);
@@ -7477,11 +7814,25 @@ Variable::get_init_block(Gogo* gogo, Named_object* function,
// Export the variable
void
-Variable::export_var(Export* exp, const std::string& name) const
+Variable::export_var(Export* exp, const Named_object* no) const
{
go_assert(this->is_global_);
exp->write_c_string("var ");
- exp->write_string(name);
+ if (no->package() != NULL)
+ {
+ char buf[50];
+ snprintf(buf, sizeof buf, "<p%d>", exp->package_index(no->package()));
+ exp->write_c_string(buf);
+ }
+
+ if (!Gogo::is_hidden_name(no->name()))
+ exp->write_string(no->name());
+ else
+ {
+ exp->write_c_string(".");
+ exp->write_string(Gogo::unpack_hidden_name(no->name()));
+ }
+
exp->write_c_string(" ");
exp->write_type(this->type());
exp->write_c_string("\n");
@@ -7489,15 +7840,23 @@ Variable::export_var(Export* exp, const std::string& name) const
// Import a variable.
-void
-Variable::import_var(Import* imp, std::string* pname, Type** ptype)
+bool
+Variable::import_var(Import* imp, std::string* pname, Package** ppkg,
+ bool* pis_exported, Type** ptype)
{
imp->require_c_string("var ");
- *pname = imp->read_identifier();
+ if (!Import::read_qualified_identifier(imp, pname, ppkg, pis_exported))
+ {
+ go_error_at(imp->location(),
+ "import error at %d: bad variable name in export data",
+ imp->pos());
+ return false;
+ }
imp->require_c_string(" ");
*ptype = imp->read_type();
imp->require_semicolon_if_old_version();
imp->require_c_string("\n");
+ return true;
}
// Convert a variable to the backend representation.
@@ -7517,7 +7876,7 @@ Variable::get_backend_variable(Gogo* gogo, Named_object* function,
else
{
bool is_parameter = this->is_parameter_;
- if (this->is_receiver_ && !type->is_direct_iface_type())
+ if (this->is_receiver_ && type->points_to() == NULL)
is_parameter = false;
if (this->is_in_heap())
{
@@ -7548,6 +7907,18 @@ Variable::get_backend_variable(Gogo* gogo, Named_object* function,
&& var_name == "runtime.writeBarrier")
is_hidden = false;
+ // If an inline body refers to this variable, then it
+ // needs to be visible in the symbol table.
+ if (this->is_referenced_by_inline_)
+ is_hidden = false;
+
+ // If this variable is in a different package, then it
+ // can't be treated as a hidden symbol. This case can
+ // arise when an inlined function refers to a
+ // package-scope unexported variable.
+ if (package != NULL)
+ is_hidden = false;
+
bvar = backend->global_variable(var_name,
asm_name,
btype,
@@ -7808,7 +8179,7 @@ Type_declaration::define_methods(Named_type* nt)
++p)
go_error_at((*p)->location(),
("invalid receiver type "
- "(receiver must be a named type"));
+ "(receiver must be a named type)"));
return;
}
}
@@ -8125,11 +8496,11 @@ Named_object::export_named_object(Export* exp) const
break;
case NAMED_OBJECT_FUNC_DECLARATION:
- this->func_declaration_value()->export_func(exp, this->name_);
+ this->func_declaration_value()->export_func(exp, this);
break;
case NAMED_OBJECT_VAR:
- this->var_value()->export_var(exp, this->name_);
+ this->var_value()->export_var(exp, this);
break;
case NAMED_OBJECT_RESULT_VAR:
@@ -8137,7 +8508,7 @@ Named_object::export_named_object(Export* exp) const
go_unreachable();
case NAMED_OBJECT_FUNC:
- this->func_value()->export_func(exp, this->name_);
+ this->func_value()->export_func(exp, this);
break;
}
}
diff --git a/gcc/go/gofrontend/gogo.h b/gcc/go/gofrontend/gogo.h
index cfa238a..c4d5bab 100644
--- a/gcc/go/gofrontend/gogo.h
+++ b/gcc/go/gofrontend/gogo.h
@@ -103,6 +103,11 @@ class Import_init
precursors() const
{ return this->precursor_functions_; }
+ // Whether this is a dummy init, which is used only to record transitive import.
+ bool
+ is_dummy() const
+ { return this->init_name_[0] == '~'; }
+
private:
// The name of the package being imported.
std::string package_name_;
@@ -617,6 +622,11 @@ class Gogo
this->gc_roots_.push_back(expr);
}
+ // Add a type to the descriptor list.
+ void
+ add_type_descriptor(Type* type)
+ { this->type_descriptors_.push_back(type); }
+
// Traverse the tree. See the Traverse class.
void
traverse(Traverse*);
@@ -683,6 +693,18 @@ class Gogo
void
check_return_statements();
+ // Remove deadcode.
+ void
+ remove_deadcode();
+
+ // Make implicit type conversions explicit.
+ void
+ add_conversions();
+
+ // Make implicit type conversions explicit in a block.
+ void
+ add_conversions_in_block(Block*);
+
// Analyze the program flow for escape information.
void
analyze_escape();
@@ -748,6 +770,12 @@ class Gogo
assign_with_write_barrier(Function*, Block*, Statement_inserter*,
Expression* lhs, Expression* rhs, Location);
+ // Return a statement that tests whether write barriers are enabled
+ // and executes either the efficient code (WITHOUT) or the write
+ // barrier function call (WITH), depending.
+ Statement*
+ check_write_barrier(Block*, Statement* without, Statement* with);
+
// Flatten parse tree.
void
flatten();
@@ -756,11 +784,6 @@ class Gogo
void
build_recover_thunks();
- // Return a declaration for __builtin_return_address or
- // __builtin_dwarf_cfa.
- static Named_object*
- declare_builtin_rf_address(const char* name, bool hasarg);
-
// Simplify statements which might use thunks: go and defer
// statements.
void
@@ -894,9 +917,27 @@ class Gogo
const std::string&
get_init_fn_name();
+ // Return the name for a dummy init function, which is not a real
+ // function but only for tracking transitive import.
+ std::string
+ dummy_init_fn_name();
+
+ // Return the package path symbol from an init function name, which
+ // can be a real init function or a dummy one.
+ std::string
+ pkgpath_from_init_fn_name(std::string);
+
// Return the name for a type descriptor symbol.
std::string
- type_descriptor_name(Type*, Named_type*);
+ type_descriptor_name(const Type*, Named_type*);
+
+ // Return the name of the type descriptor list symbol of a package.
+ std::string
+ type_descriptor_list_symbol(std::string);
+
+ // Return the name of the list of all type descriptor lists.
+ std::string
+ typelists_symbol();
// Return the assembler name for the GC symbol for a type.
std::string
@@ -964,15 +1005,21 @@ class Gogo
std::vector<Bstatement*>&,
Bfunction* init_bfunction);
+ // Build the list of type descriptors.
+ void
+ build_type_descriptor_list();
+
+ // Register the type descriptors with the runtime.
+ void
+ register_type_descriptors(std::vector<Bstatement*>&,
+ Bfunction* init_bfunction);
+
void
propagate_writebarrierrec();
Named_object*
write_barrier_variable();
- Statement*
- check_write_barrier(Block*, Statement*, Statement*);
-
// Type used to map import names to packages.
typedef std::map<std::string, Package*> Imports;
@@ -1105,6 +1152,8 @@ class Gogo
std::vector<Analysis_set> analysis_sets_;
// A list of objects to add to the GC roots.
std::vector<Expression*> gc_roots_;
+ // A list of type descriptors that we need to register.
+ std::vector<Type*> type_descriptors_;
// A list of function declarations with imported bodies that we may
// want to inline.
std::vector<Named_object*> imported_inlinable_functions_;
@@ -1483,6 +1532,11 @@ class Function
set_is_inline_only()
{ this->is_inline_only_ = true; }
+ // Mark the function as referenced by an inline body.
+ void
+ set_is_referenced_by_inline()
+ { this->is_referenced_by_inline_ = true; }
+
// Swap with another function. Used only for the thunk which calls
// recover.
void
@@ -1535,20 +1589,21 @@ class Function
// Export the function.
void
- export_func(Export*, const std::string& name) const;
+ export_func(Export*, const Named_object*) const;
// Export a function with a type.
static void
- export_func_with_type(Export*, const std::string& name,
+ export_func_with_type(Export*, const Named_object*,
const Function_type*, Results*, bool nointerface,
- Block* block, Location);
+ const std::string& asm_name, Block* block, Location);
- // Import a function.
- static void
- import_func(Import*, std::string* pname, Typed_identifier** receiver,
+ // Import a function. Reports whether the import succeeded.
+ static bool
+ import_func(Import*, std::string* pname, Package** pkg,
+ bool* is_exported, Typed_identifier** receiver,
Typed_identifier_list** pparameters,
Typed_identifier_list** presults, bool* is_varargs,
- bool* nointerface, std::string* body);
+ bool* nointerface, std::string* asm_name, std::string* body);
private:
// Type for mapping from label names to Label objects.
@@ -1625,6 +1680,9 @@ class Function
// True if this function is inline only: if it should not be emitted
// if it is not inlined.
bool is_inline_only_ : 1;
+ // True if this function is referenced from an inlined body that
+ // will be put into the export data.
+ bool is_referenced_by_inline_ : 1;
};
// A snapshot of the current binding state.
@@ -1765,11 +1823,11 @@ class Function_declaration
// Export a function declaration.
void
- export_func(Export* exp, const std::string& name) const
+ export_func(Export* exp, const Named_object* no) const
{
- Function::export_func_with_type(exp, name, this->fntype_, NULL,
+ Function::export_func_with_type(exp, no, this->fntype_, NULL,
this->is_method() && this->nointerface(),
- NULL, this->location_);
+ this->asm_name_, NULL, this->location_);
}
// Check that the types used in this declaration's signature are defined.
@@ -2019,6 +2077,14 @@ class Variable
this->in_unique_section_ = true;
}
+ // Mark the variable as referenced by an inline body.
+ void
+ set_is_referenced_by_inline()
+ {
+ go_assert(this->is_global_);
+ this->is_referenced_by_inline_ = true;
+ }
+
// Return the top-level declaration for this variable.
Statement*
toplevel_decl()
@@ -2059,11 +2125,12 @@ class Variable
// Export the variable.
void
- export_var(Export*, const std::string& name) const;
+ export_var(Export*, const Named_object*) const;
- // Import a variable.
- static void
- import_var(Import*, std::string* pname, Type** ptype);
+ // Import a variable. Reports whether the import succeeded.
+ static bool
+ import_var(Import*, std::string* pname, Package** pkg, bool* is_exported,
+ Type** ptype);
private:
// The type of a tuple.
@@ -2130,6 +2197,9 @@ class Variable
// True if this variable should be put in a unique section. This is
// used for field tracking.
bool in_unique_section_ : 1;
+ // True if this variable is referenced from an inlined body that
+ // will be put into the export data.
+ bool is_referenced_by_inline_ : 1;
// The top-level declaration for this variable. Only used for local
// variables. Must be a Temporary_statement if not NULL.
Statement* toplevel_decl_;
@@ -3624,21 +3694,24 @@ static const int RUNTIME_ERROR_STRING_SLICE_OUT_OF_BOUNDS = 5;
// locations.
static const int RUNTIME_ERROR_NIL_DEREFERENCE = 6;
-// Slice length or capacity out of bounds in make: negative or
-// overflow or length greater than capacity.
-static const int RUNTIME_ERROR_MAKE_SLICE_OUT_OF_BOUNDS = 7;
+// Slice length out of bounds in make: negative or overflow
+// or length greater than capacity.
+static const int RUNTIME_ERROR_MAKE_SLICE_LEN_OUT_OF_BOUNDS = 7;
+
+// Slice capacity out of bounds in make: negative.
+static const int RUNTIME_ERROR_MAKE_SLICE_CAP_OUT_OF_BOUNDS = 8;
// Map capacity out of bounds in make: negative or overflow.
-static const int RUNTIME_ERROR_MAKE_MAP_OUT_OF_BOUNDS = 8;
+static const int RUNTIME_ERROR_MAKE_MAP_OUT_OF_BOUNDS = 9;
// Channel capacity out of bounds in make: negative or overflow.
-static const int RUNTIME_ERROR_MAKE_CHAN_OUT_OF_BOUNDS = 9;
+static const int RUNTIME_ERROR_MAKE_CHAN_OUT_OF_BOUNDS = 10;
// Division by zero.
-static const int RUNTIME_ERROR_DIVISION_BY_ZERO = 10;
+static const int RUNTIME_ERROR_DIVISION_BY_ZERO = 11;
// Go statement with nil function.
-static const int RUNTIME_ERROR_GO_NIL = 11;
+static const int RUNTIME_ERROR_GO_NIL = 12;
// This is used by some of the langhooks.
extern Gogo* go_get_gogo();
diff --git a/gcc/go/gofrontend/import-archive.cc b/gcc/go/gofrontend/import-archive.cc
index 868def7..d5e26ce 100644
--- a/gcc/go/gofrontend/import-archive.cc
+++ b/gcc/go/gofrontend/import-archive.cc
@@ -420,7 +420,7 @@ Archive_file::read_big_archive_header(off_t off, std::string* pname,
char* buf = new char[sizeof(hdr.ar_size) + 1];
memcpy(buf, hdr.ar_size, sizeof(hdr.ar_size));
go_error_at(this->location_,
- ("%s: malformed ar_size in entry header at %ld"
+ ("%s: malformed size in entry header at %ld"
" (expected decimal, got %s)"),
this->filename_.c_str(), static_cast<long>(off), buf);
delete[] buf;
@@ -434,7 +434,7 @@ Archive_file::read_big_archive_header(off_t off, std::string* pname,
char* buf = new char[sizeof(hdr.ar_namlen) + 1];
memcpy(buf, hdr.ar_namlen, sizeof(hdr.ar_namlen));
go_error_at(this->location_,
- ("%s: malformed ar_namlen in entry header at %ld"
+ ("%s: malformed name length in entry header at %ld"
" (expected decimal, got %s)"),
this->filename_.c_str(), static_cast<long>(off), buf);
delete[] buf;
@@ -460,7 +460,7 @@ Archive_file::read_big_archive_header(off_t off, std::string* pname,
char* buf = new char[sizeof(hdr.ar_nxtmem) + 1];
memcpy(buf, hdr.ar_nxtmem, sizeof(hdr.ar_nxtmem));
go_error_at(this->location_,
- ("%s: malformed ar_nxtmem in entry header at %ld"
+ ("%s: malformed next member offset in entry header at %ld"
" (expected decimal, got %s)"),
this->filename_.c_str(), static_cast<long>(off), buf);
delete[] buf;
@@ -655,7 +655,7 @@ Archive_file::get_file_and_offset(off_t off, const std::string& hdrname,
int nfd = open(filename.c_str(), O_RDONLY | O_BINARY);
if (nfd < 0)
{
- go_error_at(this->location_, "%s: can't open nested archive %s",
+ go_error_at(this->location_, "%s: cannot open nested archive %s",
this->filename_.c_str(), filename.c_str());
return false;
}
diff --git a/gcc/go/gofrontend/import.cc b/gcc/go/gofrontend/import.cc
index c1982eb..abf0b54 100644
--- a/gcc/go/gofrontend/import.cc
+++ b/gcc/go/gofrontend/import.cc
@@ -288,8 +288,8 @@ Import::find_object_export_data(const std::string& filename,
Import::Import(Stream* stream, Location location)
: gogo_(NULL), stream_(stream), location_(location), package_(NULL),
- add_to_globals_(false), type_data_(), type_pos_(0), type_offsets_(),
- builtin_types_((- SMALLEST_BUILTIN_CODE) + 1),
+ add_to_globals_(false), packages_(), type_data_(), type_pos_(0),
+ type_offsets_(), builtin_types_((- SMALLEST_BUILTIN_CODE) + 1),
types_(), version_(EXPORT_FORMAT_UNKNOWN)
{
}
@@ -487,6 +487,8 @@ Import::read_one_import()
Package* p = this->gogo_->register_package(pkgpath, "",
Linemap::unknown_location());
p->set_package_name(package_name, this->location());
+
+ this->packages_.push_back(p);
}
// Read an indirectimport line.
@@ -503,6 +505,8 @@ Import::read_one_indirect_import()
Package* p = this->gogo_->register_package(pkgpath, "",
Linemap::unknown_location());
p->set_package_name(package_name, this->location());
+
+ this->packages_.push_back(p);
}
// Read the list of import control functions and/or init graph.
@@ -721,12 +725,19 @@ void
Import::import_var()
{
std::string name;
+ Package* vpkg;
+ bool is_exported;
Type* type;
- Variable::import_var(this, &name, &type);
+ if (!Variable::import_var(this, &name, &vpkg, &is_exported, &type))
+ return;
+ if (vpkg == NULL)
+ vpkg = this->package_;
+ if (!is_exported)
+ name = '.' + vpkg->pkgpath() + '.' + name;
Variable* var = new Variable(type, NULL, true, false, false,
this->location_);
Named_object* no;
- no = this->package_->add_variable(name, var);
+ no = vpkg->add_variable(name, var);
if (this->add_to_globals_)
this->gogo_->add_dot_import_object(no);
}
@@ -735,18 +746,27 @@ Import::import_var()
// THIS->PACKAGE_, but it will be different for a method associated
// with a type defined in a different package.
-Named_object*
+void
Import::import_func(Package* package)
{
std::string name;
+ Package* fpkg;
+ bool is_exported;
Typed_identifier* receiver;
Typed_identifier_list* parameters;
Typed_identifier_list* results;
bool is_varargs;
bool nointerface;
+ std::string asm_name;
std::string body;
- Function::import_func(this, &name, &receiver, &parameters, &results,
- &is_varargs, &nointerface, &body);
+ if (!Function::import_func(this, &name, &fpkg, &is_exported, &receiver,
+ &parameters, &results, &is_varargs, &nointerface,
+ &asm_name, &body))
+ return;
+ if (fpkg == NULL)
+ fpkg = package;
+ if (!is_exported)
+ name = '.' + fpkg->pkgpath() + '.' + name;
Function_type *fntype = Type::make_function_type(receiver, parameters,
results, this->location_);
if (is_varargs)
@@ -768,13 +788,13 @@ Import::import_func(Package* package)
rtype = rtype->points_to();
if (rtype->is_error_type())
- return NULL;
+ return;
else if (rtype->named_type() != NULL)
- no = rtype->named_type()->add_method_declaration(name, package, fntype,
+ no = rtype->named_type()->add_method_declaration(name, fpkg, fntype,
loc);
else if (rtype->forward_declaration_type() != NULL)
no = rtype->forward_declaration_type()->add_method_declaration(name,
- package,
+ fpkg,
fntype,
loc);
else
@@ -782,17 +802,17 @@ Import::import_func(Package* package)
}
else
{
- no = package->add_function_declaration(name, fntype, loc);
- if (this->add_to_globals_)
+ no = fpkg->add_function_declaration(name, fntype, loc);
+ if (this->add_to_globals_ && fpkg == package)
this->gogo_->add_dot_import_object(no);
}
if (nointerface)
no->func_declaration_value()->set_nointerface();
+ if (!asm_name.empty())
+ no->func_declaration_value()->set_asm_name(asm_name);
if (!body.empty() && !no->func_declaration_value()->has_imported_body())
no->func_declaration_value()->set_imported_body(this, body);
-
- return no;
}
// Read a type definition and initialize the entry in this->types_.
@@ -905,7 +925,7 @@ Import::read_type()
{
if (!stream->saw_error())
go_error_at(this->location_,
- "error in import data at %d: expected %< %> or %<>%>'",
+ "error in import data at %d: expected %< %> or %<>%>",
stream->pos());
stream->set_saw_error();
stream->advance(1);
@@ -1106,7 +1126,7 @@ Import::type_for_index(int index, const std::string& input_name,
if (static_cast<size_t>(index) >= this->type_offsets_.size())
{
go_error_at(this->location_,
- "error in %s at %lu: bad type index %d >= %d",
+ "error in %s at %lu: bad type index %d, max %d",
input_name.c_str(),
static_cast<unsigned long>(input_offset),
index, static_cast<int>(this->type_offsets_.size()));
@@ -1214,6 +1234,12 @@ Import::register_builtin_type(Gogo* gogo, const char* name, Builtin_code code)
this->builtin_types_[index] = named_object->type_value();
}
+// Characters that stop read_identifier. We base this on the
+// characters that stop an identifier, without worrying about
+// characters that are permitted in an identifier. That lets us skip
+// UTF-8 parsing.
+static const char * const identifier_stop = " \n;:,()[]";
+
// Read an identifier from the stream.
std::string
@@ -1225,14 +1251,74 @@ Import::read_identifier()
while (true)
{
c = stream->peek_char();
- if (c == -1 || c == ' ' || c == '\n' || c == ';' || c == ')')
+ if (c == -1 || strchr(identifier_stop, c) != NULL)
+ break;
+
+ // FIXME: Probably we shouldn't accept '.', but that might break
+ // some existing imports.
+ if (c == '.' && stream->match_c_string("..."))
break;
+
ret += c;
stream->advance(1);
}
return ret;
}
+// Read a possibly qualified identifier from IMP. The qualification
+// is <pID>, where ID is a package number. If the name has a leading
+// '.', it is not exported; otherwise, it is. Set *NAME, *PKG and
+// *IS_EXPORTED. Reports whether the read succeeded.
+
+bool
+Import::read_qualified_identifier(Import_expression* imp, std::string* name,
+ Package** pkg, bool* is_exported)
+{
+ *pkg = NULL;
+ if (imp->match_c_string("<p"))
+ {
+ imp->advance(2);
+ char buf[50];
+ char *pbuf = &buf[0];
+ while (true)
+ {
+ int next = imp->peek_char();
+ if (next == -1 || static_cast<size_t>(pbuf - buf) >= sizeof buf - 1)
+ return false;
+ if (next == '>')
+ {
+ imp->advance(1);
+ break;
+ }
+ *pbuf = static_cast<char>(next);
+ ++pbuf;
+ imp->advance(1);
+ }
+
+ *pbuf = '\0';
+ char *end;
+ long index = strtol(buf, &end, 10);
+ if (*end != '\0'
+ || index <= 0
+ || static_cast<size_t>(index) > imp->max_package_index())
+ return false;
+
+ *pkg = imp->package_at_index(index);
+ go_assert(*pkg != NULL);
+ }
+
+ *is_exported = true;
+ if (imp->match_c_string("."))
+ {
+ imp->advance(1);
+ *is_exported = false;
+ }
+
+ *name = imp->read_identifier();
+
+ return !name->empty();
+}
+
// Read a name from the stream.
std::string
@@ -1450,7 +1536,18 @@ Import_function_body::read_identifier()
for (size_t i = start; i < this->body_.length(); i++)
{
int c = static_cast<unsigned char>(this->body_[i]);
- if (c == ' ' || c == '\n' || c == ';' || c == ')')
+ if (strchr(identifier_stop, c) != NULL)
+ {
+ this->off_ = i;
+ return this->body_.substr(start, i - start);
+ }
+
+ // FIXME: Probably we shouldn't accept '.', but that might break
+ // some existing imports.
+ if (c == '.'
+ && i + 2 < this->body_.length()
+ && this->body_[i + 1] == '.'
+ && this->body_[i + 2] == '.')
{
this->off_ = i;
return this->body_.substr(start, i - start);
@@ -1514,3 +1611,64 @@ Import_function_body::read_type()
return type;
}
+
+// Return the next size to use for a vector mapping indexes to values.
+
+size_t
+Import_function_body::next_size(size_t have)
+{
+ if (have == 0)
+ return 8;
+ else if (have < 256)
+ return have * 2;
+ else
+ return have + 64;
+}
+
+// Record the index of a temporary statement.
+
+void
+Import_function_body::record_temporary(Temporary_statement* temp,
+ unsigned int idx)
+{
+ size_t have = this->temporaries_.size();
+ while (static_cast<size_t>(idx) >= have)
+ {
+ size_t want = Import_function_body::next_size(have);
+ this->temporaries_.resize(want, NULL);
+ have = want;
+ }
+ this->temporaries_[idx] = temp;
+}
+
+// Return a temporary statement given an index.
+
+Temporary_statement*
+Import_function_body::temporary_statement(unsigned int idx)
+{
+ if (static_cast<size_t>(idx) >= this->temporaries_.size())
+ return NULL;
+ return this->temporaries_[idx];
+}
+
+// Return an unnamed label given an index, defining the label if we
+// haven't seen it already.
+
+Unnamed_label*
+Import_function_body::unnamed_label(unsigned int idx, Location loc)
+{
+ size_t have = this->labels_.size();
+ while (static_cast<size_t>(idx) >= have)
+ {
+ size_t want = Import_function_body::next_size(have);
+ this->labels_.resize(want, NULL);
+ have = want;
+ }
+ Unnamed_label* label = this->labels_[idx];
+ if (label == NULL)
+ {
+ label = new Unnamed_label(loc);
+ this->labels_[idx] = label;
+ }
+ return label;
+}
diff --git a/gcc/go/gofrontend/import.h b/gcc/go/gofrontend/import.h
index c46a37e..db51f72 100644
--- a/gcc/go/gofrontend/import.h
+++ b/gcc/go/gofrontend/import.h
@@ -18,6 +18,8 @@ class Named_object;
class Named_type;
class Expression;
class Import_function_body;
+class Temporary_statement;
+class Unnamed_label;
// Expressions can be imported either directly from import data (for
// simple constant expressions that can appear in a const declaration
@@ -72,6 +74,14 @@ class Import_expression
virtual Type*
read_type() = 0;
+ // Return the maximum valid package index.
+ virtual size_t
+ max_package_index() const = 0;
+
+ // Return the package for a package index.
+ virtual Package*
+ package_at_index(int index) = 0;
+
// Return the version number of the export data we're reading.
virtual Export_data_version
version() const = 0;
@@ -257,6 +267,11 @@ class Import : public Import_expression
advance(size_t skip)
{ this->stream_->advance(skip); }
+ // Stream position, for error reporting.
+ int
+ pos()
+ { return this->stream_->pos(); }
+
// Return the version number of the export data we're reading.
Export_data_version
version() const { return this->version_; }
@@ -279,6 +294,18 @@ class Import : public Import_expression
std::string
read_name();
+ // Return the maximum valid package index. This is the size of
+ // packages_ because we will subtract 1 in package_at_index.
+ size_t
+ max_package_index() const
+ { return this->packages_.size(); }
+
+ // Return the package at an index. (We subtract 1 because package
+ // index 0 is not used.)
+ Package*
+ package_at_index(int index)
+ { return this->packages_.at(index - 1); }
+
// Read a type.
Type*
read_type();
@@ -304,6 +331,12 @@ class Import : public Import_expression
ifb()
{ return NULL; }
+ // Read a qualified identifier from an Import_expression. Sets
+ // *NAME, *PKG, and *IS_EXPORTED, and reports whether it succeeded.
+ static bool
+ read_qualified_identifier(Import_expression*, std::string* name,
+ Package** pkg, bool* is_exported);
+
private:
static Stream*
try_package_in_directory(const std::string&, Location);
@@ -360,7 +393,7 @@ class Import : public Import_expression
import_var();
// Import a function.
- Named_object*
+ void
import_func(Package*);
// Parse a type definition.
@@ -401,6 +434,8 @@ class Import : public Import_expression
// Whether to add new objects to the global scope, rather than to a
// package scope.
bool add_to_globals_;
+ // Mapping from package index to package.
+ std::vector<Package*> packages_;
// All type data.
std::string type_data_;
// Position of type data in the stream.
@@ -554,7 +589,8 @@ class Import_function_body : public Import_expression
const std::string& body, size_t off, Block* block,
int indent)
: gogo_(gogo), imp_(imp), named_object_(named_object), body_(body),
- off_(off), block_(block), indent_(indent), saw_error_(false)
+ off_(off), block_(block), indent_(indent), temporaries_(), labels_(),
+ saw_error_(false)
{ }
// The IR.
@@ -567,6 +603,11 @@ class Import_function_body : public Import_expression
location() const
{ return this->imp_->location(); }
+ // The function we are importing.
+ Named_object*
+ function() const
+ { return this->named_object_; }
+
// A reference to the body we are reading.
const std::string&
body() const
@@ -657,11 +698,34 @@ class Import_function_body : public Import_expression
version() const
{ return this->imp_->version(); }
+ // Record the index of a temporary statement.
+ void
+ record_temporary(Temporary_statement*, unsigned int);
+
+ // Return a temporary statement given an index.
+ Temporary_statement*
+ temporary_statement(unsigned int);
+
+ // Return an unnamed label given an index, defining the label if we
+ // haven't seen it already.
+ Unnamed_label*
+ unnamed_label(unsigned int, Location);
+
// Implement Import_expression.
Import_function_body*
ifb()
{ return this; }
+ // Return the maximum valid package index.
+ size_t
+ max_package_index() const
+ { return this->imp_->max_package_index(); }
+
+ // Return the package at an index.
+ Package*
+ package_at_index(int index)
+ { return this->imp_->package_at_index(index); }
+
// Return whether we have seen an error.
bool
saw_error() const
@@ -673,6 +737,9 @@ class Import_function_body : public Import_expression
{ this->saw_error_ = true; }
private:
+ static size_t
+ next_size(size_t);
+
// The IR.
Gogo* gogo_;
// The importer.
@@ -688,6 +755,10 @@ class Import_function_body : public Import_expression
Block* block_;
// Current expected indentation level.
int indent_;
+ // Temporary statements by index.
+ std::vector<Temporary_statement*> temporaries_;
+ // Unnamed labels by index.
+ std::vector<Unnamed_label*> labels_;
// Whether we've seen an error. Used to avoid reporting excess
// errors.
bool saw_error_;
diff --git a/gcc/go/gofrontend/lex.cc b/gcc/go/gofrontend/lex.cc
index e641b7e..82fd355 100644
--- a/gcc/go/gofrontend/lex.cc
+++ b/gcc/go/gofrontend/lex.cc
@@ -1863,7 +1863,7 @@ Lex::skip_cpp_comment()
}
}
if (go_name.empty() || ext_name.empty())
- go_error_at(loc, "usage: //go:linkname localname linkname");
+ go_error_at(loc, "usage: %<//go:linkname%> localname linkname");
else
{
if (this->linknames_ == NULL)
diff --git a/gcc/go/gofrontend/names.cc b/gcc/go/gofrontend/names.cc
index d9ae5910..91cbb4b 100644
--- a/gcc/go/gofrontend/names.cc
+++ b/gcc/go/gofrontend/names.cc
@@ -144,7 +144,14 @@
//
// The import function for the main package is referenced by C code,
// and is named __go_init_main. For other packages it is
-// PKGPATH..import.
+// PKGPATH..import. If a package doesn't need an init function, it
+// will have a dummy one, named ~PKGPATH.
+//
+// In each pacakge there is a list of all the type descriptors defined
+// in this package. The name of the list is PKGPATH..types.
+//
+// In the main package it gathers all the type descriptor lists in a
+// single list, named go..typelists.
//
// The type literal encoding is essentially a single line version of
// the type literal, such as "struct { pkgpath.i int; J int }". In
@@ -525,6 +532,30 @@ Gogo::get_init_fn_name()
return this->init_fn_name_;
}
+// Return the name for a dummy init function, which is not a real
+// function but only for tracking transitive import.
+
+std::string
+Gogo::dummy_init_fn_name()
+{
+ return "~" + this->pkgpath_symbol();
+}
+
+// Return the package path symbol from an init function name, which
+// can be a real init function or a dummy one.
+
+std::string
+Gogo::pkgpath_from_init_fn_name(std::string name)
+{
+ go_assert(!name.empty());
+ if (name[0] == '~')
+ return name.substr(1);
+ size_t pos = name.find("..import");
+ if (pos != std::string::npos)
+ return name.substr(0, pos);
+ go_unreachable();
+}
+
// Return a mangled name for a type. These names appear in symbol
// names in the assembler file for things like type descriptors and
// methods.
@@ -930,7 +961,7 @@ Named_type::append_mangled_type_name(Gogo* gogo, bool use_alias,
// it is the name to use.
std::string
-Gogo::type_descriptor_name(Type* type, Named_type* nt)
+Gogo::type_descriptor_name(const Type* type, Named_type* nt)
{
// The type descriptor symbol for the unsafe.Pointer type is defined
// in libgo/runtime/go-unsafe-pointer.c, so just use a reference to
@@ -985,6 +1016,23 @@ Gogo::type_descriptor_name(Type* type, Named_type* nt)
return ret;
}
+// Return the name of the type descriptor list symbol of a package.
+
+std::string
+Gogo::type_descriptor_list_symbol(std::string pkgpath)
+{
+ return pkgpath + "..types";
+}
+
+// Return the name of the list of all type descriptor lists. This is
+// only used in the main package.
+
+std::string
+Gogo::typelists_symbol()
+{
+ return "go..typelists";
+}
+
// Return the name for the GC symbol for a type. This is used to
// initialize the gcdata field of a type descriptor. This is a local
// name never referenced outside of this assembly file. (Note that
diff --git a/gcc/go/gofrontend/parse.cc b/gcc/go/gofrontend/parse.cc
index e611c70..52371b2 100644
--- a/gcc/go/gofrontend/parse.cc
+++ b/gcc/go/gofrontend/parse.cc
@@ -1359,7 +1359,7 @@ Parse::decl(void (Parse::*pfn)(void*, unsigned int), void* varg,
{
if (pragmas != 0)
go_warning_at(this->location(), 0,
- "ignoring magic //go:... comment before group");
+ "ignoring magic %<//go:...%> comment before group");
if (!this->advance_token()->is_op(OPERATOR_RPAREN))
{
this->list(pfn, varg, true);
@@ -1605,7 +1605,7 @@ Parse::type_spec(void*, unsigned int pragmas)
}
if (pragmas != 0)
go_warning_at(location, 0,
- "ignoring magic //go:... comment before type");
+ "ignoring magic %<//go:...%> comment before type");
}
else
{
@@ -1633,7 +1633,7 @@ Parse::var_spec(void*, unsigned int pragmas)
{
if (pragmas != 0)
go_warning_at(this->location(), 0,
- "ignoring magic //go:... comment before var");
+ "ignoring magic %<//go:...%> comment before var");
// Get the variable names.
Typed_identifier_list til;
@@ -2383,7 +2383,7 @@ Parse::function_decl(unsigned int pragmas)
if (pragma_check[i].decl_ok)
continue;
go_warning_at(location, 0,
- ("ignoring magic //go:%s comment "
+ ("ignoring magic %<//go:%s%> comment "
"before declaration"),
pragma_check[i].name);
}
@@ -2392,7 +2392,7 @@ Parse::function_decl(unsigned int pragmas)
if (pragma_check[i].func_ok)
continue;
go_warning_at(location, 0,
- ("ignoring magic //go:%s comment "
+ ("ignoring magic %<//go:%s%> comment "
"before function definition"),
pragma_check[i].name);
}
@@ -2401,7 +2401,7 @@ Parse::function_decl(unsigned int pragmas)
if (pragma_check[i].method_ok)
continue;
go_warning_at(location, 0,
- ("ignoring magic //go:%s comment "
+ ("ignoring magic %<//go:%s%> comment "
"before method definition"),
pragma_check[i].name);
}
@@ -2602,7 +2602,7 @@ Parse::operand(bool may_be_sink, bool* is_parenthesized)
return Expression::make_sink(location);
else
{
- go_error_at(location, "cannot use _ as value");
+ go_error_at(location, "cannot use %<_%> as value");
return Expression::make_error(location);
}
case Named_object::NAMED_OBJECT_FUNC:
@@ -4178,7 +4178,7 @@ Parse::tuple_assignment(Expression_list* lhs, bool may_be_composite_lit,
if ((*pe)->is_error_expression())
return;
if (op != OPERATOR_EQ && (*pe)->is_sink_expression())
- go_error_at((*pe)->location(), "cannot use _ as value");
+ go_error_at((*pe)->location(), "cannot use %<_%> as value");
}
for (Expression_list::const_iterator pe = vals->begin();
pe != vals->end();
@@ -5721,7 +5721,7 @@ Parse::package_clause()
name = token->identifier();
if (name == "_")
{
- go_error_at(this->location(), "invalid package name _");
+ go_error_at(this->location(), "invalid package name %<_%>");
name = Gogo::erroneous_name();
}
this->advance_token();
@@ -5752,7 +5752,7 @@ Parse::import_spec(void*, unsigned int pragmas)
{
if (pragmas != 0)
go_warning_at(this->location(), 0,
- "ignoring magic //go:... comment before import");
+ "ignoring magic %<//go:...%> comment before import");
const Token* token = this->peek_token();
Location location = token->location();
@@ -5876,7 +5876,7 @@ Parse::verify_not_sink(Expression* expr)
{
if (expr->is_sink_expression())
{
- go_error_at(expr->location(), "cannot use _ as value");
+ go_error_at(expr->location(), "cannot use %<_%> as value");
expr = Expression::make_error(expr->location());
}
diff --git a/gcc/go/gofrontend/runtime.cc b/gcc/go/gofrontend/runtime.cc
index 7ecbf68..e35658b 100644
--- a/gcc/go/gofrontend/runtime.cc
+++ b/gcc/go/gofrontend/runtime.cc
@@ -30,8 +30,14 @@ enum Runtime_function_type
RFT_BOOLPTR,
// Go type int, C type intgo.
RFT_INT,
+ // Go type uint8, C type uint8_t.
+ RFT_UINT8,
+ // Go type uint16, C type uint16_t.
+ RFT_UINT16,
// Go type int32, C type int32_t.
RFT_INT32,
+ // Go type uint32, C type uint32_t.
+ RFT_UINT32,
// Go type int64, C type int64_t.
RFT_INT64,
// Go type uint64, C type uint64_t.
@@ -107,10 +113,22 @@ runtime_function_type(Runtime_function_type bft)
t = Type::lookup_integer_type("int");
break;
+ case RFT_UINT8:
+ t = Type::lookup_integer_type("uint8");
+ break;
+
+ case RFT_UINT16:
+ t = Type::lookup_integer_type("uint16");
+ break;
+
case RFT_INT32:
t = Type::lookup_integer_type("int32");
break;
+ case RFT_UINT32:
+ t = Type::lookup_integer_type("uint32");
+ break;
+
case RFT_INT64:
t = Type::lookup_integer_type("int64");
break;
@@ -244,7 +262,10 @@ convert_to_runtime_function_type(Runtime_function_type bft, Expression* e,
case RFT_BOOL:
case RFT_BOOLPTR:
case RFT_INT:
+ case RFT_UINT8:
+ case RFT_UINT16:
case RFT_INT32:
+ case RFT_UINT32:
case RFT_INT64:
case RFT_UINT64:
case RFT_UINTPTR:
diff --git a/gcc/go/gofrontend/runtime.def b/gcc/go/gofrontend/runtime.def
index c17b481..f510a65 100644
--- a/gcc/go/gofrontend/runtime.def
+++ b/gcc/go/gofrontend/runtime.def
@@ -29,34 +29,19 @@
// result types.
// The standard C memcmp function, used for struct comparisons.
-DEF_GO_RUNTIME(MEMCMP, "__go_memcmp", P3(POINTER, POINTER, UINTPTR), R1(INT))
+DEF_GO_RUNTIME(MEMCMP, "__builtin_memcmp", P3(POINTER, POINTER, UINTPTR), R1(INT32))
// Decode a non-ASCII rune from a string.
DEF_GO_RUNTIME(DECODERUNE, "runtime.decoderune", P2(STRING, INT),
R2(RUNE, INT))
// Concatenate strings.
-DEF_GO_RUNTIME(CONCATSTRINGS, "runtime.concatstrings", P2(POINTER, SLICE),
- R1(STRING))
-DEF_GO_RUNTIME(CONCATSTRING2, "runtime.concatstring2",
- P2(POINTER, ARRAY2STRING), R1(STRING))
-DEF_GO_RUNTIME(CONCATSTRING3, "runtime.concatstring3",
- P2(POINTER, ARRAY3STRING), R1(STRING))
-DEF_GO_RUNTIME(CONCATSTRING4, "runtime.concatstring4",
- P2(POINTER, ARRAY4STRING), R1(STRING))
-DEF_GO_RUNTIME(CONCATSTRING5, "runtime.concatstring5",
- P2(POINTER, ARRAY5STRING), R1(STRING))
-
-// Compare two strings for equality.
-DEF_GO_RUNTIME(EQSTRING, "runtime.eqstring", P2(STRING, STRING), R1(BOOL))
+DEF_GO_RUNTIME(CONCATSTRINGS, "runtime.concatstrings",
+ P3(POINTER, POINTER, INT), R1(STRING))
// Compare two strings.
DEF_GO_RUNTIME(CMPSTRING, "runtime.cmpstring", P2(STRING, STRING), R1(INT))
-// Take a slice of a string.
-DEF_GO_RUNTIME(STRING_SLICE, "__go_string_slice", P3(STRING, INT, INT),
- R1(STRING))
-
// Convert an integer to a string.
DEF_GO_RUNTIME(INTSTRING, "runtime.intstring", P2(POINTER, INT64), R1(STRING))
@@ -109,6 +94,18 @@ DEF_GO_RUNTIME(CONSTRUCT_MAP, "__go_construct_map",
DEF_GO_RUNTIME(MAPACCESS1, "runtime.mapaccess1", P3(TYPE, MAP, POINTER),
R1(POINTER))
+// Look up a uint32 key in a map.
+DEF_GO_RUNTIME(MAPACCESS1_FAST32, "runtime.mapaccess1_fast32",
+ P3(TYPE, MAP, UINT32), R1(POINTER))
+
+// Look up a uint64 key in a map.
+DEF_GO_RUNTIME(MAPACCESS1_FAST64, "runtime.mapaccess1_fast64",
+ P3(TYPE, MAP, UINT64), R1(POINTER))
+
+// Look up a string key in a map.
+DEF_GO_RUNTIME(MAPACCESS1_FASTSTR, "runtime.mapaccess1_faststr",
+ P3(TYPE, MAP, STRING), R1(POINTER))
+
// Look up a key in a map when the value is large.
DEF_GO_RUNTIME(MAPACCESS1_FAT, "runtime.mapaccess1_fat",
P4(TYPE, MAP, POINTER, POINTER), R1(POINTER))
@@ -118,6 +115,21 @@ DEF_GO_RUNTIME(MAPACCESS1_FAT, "runtime.mapaccess1_fat",
DEF_GO_RUNTIME(MAPACCESS2, "runtime.mapaccess2", P3(TYPE, MAP, POINTER),
R2(POINTER, BOOL))
+// Look up a uint32 key in a map returning the value and whether
+// it is present.
+DEF_GO_RUNTIME(MAPACCESS2_FAST32, "runtime.mapaccess2_fast32",
+ P3(TYPE, MAP, UINT32), R2(POINTER, BOOL))
+
+// Look up a uint64 key in a map returning the value and whether
+// it is present.
+DEF_GO_RUNTIME(MAPACCESS2_FAST64, "runtime.mapaccess2_fast64",
+ P3(TYPE, MAP, UINT64), R2(POINTER, BOOL))
+
+// Look up a string key in a map returning the value and whether
+// it is present.
+DEF_GO_RUNTIME(MAPACCESS2_FASTSTR, "runtime.mapaccess2_faststr",
+ P3(TYPE, MAP, STRING), R2(POINTER, BOOL))
+
// Look up a key in a map, returning the value and whether it is
// present, when the value is large.
DEF_GO_RUNTIME(MAPACCESS2_FAT, "runtime.mapaccess2_fat",
@@ -127,9 +139,41 @@ DEF_GO_RUNTIME(MAPACCESS2_FAT, "runtime.mapaccess2_fat",
DEF_GO_RUNTIME(MAPASSIGN, "runtime.mapassign", P3(TYPE, MAP, POINTER),
R1(POINTER))
+// Assignment to a uint32 key in a map.
+DEF_GO_RUNTIME(MAPASSIGN_FAST32, "runtime.mapassign_fast32",
+ P3(TYPE, MAP, UINT32), R1(POINTER))
+
+// Assignment to a uint64 key in a map.
+DEF_GO_RUNTIME(MAPASSIGN_FAST64, "runtime.mapassign_fast64",
+ P3(TYPE, MAP, UINT64), R1(POINTER))
+
+// Assignment to a 32-bit pointer key in a map.
+DEF_GO_RUNTIME(MAPASSIGN_FAST32PTR, "runtime.mapassign_fast32ptr",
+ P3(TYPE, MAP, POINTER), R1(POINTER))
+
+// Assignment to a 64-bit pointer key in a map.
+DEF_GO_RUNTIME(MAPASSIGN_FAST64PTR, "runtime.mapassign_fast64ptr",
+ P3(TYPE, MAP, POINTER), R1(POINTER))
+
+// Assignment to a string key in a map.
+DEF_GO_RUNTIME(MAPASSIGN_FASTSTR, "runtime.mapassign_faststr",
+ P3(TYPE, MAP, STRING), R1(POINTER))
+
// Delete a key from a map.
DEF_GO_RUNTIME(MAPDELETE, "runtime.mapdelete", P3(TYPE, MAP, POINTER), R0())
+// Delete a uint32 key from a map.
+DEF_GO_RUNTIME(MAPDELETE_FAST32, "runtime.mapdelete_fast32",
+ P3(TYPE, MAP, UINT32), R0())
+
+// Delete a uint64 key from a map.
+DEF_GO_RUNTIME(MAPDELETE_FAST64, "runtime.mapdelete_fast64",
+ P3(TYPE, MAP, UINT64), R0())
+
+// Delete a string key from a map.
+DEF_GO_RUNTIME(MAPDELETE_FASTSTR, "runtime.mapdelete_faststr",
+ P3(TYPE, MAP, STRING), R0())
+
// Begin a range over a map.
DEF_GO_RUNTIME(MAPITERINIT, "runtime.mapiterinit", P3(TYPE, MAP, POINTER),
R0())
@@ -212,6 +256,10 @@ DEF_GO_RUNTIME(GROWSLICE, "runtime.growslice",
// Register roots (global variables) for the garbage collector.
DEF_GO_RUNTIME(REGISTER_GC_ROOTS, "runtime.registerGCRoots", P1(POINTER), R0())
+// Register type descriptors.
+DEF_GO_RUNTIME(REGISTER_TYPE_DESCRIPTORS, "runtime.registerTypeDescriptors",
+ P2(INT, POINTER), R0())
+
// Allocate memory.
DEF_GO_RUNTIME(NEW, "runtime.newobject", P1(TYPE), R1(POINTER))
@@ -269,23 +317,13 @@ DEF_GO_RUNTIME(ASSERTITAB, "runtime.assertitab", P2(TYPE, TYPE), R1(POINTER))
DEF_GO_RUNTIME(REQUIREITAB, "runtime.requireitab", P2(TYPE, TYPE),
R1(POINTER))
-// Check whether an interface type may be converted to a
-// non-interface type.
-DEF_GO_RUNTIME(ASSERTI2T, "runtime.assertI2T", P3(TYPE, TYPE, TYPE), R0())
+// Panic when an interface type to non-interface type conversion fails.
+DEF_GO_RUNTIME(PANICDOTTYPE, "runtime.panicdottype", P3(TYPE, TYPE, TYPE),
+ R0())
// Return whether we can convert a type to an interface type.
DEF_GO_RUNTIME(IFACET2IP, "runtime.ifaceT2Ip", P2(TYPE, TYPE), R1(BOOL))
-// Get the type descriptor of an empty interface.
-DEF_GO_RUNTIME(EFACETYPE, "runtime.efacetype", P1(EFACE), R1(TYPE))
-
-// Get the type descriptor of a non-empty interface.
-DEF_GO_RUNTIME(IFACETYPE, "runtime.ifacetype", P1(IFACE), R1(TYPE))
-
-
-// Compare two type descriptors for equality.
-DEF_GO_RUNTIME(IFACETYPEEQ, "runtime.ifacetypeeq", P2(TYPE, TYPE), R1(BOOL))
-
// Compare two empty interface values.
DEF_GO_RUNTIME(EFACEEQ, "runtime.efaceeq", P2(EFACE, EFACE), R1(BOOL))
@@ -313,10 +351,6 @@ DEF_GO_RUNTIME(GCWRITEBARRIER, "runtime.gcWriteBarrier",
DEF_GO_RUNTIME(TYPEDMEMMOVE, "runtime.typedmemmove",
P3(TYPE, POINTER, POINTER), R0())
-// Clear memory that contains no pointer.
-DEF_GO_RUNTIME(MEMCLRNOPTR, "runtime.memclrNoHeapPointers",
- P2(POINTER, UINTPTR), R0())
-
// Clear memory that contains pointer.
DEF_GO_RUNTIME(MEMCLRHASPTR, "runtime.memclrHasPointers",
P2(POINTER, UINTPTR), R0())
@@ -376,6 +410,72 @@ DEF_GO_RUNTIME(UNREACHABLE, "__builtin_unreachable", P0(), R0())
DEF_GO_RUNTIME(BUILTIN_MEMMOVE, "__builtin_memmove",
P3(POINTER, POINTER, UINTPTR), R0())
+// Memset, used for zeroing memory.
+DEF_GO_RUNTIME(BUILTIN_MEMSET, "__builtin_memset",
+ P3(POINTER, INT32, UINTPTR), R0())
+
+// Various intrinsics.
+
+// Get the caller's PC, used for runtime.getcallerpc.
+DEF_GO_RUNTIME(BUILTIN_RETURN_ADDRESS, "__builtin_return_address",
+ P1(UINT32), R1(POINTER))
+
+// Get the caller's SP, used for runtime.getcallersp.
+DEF_GO_RUNTIME(BUILTIN_DWARF_CFA, "__builtin_dwarf_cfa", P0(),
+ R1(POINTER))
+
+// Swap bytes.
+DEF_GO_RUNTIME(BUILTIN_BSWAP16, "__builtin_bswap16", P1(UINT16),
+ R1(UINT16))
+DEF_GO_RUNTIME(BUILTIN_BSWAP32, "__builtin_bswap32", P1(UINT32),
+ R1(UINT32))
+DEF_GO_RUNTIME(BUILTIN_BSWAP64, "__builtin_bswap64", P1(UINT64),
+ R1(UINT64))
+
+// Count trailing zeros.
+DEF_GO_RUNTIME(BUILTIN_CTZ, "__builtin_ctz", P1(UINT32), R1(INT32))
+DEF_GO_RUNTIME(BUILTIN_CTZLL, "__builtin_ctzll", P1(UINT64), R1(INT32))
+
+// Count leading zeros.
+DEF_GO_RUNTIME(BUILTIN_CLZ, "__builtin_clz", P1(UINT32), R1(INT32))
+DEF_GO_RUNTIME(BUILTIN_CLZLL, "__builtin_clzll", P1(UINT64), R1(INT32))
+
+// Count one bits.
+DEF_GO_RUNTIME(BUILTIN_POPCOUNT, "__builtin_popcount", P1(UINT32), R1(INT32))
+DEF_GO_RUNTIME(BUILTIN_POPCOUNTLL, "__builtin_popcountll", P1(UINT64), R1(INT32))
+
+// Atomics.
+DEF_GO_RUNTIME(ATOMIC_LOAD_4, "__atomic_load_4", P2(POINTER, INT32),
+ R1(UINT32))
+DEF_GO_RUNTIME(ATOMIC_LOAD_8, "__atomic_load_8", P2(POINTER, INT32),
+ R1(UINT64))
+DEF_GO_RUNTIME(ATOMIC_STORE_4, "__atomic_store_4", P3(POINTER, UINT32, INT32),
+ R0())
+DEF_GO_RUNTIME(ATOMIC_STORE_8, "__atomic_store_8", P3(POINTER, UINT64, INT32),
+ R0())
+DEF_GO_RUNTIME(ATOMIC_EXCHANGE_4, "__atomic_exchange_4", P3(POINTER, UINT32, INT32),
+ R1(UINT32))
+DEF_GO_RUNTIME(ATOMIC_EXCHANGE_8, "__atomic_exchange_8", P3(POINTER, UINT64, INT32),
+ R1(UINT64))
+DEF_GO_RUNTIME(ATOMIC_COMPARE_EXCHANGE_4, "__atomic_compare_exchange_4",
+ P6(POINTER, POINTER, UINT32, BOOL, INT32, INT32),
+ R1(BOOL))
+DEF_GO_RUNTIME(ATOMIC_COMPARE_EXCHANGE_8, "__atomic_compare_exchange_8",
+ P6(POINTER, POINTER, UINT64, BOOL, INT32, INT32),
+ R1(BOOL))
+DEF_GO_RUNTIME(ATOMIC_ADD_FETCH_4, "__atomic_add_fetch_4",
+ P3(POINTER, UINT32, INT32),
+ R1(UINT32))
+DEF_GO_RUNTIME(ATOMIC_ADD_FETCH_8, "__atomic_add_fetch_8",
+ P3(POINTER, UINT64, INT32),
+ R1(UINT64))
+DEF_GO_RUNTIME(ATOMIC_AND_FETCH_1, "__atomic_and_fetch_1",
+ P3(POINTER, UINT8, INT32),
+ R1(UINT8))
+DEF_GO_RUNTIME(ATOMIC_OR_FETCH_1, "__atomic_or_fetch_1",
+ P3(POINTER, UINT8, INT32),
+ R1(UINT8))
+
// Remove helper macros.
#undef ABFT6
#undef ABFT2
diff --git a/gcc/go/gofrontend/statements.cc b/gcc/go/gofrontend/statements.cc
index 2e2d039..968c8a0 100644
--- a/gcc/go/gofrontend/statements.cc
+++ b/gcc/go/gofrontend/statements.cc
@@ -129,24 +129,15 @@ Statement::import_statement(Import_function_body* ifb, Location loc)
{
if (ifb->match_c_string("{"))
{
- size_t nl = ifb->body().find('\n', ifb->off());
- if (nl == std::string::npos)
- {
- if (!ifb->saw_error())
- go_error_at(ifb->location(),
- "import error: no newline after { at %lu",
- static_cast<unsigned long>(ifb->off()));
- ifb->set_saw_error();
- return Statement::make_error_statement(loc);
- }
- ifb->set_off(nl + 1);
- ifb->increment_indent();
- Block* block = new Block(ifb->block(), loc);
- bool ok = Block::import_block(block, ifb, loc);
- ifb->decrement_indent();
- if (!ok)
+ bool is_lowered_for_statement;
+ Block* block = Block_statement::do_import(ifb, loc,
+ &is_lowered_for_statement);
+ if (block == NULL)
return Statement::make_error_statement(loc);
- return Statement::make_block_statement(block, loc);
+ Block_statement* s = Statement::make_block_statement(block, loc);
+ if (is_lowered_for_statement)
+ s->set_is_lowered_for_statement();
+ return s;
}
else if (ifb->match_c_string("return"))
{
@@ -155,6 +146,16 @@ Statement::import_statement(Import_function_body* ifb, Location loc)
ifb->advance(6);
return Statement::make_return_statement(NULL, loc);
}
+ else if (ifb->match_c_string("var $t"))
+ return Temporary_statement::do_import(ifb, loc);
+ else if (ifb->match_c_string("var "))
+ return Variable_declaration_statement::do_import(ifb, loc);
+ else if (ifb->match_c_string("if "))
+ return If_statement::do_import(ifb, loc);
+ else if (ifb->match_c_string(":"))
+ return Label_statement::do_import(ifb, loc);
+ else if (ifb->match_c_string("goto "))
+ return Goto_statement::do_import(ifb, loc);
Expression* lhs = Expression::import_expression(ifb, loc);
ifb->require_c_string(" = ");
@@ -322,6 +323,22 @@ Variable_declaration_statement::do_flatten(Gogo* gogo, Named_object* function,
return this;
}
+// Add explicit type conversions.
+
+void
+Variable_declaration_statement::do_add_conversions()
+{
+ Variable* var = this->var_->var_value();
+ Expression* init = var->init();
+ if (init == NULL)
+ return;
+ Type* lt = var->type();
+ Type* rt = init->type();
+ if (!Type::are_identical(lt, rt, 0, NULL)
+ && lt->interface_type() != NULL)
+ var->set_init(Expression::make_cast(lt, init, this->location()));
+}
+
// Convert a variable declaration to the backend representation.
Bstatement*
@@ -408,6 +425,55 @@ Statement::make_variable_declaration(Named_object* var)
return new Variable_declaration_statement(var);
}
+// Export a variable declaration.
+
+void
+Variable_declaration_statement::do_export_statement(Export_function_body* efb)
+{
+ efb->write_c_string("var ");
+ efb->write_string(Gogo::unpack_hidden_name(this->var_->name()));
+ efb->write_c_string(" ");
+ Variable* var = this->var_->var_value();
+ Type* type = var->type();
+ efb->write_type(type);
+ Expression* init = var->init();
+ if (init != NULL)
+ {
+ efb->write_c_string(" = ");
+
+ go_assert(efb->type_context() == NULL);
+ efb->set_type_context(type);
+
+ init->export_expression(efb);
+
+ efb->set_type_context(NULL);
+ }
+}
+
+// Import a variable declaration.
+
+Statement*
+Variable_declaration_statement::do_import(Import_function_body* ifb,
+ Location loc)
+{
+ ifb->require_c_string("var ");
+ std::string id = ifb->read_identifier();
+ ifb->require_c_string(" ");
+ Type* type = ifb->read_type();
+ Expression* init = NULL;
+ if (ifb->match_c_string(" = "))
+ {
+ ifb->advance(3);
+ init = Expression::import_expression(ifb, loc);
+ }
+ Variable* var = new Variable(type, init, false, false, false, loc);
+ var->set_is_used();
+ // FIXME: The package we are importing does not yet exist, so we
+ // can't pass the correct package here. It probably doesn't matter.
+ Named_object* no = ifb->block()->bindings()->add_variable(id, NULL, var);
+ return Statement::make_variable_declaration(no);
+}
+
// Class Temporary_statement.
// Return the type of the temporary variable.
@@ -529,6 +595,20 @@ Temporary_statement::do_flatten(Gogo*, Named_object*, Block*,
return this;
}
+// Add explicit type conversions.
+
+void
+Temporary_statement::do_add_conversions()
+{
+ if (this->init_ == NULL)
+ return;
+ Type* lt = this->type();
+ Type* rt = this->init_->type();
+ if (!Type::are_identical(lt, rt, 0, NULL)
+ && lt->interface_type() != NULL)
+ this->init_ = Expression::make_cast(lt, this->init_, this->location());
+}
+
// Convert to backend representation.
Bstatement*
@@ -610,6 +690,87 @@ Statement::make_temporary(Type* type, Expression* init,
return new Temporary_statement(type, init, location);
}
+// Export a temporary statement.
+
+void
+Temporary_statement::do_export_statement(Export_function_body* efb)
+{
+ unsigned int idx = efb->record_temporary(this);
+ char buf[100];
+ snprintf(buf, sizeof buf, "var $t%u", idx);
+ efb->write_c_string(buf);
+ if (this->type_ != NULL)
+ {
+ efb->write_c_string(" ");
+ efb->write_type(this->type_);
+ }
+ if (this->init_ != NULL)
+ {
+ efb->write_c_string(" = ");
+
+ go_assert(efb->type_context() == NULL);
+ efb->set_type_context(this->type_);
+
+ this->init_->export_expression(efb);
+
+ efb->set_type_context(NULL);
+ }
+}
+
+// Import a temporary statement.
+
+Statement*
+Temporary_statement::do_import(Import_function_body* ifb, Location loc)
+{
+ ifb->require_c_string("var ");
+ std::string id = ifb->read_identifier();
+ go_assert(id[0] == '$' && id[1] == 't');
+ const char *p = id.c_str();
+ char *end;
+ long idx = strtol(p + 2, &end, 10);
+ if (*end != '\0' || idx > 0x7fffffff)
+ {
+ if (!ifb->saw_error())
+ go_error_at(loc,
+ ("invalid export data for %qs: "
+ "bad temporary statement index at %lu"),
+ ifb->name().c_str(),
+ static_cast<unsigned long>(ifb->off()));
+ ifb->set_saw_error();
+ return Statement::make_error_statement(loc);
+ }
+
+ Type* type = NULL;
+ if (!ifb->match_c_string(" = "))
+ {
+ ifb->require_c_string(" ");
+ type = ifb->read_type();
+ }
+ Expression* init = NULL;
+ if (ifb->match_c_string(" = "))
+ {
+ ifb->advance(3);
+ init = Expression::import_expression(ifb, loc);
+ }
+ if (type == NULL && init == NULL)
+ {
+ if (!ifb->saw_error())
+ go_error_at(loc,
+ ("invalid export data for %qs: "
+ "temporary statement has neither type nor init at %lu"),
+ ifb->name().c_str(),
+ static_cast<unsigned long>(ifb->off()));
+ ifb->set_saw_error();
+ return Statement::make_error_statement(loc);
+ }
+
+ Temporary_statement* temp = Statement::make_temporary(type, init, loc);
+
+ ifb->record_temporary(temp, static_cast<unsigned int>(idx));
+
+ return temp;
+}
+
// The Move_subexpressions class is used to move all top-level
// subexpressions of an expression. This is used for things like
// index expressions in which we must evaluate the index value before
@@ -733,7 +894,7 @@ Assignment_statement::do_traverse_assignments(Traverse_assignments* tassign)
// call. Mark some slice assignments as not requiring a write barrier.
Statement*
-Assignment_statement::do_lower(Gogo*, Named_object*, Block* enclosing,
+Assignment_statement::do_lower(Gogo* gogo, Named_object*, Block* enclosing,
Statement_inserter*)
{
Map_index_expression* mie = this->lhs_->map_index_expression();
@@ -781,7 +942,59 @@ Assignment_statement::do_lower(Gogo*, Named_object*, Block* enclosing,
Temporary_reference_expression* ref =
Expression::make_temporary_reference(key_temp, loc);
Expression* a3 = Expression::make_unary(OPERATOR_AND, ref, loc);
- Expression* call = Runtime::make_call(Runtime::MAPASSIGN, loc, 3,
+ Runtime::Function code;
+ Map_type::Map_alg alg = mt->algorithm(gogo);
+ switch (alg)
+ {
+ case Map_type::MAP_ALG_FAST32:
+ {
+ code = Runtime::MAPASSIGN_FAST32;
+ Type* uint32_type = Type::lookup_integer_type("uint32");
+ Type* uint32_ptr_type = Type::make_pointer_type(uint32_type);
+ a3 = Expression::make_unsafe_cast(uint32_ptr_type, a3,
+ loc);
+ a3 = Expression::make_dereference(a3,
+ Expression::NIL_CHECK_NOT_NEEDED,
+ loc);
+ break;
+ }
+ case Map_type::MAP_ALG_FAST64:
+ {
+ code = Runtime::MAPASSIGN_FAST64;
+ Type* uint64_type = Type::lookup_integer_type("uint64");
+ Type* uint64_ptr_type = Type::make_pointer_type(uint64_type);
+ a3 = Expression::make_unsafe_cast(uint64_ptr_type, a3,
+ loc);
+ a3 = Expression::make_dereference(a3,
+ Expression::NIL_CHECK_NOT_NEEDED,
+ loc);
+ break;
+ }
+ case Map_type::MAP_ALG_FAST32PTR:
+ case Map_type::MAP_ALG_FAST64PTR:
+ {
+ code = (alg == Map_type::MAP_ALG_FAST32PTR
+ ? Runtime::MAPASSIGN_FAST32PTR
+ : Runtime::MAPASSIGN_FAST64PTR);
+ Type* ptr_type =
+ Type::make_pointer_type(Type::make_void_type());
+ Type* ptr_ptr_type = Type::make_pointer_type(ptr_type);
+ a3 = Expression::make_unsafe_cast(ptr_ptr_type, a3,
+ loc);
+ a3 = Expression::make_dereference(a3,
+ Expression::NIL_CHECK_NOT_NEEDED,
+ loc);
+ break;
+ }
+ case Map_type::MAP_ALG_FASTSTR:
+ code = Runtime::MAPASSIGN_FASTSTR;
+ a3 = ref;
+ break;
+ default:
+ code = Runtime::MAPASSIGN;
+ break;
+ }
+ Expression* call = Runtime::make_call(code, loc, 3,
a1, a2, a3);
Type* ptrval_type = Type::make_pointer_type(mt->val_type());
call = Expression::make_cast(ptrval_type, call, loc);
@@ -808,6 +1021,18 @@ Assignment_statement::do_lower(Gogo*, Named_object*, Block* enclosing,
&& ival == 0)
this->omit_write_barrier_ = true;
}
+ String_index_expression* sie = this->rhs_->string_index_expression();
+ if (sie != NULL
+ && sie->end() != NULL
+ && Expression::is_same_variable(this->lhs_, sie->string()))
+ {
+ Numeric_constant nc;
+ unsigned long ival;
+ if (sie->start()->numeric_constant_value(&nc)
+ && nc.to_unsigned_long(&ival) == Numeric_constant::NC_UL_VALID
+ && ival == 0)
+ this->omit_write_barrier_ = true;
+ }
return this;
}
@@ -907,6 +1132,18 @@ Assignment_statement::do_flatten(Gogo*, Named_object*, Block*,
return this;
}
+// Add explicit type conversions.
+
+void
+Assignment_statement::do_add_conversions()
+{
+ Type* lt = this->lhs_->type();
+ Type* rt = this->rhs_->type();
+ if (!Type::are_identical(lt, rt, 0, NULL)
+ && lt->interface_type() != NULL)
+ this->rhs_ = Expression::make_cast(lt, this->rhs_, this->location());
+}
+
// Convert an assignment statement to the backend representation.
Bstatement*
@@ -948,6 +1185,9 @@ Assignment_statement*
Statement::make_assignment(Expression* lhs, Expression* rhs,
Location location)
{
+ Temporary_reference_expression* tre = lhs->temporary_reference_expression();
+ if (tre != NULL)
+ tre->statement()->set_assigned();
return new Assignment_statement(lhs, rhs, location);
}
@@ -1307,6 +1547,13 @@ Tuple_map_assignment_statement::do_lower(Gogo* gogo, Named_object*,
if (map_type == NULL)
return Statement::make_error_statement(loc);
+ // Avoid copy for string([]byte) conversions used in map keys.
+ // mapaccess doesn't keep the reference, so this is safe.
+ Type_conversion_expression* ce = map_index->index()->conversion_expression();
+ if (ce != NULL && ce->type()->is_string_type()
+ && ce->expr()->type()->is_slice_type())
+ ce->set_no_copy(true);
+
Block* b = new Block(enclosing, loc);
// Move out any subexpressions to make sure that functions are
@@ -1346,7 +1593,47 @@ Tuple_map_assignment_statement::do_lower(Gogo* gogo, Named_object*,
Expression* a4 = map_type->fat_zero_value(gogo);
Call_expression* call;
if (a4 == NULL)
- call = Runtime::make_call(Runtime::MAPACCESS2, loc, 3, a1, a2, a3);
+ {
+ Runtime::Function code;
+ Map_type::Map_alg alg = map_type->algorithm(gogo);
+ switch (alg)
+ {
+ case Map_type::MAP_ALG_FAST32:
+ case Map_type::MAP_ALG_FAST32PTR:
+ {
+ code = Runtime::MAPACCESS2_FAST32;
+ Type* uint32_type = Type::lookup_integer_type("uint32");
+ Type* uint32_ptr_type = Type::make_pointer_type(uint32_type);
+ a3 = Expression::make_unsafe_cast(uint32_ptr_type, a3,
+ loc);
+ a3 = Expression::make_dereference(a3,
+ Expression::NIL_CHECK_NOT_NEEDED,
+ loc);
+ break;
+ }
+ case Map_type::MAP_ALG_FAST64:
+ case Map_type::MAP_ALG_FAST64PTR:
+ {
+ code = Runtime::MAPACCESS2_FAST64;
+ Type* uint64_type = Type::lookup_integer_type("uint64");
+ Type* uint64_ptr_type = Type::make_pointer_type(uint64_type);
+ a3 = Expression::make_unsafe_cast(uint64_ptr_type, a3,
+ loc);
+ a3 = Expression::make_dereference(a3,
+ Expression::NIL_CHECK_NOT_NEEDED,
+ loc);
+ break;
+ }
+ case Map_type::MAP_ALG_FASTSTR:
+ code = Runtime::MAPACCESS2_FASTSTR;
+ a3 = ref;
+ break;
+ default:
+ code = Runtime::MAPACCESS2;
+ break;
+ }
+ call = Runtime::make_call(code, loc, 3, a1, a2, a3);
+ }
else
call = Runtime::make_call(Runtime::MAPACCESS2_FAT, loc, 4, a1, a2, a3, a4);
ref = Expression::make_temporary_reference(val_ptr_temp, loc);
@@ -1836,13 +2123,24 @@ Statement::make_statement(Expression* expr, bool is_ignored)
void
Block_statement::do_export_statement(Export_function_body* efb)
{
+ Block_statement::export_block(efb, this->block_,
+ this->is_lowered_for_statement_);
+}
+
+void
+Block_statement::export_block(Export_function_body* efb, Block* block,
+ bool is_lowered_for_statement)
+{
// We are already indented to the right position.
char buf[50];
- snprintf(buf, sizeof buf, "{ //%d\n",
- Linemap::location_to_line(this->block_->start_location()));
+ efb->write_c_string("{");
+ if (is_lowered_for_statement)
+ efb->write_c_string(" /*for*/");
+ snprintf(buf, sizeof buf, " //%d\n",
+ Linemap::location_to_line(block->start_location()));
efb->write_c_string(buf);
- this->block_->export_block(efb);
+ block->export_block(efb);
// The indentation is correct for the statements in the block, so
// subtract one for the closing curly brace.
efb->decrement_indent();
@@ -1852,6 +2150,39 @@ Block_statement::do_export_statement(Export_function_body* efb)
efb->increment_indent();
}
+// Import a block statement, returning the block.
+
+Block*
+Block_statement::do_import(Import_function_body* ifb, Location loc,
+ bool* is_lowered_for_statement)
+{
+ go_assert(ifb->match_c_string("{"));
+ *is_lowered_for_statement = false;
+ if (ifb->match_c_string(" /*for*/"))
+ {
+ ifb->advance(8);
+ *is_lowered_for_statement = true;
+ }
+ size_t nl = ifb->body().find('\n', ifb->off());
+ if (nl == std::string::npos)
+ {
+ if (!ifb->saw_error())
+ go_error_at(ifb->location(),
+ "import error: no newline after %<{%> at %lu",
+ static_cast<unsigned long>(ifb->off()));
+ ifb->set_saw_error();
+ return NULL;
+ }
+ ifb->set_off(nl + 1);
+ ifb->increment_indent();
+ Block* block = new Block(ifb->block(), loc);
+ bool ok = Block::import_block(block, ifb, loc);
+ ifb->decrement_indent();
+ if (!ok)
+ return NULL;
+ return block;
+}
+
// Convert a block to the backend representation of a statement.
Bstatement*
@@ -1871,7 +2202,7 @@ Block_statement::do_dump_statement(Ast_dump_context*) const
// Make a block statement.
-Statement*
+Block_statement*
Statement::make_block_statement(Block* block, Location location)
{
return new Block_statement(block, location);
@@ -2578,7 +2909,7 @@ Thunk_statement::build_thunk(Gogo* gogo, const std::string& thunk_name)
// just for the call statement now. The other types are known.
call_statement->determine_types();
- gogo->flatten_block(function, b);
+ gogo->add_conversions_in_block(b);
if (may_call_recover
|| recover_arg != NULL
@@ -2603,6 +2934,8 @@ Thunk_statement::build_thunk(Gogo* gogo, const std::string& thunk_name)
}
}
+ gogo->flatten_block(function, b);
+
// That is all the thunk has to do.
gogo->finish_function(location);
}
@@ -3037,6 +3370,61 @@ Goto_statement::do_get_backend(Translate_context* context)
return context->backend()->goto_statement(blabel, this->location());
}
+// Export a goto statement.
+
+void
+Goto_statement::do_export_statement(Export_function_body *efb)
+{
+ efb->write_c_string("goto ");
+ efb->write_string(this->label_->name());
+}
+
+// Import a goto or goto unnamed statement.
+
+Statement*
+Goto_statement::do_import(Import_function_body* ifb, Location loc)
+{
+ ifb->require_c_string("goto ");
+ std::string id = ifb->read_identifier();
+ if (id[0] != '$')
+ {
+ Function* fn = ifb->function()->func_value();
+ Label* label = fn->add_label_reference(ifb->gogo(), id, loc, false);
+ return Statement::make_goto_statement(label, loc);
+ }
+ else
+ {
+ if (id[1] != 'l')
+ {
+ if (!ifb->saw_error())
+ go_error_at(loc,
+ ("invalid export data for %qs: "
+ "bad unnamed label at %lu"),
+ ifb->name().c_str(),
+ static_cast<unsigned long>(ifb->off()));
+ ifb->set_saw_error();
+ return Statement::make_error_statement(loc);
+ }
+ const char* p = id.c_str();
+ char* end;
+ long idx = strtol(p + 2, &end, 10);
+ if (*end != '\0' || idx > 0x7fffffff)
+ {
+ if (!ifb->saw_error())
+ go_error_at(loc,
+ ("invalid export data for %qs: "
+ "bad unnamed label index at %lu"),
+ ifb->name().c_str(),
+ static_cast<unsigned long>(ifb->off()));
+ ifb->set_saw_error();
+ return Statement::make_error_statement(loc);
+ }
+
+ Unnamed_label* label = ifb->unnamed_label(idx, loc);
+ return Statement::make_goto_unnamed_statement(label, loc);
+ }
+}
+
// Dump the AST representation for a goto statement.
void
@@ -3070,6 +3458,17 @@ Goto_unnamed_statement::do_get_backend(Translate_context* context)
return this->label_->get_goto(context, this->location());
}
+// Export a goto unnamed statement.
+
+void
+Goto_unnamed_statement::do_export_statement(Export_function_body *efb)
+{
+ unsigned int index = efb->unnamed_label_index(this->label_);
+ char buf[100];
+ snprintf(buf, sizeof buf, "goto $l%u", index);
+ efb->write_c_string(buf);
+}
+
// Dump the AST representation for an unnamed goto statement
void
@@ -3117,6 +3516,64 @@ Label_statement::do_get_backend(Translate_context* context)
return context->backend()->label_definition_statement(blabel);
}
+// Export a label.
+
+void
+Label_statement::do_export_statement(Export_function_body* efb)
+{
+ if (this->label_->is_dummy_label())
+ return;
+ // We use a leading colon, not a trailing one, to simplify import.
+ efb->write_c_string(":");
+ efb->write_string(this->label_->name());
+}
+
+// Import a label or an unnamed label.
+
+Statement*
+Label_statement::do_import(Import_function_body* ifb, Location loc)
+{
+ ifb->require_c_string(":");
+ std::string id = ifb->read_identifier();
+ if (id[0] != '$')
+ {
+ Function* fn = ifb->function()->func_value();
+ Label* label = fn->add_label_definition(ifb->gogo(), id, loc);
+ return Statement::make_label_statement(label, loc);
+ }
+ else
+ {
+ if (id[1] != 'l')
+ {
+ if (!ifb->saw_error())
+ go_error_at(loc,
+ ("invalid export data for %qs: "
+ "bad unnamed label at %lu"),
+ ifb->name().c_str(),
+ static_cast<unsigned long>(ifb->off()));
+ ifb->set_saw_error();
+ return Statement::make_error_statement(loc);
+ }
+ const char* p = id.c_str();
+ char* end;
+ long idx = strtol(p + 2, &end, 10);
+ if (*end != '\0' || idx > 0x7fffffff)
+ {
+ if (!ifb->saw_error())
+ go_error_at(loc,
+ ("invalid export data for %qs: "
+ "bad unnamed label index at %lu"),
+ ifb->name().c_str(),
+ static_cast<unsigned long>(ifb->off()));
+ ifb->set_saw_error();
+ return Statement::make_error_statement(loc);
+ }
+
+ Unnamed_label* label = ifb->unnamed_label(idx, loc);
+ return Statement::make_unnamed_label_statement(label);
+ }
+}
+
// Dump the AST for a label definition statement.
void
@@ -3155,6 +3612,18 @@ Unnamed_label_statement::do_get_backend(Translate_context* context)
return this->label_->get_definition(context);
}
+// Export an unnamed label.
+
+void
+Unnamed_label_statement::do_export_statement(Export_function_body* efb)
+{
+ unsigned int index = efb->unnamed_label_index(this->label_);
+ char buf[50];
+ // We use a leading colon, not a trailing one, to simplify import.
+ snprintf(buf, sizeof buf, ":$l%u", index);
+ efb->write_c_string(buf);
+}
+
// Dump the AST representation for an unnamed label definition statement.
void
@@ -3242,6 +3711,96 @@ If_statement::do_get_backend(Translate_context* context)
this->location());
}
+// Export an if statement.
+
+void
+If_statement::do_export_statement(Export_function_body* efb)
+{
+ efb->write_c_string("if ");
+ this->cond_->export_expression(efb);
+ efb->write_c_string(" ");
+ Block_statement::export_block(efb, this->then_block_, false);
+ if (this->else_block_ != NULL)
+ {
+ efb->write_c_string(" else ");
+ Block_statement::export_block(efb, this->else_block_, false);
+ }
+}
+
+// Import an if statement.
+
+Statement*
+If_statement::do_import(Import_function_body* ifb, Location loc)
+{
+ ifb->require_c_string("if ");
+
+ Expression* cond = Expression::import_expression(ifb, loc);
+ ifb->require_c_string(" ");
+
+ if (!ifb->match_c_string("{"))
+ {
+ if (!ifb->saw_error())
+ go_error_at(ifb->location(),
+ "import error for %qs: no block for if statement at %lu",
+ ifb->name().c_str(),
+ static_cast<unsigned long>(ifb->off()));
+ ifb->set_saw_error();
+ return Statement::make_error_statement(loc);
+ }
+
+ bool is_lowered_for_statement;
+ Block* then_block = Block_statement::do_import(ifb, loc,
+ &is_lowered_for_statement);
+ if (then_block == NULL)
+ return Statement::make_error_statement(loc);
+ if (is_lowered_for_statement)
+ {
+ if (!ifb->saw_error())
+ go_error_at(ifb->location(),
+ ("import error for %qs: "
+ "unexpected lowered for in if statement at %lu"),
+ ifb->name().c_str(),
+ static_cast<unsigned long>(ifb->off()));
+ ifb->set_saw_error();
+ return Statement::make_error_statement(loc);
+ }
+
+ Block* else_block = NULL;
+ if (ifb->match_c_string(" else "))
+ {
+ ifb->advance(6);
+ if (!ifb->match_c_string("{"))
+ {
+ if (!ifb->saw_error())
+ go_error_at(ifb->location(),
+ ("import error for %qs: no else block "
+ "for if statement at %lu"),
+ ifb->name().c_str(),
+ static_cast<unsigned long>(ifb->off()));
+ ifb->set_saw_error();
+ return Statement::make_error_statement(loc);
+ }
+
+ else_block = Block_statement::do_import(ifb, loc,
+ &is_lowered_for_statement);
+ if (else_block == NULL)
+ return Statement::make_error_statement(loc);
+ if (is_lowered_for_statement)
+ {
+ if (!ifb->saw_error())
+ go_error_at(ifb->location(),
+ ("import error for %qs: "
+ "unexpected lowered for in if statement at %lu"),
+ ifb->name().c_str(),
+ static_cast<unsigned long>(ifb->off()));
+ ifb->set_saw_error();
+ return Statement::make_error_statement(loc);
+ }
+ }
+
+ return Statement::make_if_statement(cond, then_block, else_block, loc);
+}
+
// Dump the AST representation for an if statement
void
@@ -4055,11 +4614,12 @@ Type_case_clauses::Type_case_clause::lower(Type* switch_val_type,
cond = Expression::make_binary(OPERATOR_EQEQ, ref,
Expression::make_nil(loc),
loc);
+ else if (type->interface_type() == NULL)
+ cond = Expression::make_binary(OPERATOR_EQEQ, ref,
+ Expression::make_type_descriptor(type, loc),
+ loc);
else
- cond = Runtime::make_call((type->interface_type() == NULL
- ? Runtime::IFACETYPEEQ
- : Runtime::IFACET2IP),
- loc, 2,
+ cond = Runtime::make_call(Runtime::IFACET2IP, loc, 2,
Expression::make_type_descriptor(type, loc),
ref);
@@ -4312,23 +4872,23 @@ Type_switch_statement::do_lower(Gogo*, Named_object*, Block* enclosing,
return Statement::make_error_statement(loc);
}
+ Temporary_statement* val_temp =
+ Statement::make_temporary(NULL, this->expr_, loc);
+ b->add_statement(val_temp);
+
// var descriptor_temp DESCRIPTOR_TYPE
Type* descriptor_type = Type::make_type_descriptor_ptr_type();
Temporary_statement* descriptor_temp =
Statement::make_temporary(descriptor_type, NULL, loc);
b->add_statement(descriptor_temp);
- // descriptor_temp = ifacetype(val_temp) FIXME: This should be
- // inlined.
- bool is_empty = val_type->interface_type()->is_empty();
- Expression* call = Runtime::make_call((is_empty
- ? Runtime::EFACETYPE
- : Runtime::IFACETYPE),
- loc, 1, this->expr_);
+ // descriptor_temp = ifacetype(val_temp)
+ Expression* ref = Expression::make_temporary_reference(val_temp, loc);
+ Expression* td = Expression::get_interface_type_descriptor(ref);
Temporary_reference_expression* lhs =
Expression::make_temporary_reference(descriptor_temp, loc);
lhs->set_is_lvalue();
- Statement* s = Statement::make_assignment(lhs, call, loc);
+ Statement* s = Statement::make_assignment(lhs, td, loc);
b->add_statement(s);
if (this->clauses_ != NULL)
@@ -4483,6 +5043,18 @@ Send_statement::do_flatten(Gogo*, Named_object*, Block*,
return this;
}
+// Add explicit type conversions.
+
+void
+Send_statement::do_add_conversions()
+{
+ Type* lt = this->channel_->type()->channel_type()->element_type();
+ Type* rt = this->val_->type();
+ if (!Type::are_identical(lt, rt, 0, NULL)
+ && lt->interface_type() != NULL)
+ this->val_ = Expression::make_cast(lt, this->val_, this->location());
+}
+
// Convert a send statement to the backend representation.
Bstatement*
@@ -5513,7 +6085,7 @@ For_range_statement::do_lower(Gogo* gogo, Named_object*, Block* enclosing,
if (clear != NULL)
{
if (gogo->debug_optimization())
- go_inform(loc, "map range clear");
+ go_debug(loc, "map range clear");
temp_block->add_statement(clear);
return Statement::make_block_statement(temp_block, loc);
}
@@ -5530,7 +6102,7 @@ For_range_statement::do_lower(Gogo* gogo, Named_object*, Block* enclosing,
if (clear != NULL)
{
if (gogo->debug_optimization())
- go_inform(loc, "array range clear");
+ go_debug(loc, "array range clear");
temp_block->add_statement(clear);
return Statement::make_block_statement(temp_block, loc);
}
@@ -6206,47 +6778,20 @@ For_range_statement::lower_map_range_clear(Type* map_type,
if (enclosing->bindings()->lookup_local(index_no->name()) != index_no)
return NULL;
- // Match the body. When lowering the builtin delete function, we have
- // inserted temporaries, so we actually match for
- //
- // tmp1 = m
- // tmp2 = k
- // runtime.mapdelete(TYPE, tmp1, &tmp2)
-
+ // Match the body, a single call statement delete(m, k).
const std::vector<Statement*>* statements = this->statements_->statements();
- if (statements->size() != 3)
- return NULL;
-
- Temporary_statement* ts1 = statements->at(0)->temporary_statement();
- Temporary_statement* ts2 = statements->at(1)->temporary_statement();
- Expression_statement* es3 = statements->at(2)->expression_statement();
- if (ts1 == NULL || ts2 == NULL || es3 == NULL
- || !Expression::is_same_variable(orig_range_expr, ts1->init())
- || !Expression::is_same_variable(this->index_var_, ts2->init()))
- return NULL;
- Call_expression* call = es3->expr()->call_expression();
- if (call == NULL)
- return NULL;
- Func_expression* fe = call->fn()->func_expression();
- if (fe == NULL || !fe->is_runtime_function()
- || fe->runtime_code() != Runtime::MAPDELETE)
+ if (statements->size() != 1)
return NULL;
- Expression* a1 = call->args()->at(1);
- a1 = (a1->unsafe_conversion_expression() != NULL
- ? a1->unsafe_conversion_expression()->expr()
- : a1);
- Temporary_reference_expression* tre = a1->temporary_reference_expression();
- if (tre == NULL || tre->statement() != ts1)
+ Expression_statement* es = statements->at(0)->expression_statement();
+ if (es == NULL)
return NULL;
- Expression* a2 = call->args()->at(2);
- a2 = (a2->conversion_expression() != NULL
- ? a2->conversion_expression()->expr()
- : a2);
- Unary_expression* ue = a2->unary_expression();
- if (ue == NULL || ue->op() != OPERATOR_AND)
+ Call_expression* call = es->expr()->call_expression();
+ if (call == NULL || !call->is_builtin()
+ || call->builtin_call_expression()->code()
+ != Builtin_call_expression::BUILTIN_DELETE)
return NULL;
- tre = ue->operand()->temporary_reference_expression();
- if (tre == NULL || tre->statement() != ts2)
+ if (!Expression::is_same_variable(call->args()->at(0), orig_range_expr)
+ || !Expression::is_same_variable(call->args()->at(1), this->index_var_))
return NULL;
// Everything matches. Rewrite to mapclear(TYPE, MAP).
@@ -6337,12 +6882,18 @@ For_range_statement::lower_array_range_clear(Gogo* gogo,
Temporary_statement* ts2 = Statement::make_temporary(NULL, e2, loc);
b->add_statement(ts2);
- Expression* arg1 = Expression::make_temporary_reference(ts1, loc);
- Expression* arg2 = Expression::make_temporary_reference(ts2, loc);
- Runtime::Function code = (elem_type->has_pointer()
- ? Runtime::MEMCLRHASPTR
- : Runtime::MEMCLRNOPTR);
- Expression* call = Runtime::make_call(code, loc, 2, arg1, arg2);
+ Expression* ptr_arg = Expression::make_temporary_reference(ts1, loc);
+ Expression* sz_arg = Expression::make_temporary_reference(ts2, loc);
+ Expression* call;
+ if (elem_type->has_pointer())
+ call = Runtime::make_call(Runtime::MEMCLRHASPTR, loc, 2, ptr_arg, sz_arg);
+ else
+ {
+ Type* int32_type = Type::lookup_integer_type("int32");
+ Expression* zero = Expression::make_integer_ul(0, int32_type, loc);
+ call = Runtime::make_call(Runtime::BUILTIN_MEMSET, loc, 3, ptr_arg,
+ zero, sz_arg);
+ }
Statement* cs3 = Statement::make_statement(call, true);
b->add_statement(cs3);
diff --git a/gcc/go/gofrontend/statements.h b/gcc/go/gofrontend/statements.h
index ec9ade3..432da30 100644
--- a/gcc/go/gofrontend/statements.h
+++ b/gcc/go/gofrontend/statements.h
@@ -16,6 +16,7 @@ class Block;
class Function;
class Unnamed_label;
class Export_function_body;
+class Import_function_body;
class Assignment_statement;
class Temporary_statement;
class Variable_declaration_statement;
@@ -186,7 +187,7 @@ class Statement
// Make a block statement from a Block. This is an embedded list of
// statements which may also include variable definitions.
- static Statement*
+ static Block_statement*
make_block_statement(Block*, Location);
// Make an increment statement.
@@ -332,12 +333,16 @@ class Statement
inlining_cost()
{ return this->do_inlining_cost(); }
- // Export data for this statement to BODY. INDENT is an indentation
- // level used if the export data requires multiple lines.
+ // Export data for this statement to BODY.
void
export_statement(Export_function_body* efb)
{ this->do_export_statement(efb); }
+ // Make implicit type conversions explicit.
+ void
+ add_conversions()
+ { this->do_add_conversions(); }
+
// Read a statement from export data. The location should be used
// for the returned statement. Errors should be reported using the
// Import_function_body's location method.
@@ -514,10 +519,8 @@ class Statement
{ return 0x100000; }
// Implemented by child class: write export data for this statement
- // to the string. The integer is an indentation level used if the
- // export data requires multiple lines. This need only be
- // implemented by classes that implement do_inlining_cost with a
- // reasonable value.
+ // to the string. This need only be implemented by classes that
+ // implement do_inlining_cost with a reasonable value.
virtual void
do_export_statement(Export_function_body*)
{ go_unreachable(); }
@@ -536,6 +539,11 @@ class Statement
virtual void
do_dump_statement(Ast_dump_context*) const = 0;
+ // Implemented by child class: make implicit conversions explicit.
+ virtual void
+ do_add_conversions()
+ { }
+
// Traverse an expression in a statement.
int
traverse_expression(Traverse*, Expression**);
@@ -647,6 +655,9 @@ class Assignment_statement : public Statement
void
do_dump_statement(Ast_dump_context*) const;
+ void
+ do_add_conversions();
+
private:
// Left hand side--the lvalue.
Expression* lhs_;
@@ -664,7 +675,7 @@ class Temporary_statement : public Statement
Temporary_statement(Type* type, Expression* init, Location location)
: Statement(STATEMENT_TEMPORARY, location),
type_(type), init_(init), bvariable_(NULL), is_address_taken_(false),
- value_escapes_(false)
+ value_escapes_(false), assigned_(false), uses_(0)
{ }
// Return the type of the temporary variable.
@@ -676,6 +687,17 @@ class Temporary_statement : public Statement
init() const
{ return this->init_; }
+ // Set the initializer.
+ void
+ set_init(Expression* expr)
+ { this->init_ = expr; }
+
+ // Whether something takes the address of this temporary
+ // variable.
+ bool
+ is_address_taken()
+ { return this->is_address_taken_; }
+
// Record that something takes the address of this temporary
// variable.
void
@@ -692,11 +714,35 @@ class Temporary_statement : public Statement
set_value_escapes()
{ this->value_escapes_ = true; }
+ // Whether this temporary variable is assigned (after initialization).
+ bool
+ assigned()
+ { return this->assigned_; }
+
+ // Record that this temporary variable is assigned.
+ void
+ set_assigned()
+ { this->assigned_ = true; }
+
+ // Number of uses of this temporary variable.
+ int
+ uses()
+ { return this->uses_; }
+
+ // Add one use of this temporary variable.
+ void
+ add_use()
+ { this->uses_++; }
+
// Return the temporary variable. This should not be called until
// after the statement itself has been converted.
Bvariable*
get_backend_variable(Translate_context*) const;
+ // Import the declaration of a temporary.
+ static Statement*
+ do_import(Import_function_body*, Location);
+
protected:
int
do_traverse(Traverse*);
@@ -710,6 +756,13 @@ class Temporary_statement : public Statement
void
do_check_types(Gogo*);
+ int
+ do_inlining_cost()
+ { return 1; }
+
+ void
+ do_export_statement(Export_function_body*);
+
Statement*
do_flatten(Gogo*, Named_object*, Block*, Statement_inserter*);
@@ -719,6 +772,9 @@ class Temporary_statement : public Statement
void
do_dump_statement(Ast_dump_context*) const;
+ void
+ do_add_conversions();
+
private:
// The type of the temporary variable.
Type* type_;
@@ -731,6 +787,10 @@ class Temporary_statement : public Statement
// True if the value assigned to this temporary variable escapes.
// This is used for select statements.
bool value_escapes_;
+ // True if this temporary variable is assigned (after initialization).
+ bool assigned_;
+ // Number of uses of this temporary variable.
+ int uses_;
};
// A variable declaration. This marks the point in the code where a
@@ -746,6 +806,10 @@ class Variable_declaration_statement : public Statement
var()
{ return this->var_; }
+ // Import a variable declaration.
+ static Statement*
+ do_import(Import_function_body*, Location);
+
protected:
int
do_traverse(Traverse*);
@@ -756,6 +820,13 @@ class Variable_declaration_statement : public Statement
Statement*
do_lower(Gogo*, Named_object*, Block*, Statement_inserter*);
+ int
+ do_inlining_cost()
+ { return 1; }
+
+ void
+ do_export_statement(Export_function_body*);
+
Statement*
do_flatten(Gogo*, Named_object*, Block*, Statement_inserter*);
@@ -765,6 +836,9 @@ class Variable_declaration_statement : public Statement
void
do_dump_statement(Ast_dump_context*) const;
+ void
+ do_add_conversions();
+
private:
Named_object* var_;
};
@@ -880,6 +954,16 @@ class Block_statement : public Statement
is_lowered_for_statement()
{ return this->is_lowered_for_statement_; }
+ // Export a block for a block statement.
+ static void
+ export_block(Export_function_body*, Block*, bool is_lowered_for_statement);
+
+ // Import a block statement, returning the block.
+ // *IS_LOWERED_FOR_STATEMENT reports whether this block statement
+ // was lowered from a for statement.
+ static Block*
+ do_import(Import_function_body*, Location, bool* is_lowered_for_statement);
+
protected:
int
do_traverse(Traverse* traverse)
@@ -950,6 +1034,9 @@ class Send_statement : public Statement
void
do_dump_statement(Ast_dump_context*) const;
+ void
+ do_add_conversions();
+
private:
// The channel on which to send the value.
Expression* channel_;
@@ -1324,6 +1411,10 @@ class Goto_statement : public Statement
label() const
{ return this->label_; }
+ // Import a goto statement.
+ static Statement*
+ do_import(Import_function_body*, Location);
+
protected:
int
do_traverse(Traverse*);
@@ -1338,6 +1429,13 @@ class Goto_statement : public Statement
Bstatement*
do_get_backend(Translate_context*);
+ int
+ do_inlining_cost()
+ { return 5; }
+
+ void
+ do_export_statement(Export_function_body*);
+
void
do_dump_statement(Ast_dump_context*) const;
@@ -1370,6 +1468,13 @@ class Goto_unnamed_statement : public Statement
Bstatement*
do_get_backend(Translate_context* context);
+ int
+ do_inlining_cost()
+ { return 5; }
+
+ void
+ do_export_statement(Export_function_body*);
+
void
do_dump_statement(Ast_dump_context*) const;
@@ -1392,6 +1497,10 @@ class Label_statement : public Statement
label() const
{ return this->label_; }
+ // Import a label or unnamed label.
+ static Statement*
+ do_import(Import_function_body*, Location);
+
protected:
int
do_traverse(Traverse*);
@@ -1399,6 +1508,13 @@ class Label_statement : public Statement
Bstatement*
do_get_backend(Translate_context*);
+ int
+ do_inlining_cost()
+ { return 1; }
+
+ void
+ do_export_statement(Export_function_body*);
+
void
do_dump_statement(Ast_dump_context*) const;
@@ -1421,6 +1537,13 @@ class Unnamed_label_statement : public Statement
Bstatement*
do_get_backend(Translate_context* context);
+ int
+ do_inlining_cost()
+ { return 1; }
+
+ void
+ do_export_statement(Export_function_body*);
+
void
do_dump_statement(Ast_dump_context*) const;
@@ -1444,6 +1567,18 @@ class If_statement : public Statement
condition() const
{ return this->cond_; }
+ Block*
+ then_block() const
+ { return this->then_block_; }
+
+ Block*
+ else_block() const
+ { return this->else_block_; }
+
+ // Import an if statement.
+ static Statement*
+ do_import(Import_function_body*, Location);
+
protected:
int
do_traverse(Traverse*);
@@ -1454,6 +1589,13 @@ class If_statement : public Statement
void
do_check_types(Gogo*);
+ int
+ do_inlining_cost()
+ { return 5; }
+
+ void
+ do_export_statement(Export_function_body*);
+
bool
do_may_fall_through() const;
diff --git a/gcc/go/gofrontend/types.cc b/gcc/go/gofrontend/types.cc
index 371b65f..cc65bd8 100644
--- a/gcc/go/gofrontend/types.cc
+++ b/gcc/go/gofrontend/types.cc
@@ -12,6 +12,7 @@
#include "gogo.h"
#include "go-diagnostics.h"
#include "go-encode-id.h"
+#include "go-sha1.h"
#include "operator.h"
#include "expressions.h"
#include "statements.h"
@@ -1412,6 +1413,23 @@ Type::make_type_descriptor_var(Gogo* gogo)
var_name, false, is_common,
initializer_btype, loc,
binitializer);
+
+ // For types that may be created by reflection, add it to the
+ // list of which we will register the type descriptor to the
+ // runtime.
+ // Do not add generated incomparable array/struct types, see
+ // issue #22605.
+ if (is_common
+ && (this->points_to() != NULL
+ || this->channel_type() != NULL
+ || this->map_type() != NULL
+ || this->function_type() != NULL
+ || this->is_slice_type()
+ || (this->struct_type() != NULL
+ && !this->struct_type()->is_struct_incomparable())
+ || (this->array_type() != NULL
+ && !this->array_type()->is_array_incomparable())))
+ gogo->add_type_descriptor(this);
}
// Return true if this type descriptor is defined in a different
@@ -2776,22 +2794,48 @@ Ptrmask::set_from(Gogo* gogo, Type* type, int64_t ptrsize, int64_t offset)
}
}
-// Return a symbol name for this ptrmask. This is used to coalesce
-// identical ptrmasks, which are common. The symbol name must use
-// only characters that are valid in symbols. It's nice if it's
-// short. We convert it to a string that uses only 32 characters,
-// avoiding digits and u and U.
-
+// Return a symbol name for this ptrmask. This is used to coalesce identical
+// ptrmasks, which are common. The symbol name must use only characters that are
+// valid in symbols. It's nice if it's short. For smaller ptrmasks, we convert
+// it to a string that uses only 32 characters, avoiding digits and u and U. For
+// longer pointer masks, apply the same process to the SHA1 digest of the bits,
+// so as to avoid pathologically long symbol names (see related Go issues #32083
+// and #11583 for more on this). To avoid collisions between the two encoding
+// schemes, use a prefix ("X") for the SHA form to disambiguate.
std::string
Ptrmask::symname() const
{
+ const std::vector<unsigned char>* bits(&this->bits_);
+ std::vector<unsigned char> shabits;
+ std::string prefix;
+
+ if (this->bits_.size() > 128)
+ {
+ // Produce a SHA1 digest of the data.
+ Go_sha1_helper* sha1_helper = go_create_sha1_helper();
+ sha1_helper->process_bytes(&this->bits_[0], this->bits_.size());
+ std::string digest = sha1_helper->finish();
+ delete sha1_helper;
+
+ // Redirect the bits vector to the digest, and update the prefix.
+ prefix = "X";
+ for (std::string::const_iterator p = digest.begin();
+ p != digest.end();
+ ++p)
+ {
+ unsigned char c = *p;
+ shabits.push_back(c);
+ }
+ bits = &shabits;
+ }
+
const char chars[33] = "abcdefghijklmnopqrstvwxyzABCDEFG";
go_assert(chars[32] == '\0');
- std::string ret;
+ std::string ret(prefix);
unsigned int b = 0;
int remaining = 0;
- for (std::vector<unsigned char>::const_iterator p = this->bits_.begin();
- p != this->bits_.end();
+ for (std::vector<unsigned char>::const_iterator p = bits->begin();
+ p != bits->end();
++p)
{
b |= *p << remaining;
@@ -4760,10 +4804,15 @@ Function_type::get_backend_fntype(Gogo* gogo)
// We always pass the address of the receiver parameter, in
// order to make interface calls work with unknown types,
// except for direct interface types where the interface call
- // actually passes value.
+ // actually passes the underlying pointer of the value.
Type* rtype = this->receiver_->type();
- if (!rtype->is_direct_iface_type())
- rtype = Type::make_pointer_type(rtype);
+ if (rtype->points_to() == NULL)
+ {
+ if (rtype->is_direct_iface_type())
+ rtype = Type::make_pointer_type(Type::make_void_type());
+ else
+ rtype = Type::make_pointer_type(rtype);
+ }
breceiver.btype = rtype->get_backend(gogo);
breceiver.location = this->receiver_->location();
}
@@ -7841,7 +7890,7 @@ int64_t Map_type::zero_value_align;
// pass as the zero value to those functions. Otherwise, in the
// normal case, return NULL. The map requires the "fat" functions if
// the value size is larger than max_zero_size bytes. max_zero_size
-// must match maxZero in libgo/go/runtime/hashmap.go.
+// must match maxZero in libgo/go/runtime/map.go.
Expression*
Map_type::fat_zero_value(Gogo* gogo)
@@ -7889,6 +7938,43 @@ Map_type::fat_zero_value(Gogo* gogo)
return z;
}
+// Map algorithm to use for this map type.
+
+Map_type::Map_alg
+Map_type::algorithm(Gogo* gogo)
+{
+ int64_t size;
+ bool ok = this->val_type_->backend_type_size(gogo, &size);
+ if (!ok || size > Map_type::max_val_size)
+ return MAP_ALG_SLOW;
+
+ Type* key_type = this->key_type_;
+ if (key_type->is_string_type())
+ return MAP_ALG_FASTSTR;
+ if (!key_type->compare_is_identity(gogo))
+ return MAP_ALG_SLOW;
+
+ ok = key_type->backend_type_size(gogo, &size);
+ if (!ok)
+ return MAP_ALG_SLOW;
+ if (size == 4)
+ return (key_type->has_pointer()
+ ? MAP_ALG_FAST32PTR
+ : MAP_ALG_FAST32);
+ if (size == 8)
+ {
+ if (!key_type->has_pointer())
+ return MAP_ALG_FAST64;
+ Type* ptr_type = Type::make_pointer_type(Type::make_void_type());
+ ok = ptr_type->backend_type_size(gogo, &size);
+ if (ok && size == 8)
+ return MAP_ALG_FAST64PTR;
+ // Key contains pointer but is not a single pointer.
+ // Use slow version.
+ }
+ return MAP_ALG_SLOW;
+}
+
// Return whether VAR is the map zero value.
bool
@@ -7978,7 +8064,7 @@ Map_type::do_hash_for_method(Gogo* gogo, int flags) const
// Get the backend representation for a map type. A map type is
// represented as a pointer to a struct. The struct is hmap in
-// runtime/hashmap.go.
+// runtime/map.go.
Btype*
Map_type::do_get_backend(Gogo* gogo)
@@ -8184,7 +8270,7 @@ Map_type::do_type_descriptor(Gogo* gogo, Named_type* name)
}
// Return the bucket type to use for a map type. This must correspond
-// to libgo/go/runtime/hashmap.go.
+// to libgo/go/runtime/map.go.
Type*
Map_type::bucket_type(Gogo* gogo, int64_t keysize, int64_t valsize)
@@ -8216,7 +8302,7 @@ Map_type::bucket_type(Gogo* gogo, int64_t keysize, int64_t valsize)
// be marked as having no pointers. Arrange for the bucket to have
// no pointers by changing the type of the overflow field to uintptr
// in this case. See comment on the hmap.overflow field in
- // libgo/go/runtime/hashmap.go.
+ // libgo/go/runtime/map.go.
Type* overflow_type;
if (!key_type->has_pointer() && !val_type->has_pointer())
overflow_type = Type::lookup_integer_type("uintptr");
diff --git a/gcc/go/gofrontend/types.h b/gcc/go/gofrontend/types.h
index 721d1fc..2b51df5 100644
--- a/gcc/go/gofrontend/types.h
+++ b/gcc/go/gofrontend/types.h
@@ -1494,7 +1494,12 @@ class Typed_identifier
// Set the escape note.
void
set_note(const std::string& note)
- { this->note_ = new std::string(note); }
+ {
+ if (this->note_ != NULL)
+ go_assert(*this->note_ == note);
+ else
+ this->note_ = new std::string(note);
+ }
private:
// Identifier name.
@@ -2912,6 +2917,27 @@ class Map_type : public Type
Expression*
fat_zero_value(Gogo*);
+ // Map algorithm to use for this map type. We may use specialized
+ // fast map routines for certain key types.
+ enum Map_alg
+ {
+ // 32-bit key.
+ MAP_ALG_FAST32,
+ // 32-bit pointer key.
+ MAP_ALG_FAST32PTR,
+ // 64-bit key.
+ MAP_ALG_FAST64,
+ // 64-bit pointer key.
+ MAP_ALG_FAST64PTR,
+ // String key.
+ MAP_ALG_FASTSTR,
+ // Anything else.
+ MAP_ALG_SLOW,
+ };
+
+ Map_alg
+ algorithm(Gogo*);
+
// Return whether VAR is the map zero value.
static bool
is_zero_value(Variable* var);
@@ -2931,7 +2957,7 @@ class Map_type : public Type
static Type*
make_map_type_descriptor_type();
- // This must be in sync with libgo/go/runtime/hashmap.go.
+ // This must be in sync with libgo/go/runtime/map.go.
static const int bucket_size = 8;
protected:
@@ -2974,7 +3000,7 @@ class Map_type : public Type
do_export(Export*) const;
private:
- // These must be in sync with libgo/go/runtime/hashmap.go.
+ // These must be in sync with libgo/go/runtime/map.go.
static const int max_key_size = 128;
static const int max_val_size = 128;
static const int max_zero_size = 1024;
diff --git a/gcc/go/gofrontend/wb.cc b/gcc/go/gofrontend/wb.cc
index 1d12269..501ad6a 100644
--- a/gcc/go/gofrontend/wb.cc
+++ b/gcc/go/gofrontend/wb.cc
@@ -41,9 +41,6 @@ class Mark_address_taken : public Traverse
expression(Expression**);
private:
- Call_expression*
- find_makeslice_call(Expression*);
-
// General IR.
Gogo* gogo_;
// The function we are traversing.
@@ -100,31 +97,6 @@ Mark_address_taken::statement(Block* block, size_t* pindex, Statement* s)
return TRAVERSE_CONTINUE;
}
-// Look through the expression of a Slice_value_expression's valmem to
-// find an call to makeslice.
-
-Call_expression*
-Mark_address_taken::find_makeslice_call(Expression* expr)
-{
- Unsafe_type_conversion_expression* utce =
- expr->unsafe_conversion_expression();
- if (utce != NULL)
- expr = utce->expr();
-
- Call_expression* call = expr->call_expression();
- if (call == NULL)
- return NULL;
-
- Func_expression* fe = call->fn()->func_expression();
- if (fe != NULL && fe->runtime_code() == Runtime::MAKESLICE)
- return call;
-
- // We don't worry about MAKESLICE64 bcause we don't want to use a
- // stack allocation for a large slice anyhow.
-
- return NULL;
-}
-
// Mark variable addresses taken.
int
@@ -173,7 +145,10 @@ Mark_address_taken::expression(Expression** pexpr)
Slice_value_expression* sve = expr->slice_value_expression();
if (sve != NULL)
{
- Call_expression* call = this->find_makeslice_call(sve->valmem());
+ std::pair<Call_expression*, Temporary_statement*> p =
+ Expression::find_makeslice_call(sve);
+ Call_expression* call = p.first;
+ Temporary_statement* ts = p.second;
if (call != NULL
&& Node::make_node(call)->encoding() == Node::ESCAPE_NONE)
{
@@ -203,6 +178,8 @@ Mark_address_taken::expression(Expression** pexpr)
Expression::make_slice_value(expr->type(), ptr, len_arg,
cap_arg, loc);
*pexpr = slice;
+ if (ts != NULL && ts->uses() == 1)
+ ts->set_init(Expression::make_nil(loc));
}
}
}
@@ -758,6 +735,26 @@ Gogo::assign_needs_write_barrier(Expression* lhs)
}
}
+ // Nothing to do for an assignment to *(convert(&x)) where
+ // x is local variable or a temporary variable.
+ Unary_expression* ue = lhs->unary_expression();
+ if (ue != NULL && ue->op() == OPERATOR_MULT)
+ {
+ Expression* expr = ue->operand();
+ while (true)
+ {
+ if (expr->conversion_expression() != NULL)
+ expr = expr->conversion_expression()->expr();
+ else if (expr->unsafe_conversion_expression() != NULL)
+ expr = expr->unsafe_conversion_expression()->expr();
+ else
+ break;
+ }
+ ue = expr->unary_expression();
+ if (ue != NULL && ue->op() == OPERATOR_AND)
+ return this->assign_needs_write_barrier(ue->operand());
+ }
+
// For a struct assignment, we don't need a write barrier if all the
// pointer types can not be in the heap.
Struct_type* st = lhs->type()->struct_type();
@@ -845,6 +842,7 @@ Gogo::assign_with_write_barrier(Function* function, Block* enclosing,
Type* unsafe_ptr_type = Type::make_pointer_type(Type::make_void_type());
lhs = Expression::make_unsafe_cast(unsafe_ptr_type, lhs, loc);
+ Type* uintptr_type = Type::lookup_integer_type("uintptr");
Expression* call;
switch (type->base()->classification())
{
@@ -860,24 +858,139 @@ Gogo::assign_with_write_barrier(Function* function, Block* enclosing,
case Type::TYPE_CHANNEL:
{
// These types are all represented by a single pointer.
- Type* uintptr_type = Type::lookup_integer_type("uintptr");
rhs = Expression::make_unsafe_cast(uintptr_type, rhs, loc);
call = Runtime::make_call(Runtime::GCWRITEBARRIER, loc, 2, lhs, rhs);
}
break;
case Type::TYPE_STRING:
- case Type::TYPE_STRUCT:
- case Type::TYPE_ARRAY:
+ {
+ // Assign the length field directly.
+ Expression* llen =
+ Expression::make_string_info(indir->copy(),
+ Expression::STRING_INFO_LENGTH,
+ loc);
+ Expression* rlen =
+ Expression::make_string_info(rhs,
+ Expression::STRING_INFO_LENGTH,
+ loc);
+ Statement* as = Statement::make_assignment(llen, rlen, loc);
+ inserter->insert(as);
+
+ // Assign the data field with a write barrier.
+ lhs =
+ Expression::make_string_info(indir->copy(),
+ Expression::STRING_INFO_DATA,
+ loc);
+ rhs =
+ Expression::make_string_info(rhs,
+ Expression::STRING_INFO_DATA,
+ loc);
+ assign = Statement::make_assignment(lhs, rhs, loc);
+ lhs = Expression::make_unary(OPERATOR_AND, lhs, loc);
+ rhs = Expression::make_unsafe_cast(uintptr_type, rhs, loc);
+ call = Runtime::make_call(Runtime::GCWRITEBARRIER, loc, 2, lhs, rhs);
+ }
+ break;
+
case Type::TYPE_INTERFACE:
{
- rhs = Expression::make_unary(OPERATOR_AND, rhs, loc);
- rhs->unary_expression()->set_does_not_escape();
- call = Runtime::make_call(Runtime::TYPEDMEMMOVE, loc, 3,
- Expression::make_type_descriptor(type, loc),
- lhs, rhs);
+ // Assign the first field directly.
+ // The first field is either a type descriptor or a method table.
+ // Type descriptors are either statically created, or created by
+ // the reflect package. For the latter the reflect package keeps
+ // all references.
+ // Method tables are either statically created or persistently
+ // allocated.
+ // In all cases they don't need a write barrier.
+ Expression* ltab =
+ Expression::make_interface_info(indir->copy(),
+ Expression::INTERFACE_INFO_METHODS,
+ loc);
+ Expression* rtab =
+ Expression::make_interface_info(rhs,
+ Expression::INTERFACE_INFO_METHODS,
+ loc);
+ Statement* as = Statement::make_assignment(ltab, rtab, loc);
+ inserter->insert(as);
+
+ // Assign the data field with a write barrier.
+ lhs =
+ Expression::make_interface_info(indir->copy(),
+ Expression::INTERFACE_INFO_OBJECT,
+ loc);
+ rhs =
+ Expression::make_interface_info(rhs,
+ Expression::INTERFACE_INFO_OBJECT,
+ loc);
+ assign = Statement::make_assignment(lhs, rhs, loc);
+ lhs = Expression::make_unary(OPERATOR_AND, lhs, loc);
+ rhs = Expression::make_unsafe_cast(uintptr_type, rhs, loc);
+ call = Runtime::make_call(Runtime::GCWRITEBARRIER, loc, 2, lhs, rhs);
}
break;
+
+ case Type::TYPE_ARRAY:
+ if (type->is_slice_type())
+ {
+ // Assign the lenth fields directly.
+ Expression* llen =
+ Expression::make_slice_info(indir->copy(),
+ Expression::SLICE_INFO_LENGTH,
+ loc);
+ Expression* rlen =
+ Expression::make_slice_info(rhs,
+ Expression::SLICE_INFO_LENGTH,
+ loc);
+ Statement* as = Statement::make_assignment(llen, rlen, loc);
+ inserter->insert(as);
+
+ // Assign the capacity fields directly.
+ Expression* lcap =
+ Expression::make_slice_info(indir->copy(),
+ Expression::SLICE_INFO_CAPACITY,
+ loc);
+ Expression* rcap =
+ Expression::make_slice_info(rhs,
+ Expression::SLICE_INFO_CAPACITY,
+ loc);
+ as = Statement::make_assignment(lcap, rcap, loc);
+ inserter->insert(as);
+
+ // Assign the data field with a write barrier.
+ lhs =
+ Expression::make_slice_info(indir->copy(),
+ Expression::SLICE_INFO_VALUE_POINTER,
+ loc);
+ rhs =
+ Expression::make_slice_info(rhs,
+ Expression::SLICE_INFO_VALUE_POINTER,
+ loc);
+ assign = Statement::make_assignment(lhs, rhs, loc);
+ lhs = Expression::make_unary(OPERATOR_AND, lhs, loc);
+ rhs = Expression::make_unsafe_cast(uintptr_type, rhs, loc);
+ call = Runtime::make_call(Runtime::GCWRITEBARRIER, loc, 2, lhs, rhs);
+ break;
+ }
+ // fallthrough
+
+ case Type::TYPE_STRUCT:
+ if (type->is_direct_iface_type())
+ {
+ rhs = Expression::unpack_direct_iface(rhs, loc);
+ rhs = Expression::make_unsafe_cast(uintptr_type, rhs, loc);
+ call = Runtime::make_call(Runtime::GCWRITEBARRIER, loc, 2, lhs, rhs);
+ }
+ else
+ {
+ // TODO: split assignments for small struct/array?
+ rhs = Expression::make_unary(OPERATOR_AND, rhs, loc);
+ rhs->unary_expression()->set_does_not_escape();
+ call = Runtime::make_call(Runtime::TYPEDMEMMOVE, loc, 3,
+ Expression::make_type_descriptor(type, loc),
+ lhs, rhs);
+ }
+ break;
}
return this->check_write_barrier(enclosing, assign,
diff --git a/gcc/graph.c b/gcc/graph.c
index 89b2031..33e4c03 100644
--- a/gcc/graph.c
+++ b/gcc/graph.c
@@ -52,11 +52,18 @@ open_graph_file (const char *base, const char *mode)
fp = fopen (buf, mode);
if (fp == NULL)
- fatal_error (input_location, "can%'t open %s: %m", buf);
+ fatal_error (input_location, "cannot open %s: %m", buf);
return fp;
}
+/* Disable warnings about quoting issues in the pp_xxx calls below
+ that (intentionally) don't follow GCC diagnostic conventions. */
+#if __GNUC__ >= 10
+# pragma GCC diagnostic push
+# pragma GCC diagnostic ignored "-Wformat-diag"
+#endif
+
/* Draw a basic block BB belonging to the function with FUNCDEF_NO
as its unique number. */
static void
@@ -381,3 +388,7 @@ finish_graph_dump_file (const char *base)
end_graph_dump (fp);
fclose (fp);
}
+
+#if __GNUC__ >= 10
+# pragma GCC diagnostic pop
+#endif
diff --git a/gcc/graphite-scop-detection.c b/gcc/graphite-scop-detection.c
index 4534d43..489d0b9 100644
--- a/gcc/graphite-scop-detection.c
+++ b/gcc/graphite-scop-detection.c
@@ -1105,14 +1105,12 @@ assign_parameter_index_in_region (tree name, sese_info_p region)
gcc_assert (TREE_CODE (name) == SSA_NAME
&& INTEGRAL_TYPE_P (TREE_TYPE (name))
&& ! defined_in_sese_p (name, region->region));
-
int i;
tree p;
FOR_EACH_VEC_ELT (region->params, i, p)
if (p == name)
return;
- i = region->params.length ();
region->params.safe_push (name);
}
diff --git a/gcc/hash-map-tests.c b/gcc/hash-map-tests.c
index b79c782..5888f25 100644
--- a/gcc/hash-map-tests.c
+++ b/gcc/hash-map-tests.c
@@ -103,12 +103,146 @@ test_map_of_strings_to_int ()
ASSERT_EQ (1, string_map.elements ());
}
+typedef struct hash_map_test_val_t
+{
+ static int ndefault;
+ static int ncopy;
+ static int nassign;
+ static int ndtor;
+
+ hash_map_test_val_t ()
+ : ptr (&ptr)
+ {
+ ++ndefault;
+ }
+
+ hash_map_test_val_t (const hash_map_test_val_t &)
+ : ptr (&ptr)
+ {
+ ++ncopy;
+ }
+
+ hash_map_test_val_t& operator= (const hash_map_test_val_t &)
+ {
+ ++nassign;
+ return *this;
+ }
+
+ ~hash_map_test_val_t ()
+ {
+ gcc_assert (ptr == &ptr);
+ ++ndtor;
+ }
+
+ void *ptr;
+} val_t;
+
+int val_t::ndefault;
+int val_t::ncopy;
+int val_t::nassign;
+int val_t::ndtor;
+
+static void
+test_map_of_type_with_ctor_and_dtor ()
+{
+ typedef hash_map <void *, val_t> Map;
+
+ {
+ /* Test default ctor. */
+ Map m;
+ (void)&m;
+ }
+
+ ASSERT_TRUE (val_t::ndefault == 0);
+ ASSERT_TRUE (val_t::ncopy == 0);
+ ASSERT_TRUE (val_t::nassign == 0);
+ ASSERT_TRUE (val_t::ndtor == 0);
+
+ {
+ /* Test single insertion. */
+ Map m;
+ void *p = &p;
+ m.get_or_insert (p);
+ }
+
+ ASSERT_TRUE (val_t::ndefault + val_t::ncopy == val_t::ndtor);
+
+ {
+ /* Test copy ctor. */
+ Map m1;
+ void *p = &p;
+ val_t &rv1 = m1.get_or_insert (p);
+
+ int ncopy = val_t::ncopy;
+ int nassign = val_t::nassign;
+
+ Map m2 (m1);
+ val_t *pv2 = m2.get (p);
+
+ ASSERT_TRUE (ncopy + 1 == val_t::ncopy);
+ ASSERT_TRUE (nassign == val_t::nassign);
+
+ ASSERT_TRUE (&rv1 != pv2);
+ ASSERT_TRUE (pv2->ptr == &pv2->ptr);
+ }
+
+ ASSERT_TRUE (val_t::ndefault + val_t::ncopy == val_t::ndtor);
+
+#if 0 /* Avoid testing until bug 90959 is fixed. */
+ {
+ /* Test copy assignment into an empty map. */
+ Map m1;
+ void *p = &p;
+ val_t &rv1 = m1.get_or_insert (p);
+
+ int ncopy = val_t::ncopy;
+ int nassign = val_t::nassign;
+
+ Map m2;
+ m2 = m1;
+ val_t *pv2 = m2.get (p);
+
+ ASSERT_TRUE (ncopy == val_t::ncopy);
+ ASSERT_TRUE (nassign + 1 == val_t::nassign);
+
+ ASSERT_TRUE (&rv1 != pv2);
+ ASSERT_TRUE (pv2->ptr == &pv2->ptr);
+ }
+
+ ASSERT_TRUE (val_t::ndefault + val_t::ncopy == val_t::ndtor);
+
+#endif
+
+ {
+ Map m;
+ void *p = &p, *q = &q;
+ val_t &v1 = m.get_or_insert (p);
+ val_t &v2 = m.get_or_insert (q);
+
+ ASSERT_TRUE (v1.ptr == &v1.ptr && &v2.ptr == v2.ptr);
+ }
+
+ ASSERT_TRUE (val_t::ndefault + val_t::ncopy == val_t::ndtor);
+
+ {
+ Map m;
+ void *p = &p, *q = &q;
+ m.get_or_insert (p);
+ m.remove (p);
+ m.get_or_insert (q);
+ m.remove (q);
+
+ ASSERT_TRUE (val_t::ndefault + val_t::ncopy == val_t::ndtor);
+ }
+}
+
/* Run all of the selftests within this file. */
void
hash_map_tests_c_tests ()
{
test_map_of_strings_to_int ();
+ test_map_of_type_with_ctor_and_dtor ();
}
} // namespace selftest
diff --git a/gcc/hash-map.h b/gcc/hash-map.h
index a3ef283..f3f1f9a 100644
--- a/gcc/hash-map.h
+++ b/gcc/hash-map.h
@@ -21,8 +21,20 @@ along with GCC; see the file COPYING3. If not see
#ifndef hash_map_h
#define hash_map_h
+/* Class hash_map is a hash-value based container mapping objects of
+ KeyId type to those of the Value type.
+ Both KeyId and Value may be non-trivial (non-POD) types provided
+ a suitabe Traits class. A few default Traits specializations are
+ provided for basic types such as integers, pointers, and std::pair.
+ Inserted elements are value-initialized either to zero for POD types
+ or by invoking their default ctor. Removed elements are destroyed
+ by invoking their dtor. On hash_map destruction all elements are
+ removed. Objects of hash_map type are copy-constructible but not
+ assignable. */
+
template<typename KeyId, typename Value,
- typename Traits>
+ typename Traits /* = simple_hashmap_traits<default_hash_traits<Key>,
+ Value> */>
class GTY((user)) hash_map
{
typedef typename Traits::key_type Key;
@@ -118,14 +130,19 @@ class GTY((user)) hash_map
public:
explicit hash_map (size_t n = 13, bool ggc = false,
+ bool sanitize_eq_and_hash = true,
bool gather_mem_stats = GATHER_STATISTICS
CXX_MEM_STAT_INFO)
- : m_table (n, ggc, gather_mem_stats, HASH_MAP_ORIGIN PASS_MEM_STAT) {}
+ : m_table (n, ggc, sanitize_eq_and_hash, gather_mem_stats,
+ HASH_MAP_ORIGIN PASS_MEM_STAT)
+ {
+ }
explicit hash_map (const hash_map &h, bool ggc = false,
+ bool sanitize_eq_and_hash = true,
bool gather_mem_stats = GATHER_STATISTICS
CXX_MEM_STAT_INFO)
- : m_table (h.m_table, ggc, gather_mem_stats,
+ : m_table (h.m_table, ggc, sanitize_eq_and_hash, gather_mem_stats,
HASH_MAP_ORIGIN PASS_MEM_STAT) {}
/* Create a hash_map in ggc memory. */
@@ -134,7 +151,7 @@ public:
CXX_MEM_STAT_INFO)
{
hash_map *map = ggc_alloc<hash_map> ();
- new (map) hash_map (size, true, gather_mem_stats PASS_MEM_STAT);
+ new (map) hash_map (size, true, true, gather_mem_stats PASS_MEM_STAT);
return map;
}
@@ -146,12 +163,16 @@ public:
{
hash_entry *e = m_table.find_slot_with_hash (k, Traits::hash (k),
INSERT);
- bool existed = !hash_entry::is_empty (*e);
- if (!existed)
- e->m_key = k;
+ bool ins = hash_entry::is_empty (*e);
+ if (ins)
+ {
+ e->m_key = k;
+ new ((void *) &e->m_value) Value (v);
+ }
+ else
+ e->m_value = v;
- e->m_value = v;
- return existed;
+ return !ins;
}
/* if the passed in key is in the map return its value otherwise NULL. */
@@ -163,8 +184,8 @@ public:
}
/* Return a reference to the value for the passed in key, creating the entry
- if it doesn't already exist. If existed is not NULL then it is set to false
- if the key was not previously in the map, and true otherwise. */
+ if it doesn't already exist. If existed is not NULL then it is set to
+ false if the key was not previously in the map, and true otherwise. */
Value &get_or_insert (const Key &k, bool *existed = NULL)
{
@@ -172,7 +193,10 @@ public:
INSERT);
bool ins = Traits::is_empty (*e);
if (ins)
- e->m_key = k;
+ {
+ e->m_key = k;
+ new ((void *)&e->m_value) Value ();
+ }
if (existed != NULL)
*existed = !ins;
diff --git a/gcc/hash-set-tests.c b/gcc/hash-set-tests.c
index e0d1d47..c96fe53 100644
--- a/gcc/hash-set-tests.c
+++ b/gcc/hash-set-tests.c
@@ -134,12 +134,166 @@ test_set_of_strings ()
ASSERT_EQ (2, t.elements ());
}
+typedef struct hash_set_test_value_t
+{
+ static int ndefault;
+ static int ncopy;
+ static int nassign;
+ static int ndtor;
+
+ hash_set_test_value_t (int v = 1): pval (&val), val (v)
+ {
+ ++ndefault;
+ }
+
+ hash_set_test_value_t (const hash_set_test_value_t &rhs)
+ : pval (&val), val (rhs.val)
+ {
+ ++ncopy;
+ }
+
+ hash_set_test_value_t& operator= (const hash_set_test_value_t &rhs)
+ {
+ ++nassign;
+ val = rhs.val;
+ return *this;
+ }
+
+ ~hash_set_test_value_t ()
+ {
+ /* Verify that the value hasn't been corrupted. */
+ gcc_assert (*pval > 0);
+ gcc_assert (pval == &val);
+ *pval = -3;
+ ++ndtor;
+ }
+
+ int *pval;
+ int val;
+} val_t;
+
+int val_t::ndefault;
+int val_t::ncopy;
+int val_t::nassign;
+int val_t::ndtor;
+
+struct value_hash_traits: int_hash<int, -1, -2>
+{
+ typedef int_hash<int, -1, -2> base_type;
+ typedef val_t value_type;
+ typedef value_type compare_type;
+
+ static hashval_t hash (const value_type &v)
+ {
+ return base_type::hash (v.val);
+ }
+
+ static bool equal (const value_type &a, const compare_type &b)
+ {
+ return base_type::equal (a.val, b.val);
+ }
+
+ static void mark_deleted (value_type &v)
+ {
+ base_type::mark_deleted (v.val);
+ }
+
+ static void mark_empty (value_type &v)
+ {
+ base_type::mark_empty (v.val);
+ }
+
+ static bool is_deleted (const value_type &v)
+ {
+ return base_type::is_deleted (v.val);
+ }
+
+ static bool is_empty (const value_type &v)
+ {
+ return base_type::is_empty (v.val);
+ }
+
+ static void remove (value_type &v)
+ {
+ v.~value_type ();
+ }
+};
+
+static void
+test_set_of_type_with_ctor_and_dtor ()
+{
+ typedef hash_set <val_t, false, value_hash_traits> Set;
+
+ {
+ Set s;
+ (void)&s;
+ }
+
+ ASSERT_TRUE (val_t::ndefault == 0);
+ ASSERT_TRUE (val_t::ncopy == 0);
+ ASSERT_TRUE (val_t::nassign == 0);
+ ASSERT_TRUE (val_t::ndtor == 0);
+
+ {
+ Set s;
+ ASSERT_EQ (false, s.add (val_t ()));
+ ASSERT_EQ (true, 1 == s.elements ());
+ }
+
+ ASSERT_TRUE (val_t::ndefault + val_t::ncopy == val_t::ndtor);
+
+ {
+ Set s;
+ ASSERT_EQ (false, s.add (val_t ()));
+ ASSERT_EQ (true, s.add (val_t ()));
+ ASSERT_EQ (true, 1 == s.elements ());
+ }
+
+ ASSERT_TRUE (val_t::ndefault + val_t::ncopy == val_t::ndtor);
+
+ {
+ Set s;
+ val_t v1 (1), v2 (2), v3 (3);
+ int ndefault = val_t::ndefault;
+ int nassign = val_t::nassign;
+
+ ASSERT_EQ (false, s.add (v1));
+ ASSERT_EQ (true, s.contains (v1));
+ ASSERT_EQ (true, 1 == s.elements ());
+
+ ASSERT_EQ (false, s.add (v2));
+ ASSERT_EQ (true, s.contains (v2));
+ ASSERT_EQ (true, 2 == s.elements ());
+
+ ASSERT_EQ (false, s.add (v3));
+ ASSERT_EQ (true, s.contains (v3));
+ ASSERT_EQ (true, 3 == s.elements ());
+
+ ASSERT_EQ (true, s.add (v2));
+ ASSERT_EQ (true, s.contains (v2));
+ ASSERT_EQ (true, 3 == s.elements ());
+
+ s.remove (v2);
+ ASSERT_EQ (true, 2 == s.elements ());
+ s.remove (v3);
+ ASSERT_EQ (true, 1 == s.elements ());
+
+ /* Verify that no default ctors or assignment operators have
+ been called. */
+ ASSERT_EQ (true, ndefault == val_t::ndefault);
+ ASSERT_EQ (true, nassign == val_t::nassign);
+ }
+
+ ASSERT_TRUE (val_t::ndefault + val_t::ncopy == val_t::ndtor);
+}
+
/* Run all of the selftests within this file. */
void
hash_set_tests_c_tests ()
{
test_set_of_strings ();
+ test_set_of_type_with_ctor_and_dtor ();
}
} // namespace selftest
diff --git a/gcc/hash-set.h b/gcc/hash-set.h
index de3532f..a79a88d 100644
--- a/gcc/hash-set.h
+++ b/gcc/hash-set.h
@@ -21,6 +21,16 @@ along with GCC; see the file COPYING3. If not see
#ifndef hash_set_h
#define hash_set_h
+/* Class hash_set is a hash-value based container for objects of
+ KeyId type.
+ KeyId may be a non-trivial (non-POD) type provided a suitabe Traits
+ class. Default Traits specializations are provided for basic types
+ such as integers, pointers, and std::pair. Inserted elements are
+ value-initialized either to zero for POD types or by invoking their
+ default ctor. Removed elements are destroyed by invoking their dtor.
+ On hash_set destruction all elements are removed. Objects of
+ hash_set type are copy-constructible but not assignable. */
+
template<typename KeyId, bool Lazy = false,
typename Traits = default_hash_traits<KeyId> >
class hash_set
@@ -28,7 +38,7 @@ class hash_set
public:
typedef typename Traits::value_type Key;
explicit hash_set (size_t n = 13, bool ggc = false CXX_MEM_STAT_INFO)
- : m_table (n, ggc, GATHER_STATISTICS, HASH_SET_ORIGIN PASS_MEM_STAT) {}
+ : m_table (n, ggc, true, GATHER_STATISTICS, HASH_SET_ORIGIN PASS_MEM_STAT) {}
/* Create a hash_set in gc memory with space for at least n elements. */
@@ -48,7 +58,7 @@ public:
Key *e = m_table.find_slot_with_hash (k, Traits::hash (k), INSERT);
bool existed = !Traits::is_empty (*e);
if (!existed)
- *e = k;
+ new (e) Key (k);
return existed;
}
diff --git a/gcc/hash-table.c b/gcc/hash-table.c
index 646a7a1..e3b5d3d 100644
--- a/gcc/hash-table.c
+++ b/gcc/hash-table.c
@@ -74,6 +74,9 @@ struct prime_ent const prime_tab[] = {
{ 0xfffffffb, 0x00000006, 0x00000008, 31 }
};
+/* Limit number of comparisons when calling hash_table<>::verify. */
+unsigned int hash_table_sanitize_eq_limit;
+
/* The following function returns an index into the above table of the
nearest prime number which is greater than N, and near a power of two. */
@@ -121,3 +124,15 @@ void dump_hash_table_loc_statistics (void)
hash_table_usage ().dump (origin);
}
}
+
+/* Report a hash table checking error. */
+
+ATTRIBUTE_NORETURN ATTRIBUTE_COLD
+void
+hashtab_chk_error ()
+{
+ fprintf (stderr, "hash table checking failed: "
+ "equal operator returns true for a pair "
+ "of values with a different hash value\n");
+ gcc_unreachable ();
+}
diff --git a/gcc/hash-table.h b/gcc/hash-table.h
index 4178616..0e95f5b 100644
--- a/gcc/hash-table.h
+++ b/gcc/hash-table.h
@@ -35,14 +35,17 @@ along with GCC; see the file COPYING3. If not see
several things.
- A typedef named 'value_type' to the value type (from above).
+ Provided a suitable Descriptor class it may be a user-defined,
+ non-POD type.
- A static member function named 'hash' that takes a value_type
(or 'const value_type &') and returns a hashval_t value.
- A typedef named 'compare_type' that is used to test when a value
- is found. This type is the comparison type. Usually, it will be the
- same as value_type. If it is not the same type, you must generally
- explicitly compute hash values and pass them to the hash table.
+ is found. This type is the comparison type. Usually, it will be
+ the same as value_type and may be a user-defined, non-POD type.
+ If it is not the same type, you must generally explicitly compute
+ hash values and pass them to the hash table.
- A static member function named 'equal' that takes a value_type
and a compare_type, and returns a bool. Both arguments can be
@@ -295,12 +298,16 @@ struct prime_ent
extern struct prime_ent const prime_tab[];
+/* Limit number of comparisons when calling hash_table<>::verify. */
+extern unsigned int hash_table_sanitize_eq_limit;
/* Functions for computing hash table indexes. */
extern unsigned int hash_table_higher_prime_index (unsigned long n)
ATTRIBUTE_PURE;
+extern ATTRIBUTE_NORETURN ATTRIBUTE_COLD void hashtab_chk_error ();
+
/* Return X % Y using multiplicative inverse values INV and SHIFT.
The multiplicative inverses computed above are for 32-bit types,
@@ -371,10 +378,12 @@ class hash_table
public:
explicit hash_table (size_t, bool ggc = false,
+ bool sanitize_eq_and_hash = true,
bool gather_mem_stats = GATHER_STATISTICS,
mem_alloc_origin origin = HASH_TABLE_ORIGIN
CXX_MEM_STAT_INFO);
explicit hash_table (const hash_table &, bool ggc = false,
+ bool sanitize_eq_and_hash = true,
bool gather_mem_stats = GATHER_STATISTICS,
mem_alloc_origin origin = HASH_TABLE_ORIGIN
CXX_MEM_STAT_INFO);
@@ -382,10 +391,10 @@ public:
/* Create a hash_table in gc memory. */
static hash_table *
- create_ggc (size_t n CXX_MEM_STAT_INFO)
+ create_ggc (size_t n, bool sanitize_eq_and_hash = true CXX_MEM_STAT_INFO)
{
hash_table *table = ggc_alloc<hash_table> ();
- new (table) hash_table (n, true, GATHER_STATISTICS,
+ new (table) hash_table (n, true, sanitize_eq_and_hash, GATHER_STATISTICS,
HASH_TABLE_ORIGIN PASS_MEM_STAT);
return table;
}
@@ -499,6 +508,9 @@ public:
}
private:
+ /* FIXME: Make the class assignable. See pr90959. */
+ void operator= (hash_table&);
+
template<typename T> friend void gt_ggc_mx (hash_table<T> *);
template<typename T> friend void gt_pch_nx (hash_table<T> *);
template<typename T> friend void
@@ -516,6 +528,7 @@ private:
value_type *alloc_entries (size_t n CXX_MEM_STAT_INFO) const;
value_type *find_empty_slot_for_expand (hashval_t);
+ void verify (const compare_type &comparable, hashval_t hash);
bool too_empty_p (unsigned int);
void expand ();
static bool is_deleted (value_type &v)
@@ -564,6 +577,9 @@ private:
/* if m_entries is stored in ggc memory. */
bool m_ggc;
+ /* True if the table should be sanitized for equal and hash functions. */
+ bool m_sanitize_eq_and_hash;
+
/* If we should gather memory statistics for the table. */
#if GATHER_STATISTICS
bool m_gather_mem_stats;
@@ -586,12 +602,13 @@ extern void dump_hash_table_loc_statistics (void);
template<typename Descriptor, bool Lazy,
template<typename Type> class Allocator>
hash_table<Descriptor, Lazy, Allocator>::hash_table (size_t size, bool ggc,
+ bool sanitize_eq_and_hash,
bool gather_mem_stats
ATTRIBUTE_UNUSED,
mem_alloc_origin origin
MEM_STAT_DECL) :
m_n_elements (0), m_n_deleted (0), m_searches (0), m_collisions (0),
- m_ggc (ggc)
+ m_ggc (ggc), m_sanitize_eq_and_hash (sanitize_eq_and_hash)
#if GATHER_STATISTICS
, m_gather_mem_stats (gather_mem_stats)
#endif
@@ -617,12 +634,14 @@ template<typename Descriptor, bool Lazy,
template<typename Type> class Allocator>
hash_table<Descriptor, Lazy, Allocator>::hash_table (const hash_table &h,
bool ggc,
+ bool sanitize_eq_and_hash,
bool gather_mem_stats
ATTRIBUTE_UNUSED,
mem_alloc_origin origin
MEM_STAT_DECL) :
m_n_elements (h.m_n_elements), m_n_deleted (h.m_n_deleted),
- m_searches (0), m_collisions (0), m_ggc (ggc)
+ m_searches (0), m_collisions (0), m_ggc (ggc),
+ m_sanitize_eq_and_hash (sanitize_eq_and_hash)
#if GATHER_STATISTICS
, m_gather_mem_stats (gather_mem_stats)
#endif
@@ -644,7 +663,7 @@ hash_table<Descriptor, Lazy, Allocator>::hash_table (const hash_table &h,
if (is_deleted (entry))
mark_deleted (nentries[i]);
else if (!is_empty (entry))
- nentries[i] = entry;
+ new ((void*) (nentries + i)) value_type (entry);
}
m_entries = nentries;
}
@@ -912,7 +931,13 @@ hash_table<Descriptor, Lazy, Allocator>
entry = &m_entries[index];
if (is_empty (*entry)
|| (!is_deleted (*entry) && Descriptor::equal (*entry, comparable)))
- return *entry;
+ {
+#if CHECKING_P
+ if (m_sanitize_eq_and_hash)
+ verify (comparable, hash);
+#endif
+ return *entry;
+ }
}
}
@@ -941,8 +966,12 @@ hash_table<Descriptor, Lazy, Allocator>
if (insert == INSERT && m_size * 3 <= m_n_elements * 4)
expand ();
- m_searches++;
+#if CHECKING_P
+ if (m_sanitize_eq_and_hash)
+ verify (comparable, hash);
+#endif
+ m_searches++;
value_type *first_deleted_slot = NULL;
hashval_t index = hash_table_mod1 (hash, m_size_prime_index);
hashval_t hash2 = hash_table_mod2 (hash, m_size_prime_index);
@@ -989,6 +1018,25 @@ hash_table<Descriptor, Lazy, Allocator>
return &m_entries[index];
}
+/* Verify that all existing elements in th hash table which are
+ equal to COMPARABLE have an equal HASH value provided as argument. */
+
+template<typename Descriptor, bool Lazy,
+ template<typename Type> class Allocator>
+void
+hash_table<Descriptor, Lazy, Allocator>
+::verify (const compare_type &comparable, hashval_t hash)
+{
+ for (size_t i = 0; i < MIN (hash_table_sanitize_eq_limit, m_size); i++)
+ {
+ value_type *entry = &m_entries[i];
+ if (!is_empty (*entry) && !is_deleted (*entry)
+ && hash != Descriptor::hash (*entry)
+ && Descriptor::equal (*entry, comparable))
+ hashtab_chk_error ();
+ }
+}
+
/* This function deletes an element with the given COMPARABLE value
from hash table starting with the given HASH. If there is no
matching element in the hash table, this function does nothing. */
diff --git a/gcc/hsa-gen.c b/gcc/hsa-gen.c
index edcec10..f52c49c 100644
--- a/gcc/hsa-gen.c
+++ b/gcc/hsa-gen.c
@@ -2264,7 +2264,7 @@ gen_hsa_addr_insns (tree val, hsa_op_reg *dest, hsa_bb *hbb)
{
HSA_SORRY_ATV (EXPR_LOCATION (val), "support for HSA does "
"not implement taking addresses of complex "
- "CONST_DECLs such as %E", val);
+ "%<CONST_DECL%> such as %E", val);
return;
}
@@ -2449,7 +2449,7 @@ gen_hsa_insns_for_load (hsa_op_reg *dest, tree rhs, tree type, hsa_bb *hbb)
{
HSA_SORRY_ATV (EXPR_LOCATION (rhs),
"support for HSA does not implement conversion "
- "of %E to the requested non-pointer type.", rhs);
+ "of %E to the requested non-pointer type", rhs);
return;
}
@@ -3012,7 +3012,7 @@ gen_hsa_cmp_insn_from_gimple (enum tree_code code, tree lhs, tree rhs,
default:
HSA_SORRY_ATV (EXPR_LOCATION (lhs),
"support for HSA does not implement comparison tree "
- "code %s\n", get_tree_code_name (code));
+ "code %s", get_tree_code_name (code));
return;
}
@@ -3162,8 +3162,8 @@ gen_hsa_insns_for_operation_assignment (gimple *assign, hsa_bb *hbb)
case FLOOR_DIV_EXPR:
case ROUND_DIV_EXPR:
HSA_SORRY_AT (gimple_location (assign),
- "support for HSA does not implement CEIL_DIV_EXPR, "
- "FLOOR_DIV_EXPR or ROUND_DIV_EXPR");
+ "support for HSA does not implement %<CEIL_DIV_EXPR%>, "
+ "%<FLOOR_DIV_EXPR%> or %<ROUND_DIV_EXPR%>");
return;
case TRUNC_MOD_EXPR:
opcode = BRIG_OPCODE_REM;
@@ -3172,8 +3172,8 @@ gen_hsa_insns_for_operation_assignment (gimple *assign, hsa_bb *hbb)
case FLOOR_MOD_EXPR:
case ROUND_MOD_EXPR:
HSA_SORRY_AT (gimple_location (assign),
- "support for HSA does not implement CEIL_MOD_EXPR, "
- "FLOOR_MOD_EXPR or ROUND_MOD_EXPR");
+ "support for HSA does not implement %<CEIL_MOD_EXPR%>, "
+ "%<FLOOR_MOD_EXPR%> or %<ROUND_MOD_EXPR%>");
return;
case NEGATE_EXPR:
opcode = BRIG_OPCODE_NEG;
@@ -4188,8 +4188,8 @@ gen_get_level (gimple *stmt, hsa_bb *hbb)
if (shadow_reg_ptr == NULL)
{
HSA_SORRY_AT (gimple_location (stmt),
- "support for HSA does not implement omp_get_level called "
- "from a function not being inlined within a kernel");
+ "support for HSA does not implement %<omp_get_level%> "
+ "called from a function not being inlined within a kernel");
return;
}
@@ -4230,7 +4230,8 @@ gen_hsa_alloca (gcall *call, hsa_bb *hbb)
if (lhs == NULL_TREE)
return;
- built_in_function fn = DECL_FUNCTION_CODE (gimple_call_fndecl (call));
+ tree fndecl = gimple_call_fndecl (call);
+ built_in_function fn = DECL_FUNCTION_CODE (fndecl);
gcc_checking_assert (ALLOCA_FUNCTION_CODE_P (fn));
@@ -4243,8 +4244,8 @@ gen_hsa_alloca (gcall *call, hsa_bb *hbb)
{
HSA_SORRY_ATV (gimple_location (call),
"support for HSA does not implement "
- "__builtin_alloca_with_align with a non-constant "
- "alignment: %E", alignment_tree);
+ "%qD with a non-constant alignment %E",
+ fndecl, alignment_tree);
}
bit_alignment = tree_to_uhwi (alignment_tree);
@@ -4548,7 +4549,7 @@ omp_simple_builtin::generate (gimple *stmt, hsa_bb *hbb)
HSA_SORRY_AT (gimple_location (stmt), m_warning_message);
else
HSA_SORRY_ATV (gimple_location (stmt),
- "Support for HSA does not implement calls to %s\n",
+ "support for HSA does not implement calls to %qs",
m_name);
}
else if (m_warning_message != NULL)
@@ -5049,7 +5050,7 @@ gen_hsa_atomic_for_builtin (bool ret_orig, enum BrigAtomicOperation acode,
{
HSA_SORRY_ATV (gimple_location (stmt),
"support for HSA does not implement memory model for "
- "ATOMIC_ST: %s", mmname);
+ "%<ATOMIC_ST%>: %s", mmname);
return;
}
}
@@ -5314,8 +5315,8 @@ gen_hsa_insns_for_call (gimple *stmt, hsa_bb *hbb)
gen_hsa_insns_for_direct_call (stmt, hbb);
else if (!gen_hsa_insns_for_known_library_call (stmt, hbb))
HSA_SORRY_AT (gimple_location (stmt),
- "HSA supports only calls of functions marked with pragma "
- "omp declare target");
+ "HSA supports only calls of functions marked with "
+ "%<#pragma omp declare target%>");
return;
}
@@ -5625,7 +5626,7 @@ gen_hsa_insns_for_call (gimple *stmt, hsa_bb *hbb)
case BUILT_IN_GOMP_PARALLEL:
HSA_SORRY_AT (gimple_location (stmt),
"support for HSA does not implement non-gridified "
- "OpenMP parallel constructs.");
+ "OpenMP parallel constructs");
break;
case BUILT_IN_OMP_GET_THREAD_NUM:
diff --git a/gcc/input.c b/gcc/input.c
index c589d70..1e84d2e 100644
--- a/gcc/input.c
+++ b/gcc/input.c
@@ -1215,7 +1215,8 @@ dump_location_info (FILE *stream)
if (x == y)
{
if (x < MAP_START_LOCATION (map))
- inform (x, "token %u has x-location == y-location == %u", i, x);
+ inform (x, "token %u has %<x-location == y-location == %u%>",
+ i, x);
else
fprintf (stream,
"x-location == y-location == %u encodes token # %u\n",
@@ -1223,8 +1224,8 @@ dump_location_info (FILE *stream)
}
else
{
- inform (x, "token %u has x-location == %u", i, x);
- inform (x, "token %u has y-location == %u", i, y);
+ inform (x, "token %u has %<x-location == %u%>", i, x);
+ inform (x, "token %u has %<y-location == %u%>", i, y);
}
}
fprintf (stream, "\n");
diff --git a/gcc/internal-fn.c b/gcc/internal-fn.c
index 04081f3..90f8e56 100644
--- a/gcc/internal-fn.c
+++ b/gcc/internal-fn.c
@@ -117,6 +117,7 @@ init_internal_fns ()
#define while_direct { 0, 2, false }
#define fold_extract_direct { 2, 2, false }
#define fold_left_direct { 1, 1, false }
+#define mask_fold_left_direct { 1, 1, false }
const direct_internal_fn_info direct_internal_fn_array[IFN_LAST + 1] = {
#define DEF_INTERNAL_FN(CODE, FLAGS, FNSPEC) not_direct,
@@ -3000,6 +3001,9 @@ expand_while_optab_fn (internal_fn, gcall *stmt, convert_optab optab)
#define expand_fold_left_optab_fn(FN, STMT, OPTAB) \
expand_direct_optab_fn (FN, STMT, OPTAB, 2)
+#define expand_mask_fold_left_optab_fn(FN, STMT, OPTAB) \
+ expand_direct_optab_fn (FN, STMT, OPTAB, 3)
+
/* RETURN_TYPE and ARGS are a return type and argument list that are
in principle compatible with FN (which satisfies direct_internal_fn_p).
Return the types that should be used to determine whether the
@@ -3088,6 +3092,7 @@ multi_vector_optab_supported_p (convert_optab optab, tree_pair types,
#define direct_while_optab_supported_p convert_optab_supported_p
#define direct_fold_extract_optab_supported_p direct_optab_supported_p
#define direct_fold_left_optab_supported_p direct_optab_supported_p
+#define direct_mask_fold_left_optab_supported_p direct_optab_supported_p
/* Return the optab used by internal function FN. */
diff --git a/gcc/internal-fn.def b/gcc/internal-fn.def
index e370eaa..906d74b 100644
--- a/gcc/internal-fn.def
+++ b/gcc/internal-fn.def
@@ -199,6 +199,9 @@ DEF_INTERNAL_OPTAB_FN (FOLD_EXTRACT_LAST, ECF_CONST | ECF_NOTHROW,
DEF_INTERNAL_OPTAB_FN (FOLD_LEFT_PLUS, ECF_CONST | ECF_NOTHROW,
fold_left_plus, fold_left)
+DEF_INTERNAL_OPTAB_FN (MASK_FOLD_LEFT_PLUS, ECF_CONST | ECF_NOTHROW,
+ mask_fold_left_plus, mask_fold_left)
+
/* Unary math functions. */
DEF_INTERNAL_FLT_FN (ACOS, ECF_CONST, acos, unary)
DEF_INTERNAL_FLT_FN (ACOSH, ECF_CONST, acosh, unary)
@@ -217,6 +220,7 @@ DEF_INTERNAL_FLT_FN (LOG10, ECF_CONST, log10, unary)
DEF_INTERNAL_FLT_FN (LOG1P, ECF_CONST, log1p, unary)
DEF_INTERNAL_FLT_FN (LOG2, ECF_CONST, log2, unary)
DEF_INTERNAL_FLT_FN (LOGB, ECF_CONST, logb, unary)
+DEF_INTERNAL_FLT_FN (SIGNBIT, ECF_CONST, signbit, unary)
DEF_INTERNAL_FLT_FN (SIGNIFICAND, ECF_CONST, significand, unary)
DEF_INTERNAL_FLT_FN (SIN, ECF_CONST, sin, unary)
DEF_INTERNAL_FLT_FN (SINH, ECF_CONST, sinh, unary)
diff --git a/gcc/ipa-cp.c b/gcc/ipa-cp.c
index 59b15fa..b6e781f 100644
--- a/gcc/ipa-cp.c
+++ b/gcc/ipa-cp.c
@@ -806,6 +806,20 @@ public:
{}
};
+/* Skip edges from and to nodes without ipa_cp enabled.
+ Ignore not available symbols. */
+
+static bool
+ignore_edge_p (cgraph_edge *e)
+{
+ enum availability avail;
+ cgraph_node *ultimate_target
+ = e->callee->function_or_virtual_thunk_symbol (&avail, e->caller);
+
+ return (avail <= AVAIL_INTERPOSABLE
+ || !opt_for_fn (ultimate_target->decl, flag_ipa_cp));
+}
+
/* Allocate the arrays in TOPO and topologically sort the nodes into order. */
static void
@@ -815,7 +829,8 @@ build_toporder_info (struct ipa_topo_info *topo)
topo->stack = XCNEWVEC (struct cgraph_node *, symtab->cgraph_count);
gcc_checking_assert (topo->stack_top == 0);
- topo->nnodes = ipa_reduced_postorder (topo->order, true, NULL);
+ topo->nnodes = ipa_reduced_postorder (topo->order, true,
+ ignore_edge_p);
}
/* Free information about strongly connected components and the arrays in
@@ -1070,7 +1085,6 @@ ipcp_bits_lattice::meet_with (ipcp_bits_lattice& other, unsigned precision,
if (TREE_CODE_CLASS (code) == tcc_binary)
{
tree type = TREE_TYPE (operand);
- gcc_assert (INTEGRAL_TYPE_P (type));
widest_int o_value, o_mask;
get_value_and_mask (operand, &o_value, &o_mask);
@@ -4431,7 +4445,6 @@ static bool
cgraph_edge_brings_all_agg_vals_for_node (struct cgraph_edge *cs,
struct cgraph_node *node)
{
- struct ipa_node_params *orig_caller_info = IPA_NODE_REF (cs->caller);
struct ipa_node_params *orig_node_info;
struct ipa_agg_replacement_value *aggval;
int i, ec, count;
@@ -4448,8 +4461,6 @@ cgraph_edge_brings_all_agg_vals_for_node (struct cgraph_edge *cs,
return false;
orig_node_info = IPA_NODE_REF (IPA_NODE_REF (node)->ipcp_orig_node);
- if (orig_caller_info->ipcp_orig_node)
- orig_caller_info = IPA_NODE_REF (orig_caller_info->ipcp_orig_node);
for (i = 0; i < count; i++)
{
diff --git a/gcc/ipa-devirt.c b/gcc/ipa-devirt.c
index 3e040e2..252d920 100644
--- a/gcc/ipa-devirt.c
+++ b/gcc/ipa-devirt.c
@@ -213,6 +213,8 @@ struct GTY(()) odr_type_d
bool odr_violated;
/* Set when virtual table without RTTI previaled table with. */
bool rtti_broken;
+ /* Set when the canonical type is determined using the type name. */
+ bool tbaa_enabled;
};
/* Return TRUE if all derived types of T are known and thus
@@ -284,16 +286,6 @@ struct odr_name_hasher : pointer_hash <odr_type_d>
static inline void remove (odr_type_d *);
};
-/* Has used to unify ODR types based on their associated virtual table.
- This hash is needed to keep -fno-lto-odr-type-merging to work and contains
- only polymorphic types. Types with mangled names are inserted to both. */
-
-struct odr_vtable_hasher:odr_name_hasher
-{
- static inline hashval_t hash (const odr_type_d *);
- static inline bool equal (const odr_type_d *, const tree_node *);
-};
-
static bool
can_be_name_hashed_p (tree t)
{
@@ -329,51 +321,6 @@ odr_name_hasher::hash (const odr_type_d *odr_type)
return hash_odr_name (odr_type->type);
}
-static bool
-can_be_vtable_hashed_p (tree t)
-{
- /* vtable hashing can distinguish only main variants. */
- if (TYPE_MAIN_VARIANT (t) != t)
- return false;
- /* Anonymous namespace types are always handled by name hash. */
- if (type_with_linkage_p (t) && type_in_anonymous_namespace_p (t))
- return false;
- return (TREE_CODE (t) == RECORD_TYPE
- && TYPE_BINFO (t) && BINFO_VTABLE (TYPE_BINFO (t)));
-}
-
-/* Hash type by assembler name of its vtable. */
-
-static hashval_t
-hash_odr_vtable (const_tree t)
-{
- tree v = BINFO_VTABLE (TYPE_BINFO (TYPE_MAIN_VARIANT (t)));
- inchash::hash hstate;
-
- gcc_checking_assert (in_lto_p);
- gcc_checking_assert (!type_in_anonymous_namespace_p (t));
- gcc_checking_assert (TREE_CODE (t) == RECORD_TYPE
- && TYPE_BINFO (t) && BINFO_VTABLE (TYPE_BINFO (t)));
- gcc_checking_assert (TYPE_MAIN_VARIANT (t) == t);
-
- if (TREE_CODE (v) == POINTER_PLUS_EXPR)
- {
- add_expr (TREE_OPERAND (v, 1), hstate);
- v = TREE_OPERAND (TREE_OPERAND (v, 0), 0);
- }
-
- hstate.add_hwi (IDENTIFIER_HASH_VALUE (DECL_ASSEMBLER_NAME (v)));
- return hstate.end ();
-}
-
-/* Return the computed hashcode for ODR_TYPE. */
-
-inline hashval_t
-odr_vtable_hasher::hash (const odr_type_d *odr_type)
-{
- return hash_odr_vtable (odr_type->type);
-}
-
/* For languages with One Definition Rule, work out if
types are the same based on their name.
@@ -404,60 +351,6 @@ types_same_for_odr (const_tree type1, const_tree type2)
|| (type_with_linkage_p (type2) && type_in_anonymous_namespace_p (type2)))
return false;
-
- /* ODR name of the type is set in DECL_ASSEMBLER_NAME of its TYPE_NAME.
-
- Ideally we should never need types without ODR names here. It can however
- happen in two cases:
-
- 1) for builtin types that are not streamed but rebuilt in lto/lto-lang.c
- Here testing for equivalence is safe, since their MAIN_VARIANTs are
- unique.
- 2) for units streamed with -fno-lto-odr-type-merging. Here we can't
- establish precise ODR equivalency, but for correctness we care only
- about equivalency on complete polymorphic types. For these we can
- compare assembler names of their virtual tables. */
- if ((!TYPE_NAME (type1) || !DECL_ASSEMBLER_NAME_SET_P (TYPE_NAME (type1)))
- || (!TYPE_NAME (type2) || !DECL_ASSEMBLER_NAME_SET_P (TYPE_NAME (type2))))
- {
- /* See if types are obviously different (i.e. different codes
- or polymorphic wrt non-polymorphic). This is not strictly correct
- for ODR violating programs, but we can't do better without streaming
- ODR names. */
- if (TREE_CODE (type1) != TREE_CODE (type2))
- return false;
- if (TREE_CODE (type1) == RECORD_TYPE
- && (TYPE_BINFO (type1) == NULL_TREE)
- != (TYPE_BINFO (type2) == NULL_TREE))
- return false;
- if (TREE_CODE (type1) == RECORD_TYPE && TYPE_BINFO (type1)
- && (BINFO_VTABLE (TYPE_BINFO (type1)) == NULL_TREE)
- != (BINFO_VTABLE (TYPE_BINFO (type2)) == NULL_TREE))
- return false;
-
- /* At the moment we have no way to establish ODR equivalence at LTO
- other than comparing virtual table pointers of polymorphic types.
- Eventually we should start saving mangled names in TYPE_NAME.
- Then this condition will become non-trivial. */
-
- if (TREE_CODE (type1) == RECORD_TYPE
- && TYPE_BINFO (type1) && TYPE_BINFO (type2)
- && BINFO_VTABLE (TYPE_BINFO (type1))
- && BINFO_VTABLE (TYPE_BINFO (type2)))
- {
- tree v1 = BINFO_VTABLE (TYPE_BINFO (type1));
- tree v2 = BINFO_VTABLE (TYPE_BINFO (type2));
- gcc_assert (TREE_CODE (v1) == POINTER_PLUS_EXPR
- && TREE_CODE (v2) == POINTER_PLUS_EXPR);
- return (operand_equal_p (TREE_OPERAND (v1, 1),
- TREE_OPERAND (v2, 1), 0)
- && DECL_ASSEMBLER_NAME
- (TREE_OPERAND (TREE_OPERAND (v1, 0), 0))
- == DECL_ASSEMBLER_NAME
- (TREE_OPERAND (TREE_OPERAND (v2, 0), 0)));
- }
- gcc_unreachable ();
- }
return (DECL_ASSEMBLER_NAME (TYPE_NAME (type1))
== DECL_ASSEMBLER_NAME (TYPE_NAME (type2)));
}
@@ -473,11 +366,7 @@ types_odr_comparable (tree t1, tree t2)
return (!in_lto_p
|| TYPE_MAIN_VARIANT (t1) == TYPE_MAIN_VARIANT (t2)
|| (odr_type_p (TYPE_MAIN_VARIANT (t1))
- && odr_type_p (TYPE_MAIN_VARIANT (t2)))
- || (TREE_CODE (t1) == RECORD_TYPE && TREE_CODE (t2) == RECORD_TYPE
- && TYPE_BINFO (t1) && TYPE_BINFO (t2)
- && polymorphic_type_binfo_p (TYPE_BINFO (t1))
- && polymorphic_type_binfo_p (TYPE_BINFO (t2))));
+ && odr_type_p (TYPE_MAIN_VARIANT (t2))));
}
/* Return true if T1 and T2 are ODR equivalent. If ODR equivalency is not
@@ -569,31 +458,6 @@ odr_name_hasher::equal (const odr_type_d *o1, const tree_node *t2)
== DECL_ASSEMBLER_NAME (TYPE_NAME (t2)));
}
-/* Compare types T1 and T2 and return true if they are
- equivalent. */
-
-inline bool
-odr_vtable_hasher::equal (const odr_type_d *o1, const tree_node *t2)
-{
- tree t1 = o1->type;
-
- gcc_checking_assert (TYPE_MAIN_VARIANT (t2) == t2);
- gcc_checking_assert (TYPE_MAIN_VARIANT (t1) == t1);
- gcc_checking_assert (in_lto_p);
- t1 = TYPE_MAIN_VARIANT (t1);
- t2 = TYPE_MAIN_VARIANT (t2);
- if (t1 == t2)
- return true;
- tree v1 = BINFO_VTABLE (TYPE_BINFO (t1));
- tree v2 = BINFO_VTABLE (TYPE_BINFO (t2));
- return (operand_equal_p (TREE_OPERAND (v1, 1),
- TREE_OPERAND (v2, 1), 0)
- && DECL_ASSEMBLER_NAME
- (TREE_OPERAND (TREE_OPERAND (v1, 0), 0))
- == DECL_ASSEMBLER_NAME
- (TREE_OPERAND (TREE_OPERAND (v2, 0), 0)));
-}
-
/* Free ODR type V. */
inline void
@@ -610,8 +474,6 @@ odr_name_hasher::remove (odr_type_d *v)
typedef hash_table<odr_name_hasher> odr_hash_type;
static odr_hash_type *odr_hash;
-typedef hash_table<odr_vtable_hasher> odr_vtable_hash_type;
-static odr_vtable_hash_type *odr_vtable_hash;
/* ODR types are also stored into ODR_TYPE vector to allow consistent
walking. Bases appear before derived types. Vector is garbage collected
@@ -947,7 +809,7 @@ compare_virtual_tables (varpool_node *prevailing, varpool_node *vtable)
if (warning_at (DECL_SOURCE_LOCATION
(TYPE_NAME (DECL_CONTEXT (vtable->decl))), OPT_Wodr,
"virtual table of type %qD violates "
- "one definition rule ",
+ "one definition rule",
DECL_CONTEXT (vtable->decl)))
{
if (TREE_CODE (ref1->referred->decl) == FUNCTION_DECL)
@@ -1750,12 +1612,11 @@ add_type_duplicate (odr_type val, tree type)
val->types_set->add (type);
- /* If we now have a mangled name, be sure to record it to val->type
- so ODR hash can work. */
+ if (!odr_hash)
+ return NULL;
- if (can_be_name_hashed_p (type) && !can_be_name_hashed_p (val->type))
- SET_DECL_ASSEMBLER_NAME (TYPE_NAME (val->type),
- DECL_ASSEMBLER_NAME (TYPE_NAME (type)));
+ gcc_checking_assert (can_be_name_hashed_p (type)
+ && can_be_name_hashed_p (val->type));
bool merge = true;
bool base_mismatch = false;
@@ -2034,7 +1895,6 @@ odr_type
get_odr_type (tree type, bool insert)
{
odr_type_d **slot = NULL;
- odr_type_d **vtable_slot = NULL;
odr_type val = NULL;
hashval_t hash;
bool build_bases = false;
@@ -2045,68 +1905,23 @@ get_odr_type (tree type, bool insert)
if (!in_lto_p && !TYPE_STRUCTURAL_EQUALITY_P (type))
type = TYPE_CANONICAL (type);
- gcc_checking_assert (can_be_name_hashed_p (type)
- || can_be_vtable_hashed_p (type));
+ gcc_checking_assert (can_be_name_hashed_p (type));
- /* Lookup entry, first try name hash, fallback to vtable hash. */
- if (can_be_name_hashed_p (type))
- {
- hash = hash_odr_name (type);
- slot = odr_hash->find_slot_with_hash (type, hash,
- insert ? INSERT : NO_INSERT);
- }
- if ((!slot || !*slot) && in_lto_p && can_be_vtable_hashed_p (type))
- {
- hash = hash_odr_vtable (type);
- if (!odr_vtable_hash)
- odr_vtable_hash = new odr_vtable_hash_type (23);
- vtable_slot = odr_vtable_hash->find_slot_with_hash (type, hash,
- insert ? INSERT : NO_INSERT);
- }
+ hash = hash_odr_name (type);
+ slot = odr_hash->find_slot_with_hash (type, hash,
+ insert ? INSERT : NO_INSERT);
- if (!slot && !vtable_slot)
+ if (!slot)
return NULL;
/* See if we already have entry for type. */
- if ((slot && *slot) || (vtable_slot && *vtable_slot))
+ if (*slot)
{
- if (slot && *slot)
- {
- val = *slot;
- if (flag_checking
- && in_lto_p && can_be_vtable_hashed_p (type))
- {
- hash = hash_odr_vtable (type);
- vtable_slot = odr_vtable_hash->find_slot_with_hash (type, hash,
- NO_INSERT);
- gcc_assert (!vtable_slot || *vtable_slot == *slot);
- vtable_slot = NULL;
- }
- }
- else if (*vtable_slot)
- val = *vtable_slot;
+ val = *slot;
if (val->type != type && insert
&& (!val->types_set || !val->types_set->add (type)))
- {
- /* We have type duplicate, but it may introduce vtable name or
- mangled name; be sure to keep hashes in sync. */
- if (in_lto_p && can_be_vtable_hashed_p (type)
- && (!vtable_slot || !*vtable_slot))
- {
- if (!vtable_slot)
- {
- hash = hash_odr_vtable (type);
- vtable_slot = odr_vtable_hash->find_slot_with_hash
- (type, hash, INSERT);
- gcc_checking_assert (!*vtable_slot || *vtable_slot == val);
- }
- *vtable_slot = val;
- }
- if (slot && !*slot)
- *slot = val;
- build_bases = add_type_duplicate (val, type);
- }
+ build_bases = add_type_duplicate (val, type);
}
else
{
@@ -2120,10 +1935,7 @@ get_odr_type (tree type, bool insert)
val->anonymous_namespace = 0;
build_bases = COMPLETE_TYPE_P (val->type);
insert_to_odr_array = true;
- if (slot)
- *slot = val;
- if (vtable_slot)
- *vtable_slot = val;
+ *slot = val;
}
if (build_bases && TREE_CODE (type) == RECORD_TYPE && TYPE_BINFO (type)
@@ -2170,6 +1982,60 @@ get_odr_type (tree type, bool insert)
return val;
}
+/* Return type that in ODR type hash prevailed TYPE. Be careful and punt
+ on ODR violations. */
+
+tree
+prevailing_odr_type (tree type)
+{
+ odr_type t = get_odr_type (type, false);
+ if (!t || t->odr_violated)
+ return type;
+ return t->type;
+}
+
+/* Set tbaa_enabled flag for TYPE. */
+
+void
+enable_odr_based_tbaa (tree type)
+{
+ odr_type t = get_odr_type (type, true);
+ t->tbaa_enabled = true;
+}
+
+/* True if canonical type of TYPE is determined using ODR name. */
+
+bool
+odr_based_tbaa_p (const_tree type)
+{
+ if (!RECORD_OR_UNION_TYPE_P (type))
+ return false;
+ odr_type t = get_odr_type (const_cast <tree> (type), false);
+ if (!t || !t->tbaa_enabled)
+ return false;
+ return true;
+}
+
+/* Set TYPE_CANONICAL of type and all its variants and duplicates
+ to CANONICAL. */
+
+void
+set_type_canonical_for_odr_type (tree type, tree canonical)
+{
+ odr_type t = get_odr_type (type, false);
+ unsigned int i;
+ tree tt;
+
+ for (tree t2 = t->type; t2; t2 = TYPE_NEXT_VARIANT (t2))
+ TYPE_CANONICAL (t2) = canonical;
+ if (t->types)
+ FOR_EACH_VEC_ELT (*t->types, i, tt)
+ for (tree t2 = tt; t2; t2 = TYPE_NEXT_VARIANT (t2))
+ TYPE_CANONICAL (t2) = canonical;
+}
+
+/* Return true if we reported some ODR violation on TYPE. */
+
bool
odr_type_violation_reported_p (tree type)
{
@@ -2182,11 +2048,7 @@ void
register_odr_type (tree type)
{
if (!odr_hash)
- {
- odr_hash = new odr_hash_type (23);
- if (in_lto_p)
- odr_vtable_hash = new odr_vtable_hash_type (23);
- }
+ odr_hash = new odr_hash_type (23);
if (type == TYPE_MAIN_VARIANT (type))
{
/* To get ODR warings right, first register all sub-types. */
@@ -2244,9 +2106,6 @@ dump_odr_type (FILE *f, odr_type t, int indent=0)
fprintf (f, "%s\n", t->all_derivations_known ? " (derivations known)":"");
if (TYPE_NAME (t->type))
{
- /*fprintf (f, "%*s defined at: %s:%i\n", indent * 2, "",
- DECL_SOURCE_FILE (TYPE_NAME (t->type)),
- DECL_SOURCE_LINE (TYPE_NAME (t->type)));*/
if (DECL_ASSEMBLER_NAME_SET_P (TYPE_NAME (t->type)))
fprintf (f, "%*s mangled name: %s\n", indent * 2, "",
IDENTIFIER_POINTER
@@ -2386,8 +2245,6 @@ build_type_inheritance_graph (void)
timevar_push (TV_IPA_INHERITANCE);
inheritance_dump_file = dump_begin (TDI_inheritance, &flags);
odr_hash = new odr_hash_type (23);
- if (in_lto_p)
- odr_vtable_hash = new odr_vtable_hash_type (23);
/* We reconstruct the graph starting of types of all methods seen in the
unit. */
@@ -2878,10 +2735,7 @@ rebuild_type_inheritance_graph ()
if (!odr_hash)
return;
delete odr_hash;
- if (in_lto_p)
- delete odr_vtable_hash;
odr_hash = NULL;
- odr_vtable_hash = NULL;
odr_types_ptr = NULL;
free_polymorphic_call_targets_hash ();
}
diff --git a/gcc/ipa-icf-gimple.c b/gcc/ipa-icf-gimple.c
index 2528493..0713e12 100644
--- a/gcc/ipa-icf-gimple.c
+++ b/gcc/ipa-icf-gimple.c
@@ -37,6 +37,7 @@ along with GCC; see the file COPYING3. If not see
#include "ipa-utils.h"
#include "tree-eh.h"
#include "builtins.h"
+#include "cfgloop.h"
#include "ipa-icf-gimple.h"
@@ -605,6 +606,40 @@ func_checker::compare_variable_decl (tree t1, tree t2)
return return_with_debug (ret);
}
+/* Compare loop information for basic blocks BB1 and BB2. */
+
+bool
+func_checker::compare_loops (basic_block bb1, basic_block bb2)
+{
+ if ((bb1->loop_father == NULL) != (bb2->loop_father == NULL))
+ return return_false ();
+
+ struct loop *l1 = bb1->loop_father;
+ struct loop *l2 = bb2->loop_father;
+ if (l1 == NULL)
+ return true;
+
+ if ((bb1 == l1->header) != (bb2 == l2->header))
+ return return_false_with_msg ("header");
+ if ((bb1 == l1->latch) != (bb2 == l2->latch))
+ return return_false_with_msg ("latch");
+ if (l1->simdlen != l2->simdlen)
+ return return_false_with_msg ("simdlen");
+ if (l1->safelen != l2->safelen)
+ return return_false_with_msg ("safelen");
+ if (l1->can_be_parallel != l2->can_be_parallel)
+ return return_false_with_msg ("can_be_parallel");
+ if (l1->dont_vectorize != l2->dont_vectorize)
+ return return_false_with_msg ("dont_vectorize");
+ if (l1->force_vectorize != l2->force_vectorize)
+ return return_false_with_msg ("force_vectorize");
+ if (l1->unroll != l2->unroll)
+ return return_false_with_msg ("unroll");
+ if (!compare_variable_decl (l1->simduid, l2->simduid))
+ return return_false_with_msg ("simduid");
+
+ return true;
+}
/* Function visits all gimple labels and creates corresponding
mapping between basic blocks and labels. */
@@ -727,6 +762,9 @@ func_checker::compare_bb (sem_bb *bb1, sem_bb *bb2)
if (!gsi_end_p (gsi2))
return return_false ();
+ if (!compare_loops (bb1->bb, bb2->bb))
+ return return_false ();
+
return true;
}
diff --git a/gcc/ipa-icf-gimple.h b/gcc/ipa-icf-gimple.h
index 0035db3..351bddf 100644
--- a/gcc/ipa-icf-gimple.h
+++ b/gcc/ipa-icf-gimple.h
@@ -36,34 +36,22 @@ along with GCC; see the file COPYING3. If not see
#define FPRINTF_SPACES(file, space_count, format, ...) \
fprintf (file, "%*s" format, space_count, " ", ##__VA_ARGS__);
-/* Prints a MESSAGE to dump_file if exists. FUNC is name of function and
- LINE is location in the source file. */
-
-static inline void
-dump_message_1 (const char *message, const char *func, unsigned int line)
-{
- if (dump_file && (dump_flags & TDF_DETAILS))
- fprintf (dump_file, " debug message: %s (%s:%u)\n", message, func, line);
-}
-
-/* Prints a MESSAGE to dump_file if exists. */
-#define dump_message(message) dump_message_1 (message, __func__, __LINE__)
-
/* Logs a MESSAGE to dump_file if exists and returns false. FUNC is name
of function and LINE is location in the source file. */
static inline bool
-return_false_with_message_1 (const char *message, const char *func,
- unsigned int line)
+return_false_with_message_1 (const char *message, const char *filename,
+ const char *func, unsigned int line)
{
if (dump_file && (dump_flags & TDF_DETAILS))
- fprintf (dump_file, " false returned: '%s' (%s:%u)\n", message, func, line);
+ fprintf (dump_file, " false returned: '%s' in %s at %s:%u\n", message, func,
+ filename, line);
return false;
}
/* Logs a MESSAGE to dump_file if exists and returns false. */
#define return_false_with_msg(message) \
- return_false_with_message_1 (message, __func__, __LINE__)
+ return_false_with_message_1 (message, __FILE__, __func__, __LINE__)
/* Return false and log that false value is returned. */
#define return_false() return_false_with_msg ("")
@@ -72,16 +60,19 @@ return_false_with_message_1 (const char *message, const char *func,
is location in the source file. */
static inline bool
-return_with_result (bool result, const char *func, unsigned int line)
+return_with_result (bool result, const char *filename,
+ const char *func, unsigned int line)
{
if (!result && dump_file && (dump_flags & TDF_DETAILS))
- fprintf (dump_file, " false returned: (%s:%u)\n", func, line);
+ fprintf (dump_file, " false returned: '' in %s at %s:%u\n", func,
+ filename, line);
return result;
}
/* Logs return value if RESULT is false. */
-#define return_with_debug(result) return_with_result (result, __func__, __LINE__)
+#define return_with_debug(result) return_with_result \
+ (result, __FILE__, __func__, __LINE__)
/* Verbose logging function logging statements S1 and S2 of a CODE.
FUNC is name of function and LINE is location in the source file. */
@@ -226,6 +217,9 @@ public:
/* Verifies that trees T1 and T2 do correspond. */
bool compare_variable_decl (tree t1, tree t2);
+ /* Compare loop information for basic blocks BB1 and BB2. */
+ bool compare_loops (basic_block bb1, basic_block bb2);
+
/* Return true if types are compatible for polymorphic call analysis.
COMPARE_PTR indicates if polymorphic type comparsion should be
done for pointers, too. */
diff --git a/gcc/ipa-icf.c b/gcc/ipa-icf.c
index 0741814..7c486ed 100644
--- a/gcc/ipa-icf.c
+++ b/gcc/ipa-icf.c
@@ -52,7 +52,6 @@ along with GCC; see the file COPYING3. If not see
*/
#include "config.h"
-#define INCLUDE_LIST
#include "system.h"
#include "coretypes.h"
#include "backend.h"
@@ -80,6 +79,7 @@ along with GCC; see the file COPYING3. If not see
#include "print-tree.h"
#include "ipa-utils.h"
#include "ipa-icf-gimple.h"
+#include "fibonacci_heap.h"
#include "ipa-icf.h"
#include "stor-layout.h"
#include "dbgcnt.h"
@@ -138,14 +138,15 @@ sem_usage_pair::sem_usage_pair (sem_item *_item, unsigned int _index)
}
sem_item::sem_item (sem_item_type _type, bitmap_obstack *stack)
-: type (_type), m_hash (-1), m_hash_set (false)
+: type (_type), referenced_by_count (0), m_hash (-1), m_hash_set (false)
{
setup (stack);
}
sem_item::sem_item (sem_item_type _type, symtab_node *_node,
bitmap_obstack *stack)
-: type (_type), node (_node), m_hash (-1), m_hash_set (false)
+: type (_type), node (_node), referenced_by_count (0), m_hash (-1),
+ m_hash_set (false)
{
decl = node->decl;
setup (stack);
@@ -154,13 +155,18 @@ sem_item::sem_item (sem_item_type _type, symtab_node *_node,
/* Add reference to a semantic TARGET. */
void
-sem_item::add_reference (sem_item *target)
+sem_item::add_reference (ref_map *refs,
+ sem_item *target)
{
- refs.safe_push (target);
- unsigned index = refs.length ();
- target->usages.safe_push (new sem_usage_pair(this, index));
+ unsigned index = reference_count++;
+ bool existed;
+
+ vec<sem_item *> &v
+ = refs->get_or_insert (new sem_usage_pair (target, index), &existed);
+ v.safe_push (this);
bitmap_set_bit (target->usage_index_bitmap, index);
refs_set.add (target->node);
+ ++target->referenced_by_count;
}
/* Initialize internal data structures. Bitmap STACK is used for
@@ -171,20 +177,14 @@ sem_item::setup (bitmap_obstack *stack)
{
gcc_checking_assert (node);
- refs.create (0);
+ reference_count = 0;
tree_refs.create (0);
- usages.create (0);
usage_index_bitmap = BITMAP_ALLOC (stack);
}
sem_item::~sem_item ()
{
- for (unsigned i = 0; i < usages.length (); i++)
- delete usages[i];
-
- refs.release ();
tree_refs.release ();
- usages.release ();
BITMAP_FREE (usage_index_bitmap);
}
@@ -199,13 +199,6 @@ sem_item::dump (void)
fprintf (dump_file, "[%s] %s (tree:%p)\n", type == FUNC ? "func" : "var",
node->dump_name (), (void *) node->decl);
fprintf (dump_file, " hash: %u\n", get_hash ());
- fprintf (dump_file, " references: ");
-
- for (unsigned i = 0; i < refs.length (); i++)
- fprintf (dump_file, "%s%s ", refs[i]->node->name (),
- i < refs.length() - 1 ? "," : "");
-
- fprintf (dump_file, "\n");
}
}
@@ -889,8 +882,6 @@ sem_function::equals_private (sem_item *item)
if(!m_checker->compare_bb (bb_sorted[i], m_compared_func->bb_sorted[i]))
return return_false();
- dump_message ("All BBs are equal\n");
-
auto_vec <int> bb_dict;
/* Basic block edges check. */
@@ -2230,7 +2221,7 @@ unsigned int sem_item_optimizer::class_id = 0;
sem_item_optimizer::sem_item_optimizer ()
: worklist (0), m_classes (0), m_classes_count (0), m_cgraph_node_hooks (NULL),
- m_varpool_node_hooks (NULL), m_merged_variables ()
+ m_varpool_node_hooks (NULL), m_merged_variables (), m_references ()
{
m_items.create (0);
bitmap_obstack_initialize (&m_bmstack);
@@ -2341,13 +2332,8 @@ sem_item_optimizer::read_section (lto_file_decl_data *file_data,
node = lto_symtab_encoder_deref (encoder, index);
hashval_t hash = streamer_read_uhwi (&ib_main);
-
gcc_assert (node->definition);
- if (dump_file)
- fprintf (dump_file, "Symbol added: %s (tree: %p)\n",
- node->dump_asm_name (), (void *) node->decl);
-
if (is_a<cgraph_node *> (node))
{
cgraph_node *cnode = dyn_cast <cgraph_node *> (node);
@@ -2556,9 +2542,6 @@ sem_item_optimizer::execute (void)
fprintf (dump_file, "Dump after hash based groups\n");
dump_cong_classes ();
- for (unsigned int i = 0; i < m_items.length(); i++)
- m_items[i]->init_wpa ();
-
subdivide_classes_by_equality (true);
if (dump_file)
@@ -2611,15 +2594,7 @@ sem_item_optimizer::parse_funcs_and_vars (void)
{
m_items.safe_push (f);
m_symtab_node_map.put (cnode, f);
-
- if (dump_file)
- fprintf (dump_file, "Parsed function:%s\n", f->node->asm_name ());
-
- if (dump_file && (dump_flags & TDF_DETAILS))
- f->dump_to_file (dump_file);
}
- else if (dump_file)
- fprintf (dump_file, "Not parsed function:%s\n", cnode->asm_name ());
}
varpool_node *vnode;
@@ -2644,6 +2619,7 @@ sem_item_optimizer::add_item_to_class (congruence_class *cls, sem_item *item)
{
item->index_in_class = cls->members.length ();
cls->members.safe_push (item);
+ cls->referenced_by_count += item->referenced_by_count;
item->cls = cls;
}
@@ -2745,7 +2721,7 @@ sem_item_optimizer::build_graph (void)
sem_item **slot = m_symtab_node_map.get
(e->callee->ultimate_alias_target ());
if (slot)
- item->add_reference (*slot);
+ item->add_reference (&m_references, *slot);
e = e->next_callee;
}
@@ -2757,7 +2733,7 @@ sem_item_optimizer::build_graph (void)
sem_item **slot = m_symtab_node_map.get
(ref->referred->ultimate_alias_target ());
if (slot)
- item->add_reference (*slot);
+ item->add_reference (&m_references, *slot);
}
}
}
@@ -2768,20 +2744,20 @@ sem_item_optimizer::build_graph (void)
void
sem_item_optimizer::parse_nonsingleton_classes (void)
{
- unsigned int init_called_count = 0;
+ unsigned int counter = 0;
for (unsigned i = 0; i < m_items.length (); i++)
if (m_items[i]->cls->members.length () > 1)
{
m_items[i]->init ();
- init_called_count++;
+ ++counter;
}
if (dump_file)
- fprintf (dump_file, "Init called for %u items (%.2f%%).\n",
- init_called_count,
- m_items.length () ? 100.0f * init_called_count / m_items.length ()
- : 0.0f);
+ {
+ float f = m_items.length () ? 100.0f * counter / m_items.length () : 0.0f;
+ fprintf (dump_file, "Init called for %u items (%.2f%%).\n", counter, f);
+ }
}
/* Equality function for semantic items is used to subdivide existing
@@ -2987,13 +2963,6 @@ sem_item_optimizer::verify_classes (void)
gcc_assert (item);
gcc_assert (item->cls == cls);
-
- for (unsigned k = 0; k < item->usages.length (); k++)
- {
- sem_usage_pair *usage = item->usages[k];
- gcc_assert (usage->item->index_in_class
- < usage->item->cls->members.length ());
- }
}
}
}
@@ -3106,10 +3075,11 @@ sem_item_optimizer::traverse_congruence_split (congruence_class * const &cls,
/* Release class if not presented in work list. */
if (!in_worklist)
delete cls;
- }
+ return true;
+ }
- return true;
+ return false;
}
/* Compare function for sorting pairs in do_congruence_step_f. */
@@ -3131,7 +3101,7 @@ sem_item_optimizer::sort_congruence_split (const void *a_, const void *b_)
/* Tests if a class CLS used as INDEXth splits any congruence classes.
Bitmap stack BMSTACK is used for bitmap allocation. */
-void
+bool
sem_item_optimizer::do_congruence_step_for_index (congruence_class *cls,
unsigned int index)
{
@@ -3140,31 +3110,32 @@ sem_item_optimizer::do_congruence_step_for_index (congruence_class *cls,
for (unsigned int i = 0; i < cls->members.length (); i++)
{
sem_item *item = cls->members[i];
+ sem_usage_pair needle (item, index);
+ vec<sem_item *> *callers = m_references.get (&needle);
+ if (callers == NULL)
+ continue;
- /* Iterate all usages that have INDEX as usage of the item. */
- for (unsigned int j = 0; j < item->usages.length (); j++)
+ for (unsigned int j = 0; j < callers->length (); j++)
{
- sem_usage_pair *usage = item->usages[j];
-
- if (usage->index != index)
+ sem_item *caller = (*callers)[j];
+ if (caller->cls->members.length () < 2)
continue;
-
- bitmap *slot = split_map.get (usage->item->cls);
+ bitmap *slot = split_map.get (caller->cls);
bitmap b;
if(!slot)
{
b = BITMAP_ALLOC (&m_bmstack);
- split_map.put (usage->item->cls, b);
+ split_map.put (caller->cls, b);
}
else
b = *slot;
- gcc_checking_assert (usage->item->cls);
- gcc_checking_assert (usage->item->index_in_class
- < usage->item->cls->members.length ());
+ gcc_checking_assert (caller->cls);
+ gcc_checking_assert (caller->index_in_class
+ < caller->cls->members.length ());
- bitmap_set_bit (b, usage->item->index_in_class);
+ bitmap_set_bit (b, caller->index_in_class);
}
}
@@ -3180,12 +3151,16 @@ sem_item_optimizer::do_congruence_step_for_index (congruence_class *cls,
pair.cls = cls;
splitter_class_removed = false;
+ bool r = false;
for (unsigned i = 0; i < to_split.length (); ++i)
- traverse_congruence_split (to_split[i].first, to_split[i].second, &pair);
+ r |= traverse_congruence_split (to_split[i].first, to_split[i].second,
+ &pair);
/* Bitmap clean-up. */
split_map.traverse <traverse_split_pair *,
sem_item_optimizer::release_split_map> (NULL);
+
+ return r;
}
/* Every usage of a congruence class CLS is a candidate that can split the
@@ -3206,9 +3181,9 @@ sem_item_optimizer::do_congruence_step (congruence_class *cls)
EXECUTE_IF_SET_IN_BITMAP (usage, 0, i, bi)
{
if (dump_file && (dump_flags & TDF_DETAILS))
- fprintf (dump_file, " processing congruence step for class: %u, "
- "index: %u\n", cls->id, i);
-
+ fprintf (dump_file, " processing congruence step for class: %u "
+ "(%u items, %u references), index: %u\n", cls->id,
+ cls->referenced_by_count, cls->members.length (), i);
do_congruence_step_for_index (cls, i);
if (splitter_class_removed)
@@ -3228,7 +3203,7 @@ sem_item_optimizer::worklist_push (congruence_class *cls)
return;
cls->in_worklist = true;
- worklist.push_back (cls);
+ worklist.insert (cls->referenced_by_count, cls);
}
/* Pops a class from worklist. */
@@ -3240,8 +3215,7 @@ sem_item_optimizer::worklist_pop (void)
while (!worklist.empty ())
{
- cls = worklist.front ();
- worklist.pop_front ();
+ cls = worklist.extract_min ();
if (cls->in_worklist)
{
cls->in_worklist = false;
@@ -3273,7 +3247,7 @@ sem_item_optimizer::process_cong_reduction (void)
if (dump_file)
fprintf (dump_file, "Worklist has been filled with: %lu\n",
- (unsigned long) worklist.size ());
+ (unsigned long) worklist.nodes ());
if (dump_file && (dump_flags & TDF_DETAILS))
fprintf (dump_file, "Congruence class reduction\n");
@@ -3300,13 +3274,9 @@ sem_item_optimizer::dump_cong_classes (void)
if (!dump_file)
return;
- fprintf (dump_file,
- "Congruence classes: %u (unique hash values: %lu), with total: "
- "%u items\n", m_classes_count,
- (unsigned long) m_classes.elements (), m_items.length ());
-
/* Histogram calculation. */
unsigned int max_index = 0;
+ unsigned int single_element_classes = 0;
unsigned int* histogram = XCNEWVEC (unsigned int, m_items.length () + 1);
for (hash_table<congruence_class_hash>::iterator it = m_classes.begin ();
@@ -3318,21 +3288,25 @@ sem_item_optimizer::dump_cong_classes (void)
if (c > max_index)
max_index = c;
+
+ if (c == 1)
+ ++single_element_classes;
}
fprintf (dump_file,
+ "Congruence classes: %lu with total: %u items (in a non-singular "
+ "class: %u)\n", (unsigned long) m_classes.elements (),
+ m_items.length (), m_items.length () - single_element_classes);
+ fprintf (dump_file,
"Class size histogram [num of members]: number of classe number "
"of classess\n");
-
for (unsigned int i = 0; i <= max_index; i++)
if (histogram[i])
- fprintf (dump_file, "[%u]: %u classes\n", i, histogram[i]);
-
- fprintf (dump_file, "\n\n");
+ fprintf (dump_file, "%6u: %6u\n", i, histogram[i]);
if (dump_flags & TDF_DETAILS)
- for (hash_table<congruence_class_hash>::iterator it = m_classes.begin ();
- it != m_classes.end (); ++it)
+ for (hash_table<congruence_class_hash>::iterator it = m_classes.begin ();
+ it != m_classes.end (); ++it)
{
fprintf (dump_file, " group: with %u classes:\n",
(*it)->classes.length ());
@@ -3648,7 +3622,7 @@ bool
congruence_class::is_class_used (void)
{
for (unsigned int i = 0; i < members.length (); i++)
- if (members[i]->usages.length ())
+ if (members[i]->referenced_by_count)
return true;
return false;
diff --git a/gcc/ipa-icf.h b/gcc/ipa-icf.h
index 27d588c..2bf0f15 100644
--- a/gcc/ipa-icf.h
+++ b/gcc/ipa-icf.h
@@ -29,7 +29,8 @@ class congruence_class
{
public:
/* Congruence class constructor for a new class with _ID. */
- congruence_class (unsigned int _id): in_worklist (false), id(_id)
+ congruence_class (unsigned int _id): in_worklist (false), id (_id),
+ referenced_by_count (0)
{
}
@@ -54,6 +55,9 @@ public:
/* Global unique class identifier. */
unsigned int id;
+
+ /* Total number of references to items of this class. */
+ unsigned referenced_by_count;
};
/* Semantic item type enum. */
@@ -126,7 +130,6 @@ struct symbol_compare_hash : nofree_ptr_hash <symbol_compare_collection>
}
};
-
/* Semantic item usage pair. */
class sem_usage_pair
{
@@ -141,6 +144,32 @@ public:
unsigned int index;
};
+struct sem_usage_pair_hash : pointer_hash <sem_usage_pair>
+{
+ static inline hashval_t hash (sem_usage_pair *);
+ static inline bool equal (sem_usage_pair *, sem_usage_pair *);
+};
+
+inline hashval_t
+sem_usage_pair_hash::hash (sem_usage_pair *pair)
+{
+ inchash::hash hstate;
+
+ hstate.add_ptr (pair->item);
+ hstate.add_int (pair->index);
+
+ return hstate.end ();
+}
+
+inline bool
+sem_usage_pair_hash::equal (sem_usage_pair *p1, sem_usage_pair *p2)
+{
+ return p1->item == p2->item && p1->index == p2->index;
+}
+
+struct sem_usage_hash : sem_usage_pair_hash, typed_delete_remove <sem_usage_pair> {};
+typedef hash_map<sem_usage_hash, auto_vec<sem_item *> > ref_map;
+
typedef std::pair<symtab_node *, symtab_node *> symtab_pair;
/* Semantic item is a base class that encapsulates all shared functionality
@@ -161,14 +190,11 @@ public:
/* Dump function for debugging purpose. */
DEBUG_FUNCTION void dump (void);
- /* Initialize semantic item by info reachable during LTO WPA phase. */
- virtual void init_wpa (void) = 0;
-
/* Semantic item initialization function. */
virtual void init (void) = 0;
/* Add reference to a semantic TARGET. */
- void add_reference (sem_item *target);
+ void add_reference (ref_map *map, sem_item *target);
/* Fast equality function based on knowledge known in WPA. */
virtual bool equals_wpa (sem_item *item,
@@ -216,8 +242,9 @@ public:
/* Declaration tree node. */
tree decl;
- /* Semantic references used that generate congruence groups. */
- vec <sem_item *> refs;
+ /* Number of references to a semantic symbols (function calls,
+ variable references). */
+ unsigned reference_count;
/* Pointer to a congruence class the item belongs to. */
congruence_class *cls;
@@ -225,9 +252,6 @@ public:
/* Index of the item in a class belonging to. */
unsigned int index_in_class;
- /* List of semantic items where the instance is used. */
- vec <sem_usage_pair *> usages;
-
/* A bitmap with indices of all classes referencing this item. */
bitmap usage_index_bitmap;
@@ -239,6 +263,9 @@ public:
/* Temporary hash used where hash values of references are added. */
hashval_t global_hash;
+
+ /* Number of references to this symbol. */
+ unsigned referenced_by_count;
protected:
/* Cached, once calculated hash for the item. */
@@ -295,10 +322,6 @@ public:
~sem_function ();
- inline virtual void init_wpa (void)
- {
- }
-
virtual void init (void);
virtual bool equals_wpa (sem_item *item,
hash_map <symtab_node *, sem_item *> &ignored_nodes);
@@ -402,8 +425,6 @@ public:
sem_variable (varpool_node *_node, bitmap_obstack *stack);
- inline virtual void init_wpa (void) {}
-
/* Semantic variable initialization function. */
inline virtual void init (void)
{
@@ -504,7 +525,7 @@ public:
/* Worklist of congruence classes that can potentially
refine classes of congruence. */
- std::list<congruence_class *> worklist;
+ fibonacci_heap<unsigned, congruence_class> worklist;
/* Remove semantic ITEM and release memory. */
void remove_item (sem_item *item);
@@ -581,7 +602,7 @@ private:
/* Tests if a class CLS used as INDEXth splits any congruence classes.
Bitmap stack BMSTACK is used for bitmap allocation. */
- void do_congruence_step_for_index (congruence_class *cls, unsigned int index);
+ bool do_congruence_step_for_index (congruence_class *cls, unsigned int index);
/* Makes pairing between a congruence class CLS and semantic ITEM. */
static void add_item_to_class (congruence_class *cls, sem_item *item);
@@ -644,6 +665,9 @@ private:
/* Vector of merged variables. Needed for fixup of points-to-analysis
info. */
vec <symtab_pair> m_merged_variables;
+
+ /* Hash map will all references. */
+ ref_map m_references;
}; // class sem_item_optimizer
} // ipa_icf namespace
diff --git a/gcc/ipa-inline.c b/gcc/ipa-inline.c
index 745bdf3..3475258 100644
--- a/gcc/ipa-inline.c
+++ b/gcc/ipa-inline.c
@@ -1752,6 +1752,16 @@ sum_callers (struct cgraph_node *node, void *data)
return false;
}
+/* We only propagate across edges with non-interposable callee. */
+
+inline bool
+ignore_edge_p (struct cgraph_edge *e)
+{
+ enum availability avail;
+ e->callee->function_or_virtual_thunk_symbol (&avail, e->caller);
+ return (avail <= AVAIL_INTERPOSABLE);
+}
+
/* We use greedy algorithm for inlining of small functions:
All inline candidates are put into prioritized heap ordered in
increasing badness.
@@ -1779,7 +1789,7 @@ inline_small_functions (void)
metrics. */
max_count = profile_count::uninitialized ();
- ipa_reduced_postorder (order, true, NULL);
+ ipa_reduced_postorder (order, true, ignore_edge_p);
free (order);
FOR_EACH_DEFINED_FUNCTION (node)
diff --git a/gcc/ipa-profile.c b/gcc/ipa-profile.c
index de9563d..c80ea7a 100644
--- a/gcc/ipa-profile.c
+++ b/gcc/ipa-profile.c
@@ -191,17 +191,17 @@ ipa_profile_generate_summary (void)
takes away bad histograms. */
if (h)
{
- /* counter 0 is target, counter 1 is number of execution we called target,
- counter 2 is total number of executions. */
- if (h->hvalue.counters[2])
+ gcov_type val, count, all;
+ if (get_most_common_single_value (NULL, "indirect call",
+ h, &val, &count, &all))
{
struct cgraph_edge * e = node->get_edge (stmt);
if (e && !e->indirect_unknown_callee)
continue;
- e->indirect_info->common_target_id
- = h->hvalue.counters [0];
+
+ e->indirect_info->common_target_id = val;
e->indirect_info->common_target_probability
- = GCOV_COMPUTE_SCALE (h->hvalue.counters [1], h->hvalue.counters [2]);
+ = GCOV_COMPUTE_SCALE (count, all);
if (e->indirect_info->common_target_probability > REG_BR_PROB_BASE)
{
if (dump_file)
diff --git a/gcc/ipa-prop.c b/gcc/ipa-prop.c
index d86c2f3..a53a6ec 100644
--- a/gcc/ipa-prop.c
+++ b/gcc/ipa-prop.c
@@ -1458,7 +1458,7 @@ get_ssa_def_if_simple_copy (tree rhs)
return rhs;
}
-/* Simple linked list, describing known contents of an aggregate beforere
+/* Simple linked list, describing known contents of an aggregate before
call. */
struct ipa_known_agg_contents_list
@@ -1471,41 +1471,48 @@ struct ipa_known_agg_contents_list
struct ipa_known_agg_contents_list *next;
};
-/* Find the proper place in linked list of ipa_known_agg_contents_list
- structures where to put a new one with the given LHS_OFFSET and LHS_SIZE,
- unless there is a partial overlap, in which case return NULL, or such
- element is already there, in which case set *ALREADY_THERE to true. */
+/* Add a known content item into a linked list of ipa_known_agg_contents_list
+ structure, in which all elements are sorted ascendingly by offset. */
-static struct ipa_known_agg_contents_list **
-get_place_in_agg_contents_list (struct ipa_known_agg_contents_list **list,
- HOST_WIDE_INT lhs_offset,
- HOST_WIDE_INT lhs_size,
- bool *already_there)
+static inline void
+add_to_agg_contents_list (struct ipa_known_agg_contents_list **plist,
+ struct ipa_known_agg_contents_list *item)
{
- struct ipa_known_agg_contents_list **p = list;
- while (*p && (*p)->offset < lhs_offset)
+ struct ipa_known_agg_contents_list *list = *plist;
+
+ for (; list; list = list->next)
{
- if ((*p)->offset + (*p)->size > lhs_offset)
- return NULL;
- p = &(*p)->next;
+ if (list->offset >= item->offset)
+ break;
+
+ plist = &list->next;
}
- if (*p && (*p)->offset < lhs_offset + lhs_size)
+ item->next = list;
+ *plist = item;
+}
+
+/* Check whether a given known content is clobbered by certain element in
+ a linked list of ipa_known_agg_contents_list. */
+
+static inline bool
+clobber_by_agg_contents_list_p (struct ipa_known_agg_contents_list *list,
+ struct ipa_known_agg_contents_list *item)
+{
+ for (; list; list = list->next)
{
- if ((*p)->offset == lhs_offset && (*p)->size == lhs_size)
- /* We already know this value is subsequently overwritten with
- something else. */
- *already_there = true;
- else
- /* Otherwise this is a partial overlap which we cannot
- represent. */
- return NULL;
+ if (list->offset >= item->offset)
+ return list->offset < item->offset + item->size;
+
+ if (list->offset + list->size > item->offset)
+ return true;
}
- return p;
+
+ return false;
}
/* Build aggregate jump function from LIST, assuming there are exactly
- CONST_COUNT constant entries there and that th offset of the passed argument
+ CONST_COUNT constant entries there and that offset of the passed argument
is ARG_OFFSET and store it into JFUNC. */
static void
@@ -1528,26 +1535,79 @@ build_agg_jump_func_from_list (struct ipa_known_agg_contents_list *list,
}
}
+/* If STMT is a memory store to the object whose address is BASE, extract
+ information (offset, size, and value) into CONTENT, and return true,
+ otherwise we conservatively assume the whole object is modified with
+ unknown content, and return false. CHECK_REF means that access to object
+ is expected to be in form of MEM_REF expression. */
+
+static bool
+extract_mem_content (gimple *stmt, tree base, bool check_ref,
+ struct ipa_known_agg_contents_list *content)
+{
+ HOST_WIDE_INT lhs_offset, lhs_size;
+ tree lhs, rhs, lhs_base;
+ bool reverse;
+
+ if (!gimple_assign_single_p (stmt))
+ return false;
+
+ lhs = gimple_assign_lhs (stmt);
+ rhs = gimple_assign_rhs1 (stmt);
+
+ if (!is_gimple_reg_type (TREE_TYPE (rhs))
+ || TREE_CODE (lhs) == BIT_FIELD_REF
+ || contains_bitfld_component_ref_p (lhs))
+ return false;
+
+ lhs_base = get_ref_base_and_extent_hwi (lhs, &lhs_offset,
+ &lhs_size, &reverse);
+ if (!lhs_base)
+ return false;
+
+ if (check_ref)
+ {
+ if (TREE_CODE (lhs_base) != MEM_REF
+ || TREE_OPERAND (lhs_base, 0) != base
+ || !integer_zerop (TREE_OPERAND (lhs_base, 1)))
+ return false;
+ }
+ else if (lhs_base != base)
+ return false;
+
+ rhs = get_ssa_def_if_simple_copy (rhs);
+
+ content->size = lhs_size;
+ content->offset = lhs_offset;
+ content->constant = is_gimple_ip_invariant (rhs) ? rhs : NULL_TREE;
+ content->next = NULL;
+
+ return true;
+}
+
/* Traverse statements from CALL backwards, scanning whether an aggregate given
in ARG is filled in with constant values. ARG can either be an aggregate
expression or a pointer to an aggregate. ARG_TYPE is the type of the
aggregate. JFUNC is the jump function into which the constants are
- subsequently stored. */
+ subsequently stored. AA_WALK_BUDGET_P points to limit on number of
+ statements we allow get_continuation_for_phi to examine. */
static void
-determine_locally_known_aggregate_parts (gcall *call, tree arg,
- tree arg_type,
- struct ipa_jump_func *jfunc)
+determine_known_aggregate_parts (gcall *call, tree arg,
+ tree arg_type,
+ struct ipa_jump_func *jfunc,
+ unsigned *aa_walk_budget_p)
{
- struct ipa_known_agg_contents_list *list = NULL;
+ struct ipa_known_agg_contents_list *list = NULL, *all_list = NULL;
+ bitmap visited = NULL;
int item_count = 0, const_count = 0;
+ int ipa_max_agg_items = PARAM_VALUE (PARAM_IPA_MAX_AGG_ITEMS);
HOST_WIDE_INT arg_offset, arg_size;
- gimple_stmt_iterator gsi;
tree arg_base;
bool check_ref, by_ref;
ao_ref r;
- if (PARAM_VALUE (PARAM_IPA_MAX_AGG_ITEMS) == 0)
+ if (ipa_max_agg_items == 0)
return;
/* The function operates in three stages. First, we prepare check_ref, r,
@@ -1606,82 +1666,61 @@ determine_locally_known_aggregate_parts (gcall *call, tree arg,
ao_ref_init (&r, arg);
}
- /* Second stage walks back the BB, looks at individual statements and as long
- as it is confident of how the statements affect contents of the
- aggregates, it builds a sorted linked list of ipa_agg_jf_list structures
- describing it. */
- gsi = gsi_for_stmt (call);
- gsi_prev (&gsi);
- for (; !gsi_end_p (gsi); gsi_prev (&gsi))
- {
- struct ipa_known_agg_contents_list *n, **p;
- gimple *stmt = gsi_stmt (gsi);
- HOST_WIDE_INT lhs_offset, lhs_size;
- tree lhs, rhs, lhs_base;
- bool reverse;
-
- if (!stmt_may_clobber_ref_p_1 (stmt, &r))
- continue;
- if (!gimple_assign_single_p (stmt))
- break;
+ /* Second stage traverses virtual SSA web backwards starting from the call
+ statement, only looks at individual dominating virtual operand (its
+ definition dominates the call), as long as it is confident that content
+ of the aggregate is affected by definition of the virtual operand, it
+ builds a sorted linked list of ipa_agg_jf_list describing that. */
- lhs = gimple_assign_lhs (stmt);
- rhs = gimple_assign_rhs1 (stmt);
- if (!is_gimple_reg_type (TREE_TYPE (rhs))
- || TREE_CODE (lhs) == BIT_FIELD_REF
- || contains_bitfld_component_ref_p (lhs))
- break;
-
- lhs_base = get_ref_base_and_extent_hwi (lhs, &lhs_offset,
- &lhs_size, &reverse);
- if (!lhs_base)
- break;
+ for (tree dom_vuse = gimple_vuse (call); dom_vuse;)
+ {
+ gimple *stmt = SSA_NAME_DEF_STMT (dom_vuse);
- if (check_ref)
+ if (gimple_code (stmt) == GIMPLE_PHI)
{
- if (TREE_CODE (lhs_base) != MEM_REF
- || TREE_OPERAND (lhs_base, 0) != arg_base
- || !integer_zerop (TREE_OPERAND (lhs_base, 1)))
- break;
+ dom_vuse = get_continuation_for_phi (stmt, &r, *aa_walk_budget_p,
+ &visited, false, NULL, NULL);
+ continue;
}
- else if (lhs_base != arg_base)
+
+ if (stmt_may_clobber_ref_p_1 (stmt, &r))
{
- if (DECL_P (lhs_base))
- continue;
- else
+ struct ipa_known_agg_contents_list *content
+ = XALLOCA (struct ipa_known_agg_contents_list);
+
+ if (!extract_mem_content (stmt, arg_base, check_ref, content))
break;
- }
- bool already_there = false;
- p = get_place_in_agg_contents_list (&list, lhs_offset, lhs_size,
- &already_there);
- if (!p)
- break;
- if (already_there)
- continue;
+ /* Now we get a dominating virtual operand, and need to check
+ whether its value is clobbered any other dominating one. */
+ if (content->constant
+ && !clobber_by_agg_contents_list_p (all_list, content))
+ {
+ struct ipa_known_agg_contents_list *copy
+ = XALLOCA (struct ipa_known_agg_contents_list);
- rhs = get_ssa_def_if_simple_copy (rhs);
- n = XALLOCA (struct ipa_known_agg_contents_list);
- n->size = lhs_size;
- n->offset = lhs_offset;
- if (is_gimple_ip_invariant (rhs))
- {
- n->constant = rhs;
- const_count++;
+ /* Add to the list consisting of only dominating virtual
+ operands, whose definitions can finally reach the call. */
+ add_to_agg_contents_list (&list, (*copy = *content, copy));
+
+ if (++const_count == ipa_max_agg_items)
+ break;
+ }
+
+ /* Add to the list consisting of all dominating virtual operands. */
+ add_to_agg_contents_list (&all_list, content);
+
+ if (++item_count == 2 * ipa_max_agg_items)
+ break;
}
- else
- n->constant = NULL_TREE;
- n->next = *p;
- *p = n;
+ dom_vuse = gimple_vuse (stmt);
+ }
- item_count++;
- if (const_count == PARAM_VALUE (PARAM_IPA_MAX_AGG_ITEMS)
- || item_count == 2 * PARAM_VALUE (PARAM_IPA_MAX_AGG_ITEMS))
- break;
- }
+ if (visited)
+ BITMAP_FREE (visited);
/* Third stage just goes over the list and creates an appropriate vector of
- ipa_agg_jf_item structures out of it, of sourse only if there are
+ ipa_agg_jf_item structures out of it, of course only if there are
any known constants to begin with. */
if (const_count)
@@ -1691,6 +1730,7 @@ determine_locally_known_aggregate_parts (gcall *call, tree arg,
}
}
+
/* Return the Ith param type of callee associated with call graph
edge E. */
@@ -1797,7 +1837,7 @@ ipa_set_jfunc_vr (ipa_jump_func *jf, enum value_range_kind type,
jf->m_vr = ipa_get_value_range (type, min, max);
}
-/* Assign to JF a pointer to a value_range just liek TMP but either fetch a
+/* Assign to JF a pointer to a value_range just like TMP but either fetch a
copy from ipa_vr_hash_table or allocate a new on in GC memory. */
static void
@@ -1978,7 +2018,8 @@ ipa_compute_jump_functions_for_edge (struct ipa_func_body_info *fbi,
|| !ipa_get_jf_ancestor_agg_preserved (jfunc))
&& (AGGREGATE_TYPE_P (TREE_TYPE (arg))
|| POINTER_TYPE_P (param_type)))
- determine_locally_known_aggregate_parts (call, arg, param_type, jfunc);
+ determine_known_aggregate_parts (call, arg, param_type, jfunc,
+ &fbi->aa_walk_budget);
}
if (!useful_context)
vec_free (args->polymorphic_call_contexts);
diff --git a/gcc/ipa-pure-const.c b/gcc/ipa-pure-const.c
index bb561d0..f5e5396 100644
--- a/gcc/ipa-pure-const.c
+++ b/gcc/ipa-pure-const.c
@@ -1361,12 +1361,14 @@ ignore_edge_for_nothrow (struct cgraph_edge *e)
return true;
enum availability avail;
- cgraph_node *n = e->callee->function_or_virtual_thunk_symbol (&avail,
- e->caller);
- if (avail <= AVAIL_INTERPOSABLE || TREE_NOTHROW (n->decl))
+ cgraph_node *ultimate_target
+ = e->callee->function_or_virtual_thunk_symbol (&avail, e->caller);
+ if (avail <= AVAIL_INTERPOSABLE || TREE_NOTHROW (ultimate_target->decl))
return true;
- return opt_for_fn (e->callee->decl, flag_non_call_exceptions)
- && !e->callee->binds_to_current_def_p (e->caller);
+ return ((opt_for_fn (e->callee->decl, flag_non_call_exceptions)
+ && !e->callee->binds_to_current_def_p (e->caller))
+ || !opt_for_fn (e->caller->decl, flag_ipa_pure_const)
+ || !opt_for_fn (ultimate_target->decl, flag_ipa_pure_const));
}
/* Return true if NODE is self recursive function.
@@ -1396,16 +1398,21 @@ cdtor_p (cgraph_node *n, void *)
return false;
}
-/* We only propagate across edges with non-interposable callee. */
+/* Skip edges from and to nodes without ipa_pure_const enabled.
+ Ignore not available symbols. */
static bool
ignore_edge_for_pure_const (struct cgraph_edge *e)
{
enum availability avail;
- e->callee->function_or_virtual_thunk_symbol (&avail, e->caller);
- return (avail <= AVAIL_INTERPOSABLE);
-}
+ cgraph_node *ultimate_target
+ = e->callee->function_or_virtual_thunk_symbol (&avail, e->caller);
+ return (avail <= AVAIL_INTERPOSABLE
+ || !opt_for_fn (e->caller->decl, flag_ipa_pure_const)
+ || !opt_for_fn (ultimate_target->decl,
+ flag_ipa_pure_const));
+}
/* Produce transitive closure over the callgraph and compute pure/const
attributes. */
diff --git a/gcc/ipa-reference.c b/gcc/ipa-reference.c
index 9ef03c2..7b2614f 100644
--- a/gcc/ipa-reference.c
+++ b/gcc/ipa-reference.c
@@ -676,16 +676,23 @@ get_read_write_all_from_node (struct cgraph_node *node,
}
}
-/* Skip edges from and to nodes without ipa_reference enables. This leave
- them out of strongy connected coponents and makes them easyto skip in the
+/* Skip edges from and to nodes without ipa_reference enabled.
+ Ignore not available symbols. This leave
+ them out of strongly connected components and makes them easy to skip in the
propagation loop bellow. */
static bool
ignore_edge_p (cgraph_edge *e)
{
- return (!opt_for_fn (e->caller->decl, flag_ipa_reference)
- || !opt_for_fn (e->callee->function_symbol ()->decl,
- flag_ipa_reference));
+ enum availability avail;
+ cgraph_node *ultimate_target
+ = e->callee->function_or_virtual_thunk_symbol (&avail, e->caller);
+
+ return (avail < AVAIL_INTERPOSABLE
+ || (avail == AVAIL_INTERPOSABLE
+ && !(flags_from_decl_or_type (e->callee->decl) & ECF_LEAF))
+ || !opt_for_fn (e->caller->decl, flag_ipa_reference)
+ || !opt_for_fn (ultimate_target->decl, flag_ipa_reference));
}
/* Produce the global information by preforming a transitive closure
diff --git a/gcc/ipa-utils.c b/gcc/ipa-utils.c
index 79b250c..25c2e2c 100644
--- a/gcc/ipa-utils.c
+++ b/gcc/ipa-utils.c
@@ -103,8 +103,7 @@ searchc (struct searchc_env* env, struct cgraph_node *v,
continue;
if (w->aux
- && (avail > AVAIL_INTERPOSABLE
- || avail == AVAIL_INTERPOSABLE))
+ && (avail >= AVAIL_INTERPOSABLE))
{
w_info = (struct ipa_dfs_info *) w->aux;
if (w_info->new_node)
diff --git a/gcc/ipa-utils.h b/gcc/ipa-utils.h
index b70e8c5..22e6970 100644
--- a/gcc/ipa-utils.h
+++ b/gcc/ipa-utils.h
@@ -92,6 +92,10 @@ void warn_types_mismatch (tree t1, tree t2, location_t loc1 = UNKNOWN_LOCATION,
bool odr_or_derived_type_p (const_tree t);
bool odr_types_equivalent_p (tree type1, tree type2);
bool odr_type_violation_reported_p (tree type);
+tree prevailing_odr_type (tree type);
+void enable_odr_based_tbaa (tree type);
+bool odr_based_tbaa_p (const_tree type);
+void set_type_canonical_for_odr_type (tree type, tree canonical);
/* Return vector containing possible targets of polymorphic call E.
If COMPLETEP is non-NULL, store true if the list is complete.
@@ -186,19 +190,14 @@ type_with_linkage_p (const_tree t)
if (!TYPE_NAME (t) || TREE_CODE (TYPE_NAME (t)) != TYPE_DECL)
return false;
- /* To support -fno-lto-odr-type-merigng recognize types with vtables
- to have linkage. */
- if (RECORD_OR_UNION_TYPE_P (t)
- && TYPE_BINFO (t) && BINFO_VTABLE (TYPE_BINFO (t)))
- return true;
-
- /* After free_lang_data was run and -flto-odr-type-merging we can recongize
+ /* After free_lang_data was run we can recongize
types with linkage by presence of mangled name. */
if (DECL_ASSEMBLER_NAME_SET_P (TYPE_NAME (t)))
return true;
if (in_lto_p)
return false;
+
/* We used to check for TYPE_STUB_DECL but that is set to NULL for forward
declarations. */
@@ -209,6 +208,8 @@ type_with_linkage_p (const_tree t)
if (!TYPE_CONTEXT (t))
return false;
+ gcc_checking_assert (TREE_CODE (t) == ENUMERAL_TYPE || TYPE_CXX_ODR_P (t));
+
return true;
}
@@ -242,26 +243,8 @@ odr_type_p (const_tree t)
/* We do not have this information when not in LTO, but we do not need
to care, since it is used only for type merging. */
gcc_checking_assert (in_lto_p || flag_lto);
-
- if (!type_with_linkage_p (t))
- return false;
-
- /* To support -fno-lto-odr-type-merging consider types with vtables ODR. */
- if (type_in_anonymous_namespace_p (t))
- return true;
-
- if (TYPE_NAME (t) && DECL_ASSEMBLER_NAME_SET_P (TYPE_NAME (t)))
- {
- /* C++ FE uses magic <anon> as assembler names of anonymous types.
- verify that this match with type_in_anonymous_namespace_p. */
- gcc_checking_assert (strcmp ("<anon>",
- IDENTIFIER_POINTER
- (DECL_ASSEMBLER_NAME (TYPE_NAME (t)))));
- return true;
- }
- return false;
+ return TYPE_NAME (t) && TREE_CODE (TYPE_NAME (t)) == TYPE_DECL
+ && DECL_ASSEMBLER_NAME_SET_P (TYPE_NAME (t));
}
#endif /* GCC_IPA_UTILS_H */
-
-
diff --git a/gcc/ira-color.c b/gcc/ira-color.c
index aa91b56..8a90ae1 100644
--- a/gcc/ira-color.c
+++ b/gcc/ira-color.c
@@ -1108,7 +1108,6 @@ setup_profitable_hard_regs (void)
|| empty_profitable_hard_regs (a))
continue;
data = ALLOCNO_COLOR_DATA (a);
- mode = ALLOCNO_MODE (a);
if ((costs = ALLOCNO_UPDATED_HARD_REG_COSTS (a)) != NULL
|| (costs = ALLOCNO_HARD_REG_COSTS (a)) != NULL)
{
diff --git a/gcc/ira-conflicts.c b/gcc/ira-conflicts.c
index 9a3e381..813a6d4 100644
--- a/gcc/ira-conflicts.c
+++ b/gcc/ira-conflicts.c
@@ -358,7 +358,7 @@ add_insn_allocno_copies (rtx_insn *insn)
rtx set, operand, dup;
bool bound_p[MAX_RECOG_OPERANDS];
int i, n, freq;
- HARD_REG_SET alts;
+ alternative_mask alts;
freq = REG_FREQ_FROM_BB (BLOCK_FOR_INSN (insn));
if (freq == 0)
@@ -379,7 +379,7 @@ add_insn_allocno_copies (rtx_insn *insn)
there are no dead registers, there will be no such copies. */
if (! find_reg_note (insn, REG_DEAD, NULL_RTX))
return;
- ira_setup_alts (insn, alts);
+ alts = ira_setup_alts (insn);
for (i = 0; i < recog_data.n_operands; i++)
bound_p[i] = false;
for (i = 0; i < recog_data.n_operands; i++)
diff --git a/gcc/ira-int.h b/gcc/ira-int.h
index 3c7fe4e..1ea35f7 100644
--- a/gcc/ira-int.h
+++ b/gcc/ira-int.h
@@ -963,8 +963,8 @@ extern void ira_print_disposition (FILE *);
extern void ira_debug_disposition (void);
extern void ira_debug_allocno_classes (void);
extern void ira_init_register_move_cost (machine_mode);
-extern void ira_setup_alts (rtx_insn *insn, HARD_REG_SET &alts);
-extern int ira_get_dup_out_num (int op_num, HARD_REG_SET &alts);
+extern alternative_mask ira_setup_alts (rtx_insn *);
+extern int ira_get_dup_out_num (int, alternative_mask);
/* ira-build.c */
diff --git a/gcc/ira-lives.c b/gcc/ira-lives.c
index faadf08..2029027 100644
--- a/gcc/ira-lives.c
+++ b/gcc/ira-lives.c
@@ -80,8 +80,9 @@ static int last_call_num;
/* The number of last call at which given allocno was saved. */
static int *allocno_saved_at_call;
-/* The value of get_preferred_alternatives for the current instruction,
- supplemental to recog_data. */
+/* The value returned by ira_setup_alts for the current instruction;
+ i.e. the set of alternatives that we should consider to be likely
+ candidates during reloading. */
static alternative_mask preferred_alternatives;
/* If non-NULL, the source operand of a register to register copy for which
@@ -1236,16 +1237,9 @@ process_bb_node_lives (ira_loop_tree_node_t loop_tree_node)
}
}
- extract_insn (insn);
- preferred_alternatives = get_preferred_alternatives (insn);
- preprocess_constraints (insn);
+ preferred_alternatives = ira_setup_alts (insn);
process_single_reg_class_operands (false, freq);
- /* See which defined values die here. */
- FOR_EACH_INSN_DEF (def, insn)
- if (!call_p || !DF_REF_FLAGS_IS_SET (def, DF_REF_MAY_CLOBBER))
- mark_ref_dead (def);
-
if (call_p)
{
/* Try to find a SET in the CALL_INSN_FUNCTION_USAGE, and from
@@ -1309,6 +1303,17 @@ process_bb_node_lives (ira_loop_tree_node_t loop_tree_node)
}
}
+ /* See which defined values die here. Note that we include
+ the call insn in the lifetimes of these values, so we don't
+ mistakenly consider, for e.g. an addressing mode with a
+ side-effect like a post-increment fetching the address,
+ that the use happens before the call, and the def to happen
+ after the call: we believe both to happen before the actual
+ call. (We don't handle return-values here.) */
+ FOR_EACH_INSN_DEF (def, insn)
+ if (!call_p || !DF_REF_FLAGS_IS_SET (def, DF_REF_MAY_CLOBBER))
+ mark_ref_dead (def);
+
make_early_clobber_and_input_conflicts ();
curr_point++;
diff --git a/gcc/ira.c b/gcc/ira.c
index fd481d6..214fdff 100644
--- a/gcc/ira.c
+++ b/gcc/ira.c
@@ -1784,68 +1784,59 @@ setup_prohibited_mode_move_regs (void)
-/* Setup possible alternatives in ALTS for INSN. */
-void
-ira_setup_alts (rtx_insn *insn, HARD_REG_SET &alts)
+/* Extract INSN and return the set of alternatives that we should consider.
+ This excludes any alternatives whose constraints are obviously impossible
+ to meet (e.g. because the constraint requires a constant and the operand
+ is nonconstant). It also excludes alternatives that are bound to need
+ a spill or reload, as long as we have other alternatives that match
+ exactly. */
+alternative_mask
+ira_setup_alts (rtx_insn *insn)
{
- /* MAP nalt * nop -> start of constraints for given operand and
- alternative. */
- static vec<const char *> insn_constraints;
int nop, nalt;
bool curr_swapped;
const char *p;
int commutative = -1;
extract_insn (insn);
+ preprocess_constraints (insn);
alternative_mask preferred = get_preferred_alternatives (insn);
- CLEAR_HARD_REG_SET (alts);
- insn_constraints.release ();
- insn_constraints.safe_grow_cleared (recog_data.n_operands
- * recog_data.n_alternatives + 1);
+ alternative_mask alts = 0;
+ alternative_mask exact_alts = 0;
/* Check that the hard reg set is enough for holding all
alternatives. It is hard to imagine the situation when the
assertion is wrong. */
ira_assert (recog_data.n_alternatives
<= (int) MAX (sizeof (HARD_REG_ELT_TYPE) * CHAR_BIT,
FIRST_PSEUDO_REGISTER));
+ for (nop = 0; nop < recog_data.n_operands; nop++)
+ if (recog_data.constraints[nop][0] == '%')
+ {
+ commutative = nop;
+ break;
+ }
for (curr_swapped = false;; curr_swapped = true)
{
- /* Calculate some data common for all alternatives to speed up the
- function. */
- for (nop = 0; nop < recog_data.n_operands; nop++)
- {
- for (nalt = 0, p = recog_data.constraints[nop];
- nalt < recog_data.n_alternatives;
- nalt++)
- {
- insn_constraints[nop * recog_data.n_alternatives + nalt] = p;
- while (*p && *p != ',')
- {
- /* We only support one commutative marker, the first
- one. We already set commutative above. */
- if (*p == '%' && commutative < 0)
- commutative = nop;
- p++;
- }
- if (*p)
- p++;
- }
- }
for (nalt = 0; nalt < recog_data.n_alternatives; nalt++)
{
- if (!TEST_BIT (preferred, nalt)
- || TEST_HARD_REG_BIT (alts, nalt))
+ if (!TEST_BIT (preferred, nalt) || TEST_BIT (exact_alts, nalt))
continue;
+ const operand_alternative *op_alt
+ = &recog_op_alt[nalt * recog_data.n_operands];
+ int this_reject = 0;
for (nop = 0; nop < recog_data.n_operands; nop++)
{
int c, len;
+ this_reject += op_alt[nop].reject;
+
rtx op = recog_data.operand[nop];
- p = insn_constraints[nop * recog_data.n_alternatives + nalt];
+ p = op_alt[nop].constraint;
if (*p == 0 || *p == ',')
continue;
-
+
+ bool win_p = false;
do
switch (c = *p, len = CONSTRAINT_LEN (c, p), c)
{
@@ -1863,7 +1854,14 @@ ira_setup_alts (rtx_insn *insn, HARD_REG_SET &alts)
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
- goto op_success;
+ {
+ rtx other = recog_data.operand[c - '0'];
+ if (MEM_P (other)
+ ? rtx_equal_p (other, op)
+ : REG_P (op) || SUBREG_P (op))
+ goto op_success;
+ win_p = true;
+ }
break;
case 'g':
@@ -1877,7 +1875,11 @@ ira_setup_alts (rtx_insn *insn, HARD_REG_SET &alts)
{
case CT_REGISTER:
if (reg_class_for_constraint (cn) != NO_REGS)
- goto op_success;
+ {
+ if (REG_P (op) || SUBREG_P (op))
+ goto op_success;
+ win_p = true;
+ }
break;
case CT_CONST_INT:
@@ -1888,9 +1890,14 @@ ira_setup_alts (rtx_insn *insn, HARD_REG_SET &alts)
break;
case CT_ADDRESS:
+ goto op_success;
+
case CT_MEMORY:
case CT_SPECIAL_MEMORY:
- goto op_success;
+ if (MEM_P (op))
+ goto op_success;
+ win_p = true;
+ break;
case CT_FIXED_FORM:
if (constraint_satisfied_p (op, cn))
@@ -1901,12 +1908,22 @@ ira_setup_alts (rtx_insn *insn, HARD_REG_SET &alts)
}
}
while (p += len, c);
- break;
+ if (!win_p)
+ break;
+ /* We can make the alternative match by spilling a register
+ to memory or loading something into a register. Count a
+ cost of one reload (the equivalent of the '?' constraint). */
+ this_reject += 6;
op_success:
;
}
+
if (nop >= recog_data.n_operands)
- SET_HARD_REG_BIT (alts, nalt);
+ {
+ alts |= ALTERNATIVE_BIT (nalt);
+ if (this_reject == 0)
+ exact_alts |= ALTERNATIVE_BIT (nalt);
+ }
}
if (commutative < 0)
break;
@@ -1916,14 +1933,15 @@ ira_setup_alts (rtx_insn *insn, HARD_REG_SET &alts)
if (curr_swapped)
break;
}
+ return exact_alts ? exact_alts : alts;
}
/* Return the number of the output non-early clobber operand which
should be the same in any case as operand with number OP_NUM (or
- negative value if there is no such operand). The function takes
- only really possible alternatives into consideration. */
+ negative value if there is no such operand). ALTS is the mask
+ of alternatives that we should consider. */
int
-ira_get_dup_out_num (int op_num, HARD_REG_SET &alts)
+ira_get_dup_out_num (int op_num, alternative_mask alts)
{
int curr_alt, c, original, dup;
bool ignore_p, use_commut_op_p;
@@ -1940,7 +1958,7 @@ ira_get_dup_out_num (int op_num, HARD_REG_SET &alts)
{
rtx op = recog_data.operand[op_num];
- for (curr_alt = 0, ignore_p = !TEST_HARD_REG_BIT (alts, curr_alt),
+ for (curr_alt = 0, ignore_p = !TEST_BIT (alts, curr_alt),
original = -1;;)
{
c = *str;
@@ -1951,7 +1969,7 @@ ira_get_dup_out_num (int op_num, HARD_REG_SET &alts)
else if (c == ',')
{
curr_alt++;
- ignore_p = !TEST_HARD_REG_BIT (alts, curr_alt);
+ ignore_p = !TEST_BIT (alts, curr_alt);
}
else if (! ignore_p)
switch (c)
@@ -1981,26 +1999,8 @@ ira_get_dup_out_num (int op_num, HARD_REG_SET &alts)
}
if (original == -1)
goto fail;
- dup = -1;
- for (ignore_p = false, str = recog_data.constraints[original - '0'];
- *str != 0;
- str++)
- if (ignore_p)
- {
- if (*str == ',')
- ignore_p = false;
- }
- else if (*str == '#')
- ignore_p = true;
- else if (! ignore_p)
- {
- if (*str == '=')
- dup = original - '0';
- /* It is better ignore an alternative with early clobber. */
- else if (*str == '&')
- goto fail;
- }
- if (dup >= 0)
+ dup = original - '0';
+ if (recog_data.operand_type[dup] == OP_OUT)
return dup;
fail:
if (use_commut_op_p)
@@ -2326,7 +2326,7 @@ ira_setup_eliminable_regset (void)
SET_HARD_REG_BIT (ira_no_alloc_regs, eliminables[i].from);
}
else if (cannot_elim)
- error ("%s cannot be used in asm here",
+ error ("%s cannot be used in %<asm%> here",
reg_names[eliminables[i].from]);
else
df_set_regs_ever_live (eliminables[i].from, true);
@@ -2340,7 +2340,7 @@ ira_setup_eliminable_regset (void)
SET_HARD_REG_BIT (ira_no_alloc_regs, HARD_FRAME_POINTER_REGNUM);
}
else if (frame_pointer_needed)
- error ("%s cannot be used in asm here",
+ error ("%s cannot be used in %<asm%> here",
reg_names[HARD_FRAME_POINTER_REGNUM]);
else
df_set_regs_ever_live (HARD_FRAME_POINTER_REGNUM, true);
@@ -4414,10 +4414,9 @@ rtx_moveable_p (rtx *loc, enum op_type type)
{
const char *fmt;
rtx x = *loc;
- enum rtx_code code = GET_CODE (x);
int i, j;
- code = GET_CODE (x);
+ enum rtx_code code = GET_CODE (x);
switch (code)
{
case CONST:
@@ -5198,6 +5197,8 @@ ira (FILE *f)
int ira_max_point_before_emit;
bool saved_flag_caller_saves = flag_caller_saves;
enum ira_region saved_flag_ira_region = flag_ira_region;
+ unsigned int i;
+ int num_used_regs = 0;
clear_bb_flags ();
@@ -5213,12 +5214,17 @@ ira (FILE *f)
ira_conflicts_p = optimize > 0;
+ /* Determine the number of pseudos actually requiring coloring. */
+ for (i = FIRST_PSEUDO_REGISTER; i < DF_REG_SIZE (df); i++)
+ num_used_regs += !!(DF_REG_USE_COUNT (i) + DF_REG_DEF_COUNT (i));
+
/* If there are too many pseudos and/or basic blocks (e.g. 10K
pseudos and 10K blocks or 100K pseudos and 1K blocks), we will
use simplified and faster algorithms in LRA. */
lra_simple_p
= (ira_use_lra_p
- && max_reg_num () >= (1 << 26) / last_basic_block_for_fn (cfun));
+ && num_used_regs >= (1 << 26) / last_basic_block_for_fn (cfun));
+
if (lra_simple_p)
{
/* It permits to skip live range splitting in LRA. */
diff --git a/gcc/json.cc b/gcc/json.cc
index 2e8e21b..512e2e51 100644
--- a/gcc/json.cc
+++ b/gcc/json.cc
@@ -99,6 +99,22 @@ object::set (const char *key, value *v)
m_map.put (xstrdup (key), v);
}
+/* Get the json::value * for KEY.
+
+ The object retains ownership of the value. */
+
+value *
+object::get (const char *key) const
+{
+ gcc_assert (key);
+
+ value **ptr = const_cast <map_t &> (m_map).get (key);
+ if (ptr)
+ return *ptr;
+ else
+ return NULL;
+}
+
/* class json::array, a subclass of json::value, representing
an ordered collection of values. */
@@ -240,6 +256,18 @@ assert_print_eq (const json::value &jv, const char *expected_json)
ASSERT_STREQ (expected_json, pp_formatted_text (&pp));
}
+/* Verify that object::get works as expected. */
+
+static void
+test_object_get ()
+{
+ object obj;
+ value *val = new json::string ("value");
+ obj.set ("foo", val);
+ ASSERT_EQ (obj.get ("foo"), val);
+ ASSERT_EQ (obj.get ("not-present"), NULL);
+}
+
/* Verify that JSON objects are written correctly. We can't test more than
one key/value pair, as we don't impose a guaranteed ordering. */
@@ -306,6 +334,7 @@ test_writing_literals ()
void
json_cc_tests ()
{
+ test_object_get ();
test_writing_objects ();
test_writing_arrays ();
test_writing_numbers ();
diff --git a/gcc/json.h b/gcc/json.h
index 0527a2fc..d8a690e 100644
--- a/gcc/json.h
+++ b/gcc/json.h
@@ -90,6 +90,7 @@ class object : public value
void print (pretty_printer *pp) const FINAL OVERRIDE;
void set (const char *key, value *v);
+ value *get (const char *key) const;
private:
typedef hash_map <char *, value *,
diff --git a/gcc/loop-iv.c b/gcc/loop-iv.c
index 82b4bdb..207b5e2 100644
--- a/gcc/loop-iv.c
+++ b/gcc/loop-iv.c
@@ -61,6 +61,7 @@ along with GCC; see the file COPYING3. If not see
#include "intl.h"
#include "dumpfile.h"
#include "rtl-iter.h"
+#include "tree-ssa-loop-niter.h"
/* Possible return values of iv_get_reaching_def. */
@@ -2997,6 +2998,19 @@ find_simple_exit (struct loop *loop, struct niter_desc *desc)
fprintf (dump_file, "Loop %d is not simple.\n", loop->num);
}
+ /* Fix up the finiteness if possible. We can only do it for single exit,
+ since the loop is finite, but it's possible that we predicate one loop
+ exit to be finite which can not be determined as finite in middle-end as
+ well. It results in incorrect predicate information on the exit condition
+ expression. For example, if says [(int) _1 + -8, + , -8] != 0 finite,
+ it means _1 can exactly divide -8. */
+ if (desc->infinite && single_exit (loop) && finite_loop_p (loop))
+ {
+ desc->infinite = NULL_RTX;
+ if (dump_file)
+ fprintf (dump_file, " infinite updated to finite.\n");
+ }
+
free (body);
}
diff --git a/gcc/lra-assigns.c b/gcc/lra-assigns.c
index 8b56b58..609feec 100644
--- a/gcc/lra-assigns.c
+++ b/gcc/lra-assigns.c
@@ -1692,7 +1692,7 @@ lra_assign (bool &fails_p)
&& (lra_assignment_iter_after_spill
> LRA_MAX_ASSIGNMENT_ITERATION_NUMBER))
internal_error
- ("Maximum number of LRA assignment passes is achieved (%d)\n",
+ ("maximum number of LRA assignment passes is achieved (%d)",
LRA_MAX_ASSIGNMENT_ITERATION_NUMBER);
return no_spills_p;
}
diff --git a/gcc/lra-constraints.c b/gcc/lra-constraints.c
index cf33da8..d1d99e0 100644
--- a/gcc/lra-constraints.c
+++ b/gcc/lra-constraints.c
@@ -4898,7 +4898,7 @@ lra_constraints (bool first_p)
}
if (new_insns_num > MAX_RELOAD_INSNS_NUMBER)
internal_error
- ("Max. number of generated reload insns per insn is achieved (%d)\n",
+ ("maximum number of generated reload insns per insn achieved (%d)",
MAX_RELOAD_INSNS_NUMBER);
new_insns_num++;
if (DEBUG_INSN_P (curr_insn))
diff --git a/gcc/lra-eliminations.c b/gcc/lra-eliminations.c
index ee9fd51..051839a 100644
--- a/gcc/lra-eliminations.c
+++ b/gcc/lra-eliminations.c
@@ -876,32 +876,6 @@ mark_not_eliminable (rtx x, machine_mode mem_mode)
-#ifdef HARD_FRAME_POINTER_REGNUM
-
-/* Search INSN's reg notes to see whether the destination is equal to
- WHAT + C for some constant C. Return true if so, storing C in
- *OFFSET_OUT and removing the reg note. */
-static bool
-remove_reg_equal_offset_note (rtx_insn *insn, rtx what, poly_int64 *offset_out)
-{
- rtx link, *link_loc;
-
- for (link_loc = &REG_NOTES (insn);
- (link = *link_loc) != NULL_RTX;
- link_loc = &XEXP (link, 1))
- if (REG_NOTE_KIND (link) == REG_EQUAL
- && GET_CODE (XEXP (link, 0)) == PLUS
- && XEXP (XEXP (link, 0), 0) == what
- && poly_int_rtx_p (XEXP (XEXP (link, 0), 1), offset_out))
- {
- *link_loc = XEXP (link, 1);
- return true;
- }
- return false;
-}
-
-#endif
-
/* Scan INSN and eliminate all eliminable hard registers in it.
If REPLACE_P is true, do the replacement destructively. Also
@@ -939,72 +913,6 @@ eliminate_regs_in_insn (rtx_insn *insn, bool replace_p, bool first_p,
return;
}
- /* Check for setting an eliminable register. */
- if (old_set != 0 && REG_P (SET_DEST (old_set))
- && (ep = get_elimination (SET_DEST (old_set))) != NULL)
- {
- for (ep = reg_eliminate; ep < &reg_eliminate[NUM_ELIMINABLE_REGS]; ep++)
- if (ep->from_rtx == SET_DEST (old_set) && ep->can_eliminate)
- {
- bool delete_p = replace_p;
-
-#ifdef HARD_FRAME_POINTER_REGNUM
- if (ep->from == FRAME_POINTER_REGNUM
- && ep->to == HARD_FRAME_POINTER_REGNUM)
- /* If this is setting the frame pointer register to the
- hardware frame pointer register and this is an
- elimination that will be done (tested above), this
- insn is really adjusting the frame pointer downward
- to compensate for the adjustment done before a
- nonlocal goto. */
- {
- rtx src = SET_SRC (old_set);
- poly_int64 offset = 0;
-
- /* We should never process such insn with non-zero
- UPDATE_SP_OFFSET. */
- lra_assert (known_eq (update_sp_offset, 0));
-
- if (remove_reg_equal_offset_note (insn, ep->to_rtx, &offset)
- || strip_offset (src, &offset) == ep->to_rtx)
- {
- if (replace_p)
- {
- SET_DEST (old_set) = ep->to_rtx;
- lra_update_insn_recog_data (insn);
- return;
- }
- offset -= (ep->offset - ep->previous_offset);
- src = plus_constant (Pmode, ep->to_rtx, offset);
-
- /* First see if this insn remains valid when we
- make the change. If not, keep the INSN_CODE
- the same and let the constraint pass fit it
- up. */
- validate_change (insn, &SET_SRC (old_set), src, 1);
- validate_change (insn, &SET_DEST (old_set),
- ep->from_rtx, 1);
- if (! apply_change_group ())
- {
- SET_SRC (old_set) = src;
- SET_DEST (old_set) = ep->from_rtx;
- }
- lra_update_insn_recog_data (insn);
- /* Add offset note for future updates. */
- add_reg_note (insn, REG_EQUAL, copy_rtx (src));
- return;
- }
- }
-#endif
-
- /* This insn isn't serving a useful purpose. We delete it
- when REPLACE is set. */
- if (delete_p)
- lra_delete_dead_insn (insn);
- return;
- }
- }
-
/* We allow one special case which happens to work on all machines we
currently support: a single set with the source or a REG_EQUAL
note being a PLUS of an eliminable register and a constant. */
@@ -1145,8 +1053,7 @@ eliminate_regs_in_insn (rtx_insn *insn, bool replace_p, bool first_p,
PARALLEL since the new one still will, but we can't call
single_set without having put new body into the insn and the
re-recognition won't hurt in this rare case. */
- id = lra_update_insn_recog_data (insn);
- static_id = id->insn_static_data;
+ lra_update_insn_recog_data (insn);
}
/* Spill pseudos which are assigned to hard registers in SET. Add
diff --git a/gcc/lra.c b/gcc/lra.c
index bef2f67..982a3cc 100644
--- a/gcc/lra.c
+++ b/gcc/lra.c
@@ -1029,12 +1029,8 @@ lra_set_insn_recog_data (rtx_insn *insn)
data->operand_loc,
constraints, operand_mode, NULL);
if (nop > 0)
- {
- const char *p = recog_data.constraints[0];
-
- for (p = constraints[0]; *p; p++)
- nalt += *p == ',';
- }
+ for (const char *p =constraints[0]; *p; p++)
+ nalt += *p == ',';
data->insn_static_data = insn_static_data
= get_static_insn_data (-1, nop, 0, nalt);
for (i = 0; i < nop; i++)
diff --git a/gcc/lto-compress.c b/gcc/lto-compress.c
index 3287178..b925363 100644
--- a/gcc/lto-compress.c
+++ b/gcc/lto-compress.c
@@ -35,6 +35,10 @@ along with GCC; see the file COPYING3. If not see
#include "lto-compress.h"
#include "timevar.h"
+#ifdef HAVE_ZSTD_H
+#include <zstd.h>
+#endif
+
/* Compression stream structure, holds the flush callback and opaque token,
the buffered data, and a note of whether compressing or uncompressing. */
@@ -92,6 +96,91 @@ lto_normalized_zlib_level (void)
return level;
}
+/* Free the buffer and memory associated with STREAM. */
+
+static void
+lto_destroy_compression_stream (struct lto_compression_stream *stream)
+{
+ free (stream->buffer);
+ free (stream);
+}
+
+#ifdef HAVE_ZSTD_H
+/* Return a zstd compression level that zstd will not reject. Normalizes
+ the compression level from the command line flag, clamping non-default
+ values to the appropriate end of their valid range. */
+
+static int
+lto_normalized_zstd_level (void)
+{
+ int level = flag_lto_compression_level;
+
+ if (level != ZSTD_CLEVEL_DEFAULT)
+ {
+ if (level < 1)
+ level = 1;
+ else if (level > ZSTD_maxCLevel ())
+ level = ZSTD_maxCLevel ();
+ }
+
+ return level;
+}
+
+/* Compress STREAM using ZSTD algorithm. */
+
+static void
+lto_compression_zstd (struct lto_compression_stream *stream)
+{
+ unsigned char *cursor = (unsigned char *) stream->buffer;
+ size_t size = stream->bytes;
+
+ timevar_push (TV_IPA_LTO_COMPRESS);
+ size_t const outbuf_length = ZSTD_compressBound (size);
+ char *outbuf = (char *) xmalloc (outbuf_length);
+
+ size_t const csize = ZSTD_compress (outbuf, outbuf_length, cursor, size,
+ lto_normalized_zstd_level ());
+
+ if (ZSTD_isError (csize))
+ internal_error ("compressed stream: %s", ZSTD_getErrorName (csize));
+
+ stream->callback (outbuf, csize, NULL);
+
+ lto_destroy_compression_stream (stream);
+ free (outbuf);
+ timevar_pop (TV_IPA_LTO_COMPRESS);
+}
+
+/* Uncompress STREAM using ZSTD algorithm. */
+
+static void
+lto_uncompression_zstd (struct lto_compression_stream *stream)
+{
+ unsigned char *cursor = (unsigned char *) stream->buffer;
+ size_t size = stream->bytes;
+
+ timevar_push (TV_IPA_LTO_DECOMPRESS);
+ unsigned long long const rsize = ZSTD_getFrameContentSize (cursor, size);
+ if (rsize == ZSTD_CONTENTSIZE_ERROR)
+ internal_error ("original not compressed with zstd");
+ else if (rsize == ZSTD_CONTENTSIZE_UNKNOWN)
+ internal_error ("original size unknown");
+
+ char *outbuf = (char *) xmalloc (rsize);
+ size_t const dsize = ZSTD_decompress (outbuf, rsize, cursor, size);
+
+ if (ZSTD_isError (dsize))
+ internal_error ("decompressed stream: %s", ZSTD_getErrorName (dsize));
+
+ stream->callback (outbuf, dsize, stream->opaque);
+
+ lto_destroy_compression_stream (stream);
+ free (outbuf);
+ timevar_pop (TV_IPA_LTO_DECOMPRESS);
+}
+
+#endif
+
/* Create a new compression stream, with CALLBACK flush function passed
OPAQUE token, IS_COMPRESSION indicates if compressing or uncompressing. */
@@ -132,15 +221,6 @@ lto_append_to_compression_stream (struct lto_compression_stream *stream,
stream->bytes += num_chars;
}
-/* Free the buffer and memory associated with STREAM. */
-
-static void
-lto_destroy_compression_stream (struct lto_compression_stream *stream)
-{
- free (stream->buffer);
- free (stream);
-}
-
/* Return a new compression stream, with CALLBACK flush function passed
OPAQUE token. */
@@ -163,10 +243,8 @@ lto_compress_block (struct lto_compression_stream *stream,
lto_stats.num_output_il_bytes += num_chars;
}
-/* Finalize STREAM compression, and free stream allocations. */
-
-void
-lto_end_compression (struct lto_compression_stream *stream)
+static void ATTRIBUTE_UNUSED
+lto_compression_zlib (struct lto_compression_stream *stream)
{
unsigned char *cursor = (unsigned char *) stream->buffer;
size_t remaining = stream->bytes;
@@ -226,6 +304,16 @@ lto_end_compression (struct lto_compression_stream *stream)
timevar_pop (TV_IPA_LTO_COMPRESS);
}
+void
+lto_end_compression (struct lto_compression_stream *stream)
+{
+#ifdef HAVE_ZSTD_H
+ lto_compression_zstd (stream);
+#else
+ lto_compression_zlib (stream);
+#endif
+}
+
/* Return a new uncompression stream, with CALLBACK flush function passed
OPAQUE token. */
@@ -248,14 +336,8 @@ lto_uncompress_block (struct lto_compression_stream *stream,
lto_stats.num_input_il_bytes += num_chars;
}
-/* Finalize STREAM uncompression, and free stream allocations.
-
- Because of the way LTO IL streams are compressed, there may be several
- concatenated compressed segments in the accumulated data, so for this
- function we iterate decompressions until no data remains. */
-
-void
-lto_end_uncompression (struct lto_compression_stream *stream)
+static void
+lto_uncompression_zlib (struct lto_compression_stream *stream)
{
unsigned char *cursor = (unsigned char *) stream->buffer;
size_t remaining = stream->bytes;
@@ -318,3 +400,20 @@ lto_end_uncompression (struct lto_compression_stream *stream)
free (outbuf);
timevar_pop (TV_IPA_LTO_DECOMPRESS);
}
+
+void
+lto_end_uncompression (struct lto_compression_stream *stream,
+ lto_compression compression)
+{
+#ifdef HAVE_ZSTD_H
+ if (compression == ZSTD)
+ {
+ lto_uncompression_zstd (stream);
+ return;
+ }
+#endif
+ if (compression == ZSTD)
+ internal_error ("compiler does not support ZSTD LTO compression");
+
+ lto_uncompression_zlib (stream);
+}
diff --git a/gcc/lto-compress.h b/gcc/lto-compress.h
index 87f53f7..564b17e 100644
--- a/gcc/lto-compress.h
+++ b/gcc/lto-compress.h
@@ -37,6 +37,7 @@ extern struct lto_compression_stream
void *opaque);
extern void lto_uncompress_block (struct lto_compression_stream *stream,
const char *base, size_t num_chars);
-extern void lto_end_uncompression (struct lto_compression_stream *stream);
+extern void lto_end_uncompression (struct lto_compression_stream *stream,
+ lto_compression compression);
#endif /* GCC_LTO_COMPRESS_H */
diff --git a/gcc/lto-section-in.c b/gcc/lto-section-in.c
index 4cfc0ca..80fdb03 100644
--- a/gcc/lto-section-in.c
+++ b/gcc/lto-section-in.c
@@ -52,10 +52,10 @@ const char *lto_section_name[LTO_N_SECTION_TYPES] =
"icf",
"offload_table",
"mode_table",
- "hsa"
+ "hsa",
+ "lto"
};
-
/* Hooks so that the ipa passes can call into the lto front end to get
sections. */
@@ -146,7 +146,7 @@ lto_get_section_data (struct lto_file_decl_data *file_data,
/* WPA->ltrans streams are not compressed with exception of function bodies
and variable initializers that has been verbatim copied from earlier
compilations. */
- if (!flag_ltrans || decompress)
+ if ((!flag_ltrans || decompress) && section_type != LTO_section_lto)
{
/* Create a mapping header containing the underlying data and length,
and prepend this to the uncompression buffer. The uncompressed data
@@ -161,15 +161,12 @@ lto_get_section_data (struct lto_file_decl_data *file_data,
stream = lto_start_uncompression (lto_append_data, &buffer);
lto_uncompress_block (stream, data, *len);
- lto_end_uncompression (stream);
+ lto_end_uncompression (stream, file_data->lto_section_header.compression);
*len = buffer.length - header_length;
data = buffer.data + header_length;
}
- lto_check_version (((const lto_header *)data)->major_version,
- ((const lto_header *)data)->minor_version,
- file_data->file_name);
return data;
}
diff --git a/gcc/lto-section-out.c b/gcc/lto-section-out.c
index c91e58f..7ae1021 100644
--- a/gcc/lto-section-out.c
+++ b/gcc/lto-section-out.c
@@ -285,8 +285,6 @@ lto_destroy_simple_output_block (struct lto_simple_output_block *ob)
/* Write the header which says how to decode the pieces of the
t. */
memset (&header, 0, sizeof (struct lto_simple_header));
- header.major_version = LTO_major_version;
- header.minor_version = LTO_minor_version;
header.main_size = ob->main_stream->total_size;
lto_write_data (&header, sizeof header);
diff --git a/gcc/lto-streamer-in.c b/gcc/lto-streamer-in.c
index 7727b9b..49fd573 100644
--- a/gcc/lto-streamer-in.c
+++ b/gcc/lto-streamer-in.c
@@ -1005,6 +1005,7 @@ input_struct_function_base (struct function *fn, struct data_in *data_in,
fn->has_forced_label_in_static = bp_unpack_value (&bp, 1);
fn->calls_alloca = bp_unpack_value (&bp, 1);
fn->calls_setjmp = bp_unpack_value (&bp, 1);
+ fn->calls_eh_return = bp_unpack_value (&bp, 1);
fn->has_force_vectorize_loops = bp_unpack_value (&bp, 1);
fn->has_simduid_loops = bp_unpack_value (&bp, 1);
fn->va_list_fpr_size = bp_unpack_value (&bp, 8);
@@ -1700,7 +1701,7 @@ lto_input_mode_table (struct lto_file_decl_data *file_data)
}
/* FALLTHRU */
default:
- fatal_error (UNKNOWN_LOCATION, "unsupported mode %s\n", mname);
+ fatal_error (UNKNOWN_LOCATION, "unsupported mode %qs", mname);
break;
}
}
diff --git a/gcc/lto-streamer-out.c b/gcc/lto-streamer-out.c
index b6e395b..49ca5ce 100644
--- a/gcc/lto-streamer-out.c
+++ b/gcc/lto-streamer-out.c
@@ -782,7 +782,7 @@ DFS::DFS_write_tree_body (struct output_block *ob,
/* Drop names that were created for anonymous entities. */
if (DECL_NAME (expr)
&& TREE_CODE (DECL_NAME (expr)) == IDENTIFIER_NODE
- && anon_aggrname_p (DECL_NAME (expr)))
+ && IDENTIFIER_ANON_P (DECL_NAME (expr)))
;
else
DFS_follow_tree_edge (DECL_NAME (expr));
@@ -1143,7 +1143,6 @@ hash_tree (struct streamer_tree_cache_d *cache, hash_map<tree, hashval_t> *map,
if (CODE_CONTAINS_STRUCT (code, TS_TYPE_COMMON))
{
hstate.add_hwi (TYPE_MODE (t));
- hstate.add_flag (TYPE_STRING_FLAG (t));
/* TYPE_NO_FORCE_BLK is private to stor-layout and need
no streaming. */
hstate.add_flag (TYPE_PACKED (t));
@@ -1154,9 +1153,12 @@ hash_tree (struct streamer_tree_cache_d *cache, hash_map<tree, hashval_t> *map,
{
hstate.add_flag (TYPE_TRANSPARENT_AGGR (t));
hstate.add_flag (TYPE_FINAL_P (t));
+ hstate.add_flag (TYPE_CXX_ODR_P (t));
}
else if (code == ARRAY_TYPE)
hstate.add_flag (TYPE_NONALIASED_COMPONENT (t));
+ if (code == ARRAY_TYPE || code == INTEGER_TYPE)
+ hstate.add_flag (TYPE_STRING_FLAG (t));
if (AGGREGATE_TYPE_P (t))
hstate.add_flag (TYPE_TYPELESS_STORAGE (t));
hstate.commit_flag ();
@@ -1211,7 +1213,7 @@ hash_tree (struct streamer_tree_cache_d *cache, hash_map<tree, hashval_t> *map,
/* Drop names that were created for anonymous entities. */
if (DECL_NAME (t)
&& TREE_CODE (DECL_NAME (t)) == IDENTIFIER_NODE
- && anon_aggrname_p (DECL_NAME (t)))
+ && IDENTIFIER_ANON_P (DECL_NAME (t)))
;
else
visit (DECL_NAME (t));
@@ -1972,10 +1974,6 @@ produce_asm (struct output_block *ob, tree fn)
/* The entire header is stream computed here. */
memset (&header, 0, sizeof (struct lto_function_header));
- /* Write the header. */
- header.major_version = LTO_major_version;
- header.minor_version = LTO_minor_version;
-
if (section_type == LTO_section_function_body)
header.cfg_size = ob->cfg_stream->total_size;
header.main_size = ob->main_stream->total_size;
@@ -2029,6 +2027,7 @@ output_struct_function_base (struct output_block *ob, struct function *fn)
bp_pack_value (&bp, fn->has_forced_label_in_static, 1);
bp_pack_value (&bp, fn->calls_alloca, 1);
bp_pack_value (&bp, fn->calls_setjmp, 1);
+ bp_pack_value (&bp, fn->calls_eh_return, 1);
bp_pack_value (&bp, fn->has_force_vectorize_loops, 1);
bp_pack_value (&bp, fn->has_simduid_loops, 1);
bp_pack_value (&bp, fn->va_list_fpr_size, 8);
@@ -2267,10 +2266,6 @@ lto_output_toplevel_asms (void)
/* The entire header stream is computed here. */
memset (&header, 0, sizeof (header));
- /* Write the header. */
- header.major_version = LTO_major_version;
- header.minor_version = LTO_minor_version;
-
header.main_size = ob->main_stream->total_size;
header.string_size = ob->string_stream->total_size;
lto_write_data (&header, sizeof header);
@@ -2387,6 +2382,33 @@ prune_offload_funcs (void)
DECL_PRESERVE_P (fn_decl) = 1;
}
+/* Produce LTO section that contains global information
+ about LTO bytecode. */
+
+static void
+produce_lto_section ()
+{
+ /* Stream LTO meta section. */
+ output_block *ob = create_output_block (LTO_section_lto);
+
+ char * section_name = lto_get_section_name (LTO_section_lto, NULL, NULL);
+ lto_begin_section (section_name, false);
+ free (section_name);
+
+#ifdef HAVE_ZSTD_H
+ lto_compression compression = ZSTD;
+#else
+ lto_compression compression = ZLIB;
+#endif
+
+ bool slim_object = flag_generate_lto && !flag_fat_lto_objects;
+ lto_section s
+ = { LTO_major_version, LTO_minor_version, slim_object, compression, 0 };
+ lto_write_data (&s, sizeof s);
+ lto_end_section ();
+ destroy_output_block (ob);
+}
+
/* Main entry point from the pass manager. */
void
@@ -2394,17 +2416,23 @@ lto_output (void)
{
struct lto_out_decl_state *decl_state;
bitmap output = NULL;
+ bitmap_obstack output_obstack;
int i, n_nodes;
lto_symtab_encoder_t encoder = lto_get_out_decl_state ()->symtab_node_encoder;
prune_offload_funcs ();
if (flag_checking)
- output = lto_bitmap_alloc ();
+ {
+ bitmap_obstack_initialize (&output_obstack);
+ output = BITMAP_ALLOC (&output_obstack);
+ }
/* Initialize the streamer. */
lto_streamer_init ();
+ produce_lto_section ();
+
n_nodes = lto_symtab_encoder_size (encoder);
/* Process only the functions with bodies. */
for (i = 0; i < n_nodes; i++)
@@ -2416,10 +2444,7 @@ lto_output (void)
&& !node->alias)
{
if (flag_checking)
- {
- gcc_assert (!bitmap_bit_p (output, DECL_UID (node->decl)));
- bitmap_set_bit (output, DECL_UID (node->decl));
- }
+ gcc_assert (bitmap_set_bit (output, DECL_UID (node->decl)));
decl_state = lto_new_out_decl_state ();
lto_push_out_decl_state (decl_state);
if (gimple_has_body_p (node->decl)
@@ -2449,10 +2474,7 @@ lto_output (void)
{
timevar_push (TV_IPA_LTO_CTORS_OUT);
if (flag_checking)
- {
- gcc_assert (!bitmap_bit_p (output, DECL_UID (node->decl)));
- bitmap_set_bit (output, DECL_UID (node->decl));
- }
+ gcc_assert (bitmap_set_bit (output, DECL_UID (node->decl)));
decl_state = lto_new_out_decl_state ();
lto_push_out_decl_state (decl_state);
if (DECL_INITIAL (node->decl) != error_mark_node
@@ -2477,9 +2499,11 @@ lto_output (void)
output_offload_tables ();
-#if CHECKING_P
- lto_bitmap_free (output);
-#endif
+ if (flag_checking)
+ {
+ BITMAP_FREE (output);
+ bitmap_obstack_release (&output_obstack);
+ }
}
/* Write each node in encoded by ENCODER to OB, as well as those reachable
@@ -2824,10 +2848,6 @@ lto_write_mode_table (void)
struct lto_simple_header_with_strings header;
memset (&header, 0, sizeof (header));
- /* Write the header. */
- header.major_version = LTO_major_version;
- header.minor_version = LTO_minor_version;
-
header.main_size = ob->main_stream->total_size;
header.string_size = ob->string_stream->total_size;
lto_write_data (&header, sizeof header);
@@ -2898,9 +2918,6 @@ produce_asm_for_decls (void)
lto_output_decl_state_streams (ob, fn_out_state);
}
- header.major_version = LTO_major_version;
- header.minor_version = LTO_minor_version;
-
/* Currently not used. This field would allow us to preallocate
the globals vector, so that it need not be resized as it is extended. */
header.num_nodes = -1;
diff --git a/gcc/lto-streamer.c b/gcc/lto-streamer.c
index 7852ffc..bd0126f 100644
--- a/gcc/lto-streamer.c
+++ b/gcc/lto-streamer.c
@@ -35,11 +35,6 @@ along with GCC; see the file COPYING3. If not see
/* Statistics gathered during LTO, WPA and LTRANS. */
struct lto_stats_d lto_stats;
-/* LTO uses bitmaps with different life-times. So use a separate
- obstack for all LTO bitmaps. */
-static bitmap_obstack lto_obstack;
-static bool lto_obstack_initialized;
-
const char *section_name_prefix = LTO_SECTION_NAME_PREFIX;
/* Set when streaming LTO for offloading compiler. */
bool lto_stream_offload_p;
@@ -113,28 +108,6 @@ lto_tag_name (enum LTO_tags tag)
}
-/* Allocate a bitmap from heap. Initializes the LTO obstack if necessary. */
-
-bitmap
-lto_bitmap_alloc (void)
-{
- if (!lto_obstack_initialized)
- {
- bitmap_obstack_initialize (&lto_obstack);
- lto_obstack_initialized = true;
- }
- return BITMAP_ALLOC (&lto_obstack);
-}
-
-/* Free bitmap B. */
-
-void
-lto_bitmap_free (bitmap b)
-{
- BITMAP_FREE (b);
-}
-
-
/* Get a section name for a particular type or name. The NAME field
is only used if SECTION_TYPE is LTO_section_function_body. For all
others it is ignored. The callee of this function is responsible
diff --git a/gcc/lto-streamer.h b/gcc/lto-streamer.h
index 5cd2a60..f1593d64 100644
--- a/gcc/lto-streamer.h
+++ b/gcc/lto-streamer.h
@@ -120,7 +120,7 @@ along with GCC; see the file COPYING3. If not see
String are represented in the table as pairs, a length in ULEB128
form followed by the data for the string. */
-#define LTO_major_version 8
+#define LTO_major_version 9
#define LTO_minor_version 0
typedef unsigned char lto_decl_flags_t;
@@ -234,6 +234,7 @@ enum lto_section_type
LTO_section_offload_table,
LTO_section_mode_table,
LTO_section_ipa_hsa,
+ LTO_section_lto,
LTO_N_SECTION_TYPES /* Must be last. */
};
@@ -378,18 +379,31 @@ public:
unsigned int len;
};
+/* Compression algorithm used for compression of LTO bytecode. */
-/* The is the first part of the record for a function or constructor
- in the .o file. */
-struct lto_header
+enum lto_compression
+{
+ ZLIB,
+ ZSTD
+};
+
+/* Structure that represents LTO ELF section with information
+ about the format. */
+
+struct lto_section
{
int16_t major_version;
int16_t minor_version;
+ unsigned char slim_object: 1;
+ lto_compression compression: 4;
+ int32_t reserved0: 27;
};
+STATIC_ASSERT (sizeof (lto_section) == 8);
+
/* The is the first part of the record in an LTO file for many of the
IPA passes. */
-struct lto_simple_header : lto_header
+struct lto_simple_header
{
/* Size of main gimple body of function. */
int32_t main_size;
@@ -589,6 +603,9 @@ struct GTY(()) lto_file_decl_data
/* Mode translation table. */
const unsigned char *mode_table;
+
+ /* Read LTO section. */
+ lto_section lto_section_header;
};
typedef struct lto_file_decl_data *lto_file_decl_data_ptr;
@@ -822,8 +839,6 @@ extern void lto_append_block (struct lto_output_stream *);
extern bool lto_stream_offload_p;
extern const char *lto_tag_name (enum LTO_tags);
-extern bitmap lto_bitmap_alloc (void);
-extern void lto_bitmap_free (bitmap);
extern char *lto_get_section_name (int, const char *, struct lto_file_decl_data *);
extern void print_lto_report (const char *);
extern void lto_streamer_init (void);
diff --git a/gcc/lto-wrapper.c b/gcc/lto-wrapper.c
index ac97149..9468977 100644
--- a/gcc/lto-wrapper.c
+++ b/gcc/lto-wrapper.c
@@ -155,7 +155,8 @@ get_options_from_collect_gcc_options (const char *collect_gcc,
do
{
if (argv_storage[j] == '\0')
- fatal_error (input_location, "malformed COLLECT_GCC_OPTIONS");
+ fatal_error (input_location,
+ "malformed %<COLLECT_GCC_OPTIONS%>");
else if (strncmp (&argv_storage[j], "'\\''", 4) == 0)
{
argv_storage[k++] = '\'';
@@ -310,7 +311,7 @@ merge_and_complain (struct cl_decoded_option **decoded_options,
append_option (decoded_options, decoded_options_count, foption);
else if (strcmp ((*decoded_options)[j].arg, foption->arg))
fatal_error (input_location,
- "Option %s with different values",
+ "option %s with different values",
foption->orig_option_with_args_text);
break;
@@ -394,7 +395,7 @@ merge_and_complain (struct cl_decoded_option **decoded_options,
append_option (decoded_options, decoded_options_count, foption);
else if (foption->value != (*decoded_options)[j].value)
fatal_error (input_location,
- "Option %s not used consistently in all LTO input"
+ "option %s not used consistently in all LTO input"
" files", foption->orig_option_with_args_text);
break;
@@ -822,7 +823,7 @@ compile_offload_image (const char *target, const char *compiler_path,
if (!compiler)
fatal_error (input_location,
- "could not find %s in %s (consider using %<-B%>)\n",
+ "could not find %s in %s (consider using %<-B%>)",
suffix + 1, compiler_path);
/* Generate temporary output file name. */
@@ -903,7 +904,7 @@ compile_images_for_offload_targets (unsigned in_argc, char *in_argv[],
linker_opts, linker_opt_count);
if (!offload_names[next_name_entry])
fatal_error (input_location,
- "problem with building target image for %s\n", names[i]);
+ "problem with building target image for %s", names[i]);
next_name_entry++;
}
@@ -960,7 +961,7 @@ find_crtoffloadtable (void)
}
if (i == n_paths)
fatal_error (input_location,
- "installation error, can%'t find crtoffloadtable.o");
+ "installation error, cannot find %<crtoffloadtable.o%>");
free_array_of_ptrs ((void **) paths, n_paths);
}
@@ -1072,7 +1073,7 @@ debug_objcopy (const char *infile, bool rename)
&off, &len, &errmsg, &err) != 1)
{
if (errmsg)
- fatal_error (0, "%s: %s\n", errmsg, xstrerror (err));
+ fatal_error (0, "%s: %s", errmsg, xstrerror (err));
simple_object_release_read (inobj);
close (infd);
@@ -1092,7 +1093,7 @@ debug_objcopy (const char *infile, bool rename)
if (errmsg)
{
unlink_if_ordinary (outfile);
- fatal_error (0, "%s: %s\n", errmsg, xstrerror (err));
+ fatal_error (0, "%s: %s", errmsg, xstrerror (err));
}
simple_object_release_read (inobj);
@@ -1144,11 +1145,11 @@ run_gcc (unsigned argc, char *argv[])
collect_gcc = getenv ("COLLECT_GCC");
if (!collect_gcc)
fatal_error (input_location,
- "environment variable COLLECT_GCC must be set");
+ "environment variable %<COLLECT_GCC%> must be set");
collect_gcc_options = getenv ("COLLECT_GCC_OPTIONS");
if (!collect_gcc_options)
fatal_error (input_location,
- "environment variable COLLECT_GCC_OPTIONS must be set");
+ "environment variable %<COLLECT_GCC_OPTIONS%> must be set");
get_options_from_collect_gcc_options (collect_gcc, collect_gcc_options,
CL_LANG_ALL,
&decoded_options,
@@ -1548,7 +1549,7 @@ cont1:
int priority;
if (!stream)
- fatal_error (input_location, "fopen: %s: %m", ltrans_output_file);
+ fatal_error (input_location, "%<fopen%>: %s: %m", ltrans_output_file);
/* Parse the list of LTRANS inputs from the WPA stage. */
obstack_init (&env_obstack);
@@ -1565,7 +1566,7 @@ cont1:
{
if (!feof (stream))
fatal_error (input_location,
- "Corrupted ltrans output file %s",
+ "corrupted ltrans output file %s",
ltrans_output_file);
break;
}
@@ -1754,7 +1755,7 @@ main (int argc, char *argv[])
diagnostic_initialize (global_dc, 0);
if (atexit (lto_wrapper_cleanup) != 0)
- fatal_error (input_location, "atexit failed");
+ fatal_error (input_location, "%<atexit%> failed");
if (signal (SIGINT, SIG_IGN) != SIG_IGN)
signal (SIGINT, fatal_signal);
diff --git a/gcc/lto/ChangeLog b/gcc/lto/ChangeLog
index 942b4b5..23ad84e 100644
--- a/gcc/lto/ChangeLog
+++ b/gcc/lto/ChangeLog
@@ -1,3 +1,50 @@
+2019-07-03 Martin Liska <mliska@suse.cz>
+
+ * lto-common.c: Read LTO section and verify header.
+
+2019-06-27 Jan Hubicka <jh@suse.cz>
+
+ * lto-common.c (lto_register_canonical_types_for_odr_types):
+ Copy CXX_ODR_P from the main variant.
+
+2019-06-27 Jan Hubicka <jh@suse.cz>
+
+ * lto-common.c: tree-pretty-print.h
+ (type_streaming_finished): New static var.
+ (gimple_register_canonical_type_1): Return updated hash; handle ODR
+ types.
+ (iterative_hash_canonical_type): Update use of
+ gimple_register_canonical_type_1.
+
+2019-06-27 Martin Liska <mliska@suse.cz>
+
+ * lto-dump.c (struct symbol_entry): Add default dtor.
+ (struct variable_entry): Likewise.
+ (struct function_entry): Likewise.
+ (dump_list_functions): Release memory.
+ (dump_list_variables): Likewise.
+
+2019-06-24 Jan Hubicka <jh@suse.cz>
+
+ * lto-common.c (compare_tree_sccs_1): Compare CXX_ODR_P;
+ compare STRING_FLAG only for arrays and integers.
+
+2019-06-05 Martin Sebor <msebor@redhat.com>
+
+ * lto-common.c (lto_file_finalize): Adjust quoting and hyphenation.
+
+2019-05-16 Martin Sebor <msebor@redhat.com>
+
+ * lto-dump.c (lto_main): Same.
+ * lto.c (stream_out): Same.
+
+2019-05-10 Martin Liska <mliska@suse.cz>
+
+ * Make-lang.in: Use program_transform_name for lto-dump.
+ * config-lang.in: Do not mark lto-dump compiler as we don't
+ want to have it installed at
+ lib/gcc/x86_64-pc-linux-gnu/10.0.0/lto-dump.
+
2019-05-07 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE>
* lto-common.c (lto_file_read): Print section->start as int64_t,
diff --git a/gcc/lto/Make-lang.in b/gcc/lto/Make-lang.in
index 92487e1..afcfc98 100644
--- a/gcc/lto/Make-lang.in
+++ b/gcc/lto/Make-lang.in
@@ -22,6 +22,7 @@
# The name of the LTO compiler.
LTO_EXE = lto1$(exeext)
LTO_DUMP_EXE = lto-dump$(exeext)
+LTO_DUMP_INSTALL_NAME := $(shell echo lto-dump|sed '$(program_transform_name)')
# The LTO-specific object files inclued in $(LTO_EXE).
LTO_OBJS = lto/lto-lang.o lto/lto.o lto/lto-object.o attribs.o lto/lto-partition.o lto/lto-symtab.o lto/lto-common.o
lto_OBJS = $(LTO_OBJS)
@@ -48,7 +49,7 @@ lto.rest.encap:
lto.tags:
lto.install-common: installdirs
$(INSTALL_PROGRAM) $(LTO_DUMP_EXE) \
- $(DESTDIR)/$(bindir)/$(LTO_DUMP_EXE)
+ $(DESTDIR)/$(bindir)/$(LTO_DUMP_INSTALL_NAME)$(exeext)
lto.install-man:
lto.install-info:
diff --git a/gcc/lto/config-lang.in b/gcc/lto/config-lang.in
index 37c8f6e..c7aa41f 100644
--- a/gcc/lto/config-lang.in
+++ b/gcc/lto/config-lang.in
@@ -18,7 +18,7 @@
# <http://www.gnu.org/licenses/>.
language="lto"
-compilers="lto1\$(exeext) lto-dump\$(exeext)"
+compilers="lto1\$(exeext)"
gtfiles="\$(srcdir)/lto/lto-tree.h \$(srcdir)/lto/lto-lang.c \$(srcdir)/lto/lto.c \$(srcdir)/lto/lto.h \$(srcdir)/lto/lto-common.h \$(srcdir)/lto/lto-common.c \$(srcdir)/lto/lto-dump.c"
diff --git a/gcc/lto/lto-common.c b/gcc/lto/lto-common.c
index 078075c..bc8c2b4 100644
--- a/gcc/lto/lto-common.c
+++ b/gcc/lto/lto-common.c
@@ -1,5 +1,5 @@
/* Top-level LTO routines.
- Copyright (C) 2009-2018 Free Software Foundation, Inc.
+ Copyright (C) 2009-2019 Free Software Foundation, Inc.
Contributed by CodeSourcery, Inc.
This file is part of GCC.
@@ -56,6 +56,11 @@ along with GCC; see the file COPYING3. If not see
#include "attribs.h"
#include "builtins.h"
#include "lto-common.h"
+#include "tree-pretty-print.h"
+
+/* True when no new types are going to be streamd from the global stream. */
+
+static bool type_streaming_finished = false;
GTY(()) tree first_personality_decl;
@@ -217,9 +222,14 @@ static hash_map<const_tree, hashval_t> *canonical_type_hash_cache;
static unsigned long num_canonical_type_hash_entries;
static unsigned long num_canonical_type_hash_queries;
+/* Types postponed for registration to the canonical type table.
+ During streaming we postpone all TYPE_CXX_ODR_P types so we can alter
+ decide whether there is conflict with non-ODR type or not. */
+static GTY(()) vec<tree, va_gc> *types_to_register = NULL;
+
static void iterative_hash_canonical_type (tree type, inchash::hash &hstate);
static hashval_t gimple_canonical_type_hash (const void *p);
-static void gimple_register_canonical_type_1 (tree t, hashval_t hash);
+static hashval_t gimple_register_canonical_type_1 (tree t, hashval_t hash);
/* Returning a hash value for gimple type TYPE.
@@ -357,9 +367,9 @@ iterative_hash_canonical_type (tree type, inchash::hash &hstate)
optimal order. To avoid quadratic behavior also register the
type here. */
v = hash_canonical_type (type);
- gimple_register_canonical_type_1 (type, v);
+ v = gimple_register_canonical_type_1 (type, v);
}
- hstate.add_int (v);
+ hstate.merge_hash (v);
}
/* Returns the hash for a canonical type P. */
@@ -388,7 +398,7 @@ gimple_canonical_type_eq (const void *p1, const void *p2)
/* Main worker for gimple_register_canonical_type. */
-static void
+static hashval_t
gimple_register_canonical_type_1 (tree t, hashval_t hash)
{
void **slot;
@@ -397,6 +407,75 @@ gimple_register_canonical_type_1 (tree t, hashval_t hash)
&& type_with_alias_set_p (t)
&& canonical_type_used_p (t));
+ /* ODR types for which there is no ODR violation and we did not record
+ structurally equivalent non-ODR type can be treated as unique by their
+ name.
+
+ hash passed to gimple_register_canonical_type_1 is a structural hash
+ that we can use to lookup structurally equivalent non-ODR type.
+ In case we decide to treat type as unique ODR type we recompute hash based
+ on name and let TBAA machinery know about our decision. */
+ if (RECORD_OR_UNION_TYPE_P (t)
+ && odr_type_p (t) && !odr_type_violation_reported_p (t))
+ {
+ /* Here we rely on fact that all non-ODR types was inserted into
+ canonical type hash and thus we can safely detect conflicts between
+ ODR types and interoperable non-ODR types. */
+ gcc_checking_assert (type_streaming_finished
+ && TYPE_MAIN_VARIANT (t) == t);
+ slot = htab_find_slot_with_hash (gimple_canonical_types, t, hash,
+ NO_INSERT);
+ if (slot && !TYPE_CXX_ODR_P (*(tree *)slot))
+ {
+ tree nonodr = *(tree *)slot;
+ if (symtab->dump_file)
+ {
+ fprintf (symtab->dump_file,
+ "ODR and non-ODR type conflict: ");
+ print_generic_expr (symtab->dump_file, t);
+ fprintf (symtab->dump_file, " and ");
+ print_generic_expr (symtab->dump_file, nonodr);
+ fprintf (symtab->dump_file, " mangled:%s\n",
+ IDENTIFIER_POINTER
+ (DECL_ASSEMBLER_NAME (TYPE_NAME (t))));
+ }
+ /* Set canonical for T and all other ODR equivalent duplicates
+ including incomplete structures. */
+ set_type_canonical_for_odr_type (t, nonodr);
+ }
+ else
+ {
+ tree prevail = prevailing_odr_type (t);
+
+ if (symtab->dump_file)
+ {
+ fprintf (symtab->dump_file,
+ "New canonical ODR type: ");
+ print_generic_expr (symtab->dump_file, t);
+ fprintf (symtab->dump_file, " mangled:%s\n",
+ IDENTIFIER_POINTER
+ (DECL_ASSEMBLER_NAME (TYPE_NAME (t))));
+ }
+ /* Set canonical for T and all other ODR equivalent duplicates
+ including incomplete structures. */
+ set_type_canonical_for_odr_type (t, prevail);
+ enable_odr_based_tbaa (t);
+ if (!type_in_anonymous_namespace_p (t))
+ hash = htab_hash_string (IDENTIFIER_POINTER
+ (DECL_ASSEMBLER_NAME
+ (TYPE_NAME (t))));
+ else
+ hash = TYPE_UID (t);
+
+ /* All variants of t now have TYPE_CANONICAL set to prevail.
+ Update canonical type hash cache accordingly. */
+ num_canonical_type_hash_entries++;
+ bool existed_p = canonical_type_hash_cache->put (prevail, hash);
+ gcc_checking_assert (!existed_p);
+ }
+ return hash;
+ }
+
slot = htab_find_slot_with_hash (gimple_canonical_types, t, hash, INSERT);
if (*slot)
{
@@ -413,6 +492,7 @@ gimple_register_canonical_type_1 (tree t, hashval_t hash)
bool existed_p = canonical_type_hash_cache->put (t, hash);
gcc_assert (!existed_p);
}
+ return hash;
}
/* Register type T in the global type table gimple_types and set
@@ -464,6 +544,43 @@ lto_register_canonical_types (tree node, bool first_p)
gimple_register_canonical_type (node);
}
+/* Finish canonical type calculation: after all units has been streamed in we
+ can check if given ODR type structurally conflicts with a non-ODR type. In
+ the first case we set type canonical according to the canonical type hash.
+ In the second case we use type names. */
+
+static void
+lto_register_canonical_types_for_odr_types ()
+{
+ tree t;
+ unsigned int i;
+
+ if (!types_to_register)
+ return;
+
+ type_streaming_finished = true;
+
+ /* Be sure that no types derived from ODR types was
+ not inserted into the hash table. */
+ if (flag_checking)
+ FOR_EACH_VEC_ELT (*types_to_register, i, t)
+ gcc_assert (!TYPE_CANONICAL (t));
+
+ /* Register all remaining types. */
+ FOR_EACH_VEC_ELT (*types_to_register, i, t)
+ {
+ /* For pre-streamed types like va-arg it is possible that main variant
+ is !CXX_ODR_P while the variant (which is streamed) is.
+ Copy CXX_ODR_P to make type verifier happy. This is safe because
+ in canonical type calculation we only consider main variants.
+ However we can not change this flag before streaming is finished
+ to not affect tree merging. */
+ TYPE_CXX_ODR_P (t) = TYPE_CXX_ODR_P (TYPE_MAIN_VARIANT (t));
+ if (!TYPE_CANONICAL (t))
+ gimple_register_canonical_type (t);
+ }
+}
+
/* Remember trees that contains references to declarations. */
vec <tree, va_gc> *tree_with_vars;
@@ -1124,15 +1241,17 @@ compare_tree_sccs_1 (tree t1, tree t2, tree **map)
if (CODE_CONTAINS_STRUCT (code, TS_TYPE_COMMON))
{
compare_values (TYPE_MODE);
- compare_values (TYPE_STRING_FLAG);
compare_values (TYPE_NEEDS_CONSTRUCTING);
if (RECORD_OR_UNION_TYPE_P (t1))
{
compare_values (TYPE_TRANSPARENT_AGGR);
compare_values (TYPE_FINAL_P);
+ compare_values (TYPE_CXX_ODR_P);
}
else if (code == ARRAY_TYPE)
compare_values (TYPE_NONALIASED_COMPONENT);
+ if (code == ARRAY_TYPE || code == INTEGER_TYPE)
+ compare_values (TYPE_STRING_FLAG);
if (AGGREGATE_TYPE_P (t1))
compare_values (TYPE_TYPELESS_STORAGE);
compare_values (TYPE_EMPTY_P);
@@ -1655,6 +1774,7 @@ unify_scc (struct data_in *data_in, unsigned from,
}
+
/* Read all the symbols from buffer DATA, using descriptors in DECL_DATA.
RESOLUTIONS is the set of symbols picked by the linker (read from the
resolution file when the linker plugin is being used). */
@@ -1747,12 +1867,23 @@ lto_read_decls (struct lto_file_decl_data *decl_data, const void *data,
num_prevailing_types++;
lto_fixup_prevailing_type (t);
- /* Compute the canonical type of all types.
+ /* Compute the canonical type of all non-ODR types.
+ Delay ODR types for the end of merging process - the canonical
+ type for those can be computed using the (unique) name however
+ we want to do this only if units in other languages do not
+ contain structurally equivalent type.
+
Because SCC components are streamed in random (hash) order
we may have encountered the type before while registering
type canonical of a derived type in the same SCC. */
if (!TYPE_CANONICAL (t))
- gimple_register_canonical_type (t);
+ {
+ if (!RECORD_OR_UNION_TYPE_P (t)
+ || !TYPE_CXX_ODR_P (t))
+ gimple_register_canonical_type (t);
+ else if (COMPLETE_TYPE_P (t))
+ vec_safe_push (types_to_register, t);
+ }
if (TYPE_MAIN_VARIANT (t) == t && odr_type_p (t))
register_odr_type (t);
}
@@ -2058,10 +2189,26 @@ lto_file_finalize (struct lto_file_decl_data *file_data, lto_file *file)
#else
file_data->mode_table = lto_mode_identity_table;
#endif
+
+ /* Read and verify LTO section. */
+ data = lto_get_section_data (file_data, LTO_section_lto, NULL, &len, false);
+ if (data == NULL)
+ {
+ fatal_error (input_location, "bytecode stream in file %qs generated "
+ "with GCC compiler older than 10.0", file_data->file_name);
+ return;
+ }
+
+ file_data->lto_section_header = *(const lto_section *)data;
+ lto_check_version (file_data->lto_section_header.major_version,
+ file_data->lto_section_header.minor_version,
+ file_data->file_name);
+
data = lto_get_section_data (file_data, LTO_section_decls, NULL, &len);
if (data == NULL)
{
- internal_error ("cannot read LTO decls from %s", file_data->file_name);
+ internal_error ("cannot read %<LTO_section_decls%> from %s",
+ file_data->file_name);
return;
}
/* Frees resolutions. */
@@ -2602,6 +2749,8 @@ read_cgraph_and_symbols (unsigned nfiles, const char **fnames)
ggc_free(decl_data);
real_file_decl_data = NULL;
+ lto_register_canonical_types_for_odr_types ();
+
if (resolution_file_name)
fclose (resolution);
diff --git a/gcc/lto/lto-dump.c b/gcc/lto/lto-dump.c
index 39b4423..e9de33c 100644
--- a/gcc/lto/lto-dump.c
+++ b/gcc/lto/lto-dump.c
@@ -44,6 +44,9 @@ struct symbol_entry
symbol_entry (symtab_node *node_): node (node_)
{}
+ virtual ~symbol_entry ()
+ {}
+
char* get_name () const
{
if (flag_lto_dump_demangle)
@@ -72,6 +75,9 @@ struct variable_entry: public symbol_entry
variable_entry (varpool_node *node_): symbol_entry (node_)
{}
+ virtual ~variable_entry ()
+ {}
+
virtual size_t get_size () const
{
varpool_node *vnode = dyn_cast<varpool_node *> (node);
@@ -99,6 +105,9 @@ struct function_entry: public symbol_entry
function_entry (cgraph_node *node_): symbol_entry (node_)
{}
+ virtual ~function_entry ()
+ {}
+
virtual void dump ()
{
symbol_entry :: dump ();
@@ -166,7 +175,10 @@ void dump_list_functions (void)
int i=0;
symbol_entry* e;
FOR_EACH_VEC_ELT (v, i, e)
- e->dump ();
+ {
+ e->dump ();
+ delete e;
+ }
}
/* Dump list of variables and their details. */
@@ -194,7 +206,10 @@ void dump_list_variables (void)
int i=0;
symbol_entry* e;
FOR_EACH_VEC_ELT (v, i, e)
- e->dump ();
+ {
+ e->dump ();
+ delete e;
+ }
}
/* Dump symbol list. */
@@ -320,7 +335,8 @@ lto_main (void)
node->get_untransformed_body ();
if (!GATHER_STATISTICS)
warning_at (input_location, 0,
- "Not configured with --enable-gather-detailed-mem-stats.");
+ "Not configured with "
+ "%<--enable-gather-detailed-mem-stats%>.");
else
dump_gimple_statistics ();
}
@@ -329,7 +345,8 @@ lto_main (void)
/* Dump tree statistics. */
if (!GATHER_STATISTICS)
warning_at (input_location, 0,
- "Not configured with --enable-gather-detailed-mem-stats.");
+ "Not configured with "
+ "%<--enable-gather-detailed-mem-stats%>.");
else
{
printf ("Tree Statistics\n");
diff --git a/gcc/lto/lto-lang.c b/gcc/lto/lto-lang.c
index e155ea3..cc44afc 100644
--- a/gcc/lto/lto-lang.c
+++ b/gcc/lto/lto-lang.c
@@ -1259,10 +1259,12 @@ lto_build_c_type_nodes (void)
for (i = 0; i < NUM_INT_N_ENTS; i++)
if (int_n_enabled_p[i])
{
- char name[50];
+ char name[50], altname[50];
sprintf (name, "__int%d unsigned", int_n_data[i].bitsize);
+ sprintf (altname, "__int%d__ unsigned", int_n_data[i].bitsize);
- if (strcmp (name, SIZE_TYPE) == 0)
+ if (strcmp (name, SIZE_TYPE) == 0
+ || strcmp (altname, SIZE_TYPE) == 0)
{
intmax_type_node = int_n_trees[i].signed_type;
uintmax_type_node = int_n_trees[i].unsigned_type;
diff --git a/gcc/lto/lto.c b/gcc/lto/lto.c
index bf79020..814f03a 100644
--- a/gcc/lto/lto.c
+++ b/gcc/lto/lto.c
@@ -159,7 +159,7 @@ stream_out (char *temp_filename, lto_symtab_encoder_t encoder, int part)
{
lto_file *file = lto_obj_file_open (temp_filename, true);
if (!file)
- fatal_error (input_location, "lto_obj_file_open() failed");
+ fatal_error (input_location, "%<lto_obj_file_open()%> failed");
lto_set_current_out_file (file);
gcc_assert (!dump_file);
diff --git a/gcc/match.pd b/gcc/match.pd
index 29c94e0..4a7aa01 100644
--- a/gcc/match.pd
+++ b/gcc/match.pd
@@ -217,6 +217,14 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
|| !COMPLEX_FLOAT_TYPE_P (type)))
(negate @0)))
+/* Transform { 0 or 1 } * { 0 or 1 } into { 0 or 1 } & { 0 or 1 } */
+(simplify
+ (mult SSA_NAME@1 SSA_NAME@2)
+ (if (INTEGRAL_TYPE_P (type)
+ && get_nonzero_bits (@1) == 1
+ && get_nonzero_bits (@2) == 1)
+ (bit_and @1 @2)))
+
/* Transform x * { 0 or 1, 0 or 1, ... } into x & { 0 or -1, 0 or -1, ...},
unless the target has native support for the former but not the latter. */
(simplify
@@ -1495,9 +1503,26 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
/* X / 4 < Y / 4 iff X < Y when the division is known to be exact. */
(for cmp (simple_comparison)
(simplify
- (cmp (exact_div @0 INTEGER_CST@2) (exact_div @1 @2))
- (if (wi::gt_p (wi::to_wide (@2), 0, TYPE_SIGN (TREE_TYPE (@2))))
- (cmp @0 @1))))
+ (cmp (convert?@3 (exact_div @0 INTEGER_CST@2)) (convert? (exact_div @1 @2)))
+ (if (element_precision (@3) >= element_precision (@0)
+ && types_match (@0, @1))
+ (if (wi::lt_p (wi::to_wide (@2), 0, TYPE_SIGN (TREE_TYPE (@2))))
+ (if (!TYPE_UNSIGNED (TREE_TYPE (@3)))
+ (cmp @1 @0)
+ (if (tree_expr_nonzero_p (@0) && tree_expr_nonzero_p (@1))
+ (with
+ {
+ tree utype = unsigned_type_for (TREE_TYPE (@0));
+ }
+ (cmp (convert:utype @1) (convert:utype @0)))))
+ (if (wi::gt_p (wi::to_wide (@2), 1, TYPE_SIGN (TREE_TYPE (@2))))
+ (if (TYPE_UNSIGNED (TREE_TYPE (@0)) || !TYPE_UNSIGNED (TREE_TYPE (@3)))
+ (cmp @0 @1)
+ (with
+ {
+ tree utype = unsigned_type_for (TREE_TYPE (@0));
+ }
+ (cmp (convert:utype @0) (convert:utype @1)))))))))
/* X / C1 op C2 into a simple range test. */
(for cmp (simple_comparison)
@@ -2918,6 +2943,21 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
(if (integer_zerop (@0))
@2)))
+/* Sink unary operations to constant branches, but only if we do fold it to
+ constants. */
+(for op (negate bit_not abs absu)
+ (simplify
+ (op (vec_cond @0 VECTOR_CST@1 VECTOR_CST@2))
+ (with
+ {
+ tree cst1, cst2;
+ cst1 = const_unop (op, type, @1);
+ if (cst1)
+ cst2 = const_unop (op, type, @2);
+ }
+ (if (cst1 && cst2)
+ (vec_cond @0 { cst1; } { cst2; })))))
+
/* Simplification moved from fold_cond_expr_with_comparison. It may also
be extended. */
/* This pattern implements two kinds simplification:
@@ -3633,6 +3673,33 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
!= (cmp == LT_EXPR || cmp == LE_EXPR), type); }
(cmp @0 { wide_int_to_tree (TREE_TYPE (@0), prod); }))))))
+/* Fold (size_t)(A /[ex] B) CMP C to (size_t)A CMP (size_t)B * C or A CMP' 0.
+
+ For small C (less than max/B), this is (size_t)A CMP (size_t)B * C.
+ For large C (more than min/B+2^size), this is also true, with the
+ multiplication computed modulo 2^size.
+ For intermediate C, this just tests the sign of A. */
+(for cmp (lt le gt ge)
+ cmp2 (ge ge lt lt)
+ (simplify
+ (cmp (convert (exact_div @0 INTEGER_CST@1)) INTEGER_CST@2)
+ (if (tree_nop_conversion_p (TREE_TYPE (@0), TREE_TYPE (@2))
+ && TYPE_UNSIGNED (TREE_TYPE (@2)) && !TYPE_UNSIGNED (TREE_TYPE (@0))
+ && wi::gt_p (wi::to_wide (@1), 0, TYPE_SIGN (TREE_TYPE (@1))))
+ (with
+ {
+ tree utype = TREE_TYPE (@2);
+ wide_int denom = wi::to_wide (@1);
+ wide_int right = wi::to_wide (@2);
+ wide_int smax = wi::sdiv_trunc (wi::max_value (TREE_TYPE (@0)), denom);
+ wide_int smin = wi::sdiv_trunc (wi::min_value (TREE_TYPE (@0)), denom);
+ bool small = wi::leu_p (right, smax);
+ bool large = wi::geu_p (right, smin);
+ }
+ (if (small || large)
+ (cmp (convert:utype @0) (mult @2 (convert @1)))
+ (cmp2 @0 { build_zero_cst (TREE_TYPE (@0)); }))))))
+
/* Unordered tests if either argument is a NaN. */
(simplify
(bit_ior (unordered @0 @0) (unordered @1 @1))
@@ -5374,3 +5441,130 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
(bit_and:elt_type
(BIT_FIELD_REF:elt_type @0 { size; } { pos; })
{ elt; })))))))
+
+(simplify
+ (vec_perm @0 @1 VECTOR_CST@2)
+ (with
+ {
+ tree op0 = @0, op1 = @1, op2 = @2;
+
+ /* Build a vector of integers from the tree mask. */
+ vec_perm_builder builder;
+ if (!tree_to_vec_perm_builder (&builder, op2))
+ return NULL_TREE;
+
+ /* Create a vec_perm_indices for the integer vector. */
+ poly_uint64 nelts = TYPE_VECTOR_SUBPARTS (type);
+ bool single_arg = (op0 == op1);
+ vec_perm_indices sel (builder, single_arg ? 1 : 2, nelts);
+ }
+ (if (sel.series_p (0, 1, 0, 1))
+ { op0; }
+ (if (sel.series_p (0, 1, nelts, 1))
+ { op1; }
+ (with
+ {
+ if (!single_arg)
+ {
+ if (sel.all_from_input_p (0))
+ op1 = op0;
+ else if (sel.all_from_input_p (1))
+ {
+ op0 = op1;
+ sel.rotate_inputs (1);
+ }
+ else if (known_ge (poly_uint64 (sel[0]), nelts))
+ {
+ std::swap (op0, op1);
+ sel.rotate_inputs (1);
+ }
+ }
+ gassign *def;
+ tree cop0 = op0, cop1 = op1;
+ if (TREE_CODE (op0) == SSA_NAME
+ && (def = dyn_cast <gassign *> (SSA_NAME_DEF_STMT (op0)))
+ && gimple_assign_rhs_code (def) == CONSTRUCTOR)
+ cop0 = gimple_assign_rhs1 (def);
+ if (TREE_CODE (op1) == SSA_NAME
+ && (def = dyn_cast <gassign *> (SSA_NAME_DEF_STMT (op1)))
+ && gimple_assign_rhs_code (def) == CONSTRUCTOR)
+ cop1 = gimple_assign_rhs1 (def);
+
+ tree t;
+ }
+ (if ((TREE_CODE (cop0) == VECTOR_CST
+ || TREE_CODE (cop0) == CONSTRUCTOR)
+ && (TREE_CODE (cop1) == VECTOR_CST
+ || TREE_CODE (cop1) == CONSTRUCTOR)
+ && (t = fold_vec_perm (type, cop0, cop1, sel)))
+ { t; }
+ (with
+ {
+ bool changed = (op0 == op1 && !single_arg);
+ tree ins = NULL_TREE;
+ unsigned at = 0;
+
+ /* See if the permutation is performing a single element
+ insert from a CONSTRUCTOR or constant and use a BIT_INSERT_EXPR
+ in that case. But only if the vector mode is supported,
+ otherwise this is invalid GIMPLE. */
+ if (TYPE_MODE (type) != BLKmode
+ && (TREE_CODE (cop0) == VECTOR_CST
+ || TREE_CODE (cop0) == CONSTRUCTOR
+ || TREE_CODE (cop1) == VECTOR_CST
+ || TREE_CODE (cop1) == CONSTRUCTOR))
+ {
+ if (sel.series_p (1, 1, nelts + 1, 1))
+ {
+ /* After canonicalizing the first elt to come from the
+ first vector we only can insert the first elt from
+ the first vector. */
+ at = 0;
+ if ((ins = fold_read_from_vector (cop0, sel[0])))
+ op0 = op1;
+ }
+ else
+ {
+ unsigned int encoded_nelts = sel.encoding ().encoded_nelts ();
+ for (at = 0; at < encoded_nelts; ++at)
+ if (maybe_ne (sel[at], at))
+ break;
+ if (at < encoded_nelts && sel.series_p (at + 1, 1, at + 1, 1))
+ {
+ if (known_lt (at, nelts))
+ ins = fold_read_from_vector (cop0, sel[at]);
+ else
+ ins = fold_read_from_vector (cop1, sel[at] - nelts);
+ }
+ }
+ }
+
+ /* Generate a canonical form of the selector. */
+ if (!ins && sel.encoding () != builder)
+ {
+ /* Some targets are deficient and fail to expand a single
+ argument permutation while still allowing an equivalent
+ 2-argument version. */
+ tree oldop2 = op2;
+ if (sel.ninputs () == 2
+ || can_vec_perm_const_p (TYPE_MODE (type), sel, false))
+ op2 = vec_perm_indices_to_tree (TREE_TYPE (op2), sel);
+ else
+ {
+ vec_perm_indices sel2 (builder, 2, nelts);
+ if (can_vec_perm_const_p (TYPE_MODE (type), sel2, false))
+ op2 = vec_perm_indices_to_tree (TREE_TYPE (op2), sel2);
+ else
+ /* Not directly supported with either encoding,
+ so use the preferred form. */
+ op2 = vec_perm_indices_to_tree (TREE_TYPE (op2), sel);
+ }
+ if (!operand_equal_p (op2, oldop2, 0))
+ changed = true;
+ }
+ }
+ (if (ins)
+ (bit_insert { op0; } { ins; }
+ { bitsize_int (at * tree_to_uhwi (TYPE_SIZE (TREE_TYPE (type)))); })
+ (if (changed)
+ (vec_perm { op0; } { op1; } { op2; }))))))))))
diff --git a/gcc/mem-stats.h b/gcc/mem-stats.h
index 63ce871..7796059 100644
--- a/gcc/mem-stats.h
+++ b/gcc/mem-stats.h
@@ -559,9 +559,9 @@ template <class T>
inline
mem_alloc_description<T>::mem_alloc_description ()
{
- m_map = new mem_map_t (13, false, false);
- m_reverse_map = new reverse_mem_map_t (13, false, false);
- m_reverse_object_map = new reverse_object_map_t (13, false, false);
+ m_map = new mem_map_t (13, false, false, false);
+ m_reverse_map = new reverse_mem_map_t (13, false, false, false);
+ m_reverse_object_map = new reverse_object_map_t (13, false, false, false);
}
/* Default destructor. */
diff --git a/gcc/multiple_target.c b/gcc/multiple_target.c
index 0a87241..7aea684 100644
--- a/gcc/multiple_target.c
+++ b/gcc/multiple_target.c
@@ -158,7 +158,8 @@ create_dispatcher_calls (struct cgraph_node *node)
{
symtab_node *source = ref->referring;
source->create_reference (inode, IPA_REF_ALIAS);
- source->add_to_same_comdat_group (inode);
+ if (inode->get_comdat_group ())
+ source->add_to_same_comdat_group (inode);
}
else
gcc_unreachable ();
@@ -356,7 +357,7 @@ expand_target_clones (struct cgraph_node *node, bool definition)
}
if (node->definition
- && !tree_versionable_function_p (node->decl))
+ && (node->alias || !tree_versionable_function_p (node->decl)))
{
auto_diagnostic_group d;
error_at (DECL_SOURCE_LOCATION (node->decl),
@@ -365,6 +366,9 @@ expand_target_clones (struct cgraph_node *node, bool definition)
if (lookup_attribute ("noclone", DECL_ATTRIBUTES (node->decl)))
reason = G_("function %q+F can never be copied "
"because it has %<noclone%> attribute");
+ else if (node->alias)
+ reason
+ = "%<target_clones%> cannot be combined with %<alias%> attribute";
else
reason = copy_forbidden (DECL_STRUCT_FUNCTION (node->decl));
if (reason)
diff --git a/gcc/objc/ChangeLog b/gcc/objc/ChangeLog
index 04eb3fe9..d001a50 100644
--- a/gcc/objc/ChangeLog
+++ b/gcc/objc/ChangeLog
@@ -1,3 +1,33 @@
+2019-06-05 Martin Sebor <msebor@redhat.com>
+
+ * objc-act.c (objc_build_setter_call): Adjust quoting and hyphenation.
+ * objc-encoding.c (encode_gnu_bitfield): Same.
+
+2019-05-18 Iain Sandoe <iain@sandoe.co.uk>
+
+ * objc/objc-act.h (OCTI_INSTANCE_TYPE, OCTI_INSTANCETYPE_NAME): New.
+ (objc_global_trees): Add instance type and name.
+ (INSTANCE_TYPEDEF_NAME): New.
+ * objc/objc-act.c (synth_module_prologue): Build decls for
+ objc_instancetype_type and objc_instancetype_name.
+
+2019-05-16 Martin Sebor <msebor@redhat.com>
+
+ * objc-act.c (objc_begin_catch_clause): Quote keywords and options
+ in diagnostics.
+ (objc_build_throw_stmt): Same.
+ (objc_finish_message_expr): Same.
+ (get_super_receiver): Same.
+ * objc-next-runtime-abi-01.c (objc_next_runtime_abi_01_init): Spell
+ out "less than" in English./
+ * objc-next-runtime-abi-02.c (objc_next_runtime_abi_02_init): Spell
+ out "greater" in English.
+
+2019-05-10 Jakub Jelinek <jakub@redhat.com>
+
+ PR pch/90326
+ * config-lang.in (gtfiles): Add c-family/c-format.c.
+
2019-04-05 Martin Liska <mliska@suse.cz>
PR translation/89936
diff --git a/gcc/objc/config-lang.in b/gcc/objc/config-lang.in
index a982049..bb37219 100644
--- a/gcc/objc/config-lang.in
+++ b/gcc/objc/config-lang.in
@@ -35,4 +35,4 @@ lang_requires="c"
# Order is important. If you change this list, make sure you test
# building without C++ as well; that is, remove the gcc/cp directory,
# and build with --enable-languages=c,objc.
-gtfiles="\$(srcdir)/objc/objc-map.h \$(srcdir)/c-family/c-objc.h \$(srcdir)/objc/objc-act.h \$(srcdir)/objc/objc-act.c \$(srcdir)/objc/objc-runtime-shared-support.c \$(srcdir)/objc/objc-gnu-runtime-abi-01.c \$(srcdir)/objc/objc-next-runtime-abi-01.c \$(srcdir)/objc/objc-next-runtime-abi-02.c \$(srcdir)/c/c-parser.h \$(srcdir)/c/c-parser.c \$(srcdir)/c/c-tree.h \$(srcdir)/c/c-decl.c \$(srcdir)/c/c-lang.h \$(srcdir)/c/c-objc-common.c \$(srcdir)/c-family/c-common.c \$(srcdir)/c-family/c-common.h \$(srcdir)/c-family/c-cppbuiltin.c \$(srcdir)/c-family/c-pragma.h \$(srcdir)/c-family/c-pragma.c"
+gtfiles="\$(srcdir)/objc/objc-map.h \$(srcdir)/c-family/c-objc.h \$(srcdir)/objc/objc-act.h \$(srcdir)/objc/objc-act.c \$(srcdir)/objc/objc-runtime-shared-support.c \$(srcdir)/objc/objc-gnu-runtime-abi-01.c \$(srcdir)/objc/objc-next-runtime-abi-01.c \$(srcdir)/objc/objc-next-runtime-abi-02.c \$(srcdir)/c/c-parser.h \$(srcdir)/c/c-parser.c \$(srcdir)/c/c-tree.h \$(srcdir)/c/c-decl.c \$(srcdir)/c/c-lang.h \$(srcdir)/c/c-objc-common.c \$(srcdir)/c-family/c-common.c \$(srcdir)/c-family/c-common.h \$(srcdir)/c-family/c-cppbuiltin.c \$(srcdir)/c-family/c-pragma.h \$(srcdir)/c-family/c-pragma.c \$(srcdir)/c-family/c-format.c"
diff --git a/gcc/objc/objc-act.c b/gcc/objc/objc-act.c
index 5cf7205..6c18804 100644
--- a/gcc/objc/objc-act.c
+++ b/gcc/objc/objc-act.c
@@ -458,7 +458,7 @@ objc_write_global_declarations (void)
char * const dumpname = concat (dump_base_name, ".decl", NULL);
gen_declaration_file = fopen (dumpname, "w");
if (gen_declaration_file == 0)
- fatal_error (input_location, "can%'t open %s: %m", dumpname);
+ fatal_error (input_location, "cannot open %s: %m", dumpname);
free (dumpname);
}
@@ -1747,7 +1747,7 @@ objc_build_setter_call (tree lhs, tree rhs)
if (PROPERTY_READONLY (property_decl))
{
- error ("readonly property cannot be set");
+ error ("%qs property cannot be set", "readonly");
return error_mark_node;
}
else
@@ -2950,12 +2950,14 @@ synth_module_prologue (void)
objc_class_reference = xref_tag (RECORD_TYPE, objc_class_id);
objc_object_type = build_pointer_type (objc_object_reference);
+ objc_instancetype_type = build_pointer_type (objc_object_reference);
objc_class_type = build_pointer_type (objc_class_reference);
objc_object_name = get_identifier (OBJECT_TYPEDEF_NAME);
+ objc_instancetype_name = get_identifier (INSTANCE_TYPEDEF_NAME);
objc_class_name = get_identifier (CLASS_TYPEDEF_NAME);
- /* Declare the 'id' and 'Class' typedefs. */
+ /* Declare the 'id', 'instancetype' and 'Class' typedefs. */
type = lang_hooks.decls.pushdecl (build_decl (input_location,
TYPE_DECL,
objc_object_name,
@@ -2964,6 +2966,12 @@ synth_module_prologue (void)
type = lang_hooks.decls.pushdecl (build_decl (input_location,
TYPE_DECL,
+ objc_instancetype_name,
+ objc_instancetype_type));
+ TREE_NO_WARNING (type) = 1;
+
+ type = lang_hooks.decls.pushdecl (build_decl (input_location,
+ TYPE_DECL,
objc_class_name,
objc_class_type));
TREE_NO_WARNING (type) = 1;
@@ -4208,13 +4216,13 @@ objc_begin_catch_clause (tree decl)
}
else if (!objc_type_valid_for_messaging (type, false))
{
- error ("@catch parameter is not a known Objective-C class type");
+ error ("%<@catch%> parameter is not a known Objective-C class type");
type = error_mark_node;
}
else if (TYPE_HAS_OBJC_INFO (TREE_TYPE (type))
&& TYPE_OBJC_PROTOCOL_LIST (TREE_TYPE (type)))
{
- error ("@catch parameter cannot be protocol-qualified");
+ error ("%<@catch%> parameter cannot be protocol-qualified");
type = error_mark_node;
}
else if (POINTER_TYPE_P (type) && objc_is_object_id (TREE_TYPE (type)))
@@ -4336,7 +4344,8 @@ objc_build_throw_stmt (location_t loc, tree throw_expr)
if (cur_try_context == NULL
|| cur_try_context->current_catch == NULL)
{
- error_at (loc, "%<@throw%> (rethrow) used outside of a @catch block");
+ error_at (loc,
+ "%<@throw%> (rethrow) used outside of a %<@catch%> block");
return error_mark_node;
}
@@ -5411,7 +5420,8 @@ objc_finish_message_expr (tree receiver, tree sel_name, tree method_params,
prototype. Emit a warning, then keep going (this
will use any method with a matching name, as if the
receiver was of type 'Class'). */
- warning (0, "@interface of class %qE not found", class_tree);
+ warning (0, "%<@interface%> of class %qE not found",
+ class_tree);
}
}
/* Handle `self' and `super'. */
@@ -5545,7 +5555,7 @@ objc_finish_message_expr (tree receiver, tree sel_name, tree method_params,
warning, either include an @interface for the
class, or cast the receiver to 'id'. Note that
rtype is an IDENTIFIER_NODE at this point. */
- warning (0, "@interface of class %qE not found", rtype);
+ warning (0, "%<@interface%> of class %qE not found", rtype);
}
}
@@ -5628,11 +5638,9 @@ objc_finish_message_expr (tree receiver, tree sel_name, tree method_params,
if (!warn_missing_methods)
{
warning_at (input_location,
- 0, "(Messages without a matching method signature");
- warning_at (input_location,
- 0, "will be assumed to return %<id%> and accept");
- warning_at (input_location,
- 0, "%<...%> as arguments.)");
+ 0, "(messages without a matching method signature "
+ "will be assumed to return %<id%> and accept "
+ "%<...%> as arguments)");
warn_missing_methods = true;
}
}
@@ -8848,7 +8856,7 @@ get_super_receiver (void)
}
else
{
- error ("[super ...] must appear in a method context");
+ error ("%<[super ...]%> must appear in a method context");
return error_mark_node;
}
}
diff --git a/gcc/objc/objc-act.h b/gcc/objc/objc-act.h
index 5794cdf4..3b69043 100644
--- a/gcc/objc/objc-act.h
+++ b/gcc/objc/objc-act.h
@@ -313,6 +313,7 @@ enum objc_tree_index
OCTI_SUPER_TYPE,
OCTI_SEL_TYPE,
OCTI_ID_TYPE,
+ OCTI_INSTANCE_TYPE,
OCTI_CLS_TYPE,
OCTI_NST_TYPE,
OCTI_PROTO_TYPE,
@@ -368,6 +369,7 @@ enum objc_tree_index
OCTI_OBJ_ID,
OCTI_CLS_ID,
OCTI_ID_NAME,
+ OCTI_INSTANCETYPE_NAME,
OCTI_CLASS_NAME,
OCTI_CNST_STR_ID,
OCTI_CNST_STR_TYPE,
@@ -443,6 +445,7 @@ extern GTY(()) tree objc_global_trees[OCTI_MAX];
#define objc_super_type objc_global_trees[OCTI_SUPER_TYPE]
#define objc_selector_type objc_global_trees[OCTI_SEL_TYPE]
#define objc_object_type objc_global_trees[OCTI_ID_TYPE]
+#define objc_instancetype_type objc_global_trees[OCTI_INSTANCE_TYPE]
#define objc_class_type objc_global_trees[OCTI_CLS_TYPE]
#define objc_instance_type objc_global_trees[OCTI_NST_TYPE]
#define objc_protocol_type objc_global_trees[OCTI_PROTO_TYPE]
@@ -570,7 +573,8 @@ extern GTY(()) tree objc_global_trees[OCTI_MAX];
#define objc_object_id objc_global_trees[OCTI_OBJ_ID]
#define objc_class_id objc_global_trees[OCTI_CLS_ID]
-#define objc_object_name objc_global_trees[OCTI_ID_NAME]
+#define objc_object_name objc_global_trees[OCTI_ID_NAME]
+#define objc_instancetype_name objc_global_trees[OCTI_INSTANCETYPE_NAME]
#define objc_class_name objc_global_trees[OCTI_CLASS_NAME]
/* Constant string classes. */
@@ -608,6 +612,7 @@ extern GTY(()) tree objc_global_trees[OCTI_MAX];
/* Reserved tag definitions. */
#define OBJECT_TYPEDEF_NAME "id"
+#define INSTANCE_TYPEDEF_NAME "instancetype"
#define CLASS_TYPEDEF_NAME "Class"
#define TAG_OBJECT "objc_object"
diff --git a/gcc/objc/objc-encoding.c b/gcc/objc/objc-encoding.c
index 2db7c09..91ad7d9 100644
--- a/gcc/objc/objc-encoding.c
+++ b/gcc/objc/objc-encoding.c
@@ -801,7 +801,7 @@ encode_gnu_bitfield (int position, tree type, int size)
else
{
/* Do not do any encoding, produce an error and keep going. */
- error ("trying to encode non-integer type as a bitfield");
+ error ("trying to encode non-integer type as a bit-field");
return;
}
diff --git a/gcc/objc/objc-next-runtime-abi-01.c b/gcc/objc/objc-next-runtime-abi-01.c
index 77d2c37..fa83e64 100644
--- a/gcc/objc/objc-next-runtime-abi-01.c
+++ b/gcc/objc/objc-next-runtime-abi-01.c
@@ -150,7 +150,8 @@ objc_next_runtime_abi_01_init (objc_runtime_hooks *rthooks)
{
warning_at (UNKNOWN_LOCATION, OPT_Wall,
"%<-fobjc-sjlj-exceptions%> is the only supported exceptions "
- "system for %<-fnext-runtime%> with %<-fobjc-abi-version%> < 2");
+ "system for %<-fnext-runtime%> with %<-fobjc-abi-version%> "
+ "argument less than 2");
}
rthooks->initialize = next_runtime_01_initialize;
diff --git a/gcc/objc/objc-next-runtime-abi-02.c b/gcc/objc/objc-next-runtime-abi-02.c
index a221419..aa1cbde 100644
--- a/gcc/objc/objc-next-runtime-abi-02.c
+++ b/gcc/objc/objc-next-runtime-abi-02.c
@@ -241,8 +241,10 @@ objc_next_runtime_abi_02_init (objc_runtime_hooks *rthooks)
if (flag_objc_exceptions && flag_objc_sjlj_exceptions)
{
- inform (UNKNOWN_LOCATION, "%<-fobjc-sjlj-exceptions%> is ignored for "
- "%<-fnext-runtime%> when %<-fobjc-abi-version%> >= 2");
+ inform (UNKNOWN_LOCATION,
+ "%<-fobjc-sjlj-exceptions%> is ignored for "
+ "%<-fnext-runtime%> when %<-fobjc-abi-version%> "
+ "greater than 1");
flag_objc_sjlj_exceptions = 0;
}
diff --git a/gcc/objcp/ChangeLog b/gcc/objcp/ChangeLog
index eb8c7b8..02e2130 100644
--- a/gcc/objcp/ChangeLog
+++ b/gcc/objcp/ChangeLog
@@ -1,3 +1,8 @@
+2019-05-10 Jakub Jelinek <jakub@redhat.com>
+
+ PR pch/90326
+ * config-lang.in (gtfiles): Don't add c-family/c-cppbuiltin.c.
+
2019-01-01 Jakub Jelinek <jakub@redhat.com>
Update copyright years.
diff --git a/gcc/objcp/config-lang.in b/gcc/objcp/config-lang.in
index 71bf986..6c38806 100644
--- a/gcc/objcp/config-lang.in
+++ b/gcc/objcp/config-lang.in
@@ -52,7 +52,6 @@ gtfiles="$(. $srcdir/cp/config-lang.in ; \
gtfiles="$gtfiles \
\$(srcdir)/objc/objc-act.h \
\$(srcdir)/objc/objc-map.h \
-\$(srcdir)/c-family/c-cppbuiltin.c \
\$(srcdir)/objc/objc-act.c \
\$(srcdir)/objc/objc-gnu-runtime-abi-01.c \
\$(srcdir)/objc/objc-next-runtime-abi-01.c \
diff --git a/gcc/omp-expand.c b/gcc/omp-expand.c
index 89a3a32..9236b36 100644
--- a/gcc/omp-expand.c
+++ b/gcc/omp-expand.c
@@ -100,6 +100,9 @@ struct omp_region
/* True if this is a combined parallel+workshare region. */
bool is_combined_parallel;
+ /* Copy of fd.lastprivate_conditional != 0. */
+ bool has_lastprivate_conditional;
+
/* The ordered stmt if type is GIMPLE_OMP_ORDERED and it has
a depend clause. */
gomp_ordered *ord_stmt;
@@ -345,12 +348,16 @@ determine_parallel_type (struct omp_region *region)
|| ((OMP_CLAUSE_SCHEDULE_KIND (c) & OMP_CLAUSE_SCHEDULE_MASK)
== OMP_CLAUSE_SCHEDULE_STATIC)
|| omp_find_clause (clauses, OMP_CLAUSE_ORDERED)
- || omp_find_clause (clauses, OMP_CLAUSE__REDUCTEMP_))
+ || omp_find_clause (clauses, OMP_CLAUSE__REDUCTEMP_)
+ || ((c = omp_find_clause (clauses, OMP_CLAUSE__CONDTEMP_))
+ && POINTER_TYPE_P (TREE_TYPE (OMP_CLAUSE_DECL (c)))))
return;
}
else if (region->inner->type == GIMPLE_OMP_SECTIONS
- && omp_find_clause (gimple_omp_sections_clauses (ws_stmt),
- OMP_CLAUSE__REDUCTEMP_))
+ && (omp_find_clause (gimple_omp_sections_clauses (ws_stmt),
+ OMP_CLAUSE__REDUCTEMP_)
+ || omp_find_clause (gimple_omp_sections_clauses (ws_stmt),
+ OMP_CLAUSE__CONDTEMP_)))
return;
region->is_combined_parallel = true;
@@ -597,8 +604,12 @@ expand_parallel_call (struct omp_region *region, basic_block bb,
switch (region->inner->sched_kind)
{
case OMP_CLAUSE_SCHEDULE_RUNTIME:
- if ((region->inner->sched_modifiers
- & OMP_CLAUSE_SCHEDULE_NONMONOTONIC) != 0)
+ /* For lastprivate(conditional:), our implementation
+ requires monotonic behavior. */
+ if (region->inner->has_lastprivate_conditional != 0)
+ start_ix2 = 3;
+ else if ((region->inner->sched_modifiers
+ & OMP_CLAUSE_SCHEDULE_NONMONOTONIC) != 0)
start_ix2 = 6;
else if ((region->inner->sched_modifiers
& OMP_CLAUSE_SCHEDULE_MONOTONIC) == 0)
@@ -609,7 +620,8 @@ expand_parallel_call (struct omp_region *region, basic_block bb,
case OMP_CLAUSE_SCHEDULE_DYNAMIC:
case OMP_CLAUSE_SCHEDULE_GUIDED:
if ((region->inner->sched_modifiers
- & OMP_CLAUSE_SCHEDULE_MONOTONIC) == 0)
+ & OMP_CLAUSE_SCHEDULE_MONOTONIC) == 0
+ && !region->inner->has_lastprivate_conditional)
{
start_ix2 = 3 + region->inner->sched_kind;
break;
@@ -2679,16 +2691,26 @@ expand_omp_for_generic (struct omp_region *region,
gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
if (fd->ordered
- && omp_find_clause (gimple_omp_for_clauses (gsi_stmt (gsi)),
+ && omp_find_clause (gimple_omp_for_clauses (fd->for_stmt),
OMP_CLAUSE_LASTPRIVATE))
ordered_lastprivate = false;
tree reductions = NULL_TREE;
- tree mem = NULL_TREE;
+ tree mem = NULL_TREE, cond_var = NULL_TREE, condtemp = NULL_TREE;
+ tree memv = NULL_TREE;
+ if (fd->lastprivate_conditional)
+ {
+ tree c = omp_find_clause (gimple_omp_for_clauses (fd->for_stmt),
+ OMP_CLAUSE__CONDTEMP_);
+ if (fd->have_pointer_condtemp)
+ condtemp = OMP_CLAUSE_DECL (c);
+ c = omp_find_clause (OMP_CLAUSE_CHAIN (c), OMP_CLAUSE__CONDTEMP_);
+ cond_var = OMP_CLAUSE_DECL (c);
+ }
if (sched_arg)
{
if (fd->have_reductemp)
{
- tree c = omp_find_clause (gimple_omp_for_clauses (gsi_stmt (gsi)),
+ tree c = omp_find_clause (gimple_omp_for_clauses (fd->for_stmt),
OMP_CLAUSE__REDUCTEMP_);
reductions = OMP_CLAUSE_DECL (c);
gcc_assert (TREE_CODE (reductions) == SSA_NAME);
@@ -2703,8 +2725,20 @@ expand_omp_for_generic (struct omp_region *region,
}
else
reductions = null_pointer_node;
- /* For now. */
- mem = null_pointer_node;
+ if (fd->have_pointer_condtemp)
+ {
+ tree type = TREE_TYPE (condtemp);
+ memv = create_tmp_var (type);
+ TREE_ADDRESSABLE (memv) = 1;
+ unsigned HOST_WIDE_INT sz
+ = tree_to_uhwi (TYPE_SIZE_UNIT (TREE_TYPE (type)));
+ sz *= fd->lastprivate_conditional;
+ expand_omp_build_assign (&gsi, memv, build_int_cst (type, sz),
+ false);
+ mem = build_fold_addr_expr (memv);
+ }
+ else
+ mem = null_pointer_node;
}
if (fd->collapse > 1 || fd->ordered)
{
@@ -2959,6 +2993,8 @@ expand_omp_for_generic (struct omp_region *region,
gsi_insert_before (&gsi, gimple_build_assign (arr, clobber),
GSI_SAME_STMT);
}
+ if (fd->have_pointer_condtemp)
+ expand_omp_build_assign (&gsi, condtemp, memv, false);
if (fd->have_reductemp)
{
gimple *g = gsi_stmt (gsi);
@@ -3029,6 +3065,35 @@ expand_omp_for_generic (struct omp_region *region,
NULL_TREE, false, GSI_CONTINUE_LINKING);
assign_stmt = gimple_build_assign (startvar, t);
gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
+ if (cond_var)
+ {
+ tree itype = TREE_TYPE (cond_var);
+ /* For lastprivate(conditional:) itervar, we need some iteration
+ counter that starts at unsigned non-zero and increases.
+ Prefer as few IVs as possible, so if we can use startvar
+ itself, use that, or startvar + constant (those would be
+ incremented with step), and as last resort use the s0 + 1
+ incremented by 1. */
+ if ((fd->ordered && fd->collapse == 1)
+ || bias
+ || POINTER_TYPE_P (type)
+ || TREE_CODE (fd->loop.n1) != INTEGER_CST
+ || fd->loop.cond_code != LT_EXPR)
+ t = fold_build2 (PLUS_EXPR, itype, fold_convert (itype, istart0),
+ build_int_cst (itype, 1));
+ else if (tree_int_cst_sgn (fd->loop.n1) == 1)
+ t = fold_convert (itype, t);
+ else
+ {
+ tree c = fold_convert (itype, fd->loop.n1);
+ c = fold_build2 (MINUS_EXPR, itype, build_int_cst (itype, 1), c);
+ t = fold_build2 (PLUS_EXPR, itype, fold_convert (itype, t), c);
+ }
+ t = force_gimple_operand_gsi (&gsi, t, false,
+ NULL_TREE, false, GSI_CONTINUE_LINKING);
+ assign_stmt = gimple_build_assign (cond_var, t);
+ gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
+ }
t = iend0;
if (fd->ordered && fd->collapse == 1)
@@ -3200,6 +3265,25 @@ expand_omp_for_generic (struct omp_region *region,
vmain = gimple_omp_continue_control_use (cont_stmt);
vback = gimple_omp_continue_control_def (cont_stmt);
+ if (cond_var)
+ {
+ tree itype = TREE_TYPE (cond_var);
+ tree t2;
+ if ((fd->ordered && fd->collapse == 1)
+ || bias
+ || POINTER_TYPE_P (type)
+ || TREE_CODE (fd->loop.n1) != INTEGER_CST
+ || fd->loop.cond_code != LT_EXPR)
+ t2 = build_int_cst (itype, 1);
+ else
+ t2 = fold_convert (itype, fd->loop.step);
+ t2 = fold_build2 (PLUS_EXPR, itype, cond_var, t2);
+ t2 = force_gimple_operand_gsi (&gsi, t2, false,
+ NULL_TREE, true, GSI_SAME_STMT);
+ assign_stmt = gimple_build_assign (cond_var, t2);
+ gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
+ }
+
if (!gimple_omp_for_combined_p (fd->for_stmt))
{
if (POINTER_TYPE_P (type))
@@ -3418,6 +3502,98 @@ expand_omp_for_generic (struct omp_region *region,
}
}
+/* Helper function for expand_omp_for_static_nochunk. If PTR is NULL,
+ compute needed allocation size. If !ALLOC of team allocations,
+ if ALLOC of thread allocation. SZ is the initial needed size for
+ other purposes, ALLOC_ALIGN guaranteed alignment of allocation in bytes,
+ CNT number of elements of each array, for !ALLOC this is
+ omp_get_num_threads (), for ALLOC number of iterations handled by the
+ current thread. If PTR is non-NULL, it is the start of the allocation
+ and this routine shall assign to OMP_CLAUSE_DECL (c) of those _scantemp_
+ clauses pointers to the corresponding arrays. */
+
+static tree
+expand_omp_scantemp_alloc (tree clauses, tree ptr, unsigned HOST_WIDE_INT sz,
+ unsigned HOST_WIDE_INT alloc_align, tree cnt,
+ gimple_stmt_iterator *gsi, bool alloc)
+{
+ tree eltsz = NULL_TREE;
+ unsigned HOST_WIDE_INT preval = 0;
+ if (ptr && sz)
+ ptr = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (ptr),
+ ptr, size_int (sz));
+ for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
+ if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE__SCANTEMP_
+ && !OMP_CLAUSE__SCANTEMP__CONTROL (c)
+ && (!OMP_CLAUSE__SCANTEMP__ALLOC (c)) != alloc)
+ {
+ tree pointee_type = TREE_TYPE (TREE_TYPE (OMP_CLAUSE_DECL (c)));
+ unsigned HOST_WIDE_INT al = TYPE_ALIGN_UNIT (pointee_type);
+ if (tree_fits_uhwi_p (TYPE_SIZE_UNIT (pointee_type)))
+ {
+ unsigned HOST_WIDE_INT szl
+ = tree_to_uhwi (TYPE_SIZE_UNIT (pointee_type));
+ szl = least_bit_hwi (szl);
+ if (szl)
+ al = MIN (al, szl);
+ }
+ if (ptr == NULL_TREE)
+ {
+ if (eltsz == NULL_TREE)
+ eltsz = TYPE_SIZE_UNIT (pointee_type);
+ else
+ eltsz = size_binop (PLUS_EXPR, eltsz,
+ TYPE_SIZE_UNIT (pointee_type));
+ }
+ if (preval == 0 && al <= alloc_align)
+ {
+ unsigned HOST_WIDE_INT diff = ROUND_UP (sz, al) - sz;
+ sz += diff;
+ if (diff && ptr)
+ ptr = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (ptr),
+ ptr, size_int (diff));
+ }
+ else if (al > preval)
+ {
+ if (ptr)
+ {
+ ptr = fold_convert (pointer_sized_int_node, ptr);
+ ptr = fold_build2 (PLUS_EXPR, pointer_sized_int_node, ptr,
+ build_int_cst (pointer_sized_int_node,
+ al - 1));
+ ptr = fold_build2 (BIT_AND_EXPR, pointer_sized_int_node, ptr,
+ build_int_cst (pointer_sized_int_node,
+ -(HOST_WIDE_INT) al));
+ ptr = fold_convert (ptr_type_node, ptr);
+ }
+ else
+ sz += al - 1;
+ }
+ if (tree_fits_uhwi_p (TYPE_SIZE_UNIT (pointee_type)))
+ preval = al;
+ else
+ preval = 1;
+ if (ptr)
+ {
+ expand_omp_build_assign (gsi, OMP_CLAUSE_DECL (c), ptr, false);
+ ptr = OMP_CLAUSE_DECL (c);
+ ptr = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (ptr), ptr,
+ size_binop (MULT_EXPR, cnt,
+ TYPE_SIZE_UNIT (pointee_type)));
+ }
+ }
+
+ if (ptr == NULL_TREE)
+ {
+ eltsz = size_binop (MULT_EXPR, eltsz, cnt);
+ if (sz)
+ eltsz = size_binop (PLUS_EXPR, eltsz, size_int (sz));
+ return eltsz;
+ }
+ else
+ return ptr;
+}
+
/* A subroutine of expand_omp_for. Generate code for a parallel
loop with static schedule and no specified chunk size. Given
parameters:
@@ -3460,17 +3636,19 @@ expand_omp_for_static_nochunk (struct omp_region *region,
struct omp_for_data *fd,
gimple *inner_stmt)
{
- tree n, q, s0, e0, e, t, tt, nthreads, threadid;
+ tree n, q, s0, e0, e, t, tt, nthreads = NULL_TREE, threadid;
tree type, itype, vmain, vback;
basic_block entry_bb, second_bb, third_bb, exit_bb, seq_start_bb;
basic_block body_bb, cont_bb, collapse_bb = NULL;
- basic_block fin_bb;
- gimple_stmt_iterator gsi;
+ basic_block fin_bb, fourth_bb = NULL, fifth_bb = NULL, sixth_bb = NULL;
+ basic_block exit1_bb = NULL, exit2_bb = NULL, exit3_bb = NULL;
+ gimple_stmt_iterator gsi, gsip;
edge ep;
bool broken_loop = region->cont == NULL;
tree *counts = NULL;
tree n1, n2, step;
tree reductions = NULL_TREE;
+ tree cond_var = NULL_TREE, condtemp = NULL_TREE;
itype = type = TREE_TYPE (fd->loop.v);
if (POINTER_TYPE_P (type))
@@ -3495,6 +3673,8 @@ expand_omp_for_static_nochunk (struct omp_region *region,
/* Iteration space partitioning goes in ENTRY_BB. */
gsi = gsi_last_nondebug_bb (entry_bb);
gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
+ gsip = gsi;
+ gsi_prev (&gsip);
if (fd->collapse > 1)
{
@@ -3524,7 +3704,7 @@ expand_omp_for_static_nochunk (struct omp_region *region,
n2 = force_gimple_operand_gsi (&gsi, n2, true, NULL_TREE,
true, GSI_SAME_STMT);
gcond *cond_stmt = gimple_build_cond (fd->loop.cond_code, n1, n2,
- NULL_TREE, NULL_TREE);
+ NULL_TREE, NULL_TREE);
gsi_insert_before (&gsi, cond_stmt, GSI_SAME_STMT);
if (walk_tree (gimple_cond_lhs_ptr (cond_stmt),
expand_omp_regimplify_p, NULL, NULL)
@@ -3554,28 +3734,103 @@ expand_omp_for_static_nochunk (struct omp_region *region,
gsi = gsi_last_bb (entry_bb);
}
- if (fd->have_reductemp)
+ if (fd->lastprivate_conditional)
+ {
+ tree clauses = gimple_omp_for_clauses (fd->for_stmt);
+ tree c = omp_find_clause (clauses, OMP_CLAUSE__CONDTEMP_);
+ if (fd->have_pointer_condtemp)
+ condtemp = OMP_CLAUSE_DECL (c);
+ c = omp_find_clause (OMP_CLAUSE_CHAIN (c), OMP_CLAUSE__CONDTEMP_);
+ cond_var = OMP_CLAUSE_DECL (c);
+ }
+ if (fd->have_reductemp
+ || fd->have_pointer_condtemp
+ || fd->have_nonctrl_scantemp)
{
tree t1 = build_int_cst (long_integer_type_node, 0);
tree t2 = build_int_cst (long_integer_type_node, 1);
tree t3 = build_int_cstu (long_integer_type_node,
(HOST_WIDE_INT_1U << 31) + 1);
tree clauses = gimple_omp_for_clauses (fd->for_stmt);
- clauses = omp_find_clause (clauses, OMP_CLAUSE__REDUCTEMP_);
- reductions = OMP_CLAUSE_DECL (clauses);
- gcc_assert (TREE_CODE (reductions) == SSA_NAME);
- gimple *g = SSA_NAME_DEF_STMT (reductions);
- reductions = gimple_assign_rhs1 (g);
- OMP_CLAUSE_DECL (clauses) = reductions;
- gimple_stmt_iterator gsi2 = gsi_for_stmt (g);
+ gimple_stmt_iterator gsi2 = gsi_none ();
+ gimple *g = NULL;
+ tree mem = null_pointer_node, memv = NULL_TREE;
+ unsigned HOST_WIDE_INT condtemp_sz = 0;
+ unsigned HOST_WIDE_INT alloc_align = 0;
+ if (fd->have_reductemp)
+ {
+ gcc_assert (!fd->have_nonctrl_scantemp);
+ tree c = omp_find_clause (clauses, OMP_CLAUSE__REDUCTEMP_);
+ reductions = OMP_CLAUSE_DECL (c);
+ gcc_assert (TREE_CODE (reductions) == SSA_NAME);
+ g = SSA_NAME_DEF_STMT (reductions);
+ reductions = gimple_assign_rhs1 (g);
+ OMP_CLAUSE_DECL (c) = reductions;
+ gsi2 = gsi_for_stmt (g);
+ }
+ else
+ {
+ if (gsi_end_p (gsip))
+ gsi2 = gsi_after_labels (region->entry);
+ else
+ gsi2 = gsip;
+ reductions = null_pointer_node;
+ }
+ if (fd->have_pointer_condtemp || fd->have_nonctrl_scantemp)
+ {
+ tree type;
+ if (fd->have_pointer_condtemp)
+ type = TREE_TYPE (condtemp);
+ else
+ type = ptr_type_node;
+ memv = create_tmp_var (type);
+ TREE_ADDRESSABLE (memv) = 1;
+ unsigned HOST_WIDE_INT sz = 0;
+ tree size = NULL_TREE;
+ if (fd->have_pointer_condtemp)
+ {
+ sz = tree_to_uhwi (TYPE_SIZE_UNIT (TREE_TYPE (type)));
+ sz *= fd->lastprivate_conditional;
+ condtemp_sz = sz;
+ }
+ if (fd->have_nonctrl_scantemp)
+ {
+ nthreads = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
+ gimple *g = gimple_build_call (nthreads, 0);
+ nthreads = create_tmp_var (integer_type_node);
+ gimple_call_set_lhs (g, nthreads);
+ gsi_insert_before (&gsi2, g, GSI_SAME_STMT);
+ nthreads = fold_convert (sizetype, nthreads);
+ alloc_align = TYPE_ALIGN_UNIT (long_long_integer_type_node);
+ size = expand_omp_scantemp_alloc (clauses, NULL_TREE, sz,
+ alloc_align, nthreads, NULL,
+ false);
+ size = fold_convert (type, size);
+ }
+ else
+ size = build_int_cst (type, sz);
+ expand_omp_build_assign (&gsi2, memv, size, false);
+ mem = build_fold_addr_expr (memv);
+ }
tree t
= build_call_expr (builtin_decl_explicit (BUILT_IN_GOMP_LOOP_START),
9, t1, t2, t2, t3, t1, null_pointer_node,
- null_pointer_node, reductions, null_pointer_node);
+ null_pointer_node, reductions, mem);
force_gimple_operand_gsi (&gsi2, t, true, NULL_TREE,
true, GSI_SAME_STMT);
- gsi_remove (&gsi2, true);
- release_ssa_name (gimple_assign_lhs (g));
+ if (fd->have_pointer_condtemp)
+ expand_omp_build_assign (&gsi2, condtemp, memv, false);
+ if (fd->have_nonctrl_scantemp)
+ {
+ tree ptr = fd->have_pointer_condtemp ? condtemp : memv;
+ expand_omp_scantemp_alloc (clauses, ptr, condtemp_sz,
+ alloc_align, nthreads, &gsi2, false);
+ }
+ if (fd->have_reductemp)
+ {
+ gsi_remove (&gsi2, true);
+ release_ssa_name (gimple_assign_lhs (g));
+ }
}
switch (gimple_omp_for_kind (fd->for_stmt))
{
@@ -3661,6 +3916,72 @@ expand_omp_for_static_nochunk (struct omp_region *region,
gsi = gsi_last_nondebug_bb (third_bb);
gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
+ if (fd->have_nonctrl_scantemp)
+ {
+ tree clauses = gimple_omp_for_clauses (fd->for_stmt);
+ tree controlp = NULL_TREE, controlb = NULL_TREE;
+ for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
+ if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE__SCANTEMP_
+ && OMP_CLAUSE__SCANTEMP__CONTROL (c))
+ {
+ if (TREE_TYPE (OMP_CLAUSE_DECL (c)) == boolean_type_node)
+ controlb = OMP_CLAUSE_DECL (c);
+ else
+ controlp = OMP_CLAUSE_DECL (c);
+ if (controlb && controlp)
+ break;
+ }
+ gcc_assert (controlp && controlb);
+ tree cnt = create_tmp_var (sizetype);
+ gimple *g = gimple_build_assign (cnt, NOP_EXPR, q);
+ gsi_insert_before (&gsi, g, GSI_SAME_STMT);
+ unsigned HOST_WIDE_INT alloc_align = TYPE_ALIGN_UNIT (ptr_type_node);
+ tree sz = expand_omp_scantemp_alloc (clauses, NULL_TREE, 0,
+ alloc_align, cnt, NULL, true);
+ tree size = create_tmp_var (sizetype);
+ expand_omp_build_assign (&gsi, size, sz, false);
+ tree cmp = fold_build2 (GT_EXPR, boolean_type_node,
+ size, size_int (16384));
+ expand_omp_build_assign (&gsi, controlb, cmp);
+ g = gimple_build_cond (NE_EXPR, controlb, boolean_false_node,
+ NULL_TREE, NULL_TREE);
+ gsi_insert_before (&gsi, g, GSI_SAME_STMT);
+ fourth_bb = split_block (third_bb, g)->dest;
+ gsi = gsi_last_nondebug_bb (fourth_bb);
+ /* FIXME: Once we have allocators, this should use allocator. */
+ g = gimple_build_call (builtin_decl_explicit (BUILT_IN_MALLOC), 1, size);
+ gimple_call_set_lhs (g, controlp);
+ gsi_insert_before (&gsi, g, GSI_SAME_STMT);
+ expand_omp_scantemp_alloc (clauses, controlp, 0, alloc_align, cnt,
+ &gsi, true);
+ gsi_prev (&gsi);
+ g = gsi_stmt (gsi);
+ fifth_bb = split_block (fourth_bb, g)->dest;
+ gsi = gsi_last_nondebug_bb (fifth_bb);
+
+ g = gimple_build_call (builtin_decl_implicit (BUILT_IN_STACK_SAVE), 0);
+ gimple_call_set_lhs (g, controlp);
+ gsi_insert_before (&gsi, g, GSI_SAME_STMT);
+ tree alloca_decl = builtin_decl_explicit (BUILT_IN_ALLOCA_WITH_ALIGN);
+ for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
+ if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE__SCANTEMP_
+ && OMP_CLAUSE__SCANTEMP__ALLOC (c))
+ {
+ tree tmp = create_tmp_var (sizetype);
+ tree pointee_type = TREE_TYPE (TREE_TYPE (OMP_CLAUSE_DECL (c)));
+ g = gimple_build_assign (tmp, MULT_EXPR, cnt,
+ TYPE_SIZE_UNIT (pointee_type));
+ gsi_insert_before (&gsi, g, GSI_SAME_STMT);
+ g = gimple_build_call (alloca_decl, 2, tmp,
+ size_int (TYPE_ALIGN (pointee_type)));
+ gimple_call_set_lhs (g, OMP_CLAUSE_DECL (c));
+ gsi_insert_before (&gsi, g, GSI_SAME_STMT);
+ }
+
+ sixth_bb = split_block (fifth_bb, g)->dest;
+ gsi = gsi_last_nondebug_bb (sixth_bb);
+ }
+
t = build2 (MULT_EXPR, itype, q, threadid);
t = build2 (PLUS_EXPR, itype, t, tt);
s0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
@@ -3735,6 +4056,33 @@ expand_omp_for_static_nochunk (struct omp_region *region,
NULL_TREE, false, GSI_CONTINUE_LINKING);
assign_stmt = gimple_build_assign (startvar, t);
gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
+ if (cond_var)
+ {
+ tree itype = TREE_TYPE (cond_var);
+ /* For lastprivate(conditional:) itervar, we need some iteration
+ counter that starts at unsigned non-zero and increases.
+ Prefer as few IVs as possible, so if we can use startvar
+ itself, use that, or startvar + constant (those would be
+ incremented with step), and as last resort use the s0 + 1
+ incremented by 1. */
+ if (POINTER_TYPE_P (type)
+ || TREE_CODE (n1) != INTEGER_CST
+ || fd->loop.cond_code != LT_EXPR)
+ t = fold_build2 (PLUS_EXPR, itype, fold_convert (itype, s0),
+ build_int_cst (itype, 1));
+ else if (tree_int_cst_sgn (n1) == 1)
+ t = fold_convert (itype, t);
+ else
+ {
+ tree c = fold_convert (itype, n1);
+ c = fold_build2 (MINUS_EXPR, itype, build_int_cst (itype, 1), c);
+ t = fold_build2 (PLUS_EXPR, itype, fold_convert (itype, t), c);
+ }
+ t = force_gimple_operand_gsi (&gsi, t, false,
+ NULL_TREE, false, GSI_CONTINUE_LINKING);
+ assign_stmt = gimple_build_assign (cond_var, t);
+ gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
+ }
t = fold_convert (itype, e0);
t = fold_build2 (MULT_EXPR, itype, t, step);
@@ -3816,6 +4164,23 @@ expand_omp_for_static_nochunk (struct omp_region *region,
vmain = gimple_omp_continue_control_use (cont_stmt);
vback = gimple_omp_continue_control_def (cont_stmt);
+ if (cond_var)
+ {
+ tree itype = TREE_TYPE (cond_var);
+ tree t2;
+ if (POINTER_TYPE_P (type)
+ || TREE_CODE (n1) != INTEGER_CST
+ || fd->loop.cond_code != LT_EXPR)
+ t2 = build_int_cst (itype, 1);
+ else
+ t2 = fold_convert (itype, step);
+ t2 = fold_build2 (PLUS_EXPR, itype, cond_var, t2);
+ t2 = force_gimple_operand_gsi (&gsi, t2, false,
+ NULL_TREE, true, GSI_SAME_STMT);
+ assign_stmt = gimple_build_assign (cond_var, t2);
+ gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
+ }
+
if (!gimple_omp_for_combined_p (fd->for_stmt))
{
if (POINTER_TYPE_P (type))
@@ -3847,7 +4212,9 @@ expand_omp_for_static_nochunk (struct omp_region *region,
if (!gimple_omp_return_nowait_p (gsi_stmt (gsi)))
{
t = gimple_omp_return_lhs (gsi_stmt (gsi));
- if (fd->have_reductemp)
+ if (fd->have_reductemp
+ || ((fd->have_pointer_condtemp || fd->have_scantemp)
+ && !fd->have_nonctrl_scantemp))
{
tree fn;
if (t)
@@ -3858,15 +4225,54 @@ expand_omp_for_static_nochunk (struct omp_region *region,
if (t)
{
gimple_call_set_lhs (g, t);
- gsi_insert_after (&gsi, gimple_build_assign (reductions,
- NOP_EXPR, t),
- GSI_SAME_STMT);
+ if (fd->have_reductemp)
+ gsi_insert_after (&gsi, gimple_build_assign (reductions,
+ NOP_EXPR, t),
+ GSI_SAME_STMT);
}
gsi_insert_after (&gsi, g, GSI_SAME_STMT);
}
else
gsi_insert_after (&gsi, omp_build_barrier (t), GSI_SAME_STMT);
}
+ else if (fd->have_pointer_condtemp)
+ {
+ tree fn = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END_NOWAIT);
+ gcall *g = gimple_build_call (fn, 0);
+ gsi_insert_after (&gsi, g, GSI_SAME_STMT);
+ }
+ if (fd->have_scantemp && !fd->have_nonctrl_scantemp)
+ {
+ tree clauses = gimple_omp_for_clauses (fd->for_stmt);
+ tree controlp = NULL_TREE, controlb = NULL_TREE;
+ for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
+ if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE__SCANTEMP_
+ && OMP_CLAUSE__SCANTEMP__CONTROL (c))
+ {
+ if (TREE_TYPE (OMP_CLAUSE_DECL (c)) == boolean_type_node)
+ controlb = OMP_CLAUSE_DECL (c);
+ else
+ controlp = OMP_CLAUSE_DECL (c);
+ if (controlb && controlp)
+ break;
+ }
+ gcc_assert (controlp && controlb);
+ gimple *g = gimple_build_cond (NE_EXPR, controlb, boolean_false_node,
+ NULL_TREE, NULL_TREE);
+ gsi_insert_before (&gsi, g, GSI_SAME_STMT);
+ exit1_bb = split_block (exit_bb, g)->dest;
+ gsi = gsi_after_labels (exit1_bb);
+ g = gimple_build_call (builtin_decl_explicit (BUILT_IN_FREE), 1,
+ controlp);
+ gsi_insert_before (&gsi, g, GSI_SAME_STMT);
+ exit2_bb = split_block (exit1_bb, g)->dest;
+ gsi = gsi_after_labels (exit2_bb);
+ g = gimple_build_call (builtin_decl_implicit (BUILT_IN_STACK_RESTORE), 1,
+ controlp);
+ gsi_insert_before (&gsi, g, GSI_SAME_STMT);
+ exit3_bb = split_block (exit2_bb, g)->dest;
+ gsi = gsi_after_labels (exit3_bb);
+ }
gsi_remove (&gsi, true);
/* Connect all the blocks. */
@@ -3875,8 +4281,34 @@ expand_omp_for_static_nochunk (struct omp_region *region,
ep = find_edge (entry_bb, second_bb);
ep->flags = EDGE_TRUE_VALUE;
ep->probability = profile_probability::guessed_always ().apply_scale (1, 4);
- find_edge (third_bb, seq_start_bb)->flags = EDGE_FALSE_VALUE;
- find_edge (third_bb, fin_bb)->flags = EDGE_TRUE_VALUE;
+ if (fourth_bb)
+ {
+ ep = make_edge (third_bb, fifth_bb, EDGE_FALSE_VALUE);
+ ep->probability
+ = profile_probability::guessed_always ().apply_scale (1, 2);
+ ep = find_edge (third_bb, fourth_bb);
+ ep->flags = EDGE_TRUE_VALUE;
+ ep->probability
+ = profile_probability::guessed_always ().apply_scale (1, 2);
+ ep = find_edge (fourth_bb, fifth_bb);
+ redirect_edge_and_branch (ep, sixth_bb);
+ }
+ else
+ sixth_bb = third_bb;
+ find_edge (sixth_bb, seq_start_bb)->flags = EDGE_FALSE_VALUE;
+ find_edge (sixth_bb, fin_bb)->flags = EDGE_TRUE_VALUE;
+ if (exit1_bb)
+ {
+ ep = make_edge (exit_bb, exit2_bb, EDGE_FALSE_VALUE);
+ ep->probability
+ = profile_probability::guessed_always ().apply_scale (1, 2);
+ ep = find_edge (exit_bb, exit1_bb);
+ ep->flags = EDGE_TRUE_VALUE;
+ ep->probability
+ = profile_probability::guessed_always ().apply_scale (1, 2);
+ ep = find_edge (exit1_bb, exit2_bb);
+ redirect_edge_and_branch (ep, exit3_bb);
+ }
if (!broken_loop)
{
@@ -3904,12 +4336,22 @@ expand_omp_for_static_nochunk (struct omp_region *region,
set_immediate_dominator (CDI_DOMINATORS, second_bb, entry_bb);
set_immediate_dominator (CDI_DOMINATORS, third_bb, entry_bb);
- set_immediate_dominator (CDI_DOMINATORS, seq_start_bb, third_bb);
+ if (fourth_bb)
+ {
+ set_immediate_dominator (CDI_DOMINATORS, fifth_bb, third_bb);
+ set_immediate_dominator (CDI_DOMINATORS, sixth_bb, third_bb);
+ }
+ set_immediate_dominator (CDI_DOMINATORS, seq_start_bb, sixth_bb);
set_immediate_dominator (CDI_DOMINATORS, body_bb,
recompute_dominator (CDI_DOMINATORS, body_bb));
set_immediate_dominator (CDI_DOMINATORS, fin_bb,
recompute_dominator (CDI_DOMINATORS, fin_bb));
+ if (exit1_bb)
+ {
+ set_immediate_dominator (CDI_DOMINATORS, exit2_bb, exit_bb);
+ set_immediate_dominator (CDI_DOMINATORS, exit3_bb, exit_bb);
+ }
struct loop *loop = body_bb->loop_father;
if (loop != entry_bb->loop_father)
@@ -3997,12 +4439,13 @@ expand_omp_for_static_chunk (struct omp_region *region,
tree type, itype, vmain, vback, vextra;
basic_block entry_bb, exit_bb, body_bb, seq_start_bb, iter_part_bb;
basic_block trip_update_bb = NULL, cont_bb, collapse_bb = NULL, fin_bb;
- gimple_stmt_iterator gsi;
+ gimple_stmt_iterator gsi, gsip;
edge se;
bool broken_loop = region->cont == NULL;
tree *counts = NULL;
tree n1, n2, step;
tree reductions = NULL_TREE;
+ tree cond_var = NULL_TREE, condtemp = NULL_TREE;
itype = type = TREE_TYPE (fd->loop.v);
if (POINTER_TYPE_P (type))
@@ -4031,6 +4474,8 @@ expand_omp_for_static_chunk (struct omp_region *region,
/* Trip and adjustment setup goes in ENTRY_BB. */
gsi = gsi_last_nondebug_bb (entry_bb);
gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
+ gsip = gsi;
+ gsi_prev (&gsip);
if (fd->collapse > 1)
{
@@ -4090,28 +4535,68 @@ expand_omp_for_static_chunk (struct omp_region *region,
gsi = gsi_last_bb (entry_bb);
}
- if (fd->have_reductemp)
+ if (fd->lastprivate_conditional)
+ {
+ tree clauses = gimple_omp_for_clauses (fd->for_stmt);
+ tree c = omp_find_clause (clauses, OMP_CLAUSE__CONDTEMP_);
+ if (fd->have_pointer_condtemp)
+ condtemp = OMP_CLAUSE_DECL (c);
+ c = omp_find_clause (OMP_CLAUSE_CHAIN (c), OMP_CLAUSE__CONDTEMP_);
+ cond_var = OMP_CLAUSE_DECL (c);
+ }
+ if (fd->have_reductemp || fd->have_pointer_condtemp)
{
tree t1 = build_int_cst (long_integer_type_node, 0);
tree t2 = build_int_cst (long_integer_type_node, 1);
tree t3 = build_int_cstu (long_integer_type_node,
(HOST_WIDE_INT_1U << 31) + 1);
tree clauses = gimple_omp_for_clauses (fd->for_stmt);
- clauses = omp_find_clause (clauses, OMP_CLAUSE__REDUCTEMP_);
- reductions = OMP_CLAUSE_DECL (clauses);
- gcc_assert (TREE_CODE (reductions) == SSA_NAME);
- gimple *g = SSA_NAME_DEF_STMT (reductions);
- reductions = gimple_assign_rhs1 (g);
- OMP_CLAUSE_DECL (clauses) = reductions;
- gimple_stmt_iterator gsi2 = gsi_for_stmt (g);
+ gimple_stmt_iterator gsi2 = gsi_none ();
+ gimple *g = NULL;
+ tree mem = null_pointer_node, memv = NULL_TREE;
+ if (fd->have_reductemp)
+ {
+ tree c = omp_find_clause (clauses, OMP_CLAUSE__REDUCTEMP_);
+ reductions = OMP_CLAUSE_DECL (c);
+ gcc_assert (TREE_CODE (reductions) == SSA_NAME);
+ g = SSA_NAME_DEF_STMT (reductions);
+ reductions = gimple_assign_rhs1 (g);
+ OMP_CLAUSE_DECL (c) = reductions;
+ gsi2 = gsi_for_stmt (g);
+ }
+ else
+ {
+ if (gsi_end_p (gsip))
+ gsi2 = gsi_after_labels (region->entry);
+ else
+ gsi2 = gsip;
+ reductions = null_pointer_node;
+ }
+ if (fd->have_pointer_condtemp)
+ {
+ tree type = TREE_TYPE (condtemp);
+ memv = create_tmp_var (type);
+ TREE_ADDRESSABLE (memv) = 1;
+ unsigned HOST_WIDE_INT sz
+ = tree_to_uhwi (TYPE_SIZE_UNIT (TREE_TYPE (type)));
+ sz *= fd->lastprivate_conditional;
+ expand_omp_build_assign (&gsi2, memv, build_int_cst (type, sz),
+ false);
+ mem = build_fold_addr_expr (memv);
+ }
tree t
= build_call_expr (builtin_decl_explicit (BUILT_IN_GOMP_LOOP_START),
9, t1, t2, t2, t3, t1, null_pointer_node,
- null_pointer_node, reductions, null_pointer_node);
+ null_pointer_node, reductions, mem);
force_gimple_operand_gsi (&gsi2, t, true, NULL_TREE,
true, GSI_SAME_STMT);
- gsi_remove (&gsi2, true);
- release_ssa_name (gimple_assign_lhs (g));
+ if (fd->have_pointer_condtemp)
+ expand_omp_build_assign (&gsi2, condtemp, memv, false);
+ if (fd->have_reductemp)
+ {
+ gsi_remove (&gsi2, true);
+ release_ssa_name (gimple_assign_lhs (g));
+ }
}
switch (gimple_omp_for_kind (fd->for_stmt))
{
@@ -4286,6 +4771,33 @@ expand_omp_for_static_chunk (struct omp_region *region,
NULL_TREE, false, GSI_CONTINUE_LINKING);
assign_stmt = gimple_build_assign (startvar, t);
gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
+ if (cond_var)
+ {
+ tree itype = TREE_TYPE (cond_var);
+ /* For lastprivate(conditional:) itervar, we need some iteration
+ counter that starts at unsigned non-zero and increases.
+ Prefer as few IVs as possible, so if we can use startvar
+ itself, use that, or startvar + constant (those would be
+ incremented with step), and as last resort use the s0 + 1
+ incremented by 1. */
+ if (POINTER_TYPE_P (type)
+ || TREE_CODE (n1) != INTEGER_CST
+ || fd->loop.cond_code != LT_EXPR)
+ t = fold_build2 (PLUS_EXPR, itype, fold_convert (itype, s0),
+ build_int_cst (itype, 1));
+ else if (tree_int_cst_sgn (n1) == 1)
+ t = fold_convert (itype, t);
+ else
+ {
+ tree c = fold_convert (itype, n1);
+ c = fold_build2 (MINUS_EXPR, itype, build_int_cst (itype, 1), c);
+ t = fold_build2 (PLUS_EXPR, itype, fold_convert (itype, t), c);
+ }
+ t = force_gimple_operand_gsi (&gsi, t, false,
+ NULL_TREE, false, GSI_CONTINUE_LINKING);
+ assign_stmt = gimple_build_assign (cond_var, t);
+ gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
+ }
t = fold_convert (itype, e0);
t = fold_build2 (MULT_EXPR, itype, t, step);
@@ -4373,6 +4885,23 @@ expand_omp_for_static_chunk (struct omp_region *region,
vmain = gimple_omp_continue_control_use (cont_stmt);
vback = gimple_omp_continue_control_def (cont_stmt);
+ if (cond_var)
+ {
+ tree itype = TREE_TYPE (cond_var);
+ tree t2;
+ if (POINTER_TYPE_P (type)
+ || TREE_CODE (n1) != INTEGER_CST
+ || fd->loop.cond_code != LT_EXPR)
+ t2 = build_int_cst (itype, 1);
+ else
+ t2 = fold_convert (itype, step);
+ t2 = fold_build2 (PLUS_EXPR, itype, cond_var, t2);
+ t2 = force_gimple_operand_gsi (&gsi, t2, false,
+ NULL_TREE, true, GSI_SAME_STMT);
+ assign_stmt = gimple_build_assign (cond_var, t2);
+ gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
+ }
+
if (!gimple_omp_for_combined_p (fd->for_stmt))
{
if (POINTER_TYPE_P (type))
@@ -4416,7 +4945,7 @@ expand_omp_for_static_chunk (struct omp_region *region,
if (!gimple_omp_return_nowait_p (gsi_stmt (gsi)))
{
t = gimple_omp_return_lhs (gsi_stmt (gsi));
- if (fd->have_reductemp)
+ if (fd->have_reductemp || fd->have_pointer_condtemp)
{
tree fn;
if (t)
@@ -4427,15 +4956,22 @@ expand_omp_for_static_chunk (struct omp_region *region,
if (t)
{
gimple_call_set_lhs (g, t);
- gsi_insert_after (&gsi, gimple_build_assign (reductions,
- NOP_EXPR, t),
- GSI_SAME_STMT);
+ if (fd->have_reductemp)
+ gsi_insert_after (&gsi, gimple_build_assign (reductions,
+ NOP_EXPR, t),
+ GSI_SAME_STMT);
}
gsi_insert_after (&gsi, g, GSI_SAME_STMT);
}
else
gsi_insert_after (&gsi, omp_build_barrier (t), GSI_SAME_STMT);
}
+ else if (fd->have_pointer_condtemp)
+ {
+ tree fn = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END_NOWAIT);
+ gcall *g = gimple_build_call (fn, 0);
+ gsi_insert_after (&gsi, g, GSI_SAME_STMT);
+ }
gsi_remove (&gsi, true);
/* Connect the new blocks. */
@@ -4664,11 +5200,19 @@ expand_omp_simd (struct omp_region *region, struct omp_for_data *fd)
tree *counts = NULL;
int i;
int safelen_int = INT_MAX;
+ bool dont_vectorize = false;
tree safelen = omp_find_clause (gimple_omp_for_clauses (fd->for_stmt),
OMP_CLAUSE_SAFELEN);
tree simduid = omp_find_clause (gimple_omp_for_clauses (fd->for_stmt),
OMP_CLAUSE__SIMDUID_);
+ tree ifc = omp_find_clause (gimple_omp_for_clauses (fd->for_stmt),
+ OMP_CLAUSE_IF);
+ tree simdlen = omp_find_clause (gimple_omp_for_clauses (fd->for_stmt),
+ OMP_CLAUSE_SIMDLEN);
+ tree condtemp = omp_find_clause (gimple_omp_for_clauses (fd->for_stmt),
+ OMP_CLAUSE__CONDTEMP_);
tree n1, n2;
+ tree cond_var = condtemp ? OMP_CLAUSE_DECL (condtemp) : NULL_TREE;
if (safelen)
{
@@ -4681,6 +5225,12 @@ expand_omp_simd (struct omp_region *region, struct omp_for_data *fd)
if (safelen_int == 1)
safelen_int = 0;
}
+ if ((ifc && integer_zerop (OMP_CLAUSE_IF_EXPR (ifc)))
+ || (simdlen && integer_onep (OMP_CLAUSE_SIMDLEN_EXPR (simdlen))))
+ {
+ safelen_int = 0;
+ dont_vectorize = true;
+ }
type = TREE_TYPE (fd->loop.v);
entry_bb = region->entry;
cont_bb = region->cont;
@@ -4792,6 +5342,18 @@ expand_omp_simd (struct omp_region *region, struct omp_for_data *fd)
expand_omp_build_assign (&gsi, fd->loops[i].v, t);
}
}
+ if (cond_var)
+ {
+ if (POINTER_TYPE_P (type)
+ || TREE_CODE (n1) != INTEGER_CST
+ || fd->loop.cond_code != LT_EXPR
+ || tree_int_cst_sgn (n1) != 1)
+ expand_omp_build_assign (&gsi, cond_var,
+ build_one_cst (TREE_TYPE (cond_var)));
+ else
+ expand_omp_build_assign (&gsi, cond_var,
+ fold_convert (TREE_TYPE (cond_var), n1));
+ }
/* Remove the GIMPLE_OMP_FOR statement. */
gsi_remove (&gsi, true);
@@ -4857,6 +5419,19 @@ expand_omp_simd (struct omp_region *region, struct omp_for_data *fd)
expand_omp_build_assign (&gsi, fd->loops[i].v, t);
}
}
+ if (cond_var)
+ {
+ if (POINTER_TYPE_P (type)
+ || TREE_CODE (n1) != INTEGER_CST
+ || fd->loop.cond_code != LT_EXPR
+ || tree_int_cst_sgn (n1) != 1)
+ t = fold_build2 (PLUS_EXPR, TREE_TYPE (cond_var), cond_var,
+ build_one_cst (TREE_TYPE (cond_var)));
+ else
+ t = fold_build2 (PLUS_EXPR, TREE_TYPE (cond_var), cond_var,
+ fold_convert (TREE_TYPE (cond_var), step));
+ expand_omp_build_assign (&gsi, cond_var, t);
+ }
/* Remove GIMPLE_OMP_CONTINUE. */
gsi_remove (&gsi, true);
@@ -4963,8 +5538,17 @@ expand_omp_simd (struct omp_region *region, struct omp_for_data *fd)
&& loop->safelen > 1)
{
loop->force_vectorize = true;
+ if (simdlen && tree_fits_uhwi_p (OMP_CLAUSE_SIMDLEN_EXPR (simdlen)))
+ {
+ unsigned HOST_WIDE_INT v
+ = tree_to_uhwi (OMP_CLAUSE_SIMDLEN_EXPR (simdlen));
+ if (v < INT_MAX && v <= (unsigned HOST_WIDE_INT) loop->safelen)
+ loop->simdlen = v;
+ }
cfun->has_force_vectorize_loops = true;
}
+ else if (dont_vectorize)
+ loop->dont_vectorize = true;
}
else if (simduid)
cfun->has_simduid_loops = true;
@@ -5928,6 +6512,7 @@ expand_omp_for (struct omp_region *region, gimple *inner_stmt)
&fd, loops);
region->sched_kind = fd.sched_kind;
region->sched_modifiers = fd.sched_modifiers;
+ region->has_lastprivate_conditional = fd.lastprivate_conditional != 0;
gcc_assert (EDGE_COUNT (region->entry->succs) == 2);
BRANCH_EDGE (region->entry)->flags &= ~EDGE_ABNORMAL;
@@ -5980,14 +6565,16 @@ expand_omp_for (struct omp_region *region, gimple *inner_stmt)
switch (fd.sched_kind)
{
case OMP_CLAUSE_SCHEDULE_RUNTIME:
- if ((fd.sched_modifiers & OMP_CLAUSE_SCHEDULE_NONMONOTONIC) != 0)
+ if ((fd.sched_modifiers & OMP_CLAUSE_SCHEDULE_NONMONOTONIC) != 0
+ && fd.lastprivate_conditional == 0)
{
gcc_assert (!fd.have_ordered);
fn_index = 6;
sched = 4;
}
else if ((fd.sched_modifiers & OMP_CLAUSE_SCHEDULE_MONOTONIC) == 0
- && !fd.have_ordered)
+ && !fd.have_ordered
+ && fd.lastprivate_conditional == 0)
fn_index = 7;
else
{
@@ -5998,7 +6585,8 @@ expand_omp_for (struct omp_region *region, gimple *inner_stmt)
case OMP_CLAUSE_SCHEDULE_DYNAMIC:
case OMP_CLAUSE_SCHEDULE_GUIDED:
if ((fd.sched_modifiers & OMP_CLAUSE_SCHEDULE_MONOTONIC) == 0
- && !fd.have_ordered)
+ && !fd.have_ordered
+ && fd.lastprivate_conditional == 0)
{
fn_index = 3 + fd.sched_kind;
sched = (fd.sched_kind == OMP_CLAUSE_SCHEDULE_GUIDED) + 2;
@@ -6023,7 +6611,7 @@ expand_omp_for (struct omp_region *region, gimple *inner_stmt)
else
start_ix = ((int)BUILT_IN_GOMP_LOOP_STATIC_START) + fn_index;
next_ix = ((int)BUILT_IN_GOMP_LOOP_STATIC_NEXT) + fn_index;
- if (fd.have_reductemp)
+ if (fd.have_reductemp || fd.have_pointer_condtemp)
{
if (fd.ordered)
start_ix = (int)BUILT_IN_GOMP_LOOP_DOACROSS_START;
@@ -6146,21 +6734,62 @@ expand_omp_sections (struct omp_region *region)
vin = gimple_omp_sections_control (sections_stmt);
tree clauses = gimple_omp_sections_clauses (sections_stmt);
tree reductmp = omp_find_clause (clauses, OMP_CLAUSE__REDUCTEMP_);
- if (reductmp)
- {
- tree reductions = OMP_CLAUSE_DECL (reductmp);
- gcc_assert (TREE_CODE (reductions) == SSA_NAME);
- gimple *g = SSA_NAME_DEF_STMT (reductions);
- reductions = gimple_assign_rhs1 (g);
- OMP_CLAUSE_DECL (reductmp) = reductions;
- gimple_stmt_iterator gsi = gsi_for_stmt (g);
+ tree condtmp = omp_find_clause (clauses, OMP_CLAUSE__CONDTEMP_);
+ tree cond_var = NULL_TREE;
+ if (reductmp || condtmp)
+ {
+ tree reductions = null_pointer_node, mem = null_pointer_node;
+ tree memv = NULL_TREE, condtemp = NULL_TREE;
+ gimple_stmt_iterator gsi = gsi_none ();
+ gimple *g = NULL;
+ if (reductmp)
+ {
+ reductions = OMP_CLAUSE_DECL (reductmp);
+ gcc_assert (TREE_CODE (reductions) == SSA_NAME);
+ g = SSA_NAME_DEF_STMT (reductions);
+ reductions = gimple_assign_rhs1 (g);
+ OMP_CLAUSE_DECL (reductmp) = reductions;
+ gsi = gsi_for_stmt (g);
+ }
+ else
+ gsi = si;
+ if (condtmp)
+ {
+ condtemp = OMP_CLAUSE_DECL (condtmp);
+ tree c = omp_find_clause (OMP_CLAUSE_CHAIN (condtmp),
+ OMP_CLAUSE__CONDTEMP_);
+ cond_var = OMP_CLAUSE_DECL (c);
+ tree type = TREE_TYPE (condtemp);
+ memv = create_tmp_var (type);
+ TREE_ADDRESSABLE (memv) = 1;
+ unsigned cnt = 0;
+ for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
+ if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
+ && OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (c))
+ ++cnt;
+ unsigned HOST_WIDE_INT sz
+ = tree_to_uhwi (TYPE_SIZE_UNIT (TREE_TYPE (type))) * cnt;
+ expand_omp_build_assign (&gsi, memv, build_int_cst (type, sz),
+ false);
+ mem = build_fold_addr_expr (memv);
+ }
t = build_int_cst (unsigned_type_node, len - 1);
u = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS2_START);
- stmt = gimple_build_call (u, 3, t, reductions, null_pointer_node);
+ stmt = gimple_build_call (u, 3, t, reductions, mem);
gimple_call_set_lhs (stmt, vin);
gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
- gsi_remove (&gsi, true);
- release_ssa_name (gimple_assign_lhs (g));
+ if (condtmp)
+ {
+ expand_omp_build_assign (&gsi, condtemp, memv, false);
+ tree t = build2 (PLUS_EXPR, TREE_TYPE (cond_var),
+ vin, build_one_cst (TREE_TYPE (cond_var)));
+ expand_omp_build_assign (&gsi, cond_var, t, false);
+ }
+ if (reductmp)
+ {
+ gsi_remove (&gsi, true);
+ release_ssa_name (gimple_assign_lhs (g));
+ }
}
else if (!is_combined_parallel (region))
{
@@ -6176,7 +6805,7 @@ expand_omp_sections (struct omp_region *region)
u = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_NEXT);
stmt = gimple_build_call (u, 0);
}
- if (!reductmp)
+ if (!reductmp && !condtmp)
{
gimple_call_set_lhs (stmt, vin);
gsi_insert_after (&si, stmt, GSI_SAME_STMT);
@@ -6268,7 +6897,13 @@ expand_omp_sections (struct omp_region *region)
bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_NEXT);
stmt = gimple_build_call (bfn_decl, 0);
gimple_call_set_lhs (stmt, vnext);
- gsi_insert_after (&si, stmt, GSI_SAME_STMT);
+ gsi_insert_before (&si, stmt, GSI_SAME_STMT);
+ if (cond_var)
+ {
+ tree t = build2 (PLUS_EXPR, TREE_TYPE (cond_var),
+ vnext, build_one_cst (TREE_TYPE (cond_var)));
+ expand_omp_build_assign (&si, cond_var, t, false);
+ }
gsi_remove (&si, true);
single_succ_edge (l1_bb)->flags = EDGE_FALLTHRU;
diff --git a/gcc/omp-general.c b/gcc/omp-general.c
index 356772f..8086f9a 100644
--- a/gcc/omp-general.c
+++ b/gcc/omp-general.c
@@ -168,6 +168,10 @@ omp_extract_for_data (gomp_for *for_stmt, struct omp_for_data *fd,
fd->have_nowait = distribute || simd;
fd->have_ordered = false;
fd->have_reductemp = false;
+ fd->have_pointer_condtemp = false;
+ fd->have_scantemp = false;
+ fd->have_nonctrl_scantemp = false;
+ fd->lastprivate_conditional = 0;
fd->tiling = NULL_TREE;
fd->collapse = 1;
fd->ordered = 0;
@@ -220,6 +224,21 @@ omp_extract_for_data (gomp_for *for_stmt, struct omp_for_data *fd,
break;
case OMP_CLAUSE__REDUCTEMP_:
fd->have_reductemp = true;
+ break;
+ case OMP_CLAUSE_LASTPRIVATE:
+ if (OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (t))
+ fd->lastprivate_conditional++;
+ break;
+ case OMP_CLAUSE__CONDTEMP_:
+ if (POINTER_TYPE_P (TREE_TYPE (OMP_CLAUSE_DECL (t))))
+ fd->have_pointer_condtemp = true;
+ break;
+ case OMP_CLAUSE__SCANTEMP_:
+ fd->have_scantemp = true;
+ if (!OMP_CLAUSE__SCANTEMP__ALLOC (t)
+ && !OMP_CLAUSE__SCANTEMP__CONTROL (t))
+ fd->have_nonctrl_scantemp = true;
+ break;
default:
break;
}
@@ -469,7 +488,7 @@ omp_max_vf (void)
return 1;
auto_vector_sizes sizes;
- targetm.vectorize.autovectorize_vector_sizes (&sizes);
+ targetm.vectorize.autovectorize_vector_sizes (&sizes, true);
if (!sizes.is_empty ())
{
poly_uint64 vf = 0;
@@ -608,9 +627,138 @@ oacc_set_fn_attrib (tree fn, tree clauses, vec<tree> *args)
}
}
-/* Process the routine's dimension clauess to generate an attribute
- value. Issue diagnostics as appropriate. We default to SEQ
- (OpenACC 2.5 clarifies this). All dimensions have a size of zero
+/* Verify OpenACC routine clauses.
+
+ Returns 0 if FNDECL should be marked with an OpenACC 'routine' directive, 1
+ if it has already been marked in compatible way, and -1 if incompatible.
+ Upon returning, the chain of clauses will contain exactly one clause
+ specifying the level of parallelism. */
+
+int
+oacc_verify_routine_clauses (tree fndecl, tree *clauses, location_t loc,
+ const char *routine_str)
+{
+ tree c_level = NULL_TREE;
+ tree c_p = NULL_TREE;
+ for (tree c = *clauses; c; c_p = c, c = OMP_CLAUSE_CHAIN (c))
+ switch (OMP_CLAUSE_CODE (c))
+ {
+ case OMP_CLAUSE_GANG:
+ case OMP_CLAUSE_WORKER:
+ case OMP_CLAUSE_VECTOR:
+ case OMP_CLAUSE_SEQ:
+ if (c_level == NULL_TREE)
+ c_level = c;
+ else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_CODE (c_level))
+ {
+ /* This has already been diagnosed in the front ends. */
+ /* Drop the duplicate clause. */
+ gcc_checking_assert (c_p != NULL_TREE);
+ OMP_CLAUSE_CHAIN (c_p) = OMP_CLAUSE_CHAIN (c);
+ c = c_p;
+ }
+ else
+ {
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "%qs specifies a conflicting level of parallelism",
+ omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
+ inform (OMP_CLAUSE_LOCATION (c_level),
+ "... to the previous %qs clause here",
+ omp_clause_code_name[OMP_CLAUSE_CODE (c_level)]);
+ /* Drop the conflicting clause. */
+ gcc_checking_assert (c_p != NULL_TREE);
+ OMP_CLAUSE_CHAIN (c_p) = OMP_CLAUSE_CHAIN (c);
+ c = c_p;
+ }
+ break;
+ default:
+ gcc_unreachable ();
+ }
+ if (c_level == NULL_TREE)
+ {
+ /* Default to an implicit 'seq' clause. */
+ c_level = build_omp_clause (loc, OMP_CLAUSE_SEQ);
+ OMP_CLAUSE_CHAIN (c_level) = *clauses;
+ *clauses = c_level;
+ }
+ /* In *clauses, we now have exactly one clause specifying the level of
+ parallelism. */
+
+ tree attr
+ = lookup_attribute ("omp declare target", DECL_ATTRIBUTES (fndecl));
+ if (attr != NULL_TREE)
+ {
+ /* If a "#pragma acc routine" has already been applied, just verify
+ this one for compatibility. */
+ /* Collect previous directive's clauses. */
+ tree c_level_p = NULL_TREE;
+ for (tree c = TREE_VALUE (attr); c; c = OMP_CLAUSE_CHAIN (c))
+ switch (OMP_CLAUSE_CODE (c))
+ {
+ case OMP_CLAUSE_GANG:
+ case OMP_CLAUSE_WORKER:
+ case OMP_CLAUSE_VECTOR:
+ case OMP_CLAUSE_SEQ:
+ gcc_checking_assert (c_level_p == NULL_TREE);
+ c_level_p = c;
+ break;
+ default:
+ gcc_unreachable ();
+ }
+ gcc_checking_assert (c_level_p != NULL_TREE);
+ /* ..., and compare to current directive's, which we've already collected
+ above. */
+ tree c_diag;
+ tree c_diag_p;
+ /* Matching level of parallelism? */
+ if (OMP_CLAUSE_CODE (c_level) != OMP_CLAUSE_CODE (c_level_p))
+ {
+ c_diag = c_level;
+ c_diag_p = c_level_p;
+ goto incompatible;
+ }
+ /* Compatible. */
+ return 1;
+
+ incompatible:
+ if (c_diag != NULL_TREE)
+ error_at (OMP_CLAUSE_LOCATION (c_diag),
+ "incompatible %qs clause when applying"
+ " %<%s%> to %qD, which has already been"
+ " marked with an OpenACC 'routine' directive",
+ omp_clause_code_name[OMP_CLAUSE_CODE (c_diag)],
+ routine_str, fndecl);
+ else if (c_diag_p != NULL_TREE)
+ error_at (loc,
+ "missing %qs clause when applying"
+ " %<%s%> to %qD, which has already been"
+ " marked with an OpenACC 'routine' directive",
+ omp_clause_code_name[OMP_CLAUSE_CODE (c_diag_p)],
+ routine_str, fndecl);
+ else
+ gcc_unreachable ();
+ if (c_diag_p != NULL_TREE)
+ inform (OMP_CLAUSE_LOCATION (c_diag_p),
+ "... with %qs clause here",
+ omp_clause_code_name[OMP_CLAUSE_CODE (c_diag_p)]);
+ else
+ {
+ /* In the front ends, we don't preserve location information for the
+ OpenACC routine directive itself. However, that of c_level_p
+ should be close. */
+ location_t loc_routine = OMP_CLAUSE_LOCATION (c_level_p);
+ inform (loc_routine, "... without %qs clause near to here",
+ omp_clause_code_name[OMP_CLAUSE_CODE (c_diag)]);
+ }
+ /* Incompatible. */
+ return -1;
+ }
+
+ return 0;
+}
+
+/* Process the OpenACC 'routine' directive clauses to generate an attribute
+ for the level of parallelism. All dimensions have a size of zero
(dynamic). TREE_PURPOSE is set to indicate whether that dimension
can have a loop partitioned on it. non-zero indicates
yes, zero indicates no. By construction once a non-zero has been
@@ -632,16 +780,10 @@ oacc_build_routine_dims (tree clauses)
for (ix = GOMP_DIM_MAX + 1; ix--;)
if (OMP_CLAUSE_CODE (clauses) == ids[ix])
{
- if (level >= 0)
- error_at (OMP_CLAUSE_LOCATION (clauses),
- "multiple loop axes specified for routine");
level = ix;
break;
}
-
- /* Default to SEQ. */
- if (level < 0)
- level = GOMP_DIM_MAX;
+ gcc_checking_assert (level >= 0);
tree dims = NULL_TREE;
diff --git a/gcc/omp-general.h b/gcc/omp-general.h
index 60faa52..80d42af 100644
--- a/gcc/omp-general.h
+++ b/gcc/omp-general.h
@@ -63,6 +63,8 @@ struct omp_for_data
int collapse; /* Collapsed loops, 1 for a non-collapsed loop. */
int ordered;
bool have_nowait, have_ordered, simd_schedule, have_reductemp;
+ bool have_pointer_condtemp, have_scantemp, have_nonctrl_scantemp;
+ int lastprivate_conditional;
unsigned char sched_modifiers;
enum omp_clause_schedule_kind sched_kind;
struct omp_for_data_loop *loops;
@@ -84,6 +86,8 @@ extern tree oacc_launch_pack (unsigned code, tree device, unsigned op);
extern tree oacc_replace_fn_attrib_attr (tree attribs, tree dims);
extern void oacc_replace_fn_attrib (tree fn, tree dims);
extern void oacc_set_fn_attrib (tree fn, tree clauses, vec<tree> *args);
+extern int oacc_verify_routine_clauses (tree, tree *, location_t,
+ const char *);
extern tree oacc_build_routine_dims (tree clauses);
extern tree oacc_get_fn_attrib (tree fn);
extern bool offloading_function_p (tree fn);
diff --git a/gcc/omp-low.c b/gcc/omp-low.c
index 874781a..98a9df5 100644
--- a/gcc/omp-low.c
+++ b/gcc/omp-low.c
@@ -119,10 +119,14 @@ struct omp_context
and then offsets (if constant, otherwise NULL) for each entry. */
vec<tree> task_reductions;
- /* And a hash map from the reduction clauses to the registered array
+ /* A hash map from the reduction clauses to the registered array
elts. */
hash_map<tree, unsigned> *task_reduction_map;
+ /* And a hash map from the lastprivate(conditional:) variables to their
+ corresponding tracking loop iteration variables. */
+ hash_map<tree, tree> *lastprivate_conditional_map;
+
/* Nesting depth of this context. Used to beautify error messages re
invalid gotos. The outermost ctx is depth 1, with depth 0 being
reserved for the main body of the function. */
@@ -133,6 +137,16 @@ struct omp_context
/* True if this construct can be cancelled. */
bool cancellable;
+
+ /* True if lower_omp_1 should look up lastprivate conditional in parent
+ context. */
+ bool combined_into_simd_safelen0;
+
+ /* True if there is nested scan context with inclusive clause. */
+ bool scan_inclusive;
+
+ /* True if there is nested scan context with exclusive clause. */
+ bool scan_exclusive;
};
static splay_tree all_contexts;
@@ -955,6 +969,8 @@ delete_omp_context (splay_tree_value value)
delete ctx->task_reduction_map;
}
+ delete ctx->lastprivate_conditional_map;
+
XDELETE (ctx);
}
@@ -1407,6 +1423,19 @@ scan_sharing_clauses (tree clauses, omp_context *ctx)
install_var_local (decl, ctx);
break;
+ case OMP_CLAUSE__CONDTEMP_:
+ decl = OMP_CLAUSE_DECL (c);
+ if (is_parallel_ctx (ctx))
+ {
+ install_var_field (decl, false, 3, ctx);
+ install_var_local (decl, ctx);
+ }
+ else if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
+ && (gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
+ && !OMP_CLAUSE__CONDTEMP__ITER (c))
+ install_var_local (decl, ctx);
+ break;
+
case OMP_CLAUSE__CACHE_:
default:
gcc_unreachable ();
@@ -1581,6 +1610,7 @@ scan_sharing_clauses (tree clauses, omp_context *ctx)
case OMP_CLAUSE__SIMT_:
case OMP_CLAUSE_IF_PRESENT:
case OMP_CLAUSE_FINALIZE:
+ case OMP_CLAUSE__CONDTEMP_:
break;
case OMP_CLAUSE__CACHE_:
@@ -2550,6 +2580,10 @@ check_omp_nesting_restrictions (gimple *stmt, omp_context *ctx)
if (ctx != NULL)
{
+ if (gimple_code (ctx->stmt) == GIMPLE_OMP_SCAN
+ && ctx->outer
+ && gimple_code (ctx->outer->stmt) == GIMPLE_OMP_FOR)
+ ctx = ctx->outer;
if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
&& gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
{
@@ -2576,7 +2610,8 @@ check_omp_nesting_restrictions (gimple *stmt, omp_context *ctx)
}
}
else if (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_LOAD
- || gimple_code (stmt) == GIMPLE_OMP_ATOMIC_STORE)
+ || gimple_code (stmt) == GIMPLE_OMP_ATOMIC_STORE
+ || gimple_code (stmt) == GIMPLE_OMP_SCAN)
return true;
error_at (gimple_location (stmt),
"OpenMP constructs other than %<#pragma omp ordered simd%>"
@@ -3087,6 +3122,7 @@ check_omp_nesting_restrictions (gimple *stmt, omp_context *ctx)
case GF_OMP_TARGET_KIND_OACC_UPDATE: stmt_name = "update"; break;
case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
stmt_name = "enter/exit data"; break;
+ case GF_OMP_TARGET_KIND_OACC_DECLARE: stmt_name = "declare"; break;
case GF_OMP_TARGET_KIND_OACC_HOST_DATA: stmt_name = "host_data";
break;
default: gcc_unreachable ();
@@ -3283,8 +3319,8 @@ scan_omp_1_stmt (gimple_stmt_iterator *gsi, bool *handled_ops_p,
break;
case GIMPLE_OMP_FOR:
- if (((gimple_omp_for_kind (as_a <gomp_for *> (stmt))
- & GF_OMP_FOR_KIND_MASK) == GF_OMP_FOR_KIND_SIMD)
+ if ((gimple_omp_for_kind (as_a <gomp_for *> (stmt))
+ == GF_OMP_FOR_KIND_SIMD)
&& omp_maybe_offloaded_ctx (ctx)
&& omp_max_simt_vf ())
scan_omp_simd (gsi, as_a <gomp_for *> (stmt), ctx);
@@ -3300,6 +3336,15 @@ scan_omp_1_stmt (gimple_stmt_iterator *gsi, bool *handled_ops_p,
scan_omp_single (as_a <gomp_single *> (stmt), ctx);
break;
+ case GIMPLE_OMP_SCAN:
+ if (tree clauses = gimple_omp_scan_clauses (as_a <gomp_scan *> (stmt)))
+ {
+ if (OMP_CLAUSE_CODE (clauses) == OMP_CLAUSE_INCLUSIVE)
+ ctx->scan_inclusive = true;
+ else if (OMP_CLAUSE_CODE (clauses) == OMP_CLAUSE_EXCLUSIVE)
+ ctx->scan_exclusive = true;
+ }
+ /* FALLTHRU */
case GIMPLE_OMP_SECTION:
case GIMPLE_OMP_MASTER:
case GIMPLE_OMP_ORDERED:
@@ -3600,7 +3645,7 @@ omp_clause_aligned_alignment (tree clause)
unsigned int al = 1;
opt_scalar_mode mode_iter;
auto_vector_sizes sizes;
- targetm.vectorize.autovectorize_vector_sizes (&sizes);
+ targetm.vectorize.autovectorize_vector_sizes (&sizes, true);
poly_uint64 vs = 0;
for (unsigned int i = 0; i < sizes.length (); ++i)
vs = ordered_max (vs, sizes[i]);
@@ -3641,6 +3686,7 @@ struct omplow_simd_context {
omplow_simd_context () { memset (this, 0, sizeof (*this)); }
tree idx;
tree lane;
+ tree lastlane;
vec<tree, va_heap> simt_eargs;
gimple_seq simt_dlist;
poly_uint64_pod max_vf;
@@ -3652,7 +3698,9 @@ struct omplow_simd_context {
static bool
lower_rec_simd_input_clauses (tree new_var, omp_context *ctx,
- omplow_simd_context *sctx, tree &ivar, tree &lvar)
+ omplow_simd_context *sctx, tree &ivar,
+ tree &lvar, tree *rvar = NULL,
+ tree *rvar2 = NULL)
{
if (known_eq (sctx->max_vf, 0U))
{
@@ -3708,10 +3756,51 @@ lower_rec_simd_input_clauses (tree new_var, omp_context *ctx,
= tree_cons (get_identifier ("omp simd array"), NULL,
DECL_ATTRIBUTES (avar));
gimple_add_tmp_var (avar);
- ivar = build4 (ARRAY_REF, TREE_TYPE (new_var), avar, sctx->idx,
+ tree iavar = avar;
+ if (rvar)
+ {
+ /* For inscan reductions, create another array temporary,
+ which will hold the reduced value. */
+ iavar = create_tmp_var_raw (atype);
+ if (TREE_ADDRESSABLE (new_var))
+ TREE_ADDRESSABLE (iavar) = 1;
+ DECL_ATTRIBUTES (iavar)
+ = tree_cons (get_identifier ("omp simd array"), NULL,
+ tree_cons (get_identifier ("omp simd inscan"), NULL,
+ DECL_ATTRIBUTES (iavar)));
+ gimple_add_tmp_var (iavar);
+ ctx->cb.decl_map->put (avar, iavar);
+ if (sctx->lastlane == NULL_TREE)
+ sctx->lastlane = create_tmp_var (unsigned_type_node);
+ *rvar = build4 (ARRAY_REF, TREE_TYPE (new_var), iavar,
+ sctx->lastlane, NULL_TREE, NULL_TREE);
+ TREE_THIS_NOTRAP (*rvar) = 1;
+
+ if (ctx->scan_exclusive)
+ {
+ /* And for exclusive scan yet another one, which will
+ hold the value during the scan phase. */
+ tree savar = create_tmp_var_raw (atype);
+ if (TREE_ADDRESSABLE (new_var))
+ TREE_ADDRESSABLE (savar) = 1;
+ DECL_ATTRIBUTES (savar)
+ = tree_cons (get_identifier ("omp simd array"), NULL,
+ tree_cons (get_identifier ("omp simd inscan "
+ "exclusive"), NULL,
+ DECL_ATTRIBUTES (savar)));
+ gimple_add_tmp_var (savar);
+ ctx->cb.decl_map->put (iavar, savar);
+ *rvar2 = build4 (ARRAY_REF, TREE_TYPE (new_var), savar,
+ sctx->idx, NULL_TREE, NULL_TREE);
+ TREE_THIS_NOTRAP (*rvar2) = 1;
+ }
+ }
+ ivar = build4 (ARRAY_REF, TREE_TYPE (new_var), iavar, sctx->idx,
NULL_TREE, NULL_TREE);
lvar = build4 (ARRAY_REF, TREE_TYPE (new_var), avar, sctx->lane,
NULL_TREE, NULL_TREE);
+ TREE_THIS_NOTRAP (ivar) = 1;
+ TREE_THIS_NOTRAP (lvar) = 1;
}
if (DECL_P (new_var))
{
@@ -3772,7 +3861,7 @@ static void
lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
omp_context *ctx, struct omp_for_data *fd)
{
- tree c, dtor, copyin_seq, x, ptr;
+ tree c, copyin_seq, x, ptr;
bool copyin_by_ref = false;
bool lastprivate_firstprivate = false;
bool reduction_omp_orig_ref = false;
@@ -3782,7 +3871,8 @@ lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
omplow_simd_context sctx = omplow_simd_context ();
tree simt_lane = NULL_TREE, simtrec = NULL_TREE;
tree ivar = NULL_TREE, lvar = NULL_TREE, uid = NULL_TREE;
- gimple_seq llist[3] = { };
+ gimple_seq llist[4] = { };
+ tree nonconst_simd_if = NULL_TREE;
copyin_seq = NULL;
sctx.is_simt = is_simd && omp_find_clause (clauses, OMP_CLAUSE__SIMT_);
@@ -3804,12 +3894,39 @@ lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
case OMP_CLAUSE_LASTPRIVATE:
if (is_variable_sized (OMP_CLAUSE_DECL (c)))
sctx.max_vf = 1;
+ else if (omp_is_reference (OMP_CLAUSE_DECL (c)))
+ {
+ tree rtype = TREE_TYPE (TREE_TYPE (OMP_CLAUSE_DECL (c)));
+ if (!TREE_CONSTANT (TYPE_SIZE_UNIT (rtype)))
+ sctx.max_vf = 1;
+ }
break;
case OMP_CLAUSE_REDUCTION:
case OMP_CLAUSE_IN_REDUCTION:
if (TREE_CODE (OMP_CLAUSE_DECL (c)) == MEM_REF
|| is_variable_sized (OMP_CLAUSE_DECL (c)))
sctx.max_vf = 1;
+ else if (omp_is_reference (OMP_CLAUSE_DECL (c)))
+ {
+ tree rtype = TREE_TYPE (TREE_TYPE (OMP_CLAUSE_DECL (c)));
+ if (!TREE_CONSTANT (TYPE_SIZE_UNIT (rtype)))
+ sctx.max_vf = 1;
+ }
+ break;
+ case OMP_CLAUSE_IF:
+ if (integer_zerop (OMP_CLAUSE_IF_EXPR (c)))
+ sctx.max_vf = 1;
+ else if (TREE_CODE (OMP_CLAUSE_IF_EXPR (c)) != INTEGER_CST)
+ nonconst_simd_if = OMP_CLAUSE_IF_EXPR (c);
+ break;
+ case OMP_CLAUSE_SIMDLEN:
+ if (integer_onep (OMP_CLAUSE_SIMDLEN_EXPR (c)))
+ sctx.max_vf = 1;
+ break;
+ case OMP_CLAUSE__CONDTEMP_:
+ /* FIXME: lastprivate(conditional:) not handled for SIMT yet. */
+ if (sctx.is_simt)
+ sctx.max_vf = 1;
break;
default:
continue;
@@ -4024,6 +4141,11 @@ lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
DECL_HAS_VALUE_EXPR_P (new_var) = 1;
}
continue;
+ case OMP_CLAUSE__CONDTEMP_:
+ if (is_parallel_ctx (ctx)
+ || (is_simd && !OMP_CLAUSE__CONDTEMP__ITER (c)))
+ break;
+ continue;
default:
continue;
}
@@ -4426,12 +4548,7 @@ lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
x = lang_hooks.decls.omp_clause_dtor
(c, build_simple_mem_ref (y2));
if (x)
- {
- gimple_seq tseq = NULL;
- dtor = x;
- gimplify_stmt (&dtor, &tseq);
- gimple_seq_add_seq (dlist, tseq);
- }
+ gimplify_and_add (x, dlist);
}
}
else
@@ -4618,8 +4735,8 @@ lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
/* For reduction in SIMD loop, defer adding the
initialization of the reference, because if we decide
to use SIMD array for it, the initilization could cause
- expansion ICE. */
- if (c_kind == OMP_CLAUSE_REDUCTION && is_simd)
+ expansion ICE. Ditto for other privatization clauses. */
+ if (is_simd)
x = NULL_TREE;
else
{
@@ -4690,6 +4807,20 @@ lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
TREE_NO_WARNING (var) = 1;
break;
+ case OMP_CLAUSE__CONDTEMP_:
+ if (is_parallel_ctx (ctx))
+ {
+ x = build_receiver_ref (var, false, ctx);
+ SET_DECL_VALUE_EXPR (new_var, x);
+ DECL_HAS_VALUE_EXPR_P (new_var) = 1;
+ }
+ else if (is_simd && !OMP_CLAUSE__CONDTEMP__ITER (c))
+ {
+ x = build_zero_cst (TREE_TYPE (var));
+ goto do_private;
+ }
+ break;
+
case OMP_CLAUSE_LASTPRIVATE:
if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
break;
@@ -4715,29 +4846,97 @@ lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
{
tree y = lang_hooks.decls.omp_clause_dtor (c, new_var);
if ((TREE_ADDRESSABLE (new_var) || nx || y
- || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE)
+ || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
+ || OMP_CLAUSE_CODE (c) == OMP_CLAUSE__CONDTEMP_
+ || omp_is_reference (var))
&& lower_rec_simd_input_clauses (new_var, ctx, &sctx,
ivar, lvar))
{
+ if (omp_is_reference (var))
+ {
+ gcc_assert (TREE_CODE (new_var) == MEM_REF);
+ tree new_vard = TREE_OPERAND (new_var, 0);
+ gcc_assert (DECL_P (new_vard));
+ SET_DECL_VALUE_EXPR (new_vard,
+ build_fold_addr_expr (lvar));
+ DECL_HAS_VALUE_EXPR_P (new_vard) = 1;
+ }
+
if (nx)
x = lang_hooks.decls.omp_clause_default_ctor
(c, unshare_expr (ivar), x);
+ else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE__CONDTEMP_)
+ {
+ x = build2 (MODIFY_EXPR, TREE_TYPE (ivar),
+ unshare_expr (ivar), x);
+ nx = x;
+ }
if (nx && x)
gimplify_and_add (x, &llist[0]);
+ if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
+ && OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (c))
+ {
+ tree v = new_var;
+ if (!DECL_P (v))
+ {
+ gcc_assert (TREE_CODE (v) == MEM_REF);
+ v = TREE_OPERAND (v, 0);
+ gcc_assert (DECL_P (v));
+ }
+ v = *ctx->lastprivate_conditional_map->get (v);
+ tree t = create_tmp_var (TREE_TYPE (v));
+ tree z = build_zero_cst (TREE_TYPE (v));
+ tree orig_v
+ = build_outer_var_ref (var, ctx,
+ OMP_CLAUSE_LASTPRIVATE);
+ gimple_seq_add_stmt (dlist,
+ gimple_build_assign (t, z));
+ gcc_assert (DECL_HAS_VALUE_EXPR_P (v));
+ tree civar = DECL_VALUE_EXPR (v);
+ gcc_assert (TREE_CODE (civar) == ARRAY_REF);
+ civar = unshare_expr (civar);
+ TREE_OPERAND (civar, 1) = sctx.idx;
+ x = build2 (MODIFY_EXPR, TREE_TYPE (t), t,
+ unshare_expr (civar));
+ x = build2 (COMPOUND_EXPR, TREE_TYPE (orig_v), x,
+ build2 (MODIFY_EXPR, TREE_TYPE (orig_v),
+ orig_v, unshare_expr (ivar)));
+ tree cond = build2 (LT_EXPR, boolean_type_node, t,
+ civar);
+ x = build3 (COND_EXPR, void_type_node, cond, x,
+ void_node);
+ gimple_seq tseq = NULL;
+ gimplify_and_add (x, &tseq);
+ if (ctx->outer)
+ lower_omp (&tseq, ctx->outer);
+ gimple_seq_add_seq (&llist[1], tseq);
+ }
if (y)
{
y = lang_hooks.decls.omp_clause_dtor (c, ivar);
if (y)
- {
- gimple_seq tseq = NULL;
-
- dtor = y;
- gimplify_stmt (&dtor, &tseq);
- gimple_seq_add_seq (&llist[1], tseq);
- }
+ gimplify_and_add (y, &llist[1]);
}
break;
}
+ if (omp_is_reference (var))
+ {
+ gcc_assert (TREE_CODE (new_var) == MEM_REF);
+ tree new_vard = TREE_OPERAND (new_var, 0);
+ gcc_assert (DECL_P (new_vard));
+ tree type = TREE_TYPE (TREE_TYPE (new_vard));
+ x = TYPE_SIZE_UNIT (type);
+ if (TREE_CONSTANT (x))
+ {
+ x = create_tmp_var_raw (type, get_name (var));
+ gimple_add_tmp_var (x);
+ TREE_ADDRESSABLE (x) = 1;
+ x = build_fold_addr_expr_loc (clause_loc, x);
+ x = fold_convert_loc (clause_loc,
+ TREE_TYPE (new_vard), x);
+ gimplify_assign (new_vard, x, ilist);
+ }
+ }
}
if (nx)
gimplify_and_add (nx, ilist);
@@ -4746,13 +4945,7 @@ lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
do_dtor:
x = lang_hooks.decls.omp_clause_dtor (c, new_var);
if (x)
- {
- gimple_seq tseq = NULL;
-
- dtor = x;
- gimplify_stmt (&dtor, &tseq);
- gimple_seq_add_seq (dlist, tseq);
- }
+ gimplify_and_add (x, dlist);
break;
case OMP_CLAUSE_LINEAR:
@@ -4825,6 +5018,28 @@ lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
if (OMP_CLAUSE_LINEAR_ARRAY (c))
{
+ if (omp_is_reference (var))
+ {
+ gcc_assert (TREE_CODE (new_var) == MEM_REF);
+ tree new_vard = TREE_OPERAND (new_var, 0);
+ gcc_assert (DECL_P (new_vard));
+ tree type = TREE_TYPE (TREE_TYPE (new_vard));
+ nx = TYPE_SIZE_UNIT (type);
+ if (TREE_CONSTANT (nx))
+ {
+ nx = create_tmp_var_raw (type,
+ get_name (var));
+ gimple_add_tmp_var (nx);
+ TREE_ADDRESSABLE (nx) = 1;
+ nx = build_fold_addr_expr_loc (clause_loc,
+ nx);
+ nx = fold_convert_loc (clause_loc,
+ TREE_TYPE (new_vard),
+ nx);
+ gimplify_assign (new_vard, nx, ilist);
+ }
+ }
+
x = lang_hooks.decls.omp_clause_linear_ctor
(c, new_var, x, t);
gimplify_and_add (x, ilist);
@@ -4839,10 +5054,20 @@ lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
}
if ((OMP_CLAUSE_CODE (c) != OMP_CLAUSE_LINEAR
- || TREE_ADDRESSABLE (new_var))
+ || TREE_ADDRESSABLE (new_var)
+ || omp_is_reference (var))
&& lower_rec_simd_input_clauses (new_var, ctx, &sctx,
ivar, lvar))
{
+ if (omp_is_reference (var))
+ {
+ gcc_assert (TREE_CODE (new_var) == MEM_REF);
+ tree new_vard = TREE_OPERAND (new_var, 0);
+ gcc_assert (DECL_P (new_vard));
+ SET_DECL_VALUE_EXPR (new_vard,
+ build_fold_addr_expr (lvar));
+ DECL_HAS_VALUE_EXPR_P (new_vard) = 1;
+ }
if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR)
{
tree iv = create_tmp_var (TREE_TYPE (new_var));
@@ -4868,14 +5093,26 @@ lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
gimplify_and_add (x, &llist[0]);
x = lang_hooks.decls.omp_clause_dtor (c, ivar);
if (x)
+ gimplify_and_add (x, &llist[1]);
+ break;
+ }
+ if (omp_is_reference (var))
+ {
+ gcc_assert (TREE_CODE (new_var) == MEM_REF);
+ tree new_vard = TREE_OPERAND (new_var, 0);
+ gcc_assert (DECL_P (new_vard));
+ tree type = TREE_TYPE (TREE_TYPE (new_vard));
+ nx = TYPE_SIZE_UNIT (type);
+ if (TREE_CONSTANT (nx))
{
- gimple_seq tseq = NULL;
-
- dtor = x;
- gimplify_stmt (&dtor, &tseq);
- gimple_seq_add_seq (&llist[1], tseq);
+ nx = create_tmp_var_raw (type, get_name (var));
+ gimple_add_tmp_var (nx);
+ TREE_ADDRESSABLE (nx) = 1;
+ nx = build_fold_addr_expr_loc (clause_loc, nx);
+ nx = fold_convert_loc (clause_loc,
+ TREE_TYPE (new_vard), nx);
+ gimplify_assign (new_vard, nx, ilist);
}
- break;
}
}
x = lang_hooks.decls.omp_clause_copy_ctor
@@ -4952,9 +5189,15 @@ lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
new_vard = TREE_OPERAND (new_var, 0);
gcc_assert (DECL_P (new_vard));
}
+ tree rvar = NULL_TREE, *rvarp = NULL, rvar2 = NULL_TREE;
+ if (is_simd
+ && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
+ && OMP_CLAUSE_REDUCTION_INSCAN (c))
+ rvarp = &rvar;
if (is_simd
&& lower_rec_simd_input_clauses (new_var, ctx, &sctx,
- ivar, lvar))
+ ivar, lvar, rvarp,
+ &rvar2))
{
if (new_vard == new_var)
{
@@ -4970,6 +5213,98 @@ lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
x = lang_hooks.decls.omp_clause_default_ctor
(c, unshare_expr (ivar),
build_outer_var_ref (var, ctx));
+ if (rvarp)
+ {
+ if (x)
+ {
+ gimplify_and_add (x, &llist[0]);
+
+ tree ivar2 = unshare_expr (lvar);
+ TREE_OPERAND (ivar2, 1) = sctx.idx;
+ x = lang_hooks.decls.omp_clause_default_ctor
+ (c, ivar2, build_outer_var_ref (var, ctx));
+ gimplify_and_add (x, &llist[0]);
+
+ if (rvar2)
+ {
+ x = lang_hooks.decls.omp_clause_default_ctor
+ (c, unshare_expr (rvar2),
+ build_outer_var_ref (var, ctx));
+ gimplify_and_add (x, &llist[0]);
+ }
+
+ /* For types that need construction, add another
+ private var which will be default constructed
+ and optionally initialized with
+ OMP_CLAUSE_REDUCTION_GIMPLE_INIT, as in the
+ loop we want to assign this value instead of
+ constructing and destructing it in each
+ iteration. */
+ tree nv = create_tmp_var_raw (TREE_TYPE (ivar));
+ gimple_add_tmp_var (nv);
+ ctx->cb.decl_map->put (TREE_OPERAND (rvar2
+ ? rvar2
+ : ivar, 0),
+ nv);
+ x = lang_hooks.decls.omp_clause_default_ctor
+ (c, nv, build_outer_var_ref (var, ctx));
+ gimplify_and_add (x, ilist);
+
+ if (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c))
+ {
+ tseq = OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c);
+ x = DECL_VALUE_EXPR (new_vard);
+ tree vexpr = nv;
+ if (new_vard != new_var)
+ vexpr = build_fold_addr_expr (nv);
+ SET_DECL_VALUE_EXPR (new_vard, vexpr);
+ lower_omp (&tseq, ctx);
+ SET_DECL_VALUE_EXPR (new_vard, x);
+ gimple_seq_add_seq (ilist, tseq);
+ OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c) = NULL;
+ }
+
+ x = lang_hooks.decls.omp_clause_dtor (c, nv);
+ if (x)
+ gimplify_and_add (x, dlist);
+ }
+
+ tree ref = build_outer_var_ref (var, ctx);
+ x = unshare_expr (ivar);
+ x = lang_hooks.decls.omp_clause_assign_op (c, x,
+ ref);
+ gimplify_and_add (x, &llist[0]);
+
+ ref = build_outer_var_ref (var, ctx);
+ x = lang_hooks.decls.omp_clause_assign_op (c, ref,
+ rvar);
+ gimplify_and_add (x, &llist[3]);
+
+ DECL_HAS_VALUE_EXPR_P (placeholder) = 0;
+ if (new_vard == new_var)
+ SET_DECL_VALUE_EXPR (new_var, lvar);
+ else
+ SET_DECL_VALUE_EXPR (new_vard,
+ build_fold_addr_expr (lvar));
+
+ x = lang_hooks.decls.omp_clause_dtor (c, ivar);
+ if (x)
+ gimplify_and_add (x, &llist[1]);
+
+ tree ivar2 = unshare_expr (lvar);
+ TREE_OPERAND (ivar2, 1) = sctx.idx;
+ x = lang_hooks.decls.omp_clause_dtor (c, ivar2);
+ if (x)
+ gimplify_and_add (x, &llist[1]);
+
+ if (rvar2)
+ {
+ x = lang_hooks.decls.omp_clause_dtor (c, rvar2);
+ if (x)
+ gimplify_and_add (x, &llist[1]);
+ }
+ break;
+ }
if (x)
gimplify_and_add (x, &llist[0]);
if (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c))
@@ -4991,12 +5326,7 @@ lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
build_fold_addr_expr (lvar));
x = lang_hooks.decls.omp_clause_dtor (c, ivar);
if (x)
- {
- tseq = NULL;
- dtor = x;
- gimplify_stmt (&dtor, &tseq);
- gimple_seq_add_seq (&llist[1], tseq);
- }
+ gimplify_and_add (x, &llist[1]);
break;
}
/* If this is a reference to constant size reduction var
@@ -5037,6 +5367,66 @@ lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
: build_outer_var_ref (var, ctx));
if (x)
gimplify_and_add (x, ilist);
+
+ if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
+ && OMP_CLAUSE_REDUCTION_INSCAN (c))
+ {
+ if (x || (!is_simd
+ && OMP_CLAUSE_REDUCTION_OMP_ORIG_REF (c)))
+ {
+ tree nv = create_tmp_var_raw (TREE_TYPE (new_var));
+ gimple_add_tmp_var (nv);
+ ctx->cb.decl_map->put (new_vard, nv);
+ x = lang_hooks.decls.omp_clause_default_ctor
+ (c, nv, build_outer_var_ref (var, ctx));
+ if (x)
+ gimplify_and_add (x, ilist);
+ if (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c))
+ {
+ tseq = OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c);
+ tree vexpr = nv;
+ if (new_vard != new_var)
+ vexpr = build_fold_addr_expr (nv);
+ SET_DECL_VALUE_EXPR (new_vard, vexpr);
+ DECL_HAS_VALUE_EXPR_P (new_vard) = 1;
+ lower_omp (&tseq, ctx);
+ SET_DECL_VALUE_EXPR (new_vard, NULL_TREE);
+ DECL_HAS_VALUE_EXPR_P (new_vard) = 0;
+ gimple_seq_add_seq (ilist, tseq);
+ }
+ OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c) = NULL;
+ if (is_simd && ctx->scan_exclusive)
+ {
+ tree nv2
+ = create_tmp_var_raw (TREE_TYPE (new_var));
+ gimple_add_tmp_var (nv2);
+ ctx->cb.decl_map->put (nv, nv2);
+ x = lang_hooks.decls.omp_clause_default_ctor
+ (c, nv2, build_outer_var_ref (var, ctx));
+ gimplify_and_add (x, ilist);
+ x = lang_hooks.decls.omp_clause_dtor (c, nv2);
+ if (x)
+ gimplify_and_add (x, dlist);
+ }
+ x = lang_hooks.decls.omp_clause_dtor (c, nv);
+ if (x)
+ gimplify_and_add (x, dlist);
+ }
+ else if (is_simd
+ && ctx->scan_exclusive
+ && TREE_ADDRESSABLE (TREE_TYPE (new_var)))
+ {
+ tree nv2 = create_tmp_var_raw (TREE_TYPE (new_var));
+ gimple_add_tmp_var (nv2);
+ ctx->cb.decl_map->put (new_vard, nv2);
+ x = lang_hooks.decls.omp_clause_dtor (c, nv2);
+ if (x)
+ gimplify_and_add (x, dlist);
+ }
+ DECL_HAS_VALUE_EXPR_P (placeholder) = 0;
+ goto do_dtor;
+ }
+
if (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c))
{
tseq = OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c);
@@ -5121,12 +5511,33 @@ lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
new_vard = TREE_OPERAND (new_var, 0);
gcc_assert (DECL_P (new_vard));
}
+ tree rvar = NULL_TREE, *rvarp = NULL, rvar2 = NULL_TREE;
+ if (is_simd
+ && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
+ && OMP_CLAUSE_REDUCTION_INSCAN (c))
+ rvarp = &rvar;
if (is_simd
&& lower_rec_simd_input_clauses (new_var, ctx, &sctx,
- ivar, lvar))
+ ivar, lvar, rvarp,
+ &rvar2))
{
+ if (new_vard != new_var)
+ {
+ SET_DECL_VALUE_EXPR (new_vard,
+ build_fold_addr_expr (lvar));
+ DECL_HAS_VALUE_EXPR_P (new_vard) = 1;
+ }
+
tree ref = build_outer_var_ref (var, ctx);
+ if (rvarp)
+ {
+ gimplify_assign (ivar, ref, &llist[0]);
+ ref = build_outer_var_ref (var, ctx);
+ gimplify_assign (ref, rvar, &llist[3]);
+ break;
+ }
+
gimplify_assign (unshare_expr (ivar), x, &llist[0]);
if (sctx.is_simt)
@@ -5143,17 +5554,14 @@ lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
ref = build_outer_var_ref (var, ctx);
gimplify_assign (ref, x, &llist[1]);
- if (new_vard != new_var)
- {
- SET_DECL_VALUE_EXPR (new_vard,
- build_fold_addr_expr (lvar));
- DECL_HAS_VALUE_EXPR_P (new_vard) = 1;
- }
}
else
{
if (omp_is_reference (var) && is_simd)
handle_simd_reference (clause_loc, new_vard, ilist);
+ if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
+ && OMP_CLAUSE_REDUCTION_INSCAN (c))
+ break;
gimplify_assign (new_var, x, ilist);
if (is_simd)
{
@@ -5180,7 +5588,48 @@ lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
}
if (known_eq (sctx.max_vf, 1U))
- sctx.is_simt = false;
+ {
+ sctx.is_simt = false;
+ if (ctx->lastprivate_conditional_map)
+ {
+ if (gimple_omp_for_combined_into_p (ctx->stmt))
+ {
+ /* Signal to lower_omp_1 that it should use parent context. */
+ ctx->combined_into_simd_safelen0 = true;
+ for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
+ if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
+ && OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (c))
+ {
+ tree o = lookup_decl (OMP_CLAUSE_DECL (c), ctx);
+ tree *v
+ = ctx->lastprivate_conditional_map->get (o);
+ tree po = lookup_decl (OMP_CLAUSE_DECL (c), ctx->outer);
+ tree *pv
+ = ctx->outer->lastprivate_conditional_map->get (po);
+ *v = *pv;
+ }
+ }
+ else
+ {
+ /* When not vectorized, treat lastprivate(conditional:) like
+ normal lastprivate, as there will be just one simd lane
+ writing the privatized variable. */
+ delete ctx->lastprivate_conditional_map;
+ ctx->lastprivate_conditional_map = NULL;
+ }
+ }
+ }
+
+ if (nonconst_simd_if)
+ {
+ if (sctx.lane == NULL_TREE)
+ {
+ sctx.idx = create_tmp_var (unsigned_type_node);
+ sctx.lane = create_tmp_var (unsigned_type_node);
+ }
+ /* FIXME: For now. */
+ sctx.is_simt = false;
+ }
if (sctx.lane || sctx.is_simt)
{
@@ -5211,14 +5660,24 @@ lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
}
if (sctx.lane)
{
- gimple *g
- = gimple_build_call_internal (IFN_GOMP_SIMD_LANE, 1, uid);
+ gimple *g = gimple_build_call_internal (IFN_GOMP_SIMD_LANE,
+ 2 + (nonconst_simd_if != NULL),
+ uid, integer_zero_node,
+ nonconst_simd_if);
gimple_call_set_lhs (g, sctx.lane);
gimple_stmt_iterator gsi = gsi_start_1 (gimple_omp_body_ptr (ctx->stmt));
gsi_insert_before_without_update (&gsi, g, GSI_SAME_STMT);
g = gimple_build_assign (sctx.lane, INTEGER_CST,
build_int_cst (unsigned_type_node, 0));
gimple_seq_add_stmt (ilist, g);
+ if (sctx.lastlane)
+ {
+ g = gimple_build_call_internal (IFN_GOMP_SIMD_LAST_LANE,
+ 2, uid, sctx.lane);
+ gimple_call_set_lhs (g, sctx.lastlane);
+ gimple_seq_add_stmt (dlist, g);
+ gimple_seq_add_seq (dlist, llist[3]);
+ }
/* Emit reductions across SIMT lanes in log_2(simt_vf) steps. */
if (llist[2])
{
@@ -5305,7 +5764,10 @@ lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
lastprivate clauses we need to ensure the lastprivate copying
happens after firstprivate copying in all threads. And similarly
for UDRs if initializer expression refers to omp_orig. */
- if (copyin_by_ref || lastprivate_firstprivate || reduction_omp_orig_ref)
+ if (copyin_by_ref || lastprivate_firstprivate
+ || (reduction_omp_orig_ref
+ && !ctx->scan_inclusive
+ && !ctx->scan_exclusive))
{
/* Don't add any barrier for #pragma omp simd or
#pragma omp distribute. */
@@ -5335,18 +5797,119 @@ lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
}
}
+/* Create temporary variables for lastprivate(conditional:) implementation
+ in context CTX with CLAUSES. */
+
+static void
+lower_lastprivate_conditional_clauses (tree *clauses, omp_context *ctx)
+{
+ tree iter_type = NULL_TREE;
+ tree cond_ptr = NULL_TREE;
+ tree iter_var = NULL_TREE;
+ bool is_simd = (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
+ && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD);
+ tree next = *clauses;
+ for (tree c = *clauses; c; c = OMP_CLAUSE_CHAIN (c))
+ if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
+ && OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (c))
+ {
+ if (is_simd)
+ {
+ tree cc = omp_find_clause (next, OMP_CLAUSE__CONDTEMP_);
+ gcc_assert (cc);
+ if (iter_type == NULL_TREE)
+ {
+ iter_type = TREE_TYPE (OMP_CLAUSE_DECL (cc));
+ iter_var = create_tmp_var_raw (iter_type);
+ DECL_CONTEXT (iter_var) = current_function_decl;
+ DECL_SEEN_IN_BIND_EXPR_P (iter_var) = 1;
+ DECL_CHAIN (iter_var) = ctx->block_vars;
+ ctx->block_vars = iter_var;
+ tree c3
+ = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__CONDTEMP_);
+ OMP_CLAUSE__CONDTEMP__ITER (c3) = 1;
+ OMP_CLAUSE_DECL (c3) = iter_var;
+ OMP_CLAUSE_CHAIN (c3) = *clauses;
+ *clauses = c3;
+ ctx->lastprivate_conditional_map = new hash_map<tree, tree>;
+ }
+ next = OMP_CLAUSE_CHAIN (cc);
+ tree o = lookup_decl (OMP_CLAUSE_DECL (c), ctx);
+ tree v = lookup_decl (OMP_CLAUSE_DECL (cc), ctx);
+ ctx->lastprivate_conditional_map->put (o, v);
+ continue;
+ }
+ if (iter_type == NULL)
+ {
+ if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR)
+ {
+ struct omp_for_data fd;
+ omp_extract_for_data (as_a <gomp_for *> (ctx->stmt), &fd,
+ NULL);
+ iter_type = unsigned_type_for (fd.iter_type);
+ }
+ else if (gimple_code (ctx->stmt) == GIMPLE_OMP_SECTIONS)
+ iter_type = unsigned_type_node;
+ tree c2 = omp_find_clause (*clauses, OMP_CLAUSE__CONDTEMP_);
+ if (c2)
+ {
+ cond_ptr
+ = lookup_decl_in_outer_ctx (OMP_CLAUSE_DECL (c2), ctx);
+ OMP_CLAUSE_DECL (c2) = cond_ptr;
+ }
+ else
+ {
+ cond_ptr = create_tmp_var_raw (build_pointer_type (iter_type));
+ DECL_CONTEXT (cond_ptr) = current_function_decl;
+ DECL_SEEN_IN_BIND_EXPR_P (cond_ptr) = 1;
+ DECL_CHAIN (cond_ptr) = ctx->block_vars;
+ ctx->block_vars = cond_ptr;
+ c2 = build_omp_clause (UNKNOWN_LOCATION,
+ OMP_CLAUSE__CONDTEMP_);
+ OMP_CLAUSE_DECL (c2) = cond_ptr;
+ OMP_CLAUSE_CHAIN (c2) = *clauses;
+ *clauses = c2;
+ }
+ iter_var = create_tmp_var_raw (iter_type);
+ DECL_CONTEXT (iter_var) = current_function_decl;
+ DECL_SEEN_IN_BIND_EXPR_P (iter_var) = 1;
+ DECL_CHAIN (iter_var) = ctx->block_vars;
+ ctx->block_vars = iter_var;
+ tree c3
+ = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__CONDTEMP_);
+ OMP_CLAUSE__CONDTEMP__ITER (c3) = 1;
+ OMP_CLAUSE_DECL (c3) = iter_var;
+ OMP_CLAUSE_CHAIN (c3) = OMP_CLAUSE_CHAIN (c2);
+ OMP_CLAUSE_CHAIN (c2) = c3;
+ ctx->lastprivate_conditional_map = new hash_map<tree, tree>;
+ }
+ tree v = create_tmp_var_raw (iter_type);
+ DECL_CONTEXT (v) = current_function_decl;
+ DECL_SEEN_IN_BIND_EXPR_P (v) = 1;
+ DECL_CHAIN (v) = ctx->block_vars;
+ ctx->block_vars = v;
+ tree o = lookup_decl (OMP_CLAUSE_DECL (c), ctx);
+ ctx->lastprivate_conditional_map->put (o, v);
+ }
+}
+
/* Generate code to implement the LASTPRIVATE clauses. This is used for
both parallel and workshare constructs. PREDICATE may be NULL if it's
- always true. */
+ always true. BODY_P is the sequence to insert early initialization
+ if needed, STMT_LIST is where the non-conditional lastprivate handling
+ goes into and CSTMT_LIST is a sequence that needs to be run in a critical
+ section. */
static void
-lower_lastprivate_clauses (tree clauses, tree predicate, gimple_seq *stmt_list,
+lower_lastprivate_clauses (tree clauses, tree predicate, gimple_seq *body_p,
+ gimple_seq *stmt_list, gimple_seq *cstmt_list,
omp_context *ctx)
{
tree x, c, label = NULL, orig_clauses = clauses;
bool par_clauses = false;
tree simduid = NULL, lastlane = NULL, simtcond = NULL, simtlast = NULL;
+ unsigned HOST_WIDE_INT conditional_off = 0;
/* Early exit if there are no lastprivate or linear clauses. */
for (; clauses ; clauses = OMP_CLAUSE_CHAIN (clauses))
@@ -5425,10 +5988,54 @@ lower_lastprivate_clauses (tree clauses, tree predicate, gimple_seq *stmt_list,
gimple_seq_add_stmt (stmt_list, gimple_build_label (label_true));
}
+ tree cond_ptr = NULL_TREE;
for (c = clauses; c ;)
{
tree var, new_var;
location_t clause_loc = OMP_CLAUSE_LOCATION (c);
+ gimple_seq *this_stmt_list = stmt_list;
+ tree lab2 = NULL_TREE;
+
+ if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
+ && OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (c)
+ && ctx->lastprivate_conditional_map
+ && !ctx->combined_into_simd_safelen0)
+ {
+ gcc_assert (body_p);
+ if (simduid)
+ goto next;
+ if (cond_ptr == NULL_TREE)
+ {
+ cond_ptr = omp_find_clause (orig_clauses, OMP_CLAUSE__CONDTEMP_);
+ cond_ptr = OMP_CLAUSE_DECL (cond_ptr);
+ }
+ tree type = TREE_TYPE (TREE_TYPE (cond_ptr));
+ tree o = lookup_decl (OMP_CLAUSE_DECL (c), ctx);
+ tree v = *ctx->lastprivate_conditional_map->get (o);
+ gimplify_assign (v, build_zero_cst (type), body_p);
+ this_stmt_list = cstmt_list;
+ tree mem;
+ if (POINTER_TYPE_P (TREE_TYPE (cond_ptr)))
+ {
+ mem = build2 (MEM_REF, type, cond_ptr,
+ build_int_cst (TREE_TYPE (cond_ptr),
+ conditional_off));
+ conditional_off += tree_to_uhwi (TYPE_SIZE_UNIT (type));
+ }
+ else
+ mem = build4 (ARRAY_REF, type, cond_ptr,
+ size_int (conditional_off++), NULL_TREE, NULL_TREE);
+ tree mem2 = copy_node (mem);
+ gimple_seq seq = NULL;
+ mem = force_gimple_operand (mem, &seq, true, NULL_TREE);
+ gimple_seq_add_seq (this_stmt_list, seq);
+ tree lab1 = create_artificial_label (UNKNOWN_LOCATION);
+ lab2 = create_artificial_label (UNKNOWN_LOCATION);
+ gimple *g = gimple_build_cond (GT_EXPR, v, mem, lab1, lab2);
+ gimple_seq_add_stmt (this_stmt_list, g);
+ gimple_seq_add_stmt (this_stmt_list, gimple_build_label (lab1));
+ gimplify_assign (mem2, v, this_stmt_list);
+ }
if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
|| (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
@@ -5470,11 +6077,12 @@ lower_lastprivate_clauses (tree clauses, tree predicate, gimple_seq *stmt_list,
2, simduid,
TREE_OPERAND (val, 1));
gimple_call_set_lhs (g, lastlane);
- gimple_seq_add_stmt (stmt_list, g);
+ gimple_seq_add_stmt (this_stmt_list, g);
}
new_var = build4 (ARRAY_REF, TREE_TYPE (val),
TREE_OPERAND (val, 0), lastlane,
NULL_TREE, NULL_TREE);
+ TREE_THIS_NOTRAP (new_var) = 1;
}
}
else if (maybe_simt)
@@ -5488,13 +6096,13 @@ lower_lastprivate_clauses (tree clauses, tree predicate, gimple_seq *stmt_list,
gcall *g = gimple_build_call_internal
(IFN_GOMP_SIMT_LAST_LANE, 1, simtcond);
gimple_call_set_lhs (g, simtlast);
- gimple_seq_add_stmt (stmt_list, g);
+ gimple_seq_add_stmt (this_stmt_list, g);
}
x = build_call_expr_internal_loc
(UNKNOWN_LOCATION, IFN_GOMP_SIMT_XCHG_IDX,
TREE_TYPE (val), 2, val, simtlast);
new_var = unshare_expr (new_var);
- gimplify_assign (new_var, x, stmt_list);
+ gimplify_assign (new_var, x, this_stmt_list);
new_var = unshare_expr (new_var);
}
@@ -5502,7 +6110,7 @@ lower_lastprivate_clauses (tree clauses, tree predicate, gimple_seq *stmt_list,
&& OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
{
lower_omp (&OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c), ctx);
- gimple_seq_add_seq (stmt_list,
+ gimple_seq_add_seq (this_stmt_list,
OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c));
OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c) = NULL;
}
@@ -5510,7 +6118,7 @@ lower_lastprivate_clauses (tree clauses, tree predicate, gimple_seq *stmt_list,
&& OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c))
{
lower_omp (&OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c), ctx);
- gimple_seq_add_seq (stmt_list,
+ gimple_seq_add_seq (this_stmt_list,
OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c));
OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c) = NULL;
}
@@ -5530,8 +6138,13 @@ lower_lastprivate_clauses (tree clauses, tree predicate, gimple_seq *stmt_list,
if (omp_is_reference (var))
new_var = build_simple_mem_ref_loc (clause_loc, new_var);
x = lang_hooks.decls.omp_clause_assign_op (c, x, new_var);
- gimplify_and_add (x, stmt_list);
+ gimplify_and_add (x, this_stmt_list);
+
+ if (lab2)
+ gimple_seq_add_stmt (this_stmt_list, gimple_build_label (lab2));
}
+
+ next:
c = OMP_CLAUSE_CHAIN (c);
if (c == NULL && !par_clauses)
{
@@ -5779,10 +6392,15 @@ lower_oacc_reductions (location_t loc, tree clauses, tree level, bool inner,
gimple_seq_add_seq (join_seq, after_join);
}
-/* Generate code to implement the REDUCTION clauses. */
+/* Generate code to implement the REDUCTION clauses, append it
+ to STMT_SEQP. CLIST if non-NULL is a pointer to a sequence
+ that should be emitted also inside of the critical section,
+ in that case clear *CLIST afterwards, otherwise leave it as is
+ and let the caller emit it itself. */
static void
-lower_reduction_clauses (tree clauses, gimple_seq *stmt_seqp, omp_context *ctx)
+lower_reduction_clauses (tree clauses, gimple_seq *stmt_seqp,
+ gimple_seq *clist, omp_context *ctx)
{
gimple_seq sub_seq = NULL;
gimple *stmt;
@@ -5798,6 +6416,10 @@ lower_reduction_clauses (tree clauses, gimple_seq *stmt_seqp, omp_context *ctx)
&& gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
return;
+ /* inscan reductions are handled elsewhere. */
+ if (ctx->scan_inclusive || ctx->scan_exclusive)
+ return;
+
/* First see if there is exactly one reduction clause. Use OMP_ATOMIC
update in that case, otherwise use a lock. */
for (c = clauses; c && count < 2; c = OMP_CLAUSE_CHAIN (c))
@@ -6024,6 +6646,12 @@ lower_reduction_clauses (tree clauses, gimple_seq *stmt_seqp, omp_context *ctx)
gimple_seq_add_seq (stmt_seqp, sub_seq);
+ if (clist)
+ {
+ gimple_seq_add_seq (stmt_seqp, *clist);
+ *clist = NULL;
+ }
+
stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_END),
0);
gimple_seq_add_stmt (stmt_seqp, stmt);
@@ -6311,7 +6939,16 @@ lower_send_shared_vars (gimple_seq *ilist, gimple_seq *olist, omp_context *ctx)
if (use_pointer_for_field (ovar, ctx))
{
x = build_sender_ref (ovar, ctx);
- var = build_fold_addr_expr (var);
+ if (TREE_CODE (TREE_TYPE (f)) == ARRAY_TYPE
+ && TREE_TYPE (f) == TREE_TYPE (ovar))
+ {
+ gcc_assert (is_parallel_ctx (ctx)
+ && DECL_ARTIFICIAL (ovar));
+ /* _condtemp_ clause. */
+ var = build_constructor (TREE_TYPE (x), NULL);
+ }
+ else
+ var = build_fold_addr_expr (var);
gimplify_assign (x, var, ilist);
}
else
@@ -6608,7 +7245,7 @@ lower_omp_sections (gimple_stmt_iterator *gsi_p, omp_context *ctx)
gomp_sections *stmt;
gimple *t;
gbind *new_stmt, *bind;
- gimple_seq ilist, dlist, olist, tred_dlist = NULL, new_body;
+ gimple_seq ilist, dlist, olist, tred_dlist = NULL, clist = NULL, new_body;
stmt = as_a <gomp_sections *> (gsi_stmt (*gsi_p));
@@ -6637,9 +7274,15 @@ lower_omp_sections (gimple_stmt_iterator *gsi_p, omp_context *ctx)
gimple_seq_add_stmt (&ilist, gimple_build_assign (rtmp, temp));
}
+ tree *clauses_ptr = gimple_omp_sections_clauses_ptr (stmt);
+ lower_lastprivate_conditional_clauses (clauses_ptr, ctx);
+
lower_rec_input_clauses (gimple_omp_sections_clauses (stmt),
&ilist, &dlist, ctx, NULL);
+ control = create_tmp_var (unsigned_type_node, ".section");
+ gimple_omp_sections_set_control (stmt, control);
+
new_body = gimple_omp_body (stmt);
gimple_omp_set_body (stmt, NULL);
tgsi = gsi_start (new_body);
@@ -6661,7 +7304,7 @@ lower_omp_sections (gimple_stmt_iterator *gsi_p, omp_context *ctx)
{
gimple_seq l = NULL;
lower_lastprivate_clauses (gimple_omp_sections_clauses (stmt), NULL,
- &l, ctx);
+ &ilist, &l, &clist, ctx);
gsi_insert_seq_after (&tgsi, l, GSI_CONTINUE_LINKING);
gimple_omp_section_set_last (sec_start);
}
@@ -6674,7 +7317,18 @@ lower_omp_sections (gimple_stmt_iterator *gsi_p, omp_context *ctx)
bind = gimple_build_bind (NULL, new_body, block);
olist = NULL;
- lower_reduction_clauses (gimple_omp_sections_clauses (stmt), &olist, ctx);
+ lower_reduction_clauses (gimple_omp_sections_clauses (stmt), &olist,
+ &clist, ctx);
+ if (clist)
+ {
+ tree fndecl = builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_START);
+ gcall *g = gimple_build_call (fndecl, 0);
+ gimple_seq_add_stmt (&olist, g);
+ gimple_seq_add_seq (&olist, clist);
+ fndecl = builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_END);
+ g = gimple_build_call (fndecl, 0);
+ gimple_seq_add_stmt (&olist, g);
+ }
block = make_node (BLOCK);
new_stmt = gimple_build_bind (NULL, NULL, block);
@@ -6692,9 +7346,7 @@ lower_omp_sections (gimple_stmt_iterator *gsi_p, omp_context *ctx)
gimple_seq_add_stmt (&new_body, gimple_build_omp_sections_switch ());
gimple_seq_add_stmt (&new_body, bind);
- control = create_tmp_var (unsigned_type_node, ".section");
t = gimple_build_omp_continue (control, control);
- gimple_omp_sections_set_control (stmt, control);
gimple_seq_add_stmt (&new_body, t);
gimple_seq_add_seq (&new_body, olist);
@@ -7941,6 +8593,296 @@ lower_omp_ordered (gimple_stmt_iterator *gsi_p, omp_context *ctx)
}
+/* Expand code for an OpenMP scan directive and the structured block
+ before the scan directive. */
+
+static void
+lower_omp_scan (gimple_stmt_iterator *gsi_p, omp_context *ctx)
+{
+ gimple *stmt = gsi_stmt (*gsi_p);
+ bool has_clauses
+ = gimple_omp_scan_clauses (as_a <gomp_scan *> (stmt)) != NULL;
+ tree lane = NULL_TREE;
+ gimple_seq before = NULL;
+ omp_context *octx = ctx->outer;
+ gcc_assert (octx);
+ if (octx->scan_exclusive && !has_clauses)
+ {
+ gimple_stmt_iterator gsi2 = *gsi_p;
+ gsi_next (&gsi2);
+ gimple *stmt2 = gsi_stmt (gsi2);
+ /* For exclusive scan, swap GIMPLE_OMP_SCAN without clauses
+ with following GIMPLE_OMP_SCAN with clauses, so that input_phase,
+ the one with exclusive clause(s), comes first. */
+ if (stmt2
+ && gimple_code (stmt2) == GIMPLE_OMP_SCAN
+ && gimple_omp_scan_clauses (as_a <gomp_scan *> (stmt2)) != NULL)
+ {
+ gsi_remove (gsi_p, false);
+ gsi_insert_after (gsi_p, stmt, GSI_SAME_STMT);
+ ctx = maybe_lookup_ctx (stmt2);
+ gcc_assert (ctx);
+ lower_omp_scan (gsi_p, ctx);
+ return;
+ }
+ }
+
+ bool input_phase = has_clauses ^ octx->scan_inclusive;
+ bool is_simd = (gimple_code (octx->stmt) == GIMPLE_OMP_FOR
+ && (gimple_omp_for_kind (octx->stmt) & GF_OMP_FOR_SIMD)
+ && !gimple_omp_for_combined_into_p (octx->stmt));
+ bool is_for = (gimple_code (octx->stmt) == GIMPLE_OMP_FOR
+ && gimple_omp_for_kind (octx->stmt) == GF_OMP_FOR_KIND_FOR
+ && !gimple_omp_for_combined_p (octx->stmt));
+ if (is_simd)
+ if (tree c = omp_find_clause (gimple_omp_for_clauses (octx->stmt),
+ OMP_CLAUSE__SIMDUID_))
+ {
+ tree uid = OMP_CLAUSE__SIMDUID__DECL (c);
+ lane = create_tmp_var (unsigned_type_node);
+ tree t = build_int_cst (integer_type_node,
+ input_phase ? 1
+ : octx->scan_inclusive ? 2 : 3);
+ gimple *g
+ = gimple_build_call_internal (IFN_GOMP_SIMD_LANE, 2, uid, t);
+ gimple_call_set_lhs (g, lane);
+ gimple_seq_add_stmt (&before, g);
+ }
+
+ if (is_simd || is_for)
+ {
+ for (tree c = gimple_omp_for_clauses (octx->stmt);
+ c; c = OMP_CLAUSE_CHAIN (c))
+ if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
+ && OMP_CLAUSE_REDUCTION_INSCAN (c))
+ {
+ location_t clause_loc = OMP_CLAUSE_LOCATION (c);
+ tree var = OMP_CLAUSE_DECL (c);
+ tree new_var = lookup_decl (var, octx);
+ tree val = new_var;
+ tree var2 = NULL_TREE;
+ tree var3 = NULL_TREE;
+ tree var4 = NULL_TREE;
+ tree lane0 = NULL_TREE;
+ tree new_vard = new_var;
+ if (omp_is_reference (var))
+ {
+ new_var = build_simple_mem_ref_loc (clause_loc, new_var);
+ val = new_var;
+ }
+ if (DECL_HAS_VALUE_EXPR_P (new_vard))
+ {
+ val = DECL_VALUE_EXPR (new_vard);
+ if (new_vard != new_var)
+ {
+ gcc_assert (TREE_CODE (val) == ADDR_EXPR);
+ val = TREE_OPERAND (val, 0);
+ }
+ if (TREE_CODE (val) == ARRAY_REF
+ && VAR_P (TREE_OPERAND (val, 0)))
+ {
+ tree v = TREE_OPERAND (val, 0);
+ if (lookup_attribute ("omp simd array",
+ DECL_ATTRIBUTES (v)))
+ {
+ val = unshare_expr (val);
+ lane0 = TREE_OPERAND (val, 1);
+ TREE_OPERAND (val, 1) = lane;
+ var2 = lookup_decl (v, octx);
+ if (octx->scan_exclusive)
+ var4 = lookup_decl (var2, octx);
+ if (input_phase
+ && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
+ var3 = maybe_lookup_decl (var4 ? var4 : var2, octx);
+ if (!input_phase)
+ {
+ var2 = build4 (ARRAY_REF, TREE_TYPE (val),
+ var2, lane, NULL_TREE, NULL_TREE);
+ TREE_THIS_NOTRAP (var2) = 1;
+ if (octx->scan_exclusive)
+ {
+ var4 = build4 (ARRAY_REF, TREE_TYPE (val),
+ var4, lane, NULL_TREE,
+ NULL_TREE);
+ TREE_THIS_NOTRAP (var4) = 1;
+ }
+ }
+ else
+ var2 = val;
+ }
+ }
+ gcc_assert (var2);
+ }
+ else
+ {
+ var2 = build_outer_var_ref (var, octx);
+ if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
+ {
+ var3 = maybe_lookup_decl (new_vard, octx);
+ if (var3 == new_vard || var3 == NULL_TREE)
+ var3 = NULL_TREE;
+ else if (is_simd && octx->scan_exclusive && !input_phase)
+ {
+ var4 = maybe_lookup_decl (var3, octx);
+ if (var4 == var3 || var4 == NULL_TREE)
+ {
+ if (TREE_ADDRESSABLE (TREE_TYPE (new_var)))
+ {
+ var4 = var3;
+ var3 = NULL_TREE;
+ }
+ else
+ var4 = NULL_TREE;
+ }
+ }
+ }
+ if (is_simd
+ && octx->scan_exclusive
+ && !input_phase
+ && var4 == NULL_TREE)
+ var4 = create_tmp_var (TREE_TYPE (val));
+ }
+ if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
+ {
+ tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
+ if (input_phase)
+ {
+ if (var3)
+ {
+ /* If we've added a separate identity element
+ variable, copy it over into val. */
+ tree x = lang_hooks.decls.omp_clause_assign_op (c, val,
+ var3);
+ gimplify_and_add (x, &before);
+ }
+ else if (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c))
+ {
+ /* Otherwise, assign to it the identity element. */
+ gimple_seq tseq = OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c);
+ if (is_for)
+ tseq = copy_gimple_seq_and_replace_locals (tseq);
+ tree ref = build_outer_var_ref (var, octx);
+ tree x = (DECL_HAS_VALUE_EXPR_P (new_vard)
+ ? DECL_VALUE_EXPR (new_vard) : NULL_TREE);
+ if (x)
+ {
+ if (new_vard != new_var)
+ val = build_fold_addr_expr_loc (clause_loc, val);
+ SET_DECL_VALUE_EXPR (new_vard, val);
+ }
+ SET_DECL_VALUE_EXPR (placeholder, ref);
+ DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
+ lower_omp (&tseq, octx);
+ if (x)
+ SET_DECL_VALUE_EXPR (new_vard, x);
+ SET_DECL_VALUE_EXPR (placeholder, NULL_TREE);
+ DECL_HAS_VALUE_EXPR_P (placeholder) = 0;
+ gimple_seq_add_seq (&before, tseq);
+ if (is_simd)
+ OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c) = NULL;
+ }
+ }
+ else if (is_simd)
+ {
+ tree x;
+ if (octx->scan_exclusive)
+ {
+ tree v4 = unshare_expr (var4);
+ tree v2 = unshare_expr (var2);
+ x = lang_hooks.decls.omp_clause_assign_op (c, v4, v2);
+ gimplify_and_add (x, &before);
+ }
+ gimple_seq tseq = OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c);
+ x = (DECL_HAS_VALUE_EXPR_P (new_vard)
+ ? DECL_VALUE_EXPR (new_vard) : NULL_TREE);
+ tree vexpr = val;
+ if (x && new_vard != new_var)
+ vexpr = build_fold_addr_expr_loc (clause_loc, val);
+ if (x)
+ SET_DECL_VALUE_EXPR (new_vard, vexpr);
+ SET_DECL_VALUE_EXPR (placeholder, var2);
+ DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
+ lower_omp (&tseq, octx);
+ gimple_seq_add_seq (&before, tseq);
+ OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
+ if (x)
+ SET_DECL_VALUE_EXPR (new_vard, x);
+ SET_DECL_VALUE_EXPR (placeholder, NULL_TREE);
+ DECL_HAS_VALUE_EXPR_P (placeholder) = 0;
+ if (octx->scan_inclusive)
+ {
+ x = lang_hooks.decls.omp_clause_assign_op (c, val,
+ var2);
+ gimplify_and_add (x, &before);
+ }
+ else if (lane0 == NULL_TREE)
+ {
+ x = lang_hooks.decls.omp_clause_assign_op (c, val,
+ var4);
+ gimplify_and_add (x, &before);
+ }
+ }
+ }
+ else
+ {
+ if (input_phase)
+ {
+ /* input phase. Set val to initializer before
+ the body. */
+ tree x = omp_reduction_init (c, TREE_TYPE (new_var));
+ gimplify_assign (val, x, &before);
+ }
+ else if (is_simd)
+ {
+ /* scan phase. */
+ enum tree_code code = OMP_CLAUSE_REDUCTION_CODE (c);
+ if (code == MINUS_EXPR)
+ code = PLUS_EXPR;
+
+ tree x = build2 (code, TREE_TYPE (var2),
+ unshare_expr (var2), unshare_expr (val));
+ if (octx->scan_inclusive)
+ {
+ gimplify_assign (unshare_expr (var2), x, &before);
+ gimplify_assign (val, var2, &before);
+ }
+ else
+ {
+ gimplify_assign (unshare_expr (var4),
+ unshare_expr (var2), &before);
+ gimplify_assign (var2, x, &before);
+ if (lane0 == NULL_TREE)
+ gimplify_assign (val, var4, &before);
+ }
+ }
+ }
+ if (octx->scan_exclusive && !input_phase && lane0)
+ {
+ tree vexpr = unshare_expr (var4);
+ TREE_OPERAND (vexpr, 1) = lane0;
+ if (new_vard != new_var)
+ vexpr = build_fold_addr_expr_loc (clause_loc, vexpr);
+ SET_DECL_VALUE_EXPR (new_vard, vexpr);
+ }
+ }
+ }
+ else if (has_clauses)
+ sorry_at (gimple_location (stmt),
+ "%<#pragma omp scan%> not supported yet");
+ if (!is_for)
+ {
+ gsi_insert_seq_after (gsi_p, gimple_omp_body (stmt), GSI_SAME_STMT);
+ gsi_insert_seq_after (gsi_p, before, GSI_SAME_STMT);
+ gsi_replace (gsi_p, gimple_build_nop (), true);
+ }
+ else if (before)
+ {
+ gimple_stmt_iterator gsi = gsi_start_1 (gimple_omp_body_ptr (stmt));
+ gsi_insert_seq_before (&gsi, before, GSI_SAME_STMT);
+ }
+}
+
+
/* Gimplify a GIMPLE_OMP_CRITICAL statement. This is a relatively simple
substitution of a couple of function calls. But in the NAMED case,
requires that languages coordinate a symbol name. It is therefore
@@ -8051,11 +8993,13 @@ lower_omp_critical (gimple_stmt_iterator *gsi_p, omp_context *ctx)
for a lastprivate clause. Given a loop control predicate of (V
cond N2), we gate the clause on (!(V cond N2)). The lowered form
is appended to *DLIST, iterator initialization is appended to
- *BODY_P. */
+ *BODY_P. *CLIST is for lastprivate(conditional:) code that needs
+ to be emitted in a critical section. */
static void
lower_omp_for_lastprivate (struct omp_for_data *fd, gimple_seq *body_p,
- gimple_seq *dlist, struct omp_context *ctx)
+ gimple_seq *dlist, gimple_seq *clist,
+ struct omp_context *ctx)
{
tree clauses, cond, vinit;
enum tree_code cond_code;
@@ -8135,7 +9079,7 @@ lower_omp_for_lastprivate (struct omp_for_data *fd, gimple_seq *body_p,
clauses = gimple_omp_for_clauses (fd->for_stmt);
stmts = NULL;
- lower_lastprivate_clauses (clauses, cond, &stmts, ctx);
+ lower_lastprivate_clauses (clauses, cond, body_p, &stmts, clist, ctx);
if (!gimple_seq_empty_p (stmts))
{
gimple_seq_add_seq (&stmts, *dlist);
@@ -8156,6 +9100,712 @@ lower_omp_for_lastprivate (struct omp_for_data *fd, gimple_seq *body_p,
}
}
+/* Callback for walk_gimple_seq. Find #pragma omp scan statement. */
+
+tree
+omp_find_scan (gimple_stmt_iterator *gsi_p, bool *handled_ops_p,
+ struct walk_stmt_info *wi)
+{
+ gimple *stmt = gsi_stmt (*gsi_p);
+
+ *handled_ops_p = true;
+ switch (gimple_code (stmt))
+ {
+ WALK_SUBSTMTS;
+
+ case GIMPLE_OMP_SCAN:
+ *(gimple_stmt_iterator *) (wi->info) = *gsi_p;
+ return integer_zero_node;
+ default:
+ break;
+ }
+ return NULL;
+}
+
+/* Helper function for lower_omp_for, add transformations for a worksharing
+ loop with scan directives inside of it.
+ For worksharing loop not combined with simd, transform:
+ #pragma omp for reduction(inscan,+:r) private(i)
+ for (i = 0; i < n; i = i + 1)
+ {
+ {
+ update (r);
+ }
+ #pragma omp scan inclusive(r)
+ {
+ use (r);
+ }
+ }
+
+ into two worksharing loops + code to merge results:
+
+ num_threads = omp_get_num_threads ();
+ thread_num = omp_get_thread_num ();
+ if (thread_num == 0) goto <D.2099>; else goto <D.2100>;
+ <D.2099>:
+ var2 = r;
+ goto <D.2101>;
+ <D.2100>:
+ // For UDRs this is UDR init, or if ctors are needed, copy from
+ // var3 that has been constructed to contain the neutral element.
+ var2 = 0;
+ <D.2101>:
+ ivar = 0;
+ // The _scantemp_ clauses will arrange for rpriva to be initialized to
+ // a shared array with num_threads elements and rprivb to a local array
+ // number of elements equal to the number of (contiguous) iterations the
+ // current thread will perform. controlb and controlp variables are
+ // temporaries to handle deallocation of rprivb at the end of second
+ // GOMP_FOR.
+ #pragma omp for _scantemp_(rpriva) _scantemp_(rprivb) _scantemp_(controlb) \
+ _scantemp_(controlp) reduction(inscan,+:r) private(i) nowait
+ for (i = 0; i < n; i = i + 1)
+ {
+ {
+ // For UDRs this is UDR init or copy from var3.
+ r = 0;
+ // This is the input phase from user code.
+ update (r);
+ }
+ {
+ // For UDRs this is UDR merge.
+ var2 = var2 + r;
+ // Rather than handing it over to the user, save to local thread's
+ // array.
+ rprivb[ivar] = var2;
+ // For exclusive scan, the above two statements are swapped.
+ ivar = ivar + 1;
+ }
+ }
+ // And remember the final value from this thread's into the shared
+ // rpriva array.
+ rpriva[(sizetype) thread_num] = var2;
+ // If more than one thread, compute using Work-Efficient prefix sum
+ // the inclusive parallel scan of the rpriva array.
+ if (num_threads > 1) goto <D.2102>; else goto <D.2103>;
+ <D.2102>:
+ GOMP_barrier ();
+ down = 0;
+ k = 1;
+ num_threadsu = (unsigned int) num_threads;
+ thread_numup1 = (unsigned int) thread_num + 1;
+ <D.2108>:
+ twok = k << 1;
+ if (twok > num_threadsu) goto <D.2110>; else goto <D.2111>;
+ <D.2110>:
+ down = 4294967295;
+ k = k >> 1;
+ if (k == num_threadsu) goto <D.2112>; else goto <D.2111>;
+ <D.2112>:
+ k = k >> 1;
+ <D.2111>:
+ twok = k << 1;
+ cplx = .MUL_OVERFLOW (thread_nump1, twok);
+ mul = REALPART_EXPR <cplx>;
+ ovf = IMAGPART_EXPR <cplx>;
+ if (ovf == 0) goto <D.2116>; else goto <D.2117>;
+ <D.2116>:
+ andv = k & down;
+ andvm1 = andv + 4294967295;
+ l = mul + andvm1;
+ if (l < num_threadsu) goto <D.2120>; else goto <D.2117>;
+ <D.2120>:
+ // For UDRs this is UDR merge, performed using var2 variable as temporary,
+ // i.e. var2 = rpriva[l - k]; UDR merge (var2, rpriva[l]); rpriva[l] = var2;
+ rpriva[l] = rpriva[l - k] + rpriva[l];
+ <D.2117>:
+ if (down == 0) goto <D.2121>; else goto <D.2122>;
+ <D.2121>:
+ k = k << 1;
+ goto <D.2123>;
+ <D.2122>:
+ k = k >> 1;
+ <D.2123>:
+ GOMP_barrier ();
+ if (k != 0) goto <D.2108>; else goto <D.2103>;
+ <D.2103>:
+ if (thread_num == 0) goto <D.2124>; else goto <D.2125>;
+ <D.2124>:
+ // For UDRs this is UDR init or copy from var3.
+ var2 = 0;
+ goto <D.2126>;
+ <D.2125>:
+ var2 = rpriva[thread_num - 1];
+ <D.2126>:
+ ivar = 0;
+ #pragma omp for _scantemp_(controlb) _scantemp_(controlp) \
+ reduction(inscan,+:r) private(i)
+ for (i = 0; i < n; i = i + 1)
+ {
+ {
+ // For UDRs, this is UDR merge (rprivb[ivar], var2); r = rprivb[ivar];
+ r = rprivb[ivar] + var2;
+ }
+ {
+ // This is the scan phase from user code.
+ use (r);
+ // Plus a bump of the iterator.
+ ivar = ivar + 1;
+ }
+ } */
+
+static void
+lower_omp_for_scan (gimple_seq *body_p, gimple_seq *dlist, gomp_for *stmt,
+ struct omp_for_data *fd, omp_context *ctx)
+{
+ gcc_assert (ctx->scan_inclusive || ctx->scan_exclusive);
+
+ gimple_seq body = gimple_omp_body (stmt);
+ gimple_stmt_iterator input1_gsi = gsi_none ();
+ struct walk_stmt_info wi;
+ memset (&wi, 0, sizeof (wi));
+ wi.val_only = true;
+ wi.info = (void *) &input1_gsi;
+ walk_gimple_seq_mod (&body, omp_find_scan, NULL, &wi);
+ gcc_assert (!gsi_end_p (input1_gsi));
+
+ gimple *input_stmt1 = gsi_stmt (input1_gsi);
+ gimple_stmt_iterator gsi = input1_gsi;
+ gsi_next (&gsi);
+ gimple_stmt_iterator scan1_gsi = gsi;
+ gimple *scan_stmt1 = gsi_stmt (gsi);
+ gcc_assert (scan_stmt1 && gimple_code (scan_stmt1) == GIMPLE_OMP_SCAN);
+
+ gimple_seq input_body = gimple_omp_body (input_stmt1);
+ gimple_seq scan_body = gimple_omp_body (scan_stmt1);
+ gimple_omp_set_body (input_stmt1, NULL);
+ gimple_omp_set_body (scan_stmt1, NULL);
+ gimple_omp_set_body (stmt, NULL);
+
+ gomp_for *new_stmt = as_a <gomp_for *> (gimple_copy (stmt));
+ gimple_seq new_body = copy_gimple_seq_and_replace_locals (body);
+ gimple_omp_set_body (stmt, body);
+ gimple_omp_set_body (input_stmt1, input_body);
+
+ gimple_stmt_iterator input2_gsi = gsi_none ();
+ memset (&wi, 0, sizeof (wi));
+ wi.val_only = true;
+ wi.info = (void *) &input2_gsi;
+ walk_gimple_seq_mod (&new_body, omp_find_scan, NULL, &wi);
+ gcc_assert (!gsi_end_p (input2_gsi));
+
+ gimple *input_stmt2 = gsi_stmt (input2_gsi);
+ gsi = input2_gsi;
+ gsi_next (&gsi);
+ gimple_stmt_iterator scan2_gsi = gsi;
+ gimple *scan_stmt2 = gsi_stmt (gsi);
+ gcc_assert (scan_stmt2 && gimple_code (scan_stmt2) == GIMPLE_OMP_SCAN);
+ gimple_omp_set_body (scan_stmt2, scan_body);
+
+ tree num_threads = create_tmp_var (integer_type_node);
+ tree thread_num = create_tmp_var (integer_type_node);
+ tree nthreads_decl = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
+ tree threadnum_decl = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
+ gimple *g = gimple_build_call (nthreads_decl, 0);
+ gimple_call_set_lhs (g, num_threads);
+ gimple_seq_add_stmt (body_p, g);
+ g = gimple_build_call (threadnum_decl, 0);
+ gimple_call_set_lhs (g, thread_num);
+ gimple_seq_add_stmt (body_p, g);
+
+ tree ivar = create_tmp_var (sizetype);
+ tree new_clauses1 = NULL_TREE, new_clauses2 = NULL_TREE;
+ tree *cp1 = &new_clauses1, *cp2 = &new_clauses2;
+ tree k = create_tmp_var (unsigned_type_node);
+ tree l = create_tmp_var (unsigned_type_node);
+
+ gimple_seq clist = NULL, mdlist = NULL;
+ gimple_seq thr01_list = NULL, thrn1_list = NULL;
+ gimple_seq thr02_list = NULL, thrn2_list = NULL;
+ gimple_seq scan1_list = NULL, input2_list = NULL;
+ gimple_seq last_list = NULL, reduc_list = NULL;
+ for (tree c = gimple_omp_for_clauses (stmt); c; c = OMP_CLAUSE_CHAIN (c))
+ if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
+ && OMP_CLAUSE_REDUCTION_INSCAN (c))
+ {
+ location_t clause_loc = OMP_CLAUSE_LOCATION (c);
+ tree var = OMP_CLAUSE_DECL (c);
+ tree new_var = lookup_decl (var, ctx);
+ tree var3 = NULL_TREE;
+ tree new_vard = new_var;
+ if (omp_is_reference (var))
+ new_var = build_simple_mem_ref_loc (clause_loc, new_var);
+ if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
+ {
+ var3 = maybe_lookup_decl (new_vard, ctx);
+ if (var3 == new_vard)
+ var3 = NULL_TREE;
+ }
+
+ tree ptype = build_pointer_type (TREE_TYPE (new_var));
+ tree rpriva = create_tmp_var (ptype);
+ tree nc = build_omp_clause (clause_loc, OMP_CLAUSE__SCANTEMP_);
+ OMP_CLAUSE_DECL (nc) = rpriva;
+ *cp1 = nc;
+ cp1 = &OMP_CLAUSE_CHAIN (nc);
+
+ tree rprivb = create_tmp_var (ptype);
+ nc = build_omp_clause (clause_loc, OMP_CLAUSE__SCANTEMP_);
+ OMP_CLAUSE_DECL (nc) = rprivb;
+ OMP_CLAUSE__SCANTEMP__ALLOC (nc) = 1;
+ *cp1 = nc;
+ cp1 = &OMP_CLAUSE_CHAIN (nc);
+
+ tree var2 = create_tmp_var_raw (TREE_TYPE (new_var));
+ if (new_vard != new_var)
+ TREE_ADDRESSABLE (var2) = 1;
+ gimple_add_tmp_var (var2);
+
+ tree x = fold_convert_loc (clause_loc, sizetype, thread_num);
+ x = fold_build2_loc (clause_loc, MULT_EXPR, sizetype, x,
+ TYPE_SIZE_UNIT (TREE_TYPE (ptype)));
+ x = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (rpriva), rpriva, x);
+ tree rpriva_ref = build_simple_mem_ref_loc (clause_loc, x);
+
+ x = fold_build2_loc (clause_loc, PLUS_EXPR, integer_type_node,
+ thread_num, integer_minus_one_node);
+ x = fold_convert_loc (clause_loc, sizetype, x);
+ x = fold_build2_loc (clause_loc, MULT_EXPR, sizetype, x,
+ TYPE_SIZE_UNIT (TREE_TYPE (ptype)));
+ x = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (rpriva), rpriva, x);
+ tree rprivam1_ref = build_simple_mem_ref_loc (clause_loc, x);
+
+ x = fold_convert_loc (clause_loc, sizetype, l);
+ x = fold_build2_loc (clause_loc, MULT_EXPR, sizetype, x,
+ TYPE_SIZE_UNIT (TREE_TYPE (ptype)));
+ x = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (rpriva), rpriva, x);
+ tree rprival_ref = build_simple_mem_ref_loc (clause_loc, x);
+
+ x = fold_build2_loc (clause_loc, MINUS_EXPR, unsigned_type_node, l, k);
+ x = fold_convert_loc (clause_loc, sizetype, x);
+ x = fold_build2_loc (clause_loc, MULT_EXPR, sizetype, x,
+ TYPE_SIZE_UNIT (TREE_TYPE (ptype)));
+ x = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (rpriva), rpriva, x);
+ tree rprivalmk_ref = build_simple_mem_ref_loc (clause_loc, x);
+
+ x = fold_build2_loc (clause_loc, MULT_EXPR, sizetype, ivar,
+ TYPE_SIZE_UNIT (TREE_TYPE (ptype)));
+ x = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (rprivb), rprivb, x);
+ tree rprivb_ref = build_simple_mem_ref_loc (clause_loc, x);
+
+ if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
+ {
+ tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
+ tree val = var2;
+ if (new_vard != new_var)
+ val = build_fold_addr_expr_loc (clause_loc, val);
+
+ x = lang_hooks.decls.omp_clause_default_ctor
+ (c, var2, build_outer_var_ref (var, ctx));
+ if (x)
+ gimplify_and_add (x, &clist);
+
+ x = build_outer_var_ref (var, ctx);
+ x = lang_hooks.decls.omp_clause_assign_op (c, var2, x);
+ gimplify_and_add (x, &thr01_list);
+
+ tree y = (DECL_HAS_VALUE_EXPR_P (new_vard)
+ ? DECL_VALUE_EXPR (new_vard) : NULL_TREE);
+ if (var3)
+ {
+ x = lang_hooks.decls.omp_clause_assign_op (c, var2, var3);
+ gimplify_and_add (x, &thrn1_list);
+ x = lang_hooks.decls.omp_clause_assign_op (c, var2, var3);
+ gimplify_and_add (x, &thr02_list);
+ }
+ else if (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c))
+ {
+ /* Otherwise, assign to it the identity element. */
+ gimple_seq tseq = OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c);
+ tseq = copy_gimple_seq_and_replace_locals (tseq);
+ SET_DECL_VALUE_EXPR (new_vard, val);
+ DECL_HAS_VALUE_EXPR_P (new_vard) = 1;
+ SET_DECL_VALUE_EXPR (placeholder, error_mark_node);
+ DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
+ lower_omp (&tseq, ctx);
+ gimple_seq_add_seq (&thrn1_list, tseq);
+ tseq = OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c);
+ lower_omp (&tseq, ctx);
+ gimple_seq_add_seq (&thr02_list, tseq);
+ SET_DECL_VALUE_EXPR (placeholder, NULL_TREE);
+ DECL_HAS_VALUE_EXPR_P (placeholder) = 0;
+ OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c) = NULL;
+ if (y)
+ SET_DECL_VALUE_EXPR (new_vard, y);
+ else
+ {
+ DECL_HAS_VALUE_EXPR_P (new_vard) = 0;
+ SET_DECL_VALUE_EXPR (new_vard, NULL_TREE);
+ }
+ }
+
+ x = lang_hooks.decls.omp_clause_assign_op (c, var2, rprivam1_ref);
+ gimplify_and_add (x, &thrn2_list);
+
+ if (ctx->scan_exclusive)
+ {
+ x = unshare_expr (rprivb_ref);
+ x = lang_hooks.decls.omp_clause_assign_op (c, x, var2);
+ gimplify_and_add (x, &scan1_list);
+ }
+
+ gimple_seq tseq = OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c);
+ tseq = copy_gimple_seq_and_replace_locals (tseq);
+ SET_DECL_VALUE_EXPR (placeholder, var2);
+ DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
+ lower_omp (&tseq, ctx);
+ gimple_seq_add_seq (&scan1_list, tseq);
+
+ if (ctx->scan_inclusive)
+ {
+ x = unshare_expr (rprivb_ref);
+ x = lang_hooks.decls.omp_clause_assign_op (c, x, var2);
+ gimplify_and_add (x, &scan1_list);
+ }
+
+ x = unshare_expr (rpriva_ref);
+ x = lang_hooks.decls.omp_clause_assign_op (c, x, var2);
+ gimplify_and_add (x, &mdlist);
+
+ tseq = OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c);
+ tseq = copy_gimple_seq_and_replace_locals (tseq);
+ SET_DECL_VALUE_EXPR (new_vard, val);
+ DECL_HAS_VALUE_EXPR_P (new_vard) = 1;
+ SET_DECL_VALUE_EXPR (placeholder, rprivb_ref);
+ lower_omp (&tseq, ctx);
+ if (y)
+ SET_DECL_VALUE_EXPR (new_vard, y);
+ else
+ {
+ DECL_HAS_VALUE_EXPR_P (new_vard) = 0;
+ SET_DECL_VALUE_EXPR (new_vard, NULL_TREE);
+ }
+ gimple_seq_add_seq (&input2_list, tseq);
+
+ x = unshare_expr (new_var);
+ x = lang_hooks.decls.omp_clause_assign_op (c, x, rprivb_ref);
+ gimplify_and_add (x, &input2_list);
+
+ x = build_outer_var_ref (var, ctx);
+ x = lang_hooks.decls.omp_clause_assign_op (c, x, rpriva_ref);
+ gimplify_and_add (x, &last_list);
+
+ x = lang_hooks.decls.omp_clause_assign_op (c, var2, rprivalmk_ref);
+ gimplify_and_add (x, &reduc_list);
+ tseq = OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c);
+ tseq = copy_gimple_seq_and_replace_locals (tseq);
+ val = rprival_ref;
+ if (new_vard != new_var)
+ val = build_fold_addr_expr_loc (clause_loc, val);
+ SET_DECL_VALUE_EXPR (new_vard, val);
+ DECL_HAS_VALUE_EXPR_P (new_vard) = 1;
+ SET_DECL_VALUE_EXPR (placeholder, var2);
+ lower_omp (&tseq, ctx);
+ OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
+ SET_DECL_VALUE_EXPR (placeholder, NULL_TREE);
+ DECL_HAS_VALUE_EXPR_P (placeholder) = 0;
+ if (y)
+ SET_DECL_VALUE_EXPR (new_vard, y);
+ else
+ {
+ DECL_HAS_VALUE_EXPR_P (new_vard) = 0;
+ SET_DECL_VALUE_EXPR (new_vard, NULL_TREE);
+ }
+ gimple_seq_add_seq (&reduc_list, tseq);
+ x = lang_hooks.decls.omp_clause_assign_op (c, rprival_ref, var2);
+ gimplify_and_add (x, &reduc_list);
+
+ x = lang_hooks.decls.omp_clause_dtor (c, var2);
+ if (x)
+ gimplify_and_add (x, dlist);
+ }
+ else
+ {
+ x = build_outer_var_ref (var, ctx);
+ gimplify_assign (var2, x, &thr01_list);
+
+ x = omp_reduction_init (c, TREE_TYPE (new_var));
+ gimplify_assign (var2, unshare_expr (x), &thrn1_list);
+ gimplify_assign (var2, x, &thr02_list);
+
+ gimplify_assign (var2, rprivam1_ref, &thrn2_list);
+
+ enum tree_code code = OMP_CLAUSE_REDUCTION_CODE (c);
+ if (code == MINUS_EXPR)
+ code = PLUS_EXPR;
+
+ if (ctx->scan_exclusive)
+ gimplify_assign (unshare_expr (rprivb_ref), var2, &scan1_list);
+ x = build2 (code, TREE_TYPE (new_var), var2, new_var);
+ gimplify_assign (var2, x, &scan1_list);
+ if (ctx->scan_inclusive)
+ gimplify_assign (unshare_expr (rprivb_ref), var2, &scan1_list);
+
+ gimplify_assign (unshare_expr (rpriva_ref), var2, &mdlist);
+
+ x = build2 (code, TREE_TYPE (new_var), rprivb_ref, var2);
+ gimplify_assign (new_var, x, &input2_list);
+
+ gimplify_assign (build_outer_var_ref (var, ctx), rpriva_ref,
+ &last_list);
+
+ x = build2 (code, TREE_TYPE (new_var), rprivalmk_ref,
+ unshare_expr (rprival_ref));
+ gimplify_assign (rprival_ref, x, &reduc_list);
+ }
+ }
+
+ g = gimple_build_assign (ivar, PLUS_EXPR, ivar, size_one_node);
+ gimple_seq_add_stmt (&scan1_list, g);
+ g = gimple_build_assign (ivar, PLUS_EXPR, ivar, size_one_node);
+ gimple_seq_add_stmt (gimple_omp_body_ptr (scan_stmt2), g);
+
+ tree controlb = create_tmp_var (boolean_type_node);
+ tree controlp = create_tmp_var (ptr_type_node);
+ tree nc = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__SCANTEMP_);
+ OMP_CLAUSE_DECL (nc) = controlb;
+ OMP_CLAUSE__SCANTEMP__CONTROL (nc) = 1;
+ *cp1 = nc;
+ cp1 = &OMP_CLAUSE_CHAIN (nc);
+ nc = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__SCANTEMP_);
+ OMP_CLAUSE_DECL (nc) = controlp;
+ OMP_CLAUSE__SCANTEMP__CONTROL (nc) = 1;
+ *cp1 = nc;
+ cp1 = &OMP_CLAUSE_CHAIN (nc);
+ nc = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__SCANTEMP_);
+ OMP_CLAUSE_DECL (nc) = controlb;
+ OMP_CLAUSE__SCANTEMP__CONTROL (nc) = 1;
+ *cp2 = nc;
+ cp2 = &OMP_CLAUSE_CHAIN (nc);
+ nc = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__SCANTEMP_);
+ OMP_CLAUSE_DECL (nc) = controlp;
+ OMP_CLAUSE__SCANTEMP__CONTROL (nc) = 1;
+ *cp2 = nc;
+ cp2 = &OMP_CLAUSE_CHAIN (nc);
+
+ *cp1 = gimple_omp_for_clauses (stmt);
+ gimple_omp_for_set_clauses (stmt, new_clauses1);
+ *cp2 = gimple_omp_for_clauses (new_stmt);
+ gimple_omp_for_set_clauses (new_stmt, new_clauses2);
+
+ gimple_omp_set_body (scan_stmt1, scan1_list);
+ gimple_omp_set_body (input_stmt2, input2_list);
+
+ gsi_insert_seq_after (&input1_gsi, gimple_omp_body (input_stmt1),
+ GSI_SAME_STMT);
+ gsi_remove (&input1_gsi, true);
+ gsi_insert_seq_after (&scan1_gsi, gimple_omp_body (scan_stmt1),
+ GSI_SAME_STMT);
+ gsi_remove (&scan1_gsi, true);
+ gsi_insert_seq_after (&input2_gsi, gimple_omp_body (input_stmt2),
+ GSI_SAME_STMT);
+ gsi_remove (&input2_gsi, true);
+ gsi_insert_seq_after (&scan2_gsi, gimple_omp_body (scan_stmt2),
+ GSI_SAME_STMT);
+ gsi_remove (&scan2_gsi, true);
+
+ gimple_seq_add_seq (body_p, clist);
+
+ tree lab1 = create_artificial_label (UNKNOWN_LOCATION);
+ tree lab2 = create_artificial_label (UNKNOWN_LOCATION);
+ tree lab3 = create_artificial_label (UNKNOWN_LOCATION);
+ g = gimple_build_cond (EQ_EXPR, thread_num, integer_zero_node, lab1, lab2);
+ gimple_seq_add_stmt (body_p, g);
+ g = gimple_build_label (lab1);
+ gimple_seq_add_stmt (body_p, g);
+ gimple_seq_add_seq (body_p, thr01_list);
+ g = gimple_build_goto (lab3);
+ gimple_seq_add_stmt (body_p, g);
+ g = gimple_build_label (lab2);
+ gimple_seq_add_stmt (body_p, g);
+ gimple_seq_add_seq (body_p, thrn1_list);
+ g = gimple_build_label (lab3);
+ gimple_seq_add_stmt (body_p, g);
+
+ g = gimple_build_assign (ivar, size_zero_node);
+ gimple_seq_add_stmt (body_p, g);
+
+ gimple_seq_add_stmt (body_p, stmt);
+ gimple_seq_add_seq (body_p, body);
+ gimple_seq_add_stmt (body_p, gimple_build_omp_continue (fd->loop.v,
+ fd->loop.v));
+
+ g = gimple_build_omp_return (true);
+ gimple_seq_add_stmt (body_p, g);
+ gimple_seq_add_seq (body_p, mdlist);
+
+ lab1 = create_artificial_label (UNKNOWN_LOCATION);
+ lab2 = create_artificial_label (UNKNOWN_LOCATION);
+ g = gimple_build_cond (GT_EXPR, num_threads, integer_one_node, lab1, lab2);
+ gimple_seq_add_stmt (body_p, g);
+ g = gimple_build_label (lab1);
+ gimple_seq_add_stmt (body_p, g);
+
+ g = omp_build_barrier (NULL);
+ gimple_seq_add_stmt (body_p, g);
+
+ tree down = create_tmp_var (unsigned_type_node);
+ g = gimple_build_assign (down, build_zero_cst (unsigned_type_node));
+ gimple_seq_add_stmt (body_p, g);
+
+ g = gimple_build_assign (k, build_one_cst (unsigned_type_node));
+ gimple_seq_add_stmt (body_p, g);
+
+ tree num_threadsu = create_tmp_var (unsigned_type_node);
+ g = gimple_build_assign (num_threadsu, NOP_EXPR, num_threads);
+ gimple_seq_add_stmt (body_p, g);
+
+ tree thread_numu = create_tmp_var (unsigned_type_node);
+ g = gimple_build_assign (thread_numu, NOP_EXPR, thread_num);
+ gimple_seq_add_stmt (body_p, g);
+
+ tree thread_nump1 = create_tmp_var (unsigned_type_node);
+ g = gimple_build_assign (thread_nump1, PLUS_EXPR, thread_numu,
+ build_int_cst (unsigned_type_node, 1));
+ gimple_seq_add_stmt (body_p, g);
+
+ lab3 = create_artificial_label (UNKNOWN_LOCATION);
+ g = gimple_build_label (lab3);
+ gimple_seq_add_stmt (body_p, g);
+
+ tree twok = create_tmp_var (unsigned_type_node);
+ g = gimple_build_assign (twok, LSHIFT_EXPR, k, integer_one_node);
+ gimple_seq_add_stmt (body_p, g);
+
+ tree lab4 = create_artificial_label (UNKNOWN_LOCATION);
+ tree lab5 = create_artificial_label (UNKNOWN_LOCATION);
+ tree lab6 = create_artificial_label (UNKNOWN_LOCATION);
+ g = gimple_build_cond (GT_EXPR, twok, num_threadsu, lab4, lab5);
+ gimple_seq_add_stmt (body_p, g);
+ g = gimple_build_label (lab4);
+ gimple_seq_add_stmt (body_p, g);
+ g = gimple_build_assign (down, build_all_ones_cst (unsigned_type_node));
+ gimple_seq_add_stmt (body_p, g);
+ g = gimple_build_assign (k, RSHIFT_EXPR, k, integer_one_node);
+ gimple_seq_add_stmt (body_p, g);
+
+ g = gimple_build_cond (EQ_EXPR, k, num_threadsu, lab6, lab5);
+ gimple_seq_add_stmt (body_p, g);
+ g = gimple_build_label (lab6);
+ gimple_seq_add_stmt (body_p, g);
+
+ g = gimple_build_assign (k, RSHIFT_EXPR, k, integer_one_node);
+ gimple_seq_add_stmt (body_p, g);
+
+ g = gimple_build_label (lab5);
+ gimple_seq_add_stmt (body_p, g);
+
+ g = gimple_build_assign (twok, LSHIFT_EXPR, k, integer_one_node);
+ gimple_seq_add_stmt (body_p, g);
+
+ tree cplx = create_tmp_var (build_complex_type (unsigned_type_node, false));
+ g = gimple_build_call_internal (IFN_MUL_OVERFLOW, 2, thread_nump1, twok);
+ gimple_call_set_lhs (g, cplx);
+ gimple_seq_add_stmt (body_p, g);
+ tree mul = create_tmp_var (unsigned_type_node);
+ g = gimple_build_assign (mul, REALPART_EXPR,
+ build1 (REALPART_EXPR, unsigned_type_node, cplx));
+ gimple_seq_add_stmt (body_p, g);
+ tree ovf = create_tmp_var (unsigned_type_node);
+ g = gimple_build_assign (ovf, IMAGPART_EXPR,
+ build1 (IMAGPART_EXPR, unsigned_type_node, cplx));
+ gimple_seq_add_stmt (body_p, g);
+
+ tree lab7 = create_artificial_label (UNKNOWN_LOCATION);
+ tree lab8 = create_artificial_label (UNKNOWN_LOCATION);
+ g = gimple_build_cond (EQ_EXPR, ovf, build_zero_cst (unsigned_type_node),
+ lab7, lab8);
+ gimple_seq_add_stmt (body_p, g);
+ g = gimple_build_label (lab7);
+ gimple_seq_add_stmt (body_p, g);
+
+ tree andv = create_tmp_var (unsigned_type_node);
+ g = gimple_build_assign (andv, BIT_AND_EXPR, k, down);
+ gimple_seq_add_stmt (body_p, g);
+ tree andvm1 = create_tmp_var (unsigned_type_node);
+ g = gimple_build_assign (andvm1, PLUS_EXPR, andv,
+ build_minus_one_cst (unsigned_type_node));
+ gimple_seq_add_stmt (body_p, g);
+
+ g = gimple_build_assign (l, PLUS_EXPR, mul, andvm1);
+ gimple_seq_add_stmt (body_p, g);
+
+ tree lab9 = create_artificial_label (UNKNOWN_LOCATION);
+ g = gimple_build_cond (LT_EXPR, l, num_threadsu, lab9, lab8);
+ gimple_seq_add_stmt (body_p, g);
+ g = gimple_build_label (lab9);
+ gimple_seq_add_stmt (body_p, g);
+ gimple_seq_add_seq (body_p, reduc_list);
+ g = gimple_build_label (lab8);
+ gimple_seq_add_stmt (body_p, g);
+
+ tree lab10 = create_artificial_label (UNKNOWN_LOCATION);
+ tree lab11 = create_artificial_label (UNKNOWN_LOCATION);
+ tree lab12 = create_artificial_label (UNKNOWN_LOCATION);
+ g = gimple_build_cond (EQ_EXPR, down, build_zero_cst (unsigned_type_node),
+ lab10, lab11);
+ gimple_seq_add_stmt (body_p, g);
+ g = gimple_build_label (lab10);
+ gimple_seq_add_stmt (body_p, g);
+ g = gimple_build_assign (k, LSHIFT_EXPR, k, integer_one_node);
+ gimple_seq_add_stmt (body_p, g);
+ g = gimple_build_goto (lab12);
+ gimple_seq_add_stmt (body_p, g);
+ g = gimple_build_label (lab11);
+ gimple_seq_add_stmt (body_p, g);
+ g = gimple_build_assign (k, RSHIFT_EXPR, k, integer_one_node);
+ gimple_seq_add_stmt (body_p, g);
+ g = gimple_build_label (lab12);
+ gimple_seq_add_stmt (body_p, g);
+
+ g = omp_build_barrier (NULL);
+ gimple_seq_add_stmt (body_p, g);
+
+ g = gimple_build_cond (NE_EXPR, k, build_zero_cst (unsigned_type_node),
+ lab3, lab2);
+ gimple_seq_add_stmt (body_p, g);
+
+ g = gimple_build_label (lab2);
+ gimple_seq_add_stmt (body_p, g);
+
+ lab1 = create_artificial_label (UNKNOWN_LOCATION);
+ lab2 = create_artificial_label (UNKNOWN_LOCATION);
+ lab3 = create_artificial_label (UNKNOWN_LOCATION);
+ g = gimple_build_cond (EQ_EXPR, thread_num, integer_zero_node, lab1, lab2);
+ gimple_seq_add_stmt (body_p, g);
+ g = gimple_build_label (lab1);
+ gimple_seq_add_stmt (body_p, g);
+ gimple_seq_add_seq (body_p, thr02_list);
+ g = gimple_build_goto (lab3);
+ gimple_seq_add_stmt (body_p, g);
+ g = gimple_build_label (lab2);
+ gimple_seq_add_stmt (body_p, g);
+ gimple_seq_add_seq (body_p, thrn2_list);
+ g = gimple_build_label (lab3);
+ gimple_seq_add_stmt (body_p, g);
+
+ g = gimple_build_assign (ivar, size_zero_node);
+ gimple_seq_add_stmt (body_p, g);
+ gimple_seq_add_stmt (body_p, new_stmt);
+ gimple_seq_add_seq (body_p, new_body);
+
+ gimple_seq new_dlist = NULL;
+ lab1 = create_artificial_label (UNKNOWN_LOCATION);
+ lab2 = create_artificial_label (UNKNOWN_LOCATION);
+ tree num_threadsm1 = create_tmp_var (integer_type_node);
+ g = gimple_build_assign (num_threadsm1, PLUS_EXPR, num_threads,
+ integer_minus_one_node);
+ gimple_seq_add_stmt (&new_dlist, g);
+ g = gimple_build_cond (EQ_EXPR, thread_num, num_threadsm1, lab1, lab2);
+ gimple_seq_add_stmt (&new_dlist, g);
+ g = gimple_build_label (lab1);
+ gimple_seq_add_stmt (&new_dlist, g);
+ gimple_seq_add_seq (&new_dlist, last_list);
+ g = gimple_build_label (lab2);
+ gimple_seq_add_stmt (&new_dlist, g);
+ gimple_seq_add_seq (&new_dlist, *dlist);
+ *dlist = new_dlist;
+}
/* Lower code for an OMP loop directive. */
@@ -8167,7 +9817,7 @@ lower_omp_for (gimple_stmt_iterator *gsi_p, omp_context *ctx)
gomp_for *stmt = as_a <gomp_for *> (gsi_stmt (*gsi_p));
gbind *new_stmt;
gimple_seq omp_for_body, body, dlist, tred_ilist = NULL, tred_dlist = NULL;
- gimple_seq cnt_list = NULL;
+ gimple_seq cnt_list = NULL, clist = NULL;
gimple_seq oacc_head = NULL, oacc_tail = NULL;
size_t i;
@@ -8280,6 +9930,9 @@ lower_omp_for (gimple_stmt_iterator *gsi_p, omp_context *ctx)
gimple_seq_add_stmt (&body, gimple_build_assign (rtmp, temp));
}
+ lower_lastprivate_conditional_clauses (gimple_omp_for_clauses_ptr (stmt),
+ ctx);
+
lower_rec_input_clauses (gimple_omp_for_clauses (stmt), &body, &dlist, ctx,
fdp);
gimple_seq_add_seq (rclauses ? &tred_ilist : &body,
@@ -8330,7 +9983,7 @@ lower_omp_for (gimple_stmt_iterator *gsi_p, omp_context *ctx)
if (oacc_head)
gimple_seq_add_seq (&body, oacc_head);
- lower_omp_for_lastprivate (&fd, &body, &dlist, ctx);
+ lower_omp_for_lastprivate (&fd, &body, &dlist, &clist, ctx);
if (gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_FOR)
for (tree c = gimple_omp_for_clauses (stmt); c; c = OMP_CLAUSE_CHAIN (c))
@@ -8346,16 +9999,36 @@ lower_omp_for (gimple_stmt_iterator *gsi_p, omp_context *ctx)
bool phony_loop = (gimple_omp_for_kind (stmt) != GF_OMP_FOR_KIND_GRID_LOOP
&& gimple_omp_for_grid_phony (stmt));
- if (!phony_loop)
- gimple_seq_add_stmt (&body, stmt);
- gimple_seq_add_seq (&body, gimple_omp_body (stmt));
+ if ((ctx->scan_inclusive || ctx->scan_exclusive)
+ && gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_FOR)
+ {
+ gcc_assert (!phony_loop);
+ lower_omp_for_scan (&body, &dlist, stmt, &fd, ctx);
+ }
+ else
+ {
+ if (!phony_loop)
+ gimple_seq_add_stmt (&body, stmt);
+ gimple_seq_add_seq (&body, gimple_omp_body (stmt));
+ }
if (!phony_loop)
gimple_seq_add_stmt (&body, gimple_build_omp_continue (fd.loop.v,
fd.loop.v));
/* After the loop, add exit clauses. */
- lower_reduction_clauses (gimple_omp_for_clauses (stmt), &body, ctx);
+ lower_reduction_clauses (gimple_omp_for_clauses (stmt), &body, &clist, ctx);
+
+ if (clist)
+ {
+ tree fndecl = builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_START);
+ gcall *g = gimple_build_call (fndecl, 0);
+ gimple_seq_add_stmt (&body, g);
+ gimple_seq_add_seq (&body, clist);
+ fndecl = builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_END);
+ g = gimple_build_call (fndecl, 0);
+ gimple_seq_add_stmt (&body, g);
+ }
if (ctx->cancellable)
gimple_seq_add_stmt (&body, gimple_build_label (ctx->cancel_label));
@@ -8977,7 +10650,7 @@ lower_omp_taskreg (gimple_stmt_iterator *gsi_p, omp_context *ctx)
lower_rec_input_clauses (clauses, &par_ilist, &par_olist, ctx, NULL);
lower_omp (&par_body, ctx);
if (gimple_code (stmt) == GIMPLE_OMP_PARALLEL)
- lower_reduction_clauses (clauses, &par_rlist, ctx);
+ lower_reduction_clauses (clauses, &par_rlist, NULL, ctx);
/* Declare all the variables created by mapping and the variables
declared in the scope of the parallel body. */
@@ -10166,7 +11839,8 @@ lower_omp_teams (gimple_stmt_iterator *gsi_p, omp_context *ctx)
lower_rec_input_clauses (gimple_omp_teams_clauses (teams_stmt),
&bind_body, &dlist, ctx, NULL);
lower_omp (gimple_omp_body_ptr (teams_stmt), ctx);
- lower_reduction_clauses (gimple_omp_teams_clauses (teams_stmt), &olist, ctx);
+ lower_reduction_clauses (gimple_omp_teams_clauses (teams_stmt), &olist,
+ NULL, ctx);
if (!gimple_omp_teams_grid_phony (teams_stmt))
{
gimple_seq_add_stmt (&bind_body, teams_stmt);
@@ -10393,6 +12067,11 @@ lower_omp_1 (gimple_stmt_iterator *gsi_p, omp_context *ctx)
gcc_assert (ctx);
lower_omp_ordered (gsi_p, ctx);
break;
+ case GIMPLE_OMP_SCAN:
+ ctx = maybe_lookup_ctx (stmt);
+ gcc_assert (ctx);
+ lower_omp_scan (gsi_p, ctx);
+ break;
case GIMPLE_OMP_CRITICAL:
ctx = maybe_lookup_ctx (stmt);
gcc_assert (ctx);
@@ -10475,8 +12154,51 @@ lower_omp_1 (gimple_stmt_iterator *gsi_p, omp_context *ctx)
default:
break;
}
+ goto regimplify;
+
+ case GIMPLE_ASSIGN:
+ for (omp_context *up = ctx; up; up = up->outer)
+ {
+ if (gimple_code (up->stmt) == GIMPLE_OMP_ORDERED
+ || gimple_code (up->stmt) == GIMPLE_OMP_CRITICAL
+ || gimple_code (up->stmt) == GIMPLE_OMP_TASKGROUP
+ || gimple_code (up->stmt) == GIMPLE_OMP_SECTION
+ || gimple_code (up->stmt) == GIMPLE_OMP_SCAN
+ || (gimple_code (up->stmt) == GIMPLE_OMP_TARGET
+ && (gimple_omp_target_kind (up->stmt)
+ == GF_OMP_TARGET_KIND_DATA)))
+ continue;
+ else if (!up->lastprivate_conditional_map)
+ break;
+ tree lhs = get_base_address (gimple_assign_lhs (stmt));
+ if (TREE_CODE (lhs) == MEM_REF
+ && DECL_P (TREE_OPERAND (lhs, 0))
+ && TREE_CODE (TREE_TYPE (TREE_OPERAND (lhs,
+ 0))) == REFERENCE_TYPE)
+ lhs = TREE_OPERAND (lhs, 0);
+ if (DECL_P (lhs))
+ if (tree *v = up->lastprivate_conditional_map->get (lhs))
+ {
+ tree clauses;
+ if (up->combined_into_simd_safelen0)
+ up = up->outer;
+ if (gimple_code (up->stmt) == GIMPLE_OMP_FOR)
+ clauses = gimple_omp_for_clauses (up->stmt);
+ else
+ clauses = gimple_omp_sections_clauses (up->stmt);
+ tree c = omp_find_clause (clauses, OMP_CLAUSE__CONDTEMP_);
+ if (!OMP_CLAUSE__CONDTEMP__ITER (c))
+ c = omp_find_clause (OMP_CLAUSE_CHAIN (c),
+ OMP_CLAUSE__CONDTEMP_);
+ gcc_assert (OMP_CLAUSE__CONDTEMP__ITER (c));
+ gimple *g = gimple_build_assign (*v, OMP_CLAUSE_DECL (c));
+ gsi_insert_after (gsi_p, g, GSI_SAME_STMT);
+ }
+ }
/* FALLTHRU */
+
default:
+ regimplify:
if ((ctx || task_shared_vars)
&& walk_gimple_op (stmt, lower_omp_regimplify_p,
ctx ? NULL : &wi))
@@ -10712,6 +12434,7 @@ diagnose_sb_1 (gimple_stmt_iterator *gsi_p, bool *handled_ops_p,
case GIMPLE_OMP_SECTION:
case GIMPLE_OMP_MASTER:
case GIMPLE_OMP_ORDERED:
+ case GIMPLE_OMP_SCAN:
case GIMPLE_OMP_CRITICAL:
case GIMPLE_OMP_TARGET:
case GIMPLE_OMP_TEAMS:
@@ -10772,6 +12495,7 @@ diagnose_sb_2 (gimple_stmt_iterator *gsi_p, bool *handled_ops_p,
case GIMPLE_OMP_SECTION:
case GIMPLE_OMP_MASTER:
case GIMPLE_OMP_ORDERED:
+ case GIMPLE_OMP_SCAN:
case GIMPLE_OMP_CRITICAL:
case GIMPLE_OMP_TARGET:
case GIMPLE_OMP_TEAMS:
diff --git a/gcc/omp-offload.c b/gcc/omp-offload.c
index 97ae47b..c8a281c 100644
--- a/gcc/omp-offload.c
+++ b/gcc/omp-offload.c
@@ -300,7 +300,7 @@ oacc_xform_loop (gcall *call)
tree chunk_size = NULL_TREE;
unsigned mask = (unsigned) TREE_INT_CST_LOW (gimple_call_arg (call, 5));
tree lhs = gimple_call_lhs (call);
- tree type = TREE_TYPE (lhs);
+ tree type = NULL_TREE;
tree diff_type = TREE_TYPE (range);
tree r = NULL_TREE;
gimple_seq seq = NULL;
@@ -308,6 +308,15 @@ oacc_xform_loop (gcall *call)
unsigned outer_mask = mask & (~mask + 1); // Outermost partitioning
unsigned inner_mask = mask & ~outer_mask; // Inner partitioning (if any)
+ /* Skip lowering if return value of IFN_GOACC_LOOP call is not used. */
+ if (!lhs)
+ {
+ gsi_replace_with_seq (&gsi, seq, true);
+ return;
+ }
+
+ type = TREE_TYPE (lhs);
+
#ifdef ACCEL_COMPILER
chunk_size = gimple_call_arg (call, 4);
if (integer_minus_onep (chunk_size) /* Force static allocation. */
diff --git a/gcc/optabs-query.c b/gcc/optabs-query.c
index 71c73fb..4116bfe 100644
--- a/gcc/optabs-query.c
+++ b/gcc/optabs-query.c
@@ -415,8 +415,9 @@ can_vec_perm_var_p (machine_mode mode)
permute (if the target supports that).
Note that additional permutations representing whole-vector shifts may
- also be handled via the vec_shr optab, but only where the second input
- vector is entirely constant zeroes; this case is not dealt with here. */
+ also be handled via the vec_shr or vec_shl optab, but only where the
+ second input vector is entirely constant zeroes; this case is not dealt
+ with here. */
bool
can_vec_perm_const_p (machine_mode mode, const vec_perm_indices &sel,
@@ -593,7 +594,7 @@ can_vec_mask_load_store_p (machine_mode mode,
return true;
auto_vector_sizes vector_sizes;
- targetm.vectorize.autovectorize_vector_sizes (&vector_sizes);
+ targetm.vectorize.autovectorize_vector_sizes (&vector_sizes, true);
for (unsigned int i = 0; i < vector_sizes.length (); ++i)
{
poly_uint64 cur = vector_sizes[i];
diff --git a/gcc/optabs.c b/gcc/optabs.c
index a0e361b..18ca737 100644
--- a/gcc/optabs.c
+++ b/gcc/optabs.c
@@ -2095,8 +2095,8 @@ expand_twoval_binop (optab binoptab, rtx op0, rtx op1, rtx targ0, rtx targ1,
xop1 = avoid_expensive_constant (mode1, binoptab, 1, xop1, unsignedp);
create_fixed_operand (&ops[0], targ0);
- create_convert_operand_from (&ops[1], op0, mode, unsignedp);
- create_convert_operand_from (&ops[2], op1, mode, unsignedp);
+ create_convert_operand_from (&ops[1], xop0, mode, unsignedp);
+ create_convert_operand_from (&ops[2], xop1, mode, unsignedp);
create_fixed_operand (&ops[3], targ1);
if (maybe_expand_insn (icode, 4, ops))
return 1;
@@ -5444,19 +5444,45 @@ vector_compare_rtx (machine_mode cmp_mode, enum tree_code tcode,
}
/* Check if vec_perm mask SEL is a constant equivalent to a shift of
- the first vec_perm operand, assuming the second operand is a constant
- vector of zeros. Return the shift distance in bits if so, or NULL_RTX
- if the vec_perm is not a shift. MODE is the mode of the value being
- shifted. */
+ the first vec_perm operand, assuming the second operand (for left shift
+ first operand) is a constant vector of zeros. Return the shift distance
+ in bits if so, or NULL_RTX if the vec_perm is not a shift. MODE is the
+ mode of the value being shifted. SHIFT_OPTAB is vec_shr_optab for right
+ shift or vec_shl_optab for left shift. */
static rtx
-shift_amt_for_vec_perm_mask (machine_mode mode, const vec_perm_indices &sel)
+shift_amt_for_vec_perm_mask (machine_mode mode, const vec_perm_indices &sel,
+ optab shift_optab)
{
unsigned int bitsize = GET_MODE_UNIT_BITSIZE (mode);
poly_int64 first = sel[0];
if (maybe_ge (sel[0], GET_MODE_NUNITS (mode)))
return NULL_RTX;
- if (!sel.series_p (0, 1, first, 1))
+ if (shift_optab == vec_shl_optab)
+ {
+ unsigned int nelt;
+ if (!GET_MODE_NUNITS (mode).is_constant (&nelt))
+ return NULL_RTX;
+ unsigned firstidx = 0;
+ for (unsigned int i = 0; i < nelt; i++)
+ {
+ if (known_eq (sel[i], nelt))
+ {
+ if (i == 0 || firstidx)
+ return NULL_RTX;
+ firstidx = i;
+ }
+ else if (firstidx
+ ? maybe_ne (sel[i], nelt + i - firstidx)
+ : maybe_ge (sel[i], nelt))
+ return NULL_RTX;
+ }
+
+ if (firstidx == 0)
+ return NULL_RTX;
+ first = firstidx;
+ }
+ else if (!sel.series_p (0, 1, first, 1))
{
unsigned int nelt;
if (!GET_MODE_NUNITS (mode).is_constant (&nelt))
@@ -5544,25 +5570,37 @@ expand_vec_perm_const (machine_mode mode, rtx v0, rtx v1,
target instruction. */
vec_perm_indices indices (sel, 2, GET_MODE_NUNITS (mode));
- /* See if this can be handled with a vec_shr. We only do this if the
- second vector is all zeroes. */
- insn_code shift_code = optab_handler (vec_shr_optab, mode);
- insn_code shift_code_qi = ((qimode != VOIDmode && qimode != mode)
- ? optab_handler (vec_shr_optab, qimode)
- : CODE_FOR_nothing);
-
- if (v1 == CONST0_RTX (GET_MODE (v1))
- && (shift_code != CODE_FOR_nothing
- || shift_code_qi != CODE_FOR_nothing))
+ /* See if this can be handled with a vec_shr or vec_shl. We only do this
+ if the second (for vec_shr) or first (for vec_shl) vector is all
+ zeroes. */
+ insn_code shift_code = CODE_FOR_nothing;
+ insn_code shift_code_qi = CODE_FOR_nothing;
+ optab shift_optab = unknown_optab;
+ rtx v2 = v0;
+ if (v1 == CONST0_RTX (GET_MODE (v1)))
+ shift_optab = vec_shr_optab;
+ else if (v0 == CONST0_RTX (GET_MODE (v0)))
+ {
+ shift_optab = vec_shl_optab;
+ v2 = v1;
+ }
+ if (shift_optab != unknown_optab)
+ {
+ shift_code = optab_handler (shift_optab, mode);
+ shift_code_qi = ((qimode != VOIDmode && qimode != mode)
+ ? optab_handler (shift_optab, qimode)
+ : CODE_FOR_nothing);
+ }
+ if (shift_code != CODE_FOR_nothing || shift_code_qi != CODE_FOR_nothing)
{
- rtx shift_amt = shift_amt_for_vec_perm_mask (mode, indices);
+ rtx shift_amt = shift_amt_for_vec_perm_mask (mode, indices, shift_optab);
if (shift_amt)
{
struct expand_operand ops[3];
if (shift_code != CODE_FOR_nothing)
{
create_output_operand (&ops[0], target, mode);
- create_input_operand (&ops[1], v0, mode);
+ create_input_operand (&ops[1], v2, mode);
create_convert_operand_from_type (&ops[2], shift_amt, sizetype);
if (maybe_expand_insn (shift_code, 3, ops))
return ops[0].value;
@@ -5571,7 +5609,7 @@ expand_vec_perm_const (machine_mode mode, rtx v0, rtx v1,
{
rtx tmp = gen_reg_rtx (qimode);
create_output_operand (&ops[0], tmp, qimode);
- create_input_operand (&ops[1], gen_lowpart (qimode, v0), qimode);
+ create_input_operand (&ops[1], gen_lowpart (qimode, v2), qimode);
create_convert_operand_from_type (&ops[2], shift_amt, sizetype);
if (maybe_expand_insn (shift_code_qi, 3, ops))
return gen_lowpart (mode, ops[0].value);
diff --git a/gcc/optabs.def b/gcc/optabs.def
index 8af3a2f..4ffd0f3 100644
--- a/gcc/optabs.def
+++ b/gcc/optabs.def
@@ -256,6 +256,7 @@ OPTAB_D (umul_highpart_optab, "umul$a3_highpart")
OPTAB_D (cmpmem_optab, "cmpmem$a")
OPTAB_D (cmpstr_optab, "cmpstr$a")
OPTAB_D (cmpstrn_optab, "cmpstrn$a")
+OPTAB_D (cpymem_optab, "cpymem$a")
OPTAB_D (movmem_optab, "movmem$a")
OPTAB_D (setmem_optab, "setmem$a")
OPTAB_D (strlen_optab, "strlen$a")
@@ -323,6 +324,7 @@ OPTAB_D (reduc_and_scal_optab, "reduc_and_scal_$a")
OPTAB_D (reduc_ior_scal_optab, "reduc_ior_scal_$a")
OPTAB_D (reduc_xor_scal_optab, "reduc_xor_scal_$a")
OPTAB_D (fold_left_plus_optab, "fold_left_plus_$a")
+OPTAB_D (mask_fold_left_plus_optab, "mask_fold_left_plus_$a")
OPTAB_D (extract_last_optab, "extract_last_$a")
OPTAB_D (fold_extract_last_optab, "fold_extract_last_$a")
@@ -348,6 +350,7 @@ OPTAB_D (vec_packu_float_optab, "vec_packu_float_$a")
OPTAB_D (vec_perm_optab, "vec_perm$a")
OPTAB_D (vec_realign_load_optab, "vec_realign_load_$a")
OPTAB_D (vec_set_optab, "vec_set$a")
+OPTAB_D (vec_shl_optab, "vec_shl_$a")
OPTAB_D (vec_shr_optab, "vec_shr_$a")
OPTAB_D (vec_unpack_sfix_trunc_hi_optab, "vec_unpack_sfix_trunc_hi_$a")
OPTAB_D (vec_unpack_sfix_trunc_lo_optab, "vec_unpack_sfix_trunc_lo_$a")
diff --git a/gcc/optc-save-gen.awk b/gcc/optc-save-gen.awk
index 7ecd1eb..74096bc 100644
--- a/gcc/optc-save-gen.awk
+++ b/gcc/optc-save-gen.awk
@@ -253,7 +253,7 @@ for (i = 0; i < n_opt_char; i++) {
}
for (i = 0; i < n_opt_string; i++) {
- print " if (ptr->x_" var_opt_char[i] ")";
+ print " if (ptr->x_" var_opt_string[i] ")";
print " fprintf (file, \"%*s%s (%s)\\n\",";
print " indent_to, \"\",";
print " \"" var_opt_string[i] "\",";
@@ -326,13 +326,13 @@ for (i = 0; i < n_opt_char; i++) {
for (i = 0; i < n_opt_string; i++) {
name = var_opt_string[i]
print " if (ptr1->x_" name " != ptr2->x_" name "";
- print " || (!ptr1->x_" name" || !ptr2->x_" name
+ print " && (!ptr1->x_" name" || !ptr2->x_" name
print " || strcmp (ptr1->x_" name", ptr2->x_" name ")))";
print " fprintf (file, \"%*s%s (%s/%s)\\n\",";
print " indent_to, \"\",";
print " \"" name "\",";
- print " ptr1->x_" name ",";
- print " ptr2->x_" name ");";
+ print " ptr1->x_" name " ? ptr1->x_" name " : \"(null)\",";
+ print " ptr2->x_" name " ? ptr1->x_" name " : \"(null)\");";
print "";
}
@@ -349,6 +349,7 @@ n_target_char = 0;
n_target_short = 0;
n_target_int = 0;
n_target_enum = 0;
+n_target_string = 0;
n_target_other = 0;
if (have_save) {
@@ -381,6 +382,8 @@ if (have_save) {
if (otype == var_type(flags[i]))
var_target_range[name] = ""
}
+ else if (otype ~ "^const char \\**$")
+ var_target_string[n_target_string++] = name;
else
var_target_other[n_target_other++] = name;
}
@@ -429,6 +432,10 @@ for (i = 0; i < n_target_char; i++) {
print " ptr->x_" var_target_char[i] " = opts->x_" var_target_char[i] ";";
}
+for (i = 0; i < n_target_string; i++) {
+ print " ptr->x_" var_target_string[i] " = opts->x_" var_target_string[i] ";";
+}
+
print "}";
print "";
@@ -461,6 +468,10 @@ for (i = 0; i < n_target_char; i++) {
print " opts->x_" var_target_char[i] " = ptr->x_" var_target_char[i] ";";
}
+for (i = 0; i < n_target_string; i++) {
+ print " opts->x_" var_target_string[i] " = ptr->x_" var_target_string[i] ";";
+}
+
# This must occur after the normal variables in case the code depends on those
# variables.
print "";
@@ -530,6 +541,15 @@ for (i = 0; i < n_target_char; i++) {
print "";
}
+for (i = 0; i < n_target_string; i++) {
+ print " if (ptr->x_" var_target_string[i] ")";
+ print " fprintf (file, \"%*s%s (%s)\\n\",";
+ print " indent, \"\",";
+ print " \"" var_target_string[i] "\",";
+ print " ptr->x_" var_target_string[i] ");";
+ print "";
+}
+
print "";
print " if (targetm.target_option.print)";
print " targetm.target_option.print (file, indent, ptr);";
@@ -605,6 +625,19 @@ for (i = 0; i < n_target_char; i++) {
print "";
}
+for (i = 0; i < n_target_string; i++) {
+ name = var_target_string[i]
+ print " if (ptr1->x_" name " != ptr2->x_" name "";
+ print " && (!ptr1->x_" name" || !ptr2->x_" name
+ print " || strcmp (ptr1->x_" name", ptr2->x_" name ")))";
+ print " fprintf (file, \"%*s%s (%s/%s)\\n\",";
+ print " indent, \"\",";
+ print " \"" name "\",";
+ print " ptr1->x_" name " ? ptr1->x_" name " : \"(null)\",";
+ print " ptr2->x_" name " ? ptr1->x_" name " : \"(null)\");";
+ print "";
+}
+
print "}";
print "";
diff --git a/gcc/opts-common.c b/gcc/opts-common.c
index 8456dcc..660dfe6 100644
--- a/gcc/opts-common.c
+++ b/gcc/opts-common.c
@@ -1234,7 +1234,7 @@ cmdline_handle_error (location_t loc, const struct cl_option *option,
{
if (errors & CL_ERR_DISABLED)
{
- error_at (loc, "command line option %qs"
+ error_at (loc, "command-line option %qs"
" is not supported by this configuration", opt);
return true;
}
@@ -1323,7 +1323,7 @@ read_cmdline_option (struct gcc_options *opts,
if (decoded->opt_index == OPT_SPECIAL_unknown)
{
if (handlers->unknown_option_callback (decoded))
- error_at (loc, "unrecognized command line option %qs", decoded->arg);
+ error_at (loc, "unrecognized command-line option %qs", decoded->arg);
return;
}
@@ -1355,7 +1355,7 @@ read_cmdline_option (struct gcc_options *opts,
if (!handle_option (opts, opts_set, decoded, lang_mask, DK_UNSPECIFIED,
loc, handlers, false, dc))
- error_at (loc, "unrecognized command line option %qs", opt);
+ error_at (loc, "unrecognized command-line option %qs", opt);
}
/* Set any field in OPTS, and OPTS_SET if not NULL, for option
diff --git a/gcc/opts-global.c b/gcc/opts-global.c
index e6eaeb2..bf4db77 100644
--- a/gcc/opts-global.c
+++ b/gcc/opts-global.c
@@ -99,13 +99,13 @@ complain_wrong_lang (const struct cl_decoded_option *decoded,
bad_lang = write_langs (lang_mask);
if (opt_flags == CL_DRIVER)
- error ("command line option %qs is valid for the driver but not for %s",
+ error ("command-line option %qs is valid for the driver but not for %s",
text, bad_lang);
else if (lang_mask == CL_DRIVER)
gcc_unreachable ();
else
/* Eventually this should become a hard error IMO. */
- warning (0, "command line option %qs is valid for %s but not for %s",
+ warning (0, "command-line option %qs is valid for %s but not for %s",
text, ok_langs, bad_lang);
free (ok_langs);
@@ -136,7 +136,7 @@ print_ignored_options (void)
opt = ignored_options.pop ();
warning_at (UNKNOWN_LOCATION, 0,
- "unrecognized command line option %qs", opt);
+ "unrecognized command-line option %qs", opt);
}
}
@@ -317,8 +317,11 @@ decode_options (struct gcc_options *opts, struct gcc_options *opts_set,
finish_options (opts, opts_set, loc);
/* Print --help=* if used. */
- if (help_option_argument != NULL)
- print_help (opts, lang_mask);
+ unsigned i;
+ const char *arg;
+
+ FOR_EACH_VEC_ELT (help_option_arguments, i, arg)
+ print_help (opts, lang_mask, arg);
}
/* Hold command-line options associated with stack limitation. */
@@ -376,12 +379,12 @@ handle_common_deferred_options (void)
case OPT_fdump_:
if (!g->get_dumps ()->dump_switch_p (opt->arg))
- error ("unrecognized command line option %<-fdump-%s%>", opt->arg);
+ error ("unrecognized command-line option %<-fdump-%s%>", opt->arg);
break;
case OPT_fopt_info_:
if (!opt_info_switch_p (opt->arg))
- error ("unrecognized command line option %<-fopt-info-%s%>",
+ error ("unrecognized command-line option %<-fopt-info-%s%>",
opt->arg);
break;
diff --git a/gcc/opts.c b/gcc/opts.c
index 71adc21..b38bfb1 100644
--- a/gcc/opts.c
+++ b/gcc/opts.c
@@ -494,6 +494,7 @@ static const struct default_options default_options_table[] =
{ OPT_LEVELS_2_PLUS, OPT_fdevirtualize, NULL, 1 },
{ OPT_LEVELS_2_PLUS, OPT_fdevirtualize_speculatively, NULL, 1 },
{ OPT_LEVELS_2_PLUS, OPT_fexpensive_optimizations, NULL, 1 },
+ { OPT_LEVELS_2_PLUS, OPT_ffinite_loops, NULL, 1 },
{ OPT_LEVELS_2_PLUS, OPT_fgcse, NULL, 1 },
{ OPT_LEVELS_2_PLUS, OPT_fhoist_adjacent_loads, NULL, 1 },
{ OPT_LEVELS_2_PLUS, OPT_findirect_inlining, NULL, 1 },
@@ -550,7 +551,7 @@ static const struct default_options default_options_table[] =
{ OPT_LEVELS_3_PLUS, OPT_fpredictive_commoning, NULL, 1 },
{ OPT_LEVELS_3_PLUS, OPT_fsplit_loops, NULL, 1 },
{ OPT_LEVELS_3_PLUS, OPT_fsplit_paths, NULL, 1 },
- { OPT_LEVELS_3_PLUS, OPT_ftree_loop_distribute_patterns, NULL, 1 },
+ { OPT_LEVELS_2_PLUS, OPT_ftree_loop_distribute_patterns, NULL, 1 },
{ OPT_LEVELS_3_PLUS, OPT_ftree_loop_distribution, NULL, 1 },
{ OPT_LEVELS_3_PLUS, OPT_ftree_loop_vectorize, NULL, 1 },
{ OPT_LEVELS_3_PLUS, OPT_ftree_partial_pre, NULL, 1 },
@@ -856,7 +857,7 @@ control_options_for_live_patching (struct gcc_options *opts,
}
/* --help option argument if set. */
-const char *help_option_argument = NULL;
+vec<const char *> help_option_arguments;
/* After all options at LOC have been read into OPTS and OPTS_SET,
@@ -1671,7 +1672,8 @@ print_specific_help (unsigned int include_flags,
description = _("The following options take joined arguments");
else
{
- internal_error ("unrecognized include_flags 0x%x passed to print_specific_help",
+ internal_error ("unrecognized %<include_flags 0x%x%> passed "
+ "to %<print_specific_help%>",
include_flags);
return;
}
@@ -1982,7 +1984,7 @@ parse_no_sanitize_attribute (char *value)
if (sanitizer_opts[i].name == NULL)
warning (OPT_Wattributes,
- "%<%s%> attribute directive ignored", q);
+ "%qs attribute directive ignored", q);
q = strtok (NULL, ",");
}
@@ -2021,14 +2023,7 @@ parse_and_check_align_values (const char *flag,
free (str);
/* Check that we have a correct number of values. */
-#ifdef SUBALIGN_LOG
- unsigned max_valid_values = 4;
-#else
- unsigned max_valid_values = 2;
-#endif
-
- if (result_values.is_empty ()
- || result_values.length () > max_valid_values)
+ if (result_values.is_empty () || result_values.length () > 4)
{
if (report_error)
error_at (loc, "invalid number of arguments for %<-falign-%s%> "
@@ -2061,7 +2056,8 @@ check_alignment_argument (location_t loc, const char *flag, const char *name)
/* Print help when OPT__help_ is set. */
void
-print_help (struct gcc_options *opts, unsigned int lang_mask)
+print_help (struct gcc_options *opts, unsigned int lang_mask,
+ const char *help_option_argument)
{
const char *a = help_option_argument;
unsigned int include_flags = 0;
@@ -2165,7 +2161,7 @@ print_help (struct gcc_options *opts, unsigned int lang_mask)
*pflags |= lang_flag;
else
warning (0,
- "--help argument %q.*s is ambiguous, "
+ "%<--help%> argument %q.*s is ambiguous, "
"please be more specific",
len, a);
}
@@ -2174,7 +2170,7 @@ print_help (struct gcc_options *opts, unsigned int lang_mask)
*pflags |= lang_flag;
else
warning (0,
- "unrecognized argument to --help= option: %q.*s",
+ "unrecognized argument to %<--help=%> option: %q.*s",
len, a);
if (comma == NULL)
@@ -2254,7 +2250,7 @@ common_handle_option (struct gcc_options *opts,
case OPT__help_:
{
- help_option_argument = arg;
+ help_option_arguments.safe_push (arg);
opts->x_exit_after_options = true;
break;
}
@@ -2831,8 +2827,8 @@ handle_param (struct gcc_options *opts, struct gcc_options *opts_set,
arg = xstrdup (carg);
equal = strchr (arg, '=');
if (!equal)
- error_at (loc, "%s: --param arguments should be of the form NAME=VALUE",
- arg);
+ error_at (loc, "%s: %qs arguments should be of the form NAME=VALUE",
+ arg, "--param");
else
{
*equal = '\0';
@@ -2842,10 +2838,10 @@ handle_param (struct gcc_options *opts, struct gcc_options *opts_set,
{
const char *suggestion = find_param_fuzzy (arg);
if (suggestion)
- error_at (loc, "invalid --param name %qs; did you mean %qs?",
- arg, suggestion);
+ error_at (loc, "invalid %qs name %qs; did you mean %qs?",
+ "--param", arg, suggestion);
else
- error_at (loc, "invalid --param name %qs", arg);
+ error_at (loc, "invalid %qs name %qs", "--param", arg);
}
else
{
@@ -2853,7 +2849,7 @@ handle_param (struct gcc_options *opts, struct gcc_options *opts_set,
value = integral_argument (equal + 1);
if (value == -1)
- error_at (loc, "invalid --param value %qs", equal + 1);
+ error_at (loc, "invalid %qs value %qs", "--param", equal + 1);
else
set_param_value (arg, value,
opts->x_param_values, opts_set->x_param_values);
diff --git a/gcc/opts.h b/gcc/opts.h
index a8afc23..e5723a9 100644
--- a/gcc/opts.h
+++ b/gcc/opts.h
@@ -419,7 +419,8 @@ extern bool target_handle_option (struct gcc_options *opts,
extern void finish_options (struct gcc_options *opts,
struct gcc_options *opts_set,
location_t loc);
-extern void print_help (struct gcc_options *opts, unsigned int lang_mask);
+extern void print_help (struct gcc_options *opts, unsigned int lang_mask, const
+ char *help_option_argument);
extern void default_options_optimization (struct gcc_options *opts,
struct gcc_options *opts_set,
struct cl_decoded_option *decoded_options,
@@ -443,7 +444,7 @@ extern const struct sanitizer_opts_s
bool can_recover;
} sanitizer_opts[];
-extern const char *help_option_argument;
+extern vec<const char *> help_option_arguments;
extern void add_misspelling_candidates (auto_vec<char *> *candidates,
const struct cl_option *option,
diff --git a/gcc/params.def b/gcc/params.def
index 5830cb5..4567c17 100644
--- a/gcc/params.def
+++ b/gcc/params.def
@@ -992,14 +992,6 @@ DEFPARAM (PARAM_PROFILE_FUNC_INTERNAL_ID,
"Use internal function id in profile lookup.",
0, 0, 1)
-/* When the parameter is 1, track the most frequent N target
- addresses in indirect-call profile. This disables
- indirect_call_profiler_v3 which tracks single target. */
-DEFPARAM (PARAM_INDIR_CALL_TOPN_PROFILE,
- "indir-call-topn-profile",
- "Track top N target addresses in indirect-call profile.",
- 0, 0, 1)
-
/* Avoid SLP vectorization of large basic blocks. */
DEFPARAM (PARAM_SLP_MAX_INSNS_IN_BB,
"slp-max-insns-in-bb",
@@ -1175,6 +1167,20 @@ DEFPARAM (PARAM_CASE_VALUES_THRESHOLD,
"if 0, use the default for the machine.",
0, 0, 0)
+DEFPARAM (PARAM_JUMP_TABLE_MAX_GROWTH_RATIO_FOR_SIZE,
+ "jump-table-max-growth-ratio-for-size",
+ "The maximum code size growth ratio when expanding "
+ "into a jump table (in percent). The parameter is used when "
+ "optimizing for size.",
+ 300, 0, 0)
+
+DEFPARAM (PARAM_JUMP_TABLE_MAX_GROWTH_RATIO_FOR_SPEED,
+ "jump-table-max-growth-ratio-for-speed",
+ "The maximum code size growth ratio when expanding "
+ "into a jump table (in percent). The parameter is used when "
+ "optimizing for speed.",
+ 800, 0, 0)
+
/* Data race flags for C++0x memory model compliance. */
DEFPARAM (PARAM_ALLOW_STORE_DATA_RACES,
"allow-store-data-races",
@@ -1422,9 +1428,15 @@ DEFPARAM(PARAM_LOOP_VERSIONING_MAX_OUTER_INSNS,
DEFPARAM(PARAM_GIMPLE_FE_COMPUTED_HOT_BB_THRESHOLD,
"gimple-fe-computed-hot-bb-threshold",
"The number of executions of a basic block which is considered hot."
- " The parameters is used only in GIMPLE FE.",
+ " The parameter is used only in GIMPLE FE.",
0, 0, 0)
+DEFPARAM(PARAM_HASH_TABLE_VERIFICATION_LIMIT,
+ "hash-table-verification-limit",
+ "The number of elements for which hash table verification is done for "
+ "each searched element.",
+ 10, 0, 0)
+
/*
Local variables:
diff --git a/gcc/passes.c b/gcc/passes.c
index a9c2288..c6331cb 100644
--- a/gcc/passes.c
+++ b/gcc/passes.c
@@ -87,8 +87,8 @@ opt_pass::clone ()
void
opt_pass::set_pass_param (unsigned int, bool)
{
- internal_error ("pass %s needs a set_pass_param implementation to handle the"
- " extra argument in NEXT_PASS", name);
+ internal_error ("pass %s needs a %<set_pass_param%> implementation "
+ "to handle the extra argument in %<NEXT_PASS%>", name);
}
bool
diff --git a/gcc/passes.def b/gcc/passes.def
index ad2efab..9a5b0cd 100644
--- a/gcc/passes.def
+++ b/gcc/passes.def
@@ -83,7 +83,7 @@ along with GCC; see the file COPYING3. If not see
/* pass_build_ealias is a dummy pass that ensures that we
execute TODO_rebuild_alias at this point. */
NEXT_PASS (pass_build_ealias);
- NEXT_PASS (pass_fre);
+ NEXT_PASS (pass_fre, true /* may_iterate */);
NEXT_PASS (pass_early_vrp);
NEXT_PASS (pass_merge_phi);
NEXT_PASS (pass_dse);
@@ -117,7 +117,7 @@ along with GCC; see the file COPYING3. If not see
NEXT_PASS (pass_oacc_kernels);
PUSH_INSERT_PASSES_WITHIN (pass_oacc_kernels)
NEXT_PASS (pass_ch);
- NEXT_PASS (pass_fre);
+ NEXT_PASS (pass_fre, true /* may_iterate */);
/* We use pass_lim to rewrite in-memory iteration and reduction
variable accesses in loops into local variables accesses. */
NEXT_PASS (pass_lim);
@@ -199,7 +199,7 @@ along with GCC; see the file COPYING3. If not see
execute TODO_rebuild_alias at this point. */
NEXT_PASS (pass_build_alias);
NEXT_PASS (pass_return_slot);
- NEXT_PASS (pass_fre);
+ NEXT_PASS (pass_fre, true /* may_iterate */);
NEXT_PASS (pass_merge_phi);
NEXT_PASS (pass_thread_jumps);
NEXT_PASS (pass_vrp, true /* warn_array_bounds_p */);
@@ -312,6 +312,7 @@ along with GCC; see the file COPYING3. If not see
NEXT_PASS (pass_strength_reduction);
NEXT_PASS (pass_split_paths);
NEXT_PASS (pass_tracer);
+ NEXT_PASS (pass_fre, false /* may_iterate */);
NEXT_PASS (pass_thread_jumps);
NEXT_PASS (pass_dominator, false /* may_peel_loop_headers_p */);
NEXT_PASS (pass_strlen);
diff --git a/gcc/plugin.c b/gcc/plugin.c
index 2896c6a..a9d3171e 100644
--- a/gcc/plugin.c
+++ b/gcc/plugin.c
@@ -231,7 +231,7 @@ add_new_plugin (const char* plugin_name)
{
plugin = (struct plugin_name_args *) *slot;
if (strcmp (plugin->full_name, plugin_name))
- error ("plugin %s was specified with different paths:\n%s\n%s",
+ error ("plugin %qs was specified with different paths: %qs and %qs",
plugin->base_name, plugin->full_name, plugin_name);
return;
}
@@ -290,7 +290,8 @@ parse_plugin_arg_opt (const char *arg)
if (!key_start)
{
- error ("malformed option %<-fplugin-arg-%s%> (missing -<key>[=<value>])",
+ error ("malformed option %<-fplugin-arg-%s%>: "
+ "missing %<-<key>[=<value>]%>",
arg);
return;
}
@@ -700,7 +701,7 @@ try_init_one_plugin (struct plugin_name_args *plugin)
dl_handle = dlopen (plugin->full_name, RTLD_NOW | RTLD_GLOBAL);
if (!dl_handle)
{
- error ("cannot load plugin %s\n%s", plugin->full_name, dlerror ());
+ error ("cannot load plugin %s: %s", plugin->full_name, dlerror ());
return false;
}
@@ -710,7 +711,7 @@ try_init_one_plugin (struct plugin_name_args *plugin)
/* Check the plugin license. */
if (dlsym (dl_handle, str_license) == NULL)
fatal_error (input_location,
- "plugin %s is not licensed under a GPL-compatible license\n"
+ "plugin %s is not licensed under a GPL-compatible license"
"%s", plugin->full_name, dlerror ());
PTR_UNION_AS_VOID_PTR (plugin_init_union) =
@@ -720,7 +721,7 @@ try_init_one_plugin (struct plugin_name_args *plugin)
if ((err = dlerror ()) != NULL)
{
dlclose(dl_handle);
- error ("cannot find %s in plugin %s\n%s", str_plugin_init_func_name,
+ error ("cannot find %s in plugin %s: %s", str_plugin_init_func_name,
plugin->full_name, err);
return false;
}
@@ -729,7 +730,7 @@ try_init_one_plugin (struct plugin_name_args *plugin)
if ((*plugin_init) (plugin, &gcc_version))
{
dlclose(dl_handle);
- error ("fail to initialize plugin %s", plugin->full_name);
+ error ("failed to initialize plugin %s", plugin->full_name);
return false;
}
/* leak dl_handle on purpose to ensure the plugin is loaded for the
diff --git a/gcc/po/ChangeLog b/gcc/po/ChangeLog
index 02663f1..5d34705 100644
--- a/gcc/po/ChangeLog
+++ b/gcc/po/ChangeLog
@@ -1,3 +1,27 @@
+2019-06-06 Joseph Myers <joseph@codesourcery.com>
+
+ * sv.po: Update.
+
+2019-06-03 Joseph Myers <joseph@codesourcery.com>
+
+ * sv.po: Update.
+
+2019-05-31 Joseph Myers <joseph@codesourcery.com>
+
+ * fi.po, sv.po: Update.
+
+2019-05-20 Joseph Myers <joseph@codesourcery.com>
+
+ * es.po, sv.po: Update.
+
+2019-05-13 Joseph Myers <joseph@codesourcery.com>
+
+ * sv.po: Update.
+
+2019-05-09 Joseph Myers <joseph@codesourcery.com>
+
+ * de.po, fr.po: Update.
+
2019-05-08 Joseph Myers <joseph@codesourcery.com>
* be.po, da.po, de.po, el.po, es.po, fi.po, fr.po, hr.po, id.po,
diff --git a/gcc/po/de.po b/gcc/po/de.po
index d5fbc07..590cda9 100644
--- a/gcc/po/de.po
+++ b/gcc/po/de.po
@@ -8,10 +8,10 @@
# Roland Illig <roland.illig@gmx.de>, 2015, 2017-2019.
msgid ""
msgstr ""
-"Project-Id-Version: gcc 9.1-b20190414\n"
+"Project-Id-Version: gcc 9.1.0\n"
"Report-Msgid-Bugs-To: https://gcc.gnu.org/bugs/\n"
"POT-Creation-Date: 2019-05-02 20:28+0000\n"
-"PO-Revision-Date: 2019-04-30 20:26+0200\n"
+"PO-Revision-Date: 2019-05-07 20:48+0200\n"
"Last-Translator: Roland Illig <roland.illig@gmx.de>\n"
"Language-Team: German <translation-team-de@lists.sourceforge.net>\n"
"Language: de\n"
@@ -1294,12 +1294,13 @@ msgid " All options with the desired characteristics have already been displayed
msgstr " Alle Optionen mit den gewünschten Eigenschaften wurden bereits angezeigt\n"
#: opts.c:1581
-#, fuzzy, c-format
-#| msgid "invalid arguments for %<-falign-%s%> option: %qs"
+#, c-format
msgid ""
" Known valid arguments for %s option:\n"
" "
-msgstr "ungültige Argumente für Option %<-falign-%s%>: %qs"
+msgstr ""
+" Bekannte gültige Argumente für Option »%s«:\n"
+" "
#: opts.c:1631
msgid "The following options are target specific"
@@ -7949,10 +7950,8 @@ msgid "-fdoc-inc=<file>\tInclude a Ddoc macro <file>."
msgstr "-fdoc-inc=<Datei>\tEine Ddoc-Makro-Datei <Datei> inkludieren."
#: d/lang.opt:234
-#, fuzzy
-#| msgid "Do not assume that standard C libraries and \"main\" exist."
msgid "Assume that standard D runtime libraries and \"D main\" exist."
-msgstr "Nicht annehmen, dass Standard-C-Bibliotheken und »main« vorhanden sind."
+msgstr "Annehmen, dass Standard-D-Laufzeitbibliotheken und »D main« vorhanden sind."
#: d/lang.opt:238
msgid "Display the frontend AST after parsing and semantic passes."
@@ -10854,10 +10853,8 @@ msgid "Cost to assume for a branch insn."
msgstr "Für Sprungbefehl anzunehmende Kosten."
#: config/arm/arm.opt:308
-#, fuzzy
-#| msgid "Generate code which uses only the general registers."
msgid "Generate code which uses the core registers only (r0-r14)."
-msgstr "Code erzeugen, der nur die allgemeinen Register verwendet."
+msgstr "Code erzeugen, der nur die Kernregister (r0–r14) verwendet."
#: config/sparc/sparc.opt:30 config/sparc/sparc.opt:34
#: config/visium/visium.opt:37
@@ -19362,12 +19359,11 @@ msgid "using the range [%E, %E] for directive argument"
msgstr "das Intervall [%E, %E] wird für das Argument der Direktive verwendet"
#: gimple-ssa-sprintf.c:3020
-#, fuzzy, gcc-internal-format
-#| msgid "%qE output %wu byte into a destination of size %wu"
+#, gcc-internal-format
msgid "%qE output %wu byte into a destination of size %wu"
msgid_plural "%qE output %wu bytes into a destination of size %wu"
-msgstr[0] "%qE hat %wu Byte in das Ziel der Größe %wu ausgegeben"
-msgstr[1] "%qE hat %wu Byte in das Ziel der Größe %wu ausgegeben"
+msgstr[0] "%qE hat %wu Byte in ein Ziel der Größe %wu ausgegeben"
+msgstr[1] "%qE hat %wu Byte in ein Ziel der Größe %wu ausgegeben"
#: gimple-ssa-sprintf.c:3025
#, gcc-internal-format
@@ -19385,12 +19381,11 @@ msgid "%qE output %wu or more bytes into a destination of size %wu"
msgstr "%qE hat %wu oder mehr Bytes in das Ziel der Größe %wu ausgegeben"
#: gimple-ssa-sprintf.c:3046
-#, fuzzy, gcc-internal-format
-#| msgid "%qE output %wu byte"
+#, gcc-internal-format
msgid "%qE output %wu byte"
msgid_plural "%qE output %wu bytes"
msgstr[0] "%qE hat %wu Byte ausgegeben"
-msgstr[1] "%qE hat %wu Byte ausgegeben"
+msgstr[1] "%qE hat %wu Bytes ausgegeben"
#: gimple-ssa-sprintf.c:3050
#, gcc-internal-format
@@ -28192,10 +28187,8 @@ msgstr "Tuning-Zeichenkette fehlt in Option »%s«"
msgid "unknown tuning option (%s)"
msgstr "unbekannte Tuning-Option »%s«"
-# https://gcc.gnu.org/bugzilla/show_bug.cgi?id=90118
#: config/aarch64/aarch64.c:11486
-#, fuzzy, gcc-internal-format
-#| msgid "incompatible options %<-mstack-protector-guard=global%> and%<-mstack-protector-guard-offset=%s%>"
+#, gcc-internal-format
msgid "incompatible options %<-mstack-protector-guard=global%> and %<-mstack-protector-guard-offset=%s%>"
msgstr "die Optionen %<-mstack-protector-guard=global%> und %<-mstack-protector-guard-offset=%s%> sind unverträglich"
@@ -28506,16 +28499,14 @@ msgid "%<-mspfp_fast%> not available on ARC600 or ARC601"
msgstr "%<-mspfp_fast%> ist auf ARC600 und ARC601 nicht verfügbar"
#: config/arc/arc.c:953
-#, fuzzy, gcc-internal-format
-#| msgid "No FPX/FPU mixing allowed"
+#, gcc-internal-format
msgid "no FPX/FPU mixing allowed"
msgstr "Mischen von FPX/FPU ist nicht erlaubt"
#: config/arc/arc.c:958
-#, fuzzy, gcc-internal-format
-#| msgid "PIC is only supported for RTPs"
+#, gcc-internal-format
msgid "PIC is not supported for %qs"
-msgstr "PIC wird nur für RTPs unterstützt"
+msgstr "PIC wird für %qs nicht unterstützt"
#: config/arc/arc.c:1021
#, gcc-internal-format
@@ -28553,7 +28544,6 @@ msgstr "die Option %<-mirq-ctrl-saved%> ist nur für ARC-v2-Prozessoren gültig"
msgid "option %<-mrgf-banked-regs%> valid only for ARC v2 processors"
msgstr "die Option %<-mrgf-banked-regs%> ist nur für ARC-v2-Prozessoren gültig"
-# https://gcc.gnu.org/bugzilla/show_bug.cgi?id=79869
#. Check options against architecture options. Throw an error if
#. option is not allowed. Extra, check options against default
#. architecture/cpu flags and throw an warning if we find a
@@ -28562,29 +28552,24 @@ msgstr "die Option %<-mrgf-banked-regs%> ist nur für ARC-v2-Prozessoren gültig
#. translated. They are like keywords which one can relate with the
#. architectural choices taken for an ARC CPU implementation.
#: config/arc/arc.c:1227
-#, fuzzy, gcc-internal-format
-#| msgid "Option %s=%s is not available for %s CPU."
+#, gcc-internal-format
msgid "option %<%s=%s%> is not available for %qs CPU"
-msgstr "Option »%s=%s« ist für die %s-CPU nicht verfügbar."
+msgstr "Option %<%s=%s%> ist für die CPU %qs nicht verfügbar"
#: config/arc/arc.c:1232
-#, fuzzy, gcc-internal-format
-#| msgid "Option %s is ignored, the default value %s is considered for %s CPU."
+#, gcc-internal-format
msgid "option %qs is ignored, the default value %qs is considered for %qs CPU"
-msgstr "Option »%s« wird ignoriert, der Vorgabewert »%s« wird für die CPU »%s« verwendet."
+msgstr "Option %qs wird ignoriert, der Vorgabewert %qs wird für die CPU %qs verwendet"
-# https://gcc.gnu.org/bugzilla/show_bug.cgi?id=79869
#: config/arc/arc.c:1240
-#, fuzzy, gcc-internal-format
-#| msgid "Option %s is not available for %s CPU"
+#, gcc-internal-format
msgid "option %qs is not available for %qs CPU"
-msgstr "Option »%s« ist für die CPU »%s« nicht verfügbar"
+msgstr "Option %qs ist für die CPU %qs nicht verfügbar"
#: config/arc/arc.c:1245
-#, fuzzy, gcc-internal-format
-#| msgid "Unset option %s is ignored, it is always enabled for %s CPU."
+#, gcc-internal-format
msgid "unset option %qs is ignored, it is always enabled for %qs CPU"
-msgstr "Nicht festgelegte Option »%s« wird ignoriert, für CPU »%s« ist sie stets eingeschaltet."
+msgstr "nicht gesetzte Option %qs wird ignoriert, für CPU %qs ist sie stets eingeschaltet"
#: config/arc/arc.c:1812
#, gcc-internal-format, gfc-internal-format
@@ -28706,16 +28691,14 @@ msgid "unknown builtin immediate operand type for operand %d"
msgstr "unbekannter eingebauter direkter Operandentyp für Operand %d"
#: config/arc/arc.c:7273
-#, fuzzy, gcc-internal-format
-#| msgid "register number must be a compile-time constant. Try giving higher optimization levels"
+#, gcc-internal-format
msgid "register number must be a compile-time constant. Try giving higher optimization levels"
msgstr "Registernummer muss bereits zur Kompilierzeit eine Konstante sein. Probieren Sie eine stärkere Optimierungsstufe"
#: config/arc/arc.c:8268
-#, fuzzy, gcc-internal-format
-#| msgid "Insn addresses not set after shorten_branches"
+#, gcc-internal-format
msgid "insn addresses not set after shorten_branches"
-msgstr "Befehlsadresse nicht festgelegt, nachdem shorten_branches aufgerufen wurde"
+msgstr "Interner Fehler: insn addresses not set after shorten_branches"
#: config/arc/arc.c:8481
#, gcc-internal-format
@@ -29122,7 +29105,7 @@ msgstr "Thumb-1 Hardware-Gleitkomma VFP ABI"
#: config/arm/arm.c:6117
#, gcc-internal-format
msgid "argument of type %qT not permitted with -mgeneral-regs-only"
-msgstr ""
+msgstr "Argument vom Typ %qT ist zusammen mit »-mgeneral-regs-only« nicht erlaubt"
#: config/arm/arm.c:6501 config/arm/arm.c:6714 config/arm/arm.c:6747
#: config/arm/arm.c:27083
@@ -30585,10 +30568,9 @@ msgid "no dispatcher found for the versioning attributes"
msgstr "kein Dispatcher für versionierte Attribute gefunden"
#: config/i386/i386.c:32300
-#, fuzzy, gcc-internal-format
-#| msgid "value %qs is not supported by attribute %<target%>"
+#, gcc-internal-format
msgid "ISA %qs is not supported in %<target%> attribute, use %<arch=%> syntax"
-msgstr "Wert %qs wird von Attribut %<target%> nicht unterstützt"
+msgstr "ISA %qs wird von Attribut %<target%> nicht unterstützt, verwenden Sie den Aufruf %<arch=%>"
#: config/i386/i386.c:32311
#, gcc-internal-format, gfc-internal-format
@@ -53129,10 +53111,9 @@ msgid "MODULE prefix at %C"
msgstr "MODULE-Präfix bei %C"
#: fortran/decl.c:6130
-#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "MODULE PROCEDURE at %C must be in a generic module interface"
+#, gcc-internal-format, gfc-internal-format
msgid "MODULE prefix at %C found outside of a module, submodule, or interface"
-msgstr "MODULE PROCEDURE bei %C muss in einer generischen Modulschnittstelle sein"
+msgstr "MODULE-Präfix bei %C muss innerhalb eines Moduls, Teilmoduls oder Interfaces sein"
#: fortran/decl.c:6177
#, gcc-internal-format, gfc-internal-format
diff --git a/gcc/po/es.po b/gcc/po/es.po
index a5c2b0e..2f3a219 100644
--- a/gcc/po/es.po
+++ b/gcc/po/es.po
@@ -40,10 +40,10 @@
#
msgid ""
msgstr ""
-"Project-Id-Version: gcc 9.1-b20190414\n"
+"Project-Id-Version: gcc 9.1.0\n"
"Report-Msgid-Bugs-To: https://gcc.gnu.org/bugs/\n"
"POT-Creation-Date: 2019-05-02 20:28+0000\n"
-"PO-Revision-Date: 2019-04-15 11:00+0200\n"
+"PO-Revision-Date: 2019-05-17 05:23+0200\n"
"Last-Translator: Antonio Ceballos Roa <aceballos@gmail.com>\n"
"Language-Team: Spanish <es@tp.org.es>\n"
"Language: es\n"
@@ -20155,7 +20155,7 @@ msgstr "El desplazamiento de %G%qD %s desde el objeto en %qE está fuera de los
#: gimple-ssa-warn-restrict.c:1803
msgid "%G%qD offset %s from the object at %qE is out of the bounds of referenced subobject %qD with type %qT at offset %wu"
-msgstr "El desplazamiento de %G%qD %s desde el objeto en %qE está fuera de los límites del subobjeto referenciado %Qd con tipo %qT en el desplazamiento %wu"
+msgstr "El desplazamiento de %G%qD %s desde el objeto en %qE está fuera de los límites del subobjeto referenciado %qD con tipo %qT en el desplazamiento %wu"
#: gimple-ssa-warn-restrict.c:1980
#, fuzzy
diff --git a/gcc/po/fi.po b/gcc/po/fi.po
index 95facc1..c66de8a 100644
--- a/gcc/po/fi.po
+++ b/gcc/po/fi.po
@@ -30,10 +30,10 @@
# duplicate
msgid ""
msgstr ""
-"Project-Id-Version: gcc 9.1-b20190203\n"
+"Project-Id-Version: gcc 9.1.0\n"
"Report-Msgid-Bugs-To: https://gcc.gnu.org/bugs/\n"
"POT-Creation-Date: 2019-05-02 20:28+0000\n"
-"PO-Revision-Date: 2019-03-05 00:07+0200\n"
+"PO-Revision-Date: 2019-05-29 18:58+0300\n"
"Last-Translator: Lauri Nurmi <lanurmi@iki.fi>\n"
"Language-Team: Finnish <translation-team-fi@lists.sourceforge.net>\n"
"Language: fi\n"
@@ -42,7 +42,7 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
"X-Bugs: Report translation errors to the Language-Team address.\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
-"X-Generator: Poedit 2.2.1\n"
+"X-Generator: Poedit 2.2.3\n"
#: cfgrtl.c:2705
msgid "flow control insn inside a basic block"
@@ -123,9 +123,9 @@ msgid "%s: all warnings being treated as errors"
msgstr "Käsittele kaikki varoitukset virheinä"
#: diagnostic.c:150
-#, fuzzy, c-format
+#, c-format
msgid "%s: some warnings being treated as errors"
-msgstr "%s: varoitus: ei lukuoikeuksia tiedostoon â€%sâ€\n"
+msgstr "%s: osa varoituksista ilmaistaan virheinä"
#: diagnostic.c:341 input.c:223 input.c:1854 c-family/c-opts.c:1400
#: fortran/cpp.c:577 fortran/error.c:1012 fortran/error.c:1032
@@ -165,12 +165,11 @@ msgstr "käännös keskeytyi.\n"
#: diagnostic.c:618
msgid "In file included from"
-msgstr ""
+msgstr "Tiedostossa, joka sisällytettiin kohdasta"
#: diagnostic.c:619
-#, fuzzy
msgid " from"
-msgstr " YHTEENSÄ :"
+msgstr " kohdasta"
#: diagnostic.c:991
#, c-format
@@ -1695,9 +1694,9 @@ msgid "The maximum number of instructions when automatically inlining."
msgstr "parametrin %qs maksimiarvo on %u"
#: params.def:87
-#, no-c-format
+#, fuzzy, no-c-format
msgid "The maximum number of instructions when automatically inlining small functions."
-msgstr ""
+msgstr "parametrin %qs maksimiarvo on %u"
#: params.def:92
#, fuzzy, no-c-format
@@ -1715,14 +1714,14 @@ msgid "Time accounted for function prologue, epilogue and other overhead."
msgstr "virheellinen ei-staattisen jäsenfunktion käyttö"
#: params.def:109
-#, no-c-format
+#, fuzzy, no-c-format
msgid "Instruction accounted for function thunk overhead."
-msgstr ""
+msgstr "virheellinen ei-staattisen jäsenfunktion käyttö"
#: params.def:114
-#, no-c-format
+#, fuzzy, no-c-format
msgid "Time accounted for function thunk overhead."
-msgstr ""
+msgstr "virheellinen ei-staattisen jäsenfunktion käyttö"
#: params.def:119
#, fuzzy, no-c-format
@@ -1740,9 +1739,9 @@ msgid "The maximum depth of recursive inlining for inline functions."
msgstr "Kumoamistoimintojen enimmäismäärä"
#: params.def:134
-#, no-c-format
+#, fuzzy, no-c-format
msgid "The maximum depth of recursive inlining for non-inline functions."
-msgstr ""
+msgstr "Kumoamistoimintojen enimmäismäärä"
#: params.def:139
#, no-c-format
@@ -1785,14 +1784,14 @@ msgid "The maximum number of instructions to consider to find accurate live regi
msgstr "parametrin %qs maksimiarvo on %u"
#: params.def:204
-#, no-c-format
+#, fuzzy, no-c-format
msgid "The maximum length of scheduling's pending operations list."
-msgstr ""
+msgstr "Kumoamistoimintojen enimmäismäärä"
#: params.def:211
-#, no-c-format
+#, fuzzy, no-c-format
msgid "The maximum number of backtrack attempts the scheduler should make when modulo scheduling a loop."
-msgstr ""
+msgstr "parametrin %qs maksimiarvo on %u"
#: params.def:216
#, fuzzy, no-c-format
@@ -1850,9 +1849,9 @@ msgid "The maximum amount of memory to be allocated by GCSE."
msgstr ""
#: params.def:269
-#, no-c-format
+#, fuzzy, no-c-format
msgid "The maximum ratio of insertions to deletions of expressions in GCSE."
-msgstr ""
+msgstr "parametrin %qs maksimiarvo on %u"
#: params.def:280
#, no-c-format
@@ -1930,9 +1929,9 @@ msgid "The maximum number of insns of a peeled loop that rolls only once."
msgstr "parametrin %qs maksimiarvo on %u"
#: params.def:375
-#, no-c-format
+#, fuzzy, no-c-format
msgid "The maximum depth of a loop nest we completely peel."
-msgstr ""
+msgstr "parametrin %qs maksimiarvo on %u"
#: params.def:381
#, fuzzy, no-c-format
@@ -2080,9 +2079,9 @@ msgid "The maximum length of path considered in cse."
msgstr ""
#: params.def:546
-#, no-c-format
+#, fuzzy, no-c-format
msgid "The maximum instructions CSE process before flushing."
-msgstr ""
+msgstr "parametrin %qs maksimiarvo on %u"
#: params.def:553
#, no-c-format
@@ -2090,9 +2089,9 @@ msgid "The minimum cost of an expensive expression in the loop invariant motion.
msgstr ""
#: params.def:562
-#, no-c-format
+#, fuzzy, no-c-format
msgid "Bound on number of candidates below that all candidates are considered in iv optimizations."
-msgstr ""
+msgstr "moduulienvälisiä optimointeja ei ole toteutettu C++:lle"
#: params.def:570
#, fuzzy, no-c-format
@@ -2110,9 +2109,9 @@ msgid "Average number of iterations of a loop."
msgstr "parametrin %qs maksimiarvo on %u"
#: params.def:588
-#, no-c-format
+#, fuzzy, no-c-format
msgid "Maximum size (in bytes) of objects tracked bytewise by dead store elimination."
-msgstr ""
+msgstr "parametrin %qs maksimiarvo on %u"
#: params.def:593
#, fuzzy, no-c-format
@@ -2145,14 +2144,14 @@ msgid "Bound on number of runtime checks inserted by the vectorizer's loop versi
msgstr ""
#: params.def:624
-#, no-c-format
+#, fuzzy, no-c-format
msgid "Maximum number of loop peels to enhance alignment of data references in a loop."
-msgstr ""
+msgstr "Kumoamistoimintojen enimmäismäärä"
#: params.def:629
-#, no-c-format
+#, fuzzy, no-c-format
msgid "The maximum memory locations recorded by cselib."
-msgstr ""
+msgstr "Kumoamistoimintojen enimmäismäärä"
#: params.def:642
#, no-c-format
@@ -2165,9 +2164,9 @@ msgid "Minimum heap size before we start collecting garbage, in kilobytes."
msgstr ""
#: params.def:655
-#, no-c-format
+#, fuzzy, no-c-format
msgid "The maximum number of instructions to search backward when looking for equivalent reload."
-msgstr ""
+msgstr "parametrin %qs maksimiarvo on %u"
#: params.def:660
#, no-c-format
@@ -2175,9 +2174,9 @@ msgid "Target block's relative execution frequency (as a percentage) required to
msgstr ""
#: params.def:665 params.def:675
-#, no-c-format
+#, fuzzy, no-c-format
msgid "The maximum number of blocks in a region to be considered for interblock scheduling."
-msgstr ""
+msgstr "parametrin %qs maksimiarvo on %u"
#: params.def:670 params.def:680
#, fuzzy, no-c-format
@@ -2185,9 +2184,9 @@ msgid "The maximum number of insns in a region to be considered for interblock s
msgstr "parametrin %qs maksimiarvo on %u"
#: params.def:685
-#, no-c-format
+#, fuzzy, no-c-format
msgid "The minimum probability of reaching a source block for interblock speculative scheduling."
-msgstr ""
+msgstr "parametrin %qs maksimiarvo on %u"
#: params.def:690
#, fuzzy, no-c-format
@@ -2195,9 +2194,9 @@ msgid "The maximum number of iterations through CFG to extend regions."
msgstr "parametrin %qs maksimiarvo on %u"
#: params.def:695
-#, no-c-format
+#, fuzzy, no-c-format
msgid "The maximum conflict delay for an insn to be considered for speculative motion."
-msgstr ""
+msgstr "parametrin %qs maksimiarvo on %u"
#: params.def:700
#, no-c-format
@@ -2220,9 +2219,9 @@ msgid "Maximum number of times that an insn could be scheduled."
msgstr "parametrin %qs maksimiarvo on %u"
#: params.def:720
-#, no-c-format
+#, fuzzy, no-c-format
msgid "Maximum number of instructions in the ready list that are considered eligible for renaming."
-msgstr ""
+msgstr "parametrin %qs maksimiarvo on %u"
#: params.def:725
#, no-c-format
@@ -2270,9 +2269,9 @@ msgid "Maximum number of fields in a structure before pointer analysis treats th
msgstr ""
#: params.def:792
-#, no-c-format
+#, fuzzy, no-c-format
msgid "The maximum number of instructions ready to be issued to be considered by the scheduler during the first scheduling pass."
-msgstr ""
+msgstr "parametrin %qs maksimiarvo on %u"
#: params.def:798
#, fuzzy, no-c-format
@@ -2280,9 +2279,9 @@ msgid "Maximum number of active local stores in RTL dead store elimination."
msgstr "parametrin %qs maksimiarvo on %u"
#: params.def:808
-#, no-c-format
+#, fuzzy, no-c-format
msgid "The number of insns executed before prefetch is completed."
-msgstr ""
+msgstr "Kumoamistoimintojen enimmäismäärä"
#: params.def:815
#, no-c-format
@@ -2320,9 +2319,9 @@ msgid "The maximum number of stmts in loop nest for loop interchange."
msgstr "parametrin %qs maksimiarvo on %u"
#: params.def:868
-#, no-c-format
+#, fuzzy, no-c-format
msgid "The minimum stride ratio for loop interchange to be profitable."
-msgstr ""
+msgstr "Kumoamistoimintojen enimmäismäärä"
#: params.def:879
#, fuzzy, no-c-format
@@ -2400,9 +2399,9 @@ msgid "Whether codegen errors should be ICEs when -fchecking."
msgstr ""
#: params.def:977
-#, no-c-format
+#, fuzzy, no-c-format
msgid "Maximum number of datarefs in loop for building loop data dependencies."
-msgstr ""
+msgstr "parametrin %qs maksimiarvo on %u"
#: params.def:984
#, no-c-format
@@ -2420,9 +2419,9 @@ msgid "Track top N target addresses in indirect-call profile."
msgstr ""
#: params.def:1006
-#, no-c-format
+#, fuzzy, no-c-format
msgid "Maximum number of instructions in basic block to be considered for SLP vectorization."
-msgstr ""
+msgstr "parametrin %qs maksimiarvo on %u"
#: params.def:1011
#, no-c-format
@@ -2645,9 +2644,9 @@ msgid "Use direct poisoning/unpoisoning instructions for variables smaller or eq
msgstr ""
#: params.def:1285
-#, no-c-format
+#, fuzzy, no-c-format
msgid "Maximum number of nested calls to search for control dependencies during uninitialized variable analysis."
-msgstr ""
+msgstr "Kumoamistoimintojen enimmäismäärä"
#: params.def:1291
#, no-c-format
@@ -2665,14 +2664,14 @@ msgid "Scale factor to apply to the number of blocks in a threading path when co
msgstr ""
#: params.def:1306
-#, no-c-format
+#, fuzzy, no-c-format
msgid "Maximum number of instructions to copy when duplicating blocks on a finite state automaton jump thread path."
-msgstr ""
+msgstr "Kumoamistoimintojen enimmäismäärä"
#: params.def:1311
-#, no-c-format
+#, fuzzy, no-c-format
msgid "Maximum number of basic blocks on a finite state automaton jump thread path."
-msgstr ""
+msgstr "Kumoamistoimintojen enimmäismäärä"
#: params.def:1316
#, fuzzy, no-c-format
@@ -2690,9 +2689,9 @@ msgid "Schedule type of omp schedule for loops parallelized by parloops (static,
msgstr ""
#: params.def:1333
-#, no-c-format
+#, fuzzy, no-c-format
msgid "Minimum number of iterations per thread of an innermost parallelized loop."
-msgstr ""
+msgstr "parametrin %qs maksimiarvo on %u"
#: params.def:1339
#, no-c-format
@@ -2700,9 +2699,9 @@ msgid "Maximum recursion depth allowed when querying a property of an SSA name."
msgstr ""
#: params.def:1345
-#, no-c-format
+#, fuzzy, no-c-format
msgid "Maximum number of insns in a basic block to consider for RTL if-conversion."
-msgstr ""
+msgstr "parametrin %qs maksimiarvo on %u"
#: params.def:1351
#, no-c-format
@@ -2755,14 +2754,14 @@ msgid "True if a non-short-circuit operation is optimal."
msgstr ""
#: params.def:1406
-#, no-c-format
+#, fuzzy, no-c-format
msgid "The maximum number of instructions in an inner loop that is being considered for versioning."
-msgstr ""
+msgstr "parametrin %qs maksimiarvo on %u"
#: params.def:1412
-#, no-c-format
+#, fuzzy, no-c-format
msgid "The maximum number of instructions in an outer loop that is being considered for versioning, on top of the instructions in inner loops."
-msgstr ""
+msgstr "parametrin %qs maksimiarvo on %u"
#: c-family/c-format.c:404
#, fuzzy
@@ -4052,7 +4051,6 @@ msgstr "Poista käytöstä POSIX ACLs -tuki"
#: config/rs6000/rs6000.c:4008
#, fuzzy
-#| msgid "-mvsx and -mno-altivec are incompatible"
msgid "%<-mvsx%> and %<-mno-altivec%> are incompatible"
msgstr "-mvsx ja -mno-altivec ovat yhteensopimattomat"
@@ -4293,9 +4291,8 @@ msgid "vector argument passed to unprototyped function"
msgstr "AltiVec-argumentti välitetty funktiolle, jolla ei ole prototyyppiä"
#: config/s390/s390.c:16057
-#, fuzzy
msgid "types differ in signedness"
-msgstr "Tiedostot %s ja %s eroavat\n"
+msgstr "tyypit eroavat etumerkillisyyden osalta"
#: config/s390/s390.c:16067
#, fuzzy
@@ -4374,9 +4371,9 @@ msgid "invalid %%s operand"
msgstr "virheellinen %%s-operandi"
#: config/sparc/sparc.c:9652
-#, c-format
+#, fuzzy, c-format
msgid "floating-point constant not a valid immediate operand"
-msgstr ""
+msgstr "muotomerkkijonolla on epäkelpo operandinumero"
#: config/stormy16/stormy16.c:1738 config/stormy16/stormy16.c:1809
#, fuzzy, c-format
@@ -5697,9 +5694,9 @@ msgid "The value of the PDT LEN parameter '%s' does not agree with that in the d
msgstr "luetellun tyypin jäsenen %qE arvo ei ole kokonaislukuvakio"
#: fortran/trans-decl.c:6025
-#, c-format
+#, fuzzy, c-format
msgid "Actual string length does not match the declared one for dummy argument '%s' (%ld/%ld)"
-msgstr ""
+msgstr "liikaa argumentteja funktiolle %s %q+#D"
#: fortran/trans-decl.c:6033
#, fuzzy, c-format
@@ -6399,20 +6396,24 @@ msgid "Set the default double precision kind to an 8 byte wide type."
msgstr "Tuota koodia big-endian-tilassa"
#: fortran/lang.opt:469
+#, fuzzy
msgid "Set the default integer kind to an 8 byte wide type."
-msgstr ""
+msgstr "Tuota koodia big-endian-tilassa"
#: fortran/lang.opt:473
+#, fuzzy
msgid "Set the default real kind to an 8 byte wide type."
-msgstr ""
+msgstr "Tuota koodia big-endian-tilassa"
#: fortran/lang.opt:477
+#, fuzzy
msgid "Set the default real kind to an 10 byte wide type."
-msgstr ""
+msgstr "Tuota koodia big-endian-tilassa"
#: fortran/lang.opt:481
+#, fuzzy
msgid "Set the default real kind to an 16 byte wide type."
-msgstr ""
+msgstr "Tuota koodia big-endian-tilassa"
#: fortran/lang.opt:485
msgid "Allow dollar signs in entity names."
@@ -6837,8 +6838,9 @@ msgid "-Walloc-zero Warn for calls to allocation functions that specify zero byt
msgstr "muuttuja %qD esitelty %<inline%>:ksi"
#: c-family/c.opt:325
+#, fuzzy
msgid "-Walloca-larger-than=<number>\tWarn on unbounded uses of alloca, and on bounded uses of alloca whose bound can be larger than <number> bytes."
-msgstr ""
+msgstr "muuttuja %qD esitelty %<inline%>:ksi"
#: c-family/c.opt:331
msgid "-Wno-alloca-larger-than Disable Walloca-larger-than= warning. Equivalent to Walloca-larger-than=<SIZE_MAX> or larger."
@@ -7098,8 +7100,9 @@ msgid "Warn about zero-length formats."
msgstr "Varoita nollan pituisista muotoiluista."
#: c-family/c.opt:605
+#, fuzzy
msgid "Warn about function calls with format strings that write past the end of the destination region."
-msgstr ""
+msgstr "%<%.*s%>-direktiivi kirjoittaa jopa %wu tavua %wu tavun kokoiseen alueeseen"
#: c-family/c.opt:610
#, fuzzy
@@ -9578,8 +9581,9 @@ msgid "Enable DWARF line debug info via GNU as."
msgstr ""
#: config/ia64/ia64.opt:110
+#, fuzzy
msgid "Enable earlier placing stop bits for better scheduling."
-msgstr ""
+msgstr "Ota käyttöön RX FPU-käskyjen käyttö."
#: config/ia64/ia64.opt:114 config/spu/spu.opt:72 config/pa/pa.opt:62
#: config/sh/sh.opt:227
@@ -9711,8 +9715,9 @@ msgid "Maximum number of nops to insert for a hint (Default 2)."
msgstr "Kumoamistoimintojen enimmäismäärä"
#: config/spu/spu.opt:60
+#, fuzzy
msgid "Approximate maximum number of instructions to allow between a hint and its branch [125]."
-msgstr ""
+msgstr "parametrin %qs maksimiarvo on %u"
#: config/spu/spu.opt:64
#, fuzzy
@@ -11376,8 +11381,9 @@ msgid "Code size: small, medium or large."
msgstr "Koodin koko: small, medium tai large."
#: config/m32r/m32r.opt:94
+#, fuzzy
msgid "Don't call any cache flush functions."
-msgstr ""
+msgstr "Määrittele käytettävä ABI"
#: config/m32r/m32r.opt:98
#, fuzzy
@@ -11582,8 +11588,9 @@ msgid "Assume ES is zero throughout program execution, use ES: for read-only dat
msgstr ""
#: config/rl78/rl78.opt:97
+#, fuzzy
msgid "Stores the MDUC registers in interrupt handlers for G13 target."
-msgstr ""
+msgstr "Määrittele käytettävä ABI"
#: config/stormy16/stormy16.opt:24
#, fuzzy
@@ -11736,8 +11743,9 @@ msgid "Valid arguments to -mtp=:"
msgstr "Kelvolliset argumentit ovat:\n"
#: config/arm/arm.opt:228
+#, fuzzy
msgid "Thumb: Generate (non-leaf) stack frames even if not needed."
-msgstr ""
+msgstr "Tuota koodia big-endian-tilassa"
#: config/arm/arm.opt:232
#, fuzzy
@@ -12133,8 +12141,9 @@ msgid "Schedule the start and end of the procedure."
msgstr "Aseta ohjelman alkuosoite"
#: config/rs6000/rs6000.opt:259
+#, fuzzy
msgid "Return all structures in memory (AIX default)."
-msgstr ""
+msgstr "Funktion â€%s†paluuarvoa kohdassa %L ei ole asetettu"
#: config/rs6000/rs6000.opt:263
#, fuzzy
@@ -12146,8 +12155,9 @@ msgid "Conform more closely to IBM XLC semantics."
msgstr ""
#: config/rs6000/rs6000.opt:271 config/rs6000/rs6000.opt:275
+#, fuzzy
msgid "Generate software reciprocal divide and square root for better throughput."
-msgstr ""
+msgstr "Varoita käännösaikaisesta nollalla jaosta"
#: config/rs6000/rs6000.opt:279
msgid "Assume that the reciprocal estimate instructions provide more accuracy."
@@ -13797,8 +13807,9 @@ msgid "Change the amount of scheduler lookahead."
msgstr ""
#: config/frv/frv.opt:219
+#, fuzzy
msgid "Assume a large TLS segment."
-msgstr ""
+msgstr "Käytä H8/300-kohdistussääntöjä"
#: config/frv/frv.opt:223
#, fuzzy
@@ -15576,27 +15587,24 @@ msgid "Provide bash completion for options starting with provided string."
msgstr ""
#: common.opt:292
-#, fuzzy
msgid "Display this information."
-msgstr " --help Näytä tämä ohje\n"
+msgstr "Näytä tämä ohje."
#: common.opt:296
msgid "--help=<class>\tDisplay descriptions of a specific class of options. <class> is one or more of optimizers, target, warnings, undocumented, params."
msgstr ""
#: common.opt:417
-#, fuzzy
msgid "Alias for --help=target."
-msgstr "Sama kuin --help=target"
+msgstr "Sama kuin --help=target."
#: common.opt:442
msgid "--param <param>=<value>\tSet parameter <param> to value. See below for a complete list of parameters."
msgstr ""
#: common.opt:470
-#, fuzzy
msgid "-O<number>\tSet optimization level to <number>."
-msgstr "Aseta optimointitasoksi <luku>"
+msgstr "-O<luku>\tAseta optimointitasoksi <luku>."
#: common.opt:474
#, fuzzy
@@ -15618,9 +15626,8 @@ msgid "This switch is deprecated; use -Wextra instead."
msgstr "%J%qD on tavallisesti ei-staattinen funktio"
#: common.opt:535
-#, fuzzy
msgid "Warn about returning structures, unions or arrays."
-msgstr "Varoita tietueiden, unionien ja taulukoiden palauttamisesta"
+msgstr "Varoita tietueiden, unionien ja taulukoiden palauttamisesta."
#: common.opt:539
msgid "Warn if a loop with constant number of iterations triggers undefined behavior."
@@ -15674,24 +15681,20 @@ msgid "Warn when an optimization pass is disabled."
msgstr "Varoita käyttämättömistä funktioista"
#: common.opt:596
-#, fuzzy
msgid "Treat all warnings as errors."
-msgstr "Käsittele kaikki varoitukset virheinä"
+msgstr "Ilmaise kaikki varoitukset virheinä."
#: common.opt:600
-#, fuzzy
msgid "Treat specified warning as error."
-msgstr "Käsittele annettu varoitus virheenä"
+msgstr "Ilmaise annettu varoitus virheenä."
#: common.opt:604
-#, fuzzy
msgid "Print extra (possibly unwanted) warnings."
-msgstr "Näytä ylimääräisiä (mahdollisesti ei-toivottuja) varoituksia"
+msgstr "Näytä ylimääräisiä (mahdollisesti ei-toivottuja) varoituksia."
#: common.opt:608
-#, fuzzy
msgid "Exit on the first error occurred."
-msgstr "Tapahtui virhe"
+msgstr "Poistu ensimmäisen virheen myötä."
#: common.opt:612
msgid "-Wframe-larger-than=<byte-size>\tWarn if a function's stack frame requires in excess of <byte-size>."
@@ -15738,9 +15741,8 @@ msgid "Warn about some C++ One Definition Rule violations during link time optim
msgstr "odotettiin iteraatioesittelyä tai -alustusta"
#: common.opt:665
-#, fuzzy
msgid "Warn about overflow in arithmetic expressions."
-msgstr "Varoita ylivuodosta aritmeettisissa lausekkeissa"
+msgstr "Varoita ylivuodosta aritmeettisissa lausekkeissa."
#: common.opt:669
msgid "During link time optimization warn about mismatched types of global declarations."
@@ -16019,8 +16021,9 @@ msgid "Replace add, compare, branch with branch on count register."
msgstr ""
#: common.opt:1076
+#, fuzzy
msgid "Use profiling information for branch probabilities."
-msgstr ""
+msgstr "säiekohtaista muistia ei tueta tälle kohteelle"
#: common.opt:1080
msgid "Perform branch target load optimization before prologue / epilogue threading."
@@ -16265,8 +16268,9 @@ msgid "Perform early inlining."
msgstr "Suorita uusille äänitetyille tiedotteille:"
#: common.opt:1379
+#, fuzzy
msgid "Perform interprocedural reduction of aggregates."
-msgstr ""
+msgstr "Sähkökatko"
#: common.opt:1383
msgid "Perform unused symbol elimination in debug info."
@@ -16281,14 +16285,12 @@ msgid "Do not suppress C++ class debug information."
msgstr ""
#: common.opt:1395
-#, fuzzy
msgid "Enable exception handling."
-msgstr "Käytä poikkeustenkäsittelyä"
+msgstr "Käytä poikkeustenkäsittelyä."
#: common.opt:1399
-#, fuzzy
msgid "Perform a number of minor, expensive optimizations."
-msgstr "moduulienvälisiä optimointeja ei ole toteutettu C++:lle"
+msgstr "Suorita useita pieniä, kalliita optimointeja."
#: common.opt:1403
msgid "-fexcess-precision=[fast|standard]\tSpecify handling of excess floating-point precision."
@@ -16311,8 +16313,9 @@ msgid "-ffixed-<register>\tMark <register> as being unavailable to the compiler.
msgstr ""
#: common.opt:1446
+#, fuzzy
msgid "Don't allocate floats and doubles in extended-precision registers."
-msgstr ""
+msgstr "kohdemuoto ei tue äärettömyyttä"
#: common.opt:1454
#, fuzzy
@@ -16342,16 +16345,19 @@ msgid "Perform global common subexpression elimination."
msgstr "moduulienvälisiä optimointeja ei ole toteutettu C++:lle"
#: common.opt:1494
+#, fuzzy
msgid "Perform enhanced load motion during global common subexpression elimination."
-msgstr ""
+msgstr "moduulienvälisiä optimointeja ei ole toteutettu C++:lle"
#: common.opt:1498
+#, fuzzy
msgid "Perform store motion after global common subexpression elimination."
-msgstr ""
+msgstr "moduulienvälisiä optimointeja ei ole toteutettu C++:lle"
#: common.opt:1502
+#, fuzzy
msgid "Perform redundant load after store elimination in global common subexpression elimination."
-msgstr ""
+msgstr "moduulienvälisiä optimointeja ei ole toteutettu C++:lle"
#: common.opt:1507
#, fuzzy
@@ -16444,8 +16450,9 @@ msgid "-fstack-reuse=[all|named_vars|none]\tSet stack reuse level for local vari
msgstr ""
#: common.opt:1626
+#, fuzzy
msgid "Convert conditional jumps in innermost loops to branchless equivalents."
-msgstr ""
+msgstr "ehtolausekkeessa on tyyppiristiriita"
#: common.opt:1638
#, fuzzy
@@ -16509,16 +16516,19 @@ msgid "Perform interprocedural constant propagation."
msgstr "Sähkökatko"
#: common.opt:1714
+#, fuzzy
msgid "Perform cloning to make Interprocedural constant propagation stronger."
-msgstr ""
+msgstr "Sähkökatko"
#: common.opt:1722
+#, fuzzy
msgid "Perform interprocedural bitwise constant propagation."
-msgstr ""
+msgstr "Sähkökatko"
#: common.opt:1726
+#, fuzzy
msgid "Perform interprocedural profile propagation."
-msgstr ""
+msgstr "Sähkökatko"
#: common.opt:1730
#, fuzzy
@@ -16531,12 +16541,14 @@ msgid "Discover pure and const functions."
msgstr "epäkelpo tallennusluokka funktiolle %qs"
#: common.opt:1738
+#, fuzzy
msgid "Perform Identical Code Folding for functions and read-only variables."
-msgstr ""
+msgstr "continue-lause silmukan ulkopuolella"
#: common.opt:1742
+#, fuzzy
msgid "Perform Identical Code Folding for functions."
-msgstr ""
+msgstr "continue-lause silmukan ulkopuolella"
#: common.opt:1746
#, fuzzy
@@ -16589,8 +16601,9 @@ msgid "-fira-verbose=<number>\tControl IRA's level of diagnostic messages."
msgstr ""
#: common.opt:1825
+#, fuzzy
msgid "Optimize induction variables on trees."
-msgstr ""
+msgstr "Tuota bittikäskyjä"
#: common.opt:1829
#, fuzzy
@@ -16648,8 +16661,9 @@ msgid "Report various link-time optimization statistics."
msgstr "moduulienvälisiä optimointeja ei ole toteutettu C++:lle"
#: common.opt:1900
+#, fuzzy
msgid "Report various link-time optimization statistics for WPA only."
-msgstr ""
+msgstr "moduulienvälisiä optimointeja ei ole toteutettu C++:lle"
#: common.opt:1904
#, fuzzy
@@ -16916,8 +16930,9 @@ msgid "-flive-patching=[inline-only-static|inline-clone]\tControl IPA optimizati
msgstr ""
#: common.opt:2208
+#, fuzzy
msgid "Relief of register pressure through live range shrinkage."
-msgstr ""
+msgstr "Ota käyttöön RX FPU-käskyjen käyttö."
#: common.opt:2212
#, fuzzy
@@ -16925,8 +16940,9 @@ msgid "Perform a register renaming optimization pass."
msgstr "moduulienvälisiä optimointeja ei ole toteutettu C++:lle"
#: common.opt:2216
+#, fuzzy
msgid "Perform a target dependent instruction fusion optimization pass."
-msgstr ""
+msgstr "moduulienvälisiä optimointeja ei ole toteutettu C++:lle"
#: common.opt:2220
msgid "Reorder basic blocks to improve code placement."
@@ -16945,8 +16961,9 @@ msgid "Reorder functions to improve code placement."
msgstr ""
#: common.opt:2245
+#, fuzzy
msgid "Add a common subexpression elimination pass after loop optimizations."
-msgstr ""
+msgstr "Käytä rekistereitä argumenttien välittämiseen"
#: common.opt:2253
msgid "Disable optimizations that assume default FP rounding behavior."
@@ -16962,12 +16979,14 @@ msgid "Enable register pressure sensitive insn scheduling."
msgstr "Ota käyttöön RX FPU-käskyjen käyttö."
#: common.opt:2265
+#, fuzzy
msgid "Allow speculative motion of non-loads."
-msgstr ""
+msgstr "HALLINTA"
#: common.opt:2269
+#, fuzzy
msgid "Allow speculative motion of some loads."
-msgstr ""
+msgstr "HALLINTA"
#: common.opt:2273
#, fuzzy
@@ -17084,8 +17103,9 @@ msgid "Emit function prologues only before parts of the function that need it, r
msgstr ""
#: common.opt:2399
+#, fuzzy
msgid "Shrink-wrap parts of the prologue and epilogue separately."
-msgstr ""
+msgstr "virheellinen ei-staattisen jäsenfunktion käyttö"
#: common.opt:2403
msgid "Disable optimizations observable by IEEE signaling NaNs."
@@ -17101,8 +17121,9 @@ msgid "Convert floating point constants to single precision constants."
msgstr "ylivuoto implisiittisessä vakiomuunnoksessa"
#: common.opt:2415
+#, fuzzy
msgid "Split lifetimes of induction variables when loops are unrolled."
-msgstr ""
+msgstr "Tuota bittikäskyjä"
#: common.opt:2419
#, fuzzy
@@ -17358,8 +17379,9 @@ msgid "In SSA-PRE optimization on trees, enable partial-partial redundancy elimi
msgstr ""
#: common.opt:2695
+#, fuzzy
msgid "Perform function-local points-to analysis on trees."
-msgstr ""
+msgstr "Sähkökatko"
#: common.opt:2699
#, fuzzy
@@ -17711,17 +17733,17 @@ msgid "Like -pedantic but issue them as errors."
msgstr ""
#: common.opt:3195
+#, fuzzy
msgid "Do not display functions compiled or elapsed time."
-msgstr ""
+msgstr "virheellinen ei-staattisen jäsenfunktion käyttö"
#: common.opt:3227
msgid "Enable verbose output."
msgstr "Ota käyttöön yksityiskohtainen tuloste."
#: common.opt:3231
-#, fuzzy
msgid "Display the compiler's version."
-msgstr " --version Näytä kääntäjän versiotiedot\n"
+msgstr "Näytä kääntäjän versio."
#: common.opt:3235
msgid "Suppress warnings."
@@ -17732,9 +17754,8 @@ msgid "Create a shared library."
msgstr "Luo jaettu kirjasto."
#: common.opt:3290
-#, fuzzy
msgid "Don't create a dynamically linked position independent executable."
-msgstr "Älä luo paikkariippumatonta suoritettavaa tiedostoa."
+msgstr "Älä luo dynaamisesti linkitettyä paikkariippumatonta suoritettavaa tiedostoa."
#: common.opt:3294
#, fuzzy
@@ -18519,9 +18540,9 @@ msgid "%K%qD specified bound %E exceeds the size %E of unterminated array"
msgstr "%qE esitelty funktion palauttavana funktiona"
#: builtins.c:3127
-#, gcc-internal-format
+#, fuzzy, gcc-internal-format
msgid "%K%qD specified bound %E may exceed the size of at most %E of unterminated array"
-msgstr ""
+msgstr "%qE esitelty funktion palauttavana funktiona"
#: builtins.c:3156
#, fuzzy, gcc-internal-format
@@ -18529,14 +18550,14 @@ msgid "%K%qD specified bound [%wu, %wu] exceeds maximum object size %E"
msgstr "Funktion %s argumentti kohdassa %L on negatiivinen"
#: builtins.c:3179
-#, gcc-internal-format
+#, fuzzy, gcc-internal-format
msgid "%K%qD specified bound [%wu, %wu] exceeds the size %E of unterminated array"
-msgstr ""
+msgstr "%qE esitelty funktion palauttavana funktiona"
#: builtins.c:3181
-#, gcc-internal-format
+#, fuzzy, gcc-internal-format
msgid "%K%qD specified bound [%wu, %wu] may exceed the size of at most %E of unterminated array"
-msgstr ""
+msgstr "%qE esitelty funktion palauttavana funktiona"
#: builtins.c:3411
#, fuzzy, gcc-internal-format
@@ -18804,9 +18825,9 @@ msgid "%Kargument %i range [%E, %E] exceeds maximum object size %E"
msgstr "Funktion %s argumentti kohdassa %L on negatiivinen"
#: calls.c:1454
-#, gcc-internal-format
+#, fuzzy, gcc-internal-format
msgid "%Kproduct %<%E * %E%> of arguments %i and %i exceeds %<SIZE_MAX%>"
-msgstr ""
+msgstr "%Kargumentin %i arvo %qE ylittää olion enimmäiskoon %E"
#: calls.c:1460
#, fuzzy, gcc-internal-format
@@ -19201,19 +19222,19 @@ msgid "loop %d%'s header is not a loop header"
msgstr "säiekohtaista muistia ei tueta tälle kohteelle"
#: cfgloop.c:1492
-#, gcc-internal-format
+#, fuzzy, gcc-internal-format
msgid "loop %d%'s header does not have exactly 2 entries"
-msgstr ""
+msgstr "säiekohtaista muistia ei tueta tälle kohteelle"
#: cfgloop.c:1499
-#, gcc-internal-format
+#, fuzzy, gcc-internal-format
msgid "loop %d%'s latch does not have an edge to its header"
-msgstr ""
+msgstr "säiekohtaista muistia ei tueta tälle kohteelle"
#: cfgloop.c:1504
-#, gcc-internal-format
+#, fuzzy, gcc-internal-format
msgid "loop %d%'s latch is not dominated by its header"
-msgstr ""
+msgstr "säiekohtaista muistia ei tueta tälle kohteelle"
#: cfgloop.c:1512
#, gcc-internal-format
@@ -19221,9 +19242,9 @@ msgid "loop %d%'s latch does not have exactly 1 successor"
msgstr ""
#: cfgloop.c:1517
-#, gcc-internal-format
+#, fuzzy, gcc-internal-format
msgid "loop %d%'s latch does not have header as successor"
-msgstr ""
+msgstr "säiekohtaista muistia ei tueta tälle kohteelle"
#: cfgloop.c:1522
#, gcc-internal-format
@@ -19231,9 +19252,9 @@ msgid "loop %d%'s latch does not belong directly to it"
msgstr ""
#: cfgloop.c:1528
-#, gcc-internal-format
+#, fuzzy, gcc-internal-format
msgid "loop %d%'s header does not belong directly to it"
-msgstr ""
+msgstr "säiekohtaista muistia ei tueta tälle kohteelle"
#: cfgloop.c:1534
#, gcc-internal-format
@@ -19341,14 +19362,14 @@ msgid "No region crossing jump at section boundary in bb %i"
msgstr "väärä määrä argumentteja funktiolle %<va_start%>"
#: cfgrtl.c:2531
-#, gcc-internal-format
+#, fuzzy, gcc-internal-format
msgid "EDGE_CROSSING missing across section boundary"
-msgstr ""
+msgstr "väärä määrä argumentteja funktiolle %<va_start%>"
#: cfgrtl.c:2561
-#, gcc-internal-format, gfc-internal-format
+#, fuzzy, gcc-internal-format, gfc-internal-format
msgid "Region crossing jump across same section in bb %i"
-msgstr ""
+msgstr "väärä määrä argumentteja funktiolle %<va_start%>"
#: cfgrtl.c:2568
#, gcc-internal-format, gfc-internal-format
@@ -19496,9 +19517,9 @@ msgid "cgraph count invalid"
msgstr "oikealle siirron lukumäärä on negatiivinen"
#: cgraph.c:3128
-#, gcc-internal-format
+#, fuzzy, gcc-internal-format
msgid "inline clone in same comdat group list"
-msgstr ""
+msgstr "virheellinen sisäinen makro â€%sâ€"
#: cgraph.c:3133
#, fuzzy, gcc-internal-format
@@ -19571,9 +19592,9 @@ msgid "inlined_to pointer refers to itself"
msgstr "Väärä taikaluku --- RESERVED_13"
#: cgraph.c:3268
-#, gcc-internal-format
+#, fuzzy, gcc-internal-format
msgid "cgraph_node has wrong clone_of"
-msgstr ""
+msgstr "ei-muuttujan %qD esittely %<for%>-silmukan alkuesittelyssä"
#: cgraph.c:3281
#, fuzzy, gcc-internal-format
@@ -19586,9 +19607,9 @@ msgid "cgraph_node is in clone list but it is not clone"
msgstr "ei-muuttujan %qD esittely %<for%>-silmukan alkuesittelyssä"
#: cgraph.c:3292
-#, gcc-internal-format
+#, fuzzy, gcc-internal-format
msgid "cgraph_node has wrong prev_clone pointer"
-msgstr ""
+msgstr "ei-muuttujan %qD esittely %<for%>-silmukan alkuesittelyssä"
#: cgraph.c:3297
#, gcc-internal-format
@@ -19921,7 +19942,6 @@ msgstr "dynaamista riippuvuutta %s ei löytynyt"
#: collect2.c:2672
#, fuzzy, gcc-internal-format
-#| msgid "unable to open dynamic dependency '%s'"
msgid "unable to open dynamic dependency %qs"
msgstr "ei voida avata dynaamista riippuvuutta â€%sâ€"
@@ -20041,9 +20061,9 @@ msgid "number of counters in profile data for function %qD does not match its pr
msgstr ""
#: coverage.c:367
-#, gcc-internal-format
+#, fuzzy, gcc-internal-format
msgid "the control flow of function %qD does not match its profile data (counter %qs)"
-msgstr ""
+msgstr "â€%s†ei ole oikea profiilidatatiedosto â€%sâ€:lle"
#: coverage.c:386
#, fuzzy, gcc-internal-format
@@ -20071,9 +20091,9 @@ msgid "cannot open %s"
msgstr "tiedostoa %s ei voi avata"
#: data-streamer-in.c:53
-#, gcc-internal-format
+#, fuzzy, gcc-internal-format
msgid "bytecode stream: string too long for the string table"
-msgstr ""
+msgstr "ei voitu luoda uutta ELF-lohkoa: %s"
#: data-streamer-in.c:84 data-streamer-in.c:113
#, fuzzy, gcc-internal-format
@@ -20107,7 +20127,6 @@ msgstr "%s[%s] %s%s%s"
#: dbgcnt.c:188
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid " %s"
msgid " %s"
msgstr " %s"
@@ -20217,9 +20236,9 @@ msgid "region_array is corrupted for region %i"
msgstr "oikealle siirron lukumäärä on negatiivinen"
#: except.c:3428 except.c:3459
-#, gcc-internal-format, gfc-internal-format
+#, fuzzy, gcc-internal-format, gfc-internal-format
msgid "lp_array is corrupted for lp %i"
-msgstr ""
+msgstr "oikealle siirron lukumäärä on negatiivinen"
#: except.c:3445
#, gcc-internal-format, gfc-internal-format
@@ -20332,9 +20351,9 @@ msgid "comparison is always %d"
msgstr "vertailu on aina %d johtuen bittikentän leveydestä"
#: fold-const.c:6168
-#, gcc-internal-format
+#, fuzzy, gcc-internal-format
msgid "%<or%> of unmatched not-equal tests is always 1"
-msgstr ""
+msgstr "looginen"
#: fold-const.c:6173
#, fuzzy, gcc-internal-format
@@ -20459,7 +20478,6 @@ msgstr "polku puuttuu %qs:n jälkeen"
#: gcc.c:3078
#, fuzzy, gcc-internal-format
-#| msgid "-pipe not supported"
msgid "%<-pipe%> not supported"
msgstr "-pipe ei ole tuettu"
@@ -20938,8 +20956,9 @@ msgid "%G%qD destination unchanged after copying no bytes from a string of lengt
msgstr "%<%.*s%>-direktiivin tuloste saattaa katketa kirjoittaessa jopa %wu tavua %wu–%wu tavun kokoiseen alueeseen"
#: gimple-fold.c:1857
+#, fuzzy
msgid "%G%qD destination unchanged after copying no bytes"
-msgstr ""
+msgstr "%<%.*s%>-direktiivin tuloste saattaa katketa kirjoittaessa jopa %wu tavua %wu–%wu tavun kokoiseen alueeseen"
#: gimple-fold.c:2225 tree-ssa-strlen.c:2181
#, fuzzy
@@ -20992,9 +21011,9 @@ msgid "%qE output truncated before the last format character"
msgstr ""
#: gimple-ssa-sprintf.c:2511 gimple-ssa-sprintf.c:2631
-#, gcc-internal-format
+#, fuzzy, gcc-internal-format
msgid "%qE may write a terminating nul past the end of the destination"
-msgstr ""
+msgstr "%<%.*s%>-direktiivi kirjoittaa jopa %wu tavua %wu tavun kokoiseen alueeseen"
#: gimple-ssa-sprintf.c:2513 gimple-ssa-sprintf.c:2633
#, fuzzy, gcc-internal-format
@@ -21050,7 +21069,7 @@ msgstr "%<%.*s%>-direktiivin tuloste saattaa katketa kirjoittaessa jopa %wu tavu
#: gimple-ssa-sprintf.c:2571
#, gcc-internal-format
msgid "%<%.*s%> directive writing likely %wu or more bytes into a region of size %wu"
-msgstr "%<%.*s%>-direktiivi kirjoittanee %wu tavua tai enemmän %wu tavun kokoiseen alueeseen"
+msgstr "%<%.*s%>-direktiivi kirjoittanee ainakin %wu tavua %wu tavun kokoiseen alueeseen"
#: gimple-ssa-sprintf.c:2580
#, gcc-internal-format
@@ -21266,13 +21285,11 @@ msgstr[1] ""
#: gimple-ssa-sprintf.c:3050
#, fuzzy, gcc-internal-format
-#| msgid "%qE output between %wu and %wu bytes into a destination of size %wu"
msgid "%qE output between %wu and %wu bytes"
msgstr "%qE tulostaa %wu–%wu tavua %wu tavun kokoiseen kohteeseen"
#: gimple-ssa-sprintf.c:3054
#, fuzzy, gcc-internal-format
-#| msgid "%qE output %wu or more bytes (assuming %wu) into a destination of size %wu"
msgid "%qE output %wu or more bytes (assuming %wu)"
msgstr "%qE tulostaa vähintään %wu tavua (oletetaan %wu) %wu tavun kokoiseen kohteeseen"
@@ -21297,14 +21314,14 @@ msgid "specified bound %wu exceeds maximum object size %wu"
msgstr "paikallisten objektien kokonaiskoko on liian suuri"
#: gimple-ssa-sprintf.c:4107
-#, gcc-internal-format
+#, fuzzy, gcc-internal-format
msgid "specified bound %wu exceeds %<INT_MAX%>"
-msgstr ""
+msgstr "paikallisten objektien kokonaiskoko on liian suuri"
#: gimple-ssa-sprintf.c:4128
-#, gcc-internal-format
+#, fuzzy, gcc-internal-format
msgid "specified bound range [%wu, %wu] exceeds %<INT_MAX%>"
-msgstr ""
+msgstr "Funktion %s argumentti kohdassa %L on negatiivinen"
#: gimple-ssa-sprintf.c:4179
#, fuzzy
@@ -21312,9 +21329,9 @@ msgid "%Gnull destination pointer"
msgstr "nollaosoitin"
#: gimple-ssa-sprintf.c:4197
-#, gcc-internal-format
+#, fuzzy, gcc-internal-format
msgid "specified bound %wu exceeds the size %wu of the destination object"
-msgstr ""
+msgstr "%qE esitelty funktion palauttavana funktiona"
#: gimple-ssa-sprintf.c:4209
#, fuzzy
@@ -21402,38 +21419,45 @@ msgid "argument to %<alloca%> is zero"
msgstr "%<__builtin_prefetch%>-funktion toinen argumentti on epäkelpo; käytetään nollaa"
#: gimple-ssa-warn-restrict.c:1437
+#, fuzzy
msgid "%G%qD accessing %wu byte at offsets %s and %s overlaps %wu byte at offset %s"
-msgstr ""
+msgstr "%<%.*s%>-direktiivi kirjoittaa jopa %wu tavua %wu tavun kokoiseen alueeseen"
#: gimple-ssa-warn-restrict.c:1439
+#, fuzzy
msgid "%G%qD accessing %wu byte at offsets %s and %s overlaps %wu bytes at offset %s"
-msgstr ""
+msgstr "%<%.*s%>-direktiivi kirjoittaa jopa %wu tavua %wu tavun kokoiseen alueeseen"
#: gimple-ssa-warn-restrict.c:1443
+#, fuzzy
msgid "%G%qD accessing %wu bytes at offsets %s and %s overlaps %wu byte at offset %s"
-msgstr ""
+msgstr "%<%.*s%>-direktiivi kirjoittaa jopa %wu tavua %wu tavun kokoiseen alueeseen"
#: gimple-ssa-warn-restrict.c:1445
+#, fuzzy
msgid "%G%qD accessing %wu bytes at offsets %s and %s overlaps %wu bytes at offset %s"
-msgstr ""
+msgstr "%<%.*s%>-direktiivi kirjoittaa jopa %wu tavua %wu tavun kokoiseen alueeseen"
#: gimple-ssa-warn-restrict.c:1452
+#, fuzzy
msgid "%G%qD accessing %wu byte at offsets %s and %s overlaps between %wu and %wu bytes at offset %s"
msgid_plural "%G%qD accessing %wu bytes at offsets %s and %s overlaps between %wu and %wu bytes at offset %s"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%<%.*s%>-direktiivi kirjoittaa jopa %wu tavua %wu tavun kokoiseen alueeseen"
+msgstr[1] "%<%.*s%>-direktiivi kirjoittaa jopa %wu tavua %wu tavun kokoiseen alueeseen"
#: gimple-ssa-warn-restrict.c:1462
+#, fuzzy
msgid "%G%qD accessing %wu byte at offsets %s and %s overlaps %wu or more bytes at offset %s"
msgid_plural "%G%qD accessing %wu bytes at offsets %s and %s overlaps %wu or more bytes at offset %s"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%<%.*s%>-direktiivi kirjoittaa jopa %wu tavua %wu tavun kokoiseen alueeseen"
+msgstr[1] "%<%.*s%>-direktiivi kirjoittaa jopa %wu tavua %wu tavun kokoiseen alueeseen"
#: gimple-ssa-warn-restrict.c:1475
+#, fuzzy
msgid "%G%qD accessing between %wu and %wu bytes at offsets %s and %s overlaps %wu byte at offset %s"
msgid_plural "%G%qD accessing between %wu and %wu bytes at offsets %s and %s overlaps %wu bytes at offset %s"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%<%.*s%>-direktiivi kirjoittaa jopa %wu tavua %wu tavun kokoiseen alueeseen"
+msgstr[1] "%<%.*s%>-direktiivi kirjoittaa jopa %wu tavua %wu tavun kokoiseen alueeseen"
#: gimple-ssa-warn-restrict.c:1485
#, fuzzy
@@ -21441,46 +21465,54 @@ msgid "%G%qD accessing between %wu and %wu bytes at offsets %s and %s overlaps b
msgstr "%<%.*s%>-direktiivi kirjoittaa jopa %wu tavua %wu tavun kokoiseen alueeseen"
#: gimple-ssa-warn-restrict.c:1493
+#, fuzzy
msgid "%G%qD accessing between %wu and %wu bytes at offsets %s and %s overlaps %wu or more bytes at offset %s"
-msgstr ""
+msgstr "%<%.*s%>-direktiivi kirjoittaa jopa %wu tavua %wu tavun kokoiseen alueeseen"
#: gimple-ssa-warn-restrict.c:1506
+#, fuzzy
msgid "%G%qD accessing %wu or more bytes at offsets %s and %s overlaps %wu byte at offset %s"
msgid_plural "%G%qD accessing %wu or more bytes at offsets %s and %s overlaps %wu bytes at offset %s"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%<%.*s%>-direktiivi kirjoittaa jopa %wu tavua %wu tavun kokoiseen alueeseen"
+msgstr[1] "%<%.*s%>-direktiivi kirjoittaa jopa %wu tavua %wu tavun kokoiseen alueeseen"
#: gimple-ssa-warn-restrict.c:1514
+#, fuzzy
msgid "%G%qD accessing %wu or more bytes at offsets %s and %s overlaps between %wu and %wu bytes at offset %s"
-msgstr ""
+msgstr "%<%.*s%>-direktiivi kirjoittaa jopa %wu tavua %wu tavun kokoiseen alueeseen"
#: gimple-ssa-warn-restrict.c:1521
+#, fuzzy
msgid "%G%qD accessing %wu or more bytes at offsets %s and %s overlaps %wu or more bytes at offset %s"
-msgstr ""
+msgstr "%<%.*s%>-direktiivi kirjoittaa jopa %wu tavua %wu tavun kokoiseen alueeseen"
#: gimple-ssa-warn-restrict.c:1549
+#, fuzzy
msgid "%G%qD accessing %wu byte may overlap %wu byte"
msgid_plural "%G%qD accessing %wu bytes may overlap %wu byte"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%<%.*s%>-direktiivi kirjoittaa jopa %wu tavua %wu tavun kokoiseen alueeseen"
+msgstr[1] "%<%.*s%>-direktiivi kirjoittaa jopa %wu tavua %wu tavun kokoiseen alueeseen"
#: gimple-ssa-warn-restrict.c:1556
+#, fuzzy
msgid "%G%qD accessing %wu byte at offsets %s and %s may overlap %wu byte at offset %s"
msgid_plural "%G%qD accessing %wu bytes at offsets %s and %s may overlap %wu byte at offset %s"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%<%.*s%>-direktiivi kirjoittaa jopa %wu tavua %wu tavun kokoiseen alueeseen"
+msgstr[1] "%<%.*s%>-direktiivi kirjoittaa jopa %wu tavua %wu tavun kokoiseen alueeseen"
#: gimple-ssa-warn-restrict.c:1567
+#, fuzzy
msgid "%G%qD accessing %wu byte may overlap up to %wu bytes"
msgid_plural "%G%qD accessing %wu bytes may overlap up to %wu bytes"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%<%.*s%>-direktiivi kirjoittaa jopa %wu tavua %wu tavun kokoiseen alueeseen"
+msgstr[1] "%<%.*s%>-direktiivi kirjoittaa jopa %wu tavua %wu tavun kokoiseen alueeseen"
#: gimple-ssa-warn-restrict.c:1574
+#, fuzzy
msgid "%G%qD accessing %wu byte at offsets %s and %s may overlap up to %wu bytes at offset %s"
msgid_plural "%G%qD accessing %wu bytes at offsets %s and %s may overlap up to %wu bytes at offset %s"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%<%.*s%>-direktiivi kirjoittaa jopa %wu tavua %wu tavun kokoiseen alueeseen"
+msgstr[1] "%<%.*s%>-direktiivi kirjoittaa jopa %wu tavua %wu tavun kokoiseen alueeseen"
#: gimple-ssa-warn-restrict.c:1587
#, fuzzy
@@ -21490,16 +21522,18 @@ msgstr[0] "%<%.*s%>-direktiivi kirjoittaa jopa %wu tavua %wu tavun kokoiseen alu
msgstr[1] "%<%.*s%>-direktiivi kirjoittaa jopa %wu tavua %wu tavun kokoiseen alueeseen"
#: gimple-ssa-warn-restrict.c:1594
+#, fuzzy
msgid "%G%qD accessing between %wu and %wu bytes at offsets %s and %s may overlap %wu byte at offset %s"
msgid_plural "%G%qD accessing between %wu and %wu bytes at offsets %s and %s may overlap up to %wu bytes at offset %s"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%<%.*s%>-direktiivi kirjoittaa jopa %wu tavua %wu tavun kokoiseen alueeseen"
+msgstr[1] "%<%.*s%>-direktiivi kirjoittaa jopa %wu tavua %wu tavun kokoiseen alueeseen"
#: gimple-ssa-warn-restrict.c:1606
+#, fuzzy
msgid "%G%qD accessing %wu or more bytes at offsets %s and %s may overlap %wu byte at offset %s"
msgid_plural "%G%qD accessing %wu or more bytes at offsets %s and %s may overlap up to %wu bytes at offset %s"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%<%.*s%>-direktiivi kirjoittaa jopa %wu tavua %wu tavun kokoiseen alueeseen"
+msgstr[1] "%<%.*s%>-direktiivi kirjoittaa jopa %wu tavua %wu tavun kokoiseen alueeseen"
#: gimple-ssa-warn-restrict.c:1652
#, fuzzy
@@ -21606,10 +21640,10 @@ msgstr "Varoita koodista, jota ei koskaan suoriteta"
#: gimplify.c:2215 gimplify.c:2223
#, gcc-internal-format
msgid "this statement may fall through"
-msgstr ""
+msgstr "suoritus saattaa jatkua tämän lausekkeen jälkeen"
#: gimplify.c:2225
-#, fuzzy, gcc-internal-format
+#, gcc-internal-format
msgid "here"
msgstr "täällä"
@@ -22346,19 +22380,19 @@ msgid "variable %qs has been referenced in offloaded code but hasn%'t been marke
msgstr ""
#: lto-cgraph.c:1276
-#, gcc-internal-format, gfc-internal-format
+#, fuzzy, gcc-internal-format, gfc-internal-format
msgid "bytecode stream: found multiple instances of cgraph node with uid %d"
-msgstr ""
+msgstr "ei voitu luoda uutta ELF-lohkoa: %s"
#: lto-cgraph.c:1444
-#, gcc-internal-format
+#, fuzzy, gcc-internal-format
msgid "bytecode stream: no caller found while reading edge"
-msgstr ""
+msgstr "ei voitu luoda uutta ELF-lohkoa: %s"
#: lto-cgraph.c:1450
-#, gcc-internal-format
+#, fuzzy, gcc-internal-format
msgid "bytecode stream: no callee found while reading edge"
-msgstr ""
+msgstr "ei voitu luoda uutta ELF-lohkoa: %s"
#: lto-cgraph.c:1524
#, fuzzy, gcc-internal-format
@@ -22397,9 +22431,9 @@ msgid "compressed stream: %s"
msgstr "Vedos (%s) on tiivistetty\n"
#: lto-section-in.c:445
-#, gcc-internal-format, gfc-internal-format
+#, fuzzy, gcc-internal-format, gfc-internal-format
msgid "bytecode stream: trying to read %d bytes after the end of the input buffer"
-msgstr ""
+msgstr "ei voitu luoda uutta ELF-lohkoa: %s"
#: lto-section-in.c:456
#, gcc-internal-format, gfc-internal-format
@@ -22578,7 +22612,6 @@ msgstr "%qE-attribuuttia ei huomioida"
#: multiple_target.c:392
#, fuzzy, gcc-internal-format
-#| msgid "multiple default labels in one switch"
msgid "multiple %<default%> targets were set"
msgstr "useita default-nimikkeitä samassa switch-lauseessa"
@@ -22658,14 +22691,14 @@ msgid "orphaned %qs construct"
msgstr "väärin aseteltu [:upper:]- ja/tai [:lower:]-rakenne"
#: omp-low.c:2704
-#, gcc-internal-format
+#, fuzzy, gcc-internal-format
msgid "%<#pragma omp cancel for%> inside %<nowait%> for construct"
-msgstr ""
+msgstr "<this%>-sanaa ei voi käyttää tässä yhteydessä"
#: omp-low.c:2709
-#, gcc-internal-format
+#, fuzzy, gcc-internal-format
msgid "%<#pragma omp cancel for%> inside %<ordered%> for construct"
-msgstr ""
+msgstr "<this%>-sanaa ei voi käyttää tässä yhteydessä"
#: omp-low.c:2729 omp-low.c:2742
#, fuzzy, gcc-internal-format
@@ -23693,9 +23726,9 @@ msgid "output operand is constant in %<asm%>"
msgstr "virheellinen lvalue asm-tulosteessa %d"
#: rtl.c:859
-#, gcc-internal-format, gfc-internal-format
+#, fuzzy, gcc-internal-format, gfc-internal-format
msgid "RTL check: access of elt %d of '%s' with last elt %d in %s, at %s:%d"
-msgstr ""
+msgstr "verifiointi epäonnistui kohdassa PC=%d: %s"
#: rtl.c:869
#, fuzzy, gcc-internal-format, gfc-internal-format
@@ -23703,9 +23736,9 @@ msgid "RTL check: expected elt %d type '%c', have '%c' (rtx %s) in %s, at %s:%d"
msgstr "verifiointi epäonnistui kohdassa PC=%d: %s"
#: rtl.c:879
-#, gcc-internal-format, gfc-internal-format
+#, fuzzy, gcc-internal-format, gfc-internal-format
msgid "RTL check: expected elt %d type '%c' or '%c', have '%c' (rtx %s) in %s, at %s:%d"
-msgstr ""
+msgstr "verifiointi epäonnistui kohdassa PC=%d: %s"
#: rtl.c:888
#, fuzzy, gcc-internal-format, gfc-internal-format
@@ -23728,19 +23761,19 @@ msgid "RTL check: attempt to treat non-block symbol as a block symbol in %s, at
msgstr ""
#: rtl.c:946
-#, gcc-internal-format, gfc-internal-format
+#, fuzzy, gcc-internal-format, gfc-internal-format
msgid "RTL check: access of hwi elt %d of vector with last elt %d in %s, at %s:%d"
-msgstr ""
+msgstr "verifiointi epäonnistui kohdassa PC=%d: %s"
#: rtl.c:956
-#, gcc-internal-format, gfc-internal-format
+#, fuzzy, gcc-internal-format, gfc-internal-format
msgid "RTL check: access of elt %d of vector with last elt %d in %s, at %s:%d"
-msgstr ""
+msgstr "verifiointi epäonnistui kohdassa PC=%d: %s"
#: rtl.c:967
-#, gcc-internal-format, gfc-internal-format
+#, fuzzy, gcc-internal-format, gfc-internal-format
msgid "RTL flag check: %s used with unexpected rtx code '%s' in %s, at %s:%d"
-msgstr ""
+msgstr "verifiointi epäonnistui kohdassa PC=%d: %s"
#: stmt.c:215
#, fuzzy, gcc-internal-format
@@ -23989,7 +24022,6 @@ msgstr ""
#: symtab.c:1158
#, fuzzy, gcc-internal-format
-#| msgid "implicit declaration of function %qE"
msgid "implicit_section flag is set but section isn%'t"
msgstr "funktio %qE esitelty implisiittisesti"
@@ -24795,9 +24827,9 @@ msgid "vector types expected in sad expression"
msgstr "vektoriylivuoto lausekkeessa"
#: tree-cfg.c:4258
-#, gcc-internal-format
+#, fuzzy, gcc-internal-format
msgid "type mismatch in BIT_INSERT_EXPR"
-msgstr ""
+msgstr "virheellinen vastaanottajatyyppi %qs"
#: tree-cfg.c:4268
#, fuzzy, gcc-internal-format
@@ -25172,9 +25204,9 @@ msgid "BB %i last statement has incorrectly set lp"
msgstr "nimettömällä kentällä on vaillinainen tyyppi"
#: tree-eh.c:4780
-#, gcc-internal-format, gfc-internal-format
+#, fuzzy, gcc-internal-format, gfc-internal-format
msgid "BB %i is missing an EH edge"
-msgstr ""
+msgstr "fr30_print_operand: tunnistamaton %%b-koodi"
#: tree-eh.c:4786
#, fuzzy, gcc-internal-format, gfc-internal-format
@@ -25182,9 +25214,9 @@ msgid "Incorrect EH edge %i->%i"
msgstr "â€Iâ€-lippu"
#: tree-eh.c:4820 tree-eh.c:4839
-#, gcc-internal-format, gfc-internal-format
+#, fuzzy, gcc-internal-format, gfc-internal-format
msgid "BB %i is missing an edge"
-msgstr ""
+msgstr "fr30_print_operand: tunnistamaton %%b-koodi"
#: tree-eh.c:4856
#, gcc-internal-format, gfc-internal-format
@@ -25197,9 +25229,9 @@ msgid "BB %i has incorrect edge"
msgstr "nimettömällä kentällä on vaillinainen tyyppi"
#: tree-eh.c:4871
-#, gcc-internal-format, gfc-internal-format
+#, fuzzy, gcc-internal-format, gfc-internal-format
msgid "BB %i has incorrect fallthru edge"
-msgstr ""
+msgstr "nimettömällä kentällä on vaillinainen tyyppi"
#: tree-inline.c:3658
#, gcc-internal-format
@@ -25371,9 +25403,9 @@ msgid "use operand missing for stmt"
msgstr "$-operandinumero puuttuu muotoilussa"
#: tree-ssa-operands.c:1035
-#, gcc-internal-format
+#, fuzzy, gcc-internal-format
msgid "stmt volatile flag not up-to-date"
-msgstr ""
+msgstr "tyypillä %qE on virtuaalisia jäsenfunktioita"
#: tree-ssa-strlen.c:2095
#, fuzzy
@@ -25526,9 +25558,9 @@ msgid "definition in block %i does not dominate use in block %i"
msgstr "%qD ei ole luokka eikä nimiavaruus"
#: tree-ssa.c:882
-#, gcc-internal-format, gfc-internal-format
+#, fuzzy, gcc-internal-format, gfc-internal-format
msgid "definition in block %i follows the use"
-msgstr ""
+msgstr "%qD ei ole luokka eikä nimiavaruus"
#: tree-ssa.c:889
#, gcc-internal-format
@@ -25736,9 +25768,9 @@ msgid "tree check: accessed operand %d of %s with %d operands in %s, at %s:%d"
msgstr "verifiointi epäonnistui kohdassa PC=%d: %s"
#: tree.c:10124
-#, gcc-internal-format, gfc-internal-format
+#, fuzzy, gcc-internal-format, gfc-internal-format
msgid "tree check: accessed operand %d of omp_clause %s with %d operands in %s, at %s:%d"
-msgstr ""
+msgstr "verifiointi epäonnistui kohdassa PC=%d: %s"
#: tree.c:13236
#, gcc-internal-format
@@ -25876,9 +25908,9 @@ msgid "Main variant is not defined"
msgstr "â€%s†on määrittelemättä"
#: tree.c:14312
-#, gcc-internal-format
+#, fuzzy, gcc-internal-format
msgid "TYPE_MAIN_VARIANT has different TYPE_MAIN_VARIANT"
-msgstr ""
+msgstr "tyyppitäsmäämättömyys komponenttiviitteessä"
#: tree.c:14324
#, gcc-internal-format
@@ -26021,9 +26053,9 @@ msgid "TYPE_STRING_FLAG is set on wrong type code"
msgstr ""
#: tree.c:14634
-#, gcc-internal-format
+#, fuzzy, gcc-internal-format
msgid "TYPE_METHOD_BASETYPE is not main variant"
-msgstr ""
+msgstr "funktiokutsu epäsopivan tyypin läpi"
#: tree.c:14641
#, fuzzy, gcc-internal-format
@@ -26101,9 +26133,9 @@ msgid "invalid register name for %q+D"
msgstr "%q+D:n virheellinen uudelleenesittely"
#: varasm.c:1409
-#, gcc-internal-format
+#, fuzzy, gcc-internal-format
msgid "data type of %q+D isn%'t suitable for a register"
-msgstr ""
+msgstr "sisäkkäisessä funktiossa käytetty globaalia rekisterimuuttujaa %qD"
#: varasm.c:1412
#, fuzzy, gcc-internal-format
@@ -26206,9 +26238,9 @@ msgid "ifunc is not supported on this target"
msgstr "Ei ole tuettu"
#: varasm.c:5963
-#, gcc-internal-format
+#, fuzzy, gcc-internal-format
msgid "weakref %q+D ultimately targets itself"
-msgstr ""
+msgstr "jäsenfunktiota %qD ei voi kutsua ilman oliota"
#: varasm.c:5965
#, fuzzy, gcc-internal-format
@@ -26460,9 +26492,9 @@ msgid "constructor priorities are not supported"
msgstr "Muodostin %qs"
#: c-family/c-attribs.c:1558
-#, gcc-internal-format, gfc-internal-format
+#, fuzzy, gcc-internal-format, gfc-internal-format
msgid "destructor priorities from 0 to %d are reserved for the implementation"
-msgstr ""
+msgstr "Muodostin %qs"
#: c-family/c-attribs.c:1563
#, fuzzy, gcc-internal-format, gfc-internal-format
@@ -26733,9 +26765,9 @@ msgstr "%qE-attribuutti pätee vain funktioihin"
#: c-family/c-attribs.c:2829 c-family/c-attribs.c:2870
#: c-family/c-attribs.c:2894
-#, fuzzy, gcc-internal-format
+#, gcc-internal-format
msgid "%qE attribute ignored on a function returning %qT"
-msgstr "%qE-attribuuttia ei huomioida %qE:lle"
+msgstr "%qE-attribuuttia ei huomioida %qT:n palauttavalle funktiolle"
#: c-family/c-attribs.c:2913
#, fuzzy, gcc-internal-format
@@ -27450,25 +27482,21 @@ msgstr "sisäinen funktio %q+D esitelty ei-funktiona"
#: c-family/c-common.c:8162
#, fuzzy, gcc-internal-format
-#| msgid "size of array %qD is not an integral constant-expression"
msgid "size of array %qE is not a constant expression"
msgstr "taulukon %qD koko ei ole kokonaislukutyyppinen vakiolauseke"
#: c-family/c-common.c:8165
#, fuzzy, gcc-internal-format
-#| msgid "size of array is not an integral constant-expression"
msgid "size of array is not a constant expression"
msgstr "taulukon koko ei ole kokonaislukutyyppinen vakiolauseke"
#: c-family/c-common.c:8169
#, fuzzy, gcc-internal-format
-#| msgid "size of array %qE is negative"
msgid "size %qE of array %qE is negative"
msgstr "taulukon %qE koko on negatiivinen"
#: c-family/c-common.c:8172
#, fuzzy, gcc-internal-format
-#| msgid "size of array is negative"
msgid "size %qE of array is negative"
msgstr "taulukon koko on negatiivinen"
@@ -28015,9 +28043,9 @@ msgid "%<#pragma omp atomic update%> uses two different variables for memory"
msgstr "virheellinen tyyppi iterointimuuttujalle %qE"
#: c-family/c-omp.c:337 c-family/c-omp.c:375
-#, gcc-internal-format
+#, fuzzy, gcc-internal-format
msgid "%<#pragma omp atomic capture%> uses two different variables for memory"
-msgstr ""
+msgstr "virheellinen tyyppi iterointimuuttujalle %qE"
#: c-family/c-omp.c:457
#, fuzzy, gcc-internal-format
@@ -28116,7 +28144,6 @@ msgstr "%qD:a käytetään alustamattomana tässä funktiossa"
#: c-family/c-opts.c:327
#, fuzzy, gcc-internal-format
-#| msgid "-I- specified twice"
msgid "%<-I-%> specified twice"
msgstr "-I- annettu kahdesti"
@@ -28137,7 +28164,6 @@ msgstr "tulostiedosto annettu kahdesti"
#: c-family/c-opts.c:800
#, fuzzy, gcc-internal-format
-#| msgid "-fexcess-precision=standard for C++"
msgid "%<-fexcess-precision=standard%> for C++"
msgstr "-fexcess-precision=standard C++-kielelle"
@@ -28147,40 +28173,34 @@ msgid "%<-fno-gnu89-inline%> is only supported in GNU99 or C99 mode"
msgstr ""
#: c-family/c-opts.c:881
-#, fuzzy, gcc-internal-format
-#| msgid "-Wformat-y2k ignored without -Wformat"
+#, gcc-internal-format
msgid "%<-Wformat-y2k%> ignored without %<-Wformat%>"
-msgstr "-Wformat-y2k jätetty huomiotta ilman valitsinta -Wformat"
+msgstr "%<-Wformat-y2k%> jätetty huomiotta ilman valitsinta %<-Wformat%>"
#: c-family/c-opts.c:883
-#, fuzzy, gcc-internal-format
-#| msgid "-Wformat-extra-args ignored without -Wformat"
+#, gcc-internal-format
msgid "%<-Wformat-extra-args%> ignored without %<-Wformat%>"
-msgstr "-Wformat-extra-args jätetty huomiotta ilman valitsinta -Wformat"
+msgstr "%<-Wformat-extra-args%> jätetty huomiotta ilman valitsinta %<-Wformat%>"
#: c-family/c-opts.c:885
-#, fuzzy, gcc-internal-format
-#| msgid "-Wformat-zero-length ignored without -Wformat"
+#, gcc-internal-format
msgid "%<-Wformat-zero-length%> ignored without %<-Wformat%>"
-msgstr "-Wformat-zero-length jätetty huomiotta ilman valitsinta -Wformat"
+msgstr "%<-Wformat-zero-length%> jätetty huomiotta ilman valitsinta %<-Wformat%>"
#: c-family/c-opts.c:887
-#, fuzzy, gcc-internal-format
-#| msgid "-Wformat-nonliteral ignored without -Wformat"
+#, gcc-internal-format
msgid "%<-Wformat-nonliteral%> ignored without %<-Wformat%>"
-msgstr "-Wformat-nonliteral jätetty huomiotta ilman valitsinta -Wformat"
+msgstr "%<-Wformat-nonliteral%> jätetty huomiotta ilman valitsinta %<-Wformat%>"
#: c-family/c-opts.c:889
-#, fuzzy, gcc-internal-format
-#| msgid "-Wformat-contains-nul ignored without -Wformat"
+#, gcc-internal-format
msgid "%<-Wformat-contains-nul%> ignored without %<-Wformat%>"
-msgstr "-Wformat-contains-nul jätetty huomiotta ilman valitsinta -Wformat"
+msgstr "%<-Wformat-contains-nul%> jätetty huomiotta ilman valitsinta %<-Wformat%>"
#: c-family/c-opts.c:891
-#, fuzzy, gcc-internal-format
-#| msgid "-Wformat-security ignored without -Wformat"
+#, gcc-internal-format
msgid "%<-Wformat-security%> ignored without %<-Wformat%>"
-msgstr "-Wformat-security jätetty huomiotta ilman valitsinta -Wformat"
+msgstr "%<-Wformat-security%> jätetty huomiotta ilman valitsinta %<-Wformat%>"
#: c-family/c-opts.c:921
#, fuzzy, gcc-internal-format
@@ -28188,20 +28208,17 @@ msgid "%<-fabi-compat-version=1%> is not supported, using =2"
msgstr "dwarfin versio %d ei ole tuettu"
#: c-family/c-opts.c:948
-#, fuzzy, gcc-internal-format
-#| msgid "-Wabi won't warn about anything"
+#, gcc-internal-format
msgid "%<-Wabi%> won%'t warn about anything"
-msgstr "-Wabi ei varoita mistään"
+msgstr "%<-Wabi%> ei varoita mistään"
#: c-family/c-opts.c:950
#, fuzzy, gcc-internal-format
-#| msgid "-Wabi warns about differences from the most up-to-date ABI, which is also used by default"
msgid "%<-Wabi%> warns about differences from the most up-to-date ABI, which is also used by default"
msgstr "-Wabi varoittaa eroista ajantasaisimpaan ABIin, joka on myös oletuksena käytössä"
#: c-family/c-opts.c:953
#, fuzzy, gcc-internal-format
-#| msgid "use e.g. -Wabi=11 to warn about changes from GCC 7"
msgid "use e.g. %<-Wabi=11%> to warn about changes from GCC 7"
msgstr "käytä esim. -Wabi=11 GCC 7:stä muuttuneista asioista varoittamiseksi"
@@ -28242,7 +28259,6 @@ msgstr "kirjoitettaessa tulostetta tiedostoon %s: %m"
#: c-family/c-opts.c:1308
#, fuzzy, gcc-internal-format
-#| msgid "to generate dependencies you must specify either -M or -MM"
msgid "to generate dependencies you must specify either %<-M%> or %<-MM%>"
msgstr "muodostaaksesi riippuvuudet sinun täytyy antaa joko -M tai -MM"
@@ -28288,7 +28304,6 @@ msgstr "ei voi lukea tiedostoa %s: %m"
#: c-family/c-pch.c:409
#, fuzzy, gcc-internal-format
-#| msgid "pch_preprocess pragma should only be used with -fpreprocessed"
msgid "pch_preprocess pragma should only be used with %<-fpreprocessed%>"
msgstr "pch_preprocess-pragmaa tulee käyttää vain valitsimen -fpreprocessed kanssa"
@@ -28304,7 +28319,6 @@ msgstr "%s: ei voitu avata PCH-tiedostoa: %m"
#: c-family/c-pch.c:422
#, fuzzy, gcc-internal-format
-#| msgid "use -Winvalid-pch for more information"
msgid "use %<-Winvalid-pch%> for more information"
msgstr "käytä -Winvalid-pch saadaksesi lisätietoja"
@@ -28360,7 +28374,6 @@ msgstr "roskaa ilmaisun %<#pragma pack%> lopussa"
#: c-family/c-pragma.c:199
#, fuzzy, gcc-internal-format
-#| msgid "#pragma pack has no effect with -fpack-struct - ignored"
msgid "#pragma pack has no effect with %<-fpack-struct%> - ignored"
msgstr "#pragma pack ei vaikuta -fpack-struct-valitsimen kanssa - jätetään huomiotta"
@@ -29522,7 +29535,6 @@ msgstr " uid = %d, gid = %d, oikeudet = 0%o.\n"
#: common/config/bfin/bfin-common.c:323
#, fuzzy, gcc-internal-format
-#| msgid "-mcpu=%s is not valid"
msgid "%<-mcpu=%s%> is not valid"
msgstr "-mcpu=%s ei ole kelvollinen"
@@ -29697,13 +29709,11 @@ msgstr "väärin muotoiltu â€#pragma optionsâ€, ei huomioida"
#: config/darwin-c.c:102 config/darwin-c.c:105 config/darwin-c.c:107
#: config/darwin-c.c:109
#, fuzzy, gcc-internal-format
-#| msgid "malformed '#pragma options', ignoring"
msgid "malformed %<#pragma options%>, ignoring"
msgstr "väärin muotoiltu â€#pragma optionsâ€, ei huomioida"
#: config/darwin-c.c:112
#, fuzzy, gcc-internal-format
-#| msgid "junk at end of %<#pragma pop_options%>"
msgid "junk at end of %<#pragma options%>"
msgstr "roskaa ilmaisun %<#pragma pop_options%> lopussa"
@@ -29714,13 +29724,11 @@ msgstr "väärin muotoiltu â€#pragma optionsâ€, ei huomioida"
#: config/darwin-c.c:134
#, fuzzy, gcc-internal-format
-#| msgid "missing '(' after '#pragma unused', ignoring"
msgid "missing %<(%> after %<#pragma unused%>, ignoring"
msgstr "puuttuva â€(†ilmaisun â€#pragma unused†jälkeen, jätetään huomiotta"
#: config/darwin-c.c:155
#, fuzzy, gcc-internal-format
-#| msgid "missing ')' after '#pragma unused', ignoring"
msgid "missing %<)%> after %<#pragma unused%>, ignoring"
msgstr "puuttuva â€)†ilmaisun â€#pragma unused†jälkeen, jätetään huomiotta"
@@ -29731,19 +29739,16 @@ msgstr "roskaa ilmaisun %<#pragma pack%> lopussa"
#: config/darwin-c.c:169
#, fuzzy, gcc-internal-format
-#| msgid "malformed '#pragma ms_struct', ignoring"
msgid "malformed %<#pragma ms_struct%>, ignoring"
msgstr "väärinmuodostettu â€#pragma ms_structâ€, jätetään huomiotta"
#: config/darwin-c.c:177
#, fuzzy, gcc-internal-format
-#| msgid "malformed '#pragma ms_struct {on|off|reset}', ignoring"
msgid "malformed %<#pragma ms_struct {on|off|reset}%>, ignoring"
msgstr "väärinmuodostettu â€#pragma ms_struct {on|off|reset}â€, jätetään huomiotta"
#: config/darwin-c.c:180
#, fuzzy, gcc-internal-format
-#| msgid "junk at end of '#pragma ms_struct'"
msgid "junk at end of %<#pragma ms_struct%>"
msgstr "roskaa ilmaisun â€#pragma ms_struct†lopussa"
@@ -30841,13 +30846,11 @@ msgstr "kohdemuoto ei tue äärettömyyttä"
#: config/arm/arm.c:3411
#, fuzzy, gcc-internal-format
-#| msgid "-mapcs-stack-check incompatible with -mno-apcs-frame"
msgid "%<-mapcs-stack-check%> incompatible with %<-mno-apcs-frame%>"
msgstr "-mapcs-stack-check on yhteensopimaton valitsimen -mno-apcs-frame kanssa"
#: config/arm/arm.c:3420
#, fuzzy, gcc-internal-format
-#| msgid "-fpic and -mapcs-reent are incompatible"
msgid "%<-fpic%> and %<-mapcs-reent%> are incompatible"
msgstr "-fpic ja -mapcs-reent ovat yhteensopimattomat"
@@ -30913,13 +30916,11 @@ msgstr "AAPCS ei tue valitsinta -mcaller-super-interworking"
#: config/arm/arm.c:3740
#, fuzzy, gcc-internal-format
-#| msgid "AAPCS does not support -mcaller-super-interworking"
msgid "AAPCS does not support %<-mcaller-super-interworking%>"
msgstr "AAPCS ei tue valitsinta -mcaller-super-interworking"
#: config/arm/arm.c:3743
#, fuzzy, gcc-internal-format
-#| msgid "AAPCS does not support -mcallee-super-interworking"
msgid "AAPCS does not support %<-mcallee-super-interworking%>"
msgstr "AAPCS ei tue valitsinta -mcallee-super-interworking"
@@ -31133,7 +31134,6 @@ msgstr "-fPIC ei ole tuettu"
#: config/avr/avr.c:767 config/visium/visium.c:424
#, fuzzy, gcc-internal-format
-#| msgid "-fPIC is not supported"
msgid "%<-fPIC%> is not supported"
msgstr "-fPIC ei ole tuettu"
@@ -31335,7 +31335,6 @@ msgstr "säiekohtaista muistia ei tueta tälle kohteelle"
#: config/bfin/bfin.c:2388
#, fuzzy, gcc-internal-format
-#| msgid "-mshared-library-id= specified without -mid-shared-library"
msgid "%<-mshared-library-id=%> specified without %<-mid-shared-library%>"
msgstr "-mshared-library-id= määritelty ilman valitsinta -mid-shared-library"
@@ -31356,7 +31355,6 @@ msgstr "valitsimia -mbig-endian ja -mlittle-endian ei voi käyttää yhdessä"
#: config/bfin/bfin.c:2407 config/m68k/m68k.c:586
#, fuzzy, gcc-internal-format
-#| msgid "cannot specify both -msep-data and -mid-shared-library"
msgid "cannot specify both %<-msep-data%> and %<-mid-shared-library%>"
msgstr "ei voi määritellä sekä valitsinta -msep-date että -mid-shared-library"
@@ -31377,7 +31375,6 @@ msgstr "valitsimia -mcorea ja -mcoreb ei voi käyttää yhdessä"
#: config/bfin/bfin.c:2436
#, fuzzy, gcc-internal-format
-#| msgid "-mcorea and -mcoreb can%'t be used together"
msgid "%<-mcorea%> and %<-mcoreb%> can%'t be used together"
msgstr "valitsimia -mcorea ja -mcoreb ei voi käyttää yhdessä"
@@ -31432,7 +31429,6 @@ msgstr ""
#: config/cris/cris.c:906
#, fuzzy, gcc-internal-format
-#| msgid "invalid use of ':' modifier"
msgid "invalid use of %<:%> modifier"
msgstr "â€:â€-määreen epäkelpo käyttö"
@@ -32277,24 +32273,24 @@ msgid "ms_hook_prologue is not compatible with nested function"
msgstr "ISO C kieltää sisäkkäiset funktiot"
#: config/i386/i386.c:7377
-#, gcc-internal-format
+#, fuzzy, gcc-internal-format
msgid "AVX512F vector argument without AVX512F enabled changes the ABI"
-msgstr ""
+msgstr "muodostimen virheellinen käyttö mallina"
#: config/i386/i386.c:7383
-#, gcc-internal-format
+#, fuzzy, gcc-internal-format
msgid "AVX512F vector return without AVX512F enabled changes the ABI"
-msgstr ""
+msgstr "muodostimen virheellinen käyttö mallina"
#: config/i386/i386.c:7397
-#, gcc-internal-format
+#, fuzzy, gcc-internal-format
msgid "AVX vector argument without AVX enabled changes the ABI"
-msgstr ""
+msgstr "muodostimen virheellinen käyttö mallina"
#: config/i386/i386.c:7403
-#, gcc-internal-format
+#, fuzzy, gcc-internal-format
msgid "AVX vector return without AVX enabled changes the ABI"
-msgstr ""
+msgstr "muodostimen virheellinen käyttö mallina"
#: config/i386/i386.c:7419
#, fuzzy, gcc-internal-format
@@ -32302,19 +32298,19 @@ msgid "SSE vector argument without SSE enabled changes the ABI"
msgstr "muodostimen virheellinen käyttö mallina"
#: config/i386/i386.c:7425
-#, gcc-internal-format
+#, fuzzy, gcc-internal-format
msgid "SSE vector return without SSE enabled changes the ABI"
-msgstr ""
+msgstr "muodostimen virheellinen käyttö mallina"
#: config/i386/i386.c:7441
-#, gcc-internal-format
+#, fuzzy, gcc-internal-format
msgid "MMX vector argument without MMX enabled changes the ABI"
-msgstr ""
+msgstr "muodostimen virheellinen käyttö mallina"
#: config/i386/i386.c:7447
-#, gcc-internal-format
+#, fuzzy, gcc-internal-format
msgid "MMX vector return without MMX enabled changes the ABI"
-msgstr ""
+msgstr "muodostimen virheellinen käyttö mallina"
#: config/i386/i386.c:7628
#, gcc-internal-format
@@ -32627,9 +32623,9 @@ msgid "argument to %qE attribute is not (keep|thunk|thunk-inline|thunk-extern)"
msgstr "%qE-attribuutti tarvitsee merkkijonovakioargumentin"
#: config/i386/i386.c:41371
-#, gcc-internal-format
+#, fuzzy, gcc-internal-format
msgid "interrupt service routine should have a pointer as the first argument"
-msgstr ""
+msgstr "keskeytyskäsittelijät eivät voi olla MIPS16-funktioita"
#: config/i386/i386.c:41378
#, fuzzy, gcc-internal-format
@@ -32637,9 +32633,9 @@ msgid "interrupt service routine should have %qs as the second argument"
msgstr "keskeytyskäsittelijät eivät voi olla MIPS16-funktioita"
#: config/i386/i386.c:41389
-#, gcc-internal-format
+#, fuzzy, gcc-internal-format
msgid "interrupt service routine can only have a pointer argument and an optional integer argument"
-msgstr ""
+msgstr "keskeytyskäsittelijät eivät voi olla MIPS16-funktioita"
#: config/i386/i386.c:41392
#, fuzzy, gcc-internal-format
@@ -32737,13 +32733,11 @@ msgstr "DJGPP-ympäristömuuttujaa ei ole määritelty"
#: config/i386/xm-djgpp.h:87
#, fuzzy, gcc-internal-format
-#| msgid "environment variable DJGPP points to missing file '%s'"
msgid "environment variable DJGPP points to missing file %qs"
msgstr "DJGPP-ympäristömuuttuja viittaa puuttuvaan tiedostoon â€%sâ€"
#: config/i386/xm-djgpp.h:90
#, fuzzy, gcc-internal-format
-#| msgid "environment variable DJGPP points to corrupt file '%s'"
msgid "environment variable DJGPP points to corrupt file %qs"
msgstr "DJGPP-ympäristömuuttuja viittaa turmeltuneeseen tiedostoon â€%sâ€"
@@ -32871,13 +32865,11 @@ msgstr "%qs-attribuutin virheellinen argumentti"
#: config/m68k/m68k.c:527
#, fuzzy, gcc-internal-format
-#| msgid "-mcpu=%s conflicts with -march=%s"
msgid "%<-mcpu=%s%> conflicts with %<-march=%s%>"
msgstr "valitsin -mcpu=%s on ristiriidassa valitsimen -march=%s kanssa"
#: config/m68k/m68k.c:598
#, fuzzy, gcc-internal-format
-#| msgid "-mpcrel -fPIC is not currently supported on selected cpu"
msgid "%<-mpcrel%> %<-fPIC%> is not currently supported on selected cpu"
msgstr "-mpcrel -fPIC ei ole nykyisin tuettu valitulle prosessorille"
@@ -33085,9 +33077,9 @@ msgid "the %qs architecture does not support %<-mfp32%>"
msgstr "%s ei tue pituusmäärettä %qs %s"
#: config/mips/mips.c:19891
-#, gcc-internal-format
+#, fuzzy, gcc-internal-format
msgid "%<-mgp32%> and %<-mfp64%> can only be combined if the target supports the mfhc1 and mthc1 instructions"
-msgstr ""
+msgstr "Valitsinta --acls voi käyttää vain POSIX-arkistoille"
#: config/mips/mips.c:19894
#, fuzzy, gcc-internal-format
@@ -34672,7 +34664,6 @@ msgstr "-mapcs-stack-check on yhteensopimaton valitsimen -mno-apcs-frame kanssa"
#: config/rs6000/freebsd64.h:113 config/rs6000/linux64.h:135
#: config/rs6000/rtems.h:114
#, fuzzy, gcc-internal-format
-#| msgid "-m64 requires a PowerPC64 cpu"
msgid "%<-m64%> requires a PowerPC64 cpu"
msgstr "-m64 vaatii PowerPC64-suorittimen"
@@ -38518,14 +38509,14 @@ msgid "too many memory order clauses"
msgstr "%s: liian monta arvoa"
#: c/c-parser.c:16142 cp/parser.c:35739
-#, gcc-internal-format
+#, fuzzy, gcc-internal-format
msgid "%<#pragma omp atomic read%> incompatible with %<acq_rel%> or %<release%> clauses"
-msgstr ""
+msgstr "%Hdatamäärittelyllä ei ole tyyppiä eikä tallennusluokkaa"
#: c/c-parser.c:16151 cp/parser.c:35748
-#, gcc-internal-format
+#, fuzzy, gcc-internal-format
msgid "%<#pragma omp atomic write%> incompatible with %<acq_rel%> or %<acquire%> clauses"
-msgstr ""
+msgstr "%Hdatamäärittelyllä ei ole tyyppiä eikä tallennusluokkaa"
#: c/c-parser.c:16160 cp/parser.c:35757
#, fuzzy, gcc-internal-format
@@ -38543,9 +38534,9 @@ msgid "invalid operator for %<#pragma omp atomic%>"
msgstr "roskaa ilmaisun %<#pragma pack%> lopussa"
#: c/c-parser.c:16479 cp/semantics.c:8959 cp/semantics.c:8969
-#, gcc-internal-format
+#, fuzzy, gcc-internal-format
msgid "%<#pragma omp atomic capture%> uses two different expressions for memory"
-msgstr ""
+msgstr "virheellinen tyyppi iterointimuuttujalle %qE"
#: c/c-parser.c:16548 c/c-parser.c:16705
#, gcc-internal-format
@@ -38583,9 +38574,9 @@ msgid "%<ordered%> clause parameter is less than %<collapse%>"
msgstr "%<void%> vain parametrina ei ole oikeutettu"
#: c/c-parser.c:16760 cp/parser.c:36887
-#, gcc-internal-format
+#, fuzzy, gcc-internal-format
msgid "%<linear%> clause may not be specified together with %<ordered%> clause with a parameter"
-msgstr ""
+msgstr "%<void%> vain parametrina ei ole oikeutettu"
#: c/c-parser.c:16778 cp/parser.c:36915
#, fuzzy, gcc-internal-format
@@ -40093,9 +40084,9 @@ msgid "used vector type where scalar is required"
msgstr "käytetty unionityypin arvoa, vaikka vaaditaan skalaari"
#: c/c-typeck.c:12747 cp/semantics.c:9111
-#, gcc-internal-format
+#, fuzzy, gcc-internal-format
msgid "%<#pragma omp cancel%> must specify one of %<parallel%>, %<for%>, %<sections%> or %<taskgroup%> clauses"
-msgstr ""
+msgstr "%Hdatamäärittelyllä ei ole tyyppiä eikä tallennusluokkaa"
#: c/c-typeck.c:12758 c/c-typeck.c:12768 cp/semantics.c:9122
#: cp/semantics.c:9132
@@ -40104,9 +40095,9 @@ msgid "expected %<cancel%> %<if%> clause modifier"
msgstr "odotettiin %<operator%>"
#: c/c-typeck.c:12803 cp/semantics.c:9168
-#, gcc-internal-format
+#, fuzzy, gcc-internal-format
msgid "%<#pragma omp cancellation point%> must specify one of %<parallel%>, %<for%>, %<sections%> or %<taskgroup%> clauses"
-msgstr ""
+msgstr "%Hdatamäärittelyllä ei ole tyyppiä eikä tallennusluokkaa"
#: c/c-typeck.c:12847 c/c-typeck.c:14323 c/c-typeck.c:14387 c/c-typeck.c:14449
#, fuzzy, gcc-internal-format
@@ -40394,9 +40385,9 @@ msgid "%qE appears more than once in %<nontemporal%> clauses"
msgstr "funktiolle %2$qE annettu argumentin %1$d tyyppi on yhteensopimaton"
#: c/c-typeck.c:14236 cp/semantics.c:6987
-#, gcc-internal-format
+#, fuzzy, gcc-internal-format
msgid "%<depend%> clause with %<depobj%> dependence type on array section"
-msgstr ""
+msgstr "%<void%> vain parametrina ei ole oikeutettu"
#: c/c-typeck.c:14247 cp/semantics.c:7012
#, fuzzy, gcc-internal-format
@@ -40409,9 +40400,9 @@ msgid "%qE does not have %<omp_depend_t%> type in %<depend%> clause with %<depob
msgstr "%<void%> vain parametrina ei ole oikeutettu"
#: c/c-typeck.c:14272 cp/semantics.c:7042
-#, gcc-internal-format
+#, fuzzy, gcc-internal-format
msgid "%qE should not have %<omp_depend_t%> type in %<depend%> clause with dependence type other than %<depobj%>"
-msgstr ""
+msgstr "%<void%> vain parametrina ei ole oikeutettu"
#: c/c-typeck.c:14315 cp/semantics.c:7086
#, fuzzy, gcc-internal-format
@@ -41222,9 +41213,9 @@ msgid "%qD clearing an object of type %#qT with no trivial copy-assignment%s"
msgstr "%q#T-tyyppisiä epä-POD-objekteja ei voi välittää %<...%>:n kautta, ohjelma tulee keskeytymään ajettaessa"
#: cp/call.c:9019
-#, fuzzy, gcc-internal-format
+#, gcc-internal-format
msgid "%qD clearing an object of non-trivial type %#qT%s"
-msgstr "%q#T-tyyppisiä epä-POD-objekteja ei voi välittää %<...%>:n kautta, ohjelma tulee keskeytymään ajettaessa"
+msgstr "%qD tyhjentää ei-triviaalintyyppisen objektin %#qT%s"
#: cp/call.c:9021
#, fuzzy, gcc-internal-format
@@ -42425,9 +42416,9 @@ msgid "conversion from %qH to %qI discards qualifiers"
msgstr "muunnos tyypistä %qT tyyppiin %qT ei säilytä tyyppimääreitä"
#: cp/cvt.c:497 cp/typeck.c:7536
-#, gcc-internal-format
+#, fuzzy, gcc-internal-format
msgid "casting %qT to %qT does not dereference pointer"
-msgstr ""
+msgstr "oliko tarkoitus käyttää loogista negaatiota?"
#: cp/cvt.c:525
#, fuzzy
@@ -45758,9 +45749,9 @@ msgid "...following parameter %P which has a default argument"
msgstr "%<operator new%>:n ensimmäisellä parametrilla ei voi olla oletusargumenttia"
#: cp/decl2.c:5349
-#, fuzzy, gcc-internal-format
+#, gcc-internal-format
msgid "implicitly-declared %qD is deprecated"
-msgstr "%qE on vanhentunut"
+msgstr "implisiittisesti esitelty %qD on vanhentunut"
#: cp/decl2.c:5353
#, gcc-internal-format
@@ -46197,9 +46188,9 @@ msgid "unnamed initializer for %qT, which has no base classes"
msgstr "virheellinen alustin taulukon jäsenelle %q#D"
#: cp/init.c:1628
-#, gcc-internal-format
+#, fuzzy, gcc-internal-format
msgid "unnamed initializer for %qT, which uses multiple inheritance"
-msgstr ""
+msgstr "virheellinen alustin taulukon jäsenelle %q#D"
#: cp/init.c:1675
#, fuzzy, gcc-internal-format
@@ -47519,9 +47510,9 @@ msgid "array bound forbidden after parenthesized type-id"
msgstr "taulukkoindeksi ei-taulukkoalustimessa"
#: cp/parser.c:8693
-#, gcc-internal-format
+#, fuzzy, gcc-internal-format
msgid "try removing the parentheses around the type-id"
-msgstr ""
+msgstr "taulukkoindeksi ei-taulukkoalustimessa"
#: cp/parser.c:8725
#, gcc-internal-format
@@ -47629,9 +47620,9 @@ msgid "%q#D declared here"
msgstr "%q+D esitelty täällä"
#: cp/parser.c:10709
-#, gcc-internal-format
+#, fuzzy, gcc-internal-format
msgid "capture of variable %qD with non-automatic storage duration"
-msgstr ""
+msgstr "poistettu funktio %q+D"
#: cp/parser.c:10747
#, fuzzy, gcc-internal-format
@@ -47936,9 +47927,9 @@ msgid "anachronistic old-style base class initializer"
msgstr ""
#: cp/parser.c:15108
-#, gcc-internal-format
+#, fuzzy, gcc-internal-format
msgid "keyword %<typename%> not allowed in this context (a qualified member initializer is implicitly a type)"
-msgstr ""
+msgstr "%<[*]%> ei ole esittelyssä"
#: cp/parser.c:15492
#, gcc-internal-format
@@ -48310,7 +48301,6 @@ msgstr "cv-määreen kaksoiskappale"
#: cp/parser.c:19846
#, fuzzy, gcc-internal-format
-#| msgid "type qualifiers ignored on function return type"
msgid "asm qualifier %qT ignored outside of function body"
msgstr "tyyppimääritteet jätetään huomiotta funktion paluutyypissä"
@@ -48696,9 +48686,9 @@ msgid "keyword %<typename%> not allowed outside of templates"
msgstr "%<[*]%> ei ole esittelyssä"
#: cp/parser.c:25148
-#, gcc-internal-format
+#, fuzzy, gcc-internal-format
msgid "keyword %<typename%> not allowed in this context (the base class is implicitly a type)"
-msgstr ""
+msgstr "%<[*]%> ei ole esittelyssä"
#: cp/parser.c:25248 cp/parser.c:25339
#, fuzzy, gcc-internal-format
@@ -49506,9 +49496,9 @@ msgid "argument to __integer_pack must be between 0 and %d"
msgstr "luetellun tyypin jäsenen %qE arvo ei ole kokonaislukuvakio"
#: cp/pt.c:3944
-#, gcc-internal-format
+#, fuzzy, gcc-internal-format
msgid "base initializer expansion %qT contains no parameter packs"
-msgstr ""
+msgstr "Muuttujatyyppi on UNKNOWN sijoituksessa kohdassa %L"
#: cp/pt.c:4012
#, fuzzy, gcc-internal-format
@@ -50290,7 +50280,6 @@ msgstr ""
#: cp/pt.c:15497
#, fuzzy, gcc-internal-format
-#| msgid "initializer element is not a constant expression"
msgid "initializer for %q#D expands to an empty list of expressions"
msgstr "alustinalkio ei ole vakiolauseke"
@@ -50641,7 +50630,6 @@ msgstr "dynamic_cast tyypistä %q#D tyypiksi %q#T ei voi koskaan onnistua"
#: cp/rtti.c:722
#, fuzzy, gcc-internal-format
-#| msgid "%<dynamic_cast%> not permitted with -fno-rtti"
msgid "%<dynamic_cast%> not permitted with %<-fno-rtti%>"
msgstr "%<dynamic_cast%> ei ole sallittu valitsimen -fno-rtti kanssa"
@@ -51190,9 +51178,9 @@ msgid "%<#pragma omp simd%> used with class iteration variable %qE"
msgstr "virheellinen tyyppi iterointimuuttujalle %qE"
#: cp/semantics.c:8956 cp/semantics.c:8966
-#, gcc-internal-format
+#, fuzzy, gcc-internal-format
msgid "%<#pragma omp atomic update%> uses two different expressions for memory"
-msgstr ""
+msgstr "virheellinen tyyppi iterointimuuttujalle %qE"
#: cp/semantics.c:9328
#, gcc-internal-format, gfc-internal-format
@@ -52504,7 +52492,6 @@ msgstr ""
#: cp/typeck2.c:1228
#, fuzzy, gcc-internal-format
-#| msgid "braces around scalar initializer"
msgid "remove %<{ }%> around initializer"
msgstr "skalaarialustimen ympärillä on aaltosulkeet"
@@ -52724,9 +52711,9 @@ msgid "eval_intrinsic(): Bad operator"
msgstr " eikä %<operator=(const %T&)%>"
#: fortran/arith.c:1642
-#, gcc-internal-format
+#, fuzzy, gcc-internal-format
msgid "eval_type_intrinsic0(): op NULL"
-msgstr ""
+msgstr " eikä %<operator=(const %T&)%>"
#: fortran/arith.c:1951
#, fuzzy, gcc-internal-format, gfc-internal-format
@@ -52943,9 +52930,9 @@ msgid "Coarray declaration at %C"
msgstr "Syntaksivirhe CHARACTER-esittelyssä kohdassa %C"
#: fortran/array.c:753
-#, gcc-internal-format
+#, fuzzy, gcc-internal-format
msgid "Upper bound of last coarray dimension must be %<*%> at %C"
-msgstr ""
+msgstr "Arvo sallitun välin ulkopuolella."
#: fortran/array.c:821
#, fuzzy, gcc-internal-format
@@ -52958,9 +52945,9 @@ msgid "gfc_compare_array_spec(): Array spec clobbered"
msgstr ""
#: fortran/array.c:981
-#, gcc-internal-format
+#, fuzzy, gcc-internal-format
msgid "DO-iterator %qs at %L is inside iterator of the same name"
-msgstr ""
+msgstr "Lausekkeen CASE-lauseessa kohdassa %L on oltava skalaari"
#: fortran/array.c:1073 fortran/array.c:1266
#, gcc-internal-format, gfc-internal-format
@@ -54331,9 +54318,9 @@ msgid "Procedure %qs at %L must have the BIND(C) attribute to be C interoperable
msgstr "tyhjä esittely"
#: fortran/decl.c:1473
-#, gcc-internal-format
+#, fuzzy, gcc-internal-format
msgid "Variable %qs at %L is a dummy argument to the BIND(C) procedure %qs but is not C interoperable because derived type %qs is not C interoperable"
-msgstr ""
+msgstr "Liikaa argumentteja funktiolle %s kohdassa %L"
#: fortran/decl.c:1480
#, fuzzy, gcc-internal-format
@@ -54386,9 +54373,9 @@ msgid "Symbol %qs at %C also declared as a type at %L"
msgstr "Proseduuri â€%s†kohdassa %L ei voi olla perustyyppiä %s"
#: fortran/decl.c:1687
-#, gcc-internal-format
+#, fuzzy, gcc-internal-format
msgid "Variable %qs in common block %qs at %C must be declared with a C interoperable kind since common block %qs is BIND(C)"
-msgstr ""
+msgstr "BIND(C)-funktion â€%s†paluutyyppi kohdassa %L ei voi olla taulukko"
#: fortran/decl.c:1727
#, fuzzy, gcc-internal-format, gfc-internal-format
@@ -54701,9 +54688,9 @@ msgid "The parameter expression at %C must be of INTEGER type and not %s type"
msgstr "Lauseke CASE-lauseessa kohdassa %L on oltava %s-tyyppinen"
#: fortran/decl.c:3676
-#, gcc-internal-format
+#, fuzzy, gcc-internal-format
msgid "The KIND parameter %qs at %C cannot either be ASSUMED or DEFERRED"
-msgstr ""
+msgstr "luetellun tyypin jäsenen %qE arvo ei ole kokonaislukuvakio"
#: fortran/decl.c:3683
#, fuzzy, gcc-internal-format
@@ -54953,9 +54940,9 @@ msgid "Implicitly declared BIND(C) function %qs at %L may not be C interoperable
msgstr "BIND(C)-funktion â€%s†paluutyyppi kohdassa %L ei voi olla taulukko"
#: fortran/decl.c:5683
-#, gcc-internal-format
+#, fuzzy, gcc-internal-format
msgid "Variable %qs in common block %qs at %L may not be a C interoperable kind though common block %qs is BIND(C)"
-msgstr ""
+msgstr "BIND(C)-funktion â€%s†paluutyyppi kohdassa %L ei voi olla taulukko"
#: fortran/decl.c:5692
#, fuzzy, gcc-internal-format
@@ -55055,9 +55042,9 @@ msgid "PURE and IMPURE must not appear both at %C"
msgstr ""
#: fortran/decl.c:6235
-#, gcc-internal-format, gfc-internal-format
+#, fuzzy, gcc-internal-format, gfc-internal-format
msgid "ELEMENTAL prefix in MODULE PROCEDURE interface is missing at %L"
-msgstr ""
+msgstr "Syntaksivirhe PROCEDURE-lauseessa kohdassa %C"
#: fortran/decl.c:6242
#, fuzzy, gcc-internal-format, gfc-internal-format
@@ -55065,9 +55052,9 @@ msgid "PURE prefix in MODULE PROCEDURE interface is missing at %L"
msgstr "Syntaksivirhe PROCEDURE-lauseessa kohdassa %C"
#: fortran/decl.c:6249
-#, gcc-internal-format, gfc-internal-format
+#, fuzzy, gcc-internal-format, gfc-internal-format
msgid "RECURSIVE prefix in MODULE PROCEDURE interface is missing at %L"
-msgstr ""
+msgstr "Syntaksivirhe PROCEDURE-lauseessa kohdassa %C"
#: fortran/decl.c:6310
#, fuzzy, gcc-internal-format, gfc-internal-format
@@ -55110,9 +55097,9 @@ msgid "Duplicate symbol %qs in formal argument list at %C"
msgstr "Kaksoiskappalesymboli â€%s†muodollisessa argumenttiluettelossa paikassa %C"
#: fortran/decl.c:6454
-#, gcc-internal-format, gfc-internal-format
+#, fuzzy, gcc-internal-format, gfc-internal-format
msgid "Mismatch in MODULE PROCEDURE formal argument names (%s/%s) at %C"
-msgstr ""
+msgstr "Syntaksivirhe PROCEDURE-lauseessa kohdassa %C"
#: fortran/decl.c:6460
#, fuzzy, gcc-internal-format, gfc-internal-format
@@ -55429,7 +55416,6 @@ msgstr "Odotettiin merkkiä â€,†kohdassa %C"
#: fortran/decl.c:8579
#, fuzzy, gcc-internal-format
-#| msgid "cannot convert to a pointer type"
msgid "Cannot set Cray pointee array spec."
msgstr "ei voi muuntaa osoitintyypiksi"
@@ -55640,9 +55626,9 @@ msgid "%qs cannot be extended at %C because it is BIND(C)"
msgstr "Muuttujalla â€%s†kohdassa %L ei voi olla sekä POINTER- että BIND(C)-attribuutit"
#: fortran/decl.c:9717
-#, gcc-internal-format
+#, fuzzy, gcc-internal-format
msgid "%qs cannot be extended at %C because it is a SEQUENCE type"
-msgstr ""
+msgstr "Muuttujalla â€%s†kohdassa %L ei voi olla sekä POINTER- että BIND(C)-attribuutit"
#: fortran/decl.c:9740
#, fuzzy, gcc-internal-format, gfc-internal-format
@@ -55840,9 +55826,9 @@ msgid "PROCEDURE list at %C"
msgstr "Odotettiin moduuliproseduurinimeä kohdassa %C"
#: fortran/decl.c:10873
-#, gcc-internal-format
+#, fuzzy, gcc-internal-format
msgid "%<=> target%> is invalid for DEFERRED binding at %C"
-msgstr ""
+msgstr "Syntaksivirhe CASE-spesifikaatiossa kohdassa %C"
#: fortran/decl.c:10879
#, gcc-internal-format
@@ -55865,9 +55851,9 @@ msgid "There is already a procedure with binding name %qs for the derived type %
msgstr "%J%qD:lle ei ole aiempaa esittelyä"
#: fortran/decl.c:10968
-#, gcc-internal-format, gfc-internal-format
+#, fuzzy, gcc-internal-format, gfc-internal-format
msgid "GENERIC at %C must be inside a derived-type CONTAINS"
-msgstr ""
+msgstr "Syntaksivirhe VALUE-lauseessa kohdassa %C"
#: fortran/decl.c:10988
#, fuzzy, gcc-internal-format
@@ -55890,9 +55876,9 @@ msgid "Expected %<=>%> at %C"
msgstr "Odotettiin merkkiä â€,†kohdassa %C"
#: fortran/decl.c:11068
-#, gcc-internal-format
+#, fuzzy, gcc-internal-format
msgid "There's already a non-generic procedure with binding name %qs for the derived type %qs at %C"
-msgstr ""
+msgstr "%J%qD:lle ei ole aiempaa esittelyä"
#: fortran/decl.c:11076
#, gcc-internal-format
@@ -55915,9 +55901,9 @@ msgid "Junk after GENERIC binding at %C"
msgstr "Roskaa CALL-lauseen jälkeen kohdassa %C"
#: fortran/decl.c:11187
-#, gcc-internal-format, gfc-internal-format
+#, fuzzy, gcc-internal-format, gfc-internal-format
msgid "FINAL declaration at %C must be inside a derived type CONTAINS section"
-msgstr ""
+msgstr "Syntaksivirhe VALUE-lauseessa kohdassa %C"
#: fortran/decl.c:11198
#, fuzzy, gcc-internal-format, gfc-internal-format
@@ -56684,7 +56670,6 @@ msgstr "vektoriylivuoto lausekkeessa"
#: fortran/f95-lang.c:251
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "can't open input file: %s"
msgid "cannot open input file: %s"
msgstr "ei voi avata syötetiedostoa: %s"
@@ -57127,7 +57112,6 @@ msgstr "Odottamaton vaihtoehtoinen paluumäärittely alirutiinikutsussa kohdassa
#: fortran/interface.c:2983
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Unexpected alternate return spec in subroutine call at %L"
msgid "Unexpected alternate return specifier in subroutine call at %L"
msgstr "Odottamaton vaihtoehtoinen paluumäärittely alirutiinikutsussa kohdassa %L"
@@ -57232,9 +57216,9 @@ msgid "Array-section actual argument with vector subscripts at %L is incompatibl
msgstr ""
#: fortran/interface.c:3305
-#, gcc-internal-format
+#, fuzzy, gcc-internal-format
msgid "Assumed-shape actual argument at %L is incompatible with the non-assumed-shape dummy argument %qs due to VOLATILE attribute"
-msgstr ""
+msgstr "muuttuvakokoista objektia ei voi alustaa"
#: fortran/interface.c:3322
#, gcc-internal-format
@@ -57242,9 +57226,9 @@ msgid "Array-section actual argument at %L is incompatible with the non-assumed-
msgstr ""
#: fortran/interface.c:3342
-#, gcc-internal-format
+#, fuzzy, gcc-internal-format
msgid "Pointer-array actual argument at %L requires an assumed-shape or pointer-array dummy argument %qs due to VOLATILE attribute"
-msgstr ""
+msgstr "muuttuvakokoista objektia ei voi alustaa"
#: fortran/interface.c:3365
#, fuzzy, gcc-internal-format, gfc-internal-format
@@ -57397,9 +57381,9 @@ msgid "Cannot overwrite GENERIC %qs at %L"
msgstr "ei voi kirjoittaa tiedostoon %s: %m"
#: fortran/interface.c:4569
-#, gcc-internal-format
+#, fuzzy, gcc-internal-format
msgid "%qs at %L overrides a procedure binding declared NON_OVERRIDABLE"
-msgstr ""
+msgstr "%s:n kohdassa %L täytyy olla INTEGER"
#: fortran/interface.c:4577
#, gcc-internal-format
@@ -57417,9 +57401,9 @@ msgid "%qs at %L overrides an ELEMENTAL procedure and must also be ELEMENTAL"
msgstr "%qs esitelty funktion palauttavana funktiona"
#: fortran/interface.c:4600
-#, gcc-internal-format
+#, fuzzy, gcc-internal-format
msgid "%qs at %L overrides a non-ELEMENTAL procedure and must not be ELEMENTAL, either"
-msgstr ""
+msgstr "%qs esitelty funktion palauttavana funktiona"
#: fortran/interface.c:4609
#, fuzzy, gcc-internal-format
@@ -57522,9 +57506,9 @@ msgid "Too many dummy arguments in DTIO procedure %qs at %L"
msgstr "Liikaa argumentteja funktiolle %s kohdassa %L"
#: fortran/intrinsic.c:201
-#, gcc-internal-format, gfc-internal-format
+#, fuzzy, gcc-internal-format, gfc-internal-format
msgid "Variable with NO_ARG_CHECK attribute at %L is only permitted as argument to the intrinsic functions C_LOC and PRESENT"
-msgstr ""
+msgstr "ASYNCHRONOUS= määrite kohdassa %L täytyy olla alustuslauseke"
#: fortran/intrinsic.c:217
#, fuzzy, gcc-internal-format, gfc-internal-format
@@ -57607,9 +57591,9 @@ msgid "resolve_intrinsic(): Too many args for intrinsic"
msgstr "vektoriylivuoto lausekkeessa"
#: fortran/intrinsic.c:4531
-#, gcc-internal-format
+#, fuzzy, gcc-internal-format
msgid "do_simplify(): Too many args for intrinsic"
-msgstr ""
+msgstr "vektoriylivuoto lausekkeessa"
#: fortran/intrinsic.c:4571
#, fuzzy, gcc-internal-format
@@ -57668,7 +57652,6 @@ msgstr "Muunnos tyypistä %s tyyppiin %s kohdassa %L"
#: fortran/intrinsic.c:5182
#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Can't convert %s to %s at %L"
msgid "Cannot convert %s to %s at %L"
msgstr "Ei voi muuntaa tyyppiä %s tyyppiin %s kohdassa %L"
@@ -58118,9 +58101,9 @@ msgid "NAMELIST object %qs in namelist %qs at %L with ALLOCATABLE or POINTER com
msgstr ""
#: fortran/io.c:3405
-#, gcc-internal-format
+#, fuzzy, gcc-internal-format
msgid "NAMELIST object %qs in namelist %qs at %L has ALLOCATABLE or POINTER components and thus requires a defined input/output procedure"
-msgstr ""
+msgstr "muuttuvakokoista objektia ei voi alustaa"
#: fortran/io.c:3416
#, fuzzy, gcc-internal-format, gfc-internal-format
@@ -58960,9 +58943,9 @@ msgstr "Syntaksivirhe IF-lauseessa kohdassa %C"
#. cause it's just semantic, and we can see if there
#. are more errors.
#: fortran/match.c:5136
-#, gcc-internal-format
+#, fuzzy, gcc-internal-format
msgid "Variable %qs at %L in common block %qs at %C must be declared with a C interoperable kind since common block %qs is bind(c)"
-msgstr ""
+msgstr "BIND(C)-funktion â€%s†paluutyyppi kohdassa %L ei voi olla taulukko"
#: fortran/match.c:5145
#, gcc-internal-format
@@ -59532,9 +59515,9 @@ msgid "Assumed-size dummy array with !$ACC DECLARE at %L"
msgstr "%Jlohkoattribuutti ei ole sallittu %qD:lle"
#: fortran/openmp.c:2137
-#, gcc-internal-format
+#, fuzzy, gcc-internal-format
msgid "%<acc update%> must contain at least one %<device%> or %<host%> or %<self%> clause at %L"
-msgstr ""
+msgstr "%Hdatamäärittelyllä ei ole tyyppiä eikä tallennusluokkaa"
#: fortran/openmp.c:2185
#, fuzzy, gcc-internal-format, gfc-internal-format
@@ -60241,9 +60224,9 @@ msgid "%s collapsed loops don't form rectangular iteration space at %L"
msgstr ""
#: fortran/openmp.c:5703
-#, gcc-internal-format, gfc-internal-format
+#, fuzzy, gcc-internal-format, gfc-internal-format
msgid "collapsed %s loops not perfectly nested at %L"
-msgstr ""
+msgstr "liian vähän argumentteja"
#: fortran/openmp.c:5712 fortran/openmp.c:5720
#, fuzzy, gcc-internal-format, gfc-internal-format
@@ -60276,9 +60259,9 @@ msgid "!$ACC LOOP %s loops don't form rectangular iteration space at %L"
msgstr ""
#: fortran/openmp.c:5870
-#, gcc-internal-format, gfc-internal-format
+#, fuzzy, gcc-internal-format, gfc-internal-format
msgid "%s !$ACC LOOP loops not perfectly nested at %L"
-msgstr ""
+msgstr "liian vähän argumentteja"
#: fortran/openmp.c:5880 fortran/openmp.c:5889
#, fuzzy, gcc-internal-format, gfc-internal-format
@@ -60326,9 +60309,9 @@ msgid "OMP TARGET UPDATE at %L requires at least one TO or FROM clause"
msgstr ""
#: fortran/openmp.c:6229
-#, gcc-internal-format
+#, fuzzy, gcc-internal-format
msgid "!$OMP DECLARE SIMD should refer to containing procedure %qs at %L"
-msgstr ""
+msgstr "tyhjä esittely"
#: fortran/openmp.c:6253
#, fuzzy, gcc-internal-format, gfc-internal-format
@@ -60616,9 +60599,9 @@ msgid "Already inside a CONTAINS block at %C"
msgstr "ISO C kieltää sisäkkäiset funktiot"
#: fortran/parse.c:3007
-#, gcc-internal-format, gfc-internal-format
+#, fuzzy, gcc-internal-format, gfc-internal-format
msgid "Component %s at %L of type LOCK_TYPE must have a codimension or be a subcomponent of a coarray, which is not possible as the component has the pointer attribute"
-msgstr ""
+msgstr "muuttuvakokoista objektia ei voi alustaa"
#: fortran/parse.c:3013
#, fuzzy, gcc-internal-format, gfc-internal-format
@@ -60636,9 +60619,9 @@ msgid "Allocatable component %s at %L must have a codimension as it has a noncoa
msgstr "muuttuvakokoista objektia ei voi alustaa"
#: fortran/parse.c:3027
-#, gcc-internal-format, gfc-internal-format
+#, fuzzy, gcc-internal-format, gfc-internal-format
msgid "Noncoarray component %s at %L of type LOCK_TYPE or with subcomponent of type LOCK_TYPE must have a codimension or be a subcomponent of a coarray. (Variables of type %s may not have a codimension as already a coarray subcomponent exists)"
-msgstr ""
+msgstr "muuttuvakokoista objektia ei voi alustaa"
#: fortran/parse.c:3034
#, gcc-internal-format, gfc-internal-format
@@ -60651,9 +60634,9 @@ msgid "Component %s at %L of type EVENT_TYPE must have a codimension or be a sub
msgstr ""
#: fortran/parse.c:3050
-#, gcc-internal-format, gfc-internal-format
+#, fuzzy, gcc-internal-format, gfc-internal-format
msgid "Pointer component %s at %L has a noncoarray subcomponent of type EVENT_TYPE, which must have a codimension or be a subcomponent of a coarray"
-msgstr ""
+msgstr "muuttuvakokoista objektia ei voi alustaa"
#: fortran/parse.c:3055
#, fuzzy, gcc-internal-format, gfc-internal-format
@@ -60661,9 +60644,9 @@ msgid "Allocatable component %s at %L of type EVENT_TYPE must have a codimension
msgstr "muuttuvakokoista objektia ei voi alustaa"
#: fortran/parse.c:3059
-#, gcc-internal-format, gfc-internal-format
+#, fuzzy, gcc-internal-format, gfc-internal-format
msgid "Allocatable component %s at %L must have a codimension as it has a noncoarray subcomponent of type EVENT_TYPE"
-msgstr ""
+msgstr "muuttuvakokoista objektia ei voi alustaa"
#: fortran/parse.c:3064
#, gcc-internal-format, gfc-internal-format
@@ -60726,9 +60709,9 @@ msgid "CONTAINS block in derived type definition at %C"
msgstr ""
#: fortran/parse.c:3418
-#, gcc-internal-format, gfc-internal-format
+#, fuzzy, gcc-internal-format, gfc-internal-format
msgid "ENUM declaration at %C has no ENUMERATORS"
-msgstr ""
+msgstr "Syntaksivirhe VALUE-lauseessa kohdassa %C"
#: fortran/parse.c:3505
#, gcc-internal-format, gfc-internal-format
@@ -61686,9 +61669,9 @@ msgid "The element in the structure constructor at %L, for pointer component %qs
msgstr "Taulukkomuodostimen CHARACTER-alkioiden kohdassa %L on oltava saman pituisia (%d/%d)"
#: fortran/resolve.c:1395
-#, gcc-internal-format
+#, fuzzy, gcc-internal-format
msgid "The NULL in the structure constructor at %L is being applied to component %qs, which is neither a POINTER nor ALLOCATABLE"
-msgstr ""
+msgstr "Taulukkomuodostimen CHARACTER-alkioiden kohdassa %L on oltava saman pituisia (%d/%d)"
#: fortran/resolve.c:1430
#, fuzzy, gcc-internal-format
@@ -61701,9 +61684,9 @@ msgid "The element in the structure constructor at %L, for pointer component %qs
msgstr "Taulukkomuodostimen CHARACTER-alkioiden kohdassa %L on oltava saman pituisia (%d/%d)"
#: fortran/resolve.c:1475
-#, gcc-internal-format
+#, fuzzy, gcc-internal-format
msgid "Invalid expression in the structure constructor for pointer component %qs at %L in PURE procedure"
-msgstr ""
+msgstr "Taulukkomuodostimen CHARACTER-alkioiden kohdassa %L on oltava saman pituisia (%d/%d)"
#: fortran/resolve.c:1599
#, gcc-internal-format
@@ -61942,9 +61925,9 @@ msgid "Generic subroutine %qs at %L is not consistent with an intrinsic subrouti
msgstr "Luontaisella â€%s†kohdassa %L ei voi olla alustinta"
#: fortran/resolve.c:3479
-#, gcc-internal-format
+#, fuzzy, gcc-internal-format
msgid "Subroutine %qs at %L is INTRINSIC but is not compatible with an intrinsic"
-msgstr ""
+msgstr "Luontaisella â€%s†kohdassa %L ei voi olla alustinta"
#: fortran/resolve.c:3524
#, fuzzy, gcc-internal-format
@@ -62255,9 +62238,9 @@ msgid "Passed-object at %L must be scalar"
msgstr "Lausekkeen CASE-lauseessa kohdassa %L on oltava skalaari"
#: fortran/resolve.c:6079
-#, gcc-internal-format
+#, fuzzy, gcc-internal-format
msgid "Base object for procedure-pointer component call at %L is of ABSTRACT type %qs"
-msgstr ""
+msgstr "FINAL-proseduurin argumentin kohdassa %L täytyy olla tyyppiä â€%sâ€"
#: fortran/resolve.c:6118
#, fuzzy, gcc-internal-format
@@ -62271,9 +62254,9 @@ msgstr "FINAL-proseduurin argumentin kohdassa %L täytyy olla tyyppiä â€%sâ€"
#. Nothing matching found!
#: fortran/resolve.c:6315
-#, gcc-internal-format
+#, fuzzy, gcc-internal-format
msgid "Found no matching specific binding for the call to the GENERIC %qs at %L"
-msgstr ""
+msgstr "%J%qD:lle ei ole aiempaa esittelyä"
#: fortran/resolve.c:6349
#, fuzzy, gcc-internal-format
@@ -62625,9 +62608,9 @@ msgid "DTIO %s procedure at %L must be recursive"
msgstr "Lausekkeen CASE-lauseessa kohdassa %L on oltava skalaari"
#: fortran/resolve.c:9514
-#, gcc-internal-format, gfc-internal-format
+#, fuzzy, gcc-internal-format, gfc-internal-format
msgid "Data transfer element at %L cannot be polymorphic unless it is processed by a defined input/output procedure"
-msgstr ""
+msgstr "muuttuvakokoista objektia ei voi alustaa"
#: fortran/resolve.c:9527
#, fuzzy, gcc-internal-format, gfc-internal-format
@@ -62710,9 +62693,9 @@ msgid "Imageset argument at %L must between 1 and num_images()"
msgstr "puhdistusargumentti ei ole tunniste"
#: fortran/resolve.c:9816
-#, gcc-internal-format, gfc-internal-format
+#, fuzzy, gcc-internal-format, gfc-internal-format
msgid "Statement at %L is not a valid branch target statement for the branch statement at %L"
-msgstr ""
+msgstr "Odotettiin muuttujaa READ-lauseessa kohdassa %C"
#: fortran/resolve.c:9826
#, gcc-internal-format, gfc-internal-format
@@ -62972,9 +62955,9 @@ msgid "Implied SAVE for module variable %qs at %L, needed due to the default ini
msgstr "muuttuvakokoista objektia ei voi alustaa"
#: fortran/resolve.c:12362
-#, gcc-internal-format
+#, fuzzy, gcc-internal-format
msgid "Entity %qs at %L has a deferred type parameter and requires either the POINTER or ALLOCATABLE attribute"
-msgstr ""
+msgstr "kolme pistettä sisältävä parametriluettelo ei sovellu tyhjään parametrinimiluettelon esittelyyn"
#. F08:C541. The shape of an array defined in a main program or module
#. * needs to be constant.
@@ -63042,9 +63025,9 @@ msgid "Character-valued statement function %qs at %L must have constant length"
msgstr "%<__builtin_expect%>-funktion toisen argumentin pitää olla vakio"
#: fortran/resolve.c:12605
-#, gcc-internal-format
+#, fuzzy, gcc-internal-format
msgid "%qs is of a PRIVATE type and cannot be a dummy argument of %qs, which is PUBLIC at %L"
-msgstr ""
+msgstr "Proseduuri â€%s†kohdassa %L ei voi olla perustyyppiä %s"
#: fortran/resolve.c:12627
#, gcc-internal-format
@@ -63142,9 +63125,9 @@ msgid "Mismatch in ELEMENTAL attribute between MODULE PROCEDURE at %L and its in
msgstr ""
#: fortran/resolve.c:12881
-#, gcc-internal-format, gfc-internal-format
+#, fuzzy, gcc-internal-format, gfc-internal-format
msgid "Mismatch in PURE attribute between MODULE PROCEDURE at %L and its interface in %s"
-msgstr ""
+msgstr "Syntaksivirhe PROCEDURE-lauseessa kohdassa %C"
#: fortran/resolve.c:12889
#, gcc-internal-format, gfc-internal-format
@@ -63412,14 +63395,14 @@ msgid "Assumed size array %qs in namelist %qs at %L is not allowed"
msgstr "Tyhjä taulukkomuodostin kohdassa %C ei ole sallittu"
#: fortran/resolve.c:14504
-#, gcc-internal-format
+#, fuzzy, gcc-internal-format
msgid "NAMELIST array object %qs with assumed shape in namelist %qs at %L"
-msgstr ""
+msgstr "funktiota %<__builtin_next_arg%> kutsuttu ilman argumenttia"
#: fortran/resolve.c:14510
-#, gcc-internal-format
+#, fuzzy, gcc-internal-format
msgid "NAMELIST array object %qs with nonconstant shape in namelist %qs at %L"
-msgstr ""
+msgstr "funktiota %<__builtin_next_arg%> kutsuttu ilman argumenttia"
#: fortran/resolve.c:14518
#, fuzzy, gcc-internal-format
@@ -63427,19 +63410,19 @@ msgid "NAMELIST object %qs with nonconstant character length in namelist %qs at
msgstr "funktiota %<__builtin_next_arg%> kutsuttu ilman argumenttia"
#: fortran/resolve.c:14535
-#, gcc-internal-format
+#, fuzzy, gcc-internal-format
msgid "NAMELIST object %qs was declared PRIVATE and cannot be member of PUBLIC namelist %qs at %L"
-msgstr ""
+msgstr "funktiota %<__builtin_next_arg%> kutsuttu ilman argumenttia"
#: fortran/resolve.c:14557
-#, gcc-internal-format
+#, fuzzy, gcc-internal-format
msgid "NAMELIST object %qs has use-associated PRIVATE components and cannot be member of namelist %qs at %L"
-msgstr ""
+msgstr "funktiota %<__builtin_next_arg%> kutsuttu ilman argumenttia"
#: fortran/resolve.c:14568
-#, gcc-internal-format
+#, fuzzy, gcc-internal-format
msgid "NAMELIST object %qs has PRIVATE components and cannot be a member of PUBLIC namelist %qs at %L"
-msgstr ""
+msgstr "funktiota %<__builtin_next_arg%> kutsuttu ilman argumenttia"
#: fortran/resolve.c:14595
#, fuzzy, gcc-internal-format
@@ -63497,9 +63480,9 @@ msgid "PROCEDURE attribute conflicts with PROTECTED attribute at %L"
msgstr "SAVE-attribuuttia kohdassa %L ei voida määritellä PURE-proseduurissa"
#: fortran/resolve.c:14925
-#, gcc-internal-format
+#, fuzzy, gcc-internal-format
msgid "%qs at %L has the CONTIGUOUS attribute but is not an array pointer or an assumed-shape or assumed-rank array"
-msgstr ""
+msgstr "Muuttujalla â€%s†kohdassa %L ei voi olla sekä POINTER- että BIND(C)-attribuutit"
#: fortran/resolve.c:14946
#, fuzzy, gcc-internal-format, gfc-internal-format
@@ -63622,9 +63605,9 @@ msgid "Variable %s at %L of type EVENT_TYPE or with subcomponent of type EVENT_T
msgstr ""
#: fortran/resolve.c:15277
-#, gcc-internal-format
+#, fuzzy, gcc-internal-format
msgid "The INTENT(OUT) dummy argument %qs at %L is ASSUMED SIZE and so cannot have a default initializer"
-msgstr ""
+msgstr "kääntäjänsisäisen â€%2$sâ€-funktion argumentin â€%1$s†kohdassa %3$L ei voi olla INTENT(IN)"
#: fortran/resolve.c:15289
#, fuzzy, gcc-internal-format
@@ -64714,14 +64697,14 @@ msgid "Invalid expression in gfc_target_interpret_expr."
msgstr "epäkelvot operandit binääriselle %s-operaatiolle"
#: fortran/target-memory.c:704
-#, gcc-internal-format, gfc-internal-format
+#, fuzzy, gcc-internal-format, gfc-internal-format
msgid "Overlapping unequal initializers in EQUIVALENCE at %L"
-msgstr ""
+msgstr "Odotettiin argumenttiluetteloa kohdassa %C"
#: fortran/target-memory.c:707
-#, gcc-internal-format, gfc-internal-format
+#, fuzzy, gcc-internal-format, gfc-internal-format
msgid "Overlapping unequal initializers in EQUIVALENCE at %C"
-msgstr ""
+msgstr "Odotettiin argumenttiluetteloa kohdassa %C"
#: fortran/target-memory.c:797
#, fuzzy, gcc-internal-format, gfc-internal-format
@@ -65048,9 +65031,9 @@ msgid "gfc_validate_kind(): Got bad type"
msgstr "vektoriylivuoto lausekkeessa"
#: fortran/trans-types.c:777
-#, gcc-internal-format
+#, fuzzy, gcc-internal-format
msgid "gfc_validate_kind(): Got bad kind"
-msgstr ""
+msgstr "vektoriylivuoto lausekkeessa"
#: fortran/trans.c:2117
#, fuzzy, gcc-internal-format
@@ -65669,9 +65652,9 @@ msgid "strong-cast assignment has been intercepted"
msgstr "muuttujalla %qD on alustin, mutta vaillinainen tyyppi"
#: objc/objc-act.c:3732
-#, gcc-internal-format
+#, fuzzy, gcc-internal-format
msgid "strong-cast may possibly be needed"
-msgstr ""
+msgstr "muuttujalla %qD on alustin, mutta vaillinainen tyyppi"
#: objc/objc-act.c:3742
#, fuzzy, gcc-internal-format
@@ -66303,7 +66286,6 @@ msgstr "luokkanimeä ei ole annettu %qs:n kanssa"
#: c-family/c.opt:1519
#, fuzzy, gcc-internal-format
-#| msgid "-fhandle-exceptions has been renamed -fexceptions (and is now on by default)"
msgid "%<-fhandle-exceptions%> has been renamed %<-fexceptions%> (and is now on by default)"
msgstr "-fhandle-exceptions on uudelleennimetty: -fexceptions (ja se on nyt oletuksena päällä)"
diff --git a/gcc/po/fr.po b/gcc/po/fr.po
index fefda93..dce1b2d 100644
--- a/gcc/po/fr.po
+++ b/gcc/po/fr.po
@@ -132,10 +132,10 @@
#
msgid ""
msgstr ""
-"Project-Id-Version: gcc 9.1-b20190414\n"
+"Project-Id-Version: gcc 9.1.0\n"
"Report-Msgid-Bugs-To: https://gcc.gnu.org/bugs/\n"
"POT-Creation-Date: 2019-05-02 20:28+0000\n"
-"PO-Revision-Date: 2019-04-21 11:13+0200\n"
+"PO-Revision-Date: 2019-05-08 21:01+0200\n"
"Last-Translator: Frédéric Marchal <fmarchal@perso.be>\n"
"Language-Team: French <traduc@traduc.org>\n"
"Language: fr\n"
@@ -1406,12 +1406,13 @@ msgid " All options with the desired characteristics have already been displayed
msgstr " Toutes les options avec les caractéristiques désirées ont déjà été affichées\n"
#: opts.c:1581
-#, fuzzy, c-format
-#| msgid "invalid arguments for %<-falign-%s%> option: %qs"
+#, c-format
msgid ""
" Known valid arguments for %s option:\n"
" "
-msgstr "arguments invalides pour l'option %<-falign-%s%>: %qs"
+msgstr ""
+" Arguments valides connus pour l’option %s:\n"
+" "
#: opts.c:1631
msgid "The following options are target specific"
@@ -8059,10 +8060,8 @@ msgid "-fdoc-inc=<file>\tInclude a Ddoc macro <file>."
msgstr "-fdoc-inc=<fichier>\tInclure un <fichier> macro Ddoc."
#: d/lang.opt:234
-#, fuzzy
-#| msgid "Do not assume that standard C libraries and \"main\" exist."
msgid "Assume that standard D runtime libraries and \"D main\" exist."
-msgstr "Ne pas supposer que les bibliothèques standards du C et « main » existent."
+msgstr "Supposer que les bibliothèques standards d’exécution du D et « D main » existent."
#: d/lang.opt:238
msgid "Display the frontend AST after parsing and semantic passes."
@@ -10968,19 +10967,17 @@ msgid "Cost to assume for a branch insn."
msgstr "Coût supposé pour une insn de branchement."
#: config/arm/arm.opt:308
-#, fuzzy
-#| msgid "Generate code which uses only the general registers."
msgid "Generate code which uses the core registers only (r0-r14)."
-msgstr "Générer du code qui n'utilise que des registres généraux."
+msgstr "Générer du code qui n’utilise que des registres du cœur (r0-r14)."
#: config/sparc/sparc.opt:30 config/sparc/sparc.opt:34
#: config/visium/visium.opt:37
msgid "Use hardware FP."
-msgstr "Utiliser l'unité en virgule flottante matérielle."
+msgstr "Utiliser l’unité en virgule flottante matérielle."
#: config/sparc/sparc.opt:38 config/visium/visium.opt:41
msgid "Do not use hardware FP."
-msgstr "Ne pas utiliser l'unité en virgule flottante matérielle."
+msgstr "Ne pas utiliser l’unité en virgule flottante matérielle."
#: config/sparc/sparc.opt:42
msgid "Use flat register window model."
@@ -19488,12 +19485,11 @@ msgid "using the range [%E, %E] for directive argument"
msgstr "utilise la plage [%E, %E] pour l'argument de la directive"
#: gimple-ssa-sprintf.c:3020
-#, fuzzy, gcc-internal-format
-#| msgid "%qE output %wu byte into a destination of size %wu"
+#, gcc-internal-format
msgid "%qE output %wu byte into a destination of size %wu"
msgid_plural "%qE output %wu bytes into a destination of size %wu"
msgstr[0] "%qE écrit %wu octet dans une destination dont la taille est %wu"
-msgstr[1] "%qE écrit %wu octet dans une destination dont la taille est %wu"
+msgstr[1] "%qE écrit %wu octets dans une destination dont la taille est %wu"
#: gimple-ssa-sprintf.c:3025
#, gcc-internal-format
@@ -19511,12 +19507,11 @@ msgid "%qE output %wu or more bytes into a destination of size %wu"
msgstr "%qE écrit %wu octets ou plus dans une destination dont la taille est %wu"
#: gimple-ssa-sprintf.c:3046
-#, fuzzy, gcc-internal-format
-#| msgid "%qE output %wu byte"
+#, gcc-internal-format
msgid "%qE output %wu byte"
msgid_plural "%qE output %wu bytes"
msgstr[0] "%qE écrit %wu octet"
-msgstr[1] "%qE écrit %wu octet"
+msgstr[1] "%qE écrit %wu octets"
#: gimple-ssa-sprintf.c:3050
#, gcc-internal-format
@@ -28258,8 +28253,7 @@ msgid "unknown tuning option (%s)"
msgstr "option d'ajustement inconnue (%s)"
#: config/aarch64/aarch64.c:11486
-#, fuzzy, gcc-internal-format
-#| msgid "incompatible options %<-mstack-protector-guard=global%> and%<-mstack-protector-guard-offset=%s%>"
+#, gcc-internal-format
msgid "incompatible options %<-mstack-protector-guard=global%> and %<-mstack-protector-guard-offset=%s%>"
msgstr "%<-mstack-protector-guard=global%> et %<-mstack-protector-guard-offset=%qs%> incompatibles"
@@ -28560,16 +28554,14 @@ msgid "%<-mspfp_fast%> not available on ARC600 or ARC601"
msgstr "%<-mspfp_fast%> pas disponible sur ARC600 ou ARC601"
#: config/arc/arc.c:953
-#, fuzzy, gcc-internal-format
-#| msgid "No FPX/FPU mixing allowed"
+#, gcc-internal-format
msgid "no FPX/FPU mixing allowed"
-msgstr "Le mélange de FPX/FPU est interdit"
+msgstr "le mélange de FPX/FPU est interdit"
#: config/arc/arc.c:958
-#, fuzzy, gcc-internal-format
-#| msgid "PIC is only supported for RTPs"
+#, gcc-internal-format
msgid "PIC is not supported for %qs"
-msgstr "PIC est uniquement supporté pour RTP"
+msgstr "PIC n’est pas supporté pour %qs"
#: config/arc/arc.c:1021
#, gcc-internal-format
@@ -28615,28 +28607,24 @@ msgstr "l'option %<-mrgf-banked-regs%> est uniquement valable pour les processeu
#. translated. They are like keywords which one can relate with the
#. architectural choices taken for an ARC CPU implementation.
#: config/arc/arc.c:1227
-#, fuzzy, gcc-internal-format
-#| msgid "Option %s=%s is not available for %s CPU."
+#, gcc-internal-format
msgid "option %<%s=%s%> is not available for %qs CPU"
-msgstr "L'option %s=%s n'est pas disponible pour le processeur %s."
+msgstr "l’option %<%s=%s%> n’est pas disponible pour le processeur %qs"
#: config/arc/arc.c:1232
-#, fuzzy, gcc-internal-format
-#| msgid "Option %s is ignored, the default value %s is considered for %s CPU."
+#, gcc-internal-format
msgid "option %qs is ignored, the default value %qs is considered for %qs CPU"
-msgstr "L'option %s est ignorée, la valeur par défaut %s est considérée pour le processeur %s."
+msgstr "l’option %qs est ignorée, la valeur par défaut %qs est considérée pour le processeur %qs"
#: config/arc/arc.c:1240
-#, fuzzy, gcc-internal-format
-#| msgid "Option %s is not available for %s CPU"
+#, gcc-internal-format
msgid "option %qs is not available for %qs CPU"
-msgstr "L'option %s n'est pas disponible pour le processeur %s"
+msgstr "l’option %qs n'est pas disponible pour le processeur %qs"
#: config/arc/arc.c:1245
-#, fuzzy, gcc-internal-format
-#| msgid "Unset option %s is ignored, it is always enabled for %s CPU."
+#, gcc-internal-format
msgid "unset option %qs is ignored, it is always enabled for %qs CPU"
-msgstr "Supprimer la définition de l'option %s est ignoré, elle est toujours activée pour le processeur %s."
+msgstr "supprimer la définition de l’option %qs est ignoré, elle est toujours activée pour le processeur %qs"
#: config/arc/arc.c:1812
#, gcc-internal-format, gfc-internal-format
@@ -28758,14 +28746,12 @@ msgid "unknown builtin immediate operand type for operand %d"
msgstr "type d'opérande immédiat de la fonction intégrée inconnu pour l'opérande %d"
#: config/arc/arc.c:7273
-#, fuzzy, gcc-internal-format
-#| msgid "register number must be a compile-time constant. Try giving higher optimization levels"
+#, gcc-internal-format
msgid "register number must be a compile-time constant. Try giving higher optimization levels"
msgstr "le numéro de registre doit être une constante à la compilation. Essayez à des niveaux d'optimisation supérieurs"
#: config/arc/arc.c:8268
-#, fuzzy, gcc-internal-format
-#| msgid "Insn addresses not set after shorten_branches"
+#, gcc-internal-format
msgid "insn addresses not set after shorten_branches"
msgstr "les adresses des insn ne sont pas définies après shorten_branches"
@@ -29172,7 +29158,7 @@ msgstr "ABI VFP en virgule flottante matérielle du Thumb-1"
#: config/arm/arm.c:6117
#, gcc-internal-format
msgid "argument of type %qT not permitted with -mgeneral-regs-only"
-msgstr ""
+msgstr "argument de type %qT pas permis avec -mgeneral-regs-only"
#: config/arm/arm.c:6501 config/arm/arm.c:6714 config/arm/arm.c:6747
#: config/arm/arm.c:27083
@@ -30629,10 +30615,9 @@ msgid "no dispatcher found for the versioning attributes"
msgstr "pas de répartiteur trouvé pour les attributs de version"
#: config/i386/i386.c:32300
-#, fuzzy, gcc-internal-format
-#| msgid "value %qs is not supported by attribute %<target%>"
+#, gcc-internal-format
msgid "ISA %qs is not supported in %<target%> attribute, use %<arch=%> syntax"
-msgstr "la valeur %qs n'est pas supportée par l'attribut %<target%>"
+msgstr "l’ISA %qs n'est pas supportée par l'attribut %<target%>, utilisez la syntaxe %<arch=%>"
#: config/i386/i386.c:32311
#, gcc-internal-format, gfc-internal-format
@@ -53140,10 +53125,9 @@ msgid "MODULE prefix at %C"
msgstr "Préfixe de MODULE à %C"
#: fortran/decl.c:6130
-#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "MODULE PROCEDURE at %C must be in a generic module interface"
+#, gcc-internal-format, gfc-internal-format
msgid "MODULE prefix at %C found outside of a module, submodule, or interface"
-msgstr "MODULE PROCEDURE à %C doit être dans une interface de module générique"
+msgstr "préfixe MODULE à %C trouvé en dehors d'un module, sous-module ou interface"
#: fortran/decl.c:6177
#, gcc-internal-format, gfc-internal-format
diff --git a/gcc/po/sv.po b/gcc/po/sv.po
index cf62763..2bebd9b 100644
--- a/gcc/po/sv.po
+++ b/gcc/po/sv.po
@@ -22,10 +22,10 @@
# thunk snutt
msgid ""
msgstr ""
-"Project-Id-Version: gcc 9.1-b20190414\n"
+"Project-Id-Version: gcc 9.1.0\n"
"Report-Msgid-Bugs-To: https://gcc.gnu.org/bugs/\n"
"POT-Creation-Date: 2019-05-02 20:28+0000\n"
-"PO-Revision-Date: 2019-05-05 22:48+0200\n"
+"PO-Revision-Date: 2019-06-04 10:48+0200\n"
"Last-Translator: Göran Uddeborg <goeran@uddeborg.se>\n"
"Language-Team: Swedish <tp-sv@listor.tp-sv.se>\n"
"Language: sv\n"
@@ -1297,12 +1297,13 @@ msgid " All options with the desired characteristics have already been displayed
msgstr " Alla flaggor med de eftersökta egenskaperna har redan visats\n"
#: opts.c:1581
-#, fuzzy, c-format
-#| msgid "invalid arguments for %<-falign-%s%> option: %qs"
+#, c-format
msgid ""
" Known valid arguments for %s option:\n"
" "
-msgstr "ogiltigt argument till flaggan %<-falign-%s%>: %qs"
+msgstr ""
+" Kända giltiga argument till flaggan %s:\n"
+" "
#: opts.c:1631
msgid "The following options are target specific"
@@ -7953,10 +7954,8 @@ msgid "-fdoc-inc=<file>\tInclude a Ddoc macro <file>."
msgstr "-fdoc-inc=<fil>\t\tInkludera ett Ddoc-makro <fil>."
#: d/lang.opt:234
-#, fuzzy
-#| msgid "Do not assume that standard C libraries and \"main\" exist."
msgid "Assume that standard D runtime libraries and \"D main\" exist."
-msgstr "Anta inte att standard C-bibliotek och â€main†finns."
+msgstr "Anta att standard D-körtidsbibliotek och â€D main†finns."
#: d/lang.opt:238
msgid "Display the frontend AST after parsing and semantic passes."
@@ -10859,10 +10858,8 @@ msgid "Cost to assume for a branch insn."
msgstr "Kostnad att anta för en greninstruktion."
#: config/arm/arm.opt:308
-#, fuzzy
-#| msgid "Generate code which uses only the general registers."
msgid "Generate code which uses the core registers only (r0-r14)."
-msgstr "Generera kod som använder endast generella register."
+msgstr "Generera kod som endast använder kärnregister (r0-r14)."
#: config/sparc/sparc.opt:30 config/sparc/sparc.opt:34
#: config/visium/visium.opt:37
@@ -19365,8 +19362,7 @@ msgid "using the range [%E, %E] for directive argument"
msgstr "använder intervallet [%E, %E] som direktivargument"
#: gimple-ssa-sprintf.c:3020
-#, fuzzy, gcc-internal-format
-#| msgid "%qE output %wu byte into a destination of size %wu"
+#, gcc-internal-format
msgid "%qE output %wu byte into a destination of size %wu"
msgid_plural "%qE output %wu bytes into a destination of size %wu"
msgstr[0] "%qE-utdata på %wu byte in i en destination med storlek %wu"
@@ -19388,8 +19384,7 @@ msgid "%qE output %wu or more bytes into a destination of size %wu"
msgstr "%qE-utdata på %wu eller fler byte in i en destination med storlek %wu"
#: gimple-ssa-sprintf.c:3046
-#, fuzzy, gcc-internal-format
-#| msgid "%qE output %wu byte"
+#, gcc-internal-format
msgid "%qE output %wu byte"
msgid_plural "%qE output %wu bytes"
msgstr[0] "%qE-utdata %wu byte"
@@ -28124,8 +28119,7 @@ msgid "unknown tuning option (%s)"
msgstr "okänd trimningsflagga (%s)"
#: config/aarch64/aarch64.c:11486
-#, fuzzy, gcc-internal-format
-#| msgid "incompatible options %<-mstack-protector-guard=global%> and%<-mstack-protector-guard-offset=%s%>"
+#, gcc-internal-format
msgid "incompatible options %<-mstack-protector-guard=global%> and %<-mstack-protector-guard-offset=%s%>"
msgstr "inkompatibla flaggor %<-mstack-protector-guard=global%> och %<-mstack-protector-guard-offset=%s%>"
@@ -28426,16 +28420,14 @@ msgid "%<-mspfp_fast%> not available on ARC600 or ARC601"
msgstr "%<-mspfp_fast%> är inte tillgängligt på ARC600 eller ARC601"
#: config/arc/arc.c:953
-#, fuzzy, gcc-internal-format
-#| msgid "No FPX/FPU mixing allowed"
+#, gcc-internal-format
msgid "no FPX/FPU mixing allowed"
-msgstr "Ingen FPX/FPU-blandning tillåten"
+msgstr "ingen FPX/FPU-blandning tillåten"
#: config/arc/arc.c:958
-#, fuzzy, gcc-internal-format
-#| msgid "PIC is only supported for RTPs"
+#, gcc-internal-format
msgid "PIC is not supported for %qs"
-msgstr "PIC stödjs endast för RTP:er"
+msgstr "PIC stödjs inte för %qs"
#: config/arc/arc.c:1021
#, gcc-internal-format
@@ -28481,28 +28473,24 @@ msgstr "flaggan %<-mrgf-banked-regs%> är giltig endast för ARC v2-processorer"
#. translated. They are like keywords which one can relate with the
#. architectural choices taken for an ARC CPU implementation.
#: config/arc/arc.c:1227
-#, fuzzy, gcc-internal-format
-#| msgid "Option %s=%s is not available for %s CPU."
+#, gcc-internal-format
msgid "option %<%s=%s%> is not available for %qs CPU"
-msgstr "Flaggan %s=%s är inte tillgänglig för CPU:n %s."
+msgstr "flaggan %<%s=%s%> är inte tillgänglig för CPU:n %qs."
#: config/arc/arc.c:1232
-#, fuzzy, gcc-internal-format
-#| msgid "Option %s is ignored, the default value %s is considered for %s CPU."
+#, gcc-internal-format
msgid "option %qs is ignored, the default value %qs is considered for %qs CPU"
-msgstr "Flaggan %s ignoreras, standardvärdet %s antas för CPU:n %s."
+msgstr "flaggan %s ignoreras, standardvärdet %qs antas för CPU:n %qs."
#: config/arc/arc.c:1240
-#, fuzzy, gcc-internal-format
-#| msgid "Option %s is not available for %s CPU"
+#, gcc-internal-format
msgid "option %qs is not available for %qs CPU"
-msgstr "Flaggan %s är inte tillgänglig för CPU:n %s"
+msgstr "flaggan %qs är inte tillgänglig för CPU:n %qs"
#: config/arc/arc.c:1245
-#, fuzzy, gcc-internal-format
-#| msgid "Unset option %s is ignored, it is always enabled for %s CPU."
+#, gcc-internal-format
msgid "unset option %qs is ignored, it is always enabled for %qs CPU"
-msgstr "Den nollställda flaggan %s ignoreras, den är alltid aktiverad för CPU:n %s."
+msgstr "den nollställda flaggan %qs ignoreras, den är alltid aktiverad för CPU:n %qs."
#: config/arc/arc.c:1812
#, gcc-internal-format, gfc-internal-format
@@ -28624,16 +28612,14 @@ msgid "unknown builtin immediate operand type for operand %d"
msgstr "okänd inbyggd omedelbar operandtyp för operand %d"
#: config/arc/arc.c:7273
-#, fuzzy, gcc-internal-format
-#| msgid "register number must be a compile-time constant. Try giving higher optimization levels"
+#, gcc-internal-format
msgid "register number must be a compile-time constant. Try giving higher optimization levels"
msgstr "registernummer måste vara en konstant vid kompileringstillfället. Försök att ange högre optimeringsnivåer"
#: config/arc/arc.c:8268
-#, fuzzy, gcc-internal-format
-#| msgid "Insn addresses not set after shorten_branches"
+#, gcc-internal-format
msgid "insn addresses not set after shorten_branches"
-msgstr "Instruktionsadresser sätts inte efter shorten_branches"
+msgstr "instruktionsadresser sätts inte efter shorten_branches"
#: config/arc/arc.c:8481
#, gcc-internal-format
@@ -29038,7 +29024,7 @@ msgstr "Thumb-1 hårda flyttals VFP ABI"
#: config/arm/arm.c:6117
#, gcc-internal-format
msgid "argument of type %qT not permitted with -mgeneral-regs-only"
-msgstr ""
+msgstr "argument av typen %qT är inte tillåtna med -mgeneral-regs-only"
#: config/arm/arm.c:6501 config/arm/arm.c:6714 config/arm/arm.c:6747
#: config/arm/arm.c:27083
@@ -30496,10 +30482,9 @@ msgid "no dispatcher found for the versioning attributes"
msgstr "ingen avsändare funnen för versionsattributen"
#: config/i386/i386.c:32300
-#, fuzzy, gcc-internal-format
-#| msgid "value %qs is not supported by attribute %<target%>"
+#, gcc-internal-format
msgid "ISA %qs is not supported in %<target%> attribute, use %<arch=%> syntax"
-msgstr "värdet %qs stödjs inte av attributet %<target%>"
+msgstr "ISA:n %qs stödjs inte i attributet %<target%>, använd syntaxen %<arch=%>"
#: config/i386/i386.c:32311
#, gcc-internal-format, gfc-internal-format
@@ -31854,10 +31839,9 @@ msgid "cannot open intermediate ptx file"
msgstr "kan inte öppna intermediär ptx-fil"
#: config/nvptx/nvptx.c:197
-#, fuzzy, gcc-internal-format
-#| msgid "option %s is not supported together with -fopenacc"
+#, gcc-internal-format
msgid "option %s is not supported together with %<-fopenacc%>"
-msgstr "flaggan %s stödjs inte tillsammans med -fopenacc"
+msgstr "flaggan %s stödjs inte tillsammans med %<-fopenacc%>"
#: config/nvptx/nvptx.c:223
#, gcc-internal-format
@@ -31890,10 +31874,9 @@ msgid "%qE attribute not allowed with auto storage class"
msgstr "attributet %qE är inte tillåtet med lagringsklassen auto"
#: config/nvptx/nvptx.c:5641
-#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "using vector_length (%d), ignoring %d"
+#, gcc-internal-format, gfc-internal-format
msgid "using vector_length (%d) due to call to vector-partitionable routine, ignoring %d"
-msgstr "använder vector_length (%d), ignorerar %d"
+msgstr "använder vector_length (%d) på grund av anrop av vektorpartitionerbar rutin, ignorerar %d"
#: config/nvptx/nvptx.c:5649
#, gcc-internal-format, gfc-internal-format
@@ -31906,10 +31889,9 @@ msgid "using vector_length (%d), ignoring %d"
msgstr "använder vector_length (%d), ignorerar %d"
#: config/or1k/or1k.c:1268
-#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "unexpected operand"
+#, gcc-internal-format, gfc-internal-format
msgid "unexpected operand: %d"
-msgstr "oväntad operand"
+msgstr "oväntad operand: %d"
#: config/pa/pa.c:532
#, gcc-internal-format
@@ -31922,16 +31904,14 @@ msgid "PIC code generation is not compatible with fast indirect calls"
msgstr "PIC-kodsgenerering är inte kompatibelt med snabba indirekta anrop"
#: config/pa/pa.c:542
-#, fuzzy, gcc-internal-format
-#| msgid "-g is only supported when using GAS on this processor,"
+#, gcc-internal-format
msgid "%<-g%> is only supported when using GAS on this processor,"
-msgstr "-g stödjs bara när man använder GAS på denna processor,"
+msgstr "%<-g%> stödjs bara när man använder GAS på denna processor,"
#: config/pa/pa.c:543
-#, fuzzy, gcc-internal-format
-#| msgid "-g option disabled"
+#, gcc-internal-format
msgid "%<-g%> option disabled"
-msgstr "flaggan -g är avslagen"
+msgstr "flaggan %<-g%> är avslagen"
#: config/pa/pa.c:8794
#, gcc-internal-format, gfc-internal-format
@@ -31939,28 +31919,24 @@ msgid "alignment (%u) for %s exceeds maximum alignment for global common data.
msgstr "justering (%u) för %s överskrider maximal justering för globala common-data. Använder %u"
#: config/riscv/riscv.c:354
-#, fuzzy, gcc-internal-format
-#| msgid "unknown cpu %qs for -mtune"
+#, gcc-internal-format
msgid "unknown cpu %qs for %<-mtune%>"
-msgstr "okänt cpu %qs till -mtune"
+msgstr "okänt cpu %qs till %<-mtune%>"
#: config/riscv/riscv.c:2835
-#, fuzzy, gcc-internal-format
-#| msgid "argument to %qE attribute is neither zero, nor one"
+#, gcc-internal-format
msgid "argument to %qE attribute is not \"user\", \"supervisor\", or \"machine\""
-msgstr "argumentet till attributet %qE är varken noll eller ett"
+msgstr "argumentet till attributet %qE är inte â€userâ€, â€supervisor†eller â€machineâ€"
#: config/riscv/riscv.c:4461
-#, fuzzy, gcc-internal-format
-#| msgid "-mdiv requires -march to subsume the %<M%> extension"
+#, gcc-internal-format
msgid "%<-mdiv%> requires %<-march%> to subsume the %<M%> extension"
-msgstr "-mdiv kräver -march för att innefatta utökningen %<M%>"
+msgstr "%<-mdiv%> kräver %<-march%> för att innefatta utökningen %<M%>"
#: config/riscv/riscv.c:4502
-#, fuzzy, gcc-internal-format
-#| msgid "requested ABI requires -march to subsume the %qc extension"
+#, gcc-internal-format
msgid "requested ABI requires %<-march%> to subsume the %qc extension"
-msgstr "begärt ABI kräver -march för att innefatta utökningen %qc"
+msgstr "begärt ABI kräver %<-march%> för att innefatta utökningen %qc"
#: config/riscv/riscv.c:4506
#, gcc-internal-format
@@ -31968,16 +31944,14 @@ msgid "rv32e requires ilp32e ABI"
msgstr "rv32e kräver ABI:et ilp32e"
#: config/riscv/riscv.c:4510
-#, fuzzy, gcc-internal-format
-#| msgid "ABI requires -march=rv%d"
+#, gcc-internal-format
msgid "ABI requires %<-march=rv%d%>"
-msgstr "ABI:et kräver -march=rv%d"
+msgstr "ABI:et kräver %<-march=rv%d%>"
#: config/riscv/riscv.c:4520
-#, fuzzy, gcc-internal-format
-#| msgid "-mpreferred-stack-boundary=%d must be between %d and %d"
+#, gcc-internal-format
msgid "%<-mpreferred-stack-boundary=%d%> must be between %d and %d"
-msgstr "-mpreferred-stack-boundary=%d måste vara mellan %d och %d"
+msgstr "%<-mpreferred-stack-boundary=%d%> måste vara mellan %d och %d"
#: config/riscv/riscv.c:4533
#, gcc-internal-format
@@ -31985,17 +31959,15 @@ msgid "%<-mriscv-attribute%> RISC-V ELF attribute requires GNU as 2.32 [%<-mrisc
msgstr "%<-mriscv-attribute%> RISC-V ELF-attribut behöver GNU as 2.32 [%<-mriscv-attribute%>]"
#: config/riscv/riscv.c:4825
-#, fuzzy, gcc-internal-format
-#| msgid "%qs function cannot have arguments"
+#, gcc-internal-format
msgid "%qs function cannot have different interrupt type"
-msgstr "funktionen %qs kan inte ha argument"
+msgstr "funktionen %qs kan inte ha olika avbrottstyp"
#. Address spaces are currently only supported by C.
#: config/rl78/rl78.c:375
-#, fuzzy, gcc-internal-format
-#| msgid "-mes0 can only be used with C"
+#, gcc-internal-format
msgid "%<-mes0%> can only be used with C"
-msgstr "-mes0 kan endast användas med C"
+msgstr "%<-mes0%> kan endast användas med C"
#: config/rl78/rl78.c:378
#, gcc-internal-format
@@ -32003,31 +31975,27 @@ msgid "mduc registers only saved for G13 target"
msgstr "mduc-register sparas endast för målet G13"
#: config/rl78/rl78.c:393
-#, fuzzy, gcc-internal-format
-#| msgid "-mmul=g13 cannot be used with -mcpu=g10"
+#, gcc-internal-format
msgid "%<-mmul=g13%> cannot be used with %<-mcpu=g10%>"
-msgstr "-mmul=g13 kan inte användas med -mcpu=g10"
+msgstr "%<-mmul=g13%> kan inte användas med %<-mcpu=g10%>"
#: config/rl78/rl78.c:395
-#, fuzzy, gcc-internal-format
-#| msgid "-mmul=g14 cannot be used with -mcpu=g10"
+#, gcc-internal-format
msgid "%<-mmul=g14%> cannot be used with %<-mcpu=g10%>"
-msgstr "-mmul=g14 kan inte användas med -mcpu=g10"
+msgstr "%<-mmul=g14%> kan inte användas med %<-mcpu=g10%>"
#. The S2 core does not have mul/div instructions.
#: config/rl78/rl78.c:407
-#, fuzzy, gcc-internal-format
-#| msgid "-mmul=g14 cannot be used with -mcpu=g13"
+#, gcc-internal-format
msgid "%<-mmul=g14%> cannot be used with %<-mcpu=g13%>"
-msgstr "-mmul=g14 kan inte användas med -mcpu=g13"
+msgstr "%<-mmul=g14%> kan inte användas med %<-mcpu=g13%>"
#. The G14 core does not have the hardware multiply peripheral used by the
#. G13 core, hence you cannot use G13 multipliy routines on G14 hardware.
#: config/rl78/rl78.c:420
-#, fuzzy, gcc-internal-format
-#| msgid "-mmul=g13 cannot be used with -mcpu=g14"
+#, gcc-internal-format
msgid "%<-mmul=g13%> cannot be used with %<-mcpu=g14%>"
-msgstr "-mmul=g13 kan inte användas med -mcpu=g14"
+msgstr "%<-mmul=g13%> kan inte användas med %<-mcpu=g14%>"
#: config/rl78/rl78.c:843
#, gcc-internal-format
@@ -32035,8 +32003,7 @@ msgid "naked attribute only applies to functions"
msgstr "attributet naked är bara tillämpligt på funktioner"
#: config/rl78/rl78.c:867
-#, fuzzy, gcc-internal-format
-#| msgid "%qE attribute doesn't apply to functions"
+#, gcc-internal-format
msgid "%qE attribute doesn%'t apply to functions"
msgstr "attributet %qE är inte tillämpligt på funktioner"
@@ -32048,15 +32015,12 @@ msgid "converting far pointer to near pointer"
msgstr "konverterar fjärrpekare till närpekare"
#: config/rs6000/driver-rs6000.c:268
-#, fuzzy, gcc-internal-format
-#| msgid ""
-#| "Unsupported cpu name returned from kernel for -mcpu=native: %s\n"
-#| "Please use an explicit cpu name. Valid cpu names are: %s"
+#, gcc-internal-format
msgid ""
"Unsupported cpu name returned from kernel for %<-mcpu=native%>: %s\n"
"Please use an explicit cpu name. Valid cpu names are: %s"
msgstr ""
-"Ej stött cpu-namn returnerat från kärnan till -mcpu=native: %s\n"
+"Ej stött cpu-namn returnerat från kärnan till %<-mcpu=native%>: %s\n"
"Ange ett explicit cpu-namn. Giltiga cpu-namn är: %s"
#: config/rs6000/host-darwin.c:61
@@ -32221,10 +32185,9 @@ msgid "target attribute or pragma changes long double size"
msgstr "målattribut eller pragma ändrar storlek på long double"
#: config/rs6000/rs6000.c:4312
-#, fuzzy, gcc-internal-format
-#| msgid "%qs requires full ISA 3.0 support"
+#, gcc-internal-format
msgid "%qs requires full ISA 2.06 support"
-msgstr "%qs behöver fullt ISA 3.0-stöd"
+msgstr "%qs behöver fullt ISA 2.06-stöd"
#: config/rs6000/rs6000.c:4321
#, gcc-internal-format
@@ -32242,10 +32205,9 @@ msgid "%qs requires VSX support"
msgstr "%qs behöver VSX-stöd"
#: config/rs6000/rs6000.c:4350
-#, fuzzy, gcc-internal-format
-#| msgid "The -mfloat128 option may not be fully supported"
+#, gcc-internal-format
msgid "The %<-mfloat128%> option may not be fully supported"
-msgstr "Flaggan -mfloat128 kan inte stödjas helt"
+msgstr "Flaggan %<-mfloat128%> kanske inte stödjs fullt ut"
#: config/rs6000/rs6000.c:4373
#, gcc-internal-format
@@ -32333,10 +32295,9 @@ msgid "internal error: builtin function %qs already processed"
msgstr "internt fel: den inbyggda funktionen %qs redan bearbetad"
#: config/rs6000/rs6000.c:13378
-#, fuzzy, gcc-internal-format
-#| msgid "__builtin_saveregs not supported by this target"
+#, gcc-internal-format
msgid "%<__builtin_mffsl%> not supported with %<-msoft-float%>"
-msgstr "__builtin_saveregs stödjs inte på denna målarkitektur"
+msgstr "%<__builtin_mffsl%> stödjs inte med %<-msoft-float%>"
#: config/rs6000/rs6000.c:13419
#, gcc-internal-format
@@ -32344,46 +32305,39 @@ msgid "argument 1 must be an 8-bit field value"
msgstr "argument 1 måste vara ett 8-bitars fältvärde"
#: config/rs6000/rs6000.c:13450
-#, fuzzy, gcc-internal-format
-#| msgid "__builtin_thread_pointer is not supported on this target"
+#, gcc-internal-format
msgid "%<__builtin_mtfsb0%> and %<__builtin_mtfsb1%> not supported with %<-msoft-float%>"
-msgstr "__builtin_thread_pointer stödjs inte på denna målarkitektur"
+msgstr "%<__builtin_mtfsb0%> och %<__builtin_mtfsb1%> stödjs inte med %<-msoft-float%>"
#: config/rs6000/rs6000.c:13462
-#, fuzzy, gcc-internal-format
-#| msgid "%Klast argument of %qD is not integer constant between 0 and 3"
+#, gcc-internal-format
msgid "Argument must be a constant between 0 and 31."
-msgstr "%Ksista argumentet till %qD är inte en heltalskonstant mellan 0 och 3"
+msgstr "Argumentet måste vara en konstant mellan 0 och 31."
#: config/rs6000/rs6000.c:13488
-#, fuzzy, gcc-internal-format
-#| msgid "__builtin_eh_return not supported on this target"
+#, gcc-internal-format
msgid "%<__builtin_set_fpscr_rn%> not supported with %<-msoft-float%>"
-msgstr "__builtin_eh_return stödjs inte på denna målarkitektur"
+msgstr "%<__builtin_set_fpscr_rn%> stödjs inte med %<-msoft-float%>"
#: config/rs6000/rs6000.c:13503
-#, fuzzy, gcc-internal-format
-#| msgid "Argument of ACOS at %L must be between -1 and 1"
+#, gcc-internal-format
msgid "Argument must be a value between 0 and 3."
-msgstr "Argument till ACOS vid %L måste vara mellan -1 och 1"
+msgstr "Argumentet måste vara ett värde mellan 0 och 3."
#: config/rs6000/rs6000.c:13528
-#, fuzzy, gcc-internal-format
-#| msgid "__builtin_set_thread_pointer is not supported on this target"
+#, gcc-internal-format
msgid "%<__builtin_set_fpscr_drn%> is not supported in 32-bit mode."
-msgstr "__builtin_set_thread_pointer stödjs inte på denna målarkitektur"
+msgstr "%<__builtin_set_fpscr_drn%> stödjs inte i 32-bitsläge."
#: config/rs6000/rs6000.c:13533
-#, fuzzy, gcc-internal-format
-#| msgid "__builtin_eh_return not supported on this target"
+#, gcc-internal-format
msgid "%<__builtin_set_fpscr_drn%> not supported with %<-msoft-float%>"
-msgstr "__builtin_eh_return stödjs inte på denna målarkitektur"
+msgstr "%<__builtin_set_fpscr_drn%> stödjs inte med %<-msoft-float%>"
#: config/rs6000/rs6000.c:13552
-#, fuzzy, gcc-internal-format
-#| msgid "Argument of ACOS at %L must be between -1 and 1"
+#, gcc-internal-format
msgid "Argument must be a value between 0 and 7."
-msgstr "Argument till ACOS vid %L måste vara mellan -1 och 1"
+msgstr "Argumentet måste vara ett värde mellan 0 och 7."
#: config/rs6000/rs6000.c:13593
#, gcc-internal-format
@@ -32396,22 +32350,19 @@ msgid "argument 2 must be a 1-bit unsigned literal"
msgstr "argument 2 måste vara en 1-bits litteral utan tecken"
#: config/rs6000/rs6000.c:13688
-#, fuzzy, gcc-internal-format
-#| msgid "argument 2 must be a 5-bit unsigned literal"
+#, gcc-internal-format
msgid "argument 2 must be a 2-bit unsigned literal"
-msgstr "argument 2 måste vara en 5-bitars litteral utan tecken"
+msgstr "argument 2 måste vara en 2-bitars litteral utan tecken"
#: config/rs6000/rs6000.c:13699
-#, fuzzy, gcc-internal-format
-#| msgid "argument 2 must be a 5-bit unsigned literal"
+#, gcc-internal-format
msgid "argument 2 must be a 3-bit unsigned literal"
-msgstr "argument 2 måste vara en 5-bitars litteral utan tecken"
+msgstr "argument 2 måste vara en 3-bitars litteral utan tecken"
#: config/rs6000/rs6000.c:13710
-#, fuzzy, gcc-internal-format
-#| msgid "argument 2 must be a 5-bit unsigned literal"
+#, gcc-internal-format
msgid "argument 2 must be a 4-bit unsigned literal"
-msgstr "argument 2 måste vara en 5-bitars litteral utan tecken"
+msgstr "argument 2 måste vara en 4-bitars litteral utan tecken"
#: config/rs6000/rs6000.c:13724
#, gcc-internal-format
@@ -32592,10 +32543,9 @@ msgid "%qs uses register r29"
msgstr "%qs använder register r29"
#: config/rs6000/rs6000.c:29371
-#, fuzzy, gcc-internal-format
-#| msgid "Stack frame larger than 2G is not supported for -fsplit-stack"
+#, gcc-internal-format
msgid "Stack frame larger than 2G is not supported for %<-fsplit-stack%>"
-msgstr "Stackramar större än 2 G stödjs inte med -fsplit-stack"
+msgstr "Stackramar större än 2 G stödjs inte med %<-fsplit-stack%>"
#: config/rs6000/rs6000.c:30357
#, gcc-internal-format
@@ -32744,10 +32694,9 @@ msgstr "Multiversionering av virtuell funktion stödjs inte"
#. The macro SUBTARGET_OVERRIDE_OPTIONS is provided for subtargets, to
#. get control in TARGET_OPTION_OVERRIDE.
#: config/rs6000/aix61.h:30 config/rs6000/aix71.h:30 config/rs6000/aix72.h:30
-#, fuzzy, gcc-internal-format
-#| msgid "-maix64 requires PowerPC64 architecture remain enabled"
+#, gcc-internal-format
msgid "%<-maix64%> requires PowerPC64 architecture remain enabled"
-msgstr "-maix64 kräver att arkitekturen PowerPC64 fortfarande är aktiverad"
+msgstr "%<-maix64%> kräver att arkitekturen PowerPC64 fortfarande är aktiverad"
#: config/rs6000/aix61.h:36 config/rs6000/aix71.h:36 config/rs6000/aix72.h:36
#, gcc-internal-format
@@ -32755,42 +32704,36 @@ msgid "soft-float and long-double-128 are incompatible"
msgstr "soft-float och long-double-128 är inkompatibla"
#: config/rs6000/aix61.h:40 config/rs6000/aix71.h:40 config/rs6000/aix72.h:40
-#, fuzzy, gcc-internal-format
-#| msgid "-maix64 required: 64-bit computation with 32-bit addressing not yet supported"
+#, gcc-internal-format
msgid "%<-maix64%> required: 64-bit computation with 32-bit addressing not yet supported"
-msgstr "-maix64 krävs: 64-bitsberäkningar med 32-bitars adressering stödjs inte än"
+msgstr "%<-maix64%> krävs: 64-bitsberäkningar med 32-bitars adressering stödjs inte än"
#: config/rs6000/aix61.h:47 config/rs6000/aix71.h:47 config/rs6000/aix72.h:47
#: config/rs6000/freebsd64.h:120 config/rs6000/rtems.h:121
-#, fuzzy, gcc-internal-format
-#| msgid "-mcmodel incompatible with other toc options"
+#, gcc-internal-format
msgid "%<-mcmodel%> incompatible with other toc options"
-msgstr "-mcmodel är inkompatibel med andra toc-flaggor"
+msgstr "%<-mcmodel%> är inkompatibel med andra toc-flaggor"
#: config/rs6000/freebsd64.h:98 config/rs6000/linux64.h:115
-#, fuzzy, gcc-internal-format
-#| msgid "-mcall-aixdesc incompatible with -mabi=elfv2"
+#, gcc-internal-format
msgid "%<-mcall-aixdesc%> incompatible with %<-mabi=elfv2%>"
-msgstr "-mcall-aixdesc är inkompatibel med -mabi=elfv2"
+msgstr "%<-mcall-aixdesc%> är inkompatibel med %<-mabi=elfv2%>"
#: config/rs6000/freebsd64.h:113 config/rs6000/linux64.h:135
#: config/rs6000/rtems.h:114
-#, fuzzy, gcc-internal-format
-#| msgid "-m64 requires a PowerPC64 cpu"
+#, gcc-internal-format
msgid "%<-m64%> requires a PowerPC64 cpu"
-msgstr "-m64 kräver en PowerPC64-CPU"
+msgstr "%<-m64%> kräver en PowerPC64-CPU"
#: config/rs6000/linux64.h:142
-#, fuzzy, gcc-internal-format
-#| msgid "-mcmodel incompatible with other toc options"
+#, gcc-internal-format
msgid "%<-mcmodel incompatible with other toc options%>"
-msgstr "-mcmodel är inkompatibel med andra toc-flaggor"
+msgstr "%<-mcmodel%> är inkompatibel med andra toc-flaggor"
#: config/rs6000/linux64.h:161
-#, fuzzy, gcc-internal-format
-#| msgid "this builtin is not supported for this target"
+#, gcc-internal-format
msgid "%qs unsupported for this ABI"
-msgstr "denna inbyggda stödjs inte på denna målarkitektur"
+msgstr "%qs stödjs inte för detta ABI"
#. The macro SUBTARGET_OVERRIDE_OPTIONS is provided for subtargets, to
#. get control in TARGET_OPTION_OVERRIDE.
@@ -32840,10 +32783,9 @@ msgid "%<-m%s%> not supported in this configuration"
msgstr "%<-m%s%> stödjs inte i denna konfiguration"
#: config/rx/rx.c:651
-#, fuzzy, gcc-internal-format
-#| msgid "unrecognized control register number: %d - using 'psw'"
+#, gcc-internal-format
msgid "unrecognized control register number: %d- using %<psw%>"
-msgstr "okänt styrregisternummer: %d - använder â€pswâ€"
+msgstr "okänt styrregisternummer: %d – använder %<psw%>"
#: config/rx/rx.c:1389
#, gcc-internal-format
@@ -32851,22 +32793,19 @@ msgid "multiple fast interrupt routines seen: %qE and %qE"
msgstr "flera snabba avbrottsrutiner sedda: %qE och %qE"
#: config/rx/rx.c:2596
-#, fuzzy, gcc-internal-format
-#| msgid "__builtin_rx_%s takes 'C', 'Z', 'S', 'O', 'I', or 'U'"
+#, gcc-internal-format
msgid "%<__builtin_rx_%s%> takes %<C%>, %<Z%>, %<S%>, %<O%>, %<I%>, or %<U%>"
-msgstr "__builtin_rx_%s tar â€Câ€, â€Zâ€, â€Sâ€, â€Oâ€, â€I†eller â€Uâ€"
+msgstr "%<__builtin_rx_%s%> tar %<C%>, %<Z%>, %<S%>, %<O%>, %<I%> eller %<U%>"
#: config/rx/rx.c:2599
-#, fuzzy, gcc-internal-format
-#| msgid "use __builtin_rx_mvtc (0, ... ) to write arbitrary values to PSW"
+#, gcc-internal-format
msgid "use %<__builtin_rx_mvtc%> (0, ... ) to write arbitrary values to PSW"
-msgstr "använd __builtin_rx_mvtc (0, ...) för att skriva godtyckliga värden till PSW"
+msgstr "använd %<__builtin_rx_mvtc%> (0, ...) för att skriva godtyckliga värden till PSW"
#: config/rx/rx.c:2646
-#, fuzzy, gcc-internal-format
-#| msgid "-mno-allow-string-insns forbids the generation of the RMPA instruction"
+#, gcc-internal-format
msgid "%<-mno-allow-string-insns%> forbids the generation of the RMPA instruction"
-msgstr "-mno-allow-string-insns förbjuder genereringen av instruktionen RMPA"
+msgstr "%<-mno-allow-string-insns%> förbjuder genereringen av instruktionen RMPA"
#: config/rx/rx.c:2794
#, gcc-internal-format
@@ -32899,10 +32838,9 @@ msgid "builtin %qF is deprecated."
msgstr "inbyggd %qF bör undvikas."
#: config/s390/s390-c.c:898
-#, fuzzy, gcc-internal-format
-#| msgid "%qF requires -mvx"
+#, gcc-internal-format
msgid "%qF requires %<-mvx%>"
-msgstr "%qF behöver -mvx"
+msgstr "%qF behöver %<-mvx%>"
#: config/s390/s390-c.c:904
#, gcc-internal-format
@@ -32940,28 +32878,24 @@ msgid "constant argument %d for builtin %qF is out of range for target type"
msgstr "det konstanta argumentet %d till den inbyggda %qF är utanför intervallet för måltypen"
#: config/s390/s390.c:733
-#, fuzzy, gcc-internal-format
-#| msgid "constant argument %d for builtin %qF is out of range (0.."
+#, gcc-internal-format
msgid "constant argument %d for builtin %qF is out of range (0..%wu)"
-msgstr "det konstanta argumentet %d till den inbyggda %qF ligger utanför intervallet (0.."
+msgstr "det konstanta argumentet %d till den inbyggda %qF ligger utanför intervallet (0..%wu)"
#: config/s390/s390.c:749
-#, fuzzy, gcc-internal-format
-#| msgid "constant argument %d for builtin %qF is out of range (0.."
+#, gcc-internal-format
msgid "constant argument %d for builtin %qF is out of range (%wd..%wd)"
-msgstr "det konstanta argumentet %d till den inbyggda %qF ligger utanför intervallet (0.."
+msgstr "det konstanta argumentet %d till den inbyggda %qF ligger utanför intervallet (%wd..%wd)"
#: config/s390/s390.c:798
-#, fuzzy, gcc-internal-format
-#| msgid "builtin %qF is not supported without -mhtm (default with -march=zEC12 and higher)."
+#, gcc-internal-format
msgid "builtin %qF is not supported without %<-mhtm%> (default with %<-march=zEC12%> and higher)."
-msgstr "inbyggd %qF stödjs inte utan -mhtm (standard med -march=zEC12 och högre)."
+msgstr "inbyggd %qF stödjs inte utan %<-mhtm%> (standard med %<-march=zEC12%> och högre)."
#: config/s390/s390.c:804
-#, fuzzy, gcc-internal-format
-#| msgid "builtin %qF requires -mvx (default with -march=z13 and higher)."
+#, gcc-internal-format
msgid "builtin %qF requires %<-mvx%> (default with %<-march=z13%> and higher)."
-msgstr "inbyggd %qF behöver -mvx (standard med -march=z13 och högre)."
+msgstr "inbyggd %qF behöver %<-mvx%> (standard med %<-march=z13%> och högre)."
#: config/s390/s390.c:811
#, gcc-internal-format
@@ -33020,10 +32954,9 @@ msgid "%qs uses dynamic stack allocation"
msgstr "%qs använder dynamisk stackallokering"
#: config/s390/s390.c:12771
-#, fuzzy, gcc-internal-format
-#| msgid "%<__RTL%> function cannot be compiled with %<-flto%>"
+#, gcc-internal-format
msgid "nested functions cannot be profiled with %<-mfentry%> on s390"
-msgstr "en %<__RTL%>-funktion kan inte kompileras med %<-flto%>"
+msgstr "nästade funktioner kan inte profileras med %<-fentry%> på s390"
#: config/s390/s390.c:15042
#, gcc-internal-format
@@ -33031,10 +32964,9 @@ msgid "64-bit ABI not supported in ESA/390 mode"
msgstr "64-bits ABI stödjs inte i ESA/390-läge"
#: config/s390/s390.c:15049
-#, fuzzy, gcc-internal-format
-#| msgid "thunk-inline is only supported with -mindirect-branch-jump"
+#, gcc-internal-format
msgid "thunk-inline is only supported with %<-mindirect-branch-jump%>"
-msgstr "thunk-inline stödjs endast med -mindirect-branch-jump"
+msgstr "thunk-inline stödjs endast med %<-mindirect-branch-jump%>"
#: config/s390/s390.c:15084
#, gcc-internal-format, gfc-internal-format
@@ -33042,10 +32974,9 @@ msgid "hardware vector support not available on %s"
msgstr "vektorstöd i hårdvara är inte tillgängliga på %s"
#: config/s390/s390.c:15087
-#, fuzzy, gcc-internal-format
-#| msgid "hardware vector support not available with -msoft-float"
+#, gcc-internal-format
msgid "hardware vector support not available with %<-msoft-float%>"
-msgstr "stöd för hårdvaruvektorer är inte tillgängligt med -msoft-float"
+msgstr "stöd för hårdvaruvektorer är inte tillgängligt med %<-msoft-float%>"
#: config/s390/s390.c:15116
#, gcc-internal-format, gfc-internal-format
@@ -33058,16 +32989,14 @@ msgid "hardware decimal floating point instructions not available in ESA/390 mod
msgstr "hårdvaruinstruktioner för decimalflyttal är inte tillgängliga i läget ESA/390"
#: config/s390/s390.c:15132
-#, fuzzy, gcc-internal-format
-#| msgid "-mhard-dfp can%'t be used in conjunction with -msoft-float"
+#, gcc-internal-format
msgid "%<-mhard-dfp%> can%'t be used in conjunction with %<-msoft-float%>"
-msgstr "-mhard-dfp kan inte användas tillsammans med -msoft-float"
+msgstr "%<-mhard-dfp%> kan inte användas tillsammans med %<-msoft-float%>"
#: config/s390/s390.c:15141
-#, fuzzy, gcc-internal-format
-#| msgid "-mbackchain -mpacked-stack -mhard-float are not supported in combination"
+#, gcc-internal-format
msgid "%<-mbackchain%> %<-mpacked-stack%> %<-mhard-float%> are not supported in combination"
-msgstr "-mbackchain -mpacked-stack -mhard-float stödjs inte i kombination"
+msgstr "%<-mbackchain%> %<-mpacked-stack%> %<-mhard-float%> stödjs inte i kombination"
#: config/s390/s390.c:15147
#, gcc-internal-format
@@ -33080,16 +33009,14 @@ msgid "stack size must not be greater than 64k"
msgstr "stackstorlek får inte vara större än 64 k"
#: config/s390/s390.c:15152
-#, fuzzy, gcc-internal-format
-#| msgid "-mstack-guard implies use of -mstack-size"
+#, gcc-internal-format
msgid "%<-mstack-guard%> implies use of %<-mstack-size%>"
-msgstr "-mstack-guard implicerar användning av -mstack-size"
+msgstr "%<-mstack-guard%> implicerar användning av %<-mstack-size%>"
#: config/s390/s390.c:15241
-#, fuzzy, gcc-internal-format
-#| msgid "-mno-mpy supported only for ARC700 or ARCv2"
+#, gcc-internal-format
msgid "%<-mfentry%> is supported only for 64-bit CPUs"
-msgstr "-mno-mpy stödjs endast för ARC700 eller ARCv2"
+msgstr "%<-mfentry%> stödjs endast för 64-bitars CPU:er"
#. argument is not a plain number
#: config/s390/s390.c:15277
@@ -33103,10 +33030,9 @@ msgid "argument to %qs is too large (max. %d)"
msgstr "argumentet till %qs är för stort (max. %d)"
#: config/s390/s390.c:15314
-#, fuzzy, gcc-internal-format
-#| msgid "-mno-pic-data-is-text-relative cannot be used without -fpic/-fPIC"
+#, gcc-internal-format
msgid "%<-mno-pic-data-is-text-relative%> cannot be used without %<-fpic%>/%<-fPIC%>"
-msgstr "-mno-pic-data-is-text-relative kan inte användas utan -fpic/-fPIC"
+msgstr "%<-mno-pic-data-is-text-relative%> kan inte användas utan %<-fpic%>/%<-fPIC%>"
#. Value is not allowed for the target attribute.
#: config/s390/s390.c:15481
@@ -33115,22 +33041,19 @@ msgid "value %qs is not supported by attribute %<target%>"
msgstr "värdet %qs stödjs inte av attributet %<target%>"
#: config/sh/sh.c:936
-#, fuzzy, gcc-internal-format
-#| msgid "ignoring -fschedule-insns because of exception handling bug"
+#, gcc-internal-format
msgid "ignoring %<-fschedule-insns%> because of exception handling bug"
-msgstr "ignorerar -fschedule-insns på grund av ett fel i undantagshanteringen"
+msgstr "ignorerar %<-fschedule-insns%> på grund av ett fel i undantagshanteringen"
#: config/sh/sh.c:953
-#, fuzzy, gcc-internal-format
-#| msgid "unwind tables currently require either a frame pointer or -maccumulate-outgoing-args for correctness"
+#, gcc-internal-format
msgid "unwind tables currently require either a frame pointer or %<-maccumulate-outgoing-args%> for correctness"
-msgstr "utrullningstabeller kräver för närvarande antingen en rampekare eller -maccumulate-outgoing-args för att bli korrekt"
+msgstr "utrullningstabeller kräver för närvarande antingen en rampekare eller %<-maccumulate-outgoing-args%> för att bli korrekt"
#: config/sh/sh.c:7416
-#, fuzzy, gcc-internal-format
-#| msgid "__builtin_saveregs not supported by this subtarget"
+#, gcc-internal-format
msgid "%<__builtin_saveregs%> not supported by this subtarget"
-msgstr "__builtin_saveregs stödjs inte på denna målunderarkitektur"
+msgstr "%<__builtin_saveregs%> stödjs inte på denna målunderarkitektur"
#: config/sh/sh.c:8368
#, gcc-internal-format
@@ -33165,10 +33088,9 @@ msgstr "r0 behöver vara tillgängligt som ett anropsöverskrivet register"
#. The kernel loader cannot handle the relaxation relocations, so it cannot load kernel modules (which are ET_REL) or RTP executables (which are linked with --emit-relocs). No relaxation relocations appear in shared libraries, so relaxation is OK for RTP PIC.
#: config/sh/vxworks.h:43
-#, fuzzy, gcc-internal-format
-#| msgid "-mrelax is only supported for RTP PIC"
+#, gcc-internal-format
msgid "%<-mrelax%> is only supported for RTP PIC"
-msgstr "-mrelax stödjs endast för RTP PIC"
+msgstr "%<-mrelax%> stödjs endast för RTP PIC"
#: config/sparc/sparc.c:1770
#, gcc-internal-format, gfc-internal-format
@@ -33176,22 +33098,19 @@ msgid "%s is not supported by this configuration"
msgstr "%s stödjs inte i denna konfiguration"
#: config/sparc/sparc.c:1777
-#, fuzzy, gcc-internal-format
-#| msgid "-mlong-double-64 not allowed with -m64"
+#, gcc-internal-format
msgid "%<-mlong-double-64%> not allowed with %<-m64%>"
-msgstr "-mlong-double-64 är inte tillåten med -m64"
+msgstr "%<-mlong-double-64%> är inte tillåten med %<-m64%>"
#: config/sparc/sparc.c:1785
-#, fuzzy, gcc-internal-format
-#| msgid "-fcall-saved-REG is not supported for out registers"
+#, gcc-internal-format
msgid "%<-fcall-saved-REG%> is not supported for out registers"
-msgstr "-fcall-saved-REG stödjs inte för utregister"
+msgstr "%<-fcall-saved-REG%> stödjs inte för utregister"
#: config/sparc/sparc.c:1909
-#, fuzzy, gcc-internal-format
-#| msgid "-mcmodel= is not supported on 32-bit systems"
+#, gcc-internal-format
msgid "%<-mcmodel=%> is not supported in 32-bit mode"
-msgstr "-mcmodel= stödjs inte på 32-bitars system"
+msgstr "%<-mcmodel=%> stödjs inte i 32-bitarsläge"
#: config/spu/spu-c.c:133
#, gcc-internal-format, gfc-internal-format
@@ -33209,16 +33128,14 @@ msgid "parameter list does not match a valid signature for %s()"
msgstr "parameterlistan stämmer inte med någon giltig signatur för %s()"
#: config/spu/spu.c:262
-#, fuzzy, gcc-internal-format
-#| msgid "bad value (%qs) for %<-march=%> switch"
+#, gcc-internal-format
msgid "bad value (%s) for %<-march=%> switch"
-msgstr "felaktigt värde (%qs) till flaggan %<-march=%>"
+msgstr "felaktigt värde (%s) till flaggan %<-march=%>"
#: config/spu/spu.c:273
-#, fuzzy, gcc-internal-format
-#| msgid "bad value (%qs) for %<-mtune=%> switch"
+#, gcc-internal-format
msgid "bad value (%s) for %<-mtune=%> switch"
-msgstr "felaktigt värde (%qs) till flaggan %<-mtune=%>"
+msgstr "felaktigt värde (%s) till flaggan %<-mtune=%>"
#: config/spu/spu.c:5200 config/spu/spu.c:5203
#, gcc-internal-format
@@ -33398,10 +33315,9 @@ msgid "too much stack space to prepare: %d"
msgstr "för mycket stackutrymme att förbereda: %d"
#: config/visium/visium.c:731
-#, fuzzy, gcc-internal-format
-#| msgid "an interrupt handler cannot be compiled with -muser-mode"
+#, gcc-internal-format
msgid "an interrupt handler cannot be compiled with %<-muser-mode%>"
-msgstr "en avbrottshanterare kan inte kompileras med -muser-mode"
+msgstr "en avbrottshanterare kan inte kompileras med %<-muser-mode%>"
#: config/vms/vms-c.c:44
#, gcc-internal-format
@@ -33414,40 +33330,34 @@ msgid "junk at end of #pragma __standard"
msgstr "skräp vid slutet av #pragma __standard"
#: config/vms/vms-c.c:81
-#, fuzzy, gcc-internal-format
-#| msgid "malformed '#pragma member_alignment', ignoring"
+#, gcc-internal-format
msgid "malformed %<#pragma member_alignment%>, ignoring"
-msgstr "felformaterat â€#pragma member_alignmentâ€, ignoreras"
+msgstr "felformaterat %<#pragma member_alignment%>, ignoreras"
#: config/vms/vms-c.c:96
-#, fuzzy, gcc-internal-format
-#| msgid "unknown '#pragma member_alignment' name %s"
+#, gcc-internal-format
msgid "unknown %<#pragma member_alignment%> name %s"
-msgstr "okänt â€#pragma member_alignmentâ€-namn %s"
+msgstr "okänt %<#pragma member_alignment%>-namn %s"
#: config/vms/vms-c.c:101
-#, fuzzy, gcc-internal-format
-#| msgid "malformed '#pragma member_alignment'"
+#, gcc-internal-format
msgid "malformed %<#pragma member_alignment%>"
-msgstr "felformaterat â€#pragma member_alignmentâ€"
+msgstr "felformaterat %<#pragma member_alignment%>"
#: config/vms/vms-c.c:135
-#, fuzzy, gcc-internal-format
-#| msgid "unhandled alignment for '#pragma nomember_alignment'"
+#, gcc-internal-format
msgid "unhandled alignment for %<#pragma nomember_alignment%>"
-msgstr "ej hanterad justering för â€#pragma nomember_alignmentâ€"
+msgstr "ej hanterad justering för %<#pragma nomember_alignment%>"
#: config/vms/vms-c.c:148
-#, fuzzy, gcc-internal-format
-#| msgid "garbage at end of '#pragma nomember_alignment'"
+#, gcc-internal-format
msgid "garbage at end of %<#pragma nomember_alignment%>"
-msgstr "skräp vid slutet av â€#pragma nomember_alignmentâ€"
+msgstr "skräp vid slutet av %<#pragma nomember_alignment%>"
#: config/vms/vms-c.c:203
-#, fuzzy, gcc-internal-format
-#| msgid "malformed '#pragma extern_model', ignoring"
+#, gcc-internal-format
msgid "malformed %<#pragma extern_model%>, ignoring"
-msgstr "felformaterat â€#pragma extern_modelâ€, ignoreras"
+msgstr "felformaterat %<#pragma extern_model%>, ignoreras"
# Detta är ordagrannt argumenten till ett pragma.
#: config/vms/vms-c.c:224
@@ -33456,10 +33366,9 @@ msgid "extern model globalvalue"
msgstr "extern model globalvalue"
#: config/vms/vms-c.c:229
-#, fuzzy, gcc-internal-format
-#| msgid "unknown '#pragma extern_model' model '%s'"
+#, gcc-internal-format
msgid "unknown %<#pragma extern_model%> model %qs"
-msgstr "okänd â€#pragma extern_modelâ€-modell â€%sâ€"
+msgstr "okänd %<#pragma extern_model%>-modell %qs"
#: config/vms/vms-c.c:235
#, gcc-internal-format
@@ -33492,10 +33401,9 @@ msgid "boolean registers required for the floating-point option"
msgstr "booleska register krävs för flyttalsalternativet"
#: config/xtensa/xtensa.c:2259
-#, fuzzy, gcc-internal-format
-#| msgid "-f%s is not supported with CONST16 instructions"
+#, gcc-internal-format
msgid "%<-f%s%> is not supported with CONST16 instructions"
-msgstr "-f%s stödjs inte med CONST16-instruktioner"
+msgstr "%<-f%s%> stödjs inte med CONST16-instruktioner"
#: config/xtensa/xtensa.c:2266
#, gcc-internal-format
@@ -33514,10 +33422,9 @@ msgid "%<-gnat%> misspelled as %<-gant%>"
msgstr "%<-gnat%> felstavat som %<-gant%>"
#: ada/gcc-interface/misc.c:259
-#, fuzzy, gcc-internal-format
-#| msgid "-fexcess-precision=standard for Ada"
+#, gcc-internal-format
msgid "%<-fexcess-precision=standard%> for Ada"
-msgstr "-fexcess-precision=standard för Ada"
+msgstr "%<-fexcess-precision=standard%> för Ada"
#: ada/gcc-interface/misc.c:278
#, gcc-internal-format
@@ -33729,28 +33636,24 @@ msgid "redeclaration of enumerator %q+D"
msgstr "omdeklaration av uppräkningstyp %q+D"
#: c/c-decl.c:1980
-#, fuzzy, gcc-internal-format
-#| msgid "conflicting types for built-in function %q+D"
+#, gcc-internal-format
msgid "conflicting types for built-in function %q+D; expected %qT"
-msgstr "motstridiga typer på inbyggd funktion %q+D"
+msgstr "motstridiga typer på inbyggd funktion %q+D; %qT förväntades"
#: c/c-decl.c:1990
-#, fuzzy, gcc-internal-format
-#| msgid "%qD was declared here"
+#, gcc-internal-format
msgid "%qD is declared in header %qs"
-msgstr "%qD deklarerades här"
+msgstr "%qD deklarerades i huvudet %qs"
#: c/c-decl.c:2002
-#, fuzzy, gcc-internal-format
-#| msgid "invalid argument to built-in function %s"
+#, gcc-internal-format
msgid "mismatch in argument %u type of built-in function %qD; expected %qT"
-msgstr "ogiltigt argument till den inbyggda funktionen %s"
+msgstr "typen på argument %u till den inbyggda funktionen %qD stämmer inte; %qT förväntades"
#: c/c-decl.c:2007
-#, fuzzy, gcc-internal-format
-#| msgid "conflicting types for built-in function %q+D"
+#, gcc-internal-format
msgid "mismatch in return type of built-in function %qD; expected %qT"
-msgstr "motstridiga typer på inbyggd funktion %q+D"
+msgstr "returtypen på den inbyggda funktionen %qD stämmer inte; %qT förväntades"
#: c/c-decl.c:2032 c/c-decl.c:2045 c/c-decl.c:2081
#, gcc-internal-format
@@ -33793,16 +33696,14 @@ msgid "redefinition of typedef %q+D"
msgstr "omdefinition av typedef %q+D"
#: c/c-decl.c:2149
-#, fuzzy, gcc-internal-format
-#| msgid "declaration of %q+D shadows a built-in function"
+#, gcc-internal-format
msgid "declaration of %qD shadows a built-in function"
-msgstr "deklaration av %q+D skuggar en inbyggd funktion"
+msgstr "deklaration av %qD skuggar en inbyggd funktion"
#: c/c-decl.c:2165
-#, fuzzy, gcc-internal-format
-#| msgid "declaration of function %qD in invalid context"
+#, gcc-internal-format
msgid "declaration of built-in function %qD without a prototype; expected %qT"
-msgstr "deklaration av funktionen %qD i ogiltig kontext"
+msgstr "deklaration av den inbyggda funktionen %qD utan en prototyp; %qT förväntades"
#: c/c-decl.c:2192 c/c-decl.c:2303
#, gcc-internal-format
@@ -35109,16 +35010,14 @@ msgid "%<for%> loop initial declarations are only allowed in C99 or C11 mode"
msgstr "%<for%>-slinga med startdeklaration är endast tillåtet i C99- och C11-läge"
#: c/c-decl.c:9809
-#, fuzzy, gcc-internal-format
-#| msgid "use option -std=c99, -std=gnu99, -std=c11 or -std=gnu11 to compile your code"
+#, gcc-internal-format
msgid "use option %<-std=c99%>, %<-std=gnu99%>, %<-std=c11%> or %<-std=gnu11%> to compile your code"
-msgstr "använd flaggan -std=c99, -std=gnu99, -std=c11 eller -std=gnu11 för att kompilera din kod"
+msgstr "använd flaggan %<-std=c99%>, %<-std=gnu99%>, %<-std=c11%> eller %<-std=gnu11%> för att kompilera din kod"
#: c/c-decl.c:9816
-#, fuzzy, gcc-internal-format
-#| msgid "ISO C90 does not support %<[*]%> array declarators"
+#, gcc-internal-format
msgid "ISO C90 does not support %<for%> loop initial declarations"
-msgstr "ISO C90 stödjer inte %<[*]%>-vektordeklarerare"
+msgstr "ISO C90 stödjer inte %<for%>-slingor med initiala deklarationer"
#: c/c-decl.c:9848
#, gcc-internal-format
@@ -35514,10 +35413,9 @@ msgid "expected string literal"
msgstr "strängkonstant förväntades"
#: c/c-parser.c:2473
-#, fuzzy, gcc-internal-format
-#| msgid "ISO C99 does not support %<_Static_assert%>"
+#, gcc-internal-format
msgid "ISO C11 does not support omitting the string in %<_Static_assert%>"
-msgstr "ISO C99 stödjer inte %<_Static_assert%>"
+msgstr "ISO C11 stödjer inte att utesluta strängen i %<_Static_assert%>"
#: c/c-parser.c:2479
#, gcc-internal-format
@@ -35565,10 +35463,9 @@ msgid "%<_Atomic%> applied to a qualified type"
msgstr "%<_Atomic%> tillämpat på en kvalificerad typ"
#: c/c-parser.c:2883
-#, fuzzy, gcc-internal-format
-#| msgid "%<__GIMPLE%> only valid with -fgimple"
+#, gcc-internal-format
msgid "%<__GIMPLE%> only valid with %<-fgimple%>"
-msgstr "%<__GIMPLE%> är endast giltigt med -fgimple"
+msgstr "%<__GIMPLE%> är endast giltigt med %<-fgimple%>"
#: c/c-parser.c:2981
#, gcc-internal-format
@@ -35806,23 +35703,20 @@ msgid "missing collection in fast enumeration"
msgstr "saknad samling i snabb uppräkning"
#: c/c-parser.c:6386 c/c-parser.c:6397 c/c-parser.c:6408
-#, fuzzy, gcc-internal-format
-#| msgid "duplicate cv-qualifier"
+#, gcc-internal-format
msgid "duplicate asm qualifier %qE"
-msgstr "upprepade cv-kvalificerare"
+msgstr "upprepade asm-kvalificerare %qE"
#: c/c-parser.c:6387 c/c-parser.c:6398 c/c-parser.c:6409 cp/parser.c:19841
#: cp/parser.c:19857 cp/parser.c:19870
-#, fuzzy, gcc-internal-format
-#| msgid "it was later defined here"
+#, gcc-internal-format
msgid "first seen here"
-msgstr "det definierades senare här"
+msgstr "först sedd här"
#: c/c-parser.c:6418
-#, fuzzy, gcc-internal-format
-#| msgid "%qE is not a class template"
+#, gcc-internal-format
msgid "%qE is not an asm qualifier"
-msgstr "%qE är inte en klassmall"
+msgstr "%qE är inte en asm-kvalificerare"
#: c/c-parser.c:6461
#, gcc-internal-format
@@ -36153,10 +36047,9 @@ msgid "using integer absolute value function %qD when argument is of complex typ
msgstr "använder absolutvärdesfunktionen %qD för heltal när argumentet är av den komplexa typen %qT"
#: c/c-parser.c:9417
-#, fuzzy, gcc-internal-format
-#| msgid "using %qs with unsigned type has no effect"
+#, gcc-internal-format
msgid "taking the absolute value of unsigned type %qT has no effect"
-msgstr "att använda %qs med en teckenlös typ har ingen effekt"
+msgstr "att ta absolutvärdet av en teckenlös typ %qT har ingen effekt"
#: c/c-parser.c:9428
#, gcc-internal-format
@@ -36314,10 +36207,9 @@ msgid "expression must be integral"
msgstr "uttrycket måste vara ett heltal"
#: c/c-parser.c:12119 c/c-parser.c:12131
-#, fuzzy, gcc-internal-format
-#| msgid "expected %<,%> or %<)%>"
+#, gcc-internal-format
msgid "expected %<)%> or %<,%>"
-msgstr "%<,%> eller %<)%> förväntades"
+msgstr "%<)%> eller %<,%> förväntades"
#: c/c-parser.c:12266 c/c-parser.c:19586
#, gcc-internal-format
@@ -36403,34 +36295,29 @@ msgid "%<priority%> value must be non-negative"
msgstr "%<priority%>-värdet måste vara positivt"
#: c/c-parser.c:12890
-#, fuzzy, gcc-internal-format
-#| msgid "expected integer expression"
+#, gcc-internal-format
msgid "expected constant integer expression"
-msgstr "heltalsuttryck förväntades"
+msgstr "konstant heltalsuttryck förväntades"
#: c/c-parser.c:12929 cp/parser.c:33541
-#, fuzzy, gcc-internal-format
-#| msgid "expected %<data%>, %<update%>, %<enter%> or %<exit%>"
+#, gcc-internal-format
msgid "expected %<alloc%>, %<to%>, %<from%>, %<tofrom%>, %<firstprivate%>, %<none%> or %<default%>"
-msgstr "%<data%>, %<update%>, %<enter%> eller %<exit%> förväntades"
+msgstr "%<alloc%>, %<to%>, %<from%>, %<tofrom%>, %<firstprivate%>, %<none%> eller %<default%> förväntades"
#: c/c-parser.c:12990 cp/parser.c:33606
-#, fuzzy, gcc-internal-format
-#| msgid "expected %<class%>, %<typename%>, or %<template%>"
+#, gcc-internal-format
msgid "expected %<scalar%>, %<aggregate%> or %<pointer%>"
-msgstr "%<class%>, %<typename%> eller %<template%> förväntades"
+msgstr "%<scalar%>, %<aggregate%> eller %<pointer%> förväntades"
#: c/c-parser.c:13056 cp/parser.c:33675
-#, fuzzy, gcc-internal-format
-#| msgid "too many %<if%> clauses with %qs modifier"
+#, gcc-internal-format
msgid "too many %<defaultmap%> clauses with %qs category"
-msgstr "för många %<if%>-klausuler med %qs-modifierare"
+msgstr "för många %<defaultmap%>-klausuler med %qs-modifierare"
#: c/c-parser.c:13059 cp/parser.c:33678
-#, fuzzy, gcc-internal-format
-#| msgid "too many %<if%> clauses with %qs modifier"
+#, gcc-internal-format
msgid "too many %<defaultmap%> clauses with unspecified category"
-msgstr "för många %<if%>-klausuler med %qs-modifierare"
+msgstr "för många %<defaultmap%>-klausuler med ospecificerad kategori"
#: c/c-parser.c:13123 cp/semantics.c:6633
#, gcc-internal-format
@@ -36463,10 +36350,9 @@ msgid "ordered argument needs positive constant integer expression"
msgstr "ordered-argument behöver ett positivt konstant heltalsuttryck"
#: c/c-parser.c:13545 cp/parser.c:33796
-#, fuzzy, gcc-internal-format
-#| msgid "%<_Atomic%> %qE in %<reduction%> clause"
+#, gcc-internal-format
msgid "%<inscan%> modifier on %<reduction%> clause not supported yet"
-msgstr "%<_Atomic%> %qE i %<reduction%>-klausul"
+msgstr "en %<inscan%>-modifierare på en %<reduction%>-klausul stödjs inte ännu"
#: c/c-parser.c:13601 c/c-parser.c:18869 cp/parser.c:39608
#, gcc-internal-format
@@ -36529,10 +36415,9 @@ msgid "%<simdlen%> clause expression must be positive constant integer expressio
msgstr "%<simdlen%>-klausulens uttryck måste vara ett positivt konstant heltalsuttryck"
#: c/c-parser.c:14438 cp/parser.c:34668
-#, fuzzy, gcc-internal-format
-#| msgid "%qs feature modifier is incompatible with %s %s"
+#, gcc-internal-format
msgid "%<iterator%> modifier incompatible with %qs"
-msgstr "funktionsmodifieraren %qs är inkompatibel med %s %s"
+msgstr "modifieraren %<iterator%> är inkompatibel med %qs"
#: c/c-parser.c:14485 cp/parser.c:34716 cp/parser.c:34943
#, gcc-internal-format
@@ -36665,40 +36550,34 @@ msgid "%<#pragma acc update%> must contain at least one %<device%> or %<host%> o
msgstr "%<#pragma acc update%> måste innehålla åtminstone en %<device%>- eller %<host%>- eller %<self%>-klausul"
#: c/c-parser.c:16071 cp/parser.c:35668
-#, fuzzy, gcc-internal-format
-#| msgid "expected %<+%>, %<*%>, %<-%>, %<&%>, %<^%>, %<|%>, %<&&%>, %<||%> or identifier"
+#, gcc-internal-format
msgid "expected %<read%>, %<write%>, %<update%>, %<capture%>, %<seq_cst%>, %<acq_rel%>, %<release%>, %<relaxed%> or %<hint%> clause"
-msgstr "%<+%>, %<*%>, %<-%>, %<&%>, %<^%>, %<|%>, %<&&%>, %<||%> eller identifierare förväntades"
+msgstr "%<read%>-, %<write%>-, %<update%>-, %<capture%>-, %<seq_cst%>-, %<acq_rel%>-, %<release%>-, %<relaxed%>- eller %<hint%>-klausul förväntades"
#: c/c-parser.c:16080 cp/parser.c:35677
-#, fuzzy, gcc-internal-format
-#| msgid "too many %qs clauses"
+#, gcc-internal-format
msgid "too many atomic clauses"
-msgstr "för många %qs-klausuler"
+msgstr "för många atomära klausuler"
#: c/c-parser.c:16087 cp/parser.c:35684
-#, fuzzy, gcc-internal-format
-#| msgid "too many %qs clauses"
+#, gcc-internal-format
msgid "too many memory order clauses"
-msgstr "för många %qs-klausuler"
+msgstr "för många ordningsklausuler"
#: c/c-parser.c:16142 cp/parser.c:35739
-#, fuzzy, gcc-internal-format
-#| msgid "%<#pragma omp target update%> must contain at least one %<from%> or %<to%> clauses"
+#, gcc-internal-format
msgid "%<#pragma omp atomic read%> incompatible with %<acq_rel%> or %<release%> clauses"
-msgstr "%<#pragma omp target update%> måste innehålla åtminstone en %<from%>- eller %<to%>-klausul"
+msgstr "%<#pragma omp atomic read%> är inkompatibel med en %<acq_rel%>- eller %<release%>-klausul"
#: c/c-parser.c:16151 cp/parser.c:35748
-#, fuzzy, gcc-internal-format
-#| msgid "%<#pragma omp target update%> must contain at least one %<from%> or %<to%> clauses"
+#, gcc-internal-format
msgid "%<#pragma omp atomic write%> incompatible with %<acq_rel%> or %<acquire%> clauses"
-msgstr "%<#pragma omp target update%> måste innehålla åtminstone en %<from%>- eller %<to%>-klausul"
+msgstr "%<#pragma omp atomic write%> är inkompatibel med en %<acq_rel%>- eller %<acquire%>-klausul"
#: c/c-parser.c:16160 cp/parser.c:35757
-#, fuzzy, gcc-internal-format
-#| msgid "%<#pragma omp target update%> must contain at least one %<from%> or %<to%> clauses"
+#, gcc-internal-format
msgid "%<#pragma omp atomic update%> incompatible with %<acq_rel%> or %<acquire%> clauses"
-msgstr "%<#pragma omp target update%> måste innehålla åtminstone en %<from%>- eller %<to%>-klausul"
+msgstr "%<#pragma omp atomic update%> är inkompatibel med en %<acq_rel%>- eller %<acquire%>-klausul"
#: c/c-parser.c:16426 cp/parser.c:35962 cp/parser.c:35988
#, gcc-internal-format
@@ -36721,34 +36600,29 @@ msgid "expected %<(%> or end of line"
msgstr "%<(%> eller filslut förväntades"
#: c/c-parser.c:16588 cp/semantics.c:9035
-#, fuzzy, gcc-internal-format
-#| msgid "expression %qE is not a constant expression"
+#, gcc-internal-format
msgid "%<depobj%> expression is not lvalue expression"
-msgstr "uttrycket %qE är inte ett konstant uttryck"
+msgstr "uttrycket %<depobj%> är inte ett l-värde-uttryck"
#: c/c-parser.c:16645 cp/parser.c:36220
-#, fuzzy, gcc-internal-format
-#| msgid "expected %<data%>, %<update%>, %<enter%> or %<exit%>"
+#, gcc-internal-format
msgid "expected %<in%>, %<out%>, %<inout%> or %<mutexinoutset%>"
-msgstr "%<data%>, %<update%>, %<enter%> eller %<exit%> förväntades"
+msgstr "%<in%>, %<out%>, %<inout%> eller %<mutexinoutset%> förväntades"
#: c/c-parser.c:16657 cp/parser.c:36236
-#, fuzzy, gcc-internal-format
-#| msgid "expected %<;%>, %<,%> or %<)%>"
+#, gcc-internal-format
msgid "expected %<depend%>, %<destroy%> or %<update%> clause"
-msgstr "%<;%>, %<,%> eller %<)%> förväntades"
+msgstr "%<depend%>-, %<destroy%>- eller %<update%>-klausul förväntades"
#: c/c-parser.c:16693 cp/parser.c:36269
-#, fuzzy, gcc-internal-format
-#| msgid "expected %<class%>, %<typename%>, or %<template%>"
+#, gcc-internal-format
msgid "expected %<acq_rel%>, %<release%> or %<acquire%>"
-msgstr "%<class%>, %<typename%> eller %<template%> förväntades"
+msgstr "%<acq_rel%>, %<release%> eller %<acquire%> förväntades"
#: c/c-parser.c:16700 cp/parser.c:36276
-#, fuzzy, gcc-internal-format
-#| msgid "%<nonmonotonic%> schedule modifier specified together with %<ordered%> clause"
+#, gcc-internal-format
msgid "%<flush%> list specified together with memory order clause"
-msgstr "%<nonmonotonic%>-schemaläggningsmodifierare angiven tillsammans med %<ordered%>-klausul"
+msgstr "%<flush%>-lista specificerat tillsammans med minnesordningsklausul"
#: c/c-parser.c:16749 cp/parser.c:36876
#, gcc-internal-format
@@ -36811,10 +36685,9 @@ msgid "%<#pragma omp target data%> with map-type other than %<to%>, %<from%>, %<
msgstr "%<#pragma omp target data%> med en annan map-typ än %<to%>, %<from%>, %<tofrom%> eller %<alloc%> på %<map%>-klausul"
#: c/c-parser.c:18045 cp/parser.c:38220
-#, fuzzy, gcc-internal-format
-#| msgid "%<#pragma omp target data%> must contain at least one %<map%> clause"
+#, gcc-internal-format
msgid "%<#pragma omp target data%> must contain at least one %<map%> or %<use_device_ptr%> clause"
-msgstr "%<#pragma omp target data%> måste innehålla åtminstone en %<map%>-klausul"
+msgstr "%<#pragma omp target data%> måste innehålla åtminstone en %<map%>- eller %<use_device_ptr%>-klausul"
#: c/c-parser.c:18092 cp/parser.c:38445
#, gcc-internal-format
@@ -36947,10 +36820,9 @@ msgid "expected %<simd%> or %<reduction%> or %<target%>"
msgstr "%<simd%> eller %<reduction%> eller %<target%> förväntades"
#: c/c-parser.c:19255 cp/parser.c:39896
-#, fuzzy, gcc-internal-format
-#| msgid "expected %<class%>, %<typename%>, or %<template%>"
+#, gcc-internal-format
msgid "expected %<seq_cst%>, %<relaxed%> or %<acq_rel%>"
-msgstr "%<class%>, %<typename%> eller %<template%> förväntades"
+msgstr "%<seq_cst%>, %<relaxed%> eller %<acq_rel%> förväntades"
#: c/c-parser.c:19275 cp/parser.c:39922
#, gcc-internal-format
@@ -36958,10 +36830,9 @@ msgid "expected %<unified_address%>, %<unified_shared_memory%>, %<dynamic_alloca
msgstr "en klausul %<unified_address%>, %<unified_shared_memory%>, %<dynamic_allocators%>, %<reverse_offload%> eller %<atomic_default_mem_order%> förväntades"
#: c/c-parser.c:19284 cp/parser.c:39931
-#, fuzzy, gcc-internal-format
-#| msgid "strong using directive no longer supported"
+#, gcc-internal-format
msgid "%qs clause on %<requires%> directive not supported yet"
-msgstr "direktivet strong using stödjs inte längre"
+msgstr "klausulen %qs på direktivet %<requires%> stödjs inte ännu"
#: c/c-parser.c:19296 cp/parser.c:39943
#, gcc-internal-format
@@ -36979,22 +36850,19 @@ msgid "%<atomic_default_mem_order%> clause used lexically after first %<atomic%>
msgstr "klausulen %<atomic_default_mem_order%> använd lexikalt efter första konsstruktionen %<atomic%> utan minnesordningsklausul"
#: c/c-parser.c:19331 cp/parser.c:39978
-#, fuzzy, gcc-internal-format
-#| msgid "%<#pragma omp target data%> must contain at least one %<map%> clause"
+#, gcc-internal-format
msgid "%<pragma omp requires%> requires at least one clause"
-msgstr "%<#pragma omp target data%> måste innehålla åtminstone en %<map%>-klausul"
+msgstr "%<pragma omp requires%> kräver åtminstone en klausul"
#: c/c-parser.c:19350
-#, fuzzy, gcc-internal-format
-#| msgid "%<_Atomic%> %qE in %<reduction%> clause"
+#, gcc-internal-format
msgid "zero sized type %qT in %<reduction%> clause"
-msgstr "%<_Atomic%> %qE i %<reduction%>-klausul"
+msgstr "nollstor typ %qT i %<reduction%>-klausul"
#: c/c-parser.c:19356
-#, fuzzy, gcc-internal-format
-#| msgid "variable length element type in array %<reduction%> clause"
+#, gcc-internal-format
msgid "variable sized type %qT in %<reduction%> clause"
-msgstr "elementtyp med variabel längd i vektor-%<reduction%>-klausul"
+msgstr "typen %qT med variabel storlek i-%<reduction%>-klausul"
#: c/c-parser.c:19588 cp/semantics.c:8025
#, gcc-internal-format
@@ -37291,10 +37159,9 @@ msgid "too many arguments to method %qE"
msgstr "för många argument till metoden %qE"
#: c/c-typeck.c:3513
-#, fuzzy, gcc-internal-format
-#| msgid "too many arguments to function %qE"
+#, gcc-internal-format
msgid "too many arguments to built-in function %qE expecting %d"
-msgstr "för många argument till funktionen %qE"
+msgstr "för många argument till den inbyggda funktionen %qE, %d förväntades"
#: c/c-typeck.c:3585
#, gcc-internal-format
@@ -37302,10 +37169,9 @@ msgid "implicit conversion from %qT to %qT when passing argument to function"
msgstr "implicit konvertering från %qT till %qT när argument skickas till en funktion"
#: c/c-typeck.c:3653
-#, fuzzy, gcc-internal-format
-#| msgid "too few arguments to function %qE"
+#, gcc-internal-format
msgid "too few arguments to built-in function %qE expecting %u"
-msgstr "för få argument till funktionen %qE"
+msgstr "för få argument till den inbyggda funktionen %qE, %u förväntades"
#: c/c-typeck.c:3828 c/c-typeck.c:3856 cp/typeck.c:4905 cp/typeck.c:5166
#, gcc-internal-format
@@ -37363,10 +37229,9 @@ msgid "ISO C does not support %<~%> for complex conjugation"
msgstr "ISO C stödjer inte %<~%> för komplex konjugering"
#: c/c-typeck.c:4434
-#, fuzzy, gcc-internal-format
-#| msgid "wrong type argument to abs"
+#, gcc-internal-format
msgid "wrong type argument to absu"
-msgstr "fel typ på argument till abs"
+msgstr "fel typ på argument till absu"
#: c/c-typeck.c:4459
#, gcc-internal-format
@@ -37494,10 +37359,9 @@ msgid "ISO C forbids conditional expr between %<void *%> and function pointer"
msgstr "ISO C förbjuder villkorliga uttryck mellan %<void *%> och funktionspekare"
#: c/c-typeck.c:5342
-#, fuzzy, gcc-internal-format
-#| msgid "pointer type mismatch in conditional expression"
+#, gcc-internal-format
msgid "pointer type mismatch between %qT and %qT of %qD and %qD in conditional expression"
-msgstr "pekartyper stämmer inte i villkorsuttryck"
+msgstr "pekartyper stämmer inte mellan %qT och %qT hos %qD och %qD i villkorsuttryck"
#: c/c-typeck.c:5347
#, gcc-internal-format
@@ -37648,10 +37512,9 @@ msgid "%qD argument %d promotes to %qT where %qT is expected in a call to built-
msgstr "argument %2$d till %1$qD befordras till %3$qT där %4$qT förväntas i ett anrop till den inbyggda funktionen som deklarerats utan prototyp"
#: c/c-typeck.c:6503
-#, fuzzy, gcc-internal-format
-#| msgid "routine %qD declared here"
+#, gcc-internal-format
msgid "built-in %qD declared here"
-msgstr "rutinen %qD är deklarerad här"
+msgstr "den inbyggda %qD är deklarerad här"
#: c/c-typeck.c:6702
#, gcc-internal-format
@@ -37801,10 +37664,9 @@ msgid "passing argument %d of %qE from incompatible pointer type"
msgstr "skickar argument %d till %qE från inkompatibel pekartyp"
#: c/c-typeck.c:7251
-#, fuzzy, gcc-internal-format
-#| msgid "assignment to %qT from incompatible pointer type %qT"
+#, gcc-internal-format
msgid "assignment to %qT from pointer to %qD with incompatible type %qT"
-msgstr "tilldelning till %qT från inkompatibel pekartyp %qT"
+msgstr "tilldelning till %qT från pekare till %qD med inkompatibel typ %qT"
#: c/c-typeck.c:7256
#, gcc-internal-format
@@ -37812,10 +37674,9 @@ msgid "assignment to %qT from incompatible pointer type %qT"
msgstr "tilldelning till %qT från inkompatibel pekartyp %qT"
#: c/c-typeck.c:7262
-#, fuzzy, gcc-internal-format
-#| msgid "initialization of %qT from incompatible pointer type %qT"
+#, gcc-internal-format
msgid "initialization of %qT from pointer to %qD with incompatible type %qT"
-msgstr "initiering av %qT från inkompatibel pekartyp %qT"
+msgstr "initiering av %qT från pekare til %qD inkompatibel typ %qT"
#: c/c-typeck.c:7267
#, gcc-internal-format
@@ -37823,10 +37684,9 @@ msgid "initialization of %qT from incompatible pointer type %qT"
msgstr "initiering av %qT från inkompatibel pekartyp %qT"
#: c/c-typeck.c:7274
-#, fuzzy, gcc-internal-format
-#| msgid "returning %qT from a function with incompatible return type %qT"
+#, gcc-internal-format
msgid "returning pointer to %qD of type %qT from a function with incompatible type %qT"
-msgstr "returnerar %qT från en funktion med inkompatibel returtyp %qT"
+msgstr "returnerar pekaer till %qD av typen %qT från en funktion med inkompatibel typ %qT"
#: c/c-typeck.c:7279
#, gcc-internal-format
@@ -37904,10 +37764,9 @@ msgid "initialization of a flexible array member"
msgstr "initiering av medlem som är en flexibel vektor"
#: c/c-typeck.c:7749 cp/typeck2.c:1128
-#, fuzzy, gcc-internal-format
-#| msgid "initialization of %qT from incompatible pointer type %qT"
+#, gcc-internal-format
msgid "cannot initialize array of %qT from a string literal with type array of %qT"
-msgstr "initiering av %qT från inkompatibel pekartyp %qT"
+msgstr "det går inte att initiera vektorn av %qT från en strängliteral med typvektor %qT"
#: c/c-typeck.c:7789
#, gcc-internal-format
@@ -38278,10 +38137,9 @@ msgstr "%<#pragma omp cancel%> måste ange en av klausulerna %<parallel%>, %<for
#: c/c-typeck.c:12758 c/c-typeck.c:12768 cp/semantics.c:9122
#: cp/semantics.c:9132
-#, fuzzy, gcc-internal-format
-#| msgid "expected %<parallel%> or %<target%> %<if%> clause modifier"
+#, gcc-internal-format
msgid "expected %<cancel%> %<if%> clause modifier"
-msgstr "%<parallel%>- eller %<target%>-modifierare av %<if%>-klausul förväntades"
+msgstr "%<cancel%> %<if%>-klausulmodifierare förväntades"
#: c/c-typeck.c:12803 cp/semantics.c:9168
#, gcc-internal-format
@@ -38391,28 +38249,24 @@ msgid "%qE does not have pointer or array type"
msgstr "%qE har inte pekar- eller vektortyp"
#: c/c-typeck.c:13526 cp/semantics.c:6012
-#, fuzzy, gcc-internal-format
-#| msgid "throwing NULL, which has integral, not pointer type"
+#, gcc-internal-format
msgid "iterator %qD has neither integral nor pointer type"
-msgstr "kastar NULL, som har heltals-, inte pekartyp"
+msgstr "iteratorn %qD har varken heltals- eller pekartyp"
#: c/c-typeck.c:13533
-#, fuzzy, gcc-internal-format
-#| msgid "%<_Atomic%>-qualified array type"
+#, gcc-internal-format
msgid "iterator %qD has %<_Atomic%> qualified type"
-msgstr "%<_Atomic%>-kvalificerad vektortyp"
+msgstr "iteratorn %qD har %<_Atomic%>-kvalificerad typ"
#: c/c-typeck.c:13539 cp/semantics.c:6019
-#, fuzzy, gcc-internal-format
-#| msgid "parameter %qD has incomplete type"
+#, gcc-internal-format
msgid "iterator %qD has const qualified type"
-msgstr "parametern %qD har ofullständig typ"
+msgstr "iteratorn %qD har const-kvalificerad typ"
#: c/c-typeck.c:13552 cp/semantics.c:6035
-#, fuzzy, gcc-internal-format
-#| msgid "bit-field %qD with non-integral type"
+#, gcc-internal-format
msgid "iterator step with non-integral type"
-msgstr "bitfält %qD med en icke-heltalstyp"
+msgstr "iteratorsteg med en icke-heltalstyp"
#: c/c-typeck.c:13572 cp/semantics.c:6068
#, gcc-internal-format
@@ -38425,22 +38279,19 @@ msgid "type of iterator %qD refers to outer iterator %qD"
msgstr "typ av iteratorn %qD refererar till den yttre iteratorn %qD"
#: c/c-typeck.c:13606 cp/semantics.c:6102
-#, fuzzy, gcc-internal-format
-#| msgid "condition expression refers to iteration variable %qD"
+#, gcc-internal-format
msgid "begin expression refers to outer iterator %qD"
-msgstr "villkorsuttrycket refererar till iterationsvariabeln %qD"
+msgstr "startuttrycket refererar till den yttre iteratiorn %qD"
#: c/c-typeck.c:13612 cp/semantics.c:6108
-#, fuzzy, gcc-internal-format
-#| msgid "condition expression refers to iteration variable %qD"
+#, gcc-internal-format
msgid "end expression refers to outer iterator %qD"
-msgstr "villkorsuttrycket refererar till iterationsvariabeln %qD"
+msgstr "slututtrycket refererar till den yttre iteratiorn %qD"
#: c/c-typeck.c:13618 cp/semantics.c:6114
-#, fuzzy, gcc-internal-format
-#| msgid "initializer expression refers to iteration variable %qD"
+#, gcc-internal-format
msgid "step expression refers to outer iterator %qD"
-msgstr "initieraruttrycket refererar till iterationsvariabeln %qD"
+msgstr "steguttrycket refererar till den yttre iteratiorn %qD"
#: c/c-typeck.c:13730 c/c-typeck.c:13740
#, gcc-internal-format
@@ -38453,16 +38304,14 @@ msgid "%<_Atomic%> %qE in %<reduction%> clause"
msgstr "%<_Atomic%> %qE i %<reduction%>-klausul"
#: c/c-typeck.c:13770
-#, fuzzy, gcc-internal-format
-#| msgid "bit-field %qE in %qs clause"
+#, gcc-internal-format
msgid "zero sized type %qT in %qs clause"
-msgstr "bitfältet %qE i %qs-klausul"
+msgstr "nollstor typ %qT i %qs-klausul"
#: c/c-typeck.c:13778
-#, fuzzy, gcc-internal-format
-#| msgid "bit-field %qE in %qs clause"
+#, gcc-internal-format
msgid "variable sized type %qT in %qs clause"
-msgstr "bitfältet %qE i %qs-klausul"
+msgstr "typen %qT med variabel storlek i %qs-klausul"
#: c/c-typeck.c:13828
#, gcc-internal-format
@@ -38573,16 +38422,14 @@ msgid "%qE appears more than once in %<aligned%> clauses"
msgstr "%qE förekommer mer än en gång i %<aligned%>-klausuler"
#: c/c-typeck.c:14165 cp/semantics.c:6936
-#, fuzzy, gcc-internal-format
-#| msgid "%qE is not a variable in %<depend%> clause"
+#, gcc-internal-format
msgid "%qE is not a variable in %<nontemporal%> clause"
-msgstr "%qE är inte en variabel i en %<depend%>-klausul"
+msgstr "%qE är inte en variabel i en %<nontemporal%>-klausul"
#: c/c-typeck.c:14171
-#, fuzzy, gcc-internal-format
-#| msgid "%qE appears more than once in %<aligned%> clauses"
+#, gcc-internal-format
msgid "%qE appears more than once in %<nontemporal%> clauses"
-msgstr "%qE förekommer mer än en gång i %<aligned%>-klausuler"
+msgstr "%qE förekommer mer än en gång i %<nontemporal%>-klausuler"
#: c/c-typeck.c:14236 cp/semantics.c:6987
#, gcc-internal-format
@@ -38590,10 +38437,9 @@ msgid "%<depend%> clause with %<depobj%> dependence type on array section"
msgstr "klausulen %<depend%> med beroendetyp %<depobj%> på vektorsektion"
#: c/c-typeck.c:14247 cp/semantics.c:7012
-#, fuzzy, gcc-internal-format
-#| msgid "%qE is not a variable in %<depend%> clause"
+#, gcc-internal-format
msgid "%qE is not lvalue expression nor array section in %<depend%> clause"
-msgstr "%qE är inte en variabel i en %<depend%>-klausul"
+msgstr "%qE är varken ett l-värdeuttryck eller en vektorsektion i en %<depend%>-klausul"
#: c/c-typeck.c:14263 cp/semantics.c:7031
#, gcc-internal-format
@@ -38689,10 +38535,9 @@ msgid "%<linear%> clause step is a parameter %qD not specified in %<uniform%> cl
msgstr "%<linear%>-klausulsteg är en parameter %qD inte angiven i %<uniform%>-klausul"
#: c/c-typeck.c:14787 cp/semantics.c:7709
-#, fuzzy, gcc-internal-format
-#| msgid "%<nowait%> clause must not be used together with %<copyprivate%>"
+#, gcc-internal-format
msgid "%<nogroup%> clause must not be used together with %<reduction%> clause"
-msgstr "en %<nowait%>-klausul får inte användas tillsammans med %<copyprivate%>"
+msgstr "en %<nogroup%>-klausul får inte användas tillsammans med en %<reduction%>-klausul"
#: c/c-typeck.c:14953
#, gcc-internal-format
@@ -38710,40 +38555,34 @@ msgid "C++ requires promoted type, not enum type, in %<va_arg%>"
msgstr "C++ kräver en befordrad typ, inte en uppräkningstyp, i %<va_arg%>"
#: c/gimple-parser.c:249
-#, fuzzy, gcc-internal-format
-#| msgid "No edge out of thunk node"
+#, gcc-internal-format
msgid "edge not found"
-msgstr "Ingen båge ut från snuttnod"
+msgstr "bågen finns inte"
#: c/gimple-parser.c:382 c/gimple-parser.c:388
-#, fuzzy, gcc-internal-format
-#| msgid "expected pointer"
+#, gcc-internal-format
msgid "expected block index"
-msgstr "pekare förväntades"
+msgstr "blockindex förväntades"
#: c/gimple-parser.c:396
-#, fuzzy, gcc-internal-format
-#| msgid "invalid operation"
+#, gcc-internal-format
msgid "invalid block index"
-msgstr "ogiltig operation"
+msgstr "felaktigt blockindex"
#: c/gimple-parser.c:406
-#, fuzzy, gcc-internal-format
-#| msgid "expected type specifier"
+#, gcc-internal-format
msgid "expected block specifier"
-msgstr "typspecificerare förväntades"
+msgstr "blockspecificerare förväntades"
#: c/gimple-parser.c:424
-#, fuzzy, gcc-internal-format
-#| msgid "expected pass name"
+#, gcc-internal-format
msgid "expected loop number"
-msgstr "passnamn förväntades"
+msgstr "slingnummer förväntades"
#: c/gimple-parser.c:435
-#, fuzzy, gcc-internal-format
-#| msgid "unknown relocation unspec"
+#, gcc-internal-format
msgid "unknown block specifier"
-msgstr "okänd avspecifikation av omlokalisering"
+msgstr "okänd blockspecifiserare"
#: c/gimple-parser.c:449 c/gimple-parser.c:533
#, gcc-internal-format
@@ -38751,16 +38590,14 @@ msgid "stmts without block"
msgstr "satser utan block"
#: c/gimple-parser.c:485
-#, fuzzy, gcc-internal-format
-#| msgid "duplicate label %qD"
+#, gcc-internal-format
msgid "duplicate loop header"
-msgstr "dubblerad etikett %qD"
+msgstr "dubblerat slinghuvud"
#: c/gimple-parser.c:692
-#, fuzzy, gcc-internal-format
-#| msgid "invalid base-class specification"
+#, gcc-internal-format
msgid "invalid source block specification"
-msgstr "ogiltig basklasspecifikation"
+msgstr "ogiltig källkodsblockspecifikation"
#: c/gimple-parser.c:854
#, gcc-internal-format
@@ -38798,16 +38635,14 @@ msgid "invalid base %qE for SSA name"
msgstr "ogiltig bas %qE för SSA-namn"
#: c/gimple-parser.c:1077
-#, fuzzy, gcc-internal-format
-#| msgid "expected function name"
+#, gcc-internal-format
msgid "expecting internal function name"
-msgstr "ett funktionsnamn förväntades"
+msgstr "ett internt funktionsnamn förväntades"
#: c/gimple-parser.c:1090
-#, fuzzy, gcc-internal-format
-#| msgid "call to internal function %qE"
+#, gcc-internal-format
msgid "unknown internal function %qE"
-msgstr "anrop av intern funktion %qE"
+msgstr "okänd intern funktion %qE"
#: c/gimple-parser.c:1214
#, gcc-internal-format
@@ -38821,10 +38656,9 @@ msgid "invalid _Literal"
msgstr "ogiltig _Literal"
#: c/gimple-parser.c:1272
-#, fuzzy, gcc-internal-format
-#| msgid "initializer invalid for static member with constructor"
+#, gcc-internal-format
msgid "invalid type for _Literal with constructor"
-msgstr "initierare är ogiltig för statisk medlem med konstruerare"
+msgstr "felaktig typ för _Literal med konstruerare"
#: c/gimple-parser.c:1374
#, gcc-internal-format
@@ -38852,10 +38686,9 @@ msgid "expected else statement"
msgstr "else-sats förväntades"
#: c/gimple-parser.c:1974
-#, fuzzy, gcc-internal-format
-#| msgid "expected label"
+#, gcc-internal-format
msgid "expected case label"
-msgstr "etikett förväntades"
+msgstr "case-etikett förväntades"
#. A bad conversion for 'this' must be discarding cv-quals.
#: cp/call.c:3553
@@ -39201,10 +39034,9 @@ msgid "passing NULL to non-pointer argument %P of %qD"
msgstr "skickar NULL till icke-pekarargument %P till %qD"
#: cp/call.c:6873 cp/call.c:6892 cp/typeck.c:4065
-#, fuzzy, gcc-internal-format
-#| msgid " declared here"
+#, gcc-internal-format
msgid " declared here"
-msgstr " deklarerad här"
+msgstr " deklarerad här"
#: cp/call.c:6877
#, gcc-internal-format
@@ -39285,10 +39117,9 @@ msgid "implicit conversion from %qH to %qI when passing argument to function"
msgstr "implicit konvertering från %qH till %qI när argument skickas till en funktion"
#: cp/call.c:7544 cp/cvt.c:1925
-#, fuzzy, gcc-internal-format
-#| msgid "scoped enum %qT passed through ... as %qT before -fabi-version=6, %qT after"
+#, gcc-internal-format
msgid "scoped enum %qT passed through ... as %qT before %<-fabi-version=6%>, %qT after"
-msgstr "enum %qT med räckvidd skickad vidare … som %qT före -fabi-version=6, %qT efter"
+msgstr "enum %qT med räckvidd skickad vidare … som %qT före %<-fabi-version=6%>, %qT efter"
#: cp/call.c:7581
#, gcc-internal-format
@@ -39346,10 +39177,9 @@ msgid "deducing %qT as %qT"
msgstr "härleder %qT som %qT"
#: cp/call.c:8381
-#, fuzzy, gcc-internal-format
-#| msgid " (you can disable this with -fno-deduce-init-list)"
+#, gcc-internal-format
msgid " (you can disable this with %<-fno-deduce-init-list%>)"
-msgstr " (du kan avaktivera detta med -fno-deduce-init-list)"
+msgstr " (du kan avaktivera detta med %<-fno-deduce-init-list%>)"
#: cp/call.c:8493
#, gcc-internal-format
@@ -39625,10 +39455,9 @@ msgid "cannot convert from base class %qT to derived class %qT via virtual base
msgstr "kan inte konvertera från basklassen %qT till den härledda klassen %qT via den virtuella basen %qT"
#: cp/class.c:372
-#, fuzzy, gcc-internal-format
-#| msgid "cannot convert from base class %qT to derived class %qT because the base is virtual"
+#, gcc-internal-format
msgid "cannot convert from %qT to base class %qT because %qT is incomplete"
-msgstr "kan inte konvertera från basklassen %qT till den härledda klassen %qT eftersom basen är virtuell"
+msgstr "kan inte konvertera %qT till basklassen %qT eftersom %qT är inkomplett"
#: cp/class.c:1106
#, gcc-internal-format
@@ -39778,10 +39607,9 @@ msgid "the ellipsis in %qD is not inherited"
msgstr "ellipsen i %qD ärvs inte"
#: cp/class.c:3220
-#, fuzzy, gcc-internal-format
-#| msgid "bit-field %q+#D with non-integral type"
+#, gcc-internal-format
msgid "bit-field %q#D with non-integral type %qT"
-msgstr "bitfält %q+#D har en icke-heltalstyp"
+msgstr "bitfält %q#D har en icke-heltalstyp %qT"
#: cp/class.c:3236
#, gcc-internal-format
@@ -39824,10 +39652,9 @@ msgid "member %q+#D with copy assignment operator not allowed in union"
msgstr "medlem %q+#D med kopieringstilldelningsoperator inte tillåten i union"
#: cp/class.c:3332
-#, fuzzy, gcc-internal-format
-#| msgid "unrestricted unions only available with -std=c++11 or -std=gnu++11"
+#, gcc-internal-format
msgid "unrestricted unions only available with %<-std=c++11%> or %<-std=gnu++11%>"
-msgstr "obegränsade unioner är endast tillgängliga med -std=c++11 eller -std=gnu++11"
+msgstr "obegränsade unioner är endast tillgängliga med %<-std=c++11%> eller %<-std=gnu++11%>"
#: cp/class.c:3460
#, gcc-internal-format
@@ -39895,16 +39722,14 @@ msgid " but does not override %<operator=(const %T&)%>"
msgstr " men ersätter inte %<operator=(const %T&)%>"
#: cp/class.c:4146
-#, fuzzy, gcc-internal-format
-#| msgid "alignment of %qD increased in -fabi-version=9 (GCC 5.2)"
+#, gcc-internal-format
msgid "alignment of %qD increased in %<-fabi-version=9%> (GCC 5.2)"
-msgstr "justeringen av %qD ökade i -fabi-version=9 (GCC 5.2)"
+msgstr "justeringen av %qD ökade i %<-fabi-version=9%> (GCC 5.2)"
#: cp/class.c:4149
-#, fuzzy, gcc-internal-format
-#| msgid "alignment of %qD will increase in -fabi-version=9"
+#, gcc-internal-format
msgid "alignment of %qD will increase in %<-fabi-version=9%>"
-msgstr "justering av %qD kommer öka med -fabi-version=9"
+msgstr "justering av %qD kommer öka i %<-fabi-version=9%>"
#: cp/class.c:4442
#, gcc-internal-format
@@ -40122,16 +39947,14 @@ msgid "cannot convert %qE from type %qT to type %qT"
msgstr "kan inte konvertera %qE från typ %qT till typ %qT"
#: cp/class.c:8418
-#, fuzzy, gcc-internal-format
-#| msgid "declaration of %qD as member of %qT"
+#, gcc-internal-format
msgid "declaration of %q#D changes meaning of %qD"
-msgstr "deklaration av %qD som medlem av %qT"
+msgstr "deklaration av %q#D ändrar betydelsen av %qD"
#: cp/class.c:8421
-#, fuzzy, gcc-internal-format
-#| msgid "redeclared here as %q#D"
+#, gcc-internal-format
msgid "%qD declared here as %q#D"
-msgstr "omdeklarerad här som %q#D"
+msgstr "%qD deklarerad här som %q#D"
#: cp/constexpr.c:106
#, gcc-internal-format
@@ -40244,10 +40067,9 @@ msgid "call has circular dependency"
msgstr "anrop har cirkulärt beroende"
#: cp/constexpr.c:1780
-#, fuzzy, gcc-internal-format
-#| msgid "%<constexpr%> evaluation depth exceeds maximum of %d (use -fconstexpr-depth= to increase the maximum)"
+#, gcc-internal-format
msgid "%<constexpr%> evaluation depth exceeds maximum of %d (use %<-fconstexpr-depth=%> to increase the maximum)"
-msgstr "beräkning av %<constexpr%> överskrider maxvärdet på %d (använd -fconstexpr-depth= för att öka maxvärdet)"
+msgstr "beräkning av %<constexpr%> överskrider maxvärdet på %d (använd %<-fconstexpr-depth=%> för att öka maxvärdet)"
#: cp/constexpr.c:2016
#, gcc-internal-format
@@ -40376,10 +40198,9 @@ msgid "modification of %qE is not a constant expression"
msgstr "ändring av %qE är inte ett konstant uttryck"
#: cp/constexpr.c:3861
-#, fuzzy, gcc-internal-format
-#| msgid "Change of value in conversion from %qs to %qs at %L"
+#, gcc-internal-format
msgid "change of the active member of a union from %qD to %qD"
-msgstr "Ändring av värde vid konvertering från %qs till %qs vid %L"
+msgstr "ändring av den aktiva medlemmen av en union %qD till %qD"
#: cp/constexpr.c:4162 cp/constexpr.c:5213
#, gcc-internal-format
@@ -40387,10 +40208,9 @@ msgid "statement is not a constant expression"
msgstr "satsen är inte ett konstant uttryck"
#: cp/constexpr.c:4262
-#, fuzzy, gcc-internal-format
-#| msgid "%<constexpr%> loop iteration count exceeds limit of %d (use -fconstexpr-loop-limit= to increase the limit)"
+#, gcc-internal-format
msgid "%<constexpr%> loop iteration count exceeds limit of %d (use %<-fconstexpr-loop-limit=%> to increase the limit)"
-msgstr "%<constexpr%>-slingiterationsantal överskrider gränsen på %d (använd -fconstexpr-loop-limit= för att öka gränsen)"
+msgstr "%<constexpr%>-slingiterationsantal överskrider gränsen på %d (använd %<-fconstexpr-loop-limit=%> för att öka gränsen)"
#: cp/constexpr.c:4411
#, gcc-internal-format
@@ -40398,10 +40218,9 @@ msgid "value %qE of type %qT is not a constant expression"
msgstr "värdet %qE av typen %qT är inte ett konstant uttryck"
#: cp/constexpr.c:4425
-#, fuzzy, gcc-internal-format
-#| msgid "%<constexpr%> loop iteration count exceeds limit of %d (use -fconstexpr-loop-limit= to increase the limit)"
+#, gcc-internal-format
msgid "%<constexpr%> evaluation operation count exceeds limit of %wd (use -fconstexpr-ops-limit= to increase the limit)"
-msgstr "%<constexpr%>-slingiterationsantal överskrider gränsen på %d (använd -fconstexpr-loop-limit= för att öka gränsen)"
+msgstr "antalet %<constexpr%>-evalueringsoperationer överskrider gränsen på %wd (använd -fconstexpr-loop-limit= för att öka gränsen)"
#: cp/constexpr.c:4593 cp/constexpr.c:6551
#, gcc-internal-format
@@ -40450,10 +40269,9 @@ msgid "conversion from pointer type %qT to arithmetic type %qT in a constant exp
msgstr "konvertering från pekartypen %qT till den aritmetiska typen %qT i ett konstant uttryck"
#: cp/constexpr.c:5888
-#, fuzzy, gcc-internal-format
-#| msgid "invalid cast of an rvalue expression of type %qT to type %qT"
+#, gcc-internal-format
msgid "lvalue-to-rvalue conversion of a volatile lvalue %qE with type %qT"
-msgstr "ogiltig typkonvertering av ett rvärdeuttryck av typ %qT till typ %qT"
+msgstr "konvertering av l-värde till r-värde av ett volatilt l-värde %qE med typen %qT"
#: cp/constexpr.c:6092
#, gcc-internal-format
@@ -40486,10 +40304,9 @@ msgid "lambda-expression is not a constant expression before C++17"
msgstr "lambdauttryck är inte ett konstant uttryck före C++17"
#: cp/constexpr.c:6395
-#, fuzzy, gcc-internal-format
-#| msgid "virtual functions cannot be friends"
+#, gcc-internal-format
msgid "virtual functions cannot be constexpr before C++2a"
-msgstr "virtuella funktioner kan inte vara vänner"
+msgstr "virtuella funktioner kan inte constexpr före C++2a"
#: cp/constexpr.c:6407
#, gcc-internal-format
@@ -40558,10 +40375,9 @@ msgid "in C++11 this throw will terminate because destructors default to noexcep
msgstr "i C++11 kommer denna throw att avsluta eftersom standard för destruerare är noexcept"
#: cp/cp-gimplify.c:2782
-#, fuzzy, gcc-internal-format
-#| msgid "ignoring attributes in template argument %qE"
+#, gcc-internal-format
msgid "ignoring attribute %qE after earlier %qE"
-msgstr "ignorerar attribut i mallargumentet %qE"
+msgstr "ignorerar attributet %qE efter tidigare %qE"
#: cp/cvt.c:91
msgid "can%'t convert from incomplete type %qH to %qI"
@@ -40898,8 +40714,7 @@ msgid "converting NULL to non-pointer type"
msgstr "konvertera av NULL till icke-pekartyp"
#: cp/cvt.c:1825
-#, fuzzy, gcc-internal-format
-#| msgid "default type conversion can't deduce template argument for %qD"
+#, gcc-internal-format
msgid "default type conversion can%'t deduce template argument for %qD"
msgstr "standardtypkonvertering kan inte härleda mallargumentet för %qD"
@@ -40979,16 +40794,14 @@ msgid "redeclaration of %q#D may not have default arguments"
msgstr "omdeklaration av %q#D kan inte ha standardargument"
#: cp/decl.c:1307
-#, fuzzy, gcc-internal-format
-#| msgid "friend declaration %q#D declares a non-template function"
+#, gcc-internal-format
msgid "friend declaration of %q#D specifies default arguments and isn%'t the only declaration"
-msgstr "vändeklaration %q#D deklarerar en icke-mall-funktion"
+msgstr "vändeklaration av %q#D anger standardargument och är inte den enda deklarationen"
#: cp/decl.c:1310
-#, fuzzy, gcc-internal-format
-#| msgid "previous declaration of %qD"
+#, gcc-internal-format
msgid "previous declaration of %q#D"
-msgstr "tidigare deklaration av %qD"
+msgstr "tidigare deklaration av %q#D"
#: cp/decl.c:1388
#, gcc-internal-format
@@ -41041,34 +40854,29 @@ msgid "ignoring the %q#D declaration"
msgstr "ignorerar deklarationen %q#D"
#: cp/decl.c:1616
-#, fuzzy, gcc-internal-format
-#| msgid "literal operator template %q+D conflicts with raw literal operator %qD"
+#, gcc-internal-format
msgid "literal operator %q#D conflicts with raw literal operator"
-msgstr "den litterala operatormallen %q+D står i konflikt med den råa litterala operatorn %qD"
+msgstr "den litterala operatorn %q#D står i konflikt med den råa litterala operatorn"
#: cp/decl.c:1620
-#, fuzzy, gcc-internal-format
-#| msgid "raw literal operator %q+D conflicts with literal operator template %qD"
+#, gcc-internal-format
msgid "raw literal operator %q#D conflicts with literal operator template"
-msgstr "den råa litterala operatorn %q+D står i konflikt med den litterala operatormallen %qD"
+msgstr "den råa litterala operatorn %q#D står i konflikt med den litterala operatormallen"
#: cp/decl.c:1633
-#, fuzzy, gcc-internal-format
-#| msgid "%q#D redeclared as different kind of symbol"
+#, gcc-internal-format
msgid "%q#D redeclared as different kind of entity"
-msgstr "%q#D omdeklarerad som en annan sorts symbol"
+msgstr "%q#D omdeklarerad som en annan sorts entitet"
#: cp/decl.c:1654
-#, fuzzy, gcc-internal-format
-#| msgid "conflicting declaration of template %q+#D"
+#, gcc-internal-format
msgid "conflicting declaration of template %q#D"
-msgstr "motstridig deklaration av mallen %q+#D"
+msgstr "motstridig deklaration av mallen %q#D"
#: cp/decl.c:1673
-#, fuzzy, gcc-internal-format
-#| msgid "ambiguating new declaration %q+#D"
+#, gcc-internal-format
msgid "ambiguating new declaration %q#D"
-msgstr "ny deklaration %q+#D som skapar tvetydighet"
+msgstr "ny deklaration %q#D som skapar tvetydighet"
#: cp/decl.c:1676 cp/decl.c:1706
#, gcc-internal-format
@@ -41076,22 +40884,19 @@ msgid "old declaration %q#D"
msgstr "gammal deklaration av %q#D"
#: cp/decl.c:1687
-#, fuzzy, gcc-internal-format
-#| msgid "conflicting declaration of C function %q+#D"
+#, gcc-internal-format
msgid "conflicting declaration of C function %q#D"
-msgstr "motstridande deklaration av C-funktionen %q+#D"
+msgstr "motstridande deklaration av C-funktionen %q#D"
#: cp/decl.c:1704
-#, fuzzy, gcc-internal-format
-#| msgid "ambiguating new declaration of %q+#D"
+#, gcc-internal-format
msgid "ambiguating new declaration of %q#D"
-msgstr "ny deklaration av %q+#D som skapar tvetydighet"
+msgstr "ny deklaration av %q#D som skapar tvetydighet"
#: cp/decl.c:1714
-#, fuzzy, gcc-internal-format
-#| msgid "conflicting declaration %q+#D"
+#, gcc-internal-format
msgid "conflicting declaration %q#D"
-msgstr "motstridande deklaration av %q+#D"
+msgstr "motstridande deklaration av %q#D"
#: cp/decl.c:1716
#, gcc-internal-format
@@ -41119,10 +40924,9 @@ msgid "previous non-prototype definition here"
msgstr "tidigare definition som inte är en prototyp här"
#: cp/decl.c:1829
-#, fuzzy, gcc-internal-format
-#| msgid "conflicting declaration of %q+#D with %qL linkage"
+#, gcc-internal-format
msgid "conflicting declaration of %q#D with %qL linkage"
-msgstr "motstridig deklaration av %q+#D med länkklass %qL"
+msgstr "motstridig deklaration av %q#D med länkklass %qL"
#: cp/decl.c:1832
#, gcc-internal-format
@@ -41140,16 +40944,14 @@ msgid "previous specification in %q#D here"
msgstr "tidigare specifikation i %q#D här"
#: cp/decl.c:1928
-#, fuzzy, gcc-internal-format
-#| msgid "previous definition of %qD was here"
+#, gcc-internal-format
msgid "previous definition of %qD here"
-msgstr "tidigare definition av %qD var här"
+msgstr "tidigare definition av %qD här"
#: cp/decl.c:1929
-#, fuzzy, gcc-internal-format
-#| msgid "previous declaration of %qD was here"
+#, gcc-internal-format
msgid "previous declaration of %qD here"
-msgstr "tidigare deklaration av %qD var här"
+msgstr "tidigare deklaration av %qD här"
#: cp/decl.c:1968
#, gcc-internal-format
@@ -41157,10 +40959,9 @@ msgid "redundant redeclaration of %qD in same scope"
msgstr "överflödig omdeklaration av %qD i samma definitionsområde"
#: cp/decl.c:1980
-#, fuzzy, gcc-internal-format
-#| msgid "deleted definition of %q+D"
+#, gcc-internal-format
msgid "deleted definition of %qD"
-msgstr "borttagen definition av %q+D"
+msgstr "borttagen definition av %qD"
#. From [temp.expl.spec]:
#.
@@ -41317,10 +41118,9 @@ msgid "%qD is not a type"
msgstr "%qD är inte en typ"
#: cp/decl.c:3826 cp/parser.c:6492
-#, fuzzy, gcc-internal-format
-#| msgid "%qD used without template parameters"
+#, gcc-internal-format
msgid "%qD used without template arguments"
-msgstr "%qD använd utan mallparametrar"
+msgstr "%qD använd utan mallargument"
#: cp/decl.c:3837
#, gcc-internal-format
@@ -41358,10 +41158,9 @@ msgid "template parameters do not match template %qD"
msgstr "mallparametrar stämmer inte med mallen %qD"
#: cp/decl.c:4283
-#, fuzzy, gcc-internal-format
-#| msgid "-faligned-new=%d is not a power of two"
+#, gcc-internal-format
msgid "%<-faligned-new=%d%> is not a power of two"
-msgstr "-faligned-new=%d är inte en exponent av två"
+msgstr "%<-faligned-new=%d%> är inte en exponent av två"
#: cp/decl.c:4751
#, gcc-internal-format
@@ -41696,10 +41495,9 @@ msgid "braces around scalar initializer for type %qT"
msgstr "klamrar runt skalär initierare för typen %qT"
#: cp/decl.c:6117
-#, fuzzy, gcc-internal-format
-#| msgid "braces around scalar initializer for type %qT"
+#, gcc-internal-format
msgid "too many braces around scalar initializerfor type %qT"
-msgstr "klamrar runt skalär initierare för typen %qT"
+msgstr "för många klamrar runt skalär initierare för typen %qT"
#: cp/decl.c:6237
#, gcc-internal-format
@@ -42053,10 +41851,9 @@ msgid "%<inline%> is not allowed in declaration of friend template specializatio
msgstr "%<inline%> är inte tillåtet i deklaration av vänmallspecialisering %qD"
#: cp/decl.c:8951
-#, fuzzy, gcc-internal-format
-#| msgid "declaration of %q#D outside of class is not definition"
+#, gcc-internal-format
msgid "friend declaration of %qD specifies default arguments and isn%'t a definition"
-msgstr "deklaration av %q#D utanför en klass är inte en definition"
+msgstr "vändeklarationen av %qD anger standardargument och är inte en definition"
#: cp/decl.c:8998
#, gcc-internal-format
@@ -42389,10 +42186,9 @@ msgid "%<inline%> specifier invalid for variable %qD declared at block scope"
msgstr "specificeraren %<inline%> är ogiltig för variabeln %qD deklarerad med blockräckvidd"
#: cp/decl.c:10209
-#, fuzzy, gcc-internal-format
-#| msgid "inline variables are only available with -std=c++17 or -std=gnu++17"
+#, gcc-internal-format
msgid "inline variables are only available with %<-std=c++17%> or %<-std=gnu++17%>"
-msgstr "inline-variabler är endast tillgängliga med -std=c++17 eller -std=gnu++17"
+msgstr "inline-variabler är endast tillgängliga med %<-std=c++17%> eller %<-std=gnu++17%>"
#: cp/decl.c:10467
#, gcc-internal-format
@@ -42485,34 +42281,29 @@ msgid "ISO C++ does not support %<__int%d%> for %qs"
msgstr "ISO C++ stödjer inte %<__int%d%> för %qs"
#: cp/decl.c:10841
-#, fuzzy, gcc-internal-format
-#| msgid "%<signed%> and %<unsigned%> specified together for %qs"
+#, gcc-internal-format
msgid "%<signed%> and %<unsigned%> specified together"
-msgstr "%<signed%> och %<unsigned%> givna tillsammans för %qs"
+msgstr "%<signed%> och %<unsigned%> givna tillsammans"
#: cp/decl.c:10847
-#, fuzzy, gcc-internal-format
-#| msgid "%<long%> and %<short%> specified together for %qs"
+#, gcc-internal-format
msgid "%<long%> and %<short%> specified together"
-msgstr "%<long%> och %<short%> angivna tillsammans för %qs"
+msgstr "%<long%> och %<short%> angivna tillsammans"
#: cp/decl.c:10855 cp/decl.c:10861
-#, fuzzy, gcc-internal-format
-#| msgid "%qs used with %qE"
+#, gcc-internal-format
msgid "%qs specified with %qT"
-msgstr "%qs använd med %qE"
+msgstr "%qs specificerad med %qT"
#: cp/decl.c:10866
-#, fuzzy, gcc-internal-format
-#| msgid "%qE used with %<typedef%>"
+#, gcc-internal-format
msgid "%qs specified with %<decltype%>"
-msgstr "%qE använd med %<typedef%>"
+msgstr "%qs specificerad med %<decltype%>"
#: cp/decl.c:10868
-#, fuzzy, gcc-internal-format
-#| msgid "%qE used with %<typedef%>"
+#, gcc-internal-format
msgid "%qs specified with %<typeof%>"
-msgstr "%qE använd med %<typedef%>"
+msgstr "%qs specificerad använd med %<typeof%>"
#: cp/decl.c:10934
#, gcc-internal-format
@@ -42530,10 +42321,9 @@ msgid "member %qD cannot be declared both %<virtual%> and %<static%>"
msgstr "medlem %qD kan inte deklareras både %<virtual%> och %<static%>"
#: cp/decl.c:11002
-#, fuzzy, gcc-internal-format
-#| msgid "member %qD cannot be declared both %<virtual%> and %<constexpr%>"
+#, gcc-internal-format
msgid "member %qD can be declared both %<virtual%> and %<constexpr%> only in %<-std=c++2a%> or %<-std=gnu++2a%>"
-msgstr "medlem %qD kan inte deklareras både %<virtual%> och %<constexpr%>"
+msgstr "medlem %qD kan deklareras både %<virtual%> och %<constexpr%> endast i %<-std=c++2a%> eller %<-std=gnu++2a%>"
#: cp/decl.c:11015
#, gcc-internal-format
@@ -42671,10 +42461,9 @@ msgid "%qs function uses %<auto%> type specifier without trailing return type"
msgstr "funktionen %qs använder typspecificeraren %<auto%> utan avslutande returtyp"
#: cp/decl.c:11370
-#, fuzzy, gcc-internal-format
-#| msgid "deduced return type only available with -std=c++14 or -std=gnu++14"
+#, gcc-internal-format
msgid "deduced return type only available with %<-std=c++14%> or %<-std=gnu++14%>"
-msgstr "härledd returtyp är endast tillgänglig med -std=c++14 eller -std=gnu++14"
+msgstr "härledd returtyp är endast tillgänglig med %<-std=c++14%> eller %<-std=gnu++14%>"
#: cp/decl.c:11375
#, gcc-internal-format
@@ -42687,16 +42476,14 @@ msgid "%qs function with trailing return type has %qT as its type rather than pl
msgstr "funktionen %qs med avslutande returtyp har %qT som sin typ istället för bara %<auto%>"
#: cp/decl.c:11391
-#, fuzzy, gcc-internal-format
-#| msgid "%qs function with trailing return type has %qT as its type rather than plain %<auto%>"
+#, gcc-internal-format
msgid "%qs function with trailing return type has %<decltype(auto)%> as its type rather than plain %<auto%>"
-msgstr "funktionen %qs med avslutande returtyp har %qT som sin typ istället för bara %<auto%>"
+msgstr "funktionen %qs med avslutande returtyp har %<decltype(auto)%> som sin typ istället för bara %<auto%>"
#: cp/decl.c:11396
-#, fuzzy, gcc-internal-format
-#| msgid "invalid use of %<restrict%>"
+#, gcc-internal-format
msgid "invalid use of %<decltype(auto)%>"
-msgstr "ogiltigt användning av %<restrict%>"
+msgstr "ogiltigt användning av %<decltype(auto)%>"
#: cp/decl.c:11407
#, gcc-internal-format
@@ -42714,10 +42501,9 @@ msgid "trailing return type %qT of deduction guide is not a specialization of %q
msgstr "den avslutande returtypen %qT hos deduktionsguiden är inte en specialisering av %qT"
#: cp/decl.c:11441
-#, fuzzy, gcc-internal-format
-#| msgid "trailing return type only available with -std=c++11 or -std=gnu++11"
+#, gcc-internal-format
msgid "trailing return type only available with %<-std=c++11%> or %<-std=gnu++11%>"
-msgstr "avslutande returtyp är endast tillgänglig med -std=c++11 eller -std=gnu++11"
+msgstr "avslutande returtyp är endast tillgänglig med %<-std=c++11%> eller %<-std=gnu++11%>"
#: cp/decl.c:11444
#, gcc-internal-format
@@ -42900,16 +42686,14 @@ msgid "function %qs cannot be declared %<mutable%>"
msgstr "funktionen %qs kan inte deklareras %<mutable%>"
#: cp/decl.c:12008
-#, fuzzy, gcc-internal-format
-#| msgid "static %qs cannot be declared %<mutable%>"
+#, gcc-internal-format
msgid "%<static%> %qs cannot be declared %<mutable%>"
-msgstr "statiska %qs kan inte deklareras %<mutable%>"
+msgstr "%<static%> %qs kan inte deklareras %<mutable%>"
#: cp/decl.c:12014
-#, fuzzy, gcc-internal-format
-#| msgid "const %qs cannot be declared %<mutable%>"
+#, gcc-internal-format
msgid "%<const%> %qs cannot be declared %<mutable%>"
-msgstr "const %qs kan inte deklareras %<mutable%>"
+msgstr "%<const%> %qs kan inte deklareras %<mutable%>"
#: cp/decl.c:12020
#, gcc-internal-format
@@ -42917,10 +42701,9 @@ msgid "reference %qs cannot be declared %<mutable%>"
msgstr "referensen %qs kan inte deklareras %<mutable%>"
#: cp/decl.c:12056
-#, fuzzy, gcc-internal-format
-#| msgid "%<[*]%> not in a declaration"
+#, gcc-internal-format
msgid "%<auto%> not allowed in alias declaration"
-msgstr "%<[*]%> är inte i en deklaration"
+msgstr "%<auto%> är inte tillåtet i en aliasdeklaration"
#: cp/decl.c:12059
#, gcc-internal-format
@@ -43104,10 +42887,9 @@ msgid "%qE is neither function nor member function; cannot be declared friend"
msgstr "%qE är varken en funktion eller medlemsfunktion, kan inte deklareras som vän"
#: cp/decl.c:12567
-#, fuzzy, gcc-internal-format
-#| msgid "%qE is neither function nor member function; cannot be declared friend"
+#, gcc-internal-format
msgid "unnamed field is neither function nor member function; cannot be declared friend"
-msgstr "%qE är varken en funktion eller medlemsfunktion, kan inte deklareras som vän"
+msgstr "ett namnlöst fält är varken en funktion eller medlemsfunktion, kan inte deklareras som vän"
#: cp/decl.c:12612
#, gcc-internal-format
@@ -43357,34 +43139,29 @@ msgid "%qD cannot have default arguments"
msgstr "%qD kan inte ha standardargument"
#: cp/decl.c:13724
-#, fuzzy, gcc-internal-format
-#| msgid "conversion to void will never use a type conversion operator"
+#, gcc-internal-format
msgid "converting %qT to %<void%> will never use a type conversion operator"
-msgstr "konvertering till void kommer aldrig använda en typkonverteringsoperator"
+msgstr "konvertering av %qT till %<void%> kommer aldrig använda en typkonverteringsoperator"
#: cp/decl.c:13731
-#, fuzzy, gcc-internal-format
-#| msgid "conversion to a reference to the same type will never use a type conversion operator"
+#, gcc-internal-format
msgid "converting %qT to a reference to the same type will never use a type conversion operator"
-msgstr "konvertering till en referens till samma typ kommer aldrig använda en typkonverteringsoperator"
+msgstr "konvertering till %qT till en referens till samma typ kommer aldrig använda en typkonverteringsoperator"
#: cp/decl.c:13733
-#, fuzzy, gcc-internal-format
-#| msgid "conversion to the same type will never use a type conversion operator"
+#, gcc-internal-format
msgid "converting %qT to the same type will never use a type conversion operator"
-msgstr "konvertering till samma typ kommer aldrig använda en typkonverteringsoperator"
+msgstr "konvertering till %qT till samma typ kommer aldrig använda en typkonverteringsoperator"
#: cp/decl.c:13742
-#, fuzzy, gcc-internal-format
-#| msgid "conversion to a reference to a base class will never use a type conversion operator"
+#, gcc-internal-format
msgid "converting %qT to a reference to a base class %qT will never use a type conversion operator"
-msgstr "konvertering till en referens till en basklass kommer aldrig använda en typkonverteringsoperator"
+msgstr "konvertering till %qT till en referens till basklassen %qT kommer aldrig använda en typkonverteringsoperator"
#: cp/decl.c:13744
-#, fuzzy, gcc-internal-format
-#| msgid "conversion to a base class will never use a type conversion operator"
+#, gcc-internal-format
msgid "converting %qT to a base class %qT will never use a type conversion operator"
-msgstr "konvertering till en basklass kommer aldrig använda en typkonverteringsoperator"
+msgstr "konvertering till %qT till basklassen %qT kommer aldrig använda en typkonverteringsoperator"
#: cp/decl.c:13760
#, gcc-internal-format
@@ -43738,10 +43515,9 @@ msgid "%<asm%> specifiers are not permitted on non-static data members"
msgstr "%<asm%>-specificerare är inte tillåtna på icke-statiska datamedlemmar"
#: cp/decl2.c:1045
-#, fuzzy, gcc-internal-format
-#| msgid "bit-field %qD with non-integral type"
+#, gcc-internal-format
msgid "bit-field %qD with non-integral type %qT"
-msgstr "bitfält %qD med en icke-heltalstyp"
+msgstr "bitfältet %qD med icke-heltalstypen %qT"
#: cp/decl2.c:1053
#, gcc-internal-format
@@ -43835,10 +43611,9 @@ msgstr "%<operator delete%> måste returnera typ %qT"
#. A destroying operator delete shall be a class member function named
#. operator delete.
#: cp/decl2.c:1776
-#, fuzzy, gcc-internal-format
-#| msgid "destructor cannot be static member function"
+#, gcc-internal-format
msgid "destroying operator delete must be a member function"
-msgstr "destruerare kan inte vara en statisk medlemsfunktion"
+msgstr "den destruerande operatorn delete måste vara medlemsfunktion"
#: cp/decl2.c:1779
#, gcc-internal-format
@@ -43945,10 +43720,9 @@ msgid "previous mangling %q#D"
msgstr "tidigare mangling %q#D"
#: cp/decl2.c:4627
-#, fuzzy, gcc-internal-format
-#| msgid "a later -fabi-version= (or =0) avoids this error with a change in mangling"
+#, gcc-internal-format
msgid "a later %<-fabi-version=%> (or =0) avoids this error with a change in mangling"
-msgstr "en senare -fabi-version= (eller =0) undviker detta fel med en ändring av manglingen"
+msgstr "en senare %<-fabi-version=%> (eller =0) undviker detta fel med en ändring av manglingen"
#: cp/decl2.c:4699 cp/decl2.c:4702
#, gcc-internal-format
@@ -43961,22 +43735,19 @@ msgid "inline function %qD used but never defined"
msgstr "inline-funktion %qD använd men aldrig definierad"
#: cp/decl2.c:5244
-#, fuzzy, gcc-internal-format
-#| msgid "default argument missing for parameter %P of %q+#D"
+#, gcc-internal-format
msgid "default argument missing for parameter %P of %q#D"
-msgstr "standardargumentet saknas för parameter %P till %q+#D"
+msgstr "standardargumentet saknas för parameter %P till %q#D"
#: cp/decl2.c:5249
-#, fuzzy, gcc-internal-format
-#| msgid "parameter pack cannot have a default argument"
+#, gcc-internal-format
msgid "...following parameter %P which has a default argument"
-msgstr "parameterpaket kan inte ha ett standardargument"
+msgstr "… följande parameter %P som har ett standardargument"
#: cp/decl2.c:5349
-#, fuzzy, gcc-internal-format
-#| msgid "class %qE is deprecated"
+#, gcc-internal-format
msgid "implicitly-declared %qD is deprecated"
-msgstr "klassen %qE bör undvikas"
+msgstr "implicit deklarerad %qD bör undvikas"
#: cp/decl2.c:5353
#, gcc-internal-format
@@ -44016,94 +43787,79 @@ msgid "[...]"
msgstr "[…]"
#: cp/error.c:4150
-#, fuzzy, gcc-internal-format
-#| msgid "extended initializer lists only available with -std=c++11 or -std=gnu++11"
+#, gcc-internal-format
msgid "extended initializer lists only available with %<-std=c++11%> or %<-std=gnu++11%>"
-msgstr "utökade initierarlistor är endast tillgängliga med -std=c++11 eller -std=gnu++11"
+msgstr "utökade initierarlistor är endast tillgängliga med %<-std=c++11%> eller %<-std=gnu++11%>"
#: cp/error.c:4155
-#, fuzzy, gcc-internal-format
-#| msgid "explicit conversion operators only available with -std=c++11 or -std=gnu++11"
+#, gcc-internal-format
msgid "explicit conversion operators only available with %<-std=c++11%> or %<-std=gnu++11%>"
-msgstr "explicita konverteringsoperatorer är endast tillgängliga med -std=c++11 eller -std=gnu++11"
+msgstr "explicita konverteringsoperatorer är endast tillgängliga med %<-std=c++11%> eller %<-std=gnu++11%>"
#: cp/error.c:4160
-#, fuzzy, gcc-internal-format
-#| msgid "variadic templates only available with -std=c++11 or -std=gnu++11"
+#, gcc-internal-format
msgid "variadic templates only available with %<-std=c++11%> or %<-std=gnu++11%>"
-msgstr "variadiska mallar är endast tillgängliga med -std=c++11 eller -std=gnu++11"
+msgstr "variadiska mallar är endast tillgängliga med %<-std=c++11%> eller %<-std=gnu++11%>"
#: cp/error.c:4165
-#, fuzzy, gcc-internal-format
-#| msgid "lambda expressions only available with -std=c++11 or -std=gnu++11"
+#, gcc-internal-format
msgid "lambda expressions only available with %<-std=c++11%> or %<-std=gnu++11%>"
-msgstr "lambdauttryck är endast tillgängliga med -std=c++11 eller -std=gnu++11"
+msgstr "lambdauttryck är endast tillgängliga med %<-std=c++11%> eller %<-std=gnu++11%>"
#: cp/error.c:4170
-#, fuzzy, gcc-internal-format
-#| msgid "C++11 auto only available with -std=c++11 or -std=gnu++11"
+#, gcc-internal-format
msgid "C++11 auto only available with %<-std=c++11%> or %<-std=gnu++11%>"
-msgstr "C++11 auto är endast tillgängligt med -std=c++11 eller -std=gnu++11"
+msgstr "C++11 auto är endast tillgängligt med %<-std=c++11%> eller %<-std=gnu++11%>"
#: cp/error.c:4175
-#, fuzzy, gcc-internal-format
-#| msgid "scoped enums only available with -std=c++11 or -std=gnu++11"
+#, gcc-internal-format
msgid "scoped enums only available with %<-std=c++11%> or %<-std=gnu++11%>"
-msgstr "enum med räckvidd är endast tillgängliga med -std=c++11 eller -std=gnu++11"
+msgstr "enum med räckvidd är endast tillgängliga med %<-std=c++11%> eller %<-std=gnu++11%>"
#: cp/error.c:4180
-#, fuzzy, gcc-internal-format
-#| msgid "defaulted and deleted functions only available with -std=c++11 or -std=gnu++11"
+#, gcc-internal-format
msgid "defaulted and deleted functions only available with %<-std=c++11%> or %<-std=gnu++11%>"
-msgstr "standarddefinierade och borttagna funktioner är endast tillgängliga med -std=c++11 eller -std=gnu++11"
+msgstr "standarddefinierade och borttagna funktioner är endast tillgängliga med %<-std=c++11%> eller %<-std=gnu++11%>"
#: cp/error.c:4185
-#, fuzzy, gcc-internal-format
-#| msgid "inline namespaces only available with -std=c++11 or -std=gnu++11"
+#, gcc-internal-format
msgid "inline namespaces only available with %<-std=c++11%> or %<-std=gnu++11%>"
-msgstr "inline-namnrymder är endast tillgängliga med -std=c++11 eller -std=gnu++11"
+msgstr "inline-namnrymder är endast tillgängliga med %<-std=c++11%> eller %<-std=gnu++11%>"
#: cp/error.c:4190
-#, fuzzy, gcc-internal-format
-#| msgid "override controls (override/final) only available with -std=c++11 or -std=gnu++11"
+#, gcc-internal-format
msgid "override controls (override/final) only available with %<-std=c++11%> or %<-std=gnu++11%>"
-msgstr "styrning av åsidosättande (override/final) är endast tillgängliga med -std=c++11 eller -std=gnu++11"
+msgstr "styrning av åsidosättande (override/final) är endast tillgängliga med %<-std=c++11%> eller %<-std=gnu++11%>"
#: cp/error.c:4195
-#, fuzzy, gcc-internal-format
-#| msgid "non-static data member initializers only available with -std=c++11 or -std=gnu++11"
+#, gcc-internal-format
msgid "non-static data member initializers only available with %<-std=c++11%> or %<-std=gnu++11%>"
-msgstr "initierare av datamedlemmar som inte är statiska är endast tillgängliga med -std=c++11 eller -std=gnu++11"
+msgstr "initierare av datamedlemmar som inte är statiska är endast tillgängliga med %<-std=c++11%> eller %<-std=gnu++11%>"
#: cp/error.c:4200
-#, fuzzy, gcc-internal-format
-#| msgid "user-defined literals only available with -std=c++11 or -std=gnu++11"
+#, gcc-internal-format
msgid "user-defined literals only available with %<-std=c++11%> or %<-std=gnu++11%>"
-msgstr "användardefinierade litteraler är endast tillgängliga med -std=c++11 eller -std=gnu++11"
+msgstr "användardefinierade litteraler är endast tillgängliga med %<-std=c++11%> eller %<-std=gnu++11%>"
#: cp/error.c:4205
-#, fuzzy, gcc-internal-format
-#| msgid "delegating constructors only available with -std=c++11 or -std=gnu++11"
+#, gcc-internal-format
msgid "delegating constructors only available with %<-std=c++11%> or %<-std=gnu++11%>"
-msgstr "delegerande konstruerare är endast tillgängliga med -std=c++11 eller -std=gnu++11"
+msgstr "delegerande konstruerare är endast tillgängliga med %<-std=c++11%> eller %<-std=gnu++11%>"
#: cp/error.c:4210
-#, fuzzy, gcc-internal-format
-#| msgid "inheriting constructors only available with -std=c++11 or -std=gnu++11"
+#, gcc-internal-format
msgid "inheriting constructors only available with %<-std=c++11%> or %<-std=gnu++11%>"
-msgstr "ärvande konstruerare är endast tillgängliga med -std=c++11 eller -std=gnu++11"
+msgstr "ärvande konstruerare är endast tillgängliga med %<-std=c++11%> eller %<-std=gnu++11%>"
#: cp/error.c:4215
-#, fuzzy, gcc-internal-format
-#| msgid "c++11 attributes only available with -std=c++11 or -std=gnu++11"
+#, gcc-internal-format
msgid "c++11 attributes only available with %<-std=c++11%> or %<-std=gnu++11%>"
-msgstr "c++11-attribut är endast tillgängligt med -std=c++11 eller -std=gnu++11"
+msgstr "c++11-attribut är endast tillgängligt med %<-std=c++11%> eller %<-std=gnu++11%>"
#: cp/error.c:4220
-#, fuzzy, gcc-internal-format
-#| msgid "ref-qualifiers only available with -std=c++11 or -std=gnu++11"
+#, gcc-internal-format
msgid "ref-qualifiers only available with %<-std=c++11%> or %<-std=gnu++11%>"
-msgstr "ref-kvalificerare är endast tillgängliga med -std=c++11 eller -std=gnu++11"
+msgstr "ref-kvalificerare är endast tillgängliga med %<-std=c++11%> eller %<-std=gnu++11%>"
#: cp/error.c:4270
#, gcc-internal-format
@@ -44116,10 +43872,9 @@ msgid "reference to %<%T::%D%> is ambiguous"
msgstr "referens till %<%T::%D%> är tvetydig"
#: cp/error.c:4288
-#, fuzzy, gcc-internal-format
-#| msgid "%qT has no member named %qE; did you mean %qE?"
+#, gcc-internal-format
msgid "%qD is not a member of %qT; did you mean %qs?"
-msgstr "%qT har ingen medlem med namnet %qE; menade du %qE?"
+msgstr "%qD är inte en medlem av %qT; menade du %qs?"
#: cp/error.c:4292 cp/typeck.c:2437
#, gcc-internal-format
@@ -44127,10 +43882,9 @@ msgid "%qD is not a member of %qT"
msgstr "%qD har inte en medlem av %qT"
#: cp/error.c:4314
-#, fuzzy, gcc-internal-format
-#| msgid "%qT has no member named %qE; did you mean %qE?"
+#, gcc-internal-format
msgid "%qD is not a member of %qD; did you mean %qs?"
-msgstr "%qT har ingen medlem med namnet %qE; menade du %qE?"
+msgstr "%qD är inte en medlem av %qD; menade du %qs?"
#: cp/error.c:4318 cp/typeck.c:3031
#, gcc-internal-format
@@ -44138,10 +43892,9 @@ msgid "%qD is not a member of %qD"
msgstr "%qD är inte en medlem av %qD"
#: cp/error.c:4329
-#, fuzzy, gcc-internal-format
-#| msgid "%<::%D%> has not been declared"
+#, gcc-internal-format
msgid "%<::%D%> has not been declared; did you mean %qs?"
-msgstr "%<::%D%> har inte deklarerats"
+msgstr "%<::%D%> har inte deklarerats; menade du %qs?"
#: cp/error.c:4333
#, gcc-internal-format
@@ -44149,16 +43902,14 @@ msgid "%<::%D%> has not been declared"
msgstr "%<::%D%> har inte deklarerats"
#: cp/except.c:146
-#, fuzzy, gcc-internal-format
-#| msgid "%qD declared here"
+#, gcc-internal-format
msgid "%qs declared incorrectly"
-msgstr "%qD är deklarerad här"
+msgstr "%qs är felaktigt deklarerad"
#: cp/except.c:418
-#, fuzzy, gcc-internal-format
-#| msgid "exception handling disabled, use -fexceptions to enable"
+#, gcc-internal-format
msgid "exception handling disabled, use %<-fexceptions%> to enable"
-msgstr "undantagshantering avslagen, använd -fexceptions för att aktivera"
+msgstr "undantagshantering avslagen, använd %<-fexceptions%> för att aktivera"
#: cp/except.c:644
#, gcc-internal-format
@@ -44728,10 +44479,9 @@ msgid "%qD not defined"
msgstr "%qD inte definierad"
#: cp/lex.c:515
-#, fuzzy, gcc-internal-format
-#| msgid "%qD was not declared in this scope"
+#, gcc-internal-format
msgid "%qD was not declared in this scope; did you mean %qs?"
-msgstr "%qD deklarerades inte i detta definitionsområde"
+msgstr "%qD deklarerades inte i detta definitionsområde; menade du %qs?"
#: cp/lex.c:519
#, gcc-internal-format
@@ -44804,22 +44554,19 @@ msgid "the mangled name of %qD changes between %<%s=%d%> (%qD) and %<%s=%d%> (%q
msgstr "det manglade namnet på %qD ändras mellan %<%s=%d%> (%qD) och %<%s=%d%> (%qD)"
#: cp/mangle.c:4216
-#, fuzzy, gcc-internal-format
-#| msgid "the mangled name of a thunk for %qD changes between -fabi-version=%d and -fabi-version=%d"
+#, gcc-internal-format
msgid "the mangled name of a thunk for %qD changes between %<-fabi-version=%d%> and %<-fabi-version=%d%>"
-msgstr "det manglade namnet på en snutt för %qD ändras mellan -fabi-version=%d och -fabi-version=%d"
+msgstr "det manglade namnet på en snutt för %qD ändras mellan %<-fabi-version=%d%> och %<-fabi-version=%d%>"
#: cp/mangle.c:4221
-#, fuzzy, gcc-internal-format
-#| msgid "the mangled name of %qD changes between -fabi-version=%d and -fabi-version=%d"
+#, gcc-internal-format
msgid "the mangled name of %qD changes between %<-fabi-version=%d%> and %<-fabi-version=%d%>"
-msgstr "det manglade namnet på %qD ändras mellan -fabi-version=%d och -fabi-version=%d"
+msgstr "det manglade namnet på %qD ändras mellan %<-fabi-version=%d%> och %<-fabi-version=%d%>"
#: cp/mangle.c:4226
-#, fuzzy, gcc-internal-format
-#| msgid "the mangled name of the initialization guard variable for %qD changes between -fabi-version=%d and -fabi-version=%d"
+#, gcc-internal-format
msgid "the mangled name of the initialization guard variable for %qD changes between %<-fabi-version=%d%> and %<-fabi-version=%d%>"
-msgstr "det manglade namnet på initieringsvaktsvariabeln för %qD ändras mellan -fabi-version=%d och -fabi-version=%d"
+msgstr "det manglade namnet på initieringsvaktsvariabeln för %qD ändras mellan %<-fabi-version=%d%> och %<-fabi-version=%d%>"
#: cp/method.c:831 cp/method.c:1343
#, gcc-internal-format
@@ -44956,10 +44703,9 @@ msgid "due to different exception specifications"
msgstr "på grund av olika undantagsspecifikationer"
#: cp/name-lookup.c:2661
-#, fuzzy, gcc-internal-format
-#| msgid "parameter %qD invalidly declared method type"
+#, gcc-internal-format
msgid "lambda parameter %qD previously declared as a capture"
-msgstr "parameter %qD ogiltigt deklarerad metodtyp"
+msgstr "lambdaparametern %qD är deklarerad tidigare som en fångst"
#: cp/name-lookup.c:2682
#, gcc-internal-format
@@ -45115,10 +44861,9 @@ msgid "maximum limit of %d namespaces searched for %qE"
msgstr "maxgräns på %d namnrymder sökta %qE"
#: cp/name-lookup.c:5347
-#, fuzzy, gcc-internal-format
-#| msgid "%qD declared here"
+#, gcc-internal-format
msgid "%qE declared here"
-msgstr "%qD är deklarerad här"
+msgstr "%qE är deklarerad här"
#: cp/name-lookup.c:5373
#, gcc-internal-format
@@ -45153,8 +44898,7 @@ msgid "it was later defined here"
msgstr "det definierades senare här"
#: cp/name-lookup.c:6899
-#, fuzzy, gcc-internal-format
-#| msgid "declaration of %<std::initializer_list%> does not match %<#include <initializer_list>%>, isn't a template"
+#, gcc-internal-format
msgid "declaration of %<std::initializer_list%> does not match %<#include <initializer_list>%>, isn%'t a template"
msgstr "definitionen av %<std::initializer_list%> matchar inte %<#include <initializer_list>%>, är inte en mall"
@@ -45395,10 +45139,9 @@ msgid "%qs cannot appear in a constant-expression"
msgstr "%qs får inte finnas i ett konstantuttryck"
#: cp/parser.c:3293
-#, fuzzy, gcc-internal-format
-#| msgid "class template argument deduction is only available with -std=c++17 or -std=gnu++17"
+#, gcc-internal-format
msgid "class template argument deduction is only available with %<-std=c++17%> or %<-std=gnu++17%>"
-msgstr "härledning av klassmallargument är endast tillgängligt med -std=c++17 eller -std=gnu++17"
+msgstr "härledning av klassmallargument är endast tillgängligt med %<-std=c++17%> eller %<-std=gnu++17%>"
#: cp/parser.c:3298
#, gcc-internal-format
@@ -45422,28 +45165,24 @@ msgid "%qE does not name a type"
msgstr "%qE är inte namnet på en typ"
#: cp/parser.c:3327
-#, fuzzy, gcc-internal-format
-#| msgid "C++11 %<constexpr%> only available with -std=c++11 or -std=gnu++11"
+#, gcc-internal-format
msgid "C++11 %<constexpr%> only available with %<-std=c++11%> or %<-std=gnu++11%>"
-msgstr "C++11 %<constexpr%> är endast tillgängligt med -std=c++11 eller -std=gnu++11"
+msgstr "C++11 %<constexpr%> är endast tillgängligt med %<-std=c++11%> eller %<-std=gnu++11%>"
#: cp/parser.c:3330
-#, fuzzy, gcc-internal-format
-#| msgid "C++11 %<noexcept%> only available with -std=c++11 or -std=gnu++11"
+#, gcc-internal-format
msgid "C++11 %<noexcept%> only available with %<-std=c++11%> or %<-std=gnu++11%>"
-msgstr "C++11 %<noexcept%> är endast tillgängligt med -std=c++11 eller -std=gnu++11"
+msgstr "C++11 %<noexcept%> är endast tillgängligt med %<-std=c++11%> eller %<-std=gnu++11%>"
#: cp/parser.c:3335
-#, fuzzy, gcc-internal-format
-#| msgid "C++11 %<thread_local%> only available with -std=c++11 or -std=gnu++11"
+#, gcc-internal-format
msgid "C++11 %<thread_local%> only available with %<-std=c++11%> or %<-std=gnu++11%>"
-msgstr "C++11 %<thread_local%> är endast tillgängligt med -std=c++11 eller -std=gnu++11"
+msgstr "C++11 %<thread_local%> är endast tillgängligt med %<-std=c++11%> eller %<-std=gnu++11%>"
#: cp/parser.c:3338
-#, fuzzy, gcc-internal-format
-#| msgid "%<concept%> only available with -fconcepts"
+#, gcc-internal-format
msgid "%<concept%> only available with %<-fconcepts%>"
-msgstr "%<concept%> är endast tillgängligt med -fconcepts"
+msgstr "%<concept%> är endast tillgängligt med %<-fconcepts%>"
#: cp/parser.c:3364
#, gcc-internal-format
@@ -45451,10 +45190,9 @@ msgid "(perhaps %<typename %T::%E%> was intended)"
msgstr "(kanske %<typename %T::%E%> avsågs)"
#: cp/parser.c:3393 cp/parser.c:3405
-#, fuzzy, gcc-internal-format
-#| msgid "%qE in namespace %qE does not name a template type"
+#, gcc-internal-format
msgid "%qE in namespace %qE does not name a template type; did you mean %qs?"
-msgstr "%qE i namnrymden %qE är inte namnet på en malltyp"
+msgstr "%qE i namnrymden %qE är inte namnet på en malltyp; menade du %qs?"
#: cp/parser.c:3398 cp/parser.c:3410
#, gcc-internal-format
@@ -45462,10 +45200,9 @@ msgid "%qE in namespace %qE does not name a template type"
msgstr "%qE i namnrymden %qE är inte namnet på en malltyp"
#: cp/parser.c:3418
-#, fuzzy, gcc-internal-format
-#| msgid "%qE does not name a type; did you mean %qs?"
+#, gcc-internal-format
msgid "%qE in namespace %qE does not name a type; did you mean %qs?"
-msgstr "%qE är inte namnet på en typ; menade du %qs?"
+msgstr "%qE i namnrymden %qE är inte namnet på en typ; menade du %qs?"
#: cp/parser.c:3423
#, gcc-internal-format
@@ -45558,10 +45295,9 @@ msgid "or use %<j%> instead of %<i%> for the GNU built-in suffix"
msgstr "eller använd %<j%> istället för %<i%> som GNU:s inbyggda suffix"
#: cp/parser.c:4557
-#, fuzzy, gcc-internal-format
-#| msgid "use -fext-numeric-literals to enable more built-in suffixes"
+#, gcc-internal-format
msgid "use %<-fext-numeric-literals%> to enable more built-in suffixes"
-msgstr "använd -fext-numeric-literals för att aktivera fler inbyggda suffix"
+msgstr "använd %<-fext-numeric-literals%> för att aktivera fler inbyggda suffix"
#: cp/parser.c:4643
#, gcc-internal-format
@@ -45614,10 +45350,9 @@ msgid "statement-expressions are not allowed outside functions nor in template-a
msgstr "satsuttryck är inte tillåtna utanför funktioner eller i mallargumentlistor"
#: cp/parser.c:5336
-#, fuzzy, gcc-internal-format
-#| msgid "fold-expressions only available with -std=c++17 or -std=gnu++17"
+#, gcc-internal-format
msgid "fold-expressions only available with %<-std=c++17%> or %<-std=gnu++17%>"
-msgstr "vikningsuttryck är endast tillgängliga med -std=c++17 eller -std=gnu++17"
+msgstr "vikningsuttryck är endast tillgängliga med %<-std=c++17%> eller %<-std=gnu++17%>"
#: cp/parser.c:5394 cp/parser.c:5571 cp/parser.c:5746 cp/semantics.c:3693
#, gcc-internal-format
@@ -45650,10 +45385,9 @@ msgid "scope %qT before %<~%> is not a class-name"
msgstr "räckvidd %qT före %<~%> är inte ett klassnamn"
#: cp/parser.c:6074 cp/parser.c:8008
-#, fuzzy, gcc-internal-format
-#| msgid "%<~auto%> only available with -std=c++14 or -std=gnu++14"
+#, gcc-internal-format
msgid "%<~auto%> only available with %<-std=c++14%> or %<-std=gnu++14%>"
-msgstr "%<~auto%> är endast tillgängligt med -std=c++14 eller -std=gnu++14"
+msgstr "%<~auto%> är endast tillgängligt med %<-std=c++14%> eller %<-std=gnu++14%>"
#: cp/parser.c:6185
#, gcc-internal-format
@@ -45756,10 +45490,9 @@ msgid "types may not be defined in %<noexcept%> expressions"
msgstr "typer får inte definieras i %<noexcept%>-uttryck"
#: cp/parser.c:8527 cp/parser.c:28948
-#, fuzzy, gcc-internal-format
-#| msgid "types may not be defined in a new-expression"
+#, gcc-internal-format
msgid "types may not be defined in %qs expressions"
-msgstr "typer får inte definieras i en new-uttryck"
+msgstr "typer får inte definieras i en %qs-uttryck"
#: cp/parser.c:8675
#, gcc-internal-format
@@ -45817,28 +45550,24 @@ msgid "ISO C++ does not allow ?: with omitted middle operand"
msgstr "ISO C++ tillåter inte ?: med mellersta operanden utelämnad"
#: cp/parser.c:10107
-#, fuzzy, gcc-internal-format
-#| msgid "types may not be defined within __builtin_offsetof"
+#, gcc-internal-format
msgid "types may not be defined within %<__builtin_offsetof%>"
-msgstr "typer får inte definieras i __builtin_offsetof"
+msgstr "typer får inte definieras i %<__builtin_offsetof%>"
#: cp/parser.c:10396
-#, fuzzy, gcc-internal-format
-#| msgid "lambda templates are only available with -std=c++2a or -std=gnu++2a"
+#, gcc-internal-format
msgid "lambda-expression in unevaluated context only available with %<-std=c++2a%> or %<-std=gnu++2a%>"
-msgstr "lambdamallar är endast tillgängliga med -std=c++2a eller -std=gnu++2a"
+msgstr "lambdauttryck i oberäknade sammanhang är endast tillgängliga med %<-std=c++2a%> eller %<-std=gnu++2a%>"
#: cp/parser.c:10406
-#, fuzzy, gcc-internal-format
-#| msgid "lambda templates are only available with -std=c++2a or -std=gnu++2a"
+#, gcc-internal-format
msgid "lambda-expression in template-argument only available with %<-std=c++2a%> or %<-std=gnu++2a%>"
-msgstr "lambdamallar är endast tillgängliga med -std=c++2a eller -std=gnu++2a"
+msgstr "lambdauttryck i mallargument är endast tillgängliga med %<-std=c++2a%> eller %<-std=gnu++2a%>"
#: cp/parser.c:10551
-#, fuzzy, gcc-internal-format
-#| msgid "the lambda has no capture-default"
+#, gcc-internal-format
msgid "non-local lambda expression cannot have a capture-default"
-msgstr "lambdat har ingen standardfångst"
+msgstr "icke-lokala lambda-uttryck kan inte ha en standardfångst"
#: cp/parser.c:10573
#, gcc-internal-format
@@ -45856,22 +45585,19 @@ msgid "already captured %qD in lambda expression"
msgstr "redan infångad %qD i lambdauttryck"
#: cp/parser.c:10608
-#, fuzzy, gcc-internal-format
-#| msgid "%<*this%> capture only available with -std=c++17 or -std=gnu++17"
+#, gcc-internal-format
msgid "%<*this%> capture only available with %<-std=c++17%> or %<-std=gnu++17%>"
-msgstr "fångst av %<*this%> är endast tillgängligt med -std=c++17 eller -std=gnu++17"
+msgstr "fångst av %<*this%> är endast tillgängligt med %<-std=c++17%> eller %<-std=gnu++17%>"
#: cp/parser.c:10629
-#, fuzzy, gcc-internal-format
-#| msgid "lambda templates are only available with -std=c++2a or -std=gnu++2a"
+#, gcc-internal-format
msgid "pack init-capture only available with %<-std=c++2a%> or %<-std=gnu++2a%>"
-msgstr "lambdamallar är endast tillgängliga med -std=c++2a eller -std=gnu++2a"
+msgstr "pack init-fångst är endast tillgängliga med %<-std=c++2a%> eller %<-std=gnu++2a%>"
#: cp/parser.c:10668
-#, fuzzy, gcc-internal-format
-#| msgid "lambda capture initializers only available with -std=c++14 or -std=gnu++14"
+#, gcc-internal-format
msgid "lambda capture initializers only available with %<-std=c++14%> or %<-std=gnu++14%>"
-msgstr "lambdafångstinitierare är endast tillgängliga med -std=c++14 eller -std=gnu++14"
+msgstr "lambdafångstinitierare är endast tillgängliga med %<-std=c++14%> eller %<-std=gnu++14%>"
#: cp/parser.c:10675
#, gcc-internal-format
@@ -45894,10 +45620,9 @@ msgid "capture of variable %qD with non-automatic storage duration"
msgstr "fångst av variabeln %qD med ej automatisk lagringsvaraktighet"
#: cp/parser.c:10747
-#, fuzzy, gcc-internal-format
-#| msgid "too many %<if%> clauses"
+#, gcc-internal-format
msgid "too many %<...%> in lambda capture"
-msgstr "för många %<if%>-klausuler"
+msgstr "för många %<...%> i lambdafångst"
#: cp/parser.c:10758
#, gcc-internal-format
@@ -45910,16 +45635,14 @@ msgid "explicit by-reference capture of %qD redundant with by-reference capture
msgstr "explicit fångst via referens av %qD överflödigt med standardfångst via referens"
#: cp/parser.c:10837
-#, fuzzy, gcc-internal-format
-#| msgid "lambda templates are only available with -std=c++14 or -std=gnu++14"
+#, gcc-internal-format
msgid "lambda templates are only available with %<-std=c++14%> or %<-std=gnu++14%>"
-msgstr "lambdamallar är endast tillgängliga med -std=c++14 eller -std=gnu++14"
+msgstr "lambdamallar är endast tillgängliga med %<-std=c++14%> eller %<-std=gnu++14%>"
#: cp/parser.c:10841
-#, fuzzy, gcc-internal-format
-#| msgid "lambda templates are only available with -std=c++2a or -std=gnu++2a"
+#, gcc-internal-format
msgid "lambda templates are only available with %<-std=c++2a%> or %<-std=gnu++2a%>"
-msgstr "lambdamallar är endast tillgängliga med -std=c++2a eller -std=gnu++2a"
+msgstr "lambdamallar är endast tillgängliga med %<-std=c++2a%> eller %<-std=gnu++2a%>"
#: cp/parser.c:10875
#, gcc-internal-format
@@ -45932,10 +45655,9 @@ msgid "duplicate %<mutable%>"
msgstr "dubblerad %<mutable%>"
#: cp/parser.c:10940
-#, fuzzy, gcc-internal-format
-#| msgid "%<constexpr%> lambda only available with -std=c++17 or -std=gnu++17"
+#, gcc-internal-format
msgid "%<constexpr%> lambda only available with %<-std=c++17%> or %<-std=gnu++17%>"
-msgstr "%<constexpr%> lambda är endast tillgängligt med -std=c++17 eller -std=gnu++17"
+msgstr "%<constexpr%> lambda är endast tillgängligt med %<-std=c++17%> eller %<-std=gnu++17%>"
#: cp/parser.c:11339 cp/parser.c:11540
#, gcc-internal-format
@@ -45968,16 +45690,14 @@ msgid "compound-statement in %<constexpr%> function"
msgstr "sammansatt sats i en %<constexpr%>-funktion"
#: cp/parser.c:11765
-#, fuzzy, gcc-internal-format
-#| msgid "%<if constexpr%> only available with -std=c++17 or -std=gnu++17"
+#, gcc-internal-format
msgid "%<if constexpr%> only available with %<-std=c++17%> or %<-std=gnu++17%>"
-msgstr "%<if constexpr%> är endast tillgängligt med -std=c++17 eller -std=gnu++17"
+msgstr "%<if constexpr%> är endast tillgängligt med %<-std=c++17%> eller %<-std=gnu++17%>"
#: cp/parser.c:11792
-#, fuzzy, gcc-internal-format
-#| msgid "init-statement in selection statements only available with -std=c++17 or -std=gnu++17"
+#, gcc-internal-format
msgid "init-statement in selection statements only available with %<-std=c++17%> or %<-std=gnu++17%>"
-msgstr "init-satsen i valsatser är endast tillgängliga med -std=c++17 eller -std=gnu++17"
+msgstr "init-satsen i valsatser är endast tillgängliga med %<-std=c++17%> eller %<-std=gnu++17%>"
#: cp/parser.c:11962 cp/parser.c:29418
#, gcc-internal-format
@@ -45985,16 +45705,14 @@ msgid "expected selection-statement"
msgstr "selektionssats förväntades"
#: cp/parser.c:11999
-#, fuzzy, gcc-internal-format
-#| msgid "function returning an array"
+#, gcc-internal-format
msgid "condition declares an array"
-msgstr "funktion som returnerar en vektor"
+msgstr "villkor deklarerar en vektor"
#: cp/parser.c:12001
-#, fuzzy, gcc-internal-format
-#| msgid "field %qE declared as a function"
+#, gcc-internal-format
msgid "condition declares a function"
-msgstr "fältet %qE deklarerat som en funktion"
+msgstr "villkor deklarerar en funktion"
#: cp/parser.c:12041
#, gcc-internal-format
@@ -46023,16 +45741,14 @@ msgid "expected iteration-statement"
msgstr "iterationssats förväntades"
#: cp/parser.c:12779
-#, fuzzy, gcc-internal-format
-#| msgid "range-based %<for%> loops only available with -std=c++11 or -std=gnu++11"
+#, gcc-internal-format
msgid "range-based %<for%> loops with initializer only available with %<-std=c++2a%> or %<-std=gnu++2a%>"
-msgstr "intervallbaserad %<for%>-slinga är endast tillgänglig med -std=c++11 eller -std=gnu++11"
+msgstr "intervallbaserade %<for%>-slingor med initierare är endast tillgängliga med %<-std=c++2a%> eller %<-std=gnu++2a%>"
#: cp/parser.c:12803
-#, fuzzy, gcc-internal-format
-#| msgid "range-based %<for%> loops only available with -std=c++11 or -std=gnu++11"
+#, gcc-internal-format
msgid "range-based %<for%> loops only available with %<-std=c++11%> or %<-std=gnu++11%>"
-msgstr "intervallbaserad %<for%>-slinga är endast tillgänglig med -std=c++11 eller -std=gnu++11"
+msgstr "intervallbaserad %<for%>-slinga är endast tillgänglig med %<-std=c++11%> eller %<-std=gnu++11%>"
#: cp/parser.c:12929
#, gcc-internal-format
@@ -46091,10 +45807,9 @@ msgid "multiple declarations in range-based %<for%> loop"
msgstr "flera deklarationer i intervallbaserad %<for%>-slinga"
#: cp/parser.c:13745
-#, fuzzy, gcc-internal-format
-#| msgid "structured bindings only available with -std=c++17 or -std=gnu++17"
+#, gcc-internal-format
msgid "structured bindings only available with %<-std=c++17%> or %<-std=gnu++17%>"
-msgstr "strukturerade bindningar är endast tillgängliga med -std=c++17 eller -std=gnu++17"
+msgstr "strukturerade bindningar är endast tillgängliga med %<-std=c++17%> eller %<-std=gnu++17%>"
#: cp/parser.c:13797
#, gcc-internal-format
@@ -46127,10 +45842,9 @@ msgid "%qD invalid in lambda"
msgstr "%qD är ogiltigt i lambda"
#: cp/parser.c:14178
-#, fuzzy, gcc-internal-format
-#| msgid "decl-specifier invalid in condition"
+#, gcc-internal-format
msgid "type-specifier invalid in lambda"
-msgstr "decl-specificerare är ogiltig i villkor"
+msgstr "typspecificerare är ogiltig i lambda"
#: cp/parser.c:14197
#, gcc-internal-format
@@ -46143,16 +45857,14 @@ msgid "templates may not be %<virtual%>"
msgstr "mallar får inte vara %<virtual%>"
#: cp/parser.c:14289
-#, fuzzy, gcc-internal-format
-#| msgid "types may not be defined in an exception-specification"
+#, gcc-internal-format
msgid "types may not be defined in explicit-specifier"
-msgstr "typer får inte definieras i en undantagsspecifikation"
+msgstr "typer får inte definieras i en explicit-specificerare"
#: cp/parser.c:14293
-#, fuzzy, gcc-internal-format
-#| msgid "%<~auto%> only available with -std=c++14 or -std=gnu++14"
+#, gcc-internal-format
msgid "%<explicit(bool)%> only available with %<-std=c++2a%> or %<-std=gnu++2a%>"
-msgstr "%<~auto%> är endast tillgängligt med -std=c++14 eller -std=gnu++14"
+msgstr "%<explicit(bool)%> är endast tillgängligt med %<-std=c++2a%> eller %<-std=gnu++2a%>"
#: cp/parser.c:14357
#, gcc-internal-format
@@ -46160,10 +45872,9 @@ msgid "invalid linkage-specification"
msgstr "ogiltig länkklasspecifikation"
#: cp/parser.c:14461
-#, fuzzy, gcc-internal-format
-#| msgid "static_assert without a message only available with -std=c++17 or -std=gnu++17"
+#, gcc-internal-format
msgid "static_assert without a message only available with %<-std=c++17%> or %<-std=gnu++17%>"
-msgstr "static_assert utan ett meddelande är endast tillgänglig med -std=c++17 eller -std=gnu++17"
+msgstr "static_assert utan ett meddelande är endast tillgänglig med %<-std=c++17%> eller %<-std=gnu++17%>"
#: cp/parser.c:14663
#, gcc-internal-format
@@ -46297,10 +46008,9 @@ msgid "(if you use %<-fpermissive%> or %<-std=c++11%>, or %<-std=gnu++11%> G++ w
msgstr "(om du använder %<-fpermissive%> eller %<-std=c++11%> eller %<-std=gnu++11%> kommer G++ acceptera din kod)"
#: cp/parser.c:16426
-#, fuzzy, gcc-internal-format
-#| msgid "invalid non-type template argument"
+#, gcc-internal-format
msgid "invalid template-argument-list"
-msgstr "ogiltigt mallargument som inte är en typ"
+msgstr "felaktig mallargumentlista"
#: cp/parser.c:16427
#, gcc-internal-format
@@ -46308,10 +46018,9 @@ msgid "function name as the left hand operand of %<<%> is ill-formed in C++2a; w
msgstr "ett funktionsnamn som vänster operand av %<<%> är felformad i C++2a; slå in funktionsnamnet i %<()%>"
#: cp/parser.c:16434
-#, fuzzy, gcc-internal-format
-#| msgid "expected template-argument"
+#, gcc-internal-format
msgid "expected %<(%> after template-argument-list"
-msgstr "mallargument förväntades"
+msgstr "%<(%> förväntadess efter mallargumentlista"
#: cp/parser.c:16540
#, gcc-internal-format
@@ -46371,22 +46080,19 @@ msgid "expected type specifier"
msgstr "typspecificerare förväntades"
#: cp/parser.c:17702
-#, fuzzy, gcc-internal-format
-#| msgid "use of %<auto%> in lambda parameter declaration only available with -std=c++14 or -std=gnu++14"
+#, gcc-internal-format
msgid "use of %<auto%> in lambda parameter declaration only available with %<-std=c++14%> or %<-std=gnu++14%>"
-msgstr "användning av %<auto%> i lambdaparameterdeklarationer är endast tillgängligt med -std=c++14 eller -std=gnu++14"
+msgstr "användning av %<auto%> i lambdaparameterdeklarationer är endast tillgängligt med %<-std=c++14%> eller %<-std=gnu++14%>"
#: cp/parser.c:17708
-#, fuzzy, gcc-internal-format
-#| msgid "use of %<auto%> in parameter declaration only available with -std=c++14 or -std=gnu++14"
+#, gcc-internal-format
msgid "use of %<auto%> in parameter declaration only available with %<-std=c++14%> or %<-std=gnu++14%>"
-msgstr "användning av %<auto%> i parameterdeklarationer är endast tillgängligt med -std=c++14 eller -std=gnu++14"
+msgstr "användning av %<auto%> i parameterdeklarationer är endast tillgängligt med %<-std=c++14%> eller %<-std=gnu++14%>"
#: cp/parser.c:17713
-#, fuzzy, gcc-internal-format
-#| msgid "use of %<auto%> in parameter declaration only available with -fconcepts"
+#, gcc-internal-format
msgid "use of %<auto%> in parameter declaration only available with %<-fconcepts%>"
-msgstr "användning av %<auto%> i parameterdeklarationer är endast tillgängligt med -fconcepts"
+msgstr "användning av %<auto%> i parameterdeklarationer är endast tillgängligt med %<-fconcepts%>"
#: cp/parser.c:17866
#, gcc-internal-format
@@ -46404,10 +46110,9 @@ msgid "elaborated-type-specifier for a scoped enum must not use the %qD keyword"
msgstr "beräknad typspecifikation för en enum med räckvidd får inte använda nyckelordet %qD"
#: cp/parser.c:18353
-#, fuzzy, gcc-internal-format
-#| msgid "typedef name may not be a nested-name-specifier"
+#, gcc-internal-format
msgid "%<template%> must follow a nested-name-specifier"
-msgstr "typedef-namn får inte vara en nästad-namnspecificerare"
+msgstr "%<template%> måste följa en nästad-namnspecificerare"
#: cp/parser.c:18514
#, gcc-internal-format
@@ -46495,10 +46200,9 @@ msgid "opaque-enum-specifier must use a simple identifier"
msgstr "en ogenomskinlig enum-specifikation måste använda en enkel identifierare"
#: cp/parser.c:19170
-#, fuzzy, gcc-internal-format
-#| msgid "%qE does not name a type; did you mean %qs?"
+#, gcc-internal-format
msgid "%qD is not a namespace-name; did you mean %qs?"
-msgstr "%qE är inte namnet på en typ; menade du %qs?"
+msgstr "%qD är inte ett namnrymdsnamn; menade du %qs?"
#: cp/parser.c:19174
#, gcc-internal-format
@@ -46511,10 +46215,9 @@ msgid "expected namespace-name"
msgstr "namnrymdsnamn förväntades"
#: cp/parser.c:19239
-#, fuzzy, gcc-internal-format
-#| msgid "nested namespace definitions only available with -std=c++17 or -std=gnu++17"
+#, gcc-internal-format
msgid "nested inline namespace definitions only available with %<-std=c++2a%> or %<-std=gnu++2a%>"
-msgstr "nästade namnrymdsdefinitioner är endast tillgängliga med -std=c++17 eller -std=gnu++17"
+msgstr "nästade inline-namnrymdsdefinitioner är endast tillgängliga med %<-std=c++2a%> eller %<-std=gnu++2a%>"
#: cp/parser.c:19250
#, gcc-internal-format
@@ -46522,10 +46225,9 @@ msgid "standard attributes on namespaces must precede the namespace name"
msgstr "standardattribut på namnrymder måste föregå namnrymdsnamnet"
#: cp/parser.c:19269
-#, fuzzy, gcc-internal-format
-#| msgid "nested namespace definitions only available with -std=c++17 or -std=gnu++17"
+#, gcc-internal-format
msgid "nested namespace definitions only available with %<-std=c++17%> or %<-std=gnu++17%>"
-msgstr "nästade namnrymdsdefinitioner är endast tillgängliga med -std=c++17 eller -std=gnu++17"
+msgstr "nästade namnrymdsdefinitioner är endast tillgängliga med %<-std=c++17%> eller %<-std=gnu++17%>"
#: cp/parser.c:19279
#, gcc-internal-format
@@ -46558,10 +46260,9 @@ msgid "%<namespace%> definition is not allowed here"
msgstr "%<namespace%>-definition är inte tillåten här"
#: cp/parser.c:19505
-#, fuzzy, gcc-internal-format
-#| msgid "pack expansion in using-declaration only available with -std=c++17 or -std=gnu++17"
+#, gcc-internal-format
msgid "pack expansion in using-declaration only available with %<-std=c++17%> or %<-std=gnu++17%>"
-msgstr "paketexpansion i using-deklaration är endast tillgängligt med -std=c++17 eller -std=gnu++17"
+msgstr "paketexpansion i using-deklaration är endast tillgängligt med %<-std=c++17%> eller %<-std=gnu++17%>"
#: cp/parser.c:19520
#, gcc-internal-format
@@ -46569,10 +46270,9 @@ msgid "a template-id may not appear in a using-declaration"
msgstr "ett mall-id får inte förekomma i en using-deklaration"
#: cp/parser.c:19567
-#, fuzzy, gcc-internal-format
-#| msgid "comma-separated list in using-declaration only available with -std=c++17 or -std=gnu++17"
+#, gcc-internal-format
msgid "comma-separated list in using-declaration only available with %<-std=c++17%> or %<-std=gnu++17%>"
-msgstr "en kommaseparerad lista i using-deklaration är endast tillgängligt med -std=c++17 eller -std=gnu++17"
+msgstr "en kommaseparerad lista i using-deklaration är endast tillgängligt med %<-std=c++17%> eller %<-std=gnu++17%>"
#: cp/parser.c:19577
#, gcc-internal-format
@@ -46590,28 +46290,24 @@ msgid "%<asm%> in %<constexpr%> function"
msgstr "%<asm%> i %<constexpr%>-funktion"
#: cp/parser.c:19840 cp/parser.c:19856 cp/parser.c:19869
-#, fuzzy, gcc-internal-format
-#| msgid "duplicate cv-qualifier"
+#, gcc-internal-format
msgid "duplicate asm qualifier %qT"
-msgstr "upprepade cv-kvalificerare"
+msgstr "dubblerad asm-kvalificerare %qT"
#: cp/parser.c:19846
-#, fuzzy, gcc-internal-format
-#| msgid "type qualifiers ignored on function return type"
+#, gcc-internal-format
msgid "asm qualifier %qT ignored outside of function body"
-msgstr "typkvalificerare ignoreras för funktions returtyp"
+msgstr "asm-kvalificeraren %qT ignoreras utanför en funktionskropp"
#: cp/parser.c:19881
-#, fuzzy, gcc-internal-format
-#| msgid "%qT is not a namespace"
+#, gcc-internal-format
msgid "%qT is not an asm qualifier"
-msgstr "%qT är inte en namnrymd"
+msgstr "%qT är inte en asm-kvalificerare"
#: cp/parser.c:19897
-#, fuzzy, gcc-internal-format
-#| msgid "use of parameter outside function body"
+#, gcc-internal-format
msgid "asm qualifier outside of function body"
-msgstr "användning av parameter utanför funktionskroppen"
+msgstr "asm-kvalificerare utanför funktionskropp"
#: cp/parser.c:20268
#, gcc-internal-format
@@ -46785,22 +46481,19 @@ msgid "parameter pack cannot have a default argument"
msgstr "parameterpaket kan inte ha ett standardargument"
#: cp/parser.c:22685
-#, fuzzy, gcc-internal-format
-#| msgid "%<if constexpr%> only available with -std=c++17 or -std=gnu++17"
+#, gcc-internal-format
msgid "function-try-block body of %<constexpr%> constructor only available with %<-std=c++2a%> or %<-std=gnu++2a%>"
-msgstr "%<if constexpr%> är endast tillgängligt med -std=c++17 eller -std=gnu++17"
+msgstr "funktions-try-blockskropp av %<constexpr%>-konstruerare är endast tillgängligt med %<-std=c++2a%> eller %<-std=gnu++2a%>"
#: cp/parser.c:22689
-#, fuzzy, gcc-internal-format
-#| msgid "%<if constexpr%> only available with -std=c++17 or -std=gnu++17"
+#, gcc-internal-format
msgid "function-try-block body of %<constexpr%> function only available with %<-std=c++2a%> or %<-std=gnu++2a%>"
-msgstr "%<if constexpr%> är endast tillgängligt med -std=c++17 eller -std=gnu++17"
+msgstr "funktions-try-blockskropp av %<constexpr%>-funktioner är endast tillgängligt med %<-std=c++2a%> eller %<-std=gnu++2a%>"
#: cp/parser.c:23010
-#, fuzzy, gcc-internal-format
-#| msgid "C++ designated initializers only available with -std=c++2a or -std=gnu++2a"
+#, gcc-internal-format
msgid "C++ designated initializers only available with %<-std=c++2a%> or %<-std=gnu++2a%>"
-msgstr "C++ designerade initierare är endast tillgängliga med -std=c++2a eller -std=gnu++2a"
+msgstr "C++ designerade initierare är endast tillgängliga med %<-std=c++2a%> eller %<-std=gnu++2a%>"
#: cp/parser.c:23030
#, gcc-internal-format
@@ -46903,10 +46596,9 @@ msgid "expected class-key"
msgstr "klassnyckel förväntades"
#: cp/parser.c:24227
-#, fuzzy, gcc-internal-format
-#| msgid "ISO C++ forbids typename key in template template parameter; use -std=c++17 or -std=gnu++17"
+#, gcc-internal-format
msgid "ISO C++ forbids typename key in template template parameter; use %<-std=c++17%> or %<-std=gnu++17%>"
-msgstr "ISO C++ förbjuder nyckelordet typename i mall-mall-parameter; använd -std=c++17 eller -std=gnu++17"
+msgstr "ISO C++ förbjuder nyckelordet typename i mall-mall-parameter; använd %<-std=c++17%> eller %<-std=gnu++17%>"
#: cp/parser.c:24231
#, gcc-internal-format
@@ -46929,10 +46621,9 @@ msgid "a storage class on an anonymous aggregate in class scope is not allowed"
msgstr "en lagringklass på ett anonymt aggregat i klassräckvidd tillåts inte"
#: cp/parser.c:24613
-#, fuzzy, gcc-internal-format
-#| msgid "default member initializers for bit-fields only available with -std=c++2a or -std=gnu++2a"
+#, gcc-internal-format
msgid "default member initializers for bit-fields only available with %<-std=c++2a%> or %<-std=gnu++2a%>"
-msgstr "standardmedlemsinitierare för bitfält är endast tillgängliga med -std=c++2a eller -std=gnu++2a"
+msgstr "standardmedlemsinitierare för bitfält är endast tillgängliga med %<-std=c++2a%> eller %<-std=gnu++2a%>"
#: cp/parser.c:24620
#, gcc-internal-format
@@ -47015,10 +46706,9 @@ msgid "invalid use of %<auto%> in exception-specification"
msgstr "ogiltig användning av %<auto%> i undantagsspecifikation"
#: cp/parser.c:25438
-#, fuzzy, gcc-internal-format
-#| msgid "%<if constexpr%> only available with -std=c++17 or -std=gnu++17"
+#, gcc-internal-format
msgid "%<try%> in %<constexpr%> function only available with %<-std=c++2a%> or %<-std=gnu++2a%>"
-msgstr "%<if constexpr%> är endast tillgängligt med -std=c++17 eller -std=gnu++17"
+msgstr "%<try%> i %<constexpr%>-funktioner är endast tillgängligt med %<-std=c++2a%> eller %<-std=gnu++2a%>"
#: cp/parser.c:25550
#, gcc-internal-format
@@ -47051,16 +46741,14 @@ msgid "expected attribute before %<...%>"
msgstr "attribut förväntades före %<...%>"
#: cp/parser.c:26317
-#, fuzzy, gcc-internal-format
-#| msgid "attribute using prefix only available with -std=c++17 or -std=gnu++17"
+#, gcc-internal-format
msgid "attribute using prefix only available with %<-std=c++17%> or %<-std=gnu++17%>"
-msgstr "attribut som använder prefix är endast tillgängligt med -std=c++17 eller -std=gnu++17"
+msgstr "attribut som använder prefix är endast tillgängligt med %<-std=c++17%> eller %<-std=gnu++17%>"
#: cp/parser.c:26641
-#, fuzzy, gcc-internal-format
-#| msgid "%<requires%> only available with -fconcepts"
+#, gcc-internal-format
msgid "%<requires%> only available with %<-fconcepts%>"
-msgstr "%<requires%> är endast tillgängligt med -fconcepts"
+msgstr "%<requires%> är endast tillgängligt med %<-fconcepts%>"
#: cp/parser.c:26673
#, gcc-internal-format
@@ -47102,16 +46790,14 @@ msgid "ISO C++ did not adopt string literal operator templates taking an argumen
msgstr "ISO C++ antog inte mallar för strängliteralsoperatorer som tar argumentpaket av tecken"
#: cp/parser.c:27934
-#, fuzzy, gcc-internal-format
-#| msgid "literal operator template %qD has invalid parameter list. Expected non-type template argument pack <char...> or <typename CharT, CharT...>"
+#, gcc-internal-format
msgid "literal operator template %qD has invalid parameter list; Expected non-type template parameter pack <char...> or single non-type parameter of class type"
-msgstr "den litterala operatormallen %qD har ogiltig parameterlista. Ett mallargument som inte är en typ pack <char...> eller <typename CharT, CharT...> förväntades"
+msgstr "den litterala operatormallen %qD har ogiltig parameterlista. Ett mallargument som inte är en typ pack <char...> eller en ensam icke-typparameter av klasstyp"
#: cp/parser.c:27939
-#, fuzzy, gcc-internal-format
-#| msgid "literal operator template %qD has invalid parameter list. Expected non-type template argument pack <char...>"
+#, gcc-internal-format
msgid "literal operator template %qD has invalid parameter list. Expected non-type template parameter pack <char...>"
-msgstr "den litterala operatormallen %qD har ogiltig parameterlista. Ett mallargument som inte är en typ pack <char...> förväntades"
+msgstr "den litterala operatormallen %qD har ogiltig parameterlista. En mallparameter som inte är en typ pack <char...> förväntades"
#: cp/parser.c:28033
#, gcc-internal-format
@@ -47420,10 +47106,9 @@ msgid "invalid type for property"
msgstr "ogiltig typ på egenskap"
#: cp/parser.c:32966
-#, fuzzy, gcc-internal-format
-#| msgid "expected integer expression"
+#, gcc-internal-format
msgid "expected integer expression list"
-msgstr "heltalsuttryck förväntades"
+msgstr "heltalsuttryckslista förväntades"
#: cp/parser.c:32983
#, gcc-internal-format
@@ -47436,10 +47121,9 @@ msgid "invalid reduction-identifier"
msgstr "ogiltig reduktionsidentifierare"
#: cp/parser.c:34526
-#, fuzzy, gcc-internal-format
-#| msgid "types may not be defined in parameter types"
+#, gcc-internal-format
msgid "types may not be defined in iterator type"
-msgstr "typer får inte definieras i parametertyper"
+msgstr "typer får inte definieras i iteratortyp"
#: cp/parser.c:36497
#, gcc-internal-format
@@ -47447,10 +47131,9 @@ msgid "parenthesized initialization is not allowed in OpenMP %<for%> loop"
msgstr "initiering i parenteser är inte tillåtet i en OpenMP-%<for%>-slinga"
#: cp/parser.c:36986
-#, fuzzy, gcc-internal-format
-#| msgid "%<ordered%> clause with parameter may not be specified on %qs construct"
+#, gcc-internal-format
msgid "%<ordered%> clause with parameter on range-based %<for%> loop"
-msgstr "en %<ordered%>-klausul med parameter får inte anges på en %qs-konstruktion"
+msgstr "en %<ordered%>-klausul med parameter på en intervallbaserat %<for%>-slinga"
#: cp/parser.c:37072 cp/pt.c:16764
#, gcc-internal-format
@@ -47671,10 +47354,9 @@ msgid "ambiguous template specialization %qD for %q+D"
msgstr "tvetydig mallspecialisering %qD för %q+D"
#: cp/pt.c:2637
-#, fuzzy, gcc-internal-format
-#| msgid "variable templates only available with -std=c++14 or -std=gnu++14"
+#, gcc-internal-format
msgid "variable templates only available with %<-std=c++14%> or %<-std=gnu++14%>"
-msgstr "variabelmallar är endast tillgängliga med -std=c++14 eller -std=gnu++14"
+msgstr "variabelmallar är endast tillgängliga med %<-std=c++14%> eller %<-std=gnu++14%>"
#: cp/pt.c:2647
#, gcc-internal-format
@@ -47813,16 +47495,14 @@ msgid "base initializer expansion %qT contains no parameter packs"
msgstr "basinitierarexpansionen %qT innehåller inga parameterpaket"
#: cp/pt.c:4012
-#, fuzzy, gcc-internal-format
-#| msgid "expansion pattern %qT contains no argument packs"
+#, gcc-internal-format
msgid "expansion pattern %qT contains no parameter packs"
-msgstr "expansionsmönster %qT innehåller inga argumentpaket"
+msgstr "expansionsmönster %qT innehåller inga parameterpaket"
#: cp/pt.c:4014
-#, fuzzy, gcc-internal-format
-#| msgid "expansion pattern %qE contains no argument packs"
+#, gcc-internal-format
msgid "expansion pattern %qE contains no parameter packs"
-msgstr "expansionsmönster %qE innehåller inga argumentpaket"
+msgstr "expansionsmönster %qE innehåller inga parameterpaket"
#: cp/pt.c:4066
#, gcc-internal-format
@@ -47950,10 +47630,9 @@ msgid "default template arguments may not be used in template friend declaration
msgstr "standardmallargument får inte användas i vändeklarerade mallar"
#: cp/pt.c:5320
-#, fuzzy, gcc-internal-format
-#| msgid "default template arguments may not be used in function templates without -std=c++11 or -std=gnu++11"
+#, gcc-internal-format
msgid "default template arguments may not be used in function templates without %<-std=c++11%> or %<-std=gnu++11%>"
-msgstr "standarmallargument får inte användas i funktionsmallar utan -std=c++11 eller -std=gnu++11"
+msgstr "standarmallargument får inte användas i funktionsmallar utan %<-std=c++11%> eller %<-std=gnu++11%>"
#: cp/pt.c:5323
#, gcc-internal-format
@@ -48119,8 +47798,7 @@ msgid "because it is a member of %qT"
msgstr "för att den är en medlem av %qT"
#: cp/pt.c:6393
-#, fuzzy, gcc-internal-format
-#| msgid " couldn't deduce template parameter %qD"
+#, gcc-internal-format
msgid " couldn%'t deduce template parameter %qD"
msgstr " kunde inte härleda mallparametrar %qD"
@@ -48202,8 +47880,7 @@ msgid " template parameters of a template template argument are inconsistent wi
msgstr " mallparametrarna till ett mallmallargument är inkonsistenta med andra härledda mallargument"
#: cp/pt.c:6569
-#, fuzzy, gcc-internal-format
-#| msgid " can't deduce a template for %qT from non-template type %qT"
+#, gcc-internal-format
msgid " can%'t deduce a template for %qT from non-template type %qT"
msgstr " det går inte att härleda en mall för %qT från typen %qT som inte är en mall"
@@ -48218,10 +47895,9 @@ msgid "%qE is not a valid template argument of type %qT because %qE is not a var
msgstr "%qE är inte ett giltigt mallargument för typen %qT eftersom %qE inte är en variabel"
#: cp/pt.c:6632
-#, fuzzy, gcc-internal-format
-#| msgid "%qE is not a valid template argument of type %qT because %qD does not have external linkage"
+#, gcc-internal-format
msgid "%qE is not a valid template argument of type %qT in C++98 because %qD does not have external linkage"
-msgstr "%qE är inte ett giltigt mallargument av typ %qT eftersom %qD inte har extern länkklass"
+msgstr "%qE är inte ett giltigt mallargument av typ %qT i C++98 eftersom %qD inte har extern länkklass"
#: cp/pt.c:6641
#, gcc-internal-format
@@ -48434,10 +48110,9 @@ msgid "use of invalid variable template %qE"
msgstr "användning av felaktig variabelmall %qE"
#: cp/pt.c:10246
-#, fuzzy, gcc-internal-format
-#| msgid "template instantiation depth exceeds maximum of %d (use -ftemplate-depth= to increase the maximum)"
+#, gcc-internal-format
msgid "template instantiation depth exceeds maximum of %d (use %<-ftemplate-depth=%> to increase the maximum)"
-msgstr "mallinstansieringsdjupet överskrider maxvärdet på %d (använd -ftemplate-depth= för att öka maxvärdet)"
+msgstr "mallinstansieringsdjupet överskrider maxvärdet på %d (använd %<-ftemplate-depth=%> för att öka maxvärdet)"
#: cp/pt.c:11326
#, gcc-internal-format
@@ -48450,10 +48125,9 @@ msgid "fold of empty expansion over %O"
msgstr "fold över tom expansion över %O"
#: cp/pt.c:12203
-#, fuzzy, gcc-internal-format
-#| msgid "%qE is not at beginning of declaration"
+#, gcc-internal-format
msgid "%qE is not the entire pattern of the pack expansion"
-msgstr "%qE är inte i början av deklarationen"
+msgstr "%qE är inte hela mönstret av paketexpansionen"
#: cp/pt.c:12293
#, gcc-internal-format
@@ -48599,10 +48273,9 @@ msgid "say %<typename %E%> if a type is meant"
msgstr "säg %<typename %E%> om en typ avses"
#: cp/pt.c:15497
-#, fuzzy, gcc-internal-format
-#| msgid "initializer element is not a constant expression"
+#, gcc-internal-format
msgid "initializer for %q#D expands to an empty list of expressions"
-msgstr "initierarelement är inte ett konstant uttryck"
+msgstr "initierare för %q#D expanderar till en tom uttryckslista"
#: cp/pt.c:15620
#, gcc-internal-format
@@ -48645,10 +48318,9 @@ msgid "%qD declared here, later in the translation unit"
msgstr "%qD är deklarerad här, senare i översättningsenheten"
#: cp/pt.c:19041
-#, fuzzy, gcc-internal-format
-#| msgid "wrong number of arguments to %<__builtin_choose_expr%>"
+#, gcc-internal-format
msgid "wrong number of arguments to %<__builtin_convertvector%>"
-msgstr "fel antal argument till %<__builtin_choose_expr%>"
+msgstr "fel antal argument till %<__builtin_convertvector%>"
#: cp/pt.c:19336
#, gcc-internal-format
@@ -48702,19 +48374,17 @@ msgstr "%s %#qS"
#: cp/pt.c:23735 cp/pt.c:23830
#, gcc-internal-format
msgid "explicit instantiation of non-template %q#D"
-msgstr "explicit instansieringar av icke-mall %q#D"
+msgstr "explicit instansiering av icke-mall %q#D"
#: cp/pt.c:23741
-#, fuzzy, gcc-internal-format
-#| msgid "specialization of variable concept %q#D"
+#, gcc-internal-format
msgid "explicit instantiation of variable concept %q#D"
-msgstr "specialisering av variabelkonceptet %q#D"
+msgstr "explicit instansiering av variabelkonceptet %q#D"
#: cp/pt.c:23743
-#, fuzzy, gcc-internal-format
-#| msgid "explicit specialization of function concept %qD"
+#, gcc-internal-format
msgid "explicit instantiation of function concept %q#D"
-msgstr "explicit specialisering av funktionskonceptet %qD"
+msgstr "explicit instansiering av funktionskonceptet %q#D"
#: cp/pt.c:23762
#, gcc-internal-format
@@ -48794,28 +48464,24 @@ msgid "explicit instantiation of %qD but no definition available"
msgstr "explicit instansiering av %qD men ingen definition tillgänglig"
#: cp/pt.c:24841
-#, fuzzy, gcc-internal-format
-#| msgid "template instantiation depth exceeds maximum of %d instantiating %q+D, possibly from virtual table generation (use -ftemplate-depth= to increase the maximum)"
+#, gcc-internal-format
msgid "template instantiation depth exceeds maximum of %d instantiating %q+D, possibly from virtual table generation (use %<-ftemplate-depth=%> to increase the maximum)"
-msgstr "mallinstansieringsdjupet överskrider maxvärdet på %d vid instansiering av %q+D, möjligen från generering av virtuell tabell (använd -ftemplate-depth= för att öka maxvärdet)"
+msgstr "mallinstansieringsdjupet överskrider maxvärdet på %d vid instansiering av %q+D, möjligen från generering av virtuell tabell (använd %<-ftemplate-depth=%> för att öka maxvärdet)"
#: cp/pt.c:25216
-#, fuzzy, gcc-internal-format
-#| msgid "lambda templates are only available with -std=c++2a or -std=gnu++2a"
+#, gcc-internal-format
msgid "non-type template parameters of class type only available with %<-std=c++2a%> or %<-std=gnu++2a%>"
-msgstr "lambdamallar är endast tillgängliga med -std=c++2a eller -std=gnu++2a"
+msgstr "mallparameter av klasstyp som inte är en typ är endast tillgängligt med %<-std=c++2a%> eller %<-std=gnu++2a%>"
#: cp/pt.c:25224
-#, fuzzy, gcc-internal-format
-#| msgid "%q#T is not a valid type for a template non-type parameter"
+#, gcc-internal-format
msgid "%qT is not a valid type for a template non-type parameter because it is not literal"
-msgstr "%q#T är inte en giltig typ för en mallparameter som inte är en typ"
+msgstr "%qT är inte en giltig typ för en mallparameter som inte är en typ eftersom det inte är en litteral"
#: cp/pt.c:25231
-#, fuzzy, gcc-internal-format
-#| msgid "%q#T is not a valid type for a template non-type parameter"
+#, gcc-internal-format
msgid "%qT is not a valid type for a template non-type parameter because it has a mutable member"
-msgstr "%q#T är inte en giltig typ för en mallparameter som inte är en typ"
+msgstr "%qT är inte en giltig typ för en mallparameter som inte är en typ för att den har en muterbar medlem"
#: cp/pt.c:25243
#, gcc-internal-format
@@ -48913,10 +48579,9 @@ msgid "invalid use of %qT in template argument"
msgstr "felaktig användning av %qT i mallargument"
#: cp/repo.c:113
-#, fuzzy, gcc-internal-format
-#| msgid "-frepo must be used with -c"
+#, gcc-internal-format
msgid "%<-frepo%> must be used with %<-c%>"
-msgstr "-frepo måste användas tillsammans med -c"
+msgstr "%<-frepo%> måste användas tillsammans med %<-c%>"
#: cp/repo.c:203
#, gcc-internal-format, gfc-internal-format
@@ -48929,10 +48594,9 @@ msgid "can%'t create repository information file %qs"
msgstr "kan inte skapa förrådsinformationsfil %qs"
#: cp/rtti.c:313
-#, fuzzy, gcc-internal-format
-#| msgid "cannot use %<typeid%> with -fno-rtti"
+#, gcc-internal-format
msgid "cannot use %<typeid%> with %<-fno-rtti%>"
-msgstr "kan inte använda %<typeid%> med -fno-rtti"
+msgstr "kan inte använda %<typeid%> med %<-fno-rtti%>"
#: cp/rtti.c:322
#, gcc-internal-format
@@ -48955,10 +48619,9 @@ msgid "dynamic_cast of %q#D to %q#T can never succeed"
msgstr "dynamic_cast av %q#D till %q#T kan aldrig lyckas"
#: cp/rtti.c:722
-#, fuzzy, gcc-internal-format
-#| msgid "%<dynamic_cast%> not permitted with -fno-rtti"
+#, gcc-internal-format
msgid "%<dynamic_cast%> not permitted with %<-fno-rtti%>"
-msgstr "%<dynamic_cast%> är inte tillåtet med -fno-rtti"
+msgstr "%<dynamic_cast%> är inte tillåtet med %<-fno-rtti%>"
#: cp/rtti.c:801
#, gcc-internal-format
@@ -49086,10 +48749,9 @@ msgid "invalid use of member %qD in static member function"
msgstr "ogiltig användning av %qD i en statisk medlemsfunktion"
#: cp/semantics.c:2127
-#, fuzzy, gcc-internal-format
-#| msgid "missing template arguments"
+#, gcc-internal-format
msgid "%qE missing template arguments"
-msgstr "mallargument saknas"
+msgstr "%qE mallargument saknas"
#: cp/semantics.c:2187
#, gcc-internal-format
@@ -49426,22 +49088,19 @@ msgid "%<aligned%> clause alignment expression must be integral"
msgstr "%<aligned%>-klausuls justeringsuttryck måste vara heltal"
#: cp/semantics.c:6932
-#, fuzzy, gcc-internal-format
-#| msgid "%qD is not a variable in %<depend%> clause"
+#, gcc-internal-format
msgid "%qD is not a variable in %<nontemporal%> clause"
-msgstr "%qD är inte en variabel i %<depend%>-klausul"
+msgstr "%qD är inte en variabel i %<nontemporal%>-klausul"
#: cp/semantics.c:6943
-#, fuzzy, gcc-internal-format
-#| msgid "%qD appears more than once in %<aligned%> clauses"
+#, gcc-internal-format
msgid "%qD appears more than once in %<nontemporal%> clauses"
-msgstr "%qD förekommer mer än en gång i %<aligned%>-klausuler"
+msgstr "%qD förekommer mer än en gång i %<nontemporal%>-klausuler"
#: cp/semantics.c:7008
-#, fuzzy, gcc-internal-format
-#| msgid "%qD is not a variable in %<depend%> clause"
+#, gcc-internal-format
msgid "%qD is not lvalue expression nor array section in %<depend%> clause"
-msgstr "%qD är inte en variabel i %<depend%>-klausul"
+msgstr "%qD är inte ett l-värdeuttryck eller vektorsektion i en %<depend%>-klausul"
#: cp/semantics.c:7353
#, gcc-internal-format
@@ -49464,16 +49123,14 @@ msgid "%<priority%> expression must be integral"
msgstr "%<priority%>-uttryck måste vara ett heltal"
#: cp/semantics.c:7485
-#, fuzzy, gcc-internal-format
-#| msgid "%<wait%> expression must be integral"
+#, gcc-internal-format
msgid "%<hint%> expression must be integral"
-msgstr "%<wait%>-uttryck måste vara heltal"
+msgstr "%<hint%>-uttryck måste vara heltal"
#: cp/semantics.c:7498
-#, fuzzy, gcc-internal-format
-#| msgid "%qs length expression must be positive constant integer expression"
+#, gcc-internal-format
msgid "%<hint%> expression must be constant integer expression"
-msgstr "%qs längduttryck måste vara ett positivt konstant heltalsuttryck"
+msgstr "%<hint%>-uttryck måste vara ett konstant heltalsuttryck"
#: cp/semantics.c:7521
#, gcc-internal-format
@@ -49566,16 +49223,14 @@ msgid "statement-expression in a constant expression"
msgstr "satsuttryck i ett konstant uttryck"
#: cp/tree.c:3986
-#, fuzzy, gcc-internal-format
-#| msgid "-fabi-version=13 (GCC 8.2) fixes the calling convention for %qT, which was accidentally changed in 8.1"
+#, gcc-internal-format
msgid "%<-fabi-version=13%> (GCC 8.2) fixes the calling convention for %qT, which was accidentally changed in 8.1"
-msgstr "-fabi-version=13 (GCC 8.2) fixar anropskonventionen för %qT, som ändrades av misstag i 8.1"
+msgstr "%<-fabi-version=13%> (GCC 8.2) fixar anropskonventionen för %qT, som ändrades av misstag i 8.1"
#: cp/tree.c:3990
-#, fuzzy, gcc-internal-format
-#| msgid "-fabi-version=12 (GCC 8.1) accidentally changes the calling convention for %qT"
+#, gcc-internal-format
msgid "%<-fabi-version=12%> (GCC 8.1) accidentally changes the calling convention for %qT"
-msgstr "-fabi-version=12 (GCC 8.1) ändrar av misstag anropskonventionen för %qT"
+msgstr "%<-fabi-version=12%> (GCC 8.1) ändrar av misstag anropskonventionen för %qT"
#: cp/tree.c:3993
#, gcc-internal-format
@@ -49583,10 +49238,9 @@ msgid " declared here"
msgstr " deklarerad här"
#: cp/tree.c:3998
-#, fuzzy, gcc-internal-format
-#| msgid "the calling convention for %qT changes in -fabi-version=13 (GCC 8.2)"
+#, gcc-internal-format
msgid "the calling convention for %qT changes in %<-fabi-version=13%> (GCC 8.2)"
-msgstr "anropskonventionen för %qT ändras i -fabi-version=13 (GCC 8.2)"
+msgstr "anropskonventionen för %qT ändras i %<-fabi-version=13%> (GCC 8.2)"
#: cp/tree.c:4000
#, gcc-internal-format
@@ -49604,28 +49258,24 @@ msgid "%qE attribute can only be applied to functions or to class or enumeration
msgstr "attributet %qE kan bara användas på funktioner eller på klass- eller uppräkningstyper"
#: cp/tree.c:4394
-#, fuzzy, gcc-internal-format
-#| msgid "%qE attribute can only be applied to functions or to class or enumeration types"
+#, gcc-internal-format
msgid "%qE attribute can only be applied to non-static data members"
-msgstr "attributet %qE kan bara användas på funktioner eller på klass- eller uppräkningstyper"
+msgstr "attributet %qE kan bara användas på icke-statiska datamedlemmar"
#: cp/tree.c:4400
-#, fuzzy, gcc-internal-format
-#| msgid "%qE attribute cannot be applied to variables with specific sections"
+#, gcc-internal-format
msgid "%qE attribute cannot be applied to a bit-field"
-msgstr "attributet %qE kan inte tillämpas på variabler med specifika sektioner"
+msgstr "attributet %qE kan inte tillämpas på ett bitfält"
#: cp/tree.c:4420
-#, fuzzy, gcc-internal-format
-#| msgid "the %qE attribute requires arguments"
+#, gcc-internal-format
msgid "%qE attribute takes no arguments"
-msgstr "attributet %qE behöver argument"
+msgstr "attributet %qE tar inga argument"
#: cp/tree.c:4424
-#, fuzzy, gcc-internal-format
-#| msgid "%qE attribute does not apply to functions"
+#, gcc-internal-format
msgid "ISO C++ %qE attribute does not apply to functions; treating as %<[[gnu::%E]]%>"
-msgstr "attributet %qE är inte tillämpligt på funktioner"
+msgstr "ISO C++-attributet %qE är inte tillämpligt på funktioner; hanteras som %<[[gnu::%E]]%>"
#: cp/tree.c:4485
#, gcc-internal-format
@@ -49869,16 +49519,14 @@ msgid "%q#T has no member named %qE"
msgstr "%q#T har ingen medlem med namnet %qE"
#: cp/typeck.c:2857
-#, fuzzy, gcc-internal-format
-#| msgid "%q#T has no member named %qE; did you mean %qE?"
+#, gcc-internal-format
msgid "%q#T has no member named %qE; did you mean %q#D? (accessible via %q#D)"
-msgstr "%q#T har ingen medlem med namnet %qE, menade du %qE?"
+msgstr "%q#T har ingen medlem med namnet %qE, menade du %q#D? (Ã¥tkomligt via %q#D)"
#: cp/typeck.c:2868
-#, fuzzy, gcc-internal-format
-#| msgid "%q#T has no member named %qE; did you mean %qE?"
+#, gcc-internal-format
msgid "%q#T has no member named %qE; did you mean %q#D? (not accessible from this context)"
-msgstr "%q#T har ingen medlem med namnet %qE, menade du %qE?"
+msgstr "%q#T har ingen medlem med namnet %qE, menade du %q#D? (inte åtkomlig från detta sammanhang)"
#: cp/typeck.c:2882
#, gcc-internal-format
@@ -50157,10 +49805,9 @@ msgstr "ISO C++ förbjuder att ta adressen till en bunden medlemsfunktion för a
#. Make this a permerror because we used to accept it.
#: cp/typeck.c:6039
-#, fuzzy, gcc-internal-format
-#| msgid "taking address of temporary"
+#, gcc-internal-format
msgid "taking address of rvalue"
-msgstr "tar adress till något temporärt"
+msgstr "tar adress till ett r-värde"
#: cp/typeck.c:6056
#, gcc-internal-format
@@ -50513,10 +50160,9 @@ msgid "remove %<std::move%> call"
msgstr "ta bort anrop av %<std::move%>"
#: cp/typeck.c:9488
-#, fuzzy, gcc-internal-format
-#| msgid "too many values in return statement"
+#, gcc-internal-format
msgid "redundant move in return statement"
-msgstr "för många värden i retursats"
+msgstr "redundant förflyttning i retursats"
#: cp/typeck.c:9526
#, gcc-internal-format
@@ -50569,10 +50215,9 @@ msgstr "%<operator new%> får inte returnera NULL om den inte är deklarerad %<t
#. Make this a permerror because we used to accept it.
#: cp/typeck.c:10280
-#, fuzzy, gcc-internal-format
-#| msgid "using temporary as lvalue"
+#, gcc-internal-format
msgid "using rvalue as lvalue"
-msgstr "använder temporär som lvärde"
+msgstr "använder r-värde som l-värde"
#: cp/typeck2.c:50
#, gcc-internal-format
@@ -50791,16 +50436,12 @@ msgid "constructor syntax used, but no constructor declared for type %qT"
msgstr "konstruerarsyntax använd, men ingen konstruerare är deklarerad för typ %qT"
#: cp/typeck2.c:997
-#, fuzzy
-#| msgid "narrowing conversion of %qE from %qH to %qI inside { } is ill-formed in C++11"
msgid "narrowing conversion of %qE from %qH to %qI is ill-formed in C++11"
-msgstr "avsmalnande konvertering av %qE från %qH till %qI inuti { } är felaktig i C++11"
+msgstr "avsmalnande konvertering av %qE från %qH till %qI är felaktig i C++11"
#: cp/typeck2.c:1009 cp/typeck2.c:1022
-#, fuzzy
-#| msgid "narrowing conversion of %qE from %qH to %qI inside { }"
msgid "narrowing conversion of %qE from %qH to %qI"
-msgstr "avsmalnande konvertering av %qE från %qH till %qI inuti { }"
+msgstr "avsmalnande konvertering av %qE från %qH till %qI"
#: cp/typeck2.c:1012
#, gcc-internal-format
@@ -50818,10 +50459,9 @@ msgid "initializing a base class of type %qT results in object slicing"
msgstr "att initiera en basklass av typ %qT resulterar i objektskivning"
#: cp/typeck2.c:1228
-#, fuzzy, gcc-internal-format
-#| msgid "braces around scalar initializer"
+#, gcc-internal-format
msgid "remove %<{ }%> around initializer"
-msgstr "klamrar runt skalär initierare"
+msgstr "ta bort %<{ }%> runt initierare"
#: cp/typeck2.c:1245
#, gcc-internal-format
@@ -51831,10 +51471,9 @@ msgid "%qs argument of %qs intrinsic at %L must be default real"
msgstr "%qs-argumentet till inbyggd %qs vid %L måste vara standard reell"
#: fortran/check.c:2176
-#, fuzzy, gcc-internal-format
-#| msgid "%<I%> at %L and %<J%>' at %L cannot both be BOZ literal constants"
+#, gcc-internal-format
msgid "Arguments of %qs at %L and %L cannot both be BOZ literal constants"
-msgstr "%<I%> vid %L och %<J%> vid %L kan inte båda vara litterala BOZ-konstanter"
+msgstr "Argument till %qs vid %L och %L kan inte båda vara litterala BOZ-konstanter"
#: fortran/check.c:2300
#, gcc-internal-format
@@ -51857,10 +51496,9 @@ msgid "COMPLEX argument %qs of %qs intrinsic at %L"
msgstr "COMPLEX-argumentet %qs till inbyggd %qs vid %L"
#: fortran/check.c:2512
-#, fuzzy, gcc-internal-format
-#| msgid "types have different parameter counts"
+#, gcc-internal-format
msgid "Arguments of %qs have different kind type parameters at %L"
-msgstr "typer har olika parameterantal"
+msgstr "Argument till %qs har olika sorts typeparametrar vid %L"
#: fortran/check.c:2608
#, gcc-internal-format, gfc-internal-format
@@ -51943,10 +51581,9 @@ msgid "%qs argument of %qs intrinsic at %L must be of rank 1 or 2"
msgstr "%qs-argumentet till inbyggd %qs vid %L måste ha ordning 1 eller 2"
#: fortran/check.c:3360
-#, fuzzy, gcc-internal-format
-#| msgid "%qs argument of %qs intrinsic at %L must be an interoperable data entity: %s"
+#, gcc-internal-format
msgid "Argument %qs of %qs intrinsic at %L must be in type conformance to argument %qs at %L"
-msgstr "Argumentet %qs till inbyggd %qs vid %L måste vara en interoperabel dataenhet: %s"
+msgstr "Argumentet %qs till inbyggd %qs vid %L måste vara typkonformt med argument %qs vid %L"
#: fortran/check.c:3525
#, gcc-internal-format
@@ -52319,21 +51956,19 @@ msgid "%<MOLD%> argument of %<TRANSFER%> intrinsic at %L is an array and shall n
msgstr "argumentet %<MOLD%> till den inbyggda %<TRANSFER%> vid %L är en vektor och skall inte ha lagringsstorlek 0 när argumentet %<SOURCE%> har en storlek större än 0"
#: fortran/check.c:5551
-#, fuzzy, gcc-internal-format
-#| msgid "%<MOLD%> argument of %<TRANSFER%> intrinsic at %L must not be %s"
+#, gcc-internal-format
msgid "%<SOURCE%> argument of %<TRANSFER%> intrinsic at %L must not be a %s"
-msgstr "%<MOLD%>-argumentet till inbyggd %<TRANSFER%> vid %L måste vara %s"
+msgstr "%<MOLD%>-argumentet till inbyggd %<TRANSFER%> vid %L får inte vara %s"
#: fortran/check.c:5561
-#, fuzzy, gcc-internal-format
-#| msgid "%<MOLD%> argument of %<TRANSFER%> intrinsic at %L must not be %s"
+#, gcc-internal-format
msgid "%<MOLD%> argument of %<TRANSFER%> intrinsic at %L must not be a %s"
-msgstr "%<MOLD%>-argumentet till inbyggd %<TRANSFER%> vid %L måste vara %s"
+msgstr "%<MOLD%>-argumentet till inbyggd %<TRANSFER%> vid %L måste vara en %s"
#: fortran/check.c:5569
#, gcc-internal-format
msgid "%<MOLD%> argument of %<TRANSFER%> intrinsic at %L must not be %s"
-msgstr "%<MOLD%>-argumentet till inbyggd %<TRANSFER%> vid %L måste vara %s"
+msgstr "%<MOLD%>-argumentet till inbyggd %<TRANSFER%> vid %L får inte vara %s"
#: fortran/check.c:5600
#, gcc-internal-format, gfc-internal-format
@@ -52743,16 +52378,14 @@ msgid "Cannot initialize parameter array at %L with variable length elements"
msgstr "Det går inte att initiera en parametervektor vid %L med element med variabel längd"
#: fortran/decl.c:1981
-#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Can't initialize implied-shape array at %L with scalar"
+#, gcc-internal-format, gfc-internal-format
msgid "Cannot initialize implied-shape array at %L with scalar"
msgstr "Det går inte att initiera en vektor med antagen form vid %L med en skalär"
#: fortran/decl.c:1992
-#, fuzzy, gcc-internal-format
-#| msgid "gfc_array_dimen_size(): Bad dimension"
+#, gcc-internal-format
msgid "gfc_array_size failed"
-msgstr "gfc_array_dimen_size(): Felaktig dimension"
+msgstr "gfc_array_size misslyckades"
#: fortran/decl.c:2022
#, gcc-internal-format, gfc-internal-format
@@ -52845,8 +52478,7 @@ msgid "%qs entity cannot have attributes at %C"
msgstr "Enheten %qs kan inte ha attribut vid %C"
#: fortran/decl.c:2493
-#, fuzzy, gcc-internal-format
-#| msgid "Non-PARAMETER symbol %qs at %L can't be implied-shape"
+#, gcc-internal-format
msgid "Non-PARAMETER symbol %qs at %L cannot be implied-shape"
msgstr "Icke-PARAMETER-symbolen %qs vid %L kan inte ha antagen form"
@@ -52876,10 +52508,9 @@ msgid "Duplicate array spec for Cray pointee at %C"
msgstr "Dubblerad vektorspecifikation för Cray-utpekad vid %C"
#: fortran/decl.c:2671
-#, fuzzy, gcc-internal-format
-#| msgid "Couldn't set pointee array spec."
+#, gcc-internal-format
msgid "Cannot set pointee array spec."
-msgstr "Kunde inte sätta utpekads vektorspecifikation."
+msgstr "Kan inte sätta utpekads vektorspecifikation."
#: fortran/decl.c:2734
#, gcc-internal-format, gfc-internal-format
@@ -52992,10 +52623,9 @@ msgid "Syntax error in CHARACTER declaration at %C"
msgstr "Syntaxfel i CHARACTER-deklaration vid %C"
#: fortran/decl.c:3442
-#, fuzzy, gcc-internal-format
-#| msgid "RECORD at %C is an extension, enable it with -fdec-structure"
+#, gcc-internal-format
msgid "RECORD at %C is an extension, enable it with %<-fdec-structure%>"
-msgstr "RECORD vid %C är en utökning, aktivera den med -fdec-structure"
+msgstr "RECORD vid %C är en utökning, aktivera den med %<-fdec-structure%>"
#: fortran/decl.c:3455
#, gcc-internal-format, gfc-internal-format
@@ -53310,10 +52940,9 @@ msgid "Return type of BIND(C) function %qs at %L cannot be an array"
msgstr "Returtyp till BIND(C)-funktion %qs vid %L kan inte vara en vektor"
#: fortran/decl.c:5750
-#, fuzzy, gcc-internal-format
-#| msgid "Return type of BIND(C) function %qs at %L cannot be a character string"
+#, gcc-internal-format
msgid "Return type of BIND(C) function %qs of character type at %L must have length 1"
-msgstr "Returtyp till BIND(C)-funktion %qs vid %L kan inte vara en teckensträng"
+msgstr "Returtyp till BIND(C)-funktion %qs med teckentyp vid %L måste ha längden 1"
#. Use gfc_warning_now because we won't say that the symbol fails
#. just because of this.
@@ -53363,10 +52992,9 @@ msgid "MODULE prefix at %C"
msgstr "MODULE-prefix vid %C"
#: fortran/decl.c:6130
-#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "MODULE PROCEDURE at %C must be in a generic module interface"
+#, gcc-internal-format, gfc-internal-format
msgid "MODULE prefix at %C found outside of a module, submodule, or interface"
-msgstr "MODULE PROCEDURE vid %C måste vara i ett generiskt modulgränssnitt"
+msgstr "MODULE-prefix vid %C hittat utanför en modul, undermodul eller gränssnitt"
#: fortran/decl.c:6177
#, gcc-internal-format, gfc-internal-format
@@ -53394,10 +53022,9 @@ msgid "RECURSIVE prefix in MODULE PROCEDURE interface is missing at %L"
msgstr "RECURSIVE-prefixet i MODULE PROCEDURE-gränssnittet saknas vid %L"
#: fortran/decl.c:6310
-#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "A parameter name is required at %C"
+#, gcc-internal-format, gfc-internal-format
msgid "A type parameter list is required at %C"
-msgstr "Ett parameternamn krävs vid %C"
+msgstr "En typparameterlista krävs vid %C"
#: fortran/decl.c:6324 fortran/primary.c:1820
#, gcc-internal-format, gfc-internal-format
@@ -53617,16 +53244,14 @@ msgid "Missing required parentheses before BIND(C) at %C"
msgstr "Nödvändig parentes saknas före BIND(C) vid %C"
#: fortran/decl.c:7579
-#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "ENTRY statement at %C cannot appear in a contained procedure"
+#, gcc-internal-format, gfc-internal-format
msgid "ENTRY statement at %L with BIND(C) prohibited in an elemental procedure"
-msgstr "ENTRY-sats vid %C kan inte förekomma i en innesluten procedur"
+msgstr "ENTRY-sats vid %L med BIND(C) är otillåten i en elementär procedur"
#: fortran/decl.c:7714
-#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Alternate return cannot appear in operator interface at %L"
+#, gcc-internal-format, gfc-internal-format
msgid "Alternate return dummy argument cannot appear in a SUBROUTINE with the BIND(C) attribute at %L"
-msgstr "Alternativ retur får inte förekomma i operatorgränssnitt vid %L"
+msgstr "Alternativt returarattrappgument får inte förekomma i en SUBROUTINE med attributet BIND(C) vid %L"
#: fortran/decl.c:7777 fortran/decl.c:7784
#, gcc-internal-format, gfc-internal-format
@@ -53755,10 +53380,9 @@ msgid "Expected \",\" at %C"
msgstr "â€,†förväntades vid %C"
#: fortran/decl.c:8579
-#, fuzzy, gcc-internal-format
-#| msgid "Couldn't set Cray pointee array spec."
+#, gcc-internal-format
msgid "Cannot set Cray pointee array spec."
-msgstr "Kunde inte sätta Cray-utpekad vektorspecifikation."
+msgstr "Kan inte sätta Cray-utpekad vektorspecifikation."
#: fortran/decl.c:8603
#, gcc-internal-format, gfc-internal-format
@@ -53781,10 +53405,9 @@ msgid "OPTIONAL is not allowed inside of BLOCK at %C"
msgstr "OPTIONAL är inte tillåtet inuti BLOCK vid %C"
#: fortran/decl.c:8692
-#, fuzzy, gcc-internal-format
-#| msgid "Cray pointer declaration at %C requires -fcray-pointer flag"
+#, gcc-internal-format
msgid "Cray pointer declaration at %C requires %<-fcray-pointer%> flag"
-msgstr "Cray-pekardeklaration vid %C kräver flaggan -fcray-pointer"
+msgstr "Cray-pekardeklaration vid %C kräver flaggan %<-fcray-pointer%>"
#: fortran/decl.c:8731
#, gcc-internal-format, gfc-internal-format
@@ -54128,8 +53751,7 @@ msgid "Expected binding attribute at %C"
msgstr "Bindningsattribut förväntades vid %C"
#: fortran/decl.c:10748
-#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "NON_OVERRIDABLE and DEFERRED can't both appear at %C"
+#, gcc-internal-format, gfc-internal-format
msgid "NON_OVERRIDABLE and DEFERRED cannot both appear at %C"
msgstr "NON_OVERRIDABLE och DEFERRED kan inte båda finnas vid %C"
@@ -54419,34 +54041,29 @@ msgid "index in dimension %d is out of bounds at %L"
msgstr "index i dimension %d är utanför gränsen vid %L"
#: fortran/expr.c:1672
-#, fuzzy, gcc-internal-format
-#| msgid "The number of elements in the array constructor at %L requires an increase of the allowed %d upper limit. See %<-fmax-array-constructor%> option"
+#, gcc-internal-format
msgid "The number of elements in the array constructor at %L requires an increase of the allowed %d upper limit. See %<-fmax-array-constructor%> option"
msgstr "Antalet element i vektorkonstrueraren vid %L kräver en ökning av den tillåtna övre gränsen %d. Se flaggan %<-fmax-array-constructor%>"
#: fortran/expr.c:1780 fortran/primary.c:2309
-#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "MODULE prefix at %C"
+#, gcc-internal-format, gfc-internal-format
msgid "LEN part_ref at %C"
-msgstr "MODULE-prefix vid %C"
+msgstr "LEN-part_ref vid %C"
#: fortran/expr.c:1794 fortran/primary.c:2324
-#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "MODULE prefix at %C"
+#, gcc-internal-format, gfc-internal-format
msgid "KIND part_ref at %C"
-msgstr "MODULE-prefix vid %C"
+msgstr "KIND-part_ref vid %C"
#: fortran/expr.c:1805
-#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "IMPURE procedure at %C"
+#, gcc-internal-format, gfc-internal-format
msgid "RE part_ref at %C"
-msgstr "IMPURE-procedur vid %C"
+msgstr "RE-part_ref vid %C"
#: fortran/expr.c:1817
-#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "MODULE prefix at %C"
+#, gcc-internal-format, gfc-internal-format
msgid "IM part_ref at %C"
-msgstr "MODULE-prefix vid %C"
+msgstr "IM-part_ref vid %C"
#: fortran/expr.c:2396
#, gcc-internal-format, gfc-internal-format
@@ -54534,8 +54151,7 @@ msgid "Assumed shape array %qs at %L is not permitted in an initialization expre
msgstr "Vektor %qs med antagen form vid %L är inte tillåten i ett initieringsuttryck"
#: fortran/expr.c:2935
-#, fuzzy, gcc-internal-format
-#| msgid "Assumed shape array %qs at %L is not permitted in an initialization expression"
+#, gcc-internal-format
msgid "Assumed-shape array %qs at %L is not permitted in an initialization expression"
msgstr "Vektor %qs med antagen form vid %L är inte tillåten i ett initieringsuttryck"
@@ -54630,10 +54246,9 @@ msgid "Different shape for %s at %L on dimension %d (%d and %d)"
msgstr "Olika form för %s vid %L på dimension %d (%d och %d)"
#: fortran/expr.c:3523
-#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "The assignment to a KIND or LEN component of a parameterized type at %L is not allowed"
+#, gcc-internal-format, gfc-internal-format
msgid "Assignment to a LEN or KIND part_ref at %L is not allowed"
-msgstr "Tilldelningen till en KIND- eller LEN-komponent i en parametriserad typ vid %L tillåts inte"
+msgstr "Tilldelning till en LEN- eller KIND-part_ref vid %L tillåts inte"
#: fortran/expr.c:3579
#, gcc-internal-format
@@ -54641,10 +54256,9 @@ msgid "%qs at %L is not a VALUE"
msgstr "%qs vid %L är inte ett VALUE"
#: fortran/expr.c:3590
-#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Illegal stride of zero at %L"
+#, gcc-internal-format, gfc-internal-format
msgid "Illegal assignment to external procedure at %L"
-msgstr "Otillåtet steg på noll vid %L"
+msgstr "Otillåten tilldelning till extern procedur vid %L"
#: fortran/expr.c:3598
#, gcc-internal-format, gfc-internal-format
@@ -54812,10 +54426,9 @@ msgid "Procedure pointer target %qs at %L must be either an intrinsic, host or u
msgstr "Procedurpekarmålet %qs vid %L måste vara antingen en inbyggd, värd, värd- eller användningsassocierad, refererad eller ha attributet EXTERNAL"
#: fortran/expr.c:4096
-#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Pointer assignment target is not a POINTER at %L"
+#, gcc-internal-format, gfc-internal-format
msgid "Pointer assignment target cannot be a constant at %L"
-msgstr "Pekartilldelningsmålet är inte en POINTER vid %L"
+msgstr "Pekartilldelningsmålet får inte vara en konstant vid %L"
#: fortran/expr.c:4110
#, gcc-internal-format, gfc-internal-format
@@ -54866,10 +54479,9 @@ msgid "Target expression in pointer assignment at %L must deliver a pointer resu
msgstr "Måluttryck i pekartilldelning vid %L måste leverera ett pekarresultat"
#: fortran/expr.c:4223
-#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Pointer initialization target at %L must have the TARGET attribute"
+#, gcc-internal-format, gfc-internal-format
msgid "Pointer assignment target in initialization expression does not have the TARGET attribute at %L"
-msgstr "Målet för pekarinitieringen vid %L måste ha attributet TARGET"
+msgstr "Målet för pekartilldelingen i initieraruttrycket har inte attributet TARGET vid %L"
#: fortran/expr.c:4233
#, gcc-internal-format, gfc-internal-format
@@ -54922,16 +54534,14 @@ msgid "Procedure pointer initialization target at %L may not be a procedure poin
msgstr "Procedurpekarinitieringsmål vid %L får inte vara en procedurpekare"
#: fortran/expr.c:4436
-#, fuzzy, gcc-internal-format
-#| msgid "Internal procedure %qs is invalid in procedure pointer assignment at %L"
+#, gcc-internal-format
msgid "Internal procedure %qs is invalid in procedure pointer initialization at %L"
-msgstr "Intern procedur %qs är ogiltigt i procedurpekartilldelning vid %L"
+msgstr "Intern procedur %qs är ogiltigt i procedurpekarinitiering vid %L"
#: fortran/expr.c:4443
-#, fuzzy, gcc-internal-format
-#| msgid "Internal procedure %qs is invalid in procedure pointer assignment at %L"
+#, gcc-internal-format
msgid "Dummy procedure %qs is invalid in procedure pointer initialization at %L"
-msgstr "Intern procedur %qs är ogiltigt i procedurpekartilldelning vid %L"
+msgstr "Attrapproceduren %qs är ogiltig i procedurpekarinitiering vid %L"
#: fortran/expr.c:4911
#, gcc-internal-format
@@ -54989,38 +54599,32 @@ msgid "Dummy argument %qs with INTENT(IN) in variable definition context (%s) at
msgstr "Attrappargument %qs med INTENT(IN) i variabeldefinitionssammanhang (%s) vid %L"
#: fortran/expr.c:6115
-#, fuzzy, gcc-internal-format
-#| msgid "Variable %qs is PROTECTED and can not appear in a pointer association context (%s) at %L"
+#, gcc-internal-format
msgid "Variable %qs is PROTECTED and cannot appear in a pointer association context (%s) at %L"
msgstr "Variabeln %qs är PROTECTED och kan inte förekomma i ett pekarassociationssammanhang (%s) vid %L"
#: fortran/expr.c:6123
-#, fuzzy, gcc-internal-format
-#| msgid "Variable %qs is PROTECTED and can not appear in a variable definition context (%s) at %L"
+#, gcc-internal-format
msgid "Variable %qs is PROTECTED and cannot appear in a variable definition context (%s) at %L"
msgstr "Variabeln %qs är PROTECTED och kan inte förekomma i ett variabeldefinitionssammanhang (%s) vid %L"
#: fortran/expr.c:6135
-#, fuzzy, gcc-internal-format
-#| msgid "Variable %qs can not appear in a variable definition context (%s) at %L in PURE procedure"
+#, gcc-internal-format
msgid "Variable %qs cannot appear in a variable definition context (%s) at %L in PURE procedure"
msgstr "Variabeln %qs kan inte förekomma i ett variabeldefinitionssammanhang (%s) vid %L"
#: fortran/expr.c:6194
-#, fuzzy, gcc-internal-format
-#| msgid "%qs at %L associated to vector-indexed target can not be used in a variable definition context (%s)"
+#, gcc-internal-format
msgid "%qs at %L associated to vector-indexed target cannot be used in a variable definition context (%s)"
msgstr "%qs vid %L som är associerad med vektorindexerat mål kan inte användas i ett variabeldefinitionssammanhang (%s)"
#: fortran/expr.c:6199
-#, fuzzy, gcc-internal-format
-#| msgid "%qs at %L associated to expression can not be used in a variable definition context (%s)"
+#, gcc-internal-format
msgid "%qs at %L associated to expression cannot be used in a variable definition context (%s)"
msgstr "%qs vid %L som är associerad med uttryck kan inte användas i ett variabeldefinitionssammanhang (%s)"
#: fortran/expr.c:6211
-#, fuzzy, gcc-internal-format
-#| msgid "Associate-name %qs can not appear in a variable definition context (%s) at %L because its target at %L can not, either"
+#, gcc-internal-format
msgid "Associate-name %qs cannot appear in a variable definition context (%s) at %L because its target at %L cannot, either"
msgstr "Associationsnamn %qs kan inte förekomma i ett variabeldefinitionssammanhang (%s) vid %L eftersom dess mål vid %L inte heller kan"
@@ -55030,22 +54634,19 @@ msgid "Elements with the same value at %L and %L in vector subscript in a variab
msgstr "Element med samma värde vid %L och %L i vektorindex i ett variabeldefinitionssammanhang (%s)"
#: fortran/f95-lang.c:251
-#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "can't open input file: %s"
+#, gcc-internal-format, gfc-internal-format
msgid "cannot open input file: %s"
-msgstr "Kan inte öppna indatafil: %s"
+msgstr "kan inte öppna indatafilen: %s"
#: fortran/frontend-passes.c:193
-#, fuzzy, gcc-internal-format
-#| msgid "Nonconstant array section at %L in DATA statement"
+#, gcc-internal-format
msgid "Inconsistent internal state: No location in statement"
-msgstr "Ickekonstant vektorsektion vid %L i DATA-sats."
+msgstr "Inkonsistent internt tillstånd: ingen plats i satsen"
#: fortran/frontend-passes.c:209
-#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "No location in expression near %L"
+#, gcc-internal-format, gfc-internal-format
msgid "Inconsistent internal state: No location in expression near %L"
-msgstr "Ingen plats i uttryck nära %L"
+msgstr "Inkonsistent internt tillstånd: ingen plats i uttrycket nära %L"
#: fortran/frontend-passes.c:417
#, gcc-internal-format
@@ -55060,16 +54661,14 @@ msgid "Creating array temporary at %L"
msgstr "Skapar vektortemporär vid %L"
#: fortran/frontend-passes.c:895
-#, fuzzy, gcc-internal-format
-#| msgid "Removing call to function %qs at %L"
+#, gcc-internal-format
msgid "Removing call to impure function %qs at %L"
-msgstr "Tar bort anrop av funktionen %qs vid %L"
+msgstr "Tar bort anrop av den orena funktionen %qs vid %L"
#: fortran/frontend-passes.c:899
-#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Removing call to function %qs at %L"
+#, gcc-internal-format, gfc-internal-format
msgid "Removing call to impure function at %L"
-msgstr "Tar bort anrop av funktionen %qs vid %L"
+msgstr "Tar bort anrop av den orena funktionen vid %L"
#: fortran/frontend-passes.c:1354 fortran/frontend-passes.c:1393
#, gcc-internal-format
@@ -55472,16 +55071,14 @@ msgid "More actual than formal arguments in procedure call at %L"
msgstr "Fler aktuella än formella argument i proceduranrop vid %L"
#: fortran/interface.c:2975
-#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Missing alternate return spec in subroutine call at %L"
+#, gcc-internal-format, gfc-internal-format
msgid "Missing alternate return specifier in subroutine call at %L"
-msgstr "Alternativ returspecifikation saknas i subrutinanrop vid %L"
+msgstr "Alternativ returspecifierare saknas i subrutinanrop vid %L"
#: fortran/interface.c:2983
-#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Unexpected alternate return spec in subroutine call at %L"
+#, gcc-internal-format, gfc-internal-format
msgid "Unexpected alternate return specifier in subroutine call at %L"
-msgstr "Oväntad alternativ returspecifikation i subrutinanrop vid %L"
+msgstr "Oväntad alternativ returspecifierare i subrutinanrop vid %L"
#: fortran/interface.c:3010
#, gcc-internal-format
@@ -55744,8 +55341,7 @@ msgid "gfc_add_interface(): Bad interface type"
msgstr "gfc_add_interface(): Felaktig gränssnittstyp"
#: fortran/interface.c:4557
-#, fuzzy, gcc-internal-format
-#| msgid "Can't overwrite GENERIC %qs at %L"
+#, gcc-internal-format
msgid "Cannot overwrite GENERIC %qs at %L"
msgstr "Det går inte att skriva över GENERIC %qs vid %L"
@@ -55910,14 +55506,12 @@ msgid "add_sym(): Bad sizing mode"
msgstr "add_sym(): Felaktigt storleksläge"
#: fortran/intrinsic.c:1125
-#, fuzzy, gcc-internal-format
-#| msgid "The intrinsic %qs at %L is not included in the selected standard but %s and %qs will be treated as if declared EXTERNAL. Use an appropriate -std=* option or define -fall-intrinsics to allow this intrinsic."
+#, gcc-internal-format
msgid "The intrinsic %qs at %L is not included in the selected standard but %s and %qs will be treated as if declared EXTERNAL. Use an appropriate %<-std=%>* option or define %<-fall-intrinsics%> to allow this intrinsic."
-msgstr "Den inbyggda %qs vid %L ingår inte i den valda standarden utan %s och %qs kommer hanteras som om de var deklarerade EXTERNAL. Använd en tillämplig -std=*-flagga eller definiera -fall-intrinsics för att tillåta denna inbyggda."
+msgstr "Den inbyggda %qs vid %L ingår inte i den valda standarden utan %s och %qs kommer hanteras som om de var deklarerade EXTERNAL. Använd en tillämplig %<-std=*%>-flagga eller definiera %<-fall-intrinsics%> för att tillåta denna inbyggda."
#: fortran/intrinsic.c:1160
-#, fuzzy, gcc-internal-format
-#| msgid "make_generic(): Can't find generic symbol %qs"
+#, gcc-internal-format
msgid "make_generic(): Cannot find generic symbol %qs"
msgstr "make_generic(): Kan inte hitta den generiska symbolen %qs"
@@ -55932,8 +55526,7 @@ msgid "The argument list functions %%VAL, %%LOC or %%REF are not allowed in this
msgstr "Argumentlistefunktionerna vid %%VAL, %%LOC eller %%REF är inte tillåten i denna kontext vid %L"
#: fortran/intrinsic.c:4220
-#, fuzzy, gcc-internal-format
-#| msgid "Can't find keyword named %qs in call to %qs at %L"
+#, gcc-internal-format
msgid "Cannot find keyword named %qs in call to %qs at %L"
msgstr "Nyckelord med namnet %qs saknas i anrop till %qs vid %L"
@@ -56023,14 +55616,12 @@ msgid "Conversion from %s to %s at %L"
msgstr "Konvertering från %s till %s vid %L"
#: fortran/intrinsic.c:5182
-#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Can't convert %s to %s at %L"
+#, gcc-internal-format, gfc-internal-format
msgid "Cannot convert %s to %s at %L"
msgstr "Kan inte konvertera %s till %s vid %L"
#: fortran/intrinsic.c:5187
-#, fuzzy, gcc-internal-format
-#| msgid "Can't convert %qs to %qs at %L"
+#, gcc-internal-format
msgid "Cannot convert %qs to %qs at %L"
msgstr "Kan inte konvertera %qs till %qs vid %L"
@@ -56195,10 +55786,9 @@ msgid "Constant expression in FORMAT tag at %L must be of type default CHARACTER
msgstr "Konstant uttryck i FORMAT-tagg vid %L måste vara av typ CHARACTER"
#: fortran/io.c:1641
-#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Loop variable at %C cannot be a coarray"
+#, gcc-internal-format, gfc-internal-format
msgid "FORMAT tag at %C cannot be a zero-sized array"
-msgstr "Slingvariabel vid %C får inte vara en co-vektor"
+msgstr "FORMAT-taggen vid %C får inte vara en vektor med storlek noll"
#: fortran/io.c:1681
#, gcc-internal-format, gfc-internal-format
@@ -56316,16 +55906,14 @@ msgid "ASYNCHRONOUS= at %C not allowed in Fortran 95"
msgstr "ASYNCHRONOUS= vid %C är inte tillåtet i Fortran 95"
#: fortran/io.c:2216 fortran/io.c:3842
-#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "ASYNCHRONOUS= specifier at %L must be an initialization expression"
+#, gcc-internal-format, gfc-internal-format
msgid "ASYNCHRONOUS= specifier at %L must be of default CHARACTER kind"
-msgstr "ASYNCHRONOUS=-specificerare vid %L måste vara ett initieringsuttryck"
+msgstr "ASYNCHRONOUS=-specificerare vid %L måste vara av standardsorten CHARACTER"
#: fortran/io.c:2224 fortran/io.c:3850
-#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "ASYNCHRONOUS= specifier at %L must be an initialization expression"
+#, gcc-internal-format, gfc-internal-format
msgid "ASYNCHRONOUS= specifier at %L must be scalar"
-msgstr "ASYNCHRONOUS=-specificerare vid %L måste vara ett initieringsuttryck"
+msgstr "ASYNCHRONOUS=-specificerare vid %L måste vara skalär"
#: fortran/io.c:2243 fortran/io.c:3907
#, gcc-internal-format, gfc-internal-format
@@ -56523,10 +56111,9 @@ msgid "Expected variable in READ statement at %C"
msgstr "Variabel förväntades i READ-sats vid %C"
#: fortran/io.c:3617
-#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Expected variable name at %C"
+#, gcc-internal-format, gfc-internal-format
msgid "Expecting variable or io-implied-do at %L"
-msgstr "Variabelnamn förväntades vid %C"
+msgstr "Variabel eller io-implied-do förväntas vid %L"
#: fortran/io.c:3627
#, gcc-internal-format, gfc-internal-format
@@ -56545,10 +56132,9 @@ msgid "Internal file at %L with namelist"
msgstr "Intern fil vid %L med namnlista"
#: fortran/io.c:3787
-#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "DATA statement at %C is not allowed in a PURE procedure"
+#, gcc-internal-format, gfc-internal-format
msgid "IO UNIT in %s statement at %C must be an internal file in a PURE procedure"
-msgstr "DATA-sats vid %C får inte förekomma i en PURE-procedur"
+msgstr "IO UNIT i %s-satsen vid %C måste en intern fil i en PURE-procedur"
#: fortran/io.c:3832
#, gcc-internal-format, gfc-internal-format
@@ -56571,10 +56157,9 @@ msgid "PRINT namelist at %C is an extension"
msgstr "PRINT-namnlista vid %C är en utökning"
#: fortran/io.c:4182
-#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "END tag at %C not allowed in output statement"
+#, gcc-internal-format, gfc-internal-format
msgid "Comma after * at %C not allowed without I/O list"
-msgstr "END-tagg vid %C är inte tillåten i utmatningssats"
+msgstr "Komma efter * vid %C är inte tillåtet utan I/O-lista"
#: fortran/io.c:4358
#, gcc-internal-format, gfc-internal-format
@@ -56607,8 +56192,7 @@ msgid "INQUIRE statement at %L requires either FILE or UNIT specifier"
msgstr "INQUIRE-sats vid %L kräver antingen FILE- eller UNIT-specificerare"
#: fortran/io.c:4648
-#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "UNIT number in INQUIRE statement at %L can not be %d"
+#, gcc-internal-format, gfc-internal-format
msgid "UNIT number in INQUIRE statement at %L cannot be %d"
msgstr "UNIT-tal i INQUIRE-sats vid %L får inte vara %d"
@@ -56733,10 +56317,9 @@ msgid "Invalid form of PROGRAM statement at %C"
msgstr "Ogiltig form på PROGRAM-sats vid %C"
#: fortran/match.c:1358
-#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "statement is not a constant expression"
+#, gcc-internal-format, gfc-internal-format
msgid "Assignment to a constant expression at %C"
-msgstr "satsen är inte ett konstant uttryck"
+msgstr "Tilldelning till ett konstant uttryck vid %C"
#: fortran/match.c:1457 fortran/match.c:1538
#, gcc-internal-format, gfc-internal-format
@@ -56819,10 +56402,9 @@ msgid "Expected association at %C"
msgstr "Association förväntade vid %C"
#: fortran/match.c:1915
-#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Invalid character in name at %C"
+#, gcc-internal-format, gfc-internal-format
msgid "Invalid association target at %C"
-msgstr "Felaktigt tecken i namn vid %C"
+msgstr "Felaktigt associationsmål vid %C"
#: fortran/match.c:1926
#, gcc-internal-format
@@ -57331,8 +56913,7 @@ msgid "Variable %qs at %L in common block %qs at %C must be declared with a C in
msgstr "Variabel %qs vid %L i common-block %qs vid %C måste deklareras med en C-interoperativ sort eftersom common-block %qs är bind(c)"
#: fortran/match.c:5145
-#, fuzzy, gcc-internal-format
-#| msgid "Variable %qs in common block %qs at %C can not be bind(c) since it is not global"
+#, gcc-internal-format
msgid "Variable %qs in common block %qs at %C cannot be bind(c) since it is not global"
msgstr "Variabel %qs i common-block %qs vid %C får inte vara bind(c) eftersom det inte är globalt"
@@ -57362,10 +56943,9 @@ msgid "Symbol %qs, in COMMON block %qs at %C is being indirectly equivalenced to
msgstr "Symbolen %qs, i COMMON-block %qs vid %C är indirekt gjort ekvivalent med ett annat COMMON-block %qs"
#: fortran/match.c:5280
-#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "BLOCK construct at %C"
+#, gcc-internal-format, gfc-internal-format
msgid "BLOCK DATA construct at %L"
-msgstr "BLOCK-konstruktion vid %C"
+msgstr "BLOCK DATA-konstruktion vid %L"
#: fortran/match.c:5364
#, gcc-internal-format
@@ -57408,10 +56988,9 @@ msgid "Expecting a comma in EQUIVALENCE at %C"
msgstr "Komma förväntades i EQUIVALENCE vid %C"
#: fortran/match.c:5600
-#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "VALUE statement at %C"
+#, gcc-internal-format, gfc-internal-format
msgid "EQUIVALENCE statement at %C"
-msgstr "VALUE-sats vid %C"
+msgstr "EQUIVALENCE-sats vid %C"
#: fortran/match.c:5714
#, gcc-internal-format, gfc-internal-format
@@ -57690,8 +57269,7 @@ msgid "write_symtree(): Symbol not written"
msgstr "write_symtree(): Symbolen inte skriven"
#: fortran/module.c:6229
-#, fuzzy, gcc-internal-format
-#| msgid "Can't open module file %qs for writing at %C: %s"
+#, gcc-internal-format
msgid "Cannot open module file %qs for writing at %C: %s"
msgstr "Kan inte öppna modulfilen %qs för skrivning vid %C: %s"
@@ -57701,20 +57279,17 @@ msgid "Error writing module file %qs for writing: %s"
msgstr "Fel när modulfilen %qs skrevs: %s"
#: fortran/module.c:6261
-#, fuzzy, gcc-internal-format
-#| msgid "Can't delete module file %qs: %s"
+#, gcc-internal-format
msgid "Cannot delete module file %qs: %s"
msgstr "Kan inte radera modulfilen %qs: %s"
#: fortran/module.c:6264
-#, fuzzy, gcc-internal-format
-#| msgid "Can't rename module file %qs to %qs: %s"
+#, gcc-internal-format
msgid "Cannot rename module file %qs to %qs: %s"
msgstr "Kan inte ändra namn på modulfilen %qs till %qs: %s"
#: fortran/module.c:6270
-#, fuzzy, gcc-internal-format
-#| msgid "Can't delete temporary module file %qs: %s"
+#, gcc-internal-format
msgid "Cannot delete temporary module file %qs: %s"
msgstr "Kan inte radera temporär modulfil %qs: %s"
@@ -57779,8 +57354,7 @@ msgid "ISO_C_BINDING module at %C"
msgstr "ISO_C_BINDING-modul vid %C"
#: fortran/module.c:7059
-#, fuzzy, gcc-internal-format
-#| msgid "Can't find an intrinsic module named %qs at %C"
+#, gcc-internal-format
msgid "Cannot find an intrinsic module named %qs at %C"
msgstr "Det finns ingen inbyggd modul med namnet %qs vid %C"
@@ -57800,8 +57374,7 @@ msgid "IEEE_ARITHMETIC module at %C"
msgstr "IEEE_ARITHMETIC-modul vid %C"
#: fortran/module.c:7087
-#, fuzzy, gcc-internal-format
-#| msgid "Can't open module file %qs for reading at %C: %s"
+#, gcc-internal-format
msgid "Cannot open module file %qs for reading at %C: %s"
msgstr "Kan inte öppna modulfilen %qs för läsning vid %C: %s"
@@ -57826,16 +57399,14 @@ msgid "Cannot read module file %qs opened at %C, because it was created by a dif
msgstr "Kan inte läsa modulfilen %qs öppnad vid %C, eftersom den skapades av en annan version av GNU Fortran"
#: fortran/module.c:7149
-#, fuzzy, gcc-internal-format
-#| msgid "Can't USE the same %smodule we're building"
+#, gcc-internal-format
msgid "Cannot USE a submodule that is currently built"
-msgstr "Det går inte att USE samma %smodul vi bygger"
+msgstr "Det går inte att göra USE på en submodul som just nu byggs"
#: fortran/module.c:7151
-#, fuzzy, gcc-internal-format
-#| msgid "Can't USE the same %smodule we're building"
+#, gcc-internal-format
msgid "Cannot USE a module that is currently built"
-msgstr "Det går inte att USE samma %smodul vi bygger"
+msgstr "Det går inte att göra USE på en modul som just nu byggs"
#: fortran/openmp.c:296 fortran/openmp.c:397 fortran/openmp.c:692
#: fortran/openmp.c:3238
@@ -57934,10 +57505,9 @@ msgid "Only the !$ACC ROUTINE form without list is allowed in interface block at
msgstr "Endast formen !$ACC ROUTINE utan en lista är tillåten i gränssnittsblock vid %C"
#: fortran/openmp.c:2327
-#, fuzzy, gcc-internal-format
-#| msgid "Syntax error in !$ACC ROUTINE ( NAME ) at %C"
+#, gcc-internal-format
msgid "Invalid NAME %qs in !$ACC ROUTINE ( NAME ) at %C"
-msgstr "Syntaxfel i !ACC$ ROUTINE ( NAME ) vid %C"
+msgstr "Felaktigt NAME %qs i !ACC$ ROUTINE ( NAME ) vid %C"
#: fortran/openmp.c:2335
#, gcc-internal-format, gfc-internal-format
@@ -57950,10 +57520,9 @@ msgid "Syntax error in !$ACC ROUTINE ( NAME ) at %C, expecting ')' after NAME"
msgstr "Syntaxfel i !$ACC ROUTINE ( NAMN ) vid %C, ')' förväntades efter NAMN"
#: fortran/openmp.c:2357
-#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Multiple loop axes specified for routine"
+#, gcc-internal-format, gfc-internal-format
msgid "Multiple loop axes specified for routine at %C"
-msgstr "Multipla slingaxlar angivna för rutinen"
+msgstr "Multipla slingaxlar angivna för rutinen vid %C"
#: fortran/openmp.c:2367
#, gcc-internal-format, gfc-internal-format
@@ -58252,10 +57821,9 @@ msgid "INTEGER expression of SCHEDULE clause's chunk_size at %L must be positive
msgstr "INTEGER-uttryck i SCHEDULE-klausulens chunk_size vid %L måste vara positivt"
#: fortran/openmp.c:4157
-#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "%<nonmonotonic%> modifier specified for %qs schedule kind"
+#, gcc-internal-format, gfc-internal-format
msgid "NONMONOTONIC modifier specified for %s schedule kind at %L"
-msgstr "%<nonmonotonic%>-modifierare angiven för schemaläggningssort %qs"
+msgstr "NONMONOTONIC-modifierare angiven för %s schemaläggningssort vid %L"
#: fortran/openmp.c:4161
#, gcc-internal-format, gfc-internal-format
@@ -58642,10 +58210,9 @@ msgid "!$ACC LOOP cannot be a DO WHILE or DO without loop control at %L"
msgstr "!$ACC LOOP får inte vara en DO WHILE eller DO utan slingstyrning vid %L"
#: fortran/openmp.c:5836
-#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "%s cannot be a DO CONCURRENT loop at %L"
+#, gcc-internal-format, gfc-internal-format
msgid "!$ACC LOOP cannot be a DO CONCURRENT loop at %L"
-msgstr "%s kan inte vara en DO CONCURRENT-slinga vid %L"
+msgstr "!$ACC LOOP kan inte vara en DO CONCURRENT-slinga vid %L"
#: fortran/openmp.c:5842
#, gcc-internal-format, gfc-internal-format
@@ -58693,16 +58260,14 @@ msgid "Array sections: %qs not allowed in !$ACC DECLARE at %L"
msgstr "Vektorsektioner: %qs är inte tillåtet i !$ACC DECLARE vid %L"
#: fortran/openmp.c:6100
-#, fuzzy, gcc-internal-format
-#| msgid "Syntax error in !$ACC ROUTINE ( NAME ) at %C"
+#, gcc-internal-format
msgid "NAME %qs does not refer to a subroutine or function in !$ACC ROUTINE ( NAME ) at %L"
-msgstr "Syntaxfel i !ACC$ ROUTINE ( NAME ) vid %C"
+msgstr "NAME %qs refererar inte till en subrutin eller funktion i !ACC$ ROUTINE ( NAME ) vid %L"
#: fortran/openmp.c:6106
-#, fuzzy, gcc-internal-format
-#| msgid "Syntax error in !$ACC ROUTINE ( NAME ) at %C"
+#, gcc-internal-format
msgid "NAME %qs invalid in !$ACC ROUTINE ( NAME ) at %L"
-msgstr "Syntaxfel i !ACC$ ROUTINE ( NAME ) vid %C"
+msgstr "NAME %qs är felaktigt i !ACC$ ROUTINE ( NAME ) vid %L"
#: fortran/openmp.c:6207
#, gcc-internal-format, gfc-internal-format
@@ -58755,10 +58320,9 @@ msgid "Missing INITIALIZER clause for !$OMP DECLARE REDUCTION of derived type wi
msgstr "INITIALIZER-klausul saknas i !$OMP DECLARE REDUCTION av härledd typ utan standardinitierare vid %L"
#: fortran/options.c:266
-#, fuzzy, gcc-internal-format
-#| msgid "-fexcess-precision=standard for Fortran"
+#, gcc-internal-format
msgid "%<-fexcess-precision=standard%> for Fortran"
-msgstr "-fexcess-precision=standard för Fortran"
+msgstr "%<-fexcess-precision=standard%> för Fortran"
#: fortran/options.c:356
#, gcc-internal-format
@@ -59374,10 +58938,9 @@ msgid "Integer kind %d at %C not available"
msgstr "Heltalssort %d vid %C inte tillgänglig"
#: fortran/primary.c:239
-#, fuzzy, gcc-internal-format
-#| msgid "Integer too big for its kind at %C. This check can be disabled with the option -fno-range-check"
+#, gcc-internal-format
msgid "Integer too big for its kind at %C. This check can be disabled with the option %<-fno-range-check%>"
-msgstr "Heltal för stort för sin sort vid %C. Denna kontroll kan avaktiveras med flaggan -fno-range-check"
+msgstr "Heltal för stort för sin sort vid %C. Denna kontroll kan avaktiveras med flaggan %<-fno-range-check%>"
#: fortran/primary.c:267
#, gcc-internal-format, gfc-internal-format
@@ -59550,8 +59113,7 @@ msgid "Syntax error in COMPLEX constant at %C"
msgstr "Syntaxfel i COMPLEX-konstant vid %C"
#: fortran/primary.c:1573
-#, fuzzy, gcc-internal-format
-#| msgid "Namelist %qs can not be an argument at %L"
+#, gcc-internal-format
msgid "Namelist %qs cannot be an argument at %L"
msgstr "Namnlistan %qs kan inte vara ett argument vid %L"
@@ -59616,10 +59178,9 @@ msgid "Expected argument list at %C"
msgstr "Argumentlista förväntades vid %C"
#: fortran/primary.c:2296
-#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid ".XOR. operator at %C"
+#, gcc-internal-format, gfc-internal-format
msgid "RE or IM part_ref at %C"
-msgstr ".XOR.-operator vid %C"
+msgstr "RE eller IM part_ref vid %C"
#: fortran/primary.c:2301
#, gcc-internal-format, gfc-internal-format
@@ -59627,16 +59188,14 @@ msgid "The RE or IM part_ref at %C must be applied to a COMPLEX expression"
msgstr "part_ref:en RE eller IM vid %C måste tillämpas på ett COMPLEX-uttryck"
#: fortran/primary.c:2314
-#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "UNTIL_COUNT= argument at %L must be a scalar INTEGER expression"
+#, gcc-internal-format, gfc-internal-format
msgid "The LEN part_ref at %C must be applied to a CHARACTER expression"
-msgstr "UNTIL_COUNT=-argumentet vid %L måste vara ett skalärt INTEGER-uttryck"
+msgstr "LEN part_ref:en vid %C måste tillämpas på ett CHARACTER-uttryck"
#: fortran/primary.c:2330
-#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "KIND parameter of %s at %L must be an initialization expression"
+#, gcc-internal-format, gfc-internal-format
msgid "The KIND part_ref at %C must be applied to an expression of intrinsic type"
-msgstr "KIND-parametern till â€%s†vid %L mÃ¥ste vara ett initieringsuttryck"
+msgstr "KIND-part_ref:en vid %C måste tillämpas på ett uttryck av inbyggd typ"
#: fortran/primary.c:2358
#, gcc-internal-format
@@ -59689,8 +59248,7 @@ msgid "No initializer for component %qs given in the structure constructor at %C
msgstr "Ingen initierare för komponent %qs angiven i postkonstrueraren vid %C"
#: fortran/primary.c:2982
-#, fuzzy, gcc-internal-format
-#| msgid "Can't construct ABSTRACT type %qs at %L"
+#, gcc-internal-format
msgid "Cannot construct ABSTRACT type %qs at %L"
msgstr "Det går inte att konstruera ABSTRACT typ %qs vid %L"
@@ -59710,10 +59268,9 @@ msgid "Too many components in structure constructor at %L"
msgstr "För många komponenter i postkonstruerare vid %L"
#: fortran/primary.c:3080
-#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "CHARACTER expression will be truncated in assignment (%ld/%ld) at %L"
+#, gcc-internal-format, gfc-internal-format
msgid "CHARACTER expression will be truncated in constructor (%ld/%ld) at %L"
-msgstr "CHARACTER-uttryck kommer att huggas av i tilldelning (%ld/%ld) vid %L"
+msgstr "CHARACTER-uttryck kommer att huggas av i konstruerare (%ld/%ld) vid %L"
#: fortran/primary.c:3098
#, gcc-internal-format
@@ -59761,8 +59318,7 @@ msgid "Missing argument to %qs at %C"
msgstr "Argument saknas till %qs vid %C"
#: fortran/primary.c:3601
-#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "The leftmost part-ref in a data-ref can not be a function reference at %C"
+#, gcc-internal-format, gfc-internal-format
msgid "The leftmost part-ref in a data-ref cannot be a function reference at %C"
msgstr "Den vänstraste part-ref i en data-ref kan inte vara en funktionsreferens vid %C"
@@ -59954,46 +59510,39 @@ msgid "Function %s at %L with entries returning variables of different string le
msgstr "Funktionen â€%s†vid %L med ingÃ¥ngar som returnerar variabler av olika stränglängder"
#: fortran/resolve.c:841
-#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "FUNCTION result %s can't be an array in FUNCTION %s at %L"
+#, gcc-internal-format, gfc-internal-format
msgid "FUNCTION result %s cannot be an array in FUNCTION %s at %L"
msgstr "FUNCTION-resultat %s får inte vara en vektor i FUNCTION %s vid %L"
#: fortran/resolve.c:845
-#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "ENTRY result %s can't be an array in FUNCTION %s at %L"
+#, gcc-internal-format, gfc-internal-format
msgid "ENTRY result %s cannot be an array in FUNCTION %s at %L"
msgstr "ENTRY-resultat %s får inte vara en vektor i FUNCTION %s vid %L"
#: fortran/resolve.c:852
-#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "FUNCTION result %s can't be a POINTER in FUNCTION %s at %L"
+#, gcc-internal-format, gfc-internal-format
msgid "FUNCTION result %s cannot be a POINTER in FUNCTION %s at %L"
msgstr "FUNCTION-resultat %s får inte vara en POINTER i FUNCTION %s vid %L"
#: fortran/resolve.c:856
-#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "ENTRY result %s can't be a POINTER in FUNCTION %s at %L"
+#, gcc-internal-format, gfc-internal-format
msgid "ENTRY result %s cannot be a POINTER in FUNCTION %s at %L"
msgstr "ENTRY-resultat %s får inte vara en POINTER i FUNCTION %s vid %L"
#: fortran/resolve.c:894
-#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "FUNCTION result %s can't be of type %s in FUNCTION %s at %L"
+#, gcc-internal-format, gfc-internal-format
msgid "FUNCTION result %s cannot be of type %s in FUNCTION %s at %L"
msgstr "FUNCTION-resultat %s får inte vara av typen %s i FUNCTION %s vid %L"
#: fortran/resolve.c:899
-#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "ENTRY result %s can't be of type %s in FUNCTION %s at %L"
+#, gcc-internal-format, gfc-internal-format
msgid "ENTRY result %s cannot be of type %s in FUNCTION %s at %L"
msgstr "ENTRY-resultat %s får inte vara av typen %s i FUNCTION %s vid %L"
#: fortran/resolve.c:945
-#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "COMMON block /%s/ not found at %C"
+#, gcc-internal-format, gfc-internal-format
msgid "COMMON block at %L"
-msgstr "COMMON-block /%s/ finns inte vid %C"
+msgstr "COMMON-block vid %L"
#: fortran/resolve.c:952
#, gcc-internal-format
@@ -60051,8 +59600,7 @@ msgid "COMMON block %qs at %L is used as PARAMETER at %L"
msgstr "COMMON-block %qs vid %L används som PARAMETER vid %L"
#: fortran/resolve.c:1092
-#, fuzzy, gcc-internal-format
-#| msgid "COMMON block %qs at %L can not have the EXTERNAL attribute"
+#, gcc-internal-format
msgid "COMMON block %qs at %L cannot have the EXTERNAL attribute"
msgstr "COMMON-blocket %qs vid %L får inte ha attributet EXTERNAL"
@@ -60383,16 +59931,14 @@ msgid "logical_to_bitwise(): Bad intrinsic"
msgstr "logical_to_bitwise(): Felaktig inbyggd"
#: fortran/resolve.c:3863
-#, fuzzy, gcc-internal-format
-#| msgid "CHARACTER(*) function %qs at %L cannot be pointer-valued"
+#, gcc-internal-format
msgid "Impure function %qs at %L might not be evaluated"
-msgstr "CHARACTER(*)-funktion %qs vid %L kan inte ha pekarvärde"
+msgstr "Den orena funktionen %qs vid %L beräknas eventuellt inte"
#: fortran/resolve.c:3867
-#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "always_inline function might not be inlinable"
+#, gcc-internal-format, gfc-internal-format
msgid "Impure function at %L might not be evaluated"
-msgstr "always_inline-funktion kanske inte kan inline:as"
+msgstr "Den orena funktionen vid %L beräknas eventuellt inte"
#: fortran/resolve.c:4144
#, gcc-internal-format
@@ -60648,10 +60194,9 @@ msgid "Coindexed object with polymorphic allocatable subcomponent at %L"
msgstr "Co-indexerat objekt med polymorf allokerbar delkomponent vid %L"
#: fortran/resolve.c:5956 fortran/resolve.c:6108
-#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Error in type-spec at %L"
+#, gcc-internal-format, gfc-internal-format
msgid "Error in typebound call at %L"
-msgstr "Fel i typspecifikation vid %L"
+msgstr "Fel i typbundet anrop vid %L"
#: fortran/resolve.c:6072
#, gcc-internal-format, gfc-internal-format
@@ -61174,10 +60719,9 @@ msgid "The FORALL with index %qs is not used on the left side of the assignment
msgstr "FORALL med index %qs används inte på vänster sida av en tilldelning vid %L och kan därför orsaka multipla tilldelningar till detta objekt"
#: fortran/resolve.c:10180
-#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "BLOCK construct at %C"
+#, gcc-internal-format, gfc-internal-format
msgid "FORALL construct at %L"
-msgstr "BLOCK-konstruktion vid %C"
+msgstr "FORALL-konstruktion vid %L"
#: fortran/resolve.c:10201
#, gcc-internal-format, gfc-internal-format
@@ -61609,8 +61153,7 @@ msgid "Only array FINAL procedures declared for derived type %qs defined at %L,
msgstr "Endast vektor-FINAL-procedurer deklarerade för den härledda typen %qs definierade vid %L, föreslår även en skalär"
#: fortran/resolve.c:13136
-#, fuzzy, gcc-internal-format
-#| msgid "%qs and %qs can't be mixed FUNCTION/SUBROUTINE for GENERIC %qs at %L"
+#, gcc-internal-format
msgid "%qs and %qs cannot be mixed FUNCTION/SUBROUTINE for GENERIC %qs at %L"
msgstr "%qs och %qs kan inte blandad FUNCTION/SUBROUTINE för GENERIC %qs vid %L"
@@ -61630,16 +61173,14 @@ msgid "GENERIC %qs at %L must target a specific binding, %qs is GENERIC, too"
msgstr "GENERIC %qs vid %L måste ha som mål en specifik bindning, %qs är också GENERIC"
#: fortran/resolve.c:13271
-#, fuzzy, gcc-internal-format
-#| msgid "GENERIC %qs at %L can't overwrite specific binding with the same name"
+#, gcc-internal-format
msgid "GENERIC %qs at %L cannot overwrite specific binding with the same name"
msgstr "GENERIC %qs vid %L kan inte åsidosätta en specifik bindning med samma namn"
#: fortran/resolve.c:13327
-#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Type-bound operator at %L can't be NOPASS"
+#, gcc-internal-format, gfc-internal-format
msgid "Type-bound operator at %L cannot be NOPASS"
-msgstr "Typgränsoperator vid %L kan inte vara NOPASS"
+msgstr "Typbindningsoperator vid %L kan inte vara NOPASS"
#: fortran/resolve.c:13519
#, gcc-internal-format
@@ -61807,10 +61348,9 @@ msgid "Generic name %qs of function %qs at %L being the same name as derived typ
msgstr "Det generiska namnet %qs på funktionen %qs vid %L är samma namn som den härledda typen vid %L"
#: fortran/resolve.c:14433
-#, fuzzy, gcc-internal-format
-#| msgid "Derived type %qs at %L must be extensible"
+#, gcc-internal-format
msgid "Derived type %qs at %L has not been declared"
-msgstr "Härledd typ %qs vid %L måste vara utökningsbar"
+msgstr "Härledd typ %qs vid %L har inte deklarerats"
#: fortran/resolve.c:14498
#, gcc-internal-format
@@ -62093,8 +61633,7 @@ msgid "LOGICAL result variable %qs at %L with non-C_Bool kind in BIND(C) procedu
msgstr "LOGICAL-resultatvariabeln %qs vid %L med icke-C_Bool-sort i BIND(C)-proceduren %qs"
#: fortran/resolve.c:15430
-#, fuzzy, gcc-internal-format
-#| msgid "Namelist %qs can not be an argument to subroutine or function at %L"
+#, gcc-internal-format
msgid "Namelist %qs cannot be an argument to subroutine or function at %L"
msgstr "Namnlistan %qs får inte vara ett argument till en subrutin eller funktion vid %L"
@@ -62109,10 +61648,9 @@ msgid "!$OMP DECLARE TARGET variable %qs at %L isn't SAVEd"
msgstr "!$OMP DECLARE TARGET-variabeln %qs vid %L är inte SAVE:ad"
#: fortran/resolve.c:15616
-#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Expecting list of named entities at %C"
+#, gcc-internal-format, gfc-internal-format
msgid "Expecting definable entity near %L"
-msgstr "Lista med namngivna entiteter förväntades vid %C"
+msgstr "Definierbar entitet förväntades nära %L"
#: fortran/resolve.c:15624
#, gcc-internal-format
@@ -62360,8 +61898,7 @@ msgid "Illegal preprocessor directive"
msgstr "Ogiltigt preprocessordirektiv"
#: fortran/scanner.c:2471
-#, fuzzy, gcc-internal-format
-#| msgid "Can't open file %qs"
+#, gcc-internal-format
msgid "Cannot open file %qs"
msgstr "Kan inte öppna filen %qs"
@@ -62612,10 +62149,9 @@ msgid "gfc_simplify_mod(): Bad arguments"
msgstr "gfc_simplify_mod(): Felaktiga argument"
#: fortran/simplify.c:5906 fortran/simplify.c:5914
-#, fuzzy, gcc-internal-format
-#| msgid "Argument %qs of MOD at %L shall not be zero"
+#, gcc-internal-format
msgid "Argument %qs of MODULO at %L shall not be zero"
-msgstr "Argument %qs till MOD vid %L får inte vara noll"
+msgstr "Argument %qs till MODULO vid %L får inte vara noll"
#: fortran/simplify.c:5920
#, gcc-internal-format
@@ -63030,10 +62566,9 @@ msgid "Shared DO termination label %d at %C"
msgstr "Delad DO-avslutningsetikett %d vid %C"
#: fortran/symbol.c:2814
-#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "LOCK statement at %C"
+#, gcc-internal-format, gfc-internal-format
msgid "Labeled DO statement at %L"
-msgstr "LOCK-sats vid %C"
+msgstr "Etiketterad DO-sats vid %L"
#: fortran/symbol.c:3143
#, gcc-internal-format
@@ -63206,16 +62741,14 @@ msgid "The equivalence set for %qs cause an invalid extension to COMMON %qs at %
msgstr "Ekvivalensmängden för %qs orsakar en ogiltig utvidgning av COMMON %qs vid %L"
#: fortran/trans-common.c:1157
-#, fuzzy, gcc-internal-format
-#| msgid "Padding of %d bytes required before %qs in COMMON %qs at %L; reorder elements or use -fno-align-commons"
+#, gcc-internal-format
msgid "Padding of %d bytes required before %qs in COMMON %qs at %L; reorder elements or use %<-fno-align-commons%>"
-msgstr "Utfyllnad med %d byte krävs före %qs i COMMON %qs vid %L, byt ordning på element eller använd -fno-align-commons"
+msgstr "Utfyllnad med %d byte krävs före %qs i COMMON %qs vid %L, byt ordning på element eller använd %<-fno-align-commons%>"
#: fortran/trans-common.c:1163
-#, fuzzy, gcc-internal-format
-#| msgid "Padding of %d bytes required before %qs in COMMON at %L; reorder elements or use -fno-align-commons"
+#, gcc-internal-format
msgid "Padding of %d bytes required before %qs in COMMON at %L; reorder elements or use %<-fno-align-commons%>"
-msgstr "Utfyllnad med %d byte krävs före %qs i COMMON vid %L, byt ordning på element eller använd -fno-align-commons"
+msgstr "Utfyllnad med %d byte krävs före %qs i COMMON vid %L, byt ordning på element eller använd %<-fno-align-commons%>"
#: fortran/trans-common.c:1184
#, gcc-internal-format
@@ -63313,8 +62846,7 @@ msgid "Sorry, !$ACC DECLARE at %L is not allowed in BLOCK construct"
msgstr "Ledsen, !$ACC DECLARE vid %L är inte tillåtet i BLOCK-konstruktion"
#: fortran/trans-expr.c:929
-#, fuzzy, gcc-internal-format, gfc-internal-format
-#| msgid "Can't compute the length of the char array at %L."
+#, gcc-internal-format, gfc-internal-format
msgid "Cannot compute the length of the char array at %L."
msgstr "Kan inte beräkna längden på teckenvektorn vid %L."
@@ -63495,16 +63027,14 @@ msgid "%s:%s: %E: %E"
msgstr "%s:%s: %E: %E"
#: lto/lto-lang.c:867
-#, fuzzy, gcc-internal-format
-#| msgid "-fwpa and -fltrans are mutually exclusive"
+#, gcc-internal-format
msgid "%<-fwpa%> and %<-fltrans%> are mutually exclusive"
-msgstr "-fwpa och -fltrans är ömsesidigt uteslutande"
+msgstr "%<-fwpa%> och %<-fltrans%> är ömsesidigt uteslutande"
#: lto/lto-lang.c:901
-#, fuzzy, gcc-internal-format
-#| msgid "-fwpa and -fltrans are mutually exclusive"
+#, gcc-internal-format
msgid "%<-flinker-output=rel%> and %<-fltrans%> are mutually exclussive"
-msgstr "-fwpa och -fltrans är ömsesidigt uteslutande"
+msgstr "%<-fwpa%> och %<-fltrans%> är ömsesidigt uteslutande"
#: lto/lto-object.c:107
#, gcc-internal-format, gfc-internal-format
@@ -63563,10 +63093,9 @@ msgid "previously defined here"
msgstr "tidigare definition här"
#: lto/lto-symtab.c:712
-#, fuzzy, gcc-internal-format
-#| msgid "%qD violates the C++ One Definition Rule "
+#, gcc-internal-format
msgid "%qD violates the C++ One Definition Rule"
-msgstr "%qD bryter mot C++ endefinitionsregel "
+msgstr "%qD bryter mot C++ endefinitionsregel"
#: lto/lto-symtab.c:718
#, gcc-internal-format
@@ -63589,10 +63118,9 @@ msgid "%qD was previously declared here"
msgstr "%qD deklarerades tidigare här"
#: lto/lto-symtab.c:752
-#, fuzzy, gcc-internal-format
-#| msgid "code may be misoptimized unless -fno-strict-aliasing is used"
+#, gcc-internal-format
msgid "code may be misoptimized unless %<-fno-strict-aliasing%> is used"
-msgstr "koden kan feloptimeras om inte -fno-strict-aliasing används"
+msgstr "koden kan feloptimeras om inte %<-fno-strict-aliasing%> används"
#: lto/lto-symtab.c:838
#, gcc-internal-format
@@ -63835,8 +63363,7 @@ msgid "invalid property declaration"
msgstr "ogiltig egenskapsdeklaration"
#: objc/objc-act.c:910
-#, fuzzy, gcc-internal-format
-#| msgid "property can not be an array"
+#, gcc-internal-format
msgid "property cannot be an array"
msgstr "en egenskap kan inte vara en vektor"
@@ -63848,8 +63375,7 @@ msgstr "en egenskap kan inte vara en vektor"
#. underlying instance variable could be a bitfield, but that is
#. a different matter.
#: objc/objc-act.c:928
-#, fuzzy, gcc-internal-format
-#| msgid "property can not be a bit-field"
+#, gcc-internal-format
msgid "property cannot be a bit-field"
msgstr "en egenskap kan inte vara ett bitfält"
@@ -63888,22 +63414,19 @@ msgid "originally specified here"
msgstr "ursprungligen specificerad här"
#: objc/objc-act.c:1093
-#, fuzzy, gcc-internal-format
-#| msgid "'nonatomic' attribute of property %qD conflicts with previous declaration"
+#, gcc-internal-format
msgid "%<nonatomic%> attribute of property %qD conflicts with previous declaration"
-msgstr "attributet â€nonatomic†för egenskap %qD stÃ¥r i konflikt med tidigare deklaration"
+msgstr "attributet %<nonatomic%> för egenskap %qD står i konflikt med tidigare deklaration"
#: objc/objc-act.c:1104
-#, fuzzy, gcc-internal-format
-#| msgid "'getter' attribute of property %qD conflicts with previous declaration"
+#, gcc-internal-format
msgid "%<getter%> attribute of property %qD conflicts with previous declaration"
-msgstr "attributet â€getter†för egenskap %qD stÃ¥r i konflikt med tidigare deklaration"
+msgstr "attributet %<getter%> för egenskap %qD står i konflikt med tidigare deklaration"
#: objc/objc-act.c:1118
-#, fuzzy, gcc-internal-format
-#| msgid "'setter' attribute of property %qD conflicts with previous declaration"
+#, gcc-internal-format
msgid "%<setter%> attribute of property %qD conflicts with previous declaration"
-msgstr "attributet â€setter†för egenskap %qD stÃ¥r i konflikt med tidigare deklaration"
+msgstr "attributet %<setter%> för egenskap %qD står i konflikt med tidigare deklaration"
#: objc/objc-act.c:1130
#, gcc-internal-format
@@ -63911,10 +63434,9 @@ msgid "assign semantics attributes of property %qD conflict with previous declar
msgstr "attribut för tilldelningssemantik för egenskap %qD står i konflikt med tidigare deklaration"
#: objc/objc-act.c:1141
-#, fuzzy, gcc-internal-format
-#| msgid "'readonly' attribute of property %qD conflicts with previous declaration"
+#, gcc-internal-format
msgid "%<readonly%> attribute of property %qD conflicts with previous declaration"
-msgstr "attributet â€readonly†för egenskap %qD stÃ¥r i konflikt med tidigare deklaration"
+msgstr "attributet %<readonly%> för egenskap %qD står i konflikt med tidigare deklaration"
#: objc/objc-act.c:1180
#, gcc-internal-format
@@ -63951,8 +63473,7 @@ msgid "could not find setter/getter for %qE in class %qE"
msgstr "det går inte att hitta setter/getter för %qE i klassen %qE"
#: objc/objc-act.c:1750
-#, fuzzy, gcc-internal-format
-#| msgid "readonly property can not be set"
+#, gcc-internal-format
msgid "readonly property cannot be set"
msgstr "egenskapen readonly kan inte sättas"
@@ -63972,8 +63493,7 @@ msgid "method definition not in @implementation context"
msgstr "metoddefinition som inte är i @implementation-kontext"
#: objc/objc-act.c:2060
-#, fuzzy, gcc-internal-format
-#| msgid "method attributes can not be specified in @implementation context"
+#, gcc-internal-format
msgid "method attributes cannot be specified in @implementation context"
msgstr "metodattribut kan inte anges i @implementation-kontext"
@@ -64133,8 +63653,7 @@ msgid "@catch parameter is not a known Objective-C class type"
msgstr "@catch-parameter är inte en känd Objective-C-klasstyp"
#: objc/objc-act.c:4217
-#, fuzzy, gcc-internal-format
-#| msgid "@catch parameter can not be protocol-qualified"
+#, gcc-internal-format
msgid "@catch parameter cannot be protocol-qualified"
msgstr "@catch-parameter kan inte vara protokollkvalificerad"
@@ -64179,8 +63698,7 @@ msgid "inconsistent instance variable specification"
msgstr "inkonsistent specifikation av instansvariabel"
#: objc/objc-act.c:4684
-#, fuzzy, gcc-internal-format
-#| msgid "can not use an object as parameter to a method"
+#, gcc-internal-format
msgid "cannot use an object as parameter to a method"
msgstr "det går inte att använda ett objekt som parameter till en metod"
@@ -64455,8 +63973,7 @@ msgid "duplicate interface declaration for class %qE"
msgstr "dubblerad gränssnittsdeklaration av klass %qE"
#: objc/objc-act.c:7232 objc/objc-act.c:7428
-#, fuzzy, gcc-internal-format
-#| msgid "can not find instance variable associated with property"
+#, gcc-internal-format
msgid "cannot find instance variable associated with property"
msgstr "det går inte att hitta någon instansvariabel associerad med egenskapen"
@@ -64492,16 +64009,14 @@ msgid "property %qs is using instance variable %qs of incompatible type"
msgstr "egenskapen %qs använder instansvariabeln %qs av inkompatibel typ"
#: objc/objc-act.c:7645
-#, fuzzy, gcc-internal-format
-#| msgid "'assign' property %qs is using bit-field instance variable %qs"
+#, gcc-internal-format
msgid "%<assign%> property %qs is using bit-field instance variable %qs"
-msgstr "â€assignâ€-egenskap %qs använder bitfältsinstansvariabeln %qs"
+msgstr "egenskapen %<assign%> %qs använder bitfältsinstansvariabeln %qs"
#: objc/objc-act.c:7659
-#, fuzzy, gcc-internal-format
-#| msgid "'atomic' property %qs is using bit-field instance variable %qs"
+#, gcc-internal-format
msgid "%<atomic%> property %qs is using bit-field instance variable %qs"
-msgstr "â€atomicâ€-egenskap %qs använder bitfältsinstansvariabeln %qs"
+msgstr "egenskapen %<atomic%> %qs använder bitfältsinstansvariabeln %qs"
#: objc/objc-act.c:7678
#, gcc-internal-format
@@ -64523,8 +64038,7 @@ msgid "%<@synthesize%> not in @implementation context"
msgstr "%<@synthesize%> som inte är i @implementation-kontext"
#: objc/objc-act.c:7736
-#, fuzzy, gcc-internal-format
-#| msgid "%<@synthesize%> can not be used in categories"
+#, gcc-internal-format
msgid "%<@synthesize%> cannot be used in categories"
msgstr "%<@synthesize%> kan inte användas i kategorier"
@@ -64737,10 +64251,9 @@ msgid "no class name specified with %qs"
msgstr "inget klassnamn angivet med %qs"
#: c-family/c.opt:1519
-#, fuzzy, gcc-internal-format
-#| msgid "-fhandle-exceptions has been renamed -fexceptions (and is now on by default)"
+#, gcc-internal-format
msgid "%<-fhandle-exceptions%> has been renamed %<-fexceptions%> (and is now on by default)"
-msgstr "-fhandle-exceptions har bytt namn till -fexceptions (och är nu normalt påslagen)"
+msgstr "%<-fhandle-exceptions%> har bytt namn till %<-fexceptions%> (och är nu normalt påslagen)"
#: c-family/c.opt:1602
#, gcc-internal-format
@@ -64914,1778 +64427,3 @@ msgstr "okänt synlighetsvärde %qs"
#, gcc-internal-format
msgid "unknown vtable verify initialization priority %qs"
msgstr "okänd initieringsprioritet för vtable-verifiering %qs"
-
-#~ msgid "%qE output %wu bytes into a destination of size %wu"
-#~ msgstr "%qE-utdata på %wu byte in i en destination med storlek %wu"
-
-#~ msgid "%qE output %wu bytes"
-#~ msgstr "%qE-utdata %wu byte"
-
-#~ msgid "PIC is not supported for %s. Generating non-PIC code only.."
-#~ msgstr "PIC stödjs inte för %s. Genererar endast icke-PIC-kod."
-
-#~ msgid "no dispatcher found for %s"
-#~ msgstr "ingen avsändare funnen för %s"
-
-#~ msgid "invalid %%t operand %<%wd%>"
-#~ msgstr "ogiltig %%t-operand %<%wd%>â€"
-
-#~ msgid "cannot find '%s'"
-#~ msgstr "kan inte hitta â€%sâ€"
-
-#~ msgid "junk at end of '#pragma options'"
-#~ msgstr "skräp vid slutet av â€#pragma optionsâ€"
-
-#~ msgid "string literal in function template signature"
-#~ msgstr "stränglitteral i funktionsmallsignatur"
-
-#, fuzzy
-#~| msgid "narrowing conversion of %qE from %qH to %qI inside { }"
-#~ msgid "narrowing conversion of %qE from %qH to %qI "
-#~ msgstr "avsmalnande konvertering av %qE från %qH till %qI inuti { }"
-
-#~ msgid "%s is thrown but not caught"
-#~ msgstr "%s kastas men fångas inte"
-
-#, fuzzy
-#~| msgid "%qD is not an function argument"
-#~ msgid "cannot pass type %s as a function argument"
-#~ msgstr "%qD är inte en funktionsmall"
-
-#, fuzzy
-#~| msgid "cannot take address of %qs"
-#~ msgid "cannot take address of %s"
-#~ msgstr "kan inte ta adressen till %qs"
-
-#, fuzzy
-#~| msgid "cannot take address of %qs"
-#~ msgid "cannot take address of scope %s %s in @safe function %s"
-#~ msgstr "kan inte ta adressen till %qs"
-
-#, fuzzy
-#~| msgid "cannot take address of %qs"
-#~ msgid "cannot take address of %s %s in @safe function %s"
-#~ msgstr "kan inte ta adressen till %qs"
-
-#, fuzzy
-#~| msgid "Constant expression required at %C"
-#~ msgid "constant expression expected, not %s"
-#~ msgstr "Konstant uttryck krävs vid %C"
-
-#, fuzzy
-#~| msgid "write_symbol(): bad module symbol %qs"
-#~ msgid "with symbol %s is shadowing local symbol %s"
-#~ msgstr "write_symbol(): felaktig modulsymbol %qs"
-
-#, fuzzy
-#~| msgid "Loop variable at %C cannot be a sub-component"
-#~ msgid "variable __ctfe cannot be read at compile time"
-#~ msgstr "Slingvariabel vid %C får inte vara en subkomponent"
-
-#~ msgid "`%s` is not defined, perhaps `import %s;` is needed?"
-#~ msgstr "â€%s†är inte definierad, kanske â€import %s;†behövs?"
-
-#, fuzzy
-#~| msgid "valid arguments are: %s; did you mean %qs?"
-#~ msgid "undefined identifier `%s`, did you mean %s `%s`?"
-#~ msgstr "giltiga argument är: %s; menade du %qs?"
-
-#, fuzzy
-#~| msgid "valid arguments are: %s; did you mean %qs?"
-#~ msgid "undefined identifier `%s`, did you mean `%s`?"
-#~ msgstr "giltiga argument är: %s; menade du %qs?"
-
-#, fuzzy
-#~| msgid "expected identifier"
-#~ msgid "undefined identifier `%s`"
-#~ msgstr "identifierare förväntades"
-
-#, fuzzy
-#~| msgid "%qT is not a class, struct, or union type"
-#~ msgid "%s is not in a class or struct scope"
-#~ msgstr "%qT är inte en klass-, post- eller unionstyp"
-
-#, fuzzy
-#~| msgid "invalid use of non-static member function of type %qT"
-#~ msgid "'this' is only defined in non-static member functions, not %s"
-#~ msgstr "ogiltig användning av icke-statisk medlemsfunktion av typen %qT"
-
-#, fuzzy
-#~| msgid "%qT is not a class type"
-#~ msgid "%s is not in a class scope"
-#~ msgstr "%qT är inte en klasstyp"
-
-#~ msgid "class %s has no 'super'"
-#~ msgstr "klassen %s har ingen â€superâ€"
-
-#, fuzzy
-#~| msgid "no sclass for %s stab (0x%x)"
-#~ msgid "no base class for %s"
-#~ msgstr "ingen klass för %s-stab (0x%x)"
-
-#, fuzzy
-#~| msgid "%<this%> is unavailable for static member functions"
-#~ msgid "'super' is only allowed in non-static class member functions"
-#~ msgstr "%<this%> är inte tillgängligt i en statisk medlemsfunktion"
-
-#, fuzzy
-#~| msgid "%qs at %C is not a variable"
-#~ msgid "%s of type %s has no value"
-#~ msgstr "%qs vid %C är inte en variabel"
-
-#, fuzzy
-#~| msgid "number of results does not match number of values"
-#~ msgid "number of keys is %u, must match number of values %u"
-#~ msgstr "antalet resultat stämmer inte med antalet värden"
-
-#, fuzzy
-#~| msgid "forming reference to void"
-#~ msgid "forward reference of %s %s"
-#~ msgstr "formar referens till void"
-
-#, fuzzy
-#~| msgid "in expansion of macro %qs"
-#~ msgid "recursive expansion of %s '%s'"
-#~ msgstr "i expansionen av makrot %qs"
-
-#~ msgid "'this' for nested class must be a class type, not %s"
-#~ msgstr "â€this†för en nästad klass mÃ¥ste vara en klasstyp, inte %s"
-
-#, fuzzy
-#~| msgid "%qT is not a nested class of %qT"
-#~ msgid "e.new is only for allocating nested classes, not %s"
-#~ msgstr "%qT är inte en nästad klass i %qT"
-
-#~ msgid "default construction is disabled for type %s"
-#~ msgstr "standardkonstrueraren är avaktiverad för typen %s"
-
-#, fuzzy
-#~| msgid "cannot type switch on non-interface value"
-#~ msgid "cannot create instance of interface %s"
-#~ msgstr "kan inte göra en typ-switch på något som inte är ett gränssnittsvärde"
-
-#, fuzzy
-#~| msgid "cannot declare catch parameter to be of abstract class type %qT"
-#~ msgid "cannot create instance of abstract class %s"
-#~ msgstr "det går inte att deklarera en fångstparametern att vara av abstrakt klasstyp %qT"
-
-#~ msgid "outer class %s 'this' needed to 'new' nested class %s"
-#~ msgstr "den yttre klassen %s â€this†behövs för â€new†pÃ¥ den nästad klassen %s"
-
-#, fuzzy
-#~| msgid " expected a template of type %qD, got %qT"
-#~ msgid "'this' for nested class must be of type %s, not %s"
-#~ msgstr " förväntade en mall av typen %qD, fick %qT"
-
-#~ msgid "nested type %s should have the same or weaker constancy as enclosing type %s"
-#~ msgstr "den nästade typen %s skall ha samma eller svagare konstanthet som den omslutande typen %s"
-
-#~ msgid "e.new is only for allocating nested classes"
-#~ msgstr "e.new är endast till för att allokera nästade klasser"
-
-#~ msgid "outer function context of %s is needed to 'new' nested class %s"
-#~ msgstr "den yttre funktionskontexten för %s behövs för â€new†pÃ¥ den nästade klassen %s"
-
-#, fuzzy
-#~| msgid "no match for "
-#~ msgid "no allocator for %s"
-#~ msgstr "ingen matchning för "
-
-#, fuzzy
-#~| msgid "In constructor %qs"
-#~ msgid "no constructor for %s"
-#~ msgstr "I konstruerare %qs"
-
-#, fuzzy
-#~| msgid "too many arguments for format"
-#~ msgid "too many arguments for array"
-#~ msgstr "för många argument för formatsträng"
-
-#, fuzzy
-#~| msgid "REAL array index at %L"
-#~ msgid "negative array index %s"
-#~ msgstr "REAL-vektorindex vid %L"
-
-#, fuzzy
-#~| msgid "too many arguments to constructor %q#D"
-#~ msgid "more than one argument for construction of %s"
-#~ msgstr "för många argument till konstrueraren %q#D"
-
-#~ msgid "new can only create structs, dynamic arrays or class objects, not %s's"
-#~ msgstr "new kan endast skapa strukturer, dynamiska vektorer eller klassobjekt, inte %s:er"
-
-#, fuzzy
-#~| msgid "%qs has overflowed"
-#~ msgid "%s has no value"
-#~ msgstr "%qs har spillt över"
-
-#, fuzzy
-#~| msgid "cannot convert to a pointer type"
-#~ msgid "cannot infer function literal type"
-#~ msgstr "kan inte konvertera till en pekartyp"
-
-#, fuzzy
-#~| msgid "declaration of %qD as array of void"
-#~ msgid "declaration %s is already defined"
-#~ msgstr "deklaration av %qD som en vektor av void"
-
-#, fuzzy
-#~| msgid "%qD is already defined in the class %qT"
-#~ msgid "declaration %s is already defined in another scope in %s"
-#~ msgstr "%qD är redan definierad i klassen %qT"
-
-#~ msgid "%s %s is shadowing %s %s"
-#~ msgstr "%s %s skuggar %s %s"
-
-#, fuzzy
-#~| msgid "no data type for mode %qs"
-#~ msgid "no type for typeid(%s)"
-#~ msgstr "ingen datatyp för läge %qs"
-
-#, fuzzy
-#~| msgid "non-constant condition for static assertion"
-#~ msgid "can only declare type aliases within static if conditionals or static asserts"
-#~ msgstr "icke-konstant villkor i statisk deklaration"
-
-#, fuzzy
-#~| msgid "incompatible types in binary expression"
-#~ msgid "incomplete mixin expression (%s)"
-#~ msgstr "inkompatibla typer i binärt uttryck"
-
-#~ msgid "need -Jpath switch to import text file %s"
-#~ msgstr "flaggan -Jpath behövs för att importera textfilen %s"
-
-#~ msgid "file %s cannot be found or not in a path specified with -J"
-#~ msgstr "filen %s finns inte eller ligger inte i någon sökväg som anges med -J"
-
-#, fuzzy
-#~| msgid "Cannot read %s"
-#~ msgid "cannot read file %s"
-#~ msgstr "Kan inte läsa %s"
-
-#, fuzzy
-#~| msgid "%qE is not a constant expression"
-#~ msgid "%s is not an expression"
-#~ msgstr "%qE är inte ett konstant uttryck"
-
-#~ msgid "%smethod %s is not callable using a %s%s"
-#~ msgstr "%smetoden %s kan inte anropas med ett %s%s"
-
-#, fuzzy
-#~| msgid "recursive evaluation of default argument for %q#D"
-#~ msgid "recursive evaluation of %s"
-#~ msgstr "rekursiv beräkning av standardargument till %q#D"
-
-#, fuzzy
-#~| msgid "%s does not support %s"
-#~ msgid "%s %s does not overload ()"
-#~ msgstr "%s stödjer inte %s"
-
-#, fuzzy
-#~| msgid "cannot call member function %qD without object"
-#~ msgid "cannot call public/export function %s from invariant"
-#~ msgstr "det går inte att anropa medlemsfunktion %qD utan ett objekt"
-
-#, fuzzy
-#~| msgid "a call to a constructor cannot appear in a constant-expression"
-#~ msgid "super class constructor call must be in a constructor"
-#~ msgstr "ett anrop till en konstruerare får inte finnas i ett konstantuttryck"
-
-#, fuzzy
-#~| msgid "no super class declared in interface for %qE"
-#~ msgid "no super class constructor for %s"
-#~ msgstr "ingen superklass deklarerad i gränssnittet för %qE"
-
-#~ msgid "constructor calls not allowed in loops or after labels"
-#~ msgstr "konstrueraranrop är inte tillåtna i slingor eller efter etiketter"
-
-#, fuzzy
-#~| msgid "multiple inline callers"
-#~ msgid "multiple constructor calls"
-#~ msgstr "flera inline-anropare"
-
-#, fuzzy
-#~| msgid "initializer invalid for static member with constructor"
-#~ msgid "an earlier return statement skips constructor"
-#~ msgstr "initierare är ogiltig för statisk medlem med konstruerare"
-
-#, fuzzy
-#~| msgid "a constructor cannot be %<concept%>"
-#~ msgid "constructor call must be in a constructor"
-#~ msgstr "en konstruerare kan inte vara %<concept%>"
-
-#, fuzzy
-#~| msgid "In copy constructor %qs"
-#~ msgid "cyclic constructor call"
-#~ msgstr "I kopieringskonstruerare %qs"
-
-#~ msgid "function expected before (), not '%s'"
-#~ msgstr "en funktion förvändades före (), inte â€%sâ€"
-
-#~ msgid "need 'this' for '%s' of type '%s'"
-#~ msgstr "behöver â€this†till â€%s†av typen â€%sâ€"
-
-#, fuzzy
-#~| msgid "expected %qT but argument is of type %qT"
-#~ msgid "function expected before (), not %s of type %s"
-#~ msgstr "%qT förväntades men argumentet har typ %qT"
-
-#~ msgid "pure %s '%s' cannot call impure %s '%s'"
-#~ msgstr "ren %s â€%s†kan inte anropa oren %s â€%sâ€"
-
-#~ msgid "@nogc %s '%s' cannot call non-@nogc %s '%s'"
-#~ msgstr "@nogc %s â€%s†kan inte anropa icke-@nogc %s â€%sâ€"
-
-#~ msgid "@safe %s '%s' cannot call @system %s '%s'"
-#~ msgstr "@safe %s â€%s†kan inte anropa @system %s â€%sâ€"
-
-#~ msgid "forward reference to inferred return type of function call '%s'"
-#~ msgstr "framÃ¥treferens till en härledd returtyp av funktionsanrop â€%sâ€"
-
-#, fuzzy
-#~| msgid "forming reference to void"
-#~ msgid "forward reference to %s %s"
-#~ msgstr "formar referens till void"
-
-#, fuzzy
-#~| msgid "forming reference to void"
-#~ msgid "forward reference to %s"
-#~ msgstr "formar referens till void"
-
-#~ msgid "'this' reference necessary to take address of member %s in @safe function %s"
-#~ msgstr "en â€thisâ€-referens är nödvändig för att ta adressen till medlemmen %s i @safe-funktionen %s"
-
-#~ msgid "cannot take address of ref return of %s() in @safe function %s"
-#~ msgstr "det går inte att ta adressen till en ref-retur hos %s() i @safe-funktionen %s"
-
-#~ msgid "using * on an array is no longer supported; use *(%s).ptr instead"
-#~ msgstr "att använda * på en vektor stödjs inte längre; använd *(%s).ptr istället"
-
-#~ msgid "can only * a pointer, not a '%s'"
-#~ msgstr "det gÃ¥r bara att använda * pÃ¥ en pekare, inte en â€%sâ€"
-
-#, fuzzy
-#~| msgid "invalid operation (%s)"
-#~ msgid "invalid array operation %s (possible missing [])"
-#~ msgstr "ogiltig operation (%s)"
-
-#, fuzzy
-#~| msgid "cannot type switch on non-interface value"
-#~ msgid "cannot delete instance of COM interface %s"
-#~ msgstr "kan inte göra en typ-switch på något som inte är ett gränssnittsvärde"
-
-#, fuzzy
-#~| msgid "cannot use type %s as type %s"
-#~ msgid "cannot delete type %s"
-#~ msgstr "det går inte att använda typ %s som typ %s"
-
-#, fuzzy
-#~| msgid "%qD is not defined outside of function scope"
-#~ msgid "%s is not @safe but is used in @safe function %s"
-#~ msgstr "%qD är inte definierad utanför funktionsnivå"
-
-#, fuzzy
-#~| msgid "Cannot map %s"
-#~ msgid "cannot cast %s"
-#~ msgstr "Kan inte avbilda %s"
-
-#, fuzzy
-#~| msgid "cannot use type %s as type %s"
-#~ msgid "cannot cast %s to tuple type %s"
-#~ msgstr "det går inte att använda typ %s som typ %s"
-
-#, fuzzy
-#~| msgid "By-value argument at %L is not allowed in this context"
-#~ msgid "cast from %s to %s not allowed in safe code"
-#~ msgstr "Värdesargument vid %L är inte tillåtet i denna kontext"
-
-#, fuzzy
-#~| msgid "cannot open '%s'"
-#~ msgid "cannot slice type '%s'"
-#~ msgstr "kan inte öppna â€%sâ€"
-
-#, fuzzy
-#~| msgid "cannot read function profile from %s"
-#~ msgid "cannot slice function pointer %s"
-#~ msgstr "det går inte att läsa profilen från %s"
-
-#~ msgid "need upper and lower bound to slice pointer"
-#~ msgstr "behöver övre och undre gräns för att skiva pekare"
-
-#, fuzzy
-#~| msgid "#pragma GCC option is not allowed inside functions"
-#~ msgid "pointer slicing not allowed in safe functions"
-#~ msgstr "#pragma GCC option tillåts inte inuti funktioner"
-
-#~ msgid "need upper and lower bound to slice tuple"
-#~ msgstr "behöver undre och övre gräns för att skiva tuppel"
-
-#, fuzzy
-#~| msgid "%s cannot be used in asm here"
-#~ msgid "%s cannot be sliced with []"
-#~ msgstr "%s kan inte användas i en asm här"
-
-#, fuzzy
-#~| msgid "index value is out of bound"
-#~ msgid "string slice [%llu .. %llu] is out of bounds"
-#~ msgstr "indexvärdet är utanför gränsen"
-
-#, fuzzy
-#~| msgid "no pre-increment operator for type"
-#~ msgid "no [] operator overload for type %s"
-#~ msgstr "ingen pre-ökningsoperator för typen"
-
-#, fuzzy
-#~| msgid "only zero initializers are allowed in section %qs"
-#~ msgid "only one index allowed to index %s"
-#~ msgstr "endast nollinitierare är tillåtna i sektionen %qs"
-
-#, fuzzy
-#~| msgid "cannot read function profile from %s"
-#~ msgid "cannot index function pointer %s"
-#~ msgstr "det går inte att läsa profilen från %s"
-
-#, fuzzy
-#~| msgid "virtual functions cannot be friends"
-#~ msgid "safe function '%s' cannot index pointer '%s'"
-#~ msgstr "virtuella funktioner kan inte vara vänner"
-
-#, fuzzy
-#~| msgid "array subscript [%E, %E] is outside array bounds of %qT"
-#~ msgid "array index [%llu] is outside array bounds [0 .. %llu]"
-#~ msgstr "vektorindexen [%E, %E] är utanför vektorgränserna för %qT"
-
-#~ msgid "%s must be an array or pointer type, not %s"
-#~ msgstr "%s måste vara en vektor- eller pekartyp, inte %s"
-
-# Första och sista %s blir ett engelskt ord, felrapporterat:
-# https://gcc.gnu.org/bugzilla/show_bug.cgi?id=89823
-#~ msgid "cannot post-%s array slice '%s', use pre-%s instead"
-#~ msgstr "kan inte efter-%s vektorskivan â€%sâ€, använd för-%s istället"
-
-#, fuzzy
-#~| msgid " mismatched types %qT and %qT"
-#~ msgid "mismatched tuple lengths, %d and %d"
-#~ msgstr " typerna %qT och %qT stämmer inte överens"
-
-#, fuzzy
-#~| msgid "Conversion from %s to %s at %L"
-#~ msgid "conversion error from %s to %s"
-#~ msgstr "Konvertering från %s till %s vid %L"
-
-#, fuzzy
-#~| msgid " mismatched types %qT and %qT"
-#~ msgid "mismatched array lengths, %d and %d"
-#~ msgstr " typerna %qT och %qT stämmer inte överens"
-
-#, fuzzy
-#~| msgid "system path %qs is not absolute"
-#~ msgid "slice %s is not mutable"
-#~ msgstr "systemsökväg %qs är inte absolut"
-
-#~ msgid "cannot copy void[] to void[] in @safe code"
-#~ msgstr "det går inte att kopiera void[] till void[] i @safe-kod"
-
-#, fuzzy
-#~| msgid "cannot decompose address"
-#~ msgid "cannot rebind scope variables"
-#~ msgstr "kan inte dekomponera adress."
-
-#~ msgid "cannot modify compiler-generated variable __ctfe"
-#~ msgstr "det går inte att ändra den kompilatorgenererade variabeln __ctfe"
-
-#, fuzzy
-#~| msgid "cannot apply %<offsetof%> to static data member %qD"
-#~ msgid "cannot append to static array %s"
-#~ msgstr "det går inte att använda %<offsetof%> på en statisk datamedlem %qD"
-
-#, fuzzy
-#~| msgid "cannot use type %s as type %s"
-#~ msgid "cannot append type %s to type %s"
-#~ msgstr "det går inte att använda typ %s som typ %s"
-
-#, fuzzy
-#~| msgid "source is not a pointer"
-#~ msgid "can't subtract %s from pointer"
-#~ msgstr "källan är inte en pekare"
-
-#, fuzzy
-#~| msgid "cannot read function profile from %s"
-#~ msgid "can't subtract pointer from %s"
-#~ msgstr "det går inte att läsa profilen från %s"
-
-#~ msgid "cannot perform modulo complex arithmetic"
-#~ msgstr "det gör inte att göra modulo i komplex aritmetik"
-
-#~ msgid "do not use null when comparing class types"
-#~ msgstr "använd inte null vid jämförelse av klasstyper"
-
-#, fuzzy
-#~| msgid "recursive inlining"
-#~ msgid "recursive opCmp expansion"
-#~ msgstr "rekursiv inline:ing"
-
-#~ msgid "array comparison type mismatch, %s vs %s"
-#~ msgstr "typer stämmer inte i vektorjämförelse, %s mot %s"
-
-#~ msgid "need member function opCmp() for %s %s to compare"
-#~ msgstr "behöver medlemsfunktionen opCmp() för %s %s för att jämföra"
-
-#~ msgid "compare not defined for complex operands"
-#~ msgstr "jämförelse är inte definierad för komplexa operander"
-
-#, fuzzy
-#~| msgid "%<locus%> is not defined as a type"
-#~ msgid "%s is not defined for associative arrays"
-#~ msgstr "%<locus%> är inte definierad som en typ"
-
-#~ msgid "'%s' is not defined for array comparisons"
-#~ msgstr "â€%s†är inte definierat för vektorjämförelser"
-
-#~ msgid "floating point operator '%s' always returns %s for non-floating comparisons"
-#~ msgstr "flyttalsoperatorn â€%s†returnerar alltid %s för jämförelse av icke-flyttal"
-
-#~ msgid "use '%s' for non-floating comparisons rather than floating point operator '%s'"
-#~ msgstr "använd â€%s†för jämförelse av icke-flyttal istället för flyttalsoperatorn â€%sâ€"
-
-#~ msgid "use std.math.isNaN to deal with NaN operands rather than floating point operator '%s'"
-#~ msgstr "använd std.math.isNaN för att hantera NaN-operander istället för flyttalsoperatorn â€%sâ€"
-
-#, fuzzy
-#~| msgid "incomplete type %qT does not have member %qD"
-#~ msgid "template %s does not have property '%s'"
-#~ msgstr "ofullständig typ %qT har inte medlem %qD"
-
-#, fuzzy
-#~| msgid "%s does not support %s"
-#~ msgid "expression %s does not have property '%s'"
-#~ msgstr "%s stödjer inte %s"
-
-#, fuzzy
-#~| msgid "cannot declare reference to %q#T"
-#~ msgid "circular reference to %s '%s'"
-#~ msgstr "det går inte att deklarera referens till %q#T"
-
-#, fuzzy
-#~| msgid "forming reference to void"
-#~ msgid "forward reference to %s '%s'"
-#~ msgstr "formar referens till void"
-
-#~ msgid "undefined identifier '%s' in %s '%s', did you mean %s '%s'?"
-#~ msgstr "odefinierad identifierare â€%s†i %s â€%sâ€, menade du %s â€%sâ€?"
-
-#~ msgid "undefined identifier '%s' in %s '%s'"
-#~ msgstr "odefinierad identifierare â€%s†i %s â€%sâ€"
-
-#, fuzzy
-#~| msgid "%qT is not a template"
-#~ msgid "%s isn't a template"
-#~ msgstr "%qT är inte en mall"
-
-#, fuzzy
-#~| msgid "deprecated conversion from string constant to %qT"
-#~ msgid "expected constant string constraint for operand, not `%s`"
-#~ msgstr "konvertering från strängkonstant till %qT bör undvikas"
-
-#~ msgid "expected constant string constraint for clobber name, not `%s`"
-#~ msgstr "begränsning av konstant sträng förvändades för överskrivet namn, inte â€%sâ€"
-
-#, fuzzy
-#~| msgid "expected an identifier for the attribute name"
-#~ msgid "expected identifier for goto label name, not `%s`"
-#~ msgstr "en identifierare förväntades som attributnamn"
-
-#, fuzzy
-#~| msgid "third argument to function %qE must be a constant integer"
-#~ msgid "asm instruction template must be a constant char string"
-#~ msgstr "tredje argumentet till funktionen %qE måste vara ett konstant heltal"
-
-#~ msgid "extended asm statements with labels cannot have output constraints"
-#~ msgstr "utökade asm-satser med etiketter kan inte ha utmatningsbegräsningar"
-
-#, fuzzy
-#~| msgid "initializer element is not a constant expression"
-#~ msgid "initializer must be an expression, not '%s'"
-#~ msgstr "initierarelement är inte ett konstant uttryck"
-
-#, fuzzy
-#~| msgid "nonconstant array index in initializer"
-#~ msgid "cannot use non-constant CTFE pointer in an initializer '%s'"
-#~ msgstr "ickekonstant vektorindex i initierare"
-
-#~ msgid "cannot infer type from %s %s, possible circular dependency"
-#~ msgstr "det går inte att härleda typen från %s %s, möjligt cirkulärt beroende"
-
-#, fuzzy
-#~| msgid "cannot read string table from %s"
-#~ msgid "cannot infer type from %s %s"
-#~ msgstr "det går inte att läsa strängtabellen från %s"
-
-#, fuzzy
-#~| msgid "assuming cast to type %qT from overloaded function"
-#~ msgid "cannot infer type from overloaded function symbol %s"
-#~ msgstr "antar typkonvertering till %qT från överlagrad funktion"
-
-#~ msgid "field %s.%s cannot access pointers in @safe code that overlap other fields"
-#~ msgstr "fältet %s.%s kan inte komma åt pekare i @safe-kod som överlappar andra fält"
-
-#, fuzzy
-#~| msgid "cannot emit unaligned pointers in ptx assembly"
-#~ msgid "field %s.%s cannot modify misaligned pointers in @safe code"
-#~ msgstr "kan inte skicka ut ojusterade pekare i ptx-assembler"
-
-#~ msgid "field %s.%s cannot modify fields in @safe code that overlap fields with other storage classes"
-#~ msgstr "fältet %s.%s kan inte ändra fält i @safe-kod som överlappar fält med andra lagringsklasser"
-
-#, fuzzy
-#~| msgid "The derived parameter %qs at %C does not have a default value"
-#~ msgid "expression %s of type %s does not have a boolean value"
-#~ msgstr "Den härledda parametern %qs vid %C har inte ett standardvärde"
-
-#, fuzzy
-#~| msgid "integral expression %qE is not constant"
-#~ msgid "expression %s is not constant"
-#~ msgstr "heltalsuttryck %qE är inte konstant"
-
-#~ msgid "can't open %s: %m"
-#~ msgstr "det går inte att öppna %s: %m"
-
-#~ msgid "-march=%s: invalid ISA string"
-#~ msgstr "-march=%s: felaktig ISA-sträng"
-
-#~ msgid "-freorder-blocks-and-partition does not work with exceptions on this architecture"
-#~ msgstr "-freorder-blocks-and-partition fungerar inte med undantag på denna arkitektur"
-
-#~ msgid "bad value %qs for -mtune switch"
-#~ msgstr "felaktigt värde %qs till flaggan -mtune"
-
-#~ msgid "the xabort's argument must be an 8-bit immediate"
-#~ msgstr "argumentet till xabort måste vara en 8-bitars omedelbar"
-
-#~ msgid "-freorder-blocks-and-partition does not work on this architecture"
-#~ msgstr "-freorder-blocks-and-partition fungerar inte på denna arkitektur"
-
-#~ msgid "constant argument %d for builtin %qF is out of range ("
-#~ msgstr "det konstanta argumentet %d till den inbyggda %qF ligger utanför intervallet ("
-
-#~ msgid "bad value (%s) for -mcmodel= switch"
-#~ msgstr "felaktigt värde (%s) till flaggan -mcmodel="
-
-#~ msgid "bad value (%s) for -march= switch"
-#~ msgstr "felaktigt värde (%s) till flaggan -march="
-
-#~ msgid "bad value (%s) for -mtune= switch"
-#~ msgstr "felaktigt värde (%s) till flaggan -mtune"
-
-#~ msgid "expected semicolon"
-#~ msgstr "semikolon förväntades"
-
-#~ msgid "expected case label or goto statement"
-#~ msgstr "case-etikett eller goto-sats förväntades"
-
-#~ msgid "body of %<constexpr%> constructor cannot be a function-try-block"
-#~ msgstr "kroppen av %<constexpr%>-konstruerare kan inte vara ett function-try-block"
-
-#~ msgid "size of array %qD is negative"
-#~ msgstr "storleken på vektorn %qD är negativ"
-
-#~ msgid "%<try%> in %<constexpr%> function"
-#~ msgstr "%<try%> i %<constexpr%>-funktion"
-
-#~ msgid "Change of value in conversion from %qs to %qs at %L"
-#~ msgstr "Ändring av värde vid konvertering från %qs till %qs vid %L"
-
-#~ msgid "The number of elements in the array constructor at %L requires an increase of the allowed %d upper limit. See -fmax-array-constructor option"
-#~ msgstr "Antalet element i vektorkonstrueraren vid %L kräver en ökning av den tillåtna övre gränsen %d. Se flaggan -fmax-array-constructor"
-
-#~ msgid "Lower bound has to be present at %L"
-#~ msgstr "Undre gräns måste finnas vid %L"
-
-#~ msgid "Either all or none of the upper bounds must be specified at %L"
-#~ msgstr "Antingen alla eller ingen av de övre gränserna måste anges vid %L"
-
-#~ msgid "Syntax error in !$ACC ROUTINE ( NAME ) at %C, invalid function name %s"
-#~ msgstr "Syntaxfel i !$ACC ROUTINE ( NAMN ) vid %C, felaktigt funktionsnamn %s"
-
-#~ msgid " -i, --intermediate-format Output .gcov file in intermediate text format\n"
-#~ msgstr " -i, --intermediate-format Skriv .gcov-filer i intermediärt textformat\n"
-
-#~ msgid "Cannot open intermediate output file %s\n"
-#~ msgstr "Kan inte öppna intermediär utdatafil %s\n"
-
-#~ msgid "Maximum size of a SCC before SCCVN stops processing a function."
-#~ msgstr "Maximal storlek på en SCC före SCCVN slutar bearbeta en funktion."
-
-#~ msgid "Maximum number of statements to be included into a single static constructor generated by Pointer Bounds Checker."
-#~ msgstr "Maximalt antal satser som skall inkluderas i en enskild statisk konstruerare genererad av pekargränskontrolleraren."
-
-#~ msgid "-maltivec=le not allowed for big-endian targets"
-#~ msgstr "-maltivec=le är inte tillåtet för mål med rak byteordning"
-
-#~ msgid "-mvsx and -mpaired are incompatible"
-#~ msgstr "-mvsx och -mpaired är inkompatibla"
-
-#~ msgid "-mtoc-fusion requires 64-bit"
-#~ msgstr "--mtoc-fusion kräver 64-bitar"
-
-#~ msgid "-mtoc-fusion requires medium/large code model"
-#~ msgstr "-mtoc-fusion behöver medium/stor kodmodell"
-
-#~ msgid "emit_fusion_p9_load, bad reg #1"
-#~ msgstr "emit_fusion_p9_load, felaktigt register nr. 1"
-
-#~ msgid "emit_fusion_p9_load, bad reg #2"
-#~ msgstr "emit_fusion_p9_load, felaktigt register nr. 2"
-
-#~ msgid "emit_fusion_p9_load not MEM"
-#~ msgstr "emit_fusion_p9_load inte MEM"
-
-#~ msgid "emit_fusion_p9_store, bad reg #1"
-#~ msgstr "emit_fusion_p9_store, felaktigt register nr. 1"
-
-#~ msgid "emit_fusion_p9_store, bad reg #2"
-#~ msgstr "emit_fusion_p9_store, felaktigt register nr. 2"
-
-#~ msgid "emit_fusion_p9_store not MEM"
-#~ msgstr "emit_fusion_p9_store inte MEM"
-
-#~ msgid "Warn about memory access errors found by Pointer Bounds Checker."
-#~ msgstr "Varna för minnesåtkomstfel som hittas av pekargränskontrollen."
-
-#~ msgid "Add Pointer Bounds Checker instrumentation. fchkp-* flags are used to control instrumentation. Currently available for C, C++ and ObjC."
-#~ msgstr "Lägg till instrumentering för pekargränskontroller. fchkp-*-flaggor används för att styra instrumenteringen. För närvarande tillgängligt för C, C++ och ObjC."
-
-#~ msgid "Generate pointer bounds checks for variables with incomplete type."
-#~ msgstr "Generera pekargränskontroller för variabler med ofullständig typ."
-
-#~ msgid "Use zero bounds for all incoming arguments in 'main' function. It helps when instrumented binaries are used with legacy libs."
-#~ msgstr "Använd nollgränser för alla inkommande argument i funktionen â€mainâ€. Det hjälper till när instrumenterade binärer används med gamla bibliotek."
-
-#~ msgid "Forces Pointer Bounds Checker to use narrowed bounds for address of the first field in the structure. By default pointer to the first field has the same bounds as pointer to the whole structure."
-#~ msgstr "Tvingar pekargränskontrolleraren till att använda avsmalnade gränser för adresser till det första fältet i posten. Som standard har pekare till det första fältet samma gränser som pekare till hela posten."
-
-#~ msgid "Control how Pointer Bounds Checker handle pointers to object fields. When narrowing is on, field bounds are used. Otherwise full object bounds are used."
-#~ msgstr "Styr hur pekargränskontrollen hanterare pekare till objektfält. När avsmalning är påslaget används fältgränser. Annars används hela objektets gränser."
-
-#~ msgid "Forces Pointer Bounds Checker to use bounds of the innermost arrays in case of nested static arrays access. By default outermost array is used."
-#~ msgstr "Tvingar pekargränskontrollen att använda gränser för de innersta vektorerna för nästade statiska vektoråtkomster. Som standard används den yttersta vektorn."
-
-#~ msgid "Forces Pointer Bounds Checker to treat all trailing arrays in structures as possibly flexible. By default only arrays fields with zero length or that are marked with attribute bnd_variable_size are treated as flexible."
-#~ msgstr "Tvingar pekargränskontrollen att behandla alla avslutande vektorer i poster som eventuellt flexibla. Som standard hanteras endast vektorfält med nollängd eller som är märkta med attributet bnd_variable_size som flexibla."
-
-#~ msgid "Allow Pointer Bounds Checker optimizations. By default allowed on optimization levels >0."
-#~ msgstr "Tillåt optimeringar av pekargränskontrollen. Som standard tillåts det vid optimeringsnivåer >0."
-
-#~ msgid "Allow to use *_nobnd versions of string functions by Pointer Bounds Checker."
-#~ msgstr "Tillåt användning av *_nobnd-versioner av strängfunktioner av pekargränskontrollen."
-
-#~ msgid "Allow to use *_nochk versions of string functions by Pointer Bounds Checker."
-#~ msgstr "Tillåt användning av *_nochk-versioner av strängfunktioner av pekargränskontrollen."
-
-#~ msgid "Use statically initialized variable for vars bounds instead of generating them each time it is required."
-#~ msgstr "Använd en statiskt initierad variabel för variabelgränser istället för att generera dem varje gång det behövs."
-
-#~ msgid "Use statically initialized variable for constant bounds instead of generating them each time it is required."
-#~ msgstr "Använd en statiskt initierad variabel för konstantgränser istället för att generera dem varje gång det behövs."
-
-#~ msgid "With this option zero size obtained dynamically for objects with incomplete type will be treated as infinite."
-#~ msgstr "Med denna flagga kommer en dynamiskt erhållen storlek på noll för objekt med ofullständig typ hanteras som oändlig."
-
-#~ msgid "Generate checks for all read accesses to memory."
-#~ msgstr "Generera kontroller av alla läsåtkomster till minnet."
-
-#~ msgid "Generate checks for all write accesses to memory."
-#~ msgstr "Generera kontroller av alla skrivåtkomster till minnet."
-
-#~ msgid "Generate bounds stores for pointer writes."
-#~ msgstr "Generera gränslagringar för pekarskrivningar."
-
-#~ msgid "Generate bounds passing for calls."
-#~ msgstr "Generera skickande av gränser för anrop."
-
-#~ msgid "Transform instrumented builtin calls into calls to wrappers."
-#~ msgstr "Transformera instrumenterade inbyggda anrop till anrop av inkapslingar."
-
-#~ msgid "Scope of for-init-statement variables is local to the loop."
-#~ msgstr "Räckvidden av for-init-satsvariabler är lokal till slingan."
-
-#~ msgid "Inject friend functions into enclosing namespace."
-#~ msgstr "Skjut in friend-funktioner i omgivande namnrymd."
-
-#~ msgid "Do not use inline patterns for copying memory."
-#~ msgstr "Använd inte inline-mönster för att kopiera minne."
-
-#~ msgid "Use inline patterns for copying memory."
-#~ msgstr "Använd inline-mönster för att kopiera minne."
-
-#~ msgid "Do not pretend that branches are expensive."
-#~ msgstr "Låtsas inte att grenar är dyra."
-
-#~ msgid "Pretend that branches are expensive."
-#~ msgstr "Låtsas att grenar är dyra."
-
-#~ msgid "Use 32 bit float."
-#~ msgstr "Använd 32 bits float."
-
-#~ msgid "Use 64 bit float."
-#~ msgstr "Använd 64 bits float."
-
-#~ msgid "%<-mpcommit%> was deprecated"
-#~ msgstr "%<-mpcommit%> bör undvikas"
-
-#~ msgid "Support MPX code generation."
-#~ msgstr "Stöd MPX-kodgenerering."
-
-#~ msgid "Attempt to avoid generating instruction sequences containing ret bytes."
-#~ msgstr "Försök undvika att generera instruktionssekvenser som innehåller ret-byte:ar."
-
-#~ msgid "Generate AltiVec instructions using little-endian element order."
-#~ msgstr "Generera AltiVec-instruktioner med elementordning för omvänd byteordning."
-
-#~ msgid "Generate AltiVec instructions using big-endian element order."
-#~ msgstr "Generera AltiVec-instruktioner med elementordning för rak byteordning."
-
-#~ msgid "Generate string instructions for block moves."
-#~ msgstr "Generera stränginstruktioner för blockförflyttningar."
-
-#~ msgid "Specify how many bytes should be moved inline before calling out to memcpy/memmove."
-#~ msgstr "Ange hur många byte som bör flyttas inline före anrop av memcpy/memmove."
-
-#~ msgid "Specify the maximum number pairs of load instructions that should be generated inline for the compare. If the number needed exceeds the limit, a call to memcmp will be generated instead."
-#~ msgstr "Ange det maximala antalet par av lastningsinstruktioner som skall genereras inline för jämförelsen. Om antalet som behövs överskrider gränsen kommer istället ett anrop till memcmp genereras."
-
-#~ msgid "Specify the maximum number pairs of load instructions that should be generated inline for the compare. If the number needed exceeds the limit, a call to strncmp will be generated instead."
-#~ msgstr "Ange det maximala antalet par av lastningsinstruktioner som skall genereras inline för jämförelsen. Om antalet som behövs överskrider gränsen kommer istället ett anrop till strncmp genereras."
-
-#~ msgid "Deprecated option. Use -mno-isel instead."
-#~ msgstr "Undanbedd flagga. Använd -mno-isel istället."
-
-#~ msgid "Deprecated option. Use -misel instead."
-#~ msgstr "Undanbedd flagga. Använd -misel istället."
-
-#~ msgid "Generate SPE SIMD instructions on E500."
-#~ msgstr "Generera SPE SIMD-instruktioner för E500."
-
-#~ msgid "Generate PPC750CL paired-single instructions."
-#~ msgstr "Generera PPC750CL:s par-singel-instruktioner."
-
-#~ msgid "Deprecated option. Use -mno-spe instead."
-#~ msgstr "Undanbedd flagga. Använd -mno-spe istället."
-
-#~ msgid "Deprecated option. Use -mspe instead."
-#~ msgstr "Undanbedd flagga. Använd -mspe istället."
-
-#~ msgid "Use the SPE ABI extensions."
-#~ msgstr "Använd ABI-utökningarna SPE."
-
-#~ msgid "Do not use the SPE ABI extensions."
-#~ msgstr "Använd inte ABI-utökningarna SPE."
-
-#~ msgid "using IEEE extended precision long double"
-#~ msgstr "använder long double med IEEE:s utökade precision"
-
-#~ msgid "using IBM extended precision long double"
-#~ msgstr "använder long double med IBM:s utökade precision"
-
-#~ msgid "-mtraceback=\tSelect full, part, or no traceback table."
-#~ msgstr "-mtraceback=\tVälj fullständig, partiell, eller ingen bakåtspårningstabell."
-
-#~ msgid "Warn when a Cell microcoded instruction is emitted."
-#~ msgstr "Varna när en Cell-mikrokodsinstruktion avges."
-
-#~ msgid "-mfloat-gprs=\tSelect GPR floating point method."
-#~ msgstr "-mfloat-gprs=\tVälj GPR-flyttalsmetod."
-
-#~ msgid "Valid arguments to -mfloat-gprs=:"
-#~ msgstr "Giltiga argument till -mfloat-gprs=:"
-
-#~ msgid "-mlong-double-<n>\tSpecify size of long double (64 or 128 bits)."
-#~ msgstr "-mlong-double-<n>\tAnge storlek på long double (64 eller 128 bitar)."
-
-#~ msgid "Single-precision floating point unit."
-#~ msgstr "Enkelprecisions flyttalsenhet."
-
-#~ msgid "Double-precision floating point unit."
-#~ msgstr "Dubbelprecisions flyttalsenhet."
-
-#~ msgid "Floating point unit does not support divide & sqrt."
-#~ msgstr "Flyttalsenheten stödjer inte division & kvadratrot."
-
-#~ msgid "-mfpu=\tSpecify FP (sp, dp, sp-lite, dp-lite) (implies -mxilinx-fpu)."
-#~ msgstr "-mfpu=\tAnge FP (sp, dp, sp-lite, dp-lite) (implicerar -mxilinx-fpu)."
-
-#~ msgid "Specify Xilinx FPU."
-#~ msgstr "Ange Xilinx-FPU."
-
-#~ msgid "Allow 128-bit integers in VSX registers."
-#~ msgstr "Tillåt 128-bitars heltal i VSX-register."
-
-#~ msgid "Use ISA 2.07 direct move between GPR & VSX register instructions."
-#~ msgstr "Använd ISA 2.07:s direkta förflyttning mellan GPR- och VSX-registerinstruktioner."
-
-#~ msgid "Allow double variables in upper registers with -mcpu=power7 or -mvsx."
-#~ msgstr "Tillåt double-variabler i övre register med -mcpu=power7 eller -mvsx."
-
-#~ msgid "Allow float variables in upper registers with -mcpu=power8 or -mpower8-vector."
-#~ msgstr "Tillåt flyttalsvariabler i övre register med -mcpu=power8 eller -mpower8-vector."
-
-#~ msgid "Allow float/double variables in upper registers if cpu allows it."
-#~ msgstr "Tillåt float/double-variabler i övre register om cpu:n tillåter det."
-
-#~ msgid "Allow 64-bit integer variables in upper registers with -mcpu=power7 or -mvsx."
-#~ msgstr "Tillåt 64-bitars heltalsvariabler i övre register med -mcpu=power7 eller -mvsx."
-
-#~ msgid "Fuse certain operations together for better performance on power9."
-#~ msgstr "Smält samman vissa operationer för bättre prestanda på power9."
-
-#~ msgid "Use scalar register+offset memory instructions added in ISA 3.0."
-#~ msgstr "Använd skalära register+avstånd-minnesinstruktioner som lades till i ISA 3.0."
-
-#~ msgid "Use vector register+offset memory instructions added in ISA 3.0."
-#~ msgstr "Använd register+avstånd vektorminnesinstruktioner som lades till i ISA 3.0."
-
-#~ msgid "Use register+offset memory instructions added in ISA 3.0."
-#~ msgstr "Använd register+avstånds-minnesinstruktioner som lades till i ISA 3.0."
-
-#~ msgid "Allow the IEEE 128-bit types without requiring the __float128 keyword."
-#~ msgstr "Tillåt IEEE 128-bitars flyttalstyper utan att kräva nyckelordet __float128."
-
-#~ msgid "Enable small integers to be in VSX registers."
-#~ msgstr "Aktivera att små heltal får finnas i VSX-register."
-
-#~ msgid "Select ABI calling convention."
-#~ msgstr "Välj ABI-konvention för anrop."
-
-#~ msgid "%<-mstring%> is deprecated"
-#~ msgstr "%<-mstring%> bör undvikas"
-
-#~ msgid "Max number of pairs of load insns for compare."
-#~ msgstr "Maximala antalet par av laddinstruktioner för jämförelser."
-
-#~ msgid "%<-misel=no%> is deprecated; use %<-mno-isel%> instead"
-#~ msgstr "%<-misel=no%> bör undvikas; använd %<-mno-isel%> istället"
-
-#~ msgid "%<-misel=yes%> is deprecated; use %<-misel%> instead"
-#~ msgstr "%<-misel=yes%> bör undvikas; använd %<-misel%> istället"
-
-#~ msgid "Do not generate millicode thunks (needed only with -Os)."
-#~ msgstr "Generera inte millikodsnutt (behövs endast med -Os)."
-
-#~ msgid "Enable lra."
-#~ msgstr "Aktivera lra."
-
-#~ msgid "switch %qs no longer supported"
-#~ msgstr "flaggan %qs stödjs inte längre"
-
-#~ msgid "cannot read working set from %s"
-#~ msgstr "det går inte arbetsmängden från %s"
-
-#~ msgid "Your target platform does not support -fcheck-pointer-bounds"
-#~ msgstr "Din målplattform stödjer inte -fcheck-pointer-bounds"
-
-#~ msgid "Instrumentation clone does not reference original node"
-#~ msgstr "Instrumenteringsklonen refererar inte originalnoden"
-
-#~ msgid "Not instrumented node has non-NULL original declaration"
-#~ msgstr "Oinstrumenterad nod har en originaldeklaration som inte är NULL"
-
-#~ msgid "Instrumented node has wrong original declaration"
-#~ msgstr "Instrumenterad not har felaktig originaldeklaration"
-
-#~ msgid "Node has more than one chkp reference"
-#~ msgstr "Noden har mer än en chkp-referens"
-
-#~ msgid "Wrong node is referenced with chkp reference"
-#~ msgstr "Fel nod refereras med en chkp-referens"
-
-#~ msgid "Analyzed node has no reference to instrumented version"
-#~ msgstr "Analyserad nod har ingen referens till en instrumenterad version"
-
-#~ msgid "Alias chain for instrumented node is broken"
-#~ msgstr "En aliaskedja för en instrumenterad not är bruten"
-
-#~ msgid "Instrumentation thunk has wrong edge callee"
-#~ msgstr "Instrumenteringssnutten har fel anropande båge"
-
-#~ msgid "number of counters is %d instead of %d"
-#~ msgstr "antal räknare är %d istället för %d"
-
-#~ msgid "cannot merge separate %s counters for function %u"
-#~ msgstr "kan inte slå samman separata %s-räknare för funktionen %u"
-
-#~ msgid "iteration variable %qE should not be lastprivate"
-#~ msgstr "iterationsvariabel %qE får inte vara lastprivate"
-
-#~ msgid "iteration variable %qE should not be private"
-#~ msgstr "instansvariabel %qE får inte vara privat"
-
-#~ msgid "function cannot be instrumented"
-#~ msgstr "funktionen kan inte instrumenteras"
-
-#~ msgid "a type with different qualifiers is defined in another translation unit"
-#~ msgstr "en typ med andra kvalificerare är definierad i en annan översättningsenhet"
-
-#~ msgid "a type with different attributes is defined in another translation unit"
-#~ msgstr "en typ med andra attribut är definierad i en annan översättningsenhet"
-
-#~ msgid "a type with different alignment is defined in another translation unit"
-#~ msgstr "en typ med annan justering är definierad i en annan översättningsenhet"
-
-#~ msgid "-falign-jumps=%d is not between 0 and %d"
-#~ msgstr "-falign-jumps=%d är inte mellan 0 och %d"
-
-#~ msgid "-falign-functions=%d is not between 0 and %d"
-#~ msgstr "-falign-functions=%d är inte mellan 0 och %d"
-
-#~ msgid "-falign-labels=%d is not between 0 and %d"
-#~ msgstr "-falign-labels=%d är inte mellan 0 och %d"
-
-#~ msgid "corrupted profile info: edge from %i to %i exceeds maximal count"
-#~ msgstr "trasig profileringsinformation: båge från %i till %i överskred maximalt antal"
-
-#~ msgid "corrupted profile info: sum_all is smaller than sum_max"
-#~ msgstr "trasig profileringsinformation: sum_all är mindre än sum_max"
-
-#~ msgid "size of %q+D is %d bytes"
-#~ msgstr "storleken på %q+D är %d byte"
-
-#~ msgid "size of %q+D is larger than %wd bytes"
-#~ msgstr "storleken på %q+D är större än %wd byte"
-
-#~ msgid "%<-fcheck-pointer-bounds%> is not supported for this target"
-#~ msgstr "%<-fcheck-pointer-bounds%> stödjs inte för denna målarkitektur"
-
-#~ msgid "%<-fcheck-pointer-bounds%> is not supported with %<-fsanitize=bounds-strict%>"
-#~ msgstr "%<-fcheck-pointer-bounds%> stödjs inte med %<-fsanitize=bounds-strict%>"
-
-#~ msgid "%<-fcheck-pointer-bounds%> is not supported with %<-fsanitize=bounds%>"
-#~ msgstr "%<-fcheck-pointer-bounds%> stödjs inte med %<-fsanitize=bounds%>"
-
-#~ msgid "%<-fcheck-pointer-bounds%> is not supported with Address Sanitizer"
-#~ msgstr "%<-fcheck-pointer-bounds%> stödjs inte med adressrengöring"
-
-#~ msgid "%<-fcheck-pointer-bounds%> is not supported with Thread Sanitizer"
-#~ msgstr "%<-fcheck-pointer-bounds%> stödjs inte med trådrengöring"
-
-#~ msgid "SSA name in freelist but still referenced"
-#~ msgstr "SSA-namn i frilista men fortfarande refererad"
-
-#~ msgid "invalid first operand of MEM_REF"
-#~ msgstr "ogiltig första operand till MEM_REF"
-
-#~ msgid "MODIFY_EXPR not expected while having tuples"
-#~ msgstr "MODIFY_EXPR förväntades inte när man har tupler"
-
-#~ msgid "non-integral used in condition"
-#~ msgstr "icke-heltal använt i villkor"
-
-#~ msgid "invalid conditional operand"
-#~ msgstr "ogiltig villkorlig operand"
-
-#~ msgid "invalid reference prefix"
-#~ msgstr "ogiltigt referensprefix"
-
-#~ msgid "invalid operand to plus/minus, type is a pointer"
-#~ msgstr "ogiltig operand till plus/minus, typen är en pekare"
-
-#~ msgid "invalid operand to pointer diff, operand is not a pointer"
-#~ msgstr "ogiltig operand till pekarskillnad, första operanden är inte en pekare"
-
-#~ msgid "invalid type for pointer diff"
-#~ msgstr "ogiltig typ för pekarskillnad"
-
-#~ msgid "invalid operand to pointer plus, first operand is not a pointer"
-#~ msgstr "ogiltig operand till pekarplus, första operanden är inte en pekare"
-
-#~ msgid "invalid operand to pointer plus, second operand is not an integer type of appropriate width"
-#~ msgstr "ogiltig operand till pekarplus, andra operanden är inte en heltalstyp med lämplig bredd"
-
-#~ msgid "type mismatch in fused multiply-add expression"
-#~ msgstr "typer stämmer inte i sammansmält multiplicera-addera-uttryck"
-
-#~ msgid "in statement"
-#~ msgstr "i sats"
-
-#~ msgid "memory access check always fail"
-#~ msgstr "minnesåtkomstkontrollen misslyckas alltid"
-
-#~ msgid "-fcheck-pointer-bounds requires %qs name for internal usage"
-#~ msgstr "-fcheck-pointer-bounds kräver %qs-namn för intern användning"
-
-#~ msgid "pointer bounds were lost due to unexpected expression %s"
-#~ msgstr "pekargränserna gick förlorade på grund av det oväntade uttrycket %s"
-
-#~ msgid "chkp_get_bounds_by_definition: Unexpected var of type %s"
-#~ msgstr "chkp_get_bounds_by_definition: Oväntad variabel av typen %s"
-
-#~ msgid "chkp_get_bounds_by_definition: Unexpected GIMPLE code %s"
-#~ msgstr "chkp_get_bounds_by_definition: Oväntad GIMPLE-kod %s"
-
-#~ msgid "chkp_make_addressed_object_bounds: Unexpected tree code %s"
-#~ msgstr "chkp_make_addressed_object_bounds: Oväntad trädkod %s"
-
-#~ msgid "chkp_find_bounds: Unexpected tree code %s"
-#~ msgstr "chkp_find_bounds: Oväntad trädkod %s"
-
-#~ msgid "chkp_find_bounds: Cannot find bounds for pointer"
-#~ msgstr "chkp_find_bounds: Kan inte hitta gränserna för pekare"
-
-#~ msgid "chkp_walk_pointer_assignments: unexpected RHS type: %s"
-#~ msgstr "chkp_walk_pointer_assignments: oväntad RHS-typ: %s"
-
-#~ msgid "alignment for %q+D must be at least %d"
-#~ msgstr "justering för %q+D måste vara åtminstone %d"
-
-#~ msgid "tls_model argument not a string"
-#~ msgstr "tls_model-argument är inte en sträng"
-
-#~ msgid "tls_model argument must be one of \"local-exec\", \"initial-exec\", \"local-dynamic\" or \"global-dynamic\""
-#~ msgstr "tls_model-argument mÃ¥ste vara ett av â€local-execâ€, â€initial-execâ€, â€local-dynamic†eller â€global-dynamicâ€"
-
-#~ msgid "alloc_size parameter outside range"
-#~ msgstr "alloc_size-parameter utanför giltigt intervall"
-
-#~ msgid "alloc_align parameter outside range"
-#~ msgstr "alloc_align-parameter utanför giltigt intervall"
-
-#~ msgid "assume_aligned parameter not integer constant"
-#~ msgstr "assume_aligned-parameter är inte en heltalskonstant"
-
-#~ msgid "requested alignment is too large"
-#~ msgstr "begärd minnesjustering är för stor"
-
-#~ msgid "format string has invalid operand number"
-#~ msgstr "formatsträng har ogiltigt operandnummer"
-
-#~ msgid "%<...%> has invalid operand number"
-#~ msgstr "%<...%> har ogiltigt operandnummer"
-
-#~ msgid "%<gcall%> is not defined as a type"
-#~ msgstr "%<gcall%> är inte definierad som en typ"
-
-#~ msgid "-Walloca-larger-than=0 is meaningless"
-#~ msgstr "-Walloca-larger-than=0 är meningslöst"
-
-#~ msgid "-Wvla-larger-than=0 is meaningless"
-#~ msgstr "-Wvla-larger-than=0 är meningslöst"
-
-#~ msgid "value of -mirq-ctrl-saved must have form R0-REGx"
-#~ msgstr "värdet på -mirq-ctrl-saved måste ha formen R0-REGx"
-
-#~ msgid "compact-casesi is not applicable to ARCv2"
-#~ msgstr "compact-casesi är inte tillämplig på ARCv2"
-
-#~ msgid "Intel MPX does not support x32"
-#~ msgstr "Intel MPX stödjer inte x32"
-
-#~ msgid "%<-mindirect-branch=thunk-extern%>, %<-fcf-protection=branch%> and %<-fcheck-pointer-bounds%> are not compatible"
-#~ msgstr "%<-mindirect-branch=thunk-extern%>, %<-fcf-protection=branch%> och %<--fcheck-pointer-bounds%> är inte kompatibla"
-
-#~ msgid "Pointer Checker requires MPX support on this target. Use -mmpx options to enable MPX."
-#~ msgstr "Pekarkontrolleraren kräver stöd för MPX på detta mål. Använd flaggan -mmpx för att aktivera MPX."
-
-#~ msgid "position-independent code not supported"
-#~ msgstr "positionsoberoende kod stödjs inte"
-
-#~ msgid "`custom-%s=' argument requires numeric digits"
-#~ msgstr "argumentet â€custom-%s=†behöver numeriska siffror"
-
-#~ msgid "vec_mul only accepts 2 arguments"
-#~ msgstr "vec_mul tar endast 2 argument"
-
-#~ msgid "vec_cmpne only accepts 2 arguments"
-#~ msgstr "vec_cmpne tar endast 2 argument"
-
-#~ msgid "vec_adde only accepts 3 arguments"
-#~ msgstr "vec_adde tar endast 3 argument"
-
-#~ msgid "vec_addec only accepts 3 arguments"
-#~ msgstr "vec_addec tar endast 3 argument"
-
-#~ msgid "%s only accepts %d arguments"
-#~ msgstr "%s tar endast %d argument"
-
-#~ msgid "%s only accepts 1 argument"
-#~ msgstr "%s tar endast ett argument"
-
-#~ msgid "%s only accepts 2 arguments"
-#~ msgstr "%s tar bara 2 argument"
-
-#~ msgid "vec_extract only accepts 2 arguments"
-#~ msgstr "vec_extract tar endast 2 argument"
-
-#~ msgid "vec_insert only accepts 3 arguments"
-#~ msgstr "vec_insert tar endast 3 argument"
-
-#~ msgid "__builtin_cmpb only accepts 2 arguments"
-#~ msgstr "__builtin_cmpb tar endast 2 argument"
-
-#~ msgid "Builtin function %s not supported in this compiler configuration"
-#~ msgstr "Den inbyggda funktionen %s stödjs inte i denna kompilatorkonfiguration"
-
-#~ msgid "invalid parameter combination for AltiVec intrinsic %s"
-#~ msgstr "ogiltig parameterkombination för inbyggd %s i AltiVec"
-
-#~ msgid "-mrecip requires -ffinite-math or -ffast-math"
-#~ msgstr "-mrecip kräver -ffinite-math eller -ffast-math"
-
-#~ msgid "-mrecip requires -fno-trapping-math or -ffast-math"
-#~ msgstr "-mrecip kräver -fno-trapping-math eller -ffast-math"
-
-#~ msgid "-mrecip requires -freciprocal-math or -ffast-math"
-#~ msgstr "-mrecip kräver -freciprocal-math eller -ffast-math"
-
-#~ msgid "-m64 requires PowerPC64 architecture, enabling"
-#~ msgstr "-m64 kräver PowerPC64-arkitektur, aktiverar"
-
-#~ msgid "-malign-power is not supported for 64-bit Darwin; it is incompatible with the installed C and C++ libraries"
-#~ msgstr "-malign-power stödjs inte för 64-bitars Darwin, det är inkompatibelt med de installerade C- och C++-biblioteken"
-
-#~ msgid "will not generate power9 instructions because assembler lacks power9 support"
-#~ msgstr "kommer inte generera power9-instruktioner för att assemblern saknar stöd för power9"
-
-#~ msgid "will not generate power8 instructions because assembler lacks power8 support"
-#~ msgstr "kommer inte generera power8-instruktioner för att assemblern saknar stöd för power8"
-
-#~ msgid "will not generate power7 instructions because assembler lacks power7 support"
-#~ msgstr "kommer inte generera power7-instruktioner för att assemblern saknar stöd för power7"
-
-#~ msgid "will not generate power6 instructions because assembler lacks power6 support"
-#~ msgstr "kommer inte generera power6-instruktioner för att assemblern saknar stöd för power6"
-
-#~ msgid "will not generate power5 instructions because assembler lacks power5 support"
-#~ msgstr "kommer inte generera power5-instruktioner för att assemblern saknar stöd för power5"
-
-#~ msgid "not configured for SPE ABI"
-#~ msgstr "inte konfigurerad för SPE-ABI"
-
-#~ msgid "not configured for SPE instruction set"
-#~ msgstr "inte konfigurerad för instruktionsuppsättningen SPE"
-
-#~ msgid "target attribute or pragma changes SPE ABI"
-#~ msgstr "målattribut eller pragma ändrar SPE ABI"
-
-#~ msgid "SPE not supported in this target"
-#~ msgstr "SPE stödjs inte på denna målarkitektur"
-
-#~ msgid "-mmultiple is not supported on little endian systems"
-#~ msgstr "-mmultiple stödjs inte på system med omvänd byteordning"
-
-#~ msgid "-mstring is not supported on little endian systems"
-#~ msgstr "-mstring stödjs inte på system med omvänd byteordning"
-
-#~ msgid "-mpower9-minmax incompatible with explicitly disabled options"
-#~ msgstr "-mpower9-minmax är inkompatibel med uttryckligen avaktiverade flaggor"
-
-#~ msgid "Power9 target option is incompatible with -mcpu=<xxx> for <xxx> less than power9"
-#~ msgstr "Målflaggan för power9 är inkompatibel med -mcpu=<xxx> för <xxx> som är mindre än power9"
-
-#~ msgid "-mcrypto requires -maltivec"
-#~ msgstr "-mcrypto behöver -maltivec"
-
-#~ msgid "-mdirect-move requires -mvsx"
-#~ msgstr "-mdirect-move behöver -mvsx"
-
-#~ msgid "-mpower8-vector requires -maltivec"
-#~ msgstr "-mpower8-vector behöver -maltivec"
-
-#~ msgid "-mpower8-vector requires -mvsx"
-#~ msgstr "-mpower8-vector behöver -mvsx"
-
-#~ msgid "-mvsx-timode requires -mvsx"
-#~ msgstr "-mvsx-timode behöver -mvsx"
-
-#~ msgid "-mhard-dfp requires -mhard-float"
-#~ msgstr "-mhard-dfp behöver -mhard-float"
-
-#~ msgid "-mupper-regs-df requires -mvsx"
-#~ msgstr "-mupper-regs-df behöver -mvsx"
-
-#~ msgid "-mupper-regs-di requires -mvsx"
-#~ msgstr "-mupper-regs-di behöver -mvsx"
-
-#~ msgid "-mupper-regs-sf requires -mpower8-vector"
-#~ msgstr "-mupper-regs-sf behöver -mpower8-vector"
-
-#~ msgid "-mpower8-fusion-sign requires -mpower8-fusion"
-#~ msgstr "-mpower8-fusion-sign behöver -mpower8-fusion"
-
-#~ msgid "-mtoc-fusion requires -mpower8-fusion"
-#~ msgstr "-mtoc-fusion behöver -mpower8-fusion"
-
-#~ msgid "-mpower9-fusion requires -mpower8-fusion"
-#~ msgstr "-mpower9-fusion behöver -mpower8-fusion"
-
-#~ msgid "-mpower9-vector requires -mpower8-vector"
-#~ msgstr "-mpower9-vector behöver -mpower8-vector"
-
-#~ msgid "-mpower9-dform requires -mpower9-vector"
-#~ msgstr "-mpower9-dform behöver -mpower9-vector"
-
-#~ msgid "-mpower9-dform, -mpower9-dform-vector, -mpower9-dform-scalar require -mdirect-move"
-#~ msgstr "-mpower9-dform, -mpower9-dform-vector, -mpower9-dform-scalar kräver -mdirect-move"
-
-#~ msgid "-mpower9-dform requires -mupper-regs-df"
-#~ msgstr "-mpower9-dform behöver -mupper-regs-df"
-
-#~ msgid "-mpower9-dform requires -mupper-regs-sf"
-#~ msgstr "-mpower9-dform behöver -mupper-regs-sf"
-
-#~ msgid "-mvsx-timode might need -mlra"
-#~ msgstr "-mvsx-timode kan behöva -mlra"
-
-#~ msgid "-mallow-movmisalign requires -mvsx"
-#~ msgstr "-mallow-movmisalign behöver -mvsx"
-
-#~ msgid "-mefficient-unaligned-vsx requires -mvsx"
-#~ msgstr "-mefficient-unaligned-vsx behöver -mvsx"
-
-#~ msgid "-mefficient-unaligned-vsx requires -mallow-movmisalign"
-#~ msgstr "-mefficient-unaligned-vsx behöver -mallow-movmisalign"
-
-#~ msgid "-mvsx-small-integer requires -mpower8-vector, -mupper-regs-di, and -mdirect-move"
-#~ msgstr "-mvsx-small-integer kräver -mpower8-vector, -mupper-regs-di och -mdirect-move"
-
-#~ msgid "-mfloat128 requires VSX support"
-#~ msgstr "-mfloat128 behöver VSX-stöd"
-
-#~ msgid "-mfloat128-type requires VSX support"
-#~ msgstr "-mfloat128-type behöver VSX-stöd"
-
-#~ msgid "-mfloat128 requires -mfloat128-type"
-#~ msgstr "-mfloat128 behöver -mfloat128-type"
-
-#~ msgid "-mfloat128-hardware requires -mfloat128-type"
-#~ msgstr "-mfloat128-hardware behöver -mfloat128-type"
-
-#~ msgid "-mfloat128-hardware requires full ISA 3.0 support"
-#~ msgstr "-mfloat128-hardware behöver fullt ISA 3.0-stöd"
-
-#~ msgid "-mfloat128-hardware requires -m64"
-#~ msgstr "-mfloat128-hardware behöver -m64"
-
-#~ msgid "unknown vectorization library ABI type (%s) for -mveclibabi= switch"
-#~ msgstr "okänd ABI-typ (%s) till vektoriseringsbibliotek för flaggan -mveclibabi="
-
-#~ msgid "target attribute or pragma changes single precision floating point"
-#~ msgstr "målattribut eller pragma ändrar enkel precisions flyttal"
-
-#~ msgid "target attribute or pragma changes double precision floating point"
-#~ msgstr "målattribut eller pragma ändrar dubbel precisions flyttal"
-
-#~ msgid "-mstack-protector-guard=tls needs a valid base register"
-#~ msgstr "-mstack-protector-guard=tls behöver ett giltigt basregister"
-
-#~ msgid "cannot return value in vector register because altivec instructions are disabled, use -maltivec to enable them"
-#~ msgstr "det går inte att returnera värde i vektorregister för att altivec-instruktioner är avaktiverade, använd -maltivec för att aktivera dem"
-
-#~ msgid "cannot pass argument in vector register because altivec instructions are disabled, use -maltivec to enable them"
-#~ msgstr "det går inte att skicka argument i vektorregister för att altivec-instruktioner är avaktiverade, använd -maltivec för att aktivera dem"
-
-#~ msgid "internal error: builtin function %s already processed"
-#~ msgstr "internt fel: den inbyggda funktionen %s redan bearbetad"
-
-#~ msgid "argument 1 of __builtin_altivec_predicate must be a constant"
-#~ msgstr "argumentet 1 till __builtin_altivec_predicate måste vara en konstant"
-
-#~ msgid "argument 1 of __builtin_altivec_predicate is out of range"
-#~ msgstr "argument 1 till __builtin_altivec_predicate är utanför sitt intervall"
-
-#~ msgid "builtin %s is only valid in 64-bit mode"
-#~ msgstr "inbyggd %s är endast giltigt i 64-bitsläge"
-
-#~ msgid "builtin %s only accepts a string argument"
-#~ msgstr "den inbyggda %s tar endast ett strängargument"
-
-#~ msgid "cpu %s is an invalid argument to builtin %s"
-#~ msgstr "cpu %s är ett ogiltigt argument till den inbyggda %s"
-
-#~ msgid "hwcap %s is an invalid argument to builtin %s"
-#~ msgstr "hwcap %s är ett ogiltigt argument till den inbyggda %s"
-
-#~ msgid "argument to dss must be a 2-bit unsigned literal"
-#~ msgstr "argument till dss måste vara en 2-bitars litteral utan tecken"
-
-#~ msgid "second argument to vec_vextract4b must be 0..12"
-#~ msgstr "andra argumentet till vec_vextract4b måste vara 0..12"
-
-#~ msgid "third argument to vec_vinsert4b must be 0..12"
-#~ msgstr "tredje argumentet till vec_vinsert4b måste vara 0..12"
-
-#~ msgid "argument 1 of __builtin_paired_predicate must be a constant"
-#~ msgstr "argument 1 till __builtin_paired_predicate måste vara en konstant"
-
-#~ msgid "argument 1 of __builtin_paired_predicate is out of range"
-#~ msgstr "argument 1 till __builtin_paired_predicate är utanför sitt intervall"
-
-#~ msgid "argument 1 of __builtin_spe_predicate must be a constant"
-#~ msgstr "argument 1 till __builtin_spe_predicate måste vara en konstant"
-
-#~ msgid "argument 1 of __builtin_spe_predicate is out of range"
-#~ msgstr "argument 1 till __builtin_spe_predicate är utanför sitt intervall"
-
-#~ msgid "Builtin function %s is only valid for the cell processor"
-#~ msgstr "Den inbyggda funktionen %s är endast giltig för cell-processorn"
-
-#~ msgid "Builtin function %s requires the -mvsx option"
-#~ msgstr "Den inbyggda funktionen %s behöver flaggan -mvsx"
-
-#~ msgid "Builtin function %s requires the -mhtm option"
-#~ msgstr "Den inbyggda funktionen %s behöver flaggan -mhtm"
-
-#~ msgid "Builtin function %s requires the -maltivec option"
-#~ msgstr "Den inbyggda funktionen %s behöver flaggan -maltivec"
-
-#~ msgid "Builtin function %s requires the -mpaired option"
-#~ msgstr "Den inbyggda funktionen %s behöver flaggan -mpaired"
-
-#~ msgid "Builtin function %s requires the -mspe option"
-#~ msgstr "Den inbyggda funktionen %s behöver flaggan -mspe"
-
-#~ msgid "Builtin function %s requires the -mhard-dfp and -mpower8-vector options"
-#~ msgstr "Den inbyggda funktionen %s behöver flaggorna -mhard-dfp och -mpower8-vector"
-
-#~ msgid "Builtin function %s requires the -mhard-dfp option"
-#~ msgstr "Den inbyggda funktionen %s behöver flaggan -mhard-dfp"
-
-#~ msgid "Builtin function %s requires the -mpower8-vector option"
-#~ msgstr "Den inbyggda funktionen %s behöver flaggan -mpower8-vector"
-
-#~ msgid "Builtin function %s requires the -mcpu=power9 and -m64 options"
-#~ msgstr "Den inbyggda funktionen %s behöver flaggorna -mcpu=power9 och -m64"
-
-#~ msgid "Builtin function %s requires the -mcpu=power9 option"
-#~ msgstr "Den inbyggda funktionen %s behöver flaggan -mcpu=power9"
-
-#~ msgid "Builtin function %s requires the -mhard-float and -mlong-double-128 options"
-#~ msgstr "Den inbyggda funktionen %s behöver flaggorna -mhard-float och -mlong-double-128"
-
-#~ msgid "Builtin function %s requires the -mhard-float option"
-#~ msgstr "Den inbyggda funktionen %s behöver flaggan -mhard-float"
-
-#~ msgid "Builtin function %s requires the -mfloat128 option"
-#~ msgstr "Den inbyggda funktionen %s behöver flaggan -mfloat128"
-
-#~ msgid "Builtin function %s is not supported with the current options"
-#~ msgstr "Den inbyggda funktionen %s stödjs inte med de aktuella flaggorna"
-
-#~ msgid "internal error: builtin function %s had an unexpected return type %s"
-#~ msgstr "internt fel: inbyggd funktion %s hade en oväntad returtyp %s"
-
-#~ msgid "internal error: builtin function %s, argument %d had unexpected argument type %s"
-#~ msgstr "internt fel: inbyggd funktion %s, argument %d har en oväntad argumenttyp %s"
-
-#~ msgid "-fsplit-stack uses register r29"
-#~ msgstr "-fsplit-stack använder register r29"
-
-#~ msgid "You cannot take the address of a nested function if you use the -mno-pointers-to-nested-functions option."
-#~ msgstr "Du kan inte ta adressen till en nästad funktion om du använder flaggan -mno-pointers-to-nested-functions"
-
-#~ msgid "use of %<long%> in AltiVec types is invalid for 64-bit code without -mvsx"
-#~ msgstr "användning av %<long%> i AltiVec-typer är ogiltigt för 64-bitskod utan -mvsx"
-
-#~ msgid "use of %<long long%> in AltiVec types is invalid without -mvsx"
-#~ msgstr "användning av %<long long%> i AltiVec-typer är ogiltigt utan -mvsx"
-
-#~ msgid "use of %<double%> in AltiVec types is invalid without -mvsx"
-#~ msgstr "användning av %<double%> i AltiVec-typer är ogiltigt utan -mvsx"
-
-#~ msgid "emitting microcode insn %s\t[%s] #%d"
-#~ msgstr "matar ut mikrokodsinstruktion %s\t[%s] nr %d"
-
-#~ msgid "emitting conditional microcode insn %s\t[%s] #%d"
-#~ msgstr "matar ut villkorlig mikrokodsinstruktion %s\t[%s] nr %d"
-
-#~ msgid "invalid cpu \"%s\" for %s\"%s\"%s"
-#~ msgstr "felaktig cpu â€%s†för %sâ€%sâ€%s"
-
-#~ msgid "%s\"%s\"%s is not allowed"
-#~ msgstr "%sâ€%sâ€%s är inte tillÃ¥tet"
-
-#~ msgid "%s\"%s\"%s is invalid"
-#~ msgstr "%sâ€%sâ€%s är ogiltigt"
-
-#~ msgid "-mno-%s turns off -m%s"
-#~ msgstr "-mno-%s slår av -m%s"
-
-#~ msgid "-mno-power9-vector turns off -mpower9-dform"
-#~ msgstr "-mno-power9-vector slår av -mpower9-dform"
-
-#~ msgid "AltiVec and SPE instructions cannot coexist"
-#~ msgstr "AltiVec- och SPE-instruktioner kan inte samexistera"
-
-#~ msgid "VSX and SPE instructions cannot coexist"
-#~ msgstr "VSX- och SPE-instruktioner kan inte samexistera"
-
-#~ msgid "64-bit SPE not supported"
-#~ msgstr "64-bitars SPE stödjs inte"
-
-#~ msgid "E500 and FPRs not supported"
-#~ msgstr "E500 och FPR:er stödjs inte"
-
-#~ msgid "bad value for -mcall-%s"
-#~ msgstr "felaktigt värde för -mcall-%s"
-
-#~ msgid "bad value for -msdata=%s"
-#~ msgstr "felaktigt värde för -msdata-%s"
-
-#~ msgid "-mrelocatable and -msdata=%s are incompatible"
-#~ msgstr "-mrelocatable och -msdata=%s är inkompatibla"
-
-#~ msgid "-f%s and -msdata=%s are incompatible"
-#~ msgstr "-f%s och -msdata=%s är inkompatibla"
-
-#~ msgid "-msdata=%s and -mcall-%s are incompatible"
-#~ msgstr "-msdata=%s och -mcall-%s är inkompatibla"
-
-#~ msgid "-mrelocatable and -mno-minimal-toc are incompatible"
-#~ msgstr "-mrelocatable och -mno-minimal-toc är inkompatibla"
-
-#~ msgid "-mrelocatable and -mcall-%s are incompatible"
-#~ msgstr "-mrelocatable och -mcall-%s är inkompatibla"
-
-#~ msgid "-fPIC and -mcall-%s are incompatible"
-#~ msgstr "-fPIC och -mcall-%s är inkompatibla"
-
-#~ msgid "-msecure-plt not supported by your assembler"
-#~ msgstr "-msecure-plt stödjs inte av din assembler"
-
-#~ msgid "-m%s not supported in this configuration"
-#~ msgstr "-m%s stödjs inte i denna konfiguration"
-
-#~ msgid "%qs command-line option is deprecated"
-#~ msgstr "kommandoradsflaggan %qs bör undvikas"
-
-#~ msgid "will not generate %qs instructions because assembler lacks %qs support"
-#~ msgstr "kommer inte generera %qs-instruktioner för att assemblern saknar stöd för %qs"
-
-#~ msgid "CPUs older than z900 are not supported for -fsplit-stack"
-#~ msgstr "CPU:er äldre än z900 stödjs inte med -fsplit-stack"
-
-#~ msgid "%sarch=%s%s is deprecated and will be removed in future releases; use at least %sarch=z900%s"
-#~ msgstr "%sarch=%s%s bör undvikas och kommer tas bort i framtida utgåvor; använd åtminstone %sarch=z900%s"
-
-#~ msgid "%stune=%s%s is deprecated and will be removed in future releases; use at least %stune=z900%s"
-#~ msgstr "%stune=%s%s bör undvikas och kommer tas bort i framtida utgåvor; använd åtminstone %stune=z900%s"
-
-#~ msgid "z/Architecture mode not supported on %s"
-#~ msgstr "z/Architecture-läge stödjs inte på %s"
-
-#~ msgid "-mindirect-branch* options require -march=z900 or higher"
-#~ msgstr "flaggorna -mindirect-branch* kräver -march=z900 eller högre"
-
-#~ msgid "-mfunction-return* options require -march=z900 or higher"
-#~ msgstr "flaggorna -mfunction-return* kräver -march=z900 eller högre"
-
-#~ msgid "out-of-bounds access may be optimized away"
-#~ msgstr "åtkomst utanför gränserna kan optimeras bort"
-
-#~ msgid "containing loop"
-#~ msgstr "kringliggande slinga"
-
-#~ msgid "%E qualifier ignored on asm"
-#~ msgstr "kvalificeraren %E ignorerad på asm"
-
-#~ msgid "expected integer expression before ')'"
-#~ msgstr "heltalsuttryck förväntades före â€)â€"
-
-#~ msgid "expected %<tofrom%>"
-#~ msgstr "%<tofrom%> förväntades"
-
-#~ msgid "expected %<scalar%>"
-#~ msgstr "%<scalar%> förväntades"
-
-#~ msgid "cannot pass rvalue to reference parameter"
-#~ msgstr "kan inte skicka rvalue till referensparameter"
-
-#~ msgid "char-array initialized from wide string"
-#~ msgstr "char-vektor initierad från bred sträng"
-
-#~ msgid "wide character array initialized from non-wide string"
-#~ msgstr "bred teckenvektor initierad från icke-bred sträng"
-
-#~ msgid "wide character array initialized from incompatible wide string"
-#~ msgstr "bred teckenvektor initierad från en inkompatibel bred sträng"
-
-#~ msgid "invalid number of operands to __FMA"
-#~ msgstr "felaktigt antal operander till __FMA"
-
-#~ msgid "%q+D declared to take const reference, but implicit declaration would take non-const"
-#~ msgstr "%q+D deklarerad att ta const-referens, men implicit deklaration skulle ta icke-const"
-
-#~ msgid "declaration of %q#D"
-#~ msgstr "deklaration av %q#D"
-
-#~ msgid "changes meaning of %qD from %q#D"
-#~ msgstr "byter betydelse av %qD från %q#D"
-
-#~ msgid "expression %qE has side-effects"
-#~ msgstr "uttrycket %qE har sidoeffekter"
-
-#~ msgid "declaration of %q+#D conflicts with built-in declaration %q#D"
-#~ msgstr "deklaration av %q+#D står i konflikt med inbyggd deklaration %q#D"
-
-#~ msgid "%<-fno-for-scope%> is deprecated"
-#~ msgstr "%<-fno-for-scope%> bör undvikas"
-
-#~ msgid "%<-ffriend-injection%> is deprecated"
-#~ msgstr "%<-ffriend-injection%> bör undvikas"
-
-#~ msgid "%<signed%> or %<unsigned%> invalid for %qs"
-#~ msgstr "%<signed%> eller %<unsigned%> är ogiltigt för %qs"
-
-#~ msgid "%<long long%> invalid for %qs"
-#~ msgstr "%<long long%> ogiltig för %qs"
-
-#~ msgid "%<long%> invalid for %qs"
-#~ msgstr "%<long%> ogiltig för %qs"
-
-#~ msgid "%<short%> invalid for %qs"
-#~ msgstr "%<short%> ogiltig för %qs"
-
-#~ msgid "%<long%> or %<short%> invalid for %qs"
-#~ msgstr "%<long%> eller %<short%> ogiltig för %qs"
-
-#~ msgid "%<long%>, %<int%>, %<short%>, or %<char%> invalid for %qs"
-#~ msgstr "%<long%>, %<int%>, %<short%> eller %<char%> ogiltig för %qs"
-
-#~ msgid "%<long%> or %<short%> specified with char for %qs"
-#~ msgstr "%<long%> eller %<short%> angiven med char för %qs"
-
-#~ msgid "%<short%> or %<long%> invalid for %qs"
-#~ msgstr "%<short%> eller %<long%> ogiltig för %qs"
-
-#~ msgid "long, short, signed or unsigned used invalidly for %qs"
-#~ msgstr "long, short, signed eller unsigned använd felaktigt för %qs"
-
-#~ msgid "storage class specifiers invalid in parameter declarations"
-#~ msgstr "specificerare av lagringsklass ogiltig i parameterdeklarationer"
-
-#~ msgid "conversion to a reference to void will never use a type conversion operator"
-#~ msgstr "konvertering till en referens till void kommer aldrig använda en typkonverteringsoperator"
-
-#~ msgid "member %qD conflicts with virtual function table field name"
-#~ msgstr "medlem %qD står i konflikt med fältnamn i tabell över virtuella funktioner"
-
-#~ msgid "injected friend %qD is visible due to %<-ffriend-injection%>"
-#~ msgstr "inskjuten vän %qD är synlig på grund av %<-ffriend-injection%>"
-
-#~ msgid "name lookup of %qD changed"
-#~ msgstr "namnuppslagning av %qD ändrades"
-
-#~ msgid "matches this %qD under ISO standard rules"
-#~ msgstr "matchar denna %qD under ISO:s standardregler"
-
-#~ msgid " matches this %qD under old rules"
-#~ msgstr " stämmer med denna %qD under gamla regler"
-
-#~ msgid "name lookup of %qD changed for ISO %<for%> scoping"
-#~ msgstr "namnuppslagning av %qD ändrad för räckvidd i %<for%> enligt ISO"
-
-#~ msgid "cannot use obsolete binding %qD because it has a destructor"
-#~ msgstr "det går inte att använda föråldrad bindning vid %qD för att den har en destruerare"
-
-#~ msgid "using obsolete binding %qD"
-#~ msgstr "använder föråldrad bindning %qD"
-
-#~ msgid "suggested alternative: %qs"
-#~ msgstr "föreslaget alternativ: %qs"
-
-#~ msgid "lambda-expression in unevaluated context"
-#~ msgstr "lambdauttryck i oevaluerat sammanhang"
-
-#~ msgid "lambda-expression in template-argument"
-#~ msgstr "lambdauttryck i mallargument"
-
-#~ msgid "empty introduction-list"
-#~ msgstr "tom introduktionslista"
-
-#~ msgid "%qE is not a valid template argument for type %qT because it is not an object with linkage"
-#~ msgstr "%qE är inte ett giltigt mallargument för typen %qT eftersom det inte är ett objekt med länkklass"
-
-#~ msgid "%qE is not a valid template argument for type %qT because object %qD does not have linkage"
-#~ msgstr "%qE är inte ett giltigt mallargument för typ %qT eftersom objekt %qD inte har någon länkklass"
-
-#~ msgid "%<num_tasks%> expression must be integral"
-#~ msgstr "%<num_tasks%>-uttryck måste vara ett heltal"
-
-#~ msgid "lambda-expression in a constant expression"
-#~ msgstr "lambdauttryck i ett konstant uttryck"
-
-#~ msgid "taking address of xvalue (rvalue reference)"
-#~ msgstr "tar adressen till xvalue (rvalue-referens)"
-
-#~ msgid "reference to non-lvalue returned"
-#~ msgstr "referens till annat än lvärde returnerad"
-
-#~ msgid "using xvalue (rvalue reference) as lvalue"
-#~ msgstr "hjälp xvärde (rvärdesreferens) som lvärde"
-
-#~ msgid "int-array initialized from non-wide string"
-#~ msgstr "int-vektor initierad från icke-bred sträng"
-
-#~ msgid "int-array initialized from incompatible wide string"
-#~ msgstr "int-vektor initierad från inkompatibel bred sträng"
-
-#~ msgid "BACK argument to %qs intrinsic not yet implemented"
-#~ msgstr "Argumentet BACK till inbyggd %qs är inte implementerat ännu"
-
-#~ msgid "No location in statement"
-#~ msgstr "Ingen plats i sats"
-
-#~ msgid "Namelist %s cannot be renamed by USE association to %s"
-#~ msgstr "Namnlistan %s får inte namnändras av USE-association till %s"
-
-#~ msgid "Loop parallelized across gangs is not allowed inside another loop parallelized across gangs at %L"
-#~ msgstr "Slinga parallelliserad över gang är inte tillåten inuti en annan slinga parallelliserad över gang vid %L"
-
-#~ msgid "Loop parallelized across gangs is not allowed inside loop parallelized across workers at %L"
-#~ msgstr "Slinga parallelliserad över gang är inte tillåten inuti en slinga parallelliserad över worker vid %L"
-
-#~ msgid "Loop parallelized across workers is not allowed inside another loop parallelized across workers at %L"
-#~ msgstr "Slinga parallelliserad över worker är inte tillåten inuti en annan slinga parallelliserad över worker vid %L"
-
-#~ msgid "Loop parallelized across workers is not allowed inside another loop parallelized across vectors at %L"
-#~ msgstr "Slinga parallelliserad över worker är inte tillåten inuti en annan slinga parallelliserad över vektorer vid %L"
-
-#~ msgid "Loop parallelized across vectors is not allowed inside another loop parallelized across vectors at %L"
-#~ msgstr "Slinga parallelliserad över vektorer är inte tillåten inuti en annan slinga parallelliserad över vektorer vid %L"
-
-#~ msgid "Clause SEQ conflicts with INDEPENDENT at %L"
-#~ msgstr "Klausulen SEQ står i konflikt med INDEPENDENT vid %L"
-
-#~ msgid "Clause SEQ conflicts with GANG at %L"
-#~ msgstr "Klausulen SEQ står i konflikt med GANG vid %L"
-
-#~ msgid "Clause SEQ conflicts with WORKER at %L"
-#~ msgstr "Klausulen SEQ står i konflikt med WORKER vid %L"
-
-#~ msgid "Clause SEQ conflicts with VECTOR at %L"
-#~ msgstr "Klausulen SEQ står i konflikt med VECTOR vid %L"
-
-#~ msgid "Clause SEQ conflicts with AUTO at %L"
-#~ msgstr "Klausulen SEQ står i konflikt med AUTO vid %L"
-
-#~ msgid "Clause AUTO conflicts with GANG at %L"
-#~ msgstr "Klausulen AUTO står i konflikt med GANG vid %L"
-
-#~ msgid "Clause AUTO conflicts with WORKER at %L"
-#~ msgstr "Klausulen AUTO står i konflikt med WORKER vid %L"
-
-#~ msgid "Clause AUTO conflicts with VECTOR at %L"
-#~ msgstr "Klausulen AUTO står i konflikt med VECTOR vid %L"
-
-#~ msgid "The pointer component %qs of %qs at %L is a type that has not been declared"
-#~ msgstr "Pekarkomponenten %qs av %qs vid %L är en typen som inte har deklarerats"
-
-#~ msgid "check_data_variable(): Bad expression"
-#~ msgstr "check_data_variable(): Felaktigt uttryck"
-
-#~ msgid "Second argument of MODULO at %L is zero"
-#~ msgstr "Andra argumentet till MODULO vid %L är noll"
-
-#~ msgid "gfc_convert_constant(): Unexpected type"
-#~ msgstr "gfc_convert_constant(): Oväntad typ"
-
-#~ msgid "gfc_conv_constant_to_tree(): invalid type: %s"
-#~ msgstr "gfc_conv_constant_to_tree(): ogiltig typ: %s"
diff --git a/gcc/predict.def b/gcc/predict.def
index 53b39ab..24c1385 100644
--- a/gcc/predict.def
+++ b/gcc/predict.def
@@ -229,3 +229,10 @@ DEF_PREDICTOR (PRED_FORTRAN_ABSENT_DUMMY, "Fortran absent dummy", \
to be very likely. */
DEF_PREDICTOR (PRED_FORTRAN_LOOP_PREHEADER, "Fortran loop preheader", \
HITRATE (99), 0)
+
+/* Fortran assumed size arrays can be non-contiguous, so they need
+ to be repacked. */
+
+DEF_PREDICTOR (PRED_FORTRAN_CONTIGUOUS, "Fortran contiguous", \
+ HITRATE (75), 0)
+
diff --git a/gcc/print-rtl.c b/gcc/print-rtl.c
index fbb1085..10948ef 100644
--- a/gcc/print-rtl.c
+++ b/gcc/print-rtl.c
@@ -54,6 +54,13 @@ along with GCC; see the file COPYING3. If not see
#include "print-rtl.h"
#include "rtl-iter.h"
+/* Disable warnings about quoting issues in the pp_xxx calls below
+ that (intentionally) don't follow GCC diagnostic conventions. */
+#if __GNUC__ >= 10
+# pragma GCC diagnostic push
+# pragma GCC diagnostic ignored "-Wformat-diag"
+#endif
+
/* String printed at beginning of each RTL when it is dumped.
This string is set to ASM_COMMENT_START when the RTL is dumped in
the assembly output file. */
@@ -2142,3 +2149,7 @@ debug_bb_n_slim (int n)
}
#endif
+
+#if __GNUC__ >= 10
+# pragma GCC diagnostic pop
+#endif
diff --git a/gcc/print-tree.c b/gcc/print-tree.c
index 81b66a1..debea2b 100644
--- a/gcc/print-tree.c
+++ b/gcc/print-tree.c
@@ -233,6 +233,15 @@ print_node (FILE *file, const char *prefix, tree node, int indent,
return;
code = TREE_CODE (node);
+
+ /* It is unsafe to look at any other fields of a node with ERROR_MARK or
+ invalid code. */
+ if (code == ERROR_MARK || code >= MAX_TREE_CODES)
+ {
+ print_node_brief (file, prefix, node, indent);
+ return;
+ }
+
tclass = TREE_CODE_CLASS (code);
/* Don't get too deep in nesting. If the user wants to see deeper,
@@ -251,13 +260,6 @@ print_node (FILE *file, const char *prefix, tree node, int indent,
return;
}
- /* It is unsafe to look at any other fields of an ERROR_MARK node. */
- if (code == ERROR_MARK)
- {
- print_node_brief (file, prefix, node, indent);
- return;
- }
-
/* Allow this function to be called if the table is not there. */
if (table)
{
@@ -599,7 +601,7 @@ print_node (FILE *file, const char *prefix, tree node, int indent,
if (TYPE_NO_FORCE_BLK (node))
fputs (" no-force-blk", file);
- if (TYPE_STRING_FLAG (node))
+ if (code == ARRAY_TYPE && TYPE_STRING_FLAG (node))
fputs (" string-flag", file);
if (TYPE_NEEDS_CONSTRUCTING (node))
@@ -612,6 +614,11 @@ print_node (FILE *file, const char *prefix, tree node, int indent,
&& TYPE_REVERSE_STORAGE_ORDER (node))
fputs (" reverse-storage-order", file);
+ if ((code == RECORD_TYPE
+ || code == UNION_TYPE)
+ && TYPE_CXX_ODR_P (node))
+ fputs (" cxx-odr-p", file);
+
/* The transparent-union flag is used for different things in
different nodes. */
if ((code == UNION_TYPE || code == RECORD_TYPE)
diff --git a/gcc/profile-count.c b/gcc/profile-count.c
index 4f0bac0..2b774a7 100644
--- a/gcc/profile-count.c
+++ b/gcc/profile-count.c
@@ -168,11 +168,11 @@ profile_probability::dump (FILE *f) const
fprintf (f, "always");
else
fprintf (f, "%3.1f%%", (double)m_val * 100 / max_probability);
- if (m_quality == profile_adjusted)
+ if (m_quality == ADJUSTED)
fprintf (f, " (adjusted)");
- else if (m_quality == profile_afdo)
+ else if (m_quality == AFDO)
fprintf (f, " (auto FDO)");
- else if (m_quality == profile_guessed)
+ else if (m_quality == GUESSED)
fprintf (f, " (guessed)");
}
}
@@ -268,7 +268,7 @@ profile_count::to_frequency (struct function *fun) const
{
if (!initialized_p ())
return BB_FREQ_MAX;
- if (*this == profile_count::zero ())
+ if (*this == zero ())
return 0;
gcc_assert (REG_BR_PROB_BASE == BB_FREQ_MAX
&& fun->cfg->count_max.initialized_p ());
@@ -287,7 +287,7 @@ profile_count::to_cgraph_frequency (profile_count entry_bb_count) const
{
if (!initialized_p () || !entry_bb_count.initialized_p ())
return CGRAPH_FREQ_BASE;
- if (*this == profile_count::zero ())
+ if (*this == zero ())
return 0;
gcc_checking_assert (entry_bb_count.initialized_p ());
uint64_t scale;
@@ -310,7 +310,7 @@ profile_count::to_sreal_scale (profile_count in, bool *known) const
}
if (known)
*known = true;
- if (*this == profile_count::zero ())
+ if (*this == zero ())
return 0;
if (!in.m_val)
@@ -337,7 +337,7 @@ profile_count::adjust_for_ipa_scaling (profile_count *num,
if (*num == *den)
return;
/* Scaling to zero is always zero. */
- if (*num == profile_count::zero ())
+ if (*num == zero ())
return;
/* If den is non-zero we are safe. */
if (den->force_nonzero () == *den)
@@ -353,15 +353,16 @@ profile_count::adjust_for_ipa_scaling (profile_count *num,
if it is nonzero, not changing anything if IPA is uninitialized
and if IPA is zero, turning THIS into corresponding local profile with
global0. */
+
profile_count
profile_count::combine_with_ipa_count (profile_count ipa)
{
ipa = ipa.ipa ();
if (ipa.nonzero_p ())
return ipa;
- if (!ipa.initialized_p () || *this == profile_count::zero ())
+ if (!ipa.initialized_p () || *this == zero ())
return *this;
- if (ipa == profile_count::zero ())
+ if (ipa == zero ())
return this->global0 ();
return this->global0adjusted ();
}
@@ -369,6 +370,7 @@ profile_count::combine_with_ipa_count (profile_count ipa)
/* The profiling runtime uses gcov_type, which is usually 64bit integer.
Conversions back and forth are used to read the coverage and get it
into internal representation. */
+
profile_count
profile_count::from_gcov_type (gcov_type v, profile_quality quality)
{
@@ -383,7 +385,6 @@ profile_count::from_gcov_type (gcov_type v, profile_quality quality)
return ret;
}
-
/* COUNT1 times event happens with *THIS probability, COUNT2 times OTHER
happens with COUNT2 probablity. Return probablity that either *THIS or
OTHER happens. */
@@ -406,6 +407,5 @@ profile_probability::combine_with_count (profile_count count1,
return *this * count1.probability_in (count1 + count2)
+ other * count2.probability_in (count1 + count2);
else
- return *this * profile_probability::even ()
- + other * profile_probability::even ();
+ return *this * even () + other * even ();
}
diff --git a/gcc/profile-count.h b/gcc/profile-count.h
index 2669f0d..cbab596 100644
--- a/gcc/profile-count.h
+++ b/gcc/profile-count.h
@@ -28,35 +28,40 @@ class profile_count;
inside of classes, this is in global namespace. */
enum profile_quality {
/* Uninitialized value. */
- profile_uninitialized,
+ UNINITIALIZED_PROFILE,
+
/* Profile is based on static branch prediction heuristics and may
or may not match reality. It is local to function and cannot be compared
inter-procedurally. Never used by probabilities (they are always local).
*/
- profile_guessed_local,
+ GUESSED_LOCAL,
+
/* Profile was read by feedback and was 0, we used local heuristics to guess
better. This is the case of functions not run in profile fedback.
Never used by probabilities. */
- profile_guessed_global0,
+ GUESSED_GLOBAL0,
- /* Same as profile_guessed_global0 but global count is adjusted 0. */
- profile_guessed_global0adjusted,
+ /* Same as GUESSED_GLOBAL0 but global count is adjusted 0. */
+ GUESSED_GLOBAL0_ADJUSTED,
/* Profile is based on static branch prediction heuristics. It may or may
not reflect the reality but it can be compared interprocedurally
(for example, we inlined function w/o profile feedback into function
with feedback and propagated from that).
Never used by probablities. */
- profile_guessed,
+ GUESSED,
+
/* Profile was determined by autofdo. */
- profile_afdo,
+ AFDO,
+
/* Profile was originally based on feedback but it was adjusted
by code duplicating optimization. It may not precisely reflect the
particular code path. */
- profile_adjusted,
+ ADJUSTED,
+
/* Profile was read from profile feedback or determined by accurate static
method. */
- profile_precise
+ PRECISE
};
extern const char *profile_quality_as_string (enum profile_quality);
@@ -105,7 +110,7 @@ safe_scale_64bit (uint64_t a, uint64_t b, uint64_t c, uint64_t *res)
values greater than 1 needs to be represented otherwise.
In addition to actual value the quality of profile is tracked and propagated
- through all operations. Special value UNINITIALIZED is used for probabilities
+ through all operations. Special value UNINITIALIZED_PROFILE is used for probabilities
that has not been determined yet (for example bacause of
-fno-guess-branch-probability)
@@ -152,7 +157,7 @@ class GTY((user)) profile_probability
friend class profile_count;
public:
profile_probability (): m_val (uninitialized_probability),
- m_quality (profile_guessed)
+ m_quality (GUESSED)
{}
profile_probability (uint32_t val, profile_quality quality):
@@ -164,78 +169,85 @@ public:
{
profile_probability ret;
ret.m_val = 0;
- ret.m_quality = profile_precise;
+ ret.m_quality = PRECISE;
return ret;
}
+
static profile_probability guessed_never ()
{
profile_probability ret;
ret.m_val = 0;
- ret.m_quality = profile_guessed;
+ ret.m_quality = GUESSED;
return ret;
}
+
static profile_probability very_unlikely ()
{
/* Be consistent with PROB_VERY_UNLIKELY in predict.h. */
- profile_probability r
- = profile_probability::guessed_always ().apply_scale (1, 2000);
+ profile_probability r = guessed_always ().apply_scale (1, 2000);
r.m_val--;
return r;
}
+
static profile_probability unlikely ()
{
/* Be consistent with PROB_VERY_LIKELY in predict.h. */
- profile_probability r
- = profile_probability::guessed_always ().apply_scale (1, 5);
+ profile_probability r = guessed_always ().apply_scale (1, 5);
r.m_val--;
return r;
}
+
static profile_probability even ()
{
- return profile_probability::guessed_always ().apply_scale (1, 2);
+ return guessed_always ().apply_scale (1, 2);
}
+
static profile_probability very_likely ()
{
- return profile_probability::always () - very_unlikely ();
+ return always () - very_unlikely ();
}
+
static profile_probability likely ()
{
- return profile_probability::always () - unlikely ();
+ return always () - unlikely ();
}
+
static profile_probability guessed_always ()
{
profile_probability ret;
ret.m_val = max_probability;
- ret.m_quality = profile_guessed;
+ ret.m_quality = GUESSED;
return ret;
}
+
static profile_probability always ()
{
profile_probability ret;
ret.m_val = max_probability;
- ret.m_quality = profile_precise;
+ ret.m_quality = PRECISE;
return ret;
}
+
/* Probabilities which has not been initialized. Either because
initialization did not happen yet or because profile is unknown. */
static profile_probability uninitialized ()
{
profile_probability c;
c.m_val = uninitialized_probability;
- c.m_quality = profile_guessed;
+ c.m_quality = GUESSED;
return c;
}
-
/* Return true if value has been initialized. */
bool initialized_p () const
{
return m_val != uninitialized_probability;
}
+
/* Return true if value can be trusted. */
bool reliable_p () const
{
- return m_quality >= profile_adjusted;
+ return m_quality >= ADJUSTED;
}
/* Conversion from and to REG_BR_PROB_BASE integer fixpoint arithmetics.
@@ -245,9 +257,10 @@ public:
profile_probability ret;
gcc_checking_assert (v >= 0 && v <= REG_BR_PROB_BASE);
ret.m_val = RDIV (v * (uint64_t) max_probability, REG_BR_PROB_BASE);
- ret.m_quality = profile_guessed;
+ ret.m_quality = GUESSED;
return ret;
}
+
int to_reg_br_prob_base () const
{
gcc_checking_assert (initialized_p ());
@@ -262,12 +275,12 @@ public:
ret.m_quality = (enum profile_quality)(v & 7);
return ret;
}
+
int to_reg_br_prob_note () const
{
gcc_checking_assert (initialized_p ());
int ret = m_val * 8 + m_quality;
- gcc_checking_assert (profile_probability::from_reg_br_prob_note (ret)
- == *this);
+ gcc_checking_assert (from_reg_br_prob_note (ret) == *this);
return ret;
}
@@ -286,7 +299,7 @@ public:
gcc_checking_assert (tmp <= max_probability);
ret.m_val = tmp;
}
- ret.m_quality = profile_precise;
+ ret.m_quality = PRECISE;
return ret;
}
@@ -295,31 +308,33 @@ public:
{
return m_val == other.m_val && m_quality == other.m_quality;
}
+
profile_probability operator+ (const profile_probability &other) const
{
- if (other == profile_probability::never ())
+ if (other == never ())
return *this;
- if (*this == profile_probability::never ())
+ if (*this == never ())
return other;
if (!initialized_p () || !other.initialized_p ())
- return profile_probability::uninitialized ();
+ return uninitialized ();
profile_probability ret;
ret.m_val = MIN ((uint32_t)(m_val + other.m_val), max_probability);
ret.m_quality = MIN (m_quality, other.m_quality);
return ret;
}
+
profile_probability &operator+= (const profile_probability &other)
{
- if (other == profile_probability::never ())
+ if (other == never ())
return *this;
- if (*this == profile_probability::never ())
+ if (*this == never ())
{
*this = other;
return *this;
}
if (!initialized_p () || !other.initialized_p ())
- return *this = profile_probability::uninitialized ();
+ return *this = uninitialized ();
else
{
m_val = MIN ((uint32_t)(m_val + other.m_val), max_probability);
@@ -327,25 +342,27 @@ public:
}
return *this;
}
+
profile_probability operator- (const profile_probability &other) const
{
- if (*this == profile_probability::never ()
- || other == profile_probability::never ())
+ if (*this == never ()
+ || other == never ())
return *this;
if (!initialized_p () || !other.initialized_p ())
- return profile_probability::uninitialized ();
+ return uninitialized ();
profile_probability ret;
ret.m_val = m_val >= other.m_val ? m_val - other.m_val : 0;
ret.m_quality = MIN (m_quality, other.m_quality);
return ret;
}
+
profile_probability &operator-= (const profile_probability &other)
{
- if (*this == profile_probability::never ()
- || other == profile_probability::never ())
+ if (*this == never ()
+ || other == never ())
return *this;
if (!initialized_p () || !other.initialized_p ())
- return *this = profile_probability::uninitialized ();
+ return *this = uninitialized ();
else
{
m_val = m_val >= other.m_val ? m_val - other.m_val : 0;
@@ -353,45 +370,48 @@ public:
}
return *this;
}
+
profile_probability operator* (const profile_probability &other) const
{
- if (*this == profile_probability::never ()
- || other == profile_probability::never ())
- return profile_probability::never ();
+ if (*this == never ()
+ || other == never ())
+ return never ();
if (!initialized_p () || !other.initialized_p ())
- return profile_probability::uninitialized ();
+ return uninitialized ();
profile_probability ret;
ret.m_val = RDIV ((uint64_t)m_val * other.m_val, max_probability);
- ret.m_quality = MIN (MIN (m_quality, other.m_quality), profile_adjusted);
+ ret.m_quality = MIN (MIN (m_quality, other.m_quality), ADJUSTED);
return ret;
}
+
profile_probability &operator*= (const profile_probability &other)
{
- if (*this == profile_probability::never ()
- || other == profile_probability::never ())
- return *this = profile_probability::never ();
+ if (*this == never ()
+ || other == never ())
+ return *this = never ();
if (!initialized_p () || !other.initialized_p ())
- return *this = profile_probability::uninitialized ();
+ return *this = uninitialized ();
else
{
m_val = RDIV ((uint64_t)m_val * other.m_val, max_probability);
- m_quality = MIN (MIN (m_quality, other.m_quality), profile_adjusted);
+ m_quality = MIN (MIN (m_quality, other.m_quality), ADJUSTED);
}
return *this;
}
+
profile_probability operator/ (const profile_probability &other) const
{
- if (*this == profile_probability::never ())
- return profile_probability::never ();
+ if (*this == never ())
+ return never ();
if (!initialized_p () || !other.initialized_p ())
- return profile_probability::uninitialized ();
+ return uninitialized ();
profile_probability ret;
/* If we get probability above 1, mark it as unreliable and return 1. */
if (m_val >= other.m_val)
{
ret.m_val = max_probability;
ret.m_quality = MIN (MIN (m_quality, other.m_quality),
- profile_guessed);
+ GUESSED);
return ret;
}
else if (!m_val)
@@ -403,15 +423,16 @@ public:
other.m_val),
max_probability);
}
- ret.m_quality = MIN (MIN (m_quality, other.m_quality), profile_adjusted);
+ ret.m_quality = MIN (MIN (m_quality, other.m_quality), ADJUSTED);
return ret;
}
+
profile_probability &operator/= (const profile_probability &other)
{
- if (*this == profile_probability::never ())
- return *this = profile_probability::never ();
+ if (*this == never ())
+ return *this = never ();
if (!initialized_p () || !other.initialized_p ())
- return *this = profile_probability::uninitialized ();
+ return *this = uninitialized ();
else
{
/* If we get probability above 1, mark it as unreliable
@@ -420,7 +441,7 @@ public:
{
m_val = max_probability;
m_quality = MIN (MIN (m_quality, other.m_quality),
- profile_guessed);
+ GUESSED);
return *this;
}
else if (!m_val)
@@ -432,7 +453,7 @@ public:
other.m_val),
max_probability);
}
- m_quality = MIN (MIN (m_quality, other.m_quality), profile_adjusted);
+ m_quality = MIN (MIN (m_quality, other.m_quality), ADJUSTED);
}
return *this;
}
@@ -460,14 +481,14 @@ public:
Avoid scaling when overall outcome is supposed to be always.
Without knowing that one is inverse of toher, the result would be
conservative. */
- if (!(*this == profile_probability::always ()))
+ if (!(*this == always ()))
*this = (*this - ret) / ret.invert ();
return ret;
}
gcov_type apply (gcov_type val) const
{
- if (*this == profile_probability::uninitialized ())
+ if (*this == uninitialized ())
return val / 2;
return RDIV (val * m_val, max_probability);
}
@@ -475,14 +496,14 @@ public:
/* Return 1-*THIS. */
profile_probability invert () const
{
- return profile_probability::always() - *this;
+ return always() - *this;
}
/* Return THIS with quality dropped to GUESSED. */
profile_probability guessed () const
{
profile_probability ret = *this;
- ret.m_quality = profile_guessed;
+ ret.m_quality = GUESSED;
return ret;
}
@@ -490,22 +511,22 @@ public:
profile_probability afdo () const
{
profile_probability ret = *this;
- ret.m_quality = profile_afdo;
+ ret.m_quality = AFDO;
return ret;
}
/* Return *THIS * NUM / DEN. */
profile_probability apply_scale (int64_t num, int64_t den) const
{
- if (*this == profile_probability::never ())
+ if (*this == never ())
return *this;
if (!initialized_p ())
- return profile_probability::uninitialized ();
+ return uninitialized ();
profile_probability ret;
uint64_t tmp;
safe_scale_64bit (m_val, num, den, &tmp);
ret.m_val = MIN (tmp, max_probability);
- ret.m_quality = MIN (m_quality, profile_adjusted);
+ ret.m_quality = MIN (m_quality, ADJUSTED);
return ret;
}
@@ -525,10 +546,9 @@ public:
noreturn heuristic that is only one giving probability over 99% or bellow
1%. In future we might want to propagate reliability information across the
CFG if we find this information useful on multiple places. */
-
bool probably_reliable_p () const
{
- if (m_quality >= profile_adjusted)
+ if (m_quality >= ADJUSTED)
return true;
if (!initialized_p ())
return false;
@@ -539,10 +559,10 @@ public:
/* Return false if profile_probability is bogus. */
bool verify () const
{
- gcc_checking_assert (m_quality != profile_uninitialized);
+ gcc_checking_assert (m_quality != UNINITIALIZED_PROFILE);
if (m_val == uninitialized_probability)
- return m_quality == profile_guessed;
- else if (m_quality < profile_guessed)
+ return m_quality == GUESSED;
+ else if (m_quality < GUESSED)
return false;
return m_val <= max_probability;
}
@@ -553,6 +573,7 @@ public:
{
return initialized_p () && other.initialized_p () && m_val < other.m_val;
}
+
bool operator> (const profile_probability &other) const
{
return initialized_p () && other.initialized_p () && m_val > other.m_val;
@@ -562,6 +583,7 @@ public:
{
return initialized_p () && other.initialized_p () && m_val <= other.m_val;
}
+
bool operator>= (const profile_probability &other) const
{
return initialized_p () && other.initialized_p () && m_val >= other.m_val;
@@ -581,8 +603,10 @@ public:
/* Return true if THIS is known to differ significantly from OTHER. */
bool differs_from_p (profile_probability other) const;
+
/* Return if difference is greater than 50%. */
bool differs_lot_from_p (profile_probability other) const;
+
/* COUNT1 times event happens with *THIS probability, COUNT2 times OTHER
happens with COUNT2 probablity. Return probablity that either *THIS or
OTHER happens. */
@@ -684,8 +708,8 @@ private:
{
if (!initialized_p () || !other.initialized_p ())
return true;
- if (*this == profile_count::zero ()
- || other == profile_count::zero ())
+ if (*this == zero ()
+ || other == zero ())
return true;
return ipa_p () == other.ipa_p ();
}
@@ -695,31 +719,35 @@ public:
{
return from_gcov_type (0);
}
+
static profile_count adjusted_zero ()
{
profile_count c;
c.m_val = 0;
- c.m_quality = profile_adjusted;
+ c.m_quality = ADJUSTED;
return c;
}
+
static profile_count guessed_zero ()
{
profile_count c;
c.m_val = 0;
- c.m_quality = profile_guessed;
+ c.m_quality = GUESSED;
return c;
}
+
static profile_count one ()
{
return from_gcov_type (1);
}
+
/* Value of counters which has not been initialized. Either because
initialization did not happen yet or because profile is unknown. */
static profile_count uninitialized ()
{
profile_count c;
c.m_val = uninitialized_count;
- c.m_quality = profile_guessed_local;
+ c.m_quality = GUESSED_LOCAL;
return c;
}
@@ -735,20 +763,23 @@ public:
{
return m_val != uninitialized_count;
}
+
/* Return true if value can be trusted. */
bool reliable_p () const
{
- return m_quality >= profile_adjusted;
+ return m_quality >= ADJUSTED;
}
+
/* Return true if vlaue can be operated inter-procedurally. */
bool ipa_p () const
{
- return !initialized_p () || m_quality >= profile_guessed_global0;
+ return !initialized_p () || m_quality >= GUESSED_GLOBAL0;
}
+
/* Return true if quality of profile is precise. */
bool precise_p () const
{
- return m_quality == profile_precise;
+ return m_quality == PRECISE;
}
/* Get the value of the count. */
@@ -763,8 +794,8 @@ public:
that makes it terminate in a way not visible in CFG. */
bool ok_for_merging (profile_count other) const
{
- if (m_quality < profile_adjusted
- || other.m_quality < profile_adjusted)
+ if (m_quality < ADJUSTED
+ || other.m_quality < ADJUSTED)
return true;
return !(other < *this);
}
@@ -787,14 +818,15 @@ public:
{
return m_val == other.m_val && m_quality == other.m_quality;
}
+
profile_count operator+ (const profile_count &other) const
{
- if (other == profile_count::zero ())
+ if (other == zero ())
return *this;
- if (*this == profile_count::zero ())
+ if (*this == zero ())
return other;
if (!initialized_p () || !other.initialized_p ())
- return profile_count::uninitialized ();
+ return uninitialized ();
profile_count ret;
gcc_checking_assert (compatible_p (other));
@@ -802,17 +834,18 @@ public:
ret.m_quality = MIN (m_quality, other.m_quality);
return ret;
}
+
profile_count &operator+= (const profile_count &other)
{
- if (other == profile_count::zero ())
+ if (other == zero ())
return *this;
- if (*this == profile_count::zero ())
+ if (*this == zero ())
{
*this = other;
return *this;
}
if (!initialized_p () || !other.initialized_p ())
- return *this = profile_count::uninitialized ();
+ return *this = uninitialized ();
else
{
gcc_checking_assert (compatible_p (other));
@@ -821,24 +854,26 @@ public:
}
return *this;
}
+
profile_count operator- (const profile_count &other) const
{
- if (*this == profile_count::zero () || other == profile_count::zero ())
+ if (*this == zero () || other == zero ())
return *this;
if (!initialized_p () || !other.initialized_p ())
- return profile_count::uninitialized ();
+ return uninitialized ();
gcc_checking_assert (compatible_p (other));
profile_count ret;
ret.m_val = m_val >= other.m_val ? m_val - other.m_val : 0;
ret.m_quality = MIN (m_quality, other.m_quality);
return ret;
}
+
profile_count &operator-= (const profile_count &other)
{
- if (*this == profile_count::zero () || other == profile_count::zero ())
+ if (*this == zero () || other == zero ())
return *this;
if (!initialized_p () || !other.initialized_p ())
- return *this = profile_count::uninitialized ();
+ return *this = uninitialized ();
else
{
gcc_checking_assert (compatible_p (other));
@@ -851,8 +886,8 @@ public:
/* Return false if profile_count is bogus. */
bool verify () const
{
- gcc_checking_assert (m_quality != profile_uninitialized);
- return m_val != uninitialized_count || m_quality == profile_guessed_local;
+ gcc_checking_assert (m_quality != UNINITIALIZED_PROFILE);
+ return m_val != uninitialized_count || m_quality == GUESSED_LOCAL;
}
/* Comparsions are three-state and conservative. False is returned if
@@ -861,30 +896,33 @@ public:
{
if (!initialized_p () || !other.initialized_p ())
return false;
- if (*this == profile_count::zero ())
- return !(other == profile_count::zero ());
- if (other == profile_count::zero ())
+ if (*this == zero ())
+ return !(other == zero ());
+ if (other == zero ())
return false;
gcc_checking_assert (compatible_p (other));
return m_val < other.m_val;
}
+
bool operator> (const profile_count &other) const
{
if (!initialized_p () || !other.initialized_p ())
return false;
- if (*this == profile_count::zero ())
+ if (*this == zero ())
return false;
- if (other == profile_count::zero ())
- return !(*this == profile_count::zero ());
+ if (other == zero ())
+ return !(*this == zero ());
gcc_checking_assert (compatible_p (other));
return initialized_p () && other.initialized_p () && m_val > other.m_val;
}
+
bool operator< (const gcov_type other) const
{
gcc_checking_assert (ipa_p ());
gcc_checking_assert (other >= 0);
return initialized_p () && m_val < (uint64_t) other;
}
+
bool operator> (const gcov_type other) const
{
gcc_checking_assert (ipa_p ());
@@ -896,36 +934,40 @@ public:
{
if (!initialized_p () || !other.initialized_p ())
return false;
- if (*this == profile_count::zero ())
+ if (*this == zero ())
return true;
- if (other == profile_count::zero ())
- return (*this == profile_count::zero ());
+ if (other == zero ())
+ return (*this == zero ());
gcc_checking_assert (compatible_p (other));
return m_val <= other.m_val;
}
+
bool operator>= (const profile_count &other) const
{
if (!initialized_p () || !other.initialized_p ())
return false;
- if (other == profile_count::zero ())
+ if (other == zero ())
return true;
- if (*this == profile_count::zero ())
- return (other == profile_count::zero ());
+ if (*this == zero ())
+ return (other == zero ());
gcc_checking_assert (compatible_p (other));
return m_val >= other.m_val;
}
+
bool operator<= (const gcov_type other) const
{
gcc_checking_assert (ipa_p ());
gcc_checking_assert (other >= 0);
return initialized_p () && m_val <= (uint64_t) other;
}
+
bool operator>= (const gcov_type other) const
{
gcc_checking_assert (ipa_p ());
gcc_checking_assert (other >= 0);
return initialized_p () && m_val >= (uint64_t) other;
}
+
/* Return true when value is not zero and can be used for scaling.
This is different from *this > 0 because that requires counter to
be IPA. */
@@ -943,7 +985,7 @@ public:
if (ret.m_val == 0)
{
ret.m_val = 1;
- ret.m_quality = MIN (m_quality, profile_adjusted);
+ ret.m_quality = MIN (m_quality, ADJUSTED);
}
return ret;
}
@@ -954,9 +996,9 @@ public:
return other;
if (!other.initialized_p ())
return *this;
- if (*this == profile_count::zero ())
+ if (*this == zero ())
return other;
- if (other == profile_count::zero ())
+ if (other == zero ())
return *this;
gcc_checking_assert (compatible_p (other));
if (m_val < other.m_val || (m_val == other.m_val
@@ -973,22 +1015,22 @@ public:
if (m_val == 0)
return *this;
if (!initialized_p ())
- return profile_count::uninitialized ();
+ return uninitialized ();
profile_count ret;
ret.m_val = RDIV (m_val * prob, REG_BR_PROB_BASE);
- ret.m_quality = MIN (m_quality, profile_adjusted);
+ ret.m_quality = MIN (m_quality, ADJUSTED);
return ret;
}
/* Scale counter according to PROB. */
profile_count apply_probability (profile_probability prob) const
{
- if (*this == profile_count::zero ())
+ if (*this == zero ())
return *this;
if (prob == profile_probability::never ())
- return profile_count::zero ();
+ return zero ();
if (!initialized_p ())
- return profile_count::uninitialized ();
+ return uninitialized ();
profile_count ret;
uint64_t tmp;
safe_scale_64bit (m_val, prob.m_val, profile_probability::max_probability,
@@ -997,30 +1039,32 @@ public:
ret.m_quality = MIN (m_quality, prob.m_quality);
return ret;
}
+
/* Return *THIS * NUM / DEN. */
profile_count apply_scale (int64_t num, int64_t den) const
{
if (m_val == 0)
return *this;
if (!initialized_p ())
- return profile_count::uninitialized ();
+ return uninitialized ();
profile_count ret;
uint64_t tmp;
gcc_checking_assert (num >= 0 && den > 0);
safe_scale_64bit (m_val, num, den, &tmp);
ret.m_val = MIN (tmp, max_count);
- ret.m_quality = MIN (m_quality, profile_adjusted);
+ ret.m_quality = MIN (m_quality, ADJUSTED);
return ret;
}
+
profile_count apply_scale (profile_count num, profile_count den) const
{
- if (*this == profile_count::zero ())
+ if (*this == zero ())
return *this;
- if (num == profile_count::zero ())
+ if (num == zero ())
return num;
if (!initialized_p () || !num.initialized_p () || !den.initialized_p ())
- return profile_count::uninitialized ();
+ return uninitialized ();
if (num == den)
return *this;
gcc_checking_assert (den.m_val);
@@ -1029,10 +1073,10 @@ public:
uint64_t val;
safe_scale_64bit (m_val, num.m_val, den.m_val, &val);
ret.m_val = MIN (val, max_count);
- ret.m_quality = MIN (MIN (MIN (m_quality, profile_adjusted),
+ ret.m_quality = MIN (MIN (MIN (m_quality, ADJUSTED),
num.m_quality), den.m_quality);
if (num.ipa_p () && !ret.ipa_p ())
- ret.m_quality = MIN (num.m_quality, profile_guessed);
+ ret.m_quality = MIN (num.m_quality, GUESSED);
return ret;
}
@@ -1042,7 +1086,7 @@ public:
profile_count ret = *this;
if (!initialized_p ())
return *this;
- ret.m_quality = profile_guessed_local;
+ ret.m_quality = GUESSED_LOCAL;
return ret;
}
@@ -1052,7 +1096,7 @@ public:
profile_count ret = *this;
if (!initialized_p ())
return *this;
- ret.m_quality = profile_guessed_global0;
+ ret.m_quality = GUESSED_GLOBAL0;
return ret;
}
@@ -1063,7 +1107,7 @@ public:
profile_count ret = *this;
if (!initialized_p ())
return *this;
- ret.m_quality = profile_guessed_global0adjusted;
+ ret.m_quality = GUESSED_GLOBAL0_ADJUSTED;
return ret;
}
@@ -1071,7 +1115,7 @@ public:
profile_count guessed () const
{
profile_count ret = *this;
- ret.m_quality = MIN (ret.m_quality, profile_guessed);
+ ret.m_quality = MIN (ret.m_quality, GUESSED);
return ret;
}
@@ -1079,20 +1123,20 @@ public:
acorss functions. */
profile_count ipa () const
{
- if (m_quality > profile_guessed_global0adjusted)
+ if (m_quality > GUESSED_GLOBAL0_ADJUSTED)
return *this;
- if (m_quality == profile_guessed_global0)
- return profile_count::zero ();
- if (m_quality == profile_guessed_global0adjusted)
- return profile_count::adjusted_zero ();
- return profile_count::uninitialized ();
+ if (m_quality == GUESSED_GLOBAL0)
+ return zero ();
+ if (m_quality == GUESSED_GLOBAL0_ADJUSTED)
+ return adjusted_zero ();
+ return uninitialized ();
}
/* Return THIS with quality dropped to AFDO. */
profile_count afdo () const
{
profile_count ret = *this;
- ret.m_quality = profile_afdo;
+ ret.m_quality = AFDO;
return ret;
}
@@ -1100,13 +1144,13 @@ public:
OVERALL. */
profile_probability probability_in (const profile_count overall) const
{
- if (*this == profile_count::zero ()
- && !(overall == profile_count::zero ()))
+ if (*this == zero ()
+ && !(overall == zero ()))
return profile_probability::never ();
if (!initialized_p () || !overall.initialized_p ()
|| !overall.m_val)
return profile_probability::uninitialized ();
- if (*this == overall && m_quality == profile_precise)
+ if (*this == overall && m_quality == PRECISE)
return profile_probability::always ();
profile_probability ret;
gcc_checking_assert (compatible_p (overall));
@@ -1114,14 +1158,14 @@ public:
if (overall.m_val < m_val)
{
ret.m_val = profile_probability::max_probability;
- ret.m_quality = profile_guessed;
+ ret.m_quality = GUESSED;
return ret;
}
else
ret.m_val = RDIV (m_val * profile_probability::max_probability,
overall.m_val);
ret.m_quality = MIN (MAX (MIN (m_quality, overall.m_quality),
- profile_guessed), profile_adjusted);
+ GUESSED), ADJUSTED);
return ret;
}
@@ -1154,7 +1198,7 @@ public:
Conversions back and forth are used to read the coverage and get it
into internal representation. */
static profile_count from_gcov_type (gcov_type v,
- profile_quality quality = profile_precise);
+ profile_quality quality = PRECISE);
/* LTO streaming support. */
static profile_count stream_in (struct lto_input_block *);
diff --git a/gcc/profile.c b/gcc/profile.c
index a1dba1a..e3f8c55 100644
--- a/gcc/profile.c
+++ b/gcc/profile.c
@@ -167,12 +167,11 @@ instrument_values (histogram_values values)
gimple_gen_pow2_profiler (hist, t, 0);
break;
- case HIST_TYPE_SINGLE_VALUE:
- gimple_gen_one_value_profiler (hist, t, 0);
+ case HIST_TYPE_TOPN_VALUES:
+ gimple_gen_topn_values_profiler (hist, t, 0);
break;
case HIST_TYPE_INDIR_CALL:
- case HIST_TYPE_INDIR_CALL_TOPN:
gimple_gen_ic_profiler (hist, t, 0);
break;
diff --git a/gcc/read-md.h b/gcc/read-md.h
index 18426f7..327f378 100644
--- a/gcc/read-md.h
+++ b/gcc/read-md.h
@@ -337,6 +337,7 @@ class rtx_reader : public md_reader
~rtx_reader ();
bool read_rtx (const char *rtx_name, vec<rtx> *rtxen);
+ rtx rtx_alloc_for_name (const char *);
rtx read_rtx_code (const char *code_name);
virtual rtx read_rtx_operand (rtx return_rtx, int idx);
rtx read_nested_rtx ();
diff --git a/gcc/read-rtl-function.c b/gcc/read-rtl-function.c
index 53f7a94..3cf34ba 100644
--- a/gcc/read-rtl-function.c
+++ b/gcc/read-rtl-function.c
@@ -707,7 +707,7 @@ parse_edge_flag_token (const char *tok)
} while (0);
#include "cfg-flags.def"
#undef DEF_EDGE_FLAG
- error ("unrecognized edge flag: '%s'", tok);
+ error ("unrecognized edge flag: %qs", tok);
return 0;
}
@@ -978,7 +978,7 @@ function_reader::parse_enum_value (int num_values, const char *const *strings)
if (strcmp (name.string, strings[i]) == 0)
return i;
}
- error ("unrecognized enum value: '%s'", name.string);
+ error ("unrecognized enum value: %qs", name.string);
return 0;
}
diff --git a/gcc/read-rtl.c b/gcc/read-rtl.c
index ebd69bd..6b1b811 100644
--- a/gcc/read-rtl.c
+++ b/gcc/read-rtl.c
@@ -194,22 +194,31 @@ static const compact_insn_name compact_insn_names[] = {
{ NOTE, "cnote" }
};
-/* Implementations of the iterator_group callbacks for codes. */
+/* Return the rtx code for NAME, or UNKNOWN if NAME isn't a valid rtx code. */
-static int
-find_code (const char *name)
+static rtx_code
+maybe_find_code (const char *name)
{
- int i;
-
- for (i = 0; i < NUM_RTX_CODE; i++)
+ for (int i = 0; i < NUM_RTX_CODE; i++)
if (strcmp (GET_RTX_NAME (i), name) == 0)
- return i;
+ return (rtx_code) i;
- for (i = 0; i < (signed)ARRAY_SIZE (compact_insn_names); i++)
+ for (int i = 0; i < (signed)ARRAY_SIZE (compact_insn_names); i++)
if (strcmp (compact_insn_names[i].name, name) == 0)
return compact_insn_names[i].code;
- fatal_with_file_and_line ("unknown rtx code `%s'", name);
+ return UNKNOWN;
+}
+
+/* Implementations of the iterator_group callbacks for codes. */
+
+static int
+find_code (const char *name)
+{
+ rtx_code code = maybe_find_code (name);
+ if (code == UNKNOWN)
+ fatal_with_file_and_line ("unknown rtx code `%s'", name);
+ return code;
}
static void
@@ -277,9 +286,11 @@ apply_subst_iterator (rtx rt, unsigned int, int value)
return;
gcc_assert (GET_CODE (rt) == DEFINE_INSN
|| GET_CODE (rt) == DEFINE_INSN_AND_SPLIT
+ || GET_CODE (rt) == DEFINE_INSN_AND_REWRITE
|| GET_CODE (rt) == DEFINE_EXPAND);
- int attrs = GET_CODE (rt) == DEFINE_INSN_AND_SPLIT ? 7 : 4;
+ int attrs = (GET_CODE (rt) == DEFINE_INSN_AND_SPLIT ? 7
+ : GET_CODE (rt) == DEFINE_INSN_AND_REWRITE ? 6 : 4);
attrs_vec = XVEC (rt, attrs);
/* If we've already added attribute 'current_iterator_name', then we
@@ -540,6 +551,7 @@ add_condition_to_rtx (rtx x, const char *extra)
break;
case DEFINE_INSN_AND_SPLIT:
+ case DEFINE_INSN_AND_REWRITE:
XSTR (x, 2) = add_condition_to_string (XSTR (x, 2), extra);
XSTR (x, 4) = add_condition_to_string (XSTR (x, 4), extra);
break;
@@ -623,6 +635,7 @@ named_rtx_p (rtx x)
case DEFINE_EXPAND:
case DEFINE_INSN:
case DEFINE_INSN_AND_SPLIT:
+ case DEFINE_INSN_AND_REWRITE:
return true;
default:
@@ -1282,7 +1295,7 @@ read_subst_mapping (htab_t subst_iters_table, htab_t subst_attrs_table,
m = add_mapping (&substs, subst_iters_table, attr_operands[1]);
end_ptr = &m->values;
end_ptr = add_map_value (end_ptr, 1, "");
- end_ptr = add_map_value (end_ptr, 2, "");
+ add_map_value (end_ptr, 2, "");
add_define_attr_for_define_subst (attr_operands[1], queue);
}
@@ -1290,7 +1303,7 @@ read_subst_mapping (htab_t subst_iters_table, htab_t subst_attrs_table,
m = add_mapping (&substs, subst_attrs_table, attr_operands[0]);
end_ptr = &m->values;
end_ptr = add_map_value (end_ptr, 1, attr_operands[2]);
- end_ptr = add_map_value (end_ptr, 2, attr_operands[3]);
+ add_map_value (end_ptr, 2, attr_operands[3]);
}
/* Check newly-created code iterator ITERATOR to see whether every code has the
@@ -1306,7 +1319,37 @@ check_code_iterator (struct mapping *iterator)
for (v = iterator->values->next; v != 0; v = v->next)
if (strcmp (GET_RTX_FORMAT (bellwether), GET_RTX_FORMAT (v->number)) != 0)
fatal_with_file_and_line ("code iterator `%s' combines "
- "different rtx formats", iterator->name);
+ "`%s' and `%s', which have different "
+ "rtx formats", iterator->name,
+ GET_RTX_NAME (bellwether),
+ GET_RTX_NAME (v->number));
+}
+
+/* Check that all values of attribute ATTR are rtx codes that have a
+ consistent format. Return a representative code. */
+
+static rtx_code
+check_code_attribute (mapping *attr)
+{
+ rtx_code bellwether = UNKNOWN;
+ for (map_value *v = attr->values; v != 0; v = v->next)
+ {
+ rtx_code code = maybe_find_code (v->string);
+ if (code == UNKNOWN)
+ fatal_with_file_and_line ("code attribute `%s' contains "
+ "unrecognized rtx code `%s'",
+ attr->name, v->string);
+ if (bellwether == UNKNOWN)
+ bellwether = code;
+ else if (strcmp (GET_RTX_FORMAT (bellwether),
+ GET_RTX_FORMAT (code)) != 0)
+ fatal_with_file_and_line ("code attribute `%s' combines "
+ "`%s' and `%s', which have different "
+ "rtx formats", attr->name,
+ GET_RTX_NAME (bellwether),
+ GET_RTX_NAME (code));
+ }
+ return bellwether;
}
/* Read an rtx-related declaration from the MD file, given that it
@@ -1467,6 +1510,54 @@ parse_reg_note_name (const char *string)
fatal_with_file_and_line ("unrecognized REG_NOTE name: `%s'", string);
}
+/* Allocate an rtx for code NAME. If NAME is a code iterator or code
+ attribute, record its use for later and use one of its possible
+ values as an interim rtx code. */
+
+rtx
+rtx_reader::rtx_alloc_for_name (const char *name)
+{
+#ifdef GENERATOR_FILE
+ size_t len = strlen (name);
+ if (name[0] == '<' && name[len - 1] == '>')
+ {
+ /* Copy the attribute string into permanent storage, without the
+ angle brackets around it. */
+ obstack *strings = get_string_obstack ();
+ obstack_grow0 (strings, name + 1, len - 2);
+ char *deferred_name = XOBFINISH (strings, char *);
+
+ /* Find the name of the attribute. */
+ const char *attr = strchr (deferred_name, ':');
+ if (!attr)
+ attr = deferred_name;
+
+ /* Find the attribute itself. */
+ mapping *m = (mapping *) htab_find (codes.attrs, &attr);
+ if (!m)
+ fatal_with_file_and_line ("unknown code attribute `%s'", attr);
+
+ /* Pick the first possible code for now, and record the attribute
+ use for later. */
+ rtx x = rtx_alloc (check_code_attribute (m));
+ record_attribute_use (&codes, x, 0, deferred_name);
+ return x;
+ }
+
+ mapping *iterator = (mapping *) htab_find (codes.iterators, &name);
+ if (iterator != 0)
+ {
+ /* Pick the first possible code for now, and record the iterator
+ use for later. */
+ rtx x = rtx_alloc (rtx_code (iterator->values->number));
+ record_iterator_use (iterator, x, 0);
+ return x;
+ }
+#endif
+
+ return rtx_alloc (rtx_code (codes.find_builtin (name)));
+}
+
/* Subroutine of read_rtx and read_nested_rtx. CODE_NAME is the name of
either an rtx code or a code iterator. Parse the rest of the rtx and
return it. */
@@ -1475,7 +1566,6 @@ rtx
rtx_reader::read_rtx_code (const char *code_name)
{
RTX_CODE code;
- struct mapping *iterator = NULL;
const char *format_ptr;
struct md_name name;
rtx return_rtx;
@@ -1509,20 +1599,9 @@ rtx_reader::read_rtx_code (const char *code_name)
return return_rtx;
}
- /* If this code is an iterator, build the rtx using the iterator's
- first value. */
-#ifdef GENERATOR_FILE
- iterator = (struct mapping *) htab_find (codes.iterators, &code_name);
- if (iterator != 0)
- code = (enum rtx_code) iterator->values->number;
- else
- code = (enum rtx_code) codes.find_builtin (code_name);
-#else
- code = (enum rtx_code) codes.find_builtin (code_name);
-#endif
-
/* If we end up with an insn expression then we free this space below. */
- return_rtx = rtx_alloc (code);
+ return_rtx = rtx_alloc_for_name (code_name);
+ code = GET_CODE (return_rtx);
format_ptr = GET_RTX_FORMAT (code);
memset (return_rtx, 0, RTX_CODE_SIZE (code));
PUT_CODE (return_rtx, code);
@@ -1534,9 +1613,6 @@ rtx_reader::read_rtx_code (const char *code_name)
m_reuse_rtx_by_id[reuse_id] = return_rtx;
}
- if (iterator)
- record_iterator_use (iterator, return_rtx, 0);
-
/* Check for flags. */
read_flags (return_rtx);
@@ -1765,8 +1841,8 @@ rtx_reader::read_rtx_operand (rtx return_rtx, int idx)
break;
}
- /* The output template slot of a DEFINE_INSN,
- DEFINE_INSN_AND_SPLIT, or DEFINE_PEEPHOLE automatically
+ /* The output template slot of a DEFINE_INSN, DEFINE_INSN_AND_SPLIT,
+ DEFINE_INSN_AND_REWRITE or DEFINE_PEEPHOLE automatically
gets a star inserted as its first character, if it is
written with a brace block instead of a string constant. */
star_if_braced = (format_ptr[idx] == 'T');
@@ -1783,7 +1859,8 @@ rtx_reader::read_rtx_operand (rtx return_rtx, int idx)
if (*stringbuf == '\0'
&& idx == 0
&& (GET_CODE (return_rtx) == DEFINE_INSN
- || GET_CODE (return_rtx) == DEFINE_INSN_AND_SPLIT))
+ || GET_CODE (return_rtx) == DEFINE_INSN_AND_SPLIT
+ || GET_CODE (return_rtx) == DEFINE_INSN_AND_REWRITE))
{
struct obstack *string_obstack = get_string_obstack ();
char line_name[20];
diff --git a/gcc/reg-stack.c b/gcc/reg-stack.c
index 033c978..5576630 100644
--- a/gcc/reg-stack.c
+++ b/gcc/reg-stack.c
@@ -484,7 +484,6 @@ check_asm_stack_operands (rtx_insn *insn)
if (which_alternative < 0)
{
- malformed_asm = 1;
/* Avoid further trouble with this insn. */
PATTERN (insn) = gen_rtx_USE (VOIDmode, const0_rtx);
return 0;
@@ -545,7 +544,8 @@ check_asm_stack_operands (rtx_insn *insn)
for (j = 0; j < n_clobbers; j++)
if (REGNO (recog_data.operand[i]) == REGNO (clobber_reg[j]))
{
- error_for_asm (insn, "output constraint %d cannot be specified together with \"%s\" clobber",
+ error_for_asm (insn, "output constraint %d cannot be "
+ "specified together with %qs clobber",
i, reg_names [REGNO (clobber_reg[j])]);
malformed_asm = 1;
break;
@@ -568,7 +568,7 @@ check_asm_stack_operands (rtx_insn *insn)
if (i != LAST_STACK_REG + 1)
{
- error_for_asm (insn, "output regs must be grouped at top of stack");
+ error_for_asm (insn, "output registers must be grouped at top of stack");
malformed_asm = 1;
}
@@ -608,7 +608,8 @@ check_asm_stack_operands (rtx_insn *insn)
if (i != LAST_STACK_REG + 1)
{
error_for_asm (insn,
- "implicitly popped regs must be grouped at top of stack");
+ "implicitly popped registers must be grouped "
+ "at top of stack");
malformed_asm = 1;
}
@@ -625,7 +626,8 @@ check_asm_stack_operands (rtx_insn *insn)
if (i != LAST_STACK_REG + 1)
{
error_for_asm (insn,
- "explicitly used regs must be grouped at top of stack");
+ "explicitly used registers must be grouped "
+ "at top of stack");
malformed_asm = 1;
}
diff --git a/gcc/regcprop.c b/gcc/regcprop.c
index 4842ce9..a18c24f 100644
--- a/gcc/regcprop.c
+++ b/gcc/regcprop.c
@@ -1216,8 +1216,8 @@ validate_value_data (struct value_data *vd)
if (vd->e[i].mode == VOIDmode)
{
if (vd->e[i].next_regno != INVALID_REGNUM)
- internal_error ("validate_value_data: [%u] Bad next_regno for empty chain (%u)",
- i, vd->e[i].next_regno);
+ internal_error ("%qs: [%u] bad %<next_regno%> for empty chain (%u)",
+ __func__, i, vd->e[i].next_regno);
continue;
}
@@ -1228,11 +1228,11 @@ validate_value_data (struct value_data *vd)
j = vd->e[j].next_regno)
{
if (TEST_HARD_REG_BIT (set, j))
- internal_error ("validate_value_data: Loop in regno chain (%u)",
- j);
+ internal_error ("%qs: loop in %<next_regno%> chain (%u)",
+ __func__, j);
if (vd->e[j].oldest_regno != i)
- internal_error ("validate_value_data: [%u] Bad oldest_regno (%u)",
- j, vd->e[j].oldest_regno);
+ internal_error ("%qs: [%u] bad %<oldest_regno%> (%u)",
+ __func__, j, vd->e[j].oldest_regno);
SET_HARD_REG_BIT (set, j);
}
@@ -1243,8 +1243,9 @@ validate_value_data (struct value_data *vd)
&& (vd->e[i].mode != VOIDmode
|| vd->e[i].oldest_regno != i
|| vd->e[i].next_regno != INVALID_REGNUM))
- internal_error ("validate_value_data: [%u] Non-empty reg in chain (%s %u %i)",
- i, GET_MODE_NAME (vd->e[i].mode), vd->e[i].oldest_regno,
+ internal_error ("%qs: [%u] non-empty register in chain (%s %u %i)",
+ __func__, i,
+ GET_MODE_NAME (vd->e[i].mode), vd->e[i].oldest_regno,
vd->e[i].next_regno);
}
diff --git a/gcc/reginfo.c b/gcc/reginfo.c
index 315c5ec..bec2d40 100644
--- a/gcc/reginfo.c
+++ b/gcc/reginfo.c
@@ -717,11 +717,11 @@ fix_register (const char *name, int fixed, int call_used)
switch (call_used)
{
case 0:
- error ("can%'t use %qs as a call-saved register", name);
+ error ("cannot use %qs as a call-saved register", name);
break;
case 1:
- error ("can%'t use %qs as a call-used register", name);
+ error ("cannot use %qs as a call-used register", name);
break;
default:
@@ -733,7 +733,7 @@ fix_register (const char *name, int fixed, int call_used)
switch (call_used)
{
case 1:
- error ("can%'t use %qs as a fixed register", name);
+ error ("cannot use %qs as a fixed register", name);
break;
case 0:
diff --git a/gcc/regrename.c b/gcc/regrename.c
index 637b3cb..5259d56 100644
--- a/gcc/regrename.c
+++ b/gcc/regrename.c
@@ -1426,10 +1426,9 @@ scan_rtx (rtx_insn *insn, rtx *loc, enum reg_class cl, enum scan_actions action,
{
const char *fmt;
rtx x = *loc;
- enum rtx_code code = GET_CODE (x);
int i, j;
- code = GET_CODE (x);
+ enum rtx_code code = GET_CODE (x);
switch (code)
{
case CONST:
diff --git a/gcc/reload1.c b/gcc/reload1.c
index bb112d8..3ad6f1d 100644
--- a/gcc/reload1.c
+++ b/gcc/reload1.c
@@ -2062,7 +2062,7 @@ static void
spill_failure (rtx_insn *insn, enum reg_class rclass)
{
if (asm_noperands (PATTERN (insn)) >= 0)
- error_for_asm (insn, "can%'t find a register in class %qs while "
+ error_for_asm (insn, "cannot find a register in class %qs while "
"reloading %<asm%>",
reg_class_names[rclass]);
else
@@ -3234,96 +3234,6 @@ eliminate_regs_in_insn (rtx_insn *insn, int replace)
return 0;
}
- if (old_set != 0 && REG_P (SET_DEST (old_set))
- && REGNO (SET_DEST (old_set)) < FIRST_PSEUDO_REGISTER)
- {
- /* Check for setting an eliminable register. */
- for (ep = reg_eliminate; ep < &reg_eliminate[NUM_ELIMINABLE_REGS]; ep++)
- if (ep->from_rtx == SET_DEST (old_set) && ep->can_eliminate)
- {
- /* If this is setting the frame pointer register to the
- hardware frame pointer register and this is an elimination
- that will be done (tested above), this insn is really
- adjusting the frame pointer downward to compensate for
- the adjustment done before a nonlocal goto. */
- if (!HARD_FRAME_POINTER_IS_FRAME_POINTER
- && ep->from == FRAME_POINTER_REGNUM
- && ep->to == HARD_FRAME_POINTER_REGNUM)
- {
- rtx base = SET_SRC (old_set);
- rtx_insn *base_insn = insn;
- HOST_WIDE_INT offset = 0;
-
- while (base != ep->to_rtx)
- {
- rtx_insn *prev_insn;
- rtx prev_set;
-
- if (GET_CODE (base) == PLUS
- && CONST_INT_P (XEXP (base, 1)))
- {
- offset += INTVAL (XEXP (base, 1));
- base = XEXP (base, 0);
- }
- else if ((prev_insn = prev_nonnote_insn (base_insn)) != 0
- && (prev_set = single_set (prev_insn)) != 0
- && rtx_equal_p (SET_DEST (prev_set), base))
- {
- base = SET_SRC (prev_set);
- base_insn = prev_insn;
- }
- else
- break;
- }
-
- if (base == ep->to_rtx)
- {
- rtx src = plus_constant (Pmode, ep->to_rtx,
- offset - ep->offset);
-
- new_body = old_body;
- if (! replace)
- {
- new_body = copy_insn (old_body);
- if (REG_NOTES (insn))
- REG_NOTES (insn) = copy_insn_1 (REG_NOTES (insn));
- }
- PATTERN (insn) = new_body;
- old_set = single_set (insn);
-
- /* First see if this insn remains valid when we
- make the change. If not, keep the INSN_CODE
- the same and let reload fit it up. */
- validate_change (insn, &SET_SRC (old_set), src, 1);
- validate_change (insn, &SET_DEST (old_set),
- ep->to_rtx, 1);
- if (! apply_change_group ())
- {
- SET_SRC (old_set) = src;
- SET_DEST (old_set) = ep->to_rtx;
- }
-
- val = 1;
- goto done;
- }
- }
-
- /* In this case this insn isn't serving a useful purpose. We
- will delete it in reload_as_needed once we know that this
- elimination is, in fact, being done.
-
- If REPLACE isn't set, we can't delete this insn, but needn't
- process it since it won't be used unless something changes. */
- if (replace)
- {
- delete_dead_insn (insn);
- return 1;
- }
- val = 1;
- goto done;
- }
- }
-
/* We allow one special case which happens to work on all machines we
currently support: a single set with the source or a REG_EQUAL
note being a PLUS of an eliminable register and a constant. */
diff --git a/gcc/reorg.c b/gcc/reorg.c
index 8134938..bdfcf88 100644
--- a/gcc/reorg.c
+++ b/gcc/reorg.c
@@ -2708,14 +2708,13 @@ fill_slots_from_thread (rtx_jump_insn *insn, rtx condition,
&& GET_CODE (PATTERN (new_thread)) != ASM_INPUT
&& asm_noperands (PATTERN (new_thread)) < 0)
{
- rtx pat = PATTERN (new_thread);
rtx dest;
rtx src;
/* We know "new_thread" is an insn due to NONJUMP_INSN_P (new_thread)
above. */
trial = as_a <rtx_insn *> (new_thread);
- pat = PATTERN (trial);
+ rtx pat = PATTERN (trial);
if (!NONJUMP_INSN_P (trial)
|| GET_CODE (pat) != SET
diff --git a/gcc/rtl.def b/gcc/rtl.def
index f4c9d94..63b09b3 100644
--- a/gcc/rtl.def
+++ b/gcc/rtl.def
@@ -936,6 +936,12 @@ DEF_RTL_EXPR(DEFINE_SPLIT, "define_split", "EsES", RTX_EXTRA)
7: optionally, a vector of attributes for this insn. */
DEF_RTL_EXPR(DEFINE_INSN_AND_SPLIT, "define_insn_and_split", "sEsTsESV", RTX_EXTRA)
+/* A form of define_insn_and_split in which the split insn pattern (operand 5)
+ is determined automatically by replacing match_operands with match_dups
+ and match_operators with match_op_dups. The operands are the same as
+ define_insn_and_split but with operand 5 removed. */
+DEF_RTL_EXPR(DEFINE_INSN_AND_REWRITE, "define_insn_and_rewrite", "sEsTsSV", RTX_EXTRA)
+
/* Definition of an RTL peephole operation.
Follows the same arguments as define_split. */
DEF_RTL_EXPR(DEFINE_PEEPHOLE2, "define_peephole2", "EsES", RTX_EXTRA)
diff --git a/gcc/rtl.h b/gcc/rtl.h
index b4a906f..31fba82 100644
--- a/gcc/rtl.h
+++ b/gcc/rtl.h
@@ -1052,6 +1052,10 @@ is_a_helper <rtx_note *>::test (rtx_insn *insn)
#define CONSTANT_P(X) \
(GET_RTX_CLASS (GET_CODE (X)) == RTX_CONST_OBJ)
+/* 1 if X is a LABEL_REF. */
+#define LABEL_REF_P(X) \
+ (GET_CODE (X) == LABEL_REF)
+
/* 1 if X can be used to represent an object. */
#define OBJECT_P(X) \
((GET_RTX_CLASS (GET_CODE (X)) & RTX_OBJ_MASK) == RTX_OBJ_RESULT)
diff --git a/gcc/sched-rgn.c b/gcc/sched-rgn.c
index 83688b3..d400130 100644
--- a/gcc/sched-rgn.c
+++ b/gcc/sched-rgn.c
@@ -67,6 +67,13 @@ along with GCC; see the file COPYING3. If not see
#include "pretty-print.h"
#include "print-rtl.h"
+/* Disable warnings about quoting issues in the pp_xxx calls below
+ that (intentionally) don't follow GCC diagnostic conventions. */
+#if __GNUC__ >= 10
+# pragma GCC diagnostic push
+# pragma GCC diagnostic ignored "-Wformat-diag"
+#endif
+
#ifdef INSN_SCHEDULING
/* Some accessor macros for h_i_d members only used within this file. */
@@ -3947,3 +3954,7 @@ make_pass_sched_fusion (gcc::context *ctxt)
{
return new pass_sched_fusion (ctxt);
}
+
+#if __GNUC__ >= 10
+# pragma GCC diagnostic pop
+#endif
diff --git a/gcc/selftest-run-tests.c b/gcc/selftest-run-tests.c
index c2e0ee2..6ed7d82 100644
--- a/gcc/selftest-run-tests.c
+++ b/gcc/selftest-run-tests.c
@@ -90,6 +90,7 @@ selftest::run_tests ()
rely on. */
diagnostic_show_locus_c_tests ();
diagnostic_c_tests ();
+ diagnostic_format_json_cc_tests ();
edit_context_c_tests ();
fold_const_c_tests ();
spellcheck_c_tests ();
diff --git a/gcc/selftest.h b/gcc/selftest.h
index 3e00e75..d278f0a 100644
--- a/gcc/selftest.h
+++ b/gcc/selftest.h
@@ -218,6 +218,7 @@ extern void bitmap_c_tests ();
extern void cgraph_c_tests ();
extern void convert_c_tests ();
extern void diagnostic_c_tests ();
+extern void diagnostic_format_json_cc_tests ();
extern void diagnostic_show_locus_c_tests ();
extern void dumpfile_c_tests ();
extern void edit_context_c_tests ();
diff --git a/gcc/stmt.c b/gcc/stmt.c
index b69d7c4..8ed3bf5 100644
--- a/gcc/stmt.c
+++ b/gcc/stmt.c
@@ -521,7 +521,7 @@ check_unique_operand_names (tree outputs, tree inputs, tree labels)
return true;
failure:
- error ("duplicate asm operand name %qs", TREE_STRING_POINTER (i_name));
+ error ("duplicate %<asm%> operand name %qs", TREE_STRING_POINTER (i_name));
return false;
}
diff --git a/gcc/stor-layout.c b/gcc/stor-layout.c
index 5d6f2e0..583516c 100644
--- a/gcc/stor-layout.c
+++ b/gcc/stor-layout.c
@@ -2716,10 +2716,12 @@ initialize_sizetypes (void)
for (i = 0; i < NUM_INT_N_ENTS; i++)
if (int_n_enabled_p[i])
{
- char name[50];
+ char name[50], altname[50];
sprintf (name, "__int%d unsigned", int_n_data[i].bitsize);
+ sprintf (altname, "__int%d__ unsigned", int_n_data[i].bitsize);
- if (strcmp (name, SIZETYPE) == 0)
+ if (strcmp (name, SIZETYPE) == 0
+ || strcmp (altname, SIZETYPE) == 0)
{
precision = int_n_data[i].bitsize;
}
diff --git a/gcc/symbol-summary.h b/gcc/symbol-summary.h
index 0219f3a..e90d448 100644
--- a/gcc/symbol-summary.h
+++ b/gcc/symbol-summary.h
@@ -362,7 +362,7 @@ public:
{
for (unsigned i = 0; i < m_vector->length (); i++)
if ((*m_vector[i]) != NULL)
- f ((*m_vector)[i]);
+ f ((*m_vector)[i], a);
}
/* Getter for summary callgraph node pointer. If a summary for a node
@@ -846,7 +846,7 @@ public:
{
for (unsigned i = 0; i < m_vector->length (); i++)
if ((*m_vector[i]) != NULL)
- f ((*m_vector)[i]);
+ f ((*m_vector)[i], a);
}
/* Getter for summary callgraph edge pointer.
@@ -966,21 +966,21 @@ fast_call_summary<T *, V>::is_ggc ()
template <typename T>
void
-gt_ggc_mx (fast_call_summary<T *, va_heap>* const &summary)
+gt_ggc_mx (fast_call_summary<T *, va_heap>* const &summary ATTRIBUTE_UNUSED)
{
}
template <typename T>
void
-gt_pch_nx (fast_call_summary<T *, va_heap>* const &summary)
+gt_pch_nx (fast_call_summary<T *, va_heap>* const &summary ATTRIBUTE_UNUSED)
{
}
template <typename T>
void
-gt_pch_nx (fast_call_summary<T *, va_heap>* const& summary,
- gt_pointer_operator op,
- void *cookie)
+gt_pch_nx (fast_call_summary<T *, va_heap>* const& summary ATTRIBUTE_UNUSED,
+ gt_pointer_operator op ATTRIBUTE_UNUSED,
+ void *cookie ATTRIBUTE_UNUSED)
{
}
diff --git a/gcc/symtab.c b/gcc/symtab.c
index 4bf37a1..b1589ea 100644
--- a/gcc/symtab.c
+++ b/gcc/symtab.c
@@ -1002,6 +1002,15 @@ symtab_node::debug (void)
/* Verify common part of symtab nodes. */
+#if __GNUC__ >= 10
+/* Disable warnings about missing quoting in GCC diagnostics for
+ the verification errors. Their format strings don't follow GCC
+ diagnostic conventions and the calls are ultimately followed by
+ one to internal_error. */
+# pragma GCC diagnostic push
+# pragma GCC diagnostic ignored "-Wformat-diag"
+#endif
+
DEBUG_FUNCTION bool
symtab_node::verify_base (void)
{
@@ -1288,6 +1297,10 @@ symtab_node::verify_symtab_nodes (void)
}
}
+#if __GNUC__ >= 10
+# pragma GCC diagnostic pop
+#endif
+
/* Make DECL local. FIXME: We shouldn't need to mess with rtl this early,
but other code such as notice_global_symbol generates rtl. */
@@ -1570,7 +1583,7 @@ symtab_node::set_section (symtab_node *n, void *s)
void
symtab_node::set_section (const char *section)
{
- gcc_assert (!this->alias);
+ gcc_assert (!this->alias || !this->analyzed);
call_for_symbol_and_aliases
(symtab_node::set_section, const_cast<char *>(section), true);
}
diff --git a/gcc/target.def b/gcc/target.def
index 66cee07..4165405 100644
--- a/gcc/target.def
+++ b/gcc/target.def
@@ -1899,12 +1899,14 @@ DEFHOOK
the only one that is worth considering, this hook should add all suitable\n\
vector sizes to @var{sizes}, in order of decreasing preference. The first\n\
one should be the size of @code{TARGET_VECTORIZE_PREFERRED_SIMD_MODE}.\n\
+If @var{all} is true, add suitable vector sizes even when they are generally\n\
+not expected to be worthwhile.\n\
\n\
The hook does not need to do anything if the vector returned by\n\
@code{TARGET_VECTORIZE_PREFERRED_SIMD_MODE} is the only one relevant\n\
for autovectorization. The default implementation does nothing.",
void,
- (vector_sizes *sizes),
+ (vector_sizes *sizes, bool all),
default_autovectorize_vector_sizes)
/* Function to get a target mode for a vector mask. */
@@ -2547,6 +2549,13 @@ DEFHOOK
bool, (enum function_class fn_class),
default_libc_has_function)
+DEFHOOK
+(libc_has_fast_function,
+ "This hook determines whether a function from a class of functions\n\
+@var{fn_class} has a fast implementation.",
+ bool, (int fcode),
+ default_libc_has_fast_function)
+
/* True if new jumps cannot be created, to replace existing ones or
not, at the current point in the compilation. */
DEFHOOK
@@ -3522,7 +3531,7 @@ two areas of memory, or to set, clear or store to memory, for example\n\
when copying a @code{struct}. The @code{by_pieces} infrastructure\n\
implements such memory operations as a sequence of load, store or move\n\
insns. Alternate strategies are to expand the\n\
-@code{movmem} or @code{setmem} optabs, to emit a library call, or to emit\n\
+@code{cpymem} or @code{setmem} optabs, to emit a library call, or to emit\n\
unit-by-unit, loop-based operations.\n\
\n\
This target hook should return true if, for a memory operation with a\n\
@@ -3541,7 +3550,7 @@ optimized for speed rather than size.\n\
\n\
Returning true for higher values of @var{size} can improve code generation\n\
for speed if the target does not provide an implementation of the\n\
-@code{movmem} or @code{setmem} standard names, if the @code{movmem} or\n\
+@code{cpymem} or @code{setmem} standard names, if the @code{cpymem} or\n\
@code{setmem} implementation would be more expensive than a sequence of\n\
insns, or if the overhead of a library call would dominate that of\n\
the body of the memory operation.\n\
@@ -4227,6 +4236,15 @@ DEFHOOK
rtx, (machine_mode mode, rtx result, rtx val, rtx failval),
default_speculation_safe_value)
+DEFHOOK
+(predict_doloop_p,
+ "Return true if we can predict it is possible to use a low-overhead loop\n\
+for a particular loop. The parameter @var{loop} is a pointer to the loop.\n\
+This target hook is required only when the target supports low-overhead\n\
+loops, and will help ivopts to make some decisions.\n\
+The default version of this hook returns false.",
+ bool, (struct loop *loop),
+ default_predict_doloop_p)
DEFHOOK
(can_use_doloop_p,
diff --git a/gcc/targhooks.c b/gcc/targhooks.c
index 02b9dc5..676885b 100644
--- a/gcc/targhooks.c
+++ b/gcc/targhooks.c
@@ -643,6 +643,19 @@ default_has_ifunc_p (void)
return HAVE_GNU_INDIRECT_FUNCTION;
}
+/* Return true if we predict the loop LOOP will be transformed to a
+ low-overhead loop, otherwise return false.
+
+ By default, false is returned, as this hook's applicability should be
+ verified for each target. Target maintainers should re-define the hook
+ if the target can take advantage of it. */
+
+bool
+default_predict_doloop_p (struct loop *loop ATTRIBUTE_UNUSED)
+{
+ return false;
+}
+
/* NULL if INSN insn is valid within a low-overhead loop, otherwise returns
an error message.
@@ -1316,7 +1329,7 @@ default_split_reduction (machine_mode mode)
is tried. */
void
-default_autovectorize_vector_sizes (vector_sizes *)
+default_autovectorize_vector_sizes (vector_sizes *, bool)
{
}
@@ -1600,7 +1613,7 @@ default_target_option_pragma_parse (tree ARG_UNUSED (args),
do not have the "target" pragma. */
if (args)
warning (OPT_Wpragmas,
- "#pragma GCC target is not supported for this machine");
+ "%<#pragma GCC target%> is not supported for this machine");
return false;
}
@@ -1651,6 +1664,14 @@ default_libc_has_function (enum function_class fn_class)
return false;
}
+/* By default assume that libc has not a fast implementation. */
+
+bool
+default_libc_has_fast_function (int fcode ATTRIBUTE_UNUSED)
+{
+ return false;
+}
+
bool
gnu_libc_has_function (enum function_class fn_class ATTRIBUTE_UNUSED)
{
@@ -1725,9 +1746,9 @@ get_move_ratio (bool speed_p ATTRIBUTE_UNUSED)
#ifdef MOVE_RATIO
move_ratio = (unsigned int) MOVE_RATIO (speed_p);
#else
-#if defined (HAVE_movmemqi) || defined (HAVE_movmemhi) || defined (HAVE_movmemsi) || defined (HAVE_movmemdi) || defined (HAVE_movmemti)
+#if defined (HAVE_cpymemqi) || defined (HAVE_cpymemhi) || defined (HAVE_cpymemsi) || defined (HAVE_cpymemdi) || defined (HAVE_cpymemti)
move_ratio = 2;
-#else /* No movmem patterns, pick a default. */
+#else /* No cpymem patterns, pick a default. */
move_ratio = ((speed_p) ? 15 : 3);
#endif
#endif
@@ -1735,7 +1756,7 @@ get_move_ratio (bool speed_p ATTRIBUTE_UNUSED)
}
/* Return TRUE if the move_by_pieces/set_by_pieces infrastructure should be
- used; return FALSE if the movmem/setmem optab should be expanded, or
+ used; return FALSE if the cpymem/setmem optab should be expanded, or
a call to memcpy emitted. */
bool
diff --git a/gcc/targhooks.h b/gcc/targhooks.h
index 5943627..50b03ce 100644
--- a/gcc/targhooks.h
+++ b/gcc/targhooks.h
@@ -85,6 +85,7 @@ extern bool default_fixed_point_supported_p (void);
extern bool default_has_ifunc_p (void);
+extern bool default_predict_doloop_p (struct loop *);
extern const char * default_invalid_within_doloop (const rtx_insn *);
extern tree default_builtin_vectorized_function (unsigned int, tree, tree);
@@ -110,7 +111,7 @@ default_builtin_support_vector_misalignment (machine_mode mode,
int, bool);
extern machine_mode default_preferred_simd_mode (scalar_mode mode);
extern machine_mode default_split_reduction (machine_mode);
-extern void default_autovectorize_vector_sizes (vector_sizes *);
+extern void default_autovectorize_vector_sizes (vector_sizes *, bool);
extern opt_machine_mode default_get_mask_mode (poly_uint64, poly_uint64);
extern bool default_empty_mask_is_expensive (unsigned);
extern void *default_init_cost (struct loop *);
@@ -205,6 +206,7 @@ extern unsigned int default_case_values_threshold (void);
extern bool default_have_conditional_execution (void);
extern bool default_libc_has_function (enum function_class);
+extern bool default_libc_has_fast_function (int fcode);
extern bool no_c99_libc_has_function (enum function_class);
extern bool gnu_libc_has_function (enum function_class);
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index f75dbe7..1695bab 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,3234 @@
+2019-07-03 Wilco Dijkstra <wdijkstr@arm.com>
+
+ * gcc.dg/store_merging_27.c: Fix test for Arm.
+ * gcc.dg/store_merging_28.c: Likewise.
+ * gcc.dg/store_merging_29.c: Likewise.
+ * gcc.dg/tree-ssa/dump-6.c: Likewise.
+
+2019-07-03 Richard Biener <rguenther@suse.de>
+
+ PR middle-end/91069
+ * gcc.dg/pr91069.c: New testcase.
+
+2019-07-03 Martin Liska <mliska@suse.cz>
+
+ * gcc.dg/tree-prof/val-prof-2.c: Update scanned pattern
+ as we do now better.
+
+2019-07-03 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gnat.dg/specs/debug1.ads: New test.
+
+2019-07-03 Martin Liska <mliska@suse.cz>
+
+ PR tree-optimization/90892
+ * gcc.dg/pr90892.c: New test.
+
+2019-07-03 Martin Liska <mliska@suse.cz>
+
+ PR middle-end/90899
+ * gcc.target/i386/pr90899.c: New test.
+
+2019-07-03 Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/91033
+ * gcc.target/i386/pr91033.c: New test.
+
+2019-07-03 Bob Duff <duff@adacore.com>
+
+ * gnat.dg/task2.adb, gnat.dg/task2_pkg.adb,
+ gnat.dg/task2_pkg.ads: New testcase.
+
+2019-07-03 Ed Schonberg <schonberg@adacore.com>
+
+ * gnat.dg/inline16.adb, gnat.dg/inline16_gen.adb,
+ gnat.dg/inline16_gen.ads, gnat.dg/inline16_types.ads: New
+ testcase.
+
+2019-07-03 Justin Squirek <squirek@adacore.com>
+
+ * gnat.dg/renaming13.adb, gnat.dg/renaming14.adb: New testcases.
+
+2019-07-03 Hristian Kirtchev <kirtchev@adacore.com>
+
+ * gnat.dg/inline15.adb, gnat.dg/inline15_gen.adb,
+ gnat.dg/inline15_gen.ads, gnat.dg/inline15_types.ads: New
+ testcase.
+
+2019-07-03 Bob Duff <duff@adacore.com>
+
+ * gnat.dg/warn20.adb, gnat.dg/warn20_pkg.adb,
+ gnat.dg/warn20_pkg.ads: New testcase.
+
+2019-07-03 Ed Schonberg <schonberg@adacore.com>
+
+ * gnat.dg/predicate6.adb, gnat.dg/predicate6.ads: New testcase.
+ * gnat.dg/static_pred1.adb: Remove expected error.
+
+2019-07-03 Ed Schonberg <schonberg@adacore.com>
+
+ * gnat.dg/predicate5.adb, gnat.dg/predicate5.ads: New testcase.
+
+2019-07-03 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gnat.dg/alignment14.adb: New testcase.
+
+2019-07-03 Ed Schonberg <schonberg@adacore.com>
+
+ * gnat.dg/predicate4.adb, gnat.dg/predicate4_pkg.ads: New
+ testcase.
+
+2019-07-03 Jakub Jelinek <jakub@redhat.com>
+
+ * c-c++-common/gomp/scan-3.c (f1): Don't expect a sorry message.
+ * c-c++-common/gomp/scan-5.c (foo): Likewise.
+
+ * c-c++-common/gomp/scan-5.c: New test.
+
+ * c-c++-common/gomp/lastprivate-conditional-5.c: New test.
+
+2019-07-02 Jeff Law <law@redhat.com>
+
+ PR tree-optimization/90883
+ * g++.dg/tree-ssa/pr90883.c: Add -Os. Check dse2 for the
+ deleted store on some targets.
+
+2019-07-02 qing zhao <qing.zhao@oracle.com>
+
+ PR preprocessor/90581
+ * c-c++-common/cpp/fmax-include-depth-1a.h: New test.
+ * c-c++-common/cpp/fmax-include-depth-1b.h: New test.
+ * c-c++-common/cpp/fmax-include-depth.c: New test.
+
+2019-07-02 Jan Hubicka <jh@suse.cz>
+
+ * gcc.dg/tree-ssa/alias-access-path-7.c: New testcase.
+
+2019-07-02 Jan Hubicka <jh@suse.cz>
+
+ * g++.dg/lto/pr90990_0.C: New testcase.
+
+2019-07-02 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/58483
+ * gcc.dg/tree-ssa/ssa-dom-cse-8.c: New testcase.
+
+2019-07-01 Andreas Krebbel <krebbel@linux.ibm.com>
+
+ * gcc.target/s390/vector/vec-shift-2.c: New test.
+
+2019-07-01 Ed Schonberg <schonberg@adacore.com>
+
+ * gnat.dg/generic_inst3.adb,
+ gnat.dg/generic_inst3_kafka_lib-topic.ads,
+ gnat.dg/generic_inst3_kafka_lib.ads,
+ gnat.dg/generic_inst3_markets.ads,
+ gnat.dg/generic_inst3_traits-encodables.ads,
+ gnat.dg/generic_inst3_traits.ads: New testcase.
+
+2019-07-01 Ed Schonberg <schonberg@adacore.com>
+
+ * gnat.dg/enum_rep.adb, gnat.dg/enum_rep.ads: New testcase.
+
+2019-07-01 Ed Schonberg <schonberg@adacore.com>
+
+ * gnat.dg/derived_type6.adb, gnat.dg/derived_type6.ads: New
+ testcase.
+
+2019-07-01 Ed Schonberg <schonberg@adacore.com>
+
+ * gnat.dg/weak3.adb, gnat.dg/weak3.ads: New testcase.
+
+2019-07-01 Ed Schonberg <schonberg@adacore.com>
+
+ * gnat.dg/prot7.adb, gnat.dg/prot7.ads: New testcase.
+
+2019-07-01 Richard Biener <rguenther@suse.de>
+
+ * gcc.dg/gimplefe-42.c: New testcase.
+
+2019-07-01 Hristian Kirtchev <kirtchev@adacore.com>
+
+ * gnat.dg/sets1.adb: Update.
+
+2019-07-01 Hristian Kirtchev <kirtchev@adacore.com>
+
+ * gnat.dg/linkedlist.adb: Update.
+
+2019-07-01 Hristian Kirtchev <kirtchev@adacore.com>
+
+ * gnat.dg/dynhash.adb, gnat.dg/dynhash1.adb: Update.
+
+2019-07-01 Hristian Kirtchev <kirtchev@adacore.com>
+
+ * gnat.dg/freezing1.adb, gnat.dg/freezing1.ads,
+ gnat.dg/freezing1_pack.adb, gnat.dg/freezing1_pack.ads: New
+ testcase.
+
+2019-07-01 Jan Hubicka <hubicka@ucw.cz>
+
+ PR lto/91028
+ PR lto/90720
+ * g++.dg/lto/alias-1_0.C: Add loop to make inlining happen with
+ -fno-use-linker-plugin
+ * g++.dg/lto/alias-2_0.C: Likewise.
+
+2019-07-01 Dominique d'Humieres <dominiq@gcc.gnu.org>
+
+ * g++.dg/cpp0x/gen-attrs-67.C: Add error for darwin.
+
+2019-07-01 Richard Biener <rguenther@suse.de>
+
+ * gcc.dg/tree-ssa/pr77445-2.c: Adjust.
+
+2019-07-01 Hongtao Liu <hongtao.liu@intel.com>
+
+ * lib/target-supports.exp
+ (check_effective_target_avx512vp2intersect): New proc.
+ * gcc.target/i386/avx512vp2intersect-2intersect-1b.c: Add
+ dg-require-effective-target avx512vp2intersect.
+ * gcc.target/i386/avx512vp2intersect-2intersectvl-1b.c: Ditto.
+
+2019-06-29 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gnat.dg/specs/array5.ads: New test.
+ * gnat.dg/specs/array5_pkg1.ads: New helper.
+ * gnat.dg/specs/array5_pkg2.ads: Likewise.
+ * gnat.dg/specs/array5_pkg2-g.ads: Likewise.
+
+2019-06-29 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gnat.dg/specs/unchecked_convert1.ads: New test.
+ * gnat.dg/specs/unchecked_convert2.ads: Likewise.
+
+2019-06-29 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gnat.dg/specs/size_clause3.ads: Adjust error message.
+
+2019-06-29 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gnat.dg/specs/atomic2.ads: Adjust error message.
+ * gnat.dg/specs/clause_on_volatile.ads: Likewise.
+ * gnat.dg/specs/size_clause3.ads: Likewise.
+
+2019-06-29 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gnat.dg/array35.adb: New test.
+ * gnat.dg/array36.adb: Likewise.
+
+2019-06-28 Jan Beulich <jbeulich@suse.com>
+
+ * gcc.target/i386/gfni-5.c: New.
+
+2019-06-28 Jan Beulich <jbeulich@suse.com>
+
+ * gcc.target/i386/cvtpd2pi: New.
+
+2019-06-27 Jakub Jelinek <jakub@redhat.com>
+
+ PR c++/91024
+ * g++.dg/warn/Wimplicit-fallthrough-4.C: New test.
+
+ PR tree-optimization/91010
+ * g++.dg/vect/simd-10.cc: New test.
+
+2019-06-27 Steven G. Kargl <kargl@gcc.gnu.org>
+
+ PR fortran/90987
+ * match.c (gfc_match_common): Adjust parsing of fixed and free form
+ source code containing, e.g., COMMONI.
+
+2019-06-27 Jan Hubicka <jh@suse.cz>
+
+ * g++.dg/lto/alias-2_0.C: New testcase.
+ * g++.dg/lto/alias-2_1.C: New testcase.
+
+2019-06-27 Jakub Jelinek <jakub@redhat.com>
+
+ PR target/90991
+ * gcc.target/i386/avx2-pr90991-1.c: New test.
+ * gcc.target/i386/avx512dq-pr90991-2.c: New test.
+
+2019-06-27 Jan Beulich <jbeulich@suse.com>
+
+ * gcc.target/i386/gfni-4.c: Pass -msse2.
+
+2019-06-27 Richard Biener <rguenther@suse.de>
+
+ * gcc.dg/tree-ssa/ssa-fre-69.c: New testcase.
+
+2019-06-27 Jun Ma <JunMa@linux.alibaba.com>
+
+ PR tree-optimization/89772
+ * gcc.dg/builtin-memchr-4.c: New test.
+
+2019-06-27 Martin Liska <mliska@suse.cz>
+
+ PR tree-optimization/91014
+ * gcc.target/s390/pr91014.c: New test.
+
+2019-06-27 Richard Biener <rguenther@suse.de>
+
+ PR testsuite/91004
+ * g++.dg/torture/pr34850.C: Fix overly reduced testcase.
+
+2019-06-27 Kewen Lin <linkw@gcc.gnu.org>
+
+ PR target/62147
+ * gcc.target/powerpc/pr62147.c: New test.
+
+2019-06-26 Jeff Law <law@redhat.com>
+
+ PR tree-optimization/90883
+ * g++.dg/tree-ssa/pr90883.C: New test.
+ * gcc.dg/tree-ssa/ssa-dse-36.c: New test.
+
+2019-06-26 Uroš Bizjak <ubizjak@gmail.com>
+
+ PR target/89021
+ * lib/target-supports.exp (available_vector_sizes)
+ <[istarget i?86-*-*] || [istarget x86_64-*-*]>: Add
+ 64-bit vectors for !ia32.
+
+2019-06-26 Jeff Law <law@redhat.com>
+
+ * gcc.c-torture/execute/builtins/builtins.exp: Add -fno-tree-dse
+ as DSE compromises several of these tests.
+ * gcc.dg/builtin-stringop-chk-1.c: Similarly.
+ * gcc.dg/memcpy-2.c: Similarly.
+ * gcc.dg/pr40340-1.c: Similarly.
+ * gcc.dg/pr40340-2.c: Similarly.
+ * gcc.dg/pr40340-5.c: Similarly.
+
+2019-06-26 Steven G. Kargl <kargl@gcc.gnu.org>
+
+ PR Fortran/90988
+ ChangeLog forgotten with revision 272667
+ * gfortran.dg/pr90988_1.f90: New test.
+ * gfortran.dg/pr90988_2.f90: Ditto.
+ * gfortran.dg/pr90988_3.f90: Ditto.
+
+2019-06-26 Nathan Sidwell <nathan@acm.org>
+
+ * c-c++-common/pr90927.c: New.
+
+2019-06-26 Richard Biener <rguenther@suse.de>
+
+ PR ipa/90982
+ * g++.dg/torture/pr90982.C: New testcase.
+
+2019-06-26 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/67184
+ PR c++/69445
+ * g++.dg/other/final3.C: New.
+ * g++.dg/other/final5.C: Likewise.
+
+2019-06-26 Jakub Jelinek <jakub@redhat.com>
+
+ PR target/90991
+ * gcc.target/i386/avx512dq-pr90991-1.c: New test.
+
+2019-06-26 Li Jia He <helijia@linux.ibm.com>
+
+ * gcc.target/powerpc/maddld-1.c: New testcase.
+
+2019-06-06 Hongtao Liu <hongtao.liu@intel.com>
+ Olga Makhotina <olga.makhotina@intel.com>
+
+ * gcc.target/i386/avx512-check.h: Handle bit_AVX512VP2INTERSECT.
+ * gcc.target/i386/avx512vp2intersect-2intersect-1a.c: New test.
+ * gcc.target/i386/avx512vp2intersect-2intersect-1b.c: Likewise.
+ * gcc.target/i386/avx512vp2intersect-2intersectvl-1a.c: Likewise.
+ * gcc.target/i386/avx512vp2intersect-2intersectvl-1b.c: Likewise.
+ * gcc.target/i386/sse-12.c: Add -mavx512vp2intersect.
+ * gcc.target/i386/sse-13.c: Likewsie.
+ * gcc.target/i386/sse-14.c: Likewise.
+ * gcc.target/i386/sse-22.c: Likewise.
+ * gcc.target/i386/sse-23.c: Likewise.
+ * g++.dg/other/i386-2.C: Likewise.
+ * g++.dg/other/i386-3.C: Likewise.
+
+2019-06-25 Jakub Jelinek <jakub@redhat.com>
+
+ PR c++/90969
+ * g++.dg/ext/vector38.C: New test.
+
+2019-06-25 Martin Jambor <mjambor@suse.cz>
+
+ PR ipa/90939
+ * g++.dg/lto/pr90939_[01].C: New test.
+
+2019-06-25 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/90930
+ * gcc.dg/tree-ssa/reassoc-24.c: Adjust.
+ * gcc.dg/tree-ssa/reassoc-25.c: Likewise.
+
+2019-06-25 Claudiu Zissulescu <claziss@synopsys.com>
+
+ * gcc.target/arc/pr89838.c: New file.
+
+2019-06-25 Jozef Lawrynowicz <jozef.l@mittosystems.com>
+
+ * gcc.target/msp430/mlarge-pedwarns.c: New test.
+
+2019-06-25 Jakub Jelinek <jakub@redhat.com>
+
+ PR sanitizer/90954
+ * c-c++-common/gomp/pr90954.c: New test.
+
+2019-06-24 Iain Sandoe <iain@sandoe.co.uk>
+
+ * gcc.target/powerpc/safe-indirect-jump-1.c: Skip for Darwin.
+ * gcc.target/powerpc/safe-indirect-jump-7.c: Likewise.
+
+2019-06-24 Iain Sandoe <iain@sandoe.co.uk>
+
+ * gcc.target/powerpc/spec-barr-1.c: Adjust scan assembler regex
+ to recognise Darwin's register names.
+
+2019-06-24 Iain Sandoe <iain@sandoe.co.uk>
+
+ * gcc.dg/cpp/isysroot-1.c: Use <example.h> as the test header.
+ * gcc.dg/cpp/usr/include/stdio.h: Rename...
+ * gcc.dg/cpp/usr/include/example.h: ... to this.
+
+2019-06-24 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/90972
+ * gcc.dg/torture/pr90972.c: New testcase.
+
+2019-06-24 Martin Sebor <msebor@redhat.com>
+
+ * gcc.dg/Wfloat-equal-1.c: Adjust text of expected diagnostic.
+ * gcc.dg/misc-column.c: Ditto.
+
+2019-06-23 Ian Lance Taylor <iant@golang.org>
+
+ * go.test/test/blank1.go: Update for diagnostic message changes.
+
+2019-06-23 Iain Sandoe <iain@sandoe.co.uk>
+
+ * gcc.target/powerpc/builtins-2.c: Require VSX hardware support.
+
+2019-06-23 Iain Sandoe <iain@sandoe.co.uk>
+
+ * gcc.target/powerpc/pr80125.c (foo): Use an unsigned char
+ vector explicitly for the vec_perm.
+
+2019-06-23 Iain Sandoe <iain@sandoe.co.uk>
+
+ * gcc.target/powerpc/builtins-1.c: Account for Darwin's use of
+ __USER_LABEL_PREFIX__.
+
+2019-06-23 Iain Sandoe <iain@sandoe.co.uk>
+
+ * gcc.target/powerpc/pr71785.c: For Darwin, make test non-PIC,
+ expect the out-of-line GPR restore, and test specifically for
+ absence of branches to local labels.
+
+2019-06-22 Jerry DeLisle <jvdelisle@gcc.gnu.org>
+
+ PR fortran/89782
+ * gfortran.dg/io_constraints_14.f90: New test.
+
+2019-06-22 Iain Sandoe <iain@sandoe.co.uk>
+
+ * gcc.target/powerpc/pr64205.c: Require effective target dfp.
+ * gcc.target/powerpc/pr79909.c: Likewise.
+
+2019-06-22 Iain Sandoe <iain@sandoe.co.uk>
+
+ * gcc.target/powerpc/darwin-bool-1.c: Suppress the pedantic
+ warning about _Bool.
+
+2019-06-22 Marek Polacek <polacek@redhat.com>
+
+ PR c++/65707
+ PR c++/89480
+ PR c++/58836
+ * g++.dg/cpp0x/nondeduced5.C: New test.
+ * g++.dg/cpp0x/nondeduced6.C: New test.
+ * g++.dg/cpp0x/nondeduced7.C: New test.
+
+ PR c++/66256
+ * g++.dg/cpp0x/noexcept54.C: New test.
+
+2019-06-22 Jan Hubicka <jh@suse.cz>
+
+ * gcc.dg/tree-ssa/alias-access-path-6.c: New testcase.
+
+2019-06-22 Marek Polacek <polacek@redhat.com>
+
+ PR c++/86476 - noexcept-specifier is a complete-class context.
+ PR c++/52869
+ * g++.dg/cpp0x/noexcept45.C: New test.
+ * g++.dg/cpp0x/noexcept46.C: New test.
+ * g++.dg/cpp0x/noexcept47.C: New test.
+ * g++.dg/cpp0x/noexcept48.C: New test.
+ * g++.dg/cpp0x/noexcept49.C: New test.
+ * g++.dg/cpp0x/noexcept50.C: New test.
+ * g++.dg/cpp0x/noexcept51.C: New test.
+ * g++.dg/cpp0x/noexcept52.C: New test.
+ * g++.dg/cpp0x/noexcept53.C: New test.
+ * g++.dg/eh/shadow1.C: Adjust dg-error.
+
+ PR c++/90881 - bogus -Wunused-value in unevaluated context.
+ * g++.dg/cpp0x/Wunused-value1.C: New test.
+
+2019-06-22 Paolo Carlini <paolo.carlini@oracle.com>
+
+ * g++.dg/diagnostic/auto-storage-1.C: New.
+ * g++.dg/diagnostic/no-type-1.C: Likewise.
+ * g++.dg/diagnostic/no-type-2.C: Likewise.
+ * g++.dg/diagnostic/top-level-auto-1.C: Likewise.
+ * g++.dg/cpp0x/auto9.C: Test some locations too.
+ * g++.dg/cpp1z/register1.C: Likewise.
+ * g++.dg/cpp1z/register2.C: Likewise.
+ * g++.dg/cpp1z/register3.C: Likewise.
+ * g++.dg/other/error34.C: Likewise.
+
+2019-06-21 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/90909
+ * g++.dg/other/final7.C: New.
+
+2019-06-21 Jakub Jelinek <jakub@redhat.com>
+
+ * g++.dg/vect/simd-2.cc: Don't xfail, instead expect vectorization on
+ x86.
+ * g++.dg/vect/simd-5.cc: Likewise.
+
+2019-06-21 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/90909
+ Revert:
+ 2019-05-21 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/67184
+ PR c++/69445
+ * g++.dg/other/final3.C: New.
+ * g++.dg/other/final4.C: Likewise.
+ * g++.dg/other/final5.C: Likewise.
+
+ * g++.dg/other/final6.C: New.
+
+2019-06-21 Marek Polacek <polacek@redhat.com>
+
+ PR c++/61490 - qualified-id in friend function definition.
+ * g++.dg/diagnostic/friend2.C: New test.
+ * g++.dg/diagnostic/friend3.C: New test.
+
+ PR c++/60223 - ICE with T{} in non-deduced context.
+ * g++.dg/cpp0x/nondeduced1.C: New test.
+ * g++.dg/cpp0x/nondeduced2.C: New test.
+ * g++.dg/cpp0x/nondeduced3.C: New test.
+ * g++.dg/cpp0x/nondeduced4.C: New test.
+
+ PR c++/64235 - missing syntax error with invalid alignas.
+ * g++.dg/parse/alignas1.C: New test.
+
+2019-06-21 Steven G. Kargl <kargl@gcc.gnu.org>
+
+ PR fortran/67884
+ * gfortran.dg/dummy_procedure_8.f90: Remove a test that is ...
+ * gfortran.dg/pr67884.f90: ... covered here. New test.
+
+2019-06-21 Marek Polacek <polacek@redhat.com>
+
+ PR c++/90490 - fix decltype issues in noexcept-specifier.
+ * g++.dg/cpp0x/noexcept43.C: New test.
+ * g++.dg/cpp0x/noexcept44.C: New test.
+
+2019-06-21 Matthew Beliveau <mbelivea@redhat.com>
+
+ PR c++/90875 - added -Wswitch-outside-range option
+ * c-c++-common/Wswitch-outside-range-1.c: New test.
+ * c-c++-common/Wswitch-outside-range-2.c: New test.
+ * c-c++-common/Wswitch-outside-range-3.c: New test.
+ * c-c++-common/Wswitch-outside-range-4.c: New test.
+
+2019-06-21 Steven G. Kargl <kargl@gcc.gnu.org>
+
+ PR fortran/51991
+ gfortran.dg/pr51991.f90
+
+2019-06-21 Jeff Law <law@redhat.com>
+
+ PR tree-optimization/90949
+ * gcc.c-torture/execute/pr90949.c: New test.
+
+2019-06-21 Marek Polacek <polacek@redhat.com>
+
+ PR c++/90953 - ICE with -Wmissing-format-attribute.
+ * g++.dg/warn/miss-format-7.C: New test.
+
+2019-06-21 Richard Biener <rguenther@suse.de>
+
+ PR debug/90914
+ * g++.dg/debug/pr90914.C: New testcase.
+
+2019-06-21 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/90913
+ * gfortran.dg/vect/pr90913.f90: New testcase.
+
+2019-06-21 Jakub Jelinek <jakub@redhat.com>
+
+ * gcc.dg/vect/vect-simd-12.c: New test.
+ * gcc.dg/vect/vect-simd-13.c: New test.
+ * gcc.dg/vect/vect-simd-14.c: New test.
+ * gcc.dg/vect/vect-simd-15.c: New test.
+ * gcc.target/i386/sse2-vect-simd-12.c: New test.
+ * gcc.target/i386/sse2-vect-simd-13.c: New test.
+ * gcc.target/i386/sse2-vect-simd-14.c: New test.
+ * gcc.target/i386/sse2-vect-simd-15.c: New test.
+ * gcc.target/i386/avx2-vect-simd-12.c: New test.
+ * gcc.target/i386/avx2-vect-simd-13.c: New test.
+ * gcc.target/i386/avx2-vect-simd-14.c: New test.
+ * gcc.target/i386/avx2-vect-simd-15.c: New test.
+ * gcc.target/i386/avx512f-vect-simd-12.c: New test.
+ * gcc.target/i386/avx512f-vect-simd-13.c: New test.
+ * gcc.target/i386/avx512f-vect-simd-14.c: New test.
+ * gcc.target/i386/avx512bw-vect-simd-15.c: New test.
+ * g++.dg/vect/simd-6.cc: New test.
+ * g++.dg/vect/simd-7.cc: New test.
+ * g++.dg/vect/simd-8.cc: New test.
+ * g++.dg/vect/simd-9.cc: New test.
+ * c-c++-common/gomp/scan-2.c: Don't expect any diagnostics.
+
+ PR c++/90950
+ * g++.dg/gomp/lastprivate-1.C: New test.
+
+ * gcc.dg/vect/vect-simd-11.c: New test.
+ * gcc.target/i386/sse2-vect-simd-11.c: New test.
+ * gcc.target/i386/avx2-vect-simd-11.c: New test.
+ * gcc.target/i386/avx512bw-vect-simd-11.c: New test.
+
+2019-06-20 Marek Polacek <polacek@redhat.com>
+
+ PR c++/79781
+ * g++.dg/ext/goto1.C: New test.
+
+2019-06-20 Steven G. Kargl <kargl@gcc.gnu.org>
+
+ PR fortran/77632
+ * gfortran.dg/pr77632_1.f90: New test.
+
+2019-06-20 Marek Polacek <polacek@redhat.com>
+
+ PR c++/68265
+ * g++.dg/parse/error62.C: New test.
+
+2019-06-20 Steven G. Kargl <kargl@gcc.gnu.org>
+
+ PR fortran/86587
+ * gfortran.dg/pr86587.f90: New test.
+
+2019-06-20 Iain Sandoe <iain@sandoe.co.uk>
+
+ * obj-c++.dg/stubify-1.mm: Adjust options and scan-asm checks.
+ * obj-c++.dg/stubify-2.mm: Likewise.
+ * objc.dg/stubify-1.m: Likewise.
+ * objc.dg/stubify-2.m: Likewise.
+
+2019-06-20 Marek Polacek <polacek@redhat.com>
+
+ PR c++/87512
+ * g++.dg/cpp1z/inline-var7.C: New test.
+
+2019-06-20 H.J. Lu <hongjiu.lu@intel.com>
+
+ PR target/54855
+ * gcc.target/i386/pr54855-1.c: New test.
+ * gcc.target/i386/pr54855-2.c: Likewise.
+ * gcc.target/i386/pr54855-3.c: Likewise.
+ * gcc.target/i386/pr54855-4.c: Likewise.
+ * gcc.target/i386/pr54855-5.c: Likewise.
+ * gcc.target/i386/pr54855-6.c: Likewise.
+ * gcc.target/i386/pr54855-7.c: Likewise.
+ * gcc.target/i386/pr54855-8.c: Likewise.
+ * gcc.target/i386/pr54855-9.c: Likewise.
+ * gcc.target/i386/pr54855-10.c: Likewise.
+
+2019-06-20 Jan Hubicka <jh@suse.cz>
+
+ * gcc.c-torture/execute/alias-access-path-1.c: New testcase.
+
+2019-06-20 Marek Polacek <polacek@redhat.com>
+
+ PR c++/89873
+ * g++.dg/cpp1y/noexcept1.C: New test.
+
+2019-06-20 Thomas Koenig <tkoenig@gcc.gnu.org>
+
+ PR fortran/90937
+ * gfortran.dg/external_procedure_4.f90: New test.
+
+2019-06-20 Tom de Vries <tdevries@suse.de>
+
+ * gcc.dg/pr90866-2.c: Require global_constructor.
+
+2019-06-20 Tom de Vries <tdevries@suse.de>
+
+ * gcc.c-torture/compile/pr89280.c: Require nonlocal_goto.
+ * gcc.dg/pr88870.c: Same.
+ * gcc.dg/pr90082.c: Same.
+
+2019-06-20 Tom de Vries <tdevries@suse.de>
+
+ * gcc.dg/pr89737.c: Require indirect_jumps.
+ * gcc.dg/torture/pr87693.c: Same.
+ * gcc.dg/torture/pr89135.c: Same.
+ * gcc.dg/torture/pr90071.c: Same.
+
+2019-06-20 Tom de Vries <tdevries@suse.de>
+
+ * gcc.c-torture/compile/pr89280.c: Require label_values.
+ * gcc.dg/pr89737.c: Same.
+ * gcc.dg/pr90082.c: Same.
+ * gcc.dg/torture/pr89135.c: Same.
+ * gcc.dg/torture/pr89247.c: Same.
+ * gcc.dg/torture/pr90071.c: Same.
+
+2019-06-20 Tom de Vries <tdevries@suse.de>
+
+ * gcc.c-torture/compile/pr77754-1.c: Require alloca.
+ * gcc.c-torture/compile/pr77754-2.c: Same.
+ * gcc.c-torture/compile/pr77754-3.c: Same.
+ * gcc.c-torture/compile/pr77754-4.c: Same.
+ * gcc.c-torture/compile/pr77754-5.c: Same.
+ * gcc.c-torture/compile/pr77754-6.c: Same.
+ * gcc.c-torture/compile/pr87110.c: Same.
+ * gcc.c-torture/execute/pr86528.c: Same.
+ * gcc.dg/Walloca-larger-than-2.c: Same.
+ * gcc.dg/Walloca-larger-than.c: Same.
+ * gcc.dg/Warray-bounds-41.c: Same.
+ * gcc.dg/Wrestrict-17.c: Same.
+ * gcc.dg/Wstrict-overflow-27.c: Same.
+ * gcc.dg/Wstringop-truncation-3.c: Same.
+ * gcc.dg/pr78902.c: Same.
+ * gcc.dg/pr87099.c: Same.
+ * gcc.dg/pr87320.c: Same.
+ * gcc.dg/pr89045.c: Same.
+ * gcc.dg/strlenopt-62.c: Same.
+ * gcc.dg/tree-ssa/alias-37.c: Same.
+
+2019-06-19 Marek Polacek <polacek@redhat.com>
+
+ PR c++/60364 - noreturn after first decl not diagnosed.
+ * g++.dg/warn/noreturn-8.C: New test.
+ * g++.dg/warn/noreturn-9.C: New test.
+ * g++.dg/warn/noreturn-10.C: New test.
+ * g++.dg/warn/noreturn-11.C: New test.
+
+2019-06-19 Martin Sebor <msebor@redhat.com>
+
+ PR tree-optimization/90626
+ * gcc.dg/strlenopt-65.c: New test.
+ * gcc.dg/strlenopt-66.c: New test.
+ * gcc.dg/strlenopt.h (strcmp, strncmp): Declare.
+
+2019-06-19 Martin Sebor <msebor@redhat.com>
+
+ PR translation/90156
+ * gcc.dg/format/gcc_diag-11.c: Enable.
+
+2019-06-19 Steven G. Kargl <kargl@gcc.gnu.org>
+
+ PR fortran/69499
+ * gfortran.dg/pr69499.f90: New test.
+ * gfortran.dg/module_error_1.f90: Update dg-error string.
+
+2019-06-19 Steven G. Kargl <kargl@gcc.gnu.org>
+
+ PR fortran/69398
+ * gfortran.dg/pr69398.f90: New test.
+
+2019-06-19 Steven G. Kargl <kargl@gcc.gnu.org>
+
+ PR fortran/87907
+ * gfortran.dg/pr87907.f90: New testcase.
+
+2019-06-19 Wilco Dijkstra <wdijkstr@arm.com>
+
+ PR middle-end/84521
+ * gcc.c-torture/execute/pr84521.c: New test.
+
+2019-06-19 Jakub Jelinek <jakub@redhat.com>
+
+ * gcc.dg/vect/vect-simd-8.c: If main is defined, don't include
+ tree-vect.h nor call check_vect.
+ * gcc.dg/vect/vect-simd-9.c: Likewise.
+ * gcc.dg/vect/vect-simd-10.c: New test.
+ * gcc.target/i386/sse2-vect-simd-8.c: New test.
+ * gcc.target/i386/sse2-vect-simd-9.c: New test.
+ * gcc.target/i386/sse2-vect-simd-10.c: New test.
+ * gcc.target/i386/avx2-vect-simd-8.c: New test.
+ * gcc.target/i386/avx2-vect-simd-9.c: New test.
+ * gcc.target/i386/avx2-vect-simd-10.c: New test.
+ * gcc.target/i386/avx512f-vect-simd-8.c: New test.
+ * gcc.target/i386/avx512f-vect-simd-9.c: New test.
+ * gcc.target/i386/avx512f-vect-simd-10.c: New test.
+
+ * g++.dg/vect/simd-3.cc: New test.
+ * g++.dg/vect/simd-4.cc: New test.
+ * g++.dg/vect/simd-5.cc: New test.
+
+2019-06-19 Jakub Jelinek <jakub@redhat.com>
+
+ * g++.dg/ubsan/pr63956.C: Adjust expected diagnostics.
+
+2019-06-19 Jim MacArthur <jim.macarthur@codethink.co.uk>
+ Mark Eggleston <mark.eggleston@codethink.com>
+
+ PR fortran/89103
+ * gfortran.dg/dec_format_empty_item_1.f: New test.
+ * gfortran.dg/dec_format_empty_item_2.f: New test.
+ * gfortran.dg/dec_format_empty_item_3.f: New test.
+
+2019-06-19 Kugan Vivekanandarajah <kugan.vivekanandarajah@linaro.org>
+
+ * gcc.target/aarch64/pr88834.c: Move from here...
+ * gcc.target/aarch64/sve/pr88834.c: ...to here.
+
+2019-06-18 Cherry Zhang <cherryyz@google.com>
+
+ * go.dg/concatstring.go: New test.
+
+2019-06-18 Thomas Schwinge <thomas@codesourcery.com>
+
+ PR fortran/90921
+ * gfortran.dg/goacc/declare-3.f95: Update.
+
+ PR fortran/85221
+ * gfortran.dg/goacc/declare-3.f95: New file.
+
+ PR middle-end/90859
+ * c-c++-common/goacc/firstprivate-mappings-1.c: Update.
+
+ * c-c++-common/goacc/firstprivate-mappings-1.c: New file.
+ * g++.dg/goacc/firstprivate-mappings-1.C: Likewise.
+
+ PR testsuite/90861
+ * c-c++-common/goacc/declare-pr90861.c: New file.
+
+ PR testsuite/90868
+ * c-c++-common/goacc/declare-1.c: Update.
+ * c-c++-common/goacc/declare-2.c: Likewise.
+
+ PR middle-end/90862
+ * c-c++-common/goacc/declare-1.c: Update.
+ * c-c++-common/goacc/declare-2.c: Likewise.
+
+2019-06-18 Marek Polacek <polacek@redhat.com>
+
+ PR c++/84698
+ * g++.dg/cpp0x/noexcept42.C: New test.
+
+ PR c++/71548
+ * g++.dg/cpp0x/variadic177.C: New test.
+
+2019-06-18 Richard Sandiford <richard.sandiford@arm.com>
+
+ * gcc.target/aarch64/sve/struct_vect_18.c: Allow branches to
+ contain dots.
+ * gcc.target/aarch64/sve/struct_vect_19.c: Likewise.
+ * gcc.target/aarch64/sve/struct_vect_20.c: Likewise.
+ * gcc.target/aarch64/sve/struct_vect_21.c: Likewise.
+ * gcc.target/aarch64/sve/struct_vect_22.c: Likewise.
+ * gcc.target/aarch64/sve/struct_vect_23.c: Likewise.
+ * gcc.target/aarch64/sve/unroll-1.c: Likewise.
+ * gcc.target/aarch64/sve/while_1.c: Check for b.any.
+
+2019-06-18 Uroš Bizjak <ubizjak@gmail.com>
+
+ * gcc.target/i386/pr81563.c (dg-final): Check that no
+ registers are restored from %esp.
+
+2019-06-18 Richard Biener <rguenther@suse.de>
+
+ PR debug/90900
+ * gcc.dg/gomp/pr90900.c: New testcase.
+
+2019-06-18 Martin Sebor <msebor@redhat.com>
+
+ * gcc.dg/pr90866-2.c: Remove a pointless declaration
+ to avoid compilation errors on arm-none-eabi.
+
+2019-06-18 Szabolcs Nagy <szabolcs.nagy@arm.com>
+
+ * gcc.target/aarch64/pcs_attribute-2.c: Remove ifunc usage.
+ * gcc.target/aarch64/pcs_attribute-3.c: New test.
+
+2019-06-18 Alejandro Martinez <alejandro.martinezvicente@arm.com>
+ * gcc.target/aarch64/sve/fadda_1.c: New test.
+
+2019-06-17 Jakub Jelinek <jakub@redhat.com>
+
+ * gcc.dg/vect/vect-simd-8.c: New test.
+ * gcc.dg/vect/vect-simd-9.c: New test.
+ * g++.dg/vect/simd-2.cc: New test.
+ * g++.dg/gomp/scan-1.C: New test.
+
+2019-06-17 Uroš Bizjak <ubizjak@gmail.com>
+
+ PR target/62055
+ * gcc.target/i386/fnabs.c: New test.
+
+2019-06-17 Marek Polacek <polacek@redhat.com>
+
+ PR c++/83820 - excessive attribute arguments not detected.
+ * g++.dg/cpp0x/gen-attrs-67.C: New test.
+
+2019-06-17 Nathan Sidwell <nathan@acm.org>
+
+ PR c++/90754
+ * g++.dg/lookup/pr90754.C: New.
+
+2019-06-17 Wilco Dijkstra <wdijkstr@arm.com>
+
+ PR middle-end/64242
+ * gcc.c-torture/execute/pr64242.c: Improve test.
+
+2019-06-16 Jozef Lawrynowicz <jozef.l@mittosystems.com>
+
+ * gcc.target/msp430/mspabi_sllll.c: New test.
+ * gcc.target/msp430/mspabi_srall.c: New test.
+ * gcc.target/msp430/mspabi_srlll.c: New test.
+ * gcc.c-torture/execute/shiftdi-2.c: New test.
+
+2019-06-16 Jozef Lawrynowicz <jozef.l@mittosystems.com>
+
+ * lib/target-supports.exp: Add check_effective_target_longlong64.
+
+2019-06-16 Jan Hubicka <hubicka@ucw.cz>
+
+ * gcc.dg/tree-ssa/alias-access-path-4.c: New testcase.
+ * gcc.dg/tree-ssa/alias-access-path-5.c: New testcase.
+
+2019-06-15 Iain Buclaw <ibuclaw@gdcproject.org>
+
+ PR d/90650
+ * gdc.dg/pr90650a.d: New test.
+ * gdc.dg/pr90650b.d: New test.
+
+2019-06-15 Steven G. Kargl <kargl@gcc.gnu.org>
+
+ * gfortran.dg/dummy_derived_typed.f90: New test.
+
+2019-06-15 Jan Hubicka <hubicka@ucw.cz>
+
+ * gcc.dg/tree-ssa/alias-access-path-2.c: New testcase.
+
+2019-06-15 Steven G. Kargl <kargl@gcc.gnu.org>
+
+ * gfortran.dg/ieee/ieee_4.f90: Un-xfail on i?86-*-freebsd.
+
+2019-06-15 Iain Sandoe <iain@sandoe.co.uk>
+
+ PR objc/90709
+ * obj-c++.dg/proto-lossage-7.mm: Use proxy headers.
+ * obj-c++.dg/strings/const-cfstring-2.mm: Likewise.
+ * obj-c++.dg/strings/const-cfstring-5.mm: Likewise
+ * obj-c++.dg/strings/const-str-12.mm: Likewise.
+ * obj-c++.dg/syntax-error-1.mm: Likewise.
+ * obj-c++.dg/torture/strings/const-cfstring-1.mm: Likewise.
+ * obj-c++.dg/torture/strings/const-str-10.mm: Likewise.
+ * obj-c++.dg/torture/strings/const-str-11.mm: Likewise.
+ * obj-c++.dg/torture/strings/const-str-9.mm: Likewise.
+ * obj-c++.dg/cxx-ivars-3.mm: Skip on later Darwin, where the 10.4 API
+ in no longer supported, also on m64 where there's no meaning to it.
+ * obj-c++.dg/isa-field-1.mm: Suppress unwanted warning, add comment why.
+ * obj-c++.dg/objc-gc-3.mm: Skip for Darwin > 16, the API use is an error
+ there.
+ * obj-c++.dg/qual-types-1.mm: Prune a spurious l64 warning.
+ * obj-c++.dg/stubify-1.mm: Tidy up after better compiler warnings.
+ * obj-c++.dg/stubify-2.mm: Likewise.
+ * obj-c++.dg/try-catch-1.mm: Likewise.
+ * obj-c++.dg/try-catch-3.mm: Likewise.
+
+2019-06-15 Iain Sandoe <iain@sandoe.co.uk>
+
+ PR objc/90709
+ * objc.dg/encode-7-next-64bit.m: Use proxy headers.
+ * objc.dg/image-info.m: Likewise.
+ * objc.dg/method-6.m: Likewise.
+ * objc.dg/no-extra-load.m: Likewise.
+ * objc.dg/objc-foreach-4.m: Likewise.
+ * objc.dg/objc-foreach-5.m: Likewise.
+ * objc.dg/proto-lossage-7.m: Likewise.
+ * objc.dg/strings/const-cfstring-2.m: Likewise.
+ * objc.dg/strings/const-cfstring-5.m: Likewise.
+ * objc.dg/strings/const-str-12b.m: Likewise.
+ * objc.dg/symtab-1.m: Likewise.
+ * objc.dg/torture/strings/const-cfstring-1.m: Likewise.
+ * objc.dg/torture/strings/const-str-10.m: Likewise.
+ * objc.dg/torture/strings/const-str-11.m: Likewise.
+ * objc.dg/torture/strings/const-str-9.m: Likewise.
+ * objc.dg/zero-link-1.m: Likewise.
+ * objc.dg/zero-link-2.m: Likewise.
+ * objc.dg/zero-link-3.m: Likewise.
+ * objc.dg/isa-field-1.m: Suppress unwanted warning, add comment why.
+ * objc.dg/headers.m: XFAIL for Darwin14-19.
+ * objc.dg/objc-gc-4.m: Skip for Darwin > 16, the API use is an error
+ there.
+
+2019-06-15 Iain Sandoe <iain@sandoe.co.uk>
+
+ PR objc/90709
+ * objc-obj-c++-shared/CF-CFString.h: New.
+ * objc-obj-c++-shared/F-NSArray.h: New.
+ * objc-obj-c++-shared/F-NSAutoreleasePool.h: New.
+ * objc-obj-c++-shared/F-NSObject.h: New.
+ * objc-obj-c++-shared/F-NSString.h: New.
+ * objc-obj-c++-shared/F-NSValue.h: New.
+ * objc-obj-c++-shared/GNUStep/CoreFoundation/CFArray.h: New.
+ * objc-obj-c++-shared/GNUStep/CoreFoundation/CFAvailability.h: New.
+ * objc-obj-c++-shared/GNUStep/CoreFoundation/CFBase.h: New.
+ * objc-obj-c++-shared/GNUStep/CoreFoundation/CFCharacterSet.h: New.
+ * objc-obj-c++-shared/GNUStep/CoreFoundation/CFData.h: New.
+ * objc-obj-c++-shared/GNUStep/CoreFoundation/CFDictionary.h: New.
+ * objc-obj-c++-shared/GNUStep/CoreFoundation/CFLocale.h: New.
+ * objc-obj-c++-shared/GNUStep/CoreFoundation/CFString.h: New.
+ * objc-obj-c++-shared/GNUStep/Foundation/NSArray.h: New.
+ * objc-obj-c++-shared/GNUStep/Foundation/NSAutoreleasePool.h: New.
+ * objc-obj-c++-shared/GNUStep/Foundation/NSDate.h: New.
+ * objc-obj-c++-shared/GNUStep/Foundation/NSEnumerator.h: New.
+ * objc-obj-c++-shared/GNUStep/Foundation/NSGeometry.h: New.
+ * objc-obj-c++-shared/GNUStep/Foundation/NSObjCRuntime.h: New.
+ * objc-obj-c++-shared/GNUStep/Foundation/NSObject.h: New.
+ * objc-obj-c++-shared/GNUStep/Foundation/NSRange.h: New.
+ * objc-obj-c++-shared/GNUStep/Foundation/NSString.h: New.
+ * objc-obj-c++-shared/GNUStep/Foundation/NSValue.h: New.
+ * objc-obj-c++-shared/GNUStep/Foundation/NSZone.h: New.
+ * objc-obj-c++-shared/GNUStep/GNUstepBase/GNUstep.h: New.
+ * objc-obj-c++-shared/GNUStep/GNUstepBase/GSBlocks.h: New.
+ * objc-obj-c++-shared/GNUStep/GNUstepBase/GSConfig.h: New.
+ * objc-obj-c++-shared/GNUStep/GNUstepBase/GSObjCRuntime.h: New.
+ * objc-obj-c++-shared/GNUStep/GNUstepBase/GSVersionMacros.h: New.
+ * objc-obj-c++-shared/GNUStep/GNUstepBase/NSArray+GNUstepBase.h: New.
+ * objc-obj-c++-shared/GNUStep/GNUstepBase/NSMutableString+GNUstepBase.h:
+ New.
+ * objc-obj-c++-shared/GNUStep/GNUstepBase/NSNumber+GNUstepBase.h: New.
+ * objc-obj-c++-shared/GNUStep/GNUstepBase/NSObject+GNUstepBase.h: New.
+ * objc-obj-c++-shared/GNUStep/GNUstepBase/NSString+GNUstepBase.h: New.
+
+2019-06-15 Jakub Jelinek <jakub@redhat.com>
+
+ PR middle-end/90779
+ * c-c++-common/goacc/routine-5.c (func2): Don't expect error for
+ static block scope variable in #pragma acc routine.
+
+2019-06-14 Steven G. Kargl <kargl@gcc.gnu.org>
+
+ * gfortran.dg/integer_exponentiation_4.f90: Update test.
+ * gfortran.dg/integer_exponentiation_5.F90: Ditto.
+ * gfortran.dg/no_range_check_1.f90: Ditto.
+
+2019-06-14 Harald Anlauf <anlauf@gmx.de>
+
+ PR fortran/90577
+ PR fortran/90578
+ * gfortran.dg/lrshift_1.f90: Adjust testcase.
+ * gfortran.dg/shiftalr_3.f90: New testcase.
+
+2019-06-14 Steven G. Kargl <kargl@gcc.gnu.org>
+
+ PR fortran/89646
+ * gfortran.dg/pr89646.f90: New test.
+
+2019-06-14 H.J. Lu <hongjiu.lu@intel.com>
+
+ PR rtl-optimization/90765
+ * gcc.target/i386/pr90765-1.c: New test.
+ * gcc.target/i386/pr90765-2.c: Likewise.
+
+2019-06-14 Marek Polacek <polacek@redhat.com>
+
+ PR c++/90884 - stray note with -Wctor-dtor-privacy.
+ * g++.dg/warn/ctor-dtor-privacy-4.C: New.
+ * g++.dg/warn/ctor-dtor-privacy-4.h: New.
+
+2019-06-14 Richard Biener <rguenther@suse.de>
+
+ * gcc.dg/tree-ssa/ldist-26.c: Adjust.
+
+2019-06-14 Feng Xue <fxue@os.amperecomputing.com>
+
+ PR ipa/90401
+ * gcc.dg/ipa/ipcp-agg-10.c: New test.
+
+2019-06-13 Martin Sebor <msebor@redhat.com>
+
+ PR tree-optimization/90662
+ * gcc.dg/pr90866-2.c: New test.
+ * gcc.dg/pr90866.c: Ditto.
+
+2019-06-13 Jiufu Guo <guojiufu@linux.ibm.com>
+ Lijia He <helijia@linux.ibm.com>
+
+ PR tree-optimization/77820
+ * gcc.dg/tree-ssa/phi_on_compare-1.c: New testcase.
+ * gcc.dg/tree-ssa/phi_on_compare-2.c: New testcase.
+ * gcc.dg/tree-ssa/phi_on_compare-3.c: New testcase.
+ * gcc.dg/tree-ssa/phi_on_compare-4.c: New testcase.
+ * gcc.dg/tree-ssa/split-path-6.c: Update testcase.
+ * gcc.target/sh/pr51244-20.c: Update testcase.
+
+2019-06-13 Iain Sandoe <iain@sandoe.co.uk>
+
+ * gcc.dg/darwin-minversion-link.c: New test.
+
+2019-06-13 Steven G. Kargl <kargl@gcc.gnu.org>
+
+ PR fortran/68544
+ * gfortran.dg/pr68544.f90: New test.
+ * gfortran.dg/pr85687.f90: Modify test for new error message.
+
+2019-06-13 Iain Sandoe <iain@sandoe.co.uk>
+
+ * g++.dg/pr71694.C: Use non-PIC codegen for Darwin m32.
+
+2019-06-13 Steven G. Kargl <kargl@gcc.gnu.org>
+
+ PR fortran/89344
+ * gfortran.dg/pr89344.f90: New test.
+
+2019-06-13 Iain Sandoe <iain@sandoe.co.uk>
+
+ * gcc.dg/darwin-minversion-1.c: Use compile rather than link/run.
+ * gcc.dg/darwin-minversion-2.c: Likewise.
+
+2019-06-13 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR target/90871
+ * g++.dg/ext/altivec-15.C: Add dg-error directive.
+
+2019-06-13 Iain Sandoe <iain@sandoe.co.uk>
+
+ * gcc.dg/pr90760.c: Require alias support.
+
+2019-06-13 Jan Hubicka <hubicka@ucw.cz>
+
+ PR tree-optimization/90869
+ * g++.dg/tree-ssa/alias-access-path-1.C: New testcase.
+
+2019-06-13 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/90856
+ * gcc.target/i386/pr90856.c: New testcase.
+
+2019-06-13 Jakub Jelinek <jakub@redhat.com>
+
+ * g++.dg/tree-ssa/ssa-dse-1.C: Don't match exact number of chars of
+ = {} store.
+ * g++.dg/tree-ssa/pr31146.C: Change -fdump-tree-forwprop to
+ -fdump-tree-forwprop1 in dg-options. Expect <int[5]> in MEM.
+
+2019-06-13 Richard Biener <rguenther@suse.de>
+
+ * gcc.dg/vect/vect-version-1.c: New testcase.
+ * gcc.dg/vect/vect-version-2.c: Likewise.
+
+2019-06-13 Paolo Carlini <paolo.carlini@oracle.com>
+
+ * g++.dg/diagnostic/variably-modified-type-1.C: New.
+ * g++.dg/cpp0x/alias-decl-1.C: Test the location too.
+ * g++.dg/other/pr84792-1.C: Likewise.
+ * g++.dg/other/pr84792-2.C: Likewise.
+ * g++.dg/parse/error24.C: Likewise.
+ * g++.dg/parse/error32.C: Likewise.
+ * g++.dg/parse/error33.C: Likewise.
+ * g++.dg/parse/saved1.C: Likewise.
+ * g++.dg/template/operator6.C: Likewise.
+ * g++.dg/template/pr61745.C: Likewise.
+ * g++.dg/template/typedef41.C: Likewise.
+ * g++.old-deja/g++.jason/crash10.C: Likewise.
+
+2019-06-13 Paolo Carlini <paolo.carlini@oracle.com>
+
+ * g++.dg/diagnostic/conflicting-specifiers-1.C: New.
+ * g++.dg/diagnostic/two-or-more-data-types-1.C: Likewise.
+ * g++.dg/parse/error10.C: Adjust location.
+ * g++.dg/parse/pragma2.C: Likewise.
+
+2019-06-13 Feng Xue <fxue@os.amperecomputing.com>
+
+ PR tree-optimization/89713
+ * g++.dg/tree-ssa/empty-loop.C: New test.
+ * gcc.dg/tree-ssa/dce-2.c: New test.
+ * gcc.dg/const-1.c: Add -fno-finite-loops option.
+ * gcc.dg/graphite/graphite.exp: Likewise.
+ * gcc.dg/loop-unswitch-1.c: Likewise.
+ * gcc.dg/predict-9.c: Likewise.
+ * gcc.dg/pure-2.c: Likewise.
+ * gcc.dg/tree-ssa/20040211-1.c: Likewise.
+ * gcc.dg/tree-ssa/loop-10.c: Likewise.
+ * gcc.dg/tree-ssa/split-path-6.c: Likewise.
+ * gcc.dg/tree-ssa/ssa-thread-12.c: Likewise.
+
+2019-06-13 Kugan Vivekanandarajah <kugan.vivekanandarajah@linaro.org>
+
+ PR target/88838
+ * gcc.target/aarch64/pr88838.c: New test.
+ * gcc.target/aarch64/sve/while_1.c: Adjust.
+
+2019-06-13 Kugan Vivekanandarajah <kugan.vivekanandarajah@linaro.org>
+
+ PR target/88834
+ * gcc.target/aarch64/pr88834.c: New test.
+ * gcc.target/aarch64/sve/struct_vect_1.c: Adjust.
+ * gcc.target/aarch64/sve/struct_vect_14.c: Likewise.
+ * gcc.target/aarch64/sve/struct_vect_15.c: Likewise.
+ * gcc.target/aarch64/sve/struct_vect_16.c: Likewise.
+ * gcc.target/aarch64/sve/struct_vect_17.c: Likewise.
+ * gcc.target/aarch64/sve/struct_vect_7.c: Likewise.
+
+2019-06-12 Marek Polacek <polacek@redhat.com>
+
+ PR c++/87410
+ * g++.dg/cpp1y/pr87410.C: New test.
+
+2019-06-12 Marek Polacek <polacek@redhat.com>
+
+ PR c++/66999 - 'this' captured by reference.
+ * g++.dg/cpp0x/lambda/lambda-this21.C: New test.
+
+ PR c++/90825 - endless recursion when evaluating sizeof.
+ PR c++/90832 - endless recursion when evaluating sizeof.
+ * g++.dg/cpp0x/constexpr-sizeof2.C: New test.
+ * g++.dg/cpp0x/constexpr-sizeof3.C: New test.
+
+2019-06-12 Martin Sebor <msebor@redhat.com>
+
+ PR middle-end/90676
+ * gcc.dg/tree-ssa/pr30375.c: Adjust and simplify expected test
+ output some more.
+ * gcc.dg/tree-ssa/slsr-27.c: Ditto.
+ * gcc.dg/tree-ssa/slsr-28.c: Ditto.
+ * gcc.dg/tree-ssa/slsr-29.c: Ditto.
+ * gcc.dg/tree-ssa/ssa-dse-24.c: Ditto.
+
+2019-06-12 Marek Polacek <polacek@redhat.com>
+
+ PR c++/90736 - bogus error with alignof.
+ * g++.dg/cpp0x/alignof5.C: New test.
+
+2019-06-12 Dimitar Dimitrov <dimitar@dinux.eu>
+
+ * gcc.dg/builtin-apply2.c: Skip for PRU.
+ * gcc.dg/torture/stackalign/builtin-apply-2.c: Ditto.
+
+2019-06-12 Dimitar Dimitrov <dimitar@dinux.eu>
+
+ * g++.old-deja/g++.abi/ptrmem.C: Add PRU to list.
+
+2019-06-12 Dimitar Dimitrov <dimitar@dinux.eu>
+
+ * gcc.dg/tree-ssa/20040204-1.c: XFAIL on pru.
+ * gcc.dg/tree-ssa/reassoc-33.c: Ditto.
+ * gcc.dg/tree-ssa/reassoc-34.c: Ditto.
+ * gcc.dg/tree-ssa/reassoc-35.c: Ditto.
+ * gcc.dg/tree-ssa/reassoc-36.c: Ditto.
+
+2019-06-12 Dimitar Dimitrov <dimitar@dinux.eu>
+
+ * gcc.dg/stack-usage-1.c: Define PRU stack usage.
+
+2019-06-12 Dimitar Dimitrov <dimitar@dinux.eu>
+
+ * gcc.c-torture/execute/20101011-1.c: Define DO_TEST to 0 for PRU.
+ * gcc.dg/20020312-2.c: No PIC register for PRU.
+
+2019-06-12 Dimitar Dimitrov <dimitar@dinux.eu>
+
+ * lib/gcc-dg.exp: Filter unsupported features in PRU's TI ABI mode.
+ * lib/target-utils.exp: Ditto.
+ * lib/target-supports.exp (check_effective_target_function_pointers,
+ check_effective_target_large_return_values): New.
+
+2019-06-12 Dimitar Dimitrov <dimitar@dinux.eu>
+
+ * lib/gcc-dg.exp: Bail on region overflow for tiny targets.
+ * lib/target-utils.exp: Ditto.
+ * lib/target-supports.exp: Declare PRU target as tiny.
+
+2019-06-12 Dimitar Dimitrov <dimitar@dinux.eu>
+
+ * gcc.target/pru/abi-arg-struct.c: New test.
+ * gcc.target/pru/ashiftrt.c: New test.
+ * gcc.target/pru/builtins-1.c: New test.
+ * gcc.target/pru/builtins-error.c: New test.
+ * gcc.target/pru/clearbit.c: New test.
+ * gcc.target/pru/loop-asm.c: New test.
+ * gcc.target/pru/loop-dowhile.c: New test.
+ * gcc.target/pru/loop-hi-1.c: New test.
+ * gcc.target/pru/loop-hi-2.c: New test.
+ * gcc.target/pru/loop-qi-1.c: New test.
+ * gcc.target/pru/loop-qi-2.c: New test.
+ * gcc.target/pru/loop-short-1.c: New test.
+ * gcc.target/pru/loop-short-2.c: New test.
+ * gcc.target/pru/loop-si-1.c: New test.
+ * gcc.target/pru/loop-si-2.c: New test.
+ * gcc.target/pru/loop-u8_pcrel_overflow.c: New test.
+ * gcc.target/pru/loop-ubyte-1.c: New test.
+ * gcc.target/pru/loop-ubyte-2.c: New test.
+ * gcc.target/pru/lra-framepointer-fragmentation-1.c: New test.
+ * gcc.target/pru/lra-framepointer-fragmentation-2.c: New test.
+ * gcc.target/pru/mabi-ti-1.c: New test.
+ * gcc.target/pru/mabi-ti-2.c: New test.
+ * gcc.target/pru/mabi-ti-3.c: New test.
+ * gcc.target/pru/mabi-ti-4.c: New test.
+ * gcc.target/pru/mabi-ti-5.c: New test.
+ * gcc.target/pru/mabi-ti-6.c: New test.
+ * gcc.target/pru/mabi-ti-7.c: New test.
+ * gcc.target/pru/pr64366.c: New test.
+ * gcc.target/pru/pragma-ctable_entry.c: New test.
+ * gcc.target/pru/pru.exp: New file.
+ * gcc.target/pru/qbbc-1.c: New test.
+ * gcc.target/pru/qbbc-2.c: New test.
+ * gcc.target/pru/qbbc-3.c: New test.
+ * gcc.target/pru/qbbs-1.c: New test.
+ * gcc.target/pru/qbbs-2.c: New test.
+ * gcc.target/pru/setbit.c: New test.
+ * gcc.target/pru/zero_extend-and-hisi.c: New test.
+ * gcc.target/pru/zero_extend-and-qihi.c: New test.
+ * gcc.target/pru/zero_extend-and-qisi.c: New test.
+ * gcc.target/pru/zero_extend-hisi.c: New test.
+ * gcc.target/pru/zero_extend-qihi.c: New test.
+ * gcc.target/pru/zero_extend-qisi.c: New test.
+ * lib/target-supports.exp: Add PRU to feature filters.
+
+2019-06-12 Steven G. Kargl <kargl@gcc.gnu.org>
+
+ PR fortran/90002
+ * gfortran.dg/pr90002.f90: New test.
+
+2019-06-12 Martin Sebor <msebor@redhat.com>
+
+ PR middle-end/90676
+ * gcc.dg/tree-ssa/dump-6.c: New test.
+ * g++.dg/tree-ssa/pr19807.C: Adjust expected output.
+ * g++.dg/tree-ssa/ssa-dse-1.C: Same.
+ * gcc.dg/store_merging_5.c: Same.
+ * gcc.dg/tree-prof/stringop-2.c: Same.
+ * gcc.dg/tree-ssa/pr30375.c: Same.
+ * gcc.dg/tree-ssa/slsr-27.c: Same.
+ * gcc.dg/tree-ssa/slsr-28.c: Same.
+ * gcc.dg/tree-ssa/slsr-29.c: Same.
+ * gcc.dg/tree-ssa/ssa-dse-24.c: Same.
+
+2019-06-12 Martin Sebor <msebor@redhat.com>
+
+ PR tree-optimization/90662
+ * gcc.dg/strlenopt-62.c: New test.
+ * gcc.dg/strlenopt-63.c: New test.
+ * gcc.dg/strlenopt-64.c: New test.
+
+2019-06-12 Przemyslaw Wirkus <przemyslaw.wirkus@arm.com>
+
+ * gcc.target/arm/ssadv16qi.c: New test.
+ * gcc.target/arm/usadv16qi.c: Likewise.
+
+2019-06-12 Jakub Jelinek <jakub@redhat.com>
+
+ PR c/90760
+ * gcc.dg/pr90760.c: New test.
+
+2019-06-11 Faraz Shahbazker <fshahbazker@wavecomp.com>
+
+ * gcc.target/mips/data-sym-pool.c: Update expected output.
+ * gcc.target/mips/data-sym-multi-pool.c: New test.
+
+2019-06-11 Iain Sandoe <iain@sandoe.co.uk>
+
+ PR testsuite/65364
+ * gcc.dg/uninit-19.c (fn1): Adjust target condition for Darwin.
+ (fn2): Likewise.
+
+2019-06-11 Michael Meissner <meissner@linux.ibm.com>
+
+ * gcc.target/powerpc/localentry-1.c: Add -mpcrel option.
+ * gcc.target/powerpc/localentry-detect-1.c: Explicitly set and
+ unset -mpcrel in the target pragmas.
+ * gcc.target/powerpc/notoc-direct-1.c: Add -mpcrel option.
+ * gcc.target/powerpc/pcrel-sibcall-1.c: Explicitly set and
+ unset -mpcrel in the target pragmas.
+
+2019-06-11 Marc Glisse <marc.glisse@inria.fr>
+
+ * gcc.dg/tree-ssa/cmpexactdiv-5.c: New file.
+
+2019-06-11 Matthew Beliveau <mbelivea@redhat.com>
+
+ PR c++/90449 - add -Winaccessible-base option.
+ * g++.dg/warn/Winaccessible-base-1.C: New file.
+ * g++.dg/warn/Winaccessible-base-2.C: New file.
+ * g++.dg/warn/Winaccessible-virtual-base-1.C: New file.
+ * g++.dg/warn/Winaccessible-virtual-base-2.C: New file.
+
+2019-06-11 Jakub Jelinek <jakub@redhat.com>
+
+ PR c++/90810
+ * g++.dg/ext/vector37.C: New test.
+
+2019-06-10 Matthew Beliveau <mbelivea@redhat.com>
+
+ PR c++/87250
+ * g++.dg/cpp0x/pr87250.C: New test.
+
+2019-06-10 Jakub Jelinek <jakub@redhat.com>
+
+ PR testsuite/90772
+ * g++.dg/cpp1y/feat-cxx14.C: Use std::size_t instead of size_t.
+ * g++.dg/cpp1z/feat-cxx1z.C: Likewise.
+ * g++.dg/cpp2a/feat-cxx2a.C: Likewise.
+ * g++.dg/cpp1z/pr85569.C: Include <functional>.
+ * g++.dg/tree-ssa/pr80293.C: Include <cstdint>.
+ * g++.dg/tree-ssa/pr69336.C: Include <stdexcept>.
+
+2019-06-10 Jonathan Wakely <jwakely@redhat.com>
+
+ PR other/90695
+ * g++.dg/cpp0x/noexcept15.C: Remove dependency on library header.
+
+2019-06-10 Jakub Jelinek <jakub@redhat.com>
+
+ * c-c++-common/gomp/scan-1.c: New test.
+ * c-c++-common/gomp/scan-2.c: New test.
+ * c-c++-common/gomp/scan-3.c: New test.
+ * c-c++-common/gomp/scan-4.c: New test.
+
+2019-06-10 Martin Liska <mliska@suse.cz>
+
+ * gcc.dg/no_profile_instrument_function-attr-1.c: Fix
+ function name.
+
+2019-06-10 Claudiu Zissulescu <claziss@synopsys.com>
+
+ * gcc.target/arc/jumptables.c: Update test.
+
+2019-06-10 Claudiu Zissulescu <claziss@synopsys.com>
+
+ * gcc.target/arc/and-cnst-size.c: New test.
+ * gcc.target/arc/mov-cnst-size.c: Likewise.
+ * gcc.target/arc/or-cnst-size.c: Likewise.
+ * gcc.target/arc/store-merge-1.c: Update test.
+ * gcc.target/arc/arc700-stld-hazard.c: Likewise.
+ * gcc.target/arc/cmem-1.c: Likewise.
+ * gcc.target/arc/cmem-2.c: Likewise.
+ * gcc.target/arc/cmem-3.c: Likewise.
+ * gcc.target/arc/cmem-4.c: Likewise.
+ * gcc.target/arc/cmem-5.c: Likewise.
+ * gcc.target/arc/cmem-6.c: Likewise.
+ * gcc.target/arc/loop-4.c: Likewise.
+ * gcc.target/arc/movh_cl-1.c: Likewise.
+ * gcc.target/arc/sdata-3.c: Likewise.
+
+2019-06-10 Martin Liska <mliska@suse.cz>
+
+ * gcc.dg/ipa/pr68035.c: Update scanned pattern.
+
+2019-06-10 Iain Sandoe <iain@sandoe.co.uk>
+
+ * gcc.dg/attr-copy-6.c: Require alias support.
+
+2019-06-09 Marek Polacek <polacek@redhat.com>
+
+ PR c++/65175
+ * g++.dg/cpp0x/alias-decl-69.C: New test.
+
+ PR c++/60366
+ * g++.dg/cpp0x/lambda/lambda-ice32.C: New test.
+
+019-06-09 Paul Thomas <pault@gcc.gnu.org>
+
+ PR fortran/89365
+ * gfortran.dg/assumed_rank_bounds_3.f90 : New test.
+
+2019-06-08 Paul Thomas <pault@gcc.gnu.org>
+
+ PR fortran/90786
+ * gfortran.dg/proc_ptr_51.f90 : New test.
+
+2019-06-08 Marek Polacek <polacek@redhat.com>
+
+ PR c++/52269
+ * g++.dg/cpp0x/constexpr-decltype4.C: New test.
+
+2019-06-08 Thomas Koenig <tkoenig@gcc.gnu.org>
+ Tomáš Trnka <trnka@scm.com>
+
+ PR fortran/90744
+ * gfortran.dg/deferred_character_33.f90: New test.
+ * gfortran.dg/deferred_character_33a.f90: New test.
+
+2019-06-08 Marek Polacek <polacek@redhat.com>
+
+ PR c++/77548
+ * g++.dg/other/pr77548.C: New test.
+
+ PR c++/72845
+ * g++.dg/cpp0x/noexcept41.C: New test.
+
+2019-06-08 Prathamesh Kulkarni <prathamesh.kulkarni@linaro.org>
+
+ * gcc.target/aarch64/sve/init_1.c: Remove options
+ -O2 -fno-schedule-insns and instead pass -O.
+ Update assembly in comments.
+ * gcc.target/aarch64/sve/init_2.c: Likewise.
+ * gcc.target/aarch64/sve/init_3.c: Likewise.
+ * gcc.target/aarch64/sve/init_4.c: Likewise.
+ * gcc.target/aarch64/sve/init_5.c: Likewise and additionally
+ adjust dg-scan.
+ * gcc.target/aarch64/sve/init_6.c: Likewise.
+ * gcc.target/aarch64/sve/init_7.c: Likewise.
+ * gcc.target/aarch64/sve/init_8.c: Likewise.
+ * gcc.target/aarch64/sve/init_9.c: Likewise.
+ * gcc.target/aarch64/sve/init_10.c: Likewise.
+ * gcc.target/aarch64/sve/init_11.c: Likewise.
+ * gcc.target/aarch64/sve/init_12.c: Likewise.
+
+2019-06-07 Marek Polacek <polacek@redhat.com>
+
+ PR c++/77747
+ * g++.dg/cpp0x/inh-ctor33.C: New test.
+
+ PR c++/77967
+ * g++.dg/cpp0x/alias-decl-68.C: New test.
+
+ PR c++/77771
+ * g++.dg/cpp0x/constexpr-77771.C: New test.
+
+2019-06-07 John David Anglin <danglin@gcc.gnu.org>
+
+ * lib/scanasm.exp (dg-function-on-line): Add pattern for hppa*-*-linux*.
+
+2019-06-07 Mark Eggleston <mark.eggleston@codethink.com>
+
+ PR fortran/89100
+ * gfortran.dg/fmt_f_default_field_width_3.f90: Modify dg-error
+ to allow use when kind=16 is not supported.
+ * gfortran.dg/fmt_g_default_field_width_3.f90: Modify dg-error
+ to allow use when kind=16 is not supported.
+
+2019-06-07 Richard Biener <rguenther@suse.de>
+
+ PR debug/90574
+ * gcc.misc-tests/gcov-pr90574-1.c: New testcase.
+ * gcc.misc-tests/gcov-pr90574-2.c: Likewise.
+
+2019-06-07 Jan Hubicka <hubicka@ucw.cz>
+
+ * gcc.dg/lto/alias-access-path-2.0.c: New testcase.
+
+2019-06-07 Martin Liska <mliska@suse.cz>
+
+ PR tree-optimization/78902
+ * c-c++-common/asan/alloca_loop_unpoisoning.c: Use result
+ of __builtin_alloca.
+ * c-c++-common/asan/pr88619.c: Likewise.
+ * g++.dg/overload/using2.C: Likewise for malloc.
+ * gcc.dg/attr-alloc_size-5.c: Add new dg-warning.
+ * gcc.dg/nonnull-3.c: Use result of __builtin_strdup.
+ * gcc.dg/pr43643.c: Likewise.
+ * gcc.dg/pr59717.c: Likewise for calloc.
+ * gcc.dg/torture/pr71816.c: Likewise.
+ * gcc.dg/tree-ssa/pr78886.c: Likewise.
+ * gcc.dg/tree-ssa/pr79697.c: Likewise.
+ * gcc.dg/pr78902.c: New test.
+
+2019-06-06 Iain Sandoe <iain@sandoe.co.uk>
+
+ * g++.dg/cpp0x/alignas4.C: Amend test to check for zerofill syntax
+ on Darwin.
+
+2019-06-06 Martin Jambor <mjambor@suse.cz>
+
+ * gcc.dg/tree-ssa/alias-access-path-1.c: Remove -fno-tree-sra option.
+ * gcc.dg/tree-ssa/ssa-dse-26.c: Disable FRE.
+ * gnat.dg/opt39.adb: Adjust scan dump.
+
+2019-06-06 Jozef Lawrynowicz <jozef.l@mittosystems.com>
+
+ * gcc.target/msp430/size-optimized-shifts.c: New test.
+
+2019-06-06 Jozef Lawrynowicz <jozef.l@mittosystems.com>
+
+ * gcc.target/msp430/emulate-slli.c: New test.
+ * gcc.target/msp430/emulate-srai.c: New test.
+ * gcc.target/msp430/emulate-srli.c: New test.
+
+2019-06-06 Martin Liska <mliska@suse.cz>
+
+ PR tree-optimization/87954
+ * gcc.dg/pr87954.c: New test.
+
+2019-06-06 Richard Biener <rguenther@suse.de>
+
+ * gcc.dg/tree-ssa/alias-37.c: New testcase.
+ * gcc.dg/torture/20190604-1.c: Likewise.
+ * gcc.dg/tree-ssa/pta-callused.c: Adjust.
+
+2019-06-06 Claudiu Zissulescu <claziss@synopsys.com>
+
+ * gcc.target/arc/tmac-1.c: Reoreder dg-directives.
+ * gcc.target/arc/tmac-2.c: Likewise.
+
+2019-06-05 Martin Sebor <msebor@redhat.com>
+
+ PR c/90737
+ * c-c++-common/Wreturn-local-addr.c: New test.
+ * g++.dg/warn/Wreturn-local-addr-6.C: New test.
+
+2019-06-05 Hongtao Liu <hongtao.liu@intel.com>
+
+ * gcc.target/i386/avx512dq-vfpclasspd-1.c: Adjust scan assember
+ for {x,y,z} suffix.
+ * gcc.target/i386/avx512dq-vfpclassps-1.c: Ditto.
+
+2019-06-05 Martin Sebor <msebor@redhat.com>
+
+ * gcc.dg/format/gcc_diag-11.c: Skip until -Wformat-diag has
+ been committed.
+
+2019-06-05 Paolo Carlini <paolo.carlini@oracle.com>
+
+ * g++.dg/diagnostic/return-type-invalid-1.C: New.
+ * g++.old-deja/g++.brendan/crash16.C: Adjust.
+ * g++.old-deja/g++.law/ctors5.C: Likewise.
+
+2019-06-05 Paolo Carlini <paolo.carlini@oracle.com>
+
+ * g++.dg/other/friend4.C: Test locations too.
+ * g++.dg/other/friend5.C: Likewise.
+ * g++.dg/other/friend7.C: Likewise.
+
+2019-06-05 Segher Boessenkool <segher@kernel.crashing.org>
+
+ * g++.target/powerpc/undef-bool-3.C: Add -maltivec to dg-options.
+
+2019-06-05 Martin Sebor <msebor@redhat.com>
+
+ * gcc.dg/weak/weak-19.c: New test.
+
+2019-06-05 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gnat.dg/specs/discr6.ads: New test.
+
+2019-06-05 Sam Tebbs <sam.tebbs@arm.com>
+
+ * gcc.target/aarch64/return_address_sign_b_1.c: New file.
+ * gcc.target/aarch64/return_address_sign_b_2.c: New file.
+ * gcc.target/aarch64/return_address_sign_b_3.c: New file.
+ * gcc.target/aarch64/return_address_sign_builtin.c: New file.
+ * g++.target/aarch64/return_address_sign_ab_exception.C: New file.
+ * g++.target/aarch64/return_address_sign_b_exception.C: New file.
+
+2019-06-05 Jakub Jelinek <jakub@redhat.com>
+
+ PR debug/90733
+ * gcc.dg/pr90733.c: New test.
+
+2019-06-05 Richard Biener <rguenther@suse.de>
+
+ PR middle-end/90726
+ * gcc.dg/pr90726.c: Enable IVOPTs.
+
+2019-06-05 Jakub Jelinek <jakub@redhat.com>
+
+ * g++.dg/vect/simd-1.cc: New test.
+
+2019-06-05 Hongtao Liu <hongtao.liu@intel.com>
+
+ PR target/89803
+ * gcc.target/i386/avx-1.c (__builtin_ia32_fpclasssss,
+ __builtin_ia32_fpclasssd): Removed.
+ (__builtin_ia32_fpclassss_mask, __builtin_ia32_fpclasssd_mask): Define.
+ * gcc.target/i386/sse-13.c (__builtin_ia32_fpclasssss,
+ __builtin_ia32_fpclasssd): Removed.
+ (__builtin_ia32_fpclassss_mask, __builtin_ia32_fpclasssd_mask): Define.
+ * gcc.target/i386/sse-23.c (__builtin_ia32_fpclasssss,
+ __builtin_ia32_fpclasssd): Removed.
+ (__builtin_ia32_fpclassss_mask, __builtin_ia32_fpclasssd_mask): Define.
+ * gcc.target/i386/avx512dq-vfpclassss-2.c: New.
+ * gcc.target/i386/avx512dq-vfpclasssd-2.c: New.
+ * gcc.target/i386/avx512dq-vfpclassss-1.c (avx512f_test):
+ Add test for _mm_mask_fpclass_ss_mask.
+ * gcc.target/i386/avx512dq-vfpclasssd-1.c (avx512f_test):
+ Add test for _mm_mask_fpclass_sd_mask.
+
+2019-06-04 Segher Boessenkool <segher@kernel.crashing.org>
+
+ * gcc.target/powerpc/direct-move-double1.c (VSX_REG_ATTR): Delete.
+ * gcc.target/powerpc/direct-move-double2.c: Ditto.
+ * gcc.target/powerpc/direct-move-float1.c: Ditto.
+ * gcc.target/powerpc/direct-move-float2.c: Ditto.
+ * gcc.target/powerpc/direct-move-vint1.c: Ditto.
+ * gcc.target/powerpc/direct-move-vint2.c: Ditto.
+
+2019-06-04 Segher Boessenkool <segher@kernel.crashing.org>
+
+ * gcc.target/powerpc/direct-move-float1.c: Use "wa" instead of "ww"
+ constraint.
+
+2019-06-04 Paolo Carlini <paolo.carlini@oracle.com>
+
+ * g++.dg/concepts/pr60573.C: Test locations too.
+ * g++.dg/cpp0x/deleted13.C: Likewise.
+ * g++.dg/parse/error29.C: Likewise.
+ * g++.dg/parse/qualified4.C: Likewise.
+ * g++.dg/template/crash96.C Likewise.
+ * g++.old-deja/g++.brendan/crash22.C Likewise.
+ * g++.old-deja/g++.brendan/crash23.C Likewise.
+ * g++.old-deja/g++.law/visibility10.C Likewise.
+ * g++.old-deja/g++.other/decl5.C: Likewise.
+
+2019-06-04 Bill Schmidt <wschmidt@linux.ibm.com>
+
+ PR target/78263
+ * g++.target/powerpc: New directory.
+ * g++.target/powerpc/powerpc.exp: New test driver.
+ * g++.target/powerpc/undef-bool-3.C: New.
+
+2019-06-04 Jakub Jelinek <jakub@redhat.com>
+
+ * c-c++-common/gomp/lastprivate-conditional-2.c (foo): Don't expect
+ a sorry_at on any of the clauses.
+
+2019-06-04 Richard Biener <rguenther@suse.de>
+
+ PR middle-end/90726
+ * gcc.dg/pr90726.c: New testcase.
+
+2019-06-04 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/90738
+ * gcc.dg/torture/pr90738.c: New testcase.
+
+ Revert
+ 2019-06-03 Richard Biener <rguenther@suse.de>
+
+ * gcc.dg/tree-ssa/alias-access-path-1.c: Scan fre1.
+
+2019-06-04 Martin Liska <mliska@suse.cz>
+
+ * c-c++-common/goacc/acc-icf.c: Change scanned pattern.
+ * gfortran.dg/goacc/pr78027.f90: Likewise.
+
+2019-06-03 Segher Boessenkool <segher@kernel.crashing.org>
+
+ * gcc.target/powerpc/mmfpgpr.c: Delete.
+
+2019-06-03 David Edelsohn <dje.gcc@gmail.com>
+
+ * gcc.dg/debug/enum-1.c: Add -fno-eliminate-unused-debug-symbols
+ on AIX.
+ * g++.dg/debug/enum-1.C: Same.
+
+2019-06-03 Wilco Dijkstra <wdijkstr@arm.com>
+
+ PR middle-end/64242
+ * gcc.c-torture/execute/pr64242.c: Update test.
+
+2019-06-03 Szabolcs Nagy <szabolcs.nagy@arm.com>
+
+ * gcc.target/aarch64/pcs_attribute-2.c: New test.
+ * gcc.target/aarch64/torture/simd-abi-4.c: Check .variant_pcs support.
+ * lib/target-supports.exp (check_effective_target_aarch64_variant_pcs):
+ New.
+
+2019-06-03 Kyrylo Tkachov <kyrylo.tkachov@arm.com>
+
+ * gcc.target/aarch64/ssadv16qi.c: Add +nodotprod to pragma.
+ * gcc.target/aarch64/usadv16qi.c: Likewise.
+ * gcc.target/aarch64/ssadv16qi-dotprod.c: New test.
+ * gcc.target/aarch64/usadv16qi-dotprod.c: Likewise.
+
+2019-06-03 Prathamesh Kulkarni <prathamesh.kulkarni@linaro.org>
+
+ * lib/target-supports.exp (add_options_for_aarch64_sve): New procedure.
+ (aarch64_sve_hw_bits): Call add_options_for_aarch64_sve.
+ (check_effective_target_aarch64_sve_hw): Likewise.
+
+2019-06-03 Richard Biener <rguenther@suse.de>
+
+ * gcc.dg/tree-ssa/alias-access-path-1.c: Scan fre1.
+
+2019-06-03 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/90716
+ * gcc.dg/guality/pr90716.c: New testcase.
+
+2019-06-03 Prathamesh Kulkarni <prathamesh.kulkarni@linaro.org>
+
+ PR target/88837
+ * gcc.target/aarch64/sve/init_1.c: New test.
+ * gcc.target/aarch64/sve/init_1_run.c: Likewise.
+ * gcc.target/aarch64/sve/init_2.c: Likewise.
+ * gcc.target/aarch64/sve/init_2_run.c: Likewise.
+ * gcc.target/aarch64/sve/init_3.c: Likewise.
+ * gcc.target/aarch64/sve/init_3_run.c: Likewise.
+ * gcc.target/aarch64/sve/init_4.c: Likewise.
+ * gcc.target/aarch64/sve/init_4_run.c: Likewise.
+ * gcc.target/aarch64/sve/init_5.c: Likewise.
+ * gcc.target/aarch64/sve/init_5_run.c: Likewise.
+ * gcc.target/aarch64/sve/init_6.c: Likewise.
+ * gcc.target/aarch64/sve/init_6_run.c: Likewise.
+ * gcc.target/aarch64/sve/init_7.c: Likewise.
+ * gcc.target/aarch64/sve/init_7_run.c: Likewise.
+ * gcc.target/aarch64/sve/init_8.c: Likewise.
+ * gcc.target/aarch64/sve/init_8_run.c: Likewise.
+ * gcc.target/aarch64/sve/init_9.c: Likewise.
+ * gcc.target/aarch64/sve/init_9_run.c: Likewise.
+ * gcc.target/aarch64/sve/init_10.c: Likewise.
+ * gcc.target/aarch64/sve/init_10_run.c: Likewise.
+ * gcc.target/aarch64/sve/init_11.c: Likewise.
+ * gcc.target/aarch64/sve/init_11_run.c: Likewise.
+ * gcc.target/aarch64/sve/init_12.c: Likewise.
+ * gcc.target/aarch64/sve/init_12_run.c: Likewise.
+
+2019-06-03 Alejandro Martinez <alejandro.martinezvicente@arm.com>
+
+ PR tree-optimization/90681
+ * gfortran.dg/vect/pr90681.f: New test.
+
+2019-06-03 Richard Biener <rguenther@suse.de>
+
+ PR testsuite/90713
+ * gcc.dg/gimplefe-40.c: Add -maltivec for powerpc.
+
+2019-06-02 Thomas Koenig <tkoenig@gcc.gnu.org>
+
+ PR fortran/90539
+ * gfortran.dg/internal_pack_24.f90: New test.
+
+2019-06-01 Iain Sandoe <iain@sandoe.co.uk>
+
+ PR target/90698
+ * gcc.target/i386/pr49866.c: XFAIL for Darwin.
+ * gcc.target/i386/pr63538.c: Likewise.
+ * gcc.target/i386/pr61599-1.c: Skip for Darwin.
+
+2019-06-01 Martin Sebor <msebor@redhat.com>
+
+ PR middle-end/90694
+ * gcc.dg/tree-ssa/dump-5.c: New test.
+
+2019-05-31 Jan Hubicka <jh@suse.cz>
+
+ * g++.dg/lto/alias-1_0.C: New testcase.
+ * g++.dg/lto/alias-1_1.C: New testcase.
+
+2019-05-31 H.J. Lu <hongjiu.lu@intel.com>
+
+ PR target/89355
+ * gcc.target/i386/cet-label-3.c: New test.
+ * gcc.target/i386/cet-label-4.c: Likewise.
+ * gcc.target/i386/cet-label-5.c: Likewise.
+
+2019-05-31 Dragan Mladjenovic <dmladjenovic@wavecomp.com>
+
+ * gcc.target/mips/msa-fmadd.c: New.
+
+2019-05-31 Jakub Jelinek <jakub@redhat.com>
+
+ * c-c++-common/gomp/lastprivate-conditional-2.c (foo): Don't expect
+ a sorry on lastprivate conditional on simd construct.
+ * gcc.dg/vect/vect-simd-6.c: New test.
+ * gcc.dg/vect/vect-simd-7.c: New test.
+
+ * gcc.dg/vect/vect-simd-5.c: New test.
+
+2019-05-31 Xiong Hu Luo <luoxhu@linux.ibm.com>
+
+ PR c/43673
+ * gcc.dg/format-dfp-printf-1.c: New test.
+ * gcc.dg/format-dfp-scanf-1.c: Likewise.
+
+2019-05-31 Marc Glisse <marc.glisse@inria.fr>
+
+ * g++.dg/tree-ssa/cprop-vcond.C: New file.
+
+2019-05-31 Marc Glisse <marc.glisse@inria.fr>
+
+ * gcc.dg/tree-ssa/cmpexactdiv-3.c: New file.
+ * gcc.dg/tree-ssa/cmpexactdiv-4.c: New file.
+ * gcc.dg/Walloca-13.c: Xfail.
+
+2019-05-31 Bill Schmidt <wschmidt@linux.ibm.com>
+ Michael Meissner <meissner@linux.ibm.com>
+
+ * gcc.target/powerpc/cpu-future.c: Require powerpc_future_ok.
+ * gcc.target/powerpc/localentry-1.c: Likewise.
+ * gcc.target/powerpc/localentry-direct-1.c: Likewise.
+ * gcc.target/powerpc/notoc-direct-1.c: Likewise.
+ * gcc.target/powerpc/pcrel-sibcall-1.c: Likewise.
+ * lib/target-supports.exp (check_powerpc_future_hw_available): New.
+ (check_effective_target_powerpc_future_ok): New.
+
+2019-05-31 Thomas De Schampheleire <thomas.de_schampheleire@nokia.com>
+
+ PR debug/86964
+ * g++.dg/debug/dwarf2/fesd-any.C: Use
+ -fno-eliminate-unused-debug-symbols.
+ * g++.dg/debug/dwarf2/fesd-baseonly.C: Likewise.
+ * g++.dg/debug/dwarf2/fesd-none.C: Likewise.
+ * g++.dg/debug/dwarf2/fesd-reduced.C: Likewise.
+ * g++.dg/debug/dwarf2/fesd-sys.C: Likewise.
+ * g++.dg/debug/dwarf2/inline-var-1.C: Likewise.
+ * g++.dg/debug/enum-2.C: Likewise.
+ * gcc.dg/debug/dwarf2/fesd-any.c: Likewise.
+ * gcc.dg/debug/dwarf2/fesd-baseonly.c: Likewise.
+ * gcc.dg/debug/dwarf2/fesd-none.c: Likewise.
+ * gcc.dg/debug/dwarf2/fesd-reduced.c: Likewise.
+ * gcc.dg/debug/dwarf2/fesd-sys.c: Likewise.
+
+2019-05-31 Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/90671
+ * gcc.dg/torture/pr90671.c: New test.
+
+2019-05-31 Iain Sandoe <iain@sandoe.co.uk>
+
+ * g++.dg/cpp0x/pr84497.C: Require alias support.
+
+2019-05-31 Iain Sandoe <iain@sandoe.co.uk>
+
+ * gcc.target/i386/falign-functions-3.c: Adjust align syntax
+ and label for Darwin.
+ * gcc.target/i386/attr-aligned-2.c: Adjust align syntax for
+ Darwin.
+
+2019-05-30 Sylvia Taylor <sylvia.taylor@arm.com>
+
+ * gcc.target/aarch64/sve/fabd_1.c: New.
+
+2019-05-30 Iain Sandoe <iain@sandoe.co.uk>
+
+ * gcc.target/i386/pr86257.c: Require native TLS support.
+ * gcc.target/i386/stack-prot-sym.c: Likewise.
+
+2019-05-30 Paolo Carlini <paolo.carlini@oracle.com>
+
+ * g++.dg/cpp0x/alias-decl-18.C: Test location too.
+ * g++.dg/cpp0x/udlit-nofunc-neg.C: Likewise.
+ * g++.dg/parse/crash59.C: Likewise.
+ * g++.dg/parse/error38.C: Likewise.
+ * g++.dg/parse/error39.C: Likewise.
+ * g++.dg/template/crash31.C: Likewise.
+ * g++.dg/template/operator8.C: Likewise.
+ * g++.dg/template/operator9.C: Likewise.
+
+2019-05-29 Bill Schmidt <wschmidt@linux.ibm.com>
+
+ * gcc.target/powerpc/notoc-direct-1.c: New.
+ * gcc.target/powerpc/pcrel-sibcall-1.c: New.
+
+2019-05-29 Jakub Jelinek <jakub@redhat.com>
+
+ PR c++/90598
+ * g++.dg/cpp0x/pr90598.C: New test.
+
+2019-05-29 Thomas Koenig <tkoenig@gcc.gnu.org>
+
+ PR fortran/90539
+ * gfortran.dg/internal_pack_21.f90: Adjust scan patterns.
+ * gfortran.dg/internal_pack_22.f90: New test.
+ * gfortran.dg/internal_pack_23.f90: New test.
+
+2019-05-29 Jan Hubicka <hubicka@ucw.cz>
+
+ * tree-ssa/alias-access-spath-1.c: new testcase.
+
+2019-05-29 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/89875
+ * g++.dg/cpp0x/decltype-pr66548.C: Remove xfail.
+ * g++.dg/template/sizeof-template-argument.C: Adjust expected error.
+
+2019-05-29 Alejandro Martinez <alejandro.martinezvicente@arm.com>
+
+ * gcc.target/aarch64/sve2/aarch64-sve2.exp: New file, regression
+ driver for AArch64 SVE2.
+ * gcc.target/aarch64/sve2/average_1.c: New test.
+ * lib/target-supports.exp (check_effective_target_aarch64_sve2): New
+ helper.
+ (check_effective_target_aarch64_sve1_only): Likewise.
+ (check_effective_target_aarch64_sve2_hw): Likewise.
+ (check_effective_target_vect_avg_qi): Check for SVE1 only.
+
+2019-05-29 Sam Tebbs <sam.tebbs@arm.com>
+
+ * gcc.target/aarch64/return_address_sign_b_1.c: New file.
+ * gcc.target/aarch64/return_address_sign_b_2.c: New file.
+ * gcc.target/aarch64/return_address_sign_b_3.c: New file.
+ * gcc.target/aarch64/return_address_sign_b_exception.c: New file.
+ * gcc.target/aarch64/return_address_sign_ab_exception.c: New file.
+ * gcc.target/aarch64/return_address_sign_builtin.c: New file
+
+2019-05-29 Jakub Jelinek <jakub@redhat.com>
+
+ * c-c++-common/gomp/lastprivate-conditional-2.c (foo): Don't expect
+ sorry on lastprivate conditional on parallel for.
+ * c-c++-common/gomp/lastprivate-conditional-3.c (foo): Add tests for
+ lastprivate conditional warnings on parallel for constructs.
+ * c-c++-common/gomp/lastprivate-conditional-4.c: New test.
+
+ PR c/90628
+ * c-c++-common/builtin-arith-overflow-3.c: New test.
+
+ P1091R3 - Extending structured bindings to be more like var decls
+ P1381R1 - Reference capture of structured bindings
+ * g++.dg/cpp1z/decomp3.C (test): For static, expect only warning
+ instead of error and only for c++17_down. Add a thread_local test.
+ (z2): Add a __thread test.
+ * g++.dg/cpp2a/decomp1.C: New test.
+ * g++.dg/cpp2a/decomp1-aux.cc: New file.
+ * g++.dg/cpp2a/decomp2.C: New test.
+ * g++.dg/cpp2a/decomp3.C: New test.
+
+2019-05-29 Martin Liska <mliska@suse.cz>
+
+ PR testsuite/90657
+ * gcc.dg/ipa/pr90555.c: Remove duplicite dg-compile.
+
+2019-05-28 Bill Schmidt <wschmidt@linux.ibm.com>
+
+ * gcc.target/powerpc/localentry-detect-1.c: New file.
+
+2019-05-28 Marek Polacek <polacek@redhat.com>
+
+ PR c++/90548 - ICE with generic lambda and empty pack.
+ * g++.dg/cpp1y/lambda-generic-90548.C: New test.
+
+2019-05-28 Alejandro Martinez <alejandro.martinezvicente@arm.com>
+
+ * gcc.target/aarch64/sve/mask_load_slp_1.c: New test for SLP
+ vectorized masked loads.
+
+2019-05-28 Jeff Law <law@redhat.com>
+
+ * testsuite/gcc.target/sh/pr50749-qihisi-predec-3.c: Disable
+ loop distribution.
+
+2019-05-28 Segher Boessenkool <segher@kernel.crashing.org>
+
+ * gcc.target/powerpc/p9-dimode1.c: Don't restrict to -m64. Check for
+ all mtvsr*, not just mtvsrd. Use "wa" instead of "wi" constraints.
+ * gcc.target/powerpc/p9-dimode2.c: Ditto.
+
+2019-05-28 Martin Liska <mliska@suse.cz>
+
+ PR ipa/90555
+ * gcc.dg/ipa/pr90555.c: New test.
+
+2019-05-28 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gnat.dg/machine_attr1.ad[sb]: New test.
+
+2019-05-28 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gnat.dg/opt79.ad[sb]: New test.
+
+2019-05-28 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gnat.dg/specs/discr5.ads: New test.
+
+2019-05-28 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gnat.dg/prefetch1.ad[sb]: New test.
+
+2019-05-27 Iain Sandoe <iain@sandoe.co.uk>
+
+ * gcc.target/i386/pr22076.c: Adjust options to
+ match codegen expected by the scan-asms.
+
+2019-05-27 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gnat.dg/specs/array4.ads: New test.
+
+2019-05-27 Christophe Lyon <christophe.lyon@linaro.org>
+
+ PR tree-optimization/88440
+ * gcc.target/aarch64/sve/index_offset_1.c: Add
+ -fno-tree-loop-distribute-patterns.
+ * gcc.target/aarch64/sve/single_1.c: Likewise.
+ * gcc.target/aarch64/sve/single_2.c: Likewise.
+ * gcc.target/aarch64/sve/single_3.c: Likewise.
+ * gcc.target/aarch64/sve/single_4.c: Likewise.
+ * gcc.target/aarch64/sve/vec_init_1.c: Likewise.
+ * gcc.target/aarch64/vect-fmovd-zero.c: Likewise.
+ * gcc.target/aarch64/vect-fmovf-zero.c: Likewise.
+ * gcc.target/arm/ivopts.c: Likewise.
+
+2019-05-27 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/90637
+ * gcc.dg/gomp/pr90637.c: New testcase.
+
+2019-05-27 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gnat.dg/expect2.adb: New test.
+ * gnat.dg/expect2_pkg.ads: New helper.
+
+2019-05-27 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gnat.dg/aliased2.adb: New test.
+
+2019-05-27 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gnat.dg/limited_with7.ad[sb]: New test.
+ * gnat.dg/limited_with7_pkg.ads: New helper.
+
+2019-05-27 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gnat.dg/unchecked_convert13.adb: New test.
+
+2019-05-27 Richard Biener <rguenther@suse.de>
+
+ PR testsuite/90615
+ * gcc.dg/vect/costmodel/ppc/costmodel-vect-31b.c: Add
+ -fno-tree-loop-distribute-patterns.
+ * gcc.dg/vect/costmodel/ppc/costmodel-vect-33.c: Likewise.
+ * gcc.dg/vect/costmodel/ppc/costmodel-vect-76a.c: Likewise.
+ * gcc.dg/vect/costmodel/ppc/costmodel-vect-76b.c: Likewise.
+ * gcc.dg/vect/costmodel/ppc/costmodel-vect-76c.c: Likewise.
+ * gcc.target/powerpc/vsx-vectorize-1.c: Likewise.
+
+2019-05-26 Iain Sandoe <iain@sandoe.co.uk>
+
+ * gcc.target/i386/pr39013-1.c: Adjust scan-asms for PIE to
+ account for PIC code on Darwin.
+ * gcc.target/i386/pr39013-2.c: Likewise.
+ * gcc.target/i386/pr64317.c: Likewise.
+
+2019-05-25 Iain Sandoe <iain@sandoe.co.uk>
+
+ * gcc.target/i386/pr59874-3.c: Use the spelling of popcnt
+ expected for Darwin.
+
+2019-05-25 Iain Sandoe <iain@sandoe.co.uk>
+
+ * gcc.target/i386/pr89261.c: Test that the alignment required
+ by the test correctly produces the expected error on Darwin.
+
+2019-05-25 Iain Sandoe <iain@sandoe.co.uk>
+
+ * gcc.target/i386/pr82659-3.c: Require alias support.
+
+2019-05-25 Marek Polacek <polacek@redhat.com>
+
+ PR c++/90572 - wrong disambiguation in friend declaration.
+ * g++.dg/cpp2a/typename16.C: New test.
+ * g++.dg/parse/friend13.C: New test.
+
+2019-05-24 Jakub Jelinek <jakub@redhat.com>
+
+ * c-c++-common/gomp/lastprivate-conditional-2.c (foo): Don't expect
+ sorry for omp for.
+ * c-c++-common/gomp/lastprivate-conditional-3.c: New test.
+
+2019-05-24 Richard Biener <rguenther@suse.de>
+
+ PR testsuite/90607
+ * gcc.dg/pr53265.c: Amend for new expected diagnostic.
+
+2019-05-24 Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/90106
+ PR testsuite/90517
+ * gcc.dg/cdce1.c: Don't scan-assembler, instead -fdump-tree-optimized
+ and scan-tree-dump for tail call.
+ * gcc.dg/cdce2.c: Likewise.
+
+2019-05-24 Iain Sandoe <iain@sandoe.co.uk>
+
+ * gcc.target/i386/pconfig-1.c: Scan for the string in the generated
+ code, not in comments or miscellaneous directives.
+ * gcc.target/i386/pr18041-1.c: Likewise.
+ * gcc.target/i386/pr18041-2.c: Likewise.
+ * gcc.target/i386/wbinvd-1.c: Likewise.
+ * gcc.target/i386/wbnoinvd-1.c: Likewise.
+ * gcc.target/i386/pr66819-3.c: Specifically, check that there is no
+ call to "bar".
+ * gcc.target/i386/pr66819-4.c: Likewise.
+ * gcc.target/i386/pr82662.c
+ * gcc.target/i386/ptwrite2.c: Make the checks look for the specific
+ destination register, don't try the m32 test on m64 targets.
+
+2019-05-24 Iain Sandoe <iain@sandoe.co.uk>
+
+ * gcc.target/i386/pr67985-2.c: Adjust label checks for
+ Darwin.
+ * gcc.target/i386/pr77881.c: Likewise.
+
+2019-05-24 Iain Sandoe <iain@sandoe.co.uk>
+
+ * gcc.target/i386/falign-functions-2.c: Skip for Darwin.
+ * gcc.target/i386/pr70738-7.c: Likewise.
+ * gcc.target/i386/pr24414.c: Likewise.
+
+2019-05-23 Iain Sandoe <iain@sandoe.co.uk>
+
+ * lib/target-supports.exp (check_effective_target_mfentry): New.
+ * gcc.target/i386/fentry-override.c: Require effective target mfentry.
+ * gcc/testsuite/gcc.target/i386/fentry.c: Likewise
+ * gcc.target/i386/fentryname1.c: Likewise
+ * gcc.target/i386/fentryname2.c: Likewise
+ * gcc.target/i386/fentryname3.c: Likewise
+ * gcc.target/i386/nop-mcount.c: Likewise
+ * gcc.target/i386/pr82699-2.c: Likewise
+ * gcc.target/i386/pr82699-4.c: Likewise
+ * gcc.target/i386/pr82699-5.c: Likewise
+ * gcc.target/i386/pr82699-6.c: Likewise
+ * gcc.target/i386/returninst1.c: Likewise
+ * gcc.target/i386/returninst2.c: Likewise
+ * gcc.target/i386/returninst3.c : Likewise
+
+2019-05-23 Bill Schmidt <wschmidt@linux.ibm.com>
+
+ * gcc.target/powerpc/localentry-1.c: New file.
+
+2019-05-23 Uroš Bizjak <ubizjak@gmail.com>
+
+ PR target/90552
+ * gcc.target/i386/pr90552.c: New test.
+
+2019-05-23 Mark Eggleston <mark.eggleston@codethink.com>
+
+ * gfortran.dg/fmt_f_default_field_width_1.f90: Hide REAL(16) behind
+ __GFC_REAL_16__. Add -cpp to dg-options.
+ * gfortran.dg/fmt_f_default_field_width_2.f90: Ditto.
+ * gfortran.dg/fmt_f_default_field_width_3.f90: Ditto.
+ * gfortran.dg/fmt_g_default_field_width_1.f90: Ditto.
+ * gfortran.dg/fmt_g_default_field_width_2.f90: Ditto.
+ * gfortran.dg/fmt_g_default_field_width_3.f90: Ditto.
+
+2019-05-23 Bill Schmidt <wschmidt@linux.ibm.com>
+
+ * gcc.target/powerpc/cpu-future.c: New test.
+
+2019-05-23 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/88440
+ * gcc.dg/tree-ssa/ldist-37.c: New testcase.
+ * gcc.dg/tree-ssa/ldist-38.c: Likewise.
+ * gcc.dg/vect/vect.exp: Add -fno-tree-loop-distribute-patterns.
+ * gcc.dg/tree-ssa/ldist-37.c: Adjust.
+ * gcc.dg/tree-ssa/ldist-38.c: Likewise.
+ * g++.dg/tree-ssa/pr78847.C: Likewise.
+ * gcc.dg/autopar/pr39500-1.c: Likewise.
+ * gcc.dg/autopar/reduc-1char.c: Likewise.
+ * gcc.dg/autopar/reduc-7.c: Likewise.
+ * gcc.dg/tree-ssa/ivopts-lt-2.c: Likewise.
+ * gcc.dg/tree-ssa/ivopts-lt.c: Likewise.
+ * gcc.dg/tree-ssa/predcom-dse-1.c: Likewise.
+ * gcc.dg/tree-ssa/predcom-dse-2.c: Likewise.
+ * gcc.dg/tree-ssa/predcom-dse-3.c: Likewise.
+ * gcc.dg/tree-ssa/predcom-dse-4.c: Likewise.
+ * gcc.dg/tree-ssa/prefetch-7.c: Likewise.
+ * gcc.dg/tree-ssa/prefetch-8.c: Likewise.
+ * gcc.dg/tree-ssa/prefetch-9.c: Likewise.
+ * gcc.dg/tree-ssa/scev-11.c: Likewise.
+ * gcc.dg/vect/costmodel/i386/costmodel-vect-31.c: Likewise.
+ * gcc.dg/vect/costmodel/i386/costmodel-vect-33.c: Likewise.
+ * gcc.dg/vect/costmodel/x86_64/costmodel-vect-31.c: Likewise.
+ * gcc.dg/vect/costmodel/x86_64/costmodel-vect-33.c: Likewise.
+ * gcc.target/i386/pr30970.c: Likewise.
+ * gcc.target/i386/vect-double-1.c: Likewise.
+ * gcc.target/i386/vect-double-2.c: Likewise.
+ * gcc.dg/tree-ssa/gen-vect-2.c: Likewise.
+ * gcc.dg/tree-ssa/gen-vect-26.c: Likewise.
+ * gcc.dg/tree-ssa/gen-vect-28.c: Likewise.
+ * gcc.dg/tree-ssa/gen-vect-32.c: Likewise.
+ * gfortran.dg/vect/vect-5.f90: Likewise.
+ * gfortran.dg/vect/vect-8.f90: Likewise.
+
+2019-05-23 Martin Liska <mliska@suse.cz>
+
+ PR sanitizer/90570
+ * g++.dg/asan/pr90570.C: New test.
+
+2019-05-23 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gnat.dg/opt78.ad[sb]: New test.
+
+2019-05-23 Iain Sandoe <iain@sandoe.co.uk>
+
+ PR rtl-optimisation/64895
+ * gcc.target/i386/fuse-caller-save-rec.c: Remove XFAILs.
+ * gcc.target/i386/fuse-caller-save.c: Likewise.
+ * gcc.target/i386/fuse-caller-save-xmm.c: Adjust tests for
+ PIC cases, remove XFAILs.
+
+2019-05-23 Thomas Schwinge <thomas@codesourcery.com>
+
+ PR middle-end/90510
+ * brig.dg/test/gimple/packed.hsail: Adjust.
+
+2019-05-23 Jakub Jelinek <jakub@redhat.com>
+
+ * g++.dg/cpp2a/is-constant-evaluated8.C: New test.
+
+2019-05-23 Hans-Peter Nilsson <hp@axis.com>
+
+ * gfortran.dg/dec_io_1.f90, gfortran.dg/dtio_1.f90,
+ gfortran.dg/dtio_12.f90, gfortran.dg/fmt_en.f90,
+ gfortran.dg/namelist_89.f90: Gate test on effective_target
+ fd_truncate.
+
+2019-05-22 David Malcolm <dmalcolm@redhat.com>
+
+ PR c++/90462
+ * g++.dg/pr90462.C: New test.
+
+2019-05-22 Marek Polacek <polacek@redhat.com>
+
+ * g++.dg/cpp1y/udlit-char-template-neg.C: Expect the error on a
+ different line. Check the column number too.
+
+2019-05-22 Uroš Bizjak <ubizjak@gmail.com>
+
+ * gcc.target/i386/vect-signbitf.c (dg-final): Improve
+ scan-assembler-not string to avoid false matching on 32bit targets.
+
+2019-05-22 H.J. Lu <hongjiu.lu@intel.com>
+
+ PR target/88483
+ * gcc.target/i386/stackalign/pr88483-1.c: New test.
+ * gcc.target/i386/stackalign/pr88483-2.c: Likewise.
+
+2019-05-22 Andrew Stubbs <ams@codesourcery.com>
+
+ * gfortran.dg/coarray_lock_7.f90: Fix output patterns.
+
+2019-05-22 Mark Eggleston <mark.eggleston@codethink.com>
+
+ PR fortran/89100
+ * gfortran.dg/fmt_f_default_field_width_1.f90: New test.
+ * gfortran.dg/fmt_f_default_field_width_2.f90: New test.
+ * gfortran.dg/fmt_f_default_field_width_3.f90: New test.
+ * gfortran.dg/fmt_g_default_field_width_1.f90: New test.
+ * gfortran.dg/fmt_g_default_field_width_2.f90: New test.
+ * gfortran.dg/fmt_g_default_field_width_3.f90: New test.
+ * gfortran.dg/fmt_i_default_field_width_1.f90: New test.
+ * gfortran.dg/fmt_i_default_field_width_2.f90: New test.
+ * gfortran.dg/fmt_i_default_field_width_3.f90: New test.
+
+2019-05-22 Martin Liska <mliska@suse.cz>
+
+ PR testsuite/90564
+ * gcc.target/powerpc/pr80315-1.c: Remove usage of quotes.
+ * gcc.target/powerpc/pr80315-2.c: Likewise.
+ * gcc.target/powerpc/pr80315-3.c: Likewise.
+ * gcc.target/powerpc/pr80315-4.c: Likewise.
+
+2019-05-22 Martin Liska <mliska@suse.cz>
+
+ PR testsuite/90564
+ * gcc.target/powerpc/pr80315-1.c: Add one extra \ to escape brackets.
+ * gcc.target/powerpc/pr80315-2.c: Likewise.
+ * gcc.target/powerpc/pr80315-3.c: Likewise.
+ * gcc.target/powerpc/pr80315-4.c: Likewise.
+
+2019-05-22 Iain Sandoe <iain@sandoe.co.uk>
+
+ PR testsuite/27221
+ * g++.dg/ext/alignof2.C: XFAIL for 32bit Darwin.
+
+2019-05-22 Martin Liska <mliska@suse.cz>
+
+ PR lto/90500
+ * gcc.target/i386/pr90500-1.c: Make the test-case valid now.
+
+2019-05-22 Richard Biener <rguenther@suse.de>
+
+ * gcc.dg/tree-ssa/ssa-lim-13.c: New testcase.
+
+2019-05-22 Hans-Peter Nilsson <hp@axis.com>
+
+ PR middle-end/90553
+ * gcc.dg/torture/pr90553.c: New test.
+
+2019-05-21 Paolo Carlini <paolo.carlini@oracle.com>
+
+ * g++.dg/cpp0x/udlit-tmpl-arg-neg2.C: Check locations too.
+ * g++.dg/cpp0x/udlit-tmpl-parms-neg.C: Likewise.
+
+2019-05-21 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/67184
+ PR c++/69445
+ * g++.dg/other/final3.C: New.
+ * g++.dg/other/final4.C: Likewise.
+ * g++.dg/other/final5.C: Likewise.
+
+2019-05-21 Marek Polacek <polacek@redhat.com>
+
+ DR 1940 - static_assert in anonymous unions.
+ * g++.dg/DRs/dr1940.C: New test.
+
+2019-05-21 Uroš Bizjak <ubizjak@gmail.com>
+
+ PR target/90547
+ * gcc.target/i386/pr90547.c: New test.
+
+2019-05-21 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE>
+
+ * gcc.dg/Wattribute-alias.c: Pass emtpy arg to dg-require-ifunc.
+
+ * gcc.c-torture/execute/20030125-1.c: Pass emtpy arg to dg-require-weak.
+
+ * gcc.dg/torture/ftrapv-2.c: Pass empty arg to dg-require-fork.
+
+ * gcc.target/i386/pr84723-1.c: Remove dg-require-ifunc.
+ * gcc.target/i386/pr84723-2.c: Likewise.
+ * gcc.target/i386/pr84723-3.c: Likewise.
+ * gcc.target/i386/pr84723-4.c: Likewise.
+ * gcc.target/i386/pr84723-5.c: Likewise.
+
+2019-05-21 Iain Sandoe <iain@sandoe.co.uk>
+
+ PR testsuite/67958
+ * gcc.target/i386/pr32219-1.c: Adjust scan-asms for Darwin, comment
+ the differences.
+ * gcc.target/i386/pr32219-2.c: Likewise.
+ * gcc.target/i386/pr32219-3.c: Likewise.
+ * gcc.target/i386/pr32219-4.c: Likewise.
+ * gcc.target/i386/pr32219-5.c: Likewise.
+ * gcc.target/i386/pr32219-6.c: Likewise.
+ * gcc.target/i386/pr32219-7.c: Likewise.
+ * gcc.target/i386/pr32219-8.c: Likewise.
+
+2019-05-21 Iain Sandoe <iain@sandoe.co.uk>
+
+ PR target/63891
+ * gcc.dg/darwin-weakimport-3.c: Adjust options and explain
+ the reasons.
+
+2019-05-21 Uroš Bizjak <ubizjak@gmail.com>
+
+ * gcc.target/i386/vect-signbitf.c: New test.
+
+2019-05-21 Nathan Sidwell <nathan@acm.org>
+
+ * g++.dg/lookup/using53.C: Adjust diagnostic.
+
+2019-05-21 Richard Biener <rguenther@suse.de>
+
+ PR middle-end/90510
+ * gcc.target/i386/pr90510.c: New testcase.
+
+2019-05-21 Martin Liska <mliska@suse.cz>
+
+ * gcc.target/i386/pr90500-1.c: Add missing '""'.
+ * gcc.target/i386/pr90500-2.c: Likewise.
+
+2019-05-21 Vladislav Ivanishin <vlad@ispras.ru>
+
+ * gcc.dg/uninit-28-gimple.c: New test.
+ * gcc.dg/uninit-29-gimple.c: New test.
+ * gcc.dg/uninit-30-gimple.c: New test.
+ * gcc.dg/uninit-31-gimple.c: New test.
+
+2019-05-21 Martin Liska <mliska@suse.cz>
+
+ * gcc.dg/pr90263.c: Add -O2.
+
+2019-05-21 Martin Liska <mliska@suse.cz>
+
+ * gcc.target/powerpc/ppc64-abi-warn-1.c: Wrap a type.
+ * gcc.target/powerpc/pr80315-1.c: Use new interval format.
+ * gcc.target/powerpc/pr80315-2.c: Likewise.
+ * gcc.target/powerpc/pr80315-3.c: Likewise.
+ * gcc.target/powerpc/pr80315-4.c: Likewise.
+ * gcc.target/powerpc/warn-lvsl-lvsr.c: Wrap builtin names.
+
+2019-05-21 Martin Liska <mliska@suse.cz>
+
+ PR testsuite/90551
+ * pr90263.c: Move from gcc.c-torture/compile
+ into gcc.dg.
+
+2019-05-20 Uroš Bizjak <ubizjak@gmail.com>
+
+ PR testsuite/90503
+ * gcc.target/i386/pr22076.c (dg-options): Add -mno-sse2.
+ Remove -flax-vector-conversions.
+ (dg-additional-options): Remove.
+ (test): Change to void. Declare m0 and m1 as __m64 and
+ cast initializer in a proper way. Do not return result.
+ (dg-final): Scan for 2 instances of movq.
+
+2019-05-20 Marek Polacek <polacek@redhat.com>
+
+ CWG 2094 - volatile scalars are trivially copyable.
+ PR c++/85679
+ * g++.dg/ext/is_trivially_constructible1.C: Change the expected result
+ for volatile int.
+ * g++.dg/ext/is_trivially_copyable.C: New test.
+
+2019-05-20 Marek Polacek <polacek@redhat.com>
+
+ * g++.dg/ext/utf8-2.C: Accept both "char" and "char8_t" in aka.
+
+ * g++.dg/cpp2a/nontype-class17.C: New test.
+
+ * g++.dg/lookup/strong-using2.C: New test.
+
+2019-05-20 Jeff Law <law@redhat.com>
+
+ * gcc.dg/Wtype-limits-Wextra.c: Adjust expected output after
+ recent diagnostic cleanups.
+
+2019-05-20 Christophe Lyon <christophe.lyon@linaro.org>
+
+ PR tree-optimization/90106
+ * gcc.dg/cdce3.c: Add hard_float effective target.
+
+2019-05-20 Marc Glisse <marc.glisse@inria.fr>
+
+ * gcc.dg/torture/pta-ptrarith-3.c: Relax the matched pattern.
+
+2019-05-20 Iain Sandoe <iain@sandoe.co.uk>
+
+ PR testsuite/58321
+ * gcc.target/i386/memcpy-strategy-3.c: Adjust count for Darwin and
+ add a comment as to the reason for the difference.
+ * gcc.target/i386/memset-strategy-1.c: Likewise.
+
+2019-05-20 Jonathan Wakely <jwakely@redhat.com>
+
+ PR c++/90532 Ensure __is_constructible(T[]) is false
+ * g++.dg/ext/90532.C: New test.
+
+2019-05-20 Jakub Jelinek <jakub@redhat.com>
+
+ * gcc.target/i386/avx512f-simd-1.c: New test.
+
+2019-05-20 Christophe Lyon <christophe.lyon@linaro.org>
+
+ * gcc.target/aarch64/target_attr_10.c: Add quotes to expected
+ error message.
+ * gcc.target/arm/attr-neon-builtin-fail.c: Likewise.
+
+2019-05-20 Martin Liska <mliska@suse.cz>
+
+ PR middle-end/90263
+ * gcc.c-torture/compile/pr90263.c: New test.
+ * lib/target-supports.exp: Add check_effective_target_glibc.
+
+2019-05-20 Richard Biener <rguenther@suse.de>
+
+ PR testsuite/90518
+ * gcc.dg/gimplefe-40.c: Restrict to targets with appropriate
+ vector support.
+ * gcc.dg/gimplefe-41.c: Likewise.
+
+2019-05-19 Andrew Pinski <apinski@marvell.com>
+
+ PR pch/81721
+ * g++.dg/pch/operator-1.C: New testcase.
+ * g++.dg/pch/operator-1.Hs: New file.
+
+2019-05-19 Paul Thomas <pault@gcc.gnu.org>
+
+ PR fortran/90498
+ * gfortran.dg/associate_48.f90 : New test.
+
+2019-05-19 Thomas Koenig <tkoenig@gcc.gnu.org>
+
+ PR fortran/78290
+ * gfortran.dg/pr78290.f90: New test.
+
+2019-05-19 Thomas Koenig <tkoenig@gcc.gnu.org>
+
+ PR fortran/88821
+ * gfortran.dg/alloc_comp_auto_array_3.f90: Add -O0 to dg-options
+ to make sure the test for internal_pack is retained.
+ * gfortran.dg/assumed_type_2.f90: Split compile and run time
+ tests into this and
+ * gfortran.dg/assumed_type_2a.f90: New file.
+ * gfortran.dg/c_loc_test_22.f90: Likewise.
+ * gfortran.dg/contiguous_3.f90: Likewise.
+ * gfortran.dg/internal_pack_11.f90: Likewise.
+ * gfortran.dg/internal_pack_12.f90: Likewise.
+ * gfortran.dg/internal_pack_16.f90: Likewise.
+ * gfortran.dg/internal_pack_17.f90: Likewise.
+ * gfortran.dg/internal_pack_18.f90: Likewise.
+ * gfortran.dg/internal_pack_4.f90: Likewise.
+ * gfortran.dg/internal_pack_5.f90: Add -O0 to dg-options
+ to make sure the test for internal_pack is retained.
+ * gfortran.dg/internal_pack_6.f90: Split compile and run time
+ tests into this and
+ * gfortran.dg/internal_pack_6a.f90: New file.
+ * gfortran.dg/internal_pack_8.f90: Likewise.
+ * gfortran.dg/missing_optional_dummy_6: Split compile and run time
+ tests into this and
+ * gfortran.dg/missing_optional_dummy_6a.f90: New file.
+ * gfortran.dg/no_arg_check_2.f90: Split compile and run time tests
+ into this and
+ * gfortran.dg/no_arg_check_2a.f90: New file.
+ * gfortran.dg/typebound_assignment_5.f90: Split compile and run time
+ tests into this and
+ * gfortran.dg/typebound_assignment_5a.f90: New file.
+ * gfortran.dg/typebound_assignment_6.f90: Split compile and run time
+ tests into this and
+ * gfortran.dg/typebound_assignment_6a.f90: New file.
+ * gfortran.dg/internal_pack_19.f90: New file.
+ * gfortran.dg/internal_pack_20.f90: New file.
+ * gfortran.dg/internal_pack_21.f90: New file.
+
+2019-05-18 Iain Sandoe <iain@sandoe.co.uk>
+
+ * objc.dg/instancetype-0.m: New.
+
+2019-05-17 Martin Sebor <msebor@redhat.com>
+
+ * gcc.dg/gcc_diag-11.c: Remove accidentally committed test.
+
+ * g++.dg/overload/conv-op1.C: Adjust text of expected messages.
+ * g++.dg/ubsan/pr63956.C: Same.
+ * g++.old-deja/g++.pt/assign1.C: Same.
+
+2019-05-17 Thomas Schwinge <thomas@codesourcery.com>
+
+ PR testsuite/89433
+ * c-c++-common/goacc/routine-5.c: Update.
+ * c-c++-common/goacc/routine-level-of-parallelism-1.c: Likewise.
+ * c-c++-common/goacc/routine-level-of-parallelism-2.c: New file.
+
+ PR testsuite/89433
+ * c-c++-common/goacc/routine-2.c: Update, and move some test
+ into...
+ * c-c++-common/goacc/routine-level-of-parallelism-1.c: ... this
+ new file.
+
+ PR testsuite/89433
+ * c-c++-common/goacc/classify-routine.c: Update.
+ * gfortran.dg/goacc/classify-routine.f95: Likewise.
+
+2019-05-16 Martin Sebor <msebor@redhat.com>
+
+ * c-c++-common/Wbool-operation-1.c: Adjust text of expected diagnostics.
+ * c-c++-common/Wvarargs-2.c: Same.
+ * c-c++-common/Wvarargs.c: Same.
+ * c-c++-common/pr51768.c: Same.
+ * c-c++-common/tm/inline-asm.c: Same.
+ * c-c++-common/tm/safe-1.c: Same.
+ * g++.dg/asm-qual-1.C: Same.
+ * g++.dg/asm-qual-3.C: Same.
+ * g++.dg/conversion/dynamic1.C: Same.
+ * g++.dg/cpp0x/constexpr-89599.C: Same.
+ * g++.dg/cpp0x/constexpr-cast.C: Same.
+ * g++.dg/cpp0x/constexpr-shift1.C: Same.
+ * g++.dg/cpp0x/lambda/lambda-conv11.C: Same.
+ * g++.dg/cpp0x/nullptr04.C: Same.
+ * g++.dg/cpp0x/static_assert12.C: Same.
+ * g++.dg/cpp0x/static_assert8.C: Same.
+ * g++.dg/cpp1y/lambda-conv1.C: Same.
+ * g++.dg/cpp1y/pr79393-3.C: Same.
+ * g++.dg/cpp1y/static_assert1.C: Same.
+ * g++.dg/cpp1z/constexpr-if4.C: Same.
+ * g++.dg/cpp1z/constexpr-if5.C: Same.
+ * g++.dg/cpp1z/constexpr-if9.C: Same.
+ * g++.dg/eh/goto2.C: Same.
+ * g++.dg/eh/goto3.C: Same.
+ * g++.dg/expr/static_cast8.C: Same.
+ * g++.dg/ext/flexary5.C: Same.
+ * g++.dg/ext/utf-array-short-wchar.C: Same.
+ * g++.dg/ext/utf-array.C: Same.
+ * g++.dg/ext/utf8-2.C: Same.
+ * g++.dg/gomp/loop-4.C: Same.
+ * g++.dg/gomp/macro-4.C: Same.
+ * g++.dg/gomp/udr-1.C: Same.
+ * g++.dg/init/initializer-string-too-long.C: Same.
+ * g++.dg/other/offsetof9.C: Same.
+ * g++.dg/ubsan/pr63956.C: Same.
+ * g++.dg/warn/Wbool-operation-1.C: Same.
+ * g++.dg/warn/Wtype-limits-Wextra.C: Same.
+ * g++.dg/warn/Wtype-limits.C: Same.
+ * g++.dg/wrappers/pr88680.C: Same.
+ * g++.old-deja/g++.mike/eh55.C: Same.
+ * gcc.dg/Wsign-compare-1.c: Same.
+ * gcc.dg/Wtype-limits-Wextra.c: Same.
+ * gcc.dg/Wtype-limits.c: Same.
+ * gcc.dg/Wunknownprag.c: Same.
+ * gcc.dg/Wunsuffixed-float-constants-1.c: Same.
+ * gcc.dg/asm-6.c: Same.
+ * gcc.dg/asm-qual-1.c: Same.
+ * gcc.dg/cast-1.c: Same.
+ * gcc.dg/cast-2.c: Same.
+ * gcc.dg/cast-3.c: Same.
+ * gcc.dg/cpp/source_date_epoch-2.c: Same.
+ * gcc.dg/debug/pr85252.c: Same.
+ * gcc.dg/dfp/cast-bad.c: Same.
+ * gcc.dg/format/gcc_diag-1.c: Same.
+ * gcc.dg/format/gcc_diag-11.c: Same.
+ * gcc.dg/gcc_diag-11.c: Same.
+ * gcc.dg/gnu-cond-expr-2.c: Same.
+ * gcc.dg/gnu-cond-expr-3.c: Same.
+ * gcc.dg/gomp/macro-4.c: Same.
+ * gcc.dg/init-bad-1.c: Same.
+ * gcc.dg/init-bad-2.c: Same.
+ * gcc.dg/init-bad-3.c: Same.
+ * gcc.dg/pr27528.c: Same.
+ * gcc.dg/pr48552-1.c: Same.
+ * gcc.dg/pr48552-2.c: Same.
+ * gcc.dg/pr59846.c: Same.
+ * gcc.dg/pr61096-1.c: Same.
+ * gcc.dg/pr8788-1.c: Same.
+ * gcc.dg/pr90082.c: Same.
+ * gcc.dg/simd-2.c: Same.
+ * gcc.dg/spellcheck-params-2.c: Same.
+ * gcc.dg/spellcheck-params.c: Same.
+ * gcc.dg/strlenopt-49.c: Same.
+ * gcc.dg/tm/pr52141.c: Same.
+ * gcc.dg/torture/pr51106-1.c: Same.
+ * gcc.dg/torture/pr51106-2.c: Same.
+ * gcc.dg/utf-array-short-wchar.c: Same.
+ * gcc.dg/utf-array.c: Same.
+ * gcc.dg/utf8-2.c: Same.
+ * gcc.dg/warn-sprintf-no-nul.c: Same.
+ * gcc.target/i386/asm-flag-0.c: Same.
+ * gcc.target/i386/inline_error.c: Same.
+ * gcc.target/i386/pr30848.c: Same.
+ * gcc.target/i386/pr39082-1.c: Same.
+ * gcc.target/i386/pr39678.c: Same.
+ * gcc.target/i386/pr57756.c: Same.
+ * gcc.target/i386/pr68843-1.c: Same.
+ * gcc.target/i386/pr79804.c: Same.
+ * gcc.target/i386/pr82673.c: Same.
+ * obj-c++.dg/class-protocol-1.mm: Same.
+ * obj-c++.dg/exceptions-3.mm: Same.
+ * obj-c++.dg/exceptions-4.mm: Same.
+ * obj-c++.dg/exceptions-5.mm: Same.
+ * obj-c++.dg/exceptions-6.mm: Same.
+ * obj-c++.dg/method-12.mm: Same.
+ * obj-c++.dg/method-13.mm: Same.
+ * obj-c++.dg/method-6.mm: Same.
+ * obj-c++.dg/method-7.mm: Same.
+ * obj-c++.dg/method-9.mm: Same.
+ * obj-c++.dg/method-lookup-1.mm: Same.
+ * obj-c++.dg/proto-lossage-4.mm: Same.
+ * obj-c++.dg/protocol-qualifier-2.mm: Same.
+ * objc.dg/call-super-2.m: Same.
+ * objc.dg/class-protocol-1.m: Same.
+ * objc.dg/desig-init-1.m: Same.
+ * objc.dg/exceptions-3.m: Same.
+ * objc.dg/exceptions-4.m: Same.
+ * objc.dg/exceptions-5.m: Same.
+ * objc.dg/exceptions-6.m: Same.
+ * objc.dg/method-19.m: Same.
+ * objc.dg/method-2.m: Same.
+ * objc.dg/method-5.m: Same.
+ * objc.dg/method-6.m: Same.
+ * objc.dg/method-7.m: Same.
+ * objc.dg/method-lookup-1.m: Same.
+ * objc.dg/proto-hier-1.m: Same.
+ * objc.dg/proto-lossage-4.m: Same.
+
+2019-05-17 Dragan Mladjenovic <dmladjenovic@wavecomp.com>
+
+ * g++.dg/eh/o32-fp.C: New.
+ * gcc.target/mips/dwarfregtable-1.c: New.
+ * gcc.target/mips/dwarfregtable-2.c: New.
+ * gcc.target/mips/dwarfregtable-3.c: New.
+ * gcc.target/mips/dwarfregtable-4.c: New.
+ * gcc.target/mips/dwarfregtable.h: New.
+
+2019-05-17 H.J. Lu <hongjiu.lu@intel.com>
+
+ * gcc.target/x86_64/abi/test_varargs-m128.c: New file.
+ * gcc.target/x86_64/abi/avx/test_varargs-m256.c: Likewise.
+ * gcc.target/x86_64/abi/avx512f/test_varargs-m512.c: Likewise.
+
+2019-05-17 H.J. Lu <hongjiu.lu@intel.com>
+
+ PR target/90497
+ * gcc.target/i386/pr90497-1.c: New test.
+ * gcc.target/i386/pr90497-2.c: Likewise.
+
+2019-05-17 Robin Dapp <rdapp@linux.ibm.com>
+
+ * gcc.target/s390/global-array-element-pic.c: Add -march=z900.
+ * gcc.target/s390/global-array-element-pic2.c: New test for z10+.
+
+2019-05-17 Richard Biener <rguenther@suse.de>
+
+ * gcc.dg/gimplefe-41.c: New testcase.
+
+2019-05-17 Jun Ma <JunMa@linux.alibaba.com>
+
+ PR tree-optimization/90106
+ * gcc.dg/cdce3.c: New test.
+
+2019-05-17 Andreas Krebbel <krebbel@linux.ibm.com>
+
+ * gcc.target/s390/zvector/vec-sldw.c: New test.
+
+2019-05-17 Martin Liska <mliska@suse.cz>
+
+ PR middle-end/90478
+ * gcc.dg/tree-ssa/pr90478-2.c: Remove.
+
+2019-05-16 Jakub Jelinek <jakub@redhat.com>
+
+ * gcc.dg/vect/vect-simd-1.c: New test.
+ * gcc.dg/vect/vect-simd-2.c: New test.
+ * gcc.dg/vect/vect-simd-3.c: New test.
+ * gcc.dg/vect/vect-simd-4.c: New test.
+
+2019-05-16 Martin Liska <mliska@suse.cz>
+
+ PR lto/90500
+ * gcc.target/i386/pr90500-1.c: New test.
+ * gcc.target/i386/pr90500-2.c: New test.
+
+2019-05-16 Vladislav Ivanishin <vlad@ispras.ru>
+
+ PR tree-optimization/90394
+ * gcc.dg/uninit-pr90394-1-gimple.c: New test.
+ * gcc.dg/uninit-pr90394.c: New test.
+
+2019-05-16 Richard Biener <rguenther@suse.de>
+
+ PR testsuite/90502
+ * gcc.dg/tree-ssa/vector-6.c: Adjust for half of the
+ transforms happening earlier now.
+
+2019-05-16 Iain Sandoe <iain@sandoe.co.uk>
+
+ * lib/target-supports.exp (check_effective_target_cet): Add the
+ -fcf-protection flag to the build conditions.
+
+2019-05-16 Jun Ma <JunMa@linux.alibaba.com>
+
+ PR tree-optimization/90106
+ * gcc.dg/cdce1.c: Check tailcall code generation after cdce pass.
+ * gcc.dg/cdce2.c: Likewise.
+
+2019-05-16 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/90424
+ * g++.target/i386/pr90424-1.C: New testcase.
+ * g++.target/i386/pr90424-2.C: Likewise.
+
+2019-05-16 Richard Biener <rguenther@suse.de>
+
+ * gcc.dg/gimplefe-40.c: Amend again.
+
+2019-05-15 Cherry Zhang <cherryyz@google.com>
+
+ * go.test/test/nilptr2.go: Change use function to actually do
+ something.
+
+2019-05-16 Jakub Jelinek <jakub@redhat.com>
+
+ PR middle-end/90478
+ * gcc.dg/tree-ssa/pr90478.c: Add empty dg-options. Use long long type
+ instead of long.
+
+ * c-c++-common/gomp/simd8.c: New test.
+
+2019-05-15 Marek Polacek <polacek@redhat.com>
+
+ CWG 2096 - constraints on literal unions.
+ * g++.dg/cpp0x/literal-type1.C: New test.
+
+2019-05-15 Janne Blomqvist <jb@gcc.gnu.org>
+
+ PR fortran/90461
+ * gfortran.dg/open_errors_2.f90: Add -std=f2008, adjust line number.
+ * gfortran.dg/open_errors_3.f90: New test.
+
+2019-05-15 H.J. Lu <hongjiu.lu@intel.com>
+
+ PR target/89021
+ * gcc.target/i386/mmx-vals.h: New file.
+ * gcc.target/i386/sse2-mmx-2.c: Likewise.
+ * gcc.target/i386/sse2-mmx-3.c: Likewise.
+ * gcc.target/i386/sse2-mmx-4.c: Likewise.
+ * gcc.target/i386/sse2-mmx-5.c: Likewise.
+ * gcc.target/i386/sse2-mmx-6.c: Likewise.
+ * gcc.target/i386/sse2-mmx-7.c: Likewise.
+ * gcc.target/i386/sse2-mmx-8.c: Likewise.
+ * gcc.target/i386/sse2-mmx-9.c: Likewise.
+ * gcc.target/i386/sse2-mmx-10.c: Likewise.
+ * gcc.target/i386/sse2-mmx-11.c: Likewise.
+ * gcc.target/i386/sse2-mmx-12.c: Likewise.
+ * gcc.target/i386/sse2-mmx-13.c: Likewise.
+ * gcc.target/i386/sse2-mmx-14.c: Likewise.
+ * gcc.target/i386/sse2-mmx-15.c: Likewise.
+ * gcc.target/i386/sse2-mmx-16.c: Likewise.
+ * gcc.target/i386/sse2-mmx-17.c: Likewise.
+ * gcc.target/i386/sse2-mmx-18a.c: Likewise.
+ * gcc.target/i386/sse2-mmx-18b.c: Likewise.
+ * gcc.target/i386/sse2-mmx-18c.c: Likewise.
+ * gcc.target/i386/sse2-mmx-19a.c: Likewise.
+ * gcc.target/i386/sse2-mmx-18b.c: Likewise.
+ * gcc.target/i386/sse2-mmx-19c.c: Likewise.
+ * gcc.target/i386/sse2-mmx-19d.c: Likewise.
+ * gcc.target/i386/sse2-mmx-19e.c: Likewise.
+ * gcc.target/i386/sse2-mmx-20.c: Likewise.
+ * gcc.target/i386/sse2-mmx-21.c: Likewise.
+ * gcc.target/i386/sse2-mmx-22.c: Likewise.
+ * gcc.target/i386/sse2-mmx-cvtpi2ps.c: Likewise.
+ * gcc.target/i386/sse2-mmx-cvtps2pi.c: Likewise.
+ * gcc.target/i386/sse2-mmx-cvttps2pi.c: Likewise.
+ * gcc.target/i386/sse2-mmx-maskmovq.c: Likewise.
+ * gcc.target/i386/sse2-mmx-packssdw.c: Likewise.
+ * gcc.target/i386/sse2-mmx-packsswb.c: Likewise.
+ * gcc.target/i386/sse2-mmx-packuswb.c: Likewise.
+ * gcc.target/i386/sse2-mmx-paddb.c: Likewise.
+ * gcc.target/i386/sse2-mmx-paddd.c: Likewise.
+ * gcc.target/i386/sse2-mmx-paddq.c: Likewise.
+ * gcc.target/i386/sse2-mmx-paddsb.c: Likewise.
+ * gcc.target/i386/sse2-mmx-paddsw.c: Likewise.
+ * gcc.target/i386/sse2-mmx-paddusb.c: Likewise.
+ * gcc.target/i386/sse2-mmx-paddusw.c: Likewise.
+ * gcc.target/i386/sse2-mmx-paddw.c: Likewise.
+ * gcc.target/i386/sse2-mmx-pand.c: Likewise.
+ * gcc.target/i386/sse2-mmx-pandn.c: Likewise.
+ * gcc.target/i386/sse2-mmx-pavgb.c: Likewise.
+ * gcc.target/i386/sse2-mmx-pavgw.c: Likewise.
+ * gcc.target/i386/sse2-mmx-pcmpeqb.c: Likewise.
+ * gcc.target/i386/sse2-mmx-pcmpeqd.c: Likewise.
+ * gcc.target/i386/sse2-mmx-pcmpeqw.c: Likewise.
+ * gcc.target/i386/sse2-mmx-pcmpgtb.c: Likewise.
+ * gcc.target/i386/sse2-mmx-pcmpgtd.c: Likewise.
+ * gcc.target/i386/sse2-mmx-pcmpgtw.c: Likewise.
+ * gcc.target/i386/sse2-mmx-pextrw.c: Likewise.
+ * gcc.target/i386/sse2-mmx-pinsrw.c: Likewise.
+ * gcc.target/i386/sse2-mmx-pmaddwd.c: Likewise.
+ * gcc.target/i386/sse2-mmx-pmaxsw.c: Likewise.
+ * gcc.target/i386/sse2-mmx-pmaxub.c: Likewise.
+ * gcc.target/i386/sse2-mmx-pminsw.c: Likewise.
+ * gcc.target/i386/sse2-mmx-pminub.c: Likewise.
+ * gcc.target/i386/sse2-mmx-pmovmskb.c: Likewise.
+ * gcc.target/i386/sse2-mmx-pmulhuw.c: Likewise.
+ * gcc.target/i386/sse2-mmx-pmulhw.c: Likewise.
+ * gcc.target/i386/sse2-mmx-pmullw.c: Likewise.
+ * gcc.target/i386/sse2-mmx-pmuludq.c: Likewise.
+ * gcc.target/i386/sse2-mmx-por.c: Likewise.
+ * gcc.target/i386/sse2-mmx-psadbw.c: Likewise.
+ * gcc.target/i386/sse2-mmx-pshufw.c: Likewise.
+ * gcc.target/i386/sse2-mmx-pslld.c: Likewise.
+ * gcc.target/i386/sse2-mmx-pslldi.c: Likewise.
+ * gcc.target/i386/sse2-mmx-psllq.c: Likewise.
+ * gcc.target/i386/sse2-mmx-psllqi.c: Likewise.
+ * gcc.target/i386/sse2-mmx-psllw.c: Likewise.
+ * gcc.target/i386/sse2-mmx-psllwi.c: Likewise.
+ * gcc.target/i386/sse2-mmx-psrad.c: Likewise.
+ * gcc.target/i386/sse2-mmx-psradi.c: Likewise.
+ * gcc.target/i386/sse2-mmx-psraw.c: Likewise.
+ * gcc.target/i386/sse2-mmx-psrawi.c: Likewise.
+ * gcc.target/i386/sse2-mmx-psrld.c: Likewise.
+ * gcc.target/i386/sse2-mmx-psrldi.c: Likewise.
+ * gcc.target/i386/sse2-mmx-psrlq.c: Likewise.
+ * gcc.target/i386/sse2-mmx-psrlqi.c: Likewise.
+ * gcc.target/i386/sse2-mmx-psrlw.c: Likewise.
+ * gcc.target/i386/sse2-mmx-psrlwi.c: Likewise.
+ * gcc.target/i386/sse2-mmx-psubb.c: Likewise.
+ * gcc.target/i386/sse2-mmx-psubd.c: Likewise.
+ * gcc.target/i386/sse2-mmx-psubq.c: Likewise.
+ * gcc.target/i386/sse2-mmx-psubusb.c: Likewise.
+ * gcc.target/i386/sse2-mmx-psubusw.c: Likewise.
+ * gcc.target/i386/sse2-mmx-psubw.c: Likewise.
+ * gcc.target/i386/sse2-mmx-punpckhbw.c: Likewise.
+ * gcc.target/i386/sse2-mmx-punpckhdq.c: Likewise.
+ * gcc.target/i386/sse2-mmx-punpckhwd.c: Likewise.
+ * gcc.target/i386/sse2-mmx-punpcklbw.c: Likewise.
+ * gcc.target/i386/sse2-mmx-punpckldq.c: Likewise.
+ * gcc.target/i386/sse2-mmx-punpcklwd.c: Likewise.
+ * gcc.target/i386/sse2-mmx-pxor.c: Likewise.
+
+2019-05-15 H.J. Lu <hongjiu.lu@intel.com>
+
+ PR target/89021
+ * config/i386/i386-builtins.c (bdesc_tm): Enable MMX intrinsics
+ with SSE2.
+
+2019-05-15 H.J. Lu <hongjiu.lu@intel.com>
+
+ PR target/89021
+ * gcc.target/i386/pr82483-1.c: Error only on ia32.
+ * gcc.target/i386/pr82483-2.c: Likewise.
+
+2019-05-15 Martin Liska <mliska@suse.cz>
+
+ PR middle-end/90478
+ * gcc.dg/tree-ssa/pr90478-2.c: New test.
+ * gcc.dg/tree-ssa/pr90478.c: New test.
+
+2019-05-15 Richard Biener <rguenther@suse.de>
+
+ * gcc.dg/gimplefe-40.c: Amend.
+
+2019-05-15 Iain Sandoe <iain@sandoe.co.uk>
+
+ * lib/target-supports.exp
+ (check_effective_target_powerpc_p8vector_ok): No support for Darwin.
+ (check_effective_target_powerpc_p9vector_ok): Likewise.
+ (check_effective_target_powerpc_float128_sw_ok): Likewise.
+ (check_effective_target_powerpc_float128_hw_ok): Likewise.
+ (check_effective_target_powerpc_vsx_ok): Likewise.
+ * gcc.target/powerpc/bfp/bfp.exp: Don't try to run this for Darwin.
+ * gcc.target/powerpc/dfp/dfp.exp: Likewise.
+
+2019-05-15 Iain Sandoe <iain@sandoe.co.uk>
+
+ * gcc.dg/pr87600.h: Add __POWERPC__ as an alternate test
+ for PowerPC platforms.
+
+2019-05-15 Iain Sandoe <iain@sandoe.co.uk>
+
+ PR target/82920
+ * g++.dg/cet-notrack-1.C: Adjust scan assembler for Darwin.
+ * gcc.target/i386/cet-notrack-5a.c: Likewise.
+ * gcc.target/i386/cet-notrack-5b.c: Likewise.
+ * gcc.target/i386/cet-notrack-6b.c: Likewise.
+ * gcc.target/i386/cet-notrack-icf-1.c: Likewise.
+ * gcc.target/i386/cet-notrack-icf-2.c: Likewise.
+ * gcc.target/i386/cet-notrack-icf-3.c: Likewise.
+ * gcc.target/i386/cet-notrack-icf-4.c: Likewise.
+ * gcc.target/i386/cet-sjlj-3.c: Likewise.
+ * gcc.target/i386/cet-sjlj-5.c: Likewise.
+
+2019-05-14 Marek Polacek <polacek@redhat.com>
+
+ PR c++/68918
+ * g++.dg/cpp0x/decltype71.C: New test.
+
+ PR c++/70156
+ * g++.dg/init/static5.C: New test.
+
+2019-05-14 Iain Sandoe <iain@sandoe.co.uk>
+
+ PR target/82920
+ * gcc.target/i386/cet-sjlj-6b.c: Require effective target x32.
+ * gcc.target/i386/pr52146.c: Likewise.
+ * gcc.target/i386/pr52698.c: Likewise.
+ * gcc.target/i386/pr52857-1.c: Likewise.
+ * gcc.target/i386/pr52857-2.c: Likewise.
+ * gcc.target/i386/pr52876.c: Likewise.
+ * gcc.target/i386/pr53698.c: Likewise.
+ * gcc.target/i386/pr54157.c: Likewise.
+ * gcc.target/i386/pr55049-1.c: Likewise.
+ * gcc.target/i386/pr55093.c: Likewise.
+ * gcc.target/i386/pr55116-1.c: Likewise.
+ * gcc.target/i386/pr55116-2.c: Likewise.
+ * gcc.target/i386/pr55597.c: Likewise.
+ * gcc.target/i386/pr59929.c: Likewise.
+ * gcc.target/i386/pr66470.c: Likewise.
+
+2019-05-14 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE>
+
+ * gcc.dg/atomic/c11-atomic-exec-4.c: Simplify triplet to
+ *-*-solaris2*.
+ * gcc.dg/atomic/c11-atomic-exec-5.c: Likewise.
+ * gcc.dg/c99-math-double-1.c: Likewise.
+ * gcc.dg/c99-math-float-1.c: Likewise.
+ * gcc.dg/c99-math-long-double-1.c: Likewise.
+ * gcc.misc-tests/linkage.exp: Simplify triplet to
+ x86_64-*-solaris2*.
+
+ * gcc.target/i386/mcount_pic.c: Remove *-*-solaris2.10* && !gld
+ xfail.
+ * gcc.target/i386/pr63620.c: Likewise.
+
+ * lib/target-supports.exp (check_sse_os_support_available): Remove
+ Solaris 9/x86 workaround.
+
+2019-05-14 Richard Biener <rguenther@suse.de>
+
+ * gcc.dg/gimplefe-40.c: New testcase.
+
+2019-05-14 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR preprocessor/90382
+ * g++.dg/diagnostic/trailing1.C: New test.
+
+2019-05-14 marxin <mliska@suse.cz>
+
+ PR middle-end/90340
+ * gcc.dg/tree-ssa/pr90340-2.c: Add case-values-threshold
+ param.
+
+2019-05-14 Richard Biener <rguenther@suse.de>
+ H.J. Lu <hongjiu.lu@intel.com>
+
+ PR tree-optimization/88828
+ * gcc.target/i386/pr88828-1.c: New test.
+ * gcc.target/i386/pr88828-1a.c: Likewise.
+ * gcc.target/i386/pr88828-1b.c: Likewise.
+ * gcc.target/i386/pr88828-1c.c: Likewise.
+ * gcc.target/i386/pr88828-4a.c: Likewise.
+ * gcc.target/i386/pr88828-4b.c: Likewise.
+ * gcc.target/i386/pr88828-5a.c: Likewise.
+ * gcc.target/i386/pr88828-5b.c: Likewise.
+ * gcc.target/i386/pr88828-7.c: Likewise.
+ * gcc.target/i386/pr88828-7a.c: Likewise.
+ * gcc.target/i386/pr88828-7b.c: Likewise.
+ * gcc.target/i386/pr88828-8.c: Likewise.
+ * gcc.target/i386/pr88828-8a.c: Likewise.
+ * gcc.target/i386/pr88828-8b.c: Likewise.
+ * gcc.target/i386/pr88828-9.c: Likewise.
+ * gcc.target/i386/pr88828-9a.c: Likewise.
+ * gcc.target/i386/pr88828-9b.c: Likewise.
+
+2019-05-14 Przemyslaw Wirkus <przemyslaw.wirkus@arm.com\>
+
+ * gcc.target/aarch64/signbitv4sf.c: New test.
+ * gcc.target/aarch64/signbitv2sf.c: New test.
+
+2019-05-13 Jonathan Wakely <jwakely@redhat.com>
+
+ * g++.dg/cpp0x/Wattributes1.C: Adjust dg-error line number to fix
+ regression, by matching a note on any line.
+ * g++.dg/cpp0x/Wattributes2.C: Add another copy that checks the
+ correct line number is matched without depending on a library header.
+
+2019-05-13 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/90402
+ * gcc.dg/torture/pr90402-1.c: New testcase.
+
+2019-05-12 Iain Sandoe <iain@sandoe.co.uk>
+ Dominique d'Humieres <dominiq@gcc.gnu.org>
+
+ PR target/82920
+ * gcc.target/i386/indirect-thunk-1.c: Adjust scan-asms for Darwin,
+ do not use -fno-pic on Darwin.
+ * gcc.target/i386/indirect-thunk-2.c: Likewise.
+ * gcc.target/i386/indirect-thunk-3.c: Likewise.
+ * gcc.target/i386/indirect-thunk-4.c: Likewise.
+ * gcc.target/i386/indirect-thunk-7.c: Likewise.
+ * gcc.target/i386/indirect-thunk-attr-1.c: Likewise.
+ * gcc.target/i386/indirect-thunk-attr-2.c: Likewise.
+ * gcc.target/i386/indirect-thunk-attr-3.c: Likewise.
+ * gcc.target/i386/indirect-thunk-attr-4.c: Likewise.
+ * gcc.target/i386/indirect-thunk-attr-5.c: Likewise.
+ * gcc.target/i386/indirect-thunk-attr-6.c: Likewise.
+ * gcc.target/i386/indirect-thunk-attr-7.c: Likewise.
+ * gcc.target/i386/indirect-thunk-attr-8.c: Likewise.
+ * gcc.target/i386/indirect-thunk-extern-1.c: Likewise.
+ * gcc.target/i386/indirect-thunk-extern-2.c: Likewise.
+ * gcc.target/i386/indirect-thunk-extern-3.c: Likewise.
+ * gcc.target/i386/indirect-thunk-extern-4.c: Likewise.
+ * gcc.target/i386/indirect-thunk-extern-7.c: Likewise.
+ * gcc.target/i386/indirect-thunk-inline-1.c: Likewise.
+ * gcc.target/i386/indirect-thunk-inline-2.c: Likewise.
+ * gcc.target/i386/indirect-thunk-inline-3.c: Likewise.
+ * gcc.target/i386/indirect-thunk-inline-4.c: Likewise.
+ * gcc.target/i386/indirect-thunk-inline-7.c: Likewise.
+ * gcc.target/i386/indirect-thunk-register-1.c: Likewise.
+ * gcc.target/i386/indirect-thunk-register-2.c: Likewise.
+ * gcc.target/i386/indirect-thunk-register-3.c: Likewise.
+ * gcc.target/i386/indirect-thunk-register-4.c: Likewise.
+ * gcc.target/i386/ret-thunk-1.c: Likewise.
+ * gcc.target/i386/ret-thunk-10.c: Likewise.
+ * gcc.target/i386/ret-thunk-11.c: Likewise.
+ * gcc.target/i386/ret-thunk-12.c: Likewise.
+ * gcc.target/i386/ret-thunk-13.c: Likewise.
+ * gcc.target/i386/ret-thunk-14.c: Likewise.
+ * gcc.target/i386/ret-thunk-15.c: Likewise.
+ * gcc.target/i386/ret-thunk-16.c: Likewise.
+ * gcc.target/i386/ret-thunk-2.c: Likewise.
+ * gcc.target/i386/ret-thunk-22.c: Likewise.
+ * gcc.target/i386/ret-thunk-23.c: Likewise.
+ * gcc.target/i386/ret-thunk-24.c: Likewise.
+ * gcc.target/i386/ret-thunk-3.c: Likewise.
+ * gcc.target/i386/ret-thunk-4.c: Likewise.
+ * gcc.target/i386/ret-thunk-5.c: Likewise.
+ * gcc.target/i386/ret-thunk-6.c: Likewise.
+ * gcc.target/i386/ret-thunk-7.c: Likewise.
+ * gcc.target/i386/ret-thunk-8.c: Likewise.
+ * gcc.target/i386/ret-thunk-9.c: Likewise.
+
+2019-05-11 Iain Sandoe <iain@sandoe.co.uk>
+
+ PR testsuite/81058
+ * gcc.target/i386/avx512bw-vpmovswb-1.c: Use regular data section
+ for variables on Darwin, rather than common.
+ * gcc.target/i386/avx512bw-vpmovuswb-1.c: Likewise.
+ * gcc.target/i386/avx512bw-vpmovwb-1.c: Likewise.
+
+2019-05-11 Paolo Carlini <paolo.carlini@oracle.com>
+
+ * g++.dg/cpp2a/multiple-deleted-destroying-delete-error-1.C: New.
+ * g++.dg/cpp2a/multiple-deleted-destroying-delete-error-2.C: Likewise.
+
+2019-05-10 Thomas Koenig <tkoenig@gcc.gnu.org>
+
+ PR fortran/61968
+ * gfortran.dg/assumed_type_10.f90: New test case.
+ * gfortran.dg/assumed_type_11.f90: New test case.
+
+2019-05-10 Iain Sandoe <iain@sandoe.co.uk>
+
+ * gcc.target/x86_64/abi/avx512f/abi-avx512f.exp: Darwin is
+ now tested.
+ * gcc.target/x86_64/abi/avx512f/asm-support-darwin.s: New.
+
+2019-05-10 Paolo Carlini <paolo.carlini@oracle.com>
+
+ * g++.dg/diagnostic/main1.C: New.
+
+2019-05-10 Marek Polacek <polacek@redhat.com>
+
+ PR c++/78010 - bogus -Wsuggest-override warning on final function.
+ * g++.dg/warn/Wsuggest-override-2.C: New test.
+
+2019-05-10 Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/90385
+ * gfortran.dg/pr90385.f90: New test.
+
+ PR c++/90383
+ * g++.dg/cpp1y/constexpr-90383-1.C: New test.
+ * g++.dg/cpp1y/constexpr-90383-2.C: New test.
+
+2019-05-10 Paul Thomas <pault@gcc.gnu.org>
+
+ PR fortran/90093
+ * gfortran.dg/ISO_Fortran_binding_12.f90: New test.
+ * gfortran.dg/ISO_Fortran_binding_12.c: Supplementary code.
+
+ PR fortran/90352
+ * gfortran.dg/iso_c_binding_char_1.f90: New test.
+
+ PR fortran/90355
+ * gfortran.dg/ISO_Fortran_binding_4.f90: Add 'substr' to test
+ the direct passing of substrings as descriptors to bind(C).
+ * gfortran.dg/assign_10.f90: Increase the tree_dump count of
+ 'atmp' to account for the setting of the 'span' field.
+ * gfortran.dg/transpose_optimization_2.f90: Ditto.
+
+2019-05-10 Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/88709
+ PR tree-optimization/90271
+ * gcc.dg/store_merging_29.c: Allow 4 stores to replace 6 stores on
+ arm*-*-*.
+
+ PR pch/90326
+ * g++.dg/pch/pr90326.C: New test.
+ * g++.dg/pch/pr90326.Hs: New file.
+
+2019-05-10 Martin Liska <mliska@suse.cz>
+
+ PR middle-end/90340
+ * gcc.dg/tree-ssa/pr90340-2.c: New test.
+ * gcc.dg/tree-ssa/pr90340.c: New test.
+
+2019-05-09 Cherry Zhang <cherryyz@google.com>
+
+ * go.dg/mapstring.go: New test.
+
2019-05-09 Richard Earnshaw <rearnsha@arm.com>
PR target/90405
@@ -134,6 +3365,14 @@
optimization.
* gcc.dg/tree-ssa/pr88676-2.c: New testcase.
+2019-05-06 H.J. Lu <hongjiu.lu@intel.com>
+ Hongtao Liu <hongtao.liu@intel.com>
+
+ PR target/89750
+ PR target/86444
+ * gcc.target/i386/avx512f-vcomisd-2.c: New.
+ * gcc.target/i386/avx512f-vcomisd-2.c: Likewise.
+
2019-05-06 Steven G. Kargl <kargl@gcc.gnu.org>
PR fortran/90290
@@ -284,7 +3523,7 @@
PR fortran/60144
* gfortran.dg/block_name_2.f90: Adjust dg-error.
* gfortran.dg/dec_type_print_3.f90.f90: Likewise
- * gfortran.dg/pr60144.f90: New test.
+ * gfortran.dg/pr60144.f90: New test.
2019-05-01 Jeff Law <law@redhat.com>
@@ -3372,6 +6611,17 @@
PR target/89290
* gcc.target/i386/pr89290.c: New test.
+2019-01-23 Xuepeng Guo <xuepeng.guo@intel.com>
+
+ * gcc.target/i386/enqcmd.c: New test.
+ * gcc.target/i386/enqcmds.c: Likewise.
+ * g++.dg/other/i386-2.C: Add -menqcmd.
+ * g++.dg/other/i386-3.C: Likewise.
+ * gcc.target/i386/sse-12.c: Likewise.
+ * gcc.target/i386/sse-13.c: Likewise.
+ * gcc.target/i386/sse-14.c: Likewise.
+ * gcc.target/i386/sse-23.c: Likewise.
+
2019-01-23 Xiong Hu Luo <luoxhu@linux.vnet.ibm.com>
* gcc.target/powerpc/crypto-builtin-1.c
diff --git a/gcc/testsuite/ChangeLog-2018 b/gcc/testsuite/ChangeLog-2018
index c5ca8d9..1d5d430 100644
--- a/gcc/testsuite/ChangeLog-2018
+++ b/gcc/testsuite/ChangeLog-2018
@@ -572,6 +572,8 @@
* gcc.target/avr/pr88253.c: New test.
2018-12-17 Richard Sandiford <richard.sandiford@arm.com>
+ Ramana Radhakrishnan <ramana.radhakrishnan@arm.com>
+ Kyrylo Tkachov <kyrylo.tkachov@arm.com>
* gcc.dg/loop-versioning-1.c: New test.
* gcc.dg/loop-versioning-10.c: Likewise.
diff --git a/gcc/testsuite/brig.dg/test/gimple/packed.hsail b/gcc/testsuite/brig.dg/test/gimple/packed.hsail
index 4cba5fc..9137490 100644
--- a/gcc/testsuite/brig.dg/test/gimple/packed.hsail
+++ b/gcc/testsuite/brig.dg/test/gimple/packed.hsail
@@ -64,7 +64,7 @@ prog kernel &Kernel(kernarg_u64 %input_ptr, kernarg_u64 %output_ptr)
/* { dg-final { scan-tree-dump "_\[0-9\]+ = q2 \\\+ q3;" "gimple" } } */
/* Insert the lowest element of the result to the lowest element of the result register. */
-/* { dg-final { scan-tree-dump "= VEC_PERM_EXPR <\[a-z0-9_\]+, new_output.\[0-9\]+_\[0-9\]+, { 16, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }>;" "gimple" } } */
+/* { dg-final { scan-tree-dump "= VEC_PERM_EXPR <new_output.\[0-9\]+_\[0-9\]+, \[a-z0-9_\]+, { 0, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31 }>;" "gimple" } } */
/* FIXME */
/* { dg-final { scan-tree-dump "q4 = \(VIEW_CONVERT_EXPR<uint128_t>\\\()?s_output.\[0-9\]+\(_\[0-9\]+\)*\\\)?;" "gimple" } } */
diff --git a/gcc/testsuite/c-c++-common/Wbool-operation-1.c b/gcc/testsuite/c-c++-common/Wbool-operation-1.c
index 552b044..0489187 100644
--- a/gcc/testsuite/c-c++-common/Wbool-operation-1.c
+++ b/gcc/testsuite/c-c++-common/Wbool-operation-1.c
@@ -15,18 +15,18 @@ fn (bool b, bool b2, T b3, int n, v4si v)
{
int r = 0;
- r += ~b; /* { dg-warning "on an expression of type bool|on a boolean expression" } */
- r += n + ~b; /* { dg-warning "on an expression of type bool|on a boolean expression" } */
- r += ~(n == 1); /* { dg-warning "on an expression of type bool|on a boolean expression" } */
- r += ~(n || 1); /* { dg-warning "on an expression of type bool|on a boolean expression" } */
- r += ~b == 1; /* { dg-warning "on an expression of type bool|on a boolean expression" } */
- r += ~(++n, n == 1); /* { dg-warning "on an expression of type bool|on a boolean expression" } */
- r += ~(++n, n > 1); /* { dg-warning "on an expression of type bool|on a boolean expression" } */
- r += ~(++n, n && 1); /* { dg-warning "on an expression of type bool|on a boolean expression" } */
- r += (++n, ~b); /* { dg-warning "on an expression of type bool|on a boolean expression" } */
- r += ~b3; /* { dg-warning "on an expression of type bool|on a boolean expression" } */
- r += ~foo (); /* { dg-warning "on an expression of type bool|on a boolean expression" } */
- r += ~(bool) !1; /* { dg-warning "on an expression of type bool|on a boolean expression" } */
+ r += ~b; /* { dg-warning "on an expression of type 'bool'|on a boolean expression" } */
+ r += n + ~b; /* { dg-warning "on an expression of type 'bool'|on a boolean expression" } */
+ r += ~(n == 1); /* { dg-warning "on an expression of type 'bool'|on a boolean expression" } */
+ r += ~(n || 1); /* { dg-warning "on an expression of type 'bool'|on a boolean expression" } */
+ r += ~b == 1; /* { dg-warning "on an expression of type 'bool'|on a boolean expression" } */
+ r += ~(++n, n == 1); /* { dg-warning "on an expression of type 'bool'|on a boolean expression" } */
+ r += ~(++n, n > 1); /* { dg-warning "on an expression of type 'bool'|on a boolean expression" } */
+ r += ~(++n, n && 1); /* { dg-warning "on an expression of type 'bool'|on a boolean expression" } */
+ r += (++n, ~b); /* { dg-warning "on an expression of type 'bool'|on a boolean expression" } */
+ r += ~b3; /* { dg-warning "on an expression of type 'bool'|on a boolean expression" } */
+ r += ~foo (); /* { dg-warning "on an expression of type 'bool'|on a boolean expression" } */
+ r += ~(bool) !1; /* { dg-warning "on an expression of type 'bool'|on a boolean expression" } */
v = ~v;
r += ~(int) b;
diff --git a/gcc/testsuite/c-c++-common/Wreturn-local-addr.c b/gcc/testsuite/c-c++-common/Wreturn-local-addr.c
new file mode 100644
index 0000000..c8c3b90
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/Wreturn-local-addr.c
@@ -0,0 +1,47 @@
+/* PR c/90737 - inconsistent address of a local converted to intptr_t
+ between callee and caller
+ { dg-do compile }
+ { dg-options "-O1 -Wall -Wreturn-local-addr -fdump-tree-optimized" } */
+
+typedef __INTPTR_TYPE__ intptr_t;
+
+static inline intptr_t
+return_addr_local_as_int (void)
+{
+ int i;
+ if ((intptr_t)&i == 0)
+ __builtin_abort ();
+
+ return (intptr_t)&i;
+}
+
+void get_addr_local_as_int (void)
+{
+ intptr_t i = return_addr_local_as_int ();
+ if (i == 0)
+ __builtin_abort ();
+}
+
+
+static inline intptr_t
+return_addr_label_as_int (void)
+{
+ label:
+ if ((intptr_t)&&label == 0)
+ __builtin_abort ();
+
+ return (intptr_t)&&label;
+}
+
+void get_addr_label_as_int (void)
+{
+ intptr_t i = return_addr_label_as_int ();
+ if (i == 0)
+ __builtin_abort ();
+}
+
+/* Verify that the functions that return the address of the label
+ or local variable have been optimized away and so have the calls
+ to abort.
+ { dg-final { scan-tree-dump-not "return_addr_" "optimized" } }
+ { dg-final { scan-tree-dump-not "abort" "optimized" } } */
diff --git a/gcc/testsuite/c-c++-common/Wswitch-outside-range-1.c b/gcc/testsuite/c-c++-common/Wswitch-outside-range-1.c
new file mode 100644
index 0000000..29e56f3
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/Wswitch-outside-range-1.c
@@ -0,0 +1,8 @@
+// PR c++/90875
+
+void f(char c)
+{
+ switch (c)
+ case 300: // { dg-warning "case label value exceeds maximum value for type" }
+ case -300:; // { dg-warning "case label value is less than minimum value for type" }
+}
diff --git a/gcc/testsuite/c-c++-common/Wswitch-outside-range-2.c b/gcc/testsuite/c-c++-common/Wswitch-outside-range-2.c
new file mode 100644
index 0000000..20cc019
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/Wswitch-outside-range-2.c
@@ -0,0 +1,9 @@
+// PR c++/90875
+// { dg-options -Wno-switch-outside-range }
+
+void f(char c)
+{
+ switch (c)
+ case 300: //{ dg-bogus "case label value is less than minimum value for type" }
+ case -300:; // { dg-bogus "case label value is less than minimum value for type" }
+}
diff --git a/gcc/testsuite/c-c++-common/Wswitch-outside-range-3.c b/gcc/testsuite/c-c++-common/Wswitch-outside-range-3.c
new file mode 100644
index 0000000..baf1556
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/Wswitch-outside-range-3.c
@@ -0,0 +1,9 @@
+// PR c++/90875
+// { dg-options -Wno-pedantic }
+
+void f(char c)
+{
+ switch (c)
+
+ case -300 ... 300:; // { dg-warning "lower value in case label range less than minimum value for type|upper value in case label range exceeds maximum value for type" }
+}
diff --git a/gcc/testsuite/c-c++-common/Wswitch-outside-range-4.c b/gcc/testsuite/c-c++-common/Wswitch-outside-range-4.c
new file mode 100644
index 0000000..d9bd756
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/Wswitch-outside-range-4.c
@@ -0,0 +1,9 @@
+// PR c++/90875
+// { dg-options "-Wno-pedantic -Wno-switch-outside-range" }
+
+void f(char c)
+{
+ switch (c)
+
+ case -300 ... 300:; // { dg-bogus "lower value in case label range less than minimum value for type|upper value in case label range exceeds maximum value for type" }
+}
diff --git a/gcc/testsuite/c-c++-common/Wvarargs-2.c b/gcc/testsuite/c-c++-common/Wvarargs-2.c
index a6b51f1..08d3b94 100644
--- a/gcc/testsuite/c-c++-common/Wvarargs-2.c
+++ b/gcc/testsuite/c-c++-common/Wvarargs-2.c
@@ -9,7 +9,7 @@ void
err (int a)
{
va_list vp;
- va_start (vp, a); // { dg-error "used in function with fixed args" }
+ va_start (vp, a); // { dg-error "used in function with fixed arguments" }
}
void
diff --git a/gcc/testsuite/c-c++-common/Wvarargs.c b/gcc/testsuite/c-c++-common/Wvarargs.c
index 71d8c5d..bfd8276 100644
--- a/gcc/testsuite/c-c++-common/Wvarargs.c
+++ b/gcc/testsuite/c-c++-common/Wvarargs.c
@@ -6,7 +6,7 @@ void
err (int a)
{
va_list vp;
- va_start (vp, a); // { dg-error "used in function with fixed args" }
+ va_start (vp, a); // { dg-error "used in function with fixed arguments" }
}
#pragma GCC diagnostic push
diff --git a/gcc/testsuite/c-c++-common/asan/alloca_loop_unpoisoning.c b/gcc/testsuite/c-c++-common/asan/alloca_loop_unpoisoning.c
index 55345fd..3050d3b 100644
--- a/gcc/testsuite/c-c++-common/asan/alloca_loop_unpoisoning.c
+++ b/gcc/testsuite/c-c++-common/asan/alloca_loop_unpoisoning.c
@@ -17,7 +17,7 @@ __attribute__((noinline)) void foo(int len) {
top = &x;
volatile char array[len];
assert(!((uintptr_t) array & 31L));
- __builtin_alloca(len);
+ void *p = __builtin_alloca(len);
for (int i = 0; i < thirty_two; ++i) {
char array[i];
bot = array;
diff --git a/gcc/testsuite/c-c++-common/asan/pr88619.c b/gcc/testsuite/c-c++-common/asan/pr88619.c
index aab8a4c..fd3fbf1a 100644
--- a/gcc/testsuite/c-c++-common/asan/pr88619.c
+++ b/gcc/testsuite/c-c++-common/asan/pr88619.c
@@ -10,5 +10,5 @@ main ()
A b;
int *p = &b;
*(p - 1) = 123;
- __builtin_alloca (b);
+ void *p2 = __builtin_alloca (b);
}
diff --git a/gcc/testsuite/c-c++-common/builtin-arith-overflow-3.c b/gcc/testsuite/c-c++-common/builtin-arith-overflow-3.c
new file mode 100644
index 0000000..37a2259
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/builtin-arith-overflow-3.c
@@ -0,0 +1,42 @@
+/* PR c/90628 */
+/* { dg-do compile } */
+
+const int a = 1, b = 2, c = 3;
+const long d = 4, e = 5, f = 6;
+const long long g = 7, h = 8, i = 9;
+
+void
+f1 ()
+{
+ __builtin_add_overflow (a, b, &c); /* { dg-error "argument 3 in call to function '__builtin_add_overflow' has pointer to 'const' type" } */
+}
+
+void
+f2 ()
+{
+ __builtin_sub_overflow (d, e, &f); /* { dg-error "argument 3 in call to function '__builtin_sub_overflow' has pointer to 'const' type" } */
+}
+
+void
+f3 ()
+{
+ __builtin_mul_overflow (g, h, &i); /* { dg-error "argument 3 in call to function '__builtin_mul_overflow' has pointer to 'const' type" } */
+}
+
+void
+f4 ()
+{
+ __builtin_sadd_overflow (a, b, &c); /* { dg-warning "passing argument 3 of '__builtin_sadd_overflow' discards 'const' qualifier from pointer target type" "" { target c } } */
+} /* { dg-error "invalid conversion from 'const int\\*' to 'int\\*'" "" { target c++ } .-1 } */
+
+void
+f5 ()
+{
+ __builtin_ssubl_overflow (d, e, &f); /* { dg-warning "passing argument 3 of '__builtin_ssubl_overflow' discards 'const' qualifier from pointer target type" "" { target c } } */
+} /* { dg-error "invalid conversion from 'const long int\\*' to 'long int\\*'" "" { target c++ } .-1 } */
+
+void
+f6 ()
+{
+ __builtin_smulll_overflow (g, h, &i); /* { dg-warning "passing argument 3 of '__builtin_smulll_overflow' discards 'const' qualifier from pointer target type" "" { target c } } */
+} /* { dg-error "invalid conversion from 'const long long int\\*' to 'long long int\\*'" "" { target c++ } .-1 } */
diff --git a/gcc/testsuite/c-c++-common/convert-vec-1.c b/gcc/testsuite/c-c++-common/convert-vec-1.c
index 862190d..f891a93 100644
--- a/gcc/testsuite/c-c++-common/convert-vec-1.c
+++ b/gcc/testsuite/c-c++-common/convert-vec-1.c
@@ -1,4 +1,4 @@
/* { dg-do compile } */
/* { dg-prune-output "changes the ABI" } */
typedef float v2sf __attribute__ ((vector_size (8)));
-v2sf sub (void) { return (v2sf) 0.0; } /* { dg-error "can't convert" } */
+v2sf sub (void) { return (v2sf) 0.0; } /* { dg-error "cannot convert" } */
diff --git a/gcc/testsuite/c-c++-common/cpp/fmax-include-depth-1a.h b/gcc/testsuite/c-c++-common/cpp/fmax-include-depth-1a.h
new file mode 100644
index 0000000..4e610c0
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/cpp/fmax-include-depth-1a.h
@@ -0,0 +1 @@
+int a;
diff --git a/gcc/testsuite/c-c++-common/cpp/fmax-include-depth-1b.h b/gcc/testsuite/c-c++-common/cpp/fmax-include-depth-1b.h
new file mode 100644
index 0000000..c167587
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/cpp/fmax-include-depth-1b.h
@@ -0,0 +1 @@
+#include "fmax-include-depth-1a.h"
diff --git a/gcc/testsuite/c-c++-common/cpp/fmax-include-depth.c b/gcc/testsuite/c-c++-common/cpp/fmax-include-depth.c
new file mode 100644
index 0000000..bd8cc3a
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/cpp/fmax-include-depth.c
@@ -0,0 +1,4 @@
+/* { dg-do preprocess} */
+/* { dg-options "-fmax-include-depth=1" } */
+
+#include "fmax-include-depth-1b.h" /* { dg-error ".include nested depth 1 exceeds maximum of 1 .use -fmax-include-depth=DEPTH to increase the maximum." } */
diff --git a/gcc/testsuite/c-c++-common/goacc/acc-icf.c b/gcc/testsuite/c-c++-common/goacc/acc-icf.c
index ecfe3f2..98b536c 100644
--- a/gcc/testsuite/c-c++-common/goacc/acc-icf.c
+++ b/gcc/testsuite/c-c++-common/goacc/acc-icf.c
@@ -44,6 +44,4 @@ main ()
return 0;
}
-/* { dg-final { scan-ipa-dump-times "Not parsed function:" 4 "icf" } } */
-/* { dg-final { scan-ipa-dump "Parsed function:main" "icf" } } */
-
+/* { dg-final { scan-ipa-dump-times "with total: 1 items" 5 "icf" } } */
diff --git a/gcc/testsuite/c-c++-common/goacc/classify-routine.c b/gcc/testsuite/c-c++-common/goacc/classify-routine.c
index a723d2c..0b9ba6e 100644
--- a/gcc/testsuite/c-c++-common/goacc/classify-routine.c
+++ b/gcc/testsuite/c-c++-common/goacc/classify-routine.c
@@ -22,10 +22,10 @@ void ROUTINE ()
}
/* Check the offloaded function's attributes.
- { dg-final { scan-tree-dump-times "(?n)__attribute__\\(\\(omp declare target, oacc function \\(0 1, 1 0, 1 0\\)\\)\\)" 1 "ompexp" } } */
+ { dg-final { scan-tree-dump-times "(?n)__attribute__\\(\\(omp declare target \\(worker\\), oacc function \\(0 1, 1 0, 1 0\\)\\)\\)" 1 "ompexp" } } */
/* Check the offloaded function's classification and compute dimensions (will
always be 1 x 1 x 1 for non-offloading compilation).
{ dg-final { scan-tree-dump-times "(?n)Function is OpenACC routine level 1" 1 "oaccdevlow" } }
{ dg-final { scan-tree-dump-times "(?n)Compute dimensions \\\[1, 1, 1\\\]" 1 "oaccdevlow" } }
- { dg-final { scan-tree-dump-times "(?n)__attribute__\\(\\(oacc function \\(0 1, 1 1, 1 1\\), omp declare target, oacc function \\(0 1, 1 0, 1 0\\)\\)\\)" 1 "oaccdevlow" } } */
+ { dg-final { scan-tree-dump-times "(?n)__attribute__\\(\\(oacc function \\(0 1, 1 1, 1 1\\), omp declare target \\(worker\\), oacc function \\(0 1, 1 0, 1 0\\)\\)\\)" 1 "oaccdevlow" } } */
diff --git a/gcc/testsuite/c-c++-common/goacc/declare-1.c b/gcc/testsuite/c-c++-common/goacc/declare-1.c
index 35b1ccd..46ee01b 100644
--- a/gcc/testsuite/c-c++-common/goacc/declare-1.c
+++ b/gcc/testsuite/c-c++-common/goacc/declare-1.c
@@ -1,5 +1,5 @@
-/* Test valid uses of declare directive. */
-/* { dg-do compile } */
+/* Test valid use of the OpenACC 'declare' directive. */
+
int v0;
#pragma acc declare create(v0)
@@ -25,6 +25,7 @@ int v9;
int v10;
#pragma acc declare present_or_create(v10)
+
void
f (void)
{
@@ -93,3 +94,163 @@ f (void)
}
b:;
}
+
+
+/* The same as 'f'. */
+
+void
+f_2 (void)
+{
+ int va0;
+#pragma acc declare create(va0)
+
+ int va1;
+#pragma acc declare copyin(va1)
+
+ int *va2;
+#pragma acc declare deviceptr(va2)
+
+ int va3;
+#pragma acc declare device_resident(va3)
+
+#ifndef __cplusplus
+ /* TODO PR90868
+
+ C: "error: variable '[...]' used more than once with '#pragma acc declare'". */
+#else
+ extern int ve0;
+#pragma acc declare create(ve0)
+
+ extern int ve1;
+#pragma acc declare copyin(ve1)
+
+ extern int *ve2;
+#pragma acc declare deviceptr(ve2)
+
+ extern int ve3;
+#pragma acc declare device_resident(ve3)
+
+ extern int ve4;
+#pragma acc declare link(ve4)
+
+ extern int ve5;
+#pragma acc declare present_or_copyin(ve5)
+
+ extern int ve6;
+#pragma acc declare present_or_create(ve6)
+#endif
+
+ int va5;
+#pragma acc declare copy(va5)
+
+ int va6;
+#pragma acc declare copyout(va6)
+
+ int va7;
+#pragma acc declare present(va7)
+
+ int va8;
+#pragma acc declare present_or_copy(va8)
+
+ int va9;
+#pragma acc declare present_or_copyin(va9)
+
+ int va10;
+#pragma acc declare present_or_copyout(va10)
+
+ int va11;
+#pragma acc declare present_or_create(va11)
+
+ a:
+ {
+ int va0;
+#pragma acc declare create(va0)
+ if (v1)
+ goto a;
+ else
+ goto b;
+ }
+ b:;
+}
+
+
+/* The same as 'f' but everything contained in an OpenACC 'data' construct. */
+
+void
+f_data (void)
+{
+#pragma acc data
+ {
+ int va0;
+# pragma acc declare create(va0)
+
+ int va1;
+# pragma acc declare copyin(va1)
+
+ int *va2;
+# pragma acc declare deviceptr(va2)
+
+ int va3;
+# pragma acc declare device_resident(va3)
+
+#if 0
+ /* TODO PR90868
+
+ C: "error: variable '[...]' used more than once with '#pragma acc declare'".
+ C++: ICE during gimplification. */
+
+ extern int ve0;
+# pragma acc declare create(ve0)
+
+ extern int ve1;
+# pragma acc declare copyin(ve1)
+
+ extern int *ve2;
+# pragma acc declare deviceptr(ve2)
+
+ extern int ve3;
+# pragma acc declare device_resident(ve3)
+
+ extern int ve4;
+# pragma acc declare link(ve4)
+
+ extern int ve5;
+# pragma acc declare present_or_copyin(ve5)
+
+ extern int ve6;
+# pragma acc declare present_or_create(ve6)
+#endif
+
+ int va5;
+# pragma acc declare copy(va5)
+
+ int va6;
+# pragma acc declare copyout(va6)
+
+ int va7;
+# pragma acc declare present(va7)
+
+ int va8;
+# pragma acc declare present_or_copy(va8)
+
+ int va9;
+# pragma acc declare present_or_copyin(va9)
+
+ int va10;
+# pragma acc declare present_or_copyout(va10)
+
+ int va11;
+# pragma acc declare present_or_create(va11)
+
+ a:
+ {
+ int va0;
+# pragma acc declare create(va0)
+ if (v1)
+ goto a;
+ else
+ goto b;
+ }
+ b:;
+ }
+}
diff --git a/gcc/testsuite/c-c++-common/goacc/declare-2.c b/gcc/testsuite/c-c++-common/goacc/declare-2.c
index 33b8245..e2e22be 100644
--- a/gcc/testsuite/c-c++-common/goacc/declare-2.c
+++ b/gcc/testsuite/c-c++-common/goacc/declare-2.c
@@ -1,5 +1,5 @@
-/* Test invalid uses of declare directive. */
-/* { dg-do compile } */
+/* Test invalid use of the OpenACC 'declare' directive. */
+
#pragma acc declare /* { dg-error "no valid clauses" } */
@@ -42,6 +42,7 @@ int va11;
int va12;
#pragma acc declare create (va12) link (va12) /* { dg-error "more than once" } */
+
void
f (void)
{
@@ -65,3 +66,132 @@ f (void)
#pragma acc declare present (v2) /* { dg-error "invalid use of" } */
}
+
+
+/* The same as 'f' but everything contained in an OpenACC 'data' construct. */
+
+void
+f_data (void)
+{
+#pragma acc data
+ {
+ int va0;
+# pragma acc declare link(va0) /* { dg-error "global variable" } */
+
+ extern int ve0;
+# pragma acc declare copy(ve0) /* { dg-error "invalid use of" } */
+
+ extern int ve1;
+# pragma acc declare copyout(ve1) /* { dg-error "invalid use of" } */
+
+ extern int ve2;
+# pragma acc declare present(ve2) /* { dg-error "invalid use of" } */
+
+ extern int ve3;
+# pragma acc declare present_or_copy(ve3) /* { dg-error "invalid use of" } */
+
+ extern int ve4;
+# pragma acc declare present_or_copyout(ve4) /* { dg-error "invalid use of" } */
+
+# pragma acc declare present (v2) /* { dg-error "invalid use of" } */
+ }
+}
+
+
+/* Testing for PR90868 "Duplicate OpenACC 'declare' directives for 'extern'
+ variables". */
+
+
+void
+f_pr90868 (void)
+{
+ extern int we0;
+#pragma acc declare create(we0)
+
+ extern int we1;
+#pragma acc declare copyin(we1)
+
+ extern int *we2;
+#pragma acc declare deviceptr(we2)
+
+ extern int we3;
+#pragma acc declare device_resident(we3)
+
+ extern int we4;
+#pragma acc declare link(we4)
+
+ extern int we5;
+#pragma acc declare present_or_copyin(we5)
+
+ extern int we6;
+#pragma acc declare present_or_create(we6)
+}
+
+
+/* The same as 'f_pr90868'. */
+
+/* The errors are emitted for C only; for C++, the duplicate OpenACC 'declare'
+ directives for 'extern' variables are accepted. */
+
+void
+f_pr90868_2 (void)
+{
+ extern int we0;
+#pragma acc declare create(we0) /* { dg-error "variable 'we0' used more than once with '#pragma acc declare'" "" { target c } } */
+
+ extern int we1;
+#pragma acc declare copyin(we1) /* { dg-error "variable 'we1' used more than once with '#pragma acc declare'" "" { target c } } */
+
+ extern int *we2;
+#pragma acc declare deviceptr(we2) /* { dg-error "variable 'we2' used more than once with '#pragma acc declare'" "" { target c } } */
+
+ extern int we3;
+#pragma acc declare device_resident(we3) /* { dg-error "variable 'we3' used more than once with '#pragma acc declare'" "" { target c } } */
+
+ extern int we4;
+#pragma acc declare link(we4) /* { dg-error "variable 'we4' used more than once with '#pragma acc declare'" "" { target c } } */
+
+ extern int we5;
+#pragma acc declare present_or_copyin(we5) /* { dg-error "variable 'we5' used more than once with '#pragma acc declare'" "" { target c } } */
+
+ extern int we6;
+#pragma acc declare present_or_create(we6) /* { dg-error "variable 'we6' used more than once with '#pragma acc declare'" "" { target c } } */
+}
+
+
+/* The same as 'f_pr90868' but everything contained in an OpenACC 'data'
+ construct. */
+
+#ifdef __cplusplus
+/* TODO PR90868
+
+ C++: ICE during gimplification. */
+#else
+void
+f_pr90868_data (void)
+{
+#pragma acc data
+ {
+ extern int we0;
+# pragma acc declare create(we0) /* { dg-error "variable 'we0' used more than once with '#pragma acc declare'" "" { target c } } */
+
+ extern int we1;
+# pragma acc declare copyin(we1) /* { dg-error "variable 'we1' used more than once with '#pragma acc declare'" "" { target c } } */
+
+ extern int *we2;
+# pragma acc declare deviceptr(we2) /* { dg-error "variable 'we2' used more than once with '#pragma acc declare'" "" { target c } } */
+
+ extern int we3;
+# pragma acc declare device_resident(we3) /* { dg-error "variable 'we3' used more than once with '#pragma acc declare'" "" { target c } } */
+
+ extern int we4;
+# pragma acc declare link(we4) /* { dg-error "variable 'we4' used more than once with '#pragma acc declare'" "" { target c } } */
+
+ extern int we5;
+# pragma acc declare present_or_copyin(we5) /* { dg-error "variable 'we5' used more than once with '#pragma acc declare'" "" { target c } } */
+
+ extern int we6;
+# pragma acc declare present_or_create(we6) /* { dg-error "variable 'we6' used more than once with '#pragma acc declare'" "" { target c } } */
+ }
+}
+#endif
diff --git a/gcc/testsuite/c-c++-common/goacc/declare-pr90861.c b/gcc/testsuite/c-c++-common/goacc/declare-pr90861.c
new file mode 100644
index 0000000..7c90562
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/goacc/declare-pr90861.c
@@ -0,0 +1,21 @@
+/* Verify that OpenACC 'declare' cleans up for VLAs. */
+
+/* { dg-additional-options "-fdump-tree-gimple" } */
+
+void f1 (void)
+{
+#define N_f1 1000
+ int A_f1[N_f1];
+#pragma acc declare copy(A_f1)
+ /* { dg-final { scan-tree-dump-times {#pragma omp target oacc_declare map\(to:A_f1} 1 gimple } }
+ { dg-final { scan-tree-dump-times {#pragma omp target oacc_declare map\(from:A_f1} 1 gimple } } */
+}
+
+void f2 (void)
+{
+ int N_f2 = 1000;
+ int A_f2[N_f2];
+#pragma acc declare copy(A_f2)
+ /* { dg-final { scan-tree-dump-times {#pragma omp target oacc_declare map\(to:\(\*A_f2} 1 gimple } }
+ { dg-final { scan-tree-dump-times {#pragma omp target oacc_declare map\(from:\(\*A_f2} 1 gimple { xfail *-*-* } } } TODO PR90861 */
+}
diff --git a/gcc/testsuite/c-c++-common/goacc/firstprivate-mappings-1.c b/gcc/testsuite/c-c++-common/goacc/firstprivate-mappings-1.c
new file mode 100644
index 0000000..33576c5
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/goacc/firstprivate-mappings-1.c
@@ -0,0 +1,536 @@
+/* Verify OpenACC 'firstprivate' mappings. */
+
+/* This file is also sourced from
+ '../../../../libgomp/testsuite/libgomp.oacc-c-c++-common/firstprivate-mappings-1.c'
+ as an execution test. */
+
+/* See also '../../g++.dg/goacc/firstprivate-mappings-1.C'. */
+
+/* { dg-additional-options "-fdump-tree-omplower" } */
+
+/* { dg-additional-options "-fext-numeric-literals" { target c++ } } */
+
+/* { dg-additional-options "-Wno-psabi" } as apparently we're doing funny
+ things with vector arguments. */
+
+#include <stdbool.h>
+#include <stdint.h>
+#include <string.h>
+
+
+#ifdef __SIZEOF_INT128__
+# define HAVE_INT128 1
+#else
+# define HAVE_INT128 0
+#endif
+
+
+/* The one is only relevant for offloading compilation; will always be enabled
+ when doing tree scanning. */
+#ifdef ACC_DEVICE_TYPE_nvidia
+/* PR71064. */
+# define DO_LONG_DOUBLE 0
+#else
+# define DO_LONG_DOUBLE 1
+#endif
+
+
+/* Simplify scanning for function names in tree dumps. */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/* Inside the following OpenACC 'parallel' constructs' regions, we modify the
+ 'firstprivate' variables, so that we can check that we don't copy these
+ back. */
+
+
+static void
+p (short *spi)
+{
+ short *spo;
+#pragma acc parallel \
+ copyout (spo) \
+ firstprivate (spi)
+ {
+ spo = ++spi;
+ }
+ if (spo != spi + 1)
+ __builtin_abort ();
+}
+
+
+static void
+b (bool bi)
+{
+ bool bo;
+#pragma acc parallel \
+ copyout (bo) \
+ firstprivate (bi)
+ {
+ bo = (bi = !bi);
+ }
+ if (bo != !bi)
+ __builtin_abort ();
+}
+
+
+static void
+i (int8_t i8i,
+ uint8_t u8i,
+ int16_t i16i,
+ uint16_t u16i,
+ int32_t i32i,
+ uint32_t u32i,
+ int64_t i64i,
+ uint64_t u64i)
+{
+ int8_t i8o;
+ uint8_t u8o;
+ int16_t i16o;
+ uint16_t u16o;
+ int32_t i32o;
+ uint32_t u32o;
+ int64_t i64o;
+ uint64_t u64o;
+#pragma acc parallel \
+ copyout (i8o) \
+ firstprivate (i8i) \
+ copyout (u8o) \
+ firstprivate (u8i) \
+ copyout (i16o) \
+ firstprivate (i16i) \
+ copyout (u16o) \
+ firstprivate (u16i) \
+ copyout (i32o) \
+ firstprivate (i32i) \
+ copyout (u32o) \
+ firstprivate (u32i) \
+ copyout (i64o) \
+ firstprivate (i64i) \
+ copyout (u64o) \
+ firstprivate (u64i)
+ {
+ i8o = --i8i;
+ u8o = ++u8i;
+ i16o = --i16i;
+ u16o = ++u16i;
+ i32o = --i32i;
+ u32o = ++u32i;
+ i64o = --i64i;
+ u64o = ++u64i;
+ }
+ if (i8o != i8i - 1)
+ __builtin_abort ();
+ if (u8o != u8i + 1)
+ __builtin_abort ();
+ if (i16o != i16i - 1)
+ __builtin_abort ();
+ if (u16o != u16i + 1)
+ __builtin_abort ();
+ if (i32o != i32i - 1)
+ __builtin_abort ();
+ if (u32o != u32i + 1)
+ __builtin_abort ();
+ if (i64o != i64i - 1)
+ __builtin_abort ();
+ if (u64o != u64i + 1)
+ __builtin_abort ();
+}
+
+
+#if HAVE_INT128
+static void
+i128 (__int128 i128i, unsigned __int128 u128i)
+{
+ __int128 i128o;
+ unsigned __int128 u128o;
+# pragma acc parallel \
+ copyout (i128o) \
+ firstprivate (i128i) \
+ copyout(u128o) \
+ firstprivate (u128i)
+ {
+ i128o = --i128i;
+ u128o = ++u128i;
+ }
+ if (i128o != i128i - 1)
+ __builtin_abort ();
+ if (u128o != u128i + 1)
+ __builtin_abort ();
+}
+#endif
+
+
+static void
+flt_dbl (float flti, double dbli)
+{
+ float flto;
+ double dblo;
+#pragma acc parallel \
+ copyout (flto) \
+ firstprivate (flti) \
+ copyout (dblo) \
+ firstprivate (dbli)
+ {
+ flto = --flti;
+ dblo = --dbli;
+ }
+ if (flto != flti - 1)
+ __builtin_abort ();
+ if (dblo != dbli - 1)
+ __builtin_abort ();
+}
+
+
+static void
+ldbl (long double ldbli)
+{
+#if DO_LONG_DOUBLE
+ long double ldblo;
+# pragma acc parallel \
+ copyout (ldblo) \
+ firstprivate (ldbli)
+ {
+ ldblo = --ldbli;
+ }
+ if (ldblo != ldbli - 1)
+ __builtin_abort ();
+#endif
+}
+
+
+static void
+c (_Complex unsigned char cuci,
+ _Complex signed short cssi,
+ _Complex unsigned int cuii,
+ _Complex signed long csli,
+ _Complex float cflti,
+ _Complex double cdbli)
+{
+ _Complex unsigned char cuco;
+ _Complex signed short csso;
+ _Complex unsigned int cuio;
+ _Complex signed long cslo;
+ _Complex float cflto;
+ _Complex double cdblo;
+#pragma acc parallel \
+ copyout (cuco) \
+ firstprivate (cuci) \
+ copyout (csso) \
+ firstprivate (cssi) \
+ copyout (cuio) \
+ firstprivate (cuii) \
+ copyout (cslo) \
+ firstprivate (csli) \
+ copyout (cflto) \
+ firstprivate (cflti) \
+ copyout (cdblo) \
+ firstprivate (cdbli)
+ {
+ cuco = (cuci += (1 + 1j));
+ csso = (cssi -= (1 + 1j));
+ cuio = (cuii += (1 + 1j));
+ cslo = (csli -= (1 + 1j));
+ cflto = (cflti -= (1 + 1j));
+ cdblo = (cdbli -= (1 + 1j));
+ }
+ if (cuco != cuci + (1 + 1j))
+ __builtin_abort ();
+ if (csso != cssi - (1 + 1j))
+ __builtin_abort ();
+ if (cuio != cuii + (1 + 1j))
+ __builtin_abort ();
+ if (cslo != csli - (1 + 1j))
+ __builtin_abort ();
+ if (cflto != cflti - (1 + 1j))
+ __builtin_abort ();
+ if (cdblo != cdbli - (1 + 1j))
+ __builtin_abort ();
+}
+
+
+static void
+cldbl (_Complex long double cldbli)
+{
+#if DO_LONG_DOUBLE
+ _Complex long double cldblo;
+# pragma acc parallel \
+ copyout (cldblo) \
+ firstprivate (cldbli)
+ {
+ cldblo = (cldbli -= (1 + 1j));
+ }
+ if (cldblo != cldbli - (1 + 1j))
+ __builtin_abort ();
+#endif
+}
+
+
+#define V_EQ(v1, v2) \
+ ({ \
+ __typeof__ (v1) v_d = (v1) != (v2); \
+ __typeof__ (v_d) v_0 = { 0 }; \
+ memcmp (&v_d, &v_0, sizeof v_d) == 0; \
+ })
+
+typedef uint8_t __attribute__ ((vector_size (2 * sizeof (uint8_t)))) v2u8;
+typedef int16_t __attribute__ ((vector_size (4 * sizeof (int16_t)))) v4i16;
+typedef uint32_t __attribute__ ((vector_size (8 * sizeof (uint32_t)))) v8u32;
+typedef int64_t __attribute__ ((vector_size (16 * sizeof (int64_t)))) v16i64;
+typedef float __attribute__ ((vector_size (1 * sizeof (float)))) v1flt;
+typedef float __attribute__ ((vector_size (2 * sizeof (float)))) v2flt;
+typedef float __attribute__ ((vector_size (4 * sizeof (float)))) v4flt;
+typedef float __attribute__ ((vector_size (8 * sizeof (float)))) v8flt;
+typedef double __attribute__ ((vector_size (1 * sizeof (double)))) v1dbl;
+typedef double __attribute__ ((vector_size (2 * sizeof (double)))) v2dbl;
+typedef double __attribute__ ((vector_size (4 * sizeof (double)))) v4dbl;
+typedef double __attribute__ ((vector_size (8 * sizeof (double)))) v8dbl;
+
+static void
+v (v2u8 v2u8i, v4i16 v4i16i, v8u32 v8u32i, v16i64 v16i64i,
+ v1flt v1flti, v2flt v2flti, v4flt v4flti, v8flt v8flti,
+ v1dbl v1dbli, v2dbl v2dbli, v4dbl v4dbli, v8dbl v8dbli)
+{
+ v2u8 v2u8o;
+ v4i16 v4i16o;
+ v8u32 v8u32o;
+ v16i64 v16i64o;
+ v1flt v1flto;
+ v2flt v2flto;
+ v4flt v4flto;
+ v8flt v8flto;
+ v1dbl v1dblo;
+ v2dbl v2dblo;
+ v4dbl v4dblo;
+ v8dbl v8dblo;
+#pragma acc parallel \
+ copyout (v2u8o) \
+ firstprivate (v2u8i) \
+ copyout (v4i16o) \
+ firstprivate (v4i16i) \
+ copyout (v8u32o) \
+ firstprivate (v8u32i) \
+ copyout (v16i64o) \
+ firstprivate (v16i64i) \
+ copyout (v1flto) \
+ firstprivate (v1flti) \
+ copyout (v2flto) \
+ firstprivate (v2flti) \
+ copyout (v4flto) \
+ firstprivate (v4flti) \
+ copyout (v8flto) \
+ firstprivate (v8flti) \
+ copyout (v1dblo) \
+ firstprivate (v1dbli) \
+ copyout (v2dblo) \
+ firstprivate (v2dbli) \
+ copyout (v4dblo) \
+ firstprivate (v4dbli) \
+ copyout (v8dblo) \
+ firstprivate (v8dbli)
+ {
+ v2u8o = ++v2u8i;
+ v4i16o = --v4i16i;
+ v8u32o = ++v8u32i;
+ v16i64o = --v16i64i;
+ v1flto = --v1flti;
+ v2flto = --v2flti;
+ v4flto = --v4flti;
+ v8flto = --v8flti;
+ v1dblo = --v1dbli;
+ v2dblo = --v2dbli;
+ v4dblo = --v4dbli;
+ v8dblo = --v8dbli;
+ }
+ if (!V_EQ (v2u8o, v2u8i + 1))
+ __builtin_abort ();
+ if (!V_EQ (v4i16o, v4i16i - 1))
+ __builtin_abort ();
+ if (!V_EQ (v8u32o, v8u32i + 1))
+ __builtin_abort ();
+ if (!V_EQ (v16i64o, v16i64i - 1))
+ __builtin_abort ();
+ if (!V_EQ (v1flto, v1flti - 1))
+ __builtin_abort ();
+ if (!V_EQ (v2flto, v2flti - 1))
+ __builtin_abort ();
+ if (!V_EQ (v4flto, v4flti - 1))
+ __builtin_abort ();
+ if (!V_EQ (v8flto, v8flti - 1))
+ __builtin_abort ();
+ if (!V_EQ (v1dblo, v1dbli - 1))
+ __builtin_abort ();
+ if (!V_EQ (v2dblo, v2dbli - 1))
+ __builtin_abort ();
+ if (!V_EQ (v4dblo, v4dbli - 1))
+ __builtin_abort ();
+ if (!V_EQ (v8dblo, v8dbli - 1))
+ __builtin_abort ();
+}
+
+
+/* "error: could not find an integer type of the same size as 'long double'" */
+#if HAVE_INT128
+typedef long double __attribute__ ((vector_size (1 * sizeof (long double)))) v1ldbl;
+typedef long double __attribute__ ((vector_size (2 * sizeof (long double)))) v2ldbl;
+typedef long double __attribute__ ((vector_size (4 * sizeof (long double)))) v4ldbl;
+typedef long double __attribute__ ((vector_size (8 * sizeof (long double)))) v8ldbl;
+
+static void
+vldbl (v1ldbl v1ldbli, v2ldbl v2ldbli, v4ldbl v4ldbli, v8ldbl v8ldbli)
+{
+# if DO_LONG_DOUBLE
+ v1ldbl v1ldblo;
+ v2ldbl v2ldblo;
+ v4ldbl v4ldblo;
+ v8ldbl v8ldblo;
+# pragma acc parallel \
+ copyout (v1ldblo) \
+ firstprivate (v1ldbli) \
+ copyout (v2ldblo) \
+ firstprivate (v2ldbli) \
+ copyout (v4ldblo) \
+ firstprivate (v4ldbli) \
+ copyout (v8ldblo) \
+ firstprivate (v8ldbli)
+ {
+ v1ldblo = --v1ldbli;
+ v2ldblo = --v2ldbli;
+ v4ldblo = --v4ldbli;
+ v8ldblo = --v8ldbli;
+ }
+ if (!V_EQ (v1ldblo, v1ldbli - 1))
+ __builtin_abort ();
+ if (!V_EQ (v2ldblo, v2ldbli - 1))
+ __builtin_abort ();
+ if (!V_EQ (v4ldblo, v4ldbli - 1))
+ __builtin_abort ();
+ if (!V_EQ (v8ldblo, v8ldbli - 1))
+ __builtin_abort ();
+# endif
+}
+#endif
+
+
+static void
+vla (int array_li)
+{
+ _Complex double array[array_li];
+ uint32_t array_so;
+#pragma acc parallel \
+ copyout (array_so)
+ /* The gimplifier has created an implicit 'firstprivate' clause for the array
+ length.
+ { dg-final { scan-tree-dump {(?n)#pragma omp target oacc_parallel map\(from:array_so \[len: 4\]\) firstprivate\(array_li.[0-9]+\)} omplower { target { ! c++ } } } }
+ { dg-final { scan-tree-dump {(?n)#pragma omp target oacc_parallel map\(from:array_so \[len: 4\]\) firstprivate\(} omplower { target { c++ } } } }
+ (C++ computes an intermediate value, so can't scan for 'firstprivate(array_li)'.) */
+ /* For C, non-LP64, the gimplifier has also created a mapping for the array
+ itself; PR90859.
+ { dg-final { scan-tree-dump {(?n)#pragma omp target oacc_parallel map\(from:array_so \[len: 4\]\) firstprivate\(array_li.[0-9]+\) map\(tofrom:\(\*array.[0-9]+\) \[len: D\.[0-9]+\]\) map\(firstprivate:array \[pointer assign, bias: 0\]\) \[} omplower { target { c && { ! lp64 } } } } } */
+ {
+ array_so = sizeof array;
+ }
+ if (array_so != sizeof array)
+ __builtin_abort ();
+}
+
+
+#ifdef __cplusplus
+}
+#endif
+
+
+int
+main (int argc, char *argv[])
+{
+ {
+ short s;
+ short *sp = &s;
+ p (sp);
+ }
+
+ {
+ bool bi = true;
+ b (bi);
+ }
+
+ {
+ int8_t i8i = -1;
+ uint8_t u8i = 1;
+ int16_t i16i = -2;
+ uint16_t u16i = 2;
+ int32_t i32i = -3;
+ uint32_t u32i = 3;
+ int64_t i64i = -4;
+ uint64_t u64i = 4;
+ i (i8i, u8i, i16i, u16i, i32i, u32i, i64i, u64i);
+ }
+
+#if HAVE_INT128
+ {
+ __int128 i128i = -8;
+ unsigned __int128 u128i = 8;
+ i128 (i128i, u128i);
+ }
+#endif
+
+ {
+ float flti = .5;
+ double dbli = .25;
+ flt_dbl (flti, dbli);
+ }
+
+ {
+ long double ldbli = .125;
+ ldbl (ldbli);
+ }
+
+ {
+ _Complex unsigned char cuci = 1 + 2j;
+ _Complex signed short cssi = -2 + (-4j);
+ _Complex unsigned int cuii = 3 + 6j;
+ _Complex signed long csli = -4 + (-8j);
+ _Complex float cflti = .5 + 1j;
+ _Complex double cdbli = .25 + .5j;
+ c (cuci, cssi, cuii, csli, cflti, cdbli);
+ }
+
+ {
+ _Complex long double cldbli = .125 + .25j;
+ cldbl (cldbli);
+ }
+
+ {
+ v2u8 v2u8i = {2, 3};
+ v4i16 v4i16i = { -1, -2, 5, 4 };
+ v8u32 v8u32i = { 3, 6, 9, 11};
+ v16i64 v16i64i = { 10, 21, -25, 44, 31, -1, 1, 222, -1, -12, 52, -44, -13, 1, -1, -222};
+ v1flt v1flti = { -.5 };
+ v2flt v2flti = { 1.5, -2.5 };
+ v4flt v4flti = { 3.5, -4.5, -5.5, -6.5 };
+ v8flt v8flti = { -7.5, 8.5, 9.5, 10.5, -11.5, -12.5, 13.5, 14.5 };
+ v1dbl v1dbli = { 0.25 };
+ v2dbl v2dbli = { -1.25, -2.25 };
+ v4dbl v4dbli = { 3.25, -4.25, 5.25, 6.25 };
+ v8dbl v8dbli = { 7.25, 8.25, -9.25, -10.25, -11.25, 12.25, 13.25, -14.25 };
+ v (v2u8i, v4i16i, v8u32i, v16i64i,
+ v1flti, v2flti, v4flti, v8flti,
+ v1dbli, v2dbli, v4dbli, v8dbli);
+ }
+
+#if HAVE_INT128
+ {
+ v1ldbl v1ldbli = { -0.125 };
+ v2ldbl v2ldbli = { 1.125, -2.125 };
+ v4ldbl v4ldbli = { -3.125, -4.125, 5.125, -6.125 };
+ v8ldbl v8ldbli = { 7.125, -8.125, -9.125, 10.125, 11.125, 12.125, 13.125, 14.125 };
+ vldbl (v1ldbli, v2ldbli, v4ldbli, v8ldbli);
+ }
+#endif
+
+ vla (argc);
+
+ return 0;
+}
diff --git a/gcc/testsuite/c-c++-common/goacc/routine-2.c b/gcc/testsuite/c-c++-common/goacc/routine-2.c
index fc5eb11..be1510a 100644
--- a/gcc/testsuite/c-c++-common/goacc/routine-2.c
+++ b/gcc/testsuite/c-c++-common/goacc/routine-2.c
@@ -1,21 +1,3 @@
-#pragma acc routine gang worker /* { dg-error "multiple loop axes" } */
-void gang (void)
-{
-}
-
-#pragma acc routine worker vector /* { dg-error "multiple loop axes" } */
-void worker (void)
-{
-}
-
-#pragma acc routine vector seq /* { dg-error "multiple loop axes" } */
-void vector (void)
-{
-}
-
-#pragma acc routine seq gang /* { dg-error "multiple loop axes" } */
-void seq (void)
-{
-}
+/* Test invalid use of the OpenACC 'routine' directive. */
#pragma acc routine (nothing) gang /* { dg-error "not been declared" } */
diff --git a/gcc/testsuite/c-c++-common/goacc/routine-5.c b/gcc/testsuite/c-c++-common/goacc/routine-5.c
index b967a74..e3fbd65 100644
--- a/gcc/testsuite/c-c++-common/goacc/routine-5.c
+++ b/gcc/testsuite/c-c++-common/goacc/routine-5.c
@@ -150,61 +150,19 @@ void f_static_assert();
#pragma acc routine
__extension__ extern void ex1();
-#pragma acc routine (ex1) /* { dg-error ".#pragma acc routine. already applied to .\[void \]*ex1" } */
+#pragma acc routine (ex1) worker /* { dg-error "has already been marked with an OpenACC 'routine' directive" } */
#pragma acc routine
__extension__ __extension__ __extension__ __extension__ __extension__ void ex2()
{
}
-#pragma acc routine (ex2) /* { dg-error ".#pragma acc routine. already applied to .\[void \]*ex2" } */
+#pragma acc routine (ex2) worker /* { dg-error "has already been marked with an OpenACC 'routine' directive" } */
#pragma acc routine /* { dg-error ".#pragma acc routine. not immediately followed by function declaration or definition" } */
__extension__ int ex3;
#pragma acc routine (ex3) /* { dg-error ".ex3. does not refer to a function" } */
-/* "#pragma acc routine" already applied. */
-
-extern void fungsi_1();
-#pragma acc routine(fungsi_1) gang
-#pragma acc routine(fungsi_1) gang /* { dg-error ".#pragma acc routine. already applied to .\[void \]*fungsi_1" } */
-#pragma acc routine(fungsi_1) worker /* { dg-error ".#pragma acc routine. already applied to .\[void \]*fungsi_1" } */
-#pragma acc routine(fungsi_1) vector /* { dg-error ".#pragma acc routine. already applied to .\[void \]*fungsi_1" } */
-
-#pragma acc routine seq
-extern void fungsi_2();
-#pragma acc routine(fungsi_2) seq /* { dg-error ".#pragma acc routine. already applied to .\[void \]*fungsi_2." } */
-#pragma acc routine(fungsi_2) worker /* { dg-error ".#pragma acc routine. already applied to .\[void \]*fungsi_2." } */
-#pragma acc routine(fungsi_2) /* { dg-error ".#pragma acc routine. already applied to .\[void \]*fungsi_2." } */
-
-#pragma acc routine vector
-extern void fungsi_3();
-#pragma acc routine vector /* { dg-error ".#pragma acc routine. already applied to .\[void \]*fungsi_3." } */
-void fungsi_3()
-{
-}
-
-extern void fungsi_4();
-#pragma acc routine (fungsi_4) worker
-#pragma acc routine gang /* { dg-error ".#pragma acc routine. already applied to .\[void \]*fungsi_4." } */
-void fungsi_4()
-{
-}
-
-#pragma acc routine gang
-void fungsi_5()
-{
-}
-#pragma acc routine (fungsi_5) worker /* { dg-error ".#pragma acc routine. already applied to .\[void \]*fungsi_5." } */
-
-#pragma acc routine seq
-void fungsi_6()
-{
-}
-#pragma acc routine seq /* { dg-error ".#pragma acc routine. already applied to .\[void \]*fungsi_6." } */
-extern void fungsi_6();
-
-
/* "#pragma acc routine" must be applied before. */
void Bar ();
@@ -243,7 +201,7 @@ int
func2 (int a)
{
extern int vb4; /* { dg-error "directive for use" } */
- static int vb5; /* { dg-error "directive for use" } */
+ static int vb5;
vb4 = a + 1;
vb5 = vb4 + 1;
diff --git a/gcc/testsuite/c-c++-common/goacc/routine-level-of-parallelism-1.c b/gcc/testsuite/c-c++-common/goacc/routine-level-of-parallelism-1.c
new file mode 100644
index 0000000..4fdeb14
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/goacc/routine-level-of-parallelism-1.c
@@ -0,0 +1,449 @@
+/* Test various aspects of clauses specifying incompatible levels of
+ parallelism with the OpenACC 'routine' directive. */
+
+extern void g_1 (void);
+#pragma acc routine (g_1) gang gang /* { dg-error "too many 'gang' clauses" } */
+
+#pragma acc routine worker worker /* { dg-error "too many 'worker' clauses" } */
+void w_1 (void)
+{
+}
+
+#pragma acc routine vector vector /* { dg-error "too many 'vector' clauses" } */
+void v_1 (void)
+{
+}
+
+#pragma acc routine seq seq /* { dg-error "too many 'seq' clauses" } */
+extern void s_1 (void);
+
+
+#pragma acc routine gang gang gang /* { dg-error "too many 'gang' clauses" } */
+void g_2 (void)
+{
+}
+
+#pragma acc routine worker worker worker /* { dg-error "too many 'worker' clauses" } */
+extern void w_2 (void);
+
+extern void v_2 (void);
+#pragma acc routine (v_2) vector vector vector /* { dg-error "too many 'vector' clauses" } */
+
+#pragma acc routine seq seq seq /* { dg-error "too many 'seq' clauses" } */
+void s_2 (void)
+{
+}
+
+
+#pragma acc routine \
+ gang \
+ worker /* { dg-error ".worker. specifies a conflicting level of parallelism" } */
+void g_3 (void)
+{
+}
+#pragma acc routine (g_3) \
+ gang \
+ seq /* { dg-error ".seq. specifies a conflicting level of parallelism" } */
+#pragma acc routine (g_3) \
+ gang \
+ vector /* { dg-error ".vector. specifies a conflicting level of parallelism" } */
+
+extern void w_3 (void);
+#pragma acc routine (w_3) \
+ worker \
+ vector /* { dg-error ".vector. specifies a conflicting level of parallelism" } */
+#pragma acc routine (w_3) \
+ worker \
+ gang /* { dg-error ".gang. specifies a conflicting level of parallelism" } */
+#pragma acc routine (w_3) \
+ worker \
+ seq /* { dg-error ".seq. specifies a conflicting level of parallelism" } */
+
+#pragma acc routine \
+ vector \
+ seq /* { dg-error ".seq. specifies a conflicting level of parallelism" } */
+void v_3 (void)
+{
+}
+#pragma acc routine (v_3) \
+ vector \
+ worker /* { dg-error ".worker. specifies a conflicting level of parallelism" } */
+#pragma acc routine (v_3) \
+ vector \
+ gang /* { dg-error ".gang. specifies a conflicting level of parallelism" } */
+
+extern void s_3 (void);
+#pragma acc routine (s_3) \
+ seq \
+ gang /* { dg-error ".gang. specifies a conflicting level of parallelism" } */
+#pragma acc routine (s_3) \
+ seq \
+ vector /* { dg-error ".vector. specifies a conflicting level of parallelism" } */
+#pragma acc routine (s_3) \
+ seq \
+ worker /* { dg-error ".worker. specifies a conflicting level of parallelism" } */
+
+
+#pragma acc routine \
+ gang gang gang /* { dg-error "too many 'gang' clauses" } */ \
+ worker /* { dg-error ".worker. specifies a conflicting level of parallelism" } */ \
+ vector /* { dg-error ".vector. specifies a conflicting level of parallelism" } */ \
+ seq /* { dg-error ".seq. specifies a conflicting level of parallelism" } */
+extern void g_4 (void);
+#pragma acc routine (g_4) \
+ gang gang gang /* { dg-error "too many 'gang' clauses" } */ \
+ vector /* { dg-error ".vector. specifies a conflicting level of parallelism" } */ \
+ worker /* { dg-error ".worker. specifies a conflicting level of parallelism" } */ \
+ seq /* { dg-error ".seq. specifies a conflicting level of parallelism" } */
+#pragma acc routine (g_4) \
+ gang gang gang /* { dg-error "too many 'gang' clauses" } */ \
+ seq /* { dg-error ".seq. specifies a conflicting level of parallelism" } */ \
+ vector /* { dg-error ".vector. specifies a conflicting level of parallelism" } */ \
+ worker /* { dg-error ".worker. specifies a conflicting level of parallelism" } */
+
+extern void w_4 (void);
+#pragma acc routine (w_4) \
+ worker worker worker /* { dg-error "too many 'worker' clauses" } */ \
+ seq /* { dg-error ".seq. specifies a conflicting level of parallelism" } */ \
+ vector /* { dg-error ".vector. specifies a conflicting level of parallelism" } */ \
+ gang /* { dg-error ".gang. specifies a conflicting level of parallelism" } */
+#pragma acc routine (w_4) \
+ worker worker worker /* { dg-error "too many 'worker' clauses" } */ \
+ vector /* { dg-error ".vector. specifies a conflicting level of parallelism" } */ \
+ seq /* { dg-error ".seq. specifies a conflicting level of parallelism" } */ \
+ gang /* { dg-error ".gang. specifies a conflicting level of parallelism" } */
+#pragma acc routine (w_4) \
+ worker worker worker /* { dg-error "too many 'worker' clauses" } */ \
+ seq /* { dg-error ".seq. specifies a conflicting level of parallelism" } */ \
+ gang /* { dg-error ".gang. specifies a conflicting level of parallelism" } */ \
+ vector /* { dg-error ".vector. specifies a conflicting level of parallelism" } */
+
+#pragma acc routine \
+ vector vector vector /* { dg-error "too many 'vector' clauses" } */ \
+ worker /* { dg-error ".worker. specifies a conflicting level of parallelism" } */ \
+ seq /* { dg-error ".seq. specifies a conflicting level of parallelism" } */ \
+ gang /* { dg-error ".gang. specifies a conflicting level of parallelism" } */
+void v_4 (void)
+{
+}
+#pragma acc routine (v_4) \
+ vector vector vector /* { dg-error "too many 'vector' clauses" } */ \
+ seq /* { dg-error ".seq. specifies a conflicting level of parallelism" } */ \
+ worker /* { dg-error ".worker. specifies a conflicting level of parallelism" } */ \
+ gang /* { dg-error ".gang. specifies a conflicting level of parallelism" } */
+#pragma acc routine (v_4) \
+ vector vector vector /* { dg-error "too many 'vector' clauses" } */ \
+ gang /* { dg-error ".gang. specifies a conflicting level of parallelism" } */ \
+ seq /* { dg-error ".seq. specifies a conflicting level of parallelism" } */ \
+ worker /* { dg-error ".worker. specifies a conflicting level of parallelism" } */
+
+#pragma acc routine \
+ seq seq seq /* { dg-error "too many 'seq' clauses" } */ \
+ vector /* { dg-error ".vector. specifies a conflicting level of parallelism" } */ \
+ worker /* { dg-error ".worker. specifies a conflicting level of parallelism" } */ \
+ gang /* { dg-error ".gang. specifies a conflicting level of parallelism" } */
+void s_4 (void)
+{
+}
+#pragma acc routine (s_4) \
+ seq seq seq /* { dg-error "too many 'seq' clauses" } */ \
+ vector /* { dg-error ".vector. specifies a conflicting level of parallelism" } */ \
+ gang /* { dg-error ".gang. specifies a conflicting level of parallelism" } */ \
+ worker /* { dg-error ".worker. specifies a conflicting level of parallelism" } */
+#pragma acc routine (s_4) \
+ seq seq seq /* { dg-error "too many 'seq' clauses" } */ \
+ worker /* { dg-error ".worker. specifies a conflicting level of parallelism" } */ \
+ vector /* { dg-error ".vector. specifies a conflicting level of parallelism" } */ \
+ gang /* { dg-error ".gang. specifies a conflicting level of parallelism" } */
+
+
+#pragma acc routine \
+ gang gang gang /* { dg-error "too many 'gang' clauses" } */ \
+ worker worker /* { dg-error "too many 'worker' clauses" } */ \
+ /* { dg-error ".worker. specifies a conflicting level of parallelism" "" { target *-*-* } .-1 } */ \
+ vector vector vector /* { dg-error "too many 'vector' clauses" } */ \
+ /* { dg-error ".vector. specifies a conflicting level of parallelism" "" { target *-*-* } .-1 } */ \
+ seq seq seq seq seq /* { dg-error "too many 'seq' clauses" } */ \
+ /* { dg-error ".seq. specifies a conflicting level of parallelism" "" { target *-*-* } .-1 } */
+void g_5 (void)
+{
+}
+#pragma acc routine (g_5) \
+ gang gang gang /* { dg-error "too many 'gang' clauses" } */ \
+ vector vector vector vector /* { dg-error "too many 'vector' clauses" } */ \
+ /* { dg-error ".vector. specifies a conflicting level of parallelism" "" { target *-*-* } .-1 } */ \
+ worker worker worker /* { dg-error "too many 'worker' clauses" } */ \
+ /* { dg-error ".worker. specifies a conflicting level of parallelism" "" { target *-*-* } .-1 } */ \
+ seq seq seq seq seq seq /* { dg-error "too many 'seq' clauses" } */ \
+ /* { dg-error ".seq. specifies a conflicting level of parallelism" "" { target *-*-* } .-1 } */
+#pragma acc routine (g_5) \
+ gang gang gang /* { dg-error "too many 'gang' clauses" } */ \
+ seq seq seq seq seq /* { dg-error "too many 'seq' clauses" } */ \
+ /* { dg-error ".seq. specifies a conflicting level of parallelism" "" { target *-*-* } .-1 } */ \
+ vector vector vector vector /* { dg-error "too many 'vector' clauses" } */ \
+ /* { dg-error ".vector. specifies a conflicting level of parallelism" "" { target *-*-* } .-1 } */ \
+ worker worker worker worker /* { dg-error "too many 'worker' clauses" } */ \
+ /* { dg-error ".worker. specifies a conflicting level of parallelism" "" { target *-*-* } .-1 } */
+
+#pragma acc routine \
+ worker worker worker /* { dg-error "too many 'worker' clauses" } */ \
+ seq seq seq seq /* { dg-error "too many 'seq' clauses" } */ \
+ /* { dg-error ".seq. specifies a conflicting level of parallelism" "" { target *-*-* } .-1 } */ \
+ vector vector vector vector vector /* { dg-error "too many 'vector' clauses" } */ \
+ /* { dg-error ".vector. specifies a conflicting level of parallelism" "" { target *-*-* } .-1 } */ \
+ gang gang /* { dg-error "too many 'gang' clauses" } */ \
+ /* { dg-error ".gang. specifies a conflicting level of parallelism" "" { target *-*-* } .-1 } */
+extern void w_5 (void);
+#pragma acc routine (w_5) \
+ worker worker worker /* { dg-error "too many 'worker' clauses" } */ \
+ vector vector vector /* { dg-error "too many 'vector' clauses" } */ \
+ /* { dg-error ".vector. specifies a conflicting level of parallelism" "" { target *-*-* } .-1 } */ \
+ seq seq seq /* { dg-error "too many 'seq' clauses" } */ \
+ /* { dg-error ".seq. specifies a conflicting level of parallelism" "" { target *-*-* } .-1 } */ \
+ gang gang /* { dg-error "too many 'gang' clauses" } */ \
+ /* { dg-error ".gang. specifies a conflicting level of parallelism" "" { target *-*-* } .-1 } */
+#pragma acc routine (w_5) \
+ worker worker worker /* { dg-error "too many 'worker' clauses" } */ \
+ seq seq /* { dg-error "too many 'seq' clauses" } */ \
+ /* { dg-error ".seq. specifies a conflicting level of parallelism" "" { target *-*-* } .-1 } */ \
+ gang gang /* { dg-error "too many 'gang' clauses" } */ \
+ /* { dg-error ".gang. specifies a conflicting level of parallelism" "" { target *-*-* } .-1 } */ \
+ vector vector vector vector /* { dg-error "too many 'vector' clauses" } */ \
+ /* { dg-error ".vector. specifies a conflicting level of parallelism" "" { target *-*-* } .-1 } */
+
+#pragma acc routine \
+ vector vector vector /* { dg-error "too many 'vector' clauses" } */ \
+ worker worker worker /* { dg-error "too many 'worker' clauses" } */ \
+ /* { dg-error ".worker. specifies a conflicting level of parallelism" "" { target *-*-* } .-1 } */ \
+ seq seq seq seq seq seq /* { dg-error "too many 'seq' clauses" } */ \
+ /* { dg-error ".seq. specifies a conflicting level of parallelism" "" { target *-*-* } .-1 } */ \
+ gang gang /* { dg-error "too many 'gang' clauses" } */ \
+ /* { dg-error ".gang. specifies a conflicting level of parallelism" "" { target *-*-* } .-1 } */
+extern void v_5 (void);
+#pragma acc routine (v_5) \
+ vector vector vector /* { dg-error "too many 'vector' clauses" } */ \
+ seq seq seq seq seq seq /* { dg-error "too many 'seq' clauses" } */ \
+ /* { dg-error ".seq. specifies a conflicting level of parallelism" "" { target *-*-* } .-1 } */ \
+ worker worker /* { dg-error "too many 'worker' clauses" } */ \
+ /* { dg-error ".worker. specifies a conflicting level of parallelism" "" { target *-*-* } .-1 } */ \
+ gang gang /* { dg-error "too many 'gang' clauses" } */ \
+ /* { dg-error ".gang. specifies a conflicting level of parallelism" "" { target *-*-* } .-1 } */
+#pragma acc routine (v_5) \
+ vector vector vector /* { dg-error "too many 'vector' clauses" } */ \
+ gang gang /* { dg-error "too many 'gang' clauses" } */ \
+ /* { dg-error ".gang. specifies a conflicting level of parallelism" "" { target *-*-* } .-1 } */ \
+ seq seq seq seq seq /* { dg-error "too many 'seq' clauses" } */ \
+ /* { dg-error ".seq. specifies a conflicting level of parallelism" "" { target *-*-* } .-1 } */ \
+ worker worker /* { dg-error "too many 'worker' clauses" } */ \
+ /* { dg-error ".worker. specifies a conflicting level of parallelism" "" { target *-*-* } .-1 } */
+
+extern void s_5 (void);
+#pragma acc routine (s_5) \
+ seq seq seq /* { dg-error "too many 'seq' clauses" } */ \
+ vector vector vector vector /* { dg-error "too many 'vector' clauses" } */ \
+ /* { dg-error ".vector. specifies a conflicting level of parallelism" "" { target *-*-* } .-1 } */ \
+ worker worker worker worker worker /* { dg-error "too many 'worker' clauses" } */ \
+ /* { dg-error ".worker. specifies a conflicting level of parallelism" "" { target *-*-* } .-1 } */ \
+ gang gang /* { dg-error "too many 'gang' clauses" } */ \
+ /* { dg-error ".gang. specifies a conflicting level of parallelism" "" { target *-*-* } .-1 } */
+#pragma acc routine (s_5) \
+ seq seq seq /* { dg-error "too many 'seq' clauses" } */ \
+ vector vector vector vector /* { dg-error "too many 'vector' clauses" } */ \
+ /* { dg-error ".vector. specifies a conflicting level of parallelism" "" { target *-*-* } .-1 } */ \
+ gang gang /* { dg-error "too many 'gang' clauses" } */ \
+ /* { dg-error ".gang. specifies a conflicting level of parallelism" "" { target *-*-* } .-1 } */ \
+ worker worker worker /* { dg-error "too many 'worker' clauses" } */ \
+ /* { dg-error ".worker. specifies a conflicting level of parallelism" "" { target *-*-* } .-1 } */
+#pragma acc routine (s_5) \
+ seq seq seq /* { dg-error "too many 'seq' clauses" } */ \
+ worker worker /* { dg-error "too many 'worker' clauses" } */ \
+ /* { dg-error ".worker. specifies a conflicting level of parallelism" "" { target *-*-* } .-1 } */ \
+ vector vector vector vector /* { dg-error "too many 'vector' clauses" } */ \
+ /* { dg-error ".vector. specifies a conflicting level of parallelism" "" { target *-*-* } .-1 } */ \
+ gang gang /* { dg-error "too many 'gang' clauses" } */ \
+ /* { dg-error ".gang. specifies a conflicting level of parallelism" "" { target *-*-* } .-1 } */
+
+
+/* Like the *_5 tests, but with the order of clauses changed in the second and
+ following routine directives for the specific *_5 function. */
+
+#pragma acc routine \
+ gang gang gang /* { dg-error "too many 'gang' clauses" } */ \
+ worker worker /* { dg-error "too many 'worker' clauses" } */ \
+ /* { dg-error ".worker. specifies a conflicting level of parallelism" "" { target *-*-* } .-1 } */ \
+ vector vector vector /* { dg-error "too many 'vector' clauses" } */ \
+ /* { dg-error ".vector. specifies a conflicting level of parallelism" "" { target *-*-* } .-1 } */ \
+ seq seq seq seq seq /* { dg-error "too many 'seq' clauses" } */ \
+ /* { dg-error ".seq. specifies a conflicting level of parallelism" "" { target *-*-* } .-1 } */
+void g_6 (void)
+{
+}
+#pragma acc routine (g_6) \
+ vector vector vector vector /* { dg-error "too many 'vector' clauses" } */ \
+ /* { dg-error "incompatible .vector. clause when applying .#pragma acc routine. to .\[void \]*g_6\[\\(\\)\]*., which has already been marked with an OpenACC 'routine' directive" "" { target *-*-* } .-1 } */ \
+ gang gang gang /* { dg-error "too many 'gang' clauses" } */ \
+ /* { dg-error ".gang. specifies a conflicting level of parallelism" "" { target *-*-* } .-1 } */ \
+ worker worker worker /* { dg-error "too many 'worker' clauses" } */ \
+ /* { dg-error ".worker. specifies a conflicting level of parallelism" "" { target *-*-* } .-1 } */ \
+ seq seq seq seq seq seq /* { dg-error "too many 'seq' clauses" } */ \
+ /* { dg-error ".seq. specifies a conflicting level of parallelism" "" { target *-*-* } .-1 } */
+#pragma acc routine (g_6) \
+ seq seq seq seq seq /* { dg-error "too many 'seq' clauses" } */ \
+ /* { dg-error "incompatible .seq. clause when applying .#pragma acc routine. to .\[void \]*g_6\[\\(\\)\]*., which has already been marked with an OpenACC 'routine' directive" "" { target *-*-* } .-1 } */ \
+ gang gang gang /* { dg-error "too many 'gang' clauses" } */ \
+ /* { dg-error ".gang. specifies a conflicting level of parallelism" "" { target *-*-* } .-1 } */ \
+ vector vector vector vector /* { dg-error "too many 'vector' clauses" } */ \
+ /* { dg-error ".vector. specifies a conflicting level of parallelism" "" { target *-*-* } .-1 } */ \
+ worker worker worker worker /* { dg-error "too many 'worker' clauses" } */ \
+ /* { dg-error ".worker. specifies a conflicting level of parallelism" "" { target *-*-* } .-1 } */
+
+#pragma acc routine \
+ worker worker worker /* { dg-error "too many 'worker' clauses" } */ \
+ seq seq seq seq /* { dg-error "too many 'seq' clauses" } */ \
+ /* { dg-error ".seq. specifies a conflicting level of parallelism" "" { target *-*-* } .-1 } */ \
+ vector vector vector vector vector /* { dg-error "too many 'vector' clauses" } */ \
+ /* { dg-error ".vector. specifies a conflicting level of parallelism" "" { target *-*-* } .-1 } */ \
+ gang gang /* { dg-error "too many 'gang' clauses" } */ \
+ /* { dg-error ".gang. specifies a conflicting level of parallelism" "" { target *-*-* } .-1 } */
+extern void w_6 (void);
+#pragma acc routine (w_6) \
+ vector vector vector /* { dg-error "too many 'vector' clauses" } */ \
+ /* { dg-error "incompatible .vector. clause when applying .#pragma acc routine. to .\[void \]*w_6\[\\(\\)\]*., which has already been marked with an OpenACC 'routine' directive" "" { target *-*-* } .-1 } */ \
+ worker worker worker /* { dg-error "too many 'worker' clauses" } */ \
+ /* { dg-error ".worker. specifies a conflicting level of parallelism" "" { target *-*-* } .-1 } */ \
+ seq seq seq /* { dg-error "too many 'seq' clauses" } */ \
+ /* { dg-error ".seq. specifies a conflicting level of parallelism" "" { target *-*-* } .-1 } */ \
+ gang gang /* { dg-error "too many 'gang' clauses" } */ \
+ /* { dg-error ".gang. specifies a conflicting level of parallelism" "" { target *-*-* } .-1 } */
+#pragma acc routine (w_6) \
+ seq seq /* { dg-error "too many 'seq' clauses" } */ \
+ /* { dg-error "incompatible .seq. clause when applying .#pragma acc routine. to .\[void \]*w_6\[\\(\\)\]*., which has already been marked with an OpenACC 'routine' directive" "" { target *-*-* } .-1 } */ \
+ worker worker worker /* { dg-error "too many 'worker' clauses" } */ \
+ /* { dg-error ".worker. specifies a conflicting level of parallelism" "" { target *-*-* } .-1 } */ \
+ gang gang /* { dg-error "too many 'gang' clauses" } */ \
+ /* { dg-error ".gang. specifies a conflicting level of parallelism" "" { target *-*-* } .-1 } */ \
+ vector vector vector vector /* { dg-error "too many 'vector' clauses" } */ \
+ /* { dg-error ".vector. specifies a conflicting level of parallelism" "" { target *-*-* } .-1 } */
+
+#pragma acc routine \
+ vector vector vector /* { dg-error "too many 'vector' clauses" } */ \
+ worker worker worker /* { dg-error "too many 'worker' clauses" } */ \
+ /* { dg-error ".worker. specifies a conflicting level of parallelism" "" { target *-*-* } .-1 } */ \
+ seq seq seq seq seq seq /* { dg-error "too many 'seq' clauses" } */ \
+ /* { dg-error ".seq. specifies a conflicting level of parallelism" "" { target *-*-* } .-1 } */ \
+ gang gang /* { dg-error "too many 'gang' clauses" } */ \
+ /* { dg-error ".gang. specifies a conflicting level of parallelism" "" { target *-*-* } .-1 } */
+extern void v_6 (void);
+#pragma acc routine (v_6) \
+ seq seq seq seq seq seq /* { dg-error "too many 'seq' clauses" } */ \
+ /* { dg-error "incompatible .seq. clause when applying .#pragma acc routine. to .\[void \]*v_6\[\\(\\)\]*., which has already been marked with an OpenACC 'routine' directive" "" { target *-*-* } .-1 } */ \
+ vector vector vector /* { dg-error "too many 'vector' clauses" } */ \
+ /* { dg-error ".vector. specifies a conflicting level of parallelism" "" { target *-*-* } .-1 } */ \
+ worker worker /* { dg-error "too many 'worker' clauses" } */ \
+ /* { dg-error ".worker. specifies a conflicting level of parallelism" "" { target *-*-* } .-1 } */ \
+ gang gang /* { dg-error "too many 'gang' clauses" } */ \
+ /* { dg-error ".gang. specifies a conflicting level of parallelism" "" { target *-*-* } .-1 } */
+#pragma acc routine (v_6) \
+ gang gang /* { dg-error "too many 'gang' clauses" } */ \
+ /* { dg-error "incompatible .gang. clause when applying .#pragma acc routine. to .\[void \]*v_6\[\\(\\)\]*., which has already been marked with an OpenACC 'routine' directive" "" { target *-*-* } .-1 } */ \
+ vector vector vector /* { dg-error "too many 'vector' clauses" } */ \
+ /* { dg-error ".vector. specifies a conflicting level of parallelism" "" { target *-*-* } .-1 } */ \
+ seq seq seq seq seq /* { dg-error "too many 'seq' clauses" } */ \
+ /* { dg-error ".seq. specifies a conflicting level of parallelism" "" { target *-*-* } .-1 } */ \
+ worker worker /* { dg-error "too many 'worker' clauses" } */ \
+ /* { dg-error ".worker. specifies a conflicting level of parallelism" "" { target *-*-* } .-1 } */
+
+extern void s_6 (void);
+#pragma acc routine (s_6) \
+ seq seq seq /* { dg-error "too many 'seq' clauses" } */ \
+ vector vector vector vector /* { dg-error "too many 'vector' clauses" } */ \
+ /* { dg-error ".vector. specifies a conflicting level of parallelism" "" { target *-*-* } .-1 } */ \
+ worker worker worker worker worker /* { dg-error "too many 'worker' clauses" } */ \
+ /* { dg-error ".worker. specifies a conflicting level of parallelism" "" { target *-*-* } .-1 } */ \
+ gang gang /* { dg-error "too many 'gang' clauses" } */ \
+ /* { dg-error ".gang. specifies a conflicting level of parallelism" "" { target *-*-* } .-1 } */
+#pragma acc routine (s_6) \
+ vector vector vector vector /* { dg-error "too many 'vector' clauses" } */ \
+ /* { dg-error "incompatible .vector. clause when applying .#pragma acc routine. to .\[void \]*s_6\[\\(\\)\]*., which has already been marked with an OpenACC 'routine' directive" "" { target *-*-* } .-1 } */ \
+ seq seq seq /* { dg-error "too many 'seq' clauses" } */ \
+ /* { dg-error ".seq. specifies a conflicting level of parallelism" "" { target *-*-* } .-1 } */ \
+ gang gang /* { dg-error "too many 'gang' clauses" } */ \
+ /* { dg-error ".gang. specifies a conflicting level of parallelism" "" { target *-*-* } .-1 } */ \
+ worker worker worker /* { dg-error "too many 'worker' clauses" } */ \
+ /* { dg-error ".worker. specifies a conflicting level of parallelism" "" { target *-*-* } .-1 } */
+#pragma acc routine (s_6) \
+ worker worker /* { dg-error "too many 'worker' clauses" } */ \
+ /* { dg-error "incompatible .worker. clause when applying .#pragma acc routine. to .\[void \]*s_6\[\\(\\)\]*., which has already been marked with an OpenACC 'routine' directive" "" { target *-*-* } .-1 } */ \
+ seq seq seq /* { dg-error "too many 'seq' clauses" } */ \
+ /* { dg-error ".seq. specifies a conflicting level of parallelism" "" { target *-*-* } .-1 } */ \
+ vector vector vector vector /* { dg-error "too many 'vector' clauses" } */ \
+ /* { dg-error ".vector. specifies a conflicting level of parallelism" "" { target *-*-* } .-1 } */ \
+ gang gang /* { dg-error "too many 'gang' clauses" } */ \
+ /* { dg-error ".gang. specifies a conflicting level of parallelism" "" { target *-*-* } .-1 } */
+
+
+/* Like the *_6 tests, but without all the duplicate clauses, so that the
+ routine directives are valid in isolation. */
+
+#pragma acc routine \
+ gang
+void g_7 (void)
+{
+}
+#pragma acc routine (g_7) \
+ vector /* { dg-error "incompatible .vector. clause when applying .#pragma acc routine. to .\[void \]*g_7\[\\(\\)\]*., which has already been marked with an OpenACC 'routine' directive" } */
+#pragma acc routine (g_7) \
+ seq /* { dg-error "incompatible .seq. clause when applying .#pragma acc routine. to .\[void \]*g_7\[\\(\\)\]*., which has already been marked with an OpenACC 'routine' directive" } */
+
+#pragma acc routine \
+ worker
+extern void w_7 (void);
+#pragma acc routine (w_7) \
+ vector /* { dg-error "incompatible .vector. clause when applying .#pragma acc routine. to .\[void \]*w_7\[\\(\\)\]*., which has already been marked with an OpenACC 'routine' directive" } */
+#pragma acc routine (w_7) \
+ seq /* { dg-error "incompatible .seq. clause when applying .#pragma acc routine. to .\[void \]*w_7\[\\(\\)\]*., which has already been marked with an OpenACC 'routine' directive" } */
+
+#pragma acc routine \
+ vector
+extern void v_7 (void);
+#pragma acc routine (v_7) \
+ seq /* { dg-error "incompatible .seq. clause when applying .#pragma acc routine. to .\[void \]*v_7\[\\(\\)\]*., which has already been marked with an OpenACC 'routine' directive" } */
+#pragma acc routine (v_7) \
+ gang /* { dg-error "incompatible .gang. clause when applying .#pragma acc routine. to .\[void \]*v_7\[\\(\\)\]*., which has already been marked with an OpenACC 'routine' directive" } */
+
+extern void s_7 (void);
+#pragma acc routine (s_7) \
+ seq
+#pragma acc routine (s_7) \
+ vector /* { dg-error "incompatible .vector. clause when applying .#pragma acc routine. to .\[void \]*s_7\[\\(\\)\]*., which has already been marked with an OpenACC 'routine' directive" } */
+#pragma acc routine (s_7) \
+ worker /* { dg-error "incompatible .worker. clause when applying .#pragma acc routine. to .\[void \]*s_7\[\\(\\)\]*., which has already been marked with an OpenACC 'routine' directive" } */
+
+
+/* Test cases for implicit seq clause. */
+
+#pragma acc routine \
+ gang
+void g_8 (void)
+{
+}
+#pragma acc routine (g_8) /* { dg-error "incompatible .seq. clause when applying .#pragma acc routine. to .\[void \]*g_8\[\\(\\)\]*., which has already been marked with an OpenACC 'routine' directive" } */
+
+#pragma acc routine \
+ worker
+extern void w_8 (void);
+#pragma acc routine (w_8) /* { dg-error "incompatible .seq. clause when applying .#pragma acc routine. to .\[void \]*w_8\[\\(\\)\]*., which has already been marked with an OpenACC 'routine' directive" } */
+
+#pragma acc routine \
+ vector
+extern void v_8 (void);
+#pragma acc routine (v_8) /* { dg-error "incompatible .seq. clause when applying .#pragma acc routine. to .\[void \]*v_8\[\\(\\)\]*., which has already been marked with an OpenACC 'routine' directive" } */
+
+extern void s_8 (void);
+#pragma acc routine (s_8)
+#pragma acc routine (s_8) \
+ vector /* { dg-error "incompatible .vector. clause when applying .#pragma acc routine. to .\[void \]*s_8\[\\(\\)\]*., which has already been marked with an OpenACC 'routine' directive" } */
+#pragma acc routine (s_8) \
+ gang /* { dg-error "incompatible .gang. clause when applying .#pragma acc routine. to .\[void \]*s_8\[\\(\\)\]*., which has already been marked with an OpenACC 'routine' directive" } */
+#pragma acc routine (s_8) \
+ worker /* { dg-error "incompatible .worker. clause when applying .#pragma acc routine. to .\[void \]*s_8\[\\(\\)\]*., which has already been marked with an OpenACC 'routine' directive" } */
diff --git a/gcc/testsuite/c-c++-common/goacc/routine-level-of-parallelism-2.c b/gcc/testsuite/c-c++-common/goacc/routine-level-of-parallelism-2.c
new file mode 100644
index 0000000..a066f2b
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/goacc/routine-level-of-parallelism-2.c
@@ -0,0 +1,71 @@
+/* Test various aspects of clauses specifying compatible levels of parallelism
+ with the OpenACC 'routine' directive. The Fortran counterpart is
+ '../../gfortran.dg/goacc/routine-level-of-parallelism-1.f90'. */
+
+#pragma acc routine gang
+void g_1 (void)
+{
+}
+#pragma acc routine (g_1) gang
+#pragma acc routine (g_1) gang
+
+
+extern void w_1 (void);
+#pragma acc routine (w_1) worker
+#pragma acc routine (w_1) worker
+#pragma acc routine (w_1) worker
+
+
+#pragma acc routine vector
+extern void v_1 (void);
+#pragma acc routine (v_1) vector
+#pragma acc routine (v_1) vector
+
+
+/* Also test the implicit seq clause. */
+
+#pragma acc routine seq
+extern void s_1_1 (void);
+#pragma acc routine (s_1_1)
+#pragma acc routine (s_1_1) seq
+#pragma acc routine (s_1_1)
+#pragma acc routine (s_1_1) seq
+
+#pragma acc routine
+extern void s_1_2 (void);
+#pragma acc routine (s_1_2)
+#pragma acc routine (s_1_2) seq
+#pragma acc routine (s_1_2)
+#pragma acc routine (s_1_2) seq
+
+extern void s_2_1 (void);
+#pragma acc routine (s_2_1) seq
+#pragma acc routine (s_2_1)
+#pragma acc routine (s_2_1) seq
+#pragma acc routine (s_2_1)
+#pragma acc routine (s_2_1) seq
+
+extern void s_2_2 (void);
+#pragma acc routine (s_2_2)
+#pragma acc routine (s_2_2)
+#pragma acc routine (s_2_2) seq
+#pragma acc routine (s_2_2)
+#pragma acc routine (s_2_2) seq
+
+#pragma acc routine seq
+void s_3_1 (void)
+{
+}
+#pragma acc routine (s_3_1)
+#pragma acc routine (s_3_1) seq
+#pragma acc routine (s_3_1)
+#pragma acc routine (s_3_1) seq
+
+#pragma acc routine
+void s_3_2 (void)
+{
+}
+#pragma acc routine (s_3_2)
+#pragma acc routine (s_3_2) seq
+#pragma acc routine (s_3_2)
+#pragma acc routine (s_3_2) seq
diff --git a/gcc/testsuite/c-c++-common/gomp/lastprivate-conditional-2.c b/gcc/testsuite/c-c++-common/gomp/lastprivate-conditional-2.c
index 4b1d2ca..9330beb 100644
--- a/gcc/testsuite/c-c++-common/gomp/lastprivate-conditional-2.c
+++ b/gcc/testsuite/c-c++-common/gomp/lastprivate-conditional-2.c
@@ -4,24 +4,24 @@ foo (int *p)
int a = -1, b = -1, c = -1, d = -1, e = -1, f = -1, g = -1, h = -1;
int i;
#pragma omp parallel
- #pragma omp for lastprivate (conditional: a) /* { dg-message "not supported yet" } */
+ #pragma omp for lastprivate (conditional: a)
for (i = 0; i < 32; i++)
if (p[i])
a = i;
- #pragma omp simd lastprivate (conditional: b) /* { dg-message "not supported yet" } */
+ #pragma omp simd lastprivate (conditional: b)
for (i = 0; i < 32; i++)
if (p[i])
b = i;
#pragma omp parallel
- #pragma omp for simd lastprivate (conditional: c) /* { dg-message "not supported yet" } */
+ #pragma omp for simd lastprivate (conditional: c)
for (i = 0; i < 32; i++)
if (p[i])
c = i;
- #pragma omp parallel for lastprivate (conditional: d) /* { dg-message "not supported yet" } */
+ #pragma omp parallel for lastprivate (conditional: d)
for (i = 0; i < 32; i++)
if (p[i])
d = i;
- #pragma omp parallel for simd lastprivate (conditional: e) /* { dg-message "not supported yet" } */
+ #pragma omp parallel for simd lastprivate (conditional: e)
for (i = 0; i < 32; i++)
if (p[i])
e = i;
diff --git a/gcc/testsuite/c-c++-common/gomp/lastprivate-conditional-3.c b/gcc/testsuite/c-c++-common/gomp/lastprivate-conditional-3.c
new file mode 100644
index 0000000..dc9b003
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/gomp/lastprivate-conditional-3.c
@@ -0,0 +1,44 @@
+void
+foo (int *p)
+{
+ int i, j, k;
+ #pragma omp parallel
+ {
+ #pragma omp for lastprivate (conditional: i) /* { dg-warning "conditional 'lastprivate' on loop iterator 'i' ignored" } */
+ for (i = 0; i < 32; i++)
+ ;
+ #pragma omp for collapse (3) lastprivate (conditional: i) /* { dg-warning "conditional 'lastprivate' on loop iterator 'i' ignored" } */
+ for (i = 0; i < 32; i++)
+ for (j = 0; j < 32; ++j)
+ for (k = 0; k < 2; ++k)
+ ;
+ #pragma omp for collapse (3) lastprivate (conditional: j) /* { dg-warning "conditional 'lastprivate' on loop iterator 'j' ignored" } */
+ for (i = 0; i < 32; i++)
+ for (j = 0; j < 32; ++j)
+ for (k = 0; k < 2; ++k)
+ ;
+ #pragma omp for collapse (3) lastprivate (conditional: k) /* { dg-warning "conditional 'lastprivate' on loop iterator 'k' ignored" } */
+ for (i = 0; i < 32; i++)
+ for (j = 0; j < 32; ++j)
+ for (k = 0; k < 2; ++k)
+ ;
+ }
+ #pragma omp parallel for lastprivate (conditional: i) /* { dg-warning "conditional 'lastprivate' on loop iterator 'i' ignored" } */
+ for (i = 0; i < 32; i++)
+ ;
+ #pragma omp parallel for collapse (3) lastprivate (conditional: i) /* { dg-warning "conditional 'lastprivate' on loop iterator 'i' ignored" } */
+ for (i = 0; i < 32; i++)
+ for (j = 0; j < 32; ++j)
+ for (k = 0; k < 2; ++k)
+ ;
+ #pragma omp parallel for collapse (3) lastprivate (conditional: j) /* { dg-warning "conditional 'lastprivate' on loop iterator 'j' ignored" } */
+ for (i = 0; i < 32; i++)
+ for (j = 0; j < 32; ++j)
+ for (k = 0; k < 2; ++k)
+ ;
+ #pragma omp parallel for collapse (3) lastprivate (conditional: k) /* { dg-warning "conditional 'lastprivate' on loop iterator 'k' ignored" } */
+ for (i = 0; i < 32; i++)
+ for (j = 0; j < 32; ++j)
+ for (k = 0; k < 2; ++k)
+ ;
+}
diff --git a/gcc/testsuite/c-c++-common/gomp/lastprivate-conditional-4.c b/gcc/testsuite/c-c++-common/gomp/lastprivate-conditional-4.c
new file mode 100644
index 0000000..d87c798
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/gomp/lastprivate-conditional-4.c
@@ -0,0 +1,23 @@
+int x = 6, w = 8;
+int bar (int);
+
+void
+foo ()
+{
+ int y = 5, i;
+ #pragma omp teams num_teams(1) firstprivate (x) shared (y) shared (w)
+ {
+ int z = 7;
+ #pragma omp parallel for firstprivate (x, y, z, w) lastprivate (conditional: x, y, z, w)
+ for (i = 0; i < 64; i++)
+ if (bar (i))
+ {
+ x = i;
+ y = i + 1;
+ z = i + 2;
+ w = i + 3;
+ }
+ bar (y);
+ bar (z);
+ }
+}
diff --git a/gcc/testsuite/c-c++-common/gomp/lastprivate-conditional-5.c b/gcc/testsuite/c-c++-common/gomp/lastprivate-conditional-5.c
new file mode 100644
index 0000000..51f6b30
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/gomp/lastprivate-conditional-5.c
@@ -0,0 +1,33 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fopenmp -fdump-tree-ompexp" } */
+/* { dg-final { scan-tree-dump-times "GOMP_loop_start " 3 "ompexp" } } */
+/* { dg-final { scan-tree-dump-times "GOMP_loop_end_nowait " 3 "ompexp" } } */
+
+int r;
+
+void
+foo (int *a)
+{
+ #pragma omp for nowait lastprivate(conditional: r)
+ for (int i = 0; i < 64; ++i)
+ if (a[i])
+ r = a[i];
+}
+
+void
+bar (int *a)
+{
+ #pragma omp for nowait lastprivate(conditional: r) schedule (static, 4)
+ for (int i = 0; i < 64; ++i)
+ if (a[i])
+ r = a[i];
+}
+
+void
+baz (int *a)
+{
+ #pragma omp for nowait lastprivate(conditional: r) schedule (runtime)
+ for (int i = 0; i < 64; ++i)
+ if (a[i])
+ r = a[i];
+}
diff --git a/gcc/testsuite/c-c++-common/gomp/pr90954.c b/gcc/testsuite/c-c++-common/gomp/pr90954.c
new file mode 100644
index 0000000..cc3a6e9
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/gomp/pr90954.c
@@ -0,0 +1,27 @@
+/* PR sanitizer/90954 */
+/* { dg-do compile } */
+/* { dg-options "-fopenmp -fsanitize=undefined" } */
+
+float v;
+int i;
+
+void
+foo (float x, float y)
+{
+ #pragma omp atomic
+ v += x / y;
+}
+
+void
+bar (int x, int y)
+{
+ #pragma omp atomic
+ i += x / y;
+}
+
+void
+baz (int x, int y)
+{
+ #pragma omp atomic
+ i *= (x << y);
+}
diff --git a/gcc/testsuite/c-c++-common/gomp/scan-1.c b/gcc/testsuite/c-c++-common/gomp/scan-1.c
new file mode 100644
index 0000000..17804e3
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/gomp/scan-1.c
@@ -0,0 +1,209 @@
+int a, b;
+
+void
+f1 (void)
+{
+ #pragma omp scan inclusive (a) /* { dg-error "'#pragma omp scan' may only be used in a loop construct with 'inscan' 'reduction' clause" } */
+ #pragma omp scan exclusive (b) /* { dg-error "'#pragma omp scan' may only be used in a loop construct with 'inscan' 'reduction' clause" } */
+}
+
+void
+f2 (int *c, int *d, int *e, int *f)
+{
+ int i, l = 1;
+ #pragma omp for reduction (inscan, +: a) reduction (+: b) /* { dg-error "'inscan' and non-'inscan' 'reduction' clauses on the same construct" } */
+ for (i = 0; i < 64; i++)
+ {
+ { b++; a += c[i]; }
+ #pragma omp scan inclusive (a) /* { dg-error "" } */
+ d[i] = a;
+ }
+ #pragma omp for reduction (+: a) reduction (inscan, +: b) /* { dg-error "'inscan' and non-'inscan' 'reduction' clauses on the same construct" } */
+ for (i = 0; i < 64; i++)
+ {
+ { a++; b += c[i]; }
+ #pragma omp scan inclusive (b) /* { dg-error "" } */
+ d[i] = b;
+ }
+ #pragma omp for reduction (inscan, +: e[:2]) /* { dg-error "'inscan' 'reduction' clause with array section" } */
+ for (i = 0; i < 64; ++i)
+ {
+ { e[0] += c[i]; e[1] += c[i]; }
+ #pragma omp scan inclusive (a, e[:2]) /* { dg-error "" } */
+ { d[i] = e[0]; f[i] = e[1]; }
+ }
+ #pragma omp for reduction (inscan, +: a) ordered /* { dg-error "'ordered' clause specified together with 'inscan' 'reduction' clause" } */
+ for (i = 0; i < 64; i++)
+ {
+ a += c[i];
+ #pragma omp scan inclusive (a) /* { dg-error "" } */
+ d[i] = a;
+ }
+ #pragma omp for reduction (inscan, +: a) ordered(1) /* { dg-error "'ordered' clause specified together with 'inscan' 'reduction' clause" } */
+ for (i = 0; i < 64; i++)
+ {
+ a += c[i];
+ #pragma omp scan inclusive (a) /* { dg-error "" } */
+ d[i] = a;
+ }
+ #pragma omp for reduction (inscan, +: a) schedule(static) /* { dg-error "'schedule' clause specified together with 'inscan' 'reduction' clause" } */
+ for (i = 0; i < 64; i++)
+ {
+ a += c[i];
+ #pragma omp scan inclusive (a) /* { dg-error "" } */
+ d[i] = a;
+ }
+ #pragma omp for reduction (inscan, +: a) schedule(static, 2) /* { dg-error "'schedule' clause specified together with 'inscan' 'reduction' clause" } */
+ for (i = 0; i < 64; i++)
+ {
+ a += c[i];
+ #pragma omp scan inclusive (a) /* { dg-error "" } */
+ d[i] = a;
+ }
+ #pragma omp for reduction (inscan, +: a) schedule(nonmonotonic: dynamic, 2) /* { dg-error "'schedule' clause specified together with 'inscan' 'reduction' clause" } */
+ for (i = 0; i < 64; i++)
+ {
+ a += c[i];
+ #pragma omp scan inclusive (a) /* { dg-error "" } */
+ d[i] = a;
+ }
+ #pragma omp for reduction (inscan, +: a) linear (l) /* { dg-error "'inscan' 'reduction' clause used together with 'linear' clause for a variable other than loop iterator" } */
+ for (i = 0; i < 64; i++)
+ {
+ { a += c[i]; ++l; }
+ #pragma omp scan inclusive (a)
+ d[i] = a;
+ }
+}
+
+void
+f3 (int *c, int *d)
+{
+ int i;
+ #pragma omp teams reduction (inscan, +: a) /* { dg-error "'inscan' 'reduction' clause on 'teams' construct" } */
+ ;
+ #pragma omp parallel reduction (inscan, +: a) /* { dg-error "'inscan' 'reduction' clause on 'parallel' construct" } */
+ ;
+ #pragma omp sections reduction (inscan, +: a) /* { dg-error "'inscan' 'reduction' clause on 'sections' construct" } */
+ {
+ #pragma omp section
+ ;
+ }
+ #pragma omp target parallel for reduction (inscan, +: a) map (c[:64], d[:64]) /* { dg-error "'inscan' 'reduction' clause on construct other than 'for', 'simd', 'for simd', 'parallel for', 'parallel for simd'" } */
+ for (i = 0; i < 64; i++)
+ {
+ d[i] = a;
+ #pragma omp scan exclusive (a) /* { dg-error "" } */
+ a += c[i];
+ }
+ #pragma omp teams
+ {
+ #pragma omp distribute parallel for reduction (inscan, +: a) /* { dg-error "'inscan' 'reduction' clause on construct other than 'for', 'simd', 'for simd', 'parallel for', 'parallel for simd'" } */
+ for (i = 0; i < 64; i++)
+ {
+ d[i] = a;
+ #pragma omp scan exclusive (a) /* { dg-error "" } */
+ a += c[i];
+ }
+ #pragma omp distribute parallel for simd reduction (inscan, +: a) /* { dg-error "'inscan' 'reduction' clause on construct other than 'for', 'simd', 'for simd', 'parallel for', 'parallel for simd'" } */
+ for (i = 0; i < 64; i++)
+ {
+ d[i] = a;
+ #pragma omp scan exclusive (a) /* { dg-error "" } */
+ a += c[i];
+ }
+ }
+}
+
+void
+f4 (int *c, int *d)
+{
+ int i;
+ #pragma omp taskloop reduction (inscan, +: a) /* { dg-error "'inscan' 'reduction' clause on 'taskloop' construct" } */
+ for (i = 0; i < 64; i++)
+ {
+ d[i] = a;
+ #pragma omp scan exclusive (a) /* { dg-error "" } */
+ a += c[i];
+ }
+}
+
+void
+f5 (int *c, int *d)
+{
+ int i;
+ #pragma omp simd reduction (inscan, +: a)
+ for (i = 0; i < 64; i++)
+ {
+ d[i] = a;
+ #pragma omp scan exclusive (a, b) /* { dg-error "'b' specified in 'exclusive' clause but not in 'inscan' 'reduction' clause on the containing construct" } */
+ a += c[i];
+ }
+}
+
+void
+f6 (int *c, int *d)
+{
+ int i;
+ #pragma omp simd reduction (inscan, +: a, b) /* { dg-error "'b' specified in 'inscan' 'reduction' clause but not in 'scan' directive clause" } */
+ for (i = 0; i < 64; i++)
+ {
+ d[i] = a;
+ #pragma omp scan exclusive (a)
+ a += c[i];
+ }
+}
+
+void
+f7 (void)
+{
+ int i;
+ #pragma omp simd reduction (inscan, +: a)
+ for (i = 0; i < 64; i++)
+ {
+ if (i == 23) /* { dg-error "invalid exit from OpenMP structured block" "" { target c++ } .+1 } */
+ continue; /* { dg-error "invalid branch to/from OpenMP structured block" "" { target c } } */
+ else if (i == 27)
+ goto l1; /* { dg-error "invalid branch to/from OpenMP structured block" } */
+ #pragma omp scan exclusive (a)
+ {
+ l1: a = 0; /* { dg-error "jump to label 'l1'" "" { target c++ } } */
+ if (i == 33) /* { dg-error "invalid exit from OpenMP structured block" "" { target c++ } .+1 } */
+ continue; /* { dg-error "invalid branch to/from OpenMP structured block" "" { target c } } */
+ }
+ }
+}
+
+void
+f8 (int *c, int *d, int *e, int *f)
+{
+ int i;
+ #pragma omp for reduction (inscan, +: a, b) /* { dg-error "'b' specified in 'inscan' 'reduction' clause but not in 'scan' directive clause" } */
+ for (i = 0; i < 64; i++)
+ {
+ { a += c[i]; b += d[i]; }
+ #pragma omp scan inclusive (a) inclusive (b) /* { dg-error "expected end of line before 'inclusive'" } */
+ { e[i] = a; f[i] = b; }
+ }
+ #pragma omp for reduction (inscan, +: a, b) /* { dg-error "'.' specified in 'inscan' 'reduction' clause but not in 'scan' directive clause" } */
+ for (i = 0; i < 64; i++)
+ {
+ { a += c[i]; b += d[i]; }
+ #pragma omp scan /* { dg-error "expected 'inclusive' or 'exclusive' clause before end of line" } */
+ { e[i] = a; f[i] = b; }
+ }
+}
+
+void
+f9 (void)
+{
+ int i;
+ #pragma omp simd reduction (inscan, +: a)
+ for (i = 0; i < 64; i++)
+ {
+ if (i == 23) /* { dg-error "invalid exit from OpenMP structured block" "" { target c++ } .+1 } */
+ break; /* { dg-error "break statement used with OpenMP for loop" "" { target c } } */
+ #pragma omp scan exclusive (a)
+ a++;
+ }
+}
diff --git a/gcc/testsuite/c-c++-common/gomp/scan-2.c b/gcc/testsuite/c-c++-common/gomp/scan-2.c
new file mode 100644
index 0000000..4f322ab
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/gomp/scan-2.c
@@ -0,0 +1,14 @@
+int a, b;
+
+void
+f1 (int *c, int *d)
+{
+ int i;
+ #pragma omp simd reduction (inscan, +: a)
+ for (i = 0; i < 64; i++)
+ {
+ d[i] = a;
+ #pragma omp scan exclusive (a)
+ a += c[i];
+ }
+}
diff --git a/gcc/testsuite/c-c++-common/gomp/scan-3.c b/gcc/testsuite/c-c++-common/gomp/scan-3.c
new file mode 100644
index 0000000..4e290eb
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/gomp/scan-3.c
@@ -0,0 +1,14 @@
+int a, b;
+
+void
+f1 (int *c, int *d)
+{
+ int i;
+ #pragma omp for reduction (inscan, +: a)
+ for (i = 0; i < 64; i++)
+ {
+ d[i] = a;
+ #pragma omp scan inclusive (a)
+ a += c[i];
+ }
+}
diff --git a/gcc/testsuite/c-c++-common/gomp/scan-4.c b/gcc/testsuite/c-c++-common/gomp/scan-4.c
new file mode 100644
index 0000000..32d4006
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/gomp/scan-4.c
@@ -0,0 +1,14 @@
+int a, b;
+
+void
+f1 (int *c, int *d)
+{
+ int i;
+ #pragma omp for simd reduction (inscan, +: a)
+ for (i = 0; i < 64; i++)
+ {
+ d[i] = a;
+ #pragma omp scan exclusive (a) /* { dg-message "sorry, unimplemented: '#pragma omp scan' not supported yet" } */
+ a += c[i];
+ }
+}
diff --git a/gcc/testsuite/c-c++-common/gomp/scan-5.c b/gcc/testsuite/c-c++-common/gomp/scan-5.c
new file mode 100644
index 0000000..8241621
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/gomp/scan-5.c
@@ -0,0 +1,13 @@
+int
+foo (int *a, int *b)
+{
+ int r = 0;
+ #pragma omp parallel for reduction (inscan, +:r) default(none) firstprivate (a, b)
+ for (int i = 0; i < 64; i++)
+ {
+ r += a[i];
+ #pragma omp scan inclusive (r)
+ b[i] = r;
+ }
+ return r;
+}
diff --git a/gcc/testsuite/c-c++-common/gomp/simd8.c b/gcc/testsuite/c-c++-common/gomp/simd8.c
new file mode 100644
index 0000000..11f7411
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/gomp/simd8.c
@@ -0,0 +1,37 @@
+/* { dg-do compile } */
+/* { dg-options "-fopenmp -O3 -fdump-tree-vect-details" } */
+/* { dg-final { scan-tree-dump-times "vectorized 0 loops in function" 4 "vect" } } */
+
+int a[1024];
+
+void
+foo (void)
+{
+ #pragma omp simd if (0)
+ for (int i = 0; i < 1024; ++i)
+ a[i] = a[i] + 1;
+}
+
+void
+bar (void)
+{
+ #pragma omp simd if (0) safelen (256) simdlen (8)
+ for (int i = 0; i < 512; ++i)
+ a[i] = a[i] + 1;
+}
+
+void
+baz (void)
+{
+ #pragma omp simd safelen (256) simdlen (1)
+ for (int i = 0; i < 512; ++i)
+ a[i] = a[i] + 1;
+}
+
+void
+qux (void)
+{
+ #pragma omp simd simdlen (1) if (1)
+ for (int i = 0; i < 512; ++i)
+ a[i] = a[i] + 1;
+}
diff --git a/gcc/testsuite/c-c++-common/nonnull-1.c b/gcc/testsuite/c-c++-common/nonnull-1.c
index 2446d6f..ea98736 100644
--- a/gcc/testsuite/c-c++-common/nonnull-1.c
+++ b/gcc/testsuite/c-c++-common/nonnull-1.c
@@ -8,27 +8,27 @@
void foo(void *bar) __attribute__((nonnull(1)));
-void foo(void *bar) { if (!bar) abort(); } /* { dg-warning "nonnull argument" "bar compared to NULL" } */
+void foo(void *bar) { if (!bar) abort(); } /* { dg-warning "'nonnull' argument" "bar compared to NULL" } */
extern int func (char *, char *, char *, char *) __attribute__((nonnull));
int
func (char *cp1, char *cp2, char *cp3, char *cp4)
{
- if (cp1) /* { dg-warning "nonnull argument" "cp1 compared to NULL" } */
+ if (cp1) /* { dg-warning "'nonnull' argument" "cp1 compared to NULL" } */
return 1;
- if (cp2 == NULL) /* { dg-warning "nonnull argument" "cp2 compared to NULL" } */
+ if (cp2 == NULL) /* { dg-warning "'nonnull' argument" "cp2 compared to NULL" } */
return 2;
- if (NULL != cp3) /* { dg-warning "nonnull argument" "cp3 compared to NULL" } */
+ if (NULL != cp3) /* { dg-warning "'nonnull' argument" "cp3 compared to NULL" } */
return 3;
- return cp4 != 0 ? 0 : 1; /* { dg-warning "nonnull argument" "cp4 compared to NULL" } */
+ return cp4 != 0 ? 0 : 1; /* { dg-warning "'nonnull' argument" "cp4 compared to NULL" } */
}
__attribute__((nonnull (1))) int
func2 (char *cp)
{
- return (cp != NULL) ? 1 : 0; /* { dg-warning "nonnull argument" "cp compared to NULL" { xfail c++ } } */
+ return (cp != NULL) ? 1 : 0; /* { dg-warning "'nonnull' argument" "cp compared to NULL" { xfail c++ } } */
}
diff --git a/gcc/testsuite/c-c++-common/nonnull-2.c b/gcc/testsuite/c-c++-common/nonnull-2.c
index ebd17a2..19574cd 100644
--- a/gcc/testsuite/c-c++-common/nonnull-2.c
+++ b/gcc/testsuite/c-c++-common/nonnull-2.c
@@ -7,19 +7,19 @@ void bar (char **);
__attribute__((nonnull (1, 3))) int
foo (char *cp1, char *cp2, char *cp3, char *cp4)
{
- if (cp1 == (char *) 0) /* { dg-warning "nonnull argument" "cp1 compared to NULL" } */
+ if (cp1 == (char *) 0) /* { dg-warning "'nonnull' argument" "cp1 compared to NULL" } */
return 1;
cp1 = cp2;
- if (cp1 == (char *) 0) /* { dg-bogus "nonnull argument" } */
+ if (cp1 == (char *) 0) /* { dg-bogus "'nonnull' argument" } */
return 2;
- if (!cp4) /* { dg-bogus "nonnull argument" } */
+ if (!cp4) /* { dg-bogus "'nonnull' argument" } */
return 3;
char **p = &cp3;
bar (p);
- if (cp3 == (char *) 0) /* { dg-bogus "nonnull argument" } */
+ if (cp3 == (char *) 0) /* { dg-bogus "'nonnull' argument" } */
return 4;
return 5;
diff --git a/gcc/testsuite/c-c++-common/nonnull-3.c b/gcc/testsuite/c-c++-common/nonnull-3.c
index d2ccb24..42081c8 100644
--- a/gcc/testsuite/c-c++-common/nonnull-3.c
+++ b/gcc/testsuite/c-c++-common/nonnull-3.c
@@ -7,5 +7,5 @@ enum { r = 1 };
__attribute__ ((nonnull (r))) int
f (int *p)
{
- return p == 0; /* { dg-warning "nonnull argument 'p' compared to NULL" } */
+ return p == 0; /* { dg-warning "'nonnull' argument 'p' compared to NULL" } */
}
diff --git a/gcc/testsuite/c-c++-common/pr35503-1.c b/gcc/testsuite/c-c++-common/pr35503-1.c
index 25e3721..11075dd 100644
--- a/gcc/testsuite/c-c++-common/pr35503-1.c
+++ b/gcc/testsuite/c-c++-common/pr35503-1.c
@@ -6,5 +6,5 @@ int foo (char *__restrict buf, const char *__restrict fmt, ...);
void f(void)
{
char buf[100] = "hello";
- foo (buf, "%s-%s", buf, "world"); /* { dg-warning "passing argument 1 to restrict-qualified parameter aliases with argument 3" } */
+ foo (buf, "%s-%s", buf, "world"); /* { dg-warning "passing argument 1 to 'restrict'-qualified parameter aliases with argument 3" } */
}
diff --git a/gcc/testsuite/c-c++-common/pr35503-2.c b/gcc/testsuite/c-c++-common/pr35503-2.c
index bfcd944..887576c 100644
--- a/gcc/testsuite/c-c++-common/pr35503-2.c
+++ b/gcc/testsuite/c-c++-common/pr35503-2.c
@@ -5,7 +5,7 @@ void f(int *__restrict x, int *y, int *__restrict z, int *w);
void foo(int alpha, int beta)
{
- f (&alpha, &beta, &alpha, &alpha); /* { dg-warning "passing argument 1 to restrict-qualified parameter aliases with arguments 3, 4" } */
+ f (&alpha, &beta, &alpha, &alpha); /* { dg-warning "passing argument 1 to 'restrict'-qualified parameter aliases with arguments 3, 4" } */
/* { dg-begin-multiline-output "" }
f (&alpha, &beta, &alpha, &alpha);
diff --git a/gcc/testsuite/c-c++-common/pr35503-3.c b/gcc/testsuite/c-c++-common/pr35503-3.c
index 8cbacab..8d4b1fc 100644
--- a/gcc/testsuite/c-c++-common/pr35503-3.c
+++ b/gcc/testsuite/c-c++-common/pr35503-3.c
@@ -5,5 +5,5 @@ void f(int *x, int *__restrict y);
void foo(int a)
{
- f (&a, &a); /* { dg-warning "passing argument 2 to restrict-qualified parameter aliases with argument 1" } */
+ f (&a, &a); /* { dg-warning "passing argument 2 to 'restrict'-qualified parameter aliases with argument 1" } */
}
diff --git a/gcc/testsuite/c-c++-common/pr51768.c b/gcc/testsuite/c-c++-common/pr51768.c
index 082594c..c300392 100644
--- a/gcc/testsuite/c-c++-common/pr51768.c
+++ b/gcc/testsuite/c-c++-common/pr51768.c
@@ -5,7 +5,7 @@
void
foo (void)
{
- asm goto ("" : : : : lab, lab, lab2, lab); /* { dg-error "duplicate asm operand name" } */
+ asm goto ("" : : : : lab, lab, lab2, lab); /* { dg-error "duplicate 'asm' operand name" } */
lab:;
lab2:;
}
@@ -13,7 +13,7 @@ lab2:;
void
bar (void)
{
- asm goto ("" : : [lab] "i" (0) : : lab); /* { dg-error "duplicate asm operand name" } */
+ asm goto ("" : : [lab] "i" (0) : : lab); /* { dg-error "duplicate 'asm' operand name" } */
lab:;
}
@@ -21,5 +21,5 @@ void
baz (void)
{
int x;
- asm ("" : [lab] "=r" (x) : [lab] "r" (x)); /* { dg-error "duplicate asm operand name" } */
+ asm ("" : [lab] "=r" (x) : [lab] "r" (x)); /* { dg-error "duplicate 'asm' operand name" } */
}
diff --git a/gcc/testsuite/c-c++-common/pr90927.c b/gcc/testsuite/c-c++-common/pr90927.c
new file mode 100644
index 0000000..6b0d348
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/pr90927.c
@@ -0,0 +1,6 @@
+/* { dg-do preprocess } */
+/* { dg-additional-options "-M -MQ b\\\$ob -MT b\\\$ill" } */
+
+int i;
+
+/* { dg-final { scan-file pr90927.i {b\$ill b\$\$ob:} } } */
diff --git a/gcc/testsuite/c-c++-common/scal-to-vec1.c b/gcc/testsuite/c-c++-common/scal-to-vec1.c
index 52cc2e3..4ffdc59 100644
--- a/gcc/testsuite/c-c++-common/scal-to-vec1.c
+++ b/gcc/testsuite/c-c++-common/scal-to-vec1.c
@@ -35,9 +35,9 @@ int main (int argc, char *argv[]) {
f1 = ((int)998769576) + f0; /* { dg-error "conversion of scalar \[^\\n\]* to vector" "scalar to vector" { target { ! int16 } } } */
/* convert.c should take care of this. */
- i1 = sfl + i0; /* { dg-error "can't convert value to a vector|invalid operands" } */
- i1 = 1.5 + i0; /* { dg-error "can't convert value to a vector|invalid operands" } */
- v1 = d + v0; /* { dg-error "can't convert value to a vector|invalid operands" } */
+ i1 = sfl + i0; /* { dg-error "cannot convert value to a vector|invalid operands" } */
+ i1 = 1.5 + i0; /* { dg-error "cannot convert value to a vector|invalid operands" } */
+ v1 = d + v0; /* { dg-error "cannot convert value to a vector|invalid operands" } */
return 0;
}
diff --git a/gcc/testsuite/c-c++-common/tm/inline-asm.c b/gcc/testsuite/c-c++-common/tm/inline-asm.c
index eefd347..7389260 100644
--- a/gcc/testsuite/c-c++-common/tm/inline-asm.c
+++ b/gcc/testsuite/c-c++-common/tm/inline-asm.c
@@ -4,7 +4,7 @@
static inline void
inline_death ()
{
- __asm__ (""); /* { dg-error "asm not allowed" } */
+ __asm__ (""); /* { dg-error "'asm' not allowed" } */
}
void
diff --git a/gcc/testsuite/c-c++-common/tm/safe-1.c b/gcc/testsuite/c-c++-common/tm/safe-1.c
index 4a81a78..504113e 100644
--- a/gcc/testsuite/c-c++-common/tm/safe-1.c
+++ b/gcc/testsuite/c-c++-common/tm/safe-1.c
@@ -39,8 +39,8 @@ foo(void)
(*pi)(); /* { dg-error "unsafe indirect function call" } */
(*pu)(); /* { dg-error "unsafe indirect function call" } */
- asm(""); /* { dg-error "asm not allowed" } */
- asm("" : "=g"(i)); /* { dg-error "asm not allowed" } */
+ asm(""); /* { dg-error "'asm' not allowed" } */
+ asm("" : "=g"(i)); /* { dg-error "'asm' not allowed" } */
return fc(i);
}
@@ -62,8 +62,8 @@ bar(void)
(*pm)();
(*pu)(); /* { dg-error "unsafe indirect function call" } */
- asm(""); /* { dg-error "asm not allowed" } */
- asm("" : "=g"(i)); /* { dg-error "asm not allowed" } */
+ asm(""); /* { dg-error "'asm' not allowed" } */
+ asm("" : "=g"(i)); /* { dg-error "'asm' not allowed" } */
return fc(i);
}
diff --git a/gcc/testsuite/g++.dg/DRs/dr1940.C b/gcc/testsuite/g++.dg/DRs/dr1940.C
new file mode 100644
index 0000000..dee4ae9
--- /dev/null
+++ b/gcc/testsuite/g++.dg/DRs/dr1940.C
@@ -0,0 +1,13 @@
+// DR 1940 - static_assert in anonymous unions
+// { dg-do compile { target c++11 } }
+
+namespace N {
+ static union { int i; static_assert(1, ""); };
+}
+
+void
+g ()
+{
+ union { int j; static_assert(1, ""); };
+ N::i = 42;
+}
diff --git a/gcc/testsuite/g++.dg/abi/empty12.C b/gcc/testsuite/g++.dg/abi/empty12.C
index 20d85ff..6568fc62 100644
--- a/gcc/testsuite/g++.dg/abi/empty12.C
+++ b/gcc/testsuite/g++.dg/abi/empty12.C
@@ -2,7 +2,7 @@
// { dg-do run { target { { i?86-*-* x86_64-*-* } && { ! { ia32 } } } } }
// { dg-options "-Wabi=11 -x c" }
// { dg-additional-sources "empty12a.c" }
-// { dg-prune-output "command line option" }
+// { dg-prune-output "command-line option" }
#include "empty12.h"
extern "C" void fun(struct dummy, struct foo);
diff --git a/gcc/testsuite/g++.dg/abi/empty13.C b/gcc/testsuite/g++.dg/abi/empty13.C
index 0cb9a37..9ec1887 100644
--- a/gcc/testsuite/g++.dg/abi/empty13.C
+++ b/gcc/testsuite/g++.dg/abi/empty13.C
@@ -2,7 +2,7 @@
// { dg-do run { target { { i?86-*-* x86_64-*-* } && { ! { ia32 } } } } }
// { dg-options "-x c -fabi-version=11" }
// { dg-additional-sources "empty13a.c" }
-// { dg-prune-output "command line option" }
+// { dg-prune-output "command-line option" }
#include "empty13.h"
extern "C" void fun(struct dummy, struct foo);
diff --git a/gcc/testsuite/g++.dg/abi/empty14.C b/gcc/testsuite/g++.dg/abi/empty14.C
index 2868d8a..7deb463 100644
--- a/gcc/testsuite/g++.dg/abi/empty14.C
+++ b/gcc/testsuite/g++.dg/abi/empty14.C
@@ -2,7 +2,7 @@
// { dg-do run { target { { i?86-*-* x86_64-*-* } && { ! { ia32 } } } } }
// { dg-options "-Wabi=11 -x c" }
// { dg-additional-sources "empty14a.c" }
-// { dg-prune-output "command line option" }
+// { dg-prune-output "command-line option" }
#include "empty14.h"
extern "C" void fun(struct dummy, struct foo);
diff --git a/gcc/testsuite/g++.dg/abi/empty15.C b/gcc/testsuite/g++.dg/abi/empty15.C
index 12385f7..fd36194 100644
--- a/gcc/testsuite/g++.dg/abi/empty15.C
+++ b/gcc/testsuite/g++.dg/abi/empty15.C
@@ -2,7 +2,7 @@
// { dg-do run { target { { i?86-*-* x86_64-*-* } && { ! { ia32 } } } } }
// { dg-options "-Wabi=11 -x c" }
// { dg-additional-sources "empty15a.c" }
-// { dg-prune-output "command line option" }
+// { dg-prune-output "command-line option" }
#include "empty15.h"
extern "C" void fun(struct dummy, struct foo);
diff --git a/gcc/testsuite/g++.dg/abi/empty16.C b/gcc/testsuite/g++.dg/abi/empty16.C
index 1ca52f9..024b00e 100644
--- a/gcc/testsuite/g++.dg/abi/empty16.C
+++ b/gcc/testsuite/g++.dg/abi/empty16.C
@@ -2,7 +2,7 @@
// { dg-do run { target { { i?86-*-* x86_64-*-* } && { ! { ia32 } } } } }
// { dg-options "-Wabi=11 -x c" }
// { dg-additional-sources "empty16a.c" }
-// { dg-prune-output "command line option" }
+// { dg-prune-output "command-line option" }
#include "empty16.h"
extern "C" void fun(struct dummy, struct foo);
diff --git a/gcc/testsuite/g++.dg/abi/empty17.C b/gcc/testsuite/g++.dg/abi/empty17.C
index d386e54..a6e58fa 100644
--- a/gcc/testsuite/g++.dg/abi/empty17.C
+++ b/gcc/testsuite/g++.dg/abi/empty17.C
@@ -2,7 +2,7 @@
// { dg-do run { target { { i?86-*-* x86_64-*-* } && { ! { ia32 } } } } }
// { dg-options "-Wabi=11 -x c" }
// { dg-additional-sources "empty17a.c" }
-// { dg-prune-output "command line option" }
+// { dg-prune-output "command-line option" }
#include "empty17.h"
extern "C" void fun(struct dummy, struct foo);
diff --git a/gcc/testsuite/g++.dg/abi/empty18.C b/gcc/testsuite/g++.dg/abi/empty18.C
index be69c6a..6e64dae 100644
--- a/gcc/testsuite/g++.dg/abi/empty18.C
+++ b/gcc/testsuite/g++.dg/abi/empty18.C
@@ -2,7 +2,7 @@
// { dg-do run { target { { i?86-*-* x86_64-*-* } && { ! { ia32 } } } } }
// { dg-options "-Wabi=11 -x c" }
// { dg-additional-sources "empty18a.c" }
-// { dg-prune-output "command line option" }
+// { dg-prune-output "command-line option" }
#include "empty18.h"
extern "C" void fun(struct dummy, struct foo);
diff --git a/gcc/testsuite/g++.dg/abi/empty19.C b/gcc/testsuite/g++.dg/abi/empty19.C
index 84f5b75..8707db8 100644
--- a/gcc/testsuite/g++.dg/abi/empty19.C
+++ b/gcc/testsuite/g++.dg/abi/empty19.C
@@ -2,7 +2,7 @@
// { dg-do run { target { { i?86-*-* x86_64-*-* } && { ! { ia32 } } } } }
// { dg-options "-Wabi=11 -x c" }
// { dg-additional-sources "empty19a.c" }
-// { dg-prune-output "command line option" }
+// { dg-prune-output "command-line option" }
#include "empty19.h"
extern "C" void fun(struct dummy, struct foo);
diff --git a/gcc/testsuite/g++.dg/abi/empty22.C b/gcc/testsuite/g++.dg/abi/empty22.C
index f4f4a02..d3720f8 100644
--- a/gcc/testsuite/g++.dg/abi/empty22.C
+++ b/gcc/testsuite/g++.dg/abi/empty22.C
@@ -2,7 +2,7 @@
// { dg-do run { target { { i?86-*-* x86_64-*-* } && { ! { ia32 } } } } }
// { dg-options "-Wabi=11 -x c" }
// { dg-additional-sources "empty22a.c" }
-// { dg-prune-output "command line option" }
+// { dg-prune-output "command-line option" }
#include "empty22.h"
extern "C" void fun(struct dummy, struct foo);
diff --git a/gcc/testsuite/g++.dg/abi/empty25.C b/gcc/testsuite/g++.dg/abi/empty25.C
index da6ef51..50a4c26 100644
--- a/gcc/testsuite/g++.dg/abi/empty25.C
+++ b/gcc/testsuite/g++.dg/abi/empty25.C
@@ -2,7 +2,7 @@
// { dg-do run { target { { i?86-*-* x86_64-*-* } && { ! { ia32 } } } } }
// { dg-options "-Wabi=11 -x c" }
// { dg-additional-sources "empty25a.c" }
-// { dg-prune-output "command line option" }
+// { dg-prune-output "command-line option" }
#include "empty25.h"
extern "C" void fun(struct dummy, struct foo);
diff --git a/gcc/testsuite/g++.dg/abi/empty26.C b/gcc/testsuite/g++.dg/abi/empty26.C
index ab2f54d..785cdc7 100644
--- a/gcc/testsuite/g++.dg/abi/empty26.C
+++ b/gcc/testsuite/g++.dg/abi/empty26.C
@@ -2,7 +2,7 @@
// { dg-do run { target { { i?86-*-* x86_64-*-* } && { ! { ia32 } } } } }
// { dg-options "-Wabi=11 -x c" }
// { dg-additional-sources "empty26a.c" }
-// { dg-prune-output "command line option" }
+// { dg-prune-output "command-line option" }
#include "empty26.h"
extern "C" void fun(struct dummy, struct foo);
diff --git a/gcc/testsuite/g++.dg/asan/pr90570.C b/gcc/testsuite/g++.dg/asan/pr90570.C
new file mode 100644
index 0000000..c236690
--- /dev/null
+++ b/gcc/testsuite/g++.dg/asan/pr90570.C
@@ -0,0 +1,18 @@
+/* PR sanitizer/90570 */
+/* { dg-do run } */
+
+#include <vector>
+
+struct stru
+{
+ std::vector<int> v{1,2,3,4};
+ int i{5};
+};
+
+int main()
+{
+ stru s1;
+ stru s2;
+
+ return 0;
+}
diff --git a/gcc/testsuite/g++.dg/asm-qual-1.C b/gcc/testsuite/g++.dg/asm-qual-1.C
index 3fba592..1bb217f 100644
--- a/gcc/testsuite/g++.dg/asm-qual-1.C
+++ b/gcc/testsuite/g++.dg/asm-qual-1.C
@@ -7,7 +7,7 @@ f ()
{
asm volatile ("");
- asm const (""); // { dg-error {'const' is not an asm qualifier} }
+ asm const (""); // { dg-error {'const' is not an 'asm' qualifier} }
- asm __restrict (""); // { dg-error {'__restrict' is not an asm qualifier} }
+ asm __restrict (""); // { dg-error {'__restrict' is not an 'asm' qualifier} }
}
diff --git a/gcc/testsuite/g++.dg/asm-qual-3.C b/gcc/testsuite/g++.dg/asm-qual-3.C
index 0bf6069..80573cb 100644
--- a/gcc/testsuite/g++.dg/asm-qual-3.C
+++ b/gcc/testsuite/g++.dg/asm-qual-3.C
@@ -2,11 +2,11 @@
// { dg-do compile }
// { dg-options "-std=gnu++98" }
-asm const (""); // { dg-error {'const' is not an asm qualifier} }
-asm volatile (""); // { dg-warning {asm qualifier 'volatile' ignored outside of function body} }
+asm const (""); // { dg-error {'const' is not an 'asm' qualifier} }
+asm volatile (""); // { dg-warning {'asm' qualifier 'volatile' ignored outside of function body} }
asm restrict (""); // { dg-error {expected '\(' before 'restrict'} }
-asm inline (""); // { dg-error {asm qualifier outside of function body} }
-asm goto (""); // { dg-error {asm qualifier outside of function body} }
+asm inline (""); // { dg-error {'asm' qualifier outside of function body} }
+asm goto (""); // { dg-error {'asm' qualifier outside of function body} }
// There are many other things wrong with this code, so:
// { dg-excess-errors "" }
diff --git a/gcc/testsuite/g++.dg/cet-notrack-1.C b/gcc/testsuite/g++.dg/cet-notrack-1.C
index eab0946..ee98fd4 100644
--- a/gcc/testsuite/g++.dg/cet-notrack-1.C
+++ b/gcc/testsuite/g++.dg/cet-notrack-1.C
@@ -1,7 +1,7 @@
/* { dg-do compile { target i?86-*-* x86_64-*-* } } */
/* { dg-options "-fcf-protection" } */
/* { dg-final { scan-assembler "endbr32|endbr64" } } */
-/* { dg-final { scan-assembler-times "\tcall\[ \t]+puts" 2 } } */
+/* { dg-final { scan-assembler-times "\tcall\[ \t]+_?puts" 2 } } */
/* { dg-final { scan-assembler-times "notrack call\[ \t]+" 1 } } */
#include <stdio.h>
diff --git a/gcc/testsuite/g++.dg/concepts/decl-diagnose.C b/gcc/testsuite/g++.dg/concepts/decl-diagnose.C
index 7ac7872..019a8ce 100644
--- a/gcc/testsuite/g++.dg/concepts/decl-diagnose.C
+++ b/gcc/testsuite/g++.dg/concepts/decl-diagnose.C
@@ -17,7 +17,7 @@ struct X
template<typename T>
static concept bool f6() { return true; } // { dg-error "a concept cannot be a member function" }
static concept bool x; // { dg-error "declared 'concept'" }
- // { dg-error "uninitialized const" "" { target *-*-* } .-1 }
+ // { dg-error "uninitialized 'const" "" { target *-*-* } .-1 }
concept int x2; // { dg-error "declared 'concept'" }
concept ~X(); // { dg-error "a destructor cannot be 'concept'" }
concept X(); // { dg-error "a constructor cannot be 'concept'" }
diff --git a/gcc/testsuite/g++.dg/concepts/pr60573.C b/gcc/testsuite/g++.dg/concepts/pr60573.C
index 5688491..42cda21 100644
--- a/gcc/testsuite/g++.dg/concepts/pr60573.C
+++ b/gcc/testsuite/g++.dg/concepts/pr60573.C
@@ -9,7 +9,7 @@ struct A
void foo(auto);
};
- void B::foo(auto) {} // { dg-error "cannot define" }
+ void B::foo(auto) {} // { dg-error "8:cannot define" }
struct X
{
@@ -21,8 +21,8 @@ struct A
};
};
- void Y::Z::foo(auto) {} // { dg-error "cannot define" }
+ void Y::Z::foo(auto) {} // { dg-error "10:cannot define" }
};
- void X::Y::Z::foo(auto) {} // { dg-error "cannot define" }
+ void X::Y::Z::foo(auto) {} // { dg-error "8:cannot define" }
};
diff --git a/gcc/testsuite/g++.dg/conversion/bitfield7.C b/gcc/testsuite/g++.dg/conversion/bitfield7.C
index 1080168..d1b1b09 100644
--- a/gcc/testsuite/g++.dg/conversion/bitfield7.C
+++ b/gcc/testsuite/g++.dg/conversion/bitfield7.C
@@ -12,5 +12,5 @@ int foo (double);
int
main ()
{
- return foo (s.bar); // { dg-error "cannot bind bitfield" }
+ return foo (s.bar); // { dg-error "cannot bind bit-field" }
}
diff --git a/gcc/testsuite/g++.dg/conversion/dynamic1.C b/gcc/testsuite/g++.dg/conversion/dynamic1.C
index a781cba..3c8739c 100644
--- a/gcc/testsuite/g++.dg/conversion/dynamic1.C
+++ b/gcc/testsuite/g++.dg/conversion/dynamic1.C
@@ -11,5 +11,5 @@ A& bar();
void baz()
{
- dynamic_cast<A&>( bar().foo ); // { dg-error "cannot dynamic_cast" }
+ dynamic_cast<A&>( bar().foo ); // { dg-error "cannot 'dynamic_cast'" }
}
diff --git a/gcc/testsuite/g++.dg/cpp0x/Wattributes1.C b/gcc/testsuite/g++.dg/cpp0x/Wattributes1.C
index b1c48d4..2223936 100644
--- a/gcc/testsuite/g++.dg/cpp0x/Wattributes1.C
+++ b/gcc/testsuite/g++.dg/cpp0x/Wattributes1.C
@@ -5,4 +5,4 @@
#include <new>
__attribute__((visibility("hidden")))void*operator new(std::size_t); // { dg-warning "visibility attribute ignored" }
-// { dg-message "previous declaration" "" { target *-*-* } 125 }
+// { dg-message "previous declaration" "" { target *-*-* } 0 }
diff --git a/gcc/testsuite/g++.dg/cpp0x/Wattributes2.C b/gcc/testsuite/g++.dg/cpp0x/Wattributes2.C
new file mode 100644
index 0000000..f37b1f01
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/Wattributes2.C
@@ -0,0 +1,32 @@
+// PR c++/60373
+// { dg-do compile { target c++11 } }
+// { dg-require-visibility "" }
+
+#pragma GCC visibility push(default)
+namespace std
+{
+ using size_t = decltype(sizeof(0));
+ struct nothrow_t { };
+}
+
+void* operator new(std::size_t)
+ __attribute__((__externally_visible__));
+void* operator new[](std::size_t)
+ __attribute__((__externally_visible__));
+void* operator new(std::size_t, const std::nothrow_t&) noexcept
+ __attribute__((__externally_visible__, __malloc__));
+void* operator new[](std::size_t, const std::nothrow_t&) noexcept
+ __attribute__((__externally_visible__, __malloc__));
+void operator delete(void*) noexcept
+ __attribute__((__externally_visible__));
+void operator delete[](void*) noexcept
+ __attribute__((__externally_visible__));
+void operator delete(void*, const std::nothrow_t&) noexcept
+ __attribute__((__externally_visible__));
+void operator delete[](void*, const std::nothrow_t&) noexcept
+ __attribute__((__externally_visible__));
+#pragma GCC visibility pop
+
+__attribute__((visibility("hidden")))void*operator new(std::size_t); // { dg-warning "visibility attribute ignored" }
+
+// { dg-message "previous declaration" "" { target *-*-* } 12 }
diff --git a/gcc/testsuite/g++.dg/cpp0x/Wunused-value1.C b/gcc/testsuite/g++.dg/cpp0x/Wunused-value1.C
new file mode 100644
index 0000000..a0683b6
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/Wunused-value1.C
@@ -0,0 +1,20 @@
+// PR c++/90881
+// { dg-do compile { target c++11 } }
+// { dg-options "-Wall" }
+
+namespace std {
+ struct true_type { static const bool value = true; };
+ struct false_type { static const bool value = false; };
+}
+
+template <typename T, typename = void> struct status : std::false_type{};
+
+template <typename T> struct status<T, decltype(T::member, void())> : std::true_type {}; // { dg-bogus "left operand of comma operator has no effect" }
+
+struct s1{int member;};
+struct s2{int _member;};
+
+int main(){
+ static_assert(status<s1>::value, "has member");
+ static_assert(!status<s2>::value, "has no member");
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/addressof2.C b/gcc/testsuite/g++.dg/cpp0x/addressof2.C
index a38dce0..73942c5 100644
--- a/gcc/testsuite/g++.dg/cpp0x/addressof2.C
+++ b/gcc/testsuite/g++.dg/cpp0x/addressof2.C
@@ -16,7 +16,7 @@ struct S { int s : 5; int t; void foo (); } s;
auto c = __builtin_addressof (s);
auto d = addressof (s);
auto e = __builtin_addressof (s.s); // { dg-error "attempt to take address of bit-field" }
-auto f = addressof (s.s); // { dg-error "cannot bind bitfield" }
+auto f = addressof (s.s); // { dg-error "cannot bind bit-field" }
auto g = __builtin_addressof (S{}); // { dg-error "taking address of rvalue" }
auto h = addressof (S{}); // { dg-error "cannot bind non-const lvalue reference of type" }
auto i = __builtin_addressof (S::t); // { dg-error "invalid use of non-static data member" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/alias-decl-1.C b/gcc/testsuite/g++.dg/cpp0x/alias-decl-1.C
index c52ab46..43284d7 100644
--- a/gcc/testsuite/g++.dg/cpp0x/alias-decl-1.C
+++ b/gcc/testsuite/g++.dg/cpp0x/alias-decl-1.C
@@ -11,5 +11,6 @@ template <class U> using Ptr = U*;
template<class U> struct Ptr<U*> {}; // { dg-error "specialization" }
struct A {
- using A = int;//{ dg-error "nested|has|same name as|class|in which|declared" }
+ using A = int; // { dg-error "11:ISO C\\+\\+ forbids nested type .A." }
+// { dg-error "same name as" "" { target c++11 } .-1 }
};
diff --git a/gcc/testsuite/g++.dg/cpp0x/alias-decl-18.C b/gcc/testsuite/g++.dg/cpp0x/alias-decl-18.C
index 199b054..1e165d8 100644
--- a/gcc/testsuite/g++.dg/cpp0x/alias-decl-18.C
+++ b/gcc/testsuite/g++.dg/cpp0x/alias-decl-18.C
@@ -5,5 +5,6 @@ template<typename Z> using ::T = void(int n); // { dg-error "" }
template<typename Z> using operator int = void(int n); // { dg-error "" }
template<typename Z> using typename U = void; // { dg-error "" }
template<typename Z> using typename ::V = void(int n); // { dg-error "" }
-template<typename Z> using typename ::operator bool = void(int n); // { dg-error "" }
+template<typename Z> using typename ::operator bool = void(int n); // { dg-error "39:declaration" }
+// { dg-error "expected" "" { target *-*-* } .-1 }
using foo __attribute__((aligned(4)) = int; // { dg-error "" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/alias-decl-68.C b/gcc/testsuite/g++.dg/cpp0x/alias-decl-68.C
new file mode 100644
index 0000000..2250ef0
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/alias-decl-68.C
@@ -0,0 +1,10 @@
+// PR c++/77967
+// { dg-do compile { target c++11 } }
+
+template<typename T>
+using bar = const T&;
+
+template<typename T>
+bar<T>::bar(const T& cr) // { dg-error "" }
+{
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/alias-decl-69.C b/gcc/testsuite/g++.dg/cpp0x/alias-decl-69.C
new file mode 100644
index 0000000..7dd7aa23
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/alias-decl-69.C
@@ -0,0 +1,40 @@
+// PR c++/65175
+// { dg-do compile { target c++11 } }
+
+template <class a> using au = typename a::av;
+template <bool, class a> using az = a;
+template <template <class...> class b, class... bf> struct d {
+ template <class bh> struct f { typedef bh e; };
+ static auto g(int) -> f<b<bf...>>;
+ typedef typename decltype(g(0))::e e;
+};
+template <class = void> class h;
+template <class, class, template <class...> class, class...> struct i;
+struct j {
+ typedef int bu;
+};
+namespace bv {
+template <class> struct k : j {};
+template <class bx> struct l : i<int, void, k, bx> {};
+} // namespace bv
+template <class bx> auto bw(bx) -> az<bv::l<bx>::c, typename bv::l<bx>::bz>;
+template <class, class cd, class> struct n : j { au<cd> av; };
+template <class, class cd, class> struct K : j { au<cd> av; };
+template <class cj> struct o {
+ typedef typename cj::e e;
+ static const bool c = true;
+ typedef h<typename e::bu> bz;
+};
+template <class, class, template <class...> class cj, class... bf>
+struct i : o<d<cj, bf...>> {};
+template <class> class h {
+public:
+ typedef int av;
+ struct : i<int, int, K, int, h, int> {} s;
+ template <class> struct p : i<int, int, n, int, h<h>, int> {};
+ template <class bx, class cl>
+ auto m_fn2(bx, cl) -> az<p<cl>::c, typename p<cl>::bz>;
+ template <class bx> static auto q(int, int, bx cm) -> decltype(bw(cm));
+};
+int a, b;
+void c() { h<>::q(b, 5, a).m_fn2(5, a); }
diff --git a/gcc/testsuite/g++.dg/cpp0x/alignas4.C b/gcc/testsuite/g++.dg/cpp0x/alignas4.C
index b66fa65..1ef4870 100644
--- a/gcc/testsuite/g++.dg/cpp0x/alignas4.C
+++ b/gcc/testsuite/g++.dg/cpp0x/alignas4.C
@@ -1,7 +1,13 @@
// PR c++/59012
// { dg-do compile { target c++11 } }
// { dg-final { scan-assembler "align 8" { target { { i?86-*-* x86_64-*-* } && { { ! ia32 } && { ! *-*-darwin* } } } } } }
-// { dg-final { scan-assembler "align 4" { target ia32 } } }
+// { dg-final { scan-assembler "align 4" { target { ia32 && { ! *-*-darwin* } } } } }
+
+// Darwin produces aligned .zerofill directives for these.
+// { dg-final { scan-assembler {zerofill[^\n\r]+_a,4,2} { target { ilp32 && *-*-darwin* } } } }
+// { dg-final { scan-assembler {zerofill[^\n\r]+_a,8,3} { target { lp64 && *-*-darwin* } } } }
+// { dg-final { scan-assembler {zerofill[^\n\r]+_a2,4,2} { target { ilp32 && *-*-darwin* } } } }
+// { dg-final { scan-assembler {zerofill[^\n\r]+_a2,8,3} { target { lp64 && *-*-darwin* } } } }
template <class... T>
struct A
diff --git a/gcc/testsuite/g++.dg/cpp0x/alignof5.C b/gcc/testsuite/g++.dg/cpp0x/alignof5.C
new file mode 100644
index 0000000..09354d3
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/alignof5.C
@@ -0,0 +1,6 @@
+// PR c++/90736 - bogus error with alignof.
+// { dg-do compile { target c++11 } }
+
+constexpr int fn(const int b) { return b; }
+constexpr int c = fn(alignof(int));
+alignas(c) char d;
diff --git a/gcc/testsuite/g++.dg/cpp0x/auto9.C b/gcc/testsuite/g++.dg/cpp0x/auto9.C
index 8e49a01..8d77b0b 100644
--- a/gcc/testsuite/g++.dg/cpp0x/auto9.C
+++ b/gcc/testsuite/g++.dg/cpp0x/auto9.C
@@ -78,10 +78,10 @@ enum struct D : auto * { FF = 0 }; // { dg-error "must be an integral type|decl
void
bar ()
{
- try { } catch (auto i) { } // { dg-error "parameter" }
- try { } catch (auto) { } // { dg-error "parameter" }
- try { } catch (auto *i) { } // { dg-error "parameter" }
- try { } catch (auto *) { } // { dg-error "parameter" }
+ try { } catch (auto i) { } // { dg-error "18:parameter" }
+ try { } catch (auto) { } // { dg-error "18:parameter" }
+ try { } catch (auto *i) { } // { dg-error "18:parameter" }
+ try { } catch (auto *) { } // { dg-error "18:parameter" }
}
void
@@ -111,7 +111,7 @@ badthrow2 () throw (auto &) // { dg-error "invalid use of|expected" }
{ // { dg-error "dynamic exception specification" "" { target c++17 } .-1 }
} // { dg-warning "deprecated" "" { target { ! c++17 } } .-2 }
-template <auto V = 4> struct G {}; // { dg-error "auto" "" { target { ! c++17 } } }
+template <auto V = 4> struct G {}; // { dg-error "11:parameter" "" { target { ! c++17 } } }
template <typename T> struct H { H (); ~H (); };
H<auto> h; // { dg-error "invalid|initializer" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-77771.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-77771.C
new file mode 100644
index 0000000..fca83d9
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-77771.C
@@ -0,0 +1,16 @@
+// PR c++/77771
+// { dg-do compile { target c++11 } }
+// { dg-options "-O" }
+
+struct S
+{
+ char x[2];
+ unsigned y;
+};
+
+constexpr bool func(const S s)
+{
+ return s.x[0] != 42 || s.x[1] != 0;
+}
+
+static_assert(func({{42, 7}, 0}), "");
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-89599.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-89599.C
index 07760a3..010416a 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-89599.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-89599.C
@@ -2,5 +2,5 @@
// { dg-do compile { target c++11 } }
void foo (int x) {}
-constexpr void *arr[2] = { (void*) &foo, (void *) foo };// { dg-error "a reinterpret_cast is not a constant expression" }
-constexpr void *ptr = (void *) &foo; // { dg-error "a reinterpret_cast is not a constant expression" }
+constexpr void *arr[2] = { (void*) &foo, (void *) foo };// { dg-error "'reinterpret_cast' is not a constant expression" }
+constexpr void *ptr = (void *) &foo; // { dg-error "'reinterpret_cast' is not a constant expression" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-cast.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-cast.C
index e0c7ed3..da76a3d 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-cast.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-cast.C
@@ -7,8 +7,8 @@ int i;
// The following was accepted due to bug 49171.
constexpr void *q = reinterpret_cast<void*>(&i); // { dg-error "not a constant expression" }
-constexpr void *r0 = reinterpret_cast<void*>(1); // { dg-error "not a constant expression|reinterpret_cast from integer to pointer" }
-constexpr void *r1 = reinterpret_cast<void*>(sizeof 'x'); // { dg-error ".reinterpret_cast<void\\*>\\(1\[ul\]\*\\). is not a constant expression" }
+constexpr void *r0 = reinterpret_cast<void*>(1); // { dg-error "not a constant expression|'reinterpret_cast' from integer to pointer" }
+constexpr void *r1 = reinterpret_cast<void*>(sizeof 'x'); // { dg-error "'reinterpret_cast<void\\*>\\(1\[ul\]\*\\)' is not a constant expression" }
template <class T>
constexpr bool f ()
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-condition.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-condition.C
index 388a734..733d494 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-condition.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-condition.C
@@ -5,5 +5,5 @@ constexpr int something() { return 3; }
int main() {
if (constexpr long v = something()) {}
- if (static long v = something()) { } // { dg-error "decl-specifier invalid" }
+ if (static long v = something()) { } // { dg-error "'decl-specifier' invalid" }
}
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-decltype4.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-decltype4.C
new file mode 100644
index 0000000..64af90b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-decltype4.C
@@ -0,0 +1,21 @@
+// PR c++/52269
+// { dg-do compile { target c++11 } }
+
+template<typename T>
+int f(T x)
+{
+ return x.get();
+}
+
+// O.K. The body of `f' is not required.
+decltype(f(0)) a;
+
+template<typename T>
+constexpr int g(T x)
+{
+ return x.get();
+}
+
+// Seems to instantiate the body of `g'
+// and results in an error.
+decltype(g(0)) b;
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-neg1.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-neg1.C
index 3366992..9b52a6e 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-neg1.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-neg1.C
@@ -61,7 +61,7 @@ struct pixel2 { // { dg-message "no user-provided default constructor" }
int x, y;
};
constexpr pixel2 ur = { 1294, 1024 };// OK
-constexpr pixel2 origin; // { dg-error "uninitialized const" }
+constexpr pixel2 origin; // { dg-error "uninitialized 'const" }
constexpr const int* addr(const int& ir) { return &ir; } // OK
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-object1.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-object1.C
index 1861d40..5f54c63 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-object1.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-object1.C
@@ -15,7 +15,7 @@ constexpr A1 a1 = A1();
extern constexpr int i2; // { dg-error "definition" }
// error: missing initializer
-constexpr A1 a2; // { dg-error "uninitialized const" }
+constexpr A1 a2; // { dg-error "uninitialized 'const" }
const constexpr A1 a3 = A1();
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-shift1.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-shift1.C
index c1cfb1e..1970122 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-shift1.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-shift1.C
@@ -11,7 +11,7 @@ constexpr int i1 = fn1 (1, -1); // { dg-message "in .constexpr. expansion of " }
constexpr int
fn2 (int i, int j)
{
- return i << j; // { dg-error "is >= than the precision of the left operand" }
+ return i << j; // { dg-error "is greater than or equal to the precision .. of the left operand" }
}
constexpr int i2 = fn2 (1, 200); // { dg-message "in .constexpr. expansion of " }
@@ -43,7 +43,7 @@ constexpr int i5 = fn5 (__INT_MAX__, 1);
constexpr int
fn6 (unsigned int i, unsigned int j)
{
- return i << j; // { dg-error "is >= than the precision of the left operand" }
+ return i << j; // { dg-error "is greater than or equal to the precision .. of the left operand" }
}
constexpr int i6 = fn6 (1, -1); // { dg-message "in .constexpr. expansion of " }
@@ -67,7 +67,7 @@ constexpr int i8 = fn8 (-1, 1);
constexpr int
fn9 (int i, int j)
{
- return i >> j; // { dg-error "is >= than the precision of the left operand" }
+ return i >> j; // { dg-error "is greater than or equal to the precision .. of the left operand" }
}
constexpr int i9 = fn9 (1, 200); // { dg-message "in .constexpr. expansion of " }
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-sizeof2.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-sizeof2.C
new file mode 100644
index 0000000..8676ae4
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-sizeof2.C
@@ -0,0 +1,14 @@
+// PR c++/90825 - endless recursion when evaluating sizeof.
+// { dg-do compile { target c++11 } }
+
+class address {
+ char host_[63];
+public:
+ static constexpr unsigned buffer_size() noexcept { return sizeof(host_); }
+};
+
+template <class Archive>
+void load()
+{
+ char host[address::buffer_size()];
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-sizeof3.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-sizeof3.C
new file mode 100644
index 0000000..05f07c3
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-sizeof3.C
@@ -0,0 +1,22 @@
+// PR c++/90832 - endless recursion when evaluating sizeof.
+// { dg-do compile { target c++11 } }
+
+class B
+{
+ template <typename T> friend struct A;
+ B() {}
+};
+
+template <typename T>
+struct A
+{
+ A() noexcept(sizeof(B{})) { }
+};
+
+struct C
+{
+ C()
+ {
+ static_assert( sizeof(A<int>{}), "" );
+ }
+};
diff --git a/gcc/testsuite/g++.dg/cpp0x/decltype-pr66548.C b/gcc/testsuite/g++.dg/cpp0x/decltype-pr66548.C
index f4b7caa..3757b67 100644
--- a/gcc/testsuite/g++.dg/cpp0x/decltype-pr66548.C
+++ b/gcc/testsuite/g++.dg/cpp0x/decltype-pr66548.C
@@ -11,7 +11,7 @@ struct Meow {};
void f ()
{
- decltype (Meow.purr ()) d; // { dg-error "expected primary-expression" "pr89875" { xfail c++98_only } }
+ decltype (Meow.purr ()) d; // { dg-error "expected primary-expression" }
(void)&d;
}
@@ -19,4 +19,3 @@ void g ()
{
decltype (Meow.purr); // { dg-error "expected primary-expression" }
}
-
diff --git a/gcc/testsuite/g++.dg/cpp0x/decltype71.C b/gcc/testsuite/g++.dg/cpp0x/decltype71.C
new file mode 100644
index 0000000..24c3abf
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/decltype71.C
@@ -0,0 +1,25 @@
+// PR c++/68918
+// { dg-do compile { target c++11 } }
+
+struct foo {
+ static void a() {}
+
+ auto b() const -> decltype( this->a() )
+ {}
+
+ template<typename X>
+ auto c() -> decltype( this->a() )
+ {}
+
+ template<typename X>
+ auto d() const -> decltype( a() )
+ {}
+
+ template<typename X>
+ auto e() const -> decltype( this->a() )
+ {}
+};
+
+int main()
+{
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/defaulted18.C b/gcc/testsuite/g++.dg/cpp0x/defaulted18.C
index 83e1126..ef29f30 100644
--- a/gcc/testsuite/g++.dg/cpp0x/defaulted18.C
+++ b/gcc/testsuite/g++.dg/cpp0x/defaulted18.C
@@ -1,6 +1,6 @@
// { dg-do compile { target c++11 } }
-void f(char i, int j) = delete; // { dg-message "<deleted>" }
+void f(char i, int j) = delete; // { dg-message "(deleted)" }
void f(int i, ...); // { dg-message "void f" }
int main()
diff --git a/gcc/testsuite/g++.dg/cpp0x/defaulted2.C b/gcc/testsuite/g++.dg/cpp0x/defaulted2.C
index 45b09c1..b7b3143 100644
--- a/gcc/testsuite/g++.dg/cpp0x/defaulted2.C
+++ b/gcc/testsuite/g++.dg/cpp0x/defaulted2.C
@@ -21,7 +21,7 @@ struct B // { dg-message "user-provided default constructor" }
B() = default; // { dg-message "not user-provided" }
};
-const B b; // { dg-error "uninitialized const" }
+const B b; // { dg-error "uninitialized 'const" }
struct C
{
diff --git a/gcc/testsuite/g++.dg/cpp0x/deleted13.C b/gcc/testsuite/g++.dg/cpp0x/deleted13.C
index f10551f..ce915a8 100644
--- a/gcc/testsuite/g++.dg/cpp0x/deleted13.C
+++ b/gcc/testsuite/g++.dg/cpp0x/deleted13.C
@@ -8,5 +8,5 @@ struct A
struct B
{
- template<typename> friend void A::foo() = delete; // { dg-error "" }
+ template<typename> friend void A::foo() = delete; // { dg-error "34:cannot define" }
};
diff --git a/gcc/testsuite/g++.dg/cpp0x/gen-attrs-67.C b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-67.C
new file mode 100644
index 0000000..5d151cc
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-67.C
@@ -0,0 +1,11 @@
+// PR c++/83820 - excessive attribute arguments not detected.
+// { dg-do compile { target c++11 } }
+
+[[noreturn()]] void f0 (); // { dg-error ".noreturn. attribute does not take any arguments" }
+[[noreturn(1)]] void f1 (); // { dg-error ".noreturn. attribute does not take any arguments" }
+[[noreturn(1, 2)]] void f2 (); // { dg-error ".noreturn. attribute does not take any arguments" }
+[[maybe_unused()]] int f3(); // { dg-error ".maybe_unused. attribute does not take any arguments" }
+[[nodiscard()]] int f4(); // { dg-error ".nodiscard. attribute does not take any arguments" }
+[[gnu::noinline()]] int f5(); // { dg-error ".noinline. attribute does not take any arguments" }
+[[gnu::constructor]] int f6();
+[[gnu::constructor(101)]] int f7(); // { dg-error "constructor priorities are not supported" "" { target *-*-darwin* } }
diff --git a/gcc/testsuite/g++.dg/cpp0x/gnu_fext-numeric-literals.C b/gcc/testsuite/g++.dg/cpp0x/gnu_fext-numeric-literals.C
index 816077d..7a467a1 100644
--- a/gcc/testsuite/g++.dg/cpp0x/gnu_fext-numeric-literals.C
+++ b/gcc/testsuite/g++.dg/cpp0x/gnu_fext-numeric-literals.C
@@ -22,55 +22,55 @@ operator"" J(unsigned long long n) // { dg-warning "1:integer suffix .J. shadowe
// Floating-point imaginary...
constexpr long double
-operator"" i(long double n) // { dg-warning "1:floating point suffix .i. shadowed by implementation" "" { target c++11_only } }
+operator"" i(long double n) // { dg-warning "1:floating-point suffix .i. shadowed by implementation" "" { target c++11_only } }
{ return 4.0L * n + 0.0L; }
constexpr long double
-operator"" I(long double n) // { dg-warning "1:floating point suffix .I. shadowed by implementation" }
+operator"" I(long double n) // { dg-warning "1:floating-point suffix .I. shadowed by implementation" }
{ return 4.0L * n + 1.0L; }
constexpr long double
-operator"" j(long double n) // { dg-warning "1:floating point suffix .j. shadowed by implementation" }
+operator"" j(long double n) // { dg-warning "1:floating-point suffix .j. shadowed by implementation" }
{ return 4.0L * n + 2.0L; }
constexpr long double
-operator"" J(long double n) // { dg-warning "1:floating point suffix .J. shadowed by implementation" }
+operator"" J(long double n) // { dg-warning "1:floating-point suffix .J. shadowed by implementation" }
{ return 4.0L * n + 3.0L; }
// Fixed-point...
constexpr long double
-operator"" k(long double n) // { dg-warning "1:floating point suffix .k. shadowed by implementation" }
+operator"" k(long double n) // { dg-warning "1:floating-point suffix .k. shadowed by implementation" }
{ return 4 * (n + 1) + 0; }
constexpr long double
-operator"" K(long double n) // { dg-warning "1:floating point suffix .K. shadowed by implementation" }
+operator"" K(long double n) // { dg-warning "1:floating-point suffix .K. shadowed by implementation" }
{ return 4 * (n + 1) + 1; }
constexpr long double
-operator"" r(long double n) // { dg-warning "1:floating point suffix .r. shadowed by implementation" }
+operator"" r(long double n) // { dg-warning "1:floating-point suffix .r. shadowed by implementation" }
{ return 4 * (n + 1) + 2; }
constexpr long double
-operator"" R(long double n) // { dg-warning "1:floating point suffix .R. shadowed by implementation" }
+operator"" R(long double n) // { dg-warning "1:floating-point suffix .R. shadowed by implementation" }
{ return 4 * (n + 1) + 3; }
// Machine-defined...
constexpr long double
-operator"" w(long double n) // { dg-warning "1:floating point suffix .w. shadowed by implementation" }
+operator"" w(long double n) // { dg-warning "1:floating-point suffix .w. shadowed by implementation" }
{ return 4 * (n + 2) + 0; }
constexpr long double
-operator"" W(long double n) // { dg-warning "1:floating point suffix .W. shadowed by implementation" }
+operator"" W(long double n) // { dg-warning "1:floating-point suffix .W. shadowed by implementation" }
{ return 4 * (n + 2) + 1; }
constexpr long double
-operator"" q(long double n) // { dg-warning "1:floating point suffix .q. shadowed by implementation" }
+operator"" q(long double n) // { dg-warning "1:floating-point suffix .q. shadowed by implementation" }
{ return 4 * (n + 2) + 2; }
constexpr long double
-operator"" Q(long double n) // { dg-warning "1:floating point suffix .Q. shadowed by implementation" }
+operator"" Q(long double n) // { dg-warning "1:floating-point suffix .Q. shadowed by implementation" }
{ return 4 * (n + 2) + 3; }
int
diff --git a/gcc/testsuite/g++.dg/cpp0x/inh-ctor33.C b/gcc/testsuite/g++.dg/cpp0x/inh-ctor33.C
new file mode 100644
index 0000000..95b7812
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/inh-ctor33.C
@@ -0,0 +1,19 @@
+// PR c++/77747
+// { dg-do compile { target c++11 } }
+
+class X {
+public:
+ X() { }
+ X(int a) { }
+};
+
+class Y : public X { };
+
+class Z : public Y {
+ using X::X; // { dg-error "cannot inherit constructors from indirect base .X." }
+};
+
+int main()
+{
+ Z z{3}; // { dg-error "no matching" }
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist-deduce2.C b/gcc/testsuite/g++.dg/cpp0x/initlist-deduce2.C
new file mode 100644
index 0000000..dbf68a4
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/initlist-deduce2.C
@@ -0,0 +1,8 @@
+// Test for PR63149
+// { dg-do compile { target c++11 } }
+
+#include <initializer_list>
+
+const auto r = { 1, 2, 3 };
+using X = decltype(r);
+using X = const std::initializer_list<int>;
diff --git a/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-conv11.C b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-conv11.C
index 4b8d648..ec08f50 100644
--- a/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-conv11.C
+++ b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-conv11.C
@@ -4,7 +4,7 @@
void foo()
{
int i;
- static_cast<void(*)()>([i]{}); // { dg-error "invalid static_cast" }
- static_cast<void(*)()>([=]{}); // { dg-error "invalid static_cast" }
- static_cast<void(*)()>([&]{}); // { dg-error "invalid static_cast" }
+ static_cast<void(*)()>([i]{}); // { dg-error "invalid 'static_cast'" }
+ static_cast<void(*)()>([=]{}); // { dg-error "invalid 'static_cast'" }
+ static_cast<void(*)()>([&]{}); // { dg-error "invalid 'static_cast'" }
}
diff --git a/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-ice32.C b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-ice32.C
new file mode 100644
index 0000000..6f8d37c
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-ice32.C
@@ -0,0 +1,9 @@
+// PR c++/60366
+// { dg-do compile { target c++11 } }
+
+void
+fn ()
+{
+ auto f = [](const struct __lambda0 &self) { self(self); }; // { dg-error "" }
+ f(f); // { dg-error "" }
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-this21.C b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-this21.C
new file mode 100644
index 0000000..538dd37
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-this21.C
@@ -0,0 +1,10 @@
+// PR c++/66999 - 'this' captured by reference.
+// { dg-do compile { target c++11 } }
+
+struct X {
+ void bar (int n)
+ {
+ auto l1 = [&this] { }; // { dg-error ".this. cannot be captured by reference" }
+ auto l2 = [=, &this] { }; // { dg-error ".this. cannot be captured by reference" }
+ }
+};
diff --git a/gcc/testsuite/g++.dg/cpp0x/literal-type1.C b/gcc/testsuite/g++.dg/cpp0x/literal-type1.C
new file mode 100644
index 0000000..7b5d428
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/literal-type1.C
@@ -0,0 +1,54 @@
+// CWG 2096 - constraints on literal unions.
+// { dg-do compile { target c++11 } }
+
+struct literal { };
+typedef volatile int nonliteral_v;
+struct nonliteral {
+ nonliteral() {}
+};
+
+union U {
+ literal l;
+ nonliteral n;
+
+ constexpr U() : l{} {}
+};
+
+constexpr U u{};
+
+union U2 {
+ nonliteral n;
+ literal l;
+
+ constexpr U2() : l{} {}
+};
+
+constexpr U2 u2{};
+
+union U3 { // { dg-message "not literal" }
+ nonliteral_v n; // { dg-message "volatile type" }
+
+ constexpr U3() : n{} {}
+};
+
+constexpr U3 u3{}; // { dg-error "not literal" }
+
+union U4 {
+ nonliteral n;
+ nonliteral_v n2;
+ literal l;
+ nonliteral n3;
+
+ constexpr U4() : l{} {}
+};
+
+constexpr U4 u4{};
+
+union U5 {
+ nonliteral_v n;
+ literal l;
+
+ constexpr U5() : n{} {}
+};
+
+constexpr U5 u5{};
diff --git a/gcc/testsuite/g++.dg/cpp0x/noexcept15.C b/gcc/testsuite/g++.dg/cpp0x/noexcept15.C
index 5cbbea8..6c6eef6 100644
--- a/gcc/testsuite/g++.dg/cpp0x/noexcept15.C
+++ b/gcc/testsuite/g++.dg/cpp0x/noexcept15.C
@@ -1,12 +1,46 @@
// PR c++/50391
// { dg-do compile { target c++11 } }
-#include <type_traits>
+namespace std
+{
+ template<typename T, T Val>
+ struct integral_constant
+ { static constexpr T value = Val; };
+
+ template<typename T>
+ struct is_abstract
+ : integral_constant<bool, __is_abstract(T)>
+ { };
+
+ template<typename T, bool = is_abstract<T>::value>
+ struct is_destructible
+ : integral_constant<bool, true>
+ { };
+
+ template<typename T>
+ struct is_destructible<T, true>
+ : integral_constant<bool, false>
+ { };
+
+ template<typename T>
+ struct is_nothrow_move_constructible
+ : is_destructible<T>
+ { };
+
+ template<typename T>
+ struct decay
+ { typedef T type; };
+
+ template<typename T>
+ struct decay<T&>
+ { typedef T type; };
+
+} // std
template<class Tp>
struct single
{
- Tp elem; // { dg-error "incomplete type" }
+ Tp elem;
constexpr single(const Tp& e)
: elem(e) { }
@@ -30,3 +64,5 @@ foo(Blob *b)
{
make_single(*b);
}
+
+// { dg-excess-errors "incomplete type|not a member" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/noexcept41.C b/gcc/testsuite/g++.dg/cpp0x/noexcept41.C
new file mode 100644
index 0000000..4cd3d8d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/noexcept41.C
@@ -0,0 +1,12 @@
+// PR c++/72845
+// { dg-do compile { target c++11 } }
+
+template <typename> struct g { static const int h = 0; };
+template <typename i> void declval() { static_assert(!g<i>::h,""); }
+template <typename> struct a {
+ template <typename d, typename c>
+ friend auto f(d &&, c &&) noexcept(declval<c>) -> decltype(declval<c>); // { dg-error "different exception" }
+};
+template <typename d, typename c> auto f(d &&, c &&) -> decltype(declval<c>);
+struct e {};
+static_assert((e{}, declval<a<int>>),""); // { dg-error "no context to resolve type" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/noexcept42.C b/gcc/testsuite/g++.dg/cpp0x/noexcept42.C
new file mode 100644
index 0000000..5d7218d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/noexcept42.C
@@ -0,0 +1,21 @@
+// PR c++/84698
+// { dg-do compile { target c++11 } }
+
+template<typename A, typename B>
+struct X {
+ void swap(X& o) noexcept { }
+
+ template<typename... Args>
+ friend void swap(X<Args...>& a, X<Args...>& b) noexcept(noexcept(a.swap(b)));
+};
+
+template<typename... Args>
+inline void swap(X<Args...>& a, X<Args...>& b) noexcept(noexcept(a.swap(b)))
+{
+}
+
+int
+main ()
+{
+ X<int, int> x;
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/noexcept43.C b/gcc/testsuite/g++.dg/cpp0x/noexcept43.C
new file mode 100644
index 0000000..faa7d14
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/noexcept43.C
@@ -0,0 +1,10 @@
+// PR c++/90490
+// { dg-do compile { target c++11 } }
+
+struct R { constexpr operator bool() { return false;} };
+
+template <typename>
+struct S {
+ void g() noexcept(decltype(R{ }) { }) {
+ }
+};
diff --git a/gcc/testsuite/g++.dg/cpp0x/noexcept44.C b/gcc/testsuite/g++.dg/cpp0x/noexcept44.C
new file mode 100644
index 0000000..78c9d12
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/noexcept44.C
@@ -0,0 +1,8 @@
+// PR c++/90490
+// { dg-do compile { target c++11 } }
+
+template <typename>
+struct S {
+ void g() noexcept(decltype(int{ }) { }) {
+ }
+};
diff --git a/gcc/testsuite/g++.dg/cpp0x/noexcept45.C b/gcc/testsuite/g++.dg/cpp0x/noexcept45.C
new file mode 100644
index 0000000..39df4a6
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/noexcept45.C
@@ -0,0 +1,23 @@
+// PR c++/86476 - noexcept-specifier is a complete-class context
+// { dg-do compile { target c++11 } }
+
+struct A
+{
+ virtual void f();
+ virtual void g() noexcept;
+ virtual void h() noexcept(false);
+};
+
+struct B : A
+{
+ void f() noexcept(true);
+ void g() noexcept(true);
+ void h() noexcept(true);
+};
+
+struct D : A
+{
+ void f() noexcept(false);
+ void g() noexcept(false); // { dg-error "looser exception specification" }
+ void h() noexcept(false);
+};
diff --git a/gcc/testsuite/g++.dg/cpp0x/noexcept46.C b/gcc/testsuite/g++.dg/cpp0x/noexcept46.C
new file mode 100644
index 0000000..da7490d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/noexcept46.C
@@ -0,0 +1,28 @@
+// PR c++/86476 - noexcept-specifier is a complete-class context
+// { dg-do compile { target c++11 } }
+
+void f() noexcept(false);
+void g() noexcept(true);
+void h() noexcept;
+
+struct B {
+ friend void f() noexcept(false);
+ friend void g() noexcept(false); // { dg-error "different exception specifier" }
+ friend void h() noexcept(false); // { dg-error "different exception specifier" }
+};
+
+struct C {
+ friend void f() noexcept(true); // { dg-error "different exception specifier" }
+ friend void g() noexcept(true); // { dg-error "different exception specifier" }
+ friend void h() noexcept(true); // { dg-error "different exception specifier" }
+};
+
+void o() noexcept(false);
+void p() noexcept(true);
+void q() noexcept;
+
+struct D {
+ friend void o() noexcept(true); // { dg-error "different exception specifier" }
+ friend void p() noexcept(true);
+ friend void q() noexcept(true);
+};
diff --git a/gcc/testsuite/g++.dg/cpp0x/noexcept47.C b/gcc/testsuite/g++.dg/cpp0x/noexcept47.C
new file mode 100644
index 0000000..0848e68
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/noexcept47.C
@@ -0,0 +1,83 @@
+// PR c++/86476 - noexcept-specifier is a complete-class context
+// { dg-do compile { target c++11 } }
+
+int fn1 ();
+int fn2 () noexcept;
+int fn3 () noexcept;
+
+void g() noexcept(noexcept (fn2()));
+
+struct S1 {
+ friend void g1() noexcept(noexcept(fn2()));
+ friend void g1() noexcept(noexcept(fn1())); // { dg-error "different exception specifier" }
+};
+
+struct S2 {
+ friend void g2() noexcept(noexcept(fn1()));
+ friend void g2() noexcept(noexcept(fn1()));
+ friend void g2() noexcept(noexcept(fn1()));
+};
+
+struct S3 {
+ friend void g3() noexcept(noexcept(fn1()));
+ friend void g3() noexcept(noexcept(fn3())); // { dg-error "different exception specifier" }
+};
+
+struct S4 {
+ friend void g4() noexcept(noexcept(fn2()));
+ friend void g4() noexcept(noexcept(fn3()));
+};
+
+struct S5 {
+ friend void g() noexcept(noexcept(fn3()));
+};
+
+struct S6 {
+ friend void g() noexcept(noexcept(fn1())); // { dg-error "different exception specifier" }
+};
+
+struct S7 {
+ friend void gg() noexcept(noexcept(fn3()));
+};
+
+void gg() noexcept(noexcept(fn1())); // { dg-error "different exception specifier" }
+
+struct S8 {
+ friend void g8();
+ friend void g8() noexcept(noexcept(fn2())); // { dg-error "different exception specifier" }
+};
+
+struct S9 {
+ friend void g9();
+ friend void g9() noexcept(noexcept(fn1()));
+};
+
+struct S10 {
+ friend void g10() noexcept(noexcept(fn1()));
+ friend void g10();
+};
+
+struct S11 {
+ friend void g11() noexcept(noexcept(fn2()));
+ friend void g11(); // { dg-error "different exception specifier" }
+};
+
+struct S12 {
+ friend void g12() noexcept(false);
+ friend void g12() noexcept(noexcept(fn2())); // { dg-error "different exception specifier" }
+};
+
+struct S13 {
+ friend void g13() noexcept(false);
+ friend void g13() noexcept(noexcept(fn1()));
+};
+
+struct S14 {
+ friend void g14() noexcept(noexcept(fn1()));
+ friend void g14() noexcept(false);
+};
+
+struct S15 {
+ friend void g15() noexcept(noexcept(fn2()));
+ friend void g15() noexcept(false); // { dg-error "different exception specifier" }
+};
diff --git a/gcc/testsuite/g++.dg/cpp0x/noexcept48.C b/gcc/testsuite/g++.dg/cpp0x/noexcept48.C
new file mode 100644
index 0000000..134212c
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/noexcept48.C
@@ -0,0 +1,11 @@
+// PR c++/86476 - noexcept-specifier is a complete-class context
+// { dg-do compile { target c++11 } }
+
+int g;
+
+struct S {
+ int b;
+ friend void fn1(int n) noexcept(noexcept(n));
+ friend void fn2() noexcept(noexcept(g));
+ friend void fn3() noexcept(noexcept(b));
+};
diff --git a/gcc/testsuite/g++.dg/cpp0x/noexcept49.C b/gcc/testsuite/g++.dg/cpp0x/noexcept49.C
new file mode 100644
index 0000000..6da7ff3
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/noexcept49.C
@@ -0,0 +1,12 @@
+// PR c++/86476 - noexcept-specifier is a complete-class context
+// { dg-do compile { target c++11 } }
+
+#define SA(X) static_assert(X, #X)
+
+struct S {
+ static void f1() noexcept(b);
+ static constexpr auto b = true;
+};
+
+S s;
+SA(noexcept(s.f1()));
diff --git a/gcc/testsuite/g++.dg/cpp0x/noexcept50.C b/gcc/testsuite/g++.dg/cpp0x/noexcept50.C
new file mode 100644
index 0000000..43b38c2
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/noexcept50.C
@@ -0,0 +1,147 @@
+// PR c++/86476 - noexcept-specifier is a complete-class context
+// { dg-do compile { target c++11 } }
+
+#define SA(X) static_assert(X, #X)
+
+struct S {
+ void f1() noexcept(noexcept(i)) { }
+ void f2() noexcept(noexcept(fn())) { }
+ void f3() noexcept(noexcept(fnx())) { }
+ void f4() noexcept(noexcept(i));
+ void f5() noexcept(noexcept(fn()));
+ void f6() noexcept(noexcept(fnx()));
+
+ void f7() noexcept(1);
+ void f8() noexcept(0);
+ void f9() noexcept(b);
+ void f10() noexcept(!b);
+
+ int i;
+ static constexpr auto b = true;
+ void fny() noexcept(noexcept(fn()));
+ void fn();
+ void fnx() noexcept;
+};
+
+S s;
+SA(noexcept(s.f1()));
+SA(!noexcept(s.f2()));
+SA(noexcept(s.f3()));
+SA(noexcept(s.f4()));
+SA(!noexcept(s.f5()));
+SA(noexcept(s.f6()));
+SA(noexcept(s.f7()));
+SA(!noexcept(s.f8()));
+SA(noexcept(s.f9()));
+SA(!noexcept(s.f10()));
+
+struct S2 {
+ struct V {
+ void f1() noexcept(noexcept(fn()));
+ void f2() noexcept(noexcept(fnx()));
+ void f3() noexcept(noexcept(fn())) { }
+ void f4() noexcept(noexcept(fnx())) { }
+ void fn();
+ void fnx() noexcept;
+ } v;
+ void fn();
+ void fnx();
+};
+
+S2 s2;
+SA(!noexcept(s2.v.f1()));
+SA(noexcept(s2.v.f2()));
+SA(!noexcept(s2.v.f3()));
+SA(noexcept(s2.v.f4()));
+
+struct S3 {
+ void f1() noexcept(noexcept(fn()));
+ void f2() noexcept(noexcept(fnx()));
+ void fn();
+ void fnx() noexcept;
+};
+
+void
+S3::f1() noexcept(noexcept(fn()))
+{
+}
+
+void
+S3::f2() noexcept(noexcept(fnx()))
+{
+}
+
+struct S4 {
+ int f1 (int p) noexcept(noexcept(p)) { return p; }
+ int f2 (int p) noexcept(noexcept(p));
+ int f3 (int p = 10) noexcept(noexcept(p));
+ int f4 () noexcept(noexcept(S4{}));
+};
+
+S4 s4;
+SA(noexcept(s4.f1(1)));
+SA(noexcept(s4.f2(1)));
+SA(noexcept(s4.f3()));
+SA(noexcept(s4.f4()));
+
+template<typename T>
+struct S5 {
+ void f1() noexcept(noexcept(i)) { }
+ void f2() noexcept(noexcept(fn())) { }
+ void f3() noexcept(noexcept(fnx())) { }
+ void f4() noexcept(noexcept(i));
+ void f5() noexcept(noexcept(fn()));
+ void f6() noexcept(noexcept(fnx()));
+
+ int i;
+ void fny() noexcept(noexcept(fn()));
+ void fn();
+ void fnx() noexcept;
+};
+
+S5<int> s5;
+SA(noexcept(s5.f1()));
+SA(!noexcept(s5.f2()));
+SA(noexcept(s5.f3()));
+SA(noexcept(s5.f4()));
+SA(!noexcept(s5.f5()));
+SA(noexcept(s5.f6()));
+
+template<typename T>
+struct S6 {
+ void f1() noexcept(noexcept(x));
+ T x;
+};
+
+struct S7 {
+ template<typename U>
+ void f1 () noexcept(noexcept(U(1))) { }
+
+ template<int N>
+ void f2() noexcept(noexcept(N));
+
+ template <typename _Up>
+ void f3(_Up __p) noexcept(noexcept(__p));
+};
+
+void glob();
+void globx() noexcept;
+struct S8 {
+ void f1 () noexcept(noexcept(glob()));
+ void f2 () noexcept(noexcept(globx()));
+};
+
+S8 s8;
+SA(!noexcept(s8.f1()));
+SA(noexcept(s8.f2()));
+
+struct W {
+ constexpr operator bool();
+};
+
+template<typename T>
+struct S9 {
+ S9() noexcept(noexcept(w)) { }
+ S9 &operator=(S9 &&) noexcept(T::X);
+ W w;
+};
diff --git a/gcc/testsuite/g++.dg/cpp0x/noexcept51.C b/gcc/testsuite/g++.dg/cpp0x/noexcept51.C
new file mode 100644
index 0000000..a81032f
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/noexcept51.C
@@ -0,0 +1,14 @@
+// PR c++/86476 - noexcept-specifier is a complete-class context
+// { dg-do compile { target c++11 } }
+
+void fn1(void());
+template <typename> class A {
+ void _M_local_data();
+ A() noexcept(_M_local_data);
+};
+
+class B {
+ void _S_initialize();
+ static void _S_initialize_once();
+};
+void B::_S_initialize() { fn1(_S_initialize_once); }
diff --git a/gcc/testsuite/g++.dg/cpp0x/noexcept52.C b/gcc/testsuite/g++.dg/cpp0x/noexcept52.C
new file mode 100644
index 0000000..12c6d36
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/noexcept52.C
@@ -0,0 +1,9 @@
+// PR c++/86476 - noexcept-specifier is a complete-class context
+// { dg-do compile { target c++11 } }
+
+template <typename _Alloc> class A {
+ typedef _Alloc _Alloc_traits;
+ A &operator=(A &&) noexcept(_Alloc_traits::_S_nothrow_move);
+ A &m_fn1(A &&) noexcept(_Alloc_traits::_S_nothrow_move);
+ void m_fn2(A<char>) {}
+};
diff --git a/gcc/testsuite/g++.dg/cpp0x/noexcept53.C b/gcc/testsuite/g++.dg/cpp0x/noexcept53.C
new file mode 100644
index 0000000..b3859de
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/noexcept53.C
@@ -0,0 +1,26 @@
+// PR c++/86476 - noexcept-specifier is a complete-class context
+// { dg-do compile { target c++11 } }
+
+struct S {
+ void f1() noexcept(noexcept(fn()));
+ void f2() noexcept(noexcept(fnx()));
+ void fn();
+ void fnx() noexcept;
+};
+
+void
+S::f1() noexcept // { dg-error "different exception specifier" }
+{
+}
+
+void
+S::f2() // { dg-error "different exception specifier" }
+{
+}
+
+struct S2 {
+ void f1() noexcept(noexcept(nosuchfn())); // { dg-error "not declared in this scope" }
+ void f2() noexcept(noexcept(nothere)); // { dg-error "not declared in this scope" }
+ void f3() noexcept(noexcept(nosuchfn())) { } // { dg-error "not declared in this scope" }
+ void f4() noexcept(noexcept(nothere)) { } // { dg-error "not declared in this scope" }
+};
diff --git a/gcc/testsuite/g++.dg/cpp0x/noexcept54.C b/gcc/testsuite/g++.dg/cpp0x/noexcept54.C
new file mode 100644
index 0000000..20d844b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/noexcept54.C
@@ -0,0 +1,10 @@
+// PR c++/66256 - noexcept-specifier is a complete-class context.
+// { dg-do compile { target c++11 } }
+
+void swap(int&, int&);
+
+int& get();
+
+struct pair {
+ void swap(pair&) noexcept(noexcept(swap(get(), get()))) { } // { dg-error "no matching function for call" }
+};
diff --git a/gcc/testsuite/g++.dg/cpp0x/nondeduced1.C b/gcc/testsuite/g++.dg/cpp0x/nondeduced1.C
new file mode 100644
index 0000000..067079e
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/nondeduced1.C
@@ -0,0 +1,16 @@
+// PR c++/60223
+// { dg-do compile { target c++11 } }
+
+template<typename T, T = T{}>
+struct A { };
+
+template<typename T>
+void foo(A<T> a);
+
+void bar()
+{
+ foo(A<char, char{}>());
+ foo(A<char>());
+ foo<>(A<char>());
+ foo<>(A<char, char{}>());
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/nondeduced2.C b/gcc/testsuite/g++.dg/cpp0x/nondeduced2.C
new file mode 100644
index 0000000..3f96fe4
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/nondeduced2.C
@@ -0,0 +1,14 @@
+// PR c++/60223
+// { dg-do compile { target c++11 } }
+
+template<typename T, T>
+struct A { };
+
+template<typename T>
+void foo(A<T, T{}>);
+
+void bar()
+{
+ foo(A<char, char{}>());
+ foo<>(A<char, char{}>());
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/nondeduced3.C b/gcc/testsuite/g++.dg/cpp0x/nondeduced3.C
new file mode 100644
index 0000000..d943dce
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/nondeduced3.C
@@ -0,0 +1,16 @@
+// PR c++/60223
+// { dg-do compile { target c++11 } }
+
+template<typename T, T = T{1}>
+struct A { };
+
+template<typename T>
+void foo(A<T> a);
+
+void bar()
+{
+ foo(A<char>());
+ foo(A<char, char{1}>());
+ foo<>(A<char>());
+ foo<>(A<char, char{1}>());
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/nondeduced4.C b/gcc/testsuite/g++.dg/cpp0x/nondeduced4.C
new file mode 100644
index 0000000..818034c
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/nondeduced4.C
@@ -0,0 +1,13 @@
+// PR c++/60223
+// { dg-do compile { target c++11 } }
+
+template<typename T>
+struct A { };
+
+template<typename T>
+void foo(A<T>, T = T{});
+
+void bar()
+{
+ foo(A<int>());
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/nondeduced5.C b/gcc/testsuite/g++.dg/cpp0x/nondeduced5.C
new file mode 100644
index 0000000..dd890ec
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/nondeduced5.C
@@ -0,0 +1,12 @@
+// PR c++/65707
+// { dg-do compile { target c++11 } }
+
+template <int a> struct b {
+ typedef int c;
+ constexpr operator c() { return a; }
+};
+template <bool> struct d;
+template <typename> struct e : b<true> {};
+template <typename, typename = d<true>> struct f;
+template <typename g> struct f<g, d<e<g>{}>> {};
+template struct f<int>;
diff --git a/gcc/testsuite/g++.dg/cpp0x/nondeduced6.C b/gcc/testsuite/g++.dg/cpp0x/nondeduced6.C
new file mode 100644
index 0000000..9f68e30
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/nondeduced6.C
@@ -0,0 +1,24 @@
+// PR c++/89480
+// { dg-do compile { target c++11 } }
+
+template <typename Foo, Foo Part>
+struct TSelect {};
+
+enum What {
+ The
+};
+
+template <typename Foo>
+struct AnotherOneSelector {
+ static constexpr Foo Id = Foo::The;
+};
+
+template <typename Foo, typename SelectPartType>
+struct THelper;
+
+template <typename Foo>
+struct THelper<Foo, TSelect<Foo, Foo{AnotherOneSelector<Foo>::Id}>> {};
+
+int main() {
+ THelper<What, TSelect<What, What::The>> t;
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/nondeduced7.C b/gcc/testsuite/g++.dg/cpp0x/nondeduced7.C
new file mode 100644
index 0000000..a8aa073
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/nondeduced7.C
@@ -0,0 +1,6 @@
+// PR c++/58836
+// { dg-do compile { target c++11 } }
+
+template<typename, int> struct A;
+template<typename T> struct A<T, T{}> {}; // { dg-error "partial specialization" }
+A<int, 0> a;
diff --git a/gcc/testsuite/g++.dg/cpp0x/nsdmi-list5.C b/gcc/testsuite/g++.dg/cpp0x/nsdmi-list5.C
new file mode 100644
index 0000000..a12740b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/nsdmi-list5.C
@@ -0,0 +1,30 @@
+// PR c++/85552
+// { dg-do compile { target c++11 } }
+
+template<typename T>
+struct uptr {
+ uptr() { }
+ uptr(void*) { }
+ ~uptr() { static_assert(sizeof(T), "complete type"); }
+};
+
+class S;
+
+class Compiles
+{
+ uptr<S> s;
+};
+
+class DoesntCompile
+{
+ ~DoesntCompile();
+ DoesntCompile();
+
+ uptr<S> s1 { };
+ uptr<S> s2 { nullptr };
+};
+
+int main()
+{
+ return 0;
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/nullptr04.C b/gcc/testsuite/g++.dg/cpp0x/nullptr04.C
index 372ac51..2b90178 100644
--- a/gcc/testsuite/g++.dg/cpp0x/nullptr04.C
+++ b/gcc/testsuite/g++.dg/cpp0x/nullptr04.C
@@ -4,13 +4,13 @@
__extension__ typedef __INTPTR_TYPE__ intptr_t;
-const int n4 = static_cast<const int>(nullptr); // { dg-error "invalid static_cast " }
+const int n4 = static_cast<const int>(nullptr); // { dg-error "invalid 'static_cast' " }
const short int n5 = reinterpret_cast<short int>(nullptr); // { dg-error "loses precision" }
const intptr_t n6 = reinterpret_cast<intptr_t>(nullptr);
const intptr_t n7 = (intptr_t)nullptr;
decltype(nullptr) mynull = 0;
-const int n8 = static_cast<const int>(mynull); // { dg-error "invalid static_cast " }
+const int n8 = static_cast<const int>(mynull); // { dg-error "invalid 'static_cast' " }
const short int n9 = reinterpret_cast<short int>(mynull); // { dg-error "loses precision" }
const intptr_t n10 = reinterpret_cast<intptr_t>(mynull);
const intptr_t n11 = (intptr_t)mynull;
diff --git a/gcc/testsuite/g++.dg/cpp0x/pr42844-2.C b/gcc/testsuite/g++.dg/cpp0x/pr42844-2.C
index ff23966..75117c7 100644
--- a/gcc/testsuite/g++.dg/cpp0x/pr42844-2.C
+++ b/gcc/testsuite/g++.dg/cpp0x/pr42844-2.C
@@ -34,8 +34,8 @@ struct Derived3 : Base // { dg-message "user-provided default constructor" }
void f()
{
- const A a; // { dg-error "uninitialized const" }
- const Derived d; // { dg-error "uninitialized const" }
- const Derived2 d2; // { dg-error "uninitialized const" }
- const Derived3 d3; // { dg-error "uninitialized const" }
+ const A a; // { dg-error "uninitialized 'const" }
+ const Derived d; // { dg-error "uninitialized 'const" }
+ const Derived2 d2; // { dg-error "uninitialized 'const" }
+ const Derived3 d3; // { dg-error "uninitialized 'const" }
}
diff --git a/gcc/testsuite/g++.dg/cpp0x/pr83993.C b/gcc/testsuite/g++.dg/cpp0x/pr83993.C
index 17b7a64..c256257 100644
--- a/gcc/testsuite/g++.dg/cpp0x/pr83993.C
+++ b/gcc/testsuite/g++.dg/cpp0x/pr83993.C
@@ -7,7 +7,7 @@ const int b[5] = { 1, 2, 3, 4, 5 };
extern const int c[4];
constexpr const int *d = &a[0];
constexpr const int *d2 = a;
-constexpr const int *e = &a[1]; // { dg-error "non-zero array subscript '1' is used with array 'a' of type 'const int \\\[\\\]' with unknown bounds" }
+constexpr const int *e = &a[1]; // { dg-error "nonzero array subscript '1' is used with array 'a' of type 'const int \\\[\\\]' with unknown bounds" }
constexpr const int *f = &b[0];
constexpr const int *f2 = b;
constexpr const int *g = &b[5];
@@ -30,7 +30,7 @@ foo ()
constexpr const int *m = &l[0];
constexpr const int *m2 = l;
-constexpr const int *n = &l[1]; // { dg-error "non-zero array subscript '1' is used with array 'l' of type 'const int \\\[\\\]' with unknown bounds" }
+constexpr const int *n = &l[1]; // { dg-error "nonzero array subscript '1' is used with array 'l' of type 'const int \\\[\\\]' with unknown bounds" }
static_assert (d == d2 && f == f2 && i == i2 && m == m2, "");
const int o[] = { 1, 2 };
constexpr const int *p = &o[0];
@@ -40,7 +40,7 @@ constexpr const int *r = &o[3]; // { dg-error "array subscript value '3' is out
struct S { char a; char b[]; } s;
constexpr const char *t = &s.b[0];
constexpr const char *t2 = s.b;
-constexpr const char *u = &s.b[1]; // { dg-error "non-zero array subscript '1' is used with array of type 'char \\\[\\\]' with unknown bounds" }
+constexpr const char *u = &s.b[1]; // { dg-error "nonzero array subscript '1' is used with array of type 'char \\\[\\\]' with unknown bounds" }
struct V { int a; };
extern V v[];
constexpr V *w = &v[0];
diff --git a/gcc/testsuite/g++.dg/cpp0x/pr84497.C b/gcc/testsuite/g++.dg/cpp0x/pr84497.C
index d44a779..7eb1aee 100644
--- a/gcc/testsuite/g++.dg/cpp0x/pr84497.C
+++ b/gcc/testsuite/g++.dg/cpp0x/pr84497.C
@@ -1,6 +1,7 @@
// PR 84497 mismatch with thread constructor fn weakness
// { dg-do compile { target c++11 } }
// { dg-require-weak "" }
+// { dg-require-alias "" }
// { dg-skip-if "No .weak" { { hppa*-*-hpux* } && { ! lp64 } } }
struct Base
diff --git a/gcc/testsuite/g++.dg/cpp0x/pr87250.C b/gcc/testsuite/g++.dg/cpp0x/pr87250.C
new file mode 100644
index 0000000..fe4bf14
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/pr87250.C
@@ -0,0 +1,12 @@
+// PR c++/87250
+// { dg-do compile { target c++11 } }
+// { dg-options "-Os -fsyntax-only" }
+
+template <typename> struct a {
+ constexpr a(int) {}
+};
+template <typename> struct atomic;
+template <> struct atomic<bool> {
+ a<bool> b;
+ constexpr atomic(bool c) : b(c) {}
+};
diff --git a/gcc/testsuite/g++.dg/cpp0x/pr90598.C b/gcc/testsuite/g++.dg/cpp0x/pr90598.C
new file mode 100644
index 0000000..0ee3fb1
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/pr90598.C
@@ -0,0 +1,8 @@
+// PR c++/90598
+// { dg-do compile { target c++11 } }
+
+struct A {};
+using B = decltype(A ().~A ());
+template <typename T> struct C;
+template <> struct C<void> {};
+C<B> t;
diff --git a/gcc/testsuite/g++.dg/cpp0x/static_assert12.C b/gcc/testsuite/g++.dg/cpp0x/static_assert12.C
index 5d59e54..2ff5e00 100644
--- a/gcc/testsuite/g++.dg/cpp0x/static_assert12.C
+++ b/gcc/testsuite/g++.dg/cpp0x/static_assert12.C
@@ -27,4 +27,4 @@ main()
float_thing(1);
}
-// { dg-warning "static_assert without a message only available with " "" { target *-*-* } 21 }
+// { dg-warning "'static_assert' without a message only available with " "" { target *-*-* } 21 }
diff --git a/gcc/testsuite/g++.dg/cpp0x/static_assert8.C b/gcc/testsuite/g++.dg/cpp0x/static_assert8.C
index 239fe17..bca38ff 100644
--- a/gcc/testsuite/g++.dg/cpp0x/static_assert8.C
+++ b/gcc/testsuite/g++.dg/cpp0x/static_assert8.C
@@ -6,4 +6,4 @@ static_assert (1 == 0,); // { dg-error "expected string-literal before '\\)'" }
static_assert (1 == 0, "oops"); // { dg-error "static assertion failed" }
-// { dg-error "static_assert without a message only available with " "" { target { ! c++17 } } 3 }
+// { dg-error "'static_assert' without a message only available with " "" { target { ! c++17 } } 3 }
diff --git a/gcc/testsuite/g++.dg/cpp0x/std_fext-numeric-literals.C b/gcc/testsuite/g++.dg/cpp0x/std_fext-numeric-literals.C
index 72b8546..d251c74 100644
--- a/gcc/testsuite/g++.dg/cpp0x/std_fext-numeric-literals.C
+++ b/gcc/testsuite/g++.dg/cpp0x/std_fext-numeric-literals.C
@@ -22,55 +22,55 @@ operator"" J(unsigned long long n) // { dg-warning "1:integer suffix .J. shadowe
// Floating-point imaginary...
constexpr long double
-operator"" i(long double n) // { dg-warning "1:floating point suffix .i. shadowed by implementation" "" { target c++11_only } }
+operator"" i(long double n) // { dg-warning "1:floating-point suffix .i. shadowed by implementation" "" { target c++11_only } }
{ return 4.0L * n + 0.0L; }
constexpr long double
-operator"" I(long double n) // { dg-warning "1:floating point suffix .I. shadowed by implementation" }
+operator"" I(long double n) // { dg-warning "1:floating-point suffix .I. shadowed by implementation" }
{ return 4.0L * n + 1.0L; }
constexpr long double
-operator"" j(long double n) // { dg-warning "1:floating point suffix .j. shadowed by implementation" }
+operator"" j(long double n) // { dg-warning "1:floating-point suffix .j. shadowed by implementation" }
{ return 4.0L * n + 2.0L; }
constexpr long double
-operator"" J(long double n) // { dg-warning "1:floating point suffix .J. shadowed by implementation" }
+operator"" J(long double n) // { dg-warning "1:floating-point suffix .J. shadowed by implementation" }
{ return 4.0L * n + 3.0L; }
// Fixed-point...
constexpr long double
-operator"" k(long double n) // { dg-warning "1:floating point suffix .k. shadowed by implementation" }
+operator"" k(long double n) // { dg-warning "1:floating-point suffix .k. shadowed by implementation" }
{ return 4 * (n + 1) + 0; }
constexpr long double
-operator"" K(long double n) // { dg-warning "1:floating point suffix .K. shadowed by implementation" }
+operator"" K(long double n) // { dg-warning "1:floating-point suffix .K. shadowed by implementation" }
{ return 4 * (n + 1) + 1; }
constexpr long double
-operator"" r(long double n) // { dg-warning "1:floating point suffix .r. shadowed by implementation" }
+operator"" r(long double n) // { dg-warning "1:floating-point suffix .r. shadowed by implementation" }
{ return 4 * (n + 1) + 2; }
constexpr long double
-operator"" R(long double n) // { dg-warning "1:floating point suffix .R. shadowed by implementation" }
+operator"" R(long double n) // { dg-warning "1:floating-point suffix .R. shadowed by implementation" }
{ return 4 * (n + 1) + 3; }
// Machine-defined...
constexpr long double
-operator"" w(long double n) // { dg-warning "1:floating point suffix .w. shadowed by implementation" }
+operator"" w(long double n) // { dg-warning "1:floating-point suffix .w. shadowed by implementation" }
{ return 4 * (n + 2) + 0; }
constexpr long double
-operator"" W(long double n) // { dg-warning "1:floating point suffix .W. shadowed by implementation" }
+operator"" W(long double n) // { dg-warning "1:floating-point suffix .W. shadowed by implementation" }
{ return 4 * (n + 2) + 1; }
constexpr long double
-operator"" q(long double n) // { dg-warning "1:floating point suffix .q. shadowed by implementation" }
+operator"" q(long double n) // { dg-warning "1:floating-point suffix .q. shadowed by implementation" }
{ return 4 * (n + 2) + 2; }
constexpr long double
-operator"" Q(long double n) // { dg-warning "1:floating point suffix .Q. shadowed by implementation" }
+operator"" Q(long double n) // { dg-warning "1:floating-point suffix .Q. shadowed by implementation" }
{ return 4 * (n + 2) + 3; }
int
diff --git a/gcc/testsuite/g++.dg/cpp0x/udlit-nofunc-neg.C b/gcc/testsuite/g++.dg/cpp0x/udlit-nofunc-neg.C
index 89c7581..861a77c 100644
--- a/gcc/testsuite/g++.dg/cpp0x/udlit-nofunc-neg.C
+++ b/gcc/testsuite/g++.dg/cpp0x/udlit-nofunc-neg.C
@@ -3,7 +3,7 @@
// Test user-defined literals.
// Test error on non-function declaration.
-double operator"" _baddecl; // { dg-error "as non-function" }
+double operator"" _baddecl; // { dg-error "8:declaration of .operator\"\"_baddecl. as non-function" }
template<char...>
- int operator"" _badtmpldecl; // { dg-error "as non-function" }
+ int operator"" _badtmpldecl; // { dg-error "7:declaration of .operator\"\"_badtmpldecl. as non-function" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/udlit-shadow-neg.C b/gcc/testsuite/g++.dg/cpp0x/udlit-shadow-neg.C
index c635590..fdddd8d 100644
--- a/gcc/testsuite/g++.dg/cpp0x/udlit-shadow-neg.C
+++ b/gcc/testsuite/g++.dg/cpp0x/udlit-shadow-neg.C
@@ -2,7 +2,7 @@
// Test that the standard suffixes shadow any user-defined suffixes of the same name.
long double
-operator"" L(long double x) // { dg-warning "floating point suffix|shadowed by implementation" }
+operator"" L(long double x) // { dg-warning "floating-point suffix|shadowed by implementation" }
{ return x; }
unsigned long long int
@@ -10,7 +10,7 @@ operator"" ULL(unsigned long long int k) // { dg-warning "integer suffix|shadow
{ return k; }
long double
-operator"" l(long double x) // { dg-warning "floating point suffix|shadowed by implementation" }
+operator"" l(long double x) // { dg-warning "floating-point suffix|shadowed by implementation" }
{ return x; }
unsigned long long int
diff --git a/gcc/testsuite/g++.dg/cpp0x/udlit-tmpl-arg-neg2.C b/gcc/testsuite/g++.dg/cpp0x/udlit-tmpl-arg-neg2.C
index c426e0e..f2db95d 100644
--- a/gcc/testsuite/g++.dg/cpp0x/udlit-tmpl-arg-neg2.C
+++ b/gcc/testsuite/g++.dg/cpp0x/udlit-tmpl-arg-neg2.C
@@ -2,6 +2,6 @@
// { dg-do compile { target c++11 } }
template <T, T... U> // { dg-error "'T' has not been declared" }
-int operator"" _foo (); // { dg-error "has invalid parameter list" }
+int operator"" _foo (); // { dg-error "5:literal operator template .int operator\"\"_foo\\(\\). has invalid parameter list" }
template <T... U> // { dg-error "'T' has not been declared" }
-int operator"" _bar (); // { dg-error "has invalid parameter list" }
+int operator"" _bar (); // { dg-error "5:literal operator template .int operator\"\"_bar\\(\\). has invalid parameter list" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/udlit-tmpl-parms-neg.C b/gcc/testsuite/g++.dg/cpp0x/udlit-tmpl-parms-neg.C
index f681ecf..167d871 100644
--- a/gcc/testsuite/g++.dg/cpp0x/udlit-tmpl-parms-neg.C
+++ b/gcc/testsuite/g++.dg/cpp0x/udlit-tmpl-parms-neg.C
@@ -3,10 +3,10 @@
class Foo { };
template<wchar_t...>
- Foo operator"" _Foo(); // { dg-error "literal operator template|has invalid parameter list" }
+ Foo operator"" _Foo(); // { dg-error "7:literal operator template .Foo operator\"\"_Foo\\(\\). has invalid parameter list" }
template<char>
- Foo operator"" _Bar(); // { dg-error "literal operator template|has invalid parameter list" }
+ Foo operator"" _Bar(); // { dg-error "7:literal operator template .Foo operator\"\"_Bar\\(\\). has invalid parameter list" }
template<typename... Type>
- Foo operator"" _Bar(); // { dg-error "literal operator template|has invalid parameter list" }
+ Foo operator"" _Bar(); // { dg-error "7:literal operator template .Foo operator\"\"_Bar\\(\\). has invalid parameter list" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic177.C b/gcc/testsuite/g++.dg/cpp0x/variadic177.C
new file mode 100644
index 0000000..96736a0
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic177.C
@@ -0,0 +1,12 @@
+// PR c++/71548
+// { dg-do compile { target c++11 } }
+
+template<typename> class fl {};
+template<typename = void, template<class...> class = fl>
+struct S {};
+template<typename... T>
+void f(S<T...> ) {}
+void lol() {
+ S<> s;
+ f(s); // { dg-error "no matching function for call to" }
+}
diff --git a/gcc/testsuite/g++.dg/cpp1y/constexpr-79655.C b/gcc/testsuite/g++.dg/cpp1y/constexpr-79655.C
index cc9ce6c..063d556 100644
--- a/gcc/testsuite/g++.dg/cpp1y/constexpr-79655.C
+++ b/gcc/testsuite/g++.dg/cpp1y/constexpr-79655.C
@@ -5,14 +5,14 @@ constexpr int
foo (int x, int y)
{
int a[6] = { 1, 2, 3, 4, 5, 6 };
- a[x] = 0;
- return a[y];
+ a[x] = 0; // { dg-error "is outside the bounds" }
+ return a[y]; // { dg-error "is outside the bounds" }
}
-constexpr int b = foo (0, -1); // { dg-error "is outside the bounds|in .constexpr. expansion of " }
-constexpr int c = foo (0, 6); // { dg-error "is outside the bounds|in .constexpr. expansion of " }
-constexpr int d = foo (6, 0); // { dg-error "is outside the bounds|in .constexpr. expansion of " }
-constexpr int e = foo (-1, 0); // { dg-error "is outside the bounds|in .constexpr. expansion of " }
+constexpr int b = foo (0, -1); // { dg-message "in .constexpr. expansion of " }
+constexpr int c = foo (0, 6); // { dg-message "in .constexpr. expansion of " }
+constexpr int d = foo (6, 0); // { dg-message "in .constexpr. expansion of " }
+constexpr int e = foo (-1, 0); // { dg-message "in .constexpr. expansion of " }
static_assert (foo (5, 5) == 0, "");
static_assert (foo (4, 5) == 6, "");
static_assert (foo (5, 4) == 5, "");
diff --git a/gcc/testsuite/g++.dg/cpp1y/constexpr-90383-1.C b/gcc/testsuite/g++.dg/cpp1y/constexpr-90383-1.C
new file mode 100644
index 0000000..b398331
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1y/constexpr-90383-1.C
@@ -0,0 +1,15 @@
+// PR c++/90383
+// { dg-do compile { target c++14 } }
+
+struct alignas(8) A { constexpr A (bool x) : a(x) {} A () = delete; bool a; };
+struct B { A b; };
+
+constexpr bool
+foo ()
+{
+ B w{A (true)};
+ w.b = A (true);
+ return w.b.a;
+}
+
+static_assert (foo (), "");
diff --git a/gcc/testsuite/g++.dg/cpp1y/constexpr-90383-2.C b/gcc/testsuite/g++.dg/cpp1y/constexpr-90383-2.C
new file mode 100644
index 0000000..a08b1dd
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1y/constexpr-90383-2.C
@@ -0,0 +1,22 @@
+// PR c++/90383
+// { dg-do run { target c++14 } }
+// { dg-options "-O2" }
+
+extern "C" void abort ();
+struct alignas(8) A { constexpr A (bool x) : a(x) {} A () = default; bool a; };
+struct B { A b; };
+
+constexpr bool
+foo ()
+{
+ B w{A (true)};
+ w.b = A (true);
+ return w.b.a;
+}
+
+int
+main ()
+{
+ if (!foo ())
+ abort ();
+}
diff --git a/gcc/testsuite/g++.dg/cpp1y/feat-cxx14.C b/gcc/testsuite/g++.dg/cpp1y/feat-cxx14.C
index 412b9a3..a2a93f4 100644
--- a/gcc/testsuite/g++.dg/cpp1y/feat-cxx14.C
+++ b/gcc/testsuite/g++.dg/cpp1y/feat-cxx14.C
@@ -303,11 +303,11 @@
#if __has_include(<array>)
# define STD_ARRAY 1
# include <array>
- template<typename _Tp, size_t _Num>
+ template<typename _Tp, std::size_t _Num>
using array = std::array<_Tp, _Num>;
#elif __has_include(<tr1/array>)
# define TR1_ARRAY 1
# include <tr1/array>
- template<typename _Tp, size_t _Num>
+ template<typename _Tp, std::size_t _Num>
typedef std::tr1::array<_Tp, _Num> array;
#endif
diff --git a/gcc/testsuite/g++.dg/cpp1y/lambda-conv1.C b/gcc/testsuite/g++.dg/cpp1y/lambda-conv1.C
index 2e4ec49..2572125 100644
--- a/gcc/testsuite/g++.dg/cpp1y/lambda-conv1.C
+++ b/gcc/testsuite/g++.dg/cpp1y/lambda-conv1.C
@@ -4,10 +4,10 @@
void foo()
{
int i;
- static_cast<void(*)(int)>([i](auto){}); // { dg-error "invalid static_cast" }
- static_cast<void(*)(int)>([=](auto){}); // { dg-error "invalid static_cast" }
- static_cast<void(*)(int)>([&](auto){}); // { dg-error "invalid static_cast" }
- static_cast<float(*)(float)>([i](auto x){ return x; }); // { dg-error "invalid static_cast" }
- static_cast<float(*)(float)>([=](auto x){ return x; }); // { dg-error "invalid static_cast" }
- static_cast<float(*)(float)>([&](auto x){ return x; }); // { dg-error "invalid static_cast" }
+ static_cast<void(*)(int)>([i](auto){}); // { dg-error "invalid 'static_cast'" }
+ static_cast<void(*)(int)>([=](auto){}); // { dg-error "invalid 'static_cast'" }
+ static_cast<void(*)(int)>([&](auto){}); // { dg-error "invalid 'static_cast'" }
+ static_cast<float(*)(float)>([i](auto x){ return x; }); // { dg-error "invalid 'static_cast'" }
+ static_cast<float(*)(float)>([=](auto x){ return x; }); // { dg-error "invalid 'static_cast'" }
+ static_cast<float(*)(float)>([&](auto x){ return x; }); // { dg-error "invalid 'static_cast'" }
}
diff --git a/gcc/testsuite/g++.dg/cpp1y/lambda-generic-90548.C b/gcc/testsuite/g++.dg/cpp1y/lambda-generic-90548.C
new file mode 100644
index 0000000..b845dd8
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1y/lambda-generic-90548.C
@@ -0,0 +1,22 @@
+// PR c++/90548
+// { dg-do compile { target c++14 } }
+
+struct S { S (void ()); };
+S foo([] (auto...) { });
+S foo2{[] (auto...) {}};
+S foo3 = {[] (auto...) {}};
+
+struct W { W(void (int)); };
+W bar([](auto...) { });
+W bar2{[](auto...) { }};
+W bar3 = {[](auto...) { }};
+
+struct T { T(void (int, int)); };
+T qux([](auto...) { });
+T qux2{[](auto...) { }};
+T qux3 = {[](auto...) { }};
+
+struct R { R(void (int, int, int, int, int, int, int, int, int, int)); };
+R baz([](auto...) { });
+R baz2{[](auto...) { }};
+R baz3 = {[](auto...) { }};
diff --git a/gcc/testsuite/g++.dg/cpp1y/noexcept1.C b/gcc/testsuite/g++.dg/cpp1y/noexcept1.C
new file mode 100644
index 0000000..86e46c96
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1y/noexcept1.C
@@ -0,0 +1,13 @@
+// PR c++/89873
+// { dg-do compile { target c++14 } }
+
+template <int> bool b;
+
+template <typename>
+struct C {
+ template <typename> friend int foo() noexcept(b<1>); // { dg-error "not usable in a constant expression|different exception specifier" }
+};
+
+template <typename> int foo() noexcept(b<1>);
+
+auto a = C<int>();
diff --git a/gcc/testsuite/g++.dg/cpp1y/pr77830.C b/gcc/testsuite/g++.dg/cpp1y/pr77830.C
index 6fcb1ba..21eeda3 100644
--- a/gcc/testsuite/g++.dg/cpp1y/pr77830.C
+++ b/gcc/testsuite/g++.dg/cpp1y/pr77830.C
@@ -13,7 +13,7 @@ constexpr void
P<N>::foo (const char *, int i)
{
for (auto j = 0; j < 2; ++j)
- arr[i][j] = true;
+ arr[i][j] = true; // { dg-error "outside the bounds of array type" }
}
template <typename... T>
@@ -30,5 +30,5 @@ bar (T... a)
int
main ()
{
- constexpr auto a = bar ("", ""); // { dg-error "outside the bounds of array type|in .constexpr. expansion of " }
+ constexpr auto a = bar ("", ""); // { dg-message "in .constexpr. expansion of " }
}
diff --git a/gcc/testsuite/g++.dg/cpp1y/pr79393-3.C b/gcc/testsuite/g++.dg/cpp1y/pr79393-3.C
index 23dc265..3c73cbb 100644
--- a/gcc/testsuite/g++.dg/cpp1y/pr79393-3.C
+++ b/gcc/testsuite/g++.dg/cpp1y/pr79393-3.C
@@ -18,7 +18,7 @@ struct B : virtual A
};
B::~B () {
- throw 1; // { dg-warning "will always call terminate" }
+ throw 1; // { dg-warning "will always call 'terminate'" }
}
struct C : virtual A
diff --git a/gcc/testsuite/g++.dg/cpp1y/pr87410.C b/gcc/testsuite/g++.dg/cpp1y/pr87410.C
new file mode 100644
index 0000000..5a691e4
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1y/pr87410.C
@@ -0,0 +1,19 @@
+// PR c++/87410
+// { dg-do compile { target c++14 } }
+
+template <long a> using b = const char[a];
+template <typename, int c, int e, typename f>
+constexpr auto g(b<c> &, b<e> &, f) {}
+template <typename d, int a> auto h(b<a> &) {
+ auto i = j(static_cast<d **>(nullptr));
+ return **i;
+}
+class k {
+ using l = k;
+ const int &m() const;
+ friend constexpr auto j(l **n) -> decltype(n) {
+ g<int>("", "", static_cast<const int &(k::*)() const>(&k::m));
+ return n;
+ }
+};
+k o = h<k, 1>("");
diff --git a/gcc/testsuite/g++.dg/cpp1y/static_assert1.C b/gcc/testsuite/g++.dg/cpp1y/static_assert1.C
index ef655f4..06815fd 100644
--- a/gcc/testsuite/g++.dg/cpp1y/static_assert1.C
+++ b/gcc/testsuite/g++.dg/cpp1y/static_assert1.C
@@ -28,4 +28,4 @@ main()
float_thing(1);
}
-// { dg-warning "static_assert without a message only available with " "" { target *-*-* } 21 }
+// { dg-warning "'static_assert' without a message only available with " "" { target *-*-* } 21 }
diff --git a/gcc/testsuite/g++.dg/cpp1y/udlit-char-template-neg.C b/gcc/testsuite/g++.dg/cpp1y/udlit-char-template-neg.C
index e77ea45..d3d7121 100644
--- a/gcc/testsuite/g++.dg/cpp1y/udlit-char-template-neg.C
+++ b/gcc/testsuite/g++.dg/cpp1y/udlit-char-template-neg.C
@@ -2,7 +2,7 @@
template<typename CharT, CharT... String>
int
- operator"" _script()
- { return 42; } // { dg-error "literal operator template|has invalid parameter list" }
+ operator"" _script() // { dg-error "3:literal operator template" }
+ { return 42; }
int i = "hi!"_script;
diff --git a/gcc/testsuite/g++.dg/cpp1z/constexpr-if4.C b/gcc/testsuite/g++.dg/cpp1z/constexpr-if4.C
index 612eff8..871e31a 100644
--- a/gcc/testsuite/g++.dg/cpp1z/constexpr-if4.C
+++ b/gcc/testsuite/g++.dg/cpp1z/constexpr-if4.C
@@ -4,7 +4,7 @@
void f()
{
goto l; // { dg-message "from here" }
- if constexpr (false) // { dg-message "enters constexpr if" }
+ if constexpr (false) // { dg-message "enters 'constexpr if'" }
{
l:; // { dg-error "jump to label" }
}
diff --git a/gcc/testsuite/g++.dg/cpp1z/constexpr-if5.C b/gcc/testsuite/g++.dg/cpp1z/constexpr-if5.C
index 69d03e3..9d30b0e 100644
--- a/gcc/testsuite/g++.dg/cpp1z/constexpr-if5.C
+++ b/gcc/testsuite/g++.dg/cpp1z/constexpr-if5.C
@@ -3,7 +3,7 @@
void f()
{
- if constexpr (false) // { dg-message "enters constexpr if" }
+ if constexpr (false) // { dg-message "enters 'constexpr if'" }
{
goto l; // { dg-message "from here" }
}
diff --git a/gcc/testsuite/g++.dg/cpp1z/constexpr-if9.C b/gcc/testsuite/g++.dg/cpp1z/constexpr-if9.C
index 748278a..8aa87f7 100644
--- a/gcc/testsuite/g++.dg/cpp1z/constexpr-if9.C
+++ b/gcc/testsuite/g++.dg/cpp1z/constexpr-if9.C
@@ -4,7 +4,7 @@
void f(int i)
{
switch (i)
- if constexpr (false) // { dg-message "enters constexpr if" }
+ if constexpr (false) // { dg-message "enters 'constexpr if'" }
{
case 42:; // { dg-error "jump to case label" }
}
diff --git a/gcc/testsuite/g++.dg/cpp1z/decomp3.C b/gcc/testsuite/g++.dg/cpp1z/decomp3.C
index 95e9f37..a9b23b0 100644
--- a/gcc/testsuite/g++.dg/cpp1z/decomp3.C
+++ b/gcc/testsuite/g++.dg/cpp1z/decomp3.C
@@ -35,12 +35,17 @@ test (A &b, B c)
// { dg-warning "structured bindings only available with '-std=c..17' or '-std=gnu..17'" "" { target c++14_down } .-1 }
explicit auto [ w ] = c; // { dg-error "'explicit' outside class declaration" }
// { dg-warning "structured bindings only available with '-std=c..17' or '-std=gnu..17'" "" { target c++14_down } .-1 }
- static auto [ x ] = c; // { dg-error "structured binding declaration cannot be 'static'" }
+ static auto [ x ] = c; // { dg-warning "structured binding declaration can be 'static' only in" "" { target c++17_down } }
// { dg-warning "structured bindings only available with '-std=c..17' or '-std=gnu..17'" "" { target c++14_down } .-1 }
extern auto [ y ] { c }; // { dg-error "structured binding declaration cannot be 'extern'" }
// { dg-warning "structured bindings only available with '-std=c..17' or '-std=gnu..17'" "" { target c++14_down } .-1 }
+ thread_local auto [ z ] = c; // { dg-warning "structured binding declaration can be 'thread_local' only in" "" { target c++17_down } }
+ // { dg-warning "structured bindings only available with '-std=c..17' or '-std=gnu..17'" "" { target c++14_down } .-1 }
}
+__thread auto [ z2 ] = B (); // { dg-warning "structured binding declaration can be '__thread' only in" "" { target c++17_down } }
+ // { dg-warning "structured bindings only available with '-std=c..17' or '-std=gnu..17'" "" { target c++14_down } .-1 }
+
void
test2 (auto & [ p ] = bar ()) // { dg-error "'p' was not declared in this scope" }
{ // { dg-warning "auto" "" { target { ! concepts } } .-1 }
diff --git a/gcc/testsuite/g++.dg/cpp1z/feat-cxx1z.C b/gcc/testsuite/g++.dg/cpp1z/feat-cxx1z.C
index da372dc..a5d9446 100644
--- a/gcc/testsuite/g++.dg/cpp1z/feat-cxx1z.C
+++ b/gcc/testsuite/g++.dg/cpp1z/feat-cxx1z.C
@@ -292,12 +292,12 @@
#if __has_include(<array>)
# define STD_ARRAY 1
# include <array>
- template<typename _Tp, size_t _Num>
+ template<typename _Tp, std::size_t _Num>
using array = std::array<_Tp, _Num>;
#elif __has_include(<tr1/array>)
# define TR1_ARRAY 1
# include <tr1/array>
- template<typename _Tp, size_t _Num>
+ template<typename _Tp, std::size_t _Num>
typedef std::tr1::array<_Tp, _Num> array;
#endif
diff --git a/gcc/testsuite/g++.dg/cpp1z/inline-var2.C b/gcc/testsuite/g++.dg/cpp1z/inline-var2.C
index 1a016fa..236f6ec 100644
--- a/gcc/testsuite/g++.dg/cpp1z/inline-var2.C
+++ b/gcc/testsuite/g++.dg/cpp1z/inline-var2.C
@@ -47,7 +47,7 @@ struct W
{
static inline int var24; // { dg-warning "10:inline variables are only available with" "" { target c++14_down } }
static inline const int var25; // { dg-warning "10:inline variables are only available with" "" { target c++14_down } }
- // { dg-error "uninitialized const" "" { target *-*-* } .-1 }
+ // { dg-error "uninitialized 'const" "" { target *-*-* } .-1 }
static inline int var26 = 5; // { dg-warning "10:inline variables are only available with" "" { target c++14_down } }
static inline const int var27 = 6; // { dg-warning "10:inline variables are only available with" "" { target c++14_down } }
static inline double var28 = { 4.0 }; // { dg-warning "10:inline variables are only available with" "" { target c++14_down } }
@@ -90,7 +90,7 @@ struct Z
{
static inline int var37; // { dg-warning "10:inline variables are only available with" "" { target c++14_down } }
static inline const int var38; // { dg-warning "10:inline variables are only available with" "" { target c++14_down } }
- // { dg-error "uninitialized const" "" { target *-*-* } .-1 }
+ // { dg-error "uninitialized 'const" "" { target *-*-* } .-1 }
static inline int var39 = 5; // { dg-warning "10:inline variables are only available with" "" { target c++14_down } }
static inline const int var40 = 6; // { dg-warning "10:inline variables are only available with" "" { target c++14_down } }
static inline double var41 = { 4.0 }; // { dg-warning "10:inline variables are only available with" "" { target c++14_down } }
diff --git a/gcc/testsuite/g++.dg/cpp1z/inline-var7.C b/gcc/testsuite/g++.dg/cpp1z/inline-var7.C
new file mode 100644
index 0000000..71fa1d3
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1z/inline-var7.C
@@ -0,0 +1,20 @@
+// PR c++/87512
+// { dg-do compile { target c++17 } }
+
+template <int, typename T = int> using enable_if_t = int;
+template<typename T> struct is_pointer { enum { value = 0 }; };
+
+template <typename T>
+inline constexpr auto IsPtr = is_pointer<T>::value;
+
+class Foo;
+class Bar;
+
+template <typename T1, typename T2>
+void foo(T1, T2);
+
+template <typename T>
+enable_if_t<IsPtr<T>> foo(T, Foo);
+
+template <>
+void foo<Bar>(Bar, Bar);
diff --git a/gcc/testsuite/g++.dg/cpp1z/pr85569.C b/gcc/testsuite/g++.dg/cpp1z/pr85569.C
index aec5430..fae13d8 100644
--- a/gcc/testsuite/g++.dg/cpp1z/pr85569.C
+++ b/gcc/testsuite/g++.dg/cpp1z/pr85569.C
@@ -2,6 +2,7 @@
#include <utility>
#include <tuple>
+#include <functional>
#define LIFT_FWD(x) std::forward<decltype(x)>(x)
diff --git a/gcc/testsuite/g++.dg/cpp1z/register1.C b/gcc/testsuite/g++.dg/cpp1z/register1.C
index 44071bd..fac3498 100644
--- a/gcc/testsuite/g++.dg/cpp1z/register1.C
+++ b/gcc/testsuite/g++.dg/cpp1z/register1.C
@@ -10,7 +10,7 @@
register int a __asm (REG1); // { dg-bogus "ISO C\\+\\+17 does not allow 'register' storage class specifier" "" { target c++17 } }
#endif
register int b; // { dg-error "ISO C\\+\\+17 does not allow 'register' storage class specifier" "" { target c++17 } }
-register int c (); // { dg-error "storage class 'register' invalid for function" }
+register int c (); // { dg-error "1:storage class 'register' invalid for function" }
int foo (register int d) // { dg-error "ISO C\\+\\+17 does not allow 'register' storage class specifier" "" { target c++17 } }
{
return d;
diff --git a/gcc/testsuite/g++.dg/cpp1z/register2.C b/gcc/testsuite/g++.dg/cpp1z/register2.C
index 5d7c9f6..3688f73 100644
--- a/gcc/testsuite/g++.dg/cpp1z/register2.C
+++ b/gcc/testsuite/g++.dg/cpp1z/register2.C
@@ -11,7 +11,7 @@
register int a __asm (REG1); // { dg-bogus "ISO C\\+\\+17 does not allow 'register' storage class specifier" "" { target c++17 } }
#endif
register int b; // { dg-bogus "ISO C\\+\\+17 does not allow 'register' storage class specifier" "" { target c++17 } }
-register int c (); // { dg-error "storage class 'register' invalid for function" }
+register int c (); // { dg-error "1:storage class 'register' invalid for function" }
int foo (register int d) // { dg-bogus "ISO C\\+\\+17 does not allow 'register' storage class specifier" "" { target c++17 } }
{
return d;
diff --git a/gcc/testsuite/g++.dg/cpp1z/register3.C b/gcc/testsuite/g++.dg/cpp1z/register3.C
index 90b7f9d..2b32116 100644
--- a/gcc/testsuite/g++.dg/cpp1z/register3.C
+++ b/gcc/testsuite/g++.dg/cpp1z/register3.C
@@ -11,7 +11,7 @@
register int a __asm (REG1); // { dg-bogus "'register' storage class specifier used" }
#endif
register int b; // { dg-warning "'register' storage class specifier used" }
-register int c (); // { dg-error "storage class 'register' invalid for function" }
+register int c (); // { dg-error "1:storage class 'register' invalid for function" }
int foo (register int d) // { dg-warning "'register' storage class specifier used" }
{
return d;
diff --git a/gcc/testsuite/g++.dg/cpp2a/decomp1-aux.cc b/gcc/testsuite/g++.dg/cpp2a/decomp1-aux.cc
new file mode 100644
index 0000000..2aaa2df
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/decomp1-aux.cc
@@ -0,0 +1,52 @@
+// P1091R3
+// { dg-do compile { target { c++17 && c++14_down } } }
+
+namespace std {
+ template<typename T> struct tuple_size;
+ template<int, typename> struct tuple_element;
+}
+
+struct A {
+ int i;
+ A(int x) : i(x) {}
+ template <int I> int& get() { return i; }
+};
+struct B { int a, b, c; };
+
+template<> struct std::tuple_size<A> { static const int value = 2; };
+template<int I> struct std::tuple_element<I,A> { using type = int; };
+
+B s = { 1, 2, 3 };
+
+#line 1
+static auto [ d, e, f ] = s;
+static auto [ g, h ] = A (42);
+
+int &
+foo (int x)
+{
+ switch (x)
+ {
+ case 0: return d;
+ case 1: return e;
+ case 2: return f;
+ case 3: return g;
+ default: return h;
+ }
+}
+
+int
+bar (int x)
+{
+#line 3
+ static auto [ m, n, o ] = s;
+ static auto [ p, q ] = A (43);
+ switch (x)
+ {
+ case 0: return ++m;
+ case 1: return ++n;
+ case 2: return ++o;
+ case 3: return ++p;
+ default: return ++q;
+ }
+}
diff --git a/gcc/testsuite/g++.dg/cpp2a/decomp1.C b/gcc/testsuite/g++.dg/cpp2a/decomp1.C
new file mode 100644
index 0000000..7f7dab5
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/decomp1.C
@@ -0,0 +1,92 @@
+// P1091R3
+// { dg-do run { target c++11 } }
+// { dg-options "" }
+// { dg-additional-sources decomp1-aux.cc }
+
+namespace std {
+ template<typename T> struct tuple_size;
+ template<int, typename> struct tuple_element;
+}
+
+struct A {
+ int i;
+ A(int x) : i(x) {}
+ template <int I> int& get() { return i; }
+};
+struct B { int a, b, c; };
+
+template<> struct std::tuple_size<A> { static const int value = 2; };
+template<int I> struct std::tuple_element<I,A> { using type = int; };
+
+extern int &foo (int);
+extern int bar (int);
+extern B s;
+extern "C" void abort ();
+B t = { 4, 5, 6 };
+
+static auto [ d, e, f ] = t; // { dg-warning "structured binding declaration can be 'static' only" "" { target c++17_down } }
+ // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 }
+static auto [ g, h ] = A (44); // { dg-warning "structured binding declaration can be 'static' only" "" { target c++17_down } }
+ // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 }
+// The following warnings are in decomp1-aux.cc with #line directive.
+// { dg-warning "structured binding declaration can be 'static' only" "" { target c++17_down } 1 }
+// { dg-warning "structured bindings only available with" "" { target c++14_down } 1 }
+// { dg-warning "structured binding declaration can be 'static' only" "" { target c++17_down } 2 }
+// { dg-warning "structured bindings only available with" "" { target c++14_down } 2 }
+// { dg-warning "structured binding declaration can be 'static' only" "" { target c++17_down } 3 }
+// { dg-warning "structured bindings only available with" "" { target c++14_down } 3 }
+// { dg-warning "structured binding declaration can be 'static' only" "" { target c++17_down } 4 }
+// { dg-warning "structured bindings only available with" "" { target c++14_down } 4 }
+
+int &
+baz (int x)
+{
+ switch (x)
+ {
+ case 0: return d;
+ case 1: return e;
+ case 2: return f;
+ case 3: return g;
+ default: return h;
+ }
+}
+
+int
+qux (int x)
+{
+ static auto [ m, n, o ] = t; // { dg-warning "structured binding declaration can be 'static' only" "" { target c++17_down } }
+ // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 }
+ static auto [ p, q ] = A (45); // { dg-warning "structured binding declaration can be 'static' only" "" { target c++17_down } }
+ // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 }
+ switch (x)
+ {
+ case 0: return ++m;
+ case 1: return ++n;
+ case 2: return ++o;
+ case 3: return ++p;
+ default: return ++q;
+ }
+}
+
+int
+main ()
+{
+ int *a[10];
+ for (int i = 0; i < 5; ++i)
+ {
+ a[i] = &foo (i);
+ a[i + 5] = &baz (i);
+ }
+ for (int i = 0; i < 10; ++i)
+ for (int j = i + 1; j < 10; ++j)
+ if (a[i] == a[j] && (j != i + 1 || (i % 5) != 3))
+ abort ();
+ if (a[1] != a[0] + 1 || a[2] != a[0] + 2 || a[4] != a[3]
+ || a[6] != a[5] + 1 || a[7] != a[5] + 2 || a[9] != a[8])
+ abort ();
+ int b[] = { 1, 2, 3, 43, 43 + 6, 4, 5, 6, 45, 45 + 11 };
+ for (int i = 0; i < 10; ++i)
+ for (int j = 0; j < 3 + i; ++j)
+ if ((i < 5 ? bar (i) : qux (i - 5)) != b[i] + 1 + j)
+ abort ();
+}
diff --git a/gcc/testsuite/g++.dg/cpp2a/decomp2.C b/gcc/testsuite/g++.dg/cpp2a/decomp2.C
new file mode 100644
index 0000000..9149d02
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/decomp2.C
@@ -0,0 +1,76 @@
+// P1091R3
+// { dg-do run { target c++11 } }
+// { dg-options "" }
+// { dg-require-effective-target tls }
+
+namespace std {
+ template<typename T> struct tuple_size;
+ template<int, typename> struct tuple_element;
+}
+
+struct A {
+ int i;
+ A(int x) : i(x) {}
+ template <int I> int& get() { return i; }
+};
+struct B { int a, b, c; };
+
+template<> struct std::tuple_size<A> { static const int value = 2; };
+template<int I> struct std::tuple_element<I,A> { using type = int; };
+
+extern "C" void abort ();
+B t = { 4, 5, 6 };
+
+thread_local auto [ d, e, f ] = t; // { dg-warning "structured binding declaration can be 'thread_local' only" "" { target c++17_down } }
+ // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 }
+thread_local auto [ g, h ] = A (44); // { dg-warning "structured binding declaration can be 'thread_local' only" "" { target c++17_down } }
+ // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 }
+
+int &
+baz (int x)
+{
+ switch (x)
+ {
+ case 0: return d;
+ case 1: return e;
+ case 2: return f;
+ case 3: return g;
+ default: return h;
+ }
+}
+
+int
+qux (int x)
+{
+ thread_local auto [ m, n, o ] = t; // { dg-warning "structured binding declaration can be 'thread_local' only" "" { target c++17_down } }
+ // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 }
+ thread_local auto [ p, q ] = A (45); // { dg-warning "structured binding declaration can be 'thread_local' only" "" { target c++17_down } }
+ // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 }
+ switch (x)
+ {
+ case 0: return ++m;
+ case 1: return ++n;
+ case 2: return ++o;
+ case 3: return ++p;
+ default: return ++q;
+ }
+}
+
+int
+main ()
+{
+ int *a[5];
+ for (int i = 0; i < 5; ++i)
+ a[i] = &baz (i);
+ for (int i = 0; i < 5; ++i)
+ for (int j = i + 1; j < 5; ++j)
+ if (a[i] == a[j] && (j != i + 1 || i != 3))
+ abort ();
+ if (a[1] != a[0] + 1 || a[2] != a[0] + 2 || a[4] != a[3])
+ abort ();
+ int b[] = { 4, 5, 6, 45, 45 + 6 };
+ for (int i = 0; i < 5; ++i)
+ for (int j = 0; j < 3 + i; ++j)
+ if (qux (i) != b[i] + 1 + j)
+ abort ();
+}
diff --git a/gcc/testsuite/g++.dg/cpp2a/decomp3.C b/gcc/testsuite/g++.dg/cpp2a/decomp3.C
new file mode 100644
index 0000000..5e77973
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/decomp3.C
@@ -0,0 +1,26 @@
+// P1381R1
+// { dg-do compile { target c++11 } }
+// { dg-options "" }
+
+struct Foo { int a : 1; int b; };
+
+int main() {
+ auto[a, b] = Foo(); // { dg-warning "structured bindings only available with" "" { target c++14_down } }
+
+ auto f1 = [&] { return a; }; // { dg-error "cannot bind bit-field" }
+ auto f2 = [&a = a] { return a; }; // { dg-error "cannot bind bit-field" }
+ // { dg-warning "lambda capture initializers only available with" "" { target c++11_only } .-1 }
+ auto f3 = [&a] { return a; }; // { dg-error "cannot bind bit-field" }
+
+ auto g1 = [&] { return b; };
+ auto g2 = [&b = b] { return b; }; // { dg-warning "lambda capture initializers only available with" "" { target c++11_only } }
+ auto g3 = [&b] { return b; };
+
+ auto h1 = [=] { return a; };
+ auto h2 = [a = a] { return a; }; // { dg-warning "lambda capture initializers only available with" "" { target c++11_only } }
+ auto h3 = [a] { return a; };
+
+ auto i1 = [=] { return b; };
+ auto i2 = [b = b] { return b; }; // { dg-warning "lambda capture initializers only available with" "" { target c++11_only } }
+ auto i3 = [b] { return b; };
+}
diff --git a/gcc/testsuite/g++.dg/cpp2a/feat-cxx2a.C b/gcc/testsuite/g++.dg/cpp2a/feat-cxx2a.C
index 8ee7b82..086109a 100644
--- a/gcc/testsuite/g++.dg/cpp2a/feat-cxx2a.C
+++ b/gcc/testsuite/g++.dg/cpp2a/feat-cxx2a.C
@@ -291,12 +291,12 @@
#if __has_include(<array>)
# define STD_ARRAY 1
# include <array>
- template<typename _Tp, size_t _Num>
+ template<typename _Tp, std::size_t _Num>
using array = std::array<_Tp, _Num>;
#elif __has_include(<tr1/array>)
# define TR1_ARRAY 1
# include <tr1/array>
- template<typename _Tp, size_t _Num>
+ template<typename _Tp, std::size_t _Num>
typedef std::tr1::array<_Tp, _Num> array;
#endif
diff --git a/gcc/testsuite/g++.dg/cpp2a/is-constant-evaluated8.C b/gcc/testsuite/g++.dg/cpp2a/is-constant-evaluated8.C
new file mode 100644
index 0000000..040252c
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/is-constant-evaluated8.C
@@ -0,0 +1,19 @@
+// { dg-do compile { target c++11 } }
+// { dg-options "" }
+
+namespace std {
+ constexpr inline bool
+ is_constant_evaluated () noexcept
+ {
+ return __builtin_is_constant_evaluated ();
+ }
+}
+
+struct A { explicit (!__builtin_is_constant_evaluated ()) A (int); }; // { dg-warning "'explicit\\(bool\\)' only available with" "" { target c++17_down } }
+struct B { explicit (!std::is_constant_evaluated ()) B (int); }; // { dg-warning "'explicit\\(bool\\)' only available with" "" { target c++17_down } }
+struct C { explicit (__builtin_is_constant_evaluated ()) C (int); }; // { dg-warning "'explicit\\(bool\\)' only available with" "" { target c++17_down } }
+struct D { explicit (std::is_constant_evaluated ()) D (int); }; // { dg-warning "'explicit\\(bool\\)' only available with" "" { target c++17_down } }
+A a = 1;
+B b = 2;
+C c = 3; // { dg-error "conversion from 'int' to non-scalar type 'C' requested" }
+D d = 4; // { dg-error "conversion from 'int' to non-scalar type 'D' requested" }
diff --git a/gcc/testsuite/g++.dg/cpp2a/multiple-deleted-destroying-delete-error-1.C b/gcc/testsuite/g++.dg/cpp2a/multiple-deleted-destroying-delete-error-1.C
new file mode 100644
index 0000000..01e4142
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/multiple-deleted-destroying-delete-error-1.C
@@ -0,0 +1,12 @@
+// { dg-do compile { target c++2a } }
+
+#include <new>
+
+namespace delete_selection_d {
+ struct B {
+ void operator delete(void*) = delete;
+ void operator delete(B *, std::destroying_delete_t) = delete;
+ };
+ void delete_B(B *b) { delete b; } // { dg-bogus "deleted .* deleted" }
+ // { dg-error "deleted" "" { target c++2a } .-1 }
+}
diff --git a/gcc/testsuite/g++.dg/cpp2a/multiple-deleted-destroying-delete-error-2.C b/gcc/testsuite/g++.dg/cpp2a/multiple-deleted-destroying-delete-error-2.C
new file mode 100644
index 0000000..314e2e9
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/multiple-deleted-destroying-delete-error-2.C
@@ -0,0 +1,12 @@
+// { dg-do compile { target c++2a } }
+
+#include <new>
+
+namespace delete_selection_r {
+ struct B {
+ void operator delete(B *, std::destroying_delete_t) = delete;
+ void operator delete(void*) = delete;
+ };
+ void delete_B(B *b) { delete b; } // { dg-bogus "deleted .* deleted" }
+ // { dg-error "deleted" "" { target c++2a } .-1 }
+}
diff --git a/gcc/testsuite/g++.dg/cpp2a/nontype-class17.C b/gcc/testsuite/g++.dg/cpp2a/nontype-class17.C
new file mode 100644
index 0000000..ca5f68e
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/nontype-class17.C
@@ -0,0 +1,17 @@
+// { dg-do compile { target c++2a } }
+
+template<auto>
+struct S { };
+
+struct R { };
+
+void
+g (void)
+{
+ S<R()> s; // { dg-error "mismatch" }
+// { dg-message "treated as function" "note" { target *-*-* } .-1 }
+ S<R{}> s2;
+ S<int()> s3; // { dg-error "mismatch" }
+// { dg-message "treated as function" "note" { target *-*-* } .-1 }
+ S<int{}> s4;
+}
diff --git a/gcc/testsuite/g++.dg/cpp2a/typename16.C b/gcc/testsuite/g++.dg/cpp2a/typename16.C
new file mode 100644
index 0000000..7f4242a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/typename16.C
@@ -0,0 +1,11 @@
+// PR c++/90572
+// { dg-do compile { target c++2a } }
+
+struct X { X(int); };
+
+template<typename T> struct S {
+ friend X::X(T::t);
+};
+
+struct W { using t = int; };
+S<W> s;
diff --git a/gcc/testsuite/g++.dg/debug/dwarf2/fesd-any.C b/gcc/testsuite/g++.dg/debug/dwarf2/fesd-any.C
index a4a0b50..5868ebc 100644
--- a/gcc/testsuite/g++.dg/debug/dwarf2/fesd-any.C
+++ b/gcc/testsuite/g++.dg/debug/dwarf2/fesd-any.C
@@ -1,5 +1,5 @@
// { dg-do compile }
-// { dg-options "-gdwarf-2 -dA -femit-struct-debug-detailed=any" }
+// { dg-options "-gdwarf-2 -dA -femit-struct-debug-detailed=any -fno-eliminate-unused-debug-symbols" }
// { dg-final { scan-assembler "timespec.*DW_AT_name" } }
// { dg-final { scan-assembler "tv_sec.*DW_AT_name" } }
// { dg-final { scan-assembler "tv_nsec.*DW_AT_name" } }
diff --git a/gcc/testsuite/g++.dg/debug/dwarf2/fesd-baseonly.C b/gcc/testsuite/g++.dg/debug/dwarf2/fesd-baseonly.C
index 4f580eb..fe0016a 100644
--- a/gcc/testsuite/g++.dg/debug/dwarf2/fesd-baseonly.C
+++ b/gcc/testsuite/g++.dg/debug/dwarf2/fesd-baseonly.C
@@ -1,5 +1,5 @@
// { dg-do compile }
-// { dg-options "-gdwarf-2 -dA -femit-struct-debug-baseonly" }
+// { dg-options "-gdwarf-2 -dA -femit-struct-debug-baseonly -fno-eliminate-unused-debug-symbols" }
// { dg-final { scan-assembler "timespec.*DW_AT_name" } }
// { dg-final { scan-assembler-not "tv_sec.*DW_AT_name" } }
// { dg-final { scan-assembler-not "tv_nsec.*DW_AT_name" } }
diff --git a/gcc/testsuite/g++.dg/debug/dwarf2/fesd-none.C b/gcc/testsuite/g++.dg/debug/dwarf2/fesd-none.C
index 0af0a83..c5a3396 100644
--- a/gcc/testsuite/g++.dg/debug/dwarf2/fesd-none.C
+++ b/gcc/testsuite/g++.dg/debug/dwarf2/fesd-none.C
@@ -1,5 +1,5 @@
// { dg-do compile }
-// { dg-options "-gdwarf-2 -dA -femit-struct-debug-detailed=none" }
+// { dg-options "-gdwarf-2 -dA -femit-struct-debug-detailed=none -fno-eliminate-unused-debug-symbols" }
// { dg-final { scan-assembler "timespec.*DW_AT_name" } }
// { dg-final { scan-assembler-not "tv_sec.*DW_AT_name" } }
// { dg-final { scan-assembler-not "tv_nsec.*DW_AT_name" } }
diff --git a/gcc/testsuite/g++.dg/debug/dwarf2/fesd-reduced.C b/gcc/testsuite/g++.dg/debug/dwarf2/fesd-reduced.C
index a93b90f..ba40f17 100644
--- a/gcc/testsuite/g++.dg/debug/dwarf2/fesd-reduced.C
+++ b/gcc/testsuite/g++.dg/debug/dwarf2/fesd-reduced.C
@@ -1,5 +1,5 @@
// { dg-do compile }
-// { dg-options "-gdwarf-2 -dA -femit-struct-debug-reduced" }
+// { dg-options "-gdwarf-2 -dA -femit-struct-debug-reduced -fno-eliminate-unused-debug-symbols" }
// { dg-final { scan-assembler "timespec.*DW_AT_name" } }
// { dg-final { scan-assembler "tv_sec.*DW_AT_name" } }
// { dg-final { scan-assembler "tv_nsec.*DW_AT_name" } }
diff --git a/gcc/testsuite/g++.dg/debug/dwarf2/fesd-sys.C b/gcc/testsuite/g++.dg/debug/dwarf2/fesd-sys.C
index 95a9a31..86eeb21 100644
--- a/gcc/testsuite/g++.dg/debug/dwarf2/fesd-sys.C
+++ b/gcc/testsuite/g++.dg/debug/dwarf2/fesd-sys.C
@@ -1,5 +1,5 @@
// { dg-do compile }
-// { dg-options "-gdwarf-2 -dA -femit-struct-debug-detailed=sys" }
+// { dg-options "-gdwarf-2 -dA -femit-struct-debug-detailed=sys -fno-eliminate-unused-debug-symbols" }
// { dg-final { scan-assembler "timespec.*DW_AT_name" } }
// { dg-final { scan-assembler "tv_sec.*DW_AT_name" } }
// { dg-final { scan-assembler "tv_nsec.*DW_AT_name" } }
diff --git a/gcc/testsuite/g++.dg/debug/dwarf2/inline-var-1.C b/gcc/testsuite/g++.dg/debug/dwarf2/inline-var-1.C
index fc3e6fd..3b1c913 100644
--- a/gcc/testsuite/g++.dg/debug/dwarf2/inline-var-1.C
+++ b/gcc/testsuite/g++.dg/debug/dwarf2/inline-var-1.C
@@ -1,5 +1,5 @@
// { dg-do compile { target c++17 } }
-// { dg-options "-O -g -dA -gno-strict-dwarf" }
+// { dg-options "-O -g -dA -gno-strict-dwarf -fno-eliminate-unused-debug-symbols" }
// { dg-require-weak "" }
// { dg-final { scan-assembler-times "0x3\[^\n\r]* DW_AT_inline" 6 { xfail *-*-aix* } } }
// { dg-final { scan-assembler-times "0x1\[^\n\r]* DW_AT_inline" 2 { xfail *-*-aix* } } }
diff --git a/gcc/testsuite/g++.dg/debug/enum-1.C b/gcc/testsuite/g++.dg/debug/enum-1.C
index 7681e9b..32124c1 100644
--- a/gcc/testsuite/g++.dg/debug/enum-1.C
+++ b/gcc/testsuite/g++.dg/debug/enum-1.C
@@ -1,5 +1,6 @@
/* Verify that used enums are output. */
/* { dg-do compile } */
+/* { dg-additional-options "-fno-eliminate-unused-debug-symbols" { target powerpc-ibm-aix* } } */
/* { dg-final { scan-assembler "JTI_MAX" } } */
int var;
diff --git a/gcc/testsuite/g++.dg/debug/enum-2.C b/gcc/testsuite/g++.dg/debug/enum-2.C
index d550131..554de37 100644
--- a/gcc/testsuite/g++.dg/debug/enum-2.C
+++ b/gcc/testsuite/g++.dg/debug/enum-2.C
@@ -1,5 +1,6 @@
/* Verify that used enums are output. */
/* { dg-do compile } */
+/* { dg-options "-fno-eliminate-unused-debug-symbols" } */
/* { dg-final { scan-assembler "JTI_MAX" } } */
int var;
diff --git a/gcc/testsuite/g++.dg/debug/pr90914.C b/gcc/testsuite/g++.dg/debug/pr90914.C
new file mode 100644
index 0000000..3681d58
--- /dev/null
+++ b/gcc/testsuite/g++.dg/debug/pr90914.C
@@ -0,0 +1,8 @@
+// { dg-do compile }
+// { dg-additional-options "-feliminate-unused-debug-symbols" }
+
+template <class> class A;
+void f ()
+{
+ extern A <double> b;
+}
diff --git a/gcc/testsuite/g++.dg/diagnostic/auto-storage-1.C b/gcc/testsuite/g++.dg/diagnostic/auto-storage-1.C
new file mode 100644
index 0000000..6137825
--- /dev/null
+++ b/gcc/testsuite/g++.dg/diagnostic/auto-storage-1.C
@@ -0,0 +1,6 @@
+// { dg-do compile { target c++98_only } }
+
+void foo()
+{
+ auto void bar(); // { dg-error "3:storage class .auto. invalid for function" }
+}
diff --git a/gcc/testsuite/g++.dg/diagnostic/conflicting-specifiers-1.C b/gcc/testsuite/g++.dg/diagnostic/conflicting-specifiers-1.C
new file mode 100644
index 0000000..1a8ac02b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/diagnostic/conflicting-specifiers-1.C
@@ -0,0 +1 @@
+static typedef int i __attribute__((unused)); // { dg-error "1:conflicting specifiers" }
diff --git a/gcc/testsuite/g++.dg/diagnostic/friend2.C b/gcc/testsuite/g++.dg/diagnostic/friend2.C
new file mode 100644
index 0000000..4f4ada8
--- /dev/null
+++ b/gcc/testsuite/g++.dg/diagnostic/friend2.C
@@ -0,0 +1,10 @@
+// PR c++/61490
+// { dg-do compile }
+
+namespace N { void f (); }
+void f2 ();
+
+struct A {
+ friend void N::f () { } // { dg-error "15:friend function definition 'f' cannot have a name qualified with 'N::'" }
+ friend void ::f2 () { } // { dg-error "15:friend function definition 'f2' cannot have a name qualified with '::'" }
+};
diff --git a/gcc/testsuite/g++.dg/diagnostic/friend3.C b/gcc/testsuite/g++.dg/diagnostic/friend3.C
new file mode 100644
index 0000000..574d7ca
--- /dev/null
+++ b/gcc/testsuite/g++.dg/diagnostic/friend3.C
@@ -0,0 +1,9 @@
+// { dg-do compile }
+
+void
+fn ()
+{
+ struct S {
+ friend void bar () { } // { dg-error "17:cannot define friend function 'bar' in a local class definition" }
+ };
+}
diff --git a/gcc/testsuite/g++.dg/diagnostic/main1.C b/gcc/testsuite/g++.dg/diagnostic/main1.C
new file mode 100644
index 0000000..6bb0d78
--- /dev/null
+++ b/gcc/testsuite/g++.dg/diagnostic/main1.C
@@ -0,0 +1 @@
+int main __attribute__((unused)); // { dg-error "5:cannot declare" }
diff --git a/gcc/testsuite/g++.dg/diagnostic/no-type-1.C b/gcc/testsuite/g++.dg/diagnostic/no-type-1.C
new file mode 100644
index 0000000..8c892e5
--- /dev/null
+++ b/gcc/testsuite/g++.dg/diagnostic/no-type-1.C
@@ -0,0 +1 @@
+main() {} // { dg-error "1:ISO C\\+\\+ forbids declaration" }
diff --git a/gcc/testsuite/g++.dg/diagnostic/no-type-2.C b/gcc/testsuite/g++.dg/diagnostic/no-type-2.C
new file mode 100644
index 0000000..8a7c627
--- /dev/null
+++ b/gcc/testsuite/g++.dg/diagnostic/no-type-2.C
@@ -0,0 +1,3 @@
+// { dg-options "-w" }
+
+foo() {} // { dg-error "1:ISO C\\+\\+ forbids declaration" }
diff --git a/gcc/testsuite/g++.dg/diagnostic/return-type-invalid-1.C b/gcc/testsuite/g++.dg/diagnostic/return-type-invalid-1.C
new file mode 100644
index 0000000..56be512
--- /dev/null
+++ b/gcc/testsuite/g++.dg/diagnostic/return-type-invalid-1.C
@@ -0,0 +1,27 @@
+struct S1
+{
+ int S1(); // { dg-error "3:return type" }
+ int ~S1(); // { dg-error "3:return type" }
+ int operator int(); // { dg-error "3:return type" }
+};
+
+struct S2
+{
+ const int S2(); // { dg-error "3:return type" }
+ const int ~S2(); // { dg-error "3:return type" }
+ const int operator int(); // { dg-error "3:return type" }
+};
+
+struct S3
+{
+ volatile int S3(); // { dg-error "3:return type" }
+ volatile int ~S3(); // { dg-error "3:return type" }
+ volatile int operator int(); // { dg-error "3:return type" }
+};
+
+struct S4
+{
+ const volatile int S4(); // { dg-error "3:return type" }
+ const volatile int ~S4(); // { dg-error "3:return type" }
+ const volatile int operator int(); // { dg-error "3:return type" }
+};
diff --git a/gcc/testsuite/g++.dg/diagnostic/top-level-auto-1.C b/gcc/testsuite/g++.dg/diagnostic/top-level-auto-1.C
new file mode 100644
index 0000000..b9f74f7
--- /dev/null
+++ b/gcc/testsuite/g++.dg/diagnostic/top-level-auto-1.C
@@ -0,0 +1,3 @@
+// { dg-do compile { target c++98_only } }
+
+auto int i; // { dg-error "1:top-level declaration of .i. specifies .auto." }
diff --git a/gcc/testsuite/g++.dg/diagnostic/trailing1.C b/gcc/testsuite/g++.dg/diagnostic/trailing1.C
new file mode 100644
index 0000000..369781e
--- /dev/null
+++ b/gcc/testsuite/g++.dg/diagnostic/trailing1.C
@@ -0,0 +1,5 @@
+// { dg-do compile { target c++11 } }
+
+int const foo1() -> double; // { dg-error "1:.foo1. function with trailing return type" }
+int volatile foo2() -> double; // { dg-error "1:.foo2. function with trailing return type" }
+int const volatile foo3() -> double; // { dg-error "1:.foo3. function with trailing return type" }
diff --git a/gcc/testsuite/g++.dg/diagnostic/two-or-more-data-types-1.C b/gcc/testsuite/g++.dg/diagnostic/two-or-more-data-types-1.C
new file mode 100644
index 0000000..4323a36
--- /dev/null
+++ b/gcc/testsuite/g++.dg/diagnostic/two-or-more-data-types-1.C
@@ -0,0 +1 @@
+char int i __attribute__((unused)); // { dg-error "1:two or more data types" }
diff --git a/gcc/testsuite/g++.dg/diagnostic/variably-modified-type-1.C b/gcc/testsuite/g++.dg/diagnostic/variably-modified-type-1.C
new file mode 100644
index 0000000..4402d12
--- /dev/null
+++ b/gcc/testsuite/g++.dg/diagnostic/variably-modified-type-1.C
@@ -0,0 +1,12 @@
+// { dg-options "" }
+
+void foo ()
+{
+ int n;
+ typedef int X[n];
+ struct Z
+ {
+ X x __attribute__((unused)); // { dg-error "7:data member may not have variably modified type" }
+ void bar (X x __attribute__((unused))); // { dg-error "17:parameter may not have variably modified type" }
+ };
+}
diff --git a/gcc/testsuite/g++.dg/eh/goto2.C b/gcc/testsuite/g++.dg/eh/goto2.C
index 1cd254c..7f22f50 100644
--- a/gcc/testsuite/g++.dg/eh/goto2.C
+++ b/gcc/testsuite/g++.dg/eh/goto2.C
@@ -8,6 +8,6 @@ try
} catch (...)
{
l2: ; // { dg-error "jump to label 'l2'" }
- // { dg-message "enters catch block" "" { target *-*-*} .-1 }
- goto l1; // { dg-message "from here|enters try block" }
+ // { dg-message "enters 'catch' block" "" { target *-*-*} .-1 }
+ goto l1; // { dg-message "from here|enters 'try' block" }
}
diff --git a/gcc/testsuite/g++.dg/eh/goto3.C b/gcc/testsuite/g++.dg/eh/goto3.C
index 250324e..415782c 100644
--- a/gcc/testsuite/g++.dg/eh/goto3.C
+++ b/gcc/testsuite/g++.dg/eh/goto3.C
@@ -9,6 +9,6 @@ try
} catch (...)
{
l2: ; // { dg-error "jump to label 'l2'" }
- // { dg-message "enters catch block" "" { target *-*-*} .-1 }
- goto l1; // { dg-message "from here|enters try block" }
+ // { dg-message "enters 'catch' block" "" { target *-*-*} .-1 }
+ goto l1; // { dg-message "from here|enters 'try' block" }
}
diff --git a/gcc/testsuite/g++.dg/eh/o32-fp.C b/gcc/testsuite/g++.dg/eh/o32-fp.C
new file mode 100644
index 0000000..08fa51b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/eh/o32-fp.C
@@ -0,0 +1,47 @@
+// Test whether call saved float are restored properly for O32 ABI
+// { dg-do run { target { { { mips*-*-linux* } && hard_float } && { ! mips64 } } } }
+// { dg-options "-O2" }
+
+void __attribute__((noinline))
+bar (void)
+{
+ throw 1;
+}
+
+void __attribute__((noinline))
+foo (void)
+{
+ register double f20 __asm__ ("f20") = 0.0;
+ register double f22 __asm__ ("f22") = 0.0;
+ register double f24 __asm__ ("f24") = 0.0;
+ register double f26 __asm__ ("f26") = 0.0;
+ register double f28 __asm__ ("f28") = 0.0;
+ register double f30 __asm__ ("f30") = 0.0;
+ __asm__ __volatile__("":"+f"(f20),"+f"(f22),"+f"(f24),"+f"(f26),"+f"(f30));
+ bar ();
+}
+
+int
+main (void)
+{
+ register double f20 __asm__ ("f20") = 12.0;
+ register double f22 __asm__ ("f22") = 13.0;
+ register double f24 __asm__ ("f24") = 14.0;
+ register double f26 __asm__ ("f26") = 15.0;
+ register double f28 __asm__ ("f28") = 16.0;
+ register double f30 __asm__ ("f30") = 17.0;
+
+ try
+ {
+ foo ();
+ }
+ catch (...)
+ {
+ __asm__ ("":"+f"(f20),"+f"(f22),"+f"(f24),"+f"(f26),"+f"(f30));
+ }
+
+ if (f20 != 12.0 || f22 != 13.0 || f24 != 14.0
+ || f26 != 15.0 || f28 != 16.0 || f30 != 17.0)
+ __builtin_abort ();
+ return 0;
+}
diff --git a/gcc/testsuite/g++.dg/eh/shadow1.C b/gcc/testsuite/g++.dg/eh/shadow1.C
index 0ba6145..6bccc70 100644
--- a/gcc/testsuite/g++.dg/eh/shadow1.C
+++ b/gcc/testsuite/g++.dg/eh/shadow1.C
@@ -18,7 +18,7 @@ struct D : private B
// { dg-warning "deprecated" "" { target { c++11 && { ! c++17 } } } .-2 }
struct E : public D
{
- virtual void V () throw (D); // { dg-error "looser throw" "" { target { ! c++17 } } }
+ virtual void V () throw (D); // { dg-error "looser exception" "" { target { ! c++17 } } }
}; // { dg-error "dynamic exception specification" "" { target c++17 } .-1 }
// { dg-warning "deprecated" "" { target { c++11 && { ! c++17 } } } .-2 }
B* foo (D *);
diff --git a/gcc/testsuite/g++.dg/expr/static_cast8.C b/gcc/testsuite/g++.dg/expr/static_cast8.C
index dc4d216..6dd7560 100644
--- a/gcc/testsuite/g++.dg/expr/static_cast8.C
+++ b/gcc/testsuite/g++.dg/expr/static_cast8.C
@@ -9,9 +9,9 @@ extern C* c;
void pointers(C* c, A2* a2, B1* b1)
{
- (void) static_cast<A1*>(c); // { dg-error "invalid static_cast" }
- (void) static_cast<C*>(a2); // { dg-error "invalid static_cast" }
- (void) static_cast<B2*>(b1); // { dg-error "invalid static_cast" }
+ (void) static_cast<A1*>(c); // { dg-error "invalid 'static_cast'" }
+ (void) static_cast<C*>(a2); // { dg-error "invalid 'static_cast'" }
+ (void) static_cast<B2*>(b1); // { dg-error "invalid 'static_cast'" }
}
struct D1; // { dg-message "note: class type 'D1' is incomplete" }
@@ -21,7 +21,7 @@ struct E2; // { dg-message "note: class type 'E2' is incomplete" }
void references(C& c, D2& d2, E1& e1)
{
- (void) static_cast<D1&>(c); // { dg-error "invalid static_cast" }
- (void) static_cast<C&>(d2); // { dg-error "invalid static_cast" }
- (void) static_cast<E2&>(e1); // { dg-error "invalid static_cast" }
+ (void) static_cast<D1&>(c); // { dg-error "invalid 'static_cast'" }
+ (void) static_cast<C&>(d2); // { dg-error "invalid 'static_cast'" }
+ (void) static_cast<E2&>(e1); // { dg-error "invalid 'static_cast'" }
}
diff --git a/gcc/testsuite/g++.dg/ext/90532.C b/gcc/testsuite/g++.dg/ext/90532.C
new file mode 100644
index 0000000..acdc4e2
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/90532.C
@@ -0,0 +1,27 @@
+// { dg-do compile { target c++11 } }
+// PR c++/90532
+static_assert( !__is_constructible(int[]), "" );
+static_assert( !__is_constructible(int[], int), "" );
+static_assert( !__is_constructible(int[], int[]), "" );
+static_assert( !__is_trivially_constructible(int[]), "" );
+static_assert( !__is_trivially_constructible(int[], int), "" );
+static_assert( !__is_trivially_constructible(int[], int[]), "" );
+static_assert( !__is_trivially_constructible(int[], int(&)[]), "" );
+static_assert( !__is_trivially_constructible(int[], void), "" );
+struct A { };
+static_assert( !__is_constructible(A[]), "" );
+static_assert( !__is_constructible(A[], const A&), "" );
+static_assert( !__is_constructible(A[], const A[]), "" );
+static_assert( !__is_trivially_constructible(A[]), "" );
+static_assert( !__is_trivially_constructible(A[], const A&), "" );
+static_assert( !__is_trivially_constructible(A[], const A[]), "" );
+static_assert( !__is_trivially_constructible(A[], A(&)[]), "" );
+static_assert( !__is_trivially_constructible(A[], void), "" );
+struct B { B(); };
+static_assert( !__is_constructible(B[]), "" );
+static_assert( !__is_constructible(B[], const B&), "" );
+static_assert( !__is_trivially_constructible(B[]), "" );
+static_assert( !__is_trivially_constructible(B[], const B&), "" );
+static_assert( !__is_trivially_constructible(B[], const B[]), "" );
+static_assert( !__is_trivially_constructible(B[], B(&)[]), "" );
+static_assert( !__is_trivially_constructible(B[], void), "" );
diff --git a/gcc/testsuite/g++.dg/ext/alignof2.C b/gcc/testsuite/g++.dg/ext/alignof2.C
index 2217590..bd56cf6 100644
--- a/gcc/testsuite/g++.dg/ext/alignof2.C
+++ b/gcc/testsuite/g++.dg/ext/alignof2.C
@@ -3,7 +3,7 @@
// wrong for some fields.
// { dg-do run }
-// { dg-xfail-run-if "AIX ABI increases struct alignment for first member double" { powerpc-ibm-aix* } }
+// { dg-xfail-run-if "AIX/Darwin ABI increases struct alignment for first member double" { powerpc-ibm-aix* || { ilp32 && powerpc-*-darwin* } } }
extern "C" void abort();
diff --git a/gcc/testsuite/g++.dg/ext/altivec-15.C b/gcc/testsuite/g++.dg/ext/altivec-15.C
index d8e982d..662d678 100644
--- a/gcc/testsuite/g++.dg/ext/altivec-15.C
+++ b/gcc/testsuite/g++.dg/ext/altivec-15.C
@@ -5,7 +5,7 @@
/* This test was added for an internal compiler error. The number and
content of error messages is irrelevant. */
-struct SubData
+struct SubData // { dg-error "" }
{
inline const Float Clamp(Float f, Float f0, Float f1) // { dg-error "" }
}
diff --git a/gcc/testsuite/g++.dg/ext/constexpr-vla1.C b/gcc/testsuite/g++.dg/ext/constexpr-vla1.C
index aff1d21..6283272 100644
--- a/gcc/testsuite/g++.dg/ext/constexpr-vla1.C
+++ b/gcc/testsuite/g++.dg/ext/constexpr-vla1.C
@@ -21,10 +21,10 @@ fn_not_ok (int n)
int z = 0;
for (unsigned i = 0; i < sizeof (a); ++i)
- z += a[i];
+ z += a[i]; // { dg-error "array subscript" }
return z;
}
constexpr int n1 = fn_ok (3);
-constexpr int n2 = fn_not_ok (3); // { dg-error "array subscript|in .constexpr. expansion of " }
+constexpr int n2 = fn_not_ok (3); // { dg-message "in .constexpr. expansion of " }
diff --git a/gcc/testsuite/g++.dg/ext/flexary5.C b/gcc/testsuite/g++.dg/ext/flexary5.C
index d6d8e32..d5ec132 100644
--- a/gcc/testsuite/g++.dg/ext/flexary5.C
+++ b/gcc/testsuite/g++.dg/ext/flexary5.C
@@ -62,7 +62,7 @@ ASSERT_AT_END (D4, a);
// below is benign since GCC computes the expected value.
struct D5: E1, E2, NE { char a[]; };
-ASSERT_AT_END (D5, a); // { dg-warning "offsetof within non-standard-layout" }
+ASSERT_AT_END (D5, a); // { dg-warning "'offsetof' within non-standard-layout" }
struct A2x_1 {
size_t n;
@@ -166,29 +166,29 @@ struct A5x {
struct D22: A5x, E1, E2 { };
-ASSERT_AT_END (D22, a); // { dg-warning "offsetof within non-standard-layout" }
+ASSERT_AT_END (D22, a); // { dg-warning "'offsetof' within non-standard-layout" }
struct D23: E1, A5x, E2 { };
-ASSERT_AT_END (D23, a); // { dg-warning "offsetof within non-standard-layout" }
+ASSERT_AT_END (D23, a); // { dg-warning "'offsetof' within non-standard-layout" }
struct D24: E1, E2, A5x { };
-ASSERT_AT_END (D24, a); // { dg-warning "offsetof within non-standard-layout" }
+ASSERT_AT_END (D24, a); // { dg-warning "'offsetof' within non-standard-layout" }
struct DA5x: A5x { };
struct D25: DA5x, E1, E2 { };
-ASSERT_AT_END (D25, a); // { dg-warning "offsetof within non-standard-layout" }
+ASSERT_AT_END (D25, a); // { dg-warning "'offsetof' within non-standard-layout" }
struct D26: E1, DA5x, E2 { };
-ASSERT_AT_END (D26, a); // { dg-warning "offsetof within non-standard-layout" }
+ASSERT_AT_END (D26, a); // { dg-warning "'offsetof' within non-standard-layout" }
struct D27: E1, E2, DA5x { };
-ASSERT_AT_END (D27, a); // { dg-warning "offsetof within non-standard-layout" }
+ASSERT_AT_END (D27, a); // { dg-warning "'offsetof' within non-standard-layout" }
// Verfify that a flexible array member is diagnosed even when deep
// in the base class hierarchy.
diff --git a/gcc/testsuite/g++.dg/ext/goto1.C b/gcc/testsuite/g++.dg/ext/goto1.C
new file mode 100644
index 0000000..84bbfce
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/goto1.C
@@ -0,0 +1,9 @@
+// PR c++/79781
+// { dg-do compile { target int128 } }
+// { dg-options "" }
+
+void c() {
+ static __int128_t d = (long)&&a - (long)&&b;
+a:
+b:;
+}
diff --git a/gcc/testsuite/g++.dg/ext/is_final.C b/gcc/testsuite/g++.dg/ext/is_final.C
index b3875ad..20e5d62 100644
--- a/gcc/testsuite/g++.dg/ext/is_final.C
+++ b/gcc/testsuite/g++.dg/ext/is_final.C
@@ -43,3 +43,17 @@ static_assert( __is_final (Ff<int>), "Ff<int> is final" );
static_assert( __is_final (Ff<A>), "Ff<A> is final" );
static_assert( __is_final (Ff<Af>), "Ff<Af> is final" );
+// PR 85254
+
+template <class T> struct final_trait_wrap{ typedef T type; };
+
+template <class T> struct my_is_final
+{
+ static const bool value = __is_final(typename final_trait_wrap<T>::type);
+};
+
+struct final1 final {};
+template <typename T> struct final2 final {};
+
+static_assert( my_is_final<final1>::value, "final1 is final" );
+static_assert( my_is_final<final2<int>>::value, "final2<int> is final" );
diff --git a/gcc/testsuite/g++.dg/ext/is_trivially_constructible1.C b/gcc/testsuite/g++.dg/ext/is_trivially_constructible1.C
index 191b696..d28f2f7 100644
--- a/gcc/testsuite/g++.dg/ext/is_trivially_constructible1.C
+++ b/gcc/testsuite/g++.dg/ext/is_trivially_constructible1.C
@@ -48,7 +48,9 @@ SA(!__is_trivially_constructible(int*, const int*));
SA(!__is_trivially_constructible(D));
SA(__is_trivially_copyable(int));
-SA(!__is_trivially_copyable(volatile int));
+// Changed in CWG 2094, which made volatile-qualified scalars trivially
+// copyable.
+SA(__is_trivially_copyable(volatile int));
struct E1 {const int val;};
SA(__is_trivially_copyable(E1));
diff --git a/gcc/testsuite/g++.dg/ext/is_trivially_copyable.C b/gcc/testsuite/g++.dg/ext/is_trivially_copyable.C
new file mode 100644
index 0000000..6f93602
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/is_trivially_copyable.C
@@ -0,0 +1,16 @@
+// CWG 2094 - volatile scalars are trivially copyable.
+// PR c++/85679
+// { dg-do compile { target c++11 } }
+
+#define SA(X) static_assert((X),#X)
+
+struct S{};
+
+SA(__is_trivially_copyable(S volatile));
+SA(__is_trivially_copyable(S volatile[]));
+SA(__is_trivially_copyable(S const volatile));
+SA(__is_trivially_copyable(S const volatile[]));
+SA(__is_trivially_copyable(int volatile));
+SA(__is_trivially_copyable(int volatile[]));
+SA(__is_trivially_copyable(int const volatile));
+SA(__is_trivially_copyable(int const volatile[]));
diff --git a/gcc/testsuite/g++.dg/ext/utf-array-short-wchar.C b/gcc/testsuite/g++.dg/ext/utf-array-short-wchar.C
index f37f93c..8f0a732 100644
--- a/gcc/testsuite/g++.dg/ext/utf-array-short-wchar.C
+++ b/gcc/testsuite/g++.dg/ext/utf-array-short-wchar.C
@@ -21,9 +21,9 @@ const char16_t s16_2[] = U"ab"; /* { dg-error "from a string literal with type a
const char16_t s16_3[] = L"ab"; /* { dg-error "from a string literal with type array of .wchar_t." } */
const char16_t s16_4[] = u8"ab"; /* { dg-error "from a string literal with type array of .char." } */
-const char16_t s16_5[0] = u"ab"; /* { dg-error "chars is too long" } */
-const char16_t s16_6[1] = u"ab"; /* { dg-error "chars is too long" } */
-const char16_t s16_7[2] = u"ab"; /* { dg-error "chars is too long" } */
+const char16_t s16_5[0] = u"ab"; /* { dg-error "initializer-string for 'const char16_t \\\[0]' is too long" } */
+const char16_t s16_6[1] = u"ab"; /* { dg-error "initializer-string for 'const char16_t \\\[1]' is too long" } */
+const char16_t s16_7[2] = u"ab"; /* { dg-error "initializer-string for 'const char16_t \\\[2]' is too long" } */
const char16_t s16_8[3] = u"ab";
const char16_t s16_9[4] = u"ab";
@@ -33,9 +33,9 @@ const char32_t s32_2[] = U"ab";
const char32_t s32_3[] = L"ab"; /* { dg-error "from a string literal with type array of .wchar_t." } */
const char32_t s32_4[] = u8"ab"; /* { dg-error "from a string literal with type array of .char." } */
-const char32_t s32_5[0] = U"ab"; /* { dg-error "chars is too long" } */
-const char32_t s32_6[1] = U"ab"; /* { dg-error "chars is too long" } */
-const char32_t s32_7[2] = U"ab"; /* { dg-error "chars is too long" } */
+const char32_t s32_5[0] = U"ab"; /* { dg-error "initializer-string for 'const char32_t \\\[0]' is too long" } */
+const char32_t s32_6[1] = U"ab"; /* { dg-error "initializer-string for 'const char32_t \\\[1]' is too long" } */
+const char32_t s32_7[2] = U"ab"; /* { dg-error "initializer-string for 'const char32_t \\\[2]' is too long" } */
const char32_t s32_8[3] = U"ab";
const char32_t s32_9[4] = U"ab";
diff --git a/gcc/testsuite/g++.dg/ext/utf-array.C b/gcc/testsuite/g++.dg/ext/utf-array.C
index 0e403db..e539cd4 100644
--- a/gcc/testsuite/g++.dg/ext/utf-array.C
+++ b/gcc/testsuite/g++.dg/ext/utf-array.C
@@ -21,9 +21,9 @@ const char16_t s16_2[] = U"ab"; /* { dg-error "from a string literal with type a
const char16_t s16_3[] = L"ab"; /* { dg-error "from a string literal with type array of .wchar_t." } */
const char16_t s16_4[] = u8"ab"; /* { dg-error "from a string literal with type array of .char." } */
-const char16_t s16_5[0] = u"ab"; /* { dg-error "chars is too long" } */
-const char16_t s16_6[1] = u"ab"; /* { dg-error "chars is too long" } */
-const char16_t s16_7[2] = u"ab"; /* { dg-error "chars is too long" } */
+const char16_t s16_5[0] = u"ab"; /* { dg-error "initializer-string for 'const char16_t \\\[0]' is too long" } */
+const char16_t s16_6[1] = u"ab"; /* { dg-error "initializer-string for 'const char16_t \\\[1]' is too long" } */
+const char16_t s16_7[2] = u"ab"; /* { dg-error "initializer-string for 'const char16_t \\\[2]' is too long" } */
const char16_t s16_8[3] = u"ab";
const char16_t s16_9[4] = u"ab";
@@ -33,9 +33,9 @@ const char32_t s32_2[] = U"ab";
const char32_t s32_3[] = L"ab"; /* { dg-error "from a string literal with type array of .wchar_t." } */
const char32_t s32_4[] = u8"ab"; /* { dg-error "from a string literal with type array of .char." } */
-const char32_t s32_5[0] = U"ab"; /* { dg-error "chars is too long" } */
-const char32_t s32_6[1] = U"ab"; /* { dg-error "chars is too long" } */
-const char32_t s32_7[2] = U"ab"; /* { dg-error "chars is too long" } */
+const char32_t s32_5[0] = U"ab"; /* { dg-error "initializer-string for 'const char32_t \\\[0]' is too long" } */
+const char32_t s32_6[1] = U"ab"; /* { dg-error "initializer-string for 'const char32_t \\\[1]' is too long" } */
+const char32_t s32_7[2] = U"ab"; /* { dg-error "initializer-string for 'const char32_t \\\[2]' is too long" } */
const char32_t s32_8[3] = U"ab";
const char32_t s32_9[4] = U"ab";
diff --git a/gcc/testsuite/g++.dg/ext/utf8-2.C b/gcc/testsuite/g++.dg/ext/utf8-2.C
index b13d55f..5ce13fb 100644
--- a/gcc/testsuite/g++.dg/ext/utf8-2.C
+++ b/gcc/testsuite/g++.dg/ext/utf8-2.C
@@ -12,16 +12,16 @@ const char16_t s1[] = u8"ab"; // { dg-error "from a string literal with type arr
const char32_t s2[] = u8"ab"; // { dg-error "from a string literal with type array of .char." }
const wchar_t s3[] = u8"ab"; // { dg-error "from a string literal with type array of .char." }
-const u8_char_t t0[0] = u8"ab"; // { dg-error "chars is too long" }
-const u8_char_t t1[1] = u8"ab"; // { dg-error "chars is too long" }
-const u8_char_t t2[2] = u8"ab"; // { dg-error "chars is too long" }
+const u8_char_t t0[0] = u8"ab"; // { dg-error "initializer-string for 'const u8_char_t \\\[0]' {aka 'const \(char|char8_t\) \\\[0]'} is too long" }
+const u8_char_t t1[1] = u8"ab"; // { dg-error "initializer-string for 'const u8_char_t \\\[1]' {aka 'const \(char|char8_t\) \\\[1]'} is too long" }
+const u8_char_t t2[2] = u8"ab"; // { dg-error "initializer-string for 'const u8_char_t \\\[2]' {aka 'const \(char|char8_t\) \\\[2]'} is too long" }
const u8_char_t t3[3] = u8"ab";
const u8_char_t t4[4] = u8"ab";
-const u8_char_t u0[0] = u8"\u2160."; // { dg-error "chars is too long" }
-const u8_char_t u1[1] = u8"\u2160."; // { dg-error "chars is too long" }
-const u8_char_t u2[2] = u8"\u2160."; // { dg-error "chars is too long" }
-const u8_char_t u3[3] = u8"\u2160."; // { dg-error "chars is too long" }
-const u8_char_t u4[4] = u8"\u2160."; // { dg-error "chars is too long" }
+const u8_char_t u0[0] = u8"\u2160."; // { dg-error "initializer-string for 'const u8_char_t \\\[0]' {aka 'const \(char|char8_t\) \\\[0]'} is too long" }
+const u8_char_t u1[1] = u8"\u2160."; // { dg-error "initializer-string for 'const u8_char_t \\\[1]' {aka 'const \(char|char8_t\) \\\[1]'} is too long" }
+const u8_char_t u2[2] = u8"\u2160."; // { dg-error "initializer-string for 'const u8_char_t \\\[2]' {aka 'const \(char|char8_t\) \\\[2]'} is too long" }
+const u8_char_t u3[3] = u8"\u2160."; // { dg-error "initializer-string for 'const u8_char_t \\\[3]' {aka 'const \(char|char8_t\) \\\[3]'} is too long" }
+const u8_char_t u4[4] = u8"\u2160."; // { dg-error "initializer-string for 'const u8_char_t \\\[4]' {aka 'const \(char|char8_t\) \\\[4]'} is too long" }
const u8_char_t u5[5] = u8"\u2160.";
const u8_char_t u6[6] = u8"\u2160.";
diff --git a/gcc/testsuite/g++.dg/ext/vector37.C b/gcc/testsuite/g++.dg/ext/vector37.C
new file mode 100644
index 0000000..a7baf8d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/vector37.C
@@ -0,0 +1,29 @@
+// PR c++/90810
+// { dg-do run }
+
+void
+foo (float x, float y)
+{
+ typedef float __attribute__ ((__vector_size__ (4 * sizeof (float)), __may_alias__)) V;
+ const V a = { x, x, x, x }, b = { y, y, y, y };
+ const V c = a / b;
+ if (c[0] != 6.0f || c[1] != 6.0f || c[2] != 6.0f || c[3] != 6.0f)
+ __builtin_abort ();
+}
+
+void
+bar (float y)
+{
+ typedef float __attribute__ ((__vector_size__ (4 * sizeof (float)), __may_alias__)) V;
+ const V a = { 7.0f, 8.0f, 9.0f, 10.0f }, b = { 1.0f, 2.0f, 3.0f, y };
+ const V c = a / b;
+ if (c[0] != 7.0f || c[1] != 4.0f || c[2] != 3.0f || c[3] != 5.0f)
+ __builtin_abort ();
+}
+
+int
+main ()
+{
+ foo (12.0f, 2.0f);
+ bar (2.0f);
+}
diff --git a/gcc/testsuite/g++.dg/ext/vector38.C b/gcc/testsuite/g++.dg/ext/vector38.C
new file mode 100644
index 0000000..51a0887
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/vector38.C
@@ -0,0 +1,5 @@
+// PR c++/90969
+// { dg-do compile }
+
+__attribute__ ((__vector_size__ (4))) int v;
+int &a = v[0];
diff --git a/gcc/testsuite/g++.dg/goacc/firstprivate-mappings-1.C b/gcc/testsuite/g++.dg/goacc/firstprivate-mappings-1.C
new file mode 100644
index 0000000..639bf3f
--- /dev/null
+++ b/gcc/testsuite/g++.dg/goacc/firstprivate-mappings-1.C
@@ -0,0 +1,529 @@
+/* Verify OpenACC 'firstprivate' mappings for C++ reference types. */
+
+/* This file is also sourced from
+ '../../../../libgomp/testsuite/libgomp.oacc-c++/firstprivate-mappings-1.C'
+ as an execution test. */
+
+/* See also '../../c-c++-common/goacc/firstprivate-mappings-1.c'. */
+
+/* { dg-additional-options "-fdump-tree-omplower" } */
+
+/* { dg-additional-options "-fext-numeric-literals" { target c++ } } */
+
+#include <stdbool.h>
+#include <stdint.h>
+#include <string.h>
+
+
+#ifdef __SIZEOF_INT128__
+# define HAVE_INT128 1
+#else
+# define HAVE_INT128 0
+#endif
+
+
+/* The one is only relevant for offloading compilation; will always be enabled
+ when doing tree scanning. */
+#ifdef ACC_DEVICE_TYPE_nvidia
+/* PR71064. */
+# define DO_LONG_DOUBLE 0
+#else
+# define DO_LONG_DOUBLE 1
+#endif
+
+
+/* Simplify scanning for function names in tree dumps. */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/* Inside the following OpenACC 'parallel' constructs' regions, we modify the
+ 'firstprivate' variables, so that we can check that we don't copy these
+ back. */
+
+
+static void
+p (short *&spi)
+{
+ short *spo;
+#pragma acc parallel \
+ copyout (spo) \
+ firstprivate (spi)
+ {
+ spo = ++spi;
+ }
+ if (spo != spi + 1)
+ __builtin_abort ();
+}
+
+
+static void
+b (bool &bi)
+{
+ bool bo;
+#pragma acc parallel \
+ copyout (bo) \
+ firstprivate (bi)
+ {
+ bo = (bi = !bi);
+ }
+ if (bo != !bi)
+ __builtin_abort ();
+}
+
+
+static void
+i (int8_t &i8i,
+ uint8_t &u8i,
+ int16_t &i16i,
+ uint16_t &u16i,
+ int32_t &i32i,
+ uint32_t &u32i,
+ int64_t &i64i,
+ uint64_t &u64i)
+{
+ int8_t i8o;
+ uint8_t u8o;
+ int16_t i16o;
+ uint16_t u16o;
+ int32_t i32o;
+ uint32_t u32o;
+ int64_t i64o;
+ uint64_t u64o;
+#pragma acc parallel \
+ copyout (i8o) \
+ firstprivate (i8i) \
+ copyout (u8o) \
+ firstprivate (u8i) \
+ copyout (i16o) \
+ firstprivate (i16i) \
+ copyout (u16o) \
+ firstprivate (u16i) \
+ copyout (i32o) \
+ firstprivate (i32i) \
+ copyout (u32o) \
+ firstprivate (u32i) \
+ copyout (i64o) \
+ firstprivate (i64i) \
+ copyout (u64o) \
+ firstprivate (u64i)
+ {
+ i8o = --i8i;
+ u8o = ++u8i;
+ i16o = --i16i;
+ u16o = ++u16i;
+ i32o = --i32i;
+ u32o = ++u32i;
+ i64o = --i64i;
+ u64o = ++u64i;
+ }
+ if (i8o != i8i - 1)
+ __builtin_abort ();
+ if (u8o != u8i + 1)
+ __builtin_abort ();
+ if (i16o != i16i - 1)
+ __builtin_abort ();
+ if (u16o != u16i + 1)
+ __builtin_abort ();
+ if (i32o != i32i - 1)
+ __builtin_abort ();
+ if (u32o != u32i + 1)
+ __builtin_abort ();
+ if (i64o != i64i - 1)
+ __builtin_abort ();
+ if (u64o != u64i + 1)
+ __builtin_abort ();
+}
+
+
+#if HAVE_INT128
+static void
+i128 (__int128 &i128i, unsigned __int128 &u128i)
+{
+ __int128 i128o;
+ unsigned __int128 u128o;
+# pragma acc parallel \
+ copyout (i128o) \
+ firstprivate (i128i) \
+ copyout(u128o) \
+ firstprivate (u128i)
+ {
+ i128o = --i128i;
+ u128o = ++u128i;
+ }
+ if (i128o != i128i - 1)
+ __builtin_abort ();
+ if (u128o != u128i + 1)
+ __builtin_abort ();
+}
+#endif
+
+
+static void
+flt_dbl (float &flti, double &dbli)
+{
+ float flto;
+ double dblo;
+#pragma acc parallel \
+ copyout (flto) \
+ firstprivate (flti) \
+ copyout (dblo) \
+ firstprivate (dbli)
+ {
+ flto = --flti;
+ dblo = --dbli;
+ }
+ if (flto != flti - 1)
+ __builtin_abort ();
+ if (dblo != dbli - 1)
+ __builtin_abort ();
+}
+
+
+static void
+ldbl (long double &ldbli)
+{
+#if DO_LONG_DOUBLE
+ long double ldblo;
+# pragma acc parallel \
+ copyout (ldblo) \
+ firstprivate (ldbli)
+ {
+ ldblo = --ldbli;
+ }
+ if (ldblo != ldbli - 1)
+ __builtin_abort ();
+#endif
+}
+
+
+static void
+c (_Complex unsigned char &cuci,
+ _Complex signed short &cssi,
+ _Complex unsigned int &cuii,
+ _Complex signed long &csli,
+ _Complex float &cflti,
+ _Complex double &cdbli)
+{
+ _Complex unsigned char cuco;
+ _Complex signed short csso;
+ _Complex unsigned int cuio;
+ _Complex signed long cslo;
+ _Complex float cflto;
+ _Complex double cdblo;
+#pragma acc parallel \
+ copyout (cuco) \
+ firstprivate (cuci) \
+ copyout (csso) \
+ firstprivate (cssi) \
+ copyout (cuio) \
+ firstprivate (cuii) \
+ copyout (cslo) \
+ firstprivate (csli) \
+ copyout (cflto) \
+ firstprivate (cflti) \
+ copyout (cdblo) \
+ firstprivate (cdbli)
+ {
+ cuco = (cuci += (1 + 1j));
+ csso = (cssi -= (1 + 1j));
+ cuio = (cuii += (1 + 1j));
+ cslo = (csli -= (1 + 1j));
+ cflto = (cflti -= (1 + 1j));
+ cdblo = (cdbli -= (1 + 1j));
+ }
+ if (cuco != cuci + (1 + 1j))
+ __builtin_abort ();
+ if (csso != cssi - (1 + 1j))
+ __builtin_abort ();
+ if (cuio != cuii + (1 + 1j))
+ __builtin_abort ();
+ if (cslo != csli - (1 + 1j))
+ __builtin_abort ();
+ if (cflto != cflti - (1 + 1j))
+ __builtin_abort ();
+ if (cdblo != cdbli - (1 + 1j))
+ __builtin_abort ();
+}
+
+
+static void
+cldbl (_Complex long double &cldbli)
+{
+#if DO_LONG_DOUBLE
+ _Complex long double cldblo;
+# pragma acc parallel \
+ copyout (cldblo) \
+ firstprivate (cldbli)
+ {
+ cldblo = (cldbli -= (1 + 1j));
+ }
+ if (cldblo != cldbli - (1 + 1j))
+ __builtin_abort ();
+#endif
+}
+
+
+#define V_EQ(v1, v2) \
+ ({ \
+ __typeof__ (v1) v_d = (v1) != (v2); \
+ __typeof__ (v_d) v_0 = { 0 }; \
+ memcmp (&v_d, &v_0, sizeof v_d) == 0; \
+ })
+
+typedef uint8_t __attribute__ ((vector_size (2 * sizeof (uint8_t)))) v2u8;
+typedef int16_t __attribute__ ((vector_size (4 * sizeof (int16_t)))) v4i16;
+typedef uint32_t __attribute__ ((vector_size (8 * sizeof (uint32_t)))) v8u32;
+typedef int64_t __attribute__ ((vector_size (16 * sizeof (int64_t)))) v16i64;
+typedef float __attribute__ ((vector_size (1 * sizeof (float)))) v1flt;
+typedef float __attribute__ ((vector_size (2 * sizeof (float)))) v2flt;
+typedef float __attribute__ ((vector_size (4 * sizeof (float)))) v4flt;
+typedef float __attribute__ ((vector_size (8 * sizeof (float)))) v8flt;
+typedef double __attribute__ ((vector_size (1 * sizeof (double)))) v1dbl;
+typedef double __attribute__ ((vector_size (2 * sizeof (double)))) v2dbl;
+typedef double __attribute__ ((vector_size (4 * sizeof (double)))) v4dbl;
+typedef double __attribute__ ((vector_size (8 * sizeof (double)))) v8dbl;
+
+static void
+v (v2u8 &v2u8i, v4i16 &v4i16i, v8u32 &v8u32i, v16i64 &v16i64i,
+ v1flt &v1flti, v2flt &v2flti, v4flt &v4flti, v8flt &v8flti,
+ v1dbl &v1dbli, v2dbl &v2dbli, v4dbl &v4dbli, v8dbl &v8dbli)
+{
+ v2u8 v2u8o;
+ v4i16 v4i16o;
+ v8u32 v8u32o;
+ v16i64 v16i64o;
+ v1flt v1flto;
+ v2flt v2flto;
+ v4flt v4flto;
+ v8flt v8flto;
+ v1dbl v1dblo;
+ v2dbl v2dblo;
+ v4dbl v4dblo;
+ v8dbl v8dblo;
+#pragma acc parallel \
+ copyout (v2u8o) \
+ firstprivate (v2u8i) \
+ copyout (v4i16o) \
+ firstprivate (v4i16i) \
+ copyout (v8u32o) \
+ firstprivate (v8u32i) \
+ copyout (v16i64o) \
+ firstprivate (v16i64i) \
+ copyout (v1flto) \
+ firstprivate (v1flti) \
+ copyout (v2flto) \
+ firstprivate (v2flti) \
+ copyout (v4flto) \
+ firstprivate (v4flti) \
+ copyout (v8flto) \
+ firstprivate (v8flti) \
+ copyout (v1dblo) \
+ firstprivate (v1dbli) \
+ copyout (v2dblo) \
+ firstprivate (v2dbli) \
+ copyout (v4dblo) \
+ firstprivate (v4dbli) \
+ copyout (v8dblo) \
+ firstprivate (v8dbli)
+ {
+ v2u8o = ++v2u8i;
+ v4i16o = --v4i16i;
+ v8u32o = ++v8u32i;
+ v16i64o = --v16i64i;
+ v1flto = --v1flti;
+ v2flto = --v2flti;
+ v4flto = --v4flti;
+ v8flto = --v8flti;
+ v1dblo = --v1dbli;
+ v2dblo = --v2dbli;
+ v4dblo = --v4dbli;
+ v8dblo = --v8dbli;
+ }
+ if (!V_EQ (v2u8o, v2u8i + 1))
+ __builtin_abort ();
+ if (!V_EQ (v4i16o, v4i16i - 1))
+ __builtin_abort ();
+ if (!V_EQ (v8u32o, v8u32i + 1))
+ __builtin_abort ();
+ if (!V_EQ (v16i64o, v16i64i - 1))
+ __builtin_abort ();
+ if (!V_EQ (v1flto, v1flti - 1))
+ __builtin_abort ();
+ if (!V_EQ (v2flto, v2flti - 1))
+ __builtin_abort ();
+ if (!V_EQ (v4flto, v4flti - 1))
+ __builtin_abort ();
+ if (!V_EQ (v8flto, v8flti - 1))
+ __builtin_abort ();
+ if (!V_EQ (v1dblo, v1dbli - 1))
+ __builtin_abort ();
+ if (!V_EQ (v2dblo, v2dbli - 1))
+ __builtin_abort ();
+ if (!V_EQ (v4dblo, v4dbli - 1))
+ __builtin_abort ();
+ if (!V_EQ (v8dblo, v8dbli - 1))
+ __builtin_abort ();
+}
+
+
+/* "error: could not find an integer type of the same size as 'long double'" */
+#if HAVE_INT128
+typedef long double __attribute__ ((vector_size (1 * sizeof (long double)))) v1ldbl;
+typedef long double __attribute__ ((vector_size (2 * sizeof (long double)))) v2ldbl;
+typedef long double __attribute__ ((vector_size (4 * sizeof (long double)))) v4ldbl;
+typedef long double __attribute__ ((vector_size (8 * sizeof (long double)))) v8ldbl;
+
+static void
+vldbl (v1ldbl &v1ldbli, v2ldbl &v2ldbli, v4ldbl &v4ldbli, v8ldbl &v8ldbli)
+{
+# if DO_LONG_DOUBLE
+ v1ldbl v1ldblo;
+ v2ldbl v2ldblo;
+ v4ldbl v4ldblo;
+ v8ldbl v8ldblo;
+# pragma acc parallel \
+ copyout (v1ldblo) \
+ firstprivate (v1ldbli) \
+ copyout (v2ldblo) \
+ firstprivate (v2ldbli) \
+ copyout (v4ldblo) \
+ firstprivate (v4ldbli) \
+ copyout (v8ldblo) \
+ firstprivate (v8ldbli)
+ {
+ v1ldblo = --v1ldbli;
+ v2ldblo = --v2ldbli;
+ v4ldblo = --v4ldbli;
+ v8ldblo = --v8ldbli;
+ }
+ if (!V_EQ (v1ldblo, v1ldbli - 1))
+ __builtin_abort ();
+ if (!V_EQ (v2ldblo, v2ldbli - 1))
+ __builtin_abort ();
+ if (!V_EQ (v4ldblo, v4ldbli - 1))
+ __builtin_abort ();
+ if (!V_EQ (v8ldblo, v8ldbli - 1))
+ __builtin_abort ();
+# endif
+}
+#endif
+
+
+static void
+vla (int &array_li)
+{
+ _Complex double array[array_li];
+ uint32_t array_so;
+#pragma acc parallel \
+ copyout (array_so)
+ /* The gimplifier has created an implicit 'firstprivate' clause for the array
+ length.
+ { dg-final { scan-tree-dump {(?n)#pragma omp target oacc_parallel map\(from:array_so \[len: 4\]\) firstprivate\(} omplower } }
+ (C++ computes an intermediate value, so can't scan for 'firstprivate(array_li)'.) */
+ {
+ array_so = sizeof array;
+ }
+ if (array_so != sizeof array)
+ __builtin_abort ();
+}
+
+
+#ifdef __cplusplus
+}
+#endif
+
+
+int
+main (int argc, char *argv[])
+{
+ {
+ short s;
+ short *sp = &s;
+ p (sp);
+ }
+
+ {
+ bool bi = true;
+ b (bi);
+ }
+
+ {
+ int8_t i8i = -1;
+ uint8_t u8i = 1;
+ int16_t i16i = -2;
+ uint16_t u16i = 2;
+ int32_t i32i = -3;
+ uint32_t u32i = 3;
+ int64_t i64i = -4;
+ uint64_t u64i = 4;
+ i (i8i, u8i, i16i, u16i, i32i, u32i, i64i, u64i);
+ }
+
+#if HAVE_INT128
+ {
+ __int128 i128i = -8;
+ unsigned __int128 u128i = 8;
+ i128 (i128i, u128i);
+ }
+#endif
+
+ {
+ float flti = .5;
+ double dbli = .25;
+ flt_dbl (flti, dbli);
+ }
+
+ {
+ long double ldbli = .125;
+ ldbl (ldbli);
+ }
+
+ {
+ _Complex unsigned char cuci = 1 + 2j;
+ _Complex signed short cssi = -2 + (-4j);
+ _Complex unsigned int cuii = 3 + 6j;
+ _Complex signed long csli = -4 + (-8j);
+ _Complex float cflti = .5 + 1j;
+ _Complex double cdbli = .25 + .5j;
+ c (cuci, cssi, cuii, csli, cflti, cdbli);
+ }
+
+ {
+ _Complex long double cldbli = .125 + .25j;
+ cldbl (cldbli);
+ }
+
+ {
+ v2u8 v2u8i = {2, 3};
+ v4i16 v4i16i = { -1, -2, 5, 4 };
+ v8u32 v8u32i = { 3, 6, 9, 11};
+ v16i64 v16i64i = { 10, 21, -25, 44, 31, -1, 1, 222, -1, -12, 52, -44, -13, 1, -1, -222};
+ v1flt v1flti = { -.5 };
+ v2flt v2flti = { 1.5, -2.5 };
+ v4flt v4flti = { 3.5, -4.5, -5.5, -6.5 };
+ v8flt v8flti = { -7.5, 8.5, 9.5, 10.5, -11.5, -12.5, 13.5, 14.5 };
+ v1dbl v1dbli = { 0.25 };
+ v2dbl v2dbli = { -1.25, -2.25 };
+ v4dbl v4dbli = { 3.25, -4.25, 5.25, 6.25 };
+ v8dbl v8dbli = { 7.25, 8.25, -9.25, -10.25, -11.25, 12.25, 13.25, -14.25 };
+ v (v2u8i, v4i16i, v8u32i, v16i64i,
+ v1flti, v2flti, v4flti, v8flti,
+ v1dbli, v2dbli, v4dbli, v8dbli);
+ }
+
+#if HAVE_INT128
+ {
+ v1ldbl v1ldbli = { -0.125 };
+ v2ldbl v2ldbli = { 1.125, -2.125 };
+ v4ldbl v4ldbli = { -3.125, -4.125, 5.125, -6.125 };
+ v8ldbl v8ldbli = { 7.125, -8.125, -9.125, 10.125, 11.125, 12.125, 13.125, 14.125 };
+ vldbl (v1ldbli, v2ldbli, v4ldbli, v8ldbli);
+ }
+#endif
+
+ vla (argc);
+
+ return 0;
+}
diff --git a/gcc/testsuite/g++.dg/gomp/lastprivate-1.C b/gcc/testsuite/g++.dg/gomp/lastprivate-1.C
new file mode 100644
index 0000000..ce25e1a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/gomp/lastprivate-1.C
@@ -0,0 +1,16 @@
+// PR c++/90950
+// { dg-do compile }
+
+template <typename T>
+T
+foo (void)
+{
+ T y = 0;
+ T &x = y;
+ #pragma omp parallel for lastprivate (x)
+ for (int i = 0; i < 8; ++i)
+ x = i;
+ return x;
+}
+
+int a = foo<int> ();
diff --git a/gcc/testsuite/g++.dg/gomp/loop-4.C b/gcc/testsuite/g++.dg/gomp/loop-4.C
index cd85dbd..c45d43e 100644
--- a/gcc/testsuite/g++.dg/gomp/loop-4.C
+++ b/gcc/testsuite/g++.dg/gomp/loop-4.C
@@ -81,28 +81,28 @@ f0 ()
for (i = 64; i != 0; i += k)
;
#pragma omp for
- for (i = 0; i != 64; i += m) // { dg-error "increment is not constant 1 or -1 for != condition" }
+ for (i = 0; i != 64; i += m) // { dg-error "increment is not constant 1 or -1 for '!=' condition" }
;
#pragma omp for
- for (i = 64; i != 0; i -= m) // { dg-error "increment is not constant 1 or -1 for != condition" }
+ for (i = 64; i != 0; i -= m) // { dg-error "increment is not constant 1 or -1 for '!=' condition" }
;
#pragma omp for
- for (i = 0; i != 64; i -= n) // { dg-error "increment is not constant 1 or -1 for != condition" }
+ for (i = 0; i != 64; i -= n) // { dg-error "increment is not constant 1 or -1 for '!=' condition" }
;
#pragma omp for
- for (i = 64; i != 0; i += n) // { dg-error "increment is not constant 1 or -1 for != condition" }
+ for (i = 64; i != 0; i += n) // { dg-error "increment is not constant 1 or -1 for '!=' condition" }
;
#pragma omp for
- for (i = 0; i != 64; i += o) // { dg-error "increment is not constant 1 or -1 for != condition" }
+ for (i = 0; i != 64; i += o) // { dg-error "increment is not constant 1 or -1 for '!=' condition" }
;
#pragma omp for
- for (i = 64; i != 0; i -= o) // { dg-error "increment is not constant 1 or -1 for != condition" }
+ for (i = 64; i != 0; i -= o) // { dg-error "increment is not constant 1 or -1 for '!=' condition" }
;
#pragma omp for
- for (i = 0; i != 64; i -= p) // { dg-error "increment is not constant 1 or -1 for != condition" }
+ for (i = 0; i != 64; i -= p) // { dg-error "increment is not constant 1 or -1 for '!=' condition" }
;
#pragma omp for
- for (i = 64; i != 0; i += p) // { dg-error "increment is not constant 1 or -1 for != condition" }
+ for (i = 64; i != 0; i += p) // { dg-error "increment is not constant 1 or -1 for '!=' condition" }
;
}
@@ -165,63 +165,63 @@ f1 (I<int> &x, I<int> &y, I<int> &u, I<int> &v)
for (i = y; i != x; i = l + i)
;
#pragma omp for
- for (i = x; i != y; i = i + 2) // { dg-error "increment is not constant 1 or -1 for != condition" }
+ for (i = x; i != y; i = i + 2) // { dg-error "increment is not constant 1 or -1 for '!=' condition" }
;
#pragma omp for
- for (i = x; i != y; i = 7 + i) // { dg-error "increment is not constant 1 or -1 for != condition" }
+ for (i = x; i != y; i = 7 + i) // { dg-error "increment is not constant 1 or -1 for '!=' condition" }
;
#pragma omp for
- for (i = y; i != x; i = i - 2) // { dg-error "increment is not constant 1 or -1 for != condition" }
+ for (i = y; i != x; i = i - 2) // { dg-error "increment is not constant 1 or -1 for '!=' condition" }
;
#pragma omp for
- for (i = y; i != x; i = -7 + i) // { dg-error "increment is not constant 1 or -1 for != condition" }
+ for (i = y; i != x; i = -7 + i) // { dg-error "increment is not constant 1 or -1 for '!=' condition" }
;
#pragma omp for
- for (i = x; i != y; i = i + m) // { dg-error "increment is not constant 1 or -1 for != condition" }
+ for (i = x; i != y; i = i + m) // { dg-error "increment is not constant 1 or -1 for '!=' condition" }
;
#pragma omp for
- for (i = x; i != y; i = m + i) // { dg-error "increment is not constant 1 or -1 for != condition" }
+ for (i = x; i != y; i = m + i) // { dg-error "increment is not constant 1 or -1 for '!=' condition" }
;
#pragma omp for
- for (i = y; i != x; i = i - m) // { dg-error "increment is not constant 1 or -1 for != condition" }
+ for (i = y; i != x; i = i - m) // { dg-error "increment is not constant 1 or -1 for '!=' condition" }
;
#pragma omp for
- for (i = y; i != x; i = -m + i) // { dg-error "increment is not constant 1 or -1 for != condition" }
+ for (i = y; i != x; i = -m + i) // { dg-error "increment is not constant 1 or -1 for '!=' condition" }
;
#pragma omp for
- for (i = x; i != y; i = i - n) // { dg-error "increment is not constant 1 or -1 for != condition" }
+ for (i = x; i != y; i = i - n) // { dg-error "increment is not constant 1 or -1 for '!=' condition" }
;
#pragma omp for
- for (i = x; i != y; i = -n + i) // { dg-error "increment is not constant 1 or -1 for != condition" }
+ for (i = x; i != y; i = -n + i) // { dg-error "increment is not constant 1 or -1 for '!=' condition" }
;
#pragma omp for
- for (i = y; i != x; i = i + n) // { dg-error "increment is not constant 1 or -1 for != condition" }
+ for (i = y; i != x; i = i + n) // { dg-error "increment is not constant 1 or -1 for '!=' condition" }
;
#pragma omp for
- for (i = y; i != x; i = n + i) // { dg-error "increment is not constant 1 or -1 for != condition" }
+ for (i = y; i != x; i = n + i) // { dg-error "increment is not constant 1 or -1 for '!=' condition" }
;
#pragma omp for
- for (i = x; i != y; i = i + o) // { dg-error "increment is not constant 1 or -1 for != condition" }
+ for (i = x; i != y; i = i + o) // { dg-error "increment is not constant 1 or -1 for '!=' condition" }
;
#pragma omp for
- for (i = x; i != y; i = o + i) // { dg-error "increment is not constant 1 or -1 for != condition" }
+ for (i = x; i != y; i = o + i) // { dg-error "increment is not constant 1 or -1 for '!=' condition" }
;
#pragma omp for
- for (i = y; i != x; i = i - o) // { dg-error "increment is not constant 1 or -1 for != condition" }
+ for (i = y; i != x; i = i - o) // { dg-error "increment is not constant 1 or -1 for '!=' condition" }
;
#pragma omp for
- for (i = y; i != x; i = -o + i) // { dg-error "increment is not constant 1 or -1 for != condition" }
+ for (i = y; i != x; i = -o + i) // { dg-error "increment is not constant 1 or -1 for '!=' condition" }
;
#pragma omp for
- for (i = x; i != y; i = i - p) // { dg-error "increment is not constant 1 or -1 for != condition" }
+ for (i = x; i != y; i = i - p) // { dg-error "increment is not constant 1 or -1 for '!=' condition" }
;
#pragma omp for
- for (i = x; i != y; i = -p + i) // { dg-error "increment is not constant 1 or -1 for != condition" }
+ for (i = x; i != y; i = -p + i) // { dg-error "increment is not constant 1 or -1 for '!=' condition" }
;
#pragma omp for
- for (i = y; i != x; i = i + p) // { dg-error "increment is not constant 1 or -1 for != condition" }
+ for (i = y; i != x; i = i + p) // { dg-error "increment is not constant 1 or -1 for '!=' condition" }
;
#pragma omp for
- for (i = y; i != x; i = p + i) // { dg-error "increment is not constant 1 or -1 for != condition" }
+ for (i = y; i != x; i = p + i) // { dg-error "increment is not constant 1 or -1 for '!=' condition" }
;
}
diff --git a/gcc/testsuite/g++.dg/gomp/macro-4.C b/gcc/testsuite/g++.dg/gomp/macro-4.C
index 6a69f1a..dcc8bcb 100644
--- a/gcc/testsuite/g++.dg/gomp/macro-4.C
+++ b/gcc/testsuite/g++.dg/gomp/macro-4.C
@@ -10,9 +10,9 @@ void bar (void);
void
foo (void)
{
-#pragma omp p // { dg-warning "-:ignoring #pragma omp _Pragma" }
+#pragma omp p // { dg-warning "-:ignoring '#pragma omp _Pragma'" }
bar ();
- omp_p // { dg-warning "-:ignoring #pragma omp _Pragma" }
+ omp_p // { dg-warning "-:ignoring '#pragma omp _Pragma'" }
bar ();
}
@@ -22,8 +22,8 @@ foo (void)
void
baz (void)
{
-#pragma omp parallel // { dg-warning "-:ignoring #pragma omp serial" }
+#pragma omp parallel // { dg-warning "-:ignoring '#pragma omp serial'" }
bar ();
- omp_parallel // { dg-warning "-:ignoring #pragma omp serial" }
+ omp_parallel // { dg-warning "-:ignoring '#pragma omp serial'" }
bar ();
}
diff --git a/gcc/testsuite/g++.dg/gomp/scan-1.C b/gcc/testsuite/g++.dg/gomp/scan-1.C
new file mode 100644
index 0000000..6fd3320
--- /dev/null
+++ b/gcc/testsuite/g++.dg/gomp/scan-1.C
@@ -0,0 +1,26 @@
+// { dg-do compile { target c++11 } }
+
+struct S { S (); ~S (); S &operator = (const S &) = delete; int s; }; // { dg-message "declared here" }
+#pragma omp declare reduction (+ : S : omp_out.s += omp_in.s)
+
+S s;
+
+void
+foo (void)
+{
+ #pragma omp simd reduction (+: s)
+ for (int i = 0; i < 64; ++i)
+ s.s += i;
+}
+
+void
+bar (int *x)
+{
+ #pragma omp simd reduction (inscan, +: s) // { dg-error "use of deleted function" }
+ for (int i = 0; i < 64; ++i)
+ {
+ s.s += i;
+ #pragma omp scan inclusive (s) // { dg-error "" }
+ x[i] = s.s;
+ }
+}
diff --git a/gcc/testsuite/g++.dg/gomp/udr-1.C b/gcc/testsuite/g++.dg/gomp/udr-1.C
index 10c1c8d..c07a89b 100644
--- a/gcc/testsuite/g++.dg/gomp/udr-1.C
+++ b/gcc/testsuite/g++.dg/gomp/udr-1.C
@@ -86,11 +86,11 @@ namespace N5
namespace N6
{
struct A { int a; A () : a (0) {} };
- #pragma omp declare reduction (| : const A : omp_out.a |= omp_in.a) // { dg-error "const, volatile or __restrict" }
- #pragma omp declare reduction (+ : __const A : omp_out.a += omp_in.a) // { dg-error "const, volatile or __restrict" }
+ #pragma omp declare reduction (| : const A : omp_out.a |= omp_in.a) // { dg-error "'const', 'volatile' or '__restrict'" }
+ #pragma omp declare reduction (+ : __const A : omp_out.a += omp_in.a) // { dg-error "'const', 'volatile' or '__restrict'" }
typedef volatile A T;
- #pragma omp declare reduction (min : T : omp_out.a += omp_in.a) // { dg-error "const, volatile or __restrict" }
- #pragma omp declare reduction (* : A *__restrict : omp_out->a *= omp_in->a)// { dg-error "const, volatile or __restrict" }
+ #pragma omp declare reduction (min : T : omp_out.a += omp_in.a) // { dg-error "'const', 'volatile' or '__restrict'" }
+ #pragma omp declare reduction (* : A *__restrict : omp_out->a *= omp_in->a)// { dg-error "'const', 'volatile' or '__restrict'" }
}
namespace N7
{
@@ -98,21 +98,21 @@ namespace N7
template <typename T1, typename T2, typename T3, typename T4>
struct S
{
- #pragma omp declare reduction (| : T1 : omp_out |= omp_in) // { dg-error "const, volatile or __restrict" }
- #pragma omp declare reduction (+ : T2 : omp_out += omp_in) // { dg-error "const, volatile or __restrict" }
+ #pragma omp declare reduction (| : T1 : omp_out |= omp_in) // { dg-error "'const', 'volatile' or '__restrict'" }
+ #pragma omp declare reduction (+ : T2 : omp_out += omp_in) // { dg-error "'const', 'volatile' or '__restrict'" }
typedef T3 T;
- #pragma omp declare reduction (min : T : omp_out += omp_in) // { dg-error "const, volatile or __restrict" }
- #pragma omp declare reduction (* : T4 : omp_out *= omp_in) // { dg-error "const, volatile or __restrict" }
+ #pragma omp declare reduction (min : T : omp_out += omp_in) // { dg-error "'const', 'volatile' or '__restrict'" }
+ #pragma omp declare reduction (* : T4 : omp_out *= omp_in) // { dg-error "'const', 'volatile' or '__restrict'" }
};
S<const A, __const A, volatile A, A *__restrict> s;
template <typename T1, typename T2, typename T3, typename T4>
int foo ()
{
- #pragma omp declare reduction (| : T1 : omp_out |= omp_in) // { dg-error "const, volatile or __restrict" }
- #pragma omp declare reduction (+ : T2 : omp_out += omp_in) // { dg-error "const, volatile or __restrict" }
+ #pragma omp declare reduction (| : T1 : omp_out |= omp_in) // { dg-error "'const', 'volatile' or '__restrict'" }
+ #pragma omp declare reduction (+ : T2 : omp_out += omp_in) // { dg-error "'const', 'volatile' or '__restrict'" }
typedef T3 T;
- #pragma omp declare reduction (min : T : omp_out += omp_in) // { dg-error "const, volatile or __restrict" }
- #pragma omp declare reduction (* : T4 : omp_out *= omp_in) // { dg-error "const, volatile or __restrict" }
+ #pragma omp declare reduction (min : T : omp_out += omp_in) // { dg-error "'const', 'volatile' or '__restrict'" }
+ #pragma omp declare reduction (* : T4 : omp_out *= omp_in) // { dg-error "'const', 'volatile' or '__restrict'" }
return 0;
}
int x = foo <const A, __const A, volatile A, A *__restrict> ();
diff --git a/gcc/testsuite/g++.dg/init/initializer-string-too-long.C b/gcc/testsuite/g++.dg/init/initializer-string-too-long.C
index c4ce468..064e1ac 100644
--- a/gcc/testsuite/g++.dg/init/initializer-string-too-long.C
+++ b/gcc/testsuite/g++.dg/init/initializer-string-too-long.C
@@ -2,7 +2,7 @@
/* Verify that we highlight *which* string is too long. */
-char test[3][4] = { "ok", "too long", "ok" }; // { dg-error "initializer-string for array of chars is too long" }
+char test[3][4] = { "ok", "too long", "ok" }; // { dg-error "initializer-string for 'char \\\[4]' is too long" }
/* { dg-begin-multiline-output "" }
char test[3][4] = { "ok", "too long", "ok" };
^~~~~~~~~~
diff --git a/gcc/testsuite/g++.dg/init/pr42844.C b/gcc/testsuite/g++.dg/init/pr42844.C
index 299a30a..9b7ed05 100644
--- a/gcc/testsuite/g++.dg/init/pr42844.C
+++ b/gcc/testsuite/g++.dg/init/pr42844.C
@@ -22,22 +22,22 @@ struct G { T t; }; // { dg-message "user-provided default constructor" }
void f ()
{
- B const b; // { dg-error "uninitialized const" }
+ B const b; // { dg-error "uninitialized 'const" }
extern B const bext;
- C const c[ 1 ]; // { dg-error "uninitialized const" }
+ C const c[ 1 ]; // { dg-error "uninitialized 'const" }
extern C const cext[ 1 ];
D const d;
extern D const dext;
- E const e; // { dg-error "uninitialized const" }
+ E const e; // { dg-error "uninitialized 'const" }
extern E const eext;
- F<int> const f; // { dg-error "uninitialized const" }
+ F<int> const f; // { dg-error "uninitialized 'const" }
extern F<int> const fext;
- G<int> const g; // { dg-error "uninitialized const" }
+ G<int> const g; // { dg-error "uninitialized 'const" }
extern G<int> const gext;
}
@@ -48,7 +48,7 @@ struct I : A { int i; }; // { dg-message "user-provided default constructor" }
template <class T>
void g ()
{
- T const t; // { dg-error "uninitialized const" }
+ T const t; // { dg-error "uninitialized 'const" }
extern T const text;
}
diff --git a/gcc/testsuite/g++.dg/init/static5.C b/gcc/testsuite/g++.dg/init/static5.C
new file mode 100644
index 0000000..4eaf787
--- /dev/null
+++ b/gcc/testsuite/g++.dg/init/static5.C
@@ -0,0 +1,9 @@
+// PR c++/70156
+// { dg-do compile { target c++11 } }
+
+template <int> struct A { int i; };
+struct B { int i; };
+struct C {
+ static const A<0> a = { 0 }; // { dg-error ".constexpr. needed for in-class initialization of static data member" }
+ static const B b = { 1 }; // { dg-error ".constexpr. needed for in-class initialization of static data member" }
+};
diff --git a/gcc/testsuite/g++.dg/lookup/pr90754.C b/gcc/testsuite/g++.dg/lookup/pr90754.C
new file mode 100644
index 0000000..f68f6d4
--- /dev/null
+++ b/gcc/testsuite/g++.dg/lookup/pr90754.C
@@ -0,0 +1,11 @@
+// PR c++/90754 ICE in type lookup.
+
+class A {
+ struct COMTypeInfo;
+};
+class B {
+ struct COMTypeInfo;
+};
+class C : A, B {
+ struct COMTypeInfo;
+};
diff --git a/gcc/testsuite/g++.dg/lookup/strong-using2.C b/gcc/testsuite/g++.dg/lookup/strong-using2.C
new file mode 100644
index 0000000..1728494
--- /dev/null
+++ b/gcc/testsuite/g++.dg/lookup/strong-using2.C
@@ -0,0 +1,11 @@
+// { dg-do compile { target c++11 } }
+// { dg-options "-w" }
+
+namespace A
+{
+ namespace B // { dg-bogus "inline namespace" }
+ {
+ }
+
+ using namespace B __attribute__ ((strong)); // { dg-bogus "no longer supported" }
+}
diff --git a/gcc/testsuite/g++.dg/lookup/using53.C b/gcc/testsuite/g++.dg/lookup/using53.C
index a108b50..595612e 100644
--- a/gcc/testsuite/g++.dg/lookup/using53.C
+++ b/gcc/testsuite/g++.dg/lookup/using53.C
@@ -49,5 +49,5 @@ void
f ()
{
using N::i;
- using N::i; // { dg-error "declared" }
+ using N::i; // { dg-error "redeclaration" }
}
diff --git a/gcc/testsuite/g++.dg/lto/alias-1_0.C b/gcc/testsuite/g++.dg/lto/alias-1_0.C
new file mode 100644
index 0000000..333bcf0
--- /dev/null
+++ b/gcc/testsuite/g++.dg/lto/alias-1_0.C
@@ -0,0 +1,33 @@
+/* { dg-lto-do run } */
+/* { dg-lto-options { { -O2 -flto } } } */
+
+/* With LTO we consider all pointers to incomplete types to be possibly
+ aliasing. This makes *bptr to alias with aptr.
+ However with C++ ODR rule we can turn incomplete pointers to complete
+ dragging in info from alias-1_1.C. */
+
+#include <string.h>
+
+typedef int (*fnptr) ();
+
+__attribute__ ((used))
+struct a *aptr;
+
+__attribute__ ((used))
+struct b **bptr = (struct b**)&aptr;
+extern void init ();
+extern void inline_me_late (int);
+int n=1;
+
+
+int
+main (int argc, char **argv)
+{
+ init ();
+ aptr = 0;
+ for (int i=0; i<n; i++)
+ inline_me_late (argc);
+ if (!__builtin_constant_p (aptr == 0))
+ __builtin_abort ();
+ return (size_t)aptr;
+}
diff --git a/gcc/testsuite/g++.dg/lto/alias-1_1.C b/gcc/testsuite/g++.dg/lto/alias-1_1.C
new file mode 100644
index 0000000..49e8217
--- /dev/null
+++ b/gcc/testsuite/g++.dg/lto/alias-1_1.C
@@ -0,0 +1,16 @@
+#include <string.h>
+struct a {int a;} a;
+struct b {short b;} b;
+extern struct b **bptr;
+void
+inline_me_late (int argc)
+{
+ if (argc == -1)
+ *bptr = (struct b *)(size_t)1;
+}
+void
+init()
+{
+ a.a=1;
+ b.b=2;
+}
diff --git a/gcc/testsuite/g++.dg/lto/alias-2_0.C b/gcc/testsuite/g++.dg/lto/alias-2_0.C
new file mode 100644
index 0000000..adad3ec
--- /dev/null
+++ b/gcc/testsuite/g++.dg/lto/alias-2_0.C
@@ -0,0 +1,33 @@
+/* { dg-lto-do run } */
+/* { dg-lto-options { { -O2 -flto } } } */
+
+/* With LTO we consider all pointers to incomplete types to be possibly
+ aliasing. This makes *bptr to alias with aptr.
+ For C++ ODR types we however can work out that they are actually
+ different. */
+
+#include <string.h>
+
+typedef int (*fnptr) ();
+
+__attribute__ ((used))
+struct a *aptr;
+
+__attribute__ ((used))
+struct b **bptr = (struct b**)&aptr;
+extern void init ();
+extern void inline_me_late (int);
+int n=1;
+
+
+int
+main (int argc, char **argv)
+{
+ init ();
+ aptr = 0;
+ for (int i=0; i<n; i++)
+ inline_me_late (argc);
+ if (!__builtin_constant_p (aptr == 0))
+ __builtin_abort ();
+ return (size_t)aptr;
+}
diff --git a/gcc/testsuite/g++.dg/lto/alias-2_1.C b/gcc/testsuite/g++.dg/lto/alias-2_1.C
new file mode 100644
index 0000000..1cbebf1
--- /dev/null
+++ b/gcc/testsuite/g++.dg/lto/alias-2_1.C
@@ -0,0 +1,16 @@
+#include <string.h>
+struct a {int a;} a;
+struct b {int b;} b;
+extern struct b **bptr;
+void
+inline_me_late (int argc)
+{
+ if (argc == -1)
+ *bptr = (struct b *)(size_t)1;
+}
+void
+init()
+{
+ a.a=1;
+ b.b=2;
+}
diff --git a/gcc/testsuite/g++.dg/lto/pr90939_0.C b/gcc/testsuite/g++.dg/lto/pr90939_0.C
new file mode 100644
index 0000000..8987c34
--- /dev/null
+++ b/gcc/testsuite/g++.dg/lto/pr90939_0.C
@@ -0,0 +1,64 @@
+// PR ipa/90939
+// { dg-lto-do link }
+// { dg-lto-options { { -flto -O3 } } }
+
+
+typedef char uint8_t;
+template <class T> class A {
+public:
+ A(T *);
+};
+template <typename Derived, typename Base> const Derived &To(Base &p1) {
+ return static_cast<const Derived &>(p1);
+}
+class H;
+template <typename, typename Base> const H *To(Base *p1) {
+ return p1 ? &To<H>(*p1) : nullptr;
+}
+enum TextDirection : uint8_t;
+enum WritingMode : unsigned;
+class B {
+public:
+ WritingMode m_fn1();
+};
+class C {
+public:
+ int &m_fn2();
+};
+class D { double d;};
+class H : public D {};
+class F {
+public:
+ F(C, A<const int>, B *, WritingMode, TextDirection);
+};
+
+class G {
+public:
+ C NGLayoutAlgorithm_node;
+ B NGLayoutAlgorithm_space;
+ TextDirection NGLayoutAlgorithm_direction;
+ H NGLayoutAlgorithm_break_token;
+ G(A<const int> p1) __attribute__((noinline))
+ : break_token_(&NGLayoutAlgorithm_break_token),
+ container_builder_(NGLayoutAlgorithm_node, p1, &NGLayoutAlgorithm_space,
+ NGLayoutAlgorithm_space.m_fn1(),
+ NGLayoutAlgorithm_direction) {}
+ G(C p1, const H *) : G(&p1.m_fn2()) {}
+ A<H> break_token_;
+ F container_builder_;
+};
+
+class I : G {
+public:
+ I(const D *) __attribute__((noinline));
+};
+C a;
+I::I(const D *p1) : G(a, To<H>(p1)) {}
+
+D gd[10];
+
+int main (int argc, char *argv[])
+{
+ I i(&(gd[argc%2]));
+ return 0;
+}
diff --git a/gcc/testsuite/g++.dg/lto/pr90939_1.C b/gcc/testsuite/g++.dg/lto/pr90939_1.C
new file mode 100644
index 0000000..9add894
--- /dev/null
+++ b/gcc/testsuite/g++.dg/lto/pr90939_1.C
@@ -0,0 +1,45 @@
+typedef char uint8_t;
+template <class T> class A {
+public:
+ A(T *);
+};
+
+enum TextDirection : uint8_t;
+enum WritingMode : unsigned;
+class B {
+public:
+ WritingMode m_fn1();
+};
+class C {
+public:
+ int &m_fn2();
+};
+
+class F {
+public:
+ F(C, A<const int>, B *, WritingMode, TextDirection);
+};
+class D { double d;};
+class H : public D {};
+
+
+
+template <class T> A<T>::A(T*) {}
+
+template class A<H>;
+template class A<int const>;
+
+WritingMode __attribute__((noipa))
+B::m_fn1()
+{
+ return (WritingMode) 0;
+}
+
+int gi;
+int & __attribute__((noipa))
+C::m_fn2 ()
+{
+ return gi;
+}
+
+__attribute__((noipa)) F::F(C, A<const int>, B *, WritingMode, TextDirection) {}
diff --git a/gcc/testsuite/g++.dg/lto/pr90990_0.C b/gcc/testsuite/g++.dg/lto/pr90990_0.C
new file mode 100644
index 0000000..22a5e3f
--- /dev/null
+++ b/gcc/testsuite/g++.dg/lto/pr90990_0.C
@@ -0,0 +1,31 @@
+// { dg-lto-do link }
+/* { dg-extra-ld-options { -r -nostdlib } } */
+class A {
+public:
+ float m_floats;
+ A() {}
+};
+class B {
+public:
+ A operator[](int);
+};
+class C {
+ B m_basis;
+
+public:
+ A operator()(A) {
+ m_basis[1] = m_basis[2];
+ A a;
+ return a;
+ }
+};
+class D {
+public:
+ C m_fn1();
+};
+class F {
+ A m_pivotInB;
+ F(D &, const A &);
+};
+F::F(D &p1, const A &p2) : m_pivotInB(p1.m_fn1()(p2)) {}
+
diff --git a/gcc/testsuite/g++.dg/other/error34.C b/gcc/testsuite/g++.dg/other/error34.C
index f6b4488..7bcea43 100644
--- a/gcc/testsuite/g++.dg/other/error34.C
+++ b/gcc/testsuite/g++.dg/other/error34.C
@@ -2,5 +2,5 @@
// { dg-do compile }
// { dg-options "" }
-S () : str(__PRETTY_FUNCTION__) { return S(); } // { dg-error "forbids declaration" "decl" }
+S () : str(__PRETTY_FUNCTION__) { return S(); } // { dg-error "1:ISO C\\+\\+ forbids declaration" "decl" }
// { dg-error "only constructors" "constructor" { target *-*-* } .-1 }
diff --git a/gcc/testsuite/g++.dg/other/final3.C b/gcc/testsuite/g++.dg/other/final3.C
new file mode 100644
index 0000000..a49dc22
--- /dev/null
+++ b/gcc/testsuite/g++.dg/other/final3.C
@@ -0,0 +1,28 @@
+// PR c++/67184
+// { dg-do compile { target c++11 } }
+// { dg-options "-fdump-tree-original" }
+
+struct V {
+ virtual void foo();
+};
+
+struct wV final : V {
+};
+
+struct oV final : V {
+ void foo();
+};
+
+void call(wV& x)
+{
+ x.foo();
+ x.V::foo();
+}
+
+void call(oV& x)
+{
+ x.foo();
+ x.V::foo();
+}
+
+// { dg-final { scan-tree-dump-times "OBJ_TYPE_REF" 0 "original" } }
diff --git a/gcc/testsuite/g++.dg/other/final5.C b/gcc/testsuite/g++.dg/other/final5.C
new file mode 100644
index 0000000..8a3e608
--- /dev/null
+++ b/gcc/testsuite/g++.dg/other/final5.C
@@ -0,0 +1,19 @@
+// PR c++/69445
+// { dg-do compile { target c++11 } }
+// { dg-options "-fdump-tree-original" }
+
+struct Base {
+ virtual void foo() const = 0;
+ virtual void bar() const {}
+};
+
+struct C final : Base {
+ void foo() const { }
+};
+
+void func(const C & c) {
+ c.bar();
+ c.foo();
+}
+
+// { dg-final { scan-tree-dump-times "OBJ_TYPE_REF" 0 "original" } }
diff --git a/gcc/testsuite/g++.dg/other/final6.C b/gcc/testsuite/g++.dg/other/final6.C
new file mode 100644
index 0000000..1979038
--- /dev/null
+++ b/gcc/testsuite/g++.dg/other/final6.C
@@ -0,0 +1,9 @@
+// PR c++/90909
+// { dg-do link { target c++11 } }
+
+struct S1 { virtual void f() = 0; };
+struct S2: S1 { virtual void f() {} };
+struct S3: S2 { using S1::f; };
+struct S4 final: S3 { void g(); };
+void S4::g() { f(); }
+int main() { S4().g(); }
diff --git a/gcc/testsuite/g++.dg/other/final7.C b/gcc/testsuite/g++.dg/other/final7.C
new file mode 100644
index 0000000..43ab7ba
--- /dev/null
+++ b/gcc/testsuite/g++.dg/other/final7.C
@@ -0,0 +1,11 @@
+// PR c++/90909
+// { dg-do run { target c++11 } }
+
+#include <cassert>
+
+struct S1 { virtual bool f() { return false; } };
+struct S2: S1 { virtual bool f() { return true; } };
+struct S3: S2 { using S1::f; };
+struct S4 final: S3 { void g(); };
+void S4::g() { assert (f() == true); }
+int main() { S4().g(); }
diff --git a/gcc/testsuite/g++.dg/other/final8.C b/gcc/testsuite/g++.dg/other/final8.C
new file mode 100644
index 0000000..f90f94e
--- /dev/null
+++ b/gcc/testsuite/g++.dg/other/final8.C
@@ -0,0 +1,9 @@
+// { dg-do compile { target c++11 } }
+// { dg-final { scan-assembler-not "_ZN1BC2Ev" } }
+// { dg-final { scan-assembler-not "_ZN1BD2Ev" } }
+
+struct A { int i; A(); virtual ~A() = 0; };
+struct B final: public virtual A { int j; B(); ~B(); };
+
+B::B() {}
+B::~B() {}
diff --git a/gcc/testsuite/g++.dg/other/friend4.C b/gcc/testsuite/g++.dg/other/friend4.C
index 537643d..de5cfaf 100644
--- a/gcc/testsuite/g++.dg/other/friend4.C
+++ b/gcc/testsuite/g++.dg/other/friend4.C
@@ -3,6 +3,6 @@
struct A
{
- friend void A::foo(); // { dg-error "implicitly friends" }
- friend A::~A(); // { dg-error "implicitly friends" }
+ friend void A::foo(); // { dg-error "3:member functions are implicitly friends" }
+ friend A::~A(); // { dg-error "3:member functions are implicitly friends" }
};
diff --git a/gcc/testsuite/g++.dg/other/friend5.C b/gcc/testsuite/g++.dg/other/friend5.C
index b0ec201..f6780a4 100644
--- a/gcc/testsuite/g++.dg/other/friend5.C
+++ b/gcc/testsuite/g++.dg/other/friend5.C
@@ -5,5 +5,5 @@
struct A
{
- friend A::~A() {} /* { dg-error "implicitly friends of their class" } */
+ friend A::~A() {} /* { dg-error "3:member functions are implicitly friends of their class" } */
};
diff --git a/gcc/testsuite/g++.dg/other/friend7.C b/gcc/testsuite/g++.dg/other/friend7.C
index 4d22a87..56d994d 100644
--- a/gcc/testsuite/g++.dg/other/friend7.C
+++ b/gcc/testsuite/g++.dg/other/friend7.C
@@ -5,5 +5,5 @@
struct A
{
- friend A::~A() {} // { dg-error "implicitly friends of their class" }
+ friend A::~A() {} // { dg-error "3:member functions are implicitly friends of their class" }
};
diff --git a/gcc/testsuite/g++.dg/other/i386-2.C b/gcc/testsuite/g++.dg/other/i386-2.C
index f7a564b..b832480 100644
--- a/gcc/testsuite/g++.dg/other/i386-2.C
+++ b/gcc/testsuite/g++.dg/other/i386-2.C
@@ -1,12 +1,13 @@
/* { dg-do compile { target i?86-*-* x86_64-*-* } } */
-/* { dg-options "-O -pedantic-errors -march=k8 -msse4a -m3dnow -mavx -mavx2 -mfma4 -mxop -maes -mpclmul -mpopcnt -mabm -mlzcnt -mbmi -mbmi2 -mtbm -mlwp -mfsgsbase -mrdrnd -mf16c -mfma -mrtm -mrdseed -mprfchw -madx -mfxsr -mxsaveopt -mavx512f -mavx512er -mavx512cd -mavx512pf -msha -mprefetchwt1 -mxsavec -mxsaves -mclflushopt -mavx512dq -mavx512bw -mavx512vl -mavx512ifma -mavx512vbmi -mavx5124fmaps -mavx5124vnniw -mavx512vpopcntdq -mclwb -mmwaitx -mclzero -mpku -msgx -mrdpid -mgfni -mavx512bitalg -mpconfig -mwbnoinvd -mavx512bf16" } */
+/* { dg-options "-O -pedantic-errors -march=k8 -msse4a -m3dnow -mavx -mavx2 -mfma4 -mxop -maes -mpclmul -mpopcnt -mabm -mlzcnt -mbmi -mbmi2 -mtbm -mlwp -mfsgsbase -mrdrnd -mf16c -mfma -mrtm -mrdseed -mprfchw -madx -mfxsr -mxsaveopt -mavx512f -mavx512er -mavx512cd -mavx512pf -msha -mprefetchwt1 -mxsavec -mxsaves -mclflushopt -mavx512dq -mavx512bw -mavx512vl -mavx512ifma -mavx512vbmi -mavx5124fmaps -mavx5124vnniw -mavx512vpopcntdq -mclwb -mmwaitx -mclzero -mpku -msgx -mrdpid -mgfni -mavx512bitalg -mpconfig -mwbnoinvd -mavx512bf16 -menqcmd -mavx512vp2intersect" } */
/* Test that {,x,e,p,t,s,w,a,b,i}mmintrin.h, mm3dnow.h, fma4intrin.h,
xopintrin.h, abmintrin.h, bmiintrin.h, tbmintrin.h, lwpintrin.h,
popcntintrin.h, fmaintrin.h, pkuintrin.h, avx5124fmapsintrin.h,
avx5124vnniwintrin.h, avx512vpopcntdqintrin.h gfniintrin.h
- avx512bitalgintrin.h and mm_malloc.h.h are usable with -O
- -pedantic-errors. */
+ avx512bitalgintrin.h, avx512vp2intersectintrin.h,
+ avx512vp2intersectvlintrin.h and mm_malloc.h.h are usable
+ with -O -pedantic-errors. */
#include <x86intrin.h>
diff --git a/gcc/testsuite/g++.dg/other/i386-3.C b/gcc/testsuite/g++.dg/other/i386-3.C
index 4d6f94f..303bef4 100644
--- a/gcc/testsuite/g++.dg/other/i386-3.C
+++ b/gcc/testsuite/g++.dg/other/i386-3.C
@@ -1,11 +1,12 @@
/* { dg-do compile { target i?86-*-* x86_64-*-* } } */
-/* { dg-options "-O -fkeep-inline-functions -march=k8 -msse4a -m3dnow -mavx -mavx2 -mfma4 -mxop -maes -mpclmul -mpopcnt -mabm -mlzcnt -mbmi -mbmi2 -mtbm -mlwp -mfsgsbase -mrdrnd -mf16c -mfma -mrtm -mrdseed -mprfchw -madx -mfxsr -mxsaveopt -mavx512f -mavx512er -mavx512cd -mavx512pf -msha -mprefetchwt1 -mxsavec -mxsaves -mclflushopt -mavx512dq -mavx512bw -mavx512vl -mavx512ifma -mavx512vbmi -mavx5124fmaps -mavx5124vnniw -mavx512vpopcntdq -mclwb -mmwaitx -mclzero -mpku -msgx -mrdpid -mgfni -mavx512bitalg -mpconfig -mwbnoinvd -mavx512bf16" } */
+/* { dg-options "-O -fkeep-inline-functions -march=k8 -msse4a -m3dnow -mavx -mavx2 -mfma4 -mxop -maes -mpclmul -mpopcnt -mabm -mlzcnt -mbmi -mbmi2 -mtbm -mlwp -mfsgsbase -mrdrnd -mf16c -mfma -mrtm -mrdseed -mprfchw -madx -mfxsr -mxsaveopt -mavx512f -mavx512er -mavx512cd -mavx512pf -msha -mprefetchwt1 -mxsavec -mxsaves -mclflushopt -mavx512dq -mavx512bw -mavx512vl -mavx512ifma -mavx512vbmi -mavx5124fmaps -mavx5124vnniw -mavx512vpopcntdq -mclwb -mmwaitx -mclzero -mpku -msgx -mrdpid -mgfni -mavx512bitalg -mpconfig -mwbnoinvd -mavx512bf16 -menqcmd -mavx512vp2intersect" } */
/* Test that {,x,e,p,t,s,w,a,b,i}mmintrin.h, mm3dnow.h, fma4intrin.h,
xopintrin.h, abmintrin.h, bmiintrin.h, tbmintrin.h, lwpintrin.h,
popcntintrin.h, fmaintrin.h, pkuintrin.h, avx5124fmapsintrin.h,
avx5124vnniwintrin.h, avx512vpopcntdqintrin.h gfniintrin.h
- avx512bitalgintrin.h and mm_malloc.h are usable with -O
- -fkeep-inline-functions. */
+ avx512bitalgintrin.h, avx512vp2intersectintrin.h,
+ avx512vp2intersectvlintrin.h and mm_malloc.h are usable
+ with -O -fkeep-inline-functions. */
#include <x86intrin.h>
diff --git a/gcc/testsuite/g++.dg/other/offsetof9.C b/gcc/testsuite/g++.dg/other/offsetof9.C
index bd80fa5..1936f2e 100644
--- a/gcc/testsuite/g++.dg/other/offsetof9.C
+++ b/gcc/testsuite/g++.dg/other/offsetof9.C
@@ -4,14 +4,14 @@
struct A { int i; };
struct B : virtual A { };
-__SIZE_TYPE__ s = __builtin_offsetof (B, A::i); // { dg-warning "offsetof within non-standard-layout type" }
+__SIZE_TYPE__ s = __builtin_offsetof (B, A::i); // { dg-warning "'offsetof' within non-standard-layout type" }
template <typename T>
__SIZE_TYPE__
foo ()
{
- return __builtin_offsetof (T, A::i) // { dg-warning "offsetof within non-standard-layout type" }
- + __builtin_offsetof (B, A::i); // { dg-warning "offsetof within non-standard-layout type" }
+ return __builtin_offsetof (T, A::i) // { dg-warning "'offsetof' within non-standard-layout type" }
+ + __builtin_offsetof (B, A::i); // { dg-warning "'offsetof' within non-standard-layout type" }
}
__SIZE_TYPE__ t = foo<B> ();
diff --git a/gcc/testsuite/g++.dg/other/pr77548.C b/gcc/testsuite/g++.dg/other/pr77548.C
new file mode 100644
index 0000000..842a9e9
--- /dev/null
+++ b/gcc/testsuite/g++.dg/other/pr77548.C
@@ -0,0 +1,9 @@
+// PR c++/77548
+// { dg-do compile }
+// { dg-options "" }
+
+struct S
+{
+ int f (void) { return 0; }
+ int f (int) { return f ? : 1; } // { dg-error "cannot resolve overloaded function" }
+};
diff --git a/gcc/testsuite/g++.dg/other/pr84792-1.C b/gcc/testsuite/g++.dg/other/pr84792-1.C
index 23df8ae..9949efd 100644
--- a/gcc/testsuite/g++.dg/other/pr84792-1.C
+++ b/gcc/testsuite/g++.dg/other/pr84792-1.C
@@ -3,4 +3,4 @@ struct A {};
typedef struct
{
virtual void foo() {}
-} A::B; // { dg-error "typedef" }
+} A::B; // { dg-error "3:typedef" }
diff --git a/gcc/testsuite/g++.dg/other/pr84792-2.C b/gcc/testsuite/g++.dg/other/pr84792-2.C
index a393d57..082baae 100644
--- a/gcc/testsuite/g++.dg/other/pr84792-2.C
+++ b/gcc/testsuite/g++.dg/other/pr84792-2.C
@@ -3,4 +3,4 @@ struct A {};
typedef struct
{
void foo() {}
-} A::B; // { dg-error "typedef" }
+} A::B; // { dg-error "3:typedef" }
diff --git a/gcc/testsuite/g++.dg/overload/conv-op1.C b/gcc/testsuite/g++.dg/overload/conv-op1.C
index abcd741..d309619 100644
--- a/gcc/testsuite/g++.dg/overload/conv-op1.C
+++ b/gcc/testsuite/g++.dg/overload/conv-op1.C
@@ -10,7 +10,7 @@ struct A
void f()
{
const int i = 42;
- A()(i); // { dg-message "<conversion>" }
+ A()(i); // { dg-message "(conversion)" }
// { dg-error "qualifiers" "" { target *-*-* } .-1 }
}
diff --git a/gcc/testsuite/g++.dg/overload/using2.C b/gcc/testsuite/g++.dg/overload/using2.C
index b1d52f7..edfd1a1 100644
--- a/gcc/testsuite/g++.dg/overload/using2.C
+++ b/gcc/testsuite/g++.dg/overload/using2.C
@@ -69,7 +69,7 @@ using std::C3; using other::C3;
long C3 (long) throw ();
int main () {
- malloc (0);
+ void *p = malloc (0);
exit (0);
_exit (0); // { dg-error "ambiguous" }
diff --git a/gcc/testsuite/g++.dg/parse/alignas1.C b/gcc/testsuite/g++.dg/parse/alignas1.C
new file mode 100644
index 0000000..8f36101
--- /dev/null
+++ b/gcc/testsuite/g++.dg/parse/alignas1.C
@@ -0,0 +1,10 @@
+// PR c++/64235
+// { dg-do compile { target c++11 } }
+
+struct S {
+ double d;
+};
+
+struct alignas(sizeof(S) S1 { }; // { dg-error "expected '\\)' before 'S1'" }
+struct alignas(16 S2 { }; // { dg-error "expected '\\)' before 'S2'" }
+struct alignas(int S3 { }; // { dg-error "expected '\\)' before 'S3'" }
diff --git a/gcc/testsuite/g++.dg/parse/crash59.C b/gcc/testsuite/g++.dg/parse/crash59.C
index e5e6298..7e90dde 100644
--- a/gcc/testsuite/g++.dg/parse/crash59.C
+++ b/gcc/testsuite/g++.dg/parse/crash59.C
@@ -1,3 +1,4 @@
// PR c++/53003
-struct A{ void a{} return b // { dg-error "function definition|expected" }
+struct A{ void a{} return b // { dg-error "16:function definition" }
+// { dg-error "expected" "" { target *-*-* } .-1 }
diff --git a/gcc/testsuite/g++.dg/parse/error10.C b/gcc/testsuite/g++.dg/parse/error10.C
index 46c9eff..4750e5c 100644
--- a/gcc/testsuite/g++.dg/parse/error10.C
+++ b/gcc/testsuite/g++.dg/parse/error10.C
@@ -14,4 +14,4 @@ template <typename T> void foo()
enum typename A<T>::E e4;
}
-// { dg-error "28:two or more data types in declaration of 'e4'" "2 or more" { target *-*-* } 14 }
+// { dg-error "3:two or more data types in declaration of 'e4'" "2 or more" { target *-*-* } 14 }
diff --git a/gcc/testsuite/g++.dg/parse/error24.C b/gcc/testsuite/g++.dg/parse/error24.C
index c8ab6d9..190812e 100644
--- a/gcc/testsuite/g++.dg/parse/error24.C
+++ b/gcc/testsuite/g++.dg/parse/error24.C
@@ -2,7 +2,7 @@
// PR c++/19395
struct A {
- typedef int ::X; // { dg-error "17:typedef name may not be a nested-name-specifier" }
+ typedef int ::X; // { dg-error "15:typedef name may not be a nested-name-specifier" }
};
diff --git a/gcc/testsuite/g++.dg/parse/error29.C b/gcc/testsuite/g++.dg/parse/error29.C
index 2c3a3a7..20cc820 100644
--- a/gcc/testsuite/g++.dg/parse/error29.C
+++ b/gcc/testsuite/g++.dg/parse/error29.C
@@ -7,7 +7,7 @@ struct A {
void operator delete(void *);
};
struct B {
- friend void A::foo() {} // { dg-error "22:cannot define member function 'A::foo' within 'B'" }
- friend void A::operator delete(void*) {} // { dg-error "39:cannot define member function 'A::operator delete' within 'B'" }
- friend A::A() {} // { dg-error "15:cannot define member function 'A::A' within 'B'" }
+ friend void A::foo() {} // { dg-error "15:cannot define member function 'A::foo' within 'B'" }
+ friend void A::operator delete(void*) {} // { dg-error "15:cannot define member function 'A::operator delete' within 'B'" }
+ friend A::A() {} // { dg-error "10:cannot define member function 'A::A' within 'B'" }
};
diff --git a/gcc/testsuite/g++.dg/parse/error32.C b/gcc/testsuite/g++.dg/parse/error32.C
index da27afd..1993c06 100644
--- a/gcc/testsuite/g++.dg/parse/error32.C
+++ b/gcc/testsuite/g++.dg/parse/error32.C
@@ -3,7 +3,7 @@
struct A {};
-typedef void (A::T)(); /* { dg-error "typedef name may not be a nested-name-specifier" } */
+typedef void (A::T)(); /* { dg-error "15:typedef name may not be a nested-name-specifier" } */
void foo()
{
diff --git a/gcc/testsuite/g++.dg/parse/error33.C b/gcc/testsuite/g++.dg/parse/error33.C
index e3a7166..0d25386 100644
--- a/gcc/testsuite/g++.dg/parse/error33.C
+++ b/gcc/testsuite/g++.dg/parse/error33.C
@@ -6,7 +6,7 @@ struct A
void foo();
};
-typedef void (A::T)(); /* { dg-error "typedef name may not be a nested" } */
+typedef void (A::T)(); /* { dg-error "15:typedef name may not be a nested" } */
void bar(T); /* { dg-message "note: declared here" } */
diff --git a/gcc/testsuite/g++.dg/parse/error38.C b/gcc/testsuite/g++.dg/parse/error38.C
index 63162a8..2c64ed4 100644
--- a/gcc/testsuite/g++.dg/parse/error38.C
+++ b/gcc/testsuite/g++.dg/parse/error38.C
@@ -1,3 +1,3 @@
// PR c++/29003
-typedef int operator !(); // { dg-error "declaration" }
+typedef int operator !(); // { dg-error "13:declaration" }
diff --git a/gcc/testsuite/g++.dg/parse/error39.C b/gcc/testsuite/g++.dg/parse/error39.C
index 431571c..8710e19 100644
--- a/gcc/testsuite/g++.dg/parse/error39.C
+++ b/gcc/testsuite/g++.dg/parse/error39.C
@@ -1,6 +1,6 @@
// PR c++/41769
-void f(void operator+()); // { dg-error "declaration" }
+void f(void operator+()); // { dg-error "13:declaration" }
void g()
{
@@ -8,7 +8,7 @@ void g()
{
}
- catch(void operator+()) // { dg-error "declaration" }
+ catch(void operator+()) // { dg-error "14:declaration" }
{
}
}
diff --git a/gcc/testsuite/g++.dg/parse/error62.C b/gcc/testsuite/g++.dg/parse/error62.C
new file mode 100644
index 0000000..8dac0ff
--- /dev/null
+++ b/gcc/testsuite/g++.dg/parse/error62.C
@@ -0,0 +1,10 @@
+// PR c++/68265
+
+int main()
+{
+ int (*) {} // { dg-error "expected primary-expression" }
+ any amount of syntactic nonsense // { dg-error "not declared in this scope" }
+ on multiple lines, with *punctuation* and ++operators++ even...
+ will be silently discarded
+ until the next close brace
+}
diff --git a/gcc/testsuite/g++.dg/parse/friend13.C b/gcc/testsuite/g++.dg/parse/friend13.C
new file mode 100644
index 0000000..d716247
--- /dev/null
+++ b/gcc/testsuite/g++.dg/parse/friend13.C
@@ -0,0 +1,16 @@
+// PR c++/90572
+
+template <typename T> struct C {
+ friend C(T::fn)();
+ friend C(T::fn)(int);
+ friend C(T::fn)(int, int);
+};
+
+struct X { };
+
+template<typename T>
+struct B {
+ friend X(T::fn)();
+ friend X(T::fn)(int);
+ friend X(T::fn)(int, int);
+};
diff --git a/gcc/testsuite/g++.dg/parse/pragma2.C b/gcc/testsuite/g++.dg/parse/pragma2.C
index c5616ff..c7d4f10 100644
--- a/gcc/testsuite/g++.dg/parse/pragma2.C
+++ b/gcc/testsuite/g++.dg/parse/pragma2.C
@@ -4,5 +4,6 @@
// does not.
int f(int x,
#pragma interface // { dg-error "not allowed here" }
+// { dg-bogus "two or more" "" { xfail *-*-* } .-1 }
// The parser gets confused and issues an error on the next line.
- int y); // { dg-bogus "" "" { xfail *-*-* } }
+ int y);
diff --git a/gcc/testsuite/g++.dg/parse/qualified4.C b/gcc/testsuite/g++.dg/parse/qualified4.C
index c827fcf..71b01af 100644
--- a/gcc/testsuite/g++.dg/parse/qualified4.C
+++ b/gcc/testsuite/g++.dg/parse/qualified4.C
@@ -2,5 +2,5 @@
// { dg-options "" }
struct X {
- void X::bar() {} // { dg-error "" }
+ void X::bar() {} // { dg-error "8:extra qualification" }
};
diff --git a/gcc/testsuite/g++.dg/parse/saved1.C b/gcc/testsuite/g++.dg/parse/saved1.C
index 0153fb2..979a056 100644
--- a/gcc/testsuite/g++.dg/parse/saved1.C
+++ b/gcc/testsuite/g++.dg/parse/saved1.C
@@ -1,6 +1,7 @@
// Test that the parser doesn't go into an infinite loop from ignoring the
// PRE_PARSED_FUNCTION_DECL token.
-class C { static void* operator new(size_t); }; // { dg-error "" }
+class C { static void* operator new(size_t); }; // { dg-error "24:declaration of .operator new. as non-function" }
+// { dg-error "expected|ISO C\\+\\+ forbids" "" { target *-*-* } .-1 }
void* C::operator new(size_t) { return 0; } // { dg-error "" }
class D { D(int i): integer(i){}}; // { dg-error "" }
diff --git a/gcc/testsuite/g++.dg/pch/operator-1.C b/gcc/testsuite/g++.dg/pch/operator-1.C
new file mode 100644
index 0000000..290b5f7
--- /dev/null
+++ b/gcc/testsuite/g++.dg/pch/operator-1.C
@@ -0,0 +1,2 @@
+#include "operator-1.H"
+int main(void){ major(0);} /* { dg-warning "Did not Work" } */
diff --git a/gcc/testsuite/g++.dg/pch/operator-1.Hs b/gcc/testsuite/g++.dg/pch/operator-1.Hs
new file mode 100644
index 0000000..657dae1
--- /dev/null
+++ b/gcc/testsuite/g++.dg/pch/operator-1.Hs
@@ -0,0 +1,9 @@
+# define __glibc_macro_warning1(message) _Pragma (#message)
+# define __glibc_macro_warning(message) \
+ __glibc_macro_warning1 (GCC warning message)
+#define __SYSMACROS_DM1(...) __glibc_macro_warning (#__VA_ARGS__)
+
+#define __SYSMACROS_DM(symbol) __SYSMACROS_DM1 \
+ (Did not Work)
+
+# define major(dev) __SYSMACROS_DM (major) (dev+0)
diff --git a/gcc/testsuite/g++.dg/pch/pr90326.C b/gcc/testsuite/g++.dg/pch/pr90326.C
new file mode 100644
index 0000000..6b4c5e1
--- /dev/null
+++ b/gcc/testsuite/g++.dg/pch/pr90326.C
@@ -0,0 +1,9 @@
+#include "pr90326.H"
+
+int main()
+{
+ float f = __FLT_MAX__;
+ if (f == 0.0)
+ __builtin_abort ();
+ return 0;
+}
diff --git a/gcc/testsuite/g++.dg/pch/pr90326.Hs b/gcc/testsuite/g++.dg/pch/pr90326.Hs
new file mode 100644
index 0000000..8b1a393
--- /dev/null
+++ b/gcc/testsuite/g++.dg/pch/pr90326.Hs
@@ -0,0 +1 @@
+// empty
diff --git a/gcc/testsuite/g++.dg/pr71694.C b/gcc/testsuite/g++.dg/pr71694.C
index 0a8baf2..5b59f87 100644
--- a/gcc/testsuite/g++.dg/pr71694.C
+++ b/gcc/testsuite/g++.dg/pr71694.C
@@ -1,5 +1,6 @@
/* { dg-do compile } */
/* { dg-options "-O2 -fno-store-merging" } */
+/* { dg-additional-options "-fno-common -mdynamic-no-pic" { target { ia32 && { x86_64-*-darwin* i?86-*-darwin* } } } } */
struct B {
B() {}
diff --git a/gcc/testsuite/g++.dg/pr90462.C b/gcc/testsuite/g++.dg/pr90462.C
new file mode 100644
index 0000000..2585ba0
--- /dev/null
+++ b/gcc/testsuite/g++.dg/pr90462.C
@@ -0,0 +1,49 @@
+/* { dg-options "-Wdeprecated-copy -fdiagnostics-format=json" } */
+
+template <class> class b;
+struct B {
+ typedef b<char> *c;
+};
+class d {
+public:
+ B::c operator->();
+};
+template <class> struct e;
+class f {
+ typedef int g;
+};
+template <class, class> class h;
+template <class i> class b {
+public:
+ i j;
+ i k;
+ int l;
+ void assign() {
+ int m;
+ h<i, int> n(&m);
+ n.o(&j, &k, l);
+ }
+};
+template <class i, class> class s : f { s &p(const i *, const i *, g); };
+template <class i, class t> s<i, t> &s<i, t>::p(const i *, const i *, g) {
+ d q;
+ q->assign();
+}
+struct G {
+ G();
+ G(int);
+ G(G &);
+};
+template <class i, class> class h {
+public:
+ h(int *);
+ void o(const i *, const i *, unsigned);
+ i r();
+};
+template <class i, class t> void h<i, t>::o(const i *, const i *, unsigned) {
+ G a;
+ a = r();
+}
+template s<char, e<char>> &s<char, e<char>>::p(const char *, const char *, g);
+
+/* { dg-regexp ".*" } */
diff --git a/gcc/testsuite/g++.dg/pr90981.C b/gcc/testsuite/g++.dg/pr90981.C
new file mode 100644
index 0000000..5a27302
--- /dev/null
+++ b/gcc/testsuite/g++.dg/pr90981.C
@@ -0,0 +1,8 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -g -gdwarf-5 -gsplit-dwarf" } */
+
+/* No addresses in the DWARF, so no .debug_addr section,
+ don't crash trying to generate an addr index header anyway. */
+
+namespace { struct t {}; }
+t f () { return t (); }
diff --git a/gcc/testsuite/g++.dg/template/crash31.C b/gcc/testsuite/g++.dg/template/crash31.C
index 2269f47..c8732c8 100644
--- a/gcc/testsuite/g++.dg/template/crash31.C
+++ b/gcc/testsuite/g++.dg/template/crash31.C
@@ -1,3 +1,4 @@
// PR c++/19063
-template<operator< struct A {}; // { dg-error "" }
+template<operator< struct A {}; // { dg-error "10:declaration" }
+// { dg-error "expected|extra" "" { target *-*-* } .-1 }
diff --git a/gcc/testsuite/g++.dg/template/crash96.C b/gcc/testsuite/g++.dg/template/crash96.C
index 5c2aa99..d1ce2db 100644
--- a/gcc/testsuite/g++.dg/template/crash96.C
+++ b/gcc/testsuite/g++.dg/template/crash96.C
@@ -2,5 +2,5 @@
template<int> struct A
{
- template<int> template<int> void A::foo() {} // { dg-error "extra qualification" }
+ template<int> template<int> void A::foo() {} // { dg-error "36:extra qualification" }
};
diff --git a/gcc/testsuite/g++.dg/template/operator15.C b/gcc/testsuite/g++.dg/template/operator15.C
new file mode 100644
index 0000000..7554422
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/operator15.C
@@ -0,0 +1,6 @@
+// PR c++/60531
+
+template < class T > T foo ();
+
+bool b1 = foo<int> == foo<int>;
+int (*fp1)() = +foo<int>;
diff --git a/gcc/testsuite/g++.dg/template/operator6.C b/gcc/testsuite/g++.dg/template/operator6.C
index 94a869b..189dcc2 100644
--- a/gcc/testsuite/g++.dg/template/operator6.C
+++ b/gcc/testsuite/g++.dg/template/operator6.C
@@ -1,4 +1,4 @@
// PR c++/27315
// { dg-do compile }
-template void operator+; // { dg-error "non-function" }
+template void operator+; // { dg-error "15:declaration of .operator\\+. as non-function" }
diff --git a/gcc/testsuite/g++.dg/template/operator8.C b/gcc/testsuite/g++.dg/template/operator8.C
index 52f2218..adadc58 100644
--- a/gcc/testsuite/g++.dg/template/operator8.C
+++ b/gcc/testsuite/g++.dg/template/operator8.C
@@ -2,5 +2,6 @@
struct A
{
- template<operator+> void foo() {} // { dg-error "identifier|parameter|template arguments" }
+ template<operator+> void foo() {} // { dg-error "14:declaration" }
+ // { dg-error "expected|template" "" { target *-*-* } .-1 }
};
diff --git a/gcc/testsuite/g++.dg/template/operator9.C b/gcc/testsuite/g++.dg/template/operator9.C
index d4ebad3..c1303ef 100644
--- a/gcc/testsuite/g++.dg/template/operator9.C
+++ b/gcc/testsuite/g++.dg/template/operator9.C
@@ -1,6 +1,7 @@
//PR c++/27670
-template<operator+> void foo(); // { dg-error "before|parameter|template" }
+template<operator+> void foo(); // { dg-error "10:declaration" }
+// { dg-error "expected|template" "" { target *-*-* } .-1 }
void bar()
{
diff --git a/gcc/testsuite/g++.dg/template/pr61745.C b/gcc/testsuite/g++.dg/template/pr61745.C
index da5973e..a44bfa8 100644
--- a/gcc/testsuite/g++.dg/template/pr61745.C
+++ b/gcc/testsuite/g++.dg/template/pr61745.C
@@ -20,5 +20,6 @@ public:
Zp operator-() const { return Zp(p-val); }
// In C++2A, we have an unqualified-id (operator-) followed by
// '<', and name lookup found a function.
- friend Zp<INT,P> operator- <>(const Zp<INT,P>& a, const Zp<INT,P>& b); // { dg-error "declaration|expected" "" { target c++17_down } }
+ friend Zp<INT,P> operator- <>(const Zp<INT,P>& a, const Zp<INT,P>& b); // { dg-error "20:declaration of .operator\\-. as non-function" "" { target c++17_down } }
+ // { dg-error "expected" "" { target c++17_down } .-1 }
};
diff --git a/gcc/testsuite/g++.dg/template/sizeof-template-argument.C b/gcc/testsuite/g++.dg/template/sizeof-template-argument.C
index 31aeeec..2bfff6d 100644
--- a/gcc/testsuite/g++.dg/template/sizeof-template-argument.C
+++ b/gcc/testsuite/g++.dg/template/sizeof-template-argument.C
@@ -3,9 +3,9 @@
template<int> struct A {};
-template<typename> struct B : A <sizeof(=)> {}; /* { dg-error "template argument" } */
+template<typename> struct B : A <sizeof(=)> {}; /* { dg-error "expected primary-expression" } */
-template<typename> struct C : A <sizeof(=)> {}; /* { dg-error "template argument" } */
+template<typename> struct C : A <sizeof(=)> {}; /* { dg-error "expected primary-expression" } */
int a;
diff --git a/gcc/testsuite/g++.dg/template/typedef41.C b/gcc/testsuite/g++.dg/template/typedef41.C
index dc25518..e6619d7 100644
--- a/gcc/testsuite/g++.dg/template/typedef41.C
+++ b/gcc/testsuite/g++.dg/template/typedef41.C
@@ -2,7 +2,7 @@
template<int> struct A
{
- typedef int ::X; // { dg-error "" }
+ typedef int ::X; // { dg-error "15:typedef name" }
};
A<0> a;
diff --git a/gcc/testsuite/g++.dg/torture/pr34850.C b/gcc/testsuite/g++.dg/torture/pr34850.C
index e41620b..60a6c6a 100644
--- a/gcc/testsuite/g++.dg/torture/pr34850.C
+++ b/gcc/testsuite/g++.dg/torture/pr34850.C
@@ -13,7 +13,8 @@ extern "C" {
extern __inline __attribute__ ((__always_inline__)) __attribute__ ((__gnu_inline__, __artificial__))
void * memset (void *__dest, int __ch, size_t __len) throw () {
if (__builtin_constant_p (__len) && __len == 0)
- __warn_memset_zero_len ();
+ __warn_memset_zero_len ();
+ return __dest;
}
}
inline void clear_mem(void* ptr, u32bit n) {
diff --git a/gcc/testsuite/g++.dg/torture/pr90982.C b/gcc/testsuite/g++.dg/torture/pr90982.C
new file mode 100644
index 0000000..8edbb7c
--- /dev/null
+++ b/gcc/testsuite/g++.dg/torture/pr90982.C
@@ -0,0 +1,23 @@
+// { dg-do compile }
+
+template <int n> struct S
+{
+ long c[n];
+ void f (S d)
+ {
+ for (int i = 2;; i++)
+ c[i] &= d.c[i];
+ }
+};
+
+template <int m> struct T:S<m/64>
+{
+ void operator &= (T d)
+ { this -> f (d); }
+};
+
+void g (T<192> &d)
+{
+ T<192> v;
+ d &= v;
+}
diff --git a/gcc/testsuite/g++.dg/tree-ssa/alias-access-path-1.C b/gcc/testsuite/g++.dg/tree-ssa/alias-access-path-1.C
new file mode 100644
index 0000000..ceb0e70
--- /dev/null
+++ b/gcc/testsuite/g++.dg/tree-ssa/alias-access-path-1.C
@@ -0,0 +1,24 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -fdump-tree-fre1" } */
+
+struct a {int a1; int a2;};
+struct b:a {};
+
+struct b bvar,*bptr2;
+int
+test(void)
+{
+ struct a *bptr = &bvar;
+ bptr->a2=0;
+ bptr2->a1=1;
+ return bptr->a2;
+}
+int
+test2(void)
+{
+ struct b *bptr = &bvar;
+ bptr->a2=0;
+ bptr2->a1=1;
+ return bptr->a2;
+}
+/* { dg-final { scan-tree-dump-times "return 0" 2 "fre1" } } */
diff --git a/gcc/testsuite/g++.dg/tree-ssa/cprop-vcond.C b/gcc/testsuite/g++.dg/tree-ssa/cprop-vcond.C
new file mode 100644
index 0000000..7d62cff
--- /dev/null
+++ b/gcc/testsuite/g++.dg/tree-ssa/cprop-vcond.C
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+/* { dg-options "-O -fdump-tree-forwprop1-raw" } */
+
+typedef long vec __attribute__((vector_size(2*sizeof(long))));
+void f(vec*v){
+ vec t = { 5, 16 };
+ vec f = { 27, -11 };
+ vec r = *v ? t : f;
+ *v = -r;
+}
+
+/* { dg-final { scan-tree-dump-not "negate_expr" "forwprop1" } } */
diff --git a/gcc/testsuite/g++.dg/tree-ssa/empty-3.C b/gcc/testsuite/g++.dg/tree-ssa/empty-3.C
new file mode 100644
index 0000000..f340bd4
--- /dev/null
+++ b/gcc/testsuite/g++.dg/tree-ssa/empty-3.C
@@ -0,0 +1,16 @@
+// PR c++/20408
+// { dg-additional-options -fdump-tree-gimple }
+// { dg-final { scan-tree-dump-times "struct Foo" 2 "gimple" } }
+
+struct Foo {};
+void foo(const Foo&);
+void bar(Foo);
+
+void fooc(void)
+{
+ foo(Foo());
+}
+void barc(void)
+{
+ bar(Foo());
+}
diff --git a/gcc/testsuite/g++.dg/tree-ssa/empty-loop.C b/gcc/testsuite/g++.dg/tree-ssa/empty-loop.C
new file mode 100644
index 0000000..6b1e879
--- /dev/null
+++ b/gcc/testsuite/g++.dg/tree-ssa/empty-loop.C
@@ -0,0 +1,33 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-cddce2 -ffinite-loops" } */
+
+#include <string>
+#include <vector>
+#include <list>
+#include <set>
+#include <map>
+
+using namespace std;
+
+int foo (vector<string> &v, list<string> &l, set<string> &s, map<int, string> &m)
+{
+ for (vector<string>::iterator it = v.begin (); it != v.end (); ++it)
+ it->length();
+
+ for (list<string>::iterator it = l.begin (); it != l.end (); ++it)
+ it->length();
+
+ for (map<int, string>::iterator it = m.begin (); it != m.end (); ++it)
+ it->first + it->second.length();
+
+ for (set<string>::iterator it0 = s.begin (); it0 != s.end(); ++it0)
+ for (vector<string>::reverse_iterator it1 = v.rbegin(); it1 != v.rend(); ++it1)
+ {
+ it0->length();
+ it1->length();
+ }
+
+ return 0;
+}
+/* { dg-final { scan-tree-dump-not "if" "cddce2"} } */
+
diff --git a/gcc/testsuite/g++.dg/tree-ssa/final1.C b/gcc/testsuite/g++.dg/tree-ssa/final1.C
new file mode 100644
index 0000000..43407f0
--- /dev/null
+++ b/gcc/testsuite/g++.dg/tree-ssa/final1.C
@@ -0,0 +1,8 @@
+// { dg-do compile { target c++11 } }
+// { dg-additional-options -fdump-tree-gimple }
+// { dg-final { scan-tree-dump-not "vptr" gimple } }
+
+struct A { int i; };
+struct B final: public virtual A { int j; };
+
+int f(B* b) { return b->i; }
diff --git a/gcc/testsuite/g++.dg/tree-ssa/pr19807.C b/gcc/testsuite/g++.dg/tree-ssa/pr19807.C
index cbe06b4..10de295 100644
--- a/gcc/testsuite/g++.dg/tree-ssa/pr19807.C
+++ b/gcc/testsuite/g++.dg/tree-ssa/pr19807.C
@@ -11,7 +11,8 @@ void foo(void)
z = 1 + &a[1];
}
-/* { dg-final { scan-tree-dump-times "&MEM\\\[\\\(void .\\\)&a \\\+ 8B\\\]" 3 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "&MEM\\\[\\\(void .\\\)&a \\\+ 8B\\\]" 3 "optimized" { target { ! store_merge } } } }
+ { dg-final { scan-tree-dump-times "&MEM <int> \\\[\\\(void .\\\)&a \\\+ 8B\\\]" 3 "optimized" { target { store_merge } } } } */
void bar(int i)
diff --git a/gcc/testsuite/g++.dg/tree-ssa/pr20280.C b/gcc/testsuite/g++.dg/tree-ssa/pr20280.C
index ec4dad7..334ed8a 100644
--- a/gcc/testsuite/g++.dg/tree-ssa/pr20280.C
+++ b/gcc/testsuite/g++.dg/tree-ssa/pr20280.C
@@ -44,9 +44,9 @@ void f(X &x, bool b)
(void)(b ? x.i : x.k);
(void)(b ? x.j : x.k);
- g (b ? x.i : x.j); // { dg-error "cannot bind bitfield" }
- g (b ? x.i : x.k); // { dg-error "cannot bind bitfield" }
- g (b ? x.j : x.k); // { dg-error "cannot bind bitfield" }
+ g (b ? x.i : x.j); // { dg-error "cannot bind bit-field" }
+ g (b ? x.i : x.k); // { dg-error "cannot bind bit-field" }
+ g (b ? x.j : x.k); // { dg-error "cannot bind bit-field" }
// It's not entirely clear whether these should be accepted. The
// conditional expressions are lvalues for sure, and 8.5.3/5 exempts
diff --git a/gcc/testsuite/g++.dg/tree-ssa/pr31146.C b/gcc/testsuite/g++.dg/tree-ssa/pr31146.C
index 1a77ea9..665370d 100644
--- a/gcc/testsuite/g++.dg/tree-ssa/pr31146.C
+++ b/gcc/testsuite/g++.dg/tree-ssa/pr31146.C
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O -fdump-tree-forwprop" } */
+/* { dg-options "-O -fdump-tree-forwprop1" } */
/* We should be able to optimize this to i[j] = 1 during
early optimizations. */
@@ -12,4 +12,4 @@ void foo (int j)
*q = 1;
}
-/* { dg-final { scan-tree-dump "MEM\\\[.*&i\\\]\\\[j.*\\\] =.* 1;" "forwprop1" } } */
+/* { dg-final { scan-tree-dump "MEM <int\\\[5\\\]> \\\[.*&i\\\]\\\[j.*\\\] =.* 1;" "forwprop1" } } */
diff --git a/gcc/testsuite/g++.dg/tree-ssa/pr69336.C b/gcc/testsuite/g++.dg/tree-ssa/pr69336.C
index 3bddba1..c946176 100644
--- a/gcc/testsuite/g++.dg/tree-ssa/pr69336.C
+++ b/gcc/testsuite/g++.dg/tree-ssa/pr69336.C
@@ -3,6 +3,7 @@
#include <array>
#include <utility>
+#include <stdexcept>
template<class Key, class T, size_t N> struct static_map
diff --git a/gcc/testsuite/g++.dg/tree-ssa/pr78847.C b/gcc/testsuite/g++.dg/tree-ssa/pr78847.C
index d5a8394..e72e516 100644
--- a/gcc/testsuite/g++.dg/tree-ssa/pr78847.C
+++ b/gcc/testsuite/g++.dg/tree-ssa/pr78847.C
@@ -1,6 +1,6 @@
/* { dg-do compile } */
/* { dg-require-effective-target c++14 } */
-/* { dg-options "-O3 -fdump-tree-ldist" } */
+/* { dg-options "-O3 -fdump-tree-ldist-optimized" } */
#include <stddef.h>
#include <cstring>
@@ -23,4 +23,4 @@ void testWithLoopValue(const Foo foo, size_t ptr, char *buf_) {
buf_[ptr++] = c;
}
-/* { dg-final { scan-tree-dump "memcpy\[^\n\r\]*, 9\\);" "ldist" } } */
+/* { dg-final { scan-tree-dump "split to 0 loops and 1 library calls" "ldist" } } */
diff --git a/gcc/testsuite/g++.dg/tree-ssa/pr80293.C b/gcc/testsuite/g++.dg/tree-ssa/pr80293.C
index 7faf35a..cfdea08 100644
--- a/gcc/testsuite/g++.dg/tree-ssa/pr80293.C
+++ b/gcc/testsuite/g++.dg/tree-ssa/pr80293.C
@@ -2,6 +2,7 @@
// { dg-options "-O2 -std=gnu++11 -fdump-tree-optimized" } */
#include <array>
+#include <cstdint>
// Return a copy of the underlying memory of an arbitrary value.
template <
diff --git a/gcc/testsuite/g++.dg/tree-ssa/pr90883.C b/gcc/testsuite/g++.dg/tree-ssa/pr90883.C
new file mode 100644
index 0000000..c5faffa
--- /dev/null
+++ b/gcc/testsuite/g++.dg/tree-ssa/pr90883.C
@@ -0,0 +1,20 @@
+// { dg-options "-O2 -Os -fdump-tree-dse-details -std=c++11" }
+
+
+ class C
+ {
+ char a[7]{};
+ int b{};
+ };
+
+ C slow()
+ {
+ return {};
+ }
+
+
+// We want to match enough here to capture that we deleted an empty
+// constructor store
+// { dg-final { scan-tree-dump "Deleted redundant store: .*\.a = {}" "dse1" { target { ! i?86-*-* } } } }
+// { dg-final { scan-tree-dump "Deleted redundant store: .*\.a = {}" "dse2" { target i?86-*-* } } }
+
diff --git a/gcc/testsuite/g++.dg/tree-ssa/ssa-dse-1.C b/gcc/testsuite/g++.dg/tree-ssa/ssa-dse-1.C
index 1fd8dec..bed4886 100644
--- a/gcc/testsuite/g++.dg/tree-ssa/ssa-dse-1.C
+++ b/gcc/testsuite/g++.dg/tree-ssa/ssa-dse-1.C
@@ -97,5 +97,5 @@ int main()
}
-/* { dg-final { scan-tree-dump-times "MEM\\\[\\(struct FixBuf \\*\\)&<retval> \\+ \[0-9\]+B\\\] = {}" 1 "dse1" } } */
-
+/* { dg-final { scan-tree-dump-times "MEM\\\[\\(struct FixBuf \\*\\)&<retval> \\+ \[0-9\]+B\\\] = {}" 1 "dse1" { target { ! store_merge } } } }
+ { dg-final { scan-tree-dump-times "MEM <char\\\[\[0-9\]+]> \\\[\\(struct FixBuf \\*\\)&<retval> \\+ \[0-9\]+B\\\] = {}" 1 "dse1" { target { store_merge } } } } */
diff --git a/gcc/testsuite/g++.dg/ubsan/pr63956.C b/gcc/testsuite/g++.dg/ubsan/pr63956.C
index 34b5dd7..3a1596e 100644
--- a/gcc/testsuite/g++.dg/ubsan/pr63956.C
+++ b/gcc/testsuite/g++.dg/ubsan/pr63956.C
@@ -11,7 +11,7 @@ fn1 (int a, int b)
if (b != 2)
a <<= b;
// { dg-error "5 << -2.. is negative" "" { target *-*-* } .-1 }
- // { dg-error "is >= than the precision of the left operand" "" { target *-*-* } .-2 }
+ // { dg-error "is greater than or equal to the precision .. of the left operand" "" { target *-*-* } .-2 }
// { dg-error "-2 << 4.. is negative" "" { target *-*-* } .-3 }
return a;
}
@@ -34,7 +34,7 @@ fn2 (int a, int b)
if (b != 2)
a >>= b;
// { dg-error "4 >> -1.. is negative" "" { target *-*-* } .-1 }
- // { dg-error "is >= than the precision of the left operand" "" { target *-*-* } .-2 }
+ // { dg-error "is greater than or equal to the precision .. of the left operand" "" { target *-*-* } .-2 }
return a;
}
@@ -80,13 +80,13 @@ constexpr int
fn5 (const int *a, int b)
{
if (b != 2)
- b = a[b];
+ b = a[b]; // { dg-error "array subscript" }
return b;
}
constexpr int m1[4] = { 1, 2, 3, 4 };
constexpr int m2 = fn5 (m1, 3);
-constexpr int m3 = fn5 (m1, 4); // { dg-error "array subscript|in .constexpr. expansion of " }
+constexpr int m3 = fn5 (m1, 4); // { dg-message "in .constexpr. expansion of " }
constexpr int
fn6 (const int &a, int b)
@@ -112,11 +112,11 @@ constexpr int
fn8 (int i)
{
constexpr int g[10] = { };
- return g[i];
+ return g[i]; // { dg-error "array subscript" }
}
constexpr int o1 = fn8 (9);
-constexpr int o2 = fn8 (10); // { dg-error "array subscript|in .constexpr. expansion of " }
+constexpr int o2 = fn8 (10); // { dg-message "in .constexpr. expansion of " }
constexpr int
fn9 (int a, int b)
diff --git a/gcc/testsuite/g++.dg/vect/simd-1.cc b/gcc/testsuite/g++.dg/vect/simd-1.cc
new file mode 100644
index 0000000..76ce45d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/vect/simd-1.cc
@@ -0,0 +1,114 @@
+// { dg-require-effective-target vect_simd_clones }
+// { dg-additional-options "-fopenmp-simd" }
+// { dg-additional-options "-mavx" { target avx_runtime } }
+
+#include "../../gcc.dg/vect/tree-vect.h"
+
+int w;
+struct S {
+ int s, &t;
+ int *p;
+ S (int *x) : s (0), t (w), p (x) {};
+ void foo (short &, int &);
+ void bar (short &, int &);
+ void baz (short &, int &);
+ void qux (short &, int &);
+};
+
+__attribute__((noipa)) void
+S::foo (short &x, int &y)
+{
+ int *q = this->p;
+ #pragma omp simd lastprivate (x, s, t) private (y)
+ for (int i = 0; i < 1025; ++i)
+ {
+ y = q[i];
+ x = y;
+ q[i] = y * 2;
+ s = q[i] + 3;
+ t = q[i] + 6;
+ }
+}
+
+__attribute__((noipa)) void
+S::bar (short &x, int &y)
+{
+ #pragma omp simd linear (x) linear (s, t: 2) private (y)
+ for (int i = 0; i < 1025; ++i)
+ {
+ y = p[i];
+ x += y - 2 * i + 1;
+ p[i] = y * 2;
+ s += 2 * y - 4 * i + 2;
+ t += 2 * y - 4 * i + 2;
+ }
+}
+
+__attribute__((noipa)) void
+S::baz (short &x, int &y)
+{
+ int *q = this->p;
+ #pragma omp simd lastprivate (x, s, t) private (y) if (simd: 0)
+ for (int i = 0; i < 1025; ++i)
+ {
+ y = q[i];
+ x = y;
+ q[i] = y * 2;
+ s = q[i] + 3;
+ t = q[i] + 6;
+ }
+}
+
+__attribute__((noipa)) void
+S::qux (short &x, int &y)
+{
+ #pragma omp simd linear (x) linear (s, t: 2) private (y) simdlen (1)
+ for (int i = 0; i < 1025; ++i)
+ {
+ y = p[i];
+ x += y - 2 * i + 1;
+ p[i] = y * 2;
+ s += 2 * y - 4 * i + 2;
+ t += 2 * y - 4 * i + 2;
+ }
+}
+
+int
+main ()
+{
+ short x;
+ int a[1025], y;
+ check_vect ();
+ S s = a;
+ for (int i = 0; i < 1025; ++i)
+ {
+ a[i] = i;
+ asm volatile ("" : "+g" (i));
+ }
+ s.foo (x, y);
+ if (x != 1024 || s.s != 2051 || s.t != 2054)
+ abort ();
+ for (int i = 0; i < 1025; ++i)
+ if (a[i] != 2 * i)
+ abort ();
+ s.bar (x, y);
+ if (x != 2049 || s.s != 4101 || s.t != 4104)
+ abort ();
+ for (int i = 0; i < 1025; ++i)
+ if (a[i] != 4 * i)
+ abort ();
+ else
+ a[i] = i;
+ s.baz (x, y);
+ if (x != 1024 || s.s != 2051 || s.t != 2054)
+ abort ();
+ for (int i = 0; i < 1025; ++i)
+ if (a[i] != 2 * i)
+ abort ();
+ s.qux (x, y);
+ if (x != 2049 || s.s != 4101 || s.t != 4104)
+ abort ();
+ for (int i = 0; i < 1025; ++i)
+ if (a[i] != 4 * i)
+ abort ();
+}
diff --git a/gcc/testsuite/g++.dg/vect/simd-10.cc b/gcc/testsuite/g++.dg/vect/simd-10.cc
new file mode 100644
index 0000000..fa4dc4f
--- /dev/null
+++ b/gcc/testsuite/g++.dg/vect/simd-10.cc
@@ -0,0 +1,8 @@
+// PR tree-optimization/91010
+// { dg-do compile }
+// { dg-require-effective-target size32plus }
+// { dg-additional-options "-fopenmp-simd -fno-tree-forwprop" }
+// { dg-additional-options "-mavx" { target avx_runtime } }
+// { dg-final { scan-tree-dump-times "vectorized \[1-3] loops" 2 "vect" { target i?86-*-* x86_64-*-* } } }
+
+#include "simd-5.cc"
diff --git a/gcc/testsuite/g++.dg/vect/simd-2.cc b/gcc/testsuite/g++.dg/vect/simd-2.cc
new file mode 100644
index 0000000..6f5737b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/vect/simd-2.cc
@@ -0,0 +1,153 @@
+// { dg-require-effective-target size32plus }
+// { dg-additional-options "-fopenmp-simd" }
+// { dg-additional-options "-mavx" { target avx_runtime } }
+// { dg-final { scan-tree-dump-times "vectorized \[1-3] loops" 2 "vect" { target i?86-*-* x86_64-*-* } } }
+
+#include "../../gcc.dg/vect/tree-vect.h"
+
+struct S {
+ inline S ();
+ inline ~S ();
+ inline S (const S &);
+ inline S & operator= (const S &);
+ int s;
+};
+
+S::S () : s (0)
+{
+}
+
+S::~S ()
+{
+}
+
+S::S (const S &x)
+{
+ s = x.s;
+}
+
+S &
+S::operator= (const S &x)
+{
+ s = x.s;
+ return *this;
+}
+
+static inline void
+ini (S &x)
+{
+ x.s = 0;
+}
+
+S r, a[1024], b[1024];
+
+#pragma omp declare reduction (+: S: omp_out.s += omp_in.s)
+#pragma omp declare reduction (plus: S: omp_out.s += omp_in.s) initializer (ini (omp_priv))
+
+__attribute__((noipa)) void
+foo (S *a, S *b)
+{
+ #pragma omp simd reduction (inscan, +:r)
+ for (int i = 0; i < 1024; i++)
+ {
+ r.s += a[i].s;
+ #pragma omp scan inclusive(r)
+ b[i] = r;
+ }
+}
+
+__attribute__((noipa)) S
+bar (void)
+{
+ S s;
+ #pragma omp simd reduction (inscan, plus:s)
+ for (int i = 0; i < 1024; i++)
+ {
+ s.s += 2 * a[i].s;
+ #pragma omp scan inclusive(s)
+ b[i] = s;
+ }
+ return S (s);
+}
+
+__attribute__((noipa)) void
+baz (S *a, S *b)
+{
+ #pragma omp simd reduction (inscan, +:r) simdlen(1)
+ for (int i = 0; i < 1024; i++)
+ {
+ r.s += a[i].s;
+ #pragma omp scan inclusive(r)
+ b[i] = r;
+ }
+}
+
+__attribute__((noipa)) S
+qux (void)
+{
+ S s;
+ #pragma omp simd if (0) reduction (inscan, plus:s)
+ for (int i = 0; i < 1024; i++)
+ {
+ s.s += 2 * a[i].s;
+ #pragma omp scan inclusive(s)
+ b[i] = s;
+ }
+ return S (s);
+}
+
+int
+main ()
+{
+ S s;
+ check_vect ();
+ for (int i = 0; i < 1024; ++i)
+ {
+ a[i].s = i;
+ b[i].s = -1;
+ asm ("" : "+g" (i));
+ }
+ foo (a, b);
+ if (r.s != 1024 * 1023 / 2)
+ abort ();
+ for (int i = 0; i < 1024; ++i)
+ {
+ s.s += i;
+ if (b[i].s != s.s)
+ abort ();
+ else
+ b[i].s = 25;
+ }
+ if (bar ().s != 1024 * 1023)
+ abort ();
+ s.s = 0;
+ for (int i = 0; i < 1024; ++i)
+ {
+ s.s += 2 * i;
+ if (b[i].s != s.s)
+ abort ();
+ }
+ r.s = 0;
+ baz (a, b);
+ if (r.s != 1024 * 1023 / 2)
+ abort ();
+ s.s = 0;
+ for (int i = 0; i < 1024; ++i)
+ {
+ s.s += i;
+ if (b[i].s != s.s)
+ abort ();
+ else
+ b[i].s = 25;
+ }
+ if (qux ().s != 1024 * 1023)
+ abort ();
+ s.s = 0;
+ for (int i = 0; i < 1024; ++i)
+ {
+ s.s += 2 * i;
+ if (b[i].s != s.s)
+ abort ();
+ }
+ return 0;
+}
diff --git a/gcc/testsuite/g++.dg/vect/simd-3.cc b/gcc/testsuite/g++.dg/vect/simd-3.cc
new file mode 100644
index 0000000..d998171
--- /dev/null
+++ b/gcc/testsuite/g++.dg/vect/simd-3.cc
@@ -0,0 +1,120 @@
+// { dg-require-effective-target size32plus }
+// { dg-additional-options "-fopenmp-simd" }
+// { dg-additional-options "-mavx" { target avx_runtime } }
+// { dg-final { scan-tree-dump-times "vectorized \[1-3] loops" 2 "vect" { target i?86-*-* x86_64-*-* } } } */
+
+#include "../../gcc.dg/vect/tree-vect.h"
+
+int r, a[1024], b[1024], q;
+
+__attribute__((noipa)) void
+foo (int *a, int *b, int &r)
+{
+ #pragma omp simd reduction (inscan, +:r)
+ for (int i = 0; i < 1024; i++)
+ {
+ r += a[i];
+ #pragma omp scan inclusive(r)
+ b[i] = r;
+ }
+}
+
+__attribute__((noipa)) int
+bar (void)
+{
+ int &s = q;
+ q = 0;
+ #pragma omp simd reduction (inscan, +:s)
+ for (int i = 0; i < 1024; i++)
+ {
+ s += 2 * a[i];
+ #pragma omp scan inclusive(s)
+ b[i] = s;
+ }
+ return s;
+}
+
+__attribute__((noipa)) void
+baz (int *a, int *b, int &r)
+{
+ #pragma omp simd reduction (inscan, +:r) if (simd: 0)
+ for (int i = 0; i < 1024; i++)
+ {
+ r += a[i];
+ #pragma omp scan inclusive(r)
+ b[i] = r;
+ }
+}
+
+__attribute__((noipa)) int
+qux (void)
+{
+ int &s = q;
+ q = 0;
+ #pragma omp simd reduction (inscan, +:s) simdlen (1)
+ for (int i = 0; i < 1024; i++)
+ {
+ s += 2 * a[i];
+ #pragma omp scan inclusive(s)
+ b[i] = s;
+ }
+ return s;
+}
+
+int
+main ()
+{
+ int s = 0;
+ check_vect ();
+ for (int i = 0; i < 1024; ++i)
+ {
+ a[i] = i;
+ b[i] = -1;
+ asm ("" : "+g" (i));
+ }
+ foo (a, b, r);
+ if (r != 1024 * 1023 / 2)
+ abort ();
+ for (int i = 0; i < 1024; ++i)
+ {
+ s += i;
+ if (b[i] != s)
+ abort ();
+ else
+ b[i] = 25;
+ }
+ if (bar () != 1024 * 1023)
+ abort ();
+ s = 0;
+ for (int i = 0; i < 1024; ++i)
+ {
+ s += 2 * i;
+ if (b[i] != s)
+ abort ();
+ else
+ b[i] = -1;
+ }
+ r = 0;
+ baz (a, b, r);
+ if (r != 1024 * 1023 / 2)
+ abort ();
+ s = 0;
+ for (int i = 0; i < 1024; ++i)
+ {
+ s += i;
+ if (b[i] != s)
+ abort ();
+ else
+ b[i] = -25;
+ }
+ if (qux () != 1024 * 1023)
+ abort ();
+ s = 0;
+ for (int i = 0; i < 1024; ++i)
+ {
+ s += 2 * i;
+ if (b[i] != s)
+ abort ();
+ }
+ return 0;
+}
diff --git a/gcc/testsuite/g++.dg/vect/simd-4.cc b/gcc/testsuite/g++.dg/vect/simd-4.cc
new file mode 100644
index 0000000..8f31989
--- /dev/null
+++ b/gcc/testsuite/g++.dg/vect/simd-4.cc
@@ -0,0 +1,122 @@
+// { dg-require-effective-target size32plus }
+// { dg-additional-options "-fopenmp-simd" }
+// { dg-additional-options "-mavx" { target avx_runtime } }
+// { dg-final { scan-tree-dump-times "vectorized \[1-3] loops" 2 "vect" { target i?86-*-* x86_64-*-* } } }
+
+#include "../../gcc.dg/vect/tree-vect.h"
+
+int r, a[1024], b[1024], q;
+
+#pragma omp declare reduction (foo: int: omp_out += omp_in) initializer (omp_priv = 0)
+
+__attribute__((noipa)) void
+foo (int *a, int *b, int &r)
+{
+ #pragma omp simd reduction (inscan, foo:r)
+ for (int i = 0; i < 1024; i++)
+ {
+ r += a[i];
+ #pragma omp scan inclusive(r)
+ b[i] = r;
+ }
+}
+
+__attribute__((noipa)) int
+bar (void)
+{
+ int &s = q;
+ q = 0;
+ #pragma omp simd reduction (inscan, foo:s)
+ for (int i = 0; i < 1024; i++)
+ {
+ s += 2 * a[i];
+ #pragma omp scan inclusive(s)
+ b[i] = s;
+ }
+ return s;
+}
+
+__attribute__((noipa)) void
+baz (int *a, int *b, int &r)
+{
+ #pragma omp simd reduction (inscan, foo:r) if (simd: 0)
+ for (int i = 0; i < 1024; i++)
+ {
+ r += a[i];
+ #pragma omp scan inclusive(r)
+ b[i] = r;
+ }
+}
+
+__attribute__((noipa)) int
+qux (void)
+{
+ int &s = q;
+ q = 0;
+ #pragma omp simd reduction (inscan, foo:s) simdlen (1)
+ for (int i = 0; i < 1024; i++)
+ {
+ s += 2 * a[i];
+ #pragma omp scan inclusive(s)
+ b[i] = s;
+ }
+ return s;
+}
+
+int
+main ()
+{
+ int s = 0;
+ check_vect ();
+ for (int i = 0; i < 1024; ++i)
+ {
+ a[i] = i;
+ b[i] = -1;
+ asm ("" : "+g" (i));
+ }
+ foo (a, b, r);
+ if (r != 1024 * 1023 / 2)
+ abort ();
+ for (int i = 0; i < 1024; ++i)
+ {
+ s += i;
+ if (b[i] != s)
+ abort ();
+ else
+ b[i] = 25;
+ }
+ if (bar () != 1024 * 1023)
+ abort ();
+ s = 0;
+ for (int i = 0; i < 1024; ++i)
+ {
+ s += 2 * i;
+ if (b[i] != s)
+ abort ();
+ else
+ b[i] = -1;
+ }
+ r = 0;
+ baz (a, b, r);
+ if (r != 1024 * 1023 / 2)
+ abort ();
+ s = 0;
+ for (int i = 0; i < 1024; ++i)
+ {
+ s += i;
+ if (b[i] != s)
+ abort ();
+ else
+ b[i] = -25;
+ }
+ if (qux () != 1024 * 1023)
+ abort ();
+ s = 0;
+ for (int i = 0; i < 1024; ++i)
+ {
+ s += 2 * i;
+ if (b[i] != s)
+ abort ();
+ }
+ return 0;
+}
diff --git a/gcc/testsuite/g++.dg/vect/simd-5.cc b/gcc/testsuite/g++.dg/vect/simd-5.cc
new file mode 100644
index 0000000..dd817b8
--- /dev/null
+++ b/gcc/testsuite/g++.dg/vect/simd-5.cc
@@ -0,0 +1,153 @@
+// { dg-require-effective-target size32plus }
+// { dg-additional-options "-fopenmp-simd" }
+// { dg-additional-options "-mavx" { target avx_runtime } }
+// { dg-final { scan-tree-dump-times "vectorized \[1-3] loops" 2 "vect" { target i?86-*-* x86_64-*-* } } }
+
+#include "../../gcc.dg/vect/tree-vect.h"
+
+struct S {
+ inline S ();
+ inline ~S ();
+ inline S (const S &);
+ inline S & operator= (const S &);
+ int s;
+};
+
+S::S () : s (0)
+{
+}
+
+S::~S ()
+{
+}
+
+S::S (const S &x)
+{
+ s = x.s;
+}
+
+S &
+S::operator= (const S &x)
+{
+ s = x.s;
+ return *this;
+}
+
+static inline void
+ini (S &x)
+{
+ x.s = 0;
+}
+
+S r, a[1024], b[1024];
+
+#pragma omp declare reduction (+: S: omp_out.s += omp_in.s)
+#pragma omp declare reduction (plus: S: omp_out.s += omp_in.s) initializer (ini (omp_priv))
+
+__attribute__((noipa)) void
+foo (S *a, S *b, S &r)
+{
+ #pragma omp simd reduction (inscan, +:r)
+ for (int i = 0; i < 1024; i++)
+ {
+ r.s += a[i].s;
+ #pragma omp scan inclusive(r)
+ b[i] = r;
+ }
+}
+
+__attribute__((noipa)) S
+bar (void)
+{
+ S s;
+ #pragma omp simd reduction (inscan, plus:s)
+ for (int i = 0; i < 1024; i++)
+ {
+ s.s += 2 * a[i].s;
+ #pragma omp scan inclusive(s)
+ b[i] = s;
+ }
+ return s;
+}
+
+__attribute__((noipa)) void
+baz (S *a, S *b, S &r)
+{
+ #pragma omp simd reduction (inscan, +:r) simdlen(1)
+ for (int i = 0; i < 1024; i++)
+ {
+ r.s += a[i].s;
+ #pragma omp scan inclusive(r)
+ b[i] = r;
+ }
+}
+
+__attribute__((noipa)) S
+qux (void)
+{
+ S s;
+ #pragma omp simd if (0) reduction (inscan, plus:s)
+ for (int i = 0; i < 1024; i++)
+ {
+ s.s += 2 * a[i].s;
+ #pragma omp scan inclusive(s)
+ b[i] = s;
+ }
+ return s;
+}
+
+int
+main ()
+{
+ S s;
+ check_vect ();
+ for (int i = 0; i < 1024; ++i)
+ {
+ a[i].s = i;
+ b[i].s = -1;
+ asm ("" : "+g" (i));
+ }
+ foo (a, b, r);
+ if (r.s != 1024 * 1023 / 2)
+ abort ();
+ for (int i = 0; i < 1024; ++i)
+ {
+ s.s += i;
+ if (b[i].s != s.s)
+ abort ();
+ else
+ b[i].s = 25;
+ }
+ if (bar ().s != 1024 * 1023)
+ abort ();
+ s.s = 0;
+ for (int i = 0; i < 1024; ++i)
+ {
+ s.s += 2 * i;
+ if (b[i].s != s.s)
+ abort ();
+ }
+ r.s = 0;
+ baz (a, b, r);
+ if (r.s != 1024 * 1023 / 2)
+ abort ();
+ s.s = 0;
+ for (int i = 0; i < 1024; ++i)
+ {
+ s.s += i;
+ if (b[i].s != s.s)
+ abort ();
+ else
+ b[i].s = 25;
+ }
+ if (qux ().s != 1024 * 1023)
+ abort ();
+ s.s = 0;
+ for (int i = 0; i < 1024; ++i)
+ {
+ s.s += 2 * i;
+ if (b[i].s != s.s)
+ abort ();
+ }
+ return 0;
+}
diff --git a/gcc/testsuite/g++.dg/vect/simd-6.cc b/gcc/testsuite/g++.dg/vect/simd-6.cc
new file mode 100644
index 0000000..997f7b1
--- /dev/null
+++ b/gcc/testsuite/g++.dg/vect/simd-6.cc
@@ -0,0 +1,161 @@
+// { dg-require-effective-target size32plus }
+// { dg-additional-options "-fopenmp-simd" }
+// { dg-additional-options "-mavx" { target avx_runtime } }
+// { dg-final { scan-tree-dump-times "vectorized \[1-3] loops" 2 "vect" { xfail *-*-* } } }
+
+#include "../../gcc.dg/vect/tree-vect.h"
+
+template <typename T>
+struct S {
+ inline S ();
+ inline ~S ();
+ inline S (const S &);
+ inline S & operator= (const S &);
+ T s;
+};
+
+template <typename T>
+S<T>::S () : s (0)
+{
+}
+
+template <typename T>
+S<T>::~S ()
+{
+}
+
+template <typename T>
+S<T>::S (const S &x)
+{
+ s = x.s;
+}
+
+template <typename T>
+S<T> &
+S<T>::operator= (const S &x)
+{
+ s = x.s;
+ return *this;
+}
+
+template <typename T>
+static inline void
+ini (S<T> &x)
+{
+ x.s = 0;
+}
+
+S<int> r, a[1024], b[1024];
+
+#pragma omp declare reduction (+: S<int>: omp_out.s += omp_in.s)
+#pragma omp declare reduction (plus: S<int>: omp_out.s += omp_in.s) initializer (ini (omp_priv))
+
+template <typename T>
+__attribute__((noipa)) void
+foo (S<T> *a, S<T> *b)
+{
+ #pragma omp simd reduction (inscan, +:r)
+ for (int i = 0; i < 1024; i++)
+ {
+ b[i] = r;
+ #pragma omp scan exclusive(r)
+ r.s += a[i].s;
+ }
+}
+
+template <typename T>
+__attribute__((noipa)) S<T>
+bar (void)
+{
+ S<T> s;
+ #pragma omp simd reduction (inscan, plus:s)
+ for (int i = 0; i < 1024; i++)
+ {
+ b[i] = s;
+ #pragma omp scan exclusive(s)
+ s.s += 2 * a[i].s;
+ }
+ return S<T> (s);
+}
+
+__attribute__((noipa)) void
+baz (S<int> *a, S<int> *b)
+{
+ #pragma omp simd reduction (inscan, +:r) simdlen(1)
+ for (int i = 0; i < 1024; i++)
+ {
+ b[i] = r;
+ #pragma omp scan exclusive(r)
+ r.s += a[i].s;
+ }
+}
+
+__attribute__((noipa)) S<int>
+qux (void)
+{
+ S<int> s;
+ #pragma omp simd if (0) reduction (inscan, plus:s)
+ for (int i = 0; i < 1024; i++)
+ {
+ b[i] = s;
+ #pragma omp scan exclusive(s)
+ s.s += 2 * a[i].s;
+ }
+ return S<int> (s);
+}
+
+int
+main ()
+{
+ S<int> s;
+ check_vect ();
+ for (int i = 0; i < 1024; ++i)
+ {
+ a[i].s = i;
+ b[i].s = -1;
+ asm ("" : "+g" (i));
+ }
+ foo (a, b);
+ if (r.s != 1024 * 1023 / 2)
+ abort ();
+ for (int i = 0; i < 1024; ++i)
+ {
+ if (b[i].s != s.s)
+ abort ();
+ else
+ b[i].s = 25;
+ s.s += i;
+ }
+ if (bar<int> ().s != 1024 * 1023)
+ abort ();
+ s.s = 0;
+ for (int i = 0; i < 1024; ++i)
+ {
+ if (b[i].s != s.s)
+ abort ();
+ s.s += 2 * i;
+ }
+ r.s = 0;
+ baz (a, b);
+ if (r.s != 1024 * 1023 / 2)
+ abort ();
+ s.s = 0;
+ for (int i = 0; i < 1024; ++i)
+ {
+ if (b[i].s != s.s)
+ abort ();
+ else
+ b[i].s = 25;
+ s.s += i;
+ }
+ if (qux ().s != 1024 * 1023)
+ abort ();
+ s.s = 0;
+ for (int i = 0; i < 1024; ++i)
+ {
+ if (b[i].s != s.s)
+ abort ();
+ s.s += 2 * i;
+ }
+ return 0;
+}
diff --git a/gcc/testsuite/g++.dg/vect/simd-7.cc b/gcc/testsuite/g++.dg/vect/simd-7.cc
new file mode 100644
index 0000000..1467849
--- /dev/null
+++ b/gcc/testsuite/g++.dg/vect/simd-7.cc
@@ -0,0 +1,124 @@
+// { dg-require-effective-target size32plus }
+// { dg-additional-options "-fopenmp-simd" }
+// { dg-additional-options "-mavx" { target avx_runtime } }
+// { dg-final { scan-tree-dump-times "vectorized \[1-3] loops" 2 "vect" { target i?86-*-* x86_64-*-* } } } */
+
+#include "../../gcc.dg/vect/tree-vect.h"
+
+int r, a[1024], b[1024], q;
+
+template <typename T, typename U>
+__attribute__((noipa)) void
+foo (T a, T b, U r)
+{
+ #pragma omp simd reduction (inscan, +:r)
+ for (int i = 0; i < 1024; i++)
+ {
+ b[i] = r;
+ #pragma omp scan exclusive(r)
+ r += a[i];
+ }
+}
+
+template <typename T>
+__attribute__((noipa)) T
+bar (void)
+{
+ T &s = q;
+ q = 0;
+ #pragma omp simd reduction (inscan, +:s)
+ for (int i = 0; i < 1024; i++)
+ {
+ b[i] = s;
+ #pragma omp scan exclusive(s)
+ s += 2 * a[i];
+ }
+ return s;
+}
+
+template <typename T>
+__attribute__((noipa)) void
+baz (T *a, T *b, T &r)
+{
+ #pragma omp simd reduction (inscan, +:r) if (simd: 0)
+ for (T i = 0; i < 1024; i++)
+ {
+ b[i] = r;
+ #pragma omp scan exclusive(r)
+ r += a[i];
+ }
+}
+
+template <typename T>
+__attribute__((noipa)) int
+qux (void)
+{
+ T s = q;
+ q = 0;
+ #pragma omp simd reduction (inscan, +:s) simdlen (1)
+ for (int i = 0; i < 1024; i++)
+ {
+ b[i] = s;
+ #pragma omp scan exclusive(s)
+ s += 2 * a[i];
+ }
+ return s;
+}
+
+int
+main ()
+{
+ int s = 0;
+ check_vect ();
+ for (int i = 0; i < 1024; ++i)
+ {
+ a[i] = i;
+ b[i] = -1;
+ asm ("" : "+g" (i));
+ }
+ foo<int *, int &> (a, b, r);
+ if (r != 1024 * 1023 / 2)
+ abort ();
+ for (int i = 0; i < 1024; ++i)
+ {
+ if (b[i] != s)
+ abort ();
+ else
+ b[i] = 25;
+ s += i;
+ }
+ if (bar<int> () != 1024 * 1023)
+ abort ();
+ s = 0;
+ for (int i = 0; i < 1024; ++i)
+ {
+ if (b[i] != s)
+ abort ();
+ else
+ b[i] = -1;
+ s += 2 * i;
+ }
+ r = 0;
+ baz<int> (a, b, r);
+ if (r != 1024 * 1023 / 2)
+ abort ();
+ s = 0;
+ for (int i = 0; i < 1024; ++i)
+ {
+ if (b[i] != s)
+ abort ();
+ else
+ b[i] = -25;
+ s += i;
+ }
+ if (qux<int &> () != 1024 * 1023)
+ abort ();
+ s = 0;
+ for (int i = 0; i < 1024; ++i)
+ {
+ if (b[i] != s)
+ abort ();
+ s += 2 * i;
+ }
+ return 0;
+}
diff --git a/gcc/testsuite/g++.dg/vect/simd-8.cc b/gcc/testsuite/g++.dg/vect/simd-8.cc
new file mode 100644
index 0000000..8e297e2
--- /dev/null
+++ b/gcc/testsuite/g++.dg/vect/simd-8.cc
@@ -0,0 +1,122 @@
+// { dg-require-effective-target size32plus }
+// { dg-additional-options "-fopenmp-simd" }
+// { dg-additional-options "-mavx" { target avx_runtime } }
+// { dg-final { scan-tree-dump-times "vectorized \[1-3] loops" 2 "vect" { target i?86-*-* x86_64-*-* } } }
+
+#include "../../gcc.dg/vect/tree-vect.h"
+
+int r, a[1024], b[1024], q;
+
+#pragma omp declare reduction (foo: int: omp_out += omp_in) initializer (omp_priv = 0)
+
+__attribute__((noipa)) void
+foo (int *a, int *b, int &r)
+{
+ #pragma omp simd reduction (inscan, foo:r)
+ for (int i = 0; i < 1024; i++)
+ {
+ b[i] = r;
+ #pragma omp scan exclusive(r)
+ r += a[i];
+ }
+}
+
+__attribute__((noipa)) int
+bar (void)
+{
+ int &s = q;
+ q = 0;
+ #pragma omp simd reduction (inscan, foo:s)
+ for (int i = 0; i < 1024; i++)
+ {
+ b[i] = s;
+ #pragma omp scan exclusive(s)
+ s += 2 * a[i];
+ }
+ return s;
+}
+
+__attribute__((noipa)) void
+baz (int *a, int *b, int &r)
+{
+ #pragma omp simd reduction (inscan, foo:r) if (simd: 0)
+ for (int i = 0; i < 1024; i++)
+ {
+ b[i] = r;
+ #pragma omp scan exclusive(r)
+ r += a[i];
+ }
+}
+
+__attribute__((noipa)) int
+qux (void)
+{
+ int &s = q;
+ q = 0;
+ #pragma omp simd reduction (inscan, foo:s) simdlen (1)
+ for (int i = 0; i < 1024; i++)
+ {
+ b[i] = s;
+ #pragma omp scan exclusive(s)
+ s += 2 * a[i];
+ }
+ return s;
+}
+
+int
+main ()
+{
+ int s = 0;
+ check_vect ();
+ for (int i = 0; i < 1024; ++i)
+ {
+ a[i] = i;
+ b[i] = -1;
+ asm ("" : "+g" (i));
+ }
+ foo (a, b, r);
+ if (r != 1024 * 1023 / 2)
+ abort ();
+ for (int i = 0; i < 1024; ++i)
+ {
+ if (b[i] != s)
+ abort ();
+ else
+ b[i] = 25;
+ s += i;
+ }
+ if (bar () != 1024 * 1023)
+ abort ();
+ s = 0;
+ for (int i = 0; i < 1024; ++i)
+ {
+ if (b[i] != s)
+ abort ();
+ else
+ b[i] = -1;
+ s += 2 * i;
+ }
+ r = 0;
+ baz (a, b, r);
+ if (r != 1024 * 1023 / 2)
+ abort ();
+ s = 0;
+ for (int i = 0; i < 1024; ++i)
+ {
+ if (b[i] != s)
+ abort ();
+ else
+ b[i] = -25;
+ s += i;
+ }
+ if (qux () != 1024 * 1023)
+ abort ();
+ s = 0;
+ for (int i = 0; i < 1024; ++i)
+ {
+ if (b[i] != s)
+ abort ();
+ s += 2 * i;
+ }
+ return 0;
+}
diff --git a/gcc/testsuite/g++.dg/vect/simd-9.cc b/gcc/testsuite/g++.dg/vect/simd-9.cc
new file mode 100644
index 0000000..bfef445
--- /dev/null
+++ b/gcc/testsuite/g++.dg/vect/simd-9.cc
@@ -0,0 +1,153 @@
+// { dg-require-effective-target size32plus }
+// { dg-additional-options "-fopenmp-simd" }
+// { dg-additional-options "-mavx" { target avx_runtime } }
+// { dg-final { scan-tree-dump-times "vectorized \[1-3] loops" 2 "vect" { xfail *-*-* } } }
+
+#include "../../gcc.dg/vect/tree-vect.h"
+
+struct S {
+ inline S ();
+ inline ~S ();
+ inline S (const S &);
+ inline S & operator= (const S &);
+ int s;
+};
+
+S::S () : s (0)
+{
+}
+
+S::~S ()
+{
+}
+
+S::S (const S &x)
+{
+ s = x.s;
+}
+
+S &
+S::operator= (const S &x)
+{
+ s = x.s;
+ return *this;
+}
+
+static inline void
+ini (S &x)
+{
+ x.s = 0;
+}
+
+S r, a[1024], b[1024];
+
+#pragma omp declare reduction (+: S: omp_out.s += omp_in.s)
+#pragma omp declare reduction (plus: S: omp_out.s += omp_in.s) initializer (ini (omp_priv))
+
+__attribute__((noipa)) void
+foo (S *a, S *b, S &r)
+{
+ #pragma omp simd reduction (inscan, +:r)
+ for (int i = 0; i < 1024; i++)
+ {
+ b[i] = r;
+ #pragma omp scan exclusive(r)
+ r.s += a[i].s;
+ }
+}
+
+__attribute__((noipa)) S
+bar (void)
+{
+ S s;
+ #pragma omp simd reduction (inscan, plus:s)
+ for (int i = 0; i < 1024; i++)
+ {
+ b[i] = s;
+ #pragma omp scan exclusive(s)
+ s.s += 2 * a[i].s;
+ }
+ return s;
+}
+
+__attribute__((noipa)) void
+baz (S *a, S *b, S &r)
+{
+ #pragma omp simd reduction (inscan, +:r) simdlen(1)
+ for (int i = 0; i < 1024; i++)
+ {
+ b[i] = r;
+ #pragma omp scan exclusive(r)
+ r.s += a[i].s;
+ }
+}
+
+__attribute__((noipa)) S
+qux (void)
+{
+ S s;
+ #pragma omp simd if (0) reduction (inscan, plus:s)
+ for (int i = 0; i < 1024; i++)
+ {
+ b[i] = s;
+ #pragma omp scan exclusive(s)
+ s.s += 2 * a[i].s;
+ }
+ return s;
+}
+
+int
+main ()
+{
+ S s;
+ check_vect ();
+ for (int i = 0; i < 1024; ++i)
+ {
+ a[i].s = i;
+ b[i].s = -1;
+ asm ("" : "+g" (i));
+ }
+ foo (a, b, r);
+ if (r.s != 1024 * 1023 / 2)
+ abort ();
+ for (int i = 0; i < 1024; ++i)
+ {
+ if (b[i].s != s.s)
+ abort ();
+ else
+ b[i].s = 25;
+ s.s += i;
+ }
+ if (bar ().s != 1024 * 1023)
+ abort ();
+ s.s = 0;
+ for (int i = 0; i < 1024; ++i)
+ {
+ if (b[i].s != s.s)
+ abort ();
+ s.s += 2 * i;
+ }
+ r.s = 0;
+ baz (a, b, r);
+ if (r.s != 1024 * 1023 / 2)
+ abort ();
+ s.s = 0;
+ for (int i = 0; i < 1024; ++i)
+ {
+ if (b[i].s != s.s)
+ abort ();
+ else
+ b[i].s = 25;
+ s.s += i;
+ }
+ if (qux ().s != 1024 * 1023)
+ abort ();
+ s.s = 0;
+ for (int i = 0; i < 1024; ++i)
+ {
+ if (b[i].s != s.s)
+ abort ();
+ s.s += 2 * i;
+ }
+ return 0;
+}
diff --git a/gcc/testsuite/g++.dg/warn/Wbool-operation-1.C b/gcc/testsuite/g++.dg/warn/Wbool-operation-1.C
index 4512b85..82e9ead 100644
--- a/gcc/testsuite/g++.dg/warn/Wbool-operation-1.C
+++ b/gcc/testsuite/g++.dg/warn/Wbool-operation-1.C
@@ -6,6 +6,6 @@ template <class c>
decltype (~c{})
call ()
{
- return ~false; // { dg-warning "on an expression of type bool" }
+ return ~false; // { dg-warning "on an expression of type 'bool'" }
}
template int call<bool>();
diff --git a/gcc/testsuite/g++.dg/warn/Wfloat-equal-1.C b/gcc/testsuite/g++.dg/warn/Wfloat-equal-1.C
index 36b3fa5..1b23611 100644
--- a/gcc/testsuite/g++.dg/warn/Wfloat-equal-1.C
+++ b/gcc/testsuite/g++.dg/warn/Wfloat-equal-1.C
@@ -4,7 +4,7 @@
double a, b;
_Complex double c, d;
-int f(void) { return a == b; } /* { dg-warning "comparing floating point" } */
-int g(void) { return c == d; } /* { dg-warning "comparing floating point" } */
-int h(void) { return a != b; } /* { dg-warning "comparing floating point" } */
-int i(void) { return c != d; } /* { dg-warning "comparing floating point" } */
+int f(void) { return a == b; } /* { dg-warning "comparing floating-point" } */
+int g(void) { return c == d; } /* { dg-warning "comparing floating-point" } */
+int h(void) { return a != b; } /* { dg-warning "comparing floating-point" } */
+int i(void) { return c != d; } /* { dg-warning "comparing floating-point" } */
diff --git a/gcc/testsuite/g++.dg/warn/Wimplicit-fallthrough-4.C b/gcc/testsuite/g++.dg/warn/Wimplicit-fallthrough-4.C
new file mode 100644
index 0000000..993e695
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Wimplicit-fallthrough-4.C
@@ -0,0 +1,22 @@
+// PR c++/91024
+// { dg-do compile { target c++11 } }
+// { dg-options "-Wimplicit-fallthrough" }
+
+int
+foo (char c)
+{
+ int result = 0;
+
+ switch (c)
+ {
+ case 'O':
+ case 'K':
+ return result;
+ [[unlikely]] case 'X': // { dg-bogus "this statement may fall through" }
+ case 'x': // { dg-bogus "here" }
+ return result;
+ default:
+ break;
+ }
+ return result;
+}
diff --git a/gcc/testsuite/g++.dg/warn/Winaccessible-base-1.C b/gcc/testsuite/g++.dg/warn/Winaccessible-base-1.C
new file mode 100644
index 0000000..2e32b0b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Winaccessible-base-1.C
@@ -0,0 +1,7 @@
+// PR c++/90449
+
+struct A { int a; };
+
+struct B : A { };
+
+struct C : B, A { }; // { dg-warning "direct base 'A' inaccessible in 'C' due to ambiguity" }
diff --git a/gcc/testsuite/g++.dg/warn/Winaccessible-base-2.C b/gcc/testsuite/g++.dg/warn/Winaccessible-base-2.C
new file mode 100644
index 0000000..67bd740
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Winaccessible-base-2.C
@@ -0,0 +1,8 @@
+// PR c++/90449
+// { dg-options -Wno-inaccessible-base }
+
+struct A { int a; };
+
+struct B : A { };
+
+struct C : B, A { }; // { dg-bogus "direct base 'A' inaccessible in 'C' due to ambiguity" }
diff --git a/gcc/testsuite/g++.dg/warn/Winaccessible-virtual-base-1.C b/gcc/testsuite/g++.dg/warn/Winaccessible-virtual-base-1.C
new file mode 100644
index 0000000..051fcc6
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Winaccessible-virtual-base-1.C
@@ -0,0 +1,10 @@
+// PR c++/90449
+// { dg-options -Wextra }
+
+struct A { };
+
+struct B : virtual A { };
+
+struct C : A { };
+
+struct D : B, C { }; // { dg-warning "virtual base 'A' inaccessible in 'D' due to ambiguity" }
diff --git a/gcc/testsuite/g++.dg/warn/Winaccessible-virtual-base-2.C b/gcc/testsuite/g++.dg/warn/Winaccessible-virtual-base-2.C
new file mode 100644
index 0000000..eab9ec0
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Winaccessible-virtual-base-2.C
@@ -0,0 +1,10 @@
+// PR c++/90449
+// { dg-options "-Wextra -Wno-inaccessible-base" }
+
+struct A { };
+
+struct B : virtual A { };
+
+struct C : A { };
+
+struct D : B, C { }; // { dg-bogus "virtual base 'A' inaccessible in 'D' due to ambiguity" }
diff --git a/gcc/testsuite/g++.dg/warn/Wrestrict-1.C b/gcc/testsuite/g++.dg/warn/Wrestrict-1.C
index fe844f1..441ff34 100644
--- a/gcc/testsuite/g++.dg/warn/Wrestrict-1.C
+++ b/gcc/testsuite/g++.dg/warn/Wrestrict-1.C
@@ -7,6 +7,6 @@ void foo (char *__restrict, char *__restrict = __null);
void
bar (char *p)
{
- foo (p, p); // { dg-warning "to restrict-qualified parameter aliases with" }
+ foo (p, p); // { dg-warning "to 'restrict'-qualified parameter aliases with" }
foo (p);
}
diff --git a/gcc/testsuite/g++.dg/warn/Wrestrict-2.C b/gcc/testsuite/g++.dg/warn/Wrestrict-2.C
index 4bab03b..72957d0 100644
--- a/gcc/testsuite/g++.dg/warn/Wrestrict-2.C
+++ b/gcc/testsuite/g++.dg/warn/Wrestrict-2.C
@@ -8,8 +8,8 @@ template <int N>
void
bar (char **p)
{
- foo (p[0], p[0]); // { dg-warning "to restrict-qualified parameter aliases with" }
- foo (p[0], p[N]); // { dg-warning "to restrict-qualified parameter aliases with" }
+ foo (p[0], p[0]); // { dg-warning "to 'restrict'-qualified parameter aliases with" }
+ foo (p[0], p[N]); // { dg-warning "to 'restrict'-qualified parameter aliases with" }
foo (p[0]);
}
@@ -17,8 +17,8 @@ template <int N>
void
bar2 (char **p)
{
- foo (p[0], p[0]); // { dg-warning "to restrict-qualified parameter aliases with" }
- foo (p[0], p[N]); // { dg-bogus "to restrict-qualified parameter aliases with" }
+ foo (p[0], p[0]); // { dg-warning "to 'restrict'-qualified parameter aliases with" }
+ foo (p[0], p[N]); // { dg-bogus "to 'restrict'-qualified parameter aliases with" }
foo (p[0]);
}
diff --git a/gcc/testsuite/g++.dg/warn/Wreturn-local-addr-6.C b/gcc/testsuite/g++.dg/warn/Wreturn-local-addr-6.C
new file mode 100644
index 0000000..bfe1445
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Wreturn-local-addr-6.C
@@ -0,0 +1,29 @@
+/* PR c/90737 - inconsistent address of a local converted to intptr_t
+ between callee and caller
+ { dg-do compile }
+ { dg-options "-O1 -Wall -Wreturn-local-addr -fdump-tree-optimized" } */
+
+typedef __INTPTR_TYPE__ intptr_t;
+
+const intptr_t&
+return_addr_label_as_intref (void)
+{
+ label:
+ if ((const intptr_t*)&&label == 0)
+ __builtin_exit (1);
+
+ return *(const intptr_t*)&&label; // { dg-warning "\\\[-Wreturn-local-addr]" } */
+}
+
+const intptr_t&
+return_addr_local_as_intref (void)
+{
+ int a[1];
+ if ((const intptr_t*)a == 0)
+ __builtin_exit (1);
+
+ return (const intptr_t&)a; // { dg-warning "\\\[-Wreturn-local-addr]" } */
+}
+
+/* Verify that the return value has been replaced with zero:
+ { dg-final { scan-tree-dump-times "return 0;" 2 "optimized" } } */
diff --git a/gcc/testsuite/g++.dg/warn/Wsuggest-override-2.C b/gcc/testsuite/g++.dg/warn/Wsuggest-override-2.C
new file mode 100644
index 0000000..4948902
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Wsuggest-override-2.C
@@ -0,0 +1,9 @@
+// PR c++/78010
+// { dg-options "-std=c++11 -Wsuggest-override" }
+
+struct A {
+ virtual void f();
+};
+struct B : A {
+ void f() final; // { dg-bogus "can be marked override" }
+};
diff --git a/gcc/testsuite/g++.dg/warn/Wtype-limits-Wextra.C b/gcc/testsuite/g++.dg/warn/Wtype-limits-Wextra.C
index 0cee96a..99e1e89 100644
--- a/gcc/testsuite/g++.dg/warn/Wtype-limits-Wextra.C
+++ b/gcc/testsuite/g++.dg/warn/Wtype-limits-Wextra.C
@@ -30,10 +30,10 @@ void b (unsigned short x)
void c (unsigned int x)
{
- if (x < 0) return;/* { dg-warning "comparison of unsigned expression < 0 is always false" } */
- if (x >= 0) return;/* { dg-warning "comparison of unsigned expression >= 0 is always true" } */
- if (0 > x) return;/* { dg-warning "comparison of unsigned expression < 0 is always false" } */
- if (0 <= x) return;/* { dg-warning "comparison of unsigned expression >= 0 is always true" } */
+ if (x < 0) return;/* { dg-warning "comparison of unsigned expression in '< 0' is always false" } */
+ if (x >= 0) return;/* { dg-warning "comparison of unsigned expression in '>= 0' is always true" } */
+ if (0 > x) return;/* { dg-warning "comparison of unsigned expression in '< 0' is always false" } */
+ if (0 <= x) return;/* { dg-warning "comparison of unsigned expression in '>= 0' is always true" } */
if (1U >= 0) return;
if (1U < 0) return;
if (0 <= 1U) return;
@@ -42,18 +42,18 @@ void c (unsigned int x)
void d (unsigned long x)
{
- if (x < 0) return;/* { dg-warning "comparison of unsigned expression < 0 is always false" } */
- if (x >= 0) return;/* { dg-warning "comparison of unsigned expression >= 0 is always true" } */
- if (0 > x) return;/* { dg-warning "comparison of unsigned expression < 0 is always false" } */
- if (0 <= x) return;/* { dg-warning "comparison of unsigned expression >= 0 is always true" } */
+ if (x < 0) return;/* { dg-warning "comparison of unsigned expression in '< 0' is always false" } */
+ if (x >= 0) return;/* { dg-warning "comparison of unsigned expression in '>= 0' is always true" } */
+ if (0 > x) return;/* { dg-warning "comparison of unsigned expression in '< 0' is always false" } */
+ if (0 <= x) return;/* { dg-warning "comparison of unsigned expression in '>= 0' is always true" } */
}
void e (unsigned long long x)
{
- if (x < 0) return;/* { dg-warning "comparison of unsigned expression < 0 is always false" } */
- if (x >= 0) return;/* { dg-warning "comparison of unsigned expression >= 0 is always true" } */
- if (0 > x) return;/* { dg-warning "comparison of unsigned expression < 0 is always false" } */
- if (0 <= x) return;/* { dg-warning "comparison of unsigned expression >= 0 is always true" } */
+ if (x < 0) return;/* { dg-warning "comparison of unsigned expression in '< 0' is always false" } */
+ if (x >= 0) return;/* { dg-warning "comparison of unsigned expression in '>= 0' is always true" } */
+ if (0 > x) return;/* { dg-warning "comparison of unsigned expression in '< 0' is always false" } */
+ if (0 <= x) return;/* { dg-warning "comparison of unsigned expression in '>= 0' is always true" } */
}
int test (int x)
diff --git a/gcc/testsuite/g++.dg/warn/Wtype-limits.C b/gcc/testsuite/g++.dg/warn/Wtype-limits.C
index 7919a42..6a968d9 100644
--- a/gcc/testsuite/g++.dg/warn/Wtype-limits.C
+++ b/gcc/testsuite/g++.dg/warn/Wtype-limits.C
@@ -30,10 +30,10 @@ void b (unsigned short x)
void c (unsigned int x)
{
- if (x < 0) return;/* { dg-warning "comparison of unsigned expression < 0 is always false" } */
- if (x >= 0) return;/* { dg-warning "comparison of unsigned expression >= 0 is always true" } */
- if (0 > x) return;/* { dg-warning "comparison of unsigned expression < 0 is always false" } */
- if (0 <= x) return;/* { dg-warning "comparison of unsigned expression >= 0 is always true" } */
+ if (x < 0) return;/* { dg-warning "comparison of unsigned expression in '< 0' is always false" } */
+ if (x >= 0) return;/* { dg-warning "comparison of unsigned expression in '>= 0' is always true" } */
+ if (0 > x) return;/* { dg-warning "comparison of unsigned expression in '< 0' is always false" } */
+ if (0 <= x) return;/* { dg-warning "comparison of unsigned expression in '>= 0' is always true" } */
if (1U >= 0) return;
if (1U < 0) return;
if (0 <= 1U) return;
@@ -42,18 +42,18 @@ void c (unsigned int x)
void d (unsigned long x)
{
- if (x < 0) return;/* { dg-warning "comparison of unsigned expression < 0 is always false" } */
- if (x >= 0) return;/* { dg-warning "comparison of unsigned expression >= 0 is always true" } */
- if (0 > x) return;/* { dg-warning "comparison of unsigned expression < 0 is always false" } */
- if (0 <= x) return;/* { dg-warning "comparison of unsigned expression >= 0 is always true" } */
+ if (x < 0) return;/* { dg-warning "comparison of unsigned expression in '< 0' is always false" } */
+ if (x >= 0) return;/* { dg-warning "comparison of unsigned expression in '>= 0' is always true" } */
+ if (0 > x) return;/* { dg-warning "comparison of unsigned expression in '< 0' is always false" } */
+ if (0 <= x) return;/* { dg-warning "comparison of unsigned expression in '>= 0' is always true" } */
}
void e (unsigned long long x)
{
- if (x < 0) return;/* { dg-warning "comparison of unsigned expression < 0 is always false" } */
- if (x >= 0) return;/* { dg-warning "comparison of unsigned expression >= 0 is always true" } */
- if (0 > x) return;/* { dg-warning "comparison of unsigned expression < 0 is always false" } */
- if (0 <= x) return;/* { dg-warning "comparison of unsigned expression >= 0 is always true" } */
+ if (x < 0) return;/* { dg-warning "comparison of unsigned expression in '< 0' is always false" } */
+ if (x >= 0) return;/* { dg-warning "comparison of unsigned expression in '>= 0' is always true" } */
+ if (0 > x) return;/* { dg-warning "comparison of unsigned expression in '< 0' is always false" } */
+ if (0 <= x) return;/* { dg-warning "comparison of unsigned expression in '>= 0' is always true" } */
}
int test (int x)
diff --git a/gcc/testsuite/g++.dg/warn/ctor-dtor-privacy-4.C b/gcc/testsuite/g++.dg/warn/ctor-dtor-privacy-4.C
new file mode 100644
index 0000000..fcad34e
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/ctor-dtor-privacy-4.C
@@ -0,0 +1,5 @@
+// PR c++/90884
+// { dg-options "-Wctor-dtor-privacy" }
+// { dg-prune-output "In file included from" }
+
+#include "ctor-dtor-privacy-4.h" // { dg-bogus "is public" }
diff --git a/gcc/testsuite/g++.dg/warn/ctor-dtor-privacy-4.h b/gcc/testsuite/g++.dg/warn/ctor-dtor-privacy-4.h
new file mode 100644
index 0000000..d67fd26
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/ctor-dtor-privacy-4.h
@@ -0,0 +1,7 @@
+#pragma GCC system_header
+
+namespace std {
+struct __nonesuch {
+ __nonesuch(__nonesuch const &);
+};
+} // namespace std
diff --git a/gcc/testsuite/g++.dg/warn/miss-format-7.C b/gcc/testsuite/g++.dg/warn/miss-format-7.C
new file mode 100644
index 0000000..ac892dc
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/miss-format-7.C
@@ -0,0 +1,29 @@
+// PR c++/90953 - ICE with -Wmissing-format-attribute.
+// { dg-do compile { target c++11 } }
+// { dg-options "-Wmissing-format-attribute" }
+
+namespace std {
+union [[gnu::may_alias]] _Any_data{};
+enum _Manager_operation { __get_type_info };
+template <typename> class A;
+class B {
+ typedef bool (*_Manager_type)(_Any_data, const _Any_data &,
+ _Manager_operation);
+public:
+ _Any_data _M_functor;
+ _Manager_type _M_manager;
+};
+
+struct type_info { } t;
+
+template <typename _Res, typename... _ArgTypes>
+class A<_Res(_ArgTypes...)> : B {
+ const type_info &target_type() const noexcept;
+};
+template <typename _Res, typename... _ArgTypes>
+const type_info &A<_Res(_ArgTypes...)>::target_type() const noexcept {
+ _Any_data __typeinfo_result;
+ _M_manager(__typeinfo_result, _M_functor, __get_type_info);
+ return t;
+}
+} // namespace std
diff --git a/gcc/testsuite/g++.dg/warn/nonnull3.C b/gcc/testsuite/g++.dg/warn/nonnull3.C
index d82fa31..e869b0f 100644
--- a/gcc/testsuite/g++.dg/warn/nonnull3.C
+++ b/gcc/testsuite/g++.dg/warn/nonnull3.C
@@ -16,4 +16,4 @@ void A::bar (B *)
{
foo ((int B::*) nullptr);
}
-// { dg-warning "nonnull argument" "" {target "*-*-*"} 0 }
+// { dg-warning "'nonnull' argument" "" {target "*-*-*"} 0 }
diff --git a/gcc/testsuite/g++.dg/warn/noreturn-10.C b/gcc/testsuite/g++.dg/warn/noreturn-10.C
new file mode 100644
index 0000000..6f7df48
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/noreturn-10.C
@@ -0,0 +1,10 @@
+// PR c++/60364
+// { dg-do compile { target c++11 } }
+
+void* fn1 [[gnu::returns_twice, noreturn]] (); // { dg-warning "ignoring attribute 'noreturn' because it conflicts with attribute 'returns_twice'" }
+void* fn2 [[gnu::alloc_align(1), noreturn]] (int); // { dg-warning "ignoring attribute 'noreturn' because it conflicts with attribute 'alloc_align'" }
+void* fn3 [[gnu::alloc_size(1), noreturn]] (int); // { dg-warning "ignoring attribute 'noreturn' because it conflicts with attribute 'alloc_size'" }
+void* fn4 [[gnu::const, noreturn]] (); // { dg-warning "ignoring attribute 'noreturn' because it conflicts with attribute 'const'" }
+void* fn5 [[gnu::malloc, noreturn]] (int); // { dg-warning "ignoring attribute 'noreturn' because it conflicts with attribute 'malloc'" }
+void* fn6 [[gnu::pure, noreturn]] (); // { dg-warning "ignoring attribute 'noreturn' because it conflicts with attribute 'pure'" }
+void* fn7 [[gnu::warn_unused_result, noreturn]] (); // { dg-warning "ignoring attribute 'noreturn' because it conflicts with attribute 'warn_unused_result'" }
diff --git a/gcc/testsuite/g++.dg/warn/noreturn-11.C b/gcc/testsuite/g++.dg/warn/noreturn-11.C
new file mode 100644
index 0000000..e0265eb
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/noreturn-11.C
@@ -0,0 +1,25 @@
+// PR c++/60364
+// { dg-do compile { target c++11 } }
+
+void f1 ();
+void f1 [[gnu::noreturn]] ();
+void f1 [[noreturn]] ();
+
+void f2 ();
+__attribute__((noreturn)) void f2 ();
+void f2 [[noreturn]] ();
+
+void f3 ();
+void f3 [[gnu::noreturn]] ();
+void f3 ();
+void f3 [[noreturn]] ();
+
+void f4 ();
+void f4 ();
+void f4 ();
+void f4 [[noreturn]] (); // { dg-error "declared '\\\[\\\[noreturn\\\]\\\]' but its first declaration was not" }
+
+void f5 [[noreturn]] ();
+void f5 ();
+void f5 ();
+void f5 [[noreturn]] ();
diff --git a/gcc/testsuite/g++.dg/warn/noreturn-8.C b/gcc/testsuite/g++.dg/warn/noreturn-8.C
new file mode 100644
index 0000000..d465468
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/noreturn-8.C
@@ -0,0 +1,21 @@
+// PR c++/60364
+// { dg-do compile { target c++11 } }
+// { dg-options "-Wpedantic" }
+
+void f (); // { dg-message "previous declaration" }
+void f [[noreturn]] (); // { dg-error "declared '\\\[\\\[noreturn\\\]\\\]' but its first declaration was not" }
+
+void f2 ();
+void f2 [[gnu::noreturn]] ();
+
+void f3 ();
+__attribute__((noreturn)) void f3 ();
+
+void f4 () { __builtin_abort (); } // { dg-message "previous declaration" }
+void f4 [[noreturn]] (); // { dg-error "declared '\\\[\\\[noreturn\\\]\\\]' but its first declaration was not" }
+
+void f5 () { __builtin_abort (); }
+void f5 [[gnu::noreturn]] ();
+
+void f6 () { __builtin_abort (); }
+__attribute__((noreturn)) void f6 ();
diff --git a/gcc/testsuite/g++.dg/warn/noreturn-9.C b/gcc/testsuite/g++.dg/warn/noreturn-9.C
new file mode 100644
index 0000000..f7ede57a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/noreturn-9.C
@@ -0,0 +1,21 @@
+// PR c++/60364
+// { dg-do compile { target c++11 } }
+// { dg-options "-Wpedantic" }
+
+void f1 [[gnu::noreturn]] ();
+void f1 [[noreturn]] ();
+
+void f2 [[noreturn]] ();
+void f2 [[gnu::noreturn]] ();
+
+__attribute__((noreturn)) void f3 ();
+void f3 [[noreturn]] ();
+
+void f4 [[noreturn]] ();
+__attribute__((noreturn)) void f4 ();
+
+__attribute__((noreturn)) void f5 ();
+void f5 [[gnu::noreturn]] ();
+
+void f6 [[gnu::noreturn]] ();
+__attribute__((noreturn)) void f6 ();
diff --git a/gcc/testsuite/g++.dg/warn/pr8715.C b/gcc/testsuite/g++.dg/warn/pr8715.C
index 330c148..fccb25a 100644
--- a/gcc/testsuite/g++.dg/warn/pr8715.C
+++ b/gcc/testsuite/g++.dg/warn/pr8715.C
@@ -5,7 +5,7 @@ int foo()
{
unsigned char b = '1';
- bool x = ~b; /* { dg-warning "promoted ~unsigned is always non-zero" } */
+ bool x = ~b; /* { dg-warning "promoted bitwise complement of an unsigned value is always nonzero" } */
return 0;
}
diff --git a/gcc/testsuite/g++.dg/wrappers/pr88680.C b/gcc/testsuite/g++.dg/wrappers/pr88680.C
index 1bd6292..8f8bdd6 100644
--- a/gcc/testsuite/g++.dg/wrappers/pr88680.C
+++ b/gcc/testsuite/g++.dg/wrappers/pr88680.C
@@ -27,9 +27,9 @@ void test(unsigned n)
return;
if (N >= FOO)
return;
- if (n >= 0) // { dg-warning ">= 0 is always true" }
+ if (n >= 0) // { dg-warning "'>= 0' is always true" }
return;
- if (n < 0) // { dg-warning "< 0 is always false" }
+ if (n < 0) // { dg-warning "'< 0' is always false" }
return;
if (n >= FOO)
return;
@@ -45,9 +45,9 @@ void test(unsigned n)
return;
if (0 <= FOO)
return;
- if (0 <= n) // { dg-warning ">= 0 is always true" }
+ if (0 <= n) // { dg-warning "'>= 0' is always true" }
return;
- if (0 > n) // { dg-warning "< 0 is always false" }
+ if (0 > n) // { dg-warning "'< 0' is always false" }
return;
if (N <= FOO)
return;
diff --git a/gcc/testsuite/g++.old-deja/g++.abi/ptrmem.C b/gcc/testsuite/g++.old-deja/g++.abi/ptrmem.C
index 3417358..bda7960 100644
--- a/gcc/testsuite/g++.old-deja/g++.abi/ptrmem.C
+++ b/gcc/testsuite/g++.old-deja/g++.abi/ptrmem.C
@@ -7,7 +7,7 @@
function. However, some platforms use all bits to encode a
function pointer. Such platforms use the lowest bit of the delta,
that is shifted left by one bit. */
-#if defined __MN10300__ || defined __SH5__ || defined __arm__ || defined __thumb__ || defined __mips__ || defined __aarch64__
+#if defined __MN10300__ || defined __SH5__ || defined __arm__ || defined __thumb__ || defined __mips__ || defined __aarch64__ || defined __PRU__
#define ADJUST_PTRFN(func, virt) ((void (*)())(func))
#define ADJUST_DELTA(delta, virt) (((delta) << 1) + !!(virt))
#else
diff --git a/gcc/testsuite/g++.old-deja/g++.brendan/crash16.C b/gcc/testsuite/g++.old-deja/g++.brendan/crash16.C
index 5e6acc8..2edb2a8 100644
--- a/gcc/testsuite/g++.old-deja/g++.brendan/crash16.C
+++ b/gcc/testsuite/g++.old-deja/g++.brendan/crash16.C
@@ -3,12 +3,13 @@
// GROUPS passed old-abort
class Graph { // { dg-error "1:new types|1: note: \\(perhaps" }
+// { dg-error "1:return type" "" { target *-*-* } .-1 }
public:
unsigned char N;
Graph(void) {} // { dg-message "7:'Graph" }
}
-Graph::Graph(void) // { dg-error "18:return type|1: error: redefinition" }
+Graph::Graph(void) // { dg-error "1:redefinition" }
{ N = 10;
}
diff --git a/gcc/testsuite/g++.old-deja/g++.brendan/crash22.C b/gcc/testsuite/g++.old-deja/g++.brendan/crash22.C
index 73831a0..7e56892 100644
--- a/gcc/testsuite/g++.old-deja/g++.brendan/crash22.C
+++ b/gcc/testsuite/g++.old-deja/g++.brendan/crash22.C
@@ -6,6 +6,6 @@ struct A {
};
struct B {
- void A::a1(); // this used to die in chainon(), now grokdeclarator should// { dg-error "" } cannot declare.*
- void A::a2(); // should be fixed by the 930629 change.// { dg-error "" } cannot declare.*
+ void A::a1(); // this used to die in chainon(), now grokdeclarator should// { dg-error "10:cannot declare" } cannot declare.*
+ void A::a2(); // should be fixed by the 930629 change.// { dg-error "10:cannot declare" } cannot declare.*
};
diff --git a/gcc/testsuite/g++.old-deja/g++.brendan/crash23.C b/gcc/testsuite/g++.old-deja/g++.brendan/crash23.C
index 2506869..f09609d 100644
--- a/gcc/testsuite/g++.old-deja/g++.brendan/crash23.C
+++ b/gcc/testsuite/g++.old-deja/g++.brendan/crash23.C
@@ -10,6 +10,6 @@ public:
void f ();
void g (int);
};
- void B::f () {}// { dg-error "" } .*
- void B::g (int val) {}// { dg-error "" } .*
+ void B::f () {}// { dg-error "8:cannot define" } .*
+ void B::g (int val) {}// { dg-error "8:cannot define" } .*
};
diff --git a/gcc/testsuite/g++.old-deja/g++.jason/crash10.C b/gcc/testsuite/g++.old-deja/g++.jason/crash10.C
index cd9b7b0..2d1f71d 100644
--- a/gcc/testsuite/g++.old-deja/g++.jason/crash10.C
+++ b/gcc/testsuite/g++.old-deja/g++.jason/crash10.C
@@ -5,4 +5,4 @@ struct A {
enum foo { bar };
};
-typedef A::foo A::foo; // { dg-error "" } causes compiler segfault
+typedef A::foo A::foo; // { dg-error "16:typedef name" } causes compiler segfault
diff --git a/gcc/testsuite/g++.old-deja/g++.law/ctors5.C b/gcc/testsuite/g++.old-deja/g++.law/ctors5.C
index 96604e8..492c429 100644
--- a/gcc/testsuite/g++.old-deja/g++.law/ctors5.C
+++ b/gcc/testsuite/g++.old-deja/g++.law/ctors5.C
@@ -16,13 +16,14 @@ class X // { dg-message "7:X::X|candidate expects" } implicit constructor
class Y // { dg-error "1:new types may not be defined in a return type" "err" }
// { dg-message "1:\\(perhaps a semicolon is missing after the definition of 'Y'\\)" "note" { target *-*-* } .-1 }
+ // { dg-error "1:return type specification for constructor invalid" "err" { target *-*-* } .-2 }
{
private:
X xx;
public:
Y();
}
-X::X( int xi ) // { dg-error "14:return type specification for constructor invalid" "err" }
+X::X( int xi )
// { dg-message "1:X::X|candidate expects" "match candidate text" { target *-*-* } .-1 }
{
x = xi;
diff --git a/gcc/testsuite/g++.old-deja/g++.law/visibility10.C b/gcc/testsuite/g++.old-deja/g++.law/visibility10.C
index 23505f6..7abb4a8 100644
--- a/gcc/testsuite/g++.old-deja/g++.law/visibility10.C
+++ b/gcc/testsuite/g++.old-deja/g++.law/visibility10.C
@@ -10,7 +10,7 @@ public:
};
class deriv : public base {
- void base :: f1();// { dg-error "" } .*
+ void base :: f1();// { dg-error "8:cannot declare" } .*
};
int main ()
diff --git a/gcc/testsuite/g++.old-deja/g++.mike/eh55.C b/gcc/testsuite/g++.old-deja/g++.mike/eh55.C
index af43f66b..5835c96 100644
--- a/gcc/testsuite/g++.old-deja/g++.mike/eh55.C
+++ b/gcc/testsuite/g++.old-deja/g++.mike/eh55.C
@@ -9,7 +9,7 @@ void my_terminate_handler() {
}
void throw_an_unexpected_exception() throw() {
- throw 1; // { dg-warning "throw will always call terminate" "" { target c++17 } }
+ throw 1; // { dg-warning "'throw' will always call 'terminate'" "" { target c++17 } }
}
int main() {
diff --git a/gcc/testsuite/g++.old-deja/g++.other/cond5.C b/gcc/testsuite/g++.old-deja/g++.other/cond5.C
index 994ea6d..f4d16e9 100644
--- a/gcc/testsuite/g++.old-deja/g++.other/cond5.C
+++ b/gcc/testsuite/g++.old-deja/g++.other/cond5.C
@@ -23,8 +23,8 @@ void fn(int i)
int j;
j = (i ? e1 : e2); // { dg-warning "mismatch" }
- d = (i ? e1 : 1.0); // { dg-warning "non-enumeral" }
- d = (i ? 1.0 : e2); // { dg-warning "non-enumeral" }
+ d = (i ? e1 : 1.0); // { dg-warning "non-enumerated" }
+ d = (i ? 1.0 : e2); // { dg-warning "non-enumerated" }
E1 e = (i ? e1 : e1); // ok
j = (i ? 1 : e2); // ok
j = (i ? e1 : 1); // ok
diff --git a/gcc/testsuite/g++.old-deja/g++.other/decl5.C b/gcc/testsuite/g++.old-deja/g++.other/decl5.C
index 3ac9137..6d22932 100644
--- a/gcc/testsuite/g++.old-deja/g++.other/decl5.C
+++ b/gcc/testsuite/g++.old-deja/g++.other/decl5.C
@@ -35,7 +35,7 @@ struct B {
struct ::Q { // { dg-error "global qual" } ::Q not a member of B
int m;
};
- int A::fn() { // { dg-error "cannot define member" } A::fn not a member of B
+ int A::fn() { // { dg-error "7:cannot define member" } A::fn not a member of B
return 0;
}
void fn(struct ::Q &);
diff --git a/gcc/testsuite/g++.old-deja/g++.pt/assign1.C b/gcc/testsuite/g++.old-deja/g++.pt/assign1.C
index 95cbee0..3dfa728 100644
--- a/gcc/testsuite/g++.old-deja/g++.pt/assign1.C
+++ b/gcc/testsuite/g++.old-deja/g++.pt/assign1.C
@@ -2,7 +2,7 @@
// Origin: Mark Mitchell <mark@codesourcery.com>
template <class T>
-struct S { // { dg-error "const member\[^\n\r\]*can't use default assignment operator" }
+struct S { // { dg-error "const member\[^\n\r\]*cannot use default assignment operator" }
S();
T t;
};
diff --git a/gcc/testsuite/g++.target/aarch64/return_address_sign_ab_exception.C b/gcc/testsuite/g++.target/aarch64/return_address_sign_ab_exception.C
new file mode 100644
index 0000000..520cd18
--- /dev/null
+++ b/gcc/testsuite/g++.target/aarch64/return_address_sign_ab_exception.C
@@ -0,0 +1,30 @@
+/* { dg-do run } */
+/* { dg-options "--save-temps" } */
+
+__attribute__((target("branch-protection=pac-ret+leaf")))
+int foo_a () {
+ throw 22;
+}
+
+__attribute__((target("branch-protection=pac-ret+leaf+b-key")))
+int foo_b () {
+ throw 22;
+}
+
+int main (int argc, char** argv) {
+ try {
+ foo_a ();
+ } catch (...) {
+ try {
+ foo_b ();
+ } catch (...) {
+ return 0;
+ }
+ }
+ return 1;
+}
+
+/* { dg-final { scan-assembler-times "paciasp" 1 } } */
+/* { dg-final { scan-assembler-times "pacibsp" 1 } } */
+/* { dg-final { scan-assembler-times ".cfi_b_key_frame" 1 } } */
+
diff --git a/gcc/testsuite/g++.target/aarch64/return_address_sign_b_exception.C b/gcc/testsuite/g++.target/aarch64/return_address_sign_b_exception.C
new file mode 100644
index 0000000..eab2869
--- /dev/null
+++ b/gcc/testsuite/g++.target/aarch64/return_address_sign_b_exception.C
@@ -0,0 +1,17 @@
+/* { dg-do run } */
+/* { dg-options "-mbranch-protection=pac-ret+leaf+b-key --save-temps" } */
+
+int foo () {
+ throw 22;
+}
+
+int main (int argc, char** argv) {
+ try {
+ foo();
+ } catch (...) {
+ return 0;
+ }
+ return 1;
+}
+
+/* { dg-final { scan-assembler-times ".cfi_b_key_frame" 2 } } */
diff --git a/gcc/testsuite/g++.target/i386/pr90424-1.C b/gcc/testsuite/g++.target/i386/pr90424-1.C
new file mode 100644
index 0000000..9df8c08
--- /dev/null
+++ b/gcc/testsuite/g++.target/i386/pr90424-1.C
@@ -0,0 +1,32 @@
+/* { dg-do compile { target c++11 } } */
+/* { dg-options "-O2 -msse2 -fdump-tree-optimized" } */
+
+template <class T>
+using V [[gnu::vector_size(16)]] = T;
+
+template <class T, unsigned M = sizeof(V<T>)>
+V<T> load(const void *p) {
+ using W = V<T>;
+ W r;
+ __builtin_memcpy(&r, p, M);
+ return r;
+}
+
+// movq or movsd
+template V<char> load<char, 8>(const void *); // bad
+template V<short> load<short, 8>(const void *); // bad
+template V<int> load<int, 8>(const void *); // bad
+template V<long> load<long, 8>(const void *); // good
+// the following is disabled because V2SF isn't a supported mode
+// template V<float> load<float, 8>(const void *); // bad
+template V<double> load<double, 8>(const void *); // good (movsd?)
+
+// movd or movss
+template V<char> load<char, 4>(const void *); // bad
+template V<short> load<short, 4>(const void *); // bad
+template V<int> load<int, 4>(const void *); // good
+template V<float> load<float, 4>(const void *); // good
+
+/* We should end up with one load and one insert for each function. */
+/* { dg-final { scan-tree-dump-times "BIT_INSERT_EXPR" 9 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "MEM" 9 "optimized" } } */
diff --git a/gcc/testsuite/g++.target/i386/pr90424-2.C b/gcc/testsuite/g++.target/i386/pr90424-2.C
new file mode 100644
index 0000000..3abb65f
--- /dev/null
+++ b/gcc/testsuite/g++.target/i386/pr90424-2.C
@@ -0,0 +1,31 @@
+/* { dg-do compile { target c++11 } } */
+/* { dg-options "-O2 -msse2 -fdump-tree-optimized" } */
+
+template <class T>
+using V [[gnu::vector_size(16)]] = T;
+
+template <class T, unsigned M = sizeof(V<T>)>
+V<T> load(const void *p) {
+ V<T> r = {};
+ __builtin_memcpy(&r, p, M);
+ return r;
+}
+
+// movq or movsd
+template V<char> load<char, 8>(const void *); // bad
+template V<short> load<short, 8>(const void *); // bad
+template V<int> load<int, 8>(const void *); // bad
+template V<long> load<long, 8>(const void *); // good
+// the following is disabled because V2SF isn't a supported mode
+// template V<float> load<float, 8>(const void *); // bad
+template V<double> load<double, 8>(const void *); // good (movsd?)
+
+// movd or movss
+template V<char> load<char, 4>(const void *); // bad
+template V<short> load<short, 4>(const void *); // bad
+template V<int> load<int, 4>(const void *); // good
+template V<float> load<float, 4>(const void *); // good
+
+/* We should end up with one load and one insert for each function. */
+/* { dg-final { scan-tree-dump-times "BIT_INSERT_EXPR" 9 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "MEM" 9 "optimized" } } */
diff --git a/gcc/testsuite/g++.target/powerpc/powerpc.exp b/gcc/testsuite/g++.target/powerpc/powerpc.exp
new file mode 100644
index 0000000..4e7ea33
--- /dev/null
+++ b/gcc/testsuite/g++.target/powerpc/powerpc.exp
@@ -0,0 +1,44 @@
+# Specific regression driver for PowerPC.
+# Copyright (C) 2019 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/>. */
+
+# GCC testsuite that uses the `dg.exp' driver.
+
+# Exit immediately if this isn't a PowerPC target.
+if {![istarget powerpc*-*-*] } then {
+ return
+}
+
+# Load support procs.
+load_lib g++-dg.exp
+
+global DEFAULT_CXXFLAGS
+if ![info exists DEFAULT_CXXFLAGS] then {
+ set DEFAULT_CXXFLAGS " -pedantic-errors"
+}
+
+# Initialize `dg'.
+dg-init
+
+# Main loop.
+dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.C]] \
+ "" $DEFAULT_CXXFLAGS
+
+# All done.
+dg-finish
+
diff --git a/gcc/testsuite/g++.target/powerpc/undef-bool-3.C b/gcc/testsuite/g++.target/powerpc/undef-bool-3.C
new file mode 100644
index 0000000..b4e18bd
--- /dev/null
+++ b/gcc/testsuite/g++.target/powerpc/undef-bool-3.C
@@ -0,0 +1,13 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -std=c++11 -maltivec" } */
+
+/* Test to ensure that "bool" is not #define'd in altivec.h for C++ when
+ we require strict ANSI. We should compile without errors. */
+
+#include <altivec.h>
+
+bool foo (int x)
+{
+ return x == 2;
+}
+
diff --git a/gcc/testsuite/gcc.c-torture/compile/pr77754-1.c b/gcc/testsuite/gcc.c-torture/compile/pr77754-1.c
index 48587f7..be7ee30 100644
--- a/gcc/testsuite/gcc.c-torture/compile/pr77754-1.c
+++ b/gcc/testsuite/gcc.c-torture/compile/pr77754-1.c
@@ -1,3 +1,4 @@
+// { dg-require-effective-target alloca }
/* PR c/77754 */
int fn3();
diff --git a/gcc/testsuite/gcc.c-torture/compile/pr77754-2.c b/gcc/testsuite/gcc.c-torture/compile/pr77754-2.c
index 411f270..d088961 100644
--- a/gcc/testsuite/gcc.c-torture/compile/pr77754-2.c
+++ b/gcc/testsuite/gcc.c-torture/compile/pr77754-2.c
@@ -1,3 +1,4 @@
+// { dg-require-effective-target alloca }
/* PR c/77754 */
int fn3();
diff --git a/gcc/testsuite/gcc.c-torture/compile/pr77754-3.c b/gcc/testsuite/gcc.c-torture/compile/pr77754-3.c
index c6ff960..fb25e23 100644
--- a/gcc/testsuite/gcc.c-torture/compile/pr77754-3.c
+++ b/gcc/testsuite/gcc.c-torture/compile/pr77754-3.c
@@ -1,3 +1,4 @@
+// { dg-require-effective-target alloca }
/* PR c/77754 */
int fn3();
diff --git a/gcc/testsuite/gcc.c-torture/compile/pr77754-4.c b/gcc/testsuite/gcc.c-torture/compile/pr77754-4.c
index f027405..1c5c461 100644
--- a/gcc/testsuite/gcc.c-torture/compile/pr77754-4.c
+++ b/gcc/testsuite/gcc.c-torture/compile/pr77754-4.c
@@ -1,3 +1,4 @@
+// { dg-require-effective-target alloca }
/* PR c/77754 */
int fn3();
diff --git a/gcc/testsuite/gcc.c-torture/compile/pr77754-5.c b/gcc/testsuite/gcc.c-torture/compile/pr77754-5.c
index a9440dd..82c93d9 100644
--- a/gcc/testsuite/gcc.c-torture/compile/pr77754-5.c
+++ b/gcc/testsuite/gcc.c-torture/compile/pr77754-5.c
@@ -1,3 +1,4 @@
+// { dg-require-effective-target alloca }
/* PR c/77754 */
int fn3();
diff --git a/gcc/testsuite/gcc.c-torture/compile/pr77754-6.c b/gcc/testsuite/gcc.c-torture/compile/pr77754-6.c
index 2e7df3b..1b43043 100644
--- a/gcc/testsuite/gcc.c-torture/compile/pr77754-6.c
+++ b/gcc/testsuite/gcc.c-torture/compile/pr77754-6.c
@@ -1,3 +1,4 @@
+// { dg-require-effective-target alloca }
/* PR c/77754 */
int fn3();
diff --git a/gcc/testsuite/gcc.c-torture/compile/pr87110.c b/gcc/testsuite/gcc.c-torture/compile/pr87110.c
index 8428d3d..c2eba54 100644
--- a/gcc/testsuite/gcc.c-torture/compile/pr87110.c
+++ b/gcc/testsuite/gcc.c-torture/compile/pr87110.c
@@ -1,3 +1,4 @@
+// { dg-require-effective-target alloca }
enum a { b, c };
struct d {
_Bool e;
diff --git a/gcc/testsuite/gcc.c-torture/compile/pr89280.c b/gcc/testsuite/gcc.c-torture/compile/pr89280.c
index 9db9965..15b6e70 100644
--- a/gcc/testsuite/gcc.c-torture/compile/pr89280.c
+++ b/gcc/testsuite/gcc.c-torture/compile/pr89280.c
@@ -1,3 +1,5 @@
+// { dg-require-effective-target nonlocal_goto }
+// { dg-require-effective-target label_values }
/* PR tree-optimization/89280 */
int a;
diff --git a/gcc/testsuite/gcc.c-torture/execute/20030125-1.c b/gcc/testsuite/gcc.c-torture/execute/20030125-1.c
index 960552c3..39578e5 100644
--- a/gcc/testsuite/gcc.c-torture/execute/20030125-1.c
+++ b/gcc/testsuite/gcc.c-torture/execute/20030125-1.c
@@ -1,6 +1,6 @@
/* Verify whether math functions are simplified. */
/* { dg-require-effective-target c99_runtime } */
-/* { dg-require-weak } */
+/* { dg-require-weak "" } */
double sin(double);
double floor(double);
float
diff --git a/gcc/testsuite/gcc.c-torture/execute/20101011-1.c b/gcc/testsuite/gcc.c-torture/execute/20101011-1.c
index d2beeb5..772648d 100644
--- a/gcc/testsuite/gcc.c-torture/execute/20101011-1.c
+++ b/gcc/testsuite/gcc.c-torture/execute/20101011-1.c
@@ -103,6 +103,9 @@ __aeabi_idiv0 (int return_value)
#elif defined (__or1k__)
/* On OpenRISC division by zero does not trap. */
# define DO_TEST 0
+#elif defined (__pru__)
+/* There isn't even a signal function. */
+# define DO_TEST 0
#else
# define DO_TEST 1
#endif
diff --git a/gcc/testsuite/gcc.c-torture/execute/alias-access-path-1.c b/gcc/testsuite/gcc.c-torture/execute/alias-access-path-1.c
new file mode 100644
index 0000000..6693a2b
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/alias-access-path-1.c
@@ -0,0 +1,19 @@
+/* Test that variable
+ int val;
+ may hold value of tyope "struct c" which has same size.
+ This is valid in GIMPLE memory model. */
+
+struct a {int val;} a={1},a2;
+struct b {struct a a;};
+int val;
+struct c {struct b b;} *cptr=(void *)&val;
+
+int
+main(void)
+{
+ cptr->b.a=a;
+ val = 2;
+ a2=cptr->b.a;
+ if (a2.val == a.val)
+ __builtin_abort ();
+}
diff --git a/gcc/testsuite/gcc.c-torture/execute/builtins/builtins.exp b/gcc/testsuite/gcc.c-torture/execute/builtins/builtins.exp
index 5e899d5..fb9d3ec 100644
--- a/gcc/testsuite/gcc.c-torture/execute/builtins/builtins.exp
+++ b/gcc/testsuite/gcc.c-torture/execute/builtins/builtins.exp
@@ -37,7 +37,7 @@ load_lib c-torture.exp
torture-init
set-torture-options $C_TORTURE_OPTIONS {{}} $LTO_TORTURE_OPTIONS
-set additional_flags "-fno-tree-loop-distribute-patterns -fno-tracer"
+set additional_flags "-fno-tree-dse -fno-tree-loop-distribute-patterns -fno-tracer"
if [istarget "powerpc-*-darwin*"] {
lappend additional_flags "-Wl,-multiply_defined,suppress"
}
diff --git a/gcc/testsuite/gcc.c-torture/execute/pr64242.c b/gcc/testsuite/gcc.c-torture/execute/pr64242.c
index 46a7b23..5151f6e 100644
--- a/gcc/testsuite/gcc.c-torture/execute/pr64242.c
+++ b/gcc/testsuite/gcc.c-torture/execute/pr64242.c
@@ -5,46 +5,32 @@ extern void abort (void);
__attribute ((noinline)) void
broken_longjmp (void *p)
{
- void *buf[5];
+ void *buf[32];
__builtin_memcpy (buf, p, 5 * sizeof (void*));
+ __builtin_memset (p, 0, 5 * sizeof (void*));
/* Corrupts stack pointer... */
__builtin_longjmp (buf, 1);
}
-__attribute ((noipa)) __UINTPTR_TYPE__
-foo (void *p)
-{
- return (__UINTPTR_TYPE__) p;
-}
-
-__attribute ((noipa)) void
-bar (void *p)
-{
- asm volatile ("" : : "r" (p));
-}
-
volatile int x = 0;
-void *volatile p;
-void *volatile q;
+char *volatile p;
+char *volatile q;
int
main ()
{
void *buf[5];
- struct __attribute__((aligned (32))) S { int a[4]; } s;
- bar (&s);
p = __builtin_alloca (x);
+ q = __builtin_alloca (x);
if (!__builtin_setjmp (buf))
broken_longjmp (buf);
+ /* Compute expected next alloca offset - some targets don't align properly
+ and allocate too much. */
+ p = q + (q - p);
+
/* Fails if stack pointer corrupted. */
- q = __builtin_alloca (x);
- if (foo (p) < foo (q))
- {
- if (foo (q) - foo (p) >= 1024)
- abort ();
- }
- else if (foo (p) - foo (q) >= 1024)
+ if (p != __builtin_alloca (x))
abort ();
return 0;
diff --git a/gcc/testsuite/gcc.c-torture/execute/pr84521.c b/gcc/testsuite/gcc.c-torture/execute/pr84521.c
new file mode 100644
index 0000000..08d1a9e
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/pr84521.c
@@ -0,0 +1,53 @@
+/* { dg-require-effective-target indirect_jumps } */
+/* { dg-additional-options "-fomit-frame-pointer -fno-inline" } */
+
+extern void abort (void);
+
+void
+broken_longjmp (void *p)
+{
+ __builtin_longjmp (p, 1);
+}
+
+volatile int x = 256;
+void *volatile p = (void*)&x;
+void *volatile p1;
+
+void
+test (void)
+{
+ void *buf[5];
+ void *volatile q = p;
+
+ if (!__builtin_setjmp (buf))
+ broken_longjmp (buf);
+
+ /* Fails if stack pointer corrupted. */
+ if (p != q)
+ abort ();
+}
+
+void
+test2 (void)
+{
+ void *volatile q = p;
+ p1 = __builtin_alloca (x);
+ test ();
+
+ /* Fails if frame pointer corrupted. */
+ if (p != q)
+ abort ();
+}
+
+int
+main (void)
+{
+ void *volatile q = p;
+ test ();
+ test2 ();
+ /* Fails if stack pointer corrupted. */
+ if (p != q)
+ abort ();
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.c-torture/execute/pr86528.c b/gcc/testsuite/gcc.c-torture/execute/pr86528.c
index 2a7b011..9992faf 100644
--- a/gcc/testsuite/gcc.c-torture/execute/pr86528.c
+++ b/gcc/testsuite/gcc.c-torture/execute/pr86528.c
@@ -1,3 +1,4 @@
+// { dg-require-effective-target alloca }
/* PR middle-end/86528 */
void __attribute__((noinline, noclone))
diff --git a/gcc/testsuite/gcc.c-torture/execute/pr90949.c b/gcc/testsuite/gcc.c-torture/execute/pr90949.c
new file mode 100644
index 0000000..8c2ae39
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/pr90949.c
@@ -0,0 +1,42 @@
+void __attribute__ ((noipa, noinline)) my_puts (const char *str) { }
+
+void __attribute__ ((noipa, noinline)) my_free (void *p) { }
+
+
+struct Node
+{
+ struct Node *child;
+};
+
+struct Node space[2] = { };
+
+struct Node * __attribute__ ((noipa, noinline)) my_malloc (int bytes)
+{
+ return &space[0];
+}
+
+void
+walk (struct Node *module, int cleanup)
+{
+ if (module == 0)
+ {
+ return;
+ }
+ if (!cleanup)
+ {
+ my_puts ("No cleanup");
+ }
+ walk (module->child, cleanup);
+ if (cleanup)
+ {
+ my_free (module);
+ }
+}
+
+int
+main ()
+{
+ struct Node *node = my_malloc (sizeof (struct Node));
+ node->child = 0;
+ walk (node, 1);
+}
diff --git a/gcc/testsuite/gcc.c-torture/execute/shiftdi-2.c b/gcc/testsuite/gcc.c-torture/execute/shiftdi-2.c
new file mode 100644
index 0000000..812946f
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/shiftdi-2.c
@@ -0,0 +1,24 @@
+/* { dg-require-effective-target longlong64 } */
+
+long long a = 568513516876543756;
+long long b = -754324895235774564;
+unsigned long long c = 156789543257562457;
+
+long long expected_a[64] = {568513516876543756, 1137027033753087512, 2274054067506175024, 4548108135012350048, 9096216270024700096, -254311533660151424, -508623067320302848, -1017246134640605696, -2034492269281211392, -4068984538562422784, -8137969077124845568, 2170805919459860480, 4341611838919720960, 8683223677839441920, -1080296718030667776, -2160593436061335552, -4321186872122671104, -8642373744245342208, 1161996585218867200, 2323993170437734400, 4647986340875468800, -9150771391958614016, 145201289792323584, 290402579584647168, 580805159169294336, 1161610318338588672, 2323220636677177344, 4646441273354354688, -9153861527000842240, 139021019707867136, 278042039415734272, 556084078831468544, 1112168157662937088, 2224336315325874176, 4448672630651748352, 8897345261303496704, -652053551102558208, -1304107102205116416, -2608214204410232832, -5216428408820465664, 8013887256068620288, -2418969561572311040, -4837939123144622080, 8770865827420307456, -905012418868936704, -1810024837737873408, -3620049675475746816, -7240099350951493632, 3966545371806564352, 7933090743613128704, -2580562586483294208, -5161125172966588416, 8124493727776374784, -2197756618156802048, -4395513236313604096, -8791026472627208192, 864691128455135232, 1729382256910270464, 3458764513820540928, 6917529027641081856, -4611686018427387904, -9223372036854775808ULL, 0, 0};
+long long expected_b[64] = {-754324895235774564, -377162447617887282, -188581223808943641, -94290611904471821, -47145305952235911, -23572652976117956, -11786326488058978, -5893163244029489, -2946581622014745, -1473290811007373, -736645405503687, -368322702751844, -184161351375922, -92080675687961, -46040337843981, -23020168921991, -11510084460996, -5755042230498, -2877521115249, -1438760557625, -719380278813, -359690139407, -179845069704, -89922534852, -44961267426, -22480633713, -11240316857, -5620158429, -2810079215, -1405039608, -702519804, -351259902, -175629951, -87814976, -43907488, -21953744, -10976872, -5488436, -2744218, -1372109, -686055, -343028, -171514, -85757, -42879, -21440, -10720, -5360, -2680, -1340, -670, -335, -168, -84, -42, -21, -11, -6, -3, -2, -1, -1, -1, -1};
+unsigned long long expected_c[64] = {156789543257562457, 78394771628781228, 39197385814390614, 19598692907195307, 9799346453597653, 4899673226798826, 2449836613399413, 1224918306699706, 612459153349853, 306229576674926, 153114788337463, 76557394168731, 38278697084365, 19139348542182, 9569674271091, 4784837135545, 2392418567772, 1196209283886, 598104641943, 299052320971, 149526160485, 74763080242, 37381540121, 18690770060, 9345385030, 4672692515, 2336346257, 1168173128, 584086564, 292043282, 146021641, 73010820, 36505410, 18252705, 9126352, 4563176, 2281588, 1140794, 570397, 285198, 142599, 71299, 35649, 17824, 8912, 4456, 2228, 1114, 557, 278, 139, 69, 34, 17, 8, 4, 2, 1, 0, 0, 0, 0, 0, 0};
+
+int
+main (void)
+{
+ int i;
+
+ for (i = 0; i < 64; i++)
+ {
+ if ((a << i) != expected_a[i]
+ || (b >> i) != expected_b[i]
+ || (c >> i) != expected_c[i])
+ __builtin_abort ();
+ }
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/20020312-2.c b/gcc/testsuite/gcc.dg/20020312-2.c
index c584d35..dae3599 100644
--- a/gcc/testsuite/gcc.dg/20020312-2.c
+++ b/gcc/testsuite/gcc.dg/20020312-2.c
@@ -121,6 +121,8 @@ extern void abort (void);
/* No pic register. */
#elif defined (__AMDGCN__)
/* No pic register. */
+#elif defined(__PRU__)
+/* No pic register. */
#else
# error "Modify the test for your target."
#endif
diff --git a/gcc/testsuite/gcc.dg/Walloca-13.c b/gcc/testsuite/gcc.dg/Walloca-13.c
index d3af0c5..12e9f6c 100644
--- a/gcc/testsuite/gcc.dg/Walloca-13.c
+++ b/gcc/testsuite/gcc.dg/Walloca-13.c
@@ -8,5 +8,5 @@ void g (int *p, int *q)
{
__SIZE_TYPE__ n = (__SIZE_TYPE__)(p - q);
if (n < 100)
- f (__builtin_alloca (n));
+ f (__builtin_alloca (n)); // { dg-bogus "may be too large due to conversion" "" { xfail { *-*-* } } }
}
diff --git a/gcc/testsuite/gcc.dg/Walloca-larger-than-2.c b/gcc/testsuite/gcc.dg/Walloca-larger-than-2.c
index fe003bd..88572d9 100644
--- a/gcc/testsuite/gcc.dg/Walloca-larger-than-2.c
+++ b/gcc/testsuite/gcc.dg/Walloca-larger-than-2.c
@@ -1,6 +1,7 @@
/* PR middle-end/82063 - issues with arguments enabled by -Wall
Verify that alloca() calls in loops are not diagnosed by default.
{ dg-do compile }
+ { dg-require-effective-target alloca }
{ dg-options "-O2 -ftrack-macro-expansion=0" } */
extern void* alloca (__SIZE_TYPE__);
diff --git a/gcc/testsuite/gcc.dg/Walloca-larger-than.c b/gcc/testsuite/gcc.dg/Walloca-larger-than.c
index 284601d..32ee15f 100644
--- a/gcc/testsuite/gcc.dg/Walloca-larger-than.c
+++ b/gcc/testsuite/gcc.dg/Walloca-larger-than.c
@@ -1,5 +1,6 @@
/* PR middle-end/82063 - issues with arguments enabled by -Wall
{ dg-do compile }
+ { dg-require-effective-target alloca }
{ dg-options "-O2 -Walloca-larger-than=0 -Wvla-larger-than=0 -ftrack-macro-expansion=0" } */
extern void* alloca (__SIZE_TYPE__);
diff --git a/gcc/testsuite/gcc.dg/Warray-bounds-41.c b/gcc/testsuite/gcc.dg/Warray-bounds-41.c
index fd79590..2ff3692 100644
--- a/gcc/testsuite/gcc.dg/Warray-bounds-41.c
+++ b/gcc/testsuite/gcc.dg/Warray-bounds-41.c
@@ -1,5 +1,6 @@
/* PR tree-optimization/89662- -Warray-bounds ICE on void* arithmetic
{ dg-do compile }
+ { dg-require-effective-target alloca }
{ dg-options "-O2 -Wall" } */
void* vptr (void *c)
diff --git a/gcc/testsuite/gcc.dg/Wattribute-alias.c b/gcc/testsuite/gcc.dg/Wattribute-alias.c
index 228c1be..12774e8 100644
--- a/gcc/testsuite/gcc.dg/Wattribute-alias.c
+++ b/gcc/testsuite/gcc.dg/Wattribute-alias.c
@@ -1,6 +1,6 @@
/* PR middle-end/81824 - Warn for missing attributes with function aliases
{ dg-do compile }
- { dg-require-ifunc "require ifunc support" }
+ { dg-require-ifunc "" }
{ dg-options "-Wall -Wattribute-alias=2" } */
#define ATTR(...) __attribute__ ((__VA_ARGS__))
diff --git a/gcc/testsuite/gcc.dg/Wfloat-equal-1.c b/gcc/testsuite/gcc.dg/Wfloat-equal-1.c
index 36b3fa5..1b23611 100644
--- a/gcc/testsuite/gcc.dg/Wfloat-equal-1.c
+++ b/gcc/testsuite/gcc.dg/Wfloat-equal-1.c
@@ -4,7 +4,7 @@
double a, b;
_Complex double c, d;
-int f(void) { return a == b; } /* { dg-warning "comparing floating point" } */
-int g(void) { return c == d; } /* { dg-warning "comparing floating point" } */
-int h(void) { return a != b; } /* { dg-warning "comparing floating point" } */
-int i(void) { return c != d; } /* { dg-warning "comparing floating point" } */
+int f(void) { return a == b; } /* { dg-warning "comparing floating-point" } */
+int g(void) { return c == d; } /* { dg-warning "comparing floating-point" } */
+int h(void) { return a != b; } /* { dg-warning "comparing floating-point" } */
+int i(void) { return c != d; } /* { dg-warning "comparing floating-point" } */
diff --git a/gcc/testsuite/gcc.dg/Wrestrict-17.c b/gcc/testsuite/gcc.dg/Wrestrict-17.c
index 8061fda..4e72597 100644
--- a/gcc/testsuite/gcc.dg/Wrestrict-17.c
+++ b/gcc/testsuite/gcc.dg/Wrestrict-17.c
@@ -1,6 +1,7 @@
/* PR tree-optimization/85826 - ICE in gimple-ssa-warn-restruct on
a variable-length struct
{ dg-do compile }
+ { dg-require-effective-target alloca }
{ dg-options "-O2 -Wall" } */
int f (int n)
diff --git a/gcc/testsuite/gcc.dg/Wsign-compare-1.c b/gcc/testsuite/gcc.dg/Wsign-compare-1.c
index be3bd2f..b40bc6c 100644
--- a/gcc/testsuite/gcc.dg/Wsign-compare-1.c
+++ b/gcc/testsuite/gcc.dg/Wsign-compare-1.c
@@ -5,7 +5,7 @@
unsigned int
f0 (int x, unsigned int y)
{
- return x ? y : -1; /* { dg-warning "18:operand of \\?: changes signedness from 'int' to 'unsigned int'" } */
+ return x ? y : -1; /* { dg-warning "18:operand of '\\?:' changes signedness from 'int' to 'unsigned int'" } */
/* { dg-begin-multiline-output "" }
return x ? y : -1;
^~
@@ -15,7 +15,7 @@ f0 (int x, unsigned int y)
unsigned int
f1 (int xxx, unsigned int yyy)
{
- return xxx ? yyy : -1; /* { dg-warning "22:operand of \\?: changes signedness from 'int' to 'unsigned int'" } */
+ return xxx ? yyy : -1; /* { dg-warning "22:operand of '\\?:' changes signedness from 'int' to 'unsigned int'" } */
/* { dg-begin-multiline-output "" }
return xxx ? yyy : -1;
^~
@@ -25,7 +25,7 @@ f1 (int xxx, unsigned int yyy)
unsigned int
f2 (int xxx, unsigned int yyy)
{
- return xxx ? -1 : yyy; /* { dg-warning "16:operand of \\?: changes signedness from 'int' to 'unsigned int'" } */
+ return xxx ? -1 : yyy; /* { dg-warning "16:operand of '\\?:' changes signedness from 'int' to 'unsigned int'" } */
/* { dg-begin-multiline-output "" }
return xxx ? -1 : yyy;
^~
@@ -35,7 +35,7 @@ f2 (int xxx, unsigned int yyy)
unsigned int
f3 (unsigned int yyy)
{
- return yyy ?: -1; /* { dg-warning "17:operand of \\?: changes signedness from 'int' to 'unsigned int'" } */
+ return yyy ?: -1; /* { dg-warning "17:operand of '\\?:' changes signedness from 'int' to 'unsigned int'" } */
/* { dg-begin-multiline-output "" }
return yyy ?: -1;
^~
@@ -45,7 +45,7 @@ f3 (unsigned int yyy)
unsigned int
f4 (int xxx, unsigned yyy, short uuu)
{
- return xxx ? yyy : uuu; /* { dg-warning "22:operand of \\?: changes signedness from 'short int' to 'unsigned int'" } */
+ return xxx ? yyy : uuu; /* { dg-warning "22:operand of '\\?:' changes signedness from 'short int' to 'unsigned int'" } */
/* { dg-begin-multiline-output "" }
return xxx ? yyy : uuu;
^~~
@@ -55,7 +55,7 @@ f4 (int xxx, unsigned yyy, short uuu)
unsigned int
f5 (int xxx, unsigned yyy, short uuu)
{
- return xxx ? uuu : yyy; /* { dg-warning "16:operand of \\?: changes signedness from 'short int' to 'unsigned int'" } */
+ return xxx ? uuu : yyy; /* { dg-warning "16:operand of '\\?:' changes signedness from 'short int' to 'unsigned int'" } */
/* { dg-begin-multiline-output "" }
return xxx ? uuu : yyy;
^~~
@@ -65,7 +65,7 @@ f5 (int xxx, unsigned yyy, short uuu)
unsigned int
f6 (int xxx, unsigned yyy, signed char uuu)
{
- return xxx ? yyy : uuu; /* { dg-warning "22:operand of \\?: changes signedness from 'signed char' to 'unsigned int'" } */
+ return xxx ? yyy : uuu; /* { dg-warning "22:operand of '\\?:' changes signedness from 'signed char' to 'unsigned int'" } */
/* { dg-begin-multiline-output "" }
return xxx ? yyy : uuu;
^~~
@@ -75,7 +75,7 @@ f6 (int xxx, unsigned yyy, signed char uuu)
unsigned int
f7 (int xxx, unsigned yyy, signed char uuu)
{
- return xxx ? uuu : yyy; /* { dg-warning "16:operand of \\?: changes signedness from 'signed char' to 'unsigned int'" } */
+ return xxx ? uuu : yyy; /* { dg-warning "16:operand of '\\?:' changes signedness from 'signed char' to 'unsigned int'" } */
/* { dg-begin-multiline-output "" }
return xxx ? uuu : yyy;
^~~
diff --git a/gcc/testsuite/gcc.dg/Wstrict-overflow-27.c b/gcc/testsuite/gcc.dg/Wstrict-overflow-27.c
index 95d101a..e2cdcbc 100644
--- a/gcc/testsuite/gcc.dg/Wstrict-overflow-27.c
+++ b/gcc/testsuite/gcc.dg/Wstrict-overflow-27.c
@@ -1,4 +1,5 @@
/* { dg-do compile } */
+/* { dg-require-effective-target alloca } */
/* { dg-options "-O3 -Wstrict-overflow=2 -Werror" } */
typedef __SIZE_TYPE__ size_t;
diff --git a/gcc/testsuite/gcc.dg/Wstringop-truncation-3.c b/gcc/testsuite/gcc.dg/Wstringop-truncation-3.c
index 57f4d64..6c67974 100644
--- a/gcc/testsuite/gcc.dg/Wstringop-truncation-3.c
+++ b/gcc/testsuite/gcc.dg/Wstringop-truncation-3.c
@@ -1,5 +1,6 @@
/* PR c/85931 - -Wsizeof-pointer-memaccess for strncpy with size of source
{ dg-do compile }
+ { dg-require-effective-target alloca }
{ dg-options "-O2 -Wall -Wstringop-truncation -ftrack-macro-expansion=0" } */
typedef __SIZE_TYPE__ size_t;
diff --git a/gcc/testsuite/gcc.dg/Wtype-limits-Wextra.c b/gcc/testsuite/gcc.dg/Wtype-limits-Wextra.c
index e5e7f94..72a3951 100644
--- a/gcc/testsuite/gcc.dg/Wtype-limits-Wextra.c
+++ b/gcc/testsuite/gcc.dg/Wtype-limits-Wextra.c
@@ -21,22 +21,22 @@ void a (unsigned char x)
}
void b (unsigned short x)
-{ /* { dg-warning "comparison of unsigned expression < 0 is always false" "" { target { ! int32plus } } .+1 } */
+{ /* { dg-warning "comparison of unsigned expression in '< 0' is always false" "" { target { ! int32plus } } .+1 } */
if (x < 0) return;/* { dg-warning "comparison is always false due to limited range of data type" "" { target { int32plus } } } */
- /* { dg-warning "comparison of unsigned expression >= 0 is always true" "" { target { ! int32plus } } .+1 } */
+ /* { dg-warning "comparison of unsigned expression in '>= 0' is always true" "" { target { ! int32plus } } .+1 } */
if (x >= 0) return;/* { dg-warning "comparison is always true due to limited range of data type" "" { target { int32plus } } } */
- /* { dg-warning "comparison of unsigned expression < 0 is always false" "" { target { ! int32plus } } .+1 } */
+ /* { dg-warning "comparison of unsigned expression in '< 0' is always false" "" { target { ! int32plus } } .+1 } */
if (0 > x) return;/* { dg-warning "comparison is always false due to limited range of data type" "" { target { int32plus } } } */
- /* { dg-warning "comparison of unsigned expression >= 0 is always true" "" { target { ! int32plus } } .+1 } */
+ /* { dg-warning "comparison of unsigned expression in '>= 0' is always true" "" { target { ! int32plus } } .+1 } */
if (0 <= x) return;/* { dg-warning "comparison is always true due to limited range of data type" "" { target { int32plus } } } */
}
void c (unsigned int x)
{
- if (x < 0) return;/* { dg-warning "comparison of unsigned expression < 0 is always false" } */
- if (x >= 0) return;/* { dg-warning "comparison of unsigned expression >= 0 is always true" } */
- if (0 > x) return;/* { dg-warning "comparison of unsigned expression < 0 is always false" } */
- if (0 <= x) return;/* { dg-warning "comparison of unsigned expression >= 0 is always true" } */
+ if (x < 0) return;/* { dg-warning "comparison of unsigned expression in '< 0' is always false" } */
+ if (x >= 0) return;/* { dg-warning "comparison of unsigned expression in '>= 0' is always true" } */
+ if (0 > x) return;/* { dg-warning "comparison of unsigned expression in '< 0' is always false" } */
+ if (0 <= x) return;/* { dg-warning "comparison of unsigned expression in '>= 0' is always true" } */
if (1U >= 0) return;
if (1U < 0) return;
if (0 <= 1U) return;
@@ -45,18 +45,18 @@ void c (unsigned int x)
void d (unsigned long x)
{
- if (x < 0) return;/* { dg-warning "comparison of unsigned expression < 0 is always false" } */
- if (x >= 0) return;/* { dg-warning "comparison of unsigned expression >= 0 is always true" } */
- if (0 > x) return;/* { dg-warning "comparison of unsigned expression < 0 is always false" } */
- if (0 <= x) return;/* { dg-warning "comparison of unsigned expression >= 0 is always true" } */
+ if (x < 0) return;/* { dg-warning "comparison of unsigned expression in '< 0' is always false" } */
+ if (x >= 0) return;/* { dg-warning "comparison of unsigned expression in '>= 0' is always true" } */
+ if (0 > x) return;/* { dg-warning "comparison of unsigned expression in '< 0' is always false" } */
+ if (0 <= x) return;/* { dg-warning "comparison of unsigned expression in '>= 0' is always true" } */
}
void e (unsigned long long x)
{
- if (x < 0) return;/* { dg-warning "comparison of unsigned expression < 0 is always false" } */
- if (x >= 0) return;/* { dg-warning "comparison of unsigned expression >= 0 is always true" } */
- if (0 > x) return;/* { dg-warning "comparison of unsigned expression < 0 is always false" } */
- if (0 <= x) return;/* { dg-warning "comparison of unsigned expression >= 0 is always true" } */
+ if (x < 0) return;/* { dg-warning "comparison of unsigned expression in '< 0' is always false" } */
+ if (x >= 0) return;/* { dg-warning "comparison of unsigned expression in '>= 0' is always true" } */
+ if (0 > x) return;/* { dg-warning "comparison of unsigned expression in '< 0' is always false" } */
+ if (0 <= x) return;/* { dg-warning "comparison of unsigned expression in '>= 0' is always true" } */
}
int test (int x)
diff --git a/gcc/testsuite/gcc.dg/Wtype-limits.c b/gcc/testsuite/gcc.dg/Wtype-limits.c
index 2d6f991..6a596fc 100644
--- a/gcc/testsuite/gcc.dg/Wtype-limits.c
+++ b/gcc/testsuite/gcc.dg/Wtype-limits.c
@@ -21,22 +21,22 @@ void a (unsigned char x)
}
void b (unsigned short x)
-{ /* { dg-warning "comparison of unsigned expression < 0 is always false" "" { target { ! int32plus } } .+1 } */
+{ /* { dg-warning "comparison of unsigned expression in '< 0' is always false" "" { target { ! int32plus } } .+1 } */
if (x < 0) return;/* { dg-warning "comparison is always false due to limited range of data type" "" { target { int32plus } } } */
- /* { dg-warning "comparison of unsigned expression >= 0 is always true" "" { target { ! int32plus } } .+1 } */
+ /* { dg-warning "comparison of unsigned expression in '>= 0' is always true" "" { target { ! int32plus } } .+1 } */
if (x >= 0) return;/* { dg-warning "comparison is always true due to limited range of data type" "" { target { int32plus } } } */
- /* { dg-warning "comparison of unsigned expression < 0 is always false" "" { target { ! int32plus } } .+1 } */
+ /* { dg-warning "comparison of unsigned expression in '< 0' is always false" "" { target { ! int32plus } } .+1 } */
if (0 > x) return;/* { dg-warning "comparison is always false due to limited range of data type" "" { target { int32plus } } } */
- /* { dg-warning "comparison of unsigned expression >= 0 is always true" "" { target { ! int32plus } } .+1 } */
+ /* { dg-warning "comparison of unsigned expression in '>= 0' is always true" "" { target { ! int32plus } } .+1 } */
if (0 <= x) return;/* { dg-warning "comparison is always true due to limited range of data type" "" { target { int32plus } } } */
}
void c (unsigned int x)
{
- if (x < 0) return;/* { dg-warning "comparison of unsigned expression < 0 is always false" } */
- if (x >= 0) return;/* { dg-warning "comparison of unsigned expression >= 0 is always true" } */
- if (0 > x) return;/* { dg-warning "comparison of unsigned expression < 0 is always false" } */
- if (0 <= x) return;/* { dg-warning "comparison of unsigned expression >= 0 is always true" } */
+ if (x < 0) return;/* { dg-warning "comparison of unsigned expression in '< 0' is always false" } */
+ if (x >= 0) return;/* { dg-warning "comparison of unsigned expression in '>= 0' is always true" } */
+ if (0 > x) return;/* { dg-warning "comparison of unsigned expression in '< 0' is always false" } */
+ if (0 <= x) return;/* { dg-warning "comparison of unsigned expression in '>= 0' is always true" } */
if (1U >= 0) return;
if (1U < 0) return;
if (0 <= 1U) return;
@@ -45,18 +45,18 @@ void c (unsigned int x)
void d (unsigned long x)
{
- if (x < 0) return;/* { dg-warning "comparison of unsigned expression < 0 is always false" } */
- if (x >= 0) return;/* { dg-warning "comparison of unsigned expression >= 0 is always true" } */
- if (0 > x) return;/* { dg-warning "comparison of unsigned expression < 0 is always false" } */
- if (0 <= x) return;/* { dg-warning "comparison of unsigned expression >= 0 is always true" } */
+ if (x < 0) return;/* { dg-warning "comparison of unsigned expression in '< 0' is always false" } */
+ if (x >= 0) return;/* { dg-warning "comparison of unsigned expression in '>= 0' is always true" } */
+ if (0 > x) return;/* { dg-warning "comparison of unsigned expression in '< 0' is always false" } */
+ if (0 <= x) return;/* { dg-warning "comparison of unsigned expression in '>= 0' is always true" } */
}
void e (unsigned long long x)
{
- if (x < 0) return;/* { dg-warning "comparison of unsigned expression < 0 is always false" } */
- if (x >= 0) return;/* { dg-warning "comparison of unsigned expression >= 0 is always true" } */
- if (0 > x) return;/* { dg-warning "comparison of unsigned expression < 0 is always false" } */
- if (0 <= x) return;/* { dg-warning "comparison of unsigned expression >= 0 is always true" } */
+ if (x < 0) return;/* { dg-warning "comparison of unsigned expression in '< 0' is always false" } */
+ if (x >= 0) return;/* { dg-warning "comparison of unsigned expression in '>= 0' is always true" } */
+ if (0 > x) return;/* { dg-warning "comparison of unsigned expression in '< 0' is always false" } */
+ if (0 <= x) return;/* { dg-warning "comparison of unsigned expression in '>= 0' is always true" } */
}
int test (int x)
diff --git a/gcc/testsuite/gcc.dg/Wunknownprag.c b/gcc/testsuite/gcc.dg/Wunknownprag.c
index 3514825..158cab7 100644
--- a/gcc/testsuite/gcc.dg/Wunknownprag.c
+++ b/gcc/testsuite/gcc.dg/Wunknownprag.c
@@ -5,7 +5,7 @@
/* We used to get "unspellable token: CPP_EOF" warnings. */
-#pragma /* { dg-warning "-:ignoring #pragma" } */
-#pragma ~ /* { dg-warning "-:ignoring #pragma" } */
-#pragma baz /* { dg-warning "-:ignoring #pragma" } */
-#pragma baz baz /* { dg-warning "-:ignoring #pragma" } */
+#pragma /* { dg-warning "-:ignoring '#pragma" } */
+#pragma ~ /* { dg-warning "-:ignoring '#pragma" } */
+#pragma baz /* { dg-warning "-:ignoring '#pragma" } */
+#pragma baz baz /* { dg-warning "-:ignoring '#pragma baz baz'" } */
diff --git a/gcc/testsuite/gcc.dg/Wunsuffixed-float-constants-1.c b/gcc/testsuite/gcc.dg/Wunsuffixed-float-constants-1.c
index b4a38d5..ba992c4 100644
--- a/gcc/testsuite/gcc.dg/Wunsuffixed-float-constants-1.c
+++ b/gcc/testsuite/gcc.dg/Wunsuffixed-float-constants-1.c
@@ -8,8 +8,8 @@ double a = 1.1d;
/* With FLOAT_CONST_DECIMAL64 switched to ON these would have type
_Decimal64. */
-double b = VAL; /* { dg-warning "unsuffixed float constant" } */
-double c = 1.2; /* { dg-warning "unsuffixed float constant" } */
+double b = VAL; /* { dg-warning "unsuffixed floating constant" } */
+double c = 1.2; /* { dg-warning "unsuffixed floating constant" } */
/* With FLOAT_CONST_DECIMAL64 switched to ON these are still binary. */
diff --git a/gcc/testsuite/gcc.dg/asm-6.c b/gcc/testsuite/gcc.dg/asm-6.c
index 9c0ac1e..10983c7 100644
--- a/gcc/testsuite/gcc.dg/asm-6.c
+++ b/gcc/testsuite/gcc.dg/asm-6.c
@@ -2,6 +2,6 @@
void foo ()
{
int i;
- __asm__ ("" : [data] "=r" (i) : [data] "i" (100)); /* { dg-error "duplicate asm operand" } */
+ __asm__ ("" : [data] "=r" (i) : [data] "i" (100)); /* { dg-error "duplicate 'asm' operand" } */
__asm__ ("%[foo]" :: [bar] "i" (1)); /* { dg-error "undefined named operand" } */
}
diff --git a/gcc/testsuite/gcc.dg/asm-qual-1.c b/gcc/testsuite/gcc.dg/asm-qual-1.c
index eff6b45..7e21687 100644
--- a/gcc/testsuite/gcc.dg/asm-qual-1.c
+++ b/gcc/testsuite/gcc.dg/asm-qual-1.c
@@ -8,7 +8,7 @@ f (void)
{
asm volatile ("");
- asm const (""); /* { dg-error {'const' is not an asm qualifier} } */
+ asm const (""); /* { dg-error {'const' is not a valid 'asm' qualifier} } */
- asm restrict (""); /* { dg-error {'restrict' is not an asm qualifier} } */
+ asm restrict (""); /* { dg-error {'restrict' is not a valid 'asm' qualifier} } */
}
diff --git a/gcc/testsuite/gcc.dg/atomic/c11-atomic-exec-4.c b/gcc/testsuite/gcc.dg/atomic/c11-atomic-exec-4.c
index 344f994..d6bb629 100644
--- a/gcc/testsuite/gcc.dg/atomic/c11-atomic-exec-4.c
+++ b/gcc/testsuite/gcc.dg/atomic/c11-atomic-exec-4.c
@@ -3,7 +3,7 @@
out in two threads. */
/* { dg-do run } */
/* { dg-options "-std=c11 -pedantic-errors -pthread -U_POSIX_C_SOURCE -D_POSIX_C_SOURCE=200809L" } */
-/* { dg-additional-options "-D_XOPEN_SOURCE=600" { target *-*-solaris2.1[0-9]* } } */
+/* { dg-additional-options "-D_XOPEN_SOURCE=600" { target *-*-solaris2* } } */
/* { dg-require-effective-target pthread } */
#include <stdint.h>
diff --git a/gcc/testsuite/gcc.dg/atomic/c11-atomic-exec-5.c b/gcc/testsuite/gcc.dg/atomic/c11-atomic-exec-5.c
index 6d6b5a7..692c64a 100644
--- a/gcc/testsuite/gcc.dg/atomic/c11-atomic-exec-5.c
+++ b/gcc/testsuite/gcc.dg/atomic/c11-atomic-exec-5.c
@@ -6,7 +6,7 @@
/* { dg-options "-std=c11 -pedantic-errors -pthread -U_POSIX_C_SOURCE -D_POSIX_C_SOURCE=200809L" } */
/* { dg-add-options ieee } */
/* { dg-additional-options "-mfp-trap-mode=sui" { target alpha*-*-* } } */
-/* { dg-additional-options "-D_XOPEN_SOURCE=600" { target *-*-solaris2.1[0-9]* } } */
+/* { dg-additional-options "-D_XOPEN_SOURCE=600" { target *-*-solaris2* } } */
/* { dg-require-effective-target fenv_exceptions } */
/* { dg-require-effective-target pthread } */
/* { dg-timeout-factor 2 } */
diff --git a/gcc/testsuite/gcc.dg/attr-alloc_size-5.c b/gcc/testsuite/gcc.dg/attr-alloc_size-5.c
index 26ee43f..7aa7cbf 100644
--- a/gcc/testsuite/gcc.dg/attr-alloc_size-5.c
+++ b/gcc/testsuite/gcc.dg/attr-alloc_size-5.c
@@ -230,5 +230,5 @@ test_alloca (size_t n)
{
extern void* alloca (size_t);
- alloca (0);
+ alloca (0); /* { dg-warning "ignoring return value of '.*' declared with attribute 'warn_unused_result'" } */
}
diff --git a/gcc/testsuite/gcc.dg/attr-assume_aligned-4.c b/gcc/testsuite/gcc.dg/attr-assume_aligned-4.c
index 84f4523..2571ab8 100644
--- a/gcc/testsuite/gcc.dg/attr-assume_aligned-4.c
+++ b/gcc/testsuite/gcc.dg/attr-assume_aligned-4.c
@@ -23,14 +23,14 @@ A (16385) void* fpv_16kp1 (void); /* { dg-warning ".assume_aligned. attribute
A (32767) void* fpv_32km1 (void); /* { dg-warning ".assume_aligned. attribute argument 32767 is not a power of 2" } */
-A (4, -1) void* fpv_4_m1 (void); /* { dg-warning ".assume_aligned. attribute argument -1 is not in the range \\\[0, 4\\\)" } */
+A (4, -1) void* fpv_4_m1 (void); /* { dg-warning ".assume_aligned. attribute argument -1 is not in the range \\\[0, 3]" } */
A (4, 0) void* fpv_4_0 (void);
A (4, 1) void* fpv_4_1 (void);
A (4, 2) void* fpv_4_2 (void);
A (4, 3) void* fpv_4_3 (void);
-A (4, 4) void* fpv_4_3 (void); /* { dg-warning ".assume_aligned. attribute argument 4 is not in the range \\\[0, 4\\\)" } */
+A (4, 4) void* fpv_4_3 (void); /* { dg-warning ".assume_aligned. attribute argument 4 is not in the range \\\[0, 3]" } */
A (4) void* gpv_4_3 (void);
A (2) void* gpv_4_3 (void);
diff --git a/gcc/testsuite/gcc.dg/attr-copy-6.c b/gcc/testsuite/gcc.dg/attr-copy-6.c
index 010db0d..d1a2865 100644
--- a/gcc/testsuite/gcc.dg/attr-copy-6.c
+++ b/gcc/testsuite/gcc.dg/attr-copy-6.c
@@ -2,6 +2,7 @@
{ dg-do compile }
{ dg-skip-if "Attributes not supported" { { hppa*-*-hpux* } && { ! lp64 } } }
{ dg-options "-O2 -Wall" }
+ { dg-require-alias "" }
{ dg-require-weak "" } */
#define ATTR(...) __attribute__ ((__VA_ARGS__))
diff --git a/gcc/testsuite/gcc.dg/attr-noinline.c b/gcc/testsuite/gcc.dg/attr-noinline.c
index 13cc660..b77a346 100644
--- a/gcc/testsuite/gcc.dg/attr-noinline.c
+++ b/gcc/testsuite/gcc.dg/attr-noinline.c
@@ -3,15 +3,15 @@
extern int t();
-static inline void __attribute__((__noinline__)) function_definition(void) {t();} /* { dg-warning "inline function \[^\n\]* given attribute noinline" } */
+static inline void __attribute__((__noinline__)) function_definition(void) {t();} /* { dg-warning "inline function \[^\n\]* given attribute 'noinline'" } */
-static inline void __attribute__((__noinline__)) function_declaration_both_before(void); /* { dg-warning "inline function \[^\n\]* given attribute noinline" } */
+static inline void __attribute__((__noinline__)) function_declaration_both_before(void); /* { dg-warning "inline function \[^\n\]* given attribute 'noinline'" } */
static void function_declaration_both_before(void) {t();}
static void function_declaration_both_after(void);
-static inline void __attribute__((__noinline__)) function_declaration_both_after(void); /* { dg-warning "(inline function \[^\n\]* given attribute noinline|declared inline after its definition)" } */
+static inline void __attribute__((__noinline__)) function_declaration_both_after(void); /* { dg-warning "(inline function \[^\n\]* given attribute .noinline.|declared inline after its definition)" } */
static void function_declaration_both_after(void) {t();}
diff --git a/gcc/testsuite/gcc.dg/attr-noipa.c b/gcc/testsuite/gcc.dg/attr-noipa.c
index e2349b6..b2485bb 100644
--- a/gcc/testsuite/gcc.dg/attr-noipa.c
+++ b/gcc/testsuite/gcc.dg/attr-noipa.c
@@ -4,7 +4,7 @@
/* { dg-require-effective-target alloca } */
static inline int __attribute__((noipa))
-fn1 (void) /* { dg-warning "inline function \[^\n\]* given attribute noinline" "" } */
+fn1 (void) /* { dg-warning "inline function \[^\n\]* given attribute 'noinline'" "" } */
{
return 1;
}
diff --git a/gcc/testsuite/gcc.dg/attr-weakref-2.c b/gcc/testsuite/gcc.dg/attr-weakref-2.c
index 75cc077..172a4a6 100644
--- a/gcc/testsuite/gcc.dg/attr-weakref-2.c
+++ b/gcc/testsuite/gcc.dg/attr-weakref-2.c
@@ -4,4 +4,4 @@
typedef int vtype;
extern vtype wv1;
-extern vtype Wv1a __attribute__((weakref ("wv1"))); /* { dg-error "weakref 'Wv1a' must have static linkage" } */
+extern vtype Wv1a __attribute__((weakref ("wv1"))); /* { dg-error "'weakref' symbol 'Wv1a' must have static linkage" } */
diff --git a/gcc/testsuite/gcc.dg/autopar/pr39500-1.c b/gcc/testsuite/gcc.dg/autopar/pr39500-1.c
index 28f4789..80ae925 100644
--- a/gcc/testsuite/gcc.dg/autopar/pr39500-1.c
+++ b/gcc/testsuite/gcc.dg/autopar/pr39500-1.c
@@ -1,7 +1,7 @@
/* pr39500: autopar fails to parallel */
/* origin: nemokingdom@gmail.com(LiFeng) */
/* { dg-do compile } */
-/* { dg-options "-O2 -ftree-parallelize-loops=4 -fdump-tree-parloops2-details" } */
+/* { dg-options "-O2 -fno-tree-loop-distribute-patterns -ftree-parallelize-loops=4 -fdump-tree-parloops2-details" } */
void abort (void);
diff --git a/gcc/testsuite/gcc.dg/autopar/reduc-1char.c b/gcc/testsuite/gcc.dg/autopar/reduc-1char.c
index 0d611b96..a340240 100644
--- a/gcc/testsuite/gcc.dg/autopar/reduc-1char.c
+++ b/gcc/testsuite/gcc.dg/autopar/reduc-1char.c
@@ -61,5 +61,5 @@ int main (void)
/* { dg-final { scan-tree-dump-times "Detected reduction" 3 "parloops2" } } */
-/* { dg-final { scan-tree-dump-times "SUCCESS: may be parallelized" 4 "parloops2" } } */
+/* { dg-final { scan-tree-dump-times "SUCCESS: may be parallelized" 3 "parloops2" } } */
diff --git a/gcc/testsuite/gcc.dg/autopar/reduc-7.c b/gcc/testsuite/gcc.dg/autopar/reduc-7.c
index efae736..85b9437 100644
--- a/gcc/testsuite/gcc.dg/autopar/reduc-7.c
+++ b/gcc/testsuite/gcc.dg/autopar/reduc-7.c
@@ -85,5 +85,5 @@ int main (void)
/* { dg-final { scan-tree-dump-times "Detected reduction" 2 "parloops2" } } */
-/* { dg-final { scan-tree-dump-times "SUCCESS: may be parallelized" 3 "parloops2" } } */
+/* { dg-final { scan-tree-dump-times "SUCCESS: may be parallelized" 2 "parloops2" } } */
diff --git a/gcc/testsuite/gcc.dg/builtin-apply2.c b/gcc/testsuite/gcc.dg/builtin-apply2.c
index 3eadc77..06ef24e 100644
--- a/gcc/testsuite/gcc.dg/builtin-apply2.c
+++ b/gcc/testsuite/gcc.dg/builtin-apply2.c
@@ -1,7 +1,7 @@
/* { dg-do run } */
/* { dg-require-effective-target untyped_assembly } */
/* { dg-skip-if "Variadic funcs have all args on stack. Normal funcs have args in registers." { "avr-*-* nds32*-*-* amdgcn-*-*" } } */
-/* { dg-skip-if "Variadic funcs use different argument passing from normal funcs." { "riscv*-*-* or1k*-*-* msp430-*-*" } } */
+/* { dg-skip-if "Variadic funcs use different argument passing from normal funcs." { "riscv*-*-* or1k*-*-* msp430-*-* pru-*-*" } } */
/* { dg-skip-if "Variadic funcs use Base AAPCS. Normal funcs use VFP variant." { arm*-*-* && arm_hf_eabi } } */
/* PR target/12503 */
diff --git a/gcc/testsuite/gcc.dg/builtin-memchr-4.c b/gcc/testsuite/gcc.dg/builtin-memchr-4.c
new file mode 100644
index 0000000..58a3b44
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/builtin-memchr-4.c
@@ -0,0 +1,40 @@
+/* PR tree-optimization/89772
+ Verify that memchr calls with a pointer to a constant character
+ are folded as expected.
+ { dg-do compile }
+ { dg-options "-O1 -Wall -fdump-tree-release_ssa" } */
+
+typedef __SIZE_TYPE__ size_t;
+typedef __WCHAR_TYPE__ wchar_t;
+
+extern void* memchr (const void*, int, size_t);
+extern int printf (const char*, ...);
+extern void abort (void);
+
+#define A(expr) \
+ ((expr) \
+ ? (void)0 \
+ : (printf ("assertion failed on line %i: %s\n", \
+ __LINE__, #expr), \
+ abort ()))
+
+const char a[8] = {'a',0,'b'};
+const char b[3] = {'a','b'};
+const char c[8] = {'a','b','c'};
+
+void test_memchr_cst_char (void)
+{
+ A (!memchr (a, 'c', 2));
+ A (!memchr (a, 'c', 5));
+ A (!memchr (a, 'c', sizeof a));
+ A (&a[1] == memchr (a, 0, sizeof a));
+
+ A (!memchr (b, 0, 2));
+ A (&b[2] == memchr (b, 0, sizeof b));
+
+ A (!memchr (c, 0, 2));
+ A (&c[3] == memchr (c, 0, 4));
+ A (&c[3] == memchr (c, 0, sizeof a));
+}
+
+/* { dg-final { scan-tree-dump-not "abort" "release_ssa" } } */
diff --git a/gcc/testsuite/gcc.dg/builtin-stringop-chk-1.c b/gcc/testsuite/gcc.dg/builtin-stringop-chk-1.c
index afd07dd..40cfa04 100644
--- a/gcc/testsuite/gcc.dg/builtin-stringop-chk-1.c
+++ b/gcc/testsuite/gcc.dg/builtin-stringop-chk-1.c
@@ -1,7 +1,7 @@
/* Test whether buffer overflow warnings for __*_chk builtins
are emitted properly. */
/* { dg-do compile } */
-/* { dg-options "-O2 -Wno-format -std=gnu99 -ftrack-macro-expansion=0" } */
+/* { dg-options "-O2 -Wno-format -std=gnu99 -ftrack-macro-expansion=0 -fno-tree-dse" } */
// { dg-skip-if "packed attribute missing for t" { "epiphany-*-*" } }
extern void abort (void);
diff --git a/gcc/testsuite/gcc.dg/c90-const-expr-6.c b/gcc/testsuite/gcc.dg/c90-const-expr-6.c
index 50239ce..210659d7 100644
--- a/gcc/testsuite/gcc.dg/c90-const-expr-6.c
+++ b/gcc/testsuite/gcc.dg/c90-const-expr-6.c
@@ -7,22 +7,22 @@
__extension__ typedef __INTPTR_TYPE__ intptr_t;
/* PR 29116. */
-int n = 0, p[n * 0 + 1]; /* { dg-error "variabl|can't be evaluated" } */
+int n = 0, p[n * 0 + 1]; /* { dg-error "variabl|cannot be evaluated" } */
/* PR 31871. */
-extern int c[1 + ((intptr_t) (void *) 0)]; /* { dg-error "variab|can't be evaluated" } */
+extern int c[1 + ((intptr_t) (void *) 0)]; /* { dg-error "variab|cannot be evaluated" } */
/* Implicit conversions from floating-point constants are not OK,
although explicit ones are. */
-extern int c1[1.0 ? 1 : 0]; /* { dg-error "variab|can't be evaluated" } */
+extern int c1[1.0 ? 1 : 0]; /* { dg-error "variab|cannot be evaluated" } */
extern int c2[(int)1.0 ? 1 : 0];
-extern int c3[1.0 && 1]; /* { dg-error "variab|can't be evaluated" } */
+extern int c3[1.0 && 1]; /* { dg-error "variab|cannot be evaluated" } */
extern int c4[(int)1.0 && 1];
-extern int c5[1.0 || 1]; /* { dg-error "variab|can't be evaluated" } */
+extern int c5[1.0 || 1]; /* { dg-error "variab|cannot be evaluated" } */
extern int c6[(int)1.0 || 1];
@@ -46,7 +46,7 @@ enum f {
void
f (int a)
{
- int v[1 + ((intptr_t) (void *) 0)]; /* { dg-error "variab|can't be evaluated" } */
+ int v[1 + ((intptr_t) (void *) 0)]; /* { dg-error "variab|cannot be evaluated" } */
switch (a)
{
case (n * 0 + 1): /* { dg-error "constant" } */
diff --git a/gcc/testsuite/gcc.dg/c99-math-double-1.c b/gcc/testsuite/gcc.dg/c99-math-double-1.c
index 6441a59..0db4297 100644
--- a/gcc/testsuite/gcc.dg/c99-math-double-1.c
+++ b/gcc/testsuite/gcc.dg/c99-math-double-1.c
@@ -1,4 +1,4 @@
-/* { dg-do run { target *-*-solaris2.1[0-9]* } } */
+/* { dg-do run { target *-*-solaris2* } } */
/* { dg-options "-std=c99 -O" } */
#include <math.h>
diff --git a/gcc/testsuite/gcc.dg/c99-math-float-1.c b/gcc/testsuite/gcc.dg/c99-math-float-1.c
index 36a7396..8654e76 100644
--- a/gcc/testsuite/gcc.dg/c99-math-float-1.c
+++ b/gcc/testsuite/gcc.dg/c99-math-float-1.c
@@ -1,4 +1,4 @@
-/* { dg-do run { target *-*-solaris2.1[0-9]* } } */
+/* { dg-do run { target *-*-solaris2* } } */
/* { dg-options "-std=c99 -O" } */
#include <math.h>
diff --git a/gcc/testsuite/gcc.dg/c99-math-long-double-1.c b/gcc/testsuite/gcc.dg/c99-math-long-double-1.c
index d8146c2..97948f4c 100644
--- a/gcc/testsuite/gcc.dg/c99-math-long-double-1.c
+++ b/gcc/testsuite/gcc.dg/c99-math-long-double-1.c
@@ -1,4 +1,4 @@
-/* { dg-do run { target *-*-solaris2.1[0-9]* } } */
+/* { dg-do run { target *-*-solaris2* } } */
/* { dg-options "-std=c99 -O" } */
#include <math.h>
diff --git a/gcc/testsuite/gcc.dg/cast-1.c b/gcc/testsuite/gcc.dg/cast-1.c
index 7b12ad9..335a090 100644
--- a/gcc/testsuite/gcc.dg/cast-1.c
+++ b/gcc/testsuite/gcc.dg/cast-1.c
@@ -24,8 +24,8 @@ f (void)
(union u) l; /* { dg-error "cast to union type from type not present in union" } */
(int) sv; /* { dg-error "aggregate value used where an integer was expected" } */
(int) uv; /* { dg-error "aggregate value used where an integer was expected" } */
- (float) sv; /* { dg-error "aggregate value used where a float was expected" } */
- (float) uv; /* { dg-error "aggregate value used where a float was expected" } */
+ (float) sv; /* { dg-error "aggregate value used where a floating-point was expected" } */
+ (float) uv; /* { dg-error "aggregate value used where a floating-point was expected" } */
(_Complex double) sv; /* { dg-error "aggregate value used where a complex was expected" } */
(_Complex double) uv; /* { dg-error "aggregate value used where a complex was expected" } */
(void *) sv; /* { dg-error "cannot convert to a pointer type" } */
diff --git a/gcc/testsuite/gcc.dg/cast-2.c b/gcc/testsuite/gcc.dg/cast-2.c
index f7f58f8..2523ac4 100644
--- a/gcc/testsuite/gcc.dg/cast-2.c
+++ b/gcc/testsuite/gcc.dg/cast-2.c
@@ -24,8 +24,8 @@ f (void)
(union u) l; /* { dg-error "cast to union type from type not present in union" } */
(int) sv; /* { dg-error "aggregate value used where an integer was expected" } */
(int) uv; /* { dg-error "aggregate value used where an integer was expected" } */
- (float) sv; /* { dg-error "aggregate value used where a float was expected" } */
- (float) uv; /* { dg-error "aggregate value used where a float was expected" } */
+ (float) sv; /* { dg-error "aggregate value used where a floating-point was expected" } */
+ (float) uv; /* { dg-error "aggregate value used where a floating-point was expected" } */
(_Complex double) sv; /* { dg-error "aggregate value used where a complex was expected" } */
(_Complex double) uv; /* { dg-error "aggregate value used where a complex was expected" } */
(void *) sv; /* { dg-error "cannot convert to a pointer type" } */
diff --git a/gcc/testsuite/gcc.dg/cast-3.c b/gcc/testsuite/gcc.dg/cast-3.c
index 40d3c88..1e3f5f4 100644
--- a/gcc/testsuite/gcc.dg/cast-3.c
+++ b/gcc/testsuite/gcc.dg/cast-3.c
@@ -24,8 +24,8 @@ f (void)
(union u) l; /* { dg-error "cast to union type from type not present in union" } */
(int) sv; /* { dg-error "aggregate value used where an integer was expected" } */
(int) uv; /* { dg-error "aggregate value used where an integer was expected" } */
- (float) sv; /* { dg-error "aggregate value used where a float was expected" } */
- (float) uv; /* { dg-error "aggregate value used where a float was expected" } */
+ (float) sv; /* { dg-error "aggregate value used where a floating-point was expected" } */
+ (float) uv; /* { dg-error "aggregate value used where a floating-point was expected" } */
(_Complex double) sv; /* { dg-error "aggregate value used where a complex was expected" } */
(_Complex double) uv; /* { dg-error "aggregate value used where a complex was expected" } */
(void *) sv; /* { dg-error "cannot convert to a pointer type" } */
diff --git a/gcc/testsuite/gcc.dg/cdce1.c b/gcc/testsuite/gcc.dg/cdce1.c
index b23ad63..e7d2ca7 100644
--- a/gcc/testsuite/gcc.dg/cdce1.c
+++ b/gcc/testsuite/gcc.dg/cdce1.c
@@ -1,8 +1,9 @@
-/* { dg-do run } */
-/* { dg-options "-O2 -fmath-errno -fdump-tree-cdce-details -lm" } */
+/* { dg-do run } */
+/* { dg-options "-O2 -fmath-errno -fdump-tree-cdce-details -fdump-tree-optimized -lm" } */
/* { dg-require-effective-target int32plus } */
-/* { dg-final { scan-tree-dump "cdce1.c:16: .* function call is shrink-wrapped into error conditions\." "cdce" } } */
/* { dg-require-effective-target large_double } */
+/* { dg-final { scan-tree-dump "cdce1.c:17: \[^\n\r]* function call is shrink-wrapped into error conditions\." "cdce" } } */
+/* { dg-final { scan-tree-dump "pow \\(\[^\n\r]*\\); \\\[tail call\\\]" "optimized" } } */
#include <stdlib.h>
#include <math.h>
diff --git a/gcc/testsuite/gcc.dg/cdce2.c b/gcc/testsuite/gcc.dg/cdce2.c
index 30e7cb1..7924973 100644
--- a/gcc/testsuite/gcc.dg/cdce2.c
+++ b/gcc/testsuite/gcc.dg/cdce2.c
@@ -1,7 +1,8 @@
-/* { dg-do run } */
+/* { dg-do run } */
/* { dg-skip-if "doubles are floats" { "avr-*-*" } } */
-/* { dg-options "-O2 -fmath-errno -fdump-tree-cdce-details -lm" } */
-/* { dg-final { scan-tree-dump "cdce2.c:15: .* function call is shrink-wrapped into error conditions\." "cdce" } } */
+/* { dg-options "-O2 -fmath-errno -fdump-tree-cdce-details -fdump-tree-optimized -lm" } */
+/* { dg-final { scan-tree-dump "cdce2.c:16: \[^\n\r]* function call is shrink-wrapped into error conditions\." "cdce" } } */
+/* { dg-final { scan-tree-dump "log \\(\[^\n\r]*\\); \\\[tail call\\\]" "optimized" } } */
#include <stdlib.h>
#include <math.h>
diff --git a/gcc/testsuite/gcc.dg/cdce3.c b/gcc/testsuite/gcc.dg/cdce3.c
new file mode 100644
index 0000000..7e85d8a
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/cdce3.c
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target hard_float } */
+/* { dg-options "-O2 -fmath-errno -fdump-tree-cdce-details -fdump-tree-optimized" } */
+/* { dg-final { scan-tree-dump "cdce3.c:10: \[^\n\r]* function call is shrink-wrapped into error conditions\." "cdce" } } */
+/* { dg-final { scan-tree-dump "sqrtf \\(\[^\n\r]*\\); \\\[tail call\\\]" "optimized" } } */
+
+float sqrtf (float);
+float foo (float x)
+{
+ return sqrtf (x);
+}
+
diff --git a/gcc/testsuite/gcc.dg/const-1.c b/gcc/testsuite/gcc.dg/const-1.c
index a5b2b16..2e95bd8 100644
--- a/gcc/testsuite/gcc.dg/const-1.c
+++ b/gcc/testsuite/gcc.dg/const-1.c
@@ -1,5 +1,5 @@
/* { dg-do compile { target nonpic } } */
-/* { dg-options "-O2 -Wsuggest-attribute=const" } */
+/* { dg-options "-O2 -Wsuggest-attribute=const -fno-finite-loops" } */
extern int extern_const(int a) __attribute__ ((const));
diff --git a/gcc/testsuite/gcc.dg/cpp/isysroot-1.c b/gcc/testsuite/gcc.dg/cpp/isysroot-1.c
index 7263ce4..4c54f9e 100644
--- a/gcc/testsuite/gcc.dg/cpp/isysroot-1.c
+++ b/gcc/testsuite/gcc.dg/cpp/isysroot-1.c
@@ -1,10 +1,17 @@
/* { dg-options "-isysroot ${srcdir}/gcc.dg/cpp" } */
/* { dg-do compile { target *-*-darwin* } } */
-#include <stdio.h>
+/* For the test to succeed there needs to be some header that is to be found
+ in the 'expected' place i.e. <sysroot>/usr/include/. It's important that
+ it is not the name of a header for which fixincludes have been applied,
+ since such headers will be found in the gcc include-fixed dir and, in
+ general, reference additional headers. The dummy sysroot will prevent the
+ additional headers from being found, resulting in a failed test. So use
+ a header name we don't expect to see. */
+#include <example.h>
int main()
{
- /* Special stdio.h supplies function foo. */
+ /* Special example.h supplies function foo. */
void (*x)(void) = foo;
return 0;
}
diff --git a/gcc/testsuite/gcc.dg/cpp/source_date_epoch-2.c b/gcc/testsuite/gcc.dg/cpp/source_date_epoch-2.c
index ae18362..2ca8fa3 100644
--- a/gcc/testsuite/gcc.dg/cpp/source_date_epoch-2.c
+++ b/gcc/testsuite/gcc.dg/cpp/source_date_epoch-2.c
@@ -6,7 +6,7 @@
int
main(void)
{
- __builtin_printf ("%s %s\n", __DATE__, __TIME__); /* { dg-error "SOURCE_DATE_EPOCH must expand" } */
+ __builtin_printf ("%s %s\n", __DATE__, __TIME__); /* { dg-error "environment variable 'SOURCE_DATE_EPOCH' must expand" } */
__builtin_printf ("%s %s\n", __DATE__, __TIME__);
return 0;
}
diff --git a/gcc/testsuite/gcc.dg/cpp/usr/include/stdio.h b/gcc/testsuite/gcc.dg/cpp/usr/include/example.h
index c674e89..c674e89 100644
--- a/gcc/testsuite/gcc.dg/cpp/usr/include/stdio.h
+++ b/gcc/testsuite/gcc.dg/cpp/usr/include/example.h
diff --git a/gcc/testsuite/gcc.dg/darwin-minversion-1.c b/gcc/testsuite/gcc.dg/darwin-minversion-1.c
index ee6493a..5f8524f 100644
--- a/gcc/testsuite/gcc.dg/darwin-minversion-1.c
+++ b/gcc/testsuite/gcc.dg/darwin-minversion-1.c
@@ -1,6 +1,6 @@
/* Basic test for -mmacosx-version-min switch on Darwin. */
/* { dg-options "-mmacosx-version-min=10.5" } */
-/* { dg-do run { target *-*-darwin* } } */
+/* { dg-do compile { target *-*-darwin* } } */
int
main ()
diff --git a/gcc/testsuite/gcc.dg/darwin-minversion-2.c b/gcc/testsuite/gcc.dg/darwin-minversion-2.c
index 46fab67..3dbbca6 100644
--- a/gcc/testsuite/gcc.dg/darwin-minversion-2.c
+++ b/gcc/testsuite/gcc.dg/darwin-minversion-2.c
@@ -1,6 +1,6 @@
/* Basic test for -mmacosx-version-min switch on Darwin. */
/* { dg-options "-mmacosx-version-min=10.1 -mmacosx-version-min=10.5" } */
-/* { dg-do run { target *-*-darwin* } } */
+/* { dg-do compile { target *-*-darwin* } } */
int
main ()
diff --git a/gcc/testsuite/gcc.dg/darwin-minversion-link.c b/gcc/testsuite/gcc.dg/darwin-minversion-link.c
new file mode 100644
index 0000000..0a80048
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/darwin-minversion-link.c
@@ -0,0 +1,26 @@
+/* Test that we can handle leading-zeros on mmacosx-version-min for invocations
+ including linking (so that spec processing works). To make sure that any
+ necessary target libs are present we make this specific to the target version
+ being built. */
+/* { dg-do link { target *-*-darwin* } } */
+/* { dg-additional-options "-mmacosx-version-min=010.04.11 -DCHECK=1049" { target *-*-darwin8* } } */
+/* { dg-additional-options "-mmacosx-version-min=010.05.08 -DCHECK=1058" { target *-*-darwin9* } } */
+/* { dg-additional-options "-mmacosx-version-min=010.06.08 -DCHECK=1068" { target *-*-darwin10* } } */
+/* { dg-additional-options "-mmacosx-version-min=010.07.05 -DCHECK=1075" { target *-*-darwin11* } } */
+/* { dg-additional-options "-mmacosx-version-min=010.08.05 -DCHECK=1085" { target *-*-darwin12* } } */
+/* { dg-additional-options "-mmacosx-version-min=010.09.05 -DCHECK=1095" { target *-*-darwin13* } } */
+/* { dg-additional-options "-mmacosx-version-min=010.010.03 -DCHECK=101003" { target *-*-darwin14* } } */
+/* { dg-additional-options "-mmacosx-version-min=010.011.06 -DCHECK=101106" { target *-*-darwin15* } } */
+/* { dg-additional-options "-mmacosx-version-min=010.012.06 -DCHECK=101206" { target *-*-darwin16* } } */
+/* { dg-additional-options "-mmacosx-version-min=010.013.06 -DCHECK=101306" { target *-*-darwin17* } } */
+/* This next test covers 10.18 and (currently unreleased) 10.19 for now. */
+/* { dg-additional-options "-mmacosx-version-min=010.014.05 -DCHECK=101405" { target *-*-darwin1[89]* } } */
+
+int
+main ()
+{
+#if __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ != CHECK
+ fail me;
+#endif
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/darwin-weakimport-3.c b/gcc/testsuite/gcc.dg/darwin-weakimport-3.c
index 77ab980..a15b5b0 100644
--- a/gcc/testsuite/gcc.dg/darwin-weakimport-3.c
+++ b/gcc/testsuite/gcc.dg/darwin-weakimport-3.c
@@ -1,5 +1,20 @@
/* { dg-do compile { target *-*-darwin* } } */
-/* { dg-options "-fno-asynchronous-unwind-tables" } */
+
+/* Here we want to test if "foo" gets placed into a coalesced
+ section (it should not).
+
+ However, for i386, and PIC code we have a "get_pc thunk" that
+ is (correctly) placed in a coalesced section when using an older
+ linker - also unwind tables are emitted into coalesced.
+
+ With modern linkers this is moot, since even weak symbols
+ are emitted into the regular sections.
+
+ To avoid the unwind tables -fno-asynchronous-unwind-tables.
+ To ensure that we emit code for an older linker -mtarget-linker
+ To avoid the get_pc thunk optimise at least O1. */
+
+/* { dg-options "-fno-asynchronous-unwind-tables -O1 -mtarget-linker 85.2" } */
/* { dg-require-weak "" } */
/* { dg-final { scan-assembler-not "coalesced" } } */
diff --git a/gcc/testsuite/gcc.dg/debug/dwarf2/fesd-any.c b/gcc/testsuite/gcc.dg/debug/dwarf2/fesd-any.c
index 810788a..4062268 100644
--- a/gcc/testsuite/gcc.dg/debug/dwarf2/fesd-any.c
+++ b/gcc/testsuite/gcc.dg/debug/dwarf2/fesd-any.c
@@ -1,5 +1,5 @@
// { dg-do compile }
-// { dg-options "-gdwarf -dA -femit-struct-debug-detailed=any" }
+// { dg-options "-gdwarf -dA -femit-struct-debug-detailed=any -fno-eliminate-unused-debug-symbols" }
// { dg-final { scan-assembler "timespec.*DW_AT_name" } }
// { dg-final { scan-assembler "tv_sec.*DW_AT_name" } }
// { dg-final { scan-assembler "tv_nsec.*DW_AT_name" } }
diff --git a/gcc/testsuite/gcc.dg/debug/dwarf2/fesd-baseonly.c b/gcc/testsuite/gcc.dg/debug/dwarf2/fesd-baseonly.c
index aefcb87..fffdf04 100644
--- a/gcc/testsuite/gcc.dg/debug/dwarf2/fesd-baseonly.c
+++ b/gcc/testsuite/gcc.dg/debug/dwarf2/fesd-baseonly.c
@@ -1,5 +1,5 @@
// { dg-do compile }
-// { dg-options "-gdwarf -dA -femit-struct-debug-baseonly" }
+// { dg-options "-gdwarf -dA -femit-struct-debug-baseonly -fno-eliminate-unused-debug-symbols" }
// { dg-final { scan-assembler "timespec.*DW_AT_name" } }
// { dg-final { scan-assembler-not "tv_sec.*DW_AT_name" } }
// { dg-final { scan-assembler-not "tv_nsec.*DW_AT_name" } }
diff --git a/gcc/testsuite/gcc.dg/debug/dwarf2/fesd-none.c b/gcc/testsuite/gcc.dg/debug/dwarf2/fesd-none.c
index 193c05d..6fba512 100644
--- a/gcc/testsuite/gcc.dg/debug/dwarf2/fesd-none.c
+++ b/gcc/testsuite/gcc.dg/debug/dwarf2/fesd-none.c
@@ -1,5 +1,5 @@
// { dg-do compile }
-// { dg-options "-gdwarf -dA -femit-struct-debug-detailed=none" }
+// { dg-options "-gdwarf -dA -femit-struct-debug-detailed=none -fno-eliminate-unused-debug-symbols" }
// { dg-final { scan-assembler "timespec.*DW_AT_name" } }
// { dg-final { scan-assembler-not "tv_sec.*DW_AT_name" } }
// { dg-final { scan-assembler-not "tv_nsec.*DW_AT_name" } }
diff --git a/gcc/testsuite/gcc.dg/debug/dwarf2/fesd-reduced.c b/gcc/testsuite/gcc.dg/debug/dwarf2/fesd-reduced.c
index ebbfc36..4209e30 100644
--- a/gcc/testsuite/gcc.dg/debug/dwarf2/fesd-reduced.c
+++ b/gcc/testsuite/gcc.dg/debug/dwarf2/fesd-reduced.c
@@ -1,5 +1,5 @@
// { dg-do compile }
-// { dg-options "-gdwarf -dA -femit-struct-debug-reduced" }
+// { dg-options "-gdwarf -dA -femit-struct-debug-reduced -fno-eliminate-unused-debug-symbols" }
// { dg-final { scan-assembler "timespec.*DW_AT_name" } }
// { dg-final { scan-assembler "tv_sec.*DW_AT_name" } }
// { dg-final { scan-assembler "tv_nsec.*DW_AT_name" } }
diff --git a/gcc/testsuite/gcc.dg/debug/dwarf2/fesd-sys.c b/gcc/testsuite/gcc.dg/debug/dwarf2/fesd-sys.c
index ad0a44a..9c100d7 100644
--- a/gcc/testsuite/gcc.dg/debug/dwarf2/fesd-sys.c
+++ b/gcc/testsuite/gcc.dg/debug/dwarf2/fesd-sys.c
@@ -1,5 +1,5 @@
// { dg-do compile }
-// { dg-options "-gdwarf -dA -femit-struct-debug-detailed=sys" }
+// { dg-options "-gdwarf -dA -femit-struct-debug-detailed=sys -fno-eliminate-unused-debug-symbols" }
// { dg-final { scan-assembler "timespec.*DW_AT_name" } }
// { dg-final { scan-assembler "tv_sec.*DW_AT_name" } }
// { dg-final { scan-assembler "tv_nsec.*DW_AT_name" } }
diff --git a/gcc/testsuite/gcc.dg/debug/enum-1.c b/gcc/testsuite/gcc.dg/debug/enum-1.c
index 7681e9b..32124c1 100644
--- a/gcc/testsuite/gcc.dg/debug/enum-1.c
+++ b/gcc/testsuite/gcc.dg/debug/enum-1.c
@@ -1,5 +1,6 @@
/* Verify that used enums are output. */
/* { dg-do compile } */
+/* { dg-additional-options "-fno-eliminate-unused-debug-symbols" { target powerpc-ibm-aix* } } */
/* { dg-final { scan-assembler "JTI_MAX" } } */
int var;
diff --git a/gcc/testsuite/gcc.dg/debug/pr85252.c b/gcc/testsuite/gcc.dg/debug/pr85252.c
index 6e5ca85..9bd4d48 100644
--- a/gcc/testsuite/gcc.dg/debug/pr85252.c
+++ b/gcc/testsuite/gcc.dg/debug/pr85252.c
@@ -5,7 +5,7 @@ void
foo (void)
{
static char a[0] = "";
- static char b[0] = "b"; /* { dg-warning "initializer-string for array of chars is too long" } */
+ static char b[0] = "b"; /* { dg-warning "initializer-string for array of 'char' is too long" } */
static char c[1] = "c";
- static char d[1] = "de"; /* { dg-warning "initializer-string for array of chars is too long" } */
+ static char d[1] = "de"; /* { dg-warning "initializer-string for array of 'char' is too long" } */
}
diff --git a/gcc/testsuite/gcc.dg/dfp/cast-bad.c b/gcc/testsuite/gcc.dg/dfp/cast-bad.c
index e9e31ff..fcaf22d 100644
--- a/gcc/testsuite/gcc.dg/dfp/cast-bad.c
+++ b/gcc/testsuite/gcc.dg/dfp/cast-bad.c
@@ -31,10 +31,10 @@ f (void)
(struct s) d128; /* { dg-error "conversion to non-scalar type requested" } */
(union u) d128; /* { dg-error "cast to union type from type not present in union" } */
- (_Decimal32) sv; /* { dg-error "aggregate value used where a float was expected" } */
- (_Decimal32) uv; /* { dg-error "aggregate value used where a float was expected" } */
- (_Decimal64) sv; /* { dg-error "aggregate value used where a float was expected" } */
- (_Decimal64) uv; /* { dg-error "aggregate value used where a float was expected" } */
- (_Decimal128) sv; /* { dg-error "aggregate value used where a float was expected" } */
- (_Decimal128) uv; /* { dg-error "aggregate value used where a float was expected" } */
+ (_Decimal32) sv; /* { dg-error "aggregate value used where a floating-point was expected" } */
+ (_Decimal32) uv; /* { dg-error "aggregate value used where a floating-point was expected" } */
+ (_Decimal64) sv; /* { dg-error "aggregate value used where a floating-point was expected" } */
+ (_Decimal64) uv; /* { dg-error "aggregate value used where a floating-point was expected" } */
+ (_Decimal128) sv; /* { dg-error "aggregate value used where a floating-point was expected" } */
+ (_Decimal128) uv; /* { dg-error "aggregate value used where a floating-point was expected" } */
}
diff --git a/gcc/testsuite/gcc.dg/dfp/warn-abs-2.c b/gcc/testsuite/gcc.dg/dfp/warn-abs-2.c
index c1a1994..403b039 100644
--- a/gcc/testsuite/gcc.dg/dfp/warn-abs-2.c
+++ b/gcc/testsuite/gcc.dg/dfp/warn-abs-2.c
@@ -8,16 +8,16 @@
void tst_decimal (_Decimal32 *p32, _Decimal64 *p64, _Decimal128 *p128)
{
*p32 = abs(*p32); /* { dg-warning "using integer absolute value function" } */
- *p64 = fabs(*p64); /* { dg-warning "using floating point absolute value function" } */
+ *p64 = fabs(*p64); /* { dg-warning "using floating-point absolute value function" } */
*p128 = cabsl(*p128); /* { dg-warning "using complex absolute value function" } */
}
void tst_notdecimal (int *pi, double *pd, long double *pld, complex double *pc)
{
- *pi = __builtin_fabsd32 (*pi); /* { dg-warning "using decimal floating point absolute value function" } */
- *pd = __builtin_fabsd64 (*pd); /* { dg-warning "using decimal floating point absolute value function" } */
- *pld = __builtin_fabsd64 (*pld); /* { dg-warning "using decimal floating point absolute value function" } */
- *pc = __builtin_fabsd128 (*pc); /* { dg-warning "using decimal floating point absolute value function" } */
+ *pi = __builtin_fabsd32 (*pi); /* { dg-warning "using decimal floating-point absolute value function" } */
+ *pd = __builtin_fabsd64 (*pd); /* { dg-warning "using decimal floating-point absolute value function" } */
+ *pld = __builtin_fabsd64 (*pld); /* { dg-warning "using decimal floating-point absolute value function" } */
+ *pc = __builtin_fabsd128 (*pc); /* { dg-warning "using decimal floating-point absolute value function" } */
}
void
diff --git a/gcc/testsuite/gcc.dg/enum-mode-1.c b/gcc/testsuite/gcc.dg/enum-mode-1.c
index 09276b7..9d3ea26 100644
--- a/gcc/testsuite/gcc.dg/enum-mode-1.c
+++ b/gcc/testsuite/gcc.dg/enum-mode-1.c
@@ -1,10 +1,10 @@
/* { dg-do compile } */
-enum e1 { A = 256 } __attribute__((__mode__(__byte__))); /* { dg-error "specified mode too small for enumeral values" } */
-enum e2 { B = 256 } __attribute__((__packed__, __mode__(__byte__))); /* { dg-error "specified mode too small for enumeral values" } */
+enum e1 { A = 256 } __attribute__((__mode__(__byte__))); /* { dg-error "specified mode too small for enumerated values" } */
+enum e2 { B = 256 } __attribute__((__packed__, __mode__(__byte__))); /* { dg-error "specified mode too small for enumerated values" } */
-enum e3 { C = __INT_MAX__ } __attribute__((__mode__(__QI__))); /* { dg-error "specified mode too small for enumeral values" } */
-enum e4 { D = __INT_MAX__ } __attribute__((__packed__, __mode__(__QI__))); /* { dg-error "specified mode too small for enumeral values" } */
+enum e3 { C = __INT_MAX__ } __attribute__((__mode__(__QI__))); /* { dg-error "specified mode too small for enumerated values" } */
+enum e4 { D = __INT_MAX__ } __attribute__((__packed__, __mode__(__QI__))); /* { dg-error "specified mode too small for enumerated values" } */
-enum e5 { E = __INT_MAX__ } __attribute__((__mode__(__HI__))); /* { dg-error "specified mode too small for enumeral values" "" { xfail int16 } } */
-enum e6 { F = __INT_MAX__ } __attribute__((__packed__, __mode__(__HI__))); /* { dg-error "specified mode too small for enumeral values" "" { xfail int16 } } */
+enum e5 { E = __INT_MAX__ } __attribute__((__mode__(__HI__))); /* { dg-error "specified mode too small for enumerated values" "" { xfail int16 } } */
+enum e6 { F = __INT_MAX__ } __attribute__((__packed__, __mode__(__HI__))); /* { dg-error "specified mode too small for enumerated values" "" { xfail int16 } } */
diff --git a/gcc/testsuite/gcc.dg/format/dfp-printf-1.c b/gcc/testsuite/gcc.dg/format/dfp-printf-1.c
index e92f161..a290895 100644
--- a/gcc/testsuite/gcc.dg/format/dfp-printf-1.c
+++ b/gcc/testsuite/gcc.dg/format/dfp-printf-1.c
@@ -17,6 +17,8 @@ foo (_Decimal32 x, _Decimal64 y, _Decimal128 z, int i, unsigned int j,
/* Check lack of warnings for valid usage. */
+ printf ("%Ha\n", x);
+ printf ("%HA\n", x);
printf ("%Hf\n", x);
printf ("%HF\n", x);
printf ("%He\n", x);
@@ -24,6 +26,8 @@ foo (_Decimal32 x, _Decimal64 y, _Decimal128 z, int i, unsigned int j,
printf ("%Hg\n", x);
printf ("%HG\n", x);
+ printf ("%Da\n", y);
+ printf ("%DA\n", y);
printf ("%Df\n", y);
printf ("%DF\n", y);
printf ("%De\n", y);
@@ -31,6 +35,8 @@ foo (_Decimal32 x, _Decimal64 y, _Decimal128 z, int i, unsigned int j,
printf ("%Dg\n", y);
printf ("%DG\n", y);
+ printf ("%DDa\n", z);
+ printf ("%DDA\n", z);
printf ("%DDf\n", z);
printf ("%DDF\n", z);
printf ("%DDe\n", z);
@@ -43,12 +49,16 @@ foo (_Decimal32 x, _Decimal64 y, _Decimal128 z, int i, unsigned int j,
/* Check warnings for type mismatches. */
+ printf ("%Ha\n", y); /* { dg-warning "expects argument" "bad use of %H" } */
+ printf ("%HA\n", y); /* { dg-warning "expects argument" "bad use of %H" } */
printf ("%Hf\n", y); /* { dg-warning "expects argument" "bad use of %H" } */
printf ("%HF\n", y); /* { dg-warning "expects argument" "bad use of %H" } */
printf ("%He\n", y); /* { dg-warning "expects argument" "bad use of %H" } */
printf ("%HE\n", y); /* { dg-warning "expects argument" "bad use of %H" } */
printf ("%Hg\n", y); /* { dg-warning "expects argument" "bad use of %H" } */
printf ("%HG\n", y); /* { dg-warning "expects argument" "bad use of %H" } */
+ printf ("%Ha\n", z); /* { dg-warning "expects argument" "bad use of %H" } */
+ printf ("%HA\n", z); /* { dg-warning "expects argument" "bad use of %H" } */
printf ("%Hf\n", z); /* { dg-warning "expects argument" "bad use of %H" } */
printf ("%HF\n", z); /* { dg-warning "expects argument" "bad use of %H" } */
printf ("%He\n", z); /* { dg-warning "expects argument" "bad use of %H" } */
@@ -56,12 +66,16 @@ foo (_Decimal32 x, _Decimal64 y, _Decimal128 z, int i, unsigned int j,
printf ("%Hg\n", z); /* { dg-warning "expects argument" "bad use of %H" } */
printf ("%HG\n", z); /* { dg-warning "expects argument" "bad use of %H" } */
+ printf ("%Da\n", x); /* { dg-warning "expects argument" "bad use of %D" } */
+ printf ("%DA\n", x); /* { dg-warning "expects argument" "bad use of %D" } */
printf ("%Df\n", x); /* { dg-warning "expects argument" "bad use of %D" } */
printf ("%DF\n", x); /* { dg-warning "expects argument" "bad use of %D" } */
printf ("%De\n", x); /* { dg-warning "expects argument" "bad use of %D" } */
printf ("%DE\n", x); /* { dg-warning "expects argument" "bad use of %D" } */
printf ("%Dg\n", x); /* { dg-warning "expects argument" "bad use of %D" } */
printf ("%DG\n", x); /* { dg-warning "expects argument" "bad use of %D" } */
+ printf ("%Da\n", z); /* { dg-warning "expects argument" "bad use of %D" } */
+ printf ("%DA\n", z); /* { dg-warning "expects argument" "bad use of %D" } */
printf ("%Df\n", z); /* { dg-warning "expects argument" "bad use of %D" } */
printf ("%DF\n", z); /* { dg-warning "expects argument" "bad use of %D" } */
printf ("%De\n", z); /* { dg-warning "expects argument" "bad use of %D" } */
@@ -69,12 +83,16 @@ foo (_Decimal32 x, _Decimal64 y, _Decimal128 z, int i, unsigned int j,
printf ("%Dg\n", z); /* { dg-warning "expects argument" "bad use of %D" } */
printf ("%DG\n", z); /* { dg-warning "expects argument" "bad use of %D" } */
+ printf ("%DDa\n", x); /* { dg-warning "expects argument" "bad use of %DD" } */
+ printf ("%DDA\n", x); /* { dg-warning "expects argument" "bad use of %DD" } */
printf ("%DDf\n", x); /* { dg-warning "expects argument" "bad use of %DD" } */
printf ("%DDF\n", x); /* { dg-warning "expects argument" "bad use of %DD" } */
printf ("%DDe\n", x); /* { dg-warning "expects argument" "bad use of %DD" } */
printf ("%DDE\n", x); /* { dg-warning "expects argument" "bad use of %DD" } */
printf ("%DDg\n", x); /* { dg-warning "expects argument" "bad use of %DD" } */
printf ("%DDG\n", x); /* { dg-warning "expects argument" "bad use of %DD" } */
+ printf ("%DDa\n", y); /* { dg-warning "expects argument" "bad use of %DD" } */
+ printf ("%DDA\n", y); /* { dg-warning "expects argument" "bad use of %DD" } */
printf ("%DDf\n", y); /* { dg-warning "expects argument" "bad use of %DD" } */
printf ("%DDF\n", y); /* { dg-warning "expects argument" "bad use of %DD" } */
printf ("%DDe\n", y); /* { dg-warning "expects argument" "bad use of %DD" } */
@@ -90,8 +108,8 @@ foo (_Decimal32 x, _Decimal64 y, _Decimal128 z, int i, unsigned int j,
printf ("%Hu\n", j); /* { dg-warning "length" "bad use of %H" } */
printf ("%Hx\n", j); /* { dg-warning "length" "bad use of %H" } */
printf ("%HX\n", j); /* { dg-warning "length" "bad use of %H" } */
- printf ("%Ha\n", d); /* { dg-warning "length" "bad use of %H" } */
- printf ("%HA\n", d); /* { dg-warning "length" "bad use of %H" } */
+ printf ("%Ha\n", d); /* { dg-warning "expects argument" "bad use of %H" } */
+ printf ("%HA\n", d); /* { dg-warning "expects argument" "bad use of %H" } */
printf ("%Hc\n", i); /* { dg-warning "length" "bad use of %H" } */
printf ("%Hs\n", p); /* { dg-warning "length" "bad use of %H" } */
printf ("%Hp\n", p); /* { dg-warning "length" "bad use of %H" } */
@@ -100,6 +118,8 @@ foo (_Decimal32 x, _Decimal64 y, _Decimal128 z, int i, unsigned int j,
/* Sanity checks for flags, field width, and precision in formats for
DFP types. */
+ printf ("%-Ha\n", x);
+ printf ("%+HA\n", x);
printf ("%-Hf\n", x);
printf ("%+HF\n", x);
printf ("% He\n", x);
@@ -107,6 +127,8 @@ foo (_Decimal32 x, _Decimal64 y, _Decimal128 z, int i, unsigned int j,
printf ("%0Hg\n", x);
printf ("%#0HG\n", x);
+ printf ("%0#Da\n", y);
+ printf ("%0DA\n", y);
printf ("%0#Df\n", y);
printf ("%0DF\n", y);
printf ("%#De\n", y);
@@ -114,6 +136,8 @@ foo (_Decimal32 x, _Decimal64 y, _Decimal128 z, int i, unsigned int j,
printf ("%-#0Dg\n", y); /* { dg-warning "flag ignored" "ignore flag" } */
printf ("%0+ DG\n", y); /* { dg-warning "flag ignored" "ignore flag" } */
+ printf ("%DDa\n", z);
+ printf ("%0DDA\n", z);
printf ("%DDf\n", z);
printf ("%0DDF\n", z);
printf ("%#0DDe\n", z);
diff --git a/gcc/testsuite/gcc.dg/format/dfp-scanf-1.c b/gcc/testsuite/gcc.dg/format/dfp-scanf-1.c
index ffa12a8..6df3bc6 100644
--- a/gcc/testsuite/gcc.dg/format/dfp-scanf-1.c
+++ b/gcc/testsuite/gcc.dg/format/dfp-scanf-1.c
@@ -17,6 +17,8 @@ voo (_Decimal32 *x, _Decimal64 *y, _Decimal128 *z, int *i, unsigned int *j,
/* Check lack of warnings for valid usage. */
+ scanf ("%Ha", x);
+ scanf ("%HA", x);
scanf ("%Hf", x);
scanf ("%HF", x);
scanf ("%He", x);
@@ -24,6 +26,8 @@ voo (_Decimal32 *x, _Decimal64 *y, _Decimal128 *z, int *i, unsigned int *j,
scanf ("%Hg", x);
scanf ("%HG", x);
+ scanf ("%Da", y);
+ scanf ("%DA", y);
scanf ("%Df", y);
scanf ("%DF", y);
scanf ("%De", y);
@@ -31,6 +35,8 @@ voo (_Decimal32 *x, _Decimal64 *y, _Decimal128 *z, int *i, unsigned int *j,
scanf ("%Dg", y);
scanf ("%DG", y);
+ scanf ("%DDa", z);
+ scanf ("%DDA", z);
scanf ("%DDf", z);
scanf ("%DDF", z);
scanf ("%DDe", z);
@@ -43,12 +49,16 @@ voo (_Decimal32 *x, _Decimal64 *y, _Decimal128 *z, int *i, unsigned int *j,
/* Check warnings for type mismatches. */
+ scanf ("%Ha", y); /* { dg-warning "expects argument" "bad use of %H" } */
+ scanf ("%HA", y); /* { dg-warning "expects argument" "bad use of %H" } */
scanf ("%Hf", y); /* { dg-warning "expects argument" "bad use of %H" } */
scanf ("%HF", y); /* { dg-warning "expects argument" "bad use of %H" } */
scanf ("%He", y); /* { dg-warning "expects argument" "bad use of %H" } */
scanf ("%HE", y); /* { dg-warning "expects argument" "bad use of %H" } */
scanf ("%Hg", y); /* { dg-warning "expects argument" "bad use of %H" } */
scanf ("%HG", y); /* { dg-warning "expects argument" "bad use of %H" } */
+ scanf ("%Ha", z); /* { dg-warning "expects argument" "bad use of %H" } */
+ scanf ("%HA", z); /* { dg-warning "expects argument" "bad use of %H" } */
scanf ("%Hf", z); /* { dg-warning "expects argument" "bad use of %H" } */
scanf ("%HF", z); /* { dg-warning "expects argument" "bad use of %H" } */
scanf ("%He", z); /* { dg-warning "expects argument" "bad use of %H" } */
@@ -56,12 +66,16 @@ voo (_Decimal32 *x, _Decimal64 *y, _Decimal128 *z, int *i, unsigned int *j,
scanf ("%Hg", z); /* { dg-warning "expects argument" "bad use of %H" } */
scanf ("%HG", z); /* { dg-warning "expects argument" "bad use of %H" } */
+ scanf ("%Da", x); /* { dg-warning "expects argument" "bad use of %D" } */
+ scanf ("%DA", x); /* { dg-warning "expects argument" "bad use of %D" } */
scanf ("%Df", x); /* { dg-warning "expects argument" "bad use of %D" } */
scanf ("%DF", x); /* { dg-warning "expects argument" "bad use of %D" } */
scanf ("%De", x); /* { dg-warning "expects argument" "bad use of %D" } */
scanf ("%DE", x); /* { dg-warning "expects argument" "bad use of %D" } */
scanf ("%Dg", x); /* { dg-warning "expects argument" "bad use of %D" } */
scanf ("%DG", x); /* { dg-warning "expects argument" "bad use of %D" } */
+ scanf ("%Da", z); /* { dg-warning "expects argument" "bad use of %D" } */
+ scanf ("%DA", z); /* { dg-warning "expects argument" "bad use of %D" } */
scanf ("%Df", z); /* { dg-warning "expects argument" "bad use of %D" } */
scanf ("%DF", z); /* { dg-warning "expects argument" "bad use of %D" } */
scanf ("%De", z); /* { dg-warning "expects argument" "bad use of %D" } */
@@ -69,12 +83,16 @@ voo (_Decimal32 *x, _Decimal64 *y, _Decimal128 *z, int *i, unsigned int *j,
scanf ("%Dg", z); /* { dg-warning "expects argument" "bad use of %D" } */
scanf ("%DG", z); /* { dg-warning "expects argument" "bad use of %D" } */
+ scanf ("%DDa", x); /* { dg-warning "expects argument" "bad use of %DD" } */
+ scanf ("%DDA", x); /* { dg-warning "expects argument" "bad use of %DD" } */
scanf ("%DDf", x); /* { dg-warning "expects argument" "bad use of %DD" } */
scanf ("%DDF", x); /* { dg-warning "expects argument" "bad use of %DD" } */
scanf ("%DDe", x); /* { dg-warning "expects argument" "bad use of %DD" } */
scanf ("%DDE", x); /* { dg-warning "expects argument" "bad use of %DD" } */
scanf ("%DDg", x); /* { dg-warning "expects argument" "bad use of %DD" } */
scanf ("%DDG", x); /* { dg-warning "expects argument" "bad use of %DD" } */
+ scanf ("%DDa", y); /* { dg-warning "expects argument" "bad use of %DD" } */
+ scanf ("%DDA", y); /* { dg-warning "expects argument" "bad use of %DD" } */
scanf ("%DDf", y); /* { dg-warning "expects argument" "bad use of %DD" } */
scanf ("%DDF", y); /* { dg-warning "expects argument" "bad use of %DD" } */
scanf ("%DDe", y); /* { dg-warning "expects argument" "bad use of %DD" } */
@@ -90,8 +108,8 @@ voo (_Decimal32 *x, _Decimal64 *y, _Decimal128 *z, int *i, unsigned int *j,
scanf ("%Hu\n", j); /* { dg-warning "length" "bad use of %H" } */
scanf ("%Hx\n", j); /* { dg-warning "length" "bad use of %H" } */
scanf ("%HX\n", j); /* { dg-warning "length" "bad use of %H" } */
- scanf ("%Ha\n", d); /* { dg-warning "length" "bad use of %H" } */
- scanf ("%HA\n", d); /* { dg-warning "length" "bad use of %H" } */
+ scanf ("%Ha\n", d); /* { dg-warning "expects argument" "bad use of %H" } */
+ scanf ("%HA\n", d); /* { dg-warning "expects argument" "bad use of %H" } */
scanf ("%Hc\n", i); /* { dg-warning "length" "bad use of %H" } */
scanf ("%Hs\n", p); /* { dg-warning "length" "bad use of %H" } */
scanf ("%Hp\n", p); /* { dg-warning "length" "bad use of %H" } */
diff --git a/gcc/testsuite/gcc.dg/format/gcc_diag-1.c b/gcc/testsuite/gcc.dg/format/gcc_diag-1.c
index 8761456..4a64d54 100644
--- a/gcc/testsuite/gcc.dg/format/gcc_diag-1.c
+++ b/gcc/testsuite/gcc.dg/format/gcc_diag-1.c
@@ -1,7 +1,7 @@
/* Test for GCC diagnostic formats. */
/* Origin: Kaveh Ghazi <ghazi@caip.rutgers.edu> */
/* { dg-do compile } */
-/* { dg-options "-Wformat" } */
+/* { dg-options "-Wformat -Wno-format-diag" } */
#include "format.h"
diff --git a/gcc/testsuite/gcc.dg/format/gcc_diag-11.c b/gcc/testsuite/gcc.dg/format/gcc_diag-11.c
new file mode 100644
index 0000000..a976c7a
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/format/gcc_diag-11.c
@@ -0,0 +1,455 @@
+/* Test warnings for common punctuation, quoting, and spelling issues
+ in GCC diagnostics.
+ { dg-do compile }
+ { dg-options "-Wformat -Wformat-diag" } */
+
+/* Magic identifiers must be set before the attribute is used. */
+
+typedef long long __gcc_host_wide_int__;
+
+typedef struct location_s
+{
+ const char *file;
+ int line;
+} location_t;
+
+union tree_node;
+typedef union tree_node *tree;
+
+/* Define gimple as a dummy type. The typedef must be provided for
+ the C test to find the symbol. */
+typedef struct gimple gimple;
+
+/* Likewise for cgraph_node. */
+typedef struct cgraph_node cgraph_node;
+
+#define ATTR(...) __attribute__ ((__VA_ARGS__))
+#define FORMAT(kind) ATTR (format (__gcc_## kind ##__, 1, 2))
+
+/* Raw formatting function like pp_format. */
+void diag_raw (const char*, ...) ATTR (format (__gcc_diag_raw__, 1, 2));
+void cdiag_raw (const char*, ...) ATTR (format (__gcc_cdiag_raw__, 1, 2));
+void tdiag_raw (const char*, ...) ATTR (format (gcc_tdiag_raw, 1, 2));
+void cxxdiag_raw (const char*, ...) ATTR (format (gcc_cxxdiag_raw, 1, 2));
+
+/* Basic formatting function_format. */
+void diag (const char*, ...) FORMAT (diag);
+
+/* Diagnostic formatting function like error or warning declared
+ by the C front end. */
+void cdiag (const char*, ...) FORMAT (cdiag);
+
+/* Diagnostic formatting function like error or warning declared
+ by the middle-end or back-end. */
+void tdiag (const char*, ...) FORMAT (tdiag);
+
+/* Diagnostic formatting function like error or warning declared
+ by the C++ front-end. */
+void cxxdiag (const char*, ...) FORMAT (cxxdiag);
+
+
+/* Verify that functions declared with __gcc_diag_raw__ attribute
+ are not subject to -Wformat-diag. */
+
+void test_diag_raw (tree t, gimple *gc)
+{
+ diag_raw ("a b");
+ diag_raw ("newline\n");
+ diag_raw ("lone period.");
+ diag_raw ("multiple punctuators: !!!");
+ diag_raw ("unbalanced paren (");
+ diag_raw ("keyword alignas and identifier_with_underscores");
+ diag_raw ("disable __builtin_abs with the -fno-builtin-abs option");
+ diag_raw ("who says I can't have no stinkin' contractions? ");
+
+ cdiag_raw ("__atomic_sync (%qE) == 7???", t);
+ tdiag_raw ("__builtin_abs (%E) < 0!?!", t);
+ cxxdiag_raw ("template <> int f (%E", t);
+}
+
+/* Verify that functions declared with the C front-end __gcc_cdiag__
+ attribute detect invalid whitespace in format strings. */
+
+void test_cdiag_whitespace (tree t, gimple *gc)
+{
+ (void)&t; (void)&gc;
+
+ /* Verify that strings of leading spaces don't trigger a warning. */
+ cdiag (" a");
+ cdiag (" b");
+ cdiag (" c");
+ cdiag ("%< %>a");
+ cdiag ("%< %>a");
+ cdiag ("a b");
+ cdiag ("a b"); /* { dg-warning "unquoted sequence of 2 consecutive space characters" } */
+ cdiag ("a "); /* { dg-warning "spurious trailing space" } */
+ cdiag ("a "); /* { dg-warning "spurious trailing space" } */
+ cdiag ("a%< %>");
+ cdiag ("a%< %>%< %>");
+ cdiag ("a%< %> "); /* { dg-warning "spurious trailing space" } */
+ cdiag ("a%< %> %< %>"); /* { dg-warning "unquoted sequence of 2 consecutive space characters" } */
+
+ /* It's debatable whether the following two formst strings should
+ be diagnosed. They aren't only because it's simpler that way. */
+ cdiag ("a %< %>");
+ cdiag ("a%< %> %< %>");
+
+ /* Exercise other whitespace characters. */
+ cdiag ("a\fb"); /* { dg-warning "unquoted whitespace character '\\\\x0c'" } */
+ cdiag ("a\nb"); /* { dg-warning "unquoted whitespace character '\\\\x0a'" } */
+ cdiag ("a\rb"); /* { dg-warning "unquoted whitespace character '\\\\x0d'" } */
+ cdiag ("a\vb"); /* { dg-warning "unquoted whitespace character '\\\\x0b'" } */
+
+ cdiag ("First sentence. And a next.");
+ cdiag ("First sentence. not capitalized sentence"); /* { dg-warning "inconsistent capitalization" } */
+
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wformat-diag"
+
+ /* Verify that the warning can be suppressed. */
+ cdiag ("\ta\b c\vb\n");
+
+#pragma GCC diagnostic pop
+}
+
+
+void test_cdiag_control (tree t, gimple *gc)
+{
+ (void)&t; (void)&gc;
+
+ cdiag ("\1"); /* { dg-warning "unquoted control character '\\\\x01'" } */
+ cdiag ("a\ab"); /* { dg-warning "unquoted control character '\\\\x07'" } */
+ cdiag ("a\bb"); /* { dg-warning "unquoted control character '\\\\x08'" } */
+}
+
+
+void test_cdiag_punct (tree t, gimple *gc, int i)
+{
+ (void)&t; (void)&gc;
+
+ /* Exercise the period. */
+ cdiag (".abc"); /* { dg-warning "spurious leading punctuation sequence .\.." } */
+ cdiag ("abc;"); /* { dg-warning "spurious trailing punctuation sequence .;." } */
+ /* Verify that sentences that start with an uppercase letter and end
+ in a period are not diagnosed. */
+ cdiag ("This is a full sentence.");
+ cdiag ("Capitalized sentence (with a parethetical note).");
+ cdiag ("Not a full sentence;"); /* { dg-warning "spurious trailing punctuation sequence .;." } */
+ cdiag ("Neither is this one,"); /* { dg-warning "spurious trailing punctuation sequence .,." } */
+
+ /* Exercise the ellipsis. */
+ cdiag ("this message...");
+ cdiag ("...continues here");
+ cdiag ("but...not here"); /* { dg-warning "unquoted sequence of 3 consecutive punctuation characters" } */
+
+ /* Verify that parenthesized sentences are accepted, even the whole
+ meesage (done in the C++ front end). */
+ cdiag ("null argument where non-null required (argument %i)", i);
+ cdiag ("null (argument %i) where non-null required", i);
+ cdiag ("(see what comes next)");
+
+ /* Verify that only a single trailing colon is accepted. */
+ cdiag ("candidates are:");
+ cdiag ("candidates are::"); /* { dg-warning "spurious trailing punctuation sequence .::." } */
+
+ /* Exercise C++. */
+ cdiag ("C++ is cool");
+ cdiag ("this is c++");
+ cdiag ("you can do this in C++ but not in C");
+
+ /* Also verify that G++ is accepted. */
+ cdiag ("G++ rocks");
+ cdiag ("this is accepted by g++");
+ cdiag ("valid in G++ (or g++) but not in gcc");
+
+ /* Exercise parenthetical note followed by a colon, semicolon,
+ or a comma. */
+ cdiag ("found a bug (here):");
+ cdiag ("because of another bug (over there); fix it");
+
+ cdiag ("found foo (123): go look at it");
+ cdiag ("missed bar (abc); will try harder next time");
+
+ cdiag ("expected this (or that), got something else (or who knows what)");
+
+ /* Exercise parenthetical note with a question mark. */
+ cdiag ("hmmm (did you really mean that?)");
+ cdiag ("error (did you mean %<foo()%>?)");
+ /* And a question mark after a parenthetical note. */
+ cdiag ("did you mean this (or that)?");
+
+ /* But make sure unbalanced parenthese are diagnosed. */
+ cdiag ("or this or the other)?"); /* { dg-warning "unbalanced punctuation character '\\\)'" } */
+
+ cdiag ("## Heading"); /* { dg-warning "spurious leading punctuation sequence .##." } */
+ cdiag ("## %s ##", "1"); /* { dg-warning "spurious (leading|trailing) punctuation sequence .##." } */
+
+ cdiag ("#1 priority"); /* { dg-warning "spurious leading punctuation sequence .#." } */
+ cdiag ("priority #2");
+
+ /* Quoting. */
+ cdiag ("\"quoted\"");
+ cdiag ("\"quoted\" string");
+ cdiag ("this is a \"string in quotes\"");
+ cdiag ("\"missing closing quote"); /* { dg-warning "unterminated quote character '\"'" } */
+
+ /* PR translation/90121 - punctuation character after a space. */
+ cdiag ("bad version : 1"); /* { dg-warning "space followed by punctuation character ':'" } */
+ cdiag ("problem ; fix it"); /* { dg-warning "space followed by punctuation character ';'" } */
+ cdiag ("End . not."); /* { dg-warning "space followed by punctuation character '.'" } */
+ cdiag ("it is bad , very bad"); /* { dg-warning "space followed by punctuation character ','" } */
+ cdiag ("say what ?"); /* { dg-warning "space followed by punctuation character '?'" } */
+
+ /* But these are okay after a space. But should they be? */
+ cdiag ("1 / 2");
+ cdiag ("2 + 3");
+ cdiag ("2 - 3");
+}
+
+void test_cdiag_punct_balance (tree t, gimple *gc)
+{
+ (void)&t; (void)&gc;
+
+ /* Less-than and greater than. */
+ cdiag ("a < b"); /* { dg-warning "unbalanced punctuation character '<' in format" } */
+ cdiag ("must be > 0"); /* { dg-warning "unbalanced punctuation character '>' in format" } */
+
+ cdiag ("f()"); /* { dg-warning "spurious trailing punctuation sequence .\\\(\\\)." } */
+ cdiag ("g(1)");
+ cdiag ("("); /* { dg-warning "spurious leading punctuation character|unbalanced" } */
+ cdiag ("()"); /* { dg-warning "spurious leading punctuation sequence" } */
+ cdiag (")"); /* { dg-warning "unbalanced punctuation character '\\\)'" } */
+ cdiag ("f()g"); /* { dg-warning "unquoted sequence of 2 consecutive punctuation characters" } */
+ cdiag ("illegal operand (1)");
+}
+
+
+void test_cdiag_nongraph (tree t, gimple *gc)
+{
+ (void)&t; (void)&gc;
+
+ cdiag ("a\376b"); /* { dg-warning "unquoted non-graph character '\\\\xfe'" } */
+ cdiag ("a\377b"); /* { dg-warning "unquoted non-graph character '\\\\xff'" } */
+}
+
+
+void test_cdiag_attribute (tree t, gimple *gc)
+{
+ (void)&t; (void)&gc;
+
+ cdiag ("attribute foo");
+ cdiag ("this is attribute bar");
+ cdiag ("bad __attribute bar"); /* { dg-warning "unquoted attribute" } */
+ cdiag ("__attribute__ (foobar) bad"); /* { dg-warning "unquoted attribute" } */
+ cdiag ("__attribute__ ((foobar))"); /* { dg-warning "unquoted attribute" } */
+ cdiag ("__attribute__ (xxx))"); /* { dg-warning "unquoted attribute" } */
+ /* { dg-warning "unbalanced punctuation character '\\\)'" "xxx" { target *-*-* } .-1 } */
+ cdiag ("__attribute__ ((yyy)))"); /* { dg-warning "unquoted attribute" } */
+ /* { dg-warning "unbalanced punctuation character '\\\)'" "yyy" { target *-*-* } .-1 } */
+ cdiag ("__attribute__ ((zzz)"); /* { dg-warning "unquoted attribute" } */
+ /* { dg-warning "unbalanced punctuation character '\\\('" "zzz" { target *-*-* } .-1 } */
+
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wformat-diag"
+
+ /* Verify that the warning can be suppressed. */
+ cdiag ("__attribute__ (((");
+
+#pragma GCC diagnostic pop
+}
+
+void test_cdiag_builtin (tree t, gimple *gc)
+{
+ (void)&t; (void)&gc;
+
+ cdiag ("__builtin_abort"); /* { dg-warning "unquoted name of built-in function '__builtin_abort'" } */
+ cdiag ("in __builtin_trap"); /* { dg-warning "unquoted name of built-in function '__builtin_trap'" } */
+ cdiag ("__builtin_xyz bites");/* { dg-warning "unquoted name of built-in function '__builtin_xyz'" } */
+
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wformat-diag"
+
+ /* Verify that the warning can be suppressed. */
+ cdiag ("__builtin____with____lots__of__underscores");
+
+#pragma GCC diagnostic pop
+}
+
+
+void test_cdiag_option (tree t, gimple *gc)
+{
+ (void)&t; (void)&gc;
+
+ cdiag ("%<-Wall%>");
+ cdiag ("use option %<-Wextra%> to enable additinal warnings");
+
+ cdiag ("-O2 is fast"); /* { dg-warning "unquoted option name '-O2'" } */
+ cdiag ("but -O3 is faster"); /* { dg-warning "unquoted option name '-O3'" } */
+
+ cdiag ("get --help"); /* { dg-warning "unquoted option name '--help'" } */
+ cdiag ("enable -m32"); /* { dg-warning "unquoted option name '-m32'" } */
+ cdiag ("value is -12");
+ cdiag ("foo-O2");
+ cdiag ("a-W");
+}
+
+
+void test_cdiag_keyword (tree t, gimple *gc)
+{
+ cdiag ("alignasi");
+ cdiag ("malignofer or alignofus");
+ cdiag ("use alignof"); /* { dg-warning "unquoted keyword 'alignof'" } */
+ cdiag ("or _Alignof"); /* { dg-warning " keyword '_Alignof'" } */
+ cdiag ("_Pragma too"); /* { dg-warning " keyword '_Pragma'" } */
+
+ cdiag ("a #error directive"); /* { dg-warning "unquoted preprocessing directive '#error'" } */
+ cdiag ("#include file"); /* { dg-warning "unquoted preprocessing directive '#include'" } */
+ cdiag ("but #pragma foobar"); /* { dg-warning "unquoted preprocessing directive '#pragma'" } */
+ cdiag ("pragma foobar is okay");
+ cdiag ("or even # pragma is fine");
+
+ /* Exercise qualifiers. */
+ cdiag ("const function");
+ cdiag ("const-qualified variable"); /* { dg-warning "unquoted keyword 'const-qualified'" } */
+ /* { dg-message "use '%<const%>-qualified' instead" "const-qualified" { target *-*-* } .-1 } */
+ cdiag ("a const %qD", t); /* { dg-warning "unquoted keyword 'const'" } */
+ cdiag ("restrict %qE", t); /* { dg-warning "unquoted keyword 'restrict'" } */
+ cdiag ("volatile %qT", t); /* { dg-warning "unquoted keyword 'volatile'" } */
+ cdiag ("const %qD and restrict %qE or volatile %qT", t, t, t);
+ /* { dg-warning "unquoted keyword 'const'" "" { target *-*-* } .-1 } */
+ /* { dg-warning "unquoted keyword 'restrict'" "" { target *-*-* } .-2 } */
+ /* { dg-warning "unquoted keyword 'volatile'" "" { target *-*-* } .-3 } */
+
+ cdiag ("an offsetof here"); /* { dg-warning "unquoted keyword 'offsetof" } */
+ cdiag ("sizeof x"); /* { dg-warning "unquoted keyword 'sizeof" } */
+ cdiag ("have typeof"); /* { dg-warning "unquoted keyword 'typeof" } */
+
+ /* Words that are not keywords are so are not expected to be quoted. */
+ cdiag ("break rules");
+ cdiag ("if we continue by default for a short while else do nothing");
+ cdiag ("register a function for unsigned extern to void const reads");
+ cdiag ("or volatile access");
+}
+
+
+void test_cdiag_operator (tree t, gimple *gc)
+{
+ cdiag ("x != 0"); /* { dg-warning "unquoted operator '!='" } */
+ cdiag ("logical &&"); /* { dg-warning "unquoted operator '&&" } */
+ cdiag ("+= operator"); /* { dg-warning "unquoted operator '\\\+=" } */
+ cdiag ("a == b"); /* { dg-warning "unquoted operator '=='" } */
+ cdiag ("++a"); /* { dg-warning "unquoted operator '\\\+\\\+'" } */
+ cdiag ("b--"); /* { dg-warning "unquoted operator '--'" } */
+ cdiag ("1 << 2"); /* { dg-warning "unquoted operator '<<'" } */
+ cdiag (">> here <<"); /* { dg-warning "unquoted operator '>>|<<'" } */
+}
+
+
+void test_cdiag_type_name (tree t, gimple *gc)
+{
+ cdiag ("the word character should not be quoted");
+ cdiag ("but char should be"); /* { dg-warning "unquoted keyword 'char'" } */
+
+ cdiag ("unsigned char should be quoted"); /* { dg-warning "unquoted type name 'unsigned char'" } */
+ cdiag ("but unsigned character is fine");
+
+ cdiag ("as should int"); /* { dg-warning "unquoted keyword 'int'" } */
+ cdiag ("and signed int"); /* { dg-warning "unquoted type name 'signed int'" } */
+ cdiag ("and also unsigned int"); /* { dg-warning "unquoted type name 'unsigned int'" } */
+ cdiag ("very long thing");
+ cdiag ("use long long here"); /* { dg-warning "unquoted type name 'long long'" } */
+
+ cdiag ("have a floating type");
+ cdiag ("found float type"); /* { dg-warning "unquoted keyword 'float'" } */
+
+ cdiag ("wchar_t is wide"); /* { dg-warning "unquoted identifier or keyword 'wchar_t'" } */
+}
+
+
+void test_cdiag_identifier (tree t, gimple *gc)
+{
+ (void)&t; (void)&gc;
+
+ cdiag ("private _x ident"); /* { dg-warning "unquoted identifier or keyword '_x'" } */
+ cdiag ("and another __y"); /* { dg-warning "unquoted identifier or keyword '__y'" } */
+ cdiag ("ident z_ with trailing underscore"); /* { dg-warning "unquoted identifier or keyword 'z_'" } */
+ cdiag ("v_ variable"); /* { dg-warning "unquoted identifier or keyword 'v_'" } */
+ cdiag ("call foo_bar"); /* { dg-warning "unquoted identifier or keyword 'foo_bar'" } */
+ cdiag ("unqoted x_y ident"); /* { dg-warning "unquoted identifier or keyword 'x_y'" } */
+
+ cdiag ("size_t type"); /* { dg-warning "unquoted identifier or keyword 'size_t'" } */
+ cdiag ("bigger than INT_MAX");/* { dg-warning "unquoted identifier or keyword 'INT_MAX'" } */
+
+ cdiag ("quoted ident %<a_b%>");
+ cdiag ("another quoted identifier %<x_%> here");
+}
+
+
+void test_cdiag_bad_words (tree t, gimple *gc)
+{
+ (void)&t; (void)&gc;
+
+ cdiag ("aren't you dumb?"); /* { dg-warning "bare apostrophe ''' in format" } */
+ cdiag ("bitfields suck"); /* { dg-warning "misspelled term 'bitfields' in format; use 'bit-fields' instead" } */
+ cdiag ("invalid bitfield"); /* { dg-warning "misspelled term 'bitfield' in format; use 'bit-field' instead" } */
+ cdiag ("bad builtin function"); /* { dg-warning "misspelled term 'builtin function' in format; use 'built-in function' instead" } */
+ cdiag ("bad builtin function"); /* { dg-warning "misspelled term 'builtin function' in format; use 'built-in function' instead" } */
+ cdiag ("builtin function x"); /* { dg-warning "misspelled term 'builtin function' in format; use 'built-in function' instead" } */
+ cdiag ("builtin functions disabled"); /* { dg-warning "misspelled term 'builtin functions' in format; use 'built-in functions' instead" } */
+ cdiag ("enable builtin functions"); /* { dg-warning "misspelled term 'builtin functions' in format; use 'built-in functions' instead" } */
+ cdiag ("you can't do that"); /* { dg-warning "contraction 'can't' in format" } */
+ cdiag ("you can%'t do that");/* { dg-warning "contraction 'can%'t' in format" } */
+ cdiag ("Can%'t touch this.");/* { dg-warning "contraction 'Can%'t' in format" } */
+ cdiag ("on the commandline");/* { dg-warning "misspelled term 'commandline' in format; use 'command line' instead" } */
+ cdiag ("command line option");/* { dg-warning "misspelled term 'command line option' in format; use 'command-line option' instead" } */
+ cdiag ("it mustn't be"); /* { dg-warning "contraction 'mustn't' in format" } */
+ cdiag ("isn't that silly?"); /* { dg-warning "bare apostrophe ''' in format" } */
+
+ cdiag ("can not do this"); /* { dg-warning "misspelled term 'can not' in format; use 'cannot' instead" } */
+ cdiag ("you can not"); /* { dg-warning "misspelled term 'can not' in format; use 'cannot' instead" } */
+
+ /* See PR target/90157 - aarch64: unnecessary abbreviation in diagnostic */
+ cdiag ("Mising arg."); /* { dg-warning "misspelled term 'arg' in format; use 'argument' instead" } */
+ cdiag ("2 args: a and b"); /* { dg-warning "misspelled term 'args' in format; use 'arguments' instead" } */
+ cdiag ("arg 1"); /* { dg-warning "misspelled term 'arg' in format; use 'argument' instead" } */
+ cdiag ("Args are wrong."); /* { dg-warning "misspelled term 'Args' in format; use 'arguments' instead" } */
+ cdiag ("bad arg"); /* { dg-warning "misspelled term 'arg' in format; use 'argument' instead" } */
+ cdiag ("two args"); /* { dg-warning "misspelled term 'args' in format; use 'arguments' instead" } */
+ cdiag ("args 1 and 2"); /* { dg-warning "misspelled term 'args' in format; use 'arguments' instead" } */
+
+ cdiag ("Reg A"); /* { dg-warning "misspelled term 'Reg' in format; use 'register' instead" } */
+ cdiag ("regs A and B"); /* { dg-warning "misspelled term 'regs' in format; use 'registers' instead" } */
+ cdiag ("no regs"); /* { dg-warning "misspelled term 'regs' in format; use 'registers' instead" } */
+
+ /* Verify words that end in "arg" and "args" or "reg" and "regs" are
+ not diagnosed. */
+ cdiag ("gulmarg and balfarg");
+ cdiag ("ademargs or toshargs");
+ cdiag ("talk to Greg");
+ cdiag ("prepreg is a fabric");
+ cdiag ("there are dregs in my wine");
+}
+
+
+void test_cdiag_directive (tree t, gimple *gc)
+{
+ (void)&t; (void)&gc;
+
+ cxxdiag ("%<%s%>", ""); /* { dg-warning "quoted '%s' directive in format" } */
+ /* This was asked to be diagnosed in PR #90158 but there, the \"%s\"
+ is in parenheses which ends up getting diagnosed because of
+ the two consecutive punctuation characters, ( and ". */
+ cdiag ("\"%s\"", ""); /* { dg-warning "quoted '%s' directive in format" } */
+
+ /* Make sure quoted paired tokens are not diagnosed. */
+ cdiag ("%<'%>");
+ cdiag ("%<\"%>");
+ cdiag ("%<<%>");
+ cdiag ("%<>%>");
+ cdiag ("%<(%>");
+ cdiag ("%<)%>");
+ cdiag ("%<[%>");
+ cdiag ("%<]%>");
+
+ cdiag ("%<'%> %<\"%> %<>%> %<<%> %<)%> %<(%> %<]%> %<[%>");
+}
diff --git a/gcc/testsuite/gcc.dg/funroll-loops-all.c b/gcc/testsuite/gcc.dg/funroll-loops-all.c
index 9cdc901..ab12df1 100644
--- a/gcc/testsuite/gcc.dg/funroll-loops-all.c
+++ b/gcc/testsuite/gcc.dg/funroll-loops-all.c
@@ -1,4 +1,4 @@
/* PR 17594 */
/* { dg-do compile } */
/* { dg-options "-funroll-loops-all" } */
-/* { dg-error "unrecognized command line option '-funroll-loops-all'" "" { target *-*-* } 0 } */
+/* { dg-error "unrecognized command-line option '-funroll-loops-all'" "" { target *-*-* } 0 } */
diff --git a/gcc/testsuite/gcc.dg/gimplefe-40.c b/gcc/testsuite/gcc.dg/gimplefe-40.c
new file mode 100644
index 0000000..3c5bb4c
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/gimplefe-40.c
@@ -0,0 +1,24 @@
+/* { dg-do compile { target { int128 && vect_float } } } */
+/* { dg-options "-fgimple -Wno-psabi -w" } */
+/* { dg-additional-options "-maltivec" { target { powerpc*-*-* && powerpc_altivec_ok } } } */
+
+typedef float v4sf __attribute__((vector_size(16)));
+v4sf __GIMPLE (ssa)
+load (const void * p)
+{
+ __int128 unsigned _3;
+ v4sf _4;
+ v4sf _6;
+ float _5;
+
+ __BB(2):
+ _3 = __MEM <__int128 unsigned, 8> ((char *)p_2(D));
+ _4 = __VIEW_CONVERT <v4sf>(_3);
+#if __SIZEOF_FLOAT__ == 4
+ _5 = __BIT_FIELD_REF <float> (_4, 32, 64);
+#else
+ _5 = 1.0f;
+#endif
+ _6 = __BIT_INSERT (_4, _5, 0);
+ return _6;
+}
diff --git a/gcc/testsuite/gcc.dg/gimplefe-41.c b/gcc/testsuite/gcc.dg/gimplefe-41.c
new file mode 100644
index 0000000..c3e2f0e
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/gimplefe-41.c
@@ -0,0 +1,39 @@
+/* { dg-do compile { target { vect_double && vect_long_long } } } */
+/* { dg-options "-fgimple -Wno-psabi -w" } */
+
+typedef double __v2df __attribute__ ((__vector_size__ (16)));
+typedef unsigned long long __v2di __attribute__ ((__vector_size__ (16)));
+
+__v2df __GIMPLE (ssa)
+_mm_add_sd (__v2df x, __v2df y)
+{
+ __v2df z;
+ double _1;
+ double _2;
+ double _3;
+ __v2df _7;
+
+ __BB(2):
+ _1 = __BIT_FIELD_REF <double> (x_4(D), 64u, 0u);
+ _2 = __BIT_FIELD_REF <double> (y_5(D), 64u, 0u);
+ _3 = _1 + _2;
+ _7 = _Literal (__v2df) {_3, _3};
+ z_6 = __VEC_PERM (x_4(D), _7, _Literal (__v2di) { 2ul, 1ul });
+ return z_6;
+}
+
+__v2df __GIMPLE (ssa)
+_mm_add_sd2 (__v2df x, __v2df y)
+{
+ __v2df z;
+ double _1;
+ double _2;
+ double _3;
+
+ __BB(2):
+ _1 = __BIT_FIELD_REF <double> (x_4(D), 64u, 0u);
+ _2 = __BIT_FIELD_REF <double> (y_5(D), 64u, 0u);
+ _3 = _1 + _2;
+ z_6 = __BIT_INSERT (x_4(D), _3, 0);
+ return z_6;
+}
diff --git a/gcc/testsuite/gcc.dg/gimplefe-42.c b/gcc/testsuite/gcc.dg/gimplefe-42.c
new file mode 100644
index 0000000..b790339
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/gimplefe-42.c
@@ -0,0 +1,18 @@
+/* { dg-do compile } */
+/* { dg-options "-fgimple" } */
+
+typedef char ref_all_char __attribute__((may_alias));
+char a[7];
+__GIMPLE void f()
+{
+ int _1;
+ /* string literals inside __MEM need their address taken. */
+ __MEM <char[7]> ((ref_all_char *)&a)
+ = __MEM <char[7]> (_Literal (char *) &"654321");
+ /* but plain assignment also works. */
+ __MEM <char[7]> ((ref_all_char *)&a) = "654321";
+ /* also punning with int. */
+ _1 = __MEM <int> (_Literal (char *) &"654321");
+ __MEM <int> ((ref_all_char *)&a) = _1;
+ return;
+}
diff --git a/gcc/testsuite/gcc.dg/gnu-cond-expr-2.c b/gcc/testsuite/gcc.dg/gnu-cond-expr-2.c
index 2e561e4..fed5adf 100644
--- a/gcc/testsuite/gcc.dg/gnu-cond-expr-2.c
+++ b/gcc/testsuite/gcc.dg/gnu-cond-expr-2.c
@@ -9,5 +9,5 @@ int a, b, c;
void
f (void)
{
- c = (++a ? : b); /* { dg-warning "ISO C forbids omitting the middle term of a \\?: expression" } */
+ c = (++a ? : b); /* { dg-warning "ISO C forbids omitting the middle term of a '\\?:' expression" } */
}
diff --git a/gcc/testsuite/gcc.dg/gnu-cond-expr-3.c b/gcc/testsuite/gcc.dg/gnu-cond-expr-3.c
index 90555ad..08657ff 100644
--- a/gcc/testsuite/gcc.dg/gnu-cond-expr-3.c
+++ b/gcc/testsuite/gcc.dg/gnu-cond-expr-3.c
@@ -9,5 +9,5 @@ int a, b, c;
void
f (void)
{
- c = (++a ? : b); /* { dg-error "ISO C forbids omitting the middle term of a \\?: expression" } */
+ c = (++a ? : b); /* { dg-error "ISO C forbids omitting the middle term of a '\\?:' expression" } */
}
diff --git a/gcc/testsuite/gcc.dg/gomp/macro-4.c b/gcc/testsuite/gcc.dg/gomp/macro-4.c
index 28d198b..a4ed9a3 100644
--- a/gcc/testsuite/gcc.dg/gomp/macro-4.c
+++ b/gcc/testsuite/gcc.dg/gomp/macro-4.c
@@ -10,9 +10,9 @@ void bar (void);
void
foo (void)
{
-#pragma omp p /* { dg-warning "-:ignoring #pragma omp _Pragma" } */
+#pragma omp p /* { dg-warning "-:ignoring '#pragma omp _Pragma'" } */
bar ();
- omp_p /* { dg-warning "-:ignoring #pragma omp _Pragma" } */
+ omp_p /* { dg-warning "-:ignoring '#pragma omp _Pragma'" } */
bar ();
}
@@ -22,8 +22,8 @@ foo (void)
void
baz (void)
{
-#pragma omp parallel /* { dg-warning "-:ignoring #pragma omp serial" } */
+#pragma omp parallel /* { dg-warning "-:ignoring '#pragma omp serial'" } */
bar ();
- omp_parallel /* { dg-warning "-:ignoring #pragma omp serial" } */
+ omp_parallel /* { dg-warning "-:ignoring '#pragma omp serial'" } */
bar ();
}
diff --git a/gcc/testsuite/gcc.dg/gomp/pr90637.c b/gcc/testsuite/gcc.dg/gomp/pr90637.c
new file mode 100644
index 0000000..983e03e
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/gomp/pr90637.c
@@ -0,0 +1,14 @@
+/* PR tree-optimization/90637 */
+/* { dg-do compile } */
+/* { dg-options "-fopenmp -O1 --param sink-frequency-threshold=90" } */
+
+int v;
+
+void
+foo (int c)
+{
+ int i;
+#pragma omp for simd if (c) lastprivate (v) schedule (static, 16)
+ for (i = 0; i < 64; ++i)
+ v = i;
+}
diff --git a/gcc/testsuite/gcc.dg/gomp/pr90900.c b/gcc/testsuite/gcc.dg/gomp/pr90900.c
new file mode 100644
index 0000000..d4c5d7d5
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/gomp/pr90900.c
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fopenmp -g" } */
+
+void f (int a)
+{
+ void *x = &&lab;
+#pragma omp parallel
+ if (a)
+ { lab: __builtin_unreachable(); }
+ x;
+}
diff --git a/gcc/testsuite/gcc.dg/graphite/graphite.exp b/gcc/testsuite/gcc.dg/graphite/graphite.exp
index ea61446..523a955 100644
--- a/gcc/testsuite/gcc.dg/graphite/graphite.exp
+++ b/gcc/testsuite/gcc.dg/graphite/graphite.exp
@@ -56,7 +56,7 @@ set vect_files [lsort [glob -nocomplain $srcdir/$subdir/vect-*.c ] ]
# Tests to be compiled.
set dg-do-what-default compile
-dg-runtest $scop_files "" "-O2 -fgraphite -fdump-tree-graphite-all"
+dg-runtest $scop_files "" "-O2 -fgraphite -fdump-tree-graphite-all -fno-finite-loops"
dg-runtest $id_files "" "-O2 -fgraphite-identity -ffast-math -fdump-tree-graphite-details"
# Tests to be run.
diff --git a/gcc/testsuite/gcc.dg/guality/pr90716.c b/gcc/testsuite/gcc.dg/guality/pr90716.c
new file mode 100644
index 0000000..b2f5c9d
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/guality/pr90716.c
@@ -0,0 +1,25 @@
+/* { dg-do run } */
+/* { dg-options "-g" } */
+
+void __attribute__((noinline))
+optimize_me_not ()
+{
+ __asm__ volatile ("" : : : "memory");
+}
+int a[7][8];
+int main()
+{
+ int b, j;
+ b = 0;
+ for (; b < 7; b++) {
+ j = 0;
+ for (; j < 8; j++)
+ a[b][j] = 0;
+ }
+ /* j may very well be optimized out, so we cannot test for j == 8.
+ Instead test j + 1 which will make the test UNSUPPORTED if i
+ is optimized out. Since the test previously had wrong debug
+ with j == 0 this is acceptable. */
+ optimize_me_not(); /* { dg-final { gdb-test . "j + 1" "9" } } */
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/init-bad-1.c b/gcc/testsuite/gcc.dg/init-bad-1.c
index a7e8c5a..6173404 100644
--- a/gcc/testsuite/gcc.dg/init-bad-1.c
+++ b/gcc/testsuite/gcc.dg/init-bad-1.c
@@ -16,9 +16,9 @@ void h(a)
char s[1] = "x";
char s1[1] = { "x" };
-char t[1] = "xy"; /* { dg-warning "initializer-string for array of chars is too long" } */
-char t1[1] = { "xy" }; /* { dg-warning "initializer-string for array of chars is too long" } */
-char u[1] = { "x", "x" }; /* { dg-error "excess elements in char array initializer" } */
+char t[1] = "xy"; /* { dg-warning "initializer-string for array of 'char' is too long" } */
+char t1[1] = { "xy" }; /* { dg-warning "initializer-string for array of 'char' is too long" } */
+char u[1] = { "x", "x" }; /* { dg-error "excess elements in 'char' array initializer" } */
/* { dg-message "near init" "near" { target *-*-* } .-1 } */
int i = { }; /* { dg-error "empty scalar initializer" } */
diff --git a/gcc/testsuite/gcc.dg/init-bad-2.c b/gcc/testsuite/gcc.dg/init-bad-2.c
index dad57b9..4775c48 100644
--- a/gcc/testsuite/gcc.dg/init-bad-2.c
+++ b/gcc/testsuite/gcc.dg/init-bad-2.c
@@ -17,9 +17,9 @@ void h(a)
char s[1] = "x";
char s1[1] = { "x" };
-char t[1] = "xy"; /* { dg-warning "initializer-string for array of chars is too long" } */
-char t1[1] = { "xy" }; /* { dg-warning "initializer-string for array of chars is too long" } */
-char u[1] = { "x", "x" }; /* { dg-error "excess elements in char array initializer" } */
+char t[1] = "xy"; /* { dg-warning "initializer-string for array of 'char' is too long" } */
+char t1[1] = { "xy" }; /* { dg-warning "initializer-string for array of 'char' is too long" } */
+char u[1] = { "x", "x" }; /* { dg-error "excess elements in 'char' array initializer" } */
/* { dg-message "near init" "near" { target *-*-* } .-1 } */
int j = { 1 };
diff --git a/gcc/testsuite/gcc.dg/init-bad-3.c b/gcc/testsuite/gcc.dg/init-bad-3.c
index d320e0e..c5c338d 100644
--- a/gcc/testsuite/gcc.dg/init-bad-3.c
+++ b/gcc/testsuite/gcc.dg/init-bad-3.c
@@ -17,9 +17,9 @@ void h(a)
char s[1] = "x";
char s1[1] = { "x" };
-char t[1] = "xy"; /* { dg-error "initializer-string for array of chars is too long" } */
-char t1[1] = { "xy" }; /* { dg-error "initializer-string for array of chars is too long" } */
-char u[1] = { "x", "x" }; /* { dg-error "excess elements in char array initializer" } */
+char t[1] = "xy"; /* { dg-error "initializer-string for array of 'char' is too long" } */
+char t1[1] = { "xy" }; /* { dg-error "initializer-string for array of 'char' is too long" } */
+char u[1] = { "x", "x" }; /* { dg-error "excess elements in 'char' array initializer" } */
/* { dg-message "near init" "near" { target *-*-* } .-1 } */
int j = { 1 };
diff --git a/gcc/testsuite/gcc.dg/ipa/ipcp-agg-10.c b/gcc/testsuite/gcc.dg/ipa/ipcp-agg-10.c
new file mode 100644
index 0000000..16d62e7
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/ipa/ipcp-agg-10.c
@@ -0,0 +1,78 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -fdump-ipa-cp-details -fno-inline" } */
+
+int data1;
+
+int callee1(int *v)
+{
+ if (*v < 2)
+ return 0;
+ else
+ {
+ int t = data1;
+
+ data1 = *v;
+ *v = t;
+
+ return 1;
+ }
+}
+
+int __attribute__((pure)) callee2(int *v)
+{
+ if (*v < 2)
+ return 0;
+ else
+ {
+ data1 = v[0] + v[2];
+
+ return 1;
+ }
+}
+
+int caller1(int c, int *r)
+{
+ int a = 1;
+
+ if (c)
+ return callee1(&a);
+ else
+ {
+ *r = 2;
+ return callee1(r);
+ }
+}
+
+int data2[200];
+int data3;
+
+int __attribute__((const)) gen_cond(int);
+
+int caller2(void)
+{
+ int i, j;
+ int sum = 0;
+ int a[8];
+
+ a[0] = 3;
+ for (i = 0; i < 100; i++)
+ {
+ if (gen_cond (i))
+ continue;
+
+ a[2] = 4;
+ for (j = 0; j < 100; j++)
+ {
+ data2[i + j] = (i ^ j) + data3;
+
+ sum += callee2(a);
+ }
+ }
+
+ return sum;
+}
+
+/* { dg-final { scan-ipa-dump-times "offset: 0, cst: 1" 1 "cp" } } */
+/* { dg-final { scan-ipa-dump-times "offset: 0, cst: 2" 1 "cp" } } */
+/* { dg-final { scan-ipa-dump-times "offset: 0, cst: 3" 1 "cp" } } */
+/* { dg-final { scan-ipa-dump-times "offset: 64, cst: 4" 1 "cp" } } */
diff --git a/gcc/testsuite/gcc.dg/ipa/pr68035.c b/gcc/testsuite/gcc.dg/ipa/pr68035.c
index a8cb779..f6adad9 100644
--- a/gcc/testsuite/gcc.dg/ipa/pr68035.c
+++ b/gcc/testsuite/gcc.dg/ipa/pr68035.c
@@ -105,4 +105,4 @@ list_49,
};
-/* { dg-final { scan-ipa-dump "unique hash values: 51" "icf" } } */
+/* { dg-final { scan-ipa-dump "Congruence classes: 51" "icf" } } */
diff --git a/gcc/testsuite/gcc.dg/ipa/pr90555.c b/gcc/testsuite/gcc.dg/ipa/pr90555.c
new file mode 100644
index 0000000..327cff9
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/ipa/pr90555.c
@@ -0,0 +1,66 @@
+/* { dg-do compile { target i?86-*-* x86_64-*-* } } */
+/* { dg-options "-fopenmp-simd -O2 -mavx512f -fdump-ipa-icf" } */
+
+#define N 1024
+int a[N];
+
+void
+test_simdlen1 (void)
+{
+ int i;
+ #pragma omp simd simdlen (4)
+ for (i = 0; i < N; ++i)
+ a[i] = a[i] + 1;
+}
+
+void
+test_simdlen2 (void)
+{
+ int i;
+ #pragma omp simd simdlen (8)
+ for (i = 0; i < N; ++i)
+ a[i] = a[i] + 1;
+}
+
+void
+test_safelen1 (void)
+{
+ int i;
+ #pragma omp simd safelen (4)
+ for (i = 0; i < N; ++i)
+ a[i] = a[i] + 1;
+}
+
+void
+test_safelen2 (void)
+{
+ int i;
+ #pragma omp simd safelen (8)
+ for (i = 0; i < N; ++i)
+ a[i] = a[i] + 1;
+}
+
+int d[1024];
+
+int
+test_simduid1 (int j, int b)
+{
+ int l, c = 0;
+#pragma omp simd reduction(+: c)
+ for (l = 0; l < b; ++l)
+ c += d[j + l];
+ return c;
+}
+
+int
+test_simduid2 (int j, int b)
+{
+ int l, c2 = 0;
+#pragma omp simd reduction(+: c2)
+ for (l = 0; l < b; ++l)
+ c2 += d[j + l];
+ return c2;
+}
+
+/* { dg-final { scan-ipa-dump "Semantic equality hit:test_simduid1->test_simduid2" "icf" } } */
+/* { dg-final { scan-ipa-dump "Equal symbols: 1" "icf" } } */
diff --git a/gcc/testsuite/gcc.dg/loop-unswitch-1.c b/gcc/testsuite/gcc.dg/loop-unswitch-1.c
index f6fc41d..de2fb2c 100644
--- a/gcc/testsuite/gcc.dg/loop-unswitch-1.c
+++ b/gcc/testsuite/gcc.dg/loop-unswitch-1.c
@@ -1,6 +1,6 @@
/* For PR rtl-optimization/27735 */
/* { dg-do compile } */
-/* { dg-options "-O2 -funswitch-loops -fdump-tree-unswitch-details" } */
+/* { dg-options "-O2 -funswitch-loops -fdump-tree-unswitch-details -fno-finite-loops" } */
void set_color(void);
void xml_colorize_line(unsigned int *p, int state)
diff --git a/gcc/testsuite/gcc.dg/lto/alias-access-path-2_0.c b/gcc/testsuite/gcc.dg/lto/alias-access-path-2_0.c
new file mode 100644
index 0000000..7a53a1a
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/lto/alias-access-path-2_0.c
@@ -0,0 +1,38 @@
+/* { dg-lto-do run } */
+/* { dg-lto-options { { -O3 -flto -fno-early-inlining } } } */
+
+/* In this test the access patch orracle (aliasing_component_refs_p)
+ can disambiguage array[0] from array[1] by base+offset but it needs to be
+ able to find the common type and not give up by not being able to compare
+ types earlier. */
+
+typedef int (*fnptr) ();
+
+__attribute__ ((used))
+struct a
+{
+ void *array[2];
+} a, *aptr = &a;
+
+__attribute__ ((used))
+struct b
+{
+ struct a a;
+} *bptr;
+
+static void
+inline_me_late (int argc)
+{
+ if (argc == -1)
+ bptr->a.array[1] = bptr;
+}
+
+int
+main (int argc)
+{
+ aptr->array[0] = 0;
+ inline_me_late (argc);
+ if (!__builtin_constant_p (aptr->array[0] == 0))
+ __builtin_abort ();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/memcpy-2.c b/gcc/testsuite/gcc.dg/memcpy-2.c
index 7f839d2..6ad8874 100644
--- a/gcc/testsuite/gcc.dg/memcpy-2.c
+++ b/gcc/testsuite/gcc.dg/memcpy-2.c
@@ -1,6 +1,6 @@
/* PR middle-end/38454 */
/* { dg-do compile } */
-/* { dg-options "-O2" } */
+/* { dg-options "-O2 -fno-tree-dse" } */
typedef __SIZE_TYPE__ size_t;
diff --git a/gcc/testsuite/gcc.dg/misc-column.c b/gcc/testsuite/gcc.dg/misc-column.c
index e68300b..7dc6e58 100644
--- a/gcc/testsuite/gcc.dg/misc-column.c
+++ b/gcc/testsuite/gcc.dg/misc-column.c
@@ -13,7 +13,7 @@ extern void bar();
void foo (void)
{
- if (a == b) /* { dg-warning "9:comparing floating point with" } */
+ if (a == b) /* { dg-warning "9:comparing floating-point with" } */
bar ();
if (p < q) /* { dg-warning "9:comparison of distinct pointer types" } */
diff --git a/gcc/testsuite/gcc.dg/no_profile_instrument_function-attr-1.c b/gcc/testsuite/gcc.dg/no_profile_instrument_function-attr-1.c
index 41d7455..0c7e096 100644
--- a/gcc/testsuite/gcc.dg/no_profile_instrument_function-attr-1.c
+++ b/gcc/testsuite/gcc.dg/no_profile_instrument_function-attr-1.c
@@ -19,6 +19,6 @@ int main ()
}
/* { dg-final { scan-tree-dump-times "__gcov0\\.main.* = PROF_edge_counter" 1 "optimized"} } */
-/* { dg-final { scan-tree-dump-times "__gcov_indirect_call_profiler_v3" 1 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "__gcov_indirect_call_profiler_v" 1 "optimized" } } */
/* { dg-final { scan-tree-dump-times "__gcov_time_profiler_counter = " 1 "optimized" } } */
/* { dg-final { scan-tree-dump-times "__gcov_init" 1 "optimized" } } */
diff --git a/gcc/testsuite/gcc.dg/nonnull-3.c b/gcc/testsuite/gcc.dg/nonnull-3.c
index 040248c..6f7bc4f 100644
--- a/gcc/testsuite/gcc.dg/nonnull-3.c
+++ b/gcc/testsuite/gcc.dg/nonnull-3.c
@@ -56,8 +56,8 @@ foo (void *p, char *s)
__builtin_strspn (s, NULL); /* { dg-warning "null" "null pointer check" } */
__builtin_strchr (NULL, 16); /* { dg-warning "null" "null pointer check" } */
__builtin_strrchr (NULL, 16); /* { dg-warning "null" "null pointer check" } */
- __builtin_strdup (NULL); /* { dg-warning "null" "null pointer check" } */
- __builtin_strndup (NULL, 16); /* { dg-warning "null" "null pointer check" } */
+ void *p1 = __builtin_strdup (NULL); /* { dg-warning "null" "null pointer check" } */
+ void *p2 = __builtin_strndup (NULL, 16); /* { dg-warning "null" "null pointer check" } */
__builtin_nan (NULL); /* { dg-warning "null" "null pointer check" } */
__builtin_nanf (NULL); /* { dg-warning "null" "null pointer check" } */
diff --git a/gcc/testsuite/gcc.dg/opts-5.c b/gcc/testsuite/gcc.dg/opts-5.c
index ab1e6f9..80bead8 100644
--- a/gcc/testsuite/gcc.dg/opts-5.c
+++ b/gcc/testsuite/gcc.dg/opts-5.c
@@ -2,4 +2,4 @@
/* { dg-do compile } */
/* { dg-options "-fstack-limit" } */
-/* { dg-error "unrecognized command line option" "" { target *-*-* } 0 } */
+/* { dg-error "unrecognized command-line option" "" { target *-*-* } 0 } */
diff --git a/gcc/testsuite/gcc.dg/parm-mismatch-1.c b/gcc/testsuite/gcc.dg/parm-mismatch-1.c
index 75dad1e..058f2e8 100644
--- a/gcc/testsuite/gcc.dg/parm-mismatch-1.c
+++ b/gcc/testsuite/gcc.dg/parm-mismatch-1.c
@@ -1,4 +1,4 @@
-/* Test diagnostics for parameter mismatches. Types that can't match
+/* Test diagnostics for parameter mismatches. Types that cannot match
(). */
/* Origin: Joseph Myers <joseph@codesourcery.com> */
/* { dg-do compile } */
@@ -6,13 +6,13 @@
void f0(); /* { dg-message "note: previous declaration of 'f0' was here" } */
void f0(int, ...); /* { dg-error "conflicting types for 'f0'" } */
-/* { dg-message "note: a parameter list with an ellipsis can't match an empty parameter name list declaration" "note" { target *-*-* } .-1 } */
+/* { dg-message "note: a parameter list with an ellipsis cannot match an empty parameter name list declaration" "note" { target *-*-* } .-1 } */
void f1(int, ...); /* { dg-message "note: previous declaration of 'f1' was here" } */
void f1(); /* { dg-error "conflicting types for 'f1'" } */
-/* { dg-message "note: a parameter list with an ellipsis can't match an empty parameter name list declaration" "note" { target *-*-* } .-1 } */
+/* { dg-message "note: a parameter list with an ellipsis cannot match an empty parameter name list declaration" "note" { target *-*-* } .-1 } */
void f2(); /* { dg-message "note: previous declaration of 'f2' was here" } */
void f2(char); /* { dg-error "conflicting types for 'f2'" } */
-/* { dg-message "note: an argument type that has a default promotion can't match an empty parameter name list declaration" "note" { target *-*-* } .-1 } */
+/* { dg-message "note: an argument type that has a default promotion cannot match an empty parameter name list declaration" "note" { target *-*-* } .-1 } */
void f3(char); /* { dg-message "note: previous declaration of 'f3' was here" } */
void f3(); /* { dg-error "conflicting types for 'f3'" } */
-/* { dg-message "note: an argument type that has a default promotion can't match an empty parameter name list declaration" "note" { target *-*-* } .-1 } */
+/* { dg-message "note: an argument type that has a default promotion cannot match an empty parameter name list declaration" "note" { target *-*-* } .-1 } */
diff --git a/gcc/testsuite/gcc.dg/plugin/start_unit_plugin.c b/gcc/testsuite/gcc.dg/plugin/start_unit_plugin.c
index b98cf55..61e9494 100644
--- a/gcc/testsuite/gcc.dg/plugin/start_unit_plugin.c
+++ b/gcc/testsuite/gcc.dg/plugin/start_unit_plugin.c
@@ -40,6 +40,19 @@ gate_start_unit (void)
static void start_unit_callback (void *gcc_data, void *user_data)
{
+ static const struct ggc_root_tab root[] = {
+ {
+ &fake_var,
+ 1,
+ sizeof (fake_var),
+ &gt_ggc_mx_tree_node,
+ &gt_pch_nx_tree_node
+ },
+ LAST_GGC_ROOT_TAB
+ };
+
+ register_callback ("start_unit", PLUGIN_REGISTER_GGC_ROOTS, NULL,
+ (void *)root);
if (integer_type_node) {
fake_var = build_decl (UNKNOWN_LOCATION, VAR_DECL,
get_identifier ("_fake_var_"),
diff --git a/gcc/testsuite/gcc.dg/pr27528.c b/gcc/testsuite/gcc.dg/pr27528.c
index c9bb238..d63238e 100644
--- a/gcc/testsuite/gcc.dg/pr27528.c
+++ b/gcc/testsuite/gcc.dg/pr27528.c
@@ -7,16 +7,16 @@ void
foo (int *x, int y)
{
int constant = 0;
- asm ("# %0" :: "i" (x)); /* { dg-warning "probably doesn't match" } */
+ asm ("# %0" :: "i" (x)); /* { dg-warning "probably does not match" } */
/* { dg-error "impossible constraint" "" { target *-*-* } .-1 } */
- asm ("# %0" :: "i" (bar (*x))); /* { dg-warning "probably doesn't match" } */
+ asm ("# %0" :: "i" (bar (*x))); /* { dg-warning "probably does not match" } */
/* { dg-error "impossible constraint" "" { target *-*-* } .-1 } */
- asm ("# %0" :: "i" (*x + 0x11)); /* { dg-warning "probably doesn't match" } */
+ asm ("# %0" :: "i" (*x + 0x11)); /* { dg-warning "probably does not match" } */
/* { dg-error "impossible constraint" "" { target *-*-* } .-1 } */
- asm ("# %0" :: "i" (constant)); /* { dg-warning "probably doesn't match" } */
+ asm ("# %0" :: "i" (constant)); /* { dg-warning "probably does not match" } */
/* { dg-error "impossible constraint" "" { target *-*-* } .-1 } */
asm ("# %0" :: "i" (y * 0)); /* folded */
diff --git a/gcc/testsuite/gcc.dg/pr28322-2.c b/gcc/testsuite/gcc.dg/pr28322-2.c
index 89dd153..c9e5e22 100644
--- a/gcc/testsuite/gcc.dg/pr28322-2.c
+++ b/gcc/testsuite/gcc.dg/pr28322-2.c
@@ -8,5 +8,5 @@ int foo (void)
return i;
}
-/* { dg-warning "unrecognized command line option .-Wno-foobar." "" { target *-*-* } 0 } */
+/* { dg-warning "unrecognized command-line option .-Wno-foobar." "" { target *-*-* } 0 } */
diff --git a/gcc/testsuite/gcc.dg/pr28322-3.c b/gcc/testsuite/gcc.dg/pr28322-3.c
index e714a3c..85926ad 100644
--- a/gcc/testsuite/gcc.dg/pr28322-3.c
+++ b/gcc/testsuite/gcc.dg/pr28322-3.c
@@ -6,5 +6,5 @@ void foo(void)
{
int i = 1;
}
-/* { dg-message "unrecognized command line option .-fno-foobar." "f" { target *-*-* } 0 } */
-/* { dg-message "unrecognized command line option .-mno-foobar." "m" { target *-*-* } 0 } */
+/* { dg-message "unrecognized command-line option .-fno-foobar." "f" { target *-*-* } 0 } */
+/* { dg-message "unrecognized command-line option .-mno-foobar." "m" { target *-*-* } 0 } */
diff --git a/gcc/testsuite/gcc.dg/pr40340-1.c b/gcc/testsuite/gcc.dg/pr40340-1.c
index 8fbb206..6307e06 100644
--- a/gcc/testsuite/gcc.dg/pr40340-1.c
+++ b/gcc/testsuite/gcc.dg/pr40340-1.c
@@ -1,6 +1,6 @@
/* PR middle-end/40340 */
/* { dg-do compile } */
-/* { dg-options "-O2 -Wall -Wno-system-headers" } */
+/* { dg-options "-O2 -Wall -Wno-system-headers -fno-tree-dse" } */
#include "pr40340.h"
diff --git a/gcc/testsuite/gcc.dg/pr40340-2.c b/gcc/testsuite/gcc.dg/pr40340-2.c
index 10083ac..ea76e10 100644
--- a/gcc/testsuite/gcc.dg/pr40340-2.c
+++ b/gcc/testsuite/gcc.dg/pr40340-2.c
@@ -1,6 +1,6 @@
/* PR middle-end/40340 */
/* { dg-do compile } */
-/* { dg-options "-O2 -Wall -Wno-system-headers" } */
+/* { dg-options "-O2 -Wall -Wno-system-headers -fno-tree-dse" } */
#include "pr40340.h"
diff --git a/gcc/testsuite/gcc.dg/pr40340-5.c b/gcc/testsuite/gcc.dg/pr40340-5.c
index 0e48a2c..99e58f2 100644
--- a/gcc/testsuite/gcc.dg/pr40340-5.c
+++ b/gcc/testsuite/gcc.dg/pr40340-5.c
@@ -1,6 +1,6 @@
/* PR middle-end/40340 */
/* { dg-do compile } */
-/* { dg-options "-O2 -Wall -Wsystem-headers -g" } */
+/* { dg-options "-O2 -Wall -Wsystem-headers -g -fno-tree-dse" } */
#define TEST3
#include "pr40340.h"
diff --git a/gcc/testsuite/gcc.dg/pr43643.c b/gcc/testsuite/gcc.dg/pr43643.c
index b0c57c0..43896ab 100644
--- a/gcc/testsuite/gcc.dg/pr43643.c
+++ b/gcc/testsuite/gcc.dg/pr43643.c
@@ -10,9 +10,9 @@ extern char *strdup (const char *);
void
func(char *a, char *b, char *c)
{
- strdup(a);
- strdup(b);
- strdup(c);
+ void *p = strdup(a);
+ p = strdup(b);
+ p = strdup(c);
}
int
diff --git a/gcc/testsuite/gcc.dg/pr48552-1.c b/gcc/testsuite/gcc.dg/pr48552-1.c
index 6626a58..70d3483 100644
--- a/gcc/testsuite/gcc.dg/pr48552-1.c
+++ b/gcc/testsuite/gcc.dg/pr48552-1.c
@@ -15,7 +15,7 @@ f2 (void *x)
{
__asm volatile ("" : "=r" (*x)); /* { dg-warning "dereferencing" "deref" } */
} /* { dg-error "invalid use of void expression" "void expr" { target *-*-* } .-1 } */
- /* { dg-error "invalid lvalue in asm output 0" "invalid lvalue" { target *-*-* } .-2 } */
+ /* { dg-error "invalid lvalue in 'asm' output 0" "invalid lvalue" { target *-*-* } .-2 } */
void
f3 (void *x)
{
@@ -39,7 +39,7 @@ f6 (void *x)
{
__asm volatile ("" : "=g" (*x)); /* { dg-warning "dereferencing" "deref" } */
} /* { dg-error "invalid use of void expression" "void expr" { target *-*-* } .-1 } */
- /* { dg-error "invalid lvalue in asm output 0" "invalid lvalue" { target *-*-* } .-2 } */
+ /* { dg-error "invalid lvalue in 'asm' output 0" "invalid lvalue" { target *-*-* } .-2 } */
void
f7 (struct S *x)
{
@@ -49,5 +49,5 @@ f7 (struct S *x)
void
f8 (struct S *x)
{
- __asm volatile ("" : "=r" (*x)); /* { dg-error "invalid lvalue in asm output 0" } */
+ __asm volatile ("" : "=r" (*x)); /* { dg-error "invalid lvalue in 'asm' output 0" } */
}
diff --git a/gcc/testsuite/gcc.dg/pr48552-2.c b/gcc/testsuite/gcc.dg/pr48552-2.c
index c3aca89..ce6bece 100644
--- a/gcc/testsuite/gcc.dg/pr48552-2.c
+++ b/gcc/testsuite/gcc.dg/pr48552-2.c
@@ -15,7 +15,7 @@ f2 (void *x)
{
__asm ("" : "=r" (*x)); /* { dg-warning "dereferencing" "deref" } */
} /* { dg-error "invalid use of void expression" "void expr" { target *-*-* } .-1 } */
- /* { dg-error "invalid lvalue in asm output 0" "invalid lvalue" { target *-*-* } .-2 } */
+ /* { dg-error "invalid lvalue in 'asm' output 0" "invalid lvalue" { target *-*-* } .-2 } */
void
f3 (void *x)
{
@@ -39,7 +39,7 @@ f6 (void *x)
{
__asm ("" : "=g" (*x)); /* { dg-warning "dereferencing" "deref" } */
} /* { dg-error "invalid use of void expression" "void expr" { target *-*-* } .-1 } */
- /* { dg-error "invalid lvalue in asm output 0" "invalid lvalue" { target *-*-* } .-2 } */
+ /* { dg-error "invalid lvalue in 'asm' output 0" "invalid lvalue" { target *-*-* } .-2 } */
void
f7 (struct S *x)
{
@@ -49,5 +49,5 @@ f7 (struct S *x)
void
f8 (struct S *x)
{
- __asm ("" : "=r" (*x)); /* { dg-error "invalid lvalue in asm output 0" } */
+ __asm ("" : "=r" (*x)); /* { dg-error "invalid lvalue in 'asm' output 0" } */
}
diff --git a/gcc/testsuite/gcc.dg/pr53265.c b/gcc/testsuite/gcc.dg/pr53265.c
index d641822..a727211 100644
--- a/gcc/testsuite/gcc.dg/pr53265.c
+++ b/gcc/testsuite/gcc.dg/pr53265.c
@@ -38,7 +38,8 @@ fn3 (void)
for (i = 0; i < (int) (sizeof (a) / sizeof (a[0])); i++) /* { dg-message "note: within this loop" } */
{
c[i + 8] = b[i]; /* { dg-warning "8 invokes undefined behavior" } */
- a[i + 8] = b[i + 8];
+ /* { dg-warning "out of the bounds" "" { target *-*-* } .-1 } */
+ a[i + 8] = b[i + 8]; /* { dg-warning "out of the bounds" } */
}
bar (a);
bar (c);
diff --git a/gcc/testsuite/gcc.dg/pr59717.c b/gcc/testsuite/gcc.dg/pr59717.c
index e49020a..64e4f32 100644
--- a/gcc/testsuite/gcc.dg/pr59717.c
+++ b/gcc/testsuite/gcc.dg/pr59717.c
@@ -242,7 +242,7 @@ stdlib (void *p, void *q, __SIZE_TYPE__ sz)
{
abort (); /* { dg-warning "incompatible implicit" } */
/* { dg-message "include ..stdlib.h.." "" { target *-*-* } .-1 } */
- calloc (sz, 1); /* { dg-warning "incompatible implicit" } */
+ void *p1 = calloc (sz, 1); /* { dg-warning "incompatible implicit" } */
/* { dg-message "include ..stdlib.h.." "" { target *-*-* } .-1 } */
exit (1); /* { dg-warning "incompatible implicit" } */
/* { dg-message "include ..stdlib.h.." "" { target *-*-* } .-1 } */
@@ -252,11 +252,11 @@ stdlib (void *p, void *q, __SIZE_TYPE__ sz)
/* { dg-message "include ..stdlib.h.." "" { target *-*-* } .-1 } */
llabs (1LL); /* { dg-warning "incompatible implicit" } */
/* { dg-message "include ..stdlib.h.." "" { target *-*-* } .-1 } */
- malloc (sz); /* { dg-warning "incompatible implicit" } */
+ void *p2 = malloc (sz); /* { dg-warning "incompatible implicit" } */
/* { dg-message "include ..stdlib.h.." "" { target *-*-* } .-1 } */
- realloc (p, sz); /* { dg-warning "incompatible implicit" } */
+ void *p3 = realloc (p, sz); /* { dg-warning "incompatible implicit" } */
/* { dg-message "include ..stdlib.h.." "" { target *-*-* } .-1 } */
- aligned_alloc (sz, sz); /* { dg-warning "incompatible implicit" } */
+ void *p4 = aligned_alloc (sz, sz); /* { dg-warning "incompatible implicit" } */
/* { dg-message "include ..stdlib.h.." "" { target *-*-* } .-1 } */
}
diff --git a/gcc/testsuite/gcc.dg/pr59846.c b/gcc/testsuite/gcc.dg/pr59846.c
index b3dd0de..9b01b22 100644
--- a/gcc/testsuite/gcc.dg/pr59846.c
+++ b/gcc/testsuite/gcc.dg/pr59846.c
@@ -17,13 +17,13 @@ fn2 (unsigned int p)
_Bool
fn3 (unsigned int p)
{
- return p >= 0U; /* { dg-warning "12:comparison of unsigned expression >= 0 is always true" } */
+ return p >= 0U; /* { dg-warning "12:comparison of unsigned expression in '>= 0' is always true" } */
}
_Bool
fn4 (unsigned int p)
{
- return p < 0U; /* { dg-warning "12:comparison of unsigned expression < 0 is always false" } */
+ return p < 0U; /* { dg-warning "12:comparison of unsigned expression in '< 0' is always false" } */
}
_Bool
diff --git a/gcc/testsuite/gcc.dg/pr60087.c b/gcc/testsuite/gcc.dg/pr60087.c
index c6cf7aa..b3bd811 100644
--- a/gcc/testsuite/gcc.dg/pr60087.c
+++ b/gcc/testsuite/gcc.dg/pr60087.c
@@ -7,8 +7,8 @@ foo (unsigned int ui, int i)
{
const unsigned char uc = 0;
_Bool b;
- b = 0 != ~uc; /* { dg-warning "9:promoted ~unsigned is always non-zero" } */
- b = 2 != ~uc; /* { dg-warning "9:comparison of promoted ~unsigned with constant" } */
- b = uc == ~uc; /* { dg-warning "10:comparison of promoted ~unsigned with unsigned" } */
+ b = 0 != ~uc; /* { dg-warning "9:promoted bitwise complement of an unsigned value is always nonzero" } */
+ b = 2 != ~uc; /* { dg-warning "9:comparison of promoted bitwise complement of an unsigned value with constant" } */
+ b = uc == ~uc; /* { dg-warning "10:comparison of promoted bitwise complement of an unsigned value with unsigned" } */
b = i == ui; /* { dg-warning "9:comparison of integer expressions of different signedness" } */
}
diff --git a/gcc/testsuite/gcc.dg/pr61096-1.c b/gcc/testsuite/gcc.dg/pr61096-1.c
index 111585d..e707904 100644
--- a/gcc/testsuite/gcc.dg/pr61096-1.c
+++ b/gcc/testsuite/gcc.dg/pr61096-1.c
@@ -47,7 +47,7 @@ __extension__ int a15[10] = {[2 ... 1] = 4 }; /* { dg-error "31:empty index rang
__extension__ int a16[10] = {[2 ... 100] = 4 }; /* { dg-error "31:array index range in initializer exceeds array bounds" } */
int a17[] = { .B = 1 }; /* { dg-error "15:field name not in record or union initializer" } */
int a18[] = { e }; /* { dg-error "15:initializer element is not constant" } */
-char a19[1] = { "x", "x" }; /* { dg-error "22:excess elements in char array initializer" } */
+char a19[1] = { "x", "x" }; /* { dg-error "22:excess elements in 'char' array initializer" } */
void
bar (void)
diff --git a/gcc/testsuite/gcc.dg/pr78902.c b/gcc/testsuite/gcc.dg/pr78902.c
new file mode 100644
index 0000000..51b4254
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr78902.c
@@ -0,0 +1,15 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target alloca } */
+
+void *ptr;
+
+void foo(void)
+{
+ __builtin_malloc (1); /* { dg-warning "ignoring return value of '__builtin_malloc' declared with attribute 'warn_unused_result'" } */
+ __builtin_calloc (10, 20); /* { dg-warning "ignoring return value of '__builtin_calloc' declared with attribute 'warn_unused_result'" } */
+ __builtin_alloca (10); /* { dg-warning "ignoring return value of '__builtin_alloca' declared with attribute 'warn_unused_result'" } */
+ __builtin_realloc (ptr, 100); /* { dg-warning "ignoring return value of '__builtin_realloc' declared with attribute 'warn_unused_result'" } */
+ __builtin_aligned_alloc (10, 16); /* { dg-warning "ignoring return value of '__builtin_aligned_alloc' declared with attribute 'warn_unused_result'" } */
+ __builtin_strdup ("pes"); /* { dg-warning "ignoring return value of '__builtin_strdup' declared with attribute 'warn_unused_result'" } */
+ __builtin_strndup ("pes", 10); /* { dg-warning "ignoring return value of '__builtin_strndup' declared with attribute 'warn_unused_result'" } */
+}
diff --git a/gcc/testsuite/gcc.dg/pr78957.c b/gcc/testsuite/gcc.dg/pr78957.c
index 305023e..4322119 100644
--- a/gcc/testsuite/gcc.dg/pr78957.c
+++ b/gcc/testsuite/gcc.dg/pr78957.c
@@ -1,6 +1,6 @@
/* PR driver/78957 */
/* { dg-do compile } */
/* { dg-options "-fno-sso-struct=none" } */
-/* { dg-error "unrecognized command line option" "" { target *-*-* } 0 } */
+/* { dg-error "unrecognized command-line option" "" { target *-*-* } 0 } */
int i;
diff --git a/gcc/testsuite/gcc.dg/pr87099.c b/gcc/testsuite/gcc.dg/pr87099.c
index 599d721..47e2315 100644
--- a/gcc/testsuite/gcc.dg/pr87099.c
+++ b/gcc/testsuite/gcc.dg/pr87099.c
@@ -1,5 +1,6 @@
/* PR middle-end/87099 */
/* { dg-do compile } */
+/* { dg-require-effective-target alloca } */
/* { dg-options "-Wstringop-overflow" } */
void bar (char *);
diff --git a/gcc/testsuite/gcc.dg/pr8715.c b/gcc/testsuite/gcc.dg/pr8715.c
index e45e77c..2878a48 100644
--- a/gcc/testsuite/gcc.dg/pr8715.c
+++ b/gcc/testsuite/gcc.dg/pr8715.c
@@ -7,7 +7,7 @@ int foo()
{
unsigned char b = '1';
- bool x = ~b; /* { dg-warning "promoted ~unsigned is always non-zero" } */
+ bool x = ~b; /* { dg-warning "promoted bitwise complement of an unsigned value is always nonzero" } */
return 0;
}
diff --git a/gcc/testsuite/gcc.dg/pr87320.c b/gcc/testsuite/gcc.dg/pr87320.c
index 38ece59..b92ba89 100644
--- a/gcc/testsuite/gcc.dg/pr87320.c
+++ b/gcc/testsuite/gcc.dg/pr87320.c
@@ -1,5 +1,6 @@
/* PR tree-optimization/87320 */
/* { dg-do run } */
+/* { dg-require-effective-target alloca } */
/* { dg-options "-O3" } */
/* { dg-additional-options "-mavx" { target avx_runtime } } */
diff --git a/gcc/testsuite/gcc.dg/pr87600.h b/gcc/testsuite/gcc.dg/pr87600.h
index 5ebb928..af91f63 100644
--- a/gcc/testsuite/gcc.dg/pr87600.h
+++ b/gcc/testsuite/gcc.dg/pr87600.h
@@ -7,7 +7,7 @@
#elif defined (__i386__)
# define REG1 "%eax"
# define REG2 "%edx"
-#elif defined (__powerpc__)
+#elif defined (__powerpc__) || defined (__POWERPC__)
# define REG1 "r3"
# define REG2 "r4"
#elif defined (__s390__)
diff --git a/gcc/testsuite/gcc.dg/pr8788-1.c b/gcc/testsuite/gcc.dg/pr8788-1.c
index b05f533..2281a02 100644
--- a/gcc/testsuite/gcc.dg/pr8788-1.c
+++ b/gcc/testsuite/gcc.dg/pr8788-1.c
@@ -12,7 +12,7 @@ typedef struct {
void switch_to_stack (my_stack *stack){
asm ( /* { dg-error "impossible constraint" } */
-/* { dg-warning "asm operand 1" "asm operand 1" { target *-*-* } .-1 } */
+/* { dg-warning "'asm' operand 1" "asm operand 1" { target *-*-* } .-1 } */
"\n"
: "+r" (stack->regs)
);
diff --git a/gcc/testsuite/gcc.dg/pr87954.c b/gcc/testsuite/gcc.dg/pr87954.c
new file mode 100644
index 0000000..620657c
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr87954.c
@@ -0,0 +1,21 @@
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+
+#define __GFP_DMA 1u
+#define __GFP_RECLAIM 0x10u
+
+#define KMALLOC_DMA 2
+#define KMALLOC_RECLAIM 1
+
+unsigned int
+imul(unsigned int flags)
+{
+ int is_dma, type_dma, is_rec;
+
+ is_dma = !!(flags & __GFP_DMA);
+ type_dma = is_dma * KMALLOC_DMA;
+ is_rec = !!(flags & __GFP_RECLAIM);
+
+ return type_dma + (is_rec * !is_dma) * KMALLOC_RECLAIM;
+}
+
+/* { dg-final { scan-tree-dump-times { \* } 1 "optimized" } } */
diff --git a/gcc/testsuite/gcc.dg/pr88870.c b/gcc/testsuite/gcc.dg/pr88870.c
index 3f46f32..81f686b 100644
--- a/gcc/testsuite/gcc.dg/pr88870.c
+++ b/gcc/testsuite/gcc.dg/pr88870.c
@@ -1,5 +1,6 @@
/* PR rtl-optimization/88870 */
/* { dg-do compile } */
+/* { dg-require-effective-target nonlocal_goto } */
/* { dg-options "-O1 -fexceptions -fnon-call-exceptions -ftrapv -fno-tree-dominator-opts" } */
int a, b;
diff --git a/gcc/testsuite/gcc.dg/pr89045.c b/gcc/testsuite/gcc.dg/pr89045.c
index d8ba65b..2b5730d 100644
--- a/gcc/testsuite/gcc.dg/pr89045.c
+++ b/gcc/testsuite/gcc.dg/pr89045.c
@@ -1,5 +1,6 @@
/* PR c/89045 */
/* { dg-do compile } */
+/* { dg-require-effective-target alloca } */
/* { dg-options "" } */
int
diff --git a/gcc/testsuite/gcc.dg/pr89737.c b/gcc/testsuite/gcc.dg/pr89737.c
index cd3dc81..7dc48cd 100644
--- a/gcc/testsuite/gcc.dg/pr89737.c
+++ b/gcc/testsuite/gcc.dg/pr89737.c
@@ -1,4 +1,6 @@
/* { dg-do compile } */
+/* { dg-require-effective-target indirect_jumps } */
+/* { dg-require-effective-target label_values } */
/* { dg-options "-O2 -fdump-tree-profile_estimate" } */
int a, b;
diff --git a/gcc/testsuite/gcc.dg/pr90082.c b/gcc/testsuite/gcc.dg/pr90082.c
index bb8293f..a8d76bb 100644
--- a/gcc/testsuite/gcc.dg/pr90082.c
+++ b/gcc/testsuite/gcc.dg/pr90082.c
@@ -1,5 +1,7 @@
/* PR rtl-optimization/90082 */
/* { dg-do compile } */
+/* { dg-require-effective-target nonlocal_goto } */
+/* { dg-require-effective-target label_values } */
/* { dg-options "-O1 -fnon-call-exceptions -ftrapv" } */
void *buf[5];
@@ -9,5 +11,5 @@ foo (int a)
{
if (__builtin_setjmp (buf) == 0)
__asm__ ("" : : "n" (a * 2)); /* { dg-error "impossible constraint in 'asm'" } */
- /* { dg-warning "asm operand 0 probably doesn't match constraints" "" { target *-*-* } .-1 } */
+ /* { dg-warning "'asm' operand 0 probably does not match constraints" "" { target *-*-* } .-1 } */
}
diff --git a/gcc/testsuite/gcc.dg/pr90263.c b/gcc/testsuite/gcc.dg/pr90263.c
new file mode 100644
index 0000000..3222a53
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr90263.c
@@ -0,0 +1,12 @@
+/* PR middle-end/90263 */
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+/* { dg-require-effective-target glibc } */
+
+int *f (int *p, int *q, long n)
+{
+ return __builtin_mempcpy (p, q, n);
+}
+
+/* { dg-final { scan-assembler "mempcpy" { target { i?86-*-* x86_64-*-* } } } } */
+/* { dg-final { scan-assembler "memcpy" { target { ! { i?86-*-* x86_64-*-* } } } } } */
diff --git a/gcc/testsuite/gcc.dg/pr90726.c b/gcc/testsuite/gcc.dg/pr90726.c
new file mode 100644
index 0000000..92987de
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr90726.c
@@ -0,0 +1,56 @@
+/* { dg-do compile } */
+/* { dg-options "-fgimple -O2" } */
+
+int __GIMPLE (ssa,guessed_local(12348030),startwith("fix_loops"))
+un (int dd)
+{
+ int s2;
+ int q8;
+ int nz;
+
+ __BB(2,guessed_local(12348030)):
+ goto __BB3(guessed(134217728));
+
+ __BB(3,loop_header(1),guessed_local(37044096)):
+ nz_7 = __PHI (__BB2: 0, __BB5: nz_10);
+ q8_13 = dd_9(D) * dd_9(D);
+ q8_17 = q8_13 * q8_13;
+ q8_21 = q8_17 * q8_17;
+ q8_25 = q8_21 * q8_21;
+ q8_29 = q8_25 * q8_25;
+ q8_33 = q8_29 * q8_29;
+ q8_37 = q8_33 * q8_33;
+ q8_41 = q8_37 * q8_37;
+ q8_45 = q8_41 * q8_41;
+ q8_49 = q8_45 * q8_45;
+ q8_53 = q8_49 * q8_49;
+ q8_57 = q8_53 * q8_53;
+ q8_61 = q8_57 * q8_57;
+ q8_65 = q8_61 * q8_61;
+ q8_69 = q8_65 * q8_65;
+ q8_73 = q8_69 * q8_69;
+ q8_77 = q8_73 * q8_73;
+ q8_81 = q8_77 * q8_77;
+ q8_85 = q8_81 * q8_81;
+ q8_89 = q8_85 * q8_85;
+ q8_93 = q8_89 * q8_89;
+ q8_97 = q8_93 * q8_93;
+ q8_101 = q8_97 * q8_97;
+ q8_105 = q8_101 * q8_101;
+ q8_109 = q8_105 * q8_105;
+ q8_113 = q8_109 * q8_109;
+ q8_117 = q8_113 * q8_113;
+ q8_121 = q8_117 * q8_117;
+ nz_10 = nz_7 + 1;
+ if (nz_10 != 3)
+ goto __BB5(guessed(89478485));
+ else
+ goto __BB4(guessed(44739243));
+
+ __BB(5,guessed_local(24696064)):
+ goto __BB3(precise(134217728));
+
+ __BB(4,guessed_local(12348031)):
+ return q8_121;
+
+}
diff --git a/gcc/testsuite/gcc.dg/pr90733.c b/gcc/testsuite/gcc.dg/pr90733.c
new file mode 100644
index 0000000..7d2a7fb
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr90733.c
@@ -0,0 +1,22 @@
+/* PR debug/90733 */
+/* { dg-do compile } */
+/* { dg-options "-g -O2 -w" } */
+
+struct S { unsigned a : 1; };
+union U { struct S b; _Complex unsigned c; };
+
+union U
+foo (union U d)
+{
+ union U e = d;
+ return e;
+}
+
+int
+bar (void)
+{
+ union U x, y;
+ x.c = x.b.a;
+ y = foo (x);
+ return x.c != y.c;
+}
diff --git a/gcc/testsuite/gcc.dg/pr90760.c b/gcc/testsuite/gcc.dg/pr90760.c
new file mode 100644
index 0000000..6092a4e
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr90760.c
@@ -0,0 +1,9 @@
+/* PR c/90760 */
+/* { dg-do compile } */
+/* { dg-require-alias "" } */
+/* { dg-require-named-sections "" } */
+
+void bar (void) {}
+void foo (void) __attribute__ ((alias ("bar"))); /* { dg-error "section of alias 'foo' must match section of its target" } */
+void foo (void) __attribute__ ((section ("baz")));
+void qux (void) __attribute__ ((alias ("bar"), section ("baz"))); /* { dg-error "section of alias 'qux' must match section of its target" } */
diff --git a/gcc/testsuite/gcc.dg/pr90866-2.c b/gcc/testsuite/gcc.dg/pr90866-2.c
new file mode 100644
index 0000000..6414799
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr90866-2.c
@@ -0,0 +1,26 @@
+/* PR tree-optimization/90866 - ICE in fold_binary_loc, at fold-const.c:9827
+ { dg-do compile }
+ { dg-require-effective-target global_constructor }
+ { dg-options "-O2 -fsanitize=thread" }
+ */
+
+typedef enum { a } b;
+typedef struct {
+ int c[0];
+} d;
+typedef struct {
+ int *data;
+} e;
+typedef struct {
+ e buffer;
+} f;
+int g, h;
+
+int i(f *j, d *k, b l, int m) {
+ if (l)
+ if (m) {
+ h = j->buffer.data[0];
+ k->c[g] = k->c[g] * 8;
+ }
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/pr90866.c b/gcc/testsuite/gcc.dg/pr90866.c
new file mode 100644
index 0000000..66c92ee
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr90866.c
@@ -0,0 +1,18 @@
+/* PR tree-optimization/90866 - ICE in fold_binary_loc, at fold-const.c:9827
+ { dg-do compile }
+ { dg-options "-O3 -Wall -fno-tree-loop-optimize" } */
+
+int a[1024], b[1024];
+
+void f (void)
+{
+ int i = 0;
+ for ( ; ; i++)
+ {
+ b[16] = a[i * 16 + 10];
+ b[i * 16 + 11] = a[i * 16 + 11] * 3;
+ b[i * 16 + 12] = a[i * 16 + 12] * 4;
+ b[i * 16 + 13] = a[i * 16 + 13] * 4;
+ b[i * 16 + 14] = a[i * 16 + 14] * 3;
+ }
+}
diff --git a/gcc/testsuite/gcc.dg/pr90892.c b/gcc/testsuite/gcc.dg/pr90892.c
new file mode 100644
index 0000000..e4b5310
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr90892.c
@@ -0,0 +1,14 @@
+/* PR tree-optimization/90892 */
+/* { dg-do run } */
+/* { dg-options "-O2" } */
+
+const char *a = "A\0b";
+
+int
+main()
+{
+ if (__builtin_strncmp(a, "A\0", 2) != 0)
+ __builtin_abort ();
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/pr91069.c b/gcc/testsuite/gcc.dg/pr91069.c
new file mode 100644
index 0000000..221da30
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr91069.c
@@ -0,0 +1,20 @@
+/* { dg-do run } */
+/* { dg-options "-std=gnu11" } */
+
+typedef double v2df __attribute__((vector_size(16)));
+typedef long v2di __attribute__((vector_size(16)));
+
+void foo (v2df *res, v2df *src)
+{
+ v2df x = *src;
+ *res = __builtin_shuffle ((v2df) { 1.0, 0.0 }, x, (v2di) { 1, 3 });
+}
+
+int main()
+{
+ v2df x = (v2df) { 0.0, 2.0 };
+ foo (&x, &x);
+ if (x[0] != 0.0 || x[1] != 2.0)
+ __builtin_abort ();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/predict-9.c b/gcc/testsuite/gcc.dg/predict-9.c
index 7e5ba08..f491c51 100644
--- a/gcc/testsuite/gcc.dg/predict-9.c
+++ b/gcc/testsuite/gcc.dg/predict-9.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -fdisable-tree-evrp -fdump-tree-profile_estimate" } */
+/* { dg-options "-O2 -fdisable-tree-evrp -fdump-tree-profile_estimate -fno-finite-loops" } */
extern int global;
extern int global2;
diff --git a/gcc/testsuite/gcc.dg/pure-2.c b/gcc/testsuite/gcc.dg/pure-2.c
index fe6e2bc..318cfd1 100644
--- a/gcc/testsuite/gcc.dg/pure-2.c
+++ b/gcc/testsuite/gcc.dg/pure-2.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -Wsuggest-attribute=pure" } */
+/* { dg-options "-O2 -Wsuggest-attribute=pure -fno-finite-loops" } */
/* { dg-add-options bind_pic_locally } */
extern int extern_const(int a) __attribute__ ((pure));
diff --git a/gcc/testsuite/gcc.dg/simd-1.c b/gcc/testsuite/gcc.dg/simd-1.c
index d77f2bb..6017248 100644
--- a/gcc/testsuite/gcc.dg/simd-1.c
+++ b/gcc/testsuite/gcc.dg/simd-1.c
@@ -45,7 +45,7 @@ hanneke ()
foo = (typeof (foo)) foo2;
/* Casted assignment between scalar and SIMD of different size. */
- foo1 = (typeof (foo1)) foo2; /* { dg-error "can't convert a vector of type" } */
+ foo1 = (typeof (foo1)) foo2; /* { dg-error "cannot convert a vector of type" } */
/* Operators on compatible SIMD types. */
a += b + b;
diff --git a/gcc/testsuite/gcc.dg/simd-2.c b/gcc/testsuite/gcc.dg/simd-2.c
index 13e1cab..d24e076 100644
--- a/gcc/testsuite/gcc.dg/simd-2.c
+++ b/gcc/testsuite/gcc.dg/simd-2.c
@@ -33,10 +33,10 @@ hanneke ()
foo = a; /* { dg-error "incompatible types when assigning" } */
/* Casted assignment between scalar and SIMD of same size. */
- foo = (typeof (foo)) foo2; /* { dg-error "aggregate value used where a float was expected" } */
+ foo = (typeof (foo)) foo2; /* { dg-error "aggregate value used where a floating-point was expected" } */
/* Casted assignment between scalar and SIMD of different size. */
- foo1 = (typeof (foo1)) foo2; /* { dg-error "aggregate value used where a float was expected" } */
+ foo1 = (typeof (foo1)) foo2; /* { dg-error "aggregate value used where a floating-point was expected" } */
/* Operators on compatible SIMD types. */
a += b + b;
diff --git a/gcc/testsuite/gcc.dg/spellcheck-options-1.c b/gcc/testsuite/gcc.dg/spellcheck-options-1.c
index cd5fdca..bebb494 100644
--- a/gcc/testsuite/gcc.dg/spellcheck-options-1.c
+++ b/gcc/testsuite/gcc.dg/spellcheck-options-1.c
@@ -1,4 +1,4 @@
/* { dg-do compile } */
/* { dg-options "-Wcoercion" } */
-/* { dg-error "unrecognized command line option '-Wcoercion'; did you mean '-Wconversion'?" "" { target *-*-* } 0 } */
+/* { dg-error "unrecognized command-line option '-Wcoercion'; did you mean '-Wconversion'?" "" { target *-*-* } 0 } */
diff --git a/gcc/testsuite/gcc.dg/spellcheck-options-10.c b/gcc/testsuite/gcc.dg/spellcheck-options-10.c
index 1957205..77c6b54 100644
--- a/gcc/testsuite/gcc.dg/spellcheck-options-10.c
+++ b/gcc/testsuite/gcc.dg/spellcheck-options-10.c
@@ -3,4 +3,4 @@
/* { dg-do compile } */
/* { dg-options "-fno-if-convert" } */
-/* { dg-error "unrecognized command line option .-fno-if-convert.; did you mean .-fno-if-conversion.?" "" { target *-*-* } 0 } */
+/* { dg-error "unrecognized command-line option .-fno-if-convert.; did you mean .-fno-if-conversion.?" "" { target *-*-* } 0 } */
diff --git a/gcc/testsuite/gcc.dg/spellcheck-options-12.c b/gcc/testsuite/gcc.dg/spellcheck-options-12.c
index b5e65e5..9fbd944 100644
--- a/gcc/testsuite/gcc.dg/spellcheck-options-12.c
+++ b/gcc/testsuite/gcc.dg/spellcheck-options-12.c
@@ -4,4 +4,4 @@
/* { dg-do compile } */
/* { dg-options "-fno-stack-protector-explicit" } */
-/* { dg-error "unrecognized command line option .-fno-stack-protector-explicit.; did you mean .-fstack-protector-explicit.." "" { target *-*-* } 0 } */
+/* { dg-error "unrecognized command-line option .-fno-stack-protector-explicit.; did you mean .-fstack-protector-explicit.." "" { target *-*-* } 0 } */
diff --git a/gcc/testsuite/gcc.dg/spellcheck-options-13.c b/gcc/testsuite/gcc.dg/spellcheck-options-13.c
index 0d00642..94db0c5 100644
--- a/gcc/testsuite/gcc.dg/spellcheck-options-13.c
+++ b/gcc/testsuite/gcc.dg/spellcheck-options-13.c
@@ -2,4 +2,4 @@
/* { dg-do compile } */
/* { dg-options "-fsanitize" } */
-/* { dg-error "unrecognized command line option '-fsanitize'; did you mean '-fsanitize='?" "" { target *-*-* } 0 } */
+/* { dg-error "unrecognized command-line option '-fsanitize'; did you mean '-fsanitize='?" "" { target *-*-* } 0 } */
diff --git a/gcc/testsuite/gcc.dg/spellcheck-options-18.c b/gcc/testsuite/gcc.dg/spellcheck-options-18.c
index 387d04e..26694f9 100644
--- a/gcc/testsuite/gcc.dg/spellcheck-options-18.c
+++ b/gcc/testsuite/gcc.dg/spellcheck-options-18.c
@@ -1,3 +1,3 @@
/* { dg-do compile } */
/* { dg-options "-fprofile-update" } */
-/* { dg-error "unrecognized command line option '-fprofile-update'; did you mean '-fprofile-update='?" "" { target *-*-* } 0 } */
+/* { dg-error "unrecognized command-line option '-fprofile-update'; did you mean '-fprofile-update='?" "" { target *-*-* } 0 } */
diff --git a/gcc/testsuite/gcc.dg/spellcheck-options-19.c b/gcc/testsuite/gcc.dg/spellcheck-options-19.c
index 5a10476..68e85a7 100644
--- a/gcc/testsuite/gcc.dg/spellcheck-options-19.c
+++ b/gcc/testsuite/gcc.dg/spellcheck-options-19.c
@@ -1,3 +1,3 @@
/* { dg-do compile } */
/* { dg-options "-fno-sanitize" } */
-/* { dg-error "unrecognized command line option '-fno-sanitize'; did you mean '-fno-sanitize='?" "" { target *-*-* } 0 } */
+/* { dg-error "unrecognized command-line option '-fno-sanitize'; did you mean '-fno-sanitize='?" "" { target *-*-* } 0 } */
diff --git a/gcc/testsuite/gcc.dg/spellcheck-options-2.c b/gcc/testsuite/gcc.dg/spellcheck-options-2.c
index 786266d..5156ad3 100644
--- a/gcc/testsuite/gcc.dg/spellcheck-options-2.c
+++ b/gcc/testsuite/gcc.dg/spellcheck-options-2.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
/* { dg-options "-Wthis-should-not-get-a-hint" } */
/* { dg-bogus "did you mean" "" { target *-*-* } 0 } */
-/* { dg-error "unrecognized command line option '-Wthis-should-not-get-a-hint'" "" { target *-*-* } 0 } */
+/* { dg-error "unrecognized command-line option '-Wthis-should-not-get-a-hint'" "" { target *-*-* } 0 } */
diff --git a/gcc/testsuite/gcc.dg/spellcheck-options-20.c b/gcc/testsuite/gcc.dg/spellcheck-options-20.c
index dfc6149..d856d5a 100644
--- a/gcc/testsuite/gcc.dg/spellcheck-options-20.c
+++ b/gcc/testsuite/gcc.dg/spellcheck-options-20.c
@@ -1,3 +1,3 @@
/* { dg-do compile } */
/* { dg-options "-Walloc-size-larger-than" } */
-/* { dg-error "unrecognized command line option '-Walloc-size-larger-than'; did you mean '-Walloc-size-larger-than='?" "" { target *-*-* } 0 } */
+/* { dg-error "unrecognized command-line option '-Walloc-size-larger-than'; did you mean '-Walloc-size-larger-than='?" "" { target *-*-* } 0 } */
diff --git a/gcc/testsuite/gcc.dg/spellcheck-options-3.c b/gcc/testsuite/gcc.dg/spellcheck-options-3.c
index 4133df9..cecc502 100644
--- a/gcc/testsuite/gcc.dg/spellcheck-options-3.c
+++ b/gcc/testsuite/gcc.dg/spellcheck-options-3.c
@@ -3,4 +3,4 @@
/* { dg-do compile } */
/* { dg-options "-sanitize=address" } */
-/* { dg-error "unrecognized command line option '-sanitize=address'; did you mean '-fsanitize=address'?" "" { target *-*-* } 0 } */
+/* { dg-error "unrecognized command-line option '-sanitize=address'; did you mean '-fsanitize=address'?" "" { target *-*-* } 0 } */
diff --git a/gcc/testsuite/gcc.dg/spellcheck-options-4.c b/gcc/testsuite/gcc.dg/spellcheck-options-4.c
index 252376f..ab730ed 100644
--- a/gcc/testsuite/gcc.dg/spellcheck-options-4.c
+++ b/gcc/testsuite/gcc.dg/spellcheck-options-4.c
@@ -3,4 +3,4 @@
/* { dg-do compile } */
/* { dg-options "-sanitize-recover=integer-divide-by-0" } */
-/* { dg-error "unrecognized command line option '-sanitize-recover=integer-divide-by-0'; did you mean '-fsanitize-recover=integer-divide-by-zero'?" "" { target *-*-* } 0 } */
+/* { dg-error "unrecognized command-line option '-sanitize-recover=integer-divide-by-0'; did you mean '-fsanitize-recover=integer-divide-by-zero'?" "" { target *-*-* } 0 } */
diff --git a/gcc/testsuite/gcc.dg/spellcheck-options-5.c b/gcc/testsuite/gcc.dg/spellcheck-options-5.c
index 9a02bb7..097faf0 100644
--- a/gcc/testsuite/gcc.dg/spellcheck-options-5.c
+++ b/gcc/testsuite/gcc.dg/spellcheck-options-5.c
@@ -3,4 +3,4 @@
/* { dg-do compile } */
/* { dg-options "-no-sanitize=all" } */
-/* { dg-error "unrecognized command line option '-no-sanitize=all'; did you mean '-fno-sanitize=all'?" "" { target *-*-* } 0 } */
+/* { dg-error "unrecognized command-line option '-no-sanitize=all'; did you mean '-fno-sanitize=all'?" "" { target *-*-* } 0 } */
diff --git a/gcc/testsuite/gcc.dg/spellcheck-options-6.c b/gcc/testsuite/gcc.dg/spellcheck-options-6.c
index 4d6bf0d..591e214 100644
--- a/gcc/testsuite/gcc.dg/spellcheck-options-6.c
+++ b/gcc/testsuite/gcc.dg/spellcheck-options-6.c
@@ -3,4 +3,4 @@
/* { dg-do compile } */
/* { dg-options "-fwarn-no-abi-tag" } */
-/* { dg-error "unrecognized command line option '-fwarn-no-abi-tag'; did you mean '--warn-no-abi-tag'?" "" { target *-*-* } 0 } */
+/* { dg-error "unrecognized command-line option '-fwarn-no-abi-tag'; did you mean '--warn-no-abi-tag'?" "" { target *-*-* } 0 } */
diff --git a/gcc/testsuite/gcc.dg/spellcheck-options-7.c b/gcc/testsuite/gcc.dg/spellcheck-options-7.c
index ca893994..277d7d4 100644
--- a/gcc/testsuite/gcc.dg/spellcheck-options-7.c
+++ b/gcc/testsuite/gcc.dg/spellcheck-options-7.c
@@ -3,4 +3,4 @@
/* { dg-do compile } */
/* { dg-options "-tls-model=global-dynamic" } */
-/* { dg-error "unrecognized command line option '-tls-model=global-dynamic'; did you mean '-ftls-model=global-dynamic'?" "" { target *-*-* } 0 } */
+/* { dg-error "unrecognized command-line option '-tls-model=global-dynamic'; did you mean '-ftls-model=global-dynamic'?" "" { target *-*-* } 0 } */
diff --git a/gcc/testsuite/gcc.dg/spellcheck-options-8.c b/gcc/testsuite/gcc.dg/spellcheck-options-8.c
index 2cc6c1f..43cd5ac 100644
--- a/gcc/testsuite/gcc.dg/spellcheck-options-8.c
+++ b/gcc/testsuite/gcc.dg/spellcheck-options-8.c
@@ -3,4 +3,4 @@
/* { dg-do compile } */
/* { dg-options "--Wno-narrowing" } */
-/* { dg-error "unrecognized command line option '--Wno-narrowing'; did you mean '-Wno-narrowing'?" "" { target *-*-* } 0 } */
+/* { dg-error "unrecognized command-line option '--Wno-narrowing'; did you mean '-Wno-narrowing'?" "" { target *-*-* } 0 } */
diff --git a/gcc/testsuite/gcc.dg/spellcheck-options-9.c b/gcc/testsuite/gcc.dg/spellcheck-options-9.c
index 768b6f8..509f9e5 100644
--- a/gcc/testsuite/gcc.dg/spellcheck-options-9.c
+++ b/gcc/testsuite/gcc.dg/spellcheck-options-9.c
@@ -3,4 +3,4 @@
/* { dg-do compile } */
/* { dg-options "-fmo-unroll-loops" } */
-/* { dg-error "unrecognized command line option '-fmo-unroll-loops'; did you mean '-fno-unroll-loops'?" "" { target *-*-* } 0 } */
+/* { dg-error "unrecognized command-line option '-fmo-unroll-loops'; did you mean '-fno-unroll-loops'?" "" { target *-*-* } 0 } */
diff --git a/gcc/testsuite/gcc.dg/spellcheck-params-2.c b/gcc/testsuite/gcc.dg/spellcheck-params-2.c
index 27e293f..8187de4 100644
--- a/gcc/testsuite/gcc.dg/spellcheck-params-2.c
+++ b/gcc/testsuite/gcc.dg/spellcheck-params-2.c
@@ -1,4 +1,4 @@
/* { dg-do compile } */
/* { dg-options "--param does-not-resemble-anything=42" } */
-/* { dg-error "invalid --param name .does-not-resemble-anything." "" { target *-*-* } 0 } */
+/* { dg-error "invalid '--param' name 'does-not-resemble-anything'" "" { target *-*-* } 0 } */
diff --git a/gcc/testsuite/gcc.dg/spellcheck-params.c b/gcc/testsuite/gcc.dg/spellcheck-params.c
index 1bb7bca..01e1343 100644
--- a/gcc/testsuite/gcc.dg/spellcheck-params.c
+++ b/gcc/testsuite/gcc.dg/spellcheck-params.c
@@ -1,4 +1,4 @@
/* { dg-do compile } */
/* { dg-options "--param max-early-inliner-iteration=3" } */
-/* { dg-error "invalid --param name .max-early-inliner-iteration.; did you mean .max-early-inliner-iterations.?" "" { target *-*-* } 0 } */
+/* { dg-error "invalid '--param' name 'max-early-inliner-iteration'; did you mean 'max-early-inliner-iterations'?" "" { target *-*-* } 0 } */
diff --git a/gcc/testsuite/gcc.dg/stack-usage-1.c b/gcc/testsuite/gcc.dg/stack-usage-1.c
index e644014..b264222 100644
--- a/gcc/testsuite/gcc.dg/stack-usage-1.c
+++ b/gcc/testsuite/gcc.dg/stack-usage-1.c
@@ -93,6 +93,8 @@
# define SIZE 254
#elif defined (__nios2__)
# define SIZE 252
+#elif defined (__PRU__)
+# define SIZE 252
#elif defined (__v850__)
#define SIZE 260
#elif defined (__mn10300__)
diff --git a/gcc/testsuite/gcc.dg/store_merging_27.c b/gcc/testsuite/gcc.dg/store_merging_27.c
index a691368..d3cd117 100644
--- a/gcc/testsuite/gcc.dg/store_merging_27.c
+++ b/gcc/testsuite/gcc.dg/store_merging_27.c
@@ -18,7 +18,7 @@ bar (struct S *x)
int
main ()
{
- struct S s = {};
+ __attribute__((aligned(8))) struct S s = {};
s.buf[1] = 1;
s.buf[3] = 2;
bar (&s);
diff --git a/gcc/testsuite/gcc.dg/store_merging_28.c b/gcc/testsuite/gcc.dg/store_merging_28.c
index 95a0822..2d6cffc4 100644
--- a/gcc/testsuite/gcc.dg/store_merging_28.c
+++ b/gcc/testsuite/gcc.dg/store_merging_28.c
@@ -3,7 +3,7 @@
/* { dg-require-effective-target store_merge } */
/* { dg-options "-O2 -fno-ipa-icf -fdump-tree-store-merging-details" } */
/* { dg-final { scan-tree-dump-times "New sequence of \[24] stores to replace old one of 16 stores" 8 "store-merging" { target { i?86-*-* x86_64-*-* } } } } */
-/* { dg-final { scan-tree-dump-times "New sequence of \[24] stores to replace old one of 6 stores" 1 "store-merging" } } */
+/* { dg-final { scan-tree-dump-times "New sequence of \[24] stores to replace old one of 6 stores" 1 "store-merging" { target { ! arm*-*-* } } } } */
typedef struct S { char data[16]; } S;
void optimize_me (S);
diff --git a/gcc/testsuite/gcc.dg/store_merging_29.c b/gcc/testsuite/gcc.dg/store_merging_29.c
index 52dd0f7..6b32aa9 100644
--- a/gcc/testsuite/gcc.dg/store_merging_29.c
+++ b/gcc/testsuite/gcc.dg/store_merging_29.c
@@ -2,8 +2,8 @@
/* { dg-do run { target int32 } } */
/* { dg-require-effective-target store_merge } */
/* { dg-options "-O2 -fdump-tree-store-merging-details" } */
-/* { dg-final { scan-tree-dump "New sequence of 3 stores to replace old one of 6 stores" "store-merging" { target le } } } */
-/* { dg-final { scan-tree-dump "New sequence of \[34] stores to replace old one of 6 stores" "store-merging" { target be } } } */
+/* { dg-final { scan-tree-dump "New sequence of 3 stores to replace old one of 6 stores" "store-merging" { target { le && { ! arm*-*-* } } } } } */
+/* { dg-final { scan-tree-dump "New sequence of \[34] stores to replace old one of 6 stores" "store-merging" { target { be && { ! arm*-*-* } } } } } */
struct T { char a[1024]; };
diff --git a/gcc/testsuite/gcc.dg/store_merging_5.c b/gcc/testsuite/gcc.dg/store_merging_5.c
index e6c3497..6e7c725 100644
--- a/gcc/testsuite/gcc.dg/store_merging_5.c
+++ b/gcc/testsuite/gcc.dg/store_merging_5.c
@@ -26,5 +26,7 @@ foo1 (struct bar *p, char tmp)
}
-/* { dg-final { scan-tree-dump-times "Merging successful" 1 "store-merging" } } */
-/* { dg-final { scan-tree-dump-times "MEM\\\[.*\\\]" 1 "store-merging" } } */
+/* { dg-final { scan-tree-dump-times "Merging successful" 1 "store-merging" } }
+ { dg-final { scan-tree-dump-times "MEM\\\[.*\\\]" 1 "store-merging" { target { ! store_merge } } } }
+ { dg-final { scan-tree-dump-times "MEM <unsigned int> \\\[.*\\\]" 1 "store-merging" { target { store_merge && ilp32 } } } }
+ { dg-final { scan-tree-dump-times "MEM <unsigned long> \\\[.*\\\]" 1 "store-merging" { target { store_merge && lp64 } } } } */
diff --git a/gcc/testsuite/gcc.dg/strlenopt-49.c b/gcc/testsuite/gcc.dg/strlenopt-49.c
index 2e6ccd3..f901fd14 100644
--- a/gcc/testsuite/gcc.dg/strlenopt-49.c
+++ b/gcc/testsuite/gcc.dg/strlenopt-49.c
@@ -11,8 +11,8 @@ const char a3[3] = "12\0";
const char a8[8] = "1234567\0";
const char a9[9] = "12345678\0";
-const char ax[9] = "12345678\0\0\0\0"; /* { dg-warning "initializer-string for array of chars is too long" } */
-const char ay[9] = "\00012345678\0\0\0\0"; /* { dg-warning "initializer-string for array of chars is too long" } */
+const char ax[9] = "12345678\0\0\0\0"; /* { dg-warning "initializer-string for array of 'char' is too long" } */
+const char ay[9] = "\00012345678\0\0\0\0"; /* { dg-warning "initializer-string for array of 'char' is too long" } */
int len1 (void)
diff --git a/gcc/testsuite/gcc.dg/strlenopt-62.c b/gcc/testsuite/gcc.dg/strlenopt-62.c
new file mode 100644
index 0000000..569c18a
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/strlenopt-62.c
@@ -0,0 +1,190 @@
+/* PR tree-optimization/90662 - strlen of a string in a vla plus offset
+ not folded
+ { dg-do compile }
+ { dg-require-effective-target alloca }
+ { dg-options "-O2 -Wall -fdump-tree-gimple -fdump-tree-optimized" } */
+
+#include "strlenopt.h"
+
+typedef __INT16_TYPE__ int16_t;
+typedef __INT32_TYPE__ int32_t;
+
+#define CONCAT(x, y) x ## y
+#define CAT(x, y) CONCAT (x, y)
+#define FAILNAME(name, counter) \
+ CAT (CAT (CAT (call_ ## name ##_on_line_, __LINE__), _), counter)
+
+#define FAIL(name, counter) do { \
+ extern void FAILNAME (name, counter) (void); \
+ FAILNAME (name, counter)(); \
+ } while (0)
+
+/* Macro to emit a call to funcation named
+ call_in_true_branch_not_eliminated_on_line_NNN()
+ for each call that's expected to be eliminated. The dg-final
+ scan-tree-dump-time directive at the bottom of the test verifies
+ that no such call appears in output. */
+#define ELIM(expr) \
+ if (!(expr)) FAIL (in_true_branch_not_eliminated, __COUNTER__); else (void)0
+
+#define ARGS(...) __VA_ARGS__
+
+void sink (void*, ...);
+
+
+#define T(Type, expect, init, p) \
+ do { \
+ Type vla[n]; \
+ char *ptr = strcpy ((char*)vla, init); \
+ ELIM (expect == strlen (p)); \
+ sink (ptr); \
+ } while (0)
+
+void test_char_vla_local (int n)
+{
+ T (char, 0, "", vla);
+ T (char, 0, "\0", vla);
+ T (char, 1, "1", vla);
+ T (char, 2, "12", vla);
+ T (char, 3, "123", vla);
+
+ T (char, 2, "123", vla + 1);
+ T (char, 1, "123", &vla[2]);
+ T (char, 0, "123", &vla[1] + 2);
+
+ T (char, 2, "123", &vla[2] - 1);
+ T (char, 3, "123", &vla[1] - 1);
+
+ T (char, 0, "", ptr);
+ T (char, 0, "\0", ptr);
+ T (char, 1, "1", ptr);
+ T (char, 2, "12", ptr);
+ T (char, 3, "123", ptr);
+
+ T (char, 2, "123", ptr + 1);
+ T (char, 1, "123", &ptr[2]);
+ T (char, 0, "123", &ptr[1] + 2);
+}
+
+void test_int16_vla_local (int n)
+{
+ T (int16_t, 0, "", (char*)vla);
+ T (int16_t, 0, "\0", (char*)vla);
+ T (int16_t, 1, "1", (char*)vla);
+ T (int16_t, 2, "12", (char*)vla);
+ T (int16_t, 3, "123", (char*)vla);
+
+ T (int16_t, 2, "1234", (char*)(vla + 1));
+ T (int16_t, 2, "123456", (char*)&vla[2]);
+ T (int16_t, 1, "123456", (char*)&vla[2] + 1);
+ T (int16_t, 0, "123456", (char*)&vla[2] + 2);
+ T (int16_t, 0, "123456", (char*)(&vla[1] + 2));
+
+ T (int16_t, 3, "123456", (char*)&vla[2] - 1);
+ T (int16_t, 4, "123456", (char*)&vla[2] - 2);
+
+ T (int16_t, 0, "", ptr);
+ T (int16_t, 0, "\0", ptr);
+ T (int16_t, 1, "1", ptr);
+ T (int16_t, 2, "12", ptr);
+ T (int16_t, 3, "123", ptr);
+
+ T (int16_t, 2, "123", ptr + 1);
+ T (int16_t, 1, "123", &ptr[2]);
+ T (int16_t, 0, "123", &ptr[1] + 2);
+}
+
+void test_int_vla_local (int n)
+{
+ T (int16_t, 0, "", (char*)vla);
+ T (int16_t, 0, "\0", (char*)vla);
+ T (int16_t, 1, "1", (char*)vla);
+ T (int16_t, 2, "12", (char*)vla);
+ T (int16_t, 3, "123", (char*)vla);
+
+ T (int16_t, 2, "1234", (char*)(vla + 1));
+ T (int16_t, 2, "123456", (char*)&vla[2]);
+ T (int16_t, 1, "123456", (char*)&vla[2] + 1);
+ T (int16_t, 0, "123456", (char*)&vla[2] + 2);
+ T (int16_t, 0, "123456", (char*)(&vla[1] + 2));
+
+ T (int, 0, "", ptr);
+ T (int, 0, "\0", ptr);
+ T (int, 1, "1", ptr);
+ T (int, 2, "12", ptr);
+ T (int, 3, "123", ptr);
+
+ T (int, 2, "123", ptr + 1);
+ T (int, 1, "123", &ptr[2]);
+ T (int, 0, "123", &ptr[1] + 2);
+}
+
+
+#undef T
+#define T(Type, expect, parr, init, p) \
+ do { \
+ Type (*parray)[] = *ppa++; \
+ char *ptr = strcpy ((char*)parr, init); \
+ (void)&ptr; \
+ ELIM (expect == strlen (p)); \
+ } while (0)
+
+/* Have the function take a pointer to pointers to arrays so that each
+ test case can use its own pointer to avoid interference between. */
+
+void test_char_array_ptr (char (**ppa)[])
+{
+ T (char, 0, *parray, "", *parray);
+ T (char, 0, *parray, "", &(*parray)[0]);
+
+ T (char, 1, *parray, "1", &(*parray)[0]);
+ T (char, 0, *parray, "1", &(*parray)[1]);
+
+ T (char, 2, *parray, "12", &(*parray)[0]);
+ T (char, 1, *parray, "12", &(*parray)[1]);
+ T (char, 0, *parray, "12", &(*parray)[2]);
+
+ T (char, 3, *parray, "123", &(*parray)[0]);
+ T (char, 2, *parray, "123", &(*parray)[1]);
+ T (char, 1, *parray, "123", &(*parray)[2]);
+ T (char, 0, *parray, "123", &(*parray)[3]);
+
+ T (char, 3, *parray, "123", ptr);
+ T (char, 2, *parray, "123", &ptr[1]);
+ T (char, 1, *parray, "123", &ptr[2]);
+ T (char, 0, *parray, "123", &ptr[3]);
+}
+
+void test_int16_array_ptr (int16_t (**ppa)[])
+{
+ T (int16_t, 0, *parray, "", (char*)*parray);
+ T (int16_t, 0, *parray, "", (char*)&(*parray)[0]);
+
+ T (int16_t, 1, *parray, "1", (char*)&(*parray)[0]);
+ T (int16_t, 0, *parray, "12", (char*)&(*parray)[1]);
+
+ T (int16_t, 2, *parray, "12", (char*)&(*parray)[0]);
+ T (int16_t, 1, *parray, "12", (char*)&(*parray)[0] + 1);
+ T (int16_t, 2, *parray, "1234", (char*)&(*parray)[1]);
+ T (int16_t, 1, *parray, "1234", (char*)&(*parray)[1] + 1);
+ T (int16_t, 0, *parray, "1234", (char*)&(*parray)[2]);
+
+ T (int16_t, 6, *parray, "123456", (char*)&(*parray)[0]);
+ T (int16_t, 5, *parray, "123456", (char*)&(*parray)[0] + 1);
+ T (int16_t, 0, *parray, "123456", (char*)&(*parray)[0] + 6);
+ T (int16_t, 4, *parray, "123456", (char*)&(*parray)[1]);
+ T (int16_t, 3, *parray, "123456", (char*)&(*parray)[1] + 1);
+ T (int16_t, 0, *parray, "123456", (char*)&(*parray)[1] + 4);
+ T (int16_t, 2, *parray, "123456", (char*)&(*parray)[2]);
+ T (int16_t, 1, *parray, "123456", (char*)&(*parray)[2] + 1);
+ T (int16_t, 0, *parray, "123456", (char*)&(*parray)[2] + 2);
+ T (int16_t, 0, *parray, "123456", (char*)&(*parray)[3]);
+
+ T (int16_t, 3, *parray, "123", (char*)ptr);
+ T (int16_t, 2, *parray, "123", (char*)&ptr[1]);
+ T (int16_t, 1, *parray, "123", (char*)&ptr[2]);
+ T (int16_t, 0, *parray, "123", (char*)&ptr[3]);
+}
+
+/* { dg-final { scan-tree-dump-times "strlen" 0 "optimized" } }
+ { dg-final { scan-tree-dump-times "not_eliminated" 0 "optimized" } } */
diff --git a/gcc/testsuite/gcc.dg/strlenopt-63.c b/gcc/testsuite/gcc.dg/strlenopt-63.c
new file mode 100644
index 0000000..f77db6b
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/strlenopt-63.c
@@ -0,0 +1,158 @@
+/* PR tree-optimization/90662 - strlen of a string in a vla plus offset
+ not folded
+ Verify that strlen of pointers to char arrays are computed correctly
+ (whether folded or not).
+ { dg-do run }
+ { dg-options "-O2 -Wall" } */
+
+#include "strlenopt.h"
+
+#define A(expr) \
+ ((expr) \
+ ? (void)0 \
+ : (__builtin_printf ("assertion failed on line %i: %s\n", \
+ __LINE__, #expr), \
+ __builtin_abort ()))
+
+typedef char A5[5];
+
+A5 a5[5];
+A5* p[5] = { &a5[4], &a5[3], &a5[2], &a5[1], &a5[0] };
+
+__attribute__ ((noclone, noinline, noipa))
+void deref_deref (void)
+{
+ strcpy (**p, "12345");
+ A (strlen (**p) == 5);
+}
+
+__attribute__ ((noclone, noinline, noipa))
+void deref_idx_0 (void)
+{
+ strcpy (*p[0], "");
+ A (strlen (*p[0]) == 0);
+}
+
+__attribute__ ((noclone, noinline, noipa))
+void deref_idx_1 (void)
+{
+ strcpy (*p[1], "1");
+ A (strlen (*p[1]) == 1);
+ A (strlen (&(*p[1])[1]) == 0);
+
+ A (strlen (*p[0]) == 0);
+}
+
+__attribute__ ((noclone, noinline, noipa))
+void deref_idx_2 (void)
+{
+ strcpy (*p[2], "12");
+ A (strlen (*p[2]) == 2);
+ A (strlen (&(*p[2])[1]) == 1);
+ A (strlen (&(*p[2])[2]) == 0);
+
+ A (strlen (*p[1]) == 1);
+ A (strlen (*p[0]) == 0);
+}
+
+__attribute__ ((noclone, noinline, noipa))
+void deref_idx_3 (void)
+{
+ strcpy (*p[3], "123");
+ A (strlen (*p[3]) == 3);
+ A (strlen (&(*p[3])[1]) == 2);
+ A (strlen (&(*p[3])[2]) == 1);
+ A (strlen (&(*p[3])[3]) == 0);
+
+ A (strlen (*p[2]) == 2);
+ A (strlen (*p[1]) == 1);
+ A (strlen (*p[0]) == 0);
+}
+
+__attribute__ ((noclone, noinline, noipa))
+void deref_idx_4 (void)
+{
+ strcpy (*p[4], "1234");
+ A (strlen (*p[4]) == 4);
+ A (strlen (&(*p[4])[1]) == 3);
+ A (strlen (&(*p[4])[2]) == 2);
+ A (strlen (&(*p[4])[3]) == 1);
+ A (strlen (&(*p[4])[4]) == 0);
+
+ A (strlen (*p[3]) == 3);
+ A (strlen (*p[2]) == 2);
+ A (strlen (*p[1]) == 1);
+ A (strlen (*p[0]) == 0);
+}
+
+__attribute__ ((noclone, noinline, noipa))
+void deref_idx_4_x (void)
+{
+ strcpy (*p[4], "");
+ A (strlen (*p[4]) == 0);
+ A (strlen (*p[3]) == 3);
+ A (strlen (*p[2]) == 2);
+ A (strlen (*p[1]) == 1);
+ A (strlen (*p[0]) == 0);
+}
+
+__attribute__ ((noclone, noinline, noipa))
+void deref_idx_3_x (void)
+{
+ strcpy (&(*p[3])[0], "1");
+ A (strlen (*p[4]) == 0);
+ A (strlen (*p[3]) == 1);
+ A (strlen (*p[2]) == 2);
+ A (strlen (*p[1]) == 1);
+ A (strlen (*p[0]) == 0);
+}
+
+__attribute__ ((noclone, noinline, noipa))
+void deref_idx_2_x (void)
+{
+ strcpy (*p[2], "12");
+ A (strlen (*p[4]) == 0);
+ A (strlen (*p[3]) == 1);
+ A (strlen (*p[2]) == 2);
+ A (strlen (*p[1]) == 1);
+ A (strlen (*p[0]) == 0);
+}
+
+__attribute__ ((noclone, noinline, noipa))
+void deref_idx_1_x (void)
+{
+ strcpy (*p[1], "123");
+ A (strlen (*p[4]) == 0);
+ A (strlen (*p[3]) == 1);
+ A (strlen (*p[2]) == 2);
+ A (strlen (*p[1]) == 3);
+ A (strlen (*p[0]) == 0);
+}
+
+__attribute__ ((noclone, noinline, noipa))
+void deref_idx_0_x (void)
+{
+ strcpy (*p[0], "1234");
+ A (strlen (*p[4]) == 0);
+ A (strlen (*p[3]) == 1);
+ A (strlen (*p[2]) == 2);
+ A (strlen (*p[1]) == 3);
+ A (strlen (*p[0]) == 4);
+}
+
+int main (void)
+{
+ deref_deref ();
+
+ deref_idx_0 ();
+ deref_idx_1 ();
+ deref_idx_2 ();
+ deref_idx_3 ();
+ deref_idx_4 ();
+
+ deref_idx_4_x ();
+ deref_idx_3_x ();
+ deref_idx_2_x ();
+ deref_idx_1_x ();
+ deref_idx_0_x ();
+}
diff --git a/gcc/testsuite/gcc.dg/strlenopt-64.c b/gcc/testsuite/gcc.dg/strlenopt-64.c
new file mode 100644
index 0000000..5451457
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/strlenopt-64.c
@@ -0,0 +1,182 @@
+/* PR tree-optimization/90662 - strlen of a string in a vla plus offset
+ not folded
+ Verify that strlen of pointers to wide character arrays (emulated
+ by int16_t) are computed correctly (whether folded or not).
+ { dg-do run }
+ { dg-options "-O2 -Wall -Wno-incompatible-pointer-types" } */
+
+#include "strlenopt.h"
+
+typedef __INT16_TYPE__ int16_t;
+
+#define A(expr) \
+ ((expr) \
+ ? (void)0 \
+ : (__builtin_printf ("assertion failed on line %i: %s\n", \
+ __LINE__, #expr), \
+ __builtin_abort ()))
+
+typedef int16_t A5[5];
+
+A5 a5[5];
+A5* p[5] = { &a5[4], &a5[3], &a5[2], &a5[1], &a5[0] };
+
+__attribute__ ((noclone, noinline, noipa))
+void deref_deref (void)
+{
+ strcpy (**p, "12345");
+ A (strlen (**p) == 5);
+}
+
+__attribute__ ((noclone, noinline, noipa))
+void deref_idx_0 (void)
+{
+ strcpy (*p[0], "");
+ A (strlen (*p[0]) == 0);
+}
+
+__attribute__ ((noclone, noinline, noipa))
+void deref_idx_1 (void)
+{
+ strcpy (*p[1], "12");
+ A (strlen (*p[1]) == 2);
+ A (strlen (&(*p[1])[1]) == 0);
+
+ A (strlen ((char*)*p[1] + 1) == 1);
+ A (strlen ((char*)*p[1] + 2) == 0);
+ A (strlen ((char*)*p[1] + 3) == 0);
+
+ A (strlen ((char*)&(*p[1])[1] + 1) == 0);
+
+ A (strlen (*p[0]) == 0);
+}
+
+__attribute__ ((noclone, noinline, noipa))
+void deref_idx_2 (void)
+{
+ strcpy (*p[2], "1234");
+ A (strlen (*p[2]) == 4);
+ A (strlen (&(*p[2])[1]) == 2);
+ A (strlen (&(*p[2])[2]) == 0);
+
+ A (strlen ((char*)*p[2] + 1) == 3);
+ A (strlen ((char*)*p[2] + 2) == 2);
+ A (strlen ((char*)*p[2] + 3) == 1);
+ A (strlen ((char*)*p[2] + 4) == 0);
+ A (strlen ((char*)*p[2] + 5) == 0);
+
+ A (strlen ((char*)&(*p[2])[1] + 1) == 1);
+ A (strlen ((char*)&(*p[2])[1] + 2) == 0);
+
+ A (strlen (*p[1]) == 2);
+ A (strlen (*p[0]) == 0);
+}
+
+__attribute__ ((noclone, noinline, noipa))
+void deref_idx_3 (void)
+{
+ strcpy (*p[3], "123456");
+ A (strlen (*p[3]) == 6);
+ A (strlen (&(*p[3])[1]) == 4);
+ A (strlen (&(*p[3])[2]) == 2);
+ A (strlen (&(*p[3])[3]) == 0);
+
+ A (strlen ((char*)*p[3] + 1) == 5);
+ A (strlen ((char*)*p[3] + 2) == 4);
+ A (strlen ((char*)*p[3] + 3) == 3);
+ A (strlen ((char*)*p[3] + 4) == 2);
+ A (strlen ((char*)*p[3] + 5) == 1);
+ A (strlen ((char*)*p[3] + 6) == 0);
+
+ A (strlen (*p[2]) == 4);
+ A (strlen (*p[1]) == 2);
+ A (strlen (*p[0]) == 0);
+}
+
+__attribute__ ((noclone, noinline, noipa))
+void deref_idx_4 (void)
+{
+ strcpy (*p[4], "12345678");
+ A (strlen (*p[4]) == 8);
+ A (strlen (&(*p[4])[1]) == 6);
+ A (strlen (&(*p[4])[2]) == 4);
+ A (strlen (&(*p[4])[3]) == 2);
+ A (strlen (&(*p[4])[4]) == 0);
+
+ A (strlen (*p[3]) == 6);
+ A (strlen (*p[2]) == 4);
+ A (strlen (*p[1]) == 2);
+ A (strlen (*p[0]) == 0);
+}
+
+__attribute__ ((noclone, noinline, noipa))
+void deref_idx_4_x (void)
+{
+ strcpy (*p[4], "");
+ A (strlen (*p[4]) == 0);
+ A (strlen (*p[3]) == 6);
+ A (strlen (*p[2]) == 4);
+ A (strlen (*p[1]) == 2);
+ A (strlen (*p[0]) == 0);
+}
+
+__attribute__ ((noclone, noinline, noipa))
+void deref_idx_3_x (void)
+{
+ strcpy (&(*p[3])[0], "1");
+ A (strlen (*p[4]) == 0);
+ A (strlen (*p[3]) == 1);
+ A (strlen (*p[2]) == 4);
+ A (strlen (*p[1]) == 2);
+ A (strlen (*p[0]) == 0);
+}
+
+__attribute__ ((noclone, noinline, noipa))
+void deref_idx_2_x (void)
+{
+ strcpy (*p[2], "12");
+ A (strlen (*p[4]) == 0);
+ A (strlen (*p[3]) == 1);
+ A (strlen (*p[2]) == 2);
+ A (strlen (*p[1]) == 2);
+ A (strlen (*p[0]) == 0);
+}
+
+__attribute__ ((noclone, noinline, noipa))
+void deref_idx_1_x (void)
+{
+ strcpy (*p[1], "123");
+ A (strlen (*p[4]) == 0);
+ A (strlen (*p[3]) == 1);
+ A (strlen (*p[2]) == 2);
+ A (strlen (*p[1]) == 3);
+ A (strlen (*p[0]) == 0);
+}
+
+__attribute__ ((noclone, noinline, noipa))
+void deref_idx_0_x (void)
+{
+ strcpy (*p[0], "1234");
+ A (strlen (*p[4]) == 0);
+ A (strlen (*p[3]) == 1);
+ A (strlen (*p[2]) == 2);
+ A (strlen (*p[1]) == 3);
+ A (strlen (*p[0]) == 4);
+}
+
+int main (void)
+{
+ deref_deref ();
+
+ deref_idx_0 ();
+ deref_idx_1 ();
+ deref_idx_2 ();
+ deref_idx_3 ();
+ deref_idx_4 ();
+
+ deref_idx_4_x ();
+ deref_idx_3_x ();
+ deref_idx_2_x ();
+ deref_idx_1_x ();
+ deref_idx_0_x ();
+}
diff --git a/gcc/testsuite/gcc.dg/strlenopt-65.c b/gcc/testsuite/gcc.dg/strlenopt-65.c
new file mode 100644
index 0000000..a34d178
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/strlenopt-65.c
@@ -0,0 +1,162 @@
+/* PRE tree-optimization/90626 - fold strcmp(a, b) == 0 to zero when
+ one string length is exact and the other is unequal
+ { dg-do compile }
+ { dg-options "-O2 -Wall -fdump-tree-optimized" } */
+
+#include "strlenopt.h"
+
+typedef __SIZE_TYPE__ size_t;
+
+extern void abort (void);
+extern void* memcpy (void *, const void *, size_t);
+extern int strcmp (const char *, const char *);
+extern int strncmp (const char *, const char *, size_t);
+
+#define CAT(x, y) x ## y
+#define CONCAT(x, y) CAT (x, y)
+#define FAILNAME(name) CONCAT (call_ ## name ##_on_line_, __LINE__)
+
+#define FAIL(name) do { \
+ extern void FAILNAME (name) (void); \
+ FAILNAME (name)(); \
+ } while (0)
+
+/* Macro to emit a call to function named
+ call_in_true_branch_not_eliminated_on_line_NNN()
+ for each call that's expected to be eliminated. The dg-final
+ scan-tree-dump-time directive at the bottom of the test verifies
+ that no such call appears in output. */
+#define ELIM_IF_TRUE(expr) \
+ if (!(expr)) FAIL (in_true_branch_not_eliminated); else (void)0
+
+/* Macro to emit a call to a function named
+ call_made_in_{true,false}_branch_on_line_NNN()
+ for each call that's expected to be retained. The dg-final
+ scan-tree-dump-time directive at the bottom of the test verifies
+ that the expected number of both kinds of calls appears in output
+ (a pair for each line with the invocation of the KEEP() macro. */
+#define TEST_KEEP(expr) \
+ if (expr) \
+ FAIL (made_in_true_branch); \
+ else \
+ FAIL (made_in_false_branch)
+
+#define FOLD(init1, init2, arg1, arg2, bnd) \
+ do { \
+ char a[8], b[8]; \
+ sink (a, b); \
+ memcpy (a, init1, sizeof init1 - 1); \
+ memcpy (b, init2, sizeof init2 - 1); \
+ ELIM_IF_TRUE (0 != CMPFUNC (arg1, arg2, bnd)); \
+ } while (0)
+
+#define KEEP(init1, init2, arg1, arg2, bnd) \
+ do { \
+ char a[8], b[8]; \
+ sink (a, b); \
+ memcpy (a, init1, sizeof init1 - 1); \
+ memcpy (b, init2, sizeof init2 - 1); \
+ TEST_KEEP (0 == CMPFUNC (arg1, arg2, bnd)); \
+ } while (0)
+
+const char s0[1] = "";
+const char s00[2] = "\0";
+const char s10[2] = "1";
+const char s20[2] = "2";
+
+void sink (void*, ...);
+
+void test_strcmp_elim (void)
+{
+#undef CMPFUNC
+#define CMPFUNC(a, b, dummy) strcmp (a, b)
+
+ FOLD (s00, s10, "\0", "1", -1);
+ FOLD (s00, s10, "\0", b, -1);
+ FOLD (s00, s10, "\0", s10, -1);
+
+ FOLD (s00, s10, s0, "1", -1);
+ FOLD (s00, s10, s0, b, -1);
+ FOLD (s00, s10, s0, s10, -1);
+
+ FOLD ("\0", "1", s0, "1", -1);
+ FOLD ("\0", "1", s0, b, -1);
+ FOLD ("\0", "1", s0, s10, -1);
+
+ FOLD ("2", "\0", "2", "\0", -1);
+ FOLD ("2", "\0", s20, s0, -1);
+
+ FOLD ("\0", "1", a, b, -1);
+ FOLD ("2", "\0", a, b, -1);
+
+ FOLD ("4\0", "44", a, b, -1);
+ FOLD ("55", "5\0", a, b, -1);
+
+ FOLD ("666\0", "6666", a, "6666", -1);
+ FOLD ("666\0", "6666", a, b, -1);
+ FOLD ("7777", "777\0", a, b, -1);
+
+ /* Avoid testing substrings of equal length with different characters.
+ The optimization doesn't have access to the contents of the strings
+ so it can't determine whether they are equal.
+
+ FOLD ("111\0", "112", a, b, -1);
+ FOLD ("112", "111\0", a, b, -1); */
+}
+
+const char s123[] = "123";
+const char s1230[] = "123\0";
+
+const char s1234[] = "1234";
+const char s12340[] = "1234\0";
+
+void test_strncmp_elim (void)
+{
+#undef CMPFUNC
+#define CMPFUNC(a, b, n) strncmp (a, b, n)
+
+ FOLD (s1230, s1234, "123", "1234", 4);
+ FOLD (s1234, s1230, "1234", "123", 4);
+
+ FOLD (s1230, s1234, "123", s1234, 4);
+ FOLD (s1234, s1230, "1234", s123, 4);
+
+ FOLD (s1230, s1234, s123, "1234", 4);
+ FOLD (s1234, s1230, s1234, "123", 4);
+
+ FOLD (s1230, s1234, s123, b, 4);
+ FOLD (s1234, s1230, s1234, b, 4);
+
+ FOLD (s1230, s1234, a, b, 4);
+ FOLD (s1234, s1230, a, b, 4);
+
+ FOLD ("123\0", "1234", a, b, 5);
+ FOLD ("1234", "123\0", a, b, 5);
+}
+
+
+#line 1000
+
+void test_strcmp_keep (const char *s, const char *t)
+{
+#undef CMPFUNC
+#define CMPFUNC(a, b, dummy) strcmp (a, b)
+
+ KEEP ("1", "1", a, b, -1);
+
+ KEEP ("1\0", "1", a, b, -1);
+ KEEP ("1", "1\0", a, b, -1);
+
+ KEEP ("12\0", "12", a, b, -1);
+ KEEP ("12", "12\0", a, b, -1);
+
+ KEEP ("111\0", "111", a, b, -1);
+ KEEP ("112", "112\0", a, b, -1);
+
+ KEEP (s, t, a, b, -1);
+}
+
+/* { dg-final { scan-tree-dump-times "call_in_true_branch_not_eliminated_" 0 "optimized" } }
+
+ { dg-final { scan-tree-dump-times "call_made_in_true_branch_on_line_1\[0-9\]\[0-9\]\[0-9\]" 8 "optimized" } }
+ { dg-final { scan-tree-dump-times "call_made_in_false_branch_on_line_1\[0-9\]\[0-9\]\[0-9\]" 8 "optimized" } } */
diff --git a/gcc/testsuite/gcc.dg/strlenopt-66.c b/gcc/testsuite/gcc.dg/strlenopt-66.c
new file mode 100644
index 0000000..5dc10a0
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/strlenopt-66.c
@@ -0,0 +1,72 @@
+/* PRE tree-optimization/90626 - fold strcmp(a, b) == 0 to zero when
+ one string length is exact and the other is unequal
+ { dg-do compile }
+ { dg-options "-O2 -Wall -fdump-tree-optimized" } */
+
+#include "strlenopt.h"
+
+#define A(expr) \
+ ((expr) \
+ ? (void)0 \
+ : (__builtin_printf ("assertion failed on line %i: %s\n", \
+ __LINE__, #expr), \
+ __builtin_abort ()))
+
+
+__attribute__ ((noclone, noinline, noipa)) void
+clobber (void *p, int x, size_t n)
+{
+ for (volatile unsigned char *q = p; n--; )
+ *q = x;
+}
+
+__attribute__ ((noclone, noinline, noipa)) void
+test_strcmp (void)
+{
+ char a[8], b[8];
+ strcpy (a, "1235");
+ strcpy (b, "1234");
+
+ A (strcmp (a, b));
+
+ clobber (a, 0, sizeof a);
+ clobber (b, 0, sizeof b);
+ clobber (b + 4, '5', 1);
+
+ memcpy (a, "1234", 4);
+ memcpy (b, "1234", 4);
+
+ A (0 > strcmp (a, b));
+ A (0 < strcmp (b, a));
+}
+
+__attribute__ ((noclone, noinline, noipa)) void
+test_strncmp (void)
+{
+ char a[8], b[8];
+ strcpy (a, "1235");
+ strcpy (b, "1234");
+
+ A (0 == strncmp (a, b, 1));
+ A (0 == strncmp (a, b, 2));
+ A (0 == strncmp (a, b, 3));
+ A (0 < strncmp (a, b, 4));
+ A (0 > strncmp (b, a, 4));
+
+ clobber (a, 0, sizeof a);
+ clobber (b, 0, sizeof b);
+ clobber (b + 4, '5', 1);
+
+ memcpy (a, "1234", 4);
+ memcpy (b, "1234", 4);
+
+ A (0 == strncmp (a, b, 4));
+ A (0 > strncmp (a, b, 5));
+ A (0 < strncmp (b, a, 5));
+}
+
+int main (void)
+{
+ test_strcmp ();
+ test_strncmp ();
+}
diff --git a/gcc/testsuite/gcc.dg/strlenopt.h b/gcc/testsuite/gcc.dg/strlenopt.h
index a4044fd..d25e08a 100644
--- a/gcc/testsuite/gcc.dg/strlenopt.h
+++ b/gcc/testsuite/gcc.dg/strlenopt.h
@@ -15,6 +15,8 @@ void *memmove (void *, const void *, size_t);
char *strcpy (char *__restrict, const char *__restrict);
char *strcat (char *__restrict, const char *__restrict);
char *strchr (const char *, int);
+int strcmp (const char *, const char *);
+int strncmp (const char *, const char *, size_t);
void *memset (void *, int, size_t);
int memcmp (const void *, const void *, size_t);
int strcmp (const char *, const char *);
diff --git a/gcc/testsuite/gcc.dg/tm/pr52141.c b/gcc/testsuite/gcc.dg/tm/pr52141.c
index 0dabf76..dbaab30 100644
--- a/gcc/testsuite/gcc.dg/tm/pr52141.c
+++ b/gcc/testsuite/gcc.dg/tm/pr52141.c
@@ -4,7 +4,7 @@
__attribute__((always_inline))
static void asmfunc(void)
{
- __asm__ (""); /* { dg-error "asm not allowed in .transaction_safe" } */
+ __asm__ (""); /* { dg-error "'asm' not allowed in 'transaction_safe" } */
}
__attribute__((transaction_safe))
diff --git a/gcc/testsuite/gcc.dg/torture/20190604-1.c b/gcc/testsuite/gcc.dg/torture/20190604-1.c
new file mode 100644
index 0000000..884d3d5
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/20190604-1.c
@@ -0,0 +1,21 @@
+/* { dg-do run } */
+
+struct S { int *mem; };
+
+struct S * __attribute__((noinline,noipa))
+foo ()
+{
+ struct S *s = __builtin_malloc (sizeof (struct S));
+ s->mem = __builtin_malloc (sizeof (int));
+ s->mem[0] = 1;
+ return s;
+}
+
+int
+main()
+{
+ struct S *s = foo();
+ if (s->mem[0] != 1)
+ __builtin_abort ();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/torture/ftrapv-2.c b/gcc/testsuite/gcc.dg/torture/ftrapv-2.c
index 8065ee0..75e464f 100644
--- a/gcc/testsuite/gcc.dg/torture/ftrapv-2.c
+++ b/gcc/testsuite/gcc.dg/torture/ftrapv-2.c
@@ -3,7 +3,7 @@
/* { dg-skip-if "" { *-*-* } { "-flto" } { "" } } */
/* { dg-additional-options "-ftrapv" } */
/* { dg-require-effective-target trapping } */
-/* { dg-require-fork unused } */
+/* { dg-require-fork "" } */
#include <stdlib.h>
#include <unistd.h>
diff --git a/gcc/testsuite/gcc.dg/torture/pr51106-1.c b/gcc/testsuite/gcc.dg/torture/pr51106-1.c
index 8a1227d..5501b54 100644
--- a/gcc/testsuite/gcc.dg/torture/pr51106-1.c
+++ b/gcc/testsuite/gcc.dg/torture/pr51106-1.c
@@ -6,7 +6,7 @@ int
foo (int x)
{
asm goto ("" : : "i" (x) : : lab); /* { dg-error "impossible constraint" } */
- /* { dg-warning "probably doesn.t match constraints" "" { target *-*-* } .-1 } */
+ /* { dg-warning "probably does not match constraints" "" { target *-*-* } .-1 } */
return 1;
lab:
return 0;
diff --git a/gcc/testsuite/gcc.dg/torture/pr51106-2.c b/gcc/testsuite/gcc.dg/torture/pr51106-2.c
index aa76a71..2dbb832 100644
--- a/gcc/testsuite/gcc.dg/torture/pr51106-2.c
+++ b/gcc/testsuite/gcc.dg/torture/pr51106-2.c
@@ -7,7 +7,7 @@ int
bar (int x)
{
asm goto ("" : : "i" (x) : : lab); /* { dg-error "impossible constraint" } */
-/* { dg-warning "probably doesn.t match constraints" "" { target *-*-* } .-1 } */
+/* { dg-warning "probably does not match constraints" "" { target *-*-* } .-1 } */
__builtin_unreachable ();
lab:
return 0;
diff --git a/gcc/testsuite/gcc.dg/torture/pr71816.c b/gcc/testsuite/gcc.dg/torture/pr71816.c
index 179fad8..be37ad9 100644
--- a/gcc/testsuite/gcc.dg/torture/pr71816.c
+++ b/gcc/testsuite/gcc.dg/torture/pr71816.c
@@ -11,7 +11,7 @@ void *realloc();
int ext2fs_resize_mem(void *p1) {
int size = 0;
memcpy(&ext2fs_resize_mem_p, p1, sizeof(ext2fs_resize_mem_p));
- realloc(&ext2fs_resize_mem_p, size);
+ void *p = realloc(&ext2fs_resize_mem_p, size);
return 0;
}
struct ext2_icount_el *insert_icount_el() {
diff --git a/gcc/testsuite/gcc.dg/torture/pr87693.c b/gcc/testsuite/gcc.dg/torture/pr87693.c
index 802560d..b4ff594 100644
--- a/gcc/testsuite/gcc.dg/torture/pr87693.c
+++ b/gcc/testsuite/gcc.dg/torture/pr87693.c
@@ -1,4 +1,5 @@
/* { dg-do compile } */
+/* { dg-require-effective-target indirect_jumps } */
void f (void);
void g (void);
diff --git a/gcc/testsuite/gcc.dg/torture/pr89135.c b/gcc/testsuite/gcc.dg/torture/pr89135.c
index 8a93e89..278303f 100644
--- a/gcc/testsuite/gcc.dg/torture/pr89135.c
+++ b/gcc/testsuite/gcc.dg/torture/pr89135.c
@@ -1,4 +1,6 @@
/* { dg-do compile } */
+/* { dg-require-effective-target indirect_jumps } */
+/* { dg-require-effective-target label_values } */
typedef __INTPTR_TYPE__ intptr_t;
intptr_t a, b, c, d;
diff --git a/gcc/testsuite/gcc.dg/torture/pr89247.c b/gcc/testsuite/gcc.dg/torture/pr89247.c
index 558e89e..3b60f91 100644
--- a/gcc/testsuite/gcc.dg/torture/pr89247.c
+++ b/gcc/testsuite/gcc.dg/torture/pr89247.c
@@ -1,4 +1,5 @@
/* { dg-do compile } */
+/* { dg-require-effective-target label_values } */
int *a;
void b()
diff --git a/gcc/testsuite/gcc.dg/torture/pr90071.c b/gcc/testsuite/gcc.dg/torture/pr90071.c
index bfa7239..702c143 100644
--- a/gcc/testsuite/gcc.dg/torture/pr90071.c
+++ b/gcc/testsuite/gcc.dg/torture/pr90071.c
@@ -1,4 +1,6 @@
/* { dg-do compile } */
+/* { dg-require-effective-target indirect_jumps } */
+/* { dg-require-effective-target label_values } */
int a;
static int b;
diff --git a/gcc/testsuite/gcc.dg/torture/pr90402-1.c b/gcc/testsuite/gcc.dg/torture/pr90402-1.c
new file mode 100644
index 0000000..c4bd894
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr90402-1.c
@@ -0,0 +1,26 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-mavx" { target x86_64-*-* i?86-*-* } } */
+
+int kn, ha;
+
+int
+c7 (void)
+{
+}
+
+void
+ul (int w3)
+{
+ kn = c7 ();
+
+ while (w3 < 1)
+ {
+ ha += !!kn ? 1 : w3;
+
+ for (kn = 0; kn < 2; ++kn)
+ {
+ }
+
+ ++w3;
+ }
+}
diff --git a/gcc/testsuite/gcc.dg/torture/pr90553.c b/gcc/testsuite/gcc.dg/torture/pr90553.c
new file mode 100644
index 0000000..06c9cbf
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr90553.c
@@ -0,0 +1,128 @@
+/* { dg-do run } */
+
+__attribute__((__noipa__))
+void f1(int x, void (*p1 []) (int, int))
+{
+ int i;
+ for (i = 0; i < x; i++)
+ p1[i](42, 666);
+}
+
+int z1_called = 0;
+int w1_called = 0;
+
+__attribute__((__noipa__))
+void z1(int a, int b)
+{
+ if (w1_called || z1_called)
+ __builtin_abort();
+ z1_called++;
+}
+
+__attribute__((__noipa__))
+void w1(int a, int b)
+{
+ if (w1_called || !z1_called)
+ __builtin_abort();
+ w1_called++;
+}
+
+int z2_called = 0;
+int w2_called = 0;
+
+__attribute__((__noipa__))
+void z2(void)
+{
+ if (w2_called || z2_called)
+ __builtin_abort();
+ z2_called++;
+}
+
+__attribute__((__noipa__))
+void w2(void)
+{
+ if (w2_called || !z2_called)
+ __builtin_abort();
+ w2_called++;
+}
+
+void (*p2 []) () = { w2, z2 };
+
+__attribute__((__noipa__))
+void f2(int x)
+{
+ void (**q) (void) = p2 + x;
+ int i;
+ for (i = 0; i < x; i++)
+ (*(--q))();
+}
+
+__attribute__((__noipa__))
+void f3(int x, int (*p3 []) (int))
+{
+ int i;
+ int next = x;
+ for (i = 0; i < x; i++)
+ next = p3[i](next);
+}
+
+int z3_called = 0;
+int w3_called = 0;
+
+__attribute__((__noipa__))
+int z3(int a)
+{
+ if (w3_called || z3_called || a != 2)
+ __builtin_abort();
+ z3_called++;
+ return 42;
+}
+
+__attribute__((__noipa__))
+int w3(int a)
+{
+ if (w3_called || !z3_called || a != 42)
+ __builtin_abort();
+ w3_called++;
+ return 4096;
+}
+
+int (*p4 []) (int) = { z3, w3 };
+
+__attribute__((__noipa__))
+void f4(int x)
+{
+ int (**q) (int) = p4;
+ int (**r) (int) = p4 + x;
+
+ int next = x;
+ for (; q < r; q++)
+ next = (*q)(next);
+}
+
+int main(void)
+{
+ static int (*p3 []) (int) = { z3, w3 };
+
+ static void (*p1 []) (int, int) = { z1, w1 };
+
+ f1(2, p1);
+ if (z1_called != 1 || w1_called != 1)
+ __builtin_abort();
+
+ f2(2);
+ if (z2_called != 1 || w2_called != 1)
+ __builtin_abort();
+
+ f3(2, p3);
+ if (z3_called != 1 || w3_called != 1)
+ __builtin_abort();
+
+ z3_called = 0;
+ w3_called = 0;
+ f4(2);
+ if (z3_called != 1 || w3_called != 1)
+ __builtin_abort();
+
+ __builtin_exit(0);
+}
diff --git a/gcc/testsuite/gcc.dg/torture/pr90671.c b/gcc/testsuite/gcc.dg/torture/pr90671.c
new file mode 100644
index 0000000..5a99b9d
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr90671.c
@@ -0,0 +1,16 @@
+/* PR tree-optimization/90671 */
+/* { dg-do compile } */
+/* { dg-additional-options "-w -g" } */
+
+int a;
+
+int
+main ()
+{
+ int b, c;
+ for (c = 0; c < 2; c++)
+ while (a)
+ if (b)
+ break;
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/torture/pr90738.c b/gcc/testsuite/gcc.dg/torture/pr90738.c
new file mode 100644
index 0000000..b457dd5
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr90738.c
@@ -0,0 +1,20 @@
+/* { dg-do run } */
+
+int __attribute__((noipa,noinline))
+foo (int i)
+{
+ int a[2];
+ a[1] = 1;
+ int j = a[1];
+ int *p = &a[0];
+ p[i] = 0;
+ return a[j];
+}
+
+int
+main()
+{
+ if (foo (1) != 0)
+ __builtin_abort ();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/torture/pr90972.c b/gcc/testsuite/gcc.dg/torture/pr90972.c
new file mode 100644
index 0000000..24f99b0
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr90972.c
@@ -0,0 +1,24 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-mcpu=power8" { target powerpc*-*-* } } */
+
+long f;
+void a();
+void *g()
+{
+ char h[] = {}, j[] = {}, k[] = {}, l[] = {}, m[] = {}, n[] = {}, o[] = {},
+ q[] = {}, r[] = {};
+ static const char i[] = {6, 0};
+ const char *nops[] = {h, i, j, k, l, m, n, o, q, r};
+ long s = 2;
+ void *fill = a;
+ char *p = fill;
+ while (f) {
+ void *b = p;
+ const void *c = nops[1];
+ long d = s, e = __builtin_object_size(b, 0);
+ __builtin___memcpy_chk(b, c, d, e);
+ p += s;
+ f -= s;
+ }
+ return fill;
+}
diff --git a/gcc/testsuite/gcc.dg/torture/pta-ptrarith-3.c b/gcc/testsuite/gcc.dg/torture/pta-ptrarith-3.c
index b952f11..7082937 100644
--- a/gcc/testsuite/gcc.dg/torture/pta-ptrarith-3.c
+++ b/gcc/testsuite/gcc.dg/torture/pta-ptrarith-3.c
@@ -33,4 +33,4 @@ int main()
return 0;
}
-/* { dg-final { scan-tree-dump "q_. = { i j k }" "alias" } } */
+/* { dg-final { scan-tree-dump "q_\[0-9\]* = { i j k }" "alias" } } */
diff --git a/gcc/testsuite/gcc.dg/torture/stackalign/builtin-apply-2.c b/gcc/testsuite/gcc.dg/torture/stackalign/builtin-apply-2.c
index 1c6fe4f..31585a0 100644
--- a/gcc/testsuite/gcc.dg/torture/stackalign/builtin-apply-2.c
+++ b/gcc/testsuite/gcc.dg/torture/stackalign/builtin-apply-2.c
@@ -9,7 +9,7 @@
/* arm_hf_eabi: Variadic funcs use Base AAPCS. Normal funcs use VFP variant.
avr: Variadic funcs don't pass arguments in registers, while normal funcs
do. */
-/* { dg-skip-if "Variadic funcs use different argument passing from normal funcs" { arm_hf_eabi || { avr-*-* riscv*-*-* or1k*-*-* msp430-*-* amdgcn-*-* } } } */
+/* { dg-skip-if "Variadic funcs use different argument passing from normal funcs" { arm_hf_eabi || { avr-*-* riscv*-*-* or1k*-*-* msp430-*-* amdgcn-*-* pru-*-* } } } */
/* { dg-skip-if "Variadic funcs have all args on stack. Normal funcs have args in registers." { nds32*-*-* } { v850*-*-* } } */
/* { dg-require-effective-target untyped_assembly } */
diff --git a/gcc/testsuite/gcc.dg/tree-prof/stringop-2.c b/gcc/testsuite/gcc.dg/tree-prof/stringop-2.c
index 3242cf5..c1f7573 100644
--- a/gcc/testsuite/gcc.dg/tree-prof/stringop-2.c
+++ b/gcc/testsuite/gcc.dg/tree-prof/stringop-2.c
@@ -21,5 +21,6 @@ main()
}
/* autofdo doesn't support value profiling for now: */
/* { dg-final-use-not-autofdo { scan-ipa-dump "Transformation done: single value 4 stringop" "profile"} } */
-/* The versioned memset of size 4 should be optimized to an assignment. */
-/* { dg-final-use-not-autofdo { scan-tree-dump "MEM\\\[\\(void .\\)&a\\\] = 168430090" "optimized"} } */
+/* The versioned memset of size 4 should be optimized to an assignment.
+ { dg-final-use-not-autofdo { scan-tree-dump "MEM\\\[\\(void .\\)&a\\\] = 168430090" "optimized" { target { ! store_merge } } } }
+ { dg-final-use-not-autofdo { scan-tree-dump "MEM <\[a-z \]+> \\\[\\(void .\\)&a\\\] = 168430090" "optimized" { target { store_merge } } } } */
diff --git a/gcc/testsuite/gcc.dg/tree-prof/val-prof-2.c b/gcc/testsuite/gcc.dg/tree-prof/val-prof-2.c
index 8cb3c64..b3bbadf 100644
--- a/gcc/testsuite/gcc.dg/tree-prof/val-prof-2.c
+++ b/gcc/testsuite/gcc.dg/tree-prof/val-prof-2.c
@@ -25,8 +25,5 @@ main ()
return 0;
}
/* autofdo does not do value profiling so far */
-/* { dg-final-use-not-autofdo { scan-ipa-dump "Transformation done: mod power of 2" "profile" } } */
-/* This is part of code checking that n is power of 2, so we are sure that the transformation
- didn't get optimized out. */
-/* { dg-final-use-not-autofdo { scan-tree-dump "n_\[0-9\]* \\+ (4294967295|0x0*ffffffff)" "optimized"} } */
+/* { dg-final-use-not-autofdo { scan-ipa-dump "Transformation done: div/mod by constant 256" "profile" } } */
/* { dg-final-use { scan-tree-dump-not "Invalid sum" "optimized"} } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/20040204-1.c b/gcc/testsuite/gcc.dg/tree-ssa/20040204-1.c
index 255b627..2f3dcb5 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/20040204-1.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/20040204-1.c
@@ -33,4 +33,4 @@ void test55 (int x, int y)
that the && should be emitted (based on BRANCH_COST). Fix this
by teaching dom to look through && and register all components
as true. */
-/* { dg-final { scan-tree-dump-times "link_error" 0 "optimized" { xfail { ! "alpha*-*-* arm*-*-* aarch64*-*-* powerpc*-*-* cris-*-* crisv32-*-* hppa*-*-* i?86-*-* mmix-*-* mips*-*-* m68k*-*-* moxie-*-* nds32*-*-* s390*-*-* sh*-*-* sparc*-*-* spu-*-* visium-*-* x86_64-*-* riscv*-*-* or1k*-*-* msp430-*-*" } } } } */
+/* { dg-final { scan-tree-dump-times "link_error" 0 "optimized" { xfail { ! "alpha*-*-* arm*-*-* aarch64*-*-* powerpc*-*-* cris-*-* crisv32-*-* hppa*-*-* i?86-*-* mmix-*-* mips*-*-* m68k*-*-* moxie-*-* nds32*-*-* s390*-*-* sh*-*-* sparc*-*-* spu-*-* visium-*-* x86_64-*-* riscv*-*-* or1k*-*-* msp430-*-* pru*-*-*" } } } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/20040211-1.c b/gcc/testsuite/gcc.dg/tree-ssa/20040211-1.c
index d289e5d..a9bdf26 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/20040211-1.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/20040211-1.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -fdump-tree-cddce2" } */
+/* { dg-options "-O2 -fdump-tree-cddce2 -fno-finite-loops" } */
struct rtx_def;
typedef struct rtx_def *rtx;
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/alias-37.c b/gcc/testsuite/gcc.dg/tree-ssa/alias-37.c
new file mode 100644
index 0000000..2fb0e0c
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/alias-37.c
@@ -0,0 +1,18 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target alloca } */
+/* { dg-options "-O2 -fdump-tree-dse1-details" } */
+
+int i;
+int *foo (int bogus, int n)
+{
+ int a[n];
+ a[2] = bogus; /* Should elide this store since a cannot escape. */
+ int *p;
+ if (bogus)
+ p = &a[2];
+ else
+ p = &i;
+ return p;
+}
+
+/* { dg-final { scan-tree-dump "Deleted dead store" "dse1" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/alias-access-path-1.c b/gcc/testsuite/gcc.dg/tree-ssa/alias-access-path-1.c
new file mode 100644
index 0000000..ba90b56
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/alias-access-path-1.c
@@ -0,0 +1,21 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-fre3" } */
+struct foo
+{
+ int val;
+} *fooptr;
+struct bar
+{
+ struct foo foo;
+ int val2;
+} *barptr;
+int
+test ()
+{
+ struct foo foo = { 0 };
+ barptr->val2 = 123;
+ *fooptr = foo;
+ return barptr->val2;
+}
+
+/* { dg-final { scan-tree-dump-times "return 123" 1 "fre3"} } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/alias-access-path-2.c b/gcc/testsuite/gcc.dg/tree-ssa/alias-access-path-2.c
new file mode 100644
index 0000000..974cdb0
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/alias-access-path-2.c
@@ -0,0 +1,22 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-fre3" } */
+struct a {
+ int val;
+};
+struct b {
+ struct a a[10],a2[10];
+};
+struct c {
+ struct b b[10];
+} *cptr;
+
+struct d {struct c c;} *dptr;
+
+int
+test (int i, int j, int k, int l)
+{
+ cptr->b[i].a[j].val=123;
+ dptr->c.b[k].a2[l].val=2;
+ return cptr->b[i].a[j].val;
+}
+/* { dg-final { scan-tree-dump-times "return 123" 1 "fre3"} } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/alias-access-path-4.c b/gcc/testsuite/gcc.dg/tree-ssa/alias-access-path-4.c
new file mode 100644
index 0000000..641ef89
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/alias-access-path-4.c
@@ -0,0 +1,24 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+
+struct a {int v1;
+ int v2;};
+struct b {struct a a[0];};
+union c {struct b b;};
+
+int
+test (struct b *bptr1, union c *cptr, int i, int j)
+{
+ bptr1->a[i].v1=123;
+ cptr->b.a[j].v2=1;
+ return bptr1->a[i].v1;
+}
+int
+test2 (struct b *bptr1, union c *cptr, int i, int j)
+{
+ bptr1->a[i].v1=124;
+ cptr->b.a[j].v1=1;
+ return bptr1->a[i].v1;
+}
+/* { dg-final { scan-tree-dump-times "return 123" 1 "optimized"} } */
+/* { dg-final { scan-tree-dump-not "return 124" "optimized"} } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/alias-access-path-5.c b/gcc/testsuite/gcc.dg/tree-ssa/alias-access-path-5.c
new file mode 100644
index 0000000..412f99e
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/alias-access-path-5.c
@@ -0,0 +1,25 @@
+
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+
+struct a {int v1;
+ int v2;};
+struct b {int array[0]; struct a a[];};
+union c {struct b b;};
+
+int
+test (struct b *bptr1, union c *cptr, int i, int j)
+{
+ bptr1->a[i].v1=123;
+ cptr->b.a[j].v2=1;
+ return bptr1->a[i].v1;
+}
+int
+test2 (struct b *bptr1, union c *cptr, int i, int j)
+{
+ bptr1->a[i].v1=124;
+ cptr->b.a[j].v1=1;
+ return bptr1->a[i].v1;
+}
+/* { dg-final { scan-tree-dump-times "return 123" 1 "optimized"} } */
+/* { dg-final { scan-tree-dump-not "return 124" "optimized"} } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/alias-access-path-6.c b/gcc/testsuite/gcc.dg/tree-ssa/alias-access-path-6.c
new file mode 100644
index 0000000..c0de453
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/alias-access-path-6.c
@@ -0,0 +1,29 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+
+/* This tests that nonoveralpping_component_refs does not give up
+ on field delcs and continues looking to find mismatch between
+ a1 and a2. */
+struct a {
+ int a:3;
+ int b:3;
+};
+struct b {struct a a1,a2;};
+struct c {struct b b[10];} *cptr;
+struct d {struct c c;} *dptr;
+int
+test(int i,int j)
+{
+ cptr->b[i].a1.a=0;
+ dptr->c.b[j].a2.b=1;
+ return cptr->b[i].a1.a;
+}
+int
+test2(int i,int j)
+{
+ cptr->b[i].a1.a=1;
+ dptr->c.b[j].a1.a=0;
+ return cptr->b[i].a1.a;
+}
+/* { dg-final { scan-tree-dump-times "return 0" 1 "optimized"} } */
+/* { dg-final { scan-tree-dump-not "return 1" "optimized"} } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/alias-access-path-7.c b/gcc/testsuite/gcc.dg/tree-ssa/alias-access-path-7.c
new file mode 100644
index 0000000..05cf037
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/alias-access-path-7.c
@@ -0,0 +1,20 @@
+/* { dg-do compile } */
+/* { dg-options "-O1 -fno-strict-aliasing -fdump-tree-optimized" } */
+
+struct S
+{
+ int i;
+ int j;
+};
+struct U
+{
+ struct S a[10];
+};
+int
+foo (struct U *u, int n, int i, int j)
+{
+ u->a[i].i = 123;
+ u->a[j].j = j;
+ return u->a[i].i;
+}
+/* { dg-final { scan-tree-dump-times "return 123" 1 "optimized"} } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/cmpexactdiv-3.c b/gcc/testsuite/gcc.dg/tree-ssa/cmpexactdiv-3.c
new file mode 100644
index 0000000..57e280b
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/cmpexactdiv-3.c
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { dg-options "-O -fdump-tree-optimized-raw" } */
+
+int f(int*a,int*b){
+ if(sizeof(__SIZE_TYPE__)!=sizeof(__PTRDIFF_TYPE__)) return -1;
+ __SIZE_TYPE__ d = b - a;
+ return d >= 5;
+}
+
+/* { dg-final { scan-tree-dump-not "exact_div_expr" "optimized" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/cmpexactdiv-4.c b/gcc/testsuite/gcc.dg/tree-ssa/cmpexactdiv-4.c
new file mode 100644
index 0000000..1370309
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/cmpexactdiv-4.c
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { dg-options "-O -fdump-tree-optimized-raw" } */
+
+int f(int*a,int*b,int*c){
+ __PTRDIFF_TYPE__ x = -(b - a);
+ __PTRDIFF_TYPE__ y = -(c - a);
+ return x < y;
+}
+
+/* { dg-final { scan-tree-dump-not "exact_div_expr" "optimized" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/cmpexactdiv-5.c b/gcc/testsuite/gcc.dg/tree-ssa/cmpexactdiv-5.c
new file mode 100644
index 0000000..41ffce1
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/cmpexactdiv-5.c
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-options "-O -fdump-tree-optimized-raw" } */
+
+int f(int *a, int *b, int *c){
+ if(sizeof(__SIZE_TYPE__) != sizeof(__PTRDIFF_TYPE__)) return 2;
+ __SIZE_TYPE__ s = b - a;
+ __SIZE_TYPE__ t = c - a;
+ return s < t;
+}
+
+/* { dg-final { scan-tree-dump-not "exact_div_expr" "optimized" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/dce-2.c b/gcc/testsuite/gcc.dg/tree-ssa/dce-2.c
new file mode 100644
index 0000000..18c1ddb
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/dce-2.c
@@ -0,0 +1,37 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-cddce1 -ffinite-loops" } */
+
+typedef struct list {
+ char pad[15];
+ struct list *next;
+} list;
+
+int data;
+
+list *head, *tail;
+
+int __attribute__((pure)) pfn (int);
+
+int foo (unsigned u, int s)
+{
+ unsigned i;
+ list *p;
+ int j;
+
+ for (i = 0; i < u; i += 2)
+ ;
+
+ for (p = head; p; p = p->next)
+ ;
+
+ for (j = data; j & s; j = pfn (j + 3))
+ ;
+
+ for (p = head; p != tail; p = p->next)
+ for (j = data + 1; j > s; j = pfn (j + 2))
+ ;
+
+ return 0;
+}
+/* { dg-final { scan-tree-dump-not "if" "cddce1"} } */
+
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/dump-5.c b/gcc/testsuite/gcc.dg/tree-ssa/dump-5.c
new file mode 100644
index 0000000..6807b5e
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/dump-5.c
@@ -0,0 +1,15 @@
+/* PR middle-end/90694 - incorrect representation of ADDR_EXPR involving
+ a pointer to array
+ { dg-do compile }
+ { dg-options "-fdump-tree-original" } */
+
+typedef char A8[8];
+
+unsigned f (A8 *pa)
+{
+ return __builtin_strlen (&(*pa)[2]);
+}
+
+/* Veriy the expression is correct in the dump:
+ { dg-final { scan-tree-dump-not "\\\&\\\*pa\\\[2\\\]" "original" } }
+ { dg-final { scan-tree-dump "\\\&\\\(\\\*pa\\\)\\\[2\\\]" "original" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/dump-6.c b/gcc/testsuite/gcc.dg/tree-ssa/dump-6.c
new file mode 100644
index 0000000..70659c00
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/dump-6.c
@@ -0,0 +1,38 @@
+/* PR middle-end/90676 - default GIMPLE dumps lack information
+ { dg-do compile }
+ { dg-options "-O2 -fdump-tree-store-merging" }
+ { dg-require-effective-target int32plus }
+ { dg-require-effective-target store_merge } */
+
+
+extern __attribute__((aligned(2))) char a2[2];
+
+void f2 (void)
+{
+ a2[0] = 1;
+ a2[1] = 0;
+}
+
+extern __attribute__((aligned(4))) char a4[4];
+
+void f4 (void)
+{
+ a4[0] = 1;
+ a4[1] = 0;
+ a4[2] = 0;
+ a4[3] = 0;
+}
+
+extern __attribute__((aligned(8))) char a8[8];
+
+void f8 (void)
+{
+ a8[0] = 1;
+ for (int i = 1; i != 8; ++i)
+ a8[i] = 0;
+}
+
+/* { dg-final { scan-tree-dump "MEM <unsigned short> \\\[\\(char \\*\\)\\&a2] = " "store-merging" } }
+ { dg-final { scan-tree-dump "MEM <unsigned int> \\\[\\(char \\*\\)\\&a4] = " "store-merging" } }
+ { dg-final { scan-tree-dump "MEM <unsigned int> \\\[\\(char \\*\\)\\&a8] = " "store-merging" { target { ilp32 } } } }
+ { dg-final { scan-tree-dump "MEM <unsigned long> \\\[\\(char \\*\\)\\&a8] = " "store-merging" { target { lp64 } } } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/gen-vect-2.c b/gcc/testsuite/gcc.dg/tree-ssa/gen-vect-2.c
index a269129..42171a2 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/gen-vect-2.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/gen-vect-2.c
@@ -1,6 +1,6 @@
/* { dg-do run { target vect_cmdline_needed } } */
-/* { dg-options "-O2 -ftree-vectorize -fdump-tree-vect-details -fvect-cost-model=dynamic" } */
-/* { dg-options "-O2 -ftree-vectorize -fdump-tree-vect-details -fvect-cost-model=dynamic -mno-sse" { target { i?86-*-* x86_64-*-* } } } */
+/* { dg-options "-O2 -fno-tree-loop-distribute-patterns -ftree-vectorize -fdump-tree-vect-details -fvect-cost-model=dynamic" } */
+/* { dg-additional-options "-mno-sse" { target { i?86-*-* x86_64-*-* } } } */
#include <stdlib.h>
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/gen-vect-26.c b/gcc/testsuite/gcc.dg/tree-ssa/gen-vect-26.c
index 8e5f141..2423168 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/gen-vect-26.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/gen-vect-26.c
@@ -1,6 +1,6 @@
/* { dg-do run { target vect_cmdline_needed } } */
-/* { dg-options "-O2 -ftree-vectorize -fdump-tree-vect-details -fvect-cost-model=dynamic" } */
-/* { dg-options "-O2 -ftree-vectorize -fdump-tree-vect-details -fvect-cost-model=dynamic -mno-sse" { target { i?86-*-* x86_64-*-* } } } */
+/* { dg-options "-O2 -fno-tree-loop-distribute-patterns -ftree-vectorize -fdump-tree-vect-details -fvect-cost-model=dynamic" } */
+/* { dg-additional-options "-mno-sse" { target { i?86-*-* x86_64-*-* } } } */
#include <stdlib.h>
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/gen-vect-28.c b/gcc/testsuite/gcc.dg/tree-ssa/gen-vect-28.c
index ce97e09..24853e0 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/gen-vect-28.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/gen-vect-28.c
@@ -1,6 +1,6 @@
/* { dg-do run { target vect_cmdline_needed } } */
-/* { dg-options "-O2 -ftree-vectorize -fdump-tree-vect-details -fvect-cost-model=dynamic" } */
-/* { dg-options "-O2 -ftree-vectorize -fdump-tree-vect-details -fvect-cost-model=dynamic -mno-sse" { target { i?86-*-* x86_64-*-* } } } */
+/* { dg-options "-O2 -fno-tree-loop-distribute-patterns -ftree-vectorize -fdump-tree-vect-details -fvect-cost-model=dynamic" } */
+/* { dg-additional-options "-mno-sse" { target { i?86-*-* x86_64-*-* } } } */
#include <stdlib.h>
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/gen-vect-32.c b/gcc/testsuite/gcc.dg/tree-ssa/gen-vect-32.c
index 8fce438..c4bee19 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/gen-vect-32.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/gen-vect-32.c
@@ -1,5 +1,5 @@
/* { dg-do run { target vect_cmdline_needed } } */
-/* { dg-options "-O2 -ftree-vectorize -fdump-tree-vect-details -fno-vect-cost-model" } */
+/* { dg-options "-O2 -fno-tree-loop-distribute-patterns -ftree-vectorize -fdump-tree-vect-details -fno-vect-cost-model" } */
/* { dg-additional-options "-mno-sse" { target { i?86-*-* x86_64-*-* } } } */
#include <stdlib.h>
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ivopts-lt-2.c b/gcc/testsuite/gcc.dg/tree-ssa/ivopts-lt-2.c
index 634f1dd..bdbdbff 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/ivopts-lt-2.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/ivopts-lt-2.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -fdump-tree-ivopts" } */
+/* { dg-options "-O2 -fno-tree-loop-distribute-patterns -fdump-tree-ivopts" } */
/* { dg-skip-if "PR68644" { hppa*-*-* powerpc*-*-* } } */
void
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ivopts-lt.c b/gcc/testsuite/gcc.dg/tree-ssa/ivopts-lt.c
index 171c85a..7d5859b 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/ivopts-lt.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/ivopts-lt.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -fdump-tree-ivopts" } */
+/* { dg-options "-O2 -fno-tree-loop-distribute-patterns -fdump-tree-ivopts" } */
/* { dg-require-effective-target stdint_types } */
#include "stdint.h"
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ldist-26.c b/gcc/testsuite/gcc.dg/tree-ssa/ldist-26.c
index 3a69884..98450cf 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/ldist-26.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/ldist-26.c
@@ -31,6 +31,8 @@ int main()
return 0;
}
-/* { dg-final { scan-tree-dump "distributed: split to 2 loops and 0 library calls" "ldist" } } */
-/* { dg-final { scan-tree-dump "distributed: split to 1 loops and 1 library calls" "ldist" } } */
-/* { dg-final { scan-tree-dump "generated memset zero" "ldist" } } */
+/* Loop splitting splits the iteration space so we end up with two
+ loops entering loop distribution. Both should have the b[i] = 0
+ part split out as memset. */
+/* { dg-final { scan-tree-dump-times "distributed: split to 1 loops and 1 library calls" 2 "ldist" } } */
+/* { dg-final { scan-tree-dump-times "generated memset zero" 2 "ldist" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ldist-37.c b/gcc/testsuite/gcc.dg/tree-ssa/ldist-37.c
new file mode 100644
index 0000000..9aae432
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/ldist-37.c
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { dg-options "-Os -fdump-tree-ldist-optimized" } */
+
+void foo(char* restrict dst, const char* buf)
+{
+ for (int i=0; i<8; ++i)
+ *dst++ = *buf++;
+}
+
+/* { dg-final { scan-tree-dump "split to 0 loops and 1 library calls" "ldist" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ldist-38.c b/gcc/testsuite/gcc.dg/tree-ssa/ldist-38.c
new file mode 100644
index 0000000..e296e82
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/ldist-38.c
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-ldist-optimized" } */
+
+void foo(char* restrict dst, const char* buf)
+{
+ for (int i=0; i<8; ++i)
+ *dst++ = *buf++;
+}
+
+/* { dg-final { scan-tree-dump "split to 0 loops and 1 library calls" "ldist" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/loop-10.c b/gcc/testsuite/gcc.dg/tree-ssa/loop-10.c
index a29c9fb..3d05ad2 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/loop-10.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/loop-10.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -fdump-tree-optimized" } */
+/* { dg-options "-O2 -fdump-tree-optimized -fno-finite-loops" } */
/* { dg-require-effective-target int32plus } */
int bar (void);
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/phi_on_compare-1.c b/gcc/testsuite/gcc.dg/tree-ssa/phi_on_compare-1.c
new file mode 100644
index 0000000..5227c87
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/phi_on_compare-1.c
@@ -0,0 +1,30 @@
+/* { dg-do compile } */
+/* { dg-options "-Ofast -fdump-tree-vrp1" } */
+
+void g (int);
+void g1 (int);
+
+void
+f (long a, long b, long c, long d, long x)
+{
+ _Bool t;
+ if (x)
+ {
+ g (a + 1);
+ t = a < b;
+ c = d + x;
+ }
+ else
+ {
+ g (b + 1);
+ a = c + d;
+ t = c > d;
+ }
+
+ if (t)
+ g1 (c);
+
+ g (a);
+}
+
+/* { dg-final { scan-tree-dump-times "Removing basic block" 1 "vrp1" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/phi_on_compare-2.c b/gcc/testsuite/gcc.dg/tree-ssa/phi_on_compare-2.c
new file mode 100644
index 0000000..eaf89bb
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/phi_on_compare-2.c
@@ -0,0 +1,23 @@
+/* { dg-do compile } */
+/* { dg-options "-Ofast -fdump-tree-vrp1" } */
+
+void g (void);
+void g1 (void);
+
+void
+f (long a, long b, long c, long d, int x)
+{
+ _Bool t;
+ if (x)
+ t = c < d;
+ else
+ t = a < b;
+
+ if (t)
+ {
+ g1 ();
+ g ();
+ }
+}
+
+/* { dg-final { scan-tree-dump-times "Removing basic block" 1 "vrp1" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/phi_on_compare-3.c b/gcc/testsuite/gcc.dg/tree-ssa/phi_on_compare-3.c
new file mode 100644
index 0000000..d5a1e0b
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/phi_on_compare-3.c
@@ -0,0 +1,25 @@
+/* { dg-do compile } */
+/* { dg-options "-Ofast -fdump-tree-vrp1" } */
+
+void g (void);
+void g1 (void);
+
+void
+f (long a, long b, long c, long d, int x)
+{
+ int t;
+ if (x)
+ t = a < b;
+ else if (d == x)
+ t = c < b;
+ else
+ t = d > c;
+
+ if (t)
+ {
+ g1 ();
+ g ();
+ }
+}
+
+/* { dg-final { scan-tree-dump-times "Removing basic block" 1 "vrp1" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/phi_on_compare-4.c b/gcc/testsuite/gcc.dg/tree-ssa/phi_on_compare-4.c
new file mode 100644
index 0000000..53acabc
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/phi_on_compare-4.c
@@ -0,0 +1,40 @@
+/* { dg-do compile } */
+/* { dg-options "-Ofast -fdump-tree-vrp1" } */
+
+void g (int);
+void g1 (int);
+
+void
+f (long a, long b, long c, long d, int x)
+{
+ int t;
+ _Bool l1 = 0, l2 = 0;
+ if (x)
+ {
+ g (a);
+ c = a + b;
+ t = a < b;
+ l1 = 1;
+ }
+ else
+ {
+ g1 (b);
+ t = c > d;
+ d = c + b;
+ l2 = 1;
+ }
+
+ if (t)
+ {
+ if (l1 | l2)
+ g1 (c);
+ }
+ else
+ {
+ g (d);
+ g1 (a + b);
+ }
+ g (c + d);
+}
+
+/* { dg-final { scan-tree-dump-times "Removing basic block" 1 "vrp1" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr30375.c b/gcc/testsuite/gcc.dg/tree-ssa/pr30375.c
index 4494a2b..b3ac2c3 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/pr30375.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr30375.c
@@ -22,5 +22,4 @@ void test_signed_msg_encoding(void)
f();
}
-/* { dg-final { scan-tree-dump-times "MEM\\\[\\(struct _s \\*\\)&signInfo \\+ \[0-9\]+B\\\] = {}" 1 "dse1" } } */
-
+/* { dg-final { scan-tree-dump-times "MEM <char\\\[\[0-9\]+]> \\\[\\(struct _s \\*\\)&signInfo \\+ \[0-9\]+B\\\] = {}" 1 "dse1" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr66726-4.c b/gcc/testsuite/gcc.dg/tree-ssa/pr66726-4.c
new file mode 100644
index 0000000..4e43522
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr66726-4.c
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-phiopt1-details" } */
+
+#define SAT(x) (x < 0 ? 0 : (x > 255 ? 255 : x))
+
+void
+foo (unsigned char *p, int i)
+{
+ *p = SAT (i);
+}
+
+/* { dg-final { scan-tree-dump-times "COND_EXPR .*and PHI .*converted to straightline code" 1 "phiopt1" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr77445-2.c b/gcc/testsuite/gcc.dg/tree-ssa/pr77445-2.c
index c5d567d..9c22c53 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/pr77445-2.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr77445-2.c
@@ -125,7 +125,7 @@ enum STATES FMS( u8 **in , u32 *transitions) {
jump threading opportunities. Skip the later tests on aarch64. */
/* { dg-final { scan-tree-dump "Jumps threaded: 1\[1-9\]" "thread1" } } */
/* { dg-final { scan-tree-dump-times "Invalid sum" 3 "thread1" } } */
-/* { dg-final { scan-tree-dump-not "not considered" "thread1" } } */
-/* { dg-final { scan-tree-dump-not "not considered" "thread2" } } */
-/* { dg-final { scan-tree-dump-not "not considered" "thread3" { target { ! aarch64*-*-* } } } } */
-/* { dg-final { scan-tree-dump-not "not considered" "thread4" { target { ! aarch64*-*-* } } } } */
+/* { dg-final { scan-tree-dump-not "optimizing for size" "thread1" } } */
+/* { dg-final { scan-tree-dump-not "optimizing for size" "thread2" } } */
+/* { dg-final { scan-tree-dump-not "optimizing for size" "thread3" { target { ! aarch64*-*-* } } } } */
+/* { dg-final { scan-tree-dump-not "optimizing for size" "thread4" { target { ! aarch64*-*-* } } } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr78886.c b/gcc/testsuite/gcc.dg/tree-ssa/pr78886.c
index de22b83..7f62891 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/pr78886.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr78886.c
@@ -7,6 +7,6 @@ void *malloc(size_t x);
void foo(void)
{
volatile int i;
- malloc(1);
+ void *p = malloc(1);
i;
}
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr79697.c b/gcc/testsuite/gcc.dg/tree-ssa/pr79697.c
index 973ec0d..e62efd5 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/pr79697.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr79697.c
@@ -3,17 +3,17 @@
void f(void)
{
- __builtin_strdup ("abc");
+ __builtin_strdup ("abc"); /* { dg-warning "ignoring return value of '__builtin_strdup' declared with attribute 'warn_unused_result'" } */
}
void g(void)
{
- __builtin_strndup ("abc", 3);
+ __builtin_strndup ("abc", 3); /* { dg-warning "ignoring return value of '__builtin_strndup' declared with attribute 'warn_unused_result'" } */
}
void h(void)
{
- __builtin_realloc (0, 10);
+ __builtin_realloc (0, 10); /* { dg-warning "ignoring return value of '__builtin_realloc' declared with attribute 'warn_unused_result'" } */
}
/* { dg-final { scan-tree-dump "Deleting : __builtin_strdup" "cddce1" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr90340-2.c b/gcc/testsuite/gcc.dg/tree-ssa/pr90340-2.c
new file mode 100644
index 0000000..a3cb0cd
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr90340-2.c
@@ -0,0 +1,31 @@
+/* { dg-do compile { target { { x86_64-*-* aarch64-*-* ia64-*-* powerpc64-*-* } && lp64 } } } */
+/* { dg-options "-Os --param jump-table-max-growth-ratio-for-size=200 --param case-values-threshold=5 -fdump-tree-switchlower1" } */
+
+int a;
+
+int foo(char c) {
+ switch (c) {
+ case 'c':
+ return a;
+ case 's':
+ return 3;
+ case 'n':
+ return 1;
+ case '%':
+ return -2;
+ case 'o':
+ return a + 2;
+ break;
+ case 'X':
+ case 'x':
+ return 2222;
+ case 'd':
+ case 'i':
+ case 'u':
+ return 3333;
+ default:
+ return 0;
+ }
+}
+
+/* { dg-final { scan-tree-dump ";; GIMPLE switch case clusters: 37 88 99 100 105 110 111 115 117 120" "switchlower1" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr90340.c b/gcc/testsuite/gcc.dg/tree-ssa/pr90340.c
new file mode 100644
index 0000000..8f3b87c
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr90340.c
@@ -0,0 +1,31 @@
+/* { dg-do compile { target { { x86_64-*-* aarch64-*-* ia64-*-* powerpc64-*-* } && lp64 } } } */
+/* { dg-options "-Os -fdump-tree-switchlower1" } */
+
+int a;
+
+int foo(char c) {
+ switch (c) {
+ case 'c':
+ return a;
+ case 's':
+ return 3;
+ case 'n':
+ return 1;
+ case '%':
+ return -2;
+ case 'o':
+ return a + 2;
+ break;
+ case 'X':
+ case 'x':
+ return 2222;
+ case 'd':
+ case 'i':
+ case 'u':
+ return 3333;
+ default:
+ return 0;
+ }
+}
+
+/* { dg-final { scan-tree-dump ";; GIMPLE switch case clusters: 37 88 JT:99-120" "switchlower1" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr90478.c b/gcc/testsuite/gcc.dg/tree-ssa/pr90478.c
new file mode 100644
index 0000000..e424bb1
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr90478.c
@@ -0,0 +1,19 @@
+/* { dg-do compile } */
+/* { dg-options "" } */
+
+typedef struct {
+ long long a;
+} c;
+
+void e();
+
+void d() {
+ c *b;
+ switch (b->a)
+ case 8:
+ case 2:
+ case 2057594037927936:
+ case 0:
+ case 4611686018427387904:
+ e();
+}
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/predcom-dse-1.c b/gcc/testsuite/gcc.dg/tree-ssa/predcom-dse-1.c
index d3a2339..b61b651 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/predcom-dse-1.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/predcom-dse-1.c
@@ -1,5 +1,5 @@
/* { dg-do run } */
-/* { dg-options "-O2 -fno-inline -fpredictive-commoning -fdump-tree-pcom-details" } */
+/* { dg-options "-O2 -fno-inline -fno-tree-loop-distribute-patterns -fpredictive-commoning -fdump-tree-pcom-details" } */
int arr[105] = {2, 3, 5, 7, 11};
int result0[10] = {2, 3, 5, 7, 11};
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/predcom-dse-2.c b/gcc/testsuite/gcc.dg/tree-ssa/predcom-dse-2.c
index c48d438..7f959a8 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/predcom-dse-2.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/predcom-dse-2.c
@@ -1,5 +1,5 @@
/* { dg-do run } */
-/* { dg-options "-O2 -fno-inline -fpredictive-commoning -fdump-tree-pcom-details" } */
+/* { dg-options "-O2 -fno-inline -fno-tree-loop-distribute-patterns -fpredictive-commoning -fdump-tree-pcom-details" } */
int arr[105] = {2, 3, 5, 7, 11};
int result0[10] = {2, 3, 5, 7, 11};
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/predcom-dse-3.c b/gcc/testsuite/gcc.dg/tree-ssa/predcom-dse-3.c
index 9c2736c..ec08d6c 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/predcom-dse-3.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/predcom-dse-3.c
@@ -1,5 +1,5 @@
/* { dg-do run } */
-/* { dg-options "-O2 -fno-inline -fpredictive-commoning -fdump-tree-pcom-details" } */
+/* { dg-options "-O2 -fno-inline -fno-tree-loop-distribute-patterns -fpredictive-commoning -fdump-tree-pcom-details" } */
int arr1[105] = {2, 3, 5, 7, 11, 13, 0};
int arr2[105] = {2, 3, 5, 7, 11, 13, 0};
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/predcom-dse-4.c b/gcc/testsuite/gcc.dg/tree-ssa/predcom-dse-4.c
index 302425a..f97d32f 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/predcom-dse-4.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/predcom-dse-4.c
@@ -1,5 +1,5 @@
/* { dg-do run } */
-/* { dg-options "-O2 -fno-inline -fpredictive-commoning -fdump-tree-pcom-details" } */
+/* { dg-options "-O2 -fno-inline -fno-tree-loop-distribute-patterns -fpredictive-commoning -fdump-tree-pcom-details" } */
int arr[105] = {2, 3, 5, 7, 11};
int result0[10] = {2, 3, 5, 7, 11};
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/prefetch-7.c b/gcc/testsuite/gcc.dg/tree-ssa/prefetch-7.c
index c9f7027..26de871 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/prefetch-7.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/prefetch-7.c
@@ -1,5 +1,5 @@
/* { dg-do compile { target { i?86-*-* x86_64-*-* } } } */
-/* { dg-options "-O2 -fprefetch-loop-arrays -march=amdfam10 --param simultaneous-prefetches=100 -fdump-tree-aprefetch-details -fdump-tree-optimized" } */
+/* { dg-options "-O2 -fno-tree-loop-distribute-patterns -fprefetch-loop-arrays -march=amdfam10 --param simultaneous-prefetches=100 -fdump-tree-aprefetch-details -fdump-tree-optimized" } */
#define K 1000000
int a[K];
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/prefetch-8.c b/gcc/testsuite/gcc.dg/tree-ssa/prefetch-8.c
index fe433ac..cbd6a80 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/prefetch-8.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/prefetch-8.c
@@ -1,5 +1,5 @@
/* { dg-do compile { target { i?86-*-* x86_64-*-* } } } */
-/* { dg-options "-O2 -fprefetch-loop-arrays -march=amdfam10 --param simultaneous-prefetches=100 -fdump-tree-aprefetch-details -fdump-tree-optimized" } */
+/* { dg-options "-O2 -fno-tree-loop-distribute-patterns -fprefetch-loop-arrays -march=amdfam10 --param simultaneous-prefetches=100 -fdump-tree-aprefetch-details -fdump-tree-optimized" } */
#define K 1000000
int a[K];
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/prefetch-9.c b/gcc/testsuite/gcc.dg/tree-ssa/prefetch-9.c
index 5be9282..da48473 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/prefetch-9.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/prefetch-9.c
@@ -1,5 +1,5 @@
/* { dg-do compile { target { i?86-*-* x86_64-*-* } } } */
-/* { dg-options "-O2 -fprefetch-loop-arrays -march=amdfam10 --param simultaneous-prefetches=100 -fdump-tree-aprefetch-details -fdump-tree-optimized" } */
+/* { dg-options "-O2 -fno-tree-loop-distribute-patterns -fprefetch-loop-arrays -march=amdfam10 --param simultaneous-prefetches=100 -fdump-tree-aprefetch-details -fdump-tree-optimized" } */
#define K 1000000
int a[K], b[K];
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pta-callused.c b/gcc/testsuite/gcc.dg/tree-ssa/pta-callused.c
index b9a57d8..cb85ec1 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/pta-callused.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pta-callused.c
@@ -22,5 +22,5 @@ int bar (int b)
return *foo (&q);
}
-/* { dg-final { scan-tree-dump "CALLUSED\\(\[0-9\]+\\) = { ESCAPED NONLOCAL f.* i q }" "alias" } } */
+/* { dg-final { scan-tree-dump "CALLUSED\\(\[0-9\]+\\) = { f.* i q }" "alias" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/reassoc-24.c b/gcc/testsuite/gcc.dg/tree-ssa/reassoc-24.c
index 4503cd7..c320d1c 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/reassoc-24.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/reassoc-24.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O2 --param tree-reassoc-width=2 -fdump-tree-reassoc1" } */
+/* { dg-options "-O2 --param tree-reassoc-width=2 -fdump-tree-reassoc2" } */
unsigned int
foo (void)
@@ -21,4 +21,4 @@ foo (void)
/* Verify there are two pairs of __asm__ statements with no
intervening stmts. */
-/* { dg-final { scan-tree-dump-times "__asm__\[^;\n]*;\n *__asm__" 2 "reassoc1"} } */
+/* { dg-final { scan-tree-dump-times "__asm__\[^;\n]*;\n *__asm__" 2 "reassoc2"} } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/reassoc-25.c b/gcc/testsuite/gcc.dg/tree-ssa/reassoc-25.c
index 553736b..dbb0268 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/reassoc-25.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/reassoc-25.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O2 --param tree-reassoc-width=3 -fdump-tree-reassoc1-details" } */
+/* { dg-options "-O2 --param tree-reassoc-width=3 -fdump-tree-reassoc2-details" } */
unsigned int
foo (int a, int b, int c, int d)
@@ -15,4 +15,4 @@ foo (int a, int b, int c, int d)
}
/* Verify reassociation width was chosen to be 2. */
-/* { dg-final { scan-tree-dump-times "Width = 2" 1 "reassoc1"} } */
+/* { dg-final { scan-tree-dump-times "Width = 2" 1 "reassoc2"} } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/reassoc-33.c b/gcc/testsuite/gcc.dg/tree-ssa/reassoc-33.c
index 28cd779..db0ce4c 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/reassoc-33.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/reassoc-33.c
@@ -1,4 +1,4 @@
-/* { dg-do run { target { ! "m68k*-*-* mmix*-*-* bfin*-*-* v850*-*-* moxie*-*-* cris*-*-* m32c*-*-* fr30*-*-* mcore*-*-* powerpc*-*-* xtensa*-*-* hppa*-*-* nios2*-*-* or1k-*-*-*"} } } */
+/* { dg-do run { target { ! "m68k*-*-* mmix*-*-* bfin*-*-* v850*-*-* moxie*-*-* cris*-*-* m32c*-*-* fr30*-*-* mcore*-*-* powerpc*-*-* xtensa*-*-* hppa*-*-* nios2*-*-* or1k-*-*-* pru*-*-*"} } } */
/* { dg-options "-O2 -fno-inline -fdump-tree-reassoc1-details --param logical-op-non-short-circuit=1" } */
/* { dg-additional-options "-mbranch-cost=2" { target branch_cost } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/reassoc-34.c b/gcc/testsuite/gcc.dg/tree-ssa/reassoc-34.c
index f108711..31e10a4 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/reassoc-34.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/reassoc-34.c
@@ -1,4 +1,4 @@
-/* { dg-do run { target { ! "m68k*-*-* mmix*-*-* bfin*-*-* v850*-*-* moxie*-*-* cris*-*-* m32c*-*-* fr30*-*-* mcore*-*-* powerpc*-*-* xtensa*-*-* hppa*-*-* nios2*-*-* or1k*-*-*"} } } */
+/* { dg-do run { target { ! "m68k*-*-* mmix*-*-* bfin*-*-* v850*-*-* moxie*-*-* cris*-*-* m32c*-*-* fr30*-*-* mcore*-*-* powerpc*-*-* xtensa*-*-* hppa*-*-* nios2*-*-* or1k*-*-* pru*-*-*"} } } */
/* { dg-options "-O2 -fno-inline -fdump-tree-reassoc1-details --param logical-op-non-short-circuit=1" } */
/* { dg-additional-options "-mbranch-cost=2" { target branch_cost } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/reassoc-35.c b/gcc/testsuite/gcc.dg/tree-ssa/reassoc-35.c
index 98ea2ad..d509d9f 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/reassoc-35.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/reassoc-35.c
@@ -1,4 +1,4 @@
-/* { dg-do run { target { ! "m68k*-*-* mmix*-*-* bfin*-*-* v850*-*-* moxie*-*-* cris*-*-* m32c*-*-* fr30*-*-* mcore*-*-* powerpc*-*-* xtensa*-*-* hppa*-*-* nios2*-*-* or1k*-*-*"} } } */
+/* { dg-do run { target { ! "m68k*-*-* mmix*-*-* bfin*-*-* v850*-*-* moxie*-*-* cris*-*-* m32c*-*-* fr30*-*-* mcore*-*-* powerpc*-*-* xtensa*-*-* hppa*-*-* nios2*-*-* or1k*-*-* pru*-*-*"} } } */
/* { dg-options "-O2 -fno-inline -fdump-tree-reassoc1-details --param logical-op-non-short-circuit=1" } */
/* { dg-additional-options "-mbranch-cost=2" { target branch_cost } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/reassoc-36.c b/gcc/testsuite/gcc.dg/tree-ssa/reassoc-36.c
index d918410..2ad46f5 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/reassoc-36.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/reassoc-36.c
@@ -1,4 +1,4 @@
-/* { dg-do run { target { ! "m68k*-*-* mmix*-*-* bfin*-*-* v850*-*-* moxie*-*-* cris*-*-* m32c*-*-* fr30*-*-* mcore*-*-* powerpc*-*-* xtensa*-*-* hppa*-*-* nios2*-*-* or1k*-*-*"} } } */
+/* { dg-do run { target { ! "m68k*-*-* mmix*-*-* bfin*-*-* v850*-*-* moxie*-*-* cris*-*-* m32c*-*-* fr30*-*-* mcore*-*-* powerpc*-*-* xtensa*-*-* hppa*-*-* nios2*-*-* or1k*-*-* pru*-*-*"} } } */
/* { dg-options "-O2 -fno-inline -fdump-tree-reassoc1-details --param logical-op-non-short-circuit=1" } */
/* { dg-additional-options "-mbranch-cost=2" { target branch_cost } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/scev-11.c b/gcc/testsuite/gcc.dg/tree-ssa/scev-11.c
index c665fd7..2336239 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/scev-11.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/scev-11.c
@@ -15,7 +15,7 @@ foo (int n)
{
unsigned char uc = (unsigned char)i;
a[i] = i;
- b[uc] = 0;
+ b[uc] = 1;
}
bar (a);
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/slsr-27.c b/gcc/testsuite/gcc.dg/tree-ssa/slsr-27.c
index 35b3d00..c8f8e61 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/slsr-27.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/slsr-27.c
@@ -19,4 +19,5 @@ f (struct x *p, unsigned int n)
/* { dg-final { scan-tree-dump-times "\\* 4;" 1 "dom3" { target { int32 } } } } */
/* { dg-final { scan-tree-dump-times "\\* 2;" 1 "dom3" { target { int16 } } } } */
/* { dg-final { scan-tree-dump-times "p_\\d\+\\(D\\) \\+ \[^\r\n\]*_\\d\+;" 1 "dom3" } } */
-/* { dg-final { scan-tree-dump-times "MEM\\\[\\(struct x \\*\\)\[^\r\n\]*_\\d\+" 3 "dom3" } } */
+/*
+ { dg-final { scan-tree-dump-times "MEM *<int>? *\\\[\\(struct x \\*\\)\[^\r\n\]*_\\d\+" 3 "dom3" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/slsr-28.c b/gcc/testsuite/gcc.dg/tree-ssa/slsr-28.c
index 732d232..b18e9c1 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/slsr-28.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/slsr-28.c
@@ -23,4 +23,4 @@ f (struct x *p, unsigned int n)
/* { dg-final { scan-tree-dump-times "\\* 4;" 1 "dom3" { target { int32 } } } } */
/* { dg-final { scan-tree-dump-times "\\* 2;" 1 "dom3" { target { int16 } } } } */
/* { dg-final { scan-tree-dump-times "p_\\d\+\\(D\\) \\+ \[^\r\n\]*_\\d\+" 1 "dom3" } } */
-/* { dg-final { scan-tree-dump-times "MEM\\\[\\(struct x \\*\\)\[^\r\n\]*_\\d\+" 9 "dom3" } } */
+/* { dg-final { scan-tree-dump-times "MEM *<int>? *\\\[\\(struct x \\*\\)\[^\r\n\]*_\\d\+" 9 "dom3" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/slsr-29.c b/gcc/testsuite/gcc.dg/tree-ssa/slsr-29.c
index a22cc79..00e8d2b 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/slsr-29.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/slsr-29.c
@@ -25,4 +25,4 @@ f (struct x *p, unsigned int n)
/* { dg-final { scan-tree-dump-times "\\* 4;" 1 "dom3" { target { int32 } } } } */
/* { dg-final { scan-tree-dump-times "\\* 2;" 1 "dom3" { target { int16 } } } } */
/* { dg-final { scan-tree-dump-times "p_\\d\+\\(D\\) \\+ \[^\r\n\]*_\\d\+" 1 "dom3" } } */
-/* { dg-final { scan-tree-dump-times "MEM\\\[\\(struct x \\*\\)\[^\r\n\]*_\\d\+" 9 "dom3" } } */
+/* { dg-final { scan-tree-dump-times "MEM *<int>? *\\\[\\(struct x \\*\\)\[^\r\n\]*_\\d\+" 9 "dom3" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/split-path-6.c b/gcc/testsuite/gcc.dg/tree-ssa/split-path-6.c
index e9b4f26..71d0fc0 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/split-path-6.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/split-path-6.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -fsplit-paths -fno-tree-cselim -fdump-tree-split-paths-details -w" } */
+/* { dg-options "-O2 -fsplit-paths -fno-tree-cselim -fdump-tree-split-paths-details -fno-finite-loops -fno-tree-dominator-opts -fno-tree-vrp -w" } */
struct __sFILE
{
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-cse-8.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-cse-8.c
new file mode 100644
index 0000000..b419ce7
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-cse-8.c
@@ -0,0 +1,15 @@
+/* { dg-do compile } */
+/* { dg-options "-O -fgimple -fdump-tree-dom2" } */
+
+int __GIMPLE (ssa,startwith("dom"))
+foo (void *p)
+{
+ int _2;
+
+ __BB(2):
+ __MEM <int> ((char *)p_1(D) + 4) = 20;
+ _2 = __MEM <const int> ((int *)p_1(D) + 4);
+ return _2;
+}
+
+/* { dg-final { scan-tree-dump "return 20;" "dom2" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-dse-24.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dse-24.c
index 282194c..bc4b071 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/ssa-dse-24.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dse-24.c
@@ -59,4 +59,4 @@ void foo(int prec,
bar (&info);
}
-/* { dg-final { scan-tree-dump-times "MEM\\\[\\(struct printf_info \\*\\)&info \\+ \[0-9\]+B\\\] = {}" 1 "dse1" } } */
+/* { dg-final { scan-tree-dump-times "MEM <char\\\[\[0-9\]+]> \\\[\\(struct printf_info \\*\\)&info \\+ \[0-9\]+B\\\] = {}" 1 "dse1" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-dse-26.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dse-26.c
index 32d6389..836a809 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/ssa-dse-26.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dse-26.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -fdump-tree-dse1-details -fno-short-enums" } */
+/* { dg-options "-O2 -fdump-tree-dse1-details -fno-short-enums -fno-tree-fre" } */
/* { dg-skip-if "temporary variable for constraint_expr is never used" { msp430-*-* } } */
enum constraint_expr_type
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-dse-36.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dse-36.c
new file mode 100644
index 0000000..23a53bb
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dse-36.c
@@ -0,0 +1,65 @@
+/* { dg-options "-O2 -fdump-tree-dse-details -fno-tree-fre" } */
+#include <string.h>
+#include <stdlib.h>
+
+struct X
+{
+ char mem0[10];
+ char mem1[10];
+};
+
+
+void blah (struct X);
+
+
+void
+foo1()
+{
+ struct X x = { };
+ memset (x.mem1, 0, sizeof x.mem1);
+ blah (x);
+}
+
+void
+foo2()
+{
+ struct X x = { };
+ x.mem1[5] = 0;
+ blah (x);
+}
+
+void
+bar1 ()
+{
+ struct X x;
+ memset (&x, 0, sizeof x);
+ memset (&x.mem1, 0, sizeof x.mem1);
+ blah (x);
+}
+void
+bar2 ()
+{
+ struct X x;
+ memset (&x, 0, sizeof x);
+ x.mem1[5] = 0;
+ blah (x);
+}
+
+void
+baz1 ()
+{
+ struct X *x = calloc (sizeof (struct X), 1);
+ memset (&x->mem1, 0, sizeof x->mem1);
+ blah (*x);
+}
+
+void
+baz2 ()
+{
+ struct X *x = calloc (sizeof (struct X), 1);
+ x->mem1[5] = 0;
+ blah (*x);
+}
+/* { dg-final { scan-tree-dump-times "Deleted redundant call" 3 "dse1" } } */
+/* { dg-final { scan-tree-dump-times "Deleted redundant store" 3 "dse1" } } */
+
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-69.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-69.c
new file mode 100644
index 0000000..e2ce28e
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-69.c
@@ -0,0 +1,32 @@
+/* { dg-do compile } */
+/* { dg-options "-fgimple -O1 -fdump-tree-fre1" } */
+
+int a[10];
+typedef int v2si __attribute__((vector_size(__SIZEOF_INT__*2)));
+int __GIMPLE (ssa,guessed_local(97603132),startwith("fre1"))
+ foo ()
+{
+ int i;
+ int _59;
+ int _44;
+ int _13;
+ int _18;
+ v2si _80;
+ v2si _81;
+ int res;
+
+ __BB(2,guessed_local(97603132)):
+ _59 = 64;
+ i_61 = 9;
+ _44 = i_61 * i_61;
+ _80 = _Literal (v2si) {_59, _44};
+ _81 = _80;
+ __MEM <v2si> ((int *)&a + _Literal (int *) 32) = _81;
+ i_48 = 9;
+ _13 = a[8];
+ _18 = a[i_48];
+ res_15 = _13 + _18;
+ return res_15;
+}
+
+/* { dg-final { scan-tree-dump "return 145;" "fre1" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-lim-13.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-lim-13.c
new file mode 100644
index 0000000..65aa745
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-lim-13.c
@@ -0,0 +1,53 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fgimple -fdump-tree-lim2-details" } */
+
+int __GIMPLE (ssa,startwith("lim"))
+foo (int x, int n)
+{
+ int i;
+ int r;
+ int _1;
+ int _2;
+ int _6;
+
+ __BB(2):
+ goto __BB7;
+
+ __BB(3):
+ if (i_5 == 17)
+ goto __BB8;
+ else
+ goto __BB4;
+
+ __BB(4):
+ _1 = i_5 & 1;
+ if (_1 != 0)
+ goto __BB5;
+ else
+ goto __BB6;
+
+ __BB(5):
+ _2 = __ABS x_8(D);
+ r_9 = _2 / 5;
+ goto __BB6;
+
+ __BB(6):
+ r_3 = __PHI (__BB5: r_9, __BB4: r_4);
+ i_10 = i_5 + 1;
+ goto __BB7;
+
+ __BB(7,loop_header(1)):
+ r_4 = __PHI (__BB2: 1, __BB6: r_3);
+ i_5 = __PHI (__BB2: 0, __BB6: i_10);
+ if (i_5 < n_7(D))
+ goto __BB3;
+ else
+ goto __BB8;
+
+ __BB(8):
+ _6 = __PHI (__BB3: 0, __BB7: r_4);
+ return _6;
+}
+
+/* { dg-final { scan-tree-dump-times "Moving statement" 2 "lim2" } } */
+/* { dg-final { scan-tree-dump "ABSU_EXPR" "lim2" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-thread-12.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-thread-12.c
index d829b04..6752676 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/ssa-thread-12.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-thread-12.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -fdump-tree-thread2-details -fdump-tree-thread3-details -fdump-tree-thread4-details" } */
+/* { dg-options "-O2 -fdump-tree-thread2-details -fdump-tree-thread3-details -fdump-tree-thread4-details -fno-finite-loops" } */
/* { dg-final { scan-tree-dump "FSM" "thread2" } } */
/* { dg-final { scan-tree-dump "FSM" "thread3" } } */
/* { dg-final { scan-tree-dump "FSM" "thread4" { xfail *-*-* } } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/vector-6.c b/gcc/testsuite/gcc.dg/tree-ssa/vector-6.c
index 785e5df..e0bb196 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/vector-6.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/vector-6.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O -fdump-tree-ccp1 -Wno-psabi -w" } */
+/* { dg-options "-O -fdump-tree-ssa -fdump-tree-ccp1 -Wno-psabi -w" } */
/* { dg-additional-options "-msse2" { target i?86-*-* x86_64-*-* } } */
/* { dg-additional-options "-maltivec" { target powerpc_altivec_ok } } */
@@ -32,4 +32,5 @@ v4si test4 (v4si v, int i)
return v;
}
-/* { dg-final { scan-tree-dump-times "Now a gimple register: v" 4 "ccp1" { target { { i?86-*-* x86_64-*-* aarch64*-*-* spu*-*-* } || { powerpc_altivec_ok } } } } } */
+/* { dg-final { scan-tree-dump-times "Now a gimple register: v" 2 "ssa" { target { { i?86-*-* x86_64-*-* aarch64*-*-* spu*-*-* } || { powerpc_altivec_ok } } } } } */
+/* { dg-final { scan-tree-dump-times "Now a gimple register: v" 2 "ccp1" { target { { i?86-*-* x86_64-*-* aarch64*-*-* spu*-*-* } || { powerpc_altivec_ok } } } } } */
diff --git a/gcc/testsuite/gcc.dg/uninit-19.c b/gcc/testsuite/gcc.dg/uninit-19.c
index 3f5f06a..a54e60d 100644
--- a/gcc/testsuite/gcc.dg/uninit-19.c
+++ b/gcc/testsuite/gcc.dg/uninit-19.c
@@ -12,7 +12,7 @@ fn1 (int p1, float *f1, float *f2, float *f3, unsigned char *c1, float *f4,
{
if (p1 & 8)
b[3] = p10[a];
- /* { dg-warning "may be used uninitialized" "" { target { { nonpic || pie_enabled } || { hppa*64*-*-* } } } .-1 } */
+ /* { dg-warning "may be used uninitialized" "" { target { { nonpic || pie_enabled } || { hppa*64*-*-* *-*-darwin* } } } .-1 } */
}
void
@@ -22,5 +22,5 @@ fn2 ()
if (l & 6)
n = &c + m;
fn1 (l, &d, &e, &g, &i, &h, &k, n);
- /* { dg-warning "may be used uninitialized" "" { target { ! { { nonpic || pie_enabled } || { hppa*64*-*-* } } } } .-1 } */
+ /* { dg-warning "may be used uninitialized" "" { target { ! { { nonpic || pie_enabled } || { hppa*64*-*-* *-*-darwin* } } } } .-1 } */
}
diff --git a/gcc/testsuite/gcc.dg/uninit-28-gimple.c b/gcc/testsuite/gcc.dg/uninit-28-gimple.c
new file mode 100644
index 0000000..0648b8a
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/uninit-28-gimple.c
@@ -0,0 +1,47 @@
+/* { dg-do compile } */
+/* { dg-options "-fgimple -O -Wmaybe-uninitialized" } */
+
+unsigned int __GIMPLE (ssa,startwith("uninit1"))
+foo (unsigned int v)
+{
+ /* Uninit warning here would be bogus, because (16 & 3) == 0 and therefore
+ if v == 16, the uninit value is not used (the use is properly guarded). */
+ unsigned int undef; /* { dg-bogus "may be used uninitialized" } */
+ unsigned int _2;
+ unsigned int _9;
+ unsigned int _10;
+ unsigned pred;
+
+ __BB(2):
+ if (v_4(D) != 16u)
+ goto __BB3;
+ else
+ goto __BB4;
+
+ /* 'undef' is defined conditionally (under 'v != 16' predicate) */
+ __BB(3):
+ undef_8 = 8u;
+ goto __BB4;
+
+ /* An undef value flows into a phi. */
+ __BB(4):
+ undef_1 = __PHI (__BB2: undef_5(D), __BB3: undef_8);
+ pred = v_4(D) & 3u;
+ if (pred != 0u)
+ goto __BB5;
+ else
+ goto __BB6;
+
+ /* The phi value is used here (under 'v & 3' predicate). */
+ __BB(5):
+ _9 = undef_1;
+ goto __BB7;
+
+ __BB(6):
+ _10 = v_4(D);
+ goto __BB7;
+
+ __BB(7):
+ _2 = __PHI (__BB5: _9, __BB6: _10);
+ return _2;
+}
diff --git a/gcc/testsuite/gcc.dg/uninit-29-gimple.c b/gcc/testsuite/gcc.dg/uninit-29-gimple.c
new file mode 100644
index 0000000..cb5bc97
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/uninit-29-gimple.c
@@ -0,0 +1,45 @@
+/* { dg-do compile } */
+/* { dg-options "-fgimple -O -Wmaybe-uninitialized" } */
+
+unsigned int __GIMPLE (ssa,startwith("uninit1"))
+foo (unsigned int v)
+{
+ unsigned int undef; /* { dg-warning "may be used uninitialized" } */
+ unsigned int _2;
+ unsigned int _9;
+ unsigned int _10;
+ unsigned pred;
+
+ __BB(2):
+ pred = v_4(D) & 3u;
+ if (pred != 0u)
+ goto __BB3;
+ else
+ goto __BB4;
+
+ /* 'undef' is defined conditionally (under 'v & 3' predicate) */
+ __BB(3):
+ undef_8 = 8u;
+ goto __BB4;
+
+ /* An undef value flows into a phi. */
+ __BB(4):
+ undef_1 = __PHI (__BB2: undef_5(D), __BB3: undef_8);
+ if (v_4(D) != 16u)
+ goto __BB5;
+ else
+ goto __BB6;
+
+ /* The phi value is used here (under 'v != 16' predicate). */
+ __BB(5):
+ _9 = undef_1;
+ goto __BB7;
+
+ __BB(6):
+ _10 = v_4(D);
+ goto __BB7;
+
+ __BB(7):
+ _2 = __PHI (__BB5: _9, __BB6: _10);
+ return _2;
+}
diff --git a/gcc/testsuite/gcc.dg/uninit-30-gimple.c b/gcc/testsuite/gcc.dg/uninit-30-gimple.c
new file mode 100644
index 0000000..8c91f79
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/uninit-30-gimple.c
@@ -0,0 +1,43 @@
+/* { dg-do compile } */
+/* { dg-options "-fgimple -O -Wmaybe-uninitialized" } */
+
+unsigned int __GIMPLE (ssa,startwith("uninit1"))
+foo (unsigned int v)
+{
+ unsigned int undef; /* { dg-bogus "may be used uninitialized" } */
+ unsigned int _2;
+ unsigned int _9;
+ unsigned int _10;
+
+ __BB(2):
+ if (v_4(D) < 100u)
+ goto __BB3;
+ else
+ goto __BB4;
+
+ /* 'undef' is defined conditionally (under 'v < 100' predicate). */
+ __BB(3):
+ undef_8 = 8u;
+ goto __BB4;
+
+ /* An undef value flows into a phi. */
+ __BB(4):
+ undef_1 = __PHI (__BB2: undef_5(D), __BB3: undef_8);
+ if (v_4(D) == 42u)
+ goto __BB5;
+ else
+ goto __BB6;
+
+ /* The phi value is used here (under 'v == 42' predicate). */
+ __BB(5):
+ _9 = undef_1;
+ goto __BB7;
+
+ __BB(6):
+ _10 = v_4(D);
+ goto __BB7;
+
+ __BB(7):
+ _2 = __PHI (__BB5: _9, __BB6: _10);
+ return _2;
+}
diff --git a/gcc/testsuite/gcc.dg/uninit-31-gimple.c b/gcc/testsuite/gcc.dg/uninit-31-gimple.c
new file mode 100644
index 0000000..01118ef
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/uninit-31-gimple.c
@@ -0,0 +1,48 @@
+/* { dg-do compile } */
+/* { dg-options "-fgimple -O -Wmaybe-uninitialized" } */
+
+unsigned int __GIMPLE (ssa,startwith("uninit1"))
+foo (unsigned int v)
+{
+ /* If v == 2, then undef is used w/o being initialized. */
+ unsigned int undef; /* { dg-warning "may be used uninitialized" } */
+ unsigned int _2;
+ unsigned int _9;
+ unsigned int _10;
+ unsigned int pred2;
+ unsigned int pred1;
+
+ __BB(2):
+ pred2 = v_4(D) & 5u;
+ if (pred2 != 0u)
+ goto __BB3;
+ else
+ goto __BB4;
+
+ /* 'undef' is defined conditionally (under 'v & 5' predicate). */
+ __BB(3):
+ undef_8 = 8u;
+ goto __BB4;
+
+ /* An undef value flows into a phi. */
+ __BB(4):
+ undef_1 = __PHI (__BB2: undef_5(D), __BB3: undef_8);
+ pred1 = v_4(D) & 3u;
+ if (pred1 != 0u)
+ goto __BB5;
+ else
+ goto __BB6;
+
+ /* The phi value is used here (under 'v & 3' predicate). */
+ __BB(5):
+ _9 = undef_1;
+ goto __BB7;
+
+ __BB(6):
+ _10 = v_4(D);
+ goto __BB7;
+
+ __BB(7):
+ _2 = __PHI (__BB5: _9, __BB6: _10);
+ return _2;
+}
diff --git a/gcc/testsuite/gcc.dg/uninit-pr90394-1-gimple.c b/gcc/testsuite/gcc.dg/uninit-pr90394-1-gimple.c
new file mode 100644
index 0000000..f8feb6b
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/uninit-pr90394-1-gimple.c
@@ -0,0 +1,47 @@
+/* { dg-do compile } */
+/* { dg-options "-fgimple -O -Wmaybe-uninitialized" } */
+
+unsigned int __GIMPLE (ssa,startwith("uninit1"))
+foo (unsigned int v)
+{
+ /* The warning is not bogus, because (5 & 3) != 0 and therefore if v == 5,
+ the value of undef is used without being initialized. */
+ unsigned int undef; /* { dg-warning "may be used uninitialized" } */
+ unsigned int _2;
+ unsigned int _9;
+ unsigned int _10;
+ unsigned pred;
+
+ __BB(2):
+ if (v_4(D) != 5u)
+ goto __BB3;
+ else
+ goto __BB4;
+
+ /* 'undef' is defined conditionally (under 'v != 5' predicate) */
+ __BB(3):
+ undef_8 = 8u;
+ goto __BB4;
+
+ /* An undef value flows into a phi. */
+ __BB(4):
+ undef_1 = __PHI (__BB2: undef_5(D), __BB3: undef_8);
+ pred = v_4(D) & 3u;
+ if (pred != 0u)
+ goto __BB5;
+ else
+ goto __BB6;
+
+ /* The phi value is used here (under 'v & 3' predicate). */
+ __BB(5):
+ _9 = undef_1;
+ goto __BB7;
+
+ __BB(6):
+ _10 = v_4(D);
+ goto __BB7;
+
+ __BB(7):
+ _2 = __PHI (__BB5: _9, __BB6: _10);
+ return _2;
+}
diff --git a/gcc/testsuite/gcc.dg/uninit-pr90394.c b/gcc/testsuite/gcc.dg/uninit-pr90394.c
new file mode 100644
index 0000000..16e750d
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/uninit-pr90394.c
@@ -0,0 +1,33 @@
+/* { dg-do compile } */
+/* { dg-options "-O1 -fno-tree-fre -Wuninitialized" } */
+int pz;
+int zi;
+
+void
+uk (void)
+{
+ int th = 1;
+ int *gw = &zi;
+
+ for (zi = 0; zi < 2; ++zi)
+ {
+ int a2 = 0;
+
+ for (zi = 0; zi < 1; ++zi)
+ {
+ th = a2 * 2;
+
+ og:
+ for (pz = 0; pz < 1; ++pz)
+ {
+ }
+ }
+
+ pz = !!*gw ? *gw : pz;
+ pz = (!!th ? (pz & 1) : 0);
+ if (pz == 0)
+ ++a2;
+ }
+
+ goto og;
+}
diff --git a/gcc/testsuite/gcc.dg/utf-array-short-wchar.c b/gcc/testsuite/gcc.dg/utf-array-short-wchar.c
index a582e71..81b452a 100644
--- a/gcc/testsuite/gcc.dg/utf-array-short-wchar.c
+++ b/gcc/testsuite/gcc.dg/utf-array-short-wchar.c
@@ -21,8 +21,8 @@ const char16_t s16_2[] = U"ab"; /* { dg-error "from a string literal with type a
const char16_t s16_3[] = L"ab";
const char16_t s16_4[] = u8"ab"; /* { dg-error "from a string literal with type array of .char." } */
-const char16_t s16_5[0] = u"ab"; /* { dg-warning "chars is too long" } */
-const char16_t s16_6[1] = u"ab"; /* { dg-warning "chars is too long" } */
+const char16_t s16_5[0] = u"ab"; /* { dg-warning " is too long" } */
+const char16_t s16_6[1] = u"ab"; /* { dg-warning " is too long" } */
const char16_t s16_7[2] = u"ab";
const char16_t s16_8[3] = u"ab";
const char16_t s16_9[4] = u"ab";
@@ -33,11 +33,11 @@ const char32_t s32_2[] = U"ab";
const char32_t s32_3[] = L"ab"; /* { dg-error "from a string literal with type array of" } */
const char32_t s32_4[] = u8"ab"; /* { dg-error "from a string literal with type array of .char." } */
-const char32_t s32_5[0] = U"ab"; /* { dg-warning "chars is too long" } */
-const char32_t s32_6[1] = U"ab"; /* { dg-warning "chars is too long" } */
-const char32_t s32_7[2] = U"ab"; /* { dg-warning "chars is too long" "" { target "m32c-*-*" } } */
-const char32_t s32_8[3] = U"ab"; /* { dg-warning "chars is too long" "" { target "m32c-*-*" } } */
-const char32_t s32_9[4] = U"ab"; /* { dg-warning "chars is too long" "" { target "m32c-*-*" } } */
+const char32_t s32_5[0] = U"ab"; /* { dg-warning " is too long" } */
+const char32_t s32_6[1] = U"ab"; /* { dg-warning " is too long" } */
+const char32_t s32_7[2] = U"ab"; /* { dg-warning " is too long" "" { target "m32c-*-*" } } */
+const char32_t s32_8[3] = U"ab"; /* { dg-warning " is too long" "" { target "m32c-*-*" } } */
+const char32_t s32_9[4] = U"ab"; /* { dg-warning " is too long" "" { target "m32c-*-*" } } */
const wchar_t sw_0[] = "ab"; /* { dg-error "from a string literal with type array of .char." } */
const wchar_t sw_1[] = u"ab";
diff --git a/gcc/testsuite/gcc.dg/utf-array.c b/gcc/testsuite/gcc.dg/utf-array.c
index 8687989..7f0cb91 100644
--- a/gcc/testsuite/gcc.dg/utf-array.c
+++ b/gcc/testsuite/gcc.dg/utf-array.c
@@ -21,8 +21,8 @@ const char16_t s16_2[] = U"ab"; /* { dg-error "from a string literal with type a
const char16_t s16_3[] = L"ab"; /* { dg-error "from a string literal with type array of .(long |short )?(unsigned )?int." "" { target { ! wchar_t_char16_t_compatible } } } */
const char16_t s16_4[] = u8"ab"; /* { dg-error "from a string literal with type array of .char." } */
-const char16_t s16_5[0] = u"ab"; /* { dg-warning "chars is too long" } */
-const char16_t s16_6[1] = u"ab"; /* { dg-warning "chars is too long" } */
+const char16_t s16_5[0] = u"ab"; /* { dg-warning " is too long" } */
+const char16_t s16_6[1] = u"ab"; /* { dg-warning " is too long" } */
const char16_t s16_7[2] = u"ab";
const char16_t s16_8[3] = u"ab";
const char16_t s16_9[4] = u"ab";
@@ -33,11 +33,11 @@ const char32_t s32_2[] = U"ab";
const char32_t s32_3[] = L"ab"; /* { dg-error "from a string literal with type array of .(long |short )?(unsigned )?int." "" { target { ! wchar_t_char32_t_compatible } } } */
const char32_t s32_4[] = u8"ab"; /* { dg-error "from a string literal with type array of .char." } */
-const char32_t s32_5[0] = U"ab"; /* { dg-warning "chars is too long" } */
-const char32_t s32_6[1] = U"ab"; /* { dg-warning "chars is too long" } */
-const char32_t s32_7[2] = U"ab"; /* { dg-warning "chars is too long" "" { target "m32c-*-*" } } */
-const char32_t s32_8[3] = U"ab"; /* { dg-warning "chars is too long" "" { target "m32c-*-*" } } */
-const char32_t s32_9[4] = U"ab"; /* { dg-warning "chars is too long" "" { target "m32c-*-*" } } */
+const char32_t s32_5[0] = U"ab"; /* { dg-warning " is too long" } */
+const char32_t s32_6[1] = U"ab"; /* { dg-warning " is too long" } */
+const char32_t s32_7[2] = U"ab"; /* { dg-warning " is too long" "" { target "m32c-*-*" } } */
+const char32_t s32_8[3] = U"ab"; /* { dg-warning " is too long" "" { target "m32c-*-*" } } */
+const char32_t s32_9[4] = U"ab"; /* { dg-warning " is too long" "" { target "m32c-*-*" } } */
const wchar_t sw_0[] = "ab"; /* { dg-error "from a string literal with type array of .char." } */
const wchar_t sw_1[] = u"ab"; /* { dg-error "from a string literal with type array of" "" { target { ! wchar_t_char16_t_compatible } } } */
diff --git a/gcc/testsuite/gcc.dg/utf8-2.c b/gcc/testsuite/gcc.dg/utf8-2.c
index d96b15d..b3b873d 100644
--- a/gcc/testsuite/gcc.dg/utf8-2.c
+++ b/gcc/testsuite/gcc.dg/utf8-2.c
@@ -12,16 +12,16 @@ const char16_t s1[] = u8"ab"; /* { dg-error "from a string literal with type arr
const char32_t s2[] = u8"ab"; /* { dg-error "from a string literal with type array of .char." } */
const wchar_t s3[] = u8"ab"; /* { dg-error "from a string literal with type array of .char." } */
-const char t0[0] = u8"ab"; /* { dg-warning "chars is too long" } */
-const char t1[1] = u8"ab"; /* { dg-warning "chars is too long" } */
+const char t0[0] = u8"ab"; /* { dg-warning " is too long" } */
+const char t1[1] = u8"ab"; /* { dg-warning " is too long" } */
const char t2[2] = u8"ab";
const char t3[3] = u8"ab";
const char t4[4] = u8"ab";
-const char u0[0] = u8"\u2160."; /* { dg-warning "chars is too long" } */
-const char u1[1] = u8"\u2160."; /* { dg-warning "chars is too long" } */
-const char u2[2] = u8"\u2160."; /* { dg-warning "chars is too long" } */
-const char u3[3] = u8"\u2160."; /* { dg-warning "chars is too long" } */
+const char u0[0] = u8"\u2160."; /* { dg-warning " is too long" } */
+const char u1[1] = u8"\u2160."; /* { dg-warning " is too long" } */
+const char u2[2] = u8"\u2160."; /* { dg-warning " is too long" } */
+const char u3[3] = u8"\u2160."; /* { dg-warning " is too long" } */
const char u4[4] = u8"\u2160.";
const char u5[5] = u8"\u2160.";
const char u6[6] = u8"\u2160.";
diff --git a/gcc/testsuite/gcc.dg/vect/O3-pr70130.c b/gcc/testsuite/gcc.dg/vect/O3-pr70130.c
index 18a295c..f8b8440 100644
--- a/gcc/testsuite/gcc.dg/vect/O3-pr70130.c
+++ b/gcc/testsuite/gcc.dg/vect/O3-pr70130.c
@@ -1,5 +1,5 @@
/* { dg-require-effective-target vsx_hw { target powerpc*-*-* } } */
-/* { dg-additional-options "-mcpu=power7" { target powerpc*-*-* } } */
+/* { dg-additional-options "-mcpu=power7 -mno-power9-vector -mno-power8-vector" { target powerpc*-*-* } } */
#include "tree-vect.h"
diff --git a/gcc/testsuite/gcc.dg/vect/costmodel/i386/costmodel-vect-31.c b/gcc/testsuite/gcc.dg/vect/costmodel/i386/costmodel-vect-31.c
index 133ab0e..cc50a5b 100644
--- a/gcc/testsuite/gcc.dg/vect/costmodel/i386/costmodel-vect-31.c
+++ b/gcc/testsuite/gcc.dg/vect/costmodel/i386/costmodel-vect-31.c
@@ -1,4 +1,5 @@
/* { dg-require-effective-target vect_int } */
+/* { dg-additional-options "-fno-tree-loop-distribute-patterns" } */
#include <stdarg.h>
#include "../../tree-vect.h"
diff --git a/gcc/testsuite/gcc.dg/vect/costmodel/i386/costmodel-vect-33.c b/gcc/testsuite/gcc.dg/vect/costmodel/i386/costmodel-vect-33.c
index 242427d..b82b891 100644
--- a/gcc/testsuite/gcc.dg/vect/costmodel/i386/costmodel-vect-33.c
+++ b/gcc/testsuite/gcc.dg/vect/costmodel/i386/costmodel-vect-33.c
@@ -1,5 +1,6 @@
/* { dg-do compile } */
/* { dg-require-effective-target vect_int } */
+/* { dg-additional-options "-fno-tree-loop-distribute-patterns" } */
#include <stdarg.h>
#include "../../tree-vect.h"
diff --git a/gcc/testsuite/gcc.dg/vect/costmodel/ppc/costmodel-vect-31b.c b/gcc/testsuite/gcc.dg/vect/costmodel/ppc/costmodel-vect-31b.c
index b0f193f..9bb81e3 100644
--- a/gcc/testsuite/gcc.dg/vect/costmodel/ppc/costmodel-vect-31b.c
+++ b/gcc/testsuite/gcc.dg/vect/costmodel/ppc/costmodel-vect-31b.c
@@ -1,4 +1,5 @@
/* { dg-require-effective-target vect_int } */
+/* { dg-additional-options "-fno-tree-loop-distribute-patterns" } */
#include <stdarg.h>
#include "../../tree-vect.h"
diff --git a/gcc/testsuite/gcc.dg/vect/costmodel/ppc/costmodel-vect-33.c b/gcc/testsuite/gcc.dg/vect/costmodel/ppc/costmodel-vect-33.c
index db7b5a6..dc170a0 100644
--- a/gcc/testsuite/gcc.dg/vect/costmodel/ppc/costmodel-vect-33.c
+++ b/gcc/testsuite/gcc.dg/vect/costmodel/ppc/costmodel-vect-33.c
@@ -1,5 +1,6 @@
/* { dg-do compile } */
/* { dg-require-effective-target vect_int } */
+/* { dg-additional-options "-fno-tree-loop-distribute-patterns" } */
#include <stdarg.h>
#include "../../tree-vect.h"
diff --git a/gcc/testsuite/gcc.dg/vect/costmodel/ppc/costmodel-vect-76a.c b/gcc/testsuite/gcc.dg/vect/costmodel/ppc/costmodel-vect-76a.c
index 851175f..2fc751c 100644
--- a/gcc/testsuite/gcc.dg/vect/costmodel/ppc/costmodel-vect-76a.c
+++ b/gcc/testsuite/gcc.dg/vect/costmodel/ppc/costmodel-vect-76a.c
@@ -1,4 +1,5 @@
/* { dg-require-effective-target vect_int } */
+/* { dg-additional-options "-fno-tree-loop-distribute-patterns" } */
#include <stdarg.h>
#include "../../tree-vect.h"
diff --git a/gcc/testsuite/gcc.dg/vect/costmodel/ppc/costmodel-vect-76b.c b/gcc/testsuite/gcc.dg/vect/costmodel/ppc/costmodel-vect-76b.c
index d2f9992..4a7da2e 100644
--- a/gcc/testsuite/gcc.dg/vect/costmodel/ppc/costmodel-vect-76b.c
+++ b/gcc/testsuite/gcc.dg/vect/costmodel/ppc/costmodel-vect-76b.c
@@ -1,4 +1,5 @@
/* { dg-require-effective-target vect_int } */
+/* { dg-additional-options "-fno-tree-loop-distribute-patterns" } */
#include <stdarg.h>
#include "../../tree-vect.h"
diff --git a/gcc/testsuite/gcc.dg/vect/costmodel/ppc/costmodel-vect-76c.c b/gcc/testsuite/gcc.dg/vect/costmodel/ppc/costmodel-vect-76c.c
index de1039f..1fc1466 100644
--- a/gcc/testsuite/gcc.dg/vect/costmodel/ppc/costmodel-vect-76c.c
+++ b/gcc/testsuite/gcc.dg/vect/costmodel/ppc/costmodel-vect-76c.c
@@ -1,4 +1,5 @@
/* { dg-require-effective-target vect_int } */
+/* { dg-additional-options "-fno-tree-loop-distribute-patterns" } */
#include <stdarg.h>
#include "../../tree-vect.h"
diff --git a/gcc/testsuite/gcc.dg/vect/costmodel/x86_64/costmodel-vect-31.c b/gcc/testsuite/gcc.dg/vect/costmodel/x86_64/costmodel-vect-31.c
index 133ab0e..cc50a5b 100644
--- a/gcc/testsuite/gcc.dg/vect/costmodel/x86_64/costmodel-vect-31.c
+++ b/gcc/testsuite/gcc.dg/vect/costmodel/x86_64/costmodel-vect-31.c
@@ -1,4 +1,5 @@
/* { dg-require-effective-target vect_int } */
+/* { dg-additional-options "-fno-tree-loop-distribute-patterns" } */
#include <stdarg.h>
#include "../../tree-vect.h"
diff --git a/gcc/testsuite/gcc.dg/vect/costmodel/x86_64/costmodel-vect-33.c b/gcc/testsuite/gcc.dg/vect/costmodel/x86_64/costmodel-vect-33.c
index 33bf7f1..5e4affa 100644
--- a/gcc/testsuite/gcc.dg/vect/costmodel/x86_64/costmodel-vect-33.c
+++ b/gcc/testsuite/gcc.dg/vect/costmodel/x86_64/costmodel-vect-33.c
@@ -1,5 +1,6 @@
/* { dg-do compile } */
/* { dg-require-effective-target vect_int } */
+/* { dg-additional-options "-fno-tree-loop-distribute-patterns" } */
#include <stdarg.h>
#include "../../tree-vect.h"
diff --git a/gcc/testsuite/gcc.dg/vect/pr48765.c b/gcc/testsuite/gcc.dg/vect/pr48765.c
index ae36437..b091a14 100644
--- a/gcc/testsuite/gcc.dg/vect/pr48765.c
+++ b/gcc/testsuite/gcc.dg/vect/pr48765.c
@@ -1,6 +1,6 @@
/* { dg-do compile { target { powerpc*-*-* } } } */
/* { dg-skip-if "do not override -mcpu" { *-*-* } { "-mcpu=*" } { "-mcpu=power6" } } */
-/* { dg-additional-options "-O3 -mcpu=power6" } */
+/* { dg-additional-options "-O3 -mcpu=power6 -mno-power9-vector -mno-power8-vector -mno-vsx" } */
enum reg_class
{
diff --git a/gcc/testsuite/gcc.dg/vect/vect-simd-1.c b/gcc/testsuite/gcc.dg/vect/vect-simd-1.c
new file mode 100644
index 0000000..7c3feee
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/vect-simd-1.c
@@ -0,0 +1,64 @@
+/* { dg-additional-options "-fopenmp-simd" } */
+/* { dg-additional-options "-mavx" { target avx_runtime } } */
+
+#include "tree-vect.h"
+
+#define N 1024
+int a[N];
+int x;
+
+__attribute__((noipa)) int
+bar (void)
+{
+ return x;
+}
+
+__attribute__((noipa)) void
+foo (void)
+{
+ #pragma omp simd if (bar ())
+ for (int i = 0; i < N; ++i)
+ a[i] = a[i] + 1;
+}
+
+__attribute__((noipa)) void
+baz (void)
+{
+ int c = 0;
+ #pragma omp simd if (c)
+ for (int i = 0; i < N; ++i)
+ a[i] = a[i] + 1;
+}
+
+__attribute__((noipa)) void
+qux (void)
+{
+ int c = 1;
+ #pragma omp simd if (c)
+ for (int i = 0; i < N; ++i)
+ a[i] = a[i] + 1;
+}
+
+int
+main ()
+{
+ check_vect ();
+ foo ();
+ for (int i = 0; i < N; ++i)
+ if (a[i] != 1)
+ abort ();
+ x = 1;
+ foo ();
+ for (int i = 0; i < N; ++i)
+ if (a[i] != 2)
+ abort ();
+ baz ();
+ for (int i = 0; i < N; ++i)
+ if (a[i] != 3)
+ abort ();
+ qux ();
+ for (int i = 0; i < N; ++i)
+ if (a[i] != 4)
+ abort ();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/vect/vect-simd-10.c b/gcc/testsuite/gcc.dg/vect/vect-simd-10.c
new file mode 100644
index 0000000..d442d6b
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/vect-simd-10.c
@@ -0,0 +1,96 @@
+/* { dg-require-effective-target size32plus } */
+/* { dg-additional-options "-fopenmp-simd" } */
+/* { dg-additional-options "-mavx" { target avx_runtime } } */
+/* { dg-final { scan-tree-dump-times "vectorized \[1-3] loops" 2 "vect" { target i?86-*-* x86_64-*-* } } } */
+
+#ifndef main
+#include "tree-vect.h"
+#endif
+
+float r = 1.0f, a[1024], b[1024];
+
+__attribute__((noipa)) void
+foo (float *a, float *b)
+{
+ #pragma omp simd reduction (inscan, *:r)
+ for (int i = 0; i < 1024; i++)
+ {
+ r *= a[i];
+ #pragma omp scan inclusive(r)
+ b[i] = r;
+ }
+}
+
+__attribute__((noipa)) float
+bar (void)
+{
+ float s = -__builtin_inff ();
+ #pragma omp simd reduction (inscan, max:s)
+ for (int i = 0; i < 1024; i++)
+ {
+ s = s > a[i] ? s : a[i];
+ #pragma omp scan inclusive(s)
+ b[i] = s;
+ }
+ return s;
+}
+
+int
+main ()
+{
+ float s = 1.0f;
+#ifndef main
+ check_vect ();
+#endif
+ for (int i = 0; i < 1024; ++i)
+ {
+ if (i < 80)
+ a[i] = (i & 1) ? 0.25f : 0.5f;
+ else if (i < 200)
+ a[i] = (i % 3) == 0 ? 2.0f : (i % 3) == 1 ? 4.0f : 1.0f;
+ else if (i < 280)
+ a[i] = (i & 1) ? 0.25f : 0.5f;
+ else if (i < 380)
+ a[i] = (i % 3) == 0 ? 2.0f : (i % 3) == 1 ? 4.0f : 1.0f;
+ else
+ switch (i % 6)
+ {
+ case 0: a[i] = 0.25f; break;
+ case 1: a[i] = 2.0f; break;
+ case 2: a[i] = -1.0f; break;
+ case 3: a[i] = -4.0f; break;
+ case 4: a[i] = 0.5f; break;
+ case 5: a[i] = 1.0f; break;
+ default: a[i] = 0.0f; break;
+ }
+ b[i] = -19.0f;
+ asm ("" : "+g" (i));
+ }
+ foo (a, b);
+ if (r * 16384.0f != 0.125f)
+ abort ();
+ float m = -175.25f;
+ for (int i = 0; i < 1024; ++i)
+ {
+ s *= a[i];
+ if (b[i] != s)
+ abort ();
+ else
+ {
+ a[i] = m - ((i % 3) == 1 ? 2.0f : (i % 3) == 2 ? 4.0f : 0.0f);
+ b[i] = -231.75f;
+ m += 0.75f;
+ }
+ }
+ if (bar () != 592.0f)
+ abort ();
+ s = -__builtin_inff ();
+ for (int i = 0; i < 1024; ++i)
+ {
+ if (s < a[i])
+ s = a[i];
+ if (b[i] != s)
+ abort ();
+ }
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/vect/vect-simd-11.c b/gcc/testsuite/gcc.dg/vect/vect-simd-11.c
new file mode 100644
index 0000000..e7d8aa0
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/vect-simd-11.c
@@ -0,0 +1,186 @@
+/* { dg-require-effective-target size32plus } */
+/* { dg-additional-options "-fopenmp-simd" } */
+/* { dg-additional-options "-mavx" { target avx_runtime } } */
+/* { dg-final { scan-tree-dump-times "vectorized \[1-3] loops" 2 "vect" { target i?86-*-* x86_64-*-* } } } */
+
+#ifndef main
+#include "tree-vect.h"
+#endif
+
+int r, a[1024], b[1024];
+unsigned short r2, b2[1024];
+unsigned char r3, b3[1024];
+
+__attribute__((noipa)) void
+foo (int *a, int *b, unsigned short *b2, unsigned char *b3)
+{
+ #pragma omp simd reduction (inscan, +:r, r2, r3)
+ for (int i = 0; i < 1024; i++)
+ {
+ { r += a[i]; r2 += a[i]; r3 += a[i]; }
+ #pragma omp scan inclusive(r, r2, r3)
+ {
+ b[i] = r;
+ b2[i] = r2;
+ b3[i] = r3;
+ }
+ }
+}
+
+__attribute__((noipa)) int
+bar (unsigned short *s2p, unsigned char *s3p)
+{
+ int s = 0;
+ unsigned short s2 = 0;
+ unsigned char s3 = 0;
+ #pragma omp simd reduction (inscan, +:s, s2, s3)
+ for (int i = 0; i < 1024; i++)
+ {
+ {
+ s += 2 * a[i];
+ s2 += 2 * a[i];
+ s3 += 2 * a[i];
+ }
+ #pragma omp scan inclusive(s, s2, s3)
+ { b[i] = s; b2[i] = s2; b3[i] = s3; }
+ }
+ *s2p = s2;
+ *s3p = s3;
+ return s;
+}
+
+__attribute__((noipa)) void
+baz (int *a, int *b, unsigned short *b2, unsigned char *b3)
+{
+ #pragma omp simd reduction (inscan, +:r, r2, r3) if (simd: 0)
+ for (int i = 0; i < 1024; i++)
+ {
+ {
+ r += a[i];
+ r2 += a[i];
+ r3 += a[i];
+ }
+ #pragma omp scan inclusive(r, r2, r3)
+ {
+ b[i] = r;
+ b2[i] = r2;
+ b3[i] = r3;
+ }
+ }
+}
+
+__attribute__((noipa)) int
+qux (unsigned short *s2p, unsigned char *s3p)
+{
+ int s = 0;
+ unsigned short s2 = 0;
+ unsigned char s3 = 0;
+ #pragma omp simd reduction (inscan, +:s, s2, s3) simdlen (1)
+ for (int i = 0; i < 1024; i++)
+ {
+ { s += 2 * a[i]; s2 += 2 * a[i]; s3 += 2 * a[i]; }
+ #pragma omp scan inclusive(s, s2, s3)
+ { b[i] = s; b2[i] = s2; b3[i] = s3; }
+ }
+ *s2p = s2;
+ *s3p = s3;
+ return s;
+}
+
+int
+main ()
+{
+ int s = 0;
+ unsigned short s2;
+ unsigned char s3;
+#ifndef main
+ check_vect ();
+#endif
+ for (int i = 0; i < 1024; ++i)
+ {
+ a[i] = i;
+ b[i] = -1;
+ b2[i] = -1;
+ b3[i] = -1;
+ asm ("" : "+g" (i));
+ }
+ foo (a, b, b2, b3);
+ if (r != 1024 * 1023 / 2
+ || r2 != (unsigned short) r
+ || r3 != (unsigned char) r)
+ abort ();
+ for (int i = 0; i < 1024; ++i)
+ {
+ s += i;
+ if (b[i] != s
+ || b2[i] != (unsigned short) s
+ || b3[i] != (unsigned char) s)
+ abort ();
+ else
+ {
+ b[i] = 25;
+ b2[i] = 24;
+ b3[i] = 26;
+ }
+ }
+ if (bar (&s2, &s3) != 1024 * 1023)
+ abort ();
+ if (s2 != (unsigned short) (1024 * 1023)
+ || s3 != (unsigned char) (1024 * 1023))
+ abort ();
+ s = 0;
+ for (int i = 0; i < 1024; ++i)
+ {
+ s += 2 * i;
+ if (b[i] != s
+ || b2[i] != (unsigned short) s
+ || b3[i] != (unsigned char) s)
+ abort ();
+ else
+ {
+ b[i] = -1;
+ b2[i] = -1;
+ b3[i] = -1;
+ }
+ }
+ r = 0;
+ r2 = 0;
+ r3 = 0;
+ baz (a, b, b2, b3);
+ if (r != 1024 * 1023 / 2
+ || r2 != (unsigned short) r
+ || r3 != (unsigned char) r)
+ abort ();
+ s = 0;
+ for (int i = 0; i < 1024; ++i)
+ {
+ s += i;
+ if (b[i] != s
+ || b2[i] != (unsigned short) s
+ || b3[i] != (unsigned char) s)
+ abort ();
+ else
+ {
+ b[i] = 25;
+ b2[i] = 24;
+ b3[i] = 26;
+ }
+ }
+ s2 = 0;
+ s3 = 0;
+ if (qux (&s2, &s3) != 1024 * 1023)
+ abort ();
+ if (s2 != (unsigned short) (1024 * 1023)
+ || s3 != (unsigned char) (1024 * 1023))
+ abort ();
+ s = 0;
+ for (int i = 0; i < 1024; ++i)
+ {
+ s += 2 * i;
+ if (b[i] != s
+ || b2[i] != (unsigned short) s
+ || b3[i] != (unsigned char) s)
+ abort ();
+ }
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/vect/vect-simd-12.c b/gcc/testsuite/gcc.dg/vect/vect-simd-12.c
new file mode 100644
index 0000000..cdfec81
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/vect-simd-12.c
@@ -0,0 +1,122 @@
+/* { dg-require-effective-target size32plus } */
+/* { dg-additional-options "-fopenmp-simd" } */
+/* { dg-additional-options "-mavx" { target avx_runtime } } */
+/* { dg-final { scan-tree-dump-times "vectorized \[1-3] loops" 2 "vect" { target i?86-*-* x86_64-*-* } } } */
+
+#ifndef main
+#include "tree-vect.h"
+#endif
+
+int r, a[1024], b[1024];
+
+__attribute__((noipa)) void
+foo (int *a, int *b)
+{
+ #pragma omp simd reduction (inscan, +:r)
+ for (int i = 0; i < 1024; i++)
+ {
+ b[i] = r;
+ #pragma omp scan exclusive(r)
+ r += a[i];
+ }
+}
+
+__attribute__((noipa)) int
+bar (void)
+{
+ int s = 0;
+ #pragma omp simd reduction (inscan, +:s)
+ for (int i = 0; i < 1024; i++)
+ {
+ b[i] = s;
+ #pragma omp scan exclusive(s)
+ s += 2 * a[i];
+ }
+ return s;
+}
+
+__attribute__((noipa)) void
+baz (int *a, int *b)
+{
+ #pragma omp simd reduction (inscan, +:r) if (simd: 0)
+ for (int i = 0; i < 1024; i++)
+ {
+ b[i] = r;
+ #pragma omp scan exclusive(r)
+ r += a[i];
+ }
+}
+
+__attribute__((noipa)) int
+qux (void)
+{
+ int s = 0;
+ #pragma omp simd reduction (inscan, +:s) simdlen (1)
+ for (int i = 0; i < 1024; i++)
+ {
+ b[i] = s;
+ #pragma omp scan exclusive(s)
+ s += 2 * a[i];
+ }
+ return s;
+}
+
+int
+main ()
+{
+ int s = 0;
+#ifndef main
+ check_vect ();
+#endif
+ for (int i = 0; i < 1024; ++i)
+ {
+ a[i] = i;
+ b[i] = -1;
+ asm ("" : "+g" (i));
+ }
+ foo (a, b);
+ if (r != 1024 * 1023 / 2)
+ abort ();
+ for (int i = 0; i < 1024; ++i)
+ {
+ if (b[i] != s)
+ abort ();
+ else
+ b[i] = 25;
+ s += i;
+ }
+ if (bar () != 1024 * 1023)
+ abort ();
+ s = 0;
+ for (int i = 0; i < 1024; ++i)
+ {
+ if (b[i] != s)
+ abort ();
+ else
+ b[i] = -1;
+ s += 2 * i;
+ }
+ r = 0;
+ baz (a, b);
+ if (r != 1024 * 1023 / 2)
+ abort ();
+ s = 0;
+ for (int i = 0; i < 1024; ++i)
+ {
+ if (b[i] != s)
+ abort ();
+ else
+ b[i] = -25;
+ s += i;
+ }
+ if (qux () != 1024 * 1023)
+ abort ();
+ s = 0;
+ for (int i = 0; i < 1024; ++i)
+ {
+ if (b[i] != s)
+ abort ();
+ s += 2 * i;
+ }
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/vect/vect-simd-13.c b/gcc/testsuite/gcc.dg/vect/vect-simd-13.c
new file mode 100644
index 0000000..aee5244
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/vect-simd-13.c
@@ -0,0 +1,124 @@
+/* { dg-require-effective-target size32plus } */
+/* { dg-additional-options "-fopenmp-simd" } */
+/* { dg-additional-options "-mavx" { target avx_runtime } } */
+/* { dg-final { scan-tree-dump-times "vectorized \[1-3] loops" 2 "vect" { target i?86-*-* x86_64-*-* } } } */
+
+#ifndef main
+#include "tree-vect.h"
+#endif
+
+int r, a[1024], b[1024];
+
+#pragma omp declare reduction (foo: int: omp_out += omp_in) initializer (omp_priv = 0)
+
+__attribute__((noipa)) void
+foo (int *a, int *b)
+{
+ #pragma omp simd reduction (inscan, foo:r)
+ for (int i = 0; i < 1024; i++)
+ {
+ b[i] = r;
+ #pragma omp scan exclusive(r)
+ r += a[i];
+ }
+}
+
+__attribute__((noipa)) int
+bar (void)
+{
+ int s = 0;
+ #pragma omp simd reduction (inscan, foo:s)
+ for (int i = 0; i < 1024; i++)
+ {
+ b[i] = s;
+ #pragma omp scan exclusive(s)
+ s += 2 * a[i];
+ }
+ return s;
+}
+
+__attribute__((noipa)) void
+baz (int *a, int *b)
+{
+ #pragma omp simd reduction (inscan, foo:r) if (simd: 0)
+ for (int i = 0; i < 1024; i++)
+ {
+ b[i] = r;
+ #pragma omp scan exclusive(r)
+ r += a[i];
+ }
+}
+
+__attribute__((noipa)) int
+qux (void)
+{
+ int s = 0;
+ #pragma omp simd reduction (inscan, foo:s) simdlen (1)
+ for (int i = 0; i < 1024; i++)
+ {
+ b[i] = s;
+ #pragma omp scan exclusive(s)
+ s += 2 * a[i];
+ }
+ return s;
+}
+
+int
+main ()
+{
+ int s = 0;
+#ifndef main
+ check_vect ();
+#endif
+ for (int i = 0; i < 1024; ++i)
+ {
+ a[i] = i;
+ b[i] = -1;
+ asm ("" : "+g" (i));
+ }
+ foo (a, b);
+ if (r != 1024 * 1023 / 2)
+ abort ();
+ for (int i = 0; i < 1024; ++i)
+ {
+ if (b[i] != s)
+ abort ();
+ else
+ b[i] = 25;
+ s += i;
+ }
+ if (bar () != 1024 * 1023)
+ abort ();
+ s = 0;
+ for (int i = 0; i < 1024; ++i)
+ {
+ if (b[i] != s)
+ abort ();
+ else
+ b[i] = -1;
+ s += 2 * i;
+ }
+ r = 0;
+ baz (a, b);
+ if (r != 1024 * 1023 / 2)
+ abort ();
+ s = 0;
+ for (int i = 0; i < 1024; ++i)
+ {
+ if (b[i] != s)
+ abort ();
+ else
+ b[i] = -25;
+ s += i;
+ }
+ if (qux () != 1024 * 1023)
+ abort ();
+ s = 0;
+ for (int i = 0; i < 1024; ++i)
+ {
+ if (b[i] != s)
+ abort ();
+ s += 2 * i;
+ }
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/vect/vect-simd-14.c b/gcc/testsuite/gcc.dg/vect/vect-simd-14.c
new file mode 100644
index 0000000..43663bb
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/vect-simd-14.c
@@ -0,0 +1,94 @@
+/* { dg-require-effective-target size32plus } */
+/* { dg-additional-options "-fopenmp-simd" } */
+/* { dg-additional-options "-mavx" { target avx_runtime } } */
+/* { dg-final { scan-tree-dump-times "vectorized \[1-3] loops" 2 "vect" { target i?86-*-* x86_64-*-* } } } */
+
+#ifndef main
+#include "tree-vect.h"
+#endif
+
+float r = 1.0f, a[1024], b[1024];
+
+__attribute__((noipa)) void
+foo (float *a, float *b)
+{
+ #pragma omp simd reduction (inscan, *:r)
+ for (int i = 0; i < 1024; i++)
+ {
+ b[i] = r;
+ #pragma omp scan exclusive(r)
+ r *= a[i];
+ }
+}
+
+__attribute__((noipa)) float
+bar (void)
+{
+ float s = -__builtin_inff ();
+ #pragma omp simd reduction (inscan, max:s)
+ for (int i = 0; i < 1024; i++)
+ {
+ b[i] = s;
+ #pragma omp scan exclusive(s)
+ s = s > a[i] ? s : a[i];
+ }
+ return s;
+}
+
+int
+main ()
+{
+ float s = 1.0f;
+#ifndef main
+ check_vect ();
+#endif
+ for (int i = 0; i < 1024; ++i)
+ {
+ if (i < 80)
+ a[i] = (i & 1) ? 0.25f : 0.5f;
+ else if (i < 200)
+ a[i] = (i % 3) == 0 ? 2.0f : (i % 3) == 1 ? 4.0f : 1.0f;
+ else if (i < 280)
+ a[i] = (i & 1) ? 0.25f : 0.5f;
+ else if (i < 380)
+ a[i] = (i % 3) == 0 ? 2.0f : (i % 3) == 1 ? 4.0f : 1.0f;
+ else
+ switch (i % 6)
+ {
+ case 0: a[i] = 0.25f; break;
+ case 1: a[i] = 2.0f; break;
+ case 2: a[i] = -1.0f; break;
+ case 3: a[i] = -4.0f; break;
+ case 4: a[i] = 0.5f; break;
+ case 5: a[i] = 1.0f; break;
+ default: a[i] = 0.0f; break;
+ }
+ b[i] = -19.0f;
+ asm ("" : "+g" (i));
+ }
+ foo (a, b);
+ if (r * 16384.0f != 0.125f)
+ abort ();
+ float m = -175.25f;
+ for (int i = 0; i < 1024; ++i)
+ {
+ if (b[i] != s)
+ abort ();
+ else
+ b[i] = -231.75f;
+ s *= a[i];
+ a[i] = m - ((i % 3) == 1 ? 2.0f : (i % 3) == 2 ? 4.0f : 0.0f);
+ m += 0.75f;
+ }
+ if (bar () != 592.0f)
+ abort ();
+ s = -__builtin_inff ();
+ for (int i = 0; i < 1024; ++i)
+ {
+ if (b[i] != s)
+ abort ();
+ if (s < a[i])
+ s = a[i];
+ }
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/vect/vect-simd-15.c b/gcc/testsuite/gcc.dg/vect/vect-simd-15.c
new file mode 100644
index 0000000..91e34cd
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/vect-simd-15.c
@@ -0,0 +1,186 @@
+/* { dg-require-effective-target size32plus } */
+/* { dg-additional-options "-fopenmp-simd" } */
+/* { dg-additional-options "-mavx" { target avx_runtime } } */
+/* { dg-final { scan-tree-dump-times "vectorized \[1-3] loops" 2 "vect" { target i?86-*-* x86_64-*-* } } } */
+
+#ifndef main
+#include "tree-vect.h"
+#endif
+
+int r, a[1024], b[1024];
+unsigned short r2, b2[1024];
+unsigned char r3, b3[1024];
+
+__attribute__((noipa)) void
+foo (int *a, int *b, unsigned short *b2, unsigned char *b3)
+{
+ #pragma omp simd reduction (inscan, +:r, r2, r3)
+ for (int i = 0; i < 1024; i++)
+ {
+ {
+ b[i] = r;
+ b2[i] = r2;
+ b3[i] = r3;
+ }
+ #pragma omp scan exclusive(r, r2, r3)
+ { r += a[i]; r2 += a[i]; r3 += a[i]; }
+ }
+}
+
+__attribute__((noipa)) int
+bar (unsigned short *s2p, unsigned char *s3p)
+{
+ int s = 0;
+ unsigned short s2 = 0;
+ unsigned char s3 = 0;
+ #pragma omp simd reduction (inscan, +:s, s2, s3)
+ for (int i = 0; i < 1024; i++)
+ {
+ { b[i] = s; b2[i] = s2; b3[i] = s3; }
+ #pragma omp scan exclusive(s, s2, s3)
+ {
+ s += 2 * a[i];
+ s2 += 2 * a[i];
+ s3 += 2 * a[i];
+ }
+ }
+ *s2p = s2;
+ *s3p = s3;
+ return s;
+}
+
+__attribute__((noipa)) void
+baz (int *a, int *b, unsigned short *b2, unsigned char *b3)
+{
+ #pragma omp simd reduction (inscan, +:r, r2, r3) if (simd: 0)
+ for (int i = 0; i < 1024; i++)
+ {
+ {
+ b[i] = r;
+ b2[i] = r2;
+ b3[i] = r3;
+ }
+ #pragma omp scan exclusive(r, r2, r3)
+ {
+ r += a[i];
+ r2 += a[i];
+ r3 += a[i];
+ }
+ }
+}
+
+__attribute__((noipa)) int
+qux (unsigned short *s2p, unsigned char *s3p)
+{
+ int s = 0;
+ unsigned short s2 = 0;
+ unsigned char s3 = 0;
+ #pragma omp simd reduction (inscan, +:s, s2, s3) simdlen (1)
+ for (int i = 0; i < 1024; i++)
+ {
+ { b[i] = s; b2[i] = s2; b3[i] = s3; }
+ #pragma omp scan exclusive(s, s2, s3)
+ { s += 2 * a[i]; s2 += 2 * a[i]; s3 += 2 * a[i]; }
+ }
+ *s2p = s2;
+ *s3p = s3;
+ return s;
+}
+
+int
+main ()
+{
+ int s = 0;
+ unsigned short s2;
+ unsigned char s3;
+#ifndef main
+ check_vect ();
+#endif
+ for (int i = 0; i < 1024; ++i)
+ {
+ a[i] = i;
+ b[i] = -1;
+ b2[i] = -1;
+ b3[i] = -1;
+ asm ("" : "+g" (i));
+ }
+ foo (a, b, b2, b3);
+ if (r != 1024 * 1023 / 2
+ || r2 != (unsigned short) r
+ || r3 != (unsigned char) r)
+ abort ();
+ for (int i = 0; i < 1024; ++i)
+ {
+ if (b[i] != s
+ || b2[i] != (unsigned short) s
+ || b3[i] != (unsigned char) s)
+ abort ();
+ else
+ {
+ b[i] = 25;
+ b2[i] = 24;
+ b3[i] = 26;
+ }
+ s += i;
+ }
+ if (bar (&s2, &s3) != 1024 * 1023)
+ abort ();
+ if (s2 != (unsigned short) (1024 * 1023)
+ || s3 != (unsigned char) (1024 * 1023))
+ abort ();
+ s = 0;
+ for (int i = 0; i < 1024; ++i)
+ {
+ if (b[i] != s
+ || b2[i] != (unsigned short) s
+ || b3[i] != (unsigned char) s)
+ abort ();
+ else
+ {
+ b[i] = -1;
+ b2[i] = -1;
+ b3[i] = -1;
+ }
+ s += 2 * i;
+ }
+ r = 0;
+ r2 = 0;
+ r3 = 0;
+ baz (a, b, b2, b3);
+ if (r != 1024 * 1023 / 2
+ || r2 != (unsigned short) r
+ || r3 != (unsigned char) r)
+ abort ();
+ s = 0;
+ for (int i = 0; i < 1024; ++i)
+ {
+ if (b[i] != s
+ || b2[i] != (unsigned short) s
+ || b3[i] != (unsigned char) s)
+ abort ();
+ else
+ {
+ b[i] = 25;
+ b2[i] = 24;
+ b3[i] = 26;
+ }
+ s += i;
+ }
+ s2 = 0;
+ s3 = 0;
+ if (qux (&s2, &s3) != 1024 * 1023)
+ abort ();
+ if (s2 != (unsigned short) (1024 * 1023)
+ || s3 != (unsigned char) (1024 * 1023))
+ abort ();
+ s = 0;
+ for (int i = 0; i < 1024; ++i)
+ {
+ if (b[i] != s
+ || b2[i] != (unsigned short) s
+ || b3[i] != (unsigned char) s)
+ abort ();
+ s += 2 * i;
+ }
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/vect/vect-simd-2.c b/gcc/testsuite/gcc.dg/vect/vect-simd-2.c
new file mode 100644
index 0000000..42bb782
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/vect-simd-2.c
@@ -0,0 +1,18 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target vect_int } */
+/* { dg-additional-options "-fopenmp-simd" } */
+
+#define N 1024
+int a[N];
+int bar (void);
+
+void
+foo (void)
+{
+ #pragma omp simd if (bar ())
+ for (int i = 0; i < N; ++i)
+ a[i] = a[i] + 1;
+}
+
+/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" } } */
+/* { dg-final { scan-tree-dump-times "created versioning for simd if condition check" 1 "vect" } } */
diff --git a/gcc/testsuite/gcc.dg/vect/vect-simd-3.c b/gcc/testsuite/gcc.dg/vect/vect-simd-3.c
new file mode 100644
index 0000000..ff7f0dc
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/vect-simd-3.c
@@ -0,0 +1,17 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target vect_int } */
+/* { dg-additional-options "-fopenmp-simd" } */
+
+#define N 1024
+int a[N];
+
+void
+foo (void)
+{
+ int c = 0;
+ #pragma omp simd if (c)
+ for (int i = 0; i < N; ++i)
+ a[i] = a[i] + 1;
+}
+
+/* { dg-final { scan-tree-dump-times "vectorized 0 loops" 1 "vect" } } */
diff --git a/gcc/testsuite/gcc.dg/vect/vect-simd-4.c b/gcc/testsuite/gcc.dg/vect/vect-simd-4.c
new file mode 100644
index 0000000..b78b7b1
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/vect-simd-4.c
@@ -0,0 +1,18 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target vect_int } */
+/* { dg-additional-options "-fopenmp-simd" } */
+
+#define N 1024
+int a[N];
+
+void
+foo (void)
+{
+ int c = 1;
+ #pragma omp simd if (c)
+ for (int i = 0; i < N; ++i)
+ a[i] = a[i] + 1;
+}
+
+/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" } } */
+/* { dg-final { scan-tree-dump-not "created versioning for simd if condition check" "vect" } } */
diff --git a/gcc/testsuite/gcc.dg/vect/vect-simd-5.c b/gcc/testsuite/gcc.dg/vect/vect-simd-5.c
new file mode 100644
index 0000000..bacb247
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/vect-simd-5.c
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-fopenmp-simd" } */
+/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target vect_condition } } } */
+
+int x;
+
+void
+foo (int *a)
+{
+ #pragma omp simd lastprivate (x)
+ for (int i = 0; i < 1024; ++i)
+ if (a[i])
+ x = i;
+}
diff --git a/gcc/testsuite/gcc.dg/vect/vect-simd-6.c b/gcc/testsuite/gcc.dg/vect/vect-simd-6.c
new file mode 100644
index 0000000..b7e9514
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/vect-simd-6.c
@@ -0,0 +1,52 @@
+/* { dg-additional-options "-fopenmp-simd" } */
+/* { dg-final { scan-tree-dump-times "vectorized \[12] loops" 2 "vect" { target vect_condition } } } */
+
+#include "tree-vect.h"
+
+int v;
+
+__attribute__((noipa)) int
+foo (int *a)
+{
+ int x = 5;
+ #pragma omp simd lastprivate (conditional: x)
+ for (int i = 0; i < 128; i++)
+ if (a[i])
+ x = a[i];
+ return x;
+}
+
+__attribute__((noipa)) int
+bar (int *a, int *b)
+{
+ int x = 0;
+ #pragma omp simd lastprivate (conditional: x, v)
+ for (int i = 16; i < 128; ++i)
+ {
+ if (a[i])
+ x = a[i];
+ if (b[i])
+ v = b[i] + 10;
+ }
+ return x;
+}
+
+int
+main ()
+{
+ int a[128], b[128], i;
+ check_vect ();
+ for (i = 0; i < 128; i++)
+ {
+ a[i] = ((i % 11) == 2) ? i + 10 : 0;
+ asm volatile ("" : "+g" (i));
+ b[i] = ((i % 13) == 5) ? i * 2 : 0;
+ }
+ if (foo (a) != 133)
+ abort ();
+ if (bar (b, a) != 244)
+ abort ();
+ if (v != 143)
+ abort ();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/vect/vect-simd-7.c b/gcc/testsuite/gcc.dg/vect/vect-simd-7.c
new file mode 100644
index 0000000..15e0c51
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/vect-simd-7.c
@@ -0,0 +1,51 @@
+/* { dg-additional-options "-fopenmp-simd" } */
+
+#include "tree-vect.h"
+
+int v;
+
+__attribute__((noipa)) int
+foo (int *a)
+{
+ int x = 5;
+ #pragma omp simd lastprivate (conditional: x) safelen (1)
+ for (int i = 0; i < 128; i++)
+ if (a[i])
+ x = a[i];
+ return x;
+}
+
+__attribute__((noipa)) int
+bar (int *a, int *b)
+{
+ int x = 0;
+ #pragma omp simd lastprivate (conditional: x, v) if (0)
+ for (int i = 16; i < 128; ++i)
+ {
+ if (a[i])
+ x = a[i];
+ if (b[i])
+ v = b[i] + 10;
+ }
+ return x;
+}
+
+int
+main ()
+{
+ int a[128], b[128], i;
+ check_vect ();
+ for (i = 0; i < 128; i++)
+ {
+ a[i] = ((i % 11) == 2) ? i + 10 : 0;
+ asm volatile ("" : "+g" (i));
+ b[i] = ((i % 13) == 5) ? i * 2 : 0;
+ }
+ if (foo (a) != 133)
+ abort ();
+ if (bar (b, a) != 244)
+ abort ();
+ if (v != 143)
+ abort ();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/vect/vect-simd-8.c b/gcc/testsuite/gcc.dg/vect/vect-simd-8.c
new file mode 100644
index 0000000..5d10ad9
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/vect-simd-8.c
@@ -0,0 +1,122 @@
+/* { dg-require-effective-target size32plus } */
+/* { dg-additional-options "-fopenmp-simd" } */
+/* { dg-additional-options "-mavx" { target avx_runtime } } */
+/* { dg-final { scan-tree-dump-times "vectorized \[1-3] loops" 2 "vect" { target i?86-*-* x86_64-*-* } } } */
+
+#ifndef main
+#include "tree-vect.h"
+#endif
+
+int r, a[1024], b[1024];
+
+__attribute__((noipa)) void
+foo (int *a, int *b)
+{
+ #pragma omp simd reduction (inscan, +:r)
+ for (int i = 0; i < 1024; i++)
+ {
+ r += a[i];
+ #pragma omp scan inclusive(r)
+ b[i] = r;
+ }
+}
+
+__attribute__((noipa)) int
+bar (void)
+{
+ int s = 0;
+ #pragma omp simd reduction (inscan, +:s)
+ for (int i = 0; i < 1024; i++)
+ {
+ s += 2 * a[i];
+ #pragma omp scan inclusive(s)
+ b[i] = s;
+ }
+ return s;
+}
+
+__attribute__((noipa)) void
+baz (int *a, int *b)
+{
+ #pragma omp simd reduction (inscan, +:r) if (simd: 0)
+ for (int i = 0; i < 1024; i++)
+ {
+ r += a[i];
+ #pragma omp scan inclusive(r)
+ b[i] = r;
+ }
+}
+
+__attribute__((noipa)) int
+qux (void)
+{
+ int s = 0;
+ #pragma omp simd reduction (inscan, +:s) simdlen (1)
+ for (int i = 0; i < 1024; i++)
+ {
+ s += 2 * a[i];
+ #pragma omp scan inclusive(s)
+ b[i] = s;
+ }
+ return s;
+}
+
+int
+main ()
+{
+ int s = 0;
+#ifndef main
+ check_vect ();
+#endif
+ for (int i = 0; i < 1024; ++i)
+ {
+ a[i] = i;
+ b[i] = -1;
+ asm ("" : "+g" (i));
+ }
+ foo (a, b);
+ if (r != 1024 * 1023 / 2)
+ abort ();
+ for (int i = 0; i < 1024; ++i)
+ {
+ s += i;
+ if (b[i] != s)
+ abort ();
+ else
+ b[i] = 25;
+ }
+ if (bar () != 1024 * 1023)
+ abort ();
+ s = 0;
+ for (int i = 0; i < 1024; ++i)
+ {
+ s += 2 * i;
+ if (b[i] != s)
+ abort ();
+ else
+ b[i] = -1;
+ }
+ r = 0;
+ baz (a, b);
+ if (r != 1024 * 1023 / 2)
+ abort ();
+ s = 0;
+ for (int i = 0; i < 1024; ++i)
+ {
+ s += i;
+ if (b[i] != s)
+ abort ();
+ else
+ b[i] = -25;
+ }
+ if (qux () != 1024 * 1023)
+ abort ();
+ s = 0;
+ for (int i = 0; i < 1024; ++i)
+ {
+ s += 2 * i;
+ if (b[i] != s)
+ abort ();
+ }
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/vect/vect-simd-9.c b/gcc/testsuite/gcc.dg/vect/vect-simd-9.c
new file mode 100644
index 0000000..52eb24f
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/vect-simd-9.c
@@ -0,0 +1,124 @@
+/* { dg-require-effective-target size32plus } */
+/* { dg-additional-options "-fopenmp-simd" } */
+/* { dg-additional-options "-mavx" { target avx_runtime } } */
+/* { dg-final { scan-tree-dump-times "vectorized \[1-3] loops" 2 "vect" { target i?86-*-* x86_64-*-* } } } */
+
+#ifndef main
+#include "tree-vect.h"
+#endif
+
+int r, a[1024], b[1024];
+
+#pragma omp declare reduction (foo: int: omp_out += omp_in) initializer (omp_priv = 0)
+
+__attribute__((noipa)) void
+foo (int *a, int *b)
+{
+ #pragma omp simd reduction (inscan, foo:r)
+ for (int i = 0; i < 1024; i++)
+ {
+ r += a[i];
+ #pragma omp scan inclusive(r)
+ b[i] = r;
+ }
+}
+
+__attribute__((noipa)) int
+bar (void)
+{
+ int s = 0;
+ #pragma omp simd reduction (inscan, foo:s)
+ for (int i = 0; i < 1024; i++)
+ {
+ s += 2 * a[i];
+ #pragma omp scan inclusive(s)
+ b[i] = s;
+ }
+ return s;
+}
+
+__attribute__((noipa)) void
+baz (int *a, int *b)
+{
+ #pragma omp simd reduction (inscan, foo:r) if (simd: 0)
+ for (int i = 0; i < 1024; i++)
+ {
+ r += a[i];
+ #pragma omp scan inclusive(r)
+ b[i] = r;
+ }
+}
+
+__attribute__((noipa)) int
+qux (void)
+{
+ int s = 0;
+ #pragma omp simd reduction (inscan, foo:s) simdlen (1)
+ for (int i = 0; i < 1024; i++)
+ {
+ s += 2 * a[i];
+ #pragma omp scan inclusive(s)
+ b[i] = s;
+ }
+ return s;
+}
+
+int
+main ()
+{
+ int s = 0;
+#ifndef main
+ check_vect ();
+#endif
+ for (int i = 0; i < 1024; ++i)
+ {
+ a[i] = i;
+ b[i] = -1;
+ asm ("" : "+g" (i));
+ }
+ foo (a, b);
+ if (r != 1024 * 1023 / 2)
+ abort ();
+ for (int i = 0; i < 1024; ++i)
+ {
+ s += i;
+ if (b[i] != s)
+ abort ();
+ else
+ b[i] = 25;
+ }
+ if (bar () != 1024 * 1023)
+ abort ();
+ s = 0;
+ for (int i = 0; i < 1024; ++i)
+ {
+ s += 2 * i;
+ if (b[i] != s)
+ abort ();
+ else
+ b[i] = -1;
+ }
+ r = 0;
+ baz (a, b);
+ if (r != 1024 * 1023 / 2)
+ abort ();
+ s = 0;
+ for (int i = 0; i < 1024; ++i)
+ {
+ s += i;
+ if (b[i] != s)
+ abort ();
+ else
+ b[i] = -25;
+ }
+ if (qux () != 1024 * 1023)
+ abort ();
+ s = 0;
+ for (int i = 0; i < 1024; ++i)
+ {
+ s += 2 * i;
+ if (b[i] != s)
+ abort ();
+ }
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/vect/vect-version-1.c b/gcc/testsuite/gcc.dg/vect/vect-version-1.c
new file mode 100644
index 0000000..4540a11
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/vect-version-1.c
@@ -0,0 +1,20 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target vect_double } */
+/* { dg-require-effective-target vect_condition } */
+
+void foo (double *x, double *y, int m, int n, int o, int p)
+{
+ for (int i = 0; i < m; ++i)
+ for (int j = 0; j < n; ++j)
+ for (int k = 0; k < o; ++k)
+ for (int l = 0; l < p; ++l)
+ {
+ double tem = x[l] + y[l];
+ if (tem != 0.)
+ y[l] = x[l];
+ else
+ y[l] = 0.;
+ }
+}
+
+/* { dg-final { scan-tree-dump "applying loop versioning to outer loop 1" "vect" } } */
diff --git a/gcc/testsuite/gcc.dg/vect/vect-version-2.c b/gcc/testsuite/gcc.dg/vect/vect-version-2.c
new file mode 100644
index 0000000..0ea39e3
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/vect-version-2.c
@@ -0,0 +1,20 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target vect_double } */
+/* { dg-require-effective-target vect_condition } */
+
+void foo (double *x, double *y, int m, int n, int o, int p)
+{
+ for (int i = 0; i < m; ++i)
+ for (int j = 0; j < n; ++j)
+ for (int k = 0; k < o; ++k)
+ for (int l = 0; l < k; ++l)
+ {
+ double tem = x[l] + y[l];
+ if (tem != 0.)
+ y[l] = x[l];
+ else
+ y[l] = 0.;
+ }
+}
+
+/* { dg-final { scan-tree-dump "reusing loop version created by if conversion" "vect" } } */
diff --git a/gcc/testsuite/gcc.dg/vect/vect.exp b/gcc/testsuite/gcc.dg/vect/vect.exp
index 8e012d4..9569ea5 100644
--- a/gcc/testsuite/gcc.dg/vect/vect.exp
+++ b/gcc/testsuite/gcc.dg/vect/vect.exp
@@ -45,7 +45,7 @@ if ![check_vect_support_and_set_flags] {
}
# These flags are used for all targets.
-lappend DEFAULT_VECTCFLAGS "-ftree-vectorize" "-fno-vect-cost-model" "-fno-common"
+lappend DEFAULT_VECTCFLAGS "-ftree-vectorize" "-fno-tree-loop-distribute-patterns" "-fno-vect-cost-model" "-fno-common"
# Initialize `dg'.
dg-init
diff --git a/gcc/testsuite/gcc.dg/warn-abs-1.c b/gcc/testsuite/gcc.dg/warn-abs-1.c
index a7f2ab2..ccd61ef 100644
--- a/gcc/testsuite/gcc.dg/warn-abs-1.c
+++ b/gcc/testsuite/gcc.dg/warn-abs-1.c
@@ -34,9 +34,9 @@ tst_notint (float *pf, double *pd, _Complex double *pc)
void
tst_notfloat (int *pi, long *pl, complex double *pc)
{
- *pi = fabsf (*pi); /* { dg-warning "using floating point absolute value function" } */
- *pl = fabs (*pl); /* { dg-warning "using floating point absolute value function" } */
- *pc = fabs (*pc); /* { dg-warning "using floating point absolute value function" } */
+ *pi = fabsf (*pi); /* { dg-warning "using floating-point absolute value function" } */
+ *pl = fabs (*pl); /* { dg-warning "using floating-point absolute value function" } */
+ *pc = fabs (*pc); /* { dg-warning "using floating-point absolute value function" } */
}
void
diff --git a/gcc/testsuite/gcc.dg/warn-sprintf-no-nul.c b/gcc/testsuite/gcc.dg/warn-sprintf-no-nul.c
index b331bb5..a38679f 100644
--- a/gcc/testsuite/gcc.dg/warn-sprintf-no-nul.c
+++ b/gcc/testsuite/gcc.dg/warn-sprintf-no-nul.c
@@ -26,7 +26,7 @@ void sink (int, ...);
const char a[5] = "12345"; /* { dg-message "declared here" } */
const char b[6] = "123456"; /* { dg-message "declared here" } */
const char a2[][3] = {
- "", "1", "12", "123", "123\000" /* { dg-warning "initializer-string for array of chars is too long" } */
+ "", "1", "12", "123", "123\000" /* { dg-warning "initializer-string for array of 'char' is too long" } */
};
diff --git a/gcc/testsuite/gcc.dg/weak/weak-19.c b/gcc/testsuite/gcc.dg/weak/weak-19.c
new file mode 100644
index 0000000..08906b7
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/weak/weak-19.c
@@ -0,0 +1,8 @@
+/* { dg-do compile }
+ { dg-require-weak "" } */
+
+/* Verify that the following invalid pragmas are diagnosed. */
+
+#pragma weak foo = 1 /* { dg-warning "malformed '#pragma weak'" } */
+#pragma weak foo = + /* { dg-warning "malformed '#pragma weak'" } */
+#pragma weak foo = ? /* { dg-warning "malformed '#pragma weak'" } */
diff --git a/gcc/testsuite/gcc.misc-tests/gcov-pr90574-1.c b/gcc/testsuite/gcc.misc-tests/gcov-pr90574-1.c
new file mode 100644
index 0000000..41ac9bb
--- /dev/null
+++ b/gcc/testsuite/gcc.misc-tests/gcov-pr90574-1.c
@@ -0,0 +1,20 @@
+/* { dg-options "-fprofile-arcs -ftest-coverage" } */
+/* { dg-do run { target native } } */
+
+int main(int argc, char **argv)
+{
+ if (argc == 0)
+ {
+ int *ptr;
+label: /* count(#####) */
+ {
+ }
+ }
+ if (argc == 1)
+ {
+ __builtin_printf("hello\n");
+ }
+ return 0;
+}
+
+/* { dg-final { run-gcov gcov-pr90574-1.c } } */
diff --git a/gcc/testsuite/gcc.misc-tests/gcov-pr90574-2.c b/gcc/testsuite/gcc.misc-tests/gcov-pr90574-2.c
new file mode 100644
index 0000000..2db70c9
--- /dev/null
+++ b/gcc/testsuite/gcc.misc-tests/gcov-pr90574-2.c
@@ -0,0 +1,15 @@
+/* { dg-options "-fprofile-arcs -ftest-coverage" } */
+/* { dg-do run { target native } } */
+
+int main(int argc, char **argv)
+{
+ switch (argc)
+ {
+ case 0:
+ foo: /* count(#####) */
+ case 1:;
+ }
+ return 0;
+}
+
+/* { dg-final { run-gcov gcov-pr90574-2.c } } */
diff --git a/gcc/testsuite/gcc.misc-tests/linkage.exp b/gcc/testsuite/gcc.misc-tests/linkage.exp
index cb09c9b..c2c0ea0 100644
--- a/gcc/testsuite/gcc.misc-tests/linkage.exp
+++ b/gcc/testsuite/gcc.misc-tests/linkage.exp
@@ -44,7 +44,7 @@ if { [isnative] && ![is_remote host] } then {
set native_cflags "-xarch=v9"
}
}
- if {[istarget "i?86*-*-solaris2*"] || [istarget "x86_64-*-solaris2.1\[0-9\]*"]} {
+ if {[istarget "i?86*-*-solaris2*"] || [istarget "x86_64-*-solaris2*"]} {
set file_string [exec file "linkage-x.o"]
if [ string match "*64*" $file_string ] {
set native_cflags "-xarch=amd64"
diff --git a/gcc/testsuite/gcc.target/aarch64/pcs_attribute-2.c b/gcc/testsuite/gcc.target/aarch64/pcs_attribute-2.c
new file mode 100644
index 0000000..e85465f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/pcs_attribute-2.c
@@ -0,0 +1,93 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target aarch64_variant_pcs } */
+
+/* Test that .variant_pcs is emitted for vector PCS symbol references. */
+
+#define ATTR __attribute__ ((aarch64_vector_pcs))
+
+void f_undef_basepcs (void);
+
+void f_def_basepcs (void)
+{
+}
+
+ATTR void f_undef_vpcs (void);
+
+ATTR void f_def_vpcs (void)
+{
+}
+
+__attribute__ ((alias ("f_def_vpcs")))
+ATTR void f_alias_vpcs (void);
+
+__attribute__ ((weak, alias ("f_def_vpcs")))
+ATTR void f_weak_alias_vpcs (void);
+
+__attribute__ ((weak))
+ATTR void f_weak_undef_vpcs (void);
+
+__attribute__ ((visibility ("protected")))
+ATTR void f_protected_vpcs (void)
+{
+}
+
+__attribute__ ((visibility ("hidden")))
+ATTR void f_hidden_vpcs (void)
+{
+}
+
+ATTR static void f_local_vpcs (void)
+{
+}
+
+__attribute__((weakref ("f_undef_vpcs")))
+ATTR static void f_local_weakref_undef_vpcs (void);
+
+__attribute__((weakref ("f_hidden_vpcs")))
+ATTR static void f_local_weakref_def_vpcs (void);
+
+ATTR void bar_undef_vpcs (void) __asm__ ("f_undef_renamed_vpcs");
+
+ATTR void bar_def_vpcs (void) __asm__ ("f_def_renamed_vpcs");
+ATTR void bar_def_vpcs (void)
+{
+}
+
+void (*refs_basepcs[]) (void) = {
+ f_undef_basepcs,
+ f_def_basepcs,
+};
+
+void (*ATTR refs_vpcs[]) (void) = {
+ f_undef_vpcs,
+ f_def_vpcs,
+ f_alias_vpcs,
+ f_weak_alias_vpcs,
+ f_weak_undef_vpcs,
+ f_protected_vpcs,
+ f_hidden_vpcs,
+ f_local_vpcs,
+ f_local_weakref_undef_vpcs,
+ f_local_weakref_def_vpcs,
+ bar_undef_vpcs,
+ bar_def_vpcs,
+};
+
+/* Note: local symbols don't need .variant_pcs, but gcc generates it, so
+ we check them here. An undefined weakref does not show up in the
+ symbol table, only the target symbol, so it does not need .variant_pcs. */
+
+/* { dg-final { scan-assembler-not {\.variant_pcs\tf_undef_basepcs} } } */
+/* { dg-final { scan-assembler-not {\.variant_pcs\tf_def_basepcs} } } */
+/* { dg-final { scan-assembler-times {\.variant_pcs\tf_undef_vpcs} 1 } } */
+/* { dg-final { scan-assembler-times {\.variant_pcs\tf_def_vpcs} 1 } } */
+/* { dg-final { scan-assembler-times {\.variant_pcs\tf_alias_vpcs} 1 } } */
+/* { dg-final { scan-assembler-times {\.variant_pcs\tf_weak_alias_vpcs} 1 } } */
+/* { dg-final { scan-assembler-times {\.variant_pcs\tf_weak_undef_vpcs} 1 } } */
+/* { dg-final { scan-assembler-times {\.variant_pcs\tf_protected_vpcs} 1 } } */
+/* { dg-final { scan-assembler-times {\.variant_pcs\tf_hidden_vpcs} 1 } } */
+/* { dg-final { scan-assembler-times {\.variant_pcs\tf_local_vpcs} 1 } } */
+/* { dg-final { scan-assembler-not {\.variant_pcs\tf_local_weakref_undef_vpcs} } } */
+/* { dg-final { scan-assembler-times {\.variant_pcs\tf_local_weakref_def_vpcs} 1 } } */
+/* { dg-final { scan-assembler-times {\.variant_pcs\tf_undef_renamed_vpcs} 1 } } */
+/* { dg-final { scan-assembler-times {\.variant_pcs\tf_def_renamed_vpcs} 1 } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/pcs_attribute-3.c b/gcc/testsuite/gcc.target/aarch64/pcs_attribute-3.c
new file mode 100644
index 0000000..8e306af
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/pcs_attribute-3.c
@@ -0,0 +1,58 @@
+/* { dg-do compile } */
+/* { dg-require-ifunc "" } */
+/* { dg-require-effective-target aarch64_variant_pcs } */
+
+/* Test that .variant_pcs is emitted for vector PCS symbol references. */
+
+#define ATTR __attribute__ ((aarch64_vector_pcs))
+
+static void f_local_basepcs (void)
+{
+}
+
+static void (*f_ifunc_basepcs_resolver ()) (void)
+{
+ return (void (*)(void))f_local_basepcs;
+}
+
+__attribute__ ((ifunc ("f_ifunc_basepcs_resolver")))
+void f_ifunc_basepcs (void);
+
+ATTR static void f_local_vpcs (void)
+{
+}
+
+static void (*f_ifunc_vpcs_resolver ()) (void)
+{
+ return (void (*)(void))f_local_vpcs;
+}
+
+__attribute__ ((ifunc ("f_ifunc_vpcs_resolver")))
+ATTR void f_ifunc_vpcs (void);
+
+__attribute__ ((visibility ("hidden")))
+__attribute__ ((ifunc ("f_ifunc_vpcs_resolver")))
+ATTR void f_hidden_ifunc_vpcs (void);
+
+__attribute__ ((ifunc ("f_ifunc_vpcs_resolver")))
+ATTR static void f_local_ifunc_vpcs (void);
+
+void (*refs_basepcs[]) (void) = {
+ f_ifunc_basepcs,
+};
+
+void (*ATTR refs_vpcs[]) (void) = {
+ f_ifunc_vpcs,
+ f_hidden_ifunc_vpcs,
+ f_local_ifunc_vpcs,
+};
+
+/* Note: local symbols don't need .variant_pcs, but gcc generates it, so
+ we check them here. */
+
+/* { dg-final { scan-assembler-not {\.variant_pcs\tf_local_basepcs} } } */
+/* { dg-final { scan-assembler-not {\.variant_pcs\tf_ifunc_basepcs} } } */
+/* { dg-final { scan-assembler-times {\.variant_pcs\tf_local_vpcs} 1 } } */
+/* { dg-final { scan-assembler-times {\.variant_pcs\tf_ifunc_vpcs} 1 } } */
+/* { dg-final { scan-assembler-times {\.variant_pcs\tf_hidden_ifunc_vpcs} 1 } } */
+/* { dg-final { scan-assembler-times {\.variant_pcs\tf_local_ifunc_vpcs} 1 } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/pr88838.c b/gcc/testsuite/gcc.target/aarch64/pr88838.c
new file mode 100644
index 0000000..d7db847
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/pr88838.c
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-options "-S -O3 -march=armv8.2-a+sve" } */
+
+void
+f (int *restrict x, int *restrict y, int *restrict z, int n)
+{
+ for (int i = 0; i < n; i += 1)
+ x[i] = y[i] + z[i];
+}
+
+/* { dg-final { scan-assembler-not "sxtw" } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/return_address_sign_b_1.c b/gcc/testsuite/gcc.target/aarch64/return_address_sign_b_1.c
new file mode 100644
index 0000000..32d788d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/return_address_sign_b_1.c
@@ -0,0 +1,52 @@
+/* Testing return address signing where no combined instructions used. */
+/* { dg-do compile } */
+/* { dg-options "-O2 -mbranch-protection=pac-ret+leaf+b-key" } */
+/* { dg-require-effective-target lp64 } */
+
+int foo (int);
+
+/* sibcall only. */
+int __attribute__ ((target ("arch=armv8.3-a")))
+func1 (int a, int b)
+{
+ /* pacibsp */
+ return foo (a + b);
+ /* autibsp */
+}
+
+/* non-leaf function with sibcall. */
+int __attribute__ ((target ("arch=armv8.3-a")))
+func2 (int a, int b)
+{
+ /* pacibsp */
+ if (a < b)
+ return b;
+
+ a = foo (b);
+
+ return foo (a);
+ /* autibsp */
+}
+
+/* non-leaf function, legacy arch. */
+int __attribute__ ((target ("arch=armv8.2-a")))
+func3 (int a, int b, int c)
+{
+ /* pacibsp */
+ return a + foo (b) + c;
+ /* autibsp */
+}
+
+/* eh_return. */
+void __attribute__ ((target ("arch=armv8.3-a")))
+func4 (long offset, void *handler, int *ptr, int imm1, int imm2)
+{
+ /* pacibsp */
+ *ptr = imm1 + foo (imm1) + imm2;
+ __builtin_eh_return (offset, handler);
+ /* autibsp */
+ return;
+}
+
+/* { dg-final { scan-assembler-times "pacibsp" 4 } } */
+/* { dg-final { scan-assembler-times "autibsp" 4 } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/return_address_sign_b_2.c b/gcc/testsuite/gcc.target/aarch64/return_address_sign_b_2.c
new file mode 100644
index 0000000..9ed64ce
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/return_address_sign_b_2.c
@@ -0,0 +1,18 @@
+/* Testing return address signing where combined instructions used. */
+/* { dg-do compile } */
+/* { dg-options "-O2 -mbranch-protection=pac-ret+leaf+b-key" } */
+/* { dg-require-effective-target lp64 } */
+
+int foo (int);
+int bar (int, int);
+
+int __attribute__ ((target ("arch=armv8.3-a")))
+func1 (int a, int b, int c)
+{
+ /* pacibsp */
+ return a + foo (b) + c;
+ /* retab */
+}
+
+/* { dg-final { scan-assembler-times "pacibsp" 1 } } */
+/* { dg-final { scan-assembler-times "retab" 1 } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/return_address_sign_b_3.c b/gcc/testsuite/gcc.target/aarch64/return_address_sign_b_3.c
new file mode 100644
index 0000000..7183cc2
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/return_address_sign_b_3.c
@@ -0,0 +1,22 @@
+/* Testing the disable of return address signing. */
+/* { dg-do compile } */
+/* { dg-options "-O2 -mbranch-protection=pac-ret+leaf+b-key" } */
+/* { dg-require-effective-target lp64 } */
+
+int bar (int, int);
+
+int __attribute__ ((target ("arch=armv8.3-a,branch-protection=pac-ret+b-key")))
+func1_leaf (int a, int b, int c, int d)
+{
+ return a + b + c + d;
+}
+
+int __attribute__ ((target ("arch=armv8.3-a,branch-protection=none")))
+func2_none (int a, int b, int c, int d)
+{
+ return c + bar (a, b) + d;
+}
+
+/* { dg-final { scan-assembler-not "pacibsp" } } */
+/* { dg-final { scan-assembler-not "autibsp" } } */
+/* { dg-final { scan-assembler-not "retab" } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/return_address_sign_builtin.c b/gcc/testsuite/gcc.target/aarch64/return_address_sign_builtin.c
new file mode 100644
index 0000000..0a01bfc
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/return_address_sign_builtin.c
@@ -0,0 +1,16 @@
+/* { dg-do compile } */
+/* { dg-options "-mbranch-protection=pac-ret+leaf+b-key" } */
+
+/* The correct pauth instruction should be generated no matter the return
+ address signing key/scope specified in the options. */
+
+int foo() {
+ /* { dg-final { scan-assembler-times "pacia1716" 1 } } */
+ __builtin_aarch64_pacia1716(0, 0);
+ /* { dg-final { scan-assembler-times "pacib1716" 1 } } */
+ __builtin_aarch64_pacib1716(0, 0);
+ /* { dg-final { scan-assembler-times "autia1716" 1 } } */
+ __builtin_aarch64_autia1716(0, 0);
+ /* { dg-final { scan-assembler-times "autib1716" 1 } } */
+ __builtin_aarch64_autib1716(0, 0);
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/signbitv2sf.c b/gcc/testsuite/gcc.target/aarch64/signbitv2sf.c
new file mode 100644
index 0000000..2587bfe
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/signbitv2sf.c
@@ -0,0 +1,40 @@
+/* { dg-do run } */
+/* { dg-additional-options "-O3 --save-temps" } */
+
+extern void abort ();
+
+#define N 8
+float in[N] = {1.0, -1.0, -2.0, 3.0, -5.0, -8.0, 13.0, 21.0};
+int out[N];
+
+void
+foo (int *i, float *f)
+{
+ i[0] = __builtin_signbit (f[0]);
+ i[1] = __builtin_signbit (f[1]);
+}
+
+/* { dg-final { scan-assembler-not {-2147483648} } } */
+/* { dg-final { scan-assembler {\tushr\tv[0-9]+.2s, v[0-9]+.2s, 31} } } */
+
+int
+main ()
+{
+ int i;
+
+ foo (out, in);
+ foo (out + 2, in + 2);
+ foo (out + 4, in + 4);
+ foo (out + 6, in + 6);
+
+ for (i = 0; i < N; i++)
+ {
+ if (in[i] >= 0.0 && out[i])
+ abort ();
+ if (in[i] < 0.0 && !out[i])
+ abort ();
+ }
+
+ return 0;
+}
+
diff --git a/gcc/testsuite/gcc.target/aarch64/signbitv4sf.c b/gcc/testsuite/gcc.target/aarch64/signbitv4sf.c
new file mode 100644
index 0000000..18cffdc
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/signbitv4sf.c
@@ -0,0 +1,38 @@
+/* { dg-do run } */
+/* { dg-additional-options "-O3 --save-temps" } */
+
+extern void abort ();
+
+#define N 1024
+float in[N] = {1.0, -1.0, -2.0, 3.0, -5.0, -8.0, 13.0, 21.0};
+int out[N];
+
+void
+foo ()
+{
+ int i;
+ for (i = 0; i < N; i++)
+ out[i] = __builtin_signbit (in[i]);
+}
+
+/* { dg-final { scan-assembler-not {-2147483648} } } */
+/* { dg-final { scan-assembler {\tushr\tv[0-9]+.4s, v[0-9]+.4s, 31} } } */
+
+int
+main ()
+{
+ int i;
+
+ foo ();
+
+ for (i = 0; i < N; i++)
+ {
+ if (in[i] >= 0.0 && out[i])
+ abort ();
+ if (in[i] < 0.0 && !out[i])
+ abort ();
+ }
+
+ return 0;
+}
+
diff --git a/gcc/testsuite/gcc.target/aarch64/ssadv16qi-dotprod.c b/gcc/testsuite/gcc.target/aarch64/ssadv16qi-dotprod.c
new file mode 100644
index 0000000..08b6831
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/ssadv16qi-dotprod.c
@@ -0,0 +1,31 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target arm_v8_2a_dotprod_neon_ok } */
+/* { dg-add-options arm_v8_2a_dotprod_neon } */
+/* { dg-additional-options "-O3" } */
+
+#pragma GCC target "+nosve"
+
+#define N 1024
+
+signed char pix1[N], pix2[N];
+
+int foo (void)
+{
+ int i_sum = 0;
+ int i;
+
+ for (i = 0; i < N; i++)
+ i_sum += __builtin_abs (pix1[i] - pix2[i]);
+
+ return i_sum;
+}
+
+/* { dg-final { scan-assembler-not {\tsshll\t} } } */
+/* { dg-final { scan-assembler-not {\tsshll2\t} } } */
+/* { dg-final { scan-assembler-not {\tssubl\t} } } */
+/* { dg-final { scan-assembler-not {\tssubl2\t} } } */
+/* { dg-final { scan-assembler-not {\tabs\t} } } */
+
+/* { dg-final { scan-assembler {\tsabd\t} } } */
+/* { dg-final { scan-assembler {\tudot\t} } } */
+
diff --git a/gcc/testsuite/gcc.target/aarch64/ssadv16qi.c b/gcc/testsuite/gcc.target/aarch64/ssadv16qi.c
index 40b2884..85a867a 100644
--- a/gcc/testsuite/gcc.target/aarch64/ssadv16qi.c
+++ b/gcc/testsuite/gcc.target/aarch64/ssadv16qi.c
@@ -1,7 +1,7 @@
/* { dg-do compile } */
/* { dg-options "-O3" } */
-#pragma GCC target "+nosve"
+#pragma GCC target "+nosve+nodotprod"
#define N 1024
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/fabd_1.c b/gcc/testsuite/gcc.target/aarch64/sve/fabd_1.c
new file mode 100644
index 0000000..13ad83b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve/fabd_1.c
@@ -0,0 +1,35 @@
+/* { dg-do assemble { target aarch64_asm_sve_ok } } */
+/* { dg-options "-O3 --save-temps" } */
+
+#define N 16
+
+typedef float *__restrict__ vnx4sf;
+typedef double *__restrict__ vnx2df;
+typedef _Float16 *__restrict__ vnx8hf_a;
+typedef __fp16 *__restrict__ vnx8hf_b;
+
+extern float fabsf (float);
+extern double fabs (double);
+
+#define FABD(type, abs, n) \
+ void fabd_##type (type res, type a, type b) \
+ { \
+ int i; \
+ for (i = 0; i < n; i++) \
+ res[i] = abs (a[i] - b[i]); \
+ }
+
+#define TEST_SVE_F_MODES(FUNC) \
+ FUNC (vnx2df, fabs, N) \
+ FUNC (vnx4sf, fabsf, N) \
+ FUNC (vnx8hf_a, fabsf, N) \
+ FUNC (vnx8hf_b, fabsf, N) \
+
+TEST_SVE_F_MODES (FABD)
+
+/* { dg-final { scan-assembler "fabd" } } */
+/* { dg-final { scan-assembler-not "fsub" } } */
+/* { dg-final { scan-assembler-not "fabs" } } */
+/* { dg-final { scan-assembler-times {\tfabd\tz[0-9]+\.d, p[0-7]/m, z[0-9]+\.d, z[0-9]+\.d\n} 1 } } */
+/* { dg-final { scan-assembler-times {\tfabd\tz[0-9]+\.s, p[0-7]/m, z[0-9]+\.s, z[0-9]+\.s\n} 1 } } */
+/* { dg-final { scan-assembler-times {\tfabd\tz[0-9]+\.h, p[0-7]/m, z[0-9]+\.h, z[0-9]+\.h\n} 4 } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/fadda_1.c b/gcc/testsuite/gcc.target/aarch64/sve/fadda_1.c
new file mode 100644
index 0000000..158cd6c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve/fadda_1.c
@@ -0,0 +1,20 @@
+/* { dg-do assemble { target aarch64_asm_sve_ok } } */
+/* { dg-options "-O2 -ftree-vectorize --save-temps" } */
+
+#define DO_OPS(TYPE) \
+TYPE fold_##TYPE (TYPE *src, int count) \
+{ \
+ TYPE res = 0; \
+ for (int i = 0; i < count; ++i) \
+ res += src[i]; \
+ return res; \
+}
+
+DO_OPS (_Float16)
+DO_OPS (float)
+DO_OPS (double)
+
+/* { dg-final { scan-assembler-times {\tfadda\th[0-9]+, p[0-7], h[0-9]+, z[0-9]+\.h\n} 1 } } */
+/* { dg-final { scan-assembler-times {\tfadda\ts[0-9]+, p[0-7], s[0-9]+, z[0-9]+\.s\n} 1 } } */
+/* { dg-final { scan-assembler-times {\tfadda\td[0-9]+, p[0-7], d[0-9]+, z[0-9]+\.d\n} 1 } } */
+/* { dg-final { scan-assembler-not "sel" } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/index_offset_1.c b/gcc/testsuite/gcc.target/aarch64/sve/index_offset_1.c
index 31d46aa..a26be32 100644
--- a/gcc/testsuite/gcc.target/aarch64/sve/index_offset_1.c
+++ b/gcc/testsuite/gcc.target/aarch64/sve/index_offset_1.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -ftree-vectorize -msve-vector-bits=256" } */
+/* { dg-options "-O2 -ftree-vectorize -msve-vector-bits=256 -fno-tree-loop-distribute-patterns" } */
#define SIZE (15 * 8 + 3)
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/init_1.c b/gcc/testsuite/gcc.target/aarch64/sve/init_1.c
new file mode 100644
index 0000000..14abc22
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve/init_1.c
@@ -0,0 +1,26 @@
+/* { dg-do assemble { target aarch64_asm_sve_ok } } */
+/* { dg-options "-O -msve-vector-bits=256 --save-temps" } */
+
+/* Case 1.1: Trailing constants with stepped sequence. */
+
+#include <stdint.h>
+
+typedef int32_t vnx4si __attribute__((vector_size (32)));
+
+__attribute__((noipa))
+vnx4si foo(int a, int b)
+{
+ return (vnx4si) { a, b, 1, 2, 3, 4, 5, 6 };
+}
+
+/*
+foo:
+.LFB0:
+ .cfi_startproc
+ index z0.s, #1, #1
+ insr z0.s, w1
+ insr z0.s, w0
+ ret
+*/
+
+/* { dg-final { scan-assembler {\tindex\t(z[0-9]+\.s), #1, #1\n\tinsr\t\1, w1\n\tinsr\t\1, w0} } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/init_10.c b/gcc/testsuite/gcc.target/aarch64/sve/init_10.c
new file mode 100644
index 0000000..c83debe
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve/init_10.c
@@ -0,0 +1,28 @@
+/* { dg-do assemble { target aarch64_asm_sve_ok } } */
+/* { dg-options "-O -msve-vector-bits=256 --save-temps" } */
+
+/* Case 5.4: Interleaved repeating elements and non-repeating elements. */
+
+#include <stdint.h>
+
+typedef int32_t vnx4si __attribute__((vector_size (32)));
+
+__attribute__((noipa))
+vnx4si foo(int a, int b, int c, int f)
+{
+ return (vnx4si) { a, f, b, f, c, f, c, f };
+}
+
+/*
+foo:
+.LFB0:
+ .cfi_startproc
+ mov z1.s, w3
+ mov z0.s, w2
+ insr z0.s, w1
+ insr z0.s, w0
+ zip1 z0.s, z0.s, z1.s
+ ret
+*/
+
+/* { dg-final { scan-assembler {\tmov\t(z[0-9]+\.s), w3\n\tmov\t(z[0-9]+\.s), w2\n\tinsr\t\2, w1\n\tinsr\t\2, w0\n\tzip1\t\2, \2, \1} } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/init_10_run.c b/gcc/testsuite/gcc.target/aarch64/sve/init_10_run.c
new file mode 100644
index 0000000..9a6d865
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve/init_10_run.c
@@ -0,0 +1,21 @@
+/* { dg-do run { target aarch64_sve256_hw } } */
+/* { dg-options "-O2 -msve-vector-bits=256" } */
+
+#include "init_10.c"
+
+int main()
+{
+ int a = 10;
+ int b = 11;
+ int c = 12;
+ int f = 13;
+
+ vnx4si v = foo (a, b, c, f);
+ int expected[] = { a, f, b, f, c, f, c, f };
+
+ for (int i = 0; i < 8; i++)
+ if (v[i] != expected[i])
+ __builtin_abort ();
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/init_11.c b/gcc/testsuite/gcc.target/aarch64/sve/init_11.c
new file mode 100644
index 0000000..90627b4
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve/init_11.c
@@ -0,0 +1,27 @@
+/* { dg-do assemble { target aarch64_asm_sve_ok } } */
+/* { dg-options "-O -msve-vector-bits=256 --save-temps" } */
+
+/* Case 5.5: Interleaved repeating elements and trailing same elements. */
+
+#include <stdint.h>
+
+typedef int32_t vnx4si __attribute__((vector_size (32)));
+
+__attribute__((noipa))
+vnx4si foo(int a, int b, int f)
+{
+ return (vnx4si) { a, f, b, f, b, f, b, f };
+}
+
+/*
+foo:
+.LFB0:
+ .cfi_startproc
+ mov z0.s, w1
+ insr z0.s, w0
+ mov z1.s, w2
+ zip1 z0.s, z0.s, z1.s
+ ret
+*/
+
+/* { dg-final { scan-assembler {\tmov\t(z[0-9]+\.s), w1\n\tinsr\t\1, w0\n\tmov\t(z[0-9]+\.s), w2\n\tzip1\t\1, \1, \2} } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/init_11_run.c b/gcc/testsuite/gcc.target/aarch64/sve/init_11_run.c
new file mode 100644
index 0000000..4371555
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve/init_11_run.c
@@ -0,0 +1,20 @@
+/* { dg-do run { target aarch64_sve256_hw } } */
+/* { dg-options "-O2 -msve-vector-bits=256" } */
+
+#include "init_11.c"
+
+int main()
+{
+ int a = 10;
+ int b = 11;
+ int f = 12;
+
+ vnx4si v = foo (a, b, f);
+ int expected[] = { a, f, b, f, b, f, b, f };
+
+ for (int i = 0; i < 8; i++)
+ if (v[i] != expected[i])
+ __builtin_abort ();
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/init_12.c b/gcc/testsuite/gcc.target/aarch64/sve/init_12.c
new file mode 100644
index 0000000..dc20e86
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve/init_12.c
@@ -0,0 +1,29 @@
+/* { dg-do assemble { target aarch64_asm_sve_ok } } */
+/* { dg-options "-O -msve-vector-bits=256 --save-temps" } */
+
+/* Case 5.5: Interleaved repeating elements and trailing same elements. */
+
+#include <stdint.h>
+
+typedef int32_t vnx4si __attribute__((vector_size (32)));
+
+__attribute__((noipa))
+vnx4si foo(int a, int b, int f)
+{
+ return (vnx4si) { b, f, b, f, b, f, a, f };
+}
+
+/*
+foo:
+.LFB0:
+ .cfi_startproc
+ mov z1.s, w2
+ mov z0.s, w0
+ insr z0.s, w1
+ insr z0.s, w1
+ insr z0.s, w1
+ zip1 z0.s, z0.s, z1.s
+ ret
+*/
+
+/* { dg-final { scan-assembler {\tmov\t(z[0-9]+\.s), w2\n\tmov\t(z[0-9]+\.s), w0\n\tinsr\t\2, w1\n\tinsr\t\2, w1\n\tinsr\t\2, w1\n\tzip1\t\2, \2, \1} } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/init_12_run.c b/gcc/testsuite/gcc.target/aarch64/sve/init_12_run.c
new file mode 100644
index 0000000..5ce7edb
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve/init_12_run.c
@@ -0,0 +1,20 @@
+/* { dg-do run { target aarch64_sve256_hw } } */
+/* { dg-options "-O2 -msve-vector-bits=256" } */
+
+#include "init_12.c"
+
+int main()
+{
+ int a = 10;
+ int b = 11;
+ int f = 12;
+
+ vnx4si v = foo (a, b, f);
+ int expected[] = { b, f, b, f, b, f, a, f };
+
+ for (int i = 0; i < 8; i++)
+ if (v[i] != expected[i])
+ __builtin_abort ();
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/init_1_run.c b/gcc/testsuite/gcc.target/aarch64/sve/init_1_run.c
new file mode 100644
index 0000000..824a5cb
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve/init_1_run.c
@@ -0,0 +1,19 @@
+/* { dg-do run { target aarch64_sve256_hw } } */
+/* { dg-options "-O2 -msve-vector-bits=256" } */
+
+#include "init_1.c"
+
+int main()
+{
+ int a = 10;
+ int b = 11;
+
+ vnx4si v = foo (a, b);
+ int expected[] = { a, b, 1, 2, 3, 4, 5, 6 };
+
+ for (int i = 0; i < 8; i++)
+ if (v[i] != expected[i])
+ __builtin_abort ();
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/init_2.c b/gcc/testsuite/gcc.target/aarch64/sve/init_2.c
new file mode 100644
index 0000000..5b4ba10
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve/init_2.c
@@ -0,0 +1,29 @@
+/* { dg-do assemble { target aarch64_asm_sve_ok } } */
+/* { dg-options "-O -msve-vector-bits=256 --save-temps" } */
+
+/* Case 1.2: Trailing constants with repeating sequence. */
+
+#include <stdint.h>
+
+typedef int32_t vnx4si __attribute__((vector_size (32)));
+
+__attribute__((noipa))
+vnx4si foo(int a, int b)
+{
+ return (vnx4si) { a, b, 2, 3, 2, 3, 2, 3 };
+}
+
+/*
+foo:
+.LFB0:
+ .cfi_startproc
+ ptrue p0.s, vl8
+ adrp x2, .LANCHOR0
+ add x2, x2, :lo12:.LANCHOR0
+ ld1w z0.s, p0/z, [x2]
+ insr z0.s, w1
+ insr z0.s, w0
+ ret
+*/
+
+/* { dg-final { scan-assembler {\tld1w\t(z[0-9]+\.s), p[0-9]+/z, \[x[0-9]+\]\n\tinsr\t\1, w1\n\tinsr\t\1, w0} } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/init_2_run.c b/gcc/testsuite/gcc.target/aarch64/sve/init_2_run.c
new file mode 100644
index 0000000..86c191c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve/init_2_run.c
@@ -0,0 +1,19 @@
+/* { dg-do run { target aarch64_sve256_hw } } */
+/* { dg-options "-O2 -msve-vector-bits=256" } */
+
+#include "init_2.c"
+
+int main()
+{
+ int a = 10;
+ int b = 11;
+
+ vnx4si v = foo (a, b);
+ int expected[] = { a, b, 2, 3, 2, 3, 2, 3 };
+
+ for (int i = 0; i < 8; i++)
+ if (v[i] != expected[i])
+ __builtin_abort ();
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/init_3.c b/gcc/testsuite/gcc.target/aarch64/sve/init_3.c
new file mode 100644
index 0000000..28d218c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve/init_3.c
@@ -0,0 +1,27 @@
+/* { dg-do assemble { target aarch64_asm_sve_ok } } */
+/* { dg-options "-O -msve-vector-bits=256 --save-temps" } */
+
+/* Case 2.1: Leading constants with stepped sequence. */
+
+#include <stdint.h>
+
+typedef int32_t vnx4si __attribute__((vector_size (32)));
+
+__attribute__((noipa))
+vnx4si foo(int a, int b)
+{
+ return (vnx4si) { 1, 2, 3, 4, 5, 6, a, b };
+}
+
+/*
+foo:
+.LFB0:
+ .cfi_startproc
+ index z0.s, #6, #-1
+ insr z0.s, w0
+ insr z0.s, w1
+ rev z0.s, z0.s
+ ret
+*/
+
+/* { dg-final { scan-assembler {\tindex\t(z[0-9]+\.s), #6, #-1\n\tinsr\t\1, w0\n\tinsr\t\1, w1\n\trev\t\1, \1} } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/init_3_run.c b/gcc/testsuite/gcc.target/aarch64/sve/init_3_run.c
new file mode 100644
index 0000000..ce4de69
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve/init_3_run.c
@@ -0,0 +1,19 @@
+/* { dg-do run { target aarch64_sve256_hw } } */
+/* { dg-options "-O2 -msve-vector-bits=256" } */
+
+#include "init_3.c"
+
+int main()
+{
+ int a = 10;
+ int b = 11;
+
+ vnx4si v = foo (a, b);
+ int expected[] = { 1, 2, 3, 4, 5, 6, a, b };
+
+ for (int i = 0; i < 8; i++)
+ if (v[i] != expected[i])
+ __builtin_abort ();
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/init_4.c b/gcc/testsuite/gcc.target/aarch64/sve/init_4.c
new file mode 100644
index 0000000..94484b1
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve/init_4.c
@@ -0,0 +1,30 @@
+/* { dg-do assemble { target aarch64_asm_sve_ok } } */
+/* { dg-options "-O -msve-vector-bits=256 --save-temps" } */
+
+/* Case 2.2: Leading constants with stepped sequence. */
+
+#include <stdint.h>
+
+typedef int32_t vnx4si __attribute__((vector_size (32)));
+
+__attribute__((noipa))
+vnx4si foo(int a, int b)
+{
+ return (vnx4si) { 3, 2, 3, 2, 3, 2, b, a };
+}
+
+/*
+foo:
+.LFB0:
+ .cfi_startproc
+ ptrue p0.s, vl8
+ adrp x2, .LANCHOR0
+ add x2, x2, :lo12:.LANCHOR0
+ ld1w z0.s, p0/z, [x2]
+ insr z0.s, w1
+ insr z0.s, w0
+ rev z0.s, z0.s
+ ret
+*/
+
+/* { dg-final { scan-assembler {\tld1w\t(z[0-9]+\.s), p[0-9]+/z, \[x[0-9]+\]\n\tinsr\t\1, w1\n\tinsr\t\1, w0\n\trev\t\1, \1} } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/init_4_run.c b/gcc/testsuite/gcc.target/aarch64/sve/init_4_run.c
new file mode 100644
index 0000000..defee42
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve/init_4_run.c
@@ -0,0 +1,19 @@
+/* { dg-do run { target aarch64_sve256_hw } } */
+/* { dg-options "-O2 -msve-vector-bits=256" } */
+
+#include "init_4.c"
+
+int main()
+{
+ int a = 10;
+ int b = 11;
+
+ vnx4si v = foo (a, b);
+ int expected[] = { 3, 2, 3, 2, 3, 2, b, a };
+
+ for (int i = 0; i < 8; i++)
+ if (v[i] != expected[i])
+ __builtin_abort ();
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/init_5.c b/gcc/testsuite/gcc.target/aarch64/sve/init_5.c
new file mode 100644
index 0000000..a43dd7a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve/init_5.c
@@ -0,0 +1,26 @@
+/* { dg-do assemble { target aarch64_asm_sve_ok } } */
+/* { dg-options "-O -msve-vector-bits=256 --save-temps" } */
+
+/* Case 3: Trailing same element. */
+
+#include <stdint.h>
+
+typedef int32_t vnx4si __attribute__((vector_size (32)));
+
+__attribute__((noipa))
+vnx4si foo(int a, int b, int c)
+{
+ return (vnx4si) { a, b, c, c, c, c, c, c };
+}
+
+/*
+foo:
+.LFB0:
+ .cfi_startproc
+ mov z0.s, w2
+ insr z0.s, w1
+ insr z0.s, w0
+ ret
+*/
+
+/* { dg-final { scan-assembler {\tmov\t(z[0-9]+\.s), w2\n\tinsr\t\1, w1\n\tinsr\t\1, w0} } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/init_5_run.c b/gcc/testsuite/gcc.target/aarch64/sve/init_5_run.c
new file mode 100644
index 0000000..ba91d6f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve/init_5_run.c
@@ -0,0 +1,20 @@
+/* { dg-do run { target aarch64_sve256_hw } } */
+/* { dg-options "-O2 -msve-vector-bits=256" } */
+
+#include "init_5.c"
+
+int main()
+{
+ int a = 10;
+ int b = 11;
+ int c = 12;
+
+ vnx4si v = foo (a, b, c);
+ int expected[] = { a, b, c, c, c, c, c, c };
+
+ for (int i = 0; i < 8; i++)
+ if (v[i] != expected[i])
+ __builtin_abort ();
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/init_6.c b/gcc/testsuite/gcc.target/aarch64/sve/init_6.c
new file mode 100644
index 0000000..b8e30fb
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve/init_6.c
@@ -0,0 +1,27 @@
+/* { dg-do assemble { target aarch64_asm_sve_ok } } */
+/* { dg-options "-O -msve-vector-bits=256 --save-temps" } */
+
+/* Case 3: Trailing same element. */
+
+#include <stdint.h>
+
+typedef int32_t vnx4si __attribute__((vector_size (32)));
+
+__attribute__((noipa))
+vnx4si foo(int a, int b, int c)
+{
+ return (vnx4si) { c, c, c, c, c, c, b, a };
+}
+
+/*
+foo:
+.LFB0:
+ .cfi_startproc
+ mov z0.s, w2
+ insr z0.s, w1
+ insr z0.s, w0
+ rev z0.s, z0.s
+ ret
+*/
+
+/* { dg-final { scan-assembler {\tmov\t(z[0-9]+\.s), w2\n\tinsr\t\1, w1\n\tinsr\t\1, w0\n\trev\t\1, \1} } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/init_6_run.c b/gcc/testsuite/gcc.target/aarch64/sve/init_6_run.c
new file mode 100644
index 0000000..802b28f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve/init_6_run.c
@@ -0,0 +1,20 @@
+/* { dg-do run { target aarch64_sve256_hw } } */
+/* { dg-options "-O2 -msve-vector-bits=256" } */
+
+#include "init_6.c"
+
+int main()
+{
+ int a = 10;
+ int b = 11;
+ int c = 12;
+
+ vnx4si v = foo (a, b, c);
+ int expected[] = { c, c, c, c, c, c, b, a };
+
+ for (int i = 0; i < 8; i++)
+ if (v[i] != expected[i])
+ __builtin_abort ();
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/init_7.c b/gcc/testsuite/gcc.target/aarch64/sve/init_7.c
new file mode 100644
index 0000000..dd27978
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve/init_7.c
@@ -0,0 +1,31 @@
+/* { dg-do assemble { target aarch64_asm_sve_ok } } */
+/* { dg-options "-O -msve-vector-bits=256 --save-temps" } */
+
+/* Case 5.1: All elements. */
+
+#include <stdint.h>
+
+typedef int32_t vnx4si __attribute__((vector_size (32)));
+
+__attribute__((noipa))
+vnx4si foo(int a, int b, int c, int d, int e, int f, int g, int h)
+{
+ return (vnx4si) { a, b, c, d, e, f, g, h };
+}
+
+/*
+foo:
+.LFB0:
+ .cfi_startproc
+ mov z0.s, w7
+ insr z0.s, w6
+ insr z0.s, w5
+ insr z0.s, w4
+ insr z0.s, w3
+ insr z0.s, w2
+ insr z0.s, w1
+ insr z0.s, w0
+ ret
+*/
+
+/* { dg-final { scan-assembler {\tmov\t(z[0-9]+\.s), w7\n\tinsr\t\1, w6\n\tinsr\t\1, w5\n\tinsr\t\1, w4\n\tinsr\t\1, w3\n\tinsr\t\1, w2\n\tinsr\t\1, w1\n\tinsr\t\1, w0} } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/init_7_run.c b/gcc/testsuite/gcc.target/aarch64/sve/init_7_run.c
new file mode 100644
index 0000000..61fe285
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve/init_7_run.c
@@ -0,0 +1,25 @@
+/* { dg-do run { target aarch64_sve256_hw } } */
+/* { dg-options "-O2 -msve-vector-bits=256" } */
+
+#include "init_7.c"
+
+int main()
+{
+ int a = 10;
+ int b = 11;
+ int c = 12;
+ int d = 13;
+ int e = 14;
+ int f = 15;
+ int g = 16;
+ int h = 17;
+
+ vnx4si v = foo (a, b, c, d, e, f, g, h);
+ int expected[] = { a, b, c, d, e, f, g, h };
+
+ for (int i = 0; i < 8; i++)
+ if (v[i] != expected[i])
+ __builtin_abort ();
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/init_8.c b/gcc/testsuite/gcc.target/aarch64/sve/init_8.c
new file mode 100644
index 0000000..73f7aba
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve/init_8.c
@@ -0,0 +1,32 @@
+/* { dg-do assemble { target aarch64_asm_sve_ok } } */
+/* { dg-options "-O -msve-vector-bits=256 --save-temps" } */
+
+/* Case 5.2: Interleaved elements and constants. */
+
+#include <stdint.h>
+
+typedef int32_t vnx4si __attribute__((vector_size (32)));
+
+__attribute__((noipa))
+vnx4si foo(int a, int b, int c, int d)
+{
+ return (vnx4si) { a, 1, b, 2, c, 3, d, 4 };
+}
+
+/*
+foo:
+.LFB0:
+ .cfi_startproc
+ ptrue p0.s, vl8
+ adrp x4, .LANCHOR0
+ add x4, x4, :lo12:.LANCHOR0
+ ld1w z1.s, p0/z, [x4]
+ mov z0.s, w3
+ insr z0.s, w2
+ insr z0.s, w1
+ insr z0.s, w0
+ zip1 z0.s, z0.s, z1.s
+ ret
+*/
+
+/* { dg-final { scan-assembler {\tld1w\t(z[0-9]+\.s), p[0-9]+/z, \[x[0-9]+\]\n\tmov\t(z[0-9]+\.s), w3\n\tinsr\t\2, w2\n\tinsr\t\2, w1\n\tinsr\t\2, w0\n\tzip1\t\2, \2, \1} } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/init_8_run.c b/gcc/testsuite/gcc.target/aarch64/sve/init_8_run.c
new file mode 100644
index 0000000..24a0a6e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve/init_8_run.c
@@ -0,0 +1,21 @@
+/* { dg-do run { target aarch64_sve256_hw } } */
+/* { dg-options "-O2 -msve-vector-bits=256" } */
+
+#include "init_8.c"
+
+int main()
+{
+ int a = 10;
+ int b = 11;
+ int c = 12;
+ int d = 13;
+
+ vnx4si v = foo (a, b, c, d);
+ int expected[] = { a, 1, b, 2, c, 3, d, 4 };
+
+ for (int i = 0; i < 8; i++)
+ if (v[i] != expected[i])
+ __builtin_abort ();
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/init_9.c b/gcc/testsuite/gcc.target/aarch64/sve/init_9.c
new file mode 100644
index 0000000..2cc564a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve/init_9.c
@@ -0,0 +1,26 @@
+/* { dg-do assemble { target aarch64_asm_sve_ok } } */
+/* { dg-options "-O -msve-vector-bits=256 --save-temps" } */
+
+/* Case 5.3: Repeated elements. */
+
+#include <stdint.h>
+
+typedef int32_t vnx4si __attribute__((vector_size (32)));
+
+__attribute__((noipa))
+vnx4si foo(int a, int b)
+{
+ return (vnx4si) { a, b, a, b, a, b, a, b };
+}
+
+/*
+foo:
+.LFB0:
+ .cfi_startproc
+ mov z0.s, w0
+ mov z1.s, w1
+ zip1 z0.s, z0.s, z1.s
+ ret
+*/
+
+/* { dg-final { scan-assembler {\tmov\t(z[0-9]+\.s), w0\n\tmov\t(z[0-9]+\.s), w1\n\tzip1\t\1, \1, \2} } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/init_9_run.c b/gcc/testsuite/gcc.target/aarch64/sve/init_9_run.c
new file mode 100644
index 0000000..636ae3b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve/init_9_run.c
@@ -0,0 +1,19 @@
+/* { dg-do run { target aarch64_sve256_hw } } */
+/* { dg-options "-O2 -msve-vector-bits=256" } */
+
+#include "init_9.c"
+
+int main()
+{
+ int a = 10;
+ int b = 11;
+
+ vnx4si v = foo (a, b);
+ int expected[] = { a, b, a, b, a, b, a, b };
+
+ for (int i = 0; i < 8; i++)
+ if (v[i] != expected[i])
+ __builtin_abort ();
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/mask_load_slp_1.c b/gcc/testsuite/gcc.target/aarch64/sve/mask_load_slp_1.c
new file mode 100644
index 0000000..78c70b2
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve/mask_load_slp_1.c
@@ -0,0 +1,90 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -ftree-vectorize" } */
+
+#include <stdint.h>
+
+#define MASK_SLP_2(TYPE_COND, ALT_VAL) \
+void __attribute__ ((noinline, noclone)) \
+mask_slp_##TYPE_COND##_2_##ALT_VAL (int *restrict x, int *restrict y, \
+ TYPE_COND *restrict z, int n) \
+{ \
+ for (int i = 0; i < n; i += 2) \
+ { \
+ x[i] = y[i] ? z[i] : 1; \
+ x[i + 1] = y[i + 1] ? z[i + 1] : ALT_VAL; \
+ } \
+}
+
+#define MASK_SLP_4(TYPE_COND, ALT_VAL) \
+void __attribute__ ((noinline, noclone)) \
+mask_slp_##TYPE_COND##_4_##ALT_VAL (int *restrict x, int *restrict y, \
+ TYPE_COND *restrict z, int n) \
+{ \
+ for (int i = 0; i < n; i += 4) \
+ { \
+ x[i] = y[i] ? z[i] : 1; \
+ x[i + 1] = y[i + 1] ? z[i + 1] : ALT_VAL; \
+ x[i + 2] = y[i + 2] ? z[i + 2] : 1; \
+ x[i + 3] = y[i + 3] ? z[i + 3] : ALT_VAL; \
+ } \
+}
+
+#define MASK_SLP_8(TYPE_COND, ALT_VAL) \
+void __attribute__ ((noinline, noclone)) \
+mask_slp_##TYPE_COND##_8_##ALT_VAL (int *restrict x, int *restrict y, \
+ TYPE_COND *restrict z, int n) \
+{ \
+ for (int i = 0; i < n; i += 8) \
+ { \
+ x[i] = y[i] ? z[i] : 1; \
+ x[i + 1] = y[i + 1] ? z[i + 1] : ALT_VAL; \
+ x[i + 2] = y[i + 2] ? z[i + 2] : 1; \
+ x[i + 3] = y[i + 3] ? z[i + 3] : ALT_VAL; \
+ x[i + 4] = y[i + 4] ? z[i + 4] : 1; \
+ x[i + 5] = y[i + 5] ? z[i + 5] : ALT_VAL; \
+ x[i + 6] = y[i + 6] ? z[i + 6] : 1; \
+ x[i + 7] = y[i + 7] ? z[i + 7] : ALT_VAL; \
+ } \
+}
+
+#define MASK_SLP_FAIL(TYPE_COND) \
+void __attribute__ ((noinline, noclone)) \
+mask_slp_##TYPE_COND##_FAIL (int *restrict x, int *restrict y, \
+ TYPE_COND *restrict z, int n) \
+{ \
+ for (int i = 0; i < n; i += 2) \
+ { \
+ x[i] = y[i] ? z[i] : 1; \
+ x[i + 1] = y[i + 1] ? z[i + 1] : x[z[i + 1]]; \
+ } \
+}
+
+MASK_SLP_2(int8_t, 1)
+MASK_SLP_2(int8_t, 2)
+MASK_SLP_2(int, 1)
+MASK_SLP_2(int, 2)
+MASK_SLP_2(int64_t, 1)
+MASK_SLP_2(int64_t, 2)
+
+MASK_SLP_4(int8_t, 1)
+MASK_SLP_4(int8_t, 2)
+MASK_SLP_4(int, 1)
+MASK_SLP_4(int, 2)
+MASK_SLP_4(int64_t, 1)
+MASK_SLP_4(int64_t, 2)
+
+MASK_SLP_8(int8_t, 1)
+MASK_SLP_8(int8_t, 2)
+MASK_SLP_8(int, 1)
+MASK_SLP_8(int, 2)
+MASK_SLP_8(int64_t, 1)
+MASK_SLP_8(int64_t, 2)
+
+MASK_SLP_FAIL(int8_t)
+MASK_SLP_FAIL(int)
+MASK_SLP_FAIL(int64_t)
+
+/* { dg-final { scan-assembler-not {\tld2w\t} } } */
+/* { dg-final { scan-assembler-not {\tst2w\t} } } */
+/* { dg-final { scan-assembler-times {\tld1w\t} 48 } } */
+/* { dg-final { scan-assembler-times {\tst1w\t} 40 } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/pr88834.c b/gcc/testsuite/gcc.target/aarch64/sve/pr88834.c
new file mode 100644
index 0000000..7e7be4e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve/pr88834.c
@@ -0,0 +1,15 @@
+/* { dg-do compile } */
+/* { dg-options "-O3" } */
+
+void
+f (int *restrict x, int *restrict y, int *restrict z, int n)
+{
+ for (int i = 0; i < n; i += 2)
+ {
+ x[i] = y[i] + z[i];
+ x[i + 1] = y[i + 1] - z[i + 1];
+ }
+}
+
+/* { dg-final { scan-assembler-times {\tld2w\t{z[0-9]+.s - z[0-9]+.s}, p[0-7]/z, \[x[0-9]+, x[0-9]+, lsl 2\]\n} 2 } } */
+/* { dg-final { scan-assembler-times {\tst2w\t{z[0-9]+.s - z[0-9]+.s}, p[0-7], \[x[0-9]+, x[0-9]+, lsl 2\]\n} 1 } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/single_1.c b/gcc/testsuite/gcc.target/aarch64/sve/single_1.c
index 11b88ae..e3a8409 100644
--- a/gcc/testsuite/gcc.target/aarch64/sve/single_1.c
+++ b/gcc/testsuite/gcc.target/aarch64/sve/single_1.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -ftree-vectorize -fopenmp-simd -msve-vector-bits=256" } */
+/* { dg-options "-O2 -ftree-vectorize -fopenmp-simd -msve-vector-bits=256 -fno-tree-loop-distribute-patterns" } */
#ifndef N
#define N 32
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/single_2.c b/gcc/testsuite/gcc.target/aarch64/sve/single_2.c
index 1fbf489..195ee20 100644
--- a/gcc/testsuite/gcc.target/aarch64/sve/single_2.c
+++ b/gcc/testsuite/gcc.target/aarch64/sve/single_2.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -ftree-vectorize -fopenmp-simd -msve-vector-bits=512" } */
+/* { dg-options "-O2 -ftree-vectorize -fopenmp-simd -msve-vector-bits=512 -fno-tree-loop-distribute-patterns" } */
#define N 64
#include "single_1.c"
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/single_3.c b/gcc/testsuite/gcc.target/aarch64/sve/single_3.c
index a3688b6..e031276 100644
--- a/gcc/testsuite/gcc.target/aarch64/sve/single_3.c
+++ b/gcc/testsuite/gcc.target/aarch64/sve/single_3.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -ftree-vectorize -fopenmp-simd -msve-vector-bits=1024" } */
+/* { dg-options "-O2 -ftree-vectorize -fopenmp-simd -msve-vector-bits=1024 -fno-tree-loop-distribute-patterns" } */
#define N 128
#include "single_1.c"
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/single_4.c b/gcc/testsuite/gcc.target/aarch64/sve/single_4.c
index 08965d3..01ff7f6 100644
--- a/gcc/testsuite/gcc.target/aarch64/sve/single_4.c
+++ b/gcc/testsuite/gcc.target/aarch64/sve/single_4.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -ftree-vectorize -fopenmp-simd -msve-vector-bits=2048" } */
+/* { dg-options "-O2 -ftree-vectorize -fopenmp-simd -msve-vector-bits=2048 -fno-tree-loop-distribute-patterns" } */
#define N 256
#include "single_1.c"
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/struct_vect_1.c b/gcc/testsuite/gcc.target/aarch64/sve/struct_vect_1.c
index 6e3c889..918a581 100644
--- a/gcc/testsuite/gcc.target/aarch64/sve/struct_vect_1.c
+++ b/gcc/testsuite/gcc.target/aarch64/sve/struct_vect_1.c
@@ -83,9 +83,9 @@ NAME(g4) (TYPE *__restrict a, TYPE *__restrict b, TYPE *__restrict c,
}
}
-/* { dg-final { scan-assembler {\tld2b\t{z[0-9]+.b - z[0-9]+.b}, p[0-7]/z, \[x[0-9]+\]\n} } } */
+/* { dg-final { scan-assembler {\tld2b\t{z[0-9]+.b - z[0-9]+.b}, p[0-7]/z, \[x[0-9]+, x[0-9]+\]\n} } } */
/* { dg-final { scan-assembler {\tld3b\t{z[0-9]+.b - z[0-9]+.b}, p[0-7]/z, \[x[0-9]+\]\n} } } */
-/* { dg-final { scan-assembler {\tld4b\t{z[0-9]+.b - z[0-9]+.b}, p[0-7]/z, \[x[0-9]+\]\n} } } */
-/* { dg-final { scan-assembler {\tst2b\t{z[0-9]+.b - z[0-9]+.b}, p[0-7], \[x[0-9]+\]\n} } } */
+/* { dg-final { scan-assembler {\tld4b\t{z[0-9]+.b - z[0-9]+.b}, p[0-7]/z, \[x[0-9]+, x[0-9]+\]\n} } } */
+/* { dg-final { scan-assembler {\tst2b\t{z[0-9]+.b - z[0-9]+.b}, p[0-7], \[x[0-9]+, x[0-9]+\]\n} } } */
/* { dg-final { scan-assembler {\tst3b\t{z[0-9]+.b - z[0-9]+.b}, p[0-7], \[x[0-9]+\]\n} } } */
-/* { dg-final { scan-assembler {\tst4b\t{z[0-9]+.b - z[0-9]+.b}, p[0-7], \[x[0-9]+\]\n} } } */
+/* { dg-final { scan-assembler {\tst4b\t{z[0-9]+.b - z[0-9]+.b}, p[0-7], \[x[0-9]+, x[0-9]+\]\n} } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/struct_vect_14.c b/gcc/testsuite/gcc.target/aarch64/sve/struct_vect_14.c
index 45644b6..a16a79e 100644
--- a/gcc/testsuite/gcc.target/aarch64/sve/struct_vect_14.c
+++ b/gcc/testsuite/gcc.target/aarch64/sve/struct_vect_14.c
@@ -43,12 +43,12 @@
#undef NAME
#undef TYPE
-/* { dg-final { scan-assembler-times {\tld2b\t{z[0-9]+.b - z[0-9]+.b}, p[0-7]/z, \[x[0-9]+\]\n} 1 } } */
+/* { dg-final { scan-assembler-times {\tld2b\t{z[0-9]+.b - z[0-9]+.b}, p[0-7]/z, \[x[0-9]+, x[0-9]+\]\n} 1 } } */
/* { dg-final { scan-assembler-times {\tld3b\t{z[0-9]+.b - z[0-9]+.b}, p[0-7]/z, \[x[0-9]+\]\n} 1 } } */
-/* { dg-final { scan-assembler-times {\tld4b\t{z[0-9]+.b - z[0-9]+.b}, p[0-7]/z, \[x[0-9]+\]\n} 1 } } */
-/* { dg-final { scan-assembler-times {\tst2b\t{z[0-9]+.b - z[0-9]+.b}, p[0-7], \[x[0-9]+\]\n} 1 } } */
+/* { dg-final { scan-assembler-times {\tld4b\t{z[0-9]+.b - z[0-9]+.b}, p[0-7]/z, \[x[0-9]+, x[0-9]+\]\n} 1 } } */
+/* { dg-final { scan-assembler-times {\tst2b\t{z[0-9]+.b - z[0-9]+.b}, p[0-7], \[x[0-9]+, x[0-9]+\]\n} 1 } } */
/* { dg-final { scan-assembler-times {\tst3b\t{z[0-9]+.b - z[0-9]+.b}, p[0-7], \[x[0-9]+\]\n} 1 } } */
-/* { dg-final { scan-assembler-times {\tst4b\t{z[0-9]+.b - z[0-9]+.b}, p[0-7], \[x[0-9]+\]\n} 1 } } */
+/* { dg-final { scan-assembler-times {\tst4b\t{z[0-9]+.b - z[0-9]+.b}, p[0-7], \[x[0-9]+, x[0-9]+\]\n} 1 } } */
/* { dg-final { scan-assembler-times {\tld2h\t{z[0-9]+.h - z[0-9]+.h}, p[0-7]/z, \[x[0-9]+\]\n} 2 } } */
/* { dg-final { scan-assembler-times {\tld3h\t{z[0-9]+.h - z[0-9]+.h}, p[0-7]/z, \[x[0-9]+\]\n} 2 } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/struct_vect_15.c b/gcc/testsuite/gcc.target/aarch64/sve/struct_vect_15.c
index 814dbb3..bc00267 100644
--- a/gcc/testsuite/gcc.target/aarch64/sve/struct_vect_15.c
+++ b/gcc/testsuite/gcc.target/aarch64/sve/struct_vect_15.c
@@ -3,12 +3,12 @@
#include "struct_vect_14.c"
-/* { dg-final { scan-assembler-times {\tld2b\t{z[0-9]+.b - z[0-9]+.b}, p[0-7]/z, \[x[0-9]+\]\n} 1 } } */
+/* { dg-final { scan-assembler-times {\tld2b\t{z[0-9]+.b - z[0-9]+.b}, p[0-7]/z, \[x[0-9]+, x[0-9]+\]\n} 1 } } */
/* { dg-final { scan-assembler-times {\tld3b\t{z[0-9]+.b - z[0-9]+.b}, p[0-7]/z, \[x[0-9]+\]\n} 1 } } */
-/* { dg-final { scan-assembler-times {\tld4b\t{z[0-9]+.b - z[0-9]+.b}, p[0-7]/z, \[x[0-9]+\]\n} 1 } } */
-/* { dg-final { scan-assembler-times {\tst2b\t{z[0-9]+.b - z[0-9]+.b}, p[0-7], \[x[0-9]+\]\n} 1 } } */
+/* { dg-final { scan-assembler-times {\tld4b\t{z[0-9]+.b - z[0-9]+.b}, p[0-7]/z, \[x[0-9]+, x[0-9]+\]\n} 1 } } */
+/* { dg-final { scan-assembler-times {\tst2b\t{z[0-9]+.b - z[0-9]+.b}, p[0-7], \[x[0-9]+, x[0-9]+\]\n} 1 } } */
/* { dg-final { scan-assembler-times {\tst3b\t{z[0-9]+.b - z[0-9]+.b}, p[0-7], \[x[0-9]+\]\n} 1 } } */
-/* { dg-final { scan-assembler-times {\tst4b\t{z[0-9]+.b - z[0-9]+.b}, p[0-7], \[x[0-9]+\]\n} 1 } } */
+/* { dg-final { scan-assembler-times {\tst4b\t{z[0-9]+.b - z[0-9]+.b}, p[0-7], \[x[0-9]+, x[0-9]+\]\n} 1 } } */
/* { dg-final { scan-assembler-times {\tld2h\t{z[0-9]+.h - z[0-9]+.h}, p[0-7]/z, \[x[0-9]+\]\n} 2 } } */
/* { dg-final { scan-assembler-times {\tld3h\t{z[0-9]+.h - z[0-9]+.h}, p[0-7]/z, \[x[0-9]+\]\n} 2 } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/struct_vect_16.c b/gcc/testsuite/gcc.target/aarch64/sve/struct_vect_16.c
index 6ecf89b..9e2a549 100644
--- a/gcc/testsuite/gcc.target/aarch64/sve/struct_vect_16.c
+++ b/gcc/testsuite/gcc.target/aarch64/sve/struct_vect_16.c
@@ -3,12 +3,12 @@
#include "struct_vect_14.c"
-/* { dg-final { scan-assembler-times {\tld2b\t{z[0-9]+.b - z[0-9]+.b}, p[0-7]/z, \[x[0-9]+\]\n} 1 } } */
+/* { dg-final { scan-assembler-times {\tld2b\t{z[0-9]+.b - z[0-9]+.b}, p[0-7]/z, \[x[0-9]+, x[0-9]+\]\n} 1 } } */
/* { dg-final { scan-assembler-times {\tld3b\t{z[0-9]+.b - z[0-9]+.b}, p[0-7]/z, \[x[0-9]+\]\n} 1 } } */
-/* { dg-final { scan-assembler-times {\tld4b\t{z[0-9]+.b - z[0-9]+.b}, p[0-7]/z, \[x[0-9]+\]\n} 1 } } */
-/* { dg-final { scan-assembler-times {\tst2b\t{z[0-9]+.b - z[0-9]+.b}, p[0-7], \[x[0-9]+\]\n} 1 } } */
+/* { dg-final { scan-assembler-times {\tld4b\t{z[0-9]+.b - z[0-9]+.b}, p[0-7]/z, \[x[0-9]+, x[0-9]+\]\n} 1 } } */
+/* { dg-final { scan-assembler-times {\tst2b\t{z[0-9]+.b - z[0-9]+.b}, p[0-7], \[x[0-9]+, x[0-9]+\]\n} 1 } } */
/* { dg-final { scan-assembler-times {\tst3b\t{z[0-9]+.b - z[0-9]+.b}, p[0-7], \[x[0-9]+\]\n} 1 } } */
-/* { dg-final { scan-assembler-times {\tst4b\t{z[0-9]+.b - z[0-9]+.b}, p[0-7], \[x[0-9]+\]\n} 1 } } */
+/* { dg-final { scan-assembler-times {\tst4b\t{z[0-9]+.b - z[0-9]+.b}, p[0-7], \[x[0-9]+, x[0-9]+\]\n} 1 } } */
/* { dg-final { scan-assembler-times {\tld2h\t{z[0-9]+.h - z[0-9]+.h}, p[0-7]/z, \[x[0-9]+\]\n} 2 } } */
/* { dg-final { scan-assembler-times {\tld3h\t{z[0-9]+.h - z[0-9]+.h}, p[0-7]/z, \[x[0-9]+\]\n} 2 } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/struct_vect_17.c b/gcc/testsuite/gcc.target/aarch64/sve/struct_vect_17.c
index 571c6d0..e791e2e 100644
--- a/gcc/testsuite/gcc.target/aarch64/sve/struct_vect_17.c
+++ b/gcc/testsuite/gcc.target/aarch64/sve/struct_vect_17.c
@@ -3,12 +3,12 @@
#include "struct_vect_14.c"
-/* { dg-final { scan-assembler-times {\tld2b\t{z[0-9]+.b - z[0-9]+.b}, p[0-7]/z, \[x[0-9]+\]\n} 1 } } */
+/* { dg-final { scan-assembler-times {\tld2b\t{z[0-9]+.b - z[0-9]+.b}, p[0-7]/z, \[x[0-9]+, x[0-9]+\]\n} 1 } } */
/* { dg-final { scan-assembler-times {\tld3b\t{z[0-9]+.b - z[0-9]+.b}, p[0-7]/z, \[x[0-9]+\]\n} 1 } } */
-/* { dg-final { scan-assembler-times {\tld4b\t{z[0-9]+.b - z[0-9]+.b}, p[0-7]/z, \[x[0-9]+\]\n} 1 } } */
-/* { dg-final { scan-assembler-times {\tst2b\t{z[0-9]+.b - z[0-9]+.b}, p[0-7], \[x[0-9]+\]\n} 1 } } */
+/* { dg-final { scan-assembler-times {\tld4b\t{z[0-9]+.b - z[0-9]+.b}, p[0-7]/z, \[x[0-9]+, x[0-9]+\]\n} 1 } } */
+/* { dg-final { scan-assembler-times {\tst2b\t{z[0-9]+.b - z[0-9]+.b}, p[0-7], \[x[0-9]+, x[0-9]+\]\n} 1 } } */
/* { dg-final { scan-assembler-times {\tst3b\t{z[0-9]+.b - z[0-9]+.b}, p[0-7], \[x[0-9]+\]\n} 1 } } */
-/* { dg-final { scan-assembler-times {\tst4b\t{z[0-9]+.b - z[0-9]+.b}, p[0-7], \[x[0-9]+\]\n} 1 } } */
+/* { dg-final { scan-assembler-times {\tst4b\t{z[0-9]+.b - z[0-9]+.b}, p[0-7], \[x[0-9]+, x[0-9]+\]\n} 1 } } */
/* { dg-final { scan-assembler-times {\tld2h\t{z[0-9]+.h - z[0-9]+.h}, p[0-7]/z, \[x[0-9]+\]\n} 2 } } */
/* { dg-final { scan-assembler-times {\tld3h\t{z[0-9]+.h - z[0-9]+.h}, p[0-7]/z, \[x[0-9]+\]\n} 2 } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/struct_vect_18.c b/gcc/testsuite/gcc.target/aarch64/sve/struct_vect_18.c
index dc912e6..3bc53b6 100644
--- a/gcc/testsuite/gcc.target/aarch64/sve/struct_vect_18.c
+++ b/gcc/testsuite/gcc.target/aarch64/sve/struct_vect_18.c
@@ -46,4 +46,4 @@ TEST (test)
/* { dg-final { scan-assembler-times {\tstr\td} 1 } } */
/* The only branches should be in the vectorized loop. */
-/* { dg-final { scan-assembler-times {\tb[a-z]+\t} 4 } } */
+/* { dg-final { scan-assembler-times {\tb[.a-z]+\t} 4 } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/struct_vect_19.c b/gcc/testsuite/gcc.target/aarch64/sve/struct_vect_19.c
index 6568dc7..833bf06 100644
--- a/gcc/testsuite/gcc.target/aarch64/sve/struct_vect_19.c
+++ b/gcc/testsuite/gcc.target/aarch64/sve/struct_vect_19.c
@@ -46,4 +46,4 @@ TEST (test)
/* Each function should have three branches: one directly to the exit
(n <= 0), one to the single scalar epilogue iteration (n == 1),
and one branch-back for the vectorized loop. */
-/* { dg-final { scan-assembler-times {\tb[a-z]+\t} 12 } } */
+/* { dg-final { scan-assembler-times {\tb[.a-z]+\t} 12 } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/struct_vect_20.c b/gcc/testsuite/gcc.target/aarch64/sve/struct_vect_20.c
index 6c3520c..858ca74 100644
--- a/gcc/testsuite/gcc.target/aarch64/sve/struct_vect_20.c
+++ b/gcc/testsuite/gcc.target/aarch64/sve/struct_vect_20.c
@@ -46,4 +46,4 @@ TEST (test)
/* { dg-final { scan-assembler-times {\tstr\td} 1 } } */
/* The only branches should be in the vectorized loop. */
-/* { dg-final { scan-assembler-times {\tb[a-z]+\t} 4 } } */
+/* { dg-final { scan-assembler-times {\tb[.a-z]+\t} 4 } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/struct_vect_21.c b/gcc/testsuite/gcc.target/aarch64/sve/struct_vect_21.c
index 4b2a5e4..95691fe 100644
--- a/gcc/testsuite/gcc.target/aarch64/sve/struct_vect_21.c
+++ b/gcc/testsuite/gcc.target/aarch64/sve/struct_vect_21.c
@@ -46,4 +46,4 @@ TEST (test)
/* Each function should have three branches: one directly to the exit
(n <= 0), one to the single scalar epilogue iteration (n == 1),
and one branch-back for the vectorized loop. */
-/* { dg-final { scan-assembler-times {\tb[a-z]+\t} 12 } } */
+/* { dg-final { scan-assembler-times {\tb[.a-z]+\t} 12 } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/struct_vect_22.c b/gcc/testsuite/gcc.target/aarch64/sve/struct_vect_22.c
index b615360..8eb0725 100644
--- a/gcc/testsuite/gcc.target/aarch64/sve/struct_vect_22.c
+++ b/gcc/testsuite/gcc.target/aarch64/sve/struct_vect_22.c
@@ -46,4 +46,4 @@ TEST (test)
/* { dg-final { scan-assembler-times {\tstr\td} 1 } } */
/* The only branches should be in the vectorized loop. */
-/* { dg-final { scan-assembler-times {\tb[a-z]+\t} 4 } } */
+/* { dg-final { scan-assembler-times {\tb[.a-z]+\t} 4 } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/struct_vect_23.c b/gcc/testsuite/gcc.target/aarch64/sve/struct_vect_23.c
index b529e03..705b235 100644
--- a/gcc/testsuite/gcc.target/aarch64/sve/struct_vect_23.c
+++ b/gcc/testsuite/gcc.target/aarch64/sve/struct_vect_23.c
@@ -46,4 +46,4 @@ TEST (test)
/* Each function should have three branches: one directly to the exit
(n <= 0), one to the single scalar epilogue iteration (n == 1),
and one branch-back for the vectorized loop. */
-/* { dg-final { scan-assembler-times {\tb[a-z]+\t} 12 } } */
+/* { dg-final { scan-assembler-times {\tb[.a-z]+\t} 12 } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/struct_vect_7.c b/gcc/testsuite/gcc.target/aarch64/sve/struct_vect_7.c
index b741901..3d3070e 100644
--- a/gcc/testsuite/gcc.target/aarch64/sve/struct_vect_7.c
+++ b/gcc/testsuite/gcc.target/aarch64/sve/struct_vect_7.c
@@ -78,9 +78,9 @@ g4 (TYPE *__restrict a, TYPE *__restrict b, TYPE *__restrict c,
}
}
-/* { dg-final { scan-assembler {\tld2b\t{z[0-9]+.b - z[0-9]+.b}, p[0-7]/z, \[x[0-9]+\]\n} } } */
+/* { dg-final { scan-assembler {\tld2b\t{z[0-9]+.b - z[0-9]+.b}, p[0-7]/z, \[x[0-9]+, x[0-9]+\]\n} } } */
/* { dg-final { scan-assembler {\tld3b\t{z[0-9]+.b - z[0-9]+.b}, p[0-7]/z, \[x[0-9]+\]\n} } } */
-/* { dg-final { scan-assembler {\tld4b\t{z[0-9]+.b - z[0-9]+.b}, p[0-7]/z, \[x[0-9]+\]\n} } } */
-/* { dg-final { scan-assembler {\tst2b\t{z[0-9]+.b - z[0-9]+.b}, p[0-7], \[x[0-9]+\]\n} } } */
+/* { dg-final { scan-assembler {\tld4b\t{z[0-9]+.b - z[0-9]+.b}, p[0-7]/z, \[x[0-9]+, x[0-9]+\]\n} } } */
+/* { dg-final { scan-assembler {\tst2b\t{z[0-9]+.b - z[0-9]+.b}, p[0-7], \[x[0-9]+, x[0-9]+\]\n} } } */
/* { dg-final { scan-assembler {\tst3b\t{z[0-9]+.b - z[0-9]+.b}, p[0-7], \[x[0-9]+\]\n} } } */
-/* { dg-final { scan-assembler {\tst4b\t{z[0-9]+.b - z[0-9]+.b}, p[0-7], \[x[0-9]+\]\n} } } */
+/* { dg-final { scan-assembler {\tst4b\t{z[0-9]+.b - z[0-9]+.b}, p[0-7], \[x[0-9]+, x[0-9]+\]\n} } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/unroll-1.c b/gcc/testsuite/gcc.target/aarch64/sve/unroll-1.c
index d4353009..e33777f 100644
--- a/gcc/testsuite/gcc.target/aarch64/sve/unroll-1.c
+++ b/gcc/testsuite/gcc.target/aarch64/sve/unroll-1.c
@@ -10,4 +10,4 @@ fully_peel_me (double *x)
x[i] = x[i] * 2;
}
-/* { dg-final { scan-assembler-times {b..\t\.L.\n} 1 } } */
+/* { dg-final { scan-assembler-times {\tb[.a-z]+\t} 1 } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/vec_init_1.c b/gcc/testsuite/gcc.target/aarch64/sve/vec_init_1.c
index 6042606..1624ab1 100644
--- a/gcc/testsuite/gcc.target/aarch64/sve/vec_init_1.c
+++ b/gcc/testsuite/gcc.target/aarch64/sve/vec_init_1.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -ftree-vectorize" } */
+/* { dg-options "-O2 -ftree-vectorize -fno-tree-loop-distribute-patterns" } */
#include <stdint.h>
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/while_1.c b/gcc/testsuite/gcc.target/aarch64/sve/while_1.c
index a93a04b..2cfb3f6 100644
--- a/gcc/testsuite/gcc.target/aarch64/sve/while_1.c
+++ b/gcc/testsuite/gcc.target/aarch64/sve/while_1.c
@@ -26,14 +26,14 @@
TEST_ALL (ADD_LOOP)
/* { dg-final { scan-assembler-not {\tuqdec} } } */
-/* { dg-final { scan-assembler-times {\twhilelo\tp[0-7]\.b, xzr,} 2 } } */
-/* { dg-final { scan-assembler-times {\twhilelo\tp[0-7]\.b, x[0-9]+,} 2 } } */
-/* { dg-final { scan-assembler-times {\twhilelo\tp[0-7]\.h, xzr,} 2 } } */
-/* { dg-final { scan-assembler-times {\twhilelo\tp[0-7]\.h, x[0-9]+,} 2 } } */
-/* { dg-final { scan-assembler-times {\twhilelo\tp[0-7]\.s, xzr,} 3 } } */
-/* { dg-final { scan-assembler-times {\twhilelo\tp[0-7]\.s, x[0-9]+,} 3 } } */
-/* { dg-final { scan-assembler-times {\twhilelo\tp[0-7]\.d, xzr,} 3 } } */
-/* { dg-final { scan-assembler-times {\twhilelo\tp[0-7]\.d, x[0-9]+,} 3 } } */
+/* { dg-final { scan-assembler-times {\twhilelo\tp[0-7]\.b, wzr,} 2 } } */
+/* { dg-final { scan-assembler-times {\twhilelo\tp[0-7]\.b, w[0-9]+,} 2 } } */
+/* { dg-final { scan-assembler-times {\twhilelo\tp[0-7]\.h, wzr,} 2 } } */
+/* { dg-final { scan-assembler-times {\twhilelo\tp[0-7]\.h, w[0-9]+,} 2 } } */
+/* { dg-final { scan-assembler-times {\twhilelo\tp[0-7]\.s, wzr,} 3 } } */
+/* { dg-final { scan-assembler-times {\twhilelo\tp[0-7]\.s, w[0-9]+,} 3 } } */
+/* { dg-final { scan-assembler-times {\twhilelo\tp[0-7]\.d, wzr,} 3 } } */
+/* { dg-final { scan-assembler-times {\twhilelo\tp[0-7]\.d, w[0-9]+,} 3 } } */
/* { dg-final { scan-assembler-times {\tld1b\tz[0-9]+\.b, p[0-7]/z, \[x0, x[0-9]+\]\n} 2 } } */
/* { dg-final { scan-assembler-times {\tst1b\tz[0-9]+\.b, p[0-7], \[x0, x[0-9]+\]\n} 2 } } */
/* { dg-final { scan-assembler-times {\tld1h\tz[0-9]+\.h, p[0-7]/z, \[x0, x[0-9]+, lsl 1\]\n} 2 } } */
@@ -42,3 +42,4 @@ TEST_ALL (ADD_LOOP)
/* { dg-final { scan-assembler-times {\tst1w\tz[0-9]+\.s, p[0-7], \[x0, x[0-9]+, lsl 2\]\n} 3 } } */
/* { dg-final { scan-assembler-times {\tld1d\tz[0-9]+\.d, p[0-7]/z, \[x0, x[0-9]+, lsl 3\]\n} 3 } } */
/* { dg-final { scan-assembler-times {\tst1d\tz[0-9]+\.d, p[0-7], \[x0, x[0-9]+, lsl 3\]\n} 3 } } */
+/* { dg-final { scan-assembler-times {\tb\.any\t} 10 } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/sve2/aarch64-sve2.exp b/gcc/testsuite/gcc.target/aarch64/sve2/aarch64-sve2.exp
new file mode 100644
index 0000000..557de27
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve2/aarch64-sve2.exp
@@ -0,0 +1,52 @@
+# Specific regression driver for AArch64 SVE2.
+# Copyright (C) 2009-2019 Free Software Foundation, Inc.
+# Contributed by ARM Ltd.
+#
+# 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/>. */
+
+# GCC testsuite that uses the `dg.exp' driver.
+
+# Exit immediately if this isn't an AArch64 target.
+if {![istarget aarch64*-*-*] } then {
+ return
+}
+
+# Load support procs.
+load_lib gcc-dg.exp
+
+# If a testcase doesn't have special options, use these.
+global DEFAULT_CFLAGS
+if ![info exists DEFAULT_CFLAGS] then {
+ set DEFAULT_CFLAGS " -ansi -pedantic-errors"
+}
+
+# Initialize `dg'.
+dg-init
+
+# Force SVE2 if we're not testing it already.
+if { [check_effective_target_aarch64_sve2] } {
+ set sve2_flags ""
+} else {
+ set sve2_flags "-march=armv8.5-a+sve2"
+}
+
+# Main loop.
+dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.\[cCS\]]] \
+ $sve2_flags $DEFAULT_CFLAGS
+
+# All done.
+dg-finish
diff --git a/gcc/testsuite/gcc.target/aarch64/sve2/average_1.c b/gcc/testsuite/gcc.target/aarch64/sve2/average_1.c
new file mode 100644
index 0000000..3c00710
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve2/average_1.c
@@ -0,0 +1,46 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -ftree-vectorize -fdump-tree-vect-details --save-temps" } */
+
+#include <stdint.h>
+
+#define AVERAGE(TYPE, BIGGER, RND) \
+TYPE __attribute__ ((noinline, noclone)) \
+avg_##TYPE##_##RND (TYPE *restrict x, TYPE *restrict y, TYPE *restrict z, \
+ int n) \
+{ \
+ for (int i = 0; i < n; i++) \
+ { \
+ z[i] = ((BIGGER)x[i] + y[i] + RND) >> 1; \
+ } \
+}
+
+AVERAGE (int8_t, int64_t, 0)
+AVERAGE (int16_t, int64_t, 0)
+AVERAGE (int32_t, int64_t, 0)
+AVERAGE (uint8_t, uint64_t, 0)
+AVERAGE (uint16_t, uint64_t, 0)
+AVERAGE (uint32_t, uint64_t, 0)
+AVERAGE (int8_t, int64_t, 1)
+AVERAGE (int16_t, int64_t, 1)
+AVERAGE (int32_t, int64_t, 1)
+AVERAGE (uint8_t, uint64_t, 1)
+AVERAGE (uint16_t, uint64_t, 1)
+AVERAGE (uint32_t, uint64_t, 1)
+
+/* { dg-final { scan-tree-dump-times "vectorized 1 loops in function" 12 "vect" } } */
+
+/* { dg-final { scan-assembler-times {\tshadd\tz[0-9]+\.b, p[0-7]/m, z[0-9]+\.b, z[0-9]+\.b\n} 1 } } */
+/* { dg-final { scan-assembler-times {\tshadd\tz[0-9]+\.h, p[0-7]/m, z[0-9]+\.h, z[0-9]+\.h\n} 1 } } */
+/* { dg-final { scan-assembler-times {\tshadd\tz[0-9]+\.s, p[0-7]/m, z[0-9]+\.s, z[0-9]+\.s\n} 1 } } */
+
+/* { dg-final { scan-assembler-times {\tuhadd\tz[0-9]+\.b, p[0-7]/m, z[0-9]+\.b, z[0-9]+\.b\n} 1 } } */
+/* { dg-final { scan-assembler-times {\tuhadd\tz[0-9]+\.h, p[0-7]/m, z[0-9]+\.h, z[0-9]+\.h\n} 1 } } */
+/* { dg-final { scan-assembler-times {\tuhadd\tz[0-9]+\.s, p[0-7]/m, z[0-9]+\.s, z[0-9]+\.s\n} 1 } } */
+
+/* { dg-final { scan-assembler-times {\tsrhadd\tz[0-9]+\.b, p[0-7]/m, z[0-9]+\.b, z[0-9]+\.b\n} 1 } } */
+/* { dg-final { scan-assembler-times {\tsrhadd\tz[0-9]+\.h, p[0-7]/m, z[0-9]+\.h, z[0-9]+\.h\n} 1 } } */
+/* { dg-final { scan-assembler-times {\tsrhadd\tz[0-9]+\.s, p[0-7]/m, z[0-9]+\.s, z[0-9]+\.s\n} 1 } } */
+
+/* { dg-final { scan-assembler-times {\turhadd\tz[0-9]+\.b, p[0-7]/m, z[0-9]+\.b, z[0-9]+\.b\n} 1 } } */
+/* { dg-final { scan-assembler-times {\turhadd\tz[0-9]+\.h, p[0-7]/m, z[0-9]+\.h, z[0-9]+\.h\n} 1 } } */
+/* { dg-final { scan-assembler-times {\turhadd\tz[0-9]+\.s, p[0-7]/m, z[0-9]+\.s, z[0-9]+\.s\n} 1 } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/target_attr_10.c b/gcc/testsuite/gcc.target/aarch64/target_attr_10.c
index 1849904..d96a873 100644
--- a/gcc/testsuite/gcc.target/aarch64/target_attr_10.c
+++ b/gcc/testsuite/gcc.target/aarch64/target_attr_10.c
@@ -13,4 +13,4 @@ foo (uint8x16_t a, uint8x16_t b, uint8x16_t c)
return vbslq_u8 (a, b, c); /* { dg-message "called from here" } */
}
-/* { dg-error "inlining failed in call to always_inline" "" { target *-*-* } 0 } */
+/* { dg-error "inlining failed in call to 'always_inline'" "" { target *-*-* } 0 } */
diff --git a/gcc/testsuite/gcc.target/aarch64/torture/simd-abi-4.c b/gcc/testsuite/gcc.target/aarch64/torture/simd-abi-4.c
index e399690..b8d7ce0 100644
--- a/gcc/testsuite/gcc.target/aarch64/torture/simd-abi-4.c
+++ b/gcc/testsuite/gcc.target/aarch64/torture/simd-abi-4.c
@@ -1,4 +1,5 @@
-/* dg-do run */
+/* { dg-do run } */
+/* { dg-require-effective-target aarch64_variant_pcs } */
/* { dg-additional-options "-std=c99" } */
diff --git a/gcc/testsuite/gcc.target/aarch64/usadv16qi-dotprod.c b/gcc/testsuite/gcc.target/aarch64/usadv16qi-dotprod.c
new file mode 100644
index 0000000..ea8de4d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/usadv16qi-dotprod.c
@@ -0,0 +1,30 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target arm_v8_2a_dotprod_neon_ok } */
+/* { dg-add-options arm_v8_2a_dotprod_neon } */
+/* { dg-additional-options "-O3" } */
+
+#pragma GCC target "+nosve"
+
+#define N 1024
+
+unsigned char pix1[N], pix2[N];
+
+int foo (void)
+{
+ int i_sum = 0;
+ int i;
+
+ for (i = 0; i < N; i++)
+ i_sum += __builtin_abs (pix1[i] - pix2[i]);
+
+ return i_sum;
+}
+
+/* { dg-final { scan-assembler-not {\tushll\t} } } */
+/* { dg-final { scan-assembler-not {\tushll2\t} } } */
+/* { dg-final { scan-assembler-not {\tusubl\t} } } */
+/* { dg-final { scan-assembler-not {\tusubl2\t} } } */
+/* { dg-final { scan-assembler-not {\tabs\t} } } */
+
+/* { dg-final { scan-assembler {\tuabd\t} } } */
+/* { dg-final { scan-assembler {\tudot\t} } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/usadv16qi.c b/gcc/testsuite/gcc.target/aarch64/usadv16qi.c
index 69ceaf4..a66e120 100644
--- a/gcc/testsuite/gcc.target/aarch64/usadv16qi.c
+++ b/gcc/testsuite/gcc.target/aarch64/usadv16qi.c
@@ -1,7 +1,7 @@
/* { dg-do compile } */
/* { dg-options "-O3" } */
-#pragma GCC target "+nosve"
+#pragma GCC target "+nosve+nodotprod"
#define N 1024
diff --git a/gcc/testsuite/gcc.target/aarch64/vect-fmovd-zero.c b/gcc/testsuite/gcc.target/aarch64/vect-fmovd-zero.c
index c987f5f..a51aa33 100644
--- a/gcc/testsuite/gcc.target/aarch64/vect-fmovd-zero.c
+++ b/gcc/testsuite/gcc.target/aarch64/vect-fmovd-zero.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -ftree-vectorize -fdump-tree-vect-all -fno-vect-cost-model" } */
+/* { dg-options "-O2 -ftree-vectorize -fdump-tree-vect-all -fno-vect-cost-model -fno-tree-loop-distribute-patterns" } */
#pragma GCC target "+nosve"
diff --git a/gcc/testsuite/gcc.target/aarch64/vect-fmovf-zero.c b/gcc/testsuite/gcc.target/aarch64/vect-fmovf-zero.c
index 22a0535..8dfd26b 100644
--- a/gcc/testsuite/gcc.target/aarch64/vect-fmovf-zero.c
+++ b/gcc/testsuite/gcc.target/aarch64/vect-fmovf-zero.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -ftree-vectorize -fdump-tree-vect-all -fno-vect-cost-model" } */
+/* { dg-options "-O2 -ftree-vectorize -fdump-tree-vect-all -fno-vect-cost-model -fno-tree-loop-distribute-patterns" } */
#pragma GCC target "+nosve"
diff --git a/gcc/testsuite/gcc.target/arc/and-cnst-size.c b/gcc/testsuite/gcc.target/arc/and-cnst-size.c
new file mode 100644
index 0000000..9437be9
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arc/and-cnst-size.c
@@ -0,0 +1,16 @@
+/* Tests to check if and instructions are emitted efficiently. */
+/* { dg-require-effective-target codedensity } */
+/* { dg-options "-Os" } */
+
+int check_bclr (int a)
+{
+ return a & (~0x40);
+}
+
+int check_bmskn (int a)
+{
+ return a & (-128);
+}
+
+/* { dg-final { scan-assembler "bclr_s" } } */
+/* { dg-final { scan-assembler "bmskn" } } */
diff --git a/gcc/testsuite/gcc.target/arc/arc700-stld-hazard.c b/gcc/testsuite/gcc.target/arc/arc700-stld-hazard.c
index eba03d8..49b5664 100644
--- a/gcc/testsuite/gcc.target/arc/arc700-stld-hazard.c
+++ b/gcc/testsuite/gcc.target/arc/arc700-stld-hazard.c
@@ -1,5 +1,6 @@
/* { dg-do compile } */
-/* { dg-options "-mcpu=arc700 -mno-sdata" } */
+/* { dg-skip-if "" { ! { clmcpu } } } */
+/* { dg-options "-mcpu=arc700 -mno-sdata -O2" } */
volatile int a;
volatile int b;
@@ -11,4 +12,4 @@ foo ()
b = a;
}
-/* { dg-final { scan-assembler "st r\[0-9\]+,\\\[@a\\\]\[^\n\]*\n\[ \t\]+nop_s\[^\n\]*\n\[ \t\]+nop_s\[^\n\]*\n\[ \t\]+ld r\[0-9\]+,\\\[@a\\\]" } } */
+/* { dg-final { scan-assembler "st\\s+r\[0-9\]+,\\\[@a\\\]\\.*\[^\n\]*\n\[ \t\]+nop_s\[^\n\]*\n\[ \t\]+nop_s\[^\n\]*\n\[ \t\]+ld\\s+r\[0-9\]+,\\\[@a\\\]" } } */
diff --git a/gcc/testsuite/gcc.target/arc/cmem-1.c b/gcc/testsuite/gcc.target/arc/cmem-1.c
index 8ed5dcf..f0e7a8d 100644
--- a/gcc/testsuite/gcc.target/arc/cmem-1.c
+++ b/gcc/testsuite/gcc.target/arc/cmem-1.c
@@ -6,6 +6,6 @@
#include "cmem-st.inc"
-/* { dg-final { scan-assembler "xst " } } */
-/* { dg-final { scan-assembler "xstw " } } */
-/* { dg-final { scan-assembler "xstb " } } */
+/* { dg-final { scan-assembler "xst\\s" } } */
+/* { dg-final { scan-assembler "xstw\\s" } } */
+/* { dg-final { scan-assembler "xstb\\s" } } */
diff --git a/gcc/testsuite/gcc.target/arc/cmem-2.c b/gcc/testsuite/gcc.target/arc/cmem-2.c
index 39bfb28..a63df0eb 100644
--- a/gcc/testsuite/gcc.target/arc/cmem-2.c
+++ b/gcc/testsuite/gcc.target/arc/cmem-2.c
@@ -6,6 +6,6 @@
#include "cmem-ld.inc"
-/* { dg-final { scan-assembler "xld " } } */
-/* { dg-final { scan-assembler "xldw " } } */
-/* { dg-final { scan-assembler "xldb " } } */
+/* { dg-final { scan-assembler "xld\\s" } } */
+/* { dg-final { scan-assembler "xldw\\s" } } */
+/* { dg-final { scan-assembler "xldb\\s" } } */
diff --git a/gcc/testsuite/gcc.target/arc/cmem-3.c b/gcc/testsuite/gcc.target/arc/cmem-3.c
index 109084f..d3d1d595 100644
--- a/gcc/testsuite/gcc.target/arc/cmem-3.c
+++ b/gcc/testsuite/gcc.target/arc/cmem-3.c
@@ -6,6 +6,6 @@
#include "cmem-st.inc"
-/* { dg-final { scan-assembler "xst " } } */
-/* { dg-final { scan-assembler "xstw " } } */
-/* { dg-final { scan-assembler "xstb " } } */
+/* { dg-final { scan-assembler "xst\\s" } } */
+/* { dg-final { scan-assembler "xstw\\s" } } */
+/* { dg-final { scan-assembler "xstb\\s" } } */
diff --git a/gcc/testsuite/gcc.target/arc/cmem-4.c b/gcc/testsuite/gcc.target/arc/cmem-4.c
index 4ac8a22..2160f1f 100644
--- a/gcc/testsuite/gcc.target/arc/cmem-4.c
+++ b/gcc/testsuite/gcc.target/arc/cmem-4.c
@@ -6,6 +6,6 @@
#include "cmem-ld.inc"
-/* { dg-final { scan-assembler "xld " } } */
-/* { dg-final { scan-assembler "xldw " } } */
-/* { dg-final { scan-assembler "xldb " } } */
+/* { dg-final { scan-assembler "xld\\s" } } */
+/* { dg-final { scan-assembler "xldw\\s" } } */
+/* { dg-final { scan-assembler "xldb\\s" } } */
diff --git a/gcc/testsuite/gcc.target/arc/cmem-5.c b/gcc/testsuite/gcc.target/arc/cmem-5.c
index 451218b..db4142f 100644
--- a/gcc/testsuite/gcc.target/arc/cmem-5.c
+++ b/gcc/testsuite/gcc.target/arc/cmem-5.c
@@ -6,6 +6,6 @@
#include "cmem-st.inc"
-/* { dg-final { scan-assembler "xst " } } */
-/* { dg-final { scan-assembler "xstw " } } */
-/* { dg-final { scan-assembler "xstb " } } */
+/* { dg-final { scan-assembler "xst\\s" } } */
+/* { dg-final { scan-assembler "xstw\\s" } } */
+/* { dg-final { scan-assembler "xstb\\s" } } */
diff --git a/gcc/testsuite/gcc.target/arc/cmem-6.c b/gcc/testsuite/gcc.target/arc/cmem-6.c
index 0ed0608..ac22ad5 100644
--- a/gcc/testsuite/gcc.target/arc/cmem-6.c
+++ b/gcc/testsuite/gcc.target/arc/cmem-6.c
@@ -6,6 +6,6 @@
#include "cmem-ld.inc"
-/* { dg-final { scan-assembler "xld " } } */
-/* { dg-final { scan-assembler "xldw " } } */
-/* { dg-final { scan-assembler "xldb " } } */
+/* { dg-final { scan-assembler "xld\\s" } } */
+/* { dg-final { scan-assembler "xldw\\s" } } */
+/* { dg-final { scan-assembler "xldb\\s" } } */
diff --git a/gcc/testsuite/gcc.target/arc/jumptable.c b/gcc/testsuite/gcc.target/arc/jumptable.c
index fbc58e3..ffbcf93 100644
--- a/gcc/testsuite/gcc.target/arc/jumptable.c
+++ b/gcc/testsuite/gcc.target/arc/jumptable.c
@@ -31,4 +31,4 @@ int switchCase(int value, int b)
}
/* { dg-final { scan-assembler-times "bih" 1 } } */
-/* { dg-final { scan-assembler-times "b_s" 8 } } */
+/* { dg-final { scan-assembler-times "b_s" 6 } } */
diff --git a/gcc/testsuite/gcc.target/arc/loop-4.c b/gcc/testsuite/gcc.target/arc/loop-4.c
index dbe5d3f..06de418 100644
--- a/gcc/testsuite/gcc.target/arc/loop-4.c
+++ b/gcc/testsuite/gcc.target/arc/loop-4.c
@@ -3,12 +3,13 @@
/* { dg-options "-Os -fbranch-count-reg" } */
-void fn1(void *p1, int p2, int p3)
+int fn1(void *p1, int p2, int p3)
{
char *d = p1;
do
*d++ = p2;
while (--p3);
+ return *d;
}
/* { dg-final { scan-assembler "lp_count" } } */
diff --git a/gcc/testsuite/gcc.target/arc/mov-cnst-size.c b/gcc/testsuite/gcc.target/arc/mov-cnst-size.c
new file mode 100644
index 0000000..916dd8b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arc/mov-cnst-size.c
@@ -0,0 +1,42 @@
+/* Tests to check if mov instructions are emitted efficiently. */
+/* { dg-require-effective-target codedensity } */
+/* { dg-options "-Os" } */
+
+int rule1 (void)
+{
+ return 0x3f000000;
+}
+
+int rule2 (void)
+{
+ return 0x3f00;
+}
+
+int rule3 (void)
+{
+ return 0x3f0000;
+}
+
+int rule4 (void)
+{
+ return 0x22000;
+}
+
+int rule5 (void)
+{
+ return 0x8000001f;
+}
+
+int rule6 (void)
+{
+ return 0x3fffff;
+}
+
+/* { dg-final { scan-assembler "ror8\\s+r0,63" } } */
+/* { dg-final { scan-assembler "lsl8\\s+r0,63" } } */
+/* { dg-final { scan-assembler "lsl16\\s+r0,63" } } */
+/* { dg-final { scan-assembler "ror\\s+r0,63" } } */
+/* { dg-final { scan-assembler "mov_s\\s+r0,17" } } */
+/* { dg-final { scan-assembler "asl_s\\s+r0,r0,13" } } */
+/* { dg-final { scan-assembler "mov_s\\s+r0,-1" } } */
+/* { dg-final { scan-assembler "bmsk_s\\s+r0,r0,21" } } */
diff --git a/gcc/testsuite/gcc.target/arc/movh_cl-1.c b/gcc/testsuite/gcc.target/arc/movh_cl-1.c
index 9c0036c..7e838bb 100644
--- a/gcc/testsuite/gcc.target/arc/movh_cl-1.c
+++ b/gcc/testsuite/gcc.target/arc/movh_cl-1.c
@@ -36,4 +36,4 @@ woof ()
func (xx.raw);
}
-/* { dg-final { scan-assembler "movh\.cl r\[0-9\]+,0xc0000000>>16" } } */
+/* { dg-final { scan-assembler "movh\.cl\\s+r\[0-9\]+,0xc0000000>>16" } } */
diff --git a/gcc/testsuite/gcc.target/arc/or-cnst-size.c b/gcc/testsuite/gcc.target/arc/or-cnst-size.c
new file mode 100644
index 0000000..c4a9f0f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arc/or-cnst-size.c
@@ -0,0 +1,16 @@
+/* Tests to check if or instructions are emitted efficiently. */
+/* { dg-require-effective-target codedensity } */
+/* { dg-options "-Os" } */
+
+int check_bset1 (int a)
+{
+ return a | 0x80000000;
+}
+
+int check_bset2(int a)
+{
+ return a | 0x2022;
+}
+
+/* { dg-final { scan-assembler-times "bset_s" 2 } } */
+/* { dg-final { scan-assembler "or" } } */
diff --git a/gcc/testsuite/gcc.target/arc/pr89838.c b/gcc/testsuite/gcc.target/arc/pr89838.c
new file mode 100644
index 0000000..559434a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arc/pr89838.c
@@ -0,0 +1,16 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target tls } */
+/* { dg-options "-O2" } */
+
+extern void foo (void);
+extern void bar (void *);
+
+struct {
+ int __attribute__(()) a;
+ int __attribute__(()) b;
+} __thread c __attribute__((tls_model("initial-exec")));
+
+void foo (void)
+{
+ bar (&c.b);
+}
diff --git a/gcc/testsuite/gcc.target/arc/sdata-3.c b/gcc/testsuite/gcc.target/arc/sdata-3.c
index 4df7074..df66cbd 100644
--- a/gcc/testsuite/gcc.target/arc/sdata-3.c
+++ b/gcc/testsuite/gcc.target/arc/sdata-3.c
@@ -2,7 +2,7 @@
for variables which are having a different alignment
than the default data type indicates. */
/* { dg-do compile } */
-/* { dg-options "-O2" } */
+/* { dg-options "-O2 -msdata" } */
int g_a __attribute__ ((aligned (1)));
int g_b;
@@ -24,13 +24,13 @@ TEST (b, int)
TEST (c, short)
TEST (d, char)
-/* { dg-final { scan-assembler "ld r2,\\\[gp,@g_a@sda\\\]" } } */
-/* { dg-final { scan-assembler "ld.as r2,\\\[gp,@g_b@sda\\\]" } } */
-/* { dg-final { scan-assembler "ld\[hw\]\\\.as r2,\\\[gp,@g_c@sda\\\]" } } */
-/* { dg-final { scan-assembler "ldb r2,\\\[gp,@g_d@sda\\\]" } } */
+/* { dg-final { scan-assembler "ld\\s+r2,\\\[gp,@g_a@sda\\\]" } } */
+/* { dg-final { scan-assembler "ld.as\\s+r2,\\\[gp,@g_b@sda\\\]" } } */
+/* { dg-final { scan-assembler "ld\[hw\]\\\.as\\s+r2,\\\[gp,@g_c@sda\\\]" } } */
+/* { dg-final { scan-assembler "ldb\\s+r2,\\\[gp,@g_d@sda\\\]" } } */
-/* { dg-final { scan-assembler "st r0,\\\[gp,@g_a@sda\\\]" } } */
-/* { dg-final { scan-assembler "st_s r0,\\\[gp,@g_b@sda\\\]" { target { arcem || archs } } } } */
-/* { dg-final { scan-assembler "st\\\.as r0,\\\[gp,@g_b@sda\\\]" { target { arc700 || arc6xx } } } } */
-/* { dg-final { scan-assembler "st\[hw\]\\\.as r0,\\\[gp,@g_c@sda\\\]" } } */
-/* { dg-final { scan-assembler "stb r0,\\\[gp,@g_d@sda\\\]" } } */
+/* { dg-final { scan-assembler "st\\s+r0,\\\[gp,@g_a@sda\\\]" } } */
+/* { dg-final { scan-assembler "st_s\\s+r0,\\\[gp,@g_b@sda\\\]" { target { codedensity } } } } */
+/* { dg-final { scan-assembler "st\\\.as\\s+r0,\\\[gp,@g_b@sda\\\]" { target { ! { codedensity } } } } } */
+/* { dg-final { scan-assembler "st\[hw\]\\\.as\\s+r0,\\\[gp,@g_c@sda\\\]" } } */
+/* { dg-final { scan-assembler "stb\\s+r0,\\\[gp,@g_d@sda\\\]" } } */
diff --git a/gcc/testsuite/gcc.target/arc/store-merge-1.c b/gcc/testsuite/gcc.target/arc/store-merge-1.c
index 4bb8dcb..e9d4e57 100644
--- a/gcc/testsuite/gcc.target/arc/store-merge-1.c
+++ b/gcc/testsuite/gcc.target/arc/store-merge-1.c
@@ -14,4 +14,4 @@ int sigemptyset2 (sigset_t *set)
return 0;
}
-/* { dg-final { scan-assembler-times "st 0,\\\[r" 2 } } */
+/* { dg-final { scan-assembler-times "std\\s*0,\\\[r" 1 } } */
diff --git a/gcc/testsuite/gcc.target/arc/tmac-1.c b/gcc/testsuite/gcc.target/arc/tmac-1.c
index e59df5f6..3fcabf5 100644
--- a/gcc/testsuite/gcc.target/arc/tmac-1.c
+++ b/gcc/testsuite/gcc.target/arc/tmac-1.c
@@ -1,5 +1,5 @@
-/* { dg-skip-if "" { ! { clmcpu } } } */
/* { dg-do compile } */
+/* { dg-skip-if "" { ! { clmcpu } } } */
/* { dg-options "-O2 -mcpu=archs -mmpy-option=8" } */
/* Test MAC operation for MPY_OPTION = 8. */
@@ -9,4 +9,3 @@
/* { dg-final { scan-assembler "macdu" } } */
/* { dg-final { scan-assembler "mpyd " } } */
/* { dg-final { scan-assembler "mpydu" } } */
-
diff --git a/gcc/testsuite/gcc.target/arc/tmac-2.c b/gcc/testsuite/gcc.target/arc/tmac-2.c
index f0136ba..ee1339a 100644
--- a/gcc/testsuite/gcc.target/arc/tmac-2.c
+++ b/gcc/testsuite/gcc.target/arc/tmac-2.c
@@ -1,5 +1,5 @@
-/* { dg-skip-if "" { ! { clmcpu } } } */
/* { dg-do compile } */
+/* { dg-skip-if "" { ! { clmcpu } } } */
/* { dg-options "-O2 -mcpu=archs -mmpy-option=7" } */
/* Test MAC operation for MPY_OPTION = 7. */
diff --git a/gcc/testsuite/gcc.target/arm/attr-neon-builtin-fail.c b/gcc/testsuite/gcc.target/arm/attr-neon-builtin-fail.c
index 05dc579..fb6e0b9 100644
--- a/gcc/testsuite/gcc.target/arm/attr-neon-builtin-fail.c
+++ b/gcc/testsuite/gcc.target/arm/attr-neon-builtin-fail.c
@@ -14,5 +14,5 @@ foo (uint8x16_t *p)
*p = vmovq_n_u8 (3); /* { dg-message "called from here" } */
}
-/* { dg-error "inlining failed in call to always_inline" "" { target *-*-* } 0 } */
+/* { dg-error "inlining failed in call to 'always_inline'" "" { target *-*-* } 0 } */
diff --git a/gcc/testsuite/gcc.target/arm/ivopts.c b/gcc/testsuite/gcc.target/arm/ivopts.c
index 2bb6cc4..5d27240 100644
--- a/gcc/testsuite/gcc.target/arm/ivopts.c
+++ b/gcc/testsuite/gcc.target/arm/ivopts.c
@@ -1,5 +1,5 @@
/* { dg-do assemble } */
-/* { dg-options "-Os -fdump-tree-ivopts -save-temps" } */
+/* { dg-options "-Os -fdump-tree-ivopts -save-temps -fno-tree-loop-distribute-patterns" } */
void
tr5 (short array[], int n)
diff --git a/gcc/testsuite/gcc.target/arm/ssadv16qi.c b/gcc/testsuite/gcc.target/arm/ssadv16qi.c
new file mode 100644
index 0000000..dba5ef4
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/ssadv16qi.c
@@ -0,0 +1,29 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-O3 --save-temps" } */
+/* { dg-require-effective-target arm_fp_ok } */
+/* { dg-require-effective-target arm_neon_ok } */
+/* { dg-add-options arm_neon } */
+
+#define N 1024
+
+signed char pix1[N], pix2[N];
+
+int
+foo (void)
+{
+ int i_sum = 0;
+ int i;
+
+ for (i = 0; i < N; i++)
+ i_sum += __builtin_abs (pix1[i] - pix2[i]);
+
+ return i_sum;
+}
+
+/* { dg-final { scan-assembler {\tvabdl\.s8\t} } } */
+/* { dg-final { scan-assembler {\tvabal\.s8\t} } } */
+/* { dg-final { scan-assembler {\tvpadal\.s16\t} } } */
+
+/* { dg-final { scan-assembler-not {\tvmovl} } } */
+/* { dg-final { scan-assembler-not {\tvsub} } } */
+/* { dg-final { scan-assembler-not {\tvabs} } } */
diff --git a/gcc/testsuite/gcc.target/arm/usadv16qi.c b/gcc/testsuite/gcc.target/arm/usadv16qi.c
new file mode 100644
index 0000000..d744bcb
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/usadv16qi.c
@@ -0,0 +1,29 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-O3 --save-temps" } */
+/* { dg-require-effective-target arm_fp_ok } */
+/* { dg-require-effective-target arm_neon_ok } */
+/* { dg-add-options arm_neon } */
+
+#define N 1024
+
+unsigned char pix1[N], pix2[N];
+
+int
+foo (void)
+{
+ int i_sum = 0;
+ int i;
+
+ for (i = 0; i < N; i++)
+ i_sum += __builtin_abs (pix1[i] - pix2[i]);
+
+ return i_sum;
+}
+
+/* { dg-final { scan-assembler {\tvabdl\.u8\t} } } */
+/* { dg-final { scan-assembler {\tvabal\.u8\t} } } */
+/* { dg-final { scan-assembler {\tvpadal\.u16\t} } } */
+
+/* { dg-final { scan-assembler-not {\tvmovl} } } */
+/* { dg-final { scan-assembler-not {\tvsub} } } */
+/* { dg-final { scan-assembler-not {\tvabs} } } */
diff --git a/gcc/testsuite/gcc.target/i386/asm-flag-0.c b/gcc/testsuite/gcc.target/i386/asm-flag-0.c
index b0c0523..e7bd1a5 100644
--- a/gcc/testsuite/gcc.target/i386/asm-flag-0.c
+++ b/gcc/testsuite/gcc.target/i386/asm-flag-0.c
@@ -11,5 +11,5 @@ void a(void)
void b(void)
{
char x;
- asm("" : "=@ccbad"(x)); /* { dg-error "unknown asm flag output" } */
+ asm("" : "=@ccbad"(x)); /* { dg-error "unknown 'asm' flag output" } */
}
diff --git a/gcc/testsuite/gcc.target/i386/attr-aligned-2.c b/gcc/testsuite/gcc.target/i386/attr-aligned-2.c
index b99a28a..3841782 100644
--- a/gcc/testsuite/gcc.target/i386/attr-aligned-2.c
+++ b/gcc/testsuite/gcc.target/i386/attr-aligned-2.c
@@ -14,8 +14,8 @@ void f4 (void);
ALIGN (4)
void f4 (void) { }
-/* { dg-final { scan-assembler ".align 4\n\t.globl\tf4" } } */
-
+/* { dg-final { scan-assembler ".align 4\n\t.globl\tf4" { target { ! *-*-darwin* } } } } */
+/* { dg-final { scan-assembler {.align[ \t]2,0x90\n\t.globl[ \t]_f4} { target *-*-darwin* } } } */
void g (void) { }
diff --git a/gcc/testsuite/gcc.target/i386/avx-1.c b/gcc/testsuite/gcc.target/i386/avx-1.c
index e09f5a1..741b3c4 100644
--- a/gcc/testsuite/gcc.target/i386/avx-1.c
+++ b/gcc/testsuite/gcc.target/i386/avx-1.c
@@ -444,8 +444,8 @@
#define __builtin_ia32_inserti32x8_mask(A, B, F, D, E) __builtin_ia32_inserti32x8_mask(A, B, 1, D, E)
#define __builtin_ia32_insertf64x2_512_mask(A, B, F, D, E) __builtin_ia32_insertf64x2_512_mask(A, B, 1, D, E)
#define __builtin_ia32_insertf32x8_mask(A, B, F, D, E) __builtin_ia32_insertf32x8_mask(A, B, 1, D, E)
-#define __builtin_ia32_fpclassss(A, D) __builtin_ia32_fpclassss(A, 1)
-#define __builtin_ia32_fpclasssd(A, D) __builtin_ia32_fpclasssd(A, 1)
+#define __builtin_ia32_fpclassss_mask(A, D, U) __builtin_ia32_fpclassss_mask(A, 1, U)
+#define __builtin_ia32_fpclasssd_mask(A, D, U) __builtin_ia32_fpclasssd_mask(A, 1, U)
#define __builtin_ia32_fpclassps512_mask(A, D, C) __builtin_ia32_fpclassps512_mask(A, 1, C)
#define __builtin_ia32_fpclasspd512_mask(A, D, C) __builtin_ia32_fpclasspd512_mask(A, 1, C)
#define __builtin_ia32_extracti64x2_512_mask(A, E, C, D) __builtin_ia32_extracti64x2_512_mask(A, 1, C, D)
diff --git a/gcc/testsuite/gcc.target/i386/avx2-pr90991-1.c b/gcc/testsuite/gcc.target/i386/avx2-pr90991-1.c
new file mode 100644
index 0000000..1f0467e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx2-pr90991-1.c
@@ -0,0 +1,50 @@
+/* PR target/90991 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -mavx2 -masm=att" } */
+/* { dg-final { scan-assembler-times "vmovaps\[ \t]\+\\(\[^\n\r]*\\), %xmm0" 1 } } */
+/* { dg-final { scan-assembler-times "vmovapd\[ \t]\+\\(\[^\n\r]*\\), %xmm0" 1 } } */
+/* { dg-final { scan-assembler-times "vmovdqa\[ \t]\+\\(\[^\n\r]*\\), %xmm0" 1 } } */
+/* { dg-final { scan-assembler-times "vmovups\[ \t]\+\\(\[^\n\r]*\\), %xmm0" 1 } } */
+/* { dg-final { scan-assembler-times "vmovupd\[ \t]\+\\(\[^\n\r]*\\), %xmm0" 1 } } */
+/* { dg-final { scan-assembler-times "vmovdqu\[ \t]\+\\(\[^\n\r]*\\), %xmm0" 1 } } */
+/* { dg-final { scan-assembler-not "vmovaps\[^\n\r]*xmm0\[^\n\r]*xmm0" } } */
+/* { dg-final { scan-assembler-not "vmovapd\[^\n\r]*xmm0\[^\n\r]*xmm0" } } */
+/* { dg-final { scan-assembler-not "vmovdqa\[^\n\r]*xmm0\[^\n\r]*xmm0" } } */
+
+#include <x86intrin.h>
+
+__m256
+f1 (void *a)
+{
+ return _mm256_insertf128_ps (_mm256_set1_ps (0.0f), _mm_load_ps (a), 0);
+}
+
+__m256d
+f2 (void *a)
+{
+ return _mm256_insertf128_pd (_mm256_set1_pd (0.0), _mm_load_pd (a), 0);
+}
+
+__m256i
+f3 (void *a)
+{
+ return _mm256_insertf128_si256 (_mm256_set1_epi32 (0), _mm_load_si128 (a), 0);
+}
+
+__m256
+f4 (void *a)
+{
+ return _mm256_insertf128_ps (_mm256_set1_ps (0.0f), _mm_loadu_ps (a), 0);
+}
+
+__m256d
+f5 (void *a)
+{
+ return _mm256_insertf128_pd (_mm256_set1_pd (0.0), _mm_loadu_pd (a), 0);
+}
+
+__m256i
+f6 (void *a)
+{
+ return _mm256_insertf128_si256 (_mm256_set1_epi32 (0), _mm_loadu_si128 (a), 0);
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx2-vect-simd-10.c b/gcc/testsuite/gcc.target/i386/avx2-vect-simd-10.c
new file mode 100644
index 0000000..d912351
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx2-vect-simd-10.c
@@ -0,0 +1,16 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -fopenmp-simd -mavx2 -fdump-tree-vect-details" } */
+/* { dg-require-effective-target avx2 } */
+/* { dg-final { scan-tree-dump-times "vectorized \[1-3] loops" 2 "vect" } } */
+
+#include "avx2-check.h"
+
+#define main() do_main ()
+
+#include "../../gcc.dg/vect/vect-simd-10.c"
+
+static void
+avx2_test (void)
+{
+ do_main ();
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx2-vect-simd-11.c b/gcc/testsuite/gcc.target/i386/avx2-vect-simd-11.c
new file mode 100644
index 0000000..722217a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx2-vect-simd-11.c
@@ -0,0 +1,16 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -fopenmp-simd -mavx2 -fdump-tree-vect-details" } */
+/* { dg-require-effective-target avx2 } */
+/* { dg-final { scan-tree-dump-times "vectorized \[1-3] loops" 2 "vect" } } */
+
+#include "avx2-check.h"
+
+#define main() do_main ()
+
+#include "../../gcc.dg/vect/vect-simd-11.c"
+
+static void
+avx2_test (void)
+{
+ do_main ();
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx2-vect-simd-12.c b/gcc/testsuite/gcc.target/i386/avx2-vect-simd-12.c
new file mode 100644
index 0000000..b170faa
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx2-vect-simd-12.c
@@ -0,0 +1,16 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -fopenmp-simd -mavx2 -fdump-tree-vect-details" } */
+/* { dg-require-effective-target avx2 } */
+/* { dg-final { scan-tree-dump-times "vectorized \[1-3] loops" 2 "vect" } } */
+
+#include "avx2-check.h"
+
+#define main() do_main ()
+
+#include "../../gcc.dg/vect/vect-simd-12.c"
+
+static void
+avx2_test (void)
+{
+ do_main ();
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx2-vect-simd-13.c b/gcc/testsuite/gcc.target/i386/avx2-vect-simd-13.c
new file mode 100644
index 0000000..e9fb68d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx2-vect-simd-13.c
@@ -0,0 +1,16 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -fopenmp-simd -mavx2 -fdump-tree-vect-details" } */
+/* { dg-require-effective-target avx2 } */
+/* { dg-final { scan-tree-dump-times "vectorized \[1-3] loops" 2 "vect" } } */
+
+#include "avx2-check.h"
+
+#define main() do_main ()
+
+#include "../../gcc.dg/vect/vect-simd-13.c"
+
+static void
+avx2_test (void)
+{
+ do_main ();
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx2-vect-simd-14.c b/gcc/testsuite/gcc.target/i386/avx2-vect-simd-14.c
new file mode 100644
index 0000000..3293d14
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx2-vect-simd-14.c
@@ -0,0 +1,16 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -fopenmp-simd -mavx2 -fdump-tree-vect-details" } */
+/* { dg-require-effective-target avx2 } */
+/* { dg-final { scan-tree-dump-times "vectorized \[1-3] loops" 2 "vect" } } */
+
+#include "avx2-check.h"
+
+#define main() do_main ()
+
+#include "../../gcc.dg/vect/vect-simd-14.c"
+
+static void
+avx2_test (void)
+{
+ do_main ();
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx2-vect-simd-15.c b/gcc/testsuite/gcc.target/i386/avx2-vect-simd-15.c
new file mode 100644
index 0000000..0cb5e86
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx2-vect-simd-15.c
@@ -0,0 +1,16 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -fopenmp-simd -mavx2 -fdump-tree-vect-details" } */
+/* { dg-require-effective-target avx2 } */
+/* { dg-final { scan-tree-dump-times "vectorized \[1-3] loops" 2 "vect" } } */
+
+#include "avx2-check.h"
+
+#define main() do_main ()
+
+#include "../../gcc.dg/vect/vect-simd-15.c"
+
+static void
+avx2_test (void)
+{
+ do_main ();
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx2-vect-simd-8.c b/gcc/testsuite/gcc.target/i386/avx2-vect-simd-8.c
new file mode 100644
index 0000000..8edd4e1
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx2-vect-simd-8.c
@@ -0,0 +1,16 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -fopenmp-simd -mavx2 -fdump-tree-vect-details" } */
+/* { dg-require-effective-target avx2 } */
+/* { dg-final { scan-tree-dump-times "vectorized \[1-3] loops" 2 "vect" } } */
+
+#include "avx2-check.h"
+
+#define main() do_main ()
+
+#include "../../gcc.dg/vect/vect-simd-8.c"
+
+static void
+avx2_test (void)
+{
+ do_main ();
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx2-vect-simd-9.c b/gcc/testsuite/gcc.target/i386/avx2-vect-simd-9.c
new file mode 100644
index 0000000..ba1a3e6
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx2-vect-simd-9.c
@@ -0,0 +1,16 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -fopenmp-simd -mavx2 -fdump-tree-vect-details" } */
+/* { dg-require-effective-target avx2 } */
+/* { dg-final { scan-tree-dump-times "vectorized \[1-3] loops" 2 "vect" } } */
+
+#include "avx2-check.h"
+
+#define main() do_main ()
+
+#include "../../gcc.dg/vect/vect-simd-9.c"
+
+static void
+avx2_test (void)
+{
+ do_main ();
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512-check.h b/gcc/testsuite/gcc.target/i386/avx512-check.h
index 234e60c..0a377db 100644
--- a/gcc/testsuite/gcc.target/i386/avx512-check.h
+++ b/gcc/testsuite/gcc.target/i386/avx512-check.h
@@ -93,6 +93,9 @@ main ()
#ifdef VPCLMULQDQ
&& (ecx & bit_VPCLMULQDQ)
#endif
+#ifdef AVX512VP2INTERSECT
+ && (edx & bit_AVX512VP2INTERSECT)
+#endif
&& avx512f_os_support ())
{
DO_TEST ();
diff --git a/gcc/testsuite/gcc.target/i386/avx512bw-vect-simd-11.c b/gcc/testsuite/gcc.target/i386/avx512bw-vect-simd-11.c
new file mode 100644
index 0000000..92f8613
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512bw-vect-simd-11.c
@@ -0,0 +1,16 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -fopenmp-simd -mavx512bw -mprefer-vector-width=512 -fdump-tree-vect-details" } */
+/* { dg-require-effective-target avx512bw } */
+/* { dg-final { scan-tree-dump-times "vectorized \[1-3] loops" 2 "vect" } } */
+
+#include "avx512bw-check.h"
+
+#define main() do_main ()
+
+#include "../../gcc.dg/vect/vect-simd-11.c"
+
+static void
+avx512bw_test (void)
+{
+ do_main ();
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512bw-vect-simd-15.c b/gcc/testsuite/gcc.target/i386/avx512bw-vect-simd-15.c
new file mode 100644
index 0000000..8c14e20
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512bw-vect-simd-15.c
@@ -0,0 +1,16 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -fopenmp-simd -mavx512bw -mprefer-vector-width=512 -fdump-tree-vect-details" } */
+/* { dg-require-effective-target avx512bw } */
+/* { dg-final { scan-tree-dump-times "vectorized \[1-3] loops" 2 "vect" } } */
+
+#include "avx512bw-check.h"
+
+#define main() do_main ()
+
+#include "../../gcc.dg/vect/vect-simd-15.c"
+
+static void
+avx512bw_test (void)
+{
+ do_main ();
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512bw-vpmovswb-1.c b/gcc/testsuite/gcc.target/i386/avx512bw-vpmovswb-1.c
index 6bb87d2..9d470c6 100644
--- a/gcc/testsuite/gcc.target/i386/avx512bw-vpmovswb-1.c
+++ b/gcc/testsuite/gcc.target/i386/avx512bw-vpmovswb-1.c
@@ -1,5 +1,6 @@
/* { dg-do compile } */
/* { dg-options "-mavx512bw -mavx512vl -O2" } */
+/* { dg-additional-options "-fno-common" { target *-*-darwin* } } */
/* { dg-final { scan-assembler-times "vpmovswb\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
/* { dg-final { scan-assembler-times "vpmovswb\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\]*%xmm\[0-9\]+\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
/* { dg-final { scan-assembler-times "vpmovswb\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\]*%xmm\[0-9\]+\{%k\[1-7\]\}{z}(?:\n|\[ \\t\]+#)" 1 } } */
diff --git a/gcc/testsuite/gcc.target/i386/avx512bw-vpmovuswb-1.c b/gcc/testsuite/gcc.target/i386/avx512bw-vpmovuswb-1.c
index 7825e46..da51198 100644
--- a/gcc/testsuite/gcc.target/i386/avx512bw-vpmovuswb-1.c
+++ b/gcc/testsuite/gcc.target/i386/avx512bw-vpmovuswb-1.c
@@ -1,5 +1,6 @@
/* { dg-do compile } */
/* { dg-options "-mavx512bw -mavx512vl -O2" } */
+/* { dg-additional-options "-fno-common" { target *-*-darwin* } } */
/* { dg-final { scan-assembler-times "vpmovuswb\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
/* { dg-final { scan-assembler-times "vpmovuswb\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\]*%xmm\[0-9\]+\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
/* { dg-final { scan-assembler-times "vpmovuswb\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\]*%xmm\[0-9\]+\{%k\[1-7\]\}{z}(?:\n|\[ \\t\]+#)" 1 } } */
diff --git a/gcc/testsuite/gcc.target/i386/avx512bw-vpmovwb-1.c b/gcc/testsuite/gcc.target/i386/avx512bw-vpmovwb-1.c
index a1ad551..e67da87 100644
--- a/gcc/testsuite/gcc.target/i386/avx512bw-vpmovwb-1.c
+++ b/gcc/testsuite/gcc.target/i386/avx512bw-vpmovwb-1.c
@@ -1,5 +1,6 @@
/* { dg-do compile } */
/* { dg-options "-mavx512bw -mavx512vl -O2" } */
+/* { dg-additional-options "-fno-common" { target *-*-darwin* } } */
/* { dg-final { scan-assembler-times "vpmovwb\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
/* { dg-final { scan-assembler-times "vpmovwb\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\]*%xmm\[0-9\]+\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
/* { dg-final { scan-assembler-times "vpmovwb\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\]*%xmm\[0-9\]+\{%k\[1-7\]\}{z}(?:\n|\[ \\t\]+#)" 1 } } */
diff --git a/gcc/testsuite/gcc.target/i386/avx512dq-pr90991-1.c b/gcc/testsuite/gcc.target/i386/avx512dq-pr90991-1.c
new file mode 100644
index 0000000..6c96812
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512dq-pr90991-1.c
@@ -0,0 +1,47 @@
+/* PR target/90991 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -mavx512dq -masm=att" } */
+/* { dg-final { scan-assembler-times "vmovaps\[ \t]\+\\(\[^\n\r]*\\), %xmm0" 1 } } */
+/* { dg-final { scan-assembler-times "vmovapd\[ \t]\+\\(\[^\n\r]*\\), %xmm0" 1 } } */
+/* { dg-final { scan-assembler-times "vmovdqa\[ \t]\+\\(\[^\n\r]*\\), %xmm0" 1 } } */
+/* { dg-final { scan-assembler-times "vmovups\[ \t]\+\\(\[^\n\r]*\\), %xmm0" 1 } } */
+/* { dg-final { scan-assembler-times "vmovupd\[ \t]\+\\(\[^\n\r]*\\), %xmm0" 1 } } */
+/* { dg-final { scan-assembler-times "vmovdqu\[ \t]\+\\(\[^\n\r]*\\), %xmm0" 1 } } */
+
+#include <x86intrin.h>
+
+__m512
+f1 (void *a)
+{
+ return _mm512_insertf32x4 (_mm512_set1_ps (0.0f), _mm_load_ps (a), 0);
+}
+
+__m512d
+f2 (void *a)
+{
+ return _mm512_insertf64x2 (_mm512_set1_pd (0.0), _mm_load_pd (a), 0);
+}
+
+__m512i
+f3 (void *a)
+{
+ return _mm512_inserti32x4 (_mm512_set1_epi32 (0), _mm_load_si128 (a), 0);
+}
+
+__m512
+f4 (void *a)
+{
+ return _mm512_insertf32x4 (_mm512_set1_ps (0.0f), _mm_loadu_ps (a), 0);
+}
+
+__m512d
+f5 (void *a)
+{
+ return _mm512_insertf64x2 (_mm512_set1_pd (0.0), _mm_loadu_pd (a), 0);
+}
+
+__m512i
+f6 (void *a)
+{
+ return _mm512_inserti32x4 (_mm512_set1_epi32 (0), _mm_loadu_si128 (a), 0);
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512dq-pr90991-2.c b/gcc/testsuite/gcc.target/i386/avx512dq-pr90991-2.c
new file mode 100644
index 0000000..7699c31
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512dq-pr90991-2.c
@@ -0,0 +1,47 @@
+/* PR target/90991 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -mavx512dq -masm=att -mtune=intel" } */
+/* { dg-final { scan-assembler-times "vmovaps\[ \t]\+\\(\[^\n\r]*\\), %ymm0" 1 } } */
+/* { dg-final { scan-assembler-times "vmovapd\[ \t]\+\\(\[^\n\r]*\\), %ymm0" 1 } } */
+/* { dg-final { scan-assembler-times "vmovdqa\[ \t]\+\\(\[^\n\r]*\\), %ymm0" 1 } } */
+/* { dg-final { scan-assembler-times "vmovups\[ \t]\+\\(\[^\n\r]*\\), %ymm0" 1 } } */
+/* { dg-final { scan-assembler-times "vmovupd\[ \t]\+\\(\[^\n\r]*\\), %ymm0" 1 } } */
+/* { dg-final { scan-assembler-times "vmovdqu\[ \t]\+\\(\[^\n\r]*\\), %ymm0" 1 } } */
+
+#include <x86intrin.h>
+
+__m512
+f1 (void *a)
+{
+ return _mm512_insertf32x8 (_mm512_set1_ps (0.0f), _mm256_load_ps (a), 0);
+}
+
+__m512d
+f2 (void *a)
+{
+ return _mm512_insertf64x4 (_mm512_set1_pd (0.0), _mm256_load_pd (a), 0);
+}
+
+__m512i
+f3 (void *a)
+{
+ return _mm512_inserti32x8 (_mm512_set1_epi32 (0), _mm256_load_si256 (a), 0);
+}
+
+__m512
+f4 (void *a)
+{
+ return _mm512_insertf32x8 (_mm512_set1_ps (0.0f), _mm256_loadu_ps (a), 0);
+}
+
+__m512d
+f5 (void *a)
+{
+ return _mm512_insertf64x4 (_mm512_set1_pd (0.0), _mm256_loadu_pd (a), 0);
+}
+
+__m512i
+f6 (void *a)
+{
+ return _mm512_inserti32x8 (_mm512_set1_epi32 (0), _mm256_loadu_si256 (a), 0);
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512dq-vfpclasspd-1.c b/gcc/testsuite/gcc.target/i386/avx512dq-vfpclasspd-1.c
index 02f31bf..932f103 100644
--- a/gcc/testsuite/gcc.target/i386/avx512dq-vfpclasspd-1.c
+++ b/gcc/testsuite/gcc.target/i386/avx512dq-vfpclasspd-1.c
@@ -1,11 +1,11 @@
/* { dg-do compile } */
/* { dg-options "-mavx512dq -mavx512vl -O2" } */
-/* { dg-final { scan-assembler-times "vfpclasspd\[ \\t\]+\[^\{\n\]*%zmm\[0-9\]+\[^\n^k\]*%k\[0-7\](?:\n|\[ \\t\]+#)" 1 } } */
-/* { dg-final { scan-assembler-times "vfpclasspd\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\[^\n^k\]*%k\[0-7\](?:\n|\[ \\t\]+#)" 1 } } */
-/* { dg-final { scan-assembler-times "vfpclasspd\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n^k\]*%k\[0-7\](?:\n|\[ \\t\]+#)" 1 } } */
-/* { dg-final { scan-assembler-times "vfpclasspd\[ \\t\]+\[^\{\n\]*%zmm\[0-9\]+\[^\n^k\]*%k\[0-7\]\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
-/* { dg-final { scan-assembler-times "vfpclasspd\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\[^\n^k\]*%k\[0-7\]\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
-/* { dg-final { scan-assembler-times "vfpclasspd\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n^k\]*%k\[0-7\]\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfpclasspdz\[ \\t\]+\[^\{\n\]*%zmm\[0-9\]+\[^\n^k\]*%k\[0-7\](?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfpclasspdy\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\[^\n^k\]*%k\[0-7\](?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfpclasspdx\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n^k\]*%k\[0-7\](?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfpclasspdz\[ \\t\]+\[^\{\n\]*%zmm\[0-9\]+\[^\n^k\]*%k\[0-7\]\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfpclasspdy\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\[^\n^k\]*%k\[0-7\]\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfpclasspdx\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n^k\]*%k\[0-7\]\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
#include <immintrin.h>
diff --git a/gcc/testsuite/gcc.target/i386/avx512dq-vfpclassps-1.c b/gcc/testsuite/gcc.target/i386/avx512dq-vfpclassps-1.c
index df109ea..f826e89 100644
--- a/gcc/testsuite/gcc.target/i386/avx512dq-vfpclassps-1.c
+++ b/gcc/testsuite/gcc.target/i386/avx512dq-vfpclassps-1.c
@@ -1,11 +1,11 @@
/* { dg-do compile } */
/* { dg-options "-mavx512dq -mavx512vl -O2" } */
-/* { dg-final { scan-assembler-times "vfpclassps\[ \\t\]+\[^\{\n\]*%zmm\[0-9\]+\[^\n^k\]*%k\[0-7\](?:\n|\[ \\t\]+#)" 1 } } */
-/* { dg-final { scan-assembler-times "vfpclassps\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\[^\n^k\]*%k\[0-7\](?:\n|\[ \\t\]+#)" 1 } } */
-/* { dg-final { scan-assembler-times "vfpclassps\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n^k\]*%k\[0-7\](?:\n|\[ \\t\]+#)" 1 } } */
-/* { dg-final { scan-assembler-times "vfpclassps\[ \\t\]+\[^\{\n\]*%zmm\[0-9\]+\[^\n^k\]*%k\[0-7\]\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
-/* { dg-final { scan-assembler-times "vfpclassps\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\[^\n^k\]*%k\[0-7\]\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
-/* { dg-final { scan-assembler-times "vfpclassps\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n^k\]*%k\[0-7\]\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfpclasspsz\[ \\t\]+\[^\{\n\]*%zmm\[0-9\]+\[^\n^k\]*%k\[0-7\](?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfpclasspsy\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\[^\n^k\]*%k\[0-7\](?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfpclasspsx\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n^k\]*%k\[0-7\](?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfpclasspsz\[ \\t\]+\[^\{\n\]*%zmm\[0-9\]+\[^\n^k\]*%k\[0-7\]\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfpclasspsy\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\[^\n^k\]*%k\[0-7\]\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfpclasspsx\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n^k\]*%k\[0-7\]\{%k\[1-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
#include <immintrin.h>
diff --git a/gcc/testsuite/gcc.target/i386/avx512dq-vfpclasssd-1.c b/gcc/testsuite/gcc.target/i386/avx512dq-vfpclasssd-1.c
index 2d65417..fb5c1d5 100644
--- a/gcc/testsuite/gcc.target/i386/avx512dq-vfpclasssd-1.c
+++ b/gcc/testsuite/gcc.target/i386/avx512dq-vfpclasssd-1.c
@@ -1,6 +1,7 @@
/* { dg-do compile } */
/* { dg-options "-mavx512dq -O2" } */
/* { dg-final { scan-assembler-times "vfpclasssd\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n^k\]*%k\[0-7\](?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfpclasssd\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n^k\]*%k\[0-7\]\{%k\[0-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
#include <immintrin.h>
@@ -11,4 +12,5 @@ void extern
avx512dq_test (void)
{
m8 = _mm_fpclass_sd_mask (x128, 13);
+ m8 = _mm_mask_fpclass_sd_mask (m8, x128, 13);
}
diff --git a/gcc/testsuite/gcc.target/i386/avx512dq-vfpclasssd-2.c b/gcc/testsuite/gcc.target/i386/avx512dq-vfpclasssd-2.c
new file mode 100644
index 0000000..469ddc3
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512dq-vfpclasssd-2.c
@@ -0,0 +1,75 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -mavx512dq" } */
+/* { dg-require-effective-target avx512dq } */
+
+#define AVX512DQ
+#include "avx512f-helper.h"
+
+#include <math.h>
+#include <limits.h>
+#include <float.h>
+#define SIZE (128 / 64)
+#include "avx512f-mask-type.h"
+
+#ifndef __FPCLASSSD__
+#define __FPCLASSSD__
+int check_fp_class_dp (double src, int imm)
+{
+ int qNaN_res = isnan (src);
+ int sNaN_res = isnan (src);
+ int Pzero_res = (src == 0.0);
+ int Nzero_res = (src == -0.0);
+ int PInf_res = (isinf (src) == 1);
+ int NInf_res = (isinf (src) == -1);
+ int Denorm_res = (fpclassify (src) == FP_SUBNORMAL);
+ int FinNeg_res = __builtin_finite (src) && (src < 0);
+
+ int result = (((imm & 1) && qNaN_res)
+ || (((imm >> 1) & 1) && Pzero_res)
+ || (((imm >> 2) & 1) && Nzero_res)
+ || (((imm >> 3) & 1) && PInf_res)
+ || (((imm >> 4) & 1) && NInf_res)
+ || (((imm >> 5) & 1) && Denorm_res)
+ || (((imm >> 6) & 1) && FinNeg_res)
+ || (((imm >> 7) & 1) && sNaN_res));
+ return result;
+}
+#endif
+
+__mmask8
+CALC (double *s1, int imm)
+{
+ int i;
+ __mmask8 res = 0;
+
+ if (check_fp_class_dp(s1[0], imm))
+ res = res | 1;
+
+ return res;
+}
+
+void
+TEST (void)
+{
+ int i;
+ union128d src;
+ __mmask8 res1, res2, res_ref = 0;
+ __mmask8 mask = MASK_VALUE;
+
+ src.a[0] = 1.0 / 0.0;
+ for (i = 1; i < SIZE; i++)
+ {
+ src.a[i] = -24.43 + 0.6 * i;
+ }
+
+ res1 = _mm_fpclass_sd_mask (src.x, 0xFF);
+ res2 = _mm_mask_fpclass_sd_mask (mask, src.x, 0xFF);
+
+ res_ref = CALC (src.a, 0xFF);
+
+ if (res_ref != res1)
+ abort ();
+
+ if ((res_ref & mask) != res2)
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512dq-vfpclassss-1.c b/gcc/testsuite/gcc.target/i386/avx512dq-vfpclassss-1.c
index 49050c9..4822441 100644
--- a/gcc/testsuite/gcc.target/i386/avx512dq-vfpclassss-1.c
+++ b/gcc/testsuite/gcc.target/i386/avx512dq-vfpclassss-1.c
@@ -1,6 +1,7 @@
/* { dg-do compile } */
/* { dg-options "-mavx512dq -O2" } */
/* { dg-final { scan-assembler-times "vfpclassss\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n^k\]*%k\[0-7\](?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfpclassss\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n^k\]*%k\[0-7\]\{%k\[0-7\]\}(?:\n|\[ \\t\]+#)" 1 } } */
#include <immintrin.h>
@@ -11,4 +12,5 @@ void extern
avx512dq_test (void)
{
m8 = _mm_fpclass_ss_mask (x128, 13);
+ m8 = _mm_mask_fpclass_ss_mask (m8, x128, 13);
}
diff --git a/gcc/testsuite/gcc.target/i386/avx512dq-vfpclassss-2.c b/gcc/testsuite/gcc.target/i386/avx512dq-vfpclassss-2.c
new file mode 100644
index 0000000..38fd657
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512dq-vfpclassss-2.c
@@ -0,0 +1,76 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -mavx512dq" } */
+/* { dg-require-effective-target avx512dq } */
+
+#define AVX512DQ
+#include "avx512f-helper.h"
+
+#include <math.h>
+#include <limits.h>
+#include <float.h>
+#include "avx512f-mask-type.h"
+#define SIZE (128 / 32)
+
+#ifndef __FPCLASSSS__
+#define __FPCLASSSS__
+int check_fp_class_sp (float src, int imm)
+{
+ int qNaN_res = isnan (src);
+ int sNaN_res = isnan (src);
+ int Pzero_res = (src == 0.0);
+ int Nzero_res = (src == -0.0);
+ int PInf_res = (isinf (src) == 1);
+ int NInf_res = (isinf (src) == -1);
+ int Denorm_res = (fpclassify (src) == FP_SUBNORMAL);
+ int FinNeg_res = __builtin_finite (src) && (src < 0);
+
+ int result = (((imm & 1) && qNaN_res)
+ || (((imm >> 1) & 1) && Pzero_res)
+ || (((imm >> 2) & 1) && Nzero_res)
+ || (((imm >> 3) & 1) && PInf_res)
+ || (((imm >> 4) & 1) && NInf_res)
+ || (((imm >> 5) & 1) && Denorm_res)
+ || (((imm >> 6) & 1) && FinNeg_res)
+ || (((imm >> 7) & 1) && sNaN_res));
+ return result;
+}
+#endif
+
+__mmask8
+CALC (float *s1, int imm)
+{
+ int i;
+ __mmask8 res = 0;
+
+ if (check_fp_class_sp(s1[0], imm))
+ res = res | 1;
+
+ return res;
+}
+
+void
+TEST (void)
+{
+ int i;
+ union128 src;
+ __mmask8 res1, res2, res_ref = 0;
+ __mmask8 mask = MASK_VALUE;
+
+ src.a[0] = 1.0 / 0.0;
+ for (i = 1; i < SIZE; i++)
+ {
+ src.a[i] = -24.43 + 0.6 * i;
+ }
+
+ res1 = _mm_fpclass_ss_mask (src.x, 0xFF);
+ res2 = _mm_mask_fpclass_ss_mask (mask, src.x, 0xFF);
+
+
+ res_ref = CALC (src.a, 0xFF);
+
+ if (res_ref != res1)
+ abort ();
+
+ if ((mask & res_ref) != res2)
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512f-simd-1.c b/gcc/testsuite/gcc.target/i386/avx512f-simd-1.c
new file mode 100644
index 0000000..235fb91
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512f-simd-1.c
@@ -0,0 +1,35 @@
+/* { dg-do compile } */
+/* { dg-options "-fopenmp-simd -O2 -mavx512f -masm=att" } */
+/* { dg-final { scan-assembler "vpadd\[^\n\r]*%xmm" } } */
+/* { dg-final { scan-assembler "vpadd\[^\n\r]*%ymm" } } */
+/* { dg-final { scan-assembler "vpadd\[^\n\r]*%zmm" } } */
+
+#define N 1024
+int a[N];
+
+void
+f1 (void)
+{
+ int i;
+ #pragma omp simd simdlen (4)
+ for (i = 0; i < N; ++i)
+ a[i] = a[i] + 1;
+}
+
+void
+f2 (void)
+{
+ int i;
+ #pragma omp simd simdlen (8)
+ for (i = 0; i < N; ++i)
+ a[i] = a[i] + 2;
+}
+
+void
+f3 (void)
+{
+ int i;
+ #pragma omp simd simdlen (16)
+ for (i = 0; i < N; ++i)
+ a[i] = a[i] + 3;
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512f-vcomisd-2.c b/gcc/testsuite/gcc.target/i386/avx512f-vcomisd-2.c
new file mode 100644
index 0000000..a84580e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512f-vcomisd-2.c
@@ -0,0 +1,104 @@
+/* { dg-do run } */
+/* { dg-require-effective-target avx512f } */
+/* { dg-options "-O2 -mavx512f" } */
+
+#include "avx512f-check.h"
+
+static inline void __attribute__ ((__always_inline__))
+check_cmp (double s1, double s2, const int imm, int expected)
+{
+ __m128d source1 = _mm_load_sd (&s1);
+ __m128d source2 = _mm_load_sd (&s2);
+ int res = _mm_comi_round_sd (source1, source2, imm,
+ _MM_FROUND_NO_EXC);
+ if (expected != res)
+ abort();
+}
+
+static void
+do_check (double s1, double s2)
+{
+ check_cmp (s1, s2, _CMP_EQ_OQ,
+ !__builtin_isunordered (s1, s2) && s1 == s2);
+ check_cmp (s1, s2, _CMP_LT_OS,
+ !__builtin_isunordered (s1, s2) && s1 < s2);
+ check_cmp (s1, s2, _CMP_LE_OS,
+ !__builtin_isunordered (s1, s2) && s1 <= s2);
+ check_cmp (s1, s2, _CMP_UNORD_Q,
+ __builtin_isunordered (s1, s2));
+ check_cmp (s1, s2, _CMP_NEQ_UQ,
+ __builtin_isunordered (s1, s2) || s1 != s2);
+ check_cmp (s1, s2, _CMP_NLT_US,
+ __builtin_isunordered (s1, s2) || s1 >= s2);
+ check_cmp (s1, s2, _CMP_NLE_US,
+ __builtin_isunordered (s1, s2) || s1 > s2);
+ check_cmp (s1, s2, _CMP_ORD_Q,
+ !__builtin_isunordered (s1, s2));
+ check_cmp (s1, s2, _CMP_EQ_UQ,
+ __builtin_isunordered (s1, s2) || s1 == s2);
+ check_cmp (s1, s2, _CMP_NGE_US,
+ __builtin_isunordered (s1, s2) || s1 < s2);
+ check_cmp (s1, s2, _CMP_NGT_US,
+ __builtin_isunordered (s1, s2) || s1 <= s2);
+ check_cmp (s1, s2, _CMP_FALSE_OQ, 0);
+ check_cmp (s1, s2, _CMP_NEQ_OQ,
+ !__builtin_isunordered (s1, s2) && s1 != s2);
+ check_cmp (s1, s2, _CMP_GE_OS,
+ !__builtin_isunordered (s1, s2) && s1 >= s2);
+ check_cmp (s1, s2, _CMP_GT_OS,
+ !__builtin_isunordered (s1, s2) && s1 > s2);
+ check_cmp (s1, s2, _CMP_TRUE_UQ, 1);
+ check_cmp (s1, s2, _CMP_EQ_OS,
+ !__builtin_isunordered (s1, s2) && s1 == s2);
+ check_cmp (s1, s2, _CMP_LT_OQ,
+ !__builtin_isunordered (s1, s2) && s1 < s2);
+ check_cmp (s1, s2, _CMP_LE_OQ,
+ !__builtin_isunordered (s1, s2) && s1 <= s2);
+ check_cmp (s1, s2, _CMP_UNORD_S,
+ __builtin_isunordered (s1, s2));
+ check_cmp (s1, s2, _CMP_NEQ_US,
+ __builtin_isunordered (s1, s2) || s1 != s2);
+ check_cmp (s1, s2, _CMP_NLT_UQ,
+ __builtin_isunordered (s1, s2) || s1 >= s2);
+ check_cmp (s1, s2, _CMP_NLE_UQ,
+ __builtin_isunordered (s1, s2) || s1 > s2);
+ check_cmp (s1, s2, _CMP_ORD_S, !__builtin_isunordered (s1, s2));
+ check_cmp (s1, s2, _CMP_EQ_US,
+ __builtin_isunordered (s1, s2) || s1 == s2);
+ check_cmp (s1, s2, _CMP_NGE_UQ,
+ __builtin_isunordered (s1, s2) || s1 < s2);
+ check_cmp (s1, s2, _CMP_NGT_UQ,
+ __builtin_isunordered (s1, s2) || s1 <= s2);
+ check_cmp (s1, s2, _CMP_FALSE_OS, 0);
+ check_cmp (s1, s2, _CMP_NEQ_OS,
+ !__builtin_isunordered (s1, s2) && s1 != s2);
+ check_cmp (s1, s2, _CMP_GE_OQ,
+ !__builtin_isunordered (s1, s2) && s1 >= s2);
+ check_cmp (s1, s2, _CMP_GT_OQ,
+ !__builtin_isunordered (s1, s2) && s1 > s2);
+ check_cmp (s1, s2, _CMP_TRUE_US, 1);
+}
+
+static void
+avx512f_test (void)
+{
+ struct
+ {
+ double x1;
+ double x2;
+ }
+ inputs[] =
+ {
+ { 4.3, 2.18 },
+ { -4.3, 3.18 },
+ { __builtin_nan (""), -5.8 },
+ { -4.8, __builtin_nans ("") },
+ { 3.8, __builtin_nans ("") },
+ { 4.2, 4.2 },
+ { __builtin_nan (""), __builtin_nans ("") },
+ };
+ int i;
+
+ for (i = 0; i < sizeof (inputs) / sizeof (inputs[0]); i++)
+ do_check (inputs[i].x1, inputs[i].x2);
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512f-vcomiss-2.c b/gcc/testsuite/gcc.target/i386/avx512f-vcomiss-2.c
new file mode 100644
index 0000000..381a8b4
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512f-vcomiss-2.c
@@ -0,0 +1,104 @@
+/* { dg-do run } */
+/* { dg-require-effective-target avx512f } */
+/* { dg-options "-O2 -mavx512f" } */
+
+#include "avx512f-check.h"
+
+static inline void __attribute__ ((__always_inline__))
+check_cmp (float s1, float s2, const int imm, int expected)
+{
+ __m128 source1 = _mm_load_ss (&s1);
+ __m128 source2 = _mm_load_ss (&s2);
+ int res = _mm_comi_round_ss (source1, source2, imm,
+ _MM_FROUND_NO_EXC);
+ if (expected != res)
+ abort();
+}
+
+static void
+do_check (float s1, float s2)
+{
+ check_cmp (s1, s2, _CMP_EQ_OQ,
+ !__builtin_isunordered (s1, s2) && s1 == s2);
+ check_cmp (s1, s2, _CMP_LT_OS,
+ !__builtin_isunordered (s1, s2) && s1 < s2);
+ check_cmp (s1, s2, _CMP_LE_OS,
+ !__builtin_isunordered (s1, s2) && s1 <= s2);
+ check_cmp (s1, s2, _CMP_UNORD_Q,
+ __builtin_isunordered (s1, s2));
+ check_cmp (s1, s2, _CMP_NEQ_UQ,
+ __builtin_isunordered (s1, s2) || s1 != s2);
+ check_cmp (s1, s2, _CMP_NLT_US,
+ __builtin_isunordered (s1, s2) || s1 >= s2);
+ check_cmp (s1, s2, _CMP_NLE_US,
+ __builtin_isunordered (s1, s2) || s1 > s2);
+ check_cmp (s1, s2, _CMP_ORD_Q,
+ !__builtin_isunordered (s1, s2));
+ check_cmp (s1, s2, _CMP_EQ_UQ,
+ __builtin_isunordered (s1, s2) || s1 == s2);
+ check_cmp (s1, s2, _CMP_NGE_US,
+ __builtin_isunordered (s1, s2) || s1 < s2);
+ check_cmp (s1, s2, _CMP_NGT_US,
+ __builtin_isunordered (s1, s2) || s1 <= s2);
+ check_cmp (s1, s2, _CMP_FALSE_OQ, 0);
+ check_cmp (s1, s2, _CMP_NEQ_OQ,
+ !__builtin_isunordered (s1, s2) && s1 != s2);
+ check_cmp (s1, s2, _CMP_GE_OS,
+ !__builtin_isunordered (s1, s2) && s1 >= s2);
+ check_cmp (s1, s2, _CMP_GT_OS,
+ !__builtin_isunordered (s1, s2) && s1 > s2);
+ check_cmp (s1, s2, _CMP_TRUE_UQ, 1);
+ check_cmp (s1, s2, _CMP_EQ_OS,
+ !__builtin_isunordered (s1, s2) && s1 == s2);
+ check_cmp (s1, s2, _CMP_LT_OQ,
+ !__builtin_isunordered (s1, s2) && s1 < s2);
+ check_cmp (s1, s2, _CMP_LE_OQ,
+ !__builtin_isunordered (s1, s2) && s1 <= s2);
+ check_cmp (s1, s2, _CMP_UNORD_S,
+ __builtin_isunordered (s1, s2));
+ check_cmp (s1, s2, _CMP_NEQ_US,
+ __builtin_isunordered (s1, s2) || s1 != s2);
+ check_cmp (s1, s2, _CMP_NLT_UQ,
+ __builtin_isunordered (s1, s2) || s1 >= s2);
+ check_cmp (s1, s2, _CMP_NLE_UQ,
+ __builtin_isunordered (s1, s2) || s1 > s2);
+ check_cmp (s1, s2, _CMP_ORD_S, !__builtin_isunordered (s1, s2));
+ check_cmp (s1, s2, _CMP_EQ_US,
+ __builtin_isunordered (s1, s2) || s1 == s2);
+ check_cmp (s1, s2, _CMP_NGE_UQ,
+ __builtin_isunordered (s1, s2) || s1 < s2);
+ check_cmp (s1, s2, _CMP_NGT_UQ,
+ __builtin_isunordered (s1, s2) || s1 <= s2);
+ check_cmp (s1, s2, _CMP_FALSE_OS, 0);
+ check_cmp (s1, s2, _CMP_NEQ_OS,
+ !__builtin_isunordered (s1, s2) && s1 != s2);
+ check_cmp (s1, s2, _CMP_GE_OQ,
+ !__builtin_isunordered (s1, s2) && s1 >= s2);
+ check_cmp (s1, s2, _CMP_GT_OQ,
+ !__builtin_isunordered (s1, s2) && s1 > s2);
+ check_cmp (s1, s2, _CMP_TRUE_US, 1);
+}
+
+static void
+avx512f_test (void)
+{
+ struct
+ {
+ float x1;
+ float x2;
+ }
+ inputs[] =
+ {
+ { 4.3, 2.18 },
+ { -4.3, 3.18 },
+ { __builtin_nanf (""), -5.8 },
+ { -4.8, __builtin_nansf ("") },
+ { 3.8, __builtin_nansf ("") },
+ { 4.2, 4.2 },
+ { __builtin_nanf (""), __builtin_nansf ("") },
+ };
+ int i;
+
+ for (i = 0; i < sizeof (inputs) / sizeof (inputs[0]); i++)
+ do_check (inputs[i].x1, inputs[i].x2);
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512f-vect-simd-10.c b/gcc/testsuite/gcc.target/i386/avx512f-vect-simd-10.c
new file mode 100644
index 0000000..c0d7cdf
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512f-vect-simd-10.c
@@ -0,0 +1,16 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -fopenmp-simd -mavx512f -mprefer-vector-width=512 -fdump-tree-vect-details" } */
+/* { dg-require-effective-target avx512f } */
+/* { dg-final { scan-tree-dump-times "vectorized \[1-3] loops" 2 "vect" } } */
+
+#include "avx512f-check.h"
+
+#define main() do_main ()
+
+#include "../../gcc.dg/vect/vect-simd-10.c"
+
+static void
+avx512f_test (void)
+{
+ do_main ();
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512f-vect-simd-12.c b/gcc/testsuite/gcc.target/i386/avx512f-vect-simd-12.c
new file mode 100644
index 0000000..87c46d7
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512f-vect-simd-12.c
@@ -0,0 +1,16 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -fopenmp-simd -mavx512f -mprefer-vector-width=512 -fdump-tree-vect-details" } */
+/* { dg-require-effective-target avx512f } */
+/* { dg-final { scan-tree-dump-times "vectorized \[1-3] loops" 2 "vect" } } */
+
+#include "avx512f-check.h"
+
+#define main() do_main ()
+
+#include "../../gcc.dg/vect/vect-simd-12.c"
+
+static void
+avx512f_test (void)
+{
+ do_main ();
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512f-vect-simd-13.c b/gcc/testsuite/gcc.target/i386/avx512f-vect-simd-13.c
new file mode 100644
index 0000000..a8a28dc
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512f-vect-simd-13.c
@@ -0,0 +1,16 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -fopenmp-simd -mavx512f -mprefer-vector-width=512 -fdump-tree-vect-details" } */
+/* { dg-require-effective-target avx512f } */
+/* { dg-final { scan-tree-dump-times "vectorized \[1-3] loops" 2 "vect" } } */
+
+#include "avx512f-check.h"
+
+#define main() do_main ()
+
+#include "../../gcc.dg/vect/vect-simd-13.c"
+
+static void
+avx512f_test (void)
+{
+ do_main ();
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512f-vect-simd-14.c b/gcc/testsuite/gcc.target/i386/avx512f-vect-simd-14.c
new file mode 100644
index 0000000..eba9228
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512f-vect-simd-14.c
@@ -0,0 +1,16 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -fopenmp-simd -mavx512f -mprefer-vector-width=512 -fdump-tree-vect-details" } */
+/* { dg-require-effective-target avx512f } */
+/* { dg-final { scan-tree-dump-times "vectorized \[1-3] loops" 2 "vect" } } */
+
+#include "avx512f-check.h"
+
+#define main() do_main ()
+
+#include "../../gcc.dg/vect/vect-simd-14.c"
+
+static void
+avx512f_test (void)
+{
+ do_main ();
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512f-vect-simd-8.c b/gcc/testsuite/gcc.target/i386/avx512f-vect-simd-8.c
new file mode 100644
index 0000000..f469a13
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512f-vect-simd-8.c
@@ -0,0 +1,16 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -fopenmp-simd -mavx512f -mprefer-vector-width=512 -fdump-tree-vect-details" } */
+/* { dg-require-effective-target avx512f } */
+/* { dg-final { scan-tree-dump-times "vectorized \[1-3] loops" 2 "vect" } } */
+
+#include "avx512f-check.h"
+
+#define main() do_main ()
+
+#include "../../gcc.dg/vect/vect-simd-8.c"
+
+static void
+avx512f_test (void)
+{
+ do_main ();
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512f-vect-simd-9.c b/gcc/testsuite/gcc.target/i386/avx512f-vect-simd-9.c
new file mode 100644
index 0000000..1e8f5e3
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512f-vect-simd-9.c
@@ -0,0 +1,16 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -fopenmp-simd -mavx512f -mprefer-vector-width=512 -fdump-tree-vect-details" } */
+/* { dg-require-effective-target avx512f } */
+/* { dg-final { scan-tree-dump-times "vectorized \[1-3] loops" 2 "vect" } } */
+
+#include "avx512f-check.h"
+
+#define main() do_main ()
+
+#include "../../gcc.dg/vect/vect-simd-9.c"
+
+static void
+avx512f_test (void)
+{
+ do_main ();
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512vp2intersect-2intersect-1a.c b/gcc/testsuite/gcc.target/i386/avx512vp2intersect-2intersect-1a.c
new file mode 100644
index 0000000..4ce0400
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512vp2intersect-2intersect-1a.c
@@ -0,0 +1,18 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mavx512vp2intersect" } */
+/* { dg-final { scan-assembler "vp2intersectq\[ \\t\]+\[^\{\n\]*%zmm\[0-9\]+\[^\n\]*%k\[0-7\]"} } */
+/* { dg-final { scan-assembler "vp2intersectd\[ \\t\]+\[^\{\n\]*%zmm\[0-9\]+\[^\n\]*%k\[0-7\]"} } */
+
+#include <x86intrin.h>
+
+__m512i a1, b1;
+__m512i a2, b2;
+__mmask8 m8, u8;
+__mmask16 m16, u16;
+
+int foo ()
+{
+ _mm512_2intersect_epi64 (a1, b1, &u8, &m8);
+ _mm512_2intersect_epi32 (a2, b2, &u16, &m16);
+}
+
diff --git a/gcc/testsuite/gcc.target/i386/avx512vp2intersect-2intersect-1b.c b/gcc/testsuite/gcc.target/i386/avx512vp2intersect-2intersect-1b.c
new file mode 100644
index 0000000..dce8705
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512vp2intersect-2intersect-1b.c
@@ -0,0 +1,29 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -mavx512vp2intersect" } */
+/* { dg-require-effective-target avx512vp2intersect } */
+
+#define AVX512F
+#include <x86intrin.h>
+#include "avx512f-helper.h"
+
+void
+TEST (void)
+{
+ __m512i a1 = _mm512_set_epi64 (10, 43, 253, 3566, 25, -253, -243, 3456);
+ __m512i b1 = _mm512_set_epi64 (43, 100, 3566, 2353, -253, -25, 3456, 243);
+ __m512i a2 = _mm512_set_epi32 (21, 22, 23, 24, 25, 26, 27, 28,
+ 11, 12, 13, 14, 15, 16, 17, 18);
+ __m512i b2 = _mm512_set_epi32 (22, 211, 24, 213, 26, 215, 28, 217,
+ 12, 111, 14, 113, 16, 115, 18, 117);
+ __mmask8 u8 = 0, m8 = 0;
+ __mmask16 u16 = 0, m16 = 0;
+
+ _mm512_2intersect_epi64 (a1, b1, &u8, &m8);
+ /* u8 = 01010101, m8 = 10101010. */
+ if (u8 != 0x55 || m8 != 0xaa)
+ abort();
+ _mm512_2intersect_epi32 (a2, b2, &u16, &m16);
+ /* u8 = 0101010101010101, m8 = 1010101010101010. */
+ if (u16 != 0x5555 || m16 != 0xaaaa)
+ abort();
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512vp2intersect-2intersectvl-1a.c b/gcc/testsuite/gcc.target/i386/avx512vp2intersect-2intersectvl-1a.c
new file mode 100644
index 0000000..555f5ab
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512vp2intersect-2intersectvl-1a.c
@@ -0,0 +1,21 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mavx512vp2intersect -mavx512vl" } */
+/* { dg-final { scan-assembler "vp2intersectd\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\]*%k\[0-7\]" } } */
+/* { dg-final { scan-assembler "vp2intersectd\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\[^\n\]*%k\[0-7\]" } } */
+/* { dg-final { scan-assembler "vp2intersectq\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\]*%k\[0-7\]" } } */
+/* { dg-final { scan-assembler "vp2intersectq\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\[^\n\]*%k\[0-7\]" } } */
+
+#include <x86intrin.h>
+
+__m256i a2, b2;
+__m128i a3, b3;
+__mmask8 m0, m1, m2, m3, m4, m5, m6, m7;
+
+int foo ()
+{
+ _mm_2intersect_epi64 (a3, b3, &m0, &m1);
+ _mm_2intersect_epi32 (a3, b3, &m2, &m3);
+
+ _mm256_2intersect_epi64 (a2, b2, &m4, &m5);
+ _mm256_2intersect_epi32 (a2, b2, &m6, &m7);
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx512vp2intersect-2intersectvl-1b.c b/gcc/testsuite/gcc.target/i386/avx512vp2intersect-2intersectvl-1b.c
new file mode 100644
index 0000000..3801ff5
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx512vp2intersect-2intersectvl-1b.c
@@ -0,0 +1,42 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -mavx512vp2intersect -mavx512vl" } */
+/* { dg-require-effective-target avx512vp2intersect } */
+
+#define AVX512F
+#include <x86intrin.h>
+#include "avx512f-helper.h"
+
+ void
+ TEST (void)
+{
+ __m256i a1 = _mm256_set_epi64x (1, 2, 3, 4);
+ __m256i b1 = _mm256_set_epi64x (2, 11, 4, 33);
+ __m256i a2 = _mm256_set_epi32 (1, 2, 3, 4, 5, 6, 7, 8);
+ __m256i b2 = _mm256_set_epi32 (2, 11, 4, 33, 6, 55, 8, 77);
+ __m128i a3 = _mm_set_epi64x (13, 22);
+ __m128i b3 = _mm_set_epi64x (22, 1434);
+ __m128i a4 = _mm_set_epi32 (1, 2, 3, 4);
+ __m128i b4 = _mm_set_epi32 (2, 11, 4, 33);
+ __mmask8 m0, m1, m2, m3, m4, m5, m6, m7;
+ m0 = m1 = m2 = m3 = m4 = m5 = m6 = m7 = 0;
+
+ _mm_2intersect_epi64 (a3, b3, &m0, &m1);
+ /* m0 = ******01, m1 = ******10. */
+ if (m0 != 0x1 || m1 != 0x2)
+ abort();
+
+ _mm_2intersect_epi32 (a4, b4, &m2, &m3);
+ /* m2 = ****0101, m3 = ****1010. */
+ if (m2 != 0x5 || m3 != 0xa)
+ abort();
+
+ _mm256_2intersect_epi64 (a1, b1, &m4, &m5);
+ /* m4 = ****0101, m5 = ****1010. */
+ if (m4 != 0x5 || m5 != 0xa)
+ abort();
+
+ _mm256_2intersect_epi32 (a2, b2, &m6, &m7);
+ /* m0 = 01010101, m1 = 10101010. */
+ if (m6 != 0x55 || m7 != 0xaa)
+ abort();
+}
diff --git a/gcc/testsuite/gcc.target/i386/cet-label-3.c b/gcc/testsuite/gcc.target/i386/cet-label-3.c
new file mode 100644
index 0000000..9f427a8
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/cet-label-3.c
@@ -0,0 +1,23 @@
+/* PR target/89355 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -fcf-protection" } */
+/* { dg-final { scan-assembler-times "endbr32" 1 { target ia32 } } } */
+/* { dg-final { scan-assembler-times "endbr64" 1 { target { ! ia32 } } } } */
+int
+test (int* val)
+{
+ int status = 99;
+
+ if (!val)
+ {
+ status = 22;
+ goto end;
+ }
+
+ extern int x;
+ *val = x;
+
+ status = 0;
+end:
+ return status;
+}
diff --git a/gcc/testsuite/gcc.target/i386/cet-label-4.c b/gcc/testsuite/gcc.target/i386/cet-label-4.c
new file mode 100644
index 0000000..d743d2b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/cet-label-4.c
@@ -0,0 +1,12 @@
+/* PR target/89355 */
+/* { dg-do compile { target { fpic && lp64 } } } */
+/* { dg-options "-O2 -fcf-protection -fPIC -mcmodel=large" } */
+/* { dg-final { scan-assembler-times "endbr64" 1 } } */
+
+extern int val;
+
+int
+test (void)
+{
+ return val;
+}
diff --git a/gcc/testsuite/gcc.target/i386/cet-label-5.c b/gcc/testsuite/gcc.target/i386/cet-label-5.c
new file mode 100644
index 0000000..862c79b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/cet-label-5.c
@@ -0,0 +1,13 @@
+/* PR target/89355 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -fcf-protection -Wno-return-local-addr" } */
+/* { dg-final { scan-assembler-times "endbr32" 1 { target ia32 } } } */
+/* { dg-final { scan-assembler-times "endbr64" 1 { target { ! ia32 } } } } */
+
+void *
+func (void)
+{
+ return &&bar;
+bar:
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/i386/cet-notrack-5a.c b/gcc/testsuite/gcc.target/i386/cet-notrack-5a.c
index 50fe0db..c80b4f6 100644
--- a/gcc/testsuite/gcc.target/i386/cet-notrack-5a.c
+++ b/gcc/testsuite/gcc.target/i386/cet-notrack-5a.c
@@ -2,7 +2,8 @@
/* { dg-options "-O -fcf-protection" } */
/* { dg-final { scan-assembler-times "endbr32" 1 { target ia32 } } } */
/* { dg-final { scan-assembler-times "endbr64" 1 { target { ! ia32 } } } } */
-/* { dg-final { scan-assembler-not "\tcall\[ \t]+" } } */
+/* { dg-final { scan-assembler-not "\tcall\[ \t]+" { target { ! ia32 } || { ! *-*-darwin* } } } } */
+/* { dg-final { scan-assembler-times "\tcall\[ \t]+" 1 { target { ia32 && *-*-darwin* } } } } */
/* { dg-final { scan-assembler-times "notrack call\[ \t]+" 1 } } */
int (*fptr) (int) __attribute__ ((nocf_check));
diff --git a/gcc/testsuite/gcc.target/i386/cet-notrack-5b.c b/gcc/testsuite/gcc.target/i386/cet-notrack-5b.c
index 222ff62..255ad45 100644
--- a/gcc/testsuite/gcc.target/i386/cet-notrack-5b.c
+++ b/gcc/testsuite/gcc.target/i386/cet-notrack-5b.c
@@ -3,7 +3,8 @@
/* { dg-options "-O -fcf-protection" } */
/* { dg-final { scan-assembler-times "endbr32" 1 { target ia32 } } } */
/* { dg-final { scan-assembler-times "endbr64" 1 { target { ! ia32 } } } } */
-/* { dg-final { scan-assembler-times "\tcall\[ \t]+" 1 } } */
+/* { dg-final { scan-assembler-times "\tcall\[ \t]+" 1 { target { ! ia32 } || { ! *-*-darwin* } } } } */
+/* { dg-final { scan-assembler-times "\tcall\[ \t]+" 2 { target { ia32 && *-*-darwin* } } } } */
/* { dg-final { scan-assembler-times "notrack call\[ \t]+" 1 } } */
int (*fptr) (int) __attribute__ ((nocf_check));
diff --git a/gcc/testsuite/gcc.target/i386/cet-notrack-6b.c b/gcc/testsuite/gcc.target/i386/cet-notrack-6b.c
index f27088c..f950d3a 100644
--- a/gcc/testsuite/gcc.target/i386/cet-notrack-6b.c
+++ b/gcc/testsuite/gcc.target/i386/cet-notrack-6b.c
@@ -2,7 +2,8 @@
/* { dg-options "-O0 -fcf-protection" } */
/* { dg-final { scan-assembler-times "endbr32" 1 { target ia32 } } } */
/* { dg-final { scan-assembler-times "endbr64" 1 { target { ! ia32 } } } } */
-/* { dg-final { scan-assembler-not "\tcall\[ \t]+" } } */
+/* { dg-final { scan-assembler-not "\tcall\[ \t]+" { target { ! ia32 } || { ! *-*-darwin* } } } } */
+/* { dg-final { scan-assembler-times "\tcall\[ \t]+" 1 { target { ia32 && *-*-darwin* } } } } */
/* { dg-final { scan-assembler-times "notrack call\[ \t]+" 1 } } */
int foo (int arg);
diff --git a/gcc/testsuite/gcc.target/i386/cet-notrack-icf-1.c b/gcc/testsuite/gcc.target/i386/cet-notrack-icf-1.c
index b90019f..fe913e8 100644
--- a/gcc/testsuite/gcc.target/i386/cet-notrack-icf-1.c
+++ b/gcc/testsuite/gcc.target/i386/cet-notrack-icf-1.c
@@ -3,8 +3,8 @@
/* { dg-options "-O2 -fcf-protection=none" } */
/* { dg-final { scan-assembler-not "endbr" } } */
/* { dg-final { scan-assembler-not "fn3:" } } */
-/* { dg-final { scan-assembler "set\[ \t]+fn2,fn1" } } */
-/* { dg-final { scan-assembler "set\[ \t]+fn3,fn1" } } */
+/* { dg-final { scan-assembler "set\[ \t]+fn2,fn1" { target { ! *-*-darwin* } } } } */
+/* { dg-final { scan-assembler "set\[ \t]+fn3,fn1" { target { ! *-*-darwin* } } } } */
static __attribute__((noinline)) int
fn1 (int x)
diff --git a/gcc/testsuite/gcc.target/i386/cet-notrack-icf-2.c b/gcc/testsuite/gcc.target/i386/cet-notrack-icf-2.c
index 08132a3..f15594d 100644
--- a/gcc/testsuite/gcc.target/i386/cet-notrack-icf-2.c
+++ b/gcc/testsuite/gcc.target/i386/cet-notrack-icf-2.c
@@ -3,7 +3,7 @@
/* { dg-options "-O2 -fcf-protection" } */
/* { dg-final { scan-assembler "endbr" } } */
/* { dg-final { scan-assembler "fn3:" } } */
-/* { dg-final { scan-assembler "set\[ \t]+fn2,fn1" } } */
+/* { dg-final { scan-assembler "set\[ \t]+fn2,fn1" { target { ! *-*-darwin* } } } } */
static __attribute__((noinline)) int
fn1 (int x)
diff --git a/gcc/testsuite/gcc.target/i386/cet-notrack-icf-3.c b/gcc/testsuite/gcc.target/i386/cet-notrack-icf-3.c
index 3eec1e0..e1b34da 100644
--- a/gcc/testsuite/gcc.target/i386/cet-notrack-icf-3.c
+++ b/gcc/testsuite/gcc.target/i386/cet-notrack-icf-3.c
@@ -3,8 +3,8 @@
/* { dg-options "-O2 -fcf-protection=none" } */
/* { dg-final { scan-assembler-not "endbr" } } */
/* { dg-final { scan-assembler-not "fn2:" } } */
-/* { dg-final { scan-assembler "set\[ \t]+fn2,fn1" } } */
-/* { dg-final { scan-assembler "set\[ \t]+fn3,fn1" } } */
+/* { dg-final { scan-assembler "set\[ \t]+fn2,fn1" { target { ! *-*-darwin* } } } } */
+/* { dg-final { scan-assembler "set\[ \t]+fn3,fn1" { target { ! *-*-darwin* } } } } */
int (*foo)(int);
diff --git a/gcc/testsuite/gcc.target/i386/cet-notrack-icf-4.c b/gcc/testsuite/gcc.target/i386/cet-notrack-icf-4.c
index b5f0787..7d64666 100644
--- a/gcc/testsuite/gcc.target/i386/cet-notrack-icf-4.c
+++ b/gcc/testsuite/gcc.target/i386/cet-notrack-icf-4.c
@@ -3,7 +3,7 @@
/* { dg-options "-O2 -fcf-protection" } */
/* { dg-final { scan-assembler "endbr" } } */
/* { dg-final { scan-assembler "fn2:" } } */
-/* { dg-final { scan-assembler "set\[ \t]+fn3,fn1" } } */
+/* { dg-final { scan-assembler "set\[ \t]+fn3,fn1" { target { ! *-*-darwin* } } } } */
int (*foo)(int);
diff --git a/gcc/testsuite/gcc.target/i386/cet-sjlj-3.c b/gcc/testsuite/gcc.target/i386/cet-sjlj-3.c
index 25117cc..e2653db 100644
--- a/gcc/testsuite/gcc.target/i386/cet-sjlj-3.c
+++ b/gcc/testsuite/gcc.target/i386/cet-sjlj-3.c
@@ -3,7 +3,7 @@
/* { dg-final { scan-assembler-times "endbr32" 4 { target ia32 } } } */
/* { dg-final { scan-assembler-times "endbr64" 4 { target { ! ia32 } } } } */
/* { dg-final { scan-assembler-times "call _?setjmp" 1 } } */
-/* { dg-final { scan-assembler-times "call longjmp" 1 } } */
+/* { dg-final { scan-assembler-times "call _?longjmp" 1 } } */
#include <stdio.h>
#include <setjmp.h>
diff --git a/gcc/testsuite/gcc.target/i386/cet-sjlj-5.c b/gcc/testsuite/gcc.target/i386/cet-sjlj-5.c
index 1b62432..8470f9c 100644
--- a/gcc/testsuite/gcc.target/i386/cet-sjlj-5.c
+++ b/gcc/testsuite/gcc.target/i386/cet-sjlj-5.c
@@ -3,7 +3,7 @@
/* { dg-final { scan-assembler-times "endbr32" 2 { target ia32 } } } */
/* { dg-final { scan-assembler-times "endbr64" 2 { target { ! ia32 } } } } */
/* { dg-final { scan-assembler-times "call _?setjmp" 1 } } */
-/* { dg-final { scan-assembler-times "call longjmp" 1 } } */
+/* { dg-final { scan-assembler-times "call _?longjmp" 1 } } */
#include <stdio.h>
#include <setjmp.h>
diff --git a/gcc/testsuite/gcc.target/i386/cet-sjlj-6b.c b/gcc/testsuite/gcc.target/i386/cet-sjlj-6b.c
index 6ec4b83..b2376e7 100644
--- a/gcc/testsuite/gcc.target/i386/cet-sjlj-6b.c
+++ b/gcc/testsuite/gcc.target/i386/cet-sjlj-6b.c
@@ -1,4 +1,5 @@
/* { dg-do compile { target { ! ia32 } } } */
+/* { dg-require-effective-target maybe_x32 } */
/* { dg-options "-O -maddress-mode=long -fcf-protection -mx32" } */
/* { dg-final { scan-assembler-times "endbr64" 2 } } */
/* { dg-final { scan-assembler-times "movq\t.*buf\\+16" 1 } } */
diff --git a/gcc/testsuite/gcc.target/i386/cvtpd2pi.c b/gcc/testsuite/gcc.target/i386/cvtpd2pi.c
new file mode 100644
index 0000000..cb043b8
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/cvtpd2pi.c
@@ -0,0 +1,36 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -msse2" } */
+
+typedef int __attribute__((vector_size(8))) v2si_t;
+typedef int __attribute__((vector_size(16))) v4si_t;
+typedef double __attribute__((vector_size(16))) v2df_t;
+
+struct __attribute__((packed)) s {
+ int i;
+ v2si_t m;
+ v4si_t v;
+};
+
+int test (struct s*ps)
+{
+ v4si_t r = ps->v;
+ v2si_t m;
+
+ if (ps->i > 0)
+ {
+ asm volatile ("" : "+m" (*ps));
+ m = __builtin_ia32_cvtpd2pi ((v2df_t)ps->v);
+ r[0] = __builtin_ia32_paddd (m, m)[0];
+ }
+ else
+ {
+ asm volatile ("" : "+m" (*ps));
+ m = __builtin_ia32_cvttpd2pi ((v2df_t)ps->v);
+ r[0] = __builtin_ia32_paddd (m, m)[0];
+ }
+
+ return r[0];
+}
+
+/* { dg-final { scan-assembler-not "cvtpd2pi\[ \t]\[^\n\r]*\\(" } } */
+/* { dg-final { scan-assembler-not "cvttpd2pi\[ \t]\[^\n\r]*\\(" } } */
diff --git a/gcc/testsuite/gcc.target/i386/enqcmd.c b/gcc/testsuite/gcc.target/i386/enqcmd.c
new file mode 100644
index 0000000..2927f20
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/enqcmd.c
@@ -0,0 +1,16 @@
+/* { dg-do compile } */
+/* { dg-options "-menqcmd -O2" } */
+/* { dg-final { scan-assembler-times "\tenqcmd" 1 } } */
+/* { dg-final { scan-assembler-times "\tsete" 1 } } */
+
+#include <x86intrin.h>
+
+unsigned int w;
+unsigned int array[16];
+
+int
+test_enqcmd (void)
+{
+ return _enqcmd(&w, array);
+}
+
diff --git a/gcc/testsuite/gcc.target/i386/enqcmds.c b/gcc/testsuite/gcc.target/i386/enqcmds.c
new file mode 100644
index 0000000..095aaf7
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/enqcmds.c
@@ -0,0 +1,15 @@
+/* { dg-do compile } */
+/* { dg-options "-menqcmd -O2" } */
+/* { dg-final { scan-assembler-times "\tenqcmds" 1 } } */
+/* { dg-final { scan-assembler-times "\tsete" 1 } } */
+
+#include <x86intrin.h>
+
+unsigned int w;
+unsigned int array[16];
+int
+test_enqcmds (void)
+{
+ return _enqcmds(&w, array);
+}
+
diff --git a/gcc/testsuite/gcc.target/i386/falign-functions-2.c b/gcc/testsuite/gcc.target/i386/falign-functions-2.c
index 26d505e..2672c87 100644
--- a/gcc/testsuite/gcc.target/i386/falign-functions-2.c
+++ b/gcc/testsuite/gcc.target/i386/falign-functions-2.c
@@ -1,5 +1,6 @@
/* { dg-do compile } */
/* { dg-options "-O2 -falign-functions=64:8" } */
+/* { dg-skip-if "SUBALIGN_LOG not set for Darwin" { *-*-darwin* } } */
void
a (void)
diff --git a/gcc/testsuite/gcc.target/i386/falign-functions-3.c b/gcc/testsuite/gcc.target/i386/falign-functions-3.c
index f4a6ace..86423c4 100644
--- a/gcc/testsuite/gcc.target/i386/falign-functions-3.c
+++ b/gcc/testsuite/gcc.target/i386/falign-functions-3.c
@@ -9,15 +9,16 @@
ALIGN (4)
void f4 (void) { }
-/* { dg-final { scan-assembler ".align 4\n\t.globl\tf4" } } */
-
+/* { dg-final { scan-assembler ".align 4\n\t.globl\tf4" { target { ! *-*-darwin* } } } } */
+/* { dg-final { scan-assembler {.align 2,0x90\n\t.globl[ \t]_f4} { target *-*-darwin* } } } */
void f32 (void) { }
-/* { dg-final { scan-assembler ".p2align 5\n\t.globl\tf32" } } */
+/* { dg-final { scan-assembler {.p2align 5\n\t.globl[ \t]_?f32} } } */
ALIGN (64)
void f64 (void) { }
-/* { dg-final { scan-assembler ".align 64\n\t.globl\tf64" } } */
+/* { dg-final { scan-assembler ".align 64\n\t.globl\tf64" { target { ! *-*-darwin* } } } } */
+/* { dg-final { scan-assembler {.align 6,0x90\n\t.globl[ \t]_f64} { target *-*-darwin* } } } */
diff --git a/gcc/testsuite/gcc.target/i386/fentry-override.c b/gcc/testsuite/gcc.target/i386/fentry-override.c
index 7bc5fc4..efba1bf 100644
--- a/gcc/testsuite/gcc.target/i386/fentry-override.c
+++ b/gcc/testsuite/gcc.target/i386/fentry-override.c
@@ -1,5 +1,6 @@
/* Test -mfentry override */
/* { dg-do compile { target { *-*-linux* && { ! ia32 } } } } */
+/* { dg-require-effective-target mfentry } */
/* { dg-options "-mfentry" } */
/* { dg-final { scan-assembler-not "__fentry__" } } */
/* Origin: Andi Kleen */
diff --git a/gcc/testsuite/gcc.target/i386/fentry.c b/gcc/testsuite/gcc.target/i386/fentry.c
index 2449e75..28edd10 100644
--- a/gcc/testsuite/gcc.target/i386/fentry.c
+++ b/gcc/testsuite/gcc.target/i386/fentry.c
@@ -1,5 +1,6 @@
/* Test -mfentry */
/* { dg-do compile { target { *-*-linux* && { ! ia32 } } } } */
+/* { dg-require-effective-target mfentry } */
/* { dg-options "-fprofile -mfentry" } */
/* { dg-final { scan-assembler "__fentry__" } } */
/* Origin: Andi Kleen */
diff --git a/gcc/testsuite/gcc.target/i386/fentryname1.c b/gcc/testsuite/gcc.target/i386/fentryname1.c
index 6d2e76d..1265342 100644
--- a/gcc/testsuite/gcc.target/i386/fentryname1.c
+++ b/gcc/testsuite/gcc.target/i386/fentryname1.c
@@ -1,4 +1,5 @@
/* { dg-do compile } */
+/* { dg-require-effective-target mfentry } */
/* { dg-options "-pg -mfentry -mfentry-name=foo" } */
/* { dg-final { scan-assembler "call.*foo" } } */
/* { dg-final { scan-assembler "call.*bar" } } */
diff --git a/gcc/testsuite/gcc.target/i386/fentryname2.c b/gcc/testsuite/gcc.target/i386/fentryname2.c
index 7d102bf..c51c5d1 100644
--- a/gcc/testsuite/gcc.target/i386/fentryname2.c
+++ b/gcc/testsuite/gcc.target/i386/fentryname2.c
@@ -1,4 +1,5 @@
/* { dg-do compile } */
+/* { dg-require-effective-target mfentry } */
/* { dg-options "-pg -mfentry -mrecord-mcount -mfentry-section=foo" } */
/* { dg-final { scan-assembler "section.*foo" } } */
/* { dg-final { scan-assembler "section.*bar" } } */
diff --git a/gcc/testsuite/gcc.target/i386/fentryname3.c b/gcc/testsuite/gcc.target/i386/fentryname3.c
index 777f4e4..5688109 100644
--- a/gcc/testsuite/gcc.target/i386/fentryname3.c
+++ b/gcc/testsuite/gcc.target/i386/fentryname3.c
@@ -1,4 +1,5 @@
/* { dg-do compile } */
+/* { dg-require-effective-target mfentry } */
/* { dg-options "-pg -mfentry" } */
/* { dg-final { scan-assembler "section.*__entry_loc" } } */
/* { dg-final { scan-assembler "0x0f, 0x1f, 0x44, 0x00, 0x00" } } */
diff --git a/gcc/testsuite/gcc.target/i386/fnabs.c b/gcc/testsuite/gcc.target/i386/fnabs.c
new file mode 100644
index 0000000..817c9a7
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/fnabs.c
@@ -0,0 +1,21 @@
+/* PR target/62055 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -msse2 -mfpmath=sse" } */
+
+float testf (float a)
+{
+ return -__builtin_fabsf (a);
+}
+
+double test (double a)
+{
+ return -__builtin_fabs (a);
+}
+
+__float128 testq (__float128 a)
+{
+ return -__builtin_fabsq (a);
+}
+
+/* { dg-final { scan-assembler-times "\tv?orp\[sd\]\[ \t\]" 2 } } */
+/* { dg-final { scan-assembler-times "\tv?por\[ \t\]" 1 } } */
diff --git a/gcc/testsuite/gcc.target/i386/fuse-caller-save-rec.c b/gcc/testsuite/gcc.target/i386/fuse-caller-save-rec.c
index 7abcf91..e8d4efb 100644
--- a/gcc/testsuite/gcc.target/i386/fuse-caller-save-rec.c
+++ b/gcc/testsuite/gcc.target/i386/fuse-caller-save-rec.c
@@ -18,14 +18,12 @@ foo (int y)
return y + bar (y);
}
-/* For !nonpic && ia32 xfails, see PR64895. */
-
/* Check that no registers are saved/restored. */
-/* { dg-final { scan-assembler-not "push" { xfail { { ! nonpic } && ia32 } } } } */
-/* { dg-final { scan-assembler-not "pop" { xfail { { ! nonpic } && ia32 } } } } */
+/* { dg-final { scan-assembler-not "push" } } */
+/* { dg-final { scan-assembler-not "pop" } } */
/* Check that addition uses dx. */
-/* { dg-final { scan-assembler-times "addl\t%\[re\]?dx, %\[re\]?ax" 1 { xfail { { ! nonpic } && ia32 } } } } */
+/* { dg-final { scan-assembler-times "addl\t%\[re\]?dx, %\[re\]?ax" 1 } } */
/* Verify that bar is self-recursive. */
/* { dg-final { scan-assembler-times "call\t_?bar" 2 } } */
diff --git a/gcc/testsuite/gcc.target/i386/fuse-caller-save-xmm.c b/gcc/testsuite/gcc.target/i386/fuse-caller-save-xmm.c
index c2d0544..4deff93 100644
--- a/gcc/testsuite/gcc.target/i386/fuse-caller-save-xmm.c
+++ b/gcc/testsuite/gcc.target/i386/fuse-caller-save-xmm.c
@@ -15,13 +15,19 @@ foo (v2df y)
return y + bar (y);
}
-/* For !nonpic && ia32 xfails, see PR64895. */
-
/* Check presence of all insns on xmm registers. These checks are expected to
pass with both -fipa-ra and -fno-ipa-ra. */
-/* { dg-final { scan-assembler-times "addpd\t\\.?LC0.*, %xmm0" 1 } } */
-/* { dg-final { scan-assembler-times "addpd\t%xmm1, %xmm0" 1 { xfail { { ! nonpic } && ia32 } } } } */
-/* { dg-final { scan-assembler-times "movapd\t%xmm0, %xmm1" 1 { xfail { { ! nonpic } && ia32 } } } } */
+
+/* Darwin local constant symbol is "lC0", ELF targets ".LC0" */
+/* { dg-final { scan-assembler-times {addpd\t\.?[Ll]C0.*, %xmm0} 1 { target { { ! ia32 } || nonpic } } } } */
+/* { dg-final { scan-assembler-times {movapd\t\.?[Ll]C0.*, %xmm1} 1 { target { ia32 && { ! nonpic } } } } } */
+
+/* We happen to get this for both cases, but in different positions. */
+/* { dg-final { scan-assembler-times "addpd\t%xmm1, %xmm0" 1 } } */
+
+/* { dg-final { scan-assembler-times "movapd\t%xmm0, %xmm1" 1 { target { { ! ia32 } || nonpic } } } } */
+/* { dg-final { scan-assembler-times "movapd\t%xmm0, %xmm2" 1 { target { ia32 && { ! nonpic } } } } } */
+/* { dg-final { scan-assembler-times "addpd\t%xmm2, %xmm0" 1 { target { ia32 && { ! nonpic } } } } } */
/* Check absence of save/restore of xmm1 register. */
/* { dg-final { scan-assembler-not "movaps\t%xmm1, \\(%\[re\]?sp\\)" } } */
diff --git a/gcc/testsuite/gcc.target/i386/fuse-caller-save.c b/gcc/testsuite/gcc.target/i386/fuse-caller-save.c
index 4b8e68d..c0e8bf4 100644
--- a/gcc/testsuite/gcc.target/i386/fuse-caller-save.c
+++ b/gcc/testsuite/gcc.target/i386/fuse-caller-save.c
@@ -16,11 +16,9 @@ foo (int y)
return y + bar (y);
}
-/* For !nonpic && ia32 xfails, see PR64895. */
-
/* Check that no registers are saved/restored. */
-/* { dg-final { scan-assembler-not "push" { xfail { { ! nonpic } && ia32 } } } } */
-/* { dg-final { scan-assembler-not "pop" { xfail { { ! nonpic } && ia32 } } } } */
+/* { dg-final { scan-assembler-not "push" } } */
+/* { dg-final { scan-assembler-not "pop" } } */
/* PR61605. If the first argument register and the return register differ, then
bar leaves the first argument register intact. That means in foo that the
@@ -31,4 +29,4 @@ foo (int y)
/* { dg-final { scan-assembler-not "movl" { target { ! ia32 } } } } */
/* Check that addition uses di (in case of no copy) or dx (in case of copy). */
-/* { dg-final { scan-assembler-times "addl\t%\[re\]?d\[ix\], %\[re\]?ax" 1 { xfail { { ! nonpic } && ia32 } } } } */
+/* { dg-final { scan-assembler-times "addl\t%\[re\]?d\[ix\], %\[re\]?ax" 1 } } */
diff --git a/gcc/testsuite/gcc.target/i386/gfni-4.c b/gcc/testsuite/gcc.target/i386/gfni-4.c
index e075005..39b3384 100644
--- a/gcc/testsuite/gcc.target/i386/gfni-4.c
+++ b/gcc/testsuite/gcc.target/i386/gfni-4.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-mgfni -O2 -msse" } */
+/* { dg-options "-mgfni -O2 -msse2" } */
/* { dg-final { scan-assembler-times "gf2p8affineinvqb\[ \\t\]+\[^\{\n\]*\\\$3\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
/* { dg-final { scan-assembler-times "gf2p8affineqb\[ \\t\]+\[^\{\n\]*\\\$3\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
/* { dg-final { scan-assembler-times "gf2p8mulb\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
diff --git a/gcc/testsuite/gcc.target/i386/gfni-5.c b/gcc/testsuite/gcc.target/i386/gfni-5.c
new file mode 100644
index 0000000..b355219
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/gfni-5.c
@@ -0,0 +1,19 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -msse2 -mgfni" } */
+
+typedef char __attribute__((vector_size(16))) v16qi_t;
+
+v16qi_t test16a (v16qi_t x, v16qi_t a)
+{
+ asm volatile ("" : "+m" (a));
+ return __builtin_ia32_vgf2p8affineqb_v16qi (x, a, 0);
+}
+
+v16qi_t test16b (v16qi_t x, v16qi_t a)
+{
+ asm volatile ("" : "+m" (x));
+ return __builtin_ia32_vgf2p8affineqb_v16qi (x, a, 0);
+}
+
+/* { dg-final { scan-assembler-times "gf2p8affineqb\[ \t].*\\(" 1 } } */
+/* { dg-final { scan-assembler-times "gf2p8affineqb\[ \t].*%xmm.*%xmm" 1 } } */
diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-1.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-1.c
index 6e94d2c..052d24d 100644
--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-1.c
+++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-1.c
@@ -1,5 +1,6 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -mindirect-branch=thunk -fno-pic" } */
+/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -mindirect-branch=thunk" } */
+/* { dg-additional-options "-fno-pic" { target { ! *-*-darwin* } } } */
typedef void (*dispatch_t)(long offset);
@@ -11,9 +12,11 @@ male_indirect_jump (long offset)
dispatch(offset);
}
-/* { dg-final { scan-assembler "mov(?:l|q)\[ \t\]*_?dispatch" { target *-*-linux* } } } */
-/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk_(r|e)ax" } } */
-/* { dg-final { scan-assembler "jmp\[ \t\]*\.LIND" } } */
-/* { dg-final { scan-assembler "call\[ \t\]*\.LIND" } } */
+/* { dg-final { scan-assembler "mov(?:l|q)\[ \t\]*dispatch" { target *-*-linux* } } } */
+/* { dg-final { scan-assembler {movq[ \t]*_dispatch} { target { lp64 && *-*-darwin* } } } } */
+/* { dg-final { scan-assembler {movl[ \t]*l_dispatch\$non_lazy_ptr-L[0-9]+\$pb} { target { ia32 && *-*-darwin* } } } } */
+/* { dg-final { scan-assembler "jmp\[ \t\]*_?__x86_indirect_thunk_(r|e)ax" } } */
+/* { dg-final { scan-assembler {jmp[ \t]*\.?LIND} } } */
+/* { dg-final { scan-assembler {call[ \t]*\.?LIND} } } */
/* { dg-final { scan-assembler {\tpause} } } */
/* { dg-final { scan-assembler {\tlfence} } } */
diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-2.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-2.c
index 3c46707..2cfbd72 100644
--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-2.c
+++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-2.c
@@ -1,5 +1,6 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -mindirect-branch=thunk -fno-pic" } */
+/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -mindirect-branch=thunk " } */
+/* { dg-additional-options "-fno-pic" { target { ! *-*-darwin* } } } */
typedef void (*dispatch_t)(long offset);
@@ -11,9 +12,11 @@ male_indirect_jump (long offset)
dispatch[offset](offset);
}
-/* { dg-final { scan-assembler "mov(?:l|q)\[ \t\]*_?dispatch" { target *-*-linux* } } } */
-/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk_(r|e)ax" } } */
-/* { dg-final { scan-assembler "jmp\[ \t\]*\.LIND" } } */
-/* { dg-final { scan-assembler "call\[ \t\]*\.LIND" } } */
+/* { dg-final { scan-assembler "mov(?:l|q)\[ \t\]*dispatch" { target *-*-linux* } } } */
+/* { dg-final { scan-assembler {movq[ \t]*_dispatch} { target { lp64 && *-*-darwin* } } } } */
+/* { dg-final { scan-assembler {movl[ \t]*l_dispatch\$non_lazy_ptr-L[0-9]+\$pb} { target { ia32 && *-*-darwin* } } } } */
+/* { dg-final { scan-assembler "jmp\[ \t\]*_?__x86_indirect_thunk_(r|e)ax" } } */
+/* { dg-final { scan-assembler {jmp[ \t]*\.?LIND} } } */
+/* { dg-final { scan-assembler {call[ \t]*\.?LIND} } } */
/* { dg-final { scan-assembler {\tpause} } } */
/* { dg-final { scan-assembler {\tlfence} } } */
diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-3.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-3.c
index e4c9b88..59bb086 100644
--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-3.c
+++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-3.c
@@ -1,5 +1,6 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -mindirect-branch=thunk -fno-pic" } */
+/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -mindirect-branch=thunk " } */
+/* { dg-additional-options "-fno-pic" { target { ! *-*-darwin* } } } */
typedef void (*dispatch_t)(long offset);
@@ -12,9 +13,11 @@ male_indirect_jump (long offset)
return 0;
}
-/* { dg-final { scan-assembler "mov(?:l|q)\[ \t\]*_?dispatch" { target *-*-linux* } } } */
-/* { dg-final { scan-assembler "call\[ \t\]*__x86_indirect_thunk_(r|e)ax" } } */
-/* { dg-final { scan-assembler "jmp\[ \t\]*\.LIND" } } */
-/* { dg-final { scan-assembler "call\[ \t\]*\.LIND" } } */
+/* { dg-final { scan-assembler "mov(?:l|q)\[ \t\]*dispatch" { target *-*-linux* } } } */
+/* { dg-final { scan-assembler {movq[ \t]*_dispatch} { target { lp64 && *-*-darwin* } } } } */
+/* { dg-final { scan-assembler {movl[ \t]*l_dispatch\$non_lazy_ptr-L[0-9]+\$pb} { target { ia32 && *-*-darwin* } } } } */
+/* { dg-final { scan-assembler "call\[ \t\]*_?__x86_indirect_thunk_(r|e)ax" } } */
+/* { dg-final { scan-assembler {jmp[ \t]*\.?LIND} } } */
+/* { dg-final { scan-assembler {call[ \t]*\.?LIND} } } */
/* { dg-final { scan-assembler {\tpause} } } */
/* { dg-final { scan-assembler {\tlfence} } } */
diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-4.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-4.c
index b22554a..59640fa 100644
--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-4.c
+++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-4.c
@@ -1,5 +1,6 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -mindirect-branch=thunk -fno-pic" } */
+/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -mindirect-branch=thunk " } */
+/* { dg-additional-options "-fno-pic" { target { ! *-*-darwin* } } } */
typedef void (*dispatch_t)(long offset);
@@ -12,9 +13,11 @@ male_indirect_jump (long offset)
return 0;
}
-/* { dg-final { scan-assembler "mov(?:l|q)\[ \t\]*_?dispatch" { target *-*-linux* } } } */
-/* { dg-final { scan-assembler "call\[ \t\]*__x86_indirect_thunk_(r|e)ax" } } */
-/* { dg-final { scan-assembler "jmp\[ \t\]*\.LIND" } } */
-/* { dg-final { scan-assembler "call\[ \t\]*\.LIND" } } */
+/* { dg-final { scan-assembler "mov(?:l|q)\[ \t\]*dispatch" { target *-*-linux* } } } */
+/* { dg-final { scan-assembler {movq[ \t]*_dispatch} { target { lp64 && *-*-darwin* } } } } */
+/* { dg-final { scan-assembler {movl[ \t]*l_dispatch\$non_lazy_ptr-L[0-9]+\$pb} { target { ia32 && *-*-darwin* } } } } */
+/* { dg-final { scan-assembler "call\[ \t\]*_?__x86_indirect_thunk_(r|e)ax" } } */
+/* { dg-final { scan-assembler {jmp[ \t]*\.?LIND} } } */
+/* { dg-final { scan-assembler {call[ \t]*\.?LIND} } } */
/* { dg-final { scan-assembler {\tpause} } } */
/* { dg-final { scan-assembler {\tlfence} } } */
diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-7.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-7.c
index 53868f4..6f2eec8 100644
--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-7.c
+++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-7.c
@@ -1,5 +1,6 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -mindirect-branch=thunk -fno-pic -fjump-tables" } */
+/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -mindirect-branch=thunk -fjump-tables" } */
+/* { dg-additional-options "-fno-pic" { target { ! *-*-darwin* } } } */
void func0 (void);
void func1 (void);
@@ -36,8 +37,10 @@ bar (int i)
}
/* { dg-final { scan-assembler "mov(?:l|q)\[ \t\]*\.L\[0-9\]+\\(,%" { target *-*-linux* } } } */
-/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk_(r|e)ax" } } */
-/* { dg-final { scan-assembler "jmp\[ \t\]*\.LIND" } } */
-/* { dg-final { scan-assembler "call\[ \t\]*\.LIND" } } */
+/* { dg-final { scan-assembler {leaq[ \t]*L[0-9]+\(%rip\)} { target { lp64 && *-*-darwin* } } } } */
+/* { dg-final { scan-assembler {addl[ \t]*L[0-9]+-L[0-9]+\$pb} { target { ia32 && *-*-darwin* } } } } */
+/* { dg-final { scan-assembler "jmp\[ \t\]*_?__x86_indirect_thunk_(r|e)ax" } } */
+/* { dg-final { scan-assembler {jmp[ \t]*\.?LIND} } } */
+/* { dg-final { scan-assembler {call[ \t]*\.?LIND} } } */
/* { dg-final { scan-assembler {\tpause} } } */
/* { dg-final { scan-assembler {\tlfence} } } */
diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-1.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-1.c
index 7106407..8620bf1 100644
--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-1.c
+++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-1.c
@@ -1,5 +1,6 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -fno-pic" } */
+/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep " } */
+/* { dg-additional-options "-fno-pic" { target { ! *-*-darwin* } } } */
typedef void (*dispatch_t)(long offset);
@@ -14,9 +15,11 @@ male_indirect_jump (long offset)
dispatch(offset);
}
-/* { dg-final { scan-assembler "mov(?:l|q)\[ \t\]*_?dispatch" { target *-*-linux* } } } */
-/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk_(r|e)ax" } } */
-/* { dg-final { scan-assembler "jmp\[ \t\]*\.LIND" } } */
-/* { dg-final { scan-assembler "call\[ \t\]*\.LIND" } } */
+/* { dg-final { scan-assembler "mov(?:l|q)\[ \t\]*dispatch" { target *-*-linux* } } } */
+/* { dg-final { scan-assembler {movq[ \t]*_dispatch} { target { lp64 && *-*-darwin* } } } } */
+/* { dg-final { scan-assembler {movl[ \t]*l_dispatch\$non_lazy_ptr-L[0-9]+\$pb} { target { ia32 && *-*-darwin* } } } } */
+/* { dg-final { scan-assembler "jmp\[ \t\]*_?__x86_indirect_thunk_(r|e)ax" } } */
+/* { dg-final { scan-assembler {jmp[ \t]*\.?LIND} } } */
+/* { dg-final { scan-assembler {call[ \t]*\.?LIND} } } */
/* { dg-final { scan-assembler {\tpause} } } */
/* { dg-final { scan-assembler {\tlfence} } } */
diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-2.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-2.c
index 27c7e5b..42e8341 100644
--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-2.c
+++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-2.c
@@ -1,5 +1,6 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -fno-pic" } */
+/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep " } */
+/* { dg-additional-options "-fno-pic" { target { ! *-*-darwin* } } } */
typedef void (*dispatch_t)(long offset);
@@ -12,9 +13,11 @@ male_indirect_jump (long offset)
dispatch[offset](offset);
}
-/* { dg-final { scan-assembler "mov(?:l|q)\[ \t\]*_?dispatch" { target *-*-linux* } } } */
-/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk_(r|e)ax" } } */
-/* { dg-final { scan-assembler "jmp\[ \t\]*\.LIND" } } */
-/* { dg-final { scan-assembler "call\[ \t\]*\.LIND" } } */
+/* { dg-final { scan-assembler "mov(?:l|q)\[ \t\]*dispatch" { target *-*-linux* } } } */
+/* { dg-final { scan-assembler {movq[ \t]*_dispatch} { target { lp64 && *-*-darwin* } } } } */
+/* { dg-final { scan-assembler {movl[ \t]*l_dispatch\$non_lazy_ptr-L[0-9]+\$pb} { target { ia32 && *-*-darwin* } } } } */
+/* { dg-final { scan-assembler "jmp\[ \t\]*_?__x86_indirect_thunk_(r|e)ax" } } */
+/* { dg-final { scan-assembler {jmp[ \t]*\.?LIND} } } */
+/* { dg-final { scan-assembler {call[ \t]*\.?LIND} } } */
/* { dg-final { scan-assembler {\tpause} } } */
/* { dg-final { scan-assembler {\tlfence} } } */
diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-3.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-3.c
index 89a2bac..6a9c513 100644
--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-3.c
+++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-3.c
@@ -1,5 +1,6 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -fno-pic" } */
+/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep " } */
+/* { dg-additional-options "-fno-pic" { target { ! *-*-darwin* } } } */
typedef void (*dispatch_t)(long offset);
@@ -14,9 +15,11 @@ male_indirect_jump (long offset)
return 0;
}
-/* { dg-final { scan-assembler "mov(?:l|q)\[ \t\]*_?dispatch" { target *-*-linux* } } } */
-/* { dg-final { scan-assembler-times "jmp\[ \t\]*\.LIND" 2 } } */
-/* { dg-final { scan-assembler-times "call\[ \t\]*\.LIND" 2 } } */
+/* { dg-final { scan-assembler "mov(?:l|q)\[ \t\]*dispatch" { target *-*-linux* } } } */
+/* { dg-final { scan-assembler {movq[ \t]*_dispatch} { target { lp64 && *-*-darwin* } } } } */
+/* { dg-final { scan-assembler {movl[ \t]*l_dispatch\$non_lazy_ptr-L[0-9]+\$pb} { target { ia32 && *-*-darwin* } } } } */
+/* { dg-final { scan-assembler-times {jmp[ \t]*\.?LIND} 2 } } */
+/* { dg-final { scan-assembler-times {call[ \t]*\.?LIND} 2 } } */
/* { dg-final { scan-assembler {\tpause} } } */
/* { dg-final { scan-assembler {\tlfence} } } */
-/* { dg-final { scan-assembler-not "__x86_indirect_thunk" } } */
+/* { dg-final { scan-assembler-not "_?__x86_indirect_thunk" } } */
diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-4.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-4.c
index 3eb83c3..85ec57b 100644
--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-4.c
+++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-4.c
@@ -1,5 +1,6 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -fno-pic" } */
+/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep " } */
+/* { dg-additional-options "-fno-pic" { target { ! *-*-darwin* } } } */
typedef void (*dispatch_t)(long offset);
@@ -13,9 +14,11 @@ male_indirect_jump (long offset)
return 0;
}
-/* { dg-final { scan-assembler "mov(?:l|q)\[ \t\]*_?dispatch" { target *-*-linux* } } } */
-/* { dg-final { scan-assembler-times "jmp\[ \t\]*\.LIND" 2 } } */
-/* { dg-final { scan-assembler-times "call\[ \t\]*\.LIND" 2 } } */
+/* { dg-final { scan-assembler "mov(?:l|q)\[ \t\]*dispatch" { target *-*-linux* } } } */
+/* { dg-final { scan-assembler {movq[ \t]*_dispatch} { target { lp64 && *-*-darwin* } } } } */
+/* { dg-final { scan-assembler {movl[ \t]*l_dispatch\$non_lazy_ptr-L[0-9]+\$pb} { target { ia32 && *-*-darwin* } } } } */
+/* { dg-final { scan-assembler-times {jmp[ \t]*\.?LIND} 2 } } */
+/* { dg-final { scan-assembler-times {call[ \t]*\.?LIND} 2 } } */
/* { dg-final { scan-assembler {\tpause} } } */
/* { dg-final { scan-assembler {\tlfence} } } */
-/* { dg-final { scan-assembler-not "__x86_indirect_thunk" } } */
+/* { dg-final { scan-assembler-not "_?__x86_indirect_thunk" } } */
diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-5.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-5.c
index 0098dd1..db1d8fb 100644
--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-5.c
+++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-5.c
@@ -1,5 +1,6 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -fno-pic" } */
+/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep " } */
+/* { dg-additional-options "-fno-pic" { target { ! *-*-darwin* } } } */
typedef void (*dispatch_t)(long offset);
@@ -14,8 +15,10 @@ male_indirect_jump (long offset)
return 0;
}
-/* { dg-final { scan-assembler "mov(?:l|q)\[ \t\]*_?dispatch" { target *-*-linux* } } } */
-/* { dg-final { scan-assembler "call\[ \t\]*__x86_indirect_thunk_(r|e)ax" } } */
+/* { dg-final { scan-assembler "mov(?:l|q)\[ \t\]*dispatch" { target *-*-linux* } } } */
+/* { dg-final { scan-assembler {movq[ \t]*_dispatch} { target { lp64 && *-*-darwin* } } } } */
+/* { dg-final { scan-assembler {movl[ \t]*l_dispatch\$non_lazy_ptr-L[0-9]+\$pb} { target { ia32 && *-*-darwin* } } } } */
+/* { dg-final { scan-assembler "call\[ \t\]*_?__x86_indirect_thunk_(r|e)ax" } } */
/* { dg-final { scan-assembler-not {\t(lfence|pause)} } } */
-/* { dg-final { scan-assembler-not "jmp\[ \t\]*\.LIND" } } */
-/* { dg-final { scan-assembler-not "call\[ \t\]*\.LIND" } } */
+/* { dg-final { scan-assembler-not {jmp[ \t]*\.?LIND} } } */
+/* { dg-final { scan-assembler-not {call[ \t]*\.?LIND} } } */
diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-6.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-6.c
index ece8de1..24fc43b 100644
--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-6.c
+++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-6.c
@@ -1,5 +1,6 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -fno-pic" } */
+/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep " } */
+/* { dg-additional-options "-fno-pic" { target { ! *-*-darwin* } } } */
typedef void (*dispatch_t)(long offset);
@@ -13,8 +14,10 @@ male_indirect_jump (long offset)
return 0;
}
-/* { dg-final { scan-assembler "mov(?:l|q)\[ \t\]*_?dispatch" { target *-*-linux* } } } */
-/* { dg-final { scan-assembler "call\[ \t\]*__x86_indirect_thunk_(r|e)ax" } } */
+/* { dg-final { scan-assembler "mov(?:l|q)\[ \t\]*dispatch" { target *-*-linux* } } } */
+/* { dg-final { scan-assembler {movq[ \t]*_dispatch} { target { lp64 && *-*-darwin* } } } } */
+/* { dg-final { scan-assembler {movl[ \t]*l_dispatch\$non_lazy_ptr-L[0-9]+\$pb} { target { ia32 && *-*-darwin* } } } } */
+/* { dg-final { scan-assembler "call\[ \t\]*_?__x86_indirect_thunk_(r|e)ax" } } */
/* { dg-final { scan-assembler-not {\t(lfence|pause)} } } */
-/* { dg-final { scan-assembler-not "jmp\[ \t\]*\.LIND" } } */
-/* { dg-final { scan-assembler-not "call\[ \t\]*\.LIND" } } */
+/* { dg-final { scan-assembler-not {jmp[ \t]*\.?LIND} } } */
+/* { dg-final { scan-assembler-not {call[ \t]*\.?LIND} } } */
diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-7.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-7.c
index ffe7350..d5f2ba6 100644
--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-7.c
+++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-7.c
@@ -1,5 +1,6 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -fno-pic" } */
+/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep " } */
+/* { dg-additional-options "-fno-pic" { target { ! *-*-darwin* } } } */
void func0 (void);
void func1 (void);
@@ -37,7 +38,9 @@ bar (int i)
}
/* { dg-final { scan-assembler "mov(?:l|q)\[ \t\]*\.L\[0-9\]+\\(,%" { target *-*-linux* } } } */
-/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk(_nt|)_(r|e)ax" } } */
+/* { dg-final { scan-assembler {leaq[ \t]*L[0-9]+\(%rip\)} { target { lp64 && *-*-darwin* } } } } */
+/* { dg-final { scan-assembler {addl[ \t]*L[0-9]+-L[0-9]+\$pb} { target { ia32 && *-*-darwin* } } } } */
+/* { dg-final { scan-assembler "jmp\[ \t\]*_?__x86_indirect_thunk(_nt|)_(r|e)ax" } } */
/* { dg-final { scan-assembler-not {\t(lfence|pause)} } } */
-/* { dg-final { scan-assembler-not "jmp\[ \t\]*\.LIND" } } */
-/* { dg-final { scan-assembler-not "call\[ \t\]*\.LIND" } } */
+/* { dg-final { scan-assembler-not {jmp[ \t]*\.?LIND} } } */
+/* { dg-final { scan-assembler-not {call[ \t]*\.?LIND} } } */
diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-8.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-8.c
index d730d31..eb75968 100644
--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-8.c
+++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-8.c
@@ -1,5 +1,6 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -mfunction-return=keep -mindirect-branch=thunk -fno-pic" } */
+/* { dg-options "-O2 -mfunction-return=keep -mindirect-branch=thunk " } */
+/* { dg-additional-options "-fno-pic" { target { ! *-*-darwin* } } } */
void func0 (void);
void func1 (void);
@@ -36,7 +37,7 @@ bar (int i)
}
}
-/* { dg-final { scan-assembler-not "__x86_indirect_thunk" } } */
+/* { dg-final { scan-assembler-not "_?__x86_indirect_thunk" } } */
/* { dg-final { scan-assembler-not {\t(lfence|pause)} } } */
-/* { dg-final { scan-assembler-not "jmp\[ \t\]*\.LIND" } } */
-/* { dg-final { scan-assembler-not "call\[ \t\]*\.LIND" } } */
+/* { dg-final { scan-assembler-not {jmp[ \t]*\.?LIND} } } */
+/* { dg-final { scan-assembler-not {call[ \t]*\.?LIND} } } */
diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-1.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-1.c
index c09dd0a..3dc02f8 100644
--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-1.c
+++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-1.c
@@ -1,5 +1,6 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -mindirect-branch=thunk-extern -fno-pic" } */
+/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -mindirect-branch=thunk-extern " } */
+/* { dg-additional-options "-fno-pic" { target { ! *-*-darwin* } } } */
typedef void (*dispatch_t)(long offset);
@@ -11,8 +12,10 @@ male_indirect_jump (long offset)
dispatch(offset);
}
-/* { dg-final { scan-assembler "mov(?:l|q)\[ \t\]*_?dispatch" { target *-*-linux* } } } */
-/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk_(r|e)ax" } } */
+/* { dg-final { scan-assembler "mov(?:l|q)\[ \t\]*dispatch" { target *-*-linux* } } } */
+/* { dg-final { scan-assembler {movq[ \t]*_dispatch} { target { lp64 && *-*-darwin* } } } } */
+/* { dg-final { scan-assembler {movl[ \t]*l_dispatch\$non_lazy_ptr-L[0-9]+\$pb} { target { ia32 && *-*-darwin* } } } } */
+/* { dg-final { scan-assembler "jmp\[ \t\]*_?__x86_indirect_thunk_(r|e)ax" } } */
/* { dg-final { scan-assembler-not {\t(lfence|pause)} } } */
-/* { dg-final { scan-assembler-not "jmp\[ \t\]*\.LIND" } } */
-/* { dg-final { scan-assembler-not "call\[ \t\]*\.LIND" } } */
+/* { dg-final { scan-assembler-not {jmp[ \t]*\.?LIND} } } */
+/* { dg-final { scan-assembler-not {call[ \t]*\.âLIND} } } */
diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-2.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-2.c
index 826425a..c4adae2 100644
--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-2.c
+++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-2.c
@@ -1,5 +1,6 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -mindirect-branch=thunk-extern -fno-pic" } */
+/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -mindirect-branch=thunk-extern " } */
+/* { dg-additional-options "-fno-pic" { target { ! *-*-darwin* } } } */
typedef void (*dispatch_t)(long offset);
@@ -11,8 +12,10 @@ male_indirect_jump (long offset)
dispatch[offset](offset);
}
-/* { dg-final { scan-assembler "mov(?:l|q)\[ \t\]*_?dispatch" { target *-*-linux* } } } */
-/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk_(r|e)ax" } } */
+/* { dg-final { scan-assembler "mov(?:l|q)\[ \t\]*dispatch" { target *-*-linux* } } } */
+/* { dg-final { scan-assembler {movq[ \t]*_dispatch} { target { lp64 && *-*-darwin* } } } } */
+/* { dg-final { scan-assembler {movl[ \t]*l_dispatch\$non_lazy_ptr-L[0-9]+\$pb} { target { ia32 && *-*-darwin* } } } } */
+/* { dg-final { scan-assembler "jmp\[ \t\]*_?__x86_indirect_thunk_(r|e)ax" } } */
/* { dg-final { scan-assembler-not {\t(lfence|pause)} } } */
-/* { dg-final { scan-assembler-not "jmp\[ \t\]*\.LIND" } } */
-/* { dg-final { scan-assembler-not "call\[ \t\]*\.LIND" } } */
+/* { dg-final { scan-assembler-not {jmp[ \t]*\.?LIND} } } */
+/* { dg-final { scan-assembler-not {call[ \t]*\.?LIND} } } */
diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-3.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-3.c
index 3856268..b800b40 100644
--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-3.c
+++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-3.c
@@ -1,5 +1,6 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -mindirect-branch=thunk-extern -fno-pic" } */
+/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -mindirect-branch=thunk-extern " } */
+/* { dg-additional-options "-fno-pic" { target { ! *-*-darwin* } } } */
typedef void (*dispatch_t)(long offset);
@@ -12,8 +13,10 @@ male_indirect_jump (long offset)
return 0;
}
-/* { dg-final { scan-assembler "mov(?:l|q)\[ \t\]*_?dispatch" { target *-*-linux* } } } */
-/* { dg-final { scan-assembler "call\[ \t\]*__x86_indirect_thunk_(r|e)ax" } } */
+/* { dg-final { scan-assembler "mov(?:l|q)\[ \t\]*dispatch" { target *-*-linux* } } } */
+/* { dg-final { scan-assembler {movq[ \t]*_dispatch} { target { lp64 && *-*-darwin* } } } } */
+/* { dg-final { scan-assembler {movl[ \t]*l_dispatch\$non_lazy_ptr-L[0-9]+\$pb} { target { ia32 && *-*-darwin* } } } } */
+/* { dg-final { scan-assembler "call\[ \t\]*_?__x86_indirect_thunk_(r|e)ax" } } */
/* { dg-final { scan-assembler-not {\t(lfence|pause)} } } */
-/* { dg-final { scan-assembler-not "jmp\[ \t\]*\.LIND" } } */
-/* { dg-final { scan-assembler-not "call\[ \t\]*\.LIND" } } */
+/* { dg-final { scan-assembler-not {jmp[ \t]*\.?LIND} } } */
+/* { dg-final { scan-assembler-not {call[ \t]*\.?LIND} } } */
diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-4.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-4.c
index 1ae49b1..f68902d 100644
--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-4.c
+++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-4.c
@@ -1,5 +1,6 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -mindirect-branch=thunk-extern -fno-pic" } */
+/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -mindirect-branch=thunk-extern " } */
+/* { dg-additional-options "-fno-pic" { target { ! *-*-darwin* } } } */
typedef void (*dispatch_t)(long offset);
@@ -12,7 +13,8 @@ male_indirect_jump (long offset)
return 0;
}
-/* { dg-final { scan-assembler "call\[ \t\]*__x86_indirect_thunk_(r|e)ax" { target x32 } } } */
-/* { dg-final { scan-assembler "mov(?:l|q)\[ \t\]*_?dispatch" { target *-*-linux* } } } */
-/* { dg-final { scan-assembler "call\[ \t\]*__x86_indirect_thunk_(r|e)ax" } } */
+/* { dg-final { scan-assembler "mov(?:l|q)\[ \t\]*dispatch" { target *-*-linux* } } } */
+/* { dg-final { scan-assembler {movq[ \t]*_dispatch} { target { lp64 && *-*-darwin* } } } } */
+/* { dg-final { scan-assembler {movl[ \t]*l_dispatch\$non_lazy_ptr-L[0-9]+\$pb} { target { ia32 && *-*-darwin* } } } } */
+/* { dg-final { scan-assembler "call\[ \t\]*_?__x86_indirect_thunk_(r|e)ax" } } */
/* { dg-final { scan-assembler-not {\t(lfence|pause)} } } */
diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-7.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-7.c
index 95c5cc1..f4c380f 100644
--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-7.c
+++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-7.c
@@ -1,5 +1,6 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -mindirect-branch=thunk-extern -fno-pic -fjump-tables" } */
+/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -mindirect-branch=thunk-extern -fjump-tables" } */
+/* { dg-additional-options "-fno-pic" { target { ! *-*-darwin* } } } */
void func0 (void);
void func1 (void);
@@ -36,7 +37,7 @@ bar (int i)
}
/* { dg-final { scan-assembler "mov(?:l|q)\[ \t\]*\.L\[0-9\]+\\(,%" { target *-*-linux* } } } */
-/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk(_nt|)_(r|e)ax" } } */
+/* { dg-final { scan-assembler "jmp\[ \t\]*_?__x86_indirect_thunk(_nt|)_(r|e)ax" } } */
/* { dg-final { scan-assembler-not {\t(lfence|pause)} } } */
-/* { dg-final { scan-assembler-not "jmp\[ \t\]*\.LIND" } } */
-/* { dg-final { scan-assembler-not "call\[ \t\]*\.LIND" } } */
+/* { dg-final { scan-assembler-not {jmp[ \t]*\.?LIND} } } */
+/* { dg-final { scan-assembler-not "call\[ \t\]*\.?LIND" } } */
diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-1.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-1.c
index 869d904..7301490 100644
--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-1.c
+++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-1.c
@@ -1,5 +1,6 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -mindirect-branch=thunk-inline -fno-pic" } */
+/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -mindirect-branch=thunk-inline " } */
+/* { dg-additional-options "-fno-pic" { target { ! *-*-darwin* } } } */
typedef void (*dispatch_t)(long offset);
@@ -11,10 +12,12 @@ male_indirect_jump (long offset)
dispatch(offset);
}
-/* { dg-final { scan-assembler "mov(?:l|q)\[ \t\]*_?dispatch" { target *-*-linux* } } } */
-/* { dg-final { scan-assembler "jmp\[ \t\]*\.LIND" } } */
-/* { dg-final { scan-assembler "call\[ \t\]*\.LIND" } } */
+/* { dg-final { scan-assembler "mov(?:l|q)\[ \t\]*dispatch" { target *-*-linux* } } } */
+/* { dg-final { scan-assembler {movq[ \t]*_dispatch} { target { lp64 && *-*-darwin* } } } } */
+/* { dg-final { scan-assembler {movl[ \t]*l_dispatch\$non_lazy_ptr-L[0-9]+\$pb} { target { ia32 && *-*-darwin* } } } } */
+/* { dg-final { scan-assembler {jmp[ \t]*\.?LIND} } } */
+/* { dg-final { scan-assembler {call[ \t]*\.?LIND} } } */
/* { dg-final { scan-assembler {\tpause} } } */
/* { dg-final { scan-assembler {\tlfence} } } */
-/* { dg-final { scan-assembler-not "__x86_indirect_thunk" } } */
+/* { dg-final { scan-assembler-not "_?__x86_indirect_thunk" } } */
/* { dg-final { scan-assembler-not "pushq\[ \t\]%rax" { target x32 } } } */
diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-2.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-2.c
index c5c16ed..ef1ba02 100644
--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-2.c
+++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-2.c
@@ -1,5 +1,6 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -mindirect-branch=thunk-inline -fno-pic" } */
+/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -mindirect-branch=thunk-inline " } */
+/* { dg-additional-options "-fno-pic" { target { ! *-*-darwin* } } } */
typedef void (*dispatch_t)(long offset);
@@ -11,10 +12,12 @@ male_indirect_jump (long offset)
dispatch[offset](offset);
}
-/* { dg-final { scan-assembler "mov(?:l|q)\[ \t\]*_?dispatch" { target *-*-linux* } } } */
-/* { dg-final { scan-assembler "jmp\[ \t\]*\.LIND" } } */
-/* { dg-final { scan-assembler "call\[ \t\]*\.LIND" } } */
+/* { dg-final { scan-assembler "mov(?:l|q)\[ \t\]*dispatch" { target *-*-linux* } } } */
+/* { dg-final { scan-assembler {movq[ \t]*_dispatch} { target { lp64 && *-*-darwin* } } } } */
+/* { dg-final { scan-assembler {movl[ \t]*l_dispatch\$non_lazy_ptr-L[0-9]+\$pb} { target { ia32 && *-*-darwin* } } } } */
+/* { dg-final { scan-assembler {jmp[ \t]*\.?LIND} } } */
+/* { dg-final { scan-assembler {call[ \t]*\.?LIND} } } */
/* { dg-final { scan-assembler {\tpause} } } */
/* { dg-final { scan-assembler {\tlfence} } } */
-/* { dg-final { scan-assembler-not "__x86_indirect_thunk" } } */
+/* { dg-final { scan-assembler-not "_?__x86_indirect_thunk" } } */
/* { dg-final { scan-assembler-not "pushq\[ \t\]%rax" { target x32 } } } */
diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-3.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-3.c
index 4a63ebe..58de8f0 100644
--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-3.c
+++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-3.c
@@ -1,5 +1,6 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -mindirect-branch=thunk-inline -fno-pic" } */
+/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -mindirect-branch=thunk-inline " } */
+/* { dg-additional-options "-fno-pic" { target { ! *-*-darwin* } } } */
typedef void (*dispatch_t)(long offset);
@@ -12,10 +13,12 @@ male_indirect_jump (long offset)
return 0;
}
-/* { dg-final { scan-assembler "mov(?:l|q)\[ \t\]*_?dispatch" { target *-*-linux* } } } */
-/* { dg-final { scan-assembler-times "jmp\[ \t\]*\.LIND" 2 } } */
-/* { dg-final { scan-assembler-times "call\[ \t\]*\.LIND" 2 } } */
+/* { dg-final { scan-assembler "mov(?:l|q)\[ \t\]*dispatch" { target *-*-linux* } } } */
+/* { dg-final { scan-assembler {movq[ \t]*_dispatch} { target { lp64 && *-*-darwin* } } } } */
+/* { dg-final { scan-assembler {movl[ \t]*l_dispatch\$non_lazy_ptr-L[0-9]+\$pb} { target { ia32 && *-*-darwin* } } } } */
+/* { dg-final { scan-assembler-times {jmp[ \t]*\.?LIND} 2 } } */
+/* { dg-final { scan-assembler-times {call[ \t]*\.?LIND} 2 } } */
/* { dg-final { scan-assembler-times {\tpause} 1 } } */
/* { dg-final { scan-assembler-times {\tlfence} 1 } } */
-/* { dg-final { scan-assembler-not "__x86_indirect_thunk" } } */
+/* { dg-final { scan-assembler-not "_?__x86_indirect_thunk" } } */
/* { dg-final { scan-assembler-not "pushq\[ \t\]%rax" { target x32 } } } */
diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-4.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-4.c
index a395ffc..3be3ce0 100644
--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-4.c
+++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-4.c
@@ -1,5 +1,6 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -mindirect-branch=thunk-inline -fno-pic" } */
+/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -mindirect-branch=thunk-inline " } */
+/* { dg-additional-options "-fno-pic" { target { ! *-*-darwin* } } } */
typedef void (*dispatch_t)(long offset);
@@ -12,10 +13,12 @@ male_indirect_jump (long offset)
return 0;
}
-/* { dg-final { scan-assembler "mov(?:l|q)\[ \t\]*_?dispatch" { target *-*-linux* } } } */
-/* { dg-final { scan-assembler-times "jmp\[ \t\]*\.LIND" 2 } } */
-/* { dg-final { scan-assembler-times "call\[ \t\]*\.LIND" 2 } } */
+/* { dg-final { scan-assembler "mov(?:l|q)\[ \t\]*dispatch" { target *-*-linux* } } } */
+/* { dg-final { scan-assembler {movq[ \t]*_dispatch} { target { lp64 && *-*-darwin* } } } } */
+/* { dg-final { scan-assembler {movl[ \t]*l_dispatch\$non_lazy_ptr-L[0-9]+\$pb} { target { ia32 && *-*-darwin* } } } } */
+/* { dg-final { scan-assembler-times {jmp[ \t]*\.?LIND} 2 } } */
+/* { dg-final { scan-assembler-times {call[ \t]*\.?LIND} 2 } } */
/* { dg-final { scan-assembler-times {\tpause} 1 } } */
/* { dg-final { scan-assembler-times {\tlfence} 1 } } */
-/* { dg-final { scan-assembler-not "__x86_indirect_thunk" } } */
+/* { dg-final { scan-assembler-not "_?__x86_indirect_thunk" } } */
/* { dg-final { scan-assembler-not "pushq\[ \t\]%rax" { target x32 } } } */
diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-7.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-7.c
index e6f0649..b161faa 100644
--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-7.c
+++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-7.c
@@ -1,5 +1,6 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -mindirect-branch=thunk-inline -fno-pic -fjump-tables" } */
+/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -mindirect-branch=thunk-inline -fjump-tables" } */
+/* { dg-additional-options "-fno-pic" { target { ! *-*-darwin* } } } */
void func0 (void);
void func1 (void);
@@ -37,8 +38,8 @@ bar (int i)
/* { dg-final { scan-assembler "mov(?:l|q)\[ \t\]*\.L\[0-9\]+\\(,%" { target *-*-linux* } } } */
/* { dg-final { scan-assembler-not "pushq\[ \t\]%(r|e)ax" } } */
-/* { dg-final { scan-assembler "jmp\[ \t\]*\.LIND" } } */
-/* { dg-final { scan-assembler "call\[ \t\]*\.LIND" } } */
+/* { dg-final { scan-assembler {jmp[ \t]*\.?LIND} } } */
+/* { dg-final { scan-assembler {call[ \t]*\.?LIND} } } */
/* { dg-final { scan-assembler {\tpause} } } */
/* { dg-final { scan-assembler {\tlfence} } } */
-/* { dg-final { scan-assembler-not "__x86_indirect_thunk" } } */
+/* { dg-final { scan-assembler-not "_?__x86_indirect_thunk" } } */
diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-register-1.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-register-1.c
index 0cf8dae..441e9f0 100644
--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-register-1.c
+++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-register-1.c
@@ -1,5 +1,6 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -mindirect-branch=thunk -mindirect-branch-register -fno-pic" } */
+/* { dg-options "-O2 -mindirect-branch=thunk -mindirect-branch-register " } */
+/* { dg-additional-options "-fno-pic" { target { ! *-*-darwin* } } } */
typedef void (*dispatch_t)(long offset);
@@ -11,11 +12,11 @@ male_indirect_jump (long offset)
dispatch(offset);
}
-/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk_(r|e)ax" } } */
-/* { dg-final { scan-assembler "jmp\[ \t\]*\.LIND" } } */
-/* { dg-final { scan-assembler "call\[ \t\]*\.LIND" } } */
+/* { dg-final { scan-assembler "jmp\[ \t\]*_?__x86_indirect_thunk_(r|e)ax" } } */
+/* { dg-final { scan-assembler {jmp[ \t]*\.?LIND} } } */
+/* { dg-final { scan-assembler {call[ \t]*\.?LIND} } } */
/* { dg-final { scan-assembler "mov\[ \t\](%eax|%rax), \\((%esp|%rsp)\\)" } } */
/* { dg-final { scan-assembler {\tpause} } } */
/* { dg-final { scan-assembler-not "push(?:l|q)\[ \t\]*_?dispatch" } } */
/* { dg-final { scan-assembler-not "pushq\[ \t\]%rax" } } */
-/* { dg-final { scan-assembler-not "__x86_indirect_thunk\n" } } */
+/* { dg-final { scan-assembler-not "_?__x86_indirect_thunk\n" } } */
diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-register-2.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-register-2.c
index e7e616b..30847db 100644
--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-register-2.c
+++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-register-2.c
@@ -1,5 +1,6 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -mindirect-branch=thunk-inline -mindirect-branch-register -fno-pic" } */
+/* { dg-options "-O2 -mindirect-branch=thunk-inline -mindirect-branch-register " } */
+/* { dg-additional-options "-fno-pic" { target { ! *-*-darwin* } } } */
typedef void (*dispatch_t)(long offset);
@@ -11,10 +12,10 @@ male_indirect_jump (long offset)
dispatch(offset);
}
-/* { dg-final { scan-assembler "jmp\[ \t\]*\.LIND" } } */
-/* { dg-final { scan-assembler "call\[ \t\]*\.LIND" } } */
+/* { dg-final { scan-assembler {jmp[ \t]*\.?LIND} } } */
+/* { dg-final { scan-assembler {call[ \t]*\.?LIND} } } */
/* { dg-final { scan-assembler "mov\[ \t\](%eax|%rax), \\((%esp|%rsp)\\)" } } */
/* { dg-final { scan-assembler {\tpause} } } */
/* { dg-final { scan-assembler-not "push(?:l|q)\[ \t\]*_?dispatch" } } */
/* { dg-final { scan-assembler-not "pushq\[ \t\]%rax" } } */
-/* { dg-final { scan-assembler-not "__x86_indirect_thunk" } } */
+/* { dg-final { scan-assembler-not "_?__x86_indirect_thunk" } } */
diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-register-3.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-register-3.c
index 5320e92..cbe14d5 100644
--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-register-3.c
+++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-register-3.c
@@ -1,5 +1,6 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -mindirect-branch=thunk-extern -mindirect-branch-register -fno-pic" } */
+/* { dg-options "-O2 -mindirect-branch=thunk-extern -mindirect-branch-register " } */
+/* { dg-additional-options "-fno-pic" { target { ! *-*-darwin* } } } */
typedef void (*dispatch_t)(long offset);
@@ -11,9 +12,9 @@ male_indirect_jump (long offset)
dispatch(offset);
}
-/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk_(r|e)ax" } } */
+/* { dg-final { scan-assembler "jmp\[ \t\]*_?__x86_indirect_thunk_(r|e)ax" } } */
/* { dg-final { scan-assembler-not "push(?:l|q)\[ \t\]*_?dispatch" } } */
/* { dg-final { scan-assembler-not "pushq\[ \t\]%rax" } } */
/* { dg-final { scan-assembler-not {\t(pause|pause|nop)} } } */
-/* { dg-final { scan-assembler-not "jmp\[ \t\]*\.LIND" } } */
-/* { dg-final { scan-assembler-not "call\[ \t\]*\.LIND" } } */
+/* { dg-final { scan-assembler-not {jmp[ \t]*\.?LIND} } } */
+/* { dg-final { scan-assembler-not {call[ \t]*\.?LIND} } } */
diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-register-4.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-register-4.c
index f0cd9b7..6d2bfc9 100644
--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-register-4.c
+++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-register-4.c
@@ -1,5 +1,6 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -mindirect-branch=keep -fno-pic" } */
+/* { dg-options "-O2 -mindirect-branch=keep " } */
+/* { dg-additional-options "-fno-pic" { target { ! *-*-darwin* } } } */
extern void (*func_p) (void);
diff --git a/gcc/testsuite/gcc.target/i386/inline_error.c b/gcc/testsuite/gcc.target/i386/inline_error.c
index 18e5066..57e60fb 100644
--- a/gcc/testsuite/gcc.target/i386/inline_error.c
+++ b/gcc/testsuite/gcc.target/i386/inline_error.c
@@ -2,7 +2,7 @@
/* { dg-options "-O0 -mno-popcnt" } */
inline int __attribute__ ((__gnu_inline__, __always_inline__, target("popcnt")))
-foo () /* { dg-error "inlining failed in call to always_inline .* target specific option mismatch" } */
+foo () /* { dg-error "inlining failed in call to 'always_inline' .* target specific option mismatch" } */
{
return 0;
}
diff --git a/gcc/testsuite/gcc.target/i386/interrupt-6.c b/gcc/testsuite/gcc.target/i386/interrupt-6.c
index bcbcc97..138b98f 100644
--- a/gcc/testsuite/gcc.target/i386/interrupt-6.c
+++ b/gcc/testsuite/gcc.target/i386/interrupt-6.c
@@ -31,7 +31,7 @@ fn4 (uword_t error_code, void *frame)
error = error_code;
}
-extern int fn5 (void *) __attribute__ ((interrupt)); /* { dg-error "interrupt service routine can't have non-void return value" } */
+extern int fn5 (void *) __attribute__ ((interrupt)); /* { dg-error "interrupt service routine must return 'void'" } */
int
fn5 (void *frame)
diff --git a/gcc/testsuite/gcc.target/i386/interrupt-7.c b/gcc/testsuite/gcc.target/i386/interrupt-7.c
index 506f61a..3e2f6a0 100644
--- a/gcc/testsuite/gcc.target/i386/interrupt-7.c
+++ b/gcc/testsuite/gcc.target/i386/interrupt-7.c
@@ -8,5 +8,5 @@ extern void fn (void *) __attribute__((interrupt));
void
foo (void)
{
- fn (&error); /* { dg-error "interrupt service routine can't be called directly" } */
+ fn (&error); /* { dg-error "interrupt service routine cannot be called directly" } */
}
diff --git a/gcc/testsuite/gcc.target/i386/mcount_pic.c b/gcc/testsuite/gcc.target/i386/mcount_pic.c
index 2eccfbd..5546933 100644
--- a/gcc/testsuite/gcc.target/i386/mcount_pic.c
+++ b/gcc/testsuite/gcc.target/i386/mcount_pic.c
@@ -11,5 +11,5 @@ int main ()
}
/* { dg-final { scan-assembler "mcount" } } */
-/* { dg-final { scan-assembler "get_pc_thunk" { xfail { *-*-solaris2.10* && { ! gld } } } } } */
+/* { dg-final { scan-assembler "get_pc_thunk" } } */
/* { dg-final { cleanup-profile-file } } */
diff --git a/gcc/testsuite/gcc.target/i386/memcpy-strategy-3.c b/gcc/testsuite/gcc.target/i386/memcpy-strategy-3.c
index ddd1ef7..11687e8 100644
--- a/gcc/testsuite/gcc.target/i386/memcpy-strategy-3.c
+++ b/gcc/testsuite/gcc.target/i386/memcpy-strategy-3.c
@@ -1,6 +1,9 @@
/* { dg-do compile } */
/* { dg-options "-O2 -march=atom -mmemcpy-strategy=vector_loop:2000:align,libcall:-1:align" } */
-/* { dg-final { scan-assembler-times "memcpy" 2 } } */
+/* On ELF platforms, one hit comes from the .file directive. */
+/* { dg-final { scan-assembler-times "memcpy" 2 { target { ! *-*-darwin* } } } } */
+/* But not on Darwin, which doesn't have a .file directive by default. */
+/* { dg-final { scan-assembler-times "_memcpy" 1 { target *-*-darwin* } } } */
char a[2048];
char b[2048];
diff --git a/gcc/testsuite/gcc.target/i386/memset-strategy-1.c b/gcc/testsuite/gcc.target/i386/memset-strategy-1.c
index d1b97c5..b4b8e2c 100644
--- a/gcc/testsuite/gcc.target/i386/memset-strategy-1.c
+++ b/gcc/testsuite/gcc.target/i386/memset-strategy-1.c
@@ -1,10 +1,12 @@
/* { dg-do compile } */
/* { dg-options "-O2 -march=atom -mmemset-strategy=libcall:-1:align" } */
-/* { dg-final { scan-assembler-times "memset" 2 } } */
+/* On ELF platforms, one hit comes from the .file directive. */
+/* { dg-final { scan-assembler-times "memset" 2 { target { ! *-*-darwin* } } } } */
+/* But not on Darwin, which doesn't have a .file directive by default. */
+/* { dg-final { scan-assembler-times "_memset" 1 { target *-*-darwin* } } } */
char a[2048];
void t (void)
{
__builtin_memset (a, 1, 2048);
}
-
diff --git a/gcc/testsuite/gcc.target/i386/mmx-vals.h b/gcc/testsuite/gcc.target/i386/mmx-vals.h
new file mode 100644
index 0000000..62d0c1c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/mmx-vals.h
@@ -0,0 +1,77 @@
+/* Routine to check correctness of the results */
+
+__attribute__((unused))
+static int
+saturate_b (int i)
+{
+ if (i > 127)
+ i = 127;
+ else if (i < -128)
+ i = -128;
+ return i;
+}
+
+__attribute__((unused))
+static int
+saturate_w (int i)
+{
+ if (i > 32767)
+ i = 32767;
+ else if (i < -32768)
+ i = -32768;
+ return i;
+}
+
+__attribute__((unused))
+static int
+saturate_ub (int i)
+{
+ if (i > 255)
+ i = 255;
+ else if (i < 0)
+ i = 0;
+ return i;
+}
+
+__attribute__((unused))
+static int
+saturate_uw (int i)
+{
+ if (i > 65535)
+ i = 65535;
+ else if (i < 0)
+ i = 0;
+ return i;
+}
+
+static long long MMXops[] =
+{
+ 0x3467512347612976LL, 0x000000000000000eLL,
+ 0x3467512347612976LL, 0x0000000000000014LL,
+ 0x3467512347612976LL, 0x000000000000003cLL,
+ 0x0000000000000000LL, 0xFFFFFFFFFFFFFFFFLL,
+ 0xFFFFFFFFFFFFFFFFLL, 0x0000000000000000LL,
+ 0x0000000000000001LL, 0x1000000000000000LL,
+ 0x1000000000000000LL, 0x0000000000000001LL,
+ 0xFF00FF00FF00FF00LL, 0x00FF00FF00FF00FFLL,
+ 0xFFFFFFFFFFFFFFFFLL, 0x0101010101010101LL,
+ 0x0101010101010101LL, 0xFFFFFFFFFFFFFFFFLL,
+ 0x0123456789ABCDEFLL, 0x0123456789ABCDEFLL,
+ 0x3467512347612976LL, 0x1839876340879234LL,
+ 0x0000000000000000LL, 0x0000000000000000LL,
+ 0xFFFFFFFFFFFFFFFFLL, 0xFFFFFFFFFFFFFFFFLL,
+ 0x7F7F7F7F7F7F7F7FLL, 0x7F7F7F7F7F7F7F7FLL,
+ 0x7F7F7F7F7F7F7F7FLL, 0x0101010101010101LL,
+ 0x7F7F7F7F7F7F7F7FLL, 0x4782082349761237LL,
+ 0x0000000000000000LL, 0x7F7F7F7F7F7F7F7FLL,
+ 0x8080808080808080LL, 0x8080808080808080LL,
+ 0x0101010101010101LL, 0x8080808080808080LL,
+ 0x8080808080808080LL, 0x0000000000000000LL,
+ 0x2372347120982458LL, 0x8080808080808080LL,
+ 0xFFFFFFFFFFFFFFFFLL, 0x8080808080808080LL,
+ 0x7F7F7F7F7F7F7F7FLL, 0xFFFFFFFFFFFFFFFFLL,
+ 0x8080808080808080LL, 0x7F7F7F7F7F7F7F7FLL,
+ 0xFFFFFFFFFFFFFFFFLL, 0x7F7F7F7F7F7F7F7FLL
+};
+
+#define MMX_num_ops (sizeof (MMXops) / sizeof (MMXops[0]))
diff --git a/gcc/testsuite/gcc.target/i386/nop-mcount.c b/gcc/testsuite/gcc.target/i386/nop-mcount.c
index a8e14bc..a5f8d27 100644
--- a/gcc/testsuite/gcc.target/i386/nop-mcount.c
+++ b/gcc/testsuite/gcc.target/i386/nop-mcount.c
@@ -1,5 +1,6 @@
/* Test -mnop-mcount */
/* { dg-do compile { target { *-*-linux* && nonpic } } } */
+/* { dg-require-effective-target mfentry } */
/* { dg-options "-pg -mfentry -mrecord-mcount -mnop-mcount" } */
/* { dg-final { scan-assembler-not "__fentry__" } } */
/* Origin: Andi Kleen */
diff --git a/gcc/testsuite/gcc.target/i386/pconfig-1.c b/gcc/testsuite/gcc.target/i386/pconfig-1.c
index a3fc4f4..40b4c0c 100644
--- a/gcc/testsuite/gcc.target/i386/pconfig-1.c
+++ b/gcc/testsuite/gcc.target/i386/pconfig-1.c
@@ -1,6 +1,6 @@
/* { dg-do compile } */
/* { dg-options "-O2 -mpconfig" } */
-/* { dg-final { scan-assembler-times "pconfig" 5 } } */
+/* { dg-final { scan-assembler-times {\tpconfig} 2 } } */
#include <x86intrin.h>
diff --git a/gcc/testsuite/gcc.target/i386/pr18041-1.c b/gcc/testsuite/gcc.target/i386/pr18041-1.c
index 24da41a..dafe5a8 100644
--- a/gcc/testsuite/gcc.target/i386/pr18041-1.c
+++ b/gcc/testsuite/gcc.target/i386/pr18041-1.c
@@ -9,5 +9,5 @@ foo (struct B *b)
b->bit0 = b->bit0 | b->bit1;
}
-/* { dg-final { scan-assembler-times "and" 1 } } */
-/* { dg-final { scan-assembler-times "or" 1 } } */
+/* { dg-final { scan-assembler-times {\tand[l|q]} 1 } } */
+/* { dg-final { scan-assembler-times {\tor[l|q]} 1 } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr18041-2.c b/gcc/testsuite/gcc.target/i386/pr18041-2.c
index 00ebd2a..1d7748b 100644
--- a/gcc/testsuite/gcc.target/i386/pr18041-2.c
+++ b/gcc/testsuite/gcc.target/i386/pr18041-2.c
@@ -10,5 +10,5 @@ bar (struct B *b, int x)
}
/* This fails to combine in 32bit mode but not for x32. */
-/* { dg-final { scan-assembler-times "and" 1 { xfail { { ! x32 } && ilp32 } } } } */
-/* { dg-final { scan-assembler-times "or" 1 { xfail { { ! x32 } && ilp32 } } } } */
+/* { dg-final { scan-assembler-times {\tand[lq]} 1 { xfail { { ! x32 } && ilp32 } } } } */
+/* { dg-final { scan-assembler-times {\tor} 1 { xfail { { ! x32 } && ilp32 } } } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr22076.c b/gcc/testsuite/gcc.target/i386/pr22076.c
index 6c1620b..427ffcd 100644
--- a/gcc/testsuite/gcc.target/i386/pr22076.c
+++ b/gcc/testsuite/gcc.target/i386/pr22076.c
@@ -1,19 +1,19 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -fomit-frame-pointer -flax-vector-conversions -mmmx" } */
-/* { dg-additional-options "-mno-vect8-ret-in-mem" { target *-*-vxworks* } } */
+/* { dg-options "-O2 -fomit-frame-pointer -mmmx -mno-sse2" } */
+/* { dg-additional-options "-fno-common" { target *-*-darwin* } } */
+/* { dg-additional-options "-mdynamic-no-pic" { target { ia32 && *-*-darwin* } } } */
#include <mmintrin.h>
-__v8qi test ()
+__m64 x;
+
+void test ()
{
- __v8qi mm0 = {1,2,3,4,5,6,7,8};
- __v8qi mm1 = {11,22,33,44,55,66,77,88};
- volatile __m64 x;
+ __m64 mm0 = (__m64)(__v8qi) {1,2,3,4,5,6,7,8};
+ __m64 mm1 = (__m64)(__v8qi) {11,22,33,44,55,66,77,88};
x = _mm_add_pi8 (mm0, mm1);
-
- return x;
}
-/* { dg-final { scan-assembler-times "movq" 3 } } */
+/* { dg-final { scan-assembler-times "movq" 2 } } */
/* { dg-final { scan-assembler-not "movl" { target nonpic } } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr24414.c b/gcc/testsuite/gcc.target/i386/pr24414.c
index bd12f0c..0acaa00 100644
--- a/gcc/testsuite/gcc.target/i386/pr24414.c
+++ b/gcc/testsuite/gcc.target/i386/pr24414.c
@@ -1,5 +1,6 @@
/* { dg-do run } */
/* { dg-options "-O2" } */
+/* { dg-skip-if "asm insert mismatches ABI for Darwin" { *-*-darwin* } } */
int test;
int
diff --git a/gcc/testsuite/gcc.target/i386/pr30848.c b/gcc/testsuite/gcc.target/i386/pr30848.c
index 2a92851..9c4e22a 100644
--- a/gcc/testsuite/gcc.target/i386/pr30848.c
+++ b/gcc/testsuite/gcc.target/i386/pr30848.c
@@ -2,5 +2,5 @@
void foo(double d)
{
- __asm__ ("" : "=u" (d)); /* { dg-error "output regs" } */
+ __asm__ ("" : "=u" (d)); /* { dg-error "output registers" } */
}
diff --git a/gcc/testsuite/gcc.target/i386/pr30970.c b/gcc/testsuite/gcc.target/i386/pr30970.c
index b1fc2d3..263db5e 100644
--- a/gcc/testsuite/gcc.target/i386/pr30970.c
+++ b/gcc/testsuite/gcc.target/i386/pr30970.c
@@ -1,5 +1,5 @@
/* { dg-do compile }
-/* { dg-options "-msse2 -O2 -ftree-vectorize -mtune=generic" } */
+/* { dg-options "-msse2 -O2 -fno-tree-loop-distribute-patterns -ftree-vectorize -mtune=generic" } */
#define N 256
int b[N];
diff --git a/gcc/testsuite/gcc.target/i386/pr32219-1.c b/gcc/testsuite/gcc.target/i386/pr32219-1.c
index bb28f9f..0fcb138 100644
--- a/gcc/testsuite/gcc.target/i386/pr32219-1.c
+++ b/gcc/testsuite/gcc.target/i386/pr32219-1.c
@@ -12,7 +12,11 @@ foo ()
return xxx;
}
-/* { dg-final { scan-assembler "movl\[ \t\]xxx\\(%rip\\), %eax" { target { ! ia32 } } } } */
-/* { dg-final { scan-assembler-not "xxx@GOTPCREL" { target { ! ia32 } } } } */
-/* { dg-final { scan-assembler "movl\[ \t\]xxx@GOTOFF\\(%\[^,\]*\\), %eax" { target ia32 } } } */
-/* { dg-final { scan-assembler-not "movl\[ \t\]xxx@GOT\\(%\[^,\]*\\), %eax" { target ia32 } } } */
+/* { dg-final { scan-assembler {movl[ \t]_?xxx\(%rip\),[ \t]%eax} { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler-not "_?xxx@GOTPCREL" { target { ! ia32 } } } } */
+
+/* { dg-final { scan-assembler "movl\[ \t\]xxx@GOTOFF\\(%\[^,\]*\\), %eax" { target { ia32 && { ! *-*-darwin* } } } } } */
+/* { dg-final { scan-assembler-not "movl\[ \t\]_?xxx@GOT\\(%\[^,\]*\\), %eax" { target { ia32 && { ! *-*-darwin* } } } } } */
+
+/* For Darwin, we default to PIC - but that's needed for Darwin's PIE. */
+/* { dg-final { scan-assembler {movl[ \t]_xxx-L1\$pb\(%eax\),[ \t]%eax} { target { ia32 && *-*-darwin* } } } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr32219-2.c b/gcc/testsuite/gcc.target/i386/pr32219-2.c
index b30862d..cb587db 100644
--- a/gcc/testsuite/gcc.target/i386/pr32219-2.c
+++ b/gcc/testsuite/gcc.target/i386/pr32219-2.c
@@ -12,6 +12,13 @@ foo ()
}
/* { dg-final { scan-assembler-not "movl\[ \t\]xxx\\(%rip\\), %" { target { ! ia32 } } } } */
+/* For Darwin m64 we are always PIC, but common symbols are indirected, which happens to
+ match the general "ELF" case. */
/* { dg-final { scan-assembler "xxx@GOTPCREL" { target { ! ia32 } } } } */
-/* { dg-final { scan-assembler-not "movl\[ \t\]xxx@GOTOFF\\(%\[^,\]*\\), %" { target ia32 } } } */
-/* { dg-final { scan-assembler "movl\[ \t\]xxx@GOT\\(%\[^,\]*\\), %" { target ia32 } } } */
+
+/* { dg-final { scan-assembler-not "movl\[ \t\]xxx@GOTOFF\\(%\[^,\]*\\), %" { target { ia32 && { ! *-*-darwin* } } } } } */
+/* { dg-final { scan-assembler "movl\[ \t\]xxx@GOT\\(%\[^,\]*\\), %" { target { ia32 && { ! *-*-darwin* } } } } } */
+
+/* Darwin m32 defaults to PIC but common symbols need to be indirected. */
+/* { dg-final { scan-assembler {movl[ \t]l_xxx\$non_lazy_ptr-L1\$pb\(%eax\),[ \t]%eax} { target { ia32 && *-*-darwin* } } } } */
+
diff --git a/gcc/testsuite/gcc.target/i386/pr32219-3.c b/gcc/testsuite/gcc.target/i386/pr32219-3.c
index 657fb78..f9cfca7 100644
--- a/gcc/testsuite/gcc.target/i386/pr32219-3.c
+++ b/gcc/testsuite/gcc.target/i386/pr32219-3.c
@@ -12,7 +12,16 @@ foo ()
return xxx;
}
-/* { dg-final { scan-assembler "movl\[ \t\]xxx\\(%rip\\), %eax" { target { ! ia32 } } } } */
-/* { dg-final { scan-assembler-not "xxx@GOTPCREL" { target { ! ia32 } } } } */
-/* { dg-final { scan-assembler "movl\[ \t\]xxx@GOTOFF\\(%\[^,\]*\\), %eax" { target ia32 } } } */
-/* { dg-final { scan-assembler-not "movl\[ \t\]xxx@GOT\\(%\[^,\]*\\), %eax" { target ia32 } } } */
+/* { dg-final { scan-assembler {movl[ \t]xxx\(%rip\),[ \t]%eax} { target { { ! ia32 } && { ! *-*-darwin* } } } } } */
+/* { dg-final { scan-assembler-not "xxx@GOTPCREL" { target { { ! ia32 } && { ! *-*-darwin* } } } } } */
+
+/* For Darwin m64, code is always PIC and we need to indirect through the GOT to allow
+ weak symbols to be interposed. The dynamic loader knows how to apply PIE to this. */
+/* { dg-final { scan-assembler {movq[ \t]_xxx@GOTPCREL\(%rip\),[ \t]%rax} { target { { ! ia32 } && *-*-darwin* } } } } */
+
+/* { dg-final { scan-assembler "movl\[ \t\]xxx@GOTOFF\\(%\[^,\]*\\), %eax" { target { ia32 && { ! *-*-darwin* } } } } } */
+/* { dg-final { scan-assembler-not "movl\[ \t\]xxx@GOT\\(%\[^,\]*\\), %eax" { target { ia32 && { ! *-*-darwin* } } } } } */
+
+/* For Darwin, we need PIC to allow PIE, but also we must indirect weak symbols so that
+ they can be indirected. Again, dyld knows how to deal with this. */
+/* { dg-final { scan-assembler {movl[ \t]l_xxx\$non_lazy_ptr-L1\$pb\(%eax\),[ \t]%eax} { target { ia32 && *-*-darwin* } } } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr32219-4.c b/gcc/testsuite/gcc.target/i386/pr32219-4.c
index ff62fa4..0ac0674 100644
--- a/gcc/testsuite/gcc.target/i386/pr32219-4.c
+++ b/gcc/testsuite/gcc.target/i386/pr32219-4.c
@@ -13,6 +13,12 @@ foo ()
}
/* { dg-final { scan-assembler-not "movl\[ \t\]xxx\\(%rip\\), %" { target { ! ia32 } } } } */
+/* Darwin is always PIC for PIE so no change, weak symbols need to be indirect and this
+ happens to match the ELF case. */
/* { dg-final { scan-assembler "xxx@GOTPCREL" { target { ! ia32 } } } } */
-/* { dg-final { scan-assembler-not "movl\[ \t\]xxx@GOTOFF\\(%\[^,\]*\\), %" { target ia32 } } } */
-/* { dg-final { scan-assembler "movl\[ \t\]xxx@GOT\\(%\[^,\]*\\), %" { target ia32 } } } */
+
+/* { dg-final { scan-assembler-not "movl\[ \t\]xxx@GOTOFF\\(%\[^,\]*\\), %" { target { ia32 && { ! *-*-darwin* } } } } } */
+/* { dg-final { scan-assembler "movl\[ \t\]xxx@GOT\\(%\[^,\]*\\), %" { target { ia32 && { ! *-*-darwin* } } } } } */
+
+/* Darwin m32 equivalent (indirect and PIC). */
+/* { dg-final { scan-assembler {movl[ \t]l_xxx\$non_lazy_ptr-L1\$pb\(%eax\),[ \t]%eax} { target { ia32 && *-*-darwin* } } } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr32219-5.c b/gcc/testsuite/gcc.target/i386/pr32219-5.c
index e8844c8..11496dc 100644
--- a/gcc/testsuite/gcc.target/i386/pr32219-5.c
+++ b/gcc/testsuite/gcc.target/i386/pr32219-5.c
@@ -11,7 +11,11 @@ foo ()
return xxx;
}
-/* { dg-final { scan-assembler "movl\[ \t\]xxx\\(%rip\\), %eax" { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler "movl\[ \t\]_?xxx\\(%rip\\), %eax" { target { ! ia32 } } } } */
/* { dg-final { scan-assembler-not "xxx@GOTPCREL" { target { ! ia32 } } } } */
-/* { dg-final { scan-assembler "movl\[ \t\]xxx@GOTOFF\\(%\[^,\]*\\), %eax" { target ia32 } } } */
-/* { dg-final { scan-assembler-not "movl\[ \t\]xxx@GOT\\(%\[^,\]*\\), %eax" { target ia32 } } } */
+
+/* { dg-final { scan-assembler "movl\[ \t\]xxx@GOTOFF\\(%\[^,\]*\\), %eax" { target { ia32 && { ! *-*-darwin* } } } } } */
+/* { dg-final { scan-assembler-not "movl\[ \t\]xxx@GOT\\(%\[^,\]*\\), %eax" { target { ia32 && { ! *-*-darwin* } } } } } */
+
+/* For Darwin m32, we need PIC (the default) to allow PIE. */
+/* { dg-final { scan-assembler {movl[ \t]_xxx-L1\$pb\(%eax\),[ \t]%eax} { target { ia32 && *-*-darwin* } } } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr32219-6.c b/gcc/testsuite/gcc.target/i386/pr32219-6.c
index 24e55ae..ff41ebd 100644
--- a/gcc/testsuite/gcc.target/i386/pr32219-6.c
+++ b/gcc/testsuite/gcc.target/i386/pr32219-6.c
@@ -11,7 +11,14 @@ foo ()
return xxx;
}
-/* { dg-final { scan-assembler-not "movl\[ \t\]xxx\\(%rip\\), %" { target { ! ia32 } } } } */
-/* { dg-final { scan-assembler "xxx@GOTPCREL" { target { ! ia32 } } } } */
-/* { dg-final { scan-assembler-not "movl\[ \t\]xxx@GOTOFF\\(%\[^,\]*\\), %" { target ia32 } } } */
-/* { dg-final { scan-assembler "movl\[ \t\]xxx@GOT\\(%\[^,\]*\\), %" { target ia32 } } } */
+/* { dg-final { scan-assembler-not "movl\[ \t\]xxx\\(%rip\\), %" { target { { ! ia32 } && { ! *-*-darwin* } } } } } */
+/* { dg-final { scan-assembler "xxx@GOTPCREL" { target { { ! ia32 } && { ! *-*-darwin* } } } } } */
+
+/* Darwin m64 is always PIC, and the dynamic linker doesn't need an indirection. */
+/* { dg-final { scan-assembler {movl[ \t]_xxx\(%rip\),[ \t]%eax} { target { { ! ia32 } && *-*-darwin* } } } } */
+
+/* { dg-final { scan-assembler-not "movl\[ \t\]xxx@GOTOFF\\(%\[^,\]*\\), %" { target { ia32 && { ! *-*-darwin* } } } } } */
+/* { dg-final { scan-assembler "movl\[ \t\]xxx@GOT\\(%\[^,\]*\\), %" { target { ia32 && { ! *-*-darwin* } } } } } */
+
+/* Darwin m32 defaults to PIC, so no change. */
+/* { dg-final { scan-assembler {movl[ \t]_xxx-L1\$pb\(%eax\),[ \t]%eax} { target { ia32 && *-*-darwin* } } } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr32219-7.c b/gcc/testsuite/gcc.target/i386/pr32219-7.c
index 9273d3e..469e9e3 100644
--- a/gcc/testsuite/gcc.target/i386/pr32219-7.c
+++ b/gcc/testsuite/gcc.target/i386/pr32219-7.c
@@ -12,7 +12,15 @@ foo ()
return xxx;
}
-/* { dg-final { scan-assembler "movl\[ \t\]xxx\\(%rip\\), %eax" { target { ! ia32 } } } } */
-/* { dg-final { scan-assembler-not "xxx@GOTPCREL" { target { ! ia32 } } } } */
-/* { dg-final { scan-assembler "movl\[ \t\]xxx@GOTOFF\\(%\[^,\]*\\), %eax" { target ia32 } } } */
-/* { dg-final { scan-assembler-not "movl\[ \t\]xxx@GOT\\(%\[^,\]*\\), %eax" { target ia32 } } } */
+/* { dg-final { scan-assembler "movl\[ \t\]xxx\\(%rip\\), %eax" { target { { ! ia32 } && { ! *-*-darwin* } } } } } */
+/* { dg-final { scan-assembler-not "xxx@GOTPCREL" { target { { ! ia32 } && { ! *-*-darwin* } } } } } */
+
+/* For Darwin m64, code is always PIC but we need to indirect through the GOT to allow
+ weak symbols to be interposed. The dynamic loader knows how to apply PIE to this. */
+/* { dg-final { scan-assembler {movq[ \t]_xxx@GOTPCREL\(%rip\),[ \t]%rax} { target { { ! ia32 } && *-*-darwin* } } } } */
+
+/* { dg-final { scan-assembler "movl\[ \t\]xxx@GOTOFF\\(%\[^,\]*\\), %eax" { target { ia32 && { ! *-*-darwin* } } } } } */
+/* { dg-final { scan-assembler-not "movl\[ \t\]xxx@GOT\\(%\[^,\]*\\), %eax" { target { ia32 && { ! *-*-darwin* } } } } } */
+
+/* Darwin m32 equivalent (indirect and PIC). */
+/* { dg-final { scan-assembler {movl[ \t]l_xxx\$non_lazy_ptr-L1\$pb\(%eax\),[ \t]%eax} { target { ia32 && *-*-darwin* } } } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr32219-8.c b/gcc/testsuite/gcc.target/i386/pr32219-8.c
index c449195..75eb287 100644
--- a/gcc/testsuite/gcc.target/i386/pr32219-8.c
+++ b/gcc/testsuite/gcc.target/i386/pr32219-8.c
@@ -13,6 +13,12 @@ foo ()
}
/* { dg-final { scan-assembler-not "movl\[ \t\]xxx\\(%rip\\), %" { target { ! ia32 } } } } */
-/* { dg-final { scan-assembler "xxx@GOTPCREL" { target { ! ia32 } } } } */
-/* { dg-final { scan-assembler-not "movl\[ \t\]xxx@GOTOFF\\(%\[^,\]*\\), %" { target ia32 } } } */
-/* { dg-final { scan-assembler "movl\[ \t\]xxx@GOT\\(%\[^,\]*\\), %" { target ia32 } } } */
+/* Darwin is always PIC so no change, weak symbols needs to be indirect and this
+ happens to match the ELF case. */
+/* { dg-final { scan-assembler "_?xxx@GOTPCREL" { target { ! ia32 } } } } */
+
+/* { dg-final { scan-assembler-not "movl\[ \t\]xxx@GOTOFF\\(%\[^,\]*\\), %" { target { ia32 && { ! *-*-darwin* } } } } } */
+/* { dg-final { scan-assembler "movl\[ \t\]xxx@GOT\\(%\[^,\]*\\), %" { target { ia32 && { ! *-*-darwin* } } } } } */
+
+/* Darwin m32 default to PIC but needs indirection for the weak symbol. */
+/* { dg-final { scan-assembler {movl[ \t]l_xxx\$non_lazy_ptr-L1\$pb\(%eax\),[ \t]%eax} { target { ia32 && *-*-darwin* } } } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr39013-1.c b/gcc/testsuite/gcc.target/i386/pr39013-1.c
index ac22746..78b1702 100644
--- a/gcc/testsuite/gcc.target/i386/pr39013-1.c
+++ b/gcc/testsuite/gcc.target/i386/pr39013-1.c
@@ -12,5 +12,9 @@ main (void)
return foo () + bar ();
}
-/* { dg-final { scan-assembler "foo@PLT" } } */
-/* { dg-final { scan-assembler "bar@PLT" } } */
+/* { dg-final { scan-assembler "foo@PLT" { target { ! *-*-darwin* } } } } */
+/* { dg-final { scan-assembler "bar@PLT" { target { ! *-*-darwin* } } } } */
+
+/* Darwin's dynamic linker does PIE without indirection. */
+/* { dg-final { scan-assembler {call[ \t]_foo} { target *-*-darwin* } } } */
+/* { dg-final { scan-assembler {call[ \t]_bar} { target *-*-darwin* } } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr39013-2.c b/gcc/testsuite/gcc.target/i386/pr39013-2.c
index 3040d81..f441290 100644
--- a/gcc/testsuite/gcc.target/i386/pr39013-2.c
+++ b/gcc/testsuite/gcc.target/i386/pr39013-2.c
@@ -12,5 +12,9 @@ main (void)
return foo () + bar ();
}
-/* { dg-final { scan-assembler "foo@PLT" } } */
-/* { dg-final { scan-assembler "bar@PLT" } } */
+/* { dg-final { scan-assembler "foo@PLT" { target { ! *-*-darwin* } } } } */
+/* { dg-final { scan-assembler "bar@PLT" { target { ! *-*-darwin* } } } } */
+
+/* Darwin's dynamic linker does PIE without indirection. */
+/* { dg-final { scan-assembler {call[ \t]_foo} { target *-*-darwin* } } } */
+/* { dg-final { scan-assembler {call[ \t]_bar} { target *-*-darwin* } } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr39082-1.c b/gcc/testsuite/gcc.target/i386/pr39082-1.c
index 2af2264..85b5671 100644
--- a/gcc/testsuite/gcc.target/i386/pr39082-1.c
+++ b/gcc/testsuite/gcc.target/i386/pr39082-1.c
@@ -13,7 +13,7 @@ extern int bar1 (union un);
extern union un bar2 (int);
int
-foo1 (union un u) /* { dg-message "note: the ABI of passing union with long double has changed in GCC 4.4" } */
+foo1 (union un u) /* { dg-message "note: the ABI of passing union with 'long double' has changed in GCC 4.4" } */
{
bar1 (u);
return u.i;
diff --git a/gcc/testsuite/gcc.target/i386/pr39678.c b/gcc/testsuite/gcc.target/i386/pr39678.c
index 0548466..c94c002 100644
--- a/gcc/testsuite/gcc.target/i386/pr39678.c
+++ b/gcc/testsuite/gcc.target/i386/pr39678.c
@@ -10,7 +10,7 @@ struct X {
struct X
foo (float *p)
-{ /* { dg-message "note: the ABI of passing structure with complex float member has changed in GCC 4.4" } */
+{ /* { dg-message "note: the ABI of passing structure with 'complex float' member has changed in GCC 4.4" } */
struct X x;
x.c = -3;
__real x.val = p[0];
diff --git a/gcc/testsuite/gcc.target/i386/pr49866.c b/gcc/testsuite/gcc.target/i386/pr49866.c
index 622c8f6..7c80f13 100644
--- a/gcc/testsuite/gcc.target/i386/pr49866.c
+++ b/gcc/testsuite/gcc.target/i386/pr49866.c
@@ -1,5 +1,6 @@
/* PR target/49866 */
/* { dg-do assemble { target lp64 } } */
+/* { dg-xfail-if "PR90698" { *-*-darwin* } } */
/* { dg-options "-O2 -mcmodel=large" } */
void fn (void *, int, int);
diff --git a/gcc/testsuite/gcc.target/i386/pr52146.c b/gcc/testsuite/gcc.target/i386/pr52146.c
index dcc28d0..9bd8136 100644
--- a/gcc/testsuite/gcc.target/i386/pr52146.c
+++ b/gcc/testsuite/gcc.target/i386/pr52146.c
@@ -1,4 +1,5 @@
/* { dg-do compile { target { ! ia32 } } } */
+/* { dg-require-effective-target maybe_x32 } */
/* { dg-options "-O2 -mx32" } */
void
diff --git a/gcc/testsuite/gcc.target/i386/pr52698.c b/gcc/testsuite/gcc.target/i386/pr52698.c
index d5cfa74..8d8988f 100644
--- a/gcc/testsuite/gcc.target/i386/pr52698.c
+++ b/gcc/testsuite/gcc.target/i386/pr52698.c
@@ -1,4 +1,5 @@
/* { dg-do compile { target { ! ia32 } } } */
+/* { dg-require-effective-target maybe_x32 } */
/* { dg-options "-O2 -mx32 -maddress-mode=long" } */
extern void abort (void);
diff --git a/gcc/testsuite/gcc.target/i386/pr52857-1.c b/gcc/testsuite/gcc.target/i386/pr52857-1.c
index 5c23339..2e8a4af 100644
--- a/gcc/testsuite/gcc.target/i386/pr52857-1.c
+++ b/gcc/testsuite/gcc.target/i386/pr52857-1.c
@@ -1,4 +1,5 @@
/* { dg-do compile { target { ! ia32 } } } */
+/* { dg-require-effective-target maybe_x32 } */
/* { dg-options "-g -O -mx32 -maddress-mode=long" } */
extern void get_BID128 (int *);
diff --git a/gcc/testsuite/gcc.target/i386/pr52857-2.c b/gcc/testsuite/gcc.target/i386/pr52857-2.c
index 99acf84..62ac5df 100644
--- a/gcc/testsuite/gcc.target/i386/pr52857-2.c
+++ b/gcc/testsuite/gcc.target/i386/pr52857-2.c
@@ -1,4 +1,5 @@
/* { dg-do compile { target { ! ia32 } } } */
+/* { dg-require-effective-target maybe_x32 } */
/* { dg-options "-g -O -mx32 -maddress-mode=long" } */
void uw_init_context_1 (void *);
diff --git a/gcc/testsuite/gcc.target/i386/pr52876.c b/gcc/testsuite/gcc.target/i386/pr52876.c
index 249206c..6255b28 100644
--- a/gcc/testsuite/gcc.target/i386/pr52876.c
+++ b/gcc/testsuite/gcc.target/i386/pr52876.c
@@ -1,4 +1,5 @@
/* { dg-do run { target x32 } } */
+/* { dg-require-effective-target maybe_x32 } */
/* { dg-options "-O2 -mx32 -maddress-mode=long" } */
extern void abort (void);
diff --git a/gcc/testsuite/gcc.target/i386/pr53698.c b/gcc/testsuite/gcc.target/i386/pr53698.c
index e36200a..9f36707 100644
--- a/gcc/testsuite/gcc.target/i386/pr53698.c
+++ b/gcc/testsuite/gcc.target/i386/pr53698.c
@@ -1,4 +1,5 @@
/* { dg-do compile { target { ! ia32 } } } */
+/* { dg-require-effective-target maybe_x32 } */
/* { dg-options "-O -mx32 -maddress-mode=long -fno-tree-dominator-opts" } */
extern char foo[];
diff --git a/gcc/testsuite/gcc.target/i386/pr54157.c b/gcc/testsuite/gcc.target/i386/pr54157.c
index 2631867..01b02c5 100644
--- a/gcc/testsuite/gcc.target/i386/pr54157.c
+++ b/gcc/testsuite/gcc.target/i386/pr54157.c
@@ -1,4 +1,5 @@
/* { dg-do compile { target { ! ia32 } } } */
+/* { dg-require-effective-target maybe_x32 } */
/* { dg-options "-O2 -mx32 -maddress-mode=long -ftree-vectorize" } */
struct s2{
diff --git a/gcc/testsuite/gcc.target/i386/pr54855-1.c b/gcc/testsuite/gcc.target/i386/pr54855-1.c
new file mode 100644
index 0000000..693aafa
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr54855-1.c
@@ -0,0 +1,16 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -msse2 -mfpmath=sse" } */
+/* { dg-final { scan-assembler-times "addsd" 1 } } */
+/* { dg-final { scan-assembler-not "movapd" } } */
+/* { dg-final { scan-assembler-not "movsd" } } */
+
+typedef double __v2df __attribute__ ((__vector_size__ (16)));
+typedef double __m128d __attribute__ ((__vector_size__ (16), __may_alias__));
+
+__m128d
+_mm_add_sd (__m128d x, __m128d y)
+{
+ __m128d z = __extension__ (__m128d)(__v2df)
+ { (((__v2df) x)[0] + ((__v2df) y)[0]), ((__v2df) x)[1] };
+ return z;
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr54855-10.c b/gcc/testsuite/gcc.target/i386/pr54855-10.c
new file mode 100644
index 0000000..9e08a85
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr54855-10.c
@@ -0,0 +1,13 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -msse2 -mfpmath=sse" } */
+/* { dg-final { scan-assembler-times "movlpd" 1 } } */
+/* { dg-final { scan-assembler-not "movsd" } } */
+
+typedef double vec __attribute__((vector_size(16)));
+
+vec
+foo (vec x, double *a)
+{
+ x[0] = *a;
+ return x;
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr54855-2.c b/gcc/testsuite/gcc.target/i386/pr54855-2.c
new file mode 100644
index 0000000..20c6f8e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr54855-2.c
@@ -0,0 +1,15 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -msse2 -mfpmath=sse" } */
+/* { dg-final { scan-assembler-times "mulsd" 1 } } */
+/* { dg-final { scan-assembler-not "movapd" } } */
+/* { dg-final { scan-assembler-not "movsd" } } */
+
+typedef double __v2df __attribute__ ((__vector_size__ (16)));
+
+__v2df
+_mm_mul_sd (__v2df x, __v2df y)
+{
+ __v2df z = x;
+ z[0] = x[0] * y[0];
+ return z;
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr54855-3.c b/gcc/testsuite/gcc.target/i386/pr54855-3.c
new file mode 100644
index 0000000..3c15dfc9
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr54855-3.c
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -msse2 -mfpmath=sse" } */
+/* { dg-final { scan-assembler-times "subsd" 1 } } */
+/* { dg-final { scan-assembler-not "movapd" } } */
+/* { dg-final { scan-assembler-not "movsd" } } */
+
+typedef double vec __attribute__((vector_size(16)));
+
+vec
+foo (vec x)
+{
+ x[0] -= 1.;
+ return x;
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr54855-4.c b/gcc/testsuite/gcc.target/i386/pr54855-4.c
new file mode 100644
index 0000000..32eb28e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr54855-4.c
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -msse2 -mfpmath=sse" } */
+/* { dg-final { scan-assembler-times "subsd" 1 } } */
+/* { dg-final { scan-assembler-not "movapd" } } */
+/* { dg-final { scan-assembler-not "movsd" } } */
+
+typedef double vec __attribute__((vector_size(16)));
+
+vec
+foo (vec x, double a)
+{
+ x[0] -= a;
+ return x;
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr54855-5.c b/gcc/testsuite/gcc.target/i386/pr54855-5.c
new file mode 100644
index 0000000..e069990
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr54855-5.c
@@ -0,0 +1,16 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -msse2 -mfpmath=sse" } */
+/* { dg-final { scan-assembler-times "subsd" 1 } } */
+/* { dg-final { scan-assembler-times "mulpd" 1 } } */
+/* { dg-final { scan-assembler-not "movapd" } } */
+/* { dg-final { scan-assembler-not "movsd" } } */
+
+typedef double __v2df __attribute__ ((__vector_size__ (16)));
+
+__v2df
+foo (__v2df x, __v2df y)
+{
+ x[0] -= y[0];
+ x *= y;
+ return x;
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr54855-6.c b/gcc/testsuite/gcc.target/i386/pr54855-6.c
new file mode 100644
index 0000000..8f44d17
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr54855-6.c
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -msse -mfpmath=sse" } */
+/* { dg-final { scan-assembler-times "divss" 1 } } */
+/* { dg-final { scan-assembler-not "movaps" } } */
+/* { dg-final { scan-assembler-not "movss" } } */
+
+typedef float vec __attribute__((vector_size(16)));
+
+vec
+foo (vec x, float f)
+{
+ x[0] /= f;
+ return x;
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr54855-7.c b/gcc/testsuite/gcc.target/i386/pr54855-7.c
new file mode 100644
index 0000000..a551bd5
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr54855-7.c
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -msse -mfpmath=sse" } */
+/* { dg-final { scan-assembler-times "divss" 1 } } */
+/* { dg-final { scan-assembler-not "movaps" } } */
+/* { dg-final { scan-assembler-not "movss" } } */
+
+typedef float vec __attribute__((vector_size(16)));
+
+vec
+foo (vec x)
+{
+ x[0] /= 2.1f;
+ return x;
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr54855-8.c b/gcc/testsuite/gcc.target/i386/pr54855-8.c
new file mode 100644
index 0000000..7602dc2
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr54855-8.c
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -msse2 -mfpmath=sse" } */
+/* { dg-final { scan-assembler-times "maxsd" 1 } } */
+/* { dg-final { scan-assembler-not "movapd" } } */
+/* { dg-final { scan-assembler-not "movsd" } } */
+
+typedef double vec __attribute__((vector_size(16)));
+
+vec
+foo (vec x, double a)
+{
+ x[0] = x[0] > a ? x[0] : a;
+ return x;
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr54855-9.c b/gcc/testsuite/gcc.target/i386/pr54855-9.c
new file mode 100644
index 0000000..40add5f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr54855-9.c
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -msse2 -mfpmath=sse" } */
+/* { dg-final { scan-assembler-times "minss" 1 } } */
+/* { dg-final { scan-assembler-not "movaps" } } */
+/* { dg-final { scan-assembler-not "movss" } } */
+
+typedef float vec __attribute__((vector_size(16)));
+
+vec
+foo (vec x, float a)
+{
+ x[0] = x[0] < a ? x[0] : a;
+ return x;
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr55049-1.c b/gcc/testsuite/gcc.target/i386/pr55049-1.c
index 387bbeb..6486ce9 100644
--- a/gcc/testsuite/gcc.target/i386/pr55049-1.c
+++ b/gcc/testsuite/gcc.target/i386/pr55049-1.c
@@ -1,5 +1,6 @@
/* { dg-do compile { target { ! ia32 } } } */
/* { dg-require-effective-target fpic } */
+/* { dg-require-effective-target maybe_x32 } */
/* { dg-options "-O2 -fPIC -mx32" } */
extern void __morestack_fail (const char *msg);
diff --git a/gcc/testsuite/gcc.target/i386/pr55093.c b/gcc/testsuite/gcc.target/i386/pr55093.c
index bfe2c50..190a942 100644
--- a/gcc/testsuite/gcc.target/i386/pr55093.c
+++ b/gcc/testsuite/gcc.target/i386/pr55093.c
@@ -1,4 +1,5 @@
/* { dg-do compile { target { ! ia32 } } } */
+/* { dg-require-effective-target maybe_x32 } */
/* { dg-options "-O2 -mx32 -maddress-mode=long" } */
/* { dg-skip-if "different ABI" { x86_64-*-mingw* } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr55116-1.c b/gcc/testsuite/gcc.target/i386/pr55116-1.c
index a2e2acd..a7d17ed0 100644
--- a/gcc/testsuite/gcc.target/i386/pr55116-1.c
+++ b/gcc/testsuite/gcc.target/i386/pr55116-1.c
@@ -1,4 +1,5 @@
/* { dg-do compile { target { ! ia32 } } } */
+/* { dg-require-effective-target maybe_x32 } */
/* { dg-options "-O2 -mx32 -maddress-mode=long" } */
int glob_int_arr[100];
diff --git a/gcc/testsuite/gcc.target/i386/pr55116-2.c b/gcc/testsuite/gcc.target/i386/pr55116-2.c
index 59bdebe..62ac0a1 100644
--- a/gcc/testsuite/gcc.target/i386/pr55116-2.c
+++ b/gcc/testsuite/gcc.target/i386/pr55116-2.c
@@ -1,4 +1,5 @@
/* { dg-do compile { target { ! ia32 } } } */
+/* { dg-require-effective-target maybe_x32 } */
/* { dg-options "-O2 -mx32 -maddress-mode=long" } */
typedef struct rtx_def *rtx;
diff --git a/gcc/testsuite/gcc.target/i386/pr55597.c b/gcc/testsuite/gcc.target/i386/pr55597.c
index 617c3e5..b942324 100644
--- a/gcc/testsuite/gcc.target/i386/pr55597.c
+++ b/gcc/testsuite/gcc.target/i386/pr55597.c
@@ -1,5 +1,6 @@
/* { dg-do compile { target { ! ia32 } } } */
/* { dg-require-effective-target fpic } */
+/* { dg-require-effective-target maybe_x32 } */
/* { dg-options "-O2 -fPIC -mx32 -maddress-mode=long" } */
struct initial_sp
diff --git a/gcc/testsuite/gcc.target/i386/pr57756.c b/gcc/testsuite/gcc.target/i386/pr57756.c
index 25c565c..9a78f62 100644
--- a/gcc/testsuite/gcc.target/i386/pr57756.c
+++ b/gcc/testsuite/gcc.target/i386/pr57756.c
@@ -3,7 +3,7 @@
/* callee cannot be inlined into caller because it has a higher target ISA. */
__attribute__((always_inline,target("sse4.2")))
-__inline int callee () /* { dg-error "inlining failed in call to always_inline" } */
+__inline int callee () /* { dg-error "inlining failed in call to 'always_inline'" } */
{
return 0;
}
diff --git a/gcc/testsuite/gcc.target/i386/pr59874-3.c b/gcc/testsuite/gcc.target/i386/pr59874-3.c
index ec55a12..0332f04 100644
--- a/gcc/testsuite/gcc.target/i386/pr59874-3.c
+++ b/gcc/testsuite/gcc.target/i386/pr59874-3.c
@@ -1,7 +1,8 @@
/* PR target/59874 */
/* { dg-do compile } */
/* { dg-options "-O2 -mpopcnt -masm=att" } */
-/* { dg-final { scan-assembler "popcntw" } } */
+/* { dg-final { scan-assembler "\tpopcntw" { target { ! *-*-darwin* } } } } */
+/* { dg-final { scan-assembler "\tpopcnt" { target *-*-darwin* } } } */
unsigned int
foo (unsigned short x)
diff --git a/gcc/testsuite/gcc.target/i386/pr59929.c b/gcc/testsuite/gcc.target/i386/pr59929.c
index 53e0b23..f770d4b 100644
--- a/gcc/testsuite/gcc.target/i386/pr59929.c
+++ b/gcc/testsuite/gcc.target/i386/pr59929.c
@@ -1,5 +1,6 @@
/* { dg-do run } */
/* { dg-options "-O0 -mno-accumulate-outgoing-args" } */
+/* { dg-require-effective-target maybe_x32 } */
/* { dg-additional-options "-mx32 -maddress-mode=short" { target x32 } } */
void
diff --git a/gcc/testsuite/gcc.target/i386/pr61599-1.c b/gcc/testsuite/gcc.target/i386/pr61599-1.c
index 71b1c2f..52fea39 100644
--- a/gcc/testsuite/gcc.target/i386/pr61599-1.c
+++ b/gcc/testsuite/gcc.target/i386/pr61599-1.c
@@ -1,5 +1,6 @@
/* PR target/61599 */
/* { dg-do run { target lp64 } } */
+/* { dg-skip-if "PR90698" { *-*-darwin* } } */
/* { dg-additional-sources pr61599-2.c } */
/* { dg-options "-mcmodel=medium -fdata-sections" } */
diff --git a/gcc/testsuite/gcc.target/i386/pr63538.c b/gcc/testsuite/gcc.target/i386/pr63538.c
index 7b979c3..87d5d3e 100644
--- a/gcc/testsuite/gcc.target/i386/pr63538.c
+++ b/gcc/testsuite/gcc.target/i386/pr63538.c
@@ -9,5 +9,5 @@ char *foo ()
{
return str;
}
-
-/* { dg-final { scan-assembler "movabs" } } */
+/* See PR90698 re. Darwin xfail. */
+/* { dg-final { scan-assembler "movabs" { xfail { *-*-darwin* } } } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr63620.c b/gcc/testsuite/gcc.target/i386/pr63620.c
index 36f6b63..bf38435 100644
--- a/gcc/testsuite/gcc.target/i386/pr63620.c
+++ b/gcc/testsuite/gcc.target/i386/pr63620.c
@@ -17,4 +17,4 @@ test (__float128 x, int p, func f)
return x;
}
-/* { dg-final { scan-assembler "get_pc_thunk" { xfail { *-*-solaris2.10* && { ! gld } } } } } */
+/* { dg-final { scan-assembler "get_pc_thunk" } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr64317.c b/gcc/testsuite/gcc.target/i386/pr64317.c
index 9e13da6..3fbdccd 100644
--- a/gcc/testsuite/gcc.target/i386/pr64317.c
+++ b/gcc/testsuite/gcc.target/i386/pr64317.c
@@ -2,9 +2,14 @@
/* { dg-require-effective-target ia32 } */
/* { dg-require-effective-target pie } */
/* { dg-options "-O2 -fpie" } */
-/* { dg-final { scan-assembler "addl\[ \\t\]+\[$\]_GLOBAL_OFFSET_TABLE_, %ebx" } } */
-/* { dg-final { scan-assembler "movl\[ \\t\]+c@GOTOFF\[(\]%ebx\[)\]" } } */
-/* { dg-final { scan-assembler-not "movl\[ \\t\]+\[0-9]+\[(\]%esp\[)\], %ebx" } } */
+/* { dg-final { scan-assembler "addl\[ \\t\]+\[$\]_GLOBAL_OFFSET_TABLE_, %ebx" { target { ! *-*-darwin* } } } } */
+/* { dg-final { scan-assembler "movl\[ \\t\]+c@GOTOFF\[(\]%ebx\[)\]" { target { ! *-*-darwin* } } } } */
+/* { dg-final { scan-assembler-not "movl\[ \\t\]+\[0-9]+\[(\]%esp\[)\], %ebx" { target { ! *-*-darwin* } } } } */
+
+/* Check PIC access to c and t1 on Darwin (PIC is default, needed for PIE). */
+/* { dg-final { scan-assembler {_c-L1\$pb\(%} { target *-*-darwin* } } } */
+/* { dg-final { scan-assembler {_t1.[0-9]+-L1\$pb\(%} { target *-*-darwin* } } } */
+
long c = 1;
int bar();
diff --git a/gcc/testsuite/gcc.target/i386/pr66470.c b/gcc/testsuite/gcc.target/i386/pr66470.c
index 5c068f3..3515b6d 100644
--- a/gcc/testsuite/gcc.target/i386/pr66470.c
+++ b/gcc/testsuite/gcc.target/i386/pr66470.c
@@ -1,5 +1,6 @@
/* PR target/66470 */
/* { dg-do compile { target { ! ia32 } } } */
+/* { dg-require-effective-target maybe_x32 } */
/* { dg-options "-O2 -mx32 -maddress-mode=long" } */
/* { dg-require-effective-target tls } */
diff --git a/gcc/testsuite/gcc.target/i386/pr66819-3.c b/gcc/testsuite/gcc.target/i386/pr66819-3.c
index 3bc5a34..76e3726 100644
--- a/gcc/testsuite/gcc.target/i386/pr66819-3.c
+++ b/gcc/testsuite/gcc.target/i386/pr66819-3.c
@@ -1,6 +1,6 @@
/* { dg-do compile { target ia32 } } */
/* { dg-options "-O2 -mregparm=3" } */
-/* { dg-final { scan-assembler-not "call" } } */
+/* { dg-final { scan-assembler-not {call[ \t]+_?bar} } } */
void (*bar)(int, int);
diff --git a/gcc/testsuite/gcc.target/i386/pr66819-4.c b/gcc/testsuite/gcc.target/i386/pr66819-4.c
index 18b2ccf..143360d0 100644
--- a/gcc/testsuite/gcc.target/i386/pr66819-4.c
+++ b/gcc/testsuite/gcc.target/i386/pr66819-4.c
@@ -1,6 +1,6 @@
/* { dg-do compile { target ia32 } } */
/* { dg-options "-O2 -mregparm=3" } */
-/* { dg-final { scan-assembler-not "call" } } */
+/* { dg-final { scan-assembler-not {call[ \t]+_?bar} } } */
#include <stdarg.h>
diff --git a/gcc/testsuite/gcc.target/i386/pr67985-2.c b/gcc/testsuite/gcc.target/i386/pr67985-2.c
index 9c7a25a..a45815a 100644
--- a/gcc/testsuite/gcc.target/i386/pr67985-2.c
+++ b/gcc/testsuite/gcc.target/i386/pr67985-2.c
@@ -10,4 +10,4 @@ foo (float x, float y)
/* { dg-final { scan-assembler-not "mulss" } } */
/* { dg-final { scan-assembler-not "movl\[ \t\].*, %eax" } } */
-/* { dg-final { scan-assembler "call\[ \t\]__mulsf3" } } */
+/* { dg-final { scan-assembler "call\[ \t\]_?__mulsf3" } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr68843-1.c b/gcc/testsuite/gcc.target/i386/pr68843-1.c
index da0676a..6198ea9 100644
--- a/gcc/testsuite/gcc.target/i386/pr68843-1.c
+++ b/gcc/testsuite/gcc.target/i386/pr68843-1.c
@@ -5,7 +5,7 @@ double
test ()
{
double x = 1.0;
- asm ("fld %1" /* { dg-error "explicitly used regs must be grouped at top of stack" } */
+ asm ("fld %1" /* { dg-error "explicitly used registers must be grouped at top of stack" } */
: "=&t" (x)
: "u" (x));
return x;
diff --git a/gcc/testsuite/gcc.target/i386/pr70738-7.c b/gcc/testsuite/gcc.target/i386/pr70738-7.c
index 2e5b49f..ee9dfbf 100644
--- a/gcc/testsuite/gcc.target/i386/pr70738-7.c
+++ b/gcc/testsuite/gcc.target/i386/pr70738-7.c
@@ -1,4 +1,4 @@
-/* { dg-do compile { target ia32 } } */
+/* { dg-do compile { target { ia32 && { ! *-*-darwin* } } } } */
/* { dg-options "-msse2 -mgeneral-regs-only" } */
extern float a, b, c;
diff --git a/gcc/testsuite/gcc.target/i386/pr77881.c b/gcc/testsuite/gcc.target/i386/pr77881.c
index 80d143f..6803341 100644
--- a/gcc/testsuite/gcc.target/i386/pr77881.c
+++ b/gcc/testsuite/gcc.target/i386/pr77881.c
@@ -8,5 +8,5 @@ foo (long long int a, long long int a2, int b)
if (a < 0 || b)
baz ();
}
-/* { dg-final { scan-assembler "js\[ \t\]\.L" } } */
-/* { dg-final { scan-assembler "jne\[ \t\]\.L" } } */
+/* { dg-final { scan-assembler "js\[ \t\]\.?L" } } */
+/* { dg-final { scan-assembler "jne\[ \t\]\.?L" } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr79804.c b/gcc/testsuite/gcc.target/i386/pr79804.c
index 10adb44..08d1a3e 100644
--- a/gcc/testsuite/gcc.target/i386/pr79804.c
+++ b/gcc/testsuite/gcc.target/i386/pr79804.c
@@ -7,4 +7,4 @@ void foo (void)
register int r19 asm ("19");
asm volatile ("# %0" : "=r"(r19)); /* { dg-error "invalid use of register" } */
-} /* { dg-error "cannot be used in asm here" } */
+} /* { dg-error "cannot be used in 'asm' here" } */
diff --git a/gcc/testsuite/gcc.target/i386/pr81563.c b/gcc/testsuite/gcc.target/i386/pr81563.c
index ebfd583..f0efcf9 100644
--- a/gcc/testsuite/gcc.target/i386/pr81563.c
+++ b/gcc/testsuite/gcc.target/i386/pr81563.c
@@ -10,5 +10,4 @@ fn1 (long long int x)
return x;
}
-/* { dg-final { scan-assembler-times "movl\[\\t \]*-8\\(%ebp\\),\[\\t \]*%esi" 1 } } */
-/* { dg-final { scan-assembler-times "movl\[\\t \]*-4\\(%ebp\\),\[\\t \]*%edi" 1 } } */
+/* { dg-final { scan-assembler-not "movl\[ \\t\]+\[0-9]*\\(%esp\\)" } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr82483-1.c b/gcc/testsuite/gcc.target/i386/pr82483-1.c
index 59a59dc8..b2028d8 100644
--- a/gcc/testsuite/gcc.target/i386/pr82483-1.c
+++ b/gcc/testsuite/gcc.target/i386/pr82483-1.c
@@ -1,7 +1,7 @@
/* PR target/82483 */
/* { dg-do compile } */
/* { dg-options "-mssse3 -mno-mmx -Wno-psabi" } */
-/* { dg-error "needs isa option" "" { target *-*-* } 0 } */
+/* { dg-error "needs isa option" "" { target ia32 } 0 } */
#include <x86intrin.h>
diff --git a/gcc/testsuite/gcc.target/i386/pr82483-2.c b/gcc/testsuite/gcc.target/i386/pr82483-2.c
index 305ddbd..c92de40 100644
--- a/gcc/testsuite/gcc.target/i386/pr82483-2.c
+++ b/gcc/testsuite/gcc.target/i386/pr82483-2.c
@@ -1,7 +1,7 @@
/* PR target/82483 */
/* { dg-do compile } */
/* { dg-options "-mssse3 -mno-mmx -Wno-psabi" } */
-/* { dg-error "needs isa option" "" { target *-*-* } 0 } */
+/* { dg-error "needs isa option" "" { target ia32 } 0 } */
#include <x86intrin.h>
diff --git a/gcc/testsuite/gcc.target/i386/pr82659-3.c b/gcc/testsuite/gcc.target/i386/pr82659-3.c
index 3bb83e3..a2d97d9 100644
--- a/gcc/testsuite/gcc.target/i386/pr82659-3.c
+++ b/gcc/testsuite/gcc.target/i386/pr82659-3.c
@@ -1,4 +1,5 @@
/* { dg-do compile } */
+/* { dg-require-alias "" } */
/* { dg-options "-O2 -fcf-protection" } */
/* { dg-final { scan-assembler-times {\mendbr} 2 } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr82662.c b/gcc/testsuite/gcc.target/i386/pr82662.c
index 8a9332b..ec08edc 100644
--- a/gcc/testsuite/gcc.target/i386/pr82662.c
+++ b/gcc/testsuite/gcc.target/i386/pr82662.c
@@ -23,4 +23,4 @@ int f9 (S x, S y) { return x >= y; }
int f10 (S x, S y) { return x < y; }
int f11 (S x, S y) { return x <= y; }
-/* { dg-final { scan-assembler-times {\mset} 12 } } */
+/* { dg-final { scan-assembler-times {\tset} 12 } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr82673.c b/gcc/testsuite/gcc.target/i386/pr82673.c
index 50eb5a3..161ec88 100644
--- a/gcc/testsuite/gcc.target/i386/pr82673.c
+++ b/gcc/testsuite/gcc.target/i386/pr82673.c
@@ -9,4 +9,4 @@ void
bar (void) /* { dg-error "frame pointer required, but reserved" } */
{
B = &y;
-} /* { dg-error "bp cannot be used in asm here" } */
+} /* { dg-error "bp cannot be used in 'asm' here" } */
diff --git a/gcc/testsuite/gcc.target/i386/pr82699-2.c b/gcc/testsuite/gcc.target/i386/pr82699-2.c
index 07a4ccb..c43cf44 100644
--- a/gcc/testsuite/gcc.target/i386/pr82699-2.c
+++ b/gcc/testsuite/gcc.target/i386/pr82699-2.c
@@ -1,4 +1,5 @@
/* { dg-do compile { target *-*-linux* } } */
+/* { dg-require-effective-target mfentry } */
/* { dg-options "-O2 -fno-pic -fcf-protection -pg -mfentry -fasynchronous-unwind-tables" } */
/* { dg-final { scan-assembler-times {\t\.cfi_startproc\n\tendbr} 1 } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr82699-4.c b/gcc/testsuite/gcc.target/i386/pr82699-4.c
index 3cc03db..719566b 100644
--- a/gcc/testsuite/gcc.target/i386/pr82699-4.c
+++ b/gcc/testsuite/gcc.target/i386/pr82699-4.c
@@ -1,4 +1,5 @@
/* { dg-do compile { target { *-*-linux* && { ! ia32 } } } } */
+/* { dg-require-effective-target mfentry } */
/* { dg-options "-O2 -fpic -fcf-protection -pg -mfentry -fasynchronous-unwind-tables" } */
/* { dg-final { scan-assembler-times {\t\.cfi_startproc\n\tendbr} 1 } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr82699-5.c b/gcc/testsuite/gcc.target/i386/pr82699-5.c
index 0c547e2..ac3c1ae 100644
--- a/gcc/testsuite/gcc.target/i386/pr82699-5.c
+++ b/gcc/testsuite/gcc.target/i386/pr82699-5.c
@@ -1,4 +1,5 @@
/* { dg-do compile { target *-*-linux* } } */
+/* { dg-require-effective-target mfentry } */
/* { dg-options "-O2 -fcf-protection -mfentry -fasynchronous-unwind-tables" } */
/* { dg-additional-options "-fno-pic" { target ia32 } } */
/* { dg-final { scan-assembler-times {\t\.cfi_startproc\n\tendbr} 1 } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr82699-6.c b/gcc/testsuite/gcc.target/i386/pr82699-6.c
index ff6bae7..0b595f4 100644
--- a/gcc/testsuite/gcc.target/i386/pr82699-6.c
+++ b/gcc/testsuite/gcc.target/i386/pr82699-6.c
@@ -1,4 +1,5 @@
/* { dg-do compile { target *-*-linux* } } */
+/* { dg-require-effective-target mfentry } */
/* { dg-options "-fno-pic -O2 -fcf-protection -pg -mfentry -mrecord-mcount -mnop-mcount -fasynchronous-unwind-tables" } */
/* { dg-final { scan-assembler-times {\t\.cfi_startproc\n\tendbr} 1 } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr84723-1.c b/gcc/testsuite/gcc.target/i386/pr84723-1.c
index 0264ecb..1357b1d 100644
--- a/gcc/testsuite/gcc.target/i386/pr84723-1.c
+++ b/gcc/testsuite/gcc.target/i386/pr84723-1.c
@@ -1,6 +1,5 @@
/* PR middle-end/84723 */
/* { dg-do compile } */
-/* { dg-require-ifunc } */
/* { dg-options "-O2" } */
__attribute__((target_clones ("avx", "default")))
diff --git a/gcc/testsuite/gcc.target/i386/pr84723-2.c b/gcc/testsuite/gcc.target/i386/pr84723-2.c
index 6456d6d..d092e67 100644
--- a/gcc/testsuite/gcc.target/i386/pr84723-2.c
+++ b/gcc/testsuite/gcc.target/i386/pr84723-2.c
@@ -1,6 +1,5 @@
/* PR middle-end/84723 */
/* { dg-do compile } */
-/* { dg-require-ifunc } */
/* { dg-options "-O2" } */
__attribute__((target_clones ("avx", "default")))
diff --git a/gcc/testsuite/gcc.target/i386/pr84723-3.c b/gcc/testsuite/gcc.target/i386/pr84723-3.c
index bb8e7ca..7bb8eb2 100644
--- a/gcc/testsuite/gcc.target/i386/pr84723-3.c
+++ b/gcc/testsuite/gcc.target/i386/pr84723-3.c
@@ -1,6 +1,5 @@
/* PR middle-end/84723 */
/* { dg-do compile } */
-/* { dg-require-ifunc } */
/* { dg-options "-O2" } */
__attribute__((target_clones ("avx", "default")))
diff --git a/gcc/testsuite/gcc.target/i386/pr84723-4.c b/gcc/testsuite/gcc.target/i386/pr84723-4.c
index 9df1008..f30567d 100644
--- a/gcc/testsuite/gcc.target/i386/pr84723-4.c
+++ b/gcc/testsuite/gcc.target/i386/pr84723-4.c
@@ -1,6 +1,5 @@
/* PR middle-end/84723 */
/* { dg-do compile } */
-/* { dg-require-ifunc } */
/* { dg-options "-O2" } */
__attribute__((target_clones ("avx", "default")))
diff --git a/gcc/testsuite/gcc.target/i386/pr84723-5.c b/gcc/testsuite/gcc.target/i386/pr84723-5.c
index c7aa928..0167df3 100644
--- a/gcc/testsuite/gcc.target/i386/pr84723-5.c
+++ b/gcc/testsuite/gcc.target/i386/pr84723-5.c
@@ -1,6 +1,5 @@
/* PR middle-end/84723 */
/* { dg-do compile } */
-/* { dg-require-ifunc } */
/* { dg-options "-O2" } */
__attribute__((target_clones ("avx", "default")))
diff --git a/gcc/testsuite/gcc.target/i386/pr86257.c b/gcc/testsuite/gcc.target/i386/pr86257.c
index 07fbba9..bc758c2 100644
--- a/gcc/testsuite/gcc.target/i386/pr86257.c
+++ b/gcc/testsuite/gcc.target/i386/pr86257.c
@@ -1,6 +1,6 @@
/* { dg-require-effective-target lp64 } */
/* { dg-require-effective-target fpic } */
-/* { dg-require-effective-target tls } */
+/* { dg-require-effective-target tls_native } */
/* { dg-options "-g -fPIC -mtls-dialect=gnu" } */
__thread int i;
diff --git a/gcc/testsuite/gcc.target/i386/pr88828-1.c b/gcc/testsuite/gcc.target/i386/pr88828-1.c
new file mode 100644
index 0000000..a15d1fe
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr88828-1.c
@@ -0,0 +1,49 @@
+/* { dg-do run { target sse2_runtime } } */
+/* { dg-options "-O2 -msse2" } */
+
+#include "pr88828-1a.c"
+#include "pr88828-1b.c"
+#include "pr88828-1c.c"
+
+extern void abort ();
+
+void
+do_check (__v4sf y, float f[4], float z)
+{
+ int i;
+
+ for (i = 0; i < 4; i++)
+ if (i == 0)
+ {
+ if (y[i] != z)
+ abort ();
+ }
+ else
+ {
+ if (y[i] != f[i])
+ abort ();
+ }
+}
+
+int
+main (void)
+{
+ float f[4] = { -11, 2, 55553, -4 };
+ float z = 134567;
+ __v4sf x = { f[0], f[1], f[2], f[3] };
+ __v4sf y;
+ int i;
+
+ for (i = 0; i < 4; i++)
+ if (x[i] != f[i])
+ abort ();
+
+ y = foo1 (x, z);
+ do_check (y, f, z);
+ y = foo2 (x, z);
+ do_check (y, f, z);
+ y = foo3 (x, z);
+ do_check (y, f, z);
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr88828-1a.c b/gcc/testsuite/gcc.target/i386/pr88828-1a.c
new file mode 100644
index 0000000..d37b24c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr88828-1a.c
@@ -0,0 +1,17 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -msse -mno-sse4" } */
+/* { dg-final { scan-assembler "movss" } } */
+/* { dg-final { scan-assembler-not "movaps" } } */
+/* { dg-final { scan-assembler-not "movlhps" } } */
+/* { dg-final { scan-assembler-not "unpcklps" } } */
+/* { dg-final { scan-assembler-not "shufps" } } */
+
+typedef float __v4sf __attribute__ ((__vector_size__ (16)));
+
+__attribute__((noinline, noclone))
+__v4sf
+foo1 (__v4sf x, float f)
+{
+ __v4sf y = { f, x[1], x[2], x[3] };
+ return y;
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr88828-1b.c b/gcc/testsuite/gcc.target/i386/pr88828-1b.c
new file mode 100644
index 0000000..af4aced
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr88828-1b.c
@@ -0,0 +1,23 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -msse -mno-sse4" } */
+/* { dg-final { scan-assembler "movss" } } */
+/* { dg-final { scan-assembler-not "movaps" } } */
+/* { dg-final { scan-assembler-not "movlhps" } } */
+/* { dg-final { scan-assembler-not "unpcklps" } } */
+/* { dg-final { scan-assembler-not "shufps" } } */
+
+typedef float __v4sf __attribute__ ((__vector_size__ (16)));
+
+static __v4sf
+vector_init (float f0,float f1, float f2,float f3)
+{
+ __v4sf y = { f0, f1, f2, f3 };
+ return y;
+}
+
+__attribute__((noinline, noclone))
+__v4sf
+foo2 (__v4sf x, float f)
+{
+ return vector_init (f, x[1], x[2], x[3]) ;
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr88828-1c.c b/gcc/testsuite/gcc.target/i386/pr88828-1c.c
new file mode 100644
index 0000000..a117f3e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr88828-1c.c
@@ -0,0 +1,18 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -msse -mno-sse4" } */
+/* { dg-final { scan-assembler "movss" } } */
+/* { dg-final { scan-assembler-not "movaps" } } */
+/* { dg-final { scan-assembler-not "movlhps" } } */
+/* { dg-final { scan-assembler-not "unpcklps" } } */
+/* { dg-final { scan-assembler-not "shufps" } } */
+
+typedef float __v4sf __attribute__ ((__vector_size__ (16)));
+
+__attribute__((noinline, noclone))
+__v4sf
+foo3 (__v4sf x, float f)
+{
+ __v4sf y = x;
+ y[0] = f;
+ return y;
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr88828-4a.c b/gcc/testsuite/gcc.target/i386/pr88828-4a.c
new file mode 100644
index 0000000..64043b9
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr88828-4a.c
@@ -0,0 +1,18 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -msse -mno-sse4" } */
+/* { dg-final { scan-assembler "movss" } } */
+/* { dg-final { scan-assembler-times "shufps" 1 } } */
+/* { dg-final { scan-assembler-not "movaps" } } */
+/* { dg-final { scan-assembler-not "movlhps" } } */
+/* { dg-final { scan-assembler-not "unpcklps" } } */
+
+typedef float __v4sf __attribute__ ((__vector_size__ (16)));
+
+__attribute__((noinline, noclone))
+__v4sf
+foo (__v4sf x, float f)
+{
+ __v4sf y = { x[0], x[2], x[3], x[1] };
+ y[0] = f;
+ return y;
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr88828-4b.c b/gcc/testsuite/gcc.target/i386/pr88828-4b.c
new file mode 100644
index 0000000..ad8d2b9
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr88828-4b.c
@@ -0,0 +1,21 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mavx" } */
+/* { dg-final { scan-assembler-times "vpermilps" 1 } } */
+/* { dg-final { scan-assembler-times "vmovss" 1 { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler-times "vpinsrd" 1 { target ia32 } } } */
+/* { dg-final { scan-assembler-not "vmovss" { target ia32 } } } */
+/* { dg-final { scan-assembler-not "vshufps" } } */
+/* { dg-final { scan-assembler-not "vmovaps" } } */
+/* { dg-final { scan-assembler-not "vmovlhps" } } */
+/* { dg-final { scan-assembler-not "vunpcklps" } } */
+
+typedef float __v4sf __attribute__ ((__vector_size__ (16)));
+
+__attribute__((noinline, noclone))
+__v4sf
+foo (__v4sf x, float f)
+{
+ __v4sf y = { x[0], x[2], x[3], x[1] };
+ y[0] = f;
+ return y;
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr88828-5a.c b/gcc/testsuite/gcc.target/i386/pr88828-5a.c
new file mode 100644
index 0000000..5e908fa
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr88828-5a.c
@@ -0,0 +1,18 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -msse -mno-sse4" } */
+/* { dg-final { scan-assembler "movss" } } */
+/* { dg-final { scan-assembler-times "shufps" 2 } } */
+/* { dg-final { scan-assembler-times "movaps" 1 } } */
+/* { dg-final { scan-assembler-not "movlhps" } } */
+/* { dg-final { scan-assembler-not "unpcklps" } } */
+
+typedef float __v4sf __attribute__ ((__vector_size__ (16)));
+
+__attribute__((noinline, noclone))
+__v4sf
+foo (__v4sf x, float f)
+{
+ __v4sf y = { x[0], x[2], x[3], x[0] };
+ y[3] = f;
+ return y;
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr88828-5b.c b/gcc/testsuite/gcc.target/i386/pr88828-5b.c
new file mode 100644
index 0000000..988a488
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr88828-5b.c
@@ -0,0 +1,20 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mavx" } */
+/* { dg-final { scan-assembler-times "vpermilps" 1 } } */
+/* { dg-final { scan-assembler-times "vinsertps" 1 } } */
+/* { dg-final { scan-assembler-not "vshufps" } } */
+/* { dg-final { scan-assembler-not "vmovss" } } */
+/* { dg-final { scan-assembler-not "vmovaps" } } */
+/* { dg-final { scan-assembler-not "vmovlhps" } } */
+/* { dg-final { scan-assembler-not "vunpcklps" } } */
+
+typedef float __v4sf __attribute__ ((__vector_size__ (16)));
+
+__attribute__((noinline, noclone))
+__v4sf
+foo (__v4sf x, float f)
+{
+ __v4sf y = { x[0], x[2], x[3], x[0] };
+ y[3] = f;
+ return y;
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr88828-7.c b/gcc/testsuite/gcc.target/i386/pr88828-7.c
new file mode 100644
index 0000000..4302c26
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr88828-7.c
@@ -0,0 +1,53 @@
+/* { dg-do run { target sse2_runtime } } */
+/* { dg-options "-O2 -msse2 -fexcess-precision=standard" } */
+
+#include "pr88828-7a.c"
+#include "pr88828-7b.c"
+
+extern void abort ();
+
+float
+bar (float x, float y)
+{
+ return x / y - y * x;
+}
+
+void
+do_check (__v4sf x, float f1[4], float f2[4])
+{
+ int i;
+
+ for (i = 0; i < 4; i++)
+ if (i == 0)
+ {
+ if (x[i] != bar (f1[i], f2[i]))
+ abort ();
+ }
+ else
+ {
+ if (x[i] != f1[i])
+ abort ();
+ }
+}
+
+int
+main (void)
+{
+ float f1[4] = { -11, 2, 55553, -4 };
+ float f2[4] = { 111, 3.3, -55.553, 4.8 };
+ __v4sf x = { f1[0], f1[1], f1[2], f1[3] };
+ __v4sf y = { f2[0], f2[1], f2[2], f2[3] };
+ __v4sf z;
+ int i;
+
+ for (i = 0; i < 4; i++)
+ if (x[i] != f1[i] || y[i] != f2[i] )
+ abort ();
+
+ z = foo1 (x, y);
+ do_check (z, f1, f2);
+ x = foo2 (x, y);
+ do_check (z, f1, f2);
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr88828-7a.c b/gcc/testsuite/gcc.target/i386/pr88828-7a.c
new file mode 100644
index 0000000..f1ae574
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr88828-7a.c
@@ -0,0 +1,16 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -msse -mno-sse4" } */
+/* { dg-final { scan-assembler-not "movlhps" } } */
+/* { dg-final { scan-assembler-not "unpckhps" } } */
+/* { dg-final { scan-assembler-not "unpcklps" } } */
+/* { dg-final { scan-assembler-not "shufps" } } */
+
+typedef float __v4sf __attribute__ ((__vector_size__ (16)));
+extern float bar (float, float);
+
+__v4sf
+foo1 (__v4sf x, __v4sf y)
+{
+ __v4sf z = { bar (x[0], y[0]), x[1], x[2], x[3] };
+ return z;
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr88828-7b.c b/gcc/testsuite/gcc.target/i386/pr88828-7b.c
new file mode 100644
index 0000000..c027c56
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr88828-7b.c
@@ -0,0 +1,22 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -msse -mno-sse4" } */
+/* { dg-final { scan-assembler-not "movlhps" } } */
+/* { dg-final { scan-assembler-not "unpckhps" } } */
+/* { dg-final { scan-assembler-not "unpcklps" } } */
+/* { dg-final { scan-assembler-not "shufps" } } */
+
+typedef float __v4sf __attribute__ ((__vector_size__ (16)));
+extern float bar (float, float);
+
+static __v4sf
+vector_init (float f0,float f1, float f2,float f3)
+{
+ __v4sf y = { f0, f1, f2, f3 };
+ return y;
+}
+
+__v4sf
+foo2 (__v4sf x, __v4sf y)
+{
+ return vector_init (bar (x[0], y[0]), x[1], x[2], x[3]) ;
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr88828-8.c b/gcc/testsuite/gcc.target/i386/pr88828-8.c
new file mode 100644
index 0000000..3b8eabd
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr88828-8.c
@@ -0,0 +1,46 @@
+/* { dg-do run { target sse2_runtime } } */
+/* { dg-options "-O2 -msse2" } */
+
+#include "pr88828-8a.c"
+#include "pr88828-8b.c"
+
+extern void abort ();
+
+void
+do_check (__v4sf y, float f[4], float z)
+{
+ int i;
+
+ for (i = 0; i < 4; i++)
+ if (i == 0)
+ {
+ if (y[i] != z)
+ abort ();
+ }
+ else
+ {
+ if (y[i] != f[i])
+ abort ();
+ }
+}
+
+int
+main (void)
+{
+ float f[4] = { -11, 2, 55553, -4 };
+ float z = 11.4;
+ __v4sf x = { f[0], f[1], f[2], f[3] };
+ __v4sf y;
+ int i;
+
+ for (i = 0; i < 4; i++)
+ if (x[i] != f[i])
+ abort ();
+
+ y = foo1 (x);
+ do_check (y, f, z);
+ y = foo2 (x);
+ do_check (y, f, z);
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr88828-8a.c b/gcc/testsuite/gcc.target/i386/pr88828-8a.c
new file mode 100644
index 0000000..5d383df
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr88828-8a.c
@@ -0,0 +1,15 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -msse -mno-sse4" } */
+/* { dg-final { scan-assembler-not "movlhps" } } */
+/* { dg-final { scan-assembler-not "unpckhps" } } */
+/* { dg-final { scan-assembler-not "unpcklps" } } */
+/* { dg-final { scan-assembler-not "shufps" } } */
+
+typedef float __v4sf __attribute__ ((__vector_size__ (16)));
+
+__v4sf
+foo1 (__v4sf x)
+{
+ __v4sf z = { 11.4, x[1], x[2], x[3] };
+ return z;
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr88828-8b.c b/gcc/testsuite/gcc.target/i386/pr88828-8b.c
new file mode 100644
index 0000000..5ffbc9c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr88828-8b.c
@@ -0,0 +1,21 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -msse -mno-sse4" } */
+/* { dg-final { scan-assembler-not "movlhps" } } */
+/* { dg-final { scan-assembler-not "unpckhps" } } */
+/* { dg-final { scan-assembler-not "unpcklps" } } */
+/* { dg-final { scan-assembler-not "shufps" } } */
+
+typedef float __v4sf __attribute__ ((__vector_size__ (16)));
+
+static __v4sf
+vector_init (float f0,float f1, float f2,float f3)
+{
+ __v4sf y = { f0, f1, f2, f3 };
+ return y;
+}
+
+__v4sf
+foo2 (__v4sf x)
+{
+ return vector_init (11.4, x[1], x[2], x[3]) ;
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr88828-9.c b/gcc/testsuite/gcc.target/i386/pr88828-9.c
new file mode 100644
index 0000000..c33907b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr88828-9.c
@@ -0,0 +1,46 @@
+/* { dg-do run { target sse2_runtime } } */
+/* { dg-options "-O2 -msse2" } */
+
+#include "pr88828-9a.c"
+#include "pr88828-9b.c"
+
+extern void abort ();
+
+void
+do_check (__v4sf y, float f[4], float z)
+{
+ int i;
+
+ for (i = 0; i < 4; i++)
+ if (i == 0)
+ {
+ if (y[i] != z)
+ abort ();
+ }
+ else
+ {
+ if (y[i] != f[i])
+ abort ();
+ }
+}
+
+int
+main (void)
+{
+ float f[4] = { -11, 2, 55553, -4 };
+ float z = 11.4;
+ __m128 x = (__m128) (__v4sf) { f[0], f[1], f[2], f[3] };
+ __m128 y;
+ int i;
+
+ for (i = 0; i < 4; i++)
+ if (x[i] != f[i])
+ abort ();
+
+ y = foo1 (x);
+ do_check (y, f, z);
+ y = foo2 (x);
+ do_check (y, f, z);
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr88828-9a.c b/gcc/testsuite/gcc.target/i386/pr88828-9a.c
new file mode 100644
index 0000000..7f83065
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr88828-9a.c
@@ -0,0 +1,16 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -msse -mno-sse4" } */
+/* { dg-final { scan-assembler-not "movlhps" } } */
+/* { dg-final { scan-assembler-not "unpckhps" } } */
+/* { dg-final { scan-assembler-not "unpcklps" } } */
+/* { dg-final { scan-assembler-not "shufps" } } */
+
+typedef float __v4sf __attribute__ ((__vector_size__ (16)));
+typedef float __m128 __attribute__ ((__vector_size__ (16), __may_alias__));
+
+__m128
+foo1 (__m128 x)
+{
+ __v4sf z = { 11.4, ((__v4sf) x)[1], ((__v4sf) x)[2], ((__v4sf) x) [3] };
+ return (__m128) z;
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr88828-9b.c b/gcc/testsuite/gcc.target/i386/pr88828-9b.c
new file mode 100644
index 0000000..6588ad1
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr88828-9b.c
@@ -0,0 +1,23 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -msse -mno-sse4" } */
+/* { dg-final { scan-assembler-not "movlhps" } } */
+/* { dg-final { scan-assembler-not "unpckhps" } } */
+/* { dg-final { scan-assembler-not "unpcklps" } } */
+/* { dg-final { scan-assembler-not "shufps" } } */
+
+typedef float __v4sf __attribute__ ((__vector_size__ (16)));
+typedef float __m128 __attribute__ ((__vector_size__ (16), __may_alias__));
+
+static __m128
+vector_init (float f0,float f1, float f2,float f3)
+{
+ __v4sf y = { f0, f1, f2, f3 };
+ return (__m128) y;
+}
+
+__m128
+foo2 (__m128 x)
+{
+ return vector_init (11.4, ((__v4sf) x)[1], ((__v4sf) x)[2],
+ ((__v4sf) x) [3]);
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr89261.c b/gcc/testsuite/gcc.target/i386/pr89261.c
index 63882c0..c5c4273 100644
--- a/gcc/testsuite/gcc.target/i386/pr89261.c
+++ b/gcc/testsuite/gcc.target/i386/pr89261.c
@@ -5,5 +5,6 @@
typedef double __v2df __attribute__ ((vector_size (16), aligned (1 << 28)));
__v2df foo = { 1.0, 2.0 };
+/* { dg-error {alignment of 'foo' is greater than maximum object file alignment 32768} "" { target *-*-darwin* } .-1 } */
-/* { dg-final { scan-assembler "\.align\[ \t]+268435456" } } */
+/* { dg-final { scan-assembler "\.align\[ \t]+268435456" { target { ! *-*-darwin* } } } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr90497-1.c b/gcc/testsuite/gcc.target/i386/pr90497-1.c
new file mode 100644
index 0000000..ed6ded7
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr90497-1.c
@@ -0,0 +1,12 @@
+/* PR target/90497 */
+/* { dg-do compile } */
+/* { dg-options "-mno-sse -mmmx" { target ia32 } } */
+/* { dg-options "-mno-mmx" { target { ! ia32 } } } */
+
+typedef char __v8qi __attribute__ ((__vector_size__ (8)));
+
+__v8qi
+foo (__v8qi x, __v8qi y)
+{
+ return __builtin_ia32_pcmpeqb (x, y);
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr90497-2.c b/gcc/testsuite/gcc.target/i386/pr90497-2.c
new file mode 100644
index 0000000..99ee575
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr90497-2.c
@@ -0,0 +1,11 @@
+/* PR target/90497 */
+/* { dg-do compile { target ia32 } } */
+/* { dg-options "-mno-sse -m3dnow" } */
+
+typedef char __v8qi __attribute__ ((__vector_size__ (8)));
+
+__v8qi
+foo (__v8qi x, __v8qi y)
+{
+ return __builtin_ia32_pavgusb (x, y);
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr90500-1.c b/gcc/testsuite/gcc.target/i386/pr90500-1.c
new file mode 100644
index 0000000..4282a3e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr90500-1.c
@@ -0,0 +1,7 @@
+/* PR middle-end/84723 */
+/* { dg-do compile } */
+/* { dg-require-ifunc "" } */
+
+__attribute__((target_clones("arch=haswell", "default"))) int __tanh() {}
+__typeof(__tanh) tanhf64 __attribute__((alias("__tanh")))
+__attribute__((__copy__(__tanh)));
diff --git a/gcc/testsuite/gcc.target/i386/pr90500-2.c b/gcc/testsuite/gcc.target/i386/pr90500-2.c
new file mode 100644
index 0000000..cb0658d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr90500-2.c
@@ -0,0 +1,7 @@
+/* PR middle-end/84723 */
+/* { dg-do compile } */
+/* { dg-require-ifunc "" } */
+
+__attribute__((target_clones("arch=haswell", "default"))) int __tanh() {}
+__typeof(__tanh) tanhf64 __attribute__((alias("__tanh"),target_clones("arch=haswell", "default"))); /* { dg-error "clones for .target_clones. attribute cannot be created" } */
+ /* { dg-message "'target_clones' cannot be combined with 'alias' attribute" "" { target *-*-* } .-1 } */
diff --git a/gcc/testsuite/gcc.target/i386/pr90510.c b/gcc/testsuite/gcc.target/i386/pr90510.c
new file mode 100644
index 0000000..a3c11a4
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr90510.c
@@ -0,0 +1,22 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -msse2 -fdump-tree-optimized" } */
+
+typedef double __v2df __attribute__ ((__vector_size__ (16)));
+typedef long long __v2di __attribute__ ((__vector_size__ (16)));
+
+__v2df
+_mm_add_sd_A (__v2df x, __v2df y)
+{
+ double tem = x[0] + y[0];
+ return __builtin_shuffle ( x, (__v2df) { tem, tem }, (__v2di) { 2, 1 } );
+}
+
+__v2df
+_mm_add_sd_B (__v2df x, __v2df y)
+{
+ __v2df z = { (x[0] + y[0]), x[1] };
+ return z;
+}
+
+/* { dg-final { scan-tree-dump-times "BIT_INSERT_EXPR" 2 "optimized" } } */
+/* { dg-final { scan-assembler-not "unpck" } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr90547.c b/gcc/testsuite/gcc.target/i386/pr90547.c
new file mode 100644
index 0000000..fcfe669
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr90547.c
@@ -0,0 +1,21 @@
+/* PR target/90547 */
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+void
+foo ()
+{
+ void *g[] = {&&a, &&b};
+
+ for (unsigned c = 0x1F;; c >>= 1)
+ {
+ unsigned d = (long)("a"+1);
+ long e = 8;
+
+ while (e)
+ {
+ a: goto *g[c&d];
+ b: e--;
+ }
+ }
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr90552.c b/gcc/testsuite/gcc.target/i386/pr90552.c
new file mode 100644
index 0000000..59b7e84
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr90552.c
@@ -0,0 +1,11 @@
+/* PR target/90552 *
+/* { dg-do compile } */
+/* { dg-options "-Os" } */
+
+__attribute__((optimize(2)))
+int foo (int x)
+{
+ return x / 3;
+}
+
+/* { dg-final { scan-assembler-not "idiv" } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr90765-1.c b/gcc/testsuite/gcc.target/i386/pr90765-1.c
new file mode 100644
index 0000000..178c3ff
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr90765-1.c
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mavx512f" } */
+/* { dg-final { scan-assembler-not "and\[lq\]?\[\\t \]*\\$-64,\[\\t \]*%\[re\]?sp" } } */
+
+typedef int __v16si __attribute__ ((__vector_size__ (64)));
+
+void
+foo (__v16si x, int i0, int i1, int i2, int i3, int i4, int i5, __v16si *p)
+{
+ *p = x;
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr90765-2.c b/gcc/testsuite/gcc.target/i386/pr90765-2.c
new file mode 100644
index 0000000..45cf1f0
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr90765-2.c
@@ -0,0 +1,18 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mavx512f" } */
+/* { dg-final { scan-assembler "and\[lq\]?\[\\t \]*\\$-64,\[\\t \]*%\[re\]?sp" } } */
+/* { dg-skip-if "" { x86_64-*-mingw* } } */
+
+typedef int __v16si __attribute__ ((__vector_size__ (64)));
+
+extern void foo (__v16si, __v16si, __v16si, __v16si, __v16si, __v16si,
+ __v16si, __v16si, __v16si, int, int, int, int, int,
+ int, __v16si *);
+
+extern __v16si x, y;
+
+void
+bar (void)
+{
+ foo (x, x, x, x, x, x, x, x, x, 0, 1, 2, 3, 4, 5, &y);
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr90856.c b/gcc/testsuite/gcc.target/i386/pr90856.c
new file mode 100644
index 0000000..a9a909b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr90856.c
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-options "-O3" } */
+
+typedef struct { int v; } S1;
+typedef struct { S1 s1[32]; } S2;
+
+S1 clearS1() { S1 s; s.v = 1; return s; }
+
+void
+clearS2(__seg_gs S2 *p, int n)
+{
+ for (int i = 0; i < n; ++i)
+ p->s1[i] = clearS1();
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr90899.c b/gcc/testsuite/gcc.target/i386/pr90899.c
new file mode 100644
index 0000000..e0e2d5a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr90899.c
@@ -0,0 +1,6 @@
+/* PR middle-end/90899 */
+/* { dg-do compile } */
+/* { dg-require-ifunc "" } */
+
+__attribute__ ((target_clones ("default", "arch=slm"))) static int f () { return 0; }
+__attribute__ ((alias ("f"))) __typeof (f) g;
diff --git a/gcc/testsuite/gcc.target/i386/pr91033.c b/gcc/testsuite/gcc.target/i386/pr91033.c
new file mode 100644
index 0000000..43d99d5
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr91033.c
@@ -0,0 +1,15 @@
+/* PR tree-optimization/91033 */
+/* { dg-do compile { target pthread } } */
+/* { dg-options "-march=knl -O2 -fopenmp-simd -ftree-parallelize-loops=2" } */
+
+#define N 1024
+int a[N];
+
+void
+foo (void)
+{
+ int i;
+ #pragma omp simd simdlen (4)
+ for (i = 0; i < N; ++i)
+ a[i] = a[i] + 1;
+}
diff --git a/gcc/testsuite/gcc.target/i386/ptwrite2.c b/gcc/testsuite/gcc.target/i386/ptwrite2.c
index bd144fc..be6b23e 100644
--- a/gcc/testsuite/gcc.target/i386/ptwrite2.c
+++ b/gcc/testsuite/gcc.target/i386/ptwrite2.c
@@ -1,7 +1,7 @@
/* { dg-do compile } */
/* { dg-options "-O2 -mptwrite " } */
-/* { dg-final { scan-assembler "ptwrite\[^\n\r\]+r" } } */
-/* { dg-final { scan-assembler "ptwrite\[^\n\r\]+e" } } */
+/* { dg-final { scan-assembler {ptwrite[^\n\r]+%eax} } } */
+/* { dg-final { scan-assembler {ptwrite[^\n\r]+%rax} { target lp64 } } } */
#include <x86intrin.h>
diff --git a/gcc/testsuite/gcc.target/i386/ret-thunk-1.c b/gcc/testsuite/gcc.target/i386/ret-thunk-1.c
index 7223f67..77f2cf6 100644
--- a/gcc/testsuite/gcc.target/i386/ret-thunk-1.c
+++ b/gcc/testsuite/gcc.target/i386/ret-thunk-1.c
@@ -6,8 +6,8 @@ foo (void)
{
}
-/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_return_thunk" } } */
-/* { dg-final { scan-assembler "jmp\[ \t\]*\.LIND" } } */
-/* { dg-final { scan-assembler "call\[ \t\]*\.LIND" } } */
+/* { dg-final { scan-assembler "jmp\[ \t\]*_?__x86_return_thunk" } } */
+/* { dg-final { scan-assembler {jmp[ \t]*\.?LIND} } } */
+/* { dg-final { scan-assembler {call[ \t]*\.?LIND} } } */
/* { dg-final { scan-assembler {\tpause} } } */
/* { dg-final { scan-assembler {\tlfence} } } */
diff --git a/gcc/testsuite/gcc.target/i386/ret-thunk-10.c b/gcc/testsuite/gcc.target/i386/ret-thunk-10.c
index b245d21..05e96e7 100644
--- a/gcc/testsuite/gcc.target/i386/ret-thunk-10.c
+++ b/gcc/testsuite/gcc.target/i386/ret-thunk-10.c
@@ -1,5 +1,6 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=thunk-inline -mindirect-branch=thunk -fno-pic" } */
+/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=thunk-inline -mindirect-branch=thunk " } */
+/* { dg-additional-options "-fno-pic" { target { ! *-*-darwin* } } } */
extern void (*bar) (void);
@@ -10,11 +11,11 @@ foo (void)
return 0;
}
-/* { dg-final { scan-assembler "jmp\[ \t\]*\.LIND" } } */
-/* { dg-final { scan-assembler "call\[ \t\]*\.LIND" } } */
-/* { dg-final { scan-assembler-not "jmp\[ \t\]*__x86_return_thunk" } } */
+/* { dg-final { scan-assembler {jmp[ \t]*\.?LIND} } } */
+/* { dg-final { scan-assembler {call[ \t]*\.?LIND} } } */
+/* { dg-final { scan-assembler-not "jmp\[ \t\]*_?__x86_return_thunk" } } */
/* { dg-final { scan-assembler-times {\tpause} 2 } } */
/* { dg-final { scan-assembler-times {\tlfence} 2 } } */
-/* { dg-final { scan-assembler "call\[ \t\]*__x86_indirect_thunk_(r|e)ax" } } */
-/* { dg-final { scan-assembler "__x86_indirect_thunk_(r|e)ax:" } } */
+/* { dg-final { scan-assembler "call\[ \t\]*_?__x86_indirect_thunk_(r|e)ax" } } */
+/* { dg-final { scan-assembler "_?__x86_indirect_thunk_(r|e)ax:" } } */
/* { dg-final { scan-assembler-not "pushq\[ \t\]%rax" } } */
diff --git a/gcc/testsuite/gcc.target/i386/ret-thunk-11.c b/gcc/testsuite/gcc.target/i386/ret-thunk-11.c
index ce0543e..19df164 100644
--- a/gcc/testsuite/gcc.target/i386/ret-thunk-11.c
+++ b/gcc/testsuite/gcc.target/i386/ret-thunk-11.c
@@ -1,5 +1,6 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=thunk-extern -mindirect-branch=thunk -fno-pic" } */
+/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=thunk-extern -mindirect-branch=thunk " } */
+/* { dg-additional-options "-fno-pic" { target { ! *-*-darwin* } } } */
extern void (*bar) (void);
@@ -10,11 +11,11 @@ foo (void)
return 0;
}
-/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_return_thunk" } } */
+/* { dg-final { scan-assembler "jmp\[ \t\]*_?__x86_return_thunk" } } */
/* { dg-final { scan-assembler-times {\tpause} 1 } } */
/* { dg-final { scan-assembler-times {\tlfence} 1 } } */
-/* { dg-final { scan-assembler "jmp\[ \t\]*\.LIND" } } */
-/* { dg-final { scan-assembler "call\[ \t\]*\.LIND" } } */
-/* { dg-final { scan-assembler "call\[ \t\]*__x86_indirect_thunk_(r|e)ax" } } */
-/* { dg-final { scan-assembler "__x86_indirect_thunk_(r|e)ax:" } } */
+/* { dg-final { scan-assembler {jmp[ \t]*\.?LIND} } } */
+/* { dg-final { scan-assembler {call[ \t]*\.?LIND} } } */
+/* { dg-final { scan-assembler "call\[ \t\]*_?__x86_indirect_thunk_(r|e)ax" } } */
+/* { dg-final { scan-assembler "_?__x86_indirect_thunk_(r|e)ax:" } } */
/* { dg-final { scan-assembler-not "pushq\[ \t\]%rax" } } */
diff --git a/gcc/testsuite/gcc.target/i386/ret-thunk-12.c b/gcc/testsuite/gcc.target/i386/ret-thunk-12.c
index 3b0023a..b4ca500 100644
--- a/gcc/testsuite/gcc.target/i386/ret-thunk-12.c
+++ b/gcc/testsuite/gcc.target/i386/ret-thunk-12.c
@@ -1,5 +1,6 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -mindirect-branch=thunk -fno-pic" } */
+/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -mindirect-branch=thunk " } */
+/* { dg-additional-options "-fno-pic" { target { ! *-*-darwin* } } } */
extern void (*bar) (void);
@@ -10,11 +11,11 @@ foo (void)
return 0;
}
-/* { dg-final { scan-assembler-not "jmp\[ \t\]*__x86_return_thunk" } } */
+/* { dg-final { scan-assembler-not "jmp\[ \t\]*_?__x86_return_thunk" } } */
/* { dg-final { scan-assembler-times {\tpause} 1 } } */
/* { dg-final { scan-assembler-times {\tlfence} 1 } } */
-/* { dg-final { scan-assembler "jmp\[ \t\]*\.LIND" } } */
-/* { dg-final { scan-assembler "call\[ \t\]*\.LIND" } } */
-/* { dg-final { scan-assembler "call\[ \t\]*__x86_indirect_thunk_(r|e)ax" } } */
-/* { dg-final { scan-assembler "__x86_indirect_thunk_(r|e)ax:" } } */
+/* { dg-final { scan-assembler {jmp[ \t]*\.?LIND} } } */
+/* { dg-final { scan-assembler {call[ \t]*\.?LIND} } } */
+/* { dg-final { scan-assembler "call\[ \t\]*_?__x86_indirect_thunk_(r|e)ax" } } */
+/* { dg-final { scan-assembler "_?__x86_indirect_thunk_(r|e)ax:" } } */
/* { dg-final { scan-assembler-not "pushq\[ \t\]%rax" } } */
diff --git a/gcc/testsuite/gcc.target/i386/ret-thunk-13.c b/gcc/testsuite/gcc.target/i386/ret-thunk-13.c
index 55f156c..2f8d3a04 100644
--- a/gcc/testsuite/gcc.target/i386/ret-thunk-13.c
+++ b/gcc/testsuite/gcc.target/i386/ret-thunk-13.c
@@ -1,5 +1,6 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -mindirect-branch=thunk-inline -fno-pic" } */
+/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -mindirect-branch=thunk-inline " } */
+/* { dg-additional-options "-fno-pic" { target { ! *-*-darwin* } } } */
extern void (*bar) (void);
extern int foo (void) __attribute__ ((function_return("thunk")));
@@ -11,11 +12,11 @@ foo (void)
return 0;
}
-/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_return_thunk" } } */
+/* { dg-final { scan-assembler "jmp\[ \t\]*_?__x86_return_thunk" } } */
/* { dg-final { scan-assembler-times {\tpause} 2 } } */
/* { dg-final { scan-assembler-times {\tlfence} 2 } } */
-/* { dg-final { scan-assembler-times "jmp\[ \t\]*\.LIND" 3 } } */
-/* { dg-final { scan-assembler-times "call\[ \t\]*\.LIND" 3 } } */
-/* { dg-final { scan-assembler-not "jmp\[ \t\]*__x86_indirect_thunk" } } */
-/* { dg-final { scan-assembler-not "call\[ \t\]*__x86_indirect_thunk_(r|e)ax" } } */
+/* { dg-final { scan-assembler-times {jmp[ \t]*\.?LIND} 3 } } */
+/* { dg-final { scan-assembler-times {call[ \t]*\.?LIND} 3 } } */
+/* { dg-final { scan-assembler-not "jmp\[ \t\]*_?__x86_indirect_thunk" } } */
+/* { dg-final { scan-assembler-not "call\[ \t\]*_?__x86_indirect_thunk_(r|e)ax" } } */
/* { dg-final { scan-assembler-not "pushq\[ \t\]%rax" } } */
diff --git a/gcc/testsuite/gcc.target/i386/ret-thunk-14.c b/gcc/testsuite/gcc.target/i386/ret-thunk-14.c
index 1c79043..3eaddee 100644
--- a/gcc/testsuite/gcc.target/i386/ret-thunk-14.c
+++ b/gcc/testsuite/gcc.target/i386/ret-thunk-14.c
@@ -1,5 +1,6 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -mindirect-branch=thunk-extern -fno-pic" } */
+/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -mindirect-branch=thunk-extern " } */
+/* { dg-additional-options "-fno-pic" { target { ! *-*-darwin* } } } */
extern void (*bar) (void);
@@ -13,9 +14,11 @@ foo (void)
/* { dg-final { scan-assembler-times {\tpause} 1 } } */
/* { dg-final { scan-assembler-times {\tlfence} 1 } } */
-/* { dg-final { scan-assembler-not "jmp\[ \t\]*__x86_return_thunk" } } */
-/* { dg-final { scan-assembler "jmp\[ \t\]*\.LIND" } } */
-/* { dg-final { scan-assembler "call\[ \t\]*\.LIND" } } */
-/* { dg-final { scan-assembler "mov(?:l|q)\[ \t\]*_?bar" { target *-*-linux* } } } */
-/* { dg-final { scan-assembler "call\[ \t\]*__x86_indirect_thunk_(r|e)ax" } } */
+/* { dg-final { scan-assembler-not "jmp\[ \t\]*_?__x86_return_thunk" } } */
+/* { dg-final { scan-assembler {jmp[ \t]*\.?LIND} } } */
+/* { dg-final { scan-assembler {call[ \t]*\.?LIND} } } */
+/* { dg-final { scan-assembler "mov(?:l|q)\[ \t\]*bar" { target *-*-linux* } } } */
+/* { dg-final { scan-assembler {movq[ \t]*_bar} { target { lp64 && *-*-darwin* } } } } */
+/* { dg-final { scan-assembler {movl[ \t]*l_bar\$non_lazy_ptr-L[0-9]+\$pb} { target { ia32 && *-*-darwin* } } } } */
+/* { dg-final { scan-assembler "call\[ \t\]*_?__x86_indirect_thunk_(r|e)ax" } } */
/* { dg-final { scan-assembler-not "pushq\[ \t\]%rax" } } */
diff --git a/gcc/testsuite/gcc.target/i386/ret-thunk-15.c b/gcc/testsuite/gcc.target/i386/ret-thunk-15.c
index bc2bedf..2793f72 100644
--- a/gcc/testsuite/gcc.target/i386/ret-thunk-15.c
+++ b/gcc/testsuite/gcc.target/i386/ret-thunk-15.c
@@ -1,5 +1,6 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -mindirect-branch=keep -fno-pic" } */
+/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -mindirect-branch=keep " } */
+/* { dg-additional-options "-fno-pic" { target { ! *-*-darwin* } } } */
extern void (*bar) (void);
@@ -11,11 +12,13 @@ foo (void)
return 0;
}
-/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_return_thunk" } } */
-/* { dg-final { scan-assembler "jmp\[ \t\]*\.LIND" } } */
-/* { dg-final { scan-assembler "call\[ \t\]*\.LIND" } } */
+/* { dg-final { scan-assembler "jmp\[ \t\]*_?__x86_return_thunk" } } */
+/* { dg-final { scan-assembler {jmp[ \t]*\.?LIND} } } */
+/* { dg-final { scan-assembler {call[ \t]*\.?LIND} } } */
/* { dg-final { scan-assembler-times {\tpause} 1 } } */
/* { dg-final { scan-assembler-times {\tlfence} 1 } } */
-/* { dg-final { scan-assembler "mov(?:l|q)\[ \t\]*_?bar" { target *-*-linux* } } } */
-/* { dg-final { scan-assembler "call\[ \t\]*__x86_indirect_thunk_(r|e)ax" } } */
+/* { dg-final { scan-assembler "mov(?:l|q)\[ \t\]*bar" { target *-*-linux* } } } */
+/* { dg-final { scan-assembler {movq[ \t]*_bar} { target { lp64 && *-*-darwin* } } } } */
+/* { dg-final { scan-assembler {movl[ \t]*l_bar\$non_lazy_ptr-L[0-9]+\$pb} { target { ia32 && *-*-darwin* } } } } */
+/* { dg-final { scan-assembler "call\[ \t\]*_?__x86_indirect_thunk_(r|e)ax" } } */
/* { dg-final { scan-assembler-not "pushq\[ \t\]%rax" } } */
diff --git a/gcc/testsuite/gcc.target/i386/ret-thunk-16.c b/gcc/testsuite/gcc.target/i386/ret-thunk-16.c
index a16cad1..5f439e4 100644
--- a/gcc/testsuite/gcc.target/i386/ret-thunk-16.c
+++ b/gcc/testsuite/gcc.target/i386/ret-thunk-16.c
@@ -1,5 +1,6 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -mfunction-return=thunk-inline -mindirect-branch=thunk-extern -fno-pic" } */
+/* { dg-options "-O2 -mfunction-return=thunk-inline -mindirect-branch=thunk-extern " } */
+/* { dg-additional-options "-fno-pic" { target { ! *-*-darwin* } } } */
extern void (*bar) (void);
@@ -11,8 +12,8 @@ foo (void)
return 0;
}
-/* { dg-final { scan-assembler-not "__x86_indirect_thunk" } } */
-/* { dg-final { scan-assembler-not "__x86_return_thunk" } } */
+/* { dg-final { scan-assembler-not "_?__x86_indirect_thunk" } } */
+/* { dg-final { scan-assembler-not "_?__x86_return_thunk" } } */
/* { dg-final { scan-assembler-not {\t(lfence|pause)} } } */
-/* { dg-final { scan-assembler-not "jmp\[ \t\]*\.LIND" } } */
-/* { dg-final { scan-assembler-not "call\[ \t\]*\.LIND" } } */
+/* { dg-final { scan-assembler-not {jmp[ \t]*\.?LIND} } } */
+/* { dg-final { scan-assembler-not {call[ \t]*\.?LIND} } } */
diff --git a/gcc/testsuite/gcc.target/i386/ret-thunk-2.c b/gcc/testsuite/gcc.target/i386/ret-thunk-2.c
index c6659e3..3cb9421 100644
--- a/gcc/testsuite/gcc.target/i386/ret-thunk-2.c
+++ b/gcc/testsuite/gcc.target/i386/ret-thunk-2.c
@@ -6,8 +6,8 @@ foo (void)
{
}
-/* { dg-final { scan-assembler "jmp\[ \t\]*\.LIND" } } */
-/* { dg-final { scan-assembler "call\[ \t\]*\.LIND" } } */
+/* { dg-final { scan-assembler {jmp[ \t]*\.?LIND} } } */
+/* { dg-final { scan-assembler {call[ \t]*\.?LIND} } } */
/* { dg-final { scan-assembler {\tpause} } } */
/* { dg-final { scan-assembler {\tlfence} } } */
-/* { dg-final { scan-assembler-not "jmp\[ \t\]*__x86_return_thunk" } } */
+/* { dg-final { scan-assembler-not "jmp\[ \t\]*_?__x86_return_thunk" } } */
diff --git a/gcc/testsuite/gcc.target/i386/ret-thunk-22.c b/gcc/testsuite/gcc.target/i386/ret-thunk-22.c
index 89e086d..9a9f42e 100644
--- a/gcc/testsuite/gcc.target/i386/ret-thunk-22.c
+++ b/gcc/testsuite/gcc.target/i386/ret-thunk-22.c
@@ -6,10 +6,12 @@ struct s { _Complex unsigned short x; };
struct s gs = { 100 + 200i };
struct s __attribute__((noinline)) foo (void) { return gs; }
-/* { dg-final { scan-assembler-times "popl\[\\t \]*%ecx" 1 } } */
-/* { dg-final { scan-assembler "lea\[l\]?\[\\t \]*4\\(%esp\\), %esp" } } */
-/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_return_thunk_ecx" } } */
-/* { dg-final { scan-assembler "jmp\[ \t\]*\.LIND" } } */
-/* { dg-final { scan-assembler "call\[ \t\]*\.LIND" } } */
+/* { dg-final { scan-assembler-times "popl\[\\t \]*%ecx" 1 { target { ! *-*-darwin* } } } } */
+/* { dg-final { scan-assembler "lea\[l\]?\[\\t \]*4\\(%esp\\), %esp" { target { ! *-*-darwin* } } } } */
+/* { dg-final { scan-assembler "jmp\[ \t\]*_?__x86_return_thunk_ecx" { target { ! *-*-darwin* } } } } */
+/* { dg-final { scan-assembler {call[ \t]*___x86.get_pc_thunk.cx} { target { *-*-darwin* } } } } */
+/* { dg-final { scan-assembler {jmp[ \t]*___x86_return_thunk} { target { *-*-darwin* } } } } */
+/* { dg-final { scan-assembler {jmp[ \t]*\.?LIND} } } */
+/* { dg-final { scan-assembler {call[ \t]*\.?LIND} } } */
/* { dg-final { scan-assembler {\tpause} } } */
/* { dg-final { scan-assembler {\tlfence} } } */
diff --git a/gcc/testsuite/gcc.target/i386/ret-thunk-23.c b/gcc/testsuite/gcc.target/i386/ret-thunk-23.c
index 43f0cca..69469a4 100644
--- a/gcc/testsuite/gcc.target/i386/ret-thunk-23.c
+++ b/gcc/testsuite/gcc.target/i386/ret-thunk-23.c
@@ -6,10 +6,12 @@ struct s { _Complex unsigned short x; };
struct s gs = { 100 + 200i };
struct s __attribute__((noinline)) foo (void) { return gs; }
-/* { dg-final { scan-assembler-times "popl\[\\t \]*%ecx" 1 } } */
-/* { dg-final { scan-assembler "lea\[l\]?\[\\t \]*4\\(%esp\\), %esp" } } */
-/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_return_thunk_ecx" } } */
-/* { dg-final { scan-assembler-not "jmp\[ \t\]*\.LIND" } } */
-/* { dg-final { scan-assembler-not "call\[ \t\]*\.LIND" } } */
+/* { dg-final { scan-assembler-times "popl\[\\t \]*%ecx" 1 { target { ! *-*-darwin* } } } } */
+/* { dg-final { scan-assembler "lea\[l\]?\[\\t \]*4\\(%esp\\), %esp" { target { ! *-*-darwin* } } } } */
+/* { dg-final { scan-assembler "jmp\[ \t\]*_?__x86_return_thunk_ecx" { target { ! *-*-darwin* } } } } */
+/* { dg-final { scan-assembler {call[ \t]*___x86.get_pc_thunk.cx} { target { *-*-darwin* } } } } */
+/* { dg-final { scan-assembler {jmp[ \t]*___x86_return_thunk} { target { *-*-darwin* } } } } */
+/* { dg-final { scan-assembler-not {jmp[ \t]*\.?LIND} } } */
+/* { dg-final { scan-assembler-not {call[ \t]*\.?LIND} } } */
/* { dg-final { scan-assembler-not {\tpause} } } */
/* { dg-final { scan-assembler-not {\tlfence} } } */
diff --git a/gcc/testsuite/gcc.target/i386/ret-thunk-24.c b/gcc/testsuite/gcc.target/i386/ret-thunk-24.c
index 8729e35..0e78779 100644
--- a/gcc/testsuite/gcc.target/i386/ret-thunk-24.c
+++ b/gcc/testsuite/gcc.target/i386/ret-thunk-24.c
@@ -6,10 +6,12 @@ struct s { _Complex unsigned short x; };
struct s gs = { 100 + 200i };
struct s __attribute__((noinline)) foo (void) { return gs; }
-/* { dg-final { scan-assembler-times "popl\[\\t \]*%ecx" 1 } } */
-/* { dg-final { scan-assembler "lea\[l\]?\[\\t \]*4\\(%esp\\), %esp" } } */
-/* { dg-final { scan-assembler-not "jmp\[ \t\]*__x86_return_thunk_ecx" } } */
-/* { dg-final { scan-assembler "jmp\[ \t\]*\.LIND" } } */
-/* { dg-final { scan-assembler "call\[ \t\]*\.LIND" } } */
+/* { dg-final { scan-assembler-times "popl\[\\t \]*%ecx" 1 { target { ! *-*-darwin* } } } } */
+/* { dg-final { scan-assembler "lea\[l\]?\[\\t \]*4\\(%esp\\), %esp" { target { ! *-*-darwin* } } } } */
+/* { dg-final { scan-assembler-not "jmp\[ \t\]*_?__x86_return_thunk_ecx" { target { ! *-*-darwin* } } } } */
+/* { dg-final { scan-assembler {call[ \t]*___x86.get_pc_thunk.cx} { target { *-*-darwin* } } } } */
+/* { dg-final { scan-assembler-not {jmp[ \t]*___x86_return_thunk} { target { *-*-darwin* } } } } */
+/* { dg-final { scan-assembler {jmp[ \t]*\.?LIND} } } */
+/* { dg-final { scan-assembler {call[ \t]*\.?LIND} } } */
/* { dg-final { scan-assembler {\tpause} } } */
/* { dg-final { scan-assembler {\tlfence} } } */
diff --git a/gcc/testsuite/gcc.target/i386/ret-thunk-3.c b/gcc/testsuite/gcc.target/i386/ret-thunk-3.c
index 0f7f388..eb58516 100644
--- a/gcc/testsuite/gcc.target/i386/ret-thunk-3.c
+++ b/gcc/testsuite/gcc.target/i386/ret-thunk-3.c
@@ -6,7 +6,7 @@ foo (void)
{
}
-/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_return_thunk" } } */
+/* { dg-final { scan-assembler "jmp\[ \t\]*_?__x86_return_thunk" } } */
/* { dg-final { scan-assembler-not {\t(lfence|pause)} } } */
-/* { dg-final { scan-assembler-not "jmp\[ \t\]*\.LIND" } } */
-/* { dg-final { scan-assembler-not "call\[ \t\]*\.LIND" } } */
+/* { dg-final { scan-assembler-not {jmp[ \t]*\.?LIND} } } */
+/* { dg-final { scan-assembler-not {call[ \t]*\.?LIND} } } */
diff --git a/gcc/testsuite/gcc.target/i386/ret-thunk-4.c b/gcc/testsuite/gcc.target/i386/ret-thunk-4.c
index 9ae37e8..736f727 100644
--- a/gcc/testsuite/gcc.target/i386/ret-thunk-4.c
+++ b/gcc/testsuite/gcc.target/i386/ret-thunk-4.c
@@ -6,7 +6,7 @@ foo (void)
{
}
-/* { dg-final { scan-assembler-not "jmp\[ \t\]*__x86_return_thunk" } } */
+/* { dg-final { scan-assembler-not "jmp\[ \t\]*_?__x86_return_thunk" } } */
/* { dg-final { scan-assembler-not {\t(lfence|pause)} } } */
-/* { dg-final { scan-assembler-not "jmp\[ \t\]*\.LIND" } } */
-/* { dg-final { scan-assembler-not "call\[ \t\]*\.LIND" } } */
+/* { dg-final { scan-assembler-not {jmp[ \t]*\.?LIND} } } */
+/* { dg-final { scan-assembler-not {call[ \t]*\.?LIND} } } */
diff --git a/gcc/testsuite/gcc.target/i386/ret-thunk-5.c b/gcc/testsuite/gcc.target/i386/ret-thunk-5.c
index 4bd0d2a..862f21d 100644
--- a/gcc/testsuite/gcc.target/i386/ret-thunk-5.c
+++ b/gcc/testsuite/gcc.target/i386/ret-thunk-5.c
@@ -8,8 +8,8 @@ foo (void)
{
}
-/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_return_thunk" } } */
-/* { dg-final { scan-assembler "jmp\[ \t\]*\.LIND" } } */
-/* { dg-final { scan-assembler "call\[ \t\]*\.LIND" } } */
+/* { dg-final { scan-assembler "jmp\[ \t\]*_?__x86_return_thunk" } } */
+/* { dg-final { scan-assembler {jmp[ \t]*\.?LIND} } } */
+/* { dg-final { scan-assembler {call[ \t]*\.?LIND} } } */
/* { dg-final { scan-assembler {\tpause} } } */
/* { dg-final { scan-assembler {\tlfence} } } */
diff --git a/gcc/testsuite/gcc.target/i386/ret-thunk-6.c b/gcc/testsuite/gcc.target/i386/ret-thunk-6.c
index 053841f..9517c92 100644
--- a/gcc/testsuite/gcc.target/i386/ret-thunk-6.c
+++ b/gcc/testsuite/gcc.target/i386/ret-thunk-6.c
@@ -7,8 +7,8 @@ foo (void)
{
}
-/* { dg-final { scan-assembler "jmp\[ \t\]*\.LIND" } } */
-/* { dg-final { scan-assembler "call\[ \t\]*\.LIND" } } */
+/* { dg-final { scan-assembler {jmp[ \t]*\.?LIND} } } */
+/* { dg-final { scan-assembler {call[ \t]*\.?LIND} } } */
/* { dg-final { scan-assembler {\tpause} } } */
/* { dg-final { scan-assembler {\tlfence} } } */
-/* { dg-final { scan-assembler-not "jmp\[ \t\]*__x86_return_thunk" } } */
+/* { dg-final { scan-assembler-not "jmp\[ \t\]*_?__x86_return_thunk" } } */
diff --git a/gcc/testsuite/gcc.target/i386/ret-thunk-7.c b/gcc/testsuite/gcc.target/i386/ret-thunk-7.c
index 262e678..dd68f83 100644
--- a/gcc/testsuite/gcc.target/i386/ret-thunk-7.c
+++ b/gcc/testsuite/gcc.target/i386/ret-thunk-7.c
@@ -7,7 +7,7 @@ foo (void)
{
}
-/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_return_thunk" } } */
+/* { dg-final { scan-assembler "jmp\[ \t\]*_?__x86_return_thunk" } } */
/* { dg-final { scan-assembler-not {\t(lfence|pause)} } } */
-/* { dg-final { scan-assembler-not "jmp\[ \t\]*\.LIND" } } */
-/* { dg-final { scan-assembler-not "call\[ \t\]*\.LIND" } } */
+/* { dg-final { scan-assembler-not {jmp[ \t]*\.?LIND} } } */
+/* { dg-final { scan-assembler-not {call[ \t]*\.?LIND} } } */
diff --git a/gcc/testsuite/gcc.target/i386/ret-thunk-8.c b/gcc/testsuite/gcc.target/i386/ret-thunk-8.c
index c1658e9..0a611d9 100644
--- a/gcc/testsuite/gcc.target/i386/ret-thunk-8.c
+++ b/gcc/testsuite/gcc.target/i386/ret-thunk-8.c
@@ -8,7 +8,7 @@ foo (void)
{
}
-/* { dg-final { scan-assembler-not "jmp\[ \t\]*__x86_return_thunk" } } */
+/* { dg-final { scan-assembler-not "jmp\[ \t\]*_?__x86_return_thunk" } } */
/* { dg-final { scan-assembler-not {\t(lfence|pause)} } } */
-/* { dg-final { scan-assembler-not "jmp\[ \t\]*\.LIND" } } */
-/* { dg-final { scan-assembler-not "call\[ \t\]*\.LIND" } } */
+/* { dg-final { scan-assembler-not {jmp[ \t]*\.?LIND} } } */
+/* { dg-final { scan-assembler-not {call[ \t]*\.?LIND} } } */
diff --git a/gcc/testsuite/gcc.target/i386/ret-thunk-9.c b/gcc/testsuite/gcc.target/i386/ret-thunk-9.c
index 819671a..63af674 100644
--- a/gcc/testsuite/gcc.target/i386/ret-thunk-9.c
+++ b/gcc/testsuite/gcc.target/i386/ret-thunk-9.c
@@ -1,5 +1,6 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=thunk -mindirect-branch=thunk -fno-pic" } */
+/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=thunk -mindirect-branch=thunk " } */
+/* { dg-additional-options "-fno-pic" { target { ! *-*-darwin* } } } */
extern void (*bar) (void);
@@ -10,12 +11,14 @@ foo (void)
return 0;
}
-/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_return_thunk" } } */
-/* { dg-final { scan-assembler "jmp\[ \t\]*\.LIND" } } */
-/* { dg-final { scan-assembler "call\[ \t\]*\.LIND" } } */
-/* { dg-final { scan-assembler "__x86_return_thunk:" } } */
-/* { dg-final { scan-assembler "mov(?:l|q)\[ \t\]*_?bar" { target *-*-linux* } } } */
+/* { dg-final { scan-assembler "jmp\[ \t\]*_?__x86_return_thunk" } } */
+/* { dg-final { scan-assembler {jmp[ \t]+\.?LIND} } } */
+/* { dg-final { scan-assembler {call[ \t]+\.?LIND} } } */
+/* { dg-final { scan-assembler "_?__x86_return_thunk:" } } */
+/* { dg-final { scan-assembler "mov(?:l|q)\[ \t\]*bar" { target *-*-linux* } } } */
+/* { dg-final { scan-assembler {movq[ \t]*_bar} { target { lp64 && *-*-darwin* } } } } */
+/* { dg-final { scan-assembler {movl[ \t]*l_bar\$non_lazy_ptr-L[0-9]+\$pb} { target { ia32 && *-*-darwin* } } } } */
/* { dg-final { scan-assembler-times {\tpause} 2 } } */
/* { dg-final { scan-assembler-times {\tlfence} 2 } } */
-/* { dg-final { scan-assembler "call\[ \t\]*__x86_indirect_thunk_(r|e)ax" } } */
+/* { dg-final { scan-assembler "call\[ \t\]*_?__x86_indirect_thunk_(r|e)ax" } } */
/* { dg-final { scan-assembler-not "pushq\[ \t\]%rax" } } */
diff --git a/gcc/testsuite/gcc.target/i386/returninst1.c b/gcc/testsuite/gcc.target/i386/returninst1.c
index d7ecc41..133fdee 100644
--- a/gcc/testsuite/gcc.target/i386/returninst1.c
+++ b/gcc/testsuite/gcc.target/i386/returninst1.c
@@ -1,4 +1,5 @@
/* { dg-do compile { target { ! ia32 } } } */
+/* { dg-require-effective-target mfentry } */
/* { dg-options "-pg -mfentry -minstrument-return=call -mrecord-return" } */
/* { dg-final { scan-assembler "call.*__return__" } } */
/* { dg-final { scan-assembler "section.*return_loc" } } */
diff --git a/gcc/testsuite/gcc.target/i386/returninst2.c b/gcc/testsuite/gcc.target/i386/returninst2.c
index 4724b40..3629310 100644
--- a/gcc/testsuite/gcc.target/i386/returninst2.c
+++ b/gcc/testsuite/gcc.target/i386/returninst2.c
@@ -1,4 +1,5 @@
/* { dg-do compile { target { ! ia32 } } } */
+/* { dg-require-effective-target mfentry } */
/* { dg-options "-pg -mfentry -minstrument-return=nop5 -mrecord-return" } */
/* { dg-final { scan-assembler-times "0x0f, 0x1f, 0x44, 0x00, 0x00" 3 } } */
/* { dg-final { scan-assembler "section.*return_loc" } } */
diff --git a/gcc/testsuite/gcc.target/i386/returninst3.c b/gcc/testsuite/gcc.target/i386/returninst3.c
index 14b4445..b84cc77 100644
--- a/gcc/testsuite/gcc.target/i386/returninst3.c
+++ b/gcc/testsuite/gcc.target/i386/returninst3.c
@@ -1,4 +1,5 @@
/* { dg-do compile { target { ! ia32 } } } */
+/* { dg-require-effective-target mfentry } */
/* { dg-options "-pg -mfentry -minstrument-return=call" } */
/* { dg-final { scan-assembler-not "call.*__return__" } } */
diff --git a/gcc/testsuite/gcc.target/i386/spellcheck-options-5.c b/gcc/testsuite/gcc.target/i386/spellcheck-options-5.c
index 61946f6..f5b5d41 100644
--- a/gcc/testsuite/gcc.target/i386/spellcheck-options-5.c
+++ b/gcc/testsuite/gcc.target/i386/spellcheck-options-5.c
@@ -2,4 +2,4 @@
/* { dg-do compile { target *-*-linux* *-*-gnu* } } */
/* { dg-options "-mandroidX" } */
-/* { dg-error "unrecognized command line option '-mandroidX'; did you mean '-mandroid'" "" { target *-*-* } 0 } */
+/* { dg-error "unrecognized command-line option '-mandroidX'; did you mean '-mandroid'" "" { target *-*-* } 0 } */
diff --git a/gcc/testsuite/gcc.target/i386/sse-12.c b/gcc/testsuite/gcc.target/i386/sse-12.c
index 6066973..222675e 100644
--- a/gcc/testsuite/gcc.target/i386/sse-12.c
+++ b/gcc/testsuite/gcc.target/i386/sse-12.c
@@ -3,7 +3,7 @@
popcntintrin.h gfniintrin.h and mm_malloc.h are usable
with -O -std=c89 -pedantic-errors. */
/* { dg-do compile } */
-/* { dg-options "-O -std=c89 -pedantic-errors -march=k8 -msse4a -m3dnow -mavx -mavx2 -mfma4 -mxop -maes -mpclmul -mpopcnt -mabm -mlzcnt -mbmi -mbmi2 -mtbm -mlwp -mfsgsbase -mrdrnd -mf16c -mfma -mrtm -mrdseed -mprfchw -madx -mfxsr -mxsaveopt -mavx512f -mavx512er -mavx512cd -mavx512pf -msha -mprefetchwt1 -mxsavec -mxsaves -mclflushopt -mavx512bw -mavx512dq -mavx512vl -mavx512vbmi -mavx512ifma -mavx5124fmaps -mavx5124vnniw -mavx512vpopcntdq -mclwb -mmwaitx -mclzero -mpku -msgx -mrdpid -mgfni -mavx512bitalg -mpconfig -mwbnoinvd -mavx512bf16" } */
+/* { dg-options "-O -std=c89 -pedantic-errors -march=k8 -msse4a -m3dnow -mavx -mavx2 -mfma4 -mxop -maes -mpclmul -mpopcnt -mabm -mlzcnt -mbmi -mbmi2 -mtbm -mlwp -mfsgsbase -mrdrnd -mf16c -mfma -mrtm -mrdseed -mprfchw -madx -mfxsr -mxsaveopt -mavx512f -mavx512er -mavx512cd -mavx512pf -msha -mprefetchwt1 -mxsavec -mxsaves -mclflushopt -mavx512bw -mavx512dq -mavx512vl -mavx512vbmi -mavx512ifma -mavx5124fmaps -mavx5124vnniw -mavx512vpopcntdq -mclwb -mmwaitx -mclzero -mpku -msgx -mrdpid -mgfni -mavx512bitalg -mpconfig -mwbnoinvd -mavx512bf16 -menqcmd -mavx512vp2intersect" } */
#include <x86intrin.h>
diff --git a/gcc/testsuite/gcc.target/i386/sse-13.c b/gcc/testsuite/gcc.target/i386/sse-13.c
index 2b48c455..39b2d31 100644
--- a/gcc/testsuite/gcc.target/i386/sse-13.c
+++ b/gcc/testsuite/gcc.target/i386/sse-13.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -Werror-implicit-function-declaration -march=k8 -msse4a -m3dnow -mavx -mavx2 -mfma4 -mxop -maes -mpclmul -mpopcnt -mabm -mlzcnt -mbmi -mbmi2 -mtbm -mlwp -mfsgsbase -mrdrnd -mf16c -mfma -mrtm -mrdseed -mprfchw -madx -mfxsr -mxsaveopt -mavx512f -mavx512er -mavx512cd -mavx512pf -msha -mprefetchwt1 -mxsavec -mxsaves -mclflushopt -mavx512vl -mavx512dq -mavx512bw -mavx512vbmi -mavx512ifma -mavx5124fmaps -mavx5124vnniw -mavx512vpopcntdq -mclwb -mmwaitx -mclzero -mpku -msgx -mrdpid -mgfni -mavx512bitalg -mpconfig -mwbnoinvd -mavx512bf16" } */
+/* { dg-options "-O2 -Werror-implicit-function-declaration -march=k8 -msse4a -m3dnow -mavx -mavx2 -mfma4 -mxop -maes -mpclmul -mpopcnt -mabm -mlzcnt -mbmi -mbmi2 -mtbm -mlwp -mfsgsbase -mrdrnd -mf16c -mfma -mrtm -mrdseed -mprfchw -madx -mfxsr -mxsaveopt -mavx512f -mavx512er -mavx512cd -mavx512pf -msha -mprefetchwt1 -mxsavec -mxsaves -mclflushopt -mavx512vl -mavx512dq -mavx512bw -mavx512vbmi -mavx512ifma -mavx5124fmaps -mavx5124vnniw -mavx512vpopcntdq -mavx512vp2intersect -mclwb -mmwaitx -mclzero -mpku -msgx -mrdpid -mgfni -mavx512bitalg -mpconfig -mwbnoinvd -mavx512bf16 -menqcmd" } */
/* { dg-add-options bind_pic_locally } */
#include <mm_malloc.h>
@@ -461,8 +461,8 @@
#define __builtin_ia32_inserti32x8_mask(A, B, F, D, E) __builtin_ia32_inserti32x8_mask(A, B, 1, D, E)
#define __builtin_ia32_insertf64x2_512_mask(A, B, F, D, E) __builtin_ia32_insertf64x2_512_mask(A, B, 1, D, E)
#define __builtin_ia32_insertf32x8_mask(A, B, F, D, E) __builtin_ia32_insertf32x8_mask(A, B, 1, D, E)
-#define __builtin_ia32_fpclassss(A, D) __builtin_ia32_fpclassss(A, 1)
-#define __builtin_ia32_fpclasssd(A, D) __builtin_ia32_fpclasssd(A, 1)
+#define __builtin_ia32_fpclassss_mask(A, D, U) __builtin_ia32_fpclassss_mask(A, 1, U)
+#define __builtin_ia32_fpclasssd_mask(A, D, U) __builtin_ia32_fpclasssd_mask(A, 1, U)
#define __builtin_ia32_fpclassps512_mask(A, D, C) __builtin_ia32_fpclassps512_mask(A, 1, C)
#define __builtin_ia32_fpclasspd512_mask(A, D, C) __builtin_ia32_fpclasspd512_mask(A, 1, C)
#define __builtin_ia32_extracti64x2_512_mask(A, E, C, D) __builtin_ia32_extracti64x2_512_mask(A, 1, C, D)
diff --git a/gcc/testsuite/gcc.target/i386/sse-14.c b/gcc/testsuite/gcc.target/i386/sse-14.c
index ae7d3d5..8795109 100644
--- a/gcc/testsuite/gcc.target/i386/sse-14.c
+++ b/gcc/testsuite/gcc.target/i386/sse-14.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O0 -Werror-implicit-function-declaration -march=k8 -msse4a -m3dnow -mavx -mavx2 -mfma4 -mxop -maes -mpclmul -mpopcnt -mabm -mlzcnt -mbmi -mbmi2 -mtbm -mlwp -mfsgsbase -mrdrnd -mf16c -mfma -mrtm -mrdseed -mprfchw -madx -mfxsr -mxsaveopt -mavx512f -mavx512er -mavx512cd -mavx512pf -msha -mprefetchwt1 -mxsavec -mxsaves -mclflushopt -mavx512dq -mavx512bw -mavx512vl -mavx512ifma -mavx512vbmi -mavx5124fmaps -mavx5124vnniw -mavx512vpopcntdq -mclwb -mmwaitx -mclzero -mpku -msgx -mrdpid -mgfni -mpconfig -mwbnoinvd -mavx512vl -mavx512bf16" } */
+/* { dg-options "-O0 -Werror-implicit-function-declaration -march=k8 -msse4a -m3dnow -mavx -mavx2 -mfma4 -mxop -maes -mpclmul -mpopcnt -mabm -mlzcnt -mbmi -mbmi2 -mtbm -mlwp -mfsgsbase -mrdrnd -mf16c -mfma -mrtm -mrdseed -mprfchw -madx -mfxsr -mxsaveopt -mavx512f -mavx512er -mavx512cd -mavx512pf -msha -mprefetchwt1 -mxsavec -mxsaves -mclflushopt -mavx512dq -mavx512bw -mavx512vl -mavx512ifma -mavx512vbmi -mavx5124fmaps -mavx5124vnniw -mavx512vpopcntdq -mclwb -mmwaitx -mclzero -mpku -msgx -mrdpid -mgfni -mpconfig -mwbnoinvd -mavx512vl -mavx512bf16 -menqcmd -mavx512vp2intersect" } */
/* { dg-add-options bind_pic_locally } */
#include <mm_malloc.h>
diff --git a/gcc/testsuite/gcc.target/i386/sse-22.c b/gcc/testsuite/gcc.target/i386/sse-22.c
index 733c670..1c786bb 100644
--- a/gcc/testsuite/gcc.target/i386/sse-22.c
+++ b/gcc/testsuite/gcc.target/i386/sse-22.c
@@ -10,8 +10,9 @@
mm3dnow.h, fma4intrin.h, xopintrin.h, abmintrin.h, bmiintrin.h,
tbmintrin.h, lwpintrin.h, popcntintrin.h, fmaintrin.h,
avx5124fmapsintrin.h, avx5124vnniwintrin.h, avx512vpopcntdqintrin.h,
- avx512bitalgintrin.h and mm_malloc.h that reference the proper builtin
- functions.
+ avx512bitalgintrin.h, avx512vp2intersectintrin.h,
+ avx512vp2intersectvlintrin.h and mm_malloc.h that reference the proper
+ builtin functions.
Defining away "extern" and "__inline" results in all of them being
compiled as proper functions. */
@@ -101,7 +102,7 @@
#ifndef DIFFERENT_PRAGMAS
-#pragma GCC target ("sse4a,3dnow,avx,avx2,fma4,xop,aes,pclmul,popcnt,abm,lzcnt,bmi,bmi2,tbm,lwp,fsgsbase,rdrnd,f16c,rtm,rdseed,prfchw,adx,fxsr,xsaveopt,avx512f,avx512er,avx512cd,avx512pf,sha,prefetchwt1,avx512vl,avx512bw,avx512dq,avx512vbmi,avx512ifma,avx5124fmaps,avx5124vnniw,avx512vpopcntdq,gfni,avx512bitalg,avx512bf16")
+#pragma GCC target ("sse4a,3dnow,avx,avx2,fma4,xop,aes,pclmul,popcnt,abm,lzcnt,bmi,bmi2,tbm,lwp,fsgsbase,rdrnd,f16c,rtm,rdseed,prfchw,adx,fxsr,xsaveopt,avx512f,avx512er,avx512cd,avx512pf,sha,prefetchwt1,avx512vl,avx512bw,avx512dq,avx512vbmi,avx512ifma,avx5124fmaps,avx5124vnniw,avx512vpopcntdq,gfni,avx512bitalg,avx512bf16,avx512vp2intersect")
#endif
/* Following intrinsics require immediate arguments. They
@@ -218,7 +219,7 @@ test_4 (_mm_cmpestrz, int, __m128i, int, __m128i, int, 1)
/* immintrin.h (AVX/AVX2/RDRND/FSGSBASE/F16C/RTM/AVX512F/SHA) */
#ifdef DIFFERENT_PRAGMAS
-#pragma GCC target ("avx,avx2,rdrnd,fsgsbase,f16c,rtm,avx512f,avx512er,avx512cd,avx512pf,sha,avx512vl,avx512bw,avx512dq,avx512ifma,avx512vbmi,avx5124fmaps,avx5124vnniw,avx512vpopcntdq,gfni,avx512bitalg,avx512bf16")
+#pragma GCC target ("avx,avx2,rdrnd,fsgsbase,f16c,rtm,avx512f,avx512er,avx512cd,avx512pf,sha,avx512vl,avx512bw,avx512dq,avx512ifma,avx512vbmi,avx5124fmaps,avx5124vnniw,avx512vpopcntdq,gfni,avx512bitalg,avx512bf16,avx512vp2intersect")
#endif
#include <immintrin.h>
test_1 (_cvtss_sh, unsigned short, float, 1)
diff --git a/gcc/testsuite/gcc.target/i386/sse-23.c b/gcc/testsuite/gcc.target/i386/sse-23.c
index 58f4c82..7ea665d 100644
--- a/gcc/testsuite/gcc.target/i386/sse-23.c
+++ b/gcc/testsuite/gcc.target/i386/sse-23.c
@@ -9,8 +9,9 @@
mm3dnow.h, fma4intrin.h, xopintrin.h, abmintrin.h, bmiintrin.h,
tbmintrin.h, lwpintrin.h, popcntintrin.h, fmaintrin.h,
avx5124fmapsintrin.h, avx5124vnniwintrin.h, avx512vpopcntdqintrin.h,
- avx512bitalgintrin.h and mm_malloc.h that reference the proper builtin
- functions.
+ avx512bitalgintrin.h, avx512vp2intersectintrin.h,
+ avx512vp2intersectvlintrin.h and mm_malloc.h that reference the proper
+ builtin functions.
Defining away "extern" and "__inline" results in all of them being
compiled as proper functions. */
@@ -460,8 +461,8 @@
#define __builtin_ia32_inserti32x8_mask(A, B, F, D, E) __builtin_ia32_inserti32x8_mask(A, B, 1, D, E)
#define __builtin_ia32_insertf64x2_512_mask(A, B, F, D, E) __builtin_ia32_insertf64x2_512_mask(A, B, 1, D, E)
#define __builtin_ia32_insertf32x8_mask(A, B, F, D, E) __builtin_ia32_insertf32x8_mask(A, B, 1, D, E)
-#define __builtin_ia32_fpclassss(A, D) __builtin_ia32_fpclassss(A, 1)
-#define __builtin_ia32_fpclasssd(A, D) __builtin_ia32_fpclasssd(A, 1)
+#define __builtin_ia32_fpclassss_mask(A, D, U) __builtin_ia32_fpclassss_mask(A, 1, U)
+#define __builtin_ia32_fpclasssd_mask(A, D, U) __builtin_ia32_fpclasssd_mask(A, 1, U)
#define __builtin_ia32_fpclassps512_mask(A, D, C) __builtin_ia32_fpclassps512_mask(A, 1, C)
#define __builtin_ia32_fpclasspd512_mask(A, D, C) __builtin_ia32_fpclasspd512_mask(A, 1, C)
#define __builtin_ia32_extracti64x2_512_mask(A, E, C, D) __builtin_ia32_extracti64x2_512_mask(A, 1, C, D)
@@ -696,6 +697,6 @@
#define __builtin_ia32_vpclmulqdq_v2di(A, B, C) __builtin_ia32_vpclmulqdq_v2di(A, B, 1)
#define __builtin_ia32_vpclmulqdq_v8di(A, B, C) __builtin_ia32_vpclmulqdq_v8di(A, B, 1)
-#pragma GCC target ("sse4a,3dnow,avx,avx2,fma4,xop,aes,pclmul,popcnt,abm,lzcnt,bmi,bmi2,tbm,lwp,fsgsbase,rdrnd,f16c,fma,rtm,rdseed,prfchw,adx,fxsr,xsaveopt,avx512f,avx512er,avx512cd,avx512pf,sha,prefetchwt1,xsavec,xsaves,clflushopt,avx512bw,avx512dq,avx512vl,avx512vbmi,avx512ifma,avx5124fmaps,avx5124vnniw,avx512vpopcntdq,clwb,mwaitx,clzero,pku,sgx,rdpid,gfni,avx512vbmi2,vpclmulqdq,avx512bitalg,pconfig,wbnoinvd,avx512bf16")
+#pragma GCC target ("sse4a,3dnow,avx,avx2,fma4,xop,aes,pclmul,popcnt,abm,lzcnt,bmi,bmi2,tbm,lwp,fsgsbase,rdrnd,f16c,fma,rtm,rdseed,prfchw,adx,fxsr,xsaveopt,avx512f,avx512er,avx512cd,avx512pf,sha,prefetchwt1,xsavec,xsaves,clflushopt,avx512bw,avx512dq,avx512vl,avx512vbmi,avx512ifma,avx5124fmaps,avx5124vnniw,avx512vpopcntdq,clwb,mwaitx,clzero,pku,sgx,rdpid,gfni,avx512vbmi2,vpclmulqdq,avx512bitalg,pconfig,wbnoinvd,avx512bf16,enqcmd,avx512vp2intersect")
#include <x86intrin.h>
diff --git a/gcc/testsuite/gcc.target/i386/sse2-mmx-10.c b/gcc/testsuite/gcc.target/i386/sse2-mmx-10.c
new file mode 100644
index 0000000..4da7ed3
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/sse2-mmx-10.c
@@ -0,0 +1,43 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -fno-strict-aliasing -msse2" } */
+/* { dg-additional-options "-mno-mmx" { target { ! ia32 } } } */
+
+#include "sse2-check.h"
+#include "mmx-vals.h"
+
+__attribute__((noinline, noclone))
+static void
+test_from_int (long long *ll1, long long *r)
+{
+ int i1 = *(int *) ll1;
+ *(__m64 *) r = _m_from_int (i1);
+}
+
+/* Routine to manually compute the results */
+static void
+compute_correct_result (long long *ll1, long long *r)
+{
+ int *res = (int *) r;
+ res[0] = *(int *) ll1;
+ res[1] = 0;
+}
+
+static void
+sse2_test (void)
+{
+ int i;
+ long long r, ck;
+ int fail = 0;
+
+ /* Run the MMX tests */
+ for (i = 0; i < MMX_num_ops; i++)
+ {
+ test_from_int (&MMXops[i], &r);
+ compute_correct_result (&MMXops[i], &ck);
+ if (ck != r)
+ fail++;
+ }
+
+ if (fail != 0)
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.target/i386/sse2-mmx-11.c b/gcc/testsuite/gcc.target/i386/sse2-mmx-11.c
new file mode 100644
index 0000000..6737ec5
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/sse2-mmx-11.c
@@ -0,0 +1,39 @@
+/* { dg-do run { target { ! ia32 } } } */
+/* { dg-options "-O2 -fno-strict-aliasing -msse2 -mno-mmx" } */
+
+#include "sse2-check.h"
+#include "mmx-vals.h"
+
+__attribute__((noinline, noclone))
+static void
+test_from_long_long (long long *ll1, long long *r)
+{
+ *(__m64 *) r = _mm_cvtsi64_m64 (*ll1);
+}
+
+/* Routine to manually compute the results */
+static void
+compute_correct_result (long long *ll1, long long *r)
+{
+ *r = *ll1;
+}
+
+static void
+sse2_test (void)
+{
+ int i;
+ long long r, ck;
+ int fail = 0;
+
+ /* Run the MMX tests */
+ for (i = 0; i < MMX_num_ops; i++)
+ {
+ test_from_long_long (&MMXops[i], &r);
+ compute_correct_result (&MMXops[i], &ck);
+ if (ck != r)
+ fail++;
+ }
+
+ if (fail != 0)
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.target/i386/sse2-mmx-12.c b/gcc/testsuite/gcc.target/i386/sse2-mmx-12.c
new file mode 100644
index 0000000..b626daa
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/sse2-mmx-12.c
@@ -0,0 +1,42 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -fno-strict-aliasing -msse2" } */
+/* { dg-additional-options "-mno-mmx" { target { ! ia32 } } } */
+
+#include "sse2-check.h"
+#include "mmx-vals.h"
+
+__attribute__((noinline, noclone))
+static void
+test_to_int (long long *ll1, long long *r)
+{
+ __m64 m = *(__m64 *) ll1;
+ *(int *) r = _m_to_int (m);
+}
+
+/* Routine to manually compute the results */
+static void
+compute_correct_result (long long *ll1, long long *r)
+{
+ int *i1 = (int *) ll1;
+ *(int *) r = *i1;
+}
+
+static void
+sse2_test (void)
+{
+ int i;
+ long long r = 0, ck = 0;
+ int fail = 0;
+
+ /* Run the MMX tests */
+ for (i = 0; i < MMX_num_ops; i++)
+ {
+ test_to_int (&MMXops[i], &r);
+ compute_correct_result (&MMXops[i], &ck);
+ if (ck != r)
+ fail++;
+ }
+
+ if (fail != 0)
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.target/i386/sse2-mmx-13.c b/gcc/testsuite/gcc.target/i386/sse2-mmx-13.c
new file mode 100644
index 0000000..fd1eed6
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/sse2-mmx-13.c
@@ -0,0 +1,40 @@
+/* { dg-do run { target { ! ia32 } } } */
+/* { dg-options "-O2 -fno-strict-aliasing -msse2 -mno-mmx" } */
+
+#include "sse2-check.h"
+#include "mmx-vals.h"
+
+__attribute__((noinline, noclone))
+static void
+test_to_long_long (long long *ll1, long long *r)
+{
+ __m64 m = *(__m64 *) ll1;
+ *r = _mm_cvtm64_si64 (m);
+}
+
+/* Routine to manually compute the results */
+static void
+compute_correct_result (long long *ll1, long long *r)
+{
+ *r = *ll1;
+}
+
+static void
+sse2_test (void)
+{
+ int i;
+ long long r, ck;
+ int fail = 0;
+
+ /* Run the MMX tests */
+ for (i = 0; i < MMX_num_ops; i++)
+ {
+ test_to_long_long (&MMXops[i], &r);
+ compute_correct_result (&MMXops[i], &ck);
+ if (ck != r)
+ fail++;
+ }
+
+ if (fail != 0)
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.target/i386/sse2-mmx-14.c b/gcc/testsuite/gcc.target/i386/sse2-mmx-14.c
new file mode 100644
index 0000000..bc21ba7
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/sse2-mmx-14.c
@@ -0,0 +1,31 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -fno-strict-aliasing -msse2" } */
+/* { dg-additional-options "-mno-mmx" { target { ! ia32 } } } */
+
+#include "sse2-check.h"
+
+__attribute__((noinline, noclone))
+static void
+test_setzero (long long *r)
+{
+ *(__m64 *) r = _mm_setzero_si64 ();
+}
+
+/* Routine to manually compute the results */
+static void
+compute_correct_result (long long *r)
+{
+ *r = 0x0LL;
+}
+
+static void
+sse2_test (void)
+{
+ long long r, ck;
+
+ /* Run the MMX tests */
+ test_setzero (&r);
+ compute_correct_result (&ck);
+ if (ck != r)
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.target/i386/sse2-mmx-15.c b/gcc/testsuite/gcc.target/i386/sse2-mmx-15.c
new file mode 100644
index 0000000..ab8451b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/sse2-mmx-15.c
@@ -0,0 +1,36 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -fno-strict-aliasing -msse2" } */
+/* { dg-additional-options "-mno-mmx" { target { ! ia32 } } } */
+
+#include "sse2-check.h"
+
+__attribute__((noinline, noclone))
+static void
+test_set (int x, int y, long long *r)
+{
+ *(__m64 *) r = _mm_set_pi32 (x, y);
+}
+
+/* Routine to manually compute the results */
+static void
+compute_correct_result (int x, int y, long long *res_p)
+{
+ int *res = (int *) res_p;
+ res[0] = y;
+ res[1] = x;
+}
+
+static void
+sse2_test (void)
+{
+ int x, y;
+ long long r, ck;
+
+ /* Run the MMX tests */
+ x = 0x0badbeef;
+ y = 0x0badfeed;
+ test_set (x, y, &r);
+ compute_correct_result (x, y, &ck);
+ if (ck != r)
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.target/i386/sse2-mmx-16.c b/gcc/testsuite/gcc.target/i386/sse2-mmx-16.c
new file mode 100644
index 0000000..b348b9f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/sse2-mmx-16.c
@@ -0,0 +1,40 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -fno-strict-aliasing -msse2" } */
+/* { dg-additional-options "-mno-mmx" { target { ! ia32 } } } */
+
+#include "sse2-check.h"
+
+__attribute__((noinline, noclone))
+static void
+test_set (int i0, int i1, int i2, int i3, long long *r)
+{
+ *(__m64 *) r = _mm_set_pi16 (i0, i1, i2, i3);
+}
+
+/* Routine to manually compute the results */
+static void
+compute_correct_result (int i0, int i1, int i2, int i3, long long *res_p)
+{
+ short *res = (short *) res_p;
+ res[0] = i3;
+ res[1] = i2;
+ res[2] = i1;
+ res[3] = i0;
+}
+
+static void
+sse2_test (void)
+{
+ short i0, i1, i2, i3;
+ long long r, ck;
+
+ /* Run the MMX tests */
+ i0 = 0x0bad;
+ i1 = 0xbeef;
+ i2 = 0x0bad;
+ i3 = 0xfeed;
+ test_set (i0, i1, i2, i3, &r);
+ compute_correct_result (i0, i1, i2, i3, &ck);
+ if (ck != r)
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.target/i386/sse2-mmx-17.c b/gcc/testsuite/gcc.target/i386/sse2-mmx-17.c
new file mode 100644
index 0000000..756cbeb
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/sse2-mmx-17.c
@@ -0,0 +1,51 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -fno-strict-aliasing -msse2" } */
+/* { dg-additional-options "-mno-mmx" { target { ! ia32 } } } */
+
+#include "sse2-check.h"
+
+__attribute__((noinline, noclone))
+static void
+test_set (char i0, char i1, char i2, char i3,
+ char i4, char i5, char i6, char i7, long long *r)
+{
+ *(__m64 *) r = _mm_set_pi8 (i0, i1, i2, i3, i4, i5, i6, i7);
+}
+
+/* Routine to manually compute the results */
+static void
+compute_correct_result (char i0, char i1, char i2, char i3,
+ char i4, char i5, char i6, char i7,
+ long long *res_p)
+{
+ char *res = (char *) res_p;
+ res[0] = i7;
+ res[1] = i6;
+ res[2] = i5;
+ res[3] = i4;
+ res[4] = i3;
+ res[5] = i2;
+ res[6] = i1;
+ res[7] = i0;
+}
+
+static void
+sse2_test (void)
+{
+ char i0, i1, i2, i3, i4, i5, i6, i7;
+ long long r, ck;
+
+ /* Run the MMX tests */
+ i0 = 0x12;
+ i1 = 0x34;
+ i2 = 0x56;
+ i3 = 0x78;
+ i4 = 0x90;
+ i5 = 0xab;
+ i6 = 0xcd;
+ i7 = 0xef;
+ test_set (i0, i1, i2, i3, i4, i5, i6, i7, &r);
+ compute_correct_result (i0, i1, i2, i3, i4, i5, i6, i7, &ck);
+ if (ck != r)
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.target/i386/sse2-mmx-18a.c b/gcc/testsuite/gcc.target/i386/sse2-mmx-18a.c
new file mode 100644
index 0000000..3505a5c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/sse2-mmx-18a.c
@@ -0,0 +1,14 @@
+/* { dg-do compile { target { ! ia32 } } } */
+/* { dg-options "-O2 -msse2 -mno-mmx -mno-avx512vl" } */
+/* { dg-final { scan-assembler-times "pshufd" 1 } } */
+/* { dg-final { scan-assembler-times "movd" 1 } } */
+/* { dg-final { scan-assembler-not "movl" } } */
+
+#include <mmintrin.h>
+
+__m64
+foo (int i)
+{
+ __v2si x = { i, i };
+ return (__m64) x;
+}
diff --git a/gcc/testsuite/gcc.target/i386/sse2-mmx-18b.c b/gcc/testsuite/gcc.target/i386/sse2-mmx-18b.c
new file mode 100644
index 0000000..9b267b1
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/sse2-mmx-18b.c
@@ -0,0 +1,7 @@
+/* { dg-do compile { target { ! ia32 } } } */
+/* { dg-options "-O2 -mno-mmx -mavx512bw -mavx512vl" } */
+/* { dg-final { scan-assembler-times "pbroadcastd" 1 } } */
+/* { dg-final { scan-assembler-not "movd" } } */
+/* { dg-final { scan-assembler-not "movl" } } */
+
+#include "sse2-mmx-18a.c"
diff --git a/gcc/testsuite/gcc.target/i386/sse2-mmx-18c.c b/gcc/testsuite/gcc.target/i386/sse2-mmx-18c.c
new file mode 100644
index 0000000..394f05b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/sse2-mmx-18c.c
@@ -0,0 +1,7 @@
+/* { dg-do compile { target { ! ia32 } } } */
+/* { dg-options "-O2 -mno-mmx -mavx512bw -mno-avx512vl" } */
+/* { dg-final { scan-assembler-times "pshufd" 1 } } */
+/* { dg-final { scan-assembler-times "movd" 1 } } */
+/* { dg-final { scan-assembler-not "movl" } } */
+
+#include "sse2-mmx-18a.c"
diff --git a/gcc/testsuite/gcc.target/i386/sse2-mmx-19a.c b/gcc/testsuite/gcc.target/i386/sse2-mmx-19a.c
new file mode 100644
index 0000000..9715ace
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/sse2-mmx-19a.c
@@ -0,0 +1,14 @@
+/* { dg-do compile { target { ! ia32 } } } */
+/* { dg-options "-O2 -msse2 -mno-mmx -mno-avx -mtune=intel" } */
+/* { dg-final { scan-assembler-times "pshuflw" 1 } } */
+/* { dg-final { scan-assembler-times "movd" 1 } } */
+/* { dg-final { scan-assembler-not "movl" } } */
+
+#include <mmintrin.h>
+
+__m64
+foo (short i)
+{
+ __v4hi x = { i, i, i, i };
+ return (__m64) x;
+}
diff --git a/gcc/testsuite/gcc.target/i386/sse2-mmx-19b.c b/gcc/testsuite/gcc.target/i386/sse2-mmx-19b.c
new file mode 100644
index 0000000..a6d4231
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/sse2-mmx-19b.c
@@ -0,0 +1,7 @@
+/* { dg-do compile { target { ! ia32 } } } */
+/* { dg-options "-O2 -mno-mmx -mavx512bw -mavx512vl" } */
+/* { dg-final { scan-assembler-times "pbroadcastw" 1 } } */
+/* { dg-final { scan-assembler-not "movd" } } */
+/* { dg-final { scan-assembler-not "movl" } } */
+
+#include "sse2-mmx-19a.c"
diff --git a/gcc/testsuite/gcc.target/i386/sse2-mmx-19c.c b/gcc/testsuite/gcc.target/i386/sse2-mmx-19c.c
new file mode 100644
index 0000000..b02dc8c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/sse2-mmx-19c.c
@@ -0,0 +1,7 @@
+/* { dg-do compile { target { ! ia32 } } } */
+/* { dg-options "-O2 -mno-mmx -mavx -mno-avx2 -mtune=intel" } */
+/* { dg-final { scan-assembler-times "pshuflw" 1 } } */
+/* { dg-final { scan-assembler-times "movd" 1 } } */
+/* { dg-final { scan-assembler-not "movl" } } */
+
+#include "sse2-mmx-19a.c"
diff --git a/gcc/testsuite/gcc.target/i386/sse2-mmx-19d.c b/gcc/testsuite/gcc.target/i386/sse2-mmx-19d.c
new file mode 100644
index 0000000..5469188
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/sse2-mmx-19d.c
@@ -0,0 +1,7 @@
+/* { dg-do compile { target { ! ia32 } } } */
+/* { dg-options "-O2 -mno-mmx -mavx512bw -mno-avx512vl -mtune=intel" } */
+/* { dg-final { scan-assembler-times "pbroadcastw" 1 } } */
+/* { dg-final { scan-assembler-times "movd" 1 } } */
+/* { dg-final { scan-assembler-not "movl" } } */
+
+#include "sse2-mmx-19a.c"
diff --git a/gcc/testsuite/gcc.target/i386/sse2-mmx-19e.c b/gcc/testsuite/gcc.target/i386/sse2-mmx-19e.c
new file mode 100644
index 0000000..8be973c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/sse2-mmx-19e.c
@@ -0,0 +1,7 @@
+/* { dg-do compile { target { ! ia32 } } } */
+/* { dg-options "-O2 -mno-mmx -mavx2 -mno-avx512f -mtune=intel" } */
+/* { dg-final { scan-assembler-times "pbroadcastw" 1 } } */
+/* { dg-final { scan-assembler-times "movd" 1 } } */
+/* { dg-final { scan-assembler-not "movl" } } */
+
+#include "sse2-mmx-19a.c"
diff --git a/gcc/testsuite/gcc.target/i386/sse2-mmx-2.c b/gcc/testsuite/gcc.target/i386/sse2-mmx-2.c
new file mode 100644
index 0000000..e4cee2d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/sse2-mmx-2.c
@@ -0,0 +1,12 @@
+/* { dg-do compile { target { ! ia32 } } } */
+/* { dg-options "-O2 -msse2 -mno-mmx" } */
+/* { dg-final { scan-assembler-not "%xmm" } } */
+/* { dg-final { scan-assembler-not "%mm" } } */
+
+#include <mmintrin.h>
+
+float
+foo (__m64 x)
+{
+ return ((__v2sf) x)[0];
+}
diff --git a/gcc/testsuite/gcc.target/i386/sse2-mmx-20.c b/gcc/testsuite/gcc.target/i386/sse2-mmx-20.c
new file mode 100644
index 0000000..173fa15
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/sse2-mmx-20.c
@@ -0,0 +1,12 @@
+/* { dg-do compile { target { ! ia32 } } } */
+/* { dg-options "-O2 -msse2 -mno-mmx" } */
+/* { dg-final { scan-assembler-times "movd" 1 } } */
+/* { dg-final { scan-assembler-not "%mm" } } */
+
+#include <mmintrin.h>
+
+int
+foo (__m64 x)
+{
+ return ((__v2si) x)[0];
+}
diff --git a/gcc/testsuite/gcc.target/i386/sse2-mmx-21.c b/gcc/testsuite/gcc.target/i386/sse2-mmx-21.c
new file mode 100644
index 0000000..8f5341e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/sse2-mmx-21.c
@@ -0,0 +1,13 @@
+/* { dg-do compile { target { ! ia32 } } } */
+/* { dg-options "-O2 -msse2 -mno-mmx" } */
+/* { dg-final { scan-assembler-times "pshufd" 1 } } */
+/* { dg-final { scan-assembler-times "movd" 1 } } */
+/* { dg-final { scan-assembler-not "%mm" } } */
+
+#include <mmintrin.h>
+
+int
+foo (__m64 x)
+{
+ return ((__v2si) x)[1];
+}
diff --git a/gcc/testsuite/gcc.target/i386/sse2-mmx-22.c b/gcc/testsuite/gcc.target/i386/sse2-mmx-22.c
new file mode 100644
index 0000000..94fa587
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/sse2-mmx-22.c
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -msse2" } */
+/* { dg-additional-options "-mno-mmx" { target { ! ia32 } } } */
+
+#include <mmintrin.h>
+
+void
+foo (void)
+{
+ _mm_empty ();
+}
+
+/* { dg-final { scan-assembler-times "emms" 1 { target ia32 } } } */
+/* { dg-final { scan-assembler-not "emms" { target { ! ia32 } } } } */
diff --git a/gcc/testsuite/gcc.target/i386/sse2-mmx-3.c b/gcc/testsuite/gcc.target/i386/sse2-mmx-3.c
new file mode 100644
index 0000000..77f518b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/sse2-mmx-3.c
@@ -0,0 +1,13 @@
+/* { dg-do compile { target { ! ia32 } } } */
+/* { dg-options "-O2 -msse2 -mno-mmx" } */
+/* { dg-final { scan-assembler "cvtdq2ps" } } */
+/* { dg-final { scan-assembler-not "cvtpi2ps" } } */
+/* { dg-final { scan-assembler-not "%mm" } } */
+
+#include <xmmintrin.h>
+
+__m128
+foo (__m128 i1, __m64 i2)
+{
+ return _mm_cvtpi32_ps (i1, i2);
+}
diff --git a/gcc/testsuite/gcc.target/i386/sse2-mmx-4.c b/gcc/testsuite/gcc.target/i386/sse2-mmx-4.c
new file mode 100644
index 0000000..d923724
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/sse2-mmx-4.c
@@ -0,0 +1,4 @@
+/* { dg-do run { target { ! ia32 } } } */
+/* { dg-options "-O2 -msse2 -mno-mmx" } */
+
+#include "mmx-4.c"
diff --git a/gcc/testsuite/gcc.target/i386/sse2-mmx-5.c b/gcc/testsuite/gcc.target/i386/sse2-mmx-5.c
new file mode 100644
index 0000000..1953dc8
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/sse2-mmx-5.c
@@ -0,0 +1,11 @@
+/* { dg-do compile { target { ! ia32 } } } */
+/* { dg-options "-O2 -msse2 -mno-mmx" } */
+/* { dg-final { scan-assembler-not "%mm" } } */
+
+#include <xmmintrin.h>
+
+int
+foo (__m64 i)
+{
+ return _m_pextrw (i, 2);
+}
diff --git a/gcc/testsuite/gcc.target/i386/sse2-mmx-6.c b/gcc/testsuite/gcc.target/i386/sse2-mmx-6.c
new file mode 100644
index 0000000..f73444f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/sse2-mmx-6.c
@@ -0,0 +1,11 @@
+/* { dg-do compile { target { ! ia32 } } } */
+/* { dg-options "-O2 -msse2 -mno-mmx" } */
+/* { dg-final { scan-assembler-not "%mm" } } */
+
+#include <xmmintrin.h>
+
+__m64
+foo (__m64 i, int w)
+{
+ return _m_pinsrw (i, w, 2);
+}
diff --git a/gcc/testsuite/gcc.target/i386/sse2-mmx-7.c b/gcc/testsuite/gcc.target/i386/sse2-mmx-7.c
new file mode 100644
index 0000000..6ea491d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/sse2-mmx-7.c
@@ -0,0 +1,13 @@
+/* { dg-do compile { target { ! ia32 } } } */
+/* { dg-options "-O2 -msse2 -mno-mmx" } */
+/* { dg-final { scan-assembler "movnti" } } */
+/* { dg-final { scan-assembler-not "movntq" } } */
+/* { dg-final { scan-assembler-not "%mm" } } */
+
+#include <xmmintrin.h>
+
+void
+foo (__m64 *p, __m64 i)
+{
+ _mm_stream_pi (p, i);
+}
diff --git a/gcc/testsuite/gcc.target/i386/sse2-mmx-8.c b/gcc/testsuite/gcc.target/i386/sse2-mmx-8.c
new file mode 100644
index 0000000..342c2fa
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/sse2-mmx-8.c
@@ -0,0 +1,4 @@
+/* { dg-do run { target { ! ia32 } } } */
+/* { dg-options "-O2 -msse2 -mno-mmx" } */
+
+#include "mmx-8.c"
diff --git a/gcc/testsuite/gcc.target/i386/sse2-mmx-9.c b/gcc/testsuite/gcc.target/i386/sse2-mmx-9.c
new file mode 100644
index 0000000..f0bf725
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/sse2-mmx-9.c
@@ -0,0 +1,79 @@
+/* { dg-do run { target { ! ia32 } } } */
+/* { dg-options "-O2 -msse2 -mno-mmx" } */
+/* { dg-require-effective-target sse2 } */
+
+#include "sse2-check.h"
+
+#include <string.h>
+
+#define FLOAT_X 2.3456
+#define FLOAT_Y -4.5987
+
+static float expected_x = FLOAT_X;
+static float expected_y = FLOAT_Y;
+static __v2sf expected1 = { FLOAT_X, FLOAT_Y };
+static __v2sf expected2 = { FLOAT_X, 0 };
+static __v2sf expected3 = { FLOAT_X, FLOAT_X };
+
+float
+__attribute__((noinline, noclone))
+foo1 (__m64 x)
+{
+ return ((__v2sf) x)[0];
+}
+
+float
+__attribute__((noinline, noclone))
+foo2 (__m64 x)
+{
+ return ((__v2sf) x)[1];
+}
+
+__m64
+__attribute__((noinline, noclone))
+foo3 (float x)
+{
+ return __extension__ (__m64) (__v2sf) { x, 0 };
+}
+
+__m64
+__attribute__((noinline, noclone))
+foo4 (float x)
+{
+ return __extension__ (__m64) (__v2sf) { x, x };
+}
+
+__m64
+__attribute__((noinline, noclone))
+foo5 (float x, float y)
+{
+ return __extension__ (__m64) (__v2sf) { x, y };
+}
+
+void
+__attribute__((noinline))
+sse2_test (void)
+{
+ __m64 res;
+ float x;
+
+ x = foo1 ((__m64) expected1);
+ if (x != expected_x)
+ abort ();
+
+ x = foo2 ((__m64) expected1);
+ if (x != expected_y)
+ abort ();
+
+ res = foo3 (FLOAT_X);
+ if (memcmp (&res, &expected2, sizeof (res)))
+ abort ();
+
+ res = foo4 (FLOAT_X);
+ if (memcmp (&res, &expected3, sizeof (res)))
+ abort ();
+
+ res = foo5 (FLOAT_X, FLOAT_Y);
+ if (memcmp (&res, &expected1, sizeof (res)))
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.target/i386/sse2-mmx-cvtpi2ps.c b/gcc/testsuite/gcc.target/i386/sse2-mmx-cvtpi2ps.c
new file mode 100644
index 0000000..4ab38d6
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/sse2-mmx-cvtpi2ps.c
@@ -0,0 +1,43 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -fno-strict-aliasing -msse2" } */
+/* { dg-additional-options "-mno-mmx" { target { ! ia32 } } } */
+
+#include <string.h>
+#include "sse2-check.h"
+
+__attribute__((noinline, noclone))
+static void
+test_cvtpi32_ps (__m128 *i1, __m64 *i2, __m128 *r)
+{
+ *(__m128 *) r = _mm_cvtpi32_ps (*i1, *i2);
+}
+
+/* Routine to manually compute the results */
+static void
+compute_correct_result (__m128 *dst_p, __m64 *src_p, __m128 *res_p)
+{
+ int *src = (int *) src_p;
+ float *res = (float *) res_p;
+ *res_p = *dst_p;
+ int i;
+ __m128 r;
+ for (i = 0; i < 2; i++)
+ {
+ r = _mm_cvt_si2ss (*dst_p, src[i]);
+ res[i] = ((__v4sf) r)[0];
+ }
+}
+
+static void
+sse2_test (void)
+{
+ __m128 r, ck;
+ __v4sf x = { 1.99f, -3.9f, -4.9f, 3.8f };
+ __v2si y = { 30, -39 };
+
+ /* Run the MMX tests */
+ test_cvtpi32_ps ((__m128 *) &x, (__m64 *) &y, &r);
+ compute_correct_result ((__m128 *) &x, (__m64 *) &y, &ck);
+ if (memcmp (&ck, &r, sizeof (r)))
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.target/i386/sse2-mmx-cvtps2pi.c b/gcc/testsuite/gcc.target/i386/sse2-mmx-cvtps2pi.c
new file mode 100644
index 0000000..6084c9f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/sse2-mmx-cvtps2pi.c
@@ -0,0 +1,36 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -fno-strict-aliasing -msse2" } */
+/* { dg-additional-options "-mno-mmx" { target { ! ia32 } } } */
+
+#include "sse2-check.h"
+
+__attribute__((noinline, noclone))
+static void
+test_cvtps_pi32 (__m128 *src_p, long long *r)
+{
+ *(__m64 *) r = _mm_cvtps_pi32 (*src_p);
+}
+
+/* Routine to manually compute the results */
+static void
+compute_correct_result (__m128 *src_p, long long *res_p)
+{
+ __v4sf *src = (__v4sf *) src_p;
+ int *res = (int *) res_p;
+ int i;
+ for (i = 0; i < 2; i++)
+ res[i] = _mm_cvt_ss2si (_mm_set_ss ((*src)[i]));
+}
+
+static void
+sse2_test (void)
+{
+ long long r, ck;
+ __v4sf x = { 1.99f, -3.9f, -4.9f, 3.8f };
+
+ /* Run the MMX tests */
+ test_cvtps_pi32 ((__m128 *) &x, &r);
+ compute_correct_result ((__m128 *) &x, &ck);
+ if (ck != r)
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.target/i386/sse2-mmx-cvttps2pi.c b/gcc/testsuite/gcc.target/i386/sse2-mmx-cvttps2pi.c
new file mode 100644
index 0000000..6f12b2f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/sse2-mmx-cvttps2pi.c
@@ -0,0 +1,36 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -fno-strict-aliasing -msse2" } */
+/* { dg-additional-options "-mno-mmx" { target { ! ia32 } } } */
+
+#include "sse2-check.h"
+
+__attribute__((noinline, noclone))
+static void
+test_cvttps_pi32 (__m128 *src_p, long long *r)
+{
+ *(__m64 *) r = _mm_cvttps_pi32 (*src_p);
+}
+
+/* Routine to manually compute the results */
+static void
+compute_correct_result (__m128 *src_p, long long *res_p)
+{
+ __v4sf *src = (__v4sf *) src_p;
+ int *res = (int *) res_p;
+ int i;
+ for (i = 0; i < 2; i++)
+ res[i] = _mm_cvtt_ss2si (_mm_set_ss ((*src)[i]));
+}
+
+static void
+sse2_test (void)
+{
+ long long r, ck;
+ __v4sf x = { 1.99f, -3.9f, -4.9f, 3.8f };
+
+ /* Run the MMX tests */
+ test_cvttps_pi32 ((__m128 *) &x, &r);
+ compute_correct_result ((__m128 *) &x, &ck);
+ if (ck != r)
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.target/i386/sse2-mmx-maskmovq.c b/gcc/testsuite/gcc.target/i386/sse2-mmx-maskmovq.c
new file mode 100644
index 0000000..037f665
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/sse2-mmx-maskmovq.c
@@ -0,0 +1,102 @@
+/* { dg-do run { target mmap } } */
+/* { dg-options "-O2 -fno-strict-aliasing -msse2" } */
+/* { dg-additional-options "-mno-mmx" { target { ! ia32 } } } */
+
+#include <unistd.h>
+#include <sys/mman.h>
+#ifndef MAP_ANONYMOUS
+#define MAP_ANONYMOUS MAP_ANON
+#endif
+#include "sse2-check.h"
+#include "mmx-vals.h"
+
+__attribute__((noinline, noclone))
+static void
+test_maskmovq (long long *ll1, long long *ll2, long long *r)
+{
+ __m64 t1 = *(__m64 *) ll1;
+ __m64 t2 = *(__m64 *) ll2;
+ _m_maskmovq (t1, t2, (char *) r);
+}
+
+/* Routine to manually compute the results */
+static void
+compute_correct_result (long long *dst_p, long long *src_p,
+ long long *res_p)
+{
+ char *dst = (char *) dst_p;
+ char *src = (char *) src_p;
+ char *res = (char *) res_p;
+ int i;
+ for (i = 0; i < 8; i++)
+ if ((src[i] & 0x80) != 0)
+ res[i] = dst[i];
+}
+
+static void
+do_maskmovq_test (long long *r)
+{
+ int i;
+ long long ck;
+ int fail = 0;
+
+ /* Run the MMX tests */
+ for (i = 0; i < MMX_num_ops; i++)
+ {
+ r[0] = -1LL;
+ ck = -1LL;
+ test_maskmovq (&MMXops[i], &MMXops[i], r);
+ compute_correct_result (&MMXops[i], &MMXops[i], &ck);
+ if (*r != ck)
+ fail++;
+ }
+
+ if (fail != 0)
+ abort ();
+}
+
+static void
+sse2_test (void)
+{
+ char *buf;
+ long long *r;
+ size_t page_size = sysconf(_SC_PAGESIZE);
+
+ buf = mmap (0, 3 * page_size, PROT_READ | PROT_WRITE,
+ MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+ if (buf == MAP_FAILED)
+ {
+ perror ("mmap");
+ abort ();
+ }
+
+ if (mprotect (buf, page_size, PROT_NONE))
+ {
+ perror ("mprotect");
+ abort ();
+ }
+
+ if (mprotect (buf + 2 * page_size, page_size, PROT_NONE))
+ {
+ perror ("mprotect");
+ abort ();
+ }
+
+ r = (long long *) (buf + page_size);
+ do_maskmovq_test (r);
+
+ r = (long long *) (buf + page_size + 3);
+ do_maskmovq_test (r);
+
+ r = (long long *) (buf + page_size + 11);
+ do_maskmovq_test (r);
+
+ r = (long long *) (buf + 2 * page_size - 16);
+ do_maskmovq_test (r);
+
+ r = (long long *) (buf + 2 * page_size - 16 + 3);
+ do_maskmovq_test (r);
+
+ r = (long long *) (buf + 2 * page_size - 16 + 8);
+ do_maskmovq_test (r);
+}
diff --git a/gcc/testsuite/gcc.target/i386/sse2-mmx-packssdw.c b/gcc/testsuite/gcc.target/i386/sse2-mmx-packssdw.c
new file mode 100644
index 0000000..ef5fded
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/sse2-mmx-packssdw.c
@@ -0,0 +1,52 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -fno-strict-aliasing -msse2" } */
+/* { dg-additional-options "-mno-mmx" { target { ! ia32 } } } */
+
+#include "sse2-check.h"
+#include "mmx-vals.h"
+
+__attribute__((noinline, noclone))
+static void
+test_packssdw (long long *ll1, long long *ll2, long long *r)
+{
+ __m64 t1 = *(__m64 *) ll1;
+ __m64 t2 = *(__m64 *) ll2;
+ *(__m64 *) r = _m_packssdw (t1, t2);
+}
+
+/* Routine to manually compute the results */
+static void
+compute_correct_result (long long *dst_p, long long *src_p,
+ long long *res_p)
+{
+ int *dst = (int *) dst_p;
+ int *src = (int *) src_p;
+ short *res = (short *) res_p;
+ int i;
+
+ for (i = 0; i < 2; i++)
+ {
+ res[i] = saturate_w (dst[i]);
+ res[i + 2] = saturate_w (src[i]);
+ }
+}
+
+static void
+sse2_test (void)
+{
+ int i;
+ long long r, ck;
+ int fail = 0;
+
+ /* Run the MMX tests */
+ for (i = 0; i < MMX_num_ops; i += 2)
+ {
+ test_packssdw (&MMXops[i], &MMXops[i + 1], &r);
+ compute_correct_result (&MMXops[i], &MMXops[i + 1], &ck);
+ if (ck != r)
+ fail++;
+ }
+
+ if (fail != 0)
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.target/i386/sse2-mmx-packsswb.c b/gcc/testsuite/gcc.target/i386/sse2-mmx-packsswb.c
new file mode 100644
index 0000000..bcc3404
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/sse2-mmx-packsswb.c
@@ -0,0 +1,52 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -fno-strict-aliasing -msse2" } */
+/* { dg-additional-options "-mno-mmx" { target { ! ia32 } } } */
+
+#include "sse2-check.h"
+#include "mmx-vals.h"
+
+__attribute__((noinline, noclone))
+static void
+test_packsswb (long long *ll1, long long *ll2, long long *r)
+{
+ __m64 t1 = *(__m64 *) ll1;
+ __m64 t2 = *(__m64 *) ll2;
+ *(__m64 *) r = _m_packsswb (t1, t2);
+}
+
+/* Routine to manually compute the results */
+static void
+compute_correct_result (long long *dst_p, long long *src_p,
+ long long *res_p)
+{
+ short *dst = (short *) dst_p;
+ short *src = (short *) src_p;
+ char *res = (char *) res_p;
+ int i;
+
+ for (i = 0; i < 4; i++)
+ {
+ res[i] = saturate_b (dst[i]);
+ res[i + 4] = saturate_b (src[i]);
+ }
+}
+
+static void
+sse2_test (void)
+{
+ int i;
+ long long r, ck;
+ int fail = 0;
+
+ /* Run the MMX tests */
+ for (i = 0; i < MMX_num_ops; i += 2)
+ {
+ test_packsswb (&MMXops[i], &MMXops[i + 1], &r);
+ compute_correct_result (&MMXops[i], &MMXops[i + 1], &ck);
+ if (ck != r)
+ fail++;
+ }
+
+ if (fail != 0)
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.target/i386/sse2-mmx-packuswb.c b/gcc/testsuite/gcc.target/i386/sse2-mmx-packuswb.c
new file mode 100644
index 0000000..ac2da06
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/sse2-mmx-packuswb.c
@@ -0,0 +1,52 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -fno-strict-aliasing -msse2" } */
+/* { dg-additional-options "-mno-mmx" { target { ! ia32 } } } */
+
+#include "sse2-check.h"
+#include "mmx-vals.h"
+
+__attribute__((noinline, noclone))
+static void
+test_packuswb (long long *ll1, long long *ll2, long long *r)
+{
+ __m64 t1 = *(__m64 *) ll1;
+ __m64 t2 = *(__m64 *) ll2;
+ *(__m64 *) r = _m_packuswb (t1, t2);
+}
+
+/* Routine to manually compute the results */
+static void
+compute_correct_result (long long *dst_p, long long *src_p,
+ long long *res_p)
+{
+ short *dst = (short *) dst_p;
+ short *src = (short *) src_p;
+ unsigned char *res = (unsigned char *) res_p;
+ int i;
+
+ for (i = 0; i < 4; i++)
+ {
+ res[i] = saturate_ub (dst[i]);
+ res[i + 4] = saturate_ub (src[i]);
+ }
+}
+
+static void
+sse2_test (void)
+{
+ int i;
+ long long r, ck;
+ int fail = 0;
+
+ /* Run the MMX tests */
+ for (i = 0; i < MMX_num_ops; i += 2)
+ {
+ test_packuswb (&MMXops[i], &MMXops[i + 1], &r);
+ compute_correct_result (&MMXops[i], &MMXops[i + 1], &ck);
+ if (ck != r)
+ fail++;
+ }
+
+ if (fail != 0)
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.target/i386/sse2-mmx-paddb.c b/gcc/testsuite/gcc.target/i386/sse2-mmx-paddb.c
new file mode 100644
index 0000000..b125349
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/sse2-mmx-paddb.c
@@ -0,0 +1,48 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -fno-strict-aliasing -msse2" } */
+/* { dg-additional-options "-mno-mmx" { target { ! ia32 } } } */
+
+#include "sse2-check.h"
+#include "mmx-vals.h"
+
+__attribute__((noinline, noclone))
+static void
+test_paddb (long long *ll1, long long *ll2, long long *r)
+{
+ __m64 t1 = *(__m64 *) ll1;
+ __m64 t2 = *(__m64 *) ll2;
+ *(__m64 *) r = _m_paddb (t1, t2);
+}
+
+/* Routine to manually compute the results */
+static void
+compute_correct_result (long long *dst_p, long long *src_p,
+ long long *res_p)
+{
+ char *dst = (char *) dst_p;
+ char *src = (char *) src_p;
+ char *res = (char *) res_p;
+ int i;
+ for (i = 0; i < 8; i++)
+ res[i] = dst[i] + src[i];
+}
+
+static void
+sse2_test (void)
+{
+ int i;
+ long long r, ck;
+ int fail = 0;
+
+ /* Run the MMX tests */
+ for (i = 0; i < MMX_num_ops; i += 2)
+ {
+ test_paddb (&MMXops[i], &MMXops[i + 1], &r);
+ compute_correct_result (&MMXops[i], &MMXops[i + 1], &ck);
+ if (ck != r)
+ fail++;
+ }
+
+ if (fail != 0)
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.target/i386/sse2-mmx-paddd.c b/gcc/testsuite/gcc.target/i386/sse2-mmx-paddd.c
new file mode 100644
index 0000000..d71b217
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/sse2-mmx-paddd.c
@@ -0,0 +1,48 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -fno-strict-aliasing -msse2" } */
+/* { dg-additional-options "-mno-mmx" { target { ! ia32 } } } */
+
+#include "sse2-check.h"
+#include "mmx-vals.h"
+
+__attribute__((noinline, noclone))
+static void
+test_paddd (long long *ll1, long long *ll2, long long *r)
+{
+ __m64 t1 = *(__m64 *) ll1;
+ __m64 t2 = *(__m64 *) ll2;
+ *(__m64 *) r = _m_paddd (t1, t2);
+}
+
+/* Routine to manually compute the results */
+static void
+compute_correct_result (long long *dst_p, long long *src_p,
+ long long *res_p)
+{
+ int *dst = (int *) dst_p;
+ int *src = (int *) src_p;
+ int *res = (int *) res_p;
+ int i;
+ for (i = 0; i < 2; i++)
+ res[i] = dst[i] + src[i];
+}
+
+static void
+sse2_test (void)
+{
+ int i;
+ long long r, ck;
+ int fail = 0;
+
+ /* Run the MMX tests */
+ for (i = 0; i < MMX_num_ops; i += 2)
+ {
+ test_paddd (&MMXops[i], &MMXops[i + 1], &r);
+ compute_correct_result (&MMXops[i], &MMXops[i + 1], &ck);
+ if (ck != r)
+ fail++;
+ }
+
+ if (fail != 0)
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.target/i386/sse2-mmx-paddq.c b/gcc/testsuite/gcc.target/i386/sse2-mmx-paddq.c
new file mode 100644
index 0000000..b015393
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/sse2-mmx-paddq.c
@@ -0,0 +1,43 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -fno-strict-aliasing -msse2" } */
+/* { dg-additional-options "-mno-mmx" { target { ! ia32 } } } */
+
+#include "sse2-check.h"
+#include "mmx-vals.h"
+
+__attribute__((noinline, noclone))
+static void
+test_paddq (long long *ll1, long long *ll2, long long *r)
+{
+ __m64 t1 = *(__m64 *) ll1;
+ __m64 t2 = *(__m64 *) ll2;
+ *(__m64 *) r = _mm_add_si64 (t1, t2);
+}
+
+/* Routine to manually compute the results */
+static void
+compute_correct_result (long long *dst_p, long long *src_p,
+ long long *res_p)
+{
+ res_p[0] = dst_p[0] + src_p[0];
+}
+
+static void
+sse2_test (void)
+{
+ int i;
+ long long r, ck;
+ int fail = 0;
+
+ /* Run the MMX tests */
+ for (i = 0; i < MMX_num_ops; i += 2)
+ {
+ test_paddq (&MMXops[i], &MMXops[i + 1], &r);
+ compute_correct_result (&MMXops[i], &MMXops[i + 1], &ck);
+ if (ck != r)
+ fail++;
+ }
+
+ if (fail != 0)
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.target/i386/sse2-mmx-paddsb.c b/gcc/testsuite/gcc.target/i386/sse2-mmx-paddsb.c
new file mode 100644
index 0000000..f8236be
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/sse2-mmx-paddsb.c
@@ -0,0 +1,48 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -fno-strict-aliasing -msse2" } */
+/* { dg-additional-options "-mno-mmx" { target { ! ia32 } } } */
+
+#include "sse2-check.h"
+#include "mmx-vals.h"
+
+__attribute__((noinline, noclone))
+static void
+test_paddsb (long long *ll1, long long *ll2, long long *r)
+{
+ __m64 t1 = *(__m64 *) ll1;
+ __m64 t2 = *(__m64 *) ll2;
+ *(__m64 *) r = _m_paddsb (t1, t2);
+}
+
+/* Routine to manually compute the results */
+static void
+compute_correct_result (long long *dst_p, long long *src_p,
+ long long *res_p)
+{
+ char *dst = (char *) dst_p;
+ char *src = (char *) src_p;
+ char *res = (char *) res_p;
+ int i;
+ for (i = 0; i < 8; i++)
+ res[i] = saturate_b (dst[i] + src[i]);
+}
+
+static void
+sse2_test (void)
+{
+ int i;
+ long long r, ck;
+ int fail = 0;
+
+ /* Run the MMX tests */
+ for (i = 0; i < MMX_num_ops; i += 2)
+ {
+ test_paddsb (&MMXops[i], &MMXops[i + 1], &r);
+ compute_correct_result (&MMXops[i], &MMXops[i + 1], &ck);
+ if (ck != r)
+ fail++;
+ }
+
+ if (fail != 0)
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.target/i386/sse2-mmx-paddsw.c b/gcc/testsuite/gcc.target/i386/sse2-mmx-paddsw.c
new file mode 100644
index 0000000..cc52fe6
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/sse2-mmx-paddsw.c
@@ -0,0 +1,48 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -fno-strict-aliasing -msse2" } */
+/* { dg-additional-options "-mno-mmx" { target { ! ia32 } } } */
+
+#include "sse2-check.h"
+#include "mmx-vals.h"
+
+__attribute__((noinline, noclone))
+static void
+test_paddsw (long long *ll1, long long *ll2, long long *r)
+{
+ __m64 t1 = *(__m64 *) ll1;
+ __m64 t2 = *(__m64 *) ll2;
+ *(__m64 *) r = _m_paddsw (t1, t2);
+}
+
+/* Routine to manually compute the results */
+static void
+compute_correct_result (long long *dst_p, long long *src_p,
+ long long *res_p)
+{
+ short *dst = (short *) dst_p;
+ short *src = (short *) src_p;
+ short *res = (short *) res_p;
+ int i;
+ for (i = 0; i < 4; i++)
+ res[i] = saturate_w (dst[i] + src[i]);
+}
+
+static void
+sse2_test (void)
+{
+ int i;
+ long long r, ck;
+ int fail = 0;
+
+ /* Run the MMX tests */
+ for (i = 0; i < MMX_num_ops; i += 2)
+ {
+ test_paddsw (&MMXops[i], &MMXops[i + 1], &r);
+ compute_correct_result (&MMXops[i], &MMXops[i + 1], &ck);
+ if (ck != r)
+ fail++;
+ }
+
+ if (fail != 0)
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.target/i386/sse2-mmx-paddusb.c b/gcc/testsuite/gcc.target/i386/sse2-mmx-paddusb.c
new file mode 100644
index 0000000..c802bcf
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/sse2-mmx-paddusb.c
@@ -0,0 +1,48 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -fno-strict-aliasing -msse2" } */
+/* { dg-additional-options "-mno-mmx" { target { ! ia32 } } } */
+
+#include "sse2-check.h"
+#include "mmx-vals.h"
+
+__attribute__((noinline, noclone))
+static void
+test_paddusb (long long *ll1, long long *ll2, long long *r)
+{
+ __m64 t1 = *(__m64 *) ll1;
+ __m64 t2 = *(__m64 *) ll2;
+ *(__m64 *) r = _m_paddusb (t1, t2);
+}
+
+/* Routine to manually compute the results */
+static void
+compute_correct_result (long long *dst_p, long long *src_p,
+ long long *res_p)
+{
+ unsigned char *dst = (unsigned char *) dst_p;
+ unsigned char *src = (unsigned char *) src_p;
+ unsigned char *res = (unsigned char *) res_p;
+ int i;
+ for (i = 0; i < 8; i++)
+ res[i] = saturate_ub (dst[i] + src[i]);
+}
+
+static void
+sse2_test (void)
+{
+ int i;
+ long long r, ck;
+ int fail = 0;
+
+ /* Run the MMX tests */
+ for (i = 0; i < MMX_num_ops; i += 2)
+ {
+ test_paddusb (&MMXops[i], &MMXops[i + 1], &r);
+ compute_correct_result (&MMXops[i], &MMXops[i + 1], &ck);
+ if (ck != r)
+ fail++;
+ }
+
+ if (fail != 0)
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.target/i386/sse2-mmx-paddusw.c b/gcc/testsuite/gcc.target/i386/sse2-mmx-paddusw.c
new file mode 100644
index 0000000..c0f3c86
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/sse2-mmx-paddusw.c
@@ -0,0 +1,48 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -fno-strict-aliasing -msse2" } */
+/* { dg-additional-options "-mno-mmx" { target { ! ia32 } } } */
+
+#include "sse2-check.h"
+#include "mmx-vals.h"
+
+__attribute__((noinline, noclone))
+static void
+test_paddusw (long long *ll1, long long *ll2, long long *r)
+{
+ __m64 t1 = *(__m64 *) ll1;
+ __m64 t2 = *(__m64 *) ll2;
+ *(__m64 *) r = _m_paddusw (t1, t2);
+}
+
+/* Routine to manually compute the results */
+static void
+compute_correct_result (long long *dst_p, long long *src_p,
+ long long *res_p)
+{
+ unsigned short *dst = (unsigned short *) dst_p;
+ unsigned short *src = (unsigned short *) src_p;
+ unsigned short *res = (unsigned short *) res_p;
+ int i;
+ for (i = 0; i < 4; i++)
+ res[i] = saturate_uw (dst[i] + src[i]);
+}
+
+static void
+sse2_test (void)
+{
+ int i;
+ long long r, ck;
+ int fail = 0;
+
+ /* Run the MMX tests */
+ for (i = 0; i < MMX_num_ops; i += 2)
+ {
+ test_paddusw (&MMXops[i], &MMXops[i + 1], &r);
+ compute_correct_result (&MMXops[i], &MMXops[i + 1], &ck);
+ if (ck != r)
+ fail++;
+ }
+
+ if (fail != 0)
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.target/i386/sse2-mmx-paddw.c b/gcc/testsuite/gcc.target/i386/sse2-mmx-paddw.c
new file mode 100644
index 0000000..6921ae8
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/sse2-mmx-paddw.c
@@ -0,0 +1,48 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -fno-strict-aliasing -msse2" } */
+/* { dg-additional-options "-mno-mmx" { target { ! ia32 } } } */
+
+#include "sse2-check.h"
+#include "mmx-vals.h"
+
+__attribute__((noinline, noclone))
+static void
+test_paddw (long long *ll1, long long *ll2, long long *r)
+{
+ __m64 t1 = *(__m64 *) ll1;
+ __m64 t2 = *(__m64 *) ll2;
+ *(__m64 *) r = _m_paddw (t1, t2);
+}
+
+/* Routine to manually compute the results */
+static void
+compute_correct_result (long long *dst_p, long long *src_p,
+ long long *res_p)
+{
+ short *dst = (short *) dst_p;
+ short *src = (short *) src_p;
+ short *res = (short *) res_p;
+ int i;
+ for (i = 0; i < 4; i++)
+ res[i] = dst[i] + src[i];
+}
+
+static void
+sse2_test (void)
+{
+ int i;
+ long long r, ck;
+ int fail = 0;
+
+ /* Run the MMX tests */
+ for (i = 0; i < MMX_num_ops; i += 2)
+ {
+ test_paddw (&MMXops[i], &MMXops[i + 1], &r);
+ compute_correct_result (&MMXops[i], &MMXops[i + 1], &ck);
+ if (ck != r)
+ fail++;
+ }
+
+ if (fail != 0)
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.target/i386/sse2-mmx-pand.c b/gcc/testsuite/gcc.target/i386/sse2-mmx-pand.c
new file mode 100644
index 0000000..0047a7e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/sse2-mmx-pand.c
@@ -0,0 +1,44 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -fno-strict-aliasing -msse2" } */
+/* { dg-additional-options "-mno-mmx" { target { ! ia32 } } } */
+
+#include "sse2-check.h"
+#include "mmx-vals.h"
+
+__attribute__((noinline, noclone))
+static void
+test_pand (long long *ll1, long long *ll2, long long *r)
+{
+ __m64 t1 = *(__m64 *) ll1;
+ __m64 t2 = *(__m64 *) ll2;
+ *(__m64 *) r = _m_pand (t1, t2);
+}
+
+/* Routine to manually compute the results */
+static void
+compute_correct_result (unsigned long long *dst,
+ unsigned long long *src,
+ unsigned long long *res)
+{
+ res[0] = dst[0] & src[0];
+}
+
+static void
+sse2_test (void)
+{
+ int i;
+ long long r, ck;
+ int fail = 0;
+
+ /* Run the MMX tests */
+ for (i = 0; i < MMX_num_ops; i += 2)
+ {
+ test_pand (&MMXops[i], &MMXops[i + 1], &r);
+ compute_correct_result (&MMXops[i], &MMXops[i + 1], &ck);
+ if (ck != r)
+ fail++;
+ }
+
+ if (fail != 0)
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.target/i386/sse2-mmx-pandn.c b/gcc/testsuite/gcc.target/i386/sse2-mmx-pandn.c
new file mode 100644
index 0000000..a0cce55
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/sse2-mmx-pandn.c
@@ -0,0 +1,44 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -fno-strict-aliasing -msse2" } */
+/* { dg-additional-options "-mno-mmx" { target { ! ia32 } } } */
+
+#include "sse2-check.h"
+#include "mmx-vals.h"
+
+__attribute__((noinline, noclone))
+static void
+test_pandn (long long *ll1, long long *ll2, long long *r)
+{
+ __m64 t1 = *(__m64 *) ll1;
+ __m64 t2 = *(__m64 *) ll2;
+ *(__m64 *) r = _m_pandn (t1, t2);
+}
+
+/* Routine to manually compute the results */
+static void
+compute_correct_result (unsigned long long *dst,
+ unsigned long long *src,
+ unsigned long long *res)
+{
+ res[0] = ~dst[0] & src[0];
+}
+
+static void
+sse2_test (void)
+{
+ int i;
+ long long r, ck;
+ int fail = 0;
+
+ /* Run the MMX tests */
+ for (i = 0; i < MMX_num_ops; i += 2)
+ {
+ test_pandn (&MMXops[i], &MMXops[i + 1], &r);
+ compute_correct_result (&MMXops[i], &MMXops[i + 1], &ck);
+ if (ck != r)
+ fail++;
+ }
+
+ if (fail != 0)
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.target/i386/sse2-mmx-pavgb.c b/gcc/testsuite/gcc.target/i386/sse2-mmx-pavgb.c
new file mode 100644
index 0000000..fbb586e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/sse2-mmx-pavgb.c
@@ -0,0 +1,52 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -fno-strict-aliasing -msse2" } */
+/* { dg-additional-options "-mno-mmx" { target { ! ia32 } } } */
+
+#include "sse2-check.h"
+#include "mmx-vals.h"
+
+__attribute__((noinline, noclone))
+static void
+test_pavgb (long long *ll1, long long *ll2, long long *r)
+{
+ __m64 t1 = *(__m64 *) ll1;
+ __m64 t2 = *(__m64 *) ll2;
+ *(__m64 *) r = _m_pavgb (t1, t2);
+}
+
+/* Routine to manually compute the results */
+static void
+compute_correct_result (long long *dst_p, long long *src_p,
+ long long *res_p)
+{
+ unsigned char *dst = (unsigned char *) dst_p;
+ unsigned char *src = (unsigned char *) src_p;
+ unsigned char *res = (unsigned char *) res_p;
+ int i;
+ unsigned int tmp;
+ for (i = 0; i < 8; i++)
+ {
+ tmp = dst[i] + src[i] + 1;
+ res[i] = tmp >> 1;
+ }
+}
+
+static void
+sse2_test (void)
+{
+ int i;
+ long long r, ck;
+ int fail = 0;
+
+ /* Run the MMX tests */
+ for (i = 0; i < MMX_num_ops; i += 2)
+ {
+ test_pavgb (&MMXops[i], &MMXops[i + 1], &r);
+ compute_correct_result (&MMXops[i], &MMXops[i + 1], &ck);
+ if (ck != r)
+ fail++;
+ }
+
+ if (fail != 0)
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.target/i386/sse2-mmx-pavgw.c b/gcc/testsuite/gcc.target/i386/sse2-mmx-pavgw.c
new file mode 100644
index 0000000..81cdc21
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/sse2-mmx-pavgw.c
@@ -0,0 +1,52 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -fno-strict-aliasing -msse2" } */
+/* { dg-additional-options "-mno-mmx" { target { ! ia32 } } } */
+
+#include "sse2-check.h"
+#include "mmx-vals.h"
+
+__attribute__((noinline, noclone))
+static void
+test_pavgw (long long *ll1, long long *ll2, long long *r)
+{
+ __m64 t1 = *(__m64 *) ll1;
+ __m64 t2 = *(__m64 *) ll2;
+ *(__m64 *) r = _m_pavgw (t1, t2);
+}
+
+/* Routine to manually compute the results */
+static void
+compute_correct_result (long long *dst_p, long long *src_p,
+ long long *res_p)
+{
+ unsigned short *dst = (unsigned short *) dst_p;
+ unsigned short *src = (unsigned short *) src_p;
+ unsigned short *res = (unsigned short *) res_p;
+ int i;
+ unsigned int tmp;
+ for (i = 0; i < 4; i++)
+ {
+ tmp = dst[i] + src[i] + 1;
+ res[i] = tmp >> 1;
+ }
+}
+
+static void
+sse2_test (void)
+{
+ int i;
+ long long r, ck;
+ int fail = 0;
+
+ /* Run the MMX tests */
+ for (i = 0; i < MMX_num_ops; i += 2)
+ {
+ test_pavgw (&MMXops[i], &MMXops[i + 1], &r);
+ compute_correct_result (&MMXops[i], &MMXops[i + 1], &ck);
+ if (ck != r)
+ fail++;
+ }
+
+ if (fail != 0)
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.target/i386/sse2-mmx-pcmpeqb.c b/gcc/testsuite/gcc.target/i386/sse2-mmx-pcmpeqb.c
new file mode 100644
index 0000000..d355ba0
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/sse2-mmx-pcmpeqb.c
@@ -0,0 +1,48 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -fno-strict-aliasing -msse2" } */
+/* { dg-additional-options "-mno-mmx" { target { ! ia32 } } } */
+
+#include "sse2-check.h"
+#include "mmx-vals.h"
+
+__attribute__((noinline, noclone))
+static void
+test_pcmpeqb (long long *ll1, long long *ll2, long long *r)
+{
+ __m64 t1 = *(__m64 *) ll1;
+ __m64 t2 = *(__m64 *) ll2;
+ *(__m64 *) r = _m_pcmpeqb (t1, t2);
+}
+
+/* Routine to manually compute the results */
+static void
+compute_correct_result (long long *dst_p, long long *src_p,
+ long long *res_p)
+{
+ char *dst = (char *) dst_p;
+ char *src = (char *) src_p;
+ char *res = (char *) res_p;
+ int i;
+ for (i = 0; i < 8; i++)
+ res[i] = dst[i] == src[i] ? -1 : 0;
+}
+
+static void
+sse2_test (void)
+{
+ int i;
+ long long r, ck;
+ int fail = 0;
+
+ /* Run the MMX tests */
+ for (i = 0; i < MMX_num_ops; i += 2)
+ {
+ test_pcmpeqb (&MMXops[i], &MMXops[i + 1], &r);
+ compute_correct_result (&MMXops[i], &MMXops[i + 1], &ck);
+ if (ck != r)
+ fail++;
+ }
+
+ if (fail != 0)
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.target/i386/sse2-mmx-pcmpeqd.c b/gcc/testsuite/gcc.target/i386/sse2-mmx-pcmpeqd.c
new file mode 100644
index 0000000..bd89624
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/sse2-mmx-pcmpeqd.c
@@ -0,0 +1,48 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -fno-strict-aliasing -msse2" } */
+/* { dg-additional-options "-mno-mmx" { target { ! ia32 } } } */
+
+#include "sse2-check.h"
+#include "mmx-vals.h"
+
+__attribute__((noinline, noclone))
+static void
+test_pcmpeqd (long long *ll1, long long *ll2, long long *r)
+{
+ __m64 t1 = *(__m64 *) ll1;
+ __m64 t2 = *(__m64 *) ll2;
+ *(__m64 *) r = _m_pcmpeqd (t1, t2);
+}
+
+/* Routine to manually compute the results */
+static void
+compute_correct_result (long long *dst_p, long long *src_p,
+ long long *res_p)
+{
+ int *dst = (int *) dst_p;
+ int *src = (int *) src_p;
+ int *res = (int *) res_p;
+ int i;
+ for (i = 0; i < 2; i++)
+ res[i] = dst[i] == src[i] ? -1 : 0;
+}
+
+static void
+sse2_test (void)
+{
+ int i;
+ long long r, ck;
+ int fail = 0;
+
+ /* Run the MMX tests */
+ for (i = 0; i < MMX_num_ops; i += 2)
+ {
+ test_pcmpeqd (&MMXops[i], &MMXops[i + 1], &r);
+ compute_correct_result (&MMXops[i], &MMXops[i + 1], &ck);
+ if (ck != r)
+ fail++;
+ }
+
+ if (fail != 0)
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.target/i386/sse2-mmx-pcmpeqw.c b/gcc/testsuite/gcc.target/i386/sse2-mmx-pcmpeqw.c
new file mode 100644
index 0000000..ae15437
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/sse2-mmx-pcmpeqw.c
@@ -0,0 +1,48 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -fno-strict-aliasing -msse2" } */
+/* { dg-additional-options "-mno-mmx" { target { ! ia32 } } } */
+
+#include "sse2-check.h"
+#include "mmx-vals.h"
+
+__attribute__((noinline, noclone))
+static void
+test_pcmpeqw (long long *ll1, long long *ll2, long long *r)
+{
+ __m64 t1 = *(__m64 *) ll1;
+ __m64 t2 = *(__m64 *) ll2;
+ *(__m64 *) r = _m_pcmpeqw (t1, t2);
+}
+
+/* Routine to manually compute the results */
+static void
+compute_correct_result (long long *dst_p, long long *src_p,
+ long long *res_p)
+{
+ short *dst = (short *) dst_p;
+ short *src = (short *) src_p;
+ short *res = (short *) res_p;
+ int i;
+ for (i = 0; i < 4; i++)
+ res[i] = dst[i] == src[i] ? -1 : 0;
+}
+
+static void
+sse2_test (void)
+{
+ int i;
+ long long r, ck;
+ int fail = 0;
+
+ /* Run the MMX tests */
+ for (i = 0; i < MMX_num_ops; i += 2)
+ {
+ test_pcmpeqw (&MMXops[i], &MMXops[i + 1], &r);
+ compute_correct_result (&MMXops[i], &MMXops[i + 1], &ck);
+ if (ck != r)
+ fail++;
+ }
+
+ if (fail != 0)
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.target/i386/sse2-mmx-pcmpgtb.c b/gcc/testsuite/gcc.target/i386/sse2-mmx-pcmpgtb.c
new file mode 100644
index 0000000..f175c69
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/sse2-mmx-pcmpgtb.c
@@ -0,0 +1,48 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -fno-strict-aliasing -msse2" } */
+/* { dg-additional-options "-mno-mmx" { target { ! ia32 } } } */
+
+#include "sse2-check.h"
+#include "mmx-vals.h"
+
+__attribute__((noinline, noclone))
+static void
+test_pcmpgtb (long long *ll1, long long *ll2, long long *r)
+{
+ __m64 t1 = *(__m64 *) ll1;
+ __m64 t2 = *(__m64 *) ll2;
+ *(__m64 *) r = _m_pcmpgtb (t1, t2);
+}
+
+/* Routine to manually compute the results */
+static void
+compute_correct_result (long long *dst_p, long long *src_p,
+ long long *res_p)
+{
+ char *dst = (char *) dst_p;
+ char *src = (char *) src_p;
+ char *res = (char *) res_p;
+ int i;
+ for (i = 0; i < 8; i++)
+ res[i] = dst[i] > src[i] ? -1 : 0;
+}
+
+static void
+sse2_test (void)
+{
+ int i;
+ long long r, ck;
+ int fail = 0;
+
+ /* Run the MMX tests */
+ for (i = 0; i < MMX_num_ops; i += 2)
+ {
+ test_pcmpgtb (&MMXops[i], &MMXops[i + 1], &r);
+ compute_correct_result (&MMXops[i], &MMXops[i + 1], &ck);
+ if (ck != r)
+ fail++;
+ }
+
+ if (fail != 0)
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.target/i386/sse2-mmx-pcmpgtd.c b/gcc/testsuite/gcc.target/i386/sse2-mmx-pcmpgtd.c
new file mode 100644
index 0000000..451afb5
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/sse2-mmx-pcmpgtd.c
@@ -0,0 +1,48 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -fno-strict-aliasing -msse2" } */
+/* { dg-additional-options "-mno-mmx" { target { ! ia32 } } } */
+
+#include "sse2-check.h"
+#include "mmx-vals.h"
+
+__attribute__((noinline, noclone))
+static void
+test_pcmpgtd (long long *ll1, long long *ll2, long long *r)
+{
+ __m64 t1 = *(__m64 *) ll1;
+ __m64 t2 = *(__m64 *) ll2;
+ *(__m64 *) r = _m_pcmpgtd (t1, t2);
+}
+
+/* Routine to manually compute the results */
+static void
+compute_correct_result (long long *dst_p, long long *src_p,
+ long long *res_p)
+{
+ int *dst = (int *) dst_p;
+ int *src = (int *) src_p;
+ int *res = (int *) res_p;
+ int i;
+ for (i = 0; i < 2; i++)
+ res[i] = dst[i] > src[i] ? -1 : 0;
+}
+
+static void
+sse2_test (void)
+{
+ int i;
+ long long r, ck;
+ int fail = 0;
+
+ /* Run the MMX tests */
+ for (i = 0; i < MMX_num_ops; i += 2)
+ {
+ test_pcmpgtd (&MMXops[i], &MMXops[i + 1], &r);
+ compute_correct_result (&MMXops[i], &MMXops[i + 1], &ck);
+ if (ck != r)
+ fail++;
+ }
+
+ if (fail != 0)
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.target/i386/sse2-mmx-pcmpgtw.c b/gcc/testsuite/gcc.target/i386/sse2-mmx-pcmpgtw.c
new file mode 100644
index 0000000..f3ebe8e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/sse2-mmx-pcmpgtw.c
@@ -0,0 +1,48 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -fno-strict-aliasing -msse2" } */
+/* { dg-additional-options "-mno-mmx" { target { ! ia32 } } } */
+
+#include "sse2-check.h"
+#include "mmx-vals.h"
+
+__attribute__((noinline, noclone))
+static void
+test_pcmpgtw (long long *ll1, long long *ll2, long long *r)
+{
+ __m64 t1 = *(__m64 *) ll1;
+ __m64 t2 = *(__m64 *) ll2;
+ *(__m64 *) r = _m_pcmpgtw (t1, t2);
+}
+
+/* Routine to manually compute the results */
+static void
+compute_correct_result (long long *dst_p, long long *src_p,
+ long long *res_p)
+{
+ short *dst = (short *) dst_p;
+ short *src = (short *) src_p;
+ short *res = (short *) res_p;
+ int i;
+ for (i = 0; i < 4; i++)
+ res[i] = dst[i] > src[i] ? -1 : 0;
+}
+
+static void
+sse2_test (void)
+{
+ int i;
+ long long r, ck;
+ int fail = 0;
+
+ /* Run the MMX tests */
+ for (i = 0; i < MMX_num_ops; i += 2)
+ {
+ test_pcmpgtw (&MMXops[i], &MMXops[i + 1], &r);
+ compute_correct_result (&MMXops[i], &MMXops[i + 1], &ck);
+ if (ck != r)
+ fail++;
+ }
+
+ if (fail != 0)
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.target/i386/sse2-mmx-pextrw.c b/gcc/testsuite/gcc.target/i386/sse2-mmx-pextrw.c
new file mode 100644
index 0000000..bb48740
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/sse2-mmx-pextrw.c
@@ -0,0 +1,59 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -fno-strict-aliasing -msse2" } */
+/* { dg-additional-options "-mno-mmx" { target { ! ia32 } } } */
+
+#include <string.h>
+#include "sse2-check.h"
+
+__attribute__((noinline, noclone))
+static void
+test_pextrw (__m64 *i, unsigned int imm, int *r)
+{
+ switch (imm)
+ {
+ case 0:
+ *r = _m_pextrw (*i, 0);
+ break;
+ case 1:
+ *r = _m_pextrw (*i, 1);
+ break;
+ case 2:
+ *r = _m_pextrw (*i, 2);
+ break;
+ case 3:
+ *r = _m_pextrw (*i, 3);
+ break;
+ default:
+ break;
+ }
+}
+
+/* Routine to manually compute the results */
+static void
+compute_correct_result (__m64 *src_p, unsigned int imm, int *res_p)
+{
+ short *src = (short *) src_p;
+ if (imm < 4)
+ *res_p = src[imm];
+}
+
+static void
+sse2_test (void)
+{
+ int r, ck;
+ int i;
+ int failed = 0;
+ __v4hi y = { 3320, -3339, 48, 4392 };
+
+ /* Run the MMX tests */
+ for (i = 0; i < 4; i++)
+ {
+ test_pextrw ((__m64 *) &y, i, &r);
+ compute_correct_result ((__m64 *) &y, i, &ck);
+ if (r != ck)
+ failed++;
+ }
+
+ if (failed)
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.target/i386/sse2-mmx-pinsrw.c b/gcc/testsuite/gcc.target/i386/sse2-mmx-pinsrw.c
new file mode 100644
index 0000000..c25ddd9
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/sse2-mmx-pinsrw.c
@@ -0,0 +1,61 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -fno-strict-aliasing -msse2" } */
+/* { dg-additional-options "-mno-mmx" { target { ! ia32 } } } */
+
+#include <string.h>
+#include "sse2-check.h"
+
+__attribute__((noinline, noclone))
+static void
+test_pinsrw (__m64 *i, int val, unsigned int imm, int *r)
+{
+ switch (imm)
+ {
+ case 0:
+ *(__m64 *) r = _m_pinsrw (*i, val, 0);
+ break;
+ case 1:
+ *(__m64 *) r = _m_pinsrw (*i, val, 1);
+ break;
+ case 2:
+ *(__m64 *) r = _m_pinsrw (*i, val, 2);
+ break;
+ case 3:
+ *(__m64 *) r = _m_pinsrw (*i, val, 3);
+ break;
+ default:
+ break;
+ }
+}
+
+/* Routine to manually compute the results */
+static void
+compute_correct_result (__m64 *src_p, int val, unsigned int imm,
+ int *res_p)
+{
+ short *res = (short *) res_p;
+ *(__m64 *) res_p = *src_p;
+ if (imm < 4)
+ res[imm] = val;
+}
+
+static void
+sse2_test (void)
+{
+ int r, ck;
+ int i;
+ int failed = 0;
+ __v4hi y = { 3320, -3339, 48, 4392 };
+
+ /* Run the MMX tests */
+ for (i = 0; i < 4; i++)
+ {
+ test_pinsrw ((__m64 *) &y, 0x1234, i, &r);
+ compute_correct_result ((__m64 *) &y, 0x1234, i, &ck);
+ if (r != ck)
+ failed++;
+ }
+
+ if (failed)
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.target/i386/sse2-mmx-pmaddwd.c b/gcc/testsuite/gcc.target/i386/sse2-mmx-pmaddwd.c
new file mode 100644
index 0000000..1eace62
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/sse2-mmx-pmaddwd.c
@@ -0,0 +1,47 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -fno-strict-aliasing -msse2" } */
+/* { dg-additional-options "-mno-mmx" { target { ! ia32 } } } */
+
+#include "sse2-check.h"
+#include "mmx-vals.h"
+
+__attribute__((noinline, noclone))
+static void
+test_pmaddwd (long long *ll1, long long *ll2, long long *r)
+{
+ __m64 t1 = *(__m64 *) ll1;
+ __m64 t2 = *(__m64 *) ll2;
+ *(__m64 *) r = _m_pmaddwd (t1, t2);
+}
+
+/* Routine to manually compute the results */
+static void
+compute_correct_result (long long *dst_p, long long *src_p,
+ long long *res_p)
+{
+ short *dst = (short *) dst_p;
+ short *src = (short *) src_p;
+ int *res = (int *) res_p;
+ res[0] = dst[0] * src[0] + dst[1] * src[1];
+ res[1] = dst[2] * src[2] + dst[3] * src[3];
+}
+
+static void
+sse2_test (void)
+{
+ int i;
+ long long r, ck;
+ int fail = 0;
+
+ /* Run the MMX tests */
+ for (i = 0; i < MMX_num_ops; i += 2)
+ {
+ test_pmaddwd (&MMXops[i], &MMXops[i + 1], &r);
+ compute_correct_result (&MMXops[i], &MMXops[i + 1], &ck);
+ if (ck != r)
+ fail++;
+ }
+
+ if (fail != 0)
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.target/i386/sse2-mmx-pmaxsw.c b/gcc/testsuite/gcc.target/i386/sse2-mmx-pmaxsw.c
new file mode 100644
index 0000000..ec3b68f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/sse2-mmx-pmaxsw.c
@@ -0,0 +1,48 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -fno-strict-aliasing -msse2" } */
+/* { dg-additional-options "-mno-mmx" { target { ! ia32 } } } */
+
+#include "sse2-check.h"
+#include "mmx-vals.h"
+
+__attribute__((noinline, noclone))
+static void
+test_pmaxsw (long long *ll1, long long *ll2, long long *r)
+{
+ __m64 t1 = *(__m64 *) ll1;
+ __m64 t2 = *(__m64 *) ll2;
+ *(__m64 *) r = _m_pmaxsw (t1, t2);
+}
+
+/* Routine to manually compute the results */
+static void
+compute_correct_result (long long *dst_p, long long *src_p,
+ long long *res_p)
+{
+ short *dst = (short *) dst_p;
+ short *src = (short *) src_p;
+ short *res = (short *) res_p;
+ int i;
+ for (i = 0; i < 4; i++)
+ res[i] = dst[i] > src[i] ? dst[i] : src[i];
+}
+
+static void
+sse2_test (void)
+{
+ int i;
+ long long r, ck;
+ int fail = 0;
+
+ /* Run the MMX tests */
+ for (i = 0; i < MMX_num_ops; i += 2)
+ {
+ test_pmaxsw (&MMXops[i], &MMXops[i + 1], &r);
+ compute_correct_result (&MMXops[i], &MMXops[i + 1], &ck);
+ if (ck != r)
+ fail++;
+ }
+
+ if (fail != 0)
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.target/i386/sse2-mmx-pmaxub.c b/gcc/testsuite/gcc.target/i386/sse2-mmx-pmaxub.c
new file mode 100644
index 0000000..085d6a0
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/sse2-mmx-pmaxub.c
@@ -0,0 +1,48 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -fno-strict-aliasing -msse2" } */
+/* { dg-additional-options "-mno-mmx" { target { ! ia32 } } } */
+
+#include "sse2-check.h"
+#include "mmx-vals.h"
+
+__attribute__((noinline, noclone))
+static void
+test_pmaxub (long long *ll1, long long *ll2, long long *r)
+{
+ __m64 t1 = *(__m64 *) ll1;
+ __m64 t2 = *(__m64 *) ll2;
+ *(__m64 *) r = _m_pmaxub (t1, t2);
+}
+
+/* Routine to manually compute the results */
+static void
+compute_correct_result (long long *dst_p, long long *src_p,
+ long long *res_p)
+{
+ unsigned char *dst = (unsigned char *) dst_p;
+ unsigned char *src = (unsigned char *) src_p;
+ unsigned char *res = (unsigned char *) res_p;
+ int i;
+ for (i = 0; i < 8; i++)
+ res[i] = dst[i] > src[i] ? dst[i] : src[i];
+}
+
+static void
+sse2_test (void)
+{
+ int i;
+ long long r, ck;
+ int fail = 0;
+
+ /* Run the MMX tests */
+ for (i = 0; i < MMX_num_ops; i += 2)
+ {
+ test_pmaxub (&MMXops[i], &MMXops[i + 1], &r);
+ compute_correct_result (&MMXops[i], &MMXops[i + 1], &ck);
+ if (ck != r)
+ fail++;
+ }
+
+ if (fail != 0)
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.target/i386/sse2-mmx-pminsw.c b/gcc/testsuite/gcc.target/i386/sse2-mmx-pminsw.c
new file mode 100644
index 0000000..f64d9b2
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/sse2-mmx-pminsw.c
@@ -0,0 +1,48 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -fno-strict-aliasing -msse2" } */
+/* { dg-additional-options "-mno-mmx" { target { ! ia32 } } } */
+
+#include "sse2-check.h"
+#include "mmx-vals.h"
+
+__attribute__((noinline, noclone))
+static void
+test_pminsw (long long *ll1, long long *ll2, long long *r)
+{
+ __m64 t1 = *(__m64 *) ll1;
+ __m64 t2 = *(__m64 *) ll2;
+ *(__m64 *) r = _m_pminsw (t1, t2);
+}
+
+/* Routine to manually compute the results */
+static void
+compute_correct_result (long long *dst_p, long long *src_p,
+ long long *res_p)
+{
+ short *dst = (short *) dst_p;
+ short *src = (short *) src_p;
+ short *res = (short *) res_p;
+ int i;
+ for (i = 0; i < 4; i++)
+ res[i] = dst[i] < src[i] ? dst[i] : src[i];
+}
+
+static void
+sse2_test (void)
+{
+ int i;
+ long long r, ck;
+ int fail = 0;
+
+ /* Run the MMX tests */
+ for (i = 0; i < MMX_num_ops; i += 2)
+ {
+ test_pminsw (&MMXops[i], &MMXops[i + 1], &r);
+ compute_correct_result (&MMXops[i], &MMXops[i + 1], &ck);
+ if (ck != r)
+ fail++;
+ }
+
+ if (fail != 0)
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.target/i386/sse2-mmx-pminub.c b/gcc/testsuite/gcc.target/i386/sse2-mmx-pminub.c
new file mode 100644
index 0000000..372e5ef
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/sse2-mmx-pminub.c
@@ -0,0 +1,48 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -fno-strict-aliasing -msse2" } */
+/* { dg-additional-options "-mno-mmx" { target { ! ia32 } } } */
+
+#include "sse2-check.h"
+#include "mmx-vals.h"
+
+__attribute__((noinline, noclone))
+static void
+test_pminub (long long *ll1, long long *ll2, long long *r)
+{
+ __m64 t1 = *(__m64 *) ll1;
+ __m64 t2 = *(__m64 *) ll2;
+ *(__m64 *) r = _m_pminub (t1, t2);
+}
+
+/* Routine to manually compute the results */
+static void
+compute_correct_result (long long *dst_p, long long *src_p,
+ long long *res_p)
+{
+ unsigned char *dst = (unsigned char *) dst_p;
+ unsigned char *src = (unsigned char *) src_p;
+ unsigned char *res = (unsigned char *) res_p;
+ int i;
+ for (i = 0; i < 8; i++)
+ res[i] = dst[i] < src[i] ? dst[i] : src[i];
+}
+
+static void
+sse2_test (void)
+{
+ int i;
+ long long r, ck;
+ int fail = 0;
+
+ /* Run the MMX tests */
+ for (i = 0; i < MMX_num_ops; i += 2)
+ {
+ test_pminub (&MMXops[i], &MMXops[i + 1], &r);
+ compute_correct_result (&MMXops[i], &MMXops[i + 1], &ck);
+ if (ck != r)
+ fail++;
+ }
+
+ if (fail != 0)
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.target/i386/sse2-mmx-pmovmskb.c b/gcc/testsuite/gcc.target/i386/sse2-mmx-pmovmskb.c
new file mode 100644
index 0000000..46b18d2
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/sse2-mmx-pmovmskb.c
@@ -0,0 +1,46 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -fno-strict-aliasing -msse2" } */
+/* { dg-additional-options "-mno-mmx" { target { ! ia32 } } } */
+
+#include "sse2-check.h"
+#include "mmx-vals.h"
+
+__attribute__((noinline, noclone))
+static void
+test_pmovmskb (long long *ll1, int *r)
+{
+ __m64 t1 = *(__m64 *) ll1;
+ *r = _m_pmovmskb (t1);
+}
+
+/* Routine to manually compute the results */
+static void
+compute_correct_result (long long *src_p, int *res_p)
+{
+ char *src = (char *) src_p;
+ int i;
+ int res = 0;
+ for (i = 0; i < 8; i++)
+ res |= ((src[i] & 0x80) >> 7) << i;
+ *res_p = res;
+}
+
+static void
+sse2_test (void)
+{
+ int i;
+ int r, ck;
+ int fail = 0;
+
+ /* Run the MMX tests */
+ for (i = 0; i < MMX_num_ops; i++)
+ {
+ test_pmovmskb (&MMXops[i], &r);
+ compute_correct_result (&MMXops[i], &ck);
+ if (ck != r)
+ fail++;
+ }
+
+ if (fail != 0)
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.target/i386/sse2-mmx-pmulhuw.c b/gcc/testsuite/gcc.target/i386/sse2-mmx-pmulhuw.c
new file mode 100644
index 0000000..0f8fcbe
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/sse2-mmx-pmulhuw.c
@@ -0,0 +1,51 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -fno-strict-aliasing -msse2" } */
+/* { dg-additional-options "-mno-mmx" { target { ! ia32 } } } */
+
+#include "sse2-check.h"
+#include "mmx-vals.h"
+
+__attribute__((noinline, noclone))
+static void
+test_pmulhuw (long long *ll1, long long *ll2, long long *r)
+{
+ __m64 t1 = *(__m64 *) ll1;
+ __m64 t2 = *(__m64 *) ll2;
+ *(__m64 *) r = _m_pmulhuw (t1, t2);
+}
+
+/* Routine to manually compute the results */
+static void
+compute_correct_result (long long *dst_p, long long *src_p,
+ long long *res_p)
+{
+ unsigned short *dst = (unsigned short *) dst_p;
+ unsigned short *src = (unsigned short *) src_p;
+ unsigned short *res = (unsigned short *) res_p;
+ int i;
+ for (i = 0; i < 4; i++)
+ {
+ unsigned int t = dst[i] * src[i];
+ res[i] = t >> 16;
+ }
+}
+
+static void
+sse2_test (void)
+{
+ int i;
+ long long r, ck;
+ int fail = 0;
+
+ /* Run the MMX tests */
+ for (i = 0; i < MMX_num_ops; i += 2)
+ {
+ test_pmulhuw (&MMXops[i], &MMXops[i + 1], &r);
+ compute_correct_result (&MMXops[i], &MMXops[i + 1], &ck);
+ if (ck != r)
+ fail++;
+ }
+
+ if (fail != 0)
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.target/i386/sse2-mmx-pmulhw.c b/gcc/testsuite/gcc.target/i386/sse2-mmx-pmulhw.c
new file mode 100644
index 0000000..b89c58f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/sse2-mmx-pmulhw.c
@@ -0,0 +1,53 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -fno-strict-aliasing -msse2" } */
+/* { dg-additional-options "-mno-mmx" { target { ! ia32 } } } */
+
+#include "sse2-check.h"
+#include "mmx-vals.h"
+
+__attribute__((noinline, noclone))
+static void
+test_pmulhw (long long *ll1, long long *ll2, long long *r)
+{
+ __m64 t1 = *(__m64 *) ll1;
+ __m64 t2 = *(__m64 *) ll2;
+ *(__m64 *) r = _m_pmulhw (t1, t2);
+}
+
+/* Routine to manually compute the results */
+static void
+compute_correct_result (long long *dst_p, long long *src_p,
+ long long *res_p)
+{
+ short *dst = (short *) dst_p;
+ short *src = (short *) src_p;
+ short *res = (short *) res_p;
+ int tmp;
+ int i;
+ for (i = 0; i < 4; i++)
+ {
+ tmp = dst[i] * src[i];
+ tmp >>= 16;
+ res[i] = tmp;
+ }
+}
+
+static void
+sse2_test (void)
+{
+ int i;
+ long long r, ck;
+ int fail = 0;
+
+ /* Run the MMX tests */
+ for (i = 0; i < MMX_num_ops; i += 2)
+ {
+ test_pmulhw (&MMXops[i], &MMXops[i + 1], &r);
+ compute_correct_result (&MMXops[i], &MMXops[i + 1], &ck);
+ if (ck != r)
+ fail++;
+ }
+
+ if (fail != 0)
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.target/i386/sse2-mmx-pmullw.c b/gcc/testsuite/gcc.target/i386/sse2-mmx-pmullw.c
new file mode 100644
index 0000000..13b8962
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/sse2-mmx-pmullw.c
@@ -0,0 +1,52 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -fno-strict-aliasing -msse2" } */
+/* { dg-additional-options "-mno-mmx" { target { ! ia32 } } } */
+
+#include "sse2-check.h"
+#include "mmx-vals.h"
+
+__attribute__((noinline, noclone))
+static void
+test_pmullw (long long *ll1, long long *ll2, long long *r)
+{
+ __m64 t1 = *(__m64 *) ll1;
+ __m64 t2 = *(__m64 *) ll2;
+ *(__m64 *) r = _m_pmullw (t1, t2);
+}
+
+/* Routine to manually compute the results */
+static void
+compute_correct_result (long long *dst_p, long long *src_p,
+ long long *res_p)
+{
+ short *dst = (short *) dst_p;
+ short *src = (short *) src_p;
+ short *res = (short *) res_p;
+ int tmp;
+ int i;
+ for (i = 0; i < 4; i++)
+ {
+ tmp = dst[i] * src[i];
+ res[i] = tmp;
+ }
+}
+
+static void
+sse2_test (void)
+{
+ int i;
+ long long r, ck;
+ int fail = 0;
+
+ /* Run the MMX tests */
+ for (i = 0; i < MMX_num_ops; i += 2)
+ {
+ test_pmullw (&MMXops[i], &MMXops[i + 1], &r);
+ compute_correct_result (&MMXops[i], &MMXops[i + 1], &ck);
+ if (ck != r)
+ fail++;
+ }
+
+ if (fail != 0)
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.target/i386/sse2-mmx-pmuludq.c b/gcc/testsuite/gcc.target/i386/sse2-mmx-pmuludq.c
new file mode 100644
index 0000000..819e0e1
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/sse2-mmx-pmuludq.c
@@ -0,0 +1,47 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -fno-strict-aliasing -msse2" } */
+/* { dg-additional-options "-mno-mmx" { target { ! ia32 } } } */
+
+#include "sse2-check.h"
+#include "mmx-vals.h"
+
+__attribute__((noinline, noclone))
+static void
+test_pmuludq (long long *ll1, long long *ll2, long long *r)
+{
+ __m64 t1 = *(__m64 *) ll1;
+ __m64 t2 = *(__m64 *) ll2;
+ *(__m64 *) r = _mm_mul_su32 (t1, t2);
+}
+
+/* Routine to manually compute the results */
+static void
+compute_correct_result (long long *dst_p, long long *src_p,
+ long long *res_p)
+{
+ unsigned int *dst = (unsigned int*) dst_p;
+ unsigned int *src = (unsigned int *) src_p;
+ unsigned long long *res = (unsigned long long *) res_p;
+ res[0] = dst[0];
+ res[0] *= src[0];
+}
+
+static void
+sse2_test (void)
+{
+ int i;
+ long long r, ck;
+ int fail = 0;
+
+ /* Run the MMX tests */
+ for (i = 0; i < MMX_num_ops; i += 2)
+ {
+ test_pmuludq (&MMXops[i], &MMXops[i + 1], &r);
+ compute_correct_result (&MMXops[i], &MMXops[i + 1], &ck);
+ if (ck != r)
+ fail++;
+ }
+
+ if (fail != 0)
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.target/i386/sse2-mmx-por.c b/gcc/testsuite/gcc.target/i386/sse2-mmx-por.c
new file mode 100644
index 0000000..9dc6072
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/sse2-mmx-por.c
@@ -0,0 +1,44 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -fno-strict-aliasing -msse2" } */
+/* { dg-additional-options "-mno-mmx" { target { ! ia32 } } } */
+
+#include "sse2-check.h"
+#include "mmx-vals.h"
+
+__attribute__((noinline, noclone))
+static void
+test_por (long long *ll1, long long *ll2, long long *r)
+{
+ __m64 t1 = *(__m64 *) ll1;
+ __m64 t2 = *(__m64 *) ll2;
+ *(__m64 *) r = _m_por (t1, t2);
+}
+
+/* Routine to manually compute the results */
+static void
+compute_correct_result (unsigned long long *dst,
+ unsigned long long *src,
+ unsigned long long *res)
+{
+ res[0] = dst[0] | src[0];
+}
+
+static void
+sse2_test (void)
+{
+ int i;
+ long long r, ck;
+ int fail = 0;
+
+ /* Run the MMX tests */
+ for (i = 0; i < MMX_num_ops; i += 2)
+ {
+ test_por (&MMXops[i], &MMXops[i + 1], &r);
+ compute_correct_result (&MMXops[i], &MMXops[i + 1], &ck);
+ if (ck != r)
+ fail++;
+ }
+
+ if (fail != 0)
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.target/i386/sse2-mmx-psadbw.c b/gcc/testsuite/gcc.target/i386/sse2-mmx-psadbw.c
new file mode 100644
index 0000000..223d3b2
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/sse2-mmx-psadbw.c
@@ -0,0 +1,58 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -fno-strict-aliasing -msse2" } */
+/* { dg-additional-options "-mno-mmx" { target { ! ia32 } } } */
+
+#include "sse2-check.h"
+#include "mmx-vals.h"
+
+__attribute__((noinline, noclone))
+static void
+test_psadbw (long long *ll1, long long *ll2, long long *r)
+{
+ __m64 t1 = *(__m64 *) ll1;
+ __m64 t2 = *(__m64 *) ll2;
+ *(__m64 *) r = _m_psadbw (t1, t2);
+}
+
+/* Routine to manually compute the results */
+static void
+compute_correct_result (long long *dst_p, long long *src_p,
+ long long *res_p)
+{
+ unsigned char *dst = (unsigned char *) dst_p;
+ unsigned char *src = (unsigned char *) src_p;
+ unsigned short *res = (unsigned short *) res_p;
+ int i;
+ int tmp;
+ unsigned int sum = 0;
+ for (i = 0; i < 8; i++)
+ {
+ tmp = dst[i] - src[i];
+ if (tmp < 0)
+ tmp = -tmp;
+ sum += tmp;
+ }
+ res[0] = sum;
+ for (i = 1; i < 4; i++)
+ res[i] = 0;
+}
+
+static void
+sse2_test (void)
+{
+ int i;
+ long long r, ck;
+ int fail = 0;
+
+ /* Run the MMX tests */
+ for (i = 0; i < MMX_num_ops; i += 2)
+ {
+ test_psadbw (&MMXops[i], &MMXops[i + 1], &r);
+ compute_correct_result (&MMXops[i], &MMXops[i + 1], &ck);
+ if (ck != r)
+ fail++;
+ }
+
+ if (fail != 0)
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.target/i386/sse2-mmx-pshufw.c b/gcc/testsuite/gcc.target/i386/sse2-mmx-pshufw.c
new file mode 100644
index 0000000..b723658
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/sse2-mmx-pshufw.c
@@ -0,0 +1,248 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -fno-strict-aliasing -msse2" } */
+/* { dg-additional-options "-mno-mmx" { target { ! ia32 } } } */
+
+#include "sse2-check.h"
+#include "mmx-vals.h"
+
+__attribute__((noinline, noclone))
+static void
+test_pshufw (long long *ll1, unsigned int imm, long long *r)
+{
+ __m64 t1 = *(__m64 *) ll1;
+ switch (imm)
+ {
+ case 0:
+ *(__m64 *) r = _m_pshufw (t1, 0);
+ break;
+ case 1:
+ *(__m64 *) r = _m_pshufw (t1, 1);
+ break;
+ case 2:
+ *(__m64 *) r = _m_pshufw (t1, 2);
+ break;
+ case 3:
+ *(__m64 *) r = _m_pshufw (t1, 3);
+ break;
+ case 4:
+ *(__m64 *) r = _m_pshufw (t1, 4);
+ break;
+ case 5:
+ *(__m64 *) r = _m_pshufw (t1, 5);
+ break;
+ case 6:
+ *(__m64 *) r = _m_pshufw (t1, 6);
+ break;
+ case 7:
+ *(__m64 *) r = _m_pshufw (t1, 7);
+ break;
+ case 8:
+ *(__m64 *) r = _m_pshufw (t1, 8);
+ break;
+ case 9:
+ *(__m64 *) r = _m_pshufw (t1, 9);
+ break;
+ case 10:
+ *(__m64 *) r = _m_pshufw (t1, 10);
+ break;
+ case 11:
+ *(__m64 *) r = _m_pshufw (t1, 11);
+ break;
+ case 12:
+ *(__m64 *) r = _m_pshufw (t1, 12);
+ break;
+ case 13:
+ *(__m64 *) r = _m_pshufw (t1, 13);
+ break;
+ case 14:
+ *(__m64 *) r = _m_pshufw (t1, 14);
+ break;
+ case 15:
+ *(__m64 *) r = _m_pshufw (t1, 15);
+ break;
+ case 16:
+ *(__m64 *) r = _m_pshufw (t1, 16);
+ break;
+ case 17:
+ *(__m64 *) r = _m_pshufw (t1, 17);
+ break;
+ case 18:
+ *(__m64 *) r = _m_pshufw (t1, 18);
+ break;
+ case 19:
+ *(__m64 *) r = _m_pshufw (t1, 19);
+ break;
+ case 20:
+ *(__m64 *) r = _m_pshufw (t1, 20);
+ break;
+ case 21:
+ *(__m64 *) r = _m_pshufw (t1, 21);
+ break;
+ case 22:
+ *(__m64 *) r = _m_pshufw (t1, 22);
+ break;
+ case 23:
+ *(__m64 *) r = _m_pshufw (t1, 23);
+ break;
+ case 24:
+ *(__m64 *) r = _m_pshufw (t1, 24);
+ break;
+ case 25:
+ *(__m64 *) r = _m_pshufw (t1, 25);
+ break;
+ case 26:
+ *(__m64 *) r = _m_pshufw (t1, 26);
+ break;
+ case 27:
+ *(__m64 *) r = _m_pshufw (t1, 27);
+ break;
+ case 28:
+ *(__m64 *) r = _m_pshufw (t1, 28);
+ break;
+ case 29:
+ *(__m64 *) r = _m_pshufw (t1, 29);
+ break;
+ case 30:
+ *(__m64 *) r = _m_pshufw (t1, 30);
+ break;
+ case 31:
+ *(__m64 *) r = _m_pshufw (t1, 31);
+ break;
+ case 32:
+ *(__m64 *) r = _m_pshufw (t1, 32);
+ break;
+ case 33:
+ *(__m64 *) r = _m_pshufw (t1, 33);
+ break;
+ case 34:
+ *(__m64 *) r = _m_pshufw (t1, 34);
+ break;
+ case 35:
+ *(__m64 *) r = _m_pshufw (t1, 35);
+ break;
+ case 36:
+ *(__m64 *) r = _m_pshufw (t1, 36);
+ break;
+ case 37:
+ *(__m64 *) r = _m_pshufw (t1, 37);
+ break;
+ case 38:
+ *(__m64 *) r = _m_pshufw (t1, 38);
+ break;
+ case 39:
+ *(__m64 *) r = _m_pshufw (t1, 39);
+ break;
+ case 40:
+ *(__m64 *) r = _m_pshufw (t1, 40);
+ break;
+ case 41:
+ *(__m64 *) r = _m_pshufw (t1, 41);
+ break;
+ case 42:
+ *(__m64 *) r = _m_pshufw (t1, 42);
+ break;
+ case 43:
+ *(__m64 *) r = _m_pshufw (t1, 43);
+ break;
+ case 44:
+ *(__m64 *) r = _m_pshufw (t1, 44);
+ break;
+ case 45:
+ *(__m64 *) r = _m_pshufw (t1, 45);
+ break;
+ case 46:
+ *(__m64 *) r = _m_pshufw (t1, 46);
+ break;
+ case 47:
+ *(__m64 *) r = _m_pshufw (t1, 47);
+ break;
+ case 48:
+ *(__m64 *) r = _m_pshufw (t1, 48);
+ break;
+ case 49:
+ *(__m64 *) r = _m_pshufw (t1, 49);
+ break;
+ case 50:
+ *(__m64 *) r = _m_pshufw (t1, 50);
+ break;
+ case 51:
+ *(__m64 *) r = _m_pshufw (t1, 51);
+ break;
+ case 52:
+ *(__m64 *) r = _m_pshufw (t1, 52);
+ break;
+ case 53:
+ *(__m64 *) r = _m_pshufw (t1, 53);
+ break;
+ case 54:
+ *(__m64 *) r = _m_pshufw (t1, 54);
+ break;
+ case 55:
+ *(__m64 *) r = _m_pshufw (t1, 55);
+ break;
+ case 56:
+ *(__m64 *) r = _m_pshufw (t1, 56);
+ break;
+ case 57:
+ *(__m64 *) r = _m_pshufw (t1, 57);
+ break;
+ case 58:
+ *(__m64 *) r = _m_pshufw (t1, 58);
+ break;
+ case 59:
+ *(__m64 *) r = _m_pshufw (t1, 59);
+ break;
+ case 60:
+ *(__m64 *) r = _m_pshufw (t1, 60);
+ break;
+ case 61:
+ *(__m64 *) r = _m_pshufw (t1, 61);
+ break;
+ case 62:
+ *(__m64 *) r = _m_pshufw (t1, 62);
+ break;
+ case 63:
+ *(__m64 *) r = _m_pshufw (t1, 63);
+ break;
+ default:
+ break;
+ }
+}
+
+/* Routine to manually compute the results */
+static void
+compute_correct_result (long long *src_p, unsigned int imm,
+ long long *res_p)
+{
+ unsigned long long src = *(unsigned long long *) src_p;
+ unsigned short *res = (unsigned short *) res_p;
+ int i;
+ unsigned int shift;
+ for (i = 0; i < 4; i++)
+ {
+ shift = ((imm >> (2 * i)) & 0x3) * 16;
+ res[i] = (src >> shift) & 0xffff;
+ }
+}
+
+static void
+sse2_test (void)
+{
+ int i;
+ long long r, ck;
+ int fail = 0;
+
+ /* Run the MMX tests */
+ for (i = 0; i < MMX_num_ops; i++)
+ {
+ if (i > 63)
+ break;
+ test_pshufw (&MMXops[i], i, &r);
+ compute_correct_result (&MMXops[i], i, &ck);
+ if (ck != r)
+ fail++;
+ }
+
+ if (fail != 0)
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.target/i386/sse2-mmx-pslld.c b/gcc/testsuite/gcc.target/i386/sse2-mmx-pslld.c
new file mode 100644
index 0000000..86983c0
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/sse2-mmx-pslld.c
@@ -0,0 +1,52 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -fno-strict-aliasing -msse2" } */
+/* { dg-additional-options "-mno-mmx" { target { ! ia32 } } } */
+
+#include "sse2-check.h"
+#include "mmx-vals.h"
+
+__attribute__((noinline, noclone))
+static void
+test_pslld (long long *ll1, long long *ll2, long long *r)
+{
+ __m64 t1 = *(__m64 *) ll1;
+ __m64 t2 = *(__m64 *) ll2;
+ *(__m64 *) r = _m_pslld (t1, t2);
+}
+
+/* Routine to manually compute the results */
+static void
+compute_correct_result (long long *dst_p, long long *src_p,
+ long long *res_p)
+{
+ unsigned int *dst = (unsigned int *) dst_p;
+ unsigned int *src = (unsigned int *) src_p;
+ unsigned int *res = (unsigned int *) res_p;
+ int i;
+ if (src[1] || src[0] > 31)
+ for (i = 0; i < 2; i++)
+ res[i] = 0;
+ else
+ for (i = 0; i < 2; i++)
+ res[i] = dst[i] << src[0];
+}
+
+static void
+sse2_test (void)
+{
+ int i;
+ long long r, ck;
+ int fail = 0;
+
+ /* Run the MMX tests */
+ for (i = 0; i < MMX_num_ops; i += 2)
+ {
+ test_pslld (&MMXops[i], &MMXops[i + 1], &r);
+ compute_correct_result (&MMXops[i], &MMXops[i + 1], &ck);
+ if (ck != r)
+ fail++;
+ }
+
+ if (fail != 0)
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.target/i386/sse2-mmx-pslldi.c b/gcc/testsuite/gcc.target/i386/sse2-mmx-pslldi.c
new file mode 100644
index 0000000..07f0ae9
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/sse2-mmx-pslldi.c
@@ -0,0 +1,153 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -fno-strict-aliasing -msse2" } */
+/* { dg-additional-options "-mno-mmx" { target { ! ia32 } } } */
+
+#include "sse2-check.h"
+#include "mmx-vals.h"
+
+__attribute__((noinline, noclone))
+static void
+test_psllwi (long long *ll1, unsigned int imm, long long *r)
+{
+ __m64 t1 = *(__m64 *) ll1;
+ switch (imm)
+ {
+ case 0:
+ *(__m64 *) r = _m_pslldi (t1, 0);
+ break;
+ case 1:
+ *(__m64 *) r = _m_pslldi (t1, 1);
+ break;
+ case 2:
+ *(__m64 *) r = _m_pslldi (t1, 2);
+ break;
+ case 3:
+ *(__m64 *) r = _m_pslldi (t1, 3);
+ break;
+ case 4:
+ *(__m64 *) r = _m_pslldi (t1, 4);
+ break;
+ case 5:
+ *(__m64 *) r = _m_pslldi (t1, 5);
+ break;
+ case 6:
+ *(__m64 *) r = _m_pslldi (t1, 6);
+ break;
+ case 7:
+ *(__m64 *) r = _m_pslldi (t1, 7);
+ break;
+ case 8:
+ *(__m64 *) r = _m_pslldi (t1, 8);
+ break;
+ case 9:
+ *(__m64 *) r = _m_pslldi (t1, 9);
+ break;
+ case 10:
+ *(__m64 *) r = _m_pslldi (t1, 10);
+ break;
+ case 11:
+ *(__m64 *) r = _m_pslldi (t1, 11);
+ break;
+ case 12:
+ *(__m64 *) r = _m_pslldi (t1, 12);
+ break;
+ case 13:
+ *(__m64 *) r = _m_pslldi (t1, 13);
+ break;
+ case 14:
+ *(__m64 *) r = _m_pslldi (t1, 14);
+ break;
+ case 15:
+ *(__m64 *) r = _m_pslldi (t1, 15);
+ break;
+ case 16:
+ *(__m64 *) r = _m_pslldi (t1, 16);
+ break;
+ case 17:
+ *(__m64 *) r = _m_pslldi (t1, 17);
+ break;
+ case 18:
+ *(__m64 *) r = _m_pslldi (t1, 18);
+ break;
+ case 19:
+ *(__m64 *) r = _m_pslldi (t1, 19);
+ break;
+ case 20:
+ *(__m64 *) r = _m_pslldi (t1, 20);
+ break;
+ case 21:
+ *(__m64 *) r = _m_pslldi (t1, 21);
+ break;
+ case 22:
+ *(__m64 *) r = _m_pslldi (t1, 22);
+ break;
+ case 23:
+ *(__m64 *) r = _m_pslldi (t1, 23);
+ break;
+ case 24:
+ *(__m64 *) r = _m_pslldi (t1, 24);
+ break;
+ case 25:
+ *(__m64 *) r = _m_pslldi (t1, 25);
+ break;
+ case 26:
+ *(__m64 *) r = _m_pslldi (t1, 26);
+ break;
+ case 27:
+ *(__m64 *) r = _m_pslldi (t1, 27);
+ break;
+ case 28:
+ *(__m64 *) r = _m_pslldi (t1, 28);
+ break;
+ case 29:
+ *(__m64 *) r = _m_pslldi (t1, 29);
+ break;
+ case 30:
+ *(__m64 *) r = _m_pslldi (t1, 30);
+ break;
+ case 31:
+ *(__m64 *) r = _m_pslldi (t1, 31);
+ break;
+ default:
+ *(__m64 *) r = _m_pslldi (t1, 32);
+ break;
+ }
+}
+
+/* Routine to manually compute the results */
+static void
+compute_correct_result (long long *src_p, unsigned int imm,
+ long long *res_p)
+{
+ unsigned int *src = (unsigned int *) src_p;
+ unsigned int *res = (unsigned int *) res_p;
+ int i;
+ if (imm > 31)
+ for (i = 0; i < 2; i++)
+ res[i] = 0;
+ else
+ for (i = 0; i < 2; i++)
+ res[i] = src[i] << imm;
+}
+
+static void
+sse2_test (void)
+{
+ int i;
+ unsigned int count;
+ long long r, ck;
+ int fail = 0;
+
+ /* Run the MMX tests */
+ for (i = 0; i < MMX_num_ops; i++)
+ {
+ count = MMXops[i];
+ test_psllwi (&MMXops[i], count, &r);
+ compute_correct_result (&MMXops[i], count, &ck);
+ if (ck != r)
+ fail++;
+ }
+
+ if (fail != 0)
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.target/i386/sse2-mmx-psllq.c b/gcc/testsuite/gcc.target/i386/sse2-mmx-psllq.c
new file mode 100644
index 0000000..37d2e0b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/sse2-mmx-psllq.c
@@ -0,0 +1,47 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -fno-strict-aliasing -msse2" } */
+/* { dg-additional-options "-mno-mmx" { target { ! ia32 } } } */
+
+#include "sse2-check.h"
+#include "mmx-vals.h"
+
+__attribute__((noinline, noclone))
+static void
+test_psllq (long long *ll1, long long *ll2, long long *r)
+{
+ __m64 t1 = *(__m64 *) ll1;
+ __m64 t2 = *(__m64 *) ll2;
+ *(__m64 *) r = _m_psllq (t1, t2);
+}
+
+/* Routine to manually compute the results */
+static void
+compute_correct_result (unsigned long long *dst,
+ unsigned long long *src,
+ unsigned long long *res)
+{
+ if (src[0] > 63)
+ res[0] = 0;
+ else
+ res[0] = dst[0] << src[0];
+}
+
+static void
+sse2_test (void)
+{
+ int i;
+ long long r, ck;
+ int fail = 0;
+
+ /* Run the MMX tests */
+ for (i = 0; i < MMX_num_ops; i += 2)
+ {
+ test_psllq (&MMXops[i], &MMXops[i + 1], &r);
+ compute_correct_result (&MMXops[i], &MMXops[i + 1], &ck);
+ if (ck != r)
+ fail++;
+ }
+
+ if (fail != 0)
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.target/i386/sse2-mmx-psllqi.c b/gcc/testsuite/gcc.target/i386/sse2-mmx-psllqi.c
new file mode 100644
index 0000000..655b369
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/sse2-mmx-psllqi.c
@@ -0,0 +1,245 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -fno-strict-aliasing -msse2" } */
+/* { dg-additional-options "-mno-mmx" { target { ! ia32 } } } */
+
+#include "sse2-check.h"
+#include "mmx-vals.h"
+
+__attribute__((noinline, noclone))
+static void
+test_psllwi (long long *ll1, unsigned int imm, long long *r)
+{
+ __m64 t1 = *(__m64 *) ll1;
+ switch (imm)
+ {
+ case 0:
+ *(__m64 *) r = _m_psllqi (t1, 0);
+ break;
+ case 1:
+ *(__m64 *) r = _m_psllqi (t1, 1);
+ break;
+ case 2:
+ *(__m64 *) r = _m_psllqi (t1, 2);
+ break;
+ case 3:
+ *(__m64 *) r = _m_psllqi (t1, 3);
+ break;
+ case 4:
+ *(__m64 *) r = _m_psllqi (t1, 4);
+ break;
+ case 5:
+ *(__m64 *) r = _m_psllqi (t1, 5);
+ break;
+ case 6:
+ *(__m64 *) r = _m_psllqi (t1, 6);
+ break;
+ case 7:
+ *(__m64 *) r = _m_psllqi (t1, 7);
+ break;
+ case 8:
+ *(__m64 *) r = _m_psllqi (t1, 8);
+ break;
+ case 9:
+ *(__m64 *) r = _m_psllqi (t1, 9);
+ break;
+ case 10:
+ *(__m64 *) r = _m_psllqi (t1, 10);
+ break;
+ case 11:
+ *(__m64 *) r = _m_psllqi (t1, 11);
+ break;
+ case 12:
+ *(__m64 *) r = _m_psllqi (t1, 12);
+ break;
+ case 13:
+ *(__m64 *) r = _m_psllqi (t1, 13);
+ break;
+ case 14:
+ *(__m64 *) r = _m_psllqi (t1, 14);
+ break;
+ case 15:
+ *(__m64 *) r = _m_psllqi (t1, 15);
+ break;
+ case 16:
+ *(__m64 *) r = _m_psllqi (t1, 16);
+ break;
+ case 17:
+ *(__m64 *) r = _m_psllqi (t1, 17);
+ break;
+ case 18:
+ *(__m64 *) r = _m_psllqi (t1, 18);
+ break;
+ case 19:
+ *(__m64 *) r = _m_psllqi (t1, 19);
+ break;
+ case 20:
+ *(__m64 *) r = _m_psllqi (t1, 20);
+ break;
+ case 21:
+ *(__m64 *) r = _m_psllqi (t1, 21);
+ break;
+ case 22:
+ *(__m64 *) r = _m_psllqi (t1, 22);
+ break;
+ case 23:
+ *(__m64 *) r = _m_psllqi (t1, 23);
+ break;
+ case 24:
+ *(__m64 *) r = _m_psllqi (t1, 24);
+ break;
+ case 25:
+ *(__m64 *) r = _m_psllqi (t1, 25);
+ break;
+ case 26:
+ *(__m64 *) r = _m_psllqi (t1, 26);
+ break;
+ case 27:
+ *(__m64 *) r = _m_psllqi (t1, 27);
+ break;
+ case 28:
+ *(__m64 *) r = _m_psllqi (t1, 28);
+ break;
+ case 29:
+ *(__m64 *) r = _m_psllqi (t1, 29);
+ break;
+ case 30:
+ *(__m64 *) r = _m_psllqi (t1, 30);
+ break;
+ case 31:
+ *(__m64 *) r = _m_psllqi (t1, 31);
+ break;
+ case 32:
+ *(__m64 *) r = _m_psllqi (t1, 32);
+ break;
+ case 33:
+ *(__m64 *) r = _m_psllqi (t1, 33);
+ break;
+ case 34:
+ *(__m64 *) r = _m_psllqi (t1, 34);
+ break;
+ case 35:
+ *(__m64 *) r = _m_psllqi (t1, 35);
+ break;
+ case 36:
+ *(__m64 *) r = _m_psllqi (t1, 36);
+ break;
+ case 37:
+ *(__m64 *) r = _m_psllqi (t1, 37);
+ break;
+ case 38:
+ *(__m64 *) r = _m_psllqi (t1, 38);
+ break;
+ case 39:
+ *(__m64 *) r = _m_psllqi (t1, 39);
+ break;
+ case 40:
+ *(__m64 *) r = _m_psllqi (t1, 40);
+ break;
+ case 41:
+ *(__m64 *) r = _m_psllqi (t1, 41);
+ break;
+ case 42:
+ *(__m64 *) r = _m_psllqi (t1, 42);
+ break;
+ case 43:
+ *(__m64 *) r = _m_psllqi (t1, 43);
+ break;
+ case 44:
+ *(__m64 *) r = _m_psllqi (t1, 44);
+ break;
+ case 45:
+ *(__m64 *) r = _m_psllqi (t1, 45);
+ break;
+ case 46:
+ *(__m64 *) r = _m_psllqi (t1, 46);
+ break;
+ case 47:
+ *(__m64 *) r = _m_psllqi (t1, 47);
+ break;
+ case 48:
+ *(__m64 *) r = _m_psllqi (t1, 48);
+ break;
+ case 49:
+ *(__m64 *) r = _m_psllqi (t1, 49);
+ break;
+ case 50:
+ *(__m64 *) r = _m_psllqi (t1, 50);
+ break;
+ case 51:
+ *(__m64 *) r = _m_psllqi (t1, 51);
+ break;
+ case 52:
+ *(__m64 *) r = _m_psllqi (t1, 52);
+ break;
+ case 53:
+ *(__m64 *) r = _m_psllqi (t1, 53);
+ break;
+ case 54:
+ *(__m64 *) r = _m_psllqi (t1, 54);
+ break;
+ case 55:
+ *(__m64 *) r = _m_psllqi (t1, 55);
+ break;
+ case 56:
+ *(__m64 *) r = _m_psllqi (t1, 56);
+ break;
+ case 57:
+ *(__m64 *) r = _m_psllqi (t1, 57);
+ break;
+ case 58:
+ *(__m64 *) r = _m_psllqi (t1, 58);
+ break;
+ case 59:
+ *(__m64 *) r = _m_psllqi (t1, 59);
+ break;
+ case 60:
+ *(__m64 *) r = _m_psllqi (t1, 60);
+ break;
+ case 61:
+ *(__m64 *) r = _m_psllqi (t1, 61);
+ break;
+ case 62:
+ *(__m64 *) r = _m_psllqi (t1, 62);
+ break;
+ case 63:
+ *(__m64 *) r = _m_psllqi (t1, 63);
+ break;
+ default:
+ *(__m64 *) r = _m_psllqi (t1, 64);
+ break;
+ }
+}
+
+/* Routine to manually compute the results */
+static void
+compute_correct_result (unsigned long long *src, unsigned int imm,
+ unsigned long long *res)
+{
+ int i;
+ if (imm > 63)
+ res[0] = 0;
+ else
+ res[0] = src[0] << imm;
+}
+
+static void
+sse2_test (void)
+{
+ int i;
+ unsigned int count;
+ long long r, ck;
+ int fail = 0;
+
+ /* Run the MMX tests */
+ for (i = 0; i < MMX_num_ops; i++)
+ {
+ count = MMXops[i];
+ test_psllwi (&MMXops[i], count, &r);
+ compute_correct_result (&MMXops[i], count, &ck);
+ if (ck != r)
+ fail++;
+ }
+
+ if (fail != 0)
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.target/i386/sse2-mmx-psllw.c b/gcc/testsuite/gcc.target/i386/sse2-mmx-psllw.c
new file mode 100644
index 0000000..7c27d14
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/sse2-mmx-psllw.c
@@ -0,0 +1,52 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -fno-strict-aliasing -msse2" } */
+/* { dg-additional-options "-mno-mmx" { target { ! ia32 } } } */
+
+#include "sse2-check.h"
+#include "mmx-vals.h"
+
+__attribute__((noinline, noclone))
+static void
+test_psllw (long long *ll1, long long *ll2, long long *r)
+{
+ __m64 t1 = *(__m64 *) ll1;
+ __m64 t2 = *(__m64 *) ll2;
+ *(__m64 *) r = _m_psllw (t1, t2);
+}
+
+/* Routine to manually compute the results */
+static void
+compute_correct_result (long long *dst_p, long long *src_p,
+ long long *res_p)
+{
+ unsigned short *dst = (unsigned short *) dst_p;
+ unsigned int *src = (unsigned int *) src_p;
+ unsigned short *res = (unsigned short *) res_p;
+ int i;
+ if (src[1] || src[0] > 15)
+ for (i = 0; i < 4; i++)
+ res[i] = 0;
+ else
+ for (i = 0; i < 4; i++)
+ res[i] = dst[i] << src[0];
+}
+
+static void
+sse2_test (void)
+{
+ int i;
+ long long r, ck;
+ int fail = 0;
+
+ /* Run the MMX tests */
+ for (i = 0; i < MMX_num_ops; i += 2)
+ {
+ test_psllw (&MMXops[i], &MMXops[i + 1], &r);
+ compute_correct_result (&MMXops[i], &MMXops[i + 1], &ck);
+ if (ck != r)
+ fail++;
+ }
+
+ if (fail != 0)
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.target/i386/sse2-mmx-psllwi.c b/gcc/testsuite/gcc.target/i386/sse2-mmx-psllwi.c
new file mode 100644
index 0000000..458463b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/sse2-mmx-psllwi.c
@@ -0,0 +1,105 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -fno-strict-aliasing -msse2" } */
+/* { dg-additional-options "-mno-mmx" { target { ! ia32 } } } */
+
+#include "sse2-check.h"
+#include "mmx-vals.h"
+
+__attribute__((noinline, noclone))
+static void
+test_psllwi (long long *ll1, unsigned int imm, long long *r)
+{
+ __m64 t1 = *(__m64 *) ll1;
+ switch (imm)
+ {
+ case 0:
+ *(__m64 *) r = _m_psllwi (t1, 0);
+ break;
+ case 1:
+ *(__m64 *) r = _m_psllwi (t1, 1);
+ break;
+ case 2:
+ *(__m64 *) r = _m_psllwi (t1, 2);
+ break;
+ case 3:
+ *(__m64 *) r = _m_psllwi (t1, 3);
+ break;
+ case 4:
+ *(__m64 *) r = _m_psllwi (t1, 4);
+ break;
+ case 5:
+ *(__m64 *) r = _m_psllwi (t1, 5);
+ break;
+ case 6:
+ *(__m64 *) r = _m_psllwi (t1, 6);
+ break;
+ case 7:
+ *(__m64 *) r = _m_psllwi (t1, 7);
+ break;
+ case 8:
+ *(__m64 *) r = _m_psllwi (t1, 8);
+ break;
+ case 9:
+ *(__m64 *) r = _m_psllwi (t1, 9);
+ break;
+ case 10:
+ *(__m64 *) r = _m_psllwi (t1, 10);
+ break;
+ case 11:
+ *(__m64 *) r = _m_psllwi (t1, 11);
+ break;
+ case 12:
+ *(__m64 *) r = _m_psllwi (t1, 12);
+ break;
+ case 13:
+ *(__m64 *) r = _m_psllwi (t1, 13);
+ break;
+ case 14:
+ *(__m64 *) r = _m_psllwi (t1, 14);
+ break;
+ case 15:
+ *(__m64 *) r = _m_psllwi (t1, 15);
+ break;
+ default:
+ *(__m64 *) r = _m_psllwi (t1, 16);
+ break;
+ }
+}
+
+/* Routine to manually compute the results */
+static void
+compute_correct_result (long long *src_p, unsigned int imm,
+ long long *res_p)
+{
+ unsigned short *src = (unsigned short *) src_p;
+ unsigned short *res = (unsigned short *) res_p;
+ int i;
+ if (imm > 15)
+ for (i = 0; i < 4; i++)
+ res[i] = 0;
+ else
+ for (i = 0; i < 4; i++)
+ res[i] = src[i] << imm;
+}
+
+static void
+sse2_test (void)
+{
+ int i;
+ unsigned int count;
+ long long r, ck;
+ int fail = 0;
+
+ /* Run the MMX tests */
+ for (i = 0; i < MMX_num_ops; i++)
+ {
+ count = MMXops[i];
+ test_psllwi (&MMXops[i], count, &r);
+ compute_correct_result (&MMXops[i], count, &ck);
+ if (ck != r)
+ fail++;
+ }
+
+ if (fail != 0)
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.target/i386/sse2-mmx-psrad.c b/gcc/testsuite/gcc.target/i386/sse2-mmx-psrad.c
new file mode 100644
index 0000000..494bcb4
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/sse2-mmx-psrad.c
@@ -0,0 +1,52 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -fno-strict-aliasing -msse2" } */
+/* { dg-additional-options "-mno-mmx" { target { ! ia32 } } } */
+
+#include "sse2-check.h"
+#include "mmx-vals.h"
+
+__attribute__((noinline, noclone))
+static void
+test_psrad (long long *ll1, long long *ll2, long long *r)
+{
+ __m64 t1 = *(__m64 *) ll1;
+ __m64 t2 = *(__m64 *) ll2;
+ *(__m64 *) r = _m_psrad (t1, t2);
+}
+
+/* Routine to manually compute the results */
+static void
+compute_correct_result (long long *dst_p, long long *src_p,
+ long long *res_p)
+{
+ int *dst = (int *) dst_p;
+ unsigned int *src = (unsigned int *) src_p;
+ int *res = (int *) res_p;
+ int i;
+ if (src[1] || src[0] > 31)
+ for (i = 0; i < 2; i++)
+ res[i] = dst[i] < 0 ? -1 : 0;
+ else
+ for (i = 0; i < 2; i++)
+ res[i] = dst[i] >> src[0];
+}
+
+static void
+sse2_test (void)
+{
+ int i;
+ long long r, ck;
+ int fail = 0;
+
+ /* Run the MMX tests */
+ for (i = 0; i < MMX_num_ops; i += 2)
+ {
+ test_psrad (&MMXops[i], &MMXops[i + 1], &r);
+ compute_correct_result (&MMXops[i], &MMXops[i + 1], &ck);
+ if (ck != r)
+ fail++;
+ }
+
+ if (fail != 0)
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.target/i386/sse2-mmx-psradi.c b/gcc/testsuite/gcc.target/i386/sse2-mmx-psradi.c
new file mode 100644
index 0000000..4ae2ac8
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/sse2-mmx-psradi.c
@@ -0,0 +1,153 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -fno-strict-aliasing -msse2" } */
+/* { dg-additional-options "-mno-mmx" { target { ! ia32 } } } */
+
+#include "sse2-check.h"
+#include "mmx-vals.h"
+
+__attribute__((noinline, noclone))
+static void
+test_psradi (long long *ll1, unsigned int imm, long long *r)
+{
+ __m64 t1 = *(__m64 *) ll1;
+ switch (imm)
+ {
+ case 0:
+ *(__m64 *) r = _m_psradi (t1, 0);
+ break;
+ case 1:
+ *(__m64 *) r = _m_psradi (t1, 1);
+ break;
+ case 2:
+ *(__m64 *) r = _m_psradi (t1, 2);
+ break;
+ case 3:
+ *(__m64 *) r = _m_psradi (t1, 3);
+ break;
+ case 4:
+ *(__m64 *) r = _m_psradi (t1, 4);
+ break;
+ case 5:
+ *(__m64 *) r = _m_psradi (t1, 5);
+ break;
+ case 6:
+ *(__m64 *) r = _m_psradi (t1, 6);
+ break;
+ case 7:
+ *(__m64 *) r = _m_psradi (t1, 7);
+ break;
+ case 8:
+ *(__m64 *) r = _m_psradi (t1, 8);
+ break;
+ case 9:
+ *(__m64 *) r = _m_psradi (t1, 9);
+ break;
+ case 10:
+ *(__m64 *) r = _m_psradi (t1, 10);
+ break;
+ case 11:
+ *(__m64 *) r = _m_psradi (t1, 11);
+ break;
+ case 12:
+ *(__m64 *) r = _m_psradi (t1, 12);
+ break;
+ case 13:
+ *(__m64 *) r = _m_psradi (t1, 13);
+ break;
+ case 14:
+ *(__m64 *) r = _m_psradi (t1, 14);
+ break;
+ case 15:
+ *(__m64 *) r = _m_psradi (t1, 15);
+ break;
+ case 16:
+ *(__m64 *) r = _m_psradi (t1, 16);
+ break;
+ case 17:
+ *(__m64 *) r = _m_psradi (t1, 17);
+ break;
+ case 18:
+ *(__m64 *) r = _m_psradi (t1, 18);
+ break;
+ case 19:
+ *(__m64 *) r = _m_psradi (t1, 19);
+ break;
+ case 20:
+ *(__m64 *) r = _m_psradi (t1, 20);
+ break;
+ case 21:
+ *(__m64 *) r = _m_psradi (t1, 21);
+ break;
+ case 22:
+ *(__m64 *) r = _m_psradi (t1, 22);
+ break;
+ case 23:
+ *(__m64 *) r = _m_psradi (t1, 23);
+ break;
+ case 24:
+ *(__m64 *) r = _m_psradi (t1, 24);
+ break;
+ case 25:
+ *(__m64 *) r = _m_psradi (t1, 25);
+ break;
+ case 26:
+ *(__m64 *) r = _m_psradi (t1, 26);
+ break;
+ case 27:
+ *(__m64 *) r = _m_psradi (t1, 27);
+ break;
+ case 28:
+ *(__m64 *) r = _m_psradi (t1, 28);
+ break;
+ case 29:
+ *(__m64 *) r = _m_psradi (t1, 29);
+ break;
+ case 30:
+ *(__m64 *) r = _m_psradi (t1, 30);
+ break;
+ case 31:
+ *(__m64 *) r = _m_psradi (t1, 31);
+ break;
+ default:
+ *(__m64 *) r = _m_psradi (t1, 32);
+ break;
+ }
+}
+
+/* Routine to manually compute the results */
+static void
+compute_correct_result (long long *src_p, unsigned int imm,
+ long long *res_p)
+{
+ int *src = (int *) src_p;
+ int *res = (int *) res_p;
+ int i;
+ if (imm > 31)
+ for (i = 0; i < 2; i++)
+ res[i] = src[i] < 0 ? -1 : 0;
+ else
+ for (i = 0; i < 2; i++)
+ res[i] = src[i] >> imm;
+}
+
+static void
+sse2_test (void)
+{
+ int i;
+ unsigned int count;
+ long long r, ck;
+ int fail = 0;
+
+ /* Run the MMX tests */
+ for (i = 0; i < MMX_num_ops; i++)
+ {
+ count = MMXops[i];
+ test_psradi (&MMXops[i], count, &r);
+ compute_correct_result (&MMXops[i], count, &ck);
+ if (ck != r)
+ fail++;
+ }
+
+ if (fail != 0)
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.target/i386/sse2-mmx-psraw.c b/gcc/testsuite/gcc.target/i386/sse2-mmx-psraw.c
new file mode 100644
index 0000000..dd097f2
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/sse2-mmx-psraw.c
@@ -0,0 +1,52 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -fno-strict-aliasing -msse2" } */
+/* { dg-additional-options "-mno-mmx" { target { ! ia32 } } } */
+
+#include "sse2-check.h"
+#include "mmx-vals.h"
+
+__attribute__((noinline, noclone))
+static void
+test_psraw (long long *ll1, long long *ll2, long long *r)
+{
+ __m64 t1 = *(__m64 *) ll1;
+ __m64 t2 = *(__m64 *) ll2;
+ *(__m64 *) r = _m_psraw (t1, t2);
+}
+
+/* Routine to manually compute the results */
+static void
+compute_correct_result (long long *dst_p, long long *src_p,
+ long long *res_p)
+{
+ short *dst = (short *) dst_p;
+ unsigned int *src = (unsigned int *) src_p;
+ short *res = (short *) res_p;
+ int i;
+ if (src[1] || src[0] > 15)
+ for (i = 0; i < 4; i++)
+ res[i] = dst[i] < 0 ? -1 : 0;
+ else
+ for (i = 0; i < 4; i++)
+ res[i] = dst[i] >> src[0];
+}
+
+static void
+sse2_test (void)
+{
+ int i;
+ long long r, ck;
+ int fail = 0;
+
+ /* Run the MMX tests */
+ for (i = 0; i < MMX_num_ops; i += 2)
+ {
+ test_psraw (&MMXops[i], &MMXops[i + 1], &r);
+ compute_correct_result (&MMXops[i], &MMXops[i + 1], &ck);
+ if (ck != r)
+ fail++;
+ }
+
+ if (fail != 0)
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.target/i386/sse2-mmx-psrawi.c b/gcc/testsuite/gcc.target/i386/sse2-mmx-psrawi.c
new file mode 100644
index 0000000..30a2d8b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/sse2-mmx-psrawi.c
@@ -0,0 +1,105 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -fno-strict-aliasing -msse2" } */
+/* { dg-additional-options "-mno-mmx" { target { ! ia32 } } } */
+
+#include "sse2-check.h"
+#include "mmx-vals.h"
+
+__attribute__((noinline, noclone))
+static void
+test_psrawi (long long *ll1, unsigned int imm, long long *r)
+{
+ __m64 t1 = *(__m64 *) ll1;
+ switch (imm)
+ {
+ case 0:
+ *(__m64 *) r = _m_psrawi (t1, 0);
+ break;
+ case 1:
+ *(__m64 *) r = _m_psrawi (t1, 1);
+ break;
+ case 2:
+ *(__m64 *) r = _m_psrawi (t1, 2);
+ break;
+ case 3:
+ *(__m64 *) r = _m_psrawi (t1, 3);
+ break;
+ case 4:
+ *(__m64 *) r = _m_psrawi (t1, 4);
+ break;
+ case 5:
+ *(__m64 *) r = _m_psrawi (t1, 5);
+ break;
+ case 6:
+ *(__m64 *) r = _m_psrawi (t1, 6);
+ break;
+ case 7:
+ *(__m64 *) r = _m_psrawi (t1, 7);
+ break;
+ case 8:
+ *(__m64 *) r = _m_psrawi (t1, 8);
+ break;
+ case 9:
+ *(__m64 *) r = _m_psrawi (t1, 9);
+ break;
+ case 10:
+ *(__m64 *) r = _m_psrawi (t1, 10);
+ break;
+ case 11:
+ *(__m64 *) r = _m_psrawi (t1, 11);
+ break;
+ case 12:
+ *(__m64 *) r = _m_psrawi (t1, 12);
+ break;
+ case 13:
+ *(__m64 *) r = _m_psrawi (t1, 13);
+ break;
+ case 14:
+ *(__m64 *) r = _m_psrawi (t1, 14);
+ break;
+ case 15:
+ *(__m64 *) r = _m_psrawi (t1, 15);
+ break;
+ default:
+ *(__m64 *) r = _m_psrawi (t1, 16);
+ break;
+ }
+}
+
+/* Routine to manually compute the results */
+static void
+compute_correct_result (long long *src_p, unsigned int imm,
+ long long *res_p)
+{
+ short *src = (short *) src_p;
+ short *res = (short *) res_p;
+ int i;
+ if (imm > 15)
+ for (i = 0; i < 4; i++)
+ res[i] = src[i] < 0 ? -1 : 0;
+ else
+ for (i = 0; i < 4; i++)
+ res[i] = src[i] >> imm;
+}
+
+static void
+sse2_test (void)
+{
+ int i;
+ unsigned int count;
+ long long r, ck;
+ int fail = 0;
+
+ /* Run the MMX tests */
+ for (i = 0; i < MMX_num_ops; i++)
+ {
+ count = MMXops[i];
+ test_psrawi (&MMXops[i], count, &r);
+ compute_correct_result (&MMXops[i], count, &ck);
+ if (ck != r)
+ fail++;
+ }
+
+ if (fail != 0)
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.target/i386/sse2-mmx-psrld.c b/gcc/testsuite/gcc.target/i386/sse2-mmx-psrld.c
new file mode 100644
index 0000000..3858be1
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/sse2-mmx-psrld.c
@@ -0,0 +1,52 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -fno-strict-aliasing -msse2" } */
+/* { dg-additional-options "-mno-mmx" { target { ! ia32 } } } */
+
+#include "sse2-check.h"
+#include "mmx-vals.h"
+
+__attribute__((noinline, noclone))
+static void
+test_psrld (long long *ll1, long long *ll2, long long *r)
+{
+ __m64 t1 = *(__m64 *) ll1;
+ __m64 t2 = *(__m64 *) ll2;
+ *(__m64 *) r = _m_psrld (t1, t2);
+}
+
+/* Routine to manually compute the results */
+static void
+compute_correct_result (long long *dst_p, long long *src_p,
+ long long *res_p)
+{
+ int *dst = (int *) dst_p;
+ unsigned int *src = (unsigned int *) src_p;
+ int *res = (int *) res_p;
+ int i;
+ if (src[1] || src[0] > 31)
+ for (i = 0; i < 2; i++)
+ res[i] = 0;
+ else
+ for (i = 0; i < 2; i++)
+ res[i] = dst[i] >> src[0];
+}
+
+static void
+sse2_test (void)
+{
+ int i;
+ long long r, ck;
+ int fail = 0;
+
+ /* Run the MMX tests */
+ for (i = 0; i < MMX_num_ops; i += 2)
+ {
+ test_psrld (&MMXops[i], &MMXops[i + 1], &r);
+ compute_correct_result (&MMXops[i], &MMXops[i + 1], &ck);
+ if (ck != r)
+ fail++;
+ }
+
+ if (fail != 0)
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.target/i386/sse2-mmx-psrldi.c b/gcc/testsuite/gcc.target/i386/sse2-mmx-psrldi.c
new file mode 100644
index 0000000..9315b6f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/sse2-mmx-psrldi.c
@@ -0,0 +1,153 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -fno-strict-aliasing -msse2" } */
+/* { dg-additional-options "-mno-mmx" { target { ! ia32 } } } */
+
+#include "sse2-check.h"
+#include "mmx-vals.h"
+
+__attribute__((noinline, noclone))
+static void
+test_psrldi (long long *ll1, unsigned int imm, long long *r)
+{
+ __m64 t1 = *(__m64 *) ll1;
+ switch (imm)
+ {
+ case 0:
+ *(__m64 *) r = _m_psrldi (t1, 0);
+ break;
+ case 1:
+ *(__m64 *) r = _m_psrldi (t1, 1);
+ break;
+ case 2:
+ *(__m64 *) r = _m_psrldi (t1, 2);
+ break;
+ case 3:
+ *(__m64 *) r = _m_psrldi (t1, 3);
+ break;
+ case 4:
+ *(__m64 *) r = _m_psrldi (t1, 4);
+ break;
+ case 5:
+ *(__m64 *) r = _m_psrldi (t1, 5);
+ break;
+ case 6:
+ *(__m64 *) r = _m_psrldi (t1, 6);
+ break;
+ case 7:
+ *(__m64 *) r = _m_psrldi (t1, 7);
+ break;
+ case 8:
+ *(__m64 *) r = _m_psrldi (t1, 8);
+ break;
+ case 9:
+ *(__m64 *) r = _m_psrldi (t1, 9);
+ break;
+ case 10:
+ *(__m64 *) r = _m_psrldi (t1, 10);
+ break;
+ case 11:
+ *(__m64 *) r = _m_psrldi (t1, 11);
+ break;
+ case 12:
+ *(__m64 *) r = _m_psrldi (t1, 12);
+ break;
+ case 13:
+ *(__m64 *) r = _m_psrldi (t1, 13);
+ break;
+ case 14:
+ *(__m64 *) r = _m_psrldi (t1, 14);
+ break;
+ case 15:
+ *(__m64 *) r = _m_psrldi (t1, 15);
+ break;
+ case 16:
+ *(__m64 *) r = _m_psrldi (t1, 16);
+ break;
+ case 17:
+ *(__m64 *) r = _m_psrldi (t1, 17);
+ break;
+ case 18:
+ *(__m64 *) r = _m_psrldi (t1, 18);
+ break;
+ case 19:
+ *(__m64 *) r = _m_psrldi (t1, 19);
+ break;
+ case 20:
+ *(__m64 *) r = _m_psrldi (t1, 20);
+ break;
+ case 21:
+ *(__m64 *) r = _m_psrldi (t1, 21);
+ break;
+ case 22:
+ *(__m64 *) r = _m_psrldi (t1, 22);
+ break;
+ case 23:
+ *(__m64 *) r = _m_psrldi (t1, 23);
+ break;
+ case 24:
+ *(__m64 *) r = _m_psrldi (t1, 24);
+ break;
+ case 25:
+ *(__m64 *) r = _m_psrldi (t1, 25);
+ break;
+ case 26:
+ *(__m64 *) r = _m_psrldi (t1, 26);
+ break;
+ case 27:
+ *(__m64 *) r = _m_psrldi (t1, 27);
+ break;
+ case 28:
+ *(__m64 *) r = _m_psrldi (t1, 28);
+ break;
+ case 29:
+ *(__m64 *) r = _m_psrldi (t1, 29);
+ break;
+ case 30:
+ *(__m64 *) r = _m_psrldi (t1, 30);
+ break;
+ case 31:
+ *(__m64 *) r = _m_psrldi (t1, 31);
+ break;
+ default:
+ *(__m64 *) r = _m_psrldi (t1, 32);
+ break;
+ }
+}
+
+/* Routine to manually compute the results */
+static void
+compute_correct_result (long long *src_p, unsigned int imm,
+ long long *res_p)
+{
+ int *src = (int *) src_p;
+ int *res = (int *) res_p;
+ int i;
+ if (imm > 31)
+ for (i = 0; i < 2; i++)
+ res[i] = 0;
+ else
+ for (i = 0; i < 2; i++)
+ res[i] = src[i] >> imm;
+}
+
+static void
+sse2_test (void)
+{
+ int i;
+ unsigned int count;
+ long long r, ck;
+ int fail = 0;
+
+ /* Run the MMX tests */
+ for (i = 0; i < MMX_num_ops; i++)
+ {
+ count = MMXops[i];
+ test_psrldi (&MMXops[i], count, &r);
+ compute_correct_result (&MMXops[i], count, &ck);
+ if (ck != r)
+ fail++;
+ }
+
+ if (fail != 0)
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.target/i386/sse2-mmx-psrlq.c b/gcc/testsuite/gcc.target/i386/sse2-mmx-psrlq.c
new file mode 100644
index 0000000..064fb4a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/sse2-mmx-psrlq.c
@@ -0,0 +1,47 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -fno-strict-aliasing -msse2" } */
+/* { dg-additional-options "-mno-mmx" { target { ! ia32 } } } */
+
+#include "sse2-check.h"
+#include "mmx-vals.h"
+
+__attribute__((noinline, noclone))
+static void
+test_psrlq (long long *ll1, long long *ll2, long long *r)
+{
+ __m64 t1 = *(__m64 *) ll1;
+ __m64 t2 = *(__m64 *) ll2;
+ *(__m64 *) r = _m_psrlq (t1, t2);
+}
+
+/* Routine to manually compute the results */
+static void
+compute_correct_result (unsigned long long *dst,
+ unsigned long long *src,
+ unsigned long long *res)
+{
+ if (src[0] > 63)
+ res[0] = 0;
+ else
+ res[0] = dst[0] >> src[0];
+}
+
+static void
+sse2_test (void)
+{
+ int i;
+ long long r, ck;
+ int fail = 0;
+
+ /* Run the MMX tests */
+ for (i = 0; i < MMX_num_ops; i += 2)
+ {
+ test_psrlq (&MMXops[i], &MMXops[i + 1], &r);
+ compute_correct_result (&MMXops[i], &MMXops[i + 1], &ck);
+ if (ck != r)
+ fail++;
+ }
+
+ if (fail != 0)
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.target/i386/sse2-mmx-psrlqi.c b/gcc/testsuite/gcc.target/i386/sse2-mmx-psrlqi.c
new file mode 100644
index 0000000..35de178
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/sse2-mmx-psrlqi.c
@@ -0,0 +1,245 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -fno-strict-aliasing -msse2" } */
+/* { dg-additional-options "-mno-mmx" { target { ! ia32 } } } */
+
+#include "sse2-check.h"
+#include "mmx-vals.h"
+
+__attribute__((noinline, noclone))
+static void
+test_psllwi (long long *ll1, unsigned int imm, long long *r)
+{
+ __m64 t1 = *(__m64 *) ll1;
+ switch (imm)
+ {
+ case 0:
+ *(__m64 *) r = _m_psrlqi (t1, 0);
+ break;
+ case 1:
+ *(__m64 *) r = _m_psrlqi (t1, 1);
+ break;
+ case 2:
+ *(__m64 *) r = _m_psrlqi (t1, 2);
+ break;
+ case 3:
+ *(__m64 *) r = _m_psrlqi (t1, 3);
+ break;
+ case 4:
+ *(__m64 *) r = _m_psrlqi (t1, 4);
+ break;
+ case 5:
+ *(__m64 *) r = _m_psrlqi (t1, 5);
+ break;
+ case 6:
+ *(__m64 *) r = _m_psrlqi (t1, 6);
+ break;
+ case 7:
+ *(__m64 *) r = _m_psrlqi (t1, 7);
+ break;
+ case 8:
+ *(__m64 *) r = _m_psrlqi (t1, 8);
+ break;
+ case 9:
+ *(__m64 *) r = _m_psrlqi (t1, 9);
+ break;
+ case 10:
+ *(__m64 *) r = _m_psrlqi (t1, 10);
+ break;
+ case 11:
+ *(__m64 *) r = _m_psrlqi (t1, 11);
+ break;
+ case 12:
+ *(__m64 *) r = _m_psrlqi (t1, 12);
+ break;
+ case 13:
+ *(__m64 *) r = _m_psrlqi (t1, 13);
+ break;
+ case 14:
+ *(__m64 *) r = _m_psrlqi (t1, 14);
+ break;
+ case 15:
+ *(__m64 *) r = _m_psrlqi (t1, 15);
+ break;
+ case 16:
+ *(__m64 *) r = _m_psrlqi (t1, 16);
+ break;
+ case 17:
+ *(__m64 *) r = _m_psrlqi (t1, 17);
+ break;
+ case 18:
+ *(__m64 *) r = _m_psrlqi (t1, 18);
+ break;
+ case 19:
+ *(__m64 *) r = _m_psrlqi (t1, 19);
+ break;
+ case 20:
+ *(__m64 *) r = _m_psrlqi (t1, 20);
+ break;
+ case 21:
+ *(__m64 *) r = _m_psrlqi (t1, 21);
+ break;
+ case 22:
+ *(__m64 *) r = _m_psrlqi (t1, 22);
+ break;
+ case 23:
+ *(__m64 *) r = _m_psrlqi (t1, 23);
+ break;
+ case 24:
+ *(__m64 *) r = _m_psrlqi (t1, 24);
+ break;
+ case 25:
+ *(__m64 *) r = _m_psrlqi (t1, 25);
+ break;
+ case 26:
+ *(__m64 *) r = _m_psrlqi (t1, 26);
+ break;
+ case 27:
+ *(__m64 *) r = _m_psrlqi (t1, 27);
+ break;
+ case 28:
+ *(__m64 *) r = _m_psrlqi (t1, 28);
+ break;
+ case 29:
+ *(__m64 *) r = _m_psrlqi (t1, 29);
+ break;
+ case 30:
+ *(__m64 *) r = _m_psrlqi (t1, 30);
+ break;
+ case 31:
+ *(__m64 *) r = _m_psrlqi (t1, 31);
+ break;
+ case 32:
+ *(__m64 *) r = _m_psrlqi (t1, 32);
+ break;
+ case 33:
+ *(__m64 *) r = _m_psrlqi (t1, 33);
+ break;
+ case 34:
+ *(__m64 *) r = _m_psrlqi (t1, 34);
+ break;
+ case 35:
+ *(__m64 *) r = _m_psrlqi (t1, 35);
+ break;
+ case 36:
+ *(__m64 *) r = _m_psrlqi (t1, 36);
+ break;
+ case 37:
+ *(__m64 *) r = _m_psrlqi (t1, 37);
+ break;
+ case 38:
+ *(__m64 *) r = _m_psrlqi (t1, 38);
+ break;
+ case 39:
+ *(__m64 *) r = _m_psrlqi (t1, 39);
+ break;
+ case 40:
+ *(__m64 *) r = _m_psrlqi (t1, 40);
+ break;
+ case 41:
+ *(__m64 *) r = _m_psrlqi (t1, 41);
+ break;
+ case 42:
+ *(__m64 *) r = _m_psrlqi (t1, 42);
+ break;
+ case 43:
+ *(__m64 *) r = _m_psrlqi (t1, 43);
+ break;
+ case 44:
+ *(__m64 *) r = _m_psrlqi (t1, 44);
+ break;
+ case 45:
+ *(__m64 *) r = _m_psrlqi (t1, 45);
+ break;
+ case 46:
+ *(__m64 *) r = _m_psrlqi (t1, 46);
+ break;
+ case 47:
+ *(__m64 *) r = _m_psrlqi (t1, 47);
+ break;
+ case 48:
+ *(__m64 *) r = _m_psrlqi (t1, 48);
+ break;
+ case 49:
+ *(__m64 *) r = _m_psrlqi (t1, 49);
+ break;
+ case 50:
+ *(__m64 *) r = _m_psrlqi (t1, 50);
+ break;
+ case 51:
+ *(__m64 *) r = _m_psrlqi (t1, 51);
+ break;
+ case 52:
+ *(__m64 *) r = _m_psrlqi (t1, 52);
+ break;
+ case 53:
+ *(__m64 *) r = _m_psrlqi (t1, 53);
+ break;
+ case 54:
+ *(__m64 *) r = _m_psrlqi (t1, 54);
+ break;
+ case 55:
+ *(__m64 *) r = _m_psrlqi (t1, 55);
+ break;
+ case 56:
+ *(__m64 *) r = _m_psrlqi (t1, 56);
+ break;
+ case 57:
+ *(__m64 *) r = _m_psrlqi (t1, 57);
+ break;
+ case 58:
+ *(__m64 *) r = _m_psrlqi (t1, 58);
+ break;
+ case 59:
+ *(__m64 *) r = _m_psrlqi (t1, 59);
+ break;
+ case 60:
+ *(__m64 *) r = _m_psrlqi (t1, 60);
+ break;
+ case 61:
+ *(__m64 *) r = _m_psrlqi (t1, 61);
+ break;
+ case 62:
+ *(__m64 *) r = _m_psrlqi (t1, 62);
+ break;
+ case 63:
+ *(__m64 *) r = _m_psrlqi (t1, 63);
+ break;
+ default:
+ *(__m64 *) r = _m_psrlqi (t1, 64);
+ break;
+ }
+}
+
+/* Routine to manually compute the results */
+static void
+compute_correct_result (unsigned long long *src, unsigned int imm,
+ unsigned long long *res)
+{
+ int i;
+ if (imm > 63)
+ res[0] = 0;
+ else
+ res[0] = src[0] >> imm;
+}
+
+static void
+sse2_test (void)
+{
+ int i;
+ unsigned int count;
+ long long r, ck;
+ int fail = 0;
+
+ /* Run the MMX tests */
+ for (i = 0; i < MMX_num_ops; i++)
+ {
+ count = MMXops[i];
+ test_psllwi (&MMXops[i], count, &r);
+ compute_correct_result (&MMXops[i], count, &ck);
+ if (ck != r)
+ fail++;
+ }
+
+ if (fail != 0)
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.target/i386/sse2-mmx-psrlw.c b/gcc/testsuite/gcc.target/i386/sse2-mmx-psrlw.c
new file mode 100644
index 0000000..d2c1680
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/sse2-mmx-psrlw.c
@@ -0,0 +1,52 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -fno-strict-aliasing -msse2" } */
+/* { dg-additional-options "-mno-mmx" { target { ! ia32 } } } */
+
+#include "sse2-check.h"
+#include "mmx-vals.h"
+
+__attribute__((noinline, noclone))
+static void
+test_psrlw (long long *ll1, long long *ll2, long long *r)
+{
+ __m64 t1 = *(__m64 *) ll1;
+ __m64 t2 = *(__m64 *) ll2;
+ *(__m64 *) r = _m_psrlw (t1, t2);
+}
+
+/* Routine to manually compute the results */
+static void
+compute_correct_result (long long *dst_p, long long *src_p,
+ long long *res_p)
+{
+ short *dst = (short *) dst_p;
+ unsigned int *src = (unsigned int *) src_p;
+ short *res = (short *) res_p;
+ int i;
+ if (src[1] || src[0] > 15)
+ for (i = 0; i < 4; i++)
+ res[i] = 0;
+ else
+ for (i = 0; i < 4; i++)
+ res[i] = dst[i] >> src[0];
+}
+
+static void
+sse2_test (void)
+{
+ int i;
+ long long r, ck;
+ int fail = 0;
+
+ /* Run the MMX tests */
+ for (i = 0; i < MMX_num_ops; i += 2)
+ {
+ test_psrlw (&MMXops[i], &MMXops[i + 1], &r);
+ compute_correct_result (&MMXops[i], &MMXops[i + 1], &ck);
+ if (ck != r)
+ fail++;
+ }
+
+ if (fail != 0)
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.target/i386/sse2-mmx-psrlwi.c b/gcc/testsuite/gcc.target/i386/sse2-mmx-psrlwi.c
new file mode 100644
index 0000000..0dbffa5
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/sse2-mmx-psrlwi.c
@@ -0,0 +1,105 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -fno-strict-aliasing -msse2" } */
+/* { dg-additional-options "-mno-mmx" { target { ! ia32 } } } */
+
+#include "sse2-check.h"
+#include "mmx-vals.h"
+
+__attribute__((noinline, noclone))
+static void
+test_psrlwi (long long *ll1, unsigned int imm, long long *r)
+{
+ __m64 t1 = *(__m64 *) ll1;
+ switch (imm)
+ {
+ case 0:
+ *(__m64 *) r = _m_psrlwi (t1, 0);
+ break;
+ case 1:
+ *(__m64 *) r = _m_psrlwi (t1, 1);
+ break;
+ case 2:
+ *(__m64 *) r = _m_psrlwi (t1, 2);
+ break;
+ case 3:
+ *(__m64 *) r = _m_psrlwi (t1, 3);
+ break;
+ case 4:
+ *(__m64 *) r = _m_psrlwi (t1, 4);
+ break;
+ case 5:
+ *(__m64 *) r = _m_psrlwi (t1, 5);
+ break;
+ case 6:
+ *(__m64 *) r = _m_psrlwi (t1, 6);
+ break;
+ case 7:
+ *(__m64 *) r = _m_psrlwi (t1, 7);
+ break;
+ case 8:
+ *(__m64 *) r = _m_psrlwi (t1, 8);
+ break;
+ case 9:
+ *(__m64 *) r = _m_psrlwi (t1, 9);
+ break;
+ case 10:
+ *(__m64 *) r = _m_psrlwi (t1, 10);
+ break;
+ case 11:
+ *(__m64 *) r = _m_psrlwi (t1, 11);
+ break;
+ case 12:
+ *(__m64 *) r = _m_psrlwi (t1, 12);
+ break;
+ case 13:
+ *(__m64 *) r = _m_psrlwi (t1, 13);
+ break;
+ case 14:
+ *(__m64 *) r = _m_psrlwi (t1, 14);
+ break;
+ case 15:
+ *(__m64 *) r = _m_psrlwi (t1, 15);
+ break;
+ default:
+ *(__m64 *) r = _m_psrlwi (t1, 16);
+ break;
+ }
+}
+
+/* Routine to manually compute the results */
+static void
+compute_correct_result (long long *src_p, unsigned int imm,
+ long long *res_p)
+{
+ short *src = (short *) src_p;
+ short *res = (short *) res_p;
+ int i;
+ if (imm > 15)
+ for (i = 0; i < 4; i++)
+ res[i] = 0;
+ else
+ for (i = 0; i < 4; i++)
+ res[i] = src[i] >> imm;
+}
+
+static void
+sse2_test (void)
+{
+ int i;
+ unsigned int count;
+ long long r, ck;
+ int fail = 0;
+
+ /* Run the MMX tests */
+ for (i = 0; i < MMX_num_ops; i++)
+ {
+ count = MMXops[i];
+ test_psrlwi (&MMXops[i], count, &r);
+ compute_correct_result (&MMXops[i], count, &ck);
+ if (ck != r)
+ fail++;
+ }
+
+ if (fail != 0)
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.target/i386/sse2-mmx-psubb.c b/gcc/testsuite/gcc.target/i386/sse2-mmx-psubb.c
new file mode 100644
index 0000000..de0076a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/sse2-mmx-psubb.c
@@ -0,0 +1,48 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -fno-strict-aliasing -msse2" } */
+/* { dg-additional-options "-mno-mmx" { target { ! ia32 } } } */
+
+#include "sse2-check.h"
+#include "mmx-vals.h"
+
+__attribute__((noinline, noclone))
+static void
+test_psubb (long long *ll1, long long *ll2, long long *r)
+{
+ __m64 t1 = *(__m64 *) ll1;
+ __m64 t2 = *(__m64 *) ll2;
+ *(__m64 *) r = _m_psubb (t1, t2);
+}
+
+/* Routine to manually compute the results */
+static void
+compute_correct_result (long long *dst_p, long long *src_p,
+ long long *res_p)
+{
+ char *dst = (char *) dst_p;
+ char *src = (char *) src_p;
+ char *res = (char *) res_p;
+ int i;
+ for (i = 0; i < 8; i++)
+ res[i] = dst[i] - src[i];
+}
+
+static void
+sse2_test (void)
+{
+ int i;
+ long long r, ck;
+ int fail = 0;
+
+ /* Run the MMX tests */
+ for (i = 0; i < MMX_num_ops; i += 2)
+ {
+ test_psubb (&MMXops[i], &MMXops[i + 1], &r);
+ compute_correct_result (&MMXops[i], &MMXops[i + 1], &ck);
+ if (ck != r)
+ fail++;
+ }
+
+ if (fail != 0)
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.target/i386/sse2-mmx-psubd.c b/gcc/testsuite/gcc.target/i386/sse2-mmx-psubd.c
new file mode 100644
index 0000000..344f632
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/sse2-mmx-psubd.c
@@ -0,0 +1,48 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -fno-strict-aliasing -msse2" } */
+/* { dg-additional-options "-mno-mmx" { target { ! ia32 } } } */
+
+#include "sse2-check.h"
+#include "mmx-vals.h"
+
+__attribute__((noinline, noclone))
+static void
+test_psubd (long long *ll1, long long *ll2, long long *r)
+{
+ __m64 t1 = *(__m64 *) ll1;
+ __m64 t2 = *(__m64 *) ll2;
+ *(__m64 *) r = _m_psubd (t1, t2);
+}
+
+/* Routine to manually compute the results */
+static void
+compute_correct_result (long long *dst_p, long long *src_p,
+ long long *res_p)
+{
+ int *dst = (int *) dst_p;
+ int *src = (int *) src_p;
+ int *res = (int *) res_p;
+ int i;
+ for (i = 0; i < 2; i++)
+ res[i] = dst[i] - src[i];
+}
+
+static void
+sse2_test (void)
+{
+ int i;
+ long long r, ck;
+ int fail = 0;
+
+ /* Run the MMX tests */
+ for (i = 0; i < MMX_num_ops; i += 2)
+ {
+ test_psubd (&MMXops[i], &MMXops[i + 1], &r);
+ compute_correct_result (&MMXops[i], &MMXops[i + 1], &ck);
+ if (ck != r)
+ fail++;
+ }
+
+ if (fail != 0)
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.target/i386/sse2-mmx-psubq.c b/gcc/testsuite/gcc.target/i386/sse2-mmx-psubq.c
new file mode 100644
index 0000000..613f302
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/sse2-mmx-psubq.c
@@ -0,0 +1,43 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -fno-strict-aliasing -msse2" } */
+/* { dg-additional-options "-mno-mmx" { target { ! ia32 } } } */
+
+#include "sse2-check.h"
+#include "mmx-vals.h"
+
+__attribute__((noinline, noclone))
+static void
+test_psubq (long long *ll1, long long *ll2, long long *r)
+{
+ __m64 t1 = *(__m64 *) ll1;
+ __m64 t2 = *(__m64 *) ll2;
+ *(__m64 *) r = _mm_sub_si64 (t1, t2);
+}
+
+/* Routine to manually compute the results */
+static void
+compute_correct_result (long long *dst_p, long long *src_p,
+ long long *res_p)
+{
+ res_p[0] = dst_p[0] - src_p[0];
+}
+
+static void
+sse2_test (void)
+{
+ int i;
+ long long r, ck;
+ int fail = 0;
+
+ /* Run the MMX tests */
+ for (i = 0; i < MMX_num_ops; i += 2)
+ {
+ test_psubq (&MMXops[i], &MMXops[i + 1], &r);
+ compute_correct_result (&MMXops[i], &MMXops[i + 1], &ck);
+ if (ck != r)
+ fail++;
+ }
+
+ if (fail != 0)
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.target/i386/sse2-mmx-psubusb.c b/gcc/testsuite/gcc.target/i386/sse2-mmx-psubusb.c
new file mode 100644
index 0000000..ad6112a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/sse2-mmx-psubusb.c
@@ -0,0 +1,48 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -fno-strict-aliasing -msse2" } */
+/* { dg-additional-options "-mno-mmx" { target { ! ia32 } } } */
+
+#include "sse2-check.h"
+#include "mmx-vals.h"
+
+__attribute__((noinline, noclone))
+static void
+test_psubusb (long long *ll1, long long *ll2, long long *r)
+{
+ __m64 t1 = *(__m64 *) ll1;
+ __m64 t2 = *(__m64 *) ll2;
+ *(__m64 *) r = _m_psubusb (t1, t2);
+}
+
+/* Routine to manually compute the results */
+static void
+compute_correct_result (long long *dst_p, long long *src_p,
+ long long *res_p)
+{
+ unsigned char *dst = (unsigned char *) dst_p;
+ unsigned char *src = (unsigned char *) src_p;
+ unsigned char *res = (unsigned char *) res_p;
+ int i;
+ for (i = 0; i < 8; i++)
+ res[i] = saturate_ub (dst[i] - src[i]);
+}
+
+static void
+sse2_test (void)
+{
+ int i;
+ long long r, ck;
+ int fail = 0;
+
+ /* Run the MMX tests */
+ for (i = 0; i < MMX_num_ops; i += 2)
+ {
+ test_psubusb (&MMXops[i], &MMXops[i + 1], &r);
+ compute_correct_result (&MMXops[i], &MMXops[i + 1], &ck);
+ if (ck != r)
+ fail++;
+ }
+
+ if (fail != 0)
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.target/i386/sse2-mmx-psubusw.c b/gcc/testsuite/gcc.target/i386/sse2-mmx-psubusw.c
new file mode 100644
index 0000000..8a8a9c0
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/sse2-mmx-psubusw.c
@@ -0,0 +1,48 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -fno-strict-aliasing -msse2" } */
+/* { dg-additional-options "-mno-mmx" { target { ! ia32 } } } */
+
+#include "sse2-check.h"
+#include "mmx-vals.h"
+
+__attribute__((noinline, noclone))
+static void
+test_psubusw (long long *ll1, long long *ll2, long long *r)
+{
+ __m64 t1 = *(__m64 *) ll1;
+ __m64 t2 = *(__m64 *) ll2;
+ *(__m64 *) r = _m_psubusw (t1, t2);
+}
+
+/* Routine to manually compute the results */
+static void
+compute_correct_result (long long *dst_p, long long *src_p,
+ long long *res_p)
+{
+ unsigned short *dst = (unsigned short *) dst_p;
+ unsigned short *src = (unsigned short *) src_p;
+ unsigned short *res = (unsigned short *) res_p;
+ int i;
+ for (i = 0; i < 4; i++)
+ res[i] = saturate_uw (dst[i] - src[i]);
+}
+
+static void
+sse2_test (void)
+{
+ int i;
+ long long r, ck;
+ int fail = 0;
+
+ /* Run the MMX tests */
+ for (i = 0; i < MMX_num_ops; i += 2)
+ {
+ test_psubusw (&MMXops[i], &MMXops[i + 1], &r);
+ compute_correct_result (&MMXops[i], &MMXops[i + 1], &ck);
+ if (ck != r)
+ fail++;
+ }
+
+ if (fail != 0)
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.target/i386/sse2-mmx-psubw.c b/gcc/testsuite/gcc.target/i386/sse2-mmx-psubw.c
new file mode 100644
index 0000000..4d53c8c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/sse2-mmx-psubw.c
@@ -0,0 +1,48 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -fno-strict-aliasing -msse2" } */
+/* { dg-additional-options "-mno-mmx" { target { ! ia32 } } } */
+
+#include "sse2-check.h"
+#include "mmx-vals.h"
+
+__attribute__((noinline, noclone))
+static void
+test_psubw (long long *ll1, long long *ll2, long long *r)
+{
+ __m64 t1 = *(__m64 *) ll1;
+ __m64 t2 = *(__m64 *) ll2;
+ *(__m64 *) r = _m_psubw (t1, t2);
+}
+
+/* Routine to manually compute the results */
+static void
+compute_correct_result (long long *dst_p, long long *src_p,
+ long long *res_p)
+{
+ short *dst = (short *) dst_p;
+ short *src = (short *) src_p;
+ short *res = (short *) res_p;
+ int i;
+ for (i = 0; i < 4; i++)
+ res[i] = dst[i] - src[i];
+}
+
+static void
+sse2_test (void)
+{
+ int i;
+ long long r, ck;
+ int fail = 0;
+
+ /* Run the MMX tests */
+ for (i = 0; i < MMX_num_ops; i += 2)
+ {
+ test_psubw (&MMXops[i], &MMXops[i + 1], &r);
+ compute_correct_result (&MMXops[i], &MMXops[i + 1], &ck);
+ if (ck != r)
+ fail++;
+ }
+
+ if (fail != 0)
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.target/i386/sse2-mmx-punpckhbw.c b/gcc/testsuite/gcc.target/i386/sse2-mmx-punpckhbw.c
new file mode 100644
index 0000000..07281f2
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/sse2-mmx-punpckhbw.c
@@ -0,0 +1,53 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -fno-strict-aliasing -msse2" } */
+/* { dg-additional-options "-mno-mmx" { target { ! ia32 } } } */
+
+#include "sse2-check.h"
+#include "mmx-vals.h"
+
+__attribute__((noinline, noclone))
+static void
+test_punpckhbw (long long *ll1, long long *ll2, long long *r)
+{
+ __m64 t1 = *(__m64 *) ll1;
+ __m64 t2 = *(__m64 *) ll2;
+ *(__m64 *) r = _m_punpckhbw (t1, t2);
+}
+
+/* Routine to manually compute the results */
+static void
+compute_correct_result (long long *dst_p, long long *src_p,
+ long long *res_p)
+{
+ char *dst = (char *) dst_p;
+ char *src = (char *) src_p;
+ char *res = (char *) res_p;
+ res[0] = dst[4];
+ res[1] = src[4];
+ res[2] = dst[5];
+ res[3] = src[5];
+ res[4] = dst[6];
+ res[5] = src[6];
+ res[6] = dst[7];
+ res[7] = src[7];
+}
+
+static void
+sse2_test (void)
+{
+ int i;
+ long long r, ck;
+ int fail = 0;
+
+ /* Run the MMX tests */
+ for (i = 0; i < MMX_num_ops; i += 2)
+ {
+ test_punpckhbw (&MMXops[i], &MMXops[i + 1], &r);
+ compute_correct_result (&MMXops[i], &MMXops[i + 1], &ck);
+ if (ck != r)
+ fail++;
+ }
+
+ if (fail != 0)
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.target/i386/sse2-mmx-punpckhdq.c b/gcc/testsuite/gcc.target/i386/sse2-mmx-punpckhdq.c
new file mode 100644
index 0000000..6c67af9
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/sse2-mmx-punpckhdq.c
@@ -0,0 +1,47 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -fno-strict-aliasing -msse2" } */
+/* { dg-additional-options "-mno-mmx" { target { ! ia32 } } } */
+
+#include "sse2-check.h"
+#include "mmx-vals.h"
+
+__attribute__((noinline, noclone))
+static void
+test_punpckhdq (long long *ll1, long long *ll2, long long *r)
+{
+ __m64 t1 = *(__m64 *) ll1;
+ __m64 t2 = *(__m64 *) ll2;
+ *(__m64 *) r = _m_punpckhdq (t1, t2);
+}
+
+/* Routine to manually compute the results */
+static void
+compute_correct_result (long long *dst_p, long long *src_p,
+ long long *res_p)
+{
+ int *dst = (int *) dst_p;
+ int *src = (int *) src_p;
+ int *res = (int *) res_p;
+ res[0] = dst[1];
+ res[1] = src[1];
+}
+
+static void
+sse2_test (void)
+{
+ int i;
+ long long r, ck;
+ int fail = 0;
+
+ /* Run the MMX tests */
+ for (i = 0; i < MMX_num_ops; i += 2)
+ {
+ test_punpckhdq (&MMXops[i], &MMXops[i + 1], &r);
+ compute_correct_result (&MMXops[i], &MMXops[i + 1], &ck);
+ if (ck != r)
+ fail++;
+ }
+
+ if (fail != 0)
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.target/i386/sse2-mmx-punpckhwd.c b/gcc/testsuite/gcc.target/i386/sse2-mmx-punpckhwd.c
new file mode 100644
index 0000000..b6c3483
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/sse2-mmx-punpckhwd.c
@@ -0,0 +1,49 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -fno-strict-aliasing -msse2" } */
+/* { dg-additional-options "-mno-mmx" { target { ! ia32 } } } */
+
+#include "sse2-check.h"
+#include "mmx-vals.h"
+
+__attribute__((noinline, noclone))
+static void
+test_punpckhwd (long long *ll1, long long *ll2, long long *r)
+{
+ __m64 t1 = *(__m64 *) ll1;
+ __m64 t2 = *(__m64 *) ll2;
+ *(__m64 *) r = _m_punpckhwd (t1, t2);
+}
+
+/* Routine to manually compute the results */
+static void
+compute_correct_result (long long *dst_p, long long *src_p,
+ long long *res_p)
+{
+ short *dst = (short *) dst_p;
+ short *src = (short *) src_p;
+ short *res = (short *) res_p;
+ res[0] = dst[2];
+ res[1] = src[2];
+ res[2] = dst[3];
+ res[3] = src[3];
+}
+
+static void
+sse2_test (void)
+{
+ int i;
+ long long r, ck;
+ int fail = 0;
+
+ /* Run the MMX tests */
+ for (i = 0; i < MMX_num_ops; i += 2)
+ {
+ test_punpckhwd (&MMXops[i], &MMXops[i + 1], &r);
+ compute_correct_result (&MMXops[i], &MMXops[i + 1], &ck);
+ if (ck != r)
+ fail++;
+ }
+
+ if (fail != 0)
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.target/i386/sse2-mmx-punpcklbw.c b/gcc/testsuite/gcc.target/i386/sse2-mmx-punpcklbw.c
new file mode 100644
index 0000000..dcf6d3f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/sse2-mmx-punpcklbw.c
@@ -0,0 +1,53 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -fno-strict-aliasing -msse2" } */
+/* { dg-additional-options "-mno-mmx" { target { ! ia32 } } } */
+
+#include "sse2-check.h"
+#include "mmx-vals.h"
+
+__attribute__((noinline, noclone))
+static void
+test_punpcklbw (long long *ll1, long long *ll2, long long *r)
+{
+ __m64 t1 = *(__m64 *) ll1;
+ __m64 t2 = *(__m64 *) ll2;
+ *(__m64 *) r = _m_punpcklbw (t1, t2);
+}
+
+/* Routine to manually compute the results */
+static void
+compute_correct_result (long long *dst_p, long long *src_p,
+ long long *res_p)
+{
+ char *dst = (char *) dst_p;
+ char *src = (char *) src_p;
+ char *res = (char *) res_p;
+ res[0] = dst[0];
+ res[1] = src[0];
+ res[2] = dst[1];
+ res[3] = src[1];
+ res[4] = dst[2];
+ res[5] = src[2];
+ res[6] = dst[3];
+ res[7] = src[3];
+}
+
+static void
+sse2_test (void)
+{
+ int i;
+ long long r, ck;
+ int fail = 0;
+
+ /* Run the MMX tests */
+ for (i = 0; i < MMX_num_ops; i += 2)
+ {
+ test_punpcklbw (&MMXops[i], &MMXops[i + 1], &r);
+ compute_correct_result (&MMXops[i], &MMXops[i + 1], &ck);
+ if (ck != r)
+ fail++;
+ }
+
+ if (fail != 0)
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.target/i386/sse2-mmx-punpckldq.c b/gcc/testsuite/gcc.target/i386/sse2-mmx-punpckldq.c
new file mode 100644
index 0000000..463c6d2
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/sse2-mmx-punpckldq.c
@@ -0,0 +1,47 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -fno-strict-aliasing -msse2" } */
+/* { dg-additional-options "-mno-mmx" { target { ! ia32 } } } */
+
+#include "sse2-check.h"
+#include "mmx-vals.h"
+
+__attribute__((noinline, noclone))
+static void
+test_punpckldq (long long *ll1, long long *ll2, long long *r)
+{
+ __m64 t1 = *(__m64 *) ll1;
+ __m64 t2 = *(__m64 *) ll2;
+ *(__m64 *) r = _m_punpckldq (t1, t2);
+}
+
+/* Routine to manually compute the results */
+static void
+compute_correct_result (long long *dst_p, long long *src_p,
+ long long *res_p)
+{
+ int *dst = (int *) dst_p;
+ int *src = (int *) src_p;
+ int *res = (int *) res_p;
+ res[0] = dst[0];
+ res[1] = src[0];
+}
+
+static void
+sse2_test (void)
+{
+ int i;
+ long long r, ck;
+ int fail = 0;
+
+ /* Run the MMX tests */
+ for (i = 0; i < MMX_num_ops; i += 2)
+ {
+ test_punpckldq (&MMXops[i], &MMXops[i + 1], &r);
+ compute_correct_result (&MMXops[i], &MMXops[i + 1], &ck);
+ if (ck != r)
+ fail++;
+ }
+
+ if (fail != 0)
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.target/i386/sse2-mmx-punpcklwd.c b/gcc/testsuite/gcc.target/i386/sse2-mmx-punpcklwd.c
new file mode 100644
index 0000000..acd62f5
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/sse2-mmx-punpcklwd.c
@@ -0,0 +1,49 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -fno-strict-aliasing -msse2" } */
+/* { dg-additional-options "-mno-mmx" { target { ! ia32 } } } */
+
+#include "sse2-check.h"
+#include "mmx-vals.h"
+
+__attribute__((noinline, noclone))
+static void
+test_punpcklwd (long long *ll1, long long *ll2, long long *r)
+{
+ __m64 t1 = *(__m64 *) ll1;
+ __m64 t2 = *(__m64 *) ll2;
+ *(__m64 *) r = _m_punpcklwd (t1, t2);
+}
+
+/* Routine to manually compute the results */
+static void
+compute_correct_result (long long *dst_p, long long *src_p,
+ long long *res_p)
+{
+ short *dst = (short *) dst_p;
+ short *src = (short *) src_p;
+ short *res = (short *) res_p;
+ res[0] = dst[0];
+ res[1] = src[0];
+ res[2] = dst[1];
+ res[3] = src[1];
+}
+
+static void
+sse2_test (void)
+{
+ int i;
+ long long r, ck;
+ int fail = 0;
+
+ /* Run the MMX tests */
+ for (i = 0; i < MMX_num_ops; i += 2)
+ {
+ test_punpcklwd (&MMXops[i], &MMXops[i + 1], &r);
+ compute_correct_result (&MMXops[i], &MMXops[i + 1], &ck);
+ if (ck != r)
+ fail++;
+ }
+
+ if (fail != 0)
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.target/i386/sse2-mmx-pxor.c b/gcc/testsuite/gcc.target/i386/sse2-mmx-pxor.c
new file mode 100644
index 0000000..be63298
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/sse2-mmx-pxor.c
@@ -0,0 +1,44 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -fno-strict-aliasing -msse2" } */
+/* { dg-additional-options "-mno-mmx" { target { ! ia32 } } } */
+
+#include "sse2-check.h"
+#include "mmx-vals.h"
+
+__attribute__((noinline, noclone))
+static void
+test_pxor (long long *ll1, long long *ll2, long long *r)
+{
+ __m64 t1 = *(__m64 *) ll1;
+ __m64 t2 = *(__m64 *) ll2;
+ *(__m64 *) r = _m_pxor (t1, t2);
+}
+
+/* Routine to manually compute the results */
+static void
+compute_correct_result (unsigned long long *dst,
+ unsigned long long *src,
+ unsigned long long *res)
+{
+ res[0] = dst[0] ^ src[0];
+}
+
+static void
+sse2_test (void)
+{
+ int i;
+ long long r, ck;
+ int fail = 0;
+
+ /* Run the MMX tests */
+ for (i = 0; i < MMX_num_ops; i += 2)
+ {
+ test_pxor (&MMXops[i], &MMXops[i + 1], &r);
+ compute_correct_result (&MMXops[i], &MMXops[i + 1], &ck);
+ if (ck != r)
+ fail++;
+ }
+
+ if (fail != 0)
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.target/i386/sse2-vect-simd-10.c b/gcc/testsuite/gcc.target/i386/sse2-vect-simd-10.c
new file mode 100644
index 0000000..3cc182a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/sse2-vect-simd-10.c
@@ -0,0 +1,15 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -fopenmp-simd -msse2 -mno-sse3 -fdump-tree-vect-details" } */
+/* { dg-require-effective-target sse2 } */
+
+#include "sse2-check.h"
+
+#define main() do_main ()
+
+#include "../../gcc.dg/vect/vect-simd-10.c"
+
+static void
+sse2_test (void)
+{
+ do_main ();
+}
diff --git a/gcc/testsuite/gcc.target/i386/sse2-vect-simd-11.c b/gcc/testsuite/gcc.target/i386/sse2-vect-simd-11.c
new file mode 100644
index 0000000..aed43d5
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/sse2-vect-simd-11.c
@@ -0,0 +1,16 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -fopenmp-simd -msse2 -mno-sse3 -fdump-tree-vect-details" } */
+/* { dg-require-effective-target sse2 } */
+/* { dg-final { scan-tree-dump-times "vectorized \[1-3] loops" 2 "vect" } } */
+
+#include "sse2-check.h"
+
+#define main() do_main ()
+
+#include "../../gcc.dg/vect/vect-simd-11.c"
+
+static void
+sse2_test (void)
+{
+ do_main ();
+}
diff --git a/gcc/testsuite/gcc.target/i386/sse2-vect-simd-12.c b/gcc/testsuite/gcc.target/i386/sse2-vect-simd-12.c
new file mode 100644
index 0000000..e6f1591
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/sse2-vect-simd-12.c
@@ -0,0 +1,16 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -fopenmp-simd -msse2 -mno-sse3 -fdump-tree-vect-details" } */
+/* { dg-require-effective-target sse2 } */
+/* { dg-final { scan-tree-dump-times "vectorized \[1-3] loops" 2 "vect" } } */
+
+#include "sse2-check.h"
+
+#define main() do_main ()
+
+#include "../../gcc.dg/vect/vect-simd-12.c"
+
+static void
+sse2_test (void)
+{
+ do_main ();
+}
diff --git a/gcc/testsuite/gcc.target/i386/sse2-vect-simd-13.c b/gcc/testsuite/gcc.target/i386/sse2-vect-simd-13.c
new file mode 100644
index 0000000..5ad65b1
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/sse2-vect-simd-13.c
@@ -0,0 +1,16 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -fopenmp-simd -msse2 -mno-sse3 -fdump-tree-vect-details" } */
+/* { dg-require-effective-target sse2 } */
+/* { dg-final { scan-tree-dump-times "vectorized \[1-3] loops" 2 "vect" } } */
+
+#include "sse2-check.h"
+
+#define main() do_main ()
+
+#include "../../gcc.dg/vect/vect-simd-13.c"
+
+static void
+sse2_test (void)
+{
+ do_main ();
+}
diff --git a/gcc/testsuite/gcc.target/i386/sse2-vect-simd-14.c b/gcc/testsuite/gcc.target/i386/sse2-vect-simd-14.c
new file mode 100644
index 0000000..8274d42
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/sse2-vect-simd-14.c
@@ -0,0 +1,15 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -fopenmp-simd -msse2 -mno-sse3 -fdump-tree-vect-details" } */
+/* { dg-require-effective-target sse2 } */
+
+#include "sse2-check.h"
+
+#define main() do_main ()
+
+#include "../../gcc.dg/vect/vect-simd-14.c"
+
+static void
+sse2_test (void)
+{
+ do_main ();
+}
diff --git a/gcc/testsuite/gcc.target/i386/sse2-vect-simd-15.c b/gcc/testsuite/gcc.target/i386/sse2-vect-simd-15.c
new file mode 100644
index 0000000..8098d20
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/sse2-vect-simd-15.c
@@ -0,0 +1,16 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -fopenmp-simd -msse2 -mno-sse3 -fdump-tree-vect-details" } */
+/* { dg-require-effective-target sse2 } */
+/* { dg-final { scan-tree-dump-times "vectorized \[1-3] loops" 2 "vect" } } */
+
+#include "sse2-check.h"
+
+#define main() do_main ()
+
+#include "../../gcc.dg/vect/vect-simd-15.c"
+
+static void
+sse2_test (void)
+{
+ do_main ();
+}
diff --git a/gcc/testsuite/gcc.target/i386/sse2-vect-simd-8.c b/gcc/testsuite/gcc.target/i386/sse2-vect-simd-8.c
new file mode 100644
index 0000000..7c7aad8
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/sse2-vect-simd-8.c
@@ -0,0 +1,16 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -fopenmp-simd -msse2 -mno-sse3 -fdump-tree-vect-details" } */
+/* { dg-require-effective-target sse2 } */
+/* { dg-final { scan-tree-dump-times "vectorized \[1-3] loops" 2 "vect" } } */
+
+#include "sse2-check.h"
+
+#define main() do_main ()
+
+#include "../../gcc.dg/vect/vect-simd-8.c"
+
+static void
+sse2_test (void)
+{
+ do_main ();
+}
diff --git a/gcc/testsuite/gcc.target/i386/sse2-vect-simd-9.c b/gcc/testsuite/gcc.target/i386/sse2-vect-simd-9.c
new file mode 100644
index 0000000..0fdff41
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/sse2-vect-simd-9.c
@@ -0,0 +1,16 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -fopenmp-simd -msse2 -mno-sse3 -fdump-tree-vect-details" } */
+/* { dg-require-effective-target sse2 } */
+/* { dg-final { scan-tree-dump-times "vectorized \[1-3] loops" 2 "vect" } } */
+
+#include "sse2-check.h"
+
+#define main() do_main ()
+
+#include "../../gcc.dg/vect/vect-simd-9.c"
+
+static void
+sse2_test (void)
+{
+ do_main ();
+}
diff --git a/gcc/testsuite/gcc.target/i386/stack-prot-sym.c b/gcc/testsuite/gcc.target/i386/stack-prot-sym.c
index 7f63424..dcd7cbd 100644
--- a/gcc/testsuite/gcc.target/i386/stack-prot-sym.c
+++ b/gcc/testsuite/gcc.target/i386/stack-prot-sym.c
@@ -1,4 +1,5 @@
/* { dg-do compile } */
+/* { dg-require-effective-target tls_native } */
/* { dg-options "-O2 -fstack-protector-all -mstack-protector-guard=tls -mstack-protector-guard-reg=gs -mstack-protector-guard-symbol=my_guard" } */
void f(void) { }
diff --git a/gcc/testsuite/gcc.target/i386/stackalign/pr88483-1.c b/gcc/testsuite/gcc.target/i386/stackalign/pr88483-1.c
new file mode 100644
index 0000000..c8bb083
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/stackalign/pr88483-1.c
@@ -0,0 +1,18 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mavx2" } */
+
+struct B
+{
+ char a[12];
+ int b;
+};
+
+struct B
+f2 (void)
+{
+ struct B x = {};
+ return x;
+}
+
+/* { dg-final { scan-assembler-not "(sub|add)(l|q)\[\\t \]*\\$\[0-9\]*,\[\\t \]*%\[re\]?sp" } } */
+/* { dg-final { scan-assembler-not "and\[lq\]?\[^\\n\]*-\[0-9\]+,\[^\\n\]*sp" } } */
diff --git a/gcc/testsuite/gcc.target/i386/stackalign/pr88483-2.c b/gcc/testsuite/gcc.target/i386/stackalign/pr88483-2.c
new file mode 100644
index 0000000..e94fa1d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/stackalign/pr88483-2.c
@@ -0,0 +1,18 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mavx512f" } */
+
+struct B
+{
+ char a[12];
+ int b;
+};
+
+struct B
+f2 (void)
+{
+ struct B x = {};
+ return x;
+}
+
+/* { dg-final { scan-assembler-not "(sub|add)(l|q)\[\\t \]*\\$\[0-9\]*,\[\\t \]*%\[re\]?sp" } } */
+/* { dg-final { scan-assembler-not "and\[lq\]?\[^\\n\]*-\[0-9\]+,\[^\\n\]*sp" } } */
diff --git a/gcc/testsuite/gcc.target/i386/vect-double-1.c b/gcc/testsuite/gcc.target/i386/vect-double-1.c
index c44e669..180274c 100644
--- a/gcc/testsuite/gcc.target/i386/vect-double-1.c
+++ b/gcc/testsuite/gcc.target/i386/vect-double-1.c
@@ -1,6 +1,6 @@
/* { dg-do compile } */
/* { dg-skip-if "" { *-*-* } { "-march=*" } { "-march=core2" } } */
-/* { dg-options "-O2 -ftree-vectorize -mfpmath=sse -march=core2 -fdump-tree-vect-stats" } */
+/* { dg-options "-O2 -ftree-vectorize -fno-tree-loop-distribute-patterns -mfpmath=sse -march=core2 -fdump-tree-vect-stats" } */
/* { dg-add-options bind_pic_locally } */
extern void abort (void);
diff --git a/gcc/testsuite/gcc.target/i386/vect-double-2.c b/gcc/testsuite/gcc.target/i386/vect-double-2.c
index f6a4374..eea53bf 100644
--- a/gcc/testsuite/gcc.target/i386/vect-double-2.c
+++ b/gcc/testsuite/gcc.target/i386/vect-double-2.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -ftree-vectorize -mfpmath=sse -msse2 -mtune=atom -fdump-tree-vect-stats" } */
+/* { dg-options "-O2 -ftree-vectorize -fno-tree-loop-distribute-patterns -mfpmath=sse -msse2 -mtune=atom -fdump-tree-vect-stats" } */
extern void abort (void);
diff --git a/gcc/testsuite/gcc.target/i386/vect-signbitf.c b/gcc/testsuite/gcc.target/i386/vect-signbitf.c
new file mode 100644
index 0000000..81cae13
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/vect-signbitf.c
@@ -0,0 +1,30 @@
+/* { dg-do run { target sse2_runtime } } */
+/* { dg-options "-O2 -msse2 -ftree-vectorize -fdump-tree-vect-details -save-temps" } */
+
+extern void abort ();
+
+#define N 1024
+float a[N] = {0.0f, -0.0f, 1.0f, -1.0f,
+ -2.0f, 3.0f, -5.0f, -8.0f,
+ 13.0f, 21.0f, -25.0f, 33.0f};
+int r[N];
+
+int
+main (void)
+{
+ int i;
+
+ for (i = 0; i < N; i++)
+ r[i] = __builtin_signbitf (a[i]);
+
+ /* check results: */
+ for (i = 0; i < N; i++)
+ if (__builtin_signbitf (a[i]) && !r[i])
+ abort ();
+
+ return 0;
+}
+
+/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" } } */
+/* { dg-final { scan-assembler-not "\\$-2147483648" } } */
+/* { dg-final { scan-assembler "psrld" } } */
diff --git a/gcc/testsuite/gcc.target/i386/wbinvd-1.c b/gcc/testsuite/gcc.target/i386/wbinvd-1.c
index 7854cc2..9290d9b 100644
--- a/gcc/testsuite/gcc.target/i386/wbinvd-1.c
+++ b/gcc/testsuite/gcc.target/i386/wbinvd-1.c
@@ -1,6 +1,6 @@
/* { dg-do compile } */
/* { dg-options "-O2" } */
-/* { dg-final { scan-assembler-times "wbinvd" 2 } } */
+/* { dg-final { scan-assembler-times {\twbinvd} 1 } } */
#include "immintrin.h"
diff --git a/gcc/testsuite/gcc.target/i386/wbnoinvd-1.c b/gcc/testsuite/gcc.target/i386/wbnoinvd-1.c
index bda84cd..697f148 100644
--- a/gcc/testsuite/gcc.target/i386/wbnoinvd-1.c
+++ b/gcc/testsuite/gcc.target/i386/wbnoinvd-1.c
@@ -1,6 +1,6 @@
/* { dg-do compile } */
/* { dg-options "-O2 -mwbnoinvd" } */
-/* { dg-final { scan-assembler-times "wbnoinvd" 2 } } */
+/* { dg-final { scan-assembler-times {\twbnoinvd} 1 } } */
#include "x86intrin.h"
diff --git a/gcc/testsuite/gcc.target/mips/data-sym-multi-pool.c b/gcc/testsuite/gcc.target/mips/data-sym-multi-pool.c
new file mode 100644
index 0000000..1936f5b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/mips/data-sym-multi-pool.c
@@ -0,0 +1,45 @@
+/* { dg-do compile } */
+/* { dg-options "-mips16 -mcode-readable=yes" } */
+/* { dg-skip-if "per-function expected output" { *-*-* } { "-flto" } { "" } } */
+
+/* This testcase generates multiple constant pools within a function body. */
+
+#define C(a,b) \
+ if (a > b) goto gt; \
+ if (a < b) goto lt;
+
+#define C4(x,b) C((x)[0], b) C((x)[1],b) C((x)[2],b) C((x)[3],b)
+#define C16(x,y) C4(x, (y)[0]) C4(x, (y)[1]) C4(x, (y)[2]) C4(x, (y)[3])
+
+#define C64(x,y) C16(x,y) C16(x+4,y) C16(x+8,y)
+#define C256(x,y) C64(x,y) C64(x,y+4) C64(x,y+8)
+
+unsigned foo(int x[64], int y[64])
+{
+ C256(x,y);
+
+ return 0x01234567;
+ gt:
+ return 0x12345678;
+ lt:
+ return 0xF0123456;
+}
+
+/* Check that:
+1. The __pend symbol is emitted as STT_FUNCTION followed by instructions:
+ .type __pend_frob_<X>, @function # Symbol # must match label.
+__pend_foo_<X>: # The symbol must match.
+ .insn
+.L<Y>:
+
+2. __pend symbol at end of function has type STT_OBJECT
+
+ .type __pend_foo_<X>, @object
+__pend_foo_<X>:
+ .insn
+ .end foo
+
+ */
+
+/* { dg-final { scan-assembler "\t\\.type\t(__pend_foo_\[0-9\]+), @function\n\\1:\n\t\\.insn\n.L\[0-9\]+:\n" } } */
+/* { dg-final { scan-assembler "\t\\.type\t(__pend_foo_\[0-9\]+), @object\n\\1:\n\t\\.end\tfoo\n" } } */
diff --git a/gcc/testsuite/gcc.target/mips/data-sym-pool.c b/gcc/testsuite/gcc.target/mips/data-sym-pool.c
index 8776d2b..f093511 100644
--- a/gcc/testsuite/gcc.target/mips/data-sym-pool.c
+++ b/gcc/testsuite/gcc.target/mips/data-sym-pool.c
@@ -16,9 +16,8 @@ __pool_frob_3: # The symbol must match.
.align 2
$L3: # The label must match.
.word 305419896
- .type __pend_frob_3, @function # Symbol # must match label.
+ .type __pend_frob_3, @object # Symbol # must match label.
__pend_frob_3: # The symbol must match.
- .insn
that is `__pool_*'/`__pend_*' symbols inserted around a constant pool.
@@ -26,4 +25,4 @@ __pend_frob_3: # The symbol must match.
symbol from being placed in the constant pool at `-O0' for SVR4 code
and consequently interfering with test expectations. */
-/* { dg-final { scan-assembler "\tl\[wd\]\t\\\$\[0-9\]+,(.L(\[0-9\]+))\n.*\t\\.type\t(__pool_frob_\\2), @object\n\\3:\n\t\\.align\t2\n\\1:\n\t\\.d?word\t305419896\n\t\\.type\t(__pend_frob_\\2), @function\n\\4:\n\t\\.insn\n" } } */
+/* { dg-final { scan-assembler "\tl\[wd\]\t\\\$\[0-9\]+,(.L(\[0-9\]+))\n.*\t\\.type\t(__pool_frob_\\2), @object\n\\3:\n\t\\.align\t2\n\\1:\n\t\\.d?word\t305419896\n\t\\.type\t(__pend_frob_\\2), @object\n\\4:\n" } } */
diff --git a/gcc/testsuite/gcc.target/mips/dwarfregtable-1.c b/gcc/testsuite/gcc.target/mips/dwarfregtable-1.c
new file mode 100644
index 0000000..93d0844
--- /dev/null
+++ b/gcc/testsuite/gcc.target/mips/dwarfregtable-1.c
@@ -0,0 +1,5 @@
+/* Check if content of dwarf reg size table matches the expected. */
+/* { dg-do run } */
+/* { dg-options "-mabi=32 -mfp32" } */
+
+#include "dwarfregtable.h"
diff --git a/gcc/testsuite/gcc.target/mips/dwarfregtable-2.c b/gcc/testsuite/gcc.target/mips/dwarfregtable-2.c
new file mode 100644
index 0000000..c6dea94
--- /dev/null
+++ b/gcc/testsuite/gcc.target/mips/dwarfregtable-2.c
@@ -0,0 +1,5 @@
+/* Check if content of dwarf reg size table matches the expected. */
+/* { dg-do run } */
+/* { dg-options "-mabi=32 -mfpxx" } */
+
+#include "dwarfregtable.h"
diff --git a/gcc/testsuite/gcc.target/mips/dwarfregtable-3.c b/gcc/testsuite/gcc.target/mips/dwarfregtable-3.c
new file mode 100644
index 0000000..87937c4
--- /dev/null
+++ b/gcc/testsuite/gcc.target/mips/dwarfregtable-3.c
@@ -0,0 +1,5 @@
+/* Check if content of dwarf reg size table matches the expected. */
+/* { dg-do run } */
+/* { dg-options "-mabi=32 -mfp64" } */
+
+#include "dwarfregtable.h"
diff --git a/gcc/testsuite/gcc.target/mips/dwarfregtable-4.c b/gcc/testsuite/gcc.target/mips/dwarfregtable-4.c
new file mode 100644
index 0000000..2dd6dea
--- /dev/null
+++ b/gcc/testsuite/gcc.target/mips/dwarfregtable-4.c
@@ -0,0 +1,5 @@
+/* Check if content of dwarf reg size table matches the expected. */
+/* { dg-do run } */
+/* { dg-options "-mabi=32 -mfp64 -modd-spreg" } */
+
+#include "dwarfregtable.h"
diff --git a/gcc/testsuite/gcc.target/mips/dwarfregtable.h b/gcc/testsuite/gcc.target/mips/dwarfregtable.h
new file mode 100644
index 0000000..403f65f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/mips/dwarfregtable.h
@@ -0,0 +1,22 @@
+
+typedef unsigned Unwind_Word __attribute__((__mode__(__unwind_word__)));
+
+#define DWARF_FRAME_REGISTERS 188
+
+static unsigned char ref_dwarf_reg_size_table[DWARF_FRAME_REGISTERS + 1] =
+ {
+ [0 ... 66] = sizeof (Unwind_Word),
+ [80 ... 181] = sizeof (Unwind_Word)
+ };
+
+static unsigned char dwarf_reg_size_table[DWARF_FRAME_REGISTERS + 1] = {};
+
+int
+main (void)
+{
+ __builtin_init_dwarf_reg_size_table (dwarf_reg_size_table);
+ if (__builtin_memcmp (ref_dwarf_reg_size_table,
+ dwarf_reg_size_table, DWARF_FRAME_REGISTERS + 1) != 0)
+ __builtin_abort ();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/mips/msa-fmadd.c b/gcc/testsuite/gcc.target/mips/msa-fmadd.c
new file mode 100644
index 0000000..9265c04
--- /dev/null
+++ b/gcc/testsuite/gcc.target/mips/msa-fmadd.c
@@ -0,0 +1,101 @@
+/* { dg-do compile } */
+/* { dg-options "-mfp64 -mhard-float -mmsa -EL -flax-vector-conversions" } */
+/* { dg-skip-if "uses global registers" { *-*-* } { "-O0" } { "" } } */
+
+typedef int v4i32 __attribute__ ((vector_size(16)));
+typedef float v4f32 __attribute__ ((vector_size(16)));
+typedef double v2f64 __attribute__ ((vector_size(16)));
+
+/* Test that MSA FMADD-like intrinsics do not use first operand for multiplication. */
+
+register v4i32 a __asm__("$f20");
+register v4i32 b __asm__("$f22");
+register v4f32 c __asm__("$f24");
+register v4f32 d __asm__("$f26");
+register v2f64 e __asm__("$f28");
+register v2f64 f __asm__("$f30");
+
+void
+maddv_b_msa (void)
+{
+ a = __builtin_msa_maddv_b (a, b, b);
+}
+/* { dg-final { scan-assembler "maddv\\\.b\t\\\$w20,\\\$w22,\\\$w22" } } */
+
+void
+maddv_h_msa (void)
+{
+ a = __builtin_msa_maddv_h (a, b, b);
+}
+/* { dg-final { scan-assembler "maddv\\\.h\t\\\$w20,\\\$w22,\\\$w22" } } */
+
+void
+maddv_w_msa (void)
+{
+ a = __builtin_msa_maddv_w (a, b, b);
+}
+/* { dg-final { scan-assembler "maddv\\\.w\t\\\$w20,\\\$w22,\\\$w22" } } */
+
+void
+maddv_d_msa (void)
+{
+ a = __builtin_msa_maddv_d (a, b, b);
+}
+/* { dg-final { scan-assembler "maddv\\\.d\t\\\$w20,\\\$w22,\\\$w22" } } */
+
+void
+msubv_b_msa (void)
+{
+ a = __builtin_msa_msubv_b (a, b, b);
+}
+/* { dg-final { scan-assembler "msubv\\\.b\t\\\$w20,\\\$w22,\\\$w22" } } */
+
+void
+msubv_h_msa (void)
+{
+ a = __builtin_msa_msubv_h (a, b, b);
+}
+/* { dg-final { scan-assembler "msubv\\\.h\t\\\$w20,\\\$w22,\\\$w22" } } */
+
+void
+msubv_w_msa (void)
+{
+ a = __builtin_msa_msubv_w (a, b, b);
+}
+/* { dg-final { scan-assembler "msubv\\\.w\t\\\$w20,\\\$w22,\\\$w22" } } */
+
+void
+msubv_d_msa (void)
+{
+ a = __builtin_msa_msubv_d (a, b, b);
+}
+/* { dg-final { scan-assembler "msubv\\\.d\t\\\$w20,\\\$w22,\\\$w22" } } */
+
+void
+fmadd_w_msa (void)
+{
+ c = __builtin_msa_fmadd_w (c, d, d);
+}
+/* { dg-final { scan-assembler "fmadd\\\.w\t\\\$w24,\\\$w26,\\\$w26" } } */
+
+void
+fmadd_d_msa (void)
+{
+ e = __builtin_msa_fmadd_d (e, f, f);
+}
+/* { dg-final { scan-assembler "fmadd\\\.d\t\\\$w28,\\\$w30,\\\$w30" } } */
+
+void
+fmsub_w_msa (void)
+{
+ c = __builtin_msa_fmsub_w (c, d, d);
+}
+/* { dg-final { scan-assembler "fmsub\\\.w\t\\\$w24,\\\$w26,\\\$w26" } } */
+
+void
+fmsub_d_msa (void)
+{
+ e = __builtin_msa_fmsub_d (e, f, f);
+}
+/* { dg-final { scan-assembler "fmsub\\\.d\t\\\$w28,\\\$w30,\\\$w30" } } */
+
diff --git a/gcc/testsuite/gcc.target/msp430/emulate-slli.c b/gcc/testsuite/gcc.target/msp430/emulate-slli.c
new file mode 100644
index 0000000..0ed09d5
--- /dev/null
+++ b/gcc/testsuite/gcc.target/msp430/emulate-slli.c
@@ -0,0 +1,15 @@
+/* { dg-do compile } */
+/* { dg-options "-Os" } */
+/* { dg-final { scan-assembler-not "mspabi_slli" } } */
+/* { dg-final { scan-assembler "rlax" } } */
+
+/* Ensure that HImode shifts with source operand in memory are emulated with a
+ rotate instructions. */
+
+int a;
+
+void
+foo (void)
+{
+ a = a << 4;
+}
diff --git a/gcc/testsuite/gcc.target/msp430/emulate-srai.c b/gcc/testsuite/gcc.target/msp430/emulate-srai.c
new file mode 100644
index 0000000..6629171
--- /dev/null
+++ b/gcc/testsuite/gcc.target/msp430/emulate-srai.c
@@ -0,0 +1,15 @@
+/* { dg-do compile } */
+/* { dg-options "-Os" } */
+/* { dg-final { scan-assembler-not "mspabi_srai" } } */
+/* { dg-final { scan-assembler "rrax" } } */
+
+/* Ensure that HImode shifts with source operand in memory are emulated with a
+ rotate instructions. */
+
+int a;
+
+void
+foo (void)
+{
+ a = a >> 4;
+}
diff --git a/gcc/testsuite/gcc.target/msp430/emulate-srli.c b/gcc/testsuite/gcc.target/msp430/emulate-srli.c
new file mode 100644
index 0000000..c10f30b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/msp430/emulate-srli.c
@@ -0,0 +1,15 @@
+/* { dg-do compile } */
+/* { dg-options "-Os" } */
+/* { dg-final { scan-assembler-not "mspabi_srli" } } */
+/* { dg-final { scan-assembler "rrum" } } */
+
+/* Ensure that HImode shifts with source operand in memory are emulated with a
+ rotate instructions. */
+
+unsigned int a;
+
+void
+foo (void)
+{
+ a = a >> 4;
+}
diff --git a/gcc/testsuite/gcc.target/msp430/mlarge-pedwarns.c b/gcc/testsuite/gcc.target/msp430/mlarge-pedwarns.c
new file mode 100644
index 0000000..a16f533
--- /dev/null
+++ b/gcc/testsuite/gcc.target/msp430/mlarge-pedwarns.c
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-skip-if "" { "*-*-*" } { "-mcpu=msp430" } { "" } } */
+/* { dg-options "-mlarge -pedantic-errors" } */
+
+/* Ensure the use of builtin macros that contain __int20__ in their
+ expansion don't cause ISO C errors when -pedantic-errors is passed. */
+
+__SIZE_TYPE__ a;
+__INTPTR_TYPE__ b;
+__UINTPTR_TYPE__ c;
+__PTRDIFF_TYPE__ d;
diff --git a/gcc/testsuite/gcc.target/msp430/mspabi_sllll.c b/gcc/testsuite/gcc.target/msp430/mspabi_sllll.c
new file mode 100644
index 0000000..b88a8be
--- /dev/null
+++ b/gcc/testsuite/gcc.target/msp430/mspabi_sllll.c
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { dg-final { scan-assembler-not "ashldi3" } } */
+/* { dg-final { scan-assembler "__mspabi_sllll" } } */
+
+long long
+foo (long long a)
+{
+ return a << 4;
+}
+
diff --git a/gcc/testsuite/gcc.target/msp430/mspabi_srall.c b/gcc/testsuite/gcc.target/msp430/mspabi_srall.c
new file mode 100644
index 0000000..a0aba3d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/msp430/mspabi_srall.c
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { dg-final { scan-assembler-not "ashrdi3" } } */
+/* { dg-final { scan-assembler "__mspabi_srall" } } */
+
+long long
+foo (long long a)
+{
+ return a >> 4;
+}
+
diff --git a/gcc/testsuite/gcc.target/msp430/mspabi_srlll.c b/gcc/testsuite/gcc.target/msp430/mspabi_srlll.c
new file mode 100644
index 0000000..cb9a374
--- /dev/null
+++ b/gcc/testsuite/gcc.target/msp430/mspabi_srlll.c
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { dg-final { scan-assembler-not "lshrdi3" } } */
+/* { dg-final { scan-assembler "__mspabi_srlll" } } */
+
+unsigned long long
+foo (unsigned long long a)
+{
+ return a >> 4;
+}
+
diff --git a/gcc/testsuite/gcc.target/msp430/size-optimized-shifts.c b/gcc/testsuite/gcc.target/msp430/size-optimized-shifts.c
new file mode 100644
index 0000000..be9509b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/msp430/size-optimized-shifts.c
@@ -0,0 +1,26 @@
+/* { dg-do compile } */
+/* { dg-options "-Os" } */
+/* { dg-final { scan-assembler-not "__mspabi_sral_4" } } */
+/* { dg-final { scan-assembler-not "__mspabi_srll_4" } } */
+/* { dg-final { scan-assembler-not "__mspabi_slll_4" } } */
+/* { dg-final { scan-assembler "__mspabi_sral" } } */
+/* { dg-final { scan-assembler "__mspabi_srll" } } */
+/* { dg-final { scan-assembler "__mspabi_slll" } } */
+
+/* Ensure that SImode shifts by a constant amount do not use the const_variant
+ of the shift library code when optimizing for size. */
+
+long a;
+long b;
+long c;
+long d;
+unsigned long e;
+unsigned long f;
+
+void
+foo (void)
+{
+ a = b >> 4;
+ c = d << 4;
+ e = f >> 4;
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/bfp/bfp.exp b/gcc/testsuite/gcc.target/powerpc/bfp/bfp.exp
index 54df989..ca6779a 100644
--- a/gcc/testsuite/gcc.target/powerpc/bfp/bfp.exp
+++ b/gcc/testsuite/gcc.target/powerpc/bfp/bfp.exp
@@ -16,9 +16,11 @@
# along with GCC; see the file COPYING3. If not see
# <http://www.gnu.org/licenses/>.
-# Exit immediately if this isn't a PowerPC target or if the target is aix.
+# Exit immediately if this isn't a PowerPC target or if the target is
+# aix or Darwin.
if { (![istarget powerpc*-*-*] && ![istarget rs6000-*-*])
- || [istarget "powerpc*-*-aix*"] } then {
+ || [istarget "powerpc*-*-aix*"]
+ || [istarget "powerpc*-*-darwin*"] } then {
return
}
diff --git a/gcc/testsuite/gcc.target/powerpc/builtins-1.c b/gcc/testsuite/gcc.target/powerpc/builtins-1.c
index 8263e28..73f8fb5 100644
--- a/gcc/testsuite/gcc.target/powerpc/builtins-1.c
+++ b/gcc/testsuite/gcc.target/powerpc/builtins-1.c
@@ -330,10 +330,10 @@ int main ()
/* { dg-final { scan-assembler-times "divd" 8 { target lp64 } } } */
/* { dg-final { scan-assembler-times "divdu" 2 { target lp64 } } } */
/* { dg-final { scan-assembler-times "mulld" 4 { target lp64 } } } */
-/* check for both .__divdi3 (AIX) and __divdi3 (Linux) */
-/* { dg-final { scan-assembler-times {\mbl \.?__divdi3\M} 2 { target { ilp32 } } } } */
-/* check for both .__udivdi3 (AIX) and __udivdi3 (Linux) */
-/* { dg-final { scan-assembler-times {\mbl \.?__udivdi3\M} 2 { target { ilp32 } } } } */
+/* check for .__divdi3 (AIX), __divdi3 (Linux) and ___divdi3 (Darwin) */
+/* { dg-final { scan-assembler-times {\mbl \.?_?__divdi3\M} 2 { target { ilp32 } } } } */
+/* check for both .__udivdi3 (AIX), __udivdi3 (Linux) and ___udivdi3 (Darwin) */
+/* { dg-final { scan-assembler-times {\mbl \.?_?__udivdi3\M} 2 { target { ilp32 } } } } */
/* { dg-final { scan-assembler-times "mullw" 12 { target ilp32 } } } */
/* { dg-final { scan-assembler-times "mulhwu" 4 { target ilp32 } } } */
/* { dg-final { scan-assembler-times "xxmrgld" 0 } } */
diff --git a/gcc/testsuite/gcc.target/powerpc/builtins-2.c b/gcc/testsuite/gcc.target/powerpc/builtins-2.c
index bf3347a..0fa60b2 100644
--- a/gcc/testsuite/gcc.target/powerpc/builtins-2.c
+++ b/gcc/testsuite/gcc.target/powerpc/builtins-2.c
@@ -1,4 +1,5 @@
/* { dg-do run { target { powerpc*-*-* } } } */
+/* { dg-require-effective-target vsx_hw } */
/* { dg-options "-mdejagnu-cpu=power8 " } */
#include <altivec.h>
diff --git a/gcc/testsuite/gcc.target/powerpc/cpu-future.c b/gcc/testsuite/gcc.target/powerpc/cpu-future.c
new file mode 100644
index 0000000..ae406d0
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/cpu-future.c
@@ -0,0 +1,7 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target powerpc_future_ok } */
+/* { dg-options "-mdejagnu-cpu=future -O2" } */
+
+/* Ensure -mcpu=future compiles cleanly. */
+
+void x (void) { }
diff --git a/gcc/testsuite/gcc.target/powerpc/darwin-bool-1.c b/gcc/testsuite/gcc.target/powerpc/darwin-bool-1.c
index 2f147d0..f444edf 100644
--- a/gcc/testsuite/gcc.target/powerpc/darwin-bool-1.c
+++ b/gcc/testsuite/gcc.target/powerpc/darwin-bool-1.c
@@ -1,6 +1,8 @@
/* Check that sizeof(bool) is 4 if we don't use special options. */
/* Matt Austern <austern@apple.com> */
/* { dg-do run { target { powerpc*-*-darwin* && ilp32 } } } */
+/* We do need to suppress the ISO C doesn't support _Bool message tho. */
+/* { dg-options "-Wno-pedantic" } */
int dummy1[sizeof(_Bool) - 3];
int dummy2[5 - sizeof(_Bool)];
diff --git a/gcc/testsuite/gcc.target/powerpc/dfp/dfp.exp b/gcc/testsuite/gcc.target/powerpc/dfp/dfp.exp
index 7a34471..ea0211a 100644
--- a/gcc/testsuite/gcc.target/powerpc/dfp/dfp.exp
+++ b/gcc/testsuite/gcc.target/powerpc/dfp/dfp.exp
@@ -16,8 +16,11 @@
# along with GCC; see the file COPYING3. If not see
# <http://www.gnu.org/licenses/>.
-# Exit immediately if this isn't a PowerPC target.
-if { ![istarget powerpc*-*-*] && ![istarget rs6000-*-*] } then {
+# Exit immediately if this isn't a PowerPC target, also exit if we
+# are on Darwin which doesn't support decimal float.
+if { (![istarget powerpc*-*-*] && ![istarget rs6000-*-*])
+ || [istarget "powerpc*-*-darwin*"]
+} then {
return
}
diff --git a/gcc/testsuite/gcc.target/powerpc/direct-move-double1.c b/gcc/testsuite/gcc.target/powerpc/direct-move-double1.c
index 0c00a59..13f0192 100644
--- a/gcc/testsuite/gcc.target/powerpc/direct-move-double1.c
+++ b/gcc/testsuite/gcc.target/powerpc/direct-move-double1.c
@@ -11,6 +11,5 @@
#define TYPE double
#define IS_FLOAT 1
#define NO_ALTIVEC 1
-#define VSX_REG_ATTR "ws"
#include "direct-move.h"
diff --git a/gcc/testsuite/gcc.target/powerpc/direct-move-double2.c b/gcc/testsuite/gcc.target/powerpc/direct-move-double2.c
index dae7e85..23e3423 100644
--- a/gcc/testsuite/gcc.target/powerpc/direct-move-double2.c
+++ b/gcc/testsuite/gcc.target/powerpc/direct-move-double2.c
@@ -10,6 +10,5 @@
#define IS_FLOAT 1
#define NO_ALTIVEC 1
#define DO_MAIN
-#define VSX_REG_ATTR "ws"
#include "direct-move.h"
diff --git a/gcc/testsuite/gcc.target/powerpc/direct-move-float1.c b/gcc/testsuite/gcc.target/powerpc/direct-move-float1.c
index 1bd1f14..63ab591 100644
--- a/gcc/testsuite/gcc.target/powerpc/direct-move-float1.c
+++ b/gcc/testsuite/gcc.target/powerpc/direct-move-float1.c
@@ -13,6 +13,5 @@
#define TYPE float
#define IS_FLOAT 1
#define NO_ALTIVEC 1
-#define VSX_REG_ATTR "ww"
#include "direct-move.h"
diff --git a/gcc/testsuite/gcc.target/powerpc/direct-move-float2.c b/gcc/testsuite/gcc.target/powerpc/direct-move-float2.c
index e24f7fa..666b292 100644
--- a/gcc/testsuite/gcc.target/powerpc/direct-move-float2.c
+++ b/gcc/testsuite/gcc.target/powerpc/direct-move-float2.c
@@ -10,6 +10,5 @@
#define IS_FLOAT 1
#define NO_ALTIVEC 1
#define DO_MAIN
-#define VSX_REG_ATTR "ww"
#include "direct-move.h"
diff --git a/gcc/testsuite/gcc.target/powerpc/direct-move-vint1.c b/gcc/testsuite/gcc.target/powerpc/direct-move-vint1.c
index 1de15d1..fa9d660 100644
--- a/gcc/testsuite/gcc.target/powerpc/direct-move-vint1.c
+++ b/gcc/testsuite/gcc.target/powerpc/direct-move-vint1.c
@@ -9,6 +9,5 @@
/* Check code generation for direct move for vector types. */
#define TYPE vector int
-#define VSX_REG_ATTR "wa"
#include "direct-move.h"
diff --git a/gcc/testsuite/gcc.target/powerpc/direct-move-vint2.c b/gcc/testsuite/gcc.target/powerpc/direct-move-vint2.c
index 8618a55..b813ad4 100644
--- a/gcc/testsuite/gcc.target/powerpc/direct-move-vint2.c
+++ b/gcc/testsuite/gcc.target/powerpc/direct-move-vint2.c
@@ -8,6 +8,5 @@
#define TYPE vector int
#define DO_MAIN
-#define VSX_REG_ATTR "wa"
#include "direct-move.h"
diff --git a/gcc/testsuite/gcc.target/powerpc/fold-vec-splats-floatdouble.c b/gcc/testsuite/gcc.target/powerpc/fold-vec-splats-floatdouble.c
index c4544f1..3c7cc7c 100644
--- a/gcc/testsuite/gcc.target/powerpc/fold-vec-splats-floatdouble.c
+++ b/gcc/testsuite/gcc.target/powerpc/fold-vec-splats-floatdouble.c
@@ -8,20 +8,20 @@
#include <altivec.h>
vector float
-test1d (float x)
+test1f (float x)
{
return vec_splats (x);
}
vector double
-test1f (double x)
+test1d (double x)
{
return vec_splats (x);
}
-// float test generates the permute instruction.
+// double test generates the permute instruction.
/* { dg-final { scan-assembler-times "xxpermdi" 1 } } */
-// double test generates a convert (double to single non-signalling) followed by a splat.
+// float test generates a convert (double to single non-signalling) followed by a splat.
/* { dg-final { scan-assembler-times {\mxscvdpspn?\M} 1 } } */
/* { dg-final { scan-assembler-times {\mvspltw\M|\mxxspltw\M} 1 } } */
diff --git a/gcc/testsuite/gcc.target/powerpc/localentry-1.c b/gcc/testsuite/gcc.target/powerpc/localentry-1.c
new file mode 100644
index 0000000..068b0c0
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/localentry-1.c
@@ -0,0 +1,20 @@
+/* { dg-do compile } */
+/* { dg-options "-mdejagnu-cpu=future -O2 -mpcrel" } */
+/* { dg-require-effective-target powerpc_elfv2 } */
+/* { dg-require-effective-target powerpc_future_ok } */
+
+/* Ensure we generate ".localentry fn,1" for both leaf and non-leaf functions.
+ At present, -mcpu=future does not enable pc-relative mode, so make sure we
+ enable it to be able to check for .localentry. */
+
+extern int y (int);
+
+int x (void)
+{
+ return y (5);
+}
+
+void z (void) { };
+
+/* { dg-final { scan-assembler {\.localentry\t\mx,1\M} } } */
+/* { dg-final { scan-assembler {\.localentry\t\mz,1\M} } } */
diff --git a/gcc/testsuite/gcc.target/powerpc/localentry-detect-1.c b/gcc/testsuite/gcc.target/powerpc/localentry-detect-1.c
new file mode 100644
index 0000000..e67e7f8
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/localentry-detect-1.c
@@ -0,0 +1,15 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target powerpc_elfv2 } */
+/* { dg-require-effective-target powerpc_future_ok } */
+/* { dg-options "-O2 -mdejagnu-cpu=future" } */
+
+/* At present, -mcpu=future does not enable pc-relative mode. Enable it here
+ explicitly until it is turned on by default. */
+#pragma GCC target ("cpu=future,pcrel")
+int localentry1 () { return 5; }
+
+#pragma GCC target ("cpu=power9,no-pcrel")
+int localentry2 () { return 5; }
+
+/* { dg-final { scan-assembler {\.localentry\tlocalentry1,1\M} } } */
+/* { dg-final { scan-assembler-not {\.localentry\tlocalentry2,1\M} } } */
diff --git a/gcc/testsuite/gcc.target/powerpc/maddld-1.c b/gcc/testsuite/gcc.target/powerpc/maddld-1.c
new file mode 100644
index 0000000..4edecf1
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/maddld-1.c
@@ -0,0 +1,21 @@
+/* { dg-do compile } */
+/* { dg-options "-mdejagnu-cpu=power9 -O2" } */
+
+/* This file tests the maddld instruction can be used in SI mode
+ on power9 machine. */
+
+int
+s_madd (int a, int b, int c)
+{
+ return (a * b) + c;
+}
+
+unsigned int
+u_madd (unsigned int a, unsigned int b, unsigned int c)
+{
+ return (a * b) + c;
+}
+
+/* { dg-final { scan-assembler-times {\mmaddld\s} 2 } } */
+/* { dg-final { scan-assembler-not {\mmul} } } */
+/* { dg-final { scan-assembler-not {\madd} } } */
diff --git a/gcc/testsuite/gcc.target/powerpc/mmfpgpr.c b/gcc/testsuite/gcc.target/powerpc/mmfpgpr.c
deleted file mode 100644
index d7063a4..0000000
--- a/gcc/testsuite/gcc.target/powerpc/mmfpgpr.c
+++ /dev/null
@@ -1,22 +0,0 @@
-/* { dg-do compile { target { powerpc*-*-* && lp64 } } } */
-/* { dg-skip-if "" { powerpc*-*-darwin* } } */
-/* { dg-require-effective-target powerpc_vsx_ok } */
-/* { dg-options "-O2 -mdejagnu-cpu=power6x -mmfpgpr" } */
-/* { dg-final { scan-assembler "mffgpr" } } */
-/* { dg-final { scan-assembler "mftgpr" } } */
-
-/* Test that we generate the instructions to move between the GPR and FPR
- registers under power6x. */
-
-extern long return_long (void);
-extern double return_double (void);
-
-double return_double2 (void)
-{
- return (double) return_long ();
-}
-
-long return_long2 (void)
-{
- return (long) return_double ();
-}
diff --git a/gcc/testsuite/gcc.target/powerpc/notoc-direct-1.c b/gcc/testsuite/gcc.target/powerpc/notoc-direct-1.c
new file mode 100644
index 0000000..8603ff7
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/notoc-direct-1.c
@@ -0,0 +1,43 @@
+/* { dg-do compile } */
+/* { dg-options "-mdejagnu-cpu=future -O2 -mpcrel" } */
+/* { dg-require-effective-target powerpc_elfv2 } */
+/* { dg-require-effective-target powerpc_future_ok } */
+
+/* Test that calls generated from PC-relative code are annotated with @notoc.
+ At present, -mcpu=future does not enable pc-relative mode. Enable it here
+ explicitly until it is turned on by default. */
+
+extern int yy0 (int);
+extern void yy1 (int);
+
+int zz0 (void) __attribute__((noinline));
+void zz1 (int) __attribute__((noinline));
+
+int xx (void)
+{
+ yy1 (7);
+ return yy0 (5);
+}
+
+int zz0 ()
+{
+ asm ("");
+ return 16;
+};
+
+void zz1 (int a __attribute__((__unused__)))
+{
+ asm ("");
+};
+
+int ww (void)
+{
+ zz1 (zz0 ());
+ return 4;
+}
+
+/* { dg-final { scan-assembler {yy1@notoc} } } */
+/* { dg-final { scan-assembler {yy0@notoc} } } */
+/* { dg-final { scan-assembler {zz1@notoc} } } */
+/* { dg-final { scan-assembler {zz0@notoc} } } */
+
diff --git a/gcc/testsuite/gcc.target/powerpc/p9-dimode1.c b/gcc/testsuite/gcc.target/powerpc/p9-dimode1.c
index 424ddb5..b2cd3d6 100644
--- a/gcc/testsuite/gcc.target/powerpc/p9-dimode1.c
+++ b/gcc/testsuite/gcc.target/powerpc/p9-dimode1.c
@@ -1,21 +1,17 @@
-/* { dg-do compile { target { powerpc64*-*-* && lp64 } } } */
+/* { dg-do compile { target { powerpc*-*-* } } } */
/* { dg-require-effective-target powerpc_p9vector_ok } */
/* { dg-options "-mdejagnu-cpu=power9 -O2" } */
/* Verify P9 changes to allow DImode into Altivec registers, and generate
constants using XXSPLTIB. */
-#ifndef _ARCH_PPC64
-#error "This code is 64-bit."
-#endif
-
double
p9_zero (void)
{
long l = 0;
double ret;
- __asm__ ("xxlor %x0,%x1,%x1" : "=&d" (ret) : "wi" (l));
+ __asm__ ("xxlor %x0,%x1,%x1" : "=&d" (ret) : "wa" (l));
return ret;
}
@@ -26,7 +22,7 @@ p9_plus_1 (void)
long l = 1;
double ret;
- __asm__ ("xxlor %x0,%x1,%x1" : "=&d" (ret) : "wi" (l));
+ __asm__ ("xxlor %x0,%x1,%x1" : "=&d" (ret) : "wa" (l));
return ret;
}
@@ -37,13 +33,13 @@ p9_minus_1 (void)
long l = -1;
double ret;
- __asm__ ("xxlor %x0,%x1,%x1" : "=&d" (ret) : "wi" (l));
+ __asm__ ("xxlor %x0,%x1,%x1" : "=&d" (ret) : "wa" (l));
return ret;
}
/* { dg-final { scan-assembler {\mxxspltib\M} } } */
-/* { dg-final { scan-assembler-not {\mmtvsrd\M} } } */
+/* { dg-final { scan-assembler-not {\mmtvsr} } } */
/* { dg-final { scan-assembler-not {\mlfd\M} } } */
/* { dg-final { scan-assembler-not {\mld\M} } } */
/* { dg-final { scan-assembler-not {\mlxsd\M} } } */
diff --git a/gcc/testsuite/gcc.target/powerpc/p9-dimode2.c b/gcc/testsuite/gcc.target/powerpc/p9-dimode2.c
index dc3c360..c2196a2 100644
--- a/gcc/testsuite/gcc.target/powerpc/p9-dimode2.c
+++ b/gcc/testsuite/gcc.target/powerpc/p9-dimode2.c
@@ -1,13 +1,9 @@
-/* { dg-do compile { target { powerpc64*-*-* && lp64 } } } */
+/* { dg-do compile { target { powerpc*-*-* } } } */
/* { dg-require-effective-target powerpc_p9vector_ok } */
/* { dg-options "-mdejagnu-cpu=power9 -O2" } */
-/* Verify that large integer constants are loaded via direct move instead of being
- loaded from memory. */
-
-#ifndef _ARCH_PPC64
-#error "This code is 64-bit."
-#endif
+/* Verify that large integer constants are loaded via direct move instead of
+ being loaded from memory. */
double
p9_large (void)
@@ -15,12 +11,12 @@ p9_large (void)
long l = 0x12345678;
double ret;
- __asm__ ("xxlor %x0,%x1,%x1" : "=&d" (ret) : "wi" (l));
+ __asm__ ("xxlor %x0,%x1,%x1" : "=&d" (ret) : "wa" (l));
return ret;
}
-/* { dg-final { scan-assembler {\mmtvsrd\M} } } */
+/* { dg-final { scan-assembler {\mmtvsr} } } */
/* { dg-final { scan-assembler-not {\mld\M} } } */
/* { dg-final { scan-assembler-not {\mlfd\M} } } */
/* { dg-final { scan-assembler-not {\mlxsd\M} } } */
diff --git a/gcc/testsuite/gcc.target/powerpc/pcrel-sibcall-1.c b/gcc/testsuite/gcc.target/powerpc/pcrel-sibcall-1.c
new file mode 100644
index 0000000..0cb40d4
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/pcrel-sibcall-1.c
@@ -0,0 +1,50 @@
+/* { dg-do compile } */
+/* { dg-options "-mdejagnu-cpu=future -O2" } */
+/* { dg-require-effective-target powerpc_elfv2 } */
+/* { dg-require-effective-target powerpc_future_ok } */
+
+/* Test that potential sibcalls are not generated when the caller preserves the
+ TOC and the callee doesn't, or vice versa. At present, -mcpu=future does
+ not enable pc-relative mode. Enable it here explicitly until it is turned
+ on by default. */
+
+#pragma GCC target ("cpu=future,pcrel")
+int x (void) __attribute__((noinline));
+int y (void) __attribute__((noinline));
+int xx (void) __attribute__((noinline));
+
+int x (void)
+{
+ return 1;
+}
+
+int y (void)
+{
+ return 2;
+}
+
+int sib_call (void)
+{
+ return x ();
+}
+
+#pragma GCC target ("cpu=power9,no-pcrel")
+int normal_call (void)
+{
+ return y ();
+}
+
+int xx (void)
+{
+ return 1;
+}
+
+#pragma GCC target ("cpu=future,pcrel")
+int notoc_call (void)
+{
+ return xx ();
+}
+
+/* { dg-final { scan-assembler {\mb x@notoc\M} } } */
+/* { dg-final { scan-assembler {\mbl y\M} } } */
+/* { dg-final { scan-assembler {\mbl xx@notoc\M} } } */
diff --git a/gcc/testsuite/gcc.target/powerpc/ppc32-abi-dfp-1.c b/gcc/testsuite/gcc.target/powerpc/ppc32-abi-dfp-1.c
index 14908db..eea7f6f 100644
--- a/gcc/testsuite/gcc.target/powerpc/ppc32-abi-dfp-1.c
+++ b/gcc/testsuite/gcc.target/powerpc/ppc32-abi-dfp-1.c
@@ -45,14 +45,14 @@ __asm__ ("\t.globl\t" #NAME "_asm\n\t" \
#NAME "_asm:\n\t" \
"lis 11,gparms@ha\n\t" \
"la 11,gparms@l(11)\n\t" \
- "st 3,0(11)\n\t" \
- "st 4,4(11)\n\t" \
- "st 5,8(11)\n\t" \
- "st 6,12(11)\n\t" \
- "st 7,16(11)\n\t" \
- "st 8,20(11)\n\t" \
- "st 9,24(11)\n\t" \
- "st 10,28(11)\n\t" \
+ "stw 3,0(11)\n\t" \
+ "stw 4,4(11)\n\t" \
+ "stw 5,8(11)\n\t" \
+ "stw 6,12(11)\n\t" \
+ "stw 7,16(11)\n\t" \
+ "stw 8,20(11)\n\t" \
+ "stw 9,24(11)\n\t" \
+ "stw 10,28(11)\n\t" \
"stfd 1,32(11)\n\t" \
"stfd 2,40(11)\n\t" \
"stfd 3,48(11)\n\t" \
diff --git a/gcc/testsuite/gcc.target/powerpc/ppc64-abi-warn-1.c b/gcc/testsuite/gcc.target/powerpc/ppc64-abi-warn-1.c
index c70c14c..ae7d574 100644
--- a/gcc/testsuite/gcc.target/powerpc/ppc64-abi-warn-1.c
+++ b/gcc/testsuite/gcc.target/powerpc/ppc64-abi-warn-1.c
@@ -6,7 +6,7 @@ struct f8
float x[8];
};
-void test (struct f8 a, struct f8 b) /* { dg-message "note: the ABI of passing homogeneous float aggregates has changed" } */
+void test (struct f8 a, struct f8 b) /* { dg-message "note: the ABI of passing homogeneous 'float' aggregates has changed" } */
{
}
diff --git a/gcc/testsuite/gcc.target/powerpc/pr62147.c b/gcc/testsuite/gcc.target/powerpc/pr62147.c
new file mode 100644
index 0000000..635c737
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/pr62147.c
@@ -0,0 +1,24 @@
+/* { dg-do compile { target { powerpc*-*-* } } } */
+/* { dg-options "-O2 -fno-tree-loop-distribute-patterns" } */
+
+/* Note that it's required to disable loop-distribute-patterns, otherwise the
+ loop will be optimized to memset. */
+
+/* Expect loop_iv can know the loop is finite so the doloop_optimize
+ can perform the doloop transformation. */
+
+typedef struct {
+ int l;
+ int b[258];
+} S;
+
+void clear (S* s )
+{
+ int i;
+ int len = s->l + 1;
+
+ for (i = 0; i <= len; i++)
+ s->b[i] = 0;
+}
+
+/* { dg-final { scan-assembler {\mbdnz\M} } } */
diff --git a/gcc/testsuite/gcc.target/powerpc/pr64205.c b/gcc/testsuite/gcc.target/powerpc/pr64205.c
index 3882e3f..c726fb7 100644
--- a/gcc/testsuite/gcc.target/powerpc/pr64205.c
+++ b/gcc/testsuite/gcc.target/powerpc/pr64205.c
@@ -1,4 +1,5 @@
/* { dg-do compile { target { powerpc*-*-* && ilp32 } } } */
+/* { dg-require-effective-target dfp } */
/* { dg-skip-if "" { powerpc*-*-aix* } } */
/* { dg-options "-O2 -mdejagnu-cpu=G5 -maltivec" } */
diff --git a/gcc/testsuite/gcc.target/powerpc/pr71785.c b/gcc/testsuite/gcc.target/powerpc/pr71785.c
index 613dcd1..c667ad8 100644
--- a/gcc/testsuite/gcc.target/powerpc/pr71785.c
+++ b/gcc/testsuite/gcc.target/powerpc/pr71785.c
@@ -1,6 +1,11 @@
/* { dg-do compile { target { powerpc*-*-* } } } */
/* { dg-options "-O2" } */
-/* { dg-final { scan-assembler-not {\mb\M} } } */
+/* We have to lose the default pic codegen on Darwin. */
+/* { dg-additional-options "-mdynamic-no-pic" { target powerpc*-*-darwin* } } */
+/* ... and account for the out-of-line GPR restore. */
+/* { dg-final { scan-assembler-times {\mb[ \t]*restGPR} 1 { target powerpc*-*-darwin* } } } */
+/* { dg-final { scan-assembler-not {\mb[ \t]L} { target powerpc*-*-darwin* } } } */
+/* { dg-final { scan-assembler-not {\mb\M} { target { ! powerpc*-*-darwin* } } } } */
/* Check that all computed gotos in this testcase end up unfactored completely.
If some is not there will be a unconditional jump left; if all works fine,
diff --git a/gcc/testsuite/gcc.target/powerpc/pr79909.c b/gcc/testsuite/gcc.target/powerpc/pr79909.c
index d9fb7c3..d886c32 100644
--- a/gcc/testsuite/gcc.target/powerpc/pr79909.c
+++ b/gcc/testsuite/gcc.target/powerpc/pr79909.c
@@ -1,6 +1,7 @@
/* PR rtl-optimization/79909 */
/* { dg-do compile } */
/* { dg-options "-O2 -mxl-compat" } */
+/* { dg-require-effective-target dfp } */
/* { dg-skip-if "DFP" { powerpc*-*-aix* } } */
typedef float T __attribute__ ((mode (TD)));
diff --git a/gcc/testsuite/gcc.target/powerpc/pr80125.c b/gcc/testsuite/gcc.target/powerpc/pr80125.c
index 494a6e6..366602d 100644
--- a/gcc/testsuite/gcc.target/powerpc/pr80125.c
+++ b/gcc/testsuite/gcc.target/powerpc/pr80125.c
@@ -16,7 +16,7 @@ foo ()
vector int k = vec_mergel (i, j);
vector int l = vec_sl (k, c);
vector int m = vec_sl (l, d);
- vector char o;
+ vector unsigned char o;
vector int p = vec_perm (m, n, o);
e = vec_sra (p, c);
vec_st (e, 0, a);
diff --git a/gcc/testsuite/gcc.target/powerpc/pr80315-1.c b/gcc/testsuite/gcc.target/powerpc/pr80315-1.c
index d0fb6dc..e2db0ff 100644
--- a/gcc/testsuite/gcc.target/powerpc/pr80315-1.c
+++ b/gcc/testsuite/gcc.target/powerpc/pr80315-1.c
@@ -10,6 +10,6 @@ main()
int mask;
/* Argument 2 must be 0 or 1. Argument 3 must be in range 0..15. */
- res = __builtin_crypto_vshasigmaw (test, 1, 0xff); /* { dg-error "argument 3 must be in the range 0..15" } */
+ res = __builtin_crypto_vshasigmaw (test, 1, 0xff); /* { dg-error {argument 3 must be in the range \[0, 15\]} } */
return 0;
}
diff --git a/gcc/testsuite/gcc.target/powerpc/pr80315-2.c b/gcc/testsuite/gcc.target/powerpc/pr80315-2.c
index 30df7f1..144b705 100644
--- a/gcc/testsuite/gcc.target/powerpc/pr80315-2.c
+++ b/gcc/testsuite/gcc.target/powerpc/pr80315-2.c
@@ -10,6 +10,6 @@ main ()
int mask;
/* Argument 2 must be 0 or 1. Argument 3 must be in range 0..15. */
- res = __builtin_crypto_vshasigmad (test, 1, 0xff); /* { dg-error "argument 3 must be in the range 0..15" } */
+ res = __builtin_crypto_vshasigmad (test, 1, 0xff); /* { dg-error {argument 3 must be in the range \[0, 15\]} } */
return 0;
}
diff --git a/gcc/testsuite/gcc.target/powerpc/pr80315-3.c b/gcc/testsuite/gcc.target/powerpc/pr80315-3.c
index 5365f1d..99a3e24 100644
--- a/gcc/testsuite/gcc.target/powerpc/pr80315-3.c
+++ b/gcc/testsuite/gcc.target/powerpc/pr80315-3.c
@@ -12,6 +12,6 @@ main ()
int mask;
/* Argument 2 must be 0 or 1. Argument 3 must be in range 0..15. */
- res = vec_shasigma_be (test, 1, 0xff); /* { dg-error "argument 3 must be in the range 0..15" } */
+ res = vec_shasigma_be (test, 1, 0xff); /* { dg-error {argument 3 must be in the range \[0, 15\]} } */
return res;
}
diff --git a/gcc/testsuite/gcc.target/powerpc/pr80315-4.c b/gcc/testsuite/gcc.target/powerpc/pr80315-4.c
index eb51363..7f5f6f7 100644
--- a/gcc/testsuite/gcc.target/powerpc/pr80315-4.c
+++ b/gcc/testsuite/gcc.target/powerpc/pr80315-4.c
@@ -12,6 +12,6 @@ main ()
int mask;
/* Argument 2 must be 0 or 1. Argument 3 must be in range 0..15. */
- res = vec_shasigma_be (test, 1, 0xff); /* { dg-error "argument 3 must be in the range 0..15" } */
+ res = vec_shasigma_be (test, 1, 0xff); /* { dg-error {argument 3 must be in the range \[0, 15\]} } */
return res;
}
diff --git a/gcc/testsuite/gcc.target/powerpc/safe-indirect-jump-1.c b/gcc/testsuite/gcc.target/powerpc/safe-indirect-jump-1.c
index 16ccfe4..b9ad8c1 100644
--- a/gcc/testsuite/gcc.target/powerpc/safe-indirect-jump-1.c
+++ b/gcc/testsuite/gcc.target/powerpc/safe-indirect-jump-1.c
@@ -1,4 +1,5 @@
/* { dg-do compile } */
+/* { dg-skip-if "not implemented for Darwin" { powerpc*-*-darwin* } } */
/* { dg-additional-options "-mno-speculate-indirect-jumps" } */
/* { dg-warning "'-mno-speculate-indirect-jumps' is deprecated" "" { target *-*-* } 0 } */
diff --git a/gcc/testsuite/gcc.target/powerpc/safe-indirect-jump-7.c b/gcc/testsuite/gcc.target/powerpc/safe-indirect-jump-7.c
index e7d81d4..a316e66 100644
--- a/gcc/testsuite/gcc.target/powerpc/safe-indirect-jump-7.c
+++ b/gcc/testsuite/gcc.target/powerpc/safe-indirect-jump-7.c
@@ -1,4 +1,5 @@
/* { dg-do compile } */
+/* { dg-skip-if "not implemented for Darwin" { powerpc*-*-darwin* } } */
/* { dg-additional-options "-mno-speculate-indirect-jumps" } */
/* { dg-warning "'-mno-speculate-indirect-jumps' is deprecated" "" { target *-*-* } 0 } */
diff --git a/gcc/testsuite/gcc.target/powerpc/spec-barr-1.c b/gcc/testsuite/gcc.target/powerpc/spec-barr-1.c
index a22bf58..d837515 100644
--- a/gcc/testsuite/gcc.target/powerpc/spec-barr-1.c
+++ b/gcc/testsuite/gcc.target/powerpc/spec-barr-1.c
@@ -6,4 +6,4 @@ void foo ()
__builtin_ppc_speculation_barrier ();
}
-/* { dg-final { scan-assembler "ori 31,31,0" } } */
+/* { dg-final { scan-assembler {ori\s+r?31,r?31,r?0} } } */
diff --git a/gcc/testsuite/gcc.target/powerpc/vsx-vectorize-1.c b/gcc/testsuite/gcc.target/powerpc/vsx-vectorize-1.c
index c3d4b8a..686638f 100644
--- a/gcc/testsuite/gcc.target/powerpc/vsx-vectorize-1.c
+++ b/gcc/testsuite/gcc.target/powerpc/vsx-vectorize-1.c
@@ -1,7 +1,7 @@
/* { dg-do compile { target { powerpc*-*-* && lp64 } } } */
/* { dg-skip-if "" { powerpc*-*-darwin* } } */
/* { dg-require-effective-target powerpc_vsx_ok } */
-/* { dg-options "-mdejagnu-cpu=power7 -O2 -ftree-vectorize -fno-vect-cost-model -fdump-tree-vect-details" } */
+/* { dg-options "-mdejagnu-cpu=power7 -O2 -ftree-vectorize -fno-tree-loop-distribute-patterns -fno-vect-cost-model -fdump-tree-vect-details" } */
/* Taken from vect/vect-align-1.c. */
#include <stdlib.h>
diff --git a/gcc/testsuite/gcc.target/powerpc/warn-lvsl-lvsr.c b/gcc/testsuite/gcc.target/powerpc/warn-lvsl-lvsr.c
index bf889aa..62b37a9 100644
--- a/gcc/testsuite/gcc.target/powerpc/warn-lvsl-lvsr.c
+++ b/gcc/testsuite/gcc.target/powerpc/warn-lvsl-lvsr.c
@@ -9,6 +9,6 @@ float f[20];
void foo ()
{
- vector unsigned char a = vec_lvsl (4, f); /* { dg-warning "vec_lvsl is deprecated for little endian; use assignment for unaligned loads and stores" } */
- vector unsigned char b = vec_lvsr (8, f); /* { dg-warning "vec_lvsr is deprecated for little endian; use assignment for unaligned loads and stores" } */
+ vector unsigned char a = vec_lvsl (4, f); /* { dg-warning "'vec_lvsl' is deprecated for little endian; use assignment for unaligned loads and stores" } */
+ vector unsigned char b = vec_lvsr (8, f); /* { dg-warning "'vec_lvsr' is deprecated for little endian; use assignment for unaligned loads and stores" } */
}
diff --git a/gcc/testsuite/gcc.target/pru/abi-arg-struct.c b/gcc/testsuite/gcc.target/pru/abi-arg-struct.c
new file mode 100644
index 0000000..186074b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/pru/abi-arg-struct.c
@@ -0,0 +1,164 @@
+/* Test call argument ABI: passing structs */
+
+/* { dg-do run } */
+
+#include <stdarg.h>
+
+extern void abort (void);
+
+struct S3 { char a[3]; };
+struct S7 { char a[7]; };
+struct S8 { char a[8]; };
+
+struct S3 gs3 = {{11, 22, 33}};
+struct S7 gs7 = {{1, 2, 3, 4, 5, 6, 7}};
+struct S8 gs8 = {{1, 2, 3, 4, 5, 6, 7, 8}};
+
+int test3_struct(char a0, char a1, char a2, char a3,
+ char a4, char a5, char a6, char a7,
+ char a8, char a9, char a10, char a11,
+ int ai)
+{
+ if (a0 != 11) return 1;
+ if (a1 != 22) return 2;
+ if (a2 != 33) return 3;
+ if (a4 != 101) return 4;
+ if (a5 != 111) return 5;
+ if (a6 != 121) return 6;
+ if (a8 != 55) return 8;
+ if (a9 != 66) return 9;
+ if (a10 != 77) return 10;
+
+ if (ai != 55443322) return 100;
+
+ return 0;
+}
+
+void test3(void)
+{
+ struct S3 s3x = { {101, 111, 121} };
+ struct S3 s3y = { {55, 66, 77} };
+
+ int (* volatile f)(struct S3, struct S3, struct S3, int) =
+ (int (* volatile)(struct S3, struct S3, struct S3, int)) test3_struct;
+
+ if (f(gs3, s3x, s3y, 55443322))
+ abort();
+}
+
+int test7_struct(unsigned ai, struct S7 a0, ...)
+{
+ va_list ap;
+ struct S7 s[3];
+ int i;
+
+ va_start (ap, a0);
+
+ s[0] = a0;
+ for (i = 1; i < 3; i++) {
+ s[i] = va_arg (ap, struct S7);
+ }
+
+ va_end (ap);
+
+ if (ai != 0xaabbccdd)
+ return 1;
+
+ if (s[0].a[0] != 1) return 1;
+ if (s[0].a[1] != 2) return 1;
+ if (s[0].a[2] != 3) return 1;
+ if (s[0].a[3] != 4) return 1;
+ if (s[0].a[4] != 5) return 1;
+ if (s[0].a[5] != 6) return 1;
+ if (s[0].a[6] != 7) return 1;
+
+ if (s[1].a[0] != 11) return 1;
+ if (s[1].a[1] != 12) return 1;
+ if (s[1].a[2] != 13) return 1;
+ if (s[1].a[3] != 14) return 1;
+ if (s[1].a[4] != 15) return 1;
+ if (s[1].a[5] != 16) return 1;
+ if (s[1].a[6] != 17) return 1;
+
+ if (s[2].a[0] != 22) return 1;
+ if (s[2].a[1] != 23) return 1;
+ if (s[2].a[2] != 24) return 1;
+ if (s[2].a[3] != 25) return 1;
+ if (s[2].a[4] != 26) return 1;
+ if (s[2].a[5] != 27) return 1;
+ if (s[2].a[6] != 28) return 1;
+
+ return 0;
+}
+
+void test7(void)
+{
+ struct S7 s7x = { {11, 12, 13, 14, 15, 16, 17} };
+ struct S7 s7y = { {22, 23, 24, 25, 26, 27, 28} };
+
+ int (* volatile f)(unsigned, struct S7, struct S7, struct S7) =
+ (int (* volatile)(unsigned, struct S7, struct S7, struct S7)) test7_struct;
+
+ if (f(0xaabbccdd, gs7, s7x, s7y))
+ abort();
+}
+
+int test8_struct(char a0, char a1, char a2, char a3,
+ char a4, char a5, char a6, char a7,
+ char a8, char a9, char a10, char a11,
+ char a12, char a13, char a14, char a15,
+ char a16, char a17, char a18, char a19,
+ char a20, char a21, char a22, char a23)
+{
+ if (a0 != 1) return 1;
+ if (a1 != 2) return 1;
+ if (a2 != 3) return 1;
+ if (a3 != 4) return 1;
+ if (a4 != 5) return 1;
+ if (a5 != 6) return 1;
+ if (a6 != 7) return 1;
+ if (a7 != 8) return 1;
+
+ if (a8 != 11) return 1;
+ if (a9 != 12) return 1;
+ if (a10 != 13) return 1;
+ if (a11 != 14) return 1;
+ if (a12 != 15) return 1;
+ if (a13 != 16) return 1;
+ if (a14 != 17) return 1;
+ if (a15 != 18) return 1;
+
+ if (a16 != 22) return 1;
+ if (a17 != 23) return 1;
+ if (a18 != 24) return 1;
+ if (a19 != 25) return 1;
+ if (a20 != 26) return 1;
+ if (a21 != 27) return 1;
+ if (a22 != 28) return 1;
+ if (a23 != 29) return 1;
+
+ return 0;
+}
+
+void test8(void)
+{
+ struct S8 s8x = { {11, 12, 13, 14, 15, 16, 17, 18} };
+ struct S8 s8y = { {22, 23, 24, 25, 26, 27, 28, 29} };
+
+ int (* volatile f)(struct S8, struct S8, struct S8) =
+ (int (* volatile)(struct S8, struct S8, struct S8)) test8_struct;
+
+ if (f(gs8, s8x, s8y))
+ abort();
+}
+
+int
+main (int argc, char** argv)
+{
+ test3();
+ test7();
+ test8();
+
+ return 0;
+}
+
diff --git a/gcc/testsuite/gcc.target/pru/ashiftrt.c b/gcc/testsuite/gcc.target/pru/ashiftrt.c
new file mode 100644
index 0000000..ee8d55d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/pru/ashiftrt.c
@@ -0,0 +1,13 @@
+/* Test shift optimization */
+
+/* { dg-options "-O1" } */
+
+/* -O1 in the options is significant. */
+
+extern void func2(unsigned char);
+
+void test(unsigned char v)
+{
+ /* { dg-final { scan-assembler "lsl\tr14.b0, r14.b0, .\+\n\tlsr\tr14.b0, r14.b0" } } */
+ func2((v & 2) ? 1 : 0);
+}
diff --git a/gcc/testsuite/gcc.target/pru/builtins-1.c b/gcc/testsuite/gcc.target/pru/builtins-1.c
new file mode 100644
index 0000000..7b7472b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/pru/builtins-1.c
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+
+void delay0 (void) { __delay_cycles (0); }
+void delay1 (void) { __delay_cycles (1); }
+void delay2 (void) { __delay_cycles (2); }
+void delay3 (void) { __delay_cycles (3); }
+
+void delay_1 (void) { __delay_cycles (44); }
+void delay_2 (void) { __delay_cycles (0x1234); }
+void delay_3 (void) { __delay_cycles (0x123456); }
+
+/* { dg-final { scan-assembler-not "__delay_cycles" } } */
diff --git a/gcc/testsuite/gcc.target/pru/builtins-error.c b/gcc/testsuite/gcc.target/pru/builtins-error.c
new file mode 100644
index 0000000..a856872
--- /dev/null
+++ b/gcc/testsuite/gcc.target/pru/builtins-error.c
@@ -0,0 +1,6 @@
+/* { dg-do assemble } */
+
+void delay (long a)
+{
+ __delay_cycles (a); /* { dg-error "'__delay_cycles' only takes constant arguments" } */
+}
diff --git a/gcc/testsuite/gcc.target/pru/clearbit.c b/gcc/testsuite/gcc.target/pru/clearbit.c
new file mode 100644
index 0000000..cc24b3b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/pru/clearbit.c
@@ -0,0 +1,13 @@
+/* clearbit instruction generation */
+
+/* { dg-do compile } */
+/* { dg-options "-O1" } */
+
+unsigned int
+test_clearbit (unsigned int val)
+{
+ /* { dg-final { scan-assembler "clr\\tr14, r14, 19" } } */
+ val &= ~(1u << 19);
+ return val;
+}
+
diff --git a/gcc/testsuite/gcc.target/pru/loop-asm.c b/gcc/testsuite/gcc.target/pru/loop-asm.c
new file mode 100644
index 0000000..7b737a0
--- /dev/null
+++ b/gcc/testsuite/gcc.target/pru/loop-asm.c
@@ -0,0 +1,19 @@
+/* Test that LOOP will not be generated when body contains asm statement */
+
+/* { dg-do compile } */
+/* { dg-options "-O1 -mloop" } */
+
+/* -O1 in the options is significant. Without it do-loop will not be
+ run. */
+
+unsigned int
+test_loop (unsigned int n)
+{
+ unsigned i;
+ /* { dg-final { scan-assembler-not "loop\t.\+" } } */
+ for (i = 0; i < 10; i++) {
+ n <<= 2;
+ asm volatile ("nop" : : );
+ }
+ return n;
+}
diff --git a/gcc/testsuite/gcc.target/pru/loop-dowhile.c b/gcc/testsuite/gcc.target/pru/loop-dowhile.c
new file mode 100644
index 0000000..0926b98
--- /dev/null
+++ b/gcc/testsuite/gcc.target/pru/loop-dowhile.c
@@ -0,0 +1,45 @@
+/* Test LOOP generation for do while.
+ Ensure the post-condition "do while" is correctly translated
+ to a pre-condition PRU LOOP instruction. */
+
+/* { dg-do run } */
+/* { dg-options "-O1 -mloop" } */
+
+/* -O1 in the options is significant. Without it do-loop will not be
+ run. */
+
+extern void abort (void);
+
+volatile unsigned int int_12345 = 12345;
+volatile unsigned int int_0 = 0;
+volatile unsigned int int_1 = 1;
+
+unsigned int
+test_loop (unsigned int n)
+{
+ unsigned int i = 0;
+ volatile unsigned int s = 0;
+
+ if (n >= 0x7fff) return 0;
+
+ do {
+ s++;
+ i++;
+ } while (i < n);
+ return s;
+}
+
+
+int
+main (int argc, char** argv)
+{
+ if (test_loop (int_0) != 1)
+ abort();
+ if (test_loop (int_1) != 1)
+ abort();
+ if (test_loop (int_12345) != 12345)
+ abort();
+
+ return 0;
+}
+
diff --git a/gcc/testsuite/gcc.target/pru/loop-hi-1.c b/gcc/testsuite/gcc.target/pru/loop-hi-1.c
new file mode 100644
index 0000000..23caf20
--- /dev/null
+++ b/gcc/testsuite/gcc.target/pru/loop-hi-1.c
@@ -0,0 +1,38 @@
+/* Test LOOP recognition - short ints*/
+
+/* { dg-do run } */
+/* { dg-options "-O1 -mloop" } */
+
+/* -O1 in the options is significant. Without it do-loop will not be
+ run. */
+
+extern void abort (void);
+
+volatile unsigned short short_12345 = 12345;
+volatile unsigned short short_0 = 0;
+volatile unsigned short short_1 = 1;
+
+unsigned int
+test_loop_short (unsigned short n)
+{
+ unsigned short i;
+ volatile unsigned int s = 0;
+
+ for (i = 0; i < n; i++)
+ s++;
+ return s;
+}
+
+int
+main (int argc, char** argv)
+{
+ if (test_loop_short (short_0) != 0)
+ abort();
+ if (test_loop_short (short_1) != 1)
+ abort();
+ if (test_loop_short (short_12345) != 12345)
+ abort();
+
+ return 0;
+}
+
diff --git a/gcc/testsuite/gcc.target/pru/loop-hi-2.c b/gcc/testsuite/gcc.target/pru/loop-hi-2.c
new file mode 100644
index 0000000..0ef4ec7
--- /dev/null
+++ b/gcc/testsuite/gcc.target/pru/loop-hi-2.c
@@ -0,0 +1,17 @@
+/* Test LOOP recognition - short ints*/
+
+/* { dg-options "-O2 -mloop" } */
+
+/* -O2 in the options is significant. Without it do-loop will not be
+ run. */
+
+unsigned int
+test_loop_short (int x, short n)
+{
+ int i;
+
+ /* { dg-final { scan-assembler "loop\\t.L\[0-9\]*, r\[0-9w.\]*" } } */
+ for (i = 0; i < n; i++)
+ x <<= 3;
+ return x;
+}
diff --git a/gcc/testsuite/gcc.target/pru/loop-qi-1.c b/gcc/testsuite/gcc.target/pru/loop-qi-1.c
new file mode 100644
index 0000000..a4bb7d6
--- /dev/null
+++ b/gcc/testsuite/gcc.target/pru/loop-qi-1.c
@@ -0,0 +1,38 @@
+/* Test LOOP recognition */
+
+/* { dg-do run } */
+/* { dg-options "-O1 -mloop" } */
+
+/* -O1 in the options is significant. Without it do-loop will not be
+ run. */
+
+extern void abort (void);
+
+volatile unsigned char char_123 = 123;
+volatile unsigned char char_0 = 0;
+volatile unsigned char char_1 = 1;
+
+unsigned int
+test_loop_char (unsigned char n)
+{
+ unsigned char i;
+ volatile unsigned int s = 0;
+
+ for (i = 0; i < n; i++)
+ s++;
+ return s;
+}
+
+int
+main (int argc, char** argv)
+{
+ if (test_loop_char (char_0) != 0)
+ abort();
+ if (test_loop_char (char_1) != 1)
+ abort();
+ if (test_loop_char (char_123) != 123)
+ abort();
+
+ return 0;
+}
+
diff --git a/gcc/testsuite/gcc.target/pru/loop-qi-2.c b/gcc/testsuite/gcc.target/pru/loop-qi-2.c
new file mode 100644
index 0000000..24a343d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/pru/loop-qi-2.c
@@ -0,0 +1,17 @@
+/* Test LOOP recognition */
+
+/* { dg-options "-O2 -mloop" } */
+
+/* -O2 in the options is significant. Without it do-loop will not be
+ run. */
+
+unsigned int
+test_loop_char (unsigned int x, char n)
+{
+ int i;
+
+ /* { dg-final { scan-assembler "loop\\t.L\[0-9\]*, r\[0-9b.\]*" } } */
+ for (i = 0; i < n; i++)
+ x <<= 2;
+ return x;
+}
diff --git a/gcc/testsuite/gcc.target/pru/loop-short-1.c b/gcc/testsuite/gcc.target/pru/loop-short-1.c
new file mode 100644
index 0000000..14d7530
--- /dev/null
+++ b/gcc/testsuite/gcc.target/pru/loop-short-1.c
@@ -0,0 +1,53 @@
+/* Test LOOP generation for very short loops. */
+
+/* { dg-do run } */
+/* { dg-options "-O1 -mloop" } */
+
+/* -O1 in the options is significant. Without it do-loop will not be
+ run. */
+
+extern void abort (void);
+
+volatile unsigned int int_12345 = 12345;
+volatile unsigned int int_0 = 0;
+volatile unsigned int int_1 = 1;
+
+unsigned int
+test_loop_sum (unsigned int n)
+{
+ unsigned i;
+ volatile unsigned int s = 0;
+ for (i = 0; i < n; i++) {
+ s++;
+ }
+ return s;
+}
+
+unsigned int
+test_loop_shift20 (unsigned int n)
+{
+ unsigned i;
+ for (i = 0; i < 10; i++) {
+ n <<= 2;
+ }
+ return n;
+}
+
+int
+main (int argc, char** argv)
+{
+ if (test_loop_sum (int_0) != 0)
+ abort();
+ if (test_loop_sum (int_1) != 1)
+ abort();
+ if (test_loop_sum (int_12345) != 12345)
+ abort();
+
+ if (test_loop_shift20 (int_0) != 0)
+ abort();
+ if (test_loop_shift20 (int_1) != (1u << 20))
+ abort();
+
+ return 0;
+}
+
diff --git a/gcc/testsuite/gcc.target/pru/loop-short-2.c b/gcc/testsuite/gcc.target/pru/loop-short-2.c
new file mode 100644
index 0000000..b0e1986
--- /dev/null
+++ b/gcc/testsuite/gcc.target/pru/loop-short-2.c
@@ -0,0 +1,21 @@
+/* Test LOOP generation for very short loops. */
+
+/* { dg-options "-O1 -mloop" } */
+
+/* -O1 in the options is significant. Without it do-loop will not be
+ run. */
+
+unsigned int
+test_loop (unsigned int n, unsigned int x)
+{
+ unsigned int i;
+
+ if (n >= 0x10000) return 0;
+ if (!n) return 0;
+
+ /* { dg-final { scan-assembler "loop\\t.L\[0-9\]*, r\[0-9\]*" } } */
+ /* { dg-final { scan-assembler "nop" } } */
+ for (i = 0; i < n; i++)
+ x <<= 2;
+ return x;
+}
diff --git a/gcc/testsuite/gcc.target/pru/loop-si-1.c b/gcc/testsuite/gcc.target/pru/loop-si-1.c
new file mode 100644
index 0000000..84087bf
--- /dev/null
+++ b/gcc/testsuite/gcc.target/pru/loop-si-1.c
@@ -0,0 +1,41 @@
+/* Test LOOP recognition */
+
+/* { dg-do run } */
+/* { dg-options "-O1 -mloop" } */
+
+/* -O1 in the options is significant. Without it do-loop will not be
+ run. */
+
+extern void abort (void);
+
+volatile unsigned int int_12345 = 12345;
+volatile unsigned int int_0 = 0;
+volatile unsigned int int_1 = 1;
+
+unsigned int
+test_loop (unsigned int n)
+{
+ unsigned int i;
+ volatile unsigned int s = 0;
+
+ if (n >= 0x10000) return 0;
+
+ for (i = 0; i < n; i++)
+ s++;
+ return s;
+}
+
+
+int
+main (int argc, char** argv)
+{
+ if (test_loop (int_0) != 0)
+ abort();
+ if (test_loop (int_1) != 1)
+ abort();
+ if (test_loop (int_12345) != 12345)
+ abort();
+
+ return 0;
+}
+
diff --git a/gcc/testsuite/gcc.target/pru/loop-si-2.c b/gcc/testsuite/gcc.target/pru/loop-si-2.c
new file mode 100644
index 0000000..1e8a9d1
--- /dev/null
+++ b/gcc/testsuite/gcc.target/pru/loop-si-2.c
@@ -0,0 +1,20 @@
+/* Test LOOP recognition */
+
+/* { dg-options "-O1 -mloop" } */
+
+/* -O1 in the options is significant. Without it do-loop will not be
+ run. */
+
+unsigned int
+test_loop (unsigned int n)
+{
+ unsigned int i;
+ volatile unsigned int s = 0;
+
+ if (n >= 0x10000) return 0;
+
+ /* { dg-final { scan-assembler "loop\\t.L\[0-9\]*, r\[0-9\]*" } } */
+ for (i = 0; i < n; i++)
+ s++;
+ return s;
+}
diff --git a/gcc/testsuite/gcc.target/pru/loop-u8_pcrel_overflow.c b/gcc/testsuite/gcc.target/pru/loop-u8_pcrel_overflow.c
new file mode 100644
index 0000000..8ae91c6
--- /dev/null
+++ b/gcc/testsuite/gcc.target/pru/loop-u8_pcrel_overflow.c
@@ -0,0 +1,42 @@
+/* Test large loop bodies where U8_PCREL would overflow */
+
+/* { dg-do run } */
+/* { dg-options "-O1 -mloop" } */
+
+/* -O1 in the options is significant. Without it do-loop will not be
+ run. */
+
+extern void abort (void);
+
+#define OP do { i1 <<= 2; i1 >>= 2; i2 *= 3; i2 /= 2; } while(0)
+#define OP4 OP; OP; OP; OP
+#define OP16 OP4; OP4; OP4; OP4
+#define OP64 OP16; OP16; OP16; OP16
+#define OP256 OP64; OP64; OP64; OP64
+
+unsigned int
+test_loop (unsigned int i1, unsigned i2)
+{
+ unsigned int i;
+ volatile unsigned int s = 0;
+
+ for (i = 0; i < 100; i++) {
+ /* cannot use ASM NOP because it will prevent
+ GCC from issuing a LOOP instruction. */
+ OP256;
+ s++;
+ }
+ return s + i1 + i2;
+}
+
+volatile unsigned int I1 = 0;
+volatile unsigned int I2 = 0;
+
+int
+main (int argc, char** argv)
+{
+ if (test_loop (I1, I2) != 100)
+ abort();
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/pru/loop-ubyte-1.c b/gcc/testsuite/gcc.target/pru/loop-ubyte-1.c
new file mode 100644
index 0000000..8444f81
--- /dev/null
+++ b/gcc/testsuite/gcc.target/pru/loop-ubyte-1.c
@@ -0,0 +1,30 @@
+/* Test LOOP recognition */
+
+/* { dg-do run } */
+/* { dg-options "-O1 -mloop" } */
+
+/* -O1 in the options is significant. Without it do-loop will not be
+ run. */
+
+extern void abort (void);
+
+unsigned int
+test_loop_ubyte_101 (void)
+{
+ unsigned int i;
+ volatile unsigned int s = 0;
+
+ for (i = 0; i < 101; i++)
+ s++;
+ return s;
+}
+
+int
+main (int argc, char** argv)
+{
+ if (test_loop_ubyte_101 () != 101)
+ abort();
+
+ return 0;
+}
+
diff --git a/gcc/testsuite/gcc.target/pru/loop-ubyte-2.c b/gcc/testsuite/gcc.target/pru/loop-ubyte-2.c
new file mode 100644
index 0000000..058cbb0
--- /dev/null
+++ b/gcc/testsuite/gcc.target/pru/loop-ubyte-2.c
@@ -0,0 +1,18 @@
+/* Test LOOP recognition */
+
+/* { dg-options "-O1 -mloop" } */
+
+/* -O1 in the options is significant. Without it do-loop will not be
+ run. */
+
+unsigned int
+test_loop_ubyte_101 (void)
+{
+ unsigned int i;
+ volatile unsigned int s = 0;
+
+ /* { dg-final { scan-assembler "loop\\t.L\[0-9\]*, 101" } } */
+ for (i = 0; i < 101; i++)
+ s++;
+ return s;
+}
diff --git a/gcc/testsuite/gcc.target/pru/lra-framepointer-fragmentation-1.c b/gcc/testsuite/gcc.target/pru/lra-framepointer-fragmentation-1.c
new file mode 100644
index 0000000..ee1288f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/pru/lra-framepointer-fragmentation-1.c
@@ -0,0 +1,33 @@
+/* { dg-do assemble } */
+/* { dg-options "-O1 -fno-omit-frame-pointer" } */
+#include <stdint.h>
+
+extern uint64_t global;
+
+uint64_t __attribute__((noinline)) test(uint64_t a, uint64_t b,
+ uint64_t c, uint64_t d,
+ uint64_t e, uint64_t f,
+ uint64_t g, uint64_t h)
+{
+ uint64_t l1 = 0x12345678, l2 = 0x87654321, l3 = 1001, l4 = 1002;
+ uint64_t l5 = 1004;
+ uint32_t l6 = 2005;
+ uint8_t c1 = 101, c2 = 102;
+
+ /* The numerous dummy asm input operands create just
+ * enough register pressure to resort to using
+ * FP.b1 (r4.b1).
+ */
+
+ asm ("nop" /* { dg-error "'asm' operand has impossible constraints" } */
+ : "=r" (l1)
+ : "0" (l1), "r" (a), "r"(b),
+ "r"(c), "r"(d), "r"(e), "r"(f),
+ "r"(g), "r"(h), "r"(l2),
+ "r"(c1), "r"(c2),
+ "r"(l3), "r"(l4), "r"(l5), "r"(l6));
+
+ global = a+b+c+d+e+f+g+h + c1+c2 + l2;
+
+ return l1;
+}
diff --git a/gcc/testsuite/gcc.target/pru/lra-framepointer-fragmentation-2.c b/gcc/testsuite/gcc.target/pru/lra-framepointer-fragmentation-2.c
new file mode 100644
index 0000000..6c98e9b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/pru/lra-framepointer-fragmentation-2.c
@@ -0,0 +1,61 @@
+/* { dg-do run } */
+/* { dg-options "-O1 -fomit-frame-pointer" } */
+#include <stdint.h>
+
+extern void abort (void);
+
+uint64_t global = 5;
+
+uint64_t __attribute__((noinline)) test(uint64_t a, uint64_t b,
+ uint64_t c, uint64_t d,
+ uint64_t e, uint64_t f,
+ uint64_t g, uint64_t h)
+{
+ uint64_t l1 = 0x12345678, l2 = 0x87654321, l3 = 1001, l4 = 1002;
+ uint64_t l5 = 1004;
+ uint32_t l6 = 2005;
+ uint8_t c1 = 101, c2 = 102;
+
+ /* The numerous dummy asm input operands create just
+ * enough register pressure to resort to using FP (r4).
+ */
+
+ asm ("ldi32 %0, 0x11223344\n\t"
+ "add %0, %0, %2\n\t"
+ "add %0, %0, %3\n\t"
+ "add %0, %0, %4\n\t"
+ "add %0, %0, %5\n\t"
+ "add %0, %0, %6\n\t"
+ "add %0, %0, %7\n\t"
+ "add %0, %0, %8\n\t"
+ "add %0, %0, %9\n\t"
+ "add %0, %0, %10\n\t"
+ "add %0, %0, %11\n\t"
+ "add %0, %0, %12\n\t"
+ "add %0, %0, %13\n\t"
+ "add %0, %0, %14\n\t"
+ "add %0, %0, %15\n\t"
+ "add %0, %0, %16\n\t"
+ : "=r" (l1)
+ : "0" (l1), "r" (a), "r"(b),
+ "r"(c), "r"(d), "r"(e), "r"(f),
+ "r"(g), "r"(h), "r"(c1), "r"(c2),
+ "r"(l2), "r"(l3), "r"(l4), "r"(l5), "r"(l6));
+
+ global = a+b+c+d+e+f+g+h + c1+c2 + l2+l3+l4+l5+l6;
+
+ return l1;
+}
+
+int main()
+{
+ uint64_t a = test(1, 2, 3, 4, 5, 6, 7, 8);
+
+ if (a != 0x98878ae8) {
+ abort();
+ }
+ if (global != 0x876557a4) {
+ abort();
+ }
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/pru/mabi-ti-1.c b/gcc/testsuite/gcc.target/pru/mabi-ti-1.c
new file mode 100644
index 0000000..117ae8f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/pru/mabi-ti-1.c
@@ -0,0 +1,10 @@
+/* Test TI ABI unsupported constructs */
+
+/* { dg-do assemble } */
+/* { dg-options "-O1 -mabi=ti" } */
+
+
+int test(int a, int b, void (*fp)(void))
+{ /* { dg-error "function pointers not supported with '-mabi=ti' option" } */
+ return a+b;
+}
diff --git a/gcc/testsuite/gcc.target/pru/mabi-ti-2.c b/gcc/testsuite/gcc.target/pru/mabi-ti-2.c
new file mode 100644
index 0000000..d4a3aff
--- /dev/null
+++ b/gcc/testsuite/gcc.target/pru/mabi-ti-2.c
@@ -0,0 +1,15 @@
+/* Test TI ABI unsupported constructs */
+
+/* { dg-do assemble } */
+/* { dg-options "-O1 -mabi=ti" } */
+
+
+struct big {
+ char c[9];
+};
+
+struct big test(void)
+{ /* { dg-error "large return values not supported with '-mabi=ti' option" } */
+ static struct big b;
+ return b;
+}
diff --git a/gcc/testsuite/gcc.target/pru/mabi-ti-3.c b/gcc/testsuite/gcc.target/pru/mabi-ti-3.c
new file mode 100644
index 0000000..c49f6653
--- /dev/null
+++ b/gcc/testsuite/gcc.target/pru/mabi-ti-3.c
@@ -0,0 +1,12 @@
+/* Test TI ABI unsupported constructs */
+
+/* { dg-do assemble } */
+/* { dg-options "-O1 -mabi=ti" } */
+
+
+extern void extfunc(void (*fp)(void));
+
+void test(void)
+{
+ extfunc(test); /* { dg-error "function pointers not supported with '-mabi=ti' option" } */
+}
diff --git a/gcc/testsuite/gcc.target/pru/mabi-ti-4.c b/gcc/testsuite/gcc.target/pru/mabi-ti-4.c
new file mode 100644
index 0000000..0110e6c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/pru/mabi-ti-4.c
@@ -0,0 +1,14 @@
+/* Test TI ABI with supported constructs */
+
+/* { dg-do assemble } */
+/* { dg-options "-O1 -mabi=ti" } */
+
+
+extern void extfunc1(long long);
+extern long long extfunc2(long long);
+
+long long test(void)
+{
+ extfunc1(3);
+ return extfunc2(1);
+}
diff --git a/gcc/testsuite/gcc.target/pru/mabi-ti-5.c b/gcc/testsuite/gcc.target/pru/mabi-ti-5.c
new file mode 100644
index 0000000..38eeaa4
--- /dev/null
+++ b/gcc/testsuite/gcc.target/pru/mabi-ti-5.c
@@ -0,0 +1,33 @@
+/* Test TI ABI unsupported constructs */
+
+/* { dg-do assemble } */
+/* { dg-options "-O1 -mabi=ti" } */
+
+struct s1 {
+ void (*f)(void);
+ int a;
+};
+
+struct s2 {
+ union {
+ void (*f)(void);
+ int a;
+ long b;
+ } u;
+};
+
+int test1(struct s1 *p)
+{
+ return p->a; /* { dg-error "function pointers not supported with '-mabi=ti' option" } */
+ return 1;
+}
+
+int test1_unused_arg(struct s1 p, int a)
+{ /* { dg-error "function pointers not supported with '-mabi=ti' option" } */
+ return a;
+}
+
+int test2(struct s2 v)
+{ /* { dg-error "function pointers not supported with '-mabi=ti' option" } */
+ return 2;
+}
diff --git a/gcc/testsuite/gcc.target/pru/mabi-ti-6.c b/gcc/testsuite/gcc.target/pru/mabi-ti-6.c
new file mode 100644
index 0000000..c8aa018
--- /dev/null
+++ b/gcc/testsuite/gcc.target/pru/mabi-ti-6.c
@@ -0,0 +1,12 @@
+/* Test TI ABI unsupported constructs */
+
+/* { dg-do assemble } */
+/* { dg-options "-O1 -mabi=ti" } */
+
+
+extern void (*extfuncp)(int);
+
+void test(void)
+{
+ extfuncp(1); /* { dg-error "function pointers not supported with '-mabi=ti' option" } */
+}
diff --git a/gcc/testsuite/gcc.target/pru/mabi-ti-7.c b/gcc/testsuite/gcc.target/pru/mabi-ti-7.c
new file mode 100644
index 0000000..cc095fa
--- /dev/null
+++ b/gcc/testsuite/gcc.target/pru/mabi-ti-7.c
@@ -0,0 +1,21 @@
+/* Test TI ABI unsupported constructs */
+
+/* { dg-do assemble } */
+/* { dg-options "-O1 -mabi=ti" } */
+
+struct s1 {
+ int (*f)(void);
+ int a;
+};
+
+extern struct s1 s;
+
+int test1(void)
+{
+ return s.f(); /* { dg-error "function pointers not supported with '-mabi=ti' option" } */
+}
+
+int test2(void)
+{
+ return s.a; /* { dg-error "function pointers not supported with '-mabi=ti' option" } */
+}
diff --git a/gcc/testsuite/gcc.target/pru/pr64366.c b/gcc/testsuite/gcc.target/pru/pr64366.c
new file mode 100644
index 0000000..1608d46
--- /dev/null
+++ b/gcc/testsuite/gcc.target/pru/pr64366.c
@@ -0,0 +1,128 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+typedef int int8_t __attribute__ ((__mode__ (__QI__)));
+typedef int int16_t __attribute__ ((__mode__ (__HI__)));
+typedef int int32_t __attribute__ ((__mode__ (__SI__)));
+typedef int int64_t __attribute__ ((__mode__ (__DI__)));
+typedef unsigned char uint8_t;
+typedef unsigned short int uint16_t;
+typedef unsigned int uint32_t;
+__extension__ typedef unsigned long long int uint64_t;
+typedef int intptr_t;
+typedef struct BigStruct{
+ uint8_t a;
+ int8_t b;
+ uint16_t c;
+ int16_t d;
+ uint32_t e;
+ int32_t f;
+ uint64_t g;
+ int64_t h;
+ float i;
+ double j;
+ long double k;
+ char* l;
+ uint8_t m;
+ int8_t n;
+ uint16_t o;
+ int16_t p;
+ uint32_t q;
+ int32_t r;
+ uint64_t s;
+ int64_t t;
+ float u;
+ double v;
+ long double w;
+ char* x;
+ uint8_t y;
+ int8_t z;
+ uint16_t aa;
+ int16_t bb;
+ uint32_t cc;
+ int32_t dd;
+ uint64_t ee;
+ int64_t ff;
+ float gg;
+ double hh;
+ long double ii;
+ char* jj;
+ uint8_t kk;
+ int8_t ll;
+ uint16_t mm;
+ int16_t nn;
+ uint32_t oo;
+ int32_t pp;
+ uint64_t qq;
+ int64_t rr;
+ float ss;
+ double tt;
+ long double uu;
+ char* vv;
+ uint8_t ww;
+ int8_t xx;
+} BigStruct;
+
+extern void foobar();
+
+void
+test_large_fn (uint8_t ui8_1, int8_t si8_1, uint16_t ui16_1, int16_t si16_1,
+ uint32_t ui32_1, int32_t si32_1, uint64_t ui64_1, int64_t si64_1,
+ float f_1, double d_1, long double ld_1, char* p_1,
+ uint8_t ui8_2, int8_t si8_2, uint16_t ui16_2, int16_t si16_2,
+ uint32_t ui32_2, int32_t si32_2, uint64_t ui64_2, int64_t si64_2,
+ float f_2, double d_2, long double ld_2, char* p_2,
+ uint8_t ui8_3, int8_t si8_3, uint16_t ui16_3, int16_t si16_3,
+ uint32_t ui32_3, int32_t si32_3, uint64_t ui64_3, int64_t si64_3,
+ float f_3, double d_3, long double ld_3, char* p_3,
+ uint8_t ui8_4, int8_t si8_4, uint16_t ui16_4, int16_t si16_4,
+ uint32_t ui32_4, int32_t si32_4, uint64_t ui64_4, int64_t si64_4,
+ float f_4, double d_4, long double ld_4, char* p_4,
+ uint8_t ui8_5, int8_t si8_5)
+{
+ BigStruct retVal =
+ {
+ ui8_1 + 1, si8_1 + 1, ui16_1 + 1, si16_1 + 1,
+ ui32_1 + 1, si32_1 + 1, ui64_1 + 1, si64_1 + 1,
+ f_1 + 1, d_1 + 1, ld_1 + 1, (char*)((intptr_t)p_1 + 1),
+ ui8_2 + 2, si8_2 + 2, ui16_2 + 2, si16_2 + 2,
+ ui32_2 + 2, si32_2 + 2, ui64_2 + 2, si64_2 + 2,
+ f_2 + 2, d_2 + 2, ld_2 + 2, (char*)((intptr_t)p_2 + 2),
+ ui8_3 + 3, si8_3 + 3, ui16_3 + 3, si16_3 + 3,
+ ui32_3 + 3, si32_3 + 3, ui64_3 + 3, si64_3 + 3,
+ f_3 + 3, d_3 + 3, ld_3 + 3, (char*)((intptr_t)p_3 + 3),
+ ui8_4 + 4, si8_4 + 4, ui16_4 + 4, si16_4 + 4,
+ ui32_4 + 4, si32_4 + 4, ui64_4 + 4, si64_4 + 4,
+ f_4 + 4, d_4 + 4, ld_4 + 4, (char*)((intptr_t)p_4 + 4),
+ ui8_5 + 5, si8_5 + 5
+ };
+
+ foobar ("%" "u" " %" "d" " %hu %hd %u %d %" "ll" "u" " %" "ll" "d"
+ " %.0f %.0f %.0Lf %#lx " "%" "u" " %" "d" " %hu %hd %u %d %"
+ "ll" "u" " %" "ll" "d" " %.0f %.0f %.0Lf %#lx " "%" "u"
+ " %" "d" " %hu %hd %u %d %" "ll" "u" " %" "ll" "d"
+ " %.0f %.0f %.0Lf %#lx " "%" "u" " %" "d" " %hu %hd %u %d %"
+ "ll" "u" " %" "ll" "d" " %.0f %.0f %.0Lf %#lx %" "u" " %"
+ "d" ": " "%" "u" " %" "d" " %hu %hd %u %d %" "ll" "u" " %"
+ "ll" "d" " %.0f %.0f %.0Lf %#lx " "%" "u" " %" "d"
+ " %hu %hd %u %d %" "ll" "u" " %" "ll" "d" " %.0f %.0f %.0Lf %#lx "
+ "%" "u" " %" "d" " %hu %hd %u %d %" "ll" "u" " %" "ll" "d"
+ " %.0f %.0f %.0Lf %#lx " "%" "u" " %" "d" " %hu %hd %u %d %"
+ "ll" "u" " %" "ll" "d" " %.0f %.0f %.0Lf %#lx %" "u" " %" "d" "\n",
+ ui8_1, si8_1, ui16_1, si16_1, ui32_1, si32_1, ui64_1, si64_1,
+ f_1, d_1, ld_1, (unsigned long)p_1, ui8_2, si8_2, ui16_2, si16_2,
+ ui32_2, si32_2, ui64_2, si64_2, f_2, d_2, ld_2, (unsigned long)p_2,
+ ui8_3, si8_3, ui16_3, si16_3, ui32_3, si32_3, ui64_3, si64_3, f_3,
+ d_3, ld_3, (unsigned long)p_3, ui8_4, si8_4, ui16_4, si16_4, ui32_4,
+ si32_4, ui64_4, si64_4, f_4, d_4, ld_4, (unsigned long)p_4, ui8_5,
+ si8_5, retVal.a, retVal.b, retVal.c, retVal.d, retVal.e, retVal.f,
+ retVal.g, retVal.h, retVal.i, retVal.j, retVal.k,
+ (unsigned long)retVal.l, retVal.m, retVal.n, retVal.o, retVal.p,
+ retVal.q, retVal.r, retVal.s, retVal.t, retVal.u, retVal.v,
+ retVal.w, (unsigned long)retVal.x, retVal.y, retVal.z, retVal.aa,
+ retVal.bb, retVal.cc, retVal.dd, retVal.ee, retVal.ff, retVal.gg,
+ retVal.hh, retVal.ii, (unsigned long)retVal.jj, retVal.kk,
+ retVal.ll, retVal.mm, retVal.nn, retVal.oo, retVal.pp, retVal.qq,
+ retVal.rr, retVal.ss, retVal.tt, retVal.uu, (unsigned long)retVal.vv,
+ retVal.ww, retVal.xx);
+}
diff --git a/gcc/testsuite/gcc.target/pru/pragma-ctable_entry.c b/gcc/testsuite/gcc.target/pru/pragma-ctable_entry.c
new file mode 100644
index 0000000..2c5ea37
--- /dev/null
+++ b/gcc/testsuite/gcc.target/pru/pragma-ctable_entry.c
@@ -0,0 +1,22 @@
+/* Test specification of custom instructions via command-line options. */
+
+/* { dg-do compile } */
+/* { dg-options "-O1" } */
+
+/* -O1 in the options is significant. Without it LBCO/SBCO operations may
+ not be optimized to the respective instructions. */
+
+
+#pragma ctable_entry 12 0x48040000
+
+unsigned int
+test_ctable (unsigned int val1, unsigned int val2)
+{
+ ((volatile unsigned short int *)0x48040000)[0] = val2;
+ ((volatile unsigned int *)0x48040000)[val1] = val2;
+ return ((volatile unsigned int *)0x48040000)[4];
+}
+
+/* { dg-final { scan-assembler "sbco\\tr15.b\[012\]?, 12, 0, 2" } } */
+/* { dg-final { scan-assembler "sbco\\tr15.b0, 12, r14, 4" } } */
+/* { dg-final { scan-assembler "lbco\\tr14.b0, 12, 16, 4" } } */
diff --git a/gcc/testsuite/gcc.target/pru/pru.exp b/gcc/testsuite/gcc.target/pru/pru.exp
new file mode 100644
index 0000000..bf13303
--- /dev/null
+++ b/gcc/testsuite/gcc.target/pru/pru.exp
@@ -0,0 +1,41 @@
+# Copyright (C) 2015-2019 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GCC; see the file COPYING3. If not see
+# <http://www.gnu.org/licenses/>.
+
+# GCC testsuite that uses the `dg.exp' driver.
+
+# Exit immediately if this isn't a PRU target.
+if ![istarget pru*-*-*] then {
+ return
+}
+
+# Load support procs.
+load_lib gcc-dg.exp
+
+# If a testcase doesn't have special options, use these.
+global DEFAULT_CFLAGS
+if ![info exists DEFAULT_CFLAGS] then {
+ set DEFAULT_CFLAGS " -ansi -pedantic-errors"
+}
+
+# Initialize `dg'.
+dg-init
+
+# Main loop.
+dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.\[cCS\]]] \
+ "" $DEFAULT_CFLAGS
+
+# All done.
+dg-finish
diff --git a/gcc/testsuite/gcc.target/pru/qbbc-1.c b/gcc/testsuite/gcc.target/pru/qbbc-1.c
new file mode 100644
index 0000000..1a89190
--- /dev/null
+++ b/gcc/testsuite/gcc.target/pru/qbbc-1.c
@@ -0,0 +1,29 @@
+/* Test QBBC recognition */
+
+/* { dg-do run } */
+/* { dg-options "-O1" } */
+
+/* -O1 in the options is significant. Without it bit-check-and-branch
+ operation may not be optimized to QBBC. */
+
+extern void abort (void);
+
+unsigned int
+test_qbbc_reg (unsigned int a, unsigned int b, unsigned int val)
+{
+ if (!(val & (1 << 19)))
+ return a;
+ return b;
+}
+
+int
+main (int argc, char** argv)
+{
+ if (test_qbbc_reg (101, 505, (1u << 19)) != 505)
+ abort();
+ if (test_qbbc_reg (101, 505, (1u << 18)) != 101)
+ abort();
+
+ return 0;
+}
+
diff --git a/gcc/testsuite/gcc.target/pru/qbbc-2.c b/gcc/testsuite/gcc.target/pru/qbbc-2.c
new file mode 100644
index 0000000..208e039
--- /dev/null
+++ b/gcc/testsuite/gcc.target/pru/qbbc-2.c
@@ -0,0 +1,15 @@
+/* Test QBBC recognition */
+
+/* { dg-options "-O1" } */
+
+/* -O1 in the options is significant. Without it bit-check-and-branch
+ operation may not be optimized to QBBC. */
+
+unsigned int
+test_qbbc_reg (unsigned int a, unsigned int b, unsigned int val)
+{
+ /* { dg-final { scan-assembler "qbbc\\t.L\[0-9\]*, r16, 19" } } */
+ if (!(val & (1 << 19)))
+ return a;
+ return b;
+}
diff --git a/gcc/testsuite/gcc.target/pru/qbbc-3.c b/gcc/testsuite/gcc.target/pru/qbbc-3.c
new file mode 100644
index 0000000..7fb7e1a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/pru/qbbc-3.c
@@ -0,0 +1,15 @@
+/* Test QBBC recognition */
+
+/* { dg-options "-O1" } */
+
+/* -O1 in the options is significant. Without it bit-check-and-branch
+ operation may not be optimized to QBBC. */
+
+unsigned int
+test_qbbc_reg (unsigned int a, unsigned int b, unsigned short val)
+{
+ /* { dg-final { scan-assembler "qbbc\\t.L\[0-9\]*, r16.w0, 12" } } */
+ if (!(val & (1 << 12)))
+ return a;
+ return b;
+}
diff --git a/gcc/testsuite/gcc.target/pru/qbbs-1.c b/gcc/testsuite/gcc.target/pru/qbbs-1.c
new file mode 100644
index 0000000..01f8187
--- /dev/null
+++ b/gcc/testsuite/gcc.target/pru/qbbs-1.c
@@ -0,0 +1,29 @@
+/* Test QBBS recognition */
+
+/* { dg-do run } */
+/* { dg-options "-O1" } */
+
+/* -O1 in the options is significant. Without it bit-check-and-branch
+ operation may not be optimized to QBBS. */
+
+extern void abort (void);
+
+unsigned int
+test_qbbs_reg (unsigned int a, unsigned int b, unsigned int val)
+{
+ if (val & (1 << 19))
+ return a;
+ return b;
+}
+
+int
+main (int argc, char** argv)
+{
+ if (test_qbbs_reg (101, 505, (1u << 19)) != 101)
+ abort();
+ if (test_qbbs_reg (101, 505, (1u << 18)) != 505)
+ abort();
+
+ return 0;
+}
+
diff --git a/gcc/testsuite/gcc.target/pru/qbbs-2.c b/gcc/testsuite/gcc.target/pru/qbbs-2.c
new file mode 100644
index 0000000..fea7f20
--- /dev/null
+++ b/gcc/testsuite/gcc.target/pru/qbbs-2.c
@@ -0,0 +1,15 @@
+/* Test QBBS recognition */
+
+/* { dg-options "-O1" } */
+
+/* -O1 in the options is significant. Without it bit-check-and-branch
+ operation may not be optimized to QBBS. */
+
+unsigned int
+test_qbbs_reg (unsigned int a, unsigned int b, unsigned int val)
+{
+ /* { dg-final { scan-assembler "qbbs\\t.L\[0-9\]*, r16, 19" } } */
+ if (val & (1 << 19))
+ return a;
+ return b;
+}
diff --git a/gcc/testsuite/gcc.target/pru/setbit.c b/gcc/testsuite/gcc.target/pru/setbit.c
new file mode 100644
index 0000000..6e63b73
--- /dev/null
+++ b/gcc/testsuite/gcc.target/pru/setbit.c
@@ -0,0 +1,13 @@
+/* setbit instruction generation */
+
+/* { dg-do compile } */
+/* { dg-options "-O1" } */
+
+unsigned int
+test_setbit (unsigned int val)
+{
+ /* { dg-final { scan-assembler "set\\tr14, r14, 31" } } */
+ val |= (1u << 31);
+ return val;
+}
+
diff --git a/gcc/testsuite/gcc.target/pru/zero_extend-and-hisi.c b/gcc/testsuite/gcc.target/pru/zero_extend-and-hisi.c
new file mode 100644
index 0000000..716043c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/pru/zero_extend-and-hisi.c
@@ -0,0 +1,16 @@
+/* AND with zero extension of operands.
+ It is matched slightly different than rest of ALU ops. */
+
+/* { dg-do compile } */
+/* { dg-options "-O1" } */
+
+/* -O1 in the options is significant. Without it the zero extension might not
+ be coalesced into the ALU instruction. */
+
+unsigned int
+test_zext_and_hi (unsigned short val1, unsigned int val2)
+{
+ /* { dg-final { scan-assembler "and\\tr14, r14.w0, r15" } } */
+ return val1 & val2;
+}
+
diff --git a/gcc/testsuite/gcc.target/pru/zero_extend-and-qihi.c b/gcc/testsuite/gcc.target/pru/zero_extend-and-qihi.c
new file mode 100644
index 0000000..06f5845
--- /dev/null
+++ b/gcc/testsuite/gcc.target/pru/zero_extend-and-qihi.c
@@ -0,0 +1,16 @@
+/* AND with zero extension of operands.
+ It is matched slightly different than rest of ALU ops. */
+
+/* { dg-do compile } */
+/* { dg-options "-O1" } */
+
+/* -O1 in the options is significant. Without it the zero extension might not
+ be coalesced into the ALU instruction. */
+
+unsigned int
+test_zext_and_hi (unsigned char val1, unsigned int val2)
+{
+ /* { dg-final { scan-assembler "and\\tr14, r14.b0, r15" } } */
+ return val1 & val2;
+}
+
diff --git a/gcc/testsuite/gcc.target/pru/zero_extend-and-qisi.c b/gcc/testsuite/gcc.target/pru/zero_extend-and-qisi.c
new file mode 100644
index 0000000..06f5845
--- /dev/null
+++ b/gcc/testsuite/gcc.target/pru/zero_extend-and-qisi.c
@@ -0,0 +1,16 @@
+/* AND with zero extension of operands.
+ It is matched slightly different than rest of ALU ops. */
+
+/* { dg-do compile } */
+/* { dg-options "-O1" } */
+
+/* -O1 in the options is significant. Without it the zero extension might not
+ be coalesced into the ALU instruction. */
+
+unsigned int
+test_zext_and_hi (unsigned char val1, unsigned int val2)
+{
+ /* { dg-final { scan-assembler "and\\tr14, r14.b0, r15" } } */
+ return val1 & val2;
+}
+
diff --git a/gcc/testsuite/gcc.target/pru/zero_extend-hisi.c b/gcc/testsuite/gcc.target/pru/zero_extend-hisi.c
new file mode 100644
index 0000000..eddd429
--- /dev/null
+++ b/gcc/testsuite/gcc.target/pru/zero_extend-hisi.c
@@ -0,0 +1,43 @@
+/* ALU operations with zero extended operands. */
+
+/* { dg-do compile } */
+/* { dg-options "-O1" } */
+
+/* -O1 in the options is significant. Without it the zero extension might not
+ be coalesced into the ALU instruction. */
+
+unsigned int
+test_zext_plus_hi (unsigned short val1, unsigned int val2)
+{
+ /* { dg-final { scan-assembler "add\\tr14, r14.w0, r15" } } */
+ return val1 + val2;
+}
+
+unsigned int
+test_zext_minus_hi (unsigned short val1, unsigned int val2)
+{
+ /* { dg-final { scan-assembler "sub\\tr14, r14.w0, r15" } } */
+ return val1 - val2;
+}
+
+unsigned int
+test_zext_xor_hi (unsigned short val1, unsigned int val2)
+{
+ /* { dg-final { scan-assembler "xor\\tr14, r14.w0, r15" } } */
+ return val1 ^ val2;
+}
+
+unsigned int
+test_zext_or_hi (unsigned short val1, unsigned int val2)
+{
+ /* { dg-final { scan-assembler "or\\tr14, r14.w0, r15" } } */
+ return val1 | val2;
+}
+
+unsigned int
+test_zext_ashl_hi (unsigned short val1, unsigned int val2)
+{
+ /* { dg-final { scan-assembler "lsl\\tr14, r14.w0, r15" } } */
+ return val1 << val2;
+}
+
diff --git a/gcc/testsuite/gcc.target/pru/zero_extend-qihi.c b/gcc/testsuite/gcc.target/pru/zero_extend-qihi.c
new file mode 100644
index 0000000..62e81f8
--- /dev/null
+++ b/gcc/testsuite/gcc.target/pru/zero_extend-qihi.c
@@ -0,0 +1,43 @@
+/* ALU operations with zero extended operands. */
+
+/* { dg-do compile } */
+/* { dg-options "-O1" } */
+
+/* -O1 in the options is significant. Without it the zero extension might not
+ be coalesced into the ALU instruction. */
+
+unsigned int
+test_zext_plus_hi (unsigned char val1, unsigned short val2)
+{
+ /* { dg-final { scan-assembler "add\\tr14, r14.b0, r14.w1" } } */
+ return val1 + val2;
+}
+
+unsigned int
+test_zext_minus_hi (unsigned char val1, unsigned short val2)
+{
+ /* { dg-final { scan-assembler "sub\\tr14, r14.b0, r14.w1" } } */
+ return val1 - val2;
+}
+
+unsigned int
+test_zext_xor_hi (unsigned char val1, unsigned short val2)
+{
+ /* { dg-final { scan-assembler "xor\\tr14, r14.b0, r14.w1" } } */
+ return val1 ^ val2;
+}
+
+unsigned int
+test_zext_or_hi (unsigned char val1, unsigned short val2)
+{
+ /* { dg-final { scan-assembler "or\\tr14, r14.b0, r14.w1" } } */
+ return val1 | val2;
+}
+
+unsigned int
+test_zext_ashl_hi (unsigned char val1, unsigned short val2)
+{
+ /* { dg-final { scan-assembler "lsl\\tr14, r14.b0, r14.w1" } } */
+ return val1 << val2;
+}
+
diff --git a/gcc/testsuite/gcc.target/pru/zero_extend-qisi.c b/gcc/testsuite/gcc.target/pru/zero_extend-qisi.c
new file mode 100644
index 0000000..0e9ae4c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/pru/zero_extend-qisi.c
@@ -0,0 +1,43 @@
+/* ALU operations with zero extended operands. */
+
+/* { dg-do compile } */
+/* { dg-options "-O1" } */
+
+/* -O1 in the options is significant. Without it the zero extension might not
+ be coalesced into the ALU instruction. */
+
+unsigned int
+test_zext_plus_hi (unsigned char val1, unsigned int val2)
+{
+ /* { dg-final { scan-assembler "add\\tr14, r14.b0, r15" } } */
+ return val1 + val2;
+}
+
+unsigned int
+test_zext_minus_hi (unsigned char val1, unsigned int val2)
+{
+ /* { dg-final { scan-assembler "sub\\tr14, r14.b0, r15" } } */
+ return val1 - val2;
+}
+
+unsigned int
+test_zext_xor_hi (unsigned char val1, unsigned int val2)
+{
+ /* { dg-final { scan-assembler "xor\\tr14, r14.b0, r15" } } */
+ return val1 ^ val2;
+}
+
+unsigned int
+test_zext_or_hi (unsigned char val1, unsigned int val2)
+{
+ /* { dg-final { scan-assembler "or\\tr14, r14.b0, r15" } } */
+ return val1 | val2;
+}
+
+unsigned int
+test_zext_ashl_hi (unsigned char val1, unsigned int val2)
+{
+ /* { dg-final { scan-assembler "lsl\\tr14, r14.b0, r15" } } */
+ return val1 << val2;
+}
+
diff --git a/gcc/testsuite/gcc.target/s390/global-array-element-pic.c b/gcc/testsuite/gcc.target/s390/global-array-element-pic.c
index 7872120..3569d5b 100644
--- a/gcc/testsuite/gcc.target/s390/global-array-element-pic.c
+++ b/gcc/testsuite/gcc.target/s390/global-array-element-pic.c
@@ -1,6 +1,6 @@
/* Test accesses to global array elements in PIC code. */
/* { dg-do compile } */
-/* { dg-options "-O1 -fPIC" } */
+/* { dg-options "-O1 -march=z900 -fPIC" } */
extern char a[] __attribute__ ((aligned (2)));
extern char *b;
diff --git a/gcc/testsuite/gcc.target/s390/global-array-element-pic2.c b/gcc/testsuite/gcc.target/s390/global-array-element-pic2.c
new file mode 100644
index 0000000..b9398a8
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/global-array-element-pic2.c
@@ -0,0 +1,13 @@
+/* Test accesses to global array elements in PIC code. */
+/* { dg-do compile } */
+/* { dg-options "-O1 -march=z10 -fPIC" } */
+
+extern char a[] __attribute__ ((aligned (2)));
+extern char *b;
+
+void c()
+{
+ b = a + 4;
+ /* { dg-final { scan-assembler {(?n)\n\tlgrl\t%r\d+,a@GOTENT\n} } } */
+ /* { dg-final { scan-assembler-not {(?n)\n\tlarl\t%r\d+,a[^@]} } } */
+}
diff --git a/gcc/testsuite/gcc.target/s390/pr91014.c b/gcc/testsuite/gcc.target/s390/pr91014.c
new file mode 100644
index 0000000..eb37b33
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/pr91014.c
@@ -0,0 +1,8 @@
+/* { dg-do compile } */
+/* { dg-options "-O" } */
+/* { dg-require-effective-target alloca } */
+
+void foo(void)
+{
+ __builtin_calloc (1, 1); /* { dg-warning "ignoring return value of '__builtin_calloc' declared with attribute 'warn_unused_result'" } */
+}
diff --git a/gcc/testsuite/gcc.target/s390/vector/vec-shift-2.c b/gcc/testsuite/gcc.target/s390/vector/vec-shift-2.c
new file mode 100644
index 0000000..c7a1d93
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/vector/vec-shift-2.c
@@ -0,0 +1,24 @@
+/* { dg-do run } */
+/* { dg-options "-O3 -mzarch -march=z13 --save-temps" } */
+
+/* { dg-final { scan-assembler-times "veslf" 1 } } */
+
+typedef __attribute__((vector_size(16))) signed int v4si;
+
+v4si __attribute__((noinline,noclone))
+shift_left_by_scalar (v4si in, int shift_count)
+{
+ return in << (3 + shift_count);
+}
+
+int
+main ()
+{
+ v4si a = { 1, 2, 3, 4 };
+ v4si result = shift_left_by_scalar (a, 1);
+
+ if (result[1] != 32)
+ __builtin_abort ();
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/s390/zvector/vec-sldw.c b/gcc/testsuite/gcc.target/s390/zvector/vec-sldw.c
new file mode 100644
index 0000000..2d4b30f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/zvector/vec-sldw.c
@@ -0,0 +1,55 @@
+/* { dg-do run } */
+/* { dg-options "-O3 -mzarch -march=z13 -mzvector --save-temps" } */
+
+#include <vecintrin.h>
+
+vector signed char __attribute__((noinline,noclone))
+foo8 (vector signed char a)
+{
+ return vec_sldw (a, (vector signed char){ 0 }, 2);
+}
+
+vector signed short __attribute__((noinline,noclone))
+foo16 (vector signed short a)
+{
+ return vec_sldw (a, (vector signed short){ 0 }, 2);
+}
+
+vector int __attribute__((noinline,noclone))
+foo32 (vector int a)
+{
+ return vec_sldw (a, (vector int){ 0 }, 2);
+}
+
+vector long long __attribute__((noinline,noclone))
+foo64 (vector long long a)
+{
+ return vec_sldw (a, (vector long long){ 0 }, 2);
+}
+
+int
+main ()
+{
+ vector long long x;
+
+ x = (vector long long)foo8 ((vector signed char)
+ { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 });
+ if (x[0] != 0x08090a0b0c0d0e0fULL || x[1] != 0)
+ __builtin_abort ();
+
+ x = (vector long long)foo16 ((vector signed short){ 0, 1, 2, 3, 4, 5, 6, 7 });
+ if (x[0] != 0x0004000500060007ULL || x[1] != 0)
+ __builtin_abort ();
+
+ x = (vector long long)foo32 ((vector int){ 0, 1, 2, 3 });
+ if (x[0] != 0x0000000200000003ULL || x[1] != 0)
+ __builtin_abort ();
+
+ x = (vector long long)foo64 ((vector long long){ 0, 1 });
+ if (x[0] != 1 || x[1] != 0)
+ __builtin_abort ();
+
+ return 0;
+}
+
+/* { dg-final { scan-assembler "vsldb\t%v24,%v24,%v\[0-9\]*,8" } } */
diff --git a/gcc/testsuite/gcc.target/sh/pr50749-qihisi-predec-3.c b/gcc/testsuite/gcc.target/sh/pr50749-qihisi-predec-3.c
index 5417497..f814d7a 100644
--- a/gcc/testsuite/gcc.target/sh/pr50749-qihisi-predec-3.c
+++ b/gcc/testsuite/gcc.target/sh/pr50749-qihisi-predec-3.c
@@ -1,7 +1,7 @@
/* PR target/50749: Verify that pre-decrement addressing is generated
inside a loop. */
/* { dg-do compile } */
-/* { dg-options "-O2" } */
+/* { dg-options "-O2 -fno-tree-loop-distribute-patterns" } */
/* { dg-final { scan-assembler-times "mov.b\tr\[0-9]\+,@-r\[0-9]\+" 1 } } */
/* { dg-final { scan-assembler-times "mov.w\tr\[0-9]\+,@-r\[0-9]\+" 1 } } */
/* { dg-final { scan-assembler-times "mov.l\tr\[0-9]\+,@-r\[0-9]\+" 1 } } */
diff --git a/gcc/testsuite/gcc.target/sh/pr51244-20.c b/gcc/testsuite/gcc.target/sh/pr51244-20.c
index c342163..be265cd 100644
--- a/gcc/testsuite/gcc.target/sh/pr51244-20.c
+++ b/gcc/testsuite/gcc.target/sh/pr51244-20.c
@@ -1,7 +1,7 @@
/* Check that the SH specific sh_treg_combine RTL optimization pass works as
expected. */
/* { dg-do compile } */
-/* { dg-options "-O2" } */
+/* { dg-options "-O2 -fno-tree-dominator-opts -fno-tree-vrp" } */
/* { dg-final { scan-assembler-not "not\t" } } */
/* { dg-final { scan-assembler-times "cmp/eq" 2 } } */
diff --git a/gcc/testsuite/gcc.target/x86_64/abi/avx/test_varargs-m256.c b/gcc/testsuite/gcc.target/x86_64/abi/avx/test_varargs-m256.c
new file mode 100644
index 0000000..0c6d61f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/x86_64/abi/avx/test_varargs-m256.c
@@ -0,0 +1,104 @@
+/* Test variable number of 256-bit vector arguments passed to functions. */
+
+#include <stdio.h>
+#include "avx-check.h"
+#include "args.h"
+
+struct IntegerRegisters iregs;
+struct FloatRegisters fregs;
+
+/* This struct holds values for argument checking. */
+struct
+{
+ YMM_T i0, i1, i2, i3, i4, i5, i6, i7, i8, i9;
+} values;
+
+char *pass;
+int failed = 0;
+
+#undef assert
+#define assert(c) do { \
+ if (!(c)) {failed++; printf ("failed %s\n", pass); } \
+} while (0)
+
+#define compare(X1,X2,T) do { \
+ assert (memcmp (&X1, &X2, sizeof (T)) == 0); \
+} while (0)
+
+void
+fun_check_passing_m256_varargs (__m256 i0, __m256 i1, __m256 i2,
+ __m256 i3, ...)
+{
+ /* Check argument values. */
+ void **fp = __builtin_frame_address (0);
+ void *ra = __builtin_return_address (0);
+ __m256 *argp;
+
+ compare (values.i0, i0, __m256);
+ compare (values.i1, i1, __m256);
+ compare (values.i2, i2, __m256);
+ compare (values.i3, i3, __m256);
+
+ /* Get the pointer to the return address on stack. */
+ while (*fp != ra)
+ fp++;
+
+ /* Skip the return address stack slot. */
+ argp = (__m256 *) (((char *) fp) + 8);
+
+ /* Check __m256 arguments passed on stack. */
+ compare (values.i4, argp[0], __m256);
+ compare (values.i5, argp[1], __m256);
+ compare (values.i6, argp[2], __m256);
+ compare (values.i7, argp[3], __m256);
+ compare (values.i8, argp[4], __m256);
+ compare (values.i9, argp[5], __m256);
+
+ /* Check register contents. */
+ compare (fregs.ymm0, ymm_regs[0], __m256);
+ compare (fregs.ymm1, ymm_regs[1], __m256);
+ compare (fregs.ymm2, ymm_regs[2], __m256);
+ compare (fregs.ymm3, ymm_regs[3], __m256);
+}
+
+#define def_check_int_passing_varargs(_i0, _i1, _i2, _i3, _i4, _i5, \
+ _i6, _i7, _i8, _i9, \
+ _func, TYPE) \
+ values.i0.TYPE[0] = _i0; \
+ values.i1.TYPE[0] = _i1; \
+ values.i2.TYPE[0] = _i2; \
+ values.i3.TYPE[0] = _i3; \
+ values.i4.TYPE[0] = _i4; \
+ values.i5.TYPE[0] = _i5; \
+ values.i6.TYPE[0] = _i6; \
+ values.i7.TYPE[0] = _i7; \
+ values.i8.TYPE[0] = _i8; \
+ values.i9.TYPE[0] = _i9; \
+ clear_struct_registers; \
+ fregs.F0.TYPE[0] = _i0; \
+ fregs.F1.TYPE[0] = _i1; \
+ fregs.F2.TYPE[0] = _i2; \
+ fregs.F3.TYPE[0] = _i3; \
+ WRAP_CALL(_func) (_i0, _i1, _i2, _i3, _i4, _i5, _i6, _i7, _i8, _i9);
+
+void
+test_m256_varargs (void)
+{
+ __m256 x[10];
+ int i;
+ for (i = 0; i < 10; i++)
+ x[i] = (__m256){32+i, 0, 0, 0, 0, 0, 0, 0};
+ pass = "m256-varargs";
+ def_check_int_passing_varargs (x[0], x[1], x[2], x[3], x[4], x[5],
+ x[6], x[7], x[8], x[9],
+ fun_check_passing_m256_varargs,
+ _m256);
+}
+
+void
+avx_test (void)
+{
+ test_m256_varargs ();
+ if (failed)
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.target/x86_64/abi/avx512f/abi-avx512f.exp b/gcc/testsuite/gcc.target/x86_64/abi/avx512f/abi-avx512f.exp
index 8b361a3..01bd9af 100644
--- a/gcc/testsuite/gcc.target/x86_64/abi/avx512f/abi-avx512f.exp
+++ b/gcc/testsuite/gcc.target/x86_64/abi/avx512f/abi-avx512f.exp
@@ -37,7 +37,6 @@ set additional_flags "-W -Wall -mavx512f"
foreach src [lsort [glob -nocomplain $srcdir/$subdir/test_*.c]] {
if {[runtest_file_p $runtests $src]} {
if { ([istarget *-*-darwin*]) } then {
- # FIXME: Darwin isn't tested.
c-torture-execute [list $src \
$srcdir/$subdir/asm-support-darwin.s] \
$additional_flags
diff --git a/gcc/testsuite/gcc.target/x86_64/abi/avx512f/asm-support-darwin.s b/gcc/testsuite/gcc.target/x86_64/abi/avx512f/asm-support-darwin.s
new file mode 100644
index 0000000..5364726
--- /dev/null
+++ b/gcc/testsuite/gcc.target/x86_64/abi/avx512f/asm-support-darwin.s
@@ -0,0 +1,93 @@
+ .text
+ .p2align 4,,15
+ .globl _snapshot
+_snapshot:
+LFB3:
+ movq %rax, _rax(%rip)
+ movq %rbx, _rbx(%rip)
+ movq %rcx, _rcx(%rip)
+ movq %rdx, _rdx(%rip)
+ movq %rdi, _rdi(%rip)
+ movq %rsi, _rsi(%rip)
+ movq %rbp, _rbp(%rip)
+ movq %rsp, _rsp(%rip)
+ movq %r8, _r8(%rip)
+ movq %r9, _r9(%rip)
+ movq %r10, _r10(%rip)
+ movq %r11, _r11(%rip)
+ movq %r12, _r12(%rip)
+ movq %r13, _r13(%rip)
+ movq %r14, _r14(%rip)
+ movq %r15, _r15(%rip)
+ vmovdqu32 %zmm0, _zmm_regs+0(%rip)
+ vmovdqu32 %zmm1, _zmm_regs+64(%rip)
+ vmovdqu32 %zmm2, _zmm_regs+128(%rip)
+ vmovdqu32 %zmm3, _zmm_regs+192(%rip)
+ vmovdqu32 %zmm4, _zmm_regs+256(%rip)
+ vmovdqu32 %zmm5, _zmm_regs+320(%rip)
+ vmovdqu32 %zmm6, _zmm_regs+384(%rip)
+ vmovdqu32 %zmm7, _zmm_regs+448(%rip)
+ vmovdqu32 %zmm8, _zmm_regs+512(%rip)
+ vmovdqu32 %zmm9, _zmm_regs+576(%rip)
+ vmovdqu32 %zmm10, _zmm_regs+640(%rip)
+ vmovdqu32 %zmm11, _zmm_regs+704(%rip)
+ vmovdqu32 %zmm12, _zmm_regs+768(%rip)
+ vmovdqu32 %zmm13, _zmm_regs+832(%rip)
+ vmovdqu32 %zmm14, _zmm_regs+896(%rip)
+ vmovdqu32 %zmm15, _zmm_regs+960(%rip)
+ vmovdqu32 %zmm16, _zmm_regs+1024(%rip)
+ vmovdqu32 %zmm17, _zmm_regs+1088(%rip)
+ vmovdqu32 %zmm18, _zmm_regs+1152(%rip)
+ vmovdqu32 %zmm19, _zmm_regs+1216(%rip)
+ vmovdqu32 %zmm20, _zmm_regs+1280(%rip)
+ vmovdqu32 %zmm21, _zmm_regs+1344(%rip)
+ vmovdqu32 %zmm22, _zmm_regs+1408(%rip)
+ vmovdqu32 %zmm23, _zmm_regs+1472(%rip)
+ vmovdqu32 %zmm24, _zmm_regs+1536(%rip)
+ vmovdqu32 %zmm25, _zmm_regs+1600(%rip)
+ vmovdqu32 %zmm26, _zmm_regs+1664(%rip)
+ vmovdqu32 %zmm27, _zmm_regs+1728(%rip)
+ vmovdqu32 %zmm28, _zmm_regs+1792(%rip)
+ vmovdqu32 %zmm29, _zmm_regs+1856(%rip)
+ vmovdqu32 %zmm30, _zmm_regs+1920(%rip)
+ vmovdqu32 %zmm31, _zmm_regs+1984(%rip)
+ jmp *_callthis(%rip)
+LFE3:
+
+ .p2align 4,,15
+ .globl _snapshot_ret
+_snapshot_ret:
+ movq %rdi, _rdi(%rip)
+ subq $8, %rsp
+ call *_callthis(%rip)
+ addq $8, %rsp
+ movq %rax, _rax(%rip)
+ movq %rdx, _rdx(%rip)
+ vmovdqu32 %zmm0, _zmm_regs+0(%rip)
+ vmovdqu32 %zmm1, _zmm_regs+64(%rip)
+ fstpt _x87_regs(%rip)
+ fstpt _x87_regs+16(%rip)
+ fldt _x87_regs+16(%rip)
+ fldt _x87_regs(%rip)
+ ret
+
+ .comm _callthis,8,8
+ .comm _rax,8,8
+ .comm _rbx,8,8
+ .comm _rcx,8,8
+ .comm _rdx,8,8
+ .comm _rsi,8,8
+ .comm _rdi,8,8
+ .comm _rsp,8,8
+ .comm _rbp,8,8
+ .comm _r8,8,8
+ .comm _r9,8,8
+ .comm _r10,8,8
+ .comm _r11,8,8
+ .comm _r12,8,8
+ .comm _r13,8,8
+ .comm _r14,8,8
+ .comm _r15,8,8
+ .comm _zmm_regs,2048,64
+ .comm _x87_regs,128,32
+ .comm _volatile_var,8,8
diff --git a/gcc/testsuite/gcc.target/x86_64/abi/avx512f/test_varargs-m512.c b/gcc/testsuite/gcc.target/x86_64/abi/avx512f/test_varargs-m512.c
new file mode 100644
index 0000000..b2ba0e5
--- /dev/null
+++ b/gcc/testsuite/gcc.target/x86_64/abi/avx512f/test_varargs-m512.c
@@ -0,0 +1,104 @@
+/* Test variable number of 512-bit vector arguments passed to functions. */
+
+#include <stdio.h>
+#include "avx512f-check.h"
+#include "args.h"
+
+struct IntegerRegisters iregs;
+struct FloatRegisters fregs;
+
+/* This struct holds values for argument checking. */
+struct
+{
+ ZMM_T i0, i1, i2, i3, i4, i5, i6, i7, i8, i9;
+} values;
+
+char *pass;
+int failed = 0;
+
+#undef assert
+#define assert(c) do { \
+ if (!(c)) {failed++; printf ("failed %s\n", pass); } \
+} while (0)
+
+#define compare(X1,X2,T) do { \
+ assert (memcmp (&X1, &X2, sizeof (T)) == 0); \
+} while (0)
+
+void
+fun_check_passing_m512_varargs (__m512 i0, __m512 i1, __m512 i2,
+ __m512 i3, ...)
+{
+ /* Check argument values. */
+ void **fp = __builtin_frame_address (0);
+ void *ra = __builtin_return_address (0);
+ __m512 *argp;
+
+ compare (values.i0, i0, __m512);
+ compare (values.i1, i1, __m512);
+ compare (values.i2, i2, __m512);
+ compare (values.i3, i3, __m512);
+
+ /* Get the pointer to the return address on stack. */
+ while (*fp != ra)
+ fp++;
+
+ /* Skip the return address stack slot. */
+ argp = (__m512 *)(((char *) fp) + 8);
+
+ /* Check __m512 arguments passed on stack. */
+ compare (values.i4, argp[0], __m512);
+ compare (values.i5, argp[1], __m512);
+ compare (values.i6, argp[2], __m512);
+ compare (values.i7, argp[3], __m512);
+ compare (values.i8, argp[4], __m512);
+ compare (values.i9, argp[5], __m512);
+
+ /* Check register contents. */
+ compare (fregs.zmm0, zmm_regs[0], __m512);
+ compare (fregs.zmm1, zmm_regs[1], __m512);
+ compare (fregs.zmm2, zmm_regs[2], __m512);
+ compare (fregs.zmm3, zmm_regs[3], __m512);
+}
+
+#define def_check_int_passing_varargs(_i0, _i1, _i2, _i3, _i4, _i5, \
+ _i6, _i7, _i8, _i9, \
+ _func, TYPE) \
+ values.i0.TYPE[0] = _i0; \
+ values.i1.TYPE[0] = _i1; \
+ values.i2.TYPE[0] = _i2; \
+ values.i3.TYPE[0] = _i3; \
+ values.i4.TYPE[0] = _i4; \
+ values.i5.TYPE[0] = _i5; \
+ values.i6.TYPE[0] = _i6; \
+ values.i7.TYPE[0] = _i7; \
+ values.i8.TYPE[0] = _i8; \
+ values.i9.TYPE[0] = _i9; \
+ clear_struct_registers; \
+ fregs.F0.TYPE[0] = _i0; \
+ fregs.F1.TYPE[0] = _i1; \
+ fregs.F2.TYPE[0] = _i2; \
+ fregs.F3.TYPE[0] = _i3; \
+ WRAP_CALL(_func) (_i0, _i1, _i2, _i3, _i4, _i5, _i6, _i7, _i8, _i9);
+
+void
+test_m512_varargs (void)
+{
+ __m512 x[10];
+ int i;
+ for (i = 0; i < 10; i++)
+ x[i] = (__m512){32+i, 0, 0, 0, 0, 0, 0, 0};
+ pass = "m512-varargs";
+ def_check_int_passing_varargs (x[0], x[1], x[2], x[3], x[4], x[5],
+ x[6], x[7], x[8], x[9],
+ fun_check_passing_m512_varargs,
+ _m512);
+}
+
+void
+avx512f_test (void)
+{
+ test_m512_varargs ();
+ if (failed)
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.target/x86_64/abi/test_varargs-m128.c b/gcc/testsuite/gcc.target/x86_64/abi/test_varargs-m128.c
new file mode 100644
index 0000000..3075768
--- /dev/null
+++ b/gcc/testsuite/gcc.target/x86_64/abi/test_varargs-m128.c
@@ -0,0 +1,110 @@
+/* Test variable number of 128-bit vector arguments passed to functions. */
+
+#include <stdio.h>
+#include "defines.h"
+#include "macros.h"
+#include "args.h"
+
+struct IntegerRegisters iregs;
+struct FloatRegisters fregs;
+
+/* This struct holds values for argument checking. */
+struct
+{
+ XMM_T i0, i1, i2, i3, i4, i5, i6, i7, i8, i9;
+} values;
+
+char *pass;
+int failed = 0;
+
+#undef assert
+#define assert(c) do { \
+ if (!(c)) {failed++; printf ("failed %s\n", pass); } \
+} while (0)
+
+#define compare(X1,X2,T) do { \
+ assert (memcmp (&X1, &X2, sizeof (T)) == 0); \
+} while (0)
+
+void
+fun_check_passing_m128_varargs (__m128 i0, __m128 i1, __m128 i2,
+ __m128 i3, ...)
+{
+ /* Check argument values. */
+ void **fp = __builtin_frame_address (0);
+ void *ra = __builtin_return_address (0);
+ __m128 *argp;
+
+ compare (values.i0, i0, __m128);
+ compare (values.i1, i1, __m128);
+ compare (values.i2, i2, __m128);
+ compare (values.i3, i3, __m128);
+
+ /* Get the pointer to the return address on stack. */
+ while (*fp != ra)
+ fp++;
+
+ /* Skip the return address stack slot. */
+ argp = (__m128 *) (((char *) fp) + 8);
+
+ /* Check __m128 arguments passed on stack. */
+ compare (values.i8, argp[0], __m128);
+ compare (values.i9, argp[1], __m128);
+
+ /* Check register contents. */
+ compare (fregs.xmm0, xmm_regs[0], __m128);
+ compare (fregs.xmm1, xmm_regs[1], __m128);
+ compare (fregs.xmm2, xmm_regs[2], __m128);
+ compare (fregs.xmm3, xmm_regs[3], __m128);
+ compare (fregs.xmm4, xmm_regs[4], __m128);
+ compare (fregs.xmm5, xmm_regs[5], __m128);
+ compare (fregs.xmm6, xmm_regs[6], __m128);
+ compare (fregs.xmm7, xmm_regs[7], __m128);
+}
+
+#define def_check_int_passing_varargs(_i0, _i1, _i2, _i3, _i4, _i5, \
+ _i6, _i7, _i8, _i9, \
+ _func, TYPE) \
+ values.i0.TYPE[0] = _i0; \
+ values.i1.TYPE[0] = _i1; \
+ values.i2.TYPE[0] = _i2; \
+ values.i3.TYPE[0] = _i3; \
+ values.i4.TYPE[0] = _i4; \
+ values.i5.TYPE[0] = _i5; \
+ values.i6.TYPE[0] = _i6; \
+ values.i7.TYPE[0] = _i7; \
+ values.i8.TYPE[0] = _i8; \
+ values.i9.TYPE[0] = _i9; \
+ clear_float_registers; \
+ fregs.F0.TYPE[0] = _i0; \
+ fregs.F1.TYPE[0] = _i1; \
+ fregs.F2.TYPE[0] = _i2; \
+ fregs.F3.TYPE[0] = _i3; \
+ fregs.F4.TYPE[0] = _i4; \
+ fregs.F5.TYPE[0] = _i5; \
+ fregs.F6.TYPE[0] = _i6; \
+ fregs.F7.TYPE[0] = _i7; \
+ WRAP_CALL(_func) (_i0, _i1, _i2, _i3, _i4, _i5, _i6, _i7, _i8, _i9);
+
+void
+test_m128_varargs (void)
+{
+ __m128 x[10];
+ int i;
+ for (i = 0; i < 10; i++)
+ x[i] = (__m128){32+i, 0, 0, 0};
+ pass = "m128-varargs";
+ def_check_int_passing_varargs (x[0], x[1], x[2], x[3], x[4], x[5],
+ x[6], x[7], x[8], x[9],
+ fun_check_passing_m128_varargs,
+ _m128);
+}
+
+int
+main (void)
+{
+ test_m128_varargs ();
+ if (failed)
+ abort ();
+ return 0;
+}
diff --git a/gcc/testsuite/gdc.dg/pr90650a.d b/gcc/testsuite/gdc.dg/pr90650a.d
new file mode 100644
index 0000000..57228ca
--- /dev/null
+++ b/gcc/testsuite/gdc.dg/pr90650a.d
@@ -0,0 +1,14 @@
+// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=90650
+// { dg-do compile }
+class c
+{
+ static f ()
+ {
+ return 0;
+ }
+}
+
+void g ()
+{
+ if (0 & [0] & c.f()) {} // { dg-error "array operation \\\[0\\\] & 0 & f\\(\\) without destination memory not allowed" }
+}
diff --git a/gcc/testsuite/gdc.dg/pr90650b.d b/gcc/testsuite/gdc.dg/pr90650b.d
new file mode 100644
index 0000000..2b3192e
--- /dev/null
+++ b/gcc/testsuite/gdc.dg/pr90650b.d
@@ -0,0 +1,13 @@
+// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=90650
+// { dg-do compile }
+class c
+{
+ static f ()
+ {
+ return 0;
+ }
+}
+void g ()
+{
+ if ([0] & c.f()) {} // { dg-error "array operation \\\[0\\\] & f\\(\\) without destination memory not allowed" }
+}
diff --git a/gcc/testsuite/gdc.test/compilable/aggr_alignment.d b/gcc/testsuite/gdc.test/compilable/aggr_alignment.d
index 3a80a03..bf602ff 100644
--- a/gcc/testsuite/gdc.test/compilable/aggr_alignment.d
+++ b/gcc/testsuite/gdc.test/compilable/aggr_alignment.d
@@ -26,3 +26,16 @@ enum payloadOffset = C2.bytes.offsetof;
static assert(C2.int1.offsetof == payloadOffset + 8);
static assert(C2.alignof == size_t.sizeof);
static assert(__traits(classInstanceSize, C2) == payloadOffset + 12);
+
+
+/***************************************************/
+// https://issues.dlang.org/show_bug.cgi?id=19914
+// https://issues.dlang.org/show_bug.cgi?id=19915
+
+class TemplatedClass(T)
+{
+ align T field;
+}
+
+mixin TemplatedClass!(string);
+alias TCint = TemplatedClass!(int);
diff --git a/gcc/testsuite/gdc.test/compilable/b16976.d b/gcc/testsuite/gdc.test/compilable/b16976.d
new file mode 100644
index 0000000..f5f45ef
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/b16976.d
@@ -0,0 +1,66 @@
+/* REQUIRED_ARGS: -m64
+TEST_OUTPUT:
+---
+compilable/b16976.d(33): Deprecation: foreach: loop index implicitly converted from `size_t` to `int`
+compilable/b16976.d(34): Deprecation: foreach: loop index implicitly converted from `size_t` to `int`
+compilable/b16976.d(35): Deprecation: foreach: loop index implicitly converted from `size_t` to `char`
+compilable/b16976.d(36): Deprecation: foreach: loop index implicitly converted from `size_t` to `char`
+compilable/b16976.d(41): Deprecation: foreach: loop index implicitly converted from `size_t` to `int`
+compilable/b16976.d(42): Deprecation: foreach: loop index implicitly converted from `size_t` to `int`
+compilable/b16976.d(43): Deprecation: foreach: loop index implicitly converted from `size_t` to `char`
+compilable/b16976.d(44): Deprecation: foreach: loop index implicitly converted from `size_t` to `char`
+compilable/b16976.d(50): Deprecation: foreach: loop index implicitly converted from `size_t` to `int`
+compilable/b16976.d(51): Deprecation: foreach: loop index implicitly converted from `size_t` to `int`
+compilable/b16976.d(52): Deprecation: foreach: loop index implicitly converted from `size_t` to `char`
+compilable/b16976.d(53): Deprecation: foreach: loop index implicitly converted from `size_t` to `char`
+compilable/b16976.d(58): Deprecation: foreach: loop index implicitly converted from `size_t` to `int`
+compilable/b16976.d(59): Deprecation: foreach: loop index implicitly converted from `size_t` to `int`
+compilable/b16976.d(60): Deprecation: foreach: loop index implicitly converted from `size_t` to `char`
+compilable/b16976.d(61): Deprecation: foreach: loop index implicitly converted from `size_t` to `char`
+compilable/b16976.d(62): Deprecation: foreach: loop index implicitly converted from `size_t` to `int`
+compilable/b16976.d(63): Deprecation: foreach: loop index implicitly converted from `size_t` to `int`
+compilable/b16976.d(64): Deprecation: foreach: loop index implicitly converted from `size_t` to `char`
+compilable/b16976.d(65): Deprecation: foreach: loop index implicitly converted from `size_t` to `char`
+---
+*/
+void main()
+{
+ int[] dyn = [1,2,3,4,5];
+ int[5] sta = [1,2,3,4,5];
+ char[] str = ['1','2','3','4','5'];
+ char[5] chr = ['1','2','3','4','5'];
+
+ foreach(int i, v; dyn) { }
+ foreach_reverse(int i, v; dyn) { }
+ foreach(char i, v; dyn) { }
+ foreach_reverse(char i, v; dyn) { }
+ foreach(int i, v; sta) { }
+ foreach_reverse(int i, v; sta) { }
+ foreach(char i, v; sta) { }
+ foreach_reverse(char i, v; sta) { }
+ foreach(int i, v; str) { }
+ foreach_reverse(int i, v; str) { }
+ foreach(char i, v; str) { }
+ foreach_reverse(char i, v; str) { }
+ foreach(int i, v; chr) { }
+ foreach_reverse(int i, v; chr) { }
+ foreach(char i, v; chr) { }
+ foreach_reverse(char i, v; chr) { }
+
+ foreach(int i, dchar v; dyn) { }
+ foreach_reverse(int i, dchar v; dyn) { }
+ foreach(char i, dchar v; dyn) { }
+ foreach_reverse(char i, dchar v; dyn) { }
+ foreach(int i, dchar v; sta) { }
+ foreach_reverse(int i, dchar v; sta) { }
+ foreach(char i, dchar v; sta) { }
+ foreach_reverse(char i, dchar v; sta) { }
+ foreach(int i, dchar v; str) { }
+ foreach_reverse(int i, dchar v; str) { }
+ foreach(char i, dchar v; str) { }
+ foreach_reverse(char i, dchar v; str) { }
+ foreach(int i, dchar v; chr) { }
+ foreach_reverse(int i, dchar v; chr) { }
+ foreach(char i, dchar v; chr) { }
+ foreach_reverse(char i, dchar v; chr) { }
+}
diff --git a/gcc/testsuite/gdc.test/compilable/imports/test16214b.d b/gcc/testsuite/gdc.test/compilable/imports/test16214b.d
new file mode 100644
index 0000000..e2036fc
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/imports/test16214b.d
@@ -0,0 +1,10 @@
+module test16214b;
+import test16214a;
+
+struct Appender() { int[] arr; }
+struct Tuple() { alias A = Appender!(); }
+
+class EventLoop
+{
+ auto f() { auto x = [Tuple!().init]; }
+}
diff --git a/gcc/testsuite/gdc.test/compilable/interpret3.d b/gcc/testsuite/gdc.test/compilable/interpret3.d
index 386743e..36cdd13 100644
--- a/gcc/testsuite/gdc.test/compilable/interpret3.d
+++ b/gcc/testsuite/gdc.test/compilable/interpret3.d
@@ -3396,13 +3396,13 @@ bool test3512()
assert(q == 6);
// _aApplycw2
- foreach (int i, wchar c; s)
+ foreach (ptrdiff_t i, wchar c; s)
{
assert(i >= 0 && i < s.length);
}
// _aApplycd2
- foreach (int i, dchar c; s)
+ foreach (ptrdiff_t i, dchar c; s)
{
assert(i >= 0 && i < s.length);
}
@@ -3424,13 +3424,13 @@ bool test3512()
assert(q == 13);
// _aApplywc2
- foreach (int i, char c; w)
+ foreach (ptrdiff_t i, char c; w)
{
assert(i >= 0 && i < w.length);
}
// _aApplywd2
- foreach (int i, dchar c; w)
+ foreach (ptrdiff_t i, dchar c; w)
{
assert(i >= 0 && i < w.length);
}
@@ -3454,19 +3454,19 @@ bool test3512()
assert(q == 3);
// _aApplydc2
- foreach (int i, char c; d)
+ foreach (ptrdiff_t i, char c; d)
{
assert(i >= 0 && i < d.length);
}
// _aApplydw2
- foreach (int i, wchar c; d)
+ foreach (ptrdiff_t i, wchar c; d)
{
assert(i >= 0 && i < d.length);
}
dchar[] dr = "squop"d.dup;
- foreach (int n, char c; dr)
+ foreach (ptrdiff_t n, char c; dr)
{
if (n == 2)
break;
@@ -3482,7 +3482,7 @@ bool test3512()
{}
// _aApplyRdc2
- foreach_reverse (int n, char c; dr)
+ foreach_reverse (ptrdiff_t n, char c; dr)
{
if (n == 4)
break;
@@ -3490,14 +3490,14 @@ bool test3512()
}
// _aApplyRdw2
- foreach_reverse (int i, wchar c; dr)
+ foreach_reverse (ptrdiff_t i, wchar c; dr)
{
assert(i >= 0 && i < dr.length);
}
q = 0;
wstring w2 = ['x', 'ü', 'm']; // foreach over array literals
- foreach_reverse (int n, char c; w2)
+ foreach_reverse (ptrdiff_t n, char c; w2)
{
++q;
if (c == 'm') assert(n == 2 && q == 1);
diff --git a/gcc/testsuite/gdc.test/compilable/test16214a.d b/gcc/testsuite/gdc.test/compilable/test16214a.d
new file mode 100644
index 0000000..2ea64d9
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/test16214a.d
@@ -0,0 +1,7 @@
+// EXTRA_SOURCES: imports/test16214b.d
+// REQUIRED_ARGS: -Icompilable/imports
+
+module test16214a;
+import test16214b;
+
+class LibasyncEventLoop : EventLoop {}
diff --git a/gcc/testsuite/gdc.test/compilable/test19912.d b/gcc/testsuite/gdc.test/compilable/test19912.d
new file mode 100644
index 0000000..7a6bc9e
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/test19912.d
@@ -0,0 +1,3 @@
+// PERMUTE_ARGS:
+import object;
+void fun(string) { }
diff --git a/gcc/testsuite/gdc.test/compilable/test19941.d b/gcc/testsuite/gdc.test/compilable/test19941.d
new file mode 100644
index 0000000..add1d41
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/test19941.d
@@ -0,0 +1,57 @@
+// https://issues.dlang.org/show_bug.cgi?id=19941
+
+/******************************************/
+
+immutable i4 = 42;
+const v4 = new C4;
+class C4 { int f4 = i4; }
+
+const v5 = new C5;
+immutable i5 = 42;
+class C5 { int f5 = i5; }
+
+const v6 = new C6;
+class C6 { int f6 = i6; }
+immutable i6 = 42;
+
+/******************************************/
+
+immutable i10 = 42;
+__gshared v10 = new C10;
+class C10 { int f10 = i10; }
+
+__gshared v11 = new C11;
+immutable i11 = 42;
+class C11 { int f11 = i11; }
+
+__gshared v12 = new C12;
+class C12 { int f12 = i12; }
+immutable i12 = 42;
+
+/******************************************/
+
+immutable i13 = 42;
+immutable v13 = new C13;
+class C13 { int f13 = i13; }
+
+immutable v14 = new C14;
+immutable i14 = 42;
+class C14 { int f14 = i14; }
+
+immutable v15 = new C15;
+class C15 { int f15 = i15; }
+immutable i15 = 42;
+
+/******************************************/
+
+immutable i16 = 42;
+shared v16 = new C16;
+class C16 { int f16 = i16; }
+
+shared v17 = new C17;
+immutable i17 = 42;
+class C17 { int f17 = i17; }
+
+shared v18 = new C18;
+class C18 { int f18 = i18; }
+immutable i18 = 42;
diff --git a/gcc/testsuite/gdc.test/compilable/traits.d b/gcc/testsuite/gdc.test/compilable/traits.d
new file mode 100644
index 0000000..736eae4
--- /dev/null
+++ b/gcc/testsuite/gdc.test/compilable/traits.d
@@ -0,0 +1,10 @@
+// REQUIRED_ARGS:
+
+// This file is intended to contain all compilable traits-related tests in an
+// effort to keep the number of files in the `compilable` folder to a minimum.
+
+/******************************************/
+// https://issues.dlang.org/show_bug.cgi?id=19942
+
+static assert(!__traits(compiles, { a.init; }));
+static assert(!__traits(compiles, { import m : a; a.init; }));
diff --git a/gcc/testsuite/gdc.test/fail_compilation/b15875.d b/gcc/testsuite/gdc.test/fail_compilation/b15875.d
new file mode 100644
index 0000000..daa79b7
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/b15875.d
@@ -0,0 +1,10 @@
+/* TEST_OUTPUT:
+---
+fail_compilation/b15875.d(9): Error: circular reference to variable `a`
+fail_compilation/b15875.d(10): Error: circular reference to `b15875.f`
+---
+*/
+// https://issues.dlang.org/show_bug.cgi?id=15875
+// https://issues.dlang.org/show_bug.cgi?id=17290
+d o(int[a]a)(){}
+f.T f(){}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/b17285.d b/gcc/testsuite/gdc.test/fail_compilation/b17285.d
new file mode 100644
index 0000000..7b79cf0
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/b17285.d
@@ -0,0 +1,15 @@
+/*
+TEST_OUTPUT:
+---
+fail_compilation/b17285.d(14): Error: type `ONE` has no value
+fail_compilation/b17285.d(14): Error: type `TWO` has no value
+fail_compilation/b17285.d(14): Error: cannot implicitly convert expression `ONE` of type `b17285.ONE` to `int`
+---
+*/
+
+class ONE {}
+enum TWO;
+
+void foo() {
+ foreach(key; [ONE, TWO, 1]) {}
+}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/b19691.d b/gcc/testsuite/gdc.test/fail_compilation/b19691.d
new file mode 100644
index 0000000..8663512
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/b19691.d
@@ -0,0 +1,20 @@
+// REQUIRED_ARGS: -de
+/* TEST_OUTPUT:
+---
+fail_compilation/b19691.d(13): Error: forward reference to template `this`
+fail_compilation/b19691.d(19): Deprecation: constructor `b19691.S2.this` all parameters have default arguments, but structs cannot have default constructors.
+---
+*/
+// https://issues.dlang.org/show_bug.cgi?id=19691
+module b19691;
+
+struct S1 {
+ this(T...)(T) {
+ S2("");
+ }
+}
+
+struct S2 {
+ this(string) {}
+ this(S1 s = null) {}
+}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/b19691e.d b/gcc/testsuite/gdc.test/fail_compilation/b19691e.d
new file mode 100644
index 0000000..21d0e90
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/b19691e.d
@@ -0,0 +1,24 @@
+// REQUIRED_ARGS: -de
+/* TEST_OUTPUT:
+---
+fail_compilation/b19691e.d(17): Error: forward reference to template `this`
+fail_compilation/b19691e.d(17): Error: constructor `b19691e.S2.this(S1 s = "")` is not callable using argument types `(string)`
+fail_compilation/b19691e.d(17): Error: forward reference to template `this`
+fail_compilation/b19691e.d(23): Deprecation: constructor `b19691e.S2.this` all parameters have default arguments, but structs cannot have default constructors.
+---
+*/
+// https://issues.dlang.org/show_bug.cgi?id=19691
+module b19691e;
+
+struct S1
+{
+ this(T)(T)
+ {
+ S2("");
+ }
+}
+
+struct S2
+{
+ this(S1 s = ""){}
+}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/b19717.d b/gcc/testsuite/gdc.test/fail_compilation/b19717.d
new file mode 100644
index 0000000..6a48b88
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/b19717.d
@@ -0,0 +1,16 @@
+/*
+TEST_OUTPUT:
+---
+fail_compilation/b19717.d(16): Error: undefined identifier `Foo`, did you mean function `foo`?
+fail_compilation/b19717.d(13): Error: forward reference to template `foo`
+fail_compilation/b19717.d(13): Error: forward reference to inferred return type of function call `foo()`
+---
+*/
+
+enum bar = __traits(getMember, mixin(__MODULE__), "foo");
+
+auto foo() {
+ return foo();
+}
+
+void foo(Foo) {}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/b19717a.d b/gcc/testsuite/gdc.test/fail_compilation/b19717a.d
new file mode 100644
index 0000000..79a9de0
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/b19717a.d
@@ -0,0 +1,14 @@
+// REQUIRED_ARGS: -de
+/* TEST_OUTPUT:
+---
+fail_compilation/b19717a.d(14): Error: forward reference to template `a`
+fail_compilation/b19717a.d(14): Error: forward reference to template `a`
+fail_compilation/b19717a.d(14): Error: none of the overloads of `a` are callable using argument types `()`, candidates are:
+fail_compilation/b19717a.d(13): `b19717a.a(int b)`
+fail_compilation/b19717a.d(14): `b19717a.a(int b = a)`
+---
+*/
+module b19717a;
+
+auto a(int b) {}
+auto a(int b = a) {}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/diag16976.d b/gcc/testsuite/gdc.test/fail_compilation/diag16976.d
new file mode 100644
index 0000000..ebfb72b
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/diag16976.d
@@ -0,0 +1,44 @@
+/* TEST_OUTPUT:
+---
+fail_compilation/diag16976.d(28): Error: foreach: key cannot be of non-integral type `float`
+fail_compilation/diag16976.d(29): Error: foreach: key cannot be of non-integral type `float`
+fail_compilation/diag16976.d(30): Error: foreach: key cannot be of non-integral type `float`
+fail_compilation/diag16976.d(31): Error: foreach: key cannot be of non-integral type `float`
+fail_compilation/diag16976.d(32): Error: foreach: key cannot be of non-integral type `float`
+fail_compilation/diag16976.d(33): Error: foreach: key cannot be of non-integral type `float`
+fail_compilation/diag16976.d(34): Error: foreach: key cannot be of non-integral type `float`
+fail_compilation/diag16976.d(35): Error: foreach: key cannot be of non-integral type `float`
+fail_compilation/diag16976.d(36): Error: foreach: key cannot be of non-integral type `float`
+fail_compilation/diag16976.d(37): Error: foreach: key cannot be of non-integral type `float`
+fail_compilation/diag16976.d(38): Error: foreach: key cannot be of non-integral type `float`
+fail_compilation/diag16976.d(39): Error: foreach: key cannot be of non-integral type `float`
+fail_compilation/diag16976.d(40): Error: foreach: key cannot be of non-integral type `float`
+fail_compilation/diag16976.d(41): Error: foreach: key cannot be of non-integral type `float`
+fail_compilation/diag16976.d(42): Error: foreach: key cannot be of non-integral type `float`
+fail_compilation/diag16976.d(43): Error: foreach: key cannot be of non-integral type `float`
+---
+*/
+
+void main()
+{
+ int[] dyn = [1,2,3,4,5];
+ int[5] sta = [1,2,3,4,5];
+ char[] str = ['1','2','3','4','5'];
+ char[5] chr = ['1','2','3','4','5'];
+ foreach(float f, i; dyn) {}
+ foreach(float f, i; sta) {}
+ foreach(float f, i; str) {}
+ foreach(float f, i; chr) {}
+ foreach(float f, dchar i; dyn) {}
+ foreach(float f, dchar i; sta) {}
+ foreach(float f, dchar i; str) {}
+ foreach(float f, dchar i; chr) {}
+ foreach_reverse(float f, i; dyn) {}
+ foreach_reverse(float f, i; sta) {}
+ foreach_reverse(float f, i; str) {}
+ foreach_reverse(float f, i; chr) {}
+ foreach_reverse(float f, dchar i; dyn) {}
+ foreach_reverse(float f, dchar i; sta) {}
+ foreach_reverse(float f, dchar i; str) {}
+ foreach_reverse(float f, dchar i; chr) {}
+}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/extra-files/minimal/object.d b/gcc/testsuite/gdc.test/fail_compilation/extra-files/minimal/object.d
new file mode 100644
index 0000000..c7060b0
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/extra-files/minimal/object.d
@@ -0,0 +1 @@
+module object;
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail110.d b/gcc/testsuite/gdc.test/fail_compilation/fail110.d
index 3e9beb0..4703401 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/fail110.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail110.d
@@ -14,6 +14,6 @@ void main()
int i;
int[] a;
foreach (i; a) {}
- foreach (int i, n; a) {}
+ foreach (size_t i, n; a) {}
for (int i;;) {}
}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail19890a.d b/gcc/testsuite/gdc.test/fail_compilation/fail19890a.d
new file mode 100644
index 0000000..57c4caf
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail19890a.d
@@ -0,0 +1,7 @@
+// PERMUTE_ARGS:
+/*
+---
+fail_compilation/fail19890a.d(8): Error: `void[/^[0-9]+(LU)?$/]` size 1 * /^[0-9]+$/ exceeds 0x7fffffff size limit for static array
+---
+*/
+void[] f = cast(void[-1]) "a";
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail19890b.d b/gcc/testsuite/gdc.test/fail_compilation/fail19890b.d
new file mode 100644
index 0000000..a9b1874
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail19890b.d
@@ -0,0 +1,7 @@
+// PERMUTE_ARGS:
+/*
+---
+fail_compilation/fail19890b.d(8): Error: `void[/^[0-9]+(LU)?$/]` size 1 * /^[0-9]+$/ exceeds 0x7fffffff size limit for static array
+---
+*/
+void[] f = cast(void[-2]) "a";
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail19897.d b/gcc/testsuite/gdc.test/fail_compilation/fail19897.d
new file mode 100644
index 0000000..8dd4e14
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail19897.d
@@ -0,0 +1,13 @@
+// PERMUTE_ARGS:
+/*
+TEST_OUTPUT
+---
+fail_compilation/fail19897.d(10): Error: cannot implicitly convert expression `[]` of type `const(char[0])` to `const(char)`
+---
+*/
+struct S
+{
+ char[0] x;
+}
+const a = S('a');
+const char c = a.x;
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail19898a.d b/gcc/testsuite/gdc.test/fail_compilation/fail19898a.d
new file mode 100644
index 0000000..406e468
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail19898a.d
@@ -0,0 +1,14 @@
+/*
+PERMUTE_ARGS:
+REQUIRED_ARGS: -m64
+TEST_OUTPUT:
+---
+fail_compilation/fail19898a.d(11): Error: incompatible types for `(__key2) < (__limit3)`: both operands are of type `__vector(int[4])`
+---
+*/
+void f (__vector(int[4]) n)
+{
+ foreach (i; 0 .. n)
+ cast(void)n;
+}
+
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail19898b.d b/gcc/testsuite/gdc.test/fail_compilation/fail19898b.d
new file mode 100644
index 0000000..0b47fb78
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail19898b.d
@@ -0,0 +1,21 @@
+/*
+PERMUTE_ARGS:
+REQUIRED_ARGS: -m64
+TEST_OUTPUT:
+---
+fail_compilation/fail19898b.d(18): Error: cannot implicitly convert expression `m` of type `S` to `__vector(int[4])`
+fail_compilation/fail19898b.d(18): Error: incompatible types for `(__key2) != (__limit3)`: both operands are of type `__vector(int[4])`
+fail_compilation/fail19898b.d(18): Error: cannot cast expression `__key2` of type `__vector(int[4])` to `S`
+---
+*/
+struct S
+{
+ int a;
+}
+
+void f (__vector(int[4]) n, S m)
+{
+ foreach (i; m .. n)
+ cast(void)n;
+}
+
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail19911a.d b/gcc/testsuite/gdc.test/fail_compilation/fail19911a.d
new file mode 100644
index 0000000..672db30
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail19911a.d
@@ -0,0 +1,11 @@
+/*
+REQUIRED_ARGS: -betterC
+TEST_OUTPUT:
+---
+fail_compilation/fail19911a.d(9): Error: function `fail19911a.fun` D-style variadic functions cannot be used with -betterC
+---
+*/
+
+void fun(...)
+{
+}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail19911b.d b/gcc/testsuite/gdc.test/fail_compilation/fail19911b.d
new file mode 100644
index 0000000..b4ad22b
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail19911b.d
@@ -0,0 +1,13 @@
+/*
+DFLAGS:
+REQUIRED_ARGS:
+EXTRA_SOURCES: extra-files/minimal/object.d
+TEST_OUTPUT:
+---
+fail_compilation/fail19911b.d(10): Error: function `fail19911b.fun` `object.TypeInfo_Tuple` could not be found, but is implicitly used in D-style variadic functions
+---
+*/
+
+void fun(...)
+{
+}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail19911c.d b/gcc/testsuite/gdc.test/fail_compilation/fail19911c.d
new file mode 100644
index 0000000..d1e954e
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail19911c.d
@@ -0,0 +1,17 @@
+/*
+DFLAGS:
+REQUIRED_ARGS:
+TEST_OUTPUT:
+---
+fail_compilation/fail19911c.d(15): Error: function `object.fun` `object.TypeInfo` could not be found, but is implicitly used in D-style variadic functions
+---
+*/
+
+module object;
+
+class Object { }
+class TypeInfo_Tuple { }
+
+void fun(...)
+{
+}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail19912a.d b/gcc/testsuite/gdc.test/fail_compilation/fail19912a.d
new file mode 100644
index 0000000..47d3cf2
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail19912a.d
@@ -0,0 +1,9 @@
+// PERMUTE_ARGS:
+/*
+TEST_OUTPUT:
+---
+fail_compilation/fail19912a.d(8): Error: struct `fail19912a.object` conflicts with import `fail19912a.object` at fail_compilation/fail19912a.d
+---
+*/
+struct object { }
+void fun(string) { }
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail19912b.d b/gcc/testsuite/gdc.test/fail_compilation/fail19912b.d
new file mode 100644
index 0000000..b3bd56d
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail19912b.d
@@ -0,0 +1,9 @@
+// PERMUTE_ARGS:
+/*
+TEST_OUTPUT:
+---
+fail_compilation/fail19912b.d(8): Error: class `fail19912b.object` conflicts with import `fail19912b.object` at fail_compilation/fail19912b.d
+---
+*/
+class object { }
+void fun(string) { }
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail19912c.d b/gcc/testsuite/gdc.test/fail_compilation/fail19912c.d
new file mode 100644
index 0000000..a4656cc
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail19912c.d
@@ -0,0 +1,9 @@
+// PERMUTE_ARGS:
+/*
+TEST_OUTPUT:
+---
+fail_compilation/fail19912c.d(8): Error: alias `fail19912c.object` conflicts with import `fail19912c.object` at fail_compilation/fail19912c.d
+---
+*/
+alias object = int;
+void fun(string) { }
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail19912d.d b/gcc/testsuite/gdc.test/fail_compilation/fail19912d.d
new file mode 100644
index 0000000..fdc8dcb
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail19912d.d
@@ -0,0 +1,9 @@
+// PERMUTE_ARGS:
+/*
+TEST_OUTPUT:
+---
+fail_compilation/fail19912d.d(8): Error: enum `fail19912d.object` conflicts with import `fail19912d.object` at fail_compilation/fail19912d.d
+---
+*/
+enum object { }
+void fun(string) { }
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail19912e.d b/gcc/testsuite/gdc.test/fail_compilation/fail19912e.d
new file mode 100644
index 0000000..19cc9a6
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail19912e.d
@@ -0,0 +1,9 @@
+// PERMUTE_ARGS:
+/*
+TEST_OUTPUT:
+---
+fail_compilation/fail19912e.d(8): Error: function `fail19912e.object` conflicts with import `fail19912e.object` at fail_compilation/fail19912e.d
+---
+*/
+void object() { }
+void fun(string) { }
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail19913.d b/gcc/testsuite/gdc.test/fail_compilation/fail19913.d
new file mode 100644
index 0000000..b0f31b5
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail19913.d
@@ -0,0 +1,13 @@
+/* PERMUTE_ARGS:
+ * TEST_OUTPUT:
+---
+fail_compilation/fail19913.d(11): Error: no property `b` for type `int`
+fail_compilation/fail19913.d(11): Error: mixin `fail19913.S.b!()` is not defined
+---
+ */
+
+struct S
+{
+ mixin a.b;
+ enum { a }
+}
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail19914.d b/gcc/testsuite/gdc.test/fail_compilation/fail19914.d
new file mode 100644
index 0000000..a890d35
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail19914.d
@@ -0,0 +1,10 @@
+// PERMUTE_ARGS:
+/*
+TEST_OUTPUT:
+---
+fail_compilation/fail19914.d(9): Error: undefined identifier `c` in module `fail19914`
+fail_compilation/fail19914.d(10): Error: mixin `fail19914.a!string` error instantiating
+---
+*/
+class a(b) { align.c d; }
+mixin a!(string);
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail19915.d b/gcc/testsuite/gdc.test/fail_compilation/fail19915.d
new file mode 100644
index 0000000..17e05ee
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail19915.d
@@ -0,0 +1,10 @@
+// PERMUTE_ARGS:
+/*
+TEST_OUTPUT:
+---
+fail_compilation/fail19915.d(9): Error: undefined identifier `c` in module `fail19915`
+fail_compilation/fail19915.d(10): Error: template instance `fail19915.a!int` error instantiating
+---
+*/
+class a (b) { align.c d; }
+alias a!(int) e;
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail19922.d b/gcc/testsuite/gdc.test/fail_compilation/fail19922.d
new file mode 100644
index 0000000..5c9e2bb
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail19922.d
@@ -0,0 +1,19 @@
+/*
+DFLAGS:
+REQUIRED_ARGS:
+TEST_OUTPUT:
+---
+fail_compilation/fail19922.d(17): Error: `object.TypeInfo_Class` could not be found, but is implicitly used
+---
+*/
+
+module object;
+
+class Object {}
+
+void test()
+{
+ Object o;
+ auto ti = typeid(o);
+}
+
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail19923.d b/gcc/testsuite/gdc.test/fail_compilation/fail19923.d
new file mode 100644
index 0000000..042cf8a
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail19923.d
@@ -0,0 +1,19 @@
+/*
+DFLAGS:
+REQUIRED_ARGS:
+TEST_OUTPUT:
+---
+fail_compilation/fail19923.d(17): Error: `object.TypeInfo_Class` could not be found, but is implicitly used
+---
+*/
+
+module object;
+
+class Object {}
+
+void test()
+{
+ Object o;
+ auto ti = o.classinfo;
+}
+
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail19941.d b/gcc/testsuite/gdc.test/fail_compilation/fail19941.d
new file mode 100644
index 0000000..61e174b
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail19941.d
@@ -0,0 +1,62 @@
+/*
+TEST_OUTPUT:
+---
+fail_compilation/fail19941.d(8): Error: undefined identifier `dne`
+---
+*/
+auto a = new Auto;
+class Auto { int field = &dne; }
+
+/*
+TEST_OUTPUT:
+---
+fail_compilation/fail19941.d(17): Error: undefined identifier `dne`
+---
+*/
+const c = new Const;
+class Const { int field = &dne; }
+
+/*
+TEST_OUTPUT:
+---
+fail_compilation/fail19941.d(26): Error: undefined identifier `dne`
+---
+*/
+enum e = new Enum;
+class Enum { int field = &dne; }
+
+/*
+TEST_OUTPUT:
+---
+fail_compilation/fail19941.d(35): Error: undefined identifier `dne`
+---
+*/
+__gshared g = new Gshared;
+class Gshared { int field = &dne; }
+
+/*
+TEST_OUTPUT:
+---
+fail_compilation/fail19941.d(44): Error: undefined identifier `dne`
+---
+*/
+immutable i = new Immutable;
+class Immutable { int field = &dne; }
+
+/*
+TEST_OUTPUT:
+---
+fail_compilation/fail19941.d(53): Error: undefined identifier `dne`
+---
+*/
+shared s = new Shared;
+class Shared { int field = &dne; }
+
+/*
+TEST_OUTPUT:
+---
+fail_compilation/fail19941.d(62): Error: undefined identifier `dne`
+---
+*/
+static t = new Static;
+class Static { int field = &dne; }
diff --git a/gcc/testsuite/gdc.test/fail_compilation/fail19955.d b/gcc/testsuite/gdc.test/fail_compilation/fail19955.d
new file mode 100644
index 0000000..7cdce2c
--- /dev/null
+++ b/gcc/testsuite/gdc.test/fail_compilation/fail19955.d
@@ -0,0 +1,8 @@
+// PERMUTE_ARGS:
+/*
+TEST_OUTPUT:
+---
+fail_compilation/fail19955.d(8): Error: `switch` statement without a `default`; use `final switch` or add `default: assert(0);` or add `default: break;`
+---
+*/
+void f() { switch(1) static assert(1); }
diff --git a/gcc/testsuite/gdc.test/fail_compilation/staticarrayoverflow.d b/gcc/testsuite/gdc.test/fail_compilation/staticarrayoverflow.d
index 8743bf1..f419869 100644
--- a/gcc/testsuite/gdc.test/fail_compilation/staticarrayoverflow.d
+++ b/gcc/testsuite/gdc.test/fail_compilation/staticarrayoverflow.d
@@ -2,11 +2,14 @@
REQUIRED_ARGS: -m64
PERMUTE_ARGS:
---
-fail_compilation/staticarrayoverflow.d(21): Error: static array S[1879048192] size overflowed to 7516192768000
-fail_compilation/staticarrayoverflow.d(21): Error: variable staticarrayoverflow.y size overflow
-fail_compilation/staticarrayoverflow.d(22): Error: variable staticarrayoverflow.z size of x1000ae0 exceeds max allowed size 0x100_0000
-fail_compilation/staticarrayoverflow.d(23): Error: static array S[8070450532247928832] size overflowed to 0
-fail_compilation/staticarrayoverflow.d(23): Error: variable staticarrayoverflow.a size overflow
+fail_compilation/staticarrayoverflow.d(24): Error: static array `S[1879048192]` size overflowed to 7516192768000
+fail_compilation/staticarrayoverflow.d(24): Error: variable `staticarrayoverflow.y` size overflow
+fail_compilation/staticarrayoverflow.d(26): Error: static array `S[8070450532247928832]` size overflowed to 8070450532247928832
+fail_compilation/staticarrayoverflow.d(26): Error: variable `staticarrayoverflow.a` size overflow
+fail_compilation/staticarrayoverflow.d(27): Error: static array `S[0][18446744073709551615LU]` size overflowed to 18446744073709551615
+fail_compilation/staticarrayoverflow.d(27): Error: variable `staticarrayoverflow.b` size overflow
+fail_compilation/staticarrayoverflow.d(28): Error: static array `S[0][4294967295]` size overflowed to 4294967295
+fail_compilation/staticarrayoverflow.d(28): Error: variable `staticarrayoverflow.c` size overflow
---
*/
@@ -20,4 +23,5 @@ struct S
S[0x7000_0000] y;
S[0x100_0000/(4*1000 - 1)] z;
S[0x7000_0000_0000_0000] a;
-
+S[0][-1] b;
+S[0][uint.max] c;
diff --git a/gcc/testsuite/gfortran.dg/ISO_Fortran_binding_12.c b/gcc/testsuite/gfortran.dg/ISO_Fortran_binding_12.c
new file mode 100644
index 0000000..279d9f6
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/ISO_Fortran_binding_12.c
@@ -0,0 +1,29 @@
+/* Test the fix for PR90093. */
+
+#include <stdio.h>
+#include <math.h>
+#include "../../../libgfortran/ISO_Fortran_binding.h"
+
+/* Contributed by Reinhold Bader <Bader@lrz.de> */
+
+void foo_opt(CFI_cdesc_t *, float *, int *, int);
+void write_res();
+
+float x[34];
+
+int main() {
+ CFI_CDESC_T(1) xd;
+ CFI_index_t ext[] = {34};
+ int sz;
+
+ CFI_establish((CFI_cdesc_t *) &xd, &x, CFI_attribute_other,
+ CFI_type_float, 0, 1, ext);
+
+ foo_opt((CFI_cdesc_t *) &xd, NULL, NULL, 0);
+ sz = 12;
+ foo_opt(NULL, &x[11], &sz, 1);
+
+ write_res();
+
+ return 0;
+}
diff --git a/gcc/testsuite/gfortran.dg/ISO_Fortran_binding_12.f90 b/gcc/testsuite/gfortran.dg/ISO_Fortran_binding_12.f90
new file mode 100644
index 0000000..d71c677
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/ISO_Fortran_binding_12.f90
@@ -0,0 +1,53 @@
+! { dg-do run { target c99_runtime } }
+! { dg-additional-sources ISO_Fortran_binding_12.c }
+!
+! Test the fix for PR90093. The additional source is the main program.
+!
+! Contributed by Reinhold Bader <Bader@lrz.de>
+!
+module mod_optional
+ use, intrinsic :: iso_c_binding
+ implicit none
+ integer :: status = 0
+
+contains
+
+ subroutine foo_opt(this, that, sz, flag) bind(c)
+ real(c_float), optional :: this(:)
+ real(c_float), optional :: that(*)
+ integer(c_int), optional :: sz
+ integer(c_int), value :: flag
+ if (flag == 0) then
+ if (.not. present(this) .or. present(that) .or. present(sz)) then
+ write(*,*) 'FAIL 1', present(this), present(that), present(sz)
+ status = status + 1
+ end if
+ else if (flag == 1) then
+ if (present(this) .or. .not. present(that) .or. .not. present(sz)) then
+ write(*,*) 'FAIL 2', present(this), present(that), present(sz)
+ status = status + 1
+ end if
+ if (sz /= 12) then
+ write(*,*) 'FAIL 3'
+ status = status + 1
+ end if
+ else if (flag == 2) then
+ if (present(this) .or. present(that) .or. present(sz)) then
+ write(*,*) 'FAIL 4', present(this), present(that), present(sz)
+ status = status + 1
+ end if
+ end if
+ end subroutine foo_opt
+
+ subroutine write_res() BIND(C)
+! Add a check that the fortran missing optional is accepted by the
+! bind(C) procedure.
+ call foo_opt (flag = 2)
+ if (status == 0) then
+ write(*,*) 'OK'
+ else
+ stop 1
+ end if
+ end subroutine
+
+end module mod_optional
diff --git a/gcc/testsuite/gfortran.dg/ISO_Fortran_binding_4.f90 b/gcc/testsuite/gfortran.dg/ISO_Fortran_binding_4.f90
index 09410b7..7731d1a 100644
--- a/gcc/testsuite/gfortran.dg/ISO_Fortran_binding_4.f90
+++ b/gcc/testsuite/gfortran.dg/ISO_Fortran_binding_4.f90
@@ -1,29 +1,41 @@
! { dg-do run }
! PR fortran/89384 - this used to give a wrong results
! with contiguous.
+! The subroutine substr is a test to check a problem found while
+! debugging PR90355.
+!
! Test case by Reinhold Bader.
+!
module mod_ctg
implicit none
+
contains
+
subroutine ctg(x) BIND(C)
real, contiguous :: x(:)
-
- if (any(abs(x - [2.,4.,6.]) > 1.e-6)) then
- write(*,*) 'FAIL'
- stop 1
- else
- write(*,*) 'OK'
- end if
+ if (any(abs(x - [2.,4.,6.]) > 1.e-6)) stop 1
x = [2.,4.,6.]*10.0
end subroutine
+
+ subroutine substr(str) BIND(C)
+ character(*) :: str(:)
+ if (str(2) .ne. "ghi") stop 2
+ str = ['uvw','xyz']
+ end subroutine
+
end module
+
program p
use mod_ctg
implicit none
real :: x(6)
+ character(5) :: str(2) = ['abcde','fghij']
integer :: i
x = [ (real(i), i=1, size(x)) ]
call ctg(x(2::2))
- if (any (abs (x - [1.,20.,3.,40.,5.,60.]) > 1.e-6)) stop 2
+ if (any (abs (x - [1.,20.,3.,40.,5.,60.]) > 1.e-6)) stop 3
+
+ call substr(str(:)(2:4))
+ if (any (str .ne. ['auvwe','fxyzj'])) stop 4
end program
diff --git a/gcc/testsuite/gfortran.dg/alloc_comp_auto_array_3.f90 b/gcc/testsuite/gfortran.dg/alloc_comp_auto_array_3.f90
index 15f9ecb..2af089e 100644
--- a/gcc/testsuite/gfortran.dg/alloc_comp_auto_array_3.f90
+++ b/gcc/testsuite/gfortran.dg/alloc_comp_auto_array_3.f90
@@ -1,5 +1,5 @@
! { dg-do compile }
-! { dg-options "-fdump-tree-original" }
+! { dg-options "-O0 -fdump-tree-original" }
!
! Test the fix for PR66082. The original problem was with the first
! call foo_1d.
diff --git a/gcc/testsuite/gfortran.dg/assign_10.f90 b/gcc/testsuite/gfortran.dg/assign_10.f90
index 6e57bef..c207f9e 100644
--- a/gcc/testsuite/gfortran.dg/assign_10.f90
+++ b/gcc/testsuite/gfortran.dg/assign_10.f90
@@ -24,4 +24,4 @@ end
! Note that it is the kind conversion that generates the temp.
!
! { dg-final { scan-tree-dump-times "parm" 20 "original" } }
-! { dg-final { scan-tree-dump-times "atmp" 18 "original" } }
+! { dg-final { scan-tree-dump-times "atmp" 20 "original" } }
diff --git a/gcc/testsuite/gfortran.dg/associate_48.f90 b/gcc/testsuite/gfortran.dg/associate_48.f90
new file mode 100644
index 0000000..5ce3a49
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/associate_48.f90
@@ -0,0 +1,41 @@
+! { dg=do run }
+!
+! Test the fix for PR90498.
+!
+! Contributed by Vladimir Fuka <vladimir.fuka@gmail.com>
+!
+ type field_names_a
+ class(*), pointer :: var(:) =>null()
+ end type
+
+ type(field_names_a),pointer :: a(:)
+ allocate (a(2))
+
+ allocate (a(1)%var(2), source = ["hello"," vlad"])
+ allocate (a(2)%var(2), source = ["HELLO"," VLAD"])
+ call s(a)
+ deallocate (a(1)%var)
+ deallocate (a(2)%var)
+ deallocate (a)
+contains
+ subroutine s(a)
+
+ type(field_names_a) :: a(:)
+
+ select type (var => a(1)%var)
+ type is (character(*))
+ if (any (var .ne. ["hello"," vlad"])) stop 1
+ class default
+ stop
+ end select
+
+ associate (var => a(2)%var)
+ select type (var)
+ type is (character(*))
+ if (any (var .ne. ["HELLO"," VLAD"])) stop 2
+ class default
+ stop
+ end select
+ end associate
+ end
+end
diff --git a/gcc/testsuite/gfortran.dg/assumed_rank_bounds_3.f90 b/gcc/testsuite/gfortran.dg/assumed_rank_bounds_3.f90
new file mode 100644
index 0000000..0a428f2
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/assumed_rank_bounds_3.f90
@@ -0,0 +1,219 @@
+! { dg-do run }
+!
+! This test case is inserted as a check. PR89365 inially asserted that
+! gfortran was getting the bounds wrong for allocatable and pointer
+! actual arguments. However, the reporter accepted that it is OK and
+! this is the corrected version of his testcase, which fills a gap in
+! the testsuite.
+!
+! Contributed by Reinhold Bader <Bader@lrz.de>
+!
+module mod_ass_rank_inquiry
+ use, intrinsic :: iso_c_binding
+ implicit none
+ logical, parameter :: debug = .true.
+ integer :: error_count = 0
+!
+! using inquiry functions for assumed rank objects
+!
+ contains
+ subroutine foo_1(this)
+ real(c_float) :: this(..)
+ select case(rank(this))
+ case(0)
+ if (size(shape(this)) > 0 .or. size(lbound(this)) > 0 .or. &
+ size(ubound(this)) > 0) then
+ error_count = error_count + 1
+ if (debug) write(*,*) 'FAIL shape / lbound / ubound'
+ end if
+ if (size(this) /= 1) then
+ error_count = error_count + 1
+ if (debug) write(*,*) 'FAIL size'
+ end if
+ case(1)
+ if (sum(abs(shape(this) - [4])) > 0) then
+ error_count = error_count + 1
+ if (debug) write(*,*) 'FAIL shape'
+ end if
+ if (size(this) /= 4) then
+ error_count = error_count + 1
+ if (debug) write(*,*) 'FAIL size', size(this)
+ end if
+ if (lbound(this,1) /= 1) then
+ error_count = error_count + 1
+ if (debug) write(*,*) 'FAIL lbound',lbound(this,1)
+ end if
+ if (ubound(this,1) /= 4) then
+ error_count = error_count + 1
+ if (debug) write(*,*) 'FAIL ubound',ubound(this,1)
+ end if
+ case(3)
+ if (sum(abs(shape(this) - [ 2, 3, 4 ])) > 0) then
+ error_count = error_count + 1
+ if (debug) write(*,*) 'FAIL shape'
+ end if
+ if (size(this) /= 2*3*4) then
+ error_count = error_count + 1
+ if (debug) write(*,*) 'FAIL size'
+ end if
+ if (sum(abs(lbound(this) - [ 1, 1, 1 ])) > 0) then
+ error_count = error_count + 1
+ if (debug) write(*,*) 'FAIL lbound'
+ end if
+ if (sum(abs(ubound(this)) - [ 2, 3, 4]) > 0) then
+ error_count = error_count + 1
+ if (debug) write(*,*) 'FAIL ubound'
+ end if
+ case default
+ error_count = error_count + 1
+ end select
+ end subroutine foo_1
+ subroutine foo_2(this)
+ real(c_float), allocatable :: this(..)
+ if (.not. allocated(this)) then
+ error_count = error_count + 1
+ if (debug) write(*,*) 'FAIL allocated'
+ end if
+ select case(rank(this))
+ case(0)
+ if (size(shape(this)) > 0 .or. size(lbound(this)) > 0 .or. &
+ size(ubound(this)) > 0) then
+ error_count = error_count + 1
+ if (debug) write(*,*) 'FAIL shape / lbound / ubound'
+ end if
+ if (size(this) /= 1) then
+ error_count = error_count + 1
+ if (debug) write(*,*) 'FAIL size'
+ end if
+ case(1)
+ if (sum(abs(shape(this) - [4])) > 0) then
+ error_count = error_count + 1
+ if (debug) write(*,*) 'FAIL shape'
+ end if
+ if (size(this) /= 4) then
+ error_count = error_count + 1
+ if (debug) write(*,*) 'FAIL size', size(this)
+ end if
+ if (lbound(this,1) /= 2) then
+ error_count = error_count + 1
+ if (debug) write(*,*) 'FAIL lbound',lbound(this,1)
+ end if
+ if (ubound(this,1) /= 5) then
+ error_count = error_count + 1
+ if (debug) write(*,*) 'FAIL ubound',ubound(this,1)
+ end if
+ case(3)
+ if (sum(abs(shape(this) - [ 2, 3, 4 ])) > 0) then
+ error_count = error_count + 1
+ if (debug) write(*,*) 'FAIL shape'
+ end if
+ if (size(this) /= 2*3*4) then
+ error_count = error_count + 1
+ if (debug) write(*,*) 'FAIL size'
+ end if
+ if (sum(abs(lbound(this) - [ 0, -1, 1 ])) > 0) then
+ error_count = error_count + 1
+ if (debug) write(*,*) 'FAIL lbound', lbound(this)
+ end if
+ if (sum(abs(ubound(this)) - [ 2, 3, 4]) > 0) then
+ error_count = error_count + 1
+ if (debug) write(*,*) 'FAIL ubound', ubound(this)
+ end if
+ case default
+ error_count = error_count + 1
+ end select
+ end subroutine foo_2
+ subroutine foo_3(this)
+ real(c_float), pointer :: this(..)
+ if (.not. associated(this)) then
+ error_count = error_count + 1
+ if (debug) write(*,*) 'FAIL associated'
+ end if
+ select case(rank(this))
+ case(0)
+ if (size(shape(this)) > 0 .or. size(lbound(this)) > 0 .or. &
+ size(ubound(this)) > 0) then
+ error_count = error_count + 1
+ if (debug) write(*,*) 'FAIL shape / lbound / ubound'
+ end if
+ if (size(this) /= 1) then
+ error_count = error_count + 1
+ if (debug) write(*,*) 'FAIL size'
+ end if
+ case(1)
+ if (sum(abs(shape(this) - [4])) > 0) then
+ error_count = error_count + 1
+ if (debug) write(*,*) 'FAIL shape'
+ end if
+ if (size(this) /= 4) then
+ error_count = error_count + 1
+ if (debug) write(*,*) 'FAIL size', size(this)
+ end if
+ if (lbound(this,1) /= 2) then
+ error_count = error_count + 1
+ if (debug) write(*,*) 'FAIL lbound',lbound(this,1)
+ end if
+ if (ubound(this,1) /= 5) then
+ error_count = error_count + 1
+ if (debug) write(*,*) 'FAIL ubound',ubound(this,1)
+ end if
+ case(3)
+ if (sum(abs(shape(this) - [ 2, 3, 4 ])) > 0) then
+ error_count = error_count + 1
+ if (debug) write(*,*) 'FAIL shape'
+ end if
+ if (size(this) /= 2*3*4) then
+ error_count = error_count + 1
+ if (debug) write(*,*) 'FAIL size'
+ end if
+ if (sum(abs(lbound(this) - [ 0, -1, 1 ])) > 0) then
+ error_count = error_count + 1
+ if (debug) write(*,*) 'FAIL lbound', lbound(this)
+ end if
+ if (sum(abs(ubound(this)) - [ 2, 3, 4]) > 0) then
+ error_count = error_count + 1
+ if (debug) write(*,*) 'FAIL ubound', ubound(this)
+ end if
+ case default
+ error_count = error_count + 1
+ end select
+ end subroutine foo_3
+end module mod_ass_rank_inquiry
+program ass_rank_inquiry
+ use mod_ass_rank_inquiry
+ implicit none
+ real, allocatable :: x, y(:), z(:,:,:)
+ real, pointer :: xp, yp(:), zp(:,:,:)
+
+ allocate(x, y(2:5), z(0:1,-1:1,1:4))
+ allocate(xp, yp(2:5), zp(0:1,-1:1,1:4))
+
+
+ call foo_1(x)
+ if (error_count > 0) write(*,*) 'FAIL: after scalar ',error_count
+ call foo_1(y)
+ if (error_count > 0) write(*,*) 'FAIL: after rank-1 ',error_count
+ call foo_1(z)
+ if (error_count > 0) write(*,*) 'FAIL: after rank-3 ',error_count
+ call foo_2(x)
+ if (error_count > 0) write(*,*) 'FAIL: after allocscalar ',error_count
+ call foo_2(y)
+ if (error_count > 0) write(*,*) 'FAIL: after allocrank-1 ',error_count
+ call foo_2(z)
+ if (error_count > 0) write(*,*) 'FAIL: after allocrank-3 ',error_count
+ call foo_3(xp)
+ if (error_count > 0) write(*,*) 'FAIL: after ptrscalar ',error_count
+ call foo_3(yp)
+ if (error_count > 0) write(*,*) 'FAIL: after ptrrank-1 ',error_count
+ call foo_3(zp)
+ if (error_count > 0) write(*,*) 'FAIL: after ptrrank-3 ',error_count
+
+ if (error_count == 0) then
+ write(*,*) 'OK'
+ else
+ stop 1
+ end if
+
+ deallocate(x, y, z)
+ deallocate(xp, yp, zp)
+end program ass_rank_inquiry
diff --git a/gcc/testsuite/gfortran.dg/assumed_type_10.f90 b/gcc/testsuite/gfortran.dg/assumed_type_10.f90
new file mode 100644
index 0000000..bf0c873
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/assumed_type_10.f90
@@ -0,0 +1,46 @@
+! { dg-do compile }
+! { dg-options "-O0 -fdump-tree-original" }
+! PR 61968 - this used to generate invalid assembler containing
+! TYPE(*).
+
+module testmod
+ use iso_c_binding, only: c_size_t, c_int32_t, c_int64_t
+ implicit none
+
+ interface test
+ procedure :: test_32
+ procedure :: test_array
+ end interface test
+
+ interface
+ subroutine test_lib (a, len) bind(C, name="xxx")
+ use iso_c_binding, only: c_size_t
+ type(*), dimension(*) :: a
+ integer(c_size_t), value :: len
+ end subroutine
+ end interface
+
+contains
+
+ subroutine test_32 (a, len)
+ type(*), dimension(*) :: a
+ integer(c_int32_t), value :: len
+ call test_lib (a, int (len, kind=c_size_t))
+ end subroutine
+
+ subroutine test_array (a)
+ use iso_c_binding, only: c_size_t
+ class(*), dimension(..), target :: a
+ call test_lib (a, int (sizeof (a), kind=c_size_t))
+ end subroutine
+
+end module
+
+ subroutine test_32_ (a, len)
+ use iso_c_binding, only: c_int32_t
+ use testmod
+ type(*), dimension(*) :: a
+ integer(c_int32_t), value :: len
+ call test (a, len)
+ end subroutine
+! { dg-final { scan-tree-dump-not "! __vtype_TYPE\\(*\\)" "original" } }
diff --git a/gcc/testsuite/gfortran.dg/assumed_type_11.f90 b/gcc/testsuite/gfortran.dg/assumed_type_11.f90
new file mode 100644
index 0000000..df6572d
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/assumed_type_11.f90
@@ -0,0 +1,46 @@
+! { dg-do compile }
+! { dg-options "-O3 -fdump-tree-original" }
+! PR 61968 - this used to generate invalid assembler containing
+! TYPE(*).
+
+module testmod
+ use iso_c_binding, only: c_size_t, c_int32_t, c_int64_t
+ implicit none
+
+ interface test
+ procedure :: test_32
+ procedure :: test_array
+ end interface test
+
+ interface
+ subroutine test_lib (a, len) bind(C, name="xxx")
+ use iso_c_binding, only: c_size_t
+ type(*), dimension(*) :: a
+ integer(c_size_t), value :: len
+ end subroutine
+ end interface
+
+contains
+
+ subroutine test_32 (a, len)
+ type(*), dimension(*) :: a
+ integer(c_int32_t), value :: len
+ call test_lib (a, int (len, kind=c_size_t))
+ end subroutine
+
+ subroutine test_array (a)
+ use iso_c_binding, only: c_size_t
+ class(*), dimension(..), target :: a
+ call test_lib (a, int (sizeof (a), kind=c_size_t))
+ end subroutine
+
+end module
+
+ subroutine test_32_ (a, len)
+ use iso_c_binding, only: c_int32_t
+ use testmod
+ type(*), dimension(*) :: a
+ integer(c_int32_t), value :: len
+ call test (a, len)
+ end subroutine
+! { dg-final { scan-tree-dump-not "! __vtype_TYPE\\(*\\)" "original" } }
diff --git a/gcc/testsuite/gfortran.dg/assumed_type_2.f90 b/gcc/testsuite/gfortran.dg/assumed_type_2.f90
index dce5ac6..5d3cd7e 100644
--- a/gcc/testsuite/gfortran.dg/assumed_type_2.f90
+++ b/gcc/testsuite/gfortran.dg/assumed_type_2.f90
@@ -1,5 +1,5 @@
-! { dg-do run }
-! { dg-options "-fdump-tree-original" }
+! { dg-do compile }
+! { dg-options "-O0 -fdump-tree-original" }
!
! PR fortran/48820
!
diff --git a/gcc/testsuite/gfortran.dg/assumed_type_2a.f90 b/gcc/testsuite/gfortran.dg/assumed_type_2a.f90
new file mode 100644
index 0000000..125bfcb
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/assumed_type_2a.f90
@@ -0,0 +1,139 @@
+! { dg-do run }
+!
+! PR fortran/48820
+!
+! Test TYPE(*)
+!
+
+module mod
+ use iso_c_binding, only: c_loc, c_ptr, c_bool
+ implicit none
+ interface my_c_loc
+ function my_c_loc1(x) bind(C)
+ import c_ptr
+ type(*) :: x
+ type(c_ptr) :: my_c_loc1
+ end function
+ function my_c_loc2(x) bind(C)
+ import c_ptr
+ type(*) :: x(*)
+ type(c_ptr) :: my_c_loc2
+ end function
+ end interface my_c_loc
+contains
+ subroutine sub_scalar (arg1, presnt)
+ type(*), target, optional :: arg1
+ logical :: presnt
+ type(c_ptr) :: cpt
+ if (presnt .neqv. present (arg1)) STOP 1
+ cpt = c_loc (arg1)
+ end subroutine sub_scalar
+
+ subroutine sub_array_shape (arg2, lbounds, ubounds)
+ type(*), target :: arg2(:,:)
+ type(c_ptr) :: cpt
+ integer :: lbounds(2), ubounds(2)
+ if (any (lbound(arg2) /= lbounds)) STOP 2
+ if (any (ubound(arg2) /= ubounds)) STOP 3
+ if (any (shape(arg2) /= ubounds-lbounds+1)) STOP 4
+ if (size(arg2) /= product (ubounds-lbounds+1)) STOP 5
+ if (rank (arg2) /= 2) STOP 6
+! if (.not. is_continuous (arg2)) STOP 7 !<< Not yet implemented
+! cpt = c_loc (arg2) ! << FIXME: Valid since TS29113
+ call sub_array_assumed (arg2)
+ end subroutine sub_array_shape
+
+ subroutine sub_array_assumed (arg3)
+ type(*), target :: arg3(*)
+ type(c_ptr) :: cpt
+ cpt = c_loc (arg3)
+ end subroutine sub_array_assumed
+end module
+
+use mod
+use iso_c_binding, only: c_int, c_null_ptr
+implicit none
+type t1
+ integer :: a
+end type t1
+type :: t2
+ sequence
+ integer :: b
+end type t2
+type, bind(C) :: t3
+ integer(c_int) :: c
+end type t3
+
+integer :: scalar_int
+real, allocatable :: scalar_real_alloc
+character, pointer :: scalar_char_ptr
+
+integer :: array_int(3)
+real, allocatable :: array_real_alloc(:,:)
+character, pointer :: array_char_ptr(:,:)
+
+type(t1) :: scalar_t1
+type(t2), allocatable :: scalar_t2_alloc
+type(t3), pointer :: scalar_t3_ptr
+
+type(t1) :: array_t1(4)
+type(t2), allocatable :: array_t2_alloc(:,:)
+type(t3), pointer :: array_t3_ptr(:,:)
+
+class(t1), allocatable :: scalar_class_t1_alloc
+class(t1), pointer :: scalar_class_t1_ptr
+
+class(t1), allocatable :: array_class_t1_alloc(:,:)
+class(t1), pointer :: array_class_t1_ptr(:,:)
+
+scalar_char_ptr => null()
+scalar_t3_ptr => null()
+
+call sub_scalar (presnt=.false.)
+call sub_scalar (scalar_real_alloc, .false.)
+call sub_scalar (scalar_char_ptr, .false.)
+call sub_scalar (null (), .false.)
+call sub_scalar (scalar_t2_alloc, .false.)
+call sub_scalar (scalar_t3_ptr, .false.)
+
+allocate (scalar_real_alloc, scalar_char_ptr, scalar_t3_ptr)
+allocate (scalar_class_t1_alloc, scalar_class_t1_ptr, scalar_t2_alloc)
+allocate (array_real_alloc(3:5,2:4), array_char_ptr(-2:2,2))
+allocate (array_t2_alloc(3:5,2:4), array_t3_ptr(-2:2,2))
+allocate (array_class_t1_alloc(3,3), array_class_t1_ptr(4,4))
+
+call sub_scalar (scalar_int, .true.)
+call sub_scalar (scalar_real_alloc, .true.)
+call sub_scalar (scalar_char_ptr, .true.)
+call sub_scalar (array_int(2), .true.)
+call sub_scalar (array_real_alloc(3,2), .true.)
+call sub_scalar (array_char_ptr(0,1), .true.)
+call sub_scalar (scalar_t1, .true.)
+call sub_scalar (scalar_t2_alloc, .true.)
+call sub_scalar (scalar_t3_ptr, .true.)
+call sub_scalar (array_t1(2), .true.)
+call sub_scalar (array_t2_alloc(3,2), .true.)
+call sub_scalar (array_t3_ptr(0,1), .true.)
+call sub_scalar (array_class_t1_alloc(2,1), .true.)
+call sub_scalar (array_class_t1_ptr(3,3), .true.)
+
+call sub_array_assumed (array_int)
+call sub_array_assumed (array_real_alloc)
+call sub_array_assumed (array_char_ptr)
+call sub_array_assumed (array_t1)
+call sub_array_assumed (array_t2_alloc)
+call sub_array_assumed (array_t3_ptr)
+call sub_array_assumed (array_class_t1_alloc)
+call sub_array_assumed (array_class_t1_ptr)
+
+call sub_array_shape (array_real_alloc, [1,1], shape(array_real_alloc))
+call sub_array_shape (array_char_ptr, [1,1], shape(array_char_ptr))
+call sub_array_shape (array_t2_alloc, [1,1], shape(array_t2_alloc))
+call sub_array_shape (array_t3_ptr, [1,1], shape(array_t3_ptr))
+call sub_array_shape (array_class_t1_alloc, [1,1], shape(array_class_t1_alloc))
+call sub_array_shape (array_class_t1_ptr, [1,1], shape(array_class_t1_ptr))
+
+deallocate (scalar_char_ptr, scalar_class_t1_ptr, array_char_ptr)
+deallocate (array_class_t1_ptr, array_t3_ptr)
+
+end
diff --git a/gcc/testsuite/gfortran.dg/c_loc_test_22.f90 b/gcc/testsuite/gfortran.dg/c_loc_test_22.f90
index 5f4f977..9c40b26 100644
--- a/gcc/testsuite/gfortran.dg/c_loc_test_22.f90
+++ b/gcc/testsuite/gfortran.dg/c_loc_test_22.f90
@@ -1,5 +1,5 @@
! { dg-do compile }
-! { dg-options "-fdump-tree-original" }
+! { dg-options "-O0 -fdump-tree-original" }
!
! PR fortran/56907
!
diff --git a/gcc/testsuite/gfortran.dg/coarray_lock_7.f90 b/gcc/testsuite/gfortran.dg/coarray_lock_7.f90
index aedb226..4f4bdde 100644
--- a/gcc/testsuite/gfortran.dg/coarray_lock_7.f90
+++ b/gcc/testsuite/gfortran.dg/coarray_lock_7.f90
@@ -35,8 +35,8 @@ end
! { dg-final { scan-tree-dump-times "_gfortran_caf_lock \\(caf_token.., 0, 0, 0B, 0B, 0B, 0\\);" 1 "original" } }
! { dg-final { scan-tree-dump-times "_gfortran_caf_unlock \\(caf_token.., 0, 0, 0B, 0B, 0\\);" 1 "original" } }
-! { dg-final { scan-tree-dump-times "_gfortran_caf_lock \\(caf_token.., .*\\(\\(3 - parm....dim\\\[0\\\].lbound\\) \\+ \\(MAX_EXPR <parm....dim\\\[0\\\].ubound - parm....dim\\\[0\\\].lbound, -1> \\+ 1\\) \\* \\(3 - parm....dim\\\[1\\\].lbound\\)\\), 0, 0B, &ii, 0B, 0\\);|_gfortran_caf_lock \\(caf_token.1, \\(3 - parm....dim\\\[0\\\].lbound\\) \\+ \\(MAX_EXPR <parm....dim\\\[0\\\].ubound - parm....dim\\\[0\\\].lbound, -1> \\+ 1\\) \\* \\(3 - parm....dim\\\[1\\\].lbound\\), 0, 0B, &ii, 0B, 0\\);" 1 "original" } }
-! { dg-final { scan-tree-dump-times "_gfortran_caf_unlock \\(caf_token.., .*\\(\\(2 - parm....dim\\\[0\\\].lbound\\) \\+ \\(MAX_EXPR <parm....dim\\\[0\\\].ubound - parm....dim\\\[0\\\].lbound, -1> \\+ 1\\) \\* \\(3 - parm....dim\\\[1\\\].lbound\\)\\), 0, &ii, 0B, 0\\);|_gfortran_caf_unlock \\(caf_token.., \\(2 - parm....dim\\\[0\\\].lbound\\) \\+ \\(MAX_EXPR <parm....dim\\\[0\\\].ubound - parm....dim\\\[0\\\].lbound, -1> \\+ 1\\) \\* \\(3 - parm....dim\\\[1\\\].lbound\\), 0, &ii, 0B, 0\\);" 1 "original" } }
+! { dg-final { scan-tree-dump-times "_gfortran_caf_lock \\(caf_token.., .*\\(\\(3 - parm.\\d+.dim\\\[0\\\].lbound\\) \\+ \\(MAX_EXPR <parm.\\d+.dim\\\[0\\\].ubound - parm.\\d+.dim\\\[0\\\].lbound, -1> \\+ 1\\) \\* \\(3 - parm.\\d+.dim\\\[1\\\].lbound\\)\\), 0, 0B, &ii, 0B, 0\\);|_gfortran_caf_lock \\(caf_token.1, \\(3 - parm.\\d+.dim\\\[0\\\].lbound\\) \\+ \\(MAX_EXPR <parm.\\d+.dim\\\[0\\\].ubound - parm.\\d+.dim\\\[0\\\].lbound, -1> \\+ 1\\) \\* \\(3 - parm.\\d+.dim\\\[1\\\].lbound\\), 0, 0B, &ii, 0B, 0\\);" 1 "original" } }
+! { dg-final { scan-tree-dump-times "_gfortran_caf_unlock \\(caf_token.., .*\\(\\(2 - parm.\\d+.dim\\\[0\\\].lbound\\) \\+ \\(MAX_EXPR <parm.\\d+.dim\\\[0\\\].ubound - parm.\\d+.dim\\\[0\\\].lbound, -1> \\+ 1\\) \\* \\(3 - parm.\\d+.dim\\\[1\\\].lbound\\)\\), 0, &ii, 0B, 0\\);|_gfortran_caf_unlock \\(caf_token.., \\(2 - parm.\\d+.dim\\\[0\\\].lbound\\) \\+ \\(MAX_EXPR <parm.\\d+.dim\\\[0\\\].ubound - parm.\\d+.dim\\\[0\\\].lbound, -1> \\+ 1\\) \\* \\(3 - parm.\\d+.dim\\\[1\\\].lbound\\), 0, &ii, 0B, 0\\);" 1 "original" } }
! { dg-final { scan-tree-dump-times "_gfortran_caf_lock \\(three.token, 0, \\(integer\\(kind=4\\)\\) \\(5 - three.dim\\\[0\\\].lbound\\), &acquired.\[0-9\]+, 0B, 0B, 0\\);|_gfortran_caf_lock \\(three.token, 0, 5 - three.dim\\\[0\\\].lbound, &acquired.\[0-9\]+, 0B, 0B, 0\\);" 1 "original" } }
! { dg-final { scan-tree-dump-times "_gfortran_caf_unlock \\(three.token, 0, \\(integer\\(kind=4\\)\\) \\(8 - three.dim\\\[0\\\].lbound\\), &ii, 0B, 0\\);|_gfortran_caf_unlock \\(three.token, 0, 8 - three.dim\\\[0\\\].lbound, &ii, 0B, 0\\);" 1 "original" } }
diff --git a/gcc/testsuite/gfortran.dg/common_1.f b/gcc/testsuite/gfortran.dg/common_1.f
new file mode 100644
index 0000000..2c5e96a
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/common_1.f
@@ -0,0 +1,14 @@
+! { dg-do compile }
+ module mymod
+ type :: mytyp
+ integer :: i
+ end type mytyp
+ contains
+ subroutine mysub
+ implicit none
+ type(mytyp) :: a
+ integer :: commoni,commonj
+ commoni = a%i
+ commonj = a%j ! { dg-error "is not a member of" }
+ end subroutine mysub
+ end module mymod
diff --git a/gcc/testsuite/gfortran.dg/common_26.f90 b/gcc/testsuite/gfortran.dg/common_26.f90
new file mode 100644
index 0000000..5834d7c5
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/common_26.f90
@@ -0,0 +1,14 @@
+! { dg-do compile }
+module mymod
+ type :: mytyp
+ integer :: i
+ end type mytyp
+contains
+ subroutine mysub
+ implicit none
+ type(mytyp) :: a
+ integer :: commoni,commonj
+ commoni = a%i
+ commonj = a%j ! { dg-error "is not a member of" }
+ end subroutine mysub
+end module mymod
diff --git a/gcc/testsuite/gfortran.dg/contiguous_3.f90 b/gcc/testsuite/gfortran.dg/contiguous_3.f90
index 724ec83..ba0ccce 100644
--- a/gcc/testsuite/gfortran.dg/contiguous_3.f90
+++ b/gcc/testsuite/gfortran.dg/contiguous_3.f90
@@ -1,5 +1,5 @@
! { dg-do compile }
-! { dg-options "-fdump-tree-original" }
+! { dg-options "-O0 -fdump-tree-original" }
!
! PR fortran/40632
!
diff --git a/gcc/testsuite/gfortran.dg/dec_format_empty_item_1.f b/gcc/testsuite/gfortran.dg/dec_format_empty_item_1.f
new file mode 100644
index 0000000..ed27c18
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/dec_format_empty_item_1.f
@@ -0,0 +1,19 @@
+! { dg-do run }
+! { dg-options "-fdec" }
+!
+! Test blank/empty format items in format string
+!
+! Test case contributed by Jim MacArthur <jim.macarthur@codethink.co.uk>
+! Modified by Mark Eggleston <mark.eggleston@codethink.com>
+!
+ PROGRAM blank_format_items
+ INTEGER A/0/
+
+ OPEN(1, status="scratch")
+ WRITE(1, 10) 100
+ REWIND(1)
+ READ(1, 10) A
+ IF (a.NE.100) STOP 1
+ PRINT 10, A
+10 FORMAT( I5,)
+ END
diff --git a/gcc/testsuite/gfortran.dg/dec_format_empty_item_2.f b/gcc/testsuite/gfortran.dg/dec_format_empty_item_2.f
new file mode 100644
index 0000000..2793cb1
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/dec_format_empty_item_2.f
@@ -0,0 +1,19 @@
+! { dg-do run }
+! { dg-options "-fdec-blank-format-item" }
+!
+! Test blank/empty format items in format string
+!
+! Test case contributed by Jim MacArthur <jim.macarthur@codethink.co.uk>
+! Modified by Mark Eggleston <mark.eggleston@codethink.com>
+!
+ PROGRAM blank_format_items
+ INTEGER A/0/
+
+ OPEN(1, status="scratch")
+ WRITE(1, 10) 100
+ REWIND(1)
+ READ(1, 10) A
+ IF (a.NE.100) STOP 1
+ PRINT 10, A
+10 FORMAT( I5,)
+ END
diff --git a/gcc/testsuite/gfortran.dg/dec_format_empty_item_3.f b/gcc/testsuite/gfortran.dg/dec_format_empty_item_3.f
new file mode 100644
index 0000000..dbccd67
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/dec_format_empty_item_3.f
@@ -0,0 +1,19 @@
+! { dg-do compile }
+! { dg-options "-fdec -fno-dec-blank-format-item" }
+!
+! Test blank/empty format items in format string
+!
+! Test case contributed by Jim MacArthur <jim.macarthur@codethink.co.uk>
+! Modified by Mark Eggleston <mark.eggleston@codethink.com>
+!
+ PROGRAM blank_format_items
+ INTEGER A/0/
+
+ OPEN(1, status="scratch")
+ WRITE(1, 10) 100 ! { dg-error "FORMAT label 10 at" }
+ REWIND(1)
+ READ(1, 10) A ! { dg-error "FORMAT label 10 at" }
+ IF (a.NE.100) STOP 1
+ PRINT 10, A ! { dg-error "FORMAT label 10 at" }
+ 10 FORMAT( I5,) ! { dg-error "Missing item" }
+ END
diff --git a/gcc/testsuite/gfortran.dg/dec_io_1.f90 b/gcc/testsuite/gfortran.dg/dec_io_1.f90
index 2edc427..58daf30 100644
--- a/gcc/testsuite/gfortran.dg/dec_io_1.f90
+++ b/gcc/testsuite/gfortran.dg/dec_io_1.f90
@@ -1,4 +1,4 @@
-! { dg-do run }
+! { dg-do run { target fd_truncate } }
! { dg-options "-fdec" }
!
! Run-time tests for values of DEC I/O parameters (doesn't test functionality).
diff --git a/gcc/testsuite/gfortran.dg/deferred_character_33.f90 b/gcc/testsuite/gfortran.dg/deferred_character_33.f90
new file mode 100644
index 0000000..ec864d8
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/deferred_character_33.f90
@@ -0,0 +1,35 @@
+! { dg-do run }
+! { dg-additional-sources deferred_character_33a.f90 }
+! PR fortran/90744 - this used to pass a wrong length
+! to an external function without a prototype.
+! Original test case by Tomáš Trnka.
+module StringModule
+ implicit none
+
+contains
+ function getstr()
+ character(:), allocatable :: getstr
+
+ getstr = 'OK'
+ end function
+end module
+module TestModule
+ use StringModule
+ implicit none
+
+contains
+ subroutine DoTest()
+ if (.false.) then
+ call convrs('A',getstr())
+ else
+ call convrs('B',getstr())
+ end if
+ end subroutine
+end module
+program external_char_length
+ use TestModule
+
+ implicit none
+
+ call DoTest()
+end program
diff --git a/gcc/testsuite/gfortran.dg/deferred_character_33a.f90 b/gcc/testsuite/gfortran.dg/deferred_character_33a.f90
new file mode 100644
index 0000000..db117cc
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/deferred_character_33a.f90
@@ -0,0 +1,9 @@
+! { dg-do compile }
+subroutine convrs(quanty,fromto)
+ implicit none
+
+ character(*), intent(in) :: quanty,fromto
+
+ if (len(fromto) /= 2) stop 1
+ if (fromto /= 'OK') stop 2
+end subroutine
diff --git a/gcc/testsuite/gfortran.dg/dtio_1.f90 b/gcc/testsuite/gfortran.dg/dtio_1.f90
index c6f17d9..b168d30 100644
--- a/gcc/testsuite/gfortran.dg/dtio_1.f90
+++ b/gcc/testsuite/gfortran.dg/dtio_1.f90
@@ -1,4 +1,4 @@
-! { dg-do run }
+! { dg-do run { target fd_truncate } }
!
! Functional test of User Defined Derived Type IO, Formatted WRITE/READ
!
diff --git a/gcc/testsuite/gfortran.dg/dtio_12.f90 b/gcc/testsuite/gfortran.dg/dtio_12.f90
index 54b10cb..ac6d9e7 100644
--- a/gcc/testsuite/gfortran.dg/dtio_12.f90
+++ b/gcc/testsuite/gfortran.dg/dtio_12.f90
@@ -1,4 +1,4 @@
-! { dg-do run }
+! { dg-do run { target fd_truncate } }
!
! Test the fix for PR77657 in which the DTIO subroutine was not found,
! which led to an error in attempting to link to the abstract interface.
diff --git a/gcc/testsuite/gfortran.dg/dummy_derived_typed.f90 b/gcc/testsuite/gfortran.dg/dummy_derived_typed.f90
new file mode 100644
index 0000000..5c9b3ca
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/dummy_derived_typed.f90
@@ -0,0 +1,5 @@
+! { dg-do compile }
+subroutine s(t) ! { dg-error "Dummy argument" }
+ type t ! { dg-error "cannot be a derived" }
+ end type ! { dg-error "Expecting END SUBROUTINE" }
+end
diff --git a/gcc/testsuite/gfortran.dg/dummy_procedure_8.f90 b/gcc/testsuite/gfortran.dg/dummy_procedure_8.f90
index 7b8a264..603692c 100644
--- a/gcc/testsuite/gfortran.dg/dummy_procedure_8.f90
+++ b/gcc/testsuite/gfortran.dg/dummy_procedure_8.f90
@@ -7,7 +7,6 @@
implicit none
call call_a(a1) ! { dg-error "Character length mismatch in function result" }
-call call_a(a2) ! { dg-error "Character length mismatch in function result" }
call call_b(b1) ! { dg-error "Shape mismatch" }
call call_c(c1) ! { dg-error "POINTER attribute mismatch in function result" }
call call_d(c1) ! { dg-error "ALLOCATABLE attribute mismatch in function result" }
@@ -19,9 +18,6 @@ contains
character(1) function a1()
end function
- character(:) function a2()
- end function
-
subroutine call_a(a3)
interface
character(2) function a3()
diff --git a/gcc/testsuite/gfortran.dg/external_procedure_4.f90 b/gcc/testsuite/gfortran.dg/external_procedure_4.f90
new file mode 100644
index 0000000..403f173
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/external_procedure_4.f90
@@ -0,0 +1,19 @@
+! { dg-do compile }
+! PR fortran/90937 - this used to cause an ICE.
+! Original test case by Toon Moene.
+subroutine lfidiff
+
+ implicit none
+
+ contains
+
+ subroutine grlfi(cdnom)
+
+ character(len=*) cdnom(:)
+ character(len=len(cdnom)) clnoma
+
+ call lficas(clnoma)
+
+ end subroutine grlfi
+
+end subroutine lfidiff
diff --git a/gcc/testsuite/gfortran.dg/fmt_en.f90 b/gcc/testsuite/gfortran.dg/fmt_en.f90
index b3597e4..89011b3 100644
--- a/gcc/testsuite/gfortran.dg/fmt_en.f90
+++ b/gcc/testsuite/gfortran.dg/fmt_en.f90
@@ -1,4 +1,4 @@
-! { dg-do run }
+! { dg-do run { target fd_truncate } }
! PR60128 Invalid outputs with EN descriptors
! Test case provided by Walt Brainerd.
program pr60128
diff --git a/gcc/testsuite/gfortran.dg/fmt_f_default_field_width_1.f90 b/gcc/testsuite/gfortran.dg/fmt_f_default_field_width_1.f90
new file mode 100644
index 0000000..a2b14b7
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/fmt_f_default_field_width_1.f90
@@ -0,0 +1,45 @@
+! { dg-do run }
+! { dg-options "-cpp -fdec" }
+!
+! Test case for the default field widths enabled by the -fdec-format-defaults flag.
+!
+! This feature is not part of any Fortran standard, but it is supported by the
+! Oracle Fortran compiler and others.
+!
+
+program test
+ implicit none
+ character(50) :: buffer
+
+ real(4) :: real_4
+ real(8) :: real_8
+#ifdef __GFC_REAL_16__
+ real(16) :: real_16
+#endif
+ integer :: len
+ character(*), parameter :: fmt = "(A, F, A)"
+
+ real_4 = 4.18
+ write(buffer, fmt) ':',real_4,':'
+ print *,buffer
+ if (buffer.ne.": 4.1799998:") stop 1
+
+ real_4 = 0.00000018
+ write(buffer, fmt) ':',real_4,':'
+ print *,buffer
+ if (buffer.ne.": 0.0000002:") stop 2
+
+ real_8 = 4.18
+ write(buffer, fmt) ':',real_8,':'
+ print *,buffer
+ len = len_trim(buffer)
+ if (len /= 27) stop 3
+
+#ifdef __GFC_REAL_16__
+ real_16 = 4.18
+ write(buffer, fmt) ':',real_16,':'
+ print *,buffer
+ len = len_trim(buffer)
+ if (len /= 44) stop 4
+#endif
+end
diff --git a/gcc/testsuite/gfortran.dg/fmt_f_default_field_width_2.f90 b/gcc/testsuite/gfortran.dg/fmt_f_default_field_width_2.f90
new file mode 100644
index 0000000..1896197
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/fmt_f_default_field_width_2.f90
@@ -0,0 +1,48 @@
+! { dg-do run }
+! { dg-options "-cpp -fdec-format-defaults" }
+!
+! Test case for the default field widths enabled by the -fdec-format-defaults flag.
+!
+! This feature is not part of any Fortran standard, but it is supported by the
+! Oracle Fortran compiler and others.
+!
+! Test case added by Mark Eggleston <mark.eggleston@codethink.com> to check
+! use of -fdec-format-defaults
+!
+
+program test
+ implicit none
+ character(50) :: buffer
+
+ real(4) :: real_4
+ real(8) :: real_8
+#ifdef __GFC_REAL_16__
+ real(16) :: real_16
+#endif
+ integer :: len
+ character(*), parameter :: fmt = "(A, F, A)"
+
+ real_4 = 4.18
+ write(buffer, fmt) ':',real_4,':'
+ print *,buffer
+ if (buffer.ne.": 4.1799998:") stop 1
+
+ real_4 = 0.00000018
+ write(buffer, fmt) ':',real_4,':'
+ print *,buffer
+ if (buffer.ne.": 0.0000002:") stop 2
+
+ real_8 = 4.18
+ write(buffer, fmt) ':',real_8,':'
+ print *,buffer
+ len = len_trim(buffer)
+ if (len /= 27) stop 3
+
+#ifdef __GFC_REAL_16__
+ real_16 = 4.18
+ write(buffer, fmt) ':',real_16,':'
+ print *,buffer
+ len = len_trim(buffer)
+ if (len /= 44) stop 4
+#endif
+end
diff --git a/gcc/testsuite/gfortran.dg/fmt_f_default_field_width_3.f90 b/gcc/testsuite/gfortran.dg/fmt_f_default_field_width_3.f90
new file mode 100644
index 0000000..3e7d8f6
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/fmt_f_default_field_width_3.f90
@@ -0,0 +1,35 @@
+! { dg-do compile }
+! { dg-options "-cpp -fdec -fno-dec-format-defaults" }
+!
+! Test case for the default field widths not enabled.
+!
+! Test case added by Mark Eggleston <mark.eggleston@codethink.com> to check
+! use of -fno-dec-format-defaults
+!
+
+program test
+ implicit none
+ character(50) :: buffer
+
+ real*4 :: real_4
+ real*8 :: real_8
+#ifdef __GFC_REAL_16__
+ real*16 :: real_16
+#endif
+ integer :: len
+ character(*), parameter :: fmt = "(A, F, A)"
+
+ real_4 = 4.18
+ write(buffer, fmt) ':',real_4,':' ! { dg-error "Nonnegative width required" }
+
+ real_4 = 0.00000018
+ write(buffer, fmt) ':',real_4,':' ! { dg-error "Nonnegative width required" }
+
+ real_8 = 4.18
+ write(buffer, fmt) ':',real_8,':' ! { dg-error "Nonnegative width required" }
+
+#ifdef __GFC_REAL_16__
+ real_16 = 4.18
+ write(buffer, fmt) ':',real_16,':' ! { dg-error "Nonnegative width required" "" { target fortran_real_16 } }
+#endif
+end
diff --git a/gcc/testsuite/gfortran.dg/fmt_g_default_field_width_1.f90 b/gcc/testsuite/gfortran.dg/fmt_g_default_field_width_1.f90
new file mode 100644
index 0000000..859e648
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/fmt_g_default_field_width_1.f90
@@ -0,0 +1,50 @@
+! { dg-do run }
+! { dg-options "-cpp -fdec" }
+!
+! Test case for the default field widths enabled by the -fdec-format-defaults flag.
+!
+! This feature is not part of any Fortran standard, but it is supported by the
+! Oracle Fortran compiler and others.
+!
+
+program test
+ implicit none
+ character(50) :: buffer
+
+ real(4) :: real_4
+ real(8) :: real_8
+#ifdef __GFC_REAL_16__
+ real(16) :: real_16
+#endif
+ integer :: len
+ character(*), parameter :: fmt = "(A, G, A)"
+
+ real_4 = 4.18
+ write(buffer, fmt) ':',real_4,':'
+ print *,buffer
+ if (buffer.ne.": 4.180000 :") stop 1
+
+ real_4 = 0.00000018
+ write(buffer, fmt) ':',real_4,':'
+ print *,buffer
+ if (buffer.ne.": 0.1800000E-06:") stop 2
+
+ real_4 = 18000000.4
+ write(buffer, fmt) ':',real_4,':'
+ print *,buffer
+ if (buffer.ne.": 0.1800000E+08:") stop 3
+
+ real_8 = 4.18
+ write(buffer, fmt) ':',real_8,':'
+ print *,buffer
+ len = len_trim(buffer)
+ if (len /= 27) stop 4
+
+#ifdef __GFC_REAL_16__
+ real_16 = 4.18
+ write(buffer, fmt) ':',real_16,':'
+ print *,buffer
+ len = len_trim(buffer)
+ if (len /= 44) stop 5
+#endif
+end
diff --git a/gcc/testsuite/gfortran.dg/fmt_g_default_field_width_2.f90 b/gcc/testsuite/gfortran.dg/fmt_g_default_field_width_2.f90
new file mode 100644
index 0000000..207dcc7
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/fmt_g_default_field_width_2.f90
@@ -0,0 +1,53 @@
+! { dg-do run }
+! { dg-options "-cpp -fdec-format-defaults" }
+!
+! Test case for the default field widths enabled by the -fdec-format-defaults flag.
+!
+! This feature is not part of any Fortran standard, but it is supported by the
+! Oracle Fortran compiler and others.
+!
+! Test case added by Mark Eggleston <mark.eggleston@codethink.com> to check
+! use of -fdec-format-defaults
+!
+
+program test
+ implicit none
+ character(50) :: buffer
+
+ real(4) :: real_4
+ real(8) :: real_8
+#ifdef __GFC_REAL_16__
+ real(16) :: real_16
+#endif
+ integer :: len
+ character(*), parameter :: fmt = "(A, G, A)"
+
+ real_4 = 4.18
+ write(buffer, fmt) ':',real_4,':'
+ print *,buffer
+ if (buffer.ne.": 4.180000 :") stop 1
+
+ real_4 = 0.00000018
+ write(buffer, fmt) ':',real_4,':'
+ print *,buffer
+ if (buffer.ne.": 0.1800000E-06:") stop 2
+
+ real_4 = 18000000.4
+ write(buffer, fmt) ':',real_4,':'
+ print *,buffer
+ if (buffer.ne.": 0.1800000E+08:") stop 3
+
+ real_8 = 4.18
+ write(buffer, fmt) ':',real_8,':'
+ print *,buffer
+ len = len_trim(buffer)
+ if (len /= 27) stop 4
+
+#ifdef __GFC_REAL_16__
+ real_16 = 4.18
+ write(buffer, fmt) ':',real_16,':'
+ print *,buffer
+ len = len_trim(buffer)
+ if (len /= 44) stop 5
+#endif
+end
diff --git a/gcc/testsuite/gfortran.dg/fmt_g_default_field_width_3.f90 b/gcc/testsuite/gfortran.dg/fmt_g_default_field_width_3.f90
new file mode 100644
index 0000000..95a0598
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/fmt_g_default_field_width_3.f90
@@ -0,0 +1,38 @@
+! { dg-do compile }
+! { dg-options "-cpp -fdec -fno-dec-format-defaults" }
+!
+! Test case for the default field widths not enabled.
+!
+! Test case added by Mark Eggleston <mark.eggleston@codethink.com> to check
+! use of -fno-dec-format-defaults
+!
+
+program test
+ implicit none
+ character(50) :: buffer
+
+ real(4) :: real_4
+ real(8) :: real_8
+#ifdef __GFC_REAL_16__
+ real(16) :: real_16
+#endif
+ integer :: len
+ character(*), parameter :: fmt = "(A, G, A)"
+
+ real_4 = 4.18
+ write(buffer, fmt) ':',real_4,':' ! { dg-error "Positive width required" }
+
+ real_4 = 0.00000018
+ write(buffer, fmt) ':',real_4,':' ! { dg-error "Positive width required" }
+
+ real_4 = 18000000.4
+ write(buffer, fmt) ':',real_4,':' ! { dg-error "Positive width required" }
+
+ real_8 = 4.18
+ write(buffer, fmt) ':',real_8,':' ! { dg-error "Positive width required" }
+
+#ifdef __GFC_REAL_16__
+ real_16 = 4.18
+ write(buffer, fmt) ':',real_16,':' ! { dg-error "Positive width required" "" { target fortran_real_16 } }
+#endif
+end
diff --git a/gcc/testsuite/gfortran.dg/fmt_i_default_field_width_1.f90 b/gcc/testsuite/gfortran.dg/fmt_i_default_field_width_1.f90
new file mode 100644
index 0000000..bb539ad
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/fmt_i_default_field_width_1.f90
@@ -0,0 +1,40 @@
+! { dg-do run }
+! { dg-options -fdec }
+!
+! Test case for the default field widths enabled by the -fdec-format-defaults flag.
+!
+! This feature is not part of any Fortran standard, but it is supported by the
+! Oracle Fortran compiler and others.
+
+program test
+ character(50) :: buffer
+ character(1) :: colon
+
+ integer(2) :: integer_2
+ integer(4) :: integer_4
+ integer(8) :: integer_8
+ character(*), parameter :: fmt = "(A, I, A)"
+
+ write(buffer, fmt) ':',12340,':'
+ print *,buffer
+ if (buffer.ne.": 12340:") stop 1
+
+ read(buffer, "(1A, I, 1A)") colon, integer_4, colon
+ if ((integer_4.ne.12340).or.(colon.ne.":")) stop 2
+
+ integer_2 = -99
+ write(buffer, fmt) ':',integer_2,':'
+ print *,buffer
+ if (buffer.ne.": -99:") stop 3
+
+ integer_8 = -11112222
+ write(buffer, fmt) ':',integer_8,':'
+ print *,buffer
+ if (buffer.ne.": -11112222:") stop 4
+
+! If the width is 7 and there are 7 leading zeroes, the result should be zero.
+ integer_2 = 789
+ buffer = '0000000789'
+ read(buffer, '(I)') integer_2
+ if (integer_2.ne.0) stop 5
+end
diff --git a/gcc/testsuite/gfortran.dg/fmt_i_default_field_width_2.f90 b/gcc/testsuite/gfortran.dg/fmt_i_default_field_width_2.f90
new file mode 100644
index 0000000..1583c23
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/fmt_i_default_field_width_2.f90
@@ -0,0 +1,44 @@
+! { dg-do run }
+! { dg-options -fdec-format-defaults }
+!
+! Test case for the default field widths enabled by the -fdec-format-defaults flag.
+!
+! This feature is not part of any Fortran standard, but it is supported by the
+! Oracle Fortran compiler and others.
+!
+! Test case added by Mark Eggleston <mark.eggleston@codethink.com> to check
+! use of -fdec-format-defaults
+!
+
+program test
+ character(50) :: buffer
+ character(1) :: colon
+
+ integer(2) :: integer_2
+ integer(4) :: integer_4
+ integer(8) :: integer_8
+ character(*), parameter :: fmt = "(A, I, A)"
+
+ write(buffer, fmt) ':',12340,':'
+ print *,buffer
+ if (buffer.ne.": 12340:") stop 1
+
+ read(buffer, '(A1, I, A1)') colon, integer_4, colon
+ if ((integer_4.ne.12340).or.(colon.ne.":")) stop 2
+
+ integer_2 = -99
+ write(buffer, fmt) ':',integer_2,':'
+ print *,buffer
+ if (buffer.ne.": -99:") stop 3
+
+ integer_8 = -11112222
+ write(buffer, fmt) ':',integer_8,':'
+ print *,buffer
+ if (buffer.ne.": -11112222:") stop 4
+
+! If the width is 7 and there are 7 leading zeroes, the result should be zero.
+ integer_2 = 789
+ buffer = '0000000789'
+ read(buffer, '(I)') integer_2
+ if (integer_2.ne.0) stop 5
+end
diff --git a/gcc/testsuite/gfortran.dg/fmt_i_default_field_width_3.f90 b/gcc/testsuite/gfortran.dg/fmt_i_default_field_width_3.f90
new file mode 100644
index 0000000..325190d
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/fmt_i_default_field_width_3.f90
@@ -0,0 +1,37 @@
+! { dg-do compile }
+! { dg-options "-fdec -fno-dec-format-defaults" }
+!
+! Test case for the default field widths enabled by the -fdec-format-defaults flag.
+!
+! This feature is not part of any Fortran standard, but it is supported by the
+! Oracle Fortran compiler and others.
+!
+! Test case added by Mark Eggleston <mark.eggleston@codethink.com> to check
+! use of -fdec-format-defaults
+!
+
+program test
+ character(50) :: buffer
+ character(1) :: colon
+
+ integer(2) :: integer_2
+ integer(4) :: integer_4
+ integer(8) :: integer_8
+ character(*), parameter :: fmt = "(A, I, A)"
+
+ write(buffer, fmt) ':',12340,':' ! { dg-error "Nonnegative width required" }
+
+ read(buffer, '(A1, I, A1)') colon, integer_4, colon ! { dg-error "Nonnegative width required" }
+ if (integer_4.ne.12340) stop 2
+
+ integer_2 = -99
+ write(buffer, fmt) ':',integer_2,':' ! { dg-error "Nonnegative width required" }
+
+ integer_8 = -11112222
+ write(buffer, fmt) ':',integer_8,':' ! { dg-error "Nonnegative width required" }
+
+! If the width is 7 and there are 7 leading zeroes, the result should be zero.
+ integer_2 = 789
+ buffer = '0000000789'
+ read(buffer, '(I)') integer_2 ! { dg-error "Nonnegative width required" }
+end
diff --git a/gcc/testsuite/gfortran.dg/goacc/classify-routine.f95 b/gcc/testsuite/gfortran.dg/goacc/classify-routine.f95
index e435f5d..401d527 100644
--- a/gcc/testsuite/gfortran.dg/goacc/classify-routine.f95
+++ b/gcc/testsuite/gfortran.dg/goacc/classify-routine.f95
@@ -21,10 +21,10 @@ subroutine ROUTINE
end subroutine ROUTINE
! Check the offloaded function's attributes.
-! { dg-final { scan-tree-dump-times "(?n)__attribute__\\(\\(omp declare target, oacc function \\(0 1, 1 0, 1 0\\)\\)\\)" 1 "ompexp" } }
+! { dg-final { scan-tree-dump-times "(?n)__attribute__\\(\\(oacc function \\(0 1, 1 0, 1 0\\), omp declare target \\(worker\\)\\)\\)" 1 "ompexp" } }
! Check the offloaded function's classification and compute dimensions (will
! always be 1 x 1 x 1 for non-offloading compilation).
! { dg-final { scan-tree-dump-times "(?n)Function is OpenACC routine level 1" 1 "oaccdevlow" } }
! { dg-final { scan-tree-dump-times "(?n)Compute dimensions \\\[1, 1, 1\\\]" 1 "oaccdevlow" } }
-! { dg-final { scan-tree-dump-times "(?n)__attribute__\\(\\(oacc function \\(0 1, 1 1, 1 1\\), omp declare target, oacc function \\(0 1, 1 0, 1 0\\)\\)\\)" 1 "oaccdevlow" } }
+! { dg-final { scan-tree-dump-times "(?n)__attribute__\\(\\(oacc function \\(0 1, 1 1, 1 1\\), omp declare target \\(worker\\)\\)\\)" 1 "oaccdevlow" } }
diff --git a/gcc/testsuite/gfortran.dg/goacc/declare-3.f95 b/gcc/testsuite/gfortran.dg/goacc/declare-3.f95
new file mode 100644
index 0000000..80d9903
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/goacc/declare-3.f95
@@ -0,0 +1,53 @@
+! Test valid usage of the OpenACC 'declare' directive.
+
+! { dg-additional-options "-fdump-tree-original" }
+
+module mod_a
+ implicit none
+ integer :: a
+ !$acc declare create (a)
+end module
+
+module mod_b
+ implicit none
+ integer :: b
+ !$acc declare copyin (b)
+end module
+
+module mod_c
+ implicit none
+ integer :: c
+ !$acc declare deviceptr (c)
+end module
+
+module mod_d
+ implicit none
+ integer :: d
+ !$acc declare device_resident (d)
+end module
+
+module mod_e
+ implicit none
+ integer :: e
+ !$acc declare link (e)
+end module
+
+subroutine sub1
+ use mod_a
+ use mod_b
+ use mod_c
+ use mod_d
+ use mod_e
+end subroutine sub1
+
+program test
+ use mod_a
+ use mod_b
+ use mod_c
+ use mod_d
+ use mod_e
+
+ ! { dg-final { scan-tree-dump {(?n)#pragma acc data map\(force_alloc:d\) map\(force_deviceptr:c\) map\(force_to:b\) map\(force_alloc:a\)$} original } }
+end program test
+
+! { dg-final { scan-tree-dump-times {#pragma acc data} 1 original } }
diff --git a/gcc/testsuite/gfortran.dg/goacc/pr78027.f90 b/gcc/testsuite/gfortran.dg/goacc/pr78027.f90
index a1e51fa..cf13ff7 100644
--- a/gcc/testsuite/gfortran.dg/goacc/pr78027.f90
+++ b/gcc/testsuite/gfortran.dg/goacc/pr78027.f90
@@ -19,6 +19,4 @@ real function f()
!$acc end parallel
end
-! { dg-final { scan-ipa-dump "Not parsed function:f_._omp_fn.1" "icf" } }
-! { dg-final { scan-ipa-dump "Not parsed function:f_._omp_fn.0" "icf" } }
-! { dg-final { scan-ipa-dump "Not parsed function:f_" "icf" } }
+! { dg-final { scan-ipa-dump-times "with total: 0 items" 5 "icf" } }
diff --git a/gcc/testsuite/gfortran.dg/goacc/routine-level-of-parallelism-1.f90 b/gcc/testsuite/gfortran.dg/goacc/routine-level-of-parallelism-1.f90
index 75dd1b0..83b8c24 100644
--- a/gcc/testsuite/gfortran.dg/goacc/routine-level-of-parallelism-1.f90
+++ b/gcc/testsuite/gfortran.dg/goacc/routine-level-of-parallelism-1.f90
@@ -1,6 +1,6 @@
-! Test various aspects of clauses specifying compatible levels of
-! parallelism with the OpenACC routine directive. The Fortran counterpart is
-! c-c++-common/goacc/routine-level-of-parallelism-2.c
+! Test various aspects of clauses specifying compatible levels of parallelism
+! with the OpenACC routine directive. The C/C++ counterpart is
+! '../../c-c++-common/goacc/routine-level-of-parallelism-2.c'.
subroutine g_1
!$acc routine gang
diff --git a/gcc/testsuite/gfortran.dg/ieee/ieee_4.f90 b/gcc/testsuite/gfortran.dg/ieee/ieee_4.f90
index a91006a..a23d3a0 100644
--- a/gcc/testsuite/gfortran.dg/ieee/ieee_4.f90
+++ b/gcc/testsuite/gfortran.dg/ieee/ieee_4.f90
@@ -1,4 +1,4 @@
-! { dg-do run { xfail i?86-*-freebsd* } }
+! { dg-do run }
use :: ieee_arithmetic
implicit none
diff --git a/gcc/testsuite/gfortran.dg/integer_exponentiation_4.f90 b/gcc/testsuite/gfortran.dg/integer_exponentiation_4.f90
index 655f651..b224ef9 100644
--- a/gcc/testsuite/gfortran.dg/integer_exponentiation_4.f90
+++ b/gcc/testsuite/gfortran.dg/integer_exponentiation_4.f90
@@ -21,10 +21,10 @@ program test
print *, (-1)**huge(0_8)
print *, (-1)**(-huge(0_8)-1_8)
- print *, 2**huge(0) ! { dg-error "Arithmetic overflow" }
- print *, 2**huge(0_8) ! { dg-error "Arithmetic overflow" }
- print *, (-2)**huge(0) ! { dg-error "Arithmetic overflow" }
- print *, (-2)**huge(0_8) ! { dg-error "Arithmetic overflow" }
+ print *, 2**huge(0) ! { dg-error "Arithmetic overflow|exceeds the range" }
+ print *, 2**huge(0_8) ! { dg-error "Arithmetic overflow|exceeds the range" }
+ print *, (-2)**huge(0) ! { dg-error "Arithmetic overflow|exceeds the range" }
+ print *, (-2)**huge(0_8) ! { dg-error "Arithmetic overflow|exceeds the range" }
print *, 2**(-huge(0)-1)
print *, 2**(-huge(0_8)-1_8)
diff --git a/gcc/testsuite/gfortran.dg/integer_exponentiation_5.F90 b/gcc/testsuite/gfortran.dg/integer_exponentiation_5.F90
index 6069bdf..f16b751 100644
--- a/gcc/testsuite/gfortran.dg/integer_exponentiation_5.F90
+++ b/gcc/testsuite/gfortran.dg/integer_exponentiation_5.F90
@@ -67,8 +67,6 @@ program test
TEST(3_8,43_8,i8)
TEST(-3_8,43_8,i8)
- TEST(17_8,int(huge(0_4),kind=8)+1,i8)
-
!!!!! REAL BASE !!!!!
TEST(0.0,-1,r4)
TEST(0.0,-huge(0)-1,r4)
diff --git a/gcc/testsuite/gfortran.dg/internal_pack_11.f90 b/gcc/testsuite/gfortran.dg/internal_pack_11.f90
index a1d357c..c341a1b 100644
--- a/gcc/testsuite/gfortran.dg/internal_pack_11.f90
+++ b/gcc/testsuite/gfortran.dg/internal_pack_11.f90
@@ -1,5 +1,5 @@
! { dg-do compile }
-! { dg-options "-fdump-tree-original" }
+! { dg-options "-O0 -fdump-tree-original" }
!
! Test the fix for PR43173, where unnecessary calls to internal_pack/unpack
! were being produced below. These references are contiguous and so do not
diff --git a/gcc/testsuite/gfortran.dg/internal_pack_12.f90 b/gcc/testsuite/gfortran.dg/internal_pack_12.f90
index 55631c8..da50732 100644
--- a/gcc/testsuite/gfortran.dg/internal_pack_12.f90
+++ b/gcc/testsuite/gfortran.dg/internal_pack_12.f90
@@ -1,5 +1,5 @@
! { dg-do compile }
-! { dg-options "-fdump-tree-original" }
+! { dg-options "-O0 -fdump-tree-original" }
!
! Test the fix for PR43243, where unnecessary calls to internal_pack/unpack
! were being produced below. These references are contiguous and so do not
diff --git a/gcc/testsuite/gfortran.dg/internal_pack_16.f90 b/gcc/testsuite/gfortran.dg/internal_pack_16.f90
index 7e34c2b..92c4b15 100644
--- a/gcc/testsuite/gfortran.dg/internal_pack_16.f90
+++ b/gcc/testsuite/gfortran.dg/internal_pack_16.f90
@@ -1,5 +1,5 @@
! { dg-do compile }
-! { dg-additional-options "-fdump-tree-original" }
+! { dg-additional-options "-O0 -fdump-tree-original" }
! PR 59345 - pack/unpack was not needed here.
SUBROUTINE S1(A)
REAL :: A(3)
diff --git a/gcc/testsuite/gfortran.dg/internal_pack_17.f90 b/gcc/testsuite/gfortran.dg/internal_pack_17.f90
index c1b813b..176ad87 100644
--- a/gcc/testsuite/gfortran.dg/internal_pack_17.f90
+++ b/gcc/testsuite/gfortran.dg/internal_pack_17.f90
@@ -1,5 +1,5 @@
! { dg-do compile }
-! { dg-additional-options "-fdump-tree-original" }
+! { dg-additional-options "-O0 -fdump-tree-original" }
! PR 59345 - pack/unpack was not needed here.
! Original test case by Joost VandeVondele
SUBROUTINE S1(A)
diff --git a/gcc/testsuite/gfortran.dg/internal_pack_18.f90 b/gcc/testsuite/gfortran.dg/internal_pack_18.f90
index ede0691..b440472 100644
--- a/gcc/testsuite/gfortran.dg/internal_pack_18.f90
+++ b/gcc/testsuite/gfortran.dg/internal_pack_18.f90
@@ -1,5 +1,5 @@
! { dg-do compile }
-! { dg-additional-options "-fdump-tree-original" }
+! { dg-additional-options "-O0 -fdump-tree-original" }
! PR 57992 - this was packed/unpacked unnecessarily.
! Original case by Tobias Burnus.
subroutine test
diff --git a/gcc/testsuite/gfortran.dg/internal_pack_19.f90 b/gcc/testsuite/gfortran.dg/internal_pack_19.f90
new file mode 100644
index 0000000..06b916b
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/internal_pack_19.f90
@@ -0,0 +1,23 @@
+! { dg-do compile }
+! { dg-options "-Os -fdump-tree-original" }
+! Check that internal_pack is called with -Os.
+module x
+ implicit none
+contains
+ subroutine bar(a, n)
+ integer, intent(in) :: n
+ integer, intent(in), dimension(n) :: a
+ print *,a
+ end subroutine bar
+end module x
+
+program main
+ use x
+ implicit none
+ integer, parameter :: n = 10
+ integer, dimension(n) :: a
+ integer :: i
+ a = [(i,i=1,n)]
+ call bar(a(n:1:-1),n)
+end program main
+! { dg-final { scan-tree-dump-times "_gfortran_internal_pack" 1 "original" } }
diff --git a/gcc/testsuite/gfortran.dg/internal_pack_20.f90 b/gcc/testsuite/gfortran.dg/internal_pack_20.f90
new file mode 100644
index 0000000..f93f06b
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/internal_pack_20.f90
@@ -0,0 +1,23 @@
+! { dg-do compile }
+! { dg-options "-O -fdump-tree-original" }
+! Check that internal_pack is not called with -O.
+module x
+ implicit none
+contains
+ subroutine bar(a, n)
+ integer, intent(in) :: n
+ integer, intent(in), dimension(n) :: a
+ print *,a
+ end subroutine bar
+end module x
+
+program main
+ use x
+ implicit none
+ integer, parameter :: n = 10
+ integer, dimension(n) :: a
+ integer :: i
+ a = [(i,i=1,n)]
+ call bar(a(n:1:-1),n)
+end program main
+! { dg-final { scan-tree-dump-not "_gfortran_internal_pack" "original" } }
diff --git a/gcc/testsuite/gfortran.dg/internal_pack_21.f90 b/gcc/testsuite/gfortran.dg/internal_pack_21.f90
new file mode 100644
index 0000000..54e43ff
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/internal_pack_21.f90
@@ -0,0 +1,24 @@
+! { dg-do run }
+! { dg-options "-O -fdump-tree-original" }
+! Test handling of the optional argument.
+
+MODULE M1
+ INTEGER, PARAMETER :: dp=KIND(0.0D0)
+CONTAINS
+ SUBROUTINE S1(a)
+ REAL(dp), DIMENSION(45), INTENT(OUT), &
+ OPTIONAL :: a
+ if (present(a)) STOP 1
+ END SUBROUTINE S1
+ SUBROUTINE S2(a)
+ REAL(dp), DIMENSION(:, :), INTENT(OUT), &
+ OPTIONAL :: a
+ CALL S1(a)
+ END SUBROUTINE
+END MODULE M1
+
+USE M1
+CALL S2()
+END
+! { dg-final { scan-tree-dump-times "arg_ptr" 5 "original" } }
+! { dg-final { scan-tree-dump-not "_gfortran_internal_unpack" "original" } }
diff --git a/gcc/testsuite/gfortran.dg/internal_pack_22.f90 b/gcc/testsuite/gfortran.dg/internal_pack_22.f90
new file mode 100644
index 0000000..4e9fe59
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/internal_pack_22.f90
@@ -0,0 +1,36 @@
+! { dg-do run }
+! { dg-additional-options "-fdump-tree-original -O" }
+! Check that absent and present dummy arguments work with
+! packing when handing them down to an old-fashioned argument.
+
+module x
+ implicit none
+contains
+ subroutine foo (a,b)
+ real, dimension(:), intent(inout), optional :: a, b
+ if (present(a)) stop 1
+ if (.not. present(b)) stop 2
+ call bar (a, b)
+ end subroutine foo
+
+ subroutine bar (a,b)
+ real, dimension(2), intent(inout), optional :: a, b
+ real :: tmp
+ if (present(a)) stop 3
+ if (.not. present(b)) stop 4
+ tmp = b(2)
+ b(2) = b(1)
+ b(1) = tmp
+ end subroutine bar
+end module x
+
+program main
+ use x
+ implicit none
+ real, dimension(2) :: b
+ b(1) = 1.
+ b(2) = 42.
+ call foo(b=b)
+ if (b(1) /= 42. .or. b(2) /= 1.) stop 5
+end program main
+! { dg-final { scan-tree-dump-not "_gfortran_internal_unpack" "original" } }
diff --git a/gcc/testsuite/gfortran.dg/internal_pack_23.f90 b/gcc/testsuite/gfortran.dg/internal_pack_23.f90
new file mode 100644
index 0000000..8df82c8
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/internal_pack_23.f90
@@ -0,0 +1,27 @@
+! { dg-do run }
+! PR fortran/90539 - this used to cause an ICE.
+
+module t2
+ implicit none
+contains
+ subroutine foo(a)
+ real, dimension(*) :: a
+ if (a(1) /= 1.0 .or. a(2) /= 2.0) stop 1
+ end subroutine foo
+end module t2
+
+module t1
+ use t2
+ implicit none
+contains
+ subroutine bar(a)
+ real, dimension(:) :: a
+ if (a(1) /= 1.0 .or. a(2) /= 2.0) stop 1
+ call foo(a)
+ end subroutine bar
+end module t1
+
+program main
+ use t1
+ call bar([1.0, 2.0])
+end program main
diff --git a/gcc/testsuite/gfortran.dg/internal_pack_24.f90 b/gcc/testsuite/gfortran.dg/internal_pack_24.f90
new file mode 100644
index 0000000..cc2443e
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/internal_pack_24.f90
@@ -0,0 +1,39 @@
+! { dg-do run }
+! { dg-additional-options "-O -fdump-tree-optimized" }
+module y
+ implicit none
+contains
+ subroutine foo(a,b,c,d,e,f)
+ real, dimension(1), intent(inout) :: a, b, c, d, e, f
+ if (any([a,b,c,d,e,f] /= [1,2,3,4,5,6])) stop 1
+ a = -a
+ b = -b
+ c = -c
+ d = -d
+ e = -e
+ f = -f
+ end subroutine foo
+end module y
+module x
+ use y
+ implicit none
+contains
+ subroutine bar(a)
+ real, dimension(:) :: a
+ integer :: n1, n3, n5
+ n1 = 1
+ n3 = 3
+ n5 = 5
+ call foo(a(n1:n1), a(n1+1:n1+1), a(n3:n3), a(n3+1:n3+1), a(n5:n5), a(n5+1:n5+1))
+ end subroutine bar
+end module x
+
+program main
+ use x
+ real, dimension(6) :: a,b
+ b = [1,2,3,4,5,6]
+ a = b
+ call bar(a)
+ if (any(a /= -b)) stop 2
+end program main
+! { dg-final { scan-tree-dump-not "contiguous" "optimized" } }
diff --git a/gcc/testsuite/gfortran.dg/internal_pack_4.f90 b/gcc/testsuite/gfortran.dg/internal_pack_4.f90
index 00f3164..9de09ab 100644
--- a/gcc/testsuite/gfortran.dg/internal_pack_4.f90
+++ b/gcc/testsuite/gfortran.dg/internal_pack_4.f90
@@ -1,5 +1,4 @@
! { dg-do run }
-! { dg-options "-fdump-tree-original" }
!
! PR fortran/36132
!
@@ -25,6 +24,3 @@ END MODULE M1
USE M1
CALL S2()
END
-
-! { dg-final { scan-tree-dump-times "a != 0B \\? \\\(.*\\\) _gfortran_internal_pack" 1 "original" } }
-! { dg-final { scan-tree-dump-times "if \\(a != 0B &&" 1 "original" } }
diff --git a/gcc/testsuite/gfortran.dg/internal_pack_5.f90 b/gcc/testsuite/gfortran.dg/internal_pack_5.f90
index 3c5868f..360ade4 100644
--- a/gcc/testsuite/gfortran.dg/internal_pack_5.f90
+++ b/gcc/testsuite/gfortran.dg/internal_pack_5.f90
@@ -1,5 +1,5 @@
! { dg-do compile }
-! { dg-options "-fdump-tree-original" }
+! { dg-options "-O0 -fdump-tree-original" }
!
! PR fortran/36909
!
diff --git a/gcc/testsuite/gfortran.dg/internal_pack_6.f90 b/gcc/testsuite/gfortran.dg/internal_pack_6.f90
index d610276..6d52a8c 100644
--- a/gcc/testsuite/gfortran.dg/internal_pack_6.f90
+++ b/gcc/testsuite/gfortran.dg/internal_pack_6.f90
@@ -1,5 +1,5 @@
-! { dg-do run }
-! { dg-options "-fdump-tree-original" }
+! { dg-do compile }
+! { dg-options "-O0 -fdump-tree-original" }
!
! Test the fix for PR41113 and PR41117, in which unnecessary calls
! to internal_pack and internal_unpack were being generated.
diff --git a/gcc/testsuite/gfortran.dg/internal_pack_6a.f90 b/gcc/testsuite/gfortran.dg/internal_pack_6a.f90
new file mode 100644
index 0000000..a9fb2b5
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/internal_pack_6a.f90
@@ -0,0 +1,56 @@
+! { dg-do run }
+!
+! Test the fix for PR41113 and PR41117, in which unnecessary calls
+! to internal_pack and internal_unpack were being generated.
+!
+! Contributed by Joost VandeVondele <jv244@cam.ac.uk>
+!
+MODULE M1
+ TYPE T1
+ REAL :: data(10) = [(i, i = 1, 10)]
+ END TYPE T1
+CONTAINS
+ SUBROUTINE S1(data, i, chksum)
+ REAL, DIMENSION(*) :: data
+ integer :: i, j
+ real :: subsum, chksum
+ subsum = 0
+ do j = 1, i
+ subsum = subsum + data(j)
+ end do
+ if (abs(subsum - chksum) > 1e-6) STOP 1
+ END SUBROUTINE S1
+END MODULE
+
+SUBROUTINE S2
+ use m1
+ TYPE(T1) :: d
+
+ real :: data1(10) = [(i, i = 1, 10)]
+ REAL :: data(-4:5,-4:5) = reshape ([(real(i), i = 1, 100)], [10,10])
+
+! PR41113
+ CALL S1(d%data, 10, sum (d%data))
+ CALL S1(data1, 10, sum (data1))
+
+! PR41117
+ DO i=-4,5
+ CALL S1(data(:,i), 10, sum (data(:,i)))
+ ENDDO
+
+! With the fix for PR41113/7 this is the only time that _internal_pack
+! was called. The final part of the fix for PR43072 put paid to it too.
+ DO i=-4,5
+ CALL S1(data(-2:,i), 8, sum (data(-2:,i)))
+ ENDDO
+ DO i=-4,4
+ CALL S1(data(:,i:i+1), 20, sum (reshape (data(:,i:i+1), [20])))
+ ENDDO
+ DO i=-4,5
+ CALL S1(data(2,i), 1, data(2,i))
+ ENDDO
+END SUBROUTINE S2
+
+ call s2
+end
+
diff --git a/gcc/testsuite/gfortran.dg/internal_pack_9.f90 b/gcc/testsuite/gfortran.dg/internal_pack_9.f90
index 9ce53f4..2b44db5 100644
--- a/gcc/testsuite/gfortran.dg/internal_pack_9.f90
+++ b/gcc/testsuite/gfortran.dg/internal_pack_9.f90
@@ -1,5 +1,5 @@
! { dg-do compile }
-! { dg-options "-fdump-tree-original" }
+! { dg-options "-O0 -fdump-tree-original" }
!
! During the discussion of the fix for PR43072, in which unnecessary
! calls to internal PACK/UNPACK were being generated, the following,
diff --git a/gcc/testsuite/gfortran.dg/io_constraints_14.f90 b/gcc/testsuite/gfortran.dg/io_constraints_14.f90
new file mode 100644
index 0000000..e5b62b1
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/io_constraints_14.f90
@@ -0,0 +1,13 @@
+! { dg-do compile }
+program pr89782
+ character(len=*),parameter :: VALUES(*)=[character(len=10) :: 'NaN','NAN','nan','Inf','INF','inf','Infinity']
+ character(len=*),parameter :: VALUE='NaN'
+ real(4) :: var
+ do i=1,size(VALUES)
+ read(VALUES(i),*) float ! { dg-error "character PARAMETER" }
+ write(VALUES(i),*)float ! { dg-error "character PARAMETER" }
+ enddo
+ read(var,*)float ! { dg-error "INTEGER expression or a CHARACTER" }
+ read(VALUE,*)float ! { dg-error "character PARAMETER" }
+ write(VALUE,*)float ! { dg-error "character PARAMETER" }
+end program pr89782
diff --git a/gcc/testsuite/gfortran.dg/iso_c_binding_char_1.f90 b/gcc/testsuite/gfortran.dg/iso_c_binding_char_1.f90
new file mode 100644
index 0000000..ebf9a24
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/iso_c_binding_char_1.f90
@@ -0,0 +1,10 @@
+! { dg-do compile }
+!
+! Test the fix for PR90352.
+!
+! Contributed by Thomas Koenig <tkoenig@gcc.gnu.org>
+!
+subroutine bar(c,d) BIND(C) ! { dg-error "must be length 1" }
+ character (len=*) c
+ character (len=2) d
+end
diff --git a/gcc/testsuite/gfortran.dg/lrshift_1.f90 b/gcc/testsuite/gfortran.dg/lrshift_1.f90
index b0e5379..d262921 100644
--- a/gcc/testsuite/gfortran.dg/lrshift_1.f90
+++ b/gcc/testsuite/gfortran.dg/lrshift_1.f90
@@ -10,7 +10,7 @@ program test_rshift_lshift
1, 2, 127, 128, 129, huge(i)/2, huge(i) /)
do n = 1, size(i)
- do j = -30, 30
+ do j = 0, 31
if (lshift(i(n),j) /= c_lshift(i(n),j)) STOP 1
if (rshift(i(n),j) /= c_rshift(i(n),j)) STOP 2
end do
diff --git a/gcc/testsuite/gfortran.dg/missing_optional_dummy_6.f90 b/gcc/testsuite/gfortran.dg/missing_optional_dummy_6.f90
index 4468ff1..cb6de2e 100644
--- a/gcc/testsuite/gfortran.dg/missing_optional_dummy_6.f90
+++ b/gcc/testsuite/gfortran.dg/missing_optional_dummy_6.f90
@@ -46,14 +46,3 @@ contains
end subroutine scalar2
end program test
-
-! { dg-final { scan-tree-dump-times "scalar2 \\(slr1" 1 "original" } }
-
-! { dg-final { scan-tree-dump-times "= es1 != 0B" 1 "original" } }
-! { dg-final { scan-tree-dump-times "assumed_shape2 \\(es1" 0 "original" } }
-! { dg-final { scan-tree-dump-times "explicit_shape2 \\(es1" 1 "original" } }
-
-! { dg-final { scan-tree-dump-times "= as1 != 0B" 2 "original" } }
-! { dg-final { scan-tree-dump-times "assumed_shape2 \\(as1" 0 "original" } }
-! { dg-final { scan-tree-dump-times "explicit_shape2 \\(as1" 0 "original" } }
-
diff --git a/gcc/testsuite/gfortran.dg/missing_optional_dummy_6a.f90 b/gcc/testsuite/gfortran.dg/missing_optional_dummy_6a.f90
new file mode 100644
index 0000000..0e08ed3
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/missing_optional_dummy_6a.f90
@@ -0,0 +1,59 @@
+! { dg-do compile }
+! { dg-options "-O0 -fdump-tree-original" }
+!
+! PR fortran/41907
+!
+program test
+ implicit none
+ call scalar1 ()
+ call assumed_shape1 ()
+ call explicit_shape1 ()
+contains
+
+ ! Calling functions
+ subroutine scalar1 (slr1)
+ integer, optional :: slr1
+ call scalar2 (slr1)
+ end subroutine scalar1
+
+ subroutine assumed_shape1 (as1)
+ integer, dimension(:), optional :: as1
+ call assumed_shape2 (as1)
+ call explicit_shape2 (as1)
+ end subroutine assumed_shape1
+
+ subroutine explicit_shape1 (es1)
+ integer, dimension(5), optional :: es1
+ call assumed_shape2 (es1)
+ call explicit_shape2 (es1)
+ end subroutine explicit_shape1
+
+
+ ! Called functions
+ subroutine assumed_shape2 (as2)
+ integer, dimension(:),optional :: as2
+ if (present (as2)) STOP 1
+ end subroutine assumed_shape2
+
+ subroutine explicit_shape2 (es2)
+ integer, dimension(5),optional :: es2
+ if (present (es2)) STOP 2
+ end subroutine explicit_shape2
+
+ subroutine scalar2 (slr2)
+ integer, optional :: slr2
+ if (present (slr2)) STOP 3
+ end subroutine scalar2
+
+end program test
+
+! { dg-final { scan-tree-dump-times "scalar2 \\(slr1" 1 "original" } }
+
+! { dg-final { scan-tree-dump-times "= es1 != 0B" 1 "original" } }
+! { dg-final { scan-tree-dump-times "assumed_shape2 \\(es1" 0 "original" } }
+! { dg-final { scan-tree-dump-times "explicit_shape2 \\(es1" 1 "original" } }
+
+! { dg-final { scan-tree-dump-times "= as1 != 0B" 2 "original" } }
+! { dg-final { scan-tree-dump-times "assumed_shape2 \\(as1" 0 "original" } }
+! { dg-final { scan-tree-dump-times "explicit_shape2 \\(as1" 0 "original" } }
+
diff --git a/gcc/testsuite/gfortran.dg/module_error_1.f90 b/gcc/testsuite/gfortran.dg/module_error_1.f90
index 84decc0..1792be6 100644
--- a/gcc/testsuite/gfortran.dg/module_error_1.f90
+++ b/gcc/testsuite/gfortran.dg/module_error_1.f90
@@ -1,5 +1,5 @@
! { dg-do compile }
! PR fortran/50627
module kernels
- select type (args) ! { dg-error "Unexpected SELECT TYPE" }
+ select type (args) ! { dg-error "cannot appear in this scope" }
end module kernels
diff --git a/gcc/testsuite/gfortran.dg/namelist_89.f90 b/gcc/testsuite/gfortran.dg/namelist_89.f90
index fbb7143..91f64fe 100644
--- a/gcc/testsuite/gfortran.dg/namelist_89.f90
+++ b/gcc/testsuite/gfortran.dg/namelist_89.f90
@@ -1,4 +1,4 @@
-! { dg-do run }
+! { dg-do run { target fd_truncate } }
! PR69456 Namelist value with trailing sign is ignored without error
implicit none
integer :: ios
diff --git a/gcc/testsuite/gfortran.dg/no_arg_check_2.f90 b/gcc/testsuite/gfortran.dg/no_arg_check_2.f90
index fe33488..3570b97 100644
--- a/gcc/testsuite/gfortran.dg/no_arg_check_2.f90
+++ b/gcc/testsuite/gfortran.dg/no_arg_check_2.f90
@@ -1,5 +1,5 @@
-! { dg-do run }
-! { dg-options "-fdump-tree-original" }
+! { dg-do compile }
+! { dg-options "-O0 -fdump-tree-original" }
!
! PR fortran/39505
!
diff --git a/gcc/testsuite/gfortran.dg/no_arg_check_2a.f90 b/gcc/testsuite/gfortran.dg/no_arg_check_2a.f90
new file mode 100644
index 0000000..dc4adcb
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/no_arg_check_2a.f90
@@ -0,0 +1,121 @@
+! { dg-do run }
+!
+! PR fortran/39505
+!
+! Test NO_ARG_CHECK
+! Copied from assumed_type_2.f90
+!
+
+module mod
+ use iso_c_binding, only: c_loc, c_ptr, c_bool
+ implicit none
+ interface my_c_loc
+ function my_c_loc1(x) bind(C)
+ import c_ptr
+!GCC$ attributes NO_ARG_CHECK :: x
+ type(*) :: x
+ type(c_ptr) :: my_c_loc1
+ end function
+ end interface my_c_loc
+contains
+ subroutine sub_scalar (arg1, presnt)
+ integer(8), target, optional :: arg1
+ logical :: presnt
+ type(c_ptr) :: cpt
+!GCC$ attributes NO_ARG_CHECK :: arg1
+ if (presnt .neqv. present (arg1)) STOP 1
+ cpt = c_loc (arg1)
+ end subroutine sub_scalar
+
+ subroutine sub_array_assumed (arg3)
+!GCC$ attributes NO_ARG_CHECK :: arg3
+ logical(1), target :: arg3(*)
+ type(c_ptr) :: cpt
+ cpt = c_loc (arg3)
+ end subroutine sub_array_assumed
+end module
+
+use mod
+use iso_c_binding, only: c_int, c_null_ptr
+implicit none
+type t1
+ integer :: a
+end type t1
+type :: t2
+ sequence
+ integer :: b
+end type t2
+type, bind(C) :: t3
+ integer(c_int) :: c
+end type t3
+
+integer :: scalar_int
+real, allocatable :: scalar_real_alloc
+character, pointer :: scalar_char_ptr
+
+integer :: array_int(3)
+real, allocatable :: array_real_alloc(:,:)
+character, pointer :: array_char_ptr(:,:)
+
+type(t1) :: scalar_t1
+type(t2), allocatable :: scalar_t2_alloc
+type(t3), pointer :: scalar_t3_ptr
+
+type(t1) :: array_t1(4)
+type(t2), allocatable :: array_t2_alloc(:,:)
+type(t3), pointer :: array_t3_ptr(:,:)
+
+class(t1), allocatable :: scalar_class_t1_alloc
+class(t1), pointer :: scalar_class_t1_ptr
+
+class(t1), allocatable :: array_class_t1_alloc(:,:)
+class(t1), pointer :: array_class_t1_ptr(:,:)
+
+scalar_char_ptr => null()
+scalar_t3_ptr => null()
+
+call sub_scalar (presnt=.false.)
+call sub_scalar (scalar_real_alloc, .false.)
+call sub_scalar (scalar_char_ptr, .false.)
+call sub_scalar (null (), .false.)
+call sub_scalar (scalar_t2_alloc, .false.)
+call sub_scalar (scalar_t3_ptr, .false.)
+
+allocate (scalar_real_alloc, scalar_char_ptr, scalar_t3_ptr)
+allocate (scalar_class_t1_alloc, scalar_class_t1_ptr, scalar_t2_alloc)
+allocate (array_real_alloc(3:5,2:4), array_char_ptr(-2:2,2))
+allocate (array_t2_alloc(3:5,2:4), array_t3_ptr(-2:2,2))
+allocate (array_class_t1_alloc(3,3), array_class_t1_ptr(4,4))
+
+call sub_scalar (scalar_int, .true.)
+call sub_scalar (scalar_real_alloc, .true.)
+call sub_scalar (scalar_char_ptr, .true.)
+call sub_scalar (array_int(2), .true.)
+call sub_scalar (array_real_alloc(3,2), .true.)
+call sub_scalar (array_char_ptr(0,1), .true.)
+call sub_scalar (scalar_t1, .true.)
+call sub_scalar (scalar_t2_alloc, .true.)
+call sub_scalar (scalar_t3_ptr, .true.)
+call sub_scalar (array_t1(2), .true.)
+call sub_scalar (array_t2_alloc(3,2), .true.)
+call sub_scalar (array_t3_ptr(0,1), .true.)
+call sub_scalar (array_class_t1_alloc(2,1), .true.)
+call sub_scalar (array_class_t1_ptr(3,3), .true.)
+
+call sub_array_assumed (array_int)
+call sub_array_assumed (array_real_alloc)
+call sub_array_assumed (array_char_ptr)
+call sub_array_assumed (array_t1)
+call sub_array_assumed (array_t2_alloc)
+call sub_array_assumed (array_t3_ptr)
+call sub_array_assumed (array_class_t1_alloc)
+call sub_array_assumed (array_class_t1_ptr)
+
+deallocate (scalar_char_ptr, scalar_class_t1_ptr, array_char_ptr)
+deallocate (array_class_t1_ptr, array_t3_ptr)
+contains
+ subroutine sub(x)
+ integer :: x(:)
+ call sub_array_assumed (x)
+ end subroutine sub
+end
diff --git a/gcc/testsuite/gfortran.dg/no_range_check_1.f90 b/gcc/testsuite/gfortran.dg/no_range_check_1.f90
index d0bd242..7066e19 100644
--- a/gcc/testsuite/gfortran.dg/no_range_check_1.f90
+++ b/gcc/testsuite/gfortran.dg/no_range_check_1.f90
@@ -4,11 +4,8 @@
! This testcase arose from PR 31262
integer :: a
integer(kind=8) :: b
- a = -3
b = -huge(b) / 7
- a = a ** 73
b = 7894_8 * b - 78941_8
- if ((-3)**73 /= a) STOP 1
if (7894_8 * (-huge(b) / 7) - 78941_8 /= b) STOP 2
a = 1234789786453123
diff --git a/gcc/testsuite/gfortran.dg/open_errors_2.f90 b/gcc/testsuite/gfortran.dg/open_errors_2.f90
index 5b41834..72d63bb 100644
--- a/gcc/testsuite/gfortran.dg/open_errors_2.f90
+++ b/gcc/testsuite/gfortran.dg/open_errors_2.f90
@@ -1,6 +1,7 @@
! { dg-do run }
+! { dg-options "-std=f2008" }
! { dg-shouldfail "runtime error" }
-! { dg-output "At line 13.*File already opened" }
+! { dg-output "At line 14.*File already opened" }
! PR 65563 - this used to segfault for some versions.
variable_1 = 0
diff --git a/gcc/testsuite/gfortran.dg/open_errors_3.f90 b/gcc/testsuite/gfortran.dg/open_errors_3.f90
new file mode 100644
index 0000000..da94956
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/open_errors_3.f90
@@ -0,0 +1,11 @@
+! { dg-do run }
+! PR 90461 Open file on multiple units as of F2018
+program openmult
+ implicit none
+ character(len=*), parameter :: fname="pr90461.dat"
+ open(10, file=fname, form="unformatted")
+ open(11, file=fname, form="unformatted")
+ close(11)
+ close(10, status="delete")
+end program openmult
+! { dg-final { remote_file build delete "pr90461.dat" } }
diff --git a/gcc/testsuite/gfortran.dg/pr51991.f90 b/gcc/testsuite/gfortran.dg/pr51991.f90
new file mode 100644
index 0000000..30a18e2
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/pr51991.f90
@@ -0,0 +1,21 @@
+! { dg-do compile }
+! PR fortran/51991
+! Orginal code contributed by Sebastien Bardeau <bardeau at iram dot fr>
+module mymod
+ type :: mytyp
+ integer :: i
+ end type mytyp
+contains
+ subroutine mysub
+ implicit none
+ type(mytyp) :: a
+ integer :: i,j
+ i = a%i
+ !
+ ! Prior to patching gfortran, the following lined generated a syntax
+ ! error with the SAVE statement. Now, gfortran generates an error
+ ! that indicates 'j' is not a component of 'mytyp'.
+ !
+ j = a%j ! { dg-error "is not a member of the" }
+ end subroutine mysub
+end module mymod
diff --git a/gcc/testsuite/gfortran.dg/pr67884.f90 b/gcc/testsuite/gfortran.dg/pr67884.f90
new file mode 100644
index 0000000..d502642
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/pr67884.f90
@@ -0,0 +1,21 @@
+! { dg-do compile }
+! PR fortran/67884
+! Original code contribute by Gerhard Steinmetz
+program p
+ integer i
+ print *, [(f(i), i=1,3)]
+ print *, [(g(i), i=1,3)]
+ contains
+ function f(n) ! { dg-error "has a deferred type parameter" }
+ integer :: n
+ character(:) :: f
+ character(3) :: c = 'abc'
+ f = c(n:n)
+ end
+ function g(n) result(z) ! { dg-error "has a deferred type parameter" }
+ integer :: n
+ character(:) :: z
+ character(3) :: c = 'abc'
+ z = c(n:n)
+ end
+end program p
diff --git a/gcc/testsuite/gfortran.dg/pr68544.f90 b/gcc/testsuite/gfortran.dg/pr68544.f90
new file mode 100644
index 0000000..3b17e2a
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/pr68544.f90
@@ -0,0 +1,13 @@
+! { dg-do compile }
+! PF fortran/68544
+program p
+ real x
+ type t
+ end type
+ x = f(t) ! { dg-error "used as an actual argument" }
+end
+subroutine b
+ type t
+ end type
+ print *, shape(t) ! { dg-error "used as an actual argument" }
+end
diff --git a/gcc/testsuite/gfortran.dg/pr69398.f90 b/gcc/testsuite/gfortran.dg/pr69398.f90
new file mode 100644
index 0000000..6863746
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/pr69398.f90
@@ -0,0 +1,11 @@
+! { dg-do compile }
+! PR fortran/69398
+! Contributed by Gerhard Steinmetz
+program p
+ type t
+ end type
+ class(t), allocatable :: z(:)
+ target :: z(:) ! { dg-error "Duplicate DIMENSION attribute" }
+ allocate (z(2))
+end
+
diff --git a/gcc/testsuite/gfortran.dg/pr69499.f90 b/gcc/testsuite/gfortran.dg/pr69499.f90
new file mode 100644
index 0000000..169c6ce
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/pr69499.f90
@@ -0,0 +1,7 @@
+! { dg-do compile }
+! PR fortran/69499
+! Contributed by Gerhard Steinmetz.
+module m
+ class(*) :: z ! { dg-error "must be dummy, allocatable or pointer" }
+ select type (x => z) ! { dg-error "cannot appear in this scope" }
+end
diff --git a/gcc/testsuite/gfortran.dg/pr77632_1.f90 b/gcc/testsuite/gfortran.dg/pr77632_1.f90
new file mode 100644
index 0000000..13fed59
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/pr77632_1.f90
@@ -0,0 +1,7 @@
+! { dg-do run }
+program foo
+ implicit none
+ real, target :: a
+ real, pointer :: b => a
+ if (associated(b, a) .eqv. .false.) stop 1
+end program foo
diff --git a/gcc/testsuite/gfortran.dg/pr78290.f90 b/gcc/testsuite/gfortran.dg/pr78290.f90
new file mode 100644
index 0000000..fe0e319
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/pr78290.f90
@@ -0,0 +1,35 @@
+! { dg-do run }
+! PR 78290 - used to give an ICE (with VOLATILE) and wrong
+! code without it.
+! Original test case by Andy Bennet.
+PROGRAM main
+ IMPLICIT NONE
+ INTEGER,PARAMETER::KI=4
+
+ TYPE mytype
+ INTEGER(KIND=KI)::i=1_KI
+ END TYPE mytype
+
+ TYPE(mytype), DIMENSION(9),TARGET, SAVE::ta
+ INTEGER(KIND=KI),DIMENSION(3),TARGET, SAVE::ia = 3_KI
+ INTEGER(KIND=KI),DIMENSION(:),POINTER ::ia2 =>NULL()
+ INTEGER(KIND=KI),DIMENSION(:),POINTER ::ip =>NULL()
+ volatile::ip
+ ALLOCATE(ia2(5)); ia2=2_KI
+ ip=>ia
+ if (size(ip) /= 3) stop 1
+ CALL sub1(ip)
+ if (size(ip) /= 5) stop 2
+ if (any(ia /= [3,3,3])) stop 3
+ if (any (ip /= [2,2,2,2,2])) stop 4
+
+ ip=>ta%i
+
+CONTAINS
+
+ SUBROUTINE sub1(ipa)
+ INTEGER(KIND=KI),DIMENSION(:),POINTER::ipa
+ ipa => ia2
+ END SUBROUTINE sub1
+
+END PROGRAM main
diff --git a/gcc/testsuite/gfortran.dg/pr85687.f90 b/gcc/testsuite/gfortran.dg/pr85687.f90
index 03bc211..410b2b2 100644
--- a/gcc/testsuite/gfortran.dg/pr85687.f90
+++ b/gcc/testsuite/gfortran.dg/pr85687.f90
@@ -4,5 +4,5 @@
program p
type t
end type
- print *, rank(t) ! { dg-error "must be a data object" }
+ print *, rank(t) ! { dg-error "used as an actual argument" }
end
diff --git a/gcc/testsuite/gfortran.dg/pr86587.f90 b/gcc/testsuite/gfortran.dg/pr86587.f90
new file mode 100644
index 0000000..fb21335
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/pr86587.f90
@@ -0,0 +1,18 @@
+! { dg-do compile }
+! PR fortran/86587
+! Code contirubted by Valentin Clement <valentin.clement at env dot ethz dot ch>
+!
+module mod1
+ use iso_c_binding
+ type, bind(c), private :: mytype
+ integer(c_int) :: i1, i2
+ end type
+end module mod1
+
+module mod2
+ use iso_c_binding
+ private
+ type, bind(c) :: mytype
+ integer(c_int) :: i1, i2
+ end type
+end module mod2
diff --git a/gcc/testsuite/gfortran.dg/pr87907.f90 b/gcc/testsuite/gfortran.dg/pr87907.f90
new file mode 100644
index 0000000..0fe4e50
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/pr87907.f90
@@ -0,0 +1,23 @@
+! { dg-do compile }
+! PR fortran/pr87907
+! Original testcase contributed by Gerhard Stienmetz <gscfq at t-online dot de>
+module m
+ interface
+ module function g(x) result(z)
+ integer, intent(in) :: x
+ integer, allocatable :: z
+ end
+ end interface
+end
+
+submodule(m) m2
+ contains
+ subroutine g(x) ! { dg-error "mismatch in argument" }
+ end
+end
+
+program p
+ use m ! { dg-error "has a type" }
+ integer :: x = 3
+ call g(x) ! { dg-error "which is not consistent with" }
+end
diff --git a/gcc/testsuite/gfortran.dg/pr89344.f90 b/gcc/testsuite/gfortran.dg/pr89344.f90
new file mode 100644
index 0000000..8749071
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/pr89344.f90
@@ -0,0 +1,15 @@
+! { dg-do compile }
+program demo_setval
+ call setval(value)
+ write(*,*)'VALUE=',value
+ contains
+ subroutine setval(value)
+ class(*),intent(in) :: value
+ select type(value)
+ type is (integer)
+ value = 10 ! { dg-error "in variable definition context" }
+ type is (real)
+ value = 10.20 ! { dg-error "in variable definition context" }
+ end select
+ end subroutine setval
+end program demo_setval
diff --git a/gcc/testsuite/gfortran.dg/pr89646.f90 b/gcc/testsuite/gfortran.dg/pr89646.f90
new file mode 100644
index 0000000..c348020
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/pr89646.f90
@@ -0,0 +1,24 @@
+! { dg-do compile }
+! PR fortran/89646
+! Original testcase contributed by Ian Harvey <ian_harvey at bigpond dot com>
+!
+! This code use to give spurious warnings about aliasing.
+!
+module m
+ implicit none
+ type :: t
+ end type t
+ contains
+ ! To reproduce, both actual arguments must be TARGET,
+ ! both arguments must be of derived type.
+ subroutine s
+ type(t), target :: a(5)
+ type(t), target :: b(5)
+ call move(a, b)
+ end subroutine s
+ ! To reproduce, called procedure must be elemental.
+ elemental subroutine move(x, y)
+ type(t), intent(inout) :: x
+ type(t), intent(out) :: y
+ end subroutine move
+end module m
diff --git a/gcc/testsuite/gfortran.dg/pr90002.f90 b/gcc/testsuite/gfortran.dg/pr90002.f90
new file mode 100644
index 0000000..cb993a5
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/pr90002.f90
@@ -0,0 +1,6 @@
+! { dg-do compile }
+! { dg-options "-fcoarray=single" }
+! Contributed by Arseny Solokha <asolokha at gmx dot de>
+module pc
+ integer, dimension(1) :: zw[1:1,1:*]
+end module pc
diff --git a/gcc/testsuite/gfortran.dg/pr90385.f90 b/gcc/testsuite/gfortran.dg/pr90385.f90
new file mode 100644
index 0000000..5ce34aa
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/pr90385.f90
@@ -0,0 +1,6 @@
+! PR tree-optimization/90385
+! { dg-do compile }
+! { dg-require-effective-target pthread }
+! { dg-options "-O1 -ftree-parallelize-loops=2 -fno-tree-ccp -fno-tree-ch -fno-tree-copy-prop -fno-tree-forwprop -fno-tree-sink --param parloops-min-per-thread=5" }
+
+include 'array_constructor_47.f90'
diff --git a/gcc/testsuite/gfortran.dg/pr90988_1.f90 b/gcc/testsuite/gfortran.dg/pr90988_1.f90
new file mode 100644
index 0000000..f8b6f13
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/pr90988_1.f90
@@ -0,0 +1,14 @@
+! { dg-do compile }
+module mymod
+ type :: mytyp
+ integer :: i
+ end type mytyp
+contains
+ subroutine mysub
+ implicit none
+ type(mytyp) :: a
+ integer :: publici,publicj
+ publici = a%i
+ publicj = a%j ! { dg-error "is not a member" }
+ end subroutine mysub
+end module mymod
diff --git a/gcc/testsuite/gfortran.dg/pr90988_2.f90 b/gcc/testsuite/gfortran.dg/pr90988_2.f90
new file mode 100644
index 0000000..a684ea2
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/pr90988_2.f90
@@ -0,0 +1,14 @@
+! { dg-do compile }
+module mymod
+ type :: mytyp
+ integer :: i
+ end type mytyp
+contains
+ subroutine mysub
+ implicit none
+ type(mytyp) :: a
+ integer :: privatei,privatej
+ privatei = a%i
+ privatej = a%j ! { dg-error "is not a member" }
+ end subroutine mysub
+end module mymod
diff --git a/gcc/testsuite/gfortran.dg/pr90988_3.f90 b/gcc/testsuite/gfortran.dg/pr90988_3.f90
new file mode 100644
index 0000000..66ba06b
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/pr90988_3.f90
@@ -0,0 +1,14 @@
+! { dg-do compile }
+module mymod
+ type :: mytyp
+ integer :: i
+ end type mytyp
+contains
+ subroutine mysub
+ implicit none
+ type(mytyp) :: a
+ integer :: protectedi,protectedj
+ protectedi = a%i
+ protectedj = a%j ! { dg-error "is not a member" }
+ end subroutine mysub
+end module mymod
diff --git a/gcc/testsuite/gfortran.dg/proc_ptr_51.f90 b/gcc/testsuite/gfortran.dg/proc_ptr_51.f90
new file mode 100644
index 0000000..62b5d71
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/proc_ptr_51.f90
@@ -0,0 +1,38 @@
+! { dg-do run }
+!
+! Test the fix for PR90786.
+!
+! Contributed by Andrew benson <abensonca@gmail.com>
+!
+module f
+procedure(c), pointer :: c_
+
+ type :: s
+ integer :: i = 42
+ end type s
+ class(s), pointer :: res, tgt
+
+contains
+
+ function c()
+ implicit none
+ class(s), pointer :: c
+ c => tgt
+ return
+ end function c
+
+ subroutine fs()
+ implicit none
+ c_ => c ! This used to ICE
+ return
+ end subroutine fs
+
+end module f
+
+ use f
+ allocate (tgt, source = s(99))
+ call fs()
+ res => c_()
+ if (res%i .ne. 99) stop 1
+ deallocate (tgt)
+end
diff --git a/gcc/testsuite/gfortran.dg/shiftalr_3.f90 b/gcc/testsuite/gfortran.dg/shiftalr_3.f90
new file mode 100644
index 0000000..4eb0ba7
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/shiftalr_3.f90
@@ -0,0 +1,42 @@
+! { dg-do run }
+!
+! Test shift intrinsics when the SHIFT argument equals BIT_SIZE(arg1).
+
+program test
+ implicit none
+ ! Test compile-time simplifications
+ if (ishft (-1, 32) /= 0) stop 1 ! 0 -> simplify_shift OK
+ if (ishft (-1,-32) /= 0) stop 2 ! 0 -> simplify_shift OK
+ if (shiftl (-1, 32) /= 0) stop 3 ! 0 -> simplify_shift OK
+ if (shiftr (-1, 32) /= 0) stop 4 ! 0 -> simplify_shift OK
+ if (shifta (-1, 32) /= -1) stop 5 ! -1 -> simplify_shift OK
+ if (rshift (-1, 32) /= -1) stop 6 ! -1 -> simplify_shift OK
+ if (lshift (-1, 32) /= 0) stop 7 ! 0 -> simplify_shift OK
+ ! Test run-time
+ call foo (-1)
+contains
+ subroutine foo (n)
+ integer(4) :: i, j, k, n
+ integer, parameter :: bb = bit_size (n)
+ ! Test code generated by gfc_conv_intrinsic_ishft
+ i = ishft (n, bb) ! Logical (left) shift (Fortran 2008)
+ j = ishft (n,-bb) ! Logical (right) shift (Fortran 2008)
+ if (i /= 0) stop 11
+ if (j /= 0) stop 12
+ ! Test code generated by gfc_conv_intrinsic_shift:
+ i = shiftl (n, bb) ! Logical left shift (Fortran 2008)
+ j = shiftr (n, bb) ! Logical right shift (Fortran 2008)
+ k = shifta (n, bb) ! Arithmetic right shift (Fortran 2008)
+ if (i /= 0) stop 13
+ if (j /= 0) stop 14
+ if (k /= -1) stop 15
+ i = lshift (n, bb) ! Logical left shift (GNU extension)
+ j = rshift (n, bb) ! Arithmetic right shift (GNU extension)
+ if (i /= 0) stop 16
+ if (j /= -1) stop 17
+ do i = bb-1,bb
+ if (shifta (n, i) /= -1) stop 18
+ if (rshift (n, i) /= -1) stop 19
+ end do
+ end subroutine foo
+end program test
diff --git a/gcc/testsuite/gfortran.dg/transpose_optimization_2.f90 b/gcc/testsuite/gfortran.dg/transpose_optimization_2.f90
index 4748da1..c49cd42 100644
--- a/gcc/testsuite/gfortran.dg/transpose_optimization_2.f90
+++ b/gcc/testsuite/gfortran.dg/transpose_optimization_2.f90
@@ -61,4 +61,4 @@ end
! The check below for temporaries gave 14 and 33 for "parm" and "atmp".
!
! { dg-final { scan-tree-dump-times "parm" 72 "original" } }
-! { dg-final { scan-tree-dump-times "atmp" 12 "original" } }
+! { dg-final { scan-tree-dump-times "atmp" 13 "original" } }
diff --git a/gcc/testsuite/gfortran.dg/typebound_assignment_5.f03 b/gcc/testsuite/gfortran.dg/typebound_assignment_5.f03
index f176b84..e7c9126 100644
--- a/gcc/testsuite/gfortran.dg/typebound_assignment_5.f03
+++ b/gcc/testsuite/gfortran.dg/typebound_assignment_5.f03
@@ -1,5 +1,5 @@
-! { dg-do run }
-! { dg-options "-fdump-tree-original" }
+! { dg-do compile }
+! { dg-options "-O0 -fdump-tree-original" }
!
! PR fortran/49074
! ICE on defined assignment with class arrays.
diff --git a/gcc/testsuite/gfortran.dg/typebound_assignment_5a.f03 b/gcc/testsuite/gfortran.dg/typebound_assignment_5a.f03
new file mode 100644
index 0000000..b55b42b
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/typebound_assignment_5a.f03
@@ -0,0 +1,39 @@
+! { dg-do run }
+!
+! PR fortran/49074
+! ICE on defined assignment with class arrays.
+
+ module foo
+ type bar
+ integer :: i
+
+ contains
+
+ generic :: assignment (=) => assgn_bar
+ procedure, private :: assgn_bar
+ end type bar
+
+ contains
+
+ elemental subroutine assgn_bar (a, b)
+ class (bar), intent (inout) :: a
+ class (bar), intent (in) :: b
+
+ select type (b)
+ type is (bar)
+ a%i = b%i
+ end select
+
+ return
+ end subroutine assgn_bar
+ end module foo
+
+ program main
+ use foo
+
+ type (bar), allocatable :: foobar(:)
+
+ allocate (foobar(2))
+ foobar = [bar(1), bar(2)]
+ if (any(foobar%i /= [1, 2])) STOP 1
+ end program
diff --git a/gcc/testsuite/gfortran.dg/typebound_assignment_6.f03 b/gcc/testsuite/gfortran.dg/typebound_assignment_6.f03
index 1dbdb0c..40cd2d0 100644
--- a/gcc/testsuite/gfortran.dg/typebound_assignment_6.f03
+++ b/gcc/testsuite/gfortran.dg/typebound_assignment_6.f03
@@ -1,5 +1,4 @@
! { dg-do run }
-! { dg-options "-fdump-tree-original" }
!
! PR fortran/56136
! ICE on defined assignment with class arrays.
@@ -37,6 +36,3 @@
IF (ANY(A(2::2)%I /= (/ ((50+2*I, I=1,SIZE(A)/4), J=1,2) /))) STOP 3
END PROGRAM
-! { dg-final { scan-tree-dump-times "_gfortran_internal_pack" 1 "original" } }
-! { dg-final { scan-tree-dump-times "_gfortran_internal_unpack" 1 "original" } }
-
diff --git a/gcc/testsuite/gfortran.dg/typebound_assignment_6a.f03 b/gcc/testsuite/gfortran.dg/typebound_assignment_6a.f03
new file mode 100644
index 0000000..2dab4c7
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/typebound_assignment_6a.f03
@@ -0,0 +1,42 @@
+! { dg-do compile }
+! { dg-options "-O0 -fdump-tree-original" }
+!
+! PR fortran/56136
+! ICE on defined assignment with class arrays.
+!
+! Original testcase by Alipasha <alipash.celeris@gmail.com>
+
+ MODULE A_TEST_M
+ TYPE :: A_TYPE
+ INTEGER :: I
+ CONTAINS
+ GENERIC :: ASSIGNMENT (=) => ASGN_A
+ PROCEDURE, PRIVATE :: ASGN_A
+ END TYPE
+
+ CONTAINS
+
+ ELEMENTAL SUBROUTINE ASGN_A (A, B)
+ CLASS (A_TYPE), INTENT (INOUT) :: A
+ CLASS (A_TYPE), INTENT (IN) :: B
+ A%I = B%I
+ END SUBROUTINE
+ END MODULE A_TEST_M
+
+ PROGRAM ASGN_REALLOC_TEST
+ USE A_TEST_M
+ TYPE (A_TYPE), ALLOCATABLE :: A(:)
+ INTEGER :: I, J
+
+ ALLOCATE (A(100))
+ A = (/ (A_TYPE(I), I=1,SIZE(A)) /)
+ A(1:50) = A(51:100)
+ IF (ANY(A%I /= (/ ((50+I, I=1,SIZE(A)/2), J=1,2) /))) STOP 1
+ A(::2) = A(1:50) ! pack/unpack
+ IF (ANY(A( ::2)%I /= (/ (50+I, I=1,SIZE(A)/2) /))) STOP 2
+ IF (ANY(A(2::2)%I /= (/ ((50+2*I, I=1,SIZE(A)/4), J=1,2) /))) STOP 3
+ END PROGRAM
+
+! { dg-final { scan-tree-dump-times "_gfortran_internal_pack" 1 "original" } }
+! { dg-final { scan-tree-dump-times "_gfortran_internal_unpack" 1 "original" } }
+
diff --git a/gcc/testsuite/gfortran.dg/vect/pr45714-b.f b/gcc/testsuite/gfortran.dg/vect/pr45714-b.f
index 0d00c6f..abf33cd 100644
--- a/gcc/testsuite/gfortran.dg/vect/pr45714-b.f
+++ b/gcc/testsuite/gfortran.dg/vect/pr45714-b.f
@@ -1,5 +1,5 @@
! { dg-do compile { target powerpc*-*-* } }
-! { dg-additional-options "-O3 -mcpu=power7 -ffast-math -mveclibabi=mass" }
+! { dg-additional-options "-O3 -mcpu=power7 -mno-power9-vector -mno-power8-vector -ffast-math -mveclibabi=mass" }
integer index(18),i,j,k,l,ipiv(18),info,ichange,neq,lda,ldb,
& nrhs,iplas
diff --git a/gcc/testsuite/gfortran.dg/vect/pr90681.f b/gcc/testsuite/gfortran.dg/vect/pr90681.f
new file mode 100644
index 0000000..03d3987
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/vect/pr90681.f
@@ -0,0 +1,13 @@
+C { dg-do compile }
+C { dg-additional-options "-march=armv8.2-a+sve" { target { aarch64*-*-* } } }
+ SUBROUTINE HMU (H1)
+ COMMON DD(107)
+ DIMENSION H1(NORBS,*)
+ DO 70 J1 = IA,I1
+ H1(I1,J1) = 0
+ JO1 = J1
+ IF (JO1.EQ.1) THEN
+ H1(I1,J1) = DD(NI)
+ END IF
+ 70 CONTINUE
+ END
diff --git a/gcc/testsuite/gfortran.dg/vect/pr90913.f90 b/gcc/testsuite/gfortran.dg/vect/pr90913.f90
new file mode 100644
index 0000000..d0f2251
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/vect/pr90913.f90
@@ -0,0 +1,22 @@
+! { dg-do compile }
+! { dg-options "-O3 -ffast-math" }
+! { dg-additional-options "-mavx -mveclibabi=svml" { target i?86-*-* x86_64-*-* } }
+subroutine foo (a, b, c, d, e, f, g, h, k, l)
+ implicit none
+ integer :: d, e, f, g, i, j
+ real :: a, b(5,6), c(6), h(6,10,5), k(5,10,2), l(10,5), m, n, o
+ do i=1,5
+ do j=1,6
+ m=l(f,g)*log(c(j))
+ if (m<2) then
+ if (m<-2) then
+ h(j,f,g)=n
+ else
+ h(j,f,g)=o
+ endif
+ endif
+ b(i,j)=a+k(i,d,e)+k(i,1,e)**h(j,f,g)
+ enddo
+ enddo
+ write(*,'()')
+end
diff --git a/gcc/testsuite/gfortran.dg/vect/vect-5.f90 b/gcc/testsuite/gfortran.dg/vect/vect-5.f90
index de283e8..b11caba 100644
--- a/gcc/testsuite/gfortran.dg/vect/vect-5.f90
+++ b/gcc/testsuite/gfortran.dg/vect/vect-5.f90
@@ -1,5 +1,5 @@
! { dg-require-effective-target vect_int }
-! { dg-additional-options "--param vect-max-peeling-for-alignment=0" }
+! { dg-additional-options "-fno-tree-loop-distribute-patterns --param vect-max-peeling-for-alignment=0" }
Subroutine foo (N, M)
Integer N
diff --git a/gcc/testsuite/gfortran.dg/vect/vect-8.f90 b/gcc/testsuite/gfortran.dg/vect/vect-8.f90
index 0ac5f1c..e26cdf9 100644
--- a/gcc/testsuite/gfortran.dg/vect/vect-8.f90
+++ b/gcc/testsuite/gfortran.dg/vect/vect-8.f90
@@ -1,6 +1,6 @@
! { dg-do compile }
! { dg-require-effective-target vect_double }
-! { dg-additional-options "-finline-matmul-limit=0" }
+! { dg-additional-options "-fno-tree-loop-distribute-patterns -finline-matmul-limit=0" }
module lfk_prec
integer, parameter :: dp=kind(1.d0)
diff --git a/gcc/testsuite/gnat.dg/aliased2.adb b/gcc/testsuite/gnat.dg/aliased2.adb
new file mode 100644
index 0000000..0e1adac
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/aliased2.adb
@@ -0,0 +1,23 @@
+-- { dg-do run }
+
+procedure Aliased2 is
+
+ type Rec is record
+ Data : access constant String;
+ end record;
+
+ function Get (S : aliased String) return Rec is
+ R : Rec := (Data => S'Unchecked_Access);
+ begin
+ return R;
+ end;
+
+ S : aliased String := "Hello";
+
+ R : Rec := Get (S);
+
+begin
+ if R.Data'Length /= S'Length then
+ raise Program_Error;
+ end if;
+end;
diff --git a/gcc/testsuite/gnat.dg/alignment14.adb b/gcc/testsuite/gnat.dg/alignment14.adb
new file mode 100644
index 0000000..48ef6bd
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/alignment14.adb
@@ -0,0 +1,17 @@
+-- { dg-do compile }
+
+procedure Alignment14 is
+
+ type My_Int1 is new Integer;
+ for My_Int1'Alignment use 8;
+
+ type Arr1 is array (1 .. 2) of My_Int1;
+
+ type My_Int2 is new Integer;
+ for My_Int2'Alignment use 16;
+
+ type Arr2 is array (1 .. 2) of My_Int2;
+
+begin
+ null;
+end Alignment14;
diff --git a/gcc/testsuite/gnat.dg/array35.adb b/gcc/testsuite/gnat.dg/array35.adb
new file mode 100644
index 0000000..1c0f998
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/array35.adb
@@ -0,0 +1,24 @@
+-- { dg-do run }
+
+procedure Array35 is
+
+ subtype Str is String (1 .. 3);
+
+ type T is record
+ B : Boolean;
+ S : Str;
+ end record;
+
+ for T use record
+ B at 0 range 0 .. 0;
+ S at 0 range 1 .. 24;
+ end record;
+
+ X : T := (B => True, S => "123");
+
+begin
+ X.B := False;
+ if X.S /= "123" then
+ raise Program_Error;
+ end if;
+end;
diff --git a/gcc/testsuite/gnat.dg/array36.adb b/gcc/testsuite/gnat.dg/array36.adb
new file mode 100644
index 0000000..9f4314c
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/array36.adb
@@ -0,0 +1,28 @@
+-- { dg-do run }
+
+procedure Array36 is
+
+ subtype Str is String (1 .. 3);
+
+ type Rec is record
+ S : Str;
+ end record;
+
+ type T is record
+ B : Boolean;
+ R : Rec;
+ end record;
+
+ for T use record
+ B at 0 range 0 .. 0;
+ R at 0 range 1 .. 24;
+ end record;
+
+ X : T := (B => True, R => (S => "123"));
+
+begin
+ X.B := False;
+ if X.R.S /= "123" then
+ raise Program_Error;
+ end if;
+end;
diff --git a/gcc/testsuite/gnat.dg/derived_type6.adb b/gcc/testsuite/gnat.dg/derived_type6.adb
new file mode 100644
index 0000000..8369d62
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/derived_type6.adb
@@ -0,0 +1,5 @@
+-- { dg-do compile }
+
+package body Derived_Type6 is
+ procedure Foo is null;
+end Derived_Type6;
diff --git a/gcc/testsuite/gnat.dg/derived_type6.ads b/gcc/testsuite/gnat.dg/derived_type6.ads
new file mode 100644
index 0000000..37728a9
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/derived_type6.ads
@@ -0,0 +1,9 @@
+with Ada.Strings.Bounded;
+
+package Derived_Type6 is
+ package b is new Ada.Strings.Bounded.Generic_Bounded_Length(10);
+ subtype s1 is b.Bounded_String;
+ type s2 is new s1;
+
+ procedure Foo;
+end Derived_Type6;
diff --git a/gcc/testsuite/gnat.dg/dynhash.adb b/gcc/testsuite/gnat.dg/dynhash.adb
index c51e6e2..8b229c4 100644
--- a/gcc/testsuite/gnat.dg/dynhash.adb
+++ b/gcc/testsuite/gnat.dg/dynhash.adb
@@ -5,9 +5,10 @@ with GNAT; use GNAT;
with GNAT.Dynamic_HTables; use GNAT.Dynamic_HTables;
procedure Dynhash is
+ procedure Destroy (Val : in out Integer) is null;
function Hash (Key : Integer) return Bucket_Range_Type;
- package DHT is new Dynamic_HTable
+ package DHT is new Dynamic_Hash_Tables
(Key_Type => Integer,
Value_Type => Integer,
No_Value => 0,
@@ -16,20 +17,21 @@ procedure Dynhash is
Compression_Threshold => 0.3,
Compression_Factor => 2,
"=" => "=",
+ Destroy_Value => Destroy,
Hash => Hash);
use DHT;
function Create_And_Populate
(Low_Key : Integer;
High_Key : Integer;
- Init_Size : Positive) return Instance;
+ Init_Size : Positive) return Dynamic_Hash_Table;
-- Create a hash table with initial size Init_Size and populate it with
-- key-value pairs where both keys and values are in the range Low_Key
-- .. High_Key.
procedure Check_Empty
(Caller : String;
- T : Instance;
+ T : Dynamic_Hash_Table;
Low_Key : Integer;
High_Key : Integer);
-- Ensure that
@@ -45,12 +47,14 @@ procedure Dynhash is
-- Ensure that iterator Iter visits every key in the range Low_Key ..
-- High_Key exactly once.
- procedure Check_Locked_Mutations (Caller : String; T : in out Instance);
+ procedure Check_Locked_Mutations
+ (Caller : String;
+ T : in out Dynamic_Hash_Table);
-- Ensure that all mutation operations of hash table T are locked
procedure Check_Size
(Caller : String;
- T : Instance;
+ T : Dynamic_Hash_Table;
Exp_Count : Natural);
-- Ensure that the count of key-value pairs of hash table T matches
-- expected count Exp_Count. Emit an error if this is not the case.
@@ -134,9 +138,9 @@ procedure Dynhash is
function Create_And_Populate
(Low_Key : Integer;
High_Key : Integer;
- Init_Size : Positive) return Instance
+ Init_Size : Positive) return Dynamic_Hash_Table
is
- T : Instance;
+ T : Dynamic_Hash_Table;
begin
T := Create (Init_Size);
@@ -154,7 +158,7 @@ procedure Dynhash is
procedure Check_Empty
(Caller : String;
- T : Instance;
+ T : Dynamic_Hash_Table;
Low_Key : Integer;
High_Key : Integer)
is
@@ -227,7 +231,10 @@ procedure Dynhash is
-- Check_Locked_Mutations --
----------------------------
- procedure Check_Locked_Mutations (Caller : String; T : in out Instance) is
+ procedure Check_Locked_Mutations
+ (Caller : String;
+ T : in out Dynamic_Hash_Table)
+ is
begin
begin
Delete (T, 1);
@@ -276,7 +283,7 @@ procedure Dynhash is
procedure Check_Size
(Caller : String;
- T : Instance;
+ T : Dynamic_Hash_Table;
Exp_Count : Natural)
is
Count : constant Natural := Size (T);
@@ -305,7 +312,7 @@ procedure Dynhash is
procedure Test_Create (Init_Size : Positive) is
Count : Natural;
Iter : Iterator;
- T : Instance;
+ T : Dynamic_Hash_Table;
Val : Integer;
begin
@@ -402,7 +409,7 @@ procedure Dynhash is
Init_Size : Positive)
is
Exp_Val : Integer;
- T : Instance;
+ T : Dynamic_Hash_Table;
Val : Integer;
begin
@@ -483,7 +490,7 @@ procedure Dynhash is
is
Iter_1 : Iterator;
Iter_2 : Iterator;
- T : Instance;
+ T : Dynamic_Hash_Table;
begin
T := Create_And_Populate (Low_Key, High_Key, Init_Size);
@@ -552,7 +559,7 @@ procedure Dynhash is
procedure Test_Iterate_Empty (Init_Size : Positive) is
Iter : Iterator;
Key : Integer;
- T : Instance;
+ T : Dynamic_Hash_Table;
begin
T := Create_And_Populate (0, -1, Init_Size);
@@ -599,7 +606,7 @@ procedure Dynhash is
is
Iter : Iterator;
Key : Integer;
- T : Instance;
+ T : Dynamic_Hash_Table;
begin
T := Create_And_Populate (Low_Key, High_Key, Init_Size);
@@ -653,7 +660,7 @@ procedure Dynhash is
Init_Size : Positive)
is
Key : constant Integer := 1;
- T : Instance;
+ T : Dynamic_Hash_Table;
Val : Integer;
begin
@@ -687,7 +694,7 @@ procedure Dynhash is
High_Key : Integer;
Init_Size : Positive)
is
- T : Instance;
+ T : Dynamic_Hash_Table;
begin
T := Create_And_Populate (Low_Key, High_Key, Init_Size);
diff --git a/gcc/testsuite/gnat.dg/dynhash1.adb b/gcc/testsuite/gnat.dg/dynhash1.adb
index cbe241a..e2010de 100644
--- a/gcc/testsuite/gnat.dg/dynhash1.adb
+++ b/gcc/testsuite/gnat.dg/dynhash1.adb
@@ -1,14 +1,17 @@
+-- { dg-do run }
+
with Ada.Text_IO; use Ada.Text_IO;
with GNAT; use GNAT;
with GNAT.Dynamic_HTables; use GNAT.Dynamic_HTables;
procedure Dynhash1 is
+ procedure Destroy (Val : in out Integer) is null;
function Hash (Key : Integer) return Bucket_Range_Type is
begin
return Bucket_Range_Type (Key);
end Hash;
- package Integer_Hash_Tables is new Dynamic_HTable
+ package Integer_Hash_Tables is new Dynamic_Hash_Tables
(Key_Type => Integer,
Value_Type => Integer,
No_Value => 0,
@@ -17,11 +20,12 @@ procedure Dynhash1 is
Compression_Threshold => 0.3,
Compression_Factor => 2,
"=" => "=",
+ Destroy_Value => Destroy,
Hash => Hash);
use Integer_Hash_Tables;
Siz : Natural;
- T : Instance;
+ T : Dynamic_Hash_Table;
begin
T := Create (8);
diff --git a/gcc/testsuite/gnat.dg/enum_rep.adb b/gcc/testsuite/gnat.dg/enum_rep.adb
new file mode 100644
index 0000000..4b13078
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/enum_rep.adb
@@ -0,0 +1,5 @@
+-- { dg-do compile }
+
+package body Enum_Rep is
+ procedure Foo is null;
+end;
diff --git a/gcc/testsuite/gnat.dg/enum_rep.ads b/gcc/testsuite/gnat.dg/enum_rep.ads
new file mode 100644
index 0000000..acf282c
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/enum_rep.ads
@@ -0,0 +1,22 @@
+with Interfaces;
+
+package Enum_Rep is
+
+ type My_Type is range 00 .. 100;
+
+ subtype My_Subtype2 is Interfaces.Unsigned_32
+ range My_Type'First'Enum_Rep .. My_Type'Last'Enum_Rep;
+
+ My_Type_First : constant My_Type := My_Type'First;
+ My_Type_Last : constant My_Type := My_Type'Last;
+
+ subtype My_Subtype is Interfaces.Unsigned_32
+ range My_Type_First'Enum_Rep .. My_Type_Last'Enum_Rep;
+
+ subtype My_Subtype1 is Interfaces.Unsigned_32
+ range My_Type'Enum_Rep (My_Type'First) ..
+ My_Type'Enum_Rep (MY_Type'Last);
+
+ procedure Foo;
+
+end;
diff --git a/gcc/testsuite/gnat.dg/expect2.adb b/gcc/testsuite/gnat.dg/expect2.adb
new file mode 100644
index 0000000..fb50bd8c
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/expect2.adb
@@ -0,0 +1,24 @@
+-- { dg-do compile }
+
+with Text_IO; use Text_IO;
+with Expect2_Pkg; use Expect2_Pkg;
+
+procedure Expect2 is
+begin
+ if Unlikely (I = 0) then
+ Put_Line ("Zero was passed");
+ return;
+ end if;
+
+ if Likely (I > 0) then
+ Put_Line ("A positive number was passed");
+ else
+ Put_Line ("A negative number was passed");
+ end if;
+
+ if Expect ((I rem 2) = 0, False) then
+ Put_Line ("An even number was passed");
+ else
+ Put_Line ("An odd number was passed");
+ end if;
+end;
diff --git a/gcc/testsuite/gnat.dg/expect2_pkg.ads b/gcc/testsuite/gnat.dg/expect2_pkg.ads
new file mode 100644
index 0000000..7cb0dd3
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/expect2_pkg.ads
@@ -0,0 +1,15 @@
+package Expect2_Pkg is
+
+ I : Integer;
+ pragma Volatile (I);
+
+ function Expect (Condition : Boolean; Outcome : Boolean) return Boolean;
+ pragma Import (Intrinsic, Expect, "__builtin_expect");
+
+ function Likely (Condition : Boolean) return Boolean;
+ pragma Import (Intrinsic, Likely, "__builtin_likely");
+
+ function Unlikely (Condition : Boolean) return Boolean;
+ pragma Import (Intrinsic, Unlikely, "__builtin_unlikely");
+
+end Expect2_Pkg;
diff --git a/gcc/testsuite/gnat.dg/freezing1.adb b/gcc/testsuite/gnat.dg/freezing1.adb
new file mode 100644
index 0000000..87d8246
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/freezing1.adb
@@ -0,0 +1,5 @@
+-- { dg-do compile }
+
+package body Freezing1 is
+ procedure Foo is null;
+end Freezing1;
diff --git a/gcc/testsuite/gnat.dg/freezing1.ads b/gcc/testsuite/gnat.dg/freezing1.ads
new file mode 100644
index 0000000..f81bc78
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/freezing1.ads
@@ -0,0 +1,10 @@
+with Freezing1_Pack; use Freezing1_Pack;
+
+package Freezing1 is
+ type T is abstract tagged record
+ Collection : access I_Interface_Collection'Class :=
+ new I_Interface_Collection'Class'(Factory.Create_Collection);
+ end record;
+
+ procedure Foo;
+end Freezing1;
diff --git a/gcc/testsuite/gnat.dg/freezing1_pack.adb b/gcc/testsuite/gnat.dg/freezing1_pack.adb
new file mode 100644
index 0000000..11172af
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/freezing1_pack.adb
@@ -0,0 +1,8 @@
+package body Freezing1_Pack is
+ function Create_Collection
+ (Factory : in T_Factory) return I_Interface_Collection'Class
+ is
+ begin
+ return Implem'(null record);
+ end Create_Collection;
+end Freezing1_Pack;
diff --git a/gcc/testsuite/gnat.dg/freezing1_pack.ads b/gcc/testsuite/gnat.dg/freezing1_pack.ads
new file mode 100644
index 0000000..74d88b8
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/freezing1_pack.ads
@@ -0,0 +1,16 @@
+package Freezing1_Pack is
+ type T_Factory is abstract tagged private;
+ type I_Interface_Collection is interface;
+
+ Factory : constant T_Factory;
+
+ function Create_Collection
+ (Factory : in T_Factory) return I_Interface_Collection'Class;
+
+ type Implem is new I_Interface_Collection with null record;
+
+private
+ type T_Factory is tagged null record;
+
+ Factory : constant T_Factory := T_Factory'(null record);
+end Freezing1_Pack;
diff --git a/gcc/testsuite/gnat.dg/generic_inst3.adb b/gcc/testsuite/gnat.dg/generic_inst3.adb
new file mode 100644
index 0000000..545d72e
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/generic_inst3.adb
@@ -0,0 +1,20 @@
+-- { dg-do compile }
+
+with Generic_Inst3_Kafka_Lib.Topic;
+with Generic_Inst3_Traits.Encodables;
+with Generic_Inst3_Markets;
+
+procedure Generic_Inst3 is
+ generic
+ with package Values is new Generic_Inst3_Traits.Encodables (<>);
+ with package Topic is new Generic_Inst3_Kafka_Lib.Topic
+ (Values => Values, others => <>);
+ package Dummy is
+ end Dummy;
+
+ package Inst is new Dummy
+ (Values => Generic_Inst3_Markets.Data_Encodables,
+ Topic => Generic_Inst3_Markets.Data_Topic);
+begin
+ null;
+end Generic_Inst3;
diff --git a/gcc/testsuite/gnat.dg/generic_inst3_kafka_lib-topic.ads b/gcc/testsuite/gnat.dg/generic_inst3_kafka_lib-topic.ads
new file mode 100644
index 0000000..b0ff8ff
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/generic_inst3_kafka_lib-topic.ads
@@ -0,0 +1,7 @@
+with Generic_Inst3_Traits.Encodables;
+generic
+ Topic_Name : String;
+ with package Keys is new Generic_Inst3_Traits.Encodables (<>);
+ with package Values is new Generic_Inst3_Traits.Encodables (<>);
+package Generic_Inst3_Kafka_Lib.Topic is
+end Generic_Inst3_Kafka_Lib.Topic;
diff --git a/gcc/testsuite/gnat.dg/generic_inst3_kafka_lib.ads b/gcc/testsuite/gnat.dg/generic_inst3_kafka_lib.ads
new file mode 100644
index 0000000..2fbaee9
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/generic_inst3_kafka_lib.ads
@@ -0,0 +1,2 @@
+package Generic_Inst3_Kafka_Lib is
+end Generic_Inst3_Kafka_Lib;
diff --git a/gcc/testsuite/gnat.dg/generic_inst3_markets.ads b/gcc/testsuite/gnat.dg/generic_inst3_markets.ads
new file mode 100644
index 0000000..9add3ab
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/generic_inst3_markets.ads
@@ -0,0 +1,10 @@
+with Generic_Inst3_Kafka_Lib.Topic;
+with Generic_Inst3_Traits.Encodables;
+package Generic_Inst3_Markets is
+ type Data_Type is null record;
+ function Image (D : Data_Type) return String is ("");
+ package Data_Encodables is new Generic_Inst3_Traits.Encodables (Data_Type, Image);
+ package Data_Topic is new Generic_Inst3_Kafka_Lib.Topic
+ (Keys => Data_Encodables, Values => Data_Encodables,
+ Topic_Name => "bla");
+end Generic_Inst3_Markets;
diff --git a/gcc/testsuite/gnat.dg/generic_inst3_traits-encodables.ads b/gcc/testsuite/gnat.dg/generic_inst3_traits-encodables.ads
new file mode 100644
index 0000000..3e8814e
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/generic_inst3_traits-encodables.ads
@@ -0,0 +1,8 @@
+with Ada.Streams;
+generic
+ pragma Warnings (Off, "is not referenced");
+ type T (<>) is private;
+ with function Image (Val : in T) return String;
+package Generic_Inst3_Traits.Encodables is
+ pragma Pure;
+end Generic_Inst3_Traits.Encodables;
diff --git a/gcc/testsuite/gnat.dg/generic_inst3_traits.ads b/gcc/testsuite/gnat.dg/generic_inst3_traits.ads
new file mode 100644
index 0000000..aeb2cd1
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/generic_inst3_traits.ads
@@ -0,0 +1,3 @@
+package Generic_Inst3_Traits is
+ pragma Pure;
+end Generic_Inst3_Traits;
diff --git a/gcc/testsuite/gnat.dg/inline15.adb b/gcc/testsuite/gnat.dg/inline15.adb
new file mode 100644
index 0000000..953e72e
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/inline15.adb
@@ -0,0 +1,11 @@
+-- { dg-do compile }
+-- { dg-options "-O2" }
+
+with Inline15_Gen;
+
+procedure Inline15 is
+ package Inst is new Inline15_Gen;
+
+begin
+ Inst.Call_Func;
+end Inline15;
diff --git a/gcc/testsuite/gnat.dg/inline15_gen.adb b/gcc/testsuite/gnat.dg/inline15_gen.adb
new file mode 100644
index 0000000..f2b17f8
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/inline15_gen.adb
@@ -0,0 +1,27 @@
+package body Inline15_Gen is
+ function Initialize (Val : Inline15_Types.Enum) return Inline15_Types.Rec;
+ procedure Print (Val : Inline15_Types.Rec);
+
+ procedure Call_Func is
+ Result : constant Inline15_Types.Rec := Func (Inline15_Types.Two);
+ begin
+ null;
+ end Call_Func;
+
+ function Func (Val : Inline15_Types.Enum) return Inline15_Types.Rec is
+ begin
+ return Result : constant Inline15_Types.Rec := Initialize (Val) do
+ Print (Result);
+ end return;
+ end Func;
+
+ function Initialize (Val : Inline15_Types.Enum) return Inline15_Types.Rec is
+ pragma Warnings (Off);
+ Result : Inline15_Types.Rec (Val);
+ pragma Warnings (On);
+ begin
+ return Result;
+ end Initialize;
+
+ procedure Print (Val : Inline15_Types.Rec) is begin null; end Print;
+end Inline15_Gen;
diff --git a/gcc/testsuite/gnat.dg/inline15_gen.ads b/gcc/testsuite/gnat.dg/inline15_gen.ads
new file mode 100644
index 0000000..42856e8
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/inline15_gen.ads
@@ -0,0 +1,11 @@
+
+-- gen.ads
+
+with Inline15_Types;
+
+generic
+package Inline15_Gen is
+ function Func (Val : Inline15_Types.Enum) return Inline15_Types.Rec with Inline;
+
+ procedure Call_Func with Inline;
+end Inline15_Gen;
diff --git a/gcc/testsuite/gnat.dg/inline15_types.ads b/gcc/testsuite/gnat.dg/inline15_types.ads
new file mode 100644
index 0000000..5aaa2d6
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/inline15_types.ads
@@ -0,0 +1,17 @@
+package Inline15_Types is
+ type Enum is (One, Two, Three, Four);
+
+ type Rec (Discr : Enum) is record
+ Comp_1 : Integer;
+
+ case Discr is
+ when One =>
+ Comp_2 : Float;
+ when Two =>
+ Comp_3 : Boolean;
+ Comp_4 : Long_Float;
+ when others =>
+ null;
+ end case;
+ end record;
+end Inline15_Types;
diff --git a/gcc/testsuite/gnat.dg/inline16.adb b/gcc/testsuite/gnat.dg/inline16.adb
new file mode 100644
index 0000000..ebe8482
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/inline16.adb
@@ -0,0 +1,26 @@
+-- { dg-do compile }
+-- { dg-options "-gnatN" }
+
+with Inline16_Types; use Inline16_Types;
+with Inline16_Gen;
+
+procedure Inline16 is
+ type TYPE1 is record
+ f1 : NvU32;
+ f2 : NvU32;
+ f3 : NvU32;
+ end record
+ with Size => 96, Object_Size => 96;
+
+ package Gfw_Image_Read_Pkg1 is new Inline16_Gen (Payload_Type => TYPE1);
+ use Gfw_Image_Read_Pkg1;
+ procedure Get_Boot_Block_Info(Status : out Integer)
+ is
+ Ifr_Fixed_Min : TYPE1;
+ begin
+ Gfw_Image_Read(Ifr_Fixed_Min);
+ Status := 13;
+ end Get_Boot_Block_Info;
+begin
+ null;
+end Inline16;
diff --git a/gcc/testsuite/gnat.dg/inline16_gen.adb b/gcc/testsuite/gnat.dg/inline16_gen.adb
new file mode 100644
index 0000000..bd5b749
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/inline16_gen.adb
@@ -0,0 +1,16 @@
+with Inline16_Types; use Inline16_Types;
+
+package body Inline16_Gen
+with SPARK_Mode => On
+is
+ procedure Gfw_Image_Read (Data : out Payload_Type)
+ with SPARK_Mode => Off
+ is
+ Array_Len : constant NvU32 := Data'Size / NvU8'Size;
+ Array_Max_Idx : constant NvU32 := Array_Len - 1;
+ type Payload_As_Arr_Type is new Arr_NvU8_Idx32(0 .. Array_Max_Idx);
+ Data_As_Array : Payload_As_Arr_Type with Address => Data'Address;
+ begin
+ null;
+ end Gfw_Image_Read;
+end Inline16_Gen;
diff --git a/gcc/testsuite/gnat.dg/inline16_gen.ads b/gcc/testsuite/gnat.dg/inline16_gen.ads
new file mode 100644
index 0000000..90f1f58
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/inline16_gen.ads
@@ -0,0 +1,9 @@
+generic
+ type Payload_Type is private;
+package Inline16_Gen
+with SPARK_Mode => On
+is
+ procedure Gfw_Image_Read(Data : out Payload_Type)
+ with Inline_Always;
+
+end Inline16_Gen;
diff --git a/gcc/testsuite/gnat.dg/inline16_types.ads b/gcc/testsuite/gnat.dg/inline16_types.ads
new file mode 100644
index 0000000..dfaf640
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/inline16_types.ads
@@ -0,0 +1,7 @@
+package Inline16_Types with SPARK_Mode is
+
+ type NvU8 is mod 2 ** 8 with Size => 8;
+ type NvU32 is mod 2 ** 32 with Size => 32;
+
+ type Arr_NvU8_Idx32 is array (NvU32 range <>) of NvU8;
+end Inline16_Types;
diff --git a/gcc/testsuite/gnat.dg/inline3.adb b/gcc/testsuite/gnat.dg/inline3.adb
index b0ba513..9eae469 100644
--- a/gcc/testsuite/gnat.dg/inline3.adb
+++ b/gcc/testsuite/gnat.dg/inline3.adb
@@ -1,5 +1,5 @@
-- { dg-do compile }
--- { dg-error "not marked Inline_Always" "" { target *-*-* } 0 }
+-- { dg-error "not marked 'Inline_Always'" "" { target *-*-* } 0 }
-- { dg-error "cannot be inlined" "" { target *-*-* } 0 }
with Inline3_Pkg; use Inline3_Pkg;
diff --git a/gcc/testsuite/gnat.dg/inline5.adb b/gcc/testsuite/gnat.dg/inline5.adb
index 45803fa..5d9bed7 100644
--- a/gcc/testsuite/gnat.dg/inline5.adb
+++ b/gcc/testsuite/gnat.dg/inline5.adb
@@ -1,6 +1,6 @@
-- { dg-do compile }
-- { dg-options "-O -gnatn -Winline" }
--- { dg-warning "not marked Inline" "" { target *-*-* } 0 }
+-- { dg-warning "not marked 'Inline'" "" { target *-*-* } 0 }
-- { dg-warning "cannot be inlined" "" { target *-*-* } 0 }
with Inline5_Pkg; use Inline5_Pkg;
diff --git a/gcc/testsuite/gnat.dg/inline7.adb b/gcc/testsuite/gnat.dg/inline7.adb
index 2c2a46a..390d627 100644
--- a/gcc/testsuite/gnat.dg/inline7.adb
+++ b/gcc/testsuite/gnat.dg/inline7.adb
@@ -1,6 +1,6 @@
-- { dg-do compile }
-- { dg-options "-O -gnatn -Winline" }
--- { dg-warning "not marked Inline" "" { target *-*-* } 0 }
+-- { dg-warning "not marked 'Inline'" "" { target *-*-* } 0 }
-- { dg-warning "cannot be inlined" "" { target *-*-* } 0 }
with Inline7_Pkg1; use Inline7_Pkg1;
diff --git a/gcc/testsuite/gnat.dg/inline9.adb b/gcc/testsuite/gnat.dg/inline9.adb
index d64e134..3ab23c6 100644
--- a/gcc/testsuite/gnat.dg/inline9.adb
+++ b/gcc/testsuite/gnat.dg/inline9.adb
@@ -1,6 +1,6 @@
-- { dg-do compile }
-- { dg-options "-O -gnatn -Winline" }
--- { dg-warning "not marked Inline" "" { target *-*-* } 0 }
+-- { dg-warning "not marked 'Inline'" "" { target *-*-* } 0 }
-- { dg-warning "cannot be inlined" "" { target *-*-* } 0 }
with Inline9_Pkg; use Inline9_Pkg;
diff --git a/gcc/testsuite/gnat.dg/limited_with7.adb b/gcc/testsuite/gnat.dg/limited_with7.adb
new file mode 100644
index 0000000..13e35fe
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/limited_with7.adb
@@ -0,0 +1,12 @@
+-- { dg-do compile }
+
+with Limited_With7_Pkg; use Limited_With7_Pkg;
+
+package body Limited_With7 is
+
+ procedure Proc (R : out Limited_With7_Pkg.Rec) is
+ begin
+ R.I := 0;
+ end;
+
+end Limited_With7;
diff --git a/gcc/testsuite/gnat.dg/limited_with7.ads b/gcc/testsuite/gnat.dg/limited_with7.ads
new file mode 100644
index 0000000..2a2f86c
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/limited_with7.ads
@@ -0,0 +1,7 @@
+limited with Limited_With7_Pkg;
+
+package Limited_With7 is
+
+ procedure Proc (R : out Limited_With7_Pkg.Rec);
+
+end Limited_With7;
diff --git a/gcc/testsuite/gnat.dg/limited_with7_pkg.ads b/gcc/testsuite/gnat.dg/limited_with7_pkg.ads
new file mode 100644
index 0000000..7806eaa
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/limited_with7_pkg.ads
@@ -0,0 +1,9 @@
+package Limited_With7_Pkg is
+
+ type Rec;
+
+ type Rec is record
+ I : Integer;
+ end record;
+
+end Limited_With7_Pkg;
diff --git a/gcc/testsuite/gnat.dg/linkedlist.adb b/gcc/testsuite/gnat.dg/linkedlist.adb
index b608fe1..34df2ed 100644
--- a/gcc/testsuite/gnat.dg/linkedlist.adb
+++ b/gcc/testsuite/gnat.dg/linkedlist.adb
@@ -5,35 +5,42 @@ with GNAT; use GNAT;
with GNAT.Lists; use GNAT.Lists;
procedure Linkedlist is
- package Integer_Lists is new Doubly_Linked_List
- (Element_Type => Integer,
- "=" => "=");
+ procedure Destroy (Val : in out Integer) is null;
+
+ package Integer_Lists is new Doubly_Linked_Lists
+ (Element_Type => Integer,
+ "=" => "=",
+ Destroy_Element => Destroy);
use Integer_Lists;
procedure Check_Empty
(Caller : String;
- L : Instance;
+ L : Doubly_Linked_List;
Low_Elem : Integer;
High_Elem : Integer);
-- Ensure that none of the elements in the range Low_Elem .. High_Elem are
-- present in list L, and that the list's length is 0.
- procedure Check_Locked_Mutations (Caller : String; L : in out Instance);
+ procedure Check_Locked_Mutations
+ (Caller : String;
+ L : in out Doubly_Linked_List);
-- Ensure that all mutation operations of list L are locked
procedure Check_Present
(Caller : String;
- L : Instance;
+ L : Doubly_Linked_List;
Low_Elem : Integer;
High_Elem : Integer);
-- Ensure that all elements in the range Low_Elem .. High_Elem are present
-- in list L.
- procedure Check_Unlocked_Mutations (Caller : String; L : in out Instance);
+ procedure Check_Unlocked_Mutations
+ (Caller : String;
+ L : in out Doubly_Linked_List);
-- Ensure that all mutation operations of list L are unlocked
procedure Populate_With_Append
- (L : Instance;
+ (L : Doubly_Linked_List;
Low_Elem : Integer;
High_Elem : Integer);
-- Add elements in the range Low_Elem .. High_Elem in that order in list L
@@ -113,7 +120,7 @@ procedure Linkedlist is
procedure Check_Empty
(Caller : String;
- L : Instance;
+ L : Doubly_Linked_List;
Low_Elem : Integer;
High_Elem : Integer)
is
@@ -137,7 +144,9 @@ procedure Linkedlist is
-- Check_Locked_Mutations --
----------------------------
- procedure Check_Locked_Mutations (Caller : String; L : in out Instance) is
+ procedure Check_Locked_Mutations
+ (Caller : String;
+ L : in out Doubly_Linked_List) is
begin
begin
Append (L, 1);
@@ -247,7 +256,7 @@ procedure Linkedlist is
procedure Check_Present
(Caller : String;
- L : Instance;
+ L : Doubly_Linked_List;
Low_Elem : Integer;
High_Elem : Integer)
is
@@ -287,7 +296,10 @@ procedure Linkedlist is
-- Check_Unlocked_Mutations --
------------------------------
- procedure Check_Unlocked_Mutations (Caller : String; L : in out Instance) is
+ procedure Check_Unlocked_Mutations
+ (Caller : String;
+ L : in out Doubly_Linked_List)
+ is
begin
Append (L, 1);
Append (L, 2);
@@ -306,7 +318,7 @@ procedure Linkedlist is
--------------------------
procedure Populate_With_Append
- (L : Instance;
+ (L : Doubly_Linked_List;
Low_Elem : Integer;
High_Elem : Integer)
is
@@ -321,7 +333,7 @@ procedure Linkedlist is
-----------------
procedure Test_Append is
- L : Instance := Create;
+ L : Doubly_Linked_List := Create;
begin
Append (L, 1);
@@ -350,7 +362,7 @@ procedure Linkedlist is
Low_Bogus : constant Integer := Low_Elem - 1;
High_Bogus : constant Integer := High_Elem + 1;
- L : Instance := Create;
+ L : Doubly_Linked_List := Create;
begin
Populate_With_Append (L, Low_Elem, High_Elem);
@@ -388,7 +400,7 @@ procedure Linkedlist is
Count : Natural;
Flag : Boolean;
Iter : Iterator;
- L : Instance;
+ L : Doubly_Linked_List;
Val : Integer;
begin
@@ -548,7 +560,7 @@ procedure Linkedlist is
High_Elem : Integer)
is
Iter : Iterator;
- L : Instance := Create;
+ L : Doubly_Linked_List := Create;
begin
Populate_With_Append (L, Low_Elem, High_Elem);
@@ -635,7 +647,7 @@ procedure Linkedlist is
(Low_Elem : Integer;
High_Elem : Integer)
is
- L : Instance := Create;
+ L : Doubly_Linked_List := Create;
begin
Populate_With_Append (L, Low_Elem, High_Elem);
@@ -684,7 +696,7 @@ procedure Linkedlist is
(Low_Elem : Integer;
High_Elem : Integer)
is
- L : Instance := Create;
+ L : Doubly_Linked_List := Create;
begin
Populate_With_Append (L, Low_Elem, High_Elem);
@@ -731,7 +743,7 @@ procedure Linkedlist is
procedure Test_First is
Elem : Integer;
- L : Instance := Create;
+ L : Doubly_Linked_List := Create;
begin
-- Try to obtain the head. This operation should raise List_Empty.
@@ -766,7 +778,7 @@ procedure Linkedlist is
-----------------------
procedure Test_Insert_After is
- L : Instance := Create;
+ L : Doubly_Linked_List := Create;
begin
-- Try to insert after a non-inserted element, in an empty list
@@ -805,7 +817,7 @@ procedure Linkedlist is
------------------------
procedure Test_Insert_Before is
- L : Instance := Create;
+ L : Doubly_Linked_List := Create;
begin
-- Try to insert before a non-inserted element, in an empty list
@@ -844,7 +856,7 @@ procedure Linkedlist is
-------------------
procedure Test_Is_Empty is
- L : Instance := Create;
+ L : Doubly_Linked_List := Create;
begin
if not Is_Empty (L) then
@@ -874,7 +886,7 @@ procedure Linkedlist is
Elem : Integer;
Iter_1 : Iterator;
Iter_2 : Iterator;
- L : Instance := Create;
+ L : Doubly_Linked_List := Create;
begin
Populate_With_Append (L, 1, 5);
@@ -935,7 +947,7 @@ procedure Linkedlist is
procedure Test_Iterate_Empty is
Elem : Integer;
Iter : Iterator;
- L : Instance := Create;
+ L : Doubly_Linked_List := Create;
begin
-- Obtain an iterator. This action must lock all mutation operations of
@@ -978,7 +990,7 @@ procedure Linkedlist is
is
Elem : Integer;
Iter : Iterator;
- L : Instance := Create;
+ L : Doubly_Linked_List := Create;
begin
Populate_With_Append (L, Low_Elem, High_Elem);
@@ -1026,7 +1038,7 @@ procedure Linkedlist is
procedure Test_Last is
Elem : Integer;
- L : Instance := Create;
+ L : Doubly_Linked_List := Create;
begin
-- Try to obtain the tail. This operation should raise List_Empty.
@@ -1061,7 +1073,7 @@ procedure Linkedlist is
------------------
procedure Test_Prepend is
- L : Instance := Create;
+ L : Doubly_Linked_List := Create;
begin
Prepend (L, 5);
@@ -1084,7 +1096,7 @@ procedure Linkedlist is
------------------
procedure Test_Replace is
- L : Instance := Create;
+ L : Doubly_Linked_List := Create;
begin
Populate_With_Append (L, 1, 5);
@@ -1111,7 +1123,7 @@ procedure Linkedlist is
---------------
procedure Test_Size is
- L : Instance := Create;
+ L : Doubly_Linked_List := Create;
S : Natural;
begin
diff --git a/gcc/testsuite/gnat.dg/machine_attr1.adb b/gcc/testsuite/gnat.dg/machine_attr1.adb
new file mode 100644
index 0000000..f4e4ff7
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/machine_attr1.adb
@@ -0,0 +1,41 @@
+-- { dg-do compile { target i?86-*-linux* x86_64-*-linux* } }
+-- { dg-options "-O3 -gnatp" }
+
+package body Machine_Attr1 is
+
+ procedure Proc1 is
+ begin
+ Proc3;
+ Proc4;
+ end;
+
+ procedure Proc2 is
+ begin
+ Proc1;
+ end;
+
+ procedure Proc3 is
+ begin
+ A (1) := 0;
+ end;
+
+ procedure Proc4 is
+ begin
+ A (2) := 0;
+ end;
+
+ procedure Proc5 is
+ begin
+ for I in A'Range loop
+ A(I) := B(I) + C(I);
+ end loop;
+ end;
+
+ procedure Proc6 is
+ begin
+ for I in A'Range loop
+ A(I) := B(I) + C(I);
+ end loop;
+ end;
+
+end Machine_Attr1;
diff --git a/gcc/testsuite/gnat.dg/machine_attr1.ads b/gcc/testsuite/gnat.dg/machine_attr1.ads
new file mode 100644
index 0000000..d1f2aec
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/machine_attr1.ads
@@ -0,0 +1,25 @@
+package Machine_Attr1 is
+
+ type Arr is array (1 .. 256) of Integer;
+
+ A, B, C : Arr;
+
+ procedure Proc1;
+ pragma Machine_Attribute (Proc1, "flatten");
+
+ procedure Proc2;
+ pragma Machine_Attribute (Proc2, "used");
+
+ procedure Proc3;
+ pragma Machine_Attribute (Proc3, "cold");
+
+ procedure Proc4;
+ pragma Machine_Attribute (Proc4, "hot");
+
+ procedure Proc5;
+ pragma Machine_Attribute (Proc5, "target", "avx");
+
+ procedure Proc6;
+ pragma Machine_Attribute (Proc6, "target_clones", "avx", "avx2", "default");
+
+end Machine_Attr1;
diff --git a/gcc/testsuite/gnat.dg/opt39.adb b/gcc/testsuite/gnat.dg/opt39.adb
index 3b12cf2..0a5ef67 100644
--- a/gcc/testsuite/gnat.dg/opt39.adb
+++ b/gcc/testsuite/gnat.dg/opt39.adb
@@ -27,4 +27,5 @@ begin
end if;
end;
--- { dg-final { scan-tree-dump-times "MEM" 1 "optimized" } }
+-- { dg-final { scan-tree-dump-not "MEM" "optimized" } }
+-- { dg-final { scan-tree-dump-not "tmp" "optimized" } }
diff --git a/gcc/testsuite/gnat.dg/opt78.adb b/gcc/testsuite/gnat.dg/opt78.adb
new file mode 100644
index 0000000..e46c92b
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/opt78.adb
@@ -0,0 +1,16 @@
+-- { dg-do compile }
+-- { dg-options "-O" }
+
+package body Opt78 is
+
+ procedure Proc (P : UC; Msg : String) is
+ Default : UC := (1, "!");
+ begin
+ if P = Default then
+ raise Program_Error;
+ else
+ raise Constraint_Error;
+ end if;
+ end;
+
+end Opt78;
diff --git a/gcc/testsuite/gnat.dg/opt78.ads b/gcc/testsuite/gnat.dg/opt78.ads
new file mode 100644
index 0000000..2c489bd
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/opt78.ads
@@ -0,0 +1,13 @@
+package Opt78 is
+
+ subtype Reasonable is Integer range 1..10;
+
+ type UC (D: Reasonable := 2) is record
+ S: String (1 .. D) := "Hi";
+ end record;
+
+ type AUC is access all UC;
+
+ procedure Proc (P : UC; Msg : String);
+
+end Opt78;
diff --git a/gcc/testsuite/gnat.dg/opt79.adb b/gcc/testsuite/gnat.dg/opt79.adb
new file mode 100644
index 0000000..f58e25b
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/opt79.adb
@@ -0,0 +1,28 @@
+-- { dg-do compile }
+-- { dg-options "-O" }
+
+package body Opt79 is
+
+ function F (I : Integer) return Arr is
+ A : Arr;
+
+ procedure Nested is
+
+ procedure Inner is
+ begin
+ A (1) := 0;
+ end;
+
+ begin
+ Inner;
+ end;
+
+ begin
+ Nested;
+ for J in A'Range loop
+ A (J) := I;
+ end loop;
+ return A;
+ end;
+
+end Opt79;
diff --git a/gcc/testsuite/gnat.dg/opt79.ads b/gcc/testsuite/gnat.dg/opt79.ads
new file mode 100644
index 0000000..aa90c17
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/opt79.ads
@@ -0,0 +1,7 @@
+package Opt79 is
+
+ type Arr is array (1 .. 8) of Integer;
+
+ function F (I : Integer) return Arr;
+
+end Opt79;
diff --git a/gcc/testsuite/gnat.dg/predicate4.adb b/gcc/testsuite/gnat.dg/predicate4.adb
new file mode 100644
index 0000000..ce4ddf8
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/predicate4.adb
@@ -0,0 +1,19 @@
+-- { dg-do compile }
+-- { dg-options "-gnata" }
+
+with System.Assertions; use System.Assertions;
+with Predicate4_Pkg;
+procedure Predicate4 is
+ type V is new Float;
+ package MXI2 is new Predicate4_Pkg (V);
+ use MXI2;
+ OK : Lt := (Has => False);
+begin
+ declare
+ Wrong : Lt := (Has => True, MX => 3.14);
+ begin
+ raise Program_Error;
+ end;
+exception
+ when Assert_Failure => null;
+end;
diff --git a/gcc/testsuite/gnat.dg/predicate4_pkg.ads b/gcc/testsuite/gnat.dg/predicate4_pkg.ads
new file mode 100644
index 0000000..1b2e62d
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/predicate4_pkg.ads
@@ -0,0 +1,16 @@
+generic
+ type Value_Type is private;
+package Predicate4_Pkg is
+ type MT (Has : Boolean := False) is record
+ case Has is
+ when False =>
+ null;
+ when True =>
+ MX : Value_Type;
+ end case;
+ end record;
+
+ function Foo (M : MT) return Boolean is (not M.Has);
+ subtype LT is MT with Dynamic_Predicate => not LT.Has;
+ function Bar (M : MT) return Boolean is (Foo (M));
+end;
diff --git a/gcc/testsuite/gnat.dg/predicate5.adb b/gcc/testsuite/gnat.dg/predicate5.adb
new file mode 100644
index 0000000..01acf64
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/predicate5.adb
@@ -0,0 +1,5 @@
+-- { dg-do compile }
+
+package body Predicate5 is
+ procedure Foo is null;
+end Predicate5;
diff --git a/gcc/testsuite/gnat.dg/predicate5.ads b/gcc/testsuite/gnat.dg/predicate5.ads
new file mode 100644
index 0000000..4e8f9b9
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/predicate5.ads
@@ -0,0 +1,17 @@
+generic
+ type Value_Type is private;
+package Predicate5 is
+ type MT (Has : Boolean := False) is record
+ case Has is
+ when False =>
+ null;
+ when True =>
+ MX : Value_Type;
+ end case;
+ end record;
+ function Foo (M : MT) return Boolean is (not M.Has);
+ subtype LT is MT with Dynamic_Predicate => not LT.Has;
+ function Bar (M : MT) return Boolean is (Foo (M));
+
+ procedure Foo;
+end;
diff --git a/gcc/testsuite/gnat.dg/predicate6.adb b/gcc/testsuite/gnat.dg/predicate6.adb
new file mode 100644
index 0000000..f098569
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/predicate6.adb
@@ -0,0 +1,5 @@
+-- { dg-do compile }
+
+package body Predicate6 is
+ procedure Foo is null;
+end Predicate6;
diff --git a/gcc/testsuite/gnat.dg/predicate6.ads b/gcc/testsuite/gnat.dg/predicate6.ads
new file mode 100644
index 0000000..91e0adc
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/predicate6.ads
@@ -0,0 +1,10 @@
+generic
+package Predicate6 is
+ type Price_Kind is (Infinitely_Small, Normal, Infinitely_Large);
+ subtype Infinite_Kind is Price_Kind with Static_Predicate =>
+ Infinite_Kind in Infinitely_Small | Infinitely_Large;
+ function "not" (Kind : Infinite_Kind) return Infinite_Kind is
+ (case Kind is when Infinitely_Small => Infinitely_Large,
+ when Infinitely_Large => Infinitely_Small);
+ procedure Foo;
+end;
diff --git a/gcc/testsuite/gnat.dg/prefetch1.adb b/gcc/testsuite/gnat.dg/prefetch1.adb
new file mode 100644
index 0000000..2233da4
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/prefetch1.adb
@@ -0,0 +1,29 @@
+-- { dg-do compile }
+
+package body Prefetch1 is
+
+ procedure Prefetch_1 (Addr : System.Address);
+ pragma Import (Intrinsic, Prefetch_1, "__builtin_prefetch");
+
+ procedure Prefetch_2 (Addr : System.Address; RW : Integer);
+ pragma Import (Intrinsic, Prefetch_2, "__builtin_prefetch");
+
+ procedure Prefetch_3 (Addr : System.Address; RW : Integer; Locality : Integer);
+ pragma Import (Intrinsic, Prefetch_3, "__builtin_prefetch");
+
+ procedure My_Proc1 (Addr : System.Address) is
+ begin
+ Prefetch_1 (Addr);
+ end;
+
+ procedure My_Proc2 (Addr : System.Address) is
+ begin
+ Prefetch_2 (Addr, 1);
+ end;
+
+ procedure My_Proc3 (Addr : System.Address) is
+ begin
+ Prefetch_3 (Addr, 1, 1);
+ end;
+
+end Prefetch1;
diff --git a/gcc/testsuite/gnat.dg/prefetch1.ads b/gcc/testsuite/gnat.dg/prefetch1.ads
new file mode 100644
index 0000000..fdb655a
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/prefetch1.ads
@@ -0,0 +1,9 @@
+with System;
+
+package Prefetch1 is
+
+ procedure My_Proc1 (Addr : System.Address);
+ procedure My_Proc2 (Addr : System.Address);
+ procedure My_Proc3 (Addr : System.Address);
+
+end Prefetch1;
diff --git a/gcc/testsuite/gnat.dg/prot7.adb b/gcc/testsuite/gnat.dg/prot7.adb
new file mode 100644
index 0000000..6051ef0
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/prot7.adb
@@ -0,0 +1,22 @@
+-- { dg-do compile }
+-- { dg-options "-gnatwa -gnatVa" }
+
+package body Prot7 is
+ protected body Default_Slice is
+ function Get return Instance_Pointer is
+ begin
+ return Default;
+ end Get;
+
+ procedure Set (
+ Discard : in out Boolean;
+ Slice : in Instance_Pointer
+ ) is
+ begin
+ Discard := Default /= null;
+ if not Discard then
+ Default := Slice;
+ end if;
+ end Set;
+ end Default_Slice;
+end Prot7;
diff --git a/gcc/testsuite/gnat.dg/prot7.ads b/gcc/testsuite/gnat.dg/prot7.ads
new file mode 100644
index 0000000..5e06e26
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/prot7.ads
@@ -0,0 +1,16 @@
+package Prot7 is
+ type Instance_Pointer is access Integer;
+
+ protected Default_Slice
+ with Lock_Free
+ is
+ function Get return Instance_Pointer;
+
+ procedure Set (
+ Discard : in out Boolean;
+ Slice : in Instance_Pointer
+ );
+ private
+ Default : Instance_Pointer;
+ end Default_Slice;
+end Prot7;
diff --git a/gcc/testsuite/gnat.dg/renaming13.adb b/gcc/testsuite/gnat.dg/renaming13.adb
new file mode 100644
index 0000000..434a71e
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/renaming13.adb
@@ -0,0 +1,21 @@
+-- { dg-do run }
+
+procedure Renaming13 is
+ type Stack_Type_Base is array (Natural range <>) of Integer;
+
+ procedure Foo (Buf : in out Stack_Type_Base) is
+ S : Stack_Type_Base renames Buf;
+
+ procedure Init is
+ begin
+ S := (others => 0);
+ end;
+
+ begin
+ Init;
+ end;
+
+ Temp : Stack_Type_Base (1 .. 100);
+begin
+ Foo (Temp);
+end;
diff --git a/gcc/testsuite/gnat.dg/renaming14.adb b/gcc/testsuite/gnat.dg/renaming14.adb
new file mode 100644
index 0000000..d61a82d
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/renaming14.adb
@@ -0,0 +1,32 @@
+-- { dg-do run }
+
+procedure Renaming14 is
+ type Rec_Typ is record
+ XX : Integer;
+ end record;
+
+ type Stack_Type_Base is array (Natural range <>) of Rec_Typ;
+
+ generic
+ S : in out Stack_Type_Base;
+ package Stack is
+ procedure Init;
+ end;
+
+ package body Stack is
+ procedure Init is
+ begin
+ S := (others => (XX => 0));
+ end;
+ end;
+
+ procedure Foo (Buf : in out Stack_Type_Base) is
+ package Stack_Inst is new Stack (Buf);
+ begin
+ Stack_Inst.Init;
+ end;
+
+ Temp : Stack_Type_Base (1 .. 100);
+begin
+ Foo (Temp);
+end;
diff --git a/gcc/testsuite/gnat.dg/sets1.adb b/gcc/testsuite/gnat.dg/sets1.adb
index 54a4983..42bad38 100644
--- a/gcc/testsuite/gnat.dg/sets1.adb
+++ b/gcc/testsuite/gnat.dg/sets1.adb
@@ -7,7 +7,7 @@ with GNAT.Sets; use GNAT.Sets;
procedure Sets1 is
function Hash (Key : Integer) return Bucket_Range_Type;
- package Integer_Sets is new Membership_Set
+ package Integer_Sets is new Membership_Sets
(Element_Type => Integer,
"=" => "=",
Hash => Hash);
@@ -15,28 +15,32 @@ procedure Sets1 is
procedure Check_Empty
(Caller : String;
- S : Instance;
+ S : Membership_Set;
Low_Elem : Integer;
High_Elem : Integer);
-- Ensure that none of the elements in the range Low_Elem .. High_Elem are
-- present in set S, and that the set's length is 0.
- procedure Check_Locked_Mutations (Caller : String; S : in out Instance);
+ procedure Check_Locked_Mutations
+ (Caller : String;
+ S : in out Membership_Set);
-- Ensure that all mutation operations of set S are locked
procedure Check_Present
(Caller : String;
- S : Instance;
+ S : Membership_Set;
Low_Elem : Integer;
High_Elem : Integer);
-- Ensure that all elements in the range Low_Elem .. High_Elem are present
-- in set S.
- procedure Check_Unlocked_Mutations (Caller : String; S : in out Instance);
+ procedure Check_Unlocked_Mutations
+ (Caller : String;
+ S : in out Membership_Set);
-- Ensure that all mutation operations of set S are unlocked
procedure Populate
- (S : Instance;
+ (S : Membership_Set;
Low_Elem : Integer;
High_Elem : Integer);
-- Add elements in the range Low_Elem .. High_Elem in set S
@@ -86,7 +90,7 @@ procedure Sets1 is
procedure Check_Empty
(Caller : String;
- S : Instance;
+ S : Membership_Set;
Low_Elem : Integer;
High_Elem : Integer)
is
@@ -110,7 +114,10 @@ procedure Sets1 is
-- Check_Locked_Mutations --
----------------------------
- procedure Check_Locked_Mutations (Caller : String; S : in out Instance) is
+ procedure Check_Locked_Mutations
+ (Caller : String;
+ S : in out Membership_Set)
+ is
begin
begin
Delete (S, 1);
@@ -149,7 +156,7 @@ procedure Sets1 is
procedure Check_Present
(Caller : String;
- S : Instance;
+ S : Membership_Set;
Low_Elem : Integer;
High_Elem : Integer)
is
@@ -189,7 +196,10 @@ procedure Sets1 is
-- Check_Unlocked_Mutations --
------------------------------
- procedure Check_Unlocked_Mutations (Caller : String; S : in out Instance) is
+ procedure Check_Unlocked_Mutations
+ (Caller : String;
+ S : in out Membership_Set)
+ is
begin
Delete (S, 1);
Insert (S, 1);
@@ -209,7 +219,7 @@ procedure Sets1 is
--------------
procedure Populate
- (S : Instance;
+ (S : Membership_Set;
Low_Elem : Integer;
High_Elem : Integer)
is
@@ -231,7 +241,7 @@ procedure Sets1 is
Low_Bogus : constant Integer := Low_Elem - 1;
High_Bogus : constant Integer := High_Elem + 1;
- S : Instance := Create (Init_Size);
+ S : Membership_Set := Create (Init_Size);
begin
Populate (S, Low_Elem, High_Elem);
@@ -269,7 +279,7 @@ procedure Sets1 is
Count : Natural;
Flag : Boolean;
Iter : Iterator;
- S : Instance;
+ S : Membership_Set;
begin
-- Ensure that every routine defined in the API fails on a set which
@@ -346,7 +356,7 @@ procedure Sets1 is
Init_Size : Positive)
is
Iter : Iterator;
- S : Instance := Create (Init_Size);
+ S : Membership_Set := Create (Init_Size);
begin
Populate (S, Low_Elem, High_Elem);
@@ -391,7 +401,7 @@ procedure Sets1 is
-------------------
procedure Test_Is_Empty is
- S : Instance := Create (8);
+ S : Membership_Set := Create (8);
begin
if not Is_Empty (S) then
@@ -421,7 +431,7 @@ procedure Sets1 is
Elem : Integer;
Iter_1 : Iterator;
Iter_2 : Iterator;
- S : Instance := Create (5);
+ S : Membership_Set := Create (5);
begin
Populate (S, 1, 5);
@@ -482,7 +492,7 @@ procedure Sets1 is
procedure Test_Iterate_Empty is
Elem : Integer;
Iter : Iterator;
- S : Instance := Create (5);
+ S : Membership_Set := Create (5);
begin
-- Obtain an iterator. This action must lock all mutation operations of
@@ -526,7 +536,7 @@ procedure Sets1 is
is
Elem : Integer;
Iter : Iterator;
- S : Instance := Create (Init_Size);
+ S : Membership_Set := Create (Init_Size);
begin
Populate (S, Low_Elem, High_Elem);
@@ -573,7 +583,7 @@ procedure Sets1 is
---------------
procedure Test_Size is
- S : Instance := Create (6);
+ S : Membership_Set := Create (6);
Siz : Natural;
begin
diff --git a/gcc/testsuite/gnat.dg/specs/array4.ads b/gcc/testsuite/gnat.dg/specs/array4.ads
new file mode 100644
index 0000000..ab12c1e
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/specs/array4.ads
@@ -0,0 +1,17 @@
+-- { dg-do compile }
+-- { dg-skip-if "missing -gsplit-dwarf support" { *-*-darwin* } }
+-- { dg-options "-gsplit-dwarf" }
+
+package Array4 is
+
+ type Arr1 is array (Positive range <>) of Boolean;
+
+ Size : Positive := 20;
+
+ type Rec is record
+ A : Arr1 (1 .. Size);
+ end record;
+
+ type Arr2 is array (Positive range <>) of Rec;
+
+end Array4;
diff --git a/gcc/testsuite/gnat.dg/specs/array5.ads b/gcc/testsuite/gnat.dg/specs/array5.ads
new file mode 100644
index 0000000..b0c2d2b
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/specs/array5.ads
@@ -0,0 +1,9 @@
+-- { dg-do compile }
+
+with Array5_Pkg1; use Array5_Pkg1;
+
+package Array5 is
+
+ C : constant Integer := Arr'Last;
+
+end Array5;
diff --git a/gcc/testsuite/gnat.dg/specs/array5_pkg1.ads b/gcc/testsuite/gnat.dg/specs/array5_pkg1.ads
new file mode 100644
index 0000000..885d6a4
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/specs/array5_pkg1.ads
@@ -0,0 +1,14 @@
+with Array5_Pkg2; use Array5_Pkg2;
+with Array5_Pkg2.G;
+
+package Array5_Pkg1 is
+
+ type Derived is new Root with record
+ N : Integer;
+ end record;
+
+ package My_G is new Array5_Pkg2.G (Derived);
+
+ type Arr is array (1 .. My_G.Data.N) of Integer;
+
+end Array5_Pkg1;
diff --git a/gcc/testsuite/gnat.dg/specs/array5_pkg2-g.ads b/gcc/testsuite/gnat.dg/specs/array5_pkg2-g.ads
new file mode 100644
index 0000000..1bb9396
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/specs/array5_pkg2-g.ads
@@ -0,0 +1,13 @@
+with System.Address_To_Access_Conversions;
+
+generic
+
+ type T is new Root with private;
+
+package Array5_Pkg2.G is
+
+ package Ptr is new System.Address_To_Access_Conversions (T);
+
+ Data : Ptr.Object_Pointer;
+
+end Array5_Pkg2.G;
diff --git a/gcc/testsuite/gnat.dg/specs/array5_pkg2.ads b/gcc/testsuite/gnat.dg/specs/array5_pkg2.ads
new file mode 100644
index 0000000..6c83460
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/specs/array5_pkg2.ads
@@ -0,0 +1,5 @@
+package Array5_Pkg2 is
+
+ type Root is tagged null record;
+
+end Array5_Pkg2;
diff --git a/gcc/testsuite/gnat.dg/specs/atomic2.ads b/gcc/testsuite/gnat.dg/specs/atomic2.ads
index b332884..17b9f83 100644
--- a/gcc/testsuite/gnat.dg/specs/atomic2.ads
+++ b/gcc/testsuite/gnat.dg/specs/atomic2.ads
@@ -9,7 +9,7 @@ package Atomic2 is
end record;
for Rec1 use record
C at 0 range 0 .. 7;
- I at 1 range 0 .. 31; -- { dg-error "position of atomic field" }
+ I at 1 range 0 .. 31; -- { dg-error "position for atomic|alignment" }
end record;
type Rec2 is record
diff --git a/gcc/testsuite/gnat.dg/specs/clause_on_volatile.ads b/gcc/testsuite/gnat.dg/specs/clause_on_volatile.ads
index f4c0b98..0dcffbc 100644
--- a/gcc/testsuite/gnat.dg/specs/clause_on_volatile.ads
+++ b/gcc/testsuite/gnat.dg/specs/clause_on_volatile.ads
@@ -39,7 +39,7 @@ package Clause_On_Volatile is
For A2'Alignment use 4;
for A2 use record
B at 0 range 0 .. 7;
- AW at 1 range 0 .. 31; -- { dg-error "must be multiple" }
+ AW at 1 range 0 .. 31; -- { dg-error "must be multiple|alignment" }
end record;
type A3 is record
@@ -49,7 +49,7 @@ package Clause_On_Volatile is
For A3'Alignment use 4;
for A3 use record
B at 0 range 0 .. 7;
- AW at 1 range 0 .. 15; -- { dg-error "must be (multiple||\[0-9\]*)" }
+ AW at 1 range 0 .. 15; -- { dg-error "must be (multiple||\[0-9\]*)|alignment" }
end record;
type V1 is record
diff --git a/gcc/testsuite/gnat.dg/specs/debug1.ads b/gcc/testsuite/gnat.dg/specs/debug1.ads
new file mode 100644
index 0000000..f94b42a
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/specs/debug1.ads
@@ -0,0 +1,18 @@
+-- { dg-do compile }
+-- { dg-options "-cargs -g -dA -fgnat-encodings=minimal -margs" }
+
+package Debug1 is
+
+ type Index_T is new Positive range 1 .. 128;
+
+ type Array_Type is array (Index_T range <>) of Integer;
+
+ type Record_Type (N : Index_T := 16) is record
+ A : Array_Type (1 .. N);
+ end record;
+
+ R : Record_Type;
+
+end Debug1;
+
+-- { dg-final { scan-assembler-times "DW_AT_upper_bound" 4 } }
diff --git a/gcc/testsuite/gnat.dg/specs/discr5.ads b/gcc/testsuite/gnat.dg/specs/discr5.ads
new file mode 100644
index 0000000..c265723
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/specs/discr5.ads
@@ -0,0 +1,57 @@
+-- { dg-do compile }
+
+with System;
+
+package Discr5 is
+
+ X, Y : Boolean;
+
+ type R (D : Boolean := False) is tagged limited record
+ F : Integer;
+ case D is
+ when True =>
+ F1, F2 : Integer;
+ when False =>
+ null;
+ end case;
+ end record;
+ for R use record
+ F1 at 100 range 0..31;
+ end record;
+
+ subtype Rt is R(True);
+ subtype Rf is R(False);
+
+ type R1 (D1 : Boolean) is new R (X) with record
+ FF : Float;
+ case D1 is
+ when True =>
+ F3, F4 : Float;
+ when False =>
+ null;
+ end case;
+ end record;
+ for R1 use record
+ F4 at 200 range 0..31;
+ end record;
+
+ subtype R1t is R1 (True);
+ subtype R1f is R1 (False);
+
+ type R2 (D2 : Boolean) is new R1 (Y) with record
+ FFF: System.Address;
+ case D2 is
+ when True =>
+ F5, F6: System.Address;
+ when False =>
+ null;
+ end case;
+ end record;
+ for R2 use record
+ F6 at 300 range 0..63;
+ end record;
+
+ subtype R2t is R2 (True);
+ subtype R2f is R2 (False);
+
+end Discr5;
diff --git a/gcc/testsuite/gnat.dg/specs/discr6.ads b/gcc/testsuite/gnat.dg/specs/discr6.ads
new file mode 100644
index 0000000..af16553
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/specs/discr6.ads
@@ -0,0 +1,21 @@
+-- { dg-do compile }
+
+package Discr6 is
+
+ subtype Index_T is Integer range 0 .. 15;
+
+ type Arr is array (Index_T range <> ) of Long_Long_Integer;
+
+ type Rec2 (Size : Index_T := 2) is record
+ A : Arr (2 .. Size);
+ end record;
+
+ type Rec3 (D : Boolean := False) is record
+ R : Rec2;
+ case D is
+ when False=> null;
+ when True => I : Integer;
+ end case;
+ end record;
+
+end Discr6;
diff --git a/gcc/testsuite/gnat.dg/specs/size_clause3.ads b/gcc/testsuite/gnat.dg/specs/size_clause3.ads
index b7602d9..12ca2d1 100644
--- a/gcc/testsuite/gnat.dg/specs/size_clause3.ads
+++ b/gcc/testsuite/gnat.dg/specs/size_clause3.ads
@@ -14,7 +14,7 @@ package Size_Clause3 is
rr : R1; -- size must be 40
end record;
for S1 use record
- rr at 0 range 0 .. 39; -- { dg-error "size of .rr. with aliased or tagged" }
+ rr at 0 range 0 .. 39; -- { dg-error "size for .rr. too small" }
end record;
-- The record is explicitly given alignment 1 so its real type is 40.
@@ -44,7 +44,7 @@ package Size_Clause3 is
rr : R3; -- size must be 40
end record;
for S3 use record
- rr at 0 range 0 .. 39; -- { dg-error "size of .rr. with aliased or tagged" }
+ rr at 0 range 0 .. 39; -- { dg-error "size for .rr. too small" }
end record;
end Size_Clause3;
diff --git a/gcc/testsuite/gnat.dg/specs/unchecked_convert1.ads b/gcc/testsuite/gnat.dg/specs/unchecked_convert1.ads
new file mode 100644
index 0000000..53429cd
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/specs/unchecked_convert1.ads
@@ -0,0 +1,20 @@
+-- { dg-do compile }
+-- { dg-options "-gnatws" }
+
+with Ada.Unchecked_Conversion;
+with System;
+
+package Unchecked_Convert1 is
+
+ type Rec (D : Boolean := False) is record
+ case D is
+ when True => I : Integer;
+ when False => null;
+ end case;
+ end record;
+
+ function To_Rec is new Ada.Unchecked_Conversion (System.Address, Rec);
+
+ function F (A : System.Address) return Rec is (To_Rec (A));
+
+end Unchecked_Convert1;
diff --git a/gcc/testsuite/gnat.dg/specs/unchecked_convert2.ads b/gcc/testsuite/gnat.dg/specs/unchecked_convert2.ads
new file mode 100644
index 0000000..8b04fc1
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/specs/unchecked_convert2.ads
@@ -0,0 +1,19 @@
+-- { dg-do compile }
+-- { dg-options "-gnatws" }
+
+with Ada.Unchecked_Conversion;
+
+package Unchecked_Convert2 is
+
+ type Address is access String;
+ for Address'Size use Standard'Address_Size;
+
+ type Rec is record
+ A : Address;
+ end record;
+
+ function To_Integer is new Ada.Unchecked_Conversion (Address, Integer);
+
+ function F (R : Rec) return Integer is (To_Integer (R.A));
+
+end Unchecked_Convert2;
diff --git a/gcc/testsuite/gnat.dg/static_pred1.adb b/gcc/testsuite/gnat.dg/static_pred1.adb
index 5b32a5c..16bbde2 100644
--- a/gcc/testsuite/gnat.dg/static_pred1.adb
+++ b/gcc/testsuite/gnat.dg/static_pred1.adb
@@ -8,7 +8,7 @@ package body Static_Pred1 is
Enum_Subrange in A | C;
function "not" (Kind : Enum_Subrange) return Enum_Subrange is
- (case Kind is -- { dg-error "missing case value: \"B\"" }
+ (case Kind is
when A => C,
when C => A);
diff --git a/gcc/testsuite/gnat.dg/task2.adb b/gcc/testsuite/gnat.dg/task2.adb
new file mode 100644
index 0000000..f7a8159
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/task2.adb
@@ -0,0 +1,9 @@
+-- { dg-do run }
+
+with Task2_Pkg; use Task2_Pkg;
+
+procedure Task2 is
+ X : access T2'Class := new T2;
+begin
+ null;
+end Task2;
diff --git a/gcc/testsuite/gnat.dg/task2_pkg.adb b/gcc/testsuite/gnat.dg/task2_pkg.adb
new file mode 100644
index 0000000..9481a57
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/task2_pkg.adb
@@ -0,0 +1,6 @@
+package body Task2_Pkg is
+ task body T2 is
+ begin
+ null;
+ end T2;
+end Task2_Pkg;
diff --git a/gcc/testsuite/gnat.dg/task2_pkg.ads b/gcc/testsuite/gnat.dg/task2_pkg.ads
new file mode 100644
index 0000000..b4ef37c
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/task2_pkg.ads
@@ -0,0 +1,4 @@
+package Task2_Pkg is
+ type T is task Interface;
+ task type T2 is new T with end;
+end Task2_pkg;
diff --git a/gcc/testsuite/gnat.dg/unchecked_convert13.adb b/gcc/testsuite/gnat.dg/unchecked_convert13.adb
new file mode 100644
index 0000000..6297e27
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/unchecked_convert13.adb
@@ -0,0 +1,30 @@
+-- { dg-do compile }
+
+with Ada.Unchecked_Conversion;
+
+procedure Unchecked_Convert13 is
+
+ type B16_T is mod 2 ** 16;
+ for B16_T'Size use 16;
+ for B16_T'Alignment use 1;
+
+ type Rec_T is record
+ A : Short_Integer;
+ end record;
+ for Rec_T use record
+ A at 0 range 0 .. 15;
+ end record;
+ for Rec_T'Size use 16;
+
+ Rec : constant Rec_T := (A => 0);
+
+ function Rec_To_B16 is new Ada.Unchecked_Conversion (Rec_T, B16_T);
+
+ procedure Nested (B16 : B16_T) is
+ begin
+ null;
+ end;
+
+begin
+ Nested (Rec_To_B16 (Rec));
+end;
diff --git a/gcc/testsuite/gnat.dg/warn20.adb b/gcc/testsuite/gnat.dg/warn20.adb
new file mode 100644
index 0000000..90fbf32
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/warn20.adb
@@ -0,0 +1,11 @@
+-- { dg-do compile }
+-- { dg-options "-gnatwa" }
+
+with Warn20_Pkg;
+
+procedure Warn20 is
+ package P is new Warn20_Pkg (Integer, 0);
+ pragma Unreferenced (P);
+begin
+ null;
+end Warn20;
diff --git a/gcc/testsuite/gnat.dg/warn20_pkg.adb b/gcc/testsuite/gnat.dg/warn20_pkg.adb
new file mode 100644
index 0000000..7ee7ab7
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/warn20_pkg.adb
@@ -0,0 +1,10 @@
+package body Warn20_Pkg is
+ L : array (1 .. 10) of T := (1 .. 10 => None);
+ procedure Foo is
+ begin
+ for A of L loop
+ exit when A = None;
+ Dispatch (A);
+ end loop;
+ end;
+end;
diff --git a/gcc/testsuite/gnat.dg/warn20_pkg.ads b/gcc/testsuite/gnat.dg/warn20_pkg.ads
new file mode 100644
index 0000000..861484b
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/warn20_pkg.ads
@@ -0,0 +1,8 @@
+generic
+ type T is private;
+ None : T;
+package Warn20_Pkg is
+ generic
+ with procedure Dispatch (X : T) is null;
+ procedure Foo;
+end;
diff --git a/gcc/testsuite/gnat.dg/weak3.adb b/gcc/testsuite/gnat.dg/weak3.adb
new file mode 100644
index 0000000..ab494a0
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/weak3.adb
@@ -0,0 +1,11 @@
+-- { dg-do compile }
+
+package body Weak3 is
+
+ type T is new Integer;
+ pragma Weak_External (T); -- { dg-error "pragma applies to objects and subprograms" }
+ X : T;
+
+ procedure Foo is null;
+
+end Weak3;
diff --git a/gcc/testsuite/gnat.dg/weak3.ads b/gcc/testsuite/gnat.dg/weak3.ads
new file mode 100644
index 0000000..1c41a2d
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/weak3.ads
@@ -0,0 +1,3 @@
+package Weak3 is
+ procedure Foo;
+end Weak3;
diff --git a/gcc/testsuite/go.dg/concatstring.go b/gcc/testsuite/go.dg/concatstring.go
new file mode 100644
index 0000000..5dc4254
--- /dev/null
+++ b/gcc/testsuite/go.dg/concatstring.go
@@ -0,0 +1,8 @@
+// { dg-do compile }
+// { dg-options "-fgo-debug-optimization" }
+
+package p
+
+func F(b []byte, x string) string {
+ return "hello " + string(b) + x // { dg-error "no copy string\\(\\\[\\\]byte\\)" }
+}
diff --git a/gcc/testsuite/go.dg/mapstring.go b/gcc/testsuite/go.dg/mapstring.go
new file mode 100644
index 0000000..8a60e74
--- /dev/null
+++ b/gcc/testsuite/go.dg/mapstring.go
@@ -0,0 +1,11 @@
+// { dg-do compile }
+// { dg-options "-fgo-debug-optimization" }
+
+package p
+
+func F(m map[string]int, a, b []byte) int {
+ x := m[string(a)] // { dg-error "no copy string\\(\\\[\\\]byte\\)" }
+ y, ok := m[string(b)] // { dg-error "no copy string\\(\\\[\\\]byte\\)" }
+ _ = ok
+ return x + y
+}
diff --git a/gcc/testsuite/go.test/test/blank1.go b/gcc/testsuite/go.test/test/blank1.go
index 54a7297..b60f9e1 100644
--- a/gcc/testsuite/go.test/test/blank1.go
+++ b/gcc/testsuite/go.test/test/blank1.go
@@ -7,7 +7,7 @@
// Test that incorrect uses of the blank identifer are caught.
// Does not compile.
-package _ // ERROR "invalid package name _"
+package _ // ERROR "invalid package name"
var t struct {
_ int
@@ -18,8 +18,8 @@ type T struct {
}
func main() {
- _() // ERROR "cannot use _ as value"
- x := _+1 // ERROR "cannot use _ as value"
+ _() // ERROR "cannot use .* as value"
+ x := _+1 // ERROR "cannot use .* as value"
_ = x
_ = t._ // ERROR "cannot refer to blank field|invalid use of"
diff --git a/gcc/testsuite/go.test/test/nilptr2.go b/gcc/testsuite/go.test/test/nilptr2.go
index 57a5f80..d2f4c91 100644
--- a/gcc/testsuite/go.test/test/nilptr2.go
+++ b/gcc/testsuite/go.test/test/nilptr2.go
@@ -35,7 +35,10 @@ var m *M
var m1 *M1
var m2 *M2
-func use(interface{}) {
+var V interface{}
+
+func use(x interface{}) {
+ V = x
}
var tests = []struct{
diff --git a/gcc/testsuite/lib/gcc-dg.exp b/gcc/testsuite/lib/gcc-dg.exp
index c56e8e8..e23b63c 100644
--- a/gcc/testsuite/lib/gcc-dg.exp
+++ b/gcc/testsuite/lib/gcc-dg.exp
@@ -422,6 +422,17 @@ proc gcc-dg-prune { system text } {
return "::unsupported::memory full"
}
+ if { [string match "*error: function pointers not supported*" $text]
+ && ![check_effective_target_function_pointers] } {
+ # The format here is important. See dg.exp.
+ return "::unsupported::funcptr"
+ }
+ if { [string match "*error: large return values not supported*" $text]
+ && ![check_effective_target_large_return_values] } {
+ # The format here is important. See dg.exp.
+ return "::unsupported::large return values"
+ }
+
return $text
}
diff --git a/gcc/testsuite/lib/scanasm.exp b/gcc/testsuite/lib/scanasm.exp
index cca6d64..35ccbc8 100644
--- a/gcc/testsuite/lib/scanasm.exp
+++ b/gcc/testsuite/lib/scanasm.exp
@@ -508,7 +508,10 @@ proc dg-function-on-line { args } {
}
}
- if { [istarget hppa*-*-*] } {
+ if { [istarget hppa*-*-linux*] } {
+ set pattern [format {%s:\n\t.PROC\n\t.CALLINFO.*\n\t.ENTRY\n.L.*:\n(\t.file[^\t]*)*\t[^:]+:%d(:[0-9]+)?\n} \
+ $symbol $line]
+ } elseif { [istarget hppa*-*-*] } {
set pattern [format {\t;[^:]+:%d(:[0-9]+)?\n(\t[^\t]+\n)+%s:\n\t.PROC} \
$line $symbol]
} elseif { [istarget mips*-*-*] } {
diff --git a/gcc/testsuite/lib/target-supports.exp b/gcc/testsuite/lib/target-supports.exp
index 4bb7da2..815e837 100644
--- a/gcc/testsuite/lib/target-supports.exp
+++ b/gcc/testsuite/lib/target-supports.exp
@@ -513,7 +513,8 @@ proc check_effective_target_trampolines { } {
|| [istarget msp430-*-*]
|| [istarget nvptx-*-*]
|| [istarget hppa2.0w-hp-hpux11.23]
- || [istarget hppa64-hp-hpux11.23] } {
+ || [istarget hppa64-hp-hpux11.23]
+ || [istarget pru-*-*] } {
return 0;
}
return 1
@@ -687,6 +688,7 @@ proc check_profiling_available { test_what } {
|| [istarget nvptx-*-*]
|| [istarget powerpc-*-eabi*]
|| [istarget powerpc-*-elf]
+ || [istarget pru-*-*]
|| [istarget rx-*-*]
|| [istarget tic6x-*-elf]
|| [istarget visium-*-*]
@@ -1590,16 +1592,6 @@ proc check_sse_os_support_available { } {
# If this is not the right target then we can skip the test.
if { !([istarget i?86-*-*] || [istarget x86_64-*-*]) } {
expr 0
- } elseif { [istarget i?86-*-solaris2*] } {
- # The Solaris 2 kernel doesn't save and restore SSE registers
- # before Solaris 9 4/04. Before that, executables die with SIGILL.
- check_runtime_nocache sse_os_support_available {
- int main ()
- {
- asm volatile ("movaps %xmm0,%xmm0");
- return 0;
- }
- } "-msse"
} else {
expr 1
}
@@ -2150,6 +2142,25 @@ proc check_p9modulo_hw_available { } {
}]
}
+
+# Return 1 if the target supports executing FUTURE instructions, 0 otherwise.
+# Cache the result. It is assumed that if a simulator does not support the
+# FUTURE instructions, that it will generate an error and this test will fail.
+
+proc check_powerpc_future_hw_available { } {
+ return [check_cached_effective_target powerpc_future_hw_available {
+ check_runtime_nocache powerpc_future_hw_available {
+ int main()
+ {
+ /* Set e first and use +r to check if pli actually works. */
+ long e = -1;
+ asm ("pli %0,%1" : "+r" (e) : "n" (0x12345));
+ return (e == 0x12345);
+ }
+ } "-mfuture"
+ }]
+}
+
# Return 1 if the target supports executing __float128 on PowerPC via software
# emulation, 0 otherwise. Cache the result.
@@ -2606,6 +2617,15 @@ proc check_effective_target_int32plus { } {
}]
}
+# Return 1 if we're generating 64-bit long long using default options,
+# 0 otherwise.
+
+proc check_effective_target_longlong64 { } {
+ return [check_no_compiler_messages longlong64 object {
+ int dummy[sizeof (long long) == 8 ? 1 : -1];
+ }]
+}
+
# Return 1 if we're generating 32-bit or larger pointers using default
# options, 0 otherwise.
@@ -2633,6 +2653,32 @@ proc check_effective_target_size20plus { } {
}]
}
+# Return 1 if target supports function pointers, 0 otherwise.
+
+proc check_effective_target_function_pointers { } {
+ if { [istarget pru-*-*] } {
+ return [check_no_compiler_messages func_ptr_avail assembly {
+ #ifdef __PRU_EABI_GNU__
+ #error unsupported
+ #endif
+ }]
+ }
+ return 1
+}
+
+# Return 1 if target supports arbitrarily large return values, 0 otherwise.
+
+proc check_effective_target_large_return_values { } {
+ if { [istarget pru-*-*] } {
+ return [check_no_compiler_messages large_return_values assembly {
+ #ifdef __PRU_EABI_GNU__
+ #error unsupported
+ #endif
+ }]
+ }
+ return 1
+}
+
# Return 1 if we support 24-bit or larger array and structure sizes
# using default options, 0 otherwise.
# This implies at least a 32-bit address space, as no targets have an address
@@ -3316,6 +3362,24 @@ proc check_effective_target_aarch64_sve { } {
}]
}
+# Return 1 if this is an AArch64 target supporting SVE2.
+proc check_effective_target_aarch64_sve2 { } {
+ if { ![istarget aarch64*-*-*] } {
+ return 0
+ }
+ return [check_no_compiler_messages aarch64_sve2 assembly {
+ #if !defined (__ARM_FEATURE_SVE2)
+ #error FOO
+ #endif
+ }]
+}
+
+# Return 1 if this is an AArch64 target only supporting SVE (not SVE2).
+proc check_effective_target_aarch64_sve1_only { } {
+ return [expr { [check_effective_target_aarch64_sve]
+ && ![check_effective_target_aarch64_sve2] }]
+}
+
# Return the size in bits of an SVE vector, or 0 if the size is variable.
proc aarch64_sve_bits { } {
return [check_cached_effective_target aarch64_sve_bits {
@@ -3856,6 +3920,13 @@ proc add_options_for_arm_neon_softfp_fp16 { flags } {
return "$flags $et_arm_neon_softfp_fp16_flags"
}
+proc add_options_for_aarch64_sve { flags } {
+ if { ![istarget aarch64*-*-*] || [check_effective_target_aarch64_sve] } {
+ return "$flags"
+ }
+ return "$flags -march=armv8.2-a+sve"
+}
+
# Return 1 if this is an ARM target supporting the FP16 alternative
# format. Some multilibs may be incompatible with the options needed. Also
# set et_arm_neon_fp16_flags to the best options to add.
@@ -4333,6 +4404,22 @@ proc check_effective_target_aarch64_sve_hw { } {
asm volatile ("ptrue p0.b");
return 0;
}
+ } [add_options_for_aarch64_sve ""]]
+}
+
+# Return true if this is an AArch64 target that can run SVE2 code.
+
+proc check_effective_target_aarch64_sve2_hw { } {
+ if { ![istarget aarch64*-*-*] } {
+ return 0
+ }
+ return [check_runtime aarch64_sve2_hw_available {
+ int
+ main (void)
+ {
+ asm volatile ("addp z0.b, p0/m, z0.b, z1.b");
+ return 0;
+ }
}]
}
@@ -4353,7 +4440,7 @@ proc aarch64_sve_hw_bits { bits } {
__builtin_abort ();
return 0;
}
- }]]
+ }] [add_options_for_aarch64_sve ""]]
}
# Return true if this is an AArch64 target that can run SVE code and
@@ -5065,13 +5152,13 @@ proc check_effective_target_powerpc_p8vector_ok { } {
|| [istarget powerpc*-*-aix5.2*] } {
return 0
}
+ # Darwin doesn't run on power8, so far.
+ if { [istarget *-*-darwin*] } {
+ return 0
+ }
return [check_no_compiler_messages powerpc_p8vector_ok object {
int main (void) {
-#ifdef __MACH__
- asm volatile ("xxlorc vs0,vs0,vs0");
-#else
asm volatile ("xxlorc 0,0,0");
-#endif
return 0;
}
} "-mpower8-vector"]
@@ -5092,6 +5179,10 @@ proc check_effective_target_powerpc_p9vector_ok { } {
|| [istarget powerpc*-*-aix5.2*] } {
return 0
}
+ # Darwin doesn't run on power9, so far.
+ if { [istarget *-*-darwin*] } {
+ return 0
+ }
return [check_no_compiler_messages powerpc_p9vector_ok object {
int main (void) {
long e = -1;
@@ -5129,6 +5220,24 @@ proc check_effective_target_powerpc_p9modulo_ok { } {
}
}
+# Return 1 if this is a PowerPC target supporting -mfuture.
+# Limit this to 64-bit linux systems for now until other
+# targets support FUTURE.
+
+proc check_effective_target_powerpc_future_ok { } {
+ if { ([istarget powerpc64*-*-linux*]) } {
+ return [check_no_compiler_messages powerpc_future_ok object {
+ int main (void) {
+ long e;
+ asm ("pli %0,%1" : "=r" (e) : "n" (0x12345));
+ return e;
+ }
+ } "-mfuture"]
+ } else {
+ return 0
+ }
+}
+
# Return 1 if this is a PowerPC target supporting -mfloat128 via either
# software emulation on power7/power8 systems or hardware support on power9.
@@ -5142,6 +5251,10 @@ proc check_effective_target_powerpc_float128_sw_ok { } {
|| [istarget powerpc*-*-aix5.2*] } {
return 0
}
+ # Darwin doesn't have VSX, so no soft support for float128.
+ if { [istarget *-*-darwin*] } {
+ return 0
+ }
return [check_no_compiler_messages powerpc_float128_sw_ok object {
volatile __float128 x = 1.0q;
volatile __float128 y = 2.0q;
@@ -5168,6 +5281,10 @@ proc check_effective_target_powerpc_float128_hw_ok { } {
|| [istarget powerpc*-*-aix5.2*] } {
return 0
}
+ # Darwin doesn't run on any machine with float128 h/w so far.
+ if { [istarget *-*-darwin*] } {
+ return 0
+ }
return [check_no_compiler_messages powerpc_float128_hw_ok object {
volatile __float128 x = 1.0q;
volatile __float128 y = 2.0q;
@@ -5224,13 +5341,14 @@ proc check_effective_target_powerpc_vsx_ok { } {
|| [istarget powerpc*-*-aix6*] } {
return 0
}
+ # Darwin doesn't have VSX, even if it's used with an assembler
+ # which recognises the insns.
+ if { [istarget *-*-darwin*] } {
+ return 0
+ }
return [check_no_compiler_messages powerpc_vsx_ok object {
int main (void) {
-#ifdef __MACH__
- asm volatile ("xxlor vs0,vs0,vs0");
-#else
asm volatile ("xxlor 0,0,0");
-#endif
return 0;
}
} "-mvsx"]
@@ -6060,7 +6178,7 @@ proc check_effective_target_vect_usad_char { } {
proc check_effective_target_vect_avg_qi {} {
return [expr { [istarget aarch64*-*-*]
- && ![check_effective_target_aarch64_sve] }]
+ && ![check_effective_target_aarch64_sve1_only] }]
}
# Return 1 if the target plus current options supports a vector
@@ -6485,9 +6603,14 @@ proc available_vector_sizes { } {
} elseif { [istarget arm*-*-*]
&& [check_effective_target_arm_neon_ok] } {
lappend result 128 64
- } elseif { (([istarget i?86-*-*] || [istarget x86_64-*-*])
- && ([check_avx_available] && ![check_prefer_avx128])) } {
- lappend result 256 128
+ } elseif { [istarget i?86-*-*] || [istarget x86_64-*-*] } {
+ if { [check_avx_available] && ![check_prefer_avx128] } {
+ lappend result 256
+ }
+ lappend result 128
+ if { ![is-effective-target ia32] } {
+ lappend result 64
+ }
} elseif { [istarget sparc*-*-*] } {
lappend result 64
} else {
@@ -7845,6 +7968,20 @@ proc check_effective_target_avx512bw { } {
} "-mavx512bw" ]
}
+# Return 1 if avx512vp2intersect instructions can be compiled.
+proc check_effective_target_avx512vp2intersect { } {
+ return [check_no_compiler_messages avx512vp2intersect object {
+ typedef int __v16si __attribute__ ((__vector_size__ (64)));
+ typedef short __mmask16;
+ void
+ _mm512_2intersect_epi32 (__v16si __A, __v16si __B, __mmask16 *__U,
+ __mmask16 *__M)
+ {
+ __builtin_ia32_2intersectd512 (__U, __M, (__v16si) __A, (__v16si) __B);
+ }
+ } "-mavx512vp2intersect" ]
+}
+
# Return 1 if avx512ifma instructions can be compiled.
proc check_effective_target_avx512ifma { } {
return [check_no_compiler_messages avx512ifma object {
@@ -8588,6 +8725,17 @@ proc check_effective_target_aarch64_large { } {
}
}
+# Return 1 if the assembler accepts the aarch64 .variant_pcs directive.
+
+proc check_effective_target_aarch64_variant_pcs { } {
+ if { [istarget aarch64*-*-*] } {
+ return [check_no_compiler_messages aarch64_variant_pcs object {
+ __asm__ (".variant_pcs foo");
+ }]
+ } else {
+ return 0
+ }
+}
# Return 1 if this is a reduced AVR Tiny core. Such cores have different
# register set, instruction set, addressing capabilities and ABI.
@@ -8671,6 +8819,11 @@ proc check_effective_target_tiny {} {
&& [check_effective_target_avr_tiny] } {
return 1
}
+ # PRU Program Counter is 16-bits, and trampolines are not supported.
+ # Hence directly declare as a tiny target.
+ if [istarget pru-*-*] {
+ return 1
+ }
return 0
}]
}
@@ -9222,7 +9375,7 @@ proc check_effective_target_cet { } {
{
asm ("setssbsy");
}
- } "-O2" ]
+ } "-O2 -fcf-protection" ]
}
# Return 1 if target supports floating point "infinite"
@@ -9310,6 +9463,17 @@ proc check_effective_target_arm_v8_3a_complex_neon_hw { } {
} [add_options_for_arm_v8_3a_complex_neon ""]]
}
+# Returns 1 if the target is using glibc, 0 otherwise.
+
+proc check_effective_target_glibc { } {
+ return [check_no_compiler_messages glibc_object assembly {
+ #include <stdlib.h>
+ #if !defined(__GLIBC__)
+ #error undefined
+ #endif
+ }]
+}
+
# Return 1 if the target plus current options supports a vector
# complex addition with rotate of half and single float modes, 0 otherwise.
#
@@ -9345,3 +9509,14 @@ proc check_effective_target_llvm_binutils { } {
expr { [istarget amdgcn*-*-*]
|| [check_effective_target_offload_gcn] }}]
}
+
+# Return 1 if the compiler supports '-mfentry'.
+
+proc check_effective_target_mfentry { } {
+ if { !([istarget i?86-*-*] || [istarget x86_64-*-*]) } {
+ return 0
+ }
+ return [check_no_compiler_messages mfentry object {
+ void foo (void) { }
+ } "-mfentry"]
+}
diff --git a/gcc/testsuite/lib/target-utils.exp b/gcc/testsuite/lib/target-utils.exp
index e847fdd..0dd1f34 100644
--- a/gcc/testsuite/lib/target-utils.exp
+++ b/gcc/testsuite/lib/target-utils.exp
@@ -35,10 +35,22 @@ proc ${tool}_check_unsupported_p { output } {
&& [check_effective_target_tiny] } {
return "memory full"
}
+ if { [regexp "(^|\n)\[^\n\]*: region \[^\n\]* overflowed" $output]
+ && [check_effective_target_tiny] } {
+ return "memory full"
+ }
if { [istarget spu-*-*] && \
[string match "*exceeds local store*" $output] } {
return "memory full"
}
+ if { [string match "*error: function pointers not supported*" $output]
+ && ![check_effective_target_function_pointers] } {
+ return "function pointers not supported"
+ }
+ if { [string match "*error: large return values not supported*" $output]
+ && ![check_effective_target_large_return_values] } {
+ return "large return values not supported"
+ }
return ""
}
diff --git a/gcc/testsuite/obj-c++.dg/class-protocol-1.mm b/gcc/testsuite/obj-c++.dg/class-protocol-1.mm
index f0eab03..78957cb 100644
--- a/gcc/testsuite/obj-c++.dg/class-protocol-1.mm
+++ b/gcc/testsuite/obj-c++.dg/class-protocol-1.mm
@@ -436,6 +436,4 @@ int main ()
return(0);
}
-/* { dg-warning "Messages without a matching method signature" "" { target *-*-* } 0 } */
-/* { dg-warning "will be assumed to return .id. and accept" "" { target *-*-* } 0 } */
-/* { dg-warning ".\.\.\.. as arguments" "" { target *-*-* } 0 } */
+/* { dg-warning "messages without a matching method signature will be assumed to return .id. and accept .\.\.\.. as arguments" "" { target *-*-* } 0 } */
diff --git a/gcc/testsuite/obj-c++.dg/cxx-ivars-3.mm b/gcc/testsuite/obj-c++.dg/cxx-ivars-3.mm
index 0098349..18b671d 100644
--- a/gcc/testsuite/obj-c++.dg/cxx-ivars-3.mm
+++ b/gcc/testsuite/obj-c++.dg/cxx-ivars-3.mm
@@ -2,13 +2,14 @@
// { dg-do run { target *-*-darwin* } }
// { dg-skip-if "" { *-*-* } { "-fgnu-runtime" } { "" } }
+// { dg-skip-if "Headers incompatible with 10.4 APIs" { *-*-darwin1[3-8]* } { "-fnext-runtime" } { "" } }
// { dg-additional-options "-fobjc-call-cxx-cdtors -mmacosx-version-min=10.4 -framework Foundation" }
// This test has no equivalent or meaning for m64/ABI V2
-// { dg-xfail-run-if "No Test Avail" { *-*-darwin* && lp64 } { "-fnext-runtime" } { "" } }
+// { dg-xfail-run-if "No Test Avail" { *-*-darwin* && lp64 } { "-fnext-runtime" } { "" } }
#include <objc/objc-runtime.h>
#include <stdlib.h>
-#include <Foundation/NSObject.h>
+#include "../objc-obj-c++-shared/F-NSObject.h"
//extern "C" { int printf(const char *,...); }
#define CHECK_IF(expr) if(!(expr)) abort()
diff --git a/gcc/testsuite/obj-c++.dg/exceptions-3.mm b/gcc/testsuite/obj-c++.dg/exceptions-3.mm
index 90a657c..622e4ca 100644
--- a/gcc/testsuite/obj-c++.dg/exceptions-3.mm
+++ b/gcc/testsuite/obj-c++.dg/exceptions-3.mm
@@ -27,19 +27,19 @@ int test (id object)
int dummy = 0;
@try { @throw object; }
- @catch (int x) /* { dg-error "@catch parameter is not a known Objective-C class type" } */
+ @catch (int x) /* { dg-error "'@catch' parameter is not a known Objective-C class type" } */
{
dummy++;
}
@try { @throw object; }
- @catch (intTypedef x) /* { dg-error "@catch parameter is not a known Objective-C class type" } */
+ @catch (intTypedef x) /* { dg-error "'@catch' parameter is not a known Objective-C class type" } */
{
dummy++;
}
@try { @throw object; }
- @catch (int *x) /* { dg-error "@catch parameter is not a known Objective-C class type" } */
+ @catch (int *x) /* { dg-error "'@catch' parameter is not a known Objective-C class type" } */
{
dummy++;
}
@@ -51,7 +51,7 @@ int test (id object)
}
@try { @throw object; }
- @catch (id <MyProtocol> x) /* { dg-error "@catch parameter cannot be protocol-qualified" } */
+ @catch (id <MyProtocol> x) /* { dg-error "'@catch' parameter cannot be protocol-qualified" } */
{
dummy++;
}
@@ -63,13 +63,13 @@ int test (id object)
}
@try { @throw object; }
- @catch (MyObject <MyProtocol> *x) /* { dg-error "@catch parameter cannot be protocol-qualified" } */
+ @catch (MyObject <MyProtocol> *x) /* { dg-error "'@catch' parameter cannot be protocol-qualified" } */
{
dummy++;
}
@try { @throw object; }
- @catch (MyObject x) /* { dg-error "@catch parameter is not a known Objective-C class type" } */
+ @catch (MyObject x) /* { dg-error "'@catch' parameter is not a known Objective-C class type" } */
{ /* { dg-error "no matching function" "" { target *-*-* } .-1 } */
dummy++; /* { dg-message "MyObject" "" { target *-*-* } interface_MyObject } */
} /* { dg-message "candidate" "" { target *-*-* } interface_MyObject } */
@@ -86,7 +86,7 @@ int test (id object)
}
@try { @throw object; }
- @catch (MyObjectTypedef <MyProtocol> *x) /* { dg-error "@catch parameter cannot be protocol-qualified" } */
+ @catch (MyObjectTypedef <MyProtocol> *x) /* { dg-error "'@catch' parameter cannot be protocol-qualified" } */
{
dummy++;
}
@@ -98,7 +98,7 @@ int test (id object)
}
@try { @throw object; }
- @catch (Class x) /* { dg-error "@catch parameter is not a known Objective-C class type" } */
+ @catch (Class x) /* { dg-error "'@catch' parameter is not a known Objective-C class type" } */
{
dummy++;
}
diff --git a/gcc/testsuite/obj-c++.dg/exceptions-4.mm b/gcc/testsuite/obj-c++.dg/exceptions-4.mm
index ccdeb34a..4aa00a6 100644
--- a/gcc/testsuite/obj-c++.dg/exceptions-4.mm
+++ b/gcc/testsuite/obj-c++.dg/exceptions-4.mm
@@ -33,18 +33,18 @@ int test (id object)
@try { @throw object; }
@catch
{ /* { dg-error "expected" } */
- dummy++; /* { dg-error "@catch parameter is not a known Objective-C class type" "" { target *-*-* } .-1 } */
+ dummy++; /* { dg-error "'@catch' parameter is not a known Objective-C class type" "" { target *-*-* } .-1 } */
}
@catch () /* { dg-error "expected identifier before" } */
- { /* { dg-error "@catch parameter is not a known Objective-C class type" "" { target *-*-* } .-1 } */
+ { /* { dg-error "'@catch' parameter is not a known Objective-C class type" "" { target *-*-* } .-1 } */
dummy++;
}
@catch (i) /* { dg-error ".i. has not been declared" } */
- { /* { dg-error "@catch parameter is not a known Objective-C class type" "" { target *-*-* } .-1 } */
+ { /* { dg-error "'@catch' parameter is not a known Objective-C class type" "" { target *-*-* } .-1 } */
dummy++;
}
@catch (id <MyProtocol x) /* { dg-error "expected ... before .x." } */
- { /* { dg-error "@catch parameter cannot be protocol-qualified" "" { target *-*-* } .-1 } */
+ { /* { dg-error "'@catch' parameter cannot be protocol-qualified" "" { target *-*-* } .-1 } */
dummy++;
}
@catch MyObject *x /* { dg-error "expected ... before .MyObject." } */
diff --git a/gcc/testsuite/obj-c++.dg/exceptions-5.mm b/gcc/testsuite/obj-c++.dg/exceptions-5.mm
index 01bf108..5aa08f3 100644
--- a/gcc/testsuite/obj-c++.dg/exceptions-5.mm
+++ b/gcc/testsuite/obj-c++.dg/exceptions-5.mm
@@ -27,19 +27,19 @@ int test (id object)
int dummy = 0;
@try { @throw object; }
- @catch (int) /* { dg-error "@catch parameter is not a known Objective-C class type" } */
+ @catch (int) /* { dg-error "'@catch' parameter is not a known Objective-C class type" } */
{
dummy++;
}
@try { @throw object; }
- @catch (intTypedef) /* { dg-error "@catch parameter is not a known Objective-C class type" } */
+ @catch (intTypedef) /* { dg-error "'@catch' parameter is not a known Objective-C class type" } */
{
dummy++;
}
@try { @throw object; }
- @catch (int *) /* { dg-error "@catch parameter is not a known Objective-C class type" } */
+ @catch (int *) /* { dg-error "'@catch' parameter is not a known Objective-C class type" } */
{
dummy++;
}
@@ -51,7 +51,7 @@ int test (id object)
}
@try { @throw object; }
- @catch (id <MyProtocol>) /* { dg-error "@catch parameter cannot be protocol-qualified" } */
+ @catch (id <MyProtocol>) /* { dg-error "'@catch' parameter cannot be protocol-qualified" } */
{
dummy++;
}
@@ -63,13 +63,13 @@ int test (id object)
}
@try { @throw object; }
- @catch (MyObject <MyProtocol> *) /* { dg-error "@catch parameter cannot be protocol-qualified" } */
+ @catch (MyObject <MyProtocol> *) /* { dg-error "'@catch' parameter cannot be protocol-qualified" } */
{
dummy++;
}
@try { @throw object; }
- @catch (MyObject) /* { dg-error "@catch parameter is not a known Objective-C class type" } */
+ @catch (MyObject) /* { dg-error "'@catch' parameter is not a known Objective-C class type" } */
{ /* { dg-error "no matching function" "" { target *-*-* } .-1 } */
dummy++; /* { dg-message "MyObject" "" { target *-*-* } interface_MyObject } */
} /* { dg-message "candidate" "" { target *-*-* } interface_MyObject } */
@@ -87,7 +87,7 @@ int test (id object)
}
@try { @throw object; }
- @catch (MyObjectTypedef <MyProtocol> *) /* { dg-error "@catch parameter cannot be protocol-qualified" } */
+ @catch (MyObjectTypedef <MyProtocol> *) /* { dg-error "'@catch' parameter cannot be protocol-qualified" } */
{
dummy++;
}
@@ -99,7 +99,7 @@ int test (id object)
}
@try { @throw object; }
- @catch (Class) /* { dg-error "@catch parameter is not a known Objective-C class type" } */
+ @catch (Class) /* { dg-error "'@catch' parameter is not a known Objective-C class type" } */
{
dummy++;
}
diff --git a/gcc/testsuite/obj-c++.dg/exceptions-6.mm b/gcc/testsuite/obj-c++.dg/exceptions-6.mm
index 6f6ba78..7a776a5 100644
--- a/gcc/testsuite/obj-c++.dg/exceptions-6.mm
+++ b/gcc/testsuite/obj-c++.dg/exceptions-6.mm
@@ -9,7 +9,7 @@
void test (id object)
{
@throw object; /* Ok */
- @throw; /* { dg-error ".@throw. .rethrow. used outside of a @catch block" } */
+ @throw; /* { dg-error ".@throw. .rethrow. used outside of a '@catch' block" } */
@throw (object); /* Ok. */
@throw (id)0 /* { dg-error "expected" } */
}
diff --git a/gcc/testsuite/obj-c++.dg/isa-field-1.mm b/gcc/testsuite/obj-c++.dg/isa-field-1.mm
index 4501d01..3fb27d5 100644
--- a/gcc/testsuite/obj-c++.dg/isa-field-1.mm
+++ b/gcc/testsuite/obj-c++.dg/isa-field-1.mm
@@ -1,5 +1,7 @@
/* Ensure there are no bizarre difficulties with accessing the 'isa' field of objects. */
/* { dg-do compile } */
+/* The use of isa is deprecated, but we still want to test that is works. */
+/* { dg-additional-options "-Wno-deprecated-declarations" } */
#include "../objc-obj-c++-shared/TestsuiteObject.h"
#include "../objc-obj-c++-shared/runtime.h"
diff --git a/gcc/testsuite/obj-c++.dg/method-12.mm b/gcc/testsuite/obj-c++.dg/method-12.mm
index 2282dec..4546144 100644
--- a/gcc/testsuite/obj-c++.dg/method-12.mm
+++ b/gcc/testsuite/obj-c++.dg/method-12.mm
@@ -24,9 +24,7 @@ void foo(void) {
/* { dg-message "also found .\\+\\(Protocol \\*\\)port." "" { target *-*-* } Derived_port_last } */
[receiver starboard]; /* { dg-warning "no .\\+starboard. method found" } */
- /* { dg-warning "Messages without a matching method signature" "" { target *-*-* } .-1 } */
- /* { dg-warning "will be assumed to return .id. and accept" "" { target *-*-* } .-2 } */
- /* { dg-warning ".\.\.\.. as arguments" "" { target *-*-* } .-3 } */
+ /* { dg-warning "messages without a matching method signature will be assumed to return .id. and accept .\.\.\.. as arguments" "" { target *-*-* } 0 } */
[Class port]; /* { dg-error ".Class. is not an Objective\\-C class name or alias" } */
}
diff --git a/gcc/testsuite/obj-c++.dg/method-13.mm b/gcc/testsuite/obj-c++.dg/method-13.mm
index b0a1f59..cd53d0f 100644
--- a/gcc/testsuite/obj-c++.dg/method-13.mm
+++ b/gcc/testsuite/obj-c++.dg/method-13.mm
@@ -16,10 +16,9 @@ id foo(void) {
TestsuiteObject *obj = [[TestsuiteObject alloc] init];
id obj2 = obj;
[obj setWindow:nil]; /* { dg-warning ".TestsuiteObject. may not respond to .\\-setWindow:." } */
- /* { dg-warning "Messages without a matching method signature" "" { target *-*-* } .-1 } */
- /* { dg-warning "will be assumed to return .id. and accept" "" { target *-*-* } .-2 } */
- /* { dg-warning ".\.\.\.. as arguments" "" { target *-*-* } .-3 } */
- [obj2 setWindow:nil]; /* { dg-warning "multiple methods named .\\-setWindow:. found" } */
+ /* { dg-warning "messages without a matching method signature will be assumed to return .id. and accept .\.\.\.. as arguments" "" { target *-*-* } 0 } */
+
+[obj2 setWindow:nil]; /* { dg-warning "multiple methods named .\\-setWindow:. found" } */
/* { dg-message "using .\\-\\(void\\)setWindow:\\(TestsuiteObject \\*\\)wdw." "" { target *-*-* } Class1_setWindow } */
/* { dg-message "also found .\\-\\(void\\)setWindow:\\(Class1 \\*\\)window." "" { target *-*-* } Class2_setWindow } */
diff --git a/gcc/testsuite/obj-c++.dg/method-6.mm b/gcc/testsuite/obj-c++.dg/method-6.mm
index 8f60511..65c0043 100644
--- a/gcc/testsuite/obj-c++.dg/method-6.mm
+++ b/gcc/testsuite/obj-c++.dg/method-6.mm
@@ -8,11 +8,9 @@
@class NotKnown;
void foo(NotKnown *n) {
- [NotKnown new]; /* { dg-warning ".interface of class .NotKnown. not found" } */
- [n nonexistent_method]; /* { dg-warning ".interface of class .NotKnown. not found" } */
+ [NotKnown new]; /* { dg-warning "'.interface' of class .NotKnown. not found" } */
+ [n nonexistent_method]; /* { dg-warning "'.interface' of class .NotKnown. not found" } */
/* { dg-warning "no .\\-nonexistent_method. method found" "" { target *-*-* } .-1 } */
}
-/* { dg-warning "Messages without a matching method signature" "" { target *-*-* } 0 } */
-/* { dg-warning "will be assumed to return .id. and accept" "" { target *-*-* } 0 } */
-/* { dg-warning ".\.\.\.. as arguments" "" { target *-*-* } 0 } */
+/* { dg-warning "messages without a matching method signature will be assumed to return .id. and accept .\.\.\.. as arguments" "" { target *-*-* } 0 } */
diff --git a/gcc/testsuite/obj-c++.dg/method-7.mm b/gcc/testsuite/obj-c++.dg/method-7.mm
index 8940914..277a7e9 100644
--- a/gcc/testsuite/obj-c++.dg/method-7.mm
+++ b/gcc/testsuite/obj-c++.dg/method-7.mm
@@ -11,12 +11,10 @@ void foo(UnderSpecified *u, NotAClass *n) {
[n nonexistent_method]; /* { dg-warning "invalid receiver type" } */
/* { dg-warning "no .\\-nonexistent_method. method found" "" { target *-*-* } .-1 } */
[NotAClass nonexistent_method]; /* { dg-error ".NotAClass. is not an Objective\\-C class name or alias" } */
- [u nonexistent_method]; /* { dg-warning ".interface of class .UnderSpecified. not found" } */
+ [u nonexistent_method]; /* { dg-warning "'.interface' of class .UnderSpecified. not found" } */
/* { dg-warning "no .\\-nonexistent_method. method found" "" { target *-*-* } .-1 } */
- [UnderSpecified nonexistent_method]; /* { dg-warning ".interface of class .UnderSpecified. not found" } */
+ [UnderSpecified nonexistent_method]; /* { dg-warning "'.interface' of class .UnderSpecified. not found" } */
/* { dg-warning "no .\\+nonexistent_method. method found" "" { target *-*-* } .-1 } */
}
-/* { dg-warning "Messages without a matching method signature" "" { target *-*-* } 0 } */
-/* { dg-warning "will be assumed to return .id. and accept" "" { target *-*-* } 0 } */
-/* { dg-warning ".\.\.\.. as arguments" "" { target *-*-* } 0 } */
+/* { dg-warning "messages without a matching method signature will be assumed to return .id. and accept .\.\.\.. as arguments" "" { target *-*-* } 0 } */
diff --git a/gcc/testsuite/obj-c++.dg/method-9.mm b/gcc/testsuite/obj-c++.dg/method-9.mm
index 4509c4a..787e25d 100644
--- a/gcc/testsuite/obj-c++.dg/method-9.mm
+++ b/gcc/testsuite/obj-c++.dg/method-9.mm
@@ -27,7 +27,4 @@
}
@end
-/* { dg-warning "Messages without a matching method signature" "" { target *-*-* } 0 } */
-/* { dg-warning "will be assumed to return .id. and accept" "" { target *-*-* } 0 } */
-/* { dg-warning ".\.\.\.. as arguments" "" { target *-*-* } 0 } */
-
+/* { dg-warning "messages without a matching method signature will be assumed to return .id. and accept .\.\.\.. as arguments" "" { target *-*-* } 0 } */
diff --git a/gcc/testsuite/obj-c++.dg/method-lookup-1.mm b/gcc/testsuite/obj-c++.dg/method-lookup-1.mm
index 47499c3..e458471 100644
--- a/gcc/testsuite/obj-c++.dg/method-lookup-1.mm
+++ b/gcc/testsuite/obj-c++.dg/method-lookup-1.mm
@@ -39,7 +39,7 @@ void test (Class x, Class <MyProtocol> y, id w, id <MyProtocol> z, NotKnown *a,
/* If a class is specified by name, the @interface must be available
to check what it responds to. */
- [NotKnown classMethod]; /* { dg-warning ".interface of class .NotKnown. not found" } */
+ [NotKnown classMethod]; /* { dg-warning "'.interface' of class .NotKnown. not found" } */
/* "id w" means that "w" responds to anything, both class and
@@ -70,7 +70,7 @@ void test (Class x, Class <MyProtocol> y, id w, id <MyProtocol> z, NotKnown *a,
because they expect the compiler to do type-checking; the
@interface must be available to do this check, otherwise the
compiler does not know what "a" responds to. */
- [a instanceMethod]; /* { dg-warning ".interface of class .NotKnown. not found" } */
+ [a instanceMethod]; /* { dg-warning "'.interface' of class .NotKnown. not found" } */
/* But, if you cast it to "id", then you're disabling type-checking
and the warnings should go away. */
diff --git a/gcc/testsuite/obj-c++.dg/objc-gc-3.mm b/gcc/testsuite/obj-c++.dg/objc-gc-3.mm
index 430e583..68bebf8 100644
--- a/gcc/testsuite/obj-c++.dg/objc-gc-3.mm
+++ b/gcc/testsuite/obj-c++.dg/objc-gc-3.mm
@@ -3,6 +3,7 @@
/* Contributed by Ziemowit Laski <zlaski@apple.com> */
/* { dg-do compile } */
+/* { dg-skip-if "GC API is an error from Darwin16." { *-*-darwin1[6-8]* } { "-fnext-runtime" } { "" } } */
/* { dg-options "-fobjc-gc" } */
/* { dg-prune-output "cc1objplus: warning: '-fobjc-gc' is ignored for '-fgnu-runtime'" } */
diff --git a/gcc/testsuite/obj-c++.dg/property/dotsyntax-17.mm b/gcc/testsuite/obj-c++.dg/property/dotsyntax-17.mm
index ce01598..050d9bf 100644
--- a/gcc/testsuite/obj-c++.dg/property/dotsyntax-17.mm
+++ b/gcc/testsuite/obj-c++.dg/property/dotsyntax-17.mm
@@ -35,19 +35,19 @@ int main (void)
{
MyRootClass *object = [[MyRootClass alloc] init];
- object.count = 10; /* { dg-error "readonly property cannot be set" } */
+ object.count = 10; /* { dg-error "'readonly' property cannot be set" } */
if (object.count != 10) /* Ok */
abort ();
/* Test errors when trying to change a readonly property using
pre/post increment/decrement operators. */
- object.count++; /* { dg-error "readonly property cannot be set" } */
+ object.count++; /* { dg-error "'readonly' property cannot be set" } */
- ++object.count; /* { dg-error "readonly property cannot be set" } */
+ ++object.count; /* { dg-error "'readonly' property cannot be set" } */
- object.count--; /* { dg-error "readonly property cannot be set" } */
+ object.count--; /* { dg-error "'readonly' property cannot be set" } */
- --object.count; /* { dg-error "readonly property cannot be set" } */
+ --object.count; /* { dg-error "'readonly' property cannot be set" } */
/* Test errors when trying to change something using Objective-C 2.0
dot-syntax but there is a setter but no getter. */
diff --git a/gcc/testsuite/obj-c++.dg/property/property-neg-7.mm b/gcc/testsuite/obj-c++.dg/property/property-neg-7.mm
index 245a807..d721ed1 100644
--- a/gcc/testsuite/obj-c++.dg/property/property-neg-7.mm
+++ b/gcc/testsuite/obj-c++.dg/property/property-neg-7.mm
@@ -13,8 +13,8 @@
void foo (NSArray *ans[], id pid, id apid[], int i) {
NSArray *test;
- test.count = 1; /* { dg-error "readonly property cannot be set" } */
- ((NSArray *)pid).count = 1; /* { dg-error "readonly property cannot be set" } */
- ((NSArray *)apid[i]).count = 1; /* { dg-error "readonly property cannot be set" } */
- ans[i].count = 3; /* { dg-error "readonly property cannot be set" } */
+ test.count = 1; /* { dg-error "'readonly' property cannot be set" } */
+ ((NSArray *)pid).count = 1; /* { dg-error "'readonly' property cannot be set" } */
+ ((NSArray *)apid[i]).count = 1; /* { dg-error "'readonly' property cannot be set" } */
+ ans[i].count = 3; /* { dg-error "'readonly' property cannot be set" } */
}
diff --git a/gcc/testsuite/obj-c++.dg/proto-lossage-4.mm b/gcc/testsuite/obj-c++.dg/proto-lossage-4.mm
index 2b9945f..2e753d1 100644
--- a/gcc/testsuite/obj-c++.dg/proto-lossage-4.mm
+++ b/gcc/testsuite/obj-c++.dg/proto-lossage-4.mm
@@ -47,6 +47,4 @@ long foo(void) {
return receiver;
}
-/* { dg-warning "Messages without a matching method signature" "" { target *-*-* } 0 } */
-/* { dg-warning "will be assumed to return .id. and accept" "" { target *-*-* } 0 } */
-/* { dg-warning ".\.\.\.. as arguments" "" { target *-*-* } 0 } */
+/* { dg-warning "messages without a matching method signature will be assumed to return .id. and accept .\.\.\.. as arguments" "" { target *-*-* } 0 } */
diff --git a/gcc/testsuite/obj-c++.dg/proto-lossage-7.mm b/gcc/testsuite/obj-c++.dg/proto-lossage-7.mm
index b32cfd8..d136af9 100644
--- a/gcc/testsuite/obj-c++.dg/proto-lossage-7.mm
+++ b/gcc/testsuite/obj-c++.dg/proto-lossage-7.mm
@@ -1,9 +1,11 @@
/* Check that typedefs of ObjC classes preserve
any @protocol qualifiers. */
/* { dg-do compile } */
+/* Suppress warnings that the GNUStep headers introduce. */
+/* { dg-additional-options "-std=gnu++11 -Wno-expansion-to-defined -Wno-variadic-macros" { target *-*-darwin* } } */
#ifdef __NEXT_RUNTIME__
-#include <Foundation/NSObject.h>
+#include "../objc-obj-c++-shared/F-NSObject.h"
#define OBJECT NSObject
#else
#include <objc/Object.h>
diff --git a/gcc/testsuite/obj-c++.dg/protocol-qualifier-2.mm b/gcc/testsuite/obj-c++.dg/protocol-qualifier-2.mm
index 9fb09b5..aa3082c 100644
--- a/gcc/testsuite/obj-c++.dg/protocol-qualifier-2.mm
+++ b/gcc/testsuite/obj-c++.dg/protocol-qualifier-2.mm
@@ -25,7 +25,6 @@ void test1 (void)
{
[object1 method]; /* Ok */
[object2 method]; /* { dg-warning ".MyClass. may not respond to ..method." } */
- /* { dg-warning "without a matching method" "" { target *-*-* } .-1 } */
- /* { dg-warning "will be assumed to return" "" { target *-*-* } .-2 } */
- /* { dg-warning "as arguments" "" { target *-*-* } .-3 } */
+
+ /* { dg-warning "messages without a matching method signature will be assumed to return .id. and accept '\.\.\.' as arguments" "" { target *-*-* } 0 } */
}
diff --git a/gcc/testsuite/obj-c++.dg/qual-types-1.mm b/gcc/testsuite/obj-c++.dg/qual-types-1.mm
index dd0eb42..2fe06e4 100644
--- a/gcc/testsuite/obj-c++.dg/qual-types-1.mm
+++ b/gcc/testsuite/obj-c++.dg/qual-types-1.mm
@@ -4,6 +4,8 @@
/* { dg-do run } */
/* { dg-xfail-run-if "Needs OBJC2 ABI" { *-*-darwin* && { lp64 && { ! objc2 } } } { "-fnext-runtime" } { "" } } */
+/* { dg-prune-output ".*ld: warning: direct access in.*" } */
+
#include "../objc-obj-c++-shared/TestsuiteObject.m"
#include <stdlib.h>
diff --git a/gcc/testsuite/obj-c++.dg/strings/const-cfstring-2.mm b/gcc/testsuite/obj-c++.dg/strings/const-cfstring-2.mm
index b4fc9e6..e81f471 100644
--- a/gcc/testsuite/obj-c++.dg/strings/const-cfstring-2.mm
+++ b/gcc/testsuite/obj-c++.dg/strings/const-cfstring-2.mm
@@ -8,8 +8,8 @@
/* { dg-skip-if "NeXT only" { *-*-* } { "-fgnu-runtime" } { "" } } */
/* { dg-options "-ftrack-macro-expansion=0 -mconstant-cfstrings -Wnonportable-cfstrings" } */
-#import <Foundation/NSString.h>
-#import <CoreFoundation/CFString.h>
+#include "../../objc-obj-c++-shared/F-NSString.h"
+#include "../../objc-obj-c++-shared/CF-CFString.h"
#ifndef __CONSTANT_CFSTRINGS__
#error The -fconstant-cfstrings option is not functioning properly
diff --git a/gcc/testsuite/obj-c++.dg/strings/const-cfstring-5.mm b/gcc/testsuite/obj-c++.dg/strings/const-cfstring-5.mm
index 98bb7c5..762afb6 100644
--- a/gcc/testsuite/obj-c++.dg/strings/const-cfstring-5.mm
+++ b/gcc/testsuite/obj-c++.dg/strings/const-cfstring-5.mm
@@ -6,7 +6,7 @@
/* { dg-skip-if "NeXT only" { *-*-* } { "-fgnu-runtime" } { "" } } */
/* { dg-options "-mconstant-cfstrings" } */
-#include <Foundation/NSObject.h>
+#include "../../objc-obj-c++-shared/F-NSObject.h"
@interface Foo: NSObject {
char *cString;
diff --git a/gcc/testsuite/obj-c++.dg/strings/const-str-12.mm b/gcc/testsuite/obj-c++.dg/strings/const-str-12.mm
index d0dfb66..ade24b3 100644
--- a/gcc/testsuite/obj-c++.dg/strings/const-str-12.mm
+++ b/gcc/testsuite/obj-c++.dg/strings/const-str-12.mm
@@ -6,7 +6,7 @@
/* { dg-options "-mno-constant-cfstrings -fconstant-string-class=Foo" { target *-*-darwin* } } */
#ifdef __NEXT_RUNTIME__
-#include <Foundation/NSObject.h>
+#include "../../objc-obj-c++-shared/F-NSObject.h"
#define OBJECT NSObject
#else
#include <objc/Object.h>
diff --git a/gcc/testsuite/obj-c++.dg/stubify-1.mm b/gcc/testsuite/obj-c++.dg/stubify-1.mm
index 687739c..b82167e 100644
--- a/gcc/testsuite/obj-c++.dg/stubify-1.mm
+++ b/gcc/testsuite/obj-c++.dg/stubify-1.mm
@@ -4,13 +4,13 @@
/* { dg-do compile { target *-*-darwin* } } */
/* { dg-skip-if "" { *-*-* } { "-fgnu-runtime" } { "" } } */
/* { dg-require-effective-target ilp32 } */
-/* { dg-options "-Os -mdynamic-no-pic -fno-exceptions -mmacosx-version-min=10.4" } */
+/* { dg-options "-Os -mdynamic-no-pic -fno-exceptions -mmacosx-version-min=10.4 -mpic-symbol-stubs" } */
typedef struct objc_object { } *id ;
int x = 41 ;
extern "C" {
- extern id objc_msgSend(id self, char * op, ...);
+ extern id objc_msgSend(id self, objc_selector* op, ...);
extern int bogonic (int, int, int);
}
@@ -20,9 +20,9 @@ extern "C" {
- (Document *) close;
@end
@implementation Document
-- (Document *) class { }
-- (Document *) close { }
-- (Document *) window { }
+- (Document *) class { return (Document *)0; }
+- (Document *) close { return (Document *)0; }
+- (Document *) window { return (Document *)0; }
- (void)willEndCloseSheet:(void *)sheet returnCode:(int)returnCode contextInfo:(void *)contextInfo {
[[self window] close];
((void (*)(id, char *, int))objc_msgSend)([self class], (char *)contextInfo, 1);
@@ -32,8 +32,8 @@ extern "C" {
}
@end
-/* { dg-final { scan-assembler-not "\(bl|call\)\[ \t\]+_objc_msgSend\n" } } */
-/* { dg-final { scan-assembler "\(bl|call\)\[ \t\]+L_objc_msgSend\\\$stub\n" } } */
-/* { dg-final { scan-assembler-not "\(bl|call\)\[ \t\]+_bogonic\n" } } */
-/* { dg-final { scan-assembler "\(bl|call\)\[ \t\]+L_bogonic\\\$stub\n" } } */
-/* { dg-final { scan-assembler-not "\\\$non_lazy_ptr" } } */
+/* { dg-final { scan-assembler-not {(bl|call)[ \t]+_objc_msgSend\n} } } */
+/* { dg-final { scan-assembler {(bl|call)[ \t]+L_objc_msgSend\$stub\n} } } */
+/* { dg-final { scan-assembler-not {(bl|call)[ \t]+_bogonic\n} } } */
+/* { dg-final { scan-assembler {(bl|call)[ \t]+L_bogonic\$stub\n} } } */
+/* { dg-final { scan-assembler-not {\$non_lazy_ptr} } } */
diff --git a/gcc/testsuite/obj-c++.dg/stubify-2.mm b/gcc/testsuite/obj-c++.dg/stubify-2.mm
index 9968672..ee8e342 100644
--- a/gcc/testsuite/obj-c++.dg/stubify-2.mm
+++ b/gcc/testsuite/obj-c++.dg/stubify-2.mm
@@ -4,7 +4,7 @@
/* { dg-do compile { target *-*-darwin* } } */
/* { dg-skip-if "" { *-*-* } { "-fgnu-runtime" } { "" } } */
/* { dg-require-effective-target ilp32 } */
-/* { dg-options "-mdynamic-no-pic -fdump-rtl-jump -mmacosx-version-min=10.4" } */
+/* { dg-options "-mdynamic-no-pic -fdump-rtl-jump -mmacosx-version-min=10.4 -mpic-symbol-stubs" } */
typedef struct objc_object { } *id ;
int x = 41 ;
@@ -16,9 +16,9 @@ extern int bogonic (int, int, int) ;
- (Document *) close;
@end
@implementation Document
-- (Document *) class { }
-- (Document *) close { }
-- (Document *) window { }
+- (Document *) class { return (Document *)0; }
+- (Document *) close { return (Document *)0; }
+- (Document *) window { return (Document *)0; }
- (void)willEndCloseSheet:(void *)sheet returnCode:(int)returnCode contextInfo:(void *)contextInfo {
[[self window] close];
((void (*)(id, char *, int))objc_msgSend)([self class], (char *)contextInfo, 1);
@@ -30,4 +30,10 @@ extern int bogonic (int, int, int) ;
/* Any symbol_ref of an un-stubified objc_msgSend is an error; look
for "objc_msgSend" in quotes, without the $stub suffix. */
-/* { dg-final { scan-rtl-dump-not "symbol_ref.*\"objc_msgSend\"" "jump" } } */
+/* { dg-final { scan-rtl-dump-not {symbol_ref.*"objc_msgSend"} "jump" { target powerpc*-*-darwin* } } } */
+
+/* { dg-final { scan-assembler-not {(bl|call)[ \t]+_objc_msgSend\n} } } */
+/* { dg-final { scan-assembler {(bl|call)[ \t]+L_objc_msgSend\$stub\n} } } */
+/* { dg-final { scan-assembler-not {(bl|call)[ \t]+_Z7bogoniciii\n} } } */
+/* { dg-final { scan-assembler {(bl|call)[ \t]+L__Z7bogoniciii\$stub\n} } } */
+/* { dg-final { scan-assembler-not {\$non_lazy_ptr} } } */
diff --git a/gcc/testsuite/obj-c++.dg/syntax-error-1.mm b/gcc/testsuite/obj-c++.dg/syntax-error-1.mm
index 320d56c..edbd9ef 100644
--- a/gcc/testsuite/obj-c++.dg/syntax-error-1.mm
+++ b/gcc/testsuite/obj-c++.dg/syntax-error-1.mm
@@ -1,8 +1,10 @@
/* Graceful handling of a syntax error. */
/* { dg-do compile } */
+/* Suppress warnings that the GNUStep headers introduce. */
+/* { dg-additional-options "-std=gnu++11 -Wno-expansion-to-defined -Wno-variadic-macros" { target *-*-darwin* } } */
#ifdef __NEXT_RUNTIME__
-#include <Foundation/NSObject.h>
+#include "../objc-obj-c++-shared/F-NSObject.h"
#define OBJECT NSObject
#else
#include <objc/Object.h>
diff --git a/gcc/testsuite/obj-c++.dg/torture/strings/const-cfstring-1.mm b/gcc/testsuite/obj-c++.dg/torture/strings/const-cfstring-1.mm
index 2983c43..0f1d92b 100644
--- a/gcc/testsuite/obj-c++.dg/torture/strings/const-cfstring-1.mm
+++ b/gcc/testsuite/obj-c++.dg/torture/strings/const-cfstring-1.mm
@@ -13,8 +13,8 @@
well, we don't implement writable ones at this juncture. */
/* { dg-options "-mconstant-cfstrings -framework Cocoa -Wl,-w" { target *-*-darwin[123]* } } */
-#import <Foundation/NSString.h>
-#import <CoreFoundation/CFString.h>
+#include "../../../objc-obj-c++-shared/F-NSString.h"
+#include "../../../objc-obj-c++-shared/CF-CFString.h"
#include <stdlib.h>
void printOut(NSString *str) {
@@ -47,10 +47,10 @@ int main(void) {
checkNSRange([@"Hello World" rangeOfString:(id)CFSTR("World")]);
checkNSRange([(id)CFSTR("Hello World") rangeOfString:(id)CFSTR("World")]);
- checkCFRange(CFStringFind((CFStringRef)@"Hello World", (CFStringRef)@"World", 0));
- checkCFRange(CFStringFind(CFSTR("Hello World"), (CFStringRef)@"World", 0));
- checkCFRange(CFStringFind((CFStringRef)@"Hello World", CFSTR("World"), 0));
- checkCFRange(CFStringFind(CFSTR("Hello World"), CFSTR("World"), 0));
+ checkCFRange(CFStringFind((CFStringRef)@"Hello World", (CFStringRef)@"World", (CFStringCompareFlags)0));
+ checkCFRange(CFStringFind(CFSTR("Hello World"), (CFStringRef)@"World", (CFStringCompareFlags)0));
+ checkCFRange(CFStringFind((CFStringRef)@"Hello World", CFSTR("World"), (CFStringCompareFlags)0));
+ checkCFRange(CFStringFind(CFSTR("Hello World"), CFSTR("World"), (CFStringCompareFlags)0));
/* Check for string uniquing. */
if (s0a != s0b || s0a != s2 || s1 != (id)s2) {
diff --git a/gcc/testsuite/obj-c++.dg/torture/strings/const-str-10.mm b/gcc/testsuite/obj-c++.dg/torture/strings/const-str-10.mm
index f2e912b..e1dad12 100644
--- a/gcc/testsuite/obj-c++.dg/torture/strings/const-str-10.mm
+++ b/gcc/testsuite/obj-c++.dg/torture/strings/const-str-10.mm
@@ -6,7 +6,7 @@
/* { dg-skip-if "" { *-*-* } { "-fgnu-runtime" } { "" } } */
/* { dg-options "-mno-constant-cfstrings" { target *-*-darwin* } } */
-#include <Foundation/NSObject.h>
+#include "../../../objc-obj-c++-shared/F-NSObject.h"
#include "../../../objc-obj-c++-shared/runtime.h" /* For NEXT_OBJC_USE_NEW_INTERFACE. */
@interface NSString: NSObject
diff --git a/gcc/testsuite/obj-c++.dg/torture/strings/const-str-11.mm b/gcc/testsuite/obj-c++.dg/torture/strings/const-str-11.mm
index 7e5d9b6..30a9228 100644
--- a/gcc/testsuite/obj-c++.dg/torture/strings/const-str-11.mm
+++ b/gcc/testsuite/obj-c++.dg/torture/strings/const-str-11.mm
@@ -7,7 +7,7 @@
/* { dg-options "-fconstant-string-class=XStr" } */
/* { dg-options "-mno-constant-cfstrings -fconstant-string-class=XStr" { target *-*-darwin* } } */
-#include <Foundation/NSObject.h>
+#include "../../../objc-obj-c++-shared/F-NSObject.h"
#include "../../../objc-obj-c++-shared/runtime.h" /* For NEXT_OBJC_USE_NEW_INTERFACE. */
@interface XString: NSObject {
diff --git a/gcc/testsuite/obj-c++.dg/torture/strings/const-str-9.mm b/gcc/testsuite/obj-c++.dg/torture/strings/const-str-9.mm
index d78dc73..a1a1429 100644
--- a/gcc/testsuite/obj-c++.dg/torture/strings/const-str-9.mm
+++ b/gcc/testsuite/obj-c++.dg/torture/strings/const-str-9.mm
@@ -5,7 +5,7 @@
/* { dg-skip-if "" { *-*-* } { "-fgnu-runtime" } { "" } } */
/* { dg-options "-mno-constant-cfstrings" { target *-*-darwin* } } */
-#include <Foundation/NSObject.h>
+#include "../../../objc-obj-c++-shared/F-NSObject.h"
#include "../../../objc-obj-c++-shared/runtime.h" /* For NEXT_OBJC_USE_NEW_INTERFACE. */
@interface NSConstantString: NSObject {
diff --git a/gcc/testsuite/obj-c++.dg/try-catch-1.mm b/gcc/testsuite/obj-c++.dg/try-catch-1.mm
index cbdace6..1688995 100644
--- a/gcc/testsuite/obj-c++.dg/try-catch-1.mm
+++ b/gcc/testsuite/obj-c++.dg/try-catch-1.mm
@@ -39,4 +39,5 @@ int foo()
@finally {
printf("In @finally block (%d)... ", exc_control);
}
+ return -1;
}
diff --git a/gcc/testsuite/obj-c++.dg/try-catch-3.mm b/gcc/testsuite/obj-c++.dg/try-catch-3.mm
index b0822d3..e6868a3 100644
--- a/gcc/testsuite/obj-c++.dg/try-catch-3.mm
+++ b/gcc/testsuite/obj-c++.dg/try-catch-3.mm
@@ -15,4 +15,5 @@ const char *foo(void)
@catch (TestsuiteObject* theException) {
return [theException name];
}
+ return (const char *)0;
}
diff --git a/gcc/testsuite/objc-obj-c++-shared/CF-CFString.h b/gcc/testsuite/objc-obj-c++-shared/CF-CFString.h
new file mode 100644
index 0000000..626001b
--- /dev/null
+++ b/gcc/testsuite/objc-obj-c++-shared/CF-CFString.h
@@ -0,0 +1,33 @@
+/* Copyright (C) 2019 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 3, or (at your option)
+any later version.
+
+GCC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3. If not see
+<http://www.gnu.org/licenses/>. */
+
+#ifndef _OBJC_CF_CFSTRING_H_
+#define _OBJC_CF_CFSTRING_H_
+
+/* This is a workaround to PR90709 for the NeXT runtime.
+ If we're on a system version that has headers with items we can't
+ consume, then use the GNUStep header instead.
+*/
+
+#if __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ >= 1090
+# import "GNUStep/CoreFoundation/CFString.h"
+#else
+# import <CoreFoundation/CFString.h>
+#endif
+
+#endif /* _OBJC_CF_CFSTRING_H_ */
diff --git a/gcc/testsuite/objc-obj-c++-shared/F-NSArray.h b/gcc/testsuite/objc-obj-c++-shared/F-NSArray.h
new file mode 100644
index 0000000..99b6189
--- /dev/null
+++ b/gcc/testsuite/objc-obj-c++-shared/F-NSArray.h
@@ -0,0 +1,33 @@
+/* Copyright (C) 2019 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 3, or (at your option)
+any later version.
+
+GCC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3. If not see
+<http://www.gnu.org/licenses/>. */
+
+#ifndef _OBJC_F_NSARRAY_H_
+#define _OBJC_F_NSARRAY_H_
+
+/* This is a workaround to PR90709 for the NeXT runtime.
+ If we're on a system version that has headers with items we can't
+ consume, then use the GNUStep header instead.
+*/
+
+#if __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ >= 1090
+# import "GNUStep/Foundation/NSArray.h"
+#else
+# import <Foundation/NSArray.h>
+#endif
+
+#endif /* _OBJC_F_NSARRAY_H_ */
diff --git a/gcc/testsuite/objc-obj-c++-shared/F-NSAutoreleasePool.h b/gcc/testsuite/objc-obj-c++-shared/F-NSAutoreleasePool.h
new file mode 100644
index 0000000..17599e8
--- /dev/null
+++ b/gcc/testsuite/objc-obj-c++-shared/F-NSAutoreleasePool.h
@@ -0,0 +1,33 @@
+/* Copyright (C) 2019 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 3, or (at your option)
+any later version.
+
+GCC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3. If not see
+<http://www.gnu.org/licenses/>. */
+
+#ifndef _OBJC_F_NSAUTORELEASEPOOL_H_
+#define _OBJC_F_NSAUTORELEASEPOOL_H_
+
+/* This is a workaround to PR90709 for the NeXT runtime.
+ If we're on a system version that has headers with items we can't
+ consume, then use the GNUStep header instead.
+*/
+
+#if __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ >= 1090
+# import "GNUStep/Foundation/NSAutoreleasePool.h"
+#else
+# import <Foundation/NSAutoreleasePool.h>
+#endif
+
+#endif /* _OBJC_F_NSAUTORELEASEPOOL_H_ */
diff --git a/gcc/testsuite/objc-obj-c++-shared/F-NSObject.h b/gcc/testsuite/objc-obj-c++-shared/F-NSObject.h
new file mode 100644
index 0000000..a372d60
--- /dev/null
+++ b/gcc/testsuite/objc-obj-c++-shared/F-NSObject.h
@@ -0,0 +1,33 @@
+/* Copyright (C) 2019 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 3, or (at your option)
+any later version.
+
+GCC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3. If not see
+<http://www.gnu.org/licenses/>. */
+
+#ifndef _OBJC_F_NSOBJECT_H_
+#define _OBJC_F_NSOBJECT_H_
+
+/* This is a workaround to PR90709 for the NeXT runtime.
+ If we're on a system version that has headers with items we can't
+ consume, then use the GNUStep header instead.
+*/
+
+#if __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ >= 1090
+# import "GNUStep/Foundation/NSObject.h"
+#else
+# import <Foundation/NSObject.h>
+#endif
+
+#endif /* _OBJC_F_NSOBJECT_H_ */
diff --git a/gcc/testsuite/objc-obj-c++-shared/F-NSString.h b/gcc/testsuite/objc-obj-c++-shared/F-NSString.h
new file mode 100644
index 0000000..5c29398
--- /dev/null
+++ b/gcc/testsuite/objc-obj-c++-shared/F-NSString.h
@@ -0,0 +1,33 @@
+/* Copyright (C) 2019 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 3, or (at your option)
+any later version.
+
+GCC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3. If not see
+<http://www.gnu.org/licenses/>. */
+
+#ifndef _OBJC_F_NSSTRING_H_
+#define _OBJC_F_NSSTRING_H_
+
+/* This is a workaround to PR90709 for the NeXT runtime.
+ If we're on a system version that has headers with items we can't
+ consume, then use the GNUStep header instead.
+*/
+
+#if __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ >= 1090
+# import "GNUStep/Foundation/NSString.h"
+#else
+# import <Foundation/NSString.h>
+#endif
+
+#endif /* _OBJC_F_NSSTRING_H_ */
diff --git a/gcc/testsuite/objc-obj-c++-shared/F-NSValue.h b/gcc/testsuite/objc-obj-c++-shared/F-NSValue.h
new file mode 100644
index 0000000..fbe2ab3
--- /dev/null
+++ b/gcc/testsuite/objc-obj-c++-shared/F-NSValue.h
@@ -0,0 +1,33 @@
+/* Copyright (C) 2019 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 3, or (at your option)
+any later version.
+
+GCC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3. If not see
+<http://www.gnu.org/licenses/>. */
+
+#ifndef _OBJC_F_NSSTRING_H_
+#define _OBJC_F_NSSTRING_H_
+
+/* This is a workaround to PR90709 for the NeXT runtime.
+ If we're on a system version that has headers with items we can't
+ consume, then use the GNUStep header instead.
+*/
+
+#if __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ >= 1090
+# import "GNUStep/Foundation/NSValue.h"
+#else
+# import <Foundation/NSValue.h>
+#endif
+
+#endif /* _OBJC_F_NSSTRING_H_ */
diff --git a/gcc/testsuite/objc-obj-c++-shared/GNUStep/CoreFoundation/CFArray.h b/gcc/testsuite/objc-obj-c++-shared/GNUStep/CoreFoundation/CFArray.h
new file mode 100644
index 0000000..0145855d
--- /dev/null
+++ b/gcc/testsuite/objc-obj-c++-shared/GNUStep/CoreFoundation/CFArray.h
@@ -0,0 +1,191 @@
+/* CFArray.h
+
+ Copyright (C) 2010 Free Software Foundation, Inc.
+
+ Written by: Stefan Bidigaray
+ Date: January, 2010
+
+ This file is part of CoreBase.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; see the file COPYING.LIB.
+ If not, see <http://www.gnu.org/licenses/> or write to the
+ Free Software Foundation, 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+
+#ifndef __COREFOUNDATION_CFARRAY_H__
+#define __COREFOUNDATION_CFARRAY_H__
+
+#include "CFBase.h"
+
+CF_EXTERN_C_BEGIN
+/** \ingroup CFArrayRef
+ \brief Reference to an immutable array object.
+ */
+typedef const struct __CFArray *CFArrayRef;
+/**
+ \ingroup CFMutableArrayRef
+ \brief Reference to a mutable array object.
+ */
+typedef struct __CFArray *CFMutableArrayRef;
+
+/** \defgroup CFArrayRef CFArray Reference
+ \brief A CFArray and its mutable type, \ref CFMutableArrayRef
+ "CFMutableArray", are simple, low overhead, ordered containers for
+ objects.
+ \details
+ <code>\#include <CoreFoundation/CFArray.h></code>
+ \{
+ */
+
+/** \name Callbacks
+ \{
+ */
+typedef void (*CFArrayApplierFunction) (const void *value, void *context);
+typedef CFStringRef (*CFArrayCopyDescriptionCallBack) (const void *value);
+typedef void (*CFArrayReleaseCallBack) (CFAllocatorRef allocator,
+ const void *value);
+typedef const void *(*CFArrayRetainCallBack) (CFAllocatorRef allocator,
+ const void *value);
+typedef Boolean (*CFArrayEqualCallBack) (const void *value1,
+ const void *value2);
+/** \} */
+
+/** \brief Structure with CFArray callbacks.
+ */
+typedef struct _CFArrayCallBacks CFArrayCallBacks;
+struct _CFArrayCallBacks
+{
+ CFIndex version; /**< Structure's version number. Current version is 0. */
+ CFArrayRetainCallBack retain;
+ /**< The callback used to retain values added to the array. If NULL,
+ values are not retained. */
+ CFArrayReleaseCallBack release;
+ CFArrayCopyDescriptionCallBack copyDescription;
+ CFArrayEqualCallBack equal;
+};
+
+/** \name Predefined Callback Structures
+ \{
+ */
+CF_EXPORT const CFArrayCallBacks kCFTypeArrayCallBacks;
+/** \} */
+
+
+
+/** \name Creating an Array
+ \{
+ */
+CF_EXPORT CFArrayRef
+CFArrayCreate (CFAllocatorRef allocator, const void **values,
+ CFIndex numValues, const CFArrayCallBacks * callBacks);
+
+CF_EXPORT CFArrayRef
+CFArrayCreateCopy (CFAllocatorRef allocator, CFArrayRef theArray);
+/** \} */
+
+/** \name Examining an Array
+ \{
+ */
+CF_EXPORT CFIndex
+CFArrayBSearchValues (CFArrayRef theArray, CFRange range, const void *value,
+ CFComparatorFunction comparator, void *context);
+
+CF_EXPORT Boolean
+CFArrayContainsValue (CFArrayRef theArray, CFRange range, const void *value);
+
+CF_EXPORT CFIndex CFArrayGetCount (CFArrayRef theArray);
+
+CF_EXPORT CFIndex
+CFArrayGetCountOfValue (CFArrayRef theArray, CFRange range, const void *value);
+
+CF_EXPORT CFIndex
+CFArrayGetFirstIndexOfValue (CFArrayRef theArray, CFRange range,
+ const void *value);
+
+CF_EXPORT CFIndex
+CFArrayGetLastIndexOfValue (CFArrayRef theArray, CFRange range,
+ const void *value);
+
+CF_EXPORT void
+CFArrayGetValues (CFArrayRef theArray, CFRange range, const void **values);
+
+CF_EXPORT const void *CFArrayGetValueAtIndex (CFArrayRef theArray, CFIndex idx);
+/** \} */
+
+/** \name Applying a Function to Elements
+ \{
+ */
+CF_EXPORT void
+CFArrayApplyFunction (CFArrayRef theArray, CFRange range,
+ CFArrayApplierFunction applier, void *context);
+/** \} */
+
+/** \name Getting the CFArray Type ID
+ \{
+ */
+CF_EXPORT CFTypeID CFArrayGetTypeID (void);
+/** \} */
+
+/** \} */
+
+/** \defgroup CFMutableArrayRef CFMutableArray Reference
+ \details <code>\#include <CoreFoundation/CFArray.h></code>
+ \{
+ */
+CF_EXPORT void
+CFArrayAppendArray (CFMutableArrayRef theArray, CFArrayRef otherArray,
+ CFRange otherRange);
+
+CF_EXPORT void
+CFArrayAppendValue (CFMutableArrayRef theArray, const void *value);
+
+CF_EXPORT CFMutableArrayRef
+CFArrayCreateMutable (CFAllocatorRef allocator, CFIndex capacity,
+ const CFArrayCallBacks * callBacks);
+
+CF_EXPORT CFMutableArrayRef
+CFArrayCreateMutableCopy (CFAllocatorRef allocator, CFIndex capacity,
+ CFArrayRef theArray);
+
+CF_EXPORT void
+CFArrayExchangeValuesAtIndices (CFMutableArrayRef theArray, CFIndex idx1,
+ CFIndex idx2);
+
+CF_EXPORT void
+CFArrayInsertValueAtIndex (CFMutableArrayRef theArray, CFIndex idx,
+ const void *value);
+
+CF_EXPORT void CFArrayRemoveAllValues (CFMutableArrayRef theArray);
+
+CF_EXPORT void
+CFArrayRemoveValueAtIndex (CFMutableArrayRef theArray, CFIndex idx);
+
+CF_EXPORT void
+CFArrayReplaceValues (CFMutableArrayRef theArray, CFRange range,
+ const void **newValues, CFIndex newCount);
+
+CF_EXPORT void
+CFArraySetValueAtIndex (CFMutableArrayRef theArray, CFIndex idx,
+ const void *value);
+
+CF_EXPORT void
+CFArraySortValues (CFMutableArrayRef theArray, CFRange range,
+ CFComparatorFunction comparator, void *context);
+
+/** \} */
+
+CF_EXTERN_C_END
+#endif /* __COREFOUNDATION_CFARRAY_H__ */
diff --git a/gcc/testsuite/objc-obj-c++-shared/GNUStep/CoreFoundation/CFAvailability.h b/gcc/testsuite/objc-obj-c++-shared/GNUStep/CoreFoundation/CFAvailability.h
new file mode 100644
index 0000000..855ff5c
--- /dev/null
+++ b/gcc/testsuite/objc-obj-c++-shared/GNUStep/CoreFoundation/CFAvailability.h
@@ -0,0 +1,52 @@
+/* CFAvailability.h
+
+ Copyright (C) 2017 Free Software Foundation, Inc.
+
+ Written by: Stefan Bidigaray
+ Date: August, 2017
+
+ This file is part of the GNUstep CoreBase Library.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; see the file COPYING.LIB.
+ If not, see <http://www.gnu.org/licenses/> or write to the
+ Free Software Foundation, 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+
+#ifndef __COREFOUNDATION_CFAVAILABILITY_H__
+#define __COREFOUNDATION_CFAVAILABILITY_H__
+
+/* Compiler features */
+#ifndef __has_feature
+#define __has_feature(x) 0
+#endif
+#ifndef __has_attribute
+#define __has_attribute(x) 0
+#endif
+#ifndef __has_extension
+#define __has_extension(x) __has_feature
+#endif
+
+/* CFEnum macro for type definitions */
+#if (__cplusplus && __cplusplus >= 201103L)
+#define CF_ENUM(_type, _name) _type _name; enum : _type
+#define CF_OPTIONS(_type, _name) _type _name; enum : _type
+#else
+#define CF_ENUM(_type, _name) _type _name; enum
+#define CF_OPTIONS(_type, _name) _type _name; enum
+#endif
+
+#endif /* __COREFOUNDATION_CFAVAILABILITY_H__ */
+
diff --git a/gcc/testsuite/objc-obj-c++-shared/GNUStep/CoreFoundation/CFBase.h b/gcc/testsuite/objc-obj-c++-shared/GNUStep/CoreFoundation/CFBase.h
new file mode 100644
index 0000000..2df7b29
--- /dev/null
+++ b/gcc/testsuite/objc-obj-c++-shared/GNUStep/CoreFoundation/CFBase.h
@@ -0,0 +1,464 @@
+/* CFBase.h
+
+ Copyright (C) 2010 Free Software Foundation, Inc.
+
+ Written by: Stefan Bidigaray
+ Date: January, 2010
+
+ This file is part of the GNUstep CoreBase Library.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; see the file COPYING.LIB.
+ If not, see <http://www.gnu.org/licenses/> or write to the
+ Free Software Foundation, 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+
+#ifndef __COREFOUNDATION_CFBASE_H__
+#define __COREFOUNDATION_CFBASE_H__
+
+/* CoreFoundation defines __LITTLE_ENDIAN__ or __BIG_ENDIAN__ so we'll
+ * do the same here for compatibility.
+ */
+#if !defined(__LITTLE_ENDIAN__) && !defined(__BIG_ENDIAN__)
+#define __LITTLE_ENDIAN__ 1
+#endif
+
+#include "CFAvailability.h"
+#include "../GNUstepBase/GSVersionMacros.h"
+
+/*
+ * CoreFoundation types
+ */
+typedef unsigned char Boolean;
+typedef unsigned char UInt8;
+typedef signed char SInt8;
+typedef unsigned short UInt16;
+typedef signed short SInt16;
+typedef unsigned int UInt32;
+typedef signed int SInt32;
+typedef unsigned long long UInt64;
+typedef signed long long SInt64;
+typedef SInt32 OSStatus;
+
+typedef float Float32;
+typedef double Float64;
+typedef UInt16 UniChar;
+typedef UInt8 *StringPtr;
+typedef const StringPtr *ConstStringPtr;
+typedef UInt8 Str255[256];
+typedef const Str255 *ConstStr255Param;
+typedef SInt16 OSErr;
+typedef SInt16 RegionCode;
+typedef SInt16 LangCode;
+typedef SInt16 ScriptCode;
+typedef UInt32 FourCharCode;
+#ifndef OSTYPE_DECLARED
+typedef FourCharCode OSType;
+#define OSTYPE_DECLARED
+#endif
+typedef UInt8 Byte;
+typedef SInt8 SignedByte;
+
+#ifndef UTF32Char /* UTF32Char is also defined in GSConfig.h */
+typedef UInt32 UTF32Char;
+#endif
+typedef UInt16 UTF16Char;
+typedef UInt8 UTF8Char;
+
+#if !defined(CF_EXTERN_C_BEGIN)
+#if defined(__cplusplus)
+#define CF_EXTERN_C_BEGIN extern "C" {
+#define CF_EXTERN_C_END }
+#else
+#define CF_EXTERN_C_BEGIN
+#define CF_EXTERN_C_END
+#endif
+#endif
+
+#if defined(_WIN32)
+#if defined(BUILDING_SELF)
+#if defined(__cplusplus)
+#define CF_EXPORT extern "C" __declspec(dllexport)
+#else
+#define CF_EXPORT extern __declspec(dllexport)
+#endif
+#else
+#if defined(__cplusplus)
+#define CF_EXPORT extern "C" __declspec(dllimport)
+#else
+#define CF_EXPORT extern __declspec(dllimport)
+#endif
+#endif
+#else
+#if defined(__cplusplus)
+#define CF_EXPORT extern "C"
+#else
+#define CF_EXPORT extern
+#endif
+#endif
+
+#if !defined(__bool_true_false_are_defined)
+#define true 1
+#define false 0
+#endif
+
+#ifndef TRUE
+#define TRUE 1
+#endif
+#ifndef FALSE
+#define FALSE 0
+#endif
+
+#if !defined(CF_INLINE)
+#if defined(__GNUC__) && (__GNUC__ >= 4)
+#define CF_INLINE static __inline__ __attribute__((always_inline))
+#elif defined(__GNUC__)
+#define CF_INLINE static __inline__
+#elif defined(__MWERKS__) || defined(__cplusplus)
+#define CF_INLINE static inline
+#elif defined(_MSC_VER)
+#define CF_INLINE static __inline
+#elif _WIN32
+#define CF_INLINE static __inline__
+#else
+#define CF_INLINE static inline
+#endif
+#endif
+
+#if defined(__GNUC__) || defined(__llvm__)
+#define GS_PURE_FUNCTION __attribute__((pure))
+#else
+#define GS_PURE_FUNCTION
+#endif
+
+CF_EXTERN_C_BEGIN
+/** \defgroup CFTypeRef CFType Reference
+ \{
+ */
+typedef unsigned long CFTypeID;
+typedef const void *CFTypeRef;
+/** @}
+ */
+
+/** \defgroup BaseUtils Base Utilities
+ \{
+ */
+/** An integer value to store a hash code. */
+typedef unsigned long CFHashCode;
+/** A bitfield for passing information to functions. Can hold as many bits
+ as a word.
+ */
+typedef unsigned long CFOptionFlags;
+/** A signed integer representing an index, size, length or count. */
+typedef signed long CFIndex;
+
+/** A structure that represents a range of items in a container, such as
+ an array.
+ */
+typedef struct CFRange CFRange;
+struct CFRange
+{
+ CFIndex location;
+ /**< An integer representing the start location of the range, inclusive. */
+ CFIndex length;
+ /**< An integer representing the total number of items in the range */
+};
+
+/** Creates a CFRange structure.
+ \param location The starting location.
+ \param length The length.
+ \return An initialized CFRange structure.
+ */
+CF_INLINE CFRange
+CFRangeMake (CFIndex location, CFIndex length)
+{
+ CFRange range;
+
+ range.location = location;
+ range.length = length;
+ return range;
+}
+
+/* Returned by comparison functions */
+typedef enum
+{
+ kCFCompareLessThan = -1,
+ kCFCompareEqualTo = 0,
+ kCFCompareGreaterThan = 1
+} CFComparisonResult;
+
+/* Return when a value is not found */
+enum
+{
+ kCFNotFound = -1
+};
+
+/* Definition for standard comparison function callback. */
+typedef CFComparisonResult (*CFComparatorFunction) (const void *val1,
+ const void *val2,
+ void *context);
+
+/* CoreFoundation version numbers */
+/** \name Library Version Numbers
+ \{
+ */
+CF_EXPORT const double kCFCoreFoundationVersionNumber;
+#define kCFCoreFoundationVersionNumber10_0 196.40
+#define kCFCoreFoundationVersionNumber10_0_3 196.50
+#define kCFCoreFoundationVersionNumber10_1 226.00
+#define kCFCoreFoundationVersionNumber10_1_1 226.00
+#define kCFCoreFoundationVersionNumber10_1_2 227.20
+#define kCFCoreFoundationVersionNumber10_1_3 227.20
+#define kCFCoreFoundationVersionNumber10_1_4 227.30
+#define kCFCoreFoundationVersionNumber10_2 263.00
+#define kCFCoreFoundationVersionNumber10_2_1 263.10
+#define kCFCoreFoundationVersionNumber10_2_2 263.10
+#define kCFCoreFoundationVersionNumber10_2_3 263.30
+#define kCFCoreFoundationVersionNumber10_2_4 263.30
+#define kCFCoreFoundationVersionNumber10_2_5 263.50
+#define kCFCoreFoundationVersionNumber10_2_6 263.50
+#define kCFCoreFoundationVersionNumber10_2_7 263.50
+#define kCFCoreFoundationVersionNumber10_2_8 263.50
+#define kCFCoreFoundationVersionNumber10_3 299.00
+#define kCFCoreFoundationVersionNumber10_3_1 299.00
+#define kCFCoreFoundationVersionNumber10_3_2 299.00
+#define kCFCoreFoundationVersionNumber10_3_3 299.30
+#define kCFCoreFoundationVersionNumber10_3_4 299.31
+#define kCFCoreFoundationVersionNumber10_3_5 299.31
+#define kCFCoreFoundationVersionNumber10_3_6 299.32
+#define kCFCoreFoundationVersionNumber10_3_7 299.33
+#define kCFCoreFoundationVersionNumber10_3_8 299.33
+#define kCFCoreFoundationVersionNumber10_3_9 299.35
+#define kCFCoreFoundationVersionNumber10_4 368.00
+#define kCFCoreFoundationVersionNumber10_4_1 368.10
+#define kCFCoreFoundationVersionNumber10_4_2 368.11
+#define kCFCoreFoundationVersionNumber10_4_3 368.18
+#define kCFCoreFoundationVersionNumber10_4_4_Intel 368.26
+#define kCFCoreFoundationVersionNumber10_4_4_PowerPC 368.25
+#define kCFCoreFoundationVersionNumber10_4_5_Intel 368.26
+#define kCFCoreFoundationVersionNumber10_4_5_PowerPC 368.25
+#define kCFCoreFoundationVersionNumber10_4_6_Intel 368.26
+#define kCFCoreFoundationVersionNumber10_4_6_PowerPC 368.25
+#define kCFCoreFoundationVersionNumber10_4_7 368.27
+#define kCFCoreFoundationVersionNumber10_4_8 368.27
+#define kCFCoreFoundationVersionNumber10_4_9 368.28
+#define kCFCoreFoundationVersionNumber10_4_10 368.28
+#define kCFCoreFoundationVersionNumber10_4_11 368.31
+#define kCFCoreFoundationVersionNumber10_5 476.00
+#define kCFCoreFoundationVersionNumber10_5_1 476.00
+#define kCFCoreFoundationVersionNumber10_5_2 476.10
+#define kCFCoreFoundationVersionNumber10_5_3 476.13
+#define kCFCoreFoundationVersionNumber10_5_4 476.14
+#define kCFCoreFoundationVersionNumber10_5_5 476.15
+#define kCFCoreFoundationVersionNumber10_5_6 476.17
+/** \} */
+/** \} */
+
+#if __has_feature(attribute_cf_returns_retained)
+#define CF_RETURNS_RETAINED __attribute__((cf_returns_retained))
+#else
+#define CF_RETURNS_RETAINED
+#endif
+
+#if __has_feature(attribute_cf_returns_not_retained)
+#define CF_RETURNS_NOT_RETAINED __attribute__((cf_returns_not_retained))
+#else
+#define CF_RETURNS_NOT_RETAINED
+#endif
+
+/** \ingroup CFPropertyListRef
+ */
+typedef CFTypeRef CFPropertyListRef;
+
+/** \ingroup CFStringRef
+ */
+typedef const struct __CFString *CFStringRef;
+/** \ingroup CFMutableStringRef
+ */
+typedef struct __CFString *CFMutableStringRef;
+
+
+
+/** \defgroup CFAllocatorRef CFAllocator Reference
+ \brief CFAllocator is an opaque type used to allocate and deallocate
+ memory.
+ \{
+ */
+/** \brief A reference to a CFAllocator object.
+ */
+typedef const struct __CFAllocator *CFAllocatorRef;
+
+typedef void *(*CFAllocatorAllocateCallBack) (CFIndex allocSize,
+ CFOptionFlags hint, void *info);
+typedef void (*CFAllocatorDeallocateCallBack) (void *ptr, void *info);
+typedef void *(*CFAllocatorReallocateCallBack) (void *ptr,
+ CFIndex newsize,
+ CFOptionFlags hint, void *info);
+typedef CFIndex (*CFAllocatorPreferredSizeCallBack) (CFIndex size,
+ CFOptionFlags hint,
+ void *info);
+typedef const void *(*CFAllocatorRetainCallBack) (const void *info);
+typedef void (*CFAllocatorReleaseCallBack) (const void *info);
+typedef CFStringRef (*CFAllocatorCopyDescriptionCallBack) (const void *info);
+
+struct _CFAllocatorContext
+{
+ CFIndex version;
+ void *info;
+ CFAllocatorRetainCallBack retain;
+ CFAllocatorReleaseCallBack release;
+ CFAllocatorCopyDescriptionCallBack copyDescription;
+ CFAllocatorAllocateCallBack allocate;
+ CFAllocatorReallocateCallBack reallocate;
+ CFAllocatorDeallocateCallBack deallocate;
+ CFAllocatorPreferredSizeCallBack preferredSize;
+};
+typedef struct _CFAllocatorContext CFAllocatorContext;
+
+/** The default allocator and is equivalent to NULL.
+ \see CFAllocatorGetDefault()
+ \see CFAllocatorSetDefault()
+ */
+CF_EXPORT CFAllocatorRef kCFAllocatorDefault;
+/** The default system allocator is used internally by GNUstep and is the
+ default allocator if none is been defined.
+ \see CFAllocatorSetDefault()
+ */
+CF_EXPORT CFAllocatorRef kCFAllocatorSystemDefault;
+/** An allocator that uses the system's malloc, realloc and free functions.
+ */
+CF_EXPORT CFAllocatorRef kCFAllocatorMalloc;
+#if OS_API_VERSION(MAC_OS_X_VERSION_10_4, GS_API_LATEST)
+/** Equivalent to kCFAllocatorSystemDefault
+ */
+CF_EXPORT CFAllocatorRef kCFAllocatorMallocZone;
+#endif
+/** The NULL allocator does perform any operations. Can be passed as
+ a deallocator if you do not want GNUstep to deallocate the data.
+ */
+CF_EXPORT CFAllocatorRef kCFAllocatorNull;
+/** This is a special case allocator directing CFAllocatorCreate() to use
+ the given CFAllocatorContext structure to allocate the new allocator.
+ */
+CF_EXPORT CFAllocatorRef kCFAllocatorUseContext;
+
+/** Create a new CFAllocator.
+ \param allocator The allocator used to create this allocator or
+ kCFAllocatorUseContext to use the functions in \b context.
+ \param context The new allocator's context functions.
+ \return A new CFAllocator or NULL in case of failure.
+ \see CFAllocatorContext
+ */
+CF_EXPORT CFAllocatorRef
+CFAllocatorCreate (CFAllocatorRef allocator, CFAllocatorContext * context);
+
+/** Allocate new memory.
+ \param allocator The CFAllocator to use.
+ \param size The number of bytes to allocate.
+ \param hint Option flags. Currently unused and should be 0.
+ \return Newly allocated memory of NULL in case of failure.
+ \see CFAllocatorDeallocate()
+ */
+CF_EXPORT void *CFAllocatorAllocate (CFAllocatorRef allocator, CFIndex size,
+ CFOptionFlags hint);
+
+/** Deallocate the memory pointed to by \b ptr.
+ \param allocator The CFAllocator to use.
+ \param ptr A pointer previously allocated by CFAllocatorAllocate().
+ \see CFAllocatorAllocate()
+ */
+CF_EXPORT void CFAllocatorDeallocate (CFAllocatorRef allocator, void *ptr);
+
+CF_EXPORT CFIndex
+CFAllocatorGetPreferredSizeForSize (CFAllocatorRef allocator, CFIndex size,
+ CFOptionFlags hint);
+
+CF_EXPORT void *CFAllocatorReallocate (CFAllocatorRef allocator, void *ptr,
+ CFIndex newsize, CFOptionFlags hint);
+
+CF_EXPORT CFAllocatorRef CFAllocatorGetDefault (void);
+
+CF_EXPORT void CFAllocatorSetDefault (CFAllocatorRef allocator);
+
+CF_EXPORT void
+CFAllocatorGetContext (CFAllocatorRef allocator, CFAllocatorContext * context);
+
+CF_EXPORT CFTypeID CFAllocatorGetTypeID (void);
+/** \} */
+
+
+
+/** \ingroup CFTypeRef
+ \{
+ */
+/* These function will be implemented in CFRuntime.c since they
+ require runtime support. */
+CF_EXPORT CFStringRef CFCopyDescription (CFTypeRef cf);
+
+CF_EXPORT CFStringRef CFCopyTypeIDDescription (CFTypeID typeID);
+
+CF_EXPORT Boolean CFEqual (CFTypeRef cf1, CFTypeRef cf2);
+
+CF_EXPORT CFAllocatorRef CFGetAllocator (CFTypeRef cf);
+
+CF_EXPORT CFIndex CFGetRetainCount (CFTypeRef cf);
+
+CF_EXPORT CFTypeID CFGetTypeID (CFTypeRef cf);
+
+CF_EXPORT CFHashCode CFHash (CFTypeRef cf);
+
+#if OS_API_VERSION(MAC_OS_X_VERSION_10_4, GS_API_LATEST)
+CF_EXPORT CFTypeRef CFMakeCollectable (CFTypeRef cf);
+#endif
+
+CF_EXPORT void CFRelease (CFTypeRef cf);
+
+CF_EXPORT CFTypeRef CFRetain (CFTypeRef cf);
+
+CF_EXPORT CFTypeRef CFAutorelease(CFTypeRef arg);
+
+#if OS_API_VERSION(MAC_OS_X_VERSION_10_7, GS_API_LATEST)
+CF_EXPORT void *_CFBridgingRelease (CFTypeRef cf);
+CF_EXPORT CFTypeRef _CFBridgingRetain (void *obj);
+
+#if __has_feature(objc_arc)
+#define CFBridgingRetain(x) (__bridge_retained CFTypeRef)(x)
+#define CFBridgingRelease(x) (__bridge_transfer id)(x)
+#elif __OBJC__
+#define CFBridgingRetain(x) _CFBridgingRetain((void *)(x))
+#define CFBridgingRelease(x) (id)_CFBridgingRelease((x))
+#else
+#define CFBridgingRetain(x) _CFBridgingRetain((void *)(x))
+#define CFBridgingRelease(x) _CFBridgingRelease((x))
+#endif
+#endif
+/** \} */
+
+
+
+/** \defgroup CFNullRef CFNull Reference
+ \{
+ */
+#if OS_API_VERSION(MAC_OS_X_VERSION_10_2, GS_API_LATEST)
+typedef struct __CFNull *CFNullRef;
+
+CF_EXPORT CFNullRef kCFNull;
+
+CFTypeID CFNullGetTypeID (void);
+#endif
+/** \} */
+
+CF_EXTERN_C_END
+#endif /* __COREFOUNDATION_CFBASE_H__ */
diff --git a/gcc/testsuite/objc-obj-c++-shared/GNUStep/CoreFoundation/CFCharacterSet.h b/gcc/testsuite/objc-obj-c++-shared/GNUStep/CoreFoundation/CFCharacterSet.h
new file mode 100644
index 0000000..1cb6c66
--- /dev/null
+++ b/gcc/testsuite/objc-obj-c++-shared/GNUStep/CoreFoundation/CFCharacterSet.h
@@ -0,0 +1,173 @@
+/* CFCharacterSet.h
+
+ Copyright (C) 2012 Free Software Foundation, Inc.
+
+ Written by: Stefan Bidigaray
+ Date: January, 2012
+
+ This file is part of the GNUstep CoreBase Library.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; see the file COPYING.LIB.
+ If not, see <http://www.gnu.org/licenses/> or write to the
+ Free Software Foundation, 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef __COREFOUNDATION_CFCHARACTERSET_H__
+#define __COREFOUNDATION_CFCHARACTERSET_H__
+
+#include "CFBase.h"
+#include "CFData.h"
+
+CF_EXTERN_C_BEGIN
+
+/** \ingroup CFCharacterSetRef */
+typedef const struct __CFCharacterSet * CFCharacterSetRef;
+/** \ingroup CFMutableCharacterSetRef */
+typedef struct __CFCharacterSet * CFMutableCharacterSetRef;
+
+/** \defgroup CFCharacterSetRef CFCharacterSet Reference
+ \{
+ */
+typedef enum
+{
+ kCFCharacterSetControl = 1,
+ kCFCharacterSetWhitespace,
+ kCFCharacterSetWhitespaceAndNewline,
+ kCFCharacterSetDecimalDigit,
+ kCFCharacterSetLetter,
+ kCFCharacterSetLowercaseLetter,
+ kCFCharacterSetUppercaseLetter,
+ kCFCharacterSetNonBase,
+ kCFCharacterSetDecomposable,
+ kCFCharacterSetAlphaNumeric,
+ kCFCharacterSetPunctuation,
+#if OS_API_VERSION(MAC_OS_X_VERSION_10_2, GS_API_LATEST)
+ kCFCharacterSetCapitalizedLetter = 13,
+#endif
+#if OS_API_VERSION(MAC_OS_X_VERSION_10_3, GS_API_LATEST)
+ kCFCharacterSetSymbol = 14,
+#endif
+#if OS_API_VERSION(MAC_OS_X_VERSION_10_5, GS_API_LATEST)
+ kCFCharacterSetNewline = 15,
+#endif
+ kCFCharacterSetIllegal = 12
+} CFCharacterSetPredefinedSet;
+
+
+
+/** \name Creating Character Sets
+ \{
+ */
+#if OS_API_VERSION(MAC_OS_X_VERSION_10_3, GS_API_LATEST)
+CF_EXPORT CFCharacterSetRef
+CFCharacterSetCreateCopy (CFAllocatorRef alloc, CFCharacterSetRef set);
+#endif
+
+#if OS_API_VERSION(MAC_OS_X_VERSION_10_2, GS_API_LATEST)
+CF_EXPORT CFCharacterSetRef
+CFCharacterSetCreateInvertedSet (CFAllocatorRef alloc, CFCharacterSetRef set);
+#endif
+
+CF_EXPORT CFCharacterSetRef
+CFCharacterSetCreateWithCharactersInRange (CFAllocatorRef alloc,
+ CFRange range);
+
+CF_EXPORT CFCharacterSetRef
+CFCharacterSetCreateWithCharactersInString (CFAllocatorRef alloc,
+ CFStringRef string);
+
+CF_EXPORT CFCharacterSetRef
+CFCharacterSetCreateWithBitmapRepresentation (CFAllocatorRef alloc,
+ CFDataRef data);
+/** \} */
+
+/** \name Getting Predefined Character Sets
+ \{
+ */
+CF_EXPORT CFCharacterSetRef
+CFCharacterSetGetPredefined (CFCharacterSetPredefinedSet setIdentifier);
+/** \} */
+
+/** \name Querying Character Sets
+ \{
+ */
+CF_EXPORT CFDataRef
+CFCharacterSetCreateBitmapRepresentation (CFAllocatorRef alloc,
+ CFCharacterSetRef set);
+
+CF_EXPORT Boolean
+CFCharacterSetIsCharacterMember (CFCharacterSetRef set, UniChar c);
+
+#if OS_API_VERSION(MAC_OS_X_VERSION_10_2, GS_API_LATEST)
+CF_EXPORT Boolean
+CFCharacterSetHasMemberInPlane (CFCharacterSetRef set, CFIndex plane);
+
+CF_EXPORT Boolean
+CFCharacterSetIsLongCharacterMember (CFCharacterSetRef set, UTF32Char c);
+
+CF_EXPORT Boolean
+CFCharacterSetIsSupersetOfSet (CFCharacterSetRef set,
+ CFCharacterSetRef otherSet);
+#endif
+/** \} */
+
+/** \name Getting the Character Set Type Identifier
+ \{
+ */
+CF_EXPORT CFTypeID
+CFCharacterSetGetTypeID (void);
+/** \} */
+/** \} */
+
+/** \defgroup CFMutableCharacterSetRef CFMutableCharacterSet Reference
+ \{
+ */
+CF_EXPORT CFMutableCharacterSetRef
+CFCharacterSetCreateMutable (CFAllocatorRef alloc);
+
+CF_EXPORT CFMutableCharacterSetRef
+CFCharacterSetCreateMutableCopy (CFAllocatorRef alloc, CFCharacterSetRef set);
+
+CF_EXPORT void
+CFCharacterSetAddCharactersInRange (CFMutableCharacterSetRef set,
+ CFRange range);
+
+CF_EXPORT void
+CFCharacterSetAddCharactersInString (CFMutableCharacterSetRef set,
+ CFStringRef string);
+
+CF_EXPORT void
+CFCharacterSetRemoveCharactersInRange (CFMutableCharacterSetRef set,
+ CFRange range);
+
+CF_EXPORT void
+CFCharacterSetRemoveCharactersInString (CFMutableCharacterSetRef set,
+ CFStringRef string);
+
+CF_EXPORT void
+CFCharacterSetIntersect (CFMutableCharacterSetRef set,
+ CFCharacterSetRef otherSet);
+
+CF_EXPORT void
+CFCharacterSetInvert (CFMutableCharacterSetRef set);
+
+CF_EXPORT void
+CFCharacterSetUnion (CFMutableCharacterSetRef set, CFCharacterSetRef otherSet);
+/** \} */
+
+CF_EXTERN_C_END
+
+#endif /* __COREFOUNDATION_CFCHARACTERSET_H__ */
+
diff --git a/gcc/testsuite/objc-obj-c++-shared/GNUStep/CoreFoundation/CFData.h b/gcc/testsuite/objc-obj-c++-shared/GNUStep/CoreFoundation/CFData.h
new file mode 100644
index 0000000..9e98a69
--- /dev/null
+++ b/gcc/testsuite/objc-obj-c++-shared/GNUStep/CoreFoundation/CFData.h
@@ -0,0 +1,114 @@
+/* CFData.h
+
+ Copyright (C) 2010 Free Software Foundation, Inc.
+
+ Written by: Stefan Bidigaray
+ Date: January, 2010
+
+ This file is part of CoreBase.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; see the file COPYING.LIB.
+ If not, see <http://www.gnu.org/licenses/> or write to the
+ Free Software Foundation, 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef __COREFOUNDATION_CFDATA_H__
+#define __COREFOUNDATION_CFDATA_H__
+
+#include "CFBase.h"
+
+CF_EXTERN_C_BEGIN
+/** \ingroup CFDataRef */
+typedef const struct __CFData *CFDataRef;
+/** \ingroup CFMutableDataRef */
+typedef struct __CFData *CFMutableDataRef;
+
+/** \defgroup CFDataRef CFData Reference
+ \{
+ */
+/** \name Creating a CFData Object
+ \{
+ */
+CF_EXPORT CFDataRef
+CFDataCreate (CFAllocatorRef allocator, const UInt8 * bytes, CFIndex length);
+
+CF_EXPORT CFDataRef
+CFDataCreateCopy (CFAllocatorRef allocator, CFDataRef theData);
+
+CF_EXPORT CFDataRef
+CFDataCreateWithBytesNoCopy (CFAllocatorRef allocator, const UInt8 * bytes,
+ CFIndex length, CFAllocatorRef bytesDeallocator);
+/** \} */
+
+/** \name Examining a CFData Object
+ \{
+ */
+CF_EXPORT const UInt8 *CFDataGetBytePtr (CFDataRef theData);
+
+CF_EXPORT void
+CFDataGetBytes (CFDataRef theData, CFRange range, UInt8 * buffer);
+
+CF_EXPORT CFIndex CFDataGetLength (CFDataRef theData);
+/** \} */
+
+/** \name Getting the CFData Type ID
+ \{
+ */
+CF_EXPORT CFTypeID CFDataGetTypeID (void);
+/** \} */
+/** \} */
+
+/** \defgroup CFMutableDataRef CFMutableData Reference
+ \{
+ */
+/** \name Creating a Mutable Data Object
+ \{
+ */
+CF_EXPORT CFMutableDataRef
+CFDataCreateMutable (CFAllocatorRef allocator, CFIndex capacity);
+
+CF_EXPORT CFMutableDataRef
+CFDataCreateMutableCopy (CFAllocatorRef allocator, CFIndex capacity,
+ CFDataRef theData);
+/** \} */
+
+/** \name Accessing Mutable Data
+ \{
+ */
+CF_EXPORT UInt8 *CFDataGetMutableBytePtr (CFMutableDataRef theData);
+/** \} */
+
+/** \name Modifying a Mutable Data Object
+ \{
+ */
+CF_EXPORT void
+CFDataAppendBytes (CFMutableDataRef theData, const UInt8 * bytes,
+ CFIndex length);
+
+CF_EXPORT void CFDataDeleteBytes (CFMutableDataRef theData, CFRange range);
+
+CF_EXPORT void
+CFDataReplaceBytes (CFMutableDataRef theData, CFRange range,
+ const UInt8 * newBytes, CFIndex newLength);
+
+CF_EXPORT void
+CFDataIncreaseLength (CFMutableDataRef theData, CFIndex extraLength);
+
+CF_EXPORT void CFDataSetLength (CFMutableDataRef theData, CFIndex length);
+/** \} */
+/** \} */
+
+CF_EXTERN_C_END
+#endif /* __COREFOUNDATION_CFDATA_H__ */
diff --git a/gcc/testsuite/objc-obj-c++-shared/GNUStep/CoreFoundation/CFDictionary.h b/gcc/testsuite/objc-obj-c++-shared/GNUStep/CoreFoundation/CFDictionary.h
new file mode 100644
index 0000000..adc0dd8
--- /dev/null
+++ b/gcc/testsuite/objc-obj-c++-shared/GNUStep/CoreFoundation/CFDictionary.h
@@ -0,0 +1,174 @@
+/* CFDictionary.h
+
+ Copyright (C) 2010 Free Software Foundation, Inc.
+
+ Written by: Stefan Bidigaray
+ Date: January, 2010
+
+ This file is part of the GNUstep CoreBase Library.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; see the file COPYING.LIB.
+ If not, see <http://www.gnu.org/licenses/> or write to the
+ Free Software Foundation, 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef __COREFOUNDATION_CFDICTIONARY_H__
+#define __COREFOUNDATION_CFDICTIONARY_H__ 1
+
+#include "CFBase.h"
+
+CF_EXTERN_C_BEGIN
+/** \ingroup CFDictionaryRef */
+typedef const struct __CFDictionary *CFDictionaryRef;
+/** \ingroup CFMutableDictionaryRef */
+typedef struct __CFDictionary *CFMutableDictionaryRef;
+
+/** \defgroup CFDictionaryRef CFDictionary Reference
+ \{
+ */
+typedef void (*CFDictionaryApplierFunction) (const void *key,
+ const void *value, void *context);
+
+typedef CFStringRef (*CFDictionaryCopyDescriptionCallBack) (const void *value);
+typedef Boolean (*CFDictionaryEqualCallBack) (const void *value1,
+ const void *value2);
+typedef CFHashCode (*CFDictionaryHashCallBack) (const void *value);
+typedef void (*CFDictionaryReleaseCallBack) (CFAllocatorRef allocator,
+ const void *value);
+typedef const void *(*CFDictionaryRetainCallBack) (CFAllocatorRef allocator,
+ const void *value);
+
+typedef struct _CFDictionaryKeyCallBacks CFDictionaryKeyCallBacks;
+struct _CFDictionaryKeyCallBacks
+{
+ CFIndex version;
+ CFDictionaryRetainCallBack retain;
+ CFDictionaryReleaseCallBack release;
+ CFDictionaryCopyDescriptionCallBack copyDescription;
+ CFDictionaryEqualCallBack equal;
+ CFDictionaryHashCallBack hash;
+};
+
+typedef struct _CFDictionaryValueCallBacks CFDictionaryValueCallBacks;
+struct _CFDictionaryValueCallBacks
+{
+ CFIndex version;
+ CFDictionaryRetainCallBack retain;
+ CFDictionaryReleaseCallBack release;
+ CFDictionaryCopyDescriptionCallBack copyDescription;
+ CFDictionaryEqualCallBack equal;
+};
+
+CF_EXPORT const CFDictionaryKeyCallBacks kCFCopyStringDictionaryKeyCallBacks;
+CF_EXPORT const CFDictionaryKeyCallBacks kCFTypeDictionaryKeyCallBacks;
+CF_EXPORT const CFDictionaryValueCallBacks kCFTypeDictionaryValueCallBacks;
+
+/** \name Creating a dictionary
+ \{
+ */
+CF_EXPORT CFDictionaryRef
+CFDictionaryCreate (CFAllocatorRef allocator, const void **keys,
+ const void **values, CFIndex numValues,
+ const CFDictionaryKeyCallBacks * keyCallBacks,
+ const CFDictionaryValueCallBacks * valueCallBacks);
+
+CF_EXPORT CFDictionaryRef
+CFDictionaryCreateCopy (CFAllocatorRef allocator, CFDictionaryRef theDict);
+/** \} */
+
+/** \name Examining a dictionary
+ \{
+ */
+CF_EXPORT Boolean
+CFDictionaryContainsKey (CFDictionaryRef theDict, const void *key);
+
+CF_EXPORT Boolean
+CFDictionaryContainsValue (CFDictionaryRef theDict, const void *value);
+
+CF_EXPORT CFIndex CFDictionaryGetCount (CFDictionaryRef theDict);
+
+CF_EXPORT CFIndex
+CFDictionaryGetCountOfKey (CFDictionaryRef theDict, const void *key);
+
+CF_EXPORT CFIndex
+CFDictionaryGetCountOfValue (CFDictionaryRef theDict, const void *value);
+
+CF_EXPORT void
+CFDictionaryGetKeysAndValues (CFDictionaryRef theDict, const void **keys,
+ const void **values);
+
+CF_EXPORT const void *CFDictionaryGetValue (CFDictionaryRef theDict,
+ const void *key);
+
+CF_EXPORT Boolean
+CFDictionaryGetValueIfPresent (CFDictionaryRef theDict, const void *key,
+ const void **value);
+/** \} */
+
+/** \name Applying a funcation to a dictionary
+ \{
+ */
+CF_EXPORT void
+CFDictionaryApplyFunction (CFDictionaryRef theDict,
+ CFDictionaryApplierFunction applier, void *context);
+/** \} */
+
+/** \name Getting the CFDictionary type ID
+ \{
+ */
+CF_EXPORT CFTypeID CFDictionaryGetTypeID (void);
+/** \} */
+/** \} */
+
+/** \defgroup CFMutableDictionaryRef CFMutableDictionary Reference
+ \{
+ */
+/** \name Creating a Mutable Dictionary
+ \{
+ */
+CF_EXPORT CFMutableDictionaryRef
+CFDictionaryCreateMutable (CFAllocatorRef allocator, CFIndex capacity,
+ const CFDictionaryKeyCallBacks * keyCallBacks,
+ const CFDictionaryValueCallBacks * valueCallBacks);
+
+CF_EXPORT CFMutableDictionaryRef
+CFDictionaryCreateMutableCopy (CFAllocatorRef allocator, CFIndex capacity,
+ CFDictionaryRef theDict);
+/** \} */
+
+/** \name Modifying a Dictionary
+ \{
+ */
+CF_EXPORT void
+CFDictionaryAddValue (CFMutableDictionaryRef theDict, const void *key,
+ const void *value);
+
+CF_EXPORT void CFDictionaryRemoveAllValues (CFMutableDictionaryRef theDict);
+
+CF_EXPORT void
+CFDictionaryRemoveValue (CFMutableDictionaryRef theDict, const void *key);
+
+CF_EXPORT void
+CFDictionaryReplaceValue (CFMutableDictionaryRef theDict, const void *key,
+ const void *value);
+
+CF_EXPORT void
+CFDictionarySetValue (CFMutableDictionaryRef theDict, const void *key,
+ const void *value);
+/** \} */
+/** \} */
+
+CF_EXTERN_C_END
+#endif /* __COREFOUNDATION_CFDICTIONARY_H__ */
diff --git a/gcc/testsuite/objc-obj-c++-shared/GNUStep/CoreFoundation/CFLocale.h b/gcc/testsuite/objc-obj-c++-shared/GNUStep/CoreFoundation/CFLocale.h
new file mode 100644
index 0000000..7ae082d
--- /dev/null
+++ b/gcc/testsuite/objc-obj-c++-shared/GNUStep/CoreFoundation/CFLocale.h
@@ -0,0 +1,249 @@
+/* CFLocale.h
+
+ Copyright (C) 2010 Free Software Foundation, Inc.
+
+ Written by: Stefan Bidigaray
+ Date: March, 2011
+
+ This file is part of the GNUstep CoreBase Library.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; see the file COPYING.LIB.
+ If not, see <http://www.gnu.org/licenses/> or write to the
+ Free Software Foundation, 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef __COREFOUNDATION_CFLOCALE__
+#define __COREFOUNDATION_CFLOCALE__ 1
+
+#include "CFBase.h"
+
+#include "CFArray.h"
+#include "CFDictionary.h"
+
+#if OS_API_VERSION(MAC_OS_X_VERSION_10_3, GS_API_LATEST)
+
+CF_EXTERN_C_BEGIN
+
+/** \defgroup CFLocaleRef CFLocale Reference
+ \brief CFLocale provides basic functionality for language and/or region
+ specific operations.
+
+ Locale-sensitive operations, such as collation, calendars and
+ capitalization, may use CFLocale objects to provide language and/or region
+ specific functionality.
+
+ CFLocale is "toll-free bridged" to NSLocale.
+
+ \{
+ */
+typedef const struct __CFLocale *CFLocaleRef;
+
+/**
+ */
+enum
+{
+ kCFLocaleLanguageDirectionUnknown = 0,
+ kCFLocaleLanguageDirectionLeftToRight = 1,
+ kCFLocaleLanguageDirectionRightToLeft = 2,
+ kCFLocaleLanguageDirectionTopToBottom = 3,
+ kCFLocaleLanguageDirectionBottomToTop = 4
+};
+typedef CFIndex CFLocaleLanguageDirection;
+
+/** \name CFLocale Property Keys
+ \{
+ */
+CF_EXPORT const CFStringRef kCFLocaleMeasurementSystem; /* CFString */
+CF_EXPORT const CFStringRef kCFLocaleDecimalSeparator; /* CFString */
+CF_EXPORT const CFStringRef kCFLocaleGroupingSeparator; /* CFString */
+CF_EXPORT const CFStringRef kCFLocaleCurrencySymbol; /* CFString */
+CF_EXPORT const CFStringRef kCFLocaleCurrencyCode; /* CFString */
+#if OS_API_VERSION(MAC_OS_X_VERSION_10_4, GS_API_LATEST)
+CF_EXPORT const CFStringRef kCFLocaleIdentifier; /* CFString */
+CF_EXPORT const CFStringRef kCFLocaleLanguageCode; /* CFString */
+CF_EXPORT const CFStringRef kCFLocaleCountryCode; /* CFString */
+CF_EXPORT const CFStringRef kCFLocaleScriptCode; /* CFString */
+CF_EXPORT const CFStringRef kCFLocaleVariantCode; /* CFString */
+CF_EXPORT const CFStringRef kCFLocaleExemplarCharacterSet; /* CFCharacterSet */
+CF_EXPORT const CFStringRef kCFLocaleCalendarIdentifier; /* CFString */
+CF_EXPORT const CFStringRef kCFLocaleCalendar; /* CFCalendar */
+CF_EXPORT const CFStringRef kCFLocaleCollationIdentifier; /* CFString */
+CF_EXPORT const CFStringRef kCFLocaleUsesMetricSystem; /* CFBoolean */
+#endif
+#if OS_API_VERSION(MAC_OS_X_VERSION_10_6, GS_API_LATEST)
+CF_EXPORT const CFStringRef kCFLocaleCollatorIdentifier; /* CFString */
+CF_EXPORT const CFStringRef kCFLocaleQuotationBeginDelimiterKey; /* CFString */
+CF_EXPORT const CFStringRef kCFLocaleQuotationEndDelimiterKey; /* CFString */
+CF_EXPORT const CFStringRef kCFLocaleAlternateQuotationBeginDelimiterKey; /* CFString */
+CF_EXPORT const CFStringRef kCFLocaleAlternateQuotationEndDelimiterKey; /* CFString */
+#endif
+/** \} */
+
+/** \name CFCalendar Identifiers
+ \{
+ */
+CF_EXPORT const CFStringRef kCFGregorianCalendar;
+#if OS_API_VERSION(MAC_OS_X_VERSION_10_4, GS_API_LATEST)
+CF_EXPORT const CFStringRef kCFBuddhistCalendar;
+CF_EXPORT const CFStringRef kCFChineseCalendar;
+CF_EXPORT const CFStringRef kCFHebrewCalendar;
+CF_EXPORT const CFStringRef kCFIslamicCalendar;
+CF_EXPORT const CFStringRef kCFIslamicCivilCalendar;
+CF_EXPORT const CFStringRef kCFJapaneseCalendar;
+#endif
+#if OS_API_VERSION(MAC_OS_X_VERSION_10_6, GS_API_LATEST)
+CF_EXPORT const CFStringRef kCFRepublicOfChinaCalendar;
+CF_EXPORT const CFStringRef kCFPersianCalendar;
+CF_EXPORT const CFStringRef kCFIndianCalendar;
+CF_EXPORT const CFStringRef kCFISO8601Calendar;
+#endif
+/** \} */
+
+/** CFLocale Change Notification
+ */
+CF_EXPORT const CFStringRef kCFLocaleCurrentLocaleDidChangeNotification;
+
+
+
+/** \name Creating a Locale
+ \{
+ */
+CF_EXPORT CFLocaleRef
+CFLocaleCopyCurrent (void);
+
+CF_EXPORT CFLocaleRef
+CFLocaleCreate (CFAllocatorRef allocator,
+ CFStringRef localeIdent);
+
+CF_EXPORT CFLocaleRef
+CFLocaleCreateCopy (CFAllocatorRef allocator,
+ CFLocaleRef locale);
+
+CF_EXPORT CFLocaleRef
+CFLocaleGetSystem (void);
+/** \} */
+
+/** \name Getting System Locale Information
+ \{
+ */
+#if OS_API_VERSION(MAC_OS_X_VERSION_10_4, GS_API_LATEST)
+CF_EXPORT CFArrayRef
+CFLocaleCopyAvailableLocaleIdentifiers (void);
+#endif
+/** \} */
+
+/** \name Getting ISO Information
+ \{
+ */
+#if OS_API_VERSION(MAC_OS_X_VERSION_10_4, GS_API_LATEST)
+CF_EXPORT CFArrayRef
+CFLocaleCopyISOCountryCodes (void);
+
+CF_EXPORT CFArrayRef
+CFLocaleCopyISOLanguageCodes (void);
+
+CF_EXPORT CFArrayRef
+CFLocaleCopyISOCurrencyCodes (void);
+#endif
+
+#if OS_API_VERSION(MAC_OS_X_VERSION_10_5, GS_API_LATEST)
+CF_EXPORT CFArrayRef
+CFLocaleCopyCommonISOCurrencyCodes (void);
+#endif
+/** \{ */
+
+/** \name Accessing Language Information
+ \{
+ */
+#if OS_API_VERSION(MAC_OS_X_VERSION_10_5, GS_API_LATEST)
+CF_EXPORT CFArrayRef
+CFLocaleCopyPreferredLanguages (void);
+#endif
+
+#if OS_API_VERSION(MAC_OS_X_VERSION_10_6, GS_API_LATEST)
+CF_EXPORT CFLocaleLanguageDirection
+CFLocaleGetLanguageCharacterDirection (CFStringRef isoLangCode);
+
+CF_EXPORT CFLocaleLanguageDirection
+CFLocaleGetLanguageLineDirection (CFStringRef isoLangCode);
+#endif
+/** \} */
+
+/** \name Getting Information About a Locale
+ \{
+ */
+CF_EXPORT CFStringRef
+CFLocaleCopyDisplayNameForPropertyValue (CFLocaleRef displayLocale,
+ CFStringRef key,
+ CFStringRef value);
+
+CF_EXPORT CFTypeRef
+CFLocaleGetValue (CFLocaleRef locale,
+ CFStringRef key);
+
+CF_EXPORT CFStringRef
+CFLocaleGetIdentifier (CFLocaleRef locale);
+/** \} */
+
+/** \name Getting and Creating Locale Identifiers
+ \{
+ */
+CF_EXPORT CFStringRef
+CFLocaleCreateCanonicalLocaleIdentifierFromString (CFAllocatorRef allocator,
+ CFStringRef localeIdent);
+
+#if OS_API_VERSION(MAC_OS_X_VERSION_10_4, GS_API_LATEST)
+CF_EXPORT CFStringRef
+CFLocaleCreateCanonicalLanguageIdentifierFromString (CFAllocatorRef allocator,
+ CFStringRef localeIdent);
+
+CF_EXPORT CFDictionaryRef
+CFLocaleCreateComponentsFromLocaleIdentifier (CFAllocatorRef allocator,
+ CFStringRef localeIdent);
+
+CF_EXPORT CFStringRef
+CFLocaleCreateLocaleIdentifierFromComponents (CFAllocatorRef allocator,
+ CFDictionaryRef dictionary);
+#endif
+/** \} */
+
+/** \name Windows Locale Codes
+ \{
+ */
+#if OS_API_VERSION(MAC_OS_X_VERSION_10_6, GS_API_LATEST)
+CF_EXPORT CFStringRef
+CFLocaleCreateLocaleIdentifierFromWindowsLocaleCode (CFAllocatorRef allocator,
+ UInt32 lcid);
+
+CF_EXPORT UInt32
+CFLocaleGetWindowsLocaleCodeFromLocaleIdentifier (CFStringRef localeIdent);
+#endif
+/** \} */
+
+/** \name Getting the CFLocale Type ID
+ \{
+ */
+CF_EXPORT CFTypeID
+CFLocaleGetTypeID (void);
+/** \} */
+
+/** \} */
+
+CF_EXTERN_C_END
+
+#endif /* OS_API_VERSION >= MAC_OS_X_VERSION_10_3 */
+
+#endif /* __COREFOUNDATION_CFLOCALE__ */
+
diff --git a/gcc/testsuite/objc-obj-c++-shared/GNUStep/CoreFoundation/CFString.h b/gcc/testsuite/objc-obj-c++-shared/GNUStep/CoreFoundation/CFString.h
new file mode 100644
index 0000000..42e4967
--- /dev/null
+++ b/gcc/testsuite/objc-obj-c++-shared/GNUStep/CoreFoundation/CFString.h
@@ -0,0 +1,593 @@
+/* CFString.h
+
+ Copyright (C) 2010 Free Software Foundation, Inc.
+
+ Written by: Stefan Bidigaray
+ Date: January, 2010
+
+ This file is part of CoreBase.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; see the file COPYING.LIB.
+ If not, see <http://www.gnu.org/licenses/> or write to the
+ Free Software Foundation, 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef __COREFOUNDATION_CFSTRING_H__
+#define __COREFOUNDATION_CFSTRING_H__
+
+#include "CFBase.h"
+#include "CFArray.h"
+#include "CFCharacterSet.h"
+#include "CFData.h"
+#include "CFDictionary.h"
+#include "CFLocale.h"
+
+#include <stdarg.h>
+
+CF_EXTERN_C_BEGIN
+
+/** \defgroup CFStringRef CFString Reference
+ \brief The CFString type defines opaque objects representing strings.
+
+ CFString is "toll-free bridged" to NSString.
+
+ \{
+ */
+
+/*
+ * Data Types
+ */
+typedef UInt32 CFStringEncoding;
+
+/*
+ * Constants
+ */
+typedef enum
+{
+ kCFCompareCaseInsensitive = 1,
+ kCFCompareBackwards = 4,
+ kCFCompareAnchored = 8,
+ kCFCompareNonliteral = 16,
+ kCFCompareLocalized = 32,
+ kCFCompareNumerically = 64,
+#if OS_API_VERSION(MAC_OS_X_VERSION_10_5, GS_API_LATEST)
+ kCFCompareDiacriticInsensitive = 128,
+ kCFCompareWidthInsensitive = 256,
+ kCFCompareForcedOrdering = 512
+#endif
+} CFStringCompareFlags;
+
+enum CFStringBuiltInEncodings
+{
+ kCFStringEncodingMacRoman = 0,
+ kCFStringEncodingWindowsLatin1 = 0x0500,
+ kCFStringEncodingISOLatin1 = 0x0201,
+ kCFStringEncodingNextStepLatin = 0x0B01,
+ kCFStringEncodingASCII = 0x0600,
+ kCFStringEncodingUnicode = 0x0100,
+ kCFStringEncodingUTF8 = 0x08000100,
+ kCFStringEncodingNonLossyASCII = 0x0BFF,
+#if OS_API_VERSION(MAC_OS_X_VERSION_10_4, GS_API_LATEST)
+ kCFStringEncodingUTF16 = 0x0100,
+ kCFStringEncodingUTF16BE = 0x10000100,
+ kCFStringEncodingUTF16LE = 0x14000100,
+ kCFStringEncodingUTF32 = 0x0c000100,
+ kCFStringEncodingUTF32BE = 0x18000100,
+ kCFStringEncodingUTF32LE = 0x1c000100
+#endif
+};
+
+#if OS_API_VERSION(MAC_OS_X_VERSION_10_2, GS_API_LATEST)
+# define kCFStringEncodingInvalidId (0xffffffffU)
+#endif
+
+/** \def CFSTR(x)
+ \brief Creates a constant string object.
+
+ \note This macro will create the constant string at runtime.
+ */
+/* The 'pure' attribute tells the compiler that this function will always
+ return the same result with the same input. If it has any skill, then
+ constant propagation passes will magically make sure that this function is
+ called as few times as possible. */
+CF_EXPORT CFStringRef
+__CFStringMakeConstantString (const char *str) GS_PURE_FUNCTION;
+//#define CFSTR(x) __CFStringMakeConstantString("" x "")
+
+#ifdef __CONSTANT_CFSTRINGS__
+#define CFSTR(x) ((CFStringRef) __builtin___CFStringMakeConstantString ("" x ""))
+#else
+#define CFSTR(x) __CFStringMakeConstantString("" x "")
+#endif
+
+/** \name Creating a CFString
+ \{
+ */
+CF_EXPORT CFArrayRef
+CFStringCreateArrayBySeparatingStrings (CFAllocatorRef alloc,
+ CFStringRef theString, CFStringRef separatorString);
+
+CF_EXPORT CFStringRef
+CFStringCreateByCombiningStrings (CFAllocatorRef alloc, CFArrayRef theArray,
+ CFStringRef separatorString);
+
+CF_EXPORT CFStringRef
+CFStringCreateCopy (CFAllocatorRef alloc, CFStringRef theString);
+
+CF_EXPORT CFStringRef
+CFStringCreateFromExternalRepresentation (CFAllocatorRef alloc, CFDataRef data,
+ CFStringEncoding encoding);
+
+CF_EXPORT CFStringRef
+CFStringCreateWithBytes (CFAllocatorRef alloc, const UInt8 *bytes,
+ CFIndex numBytes, CFStringEncoding encoding, Boolean isExternalRepresentation);
+
+CF_EXPORT CFStringRef
+CFStringCreateWithCharacters (CFAllocatorRef alloc, const UniChar *chars,
+ CFIndex numChars);
+
+CF_EXPORT CFStringRef
+CFStringCreateWithCharactersNoCopy (CFAllocatorRef alloc, const UniChar *chars,
+ CFIndex numChars, CFAllocatorRef contentsDeallocator);
+
+CF_EXPORT CFStringRef
+CFStringCreateWithCString (CFAllocatorRef alloc, const char *cStr,
+ CFStringEncoding encoding);
+
+CF_EXPORT CFStringRef
+CFStringCreateWithCStringNoCopy (CFAllocatorRef alloc, const char *cStr,
+ CFStringEncoding encoding, CFAllocatorRef contentsDeallocator);
+
+CF_EXPORT CFStringRef
+CFStringCreateWithFormat (CFAllocatorRef alloc, CFDictionaryRef formatOptions,
+ CFStringRef format, ...);
+
+CF_EXPORT CFStringRef
+CFStringCreateWithFormatAndArguments (CFAllocatorRef alloc,
+ CFDictionaryRef formatOptions, CFStringRef format, va_list arguments);
+
+CF_EXPORT CFStringRef
+CFStringCreateWithSubstring (CFAllocatorRef alloc, CFStringRef str,
+ CFRange range);
+
+#if OS_API_VERSION(MAC_OS_X_VERSION_10_4, GS_API_LATEST)
+CF_EXPORT CFStringRef
+CFStringCreateWithFileSystemRepresentation (CFAllocatorRef alloc,
+ const char *buffer);
+#endif
+
+#if OS_API_VERSION(MAC_OS_X_VERSION_10_5, GS_API_LATEST)
+CF_EXPORT CFStringRef
+CFStringCreateWithBytesNoCopy (CFAllocatorRef alloc, const UInt8 *bytes,
+ CFIndex numBytes, CFStringEncoding encoding, Boolean isExternalReprentation,
+ CFAllocatorRef contentsDeallocator);
+#endif
+/** \} */
+
+/** \name Searching CFStrings
+ \{
+ */
+CF_EXPORT CFArrayRef
+CFStringCreateArrayWithFindResults (CFAllocatorRef alloc, CFStringRef theString,
+ CFStringRef stringToFind, CFRange rangeToSearch,
+ CFStringCompareFlags compareOptions);
+
+CF_EXPORT CFRange
+CFStringFind (CFStringRef theString, CFStringRef stringToFind,
+ CFStringCompareFlags compareOptions);
+
+CF_EXPORT Boolean
+CFStringFindWithOptions (CFStringRef theString, CFStringRef stringToFind,
+ CFRange rangeToSearch, CFStringCompareFlags searchOptions, CFRange *result);
+
+CF_EXPORT Boolean
+CFStringFindWithOptionsAndLocale (CFStringRef theString,CFStringRef stringToFind,
+ CFRange rangeToSearch, CFStringCompareFlags searchOptions,
+ CFLocaleRef locale, CFRange *result);
+
+CF_EXPORT void
+CFStringGetLineBounds (CFStringRef theString, CFRange range,
+ CFIndex *lineBeginIndex, CFIndex *lineEndIndex, CFIndex *contentsEndIndex);
+
+#if OS_API_VERSION(MAC_OS_X_VERSION_10_2, GS_API_LATEST)
+CF_EXPORT Boolean
+CFStringFindCharacterFromSet (CFStringRef theString, CFCharacterSetRef theSet,
+ CFRange rangeToSearch, CFStringCompareFlags searchOptions, CFRange *result);
+#endif
+
+#if OS_API_VERSION(MAC_OS_X_VERSION_10_5, GS_API_LATEST)
+CF_EXPORT void
+CFStringGetParagraphBounds (CFStringRef string, CFRange range,
+ CFIndex *parBeginIndex, CFIndex *parEndIndex, CFIndex *contentsEndIndex);
+#endif
+/** \} */
+
+/** \name Comparing String
+ \{
+ */
+CF_EXPORT CFComparisonResult
+CFStringCompare (CFStringRef theString1, CFStringRef theString2,
+ CFStringCompareFlags compareOptions);
+
+CF_EXPORT CFComparisonResult
+CFStringCompareWithOptions (CFStringRef theString1, CFStringRef theString2,
+ CFRange rangeToCOmpare, CFStringCompareFlags compareOptions);
+
+CF_EXPORT Boolean
+CFStringHasPrefix (CFStringRef theString, CFStringRef prefix);
+
+CF_EXPORT Boolean
+CFStringHasSuffix (CFStringRef theString, CFStringRef suffix);
+
+#if OS_API_VERSION(MAC_OS_X_VERSION_10_5, GS_API_LATEST)
+CF_EXPORT CFComparisonResult
+CFStringCompareWithOptionsAndLocale (CFStringRef theString1,
+ CFStringRef theString2, CFRange rangeToCOmpare,
+ CFStringCompareFlags compareOptions, CFLocaleRef locale);
+#endif
+/** \} */
+
+/** \name Accessing Characters
+ \{
+ */
+CF_EXPORT CFDataRef
+CFStringCreateExternalRepresentation (CFAllocatorRef alloc,
+ CFStringRef theString, CFStringEncoding encoding, UInt8 lossByte);
+
+CF_EXPORT CFIndex
+CFStringGetBytes (CFStringRef theString, CFRange range,
+ CFStringEncoding encoding, UInt8 lossByte, Boolean isExternalRepresentation,
+ UInt8 *buffer, CFIndex maxBufLen, CFIndex *usedBufLen);
+
+CF_EXPORT UniChar
+CFStringGetCharacterAtIndex (CFStringRef theString, CFIndex idx);
+
+CF_EXPORT void
+CFStringGetCharacters (CFStringRef theString, CFRange range, UniChar *buffer);
+
+CF_EXPORT const UniChar *
+CFStringGetCharactersPtr (CFStringRef theString);
+
+CF_EXPORT Boolean
+CFStringGetCString (CFStringRef theString, char *buffer, CFIndex bufferSize,
+ CFStringEncoding encoding);
+
+CF_EXPORT const char *
+CFStringGetCStringPtr (CFStringRef theString, CFStringEncoding encoding);
+
+CF_EXPORT CFIndex
+CFStringGetLength (CFStringRef str);
+
+CF_EXPORT CFRange
+CFStringGetRangeOfComposedCharactersAtIndex (CFStringRef theString,
+ CFIndex theIndex);
+
+#if OS_API_VERSION(MAC_OS_X_VERSION_10_6, GS_API_LATEST)
+CF_EXPORT UTF32Char
+CFStringGetLongCharacterForSurrogatePair (UniChar surrogateHigh,
+ UniChar surrogateLow);
+
+CF_EXPORT Boolean
+CFStringGetSurrogatePairForLongCharacter (UTF32Char character,
+ UniChar *surrogates);
+
+CF_EXPORT Boolean
+CFStringIsSurrogateHighCharacter (UniChar character);
+
+CF_EXPORT Boolean
+CFStringIsSurrogateLowCharacter (UniChar character);
+#endif
+/** \} */
+
+/** \name Working with Encodings
+ \{
+ */
+CF_EXPORT CFStringRef
+CFStringConvertEncodingToIANACharSetName (CFStringEncoding encoding);
+
+CF_EXPORT unsigned long
+CFStringConvertEncodingToNSStringEncoding (CFStringEncoding encoding);
+
+UInt32
+CFStringConvertEncodingToWindowsCodepage (CFStringEncoding encoding);
+
+CF_EXPORT CFStringEncoding
+CFStringConvertIANACharSetNameToEncoding (CFStringRef theString);
+
+CF_EXPORT CFStringEncoding
+CFStringConvertNSStringEncodingToEncoding (unsigned long encoding);
+
+CF_EXPORT CFStringEncoding
+CFStringConvertWindowsCodepageToEncoding (UInt32 codepage);
+
+CF_EXPORT CFStringEncoding
+CFStringGetFastestEncoding (CFStringRef theString);
+
+CF_EXPORT const CFStringEncoding *
+CFStringGetListOfAvailableEncodings (void);
+
+CF_EXPORT CFIndex
+CFStringGetMaximumSizeForEncoding (CFIndex length, CFStringEncoding encoding);
+
+CF_EXPORT CFStringEncoding
+CFStringGetMostCompatibleMacStringEncoding (CFStringEncoding encoding);
+
+CF_EXPORT CFStringRef
+CFStringGetNameOfEncoding (CFStringEncoding encoding);
+
+CF_EXPORT CFStringEncoding
+CFStringGetSmallestEncoding (CFStringRef theString);
+
+CF_EXPORT CFStringEncoding
+CFStringGetSystemEncoding (void);
+
+CF_EXPORT Boolean
+CFStringIsEncodingAvailable (CFStringEncoding encoding);
+
+#if OS_API_VERSION(MAC_OS_X_VERSION_10_4, GS_API_LATEST)
+CF_EXPORT Boolean
+CFStringGetFileSystemRepresentation (CFStringRef string, char *buffer,
+ CFIndex maxBufLen);
+
+CF_EXPORT CFIndex
+CFStringGetMaximumSizeOfFileSystemRepresentation (CFStringRef string);
+#endif
+/** \} */
+
+/** \name Getting Numeric Values
+ \{
+ */
+CF_EXPORT double
+CFStringGetDoubleValue (CFStringRef str);
+
+CF_EXPORT SInt32
+CFStringGetIntValue (CFStringRef str);
+/** \} */
+
+/** \name Getting String Properties
+ \{
+ */
+CF_EXPORT void
+CFShow (CFTypeRef obj);
+
+CF_EXPORT void
+CFShowStr (CFStringRef str);
+
+CF_EXPORT CFTypeID
+CFStringGetTypeID (void);
+/** \} */
+
+
+
+/** \name Pascal Strings
+ \{
+ */
+CF_EXPORT CFStringRef
+CFStringCreateWithPascalString (CFAllocatorRef alloc, ConstStr255Param pStr,
+ CFStringEncoding encoding);
+
+CF_EXPORT CFStringRef
+CFStringCreateWithPascalStringNoCopy (CFAllocatorRef alloc,
+ ConstStr255Param pStr, CFStringEncoding encoding,
+ CFAllocatorRef contentsDeallocate);
+
+CF_EXPORT Boolean
+CFStringGetPascalString (CFStringRef theString, StringPtr buffer,
+ CFIndex bufferSize, CFStringEncoding encoding);
+
+CF_EXPORT ConstStringPtr
+CFStringGetPascalStringPtr (CFStringRef theString, CFStringEncoding encoding);
+/** \} */
+/** \} */
+
+
+
+/** \defgroup CFMutableStringRef CFMutableString Reference
+ * \{
+ */
+#if OS_API_VERSION(MAC_OS_X_VERSION_10_2, GS_API_LATEST)
+typedef enum
+{
+ kCFStringNormalizationFormD = 0,
+ kCFStringNormalizationFormKD = 1,
+ kCFStringNormalizationFormC = 2,
+ kCFStringNormalizationFormKC = 3
+} CFStringNormalizationForm;
+#endif
+
+#if OS_API_VERSION(MAC_OS_X_VERSION_10_4, GS_API_LATEST)
+CF_EXPORT const CFStringRef kCFStringTransformStripCombiningMarks;
+CF_EXPORT const CFStringRef kCFStringTransformToLatin;
+CF_EXPORT const CFStringRef kCFStringTransformFullwidthHalfwidth;
+CF_EXPORT const CFStringRef kCFStringTransformLatinKatakana;
+CF_EXPORT const CFStringRef kCFStringTransformLatinHiragana;
+CF_EXPORT const CFStringRef kCFStringTransformHiraganaKatakana;
+CF_EXPORT const CFStringRef kCFStringTransformMandarinLatin;
+CF_EXPORT const CFStringRef kCFStringTransformLatinHangul;
+CF_EXPORT const CFStringRef kCFStringTransformLatinArabic;
+CF_EXPORT const CFStringRef kCFStringTransformLatinHebrew;
+CF_EXPORT const CFStringRef kCFStringTransformLatinThai;
+CF_EXPORT const CFStringRef kCFStringTransformLatinCyrillic;
+CF_EXPORT const CFStringRef kCFStringTransformLatinGreek;
+CF_EXPORT const CFStringRef kCFStringTransformToXMLHex;
+CF_EXPORT const CFStringRef kCFStringTransformToUnicodeName;
+#endif
+#if OS_API_VERSION(MAC_OS_X_VERSION_10_5, GS_API_LATEST)
+CF_EXPORT const CFStringRef kCFStringTransformStripDiacritics;
+#endif
+
+CF_EXPORT void
+CFStringAppend (CFMutableStringRef theString, CFStringRef appendedString);
+
+CF_EXPORT void
+CFStringAppendCharacters (CFMutableStringRef theString,
+ const UniChar *chars, CFIndex numChars);
+
+CF_EXPORT void
+CFStringAppendCString (CFMutableStringRef theString, const char *cStr,
+ CFStringEncoding encoding);
+
+CF_EXPORT void
+CFStringAppendFormat (CFMutableStringRef theString,
+ CFDictionaryRef formatOptions, CFStringRef format, ...);
+
+CF_EXPORT void
+CFStringAppendFormatAndArguments (CFMutableStringRef theString,
+ CFDictionaryRef formatOptions, CFStringRef format, va_list arguments);
+
+CF_EXPORT void
+CFStringAppendPascalString (CFMutableStringRef theString,
+ ConstStr255Param pStr, CFStringEncoding encoding);
+
+CF_EXPORT void
+CFStringCapitalize (CFMutableStringRef theString, CFLocaleRef locale);
+
+CF_EXPORT CFMutableStringRef
+CFStringCreateMutable (CFAllocatorRef alloc, CFIndex maxLength);
+
+CF_EXPORT CFMutableStringRef
+CFStringCreateMutableCopy (CFAllocatorRef alloc, CFIndex maxLength,
+ CFStringRef theString);
+
+CF_EXPORT CFMutableStringRef
+CFStringCreateMutableWithExternalCharactersNoCopy (CFAllocatorRef alloc,
+ UniChar *chars, CFIndex numChars, CFIndex capacity,
+ CFAllocatorRef externalCharactersAllocator);
+
+CF_EXPORT void
+CFStringDelete (CFMutableStringRef theString, CFRange range);
+
+CF_EXPORT void
+CFStringInsert (CFMutableStringRef str, CFIndex idx, CFStringRef insertedStr);
+
+CF_EXPORT void
+CFStringLowercase (CFMutableStringRef theString, CFLocaleRef locale);
+
+CF_EXPORT void
+CFStringPad (CFMutableStringRef theString, CFStringRef padString,
+ CFIndex length, CFIndex indexIntoPad);
+
+CF_EXPORT void
+CFStringReplace (CFMutableStringRef theString, CFRange range,
+ CFStringRef replacement);
+
+CF_EXPORT void
+CFStringReplaceAll (CFMutableStringRef theString, CFStringRef replacement);
+
+CF_EXPORT void
+CFStringSetExternalCharactersNoCopy (CFMutableStringRef theString,
+ UniChar *chars, CFIndex length, CFIndex capacity);
+
+CF_EXPORT void
+CFStringTrim (CFMutableStringRef theString, CFStringRef trimString);
+
+CF_EXPORT void
+CFStringTrimWhitespace (CFMutableStringRef theString);
+
+CF_EXPORT void
+CFStringUppercase (CFMutableStringRef theString, CFLocaleRef locale);
+
+#if OS_API_VERSION(MAC_OS_X_VERSION_10_2, GS_API_LATEST)
+CF_EXPORT CFIndex
+CFStringFindAndReplace (CFMutableStringRef theString,
+ CFStringRef stringToFind, CFStringRef replacementString,
+ CFRange rangeToSearch, CFOptionFlags compareOptions);
+
+CF_EXPORT void
+CFStringNormalize (CFMutableStringRef theString,
+ CFStringNormalizationForm theForm);
+#endif
+
+#if OS_API_VERSION(MAC_OS_X_VERSION_10_4, GS_API_LATEST)
+CF_EXPORT Boolean
+CFStringTransform (CFMutableStringRef string, CFRange *range,
+ CFStringRef transform, Boolean reverse);
+#endif
+
+#if OS_API_VERSION(MAC_OS_X_VERSION_10_5, GS_API_LATEST)
+CF_EXPORT void
+CFStringFold (CFMutableStringRef theString, CFOptionFlags theFlags,
+ CFLocaleRef theLocale);
+#endif
+/** \} */
+
+
+
+/** \ingroup CFStringRef
+ \name CFStringInlineBuffer
+ \{
+ */
+#define __kCFStringInlineBufferLength 64
+struct CFStringInlineBuffer
+{
+ UniChar buffer[__kCFStringInlineBufferLength];
+ CFStringRef theString;
+ const UniChar *directBuffer;
+ CFRange rangeToBuffer;
+ CFIndex bufferedRangeStart;
+ CFIndex bufferedRangeEnd;
+};
+typedef struct CFStringInlineBuffer CFStringInlineBuffer;
+
+CF_INLINE void
+CFStringInitInlineBuffer (CFStringRef str, CFStringInlineBuffer *buf,
+ CFRange range)
+{
+ buf->theString = str;
+ buf->rangeToBuffer = range;
+ buf->directBuffer = CFStringGetCharactersPtr (str);
+ buf->bufferedRangeStart = 0;
+ buf->bufferedRangeEnd = 0;
+}
+
+CF_INLINE UniChar
+CFStringGetCharacterFromInlineBuffer (CFStringInlineBuffer *buf, CFIndex idx)
+{
+ if (buf->directBuffer)
+ {
+ if (idx < 0 || idx >= buf->rangeToBuffer.length)
+ return 0;
+ return buf->directBuffer[idx + buf->rangeToBuffer.location];
+ }
+ else if (idx >= buf->bufferedRangeEnd || idx < buf->bufferedRangeStart)
+ {
+ CFRange range;
+
+ if (idx < 0 || idx >= buf->rangeToBuffer.length)
+ return 0;
+
+ /* Use 16 here so it's efficient to go backwards, too */
+ buf->bufferedRangeStart = idx - 16;
+ if (buf->bufferedRangeStart < 0)
+ buf->bufferedRangeStart = 0;
+ buf->bufferedRangeEnd =
+ buf->bufferedRangeStart + __kCFStringInlineBufferLength;
+ if (buf->bufferedRangeEnd > buf->rangeToBuffer.length)
+ buf->bufferedRangeEnd = buf->rangeToBuffer.length;
+
+ range = CFRangeMake (buf->rangeToBuffer.location + buf->bufferedRangeStart,
+ buf->bufferedRangeEnd - buf->bufferedRangeStart);
+
+ CFStringGetCharacters (buf->theString, range, buf->buffer);
+ }
+
+ return buf->buffer[(idx - buf->bufferedRangeStart)];
+}
+/** \} */
+
+CF_EXTERN_C_END
+
+#endif /* __COREFOUNDATION_CFSTRING_H__ */
+
diff --git a/gcc/testsuite/objc-obj-c++-shared/GNUStep/Foundation/NSArray.h b/gcc/testsuite/objc-obj-c++-shared/GNUStep/Foundation/NSArray.h
new file mode 100644
index 0000000..661e90f
--- /dev/null
+++ b/gcc/testsuite/objc-obj-c++-shared/GNUStep/Foundation/NSArray.h
@@ -0,0 +1,430 @@
+/* Interface for NSArray for GNUStep
+ Copyright (C) 1995-2015 Free Software Foundation, Inc.
+
+ Written by: Andrew Kachites McCallum <mccallum@gnu.ai.mit.edu>
+ Created: 1995
+
+ This file is part of the GNUstep Base Library.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free
+ Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02111 USA.
+ */
+
+#ifndef __NSArray_h_GNUSTEP_BASE_INCLUDE
+#define __NSArray_h_GNUSTEP_BASE_INCLUDE
+#import "../GNUstepBase/GSVersionMacros.h"
+
+#import "NSObject.h"
+#import "NSRange.h"
+#import "NSEnumerator.h"
+#if __BLOCKS__
+#import "../GNUstepBase/GSBlocks.h"
+#endif
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+@class NSString;
+@class NSURL;
+@class NSIndexSet;
+
+#if OS_API_VERSION(MAC_OS_X_VERSION_10_6, GS_API_LATEST)
+enum
+{
+ NSBinarySearchingFirstEqual = (1UL << 8), /** Specifies that the binary
+ * search should find the first object equal in the array.
+ */
+ NSBinarySearchingLastEqual = (1UL << 9), /** Specifies that the binary
+ * search should find the last object equal in the array.
+ */
+ NSBinarySearchingInsertionIndex = (1UL << 10), /** Specifies that the binary
+ * search should find the index at which an equal object should be inserted
+ * in order to keep the array sorted
+ */
+};
+
+typedef NSUInteger NSBinarySearchingOptions;
+#endif
+
+@interface GS_GENERIC_CLASS(NSArray, __covariant ElementT) : NSObject
+ <NSCoding, NSCopying, NSMutableCopying, NSFastEnumeration>
+
++ (instancetype) array;
++ (instancetype) arrayWithArray: (GS_GENERIC_CLASS(NSArray, ElementT) *)array;
++ (instancetype) arrayWithContentsOfFile: (NSString*)file;
+#if OS_API_VERSION(GS_API_MACOSX, GS_API_LATEST)
++ (instancetype) arrayWithContentsOfURL: (NSURL*)aURL;
+#endif
++ (instancetype) arrayWithObject: (id)anObject;
++ (instancetype) arrayWithObjects: (id)firstObject, ...;
++ (instancetype) arrayWithObjects: (const id[])objects count: (NSUInteger)count;
+
+- (GS_GENERIC_CLASS(NSArray, ElementT) *) arrayByAddingObject:
+ (GS_GENERIC_TYPE(ElementT))anObject;
+- (GS_GENERIC_CLASS(NSArray, ElementT) *) arrayByAddingObjectsFromArray:
+ (GS_GENERIC_CLASS(NSArray, ElementT)*)anotherArray;
+- (BOOL) containsObject: (GS_GENERIC_TYPE(ElementT))anObject;
+
+/** <override-subclass />
+ * Returns the number of elements contained in the receiver.
+ */
+- (NSUInteger) count;
+- (void) getObjects: (__unsafe_unretained GS_GENERIC_TYPE(ElementT)[])aBuffer;
+- (void) getObjects: (__unsafe_unretained GS_GENERIC_TYPE(ElementT)[])aBuffer
+ range: (NSRange)aRange;
+- (NSUInteger) indexOfObject: (GS_GENERIC_TYPE(ElementT))anObject;
+- (NSUInteger) indexOfObject: (GS_GENERIC_TYPE(ElementT))anObject
+ inRange: (NSRange)aRange;
+- (NSUInteger) indexOfObjectIdenticalTo: (GS_GENERIC_TYPE(ElementT))anObject;
+- (NSUInteger) indexOfObjectIdenticalTo: (GS_GENERIC_TYPE(ElementT))anObject
+ inRange: (NSRange)aRange;
+- (instancetype) init;
+- (instancetype) initWithArray: (GS_GENERIC_CLASS(NSArray, ElementT)*)array;
+#if OS_API_VERSION(GS_API_MACOSX, GS_API_LATEST)
+- (instancetype) initWithArray: (GS_GENERIC_CLASS(NSArray, ElementT)*)array
+ copyItems: (BOOL)shouldCopy;
+#endif
+- (instancetype) initWithContentsOfFile: (NSString*)file;
+#if OS_API_VERSION(GS_API_MACOSX, GS_API_LATEST)
+- (instancetype) initWithContentsOfURL: (NSURL*)aURL;
+#endif
+- (instancetype) initWithObjects: (GS_GENERIC_TYPE(ElementT)) firstObject, ...;
+
+/** <init /> <override-subclass />
+ * This should initialize the array with count (may be zero) objects.<br />
+ * Retains each object placed in the array.<br />
+ * Calls -init (which does nothing but maintain MacOS-X compatibility),
+ * and needs to be re-implemented in subclasses in order to have all
+ * other initialisers work.
+ */
+- (instancetype) initWithObjects: (const GS_GENERIC_TYPE(ElementT)[])objects
+ count: (NSUInteger)count;
+- (GS_GENERIC_TYPE(ElementT)) lastObject;
+#if OS_API_VERSION(MAC_OS_X_VERSION_10_6, GS_API_LATEST)
+- (GS_GENERIC_TYPE(ElementT)) firstObject;
+#endif
+
+/** <override-subclass />
+ * Returns the object at the specified index.
+ * Raises an exception of the index is beyond the array.
+ */
+- (GS_GENERIC_TYPE(ElementT)) objectAtIndex: (NSUInteger)index;
+
+#if OS_API_VERSION(MAC_OS_X_VERSION_10_4, GS_API_LATEST)
+- (GS_GENERIC_CLASS(NSArray, ElementT) *) objectsAtIndexes:
+ (NSIndexSet *)indexes;
+#endif
+
+- (GS_GENERIC_TYPE(ElementT)) firstObjectCommonWithArray:
+ (GS_GENERIC_CLASS(NSArray, ElementT) *)otherArray;
+- (BOOL) isEqualToArray: (NSArray*)otherArray;
+
+#if OS_API_VERSION(GS_API_OPENSTEP, GS_API_MACOSX)
+- (void) makeObjectsPerform: (SEL)aSelector;
+- (void) makeObjectsPerform: (SEL)aSelector withObject: (id)argument;
+#endif
+#if OS_API_VERSION(GS_API_MACOSX, GS_API_LATEST)
+- (void) makeObjectsPerformSelector: (SEL)aSelector;
+- (void) makeObjectsPerformSelector: (SEL)aSelector withObject: (id)arg;
+#endif
+
+- (NSData*) sortedArrayHint;
+- (GS_GENERIC_CLASS(NSArray, ElementT)*) sortedArrayUsingFunction:
+ (NSComparisonResult (*)(id, id, void*))comparator
+ context: (void*)context;
+- (GS_GENERIC_CLASS(NSArray, ElementT)*) sortedArrayUsingFunction:
+ (NSComparisonResult (*)(id, id, void*))comparator
+ context: (void*)context
+ hint: (NSData*)hint;
+- (GS_GENERIC_CLASS(NSArray, ElementT)*) sortedArrayUsingSelector:
+ (SEL)comparator;
+- (GS_GENERIC_CLASS(NSArray, ElementT)*) subarrayWithRange: (NSRange)aRange;
+
+- (NSString*) componentsJoinedByString: (NSString*)separator;
+- (GS_GENERIC_CLASS(NSArray, NSString*)*) pathsMatchingExtensions:
+ (GS_GENERIC_CLASS(NSArray, NSString*)*)extensions;
+
+- (GS_GENERIC_CLASS(NSEnumerator, ElementT)*) objectEnumerator;
+- (GS_GENERIC_CLASS(NSEnumerator, ElementT)*) reverseObjectEnumerator;
+
+- (NSString*) description;
+- (NSString*) descriptionWithLocale: (id)locale;
+- (NSString*) descriptionWithLocale: (id)locale
+ indent: (NSUInteger)level;
+
+- (BOOL) writeToFile: (NSString*)path atomically: (BOOL)useAuxiliaryFile;
+#if OS_API_VERSION(GS_API_MACOSX, GS_API_LATEST)
+- (BOOL) writeToURL: (NSURL*)url atomically: (BOOL)useAuxiliaryFile;
+- (GS_GENERIC_TYPE(ElementT)) valueForKey: (NSString*)key;
+- (void) setValue: (GS_GENERIC_TYPE(ElementT))value forKey: (NSString*)key;
+#endif
+
+#if OS_API_VERSION(MAC_OS_X_VERSION_10_6, GS_API_LATEST)
+
+#if __BLOCKS__
+DEFINE_BLOCK_TYPE(GSEnumeratorBlock, void, GS_GENERIC_TYPE(ElementT),
+ NSUInteger, BOOL*);
+DEFINE_BLOCK_TYPE(GSPredicateBlock, BOOL, GS_GENERIC_TYPE(ElementT),
+ NSUInteger, BOOL*);
+/**
+ * Enumerate over the collection using the given block. The first argument is
+ * the object and the second is the index in the array. The final argument is
+ * a pointer to a BOOL indicating whether the enumeration should stop. Setting
+ * this to YES will interrupt the enumeration.
+ */
+- (void) enumerateObjectsUsingBlock: (GSEnumeratorBlock)aBlock;
+
+/**
+ * Enumerate over the collection using the given block. The first argument is
+ * the object and the second is the index in the array. The final argument is
+ * a pointer to a BOOL indicating whether the enumeration should stop. Setting
+ * this to YES will interrupt the enumeration.
+ *
+ * The opts argument is a bitfield. Setting the NSNSEnumerationConcurrent flag
+ * specifies that it is thread-safe. The NSEnumerationReverse bit specifies
+ * that it should be enumerated in reverse order.
+ */
+- (void) enumerateObjectsWithOptions: (NSEnumerationOptions)opts
+ usingBlock: (GSEnumeratorBlock)aBlock;
+/**
+ * Enumerate over the specified indexes in the collection using the given
+ * block. The first argument is the object and the second is the index in the
+ * array. The final argument is a pointer to a BOOL indicating whether the
+ * enumeration should stop. Setting this to YES will interrupt the
+ * enumeration.
+ *
+ * The opts argument is a bitfield. Setting the NSNSEnumerationConcurrent flag
+ * specifies that it is thread-safe. The NSEnumerationReverse bit specifies
+ * that it should be enumerated in reverse order.
+ */
+- (void) enumerateObjectsAtIndexes: (NSIndexSet*)indexSet
+ options: (NSEnumerationOptions)opts
+ usingBlock: (GSEnumeratorBlock)block;
+/**
+ * Returns the indexes of the objects in a collection that match the condition
+ * specified by the block.
+ *
+ * The opts argument is a bitfield. Setting the NSNSEnumerationConcurrent flag
+ * specifies that it is thread-safe. The NSEnumerationReverse bit specifies
+ * that it should be enumerated in reverse order.
+ */
+- (NSIndexSet *) indexesOfObjectsWithOptions: (NSEnumerationOptions)opts
+ passingTest: (GSPredicateBlock)predicate;
+
+/**
+ * Returns the indexes of the objects in a collection that match the condition
+ * specified by the block.
+ */
+- (NSIndexSet*) indexesOfObjectsPassingTest: (GSPredicateBlock)predicate;
+
+/**
+ * Returns the indexes of the objects in a collection that match the condition
+ * specified by the block and are in the range specified by the index set.
+ *
+ * The opts argument is a bitfield. Setting the NSNSEnumerationConcurrent flag
+ * specifies that it is thread-safe. The NSEnumerationReverse bit specifies
+ * that it should be enumerated in reverse order.
+ */
+- (NSIndexSet*) indexesOfObjectsAtIndexes: (NSIndexSet*)indexSet
+ options: (NSEnumerationOptions)opts
+ passingTest: (GSPredicateBlock)predicate;
+
+/**
+ * Returns the index of the first object in the array that matches the
+ * condition specified by the block.
+ *
+ * The opts argument is a bitfield. Setting the NSNSEnumerationConcurrent flag
+ * specifies that it is thread-safe. The NSEnumerationReverse bit specifies
+ * that it should be enumerated in reverse order.
+ */
+- (NSUInteger) indexOfObjectWithOptions: (NSEnumerationOptions)opts
+ passingTest: (GSPredicateBlock)predicate;
+
+/**
+ * Returns the index of the first object in the array that matches the
+ * condition specified by the block.
+ */
+- (NSUInteger) indexOfObjectPassingTest: (GSPredicateBlock)predicate;
+
+/**
+ * Returns the index of the first object in the specified range in a collection
+ * that matches the condition specified by the block.
+ *
+ * The opts argument is a bitfield. Setting the NSNSEnumerationConcurrent flag
+ * specifies that it is thread-safe. The NSEnumerationReverse bit specifies
+ * that it should be enumerated in reverse order.
+ */
+- (NSUInteger) indexOfObjectAtIndexes: (NSIndexSet*)indexSet
+ options: (NSEnumerationOptions)opts
+ passingTest: (GSPredicateBlock)predicate;
+
+/** Returns a sorted array using the comparator to determine the
+ * order of objects.
+ */
+- (GS_GENERIC_CLASS(NSArray, ElementT) *) sortedArrayUsingComparator:
+ (NSComparator)comparator;
+
+/** Returns a sorted array using the block to determine the order of objects.
+ *
+ * The opts argument is a bitfield. Setting the NSSortConcurrent flag
+ * specifies that it is thread-safe. The NSSortStable bit specifies that
+ * it should keep equal objects in the same order.
+ */
+- (GS_GENERIC_CLASS(NSArray, ElementT) *)
+ sortedArrayWithOptions: (NSSortOptions)options
+ usingComparator: (NSComparator)comparator;
+
+/**
+ * Performs a binary search of the array within the specified range for the
+ * index of an object equal to obj according to cmp.
+ * If NSBinarySearchingInsertionIndex is specified, searches for the index
+ * at which such an object should be inserted.
+ */
+- (NSUInteger) indexOfObject: (id)key
+ inSortedRange: (NSRange)range
+ options: (NSBinarySearchingOptions)options
+ usingComparator: (NSComparator)comparator;
+#endif
+#endif
+/**
+ * Accessor for subscripting. This is called by the compiler when you write
+ * code like anArray[12]. It should not be called directly.
+ */
+- (GS_GENERIC_TYPE(ElementT)) objectAtIndexedSubscript: (NSUInteger)anIndex;
+@end
+
+
+@interface GS_GENERIC_CLASS(NSMutableArray, ElementT) : NSArray
+
++ (instancetype) arrayWithCapacity: (NSUInteger)numItems;
+
+/** <override-subclass />
+ * Adds anObject at the end of the array, thus increasing the size of
+ * the array. The object is retained upon addition.
+ */
+- (void) addObject: (GS_GENERIC_TYPE(ElementT))anObject;
+- (void) addObjectsFromArray: (GS_GENERIC_CLASS(NSArray, ElementT)*)otherArray;
+#if OS_API_VERSION(GS_API_MACOSX, GS_API_LATEST)
+- (void) exchangeObjectAtIndex: (NSUInteger)i1
+ withObjectAtIndex: (NSUInteger)i2;
+#endif
+
+/** <init /> <override-subclass />
+ * Initialise the array with the specified capacity ... this
+ * should ensure that the array can have numItems added efficiently.<br />
+ * Calls -init (which does nothing but maintain MacOS-X compatibility),
+ * and needs to be re-implemented in subclasses in order to have all
+ * other initialisers work.
+ */
+- (instancetype) initWithCapacity: (NSUInteger)numItems;
+
+/** <override-subclass />
+ * Inserts an object into the receiver at the specified location.<br />
+ * Raises an exception if given an array index which is too large.<br />
+ * The size of the array increases by one.<br />
+ * The object is retained by the array.
+ */
+- (void) insertObject: (GS_GENERIC_TYPE(ElementT))anObject
+ atIndex: (NSUInteger)index;
+#if OS_API_VERSION(MAC_OS_X_VERSION_10_4, GS_API_LATEST)
+- (void) insertObjects: (GS_GENERIC_CLASS(NSArray, ElementT) *)objects
+ atIndexes: (NSIndexSet *)indexes;
+#endif
+
+/** <override-subclass />
+ * Removes an object from the receiver at the specified location.<br />
+ * The size of the array decreases by one.<br />
+ * Raises an exception if given an array index which is too large.<br />
+ */
+- (void) removeObjectAtIndex: (NSUInteger)index;
+
+- (void) removeObjectsAtIndexes: (NSIndexSet *)indexes;
+
+/** <override-subclass />
+ * Places an object into the receiver at the specified location.<br />
+ * Raises an exception if given an array index which is too large.<br />
+ * The object is retained by the array.
+ */
+- (void) replaceObjectAtIndex: (NSUInteger)index
+ withObject: (GS_GENERIC_TYPE(ElementT))anObject;
+
+#if OS_API_VERSION(MAC_OS_X_VERSION_10_4, GS_API_LATEST)
+- (void) replaceObjectsAtIndexes: (NSIndexSet *)indexes
+ withObjects: (GS_GENERIC_CLASS(NSArray, ElementT)*)objects;
+#endif
+
+- (void) replaceObjectsInRange: (NSRange)aRange
+ withObjectsFromArray: (GS_GENERIC_CLASS(NSArray, ElementT)*)anArray;
+
+- (void) replaceObjectsInRange: (NSRange)aRange
+ withObjectsFromArray: (GS_GENERIC_CLASS(NSArray, ElementT)*)anArray
+ range: (NSRange)anotherRange;
+
+- (void) setArray: (GS_GENERIC_CLASS(NSArray, ElementT) *)otherArray;
+
+- (void) removeAllObjects;
+- (void) removeLastObject;
+- (void) removeObject: (GS_GENERIC_TYPE(ElementT))anObject;
+- (void) removeObject: (GS_GENERIC_TYPE(ElementT))anObject
+ inRange: (NSRange)aRange;
+- (void) removeObjectIdenticalTo: (GS_GENERIC_TYPE(ElementT))anObject;
+- (void) removeObjectIdenticalTo: (GS_GENERIC_TYPE(ElementT))anObject
+ inRange: (NSRange)aRange;
+- (void) removeObjectsInArray: (GS_GENERIC_CLASS(NSArray, ElementT)*)otherArray;
+- (void) removeObjectsInRange: (NSRange)aRange;
+- (void) removeObjectsFromIndices: (NSUInteger*)indices
+ numIndices: (NSUInteger)count;
+
+- (void) sortUsingFunction:
+ (NSComparisonResult (*)(GS_GENERIC_TYPE(ElementT),
+ GS_GENERIC_TYPE(ElementT),void*))compare
+ context: (void*)context;
+- (void) sortUsingSelector: (SEL)comparator;
+
+
+#if OS_API_VERSION(MAC_OS_X_VERSION_10_6, GS_API_LATEST)
+#if __BLOCKS__
+/**
+ * Sorts the array using the specified comparator block.
+ */
+- (void) sortUsingComparator: (NSComparator)comparator;
+
+/**
+ * Sorts the array using the specified comparator block and options.
+ */
+- (void) sortWithOptions: (NSSortOptions)options
+ usingComparator: (NSComparator)comparator;
+#endif
+#endif
+#if OS_API_VERSION(MAC_OS_X_VERSION_10_8, GS_API_LATEST)
+/** Set method called by the compiler with array subscripting.<br />
+ * Replaces the object at anIndex or, if anIndex is the length of the array,
+ * this method appends abObject to the array.
+ */
+- (void) setObject: (GS_GENERIC_TYPE(ElementT))anObject
+atIndexedSubscript: (NSUInteger)anIndex;
+#endif
+@end
+
+#if defined(__cplusplus)
+}
+#endif
+
+#if !NO_GNUSTEP && !defined(GNUSTEP_BASE_INTERNAL)
+#import "../GNUstepBase/NSArray+GNUstepBase.h"
+#endif
+
+#endif /* __NSArray_h_GNUSTEP_BASE_INCLUDE */
diff --git a/gcc/testsuite/objc-obj-c++-shared/GNUStep/Foundation/NSAutoreleasePool.h b/gcc/testsuite/objc-obj-c++-shared/GNUStep/Foundation/NSAutoreleasePool.h
new file mode 100644
index 0000000..c7ec486
--- /dev/null
+++ b/gcc/testsuite/objc-obj-c++-shared/GNUStep/Foundation/NSAutoreleasePool.h
@@ -0,0 +1,333 @@
+/* Interface for NSAutoreleasePool for GNUStep
+ Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc.
+
+ Written by: Andrew Kachites McCallum <mccallum@gnu.ai.mit.edu>
+ Date: 1995
+
+ This file is part of the GNUstep Base Library.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free
+ Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02111 USA.
+ */
+
+#ifndef __NSAutoreleasePool_h_GNUSTEP_BASE_INCLUDE
+#define __NSAutoreleasePool_h_GNUSTEP_BASE_INCLUDE
+#import "../GNUstepBase/GSVersionMacros.h"
+
+#import "NSObject.h"
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+@class NSAutoreleasePool;
+@class NSThread;
+
+
+/**
+ * Each thread has its own copy of these variables.
+ <example>
+{
+ NSAutoreleasePool *current_pool; // current pool for thread
+ unsigned total_objects_count; // total #/autoreleased objects over thread's lifetime
+ id *pool_cache; // cache of previously-allocated pools,
+ int pool_cache_size; // used internally for recycling
+ int pool_cache_count;
+}
+ </example>
+*/
+typedef struct autorelease_thread_vars
+{
+ /* The current, default NSAutoreleasePool for the calling thread;
+ the one that will hold objects that are arguments to
+ [NSAutoreleasePool +addObject:]. */
+ __unsafe_unretained NSAutoreleasePool *current_pool;
+
+ /* The total number of objects autoreleased since the thread was
+ started, or since -resetTotalAutoreleasedObjects was called
+ in this thread. (if compiled in) */
+ unsigned total_objects_count;
+
+ /* A cache of NSAutoreleasePool's already alloc'ed. Caching old pools
+ instead of deallocating and re-allocating them will save time. */
+ __unsafe_unretained id *pool_cache;
+ int pool_cache_size;
+ int pool_cache_count;
+} thread_vars_struct;
+
+/* Initialize an autorelease_thread_vars structure for a new thread.
+ This function is called in NSThread each time an NSThread is created.
+ TV should be of type `struct autorelease_thread_vars *' */
+#define init_autorelease_thread_vars(TV) \
+memset (TV, 0, sizeof (__typeof__ (*TV)))
+
+
+
+/**
+ * Each pool holds its objects-to-be-released in a linked-list of
+ these structures.
+ <example>
+{
+ struct autorelease_array_list *next;
+ unsigned size;
+ unsigned count;
+ id objects[0];
+}
+ </example>
+ */
+typedef struct autorelease_array_list
+{
+ struct autorelease_array_list *next;
+ unsigned size;
+ unsigned count;
+ __unsafe_unretained id objects[0];
+} array_list_struct;
+
+
+
+/**
+ * <p>
+ * The standard OpenStep system of memory management employs retain counts.
+ * When an object is created, it has a retain count of 1. When an object
+ * is retained, the retain count is incremented. When it is released the
+ * retain count is decremented, and when the retain count goes to zero the
+ * object gets deallocated.
+ * </p>
+ * <p>
+ * A simple retain/release mechanism has problems with passing objects
+ * from one scope to another,
+ * so it's augmented with autorelease pools. You can use the
+ * AUTORELEASE() macro to call the [NSObject-autorelease]
+ * method, which adds an object to the current autorelease pool by
+ * calling [NSAutoreleasePool+addObject:].<br />
+ * An autorelease pool simply maintains a reference to each object
+ * added to it, and for each addition, the autorelease pool will
+ * call the [NSObject-release] method of the object when the pool
+ * is released. So doing an AUTORELEASE() is just the same as
+ * doing a RELEASE(), but deferred until the current autorelease
+ * pool is deallocated.
+ * </p>
+ * <p>
+ * The NSAutoreleasePool class maintains a separate stack of
+ * autorelease pools objects in each thread.
+ * </p>
+ * <p>
+ * When an autorelease pool is created, it is automatically
+ * added to the stack of pools in the thread.
+ * </p>
+ * <p>
+ * When a pool is destroyed, it (and any pool later in
+ * the stack) is removed from the stack.
+ * </p>
+ * <p>
+ * This mechanism provides a simple but controllable and reasonably
+ * efficient way of managing temporary objects. An object can be
+ * autoreleased and then passed around and used until the topmost
+ * pool in the stack is destroyed.
+ * </p>
+ * <p>
+ * Most methods return objects which are either owned by autorelease
+ * pools or by the receiver of the method, so the lifetime of the
+ * returned object can be assumed to be the shorter of the lifetime
+ * of the current autorelease pool, or that of the receiver on which
+ * the method was called.<br />
+ * The exceptions to this are those object returned by -
+ * </p>
+ * <deflist>
+ * <term>[NSObject+alloc], [NSObject+allocWithZone:]</term>
+ * <desc>
+ * Methods whose names begin with alloc return an uninitialised
+ * object, owned by the caller.
+ * </desc>
+ * <term>[NSObject-init]</term>
+ * <desc>
+ * Methods whose names begin with init return an initialised
+ * version of the receiving object, owned by the caller.<br />
+ * NB. The returned object may not actually be the same as the
+ * receiver ... sometimes an init method releases the original
+ * receiver and returns an alternative.
+ * </desc>
+ * <term>[NSObject+new]</term>
+ * <desc>
+ * Methods whose names begin with new combine the effects of
+ * allocation and initialisation.
+ * </desc>
+ * <term>[NSObject-copy], [(NSCopying)-copyWithZone:]</term>
+ * <desc>
+ * Methods whose names begin with copy create a copy of the receiver
+ * which is owned by the caller.
+ * </desc>
+ * <term>
+ * [NSObject-mutableCopy], [(NSMutableCopying)-mutableCopyWithZone:]
+ * </term>
+ * <desc>
+ * Methods whose names begin with mutableCopy create a copy of the receiver
+ * which is owned by the caller.
+ * </desc>
+ * </deflist>
+ */
+NS_AUTOMATED_REFCOUNT_UNAVAILABLE
+@interface NSAutoreleasePool : NSObject
+{
+#if GS_EXPOSE(NSAutoreleasePool) && !__has_feature(objc_arc)
+ /* For re-setting the current pool when we are dealloc'ed. */
+ NSAutoreleasePool *_parent;
+ /* This pointer to our child pool is necessary for co-existing
+ with exceptions. */
+ NSAutoreleasePool *_child;
+ /* A collection of the objects to be released. */
+ struct autorelease_array_list *_released;
+ struct autorelease_array_list *_released_head;
+ /* The total number of objects autoreleased in this pool. */
+ unsigned _released_count;
+ /* The method to add an object to this pool */
+ void (*_addImp)(id, SEL, id);
+#endif
+#if GS_NONFRAGILE
+#else
+ /* Pointer to private additional data used to avoid breaking ABI
+ * when we don't have the non-fragile ABI available.
+ * Use this mechanism rather than changing the instance variable
+ * layout (see Source/GSInternal.h for details).
+ */
+ @private id _internal GS_UNUSED_IVAR;
+#endif
+}
+
+/**
+ * Adds anObj to the current autorelease pool.<br />
+ * If there is no autorelease pool in the thread,
+ * a warning is logged and the object is leaked (ie it will not be released).
+ */
++ (void) addObject: (id)anObj;
+
+/**
+ * Allocate and return an autorelease pool instance.<br />
+ * If there is an already-allocated NSAutoreleasePool available,
+ * save time by just returning that, rather than allocating a new one.<br />
+ * The pool instance becomes the current autorelease pool for this thread.
+ */
++ (id) allocWithZone: (NSZone*)zone;
+
+/**
+ * Adds anObj to this autorelease pool.
+ */
+- (void) addObject: (id)anObj;
+
+/**
+ * Raises an exception - pools should not be autoreleased.
+ */
+- (id) autorelease;
+
+#if OS_API_VERSION(MAC_OS_X_VERSION_10_4, GS_API_LATEST)
+/**
+ * Intended to trigger a garbage collection run (if needed) when called in
+ * a garbage collected environment.<br />
+ * In a non-garbage collected environment, this method implements the
+ * undocumented MacOS-X behavior, and releases the receiver.
+ */
+- (void) drain;
+#endif
+
+/**
+ * Destroys the receiver (calls -dealloc).
+ */
+- (oneway void) release;
+
+/**
+ * Raises an exception ... pools should not be retained.
+ */
+- (id) retain;
+
+#if OS_API_VERSION(GS_API_NONE, GS_API_NONE)
+/**
+ * <p>
+ * Counts the number of times that the specified object occurs
+ * in autorelease pools in the current thread.
+ * </p>
+ * <p>
+ * This method is <em>slow</em> and should probably only be
+ * used for debugging purposes.
+ * </p>
+ */
++ (unsigned) autoreleaseCountForObject: (id)anObject;
+
+/**
+ * Return the currently active autorelease pool.
+ */
++ (id) currentPool;
+
+/**
+ * <p>
+ * Specifies whether objects contained in autorelease pools are to
+ * be released when the pools are deallocated (by default YES).
+ * </p>
+ * <p>
+ * You can set this to NO for debugging purposes.
+ * </p>
+ */
++ (void) enableRelease: (BOOL)enable;
+
+/**
+ * <p>
+ * When autorelease pools are deallocated, the memory they used
+ * is retained in a cache for re-use so that new polls can be
+ * created very quickly.
+ * </p>
+ * <p>
+ * This method may be used to empty that cache, ensuring that
+ * the minimum memory is used by the application.
+ * </p>
+ */
++ (void) freeCache;
+
+/**
+ * <p>
+ * Specifies a limit to the number of objects that may be added to
+ * an autorelease pool. When this limit is reached an exception is
+ * raised.
+ * </p>
+ * <p>
+ * You can set this to a smallish value to catch problems with code
+ * that autoreleases too many objects to operate efficiently.
+ * </p>
+ * <p>
+ * Default value is maxint.
+ * </p>
+ */
++ (void) setPoolCountThreshold: (unsigned)c;
+
+/**
+ * Return the number of objects in this pool.
+ */
+- (unsigned) autoreleaseCount;
+
+/**
+ * Empties the current pool by releasing all the autoreleased objects
+ * in it. Also destroys any child pools (ones created after
+ * the receiver in the same thread) causing any objects in those pools
+ * to be released.<br />
+ * This is a low cost (efficient) method which may be used to get rid of
+ * autoreleased objects in the pool, but carry on using the pool.
+ */
+- (void) emptyPool;
+#endif
+@end
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif /* __NSAutoreleasePool_h_GNUSTEP_BASE_INCLUDE */
diff --git a/gcc/testsuite/objc-obj-c++-shared/GNUStep/Foundation/NSDate.h b/gcc/testsuite/objc-obj-c++-shared/GNUStep/Foundation/NSDate.h
new file mode 100644
index 0000000..dbec39e
--- /dev/null
+++ b/gcc/testsuite/objc-obj-c++-shared/GNUStep/Foundation/NSDate.h
@@ -0,0 +1,300 @@
+/* Interface for NSDate for GNUStep
+ Copyright (C) 1994, 1996, 1999 Free Software Foundation, Inc.
+
+ This file is part of the GNUstep Base Library.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free
+ Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02111 USA.
+ */
+
+#ifndef __NSDate_h_GNUSTEP_BASE_INCLUDE
+#define __NSDate_h_GNUSTEP_BASE_INCLUDE
+#import "../GNUstepBase/GSVersionMacros.h"
+
+#import "NSObjCRuntime.h"
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+GS_EXPORT NSString * const NSSystemClockDidChangeNotification;
+
+/**
+ * Time interval difference between two dates, in seconds.
+ */
+typedef double NSTimeInterval;
+
+/**
+ * Time interval between the unix standard reference date of 1 January 1970
+ * and the OpenStep reference date of 1 January 2001<br />
+ * This number comes from:<br />
+ * (((31 years * 365 days) + 8 days for leap years) = total number of days<br />
+ * 24 hours * 60 minutes * 60 seconds)<br />
+ * This ignores leap-seconds.
+ */
+GS_EXPORT const NSTimeInterval NSTimeIntervalSince1970;
+
+#import "NSObject.h"
+
+@class NSArray;
+@class NSCalendarDate;
+@class NSData;
+@class NSDictionary;
+@class NSString;
+@class NSTimeZone;
+@class NSTimeZoneDetail;
+
+@interface NSDate : NSObject <NSCoding,NSCopying>
+{
+}
+
+/** Returns an autoreleased instance with the current date/time.
+ */
++ (id) date;
+
+#if OS_API_VERSION(GS_API_MACOSX, GS_API_LATEST)
+/** Returns an autoreleased instance representing the date and time given
+ * by string. The value of string may be a 'natural' specification as
+ * specified by the preferences in the user defaults database, allowing
+ * phrases like 'last tuesday'
+ */
++ (id) dateWithNaturalLanguageString: (NSString*)string;
+
+/**
+ * <p>Returns an autoreleased instance representing the date and time given
+ * by string. The value of string may be a 'natural' specification as
+ * specified by the preferences in the user defaults database, allowing
+ * phrases like 'last tuesday'
+ * </p>
+ * The locale contains keys such as -
+ * <deflist>
+ * <term>NSDateTimeOrdering</term>
+ * <desc>Controls the use of ambiguous numbers. This is done as a
+ * sequence of the letters D(ay), M(onth), Y(ear), and H(our).
+ * YMDH means that the first number encountered is assumed to be a
+ * year, the second a month, the third a day, and the last an hour.
+ * </desc>
+ * <term>NSEarlierTimeDesignations</term>
+ * <desc>An array of strings for times in the past.<br />
+ * Defaults are <em>ago</em>, <em>last</em>, <em>past</em>, <em>prior</em>
+ * </desc>
+ * <term>NSHourNameDesignations</term>
+ * <desc>An array of arrays of strings identifying the time of day.
+ * Each array has an hour as its first value, and one or more words
+ * as subsequent values.<br />
+ * Defaults are: (0, midnight), (10, morning), (12, noon, lunch),
+ * (14, afternoon), (19, dinner).
+ * </desc>
+ * <term>NSLaterTimeDesignations</term>
+ * <desc>An array of strings for times in the future.<br />
+ * Default is <em>next</em>
+ * </desc>
+ * <term>NSNextDayDesignations</term>
+ * <desc>The day after today. Default is <em>tomorrow.</em>
+ * </desc>
+ * <term>NSNextNextDayDesignations</term>
+ * <desc>The day after tomorrow. Default is <em>nextday.</em>
+ * </desc>
+ * <term>NSPriorDayDesignations</term>
+ * <desc>The day before today. Default is <em>yesterday.</em>
+ * </desc>
+ * <term>NSThisDayDesignations</term>
+ * <desc>Identifies the current day. Default is <em>today.</em>
+ * </desc>
+ * <term>NSYearMonthWeekDesignations</term>
+ * <desc>An array giving the word for year, month, and week.<br />
+ * Defaults are <em>year</em>, <em>month</em> and <em>week</em>.
+ * </desc>
+ * </deflist>
+ */
++ (id) dateWithNaturalLanguageString: (NSString*)string
+ locale: (NSDictionary*)locale;
+#endif
+
+/** Returns an autoreleased instance with the date and time value given
+ * by the string using the ISO standard format YYYY-MM-DD HH:MM:SS +/-HHHMM
+ * (all the fields of which must be present).
+ */
++ (id) dateWithString: (NSString*)description;
+
+#if OS_API_VERSION(MAC_OS_X_VERSION_10_6,GS_API_LATEST)
+/** Returns an autoreleased NSDate instance whose value is offset from
+ * that of the given date by the specified interval in seconds.
+ */
++ (id) dateWithTimeInterval: (NSTimeInterval)seconds sinceDate: (NSDate*)date;
+#endif
+
+/** Returns an autoreleased instance with the offset from the unix system
+ * reference date of 1 January 1970, GMT.
+ */
++ (id) dateWithTimeIntervalSince1970: (NSTimeInterval)seconds;
+
+/** Returns an autoreleased instance with the offset from the current
+ * date/time given by seconds (which may be fractional).
+ */
++ (id) dateWithTimeIntervalSinceNow: (NSTimeInterval)seconds;
+
+/** Returns an autoreleased instance with the offset from the OpenStep
+ * reference date of 1 January 2001, GMT.
+ */
++ (id) dateWithTimeIntervalSinceReferenceDate: (NSTimeInterval)seconds;
+
+/** Returns an autoreleased instance with the date/time set in the far
+ * past.
+ */
++ (id) distantPast;
+
+/** Returns an autoreleased instance with the date/time set in the far
+ * future.
+ */
++ (id) distantFuture;
+
+/** Returns the time interval between the reference date and the current
+ * time.
+ */
++ (NSTimeInterval) timeIntervalSinceReferenceDate;
+
+/** Returns an autorelease date instance formed by adding the specified
+ * time interval in seconds to the receiver's time interval.
+ */
+- (id) addTimeInterval: (NSTimeInterval)seconds;
+
+/** Returns the time interval between the receivers value and the
+ * OpenStep reference date of 1 Jan 2001 GMT.
+ */
+- (NSComparisonResult) compare: (NSDate*)otherDate;
+
+#if OS_API_VERSION(MAC_OS_X_VERSION_10_6,GS_API_LATEST)
+/** Returns an autoreleased NSDate instance whose value is offset from
+ * that of the receiver by the specified interval.
+ */
+- (id) dateByAddingTimeInterval: (NSTimeInterval)ti;
+#endif
+
+/** Returns an autoreleased instance of the [NSCalendarDate] class whose
+ * date/time value is the same as that of the receiver, and which uses
+ * the formatString and timeZone specified.
+ */
+- (NSCalendarDate*) dateWithCalendarFormat: (NSString*)formatString
+ timeZone: (NSTimeZone*)timeZone;
+
+/** Returns a string representation of the receiver formatted according
+ * to the default format string, time zone, and locale.
+ */
+- (NSString*) description;
+
+/** Returns a string representation of the receiver formatted according
+ * to the specified format string, time zone, and locale.
+ */
+- (NSString*) descriptionWithCalendarFormat: (NSString*)format
+ timeZone: (NSTimeZone*)aTimeZone
+ locale: (NSDictionary*)l;
+
+/** Returns a string representation of the receiver formatted according
+ * to the default format string and time zone, but using the given locale.
+ */
+- (NSString*) descriptionWithLocale: (id)locale;
+
+/** Returns the earlier of the receiver and otherDate.<br />
+ * If the two represent identical date/time values, returns the receiver.
+ */
+- (NSDate*) earlierDate: (NSDate*)otherDate;
+
+/** Returns an instance initialised with the current date/time.
+ */
+- (id) init;
+
+/** Returns an instance with the date and time value given
+ * by the string using the ISO standard format YYYY-MM-DD HH:MM:SS +/-HHHMM
+ * (all the fields of which must be present).
+ */
+- (id) initWithString: (NSString*)description;
+
+/** Returns an instance with the given offset from anotherDate.
+ */
+- (id) initWithTimeInterval: (NSTimeInterval)secsToBeAdded
+ sinceDate: (NSDate*)anotherDate;
+
+#if OS_API_VERSION(GS_API_MACOSX, GS_API_LATEST)
+/** Returns an instance with the offset from the unix system
+ * reference date of 1 January 1970, GMT.
+ */
+- (id) initWithTimeIntervalSince1970: (NSTimeInterval)seconds;
+#endif
+
+/** Returns an instance with the offset from the current date/time.
+ */
+- (id) initWithTimeIntervalSinceNow: (NSTimeInterval)secsToBeAdded;
+
+/** <init />
+ * Returns an instance with the given offset from the OpenStep
+ * reference date of 1 January 2001, GMT.
+ */
+- (id) initWithTimeIntervalSinceReferenceDate: (NSTimeInterval)secs;
+
+/** Returns NO if other is not a date, otherwise returns the result of
+ * calling the -isEqualtoDate: method.
+ */
+- (BOOL) isEqual: (id)other;
+
+/** Returns whether the receiver is exactly equal to other, to the limit
+ * of the NSTimeInterval precision.<br />
+ * This is the behavior of the current MacOS-X system, not that of the
+ * OpenStep specification (which counted two dates within a second of
+ * each other as being equal).<br />
+ * The old behavior meant that two dates equal to a third date were not
+ * necessarily equal to each other (confusing), and meant that there was
+ * no reasonable way to use a date as a dictionary key or store dates
+ * in a set.
+ */
+- (BOOL) isEqualToDate: (NSDate*)other;
+
+/** Returns the earlier of the receiver and otherDate.<br />
+ * If the two represent identical date/time values, returns the receiver.
+ */
+- (NSDate*) laterDate: (NSDate*)otherDate;
+
+/** Returns the time interval between the receivers value and the
+ * unix system reference date of 1 January 1970, GMT.
+ */
+- (NSTimeInterval) timeIntervalSince1970;
+
+/** Returns the time interval between the receivers value and that of the
+ * otherDate argument. If otherDate is earlier than the receiver, the
+ * returned value will be positive, if it is later it will be negative.<br />
+ * For current (2011) OSX compatibility, this method returns NaN if otherDate
+ * is nil ... do not write code depending on that behavior.
+ */
+- (NSTimeInterval) timeIntervalSinceDate: (NSDate*)otherDate;
+
+/** Returns the time interval between the receivers value and the
+ * current date/time. If the receiver represents a date/time in
+ * the past this will be negative, if it is in the future the
+ * returned value will be positive.
+ */
+- (NSTimeInterval) timeIntervalSinceNow;
+
+/** Returns the time interval between the receivers value and the
+ * OpenStep reference date of 1 Jan 2001 GMT.
+ */
+- (NSTimeInterval) timeIntervalSinceReferenceDate;
+
+@end
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif /* __NSDate_h_GNUSTEP_BASE_INCLUDE*/
diff --git a/gcc/testsuite/objc-obj-c++-shared/GNUStep/Foundation/NSEnumerator.h b/gcc/testsuite/objc-obj-c++-shared/GNUStep/Foundation/NSEnumerator.h
new file mode 100644
index 0000000..5f31abd
--- /dev/null
+++ b/gcc/testsuite/objc-obj-c++-shared/GNUStep/Foundation/NSEnumerator.h
@@ -0,0 +1,63 @@
+/*
+ NSEnumerator.h
+
+ Copyright (C) 1998 Free Software Foundation, Inc.
+
+ Author: Scott Christley <scottc@net-community.com>
+ Date: January 1998
+
+ This file is part of the GNUstep Base Library.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free
+ Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02111 USA.
+*/
+
+#ifndef __NSEnumerator_h_GNUSTEP_BASE_INCLUDE
+#define __NSEnumerator_h_GNUSTEP_BASE_INCLUDE
+#import "../GNUstepBase/GSVersionMacros.h"
+
+#import "NSObject.h"
+
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+@class GS_GENERIC_CLASS(NSArray, ElementT);
+
+typedef struct
+{
+ unsigned long state;
+ __unsafe_unretained id *itemsPtr;
+ unsigned long *mutationsPtr;
+ unsigned long extra[5];
+} NSFastEnumerationState;
+
+@protocol NSFastEnumeration
+- (NSUInteger) countByEnumeratingWithState: (NSFastEnumerationState *)state
+ objects: (__unsafe_unretained id[])stackbuf
+ count: (NSUInteger)len;
+@end
+
+@interface GS_GENERIC_CLASS(NSEnumerator, IterT) : NSObject <NSFastEnumeration>
+- (GS_GENERIC_CLASS(NSArray, IterT) *) allObjects;
+- (GS_GENERIC_TYPE(IterT)) nextObject;
+@end
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif /* __NSEnumerator_h_GNUSTEP_BASE_INCLUDE */
diff --git a/gcc/testsuite/objc-obj-c++-shared/GNUStep/Foundation/NSGeometry.h b/gcc/testsuite/objc-obj-c++-shared/GNUStep/Foundation/NSGeometry.h
new file mode 100644
index 0000000..05888b7
--- /dev/null
+++ b/gcc/testsuite/objc-obj-c++-shared/GNUStep/Foundation/NSGeometry.h
@@ -0,0 +1,609 @@
+/* Interface for NSGeometry routines for GNUStep
+ * Copyright (C) 1995 Free Software Foundation, Inc.
+ *
+ * Written by: Adam Fedor <fedor@boulder.colorado.edu>
+ * Date: 1995,199
+ *
+ * This file is part of the GNUstep Base Library.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02111 USA.
+ */
+
+#ifndef __NSGeometry_h_GNUSTEP_BASE_INCLUDE
+#define __NSGeometry_h_GNUSTEP_BASE_INCLUDE
+#import "../GNUstepBase/GSVersionMacros.h"
+
+#import <objc/objc.h>
+
+#import "NSString.h"
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+/**** Type, Constant, and Macro Definitions **********************************/
+
+#ifndef MAX
+#define MAX(a,b) \
+ ({__typeof__(a) _MAX_a = (a); __typeof__(b) _MAX_b = (b); \
+ _MAX_a > _MAX_b ? _MAX_a : _MAX_b; })
+#define GS_DEFINED_MAX
+#endif
+
+#ifndef MIN
+#define MIN(a,b) \
+ ({__typeof__(a) _MIN_a = (a); __typeof__(b) _MIN_b = (b); \
+ _MIN_a < _MIN_b ? _MIN_a : _MIN_b; })
+#define GS_DEFINED_MIN
+#endif
+
+/**
+<example>{
+ CGFloat x;
+ CGFloat y;
+}</example>
+ <p>Represents a 2-d cartesian position.</p> */
+typedef struct _NSPoint NSPoint;
+struct _NSPoint
+{
+ CGFloat x;
+ CGFloat y;
+};
+
+#if OS_API_VERSION(GS_API_MACOSX, GS_API_LATEST)
+/** Array of NSPoint structs. */
+typedef NSPoint *NSPointArray;
+/** Pointer to NSPoint struct. */
+typedef NSPoint *NSPointPointer;
+#endif
+
+/**
+<example>{
+ CGFloat width;
+ CGFloat height;
+}</example>
+ <p>Floating point rectangle size.</p> */
+typedef struct _NSSize NSSize;
+struct _NSSize
+{
+ CGFloat width;
+ CGFloat height;
+};
+
+#if OS_API_VERSION(GS_API_MACOSX, GS_API_LATEST)
+/** Array of NSSize structs. */
+typedef NSSize *NSSizeArray;
+/** Pointer to NSSize struct. */
+typedef NSSize *NSSizePointer;
+#endif
+
+/**
+<example>{
+ NSPoint origin;
+ NSSize size;
+}</example>
+
+ <p>Rectangle.</p> */
+typedef struct _NSRect NSRect;
+struct _NSRect
+{
+ NSPoint origin;
+ NSSize size;
+};
+
+#if OS_API_VERSION(GS_API_MACOSX, GS_API_LATEST)
+/** Array of NSRect structs. */
+typedef NSRect *NSRectArray;
+/** Pointer to NSRect struct. */
+typedef NSRect *NSRectPointer;
+#endif
+
+enum
+{
+ NSMinXEdge = 0,
+ NSMinYEdge = 1,
+ NSMaxXEdge = 2,
+ NSMaxYEdge = 3
+};
+/** Sides of a rectangle.
+<example>
+{
+ NSMinXEdge,
+ NSMinYEdge,
+ NSMaxXEdge,
+ NSMaxYEdge
+}
+</example>
+ */
+typedef NSUInteger NSRectEdge;
+
+/**
+<example>{
+ CGFloat top;
+ CGFloat left;
+ CGFloat bottom;
+ CGFloat right;
+}</example>
+
+ <p>A description of the distance between the edges of two rectangles.</p> */
+#if OS_API_VERSION(MAC_OS_X_VERSION_10_7, GS_API_LATEST)
+typedef struct NSEdgeInsets {
+ CGFloat top;
+ CGFloat left;
+ CGFloat bottom;
+ CGFloat right;
+} NSEdgeInsets;
+#endif
+
+/** Point at 0,0 */
+static const NSPoint NSZeroPoint __attribute__((unused)) = {0.0,0.0};
+/** Zero-size rectangle at 0,0 */
+static const NSRect NSZeroRect __attribute__((unused)) = {{0.0,0.0},{0.0,0.0}};
+/** Zero size */
+static const NSSize NSZeroSize __attribute__((unused)) = {0.0,0.0};
+
+#if OS_API_VERSION(MAC_OS_X_VERSION_10_7, GS_API_LATEST)
+/** Zero edge insets **/
+static const NSEdgeInsets NSEdgeInsetsZero __attribute__((unused)) = {0.0,0.0,0.0,0.0};
+#endif
+
+/**** Function Prototypes ****************************************************/
+
+/*
+ * All but the most complex functions are declared static inline in this
+ * header file so that they are maximally efficient. In order to provide
+ * true functions (for code modules that don't have this header) this
+ * header is included in NSGeometry.m where the functions are no longer
+ * declared inline.
+ */
+#ifdef IN_NSGEOMETRY_M
+#define GS_GEOM_SCOPE extern
+#define GS_GEOM_ATTR
+#else
+#define GS_GEOM_SCOPE static inline
+#define GS_GEOM_ATTR __attribute__((unused))
+#endif
+
+/** Create Basic Structures... **/
+
+GS_GEOM_SCOPE NSPoint
+NSMakePoint(CGFloat x, CGFloat y) GS_GEOM_ATTR;
+
+/** Returns an NSPoint having x-coordinate X and y-coordinate Y. */
+GS_GEOM_SCOPE NSPoint
+NSMakePoint(CGFloat x, CGFloat y)
+{
+ NSPoint point;
+
+ point.x = x;
+ point.y = y;
+ return point;
+}
+
+GS_GEOM_SCOPE NSSize
+NSMakeSize(CGFloat w, CGFloat h) GS_GEOM_ATTR;
+
+/** Returns an NSSize having width w and height h. */
+GS_GEOM_SCOPE NSSize
+NSMakeSize(CGFloat w, CGFloat h)
+{
+ NSSize size;
+
+ size.width = w;
+ size.height = h;
+ return size;
+}
+
+GS_GEOM_SCOPE NSRect
+NSMakeRect(CGFloat x, CGFloat y, CGFloat w, CGFloat h) GS_GEOM_ATTR;
+
+/** Returns an NSRect having point of origin (x, y) and size {w, h}. */
+GS_GEOM_SCOPE NSRect
+NSMakeRect(CGFloat x, CGFloat y, CGFloat w, CGFloat h)
+{
+ NSRect rect;
+
+ rect.origin.x = x;
+ rect.origin.y = y;
+ rect.size.width = w;
+ rect.size.height = h;
+ return rect;
+}
+
+/** Constructs NSEdgeInsets. **/
+#if OS_API_VERSION(MAC_OS_X_VERSION_10_7, GS_API_LATEST)
+GS_GEOM_SCOPE NSEdgeInsets
+NSEdgeInsetsMake(CGFloat top, CGFloat left,
+ CGFloat bottom, CGFloat right) GS_GEOM_ATTR;
+
+GS_GEOM_SCOPE NSEdgeInsets
+NSEdgeInsetsMake(CGFloat top, CGFloat left, CGFloat bottom, CGFloat right)
+{
+ NSEdgeInsets edgeInsets;
+
+ edgeInsets.top = top;
+ edgeInsets.left = left;
+ edgeInsets.bottom = bottom;
+ edgeInsets.right = right;
+
+ return edgeInsets;
+}
+
+#if OS_API_VERSION(MAC_OS_X_VERSION_10_10, GS_API_LATEST)
+/** Compares two edge insets for equality. **/
+GS_EXPORT BOOL
+NSEdgeInsetsEqual(NSEdgeInsets e1, NSEdgeInsets e2);
+#endif
+
+#endif
+
+/** Get a Rectangle's Coordinates... **/
+
+GS_GEOM_SCOPE CGFloat
+NSMaxX(NSRect aRect) GS_GEOM_ATTR;
+
+/** Returns the greatest x-coordinate value still inside aRect. */
+GS_GEOM_SCOPE CGFloat
+NSMaxX(NSRect aRect)
+{
+ return aRect.origin.x + aRect.size.width;
+}
+
+GS_GEOM_SCOPE CGFloat
+NSMaxY(NSRect aRect) GS_GEOM_ATTR;
+
+/** Returns the greatest y-coordinate value still inside aRect. */
+GS_GEOM_SCOPE CGFloat
+NSMaxY(NSRect aRect)
+{
+ return aRect.origin.y + aRect.size.height;
+}
+
+GS_GEOM_SCOPE CGFloat
+NSMidX(NSRect aRect) GS_GEOM_ATTR;
+
+/** Returns the x-coordinate of aRect's middle point. */
+GS_GEOM_SCOPE CGFloat
+NSMidX(NSRect aRect)
+{
+ return aRect.origin.x + (aRect.size.width / 2.0);
+}
+
+GS_GEOM_SCOPE CGFloat
+NSMidY(NSRect aRect) GS_GEOM_ATTR;
+
+/** Returns the y-coordinate of aRect's middle point. */
+GS_GEOM_SCOPE CGFloat
+NSMidY(NSRect aRect)
+{
+ return aRect.origin.y + (aRect.size.height / 2.0);
+}
+
+GS_GEOM_SCOPE CGFloat
+NSMinX(NSRect aRect) GS_GEOM_ATTR;
+
+/** Returns the least x-coordinate value still inside aRect. */
+GS_GEOM_SCOPE CGFloat
+NSMinX(NSRect aRect)
+{
+ return aRect.origin.x;
+}
+
+GS_GEOM_SCOPE CGFloat
+NSMinY(NSRect aRect) GS_GEOM_ATTR;
+
+/** Returns the least y-coordinate value still inside aRect. */
+GS_GEOM_SCOPE CGFloat
+NSMinY(NSRect aRect)
+{
+ return aRect.origin.y;
+}
+
+GS_GEOM_SCOPE CGFloat
+NSWidth(NSRect aRect) GS_GEOM_ATTR;
+
+/** Returns aRect's width. */
+GS_GEOM_SCOPE CGFloat
+NSWidth(NSRect aRect)
+{
+ return aRect.size.width;
+}
+
+GS_GEOM_SCOPE CGFloat
+NSHeight(NSRect aRect) GS_GEOM_ATTR;
+
+/** Returns aRect's height. */
+GS_GEOM_SCOPE CGFloat
+NSHeight(NSRect aRect)
+{
+ return aRect.size.height;
+}
+
+GS_GEOM_SCOPE BOOL
+NSIsEmptyRect(NSRect aRect) GS_GEOM_ATTR;
+
+/** Returns 'YES' iff the area of aRect is zero (i.e., iff either
+ * of aRect's width or height is negative or zero). */
+GS_GEOM_SCOPE BOOL
+NSIsEmptyRect(NSRect aRect)
+{
+ return ((NSWidth(aRect) > 0) && (NSHeight(aRect) > 0)) ? NO : YES;
+}
+
+/** Modify a Copy of a Rectangle... **/
+
+GS_GEOM_SCOPE NSRect
+NSOffsetRect(NSRect aRect, CGFloat dx, CGFloat dy) GS_GEOM_ATTR;
+
+/** Returns the rectangle obtained by translating aRect
+ * horizontally by dx and vertically by dy. */
+GS_GEOM_SCOPE NSRect
+NSOffsetRect(NSRect aRect, CGFloat dx, CGFloat dy)
+{
+ NSRect rect = aRect;
+
+ rect.origin.x += dx;
+ rect.origin.y += dy;
+ return rect;
+}
+
+GS_GEOM_SCOPE NSRect
+NSInsetRect(NSRect aRect, CGFloat dX, CGFloat dY) GS_GEOM_ATTR;
+
+/** Returns the rectangle obtained by moving each of aRect's
+ * horizontal sides inward by dy and each of aRect's vertical
+ * sides inward by dx.<br />
+ * NB. For MacOS-X compatability, this is permitted to return
+ * a rectanglew with nagative width or height, strange as that seems.
+ */
+GS_GEOM_SCOPE NSRect
+NSInsetRect(NSRect aRect, CGFloat dX, CGFloat dY)
+{
+ NSRect rect;
+
+ rect = NSOffsetRect(aRect, dX, dY);
+ rect.size.width -= (2 * dX);
+ rect.size.height -= (2 * dY);
+ return rect;
+}
+
+/** Divides aRect into two rectangles (namely slice and remainder) by
+ * "cutting" aRect---parallel to, and a distance amount from the given edge
+ * of aRect. You may pass 0 in as either of slice or
+ * remainder to avoid obtaining either of the created rectangles. */
+GS_EXPORT void
+NSDivideRect(NSRect aRect,
+ NSRect *slice,
+ NSRect *remainder,
+ CGFloat amount,
+ NSRectEdge edge);
+
+/** Returns a rectangle obtained by expanding aRect minimally
+ * so that all four of its defining components are integers. */
+GS_EXPORT NSRect
+NSIntegralRect(NSRect aRect);
+
+/** Compute a Third Rectangle from Two Rectangles... **/
+
+GS_GEOM_SCOPE NSRect
+NSUnionRect(NSRect aRect, NSRect bRect) GS_GEOM_ATTR;
+
+/** Returns the smallest rectangle which contains both aRect
+ * and bRect (modulo a set of measure zero). If either of aRect
+ * or bRect is an empty rectangle, then the other rectangle is
+ * returned. If both are empty, then the empty rectangle is returned. */
+GS_GEOM_SCOPE NSRect
+NSUnionRect(NSRect aRect, NSRect bRect)
+{
+ NSRect rect;
+
+ if (NSIsEmptyRect(aRect) && NSIsEmptyRect(bRect))
+ return NSMakeRect(0.0,0.0,0.0,0.0);
+ else if (NSIsEmptyRect(aRect))
+ return bRect;
+ else if (NSIsEmptyRect(bRect))
+ return aRect;
+
+ rect = NSMakeRect(MIN(NSMinX(aRect), NSMinX(bRect)),
+ MIN(NSMinY(aRect), NSMinY(bRect)), 0.0, 0.0);
+
+ rect = NSMakeRect(NSMinX(rect),
+ NSMinY(rect),
+ MAX(NSMaxX(aRect), NSMaxX(bRect)) - NSMinX(rect),
+ MAX(NSMaxY(aRect), NSMaxY(bRect)) - NSMinY(rect));
+
+ return rect;
+}
+
+GS_GEOM_SCOPE NSRect
+NSIntersectionRect(NSRect aRect, NSRect bRect) GS_GEOM_ATTR;
+
+/** Returns the largest rectangle which lies in both aRect and
+ * bRect. If aRect and bRect have empty intersection (or, rather,
+ * intersection of measure zero, since this includes having their
+ * intersection be only a point or a line), then the empty
+ * rectangle is returned. */
+GS_GEOM_SCOPE NSRect
+NSIntersectionRect (NSRect aRect, NSRect bRect)
+{
+ if (NSMaxX(aRect) <= NSMinX(bRect) || NSMaxX(bRect) <= NSMinX(aRect)
+ || NSMaxY(aRect) <= NSMinY(bRect) || NSMaxY(bRect) <= NSMinY(aRect))
+ {
+ return NSMakeRect(0.0, 0.0, 0.0, 0.0);
+ }
+ else
+ {
+ NSRect rect;
+
+ if (NSMinX(aRect) <= NSMinX(bRect))
+ rect.origin.x = bRect.origin.x;
+ else
+ rect.origin.x = aRect.origin.x;
+
+ if (NSMinY(aRect) <= NSMinY(bRect))
+ rect.origin.y = bRect.origin.y;
+ else
+ rect.origin.y = aRect.origin.y;
+
+ if (NSMaxX(aRect) >= NSMaxX(bRect))
+ rect.size.width = NSMaxX(bRect) - rect.origin.x;
+ else
+ rect.size.width = NSMaxX(aRect) - rect.origin.x;
+
+ if (NSMaxY(aRect) >= NSMaxY(bRect))
+ rect.size.height = NSMaxY(bRect) - rect.origin.y;
+ else
+ rect.size.height = NSMaxY(aRect) - rect.origin.y;
+
+ return rect;
+ }
+}
+
+/** Test geometric relationships... **/
+
+/** Returns 'YES' iff aRect's and bRect's origin and size are the same. */
+GS_EXPORT BOOL
+NSEqualRects(NSRect aRect, NSRect bRect) GS_GEOM_ATTR;
+
+/** Returns 'YES' iff aSize's and bSize's width and height are the same. */
+GS_EXPORT BOOL
+NSEqualSizes(NSSize aSize, NSSize bSize) GS_GEOM_ATTR;
+
+/** Returns 'YES' iff aPoint's and bPoint's x- and y-coordinates
+ * are the same. */
+GS_EXPORT BOOL
+NSEqualPoints(NSPoint aPoint, NSPoint bPoint) GS_GEOM_ATTR;
+
+GS_GEOM_SCOPE BOOL
+NSMouseInRect(NSPoint aPoint, NSRect aRect, BOOL flipped) GS_GEOM_ATTR;
+
+/** Returns 'YES' iff aPoint is inside aRect. */
+GS_GEOM_SCOPE BOOL
+NSMouseInRect(NSPoint aPoint, NSRect aRect, BOOL flipped)
+{
+ if (flipped)
+ {
+ return ((aPoint.x >= NSMinX(aRect))
+ && (aPoint.y >= NSMinY(aRect))
+ && (aPoint.x < NSMaxX(aRect))
+ && (aPoint.y < NSMaxY(aRect))) ? YES : NO;
+ }
+ else
+ {
+ return ((aPoint.x >= NSMinX(aRect))
+ && (aPoint.y > NSMinY(aRect))
+ && (aPoint.x < NSMaxX(aRect))
+ && (aPoint.y <= NSMaxY(aRect))) ? YES : NO;
+ }
+}
+
+GS_GEOM_SCOPE BOOL
+NSPointInRect(NSPoint aPoint, NSRect aRect) GS_GEOM_ATTR;
+
+/** Just like 'NSMouseInRect(aPoint, aRect, YES)'. */
+GS_GEOM_SCOPE BOOL
+NSPointInRect(NSPoint aPoint, NSRect aRect)
+{
+ return NSMouseInRect(aPoint, aRect, YES);
+}
+
+GS_GEOM_SCOPE BOOL
+NSContainsRect(NSRect aRect, NSRect bRect) GS_GEOM_ATTR;
+
+/** Returns 'YES' iff aRect totally encloses bRect. NOTE: For
+ * this to be the case, aRect cannot be empty, nor can any side
+ * of bRect go beyond any side of aRect. Note that this behavior
+ * is different than the original OpenStep behavior, where the sides
+ * of bRect could not touch aRect. */
+GS_GEOM_SCOPE BOOL
+NSContainsRect(NSRect aRect, NSRect bRect)
+{
+ return (!NSIsEmptyRect(bRect)
+ && (NSMinX(aRect) <= NSMinX(bRect))
+ && (NSMinY(aRect) <= NSMinY(bRect))
+ && (NSMaxX(aRect) >= NSMaxX(bRect))
+ && (NSMaxY(aRect) >= NSMaxY(bRect))) ? YES : NO;
+}
+
+#if OS_API_VERSION(GS_API_MACOSX, GS_API_LATEST)
+GS_GEOM_SCOPE BOOL
+NSIntersectsRect(NSRect aRect, NSRect bRect) GS_GEOM_ATTR;
+
+/** Returns YES if aRect and bRect have non-zero intersection area
+ (intersecting at a line or a point doesn't count). */
+GS_GEOM_SCOPE BOOL
+NSIntersectsRect(NSRect aRect, NSRect bRect)
+{
+ /* Note that intersecting at a line or a point doesn't count */
+ return (NSMaxX(aRect) <= NSMinX(bRect)
+ || NSMaxX(bRect) <= NSMinX(aRect)
+ || NSMaxY(aRect) <= NSMinY(bRect)
+ || NSMaxY(bRect) <= NSMinY(aRect)
+ || NSIsEmptyRect(aRect)
+ || NSIsEmptyRect(bRect)) ? NO : YES;
+}
+#endif
+
+/** Get a String Representation... **/
+
+#ifdef __OBJC__
+/** Returns an NSString of the form "{x=X; y=Y}", where
+ * X and Y are the x- and y-coordinates of aPoint, respectively. */
+GS_EXPORT NSString *
+NSStringFromPoint(NSPoint aPoint);
+
+/** Returns an NSString of the form "{x=X; y=Y; width=W; height=H}",
+ * where X, Y, W, and H are the x-coordinate, y-coordinate,
+ * width, and height of aRect, respectively. */
+GS_EXPORT NSString *
+NSStringFromRect(NSRect aRect);
+
+/** Returns an NSString of the form "{width=W; height=H}", where
+ * W and H are the width and height of aSize, respectively. */
+GS_EXPORT NSString *
+NSStringFromSize(NSSize aSize);
+
+/** Parses point from string of form "<code>{x=a; y=b}</code>". (0,0) returned
+ if parsing fails. */
+GS_EXPORT NSPoint NSPointFromString(NSString* string);
+
+/** Parses size from string of form "<code>{width=a; height=b}</code>". Size of
+ 0,0 returned if parsing fails. */
+GS_EXPORT NSSize NSSizeFromString(NSString* string);
+
+/** Parses point from string of form "<code>{x=a; y=b; width=c;
+ height=d}</code>". Rectangle of 0 size at origin returned if parsing
+ fails.
+*/
+GS_EXPORT NSRect NSRectFromString(NSString* string);
+
+#endif /* __OBJC__ */
+
+#ifdef GS_DEFINED_MAX
+#undef GS_DEFINED_MAX
+#undef MAX
+#endif
+
+#ifdef GS_DEFINED_MIN
+#undef GS_DEFINED_MIN
+#undef MIN
+#endif
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif /* __NSGeometry_h_GNUSTEP_BASE_INCLUDE */
diff --git a/gcc/testsuite/objc-obj-c++-shared/GNUStep/Foundation/NSObjCRuntime.h b/gcc/testsuite/objc-obj-c++-shared/GNUStep/Foundation/NSObjCRuntime.h
new file mode 100644
index 0000000..189af80
--- /dev/null
+++ b/gcc/testsuite/objc-obj-c++-shared/GNUStep/Foundation/NSObjCRuntime.h
@@ -0,0 +1,317 @@
+/** Interface to ObjC runtime for GNUStep
+ Copyright (C) 1995, 1997, 2000 Free Software Foundation, Inc.
+
+ Written by: Andrew Kachites McCallum <mccallum@gnu.ai.mit.edu>
+ Date: 1995
+
+ This file is part of the GNUstep Base Library.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free
+ Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02111 USA.
+
+ AutogsdocSource: NSObjCRuntime.m
+ AutogsdocSource: NSLog.m
+
+ */
+
+#ifndef __NSObjCRuntime_h_GNUSTEP_BASE_INCLUDE
+#define __NSObjCRuntime_h_GNUSTEP_BASE_INCLUDE
+
+#ifdef __cplusplus
+#ifndef __STDC_LIMIT_MACROS
+#define __STDC_LIMIT_MACROS 1
+#endif
+#endif
+
+#import "../GNUstepBase/GSVersionMacros.h"
+#import "../GNUstepBase/GSConfig.h"
+#import "../GNUstepBase/GNUstep.h"
+#if __BLOCKS__
+#import "../GNUstepBase/GSBlocks.h"
+#endif
+
+#include <stdarg.h>
+#include <limits.h>
+#include <float.h>
+
+/* PA HP-UX kludge. */
+#if defined(__hppa__) && defined(__hpux__) && !defined(PRIuPTR)
+#define PRIuPTR "lu"
+#endif
+
+/* IRIX kludge. */
+#if defined(__sgi)
+/* IRIX 6.5 <inttypes.h> provides all definitions, but only for C99
+ compilations. */
+#define PRId8 "hhd"
+#define PRIu8 "hhu"
+#if (_MIPS_SZLONG == 32)
+#define PRId64 "lld"
+#define PRIu64 "llu"
+#endif
+/* This doesn't match <inttypes.h>, which always has "lld" here, but the
+ arguments are uint64_t, int64_t, which are unsigned long, long for
+ 64-bit in <sgidefs.h>. */
+#if (_MIPS_SZLONG == 64)
+#define PRId64 "ld"
+#define PRIu64 "lu"
+#endif
+/* This doesn't match <inttypes.h>, which has "u" here, but the arguments
+ are uintptr_t, which is always unsigned long. */
+#define PRIuPTR "lu"
+#endif
+
+/* Solaris < 10 kludge. */
+#if defined(__sun__) && defined(__svr4__) && !defined(PRIuPTR)
+#if defined(__arch64__) || defined (__x86_64__)
+#define PRIuPTR "lu"
+#define PRIdPTR "ld"
+#define PRIxPTR "lx"
+#else
+#define PRIuPTR "u"
+#define PRIdPTR "d"
+#define PRIxPTR "x"
+#endif
+#endif
+
+
+/* These typedefs must be in place before GSObjCRuntime.h is imported.
+ */
+
+#if !defined(NSINTEGER_DEFINED)
+typedef intptr_t NSInteger;
+typedef uintptr_t NSUInteger;
+# define NSIntegerMax INTPTR_MAX
+# define NSIntegerMin INTPTR_MIN
+# define NSUIntegerMax UINTPTR_MAX
+#endif /* !defined(NSINTEGER_DEFINED) */
+
+#if !defined(CGFLOAT_DEFINED)
+#if GS_SIZEOF_VOIDP == 8
+#define CGFLOAT_IS_DBL 1
+typedef double CGFloat;
+#define CGFLOAT_MIN DBL_MIN
+#define CGFLOAT_MAX DBL_MAX
+#else
+typedef float CGFloat;
+#define CGFLOAT_MIN FLT_MIN
+#define CGFLOAT_MAX FLT_MAX
+#endif
+#endif /* !defined(CGFLOAT_DEFINED) */
+
+#define NSINTEGER_DEFINED 1
+#define CGFLOAT_DEFINED 1
+#ifndef NS_AUTOMATED_REFCOUNT_UNAVAILABLE
+# if __has_feature(objc_arc)
+# define NS_AUTOMATED_REFCOUNT_UNAVAILABLE \
+ __attribute__((unavailable("Not available with automatic reference counting")))
+# else
+# define NS_AUTOMATED_REFCOUNT_UNAVAILABLE
+# endif
+#endif
+
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+
+/*
+ * We can have strongly typed enums in C++11 mode or when the objc_fixed_enum
+ * feature is availble.
+ */
+#if (__has_feature(objc_fixed_enum) || (__cplusplus && (__cplusplus > 199711L) && __has_extension(cxx_strong_enums)))
+# define _GS_NAMED_ENUM(ty, name) enum name : ty name; enum name : ty
+# define _GS_ANON_ENUM(ty) enum : ty
+# if __cplusplus
+# define NS_OPTIONS(ty,name) ty name; enum : ty
+# else
+# define NS_OPTIONS(ty,name) NS_ENUM(ty,name)
+# endif
+#else // this provides less information, but works with older compilers
+# define _GS_NAMED_ENUM(ty, name) ty name; enum
+# define _GS_ANON_ENUM(ty) enum
+# define NS_OPTIONS(ty, name) NS_ENUM(ty, name)
+#endif
+// A bit of fairy dust to expand NS_ENUM to the correct variant
+#define _GS_GET_ENUM_MACRO(_first,_second,NAME,...) NAME
+/* The trick here is that placing the variadic args first will push the name
+ * that the _GS_GET_ENUM_MACRO expands to into the correct position.
+ */
+#define NS_ENUM(...) _GS_GET_ENUM_MACRO(__VA_ARGS__,_GS_NAMED_ENUM,_GS_ANON_ENUM)(__VA_ARGS__)
+
+/*
+ * If the compiler supports nullability qualifiers, we define the macros for
+ * non-null sections.
+ */
+#if __has_feature(nullability)
+# define NS_ASSUME_NONNULL_BEGIN _Pragma("clang assume_nonnull begin")
+# define NS_ASSUME_NONNULL_END _Pragma("clang assume_nonnull end")
+#else
+# define NS_ASSUME_NONNULL_BEGIN
+# define NS_ASSUME_NONNULL_END
+#endif
+
+/*
+ * Backwards compatibility macro for instance type.
+ */
+#if !__has_feature(objc_instancetype)
+# define instancetype id
+#endif
+
+/*
+ * Backwards compatibility macros for Objective-C lightweight generics.
+ */
+#if __has_feature(objc_generics)
+# define GS_GENERIC_CLASS(clz, ...) clz<__VA_ARGS__>
+# define GS_GENERIC_TYPE_F(typeRef, fallback) typeRef
+#else
+# define GS_GENERIC_CLASS(clz, ...) clz
+# define GS_GENERIC_TYPE_F(typeRef, fallback) fallback
+#endif
+#define GS_GENERIC_TYPE(typeRef) GS_GENERIC_TYPE_F(typeRef, id)
+
+/**
+ * Backwards compatibility macro for the objc_designated_initializer attribute
+ */
+#if __has_attribute(objc_designated_initializer)
+# define NS_DESIGNATED_INITIALIZER __attribute__((objc_designated_initializer))
+#else
+# define NS_DESIGNATED_INITIALIZER
+#endif
+
+/** Bitfield used to specify options to control enumeration over collections.
+ */
+typedef NS_OPTIONS(NSUInteger, NSEnumerationOptions)
+{
+ NSEnumerationConcurrent = (1UL << 0), /** Specifies that the enumeration
+ * is concurrency-safe. Note that this does not mean that it will be
+ * carried out in a concurrent manner, only that it can be.
+ */
+
+ NSEnumerationReverse = (1UL << 1) /** Specifies that the enumeration should
+ * happen in the opposite of the natural order of the collection.
+ */
+};
+
+
+/** Bitfield used to specify options to control the sorting of collections.
+ */
+typedef NS_OPTIONS(NSUInteger, NSSortOptions)
+{
+ NSSortConcurrent = (1UL << 0), /** Specifies that the sort
+ * is concurrency-safe. Note that this does not mean that it will be
+ * carried out in a concurrent manner, only that it can be.
+ */
+ NSSortStable = (1UL << 4) /** Specifies that the sort should keep
+ * equal objects in the same order in the collection.
+ */
+};
+
+
+#import "../GNUstepBase/GSObjCRuntime.h"
+
+#if OS_API_VERSION(MAC_OS_X_VERSION_10_5,GS_API_LATEST)
+GS_EXPORT NSString *NSStringFromProtocol(Protocol *aProtocol);
+GS_EXPORT Protocol *NSProtocolFromString(NSString *aProtocolName);
+#endif
+GS_EXPORT SEL NSSelectorFromString(NSString *aSelectorName);
+GS_EXPORT NSString *NSStringFromSelector(SEL aSelector);
+GS_EXPORT SEL NSSelectorFromString(NSString *aSelectorName);
+GS_EXPORT Class NSClassFromString(NSString *aClassName);
+GS_EXPORT NSString *NSStringFromClass(Class aClass);
+GS_EXPORT const char *NSGetSizeAndAlignment(const char *typePtr,
+ NSUInteger *sizep, NSUInteger *alignp);
+
+#if OS_API_VERSION(GS_API_NONE, GS_API_NONE)
+/* Logging */
+/**
+ * OpenStep spec states that log messages go to stderr, but just in case
+ * someone wants them to go somewhere else, they can implement a function
+ * like this and assign a pointer to it to _NSLog_printf_handler.
+ */
+typedef void NSLog_printf_handler (NSString* message);
+GS_EXPORT NSLog_printf_handler *_NSLog_printf_handler;
+GS_EXPORT int _NSLogDescriptor;
+@class NSRecursiveLock;
+GS_EXPORT NSRecursiveLock *GSLogLock(void);
+#endif
+
+GS_EXPORT void NSLog(NSString *format, ...) NS_FORMAT_FUNCTION(1,2);
+GS_EXPORT void NSLogv(NSString *format, va_list args) NS_FORMAT_FUNCTION(1,0);
+
+#ifndef YES
+#define YES 1
+#endif
+#ifndef NO
+#define NO 0
+#endif
+#ifndef nil
+#define nil 0
+#endif
+
+/**
+ * Contains values <code>NSOrderedSame</code>, <code>NSOrderedAscending</code>
+ * <code>NSOrderedDescending</code>, for left hand side equals, less than, or
+ * greater than right hand side.
+ */
+typedef NS_ENUM(NSInteger, NSComparisonResult)
+{
+ NSOrderedAscending = (NSInteger)-1, NSOrderedSame, NSOrderedDescending
+};
+
+enum {NSNotFound = NSIntegerMax};
+
+#if __BLOCKS__
+DEFINE_BLOCK_TYPE(NSComparator, NSComparisonResult, id, id);
+#endif
+
+/**
+ * Declare the foundation export macro as an alias to GS_EXPORT
+ */
+#define FOUNDATION_EXPORT GS_EXPORT
+
+#if defined(__cplusplus)
+}
+#endif
+
+/**
+ * Declare Apple availability macros for compatibility purposes as no-ops.
+ */
+#define NS_CLASS_AVAILABLE(...)
+#define NS_AVAILABLE(...)
+#define NS_AVAILABLE_MAC(...)
+#define NS_DEPRECATED(...)
+#define NS_DEPRECATED_MAC(...)
+#define NS_ENUM_AVAILABLE(...)
+#define NS_ENUM_AVAILABLE_MAC(...)
+#define NS_ENUM_DEPRECATED(...)
+#define NS_ENUM_DEPRECATED_MAC(...)
+#define NS_CLASS_AVAILABLE(...)
+#define NS_CLASS_DEPRECATED(...)
+#define NS_CLASS_AVAILABLE_MAC(...)
+#define NS_CLASS_DEPRECATED_MAC(...)
+#define NS_UNAVAILABLE
+
+/* Define root class NS macro */
+#ifndef NS_ROOT_CLASS
+#if __has_attribute(objc_root_class)
+#define NS_ROOT_CLASS __attribute__((objc_root_class))
+#else
+#define NS_ROOT_CLASS
+#endif
+#endif
+
+#endif /* __NSObjCRuntime_h_GNUSTEP_BASE_INCLUDE */
diff --git a/gcc/testsuite/objc-obj-c++-shared/GNUStep/Foundation/NSObject.h b/gcc/testsuite/objc-obj-c++-shared/GNUStep/Foundation/NSObject.h
new file mode 100644
index 0000000..35647ea
--- /dev/null
+++ b/gcc/testsuite/objc-obj-c++-shared/GNUStep/Foundation/NSObject.h
@@ -0,0 +1,594 @@
+/**Interface for NSObject for GNUStep
+ Copyright (C) 1995, 1996, 1998 Free Software Foundation, Inc.
+
+ Written by: Andrew Kachites McCallum <mccallum@gnu.ai.mit.edu>
+ Date: 1995
+
+ This file is part of the GNUstep Base Library.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free
+ Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02111 USA.
+
+ AutogsdocSource: NSObject.m
+ */
+
+#ifndef __NSObject_h_GNUSTEP_BASE_INCLUDE
+#define __NSObject_h_GNUSTEP_BASE_INCLUDE
+
+#import "NSObjCRuntime.h"
+#import <objc/objc.h>
+#import "NSZone.h"
+
+#ifdef GS_WITH_GC
+#undef GS_WITH_GC
+#endif
+#define GS_WITH_GC 0
+
+#import "../GNUstepBase/GNUstep.h"
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+@class NSArchiver;
+@class NSArray;
+@class NSCoder;
+@class NSDictionary;
+@class NSPortCoder;
+@class NSMethodSignature;
+@class NSMutableString;
+@class NSRecursiveLock;
+@class NSString;
+@class NSInvocation;
+@class Protocol;
+
+/**
+ * The NSObject protocol describes a minimal set of methods that all
+ * objects are expected to support. You should be able to send any
+ * of the messages listed in this protocol to an object, and be safe
+ * in assuming that the receiver can handle it.
+ */
+@protocol NSObject
+/**
+ * Returns the class of the receiver. If the receiver is a proxy, then this
+ * may return the class of the proxy target. Use -isProxy to determine whether
+ * the receiver is a proxy. If you wish to find the real class of the
+ * receiver, ignoring proxies, then use object_getClass().
+ */
+- (Class) class;
+/**
+ * Returns the superclass of receiver's class. If the receiver is a proxy,
+ * then this may return the class of the proxy target. Use -isProxy to
+ * determine whether the receiver is a proxy. If you wish to find the real
+ * superclass of the receiver's class, ignoring proxies, then use
+ * class_getSuperclass(object_getClass()).
+ */
+- (Class) superclass;
+/**
+ * Returns whether the receiver is equal to the argument. Defining equality is
+ * complex, so be careful when implementing this method. Collections such as
+ * NSSet depend on the behaviour of this method. In particular, this method
+ * must be commutative, so for any objects a and b:
+ *
+ * [a isEqual: b] == [b isEqual: a]
+ *
+ * This means that you must be very careful when returning YES if the argument
+ * is of another class. For example, if you define a number class that returns
+ * YES if the argument is a string representation of the number, then this will
+ * break because the string will not recognise your object as being equal to
+ * itself.
+ *
+ * If two objects are equal, then they must have the same hash value, however
+ * equal hash values do not imply equality.
+ */
+- (BOOL) isEqual: (id)anObject;
+/**
+ * Returns YES if the receiver is an instance of the class, an instance of the
+ * subclass, or (in the case of proxies), an instance of something that can be
+ * treated as an instance of the class.
+ */
+- (BOOL) isKindOfClass: (Class)aClass;
+/**
+ * Returns YES if the receiver is an instance of the class or (in the case of
+ * proxies), an instance of something that can be treated as an instance of the
+ * class.
+ *
+ * Calling this method is rarely the correct thing to do. In most cases, a
+ * subclass can be substituted for a superclass, so you should never need to
+ * check that an object is really an instance of a specific class and not a
+ * subclass.
+ */
+- (BOOL) isMemberOfClass: (Class)aClass;
+/**
+ * Returns YES if the receiver is a proxy, NO otherwise. The default
+ * implementation of this method in NSObject returns NO, while the
+ * implementation in NSProxy returns YES.
+ */
+- (BOOL) isProxy;
+/**
+ * Returns a hash value for the object. All objects that are equal *MUST*
+ * return the same hash value. For efficient storage in sets, or as keys in
+ * dictionaries, different objects should return hashes spread evenly over the
+ * range of an integer.
+ *
+ * An object may not return different values from this method after being
+ * stored in a collection. This typically means that ether the hash value must
+ * be constant after the object's creation, or that the object may not be
+ * modified while stored in an unordered collection.
+ */
+- (NSUInteger) hash;
+/**
+ * Returns the receiver. In a proxy, this may (but is not required to) return
+ * the proxied object.
+ */
+- (id) self;
+/**
+ * Performs the specified selector. The selector must correspond to a method
+ * that takes no arguments.
+ */
+- (id) performSelector: (SEL)aSelector;
+/**
+ * Performs the specified selector, with the object as the argument. This
+ * method does not perform any automatic unboxing, so the selector must
+ * correspond to a method that takes one object argument.
+ */
+- (id) performSelector: (SEL)aSelector
+ withObject: (id)anObject;
+/**
+ * Performs the specified selector, with the objects as the arguments. This
+ * method does not perform any automatic unboxing, so the selector must
+ * correspond to a method that takes two object arguments.
+ */
+- (id) performSelector: (SEL)aSelector
+ withObject: (id)object1
+ withObject: (id)object2;
+/**
+ * Returns YES if the object can respond to messages with the specified
+ * selector. The default implementation in NSObject returns YES if the
+ * receiver has a method corresponding to the method, but other classes may
+ * return YES if they can respond to a selector using one of the various
+ * forwarding mechanisms.
+ */
+- (BOOL) respondsToSelector: (SEL)aSelector;
+/**
+ * Returns YES if the receiver conforms to the specified protocol.
+ */
+- (BOOL) conformsToProtocol: (Protocol*)aProtocol;
+/**
+ * Increments the reference count of the object and returns the receiver. In
+ * garbage collected mode, this method does nothing. In automated reference
+ * counting mode, you may neither implement this method nor call it directly.
+ */
+- (id) retain NS_AUTOMATED_REFCOUNT_UNAVAILABLE;
+/**
+ * Decrements the reference count of the object and destroys if it there are no
+ * remaining references. In garbage collected mode, this method does nothing.
+ * In automated reference counting mode, you may neither implement this method
+ * nor call it directly.
+ */
+- (oneway void) release NS_AUTOMATED_REFCOUNT_UNAVAILABLE;
+/**
+ * Performs a deferred -release operation. The object's reference count is
+ * decremented at the end of the scope of the current autorelease pool,
+ * identified either by a -drain message sent to the current NSAutoreleasePool
+ * instance, or in more recent versions of Objective-C by the end of an
+ * @autorelease_pool scope.
+ *
+ * In garbage collected mode, this method does nothing. In automated reference
+ * counting mode, you may neither implement this method nor call it directly.
+ */
+- (id) autorelease NS_AUTOMATED_REFCOUNT_UNAVAILABLE;
+/**
+ * Returns the current retain count of an object. This does not include the
+ * result of any pending autorelease operations.
+ *
+ * Code that relies on this method returning a sane value is broken. For
+ * singletons, it may return NSUIntegerMax. Even when it is tracking a retain
+ * count, it will not include on-stack pointers in manual retain/release mode,
+ * pointers marked as __unsafe_unretain or __weak in ARC mode, or pending
+ * autorelease operations. Its value is therefore largely meaningless. It can
+ * occasionally be useful for debugging.
+ */
+- (NSUInteger) retainCount NS_AUTOMATED_REFCOUNT_UNAVAILABLE;
+/**
+ * Returns the description of the object. This is used by the %@ format
+ * specifier in strings.
+ */
+- (NSString*) description;
+/**
+ * Returns the zone of the object.
+ */
+- (NSZone*) zone NS_AUTOMATED_REFCOUNT_UNAVAILABLE;
+@end
+
+/**
+ * This protocol must be adopted by any class wishing to support copying -
+ * ie where instances of the class should be able to create new instances
+ * which are copies of the original and, where a class has mutable and
+ * immutable versions, where the copies are immutable.
+ */
+@protocol NSCopying
+/**
+ * Called by [NSObject-copy] passing NSDefaultMallocZone() as zone.<br />
+ * This method returns a copy of the receiver and, where the receiver is a
+ * mutable variant of a class which has an immutable partner class, the
+ * object returned is an instance of that immutable class.<br />
+ * The new object is <em>not</em> autoreleased, and is considered to be
+ * 'owned' by the calling code ... which is therefore responsible for
+ * releasing it.<br />
+ * In the case where the receiver is an instance of a container class,
+ * it is undefined whether contained objects are merely retained in the
+ * new copy, or are themselves copied, or whether some other mechanism
+ * entirely is used.
+ */
+- (id) copyWithZone: (NSZone*)zone;
+@end
+
+/**
+ * This protocol must be adopted by any class wishing to support
+ * mutable copying - ie where instances of the class should be able
+ * to create mutable copies of themselves.
+ */
+@protocol NSMutableCopying
+/**
+ * Called by [NSObject-mutableCopy] passing NSDefaultMallocZone() as zone.<br />
+ * This method returns a copy of the receiver and, where the receiver is an
+ * immutable variant of a class which has a mutable partner class, the
+ * object returned is an instance of that mutable class.
+ * The new object is <em>not</em> autoreleased, and is considered to be
+ * 'owned' by the calling code ... which is therefore responsible for
+ * releasing it.<br />
+ * In the case where the receiver is an instance of a container class,
+ * it is undefined whether contained objects are merely retained in the
+ * new copy, or are themselves copied, or whether some other mechanism
+ * entirely is used.
+ */
+- (id) mutableCopyWithZone: (NSZone*)zone;
+@end
+
+/**
+ * This protocol must be adopted by any class wishing to support
+ * saving and restoring instances to an archive, or copying them
+ * to remote processes via the Distributed Objects mechanism.
+ */
+@protocol NSCoding
+
+/**
+ * Called when it is time for receiver to be serialized for writing to an
+ * archive or network connection. Receiver should record all of its instance
+ * variables using methods on aCoder. See documentation for [NSCoder],
+ * [NSArchiver], [NSKeyedArchiver], and/or [NSPortCoder] for more information.
+ */
+- (void) encodeWithCoder: (NSCoder*)aCoder;
+
+/**
+ * Called on a freshly allocated receiver when it is time to reconstitute from
+ * serialized bytes in an archive or from a network connection. Receiver
+ * should load all of its instance variables using methods on aCoder. See
+ * documentation for [NSCoder], [NSUnarchiver], [NSKeyedUnarchiver], and/or
+ * [NSPortCoder] for more information.
+ */
+- (id) initWithCoder: (NSCoder*)aDecoder;
+@end
+
+@protocol NSSecureCoding <NSCoding>
++ (BOOL)supportsSecureCoding;
+@end
+
+
+GS_ROOT_CLASS @interface NSObject <NSObject>
+{
+ /**
+ * Points to instance's class. Used by runtime to access method
+ * implementations, etc.. Set in +alloc, Unlike other instance variables,
+ * which are cleared there.
+ */
+ Class isa;
+}
+
+#if OS_API_VERSION(MAC_OS_X_VERSION_10_5, GS_API_LATEST)
+/** On a system which performs garbage collection, you should implement
+ * this method to execute code when the receiver is collected.<br />
+ * You must not call this method yourself (except when a subclass
+ * calls the superclass method within its own implementation).
+ */
+- (void) finalize;
+#endif
+
+#if OS_API_VERSION(GS_API_MACOSX, GS_API_LATEST)
+- (NSString*) className;
+#endif
+
++ (id) allocWithZone: (NSZone*)z;
++ (id) alloc;
++ (Class) class;
+
+/**
+ * This method is automatically invoked on any class which implements it
+ * when the class is loaded into the runtime.<br />
+ * It is also invoked on any category where the method is implemented
+ * when that category is loaded into the runtime.<br />
+ * The +load method is called directly by the runtime and you should never
+ * send a +load message to a class yourself.<br />
+ * This method is called <em>before</em> the +initialize message is sent
+ * to the class, so you cannot depend on class initialisation having been
+ * performed, or upon other classes existing (apart from superclasses of
+ * the receiver, since +load is called on superclasses before it is called
+ * on their subclasses).<br />
+ * As a gross generalisation, it is safe to use C code, including
+ * most ObjectiveC runtime functions within +load, but attempting to send
+ * messages to ObjectiveC objects is likely to fail.<br />
+ * In GNUstep, this method is implemented for NSObject to perform some
+ * initialisation for the base library.<br />
+ * If you implement +load for a class, don't call [super load] in your
+ * implementation.
+ */
++ (void) load;
+
+/**
+ * This message is automatically sent to a class by the runtime. It is
+ * sent once for each class, just before the class is used for the first
+ * time (excluding any automatic call to +load by the runtime).<br />
+ * The message is sent in a thread-safe manner ... other threads may not
+ * call methods of the class until +initialize has finished executing.<br />
+ * If the class has a superclass, its implementation of +initialize is
+ * called first.<br />
+ * If the class does not implement +initialize then the implementation
+ * in the closest superclass may be called. This means that +initialize may
+ * be called more than once, and the recommended way to handle this by
+ * using the
+ * <code>
+ * if (self == [classname class])
+ * </code>
+ * conditional to check whether the method is being called for a subclass.<br />
+ * You should never call +initialize yourself ... let the runtime do it.<br />
+ * You can implement +initialize in your own class if you need to.
+ * NSObject's implementation handles essential root object and base
+ * library initialization.<br />
+ * It should be safe to call [super initialize] in your implementation
+ * of +initialize.
+ */
++ (void) initialize;
++ (IMP) instanceMethodForSelector: (SEL)aSelector;
++ (NSMethodSignature*) instanceMethodSignatureForSelector: (SEL)aSelector;
++ (BOOL) instancesRespondToSelector: (SEL)aSelector;
++ (BOOL) isSubclassOfClass: (Class)aClass;
++ (id) new;
++ (void) poseAsClass: (Class)aClassObject;
++ (id) setVersion: (NSInteger)aVersion;
++ (NSInteger) version;
+
+- (id) awakeAfterUsingCoder: (NSCoder*)aDecoder;
+- (Class) classForArchiver;
+- (Class) classForCoder;
+- (id) copy;
+- (void) dealloc;
+- (void) doesNotRecognizeSelector: (SEL)aSelector;
+- (void) forwardInvocation: (NSInvocation*)anInvocation;
+- (id) init;
+- (IMP) methodForSelector: (SEL)aSelector;
+- (NSMethodSignature*) methodSignatureForSelector: (SEL)aSelector;
+- (id) mutableCopy;
+- (id) replacementObjectForArchiver: (NSArchiver*)anArchiver;
+- (id) replacementObjectForCoder: (NSCoder*)anEncoder;
+- (Class) superclass;
+#if OS_API_VERSION(MAC_OS_X_VERSION_10_5, GS_API_LATEST)
+/**
+ * This method will be called when attempting to send a message a class that
+ * does not understand it. The class may install a new method for the given
+ * selector and return YES, otherwise it should return NO.
+ *
+ * Note: This method is only reliable when using the GNUstep runtime. If you
+ * require compatibility with the GCC runtime, you must also implement
+ * -forwardInvocation: with equivalent semantics. This will be considerably
+ * slower, but more portable.
+ */
++ (BOOL) resolveClassMethod: (SEL)name;
+
+/**
+ * This method will be called when attempting to send a message an instance
+ * that does not understand it. The class may install a new method for the
+ * given selector and return YES, otherwise it should return NO.
+ *
+ * Note: This method is only reliable when using the GNUstep runtime. If you
+ * require compatibility with the GCC runtime, you must also implement
+ * -forwardInvocation: with equivalent semantics. This will be considerably
+ * slower, but more portable.
+ */
++ (BOOL) resolveInstanceMethod: (SEL)name;
+#endif
+#if OS_API_VERSION(MAC_OS_X_VERSION_10_6, GS_API_LATEST)
+/**
+ * Returns an auto-accessing proxy for the given object. This proxy sends a
+ * -beginContentAccess message to the receiver when it is created and an
+ * -endContentAccess message when it is destroyed. This prevents an object
+ * that implements the NSDiscardableContent protocol from having its contents
+ * discarded for as long as the proxy exists.
+ *
+ * On systems using the GNUstep runtime, messages send to the proxy will be
+ * slightly slower than direct messages. With the GCC runtime, they will be
+ * approximately two orders of magnitude slower. The GNUstep runtime,
+ * therefore, is strongly recommended for code calling this method.
+ */
+- (id) autoContentAccessingProxy;
+
+/**
+ * If an object does not understand a message, it may delegate it to another
+ * object. Returning nil indicates that forwarding should not take place. The
+ * default implementation of this returns nil, but care should be taken when
+ * subclassing NSObject subclasses and overriding this method that
+ * the superclass implementation is called if returning nil.
+ *
+ * Note: This method is only reliable when using the GNUstep runtime and code
+ * compiled with clang. If you require compatibility with GCC and the GCC
+ * runtime, you must also implement -forwardInvocation: with equivalent
+ * semantics. This will be considerably slower, but more portable.
+ */
+- (id) forwardingTargetForSelector: (SEL)aSelector;
+
+#endif
+@end
+
+/**
+ * Used to allocate memory to hold an object, and initialise the
+ * class of the object to be aClass etc. The allocated memory will
+ * be extraBytes larger than the space actually needed to hold the
+ * instance variables of the object.<br />
+ * This function is used by the [NSObject+allocWithZone:] method.
+ */
+GS_EXPORT id
+NSAllocateObject(Class aClass, NSUInteger extraBytes, NSZone *zone);
+
+/**
+ * Used to release the memory used by an object.<br />
+ * This function is used by the [NSObject-dealloc] method.
+ */
+GS_EXPORT void
+NSDeallocateObject(id anObject);
+
+/**
+ * Used to copy anObject. This makes a bitwise copy of anObject to
+ * memory allocated from zone. The allocated memory will be extraBytes
+ * longer than that necessary to actually store the instance variables
+ * of the copied object.<br />
+ */
+GS_EXPORT NSObject *
+NSCopyObject(NSObject *anObject, NSUInteger extraBytes, NSZone *zone);
+
+/**
+ * Returns a flag to indicate whether anObject should be retained or
+ * copied in order to make a copy in the specified zone.<br />
+ * Basically, this tests to see if anObject was allocated from
+ * requestedZone and returns YES if it was.
+ */
+GS_EXPORT BOOL
+NSShouldRetainWithZone(NSObject *anObject, NSZone *requestedZone);
+
+GS_EXPORT BOOL
+NSDecrementExtraRefCountWasZero(id anObject);
+
+GS_EXPORT NSUInteger
+NSExtraRefCount(id anObject);
+
+GS_EXPORT void
+NSIncrementExtraRefCount(id anObject);
+
+#if OS_API_VERSION(GS_API_NONE, GS_API_NONE)
+
+/** Global lock to be used by classes when operating on any global
+ data that invoke other methods which also access global; thus,
+ creating the potential for deadlock. */
+GS_EXPORT NSRecursiveLock *gnustep_global_lock;
+
+@interface NSObject (NEXTSTEP)
+- (id) error:(const char *)aString, ...;
+/* - (const char *) name;
+ Removed because OpenStep has -(NSString*)name; */
+@end
+
+#if GS_API_VERSION(GS_API_NONE, 011700)
+@interface NSObject (GNUstep)
++ (void) enableDoubleReleaseCheck: (BOOL)enable;
+@end
+#endif
+
+#endif
+
+#import "NSDate.h"
+/**
+ * Declares some methods for sending messages to self after a fixed delay.
+ * (These methods <em>are</em> in OpenStep and OS X.)
+ */
+@interface NSObject (TimedPerformers)
+
+/**
+ * Cancels any perform operations set up for the specified target
+ * in the current run loop.
+ */
++ (void) cancelPreviousPerformRequestsWithTarget: (id)obj;
+
+/**
+ * Cancels any perform operations set up for the specified target
+ * in the current loop, but only if the value of aSelector and argument
+ * with which the performs were set up match those supplied.<br />
+ * Matching of the argument may be either by pointer equality or by
+ * use of the [NSObject-isEqual:] method.
+ */
++ (void) cancelPreviousPerformRequestsWithTarget: (id)obj
+ selector: (SEL)s
+ object: (id)arg;
+/**
+ * Sets given message to be sent to this instance after given delay,
+ * in any run loop mode. See [NSRunLoop].
+ */
+- (void) performSelector: (SEL)s
+ withObject: (id)arg
+ afterDelay: (NSTimeInterval)seconds;
+
+/**
+ * Sets given message to be sent to this instance after given delay,
+ * in given run loop modes. See [NSRunLoop].
+ */
+- (void) performSelector: (SEL)s
+ withObject: (id)arg
+ afterDelay: (NSTimeInterval)seconds
+ inModes: (NSArray*)modes;
+@end
+
+#if OS_API_VERSION(MAC_OS_X_VERSION_10_6, GS_API_LATEST)
+/**
+ * The NSDiscardableContent protocol is used by objects which encapsulate data
+ * which may be discarded if resource constraints are exceeded. These
+ * constraints are typically, but not always, related memory.
+ */
+@protocol NSDiscardableContent
+
+/**
+ * This method is called before any access to the object. It returns YES if
+ * the object's content is still valid. The caller must call -endContentAccess
+ * once for every call to -beginContentAccess;
+ */
+- (BOOL) beginContentAccess;
+
+/**
+ * Discards the contents of the object if it is not currently being edited.
+ */
+- (void) discardContentIfPossible;
+
+/**
+ * This method indicates that the caller has finished accessing the contents of
+ * the object adopting this protocol. Every call to -beginContentAccess must
+ * be be paired with a call to this method after the caller has finished
+ * accessing the contents.
+ */
+- (void) endContentAccess;
+
+/**
+ * Returns YES if the contents of the object have been discarded, either via a
+ * call to -discardContentIfPossible while the object is not in use, or by some
+ * implementation dependent mechanism.
+ */
+- (BOOL) isContentDiscarded;
+@end
+#endif
+#if defined(__cplusplus)
+}
+#endif
+
+#if !NO_GNUSTEP && !defined(GNUSTEP_BASE_INTERNAL)
+#import "../GNUstepBase/NSObject+GNUstepBase.h"
+#endif
+
+#endif /* __NSObject_h_GNUSTEP_BASE_INCLUDE */
diff --git a/gcc/testsuite/objc-obj-c++-shared/GNUStep/Foundation/NSRange.h b/gcc/testsuite/objc-obj-c++-shared/GNUStep/Foundation/NSRange.h
new file mode 100644
index 0000000..845d44a
--- /dev/null
+++ b/gcc/testsuite/objc-obj-c++-shared/GNUStep/Foundation/NSRange.h
@@ -0,0 +1,235 @@
+/*
+ * Copyright (C) 1995,1999 Free Software Foundation, Inc.
+ *
+ * Written by: Adam Fedor <fedor@boulder.colorado.edu>
+ * Date: 1995
+ *
+ * This file is part of the GNUstep Base Library.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02111 USA.
+ */
+
+#ifndef __NSRange_h_GNUSTEP_BASE_INCLUDE
+#define __NSRange_h_GNUSTEP_BASE_INCLUDE
+#import "../GNUstepBase/GSVersionMacros.h"
+
+/**** Included Headers *******************************************************/
+
+#import "NSObject.h"
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+@class NSException;
+@class NXConstantString;
+
+/**** Type, Constant, and Macro Definitions **********************************/
+
+#ifndef MAX
+#define MAX(a,b) \
+ ({__typeof__(a) _MAX_a = (a); __typeof__(b) _MAX_b = (b); \
+ _MAX_a > _MAX_b ? _MAX_a : _MAX_b; })
+#define GS_DEFINED_MAX
+#endif
+
+#ifndef MIN
+#define MIN(a,b) \
+ ({__typeof__(a) _MIN_a = (a); __typeof__(b) _MIN_b = (b); \
+ _MIN_a < _MIN_b ? _MIN_a : _MIN_b; })
+#define GS_DEFINED_MIN
+#endif
+
+/**
+ * <example>
+{
+ NSUInteger location;
+ NSUInteger length;
+}</example>
+ * <p>
+ * The NSRange type is used to specify ranges of locations,
+ * typically items in an array, characters in a string, and bytes
+ * in a data object.
+ * </p>
+ * <p>
+ * As 'boundary' or 'fencepost' errors are a particularly common
+ * problem in programming, it is important that you understand
+ * how an NSRange works.
+ * </p>
+ * <p>
+ * An NSRange consists of a <em>location</em> and a <em>length</em>. The
+ * points that are considered to lie in a range are the integers from
+ * the location to the location plus the length, so the number
+ * of points in a range is the length of the range plus one.<br />
+ * However, if you consider these points like the marks on a
+ * ruler, you can only store information <strong>between</strong>
+ * points. So the number of items that can be stored in a range
+ * is the length of the range.
+ * </p>
+ */
+typedef struct _NSRange NSRange;
+struct _NSRange
+{
+ NSUInteger location;
+ NSUInteger length;
+};
+
+#if OS_API_VERSION(GS_API_MACOSX, GS_API_LATEST)
+/** Pointer to an NSRange structure. */
+typedef NSRange *NSRangePointer;
+#endif
+
+/**** Function Prototypes ****************************************************/
+
+/*
+ * All but the most complex functions are declared static inline in this
+ * header file so that they are maximally efficient. In order to provide
+ * true functions (for code modules that don't have this header) this
+ * header is included in NSRange.m where the functions are no longer
+ * declared inline.
+ */
+#ifdef IN_NSRANGE_M
+#define GS_RANGE_SCOPE extern
+#define GS_RANGE_ATTR
+#else
+#define GS_RANGE_SCOPE static inline
+#define GS_RANGE_ATTR __attribute__((unused))
+#endif
+
+GS_RANGE_SCOPE NSUInteger
+NSMaxRange(NSRange range) GS_RANGE_ATTR;
+
+/** Returns top end of range (location + length). */
+GS_RANGE_SCOPE NSUInteger
+NSMaxRange(NSRange range)
+{
+ return range.location + range.length;
+}
+
+GS_RANGE_SCOPE BOOL
+NSLocationInRange(NSUInteger location, NSRange range) GS_RANGE_ATTR;
+
+/** Returns whether location is greater than or equal to range's location
+ * and less than its max.
+ */
+GS_RANGE_SCOPE BOOL
+NSLocationInRange(NSUInteger location, NSRange range)
+{
+ return (location >= range.location) && (location < NSMaxRange(range));
+}
+
+/** Convenience method for raising an NSRangeException. */
+GS_EXPORT void _NSRangeExceptionRaise (void);
+/* NB: The implementation of _NSRangeExceptionRaise is:
+ [NSException raise: NSRangeException
+ format: @"Range location + length too great"];
+
+ _NSRangeExceptionRaise is defined in NSRange.m so that this
+ file (NSRange.h) can be included without problems in the
+ implementation of the base classes themselves. */
+
+GS_RANGE_SCOPE NSRange
+NSMakeRange(NSUInteger location, NSUInteger length) GS_RANGE_ATTR;
+
+/** Creates new range starting at location and of given length. */
+GS_RANGE_SCOPE NSRange
+NSMakeRange(NSUInteger location, NSUInteger length)
+{
+ NSRange range;
+ NSUInteger end = location + length;
+
+ if (end < location || end < length)
+ {
+ _NSRangeExceptionRaise ();
+ }
+ range.location = location;
+ range.length = length;
+ return range;
+}
+
+GS_RANGE_SCOPE BOOL
+NSEqualRanges(NSRange range1, NSRange range2) GS_RANGE_ATTR;
+
+/** Returns whether range1 and range2 have same location and length. */
+GS_RANGE_SCOPE BOOL
+NSEqualRanges(NSRange range1, NSRange range2)
+{
+ return ((range1.location == range2.location)
+ && (range1.length == range2.length));
+}
+
+GS_RANGE_SCOPE NSRange
+NSUnionRange(NSRange range1, NSRange range2) GS_RANGE_ATTR;
+
+/** Returns range going from minimum of aRange's and bRange's locations to
+ maximum of their two max's. */
+GS_RANGE_SCOPE NSRange
+NSUnionRange(NSRange aRange, NSRange bRange)
+{
+ NSRange range;
+
+ range.location = MIN(aRange.location, bRange.location);
+ range.length = MAX(NSMaxRange(aRange), NSMaxRange(bRange))
+ - range.location;
+ return range;
+}
+
+GS_RANGE_SCOPE NSRange
+NSIntersectionRange(NSRange range1, NSRange range2) GS_RANGE_ATTR;
+
+/** Returns range containing indices existing in both aRange and bRange. If
+ * the returned length is 0, the location is undefined and should be ignored.
+ */
+GS_RANGE_SCOPE NSRange
+NSIntersectionRange (NSRange aRange, NSRange bRange)
+{
+ NSRange range;
+
+ if (NSMaxRange(aRange) < bRange.location
+ || NSMaxRange(bRange) < aRange.location)
+ return NSMakeRange(0, 0);
+
+ range.location = MAX(aRange.location, bRange.location);
+ range.length = MIN(NSMaxRange(aRange), NSMaxRange(bRange))
+ - range.location;
+ return range;
+}
+
+
+@class NSString;
+
+/** Returns string of form {location=a, length=b}. */
+GS_EXPORT NSString *NSStringFromRange(NSRange range);
+
+/** Parses range from string of form {location=a, length=b}; returns range
+ with 0 location and length if this fails. */
+GS_EXPORT NSRange NSRangeFromString(NSString *aString);
+
+#ifdef GS_DEFINED_MAX
+#undef GS_DEFINED_MAX
+#undef MAX
+#endif
+
+#ifdef GS_DEFINED_MIN
+#undef GS_DEFINED_MIN
+#undef MIN
+#endif
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif /* __NSRange_h_GNUSTEP_BASE_INCLUDE */
diff --git a/gcc/testsuite/objc-obj-c++-shared/GNUStep/Foundation/NSString.h b/gcc/testsuite/objc-obj-c++-shared/GNUStep/Foundation/NSString.h
new file mode 100644
index 0000000..7863d94
--- /dev/null
+++ b/gcc/testsuite/objc-obj-c++-shared/GNUStep/Foundation/NSString.h
@@ -0,0 +1,977 @@
+/* Interface for NSString for GNUstep
+ Copyright (C) 1995, 1996, 1999 Free Software Foundation, Inc.
+
+ Written by: Andrew Kachites McCallum <mccallum@gnu.ai.mit.edu>
+ Date: 1995
+
+ This file is part of the GNUstep Base Library.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free
+ Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02111 USA.
+ */
+
+/**
+<chapter>
+ <heading>Portable path handling</heading>
+ <p>Portable path handling (across both unix-like and mswindows operating
+ systems) requires some care. A modern operating system uses the concept
+ of a single root to the filesystem, but mswindows has multiple filesystems
+ with no common root, so code must be aware of this. There is also the
+ more minor issue that windows often uses a backslash as a separator between
+ the components of a path and unix-like systems always use forward slash.<br />
+ On windows there is also the issue that two styles of path are used,
+ most commonly with a drive letter and a path on that drive
+ (eg. 'C:\directory\file') but also UNC paths
+ (eg. '//host/share/directory/file') so path handling functions must deal
+ with both formats.
+ </p>
+ <p>GNUstep has three path handling modes, 'gnustep', 'unix', and 'windows'.
+ The mode defaults to 'gnustep' but may be set using the GSPathHandling()
+ function.<br />
+ You should probably stick to using the default 'gnustep' mode in which the
+ path handling methods cope with both 'unix' and 'windows' style paths in
+ portable and tolerant manner:<br />
+ Paths are read in literally so they can be in the native format provided
+ by the operating system or in a non-native format. See
+ [NSFileManager-stringWithFileSystemRepresentation:length:].<br />
+ Paths are written out using the native format of the system the application
+ is running on (eg on windows slashes are converted to backslashes).
+ See [NSFileManager-fileSystemRepresentationWithPath:].<br />
+ The path handling methods accept either a forward or backward slash as a
+ path separator when parsing any path.<br />
+ Unless operating in 'unix' mode, a leading letter followed by a colon is
+ considered the start of a windows style path (the drive specifier), and a
+ path beginning with something of the form '//host/share/' is considered
+ the start of a UNC style path.<br />
+ The path handling methods add forward slashes when building new paths
+ internally or when standardising paths, so those path strings provide
+ a portable representation (as long as they are relative paths, not including
+ system specific roots).<br />
+ An important case to note is that on windows a path which looks at first
+ glance like an absolute path may actually be a relative one.<br />
+ 'C:file' is a relative path because it specifies a file on the C drive
+ but does not say what directory it is in.<br />
+Similarly, '/dir/file' is a relative path because it specifies the full
+location fo a file on a drive, but does not specify which drive it is on.
+ </p>
+<p>As a consequence of this path handling, you are able to work completely
+portably using relative paths (adding components, extensions and
+relative paths to a pth, or removing components, extensions and relative
+paths from a path etc), and when you save paths as strings in files
+which may be transferred to another platform, you should save a relative
+path.<br />
+When you need to know absolute paths of various points in the filesystem,
+you can use various path utility functions to obtain those absolute paths.
+For instance, instead of saving an absolute path to a file, you might want
+to save a path relative to a user's home directory. You could do that by
+calling NSHomeDirectory() to get the home directory, and only saving the
+part of the full path after that prefix.
+</p>
+</chapter>
+ */
+
+#ifndef __NSString_h_GNUSTEP_BASE_INCLUDE
+#define __NSString_h_GNUSTEP_BASE_INCLUDE
+#import "../GNUstepBase/GSVersionMacros.h"
+
+#import "NSObject.h"
+#import "NSRange.h"
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+/**
+ * Type for representing unicode characters. (16-bit)
+ */
+typedef uint16_t unichar;
+
+#if OS_API_VERSION(MAC_OS_X_VERSION_10_5,GS_API_LATEST)
+#define NSMaximumStringLength (INT_MAX-1)
+#endif
+
+@class NSArray;
+@class NSCharacterSet;
+@class NSData;
+@class NSDictionary;
+#if OS_API_VERSION(GS_API_MACOSX, GS_API_LATEST)
+@class NSError;
+@class NSLocale;
+@class NSURL;
+#endif
+
+#define NSMaximumStringLength (INT_MAX-1)
+
+enum
+{
+ NSCaseInsensitiveSearch = 1,
+ NSLiteralSearch = 2,
+ NSBackwardsSearch = 4,
+ NSAnchoredSearch = 8,
+ NSNumericSearch = 64 /* MacOS-X 10.2 */
+#if OS_API_VERSION(MAC_OS_X_VERSION_10_5,GS_API_LATEST)
+ ,
+ NSDiacriticInsensitiveSearch = 128,
+ NSWidthInsensitiveSearch = 256,
+ NSForcedOrderingSearch = 512
+#endif
+#if OS_API_VERSION(MAC_OS_X_VERSION_10_7,GS_API_LATEST)
+ ,
+ /**
+ * Treats the search string as a regular expression. This option may be
+ * combined with NSCaseInsensitiveSearch and NSAnchoredSearch, but no other
+ * search options.
+ *
+ * This option may only be used with the -rangeOfString: family of methods.
+ */
+ NSRegularExpressionSearch = 1024
+#endif
+};
+typedef NSUInteger NSStringCompareOptions;
+
+/**
+ * <p>Enumeration of available encodings for converting between bytes and
+ * characters (in [NSString]s). The ones that are shared with OpenStep and
+ * Cocoa are: <code>NSASCIIStringEncoding, NSNEXTSTEPStringEncoding,
+ * NSJapaneseEUCStringEncoding, NSUTF8StringEncoding,
+ * NSISOLatin1StringEncoding, NSSymbolStringEncoding,
+ * NSNonLossyASCIIStringEncoding, NSShiftJISStringEncoding,
+ * NSISOLatin2StringEncoding, NSUnicodeStringEncoding,
+ * NSWindowsCP1251StringEncoding, NSWindowsCP1252StringEncoding,
+ * NSWindowsCP1253StringEncoding, NSWindowsCP1254StringEncoding,
+ * NSWindowsCP1250StringEncoding, NSISO2022JPStringEncoding,
+ * NSMacOSRomanStringEncoding, NSProprietaryStringEncoding</code>.</p>
+ *
+ * <p>Additional encodings available under GNUstep are:
+ * <code>NSKOI8RStringEncoding, NSISOLatin3StringEncoding,
+ * NSISOLatin4StringEncoding, NSISOCyrillicStringEncoding,
+ * NSISOArabicStringEncoding, NSISOGreekStringEncoding,
+ * NSISOHebrewStringEncoding, NSISOLatin5StringEncoding,
+ * NSISOLatin6StringEncoding, NSISOThaiStringEncoding,
+ * NSISOLatin7StringEncoding, NSISOLatin8StringEncoding,
+ * NSISOLatin9StringEncoding, NSGB2312StringEncoding, NSUTF7StringEncoding,
+ * NSGSM0338StringEncoding, NSBIG5StringEncoding,
+ * NSKoreanEUCStringEncoding</code>.</p>
+ */
+typedef enum _NSStringEncoding
+{
+/* NB. Must not have an encoding with value zero - so we can use zero to
+ tell that a variable that should contain an encoding has not yet been
+ initialised */
+ GSUndefinedEncoding = 0,
+ NSASCIIStringEncoding = 1,
+ NSNEXTSTEPStringEncoding = 2,
+ NSJapaneseEUCStringEncoding = 3,
+ NSUTF8StringEncoding = 4,
+ NSISOLatin1StringEncoding = 5, // ISO-8859-1; West European
+ NSSymbolStringEncoding = 6,
+ NSNonLossyASCIIStringEncoding = 7,
+ NSShiftJISStringEncoding = 8,
+ NSISOLatin2StringEncoding = 9, // ISO-8859-2; East European
+ NSUnicodeStringEncoding = 10,
+ NSUTF16StringEncoding = NSUnicodeStringEncoding, // An alias
+ NSWindowsCP1251StringEncoding = 11,
+ NSWindowsCP1252StringEncoding = 12, // WinLatin1
+ NSWindowsCP1253StringEncoding = 13, // Greek
+ NSWindowsCP1254StringEncoding = 14, // Turkish
+ NSWindowsCP1250StringEncoding = 15, // WinLatin2
+ NSISO2022JPStringEncoding = 21,
+ NSMacOSRomanStringEncoding = 30,
+ NSProprietaryStringEncoding = 31,
+
+ NSKOI8RStringEncoding = 50, // Russian/Cyrillic
+ NSISOLatin3StringEncoding = 51, // ISO-8859-3; South European
+ NSISOLatin4StringEncoding = 52, // ISO-8859-4; North European
+ NSISOCyrillicStringEncoding = 22, // ISO-8859-5
+ NSISOArabicStringEncoding = 53, // ISO-8859-6
+ NSISOGreekStringEncoding = 54, // ISO-8859-7
+ NSISOHebrewStringEncoding = 55, // ISO-8859-8
+ NSISOLatin5StringEncoding = 57, // ISO-8859-9; Turkish
+ NSISOLatin6StringEncoding = 58, // ISO-8859-10; Nordic
+ NSISOThaiStringEncoding = 59, // ISO-8859-11
+/* Possible future ISO-8859 additions
+ // ISO-8859-12
+*/
+ NSISOLatin7StringEncoding = 61, // ISO-8859-13
+ NSISOLatin8StringEncoding = 62, // ISO-8859-14
+ NSISOLatin9StringEncoding = 63, // ISO-8859-15; Replaces ISOLatin1
+ NSGB2312StringEncoding = 56,
+ NSUTF7StringEncoding = 64, // RFC 2152
+ NSGSM0338StringEncoding, // GSM (mobile phone) default alphabet
+ NSBIG5StringEncoding, // Traditional chinese
+ NSKoreanEUCStringEncoding // Korean
+
+#if OS_API_VERSION(MAC_OS_X_VERSION_10_4,GS_API_LATEST)
+ ,
+ NSUTF16BigEndianStringEncoding = 0x90000100,
+ NSUTF16LittleEndianStringEncoding = 0x94000100,
+ NSUTF32StringEncoding = 0x8c000100,
+ NSUTF32BigEndianStringEncoding = 0x98000100,
+ NSUTF32LittleEndianStringEncoding = 0x9c000100
+#endif
+} NSStringEncoding;
+
+enum {
+ NSOpenStepUnicodeReservedBase = 0xF400
+};
+
+#if OS_API_VERSION(MAC_OS_X_VERSION_10_4,GS_API_LATEST)
+enum {
+ NSStringEncodingConversionAllowLossy = 1,
+ NSStringEncodingConversionExternalRepresentation = 2
+};
+typedef NSUInteger NSStringEncodingConversionOptions;
+#endif
+
+/**
+ * <p>
+ * <code>NSString</code> objects represent an immutable string of Unicode 3.0
+ * characters. These may be accessed individually as type
+ * <code>unichar</code>, an unsigned short.<br/>
+ * The [NSMutableString] subclass represents a modifiable string. Both are
+ * implemented as part of a class cluster and the instances you receive may
+ * actually be of unspecified concrete subclasses.
+ * </p>
+ * <p>
+ * A constant <code>NSString</code> can be created using the following syntax:
+ * <code>@"..."</code>, where the contents of the quotes are the
+ * string, using only ASCII characters.
+ * </p>
+ * <p>
+ * A variable string can be created using a C printf-like <em>format</em>,
+ * as in <code>[NSString stringWithFormat: @"Total is %f", t]</code>.
+ * </p>
+ * <p>
+ * To create a concrete subclass of <code>NSString</code>, you must have your
+ * class inherit from <code>NSString</code> and override at least the two
+ * primitive methods - -length and -characterAtIndex:
+ * </p>
+ * <p>
+ * In general the rule is that your subclass must override any
+ * initialiser that you want to use with it. The GNUstep
+ * implementation relaxes that to say that, you may override
+ * only the <em>designated initialiser</em> and the other
+ * initialisation methods should work.
+ * </p>
+ * <p>
+ * Where an NSString instance method returns an NSString object,
+ * the class of the actual object returned may be any subclass
+ * of NSString. The actual value returned may be a new
+ * autoreleased object, an autoreleased copy of the receiver,
+ * or the receiver itsself. While the abstract base class
+ * implementations of methods (other than initialisers) will
+ * avoid returning mutable strings by returning an autoreleased
+ * copy of a mutable receiver, concrete subclasses may behave
+ * differently, so code should not rely upon the mutability of
+ * returned strings nor upon their lifetime being greater than
+ * that of the receiver which returned them.
+ * </p>
+ */
+@interface NSString :NSObject <NSCoding, NSCopying, NSMutableCopying>
+
++ (id) string;
++ (id) stringWithCharacters: (const unichar*)chars
+ length: (NSUInteger)length;
+#if OS_API_VERSION(MAC_OS_X_VERSION_10_4,GS_API_LATEST) && GS_API_VERSION( 10200,GS_API_LATEST)
++ (id) stringWithCString: (const char*)byteString
+ encoding: (NSStringEncoding)encoding;
+#endif
++ (id) stringWithCString: (const char*)byteString
+ length: (NSUInteger)length;
++ (id) stringWithCString: (const char*)byteString;
++ (id) stringWithFormat: (NSString*)format, ... NS_FORMAT_FUNCTION(1,2);
++ (id) stringWithContentsOfFile:(NSString *)path;
+
+// Initializing Newly Allocated Strings
+- (id) init;
+#if OS_API_VERSION(MAC_OS_X_VERSION_10_4,GS_API_LATEST) && GS_API_VERSION( 10200,GS_API_LATEST)
+- (id) initWithBytes: (const void*)bytes
+ length: (NSUInteger)length
+ encoding: (NSStringEncoding)encoding;
+- (id) initWithBytesNoCopy: (void*)bytes
+ length: (NSUInteger)length
+ encoding: (NSStringEncoding)encoding
+ freeWhenDone: (BOOL)flag;
+#endif
+#if OS_API_VERSION(MAC_OS_X_VERSION_10_4,GS_API_LATEST)
++ (id) stringWithContentsOfFile: (NSString*)path
+ usedEncoding: (NSStringEncoding*)enc
+ error: (NSError**)error;
+- (id) initWithContentsOfFile: (NSString*)path
+ usedEncoding: (NSStringEncoding*)enc
+ error: (NSError**)error;
++ (id) stringWithContentsOfFile: (NSString*)path
+ encoding: (NSStringEncoding)enc
+ error: (NSError**)error;
+- (id) initWithContentsOfFile: (NSString*)path
+ encoding: (NSStringEncoding)enc
+ error: (NSError**)error;
++ (id) stringWithContentsOfURL: (NSURL*)url
+ usedEncoding: (NSStringEncoding*)enc
+ error: (NSError**)error;
+- (id) initWithContentsOfURL: (NSURL*)url
+ usedEncoding: (NSStringEncoding*)enc
+ error: (NSError**)error;
++ (id) stringWithContentsOfURL: (NSURL*)url
+ encoding: (NSStringEncoding)enc
+ error: (NSError**)error;
+- (id) initWithContentsOfURL: (NSURL*)url
+ encoding: (NSStringEncoding)enc
+ error: (NSError**)error;
+- (BOOL) writeToFile: (NSString*)path
+ atomically: (BOOL)atomically
+ encoding: (NSStringEncoding)enc
+ error: (NSError**)error;
+- (BOOL) writeToURL: (NSURL*)url
+ atomically: (BOOL)atomically
+ encoding: (NSStringEncoding)enc
+ error: (NSError**)error;
+#endif
+#if OS_API_VERSION(MAC_OS_X_VERSION_10_5,GS_API_LATEST)
+- (NSString*)stringByReplacingOccurrencesOfString: (NSString*)replace
+ withString: (NSString*)by
+ options: (NSStringCompareOptions)opts
+ range: (NSRange)searchRange;
+- (NSString*)stringByReplacingOccurrencesOfString: (NSString*)replace
+ withString: (NSString*)by;
+- (NSString*) stringByReplacingCharactersInRange: (NSRange)aRange
+ withString: (NSString*)by;
+#endif
+- (id) initWithCharactersNoCopy: (unichar*)chars
+ length: (NSUInteger)length
+ freeWhenDone: (BOOL)flag;
+- (id) initWithCharacters: (const unichar*)chars
+ length: (NSUInteger)length;
+- (id) initWithCStringNoCopy: (char*)byteString
+ length: (NSUInteger)length
+ freeWhenDone: (BOOL)flag;
+- (id) initWithCString: (const char*)byteString
+ length: (NSUInteger)length;
+- (id) initWithCString: (const char*)byteString;
+- (id) initWithString: (NSString*)string;
+- (id) initWithFormat: (NSString*)format, ... NS_FORMAT_FUNCTION(1,2);
+- (id) initWithFormat: (NSString*)format
+ arguments: (va_list)argList NS_FORMAT_FUNCTION(1,0);
+- (id) initWithData: (NSData*)data
+ encoding: (NSStringEncoding)encoding;
+- (id) initWithContentsOfFile: (NSString*)path;
+
+// Getting a String's Length
+- (NSUInteger) length;
+
+// Accessing Characters
+- (unichar) characterAtIndex: (NSUInteger)index;
+- (void) getCharacters: (unichar*)buffer;
+- (void) getCharacters: (unichar*)buffer
+ range: (NSRange)aRange;
+
+// Combining Strings
+- (NSString*) stringByAppendingFormat: (NSString*)format, ...
+ NS_FORMAT_FUNCTION(1,2);
+- (NSString*) stringByAppendingString: (NSString*)aString;
+
+// Dividing Strings into Substrings
+- (NSArray*) componentsSeparatedByString: (NSString*)separator;
+- (NSString*) substringFromIndex: (NSUInteger)index;
+- (NSString*) substringToIndex: (NSUInteger)index;
+
+// Finding Ranges of Characters and Substrings
+- (NSRange) rangeOfCharacterFromSet: (NSCharacterSet*)aSet;
+- (NSRange) rangeOfCharacterFromSet: (NSCharacterSet*)aSet
+ options: (NSUInteger)mask;
+- (NSRange) rangeOfCharacterFromSet: (NSCharacterSet*)aSet
+ options: (NSUInteger)mask
+ range: (NSRange)aRange;
+- (NSRange) rangeOfString: (NSString*)string;
+- (NSRange) rangeOfString: (NSString*)string
+ options: (NSUInteger)mask;
+- (NSRange) rangeOfString: (NSString*)aString
+ options: (NSUInteger)mask
+ range: (NSRange)aRange;
+
+// Determining Composed Character Sequences
+- (NSRange) rangeOfComposedCharacterSequenceAtIndex: (NSUInteger)anIndex;
+
+#if OS_API_VERSION(MAC_OS_X_VERSION_10_2,GS_API_LATEST)
+/** Returns a copy of the receiver normalised using the KD form.
+ */
+- (NSString *) decomposedStringWithCompatibilityMapping;
+
+/** Returns a copy of the receiver normalised using the D form.
+ */
+- (NSString *) decomposedStringWithCanonicalMapping;
+
+/** Returns a copy of the receiver normalised using the KC form.
+ */
+- (NSString *) precomposedStringWithCompatibilityMapping;
+
+/** Returns a copy of the receiver normalised using the C form.
+ */
+- (NSString *) precomposedStringWithCanonicalMapping;
+#endif
+
+// Converting String Contents into a Property List
+- (id) propertyList;
+- (NSDictionary*) propertyListFromStringsFileFormat;
+
+// Identifying and Comparing Strings
+- (NSComparisonResult) compare: (NSString*)aString;
+- (NSComparisonResult) compare: (NSString*)aString
+ options: (NSUInteger)mask;
+- (NSComparisonResult) compare: (NSString*)aString
+ options: (NSUInteger)mask
+ range: (NSRange)aRange;
+- (BOOL) hasPrefix: (NSString*)aString;
+- (BOOL) hasSuffix: (NSString*)aString;
+- (BOOL) isEqual: (id)anObject;
+- (BOOL) isEqualToString: (NSString*)aString;
+- (NSUInteger) hash;
+
+// Getting a Shared Prefix
+- (NSString*) commonPrefixWithString: (NSString*)aString
+ options: (NSUInteger)mask;
+
+// Changing Case
+- (NSString*) capitalizedString;
+- (NSString*) lowercaseString;
+- (NSString*) uppercaseString;
+
+// Getting C Strings
+- (const char*) cString;
+#if OS_API_VERSION(GS_API_MACOSX, GS_API_LATEST)
+
+#if OS_API_VERSION(MAC_OS_X_VERSION_10_4,GS_API_LATEST) && GS_API_VERSION( 10200,GS_API_LATEST)
+- (const char*) cStringUsingEncoding: (NSStringEncoding)encoding;
+- (BOOL) getCString: (char*)buffer
+ maxLength: (NSUInteger)maxLength
+ encoding: (NSStringEncoding)encoding;
+- (id) initWithCString: (const char*)byteString
+ encoding: (NSStringEncoding)encoding;
+- (NSUInteger) lengthOfBytesUsingEncoding: (NSStringEncoding)encoding;
+- (NSUInteger) maximumLengthOfBytesUsingEncoding: (NSStringEncoding)encoding;
+#endif
+
+#endif
+- (NSUInteger) cStringLength;
+- (void) getCString: (char*)buffer;
+- (void) getCString: (char*)buffer
+ maxLength: (NSUInteger)maxLength;
+- (void) getCString: (char*)buffer
+ maxLength: (NSUInteger)maxLength
+ range: (NSRange)aRange
+ remainingRange: (NSRange*)leftoverRange;
+
+// Getting Numeric Values
+- (float) floatValue;
+- (int) intValue;
+
+// Working With Encodings
+- (BOOL) canBeConvertedToEncoding: (NSStringEncoding)encoding;
+- (NSData*) dataUsingEncoding: (NSStringEncoding)encoding;
+- (NSData*) dataUsingEncoding: (NSStringEncoding)encoding
+ allowLossyConversion: (BOOL)flag;
++ (NSStringEncoding) defaultCStringEncoding;
+- (NSString*) description;
+- (NSStringEncoding) fastestEncoding;
+- (NSStringEncoding) smallestEncoding;
+
+/**
+ * Attempts to complete this string as a path in the filesystem by finding
+ * a unique completion if one exists and returning it by reference in
+ * outputName (which must be a non-nil pointer), or if it finds a set of
+ * completions they are returned by reference in outputArray, if it is non-nil.
+ * filterTypes can be an array of strings specifying extensions to consider;
+ * files without these extensions will be ignored and will not constitute
+ * completions. Returns 0 if no match found, else a positive number that is
+ * only accurate if outputArray was non-nil.
+ */
+- (NSUInteger) completePathIntoString: (NSString**)outputName
+ caseSensitive: (BOOL)flag
+ matchesIntoArray: (NSArray**)outputArray
+ filterTypes: (NSArray*)filterTypes;
+
+/**
+ * Converts the receiver to a C string path expressed in the character
+ * encoding appropriate for the local host file system. This string will be
+ * automatically freed soon after it is returned, so copy it if you need it
+ * for long.<br />
+ * NB. On mingw32 systems the filesystem representation of a path is a 16-bit
+ * unicode character string, so you should only pass the value returned by
+ * this method to functions expecting wide characters.<br />
+ * This method uses [NSFileManager-fileSystemRepresentationWithPath:] to
+ * perform the conversion.
+ */
+- (const GSNativeChar*) fileSystemRepresentation;
+
+/**
+ * Converts the receiver to a C string path using the character encoding
+ * appropriate to the local file system. This string will be stored
+ * into buffer if it is shorter (number of characters) than size,
+ * otherwise NO is returned.<br />
+ * NB. On mingw32 systems the filesystem representation of a path is a 16-bit
+ * unicode character string, so the buffer you pass to this method must be
+ * twice as many bytes as the size (number of characters) you expect to
+ * receive.<br />
+ * This method uses [NSFileManager-fileSystemRepresentationWithPath:] to
+ * perform the conversion.
+ */
+- (BOOL) getFileSystemRepresentation: (GSNativeChar*)buffer
+ maxLength: (NSUInteger)size;
+
+/**
+ * Returns a string containing the last path component of the receiver.<br />
+ * The path component is the last non-empty substring delimited by the ends
+ * of the string, or by path separator characters.<br />
+ * If the receiver only contains a root part, this method returns it.<br />
+ * If there are no non-empty substrings, this returns an empty string.<br />
+ * NB. In a windows UNC path, the host and share specification is treated as
+ * a single path component, even though it contains separators.
+ * So a string of the form '//host/share' may be returned.<br />
+ * Other special cases are apply when the string is the root.
+ * <example>
+ * @"foo/bar" produces @"bar"
+ * @"foo/bar/" produces @"bar"
+ * @"/foo/bar" produces @"bar"
+ * @"/foo" produces @"foo"
+ * @"/" produces @"/" (root is a special case)
+ * @"" produces @""
+ * @"C:/" produces @"C:/" (root is a special case)
+ * @"C:" produces @"C:"
+ * @"//host/share/" produces @"//host/share/" (root is a special case)
+ * @"//host/share" produces @"//host/share"
+ * </example>
+ */
+- (NSString*) lastPathComponent;
+
+/**
+ * Returns a new string containing the path extension of the receiver.<br />
+ * The path extension is a suffix on the last path component which starts
+ * with the extension separator (a '.') (for example .tiff is the
+ * pathExtension for /foo/bar.tiff).<br />
+ * Returns an empty string if no such extension exists.
+ * <example>
+ * @"a.b" produces @"b"
+ * @"a.b/" produces @"b"
+ * @"/path/a.ext" produces @"ext"
+ * @"/path/a." produces @""
+ * @"/path/.a" produces @"" (.a is not an extension to a file)
+ * @".a" produces @"" (.a is not an extension to a file)
+ * </example>
+ */
+- (NSString*) pathExtension;
+
+/**
+ * Returns a string where a prefix of the current user's home directory is
+ * abbreviated by '~', or returns the receiver (or an immutable copy) if
+ * it was not found to have the home directory as a prefix.
+ */
+- (NSString*) stringByAbbreviatingWithTildeInPath;
+
+/**
+ * Returns a new string with the path component given in aString
+ * appended to the receiver.<br />
+ * This removes trailing path separators from the receiver and the root
+ * part from aString and replaces them with a single slash as a path
+ * separator.<br />
+ * Also condenses any multiple separator sequences in the result into
+ * single path separators.
+ * <example>
+ * @"" with @"file" produces @"file"
+ * @"path" with @"file" produces @"path/file"
+ * @"/" with @"file" produces @"/file"
+ * @"/" with @"file" produces @"/file"
+ * @"/" with @"/file" produces @"/file"
+ * @"path with @"C:/file" produces @"path/file"
+ * </example>
+ * NB. Do not use this method to modify strings other than filesystem
+ * paths as the behavior in such cases is undefined ... for instance
+ * the string may have repeated slashes or slash-dot-slash sequences
+ * removed.
+ */
+- (NSString*) stringByAppendingPathComponent: (NSString*)aString;
+
+/**
+ * Returns a new string with the path extension given in aString
+ * appended to the receiver after an extensionSeparator ('.').<br />
+ * If the receiver has trailing path separator characters, they are
+ * stripped before the extension separator is added.<br />
+ * If the receiver contains no components after the root, the extension
+ * cannot be appended (an extension can only be appended to a file name),
+ * so a copy of the unmodified receiver is returned.<br />
+ * An empty string may be used as an extension ... in which case the extension
+ * separator is appended.<br />
+ * This behavior mirrors that of the -stringByDeletingPathExtension method.
+ * <example>
+ * @"Mail" with @"app" produces @"Mail.app"
+ * @"Mail.app" with @"old" produces @"Mail.app.old"
+ * @"file" with @"" produces @"file."
+ * @"/" with @"app" produces @"/" (no file name to append to)
+ * @"" with @"app" produces @"" (no file name to append to)
+ * </example>
+ * NB. Do not use this method to modify strings other than filesystem
+ * paths as the behavior in such cases is undefined ... for instance
+ * the string may have repeated slashes or slash-dot-slash sequences
+ * removed.
+ */
+- (NSString*) stringByAppendingPathExtension: (NSString*)aString;
+
+/**
+ * Returns a new string with the last path component (including any final
+ * path separators) removed from the receiver.<br />
+ * A string without a path component other than the root is returned
+ * without alteration.<br />
+ * See -lastPathComponent for a definition of a path component.
+ * <example>
+ * @"hello/there" produces @"hello" (a relative path)
+ * @"hello" produces @"" (a relative path)
+ * @"/hello" produces @"/" (an absolute unix path)
+ * @"/" produces @"/" (an absolute unix path)
+ * @"C:file" produces @"C:" (a relative windows path)
+ * @"C:" produces @"C:" (a relative windows path)
+ * @"C:/file" produces @"C:/" (an absolute windows path)
+ * @"C:/" produces @"C:/" (an absolute windows path)
+ * @"//host/share/file" produces @"//host/share/" (a UNC path)
+ * @"//host/share/" produces @"//host/share/" (a UNC path)
+ * @"//path/file" produces @"//path" (an absolute Unix path)
+ * </example>
+ * NB. Do not use this method to modify strings other than filesystem
+ * paths as the behavior in such cases is undefined ... for instance
+ * the string may have repeated slashes or slash-dot-slash sequences
+ * removed.
+ */
+- (NSString*) stringByDeletingLastPathComponent;
+
+/**
+ * Returns a new string with the path extension removed from the receiver.<br />
+ * Strips any trailing path separators before checking for the extension
+ * separator.<br />
+ * NB. This method does not consider a string which contains nothing
+ * between the root part and the extension separator ('.') to be a path
+ * extension. This mirrors the behavior of the -stringByAppendingPathExtension:
+ * method.
+ * <example>
+ * @"file.ext" produces @"file"
+ * @"/file.ext" produces @"/file"
+ * @"/file.ext/" produces @"/file" (trailing path separators are ignored)
+ * @"/file..ext" produces @"/file."
+ * @"/file." produces @"/file"
+ * @"/.ext" produces @"/.ext" (there is no file to strip from)
+ * @".ext" produces @".ext" (there is no file to strip from)
+ * </example>
+ * NB. Do not use this method to modify strings other than filesystem
+ * paths as the behavior in such cases is undefined ... for instance
+ * the string may have repeated slashes or slash-dot-slash sequences
+ * removed.
+ */
+- (NSString*) stringByDeletingPathExtension;
+
+/**
+ * Returns a string created by expanding the initial tilde ('~') and any
+ * following username to be the home directory of the current user or the
+ * named user.<br />
+ * Returns the receiver or an immutable copy if it was not possible to
+ * expand it.
+ */
+- (NSString*) stringByExpandingTildeInPath;
+
+/**
+ * First calls -stringByExpandingTildeInPath if necessary.<br />
+ * Replaces path string by one in which path components representing symbolic
+ * links have been replaced by their referents.<br />
+ * Removes a leading '/private' if the result is valid.<br />
+ * If links cannot be resolved, returns an unmodified copy of the receiver.
+ */
+- (NSString*) stringByResolvingSymlinksInPath;
+
+/**
+ * Returns a standardised form of the receiver, with unnecessary parts
+ * removed, tilde characters expanded, and symbolic links resolved
+ * where possible.<br />
+ * NB. Refers to the local filesystem to resolve symbolic links in
+ * absolute paths, and to expand tildes ... so this can't be used for
+ * general path manipulation.<br />
+ * If the string is an invalid path, the unmodified receiver is returned.<br />
+ * <p>
+ * Uses -stringByExpandingTildeInPath to expand tilde expressions.<br />
+ * Simplifies '//' and '/./' sequences and removes trailing '/' or '.'.<br />
+ * </p>
+ * <p>
+ * For absolute paths, uses -stringByResolvingSymlinksInPath to resolve
+ * any links, then gets rid of '/../' sequences and removes any '/private'
+ * prefix.
+ * </p>
+ */
+- (NSString*) stringByStandardizingPath;
+
+
+// for methods working with decomposed strings
+- (int) _baseLength;
+
+#if OS_API_VERSION(GS_API_MACOSX, GS_API_LATEST)
+/**
+ * Concatenates the path components in the array and returns the result.<br />
+ * This method does not remove empty path components, but does recognize an
+ * empty initial component as a special case meaning that the string
+ * returned will begin with a slash.
+ */
++ (NSString*) pathWithComponents: (NSArray*)components;
+
+/**
+ * Returns YES if the receiver represents an absolute path ...<br />
+ * Returns NO otherwise.<br />
+ * An absolute path in unix mode is one which begins
+ * with a slash or tilde.<br />
+ * In windows mode a drive specification (eg C:) followed by a slash or
+ * backslash, is an absolute path, as is any path beginning with a tilde.<br />
+ * In any mode a UNC path (//host/share...) is always absolute.<br />
+ * In the default gnustep path handling mode,
+ * the rules are the same as for windows,
+ * except that a path whose root is a slash denotes an absolute path
+ * when running on unix and a relative path when running under windows.
+ */
+- (BOOL) isAbsolutePath;
+
+/**
+ * Returns the path components of the receiver separated into an array.<br />
+ * If the receiver begins with a root sequence such as the path separator
+ * character (or a drive specification in windows) then that is used as the
+ * first element in the array.<br />
+ * Empty components are removed.<br />
+ * If a trailing path separator (which was not part of the root) was present,
+ * it is added as the last element in the array.
+ */
+- (NSArray*) pathComponents;
+
+/**
+ * Returns an array of strings made by appending the values in paths
+ * to the receiver.
+ */
+- (NSArray*) stringsByAppendingPaths: (NSArray*)paths;
+
++ (NSString*) localizedStringWithFormat: (NSString*)format, ...
+ NS_FORMAT_FUNCTION(1,2);
+
++ (id) stringWithString: (NSString*)aString;
++ (id) stringWithContentsOfURL: (NSURL*)url;
++ (id) stringWithUTF8String: (const char*)bytes;
+- (id) initWithFormat: (NSString*)format
+ locale: (NSDictionary*)locale, ... NS_FORMAT_FUNCTION(1,3);
+- (id) initWithFormat: (NSString*)format
+ locale: (NSDictionary*)locale
+ arguments: (va_list)argList NS_FORMAT_FUNCTION(1,0);
+- (id) initWithUTF8String: (const char *)bytes;
+- (id) initWithContentsOfURL: (NSURL*)url;
+- (NSString*) substringWithRange: (NSRange)aRange;
+- (NSComparisonResult) caseInsensitiveCompare: (NSString*)aString;
+- (NSComparisonResult) compare: (NSString*)string
+ options: (NSUInteger)mask
+ range: (NSRange)compareRange
+ locale: (id)locale;
+- (NSComparisonResult) localizedCompare: (NSString *)string;
+- (NSComparisonResult) localizedCaseInsensitiveCompare: (NSString *)string;
+- (BOOL) writeToFile: (NSString*)filename
+ atomically: (BOOL)useAuxiliaryFile;
+- (BOOL) writeToURL: (NSURL*)url atomically: (BOOL)atomically;
+- (double) doubleValue;
++ (NSStringEncoding*) availableStringEncodings;
++ (NSString*) localizedNameOfStringEncoding: (NSStringEncoding)encoding;
+- (void) getLineStart: (NSUInteger *)startIndex
+ end: (NSUInteger *)lineEndIndex
+ contentsEnd: (NSUInteger *)contentsEndIndex
+ forRange: (NSRange)aRange;
+- (NSRange) lineRangeForRange: (NSRange)aRange;
+- (const char*) lossyCString;
+- (NSString*) stringByAddingPercentEscapesUsingEncoding: (NSStringEncoding)e;
+- (NSString*) stringByPaddingToLength: (NSUInteger)newLength
+ withString: (NSString*)padString
+ startingAtIndex: (NSUInteger)padIndex;
+- (NSString*) stringByReplacingPercentEscapesUsingEncoding: (NSStringEncoding)e;
+- (NSString*) stringByTrimmingCharactersInSet: (NSCharacterSet*)aSet;
+- (const char *)UTF8String;
+#endif
+
+#if OS_API_VERSION(MAC_OS_X_VERSION_10_9,GS_API_LATEST)
+- (NSString *) stringByAddingPercentEncodingWithAllowedCharacters: (NSCharacterSet *)aSet;
+- (NSString *) stringByRemovingPercentEncoding;
+#endif
+
+#if OS_API_VERSION(MAC_OS_X_VERSION_10_3,GS_API_LATEST)
+/** Not implemented */
+- (void) getParagraphStart: (NSUInteger *)startIndex
+ end: (NSUInteger *)parEndIndex
+ contentsEnd: (NSUInteger *)contentsEndIndex
+ forRange: (NSRange)range;
+/** Not implemented */
+ - (NSRange) paragraphRangeForRange: (NSRange)range;
+#endif
+
+#if OS_API_VERSION(MAC_OS_X_VERSION_10_5,GS_API_LATEST)
+/**
+ * Returns YES when scanning the receiver's text from left to right
+ * finds an initial digit in the range 1-9 or a letter in the set
+ * ('Y', 'y', 'T', 't').<br />
+ * Any trailing characters are ignored.<br />
+ * Any leading whitespace or zeros or signs are also ignored.<br />
+ * Returns NO if the above conditions are not met.
+ */
+- (BOOL) boolValue;
+- (NSArray *) componentsSeparatedByCharactersInSet: (NSCharacterSet *)separator;
+- (NSInteger) integerValue;
+- (long long) longLongValue;
+/** Not implemented */
+- (NSRange) rangeOfComposedCharacterSequencesForRange: (NSRange)range;
+/** Not implemented */
+- (NSRange) rangeOfString: (NSString *)aString
+ options: (NSStringCompareOptions)mask
+ range: (NSRange)searchRange
+ locale: (NSLocale *)locale;
+
+#endif
+
+#if OS_API_VERSION(MAC_OS_X_VERSION_10_10,GS_API_LATEST)
+
+/**
+ * Returns YES if the receiver contains string, otherwise, NO.
+ */
+- (BOOL) containsString: (NSString *)string;
+
+#endif
+
+#if OS_API_VERSION(GS_API_NONE, GS_API_NONE)
++ (Class) constantStringClass;
+#endif /* GS_API_NONE */
+
+@end
+
+@interface NSMutableString : NSString
+
+// Creating Temporary Strings
++ (id) string;
++ (id) stringWithCharacters: (const unichar*)characters
+ length: (NSUInteger)length;
++ (id) stringWithCString: (const char*)byteString
+ length: (NSUInteger)length;
++ (id) stringWithCString: (const char*)byteString;
++ (id) stringWithFormat: (NSString*)format, ... NS_FORMAT_FUNCTION(1,2);
++ (id) stringWithContentsOfFile: (NSString*)path;
++ (NSMutableString*) stringWithCapacity: (NSUInteger)capacity;
+
+// Initializing Newly Allocated Strings
+- (id) initWithCapacity: (NSUInteger)capacity;
+
+// Modify A String
+- (void) appendFormat: (NSString*)format, ... NS_FORMAT_FUNCTION(1,2);
+- (void) appendString: (NSString*)aString;
+- (void) deleteCharactersInRange: (NSRange)range;
+- (void) insertString: (NSString*)aString atIndex: (NSUInteger)loc;
+- (void) replaceCharactersInRange: (NSRange)range
+ withString: (NSString*)aString;
+- (NSUInteger) replaceOccurrencesOfString: (NSString*)replace
+ withString: (NSString*)by
+ options: (NSUInteger)opts
+ range: (NSRange)searchRange;
+- (void) setString: (NSString*)aString;
+
+@end
+
+#ifdef __OBJC_GNUSTEP_RUNTIME_ABI__
+# if __OBJC_GNUSTEP_RUNTIME_ABI__ >= 20
+# define GNUSTEP_NEW_STRING_ABI
+# endif
+#endif
+
+/**
+ * <p>The NXConstantString class is used to hold constant 8-bit character
+ * string objects produced by the compiler where it sees @"..." in the
+ * source. The compiler generates the instances of this class - which
+ * has three instance variables -</p>
+ * <list>
+ * <item>a pointer to the class (this is the sole ivar of NSObject)</item>
+ * <item>a pointer to the 8-bit data</item>
+ * <item>the length of the string</item>
+ * </list>
+ * <p>In older versions of the compiler, the isa variable is always set to
+ * the NXConstantString class. In newer versions a compiler option was
+ * added for GNUstep, to permit the isa variable to be set to another
+ * class, and GNUstep uses this to avoid conflicts with the default
+ * implementation of NXConstantString in the ObjC runtime library (the
+ * preprocessor is used to change all occurrences of NXConstantString
+ * in the source code to NSConstantString).</p>
+ * <p>Since GNUstep will generally use the GNUstep extension to the
+ * compiler, you should never refer to the constant string class by
+ * name, but should use the [NSString+constantStringClass] method to
+ * get the actual class being used for constant strings.</p>
+ * What follows is a dummy declaration of the class to keep the compiler
+ * happy.
+ */
+@interface NXConstantString : NSString
+{
+@public
+#ifdef GNUSTEP_NEW_STRING_ABI
+ /**
+ * Flags. The low 16 bits are reserved for the compiler, the top 16 for use
+ * by the Foundation Framework. Currently only the low 2 bits are used, to
+ * indicate the encoding of the string, with the following values:
+ *
+ * 0. ASCII (UTF-8 using only 7-bit characters)
+ * 1. UTF-8
+ * 2. UTF-16
+ * 3. UTF-32
+ *
+ */
+ uint32_t flags;
+ /**
+ * The number of characters (UTF-16 code units) in the string.
+ */
+ uint32_t nxcslen;
+ /**
+ * The number of bytes in the string. For fixed-length encodings, this is a
+ * fixed multiple of nxcslen, but for UTF-8 it can be different.
+ */
+ uint32_t size;
+ /**
+ * Hash value.
+ */
+ uint32_t hash;
+ /**
+ * Pointer to the byte data of the string. Note that `char*` is the correct
+ * type only if the low two bits of the flags indicate that this is an ASCII
+ * or UTF-8 string, otherwise it is a pointer to 16- or 32-bit characters in
+ * native byte order.
+ */
+ const char * const nxcsptr;
+#else
+ const char * const nxcsptr;
+ const unsigned int nxcslen;
+#endif
+}
+@end
+
+#ifdef NeXT_RUNTIME
+/** For internal use with NeXT runtime;
+ needed, until Apple Radar 2870817 is fixed. */
+extern struct objc_class _NSConstantStringClassReference;
+#endif
+
+#if defined(__cplusplus)
+}
+#endif
+
+#if !NO_GNUSTEP && !defined(GNUSTEP_BASE_INTERNAL)
+#import "../GNUstepBase/NSString+GNUstepBase.h"
+#import "../GNUstepBase/NSMutableString+GNUstepBase.h"
+#endif
+
+#endif /* __NSString_h_GNUSTEP_BASE_INCLUDE */
diff --git a/gcc/testsuite/objc-obj-c++-shared/GNUStep/Foundation/NSValue.h b/gcc/testsuite/objc-obj-c++-shared/GNUStep/Foundation/NSValue.h
new file mode 100644
index 0000000..f194f01
--- /dev/null
+++ b/gcc/testsuite/objc-obj-c++-shared/GNUStep/Foundation/NSValue.h
@@ -0,0 +1,370 @@
+/* Interface for NSValue for GNUStep
+ Copyright (C) 1995, 1996 Free Software Foundation, Inc.
+
+ Written by: Adam Fedor <fedor@boulder.colorado.edu>
+ Created: 1995
+
+ This file is part of the GNUstep Base Library.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free
+ Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02111 USA.
+ */
+
+#ifndef __NSValue_h_GNUSTEP_BASE_INCLUDE
+#define __NSValue_h_GNUSTEP_BASE_INCLUDE
+#import "../GNUstepBase/GSVersionMacros.h"
+
+#import "NSObject.h"
+#import "NSGeometry.h"
+#import "NSRange.h"
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+@class NSString;
+
+/**
+ * The <code>NSValue</code> class can wrap a single primitive value as an
+ * object so it can be used in the containers and other places where an object
+ * reference is needed. Once initialized, an <code>NSValue</code> is
+ * immutable, and there is no <code>NSMutableValue</code> class. You
+ * initialize it by giving it a pointer to the primitive value, and you should
+ * be careful this does not get freed until after the <code>NSValue</code> is
+ * no longer used.
+ */
+@interface NSValue : NSObject <NSCopying, NSCoding>
+
+// Allocating and Initializing
+
+/**
+ * Create new instance with specified value (a pointer) of given type, which
+ * is a string code obtainable through the compile-time operator
+ * <code>@encode(...)</code>. For example:
+<example>
+ NSValue *theValue = [NSValue value: &amp;n withObjCType: @encode(int)];
+</example>
+ */
++ (NSValue*) value: (const void*)value withObjCType: (const char*)type;
+
+/**
+ * Create new instance holding anObject. This is useful if you want to add
+ * anObject to a collection such as [NSArray] but don't want it to be retained
+ * (a weak reference).
+ */
++ (NSValue*) valueWithNonretainedObject: (id)anObject;
+
+/**
+ * Convenience method to create instance holding an <code>NSPoint</code>
+ * structure.
+ */
++ (NSValue*) valueWithPoint: (NSPoint)point;
+
+/**
+ * Convenience method to create instance holding a pointer. Same as
+ * using <code>@encode(void *)</code> in +value:withObjCType: .
+ */
++ (NSValue*) valueWithPointer: (const void*)pointer;
+
+/**
+ * Convenience method to create instance holding an <code>NSRange</code>
+ * structure.
+ */
++ (NSValue*) valueWithRange: (NSRange)range;
+
+/**
+ * Convenience method to create instance holding an <code>NSRect</code>
+ * structure.
+ */
++ (NSValue*) valueWithRect: (NSRect)rect;
+
+/**
+ * Convenience method to create instance holding an <code>NSSize</code>
+ * structure.
+ */
++ (NSValue*) valueWithSize: (NSSize)size;
+
+#if OS_API_VERSION(GS_API_MACOSX, GS_API_LATEST)
+/**
+ * Synonym for value:withObjCType: .
+ */
++ (NSValue*) valueWithBytes: (const void*)value objCType: (const char*)type;
+
+/** <init/>
+ * Initialize with value of type, parallel to value:withObjCType: .
+ */
+- (id) initWithBytes: (const void*)data objCType: (const char*)type;
+
+/**
+ * Compares this instance to another <code>NSValue</code>. For equality,
+ * both contents and declared type of the two values must match.
+ */
+- (BOOL) isEqualToValue: (NSValue*)other;
+#endif /* GS_API_MACOSX */
+
+// Accessing Data
+
+/**
+ * Copies bytes from the pointer receiver was initialized with into buffer
+ * pointed to by value. Number of bytes copied is determined by the type. If
+ * type was a void * pointer or object id, the memory address itself is
+ * copied.
+ */
+- (void) getValue: (void*)value;
+
+/**
+ * Returns the string <code>@encode(...)</code> compatible type the receiver
+ * was initialized with.
+ */
+- (const char*) objCType;
+
+/**
+ * If receiver was initialized with an object ID, return it, else raises
+ * <code>NSInternalInconsistencyException</code>.
+ */
+- (id) nonretainedObjectValue;
+
+/**
+ * If receiver was initialized with a void * pointer, return it, else raises
+ * <code>NSInternalInconsistencyException</code>.
+ */
+- (void*) pointerValue;
+
+/**
+ * If receiver was initialized with an <code>NSRange</code> value, return it,
+ * else raises <code>NSInternalInconsistencyException</code>.
+ */
+- (NSRange) rangeValue;
+
+/**
+ * If receiver was initialized with an <code>NSRect</code> value, return it,
+ * else raises <code>NSInternalInconsistencyException</code>.
+ */
+- (NSRect) rectValue;
+
+/**
+ * If receiver was initialized with an <code>NSSize</code> value, return it,
+ * else raises <code>NSInternalInconsistencyException</code>.
+ */
+- (NSSize) sizeValue;
+
+/**
+ * If receiver was initialized with an <code>NSPoint</code> value, return it,
+ * else raises <code>NSInternalInconsistencyException</code>.
+ */
+- (NSPoint) pointValue;
+
+@end
+
+/**
+ * Subclass of [NSValue] offering convenience methods for initializing from
+ * and accessing as any C primitive numeric type. On access, the value will
+ * be type-converted if necessary, using standard C conversion rules.
+ */
+@interface NSNumber : NSValue <NSCopying,NSCoding>
+
+// Allocating and Initializing
+
+/** New instance from boolean value. */
++ (NSNumber*) numberWithBool: (BOOL)value;
+/** New instance from signed char value. */
++ (NSNumber*) numberWithChar: (signed char)value;
+/** New instance from double value. */
++ (NSNumber*) numberWithDouble: (double)value;
+/** New instance from float value. */
++ (NSNumber*) numberWithFloat: (float)value;
+/** New instance from (signed) int value. */
++ (NSNumber*) numberWithInt: (signed int)value;
+/** New instance from (signed) long value. */
++ (NSNumber*) numberWithLong: (signed long)value;
+/** New instance from (signed) long long value. */
++ (NSNumber*) numberWithLongLong: (signed long long)value;
+/** New instance from (signed) short value. */
++ (NSNumber*) numberWithShort: (signed short)value;
+/** New instance from unsigned char value. */
++ (NSNumber*) numberWithUnsignedChar: (unsigned char)value;
+/** New instance from unsigned int value. */
++ (NSNumber*) numberWithUnsignedInt: (unsigned int)value;
+/** New instance from unsigned long value. */
++ (NSNumber*) numberWithUnsignedLong: (unsigned long)value;
+/** New instance from unsigned long long value. */
++ (NSNumber*) numberWithUnsignedLongLong: (unsigned long long)value;
+/** New instance from unsigned short value. */
++ (NSNumber*) numberWithUnsignedShort: (unsigned short)value;
+
+/** Initialize from boolean value. */
+- (id) initWithBool: (BOOL)value;
+/** Initialize from signed char value. */
+- (id) initWithChar: (signed char)value;
+/** Initialize from double value. */
+- (id) initWithDouble: (double)value;
+/** Initialize from float value. */
+- (id) initWithFloat: (float)value;
+/** Initialize from (signed) int value. */
+- (id) initWithInt: (signed int)value;
+/** Initialize from (signed) long value. */
+- (id) initWithLong: (signed long)value;
+/** Initialize from (signed) long long value. */
+- (id) initWithLongLong: (signed long long)value;
+/** Initialize from (signed) short value. */
+- (id) initWithShort: (signed short)value;
+/** Initialize from unsigned char value. */
+- (id) initWithUnsignedChar: (unsigned char)value;
+/** Initialize from unsigned int value. */
+- (id) initWithUnsignedInt: (unsigned int)value;
+/** Initialize from unsigned long value. */
+- (id) initWithUnsignedLong: (unsigned long)value;
+/** Initialize from unsigned long long value. */
+- (id) initWithUnsignedLongLong: (unsigned long long)value;
+/** Initialize from unsigned short value. */
+- (id) initWithUnsignedShort: (unsigned short)value;
+
+// Accessing Data
+
+/**
+ * Return value as a BOOL; this will in fact be a char value converted
+ * if necessary from type initialized with; if you wish to consider anything
+ * nonzero TRUE do not compare directly to YES, but use <code>'!= NO'</code>.
+ */
+- (BOOL) boolValue;
+/** Returns value as a signed char, converting if necessary. */
+- (signed char) charValue;
+/** Returns value as a double, converting if necessary. */
+- (double) doubleValue;
+/** Returns value as a float, converting if necessary. */
+- (float) floatValue;
+/** Returns value as a (signed) int, converting if necessary. */
+- (signed int) intValue;
+/** Returns value as a (signed) long, converting if necessary. */
+- (signed long) longValue;
+/** Returns value as a (signed) long long, converting if necessary. */
+- (signed long long) longLongValue;
+/** Returns value as a (signed) short, converting if necessary. */
+- (signed short) shortValue;
+/** Returns value as an unsigned char, converting if necessary. */
+- (unsigned char) unsignedCharValue;
+/** Returns value as an unsigned int, converting if necessary. */
+- (unsigned int) unsignedIntValue;
+/** Returns value as an unsigned long, converting if necessary. */
+- (unsigned long) unsignedLongValue;
+/** Returns value as an unsigned long long, converting if necessary. */
+- (unsigned long long) unsignedLongLongValue;
+/** Returns value as an unsigned short, converting if necessary. */
+- (unsigned short) unsignedShortValue;
+
+/** Returns -description . */
+- (NSString*) stringValue;
+
+/**
+ * Returns the string representation of this number using a non-localised
+ * conversion (decimal point is '.' irrespective of the locale).
+ */
+- (NSString*) description;
+
+/**
+ * <p>
+ * Produces a string representation of the number. For a boolean
+ * this will be either 'true' or 'false'. For other numbers the
+ * format is produced using the initWithFormat:locale:... method
+ * of NSString, and the format depends on the type of number as
+ * follows -
+ * </p>
+ * <deflist>
+ * <term>char</term>
+ * <desc>%i</desc>
+ * <term> short</term>
+ * <desc>%hi</desc>
+ * <term> int</term>
+ * <desc>%i</desc>
+ * <term> long</term>
+ * <desc>%li</desc>
+ * <term> long long</term>
+ * <desc>%lli</desc>
+ * <term> unsigned char</term>
+ * <desc>%u</desc>
+ * <term> unsigned short</term>
+ * <desc>%hu</desc>
+ * <term> unsigned int</term>
+ * <desc>%u</desc>
+ * <term> unsigned long</term>
+ * <desc>%lu</desc>
+ * <term> unsigned long long</term>
+ * <desc>%llu</desc>
+ * <term> float</term>
+ * <desc>%0.7g</desc>
+ * <term> double</term>
+ * <desc>%0.16g</desc>
+ * </deflist>
+ */
+- (NSString*) descriptionWithLocale: (id)locale;
+
+/**
+ * Compares receiver with otherNumber, using C type conversion if necessary,
+ * and returns <code>NSOrderedAscending</code>,
+ * <code>NSOrderedDescending</code>, or <code>NSOrderedSame</code> depending
+ * on whether it is less than, greater than, or equal to otherNumber.
+ */
+- (NSComparisonResult) compare: (NSNumber*)otherNumber;
+
+/**
+ * Returns whether receiver and otherNumber represent the same numerical value.
+ */
+- (BOOL) isEqualToNumber: (NSNumber*)otherNumber;
+
+
+#if OS_API_VERSION(MAC_OS_X_VERSION_10_5, GS_API_LATEST)
+/** Return a number intialised with NSInteger.
+ */
++ (NSNumber*) numberWithInteger: (NSInteger)value;
+/** Return a number intialised with NSUInteger.
+ */
++ (NSNumber*) numberWithUnsignedInteger: (NSUInteger)value;
+/** Initialise the receiver with NSInteger content.
+ */
+- (id) initWithInteger: (NSInteger)value;
+/** Initialise the receiver with NSUInteger content.
+ */
+- (id) initWithUnsignedInteger: (NSUInteger)value;
+/** Return the contents of the receiver as NSInteger.
+ */
+- (NSInteger) integerValue;
+/** Return the contents of the receiver as NSUInteger.
+ */
+- (NSUInteger) unsignedIntegerValue;
+#endif
+
+@end
+
+#if OS_API_VERSION(GS_API_NONE, GS_API_NONE)
+
+/** Note: Defines a method that is not in the OpenStep spec, but makes
+ subclassing easier. */
+@interface NSValue (Subclassing)
+
+/** Used by value: withObjCType: to determine the concrete subclass to alloc. */
++ (Class) valueClassWithObjCType: (const char*)type;
+
+@end
+#endif
+
+#if defined(__cplusplus)
+}
+#endif
+
+#if !NO_GNUSTEP && !defined(GNUSTEP_BASE_INTERNAL)
+#import "../GNUstepBase/NSNumber+GNUstepBase.h"
+#endif
+
+#endif /* __NSValue_h_GNUSTEP_BASE_INCLUDE */
diff --git a/gcc/testsuite/objc-obj-c++-shared/GNUStep/Foundation/NSZone.h b/gcc/testsuite/objc-obj-c++-shared/GNUStep/Foundation/NSZone.h
new file mode 100644
index 0000000..21776f6
--- /dev/null
+++ b/gcc/testsuite/objc-obj-c++-shared/GNUStep/Foundation/NSZone.h
@@ -0,0 +1,335 @@
+/** Zone memory management. -*- Mode: ObjC -*-
+ Copyright (C) 1997,1998,1999 Free Software Foundation, Inc.
+
+ Written by: Yoo C. Chung <wacko@laplace.snu.ac.kr>
+ Date: January 1997
+
+ This file is part of the GNUstep Base Library.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free
+ Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02111 USA.
+
+ AutogsdocSource: NSZone.m
+ AutogsdocSource: NSPage.m
+
+ */
+
+#ifndef __NSZone_h_GNUSTEP_BASE_INCLUDE
+#define __NSZone_h_GNUSTEP_BASE_INCLUDE
+#import "../GNUstepBase/GSVersionMacros.h"
+
+/**
+ * Primary structure representing an <code>NSZone</code>. Technically it
+ * consists of a set of function pointers for zone upkeep functions plus some
+ * other things-
+<example>
+{
+ // Functions for zone.
+ void *(*malloc)(struct _NSZone *zone, size_t size);
+ void *(*realloc)(struct _NSZone *zone, void *ptr, size_t size);
+ void (*free)(struct _NSZone *zone, void *ptr);
+ void (*recycle)(struct _NSZone *zone);
+ BOOL (*check)(struct _NSZone *zone);
+ BOOL (*lookup)(struct _NSZone *zone, void *ptr);
+
+ // Zone statistics (not always maintained).
+ struct NSZoneStats (*stats)(struct _NSZone *zone);
+
+ size_t gran; // Zone granularity (passed in on initialization)
+ NSString *name; // Name of zone (default is 'nil')
+ NSZone *next; // Pointer used for internal management of multiple zones.
+}</example>
+ */
+typedef struct _NSZone NSZone;
+
+#import "NSObjCRuntime.h"
+
+@class NSString;
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+struct _NSZone
+{
+ /* Functions for zone. */
+ void *(*malloc)(struct _NSZone *zone, size_t size);
+ void *(*realloc)(struct _NSZone *zone, void *ptr, size_t size);
+ void (*free)(struct _NSZone *zone, void *ptr);
+ void (*recycle)(struct _NSZone *zone);
+ BOOL (*check)(struct _NSZone *zone);
+ BOOL (*lookup)(struct _NSZone *zone, void *ptr);
+ struct NSZoneStats (*stats)(struct _NSZone *zone);
+
+ size_t gran; // Zone granularity
+ __unsafe_unretained NSString *name; // Name of zone (default is 'nil')
+ NSZone *next;
+};
+
+/**
+ * Creates a new zone of start bytes, which will grow and shrink by
+ * granularity bytes. If canFree is 0, memory in zone is allocated but
+ * never freed, meaning allocation will be very fast. The whole zone can
+ * still be freed with NSRecycleZone(), and you should still call NSZoneFree
+ * on memory in the zone that is no longer needed, since a count of allocated
+ * pointers is kept and must reach zero before freeing the zone.<br />
+ * If Garbage Collection is enabled, this function does nothing other than
+ * log a warning and return the same value as the NSDefaultMallocZone()
+ * function.
+ */
+GS_EXPORT NSZone*
+NSCreateZone (NSUInteger start, NSUInteger gran, BOOL canFree);
+
+/** Returns the default zone for memory allocation. Memory created in this
+ * zone is the same as memory allocates using the system malloc() function.
+ */
+GS_EXPORT NSZone*
+NSDefaultMallocZone (void);
+
+/**
+ * Searches and finds the zone ptr was allocated from. The speed depends
+ * upon the number of zones and their size.<br />
+ * If Garbage Collection is enabled, this function always returns the
+ * same as the NSDefaultMallocZone() function.
+ */
+GS_EXPORT NSZone*
+NSZoneFromPointer (void *ptr);
+
+/**
+ * Allocates and returns memory for elems items of size bytes, in the
+ * given zone. Returns NULL if allocation of size 0 requested. Raises
+ * <code>NSMallocException</code> if not enough free memory in zone to
+ * allocate and no more can be obtained from system, unless using the
+ * default zone, in which case NULL is returned.<br />
+ * If Garbage Collection is enabled, this function always allocates
+ * non-scanned, non-collectable memory in the NSDefaultMallocZone() and
+ * the zone argument is ignored.
+ */
+GS_EXPORT void*
+NSZoneMalloc (NSZone *zone, NSUInteger size);
+
+/**
+ * Allocates and returns cleared memory for elems items of size bytes, in the
+ * given zone. Returns NULL if allocation of size 0 requested. Raises
+ * <code>NSMallocException</code> if not enough free memory in zone to
+ * allocate and no more can be obtained from system, unless using the
+ * default zone, in which case NULL is returned.<br />
+ * If Garbage Collection is enabled, this function always allocates
+ * non-scanned, non-collectable memory in the NSDefaultMallocZone() and
+ * the zone argument is ignored.
+ */
+GS_EXPORT void*
+NSZoneCalloc (NSZone *zone, NSUInteger elems, NSUInteger bytes);
+
+/**
+ * Reallocates the chunk of memory in zone pointed to by ptr to a new one of
+ * size bytes. Existing contents in ptr are copied over. Raises an
+ * <code>NSMallocException</code> if insufficient memory is available in the
+ * zone and no more memory can be obtained from the system, unless using the
+ * default zone, in which case NULL is returned.<br />
+ * If Garbage Collection is enabled, the zone argument is ignored.
+ */
+GS_EXPORT void*
+NSZoneRealloc (NSZone *zone, void *ptr, NSUInteger size);
+
+/**
+ * Return memory for an entire zone to system. In fact, this will not be done
+ * unless all memory in the zone has been explicitly freed (by calls to
+ * NSZoneFree()). For "non-freeable" zones, the number of NSZoneFree() calls
+ * must simply equal the number of allocation calls. The default zone, on the
+ * other hand, cannot be recycled.<br />
+ * If Garbage Collection is enabled, this function has not effect.
+ */
+GS_EXPORT void
+NSRecycleZone (NSZone *zone);
+
+/**
+ * Frees memory pointed to by ptr (which should have been allocated by a
+ * previous call to NSZoneMalloc(), NSZoneCalloc(), or NSZoneRealloc()) and
+ * returns it to zone. Note, if this is a nonfreeable zone, the memory is
+ * not actually freed, but the count of number of free()s is updated.<br />
+ * If Garbage Collection is enabled, the zone argument is ignored and this
+ * function causes ptr to be deallocated immediately.
+ */
+GS_EXPORT void
+NSZoneFree (NSZone *zone, void *ptr);
+
+/**
+ * Sets name of the given zone (useful for debugging and logging).
+ */
+GS_EXPORT void
+NSSetZoneName (NSZone *zone, NSString *name);
+
+/**
+ * Returns the name of the given zone (useful for debugging and logging).
+ */
+GS_EXPORT NSString*
+NSZoneName (NSZone *zone);
+
+#if OS_API_VERSION(GS_API_NONE, GS_API_NONE)
+
+/** Deprecated ...<br />
+ * Checks integrity of a zone. Not defined by OpenStep or OS X.
+ */
+BOOL
+NSZoneCheck (NSZone *zone);
+
+/**
+ * <code>NSZoneStats</code> is the structure returned by the NSZoneStats()
+ * function that summarizes the current usage of a zone. It is similar to
+ * the structure <em>mstats</em> in the GNU C library. It has 5 fields of
+ * type <code>size_t</code>-
+ * <deflist>
+ * <term><code>bytes_total</code></term>
+ * <desc>
+ * This is the total size of memory managed by the zone, in bytes.</desc>
+ * <term><code>chunks_used</code></term>
+ * <desc>This is the number of memory chunks in use in the zone.</desc>
+ * <term><code>bytes_used</code></term>
+ * <desc>This is the number of bytes in use.</desc>
+ * <term><code>chunks_free</code></term>
+ * <desc>This is the number of memory chunks that are not in use.</desc>
+ * <term><code>bytes_free</code></term>
+ * <desc>
+ * This is the number of bytes managed by the zone that are not in use.
+ * </desc>
+ * </deflist>
+ */
+struct NSZoneStats
+{
+ size_t bytes_total;
+ size_t chunks_used;
+ size_t bytes_used;
+ size_t chunks_free;
+ size_t bytes_free;
+};
+
+/** Deprecated ...<br />
+ * Obtain statistics about the zone. Implementation emphasis is on
+ * correctness, not speed. Not defined by OpenStep or OS X.
+ */
+struct NSZoneStats
+NSZoneStats (NSZone *zone);
+
+/**
+ * Try to get more memory - the normal process has failed.
+ * If we can't do anything, just return a null pointer.
+ * Try to do some logging if possible.
+ */
+void*
+GSOutOfMemory(NSUInteger size, BOOL retry);
+
+/**
+ * Called during +initialize to tell the class that instances created
+ * in future should have the specified instance variable as a weak
+ * pointer for garbage collection.<br />
+ * NB. making a pointer weak does not mean that it is automatically
+ * zeroed when the object it points to is garbage collected. To get that
+ * behavior you must asign values to the pointer using the
+ * GSAssignZeroingWeakPointer() function.<br />
+ * This function has no effect if the system is
+ * not built for garbage collection.
+ */
+GS_EXPORT void
+GSMakeWeakPointer(Class theClass, const char *iVarName);
+
+/**
+ * This function must be used to assign a value to a zeroing weak pointer.<br />
+ * A zeroing weak pointer is one where, when the garbage collector collects
+ * the object pointed to, it also clears the weak pointer.<br />
+ * Assigning zero (nil) will always succeed and has the effect of telling the
+ * garbage collector that it no longer needs to track the previously assigned
+ * object. Apart from that case, a source needs to be garbage collectable for
+ * this function to work, and using a non-garbage collectable value will
+ * cause the function to return NO.<br />
+ * If the destination object (the weak pointer watching the source object)
+ * belongs to a chunk of memory which may be collected before the source
+ * object is collected, it is important that it is finalised and the
+ * finalisation code assigns zero to the pointer.<br />
+ * If garbage collection is not in use, this function performs a simple
+ * assignment returning YES, unless destination is null in which case it
+ * returns NO.
+ */
+GS_EXPORT BOOL
+GSAssignZeroingWeakPointer(void **destination, void *source);
+
+#endif
+
+GS_EXPORT NSUInteger
+NSPageSize (void) __attribute__ ((const));
+
+GS_EXPORT NSUInteger
+NSLogPageSize (void) __attribute__ ((const));
+
+GS_EXPORT NSUInteger
+NSRoundDownToMultipleOfPageSize (NSUInteger bytes) __attribute__ ((const));
+
+GS_EXPORT NSUInteger
+NSRoundUpToMultipleOfPageSize (NSUInteger bytes) __attribute__ ((const));
+
+GS_EXPORT NSUInteger
+NSRealMemoryAvailable (void);
+
+GS_EXPORT void*
+NSAllocateMemoryPages (NSUInteger bytes);
+
+GS_EXPORT void
+NSDeallocateMemoryPages (void *ptr, NSUInteger bytes);
+
+GS_EXPORT void
+NSCopyMemoryPages (const void *src, void *dest, NSUInteger bytes);
+
+#if OS_API_VERSION(MAC_OS_X_VERSION_10_4, OS_API_LATEST)
+
+enum {
+ NSScannedOption = (1<<0),
+ NSCollectorDisabledOption = (1<<1)
+};
+
+/** Allocate memory. If garbage collection is not enabled this uses the
+ * default malloc zone and the options are ignored.<br />
+ * If garbage collection is enabled, the allocate memory is normally not
+ * scanned for pointers but is itsself garbage collectable. The options
+ * argument is a bitmask in which NSScannedOption sets the memory to be
+ * scanned for pointers by the garbage collector, and
+ * NSCollectorDisabledOption causes the memory to be excempt from being
+ * garbage collected itsself.<br />
+ * In any case the memory returned is zero'ed.
+ */
+GS_EXPORT void *
+NSAllocateCollectable(NSUInteger size, NSUInteger options);
+
+/** Reallocate memory to be of a different size and/or to have different
+ * options settings. The behavior of options is as for
+ * the NSAllocateCollectable() function.
+ */
+GS_EXPORT void *
+NSReallocateCollectable(void *ptr, NSUInteger size, NSUInteger options);
+
+#endif
+
+static inline id NSMakeCollectable(const void *cf) {
+#if __has_feature(objc_arc)
+ return nil;
+#else
+ return (id)cf; // Unimplemented; garbage collection is deprecated.
+#endif
+}
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif /* not __NSZone_h_GNUSTEP_BASE_INCLUDE */
diff --git a/gcc/testsuite/objc-obj-c++-shared/GNUStep/GNUstepBase/GNUstep.h b/gcc/testsuite/objc-obj-c++-shared/GNUStep/GNUstepBase/GNUstep.h
new file mode 100644
index 0000000..c3b7f2b
--- /dev/null
+++ b/gcc/testsuite/objc-obj-c++-shared/GNUStep/GNUstepBase/GNUstep.h
@@ -0,0 +1,418 @@
+/* GNUstep.h - macros to make easier to port gnustep apps to macos-x
+ Copyright (C) 2001 Free Software Foundation, Inc.
+
+ Written by: Nicola Pero <n.pero@mi.flashnet.it>
+ Date: March, October 2001
+
+ This file is part of GNUstep.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free
+ Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef __GNUSTEP_GNUSTEP_H_INCLUDED_
+#define __GNUSTEP_GNUSTEP_H_INCLUDED_
+
+/* The contents of this file are designed to be usable with either
+ * GNUstep-base or MacOS-X Foundation.
+ */
+
+#ifndef __has_feature
+# define __has_feature(x) 0
+#endif
+
+/*
+ * __has_extension has slightly different semantics from __has_feature.
+ * It evaluates to true if the feature is supported by by clang for the
+ * current compilation unit (language and -f switches), regardless of
+ * whether it is part of the language standard or just a (non-standard)
+ * extension.
+ */
+#ifndef __has_extension
+# define __has_extension(x) __has_feature(x)
+#endif
+
+/*
+ * __has_attribute is the equivalent to __has_feature and __has_extension
+ * for GNU-style attributes.
+ */
+#ifndef __has_attribute
+# define __has_attribute(x) 0
+#endif
+
+#if __has_feature(objc_arc)
+
+#ifndef RETAIN
+#define RETAIN(object) (object)
+#endif
+#ifndef RELEASE
+#define RELEASE(object)
+#endif
+#ifndef AUTORELEASE
+#define AUTORELEASE(object) (object)
+#endif
+
+#ifndef TEST_RETAIN
+#define TEST_RETAIN(object) (object)
+#endif
+#ifndef TEST_RELEASE
+#define TEST_RELEASE(object)
+#endif
+#ifndef TEST_AUTORELEASE
+#define TEST_AUTORELEASE(object) (object)
+#endif
+
+#ifndef ASSIGN
+#define ASSIGN(object,value) object = (value)
+#endif
+#ifndef ASSIGNCOPY
+#define ASSIGNCOPY(object,value) object = [(value) copy]
+#endif
+#ifndef DESTROY
+#define DESTROY(object) object = nil
+#endif
+
+#define IF_NO_GC(X)
+
+#ifndef ENTER_POOL
+#define ENTER_POOL @autoreleasepool{do{
+#endif
+
+#ifndef LEAVE_POOL
+#define LEAVE_POOL }while(0);}
+#endif
+
+#ifndef DEALLOC
+#define DEALLOC
+#endif
+
+#else
+
+#ifndef RETAIN
+/**
+ * Basic retain operation ... calls [NSObject-retain]<br />
+ * Deprecated ... pointless on modern processors.
+ * Simply call the -retain method.
+ */
+#define RETAIN(object) [(object) retain]
+#endif
+
+#ifndef RELEASE
+/**
+ * Basic release operation ... calls [NSObject-release]<br />
+ * Deprecated ... pointless on modern processors.
+ * Simply call the -release method.
+ */
+#define RELEASE(object) [(object) release]
+#endif
+
+#ifndef AUTORELEASE
+/**
+ * Basic autorelease operation ... calls [NSObject-autorelease]<br />
+ * Deprecated ... pointless on modern processors.
+ * Simply call the -autorelease method.
+ */
+#define AUTORELEASE(object) [(object) autorelease]
+#endif
+
+#ifndef TEST_RETAIN
+/**
+ * Tested retain - only invoke the
+ * objective-c method if the receiver is not nil.<br />
+ * Deprecated ... pointless on modern processors.
+ * Simply call the -retain method.
+ */
+#define TEST_RETAIN(object) ({\
+id __object = (object); (__object != nil) ? [__object retain] : nil; })
+#endif
+
+#ifndef TEST_RELEASE
+/**
+ * Tested release - only invoke the
+ * objective-c method if the receiver is not nil.<br />
+ * Deprecated ... pointless on modern processors.
+ * Simply call the -release method.
+ */
+#define TEST_RELEASE(object) ({\
+id __object = (object); if (__object != nil) [__object release]; })
+#endif
+
+#ifndef TEST_AUTORELEASE
+/**
+ * Tested autorelease - only invoke the
+ * objective-c method if the receiver is not nil.<br />
+ * Deprecated ... pointless on modern processors.
+ * Simply call the -autorelease method.
+ */
+#define TEST_AUTORELEASE(object) ({\
+id __object = (object); (__object != nil) ? [__object autorelease] : nil; })
+#endif
+
+#ifndef ASSIGN
+/**
+ * ASSIGN(object,value) assigns the value to the object with
+ * appropriate retain and release operations.<br />
+ * Use this to avoid retain/release errors.
+ */
+#define ASSIGN(object,value) ({\
+ id __object = object; \
+ object = [(value) retain]; \
+ [__object release]; \
+})
+#endif
+
+#ifndef ASSIGNCOPY
+/**
+ * ASSIGNCOPY(object,value) assigns a copy of the value to the object
+ * with release of the original.<br />
+ * Use this to avoid retain/release errors.
+ */
+#define ASSIGNCOPY(object,value) ({\
+ id __object = object; \
+ object = [(value) copy];\
+ [__object release]; \
+})
+#endif
+
+#ifndef DESTROY
+/**
+ * DESTROY() is a release operation which also sets the variable to be
+ * a nil pointer for tidiness - we can't accidentally use a DESTROYED
+ * object later. It also makes sure to set the variable to nil before
+ * releasing the object - to avoid side-effects of the release trying
+ * to reference the object being released through the variable.
+ */
+#define DESTROY(object) ({ \
+ id __o = object; \
+ object = nil; \
+ [__o release]; \
+})
+#endif
+
+#define IF_NO_GC(X) X
+
+#ifndef ENTER_POOL
+/**
+ * ENTER_POOL creates an autorelease pool and places subsequent code
+ * in a do/while loop (executed only once) which can be broken out of
+ * to reach the point when the pool is drained.<br />
+ * The block must be terminated with a corresponding LEAVE_POOL.<br />
+ * You should not return from such a block of code (to do so could
+ * leak an autorelease pool and give objects a longer lifetime than
+ * they ought to have. If you wish to leave the block of code early,
+ * you may do so using a 'break' statement.
+ */
+#define ENTER_POOL {NSAutoreleasePool *_lARP=[NSAutoreleasePool new];do{
+#endif
+
+#ifndef LEAVE_POOL
+/**
+ * LEAVE_POOL terminates a block of code started with ENTER_POOL.
+ */
+#define LEAVE_POOL }while(0);[_lARP drain];}
+#endif
+
+#ifndef DEALLOC
+/**
+ * DEALLOC calls the superclass implementation of dealloc, unless
+ * ARC is in use (in which case it does nothing).
+ */
+#define DEALLOC [super dealloc];
+#endif
+#endif
+
+#ifndef CREATE_AUTORELEASE_POOL
+/** DEPRECATED ... use ENTER_POOL and LEAVE_POOL
+ */
+#define CREATE_AUTORELEASE_POOL(X) \
+ NSAutoreleasePool *X = [NSAutoreleasePool new]
+#endif
+
+#ifndef RECREATE_AUTORELEASE_POOL
+/** DEPRECATED ... use ENTER_POOL and LEAVE_POOL
+ */
+#define RECREATE_AUTORELEASE_POOL(X) \
+ DESTROY(X);\
+ X = [NSAutoreleasePool new]
+#endif
+
+
+/**
+ * <p>
+ * This function (macro) is a GNUstep extension.
+ * </p>
+ * <p>
+ * <code>_(@"My string to translate")</code>
+ * </p>
+ * <p>
+ * is basically equivalent to
+ * </p>
+ * <p>
+ * <code>NSLocalizedString(@"My string to translate", @"")</code>
+ * </p>
+ * <p>
+ * It is useful when you need to translate an application
+ * very quickly, as you just need to enclose all strings
+ * inside <code>_()</code>. But please note that when you
+ * use this macro, you are not taking advantage of comments
+ * for the translator, so consider using
+ * <code>NSLocalizedString</code> instead when you need a
+ * comment.
+ * </p>
+ * <p>You may define GS_LOCALISATION_BUNDLE_ID to the bundle identifier
+ * of the bundle which is to provide the localisation information.<br />
+ * This can be used when compiling a single file by specifying something like
+ * '-D GS_LOCALISATION_BUNDLE_ID=$(FRAMEWORK_NAME)' in your make file.<br />
+ * If this is not defined, the localisation is provided by your application's
+ * main bundle exactly like the NSLocalizedString function.
+ * </p>
+ * <p>Alternatively you may define GS_LOCALISATION_BUNDLE to be the bundle
+ * to be used to prvide the localisation information.
+ * </p>
+ */
+# define _(X) \
+ [GS_LOCALISATION_BUNDLE localizedStringForKey: (X) value: @"" table: nil]
+
+#if !defined(GS_LOCALISATION_BUNDLE)
+# if defined(GS_LOCALISATION_BUNDLE_ID)
+# define GS_LOCALISATION_BUNDLE [NSBundle bundleWithIdentifier: \
+ GS_LOCALISATION_BUNDLE_ID]
+# else
+# define GS_LOCALISATION_BUNDLE [NSBundle mainBundle]
+# endif
+#endif
+
+
+
+/**
+ * <p>
+ * This function (macro) is a GNUstep extension.
+ * </p>
+ * <p>
+ * <code>__(@"My string to translate")</code>
+ * </p>
+ * <p>
+ * is exactly the same as
+ * </p>
+ * <p>
+ * <code>GSLocalizedStaticString(@"My string to translate", @"")</code>
+ * </p>
+ * <p>
+ * It is useful when you need to translate an application very
+ * quickly. You would use it as follows for static strings:
+ * </p>
+ * <p>
+ * <code>
+ * NSString *message = __(@"Hello there");
+ * ... more code ...
+ * NSLog (_(messages));
+ * </code>
+ * </p>
+ * <p>
+ * But please note that when you use this macro, you are not
+ * taking advantage of comments for the translator, so
+ * consider using <code>GSLocalizedStaticString</code>
+ * instead when you need a comment.
+ * </p>
+ */
+#define __(X) X
+
+/* The better way for a static string, with a comment - use as follows -
+ *
+ * static NSString *string = GSLocalizedStaticString (@"New Game",
+ * @"Menu Option");
+ *
+ * NSLog (_(string));
+ *
+ * If you need anything more complicated than this, please initialize
+ * the static strings manually.
+ */
+
+/**
+ * <p>
+ * This function (macro) is a GNUstep extensions, and it is used
+ * to localize static strings. Here is an example of a static
+ * string:
+ * </p>
+ * <p>
+ * <code>
+ * NSString *message = @"Hi there";
+ * ... some code ...
+ * NSLog (message);
+ * </code>
+ * </p>
+ * <p>
+ * This string can not be localized using the standard
+ * openstep functions/macros. By using this gnustep extension,
+ * you can localize it as follows:
+ * </p>
+ * <p>
+ * <code>
+ * NSString *message = GSLocalizedStaticString (@"Hi there",
+ * @"Greeting");
+ *
+ * ... some code ...
+ *
+ * NSLog (NSLocalizedString (message, @""));
+ * </code>
+ * </p>
+ * <p>
+ * When the tools generate the
+ * <code>Localizable.strings</code> file from the source
+ * code, they will ignore the <code>NSLocalizedString</code>
+ * call while they will extract the string (and the comment)
+ * to localize from the <code>GSLocalizedStaticString</code>
+ * call.
+ * </p>
+ * <p>
+ * When the code is compiled, instead, the
+ * <code>GSLocalizedStaticString</code> call is ignored (discarded,
+ * it is a macro which simply expands to <code>key</code>), while
+ * the <code>NSLocalizedString</code> will actually look up the
+ * string for translation in the <code>Localizable.strings</code>
+ * file.
+ * </p>
+ * <p>
+ * Please note that there is currently no macro/function to
+ * localize static strings using different tables. If you
+ * need that functionality, you have either to prepare the
+ * localization tables by hand, or to rewrite your code in
+ * such a way as not to use static strings.
+ * </p>
+ */
+#define GSLocalizedStaticString(key, comment) key
+
+/**
+ * To be used inside a method for making sure that a range does not specify
+ * anything outside the size of an array/string. Raises exception if range
+ * extends beyond [0,size]. Size must be an unsigned integer (NSUInteger).
+ */
+#define GS_RANGE_CHECK(RANGE, SIZE) \
+ if (RANGE.location > (NSUInteger)SIZE \
+ || RANGE.length > ((NSUInteger)SIZE - RANGE.location)) \
+ [NSException raise: NSRangeException format: @"in %s, range { %"\
+ PRIuPTR ", %" PRIuPTR " } extends beyond size (%" PRIuPTR ")", \
+ GSNameFromSelector(_cmd), RANGE.location, RANGE.length, (NSUInteger)SIZE]
+
+/** Checks whether INDEX is strictly less than OVER (within C array space).
+ * INDEX and OVER must be unsigned integers (NSUInteger).
+ */
+#define CHECK_INDEX_RANGE_ERROR(INDEX, OVER) \
+if ((NSUInteger)INDEX >= (NSUInteger)OVER) \
+ [NSException raise: NSRangeException \
+ format: @"in %s, index %" PRIuPTR " is out of range", \
+ GSNameFromSelector(_cmd), (NSUInteger)INDEX]
+
+#endif /* __GNUSTEP_GNUSTEP_H_INCLUDED_ */
diff --git a/gcc/testsuite/objc-obj-c++-shared/GNUStep/GNUstepBase/GSBlocks.h b/gcc/testsuite/objc-obj-c++-shared/GNUStep/GNUstepBase/GSBlocks.h
new file mode 100644
index 0000000..ac4e9c9
--- /dev/null
+++ b/gcc/testsuite/objc-obj-c++-shared/GNUStep/GNUstepBase/GSBlocks.h
@@ -0,0 +1,145 @@
+/** Definitions for block support for GNUStep
+ Copyright (C) 2011 Free Software Foundation, Inc.
+
+ This file is part of the GNUstep Base Library.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free
+ Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02111 USA.
+
+ */
+
+#ifndef __GSBlocks_h_GNUSTEP_BASE_INCLUDE
+#define __GSBlocks_h_GNUSTEP_BASE_INCLUDE
+
+/* Define the has_feature pseudo-macro for GCC. */
+#ifndef __has_feature
+#define __has_feature(x) 0
+#endif
+
+#ifndef GCC_VERSION
+#define GCC_VERSION (__GNUC__ * 1000 + __GNUC_MINOR__)
+#endif
+
+#if __has_feature(blocks)
+
+#define BLOCK_SCOPE __block
+/**
+ * Defines a block type. Will work whether or not the compiler natively
+ * supports blocks.
+ */
+#define DEFINE_BLOCK_TYPE(name, retTy, argTys, ...) \
+typedef retTy(^name)(argTys, ## __VA_ARGS__)
+
+#define DEFINE_BLOCK_TYPE_NO_ARGS(name, retTy) \
+typedef retTy(^name)()
+
+/**
+ * Calls a block. Works irrespective of whether the compiler supports blocks.
+ */
+#define CALL_BLOCK(block, args, ...) block(args, ## __VA_ARGS__)
+
+/**
+ * Calls a block without arguments.
+ */
+#define CALL_BLOCK_NO_ARGS(block) block()
+#else
+
+/* Fall-back versions for when the compiler doesn't have native blocks support.
+ */
+#if (GCC_VERSION >= 3000)
+
+#define DEFINE_BLOCK_TYPE(name, retTy, argTys, ...) \
+ typedef struct {\
+ void *isa;\
+ int flags;\
+ int reserved;\
+ retTy (*invoke)(void*, argTys, ## __VA_ARGS__);\
+ } *name
+
+#define DEFINE_BLOCK_TYPE_NO_ARGS(name, retTy) \
+ typedef struct {\
+ void *isa;\
+ int flags;\
+ int reserved;\
+ retTy (*invoke)(void*);\
+ } *name
+
+#define CALL_BLOCK(block, args, ...) block->invoke(block, args, ## __VA_ARGS__)
+
+#define CALL_BLOCK_NO_ARGS(block) block->invoke(block)
+#define BLOCK_SCOPE
+
+#else /* GCC_VERSION >= 3000 */
+
+#define DEFINE_BLOCK_TYPE(name, retTy, argTys...) \
+ typedef struct {\
+ void *isa;\
+ int flags;\
+ int reserved;\
+ retTy (*invoke)(void*, argTys);\
+ } *name
+
+#define DEFINE_BLOCK_TYPE_NO_ARGS(name, retTy) \
+ typedef struct {\
+ void *isa;\
+ int flags;\
+ int reserved;\
+ retTy (*invoke)(void*);\
+ } *name
+
+
+#define CALL_BLOCK(block, args...) block->invoke(block, args)
+#define CALL_BLOCK_NO_ARGS(block) block->invoke(block)
+#define BLOCK_SCOPE
+#endif /* GCC_VERSION >= 3000 */
+
+#endif /* __has_feature(blocks) */
+
+#if __has_include(<objc/blocks_runtime.h>)
+# include <objc/blocks_runtime.h>
+#else
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * _Block_copy and _Block_release are weakly imported, but can be assumed
+ * to be available whenever a feature using blocks is accessed
+ * by an application.
+ */
+
+/* weak attributed supported only with ELF, MINGW is COFF */
+#ifndef __MINGW32__
+
+void *_Block_copy(const void *) __attribute__((weak));
+void _Block_release(const void *) __attribute__((weak));
+
+#endif /* __MINGW32__ */
+
+#ifdef __cplusplus
+}
+#endif
+
+#ifndef Block_copy
+# define Block_copy(x) ((__typeof(x))_Block_copy((const void *)(x)))
+#endif
+#ifndef Block_release
+# define Block_release(x) _Block_release((const void *)(x))
+#endif
+
+#endif /* __has_include(<objc/blocks_runtime.h>) */
+#endif /* __GSBlocks_h_GNUSTEP_BASE_INCLUDE */
+
diff --git a/gcc/testsuite/objc-obj-c++-shared/GNUStep/GNUstepBase/GSConfig.h b/gcc/testsuite/objc-obj-c++-shared/GNUStep/GNUstepBase/GSConfig.h
new file mode 100644
index 0000000..a0e7cc7
--- /dev/null
+++ b/gcc/testsuite/objc-obj-c++-shared/GNUStep/GNUstepBase/GSConfig.h
@@ -0,0 +1,462 @@
+/* Machine/OS specific configuration information for GNUstep
+
+ Please NOTE - GSConfig.h is generated by the configure script from the
+ file GSConfig.h.in - changes/fixes need to be made to the original file,
+ not to the GSConfig.h generated from it.
+
+ Copyright (C) 1998-2010 Free Software Foundation, Inc.
+
+ Written by: Richard frith-Macdonald <richard@brainstorm.co.uk>
+
+ This file is part of the GNUstep Base Library.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free
+ Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02111 USA.
+ */
+
+#ifndef included_GSConfig_h
+#define included_GSConfig_h
+
+/* Check the compiler to see if we are building on/for ms-windows.
+ * Whatever the compiler uses, we want a standard setting of _WIN64
+ * to indicate 64bit AND _WIN32 to indicate ms-windows.
+ * These are defined by gcc, clang, and microsoft compilers anyway.
+ */
+#if defined(__WIN32__) \
+ || defined(__MS_WIN32__) \
+ || defined(__MINGW32__)
+# if !defined(_WIN32)
+# define _WIN32
+# endif
+#endif
+#if defined(__WIN64__) \
+ || defined(__MS_WIN64__) \
+ || defined(__MINGW64__)
+# if !defined(__WIN64__)
+# define __WIN64__
+# endif
+# if !defined(_WIN32)
+# define _WIN32
+# endif
+#endif
+
+/* Check to see if this is a MINGW build (all we currently support)
+ */
+#if defined(__MINGW32__) || defined(__MINGW64__)
+# if !defined(__MINGW__)
+# define __MINGW__
+# endif
+#endif
+
+// Make sure we expose the constants that we use in ObjC++ mode
+#ifndef __STDC_CONSTANT_MACROS
+#define __STDC_CONSTANT_MACROS 1
+#endif
+#ifndef __STDC_LIMIT_MACROS
+#define __STDC_LIMIT_MACROS 1
+#endif
+
+#if !defined(NeXT_Foundation_LIBRARY)
+
+/* An alternate to GS_FAKE_MAIN which forces the user to call the
+ NSProcessInfo initialization in 'main', GS_FAKE_MAIN must also
+ be undefined. */
+#if 0
+#define GS_PASS_ARGUMENTS 0
+#endif
+
+#define GS_FAKE_MAIN 0
+#if GS_FAKE_MAIN
+
+/*
+ * NOTE - if GS_FAKE_MAIN (above) is set to 1, this hack applies - and you
+ * must make sure that this file is included in any file that implements
+ * the 'main()' function and links with the GNUstep base libarary.
+ * You should NOT include this file in a program that does not link with
+ * the base library.
+ * This file is included automatically in NSObject.h and Foundation.h
+ *
+ * The Foundation classe NSProcessInfo need access to the argc, argv,
+ * and env variables of the main() function. The purpose of this (ugly hack)
+ * definition is to give the gstep-base library the opportunity to implement
+ * its own main function with private access to the global vars. The private
+ * main() implementation (in NSProcessInfo.m) will then call the user defined
+ * gnustep_base_user_main() function.
+ *
+ * The original hack was -
+ ** Written by: Georg Tuparev, EMBL & Academia Naturalis,
+ ** Heidelberg, Germany
+ ** Tuparev@EMBL-Heidelberg.de
+ **
+ ** NOTE! This is very dirty and dangerous trick. I spend several hours
+ ** on thinking and man pages browsing, but couldn't find better solution.
+ ** I know that I will spend 666 years in the Computer Hell for writing
+ ** this hack, and the master devil (Bully Boy) will send me to write
+ ** Windowz software.
+ ** BTW, for writing this hack I got personal congratulations from Dennis
+ ** Ritchie and Bjarne Stroustrup sent me a bunch of flowers and asked me
+ ** to participate in the standardization committee for C-- v.6.0 as
+ ** responsible for the new Tab-Overriding-Operator and Scope-Sensitive-
+ ** Comments ... but this makes my situation even worse ;-)
+ ** - Georg
+ *
+ * On some systems, there are other relatively clean workarounds, if this
+ * applies to the system you are running on, your configuration script
+ * should have set GS_FAKE_MAIN to zero, so that this define hack will
+ * not be used.
+ */
+
+#define main gnustep_base_user_main
+
+#endif /* GS_FAKE_MAIN */
+#endif
+
+/*
+ * Definition to specify if your processor stores words with the most
+ * significant byte first (like Motorola and SPARC, unlike Intel and VAX).
+ */
+#define GS_WORDS_BIGENDIAN 0
+
+/*
+ * Size definitions for standard types
+ */
+#define GS_SIZEOF_SHORT 2
+#define GS_SIZEOF_INT 4
+#define GS_SIZEOF_LONG 8
+#define GS_SIZEOF_LONG_LONG 8
+#define GS_SIZEOF_FLOAT 4
+#define GS_SIZEOF_DOUBLE 8
+#define GS_SIZEOF_VOIDP 8
+
+/*
+ * Size information to be places in bits 5 and 6 of type encoding bytes
+ * in archives (bits 0 to 4 are used for basic type info and bit 7 is
+ * used to mark cross-references to previously encoded objects).
+ */
+#define _GSC_S_SHT _GSC_I16
+#define _GSC_S_INT _GSC_I32
+#define _GSC_S_LNG _GSC_I64
+#define _GSC_S_LNG_LNG _GSC_I64
+
+/*
+ * Type definitions for types with known sizes.
+ */
+typedef signed char gss8;
+typedef unsigned char gsu8;
+typedef signed short gss16;
+typedef unsigned short gsu16;
+typedef signed int gss32;
+typedef unsigned int gsu32;
+typedef signed long gss64;
+typedef unsigned long gsu64;
+typedef struct { gsu8 a[16]; } gss128;
+typedef struct { gsu8 a[16]; } gsu128;
+typedef float gsf32;
+typedef double gsf64;
+
+/*
+ * Integer type with same size as a pointer
+ */
+typedef unsigned long gsuaddr;
+typedef long gssaddr;
+typedef gsuaddr gsaddr;
+
+/*
+ * Do we have real 64-bit and 128-bit integers or are we just pretending.
+ */
+#define GS_HAVE_I64 1
+#define GS_HAVE_I128 0
+
+/*
+ * Ensure some standard types are defined.
+ */
+#include <inttypes.h>
+
+
+
+
+
+
+
+
+
+
+
+/*
+ * PTR Limit information replacements for buggy headers
+ */
+#if 0
+#undef INTPTR_MAX
+#define INTPTR_MAX
+#undef INTPTR_MIN
+#define INTPTR_MIN
+#undef UINTPTR_MAX
+#define UINTPTR_MAX
+#endif
+
+
+/*
+ * Do we have zlib for file handle compression?
+ */
+#define USE_ZLIB 1
+
+/*
+ * Do we have the GNU Multiple-precision library for NSDecimal?
+ */
+//#define USE_GMP 1
+#define USE_GMP 0
+
+#ifdef GS_WITH_GC
+#undef GS_WITH_GC
+#endif
+#define GS_WITH_GC 0
+
+/*
+ * Define to say if we use NXConstantString or NSConstantString
+ */
+#define NXConstantString NSConstantString
+
+
+/*
+ * Wide unicode character type.
+ */
+#ifndef UTF32Char
+#define UTF32Char uint32_t
+#endif
+
+/*
+ * Native character type for use in systemcalls etc.
+ */
+
+#if defined(__MINGW__)
+# define GSNativeChar uint16_t
+#else
+# define GSNativeChar char
+#endif
+
+/*
+ * Types used to avoid exposing pthread header in NSLock.h
+ * NB. These types should *never* be used except to provide enough space
+ * in a class layout for the type of data actually used by the pthread
+ * implementation of the current platform.
+ */
+typedef struct {
+ uint8_t dummy[48];
+} gs_cond_t __attribute__((aligned (8)));
+typedef struct {
+ uint8_t dummy[40];
+} gs_mutex_t __attribute__((aligned (8)));
+
+#define OBJC2RUNTIME 1
+#define BASE_NATIVE_OBJC_EXCEPTIONS 1
+#define GS_NONFRAGILE 0
+#define GS_MIXEDABI 0
+#define GS_USE_LIBXML 0
+#define GS_USE_GNUTLS 0
+#define GS_USE_AVAHI 0
+#define GS_USE_MDNS 0
+#define GS_USE_ICU 0
+#define GS_USE_LIBDISPATCH 0
+#define GS_USE_LIBDISPATCH_RUNLOOP 0
+#define GS_HAVE_OBJC_ROOT_CLASS_ATTR 0
+
+#ifndef __has_include
+# define __has_include(x) 0
+#endif
+#ifndef __has_feature
+# define __has_feature(x) 0
+#endif
+#ifndef __has_builtin
+# define __has_builtin(x) 0
+#endif
+
+/*
+ * __has_extension has slightly different semantics from __has_feature.
+ * It evaluates to true if the feature is supported by by clang for the
+ * current compilation unit (language and -f switches), regardless of
+ * whether it is part of the language standard or just a (non-standard)
+ * extension.
+ */
+#ifndef __has_extension
+# define __has_extension(x) __has_feature(x)
+#endif
+
+#if defined(_WIN32)
+#define BOOL WinBOOL
+#define __OBJC_BOOL 1
+#include <w32api.h>
+#ifndef _WIN32_WINNT
+#define _WIN32_WINNT Windows2000
+#endif
+#if !defined(WINVER)
+#define WINVER Windows2000
+#elif (WINVER < Windows2000)
+#undef WINVER
+#define WINVER Windows2000
+#endif
+
+#if defined(__WIN64__)
+#include <winsock2.h>
+#include <windows.h>
+#else
+#include <windows.h>
+#include <winsock2.h>
+#endif
+
+#undef __OBJC_BOOL
+#undef BOOL
+#endif
+
+/* Include the blocks runtime header if it's available (It shouldn't matter
+ * that this doesn't work on compilers that don't support __has_include(),
+ * because they also don't support blocks).
+ */
+#if __has_include(<objc/block_runtime.h>)
+# include <objc/block_runtime.h>
+#endif
+
+#ifndef _WIN32
+#include <sys/param.h> /* Hack to get rid of warning in GNU libc 2.0.3. */
+#endif
+
+/* The following group of lines maintained by the gstep-base configure */
+#define GNUSTEP_BASE_VERSION 1.26.0
+#define GNUSTEP_BASE_MAJOR_VERSION 1
+#define GNUSTEP_BASE_MINOR_VERSION 26
+#define GNUSTEP_BASE_SUBMINOR_VERSION 0
+#define GNUSTEP_BASE_GCC_VERSION 4.0.0
+
+/* Do not use the following macros!
+ */
+#define OBJC_DEP(M) \
+ ({ static BOOL beenHere = NO; if (beenHere == NO) {\
+ beenHere = YES; fprintf(stderr, "%s:%d %s", __FILE__, __LINE__, (M));}})
+
+#define OBJC_MALLOC(VAR, TYPE, NUM) \
+ (OBJC_DEP("OBJC_MALLOC is deprecated ... use malloc\n"),(VAR) = (TYPE *) malloc ((unsigned)(NUM)*sizeof(TYPE)))
+#define OBJC_VALLOC(VAR, TYPE, NUM) \
+ (OBJC_DEP("OBJC_VALLOC is deprecated\n"),(VAR) = (TYPE *) valloc ((unsigned)(NUM)*sizeof(TYPE)))
+#define OBJC_ATOMIC_MALLOC(VAR, TYPE, NUM) \
+ (OBJC_DEP("OBJC_ATOMIC_MALLOC is deprecated\n"),(VAR) = (TYPE *) malloc ((unsigned)(NUM)*sizeof(TYPE)))
+#define OBJC_REALLOC(VAR, TYPE, NUM) \
+ (OBJC_DEP("OBJC_REALLOC is deprecated ... use realloc\n"),(VAR) = (TYPE *) realloc ((VAR), (unsigned)(NUM)*sizeof(TYPE)))
+#define OBJC_CALLOC(VAR, TYPE, NUM) \
+ (OBJC_DEP("OBJC_CALLOC is deprecated ... use calloc\n"),(VAR) = (TYPE *) calloc ((unsigned)(NUM), sizeof(TYPE)))
+#define OBJC_FREE(PTR) (OBJC_DEP("OBJC_FREE is deprecated ... use free\n"), free (PTR))
+
+#ifndef MAX
+#define MAX(a,b) \
+ ({__typeof__(a) _MAX_a = (a); __typeof__(b) _MAX_b = (b); \
+ _MAX_a > _MAX_b ? _MAX_a : _MAX_b; })
+#endif
+
+#ifndef MIN
+#define MIN(a,b) \
+ ({__typeof__(a) _MIN_a = (a); __typeof__(b) _MIN_b = (b); \
+ _MIN_a < _MIN_b ? _MIN_a : _MIN_b; })
+#endif
+
+#ifndef ABS
+#define ABS(a) \
+ ({__typeof__(a) _ABS_a = (a); \
+ _ABS_a < 0 ? -_ABS_a : _ABS_a; })
+#endif
+
+#ifndef STRINGIFY
+#define STRINGIFY(s) XSTRINGIFY(s)
+#define XSTRINGIFY(s) #s
+#endif
+
+#ifndef OBJC_STRINGIFY
+#define OBJC_STRINGIFY(s) OBJC_XSTRINGIFY(s)
+#define OBJC_XSTRINGIFY(s) @#s
+#endif
+
+#ifndef PTR2LONG
+#define PTR2LONG(P) (((char*)(P))-(char*)0)
+#endif
+#ifndef LONG2PTR
+#define LONG2PTR(L) (((char*)0)+(L))
+#endif
+
+#if VSPRINTF_RETURNS_LENGTH
+#define VSPRINTF_LENGTH(VSPF_CALL) (VSPF_CALL)
+#else
+#define VSPRINTF_LENGTH(VSPF_CALL) strlen((VSPF_CALL))
+#endif /* VSPRINTF_RETURNS_LENGTH */
+
+#if VASPRINTF_RETURNS_LENGTH
+#define VASPRINTF_LENGTH(VASPF_CALL) (VASPF_CALL)
+#else
+#define VASPRINTF_LENGTH(VASPF_CALL) strlen((VASPF_CALL))
+#endif /* VSPRINTF_RETURNS_LENGTH */
+
+/* Evil hack to stop gcc-4.1 complaining about a dealloc method which
+ * does not call the superclass implementation.
+ */
+#define GSNOSUPERDEALLOC if (0) [super dealloc]
+
+#ifndef CF_EXCLUDE_CSTD_HEADERS
+#include <sys/types.h>
+#include <stdarg.h>
+#include <assert.h>
+#include <ctype.h>
+#include <errno.h>
+#include <float.h>
+#include <limits.h>
+#include <locale.h>
+#include <math.h>
+#include <setjmp.h>
+#include <signal.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <stdbool.h>
+#endif
+
+#if !__has_feature(objc_arc)
+// NetBSD > 6 defines __weak in cdefs_elf.h
+#ifdef __NetBSD__
+#undef __weak
+#endif
+# if !defined(__weak)
+# define __weak
+# endif
+# if !defined(__strong)
+# define __strong
+# endif
+#endif
+
+#ifndef __unsafe_unretained
+# if !__has_feature(objc_arc)
+# define __unsafe_unretained
+# endif
+#endif
+#ifndef __bridge
+# if !__has_feature(objc_arc)
+# define __bridge
+# endif
+#endif
+
+#if __has_builtin(__builtin_unreachable)
+# define GS_UNREACHABLE() __builtin_unreachable()
+#else
+# define GS_UNREACHABLE() abort()
+#endif
+
+#endif /* included_GSConfig_h */
+
diff --git a/gcc/testsuite/objc-obj-c++-shared/GNUStep/GNUstepBase/GSObjCRuntime.h b/gcc/testsuite/objc-obj-c++-shared/GNUStep/GNUstepBase/GSObjCRuntime.h
new file mode 100644
index 0000000..2088ee2
--- /dev/null
+++ b/gcc/testsuite/objc-obj-c++-shared/GNUStep/GNUstepBase/GSObjCRuntime.h
@@ -0,0 +1,631 @@
+/** Interface to ObjC runtime for GNUStep
+ Copyright (C) 1995, 1997, 2000, 2002, 2003 Free Software Foundation, Inc.
+
+ Written by: Andrew Kachites McCallum <mccallum@gnu.ai.mit.edu>
+ Date: 1995
+ Written by: Richard Frith-Macdonald <rfm@gnu.org>
+ Date: 2002
+
+ This file is part of the GNUstep Base Library.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free
+ Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02111 USA.
+
+ AutogsdocSource: Additions/GSObjCRuntime.m
+
+ */
+
+#ifndef __GSObjCRuntime_h_GNUSTEP_BASE_INCLUDE
+#define __GSObjCRuntime_h_GNUSTEP_BASE_INCLUDE
+
+#import "GSVersionMacros.h"
+#import "GSConfig.h"
+
+#include <stdio.h>
+
+#if 1 || NeXT_RUNTIME
+ #include <objc/objc.h>
+ #include <objc/objc-class.h>
+ #include <objc/objc-runtime.h>
+ #ifndef _C_ATOM
+ #define _C_ATOM '%'
+ #endif
+ #define _F_CONST 0x01
+ #define _F_IN 0x01
+ #define _F_OUT 0x02
+ #define _F_INOUT 0x03
+ #define _F_BYCOPY 0x04
+ #define _F_ONEWAY 0x08
+ #define _C_CONST 'r'
+ #define _C_IN 'n'
+ #define _C_INOUT 'N'
+ #define _C_OUT 'o'
+ #define _C_BYCOPY 'O'
+ #define _C_ONEWAY 'V'
+#else /* GNU Objective C Runtime */
+ #include <objc/objc.h>
+ #if defined (__GNU_LIBOBJC__)
+ #include <objc/runtime.h>
+ #else
+ #include <objc/objc-api.h>
+ #include <objc/encoding.h>
+ #endif
+#endif
+
+/*
+ * Hack for older compiler versions that don't have all defines
+ * needed in objc-api.h
+ */
+#ifndef _C_LNG_LNG
+#define _C_LNG_LNG 'q'
+#endif
+#ifndef _C_ULNG_LNG
+#define _C_ULNG_LNG 'Q'
+#endif
+
+#if OBJC2RUNTIME
+/* We have a real ObjC2 runtime.
+ */
+#include <objc/runtime.h>
+#else
+/* We emulate an ObjC2 runtime.
+ */
+#include <ObjectiveC2/objc/runtime.h>
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+@class NSArray;
+@class NSDictionary;
+@class NSObject;
+@class NSString;
+@class NSValue;
+
+#ifndef YES
+#define YES 1
+#endif
+#ifndef NO
+#define NO 0
+#endif
+#ifndef nil
+#define nil 0
+#endif
+
+#if !defined(_C_CONST)
+#define _C_CONST 'r'
+#endif
+#if !defined(_C_IN)
+#define _C_IN 'n'
+#endif
+#if !defined(_C_INOUT)
+#define _C_INOUT 'N'
+#endif
+#if !defined(_C_OUT)
+#define _C_OUT 'o'
+#endif
+#if !defined(_C_BYCOPY)
+#define _C_BYCOPY 'O'
+#endif
+#if !defined(_C_BYREF)
+#define _C_BYREF 'R'
+#endif
+#if !defined(_C_ONEWAY)
+#define _C_ONEWAY 'V'
+#endif
+#if !defined(_C_GCINVISIBLE)
+#define _C_GCINVISIBLE '!'
+#endif
+
+/*
+ * Functions for accessing instance variables directly -
+ * We can copy an ivar into arbitrary data,
+ * Get the type encoding for a named ivar,
+ * and copy a value into an ivar.
+ */
+GS_EXPORT BOOL
+GSObjCFindVariable(id obj, const char *name,
+ const char **type, unsigned int *size, int *offset);
+
+GS_EXPORT void
+GSObjCGetVariable(id obj, int offset, unsigned int size, void *data);
+
+GS_EXPORT void
+GSObjCSetVariable(id obj, int offset, unsigned int size, const void *data);
+
+GS_EXPORT NSArray *
+GSObjCMethodNames(id obj, BOOL recurse);
+
+GS_EXPORT NSArray *
+GSObjCVariableNames(id obj, BOOL recurse);
+
+/**
+ * <p>A Behavior can be seen as a "Protocol with an implementation" or a
+ * "Class without any instance variables". A key feature of behaviors
+ * is that they give a degree of multiple inheritance.
+ * </p>
+ * <p>Behavior methods, when added to a class, override the class's
+ * superclass methods, but not the class's methods.
+ * </p>
+ * <p>Whan a behavior class is added to a receiver class, not only are the
+ * methods defined in the behavior class added, but the methods from the
+ * behavior's class hierarchy are also added (unless already present).
+ * </p>
+ * <p>It's not the case that a class adding behaviors from another class
+ * must have "no instance vars". The receiver class just has to have the
+ * same layout as the behavior class (optionally with some additional
+ * ivars after those of the behavior class).
+ * </p>
+ * <p>This function provides Behaviors without adding any new syntax to
+ * the Objective C language. Simply define a class with the methods you
+ * want to add, then call this function with that class as the behavior
+ * argument.
+ * </p>
+ * <p>This function should be called in the +initialize method of the receiver.
+ * </p>
+ * <p>If you add several behaviors to a class, be aware that the order of
+ * the additions is significant.
+ * </p>
+ */
+GS_EXPORT void
+GSObjCAddClassBehavior(Class receiver, Class behavior);
+
+/**
+ * <p>An Override can be seen as a "category implemented as a separate class
+ * and manually added to the receiver class under program control, rather
+ * than automatically added by the compiler/runtime.
+ * </p>
+ * <p>Override methods, when added to a receiver class, replace the class's
+ * class's methods of the same name (or are added if the class did not define
+ * methods with that name).
+ * </p>
+ * <p>It's not the case that a class adding overrides from another class
+ * must have "no instance vars". The receiver class just has to have the
+ * same layout as the override class (optionally with some additional
+ * ivars after those of the override class).
+ * </p>
+ * <p>This function provides overrides without adding any new syntax to
+ * the Objective C language. Simply define a class with the methods you
+ * want to add, then call this function with that class as the override
+ * argument.
+ * </p>
+ * <p>This function should usually be called in the +initialize method
+ * of the receiver.
+ * </p>
+ * <p>If you add several overrides to a class, be aware that the order of
+ * the additions is significant.
+ * </p>
+ */
+GS_EXPORT void
+GSObjCAddClassOverride(Class receiver, Class override);
+
+/** Turn on (YES), off (NO) or test (-1) behavior debugging.
+ */
+GS_EXPORT BOOL GSObjCBehaviorDebug(int setget);
+
+GS_EXPORT NSValue *
+GSObjCMakeClass(NSString *name, NSString *superName, NSDictionary *iVars);
+
+GS_EXPORT void
+GSObjCAddClasses(NSArray *classes);
+
+/**
+ * Given a NULL terminated list of methods, add them to the class.<br />
+ * If the method already exists in a superclass, the new version overrides
+ * that one, but if the method already exists in the class itsself, the
+ * new one is quietly ignored (replace==NO) or replaced with the new
+ * version (if replace==YES).<br />
+ * To add class methods, cls should be the metaclass of the class to
+ * which the methods are being added.
+ */
+GS_EXPORT void
+GSObjCAddMethods(Class cls, Method *list, BOOL replace);
+
+/*
+ * Functions for key-value encoding ... they access values in an object
+ * either by selector or directly, but do so using NSNumber for the
+ * scalar types of data.
+ */
+GS_EXPORT id
+GSObjCGetVal(NSObject *self, const char *key, SEL sel,
+ const char *type, unsigned size, int offset);
+
+GS_EXPORT void
+GSObjCSetVal(NSObject *self, const char *key, id val, SEL sel,
+ const char *type, unsigned size, int offset);
+
+/*
+ * This section includes runtime functions
+ * to query and manipulate the ObjC runtime structures.
+ * These functions take care to not use ObjC code so
+ * that they can safely be used in +(void)load implementations
+ * where applicable.
+ */
+
+/**
+ * Deprecated ... use objc_getClassList()
+ */
+GS_EXPORT unsigned int
+GSClassList(Class *buffer, unsigned int max, BOOL clearCache);
+
+/**
+ * GSObjCClass() is deprecated ... use object_getClass()
+ */
+GS_EXPORT Class GSObjCClass(id obj);
+
+/**
+ * GSObjCSuper() is deprecated ... use class_getSuperclass()
+ */
+GS_EXPORT Class GSObjCSuper(Class cls);
+
+/**
+ * GSObjCIsInstance() is deprecated ... use object_getClass()
+ * in conjunction with class_isMetaClass()
+ */
+GS_EXPORT BOOL GSObjCIsInstance(id obj);
+
+/**
+ * GSObjCIsClass() is deprecated ... use object_getClass()
+ * in conjunction with class_isMetaClass()
+ */
+GS_EXPORT BOOL GSObjCIsClass(Class cls);
+
+/**
+ * Test to see if class inherits from another class
+ * The argument to this function must NOT be nil.
+ */
+GS_EXPORT BOOL GSObjCIsKindOf(Class cls, Class other);
+
+/**
+ * GSClassFromName() is deprecated ... use objc_lookUpClass()
+ */
+GS_EXPORT Class GSClassFromName(const char *name);
+
+/**
+ * GSNameFromClass() is deprecated ... use class_getName()
+ */
+GS_EXPORT const char *GSNameFromClass(Class cls);
+
+/**
+ * GSClassNameFromObject() is deprecated ... use object_getClass()
+ * in conjunction with class_getName()
+ */
+GS_EXPORT const char *GSClassNameFromObject(id obj);
+
+/**
+ * GSNameFromSelector() is deprecated ... use sel_getName()
+ */
+GS_EXPORT const char *GSNameFromSelector(SEL sel);
+
+/**
+ * GSSelectorFromName() is deprecated ... use sel_getUid()
+ */
+GS_EXPORT SEL
+GSSelectorFromName(const char *name);
+
+/**
+ * Return the selector for the specified name and types.<br />
+ * Returns a nul pointer if the name is nul.<br />
+ * Creates a new selector if necessary.<br />
+ * Code must NOT rely on this providing a selector with type information.
+ */
+GS_EXPORT SEL
+GSSelectorFromNameAndTypes(const char *name, const char *types);
+
+/**
+ * Return the type information from the specified selector.<br />
+ * May return a nul pointer if the selector was a nul pointer or if it
+ * was not typed (or if the runtime does not support typed selectors).<br />
+ * Code must NOT rely on this providing any type information.
+ */
+GS_EXPORT const char *
+GSTypesFromSelector(SEL sel);
+
+/**
+ * Compare only the type information ignoring qualifiers, the frame layout
+ * and register markers. Unlike sel_types_match, this function also
+ * handles comparisons of types with and without any layout information.
+ */
+GS_EXPORT BOOL
+GSSelectorTypesMatch(const char *types1, const char *types2);
+
+/** Takes full type information and skips forward to the actual type
+ * as specified in the _C_... constants.
+ */
+GS_EXPORT const char *
+GSSkipTypeQualifierAndLayoutInfo(const char *types);
+
+/**
+ * Returns a protocol object with the corresponding name.
+ * This function searches the registered classes for any protocol
+ * with the supplied name. If one is found, it is cached in
+ * for future requests. If efficiency is a factor then use
+ * GSRegisterProtocol() to insert a protocol explicitly into the cache
+ * used by this function. If no protocol is found this function returns
+ * nil.
+ */
+GS_EXPORT Protocol *
+GSProtocolFromName(const char *name);
+
+/**
+ * Registers proto in the cache used by GSProtocolFromName().
+ */
+GS_EXPORT void
+GSRegisterProtocol(Protocol *proto);
+
+/**
+ * A variant of protocol_getMethodDescription which recursively searches
+ * parent protocols if the requested selector isn't found in the given
+ * protocol.
+ *
+ * Returns a {NULL, NULL} structure if the requested selector couldn't be
+ * found.
+ */
+GS_EXPORT struct objc_method_description
+GSProtocolGetMethodDescriptionRecursive(Protocol *aProtocol, SEL aSel, BOOL isRequired, BOOL isInstance);
+
+/*
+ * Unfortunately the definition of the symbols
+ * 'Method(_t)', 'MethodList(_t)' and 'IVar(_t)'
+ * are incompatible between the GNU and NeXT/Apple runtimes.
+ * We introduce GSMethod, GSMethodList and GSIVar to allow portability.
+ */
+typedef Method GSMethod;
+typedef Ivar GSIVar;
+
+/**
+ * Returns the pointer to the method structure
+ * for the selector in the specified class.
+ * Depending on searchInstanceMethods, this function searches
+ * either instance or class methods.
+ * Depending on searchSuperClassesm this function searches
+ * either the specified class only or also its superclasses.<br/>
+ * To obtain the implementation pointer IMP use returnValue->method_imp
+ * which should be safe across all runtimes.<br/>
+ * It should be safe to use this function in +load implementations.<br/>
+ * This function should currently (June 2004) be considered WIP.
+ * Please follow potential changes (Name, parameters, ...) closely until
+ * it stabilizes.
+ */
+GS_EXPORT GSMethod
+GSGetMethod(Class cls, SEL sel,
+ BOOL searchInstanceMethods,
+ BOOL searchSuperClasses);
+
+/**
+ * Deprecated .. does nothing.
+ */
+GS_EXPORT void
+GSFlushMethodCacheForClass (Class cls);
+
+/**
+ * Deprecated .. use class_getInstanceVariable()
+ */
+GS_EXPORT GSIVar
+GSCGetInstanceVariableDefinition(Class cls, const char *name);
+
+/**
+ * Deprecated .. use class_getInstanceVariable()
+ */
+GS_EXPORT GSIVar
+GSObjCGetInstanceVariableDefinition(Class cls, NSString *name);
+
+/**
+ * GSObjCVersion() is deprecated ... use class_getVersion()
+ */
+GS_EXPORT int GSObjCVersion(Class cls);
+
+/**
+ * Quickly return autoreleased data storage area.
+ */
+GS_EXPORT void *
+GSAutoreleasedBuffer(unsigned size);
+
+/**
+ * <p>Prints a message to fptr using the format string provided and any
+ * additional arguments. The format string is interpreted as by
+ * the NSString formatted initialisers, and understands the '%@' syntax
+ * for printing an object.
+ * </p>
+ * <p>The data is written to the file pointer in the default CString
+ * encoding if possible, as a UTF8 string otherwise.
+ * </p>
+ * <p>This function is recommended for printing general log messages.
+ * For debug messages use NSDebugLog() and friends. For error logging
+ * use NSLog(), and for warnings you might consider NSWarnLog().
+ * </p>
+ */
+GS_EXPORT BOOL
+GSPrintf (FILE *fptr, NSString *format, ...);
+
+
+
+GS_EXPORT NSArray *
+GSObjCAllSubclassesOfClass(Class cls);
+
+GS_EXPORT NSArray *
+GSObjCDirectSubclassesOfClass(Class cls);
+
+/** Function to change the class of the specified instance to newClass.
+ * This handles memory debugging issues in GNUstep-base and also
+ * deals with class finalisation issues in a garbage collecting
+ * environment, so you should use this function rather than attempting
+ * to swizzle class pointers directly.
+ */
+GS_EXPORT void
+GSClassSwizzle(id instance, Class newClass);
+
+#if !defined(GS_GNUSTEP_V) || (GS_GNUSTEP_V >= GS_API_ANY && GS_GNUSTEP_V < 011500)
+//GS_API_VERSION(GS_API_ANY,011500)
+
+GS_EXPORT const char *
+GSLastErrorStr(long error_id) GS_DEPRECATED_FUNC;
+
+#endif
+
+
+
+#ifndef GS_MAX_OBJECTS_FROM_STACK
+/**
+ * The number of objects to try to get from varargs into an array on
+ * the stack ... if there are more than this, use the heap.
+ * NB. This MUST be a multiple of 2
+ */
+#define GS_MAX_OBJECTS_FROM_STACK 128
+#endif
+
+/**
+ * <p>This is a macro designed to minimise the use of memory allocation and
+ * deallocation when you need to work with a vararg list of objects.<br />
+ * The objects are unpacked from the vararg list into two 'C' arrays and
+ * then a code fragment you specify is able to make use of them before
+ * that 'C' array is destroyed.
+ * </p>
+ * <p>The firstObject argument is the name of the formal parameter in your
+ * method or function which precedes the ', ...' denoting variable args.
+ * </p>
+ * <p>The code argument is a piece of objective-c code to be executed to
+ * make use of the objects stored in the 'C' arrays.<br />
+ * When this code is called the unsigned integer '__count' will contain the
+ * number of objects unpacked, the pointer '__objects' will point to
+ * the first object in each pair, and the pointer '__pairs' will point
+ * to an array containing the second halves of the pairs of objects
+ * whose first halves are in '__objects'.<br />
+ * This lets you pack a list of the form 'key, value, key, value, ...'
+ * into an array of keys and an array of values.
+ * </p>
+ */
+#define GS_USEIDPAIRLIST(firstObject, code...) ({\
+ va_list __ap; \
+ unsigned int __max = GS_MAX_OBJECTS_FROM_STACK; \
+ unsigned int __count = 0; \
+ id __buf[__max]; \
+ id *__objects = __buf; \
+ id *__pairs = &__objects[__max/2]; \
+ id __obj = firstObject; \
+ va_start(__ap, firstObject); \
+ while (__obj != nil && __count < __max) \
+ { \
+ if ((__count % 2) == 0) \
+ { \
+ __objects[__count/2] = __obj; \
+ } \
+ else \
+ { \
+ __pairs[__count/2] = __obj; \
+ } \
+ __obj = va_arg(__ap, id); \
+ if (++__count == __max) \
+ { \
+ while (__obj != nil) \
+ { \
+ __count++; \
+ __obj = va_arg(__ap, id); \
+ } \
+ } \
+ } \
+ if ((__count % 2) == 1) \
+ { \
+ __pairs[__count/2] = nil; \
+ __count++; \
+ } \
+ va_end(__ap); \
+ if (__count > __max) \
+ { \
+ unsigned int __tmp; \
+ __objects = (id*)malloc(__count*sizeof(id)); \
+ __pairs = &__objects[__count/2]; \
+ __objects[0] = firstObject; \
+ va_start(__ap, firstObject); \
+ for (__tmp = 1; __tmp < __count; __tmp++) \
+ { \
+ if ((__tmp % 2) == 0) \
+ { \
+ __objects[__tmp/2] = va_arg(__ap, id); \
+ } \
+ else \
+ { \
+ __pairs[__tmp/2] = va_arg(__ap, id); \
+ } \
+ } \
+ va_end(__ap); \
+ } \
+ code; \
+ if (__objects != __buf) free(__objects); \
+})
+
+/**
+ * <p>This is a macro designed to minimise the use of memory allocation and
+ * deallocation when you need to work with a vararg list of objects.<br />
+ * The objects are unpacked from the vararg list into a 'C' array and
+ * then a code fragment you specify is able to make use of them before
+ * that 'C' array is destroyed.
+ * </p>
+ * <p>The firstObject argument is the name of the formal parameter in your
+ * method or function which precedes the ', ...' denoting variable args.
+ * </p>
+ * <p>The code argument is a piece of objective-c code to be executed to
+ * make use of the objects stored in the 'C' array.<br />
+ * When this code is called the unsigned integer '__count' will contain the
+ * number of objects unpacked, and the pointer '__objects' will point to
+ * the unpacked objects, ie. firstObject followed by the vararg arguments
+ * up to (but not including) the first nil.
+ * </p>
+ */
+#define GS_USEIDLIST(firstObject, code...) ({\
+ va_list __ap; \
+ unsigned int __max = GS_MAX_OBJECTS_FROM_STACK; \
+ unsigned int __count = 0; \
+ id __buf[__max]; \
+ id *__objects = __buf; \
+ id __obj = firstObject; \
+ va_start(__ap, firstObject); \
+ while (__obj != nil && __count < __max) \
+ { \
+ __objects[__count] = __obj; \
+ __obj = va_arg(__ap, id); \
+ if (++__count == __max) \
+ { \
+ while (__obj != nil) \
+ { \
+ __count++; \
+ __obj = va_arg(__ap, id); \
+ } \
+ } \
+ } \
+ va_end(__ap); \
+ if (__count > __max) \
+ { \
+ unsigned int __tmp; \
+ __objects = (id*)NSZoneMalloc(NSDefaultMallocZone(),__count*sizeof(id)); \
+ va_start(__ap, firstObject); \
+ __objects[0] = firstObject; \
+ for (__tmp = 1; __tmp < __count; __tmp++) \
+ { \
+ __objects[__tmp] = va_arg(__ap, id); \
+ } \
+ va_end(__ap); \
+ } \
+ code; \
+ if (__objects != __buf) NSZoneFree (NSDefaultMallocZone(),__objects); \
+})
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __GSObjCRuntime_h_GNUSTEP_BASE_INCLUDE */
diff --git a/gcc/testsuite/objc-obj-c++-shared/GNUStep/GNUstepBase/GSVersionMacros.h b/gcc/testsuite/objc-obj-c++-shared/GNUStep/GNUstepBase/GSVersionMacros.h
new file mode 100644
index 0000000..e7cfb5e
--- /dev/null
+++ b/gcc/testsuite/objc-obj-c++-shared/GNUStep/GNUstepBase/GSVersionMacros.h
@@ -0,0 +1,460 @@
+/* GSVersionMacros.h - macros for managing API versioning and visibility
+ Copyright (C) 2006-2014 Free Software Foundation, Inc.
+
+ Written by: Richard Frith-Macdonald <rfm@gnu.org>
+ Date: Oct, October 2006
+
+ This file is part of GNUstep.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free
+ Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef __GNUSTEP_GSVERSIONMACROS_H_INCLUDED_
+#define __GNUSTEP_GSVERSIONMACROS_H_INCLUDED_
+
+/* By default we defined NO_GNUSTEP to 0 so that we will include extensions.
+ */
+#if !defined(NO_GNUSTEP)
+# define NO_GNUSTEP 0
+#endif
+
+/* Check consistency of definitions for system compatibility.
+ */
+#if defined(STRICT_OPENSTEP)
+# define GS_OPENSTEP_V 10000
+# undef NO_GNUSTEP
+# define NO_GNUSTEP 1
+#elif defined(STRICT_MACOS_X)
+# define GS_OPENSTEP_V 100600
+# undef NO_GNUSTEP
+# define NO_GNUSTEP 1
+#endif
+
+/* Define the GS_OSX_ADJUST() macro to adjust OSX style version macros
+ * to GNUstep style version macros.
+ */
+#define GS_OSX_ADJUST(V) ((V) >= 10000 ? (V) : ((V)/100*10000 + (V)%100*10))
+
+/* Define OSX compatibility version macros if necessary.
+ */
+#if !defined(MAC_OS_X_VERSION_10_0)
+#define MAC_OS_X_VERSION_10_0 1000
+#define MAC_OS_X_VERSION_10_1 1010
+#define MAC_OS_X_VERSION_10_2 1020
+#define MAC_OS_X_VERSION_10_3 1030
+#define MAC_OS_X_VERSION_10_4 1040
+#define MAC_OS_X_VERSION_10_5 1050
+#define MAC_OS_X_VERSION_10_6 1060
+#define MAC_OS_X_VERSION_10_7 1070
+#define MAC_OS_X_VERSION_10_8 1080
+#define MAC_OS_X_VERSION_10_9 1090
+#define MAC_OS_X_VERSION_10_10 1100
+#define MAC_OS_X_VERSION_10_11 1110
+#define MAC_OS_X_VERSION_10_12 1120
+#define MAC_OS_X_VERSION_10_13 1130
+#define MAC_OS_X_VERSION_10_14 1140
+#endif /* MAC_OS_X_VERSION_10_0 */
+
+/* Allow MAC_OS_X_VERSION_MAX_ALLOWED to be used in place of GS_OPENSTEP_V
+ * if GS_OPENSTEP_V is not defined.
+ */
+#ifndef GS_OPENSTEP_V
+#ifdef MAC_OS_X_VERSION_MAX_ALLOWED
+#define GS_OPENSTEP_V GS_OSX_ADJUST(MAC_OS_X_VERSION_MAX_ALLOWED)
+#endif /* MAC_OS_X_VERSION_MAX_ALLOWED */
+#endif /* GS_OPENSTEP_V */
+
+/*
+ * NB. The version values below must be integers ... by convention these are
+ * made up of two digits each for major, minor and subminor version numbers
+ * (ie each is in the range 00 to 99 though a leading zero in the major
+ * number is not permitted).
+ * So for a MacOS-X 10.3.9 release the version number would be 100309
+ *
+ * You may define GS_GNUSTEP_V or GS_OPENSTEP_V to ensure that your
+ * program only 'sees' the specified varsion of the API.
+ */
+
+/**
+ * <p>Macro to check a defined GNUstep version number (GS_GNUSTEP_V) against
+ * the supplied arguments. Returns true if no GNUstep version is specified,
+ * or if ADD &lt;= version &lt; REM, where ADD is the version
+ * number at which a feature guarded by the macro was introduced and
+ * REM is the version number at which it was removed.
+ * </p>
+ * <p>The version number arguments are six digit integers where the first
+ * two digits are the major version number, the second two are the minor
+ * version number and the last two are the subminor number (all left padded
+ * with a zero where necessary). However, for convenience you can also
+ * use the predefined constants ...
+ * <ref type="macro" id="GS_API_NONE">GS_API_NONE</ref>,
+ * <ref type="macro" id="GS_API_LATEST">GS_API_LATEST</ref>,
+ * </p>
+ * <p>Also see <ref type="macro" id="OS_API_VERSION">OS_API_VERSION</ref>
+ * </p>
+ * <p>NB. If you are changing the API (eg adding a new feature) you need
+ * to control the visibility io the new header file code using<br />
+ * <code>#if GS_API_VERSION(ADD,GS_API_LATEST)</code><br />
+ * where <code>ADD</code> is the version number of the next minor
+ * release after the most recent one.<br />
+ * As a general principle you should <em>not</em> change the API with
+ * changing subminor version numbers ... as that tends to confuse
+ * people (though Apple has sometimes done it).
+ * </p>
+ */
+#define GS_API_VERSION(ADD,REM) \
+ (!defined(GS_GNUSTEP_V) || (GS_GNUSTEP_V >= ADD && GS_GNUSTEP_V < REM))
+
+/**
+ * <p>Macro to check a defined OpenStep/OPENSTEP/MacOS-X version against the
+ * supplied arguments. Returns true if no version is specified, or if
+ * ADD &lt;= version &lt; REM, where ADD is the version
+ * number at which a feature guarded by the macro was introduced and
+ * REM is the version number at which it was removed.
+ * </p>
+ * <p>The version number arguments are six digit integers where the first
+ * two digits are the major version number, the second two are the minor
+ * version number and the last two are the subminor number (all left padded
+ * with a zero where necessary). However, for convenience you can also
+ * use any of several predefined constants ...
+ * <ref type="macro" id="GS_API_NONE">GS_API_NONE</ref>,
+ * <ref type="macro" id="GS_API_LATEST">GS_API_LATEST</ref>,
+ * <ref type="macro" id="GS_API_OSSPEC">GS_API_OSSPEC</ref>,
+ * <ref type="macro" id="GS_API_OPENSTEP">GS_API_OPENSTEP</ref>,
+ * <ref type="macro" id="GS_API_MACOSX">GS_API_MACOSX</ref>
+ * </p>
+ * <p>Also see <ref type="macro" id="GS_API_VERSION">GS_API_VERSION</ref>
+ * </p>
+ * <p>For OSX compatibility, this macro also supports the use of Apple's
+ * symbolic constants for version numbering. Their contants are currently
+ * four digit values (two digits for the major version, one for the minor,
+ * and one for the subminor).
+ * </p>
+ * <p>The Apple compatibility version macros are currently:
+ * <ref type="macro" id="MAC_OS_X_VERSION_10_0">MAC_OS_X_VERSION_10_0</ref>,
+ * <ref type="macro" id="MAC_OS_X_VERSION_10_1">MAC_OS_X_VERSION_10_1</ref>,
+ * <ref type="macro" id="MAC_OS_X_VERSION_10_2">MAC_OS_X_VERSION_10_2</ref>,
+ * <ref type="macro" id="MAC_OS_X_VERSION_10_3">MAC_OS_X_VERSION_10_3</ref>,
+ * <ref type="macro" id="MAC_OS_X_VERSION_10_4">MAC_OS_X_VERSION_10_4</ref>,
+ * <ref type="macro" id="MAC_OS_X_VERSION_10_5">MAC_OS_X_VERSION_10_5</ref>,
+ * <ref type="macro" id="MAC_OS_X_VERSION_10_6">MAC_OS_X_VERSION_10_6</ref>,
+ * <ref type="macro" id="MAC_OS_X_VERSION_10_7">MAC_OS_X_VERSION_10_7</ref>,
+ * <ref type="macro" id="MAC_OS_X_VERSION_10_8">MAC_OS_X_VERSION_10_8</ref>
+ * <ref type="macro" id="MAC_OS_X_VERSION_10_9">MAC_OS_X_VERSION_10_9</ref>
+ * </p>
+ */
+#define OS_API_VERSION(ADD,REM) \
+ (!defined(GS_OPENSTEP_V) \
+ || (GS_OPENSTEP_V>=GS_OSX_ADJUST(ADD) && GS_OPENSTEP_V<GS_OSX_ADJUST(REM)))
+
+/**
+ * A constant which is the lowest possible version number (0) so that
+ * when used as the removal version (second argument of the GS_API_VERSION
+ * or OS_API_VERSION macro) represents a feature which is not present in
+ * any version.<br />
+ * eg.<br />
+ * #if <ref type="macro" id="OS_API_VERSION">OS_API_VERSION</ref>
+ * (GS_API_NONE, GS_API_NONE)<br />
+ * denotes code not present in OpenStep/OPENSTEP/MacOS-X
+ */
+#define GS_API_NONE 0
+
+/**
+ * A constant to represent a feature which is still present in the latest
+ * version. This is the highest possible version number.<br />
+ * eg.<br />
+ * #if <ref type="macro" id="OS_API_VERSION">OS_API_VERSION</ref>
+ * (GS_API_MACOSX, GS_API_LATEST)<br />
+ * denotes code present from the initial MacOS-X version onwards.
+ */
+#define GS_API_LATEST 999999
+
+/**
+ * The version number of the initial OpenStep specification.<br />
+ * eg.<br />
+ * #if <ref type="macro" id="OS_API_VERSION">OS_API_VERSION</ref>
+ * (GS_API_OSSPEC, GS_API_LATEST)<br />
+ * denotes code present from the OpenStep specification onwards.
+ */
+#define GS_API_OSSPEC 10000
+
+/**
+ * The version number of the first OPENSTEP implementation.<br />
+ * eg.<br />
+ * #if <ref type="macro" id="OS_API_VERSION">OS_API_VERSION</ref>
+ * (GS_API_OPENSTEP, GS_API_LATEST)<br />
+ * denotes code present from the initial OPENSTEP version onwards.
+ */
+#define GS_API_OPENSTEP 40000
+
+/**
+ * The version number of the first MacOS-X implementation.<br />
+ * eg.<br />
+ * #if <ref type="macro" id="OS_API_VERSION">OS_API_VERSION</ref>
+ * (GS_API_MACOSX, GS_API_LATEST)<br />
+ * denotes code present from the initial MacOS-X version onwards.
+ */
+#define GS_API_MACOSX 100000
+
+/* Allow OSX code comparing MAC_OS_X_VERSION_MAX_ALLOWED with a specific
+ * version to see if that version is allowed, to always have it allowed
+ * on GNUstep.
+ */
+#ifndef MAC_OS_X_VERSION_MAX_ALLOWED
+#define MAC_OS_X_VERSION_MAX_ALLOWED GS_API_LATEST
+#endif /* MAC_OS_X_VERSION_MAX_ALLOWED */
+
+
+#if defined(GNUSTEP_BASE_INTERNAL)
+#include "GNUstepBase/GSConfig.h"
+#else
+#include "GSConfig.h"
+#endif
+
+
+#if defined(__GNUC__) && defined(__GNUC_MINOR__) && !defined(__clang__)
+# define GS_GCC_MINREQ(maj, min) \
+ ((__GNUC__ << 16) + __GNUC_MINOR__ >= ((maj) << 16) + (min))
+#else
+# define GS_GCC_MINREQ(maj, min) 0
+#endif
+
+#if defined(__clang__)
+# define GS_CLANG_MINREQ(maj, min) \
+ ((__clang_major__ << 16) + __clang_minor__ >= ((maj) << 16) + (min))
+#else
+# define GS_CLANG_MINREQ(maj, min) 0
+#endif
+
+/* Attribute definitions for attributes which may or may not be supported
+ * depending on the compiler being used.
+ * NB we currently expect gcc to be version 4 or later.
+ *
+ * The definition should be of the form GS_XXX_CONTEXT where XXX is the
+ * name of the attribute and CONTEXT is one of FUNC, METH, or IVAR
+ * depending on where the attribute can be applied.
+ */
+
+#if defined(__clang__) || GS_GCC_MINREQ(3,1)
+# define GS_DEPRECATED_FUNC __attribute__ ((deprecated))
+#else
+# define GS_DEPRECATED_FUNC
+#endif
+
+#define GS_UNUSED_ARG __attribute__((unused))
+
+#define GS_UNUSED_FUNC __attribute__((unused))
+
+// FIXME ... what version of gcc?
+#if __clang__
+# define GS_UNUSED_IVAR __attribute__((unused))
+#else
+# define GS_UNUSED_IVAR
+#endif
+
+
+
+#ifndef __has_feature
+#define __has_feature(x) 0
+#endif
+
+/* The following is for deciding whether private instance variables
+ * should be visible ... if we are building with a compiler which
+ * does not define __has_feature then we know we don't have non-fragile
+ * ivar support.
+ * In the header we bracket instance variable declarations in a
+ * '#if GS_EXPOSE(classname) ... #endif' sequence, so that the variables
+ * will not be visible to code which uses the library.
+ * In the source file we define EXPOSE_classname_IVARS to be 1
+ * before including the header, so that the ivars are always available
+ * in the class source itsself
+ */
+
+#if GS_MIXEDABI
+# undef GS_NONFRAGILE
+# define GS_NONFRAGILE 0 /* Mixed is treated as fragile */
+#else
+# if (__has_feature(objc_nonfragile_abi))
+# if !GS_NONFRAGILE
+# if defined(GNUSTEP_BASE_INTERNAL)
+# error "You are building gnustep-base using the objc-nonfragile-abi but your gnustep-base was not configured to use it."
+# endif
+# endif
+# else
+# if GS_NONFRAGILE
+# error "Your gnustep-base was configured for the objc-nonfragile-abi but you are not using it now."
+# endif
+# endif
+#endif
+
+#define GS_EXPOSE(X) (!GS_NONFRAGILE || defined(EXPOSE_##X##_IVARS))
+
+/* Static analyser macros: Provide annotations to help the analyser */
+#ifdef __clang__
+# define GS_NORETURN_METHOD __attribute__((__noreturn__))
+#else
+# define GS_NORETURN_METHOD
+#endif
+
+#ifndef NS_RETURNS_RETAINED
+# if __has_feature(attribute_ns_returns_retained)
+# define NS_RETURNS_RETAINED __attribute__((ns_returns_retained))
+# else
+# define NS_RETURNS_RETAINED
+# endif
+#endif
+
+#ifndef NS_RETURNS_NOT_RETAINED
+# if __has_feature(attribute_ns_returns_not_retained)
+# define NS_RETURNS_NOT_RETAINED __attribute__((ns_returns_not_retained))
+# else
+# define NS_RETURNS_NOT_RETAINED
+# endif
+#endif
+
+#ifndef NS_CONSUMED
+# if __has_feature(attribute_ns_consumed)
+# define NS_CONSUMED __attribute__((ns_consumed))
+# else
+# define NS_CONSUMED
+# endif
+#endif
+
+
+#ifndef NS_CONSUMES_SELF
+# if __has_feature(attribute_ns_consumes_self)
+# define NS_CONSUMES_SELF __attribute__((ns_consumes_self))
+# else
+# define NS_CONSUMES_SELF
+# endif
+#endif
+
+#if defined(__clang__) && defined(__OBJC__)
+static inline void gs_consumed(id NS_CONSUMED o) GS_UNUSED_FUNC;
+static inline void gs_consumed(id NS_CONSUMED GS_UNUSED_ARG o) { return; }
+#define GS_CONSUMED(O) gs_consumed(O);
+#else
+#define GS_CONSUMED(O)
+#endif
+
+/* Include the appropriate header for ObjC2 blocks support if it is in use.
+ *
+ * FIXME: "OBJC2RUNTIME" is set to "1" if the runtime supports the ObjC2
+ * runtime API, which is unrelated to whether the compiler has blocks
+ * support or not.
+ */
+#if __has_feature(blocks)
+# if OBJC2RUNTIME
+# if defined(__APPLE__)
+# include <Block.h>
+# else
+# include <objc/blocks_runtime.h>
+# endif
+# else
+# include <ObjectiveC2/blocks_runtime.h>
+# endif
+#endif
+
+/* Attribute definition for root classes, annotates the interface declaration
+ * of the class.
+ */
+#ifndef GS_ROOT_CLASS
+# if GS_HAVE_OBJC_ROOT_CLASS_ATTR || __has_feature(attribute_objc_root_class)
+# define GS_ROOT_CLASS __attribute__((objc_root_class))
+# else
+# define GS_ROOT_CLASS
+# endif
+#endif
+
+
+
+#if defined(GNUSTEP_WITH_DLL)
+
+#if BUILD_libgnustep_base_DLL
+#
+# if defined(__MINGW__)
+ /* On Mingw, the compiler will export all symbols automatically, so
+ * __declspec(dllexport) is not needed.
+ */
+# define GS_EXPORT extern
+# define GS_DECLARE
+# else
+# define GS_EXPORT __declspec(dllexport)
+# define GS_DECLARE __declspec(dllexport)
+# endif
+#else
+# define GS_EXPORT extern __declspec(dllimport)
+# define GS_DECLARE __declspec(dllimport)
+#endif
+
+#else /* GNUSTEP_WITH[OUT]_DLL */
+
+# define GS_EXPORT extern
+# define GS_DECLARE
+
+#endif
+
+
+/* Attribute macros compatible with Apple.
+ */
+
+#ifndef NS_FORMAT_ARGUMENT
+#if defined(__clang__) || GS_GCC_MINREQ(4,2)
+# define NS_FORMAT_ARGUMENT(A) __attribute__((format_arg(A)))
+#else
+# define NS_FORMAT_ARGUMENT(F,A)
+#endif
+#endif
+
+// FIXME ... what version of gcc?
+#ifndef NS_FORMAT_FUNCTION
+#if __clang__
+# define NS_FORMAT_FUNCTION(F,A) __attribute__((format(__NSString__, F, A)))
+#else
+# define NS_FORMAT_FUNCTION(F,A)
+#endif
+#endif
+
+#ifndef NS_REQUIRES_NIL_TERMINATION
+#define NS_REQUIRES_NIL_TERMINATION __attribute__((sentinel))
+#endif
+
+// FIXME ... what exact version of clang and gcc?
+#ifndef UNAVAILABLE_ATTRIBUTE
+#if defined(__clang__) || GS_GCC_MINREQ(4,0)
+# define UNAVAILABLE_ATTRIBUTE __attribute__((unavailable))
+#else
+# define UNAVAILABLE_ATTRIBUTE
+#endif
+#endif
+
+/* Check if compiler supports @optional in protocols
+ */
+#if defined(__clang__) || GS_GCC_MINREQ(4,6)
+# define GS_PROTOCOLS_HAVE_OPTIONAL 1
+#else
+# define GS_PROTOCOLS_HAVE_OPTIONAL 0
+#endif
+
+/* Check if compiler supports declared properties
+ */
+#if defined(__clang__) || GS_GCC_MINREQ(4,6)
+# define GS_HAS_DECLARED_PROPERTIES 1
+#else
+# define GS_HAS_DECLARED_PROPERTIES 0
+#endif
+
+#endif /* __GNUSTEP_GSVERSIONMACROS_H_INCLUDED_ */
diff --git a/gcc/testsuite/objc-obj-c++-shared/GNUStep/GNUstepBase/NSArray+GNUstepBase.h b/gcc/testsuite/objc-obj-c++-shared/GNUStep/GNUstepBase/NSArray+GNUstepBase.h
new file mode 100644
index 0000000..c9b595a
--- /dev/null
+++ b/gcc/testsuite/objc-obj-c++-shared/GNUStep/GNUstepBase/NSArray+GNUstepBase.h
@@ -0,0 +1,78 @@
+/** Declaration of extension methods for base additions
+
+ Copyright (C) 2003-2010 Free Software Foundation, Inc.
+
+ Written by: Richard Frith-Macdonald <rfm@gnu.org>
+ and: Adam Fedor <fedor@gnu.org>
+
+ This file is part of the GNUstep Base Library.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free
+ Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02111 USA.
+
+*/
+
+#ifndef INCLUDED_NSArray_GNUstepBase_h
+#define INCLUDED_NSArray_GNUstepBase_h
+
+#import "../GNUstepBase/GSVersionMacros.h"
+#import "../Foundation/NSArray.h"
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+#if OS_API_VERSION(GS_API_NONE,GS_API_LATEST)
+
+@interface NSArray (GNUstepBase)
+
+/** <p>Method for working with sorted arrays - use a binary chop
+ * to determine the insertion location for an object. If equal objects
+ * already exist in the array, they will be located immediately before
+ * the insertion position.
+ * </p>
+ * <p>The comparator function takes two items as arguments, the first is the
+ * item to be added, the second is the item already in the array.
+ * The function should return NSOrderedAscending if the item to be
+ * added is 'less than' the item in the array, NSOrderedDescending
+ * if it is greater, and NSOrderedSame if it is equal.
+ * </p>
+ */
+- (NSUInteger) insertionPosition: (id)item
+ usingFunction: (NSComparisonResult (*)(id, id, void *))sorter
+ context: (void *)context;
+
+/* <p>Method for working with sorted arrays - use a binary chop
+ * to determine the insertion location for an object. If equal objects
+ * already exist in the array, they will be located immediately before
+ * the insertion position.
+ * </p>
+ * <p>The selector identifies a method returning NSOrderedAscending if
+ * the receiver is 'less than' the argument, and NSOrderedDescending if
+ * it is greate.
+ * </p>
+ */
+- (NSUInteger) insertionPosition: (id)item
+ usingSelector: (SEL)comp;
+@end
+
+#endif /* OS_API_VERSION */
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif /* INCLUDED_NSArray_GNUstepBase_h */
+
diff --git a/gcc/testsuite/objc-obj-c++-shared/GNUStep/GNUstepBase/NSMutableString+GNUstepBase.h b/gcc/testsuite/objc-obj-c++-shared/GNUStep/GNUstepBase/NSMutableString+GNUstepBase.h
new file mode 100644
index 0000000..b3f7190
--- /dev/null
+++ b/gcc/testsuite/objc-obj-c++-shared/GNUStep/GNUstepBase/NSMutableString+GNUstepBase.h
@@ -0,0 +1,57 @@
+/** Declaration of extension methods for base additions
+
+ Copyright (C) 2003-2010 Free Software Foundation, Inc.
+
+ Written by: Richard Frith-Macdonald <rfm@gnu.org>
+ and: Adam Fedor <fedor@gnu.org>
+
+ This file is part of the GNUstep Base Library.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free
+ Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02111 USA.
+
+*/
+
+#ifndef INCLUDED_NSMutableString_GNUstepBase_h
+#define INCLUDED_NSMutableString_GNUstepBase_h
+
+#import "GSVersionMacros.h"
+#import "../Foundation/NSString.h"
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+#if OS_API_VERSION(GS_API_NONE,GS_API_LATEST)
+
+@interface NSMutableString (GNUstepBase)
+- (void) deleteSuffix: (NSString*)suffix;
+- (void) deletePrefix: (NSString*)prefix;
+- (NSString*) immutableProxy;
+- (void) replaceString: (NSString*)replace
+ withString: (NSString*)by;
+- (void) trimLeadSpaces;
+- (void) trimTailSpaces;
+- (void) trimSpaces;
+@end
+
+#endif /* OS_API_VERSION */
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif /* INCLUDED_NSMutableString_GNUstepBase_h */
+
diff --git a/gcc/testsuite/objc-obj-c++-shared/GNUStep/GNUstepBase/NSNumber+GNUstepBase.h b/gcc/testsuite/objc-obj-c++-shared/GNUStep/GNUstepBase/NSNumber+GNUstepBase.h
new file mode 100644
index 0000000..1bed065
--- /dev/null
+++ b/gcc/testsuite/objc-obj-c++-shared/GNUStep/GNUstepBase/NSNumber+GNUstepBase.h
@@ -0,0 +1,56 @@
+/** Declaration of extension methods for base additions
+
+ Copyright (C) 2003-2010 Free Software Foundation, Inc.
+
+ Written by: Richard Frith-Macdonald <rfm@gnu.org>
+ and: Adam Fedor <fedor@gnu.org>
+
+ This file is part of the GNUstep Base Library.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free
+ Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02111 USA.
+
+*/
+
+#ifndef INCLUDED_NSNumber_GNUstepBase_h
+#define INCLUDED_NSNumber_GNUstepBase_h
+
+#import "GSVersionMacros.h"
+#import "../Foundation/NSValue.h"
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+#if OS_API_VERSION(GS_API_NONE,GS_API_LATEST)
+
+@interface NSNumber(GNUstepBase)
+/**
+ * Parses string as a <code>double</code>, <code>int</code>, or <code>unsigned
+ * int</code> depending on what characters are present. Uses
+ * <code>atof</code> and <code>atoi</code> which don't report errors, so be
+ * careful if the string might contain an invalid value.
+ */
++ (NSValue*) valueFromString: (NSString *)string;
+@end
+
+#endif /* OS_API_VERSION */
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif /* INCLUDED_NSNumber_GNUstepBase_h */
+
diff --git a/gcc/testsuite/objc-obj-c++-shared/GNUStep/GNUstepBase/NSObject+GNUstepBase.h b/gcc/testsuite/objc-obj-c++-shared/GNUStep/GNUstepBase/NSObject+GNUstepBase.h
new file mode 100644
index 0000000..d3b2574
--- /dev/null
+++ b/gcc/testsuite/objc-obj-c++-shared/GNUStep/GNUstepBase/NSObject+GNUstepBase.h
@@ -0,0 +1,242 @@
+/** Declaration of extension methods for base additions
+
+ Copyright (C) 2003-2010 Free Software Foundation, Inc.
+
+ Written by: Richard Frith-Macdonald <rfm@gnu.org>
+ and: Adam Fedor <fedor@gnu.org>
+
+ This file is part of the GNUstep Base Library.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free
+ Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02111 USA.
+
+*/
+
+#ifndef INCLUDED_NSObject_GNUstepBase_h
+#define INCLUDED_NSObject_GNUstepBase_h
+
+#import "GSVersionMacros.h"
+#import "../Foundation/NSObject.h"
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+#if OS_API_VERSION(GS_API_NONE,GS_API_LATEST)
+
+@class NSHashTable;
+
+@interface NSObject (GNUstepBase)
+
+/**
+ WARNING: The -compare: method for NSObject is deprecated
+ due to subclasses declaring the same selector with
+ conflicting signatures.
+ Comparision of arbitrary objects is not just meaningless
+ but also dangerous as most concrete implementations
+ expect comparable objects as arguments often accessing
+ instance variables directly.
+ This method will be removed in a future release.
+*/
+- (NSComparisonResult) compare: (id)anObject;
+
+/** For backward compatibility only ... use class_isMetaClass() on the
+ * class of the receiver instead.
+ */
+- (BOOL) isInstance;
+
+/** DEPRECATED ... do not use.
+ * Transmutes the receiver into an immutable version of the same object
+ * and returns the result.<br />
+ * If the receiver is not a mutable object or cannot be simply transmuted,
+ * then this method either returns the receiver unchanged or,
+ * if the force flag is set to YES, returns an autoreleased copy of the
+ * receiver.<br />
+ * Mutable classes should override this default implementation.<br />
+ * This method is used in methods which are declared to return immutable
+ * objects (eg. an NSArray), but which create and build mutable ones
+ * internally.
+ */
+- (id) makeImmutableCopyOnFail: (BOOL)force;
+
+/** Transmutes the receiver into an immutable version of the same object.
+ * Returns YES if the receiver has become immutable, NO otherwise.<br />
+ * The default implementation returns NO.<br />
+ * Mutable classes which have an immutable counterpart they can efficiently
+ * change into, should override to transmute themselves and return YES.<br />
+ * Immutable classes should override this to simply return YES with no
+ * further action.<br />
+ * This method is used in methods which are declared to return immutable
+ * objects (eg. an NSArray), but which create and build mutable ones
+ * internally.
+ */
+- (BOOL) makeImmutable;
+
+/**
+ * Message sent when an implementation wants to explicitly exclude a method
+ * (but cannot due to compiler constraint), and wants to make sure it is not
+ * called by mistake. Default implementation raises an exception at runtime.
+ */
+- (id) notImplemented: (SEL)aSel GS_NORETURN_METHOD;
+
+/**
+ * Message sent when an implementation wants to explicitly require a subclass
+ * to implement a method (but cannot at compile time since there is no
+ * <code>abstract</code> keyword in Objective-C). Default implementation
+ * raises an exception at runtime to alert developer that he/she forgot to
+ * override a method.
+ */
+- (id) subclassResponsibility: (SEL)aSel GS_NORETURN_METHOD;
+
+/**
+ * Message sent when an implementation wants to explicitly exclude a method
+ * (but cannot due to compiler constraint) and forbid that subclasses
+ * implement it. Default implementation raises an exception at runtime. If a
+ * subclass <em>does</em> implement this method, however, the superclass's
+ * implementation will not be called, so this is not a perfect mechanism.
+ */
+- (id) shouldNotImplement: (SEL)aSel GS_NORETURN_METHOD;
+
+@end
+
+/** This is an informal protocol ... classes may implement the method to
+ * report how much memory is used by the instance and any objects it acts
+ * as a container for.
+ */
+@interface NSObject(MemoryFootprint)
+/* This method returns the memory usage of the receiver, excluding any
+ * objects already present in the exclude table.<br />
+ * The argument is a hash table configured to hold non-retained pointer
+ * objects and is used to inform the receiver that its size should not
+ * be counted again if it's already in the table.<br />
+ * The NSObject implementation returns zero if the receiver is in the
+ * table, but otherwise adds itself to the table and returns its memory
+ * footprint (the sum of all of its instance variables, but not any
+ * memory pointed to by those variables).<br />
+ * Subclasses should override this method by calling the superclass
+ * implementation, and either return the result (if it was zero) or
+ * return that value plus the sizes of any memory owned by the receiver
+ * (eg found by calling the same method on objects pointed to by the
+ * receiver's instance variables).
+ */
+- (NSUInteger) sizeInBytesExcluding: (NSHashTable*)exclude;
+@end
+
+/** This is an informal protocol ... classes may implement the method and
+ * register themselves to have it called on process exit.
+ */
+@interface NSObject(GSAtExit)
+/** This method is called on exit for any class which implements it and which
+ * has called +registerAtExit to register it to be called.<br />
+ * The order in which methods for different classes is called is the reverse
+ * of the order in which the classes were registered, but it's best to assume
+ * the method can not depend on any other class being in a usable state
+ * at the point when the method is called (rather like +load).<br />
+ * Typical use would be to release memory occupied by class data structures
+ * so that memory usage analysis software will not think the memory has
+ * been leaked.
+ */
++ (void) atExit;
+@end
+
+/** Category for methods handling leaked memory cleanup on exit of process
+ * (for use when debugging memory leaks).<br />
+ * You enable this by calling the +setShouldCleanUp: method (done implicitly
+ * by gnustep-base if the GNUSTEP_SHOULD_CLEAN_UP environment variable is
+ * set to YES).<br />
+ * Your class then has two options for performing cleanup when the process
+ * ends:
+ * <p>1. Use the +leak: method to register objects which are simply to be
+ * retained until the process ends, and then either ignored or released
+ * depending on the cleanup setting in force. This mechanism is simple
+ * and should be sufficient for many classes.
+ * </p>
+ * <p>2. Implement a +atExit method to be run when the process ends and,
+ * within your +initialize implementation, call +shouldCleanUp to determine
+ * whether cleanup should be done, and if it returns YES then call
+ * +registerAtExit to have your +atExit method called when the process
+ * terminates.
+ * </p>
+ * <p>The order in which 'leaked' objects are released and +atExit methods
+ * are called on process exist is the reverse of the order in which they
+ * werse set up suing this API.
+ * </p>
+ */
+@interface NSObject(GSCleanup)
+
+
+/** This method simply retains its argument so that it will never be
+ * deallocated during normal operation, but keeps track of it so that
+ * it is released during process exit if cleanup is enabled.<br />
+ * Returns its argument.
+ */
++ (id) NS_RETURNS_RETAINED leak: (id)anObject;
+
+/** This method retains the object at *anAddress so that it will never be
+ * deallocated during normal operation, but keeps track of the address
+ * so that the object is released and the address is zeroed during process
+ * exit if cleanup is enabled.<br />
+ * Returns the object at *anAddress.
+ */
++ (id) NS_RETURNS_RETAINED leakAt: (id*)anAddress;
+
+/** Sets the receiver to have its +atExit method called at the point when
+ * the process terminates.<br />
+ * Returns YES on success and NO on failure (if the class does not implement
+ * the method or if it is already registered to call it).<br />
+ * Implemented as a call to +registerAtExit: with the selector for the +atExit
+ * method as its argument.
+ */
++ (BOOL) registerAtExit;
+
+/** Sets the receiver to have the specified method called at the point when
+ * the process terminates.<br />
+ * Returns YES on success and NO on failure (if the class does not implement
+ * the method ir if it is already registered to call it).
+ */
++ (BOOL) registerAtExit: (SEL)aSelector;
+
+/** Specifies the default cleanup behavior on process exit ... the value
+ * returned by the NSObject implementation of the +shouldClanUp method.<br />
+ * Calling this method with a YES argument implicitly calls the +enableAtExit
+ * method as well.<br />
+ * The GNUstep Base library calls this method with the value obtained from
+ * the GNUSTEP_SHOULD_CLEAN_UP environment variable when NSObject is
+ * initialised.
+ */
++ (void) setShouldCleanUp: (BOOL)aFlag;
+
+/** Returns a flag indicating whether the receiver should clean up
+ * its data structures etc at process exit.<br />
+ * The NSObject implementation returns the value set by the +setShouldCleanUp:
+ * method but subclasses may override this.
+ */
++ (BOOL) shouldCleanUp;
+
+@end
+
+/* Macro to take an autoreleased object and either make it immutable or
+ * create an autoreleased copy of the original.
+ */
+#define GS_IMMUTABLE(O) ([O makeImmutable] == YES ? O : AUTORELEASE([O copy]))
+
+#endif /* OS_API_VERSION */
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif /* INCLUDED_NSObject_GNUstepBase_h */
+
diff --git a/gcc/testsuite/objc-obj-c++-shared/GNUStep/GNUstepBase/NSString+GNUstepBase.h b/gcc/testsuite/objc-obj-c++-shared/GNUStep/GNUstepBase/NSString+GNUstepBase.h
new file mode 100644
index 0000000..48633cd
--- /dev/null
+++ b/gcc/testsuite/objc-obj-c++-shared/GNUStep/GNUstepBase/NSString+GNUstepBase.h
@@ -0,0 +1,105 @@
+/** Declaration of extension methods for base additions
+
+ Copyright (C) 2003-2010 Free Software Foundation, Inc.
+
+ Written by: Richard Frith-Macdonald <rfm@gnu.org>
+ and: Adam Fedor <fedor@gnu.org>
+
+ This file is part of the GNUstep Base Library.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free
+ Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02111 USA.
+
+*/
+
+#ifndef INCLUDED_NSString_GNUstepBase_h
+#define INCLUDED_NSString_GNUstepBase_h
+
+#import "GSVersionMacros.h"
+#import "../Foundation/NSString.h"
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+#if OS_API_VERSION(GS_API_NONE,GS_API_LATEST)
+
+/**
+ * Provides some additional (non-standard) utility methods.
+ */
+@interface NSString (GNUstepBase)
+
+/**
+ * Alternate way to invoke <code>stringWithFormat</code> if you have or wish
+ * to build an explicit <code>va_list</code> structure.
+ */
++ (id) stringWithFormat: (NSString*)format
+ arguments: (va_list)argList NS_FORMAT_FUNCTION(1,0);
+
+/**
+ * Returns a string formed by removing the prefix string from the
+ * receiver. Raises an exception if the prefix is not present.
+ */
+- (NSString*) stringByDeletingPrefix: (NSString*)prefix;
+
+/**
+ * Returns a string formed by removing the suffix string from the
+ * receiver. Raises an exception if the suffix is not present.
+ */
+- (NSString*) stringByDeletingSuffix: (NSString*)suffix;
+
+/**
+ * Returns a string formed by removing leading white space from the
+ * receiver.
+ */
+- (NSString*) stringByTrimmingLeadSpaces;
+
+/**
+ * Returns a string formed by removing trailing white space from the
+ * receiver.
+ */
+- (NSString*) stringByTrimmingTailSpaces;
+
+/**
+ * Returns a string formed by removing both leading and trailing
+ * white space from the receiver.
+ */
+- (NSString*) stringByTrimmingSpaces;
+
+/**
+ * Returns a string in which any (and all) occurrences of
+ * replace in the receiver have been replaced with by.
+ * Returns the receiver if replace
+ * does not occur within the receiver. NB. an empty string is
+ * not considered to exist within the receiver.
+ */
+- (NSString*) stringByReplacingString: (NSString*)replace
+ withString: (NSString*)by;
+
+/**
+ * An obsolete name for -substringWithRange: ... deprecated.
+ */
+- (NSString*) substringFromRange: (NSRange)aRange;
+
+@end
+
+#endif /* OS_API_VERSION */
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif /* INCLUDED_NSString_GNUstepBase_h */
+
diff --git a/gcc/testsuite/objc.dg/call-super-2.m b/gcc/testsuite/objc.dg/call-super-2.m
index af01d44..0a3765f 100644
--- a/gcc/testsuite/objc.dg/call-super-2.m
+++ b/gcc/testsuite/objc.dg/call-super-2.m
@@ -141,6 +141,4 @@
}
@end
-/* { dg-warning "Messages without a matching method signature" "" { target *-*-* } 0 } */
-/* { dg-warning "will be assumed to return .id. and accept" "" { target *-*-* } 0 } */
-/* { dg-warning ".\.\.\.. as arguments" "" { target *-*-* } 0 } */
+/* { dg-warning "messages without a matching method signature will be assumed to return .id. and accept .\.\.\.. as arguments" "" { target *-*-* } 0 } */
diff --git a/gcc/testsuite/objc.dg/class-protocol-1.m b/gcc/testsuite/objc.dg/class-protocol-1.m
index 086201e..59c8f82 100644
--- a/gcc/testsuite/objc.dg/class-protocol-1.m
+++ b/gcc/testsuite/objc.dg/class-protocol-1.m
@@ -436,6 +436,4 @@ int main ()
return(0);
}
-/* { dg-warning "Messages without a matching method signature" "" { target *-*-* } 0 } */
-/* { dg-warning "will be assumed to return .id. and accept" "" { target *-*-* } 0 } */
-/* { dg-warning ".\.\.\.. as arguments" "" { target *-*-* } 0 } */
+/* { dg-warning "messages without a matching method signature will be assumed to return .id. and accept .\.\.\.. as arguments" "" { target *-*-* } 0 } */
diff --git a/gcc/testsuite/objc.dg/desig-init-1.m b/gcc/testsuite/objc.dg/desig-init-1.m
index 24fe709..e5d5a59 100644
--- a/gcc/testsuite/objc.dg/desig-init-1.m
+++ b/gcc/testsuite/objc.dg/desig-init-1.m
@@ -44,8 +44,4 @@ int main(void) {
return 0;
}
-/* { dg-warning "Messages without a matching method signature" "" { target *-*-* } 0 } */
-/* { dg-warning "will be assumed to return .id. and accept" "" { target *-*-* } 0 } */
-/* { dg-warning ".\.\.\.. as arguments" "" { target *-*-* } 0 } */
-
-
+/* { dg-warning "messages without a matching method signature will be assumed to return .id. and accept .\.\.\.. as arguments" "" { target *-*-* } 0 } */
diff --git a/gcc/testsuite/objc.dg/encode-7-next-64bit.m b/gcc/testsuite/objc.dg/encode-7-next-64bit.m
index 4a418fc..5686cb4 100644
--- a/gcc/testsuite/objc.dg/encode-7-next-64bit.m
+++ b/gcc/testsuite/objc.dg/encode-7-next-64bit.m
@@ -9,10 +9,11 @@
#include <stdbool.h>
#include <string.h>
#include <stdlib.h>
-#include <Foundation/NSObject.h>
+#include <stdio.h>
+#include "../objc-obj-c++-shared/F-NSObject.h"
+#include "../objc-obj-c++-shared/CF-CFString.h"
#include "../objc-obj-c++-shared/runtime.h"
-extern int printf(char *,...);
void CHECK_IF(const char *s1, const char *s2)
{
if (strcmp(s1,s2) != 0) {
diff --git a/gcc/testsuite/objc.dg/exceptions-3.m b/gcc/testsuite/objc.dg/exceptions-3.m
index 5548a39..69a6494 100644
--- a/gcc/testsuite/objc.dg/exceptions-3.m
+++ b/gcc/testsuite/objc.dg/exceptions-3.m
@@ -27,19 +27,19 @@ int test (id object)
int dummy = 0;
@try { @throw object; }
- @catch (int x) /* { dg-error "@catch parameter is not a known Objective-C class type" } */
+ @catch (int x) /* { dg-error "'@catch' parameter is not a known Objective-C class type" } */
{
dummy++;
}
@try { @throw object; }
- @catch (intTypedef x) /* { dg-error "@catch parameter is not a known Objective-C class type" } */
+ @catch (intTypedef x) /* { dg-error "'@catch' parameter is not a known Objective-C class type" } */
{
dummy++;
}
@try { @throw object; }
- @catch (int *x) /* { dg-error "@catch parameter is not a known Objective-C class type" } */
+ @catch (int *x) /* { dg-error "'@catch' parameter is not a known Objective-C class type" } */
{
dummy++;
}
@@ -51,7 +51,7 @@ int test (id object)
}
@try { @throw object; }
- @catch (id <MyProtocol> x) /* { dg-error "@catch parameter cannot be protocol-qualified" } */
+ @catch (id <MyProtocol> x) /* { dg-error "'@catch' parameter cannot be protocol-qualified" } */
{
dummy++;
}
@@ -63,13 +63,13 @@ int test (id object)
}
@try { @throw object; }
- @catch (MyObject <MyProtocol> *x) /* { dg-error "@catch parameter cannot be protocol-qualified" } */
+ @catch (MyObject <MyProtocol> *x) /* { dg-error "'@catch' parameter cannot be protocol-qualified" } */
{
dummy++;
}
@try { @throw object; }
- @catch (MyObject x) /* { dg-error "@catch parameter is not a known Objective-C class type" } */
+ @catch (MyObject x) /* { dg-error "'@catch' parameter is not a known Objective-C class type" } */
{ /* { dg-error "conversion to non-scalar type requested" "" { target *-*-* } .-1 } */
dummy++;
}
@@ -87,7 +87,7 @@ int test (id object)
}
@try { @throw object; }
- @catch (MyObjectTypedef <MyProtocol> *x) /* { dg-error "@catch parameter cannot be protocol-qualified" } */
+ @catch (MyObjectTypedef <MyProtocol> *x) /* { dg-error "'@catch' parameter cannot be protocol-qualified" } */
{
dummy++;
}
@@ -99,7 +99,7 @@ int test (id object)
}
@try { @throw object; }
- @catch (Class x) /* { dg-error "@catch parameter is not a known Objective-C class type" } */
+ @catch (Class x) /* { dg-error "'@catch' parameter is not a known Objective-C class type" } */
{
dummy++;
}
diff --git a/gcc/testsuite/objc.dg/exceptions-4.m b/gcc/testsuite/objc.dg/exceptions-4.m
index 5db60e3..bbdb741 100644
--- a/gcc/testsuite/objc.dg/exceptions-4.m
+++ b/gcc/testsuite/objc.dg/exceptions-4.m
@@ -44,7 +44,7 @@ int test (id object)
dummy++;
}
@catch (id <MyProtocol x) /* { dg-error "expected ... before .x." } */
- { /* { dg-error "@catch parameter cannot be protocol-qualified" "" { target *-*-* } .-1 } */
+ { /* { dg-error "'@catch' parameter cannot be protocol-qualified" "" { target *-*-* } .-1 } */
dummy++;
}
@catch MyObject *x /* { dg-error "expected ... before .MyObject." } */
diff --git a/gcc/testsuite/objc.dg/exceptions-5.m b/gcc/testsuite/objc.dg/exceptions-5.m
index 402aa11..55ef0f3 100644
--- a/gcc/testsuite/objc.dg/exceptions-5.m
+++ b/gcc/testsuite/objc.dg/exceptions-5.m
@@ -27,19 +27,19 @@ int test (id object)
int dummy = 0;
@try { @throw object; }
- @catch (int) /* { dg-error "@catch parameter is not a known Objective-C class type" } */
+ @catch (int) /* { dg-error "'@catch' parameter is not a known Objective-C class type" } */
{
dummy++;
}
@try { @throw object; }
- @catch (intTypedef) /* { dg-error "@catch parameter is not a known Objective-C class type" } */
+ @catch (intTypedef) /* { dg-error "'@catch' parameter is not a known Objective-C class type" } */
{
dummy++;
}
@try { @throw object; }
- @catch (int *) /* { dg-error "@catch parameter is not a known Objective-C class type" } */
+ @catch (int *) /* { dg-error "'@catch' parameter is not a known Objective-C class type" } */
{
dummy++;
}
@@ -51,7 +51,7 @@ int test (id object)
}
@try { @throw object; }
- @catch (id <MyProtocol>) /* { dg-error "@catch parameter cannot be protocol-qualified" } */
+ @catch (id <MyProtocol>) /* { dg-error "'@catch' parameter cannot be protocol-qualified" } */
{
dummy++;
}
@@ -63,13 +63,13 @@ int test (id object)
}
@try { @throw object; }
- @catch (MyObject <MyProtocol> *) /* { dg-error "@catch parameter cannot be protocol-qualified" } */
+ @catch (MyObject <MyProtocol> *) /* { dg-error "'@catch' parameter cannot be protocol-qualified" } */
{
dummy++;
}
@try { @throw object; }
- @catch (MyObject) /* { dg-error "@catch parameter is not a known Objective-C class type" } */
+ @catch (MyObject) /* { dg-error "'@catch' parameter is not a known Objective-C class type" } */
{ /* { dg-error "conversion to non-scalar type requested" "" { target *-*-* } .-1 } */
dummy++;
}
@@ -87,7 +87,7 @@ int test (id object)
}
@try { @throw object; }
- @catch (MyObjectTypedef <MyProtocol> *) /* { dg-error "@catch parameter cannot be protocol-qualified" } */
+ @catch (MyObjectTypedef <MyProtocol> *) /* { dg-error "'@catch' parameter cannot be protocol-qualified" } */
{
dummy++;
}
@@ -99,7 +99,7 @@ int test (id object)
}
@try { @throw object; }
- @catch (Class) /* { dg-error "@catch parameter is not a known Objective-C class type" } */
+ @catch (Class) /* { dg-error "'@catch' parameter is not a known Objective-C class type" } */
{
dummy++;
}
diff --git a/gcc/testsuite/objc.dg/exceptions-6.m b/gcc/testsuite/objc.dg/exceptions-6.m
index 74be98d..ae44a88 100644
--- a/gcc/testsuite/objc.dg/exceptions-6.m
+++ b/gcc/testsuite/objc.dg/exceptions-6.m
@@ -9,7 +9,7 @@
void test (id object)
{
@throw object; /* Ok */
- @throw; /* { dg-error ".@throw. .rethrow. used outside of a @catch block" } */
+ @throw; /* { dg-error ".@throw. .rethrow. used outside of a '@catch' block" } */
@throw (object); /* Ok. */
@throw (id)0 /* { dg-error "expected" } */
}
diff --git a/gcc/testsuite/objc.dg/headers.m b/gcc/testsuite/objc.dg/headers.m
index 355c2cf..e628199 100644
--- a/gcc/testsuite/objc.dg/headers.m
+++ b/gcc/testsuite/objc.dg/headers.m
@@ -2,6 +2,7 @@
// test in libstdc++-v3). Author: Loren J. Rittle <ljrittle@acm.org>.
// { dg-options "-Wall -Wpointer-arith -Wcast-qual -Wstrict-prototypes -Wshadow" }
// { dg-do compile }
+/* { dg-xfail-if "PR90709" { *-*-darwin1[4-9]* } { "-fnext-runtime" } { "" } } */
#ifdef __NEXT_RUNTIME__
#include <Foundation/NSString.h>
diff --git a/gcc/testsuite/objc.dg/image-info.m b/gcc/testsuite/objc.dg/image-info.m
index 0932913..b2effe5 100644
--- a/gcc/testsuite/objc.dg/image-info.m
+++ b/gcc/testsuite/objc.dg/image-info.m
@@ -7,7 +7,7 @@
/* { dg-skip-if "NeXT-only" { *-*-* } { "-fgnu-runtime" } { "" } } */
/* { dg-options "-freplace-objc-classes" } */
-#include <Foundation/NSObject.h>
+#include "../objc-obj-c++-shared/F-NSObject.h"
extern void abort(void);
#define CHECK_IF(expr) if(!(expr)) abort();
diff --git a/gcc/testsuite/objc.dg/instancetype-0.m b/gcc/testsuite/objc.dg/instancetype-0.m
new file mode 100644
index 0000000..32cafdf
--- /dev/null
+++ b/gcc/testsuite/objc.dg/instancetype-0.m
@@ -0,0 +1,30 @@
+/* Contributed by Iain Sandoe <iain@sandoe.co.uk>, May 2019. */
+/* { dg-do compile } */
+
+/* Basic check of parsing instancetype. */
+
+extern id class_createInstance (id, int);
+extern id class_getSuperclass (id);
+
+@interface MyObject
+{
+ Class isa;
+}
++ (instancetype)alloc;
+- (instancetype)init;
++ (instancetype)initialize;
++ (instancetype)factoryMethodA;
++ (id)factoryMethodB;
++ (Class) class;
++ (Class) superclass;
+@end
+
+@implementation MyObject
++ (instancetype)alloc { return class_createInstance (self, 0); }
+- (instancetype)init { return self; }
++ (instancetype)initialize { return self; }
++ (instancetype)factoryMethodA { return [[[self class] alloc] init]; }
++ (id)factoryMethodB { return [[[self class] alloc] init]; }
++ (Class) class { return self; }
++ (Class) superclass { return class_getSuperclass (self); }
+@end
diff --git a/gcc/testsuite/objc.dg/isa-field-1.m b/gcc/testsuite/objc.dg/isa-field-1.m
index 4501d01..a786ec3 100644
--- a/gcc/testsuite/objc.dg/isa-field-1.m
+++ b/gcc/testsuite/objc.dg/isa-field-1.m
@@ -1,5 +1,7 @@
/* Ensure there are no bizarre difficulties with accessing the 'isa' field of objects. */
/* { dg-do compile } */
+/* The use of isa is deprecated, but we still want to test that it works. */
+/* { dg-additional-options "-Wno-deprecated-declarations" } */
#include "../objc-obj-c++-shared/TestsuiteObject.h"
#include "../objc-obj-c++-shared/runtime.h"
diff --git a/gcc/testsuite/objc.dg/method-19.m b/gcc/testsuite/objc.dg/method-19.m
index 8f60511..83280fb 100644
--- a/gcc/testsuite/objc.dg/method-19.m
+++ b/gcc/testsuite/objc.dg/method-19.m
@@ -8,11 +8,9 @@
@class NotKnown;
void foo(NotKnown *n) {
- [NotKnown new]; /* { dg-warning ".interface of class .NotKnown. not found" } */
- [n nonexistent_method]; /* { dg-warning ".interface of class .NotKnown. not found" } */
+ [NotKnown new]; /* { dg-warning "'.interface' of class .NotKnown. not found" } */
+ [n nonexistent_method]; /* { dg-warning "'.interface' of class .NotKnown. not found" } */
/* { dg-warning "no .\\-nonexistent_method. method found" "" { target *-*-* } .-1 } */
}
-/* { dg-warning "Messages without a matching method signature" "" { target *-*-* } 0 } */
-/* { dg-warning "will be assumed to return .id. and accept" "" { target *-*-* } 0 } */
-/* { dg-warning ".\.\.\.. as arguments" "" { target *-*-* } 0 } */
+/* { dg-warning "messages without a matching method signature will be assumed to return .id. and accept '\.\.\.' as arguments" "" { target *-*-* } 0 } */
diff --git a/gcc/testsuite/objc.dg/method-2.m b/gcc/testsuite/objc.dg/method-2.m
index b6aa32d..cae2d7f 100644
--- a/gcc/testsuite/objc.dg/method-2.m
+++ b/gcc/testsuite/objc.dg/method-2.m
@@ -23,9 +23,7 @@
[MyIntermediate rootInstanceMethod]; /* with the same name. */
[self instanceMethod]; /* { dg-warning ".MyDerived. may not respond to .\\+instanceMethod." } */
- /* { dg-warning "Messages without a matching method signature" "" { target *-*-* } .-1 } */
- /* { dg-warning "will be assumed to return .id. and accept" "" { target *-*-* } .-2 } */
- /* { dg-warning ".\.\.\.. as arguments" "" { target *-*-* } .-3 } */
+ /* { dg-warning "messages without a matching method signature will be assumed to return .id. and accept .\.\.\.. as arguments" "" { target *-*-* } 0 } */
[MyDerived instanceMethod]; /* { dg-warning ".MyDerived. may not respond to .\\+instanceMethod." } */
}
@end
diff --git a/gcc/testsuite/objc.dg/method-5.m b/gcc/testsuite/objc.dg/method-5.m
index 8940914..277a7e9 100644
--- a/gcc/testsuite/objc.dg/method-5.m
+++ b/gcc/testsuite/objc.dg/method-5.m
@@ -11,12 +11,10 @@ void foo(UnderSpecified *u, NotAClass *n) {
[n nonexistent_method]; /* { dg-warning "invalid receiver type" } */
/* { dg-warning "no .\\-nonexistent_method. method found" "" { target *-*-* } .-1 } */
[NotAClass nonexistent_method]; /* { dg-error ".NotAClass. is not an Objective\\-C class name or alias" } */
- [u nonexistent_method]; /* { dg-warning ".interface of class .UnderSpecified. not found" } */
+ [u nonexistent_method]; /* { dg-warning "'.interface' of class .UnderSpecified. not found" } */
/* { dg-warning "no .\\-nonexistent_method. method found" "" { target *-*-* } .-1 } */
- [UnderSpecified nonexistent_method]; /* { dg-warning ".interface of class .UnderSpecified. not found" } */
+ [UnderSpecified nonexistent_method]; /* { dg-warning "'.interface' of class .UnderSpecified. not found" } */
/* { dg-warning "no .\\+nonexistent_method. method found" "" { target *-*-* } .-1 } */
}
-/* { dg-warning "Messages without a matching method signature" "" { target *-*-* } 0 } */
-/* { dg-warning "will be assumed to return .id. and accept" "" { target *-*-* } 0 } */
-/* { dg-warning ".\.\.\.. as arguments" "" { target *-*-* } 0 } */
+/* { dg-warning "messages without a matching method signature will be assumed to return .id. and accept .\.\.\.. as arguments" "" { target *-*-* } 0 } */
diff --git a/gcc/testsuite/objc.dg/method-6.m b/gcc/testsuite/objc.dg/method-6.m
index 35676b1..7d3b11c 100644
--- a/gcc/testsuite/objc.dg/method-6.m
+++ b/gcc/testsuite/objc.dg/method-6.m
@@ -5,12 +5,12 @@
/* { dg-options "-Wstrict-selector-match" } */
#ifdef __NEXT_RUNTIME__
-#include <Foundation/NSObject.h>
-#define OBJECT NSObject
+# include "../objc-obj-c++-shared/F-NSObject.h"
+# define OBJECT NSObject
#else
-#include <objc/Object.h>
-#include <objc/Protocol.h>
-#define OBJECT Object
+# include <objc/Object.h>
+# include <objc/Protocol.h>
+# define OBJECT Object
#endif
@interface Base
@@ -31,9 +31,7 @@ void foo(void) {
/* { dg-message "also found .\\+\\(Protocol \\*\\)port." "" { target *-*-* } Derived_port_last } */
[receiver starboard]; /* { dg-warning "no .\\+starboard. method found" } */
- /* { dg-warning "Messages without a matching method signature" "" { target *-*-* } .-1 } */
- /* { dg-warning "will be assumed to return .id. and accept" "" { target *-*-* } .-2 } */
- /* { dg-warning ".\.\.\.. as arguments" "" { target *-*-* } .-3 } */
+ /* { dg-warning "messages without a matching method signature will be assumed to return .id. and accept .\.\.\.. as arguments" "" { target *-*-* } 0 } */
[Class port]; /* { dg-error ".Class. is not an Objective\\-C class name or alias" } */
}
diff --git a/gcc/testsuite/objc.dg/method-7.m b/gcc/testsuite/objc.dg/method-7.m
index a5957ae..314e8ab 100644
--- a/gcc/testsuite/objc.dg/method-7.m
+++ b/gcc/testsuite/objc.dg/method-7.m
@@ -18,9 +18,7 @@ id foo(void) {
TestsuiteObject *obj = [[TestsuiteObject alloc] init];
id obj2 = obj;
[obj setWindow:nil]; /* { dg-warning ".TestsuiteObject. may not respond to .\\-setWindow:." } */
- /* { dg-warning "Messages without a matching method signature" "" { target *-*-* } .-1 } */
- /* { dg-warning "will be assumed to return .id. and accept" "" { target *-*-* } .-2 } */
- /* { dg-warning ".\.\.\.. as arguments" "" { target *-*-* } .-3 } */
+ /* { dg-warning "messages without a matching method signature will be assumed to return .id. and accept .\.\.\.. as arguments" "" { target *-*-* } 0 } */
[obj2 setWindow:nil]; /* { dg-warning "multiple methods named .\\-setWindow:. found" } */
/* { dg-message "using .\\-\\(void\\)setWindow:\\(TestsuiteObject \\*\\)wdw." "" { target *-*-* } Class1_setWindow } */
/* { dg-message "also found .\\-\\(void\\)setWindow:\\(Class1 \\*\\)window." "" { target *-*-* } Class2_setWindow } */
diff --git a/gcc/testsuite/objc.dg/method-lookup-1.m b/gcc/testsuite/objc.dg/method-lookup-1.m
index 47499c3..e458471 100644
--- a/gcc/testsuite/objc.dg/method-lookup-1.m
+++ b/gcc/testsuite/objc.dg/method-lookup-1.m
@@ -39,7 +39,7 @@ void test (Class x, Class <MyProtocol> y, id w, id <MyProtocol> z, NotKnown *a,
/* If a class is specified by name, the @interface must be available
to check what it responds to. */
- [NotKnown classMethod]; /* { dg-warning ".interface of class .NotKnown. not found" } */
+ [NotKnown classMethod]; /* { dg-warning "'.interface' of class .NotKnown. not found" } */
/* "id w" means that "w" responds to anything, both class and
@@ -70,7 +70,7 @@ void test (Class x, Class <MyProtocol> y, id w, id <MyProtocol> z, NotKnown *a,
because they expect the compiler to do type-checking; the
@interface must be available to do this check, otherwise the
compiler does not know what "a" responds to. */
- [a instanceMethod]; /* { dg-warning ".interface of class .NotKnown. not found" } */
+ [a instanceMethod]; /* { dg-warning "'.interface' of class .NotKnown. not found" } */
/* But, if you cast it to "id", then you're disabling type-checking
and the warnings should go away. */
diff --git a/gcc/testsuite/objc.dg/no-extra-load.m b/gcc/testsuite/objc.dg/no-extra-load.m
index f5e1d74..35bd1da 100644
--- a/gcc/testsuite/objc.dg/no-extra-load.m
+++ b/gcc/testsuite/objc.dg/no-extra-load.m
@@ -1,7 +1,7 @@
/* { dg-do compile { target *-*-darwin* } } */
/* { dg-skip-if "" { *-*-* } { "-fgnu-runtime" } { "" } } */
-#include <Foundation/NSObject.h>
+#include "../objc-obj-c++-shared/F-NSObject.h"
main() { [NSObject new]; }
/* { dg-final { scan-assembler-not "L_objc_msgSend\\\$non_lazy_ptr" } } */
diff --git a/gcc/testsuite/objc.dg/objc-foreach-4.m b/gcc/testsuite/objc.dg/objc-foreach-4.m
index 4d902f5..c8dc074 100644
--- a/gcc/testsuite/objc.dg/objc-foreach-4.m
+++ b/gcc/testsuite/objc.dg/objc-foreach-4.m
@@ -5,9 +5,9 @@
/* { dg-skip-if "No NeXT fast enum. pre-Darwin9" { *-*-darwin[5-8]* } { "-fnext-runtime" } { "" } } */
/* { dg-additional-options "-framework Foundation" { target { *-*-darwin* } } } */
-#include <Foundation/NSString.h>
-#include <Foundation/NSAutoreleasePool.h>
-#include <Foundation/NSArray.h>
+#include "../objc-obj-c++-shared/F-NSString.h"
+#include "../objc-obj-c++-shared/F-NSAutoreleasePool.h"
+#include "../objc-obj-c++-shared/F-NSArray.h"
// gcc -o foo foo.m -framework Foundation
diff --git a/gcc/testsuite/objc.dg/objc-foreach-5.m b/gcc/testsuite/objc.dg/objc-foreach-5.m
index 7113a7a..e02bd7a 100644
--- a/gcc/testsuite/objc.dg/objc-foreach-5.m
+++ b/gcc/testsuite/objc.dg/objc-foreach-5.m
@@ -4,8 +4,9 @@
/* { dg-skip-if "No NeXT fast enum. pre-Darwin9" { *-*-darwin[5-8]* } { "-fnext-runtime" } { "" } } */
/* { dg-additional-options "-framework Foundation" { target { *-*-darwin* } } } */
-#include <Foundation/NSArray.h>
-#include <Foundation/NSAutoreleasePool.h>
+#include "../objc-obj-c++-shared/F-NSArray.h"
+#include "../objc-obj-c++-shared/F-NSAutoreleasePool.h"
+#include "../objc-obj-c++-shared/F-NSValue.h"
NSArray * createTestVictim(unsigned capacity) {
NSMutableArray * arr = [[NSMutableArray alloc] initWithCapacity:capacity];
diff --git a/gcc/testsuite/objc.dg/objc-gc-4.m b/gcc/testsuite/objc.dg/objc-gc-4.m
index 747da4d..96c3278 100644
--- a/gcc/testsuite/objc.dg/objc-gc-4.m
+++ b/gcc/testsuite/objc.dg/objc-gc-4.m
@@ -3,6 +3,7 @@
/* Contributed by Ziemowit Laski <zlaski@apple.com> */
/* { dg-do compile } */
+/* { dg-skip-if "GC API is an error from Darwin16." { *-*-darwin1[6-8]* } { "-fnext-runtime" } { "" } } */
/* { dg-options "-fobjc-gc" } */
/* { dg-prune-output "cc1obj: warning: '-fobjc-gc' is ignored for '-fgnu-runtime'" } */
diff --git a/gcc/testsuite/objc.dg/property/dotsyntax-17.m b/gcc/testsuite/objc.dg/property/dotsyntax-17.m
index ce01598..050d9bf 100644
--- a/gcc/testsuite/objc.dg/property/dotsyntax-17.m
+++ b/gcc/testsuite/objc.dg/property/dotsyntax-17.m
@@ -35,19 +35,19 @@ int main (void)
{
MyRootClass *object = [[MyRootClass alloc] init];
- object.count = 10; /* { dg-error "readonly property cannot be set" } */
+ object.count = 10; /* { dg-error "'readonly' property cannot be set" } */
if (object.count != 10) /* Ok */
abort ();
/* Test errors when trying to change a readonly property using
pre/post increment/decrement operators. */
- object.count++; /* { dg-error "readonly property cannot be set" } */
+ object.count++; /* { dg-error "'readonly' property cannot be set" } */
- ++object.count; /* { dg-error "readonly property cannot be set" } */
+ ++object.count; /* { dg-error "'readonly' property cannot be set" } */
- object.count--; /* { dg-error "readonly property cannot be set" } */
+ object.count--; /* { dg-error "'readonly' property cannot be set" } */
- --object.count; /* { dg-error "readonly property cannot be set" } */
+ --object.count; /* { dg-error "'readonly' property cannot be set" } */
/* Test errors when trying to change something using Objective-C 2.0
dot-syntax but there is a setter but no getter. */
diff --git a/gcc/testsuite/objc.dg/property/property-neg-7.m b/gcc/testsuite/objc.dg/property/property-neg-7.m
index 245a807..d721ed1 100644
--- a/gcc/testsuite/objc.dg/property/property-neg-7.m
+++ b/gcc/testsuite/objc.dg/property/property-neg-7.m
@@ -13,8 +13,8 @@
void foo (NSArray *ans[], id pid, id apid[], int i) {
NSArray *test;
- test.count = 1; /* { dg-error "readonly property cannot be set" } */
- ((NSArray *)pid).count = 1; /* { dg-error "readonly property cannot be set" } */
- ((NSArray *)apid[i]).count = 1; /* { dg-error "readonly property cannot be set" } */
- ans[i].count = 3; /* { dg-error "readonly property cannot be set" } */
+ test.count = 1; /* { dg-error "'readonly' property cannot be set" } */
+ ((NSArray *)pid).count = 1; /* { dg-error "'readonly' property cannot be set" } */
+ ((NSArray *)apid[i]).count = 1; /* { dg-error "'readonly' property cannot be set" } */
+ ans[i].count = 3; /* { dg-error "'readonly' property cannot be set" } */
}
diff --git a/gcc/testsuite/objc.dg/proto-hier-1.m b/gcc/testsuite/objc.dg/proto-hier-1.m
index fbd00f8..0f409fc 100644
--- a/gcc/testsuite/objc.dg/proto-hier-1.m
+++ b/gcc/testsuite/objc.dg/proto-hier-1.m
@@ -53,6 +53,4 @@ int foo(void) {
return 0;
}
-/* { dg-warning "Messages without a matching method signature" "" { target *-*-* } 0 } */
-/* { dg-warning "will be assumed to return .id. and accept" "" { target *-*-* } 0 } */
-/* { dg-warning ".\.\.\.. as arguments" "" { target *-*-* } 0 } */
+/* { dg-warning "messages without a matching method signature will be assumed to return .id. and accept .\.\.\.. as arguments" "" { target *-*-* } 0 } */
diff --git a/gcc/testsuite/objc.dg/proto-lossage-4.m b/gcc/testsuite/objc.dg/proto-lossage-4.m
index 182e92d..9d1def5 100644
--- a/gcc/testsuite/objc.dg/proto-lossage-4.m
+++ b/gcc/testsuite/objc.dg/proto-lossage-4.m
@@ -49,6 +49,4 @@ long foo(void) {
return receiver;
}
-/* { dg-warning "Messages without a matching method signature" "" { target *-*-* } 0 } */
-/* { dg-warning "will be assumed to return .id. and accept" "" { target *-*-* } 0 } */
-/* { dg-warning ".\.\.\.. as arguments" "" { target *-*-* } 0 } */
+/* { dg-warning "messages without a matching method signature will be assumed to return .id. and accept .\.\.\.. as arguments" "" { target *-*-* } 0 } */
diff --git a/gcc/testsuite/objc.dg/proto-lossage-7.m b/gcc/testsuite/objc.dg/proto-lossage-7.m
index b32cfd8..118a130 100644
--- a/gcc/testsuite/objc.dg/proto-lossage-7.m
+++ b/gcc/testsuite/objc.dg/proto-lossage-7.m
@@ -3,7 +3,7 @@
/* { dg-do compile } */
#ifdef __NEXT_RUNTIME__
-#include <Foundation/NSObject.h>
+#include "../objc-obj-c++-shared/F-NSObject.h"
#define OBJECT NSObject
#else
#include <objc/Object.h>
diff --git a/gcc/testsuite/objc.dg/protocol-qualifier-2.m b/gcc/testsuite/objc.dg/protocol-qualifier-2.m
index 9fb09b5..33a6969 100644
--- a/gcc/testsuite/objc.dg/protocol-qualifier-2.m
+++ b/gcc/testsuite/objc.dg/protocol-qualifier-2.m
@@ -25,7 +25,5 @@ void test1 (void)
{
[object1 method]; /* Ok */
[object2 method]; /* { dg-warning ".MyClass. may not respond to ..method." } */
- /* { dg-warning "without a matching method" "" { target *-*-* } .-1 } */
- /* { dg-warning "will be assumed to return" "" { target *-*-* } .-2 } */
- /* { dg-warning "as arguments" "" { target *-*-* } .-3 } */
}
+/* { dg-warning "messages without a matching method signature will be assumed to return .id. and accept .\.\.\.' as arguments" "" { target *-*-* } 0 } */
diff --git a/gcc/testsuite/objc.dg/strings/const-cfstring-2.m b/gcc/testsuite/objc.dg/strings/const-cfstring-2.m
index 14ae68c..effe7f5 100644
--- a/gcc/testsuite/objc.dg/strings/const-cfstring-2.m
+++ b/gcc/testsuite/objc.dg/strings/const-cfstring-2.m
@@ -8,8 +8,8 @@
/* { dg-skip-if "NeXT only" { *-*-* } { "-fgnu-runtime" } { "" } } */
/* { dg-options "-mconstant-cfstrings -Wnonportable-cfstrings" } */
-#import <Foundation/NSString.h>
-#import <CoreFoundation/CFString.h>
+#include "../../objc-obj-c++-shared/F-NSString.h"
+#include "../../objc-obj-c++-shared/CF-CFString.h"
#ifndef __CONSTANT_CFSTRINGS__
#error The -fconstant-cfstrings option is not functioning properly
diff --git a/gcc/testsuite/objc.dg/strings/const-cfstring-5.m b/gcc/testsuite/objc.dg/strings/const-cfstring-5.m
index 98bb7c5..762afb6 100644
--- a/gcc/testsuite/objc.dg/strings/const-cfstring-5.m
+++ b/gcc/testsuite/objc.dg/strings/const-cfstring-5.m
@@ -6,7 +6,7 @@
/* { dg-skip-if "NeXT only" { *-*-* } { "-fgnu-runtime" } { "" } } */
/* { dg-options "-mconstant-cfstrings" } */
-#include <Foundation/NSObject.h>
+#include "../../objc-obj-c++-shared/F-NSObject.h"
@interface Foo: NSObject {
char *cString;
diff --git a/gcc/testsuite/objc.dg/strings/const-str-12b.m b/gcc/testsuite/objc.dg/strings/const-str-12b.m
index d0dfb66..e04f0f6 100644
--- a/gcc/testsuite/objc.dg/strings/const-str-12b.m
+++ b/gcc/testsuite/objc.dg/strings/const-str-12b.m
@@ -6,11 +6,11 @@
/* { dg-options "-mno-constant-cfstrings -fconstant-string-class=Foo" { target *-*-darwin* } } */
#ifdef __NEXT_RUNTIME__
-#include <Foundation/NSObject.h>
-#define OBJECT NSObject
+# include "../../objc-obj-c++-shared/F-NSObject.h"
+# define OBJECT NSObject
#else
-#include <objc/Object.h>
-#define OBJECT Object
+# include <objc/Object.h>
+# define OBJECT Object
#endif
#include "../../objc-obj-c++-shared/objc-test-suite-types.h"
diff --git a/gcc/testsuite/objc.dg/stubify-1.m b/gcc/testsuite/objc.dg/stubify-1.m
index 91bf73a..1e160a1 100644
--- a/gcc/testsuite/objc.dg/stubify-1.m
+++ b/gcc/testsuite/objc.dg/stubify-1.m
@@ -4,7 +4,7 @@
/* { dg-do compile { target *-*-darwin* } } */
/* { dg-skip-if "" { *-*-* } { "-fgnu-runtime" } { "" } } */
/* { dg-require-effective-target ilp32 } */
-/* { dg-options "-Os -mdynamic-no-pic -mmacosx-version-min=10.4" } */
+/* { dg-options "-Os -mdynamic-no-pic -mmacosx-version-min=10.4 -mpic-symbol-stubs" } */
typedef struct objc_object { } *id ;
int x = 41 ;
@@ -28,8 +28,8 @@ extern int bogonic (int, int, int) ;
}
@end
-/* { dg-final { scan-assembler-not "\(bl|call\)\[ \t\]+_objc_msgSend\n" } } */
-/* { dg-final { scan-assembler "\(bl|call\)\[ \t\]+L_objc_msgSend\\\$stub\n" } } */
-/* { dg-final { scan-assembler-not "\(bl|call\)\[ \t\]+_bogonic\n" } } */
-/* { dg-final { scan-assembler "\(bl|call\)\[ \t\]+L_bogonic\\\$stub\n" } } */
-/* { dg-final { scan-assembler-not "\\\$non_lazy_ptr" } } */
+/* { dg-final { scan-assembler-not {(bl|call)[ \t]+_objc_msgSend\n} } } */
+/* { dg-final { scan-assembler {(bl|call)[ \t]+L_objc_msgSend\$stub\n} } } */
+/* { dg-final { scan-assembler-not {(bl|call)[ \t]+_bogonic\n} } } */
+/* { dg-final { scan-assembler {(bl|call)[ \t]+L_bogonic\$stub\n} } } */
+/* { dg-final { scan-assembler-not {\$non_lazy_ptr} } } */
diff --git a/gcc/testsuite/objc.dg/stubify-2.m b/gcc/testsuite/objc.dg/stubify-2.m
index eaf4b96..1f53b9c 100644
--- a/gcc/testsuite/objc.dg/stubify-2.m
+++ b/gcc/testsuite/objc.dg/stubify-2.m
@@ -1,10 +1,10 @@
/* All calls must be properly stubified, m32 only. */
/* Testcase extracted from TextEdit:Document.m. */
-/* { dg-do compile { target powerpc*-*-darwin* } } */
+/* { dg-do compile { target *-*-darwin* } } */
/* { dg-skip-if "" { *-*-* } { "-fgnu-runtime" } { "" } } */
/* { dg-require-effective-target ilp32 } */
-/* { dg-options "-mdynamic-no-pic -fdump-rtl-jump -mmacosx-version-min=10.4" } */
+/* { dg-options "-mdynamic-no-pic -fdump-rtl-jump -mmacosx-version-min=10.4 -mpic-symbol-stubs" } */
typedef struct objc_object { } *id ;
int x = 41 ;
@@ -30,4 +30,10 @@ extern int bogonic (int, int, int) ;
/* Any symbol_ref of an un-stubified objc_msgSend is an error; look
for "objc_msgSend" in quotes, without the $stub suffix. */
-/* { dg-final { scan-rtl-dump-not "symbol_ref.*\"objc_msgSend\"" "jump" } } */
+/* { dg-final { scan-rtl-dump-not {symbol_ref.*"objc_msgSend"} "jump" { target powerpc*-*-darwin* } } } */
+
+/* { dg-final { scan-assembler-not {(bl|call)[ \t]+_objc_msgSend\n} } } */
+/* { dg-final { scan-assembler {(bl|call)[ \t]+L_objc_msgSend\$stub\n} } } */
+/* { dg-final { scan-assembler-not {(bl|call)[ \t]+_bogonic\n} } } */
+/* { dg-final { scan-assembler {(bl|call)[ \t]+L_bogonic\$stub\n} } } */
+/* { dg-final { scan-assembler-not {\$non_lazy_ptr} } } */
diff --git a/gcc/testsuite/objc.dg/symtab-1.m b/gcc/testsuite/objc.dg/symtab-1.m
index 04d747d..e6e0b613 100644
--- a/gcc/testsuite/objc.dg/symtab-1.m
+++ b/gcc/testsuite/objc.dg/symtab-1.m
@@ -4,7 +4,7 @@
/* { dg-do compile { target { *-*-darwin* } } } */
/* { dg-skip-if "" { *-*-* } { "-fgnu-runtime" } { "" } } */
-#include <Foundation/NSObject.h>
+#include "../objc-obj-c++-shared/F-NSObject.h"
@interface Base: NSObject
- (void)setValues;
diff --git a/gcc/testsuite/objc.dg/torture/strings/const-cfstring-1.m b/gcc/testsuite/objc.dg/torture/strings/const-cfstring-1.m
index 7e98915..a9c0ab6 100644
--- a/gcc/testsuite/objc.dg/torture/strings/const-cfstring-1.m
+++ b/gcc/testsuite/objc.dg/torture/strings/const-cfstring-1.m
@@ -13,8 +13,8 @@
Well, we don't implement writable ones at this juncture. */
/* { dg-options "-mconstant-cfstrings -framework Cocoa -Wl,-w" { target *-*-darwin[123]* } } */
-#import <Foundation/NSString.h>
-#import <CoreFoundation/CFString.h>
+#include "../../../objc-obj-c++-shared/F-NSString.h"
+#include "../../../objc-obj-c++-shared/CF-CFString.h"
#include <stdlib.h>
void printOut(NSString *str) {
diff --git a/gcc/testsuite/objc.dg/torture/strings/const-str-10.m b/gcc/testsuite/objc.dg/torture/strings/const-str-10.m
index 120bcd9..6565dc20 100644
--- a/gcc/testsuite/objc.dg/torture/strings/const-str-10.m
+++ b/gcc/testsuite/objc.dg/torture/strings/const-str-10.m
@@ -6,7 +6,8 @@
/* { dg-skip-if "" { *-*-* } { "-fgnu-runtime" } { "" } } */
/* { dg-options "-mno-constant-cfstrings" { target *-*-darwin* } } */
-#include <Foundation/NSObject.h>
+#include "../../../objc-obj-c++-shared/F-NSObject.h"
+#include <stdlib.h>
#include "../../../objc-obj-c++-shared/runtime.h" /* For NEXT_OBJC_USE_NEW_INTERFACE. */
@interface NSString: NSObject
diff --git a/gcc/testsuite/objc.dg/torture/strings/const-str-11.m b/gcc/testsuite/objc.dg/torture/strings/const-str-11.m
index 4c3f9ea..2bdb153 100644
--- a/gcc/testsuite/objc.dg/torture/strings/const-str-11.m
+++ b/gcc/testsuite/objc.dg/torture/strings/const-str-11.m
@@ -7,7 +7,7 @@
/* { dg-options "-fconstant-string-class=XStr" } */
/* { dg-options "-mno-constant-cfstrings -fconstant-string-class=XStr" { target *-*-darwin* } } */
-#include <Foundation/NSObject.h>
+#include "../../../objc-obj-c++-shared/F-NSObject.h"
#include "../../../objc-obj-c++-shared/runtime.h" /* For NEXT_OBJC_USE_NEW_INTERFACE. */
@interface XString: NSObject {
diff --git a/gcc/testsuite/objc.dg/torture/strings/const-str-9.m b/gcc/testsuite/objc.dg/torture/strings/const-str-9.m
index d65aa01..966ea5e 100644
--- a/gcc/testsuite/objc.dg/torture/strings/const-str-9.m
+++ b/gcc/testsuite/objc.dg/torture/strings/const-str-9.m
@@ -5,7 +5,7 @@
/* { dg-skip-if "" { *-*-* } { "-fgnu-runtime" } { "" } } */
/* { dg-options "-mno-constant-cfstrings" { target *-*-darwin* } } */
-#include <Foundation/NSObject.h>
+#include "../../../objc-obj-c++-shared/F-NSObject.h"
#include "../../../objc-obj-c++-shared/runtime.h" /* For NEXT_OBJC_USE_NEW_INTERFACE. */
@interface NSConstantString: NSObject {
diff --git a/gcc/testsuite/objc.dg/zero-link-1.m b/gcc/testsuite/objc.dg/zero-link-1.m
index 812267b..e1148de 100644
--- a/gcc/testsuite/objc.dg/zero-link-1.m
+++ b/gcc/testsuite/objc.dg/zero-link-1.m
@@ -5,7 +5,7 @@
/* { dg-skip-if "" { *-*-* } { "-fgnu-runtime" } { "" } } */
/* { dg-options "-fzero-link" } */
-#include <Foundation/NSObject.h>
+#include "../objc-obj-c++-shared/F-NSObject.h"
extern void abort(void);
#define CHECK_IF(expr) if(!(expr)) abort();
diff --git a/gcc/testsuite/objc.dg/zero-link-2.m b/gcc/testsuite/objc.dg/zero-link-2.m
index 3bfe84d..1910091 100644
--- a/gcc/testsuite/objc.dg/zero-link-2.m
+++ b/gcc/testsuite/objc.dg/zero-link-2.m
@@ -5,7 +5,7 @@
/* { dg-skip-if "" { *-*-* } { "-fgnu-runtime" } { "" } } */
/* { dg-options "-fno-zero-link" } */
-#include <Foundation/NSObject.h>
+#include "../objc-obj-c++-shared/F-NSObject.h"
extern void abort(void);
#define CHECK_IF(expr) if(!(expr)) abort();
diff --git a/gcc/testsuite/objc.dg/zero-link-3.m b/gcc/testsuite/objc.dg/zero-link-3.m
index 18f21db..0c77c09 100644
--- a/gcc/testsuite/objc.dg/zero-link-3.m
+++ b/gcc/testsuite/objc.dg/zero-link-3.m
@@ -7,12 +7,12 @@
/* { dg-xfail-run-if "Needs OBJC2 ABI" { *-*-darwin* && { lp64 && { ! objc2 } } } { "-fnext-runtime" } { "" } } */
#ifdef __NEXT_RUNTIME__
-#include <Foundation/NSObject.h>
-#define OBJECT NSObject
+# include "../objc-obj-c++-shared/F-NSObject.h"
+# define OBJECT NSObject
#else
-#include <objc/Object.h>
-#include <objc/Protocol.h>
-#define OBJECT Object
+# include <objc/Object.h>
+# include <objc/Protocol.h>
+# define OBJECT Object
#endif
extern void abort(void);
diff --git a/gcc/timevar.def b/gcc/timevar.def
index 13cb470..626ce49 100644
--- a/gcc/timevar.def
+++ b/gcc/timevar.def
@@ -78,8 +78,8 @@ DEFTIMEVAR (TV_IPA_INLINING , "ipa inlining heuristics")
DEFTIMEVAR (TV_IPA_FNSPLIT , "ipa function splitting")
DEFTIMEVAR (TV_IPA_COMDATS , "ipa comdats")
DEFTIMEVAR (TV_IPA_OPT , "ipa various optimizations")
-DEFTIMEVAR (TV_IPA_LTO_DECOMPRESS , "lto stream inflate")
-DEFTIMEVAR (TV_IPA_LTO_COMPRESS , "lto stream deflate")
+DEFTIMEVAR (TV_IPA_LTO_DECOMPRESS , "lto stream decompression")
+DEFTIMEVAR (TV_IPA_LTO_COMPRESS , "lto stream compression")
DEFTIMEVAR (TV_IPA_LTO_OUTPUT , "lto stream output")
DEFTIMEVAR (TV_IPA_LTO_GIMPLE_IN , "ipa lto gimple in")
DEFTIMEVAR (TV_IPA_LTO_GIMPLE_OUT , "ipa lto gimple out")
diff --git a/gcc/tlink.c b/gcc/tlink.c
index 16a7b15..485000b 100644
--- a/gcc/tlink.c
+++ b/gcc/tlink.c
@@ -484,9 +484,11 @@ recompile_files (void)
the new file name already exists. Therefore, we explicitly
remove the old file first. */
if (remove (f->key) == -1)
- fatal_error (input_location, "removing .rpo file: %m");
+ fatal_error (input_location,
+ "removing repository file %qs: %m", f->key);
if (rename (outname, f->key) == -1)
- fatal_error (input_location, "renaming .rpo file: %m");
+ fatal_error (input_location, "renaming repository file from "
+ "%qs to %qs: %m", outname, f->key);
if (!f->args)
{
diff --git a/gcc/toplev.c b/gcc/toplev.c
index 397a164..116be7b 100644
--- a/gcc/toplev.c
+++ b/gcc/toplev.c
@@ -879,7 +879,7 @@ init_asm_output (const char *name)
asm_file_name);
if (asm_out_file == 0)
fatal_error (UNKNOWN_LOCATION,
- "can%'t open %qs for writing: %m", asm_file_name);
+ "cannot open %qs for writing: %m", asm_file_name);
}
if (!flag_syntax_only)
@@ -1019,7 +1019,7 @@ output_stack_usage (void)
fprintf (stack_usage_file,
"%s:%d:%d:%s\t" HOST_WIDE_INT_PRINT_DEC"\t%s\n",
- lbasename (loc.file),
+ loc.file == NULL ? "(artificial)" : lbasename (loc.file),
loc.line,
loc.column,
name,
@@ -1056,7 +1056,7 @@ open_auxiliary_file (const char *ext)
filename = concat (aux_base_name, ".", ext, NULL);
file = fopen (filename, "w");
if (!file)
- fatal_error (input_location, "can%'t open %s for writing: %m", filename);
+ fatal_error (input_location, "cannot open %s for writing: %m", filename);
free (filename);
return file;
}
@@ -1666,7 +1666,7 @@ process_options (void)
aux_info_file = fopen (aux_info_file_name, "w");
if (aux_info_file == 0)
fatal_error (UNKNOWN_LOCATION,
- "can%'t open %s: %m", aux_info_file_name);
+ "cannot open %s: %m", aux_info_file_name);
}
if (!targetm_common.have_named_sections)
@@ -1737,7 +1737,7 @@ process_options (void)
{
warning_at (UNKNOWN_LOCATION, 0,
"%<-fstack-check=%> and %<-fstack-clash_protection%> are "
- "mutually exclusive. Disabling %<-fstack-check=%>");
+ "mutually exclusive; disabling %<-fstack-check=%>");
flag_stack_check = NO_STACK_CHECK;
}
@@ -1799,6 +1799,10 @@ process_options (void)
optimization_default_node = build_optimization_node (&global_options);
optimization_current_node = optimization_default_node;
+ if (flag_checking >= 2)
+ hash_table_sanitize_eq_limit
+ = PARAM_VALUE (PARAM_HASH_TABLE_VERIFICATION_LIMIT);
+
/* Please don't change global_options after this point, those changes won't
be reflected in optimization_{default,current}_node. */
}
@@ -2180,7 +2184,7 @@ do_compile ()
on the squared numbers. */
if (mpfr_set_emin (2 * (min_exp - 1))
|| mpfr_set_emax (2 * (max_exp + 1)))
- sorry ("mpfr not configured to handle all float modes");
+ sorry ("mpfr not configured to handle all floating modes");
/* Set up the back-end if requested. */
if (!no_backend)
diff --git a/gcc/trans-mem.c b/gcc/trans-mem.c
index 0581aae..35d4fab 100644
--- a/gcc/trans-mem.c
+++ b/gcc/trans-mem.c
@@ -754,10 +754,10 @@ diagnose_tm_1 (gimple_stmt_iterator *gsi, bool *handled_ops_p,
Either that or get the language spec to resurrect __tm_waiver. */
if (d->block_flags & DIAG_TM_SAFE)
error_at (gimple_location (stmt),
- "asm not allowed in atomic transaction");
+ "%<asm%> not allowed in atomic transaction");
else if (d->func_flags & DIAG_TM_SAFE)
error_at (gimple_location (stmt),
- "asm not allowed in %<transaction_safe%> function");
+ "%<asm%> not allowed in %<transaction_safe%> function");
break;
case GIMPLE_TRANSACTION:
@@ -3708,9 +3708,9 @@ tm_memopt_compute_available (struct tm_region *region,
/* Allocate a worklist array/queue. Entries are only added to the
list if they were not already on the list. So the size is
bounded by the number of basic blocks in the region. */
+ gcc_assert (!blocks.is_empty ());
qlen = blocks.length () - 1;
- qin = qout = worklist =
- XNEWVEC (basic_block, qlen);
+ qin = qout = worklist = XNEWVEC (basic_block, qlen);
/* Put every block in the region on the worklist. */
for (i = 0; blocks.iterate (i, &bb); ++i)
@@ -4414,7 +4414,8 @@ ipa_tm_scan_irr_block (basic_block bb)
{
tree t = build1 (NOP_EXPR, void_type_node, size_zero_node);
SET_EXPR_LOCATION (t, gimple_location (stmt));
- error ("%Kasm not allowed in %<transaction_safe%> function", t);
+ error ("%K%<asm%> not allowed in %<transaction_safe%> function",
+ t);
}
return true;
@@ -4788,7 +4789,7 @@ ipa_tm_diagnose_transaction (struct cgraph_node *node,
if (gimple_code (stmt) == GIMPLE_ASM)
{
error_at (gimple_location (stmt),
- "asm not allowed in atomic transaction");
+ "%<asm%> not allowed in atomic transaction");
continue;
}
diff --git a/gcc/tree-affine.c b/gcc/tree-affine.c
index 1d7d19e..b8a62a6 100644
--- a/gcc/tree-affine.c
+++ b/gcc/tree-affine.c
@@ -259,104 +259,66 @@ aff_combination_convert (aff_tree *comb, tree type)
}
}
-/* Splits EXPR into an affine combination of parts. */
+/* Tries to handle OP0 CODE OP1 as affine combination of parts. Returns
+ true when that was successful and returns the combination in COMB. */
-void
-tree_to_aff_combination (tree expr, tree type, aff_tree *comb)
+static bool
+expr_to_aff_combination (aff_tree *comb, tree_code code, tree type,
+ tree op0, tree op1 = NULL_TREE)
{
aff_tree tmp;
- enum tree_code code;
- tree cst, core, toffset;
poly_int64 bitpos, bitsize, bytepos;
- machine_mode mode;
- int unsignedp, reversep, volatilep;
-
- STRIP_NOPS (expr);
- code = TREE_CODE (expr);
switch (code)
{
case POINTER_PLUS_EXPR:
- tree_to_aff_combination (TREE_OPERAND (expr, 0), type, comb);
- tree_to_aff_combination (TREE_OPERAND (expr, 1), sizetype, &tmp);
+ tree_to_aff_combination (op0, type, comb);
+ tree_to_aff_combination (op1, sizetype, &tmp);
aff_combination_add (comb, &tmp);
- return;
+ return true;
case PLUS_EXPR:
case MINUS_EXPR:
- tree_to_aff_combination (TREE_OPERAND (expr, 0), type, comb);
- tree_to_aff_combination (TREE_OPERAND (expr, 1), type, &tmp);
+ tree_to_aff_combination (op0, type, comb);
+ tree_to_aff_combination (op1, type, &tmp);
if (code == MINUS_EXPR)
aff_combination_scale (&tmp, -1);
aff_combination_add (comb, &tmp);
- return;
+ return true;
case MULT_EXPR:
- cst = TREE_OPERAND (expr, 1);
- if (TREE_CODE (cst) != INTEGER_CST)
+ if (TREE_CODE (op1) != INTEGER_CST)
break;
- tree_to_aff_combination (TREE_OPERAND (expr, 0), type, comb);
- aff_combination_scale (comb, wi::to_widest (cst));
- return;
+ tree_to_aff_combination (op0, type, comb);
+ aff_combination_scale (comb, wi::to_widest (op1));
+ return true;
case NEGATE_EXPR:
- tree_to_aff_combination (TREE_OPERAND (expr, 0), type, comb);
+ tree_to_aff_combination (op0, type, comb);
aff_combination_scale (comb, -1);
- return;
+ return true;
case BIT_NOT_EXPR:
/* ~x = -x - 1 */
- tree_to_aff_combination (TREE_OPERAND (expr, 0), type, comb);
+ tree_to_aff_combination (op0, type, comb);
aff_combination_scale (comb, -1);
aff_combination_add_cst (comb, -1);
- return;
-
- case ADDR_EXPR:
- /* Handle &MEM[ptr + CST] which is equivalent to POINTER_PLUS_EXPR. */
- if (TREE_CODE (TREE_OPERAND (expr, 0)) == MEM_REF)
- {
- expr = TREE_OPERAND (expr, 0);
- tree_to_aff_combination (TREE_OPERAND (expr, 0), type, comb);
- tree_to_aff_combination (TREE_OPERAND (expr, 1), sizetype, &tmp);
- aff_combination_add (comb, &tmp);
- return;
- }
- core = get_inner_reference (TREE_OPERAND (expr, 0), &bitsize, &bitpos,
- &toffset, &mode, &unsignedp, &reversep,
- &volatilep);
- if (!multiple_p (bitpos, BITS_PER_UNIT, &bytepos))
- break;
- aff_combination_const (comb, type, bytepos);
- if (TREE_CODE (core) == MEM_REF)
- {
- tree mem_offset = TREE_OPERAND (core, 1);
- aff_combination_add_cst (comb, wi::to_poly_widest (mem_offset));
- core = TREE_OPERAND (core, 0);
- }
- else
- core = build_fold_addr_expr (core);
-
- if (TREE_CODE (core) == ADDR_EXPR)
- aff_combination_add_elt (comb, core, 1);
- else
- {
- tree_to_aff_combination (core, type, &tmp);
- aff_combination_add (comb, &tmp);
- }
- if (toffset)
- {
- tree_to_aff_combination (toffset, type, &tmp);
- aff_combination_add (comb, &tmp);
- }
- return;
+ return true;
CASE_CONVERT:
{
- tree otype = TREE_TYPE (expr);
- tree inner = TREE_OPERAND (expr, 0);
+ tree otype = type;
+ tree inner = op0;
tree itype = TREE_TYPE (inner);
enum tree_code icode = TREE_CODE (inner);
+ /* STRIP_NOPS */
+ if (tree_nop_conversion_p (otype, itype))
+ {
+ tree_to_aff_combination (op0, type, comb);
+ return true;
+ }
+
/* In principle this is a valid folding, but it isn't necessarily
an optimization, so do it here and not in fold_unary. */
if ((icode == PLUS_EXPR || icode == MINUS_EXPR || icode == MULT_EXPR)
@@ -376,9 +338,7 @@ tree_to_aff_combination (tree expr, tree type, aff_tree *comb)
{
op0 = fold_convert (otype, op0);
op1 = fold_convert (otype, op1);
- expr = fold_build2 (icode, otype, op0, op1);
- tree_to_aff_combination (expr, type, comb);
- return;
+ return expr_to_aff_combination (comb, icode, otype, op0, op1);
}
wide_int minv, maxv;
/* If inner type has wrapping overflow behavior, fold conversion
@@ -399,15 +359,102 @@ tree_to_aff_combination (tree expr, tree type, aff_tree *comb)
{
op0 = fold_convert (otype, op0);
op1 = fold_convert (otype, op1);
- expr = fold_build2 (MINUS_EXPR, otype, op0, op1);
- tree_to_aff_combination (expr, type, comb);
- return;
+ return expr_to_aff_combination (comb, MINUS_EXPR, otype,
+ op0, op1);
}
}
}
}
break;
+ default:;
+ }
+
+ return false;
+}
+
+/* Splits EXPR into an affine combination of parts. */
+
+void
+tree_to_aff_combination (tree expr, tree type, aff_tree *comb)
+{
+ aff_tree tmp;
+ enum tree_code code;
+ tree core, toffset;
+ poly_int64 bitpos, bitsize, bytepos;
+ machine_mode mode;
+ int unsignedp, reversep, volatilep;
+
+ STRIP_NOPS (expr);
+
+ code = TREE_CODE (expr);
+ switch (code)
+ {
+ case POINTER_PLUS_EXPR:
+ case PLUS_EXPR:
+ case MINUS_EXPR:
+ case MULT_EXPR:
+ if (expr_to_aff_combination (comb, code, type, TREE_OPERAND (expr, 0),
+ TREE_OPERAND (expr, 1)))
+ return;
+ break;
+
+ case NEGATE_EXPR:
+ case BIT_NOT_EXPR:
+ if (expr_to_aff_combination (comb, code, type, TREE_OPERAND (expr, 0)))
+ return;
+ break;
+
+ CASE_CONVERT:
+ /* ??? TREE_TYPE (expr) should be equal to type here, but IVOPTS
+ calls this with not showing an outer widening cast. */
+ if (expr_to_aff_combination (comb, code,
+ TREE_TYPE (expr), TREE_OPERAND (expr, 0)))
+ {
+ aff_combination_convert (comb, type);
+ return;
+ }
+ break;
+
+ case ADDR_EXPR:
+ /* Handle &MEM[ptr + CST] which is equivalent to POINTER_PLUS_EXPR. */
+ if (TREE_CODE (TREE_OPERAND (expr, 0)) == MEM_REF)
+ {
+ expr = TREE_OPERAND (expr, 0);
+ tree_to_aff_combination (TREE_OPERAND (expr, 0), type, comb);
+ tree_to_aff_combination (TREE_OPERAND (expr, 1), sizetype, &tmp);
+ aff_combination_add (comb, &tmp);
+ return;
+ }
+ core = get_inner_reference (TREE_OPERAND (expr, 0), &bitsize, &bitpos,
+ &toffset, &mode, &unsignedp, &reversep,
+ &volatilep);
+ if (!multiple_p (bitpos, BITS_PER_UNIT, &bytepos))
+ break;
+ aff_combination_const (comb, type, bytepos);
+ if (TREE_CODE (core) == MEM_REF)
+ {
+ tree mem_offset = TREE_OPERAND (core, 1);
+ aff_combination_add_cst (comb, wi::to_poly_widest (mem_offset));
+ core = TREE_OPERAND (core, 0);
+ }
+ else
+ core = build_fold_addr_expr (core);
+
+ if (TREE_CODE (core) == ADDR_EXPR)
+ aff_combination_add_elt (comb, core, 1);
+ else
+ {
+ tree_to_aff_combination (core, type, &tmp);
+ aff_combination_add (comb, &tmp);
+ }
+ if (toffset)
+ {
+ tree_to_aff_combination (toffset, type, &tmp);
+ aff_combination_add (comb, &tmp);
+ }
+ return;
+
default:
{
if (poly_int_tree_p (expr))
@@ -665,7 +712,7 @@ aff_combination_expand (aff_tree *comb ATTRIBUTE_UNUSED,
{
unsigned i;
aff_tree to_add, current, curre;
- tree e, rhs;
+ tree e;
gimple *def;
widest_int scale;
struct name_expansion *exp;
@@ -715,20 +762,38 @@ aff_combination_expand (aff_tree *comb ATTRIBUTE_UNUSED,
case PLUS_EXPR:
case MINUS_EXPR:
case MULT_EXPR:
+ if (!expr_to_aff_combination (&current, code, TREE_TYPE (name),
+ gimple_assign_rhs1 (def),
+ gimple_assign_rhs2 (def)))
+ continue;
+ break;
case NEGATE_EXPR:
case BIT_NOT_EXPR:
+ if (!expr_to_aff_combination (&current, code, TREE_TYPE (name),
+ gimple_assign_rhs1 (def)))
+ continue;
+ break;
CASE_CONVERT:
- rhs = gimple_assign_rhs_to_tree (def);
+ if (!expr_to_aff_combination (&current, code, TREE_TYPE (name),
+ gimple_assign_rhs1 (def)))
+ /* This makes us always expand conversions which we did
+ in the past and makes gcc.dg/tree-ssa/ivopts-lt-2.c
+ PASS, eliminating one induction variable in IVOPTs.
+ ??? But it is really excessive and we should try
+ harder to do without it. */
+ aff_combination_elt (&current, TREE_TYPE (name),
+ fold_convert (TREE_TYPE (name),
+ gimple_assign_rhs1 (def)));
break;
case ADDR_EXPR:
case INTEGER_CST:
case POLY_INT_CST:
- rhs = gimple_assign_rhs1 (def);
+ tree_to_aff_combination (gimple_assign_rhs1 (def),
+ TREE_TYPE (name), &current);
break;
default:
continue;
}
- tree_to_aff_combination (rhs, TREE_TYPE (name), &current);
exp = XNEW (struct name_expansion);
exp->in_progress = 1;
if (!*cache)
diff --git a/gcc/tree-call-cdce.c b/gcc/tree-call-cdce.c
index 2e482b3..9e3372f 100644
--- a/gcc/tree-call-cdce.c
+++ b/gcc/tree-call-cdce.c
@@ -93,10 +93,10 @@ along with GCC; see the file COPYING3. If not see
y = sqrt (x);
==>
- y = IFN_SQRT (x);
if (__builtin_isless (x, 0))
- sqrt (x);
-
+ y = sqrt (x);
+ else
+ y = IFN_SQRT (x);
In the vast majority of cases we should then never need to call sqrt.
Note that library functions are not supposed to clear errno to zero without
@@ -793,14 +793,16 @@ gen_shrink_wrap_conditions (gcall *bi_call, vec<gimple *> conds,
}
/* Shrink-wrap BI_CALL so that it is only called when one of the NCONDS
- conditions in CONDS is false. */
+ conditions in CONDS is false. Also move BI_NEWCALL to a new basic block
+ when it is non-null, it is called while all of the CONDS are true. */
static void
shrink_wrap_one_built_in_call_with_conds (gcall *bi_call, vec <gimple *> conds,
- unsigned int nconds)
+ unsigned int nconds,
+ gcall *bi_newcall = NULL)
{
gimple_stmt_iterator bi_call_bsi;
- basic_block bi_call_bb, join_tgt_bb, guard_bb;
+ basic_block bi_call_bb, bi_newcall_bb, join_tgt_bb, guard_bb;
edge join_tgt_in_edge_from_call, join_tgt_in_edge_fall_thru;
edge bi_call_in_edge0, guard_bb_in_edge;
unsigned tn_cond_stmts;
@@ -809,27 +811,26 @@ shrink_wrap_one_built_in_call_with_conds (gcall *bi_call, vec <gimple *> conds,
gimple *cond_expr_start;
/* The cfg we want to create looks like this:
-
- [guard n-1] <- guard_bb (old block)
- | \
- | [guard n-2] }
- | / \ }
- | / ... } new blocks
- | / [guard 0] }
- | / / | }
- [ call ] | <- bi_call_bb }
- | \ |
- | \ |
- | [ join ] <- join_tgt_bb (old iff call must end bb)
- |
+ [guard n-1] <- guard_bb (old block)
+ | \
+ | [guard n-2] }
+ | / \ }
+ | / ... } new blocks
+ | / [guard 0] }
+ | / / | }
+ [call] | <- bi_call_bb }
+ \ [newcall] <-bi_newcall_bb}
+ \ |
+ [join] <- join_tgt_bb (old iff call must end bb)
possible EH edges (only if [join] is old)
When [join] is new, the immediate dominators for these blocks are:
1. [guard n-1]: unchanged
2. [call]: [guard n-1]
- 3. [guard m]: [guard m+1] for 0 <= m <= n-2
- 4. [join]: [guard n-1]
+ 3. [newcall]: [guard 0]
+ 4. [guard m]: [guard m+1] for 0 <= m <= n-2
+ 5. [join]: [guard n-1]
We punt for the more complex case case of [join] being old and
simply free the dominance info. We also punt on postdominators,
@@ -927,6 +928,47 @@ shrink_wrap_one_built_in_call_with_conds (gcall *bi_call, vec <gimple *> conds,
edges.quick_push (edge_pair (bi_call_in_edge, guard_bb_in_edge));
}
+ /* Move BI_NEWCALL to new basic block when it is non-null. */
+ if (bi_newcall)
+ {
+ /* Get bi_newcall_bb by split join_tgt_in_edge_fall_thru edge,
+ and move BI_NEWCALL to bi_newcall_bb. */
+ bi_newcall_bb = split_edge (join_tgt_in_edge_fall_thru);
+ gimple_stmt_iterator to_gsi = gsi_start_bb (bi_newcall_bb);
+ gimple_stmt_iterator from_gsi = gsi_for_stmt (bi_newcall);
+ gsi_move_before (&from_gsi, &to_gsi);
+ join_tgt_in_edge_fall_thru = EDGE_SUCC (bi_newcall_bb, 0);
+ join_tgt_bb = join_tgt_in_edge_fall_thru->dest;
+
+ tree bi_newcall_lhs = gimple_call_lhs (bi_newcall);
+ tree bi_call_lhs = gimple_call_lhs (bi_call);
+ if (!bi_call_lhs)
+ {
+ bi_call_lhs = copy_ssa_name (bi_newcall_lhs);
+ gimple_call_set_lhs (bi_call, bi_call_lhs);
+ SSA_NAME_DEF_STMT (bi_call_lhs) = bi_call;
+ }
+
+ /* Create phi node for lhs of BI_CALL and BI_NEWCALL. */
+ gphi *new_phi = create_phi_node (copy_ssa_name (bi_newcall_lhs),
+ join_tgt_bb);
+ SSA_NAME_OCCURS_IN_ABNORMAL_PHI (PHI_RESULT (new_phi))
+ = SSA_NAME_OCCURS_IN_ABNORMAL_PHI (bi_newcall_lhs);
+ add_phi_arg (new_phi, bi_call_lhs, join_tgt_in_edge_from_call,
+ gimple_location (bi_call));
+ add_phi_arg (new_phi, bi_newcall_lhs, join_tgt_in_edge_fall_thru,
+ gimple_location (bi_newcall));
+
+ /* Replace all use of original return value with result of phi node. */
+ use_operand_p use_p;
+ gimple *use_stmt;
+ imm_use_iterator iterator;
+ FOR_EACH_IMM_USE_STMT (use_stmt, iterator, bi_newcall_lhs)
+ if (use_stmt != new_phi)
+ FOR_EACH_IMM_USE_ON_STMT (use_p, iterator)
+ SET_USE (use_p, PHI_RESULT (new_phi));
+ }
+
/* Now update the probability and profile information, processing the
guards in order of execution.
@@ -1030,9 +1072,11 @@ use_internal_fn (gcall *call)
unsigned nconds = 0;
auto_vec<gimple *, 12> conds;
+ bool is_arg_conds = false;
if (can_test_argument_range (call))
{
gen_shrink_wrap_conditions (call, conds, &nconds);
+ is_arg_conds = true;
gcc_assert (nconds != 0);
}
else
@@ -1082,8 +1126,8 @@ use_internal_fn (gcall *call)
call = new_call;
}
}
-
- shrink_wrap_one_built_in_call_with_conds (call, conds, nconds);
+ shrink_wrap_one_built_in_call_with_conds (call, conds, nconds,
+ is_arg_conds ? new_call : NULL);
}
/* The top level function for conditional dead code shrink
diff --git a/gcc/tree-cfg.c b/gcc/tree-cfg.c
index 966ce5a..a585efe 100644
--- a/gcc/tree-cfg.c
+++ b/gcc/tree-cfg.c
@@ -2722,10 +2722,10 @@ stmt_starts_bb_p (gimple *stmt, gimple *prev_stmt)
|| FORCED_LABEL (gimple_label_label (label_stmt)))
return true;
- if (prev_stmt && gimple_code (prev_stmt) == GIMPLE_LABEL)
+ if (glabel *plabel = safe_dyn_cast <glabel *> (prev_stmt))
{
- if (DECL_NONLOCAL (gimple_label_label (
- as_a <glabel *> (prev_stmt))))
+ if (DECL_NONLOCAL (gimple_label_label (plabel))
+ || !DECL_ARTIFICIAL (gimple_label_label (plabel)))
return true;
cfg_stats.num_merged_labels++;
@@ -2961,12 +2961,12 @@ verify_address (tree t, bool verify_addressable)
if (old_constant != new_constant)
{
- error ("constant not recomputed when ADDR_EXPR changed");
+ error ("constant not recomputed when %<ADDR_EXPR%> changed");
return true;
}
if (old_side_effects != new_side_effects)
{
- error ("side effects not recomputed when ADDR_EXPR changed");
+ error ("side effects not recomputed when %<ADDR_EXPR%> changed");
return true;
}
@@ -2981,13 +2981,13 @@ verify_address (tree t, bool verify_addressable)
if (DECL_GIMPLE_REG_P (base))
{
- error ("DECL_GIMPLE_REG_P set on a variable with address taken");
+ error ("%<DECL_GIMPLE_REG_P%> set on a variable with address taken");
return true;
}
if (verify_addressable && !TREE_ADDRESSABLE (base))
{
- error ("address taken, but ADDRESSABLE bit not set");
+ error ("address taken but %<TREE_ADDRESSABLE%> bit not set");
return true;
}
@@ -3036,6 +3036,8 @@ verify_types_in_gimple_min_lval (tree expr)
static bool
verify_types_in_gimple_reference (tree expr, bool require_lvalue)
{
+ const char *code_name = get_tree_code_name (TREE_CODE (expr));
+
if (TREE_CODE (expr) == REALPART_EXPR
|| TREE_CODE (expr) == IMAGPART_EXPR
|| TREE_CODE (expr) == BIT_FIELD_REF)
@@ -3043,7 +3045,7 @@ verify_types_in_gimple_reference (tree expr, bool require_lvalue)
tree op = TREE_OPERAND (expr, 0);
if (!is_gimple_reg_type (TREE_TYPE (expr)))
{
- error ("non-scalar BIT_FIELD_REF, IMAGPART_EXPR or REALPART_EXPR");
+ error ("non-scalar %qs", code_name);
return true;
}
@@ -3057,14 +3059,14 @@ verify_types_in_gimple_reference (tree expr, bool require_lvalue)
|| !types_compatible_p (bitsizetype, TREE_TYPE (t1))
|| !types_compatible_p (bitsizetype, TREE_TYPE (t2)))
{
- error ("invalid position or size operand to BIT_FIELD_REF");
+ error ("invalid position or size operand to %qs", code_name);
return true;
}
if (INTEGRAL_TYPE_P (TREE_TYPE (expr))
&& maybe_ne (TYPE_PRECISION (TREE_TYPE (expr)), size))
{
error ("integral result type precision does not match "
- "field size of BIT_FIELD_REF");
+ "field size of %qs", code_name);
return true;
}
else if (!INTEGRAL_TYPE_P (TREE_TYPE (expr))
@@ -3073,13 +3075,14 @@ verify_types_in_gimple_reference (tree expr, bool require_lvalue)
size))
{
error ("mode size of non-integral result does not "
- "match field size of BIT_FIELD_REF");
+ "match field size of %qs",
+ code_name);
return true;
}
if (INTEGRAL_TYPE_P (TREE_TYPE (op))
&& !type_has_mode_precision_p (TREE_TYPE (op)))
{
- error ("BIT_FIELD_REF of non-mode-precision operand");
+ error ("%qs of non-mode-precision operand", code_name);
return true;
}
if (!AGGREGATE_TYPE_P (TREE_TYPE (op))
@@ -3087,7 +3090,7 @@ verify_types_in_gimple_reference (tree expr, bool require_lvalue)
tree_to_poly_uint64 (TYPE_SIZE (TREE_TYPE (op)))))
{
error ("position plus size exceeds size of referenced object in "
- "BIT_FIELD_REF");
+ "%qs", code_name);
return true;
}
}
@@ -3097,7 +3100,7 @@ verify_types_in_gimple_reference (tree expr, bool require_lvalue)
&& !useless_type_conversion_p (TREE_TYPE (expr),
TREE_TYPE (TREE_TYPE (op))))
{
- error ("type mismatch in real/imagpart reference");
+ error ("type mismatch in %qs reference", code_name);
debug_generic_stmt (TREE_TYPE (expr));
debug_generic_stmt (TREE_TYPE (TREE_TYPE (op)));
return true;
@@ -3107,11 +3110,13 @@ verify_types_in_gimple_reference (tree expr, bool require_lvalue)
while (handled_component_p (expr))
{
+ code_name = get_tree_code_name (TREE_CODE (expr));
+
if (TREE_CODE (expr) == REALPART_EXPR
|| TREE_CODE (expr) == IMAGPART_EXPR
|| TREE_CODE (expr) == BIT_FIELD_REF)
{
- error ("non-top-level BIT_FIELD_REF, IMAGPART_EXPR or REALPART_EXPR");
+ error ("non-top-level %qs", code_name);
return true;
}
@@ -3126,7 +3131,7 @@ verify_types_in_gimple_reference (tree expr, bool require_lvalue)
|| (TREE_OPERAND (expr, 3)
&& !is_gimple_val (TREE_OPERAND (expr, 3))))
{
- error ("invalid operands to array reference");
+ error ("invalid operands to %qs", code_name);
debug_generic_stmt (expr);
return true;
}
@@ -3137,7 +3142,7 @@ verify_types_in_gimple_reference (tree expr, bool require_lvalue)
&& !useless_type_conversion_p (TREE_TYPE (expr),
TREE_TYPE (TREE_TYPE (op))))
{
- error ("type mismatch in array reference");
+ error ("type mismatch in %qs", code_name);
debug_generic_stmt (TREE_TYPE (expr));
debug_generic_stmt (TREE_TYPE (TREE_TYPE (op)));
return true;
@@ -3146,7 +3151,7 @@ verify_types_in_gimple_reference (tree expr, bool require_lvalue)
&& !useless_type_conversion_p (TREE_TYPE (TREE_TYPE (expr)),
TREE_TYPE (TREE_TYPE (op))))
{
- error ("type mismatch in array range reference");
+ error ("type mismatch in %qs", code_name);
debug_generic_stmt (TREE_TYPE (TREE_TYPE (expr)));
debug_generic_stmt (TREE_TYPE (TREE_TYPE (op)));
return true;
@@ -3157,13 +3162,13 @@ verify_types_in_gimple_reference (tree expr, bool require_lvalue)
if (TREE_OPERAND (expr, 2)
&& !is_gimple_val (TREE_OPERAND (expr, 2)))
{
- error ("invalid COMPONENT_REF offset operator");
+ error ("invalid %qs offset operator", code_name);
return true;
}
if (!useless_type_conversion_p (TREE_TYPE (expr),
TREE_TYPE (TREE_OPERAND (expr, 1))))
{
- error ("type mismatch in component reference");
+ error ("type mismatch in %qs", code_name);
debug_generic_stmt (TREE_TYPE (expr));
debug_generic_stmt (TREE_TYPE (TREE_OPERAND (expr, 1)));
return true;
@@ -3181,14 +3186,16 @@ verify_types_in_gimple_reference (tree expr, bool require_lvalue)
&& (TREE_CODE (op) == SSA_NAME
|| is_gimple_min_invariant (op)))
{
- error ("conversion of an SSA_NAME on the left hand side");
+ error ("conversion of %qs on the left hand side of %qs",
+ get_tree_code_name (TREE_CODE (op)), code_name);
debug_generic_stmt (expr);
return true;
}
else if (TREE_CODE (op) == SSA_NAME
&& TYPE_SIZE (TREE_TYPE (expr)) != TYPE_SIZE (TREE_TYPE (op)))
{
- error ("conversion of register to a different size");
+ error ("conversion of register to a different size in %qs",
+ code_name);
debug_generic_stmt (expr);
return true;
}
@@ -3199,20 +3206,22 @@ verify_types_in_gimple_reference (tree expr, bool require_lvalue)
expr = op;
}
+ code_name = get_tree_code_name (TREE_CODE (expr));
+
if (TREE_CODE (expr) == MEM_REF)
{
if (!is_gimple_mem_ref_addr (TREE_OPERAND (expr, 0))
|| (TREE_CODE (TREE_OPERAND (expr, 0)) == ADDR_EXPR
&& verify_address (TREE_OPERAND (expr, 0), false)))
{
- error ("invalid address operand in MEM_REF");
+ error ("invalid address operand in %qs", code_name);
debug_generic_stmt (expr);
return true;
}
if (!poly_int_tree_p (TREE_OPERAND (expr, 1))
|| !POINTER_TYPE_P (TREE_TYPE (TREE_OPERAND (expr, 1))))
{
- error ("invalid offset operand in MEM_REF");
+ error ("invalid offset operand in %qs", code_name);
debug_generic_stmt (expr);
return true;
}
@@ -3224,21 +3233,21 @@ verify_types_in_gimple_reference (tree expr, bool require_lvalue)
|| (TREE_CODE (TMR_BASE (expr)) == ADDR_EXPR
&& verify_address (TMR_BASE (expr), false)))
{
- error ("invalid address operand in TARGET_MEM_REF");
+ error ("invalid address operand in %qs", code_name);
return true;
}
if (!TMR_OFFSET (expr)
|| !poly_int_tree_p (TMR_OFFSET (expr))
|| !POINTER_TYPE_P (TREE_TYPE (TMR_OFFSET (expr))))
{
- error ("invalid offset operand in TARGET_MEM_REF");
+ error ("invalid offset operand in %qs", code_name);
debug_generic_stmt (expr);
return true;
}
}
else if (TREE_CODE (expr) == INDIRECT_REF)
{
- error ("INDIRECT_REF in gimple IL");
+ error ("%qs in gimple IL", code_name);
debug_generic_stmt (expr);
return true;
}
@@ -3345,7 +3354,7 @@ verify_gimple_call (gcall *stmt)
&& gimple_call_noreturn_p (stmt)
&& should_remove_lhs_p (lhs))
{
- error ("LHS in noreturn call");
+ error ("LHS in %<noreturn%> call");
return true;
}
@@ -3536,6 +3545,8 @@ verify_gimple_assign_unary (gassign *stmt)
return true;
}
+ const char* const code_name = get_tree_code_name (rhs_code);
+
/* First handle conversions. */
switch (rhs_code)
{
@@ -3608,7 +3619,7 @@ verify_gimple_assign_unary (gassign *stmt)
&& (!VECTOR_INTEGER_TYPE_P (rhs1_type)
|| !VECTOR_FLOAT_TYPE_P (lhs_type)))
{
- error ("invalid types in conversion to floating point");
+ error ("invalid types in conversion to floating-point");
debug_generic_expr (lhs_type);
debug_generic_expr (rhs1_type);
return true;
@@ -3663,7 +3674,7 @@ verify_gimple_assign_unary (gassign *stmt)
|| maybe_ne (2 * TYPE_VECTOR_SUBPARTS (lhs_type),
TYPE_VECTOR_SUBPARTS (rhs1_type)))
{
- error ("type mismatch in vector unpack expression");
+ error ("type mismatch in %qs expression", code_name);
debug_generic_expr (lhs_type);
debug_generic_expr (rhs1_type);
return true;
@@ -3685,7 +3696,7 @@ verify_gimple_assign_unary (gassign *stmt)
|| TYPE_UNSIGNED (rhs1_type)
|| element_precision (lhs_type) != element_precision (rhs1_type))
{
- error ("invalid types for ABSU_EXPR");
+ error ("invalid types for %qs", code_name);
debug_generic_expr (lhs_type);
debug_generic_expr (rhs1_type);
return true;
@@ -3696,7 +3707,7 @@ verify_gimple_assign_unary (gassign *stmt)
if (TREE_CODE (lhs_type) != VECTOR_TYPE
|| !useless_type_conversion_p (TREE_TYPE (lhs_type), rhs1_type))
{
- error ("vec_duplicate should be from a scalar to a like vector");
+ error ("%qs should be from a scalar to a like vector", code_name);
debug_generic_expr (lhs_type);
debug_generic_expr (rhs1_type);
return true;
@@ -3746,6 +3757,8 @@ verify_gimple_assign_binary (gassign *stmt)
return true;
}
+ const char* const code_name = get_tree_code_name (rhs_code);
+
/* First handle operations that involve different types. */
switch (rhs_code)
{
@@ -3757,7 +3770,7 @@ verify_gimple_assign_binary (gassign *stmt)
|| !(INTEGRAL_TYPE_P (rhs2_type)
|| SCALAR_FLOAT_TYPE_P (rhs2_type)))
{
- error ("type mismatch in complex expression");
+ error ("type mismatch in %qs", code_name);
debug_generic_expr (lhs_type);
debug_generic_expr (rhs1_type);
debug_generic_expr (rhs2_type);
@@ -3786,7 +3799,7 @@ verify_gimple_assign_binary (gassign *stmt)
&& INTEGRAL_TYPE_P (TREE_TYPE (rhs2_type))))
|| !useless_type_conversion_p (lhs_type, rhs1_type))
{
- error ("type mismatch in shift expression");
+ error ("type mismatch in %qs", code_name);
debug_generic_expr (lhs_type);
debug_generic_expr (rhs1_type);
debug_generic_expr (rhs2_type);
@@ -3803,7 +3816,7 @@ verify_gimple_assign_binary (gassign *stmt)
|| TREE_CODE (rhs2) != INTEGER_CST
|| (2 * TYPE_PRECISION (rhs1_type) > TYPE_PRECISION (lhs_type)))
{
- error ("type mismatch in widening vector shift expression");
+ error ("type mismatch in %qs", code_name);
debug_generic_expr (lhs_type);
debug_generic_expr (rhs1_type);
debug_generic_expr (rhs2_type);
@@ -3824,7 +3837,7 @@ verify_gimple_assign_binary (gassign *stmt)
|| (2 * TYPE_PRECISION (TREE_TYPE (rhs1_type))
> TYPE_PRECISION (TREE_TYPE (lhs_type))))
{
- error ("type mismatch in widening vector shift expression");
+ error ("type mismatch in %qs", code_name);
debug_generic_expr (lhs_type);
debug_generic_expr (rhs1_type);
debug_generic_expr (rhs2_type);
@@ -3845,7 +3858,7 @@ verify_gimple_assign_binary (gassign *stmt)
if (TREE_CODE (rhs1_type) != VECTOR_TYPE
|| TREE_CODE (rhs2_type) != VECTOR_TYPE)
{
- error ("invalid non-vector operands to vector valued plus");
+ error ("invalid non-vector operands to %qs", code_name);
return true;
}
lhs_etype = TREE_TYPE (lhs_type);
@@ -3856,7 +3869,7 @@ verify_gimple_assign_binary (gassign *stmt)
|| POINTER_TYPE_P (rhs1_etype)
|| POINTER_TYPE_P (rhs2_etype))
{
- error ("invalid (pointer) operands to plus/minus");
+ error ("invalid (pointer) operands %qs", code_name);
return true;
}
@@ -3870,7 +3883,7 @@ verify_gimple_assign_binary (gassign *stmt)
|| !useless_type_conversion_p (lhs_type, rhs1_type)
|| !ptrofftype_p (rhs2_type))
{
- error ("type mismatch in pointer plus expression");
+ error ("type mismatch in %qs", code_name);
debug_generic_stmt (lhs_type);
debug_generic_stmt (rhs1_type);
debug_generic_stmt (rhs2_type);
@@ -3891,7 +3904,7 @@ verify_gimple_assign_binary (gassign *stmt)
|| TYPE_UNSIGNED (lhs_type)
|| TYPE_PRECISION (lhs_type) != TYPE_PRECISION (rhs1_type))
{
- error ("type mismatch in pointer diff expression");
+ error ("type mismatch in %qs", code_name);
debug_generic_stmt (lhs_type);
debug_generic_stmt (rhs1_type);
debug_generic_stmt (rhs2_type);
@@ -3945,7 +3958,7 @@ verify_gimple_assign_binary (gassign *stmt)
|| maybe_lt (GET_MODE_SIZE (element_mode (rhs2_type)),
2 * GET_MODE_SIZE (element_mode (rhs1_type))))
{
- error ("type mismatch in widening sum reduction");
+ error ("type mismatch in %qs", code_name);
debug_generic_expr (lhs_type);
debug_generic_expr (rhs1_type);
debug_generic_expr (rhs2_type);
@@ -3965,7 +3978,7 @@ verify_gimple_assign_binary (gassign *stmt)
|| maybe_ne (GET_MODE_SIZE (element_mode (lhs_type)),
2 * GET_MODE_SIZE (element_mode (rhs1_type))))
{
- error ("type mismatch in vector widening multiplication");
+ error ("type mismatch in %qs", code_name);
debug_generic_expr (lhs_type);
debug_generic_expr (rhs1_type);
debug_generic_expr (rhs2_type);
@@ -4001,7 +4014,7 @@ verify_gimple_assign_binary (gassign *stmt)
|| maybe_ne (2 * TYPE_VECTOR_SUBPARTS (rhs1_type),
TYPE_VECTOR_SUBPARTS (lhs_type)))
{
- error ("type mismatch in vector pack expression");
+ error ("type mismatch in %qs", code_name);
debug_generic_expr (lhs_type);
debug_generic_expr (rhs1_type);
debug_generic_expr (rhs2_type);
@@ -4022,7 +4035,7 @@ verify_gimple_assign_binary (gassign *stmt)
|| maybe_ne (2 * TYPE_VECTOR_SUBPARTS (rhs1_type),
TYPE_VECTOR_SUBPARTS (lhs_type)))
{
- error ("type mismatch in vector pack expression");
+ error ("type mismatch in %qs", code_name);
debug_generic_expr (lhs_type);
debug_generic_expr (rhs1_type);
debug_generic_expr (rhs2_type);
@@ -4054,7 +4067,7 @@ verify_gimple_assign_binary (gassign *stmt)
case VEC_SERIES_EXPR:
if (!useless_type_conversion_p (rhs1_type, rhs2_type))
{
- error ("type mismatch in series expression");
+ error ("type mismatch in %qs", code_name);
debug_generic_expr (rhs1_type);
debug_generic_expr (rhs2_type);
return true;
@@ -4062,7 +4075,7 @@ verify_gimple_assign_binary (gassign *stmt)
if (TREE_CODE (lhs_type) != VECTOR_TYPE
|| !useless_type_conversion_p (TREE_TYPE (lhs_type), rhs1_type))
{
- error ("vector type expected in series expression");
+ error ("vector type expected in %qs", code_name);
debug_generic_expr (lhs_type);
return true;
}
@@ -4116,6 +4129,8 @@ verify_gimple_assign_ternary (gassign *stmt)
return true;
}
+ const char* const code_name = get_tree_code_name (rhs_code);
+
/* First handle operations that involve different types. */
switch (rhs_code)
{
@@ -4128,7 +4143,7 @@ verify_gimple_assign_ternary (gassign *stmt)
|| 2 * TYPE_PRECISION (rhs1_type) > TYPE_PRECISION (lhs_type)
|| TYPE_PRECISION (rhs1_type) != TYPE_PRECISION (rhs2_type))
{
- error ("type mismatch in widening multiply-accumulate expression");
+ error ("type mismatch in %qs", code_name);
debug_generic_expr (lhs_type);
debug_generic_expr (rhs1_type);
debug_generic_expr (rhs2_type);
@@ -4142,9 +4157,9 @@ verify_gimple_assign_ternary (gassign *stmt)
|| maybe_ne (TYPE_VECTOR_SUBPARTS (rhs1_type),
TYPE_VECTOR_SUBPARTS (lhs_type)))
{
- error ("the first argument of a VEC_COND_EXPR must be of a "
+ error ("the first argument of a %qs must be of a "
"boolean vector type of the same number of elements "
- "as the result");
+ "as the result", code_name);
debug_generic_expr (lhs_type);
debug_generic_expr (rhs1_type);
return true;
@@ -4160,7 +4175,7 @@ verify_gimple_assign_ternary (gassign *stmt)
if (!useless_type_conversion_p (lhs_type, rhs2_type)
|| !useless_type_conversion_p (lhs_type, rhs3_type))
{
- error ("type mismatch in conditional expression");
+ error ("type mismatch in %qs", code_name);
debug_generic_expr (lhs_type);
debug_generic_expr (rhs2_type);
debug_generic_expr (rhs3_type);
@@ -4172,7 +4187,7 @@ verify_gimple_assign_ternary (gassign *stmt)
if (!useless_type_conversion_p (lhs_type, rhs1_type)
|| !useless_type_conversion_p (lhs_type, rhs2_type))
{
- error ("type mismatch in vector permute expression");
+ error ("type mismatch in %qs", code_name);
debug_generic_expr (lhs_type);
debug_generic_expr (rhs1_type);
debug_generic_expr (rhs2_type);
@@ -4184,7 +4199,7 @@ verify_gimple_assign_ternary (gassign *stmt)
|| TREE_CODE (rhs2_type) != VECTOR_TYPE
|| TREE_CODE (rhs3_type) != VECTOR_TYPE)
{
- error ("vector types expected in vector permute expression");
+ error ("vector types expected in %qs", code_name);
debug_generic_expr (lhs_type);
debug_generic_expr (rhs1_type);
debug_generic_expr (rhs2_type);
@@ -4199,8 +4214,8 @@ verify_gimple_assign_ternary (gassign *stmt)
|| maybe_ne (TYPE_VECTOR_SUBPARTS (rhs3_type),
TYPE_VECTOR_SUBPARTS (lhs_type)))
{
- error ("vectors with different element number found "
- "in vector permute expression");
+ error ("vectors with different element number found in %qs",
+ code_name);
debug_generic_expr (lhs_type);
debug_generic_expr (rhs1_type);
debug_generic_expr (rhs2_type);
@@ -4215,7 +4230,7 @@ verify_gimple_assign_ternary (gassign *stmt)
!= GET_MODE_BITSIZE (SCALAR_TYPE_MODE
(TREE_TYPE (rhs1_type))))))
{
- error ("invalid mask type in vector permute expression");
+ error ("invalid mask type in %qs", code_name);
debug_generic_expr (lhs_type);
debug_generic_expr (rhs1_type);
debug_generic_expr (rhs2_type);
@@ -4231,7 +4246,7 @@ verify_gimple_assign_ternary (gassign *stmt)
|| 2 * GET_MODE_UNIT_BITSIZE (TYPE_MODE (TREE_TYPE (rhs1_type)))
> GET_MODE_UNIT_BITSIZE (TYPE_MODE (TREE_TYPE (lhs_type))))
{
- error ("type mismatch in sad expression");
+ error ("type mismatch in %qs", code_name);
debug_generic_expr (lhs_type);
debug_generic_expr (rhs1_type);
debug_generic_expr (rhs2_type);
@@ -4243,7 +4258,7 @@ verify_gimple_assign_ternary (gassign *stmt)
|| TREE_CODE (rhs2_type) != VECTOR_TYPE
|| TREE_CODE (rhs3_type) != VECTOR_TYPE)
{
- error ("vector types expected in sad expression");
+ error ("vector types expected in %qs", code_name);
debug_generic_expr (lhs_type);
debug_generic_expr (rhs1_type);
debug_generic_expr (rhs2_type);
@@ -4256,17 +4271,26 @@ verify_gimple_assign_ternary (gassign *stmt)
case BIT_INSERT_EXPR:
if (! useless_type_conversion_p (lhs_type, rhs1_type))
{
- error ("type mismatch in BIT_INSERT_EXPR");
+ error ("type mismatch in %qs", code_name);
debug_generic_expr (lhs_type);
debug_generic_expr (rhs1_type);
return true;
}
if (! ((INTEGRAL_TYPE_P (rhs1_type)
&& INTEGRAL_TYPE_P (rhs2_type))
+ /* Vector element insert. */
|| (VECTOR_TYPE_P (rhs1_type)
- && types_compatible_p (TREE_TYPE (rhs1_type), rhs2_type))))
- {
- error ("not allowed type combination in BIT_INSERT_EXPR");
+ && types_compatible_p (TREE_TYPE (rhs1_type), rhs2_type))
+ /* Aligned sub-vector insert. */
+ || (VECTOR_TYPE_P (rhs1_type)
+ && VECTOR_TYPE_P (rhs2_type)
+ && types_compatible_p (TREE_TYPE (rhs1_type),
+ TREE_TYPE (rhs2_type))
+ && multiple_p (TYPE_VECTOR_SUBPARTS (rhs1_type),
+ TYPE_VECTOR_SUBPARTS (rhs2_type))
+ && multiple_of_p (bitsizetype, rhs3, TYPE_SIZE (rhs2_type)))))
+ {
+ error ("not allowed type combination in %qs", code_name);
debug_generic_expr (rhs1_type);
debug_generic_expr (rhs2_type);
return true;
@@ -4275,13 +4299,13 @@ verify_gimple_assign_ternary (gassign *stmt)
|| ! types_compatible_p (bitsizetype, TREE_TYPE (rhs3))
|| ! tree_fits_uhwi_p (TYPE_SIZE (rhs2_type)))
{
- error ("invalid position or size in BIT_INSERT_EXPR");
+ error ("invalid position or size in %qs", code_name);
return true;
}
if (INTEGRAL_TYPE_P (rhs1_type)
&& !type_has_mode_precision_p (rhs1_type))
{
- error ("BIT_INSERT_EXPR into non-mode-precision operand");
+ error ("%qs into non-mode-precision operand", code_name);
return true;
}
if (INTEGRAL_TYPE_P (rhs1_type))
@@ -4291,7 +4315,7 @@ verify_gimple_assign_ternary (gassign *stmt)
|| (bitpos + TYPE_PRECISION (rhs2_type)
> TYPE_PRECISION (rhs1_type)))
{
- error ("insertion out of range in BIT_INSERT_EXPR");
+ error ("insertion out of range in %qs", code_name);
return true;
}
}
@@ -4301,7 +4325,7 @@ verify_gimple_assign_ternary (gassign *stmt)
unsigned HOST_WIDE_INT bitsize = tree_to_uhwi (TYPE_SIZE (rhs2_type));
if (bitpos % bitsize != 0)
{
- error ("vector insertion not at element boundary");
+ error ("%qs not at element boundary", code_name);
return true;
}
}
@@ -4320,7 +4344,7 @@ verify_gimple_assign_ternary (gassign *stmt)
|| maybe_lt (GET_MODE_SIZE (element_mode (rhs3_type)),
2 * GET_MODE_SIZE (element_mode (rhs1_type))))
{
- error ("type mismatch in dot product reduction");
+ error ("type mismatch in %qs", code_name);
debug_generic_expr (lhs_type);
debug_generic_expr (rhs1_type);
debug_generic_expr (rhs2_type);
@@ -4352,9 +4376,11 @@ verify_gimple_assign_single (gassign *stmt)
tree rhs1_type = TREE_TYPE (rhs1);
bool res = false;
+ const char* const code_name = get_tree_code_name (rhs_code);
+
if (!useless_type_conversion_p (lhs_type, rhs1_type))
{
- error ("non-trivial conversion at assignment");
+ error ("non-trivial conversion in %qs", code_name);
debug_generic_expr (lhs_type);
debug_generic_expr (rhs1_type);
return true;
@@ -4363,7 +4389,8 @@ verify_gimple_assign_single (gassign *stmt)
if (gimple_clobber_p (stmt)
&& !(DECL_P (lhs) || TREE_CODE (lhs) == MEM_REF))
{
- error ("non-decl/MEM_REF LHS in clobber statement");
+ error ("%qs LHS in clobber statement",
+ get_tree_code_name (TREE_CODE (lhs)));
debug_generic_expr (lhs);
return true;
}
@@ -4381,7 +4408,7 @@ verify_gimple_assign_single (gassign *stmt)
tree op = TREE_OPERAND (rhs1, 0);
if (!is_gimple_addressable (op))
{
- error ("invalid operand in unary expression");
+ error ("invalid operand in %qs", code_name);
return true;
}
@@ -4395,7 +4422,7 @@ verify_gimple_assign_single (gassign *stmt)
&& !one_pointer_to_useless_type_conversion_p (TREE_TYPE (rhs1),
TREE_TYPE (op)))
{
- error ("type mismatch in address expression");
+ error ("type mismatch in %qs", code_name);
debug_generic_stmt (TREE_TYPE (rhs1));
debug_generic_stmt (TREE_TYPE (op));
return true;
@@ -4407,7 +4434,7 @@ verify_gimple_assign_single (gassign *stmt)
/* tcc_reference */
case INDIRECT_REF:
- error ("INDIRECT_REF in gimple IL");
+ error ("%qs in gimple IL", code_name);
return true;
case COMPONENT_REF:
@@ -4422,7 +4449,7 @@ verify_gimple_assign_single (gassign *stmt)
if (!is_gimple_reg (lhs)
&& is_gimple_reg_type (TREE_TYPE (lhs)))
{
- error ("invalid rhs for gimple memory store");
+ error ("invalid RHS for gimple memory store: %qs", code_name);
debug_generic_stmt (lhs);
debug_generic_stmt (rhs1);
return true;
@@ -4448,7 +4475,7 @@ verify_gimple_assign_single (gassign *stmt)
&& !is_gimple_reg (rhs1)
&& is_gimple_reg_type (TREE_TYPE (lhs)))
{
- error ("invalid rhs for gimple memory store");
+ error ("invalid RHS for gimple memory store: %qs", code_name);
debug_generic_stmt (lhs);
debug_generic_stmt (rhs1);
return true;
@@ -4482,8 +4509,8 @@ verify_gimple_assign_single (gassign *stmt)
if (!useless_type_conversion_p (TREE_TYPE (rhs1_type),
TREE_TYPE (elt_t)))
{
- error ("incorrect type of vector CONSTRUCTOR"
- " elements");
+ error ("incorrect type of vector %qs elements",
+ code_name);
debug_generic_stmt (rhs1);
return true;
}
@@ -4491,8 +4518,8 @@ verify_gimple_assign_single (gassign *stmt)
* TYPE_VECTOR_SUBPARTS (elt_t),
TYPE_VECTOR_SUBPARTS (rhs1_type)))
{
- error ("incorrect number of vector CONSTRUCTOR"
- " elements");
+ error ("incorrect number of vector %qs elements",
+ code_name);
debug_generic_stmt (rhs1);
return true;
}
@@ -4500,14 +4527,16 @@ verify_gimple_assign_single (gassign *stmt)
else if (!useless_type_conversion_p (TREE_TYPE (rhs1_type),
elt_t))
{
- error ("incorrect type of vector CONSTRUCTOR elements");
+ error ("incorrect type of vector %qs elements",
+ code_name);
debug_generic_stmt (rhs1);
return true;
}
else if (maybe_gt (CONSTRUCTOR_NELTS (rhs1),
TYPE_VECTOR_SUBPARTS (rhs1_type)))
{
- error ("incorrect number of vector CONSTRUCTOR elements");
+ error ("incorrect number of vector %qs elements",
+ code_name);
debug_generic_stmt (rhs1);
return true;
}
@@ -4523,13 +4552,15 @@ verify_gimple_assign_single (gassign *stmt)
|| TREE_CODE (elt_i) != INTEGER_CST
|| compare_tree_int (elt_i, i) != 0))
{
- error ("vector CONSTRUCTOR with non-NULL element index");
+ error ("vector %qs with non-NULL element index",
+ code_name);
debug_generic_stmt (rhs1);
return true;
}
if (!is_gimple_val (elt_v))
{
- error ("vector CONSTRUCTOR element is not a GIMPLE value");
+ error ("vector %qs element is not a GIMPLE value",
+ code_name);
debug_generic_stmt (rhs1);
return true;
}
@@ -4537,7 +4568,7 @@ verify_gimple_assign_single (gassign *stmt)
}
else if (CONSTRUCTOR_NELTS (rhs1) != 0)
{
- error ("non-vector CONSTRUCTOR with elements");
+ error ("non-vector %qs with elements", code_name);
debug_generic_stmt (rhs1);
return true;
}
@@ -4548,7 +4579,7 @@ verify_gimple_assign_single (gassign *stmt)
rhs1 = fold (ASSERT_EXPR_COND (rhs1));
if (rhs1 == boolean_false_node)
{
- error ("ASSERT_EXPR with an always-false condition");
+ error ("%qs with an always-false condition", code_name);
debug_generic_stmt (rhs1);
return true;
}
@@ -4695,7 +4726,7 @@ verify_gimple_switch (gswitch *stmt)
if (CASE_CHAIN (elt))
{
- error ("invalid CASE_CHAIN");
+ error ("invalid %<CASE_CHAIN%>");
debug_generic_expr (elt);
return true;
}
@@ -4780,7 +4811,7 @@ verify_gimple_label (glabel *stmt)
if (!DECL_NONLOCAL (decl) && !FORCED_LABEL (decl)
&& DECL_CONTEXT (decl) != current_function_decl)
{
- error ("label%'s context is not the current function decl");
+ error ("label context is not the current function declaration");
err |= true;
}
@@ -4789,7 +4820,7 @@ verify_gimple_label (glabel *stmt)
&& (uid == -1
|| (*label_to_block_map_for_fn (cfun))[uid] != gimple_bb (stmt)))
{
- error ("incorrect entry in label_to_block_map");
+ error ("incorrect entry in %<label_to_block_map%>");
err |= true;
}
@@ -4906,7 +4937,7 @@ verify_gimple_phi (gphi *phi)
if (!phi_result)
{
- error ("invalid PHI result");
+ error ("invalid %<PHI%> result");
return true;
}
@@ -4915,7 +4946,7 @@ verify_gimple_phi (gphi *phi)
|| (virtual_p
&& SSA_NAME_VAR (phi_result) != gimple_vop (cfun)))
{
- error ("invalid PHI result");
+ error ("invalid %<PHI%> result");
err = true;
}
@@ -4925,7 +4956,7 @@ verify_gimple_phi (gphi *phi)
if (!t)
{
- error ("missing PHI def");
+ error ("missing %<PHI%> def");
err |= true;
continue;
}
@@ -4939,14 +4970,14 @@ verify_gimple_phi (gphi *phi)
|| (!virtual_p
&& !is_gimple_val (t)))
{
- error ("invalid PHI argument");
+ error ("invalid %<PHI%> argument");
debug_generic_expr (t);
err |= true;
}
#ifdef ENABLE_TYPES_CHECKING
if (!useless_type_conversion_p (TREE_TYPE (phi_result), TREE_TYPE (t)))
{
- error ("incompatible types in PHI argument %u", i);
+ error ("incompatible types in %<PHI%> argument %u", i);
debug_generic_stmt (TREE_TYPE (phi_result));
debug_generic_stmt (TREE_TYPE (t));
err |= true;
@@ -5044,7 +5075,7 @@ verify_gimple_in_seq (gimple_seq stmts)
{
timevar_push (TV_TREE_STMT_VERIFY);
if (verify_gimple_in_seq_2 (stmts))
- internal_error ("verify_gimple failed");
+ internal_error ("%<verify_gimple%> failed");
timevar_pop (TV_TREE_STMT_VERIFY);
}
@@ -5101,7 +5132,7 @@ verify_eh_throw_stmt_node (gimple *const &stmt, const int &,
{
if (!visited->contains (stmt))
{
- error ("dead STMT in EH table");
+ error ("dead statement in EH table");
debug_gimple_stmt (stmt);
eh_error_found = true;
}
@@ -5225,6 +5256,14 @@ collect_subblocks (hash_set<tree> *blocks, tree block)
}
}
+/* Disable warnings about missing quoting in GCC diagnostics for
+ the verification errors. Their format strings don't follow
+ GCC diagnostic conventions and trigger an ICE in the end. */
+#if __GNUC__ >= 10
+# pragma GCC diagnostic push
+# pragma GCC diagnostic ignored "-Wformat-diag"
+#endif
+
/* Verify the GIMPLE statements in the CFG of FN. */
DEBUG_FUNCTION void
@@ -5702,6 +5741,9 @@ gimple_verify_flow_info (void)
return err;
}
+#if __GNUC__ >= 10
+# pragma GCC diagnostic pop
+#endif
/* Updates phi nodes after creating a forwarder block joined
by edge FALLTHRU. */
@@ -8890,10 +8932,11 @@ struct cfg_hooks gimple_cfg_hooks = {
};
-/* Split all critical edges. */
+/* Split all critical edges. Split some extra (not necessarily critical) edges
+ if FOR_EDGE_INSERTION_P is true. */
unsigned int
-split_critical_edges (void)
+split_critical_edges (bool for_edge_insertion_p /* = false */)
{
basic_block bb;
edge e;
@@ -8916,11 +8959,12 @@ split_critical_edges (void)
end by control flow statements, such as RESX.
Go ahead and split them too. This matches the logic in
gimple_find_edge_insert_loc. */
- else if ((!single_pred_p (e->dest)
- || !gimple_seq_empty_p (phi_nodes (e->dest))
- || e->dest == EXIT_BLOCK_PTR_FOR_FN (cfun))
+ else if (for_edge_insertion_p
+ && (!single_pred_p (e->dest)
+ || !gimple_seq_empty_p (phi_nodes (e->dest))
+ || e->dest == EXIT_BLOCK_PTR_FOR_FN (cfun))
&& e->src != ENTRY_BLOCK_PTR_FOR_FN (cfun)
- && !(e->flags & EDGE_ABNORMAL))
+ && !(e->flags & EDGE_ABNORMAL))
{
gimple_stmt_iterator gsi;
@@ -9404,13 +9448,13 @@ do_warn_unused_result (gimple_seq seq)
if (fdecl)
warning_at (loc, OPT_Wunused_result,
- "ignoring return value of %qD, "
- "declared with attribute warn_unused_result",
+ "ignoring return value of %qD "
+ "declared with attribute %<warn_unused_result%>",
fdecl);
else
warning_at (loc, OPT_Wunused_result,
"ignoring return value of function "
- "declared with attribute warn_unused_result");
+ "declared with attribute %<warn_unused_result%>");
}
break;
diff --git a/gcc/tree-cfg.h b/gcc/tree-cfg.h
index 212f5ff..836f8e8 100644
--- a/gcc/tree-cfg.h
+++ b/gcc/tree-cfg.h
@@ -105,7 +105,7 @@ extern void extract_true_false_edges_from_block (basic_block, edge *, edge *);
extern tree find_case_label_for_value (const gswitch *switch_stmt, tree val);
extern edge find_taken_edge_switch_expr (const gswitch *switch_stmt, tree val);
extern unsigned int execute_fixup_cfg (void);
-extern unsigned int split_critical_edges (void);
+extern unsigned int split_critical_edges (bool for_edge_insertion_p = false);
extern basic_block insert_cond_bb (basic_block, gimple *, gimple *,
profile_probability);
extern bool gimple_find_sub_bbs (gimple_seq, gimple_stmt_iterator *);
@@ -128,4 +128,11 @@ should_remove_lhs_p (tree lhs)
&& !TREE_ADDRESSABLE (TREE_TYPE (lhs)));
}
+
+inline unsigned int
+split_edges_for_insertion ()
+{
+ return split_critical_edges (/*for_edge_insertion_p=*/true);
+}
+
#endif /* _TREE_CFG_H */
diff --git a/gcc/tree-chrec.c b/gcc/tree-chrec.c
index 813b87f..f50fd20 100644
--- a/gcc/tree-chrec.c
+++ b/gcc/tree-chrec.c
@@ -35,6 +35,8 @@ along with GCC; see the file COPYING3. If not see
#include "tree-ssa-loop-ivopts.h"
#include "tree-ssa-loop-niter.h"
#include "tree-chrec.h"
+#include "gimple.h"
+#include "tree-ssa-loop.h"
#include "dumpfile.h"
#include "params.h"
#include "tree-scalar-evolution.h"
@@ -959,6 +961,9 @@ chrec_contains_symbols (const_tree chrec, hash_set<const_tree> &visited,
&& flow_loop_nested_p (get_chrec_loop (chrec), loop))
return true;
+ if (visited.add (chrec))
+ return false;
+
n = TREE_OPERAND_LENGTH (chrec);
for (i = 0; i < n; i++)
if (chrec_contains_symbols (TREE_OPERAND (chrec, i), visited, loop))
@@ -978,6 +983,63 @@ chrec_contains_symbols (const_tree chrec, struct loop* loop)
return chrec_contains_symbols (chrec, visited, loop);
}
+/* Return true when CHREC contains symbolic names defined in
+ LOOP_NB. */
+
+static bool
+chrec_contains_symbols_defined_in_loop (const_tree chrec, unsigned loop_nb,
+ hash_set<const_tree> &visited)
+{
+ int i, n;
+
+ if (chrec == NULL_TREE)
+ return false;
+
+ if (is_gimple_min_invariant (chrec))
+ return false;
+
+ if (TREE_CODE (chrec) == SSA_NAME)
+ {
+ gimple *def;
+ loop_p def_loop, loop;
+
+ if (SSA_NAME_IS_DEFAULT_DEF (chrec))
+ return false;
+
+ def = SSA_NAME_DEF_STMT (chrec);
+ def_loop = loop_containing_stmt (def);
+ loop = get_loop (cfun, loop_nb);
+
+ if (def_loop == NULL)
+ return false;
+
+ if (loop == def_loop || flow_loop_nested_p (loop, def_loop))
+ return true;
+
+ return false;
+ }
+
+ if (visited.add (chrec))
+ return false;
+
+ n = TREE_OPERAND_LENGTH (chrec);
+ for (i = 0; i < n; i++)
+ if (chrec_contains_symbols_defined_in_loop (TREE_OPERAND (chrec, i),
+ loop_nb, visited))
+ return true;
+ return false;
+}
+
+/* Return true when CHREC contains symbolic names defined in
+ LOOP_NB. */
+
+bool
+chrec_contains_symbols_defined_in_loop (const_tree chrec, unsigned loop_nb)
+{
+ hash_set<const_tree> visited;
+ return chrec_contains_symbols_defined_in_loop (chrec, loop_nb, visited);
+}
+
/* Determines whether the chrec contains undetermined coefficients. */
static bool
@@ -1026,6 +1088,9 @@ tree_contains_chrecs (const_tree expr, int *size, hash_set<const_tree> &visited)
if (tree_is_chrec (expr))
return true;
+ if (visited.add (expr))
+ return false;
+
n = TREE_OPERAND_LENGTH (expr);
for (i = 0; i < n; i++)
if (tree_contains_chrecs (TREE_OPERAND (expr, i), size, visited))
diff --git a/gcc/tree-chrec.h b/gcc/tree-chrec.h
index dbbc1b1..3b5c090 100644
--- a/gcc/tree-chrec.h
+++ b/gcc/tree-chrec.h
@@ -23,11 +23,14 @@ along with GCC; see the file COPYING3. If not see
/* The following trees are unique elements. Thus the comparison of another
element to these elements should be done on the pointer to these trees,
- and not on their value. */
+ and not on their value.
-extern tree chrec_not_analyzed_yet;
-extern GTY(()) tree chrec_dont_know;
-extern GTY(()) tree chrec_known;
+ extern tree chrec_not_analyzed_yet;
+ extern tree chrec_dont_know;
+ extern tree chrec_known;
+
+ chrec_not_analyzed_yet is NULL_TREE and the others are defined
+ in global_trees[]. */
/* After having added an automatically generated element, please
include it in the following function. */
diff --git a/gcc/tree-core.h b/gcc/tree-core.h
index 552196b..9ea8638 100644
--- a/gcc/tree-core.h
+++ b/gcc/tree-core.h
@@ -306,13 +306,19 @@ enum omp_clause_code {
OpenMP clause: map ({alloc:,to:,from:,tofrom:,}variable-list). */
OMP_CLAUSE_MAP,
- /* OpenACC clause: use_device (variable_list).
+ /* OpenACC clause: use_device (variable-list).
OpenMP clause: use_device_ptr (variable-list). */
OMP_CLAUSE_USE_DEVICE_PTR,
/* OpenMP clause: is_device_ptr (variable-list). */
OMP_CLAUSE_IS_DEVICE_PTR,
+ /* OpenMP clause: inclusive (variable-list). */
+ OMP_CLAUSE_INCLUSIVE,
+
+ /* OpenMP clause: exclusive (variable-list). */
+ OMP_CLAUSE_EXCLUSIVE,
+
/* Internal structure to hold OpenACC cache directive's variable-list.
#pragma acc cache (variable-list). */
OMP_CLAUSE__CACHE_,
@@ -343,6 +349,12 @@ enum omp_clause_code {
/* Internal clause: temporary for task reductions. */
OMP_CLAUSE__REDUCTEMP_,
+ /* Internal clause: temporary for lastprivate(conditional:). */
+ OMP_CLAUSE__CONDTEMP_,
+
+ /* Internal clause: temporary for inscan reductions. */
+ OMP_CLAUSE__SCANTEMP_,
+
/* OpenACC/OpenMP clause: if (scalar-expression). */
OMP_CLAUSE_IF,
@@ -749,6 +761,9 @@ enum tree_index {
TI_CURRENT_TARGET_PRAGMA,
TI_CURRENT_OPTIMIZE_PRAGMA,
+ TI_CHREC_DONT_KNOW,
+ TI_CHREC_KNOWN,
+
TI_MAX
};
@@ -1565,6 +1580,8 @@ struct GTY(()) tree_type_common {
ENUM_BITFIELD(machine_mode) mode : 8;
+ /* TYPE_STRING_FLAG for INTEGER_TYPE and ARRAY_TYPE.
+ TYPE_CXX_ODR_P for RECORD_TYPE and UNION_TYPE. */
unsigned string_flag : 1;
unsigned lang_flag_0 : 1;
unsigned lang_flag_1 : 1;
@@ -1683,6 +1700,7 @@ struct GTY(()) tree_decl_common {
/* In a VAR_DECL and PARM_DECL, this is DECL_READ_P. */
unsigned decl_read_flag : 1;
/* In a VAR_DECL or RESULT_DECL, this is DECL_NONSHAREABLE. */
+ /* In a PARM_DECL, this is DECL_HIDDEN_STRING_LENGTH. */
unsigned decl_nonshareable_flag : 1;
/* DECL_OFFSET_ALIGN, used only for FIELD_DECLs. */
diff --git a/gcc/tree-data-ref.c b/gcc/tree-data-ref.c
index 67b960d..4dc03ef 100644
--- a/gcc/tree-data-ref.c
+++ b/gcc/tree-data-ref.c
@@ -1271,7 +1271,7 @@ create_data_ref (edge nest, loop_p loop, tree memref, gimple *stmt,
return dr;
}
-/* A helper function computes order between two tree epxressions T1 and T2.
+/* A helper function computes order between two tree expressions T1 and T2.
This is used in comparator functions sorting objects based on the order
of tree expressions. The function returns -1, 0, or 1. */
diff --git a/gcc/tree-eh.c b/gcc/tree-eh.c
index c806348..23c56b5 100644
--- a/gcc/tree-eh.c
+++ b/gcc/tree-eh.c
@@ -4728,6 +4728,14 @@ make_pass_cleanup_eh (gcc::context *ctxt)
return new pass_cleanup_eh (ctxt);
}
+/* Disable warnings about missing quoting in GCC diagnostics for
+ the verification errors. Their format strings don't follow GCC
+ diagnostic conventions but are only used for debugging. */
+#if __GNUC__ >= 10
+# pragma GCC diagnostic push
+# pragma GCC diagnostic ignored "-Wformat-diag"
+#endif
+
/* Verify that BB containing STMT as the last statement, has precisely the
edge that make_eh_edges would create. */
@@ -4874,3 +4882,7 @@ verify_eh_dispatch_edge (geh_dispatch *stmt)
return false;
}
+
+#if __GNUC__ >= 10
+# pragma GCC diagnostic pop
+#endif
diff --git a/gcc/tree-if-conv.c b/gcc/tree-if-conv.c
index ec2db00..98566e3 100644
--- a/gcc/tree-if-conv.c
+++ b/gcc/tree-if-conv.c
@@ -3066,10 +3066,12 @@ tree_if_conversion (struct loop *loop, vec<gimple *> *preds)
ifcvt_local_dce (loop->header);
/* Perform local CSE, this esp. helps the vectorizer analysis if loads
- and stores are involved.
+ and stores are involved. CSE only the loop body, not the entry
+ PHIs, those are to be kept in sync with the non-if-converted copy.
??? We'll still keep dead stores though. */
exit_bbs = BITMAP_ALLOC (NULL);
bitmap_set_bit (exit_bbs, single_exit (loop)->dest->index);
+ bitmap_set_bit (exit_bbs, loop->latch->index);
todo |= do_rpo_vn (cfun, loop_preheader_edge (loop), exit_bbs);
BITMAP_FREE (exit_bbs);
diff --git a/gcc/tree-inline.c b/gcc/tree-inline.c
index 2d314a7..42e4597 100644
--- a/gcc/tree-inline.c
+++ b/gcc/tree-inline.c
@@ -259,6 +259,11 @@ remap_ssa_name (tree name, copy_body_data *id)
struct ptr_info_def *new_pi = get_ptr_info (new_tree);
new_pi->pt = pi->pt;
}
+ /* So can range-info. */
+ if (!POINTER_TYPE_P (TREE_TYPE (name))
+ && SSA_NAME_RANGE_INFO (name))
+ duplicate_ssa_name_range_info (new_tree, SSA_NAME_RANGE_TYPE (name),
+ SSA_NAME_RANGE_INFO (name));
return new_tree;
}
@@ -292,6 +297,11 @@ remap_ssa_name (tree name, copy_body_data *id)
struct ptr_info_def *new_pi = get_ptr_info (new_tree);
new_pi->pt = pi->pt;
}
+ /* So can range-info. */
+ if (!POINTER_TYPE_P (TREE_TYPE (name))
+ && SSA_NAME_RANGE_INFO (name))
+ duplicate_ssa_name_range_info (new_tree, SSA_NAME_RANGE_TYPE (name),
+ SSA_NAME_RANGE_INFO (name));
if (SSA_NAME_IS_DEFAULT_DEF (name))
{
/* By inlining function having uninitialized variable, we might
@@ -1101,7 +1111,7 @@ remap_gimple_op_r (tree *tp, int *walk_subtrees, void *data)
/* Otherwise, just copy the node. Note that copy_tree_r already
knows not to copy VAR_DECLs, etc., so this is safe. */
- if (TREE_CODE (*tp) == MEM_REF)
+ if (TREE_CODE (*tp) == MEM_REF && !id->do_not_fold)
{
/* We need to re-canonicalize MEM_REFs from inline substitutions
that can happen when a pointer argument is an ADDR_EXPR.
@@ -1327,11 +1337,11 @@ copy_tree_body_r (tree *tp, int *walk_subtrees, void *data)
tree type = TREE_TYPE (*tp);
tree ptr = id->do_not_unshare ? *n : unshare_expr (*n);
tree old = *tp;
- *tp = gimple_fold_indirect_ref (ptr);
+ *tp = id->do_not_fold ? NULL : gimple_fold_indirect_ref (ptr);
if (! *tp)
{
type = remap_type (type, id);
- if (TREE_CODE (ptr) == ADDR_EXPR)
+ if (TREE_CODE (ptr) == ADDR_EXPR && !id->do_not_fold)
{
*tp
= fold_indirect_ref_1 (EXPR_LOCATION (ptr), type, ptr);
@@ -1360,7 +1370,7 @@ copy_tree_body_r (tree *tp, int *walk_subtrees, void *data)
return NULL;
}
}
- else if (TREE_CODE (*tp) == MEM_REF)
+ else if (TREE_CODE (*tp) == MEM_REF && !id->do_not_fold)
{
/* We need to re-canonicalize MEM_REFs from inline substitutions
that can happen when a pointer argument is an ADDR_EXPR.
@@ -1432,7 +1442,8 @@ copy_tree_body_r (tree *tp, int *walk_subtrees, void *data)
/* Handle the case where we substituted an INDIRECT_REF
into the operand of the ADDR_EXPR. */
- if (TREE_CODE (TREE_OPERAND (*tp, 0)) == INDIRECT_REF)
+ if (TREE_CODE (TREE_OPERAND (*tp, 0)) == INDIRECT_REF
+ && !id->do_not_fold)
{
tree t = TREE_OPERAND (TREE_OPERAND (*tp, 0), 0);
if (TREE_TYPE (t) != TREE_TYPE (*tp))
@@ -1637,6 +1648,12 @@ remap_gimple_stmt (gimple *stmt, copy_body_data *id)
gimple_omp_ordered_clauses (as_a <gomp_ordered *> (stmt)));
break;
+ case GIMPLE_OMP_SCAN:
+ s1 = remap_gimple_seq (gimple_omp_body (stmt), id);
+ copy = gimple_build_omp_scan
+ (s1, gimple_omp_scan_clauses (as_a <gomp_scan *> (stmt)));
+ break;
+
case GIMPLE_OMP_SECTION:
s1 = remap_gimple_seq (gimple_omp_body (stmt), id);
copy = gimple_build_omp_section (s1);
@@ -1740,6 +1757,18 @@ remap_gimple_stmt (gimple *stmt, copy_body_data *id)
return NULL;
}
}
+
+ /* We do not allow CLOBBERs of handled components. In case
+ returned value is stored via such handled component, remove
+ the clobber so stmt verifier is happy. */
+ if (gimple_clobber_p (stmt)
+ && TREE_CODE (gimple_assign_lhs (stmt)) == RESULT_DECL)
+ {
+ tree remapped = remap_decl (gimple_assign_lhs (stmt), id);
+ if (!DECL_P (remapped)
+ && TREE_CODE (remapped) != MEM_REF)
+ return NULL;
+ }
if (gimple_debug_bind_p (stmt))
{
@@ -2661,6 +2690,7 @@ initialize_cfun (tree new_fndecl, tree callee_fndecl, profile_count count)
cfun->va_list_gpr_size = src_cfun->va_list_gpr_size;
cfun->va_list_fpr_size = src_cfun->va_list_fpr_size;
cfun->has_nonlocal_label = src_cfun->has_nonlocal_label;
+ cfun->calls_eh_return = src_cfun->calls_eh_return;
cfun->stdarg = src_cfun->stdarg;
cfun->after_inlining = src_cfun->after_inlining;
cfun->can_throw_non_call_exceptions
@@ -3891,7 +3921,7 @@ function_attribute_inlinable_p (const_tree fndecl)
for (a = DECL_ATTRIBUTES (fndecl); a; a = TREE_CHAIN (a))
{
- const_tree name = TREE_PURPOSE (a);
+ const_tree name = get_attribute_name (a);
int i;
for (i = 0; targetm.attribute_table[i].name != NULL; i++)
@@ -4363,6 +4393,7 @@ estimate_num_insns (gimple *stmt, eni_weights *weights)
case GIMPLE_OMP_MASTER:
case GIMPLE_OMP_TASKGROUP:
case GIMPLE_OMP_ORDERED:
+ case GIMPLE_OMP_SCAN:
case GIMPLE_OMP_SECTION:
case GIMPLE_OMP_SECTIONS:
case GIMPLE_OMP_SINGLE:
@@ -4614,7 +4645,7 @@ expand_call_inline (basic_block bb, gimple *stmt, copy_body_data *id)
/* PR 20090218-1_0.c. Body can be provided by another module. */
&& (reason != CIF_BODY_NOT_AVAILABLE || !flag_generate_lto))
{
- error ("inlining failed in call to always_inline %q+F: %s", fn,
+ error ("inlining failed in call to %<always_inline%> %q+F: %s", fn,
cgraph_inline_failed_string (reason));
if (gimple_location (stmt) != UNKNOWN_LOCATION)
inform (gimple_location (stmt), "called from here");
@@ -4777,6 +4808,7 @@ expand_call_inline (basic_block bb, gimple *stmt, copy_body_data *id)
src_properties = id->src_cfun->curr_properties & prop_mask;
if (src_properties != prop_mask)
dst_cfun->curr_properties &= src_properties | ~prop_mask;
+ dst_cfun->calls_eh_return |= id->src_cfun->calls_eh_return;
gcc_assert (!id->src_cfun->after_inlining);
@@ -6221,11 +6253,11 @@ tree_function_versioning (tree old_decl, tree new_decl,
in the debug info that var (whole DECL_ORIGIN is the parm
PARM_DECL) is optimized away, but could be looked up at the
call site as value of D#X there. */
- tree var = vars, vexpr;
+ tree vexpr;
gimple_stmt_iterator cgsi
= gsi_after_labels (single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun)));
gimple *def_temp;
- var = vars;
+ tree var = vars;
i = vec_safe_length (*debug_args);
do
{
@@ -6370,6 +6402,7 @@ copy_fn (tree fn, tree& parms, tree& result)
since front-end specific mechanisms may rely on sharing. */
id.regimplify = false;
id.do_not_unshare = true;
+ id.do_not_fold = true;
/* We're not inside any EH region. */
id.eh_lp_nr = 0;
diff --git a/gcc/tree-inline.h b/gcc/tree-inline.h
index 4c954a0..3ede89e 100644
--- a/gcc/tree-inline.h
+++ b/gcc/tree-inline.h
@@ -113,6 +113,9 @@ struct copy_body_data
/* True if trees may not be unshared. */
bool do_not_unshare;
+ /* True if trees should not be folded during the copying. */
+ bool do_not_fold;
+
/* True if new declarations may not be created during type remapping. */
bool prevent_decl_creation_for_types;
diff --git a/gcc/tree-into-ssa.c b/gcc/tree-into-ssa.c
index 061521d..f2a91a1 100644
--- a/gcc/tree-into-ssa.c
+++ b/gcc/tree-into-ssa.c
@@ -2425,6 +2425,12 @@ pass_build_ssa::execute (function *fun)
bitmap_head *dfs;
basic_block bb;
+ /* Increase the set of variables we can rewrite into SSA form
+ by clearing TREE_ADDRESSABLE and setting DECL_GIMPLE_REG_P
+ and transform the IL to support this. */
+ if (optimize)
+ execute_update_addresses_taken ();
+
/* Initialize operand data structures. */
init_ssa_operands (fun);
@@ -3304,7 +3310,7 @@ update_ssa (unsigned update_flags)
if (SSA_NAME_IN_FREE_LIST (use))
{
- error ("statement uses released SSA name:");
+ error ("statement uses released SSA name");
debug_gimple_stmt (stmt);
fprintf (stderr, "The use of ");
print_generic_expr (stderr, use);
diff --git a/gcc/tree-loop-distribution.c b/gcc/tree-loop-distribution.c
index 3d8f13c..3881aaf 100644
--- a/gcc/tree-loop-distribution.c
+++ b/gcc/tree-loop-distribution.c
@@ -115,6 +115,7 @@ along with GCC; see the file COPYING3. If not see
#include "params.h"
#include "tree-vectorizer.h"
#include "tree-eh.h"
+#include "gimple-fold.h"
#define MAX_DATAREFS_NUM \
@@ -635,6 +636,7 @@ struct partition
bitmap stmts;
/* True if the partition defines variable which is used outside of loop. */
bool reduction_p;
+ location_t loc;
enum partition_kind kind;
enum partition_type type;
/* Data references in the partition. */
@@ -652,7 +654,9 @@ partition_alloc (void)
partition *partition = XCNEW (struct partition);
partition->stmts = BITMAP_ALLOC (NULL);
partition->reduction_p = false;
+ partition->loc = UNKNOWN_LOCATION;
partition->kind = PKIND_NORMAL;
+ partition->type = PTYPE_PARALLEL;
partition->datarefs = BITMAP_ALLOC (NULL);
return partition;
}
@@ -1027,7 +1031,9 @@ generate_memset_builtin (struct loop *loop, partition *partition)
fn = build_fold_addr_expr (builtin_decl_implicit (BUILT_IN_MEMSET));
fn_call = gimple_build_call (fn, 3, mem, val, nb_bytes);
+ gimple_set_location (fn_call, partition->loc);
gsi_insert_after (&gsi, fn_call, GSI_CONTINUE_LINKING);
+ fold_stmt (&gsi);
if (dump_file && (dump_flags & TDF_DETAILS))
{
@@ -1070,7 +1076,9 @@ generate_memcpy_builtin (struct loop *loop, partition *partition)
false, GSI_CONTINUE_LINKING);
fn = build_fold_addr_expr (builtin_decl_implicit (kind));
fn_call = gimple_build_call (fn, 3, dest, src, nb_bytes);
+ gimple_set_location (fn_call, partition->loc);
gsi_insert_after (&gsi, fn_call, GSI_CONTINUE_LINKING);
+ fold_stmt (&gsi);
if (dump_file && (dump_flags & TDF_DETAILS))
{
@@ -1096,15 +1104,13 @@ destroy_loop (struct loop *loop)
gimple_stmt_iterator dst_gsi = gsi_after_labels (exit->dest);
bool safe_p = single_pred_p (exit->dest);
- i = nbbs;
- do
+ for (unsigned i = 0; i < nbbs; ++i)
{
/* We have made sure to not leave any dangling uses of SSA
names defined in the loop. With the exception of virtuals.
Make sure we replace all uses of virtual defs that will remain
outside of the loop with the bare symbol as delete_basic_block
will release them. */
- --i;
for (gphi_iterator gsi = gsi_start_phis (bbs[i]); !gsi_end_p (gsi);
gsi_next (&gsi))
{
@@ -1139,7 +1145,6 @@ destroy_loop (struct loop *loop)
gsi_next (&gsi);
}
}
- while (i != 0);
redirect_edge_pred (exit, src);
exit->flags &= ~(EDGE_TRUE_VALUE|EDGE_FALSE_VALUE);
@@ -1653,9 +1658,11 @@ classify_builtin_ldst (loop_p loop, struct graph *rdg, partition *partition,
/* Classifies the builtin kind we can generate for PARTITION of RDG and LOOP.
For the moment we detect memset, memcpy and memmove patterns. Bitmap
- STMT_IN_ALL_PARTITIONS contains statements belonging to all partitions. */
+ STMT_IN_ALL_PARTITIONS contains statements belonging to all partitions.
+ Returns true if there is a reduction in all partitions and we
+ possibly did not mark PARTITION as having one for this reason. */
-static void
+static bool
classify_partition (loop_p loop, struct graph *rdg, partition *partition,
bitmap stmt_in_all_partitions)
{
@@ -1683,31 +1690,36 @@ classify_partition (loop_p loop, struct graph *rdg, partition *partition,
to all partitions. In such case, reduction will be computed
correctly no matter how partitions are fused/distributed. */
if (!bitmap_bit_p (stmt_in_all_partitions, i))
- {
- partition->reduction_p = true;
- return;
- }
- has_reduction = true;
+ partition->reduction_p = true;
+ else
+ has_reduction = true;
}
}
+ /* Simple workaround to prevent classifying the partition as builtin
+ if it contains any use outside of loop. For the case where all
+ partitions have the reduction this simple workaround is delayed
+ to only affect the last partition. */
+ if (partition->reduction_p)
+ return has_reduction;
+
/* Perform general partition disqualification for builtins. */
if (volatiles_p
- /* Simple workaround to prevent classifying the partition as builtin
- if it contains any use outside of loop. */
- || has_reduction
|| !flag_tree_loop_distribute_patterns)
- return;
+ return has_reduction;
/* Find single load/store data references for builtin partition. */
if (!find_single_drs (loop, rdg, partition, &single_st, &single_ld))
- return;
+ return has_reduction;
+
+ partition->loc = gimple_location (DR_STMT (single_st));
/* Classify the builtin kind. */
if (single_ld == NULL)
classify_builtin_st (loop, partition, single_st);
else
classify_builtin_ldst (loop, rdg, partition, single_st, single_ld);
+ return has_reduction;
}
/* Returns true when PARTITION1 and PARTITION2 access the same memory
@@ -2769,12 +2781,12 @@ finalize_partitions (struct loop *loop, vec<struct partition *> *partitions,
static int
distribute_loop (struct loop *loop, vec<gimple *> stmts,
- control_dependences *cd, int *nb_calls, bool *destroy_p)
+ control_dependences *cd, int *nb_calls, bool *destroy_p,
+ bool only_patterns_p)
{
ddrs_table = new hash_table<ddr_hasher> (389);
struct graph *rdg;
partition *partition;
- bool any_builtin;
int i, nbp;
*destroy_p = false;
@@ -2834,16 +2846,18 @@ distribute_loop (struct loop *loop, vec<gimple *> stmts,
for (i = 1; partitions.iterate (i, &partition); ++i)
bitmap_and_into (stmt_in_all_partitions, partitions[i]->stmts);
- any_builtin = false;
+ bool any_builtin = false;
+ bool reduction_in_all = false;
FOR_EACH_VEC_ELT (partitions, i, partition)
{
- classify_partition (loop, rdg, partition, stmt_in_all_partitions);
+ reduction_in_all
+ |= classify_partition (loop, rdg, partition, stmt_in_all_partitions);
any_builtin |= partition_builtin_p (partition);
}
/* If we are only distributing patterns but did not detect any,
simply bail out. */
- if (!flag_tree_loop_distribution
+ if (only_patterns_p
&& !any_builtin)
{
nbp = 0;
@@ -2855,7 +2869,7 @@ distribute_loop (struct loop *loop, vec<gimple *> stmts,
a loop into pieces, separated by builtin calls. That is, we
only want no or a single loop body remaining. */
struct partition *into;
- if (!flag_tree_loop_distribution)
+ if (only_patterns_p)
{
for (i = 0; partitions.iterate (i, &into); ++i)
if (!partition_builtin_p (into))
@@ -2912,6 +2926,21 @@ distribute_loop (struct loop *loop, vec<gimple *> stmts,
i--;
}
+ /* Put a non-builtin partition last if we need to preserve a reduction.
+ ??? This is a workaround that makes sort_partitions_by_post_order do
+ the correct thing while in reality it should sort each component
+ separately and then put the component with a reduction or a non-builtin
+ last. */
+ if (reduction_in_all
+ && partition_builtin_p (partitions.last()))
+ FOR_EACH_VEC_ELT (partitions, i, partition)
+ if (!partition_builtin_p (partition))
+ {
+ partitions.unordered_remove (i);
+ partitions.quick_push (partition);
+ break;
+ }
+
/* Build the partition dependency graph and fuse partitions in strong
connected component. */
if (partitions.length () > 1)
@@ -2932,6 +2961,21 @@ distribute_loop (struct loop *loop, vec<gimple *> stmts,
finalize_partitions (loop, &partitions, &alias_ddrs);
+ /* If there is a reduction in all partitions make sure the last one
+ is not classified for builtin code generation. */
+ if (reduction_in_all)
+ {
+ partition = partitions.last ();
+ if (only_patterns_p
+ && partition_builtin_p (partition)
+ && !partition_builtin_p (partitions[0]))
+ {
+ nbp = 0;
+ goto ldist_done;
+ }
+ partition->kind = PKIND_NORMAL;
+ }
+
nbp = partitions.length ();
if (nbp == 0
|| (nbp == 1 && !partition_builtin_p (partitions[0]))
@@ -3085,7 +3129,6 @@ prepare_perfect_loop_nest (struct loop *loop)
&& loop_outer (outer)
&& outer->inner == loop && loop->next == NULL
&& single_exit (outer)
- && optimize_loop_for_speed_p (outer)
&& !chrec_contains_symbols_defined_in_loop (niters, outer->num)
&& (niters = number_of_latch_executions (outer)) != NULL_TREE
&& niters != chrec_dont_know)
@@ -3139,9 +3182,11 @@ pass_loop_distribution::execute (function *fun)
walking to innermost loops. */
FOR_EACH_LOOP (loop, LI_ONLY_INNERMOST)
{
- /* Don't distribute multiple exit edges loop, or cold loop. */
+ /* Don't distribute multiple exit edges loop, or cold loop when
+ not doing pattern detection. */
if (!single_exit (loop)
- || !optimize_loop_for_speed_p (loop))
+ || (!flag_tree_loop_distribute_patterns
+ && !optimize_loop_for_speed_p (loop)))
continue;
/* Don't distribute loop if niters is unknown. */
@@ -3169,9 +3214,10 @@ pass_loop_distribution::execute (function *fun)
bool destroy_p;
int nb_generated_loops, nb_generated_calls;
- nb_generated_loops = distribute_loop (loop, work_list, cd,
- &nb_generated_calls,
- &destroy_p);
+ nb_generated_loops
+ = distribute_loop (loop, work_list, cd, &nb_generated_calls,
+ &destroy_p, (!optimize_loop_for_speed_p (loop)
+ || !flag_tree_loop_distribution));
if (destroy_p)
loops_to_be_destroyed.safe_push (loop);
diff --git a/gcc/tree-nested.c b/gcc/tree-nested.c
index 3fe23cc..e703cd9 100644
--- a/gcc/tree-nested.c
+++ b/gcc/tree-nested.c
@@ -1348,6 +1348,8 @@ convert_nonlocal_omp_clauses (tree *pclauses, struct walk_stmt_info *wi)
case OMP_CLAUSE_AUTO:
case OMP_CLAUSE_IF_PRESENT:
case OMP_CLAUSE_FINALIZE:
+ case OMP_CLAUSE__CONDTEMP_:
+ case OMP_CLAUSE__SCANTEMP_:
break;
/* The following clause belongs to the OpenACC cache directive, which
@@ -1618,6 +1620,7 @@ convert_nonlocal_reference_stmt (gimple_stmt_iterator *gsi, bool *handled_ops_p,
case GIMPLE_OMP_SECTION:
case GIMPLE_OMP_MASTER:
case GIMPLE_OMP_ORDERED:
+ case GIMPLE_OMP_SCAN:
walk_body (convert_nonlocal_reference_stmt, convert_nonlocal_reference_op,
info, gimple_omp_body_ptr (stmt));
break;
@@ -2075,6 +2078,8 @@ convert_local_omp_clauses (tree *pclauses, struct walk_stmt_info *wi)
case OMP_CLAUSE_AUTO:
case OMP_CLAUSE_IF_PRESENT:
case OMP_CLAUSE_FINALIZE:
+ case OMP_CLAUSE__CONDTEMP_:
+ case OMP_CLAUSE__SCANTEMP_:
break;
/* The following clause belongs to the OpenACC cache directive, which
@@ -2320,6 +2325,7 @@ convert_local_reference_stmt (gimple_stmt_iterator *gsi, bool *handled_ops_p,
case GIMPLE_OMP_SECTION:
case GIMPLE_OMP_MASTER:
case GIMPLE_OMP_ORDERED:
+ case GIMPLE_OMP_SCAN:
walk_body (convert_local_reference_stmt, convert_local_reference_op,
info, gimple_omp_body_ptr (stmt));
break;
@@ -2829,6 +2835,7 @@ convert_gimple_call (gimple_stmt_iterator *gsi, bool *handled_ops_p,
case GIMPLE_OMP_MASTER:
case GIMPLE_OMP_TASKGROUP:
case GIMPLE_OMP_ORDERED:
+ case GIMPLE_OMP_SCAN:
case GIMPLE_OMP_CRITICAL:
walk_body (convert_gimple_call, NULL, info, gimple_omp_body_ptr (stmt));
break;
diff --git a/gcc/tree-parloops.c b/gcc/tree-parloops.c
index 968368f..6b8c8cd 100644
--- a/gcc/tree-parloops.c
+++ b/gcc/tree-parloops.c
@@ -2794,8 +2794,16 @@ try_create_reduction_list (loop_p loop,
gimple *reduc_phi;
tree val = PHI_ARG_DEF_FROM_EDGE (phi, exit);
- if (TREE_CODE (val) == SSA_NAME && !virtual_operand_p (val))
+ if (!virtual_operand_p (val))
{
+ if (TREE_CODE (val) != SSA_NAME)
+ {
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ fprintf (dump_file,
+ " FAILED: exit PHI argument invariant.\n");
+ return false;
+ }
+
if (dump_file && (dump_flags & TDF_DETAILS))
{
fprintf (dump_file, "phi is ");
@@ -3044,11 +3052,11 @@ oacc_entry_exit_ok_1 (bitmap in_loop_bbs, vec<basic_block> region_bbs,
{
use_operand_p use_p;
gimple *use_stmt;
+ struct reduction_info *red;
single_imm_use (lhs, &use_p, &use_stmt);
- if (gimple_code (use_stmt) == GIMPLE_PHI)
+ if (gimple_code (use_stmt) == GIMPLE_PHI
+ && (red = reduction_phi (reduction_list, use_stmt)))
{
- struct reduction_info *red;
- red = reduction_phi (reduction_list, use_stmt);
tree val = PHI_RESULT (red->keep_res);
if (has_single_use (val))
{
diff --git a/gcc/tree-predcom.c b/gcc/tree-predcom.c
index 1870645..8e83a71 100644
--- a/gcc/tree-predcom.c
+++ b/gcc/tree-predcom.c
@@ -1713,7 +1713,7 @@ is_inv_store_elimination_chain (struct loop *loop, chain_p chain)
gcc_assert (!chain->has_max_use_after);
- /* If loop iterates for unknown times or fewer times than chain->lenght,
+ /* If loop iterates for unknown times or fewer times than chain->length,
we still need to setup root variable and propagate it with PHI node. */
tree niters = number_of_latch_executions (loop);
if (TREE_CODE (niters) != INTEGER_CST
diff --git a/gcc/tree-pretty-print.c b/gcc/tree-pretty-print.c
index ae0a6c1..dacda7b 100644
--- a/gcc/tree-pretty-print.c
+++ b/gcc/tree-pretty-print.c
@@ -34,6 +34,14 @@ along with GCC; see the file COPYING3. If not see
#include "internal-fn.h"
#include "gomp-constants.h"
#include "gimple.h"
+#include "fold-const.h"
+
+/* Disable warnings about quoting issues in the pp_xxx calls below
+ that (intentionally) don't follow GCC diagnostic conventions. */
+#if __GNUC__ >= 10
+# pragma GCC diagnostic push
+# pragma GCC diagnostic ignored "-Wformat-diag"
+#endif
/* Local functions, macros and variables. */
static const char *op_symbol (const_tree);
@@ -460,12 +468,24 @@ dump_omp_clause (pretty_printer *pp, tree clause, int spc, dump_flags_t flags)
case OMP_CLAUSE_IS_DEVICE_PTR:
name = "is_device_ptr";
goto print_remap;
+ case OMP_CLAUSE_INCLUSIVE:
+ name = "inclusive";
+ goto print_remap;
+ case OMP_CLAUSE_EXCLUSIVE:
+ name = "exclusive";
+ goto print_remap;
case OMP_CLAUSE__LOOPTEMP_:
name = "_looptemp_";
goto print_remap;
case OMP_CLAUSE__REDUCTEMP_:
name = "_reductemp_";
goto print_remap;
+ case OMP_CLAUSE__CONDTEMP_:
+ name = "_condtemp_";
+ goto print_remap;
+ case OMP_CLAUSE__SCANTEMP_:
+ name = "_scantemp_";
+ goto print_remap;
case OMP_CLAUSE_TO_DECLARE:
name = "to";
goto print_remap;
@@ -1362,6 +1382,129 @@ dump_omp_atomic_memory_order (pretty_printer *pp, enum omp_memory_order mo)
}
}
+/* Helper to dump a MEM_REF node. */
+
+static void
+dump_mem_ref (pretty_printer *pp, tree node, int spc, dump_flags_t flags)
+{
+ if (flags & TDF_GIMPLE)
+ {
+ pp_string (pp, "__MEM <");
+ dump_generic_node (pp, TREE_TYPE (node),
+ spc, flags | TDF_SLIM, false);
+ if (TYPE_ALIGN (TREE_TYPE (node))
+ != TYPE_ALIGN (TYPE_MAIN_VARIANT (TREE_TYPE (node))))
+ {
+ pp_string (pp, ", ");
+ pp_decimal_int (pp, TYPE_ALIGN (TREE_TYPE (node)));
+ }
+ pp_greater (pp);
+ pp_string (pp, " (");
+ if (TREE_TYPE (TREE_OPERAND (node, 0))
+ != TREE_TYPE (TREE_OPERAND (node, 1)))
+ {
+ pp_left_paren (pp);
+ dump_generic_node (pp, TREE_TYPE (TREE_OPERAND (node, 1)),
+ spc, flags | TDF_SLIM, false);
+ pp_right_paren (pp);
+ }
+ dump_generic_node (pp, TREE_OPERAND (node, 0),
+ spc, flags | TDF_SLIM, false);
+ if (! integer_zerop (TREE_OPERAND (node, 1)))
+ {
+ pp_string (pp, " + ");
+ dump_generic_node (pp, TREE_OPERAND (node, 1),
+ spc, flags | TDF_SLIM, false);
+ }
+ pp_right_paren (pp);
+ }
+ else if (integer_zerop (TREE_OPERAND (node, 1))
+ /* Dump the types of INTEGER_CSTs explicitly, for we can't
+ infer them and MEM_ATTR caching will share MEM_REFs
+ with differently-typed op0s. */
+ && TREE_CODE (TREE_OPERAND (node, 0)) != INTEGER_CST
+ /* Released SSA_NAMES have no TREE_TYPE. */
+ && TREE_TYPE (TREE_OPERAND (node, 0)) != NULL_TREE
+ /* Same pointer types, but ignoring POINTER_TYPE vs.
+ REFERENCE_TYPE. */
+ && (TREE_TYPE (TREE_TYPE (TREE_OPERAND (node, 0)))
+ == TREE_TYPE (TREE_TYPE (TREE_OPERAND (node, 1))))
+ && (TYPE_MODE (TREE_TYPE (TREE_OPERAND (node, 0)))
+ == TYPE_MODE (TREE_TYPE (TREE_OPERAND (node, 1))))
+ && (TYPE_REF_CAN_ALIAS_ALL (TREE_TYPE (TREE_OPERAND (node, 0)))
+ == TYPE_REF_CAN_ALIAS_ALL (TREE_TYPE (TREE_OPERAND (node, 1))))
+ /* Same value types ignoring qualifiers. */
+ && (TYPE_MAIN_VARIANT (TREE_TYPE (node))
+ == TYPE_MAIN_VARIANT
+ (TREE_TYPE (TREE_TYPE (TREE_OPERAND (node, 1)))))
+ && (!(flags & TDF_ALIAS)
+ || MR_DEPENDENCE_CLIQUE (node) == 0))
+ {
+ if (TREE_CODE (TREE_OPERAND (node, 0)) != ADDR_EXPR)
+ {
+ /* Enclose pointers to arrays in parentheses. */
+ tree op0 = TREE_OPERAND (node, 0);
+ tree op0type = TREE_TYPE (op0);
+ if (POINTER_TYPE_P (op0type)
+ && TREE_CODE (TREE_TYPE (op0type)) == ARRAY_TYPE)
+ pp_left_paren (pp);
+ pp_star (pp);
+ dump_generic_node (pp, op0, spc, flags, false);
+ if (POINTER_TYPE_P (op0type)
+ && TREE_CODE (TREE_TYPE (op0type)) == ARRAY_TYPE)
+ pp_right_paren (pp);
+ }
+ else
+ dump_generic_node (pp,
+ TREE_OPERAND (TREE_OPERAND (node, 0), 0),
+ spc, flags, false);
+ }
+ else
+ {
+ pp_string (pp, "MEM");
+
+ tree nodetype = TREE_TYPE (node);
+ tree op0 = TREE_OPERAND (node, 0);
+ tree op1 = TREE_OPERAND (node, 1);
+ tree op1type = TYPE_MAIN_VARIANT (TREE_TYPE (op1));
+
+ tree op0size = TYPE_SIZE (nodetype);
+ tree op1size = TYPE_SIZE (TREE_TYPE (op1type));
+
+ if (!op0size || !op1size
+ || !operand_equal_p (op0size, op1size, 0))
+ {
+ pp_string (pp, " <");
+ /* If the size of the type of the operand is not the same
+ as the size of the MEM_REF expression include the type
+ of the latter similar to the TDF_GIMPLE output to make
+ it clear how many bytes of memory are being accessed. */
+ dump_generic_node (pp, nodetype, spc, flags | TDF_SLIM, false);
+ pp_string (pp, "> ");
+ }
+
+ pp_string (pp, "[(");
+ dump_generic_node (pp, op1type, spc, flags | TDF_SLIM, false);
+ pp_right_paren (pp);
+ dump_generic_node (pp, op0, spc, flags, false);
+ if (!integer_zerop (op1))
+ if (!integer_zerop (TREE_OPERAND (node, 1)))
+ {
+ pp_string (pp, " + ");
+ dump_generic_node (pp, op1, spc, flags, false);
+ }
+ if ((flags & TDF_ALIAS)
+ && MR_DEPENDENCE_CLIQUE (node) != 0)
+ {
+ pp_string (pp, " clique ");
+ pp_unsigned_wide_integer (pp, MR_DEPENDENCE_CLIQUE (node));
+ pp_string (pp, " base ");
+ pp_unsigned_wide_integer (pp, MR_DEPENDENCE_BASE (node));
+ }
+ pp_right_bracket (pp);
+ }
+ }
+
/* Dump the node NODE on the pretty_printer PP, SPC spaces of
indent. FLAGS specifies details to show in the dump (see TDF_* in
dumpfile.h). If IS_STMT is true, the object printed is considered
@@ -1620,101 +1763,8 @@ dump_generic_node (pretty_printer *pp, tree node, int spc, dump_flags_t flags,
break;
case MEM_REF:
- {
- if (flags & TDF_GIMPLE)
- {
- pp_string (pp, "__MEM <");
- dump_generic_node (pp, TREE_TYPE (node),
- spc, flags | TDF_SLIM, false);
- if (TYPE_ALIGN (TREE_TYPE (node))
- != TYPE_ALIGN (TYPE_MAIN_VARIANT (TREE_TYPE (node))))
- {
- pp_string (pp, ", ");
- pp_decimal_int (pp, TYPE_ALIGN (TREE_TYPE (node)));
- }
- pp_greater (pp);
- pp_string (pp, " (");
- if (TREE_TYPE (TREE_OPERAND (node, 0))
- != TREE_TYPE (TREE_OPERAND (node, 1)))
- {
- pp_left_paren (pp);
- dump_generic_node (pp, TREE_TYPE (TREE_OPERAND (node, 1)),
- spc, flags | TDF_SLIM, false);
- pp_right_paren (pp);
- }
- dump_generic_node (pp, TREE_OPERAND (node, 0),
- spc, flags | TDF_SLIM, false);
- if (! integer_zerop (TREE_OPERAND (node, 1)))
- {
- pp_string (pp, " + ");
- dump_generic_node (pp, TREE_OPERAND (node, 1),
- spc, flags | TDF_SLIM, false);
- }
- pp_right_paren (pp);
- }
- else if (integer_zerop (TREE_OPERAND (node, 1))
- /* Dump the types of INTEGER_CSTs explicitly, for we can't
- infer them and MEM_ATTR caching will share MEM_REFs
- with differently-typed op0s. */
- && TREE_CODE (TREE_OPERAND (node, 0)) != INTEGER_CST
- /* Released SSA_NAMES have no TREE_TYPE. */
- && TREE_TYPE (TREE_OPERAND (node, 0)) != NULL_TREE
- /* Same pointer types, but ignoring POINTER_TYPE vs.
- REFERENCE_TYPE. */
- && (TREE_TYPE (TREE_TYPE (TREE_OPERAND (node, 0)))
- == TREE_TYPE (TREE_TYPE (TREE_OPERAND (node, 1))))
- && (TYPE_MODE (TREE_TYPE (TREE_OPERAND (node, 0)))
- == TYPE_MODE (TREE_TYPE (TREE_OPERAND (node, 1))))
- && (TYPE_REF_CAN_ALIAS_ALL (TREE_TYPE (TREE_OPERAND (node, 0)))
- == TYPE_REF_CAN_ALIAS_ALL (TREE_TYPE (TREE_OPERAND (node, 1))))
- /* Same value types ignoring qualifiers. */
- && (TYPE_MAIN_VARIANT (TREE_TYPE (node))
- == TYPE_MAIN_VARIANT
- (TREE_TYPE (TREE_TYPE (TREE_OPERAND (node, 1)))))
- && (!(flags & TDF_ALIAS)
- || MR_DEPENDENCE_CLIQUE (node) == 0))
- {
- if (TREE_CODE (TREE_OPERAND (node, 0)) != ADDR_EXPR)
- {
- pp_star (pp);
- dump_generic_node (pp, TREE_OPERAND (node, 0),
- spc, flags, false);
- }
- else
- dump_generic_node (pp,
- TREE_OPERAND (TREE_OPERAND (node, 0), 0),
- spc, flags, false);
- }
- else
- {
- tree ptype;
-
- pp_string (pp, "MEM[");
- pp_left_paren (pp);
- ptype = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_OPERAND (node, 1)));
- dump_generic_node (pp, ptype,
- spc, flags | TDF_SLIM, false);
- pp_right_paren (pp);
- dump_generic_node (pp, TREE_OPERAND (node, 0),
- spc, flags, false);
- if (!integer_zerop (TREE_OPERAND (node, 1)))
- {
- pp_string (pp, " + ");
- dump_generic_node (pp, TREE_OPERAND (node, 1),
- spc, flags, false);
- }
- if ((flags & TDF_ALIAS)
- && MR_DEPENDENCE_CLIQUE (node) != 0)
- {
- pp_string (pp, " clique ");
- pp_unsigned_wide_integer (pp, MR_DEPENDENCE_CLIQUE (node));
- pp_string (pp, " base ");
- pp_unsigned_wide_integer (pp, MR_DEPENDENCE_BASE (node));
- }
- pp_right_bracket (pp);
- }
- break;
- }
+ dump_mem_ref (pp, node, spc, flags);
+ break;
case TARGET_MEM_REF:
{
@@ -2111,13 +2161,39 @@ dump_generic_node (pretty_printer *pp, tree node, int spc, dump_flags_t flags,
break;
case BIT_FIELD_REF:
- pp_string (pp, "BIT_FIELD_REF <");
- dump_generic_node (pp, TREE_OPERAND (node, 0), spc, flags, false);
- pp_string (pp, ", ");
- dump_generic_node (pp, TREE_OPERAND (node, 1), spc, flags, false);
- pp_string (pp, ", ");
- dump_generic_node (pp, TREE_OPERAND (node, 2), spc, flags, false);
- pp_greater (pp);
+ if (flags & TDF_GIMPLE)
+ {
+ pp_string (pp, "__BIT_FIELD_REF <");
+ dump_generic_node (pp, TREE_TYPE (node),
+ spc, flags | TDF_SLIM, false);
+ if (TYPE_ALIGN (TREE_TYPE (node))
+ != TYPE_ALIGN (TYPE_MAIN_VARIANT (TREE_TYPE (node))))
+ {
+ pp_string (pp, ", ");
+ pp_decimal_int (pp, TYPE_ALIGN (TREE_TYPE (node)));
+ }
+ pp_greater (pp);
+ pp_string (pp, " (");
+ dump_generic_node (pp, TREE_OPERAND (node, 0), spc,
+ flags | TDF_SLIM, false);
+ pp_string (pp, ", ");
+ dump_generic_node (pp, TREE_OPERAND (node, 1), spc,
+ flags | TDF_SLIM, false);
+ pp_string (pp, ", ");
+ dump_generic_node (pp, TREE_OPERAND (node, 2), spc,
+ flags | TDF_SLIM, false);
+ pp_right_paren (pp);
+ }
+ else
+ {
+ pp_string (pp, "BIT_FIELD_REF <");
+ dump_generic_node (pp, TREE_OPERAND (node, 0), spc, flags, false);
+ pp_string (pp, ", ");
+ dump_generic_node (pp, TREE_OPERAND (node, 1), spc, flags, false);
+ pp_string (pp, ", ");
+ dump_generic_node (pp, TREE_OPERAND (node, 2), spc, flags, false);
+ pp_greater (pp);
+ }
break;
case BIT_INSERT_EXPR:
@@ -2653,7 +2729,10 @@ dump_generic_node (pretty_printer *pp, tree node, int spc, dump_flags_t flags,
break;
case VIEW_CONVERT_EXPR:
- pp_string (pp, "VIEW_CONVERT_EXPR<");
+ if (flags & TDF_GIMPLE)
+ pp_string (pp, "__VIEW_CONVERT <");
+ else
+ pp_string (pp, "VIEW_CONVERT_EXPR<");
dump_generic_node (pp, TREE_TYPE (node), spc, flags, false);
pp_string (pp, ">(");
dump_generic_node (pp, TREE_OPERAND (node, 0), spc, flags, false);
@@ -3261,6 +3340,14 @@ dump_generic_node (pretty_printer *pp, tree node, int spc, dump_flags_t flags,
pp_string (pp, "#pragma omp section");
goto dump_omp_body;
+ case OMP_SCAN:
+ if (OMP_SCAN_CLAUSES (node))
+ {
+ pp_string (pp, "#pragma omp scan");
+ dump_omp_clauses (pp, OMP_SCAN_CLAUSES (node), spc, flags);
+ }
+ goto dump_omp_body;
+
case OMP_MASTER:
pp_string (pp, "#pragma omp master");
goto dump_omp_body;
@@ -4210,3 +4297,7 @@ pp_double_int (pretty_printer *pp, double_int d, bool uns)
pp_string (pp, pp_buffer (pp)->digit_buffer);
}
}
+
+#if __GNUC__ >= 10
+# pragma GCC diagnostic pop
+#endif
diff --git a/gcc/tree-pretty-print.h b/gcc/tree-pretty-print.h
index 9f59328..5434e80 100644
--- a/gcc/tree-pretty-print.h
+++ b/gcc/tree-pretty-print.h
@@ -25,7 +25,7 @@ along with GCC; see the file COPYING3. If not see
#include "pretty-print.h"
#define pp_unsupported_tree(PP, T) \
- pp_verbatim (PP, "#%qs not supported by %s#", \
+ pp_verbatim (PP, "%qs not supported by %s", \
get_tree_code_name (TREE_CODE (T)), __FUNCTION__)
#define pp_ti_abstract_origin(TI) ((tree *) (TI)->x_data)
diff --git a/gcc/tree-profile.c b/gcc/tree-profile.c
index 9b6f351..554a8c9 100644
--- a/gcc/tree-profile.c
+++ b/gcc/tree-profile.c
@@ -60,7 +60,7 @@ along with GCC; see the file COPYING3. If not see
static GTY(()) tree gcov_type_node;
static GTY(()) tree tree_interval_profiler_fn;
static GTY(()) tree tree_pow2_profiler_fn;
-static GTY(()) tree tree_one_value_profiler_fn;
+static GTY(()) tree tree_topn_values_profiler_fn;
static GTY(()) tree tree_indirect_call_profiler_fn;
static GTY(()) tree tree_average_profiler_fn;
static GTY(()) tree tree_ior_profiler_fn;
@@ -101,11 +101,7 @@ init_ic_make_global_vars (void)
ic_tuple_var
= build_decl (UNKNOWN_LOCATION, VAR_DECL,
- get_identifier (
- (PARAM_VALUE (PARAM_INDIR_CALL_TOPN_PROFILE) ?
- "__gcov_indirect_call_topn" :
- "__gcov_indirect_call")),
- tuple_type);
+ get_identifier ("__gcov_indirect_call"), tuple_type);
TREE_PUBLIC (ic_tuple_var) = 1;
DECL_ARTIFICIAL (ic_tuple_var) = 1;
DECL_INITIAL (ic_tuple_var) = NULL;
@@ -121,7 +117,7 @@ gimple_init_gcov_profiler (void)
{
tree interval_profiler_fn_type;
tree pow2_profiler_fn_type;
- tree one_value_profiler_fn_type;
+ tree topn_values_profiler_fn_type;
tree gcov_type_ptr;
tree ic_profiler_fn_type;
tree average_profiler_fn_type;
@@ -165,18 +161,18 @@ gimple_init_gcov_profiler (void)
DECL_ATTRIBUTES (tree_pow2_profiler_fn));
/* void (*) (gcov_type *, gcov_type) */
- one_value_profiler_fn_type
+ topn_values_profiler_fn_type
= build_function_type_list (void_type_node,
gcov_type_ptr, gcov_type_node,
NULL_TREE);
- fn_name = concat ("__gcov_one_value_profiler", fn_suffix, NULL);
- tree_one_value_profiler_fn = build_fn_decl (fn_name,
- one_value_profiler_fn_type);
- free (CONST_CAST (char *, fn_name));
- TREE_NOTHROW (tree_one_value_profiler_fn) = 1;
- DECL_ATTRIBUTES (tree_one_value_profiler_fn)
+ fn_name = concat ("__gcov_topn_values_profiler", fn_suffix, NULL);
+ tree_topn_values_profiler_fn
+ = build_fn_decl (fn_name, topn_values_profiler_fn_type);
+
+ TREE_NOTHROW (tree_topn_values_profiler_fn) = 1;
+ DECL_ATTRIBUTES (tree_topn_values_profiler_fn)
= tree_cons (get_identifier ("leaf"), NULL,
- DECL_ATTRIBUTES (tree_one_value_profiler_fn));
+ DECL_ATTRIBUTES (tree_topn_values_profiler_fn));
init_ic_make_global_vars ();
@@ -186,9 +182,7 @@ gimple_init_gcov_profiler (void)
gcov_type_node,
ptr_type_node,
NULL_TREE);
- profiler_fn_name = "__gcov_indirect_call_profiler_v3";
- if (PARAM_VALUE (PARAM_INDIR_CALL_TOPN_PROFILE))
- profiler_fn_name = "__gcov_indirect_call_topn_profiler";
+ profiler_fn_name = "__gcov_indirect_call_profiler_v4";
tree_indirect_call_profiler_fn
= build_fn_decl (profiler_fn_name, ic_profiler_fn_type);
@@ -232,7 +226,7 @@ gimple_init_gcov_profiler (void)
late, we need to initialize them by hand. */
DECL_ASSEMBLER_NAME (tree_interval_profiler_fn);
DECL_ASSEMBLER_NAME (tree_pow2_profiler_fn);
- DECL_ASSEMBLER_NAME (tree_one_value_profiler_fn);
+ DECL_ASSEMBLER_NAME (tree_topn_values_profiler_fn);
DECL_ASSEMBLER_NAME (tree_indirect_call_profiler_fn);
DECL_ASSEMBLER_NAME (tree_average_profiler_fn);
DECL_ASSEMBLER_NAME (tree_ior_profiler_fn);
@@ -340,12 +334,13 @@ gimple_gen_pow2_profiler (histogram_value value, unsigned tag, unsigned base)
gsi_insert_before (&gsi, call, GSI_NEW_STMT);
}
-/* Output instructions as GIMPLE trees for code to find the most common value.
- VALUE is the expression whose value is profiled. TAG is the tag of the
- section for counters, BASE is offset of the counter position. */
+/* Output instructions as GIMPLE trees for code to find the most N common
+ values. VALUE is the expression whose value is profiled. TAG is the tag
+ of the section for counters, BASE is offset of the counter position. */
void
-gimple_gen_one_value_profiler (histogram_value value, unsigned tag, unsigned base)
+gimple_gen_topn_values_profiler (histogram_value value, unsigned tag,
+ unsigned base)
{
gimple *stmt = value->hvalue.stmt;
gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
@@ -356,7 +351,7 @@ gimple_gen_one_value_profiler (histogram_value value, unsigned tag, unsigned bas
ref_ptr = force_gimple_operand_gsi (&gsi, ref_ptr,
true, NULL_TREE, true, GSI_SAME_STMT);
val = prepare_instrumented_value (&gsi, value);
- call = gimple_build_call (tree_one_value_profiler_fn, 2, ref_ptr, val);
+ call = gimple_build_call (tree_topn_values_profiler_fn, 2, ref_ptr, val);
gsi_insert_before (&gsi, call, GSI_NEW_STMT);
}
@@ -376,12 +371,6 @@ gimple_gen_ic_profiler (histogram_value value, unsigned tag, unsigned base)
gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
tree ref_ptr = tree_coverage_counter_addr (tag, base);
- if ( (PARAM_VALUE (PARAM_INDIR_CALL_TOPN_PROFILE) &&
- tag == GCOV_COUNTER_V_INDIR) ||
- (!PARAM_VALUE (PARAM_INDIR_CALL_TOPN_PROFILE) &&
- tag == GCOV_COUNTER_ICALL_TOPNV))
- return;
-
ref_ptr = force_gimple_operand_gsi (&gsi, ref_ptr,
true, NULL_TREE, true, GSI_SAME_STMT);
diff --git a/gcc/tree-scalar-evolution.c b/gcc/tree-scalar-evolution.c
index c814437..81f70f1 100644
--- a/gcc/tree-scalar-evolution.c
+++ b/gcc/tree-scalar-evolution.c
@@ -304,21 +304,6 @@ struct GTY((for_user)) scev_info_str {
static unsigned nb_set_scev = 0;
static unsigned nb_get_scev = 0;
-/* The following trees are unique elements. Thus the comparison of
- another element to these elements should be done on the pointer to
- these trees, and not on their value. */
-
-/* The SSA_NAMEs that are not yet analyzed are qualified with NULL_TREE. */
-tree chrec_not_analyzed_yet;
-
-/* Reserved to the cases where the analyzer has detected an
- undecidable property at compile time. */
-tree chrec_dont_know;
-
-/* When the analyzer has detected that a property will never
- happen, then it qualifies it with chrec_known. */
-tree chrec_known;
-
struct scev_info_hasher : ggc_ptr_hash<scev_info_str>
{
static hashval_t hash (scev_info_str *i);
@@ -411,49 +396,6 @@ instantiate_cache_type::~instantiate_cache_type ()
static instantiate_cache_type *global_cache;
-/* Return true when CHREC contains symbolic names defined in
- LOOP_NB. */
-
-bool
-chrec_contains_symbols_defined_in_loop (const_tree chrec, unsigned loop_nb)
-{
- int i, n;
-
- if (chrec == NULL_TREE)
- return false;
-
- if (is_gimple_min_invariant (chrec))
- return false;
-
- if (TREE_CODE (chrec) == SSA_NAME)
- {
- gimple *def;
- loop_p def_loop, loop;
-
- if (SSA_NAME_IS_DEFAULT_DEF (chrec))
- return false;
-
- def = SSA_NAME_DEF_STMT (chrec);
- def_loop = loop_containing_stmt (def);
- loop = get_loop (cfun, loop_nb);
-
- if (def_loop == NULL)
- return false;
-
- if (loop == def_loop || flow_loop_nested_p (loop, def_loop))
- return true;
-
- return false;
- }
-
- n = TREE_OPERAND_LENGTH (chrec);
- for (i = 0; i < n; i++)
- if (chrec_contains_symbols_defined_in_loop (TREE_OPERAND (chrec, i),
- loop_nb))
- return true;
- return false;
-}
-
/* Return true when PHI is a loop-phi-node. */
static bool
@@ -3099,23 +3041,6 @@ gather_stats_on_scev_database (void)
}
-
-/* Initializer. */
-
-static void
-initialize_scalar_evolutions_analyzer (void)
-{
- /* The elements below are unique. */
- if (chrec_dont_know == NULL_TREE)
- {
- chrec_not_analyzed_yet = NULL_TREE;
- chrec_dont_know = make_node (SCEV_NOT_KNOWN);
- chrec_known = make_node (SCEV_KNOWN);
- TREE_TYPE (chrec_dont_know) = void_type_node;
- TREE_TYPE (chrec_known) = void_type_node;
- }
-}
-
/* Initialize the analysis of scalar evolutions for LOOPS. */
void
@@ -3127,8 +3052,6 @@ scev_initialize (void)
scalar_evolution_info = hash_table<scev_info_hasher>::create_ggc (100);
- initialize_scalar_evolutions_analyzer ();
-
FOR_EACH_LOOP (loop, 0)
{
loop->nb_iterations = NULL_TREE;
@@ -3505,8 +3428,9 @@ scev_finalize (void)
/* Returns true if the expression EXPR is considered to be too expensive
for scev_const_prop. */
-bool
-expression_expensive_p (tree expr)
+static bool
+expression_expensive_p (tree expr, hash_map<tree, uint64_t> &cache,
+ uint64_t &cost)
{
enum tree_code code;
@@ -3530,6 +3454,19 @@ expression_expensive_p (tree expr)
return true;
}
+ bool visited_p;
+ uint64_t &local_cost = cache.get_or_insert (expr, &visited_p);
+ if (visited_p)
+ {
+ uint64_t tem = cost + local_cost;
+ if (tem < cost)
+ return true;
+ cost = tem;
+ return false;
+ }
+ local_cost = 1;
+
+ uint64_t op_cost = 0;
if (code == CALL_EXPR)
{
tree arg;
@@ -3568,39 +3505,62 @@ expression_expensive_p (tree expr)
if (!is_inexpensive_builtin (get_callee_fndecl (expr)))
return true;
FOR_EACH_CALL_EXPR_ARG (arg, iter, expr)
- if (expression_expensive_p (arg))
+ if (expression_expensive_p (arg, cache, op_cost))
return true;
+ *cache.get (expr) += op_cost;
+ cost += op_cost + 1;
return false;
}
if (code == COND_EXPR)
- return (expression_expensive_p (TREE_OPERAND (expr, 0))
- || (EXPR_P (TREE_OPERAND (expr, 1))
- && EXPR_P (TREE_OPERAND (expr, 2)))
- /* If either branch has side effects or could trap. */
- || TREE_SIDE_EFFECTS (TREE_OPERAND (expr, 1))
- || generic_expr_could_trap_p (TREE_OPERAND (expr, 1))
- || TREE_SIDE_EFFECTS (TREE_OPERAND (expr, 0))
- || generic_expr_could_trap_p (TREE_OPERAND (expr, 0))
- || expression_expensive_p (TREE_OPERAND (expr, 1))
- || expression_expensive_p (TREE_OPERAND (expr, 2)));
+ {
+ if (expression_expensive_p (TREE_OPERAND (expr, 0), cache, op_cost)
+ || (EXPR_P (TREE_OPERAND (expr, 1))
+ && EXPR_P (TREE_OPERAND (expr, 2)))
+ /* If either branch has side effects or could trap. */
+ || TREE_SIDE_EFFECTS (TREE_OPERAND (expr, 1))
+ || generic_expr_could_trap_p (TREE_OPERAND (expr, 1))
+ || TREE_SIDE_EFFECTS (TREE_OPERAND (expr, 0))
+ || generic_expr_could_trap_p (TREE_OPERAND (expr, 0))
+ || expression_expensive_p (TREE_OPERAND (expr, 1),
+ cache, op_cost)
+ || expression_expensive_p (TREE_OPERAND (expr, 2),
+ cache, op_cost))
+ return true;
+ *cache.get (expr) += op_cost;
+ cost += op_cost + 1;
+ return false;
+ }
switch (TREE_CODE_CLASS (code))
{
case tcc_binary:
case tcc_comparison:
- if (expression_expensive_p (TREE_OPERAND (expr, 1)))
+ if (expression_expensive_p (TREE_OPERAND (expr, 1), cache, op_cost))
return true;
/* Fallthru. */
case tcc_unary:
- return expression_expensive_p (TREE_OPERAND (expr, 0));
+ if (expression_expensive_p (TREE_OPERAND (expr, 0), cache, op_cost))
+ return true;
+ *cache.get (expr) += op_cost;
+ cost += op_cost + 1;
+ return false;
default:
return true;
}
}
+bool
+expression_expensive_p (tree expr)
+{
+ hash_map<tree, uint64_t> cache;
+ uint64_t expanded_size = 0;
+ return (expression_expensive_p (expr, cache, expanded_size)
+ || expanded_size > cache.elements ());
+}
+
/* Do final value replacement for LOOP, return true if we did anything. */
bool
diff --git a/gcc/tree-sra.c b/gcc/tree-sra.c
index fd51a3d..03c1a2a 100644
--- a/gcc/tree-sra.c
+++ b/gcc/tree-sra.c
@@ -106,6 +106,7 @@ along with GCC; see the file COPYING3. If not see
#include "ipa-utils.h"
#include "builtins.h"
+
/* Enumeration of all aggregate reductions we can do. */
enum sra_mode { SRA_MODE_EARLY_IPA, /* early call regularization */
SRA_MODE_EARLY_INTRA, /* early intraprocedural SRA */
@@ -242,6 +243,10 @@ struct access
access tree. */
unsigned grp_unscalarized_data : 1;
+ /* Set if all accesses in the group consist of the same chain of
+ COMPONENT_REFs and ARRAY_REFs. */
+ unsigned grp_same_access_path : 1;
+
/* Does this access and/or group contain a write access through a
BIT_FIELD_REF? */
unsigned grp_partial_lhs : 1;
@@ -443,16 +448,18 @@ dump_access (FILE *f, struct access *access, bool grp)
"grp_scalar_write = %d, grp_total_scalarization = %d, "
"grp_hint = %d, grp_covered = %d, "
"grp_unscalarizable_region = %d, grp_unscalarized_data = %d, "
- "grp_partial_lhs = %d, grp_to_be_replaced = %d, "
- "grp_to_be_debug_replaced = %d, grp_maybe_modified = %d, "
+ "grp_same_access_path = %d, grp_partial_lhs = %d, "
+ "grp_to_be_replaced = %d, grp_to_be_debug_replaced = %d, "
+ "grp_maybe_modified = %d, "
"grp_not_necessarilly_dereferenced = %d\n",
access->grp_read, access->grp_write, access->grp_assignment_read,
access->grp_assignment_write, access->grp_scalar_read,
access->grp_scalar_write, access->grp_total_scalarization,
access->grp_hint, access->grp_covered,
access->grp_unscalarizable_region, access->grp_unscalarized_data,
- access->grp_partial_lhs, access->grp_to_be_replaced,
- access->grp_to_be_debug_replaced, access->grp_maybe_modified,
+ access->grp_same_access_path, access->grp_partial_lhs,
+ access->grp_to_be_replaced, access->grp_to_be_debug_replaced,
+ access->grp_maybe_modified,
access->grp_not_necessarilly_dereferenced);
else
fprintf (f, ", write = %d, grp_total_scalarization = %d, "
@@ -1795,6 +1802,27 @@ build_ref_for_offset (location_t loc, tree base, poly_int64 offset,
return mem_ref;
}
+/* Construct and return a memory reference that is equal to a portion of
+ MODEL->expr but is based on BASE. If this cannot be done, return NULL. */
+
+static tree
+build_reconstructed_reference (location_t, tree base, struct access *model)
+{
+ tree expr = model->expr, prev_expr = NULL;
+ while (!types_compatible_p (TREE_TYPE (expr), TREE_TYPE (base)))
+ {
+ if (!handled_component_p (expr))
+ return NULL;
+ prev_expr = expr;
+ expr = TREE_OPERAND (expr, 0);
+ }
+
+ TREE_OPERAND (prev_expr, 0) = base;
+ tree ref = unshare_expr (model->expr);
+ TREE_OPERAND (prev_expr, 0) = expr;
+ return ref;
+}
+
/* Construct a memory reference to a part of an aggregate BASE at the given
OFFSET and of the same type as MODEL. In case this is a reference to a
bit-field, the function will replicate the last component_ref of model's
@@ -1822,9 +1850,21 @@ build_ref_for_model (location_t loc, tree base, HOST_WIDE_INT offset,
NULL_TREE);
}
else
- return
- build_ref_for_offset (loc, base, offset, model->reverse, model->type,
- gsi, insert_after);
+ {
+ tree res;
+ if (model->grp_same_access_path
+ && !TREE_THIS_VOLATILE (base)
+ && (TYPE_ADDR_SPACE (TREE_TYPE (base))
+ == TYPE_ADDR_SPACE (TREE_TYPE (model->expr)))
+ && offset <= model->offset
+ /* build_reconstructed_reference can still fail if we have already
+ massaged BASE because of another type incompatibility. */
+ && (res = build_reconstructed_reference (loc, base, model)))
+ return res;
+ else
+ return build_ref_for_offset (loc, base, offset, model->reverse,
+ model->type, gsi, insert_after);
+ }
}
/* Attempt to build a memory reference that we could but into a gimple
@@ -2076,6 +2116,69 @@ find_var_candidates (void)
return ret;
}
+/* Return true if EXP is a reference chain of COMPONENT_REFs and AREAY_REFs
+ ending either with a DECL or a MEM_REF with zero offset. */
+
+static bool
+path_comparable_for_same_access (tree expr)
+{
+ while (handled_component_p (expr))
+ {
+ if (TREE_CODE (expr) == ARRAY_REF)
+ {
+ /* SSA name indices can occur here too when the array is of sie one.
+ But we cannot just re-use array_refs with SSA names elsewhere in
+ the function, so disallow non-constant indices. TODO: Remove this
+ limitation after teaching build_reconstructed_reference to replace
+ the index with the index type lower bound. */
+ if (TREE_CODE (TREE_OPERAND (expr, 1)) != INTEGER_CST)
+ return false;
+ }
+ expr = TREE_OPERAND (expr, 0);
+ }
+
+ if (TREE_CODE (expr) == MEM_REF)
+ {
+ if (!zerop (TREE_OPERAND (expr, 1)))
+ return false;
+ }
+ else
+ gcc_assert (DECL_P (expr));
+
+ return true;
+}
+
+/* Assuming that EXP1 consists of only COMPONENT_REFs and ARRAY_REFs, return
+ true if the chain of these handled components are exactly the same as EXP2
+ and the expression under them is the same DECL or an equivalent MEM_REF.
+ The reference picked by compare_access_positions must go to EXP1. */
+
+static bool
+same_access_path_p (tree exp1, tree exp2)
+{
+ if (TREE_CODE (exp1) != TREE_CODE (exp2))
+ {
+ /* Special case single-field structures loaded sometimes as the field
+ and sometimes as the structure. If the field is of a scalar type,
+ compare_access_positions will put it into exp1.
+
+ TODO: The gimple register type condition can be removed if teach
+ compare_access_positions to put inner types first. */
+ if (is_gimple_reg_type (TREE_TYPE (exp1))
+ && TREE_CODE (exp1) == COMPONENT_REF
+ && (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_OPERAND (exp1, 0)))
+ == TYPE_MAIN_VARIANT (TREE_TYPE (exp2))))
+ exp1 = TREE_OPERAND (exp1, 0);
+ else
+ return false;
+ }
+
+ if (!operand_equal_p (exp1, exp2, OEP_ADDRESS_OF))
+ return false;
+
+ return true;
+}
+
/* Sort all accesses for the given variable, check for partial overlaps and
return NULL if there are any. If there are none, pick a representative for
each combination of offset and size and create a linked list out of them.
@@ -2116,6 +2219,7 @@ sort_and_splice_var_accesses (tree var)
bool grp_partial_lhs = access->grp_partial_lhs;
bool first_scalar = is_gimple_reg_type (access->type);
bool unscalarizable_region = access->grp_unscalarizable_region;
+ bool grp_same_access_path = true;
bool bf_non_full_precision
= (INTEGRAL_TYPE_P (access->type)
&& TYPE_PRECISION (access->type) != access->size
@@ -2134,6 +2238,8 @@ sort_and_splice_var_accesses (tree var)
gcc_assert (access->offset >= low
&& access->offset + access->size <= high);
+ grp_same_access_path = path_comparable_for_same_access (access->expr);
+
j = i + 1;
while (j < access_count)
{
@@ -2184,6 +2290,11 @@ sort_and_splice_var_accesses (tree var)
}
unscalarizable_region = true;
}
+
+ if (grp_same_access_path
+ && !same_access_path_p (access->expr, ac2->expr))
+ grp_same_access_path = false;
+
ac2->group_representative = access;
j++;
}
@@ -2202,6 +2313,7 @@ sort_and_splice_var_accesses (tree var)
access->grp_total_scalarization = total_scalarization;
access->grp_partial_lhs = grp_partial_lhs;
access->grp_unscalarizable_region = unscalarizable_region;
+ access->grp_same_access_path = grp_same_access_path;
*prev_acc_ptr = access;
prev_acc_ptr = &access->next_grp;
@@ -2471,6 +2583,8 @@ analyze_access_subtree (struct access *root, struct access *parent,
root->grp_assignment_write = 1;
if (parent->grp_total_scalarization)
root->grp_total_scalarization = 1;
+ if (!parent->grp_same_access_path)
+ root->grp_same_access_path = 0;
}
if (root->grp_unscalarizable_region)
@@ -2721,13 +2835,17 @@ propagate_subaccesses_across_link (struct access *lacc, struct access *racc)
lacc->type = racc->type;
if (build_user_friendly_ref_for_offset (&t, TREE_TYPE (t),
lacc->offset, racc->type))
- lacc->expr = t;
+ {
+ lacc->expr = t;
+ lacc->grp_same_access_path = true;
+ }
else
{
lacc->expr = build_ref_for_model (EXPR_LOCATION (lacc->base),
lacc->base, lacc->offset,
racc, NULL, false);
lacc->grp_no_warning = true;
+ lacc->grp_same_access_path = false;
}
}
return ret;
diff --git a/gcc/tree-ssa-address.c b/gcc/tree-ssa-address.c
index 1c17e93..e83e1b9 100644
--- a/gcc/tree-ssa-address.c
+++ b/gcc/tree-ssa-address.c
@@ -1127,6 +1127,39 @@ maybe_fold_tmr (tree ref)
return new_ref;
}
+/* Return the preferred index scale factor for accessing memory of mode
+ MEM_MODE in the address space of pointer BASE. Assume that we're
+ optimizing for speed if SPEED is true and for size otherwise. */
+unsigned int
+preferred_mem_scale_factor (tree base, machine_mode mem_mode,
+ bool speed)
+{
+ /* For BLKmode, we can't do anything so return 1. */
+ if (mem_mode == BLKmode)
+ return 1;
+
+ struct mem_address parts = {};
+ addr_space_t as = TYPE_ADDR_SPACE (TREE_TYPE (base));
+ unsigned int fact = GET_MODE_UNIT_SIZE (mem_mode);
+
+ /* Addressing mode "base + index". */
+ parts.index = integer_one_node;
+ parts.base = integer_one_node;
+ rtx addr = addr_for_mem_ref (&parts, as, false);
+ unsigned cost = address_cost (addr, mem_mode, as, speed);
+
+ /* Addressing mode "base + index << scale". */
+ parts.step = wide_int_to_tree (sizetype, fact);
+ addr = addr_for_mem_ref (&parts, as, false);
+ unsigned new_cost = address_cost (addr, mem_mode, as, speed);
+
+ /* Compare the cost of an address with an unscaled index with
+ a scaled index and return factor if useful. */
+ if (new_cost < cost)
+ return GET_MODE_UNIT_SIZE (mem_mode);
+ return 1;
+}
+
/* Dump PARTS to FILE. */
extern void dump_mem_address (FILE *, struct mem_address *);
diff --git a/gcc/tree-ssa-address.h b/gcc/tree-ssa-address.h
index 6fa4eae..9812f36 100644
--- a/gcc/tree-ssa-address.h
+++ b/gcc/tree-ssa-address.h
@@ -39,4 +39,7 @@ tree create_mem_ref (gimple_stmt_iterator *, tree,
extern void copy_ref_info (tree, tree);
tree maybe_fold_tmr (tree);
+extern unsigned int preferred_mem_scale_factor (tree base,
+ machine_mode mem_mode,
+ bool speed);
#endif /* GCC_TREE_SSA_ADDRESS_H */
diff --git a/gcc/tree-ssa-alias.c b/gcc/tree-ssa-alias.c
index 619cc89..c3c127a 100644
--- a/gcc/tree-ssa-alias.c
+++ b/gcc/tree-ssa-alias.c
@@ -87,6 +87,8 @@ along with GCC; see the file COPYING3. If not see
this file. Low-level disambiguators dealing with points-to
information are in tree-ssa-structalias.c. */
+static int nonoverlapping_component_refs_since_match_p (tree, tree, tree, tree);
+static bool nonoverlapping_component_refs_p (const_tree, const_tree);
/* Query statistics for the different low-level disambiguators.
A high-level query may trigger multiple of them. */
@@ -98,6 +100,12 @@ static struct {
unsigned HOST_WIDE_INT ref_maybe_used_by_call_p_no_alias;
unsigned HOST_WIDE_INT call_may_clobber_ref_p_may_alias;
unsigned HOST_WIDE_INT call_may_clobber_ref_p_no_alias;
+ unsigned HOST_WIDE_INT aliasing_component_refs_p_may_alias;
+ unsigned HOST_WIDE_INT aliasing_component_refs_p_no_alias;
+ unsigned HOST_WIDE_INT nonoverlapping_component_refs_p_may_alias;
+ unsigned HOST_WIDE_INT nonoverlapping_component_refs_p_no_alias;
+ unsigned HOST_WIDE_INT nonoverlapping_component_refs_since_match_p_may_alias;
+ unsigned HOST_WIDE_INT nonoverlapping_component_refs_since_match_p_no_alias;
} alias_stats;
void
@@ -122,6 +130,24 @@ dump_alias_stats (FILE *s)
alias_stats.call_may_clobber_ref_p_no_alias,
alias_stats.call_may_clobber_ref_p_no_alias
+ alias_stats.call_may_clobber_ref_p_may_alias);
+ fprintf (s, " nonoverlapping_component_refs_p: "
+ HOST_WIDE_INT_PRINT_DEC" disambiguations, "
+ HOST_WIDE_INT_PRINT_DEC" queries\n",
+ alias_stats.nonoverlapping_component_refs_p_no_alias,
+ alias_stats.nonoverlapping_component_refs_p_no_alias
+ + alias_stats.nonoverlapping_component_refs_p_may_alias);
+ fprintf (s, " nonoverlapping_component_refs_since_match_p: "
+ HOST_WIDE_INT_PRINT_DEC" disambiguations, "
+ HOST_WIDE_INT_PRINT_DEC" queries\n",
+ alias_stats.nonoverlapping_component_refs_since_match_p_no_alias,
+ alias_stats.nonoverlapping_component_refs_since_match_p_no_alias
+ + alias_stats.nonoverlapping_component_refs_since_match_p_may_alias);
+ fprintf (s, " aliasing_component_refs_p: "
+ HOST_WIDE_INT_PRINT_DEC" disambiguations, "
+ HOST_WIDE_INT_PRINT_DEC" queries\n",
+ alias_stats.aliasing_component_refs_p_no_alias,
+ alias_stats.aliasing_component_refs_p_no_alias
+ + alias_stats.aliasing_component_refs_p_may_alias);
dump_alias_stats_in_alias_c (s);
}
@@ -727,6 +753,48 @@ ao_ref_init_from_ptr_and_size (ao_ref *ref, tree ptr, tree size)
ref->volatile_p = false;
}
+/* S1 and S2 are TYPE_SIZE or DECL_SIZE. Compare them:
+ Return -1 if S1 < S2
+ Return 1 if S1 > S2
+ Return 0 if equal or incomparable. */
+
+static int
+compare_sizes (tree s1, tree s2)
+{
+ if (!s1 || !s2)
+ return 0;
+
+ poly_uint64 size1;
+ poly_uint64 size2;
+
+ if (!poly_int_tree_p (s1, &size1) || !poly_int_tree_p (s2, &size2))
+ return 0;
+ if (known_lt (size1, size2))
+ return -1;
+ if (known_lt (size2, size1))
+ return 1;
+ return 0;
+}
+
+/* Compare TYPE1 and TYPE2 by its size.
+ Return -1 if size of TYPE1 < size of TYPE2
+ Return 1 if size of TYPE1 > size of TYPE2
+ Return 0 if types are of equal sizes or we can not compare them. */
+
+static int
+compare_type_sizes (tree type1, tree type2)
+{
+ /* Be conservative for arrays and vectors. We want to support partial
+ overlap on int[3] and int[3] as tested in gcc.dg/torture/alias-2.c. */
+ while (TREE_CODE (type1) == ARRAY_TYPE
+ || TREE_CODE (type1) == VECTOR_TYPE)
+ type1 = TREE_TYPE (type1);
+ while (TREE_CODE (type2) == ARRAY_TYPE
+ || TREE_CODE (type2) == VECTOR_TYPE)
+ type2 = TREE_TYPE (type2);
+ return compare_sizes (TYPE_SIZE (type1), TYPE_SIZE (type2));
+}
+
/* Return 1 if TYPE1 and TYPE2 are to be considered equivalent for the
purpose of TBAA. Return 0 if they are distinct and -1 if we cannot
decide. */
@@ -737,6 +805,10 @@ same_type_for_tbaa (tree type1, tree type2)
type1 = TYPE_MAIN_VARIANT (type1);
type2 = TYPE_MAIN_VARIANT (type2);
+ /* Handle the most common case first. */
+ if (type1 == type2)
+ return 1;
+
/* If we would have to do structural comparison bail out. */
if (TYPE_STRUCTURAL_EQUALITY_P (type1)
|| TYPE_STRUCTURAL_EQUALITY_P (type2))
@@ -768,10 +840,60 @@ same_type_for_tbaa (tree type1, tree type2)
return 0;
}
+/* Return true if TYPE is a composite type (i.e. we may apply one of handled
+ components on it). */
+
+static bool
+type_has_components_p (tree type)
+{
+ return AGGREGATE_TYPE_P (type) || VECTOR_TYPE_P (type)
+ || TREE_CODE (type) == COMPLEX_TYPE;
+}
+
+/* MATCH1 and MATCH2 which are part of access path of REF1 and REF2
+ respectively are either pointing to same address or are completely
+ disjoint.
+
+ Try to disambiguate using the access path starting from the match
+ and return false if there is no conflict.
+
+ Helper for aliasing_component_refs_p. */
+
+static bool
+aliasing_matching_component_refs_p (tree match1, tree ref1,
+ poly_int64 offset1, poly_int64 max_size1,
+ tree match2, tree ref2,
+ poly_int64 offset2, poly_int64 max_size2)
+{
+ poly_int64 offadj, sztmp, msztmp;
+ bool reverse;
+
+
+ get_ref_base_and_extent (match2, &offadj, &sztmp, &msztmp, &reverse);
+ offset2 -= offadj;
+ get_ref_base_and_extent (match1, &offadj, &sztmp, &msztmp, &reverse);
+ offset1 -= offadj;
+ if (!ranges_maybe_overlap_p (offset1, max_size1, offset2, max_size2))
+ {
+ ++alias_stats.aliasing_component_refs_p_no_alias;
+ return false;
+ }
+
+ int cmp = nonoverlapping_component_refs_since_match_p (match1, ref1,
+ match2, ref2);
+ if (cmp == 1
+ || (cmp == -1 && nonoverlapping_component_refs_p (ref1, ref2)))
+ {
+ ++alias_stats.aliasing_component_refs_p_no_alias;
+ return false;
+ }
+ ++alias_stats.aliasing_component_refs_p_may_alias;
+ return true;
+}
+
/* Determine if the two component references REF1 and REF2 which are
based on access types TYPE1 and TYPE2 and of which at least one is based
- on an indirect reference may alias. REF2 is the only one that can
- be a decl in which case REF2_IS_DECL is true.
+ on an indirect reference may alias.
REF1_ALIAS_SET, BASE1_ALIAS_SET, REF2_ALIAS_SET and BASE2_ALIAS_SET
are the respective alias sets. */
@@ -783,8 +905,7 @@ aliasing_component_refs_p (tree ref1,
tree ref2,
alias_set_type ref2_alias_set,
alias_set_type base2_alias_set,
- poly_int64 offset2, poly_int64 max_size2,
- bool ref2_is_decl)
+ poly_int64 offset2, poly_int64 max_size2)
{
/* If one reference is a component references through pointers try to find a
common base and apply offset based disambiguation. This handles
@@ -794,60 +915,181 @@ aliasing_component_refs_p (tree ref1,
disambiguating q->i and p->a.j. */
tree base1, base2;
tree type1, type2;
- tree *refp;
- int same_p, same_p2;
+ int same_p1 = 0, same_p2 = 0;
+ bool maybe_match = false;
+ tree end_struct_ref1 = NULL, end_struct_ref2 = NULL;
/* Choose bases and base types to search for. */
base1 = ref1;
while (handled_component_p (base1))
- base1 = TREE_OPERAND (base1, 0);
+ {
+ /* Generally access paths are monotous in the size of object. The
+ exception are trailing arrays of structures. I.e.
+ struct a {int array[0];};
+ or
+ struct a {int array1[0]; int array[];};
+ Such struct has size 0 but accesses to a.array may have non-zero size.
+ In this case the size of TREE_TYPE (base1) is smaller than
+ size of TREE_TYPE (TREE_OPERNAD (base1, 0)).
+
+ Because we compare sizes of arrays just by sizes of their elements,
+ we only need to care about zero sized array fields here. */
+ if (TREE_CODE (base1) == COMPONENT_REF
+ && TREE_CODE (TREE_TYPE (TREE_OPERAND (base1, 1))) == ARRAY_TYPE
+ && (!TYPE_SIZE (TREE_TYPE (TREE_OPERAND (base1, 1)))
+ || integer_zerop (TYPE_SIZE (TREE_TYPE (TREE_OPERAND (base1, 1)))))
+ && array_at_struct_end_p (base1))
+ {
+ gcc_checking_assert (!end_struct_ref1);
+ end_struct_ref1 = base1;
+ }
+ if (TREE_CODE (base1) == VIEW_CONVERT_EXPR
+ || TREE_CODE (base1) == BIT_FIELD_REF)
+ ref1 = TREE_OPERAND (base1, 0);
+ base1 = TREE_OPERAND (base1, 0);
+ }
type1 = TREE_TYPE (base1);
base2 = ref2;
while (handled_component_p (base2))
- base2 = TREE_OPERAND (base2, 0);
+ {
+ if (TREE_CODE (base2) == COMPONENT_REF
+ && TREE_CODE (TREE_TYPE (TREE_OPERAND (base2, 1))) == ARRAY_TYPE
+ && (!TYPE_SIZE (TREE_TYPE (TREE_OPERAND (base2, 1)))
+ || integer_zerop (TYPE_SIZE (TREE_TYPE (TREE_OPERAND (base2, 1)))))
+ && array_at_struct_end_p (base2))
+ {
+ gcc_checking_assert (!end_struct_ref2);
+ end_struct_ref2 = base2;
+ }
+ if (TREE_CODE (base2) == VIEW_CONVERT_EXPR
+ || TREE_CODE (base2) == BIT_FIELD_REF)
+ ref2 = TREE_OPERAND (base2, 0);
+ base2 = TREE_OPERAND (base2, 0);
+ }
type2 = TREE_TYPE (base2);
/* Now search for the type1 in the access path of ref2. This
- would be a common base for doing offset based disambiguation on. */
- refp = &ref2;
- while (handled_component_p (*refp)
- && same_type_for_tbaa (TREE_TYPE (*refp), type1) == 0)
- refp = &TREE_OPERAND (*refp, 0);
- same_p = same_type_for_tbaa (TREE_TYPE (*refp), type1);
- if (same_p == 1)
+ would be a common base for doing offset based disambiguation on.
+ This however only makes sense if type2 is big enough to hold type1. */
+ int cmp_outer = compare_type_sizes (type2, type1);
+
+ /* If type2 is big enough to contain type1 walk its access path.
+ We also need to care of arrays at the end of structs that may extend
+ beyond the end of structure. */
+ if (cmp_outer >= 0
+ || (end_struct_ref2
+ && compare_type_sizes (TREE_TYPE (end_struct_ref2), type1) >= 0))
{
- poly_int64 offadj, sztmp, msztmp;
- bool reverse;
- get_ref_base_and_extent (*refp, &offadj, &sztmp, &msztmp, &reverse);
- offset2 -= offadj;
- get_ref_base_and_extent (base1, &offadj, &sztmp, &msztmp, &reverse);
- offset1 -= offadj;
- return ranges_maybe_overlap_p (offset1, max_size1, offset2, max_size2);
+ tree ref = ref2;
+ while (true)
+ {
+ /* We walk from inner type to the outer types. If type we see is
+ already too large to be part of type1, terminate the search. */
+ int cmp = compare_type_sizes (type1, TREE_TYPE (ref));
+
+ if (cmp < 0
+ && (!end_struct_ref1
+ || compare_type_sizes (TREE_TYPE (end_struct_ref1),
+ TREE_TYPE (ref)) < 0))
+ break;
+ /* If types may be of same size, see if we can decide about their
+ equality. */
+ if (cmp == 0)
+ {
+ same_p2 = same_type_for_tbaa (TREE_TYPE (ref), type1);
+ if (same_p2 == 1)
+ break;
+ /* In case we can't decide whether types are same try to
+ continue looking for the exact match.
+ Remember however that we possibly saw a match
+ to bypass the access path continuations tests we do later. */
+ if (same_p2 == -1)
+ maybe_match = true;
+ }
+ if (!handled_component_p (ref))
+ break;
+ ref = TREE_OPERAND (ref, 0);
+ }
+ if (same_p2 == 1)
+ {
+ /* We assume that arrays can overlap by multiple of their elements
+ size as tested in gcc.dg/torture/alias-2.c.
+ This partial overlap happen only when both arrays are bases of
+ the access and not contained within another component ref.
+ To be safe we also assume partial overlap for VLAs. */
+ if (TREE_CODE (TREE_TYPE (base1)) == ARRAY_TYPE
+ && (!TYPE_SIZE (TREE_TYPE (base1))
+ || TREE_CODE (TYPE_SIZE (TREE_TYPE (base1))) != INTEGER_CST
+ || ref == base2))
+ /* Setting maybe_match to true triggers
+ nonoverlapping_component_refs_p test later that still may do
+ useful disambiguation. */
+ maybe_match = true;
+ else
+ return aliasing_matching_component_refs_p (base1, ref1,
+ offset1, max_size1,
+ ref, ref2,
+ offset2, max_size2);
+ }
}
/* If we didn't find a common base, try the other way around. */
- refp = &ref1;
- while (handled_component_p (*refp)
- && same_type_for_tbaa (TREE_TYPE (*refp), type2) == 0)
- refp = &TREE_OPERAND (*refp, 0);
- same_p2 = same_type_for_tbaa (TREE_TYPE (*refp), type2);
- if (same_p2 == 1)
+ if (cmp_outer <= 0
+ || (end_struct_ref1
+ && compare_type_sizes (TREE_TYPE (end_struct_ref1), type1) <= 0))
{
- poly_int64 offadj, sztmp, msztmp;
- bool reverse;
-
- get_ref_base_and_extent (*refp, &offadj, &sztmp, &msztmp, &reverse);
- offset1 -= offadj;
- get_ref_base_and_extent (base2, &offadj, &sztmp, &msztmp, &reverse);
- offset2 -= offadj;
- return ranges_maybe_overlap_p (offset1, max_size1,
- offset2, max_size2);
+ tree ref = ref1;
+ while (true)
+ {
+ int cmp = compare_type_sizes (type2, TREE_TYPE (ref));
+ if (cmp < 0
+ && (!end_struct_ref2
+ || compare_type_sizes (TREE_TYPE (end_struct_ref2),
+ TREE_TYPE (ref)) < 0))
+ break;
+ /* If types may be of same size, see if we can decide about their
+ equality. */
+ if (cmp == 0)
+ {
+ same_p1 = same_type_for_tbaa (TREE_TYPE (ref), type2);
+ if (same_p1 == 1)
+ break;
+ if (same_p1 == -1)
+ maybe_match = true;
+ }
+ if (!handled_component_p (ref))
+ break;
+ ref = TREE_OPERAND (ref, 0);
+ }
+ if (same_p1 == 1)
+ {
+ if (TREE_CODE (TREE_TYPE (base2)) == ARRAY_TYPE
+ && (!TYPE_SIZE (TREE_TYPE (base2))
+ || TREE_CODE (TYPE_SIZE (TREE_TYPE (base2))) != INTEGER_CST
+ || ref == base1))
+ maybe_match = true;
+ else
+ return aliasing_matching_component_refs_p (ref, ref1,
+ offset1, max_size1,
+ base2, ref2,
+ offset2, max_size2);
+ }
}
- /* In the remaining test we assume that there is no overlapping type
- at all. So if we are unsure, we need to give up. */
- if (same_p == -1 || same_p2 == -1)
- return true;
+ /* In the following code we make an assumption that the types in access
+ paths do not overlap and thus accesses alias only if one path can be
+ continuation of another. If we was not able to decide about equivalence,
+ we need to give up. */
+ if (maybe_match)
+ {
+ if (!nonoverlapping_component_refs_p (ref1, ref2))
+ {
+ ++alias_stats.aliasing_component_refs_p_may_alias;
+ return true;
+ }
+ ++alias_stats.aliasing_component_refs_p_no_alias;
+ return false;
+ }
/* If we have two type access paths B1.path1 and B2.path2 they may
only alias if either B1 is in B2.path2 or B2 is in B1.path1.
@@ -855,21 +1097,57 @@ aliasing_component_refs_p (tree ref1,
a part that we do not see. So we can only disambiguate now
if there is no B2 in the tail of path1 and no B1 on the
tail of path2. */
- if (base1_alias_set == ref2_alias_set
- || alias_set_subset_of (base1_alias_set, ref2_alias_set))
- return true;
+ if (compare_type_sizes (TREE_TYPE (ref2), type1) >= 0
+ && (!end_struct_ref1
+ || compare_type_sizes (TREE_TYPE (ref2),
+ TREE_TYPE (end_struct_ref1)) >= 0)
+ && type_has_components_p (TREE_TYPE (ref2))
+ && (base1_alias_set == ref2_alias_set
+ || alias_set_subset_of (base1_alias_set, ref2_alias_set)))
+ {
+ ++alias_stats.aliasing_component_refs_p_may_alias;
+ return true;
+ }
/* If this is ptr vs. decl then we know there is no ptr ... decl path. */
- if (!ref2_is_decl)
- return (base2_alias_set == ref1_alias_set
- || alias_set_subset_of (base2_alias_set, ref1_alias_set));
+ if (compare_type_sizes (TREE_TYPE (ref1), type2) >= 0
+ && (!end_struct_ref2
+ || compare_type_sizes (TREE_TYPE (ref1),
+ TREE_TYPE (end_struct_ref2)) >= 0)
+ && type_has_components_p (TREE_TYPE (ref1))
+ && (base2_alias_set == ref1_alias_set
+ || alias_set_subset_of (base2_alias_set, ref1_alias_set)))
+ {
+ ++alias_stats.aliasing_component_refs_p_may_alias;
+ return true;
+ }
+ ++alias_stats.aliasing_component_refs_p_no_alias;
return false;
}
-/* Return true if we can determine that component references REF1 and REF2,
- that are within a common DECL, cannot overlap. */
+/* Try to disambiguate REF1 and REF2 under the assumption that MATCH1 and
+ MATCH2 either point to the same address or are disjoint.
+ MATCH1 and MATCH2 are assumed to be ref in the access path of REF1 and REF2
+ respectively or NULL in the case we established equivalence of bases.
-static bool
-nonoverlapping_component_refs_of_decl_p (tree ref1, tree ref2)
+ This test works by matching the initial segment of the access path
+ and does not rely on TBAA thus is safe for !flag_strict_aliasing if
+ match was determined without use of TBAA oracle.
+
+ Return 1 if we can determine that component references REF1 and REF2,
+ that are within a common DECL, cannot overlap.
+
+ Return 0 if paths are same and thus there is nothing to disambiguate more
+ (i.e. there is must alias assuming there is must alias between MATCH1 and
+ MATCH2)
+
+ Return -1 if we can not determine 0 or 1 - this happens when we met
+ non-matching types was met in the path.
+ In this case it may make sense to continue by other disambiguation
+ oracles. */
+
+static int
+nonoverlapping_component_refs_since_match_p (tree match1, tree ref1,
+ tree match2, tree ref2)
{
auto_vec<tree, 16> component_refs1;
auto_vec<tree, 16> component_refs2;
@@ -877,33 +1155,55 @@ nonoverlapping_component_refs_of_decl_p (tree ref1, tree ref2)
/* Create the stack of handled components for REF1. */
while (handled_component_p (ref1))
{
- component_refs1.safe_push (ref1);
+ if (TREE_CODE (ref1) == VIEW_CONVERT_EXPR
+ || TREE_CODE (ref1) == BIT_FIELD_REF)
+ component_refs1.truncate (0);
+ else
+ component_refs1.safe_push (ref1);
+ if (ref1 == match1)
+ break;
ref1 = TREE_OPERAND (ref1, 0);
}
- if (TREE_CODE (ref1) == MEM_REF)
+ if (TREE_CODE (ref1) == MEM_REF && ref1 != match1)
{
if (!integer_zerop (TREE_OPERAND (ref1, 1)))
- return false;
- ref1 = TREE_OPERAND (TREE_OPERAND (ref1, 0), 0);
+ {
+ ++alias_stats.nonoverlapping_component_refs_since_match_p_may_alias;
+ return -1;
+ }
+ }
+ /* TODO: Handle TARGET_MEM_REF later. */
+ if (TREE_CODE (ref1) == TARGET_MEM_REF && ref1 != match1)
+ {
+ ++alias_stats.nonoverlapping_component_refs_since_match_p_may_alias;
+ return -1;
}
/* Create the stack of handled components for REF2. */
while (handled_component_p (ref2))
{
- component_refs2.safe_push (ref2);
+ if (TREE_CODE (ref2) == VIEW_CONVERT_EXPR
+ || TREE_CODE (ref2) == BIT_FIELD_REF)
+ component_refs2.truncate (0);
+ else
+ component_refs2.safe_push (ref2);
+ if (ref2 == match2)
+ break;
ref2 = TREE_OPERAND (ref2, 0);
}
- if (TREE_CODE (ref2) == MEM_REF)
+ if (TREE_CODE (ref2) == MEM_REF && ref2 != match2)
{
if (!integer_zerop (TREE_OPERAND (ref2, 1)))
- return false;
- ref2 = TREE_OPERAND (TREE_OPERAND (ref2, 0), 0);
+ {
+ ++alias_stats.nonoverlapping_component_refs_since_match_p_may_alias;
+ return -1;
+ }
+ }
+ if (TREE_CODE (ref2) == TARGET_MEM_REF && ref2 != match2)
+ {
+ ++alias_stats.nonoverlapping_component_refs_since_match_p_may_alias;
+ return -1;
}
-
- /* Bases must be either same or uncomparable. */
- gcc_checking_assert (ref1 == ref2
- || (DECL_P (ref1) && DECL_P (ref2)
- && compare_base_decls (ref1, ref2) != 0));
/* Pop the stacks in parallel and examine the COMPONENT_REFs of the same
rank. This is sufficient because we start from the same DECL and you
@@ -916,7 +1216,11 @@ nonoverlapping_component_refs_of_decl_p (tree ref1, tree ref2)
do
{
if (component_refs1.is_empty ())
- return false;
+ {
+ ++alias_stats
+ .nonoverlapping_component_refs_since_match_p_may_alias;
+ return 0;
+ }
ref1 = component_refs1.pop ();
}
while (!RECORD_OR_UNION_TYPE_P (TREE_TYPE (TREE_OPERAND (ref1, 0))));
@@ -924,7 +1228,11 @@ nonoverlapping_component_refs_of_decl_p (tree ref1, tree ref2)
do
{
if (component_refs2.is_empty ())
- return false;
+ {
+ ++alias_stats
+ .nonoverlapping_component_refs_since_match_p_may_alias;
+ return 0;
+ }
ref2 = component_refs2.pop ();
}
while (!RECORD_OR_UNION_TYPE_P (TREE_TYPE (TREE_OPERAND (ref2, 0))));
@@ -932,7 +1240,11 @@ nonoverlapping_component_refs_of_decl_p (tree ref1, tree ref2)
/* Beware of BIT_FIELD_REF. */
if (TREE_CODE (ref1) != COMPONENT_REF
|| TREE_CODE (ref2) != COMPONENT_REF)
- return false;
+ {
+ ++alias_stats
+ .nonoverlapping_component_refs_since_match_p_may_alias;
+ return -1;
+ }
tree field1 = TREE_OPERAND (ref1, 1);
tree field2 = TREE_OPERAND (ref2, 1);
@@ -945,7 +1257,10 @@ nonoverlapping_component_refs_of_decl_p (tree ref1, tree ref2)
/* We cannot disambiguate fields in a union or qualified union. */
if (type1 != type2 || TREE_CODE (type1) != RECORD_TYPE)
- return false;
+ {
+ ++alias_stats.nonoverlapping_component_refs_since_match_p_may_alias;
+ return -1;
+ }
if (field1 != field2)
{
@@ -953,16 +1268,26 @@ nonoverlapping_component_refs_of_decl_p (tree ref1, tree ref2)
same. */
if (DECL_BIT_FIELD_REPRESENTATIVE (field1) == field2
|| DECL_BIT_FIELD_REPRESENTATIVE (field2) == field1)
- return false;
+ {
+ ++alias_stats
+ .nonoverlapping_component_refs_since_match_p_may_alias;
+ return 0;
+ }
/* Different fields of the same record type cannot overlap.
??? Bitfields can overlap at RTL level so punt on them. */
if (DECL_BIT_FIELD (field1) && DECL_BIT_FIELD (field2))
- return false;
- return true;
+ {
+ ++alias_stats
+ .nonoverlapping_component_refs_since_match_p_may_alias;
+ return 0;
+ }
+ ++alias_stats.nonoverlapping_component_refs_since_match_p_no_alias;
+ return 1;
}
}
- return false;
+ ++alias_stats.nonoverlapping_component_refs_since_match_p_may_alias;
+ return 0;
}
/* qsort compare function to sort FIELD_DECLs after their
@@ -983,47 +1308,76 @@ ncr_compar (const void *field1_, const void *field2_)
}
/* Return true if we can determine that the fields referenced cannot
- overlap for any pair of objects. */
+ overlap for any pair of objects. This relies on TBAA. */
static bool
nonoverlapping_component_refs_p (const_tree x, const_tree y)
{
if (!flag_strict_aliasing
|| !x || !y
- || TREE_CODE (x) != COMPONENT_REF
- || TREE_CODE (y) != COMPONENT_REF)
- return false;
+ || !handled_component_p (x)
+ || !handled_component_p (y))
+ {
+ ++alias_stats.nonoverlapping_component_refs_p_may_alias;
+ return false;
+ }
auto_vec<const_tree, 16> fieldsx;
- while (TREE_CODE (x) == COMPONENT_REF)
+ while (handled_component_p (x))
{
- tree field = TREE_OPERAND (x, 1);
- tree type = DECL_FIELD_CONTEXT (field);
- if (TREE_CODE (type) == RECORD_TYPE)
- fieldsx.safe_push (field);
+ if (TREE_CODE (x) == COMPONENT_REF)
+ {
+ tree field = TREE_OPERAND (x, 1);
+ tree type = DECL_FIELD_CONTEXT (field);
+ if (TREE_CODE (type) == RECORD_TYPE)
+ fieldsx.safe_push (field);
+ }
+ else if (TREE_CODE (x) == VIEW_CONVERT_EXPR
+ || TREE_CODE (x) == BIT_FIELD_REF)
+ fieldsx.truncate (0);
x = TREE_OPERAND (x, 0);
}
if (fieldsx.length () == 0)
return false;
auto_vec<const_tree, 16> fieldsy;
- while (TREE_CODE (y) == COMPONENT_REF)
+ while (handled_component_p (y))
{
- tree field = TREE_OPERAND (y, 1);
- tree type = DECL_FIELD_CONTEXT (field);
- if (TREE_CODE (type) == RECORD_TYPE)
- fieldsy.safe_push (TREE_OPERAND (y, 1));
+ if (TREE_CODE (y) == COMPONENT_REF)
+ {
+ tree field = TREE_OPERAND (y, 1);
+ tree type = DECL_FIELD_CONTEXT (field);
+ if (TREE_CODE (type) == RECORD_TYPE)
+ fieldsy.safe_push (TREE_OPERAND (y, 1));
+ }
+ else if (TREE_CODE (y) == VIEW_CONVERT_EXPR
+ || TREE_CODE (y) == BIT_FIELD_REF)
+ fieldsy.truncate (0);
y = TREE_OPERAND (y, 0);
}
if (fieldsy.length () == 0)
- return false;
+ {
+ ++alias_stats.nonoverlapping_component_refs_p_may_alias;
+ return false;
+ }
/* Most common case first. */
if (fieldsx.length () == 1
&& fieldsy.length () == 1)
- return ((DECL_FIELD_CONTEXT (fieldsx[0])
- == DECL_FIELD_CONTEXT (fieldsy[0]))
- && fieldsx[0] != fieldsy[0]
- && !(DECL_BIT_FIELD (fieldsx[0]) && DECL_BIT_FIELD (fieldsy[0])));
+ {
+ if ((DECL_FIELD_CONTEXT (fieldsx[0])
+ == DECL_FIELD_CONTEXT (fieldsy[0]))
+ && fieldsx[0] != fieldsy[0]
+ && !(DECL_BIT_FIELD (fieldsx[0]) && DECL_BIT_FIELD (fieldsy[0])))
+ {
+ ++alias_stats.nonoverlapping_component_refs_p_no_alias;
+ return true;
+ }
+ else
+ {
+ ++alias_stats.nonoverlapping_component_refs_p_may_alias;
+ return false;
+ }
+ }
if (fieldsx.length () == 2)
{
@@ -1058,12 +1412,16 @@ nonoverlapping_component_refs_p (const_tree x, const_tree y)
same. */
if (DECL_BIT_FIELD_REPRESENTATIVE (fieldx) == fieldy
|| DECL_BIT_FIELD_REPRESENTATIVE (fieldy) == fieldx)
- return false;
+ ;
/* Different fields of the same record type cannot overlap.
??? Bitfields can overlap at RTL level so punt on them. */
- if (DECL_BIT_FIELD (fieldx) && DECL_BIT_FIELD (fieldy))
- return false;
- return true;
+ else if (DECL_BIT_FIELD (fieldx) && DECL_BIT_FIELD (fieldy))
+ ;
+ else
+ {
+ ++alias_stats.nonoverlapping_component_refs_p_no_alias;
+ return true;
+ }
}
}
if (TYPE_UID (typex) < TYPE_UID (typey))
@@ -1081,6 +1439,7 @@ nonoverlapping_component_refs_p (const_tree x, const_tree y)
}
while (1);
+ ++alias_stats.nonoverlapping_component_refs_p_may_alias;
return false;
}
@@ -1111,7 +1470,8 @@ decl_refs_may_alias_p (tree ref1, tree base1,
so we disambiguate component references manually. */
if (ref1 && ref2
&& handled_component_p (ref1) && handled_component_p (ref2)
- && nonoverlapping_component_refs_of_decl_p (ref1, ref2))
+ && nonoverlapping_component_refs_since_match_p (NULL, ref1,
+ NULL, ref2) == 1)
return false;
return true;
@@ -1161,10 +1521,8 @@ indirect_ref_may_alias_decl_p (tree ref1 ATTRIBUTE_UNUSED, tree base1,
if (!flag_strict_aliasing || !tbaa_p)
return true;
- ptrtype1 = TREE_TYPE (TREE_OPERAND (base1, 1));
-
/* If the alias set for a pointer access is zero all bets are off. */
- if (base1_alias_set == 0)
+ if (base1_alias_set == 0 || base2_alias_set == 0)
return true;
/* When we are trying to disambiguate an access with a pointer dereference
@@ -1182,19 +1540,19 @@ indirect_ref_may_alias_decl_p (tree ref1 ATTRIBUTE_UNUSED, tree base1,
if (base1_alias_set != base2_alias_set
&& !alias_sets_conflict_p (base1_alias_set, base2_alias_set))
return false;
+
+ ptrtype1 = TREE_TYPE (TREE_OPERAND (base1, 1));
+
/* If the size of the access relevant for TBAA through the pointer
is bigger than the size of the decl we can't possibly access the
decl via that pointer. */
- if (DECL_SIZE (base2) && COMPLETE_TYPE_P (TREE_TYPE (ptrtype1))
- && poly_int_tree_p (DECL_SIZE (base2))
- && poly_int_tree_p (TYPE_SIZE (TREE_TYPE (ptrtype1)))
- /* ??? This in turn may run afoul when a decl of type T which is
+ if (/* ??? This in turn may run afoul when a decl of type T which is
a member of union type U is accessed through a pointer to
type U and sizeof T is smaller than sizeof U. */
- && TREE_CODE (TREE_TYPE (ptrtype1)) != UNION_TYPE
+ TREE_CODE (TREE_TYPE (ptrtype1)) != UNION_TYPE
&& TREE_CODE (TREE_TYPE (ptrtype1)) != QUAL_UNION_TYPE
- && known_lt (wi::to_poly_widest (DECL_SIZE (base2)),
- wi::to_poly_widest (TYPE_SIZE (TREE_TYPE (ptrtype1)))))
+ && compare_sizes (DECL_SIZE (base2),
+ TYPE_SIZE (TREE_TYPE (ptrtype1))) < 0)
return false;
if (!ref2)
@@ -1209,11 +1567,16 @@ indirect_ref_may_alias_decl_p (tree ref1 ATTRIBUTE_UNUSED, tree base1,
poly_offset_int doffset2 = offset2;
if (TREE_CODE (dbase2) == MEM_REF
|| TREE_CODE (dbase2) == TARGET_MEM_REF)
- doffset2 -= mem_ref_offset (dbase2) << LOG2_BITS_PER_UNIT;
+ {
+ doffset2 -= mem_ref_offset (dbase2) << LOG2_BITS_PER_UNIT;
+ tree ptrtype2 = TREE_TYPE (TREE_OPERAND (dbase2, 1));
+ /* If second reference is view-converted, give up now. */
+ if (same_type_for_tbaa (TREE_TYPE (dbase2), TREE_TYPE (ptrtype2)) != 1)
+ return true;
+ }
- /* If either reference is view-converted, give up now. */
- if (same_type_for_tbaa (TREE_TYPE (base1), TREE_TYPE (ptrtype1)) != 1
- || same_type_for_tbaa (TREE_TYPE (dbase2), TREE_TYPE (base2)) != 1)
+ /* If first reference is view-converted, give up now. */
+ if (same_type_for_tbaa (TREE_TYPE (base1), TREE_TYPE (ptrtype1)) != 1)
return true;
/* If both references are through the same type, they do not alias
@@ -1222,16 +1585,21 @@ indirect_ref_may_alias_decl_p (tree ref1 ATTRIBUTE_UNUSED, tree base1,
For MEM_REFs we require that the component-ref offset we computed
is relative to the start of the type which we ensure by
comparing rvalue and access type and disregarding the constant
- pointer offset. */
- if ((TREE_CODE (base1) != TARGET_MEM_REF
+ pointer offset.
+
+ But avoid treating variable length arrays as "objects", instead assume they
+ can overlap by an exact multiple of their element size.
+ See gcc.dg/torture/alias-2.c. */
+ if (((TREE_CODE (base1) != TARGET_MEM_REF
|| (!TMR_INDEX (base1) && !TMR_INDEX2 (base1)))
- && same_type_for_tbaa (TREE_TYPE (base1), TREE_TYPE (dbase2)) == 1)
+ && (TREE_CODE (dbase2) != TARGET_MEM_REF
+ || (!TMR_INDEX (dbase2) && !TMR_INDEX2 (dbase2))))
+ && same_type_for_tbaa (TREE_TYPE (base1), TREE_TYPE (dbase2)) == 1
+ && (TREE_CODE (TREE_TYPE (base1)) != ARRAY_TYPE
+ || (TYPE_SIZE (TREE_TYPE (base1))
+ && TREE_CODE (TYPE_SIZE (TREE_TYPE (base1))) == INTEGER_CST)))
return ranges_maybe_overlap_p (doffset1, max_size1, doffset2, max_size2);
- if (ref1 && ref2
- && nonoverlapping_component_refs_p (ref1, ref2))
- return false;
-
/* Do access-path based disambiguation. */
if (ref1 && ref2
&& (handled_component_p (ref1) || handled_component_p (ref2)))
@@ -1240,7 +1608,7 @@ indirect_ref_may_alias_decl_p (tree ref1 ATTRIBUTE_UNUSED, tree base1,
offset1, max_size1,
ref2,
ref2_alias_set, base2_alias_set,
- offset2, max_size2, true);
+ offset2, max_size2);
return true;
}
@@ -1300,8 +1668,16 @@ indirect_refs_may_alias_p (tree ref1 ATTRIBUTE_UNUSED, tree base1,
{
poly_offset_int moff1 = mem_ref_offset (base1) << LOG2_BITS_PER_UNIT;
poly_offset_int moff2 = mem_ref_offset (base2) << LOG2_BITS_PER_UNIT;
- return ranges_maybe_overlap_p (offset1 + moff1, max_size1,
- offset2 + moff2, max_size2);
+ if (!ranges_maybe_overlap_p (offset1 + moff1, max_size1,
+ offset2 + moff2, max_size2))
+ return false;
+ if (ref1 && ref2)
+ {
+ int res = nonoverlapping_component_refs_since_match_p (NULL, ref1,
+ NULL, ref2);
+ if (res != -1)
+ return !res;
+ }
}
if (!ptr_derefs_may_alias_p (ptr1, ptr2))
return false;
@@ -1318,6 +1694,16 @@ indirect_refs_may_alias_p (tree ref1 ATTRIBUTE_UNUSED, tree base1,
|| base2_alias_set == 0)
return true;
+ /* Do type-based disambiguation. */
+ if (base1_alias_set != base2_alias_set
+ && !alias_sets_conflict_p (base1_alias_set, base2_alias_set))
+ return false;
+
+ /* If either reference is view-converted, give up now. */
+ if (same_type_for_tbaa (TREE_TYPE (base1), TREE_TYPE (ptrtype1)) != 1
+ || same_type_for_tbaa (TREE_TYPE (base2), TREE_TYPE (ptrtype2)) != 1)
+ return true;
+
/* If both references are through the same type, they do not alias
if the accesses do not overlap. This does extra disambiguation
for mixed/pointer accesses but requires strict aliasing. */
@@ -1325,29 +1711,14 @@ indirect_refs_may_alias_p (tree ref1 ATTRIBUTE_UNUSED, tree base1,
|| (!TMR_INDEX (base1) && !TMR_INDEX2 (base1)))
&& (TREE_CODE (base2) != TARGET_MEM_REF
|| (!TMR_INDEX (base2) && !TMR_INDEX2 (base2)))
- && same_type_for_tbaa (TREE_TYPE (base1), TREE_TYPE (ptrtype1)) == 1
- && same_type_for_tbaa (TREE_TYPE (base2), TREE_TYPE (ptrtype2)) == 1
&& same_type_for_tbaa (TREE_TYPE (ptrtype1),
TREE_TYPE (ptrtype2)) == 1
/* But avoid treating arrays as "objects", instead assume they
- can overlap by an exact multiple of their element size. */
+ can overlap by an exact multiple of their element size.
+ See gcc.dg/torture/alias-2.c. */
&& TREE_CODE (TREE_TYPE (ptrtype1)) != ARRAY_TYPE)
return ranges_maybe_overlap_p (offset1, max_size1, offset2, max_size2);
- /* Do type-based disambiguation. */
- if (base1_alias_set != base2_alias_set
- && !alias_sets_conflict_p (base1_alias_set, base2_alias_set))
- return false;
-
- /* If either reference is view-converted, give up now. */
- if (same_type_for_tbaa (TREE_TYPE (base1), TREE_TYPE (ptrtype1)) != 1
- || same_type_for_tbaa (TREE_TYPE (base2), TREE_TYPE (ptrtype2)) != 1)
- return true;
-
- if (ref1 && ref2
- && nonoverlapping_component_refs_p (ref1, ref2))
- return false;
-
/* Do access-path based disambiguation. */
if (ref1 && ref2
&& (handled_component_p (ref1) || handled_component_p (ref2)))
@@ -1356,15 +1727,15 @@ indirect_refs_may_alias_p (tree ref1 ATTRIBUTE_UNUSED, tree base1,
offset1, max_size1,
ref2,
ref2_alias_set, base2_alias_set,
- offset2, max_size2, false);
+ offset2, max_size2);
return true;
}
/* Return true, if the two memory references REF1 and REF2 may alias. */
-bool
-refs_may_alias_p_1 (ao_ref *ref1, ao_ref *ref2, bool tbaa_p)
+static bool
+refs_may_alias_p_2 (ao_ref *ref1, ao_ref *ref2, bool tbaa_p)
{
tree base1, base2;
poly_int64 offset1 = 0, offset2 = 0;
@@ -1521,6 +1892,20 @@ refs_may_alias_p_1 (ao_ref *ref1, ao_ref *ref2, bool tbaa_p)
gcc_unreachable ();
}
+/* Return true, if the two memory references REF1 and REF2 may alias
+ and update statistics. */
+
+bool
+refs_may_alias_p_1 (ao_ref *ref1, ao_ref *ref2, bool tbaa_p)
+{
+ bool res = refs_may_alias_p_2 (ref1, ref2, tbaa_p);
+ if (res)
+ ++alias_stats.refs_may_alias_p_may_alias;
+ else
+ ++alias_stats.refs_may_alias_p_no_alias;
+ return res;
+}
+
static bool
refs_may_alias_p (tree ref1, ao_ref *ref2, bool tbaa_p)
{
@@ -1533,15 +1918,9 @@ bool
refs_may_alias_p (tree ref1, tree ref2, bool tbaa_p)
{
ao_ref r1, r2;
- bool res;
ao_ref_init (&r1, ref1);
ao_ref_init (&r2, ref2);
- res = refs_may_alias_p_1 (&r1, &r2, tbaa_p);
- if (res)
- ++alias_stats.refs_may_alias_p_may_alias;
- else
- ++alias_stats.refs_may_alias_p_no_alias;
- return res;
+ return refs_may_alias_p_1 (&r1, &r2, tbaa_p);
}
/* Returns true if there is a anti-dependence for the STORE that
@@ -2533,13 +2912,36 @@ stmt_kills_ref_p (gimple *stmt, ao_ref *ref)
case BUILT_IN_MEMSET_CHK:
case BUILT_IN_STRNCPY:
case BUILT_IN_STPNCPY:
+ case BUILT_IN_CALLOC:
{
/* For a must-alias check we need to be able to constrain
the access properly. */
if (!ref->max_size_known_p ())
return false;
- tree dest = gimple_call_arg (stmt, 0);
- tree len = gimple_call_arg (stmt, 2);
+ tree dest;
+ tree len;
+
+ /* In execution order a calloc call will never kill
+ anything. However, DSE will (ab)use this interface
+ to ask if a calloc call writes the same memory locations
+ as a later assignment, memset, etc. So handle calloc
+ in the expected way. */
+ if (DECL_FUNCTION_CODE (callee) == BUILT_IN_CALLOC)
+ {
+ tree arg0 = gimple_call_arg (stmt, 0);
+ tree arg1 = gimple_call_arg (stmt, 1);
+ if (TREE_CODE (arg0) != INTEGER_CST
+ || TREE_CODE (arg1) != INTEGER_CST)
+ return false;
+
+ dest = gimple_call_lhs (stmt);
+ len = fold_build2 (MULT_EXPR, TREE_TYPE (arg0), arg0, arg1);
+ }
+ else
+ {
+ dest = gimple_call_arg (stmt, 0);
+ len = gimple_call_arg (stmt, 2);
+ }
if (!poly_int_tree_p (len))
return false;
tree rbase = ref->base;
@@ -2820,6 +3222,7 @@ walk_non_aliased_vuses (ao_ref *ref, tree vuse,
res = NULL;
break;
}
+ --limit;
if (stmt_may_clobber_ref_p_1 (def_stmt, ref))
{
if (!translate)
diff --git a/gcc/tree-ssa-copy.c b/gcc/tree-ssa-copy.c
index 8953263..28ff8d3 100644
--- a/gcc/tree-ssa-copy.c
+++ b/gcc/tree-ssa-copy.c
@@ -545,13 +545,12 @@ fini_copy_prop (void)
duplicate_ssa_name_ptr_info (copy_of[i].value,
SSA_NAME_PTR_INFO (var));
/* Points-to information is cfg insensitive,
- but alignment info might be cfg sensitive, if it
- e.g. is derived from VRP derived non-zero bits.
- So, do not copy alignment info if the two SSA_NAMEs
- aren't defined in the same basic block. */
+ but [E]VRP might record context sensitive alignment
+ info, non-nullness, etc. So reset context sensitive
+ info if the two SSA_NAMEs aren't defined in the same
+ basic block. */
if (var_bb != copy_of_bb)
- mark_ptr_info_alignment_unknown
- (SSA_NAME_PTR_INFO (copy_of[i].value));
+ reset_flow_sensitive_info (copy_of[i].value);
}
else if (!POINTER_TYPE_P (TREE_TYPE (var))
&& SSA_NAME_RANGE_INFO (var)
diff --git a/gcc/tree-ssa-dce.c b/gcc/tree-ssa-dce.c
index 4853f0bd..c73fbab 100644
--- a/gcc/tree-ssa-dce.c
+++ b/gcc/tree-ssa-dce.c
@@ -245,6 +245,17 @@ mark_stmt_if_obviously_necessary (gimple *stmt, bool aggressive)
mark_stmt_necessary (stmt, true);
return;
}
+ /* IFN_GOACC_LOOP calls are necessary in that they are used to
+ represent parameter (i.e. step, bound) of a lowered OpenACC
+ partitioned loop. But this kind of partitioned loop might not
+ survive from aggressive loop removal for it has loop exit and
+ is assumed to be finite. Therefore, we need to explicitly mark
+ these calls. (An example is libgomp.oacc-c-c++-common/pr84955.c) */
+ if (gimple_call_internal_p (stmt, IFN_GOACC_LOOP))
+ {
+ mark_stmt_necessary (stmt, true);
+ return;
+ }
if (!gimple_call_lhs (stmt))
return;
break;
@@ -1328,12 +1339,16 @@ eliminate_unnecessary_stmts (void)
update_stmt (stmt);
release_ssa_name (name);
- /* GOMP_SIMD_LANE or ASAN_POISON without lhs is not
- needed. */
+ /* GOMP_SIMD_LANE (unless three argument) or ASAN_POISON
+ without lhs is not needed. */
if (gimple_call_internal_p (stmt))
switch (gimple_call_internal_fn (stmt))
{
case IFN_GOMP_SIMD_LANE:
+ if (gimple_call_num_args (stmt) >= 3
+ && !integer_nonzerop (gimple_call_arg (stmt, 2)))
+ break;
+ /* FALLTHRU */
case IFN_ASAN_POISON:
remove_dead_stmt (&gsi, bb, to_remove_edges);
break;
diff --git a/gcc/tree-ssa-dse.c b/gcc/tree-ssa-dse.c
index aa998f4..df05a55 100644
--- a/gcc/tree-ssa-dse.c
+++ b/gcc/tree-ssa-dse.c
@@ -1,4 +1,4 @@
-/* Dead store elimination
+/* Dead and redundant store elimination
Copyright (C) 2004-2019 Free Software Foundation, Inc.
This file is part of GCC.
@@ -41,12 +41,20 @@ along with GCC; see the file COPYING3. If not see
A dead store is a store into a memory location which will later be
overwritten by another store without any intervening loads. In this
- case the earlier store can be deleted.
+ case the earlier store can be deleted or trimmed if the store
+ was partially dead.
+
+ A redundant store is a store into a memory location which stores
+ the exact same value as a prior store to the same memory location.
+ While this can often be handled by dead store elimination, removing
+ the redundant store is often better than removing or trimming the
+ dead store.
In our SSA + virtual operand world we use immediate uses of virtual
- operands to detect dead stores. If a store's virtual definition
+ operands to detect these cases. If a store's virtual definition
is used precisely once by a later store to the same location which
- post dominates the first store, then the first store is dead.
+ post dominates the first store, then the first store is dead. If
+ the data stored is the same, then the second store is redundant.
The single use of the store's virtual definition ensures that
there are no intervening aliased loads and the requirement that
@@ -58,7 +66,9 @@ along with GCC; see the file COPYING3. If not see
the point immediately before the later store. Again, the single
use of the virtual definition and the post-dominance relationship
ensure that such movement would be safe. Clearly if there are
- back to back stores, then the second is redundant.
+ back to back stores, then the second is makes the first dead. If
+ the second store stores the same value, then the second store is
+ redundant.
Reviewing section 10.7.2 in Morgan's "Building an Optimizing Compiler"
may also help in understanding this code since it discusses the
@@ -66,6 +76,8 @@ along with GCC; see the file COPYING3. If not see
fact, they are the same transformation applied to different views of
the CFG. */
+static void delete_dead_or_redundant_assignment (gimple_stmt_iterator *, const char *);
+static void delete_dead_or_redundant_call (gimple_stmt_iterator *, const char *);
/* Bitmap of blocks that have had EH statements cleaned. We should
remove their dead edges eventually. */
@@ -98,6 +110,9 @@ initialize_ao_ref_for_dse (gimple *stmt, ao_ref *write)
case BUILT_IN_MEMCPY:
case BUILT_IN_MEMMOVE:
case BUILT_IN_MEMSET:
+ case BUILT_IN_MEMCPY_CHK:
+ case BUILT_IN_MEMMOVE_CHK:
+ case BUILT_IN_MEMSET_CHK:
{
tree size = NULL_TREE;
if (gimple_call_num_args (stmt) == 3)
@@ -106,6 +121,26 @@ initialize_ao_ref_for_dse (gimple *stmt, ao_ref *write)
ao_ref_init_from_ptr_and_size (write, ptr, size);
return true;
}
+
+ /* A calloc call can never be dead, but it can make
+ subsequent stores redundant if they store 0 into
+ the same memory locations. */
+ case BUILT_IN_CALLOC:
+ {
+ tree nelem = gimple_call_arg (stmt, 0);
+ tree selem = gimple_call_arg (stmt, 1);
+ tree lhs;
+ if (TREE_CODE (nelem) == INTEGER_CST
+ && TREE_CODE (selem) == INTEGER_CST
+ && (lhs = gimple_call_lhs (stmt)) != NULL_TREE)
+ {
+ tree size = fold_build2 (MULT_EXPR, TREE_TYPE (nelem),
+ nelem, selem);
+ ao_ref_init_from_ptr_and_size (write, lhs, size);
+ return true;
+ }
+ }
+
default:
break;
}
@@ -434,6 +469,8 @@ maybe_trim_memstar_call (ao_ref *ref, sbitmap live, gimple *stmt)
{
case BUILT_IN_MEMCPY:
case BUILT_IN_MEMMOVE:
+ case BUILT_IN_MEMCPY_CHK:
+ case BUILT_IN_MEMMOVE_CHK:
{
int head_trim, tail_trim;
compute_trims (ref, live, &head_trim, &tail_trim, stmt);
@@ -455,6 +492,7 @@ maybe_trim_memstar_call (ao_ref *ref, sbitmap live, gimple *stmt)
}
case BUILT_IN_MEMSET:
+ case BUILT_IN_MEMSET_CHK:
{
int head_trim, tail_trim;
compute_trims (ref, live, &head_trim, &tail_trim, stmt);
@@ -551,6 +589,74 @@ check_name (tree, tree *idx, void *data)
return true;
}
+/* STMT stores the value 0 into one or more memory locations
+ (via memset, empty constructor, calloc call, etc).
+
+ See if there is a subsequent store of the value 0 to one
+ or more of the same memory location(s). If so, the subsequent
+ store is redundant and can be removed.
+
+ The subsequent stores could be via memset, empty constructors,
+ simple MEM stores, etc. */
+
+static void
+dse_optimize_redundant_stores (gimple *stmt)
+{
+ int cnt = 0;
+
+ /* We could do something fairly complex and look through PHIs
+ like DSE_CLASSIFY_STORE, but it doesn't seem to be worth
+ the effort.
+
+ Look at all the immediate uses of the VDEF (which are obviously
+ dominated by STMT). See if one or more stores 0 into the same
+ memory locations a STMT, if so remove the immediate use statements. */
+ tree defvar = gimple_vdef (stmt);
+ imm_use_iterator ui;
+ gimple *use_stmt;
+ FOR_EACH_IMM_USE_STMT (use_stmt, ui, defvar)
+ {
+ /* Limit stmt walking. */
+ if (++cnt > PARAM_VALUE (PARAM_DSE_MAX_ALIAS_QUERIES_PER_STORE))
+ BREAK_FROM_IMM_USE_STMT (ui);
+
+ /* If USE_STMT stores 0 into one or more of the same locations
+ as STMT and STMT would kill USE_STMT, then we can just remove
+ USE_STMT. */
+ tree fndecl;
+ if ((is_gimple_assign (use_stmt)
+ && gimple_vdef (use_stmt)
+ && ((gimple_assign_rhs_code (use_stmt) == CONSTRUCTOR
+ && CONSTRUCTOR_NELTS (gimple_assign_rhs1 (use_stmt)) == 0
+ && !gimple_clobber_p (stmt))
+ || (gimple_assign_rhs_code (use_stmt) == INTEGER_CST
+ && integer_zerop (gimple_assign_rhs1 (use_stmt)))))
+ || (gimple_call_builtin_p (use_stmt, BUILT_IN_NORMAL)
+ && (fndecl = gimple_call_fndecl (use_stmt)) != NULL
+ && (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_MEMSET
+ || DECL_FUNCTION_CODE (fndecl) == BUILT_IN_MEMSET_CHK)
+ && integer_zerop (gimple_call_arg (use_stmt, 1))))
+ {
+ ao_ref write;
+
+ if (!initialize_ao_ref_for_dse (use_stmt, &write))
+ BREAK_FROM_IMM_USE_STMT (ui)
+
+ if (valid_ao_ref_for_dse (&write)
+ && stmt_kills_ref_p (stmt, &write))
+ {
+ gimple_stmt_iterator gsi = gsi_for_stmt (use_stmt);
+ if (is_gimple_assign (use_stmt))
+ delete_dead_or_redundant_assignment (&gsi, "redundant");
+ else if (is_gimple_call (use_stmt))
+ delete_dead_or_redundant_call (&gsi, "redundant");
+ else
+ gcc_unreachable ();
+ }
+ }
+ }
+}
+
/* A helper of dse_optimize_stmt.
Given a GIMPLE_ASSIGN in STMT that writes to REF, classify it
according to downstream uses and defs. Sets *BY_CLOBBER_P to true
@@ -763,12 +869,12 @@ private:
/* Delete a dead call at GSI, which is mem* call of some kind. */
static void
-delete_dead_call (gimple_stmt_iterator *gsi)
+delete_dead_or_redundant_call (gimple_stmt_iterator *gsi, const char *type)
{
gimple *stmt = gsi_stmt (*gsi);
if (dump_file && (dump_flags & TDF_DETAILS))
{
- fprintf (dump_file, " Deleted dead call: ");
+ fprintf (dump_file, " Deleted %s call: ", type);
print_gimple_stmt (dump_file, stmt, 0, dump_flags);
fprintf (dump_file, "\n");
}
@@ -797,12 +903,12 @@ delete_dead_call (gimple_stmt_iterator *gsi)
/* Delete a dead store at GSI, which is a gimple assignment. */
static void
-delete_dead_assignment (gimple_stmt_iterator *gsi)
+delete_dead_or_redundant_assignment (gimple_stmt_iterator *gsi, const char *type)
{
gimple *stmt = gsi_stmt (*gsi);
if (dump_file && (dump_flags & TDF_DETAILS))
{
- fprintf (dump_file, " Deleted dead store: ");
+ fprintf (dump_file, " Deleted %s store: ", type);
print_gimple_stmt (dump_file, stmt, 0, dump_flags);
fprintf (dump_file, "\n");
}
@@ -855,11 +961,15 @@ dse_dom_walker::dse_optimize_stmt (gimple_stmt_iterator *gsi)
some builtin calls. */
if (gimple_call_builtin_p (stmt, BUILT_IN_NORMAL))
{
- switch (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt)))
+ tree fndecl = gimple_call_fndecl (stmt);
+ switch (DECL_FUNCTION_CODE (fndecl))
{
case BUILT_IN_MEMCPY:
case BUILT_IN_MEMMOVE:
case BUILT_IN_MEMSET:
+ case BUILT_IN_MEMCPY_CHK:
+ case BUILT_IN_MEMMOVE_CHK:
+ case BUILT_IN_MEMSET_CHK:
{
/* Occasionally calls with an explicit length of zero
show up in the IL. It's pointless to do analysis
@@ -867,10 +977,18 @@ dse_dom_walker::dse_optimize_stmt (gimple_stmt_iterator *gsi)
tree size = gimple_call_arg (stmt, 2);
if (integer_zerop (size))
{
- delete_dead_call (gsi);
+ delete_dead_or_redundant_call (gsi, "dead");
return;
}
+ /* If this is a memset call that initializes an object
+ to zero, it may be redundant with an earlier memset
+ or empty CONSTRUCTOR of a larger object. */
+ if ((DECL_FUNCTION_CODE (fndecl) == BUILT_IN_MEMSET
+ || DECL_FUNCTION_CODE (fndecl) == BUILT_IN_MEMSET_CHK)
+ && integer_zerop (gimple_call_arg (stmt, 1)))
+ dse_optimize_redundant_stores (stmt);
+
enum dse_store_status store_status;
m_byte_tracking_enabled
= setup_live_bytes_from_ref (&ref, m_live_bytes);
@@ -887,10 +1005,14 @@ dse_dom_walker::dse_optimize_stmt (gimple_stmt_iterator *gsi)
}
if (store_status == DSE_STORE_DEAD)
- delete_dead_call (gsi);
+ delete_dead_or_redundant_call (gsi, "dead");
return;
}
+ case BUILT_IN_CALLOC:
+ /* We already know the arguments are integer constants. */
+ dse_optimize_redundant_stores (stmt);
+
default:
return;
}
@@ -900,6 +1022,18 @@ dse_dom_walker::dse_optimize_stmt (gimple_stmt_iterator *gsi)
{
bool by_clobber_p = false;
+ /* First see if this store is a CONSTRUCTOR and if there
+ are subsequent CONSTRUCTOR stores which are totally
+ subsumed by this statement. If so remove the subsequent
+ CONSTRUCTOR store.
+
+ This will tend to make fewer calls into memset with longer
+ arguments. */
+ if (gimple_assign_rhs_code (stmt) == CONSTRUCTOR
+ && CONSTRUCTOR_NELTS (gimple_assign_rhs1 (stmt)) == 0
+ && !gimple_clobber_p (stmt))
+ dse_optimize_redundant_stores (stmt);
+
/* Self-assignments are zombies. */
if (operand_equal_p (gimple_assign_rhs1 (stmt),
gimple_assign_lhs (stmt), 0))
@@ -930,7 +1064,7 @@ dse_dom_walker::dse_optimize_stmt (gimple_stmt_iterator *gsi)
&& !by_clobber_p)
return;
- delete_dead_assignment (gsi);
+ delete_dead_or_redundant_assignment (gsi, "dead");
}
}
diff --git a/gcc/tree-ssa-forwprop.c b/gcc/tree-ssa-forwprop.c
index 32b5a15..2828c6b 100644
--- a/gcc/tree-ssa-forwprop.c
+++ b/gcc/tree-ssa-forwprop.c
@@ -2065,71 +2065,87 @@ simplify_vector_constructor (gimple_stmt_iterator *gsi)
conv_code = ERROR_MARK;
maybe_ident = true;
tree one_constant = NULL_TREE;
+ tree one_nonconstant = NULL_TREE;
auto_vec<tree> constants;
constants.safe_grow_cleared (nelts);
FOR_EACH_VEC_SAFE_ELT (CONSTRUCTOR_ELTS (op), i, elt)
{
tree ref, op1;
+ unsigned int elem;
if (i >= nelts)
return false;
+ /* Look for elements extracted and possibly converted from
+ another vector. */
op1 = get_bit_field_ref_def (elt->value, conv_code);
- if (op1)
+ if (op1
+ && TREE_CODE ((ref = TREE_OPERAND (op1, 0))) == SSA_NAME
+ && VECTOR_TYPE_P (TREE_TYPE (ref))
+ && useless_type_conversion_p (TREE_TYPE (op1),
+ TREE_TYPE (TREE_TYPE (ref)))
+ && known_eq (bit_field_size (op1), elem_size)
+ && constant_multiple_p (bit_field_offset (op1),
+ elem_size, &elem))
{
- ref = TREE_OPERAND (op1, 0);
unsigned int j;
for (j = 0; j < 2; ++j)
{
if (!orig[j])
{
- if (TREE_CODE (ref) != SSA_NAME)
- return false;
- if (! VECTOR_TYPE_P (TREE_TYPE (ref))
- || ! useless_type_conversion_p (TREE_TYPE (op1),
- TREE_TYPE (TREE_TYPE (ref))))
- return false;
- if (j && !useless_type_conversion_p (TREE_TYPE (orig[0]),
- TREE_TYPE (ref)))
- return false;
- orig[j] = ref;
- break;
+ if (j == 0
+ || useless_type_conversion_p (TREE_TYPE (orig[0]),
+ TREE_TYPE (ref)))
+ break;
}
else if (ref == orig[j])
break;
}
- if (j == 2)
- return false;
-
- unsigned int elt;
- if (maybe_ne (bit_field_size (op1), elem_size)
- || !constant_multiple_p (bit_field_offset (op1), elem_size, &elt))
- return false;
- if (j)
- elt += nelts;
- if (elt != i)
- maybe_ident = false;
- sel.quick_push (elt);
+ /* Found a suitable vector element. */
+ if (j < 2)
+ {
+ orig[j] = ref;
+ if (j)
+ elem += nelts;
+ if (elem != i)
+ maybe_ident = false;
+ sel.quick_push (elem);
+ continue;
+ }
+ /* Else fallthru. */
}
- else if (CONSTANT_CLASS_P (elt->value))
+ /* Handle elements not extracted from a vector.
+ 1. constants by permuting with constant vector
+ 2. a unique non-constant element by permuting with a splat vector */
+ if (orig[1]
+ && orig[1] != error_mark_node)
+ return false;
+ orig[1] = error_mark_node;
+ if (CONSTANT_CLASS_P (elt->value))
{
- if (orig[1]
- && orig[1] != error_mark_node)
+ if (one_nonconstant)
return false;
- orig[1] = error_mark_node;
if (!one_constant)
one_constant = elt->value;
constants[i] = elt->value;
- sel.quick_push (i + nelts);
- maybe_ident = false;
}
else
- return false;
+ {
+ if (one_constant)
+ return false;
+ if (!one_nonconstant)
+ one_nonconstant = elt->value;
+ else if (!operand_equal_p (one_nonconstant, elt->value, 0))
+ return false;
+ }
+ sel.quick_push (i + nelts);
+ maybe_ident = false;
}
if (i < nelts)
return false;
- if (! VECTOR_TYPE_P (TREE_TYPE (orig[0]))
+ if (! orig[0]
+ || ! VECTOR_TYPE_P (TREE_TYPE (orig[0]))
|| maybe_ne (TYPE_VECTOR_SUBPARTS (type),
TYPE_VECTOR_SUBPARTS (TREE_TYPE (orig[0]))))
return false;
@@ -2165,9 +2181,19 @@ simplify_vector_constructor (gimple_stmt_iterator *gsi)
GET_MODE_SIZE (TYPE_MODE (type))))
return false;
op2 = vec_perm_indices_to_tree (mask_type, indices);
+ bool convert_orig0 = false;
if (!orig[1])
orig[1] = orig[0];
- if (orig[1] == error_mark_node)
+ else if (orig[1] == error_mark_node
+ && one_nonconstant)
+ {
+ gimple_seq seq = NULL;
+ orig[1] = gimple_build_vector_from_val (&seq, UNKNOWN_LOCATION,
+ type, one_nonconstant);
+ gsi_insert_seq_before (gsi, seq, GSI_SAME_STMT);
+ convert_orig0 = true;
+ }
+ else if (orig[1] == error_mark_node)
{
tree_vector_builder vec (type, nelts, 1);
for (unsigned i = 0; i < nelts; ++i)
@@ -2177,11 +2203,12 @@ simplify_vector_constructor (gimple_stmt_iterator *gsi)
/* ??? Push a don't-care value. */
vec.quick_push (one_constant);
orig[1] = vec.build ();
+ convert_orig0 = true;
}
if (conv_code == ERROR_MARK)
gimple_assign_set_rhs_with_ops (gsi, VEC_PERM_EXPR, orig[0],
orig[1], op2);
- else if (TREE_CODE (orig[1]) == VECTOR_CST)
+ else if (convert_orig0)
{
gimple *conv
= gimple_build_assign (make_ssa_name (type), conv_code, orig[0]);
diff --git a/gcc/tree-ssa-loop-im.c b/gcc/tree-ssa-loop-im.c
index 56d8e8e..2064c29 100644
--- a/gcc/tree-ssa-loop-im.c
+++ b/gcc/tree-ssa-loop-im.c
@@ -115,9 +115,10 @@ struct mem_ref_loc
struct im_mem_ref
{
- unsigned id : 31; /* ID assigned to the memory reference
+ unsigned id : 30; /* ID assigned to the memory reference
(its index in memory_accesses.refs_list) */
unsigned ref_canonical : 1; /* Whether mem.ref was canonicalized. */
+ unsigned ref_decomposed : 1; /* Whether the ref was hashed from mem. */
hashval_t hash; /* Its hash value. */
/* The memory access itself and associated caching of alias-oracle
@@ -173,7 +174,8 @@ inline bool
mem_ref_hasher::equal (const im_mem_ref *mem1, const ao_ref *obj2)
{
if (obj2->max_size_known_p ())
- return (operand_equal_p (mem1->mem.base, obj2->base, 0)
+ return (mem1->ref_decomposed
+ && operand_equal_p (mem1->mem.base, obj2->base, 0)
&& known_eq (mem1->mem.offset, obj2->offset)
&& known_eq (mem1->mem.size, obj2->size)
&& known_eq (mem1->mem.max_size, obj2->max_size)
@@ -1389,6 +1391,7 @@ mem_ref_alloc (ao_ref *mem, unsigned hash, unsigned id)
ao_ref_init (&ref->mem, error_mark_node);
ref->id = id;
ref->ref_canonical = false;
+ ref->ref_decomposed = false;
ref->hash = hash;
ref->stored = NULL;
bitmap_initialize (&ref->indep_loop, &lim_bitmap_obstack);
@@ -1476,6 +1479,7 @@ gather_mem_refs_stmt (struct loop *loop, gimple *stmt)
HOST_WIDE_INT offset, size, max_size;
poly_int64 saved_maxsize = aor.max_size, mem_off;
tree mem_base;
+ bool ref_decomposed;
if (aor.max_size_known_p ()
&& aor.offset.is_constant (&offset)
&& aor.size.is_constant (&size)
@@ -1489,12 +1493,14 @@ gather_mem_refs_stmt (struct loop *loop, gimple *stmt)
aor.size)
&& (mem_base = get_addr_base_and_unit_offset (aor.ref, &mem_off)))
{
+ ref_decomposed = true;
hash = iterative_hash_expr (ao_ref_base (&aor), 0);
hash = iterative_hash_host_wide_int (offset, hash);
hash = iterative_hash_host_wide_int (size, hash);
}
else
{
+ ref_decomposed = false;
hash = iterative_hash_expr (aor.ref, 0);
aor.max_size = -1;
}
@@ -1543,6 +1549,7 @@ gather_mem_refs_stmt (struct loop *loop, gimple *stmt)
{
id = memory_accesses.refs_list.length ();
ref = mem_ref_alloc (&aor, hash, id);
+ ref->ref_decomposed = ref_decomposed;
memory_accesses.refs_list.safe_push (ref);
*slot = ref;
diff --git a/gcc/tree-ssa-loop-ivopts.c b/gcc/tree-ssa-loop-ivopts.c
index 9864b59..bbae83c 100644
--- a/gcc/tree-ssa-loop-ivopts.c
+++ b/gcc/tree-ssa-loop-ivopts.c
@@ -944,36 +944,19 @@ stmt_after_increment (struct loop *loop, struct iv_cand *cand, gimple *stmt)
}
}
-/* Returns true if EXP is a ssa name that occurs in an abnormal phi node. */
+/* walk_tree callback for contains_abnormal_ssa_name_p. */
-static bool
-abnormal_ssa_name_p (tree exp)
+static tree
+contains_abnormal_ssa_name_p_1 (tree *tp, int *walk_subtrees, void *)
{
- if (!exp)
- return false;
-
- if (TREE_CODE (exp) != SSA_NAME)
- return false;
+ if (TREE_CODE (*tp) == SSA_NAME
+ && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (*tp))
+ return *tp;
- return SSA_NAME_OCCURS_IN_ABNORMAL_PHI (exp) != 0;
-}
-
-/* Returns false if BASE or INDEX contains a ssa name that occurs in an
- abnormal phi node. Callback for for_each_index. */
+ if (!EXPR_P (*tp))
+ *walk_subtrees = 0;
-static bool
-idx_contains_abnormal_ssa_name_p (tree base, tree *index,
- void *data ATTRIBUTE_UNUSED)
-{
- if (TREE_CODE (base) == ARRAY_REF || TREE_CODE (base) == ARRAY_RANGE_REF)
- {
- if (abnormal_ssa_name_p (TREE_OPERAND (base, 2)))
- return false;
- if (abnormal_ssa_name_p (TREE_OPERAND (base, 3)))
- return false;
- }
-
- return !abnormal_ssa_name_p (*index);
+ return NULL_TREE;
}
/* Returns true if EXPR contains a ssa name that occurs in an
@@ -982,61 +965,8 @@ idx_contains_abnormal_ssa_name_p (tree base, tree *index,
bool
contains_abnormal_ssa_name_p (tree expr)
{
- enum tree_code code;
- enum tree_code_class codeclass;
-
- if (!expr)
- return false;
-
- code = TREE_CODE (expr);
- codeclass = TREE_CODE_CLASS (code);
-
- if (code == CALL_EXPR)
- {
- tree arg;
- call_expr_arg_iterator iter;
- FOR_EACH_CALL_EXPR_ARG (arg, iter, expr)
- if (contains_abnormal_ssa_name_p (arg))
- return true;
- return false;
- }
-
- if (code == SSA_NAME)
- return SSA_NAME_OCCURS_IN_ABNORMAL_PHI (expr) != 0;
-
- if (code == INTEGER_CST
- || is_gimple_min_invariant (expr))
- return false;
-
- if (code == ADDR_EXPR)
- return !for_each_index (&TREE_OPERAND (expr, 0),
- idx_contains_abnormal_ssa_name_p,
- NULL);
-
- if (code == COND_EXPR)
- return contains_abnormal_ssa_name_p (TREE_OPERAND (expr, 0))
- || contains_abnormal_ssa_name_p (TREE_OPERAND (expr, 1))
- || contains_abnormal_ssa_name_p (TREE_OPERAND (expr, 2));
-
- switch (codeclass)
- {
- case tcc_binary:
- case tcc_comparison:
- if (contains_abnormal_ssa_name_p (TREE_OPERAND (expr, 1)))
- return true;
-
- /* Fallthru. */
- case tcc_unary:
- if (contains_abnormal_ssa_name_p (TREE_OPERAND (expr, 0)))
- return true;
-
- break;
-
- default:
- gcc_unreachable ();
- }
-
- return false;
+ return walk_tree_without_duplicates
+ (&expr, contains_abnormal_ssa_name_p_1, NULL) != NULL_TREE;
}
/* Returns the structure describing number of iterations determined from
@@ -2451,11 +2381,13 @@ get_mem_type_for_internal_fn (gcall *call, tree *op_p)
switch (gimple_call_internal_fn (call))
{
case IFN_MASK_LOAD:
+ case IFN_MASK_LOAD_LANES:
if (op_p == gimple_call_arg_ptr (call, 0))
return TREE_TYPE (gimple_call_lhs (call));
return NULL_TREE;
case IFN_MASK_STORE:
+ case IFN_MASK_STORE_LANES:
if (op_p == gimple_call_arg_ptr (call, 0))
return TREE_TYPE (gimple_call_arg (call, 3));
return NULL_TREE;
@@ -3500,6 +3432,26 @@ add_iv_candidate_for_use (struct ivopts_data *data, struct iv_use *use)
basetype = sizetype;
record_common_cand (data, build_int_cst (basetype, 0), iv->step, use);
+ /* Compare the cost of an address with an unscaled index with the cost of
+ an address with a scaled index and add candidate if useful. */
+ poly_int64 step;
+ if (use != NULL
+ && poly_int_tree_p (iv->step, &step)
+ && address_p (use->type))
+ {
+ poly_int64 new_step;
+ unsigned int fact = preferred_mem_scale_factor
+ (use->iv->base,
+ TYPE_MODE (use->mem_type),
+ optimize_loop_for_speed_p (data->current_loop));
+
+ if (fact != 1
+ && multiple_p (step, fact, &new_step))
+ add_candidate (data, size_int (0),
+ wide_int_to_tree (sizetype, new_step),
+ true, NULL);
+ }
+
/* Record common candidate with constant offset stripped in base.
Like the use itself, we also add candidate directly for it. */
base = strip_offset (iv->base, &offset);
@@ -3782,6 +3734,63 @@ prepare_decl_rtl (tree *expr_p, int *ws, void *data)
return NULL_TREE;
}
+/* Predict whether the given loop will be transformed in the RTL
+ doloop_optimize pass. Attempt to duplicate some doloop_optimize checks.
+ This is only for target independent checks, see targetm.predict_doloop_p
+ for the target dependent ones.
+
+ Note that according to some initial investigation, some checks like costly
+ niter check and invalid stmt scanning don't have much gains among general
+ cases, so keep this as simple as possible first.
+
+ Some RTL specific checks seems unable to be checked in gimple, if any new
+ checks or easy checks _are_ missing here, please add them. */
+
+static bool ATTRIBUTE_UNUSED
+generic_predict_doloop_p (struct ivopts_data *data)
+{
+ struct loop *loop = data->current_loop;
+
+ /* Call target hook for target dependent checks. */
+ if (!targetm.predict_doloop_p (loop))
+ {
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ fprintf (dump_file, "Predict doloop failure due to"
+ " target specific checks.\n");
+ return false;
+ }
+
+ /* Similar to doloop_optimize, check iteration description to know it's
+ suitable or not. Keep it as simple as possible, feel free to extend it
+ if you find any multiple exits cases matter. */
+ edge exit = single_dom_exit (loop);
+ struct tree_niter_desc *niter_desc;
+ if (!exit || !(niter_desc = niter_for_exit (data, exit)))
+ {
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ fprintf (dump_file, "Predict doloop failure due to"
+ " unexpected niters.\n");
+ return false;
+ }
+
+ /* Similar to doloop_optimize, check whether iteration count too small
+ and not profitable. */
+ HOST_WIDE_INT est_niter = get_estimated_loop_iterations_int (loop);
+ if (est_niter == -1)
+ est_niter = get_likely_max_loop_iterations_int (loop);
+ if (est_niter >= 0 && est_niter < 3)
+ {
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ fprintf (dump_file,
+ "Predict doloop failure due to"
+ " too few iterations (%u).\n",
+ (unsigned int) est_niter);
+ return false;
+ }
+
+ return true;
+}
+
/* Determines cost of the computation of EXPR. */
static unsigned
@@ -7112,6 +7121,8 @@ get_alias_ptr_type_for_ptr_address (iv_use *use)
{
case IFN_MASK_LOAD:
case IFN_MASK_STORE:
+ case IFN_MASK_LOAD_LANES:
+ case IFN_MASK_STORE_LANES:
/* The second argument contains the correct alias type. */
gcc_assert (use->op_p = gimple_call_arg_ptr (call, 0));
return TREE_TYPE (gimple_call_arg (call, 1));
diff --git a/gcc/tree-ssa-loop-niter.c b/gcc/tree-ssa-loop-niter.c
index 470b6a2..f513859 100644
--- a/gcc/tree-ssa-loop-niter.c
+++ b/gcc/tree-ssa-loop-niter.c
@@ -1125,8 +1125,15 @@ number_of_iterations_ne (struct loop *loop, tree type, affine_iv *iv,
}
c = fold_build2 (EXACT_DIV_EXPR, niter_type, c, d);
- tmp = fold_build2 (MULT_EXPR, niter_type, c, inverse (s, bound));
- niter->niter = fold_build2 (BIT_AND_EXPR, niter_type, tmp, bound);
+ if (integer_onep (s))
+ {
+ niter->niter = c;
+ }
+ else
+ {
+ tmp = fold_build2 (MULT_EXPR, niter_type, c, inverse (s, bound));
+ niter->niter = fold_build2 (BIT_AND_EXPR, niter_type, tmp, bound);
+ }
return true;
}
@@ -1977,8 +1984,8 @@ simplify_replace_tree (tree expr, tree old, tree new_tree,
enough, and return the new expression. If STOP is specified, stop
expanding if EXPR equals to it. */
-tree
-expand_simple_operations (tree expr, tree stop)
+static tree
+expand_simple_operations (tree expr, tree stop, hash_map<tree, tree> &cache)
{
unsigned i, n;
tree ret = NULL_TREE, e, ee, e1;
@@ -1998,7 +2005,24 @@ expand_simple_operations (tree expr, tree stop)
for (i = 0; i < n; i++)
{
e = TREE_OPERAND (expr, i);
- ee = expand_simple_operations (e, stop);
+ /* SCEV analysis feeds us with a proper expression
+ graph matching the SSA graph. Avoid turning it
+ into a tree here, thus handle tree sharing
+ properly.
+ ??? The SSA walk below still turns the SSA graph
+ into a tree but until we find a testcase do not
+ introduce additional tree sharing here. */
+ bool existed_p;
+ tree &cee = cache.get_or_insert (e, &existed_p);
+ if (existed_p)
+ ee = cee;
+ else
+ {
+ cee = e;
+ ee = expand_simple_operations (e, stop, cache);
+ if (ee != e)
+ *cache.get (e) = ee;
+ }
if (e == ee)
continue;
@@ -2038,7 +2062,7 @@ expand_simple_operations (tree expr, tree stop)
&& src->loop_father != dest->loop_father)
return expr;
- return expand_simple_operations (e, stop);
+ return expand_simple_operations (e, stop, cache);
}
if (gimple_code (stmt) != GIMPLE_ASSIGN)
return expr;
@@ -2058,7 +2082,7 @@ expand_simple_operations (tree expr, tree stop)
return e;
if (code == SSA_NAME)
- return expand_simple_operations (e, stop);
+ return expand_simple_operations (e, stop, cache);
else if (code == ADDR_EXPR)
{
poly_int64 offset;
@@ -2067,7 +2091,8 @@ expand_simple_operations (tree expr, tree stop)
if (base
&& TREE_CODE (base) == MEM_REF)
{
- ee = expand_simple_operations (TREE_OPERAND (base, 0), stop);
+ ee = expand_simple_operations (TREE_OPERAND (base, 0), stop,
+ cache);
return fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (expr), ee,
wide_int_to_tree (sizetype,
mem_ref_offset (base)
@@ -2082,7 +2107,7 @@ expand_simple_operations (tree expr, tree stop)
{
CASE_CONVERT:
/* Casts are simple. */
- ee = expand_simple_operations (e, stop);
+ ee = expand_simple_operations (e, stop, cache);
return fold_build1 (code, TREE_TYPE (expr), ee);
case PLUS_EXPR:
@@ -2097,7 +2122,7 @@ expand_simple_operations (tree expr, tree stop)
if (!is_gimple_min_invariant (e1))
return expr;
- ee = expand_simple_operations (e, stop);
+ ee = expand_simple_operations (e, stop, cache);
return fold_build2 (code, TREE_TYPE (expr), ee, e1);
default:
@@ -2105,6 +2130,13 @@ expand_simple_operations (tree expr, tree stop)
}
}
+tree
+expand_simple_operations (tree expr, tree stop)
+{
+ hash_map<tree, tree> cache;
+ return expand_simple_operations (expr, stop, cache);
+}
+
/* Tries to simplify EXPR using the condition COND. Returns the simplified
expression (or EXPR unchanged, if no simplification was possible). */
@@ -2798,6 +2830,27 @@ finite_loop_p (struct loop *loop)
loop->num);
return true;
}
+
+ if (flag_finite_loops)
+ {
+ unsigned i;
+ vec<edge> exits = get_loop_exit_edges (loop);
+ edge ex;
+
+ /* If the loop has a normal exit, we can assume it will terminate. */
+ FOR_EACH_VEC_ELT (exits, i, ex)
+ if (!(ex->flags & (EDGE_EH | EDGE_ABNORMAL | EDGE_FAKE)))
+ {
+ exits.release ();
+ if (dump_file)
+ fprintf (dump_file, "Assume loop %i to be finite: it has an exit "
+ "and -ffinite-loops is on.\n", loop->num);
+ return true;
+ }
+
+ exits.release ();
+ }
+
return false;
}
diff --git a/gcc/tree-ssa-loop.c b/gcc/tree-ssa-loop.c
index 1ac6cee..208c583 100644
--- a/gcc/tree-ssa-loop.c
+++ b/gcc/tree-ssa-loop.c
@@ -768,9 +768,9 @@ get_lsm_tmp_name (tree ref, unsigned n, const char *suffix)
ns[1] = 0;
lsm_tmp_name_add (ns);
}
- return lsm_tmp_name;
if (suffix != NULL)
lsm_tmp_name_add (suffix);
+ return lsm_tmp_name;
}
/* Computes an estimated number of insns in LOOP, weighted by WEIGHTS. */
diff --git a/gcc/tree-ssa-operands.c b/gcc/tree-ssa-operands.c
index 899d47f..e643b33 100644
--- a/gcc/tree-ssa-operands.c
+++ b/gcc/tree-ssa-operands.c
@@ -974,14 +974,14 @@ verify_ssa_operands (struct function *fn, gimple *stmt)
def = SSA_NAME_VAR (def);
if (build_vdef != def)
{
- error ("virtual definition of statement not up-to-date");
+ error ("virtual definition of statement not up to date");
return true;
}
if (gimple_vdef (stmt)
&& ((def_p = gimple_vdef_op (stmt)) == NULL_DEF_OPERAND_P
|| DEF_FROM_PTR (def_p) != gimple_vdef (stmt)))
{
- error ("virtual def operand missing for stmt");
+ error ("virtual def operand missing for statement");
return true;
}
@@ -991,14 +991,14 @@ verify_ssa_operands (struct function *fn, gimple *stmt)
use = SSA_NAME_VAR (use);
if (build_vuse != use)
{
- error ("virtual use of statement not up-to-date");
+ error ("virtual use of statement not up to date");
return true;
}
if (gimple_vuse (stmt)
&& ((use_p = gimple_vuse_op (stmt)) == NULL_USE_OPERAND_P
|| USE_FROM_PTR (use_p) != gimple_vuse (stmt)))
{
- error ("virtual use operand missing for stmt");
+ error ("virtual use operand missing for statement");
return true;
}
@@ -1015,7 +1015,7 @@ verify_ssa_operands (struct function *fn, gimple *stmt)
}
if (i == build_uses.length ())
{
- error ("excess use operand for stmt");
+ error ("excess use operand for statement");
debug_generic_expr (USE_FROM_PTR (use_p));
return true;
}
@@ -1025,14 +1025,14 @@ verify_ssa_operands (struct function *fn, gimple *stmt)
FOR_EACH_VEC_ELT (build_uses, i, op)
if (op != NULL)
{
- error ("use operand missing for stmt");
+ error ("use operand missing for statement");
debug_generic_expr (*op);
return true;
}
if (gimple_has_volatile_ops (stmt) != volatile_p)
{
- error ("stmt volatile flag not up-to-date");
+ error ("statement volatile flag not up to date");
return true;
}
diff --git a/gcc/tree-ssa-phiopt.c b/gcc/tree-ssa-phiopt.c
index 90674a2..7088ff9 100644
--- a/gcc/tree-ssa-phiopt.c
+++ b/gcc/tree-ssa-phiopt.c
@@ -504,7 +504,24 @@ factor_out_conditional_conversion (edge e0, edge e1, gphi *phi,
gsi = gsi_for_stmt (arg0_def_stmt);
gsi_prev_nondebug (&gsi);
if (!gsi_end_p (gsi))
- return NULL;
+ {
+ if (gassign *assign
+ = dyn_cast <gassign *> (gsi_stmt (gsi)))
+ {
+ tree lhs = gimple_assign_lhs (assign);
+ enum tree_code ass_code
+ = gimple_assign_rhs_code (assign);
+ if (ass_code != MAX_EXPR && ass_code != MIN_EXPR)
+ return NULL;
+ if (lhs != gimple_assign_rhs1 (arg0_def_stmt))
+ return NULL;
+ gsi_prev_nondebug (&gsi);
+ if (!gsi_end_p (gsi))
+ return NULL;
+ }
+ else
+ return NULL;
+ }
gsi = gsi_for_stmt (arg0_def_stmt);
gsi_next_nondebug (&gsi);
if (!gsi_end_p (gsi))
diff --git a/gcc/tree-ssa-pre.c b/gcc/tree-ssa-pre.c
index 09335fa..086f8c3 100644
--- a/gcc/tree-ssa-pre.c
+++ b/gcc/tree-ssa-pre.c
@@ -3601,92 +3601,80 @@ do_hoist_insertion (basic_block block)
return new_stuff;
}
-/* Do a dominator walk on the control flow graph, and insert computations
- of values as necessary for PRE and hoisting. */
-
-static bool
-insert_aux (basic_block block, bool do_pre, bool do_hoist)
-{
- basic_block son;
- bool new_stuff = false;
-
- if (block)
- {
- basic_block dom;
- dom = get_immediate_dominator (CDI_DOMINATORS, block);
- if (dom)
- {
- unsigned i;
- bitmap_iterator bi;
- bitmap_set_t newset;
-
- /* First, update the AVAIL_OUT set with anything we may have
- inserted higher up in the dominator tree. */
- newset = NEW_SETS (dom);
- if (newset)
- {
- /* Note that we need to value_replace both NEW_SETS, and
- AVAIL_OUT. For both the case of NEW_SETS, the value may be
- represented by some non-simple expression here that we want
- to replace it with. */
- FOR_EACH_EXPR_ID_IN_SET (newset, i, bi)
- {
- pre_expr expr = expression_for_id (i);
- bitmap_value_replace_in_set (NEW_SETS (block), expr);
- bitmap_value_replace_in_set (AVAIL_OUT (block), expr);
- }
- }
-
- /* Insert expressions for partial redundancies. */
- if (do_pre && !single_pred_p (block))
- {
- new_stuff |= do_pre_regular_insertion (block, dom);
- if (do_partial_partial)
- new_stuff |= do_pre_partial_partial_insertion (block, dom);
- }
-
- /* Insert expressions for hoisting. */
- if (do_hoist && EDGE_COUNT (block->succs) >= 2)
- new_stuff |= do_hoist_insertion (block);
- }
- }
- for (son = first_dom_son (CDI_DOMINATORS, block);
- son;
- son = next_dom_son (CDI_DOMINATORS, son))
- {
- new_stuff |= insert_aux (son, do_pre, do_hoist);
- }
-
- return new_stuff;
-}
-
/* Perform insertion of partially redundant and hoistable values. */
static void
insert (void)
{
- bool new_stuff = true;
basic_block bb;
- int num_iterations = 0;
FOR_ALL_BB_FN (bb, cfun)
NEW_SETS (bb) = bitmap_set_new ();
- while (new_stuff)
+ int *rpo = XNEWVEC (int, n_basic_blocks_for_fn (cfun));
+ int rpo_num = pre_and_rev_post_order_compute (NULL, rpo, false);
+
+ int num_iterations = 0;
+ bool changed;
+ do
{
num_iterations++;
if (dump_file && dump_flags & TDF_DETAILS)
fprintf (dump_file, "Starting insert iteration %d\n", num_iterations);
- new_stuff = insert_aux (ENTRY_BLOCK_PTR_FOR_FN (cfun), flag_tree_pre,
- flag_code_hoisting);
+
+ changed = false;
+ for (int idx = 0; idx < rpo_num; ++idx)
+ {
+ basic_block block = BASIC_BLOCK_FOR_FN (cfun, rpo[idx]);
+ basic_block dom = get_immediate_dominator (CDI_DOMINATORS, block);
+ if (dom)
+ {
+ unsigned i;
+ bitmap_iterator bi;
+ bitmap_set_t newset;
+
+ /* First, update the AVAIL_OUT set with anything we may have
+ inserted higher up in the dominator tree. */
+ newset = NEW_SETS (dom);
+ if (newset)
+ {
+ /* Note that we need to value_replace both NEW_SETS, and
+ AVAIL_OUT. For both the case of NEW_SETS, the value may be
+ represented by some non-simple expression here that we want
+ to replace it with. */
+ FOR_EACH_EXPR_ID_IN_SET (newset, i, bi)
+ {
+ pre_expr expr = expression_for_id (i);
+ bitmap_value_replace_in_set (NEW_SETS (block), expr);
+ bitmap_value_replace_in_set (AVAIL_OUT (block), expr);
+ }
+ }
+
+ /* Insert expressions for partial redundancies. */
+ if (flag_tree_pre && !single_pred_p (block))
+ {
+ changed |= do_pre_regular_insertion (block, dom);
+ if (do_partial_partial)
+ changed |= do_pre_partial_partial_insertion (block, dom);
+ }
+
+ /* Insert expressions for hoisting. */
+ if (flag_code_hoisting && EDGE_COUNT (block->succs) >= 2)
+ changed |= do_hoist_insertion (block);
+ }
+ }
/* Clear the NEW sets before the next iteration. We have already
- fully propagated its contents. */
- if (new_stuff)
+ fully propagated its contents. */
+ if (changed)
FOR_ALL_BB_FN (bb, cfun)
bitmap_set_free (NEW_SETS (bb));
}
+ while (changed);
+
statistics_histogram_event (cfun, "insert iterations", num_iterations);
+
+ free (rpo);
}
@@ -4195,7 +4183,7 @@ pass_pre::execute (function *fun)
/* This has to happen before VN runs because
loop_optimizer_init may create new phis, etc. */
loop_optimizer_init (LOOPS_NORMAL);
- split_critical_edges ();
+ split_edges_for_insertion ();
scev_initialize ();
calculate_dominance_info (CDI_DOMINATORS);
diff --git a/gcc/tree-ssa-reassoc.c b/gcc/tree-ssa-reassoc.c
index 32bff97..9c1a9a6 100644
--- a/gcc/tree-ssa-reassoc.c
+++ b/gcc/tree-ssa-reassoc.c
@@ -2039,9 +2039,6 @@ optimize_ops_list (enum tree_code opcode,
i++;
}
- length = ops->length ();
- oelast = ops->last ();
-
if (iterate)
optimize_ops_list (opcode, ops);
}
@@ -4812,6 +4809,7 @@ rewrite_expr_tree_parallel (gassign *stmt, int width,
else
{
stmts[i] = build_and_add_sum (TREE_TYPE (last_rhs1), op1, op2, opcode);
+ gimple_set_visited (stmts[i], true);
}
if (dump_file && (dump_flags & TDF_DETAILS))
{
@@ -6012,12 +6010,7 @@ reassociate_bb (basic_block bb)
{
machine_mode mode = TYPE_MODE (TREE_TYPE (lhs));
int ops_num = ops.length ();
- int width = get_reassociation_width (ops_num, rhs_code, mode);
-
- if (dump_file && (dump_flags & TDF_DETAILS))
- fprintf (dump_file,
- "Width = %d was chosen for reassociation\n", width);
-
+ int width;
/* For binary bit operations, if there are at least 3
operands and the last last operand in OPS is a constant,
@@ -6031,10 +6024,21 @@ reassociate_bb (basic_block bb)
&& TREE_CODE (ops.last ()->op) == INTEGER_CST)
std::swap (*ops[0], *ops[ops_num - 1]);
- if (width > 1
- && ops.length () > 3)
- rewrite_expr_tree_parallel (as_a <gassign *> (stmt),
- width, ops);
+ /* Only rewrite the expression tree to parallel in the
+ last reassoc pass to avoid useless work back-and-forth
+ with initial linearization. */
+ if (!reassoc_insert_powi_p
+ && ops.length () > 3
+ && (width = get_reassociation_width (ops_num, rhs_code,
+ mode)) > 1)
+ {
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ fprintf (dump_file,
+ "Width = %d was chosen for reassociation\n",
+ width);
+ rewrite_expr_tree_parallel (as_a <gassign *> (stmt),
+ width, ops);
+ }
else
{
/* When there are three operands left, we want
diff --git a/gcc/tree-ssa-sccvn.c b/gcc/tree-ssa-sccvn.c
index 219fb9e..6b39d63 100644
--- a/gcc/tree-ssa-sccvn.c
+++ b/gcc/tree-ssa-sccvn.c
@@ -791,39 +791,6 @@ vn_reference_eq (const_vn_reference_t const vr1, const_vn_reference_t const vr2)
static void
copy_reference_ops_from_ref (tree ref, vec<vn_reference_op_s> *result)
{
- if (TREE_CODE (ref) == TARGET_MEM_REF)
- {
- vn_reference_op_s temp;
-
- result->reserve (3);
-
- memset (&temp, 0, sizeof (temp));
- temp.type = TREE_TYPE (ref);
- temp.opcode = TREE_CODE (ref);
- temp.op0 = TMR_INDEX (ref);
- temp.op1 = TMR_STEP (ref);
- temp.op2 = TMR_OFFSET (ref);
- temp.off = -1;
- temp.clique = MR_DEPENDENCE_CLIQUE (ref);
- temp.base = MR_DEPENDENCE_BASE (ref);
- result->quick_push (temp);
-
- memset (&temp, 0, sizeof (temp));
- temp.type = NULL_TREE;
- temp.opcode = ERROR_MARK;
- temp.op0 = TMR_INDEX2 (ref);
- temp.off = -1;
- result->quick_push (temp);
-
- memset (&temp, 0, sizeof (temp));
- temp.type = NULL_TREE;
- temp.opcode = TREE_CODE (TMR_BASE (ref));
- temp.op0 = TMR_BASE (ref);
- temp.off = -1;
- result->quick_push (temp);
- return;
- }
-
/* For non-calls, store the information that makes up the address. */
tree orig = ref;
while (ref)
@@ -853,6 +820,20 @@ copy_reference_ops_from_ref (tree ref, vec<vn_reference_op_s> *result)
temp.base = MR_DEPENDENCE_BASE (ref);
temp.reverse = REF_REVERSE_STORAGE_ORDER (ref);
break;
+ case TARGET_MEM_REF:
+ /* The base address gets its own vn_reference_op_s structure. */
+ temp.op0 = TMR_INDEX (ref);
+ temp.op1 = TMR_STEP (ref);
+ temp.op2 = TMR_OFFSET (ref);
+ temp.clique = MR_DEPENDENCE_CLIQUE (ref);
+ temp.base = MR_DEPENDENCE_BASE (ref);
+ result->safe_push (temp);
+ memset (&temp, 0, sizeof (temp));
+ temp.type = NULL_TREE;
+ temp.opcode = ERROR_MARK;
+ temp.op0 = TMR_INDEX2 (ref);
+ temp.off = -1;
+ break;
case BIT_FIELD_REF:
/* Record bits, position and storage order. */
temp.op0 = TREE_OPERAND (ref, 1);
@@ -2242,7 +2223,7 @@ vn_reference_lookup_3 (ao_ref *ref, tree vuse, void *vr_,
tree rhs = gimple_assign_rhs1 (def_stmt);
if (TREE_CODE (rhs) == SSA_NAME)
rhs = SSA_VAL (rhs);
- len = native_encode_expr (gimple_assign_rhs1 (def_stmt),
+ len = native_encode_expr (rhs,
buffer, sizeof (buffer),
(offseti - offset2) / BITS_PER_UNIT);
if (len > 0 && len * BITS_PER_UNIT >= maxsizei)
@@ -4059,6 +4040,7 @@ visit_reference_op_call (tree lhs, gcall *stmt)
vr2->hashcode = vr1.hashcode;
vr2->result = lhs;
vr2->result_vdef = vdef_val;
+ vr2->value_id = 0;
slot = valid_info->references->find_slot_with_hash (vr2, vr2->hashcode,
INSERT);
gcc_assert (!*slot);
@@ -5978,7 +5960,7 @@ insert_related_predicates_on_edge (enum tree_code code, tree *ops, edge pred_e)
static unsigned
process_bb (rpo_elim &avail, basic_block bb,
bool bb_visited, bool iterate_phis, bool iterate, bool eliminate,
- bool do_region, bitmap exit_bbs)
+ bool do_region, bitmap exit_bbs, bool skip_phis)
{
unsigned todo = 0;
edge_iterator ei;
@@ -5989,7 +5971,8 @@ process_bb (rpo_elim &avail, basic_block bb,
/* If we are in loop-closed SSA preserve this state. This is
relevant when called on regions from outside of FRE/PRE. */
bool lc_phi_nodes = false;
- if (loops_state_satisfies_p (LOOP_CLOSED_SSA))
+ if (!skip_phis
+ && loops_state_satisfies_p (LOOP_CLOSED_SSA))
FOR_EACH_EDGE (e, ei, bb->preds)
if (e->src->loop_father != e->dest->loop_father
&& flow_loop_nested_p (e->dest->loop_father,
@@ -6010,67 +5993,68 @@ process_bb (rpo_elim &avail, basic_block bb,
}
/* Value-number all defs in the basic-block. */
- for (gphi_iterator gsi = gsi_start_phis (bb); !gsi_end_p (gsi);
- gsi_next (&gsi))
- {
- gphi *phi = gsi.phi ();
- tree res = PHI_RESULT (phi);
- vn_ssa_aux_t res_info = VN_INFO (res);
- if (!bb_visited)
- {
- gcc_assert (!res_info->visited);
- res_info->valnum = VN_TOP;
- res_info->visited = true;
- }
+ if (!skip_phis)
+ for (gphi_iterator gsi = gsi_start_phis (bb); !gsi_end_p (gsi);
+ gsi_next (&gsi))
+ {
+ gphi *phi = gsi.phi ();
+ tree res = PHI_RESULT (phi);
+ vn_ssa_aux_t res_info = VN_INFO (res);
+ if (!bb_visited)
+ {
+ gcc_assert (!res_info->visited);
+ res_info->valnum = VN_TOP;
+ res_info->visited = true;
+ }
- /* When not iterating force backedge values to varying. */
- visit_stmt (phi, !iterate_phis);
- if (virtual_operand_p (res))
- continue;
+ /* When not iterating force backedge values to varying. */
+ visit_stmt (phi, !iterate_phis);
+ if (virtual_operand_p (res))
+ continue;
- /* Eliminate */
- /* The interesting case is gcc.dg/tree-ssa/pr22230.c for correctness
- how we handle backedges and availability.
- And gcc.dg/tree-ssa/ssa-sccvn-2.c for optimization. */
- tree val = res_info->valnum;
- if (res != val && !iterate && eliminate)
- {
- if (tree leader = avail.eliminate_avail (bb, res))
- {
- if (leader != res
- /* Preserve loop-closed SSA form. */
- && (! lc_phi_nodes
- || is_gimple_min_invariant (leader)))
- {
- if (dump_file && (dump_flags & TDF_DETAILS))
- {
- fprintf (dump_file, "Replaced redundant PHI node "
- "defining ");
- print_generic_expr (dump_file, res);
- fprintf (dump_file, " with ");
- print_generic_expr (dump_file, leader);
- fprintf (dump_file, "\n");
- }
- avail.eliminations++;
+ /* Eliminate */
+ /* The interesting case is gcc.dg/tree-ssa/pr22230.c for correctness
+ how we handle backedges and availability.
+ And gcc.dg/tree-ssa/ssa-sccvn-2.c for optimization. */
+ tree val = res_info->valnum;
+ if (res != val && !iterate && eliminate)
+ {
+ if (tree leader = avail.eliminate_avail (bb, res))
+ {
+ if (leader != res
+ /* Preserve loop-closed SSA form. */
+ && (! lc_phi_nodes
+ || is_gimple_min_invariant (leader)))
+ {
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ {
+ fprintf (dump_file, "Replaced redundant PHI node "
+ "defining ");
+ print_generic_expr (dump_file, res);
+ fprintf (dump_file, " with ");
+ print_generic_expr (dump_file, leader);
+ fprintf (dump_file, "\n");
+ }
+ avail.eliminations++;
- if (may_propagate_copy (res, leader))
- {
- /* Schedule for removal. */
- avail.to_remove.safe_push (phi);
- continue;
- }
- /* ??? Else generate a copy stmt. */
- }
- }
- }
- /* Only make defs available that not already are. But make
- sure loop-closed SSA PHI node defs are picked up for
- downstream uses. */
- if (lc_phi_nodes
- || res == val
- || ! avail.eliminate_avail (bb, res))
- avail.eliminate_push_avail (bb, res);
- }
+ if (may_propagate_copy (res, leader))
+ {
+ /* Schedule for removal. */
+ avail.to_remove.safe_push (phi);
+ continue;
+ }
+ /* ??? Else generate a copy stmt. */
+ }
+ }
+ }
+ /* Only make defs available that not already are. But make
+ sure loop-closed SSA PHI node defs are picked up for
+ downstream uses. */
+ if (lc_phi_nodes
+ || res == val
+ || ! avail.eliminate_avail (bb, res))
+ avail.eliminate_push_avail (bb, res);
+ }
/* For empty BBs mark outgoing edges executable. For non-empty BBs
we do this when processing the last stmt as we have to do this
@@ -6414,6 +6398,13 @@ do_rpo_vn (function *fn, edge entry, bitmap exit_bbs,
bitmap_set_bit (exit_bbs, EXIT_BLOCK);
}
+ /* Clear EDGE_DFS_BACK on "all" entry edges, RPO order compute will
+ re-mark those that are contained in the region. */
+ edge_iterator ei;
+ edge e;
+ FOR_EACH_EDGE (e, ei, entry->dest->preds)
+ e->flags &= ~EDGE_DFS_BACK;
+
int *rpo = XNEWVEC (int, n_basic_blocks_for_fn (fn) - NUM_FIXED_BLOCKS);
int n = rev_post_order_and_mark_dfs_back_seme
(fn, entry, exit_bbs, !loops_state_satisfies_p (LOOPS_NEED_FIXUP), rpo);
@@ -6424,6 +6415,18 @@ do_rpo_vn (function *fn, edge entry, bitmap exit_bbs,
if (!do_region)
BITMAP_FREE (exit_bbs);
+ /* If there are any non-DFS_BACK edges into entry->dest skip
+ processing PHI nodes for that block. This supports
+ value-numbering loop bodies w/o the actual loop. */
+ FOR_EACH_EDGE (e, ei, entry->dest->preds)
+ if (e != entry
+ && !(e->flags & EDGE_DFS_BACK))
+ break;
+ bool skip_entry_phis = e != NULL;
+ if (skip_entry_phis && dump_file && (dump_flags & TDF_DETAILS))
+ fprintf (dump_file, "Region does not contain all edges into "
+ "the entry block, skipping its PHIs.\n");
+
int *bb_to_rpo = XNEWVEC (int, last_basic_block_for_fn (fn));
for (int i = 0; i < n; ++i)
bb_to_rpo[rpo[i]] = i;
@@ -6453,7 +6456,9 @@ do_rpo_vn (function *fn, edge entry, bitmap exit_bbs,
edge e;
edge_iterator ei;
FOR_EACH_EDGE (e, ei, bb->preds)
- gcc_assert (e == entry || (e->src->flags & bb_in_region));
+ gcc_assert (e == entry
+ || (skip_entry_phis && bb == entry->dest)
+ || (e->src->flags & bb_in_region));
}
for (int i = 0; i < n; ++i)
{
@@ -6467,6 +6472,7 @@ do_rpo_vn (function *fn, edge entry, bitmap exit_bbs,
unsigned region_size = (((unsigned HOST_WIDE_INT)n * num_ssa_names)
/ (n_basic_blocks_for_fn (fn) - NUM_FIXED_BLOCKS));
VN_TOP = create_tmp_var_raw (void_type_node, "vn_top");
+ next_value_id = 1;
vn_ssa_aux_hash = new hash_table <vn_ssa_aux_hasher> (region_size * 2);
gcc_obstack_init (&vn_ssa_aux_obstack);
@@ -6497,7 +6503,7 @@ do_rpo_vn (function *fn, edge entry, bitmap exit_bbs,
if (e->flags & EDGE_DFS_BACK)
has_backedges = true;
e->flags &= ~EDGE_EXECUTABLE;
- if (iterate || e == entry)
+ if (iterate || e == entry || (skip_entry_phis && bb == entry->dest))
continue;
if (bb_to_rpo[e->src->index] > i)
{
@@ -6530,7 +6536,7 @@ do_rpo_vn (function *fn, edge entry, bitmap exit_bbs,
edge_iterator ei;
FOR_EACH_EDGE (e, ei, bb->preds)
{
- if (e == entry)
+ if (e == entry || (skip_entry_phis && bb == entry->dest))
continue;
int max_rpo = MAX (rpo_state[i].max_rpo,
rpo_state[bb_to_rpo[e->src->index]].max_rpo);
@@ -6619,7 +6625,7 @@ do_rpo_vn (function *fn, edge entry, bitmap exit_bbs,
todo |= process_bb (avail, bb,
rpo_state[idx].visited != 0,
rpo_state[idx].iterate,
- iterate, eliminate, do_region, exit_bbs);
+ iterate, eliminate, do_region, exit_bbs, false);
rpo_state[idx].visited++;
/* Verify if changed values flow over executable outgoing backedges
@@ -6717,8 +6723,10 @@ do_rpo_vn (function *fn, edge entry, bitmap exit_bbs,
edge e;
FOR_EACH_EDGE (e, ei, bb->preds)
if (!(e->flags & EDGE_EXECUTABLE)
- && !rpo_state[bb_to_rpo[e->src->index]].visited
- && rpo_state[bb_to_rpo[e->src->index]].max_rpo >= (int)idx)
+ && (bb == entry->dest
+ || (!rpo_state[bb_to_rpo[e->src->index]].visited
+ && (rpo_state[bb_to_rpo[e->src->index]].max_rpo
+ >= (int)idx))))
{
if (dump_file && (dump_flags & TDF_DETAILS))
fprintf (dump_file, "Cannot trust state of predecessor "
@@ -6729,7 +6737,8 @@ do_rpo_vn (function *fn, edge entry, bitmap exit_bbs,
nblk++;
todo |= process_bb (avail, bb, false, false, false, eliminate,
- do_region, exit_bbs);
+ do_region, exit_bbs,
+ skip_entry_phis && bb == entry->dest);
rpo_state[idx].visited++;
FOR_EACH_EDGE (e, ei, bb->succs)
@@ -6811,7 +6820,9 @@ do_rpo_vn (function *fn, edge entry, bitmap exit_bbs,
}
/* Region-based entry for RPO VN. Performs value-numbering and elimination
- on the SEME region specified by ENTRY and EXIT_BBS. */
+ on the SEME region specified by ENTRY and EXIT_BBS. If ENTRY is not
+ the only edge into the region at ENTRY->dest PHI nodes in ENTRY->dest
+ are not considered. */
unsigned
do_rpo_vn (function *fn, edge entry, bitmap exit_bbs)
@@ -6842,14 +6853,24 @@ class pass_fre : public gimple_opt_pass
{
public:
pass_fre (gcc::context *ctxt)
- : gimple_opt_pass (pass_data_fre, ctxt)
+ : gimple_opt_pass (pass_data_fre, ctxt), may_iterate (true)
{}
/* opt_pass methods: */
opt_pass * clone () { return new pass_fre (m_ctxt); }
- virtual bool gate (function *) { return flag_tree_fre != 0; }
+ void set_pass_param (unsigned int n, bool param)
+ {
+ gcc_assert (n == 0);
+ may_iterate = param;
+ }
+ virtual bool gate (function *)
+ {
+ return flag_tree_fre != 0 && (may_iterate || optimize > 1);
+ }
virtual unsigned int execute (function *);
+private:
+ bool may_iterate;
}; // class pass_fre
unsigned int
@@ -6858,15 +6879,16 @@ pass_fre::execute (function *fun)
unsigned todo = 0;
/* At -O[1g] use the cheap non-iterating mode. */
+ bool iterate_p = may_iterate && (optimize > 1);
calculate_dominance_info (CDI_DOMINATORS);
- if (optimize > 1)
+ if (iterate_p)
loop_optimizer_init (AVOID_CFG_MODIFICATIONS);
default_vn_walk_kind = VN_WALKREWRITE;
- todo = do_rpo_vn (fun, NULL, NULL, optimize > 1, true);
+ todo = do_rpo_vn (fun, NULL, NULL, iterate_p, true);
free_rpo_vn ();
- if (optimize > 1)
+ if (iterate_p)
loop_optimizer_finalize ();
return todo;
diff --git a/gcc/tree-ssa-scopedtables.c b/gcc/tree-ssa-scopedtables.c
index 0614afc..50413eb 100644
--- a/gcc/tree-ssa-scopedtables.c
+++ b/gcc/tree-ssa-scopedtables.c
@@ -494,7 +494,9 @@ avail_expr_hash (class expr_hash_elt *p)
{
enum tree_code code = MEM_REF;
hstate.add_object (code);
- inchash::add_expr (base, hstate);
+ inchash::add_expr (base, hstate,
+ TREE_CODE (base) == MEM_REF
+ ? OEP_ADDRESS_OF : 0);
hstate.add_object (offset);
hstate.add_object (size);
return hstate.end ();
@@ -537,13 +539,15 @@ equal_mem_array_ref_p (tree t0, tree t1)
|| maybe_ne (sz1, max1))
return false;
- if (rev0 != rev1)
+ if (rev0 != rev1 || maybe_ne (sz0, sz1) || maybe_ne (off0, off1))
return false;
- /* Types were compatible, so this is a sanity check. */
- gcc_assert (known_eq (sz0, sz1));
-
- return known_eq (off0, off1) && operand_equal_p (base0, base1, 0);
+ return operand_equal_p (base0, base1,
+ (TREE_CODE (base0) == MEM_REF
+ || TREE_CODE (base0) == TARGET_MEM_REF)
+ && (TREE_CODE (base1) == MEM_REF
+ || TREE_CODE (base1) == TARGET_MEM_REF)
+ ? OEP_ADDRESS_OF : 0);
}
/* Compare two hashable_expr structures for equivalence. They are
diff --git a/gcc/tree-ssa-sink.c b/gcc/tree-ssa-sink.c
index fe762f5..3bfad0f 100644
--- a/gcc/tree-ssa-sink.c
+++ b/gcc/tree-ssa-sink.c
@@ -433,13 +433,15 @@ statement_sink_location (gimple *stmt, basic_block frombb,
if (gimple_code (use) != GIMPLE_PHI)
{
- sinkbb = gimple_bb (use);
sinkbb = select_best_block (frombb, gimple_bb (use), stmt);
if (sinkbb == frombb)
return false;
- *togsi = gsi_for_stmt (use);
+ if (sinkbb == gimple_bb (use))
+ *togsi = gsi_for_stmt (use);
+ else
+ *togsi = gsi_after_labels (sinkbb);
return true;
}
@@ -610,7 +612,7 @@ const pass_data pass_data_sink_code =
"sink", /* name */
OPTGROUP_NONE, /* optinfo_flags */
TV_TREE_SINK, /* tv_id */
- /* PROP_no_crit_edges is ensured by running split_critical_edges in
+ /* PROP_no_crit_edges is ensured by running split_edges_for_insertion in
pass_data_sink_code::execute (). */
( PROP_cfg | PROP_ssa ), /* properties_required */
0, /* properties_provided */
@@ -636,7 +638,7 @@ unsigned int
pass_sink_code::execute (function *fun)
{
loop_optimizer_init (LOOPS_NORMAL);
- split_critical_edges ();
+ split_edges_for_insertion ();
connect_infinite_loops_to_exit ();
memset (&sink_stats, 0, sizeof (sink_stats));
calculate_dominance_info (CDI_DOMINATORS);
diff --git a/gcc/tree-ssa-strlen.c b/gcc/tree-ssa-strlen.c
index a2dc9c7..74cd6c4 100644
--- a/gcc/tree-ssa-strlen.c
+++ b/gcc/tree-ssa-strlen.c
@@ -296,34 +296,83 @@ get_stridx (tree exp)
{
if (ssa_ver_to_stridx[SSA_NAME_VERSION (exp)])
return ssa_ver_to_stridx[SSA_NAME_VERSION (exp)];
- int i;
+
tree e = exp;
- HOST_WIDE_INT off = 0;
- for (i = 0; i < 5; i++)
+ HOST_WIDE_INT offset = 0;
+ /* Follow a chain of at most 5 assignments. */
+ for (int i = 0; i < 5; i++)
{
gimple *def_stmt = SSA_NAME_DEF_STMT (e);
- if (!is_gimple_assign (def_stmt)
- || gimple_assign_rhs_code (def_stmt) != POINTER_PLUS_EXPR)
+ if (!is_gimple_assign (def_stmt))
+ return 0;
+
+ tree_code rhs_code = gimple_assign_rhs_code (def_stmt);
+ tree ptr, off;
+
+ if (rhs_code == ADDR_EXPR)
+ {
+ /* Handle indices/offsets into VLAs which are implemented
+ as pointers to arrays. */
+ ptr = gimple_assign_rhs1 (def_stmt);
+ ptr = TREE_OPERAND (ptr, 0);
+
+ /* Handle also VLAs of types larger than char. */
+ if (tree eltsize = TYPE_SIZE_UNIT (TREE_TYPE (ptr)))
+ {
+ if (TREE_CODE (ptr) == ARRAY_REF)
+ {
+ off = TREE_OPERAND (ptr, 1);
+ ptr = TREE_OPERAND (ptr, 0);
+ if (!integer_onep (eltsize))
+ {
+ /* Scale the array index by the size of the element
+ type in the rare case that it's greater than
+ the typical 1 for char, making sure both operands
+ have the same type. */
+ eltsize = fold_convert (ssizetype, eltsize);
+ off = fold_convert (ssizetype, off);
+ off = fold_build2 (MULT_EXPR, ssizetype, off, eltsize);
+ }
+ }
+ else
+ off = integer_zero_node;
+ }
+ else
+ return 0;
+
+ if (TREE_CODE (ptr) != MEM_REF)
+ return 0;
+
+ /* Add the MEM_REF byte offset. */
+ tree mem_off = TREE_OPERAND (ptr, 1);
+ off = fold_build2 (PLUS_EXPR, TREE_TYPE (off), off, mem_off);
+ ptr = TREE_OPERAND (ptr, 0);
+ }
+ else if (rhs_code == POINTER_PLUS_EXPR)
+ {
+ ptr = gimple_assign_rhs1 (def_stmt);
+ off = gimple_assign_rhs2 (def_stmt);
+ }
+ else
return 0;
- tree rhs1 = gimple_assign_rhs1 (def_stmt);
- tree rhs2 = gimple_assign_rhs2 (def_stmt);
- if (TREE_CODE (rhs1) != SSA_NAME
- || !tree_fits_shwi_p (rhs2))
+
+ if (TREE_CODE (ptr) != SSA_NAME
+ || !tree_fits_shwi_p (off))
return 0;
- HOST_WIDE_INT this_off = tree_to_shwi (rhs2);
+ HOST_WIDE_INT this_off = tree_to_shwi (off);
if (this_off < 0)
return 0;
- off = (unsigned HOST_WIDE_INT) off + this_off;
- if (off < 0)
+ offset = (unsigned HOST_WIDE_INT) offset + this_off;
+ if (offset < 0)
return 0;
- if (ssa_ver_to_stridx[SSA_NAME_VERSION (rhs1)])
+ if (ssa_ver_to_stridx[SSA_NAME_VERSION (ptr)])
{
strinfo *si
- = get_strinfo (ssa_ver_to_stridx[SSA_NAME_VERSION (rhs1)]);
- if (si && compare_nonzero_chars (si, off) >= 0)
- return get_stridx_plus_constant (si, off, exp);
+ = get_strinfo (ssa_ver_to_stridx[SSA_NAME_VERSION (ptr)]);
+ if (si && compare_nonzero_chars (si, offset) >= 0)
+ return get_stridx_plus_constant (si, offset, exp);
}
- e = rhs1;
+ e = ptr;
}
return 0;
}
@@ -891,9 +940,9 @@ adjust_related_strinfos (location_t loc, strinfo *origsi, tree adj)
tree tem;
si = unshare_strinfo (si);
- /* We shouldn't see delayed lengths here; the caller must have
- calculated the old length in order to calculate the
- adjustment. */
+ /* We shouldn't see delayed lengths here; the caller must
+ have calculated the old length in order to calculate
+ the adjustment. */
gcc_assert (si->nonzero_chars);
tem = fold_convert_loc (loc, TREE_TYPE (si->nonzero_chars), adj);
si->nonzero_chars = fold_build2_loc (loc, PLUS_EXPR,
@@ -2759,7 +2808,7 @@ handle_builtin_malloc (enum built_in_function bcode, gimple_stmt_iterator *gsi)
/* Handle a call to memset.
After a call to calloc, memset(,0,) is unnecessary.
- memset(malloc(n),0,n) is calloc(n,1).
+ memset(malloc(n),0,n) is calloc(n,1).
return true when the call is transfomred, false otherwise. */
static bool
@@ -2815,7 +2864,7 @@ handle_builtin_memset (gimple_stmt_iterator *gsi)
/* Handle a call to memcmp. We try to handle small comparisons by
converting them to load and compare, and replacing the call to memcmp
- with a __builtin_memcmp_eq call where possible.
+ with a __builtin_memcmp_eq call where possible.
return true when call is transformed, return false otherwise. */
static bool
@@ -2898,13 +2947,81 @@ handle_builtin_memcmp (gimple_stmt_iterator *gsi)
return true;
}
-/* Given an index to the strinfo vector, compute the string length for the
- corresponding string. Return -1 when unknown. */
-
-static HOST_WIDE_INT
+/* If IDX1 and IDX2 refer to strings A and B of unequal lengths, return
+ the result of 0 == strncmp (A, B, N) (which is the same as strcmp for
+ sufficiently large N). Otherwise return false. */
+
+static bool
+strxcmp_unequal (int idx1, int idx2, unsigned HOST_WIDE_INT n)
+{
+ unsigned HOST_WIDE_INT len1;
+ unsigned HOST_WIDE_INT len2;
+
+ bool nulterm1;
+ bool nulterm2;
+
+ if (idx1 < 0)
+ {
+ len1 = ~idx1;
+ nulterm1 = true;
+ }
+ else if (strinfo *si = get_strinfo (idx1))
+ {
+ if (tree_fits_uhwi_p (si->nonzero_chars))
+ {
+ len1 = tree_to_uhwi (si->nonzero_chars);
+ nulterm1 = si->full_string_p;
+ }
+ else
+ return false;
+ }
+ else
+ return false;
+
+ if (idx2 < 0)
+ {
+ len2 = ~idx2;
+ nulterm2 = true;
+ }
+ else if (strinfo *si = get_strinfo (idx2))
+ {
+ if (tree_fits_uhwi_p (si->nonzero_chars))
+ {
+ len2 = tree_to_uhwi (si->nonzero_chars);
+ nulterm2 = si->full_string_p;
+ }
+ else
+ return false;
+ }
+ else
+ return false;
+
+ /* N is set to UHWI_MAX for strcmp and less to strncmp. Adjust
+ the length of each string to consider to be no more than N. */
+ if (len1 > n)
+ len1 = n;
+ if (len2 > n)
+ len2 = n;
+
+ if ((len1 < len2 && nulterm1)
+ || (len2 < len1 && nulterm2))
+ /* The string lengths are definitely unequal and the result can
+ be folded to one (since it's used for comparison with zero). */
+ return true;
+
+ /* The string lengths may be equal or unequal. Even when equal and
+ both strings nul-terminated, without the string contents there's
+ no way to determine whether they are equal. */
+ return false;
+}
+
+/* Given an index to the strinfo vector, compute the string length
+ for the corresponding string. Return -1 when unknown. */
+
+static HOST_WIDE_INT
compute_string_length (int idx)
{
- HOST_WIDE_INT string_leni = -1;
+ HOST_WIDE_INT string_leni = -1;
gcc_assert (idx != 0);
if (idx < 0)
@@ -2924,9 +3041,9 @@ compute_string_length (int idx)
return string_leni;
}
-/* Determine the minimum size of the object referenced by DEST expression which
- must have a pointer type.
- Return the minimum size of the object if successful or NULL when the size
+/* Determine the minimum size of the object referenced by DEST expression
+ which must have a pointer type.
+ Return the minimum size of the object if successful or NULL when the size
cannot be determined. */
static tree
determine_min_objsize (tree dest)
@@ -2936,8 +3053,8 @@ determine_min_objsize (tree dest)
if (compute_builtin_object_size (dest, 2, &size))
return build_int_cst (sizetype, size);
- /* Try to determine the size of the object through the RHS of the
- assign statement. */
+ /* Try to determine the size of the object through the RHS
+ of the assign statement. */
if (TREE_CODE (dest) == SSA_NAME)
{
gimple *stmt = SSA_NAME_DEF_STMT (dest);
@@ -2962,13 +3079,13 @@ determine_min_objsize (tree dest)
type = TYPE_MAIN_VARIANT (type);
- /* We cannot determine the size of the array if it's a flexible array,
+ /* We cannot determine the size of the array if it's a flexible array,
which is declared at the end of a structure. */
if (TREE_CODE (type) == ARRAY_TYPE
&& !array_at_struct_end_p (dest))
{
tree size_t = TYPE_SIZE_UNIT (type);
- if (size_t && TREE_CODE (size_t) == INTEGER_CST
+ if (size_t && TREE_CODE (size_t) == INTEGER_CST
&& !integer_zerop (size_t))
return size_t;
}
@@ -2976,19 +3093,19 @@ determine_min_objsize (tree dest)
return NULL_TREE;
}
-/* Handle a call to strcmp or strncmp. When the result is ONLY used to do
+/* Handle a call to strcmp or strncmp. When the result is ONLY used to do
equality test against zero:
A. When the lengths of both arguments are constant and it's a strcmp:
* if the lengths are NOT equal, we can safely fold the call
to a non-zero value.
* otherwise, do nothing now.
-
- B. When the length of one argument is constant, try to replace the call with
- a __builtin_str(n)cmp_eq call where possible, i.e:
- strncmp (s, STR, C) (!)= 0 in which, s is a pointer to a string, STR is a
- string with constant length , C is a constant.
+ B. When the length of one argument is constant, try to replace the call
+ with a __builtin_str(n)cmp_eq call where possible, i.e:
+
+ strncmp (s, STR, C) (!)= 0 in which, s is a pointer to a string, STR
+ is a string with constant length , C is a constant.
if (C <= strlen(STR) && sizeof_array(s) > C)
{
replace this call with
@@ -3000,16 +3117,16 @@ determine_min_objsize (tree dest)
can handled by the following strcmp.
}
- strcmp (s, STR) (!)= 0 in which, s is a pointer to a string, STR is a
- string with constant length.
+ strcmp (s, STR) (!)= 0 in which, s is a pointer to a string, STR
+ is a string with constant length.
if (sizeof_array(s) > strlen(STR))
{
replace this call with
strcmp_eq (s, STR, strlen(STR)+1) (!)= 0
}
- Return true when the call is transformed, return false otherwise.
- */
+ Return true when the call is transformed, return false otherwise.
+ */
static bool
handle_builtin_string_cmp (gimple_stmt_iterator *gsi)
@@ -3047,19 +3164,19 @@ handle_builtin_string_cmp (gimple_stmt_iterator *gsi)
return false;
/* When the result is ONLY used to do equality test against zero. */
- FOR_EACH_IMM_USE_FAST (use_p, iter, res)
- {
+ FOR_EACH_IMM_USE_FAST (use_p, iter, res)
+ {
gimple *use_stmt = USE_STMT (use_p);
if (is_gimple_debug (use_stmt))
continue;
if (gimple_code (use_stmt) == GIMPLE_ASSIGN)
- {
+ {
tree_code code = gimple_assign_rhs_code (use_stmt);
- if (code == COND_EXPR)
+ if (code == COND_EXPR)
{
tree cond_expr = gimple_assign_rhs1 (use_stmt);
- if ((TREE_CODE (cond_expr) != EQ_EXPR
+ if ((TREE_CODE (cond_expr) != EQ_EXPR
&& (TREE_CODE (cond_expr) != NE_EXPR))
|| !integer_zerop (TREE_OPERAND (cond_expr, 1)))
return false;
@@ -3069,7 +3186,7 @@ handle_builtin_string_cmp (gimple_stmt_iterator *gsi)
if (!integer_zerop (gimple_assign_rhs2 (use_stmt)))
return false;
}
- else
+ else
return false;
}
else if (gimple_code (use_stmt) == GIMPLE_COND)
@@ -3082,21 +3199,15 @@ handle_builtin_string_cmp (gimple_stmt_iterator *gsi)
else
return false;
}
-
- /* When the lengths of both arguments are known, and they are unequal, we can
- safely fold the call to a non-zero value for strcmp;
- othewise, do nothing now. */
+
+ /* When the lengths of the arguments are known to be unequal
+ we can safely fold the call to a non-zero value for strcmp;
+ otherwise, do nothing now. */
if (idx1 != 0 && idx2 != 0)
{
- HOST_WIDE_INT const_string_leni1 = compute_string_length (idx1);
- HOST_WIDE_INT const_string_leni2 = compute_string_length (idx2);
-
- if (!is_ncmp
- && const_string_leni1 != -1
- && const_string_leni2 != -1
- && const_string_leni1 != const_string_leni2)
+ if (strxcmp_unequal (idx1, idx2, length))
{
- replace_call_with_value (gsi, integer_one_node);
+ replace_call_with_value (gsi, integer_one_node);
return true;
}
return false;
@@ -3105,56 +3216,56 @@ handle_builtin_string_cmp (gimple_stmt_iterator *gsi)
/* When the length of one argument is constant. */
tree var_string = NULL_TREE;
HOST_WIDE_INT const_string_leni = -1;
-
+
if (idx1)
{
const_string_leni = compute_string_length (idx1);
var_string = arg2;
- }
- else
+ }
+ else
{
gcc_checking_assert (idx2);
const_string_leni = compute_string_length (idx2);
var_string = arg1;
- }
+ }
- if (const_string_leni < 0)
+ if (const_string_leni < 0)
return false;
-
+
unsigned HOST_WIDE_INT var_sizei = 0;
/* try to determine the minimum size of the object pointed by var_string. */
tree size = determine_min_objsize (var_string);
if (!size)
return false;
-
+
if (tree_fits_uhwi_p (size))
var_sizei = tree_to_uhwi (size);
if (var_sizei == 0)
return false;
- /* For strncmp, if length > const_string_leni , this call can be safely
+ /* For strncmp, if length > const_string_leni , this call can be safely
transformed to a strcmp. */
if (is_ncmp && length > const_string_leni)
is_ncmp = false;
- unsigned HOST_WIDE_INT final_length
+ unsigned HOST_WIDE_INT final_length
= is_ncmp ? length : const_string_leni + 1;
/* Replace strcmp or strncmp with the corresponding str(n)cmp_eq. */
- if (var_sizei > final_length)
+ if (var_sizei > final_length)
{
- tree fn
- = (is_ncmp
- ? builtin_decl_implicit (BUILT_IN_STRNCMP_EQ)
+ tree fn
+ = (is_ncmp
+ ? builtin_decl_implicit (BUILT_IN_STRNCMP_EQ)
: builtin_decl_implicit (BUILT_IN_STRCMP_EQ));
if (!fn)
return false;
- tree const_string_len = build_int_cst (size_type_node, final_length);
+ tree const_string_len = build_int_cst (size_type_node, final_length);
update_gimple_call (gsi, fn, 3, arg1, arg2, const_string_len);
}
- else
+ else
return false;
return true;
@@ -3355,7 +3466,7 @@ handle_char_store (gimple_stmt_iterator *gsi)
and if we aren't storing '\0', we know that the length of the
string and any other zero terminated string in memory remains
the same. In that case we move to the next gimple statement and
- return to signal the caller that it shouldn't invalidate anything.
+ return to signal the caller that it shouldn't invalidate anything.
This is benefical for cases like:
@@ -3370,13 +3481,15 @@ handle_char_store (gimple_stmt_iterator *gsi)
size_t len4 = strlen (q); // This can be optimized into len2
bar (len, len2, len3, len4);
}
- */
+ */
else if (storing_nonzero_p && cmp > 0)
{
gsi_next (gsi);
return false;
}
- else if (storing_all_zeros_p || storing_nonzero_p || (offset != 0 && cmp > 0))
+ else if (storing_all_zeros_p
+ || storing_nonzero_p
+ || (offset != 0 && cmp > 0))
{
/* When STORING_NONZERO_P, we know that the string will start
with at least OFFSET + 1 nonzero characters. If storing
diff --git a/gcc/tree-ssa-structalias.c b/gcc/tree-ssa-structalias.c
index 2e2b0e8..29688d2 100644
--- a/gcc/tree-ssa-structalias.c
+++ b/gcc/tree-ssa-structalias.c
@@ -43,6 +43,7 @@
#include "stringpool.h"
#include "attribs.h"
#include "tree-ssa.h"
+#include "tree-cfg.h"
/* The idea behind this analyzer is to generate set constraints from the
program, then solve the resulting constraints in order to generate the
@@ -3854,7 +3855,6 @@ make_heapvar (const char *name, bool add_id)
DECL_EXTERNAL (heapvar) = 1;
vi = new_var_info (heapvar, name, add_id);
- vi->is_artificial_var = true;
vi->is_heap_var = true;
vi->is_unknown_size_var = true;
vi->offset = 0;
@@ -4409,6 +4409,32 @@ find_func_aliases_for_builtin_call (struct function *fn, gcall *t)
process_constraint (new_constraint (*lhsp, ac));
return true;
}
+ case BUILT_IN_STACK_SAVE:
+ case BUILT_IN_STACK_RESTORE:
+ /* Nothing interesting happens. */
+ return true;
+ case BUILT_IN_ALLOCA:
+ case BUILT_IN_ALLOCA_WITH_ALIGN:
+ case BUILT_IN_ALLOCA_WITH_ALIGN_AND_MAX:
+ {
+ tree ptr = gimple_call_lhs (t);
+ if (ptr == NULL_TREE)
+ return true;
+ get_constraint_for (ptr, &lhsc);
+ varinfo_t vi = make_heapvar ("HEAP", true);
+ /* Alloca storage is never global. To exempt it from escaped
+ handling make it a non-heap var. */
+ DECL_EXTERNAL (vi->decl) = 0;
+ vi->is_global_var = 0;
+ vi->is_heap_var = 0;
+ struct constraint_expr tmpc;
+ tmpc.var = vi->id;
+ tmpc.offset = 0;
+ tmpc.type = ADDRESSOF;
+ rhsc.safe_push (tmpc);
+ process_all_all_constraints (lhsc, rhsc);
+ return true;
+ }
case BUILT_IN_POSIX_MEMALIGN:
{
tree ptrptr = gimple_call_arg (t, 0);
@@ -4900,6 +4926,9 @@ find_func_aliases (struct function *fn, gimple *origt)
if (code == POINTER_PLUS_EXPR)
get_constraint_for_ptr_offset (gimple_assign_rhs1 (t),
gimple_assign_rhs2 (t), &rhsc);
+ else if (code == POINTER_DIFF_EXPR)
+ /* The result is not a pointer (part). */
+ ;
else if (code == BIT_AND_EXPR
&& TREE_CODE (gimple_assign_rhs2 (t)) == INTEGER_CST)
{
@@ -4908,6 +4937,17 @@ find_func_aliases (struct function *fn, gimple *origt)
get_constraint_for_ptr_offset (gimple_assign_rhs1 (t),
NULL_TREE, &rhsc);
}
+ else if (code == TRUNC_DIV_EXPR
+ || code == CEIL_DIV_EXPR
+ || code == FLOOR_DIV_EXPR
+ || code == ROUND_DIV_EXPR
+ || code == EXACT_DIV_EXPR
+ || code == TRUNC_MOD_EXPR
+ || code == CEIL_MOD_EXPR
+ || code == FLOOR_MOD_EXPR
+ || code == ROUND_MOD_EXPR)
+ /* Division and modulo transfer the pointer from the LHS. */
+ get_constraint_for_rhs (gimple_assign_rhs1 (t), &rhsc);
else if ((CONVERT_EXPR_CODE_P (code)
&& !(POINTER_TYPE_P (gimple_expr_type (t))
&& !POINTER_TYPE_P (TREE_TYPE (rhsop))))
@@ -4962,7 +5002,12 @@ find_func_aliases (struct function *fn, gimple *origt)
greturn *return_stmt = as_a <greturn *> (t);
fi = NULL;
if (!in_ipa_mode
- || !(fi = get_vi_for_tree (fn->decl)))
+ && SSA_VAR_P (gimple_return_retval (return_stmt)))
+ {
+ /* We handle simple returns by post-processing the solutions. */
+ ;
+ }
+ if (!(fi = get_vi_for_tree (fn->decl)))
make_escape_constraint (gimple_return_retval (return_stmt));
else if (in_ipa_mode)
{
@@ -5910,7 +5955,6 @@ create_function_info_for (tree decl, const char *name, bool add_id,
gcc_assert (prev_vi->offset < argvi->offset);
prev_vi->next = argvi->id;
- prev_vi = argvi;
}
return vi;
@@ -6408,9 +6452,7 @@ set_uids_in_ptset (bitmap into, bitmap from, struct pt_solution *pt,
{
varinfo_t vi = get_varinfo (i);
- /* The only artificial variables that are allowed in a may-alias
- set are heap variables. */
- if (vi->is_artificial_var && !vi->is_heap_var)
+ if (vi->is_artificial_var)
continue;
if (everything_escaped
@@ -6530,9 +6572,6 @@ find_what_var_points_to (tree fndecl, varinfo_t orig_vi)
}
else if (vi->id == nonlocal_id)
pt->nonlocal = 1;
- else if (vi->is_heap_var)
- /* We represent heapvars in the points-to set properly. */
- ;
else if (vi->id == string_id)
/* Nobody cares - STRING_CSTs are read-only entities. */
;
@@ -7240,9 +7279,6 @@ solve_constraints (void)
dump_constraint_graph (dump_file);
fprintf (dump_file, "\n\n");
}
-
- if (dump_file)
- dump_sa_points_to_info (dump_file);
}
/* Create points-to sets for the current function. See the comments
@@ -7290,6 +7326,73 @@ compute_points_to_sets (void)
/* From the constraints compute the points-to sets. */
solve_constraints ();
+ /* Post-process solutions for escapes through returns. */
+ edge_iterator ei;
+ edge e;
+ FOR_EACH_EDGE (e, ei, EXIT_BLOCK_PTR_FOR_FN (cfun)->preds)
+ if (greturn *ret = safe_dyn_cast <greturn *> (last_stmt (e->src)))
+ {
+ tree val = gimple_return_retval (ret);
+ /* ??? Easy to handle simple indirections with some work.
+ Arbitrary references like foo.bar.baz are more difficult
+ (but conservatively easy enough with just looking at the base).
+ Mind to fixup find_func_aliases as well. */
+ if (!val || !SSA_VAR_P (val))
+ continue;
+ /* returns happen last in non-IPA so they only influence
+ the ESCAPED solution and we can filter local variables. */
+ varinfo_t escaped_vi = get_varinfo (find (escaped_id));
+ varinfo_t vi = lookup_vi_for_tree (val);
+ bitmap delta = BITMAP_ALLOC (&pta_obstack);
+ bitmap_iterator bi;
+ unsigned i;
+ for (; vi; vi = vi_next (vi))
+ {
+ varinfo_t part_vi = get_varinfo (find (vi->id));
+ EXECUTE_IF_AND_COMPL_IN_BITMAP (part_vi->solution,
+ escaped_vi->solution, 0, i, bi)
+ {
+ varinfo_t pointed_to_vi = get_varinfo (i);
+ if (pointed_to_vi->is_global_var
+ /* We delay marking of heap memory as global. */
+ || pointed_to_vi->is_heap_var)
+ bitmap_set_bit (delta, i);
+ }
+ }
+
+ /* Now compute the transitive closure. */
+ bitmap_ior_into (escaped_vi->solution, delta);
+ bitmap new_delta = BITMAP_ALLOC (&pta_obstack);
+ while (!bitmap_empty_p (delta))
+ {
+ EXECUTE_IF_SET_IN_BITMAP (delta, 0, i, bi)
+ {
+ varinfo_t pointed_to_vi = get_varinfo (i);
+ pointed_to_vi = get_varinfo (find (pointed_to_vi->id));
+ unsigned j;
+ bitmap_iterator bi2;
+ EXECUTE_IF_AND_COMPL_IN_BITMAP (pointed_to_vi->solution,
+ escaped_vi->solution,
+ 0, j, bi2)
+ {
+ varinfo_t pointed_to_vi2 = get_varinfo (j);
+ if (pointed_to_vi2->is_global_var
+ /* We delay marking of heap memory as global. */
+ || pointed_to_vi2->is_heap_var)
+ bitmap_set_bit (new_delta, j);
+ }
+ }
+ bitmap_ior_into (escaped_vi->solution, new_delta);
+ bitmap_clear (delta);
+ std::swap (delta, new_delta);
+ }
+ BITMAP_FREE (delta);
+ BITMAP_FREE (new_delta);
+ }
+
+ if (dump_file)
+ dump_sa_points_to_info (dump_file);
+
/* Compute the points-to set for ESCAPED used for call-clobber analysis. */
cfun->gimple_df->escaped = find_what_var_points_to (cfun->decl,
get_varinfo (escaped_id));
@@ -8095,6 +8198,9 @@ ipa_pta_execute (void)
/* From the constraints compute the points-to sets. */
solve_constraints ();
+ if (dump_file)
+ dump_sa_points_to_info (dump_file);
+
/* Now post-process solutions to handle locals from different
runtime instantiations coming in through recursive invocations. */
unsigned shadow_var_cnt = 0;
diff --git a/gcc/tree-ssa-tail-merge.c b/gcc/tree-ssa-tail-merge.c
index 3eb63b5..cbd5a27 100644
--- a/gcc/tree-ssa-tail-merge.c
+++ b/gcc/tree-ssa-tail-merge.c
@@ -1746,7 +1746,7 @@ tail_merge_optimize (unsigned int todo)
{
cleanup_tree_cfg ();
todo &= ~TODO_cleanup_cfg;
- split_critical_edges ();
+ split_edges_for_insertion ();
}
if (!dom_info_available_p (CDI_DOMINATORS))
diff --git a/gcc/tree-ssa-threadbackward.c b/gcc/tree-ssa-threadbackward.c
index 81dc05d..1ff870a 100644
--- a/gcc/tree-ssa-threadbackward.c
+++ b/gcc/tree-ssa-threadbackward.c
@@ -261,6 +261,11 @@ thread_jumps::profitable_jump_thread_path (basic_block bbi, tree name,
gsi_next_nondebug (&gsi))
{
gimple *stmt = gsi_stmt (gsi);
+ if (gimple_call_internal_p (stmt, IFN_UNIQUE))
+ {
+ m_path.pop ();
+ return NULL;
+ }
/* Do not count empty statements and labels. */
if (gimple_code (stmt) != GIMPLE_NOP
&& !(gimple_code (stmt) == GIMPLE_ASSIGN
diff --git a/gcc/tree-ssa-threadedge.c b/gcc/tree-ssa-threadedge.c
index c3ea2d6..39ea22f 100644
--- a/gcc/tree-ssa-threadedge.c
+++ b/gcc/tree-ssa-threadedge.c
@@ -1157,6 +1157,68 @@ thread_through_normal_block (edge e,
return 0;
}
+/* There are basic blocks look like:
+ <P0>
+ p0 = a CMP b ; or p0 = (INT) (a CMP b)
+ goto <X>;
+
+ <P1>
+ p1 = c CMP d
+ goto <X>;
+
+ <X>
+ # phi = PHI <p0 (P0), p1 (P1)>
+ if (phi != 0) goto <Y>; else goto <Z>;
+
+ Then, edge (P0,X) or (P1,X) could be marked as EDGE_START_JUMP_THREAD
+ And edge (X,Y), (X,Z) is EDGE_COPY_SRC_JOINER_BLOCK
+
+ Return true if E is (P0,X) or (P1,X) */
+
+bool
+edge_forwards_cmp_to_conditional_jump_through_empty_bb_p (edge e)
+{
+ /* See if there is only one stmt which is gcond. */
+ gcond *gs;
+ if (!(gs = safe_dyn_cast<gcond *> (last_and_only_stmt (e->dest))))
+ return false;
+
+ /* See if gcond's cond is "(phi !=/== 0/1)" in the basic block. */
+ tree cond = gimple_cond_lhs (gs);
+ enum tree_code code = gimple_cond_code (gs);
+ tree rhs = gimple_cond_rhs (gs);
+ if (TREE_CODE (cond) != SSA_NAME
+ || (code != NE_EXPR && code != EQ_EXPR)
+ || (!integer_onep (rhs) && !integer_zerop (rhs)))
+ return false;
+ gphi *phi = dyn_cast <gphi *> (SSA_NAME_DEF_STMT (cond));
+ if (phi == NULL || gimple_bb (phi) != e->dest)
+ return false;
+
+ /* Check if phi's incoming value is CMP. */
+ gassign *def;
+ tree value = PHI_ARG_DEF_FROM_EDGE (phi, e);
+ if (TREE_CODE (value) != SSA_NAME
+ || !has_single_use (value)
+ || !(def = dyn_cast <gassign *> (SSA_NAME_DEF_STMT (value))))
+ return false;
+
+ /* Or if it is (INT) (a CMP b). */
+ if (CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (def)))
+ {
+ value = gimple_assign_rhs1 (def);
+ if (TREE_CODE (value) != SSA_NAME
+ || !has_single_use (value)
+ || !(def = dyn_cast<gassign *> (SSA_NAME_DEF_STMT (value))))
+ return false;
+ }
+
+ if (TREE_CODE_CLASS (gimple_assign_rhs_code (def)) != tcc_comparison)
+ return false;
+
+ return true;
+}
+
/* We are exiting E->src, see if E->dest ends with a conditional
jump which has a known value when reached via E.
@@ -1299,7 +1361,6 @@ thread_across_edge (gcond *dummy_cond,
x = new jump_thread_edge (taken_edge, EDGE_COPY_SRC_JOINER_BLOCK);
path->safe_push (x);
- found = false;
found = thread_around_empty_blocks (taken_edge,
dummy_cond,
avail_exprs_stack,
@@ -1317,10 +1378,12 @@ thread_across_edge (gcond *dummy_cond,
/* If we were able to thread through a successor of E->dest, then
record the jump threading opportunity. */
- if (found)
+ if (found
+ || edge_forwards_cmp_to_conditional_jump_through_empty_bb_p (e))
{
- propagate_threaded_block_debug_into (path->last ()->e->dest,
- taken_edge->dest);
+ if (taken_edge->dest != path->last ()->e->dest)
+ propagate_threaded_block_debug_into (path->last ()->e->dest,
+ taken_edge->dest);
register_jump_thread (path);
}
else
diff --git a/gcc/tree-ssa-threadupdate.c b/gcc/tree-ssa-threadupdate.c
index bccef87..a56ccfb 100644
--- a/gcc/tree-ssa-threadupdate.c
+++ b/gcc/tree-ssa-threadupdate.c
@@ -235,6 +235,12 @@ struct ssa_local_info_t
and sharing a template for that block is considerably more difficult. */
basic_block template_block;
+ /* If we append debug stmts to the template block after creating it,
+ this iterator won't be the last one in the block, and further
+ copies of the template block shouldn't get debug stmts after
+ it. */
+ gimple_stmt_iterator template_last_to_copy;
+
/* Blocks duplicated for the thread. */
bitmap duplicate_blocks;
@@ -1124,6 +1130,8 @@ ssa_create_duplicates (struct redirection_data **slot,
create_block_for_threading ((*path)[1]->e->src, rd, 0,
&local_info->duplicate_blocks);
local_info->template_block = rd->dup_blocks[0];
+ local_info->template_last_to_copy
+ = gsi_last_bb (local_info->template_block);
/* We do not create any outgoing edges for the template. We will
take care of that in a later traversal. That way we do not
@@ -1131,14 +1139,87 @@ ssa_create_duplicates (struct redirection_data **slot,
}
else
{
+ gimple_seq seq = NULL;
+ if (gsi_stmt (local_info->template_last_to_copy)
+ != gsi_stmt (gsi_last_bb (local_info->template_block)))
+ {
+ if (gsi_end_p (local_info->template_last_to_copy))
+ {
+ seq = bb_seq (local_info->template_block);
+ set_bb_seq (local_info->template_block, NULL);
+ }
+ else
+ seq = gsi_split_seq_after (local_info->template_last_to_copy);
+ }
create_block_for_threading (local_info->template_block, rd, 0,
&local_info->duplicate_blocks);
+ if (seq)
+ {
+ if (gsi_end_p (local_info->template_last_to_copy))
+ set_bb_seq (local_info->template_block, seq);
+ else
+ gsi_insert_seq_after (&local_info->template_last_to_copy,
+ seq, GSI_SAME_STMT);
+ }
/* Go ahead and wire up outgoing edges and update PHIs for the duplicate
block. */
ssa_fix_duplicate_block_edges (rd, local_info);
}
+ if (MAY_HAVE_DEBUG_STMTS)
+ {
+ /* Copy debug stmts from each NO_COPY src block to the block
+ that would have been its predecessor, if we can append to it
+ (we can't add stmts after a block-ending stmt), or prepending
+ to the duplicate of the successor, if there is one. If
+ there's no duplicate successor, we'll mostly drop the blocks
+ on the floor; propagate_threaded_block_debug_into, called
+ elsewhere, will consolidate and preserve the effects of the
+ binds, but none of the markers. */
+ gimple_stmt_iterator copy_to = gsi_last_bb (rd->dup_blocks[0]);
+ if (!gsi_end_p (copy_to))
+ {
+ if (stmt_ends_bb_p (gsi_stmt (copy_to)))
+ {
+ if (rd->dup_blocks[1])
+ copy_to = gsi_after_labels (rd->dup_blocks[1]);
+ else
+ copy_to = gsi_none ();
+ }
+ else
+ gsi_next (&copy_to);
+ }
+ for (unsigned int i = 2, j = 0; i < path->length (); i++)
+ if ((*path)[i]->type == EDGE_NO_COPY_SRC_BLOCK
+ && gsi_bb (copy_to))
+ {
+ for (gimple_stmt_iterator gsi = gsi_start_bb ((*path)[i]->e->src);
+ !gsi_end_p (gsi); gsi_next (&gsi))
+ {
+ if (!is_gimple_debug (gsi_stmt (gsi)))
+ continue;
+ gimple *stmt = gsi_stmt (gsi);
+ gimple *copy = gimple_copy (stmt);
+ gsi_insert_before (&copy_to, copy, GSI_SAME_STMT);
+ }
+ }
+ else if ((*path)[i]->type == EDGE_COPY_SRC_BLOCK
+ || (*path)[i]->type == EDGE_COPY_SRC_JOINER_BLOCK)
+ {
+ j++;
+ gcc_assert (j < 2);
+ copy_to = gsi_last_bb (rd->dup_blocks[j]);
+ if (!gsi_end_p (copy_to))
+ {
+ if (stmt_ends_bb_p (gsi_stmt (copy_to)))
+ copy_to = gsi_none ();
+ else
+ gsi_next (&copy_to);
+ }
+ }
+ }
+
/* Keep walking the hash table. */
return 1;
}
diff --git a/gcc/tree-ssa-uninit.c b/gcc/tree-ssa-uninit.c
index 8315878..fe8f8f0 100644
--- a/gcc/tree-ssa-uninit.c
+++ b/gcc/tree-ssa-uninit.c
@@ -1017,45 +1017,26 @@ static bool
is_value_included_in (tree val, tree boundary, enum tree_code cmpc)
{
bool inverted = false;
- bool is_unsigned;
bool result;
/* Only handle integer constant here. */
if (TREE_CODE (val) != INTEGER_CST || TREE_CODE (boundary) != INTEGER_CST)
return true;
- is_unsigned = TYPE_UNSIGNED (TREE_TYPE (val));
-
if (cmpc == GE_EXPR || cmpc == GT_EXPR || cmpc == NE_EXPR)
{
cmpc = invert_tree_comparison (cmpc, false);
inverted = true;
}
- if (is_unsigned)
- {
- if (cmpc == EQ_EXPR)
- result = tree_int_cst_equal (val, boundary);
- else if (cmpc == LT_EXPR)
- result = tree_int_cst_lt (val, boundary);
- else
- {
- gcc_assert (cmpc == LE_EXPR);
- result = tree_int_cst_le (val, boundary);
- }
- }
+ if (cmpc == EQ_EXPR)
+ result = tree_int_cst_equal (val, boundary);
+ else if (cmpc == LT_EXPR)
+ result = tree_int_cst_lt (val, boundary);
else
{
- if (cmpc == EQ_EXPR)
- result = tree_int_cst_equal (val, boundary);
- else if (cmpc == LT_EXPR)
- result = tree_int_cst_lt (val, boundary);
- else
- {
- gcc_assert (cmpc == LE_EXPR);
- result = (tree_int_cst_equal (val, boundary)
- || tree_int_cst_lt (val, boundary));
- }
+ gcc_assert (cmpc == LE_EXPR);
+ result = tree_int_cst_le (val, boundary);
}
if (inverted)
@@ -1064,6 +1045,26 @@ is_value_included_in (tree val, tree boundary, enum tree_code cmpc)
return result;
}
+/* Returns whether VAL satisfies (x CMPC BOUNDARY) predicate. CMPC can be
+ either one of the range comparison codes ({GE,LT,EQ,NE}_EXPR and the like),
+ or BIT_AND_EXPR. EXACT_P is only meaningful for the latter. It modifies the
+ question from whether VAL & BOUNDARY != 0 to whether VAL & BOUNDARY == VAL.
+ For other values of CMPC, EXACT_P is ignored. */
+
+static bool
+value_sat_pred_p (tree val, tree boundary, enum tree_code cmpc,
+ bool exact_p = false)
+{
+ if (cmpc != BIT_AND_EXPR)
+ return is_value_included_in (val, boundary, cmpc);
+
+ wide_int andw = wi::to_wide (val) & wi::to_wide (boundary);
+ if (exact_p)
+ return andw == wi::to_wide (val);
+ else
+ return andw.to_uhwi ();
+}
+
/* Returns true if PRED is common among all the predicate
chains (PREDS) (and therefore can be factored out).
NUM_PRED_CHAIN is the size of array PREDS. */
@@ -1491,17 +1492,14 @@ is_pred_expr_subset_of (pred_info expr1, pred_info expr2)
return false;
if (code2 == NE_EXPR)
- return !is_value_included_in (expr2.pred_rhs, expr1.pred_rhs, code1);
-
- if ((code1 == EQ_EXPR || code1 == BIT_AND_EXPR) && code2 == BIT_AND_EXPR)
- return (wi::to_wide (expr1.pred_rhs)
- == (wi::to_wide (expr1.pred_rhs) & wi::to_wide (expr2.pred_rhs)));
+ return !value_sat_pred_p (expr2.pred_rhs, expr1.pred_rhs, code1);
- if (code1 != code2)
- return false;
+ if (code1 == EQ_EXPR)
+ return value_sat_pred_p (expr1.pred_rhs, expr2.pred_rhs, code2);
- if (is_value_included_in (expr1.pred_rhs, expr2.pred_rhs, code2))
- return true;
+ if (code1 == code2)
+ return value_sat_pred_p (expr1.pred_rhs, expr2.pred_rhs, code2,
+ code1 == BIT_AND_EXPR);
return false;
}
diff --git a/gcc/tree-ssa.c b/gcc/tree-ssa.c
index 489f6dc..16eaa8e 100644
--- a/gcc/tree-ssa.c
+++ b/gcc/tree-ssa.c
@@ -627,6 +627,15 @@ release_defs_bitset (bitmap toremove)
}
+/* Disable warnings about missing quoting in GCC diagnostics for
+ the verification errors. Their format strings don't follow GCC
+ diagnostic conventions and the calls are ultimately followed by
+ one to internal_error. */
+#if __GNUC__ >= 10
+# pragma GCC diagnostic push
+# pragma GCC diagnostic ignored "-Wformat-diag"
+#endif
+
/* Verify virtual SSA form. */
bool
@@ -1193,6 +1202,9 @@ err:
internal_error ("verify_ssa failed");
}
+#if __GNUC__ >= 10
+# pragma GCC diagnostic pop
+#endif
/* Initialize global DFA and SSA structures. */
@@ -1521,14 +1533,29 @@ non_rewritable_lvalue_p (tree lhs)
if (DECL_P (decl)
&& VECTOR_TYPE_P (TREE_TYPE (decl))
&& TYPE_MODE (TREE_TYPE (decl)) != BLKmode
- && operand_equal_p (TYPE_SIZE_UNIT (TREE_TYPE (lhs)),
- TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (decl))), 0)
&& known_ge (mem_ref_offset (lhs), 0)
&& known_gt (wi::to_poly_offset (TYPE_SIZE_UNIT (TREE_TYPE (decl))),
mem_ref_offset (lhs))
&& multiple_of_p (sizetype, TREE_OPERAND (lhs, 1),
TYPE_SIZE_UNIT (TREE_TYPE (lhs))))
- return false;
+ {
+ poly_uint64 lhs_bits, nelts;
+ if (poly_int_tree_p (TYPE_SIZE (TREE_TYPE (lhs)), &lhs_bits)
+ && multiple_p (lhs_bits,
+ tree_to_uhwi
+ (TYPE_SIZE (TREE_TYPE (TREE_TYPE (decl)))),
+ &nelts))
+ {
+ if (known_eq (nelts, 1u))
+ return false;
+ /* For sub-vector inserts the insert vector mode has to be
+ supported. */
+ tree vtype = build_vector_type (TREE_TYPE (TREE_TYPE (decl)),
+ nelts);
+ if (TYPE_MODE (vtype) != BLKmode)
+ return false;
+ }
+ }
}
/* A vector-insert using a BIT_FIELD_REF is rewritable using
@@ -1866,20 +1893,30 @@ execute_update_addresses_taken (void)
&& bitmap_bit_p (suitable_for_renaming, DECL_UID (sym))
&& VECTOR_TYPE_P (TREE_TYPE (sym))
&& TYPE_MODE (TREE_TYPE (sym)) != BLKmode
- && operand_equal_p (TYPE_SIZE_UNIT (TREE_TYPE (lhs)),
- TYPE_SIZE_UNIT
- (TREE_TYPE (TREE_TYPE (sym))), 0)
- && tree_fits_uhwi_p (TREE_OPERAND (lhs, 1))
- && tree_int_cst_lt (TREE_OPERAND (lhs, 1),
- TYPE_SIZE_UNIT (TREE_TYPE (sym)))
- && (tree_to_uhwi (TREE_OPERAND (lhs, 1))
- % tree_to_uhwi (TYPE_SIZE_UNIT (TREE_TYPE (lhs)))) == 0)
+ && known_ge (mem_ref_offset (lhs), 0)
+ && known_gt (wi::to_poly_offset
+ (TYPE_SIZE_UNIT (TREE_TYPE (sym))),
+ mem_ref_offset (lhs))
+ && multiple_of_p (sizetype,
+ TREE_OPERAND (lhs, 1),
+ TYPE_SIZE_UNIT (TREE_TYPE (lhs))))
{
tree val = gimple_assign_rhs1 (stmt);
if (! types_compatible_p (TREE_TYPE (val),
TREE_TYPE (TREE_TYPE (sym))))
{
- tree tem = make_ssa_name (TREE_TYPE (TREE_TYPE (sym)));
+ poly_uint64 lhs_bits, nelts;
+ tree temtype = TREE_TYPE (TREE_TYPE (sym));
+ if (poly_int_tree_p (TYPE_SIZE (TREE_TYPE (lhs)),
+ &lhs_bits)
+ && multiple_p (lhs_bits,
+ tree_to_uhwi
+ (TYPE_SIZE (TREE_TYPE
+ (TREE_TYPE (sym)))),
+ &nelts)
+ && maybe_ne (nelts, 1u))
+ temtype = build_vector_type (temtype, nelts);
+ tree tem = make_ssa_name (temtype);
gimple *pun
= gimple_build_assign (tem,
build1 (VIEW_CONVERT_EXPR,
diff --git a/gcc/tree-ssanames.c b/gcc/tree-ssanames.c
index 5bac799..8b80bce 100644
--- a/gcc/tree-ssanames.c
+++ b/gcc/tree-ssanames.c
@@ -820,7 +820,12 @@ reset_flow_sensitive_info (tree name)
{
/* points-to info is not flow-sensitive. */
if (SSA_NAME_PTR_INFO (name))
- mark_ptr_info_alignment_unknown (SSA_NAME_PTR_INFO (name));
+ {
+ /* [E]VRP can derive context sensitive alignment info and
+ non-nullness properties. We must reset both. */
+ mark_ptr_info_alignment_unknown (SSA_NAME_PTR_INFO (name));
+ SSA_NAME_PTR_INFO (name)->pt.null = 1;
+ }
}
else
SSA_NAME_RANGE_INFO (name) = NULL;
diff --git a/gcc/tree-streamer-in.c b/gcc/tree-streamer-in.c
index 0084e47..35b3e98 100644
--- a/gcc/tree-streamer-in.c
+++ b/gcc/tree-streamer-in.c
@@ -251,7 +251,7 @@ unpack_ts_decl_common_value_fields (struct bitpack_d *bp, tree expr)
LABEL_DECL_UID (expr) = -1;
}
- if (TREE_CODE (expr) == FIELD_DECL)
+ else if (TREE_CODE (expr) == FIELD_DECL)
{
DECL_PACKED (expr) = (unsigned) bp_unpack_value (bp, 1);
DECL_NONADDRESSABLE_P (expr) = (unsigned) bp_unpack_value (bp, 1);
@@ -259,12 +259,15 @@ unpack_ts_decl_common_value_fields (struct bitpack_d *bp, tree expr)
expr->decl_common.off_align = bp_unpack_value (bp, 8);
}
- if (VAR_P (expr))
+ else if (VAR_P (expr))
{
DECL_HAS_DEBUG_EXPR_P (expr) = (unsigned) bp_unpack_value (bp, 1);
DECL_NONLOCAL_FRAME (expr) = (unsigned) bp_unpack_value (bp, 1);
}
+ else if (TREE_CODE (expr) == PARM_DECL)
+ DECL_HIDDEN_STRING_LENGTH (expr) = (unsigned) bp_unpack_value (bp, 1);
+
if (TREE_CODE (expr) == RESULT_DECL
|| TREE_CODE (expr) == PARM_DECL
|| VAR_P (expr))
@@ -369,7 +372,6 @@ unpack_ts_type_common_value_fields (struct bitpack_d *bp, tree expr)
mode = bp_unpack_machine_mode (bp);
SET_TYPE_MODE (expr, mode);
- TYPE_STRING_FLAG (expr) = (unsigned) bp_unpack_value (bp, 1);
/* TYPE_NO_FORCE_BLK is private to stor-layout and need
no streaming. */
TYPE_PACKED (expr) = (unsigned) bp_unpack_value (bp, 1);
@@ -380,9 +382,12 @@ unpack_ts_type_common_value_fields (struct bitpack_d *bp, tree expr)
{
TYPE_TRANSPARENT_AGGR (expr) = (unsigned) bp_unpack_value (bp, 1);
TYPE_FINAL_P (expr) = (unsigned) bp_unpack_value (bp, 1);
+ TYPE_CXX_ODR_P (expr) = (unsigned) bp_unpack_value (bp, 1);
}
else if (TREE_CODE (expr) == ARRAY_TYPE)
TYPE_NONALIASED_COMPONENT (expr) = (unsigned) bp_unpack_value (bp, 1);
+ if (TREE_CODE (expr) == ARRAY_TYPE || TREE_CODE (expr) == INTEGER_TYPE)
+ TYPE_STRING_FLAG (expr) = (unsigned) bp_unpack_value (bp, 1);
if (AGGREGATE_TYPE_P (expr))
TYPE_TYPELESS_STORAGE (expr) = (unsigned) bp_unpack_value (bp, 1);
TYPE_EMPTY_P (expr) = (unsigned) bp_unpack_value (bp, 1);
diff --git a/gcc/tree-streamer-out.c b/gcc/tree-streamer-out.c
index b664263..a83057e 100644
--- a/gcc/tree-streamer-out.c
+++ b/gcc/tree-streamer-out.c
@@ -212,7 +212,7 @@ pack_ts_decl_common_value_fields (struct bitpack_d *bp, tree expr)
bp_pack_var_len_unsigned (bp, EH_LANDING_PAD_NR (expr));
}
- if (TREE_CODE (expr) == FIELD_DECL)
+ else if (TREE_CODE (expr) == FIELD_DECL)
{
bp_pack_value (bp, DECL_PACKED (expr), 1);
bp_pack_value (bp, DECL_NONADDRESSABLE_P (expr), 1);
@@ -220,12 +220,15 @@ pack_ts_decl_common_value_fields (struct bitpack_d *bp, tree expr)
bp_pack_value (bp, expr->decl_common.off_align, 8);
}
- if (VAR_P (expr))
+ else if (VAR_P (expr))
{
bp_pack_value (bp, DECL_HAS_DEBUG_EXPR_P (expr), 1);
bp_pack_value (bp, DECL_NONLOCAL_FRAME (expr), 1);
}
+ else if (TREE_CODE (expr) == PARM_DECL)
+ bp_pack_value (bp, DECL_HIDDEN_STRING_LENGTH (expr), 1);
+
if (TREE_CODE (expr) == RESULT_DECL
|| TREE_CODE (expr) == PARM_DECL
|| VAR_P (expr))
@@ -316,7 +319,6 @@ pack_ts_type_common_value_fields (struct bitpack_d *bp, tree expr)
not necessary valid in a global context.
Use the raw value previously set by layout_type. */
bp_pack_machine_mode (bp, TYPE_MODE_RAW (expr));
- bp_pack_value (bp, TYPE_STRING_FLAG (expr), 1);
/* TYPE_NO_FORCE_BLK is private to stor-layout and need
no streaming. */
bp_pack_value (bp, TYPE_PACKED (expr), 1);
@@ -330,9 +332,12 @@ pack_ts_type_common_value_fields (struct bitpack_d *bp, tree expr)
{
bp_pack_value (bp, TYPE_TRANSPARENT_AGGR (expr), 1);
bp_pack_value (bp, TYPE_FINAL_P (expr), 1);
+ bp_pack_value (bp, TYPE_CXX_ODR_P (expr), 1);
}
else if (TREE_CODE (expr) == ARRAY_TYPE)
bp_pack_value (bp, TYPE_NONALIASED_COMPONENT (expr), 1);
+ if (TREE_CODE (expr) == ARRAY_TYPE || TREE_CODE (expr) == INTEGER_TYPE)
+ bp_pack_value (bp, TYPE_STRING_FLAG (expr), 1);
if (AGGREGATE_TYPE_P (expr))
bp_pack_value (bp, TYPE_TYPELESS_STORAGE (expr), 1);
bp_pack_value (bp, TYPE_EMPTY_P (expr), 1);
@@ -576,7 +581,7 @@ write_ts_decl_minimal_tree_pointers (struct output_block *ob, tree expr,
/* Drop names that were created for anonymous entities. */
if (DECL_NAME (expr)
&& TREE_CODE (DECL_NAME (expr)) == IDENTIFIER_NODE
- && anon_aggrname_p (DECL_NAME (expr)))
+ && IDENTIFIER_ANON_P (DECL_NAME (expr)))
stream_write_tree (ob, NULL_TREE, ref_p);
else
stream_write_tree (ob, DECL_NAME (expr), ref_p);
diff --git a/gcc/tree-streamer.c b/gcc/tree-streamer.c
index b7bd276..fb2888d 100644
--- a/gcc/tree-streamer.c
+++ b/gcc/tree-streamer.c
@@ -377,6 +377,9 @@ preload_common_nodes (struct streamer_tree_cache_d *cache)
&& i != TI_TARGET_OPTION_CURRENT
&& i != TI_CURRENT_TARGET_PRAGMA
&& i != TI_CURRENT_OPTIMIZE_PRAGMA
+ /* SCEV state shouldn't reach the IL. */
+ && i != TI_CHREC_DONT_KNOW
+ && i != TI_CHREC_KNOWN
/* Skip va_list* related nodes if offloading. For native LTO
we want them to be merged for the stdarg pass, for offloading
they might not be identical between host and offloading target. */
diff --git a/gcc/tree-switch-conversion.c b/gcc/tree-switch-conversion.c
index c3f2baf..5f8ed46 100644
--- a/gcc/tree-switch-conversion.c
+++ b/gcc/tree-switch-conversion.c
@@ -1268,7 +1268,9 @@ jump_table_cluster::can_be_handled (const vec<cluster *> &clusters,
return true;
unsigned HOST_WIDE_INT max_ratio
- = optimize_insn_for_size_p () ? max_ratio_for_size : max_ratio_for_speed;
+ = (optimize_insn_for_size_p ()
+ ? PARAM_VALUE (PARAM_JUMP_TABLE_MAX_GROWTH_RATIO_FOR_SIZE)
+ : PARAM_VALUE (PARAM_JUMP_TABLE_MAX_GROWTH_RATIO_FOR_SPEED));
unsigned HOST_WIDE_INT range = get_range (clusters[start]->get_low (),
clusters[end]->get_high ());
/* Check overflow. */
@@ -1282,7 +1284,11 @@ jump_table_cluster::can_be_handled (const vec<cluster *> &clusters,
comparison_count += sc->m_range_p ? 2 : 1;
}
- return range <= max_ratio * comparison_count;
+ unsigned HOST_WIDE_INT lhs = 100 * range;
+ if (lhs < range)
+ return false;
+
+ return lhs <= max_ratio * comparison_count;
}
/* Return true if cluster starting at START and ending at END (inclusive)
@@ -1299,11 +1305,6 @@ jump_table_cluster::is_beneficial (const vec<cluster *> &,
return end - start + 1 >= case_values_threshold ();
}
-/* Definition of jump_table_cluster constants. */
-
-const unsigned HOST_WIDE_INT jump_table_cluster::max_ratio_for_size;
-const unsigned HOST_WIDE_INT jump_table_cluster::max_ratio_for_speed;
-
/* Find bit tests of given CLUSTERS, where all members of the vector
are of type simple_cluster. New clusters are returned. */
diff --git a/gcc/tree-switch-conversion.h b/gcc/tree-switch-conversion.h
index b3bc4b9..a9a959c 100644
--- a/gcc/tree-switch-conversion.h
+++ b/gcc/tree-switch-conversion.h
@@ -269,12 +269,6 @@ struct jump_table_cluster: public group_cluster
/* Return whether jump table expansion is allowed. */
static bool is_enabled (void);
-
- /* Max growth ratio for code that is optimized for size. */
- static const unsigned HOST_WIDE_INT max_ratio_for_size = 3;
-
- /* Max growth ratio for code that is optimized for speed. */
- static const unsigned HOST_WIDE_INT max_ratio_for_speed = 8;
};
/* A GIMPLE switch statement can be expanded to a short sequence of bit-wise
diff --git a/gcc/tree-tailcall.c b/gcc/tree-tailcall.c
index f483585..a99cd11 100644
--- a/gcc/tree-tailcall.c
+++ b/gcc/tree-tailcall.c
@@ -140,6 +140,7 @@ suitable_for_tail_opt_p (void)
return true;
}
+
/* Returns false when the function is not suitable for tail call optimization
for some reason (e.g. if it takes variable number of arguments).
This test must pass in addition to suitable_for_tail_opt_p in order to make
@@ -168,6 +169,11 @@ suitable_for_tail_call_opt_p (void)
if (cfun->calls_setjmp)
return false;
+ /* Various targets don't handle tail calls correctly in functions
+ that call __builtin_eh_return. */
+ if (cfun->calls_eh_return)
+ return false;
+
/* ??? It is OK if the argument of a function is taken in some cases,
but not in all cases. See PR15387 and PR19616. Revisit for 4.1. */
for (param = DECL_ARGUMENTS (current_function_decl);
diff --git a/gcc/tree-vect-data-refs.c b/gcc/tree-vect-data-refs.c
index d71a39f..cf9cee5 100644
--- a/gcc/tree-vect-data-refs.c
+++ b/gcc/tree-vect-data-refs.c
@@ -2863,10 +2863,12 @@ strip_conversion (tree op)
}
/* Return true if vectorizable_* routines can handle statements STMT1_INFO
- and STMT2_INFO being in a single group. */
+ and STMT2_INFO being in a single group. When ALLOW_SLP_P, masked loads can
+ be grouped in SLP mode. */
static bool
-can_group_stmts_p (stmt_vec_info stmt1_info, stmt_vec_info stmt2_info)
+can_group_stmts_p (stmt_vec_info stmt1_info, stmt_vec_info stmt2_info,
+ bool allow_slp_p)
{
if (gimple_assign_single_p (stmt1_info->stmt))
return gimple_assign_single_p (stmt2_info->stmt);
@@ -2888,7 +2890,8 @@ can_group_stmts_p (stmt_vec_info stmt1_info, stmt_vec_info stmt2_info)
like those created by build_mask_conversion. */
tree mask1 = gimple_call_arg (call1, 2);
tree mask2 = gimple_call_arg (call2, 2);
- if (!operand_equal_p (mask1, mask2, 0))
+ if (!operand_equal_p (mask1, mask2, 0)
+ && (ifn == IFN_MASK_STORE || !allow_slp_p))
{
mask1 = strip_conversion (mask1);
if (!mask1)
@@ -2974,7 +2977,7 @@ vect_analyze_data_ref_accesses (vec_info *vinfo)
|| data_ref_compare_tree (DR_BASE_ADDRESS (dra),
DR_BASE_ADDRESS (drb)) != 0
|| data_ref_compare_tree (DR_OFFSET (dra), DR_OFFSET (drb)) != 0
- || !can_group_stmts_p (stmtinfo_a, stmtinfo_b))
+ || !can_group_stmts_p (stmtinfo_a, stmtinfo_b, true))
break;
/* Check that the data-refs have the same constant size. */
@@ -3000,6 +3003,13 @@ vect_analyze_data_ref_accesses (vec_info *vinfo)
|| TREE_CODE (DR_INIT (drb)) != INTEGER_CST)
break;
+ /* Different .GOMP_SIMD_LANE calls still give the same lane,
+ just hold extra information. */
+ if (STMT_VINFO_SIMD_LANE_ACCESS_P (stmtinfo_a)
+ && STMT_VINFO_SIMD_LANE_ACCESS_P (stmtinfo_b)
+ && data_ref_compare_tree (DR_INIT (dra), DR_INIT (drb)) == 0)
+ break;
+
/* Sorting has ensured that DR_INIT (dra) <= DR_INIT (drb). */
HOST_WIDE_INT init_a = TREE_INT_CST_LOW (DR_INIT (dra));
HOST_WIDE_INT init_b = TREE_INT_CST_LOW (DR_INIT (drb));
@@ -3059,6 +3069,13 @@ vect_analyze_data_ref_accesses (vec_info *vinfo)
DR_GROUP_NEXT_ELEMENT (lastinfo) = stmtinfo_b;
lastinfo = stmtinfo_b;
+ STMT_VINFO_SLP_VECT_ONLY (stmtinfo_a)
+ = !can_group_stmts_p (stmtinfo_a, stmtinfo_b, false);
+
+ if (dump_enabled_p () && STMT_VINFO_SLP_VECT_ONLY (stmtinfo_a))
+ dump_printf_loc (MSG_NOTE, vect_location,
+ "Load suitable for SLP vectorization only.\n");
+
if (init_b == init_prev
&& !to_fixup.add (DR_GROUP_FIRST_ELEMENT (stmtinfo_a))
&& dump_enabled_p ())
@@ -4055,47 +4072,67 @@ vect_find_stmt_data_reference (loop_p loop, gimple *stmt,
&& DR_OFFSET (newdr)
&& DR_INIT (newdr)
&& DR_STEP (newdr)
+ && TREE_CODE (DR_INIT (newdr)) == INTEGER_CST
&& integer_zerop (DR_STEP (newdr)))
{
+ tree base_address = DR_BASE_ADDRESS (newdr);
tree off = DR_OFFSET (newdr);
+ tree step = ssize_int (1);
+ if (integer_zerop (off)
+ && TREE_CODE (base_address) == POINTER_PLUS_EXPR)
+ {
+ off = TREE_OPERAND (base_address, 1);
+ base_address = TREE_OPERAND (base_address, 0);
+ }
STRIP_NOPS (off);
- if (TREE_CODE (DR_INIT (newdr)) == INTEGER_CST
- && TREE_CODE (off) == MULT_EXPR
+ if (TREE_CODE (off) == MULT_EXPR
&& tree_fits_uhwi_p (TREE_OPERAND (off, 1)))
{
- tree step = TREE_OPERAND (off, 1);
+ step = TREE_OPERAND (off, 1);
off = TREE_OPERAND (off, 0);
STRIP_NOPS (off);
- if (CONVERT_EXPR_P (off)
- && (TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (off, 0)))
- < TYPE_PRECISION (TREE_TYPE (off))))
- off = TREE_OPERAND (off, 0);
- if (TREE_CODE (off) == SSA_NAME)
+ }
+ if (CONVERT_EXPR_P (off)
+ && (TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (off, 0)))
+ < TYPE_PRECISION (TREE_TYPE (off))))
+ off = TREE_OPERAND (off, 0);
+ if (TREE_CODE (off) == SSA_NAME)
+ {
+ gimple *def = SSA_NAME_DEF_STMT (off);
+ /* Look through widening conversion. */
+ if (is_gimple_assign (def)
+ && CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (def)))
+ {
+ tree rhs1 = gimple_assign_rhs1 (def);
+ if (TREE_CODE (rhs1) == SSA_NAME
+ && INTEGRAL_TYPE_P (TREE_TYPE (rhs1))
+ && (TYPE_PRECISION (TREE_TYPE (off))
+ > TYPE_PRECISION (TREE_TYPE (rhs1))))
+ def = SSA_NAME_DEF_STMT (rhs1);
+ }
+ if (is_gimple_call (def)
+ && gimple_call_internal_p (def)
+ && (gimple_call_internal_fn (def) == IFN_GOMP_SIMD_LANE))
{
- gimple *def = SSA_NAME_DEF_STMT (off);
+ tree arg = gimple_call_arg (def, 0);
tree reft = TREE_TYPE (DR_REF (newdr));
- if (is_gimple_call (def)
- && gimple_call_internal_p (def)
- && (gimple_call_internal_fn (def) == IFN_GOMP_SIMD_LANE))
+ gcc_assert (TREE_CODE (arg) == SSA_NAME);
+ arg = SSA_NAME_VAR (arg);
+ if (arg == loop->simduid
+ /* For now. */
+ && tree_int_cst_equal (TYPE_SIZE_UNIT (reft), step))
{
- tree arg = gimple_call_arg (def, 0);
- gcc_assert (TREE_CODE (arg) == SSA_NAME);
- arg = SSA_NAME_VAR (arg);
- if (arg == loop->simduid
- /* For now. */
- && tree_int_cst_equal (TYPE_SIZE_UNIT (reft), step))
- {
- DR_OFFSET (newdr) = ssize_int (0);
- DR_STEP (newdr) = step;
- DR_OFFSET_ALIGNMENT (newdr) = BIGGEST_ALIGNMENT;
- DR_STEP_ALIGNMENT (newdr)
- = highest_pow2_factor (step);
- /* Mark as simd-lane access. */
- newdr->aux = (void *)-1;
- free_data_ref (dr);
- datarefs->safe_push (newdr);
- return opt_result::success ();
- }
+ DR_BASE_ADDRESS (newdr) = base_address;
+ DR_OFFSET (newdr) = ssize_int (0);
+ DR_STEP (newdr) = step;
+ DR_OFFSET_ALIGNMENT (newdr) = BIGGEST_ALIGNMENT;
+ DR_STEP_ALIGNMENT (newdr) = highest_pow2_factor (step);
+ /* Mark as simd-lane access. */
+ tree arg2 = gimple_call_arg (def, 1);
+ newdr->aux = (void *) (-1 - tree_to_uhwi (arg2));
+ free_data_ref (dr);
+ datarefs->safe_push (newdr);
+ return opt_result::success ();
}
}
}
@@ -4123,7 +4160,7 @@ vect_find_stmt_data_reference (loop_p loop, gimple *stmt,
*/
opt_result
-vect_analyze_data_refs (vec_info *vinfo, poly_uint64 *min_vf)
+vect_analyze_data_refs (vec_info *vinfo, poly_uint64 *min_vf, bool *fatal)
{
struct loop *loop = NULL;
unsigned int i;
@@ -4200,14 +4237,18 @@ vect_analyze_data_refs (vec_info *vinfo, poly_uint64 *min_vf)
}
/* See if this was detected as SIMD lane access. */
- if (dr->aux == (void *)-1)
+ if (dr->aux == (void *)-1
+ || dr->aux == (void *)-2
+ || dr->aux == (void *)-3
+ || dr->aux == (void *)-4)
{
if (nested_in_vect_loop_p (loop, stmt_info))
return opt_result::failure_at (stmt_info->stmt,
"not vectorized:"
" data ref analysis failed: %G",
stmt_info->stmt);
- STMT_VINFO_SIMD_LANE_ACCESS_P (stmt_info) = true;
+ STMT_VINFO_SIMD_LANE_ACCESS_P (stmt_info)
+ = -(uintptr_t) dr->aux;
}
tree base = get_base_address (DR_REF (dr));
@@ -4345,12 +4386,16 @@ vect_analyze_data_refs (vec_info *vinfo, poly_uint64 *min_vf)
as_a <loop_vec_info> (vinfo),
&gs_info)
|| !get_vectype_for_scalar_type (TREE_TYPE (gs_info.offset)))
- return opt_result::failure_at
- (stmt_info->stmt,
- (gatherscatter == GATHER) ?
- "not vectorized: not suitable for gather load %G" :
- "not vectorized: not suitable for scatter store %G",
- stmt_info->stmt);
+ {
+ if (fatal)
+ *fatal = false;
+ return opt_result::failure_at
+ (stmt_info->stmt,
+ (gatherscatter == GATHER)
+ ? "not vectorized: not suitable for gather load %G"
+ : "not vectorized: not suitable for scatter store %G",
+ stmt_info->stmt);
+ }
STMT_VINFO_GATHER_SCATTER_P (stmt_info) = gatherscatter;
}
}
diff --git a/gcc/tree-vect-generic.c b/gcc/tree-vect-generic.c
index e9f5505..8389f55 100644
--- a/gcc/tree-vect-generic.c
+++ b/gcc/tree-vect-generic.c
@@ -1367,6 +1367,32 @@ lower_vec_perm (gimple_stmt_iterator *gsi)
return;
}
}
+ /* And similarly vec_shl pattern. */
+ if (optab_handler (vec_shl_optab, TYPE_MODE (vect_type))
+ != CODE_FOR_nothing
+ && TREE_CODE (vec0) == VECTOR_CST
+ && initializer_zerop (vec0))
+ {
+ unsigned int first = 0;
+ for (i = 0; i < elements; ++i)
+ if (known_eq (poly_uint64 (indices[i]), elements))
+ {
+ if (i == 0 || first)
+ break;
+ first = i;
+ }
+ else if (first
+ ? maybe_ne (poly_uint64 (indices[i]),
+ elements + i - first)
+ : maybe_ge (poly_uint64 (indices[i]), elements))
+ break;
+ if (i == elements)
+ {
+ gimple_assign_set_rhs3 (stmt, mask);
+ update_stmt (stmt);
+ return;
+ }
+ }
}
else if (can_vec_perm_var_p (TYPE_MODE (vect_type)))
return;
@@ -1955,7 +1981,6 @@ expand_vector_operations_1 (gimple_stmt_iterator *gsi)
|| code == VEC_UNPACK_FLOAT_LO_EXPR
|| code == VEC_PACK_FLOAT_EXPR)
{
- type = TREE_TYPE (rhs1);
/* We do not know how to scalarize those. */
return;
}
@@ -1978,7 +2003,6 @@ expand_vector_operations_1 (gimple_stmt_iterator *gsi)
|| code == VEC_WIDEN_LSHIFT_HI_EXPR
|| code == VEC_WIDEN_LSHIFT_LO_EXPR)
{
- type = TREE_TYPE (rhs1);
/* We do not know how to scalarize those. */
return;
}
diff --git a/gcc/tree-vect-loop-manip.c b/gcc/tree-vect-loop-manip.c
index 77d3dac..c5cabc8 100644
--- a/gcc/tree-vect-loop-manip.c
+++ b/gcc/tree-vect-loop-manip.c
@@ -382,8 +382,7 @@ vect_maybe_permute_loop_masks (gimple_seq *seq, rgroup_masks *dest_rgm,
Use LOOP_COND_GSI to insert code before the exit gcond.
RGM belongs to loop LOOP. The loop originally iterated NITERS
- times and has been vectorized according to LOOP_VINFO. Each iteration
- of the vectorized loop handles VF iterations of the scalar loop.
+ times and has been vectorized according to LOOP_VINFO.
If NITERS_SKIP is nonnull, the first iteration of the vectorized loop
starts with NITERS_SKIP dummy iterations of the scalar loop before
@@ -410,34 +409,36 @@ static tree
vect_set_loop_masks_directly (struct loop *loop, loop_vec_info loop_vinfo,
gimple_seq *preheader_seq,
gimple_stmt_iterator loop_cond_gsi,
- rgroup_masks *rgm, tree vf,
- tree niters, tree niters_skip,
+ rgroup_masks *rgm, tree niters, tree niters_skip,
bool might_wrap_p)
{
tree compare_type = LOOP_VINFO_MASK_COMPARE_TYPE (loop_vinfo);
+ tree iv_type = LOOP_VINFO_MASK_IV_TYPE (loop_vinfo);
tree mask_type = rgm->mask_type;
unsigned int nscalars_per_iter = rgm->max_nscalars_per_iter;
poly_uint64 nscalars_per_mask = TYPE_VECTOR_SUBPARTS (mask_type);
+ poly_uint64 vf = LOOP_VINFO_VECT_FACTOR (loop_vinfo);
/* Calculate the maximum number of scalar values that the rgroup
handles in total, the number that it handles for each iteration
of the vector loop, and the number that it should skip during the
first iteration of the vector loop. */
tree nscalars_total = niters;
- tree nscalars_step = vf;
+ tree nscalars_step = build_int_cst (iv_type, vf);
tree nscalars_skip = niters_skip;
if (nscalars_per_iter != 1)
{
/* We checked before choosing to use a fully-masked loop that these
multiplications don't overflow. */
- tree factor = build_int_cst (compare_type, nscalars_per_iter);
+ tree compare_factor = build_int_cst (compare_type, nscalars_per_iter);
+ tree iv_factor = build_int_cst (iv_type, nscalars_per_iter);
nscalars_total = gimple_build (preheader_seq, MULT_EXPR, compare_type,
- nscalars_total, factor);
- nscalars_step = gimple_build (preheader_seq, MULT_EXPR, compare_type,
- nscalars_step, factor);
+ nscalars_total, compare_factor);
+ nscalars_step = gimple_build (preheader_seq, MULT_EXPR, iv_type,
+ nscalars_step, iv_factor);
if (nscalars_skip)
nscalars_skip = gimple_build (preheader_seq, MULT_EXPR, compare_type,
- nscalars_skip, factor);
+ nscalars_skip, compare_factor);
}
/* Create an induction variable that counts the number of scalars
@@ -445,11 +446,11 @@ vect_set_loop_masks_directly (struct loop *loop, loop_vec_info loop_vinfo,
tree index_before_incr, index_after_incr;
gimple_stmt_iterator incr_gsi;
bool insert_after;
- tree zero_index = build_int_cst (compare_type, 0);
standard_iv_increment_position (loop, &incr_gsi, &insert_after);
- create_iv (zero_index, nscalars_step, NULL_TREE, loop, &incr_gsi,
- insert_after, &index_before_incr, &index_after_incr);
+ create_iv (build_int_cst (iv_type, 0), nscalars_step, NULL_TREE, loop,
+ &incr_gsi, insert_after, &index_before_incr, &index_after_incr);
+ tree zero_index = build_int_cst (compare_type, 0);
tree test_index, test_limit, first_limit;
gimple_stmt_iterator *test_gsi;
if (might_wrap_p)
@@ -481,7 +482,8 @@ vect_set_loop_masks_directly (struct loop *loop, loop_vec_info loop_vinfo,
where the rightmost subtraction can be done directly in
COMPARE_TYPE. */
test_index = index_before_incr;
- tree adjust = nscalars_step;
+ tree adjust = gimple_convert (preheader_seq, compare_type,
+ nscalars_step);
if (nscalars_skip)
adjust = gimple_build (preheader_seq, MINUS_EXPR, compare_type,
adjust, nscalars_skip);
@@ -525,6 +527,12 @@ vect_set_loop_masks_directly (struct loop *loop, loop_vec_info loop_vinfo,
first_limit = test_limit;
}
+ /* Convert the IV value to the comparison type (either a no-op or
+ a demotion). */
+ gimple_seq test_seq = NULL;
+ test_index = gimple_convert (&test_seq, compare_type, test_index);
+ gsi_insert_seq_before (test_gsi, test_seq, GSI_SAME_STMT);
+
/* Provide a definition of each mask in the group. */
tree next_mask = NULL_TREE;
tree mask;
@@ -637,12 +645,12 @@ vect_set_loop_condition_masked (struct loop *loop, loop_vec_info loop_vinfo,
tree compare_type = LOOP_VINFO_MASK_COMPARE_TYPE (loop_vinfo);
unsigned int compare_precision = TYPE_PRECISION (compare_type);
- unsigned HOST_WIDE_INT max_vf = vect_max_vf (loop_vinfo);
tree orig_niters = niters;
/* Type of the initial value of NITERS. */
tree ni_actual_type = TREE_TYPE (niters);
unsigned int ni_actual_precision = TYPE_PRECISION (ni_actual_type);
+ tree niters_skip = LOOP_VINFO_MASK_SKIP_NITERS (loop_vinfo);
/* Convert NITERS to the same size as the compare. */
if (compare_precision > ni_actual_precision
@@ -661,36 +669,7 @@ vect_set_loop_condition_masked (struct loop *loop, loop_vec_info loop_vinfo,
else
niters = gimple_convert (&preheader_seq, compare_type, niters);
- /* Convert skip_niters to the right type. */
- tree niters_skip = LOOP_VINFO_MASK_SKIP_NITERS (loop_vinfo);
-
- /* Now calculate the value that the induction variable must be able
- to hit in order to ensure that we end the loop with an all-false mask.
- This involves adding the maximum number of inactive trailing scalar
- iterations. */
- widest_int iv_limit;
- bool known_max_iters = max_loop_iterations (loop, &iv_limit);
- if (known_max_iters)
- {
- if (niters_skip)
- {
- /* Add the maximum number of skipped iterations to the
- maximum iteration count. */
- if (TREE_CODE (niters_skip) == INTEGER_CST)
- iv_limit += wi::to_widest (niters_skip);
- else
- iv_limit += max_vf - 1;
- }
- /* IV_LIMIT is the maximum number of latch iterations, which is also
- the maximum in-range IV value. Round this value down to the previous
- vector alignment boundary and then add an extra full iteration. */
- poly_uint64 vf = LOOP_VINFO_VECT_FACTOR (loop_vinfo);
- iv_limit = (iv_limit & -(int) known_alignment (vf)) + max_vf;
- }
-
- /* Get the vectorization factor in tree form. */
- tree vf = build_int_cst (compare_type,
- LOOP_VINFO_VECT_FACTOR (loop_vinfo));
+ widest_int iv_limit = vect_iv_limit_for_full_masking (loop_vinfo);
/* Iterate over all the rgroups and fill in their masks. We could use
the first mask from any rgroup for the loop condition; here we
@@ -717,7 +696,7 @@ vect_set_loop_condition_masked (struct loop *loop, loop_vec_info loop_vinfo,
/* See whether zero-based IV would ever generate all-false masks
before wrapping around. */
bool might_wrap_p
- = (!known_max_iters
+ = (iv_limit == -1
|| (wi::min_precision (iv_limit * rgm->max_nscalars_per_iter,
UNSIGNED)
> compare_precision));
@@ -725,7 +704,7 @@ vect_set_loop_condition_masked (struct loop *loop, loop_vec_info loop_vinfo,
/* Set up all masks for this group. */
test_mask = vect_set_loop_masks_directly (loop, loop_vinfo,
&preheader_seq,
- loop_cond_gsi, rgm, vf,
+ loop_cond_gsi, rgm,
niters, niters_skip,
might_wrap_p);
}
@@ -3009,6 +2988,8 @@ vect_loop_versioning (loop_vec_info loop_vinfo,
bool version_align = LOOP_REQUIRES_VERSIONING_FOR_ALIGNMENT (loop_vinfo);
bool version_alias = LOOP_REQUIRES_VERSIONING_FOR_ALIAS (loop_vinfo);
bool version_niter = LOOP_REQUIRES_VERSIONING_FOR_NITERS (loop_vinfo);
+ tree version_simd_if_cond
+ = LOOP_REQUIRES_VERSIONING_FOR_SIMD_IF_COND (loop_vinfo);
if (check_profitability)
cond_expr = fold_build2 (GE_EXPR, boolean_type_node, scalar_loop_iters,
@@ -3030,7 +3011,8 @@ vect_loop_versioning (loop_vec_info loop_vinfo,
vect_create_cond_for_niters_checks (loop_vinfo, &cond_expr);
if (cond_expr)
- cond_expr = force_gimple_operand_1 (cond_expr, &cond_expr_stmt_list,
+ cond_expr = force_gimple_operand_1 (unshare_expr (cond_expr),
+ &cond_expr_stmt_list,
is_gimple_condexpr, NULL_TREE);
if (version_align)
@@ -3044,50 +3026,169 @@ vect_loop_versioning (loop_vec_info loop_vinfo,
vect_create_cond_for_alias_checks (loop_vinfo, &cond_expr);
}
+ if (version_simd_if_cond)
+ {
+ gcc_assert (dom_info_available_p (CDI_DOMINATORS));
+ if (flag_checking)
+ if (basic_block bb
+ = gimple_bb (SSA_NAME_DEF_STMT (version_simd_if_cond)))
+ gcc_assert (bb != loop->header
+ && dominated_by_p (CDI_DOMINATORS, loop->header, bb)
+ && (scalar_loop == NULL
+ || (bb != scalar_loop->header
+ && dominated_by_p (CDI_DOMINATORS,
+ scalar_loop->header, bb))));
+ tree zero = build_zero_cst (TREE_TYPE (version_simd_if_cond));
+ tree c = fold_build2 (NE_EXPR, boolean_type_node,
+ version_simd_if_cond, zero);
+ if (cond_expr)
+ cond_expr = fold_build2 (TRUTH_AND_EXPR, boolean_type_node,
+ c, cond_expr);
+ else
+ cond_expr = c;
+ if (dump_enabled_p ())
+ dump_printf_loc (MSG_NOTE, vect_location,
+ "created versioning for simd if condition check.\n");
+ }
+
cond_expr = force_gimple_operand_1 (unshare_expr (cond_expr),
&gimplify_stmt_list,
is_gimple_condexpr, NULL_TREE);
gimple_seq_add_seq (&cond_expr_stmt_list, gimplify_stmt_list);
- initialize_original_copy_tables ();
- if (scalar_loop)
+ /* Compute the outermost loop cond_expr and cond_expr_stmt_list are
+ invariant in. */
+ struct loop *outermost = outermost_invariant_loop_for_expr (loop, cond_expr);
+ for (gimple_stmt_iterator gsi = gsi_start (cond_expr_stmt_list);
+ !gsi_end_p (gsi); gsi_next (&gsi))
{
- edge scalar_e;
- basic_block preheader, scalar_preheader;
+ gimple *stmt = gsi_stmt (gsi);
+ update_stmt (stmt);
+ ssa_op_iter iter;
+ use_operand_p use_p;
+ basic_block def_bb;
+ FOR_EACH_SSA_USE_OPERAND (use_p, stmt, iter, SSA_OP_USE)
+ if ((def_bb = gimple_bb (SSA_NAME_DEF_STMT (USE_FROM_PTR (use_p))))
+ && flow_bb_inside_loop_p (outermost, def_bb))
+ outermost = superloop_at_depth (loop, bb_loop_depth (def_bb) + 1);
+ }
- /* We don't want to scale SCALAR_LOOP's frequencies, we need to
- scale LOOP's frequencies instead. */
- nloop = loop_version (scalar_loop, cond_expr, &condition_bb,
- prob, prob.invert (), prob, prob.invert (), true);
- scale_loop_frequencies (loop, prob);
- /* CONDITION_BB was created above SCALAR_LOOP's preheader,
- while we need to move it above LOOP's preheader. */
- e = loop_preheader_edge (loop);
- scalar_e = loop_preheader_edge (scalar_loop);
- /* The vector loop preheader might not be empty, since new
- invariants could have been created while analyzing the loop. */
- gcc_assert (single_pred_p (e->src));
- gcc_assert (empty_block_p (scalar_e->src)
- && single_pred_p (scalar_e->src));
- gcc_assert (single_pred_p (condition_bb));
- preheader = e->src;
- scalar_preheader = scalar_e->src;
- scalar_e = find_edge (condition_bb, scalar_preheader);
- e = single_pred_edge (preheader);
- redirect_edge_and_branch_force (single_pred_edge (condition_bb),
- scalar_preheader);
- redirect_edge_and_branch_force (scalar_e, preheader);
- redirect_edge_and_branch_force (e, condition_bb);
- set_immediate_dominator (CDI_DOMINATORS, condition_bb,
- single_pred (condition_bb));
- set_immediate_dominator (CDI_DOMINATORS, scalar_preheader,
- single_pred (scalar_preheader));
- set_immediate_dominator (CDI_DOMINATORS, preheader,
- condition_bb);
+ /* Search for the outermost loop we can version. Avoid versioning of
+ non-perfect nests but allow if-conversion versioned loops inside. */
+ struct loop *loop_to_version = loop;
+ if (flow_loop_nested_p (outermost, loop))
+ {
+ if (dump_enabled_p ())
+ dump_printf_loc (MSG_NOTE, vect_location,
+ "trying to apply versioning to outer loop %d\n",
+ outermost->num);
+ if (outermost->num == 0)
+ outermost = superloop_at_depth (loop, 1);
+ /* And avoid applying versioning on non-perfect nests. */
+ while (loop_to_version != outermost
+ && single_exit (loop_outer (loop_to_version))
+ && (!loop_outer (loop_to_version)->inner->next
+ || vect_loop_vectorized_call (loop_to_version))
+ && (!loop_outer (loop_to_version)->inner->next
+ || !loop_outer (loop_to_version)->inner->next->next))
+ loop_to_version = loop_outer (loop_to_version);
+ }
+
+ /* Apply versioning. If there is already a scalar version created by
+ if-conversion re-use that. Note we cannot re-use the copy of
+ an if-converted outer-loop when vectorizing the inner loop only. */
+ gcond *cond;
+ gimple *call;
+ if ((!loop_to_version->inner || loop == loop_to_version)
+ && (call = vect_loop_vectorized_call (loop_to_version, &cond)))
+ {
+ gcc_assert (scalar_loop);
+ condition_bb = gimple_bb (cond);
+ gimple_cond_set_condition_from_tree (cond, cond_expr);
+ update_stmt (cond);
+
+ if (cond_expr_stmt_list)
+ {
+ cond_exp_gsi = gsi_for_stmt (call);
+ gsi_insert_seq_before (&cond_exp_gsi, cond_expr_stmt_list,
+ GSI_SAME_STMT);
+ }
+
+ /* ??? if-conversion uses profile_probability::always () but
+ prob below is profile_probability::likely (). */
+ nloop = scalar_loop;
+ if (dump_enabled_p ())
+ dump_printf_loc (MSG_NOTE, vect_location,
+ "reusing %sloop version created by if conversion\n",
+ loop_to_version != loop ? "outer " : "");
}
else
- nloop = loop_version (loop, cond_expr, &condition_bb,
- prob, prob.invert (), prob, prob.invert (), true);
+ {
+ if (loop_to_version != loop
+ && dump_enabled_p ())
+ dump_printf_loc (MSG_NOTE, vect_location,
+ "applying loop versioning to outer loop %d\n",
+ loop_to_version->num);
+
+ initialize_original_copy_tables ();
+ nloop = loop_version (loop_to_version, cond_expr, &condition_bb,
+ prob, prob.invert (), prob, prob.invert (), true);
+ gcc_assert (nloop);
+ nloop = get_loop_copy (loop);
+
+ /* Kill off IFN_LOOP_VECTORIZED_CALL in the copy, nobody will
+ reap those otherwise; they also refer to the original
+ loops. */
+ struct loop *l = loop;
+ while (gimple *call = vect_loop_vectorized_call (l))
+ {
+ call = SSA_NAME_DEF_STMT (get_current_def (gimple_call_lhs (call)));
+ fold_loop_internal_call (call, boolean_false_node);
+ l = loop_outer (l);
+ }
+ free_original_copy_tables ();
+
+ if (cond_expr_stmt_list)
+ {
+ cond_exp_gsi = gsi_last_bb (condition_bb);
+ gsi_insert_seq_before (&cond_exp_gsi, cond_expr_stmt_list,
+ GSI_SAME_STMT);
+ }
+
+ /* Loop versioning violates an assumption we try to maintain during
+ vectorization - that the loop exit block has a single predecessor.
+ After versioning, the exit block of both loop versions is the same
+ basic block (i.e. it has two predecessors). Just in order to simplify
+ following transformations in the vectorizer, we fix this situation
+ here by adding a new (empty) block on the exit-edge of the loop,
+ with the proper loop-exit phis to maintain loop-closed-form.
+ If loop versioning wasn't done from loop, but scalar_loop instead,
+ merge_bb will have already just a single successor. */
+
+ merge_bb = single_exit (loop_to_version)->dest;
+ if (EDGE_COUNT (merge_bb->preds) >= 2)
+ {
+ gcc_assert (EDGE_COUNT (merge_bb->preds) >= 2);
+ new_exit_bb = split_edge (single_exit (loop_to_version));
+ new_exit_e = single_exit (loop_to_version);
+ e = EDGE_SUCC (new_exit_bb, 0);
+
+ for (gsi = gsi_start_phis (merge_bb); !gsi_end_p (gsi);
+ gsi_next (&gsi))
+ {
+ tree new_res;
+ orig_phi = gsi.phi ();
+ new_res = copy_ssa_name (PHI_RESULT (orig_phi));
+ new_phi = create_phi_node (new_res, new_exit_bb);
+ arg = PHI_ARG_DEF_FROM_EDGE (orig_phi, e);
+ add_phi_arg (new_phi, arg, new_exit_e,
+ gimple_phi_arg_location_from_edge (orig_phi, e));
+ adjust_phi_and_debug_stmts (orig_phi, e, PHI_RESULT (new_phi));
+ }
+ }
+
+ update_ssa (TODO_update_ssa);
+ }
if (version_niter)
{
@@ -3114,48 +3215,6 @@ vect_loop_versioning (loop_vec_info loop_vinfo,
"alignment\n");
}
- free_original_copy_tables ();
-
- /* Loop versioning violates an assumption we try to maintain during
- vectorization - that the loop exit block has a single predecessor.
- After versioning, the exit block of both loop versions is the same
- basic block (i.e. it has two predecessors). Just in order to simplify
- following transformations in the vectorizer, we fix this situation
- here by adding a new (empty) block on the exit-edge of the loop,
- with the proper loop-exit phis to maintain loop-closed-form.
- If loop versioning wasn't done from loop, but scalar_loop instead,
- merge_bb will have already just a single successor. */
-
- merge_bb = single_exit (loop)->dest;
- if (scalar_loop == NULL || EDGE_COUNT (merge_bb->preds) >= 2)
- {
- gcc_assert (EDGE_COUNT (merge_bb->preds) >= 2);
- new_exit_bb = split_edge (single_exit (loop));
- new_exit_e = single_exit (loop);
- e = EDGE_SUCC (new_exit_bb, 0);
-
- for (gsi = gsi_start_phis (merge_bb); !gsi_end_p (gsi); gsi_next (&gsi))
- {
- tree new_res;
- orig_phi = gsi.phi ();
- new_res = copy_ssa_name (PHI_RESULT (orig_phi));
- new_phi = create_phi_node (new_res, new_exit_bb);
- arg = PHI_ARG_DEF_FROM_EDGE (orig_phi, e);
- add_phi_arg (new_phi, arg, new_exit_e,
- gimple_phi_arg_location_from_edge (orig_phi, e));
- adjust_phi_and_debug_stmts (orig_phi, e, PHI_RESULT (new_phi));
- }
- }
-
- /* End loop-exit-fixes after versioning. */
-
- if (cond_expr_stmt_list)
- {
- cond_exp_gsi = gsi_last_bb (condition_bb);
- gsi_insert_seq_before (&cond_exp_gsi, cond_expr_stmt_list,
- GSI_SAME_STMT);
- }
- update_ssa (TODO_update_ssa);
return nloop;
}
diff --git a/gcc/tree-vect-loop.c b/gcc/tree-vect-loop.c
index 057a874..c46cd9d 100644
--- a/gcc/tree-vect-loop.c
+++ b/gcc/tree-vect-loop.c
@@ -730,9 +730,7 @@ vect_get_loop_niters (struct loop *loop, tree *assumptions,
if (!exit)
return cond;
- niter = chrec_dont_know;
may_be_zero = NULL_TREE;
- niter_assumptions = boolean_true_node;
if (!number_of_iterations_exit_assumptions (loop, exit, &niter_desc, NULL)
|| chrec_contains_undetermined (niter_desc.niter))
return cond;
@@ -819,10 +817,12 @@ _loop_vec_info::_loop_vec_info (struct loop *loop_in, vec_info_shared *shared)
max_vectorization_factor (0),
mask_skip_niters (NULL_TREE),
mask_compare_type (NULL_TREE),
+ simd_if_cond (NULL_TREE),
unaligned_dr (NULL),
peeling_for_alignment (0),
ptr_mask (0),
ivexpr_map (NULL),
+ scan_map (NULL),
slp_unrolling_factor (1),
single_scalar_iteration_cost (0),
vectorizable (false),
@@ -862,6 +862,26 @@ _loop_vec_info::_loop_vec_info (struct loop *loop_in, vec_info_shared *shared)
gimple *stmt = gsi_stmt (si);
gimple_set_uid (stmt, 0);
add_stmt (stmt);
+ /* If .GOMP_SIMD_LANE call for the current loop has 3 arguments, the
+ third argument is the #pragma omp simd if (x) condition, when 0,
+ loop shouldn't be vectorized, when non-zero constant, it should
+ be vectorized normally, otherwise versioned with vectorized loop
+ done if the condition is non-zero at runtime. */
+ if (loop_in->simduid
+ && is_gimple_call (stmt)
+ && gimple_call_internal_p (stmt)
+ && gimple_call_internal_fn (stmt) == IFN_GOMP_SIMD_LANE
+ && gimple_call_num_args (stmt) >= 3
+ && TREE_CODE (gimple_call_arg (stmt, 0)) == SSA_NAME
+ && (loop_in->simduid
+ == SSA_NAME_VAR (gimple_call_arg (stmt, 0))))
+ {
+ tree arg = gimple_call_arg (stmt, 2);
+ if (integer_zerop (arg) || TREE_CODE (arg) == SSA_NAME)
+ simd_if_cond = arg;
+ else
+ gcc_assert (integer_nonzerop (arg));
+ }
}
}
}
@@ -938,6 +958,7 @@ _loop_vec_info::~_loop_vec_info ()
release_vec_loop_masks (&masks);
delete ivexpr_map;
+ delete scan_map;
loop->aux = NULL;
}
@@ -1009,6 +1030,8 @@ vect_verify_full_masking (loop_vec_info loop_vinfo)
{
struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
unsigned int min_ni_width;
+ unsigned int max_nscalars_per_iter
+ = vect_get_max_nscalars_per_iter (loop_vinfo);
/* Use a normal loop if there are no statements that need masking.
This only happens in rare degenerate cases: it means that the loop
@@ -1027,7 +1050,7 @@ vect_verify_full_masking (loop_vec_info loop_vinfo)
max_ni = wi::smin (max_ni, max_back_edges + 1);
/* Account for rgroup masks, in which each bit is replicated N times. */
- max_ni *= vect_get_max_nscalars_per_iter (loop_vinfo);
+ max_ni *= max_nscalars_per_iter;
/* Work out how many bits we need to represent the limit. */
min_ni_width = wi::min_precision (max_ni, UNSIGNED);
@@ -1035,6 +1058,14 @@ vect_verify_full_masking (loop_vec_info loop_vinfo)
/* Find a scalar mode for which WHILE_ULT is supported. */
opt_scalar_int_mode cmp_mode_iter;
tree cmp_type = NULL_TREE;
+ tree iv_type = NULL_TREE;
+ widest_int iv_limit = vect_iv_limit_for_full_masking (loop_vinfo);
+ unsigned int iv_precision = UINT_MAX;
+
+ if (iv_limit != -1)
+ iv_precision = wi::min_precision (iv_limit * max_nscalars_per_iter,
+ UNSIGNED);
+
FOR_EACH_MODE_IN_CLASS (cmp_mode_iter, MODE_INT)
{
unsigned int cmp_bits = GET_MODE_BITSIZE (cmp_mode_iter.require ());
@@ -1046,10 +1077,32 @@ vect_verify_full_masking (loop_vec_info loop_vinfo)
&& can_produce_all_loop_masks_p (loop_vinfo, this_type))
{
/* Although we could stop as soon as we find a valid mode,
- it's often better to continue until we hit Pmode, since the
- operands to the WHILE are more likely to be reusable in
- address calculations. */
- cmp_type = this_type;
+ there are at least two reasons why that's not always the
+ best choice:
+
+ - An IV that's Pmode or wider is more likely to be reusable
+ in address calculations than an IV that's narrower than
+ Pmode.
+
+ - Doing the comparison in IV_PRECISION or wider allows
+ a natural 0-based IV, whereas using a narrower comparison
+ type requires mitigations against wrap-around.
+
+ Conversely, if the IV limit is variable, doing the comparison
+ in a wider type than the original type can introduce
+ unnecessary extensions, so picking the widest valid mode
+ is not always a good choice either.
+
+ Here we prefer the first IV type that's Pmode or wider,
+ and the first comparison type that's IV_PRECISION or wider.
+ (The comparison type must be no wider than the IV type,
+ to avoid extensions in the vector loop.)
+
+ ??? We might want to try continuing beyond Pmode for ILP32
+ targets if CMP_BITS < IV_PRECISION. */
+ iv_type = this_type;
+ if (!cmp_type || iv_precision > TYPE_PRECISION (cmp_type))
+ cmp_type = this_type;
if (cmp_bits >= GET_MODE_BITSIZE (Pmode))
break;
}
@@ -1060,6 +1113,7 @@ vect_verify_full_masking (loop_vec_info loop_vinfo)
return false;
LOOP_VINFO_MASK_COMPARE_TYPE (loop_vinfo) = cmp_type;
+ LOOP_VINFO_MASK_IV_TYPE (loop_vinfo) = iv_type;
return true;
}
@@ -1753,6 +1807,50 @@ vect_get_datarefs_in_loop (loop_p loop, basic_block *bbs,
return opt_result::success ();
}
+/* Look for SLP-only access groups and turn each individual access into its own
+ group. */
+static void
+vect_dissolve_slp_only_groups (loop_vec_info loop_vinfo)
+{
+ unsigned int i;
+ struct data_reference *dr;
+
+ DUMP_VECT_SCOPE ("vect_dissolve_slp_only_groups");
+
+ vec<data_reference_p> datarefs = loop_vinfo->shared->datarefs;
+ FOR_EACH_VEC_ELT (datarefs, i, dr)
+ {
+ gcc_assert (DR_REF (dr));
+ stmt_vec_info stmt_info = loop_vinfo->lookup_stmt (DR_STMT (dr));
+
+ /* Check if the load is a part of an interleaving chain. */
+ if (STMT_VINFO_GROUPED_ACCESS (stmt_info))
+ {
+ stmt_vec_info first_element = DR_GROUP_FIRST_ELEMENT (stmt_info);
+ unsigned int group_size = DR_GROUP_SIZE (first_element);
+
+ /* Check if SLP-only groups. */
+ if (!STMT_SLP_TYPE (stmt_info)
+ && STMT_VINFO_SLP_VECT_ONLY (first_element))
+ {
+ /* Dissolve the group. */
+ STMT_VINFO_SLP_VECT_ONLY (first_element) = false;
+
+ stmt_vec_info vinfo = first_element;
+ while (vinfo)
+ {
+ stmt_vec_info next = DR_GROUP_NEXT_ELEMENT (vinfo);
+ DR_GROUP_FIRST_ELEMENT (vinfo) = vinfo;
+ DR_GROUP_NEXT_ELEMENT (vinfo) = NULL;
+ DR_GROUP_SIZE (vinfo) = 1;
+ DR_GROUP_GAP (vinfo) = group_size - 1;
+ vinfo = next;
+ }
+ }
+ }
+ }
+}
+
/* Function vect_analyze_loop_2.
Apply a set of analyses on LOOP, and create a loop_vec_info struct
@@ -1769,6 +1867,11 @@ vect_analyze_loop_2 (loop_vec_info loop_vinfo, bool &fatal, unsigned *n_stmts)
/* The first group of checks is independent of the vector size. */
fatal = true;
+ if (LOOP_VINFO_SIMD_IF_COND (loop_vinfo)
+ && integer_zerop (LOOP_VINFO_SIMD_IF_COND (loop_vinfo)))
+ return opt_result::failure_at (vect_location,
+ "not vectorized: simd if(0)\n");
+
/* Find all data references in the loop (which correspond to vdefs/vuses)
and analyze their evolution in the loop. */
@@ -1798,7 +1901,7 @@ vect_analyze_loop_2 (loop_vec_info loop_vinfo, bool &fatal, unsigned *n_stmts)
/* Analyze the data references and also adjust the minimal
vectorization factor according to the loads and stores. */
- ok = vect_analyze_data_refs (loop_vinfo, &min_vf);
+ ok = vect_analyze_data_refs (loop_vinfo, &min_vf, &fatal);
if (!ok)
{
if (dump_enabled_p ())
@@ -1829,7 +1932,7 @@ vect_analyze_loop_2 (loop_vec_info loop_vinfo, bool &fatal, unsigned *n_stmts)
/* Data-flow analysis to detect stmts that do not need to be vectorized. */
- ok = vect_mark_stmts_to_be_vectorized (loop_vinfo);
+ ok = vect_mark_stmts_to_be_vectorized (loop_vinfo, &fatal);
if (!ok)
{
if (dump_enabled_p ())
@@ -1964,6 +2067,9 @@ start_over:
}
}
+ /* Dissolve SLP-only groups. */
+ vect_dissolve_slp_only_groups (loop_vinfo);
+
/* Scan all the remaining operations in the loop that are not subject
to SLP and make sure they are vectorizable. */
ok = vect_analyze_loop_operations (loop_vinfo);
@@ -2228,7 +2334,8 @@ vect_analyze_loop (struct loop *loop, loop_vec_info orig_loop_vinfo,
/* Autodetect first vector size we try. */
current_vector_size = 0;
- targetm.vectorize.autovectorize_vector_sizes (&vector_sizes);
+ targetm.vectorize.autovectorize_vector_sizes (&vector_sizes,
+ loop->simdlen != 0);
unsigned int next_size = 0;
DUMP_VECT_SCOPE ("analyze_loop_nest");
@@ -2247,6 +2354,8 @@ vect_analyze_loop (struct loop *loop, loop_vec_info orig_loop_vinfo,
unsigned n_stmts = 0;
poly_uint64 autodetected_vector_size = 0;
+ opt_loop_vec_info first_loop_vinfo = opt_loop_vec_info::success (NULL);
+ poly_uint64 first_vector_size = 0;
while (1)
{
/* Check the CFG characteristics of the loop (nesting, entry/exit). */
@@ -2257,6 +2366,7 @@ vect_analyze_loop (struct loop *loop, loop_vec_info orig_loop_vinfo,
if (dump_enabled_p ())
dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
"bad loop form.\n");
+ gcc_checking_assert (first_loop_vinfo == NULL);
return loop_vinfo;
}
@@ -2270,10 +2380,27 @@ vect_analyze_loop (struct loop *loop, loop_vec_info orig_loop_vinfo,
{
LOOP_VINFO_VECTORIZABLE_P (loop_vinfo) = 1;
- return loop_vinfo;
+ if (loop->simdlen
+ && maybe_ne (LOOP_VINFO_VECT_FACTOR (loop_vinfo),
+ (unsigned HOST_WIDE_INT) loop->simdlen))
+ {
+ if (first_loop_vinfo == NULL)
+ {
+ first_loop_vinfo = loop_vinfo;
+ first_vector_size = current_vector_size;
+ loop->aux = NULL;
+ }
+ else
+ delete loop_vinfo;
+ }
+ else
+ {
+ delete first_loop_vinfo;
+ return loop_vinfo;
+ }
}
-
- delete loop_vinfo;
+ else
+ delete loop_vinfo;
if (next_size == 0)
autodetected_vector_size = current_vector_size;
@@ -2282,10 +2409,31 @@ vect_analyze_loop (struct loop *loop, loop_vec_info orig_loop_vinfo,
&& known_eq (vector_sizes[next_size], autodetected_vector_size))
next_size += 1;
- if (fatal
- || next_size == vector_sizes.length ()
+ if (fatal)
+ {
+ gcc_checking_assert (first_loop_vinfo == NULL);
+ return opt_loop_vec_info::propagate_failure (res);
+ }
+
+ if (next_size == vector_sizes.length ()
|| known_eq (current_vector_size, 0U))
- return opt_loop_vec_info::propagate_failure (res);
+ {
+ if (first_loop_vinfo)
+ {
+ current_vector_size = first_vector_size;
+ loop->aux = (loop_vec_info) first_loop_vinfo;
+ if (dump_enabled_p ())
+ {
+ dump_printf_loc (MSG_NOTE, vect_location,
+ "***** Choosing vector size ");
+ dump_dec (MSG_NOTE, current_vector_size);
+ dump_printf (MSG_NOTE, "\n");
+ }
+ return first_loop_vinfo;
+ }
+ else
+ return opt_loop_vec_info::propagate_failure (res);
+ }
/* Try the next biggest vector size. */
current_vector_size = vector_sizes[next_size++];
@@ -3255,8 +3403,8 @@ vect_get_known_peeling_cost (loop_vec_info loop_vinfo, int peel_iters_prologue,
iterations are unknown, count a taken branch per peeled loop. */
retval = record_stmt_cost (prologue_cost_vec, 1, cond_branch_taken,
NULL, 0, vect_prologue);
- retval = record_stmt_cost (prologue_cost_vec, 1, cond_branch_taken,
- NULL, 0, vect_epilogue);
+ retval += record_stmt_cost (epilogue_cost_vec, 1, cond_branch_taken,
+ NULL, 0, vect_epilogue);
}
else
{
@@ -4963,7 +5111,6 @@ vect_create_epilog_for_reduction (vec<tree> vect_defs,
if (off != 0)
{
tree new_idx_val = idx_val;
- tree new_val = val;
if (off != v_size - el_size)
{
new_idx_val = make_ssa_name (idx_eltype);
@@ -4972,7 +5119,7 @@ vect_create_epilog_for_reduction (vec<tree> vect_defs,
old_idx_val);
gsi_insert_before (&exit_gsi, epilog_stmt, GSI_SAME_STMT);
}
- new_val = make_ssa_name (data_eltype);
+ tree new_val = make_ssa_name (data_eltype);
epilog_stmt = gimple_build_assign (new_val,
COND_EXPR,
build2 (GT_EXPR,
@@ -5153,14 +5300,13 @@ vect_create_epilog_for_reduction (vec<tree> vect_defs,
in a vector mode of smaller size and first reduce upper/lower
halves against each other. */
enum machine_mode mode1 = mode;
- tree vectype1 = vectype;
unsigned sz = tree_to_uhwi (TYPE_SIZE_UNIT (vectype));
unsigned sz1 = sz;
if (!slp_reduc
&& (mode1 = targetm.vectorize.split_reduction (mode)) != mode)
sz1 = GET_MODE_SIZE (mode1).to_constant ();
- vectype1 = get_vectype_for_scalar_type_and_size (scalar_type, sz1);
+ tree vectype1 = get_vectype_for_scalar_type_and_size (scalar_type, sz1);
reduce_with_shift = have_whole_vector_shift (mode1);
if (!VECTOR_MODE_P (mode1))
reduce_with_shift = false;
@@ -5281,7 +5427,6 @@ vect_create_epilog_for_reduction (vec<tree> vect_defs,
dump_printf_loc (MSG_NOTE, vect_location,
"Reduce using vector shifts\n");
- mode1 = TYPE_MODE (vectype1);
vec_dest = vect_create_destination_var (scalar_dest, vectype1);
for (elt_offset = nelements / 2;
elt_offset >= 1;
@@ -5766,6 +5911,30 @@ vect_expand_fold_left (gimple_stmt_iterator *gsi, tree scalar_dest,
return lhs;
}
+/* Get a masked internal function equivalent to REDUC_FN. VECTYPE_IN is the
+ type of the vector input. */
+
+static internal_fn
+get_masked_reduction_fn (internal_fn reduc_fn, tree vectype_in)
+{
+ internal_fn mask_reduc_fn;
+
+ switch (reduc_fn)
+ {
+ case IFN_FOLD_LEFT_PLUS:
+ mask_reduc_fn = IFN_MASK_FOLD_LEFT_PLUS;
+ break;
+
+ default:
+ return IFN_LAST;
+ }
+
+ if (direct_internal_fn_supported_p (mask_reduc_fn, vectype_in,
+ OPTIMIZE_FOR_SPEED))
+ return mask_reduc_fn;
+ return IFN_LAST;
+}
+
/* Perform an in-order reduction (FOLD_LEFT_REDUCTION). STMT_INFO is the
statement that sets the live-out value. REDUC_DEF_STMT is the phi
statement. CODE is the operation performed by STMT_INFO and OPS are
@@ -5788,6 +5957,7 @@ vectorize_fold_left_reduction (stmt_vec_info stmt_info,
struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
tree vectype_out = STMT_VINFO_VECTYPE (stmt_info);
stmt_vec_info new_stmt_info = NULL;
+ internal_fn mask_reduc_fn = get_masked_reduction_fn (reduc_fn, vectype_in);
int ncopies;
if (slp_node)
@@ -5864,16 +6034,21 @@ vectorize_fold_left_reduction (stmt_vec_info stmt_info,
def0 = negated;
}
- if (mask)
+ if (mask && mask_reduc_fn == IFN_LAST)
def0 = merge_with_identity (gsi, mask, vectype_out, def0,
vector_identity);
/* On the first iteration the input is simply the scalar phi
result, and for subsequent iterations it is the output of
the preceding operation. */
- if (reduc_fn != IFN_LAST)
+ if (reduc_fn != IFN_LAST || (mask && mask_reduc_fn != IFN_LAST))
{
- new_stmt = gimple_build_call_internal (reduc_fn, 2, reduc_var, def0);
+ if (mask && mask_reduc_fn != IFN_LAST)
+ new_stmt = gimple_build_call_internal (mask_reduc_fn, 3, reduc_var,
+ def0, mask);
+ else
+ new_stmt = gimple_build_call_internal (reduc_fn, 2, reduc_var,
+ def0);
/* For chained SLP reductions the output of the previous reduction
operation serves as the input of the next. For the final statement
the output cannot be a temporary - we reuse the original
@@ -8644,7 +8819,7 @@ vect_transform_loop (loop_vec_info loop_vinfo)
if (epilogue)
{
auto_vector_sizes vector_sizes;
- targetm.vectorize.autovectorize_vector_sizes (&vector_sizes);
+ targetm.vectorize.autovectorize_vector_sizes (&vector_sizes, false);
unsigned int next_size = 0;
/* Note LOOP_VINFO_NITERS_KNOWN_P and LOOP_VINFO_INT_NITERS work
@@ -8899,3 +9074,45 @@ optimize_mask_stores (struct loop *loop)
add_phi_arg (phi, gimple_vuse (last_store), e, UNKNOWN_LOCATION);
}
}
+
+/* Decide whether it is possible to use a zero-based induction variable
+ when vectorizing LOOP_VINFO with a fully-masked loop. If it is,
+ return the value that the induction variable must be able to hold
+ in order to ensure that the loop ends with an all-false mask.
+ Return -1 otherwise. */
+widest_int
+vect_iv_limit_for_full_masking (loop_vec_info loop_vinfo)
+{
+ tree niters_skip = LOOP_VINFO_MASK_SKIP_NITERS (loop_vinfo);
+ struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
+ unsigned HOST_WIDE_INT max_vf = vect_max_vf (loop_vinfo);
+
+ /* Calculate the value that the induction variable must be able
+ to hit in order to ensure that we end the loop with an all-false mask.
+ This involves adding the maximum number of inactive trailing scalar
+ iterations. */
+ widest_int iv_limit = -1;
+ if (max_loop_iterations (loop, &iv_limit))
+ {
+ if (niters_skip)
+ {
+ /* Add the maximum number of skipped iterations to the
+ maximum iteration count. */
+ if (TREE_CODE (niters_skip) == INTEGER_CST)
+ iv_limit += wi::to_widest (niters_skip);
+ else
+ iv_limit += max_vf - 1;
+ }
+ else if (LOOP_VINFO_PEELING_FOR_ALIGNMENT (loop_vinfo))
+ /* Make a conservatively-correct assumption. */
+ iv_limit += max_vf - 1;
+
+ /* IV_LIMIT is the maximum number of latch iterations, which is also
+ the maximum in-range IV value. Round this value down to the previous
+ vector alignment boundary and then add an extra full iteration. */
+ poly_uint64 vf = LOOP_VINFO_VECT_FACTOR (loop_vinfo);
+ iv_limit = (iv_limit & -(int) known_alignment (vf)) + max_vf;
+ }
+ return iv_limit;
+}
+
diff --git a/gcc/tree-vect-slp.c b/gcc/tree-vect-slp.c
index 2a1e5b8..1aaf10e 100644
--- a/gcc/tree-vect-slp.c
+++ b/gcc/tree-vect-slp.c
@@ -325,6 +325,14 @@ vect_get_and_check_slp_defs (vec_info *vinfo, unsigned char *swap,
{
internal_fn ifn = gimple_call_internal_fn (stmt);
commutative_op = first_commutative_argument (ifn);
+
+ /* Masked load, only look at mask. */
+ if (ifn == IFN_MASK_LOAD)
+ {
+ number_of_oprnds = 1;
+ /* Mask operand index. */
+ first_op_idx = 5;
+ }
}
}
else if (gassign *stmt = dyn_cast <gassign *> (stmt_info->stmt))
@@ -333,7 +341,7 @@ vect_get_and_check_slp_defs (vec_info *vinfo, unsigned char *swap,
number_of_oprnds = gimple_num_ops (stmt) - 1;
/* Swap can only be done for cond_expr if asked to, otherwise we
could result in different comparison code to the first stmt. */
- if (gimple_assign_rhs_code (stmt) == COND_EXPR
+ if (code == COND_EXPR
&& COMPARISON_CLASS_P (gimple_assign_rhs1 (stmt)))
{
first_op_cond = true;
@@ -364,6 +372,8 @@ again:
}
else
oprnd = gimple_op (stmt_info->stmt, first_op_idx + (swapped ? !i : i));
+ if (TREE_CODE (oprnd) == VIEW_CONVERT_EXPR)
+ oprnd = TREE_OPERAND (oprnd, 0);
oprnd_info = (*oprnds_info)[i];
@@ -624,7 +634,7 @@ vect_two_operations_perm_ok_p (vec<stmt_vec_info> stmts,
is false then this indicates the comparison could not be
carried out or the stmts will never be vectorized by SLP.
- Note COND_EXPR is possibly ismorphic to another one after swapping its
+ Note COND_EXPR is possibly isomorphic to another one after swapping its
operands. Set SWAP[i] to 1 if stmt I is COND_EXPR and isomorphic to
the first stmt by swapping the two operands of comparison; set SWAP[i]
to 2 if stmt I is isormorphic to the first stmt by inverting the code
@@ -651,6 +661,7 @@ vect_build_slp_tree_1 (unsigned char *swap,
machine_mode optab_op2_mode;
machine_mode vec_mode;
stmt_vec_info first_load = NULL, prev_first_load = NULL;
+ bool load_p = false;
/* For every stmt in NODE find its def stmt/s. */
stmt_vec_info stmt_info;
@@ -704,13 +715,16 @@ vect_build_slp_tree_1 (unsigned char *swap,
if (gcall *call_stmt = dyn_cast <gcall *> (stmt))
{
rhs_code = CALL_EXPR;
- if ((gimple_call_internal_p (call_stmt)
- && (!vectorizable_internal_fn_p
- (gimple_call_internal_fn (call_stmt))))
- || gimple_call_tail_p (call_stmt)
- || gimple_call_noreturn_p (call_stmt)
- || !gimple_call_nothrow_p (call_stmt)
- || gimple_call_chain (call_stmt))
+
+ if (gimple_call_internal_p (stmt, IFN_MASK_LOAD))
+ load_p = true;
+ else if ((gimple_call_internal_p (call_stmt)
+ && (!vectorizable_internal_fn_p
+ (gimple_call_internal_fn (call_stmt))))
+ || gimple_call_tail_p (call_stmt)
+ || gimple_call_noreturn_p (call_stmt)
+ || !gimple_call_nothrow_p (call_stmt)
+ || gimple_call_chain (call_stmt))
{
if (dump_enabled_p ())
dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
@@ -722,7 +736,10 @@ vect_build_slp_tree_1 (unsigned char *swap,
}
}
else
- rhs_code = gimple_assign_rhs_code (stmt);
+ {
+ rhs_code = gimple_assign_rhs_code (stmt);
+ load_p = TREE_CODE_CLASS (rhs_code) == tcc_reference;
+ }
/* Check the operation. */
if (i == 0)
@@ -889,7 +906,7 @@ vect_build_slp_tree_1 (unsigned char *swap,
} /* Grouped access. */
else
{
- if (TREE_CODE_CLASS (rhs_code) == tcc_reference)
+ if (load_p)
{
/* Not grouped load. */
if (dump_enabled_p ())
@@ -907,6 +924,7 @@ vect_build_slp_tree_1 (unsigned char *swap,
&& TREE_CODE_CLASS (rhs_code) != tcc_unary
&& TREE_CODE_CLASS (rhs_code) != tcc_expression
&& TREE_CODE_CLASS (rhs_code) != tcc_comparison
+ && rhs_code != VIEW_CONVERT_EXPR
&& rhs_code != CALL_EXPR)
{
if (dump_enabled_p ())
@@ -1143,14 +1161,23 @@ vect_build_slp_tree_2 (vec_info *vinfo,
&this_max_nunits, matches, &two_operators))
return NULL;
- /* If the SLP node is a load, terminate the recursion. */
+ /* If the SLP node is a load, terminate the recursion unless masked. */
if (STMT_VINFO_GROUPED_ACCESS (stmt_info)
&& DR_IS_READ (STMT_VINFO_DATA_REF (stmt_info)))
{
- *max_nunits = this_max_nunits;
- (*tree_size)++;
- node = vect_create_new_slp_node (stmts);
- return node;
+ if (gcall *stmt = dyn_cast <gcall *> (stmt_info->stmt))
+ {
+ /* Masked load. */
+ gcc_assert (gimple_call_internal_p (stmt, IFN_MASK_LOAD));
+ nops = 1;
+ }
+ else
+ {
+ *max_nunits = this_max_nunits;
+ (*tree_size)++;
+ node = vect_create_new_slp_node (stmts);
+ return node;
+ }
}
/* Get at the operands, verifying they are compatible. */
@@ -2834,7 +2861,7 @@ vect_slp_analyze_bb_1 (gimple_stmt_iterator region_begin,
/* Analyze the data references. */
- if (!vect_analyze_data_refs (bb_vinfo, &min_vf))
+ if (!vect_analyze_data_refs (bb_vinfo, &min_vf, NULL))
{
if (dump_enabled_p ())
dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
@@ -2980,7 +3007,7 @@ vect_slp_bb (basic_block bb)
/* Autodetect first vector size we try. */
current_vector_size = 0;
- targetm.vectorize.autovectorize_vector_sizes (&vector_sizes);
+ targetm.vectorize.autovectorize_vector_sizes (&vector_sizes, false);
unsigned int next_size = 0;
gsi = gsi_start_bb (bb);
diff --git a/gcc/tree-vect-stmts.c b/gcc/tree-vect-stmts.c
index ced4264..313b1b9 100644
--- a/gcc/tree-vect-stmts.c
+++ b/gcc/tree-vect-stmts.c
@@ -54,6 +54,7 @@ along with GCC; see the file COPYING3. If not see
#include "tree-ssa-loop-niter.h"
#include "gimple-fold.h"
#include "regs.h"
+#include "attribs.h"
/* For lang_hooks.types.type_for_mode. */
#include "langhooks.h"
@@ -607,7 +608,7 @@ process_use (stmt_vec_info stmt_vinfo, tree use, loop_vec_info loop_vinfo,
This pass detects such stmts. */
opt_result
-vect_mark_stmts_to_be_vectorized (loop_vec_info loop_vinfo)
+vect_mark_stmts_to_be_vectorized (loop_vec_info loop_vinfo, bool *fatal)
{
struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
basic_block *bbs = LOOP_VINFO_BBS (loop_vinfo);
@@ -777,7 +778,11 @@ vect_mark_stmts_to_be_vectorized (loop_vec_info loop_vinfo)
= process_use (stmt_vinfo, gs_info.offset, loop_vinfo, relevant,
&worklist, true);
if (!res)
- return res;
+ {
+ if (fatal)
+ *fatal = false;
+ return res;
+ }
}
} /* while worklist */
@@ -1480,20 +1485,19 @@ vect_init_vector (stmt_vec_info stmt_info, tree val, tree type,
val = new_temp;
}
}
- else if (CONSTANT_CLASS_P (val))
- val = fold_convert (TREE_TYPE (type), val);
else
{
- new_temp = make_ssa_name (TREE_TYPE (type));
+ gimple_seq stmts = NULL;
if (! INTEGRAL_TYPE_P (TREE_TYPE (val)))
- init_stmt = gimple_build_assign (new_temp,
- fold_build1 (VIEW_CONVERT_EXPR,
- TREE_TYPE (type),
- val));
+ val = gimple_build (&stmts, VIEW_CONVERT_EXPR,
+ TREE_TYPE (type), val);
else
- init_stmt = gimple_build_assign (new_temp, NOP_EXPR, val);
- vect_init_vector_1 (stmt_info, init_stmt, gsi);
- val = new_temp;
+ /* ??? Condition vectorization expects us to do
+ promotion of invariant/external defs. */
+ val = gimple_convert (&stmts, TREE_TYPE (type), val);
+ for (gimple_stmt_iterator gsi2 = gsi_start (stmts);
+ !gsi_end_p (gsi2); gsi_next (&gsi2))
+ vect_init_vector_1 (stmt_info, gsi_stmt (gsi2), gsi);
}
}
val = build_vector_from_val (type, val);
@@ -2592,7 +2596,7 @@ vect_check_load_store_mask (stmt_vec_info stmt_info, tree mask,
{
if (dump_enabled_p ())
dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
- "vector mask type %T",
+ "vector mask type %T"
" does not match vector data type %T.\n",
mask_vectype, vectype);
@@ -3257,7 +3261,7 @@ vectorizable_call (stmt_vec_info stmt_info, gimple_stmt_iterator *gsi,
if (nargs == 0 || nargs > 4)
return false;
- /* Ignore the argument of IFN_GOMP_SIMD_LANE, it is magic. */
+ /* Ignore the arguments of IFN_GOMP_SIMD_LANE, they are magic. */
combined_fn cfn = gimple_call_combined_fn (stmt);
if (cfn == CFN_GOMP_SIMD_LANE)
{
@@ -3483,8 +3487,7 @@ vectorizable_call (stmt_vec_info stmt_info, gimple_stmt_iterator *gsi,
= gimple_build_call_internal_vec (ifn, vargs);
gimple_call_set_lhs (call, half_res);
gimple_call_set_nothrow (call, true);
- new_stmt_info
- = vect_finish_stmt_generation (stmt_info, call, gsi);
+ vect_finish_stmt_generation (stmt_info, call, gsi);
if ((i & 1) == 0)
{
prev_res = half_res;
@@ -3583,8 +3586,7 @@ vectorizable_call (stmt_vec_info stmt_info, gimple_stmt_iterator *gsi,
gcall *call = gimple_build_call_internal_vec (ifn, vargs);
gimple_call_set_lhs (call, half_res);
gimple_call_set_nothrow (call, true);
- new_stmt_info
- = vect_finish_stmt_generation (stmt_info, call, gsi);
+ vect_finish_stmt_generation (stmt_info, call, gsi);
if ((j & 1) == 0)
{
prev_res = half_res;
@@ -6320,6 +6322,804 @@ get_group_alias_ptr_type (stmt_vec_info first_stmt_info)
}
+/* Function scan_operand_equal_p.
+
+ Helper function for check_scan_store. Compare two references
+ with .GOMP_SIMD_LANE bases. */
+
+static bool
+scan_operand_equal_p (tree ref1, tree ref2)
+{
+ machine_mode mode1, mode2;
+ poly_int64 bitsize1, bitsize2, bitpos1, bitpos2;
+ tree offset1, offset2;
+ int unsignedp1, unsignedp2, reversep1, reversep2;
+ int volatilep1 = 0, volatilep2 = 0;
+ tree base1 = get_inner_reference (ref1, &bitsize1, &bitpos1, &offset1,
+ &mode1, &unsignedp1, &reversep1,
+ &volatilep1);
+ tree base2 = get_inner_reference (ref2, &bitsize2, &bitpos2, &offset2,
+ &mode2, &unsignedp2, &reversep2,
+ &volatilep2);
+ if (reversep1 || reversep2 || volatilep1 || volatilep2)
+ return false;
+ if (!operand_equal_p (base1, base2, 0))
+ return false;
+ if (maybe_ne (bitpos1, 0) || maybe_ne (bitpos2, 0))
+ return false;
+ if (maybe_ne (bitsize1, bitsize2))
+ return false;
+ if (offset1 != offset2
+ && (!offset1
+ || !offset2
+ || !operand_equal_p (offset1, offset2, 0)))
+ return false;
+ return true;
+}
+
+
+enum scan_store_kind {
+ /* Normal permutation. */
+ scan_store_kind_perm,
+
+ /* Whole vector left shift permutation with zero init. */
+ scan_store_kind_lshift_zero,
+
+ /* Whole vector left shift permutation and VEC_COND_EXPR. */
+ scan_store_kind_lshift_cond
+};
+
+/* Function check_scan_store.
+
+ Verify if we can perform the needed permutations or whole vector shifts.
+ Return -1 on failure, otherwise exact log2 of vectype's nunits.
+ USE_WHOLE_VECTOR is a vector of enum scan_store_kind which operation
+ to do at each step. */
+
+static int
+scan_store_can_perm_p (tree vectype, tree init,
+ vec<enum scan_store_kind> *use_whole_vector = NULL)
+{
+ enum machine_mode vec_mode = TYPE_MODE (vectype);
+ unsigned HOST_WIDE_INT nunits;
+ if (!TYPE_VECTOR_SUBPARTS (vectype).is_constant (&nunits))
+ return -1;
+ int units_log2 = exact_log2 (nunits);
+ if (units_log2 <= 0)
+ return -1;
+
+ int i;
+ enum scan_store_kind whole_vector_shift_kind = scan_store_kind_perm;
+ for (i = 0; i <= units_log2; ++i)
+ {
+ unsigned HOST_WIDE_INT j, k;
+ enum scan_store_kind kind = scan_store_kind_perm;
+ vec_perm_builder sel (nunits, nunits, 1);
+ sel.quick_grow (nunits);
+ if (i == units_log2)
+ {
+ for (j = 0; j < nunits; ++j)
+ sel[j] = nunits - 1;
+ }
+ else
+ {
+ for (j = 0; j < (HOST_WIDE_INT_1U << i); ++j)
+ sel[j] = j;
+ for (k = 0; j < nunits; ++j, ++k)
+ sel[j] = nunits + k;
+ }
+ vec_perm_indices indices (sel, i == units_log2 ? 1 : 2, nunits);
+ if (!can_vec_perm_const_p (vec_mode, indices))
+ {
+ if (i == units_log2)
+ return -1;
+
+ if (whole_vector_shift_kind == scan_store_kind_perm)
+ {
+ if (optab_handler (vec_shl_optab, vec_mode) == CODE_FOR_nothing)
+ return -1;
+ whole_vector_shift_kind = scan_store_kind_lshift_zero;
+ /* Whole vector shifts shift in zeros, so if init is all zero
+ constant, there is no need to do anything further. */
+ if ((TREE_CODE (init) != INTEGER_CST
+ && TREE_CODE (init) != REAL_CST)
+ || !initializer_zerop (init))
+ {
+ tree masktype = build_same_sized_truth_vector_type (vectype);
+ if (!expand_vec_cond_expr_p (vectype, masktype, VECTOR_CST))
+ return -1;
+ whole_vector_shift_kind = scan_store_kind_lshift_cond;
+ }
+ }
+ kind = whole_vector_shift_kind;
+ }
+ if (use_whole_vector)
+ {
+ if (kind != scan_store_kind_perm && use_whole_vector->is_empty ())
+ use_whole_vector->safe_grow_cleared (i);
+ if (kind != scan_store_kind_perm || !use_whole_vector->is_empty ())
+ use_whole_vector->safe_push (kind);
+ }
+ }
+
+ return units_log2;
+}
+
+
+/* Function check_scan_store.
+
+ Check magic stores for #pragma omp scan {in,ex}clusive reductions. */
+
+static bool
+check_scan_store (stmt_vec_info stmt_info, tree vectype,
+ enum vect_def_type rhs_dt, bool slp, tree mask,
+ vect_memory_access_type memory_access_type)
+{
+ loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_info);
+ dr_vec_info *dr_info = STMT_VINFO_DR_INFO (stmt_info);
+ tree ref_type;
+
+ gcc_assert (STMT_VINFO_SIMD_LANE_ACCESS_P (stmt_info) > 1);
+ if (slp
+ || mask
+ || memory_access_type != VMAT_CONTIGUOUS
+ || TREE_CODE (DR_BASE_ADDRESS (dr_info->dr)) != ADDR_EXPR
+ || !VAR_P (TREE_OPERAND (DR_BASE_ADDRESS (dr_info->dr), 0))
+ || loop_vinfo == NULL
+ || LOOP_VINFO_FULLY_MASKED_P (loop_vinfo)
+ || STMT_VINFO_GROUPED_ACCESS (stmt_info)
+ || !integer_zerop (DR_OFFSET (dr_info->dr))
+ || !integer_zerop (DR_INIT (dr_info->dr))
+ || !(ref_type = reference_alias_ptr_type (DR_REF (dr_info->dr)))
+ || !alias_sets_conflict_p (get_alias_set (vectype),
+ get_alias_set (TREE_TYPE (ref_type))))
+ {
+ if (dump_enabled_p ())
+ dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
+ "unsupported OpenMP scan store.\n");
+ return false;
+ }
+
+ /* We need to pattern match code built by OpenMP lowering and simplified
+ by following optimizations into something we can handle.
+ #pragma omp simd reduction(inscan,+:r)
+ for (...)
+ {
+ r += something ();
+ #pragma omp scan inclusive (r)
+ use (r);
+ }
+ shall have body with:
+ // Initialization for input phase, store the reduction initializer:
+ _20 = .GOMP_SIMD_LANE (simduid.3_14(D), 0);
+ _21 = .GOMP_SIMD_LANE (simduid.3_14(D), 1);
+ D.2042[_21] = 0;
+ // Actual input phase:
+ ...
+ r.0_5 = D.2042[_20];
+ _6 = _4 + r.0_5;
+ D.2042[_20] = _6;
+ // Initialization for scan phase:
+ _25 = .GOMP_SIMD_LANE (simduid.3_14(D), 2);
+ _26 = D.2043[_25];
+ _27 = D.2042[_25];
+ _28 = _26 + _27;
+ D.2043[_25] = _28;
+ D.2042[_25] = _28;
+ // Actual scan phase:
+ ...
+ r.1_8 = D.2042[_20];
+ ...
+ The "omp simd array" variable D.2042 holds the privatized copy used
+ inside of the loop and D.2043 is another one that holds copies of
+ the current original list item. The separate GOMP_SIMD_LANE ifn
+ kinds are there in order to allow optimizing the initializer store
+ and combiner sequence, e.g. if it is originally some C++ish user
+ defined reduction, but allow the vectorizer to pattern recognize it
+ and turn into the appropriate vectorized scan.
+
+ For exclusive scan, this is slightly different:
+ #pragma omp simd reduction(inscan,+:r)
+ for (...)
+ {
+ use (r);
+ #pragma omp scan exclusive (r)
+ r += something ();
+ }
+ shall have body with:
+ // Initialization for input phase, store the reduction initializer:
+ _20 = .GOMP_SIMD_LANE (simduid.3_14(D), 0);
+ _21 = .GOMP_SIMD_LANE (simduid.3_14(D), 1);
+ D.2042[_21] = 0;
+ // Actual input phase:
+ ...
+ r.0_5 = D.2042[_20];
+ _6 = _4 + r.0_5;
+ D.2042[_20] = _6;
+ // Initialization for scan phase:
+ _25 = .GOMP_SIMD_LANE (simduid.3_14(D), 3);
+ _26 = D.2043[_25];
+ D.2044[_25] = _26;
+ _27 = D.2042[_25];
+ _28 = _26 + _27;
+ D.2043[_25] = _28;
+ // Actual scan phase:
+ ...
+ r.1_8 = D.2044[_20];
+ ... */
+
+ if (STMT_VINFO_SIMD_LANE_ACCESS_P (stmt_info) == 2)
+ {
+ /* Match the D.2042[_21] = 0; store above. Just require that
+ it is a constant or external definition store. */
+ if (rhs_dt != vect_constant_def && rhs_dt != vect_external_def)
+ {
+ fail_init:
+ if (dump_enabled_p ())
+ dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
+ "unsupported OpenMP scan initializer store.\n");
+ return false;
+ }
+
+ if (! loop_vinfo->scan_map)
+ loop_vinfo->scan_map = new hash_map<tree, tree>;
+ tree var = TREE_OPERAND (DR_BASE_ADDRESS (dr_info->dr), 0);
+ tree &cached = loop_vinfo->scan_map->get_or_insert (var);
+ if (cached)
+ goto fail_init;
+ cached = gimple_assign_rhs1 (STMT_VINFO_STMT (stmt_info));
+
+ /* These stores can be vectorized normally. */
+ return true;
+ }
+
+ if (rhs_dt != vect_internal_def)
+ {
+ fail:
+ if (dump_enabled_p ())
+ dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
+ "unsupported OpenMP scan combiner pattern.\n");
+ return false;
+ }
+
+ gimple *stmt = STMT_VINFO_STMT (stmt_info);
+ tree rhs = gimple_assign_rhs1 (stmt);
+ if (TREE_CODE (rhs) != SSA_NAME)
+ goto fail;
+
+ gimple *other_store_stmt = NULL;
+ tree var = TREE_OPERAND (DR_BASE_ADDRESS (dr_info->dr), 0);
+ bool inscan_var_store
+ = lookup_attribute ("omp simd inscan", DECL_ATTRIBUTES (var)) != NULL;
+
+ if (STMT_VINFO_SIMD_LANE_ACCESS_P (stmt_info) == 4)
+ {
+ if (!inscan_var_store)
+ {
+ use_operand_p use_p;
+ imm_use_iterator iter;
+ FOR_EACH_IMM_USE_FAST (use_p, iter, rhs)
+ {
+ gimple *use_stmt = USE_STMT (use_p);
+ if (use_stmt == stmt || is_gimple_debug (use_stmt))
+ continue;
+ if (gimple_bb (use_stmt) != gimple_bb (stmt)
+ || !is_gimple_assign (use_stmt)
+ || gimple_assign_rhs_class (use_stmt) != GIMPLE_BINARY_RHS
+ || other_store_stmt
+ || TREE_CODE (gimple_assign_lhs (use_stmt)) != SSA_NAME)
+ goto fail;
+ other_store_stmt = use_stmt;
+ }
+ if (other_store_stmt == NULL)
+ goto fail;
+ rhs = gimple_assign_lhs (other_store_stmt);
+ if (!single_imm_use (rhs, &use_p, &other_store_stmt))
+ goto fail;
+ }
+ }
+ else if (STMT_VINFO_SIMD_LANE_ACCESS_P (stmt_info) == 3)
+ {
+ use_operand_p use_p;
+ imm_use_iterator iter;
+ FOR_EACH_IMM_USE_FAST (use_p, iter, rhs)
+ {
+ gimple *use_stmt = USE_STMT (use_p);
+ if (use_stmt == stmt || is_gimple_debug (use_stmt))
+ continue;
+ if (other_store_stmt)
+ goto fail;
+ other_store_stmt = use_stmt;
+ }
+ }
+ else
+ goto fail;
+
+ gimple *def_stmt = SSA_NAME_DEF_STMT (rhs);
+ if (gimple_bb (def_stmt) != gimple_bb (stmt)
+ || !is_gimple_assign (def_stmt)
+ || gimple_assign_rhs_class (def_stmt) != GIMPLE_BINARY_RHS)
+ goto fail;
+
+ enum tree_code code = gimple_assign_rhs_code (def_stmt);
+ /* For pointer addition, we should use the normal plus for the vector
+ operation. */
+ switch (code)
+ {
+ case POINTER_PLUS_EXPR:
+ code = PLUS_EXPR;
+ break;
+ case MULT_HIGHPART_EXPR:
+ goto fail;
+ default:
+ break;
+ }
+ if (TREE_CODE_LENGTH (code) != binary_op || !commutative_tree_code (code))
+ goto fail;
+
+ tree rhs1 = gimple_assign_rhs1 (def_stmt);
+ tree rhs2 = gimple_assign_rhs2 (def_stmt);
+ if (TREE_CODE (rhs1) != SSA_NAME || TREE_CODE (rhs2) != SSA_NAME)
+ goto fail;
+
+ gimple *load1_stmt = SSA_NAME_DEF_STMT (rhs1);
+ gimple *load2_stmt = SSA_NAME_DEF_STMT (rhs2);
+ if (gimple_bb (load1_stmt) != gimple_bb (stmt)
+ || !gimple_assign_load_p (load1_stmt)
+ || gimple_bb (load2_stmt) != gimple_bb (stmt)
+ || !gimple_assign_load_p (load2_stmt))
+ goto fail;
+
+ stmt_vec_info load1_stmt_info = loop_vinfo->lookup_stmt (load1_stmt);
+ stmt_vec_info load2_stmt_info = loop_vinfo->lookup_stmt (load2_stmt);
+ if (load1_stmt_info == NULL
+ || load2_stmt_info == NULL
+ || (STMT_VINFO_SIMD_LANE_ACCESS_P (load1_stmt_info)
+ != STMT_VINFO_SIMD_LANE_ACCESS_P (stmt_info))
+ || (STMT_VINFO_SIMD_LANE_ACCESS_P (load2_stmt_info)
+ != STMT_VINFO_SIMD_LANE_ACCESS_P (stmt_info)))
+ goto fail;
+
+ if (STMT_VINFO_SIMD_LANE_ACCESS_P (stmt_info) == 4 && inscan_var_store)
+ {
+ dr_vec_info *load1_dr_info = STMT_VINFO_DR_INFO (load1_stmt_info);
+ if (TREE_CODE (DR_BASE_ADDRESS (load1_dr_info->dr)) != ADDR_EXPR
+ || !VAR_P (TREE_OPERAND (DR_BASE_ADDRESS (load1_dr_info->dr), 0)))
+ goto fail;
+ tree var1 = TREE_OPERAND (DR_BASE_ADDRESS (load1_dr_info->dr), 0);
+ tree lrhs;
+ if (lookup_attribute ("omp simd inscan", DECL_ATTRIBUTES (var1)))
+ lrhs = rhs1;
+ else
+ lrhs = rhs2;
+ use_operand_p use_p;
+ imm_use_iterator iter;
+ FOR_EACH_IMM_USE_FAST (use_p, iter, lrhs)
+ {
+ gimple *use_stmt = USE_STMT (use_p);
+ if (use_stmt == def_stmt || is_gimple_debug (use_stmt))
+ continue;
+ if (other_store_stmt)
+ goto fail;
+ other_store_stmt = use_stmt;
+ }
+ }
+
+ if (other_store_stmt == NULL)
+ goto fail;
+ if (gimple_bb (other_store_stmt) != gimple_bb (stmt)
+ || !gimple_store_p (other_store_stmt))
+ goto fail;
+
+ stmt_vec_info other_store_stmt_info
+ = loop_vinfo->lookup_stmt (other_store_stmt);
+ if (other_store_stmt_info == NULL
+ || (STMT_VINFO_SIMD_LANE_ACCESS_P (other_store_stmt_info)
+ != STMT_VINFO_SIMD_LANE_ACCESS_P (stmt_info)))
+ goto fail;
+
+ gimple *stmt1 = stmt;
+ gimple *stmt2 = other_store_stmt;
+ if (STMT_VINFO_SIMD_LANE_ACCESS_P (stmt_info) == 4 && !inscan_var_store)
+ std::swap (stmt1, stmt2);
+ if (scan_operand_equal_p (gimple_assign_lhs (stmt1),
+ gimple_assign_rhs1 (load2_stmt)))
+ {
+ std::swap (rhs1, rhs2);
+ std::swap (load1_stmt, load2_stmt);
+ std::swap (load1_stmt_info, load2_stmt_info);
+ }
+ if (!scan_operand_equal_p (gimple_assign_lhs (stmt1),
+ gimple_assign_rhs1 (load1_stmt)))
+ goto fail;
+
+ tree var3 = NULL_TREE;
+ if (STMT_VINFO_SIMD_LANE_ACCESS_P (stmt_info) == 3
+ && !scan_operand_equal_p (gimple_assign_lhs (stmt2),
+ gimple_assign_rhs1 (load2_stmt)))
+ goto fail;
+ else if (STMT_VINFO_SIMD_LANE_ACCESS_P (stmt_info) == 4)
+ {
+ dr_vec_info *load2_dr_info = STMT_VINFO_DR_INFO (load2_stmt_info);
+ if (TREE_CODE (DR_BASE_ADDRESS (load2_dr_info->dr)) != ADDR_EXPR
+ || !VAR_P (TREE_OPERAND (DR_BASE_ADDRESS (load2_dr_info->dr), 0)))
+ goto fail;
+ var3 = TREE_OPERAND (DR_BASE_ADDRESS (load2_dr_info->dr), 0);
+ if (!lookup_attribute ("omp simd array", DECL_ATTRIBUTES (var3))
+ || lookup_attribute ("omp simd inscan", DECL_ATTRIBUTES (var3))
+ || lookup_attribute ("omp simd inscan exclusive",
+ DECL_ATTRIBUTES (var3)))
+ goto fail;
+ }
+
+ dr_vec_info *other_dr_info = STMT_VINFO_DR_INFO (other_store_stmt_info);
+ if (TREE_CODE (DR_BASE_ADDRESS (other_dr_info->dr)) != ADDR_EXPR
+ || !VAR_P (TREE_OPERAND (DR_BASE_ADDRESS (other_dr_info->dr), 0)))
+ goto fail;
+
+ tree var1 = TREE_OPERAND (DR_BASE_ADDRESS (dr_info->dr), 0);
+ tree var2 = TREE_OPERAND (DR_BASE_ADDRESS (other_dr_info->dr), 0);
+ if (!lookup_attribute ("omp simd array", DECL_ATTRIBUTES (var1))
+ || !lookup_attribute ("omp simd array", DECL_ATTRIBUTES (var2))
+ || (!lookup_attribute ("omp simd inscan", DECL_ATTRIBUTES (var1)))
+ == (!lookup_attribute ("omp simd inscan", DECL_ATTRIBUTES (var2))))
+ goto fail;
+
+ if (lookup_attribute ("omp simd inscan", DECL_ATTRIBUTES (var1)))
+ std::swap (var1, var2);
+
+ if (STMT_VINFO_SIMD_LANE_ACCESS_P (stmt_info) == 4)
+ {
+ if (!lookup_attribute ("omp simd inscan exclusive",
+ DECL_ATTRIBUTES (var1)))
+ goto fail;
+ var1 = var3;
+ }
+
+ if (loop_vinfo->scan_map == NULL)
+ goto fail;
+ tree *init = loop_vinfo->scan_map->get (var1);
+ if (init == NULL)
+ goto fail;
+
+ /* The IL is as expected, now check if we can actually vectorize it.
+ Inclusive scan:
+ _26 = D.2043[_25];
+ _27 = D.2042[_25];
+ _28 = _26 + _27;
+ D.2043[_25] = _28;
+ D.2042[_25] = _28;
+ should be vectorized as (where _40 is the vectorized rhs
+ from the D.2042[_21] = 0; store):
+ _30 = MEM <vector(8) int> [(int *)&D.2043];
+ _31 = MEM <vector(8) int> [(int *)&D.2042];
+ _32 = VEC_PERM_EXPR <_40, _31, { 0, 8, 9, 10, 11, 12, 13, 14 }>;
+ _33 = _31 + _32;
+ // _33 = { _31[0], _31[0]+_31[1], _31[1]+_31[2], ..., _31[6]+_31[7] };
+ _34 = VEC_PERM_EXPR <_40, _33, { 0, 1, 8, 9, 10, 11, 12, 13 }>;
+ _35 = _33 + _34;
+ // _35 = { _31[0], _31[0]+_31[1], _31[0]+.._31[2], _31[0]+.._31[3],
+ // _31[1]+.._31[4], ... _31[4]+.._31[7] };
+ _36 = VEC_PERM_EXPR <_40, _35, { 0, 1, 2, 3, 8, 9, 10, 11 }>;
+ _37 = _35 + _36;
+ // _37 = { _31[0], _31[0]+_31[1], _31[0]+.._31[2], _31[0]+.._31[3],
+ // _31[0]+.._31[4], ... _31[0]+.._31[7] };
+ _38 = _30 + _37;
+ _39 = VEC_PERM_EXPR <_38, _38, { 7, 7, 7, 7, 7, 7, 7, 7 }>;
+ MEM <vector(8) int> [(int *)&D.2043] = _39;
+ MEM <vector(8) int> [(int *)&D.2042] = _38;
+ Exclusive scan:
+ _26 = D.2043[_25];
+ D.2044[_25] = _26;
+ _27 = D.2042[_25];
+ _28 = _26 + _27;
+ D.2043[_25] = _28;
+ should be vectorized as (where _40 is the vectorized rhs
+ from the D.2042[_21] = 0; store):
+ _30 = MEM <vector(8) int> [(int *)&D.2043];
+ _31 = MEM <vector(8) int> [(int *)&D.2042];
+ _32 = VEC_PERM_EXPR <_40, _31, { 0, 8, 9, 10, 11, 12, 13, 14 }>;
+ _33 = VEC_PERM_EXPR <_40, _32, { 0, 8, 9, 10, 11, 12, 13, 14 }>;
+ _34 = _32 + _33;
+ // _34 = { 0, _31[0], _31[0]+_31[1], _31[1]+_31[2], _31[2]+_31[3],
+ // _31[3]+_31[4], ... _31[5]+.._31[6] };
+ _35 = VEC_PERM_EXPR <_40, _34, { 0, 1, 8, 9, 10, 11, 12, 13 }>;
+ _36 = _34 + _35;
+ // _36 = { 0, _31[0], _31[0]+_31[1], _31[0]+.._31[2], _31[0]+.._31[3],
+ // _31[1]+.._31[4], ... _31[3]+.._31[6] };
+ _37 = VEC_PERM_EXPR <_40, _36, { 0, 1, 2, 3, 8, 9, 10, 11 }>;
+ _38 = _36 + _37;
+ // _38 = { 0, _31[0], _31[0]+_31[1], _31[0]+.._31[2], _31[0]+.._31[3],
+ // _31[0]+.._31[4], ... _31[0]+.._31[6] };
+ _39 = _30 + _38;
+ _50 = _31 + _39;
+ _51 = VEC_PERM_EXPR <_50, _50, { 7, 7, 7, 7, 7, 7, 7, 7 }>;
+ MEM <vector(8) int> [(int *)&D.2044] = _39;
+ MEM <vector(8) int> [(int *)&D.2042] = _51; */
+ enum machine_mode vec_mode = TYPE_MODE (vectype);
+ optab optab = optab_for_tree_code (code, vectype, optab_default);
+ if (!optab || optab_handler (optab, vec_mode) == CODE_FOR_nothing)
+ goto fail;
+
+ int units_log2 = scan_store_can_perm_p (vectype, *init);
+ if (units_log2 == -1)
+ goto fail;
+
+ return true;
+}
+
+
+/* Function vectorizable_scan_store.
+
+ Helper of vectorizable_score, arguments like on vectorizable_store.
+ Handle only the transformation, checking is done in check_scan_store. */
+
+static bool
+vectorizable_scan_store (stmt_vec_info stmt_info, gimple_stmt_iterator *gsi,
+ stmt_vec_info *vec_stmt, int ncopies)
+{
+ loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_info);
+ dr_vec_info *dr_info = STMT_VINFO_DR_INFO (stmt_info);
+ tree ref_type = reference_alias_ptr_type (DR_REF (dr_info->dr));
+ vec_info *vinfo = stmt_info->vinfo;
+ tree vectype = STMT_VINFO_VECTYPE (stmt_info);
+
+ if (dump_enabled_p ())
+ dump_printf_loc (MSG_NOTE, vect_location,
+ "transform scan store. ncopies = %d\n", ncopies);
+
+ gimple *stmt = STMT_VINFO_STMT (stmt_info);
+ tree rhs = gimple_assign_rhs1 (stmt);
+ gcc_assert (TREE_CODE (rhs) == SSA_NAME);
+
+ tree var = TREE_OPERAND (DR_BASE_ADDRESS (dr_info->dr), 0);
+ bool inscan_var_store
+ = lookup_attribute ("omp simd inscan", DECL_ATTRIBUTES (var)) != NULL;
+
+ if (STMT_VINFO_SIMD_LANE_ACCESS_P (stmt_info) == 4 && !inscan_var_store)
+ {
+ use_operand_p use_p;
+ imm_use_iterator iter;
+ FOR_EACH_IMM_USE_FAST (use_p, iter, rhs)
+ {
+ gimple *use_stmt = USE_STMT (use_p);
+ if (use_stmt == stmt || is_gimple_debug (use_stmt))
+ continue;
+ rhs = gimple_assign_lhs (use_stmt);
+ break;
+ }
+ }
+
+ gimple *def_stmt = SSA_NAME_DEF_STMT (rhs);
+ enum tree_code code = gimple_assign_rhs_code (def_stmt);
+ if (code == POINTER_PLUS_EXPR)
+ code = PLUS_EXPR;
+ gcc_assert (TREE_CODE_LENGTH (code) == binary_op
+ && commutative_tree_code (code));
+ tree rhs1 = gimple_assign_rhs1 (def_stmt);
+ tree rhs2 = gimple_assign_rhs2 (def_stmt);
+ gcc_assert (TREE_CODE (rhs1) == SSA_NAME && TREE_CODE (rhs2) == SSA_NAME);
+ gimple *load1_stmt = SSA_NAME_DEF_STMT (rhs1);
+ gimple *load2_stmt = SSA_NAME_DEF_STMT (rhs2);
+ stmt_vec_info load1_stmt_info = loop_vinfo->lookup_stmt (load1_stmt);
+ stmt_vec_info load2_stmt_info = loop_vinfo->lookup_stmt (load2_stmt);
+ dr_vec_info *load1_dr_info = STMT_VINFO_DR_INFO (load1_stmt_info);
+ dr_vec_info *load2_dr_info = STMT_VINFO_DR_INFO (load2_stmt_info);
+ tree var1 = TREE_OPERAND (DR_BASE_ADDRESS (load1_dr_info->dr), 0);
+ tree var2 = TREE_OPERAND (DR_BASE_ADDRESS (load2_dr_info->dr), 0);
+
+ if (lookup_attribute ("omp simd inscan", DECL_ATTRIBUTES (var1)))
+ {
+ std::swap (rhs1, rhs2);
+ std::swap (var1, var2);
+ std::swap (load1_dr_info, load2_dr_info);
+ }
+
+ tree *init = loop_vinfo->scan_map->get (var1);
+ gcc_assert (init);
+
+ unsigned HOST_WIDE_INT nunits;
+ if (!TYPE_VECTOR_SUBPARTS (vectype).is_constant (&nunits))
+ gcc_unreachable ();
+ auto_vec<enum scan_store_kind, 16> use_whole_vector;
+ int units_log2 = scan_store_can_perm_p (vectype, *init, &use_whole_vector);
+ gcc_assert (units_log2 > 0);
+ auto_vec<tree, 16> perms;
+ perms.quick_grow (units_log2 + 1);
+ tree zero_vec = NULL_TREE, masktype = NULL_TREE;
+ for (int i = 0; i <= units_log2; ++i)
+ {
+ unsigned HOST_WIDE_INT j, k;
+ vec_perm_builder sel (nunits, nunits, 1);
+ sel.quick_grow (nunits);
+ if (i == units_log2)
+ for (j = 0; j < nunits; ++j)
+ sel[j] = nunits - 1;
+ else
+ {
+ for (j = 0; j < (HOST_WIDE_INT_1U << i); ++j)
+ sel[j] = j;
+ for (k = 0; j < nunits; ++j, ++k)
+ sel[j] = nunits + k;
+ }
+ vec_perm_indices indices (sel, i == units_log2 ? 1 : 2, nunits);
+ if (!use_whole_vector.is_empty ()
+ && use_whole_vector[i] != scan_store_kind_perm)
+ {
+ if (zero_vec == NULL_TREE)
+ zero_vec = build_zero_cst (vectype);
+ if (masktype == NULL_TREE
+ && use_whole_vector[i] == scan_store_kind_lshift_cond)
+ masktype = build_same_sized_truth_vector_type (vectype);
+ perms[i] = vect_gen_perm_mask_any (vectype, indices);
+ }
+ else
+ perms[i] = vect_gen_perm_mask_checked (vectype, indices);
+ }
+
+ stmt_vec_info prev_stmt_info = NULL;
+ tree vec_oprnd1 = NULL_TREE;
+ tree vec_oprnd2 = NULL_TREE;
+ tree vec_oprnd3 = NULL_TREE;
+ tree dataref_ptr = DR_BASE_ADDRESS (dr_info->dr);
+ tree dataref_offset = build_int_cst (ref_type, 0);
+ tree bump = vect_get_data_ptr_increment (dr_info, vectype, VMAT_CONTIGUOUS);
+ tree ldataref_ptr = NULL_TREE;
+ tree orig = NULL_TREE;
+ if (STMT_VINFO_SIMD_LANE_ACCESS_P (stmt_info) == 4 && !inscan_var_store)
+ ldataref_ptr = DR_BASE_ADDRESS (load1_dr_info->dr);
+ for (int j = 0; j < ncopies; j++)
+ {
+ stmt_vec_info new_stmt_info;
+ if (j == 0)
+ {
+ vec_oprnd1 = vect_get_vec_def_for_operand (*init, stmt_info);
+ if (ldataref_ptr == NULL)
+ vec_oprnd2 = vect_get_vec_def_for_operand (rhs1, stmt_info);
+ vec_oprnd3 = vect_get_vec_def_for_operand (rhs2, stmt_info);
+ orig = vec_oprnd3;
+ }
+ else
+ {
+ vec_oprnd1 = vect_get_vec_def_for_stmt_copy (vinfo, vec_oprnd1);
+ if (ldataref_ptr == NULL)
+ vec_oprnd2 = vect_get_vec_def_for_stmt_copy (vinfo, vec_oprnd2);
+ vec_oprnd3 = vect_get_vec_def_for_stmt_copy (vinfo, vec_oprnd3);
+ if (!inscan_var_store)
+ dataref_offset = int_const_binop (PLUS_EXPR, dataref_offset, bump);
+ }
+
+ if (ldataref_ptr)
+ {
+ vec_oprnd2 = make_ssa_name (vectype);
+ tree data_ref = fold_build2 (MEM_REF, vectype,
+ unshare_expr (ldataref_ptr),
+ dataref_offset);
+ vect_copy_ref_info (data_ref, DR_REF (load1_dr_info->dr));
+ gimple *g = gimple_build_assign (vec_oprnd2, data_ref);
+ new_stmt_info = vect_finish_stmt_generation (stmt_info, g, gsi);
+ if (prev_stmt_info == NULL)
+ STMT_VINFO_VEC_STMT (stmt_info) = *vec_stmt = new_stmt_info;
+ else
+ STMT_VINFO_RELATED_STMT (prev_stmt_info) = new_stmt_info;
+ prev_stmt_info = new_stmt_info;
+ }
+
+ tree v = vec_oprnd2;
+ for (int i = 0; i < units_log2; ++i)
+ {
+ tree new_temp = make_ssa_name (vectype);
+ gimple *g = gimple_build_assign (new_temp, VEC_PERM_EXPR,
+ (zero_vec
+ && (use_whole_vector[i]
+ != scan_store_kind_perm))
+ ? zero_vec : vec_oprnd1, v,
+ perms[i]);
+ new_stmt_info = vect_finish_stmt_generation (stmt_info, g, gsi);
+ if (prev_stmt_info == NULL)
+ STMT_VINFO_VEC_STMT (stmt_info) = *vec_stmt = new_stmt_info;
+ else
+ STMT_VINFO_RELATED_STMT (prev_stmt_info) = new_stmt_info;
+ prev_stmt_info = new_stmt_info;
+
+ if (zero_vec && use_whole_vector[i] == scan_store_kind_lshift_cond)
+ {
+ /* Whole vector shift shifted in zero bits, but if *init
+ is not initializer_zerop, we need to replace those elements
+ with elements from vec_oprnd1. */
+ tree_vector_builder vb (masktype, nunits, 1);
+ for (unsigned HOST_WIDE_INT k = 0; k < nunits; ++k)
+ vb.quick_push (k < (HOST_WIDE_INT_1U << i)
+ ? boolean_false_node : boolean_true_node);
+
+ tree new_temp2 = make_ssa_name (vectype);
+ g = gimple_build_assign (new_temp2, VEC_COND_EXPR, vb.build (),
+ new_temp, vec_oprnd1);
+ new_stmt_info = vect_finish_stmt_generation (stmt_info, g, gsi);
+ STMT_VINFO_RELATED_STMT (prev_stmt_info) = new_stmt_info;
+ prev_stmt_info = new_stmt_info;
+ new_temp = new_temp2;
+ }
+
+ /* For exclusive scan, perform the perms[i] permutation once
+ more. */
+ if (i == 0
+ && STMT_VINFO_SIMD_LANE_ACCESS_P (stmt_info) == 4
+ && v == vec_oprnd2)
+ {
+ v = new_temp;
+ --i;
+ continue;
+ }
+
+ tree new_temp2 = make_ssa_name (vectype);
+ g = gimple_build_assign (new_temp2, code, v, new_temp);
+ new_stmt_info = vect_finish_stmt_generation (stmt_info, g, gsi);
+ STMT_VINFO_RELATED_STMT (prev_stmt_info) = new_stmt_info;
+ prev_stmt_info = new_stmt_info;
+
+ v = new_temp2;
+ }
+
+ tree new_temp = make_ssa_name (vectype);
+ gimple *g = gimple_build_assign (new_temp, code, orig, v);
+ new_stmt_info = vect_finish_stmt_generation (stmt_info, g, gsi);
+ STMT_VINFO_RELATED_STMT (prev_stmt_info) = new_stmt_info;
+ prev_stmt_info = new_stmt_info;
+
+ tree last_perm_arg = new_temp;
+ /* For exclusive scan, new_temp computed above is the exclusive scan
+ prefix sum. Turn it into inclusive prefix sum for the broadcast
+ of the last element into orig. */
+ if (STMT_VINFO_SIMD_LANE_ACCESS_P (stmt_info) == 4)
+ {
+ last_perm_arg = make_ssa_name (vectype);
+ g = gimple_build_assign (last_perm_arg, code, new_temp, vec_oprnd2);
+ new_stmt_info = vect_finish_stmt_generation (stmt_info, g, gsi);
+ STMT_VINFO_RELATED_STMT (prev_stmt_info) = new_stmt_info;
+ prev_stmt_info = new_stmt_info;
+ }
+
+ orig = make_ssa_name (vectype);
+ g = gimple_build_assign (orig, VEC_PERM_EXPR, last_perm_arg,
+ last_perm_arg, perms[units_log2]);
+ new_stmt_info = vect_finish_stmt_generation (stmt_info, g, gsi);
+ STMT_VINFO_RELATED_STMT (prev_stmt_info) = new_stmt_info;
+ prev_stmt_info = new_stmt_info;
+
+ if (!inscan_var_store)
+ {
+ tree data_ref = fold_build2 (MEM_REF, vectype,
+ unshare_expr (dataref_ptr),
+ dataref_offset);
+ vect_copy_ref_info (data_ref, DR_REF (dr_info->dr));
+ g = gimple_build_assign (data_ref, new_temp);
+ new_stmt_info = vect_finish_stmt_generation (stmt_info, g, gsi);
+ STMT_VINFO_RELATED_STMT (prev_stmt_info) = new_stmt_info;
+ prev_stmt_info = new_stmt_info;
+ }
+ }
+
+ if (inscan_var_store)
+ for (int j = 0; j < ncopies; j++)
+ {
+ if (j != 0)
+ dataref_offset = int_const_binop (PLUS_EXPR, dataref_offset, bump);
+
+ tree data_ref = fold_build2 (MEM_REF, vectype,
+ unshare_expr (dataref_ptr),
+ dataref_offset);
+ vect_copy_ref_info (data_ref, DR_REF (dr_info->dr));
+ gimple *g = gimple_build_assign (data_ref, orig);
+ stmt_vec_info new_stmt_info
+ = vect_finish_stmt_generation (stmt_info, g, gsi);
+ STMT_VINFO_RELATED_STMT (prev_stmt_info) = new_stmt_info;
+ prev_stmt_info = new_stmt_info;
+ }
+ return true;
+}
+
+
/* Function vectorizable_store.
Check if STMT_INFO defines a non scalar data-ref (array/pointer/structure)
@@ -6514,6 +7314,13 @@ vectorizable_store (stmt_vec_info stmt_info, gimple_stmt_iterator *gsi,
group_size = vec_num = 1;
}
+ if (STMT_VINFO_SIMD_LANE_ACCESS_P (stmt_info) > 1 && !vec_stmt)
+ {
+ if (!check_scan_store (stmt_info, vectype, rhs_dt, slp, mask,
+ memory_access_type))
+ return false;
+ }
+
if (!vec_stmt) /* transformation not required. */
{
STMT_VINFO_MEMORY_ACCESS_TYPE (stmt_info) = memory_access_type;
@@ -6737,6 +7544,8 @@ vectorizable_store (stmt_vec_info stmt_info, gimple_stmt_iterator *gsi,
}
return true;
}
+ else if (STMT_VINFO_SIMD_LANE_ACCESS_P (stmt_info) >= 3)
+ return vectorizable_scan_store (stmt_info, gsi, vec_stmt, ncopies);
if (STMT_VINFO_GROUPED_ACCESS (stmt_info))
DR_GROUP_STORE_COUNT (DR_GROUP_FIRST_ELEMENT (stmt_info))++;
@@ -7162,7 +7971,7 @@ vectorizable_store (stmt_vec_info stmt_info, gimple_stmt_iterator *gsi,
gcc_assert (useless_type_conversion_p (vectype,
TREE_TYPE (vec_oprnd)));
bool simd_lane_access_p
- = STMT_VINFO_SIMD_LANE_ACCESS_P (stmt_info);
+ = STMT_VINFO_SIMD_LANE_ACCESS_P (stmt_info) != 0;
if (simd_lane_access_p
&& !loop_masks
&& TREE_CODE (DR_BASE_ADDRESS (first_dr_info->dr)) == ADDR_EXPR
@@ -7622,14 +8431,6 @@ vectorizable_load (stmt_vec_info stmt_info, gimple_stmt_iterator *gsi,
if (!scalar_dest)
return false;
- if (slp_node != NULL)
- {
- if (dump_enabled_p ())
- dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
- "SLP of masked loads not supported.\n");
- return false;
- }
-
int mask_index = internal_fn_mask_index (ifn);
if (mask_index >= 0)
{
@@ -7712,6 +8513,15 @@ vectorizable_load (stmt_vec_info stmt_info, gimple_stmt_iterator *gsi,
first_stmt_info = DR_GROUP_FIRST_ELEMENT (stmt_info);
group_size = DR_GROUP_SIZE (first_stmt_info);
+ /* Refuse non-SLP vectorization of SLP-only groups. */
+ if (!slp && STMT_VINFO_SLP_VECT_ONLY (first_stmt_info))
+ {
+ if (dump_enabled_p ())
+ dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
+ "cannot vectorize load in non-SLP mode.\n");
+ return false;
+ }
+
if (slp && SLP_TREE_LOAD_PERMUTATION (slp_node).exists ())
slp_perm = true;
@@ -8346,7 +9156,7 @@ vectorizable_load (stmt_vec_info stmt_info, gimple_stmt_iterator *gsi,
if (j == 0)
{
bool simd_lane_access_p
- = STMT_VINFO_SIMD_LANE_ACCESS_P (stmt_info);
+ = STMT_VINFO_SIMD_LANE_ACCESS_P (stmt_info) != 0;
if (simd_lane_access_p
&& TREE_CODE (DR_BASE_ADDRESS (first_dr_info->dr)) == ADDR_EXPR
&& VAR_P (TREE_OPERAND (DR_BASE_ADDRESS (first_dr_info->dr), 0))
@@ -8389,8 +9199,19 @@ vectorizable_load (stmt_vec_info stmt_info, gimple_stmt_iterator *gsi,
simd_lane_access_p,
byte_offset, bump);
if (mask)
- vec_mask = vect_get_vec_def_for_operand (mask, stmt_info,
- mask_vectype);
+ {
+ if (slp_node)
+ {
+ auto_vec<tree> ops (1);
+ auto_vec<vec<tree> > vec_defs (1);
+ ops.quick_push (mask);
+ vect_get_slp_defs (ops, slp_node, &vec_defs);
+ vec_mask = vec_defs[0][0];
+ }
+ else
+ vec_mask = vect_get_vec_def_for_operand (mask, stmt_info,
+ mask_vectype);
+ }
}
else
{
diff --git a/gcc/tree-vectorizer.c b/gcc/tree-vectorizer.c
index d271049..325ef58 100644
--- a/gcc/tree-vectorizer.c
+++ b/gcc/tree-vectorizer.c
@@ -641,6 +641,7 @@ vec_info::new_stmt_vec_info (gimple *stmt)
STMT_VINFO_VECTORIZABLE (res) = true;
STMT_VINFO_VEC_REDUCTION_TYPE (res) = TREE_CODE_REDUCTION;
STMT_VINFO_VEC_CONST_COND_REDUC_CODE (res) = ERROR_MARK;
+ STMT_VINFO_SLP_VECT_ONLY (res) = false;
if (gimple_code (stmt) == GIMPLE_PHI
&& is_loop_header_bb_p (gimple_bb (stmt)))
@@ -726,8 +727,8 @@ vect_free_loop_info_assumptions (struct loop *loop)
/* If LOOP has been versioned during ifcvt, return the internal call
guarding it. */
-static gimple *
-vect_loop_vectorized_call (struct loop *loop)
+gimple *
+vect_loop_vectorized_call (struct loop *loop, gcond **cond)
{
basic_block bb = loop_preheader_edge (loop)->src;
gimple *g;
@@ -743,6 +744,8 @@ vect_loop_vectorized_call (struct loop *loop)
while (1);
if (g && gimple_code (g) == GIMPLE_COND)
{
+ if (cond)
+ *cond = as_a <gcond *> (g);
gimple_stmt_iterator gsi = gsi_for_stmt (g);
gsi_prev (&gsi);
if (!gsi_end_p (gsi))
diff --git a/gcc/tree-vectorizer.h b/gcc/tree-vectorizer.h
index 6f59af6..0dd29f8 100644
--- a/gcc/tree-vectorizer.h
+++ b/gcc/tree-vectorizer.h
@@ -396,7 +396,7 @@ typedef struct _loop_vec_info : public vec_info {
/* Condition under which this loop is analyzed and versioned. */
tree num_iters_assumptions;
- /* Threshold of number of iterations below which vectorzation will not be
+ /* Threshold of number of iterations below which vectorization will not be
performed. It is calculated from MIN_PROFITABLE_ITERS and
PARAM_MIN_VECT_LOOP_BOUND. */
unsigned int th;
@@ -428,6 +428,17 @@ typedef struct _loop_vec_info : public vec_info {
loops. */
tree mask_compare_type;
+ /* For #pragma omp simd if (x) loops the x expression. If constant 0,
+ the loop should not be vectorized, if constant non-zero, simd_if_cond
+ shouldn't be set and loop vectorized normally, if SSA_NAME, the loop
+ should be versioned on that condition, using scalar loop if the condition
+ is false and vectorized loop otherwise. */
+ tree simd_if_cond;
+
+ /* Type of the IV to use in the WHILE_ULT call for fully-masked
+ loops. */
+ tree iv_type;
+
/* Unknown DRs according to which loop was peeled. */
struct dr_vec_info *unaligned_dr;
@@ -480,6 +491,10 @@ typedef struct _loop_vec_info : public vec_info {
/* Map of IV base/step expressions to inserted name in the preheader. */
hash_map<tree_operand_hash, tree> *ivexpr_map;
+ /* Map of OpenMP "omp simd array" scan variables to corresponding
+ rhs of the store of the initializer. */
+ hash_map<tree, tree> *scan_map;
+
/* The unrolling factor needed to SLP the loop. In case of that pure SLP is
applied to the loop, i.e., no unrolling is needed, this is 1. */
poly_uint64 slp_unrolling_factor;
@@ -563,6 +578,7 @@ typedef struct _loop_vec_info : public vec_info {
#define LOOP_VINFO_MASKS(L) (L)->masks
#define LOOP_VINFO_MASK_SKIP_NITERS(L) (L)->mask_skip_niters
#define LOOP_VINFO_MASK_COMPARE_TYPE(L) (L)->mask_compare_type
+#define LOOP_VINFO_MASK_IV_TYPE(L) (L)->iv_type
#define LOOP_VINFO_PTR_MASK(L) (L)->ptr_mask
#define LOOP_VINFO_LOOP_NEST(L) (L)->shared->loop_nest
#define LOOP_VINFO_DATAREFS(L) (L)->shared->datarefs
@@ -591,6 +607,7 @@ typedef struct _loop_vec_info : public vec_info {
#define LOOP_VINFO_SCALAR_ITERATION_COST(L) (L)->scalar_cost_vec
#define LOOP_VINFO_SINGLE_SCALAR_ITERATION_COST(L) (L)->single_scalar_iteration_cost
#define LOOP_VINFO_ORIG_LOOP_INFO(L) (L)->orig_loop_info
+#define LOOP_VINFO_SIMD_IF_COND(L) (L)->simd_if_cond
#define LOOP_REQUIRES_VERSIONING_FOR_ALIGNMENT(L) \
((L)->may_misalign_stmts.length () > 0)
@@ -600,10 +617,13 @@ typedef struct _loop_vec_info : public vec_info {
|| (L)->lower_bounds.length () > 0)
#define LOOP_REQUIRES_VERSIONING_FOR_NITERS(L) \
(LOOP_VINFO_NITERS_ASSUMPTIONS (L))
+#define LOOP_REQUIRES_VERSIONING_FOR_SIMD_IF_COND(L) \
+ (LOOP_VINFO_SIMD_IF_COND (L))
#define LOOP_REQUIRES_VERSIONING(L) \
(LOOP_REQUIRES_VERSIONING_FOR_ALIGNMENT (L) \
|| LOOP_REQUIRES_VERSIONING_FOR_ALIAS (L) \
- || LOOP_REQUIRES_VERSIONING_FOR_NITERS (L))
+ || LOOP_REQUIRES_VERSIONING_FOR_NITERS (L) \
+ || LOOP_REQUIRES_VERSIONING_FOR_SIMD_IF_COND (L))
#define LOOP_VINFO_NITERS_KNOWN_P(L) \
(tree_fits_shwi_p ((L)->num_iters) && tree_to_shwi ((L)->num_iters) > 0)
@@ -897,7 +917,7 @@ struct _stmt_vec_info {
bool strided_p;
/* For both loads and stores. */
- bool simd_lane_access_p;
+ unsigned simd_lane_access_p : 3;
/* Classifies how the load or store is going to be implemented
for loop vectorization. */
@@ -935,6 +955,9 @@ struct _stmt_vec_info {
and OPERATION_BITS without changing the result. */
unsigned int operation_precision;
signop operation_sign;
+
+ /* True if this is only suitable for SLP vectorization. */
+ bool slp_vect_only_p;
};
/* Information about a gather/scatter call. */
@@ -1030,6 +1053,7 @@ STMT_VINFO_BB_VINFO (stmt_vec_info stmt_vinfo)
#define STMT_VINFO_NUM_SLP_USES(S) (S)->num_slp_uses
#define STMT_VINFO_REDUC_TYPE(S) (S)->reduc_type
#define STMT_VINFO_REDUC_DEF(S) (S)->reduc_def
+#define STMT_VINFO_SLP_VECT_ONLY(S) (S)->slp_vect_only_p
#define DR_GROUP_FIRST_ELEMENT(S) \
(gcc_checking_assert ((S)->dr_aux.dr), (S)->first_element)
@@ -1477,7 +1501,7 @@ extern unsigned record_stmt_cost (stmt_vector_for_cost *, int,
extern stmt_vec_info vect_finish_replace_stmt (stmt_vec_info, gimple *);
extern stmt_vec_info vect_finish_stmt_generation (stmt_vec_info, gimple *,
gimple_stmt_iterator *);
-extern opt_result vect_mark_stmts_to_be_vectorized (loop_vec_info);
+extern opt_result vect_mark_stmts_to_be_vectorized (loop_vec_info, bool *);
extern tree vect_get_store_rhs (stmt_vec_info);
extern tree vect_get_vec_def_for_operand_1 (stmt_vec_info, enum vect_def_type);
extern tree vect_get_vec_def_for_operand (tree, stmt_vec_info, tree = NULL);
@@ -1535,7 +1559,7 @@ extern bool vect_check_gather_scatter (stmt_vec_info, loop_vec_info,
gather_scatter_info *);
extern opt_result vect_find_stmt_data_reference (loop_p, gimple *,
vec<data_reference_p> *);
-extern opt_result vect_analyze_data_refs (vec_info *, poly_uint64 *);
+extern opt_result vect_analyze_data_refs (vec_info *, poly_uint64 *, bool *);
extern void vect_record_base_alignments (vec_info *);
extern tree vect_create_data_ref_ptr (stmt_vec_info, tree, struct loop *, tree,
tree *, gimple_stmt_iterator *,
@@ -1567,6 +1591,7 @@ extern tree vect_create_addr_base_for_vector_ref (stmt_vec_info, gimple_seq *,
/* FORNOW: Used in tree-parloops.c. */
extern stmt_vec_info vect_force_simple_reduction (loop_vec_info, stmt_vec_info,
bool *, bool);
+extern widest_int vect_iv_limit_for_full_masking (loop_vec_info loop_vinfo);
/* Used in gimple-loop-interchange.c. */
extern bool check_reduction_path (dump_user_location_t, loop_p, gphi *, tree,
enum tree_code);
@@ -1635,5 +1660,7 @@ void vect_pattern_recog (vec_info *);
/* In tree-vectorizer.c. */
unsigned vectorize_loops (void);
void vect_free_loop_info_assumptions (struct loop *);
+gimple *vect_loop_vectorized_call (struct loop *, gcond **cond = NULL);
+
#endif /* GCC_TREE_VECTORIZER_H */
diff --git a/gcc/tree-vrp.c b/gcc/tree-vrp.c
index 0a17271..dc7f825 100644
--- a/gcc/tree-vrp.c
+++ b/gcc/tree-vrp.c
@@ -287,18 +287,7 @@ value_range::set_varying ()
bool
value_range_base::may_contain_p (tree val) const
{
- if (varying_p ())
- return true;
-
- if (undefined_p ())
- return true;
-
- if (m_kind == VR_ANTI_RANGE)
- {
- int res = value_inside_range (val, min (), max ());
- return res == 0 || res == -2;
- }
- return value_inside_range (val, min (), max ()) != 0;
+ return value_inside_range (val) != 0;
}
void
@@ -776,32 +765,19 @@ value_range::set (tree val)
set (VR_RANGE, val, val, NULL);
}
-/* Set value range VR to a non-NULL range of type TYPE. */
+/* Set value range VR to a nonzero range of type TYPE. */
void
-value_range_base::set_nonnull (tree type)
+value_range_base::set_nonzero (tree type)
{
tree zero = build_int_cst (type, 0);
set (VR_ANTI_RANGE, zero, zero);
}
-void
-value_range::set_nonnull (tree type)
-{
- tree zero = build_int_cst (type, 0);
- set (VR_ANTI_RANGE, zero, zero, NULL);
-}
-
-/* Set value range VR to a NULL range of type TYPE. */
+/* Set value range VR to a ZERO range of type TYPE. */
void
-value_range_base::set_null (tree type)
-{
- set (build_int_cst (type, 0));
-}
-
-void
-value_range::set_null (tree type)
+value_range_base::set_zero (tree type)
{
set (build_int_cst (type, 0));
}
@@ -830,22 +806,6 @@ vrp_bitmap_equal_p (const_bitmap b1, const_bitmap b2)
&& bitmap_equal_p (b1, b2)));
}
-/* Return true if VR is [0, 0]. */
-
-static inline bool
-range_is_null (const value_range_base *vr)
-{
- return vr->zero_p ();
-}
-
-static inline bool
-range_is_nonnull (const value_range_base *vr)
-{
- return (vr->kind () == VR_ANTI_RANGE
- && vr->min () == vr->max ()
- && integer_zerop (vr->min ()));
-}
-
/* Return true if max and min of VR are INTEGER_CST. It's not necessary
a singleton. */
@@ -1147,55 +1107,38 @@ compare_values (tree val1, tree val2)
}
-/* Return 1 if VAL is inside value range MIN <= VAL <= MAX,
- 0 if VAL is not inside [MIN, MAX],
+/* Return 1 if VAL is inside value range.
+ 0 if VAL is not inside value range.
-2 if we cannot tell either way.
Benchmark compile/20001226-1.c compilation time after changing this
function. */
int
-value_inside_range (tree val, tree min, tree max)
+value_range_base::value_inside_range (tree val) const
{
int cmp1, cmp2;
- cmp1 = operand_less_p (val, min);
+ if (varying_p ())
+ return 1;
+
+ if (undefined_p ())
+ return 0;
+
+ cmp1 = operand_less_p (val, m_min);
if (cmp1 == -2)
return -2;
if (cmp1 == 1)
- return 0;
+ return m_kind != VR_RANGE;
- cmp2 = operand_less_p (max, val);
+ cmp2 = operand_less_p (m_max, val);
if (cmp2 == -2)
return -2;
- return !cmp2;
-}
-
-
-/* Return TRUE if *VR includes the value X. */
-
-bool
-range_includes_p (const value_range_base *vr, HOST_WIDE_INT x)
-{
- if (vr->varying_p () || vr->undefined_p ())
- return true;
- return vr->may_contain_p (build_int_cst (vr->type (), x));
-}
-
-/* If *VR has a value range that is a single constant value return that,
- otherwise return NULL_TREE.
-
- ?? This actually returns TRUE for [&x, &x], so perhaps "constant"
- is not the best name. */
-
-tree
-value_range_constant_singleton (const value_range_base *vr)
-{
- tree result = NULL;
- if (vr->singleton_p (&result))
- return result;
- return NULL;
+ if (m_kind == VR_RANGE)
+ return !cmp2;
+ else
+ return !!cmp2;
}
/* Value range wrapper for wide_int_range_set_zero_nonzero_bits.
@@ -1583,9 +1526,9 @@ extract_range_from_binary_expr (value_range_base *vr,
code is EXACT_DIV_EXPR. We could mask out bits in the resulting
range, but then we also need to hack up vrp_union. It's just
easier to special case when vr0 is ~[0,0] for EXACT_DIV_EXPR. */
- if (code == EXACT_DIV_EXPR && range_is_nonnull (&vr0))
+ if (code == EXACT_DIV_EXPR && vr0.nonzero_p ())
{
- vr->set_nonnull (expr_type);
+ vr->set_nonzero (expr_type);
return;
}
@@ -1663,9 +1606,9 @@ extract_range_from_binary_expr (value_range_base *vr,
If both are null, then the result is null. Otherwise they
are varying. */
if (!range_includes_zero_p (&vr0) && !range_includes_zero_p (&vr1))
- vr->set_nonnull (expr_type);
- else if (range_is_null (&vr0) && range_is_null (&vr1))
- vr->set_null (expr_type);
+ vr->set_nonzero (expr_type);
+ else if (vr0.zero_p () && vr1.zero_p ())
+ vr->set_zero (expr_type);
else
vr->set_varying ();
}
@@ -1692,9 +1635,9 @@ extract_range_from_binary_expr (value_range_base *vr,
&& (flag_delete_null_pointer_checks
|| (range_int_cst_p (&vr1)
&& !tree_int_cst_sign_bit (vr1.max ()))))
- vr->set_nonnull (expr_type);
- else if (range_is_null (&vr0) && range_is_null (&vr1))
- vr->set_null (expr_type);
+ vr->set_nonzero (expr_type);
+ else if (vr0.zero_p () && vr1.zero_p ())
+ vr->set_zero (expr_type);
else
vr->set_varying ();
}
@@ -1703,9 +1646,9 @@ extract_range_from_binary_expr (value_range_base *vr,
/* For pointer types, we are really only interested in asserting
whether the expression evaluates to non-NULL. */
if (!range_includes_zero_p (&vr0) && !range_includes_zero_p (&vr1))
- vr->set_nonnull (expr_type);
- else if (range_is_null (&vr0) || range_is_null (&vr1))
- vr->set_null (expr_type);
+ vr->set_nonzero (expr_type);
+ else if (vr0.zero_p () || vr1.zero_p ())
+ vr->set_zero (expr_type);
else
vr->set_varying ();
}
@@ -1898,7 +1841,7 @@ extract_range_from_binary_expr (value_range_base *vr,
bool extra_range_p;
/* Special case explicit division by zero as undefined. */
- if (range_is_null (&vr1))
+ if (vr1.zero_p ())
{
vr->set_undefined ();
return;
@@ -1937,7 +1880,7 @@ extract_range_from_binary_expr (value_range_base *vr,
}
else if (code == TRUNC_MOD_EXPR)
{
- if (range_is_null (&vr1))
+ if (vr1.zero_p ())
{
vr->set_undefined ();
return;
@@ -2141,9 +2084,9 @@ extract_range_from_unary_expr (value_range_base *vr,
if (POINTER_TYPE_P (type) || POINTER_TYPE_P (op0_type))
{
if (!range_includes_zero_p (&vr0))
- vr->set_nonnull (type);
- else if (range_is_null (&vr0))
- vr->set_null (type);
+ vr->set_nonzero (type);
+ else if (vr0.zero_p ())
+ vr->set_zero (type);
else
vr->set_varying ();
return;
@@ -6049,30 +5992,26 @@ intersect_ranges (enum value_range_kind *vr0type,
}
-/* Intersect the two value-ranges *VR0 and *VR1 and store the result
- in *VR0. This may not be the smallest possible such range. */
+/* Helper for the intersection operation for value ranges. Given two
+ value ranges VR0 and VR1, return the intersection of the two
+ ranges. This may not be the smallest possible such range. */
-void
-value_range::intersect_helper (value_range *vr0, const value_range *vr1)
+value_range_base
+value_range_base::intersect_helper (const value_range_base *vr0,
+ const value_range_base *vr1)
{
/* If either range is VR_VARYING the other one wins. */
if (vr1->varying_p ())
- return;
+ return *vr0;
if (vr0->varying_p ())
- {
- vr0->deep_copy (vr1);
- return;
- }
+ return *vr1;
/* When either range is VR_UNDEFINED the resulting range is
VR_UNDEFINED, too. */
if (vr0->undefined_p ())
- return;
+ return *vr0;
if (vr1->undefined_p ())
- {
- vr0->set_undefined ();
- return;
- }
+ return *vr1;
value_range_kind vr0type = vr0->kind ();
tree vr0min = vr0->min ();
@@ -6082,28 +6021,34 @@ value_range::intersect_helper (value_range *vr0, const value_range *vr1)
/* Make sure to canonicalize the result though as the inversion of a
VR_RANGE can still be a VR_RANGE. Work on a temporary so we can
fall back to vr0 when this turns things to varying. */
- value_range tem;
+ value_range_base tem;
tem.set_and_canonicalize (vr0type, vr0min, vr0max);
/* If that failed, use the saved original VR0. */
if (tem.varying_p ())
- return;
- vr0->update (tem.kind (), tem.min (), tem.max ());
+ return *vr0;
- /* If the result is VR_UNDEFINED there is no need to mess with
- the equivalencies. */
- if (vr0->undefined_p ())
- return;
+ return tem;
+}
+
+void
+value_range_base::intersect (const value_range_base *other)
+{
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ {
+ fprintf (dump_file, "Intersecting\n ");
+ dump_value_range (dump_file, this);
+ fprintf (dump_file, "\nand\n ");
+ dump_value_range (dump_file, other);
+ fprintf (dump_file, "\n");
+ }
+
+ *this = intersect_helper (this, other);
- /* The resulting set of equivalences for range intersection is the union of
- the two sets. */
- if (vr0->m_equiv && vr1->m_equiv && vr0->m_equiv != vr1->m_equiv)
- bitmap_ior_into (vr0->m_equiv, vr1->m_equiv);
- else if (vr1->m_equiv && !vr0->m_equiv)
+ if (dump_file && (dump_flags & TDF_DETAILS))
{
- /* All equivalence bitmaps are allocated from the same obstack. So
- we can use the obstack associated with VR to allocate vr0->equiv. */
- vr0->m_equiv = BITMAP_ALLOC (vr1->m_equiv->obstack);
- bitmap_copy (m_equiv, vr1->m_equiv);
+ fprintf (dump_file, "to\n ");
+ dump_value_range (dump_file, this);
+ fprintf (dump_file, "\n");
}
}
@@ -6118,7 +6063,36 @@ value_range::intersect (const value_range *other)
dump_value_range (dump_file, other);
fprintf (dump_file, "\n");
}
- intersect_helper (this, other);
+
+ /* If THIS is varying we want to pick up equivalences from OTHER.
+ Just special-case this here rather than trying to fixup after the
+ fact. */
+ if (this->varying_p ())
+ this->deep_copy (other);
+ else
+ {
+ value_range_base tem = intersect_helper (this, other);
+ this->update (tem.kind (), tem.min (), tem.max ());
+
+ /* If the result is VR_UNDEFINED there is no need to mess with
+ equivalencies. */
+ if (!undefined_p ())
+ {
+ /* The resulting set of equivalences for range intersection
+ is the union of the two sets. */
+ if (m_equiv && other->m_equiv && m_equiv != other->m_equiv)
+ bitmap_ior_into (m_equiv, other->m_equiv);
+ else if (other->m_equiv && !m_equiv)
+ {
+ /* All equivalence bitmaps are allocated from the same
+ obstack. So we can use the obstack associated with
+ VR to allocate this->m_equiv. */
+ m_equiv = BITMAP_ALLOC (other->m_equiv->obstack);
+ bitmap_copy (m_equiv, other->m_equiv);
+ }
+ }
+ }
+
if (dump_file && (dump_flags & TDF_DETAILS))
{
fprintf (dump_file, "to\n ");
@@ -6152,7 +6126,7 @@ value_range_base::union_helper (const value_range_base *vr0,
vr1->kind (), vr1->min (), vr1->max ());
/* Work on a temporary so we can still use vr0 when union returns varying. */
- value_range tem;
+ value_range_base tem;
tem.set_and_canonicalize (vr0type, vr0min, vr0max);
/* Failed to find an efficient meet. Before giving up and setting
@@ -6162,7 +6136,7 @@ value_range_base::union_helper (const value_range_base *vr0,
&& range_includes_zero_p (vr0) == 0
&& range_includes_zero_p (vr1) == 0)
{
- tem.set_nonnull (vr0->type ());
+ tem.set_nonzero (vr0->type ());
return tem;
}
diff --git a/gcc/tree-vrp.h b/gcc/tree-vrp.h
index 9d52b42..4ec974f 100644
--- a/gcc/tree-vrp.h
+++ b/gcc/tree-vrp.h
@@ -46,8 +46,8 @@ public:
void set (value_range_kind, tree, tree);
void set (tree);
- void set_nonnull (tree);
- void set_null (tree);
+ void set_nonzero (tree);
+ void set_zero (tree);
enum value_range_kind kind () const;
tree min () const;
@@ -62,6 +62,7 @@ public:
void set_undefined ();
void union_ (const value_range_base *);
+ void intersect (const value_range_base *);
bool operator== (const value_range_base &) const /* = delete */;
bool operator!= (const value_range_base &) const /* = delete */;
@@ -72,6 +73,7 @@ public:
bool may_contain_p (tree) const;
void set_and_canonicalize (enum value_range_kind, tree, tree);
bool zero_p () const;
+ bool nonzero_p () const;
bool singleton_p (tree *result = NULL) const;
void dump (FILE *) const;
@@ -79,6 +81,8 @@ protected:
void check ();
static value_range_base union_helper (const value_range_base *,
const value_range_base *);
+ static value_range_base intersect_helper (const value_range_base *,
+ const value_range_base *);
enum value_range_kind m_kind;
@@ -93,6 +97,9 @@ protected:
friend void gt_ggc_mx (value_range_base *&);
friend void gt_pch_nx (value_range_base &);
friend void gt_pch_nx (value_range_base *, gt_pointer_operator, void *);
+
+private:
+ int value_inside_range (tree) const;
};
/* Note value_range cannot currently be used with GC memory, only
@@ -118,8 +125,6 @@ class GTY((user)) value_range : public value_range_base
/* Deep-copies equiv bitmap argument. */
void set (value_range_kind, tree, tree, bitmap = NULL);
void set (tree);
- void set_nonnull (tree);
- void set_null (tree);
bool operator== (const value_range &) const /* = delete */;
bool operator!= (const value_range &) const /* = delete */;
@@ -145,7 +150,6 @@ class GTY((user)) value_range : public value_range_base
/* Deep-copies bitmap argument. */
void set_equiv (bitmap);
void check ();
- void intersect_helper (value_range *, const value_range *);
/* Set of SSA names whose value ranges are equivalent to this one.
This set is only valid when TYPE is VR_RANGE or VR_ANTI_RANGE. */
@@ -222,6 +226,16 @@ value_range_base::zero_p () const
&& integer_zerop (m_max));
}
+/* Return TRUE if range is nonzero. */
+
+inline bool
+value_range_base::nonzero_p () const
+{
+ return (m_kind == VR_ANTI_RANGE
+ && integer_zerop (m_min)
+ && integer_zerop (m_max));
+}
+
extern void dump_value_range (FILE *, const value_range *);
extern void dump_value_range (FILE *, const value_range_base *);
@@ -243,12 +257,10 @@ struct assert_info
extern void register_edge_assert_for (tree, edge, enum tree_code,
tree, tree, vec<assert_info> &);
extern bool stmt_interesting_for_vrp (gimple *);
-extern bool range_includes_p (const value_range_base *, HOST_WIDE_INT);
extern bool infer_value_range (gimple *, tree, tree_code *, tree *);
extern bool vrp_bitmap_equal_p (const_bitmap, const_bitmap);
-extern tree value_range_constant_singleton (const value_range_base *);
extern bool range_int_cst_p (const value_range_base *);
extern bool range_int_cst_singleton_p (const value_range_base *);
@@ -257,7 +269,6 @@ extern int compare_values_warnv (tree, tree, bool *);
extern int operand_less_p (tree, tree);
extern bool vrp_val_is_min (const_tree);
extern bool vrp_val_is_max (const_tree);
-extern int value_inside_range (tree, tree, tree);
extern tree vrp_val_min (const_tree);
extern tree vrp_val_max (const_tree);
@@ -290,7 +301,13 @@ extern value_range_kind determine_value_range (tree, wide_int *, wide_int *);
inline bool
range_includes_zero_p (const value_range_base *vr)
{
- return range_includes_p (vr, 0);
+ if (vr->undefined_p ())
+ return false;
+
+ if (vr->varying_p ())
+ return true;
+
+ return vr->may_contain_p (build_zero_cst (vr->type ()));
}
#endif /* GCC_TREE_VRP_H */
diff --git a/gcc/tree.c b/gcc/tree.c
index 73102c4..76d94c6 100644
--- a/gcc/tree.c
+++ b/gcc/tree.c
@@ -300,6 +300,8 @@ unsigned const char omp_clause_num_ops[] =
2, /* OMP_CLAUSE_MAP */
1, /* OMP_CLAUSE_USE_DEVICE_PTR */
1, /* OMP_CLAUSE_IS_DEVICE_PTR */
+ 1, /* OMP_CLAUSE_INCLUSIVE */
+ 1, /* OMP_CLAUSE_EXCLUSIVE */
2, /* OMP_CLAUSE__CACHE_ */
2, /* OMP_CLAUSE_GANG */
1, /* OMP_CLAUSE_ASYNC */
@@ -308,6 +310,8 @@ unsigned const char omp_clause_num_ops[] =
0, /* OMP_CLAUSE_SEQ */
1, /* OMP_CLAUSE__LOOPTEMP_ */
1, /* OMP_CLAUSE__REDUCTEMP_ */
+ 1, /* OMP_CLAUSE__CONDTEMP_ */
+ 1, /* OMP_CLAUSE__SCANTEMP_ */
1, /* OMP_CLAUSE_IF */
1, /* OMP_CLAUSE_NUM_THREADS */
1, /* OMP_CLAUSE_SCHEDULE */
@@ -377,6 +381,8 @@ const char * const omp_clause_code_name[] =
"map",
"use_device_ptr",
"is_device_ptr",
+ "inclusive",
+ "exclusive",
"_cache_",
"gang",
"async",
@@ -385,6 +391,8 @@ const char * const omp_clause_code_name[] =
"seq",
"_looptemp_",
"_reductemp_",
+ "_condtemp_",
+ "_scantemp_",
"if",
"num_threads",
"schedule",
@@ -2017,9 +2025,9 @@ verify_constructor_flags (tree c)
/* Return a new CONSTRUCTOR node whose type is TYPE and whose values
are in the vec pointed to by VALS. */
tree
-build_constructor (tree type, vec<constructor_elt, va_gc> *vals)
+build_constructor (tree type, vec<constructor_elt, va_gc> *vals MEM_STAT_DECL)
{
- tree c = make_node (CONSTRUCTOR);
+ tree c = make_node (CONSTRUCTOR PASS_MEM_STAT);
TREE_TYPE (c) = type;
CONSTRUCTOR_ELTS (c) = vals;
@@ -5588,11 +5596,13 @@ need_assembler_name_p (tree decl)
if (TREE_CODE (decl) == TYPE_DECL)
{
- if (flag_lto_odr_type_mering
- && DECL_NAME (decl)
+ if (DECL_NAME (decl)
&& decl == TYPE_NAME (TREE_TYPE (decl))
&& TYPE_MAIN_VARIANT (TREE_TYPE (decl)) == TREE_TYPE (decl)
&& !TYPE_ARTIFICIAL (TREE_TYPE (decl))
+ && ((TREE_CODE (TREE_TYPE (decl)) != RECORD_TYPE
+ && TREE_CODE (TREE_TYPE (decl)) != UNION_TYPE)
+ || TYPE_CXX_ODR_P (TREE_TYPE (decl)))
&& (type_with_linkage_p (TREE_TYPE (decl))
|| TREE_CODE (TREE_TYPE (decl)) == INTEGER_TYPE)
&& !variably_modified_type_p (TREE_TYPE (decl), NULL_TREE))
@@ -8204,8 +8214,6 @@ build_nonstandard_integer_type (unsigned HOST_WIDE_INT precision,
else
fixup_signed_type (itype);
- ret = itype;
-
inchash::hash hstate;
inchash::add_expr (TYPE_MAX_VALUE (itype), hstate);
ret = type_hash_canon (hstate.end (), itype);
@@ -9745,40 +9753,32 @@ clean_symbol_name (char *p)
*p = '_';
}
-/* For anonymous aggregate types, we need some sort of name to
- hold on to. In practice, this should not appear, but it should
- not be harmful if it does. */
-bool
-anon_aggrname_p(const_tree id_node)
-{
-#ifndef NO_DOT_IN_LABEL
- return (IDENTIFIER_POINTER (id_node)[0] == '.'
- && IDENTIFIER_POINTER (id_node)[1] == '_');
-#else /* NO_DOT_IN_LABEL */
-#ifndef NO_DOLLAR_IN_LABEL
- return (IDENTIFIER_POINTER (id_node)[0] == '$' \
- && IDENTIFIER_POINTER (id_node)[1] == '_');
-#else /* NO_DOLLAR_IN_LABEL */
-#define ANON_AGGRNAME_PREFIX "__anon_"
- return (!strncmp (IDENTIFIER_POINTER (id_node), ANON_AGGRNAME_PREFIX,
- sizeof (ANON_AGGRNAME_PREFIX) - 1));
-#endif /* NO_DOLLAR_IN_LABEL */
-#endif /* NO_DOT_IN_LABEL */
-}
-
-/* Return a format for an anonymous aggregate name. */
-const char *
-anon_aggrname_format()
+static GTY(()) unsigned anon_cnt = 0; /* Saved for PCH. */
+
+/* Create a unique anonymous identifier. The identifier is still a
+ valid assembly label. */
+
+tree
+make_anon_name ()
{
-#ifndef NO_DOT_IN_LABEL
- return "._%d";
-#else /* NO_DOT_IN_LABEL */
-#ifndef NO_DOLLAR_IN_LABEL
- return "$_%d";
-#else /* NO_DOLLAR_IN_LABEL */
- return "__anon_%d";
-#endif /* NO_DOLLAR_IN_LABEL */
-#endif /* NO_DOT_IN_LABEL */
+ const char *fmt =
+#if !defined (NO_DOT_IN_LABEL)
+ "."
+#elif !defined (NO_DOLLAR_IN_LABEL)
+ "$"
+#else
+ "_"
+#endif
+ "_anon_%d";
+
+ char buf[24];
+ int len = snprintf (buf, sizeof (buf), fmt, anon_cnt++);
+ gcc_checking_assert (len < int (sizeof (buf)));
+
+ tree id = get_identifier_with_length (buf, len);
+ IDENTIFIER_ANON_P (id) = true;
+
+ return id;
}
/* Generate a name for a special-purpose function.
@@ -10009,8 +10009,10 @@ void
omp_clause_check_failed (const_tree node, const char *file, int line,
const char *function, enum omp_clause_code code)
{
- internal_error ("tree check: expected omp_clause %s, have %s in %s, at %s:%d",
- omp_clause_code_name[code], get_tree_code_name (TREE_CODE (node)),
+ internal_error ("tree check: expected %<omp_clause %s%>, have %qs "
+ "in %s, at %s:%d",
+ omp_clause_code_name[code],
+ get_tree_code_name (TREE_CODE (node)),
function, trim_filename (file), line);
}
@@ -10083,7 +10085,8 @@ tree_int_cst_elt_check_failed (int idx, int len, const char *file, int line,
const char *function)
{
internal_error
- ("tree check: accessed elt %d of tree_int_cst with %d elts in %s, at %s:%d",
+ ("tree check: accessed elt %d of %<tree_int_cst%> with %d elts in %s, "
+ "at %s:%d",
idx + 1, len, function, trim_filename (file), line);
}
@@ -10095,7 +10098,7 @@ tree_vec_elt_check_failed (int idx, int len, const char *file, int line,
const char *function)
{
internal_error
- ("tree check: accessed elt %d of tree_vec with %d elts in %s, at %s:%d",
+ ("tree check: accessed elt %d of %<tree_vec%> with %d elts in %s, at %s:%d",
idx + 1, len, function, trim_filename (file), line);
}
@@ -10121,7 +10124,7 @@ omp_clause_operand_check_failed (int idx, const_tree t, const char *file,
int line, const char *function)
{
internal_error
- ("tree check: accessed operand %d of omp_clause %s with %d operands "
+ ("tree check: accessed operand %d of %<omp_clause %s%> with %d operands "
"in %s, at %s:%d", idx + 1, omp_clause_code_name[OMP_CLAUSE_CODE (t)],
omp_clause_num_ops [OMP_CLAUSE_CODE (t)], function,
trim_filename (file), line);
@@ -10382,10 +10385,12 @@ build_common_tree_nodes (bool signed_char)
for (i = 0; i < NUM_INT_N_ENTS; i++)
if (int_n_enabled_p[i])
{
- char name[50];
+ char name[50], altname[50];
sprintf (name, "__int%d unsigned", int_n_data[i].bitsize);
+ sprintf (altname, "__int%d__ unsigned", int_n_data[i].bitsize);
- if (strcmp (name, SIZE_TYPE) == 0)
+ if (strcmp (name, SIZE_TYPE) == 0
+ || strcmp (altname, SIZE_TYPE) == 0)
{
size_type_node = int_n_trees[i].unsigned_type;
}
@@ -10409,9 +10414,12 @@ build_common_tree_nodes (bool signed_char)
for (int i = 0; i < NUM_INT_N_ENTS; i++)
if (int_n_enabled_p[i])
{
- char name[50];
+ char name[50], altname[50];
sprintf (name, "__int%d", int_n_data[i].bitsize);
- if (strcmp (name, PTRDIFF_TYPE) == 0)
+ sprintf (altname, "__int%d__", int_n_data[i].bitsize);
+
+ if (strcmp (name, PTRDIFF_TYPE) == 0
+ || strcmp (altname, PTRDIFF_TYPE) == 0)
ptrdiff_type_node = int_n_trees[i].signed_type;
}
if (ptrdiff_type_node == NULL_TREE)
@@ -10635,6 +10643,12 @@ build_common_tree_nodes (bool signed_char)
va_list_type_node = t;
}
+
+ /* SCEV analyzer global shared trees. */
+ chrec_dont_know = make_node (SCEV_NOT_KNOWN);
+ TREE_TYPE (chrec_dont_know) = void_type_node;
+ chrec_known = make_node (SCEV_KNOWN);
+ TREE_TYPE (chrec_known) = void_type_node;
}
/* Modify DECL for given flags.
@@ -12299,8 +12313,12 @@ walk_tree_1 (tree *tp, walk_tree_fn func, void *data,
case OMP_CLAUSE_LINK:
case OMP_CLAUSE_USE_DEVICE_PTR:
case OMP_CLAUSE_IS_DEVICE_PTR:
+ case OMP_CLAUSE_INCLUSIVE:
+ case OMP_CLAUSE_EXCLUSIVE:
case OMP_CLAUSE__LOOPTEMP_:
case OMP_CLAUSE__REDUCTEMP_:
+ case OMP_CLAUSE__CONDTEMP_:
+ case OMP_CLAUSE__SCANTEMP_:
case OMP_CLAUSE__SIMDUID_:
WALK_SUBTREE (OMP_CLAUSE_OPERAND (*tp, 0));
/* FALLTHRU */
@@ -13447,7 +13465,11 @@ get_tree_code_name (enum tree_code code)
const char *invalid = "<invalid tree code>";
if (code >= MAX_TREE_CODES)
- return invalid;
+ {
+ if (code == 0xa5a5)
+ return "ggc_freed";
+ return invalid;
+ }
return tree_code_name[code];
}
@@ -13853,11 +13875,11 @@ verify_type_variant (const_tree t, tree tv)
{
gcc_assert (!operand_equal_p (TYPE_SIZE_UNIT (t),
TYPE_SIZE_UNIT (tv), 0));
- error ("type variant has different TYPE_SIZE_UNIT");
+ error ("type variant has different %<TYPE_SIZE_UNIT%>");
debug_tree (tv);
- error ("type variant%'s TYPE_SIZE_UNIT");
+ error ("type variant%'s %<TYPE_SIZE_UNIT%>");
debug_tree (TYPE_SIZE_UNIT (tv));
- error ("type%'s TYPE_SIZE_UNIT");
+ error ("type%'s %<TYPE_SIZE_UNIT%>");
debug_tree (TYPE_SIZE_UNIT (t));
return false;
}
@@ -13874,10 +13896,13 @@ verify_type_variant (const_tree t, tree tv)
Ada also builds variants of types with different TYPE_CONTEXT. */
if ((!in_lto_p || !TYPE_FILE_SCOPE_P (t)) && 0)
verify_variant_match (TYPE_CONTEXT);
- verify_variant_match (TYPE_STRING_FLAG);
+ if (TREE_CODE (t) == ARRAY_TYPE || TREE_CODE (t) == INTEGER_TYPE)
+ verify_variant_match (TYPE_STRING_FLAG);
+ if (TREE_CODE (t) == RECORD_TYPE || TREE_CODE (t) == UNION_TYPE)
+ verify_variant_match (TYPE_CXX_ODR_P);
if (TYPE_ALIAS_SET_KNOWN_P (t))
{
- error ("type variant with TYPE_ALIAS_SET_KNOWN_P");
+ error ("type variant with %<TYPE_ALIAS_SET_KNOWN_P%>");
debug_tree (tv);
return false;
}
@@ -13890,7 +13915,7 @@ verify_type_variant (const_tree t, tree tv)
&& (in_lto_p || !TYPE_VFIELD (tv)
|| TREE_CODE (TYPE_VFIELD (tv)) != TREE_LIST))
{
- error ("type variant has different TYPE_VFIELD");
+ error ("type variant has different %<TYPE_VFIELD%>");
debug_tree (tv);
return false;
}
@@ -13926,11 +13951,11 @@ verify_type_variant (const_tree t, tree tv)
at LTO time only. */
&& (in_lto_p && odr_type_p (t)))
{
- error ("type variant has different TYPE_BINFO");
+ error ("type variant has different %<TYPE_BINFO%>");
debug_tree (tv);
- error ("type variant%'s TYPE_BINFO");
+ error ("type variant%'s %<TYPE_BINFO%>");
debug_tree (TYPE_BINFO (tv));
- error ("type%'s TYPE_BINFO");
+ error ("type%'s %<TYPE_BINFO%>");
debug_tree (TYPE_BINFO (t));
return false;
}
@@ -13969,7 +13994,7 @@ verify_type_variant (const_tree t, tree tv)
break;
if (f1 || f2)
{
- error ("type variant has different TYPE_FIELDS");
+ error ("type variant has different %<TYPE_FIELDS%>");
debug_tree (tv);
error ("first mismatch is field");
debug_tree (f1);
@@ -13990,11 +14015,11 @@ verify_type_variant (const_tree t, tree tv)
|| TYPE_MAIN_VARIANT (TREE_TYPE (t))
!= TYPE_MAIN_VARIANT (TREE_TYPE (tv))))
{
- error ("type variant has different TREE_TYPE");
+ error ("type variant has different %<TREE_TYPE%>");
debug_tree (tv);
- error ("type variant%'s TREE_TYPE");
+ error ("type variant%'s %<TREE_TYPE%>");
debug_tree (TREE_TYPE (tv));
- error ("type%'s TREE_TYPE");
+ error ("type%'s %<TREE_TYPE%>");
debug_tree (TREE_TYPE (t));
return false;
}
@@ -14003,9 +14028,9 @@ verify_type_variant (const_tree t, tree tv)
{
error ("type is not compatible with its variant");
debug_tree (tv);
- error ("type variant%'s TREE_TYPE");
+ error ("type variant%'s %<TREE_TYPE%>");
debug_tree (TREE_TYPE (tv));
- error ("type%'s TREE_TYPE");
+ error ("type%'s %<TREE_TYPE%>");
debug_tree (TREE_TYPE (t));
return false;
}
@@ -14085,6 +14110,7 @@ gimple_canonical_types_compatible_p (const_tree t1, const_tree t2,
gcc_assert (!trust_type_canonical
|| (type_with_alias_set_p (t1) && type_with_alias_set_p (t2)));
+
/* If the types have been previously registered and found equal
they still are. */
@@ -14102,6 +14128,14 @@ gimple_canonical_types_compatible_p (const_tree t1, const_tree t2,
return TYPE_CANONICAL (t1) == TYPE_CANONICAL (t2);
}
+ /* For types where we do ODR based TBAA the canonical type is always
+ set correctly, so we know that types are different if their
+ canonical types does not match. */
+ if (trust_type_canonical
+ && (odr_type_p (t1) && odr_based_tbaa_p (t1))
+ != (odr_type_p (t2) && odr_based_tbaa_p (t2)))
+ return false;
+
/* Can't be the same type if the types don't have the same code. */
enum tree_code code = tree_code_for_canonical_type_merging (TREE_CODE (t1));
if (code != tree_code_for_canonical_type_merging (TREE_CODE (t2)))
@@ -14304,12 +14338,12 @@ verify_type (const_tree t)
tree mv = TYPE_MAIN_VARIANT (t);
if (!mv)
{
- error ("Main variant is not defined");
+ error ("main variant is not defined");
error_found = true;
}
else if (mv != TYPE_MAIN_VARIANT (mv))
{
- error ("TYPE_MAIN_VARIANT has different TYPE_MAIN_VARIANT");
+ error ("%<TYPE_MAIN_VARIANT%> has different %<TYPE_MAIN_VARIANT%>");
debug_tree (mv);
error_found = true;
}
@@ -14321,7 +14355,7 @@ verify_type (const_tree t)
;
else if (TYPE_CANONICAL (t) != ct)
{
- error ("TYPE_CANONICAL has different TYPE_CANONICAL");
+ error ("%<TYPE_CANONICAL%> has different %<TYPE_CANONICAL%>");
debug_tree (ct);
error_found = true;
}
@@ -14340,7 +14374,7 @@ verify_type (const_tree t)
&& !gimple_canonical_types_compatible_p (t, ct, false)
&& COMPLETE_TYPE_P (t))
{
- error ("TYPE_CANONICAL is not compatible");
+ error ("%<TYPE_CANONICAL%> is not compatible");
debug_tree (ct);
error_found = true;
}
@@ -14348,13 +14382,13 @@ verify_type (const_tree t)
if (COMPLETE_TYPE_P (t) && TYPE_CANONICAL (t)
&& TYPE_MODE (t) != TYPE_MODE (TYPE_CANONICAL (t)))
{
- error ("TYPE_MODE of TYPE_CANONICAL is not compatible");
+ error ("%<TYPE_MODE%> of %<TYPE_CANONICAL%> is not compatible");
debug_tree (ct);
error_found = true;
}
if (TYPE_MAIN_VARIANT (t) == t && ct && TYPE_MAIN_VARIANT (ct) != ct)
{
- error ("TYPE_CANONICAL of main variant is not main variant");
+ error ("%<TYPE_CANONICAL%> of main variant is not main variant");
debug_tree (ct);
debug_tree (TYPE_MAIN_VARIANT (ct));
error_found = true;
@@ -14370,7 +14404,7 @@ verify_type (const_tree t)
&& TREE_CODE (TYPE_VFIELD (t)) != FIELD_DECL
&& TREE_CODE (TYPE_VFIELD (t)) != TREE_LIST)
{
- error ("TYPE_VFIELD is not FIELD_DECL nor TREE_LIST");
+ error ("%<TYPE_VFIELD%> is not %<FIELD_DECL%> nor %<TREE_LIST%>");
debug_tree (TYPE_VFIELD (t));
error_found = true;
}
@@ -14380,7 +14414,7 @@ verify_type (const_tree t)
if (TYPE_NEXT_PTR_TO (t)
&& TREE_CODE (TYPE_NEXT_PTR_TO (t)) != POINTER_TYPE)
{
- error ("TYPE_NEXT_PTR_TO is not POINTER_TYPE");
+ error ("%<TYPE_NEXT_PTR_TO%> is not %<POINTER_TYPE%>");
debug_tree (TYPE_NEXT_PTR_TO (t));
error_found = true;
}
@@ -14390,7 +14424,7 @@ verify_type (const_tree t)
if (TYPE_NEXT_REF_TO (t)
&& TREE_CODE (TYPE_NEXT_REF_TO (t)) != REFERENCE_TYPE)
{
- error ("TYPE_NEXT_REF_TO is not REFERENCE_TYPE");
+ error ("%<TYPE_NEXT_REF_TO%> is not %<REFERENCE_TYPE%>");
debug_tree (TYPE_NEXT_REF_TO (t));
error_found = true;
}
@@ -14411,13 +14445,13 @@ verify_type (const_tree t)
;
else if (TREE_CODE (TYPE_BINFO (t)) != TREE_BINFO)
{
- error ("TYPE_BINFO is not TREE_BINFO");
+ error ("%<TYPE_BINFO%> is not %<TREE_BINFO%>");
debug_tree (TYPE_BINFO (t));
error_found = true;
}
else if (TREE_TYPE (TYPE_BINFO (t)) != TYPE_MAIN_VARIANT (t))
{
- error ("TYPE_BINFO type is not TYPE_MAIN_VARIANT");
+ error ("%<TYPE_BINFO%> type is not %<TYPE_MAIN_VARIANT%>");
debug_tree (TREE_TYPE (TYPE_BINFO (t)));
error_found = true;
}
@@ -14428,7 +14462,7 @@ verify_type (const_tree t)
&& TREE_CODE (TYPE_METHOD_BASETYPE (t)) != RECORD_TYPE
&& TREE_CODE (TYPE_METHOD_BASETYPE (t)) != UNION_TYPE)
{
- error ("TYPE_METHOD_BASETYPE is not record nor union");
+ error ("%<TYPE_METHOD_BASETYPE%> is not record nor union");
debug_tree (TYPE_METHOD_BASETYPE (t));
error_found = true;
}
@@ -14439,7 +14473,7 @@ verify_type (const_tree t)
&& TREE_CODE (TYPE_OFFSET_BASETYPE (t)) != RECORD_TYPE
&& TREE_CODE (TYPE_OFFSET_BASETYPE (t)) != UNION_TYPE)
{
- error ("TYPE_OFFSET_BASETYPE is not record nor union");
+ error ("%<TYPE_OFFSET_BASETYPE%> is not record nor union");
debug_tree (TYPE_OFFSET_BASETYPE (t));
error_found = true;
}
@@ -14457,21 +14491,21 @@ verify_type (const_tree t)
if (TYPE_ARRAY_MAX_SIZE (t)
&& TREE_CODE (TYPE_ARRAY_MAX_SIZE (t)) != INTEGER_CST)
{
- error ("TYPE_ARRAY_MAX_SIZE not INTEGER_CST");
+ error ("%<TYPE_ARRAY_MAX_SIZE%> not %<INTEGER_CST%>");
debug_tree (TYPE_ARRAY_MAX_SIZE (t));
error_found = true;
}
}
else if (TYPE_MAX_VALUE_RAW (t))
{
- error ("TYPE_MAX_VALUE_RAW non-NULL");
+ error ("%<TYPE_MAX_VALUE_RAW%> non-NULL");
debug_tree (TYPE_MAX_VALUE_RAW (t));
error_found = true;
}
if (TYPE_LANG_SLOT_1 (t) && in_lto_p)
{
- error ("TYPE_LANG_SLOT_1 (binfo) field is non-NULL");
+ error ("%<TYPE_LANG_SLOT_1 (binfo)%> field is non-NULL");
debug_tree (TYPE_LANG_SLOT_1 (t));
error_found = true;
}
@@ -14487,7 +14521,7 @@ verify_type (const_tree t)
CONST_DECL of ENUMERAL TYPE. */
if (TREE_CODE (value) != INTEGER_CST && TREE_CODE (value) != CONST_DECL)
{
- error ("Enum value is not CONST_DECL or INTEGER_CST");
+ error ("enum value is not %<CONST_DECL%> or %<INTEGER_CST%>");
debug_tree (value);
debug_tree (name);
error_found = true;
@@ -14495,14 +14529,15 @@ verify_type (const_tree t)
if (TREE_CODE (TREE_TYPE (value)) != INTEGER_TYPE
&& !useless_type_conversion_p (const_cast <tree> (t), TREE_TYPE (value)))
{
- error ("Enum value type is not INTEGER_TYPE nor convertible to the enum");
+ error ("enum value type is not %<INTEGER_TYPE%> nor convertible "
+ "to the enum");
debug_tree (value);
debug_tree (name);
error_found = true;
}
if (TREE_CODE (name) != IDENTIFIER_NODE)
{
- error ("Enum value name is not IDENTIFIER_NODE");
+ error ("enum value name is not %<IDENTIFIER_NODE%>");
debug_tree (value);
debug_tree (name);
error_found = true;
@@ -14512,7 +14547,7 @@ verify_type (const_tree t)
{
if (TYPE_DOMAIN (t) && TREE_CODE (TYPE_DOMAIN (t)) != INTEGER_TYPE)
{
- error ("Array TYPE_DOMAIN is not integer type");
+ error ("array %<TYPE_DOMAIN%> is not integer type");
debug_tree (TYPE_DOMAIN (t));
error_found = true;
}
@@ -14521,7 +14556,7 @@ verify_type (const_tree t)
{
if (TYPE_FIELDS (t) && !COMPLETE_TYPE_P (t) && in_lto_p)
{
- error ("TYPE_FIELDS defined in incomplete type");
+ error ("%<TYPE_FIELDS%> defined in incomplete type");
error_found = true;
}
for (tree fld = TYPE_FIELDS (t); fld; fld = TREE_CHAIN (fld))
@@ -14543,7 +14578,7 @@ verify_type (const_tree t)
;
else
{
- error ("Wrong tree in TYPE_FIELDS list");
+ error ("wrong tree in %<TYPE_FIELDS%> list");
debug_tree (fld);
error_found = true;
}
@@ -14558,13 +14593,14 @@ verify_type (const_tree t)
{
if (TYPE_CACHED_VALUES_P (t) != (TYPE_CACHED_VALUES (t) != NULL))
{
- error ("TYPE_CACHED_VALUES_P is %i while TYPE_CACHED_VALUES is %p",
+ error ("%<TYPE_CACHED_VALUES_P%> is %i while %<TYPE_CACHED_VALUES%> "
+ "is %p",
TYPE_CACHED_VALUES_P (t), (void *)TYPE_CACHED_VALUES (t));
error_found = true;
}
else if (TYPE_CACHED_VALUES_P (t) && TREE_CODE (TYPE_CACHED_VALUES (t)) != TREE_VEC)
{
- error ("TYPE_CACHED_VALUES is not TREE_VEC");
+ error ("%<TYPE_CACHED_VALUES%> is not %<TREE_VEC%>");
debug_tree (TYPE_CACHED_VALUES (t));
error_found = true;
}
@@ -14577,7 +14613,7 @@ verify_type (const_tree t)
if (TREE_VEC_ELT (TYPE_CACHED_VALUES (t), i)
&& TREE_TYPE (TREE_VEC_ELT (TYPE_CACHED_VALUES (t), i)) != t)
{
- error ("wrong TYPE_CACHED_VALUES entry");
+ error ("wrong %<TYPE_CACHED_VALUES%> entry");
debug_tree (TREE_VEC_ELT (TYPE_CACHED_VALUES (t), i));
error_found = true;
break;
@@ -14590,20 +14626,20 @@ verify_type (const_tree t)
/* C++ FE uses TREE_PURPOSE to store initial values. */
if (TREE_PURPOSE (l) && in_lto_p)
{
- error ("TREE_PURPOSE is non-NULL in TYPE_ARG_TYPES list");
+ error ("%<TREE_PURPOSE%> is non-NULL in %<TYPE_ARG_TYPES%> list");
debug_tree (l);
error_found = true;
}
if (!TYPE_P (TREE_VALUE (l)))
{
- error ("Wrong entry in TYPE_ARG_TYPES list");
+ error ("wrong entry in %<TYPE_ARG_TYPES%> list");
debug_tree (l);
error_found = true;
}
}
else if (!is_lang_specific (t) && TYPE_VALUES_RAW (t))
{
- error ("TYPE_VALUES_RAW field is non-NULL");
+ error ("%<TYPE_VALUES_RAW%> field is non-NULL");
debug_tree (TYPE_VALUES_RAW (t));
error_found = true;
}
@@ -14615,13 +14651,7 @@ verify_type (const_tree t)
&& TREE_CODE (t) != POINTER_TYPE
&& TYPE_CACHED_VALUES_P (t))
{
- error ("TYPE_CACHED_VALUES_P is set while it should not");
- error_found = true;
- }
- if (TYPE_STRING_FLAG (t)
- && TREE_CODE (t) != ARRAY_TYPE && TREE_CODE (t) != INTEGER_TYPE)
- {
- error ("TYPE_STRING_FLAG is set on wrong type code");
+ error ("%<TYPE_CACHED_VALUES_P%> is set while it should not be");
error_found = true;
}
@@ -14631,14 +14661,14 @@ verify_type (const_tree t)
if (TREE_CODE (t) == METHOD_TYPE
&& TYPE_MAIN_VARIANT (TYPE_METHOD_BASETYPE (t)) != TYPE_METHOD_BASETYPE (t))
{
- error ("TYPE_METHOD_BASETYPE is not main variant");
+ error ("%<TYPE_METHOD_BASETYPE%> is not main variant");
error_found = true;
}
if (error_found)
{
debug_tree (const_cast <tree> (t));
- internal_error ("verify_type failed");
+ internal_error ("%qs failed", __func__);
}
}
diff --git a/gcc/tree.def b/gcc/tree.def
index 1d6dded..10a14fc 100644
--- a/gcc/tree.def
+++ b/gcc/tree.def
@@ -1191,6 +1191,11 @@ DEFTREECODE (OMP_SINGLE, "omp_single", tcc_statement, 2)
Operand 1: OMP_SINGLE_CLAUSES: List of clauses. */
DEFTREECODE (OMP_TASKGROUP, "omp_taskgroup", tcc_statement, 2)
+/* OpenMP - #pragma omp scan
+ Operand 0: OMP_SCAN_BODY: Scan body.
+ Operand 1: OMP_SCAN_CLAUSES: List of clauses. */
+DEFTREECODE (OMP_SCAN, "omp_scan", tcc_statement, 2)
+
/* OpenMP - #pragma omp section
Operand 0: OMP_SECTION_BODY: Section body. */
DEFTREECODE (OMP_SECTION, "omp_section", tcc_statement, 1)
diff --git a/gcc/tree.h b/gcc/tree.h
index d65affe..3dce602 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -439,6 +439,8 @@ extern void omp_clause_range_check_failed (const_tree, const char *, int,
TREE_CHECK3 (T, RECORD_TYPE, UNION_TYPE, QUAL_UNION_TYPE)
#define NOT_RECORD_OR_UNION_CHECK(T) \
TREE_NOT_CHECK3 (T, RECORD_TYPE, UNION_TYPE, QUAL_UNION_TYPE)
+#define ARRAY_OR_INTEGER_TYPE_CHECK(T) \
+ TREE_CHECK2 (T, ARRAY_TYPE, INTEGER_TYPE)
#define NUMERICAL_TYPE_CHECK(T) \
TREE_CHECK5 (T, INTEGER_TYPE, ENUMERAL_TYPE, BOOLEAN_TYPE, REAL_TYPE, \
@@ -904,6 +906,11 @@ extern void omp_clause_range_check_failed (const_tree, const char *, int,
(TREE_CHECK2 (NODE, VAR_DECL, \
RESULT_DECL)->decl_common.decl_nonshareable_flag)
+/* In a PARM_DECL, set for Fortran hidden string length arguments that some
+ buggy callers don't pass to the callee. */
+#define DECL_HIDDEN_STRING_LENGTH(NODE) \
+ (TREE_CHECK (NODE, PARM_DECL)->decl_common.decl_nonshareable_flag)
+
/* In a CALL_EXPR, means that the call is the jump from a thunk to the
thunked-to function. */
#define CALL_FROM_THUNK_P(NODE) (CALL_EXPR_CHECK (NODE)->base.protected_flag)
@@ -927,6 +934,11 @@ extern void omp_clause_range_check_failed (const_tree, const char *, int,
#define TREE_DEPRECATED(NODE) \
((NODE)->base.deprecated_flag)
+/* Nonzero indicates an IDENTIFIER_NODE that names an anonymous
+ aggregate, (as created by anon_aggr_name_format). */
+#define IDENTIFIER_ANON_P(NODE) \
+ (IDENTIFIER_NODE_CHECK (NODE)->base.private_flag)
+
/* Nonzero in an IDENTIFIER_NODE if the name is a local alias, whose
uses are to be substituted for uses of the TREE_CHAINed identifier. */
#define IDENTIFIER_TRANSPARENT_ALIAS(NODE) \
@@ -1334,7 +1346,7 @@ class auto_suppress_location_wrappers
#define OMP_BODY(NODE) \
TREE_OPERAND (TREE_RANGE_CHECK (NODE, OACC_PARALLEL, OMP_MASTER), 0)
#define OMP_CLAUSES(NODE) \
- TREE_OPERAND (TREE_RANGE_CHECK (NODE, OACC_PARALLEL, OMP_TASKGROUP), 1)
+ TREE_OPERAND (TREE_RANGE_CHECK (NODE, OACC_PARALLEL, OMP_SCAN), 1)
/* Generic accessors for OMP nodes that keep clauses as operand 0. */
#define OMP_STANDALONE_CLAUSES(NODE) \
@@ -1425,6 +1437,9 @@ class auto_suppress_location_wrappers
#define OMP_TARGET_EXIT_DATA_CLAUSES(NODE)\
TREE_OPERAND (OMP_TARGET_EXIT_DATA_CHECK (NODE), 0)
+#define OMP_SCAN_BODY(NODE) TREE_OPERAND (OMP_SCAN_CHECK (NODE), 0)
+#define OMP_SCAN_CLAUSES(NODE) TREE_OPERAND (OMP_SCAN_CHECK (NODE), 1)
+
#define OMP_CLAUSE_SIZE(NODE) \
OMP_CLAUSE_OPERAND (OMP_CLAUSE_RANGE_CHECK (OMP_CLAUSE_CHECK (NODE), \
OMP_CLAUSE_FROM, \
@@ -1434,7 +1449,7 @@ class auto_suppress_location_wrappers
#define OMP_CLAUSE_DECL(NODE) \
OMP_CLAUSE_OPERAND (OMP_CLAUSE_RANGE_CHECK (OMP_CLAUSE_CHECK (NODE), \
OMP_CLAUSE_PRIVATE, \
- OMP_CLAUSE__REDUCTEMP_), 0)
+ OMP_CLAUSE__SCANTEMP_), 0)
#define OMP_CLAUSE_HAS_LOCATION(NODE) \
(LOCATION_LOCUS ((OMP_CLAUSE_CHECK (NODE))->omp_clause.locus) \
!= UNKNOWN_LOCATION)
@@ -1742,6 +1757,21 @@ class auto_suppress_location_wrappers
#define OMP_CLAUSE__GRIDDIM__GROUP(NODE) \
OMP_CLAUSE_OPERAND (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE__GRIDDIM_), 1)
+/* _CONDTEMP_ holding temporary with iteration count. */
+#define OMP_CLAUSE__CONDTEMP__ITER(NODE) \
+ (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE__CONDTEMP_)->base.public_flag)
+
+/* _SCANTEMP_ holding temporary with pointer to thread's local array;
+ allocation. */
+#define OMP_CLAUSE__SCANTEMP__ALLOC(NODE) \
+ (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE__SCANTEMP_)->base.public_flag)
+
+/* _SCANTEMP_ holding temporary with a control variable for deallocation;
+ one boolean_type_node for test whether alloca was used, another one
+ to pass to __builtin_stack_restore or free. */
+#define OMP_CLAUSE__SCANTEMP__CONTROL(NODE) \
+ TREE_PRIVATE (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE__SCANTEMP_))
+
/* SSA_NAME accessors. */
/* Whether SSA_NAME NODE is a virtual operand. This simply caches the
@@ -2101,7 +2131,14 @@ extern machine_mode vector_type_mode (const_tree);
/* If set in an ARRAY_TYPE, indicates a string type (for languages
that distinguish string from array of char).
If set in a INTEGER_TYPE, indicates a character type. */
-#define TYPE_STRING_FLAG(NODE) (TYPE_CHECK (NODE)->type_common.string_flag)
+#define TYPE_STRING_FLAG(NODE) \
+ (ARRAY_OR_INTEGER_TYPE_CHECK (NODE)->type_common.string_flag)
+
+/* If set for RECORD_TYPE or UNION_TYPE it indicates that the type conforms
+ to the C++ one definition rule. This is used for LTO canonical type
+ computation. */
+#define TYPE_CXX_ODR_P(NODE) \
+ (RECORD_OR_UNION_CHECK (NODE)->type_common.string_flag)
/* Nonzero in a VECTOR_TYPE if the frontends should not emit warnings
about missing conversions to other vector types of the same size. */
@@ -4057,6 +4094,11 @@ tree_strip_any_location_wrapper (tree exp)
#define current_target_pragma global_trees[TI_CURRENT_TARGET_PRAGMA]
#define current_optimize_pragma global_trees[TI_CURRENT_OPTIMIZE_PRAGMA]
+/* SCEV analyzer global shared trees. */
+#define chrec_not_analyzed_yet NULL_TREE
+#define chrec_dont_know global_trees[TI_CHREC_DONT_KNOW]
+#define chrec_known global_trees[TI_CHREC_KNOWN]
+
#define char_type_node integer_types[itk_char]
#define signed_char_type_node integer_types[itk_signed_char]
#define unsigned_char_type_node integer_types[itk_unsigned_char]
@@ -4230,7 +4272,7 @@ extern tree build_vec_series (tree, tree, tree);
extern tree build_index_vector (tree, poly_uint64, poly_uint64);
extern void recompute_constructor_flags (tree);
extern void verify_constructor_flags (tree);
-extern tree build_constructor (tree, vec<constructor_elt, va_gc> *);
+extern tree build_constructor (tree, vec<constructor_elt, va_gc> * CXX_MEM_STAT_INFO);
extern tree build_constructor_single (tree, tree, tree);
extern tree build_constructor_from_list (tree, tree);
extern tree build_constructor_va (tree, int, ...);
@@ -5436,9 +5478,9 @@ target_opts_for_fn (const_tree fndecl)
/* For anonymous aggregate types, we need some sort of name to
hold on to. In practice, this should not appear, but it should
- not be harmful if it does. */
-extern const char *anon_aggrname_format();
-extern bool anon_aggrname_p (const_tree);
+ not be harmful if it does. Identifiers returned will be
+ IDENTIFIER_ANON_P. */
+extern tree make_anon_name ();
/* The tree and const_tree overload templates. */
namespace wi
diff --git a/gcc/value-prof.c b/gcc/value-prof.c
index 5013956..66c4bba 100644
--- a/gcc/value-prof.c
+++ b/gcc/value-prof.c
@@ -228,109 +228,77 @@ dump_histogram_value (FILE *dump_file, histogram_value hist)
switch (hist->type)
{
case HIST_TYPE_INTERVAL:
- fprintf (dump_file, "Interval counter range %d -- %d",
- hist->hdata.intvl.int_start,
- (hist->hdata.intvl.int_start
- + hist->hdata.intvl.steps - 1));
if (hist->hvalue.counters)
{
- unsigned int i;
- fprintf (dump_file, " [");
- for (i = 0; i < hist->hdata.intvl.steps; i++)
- fprintf (dump_file, " %d:%" PRId64,
- hist->hdata.intvl.int_start + i,
- (int64_t) hist->hvalue.counters[i]);
- fprintf (dump_file, " ] outside range:%" PRId64,
- (int64_t) hist->hvalue.counters[i]);
+ fprintf (dump_file, "Interval counter range [%d,%d]: [",
+ hist->hdata.intvl.int_start,
+ (hist->hdata.intvl.int_start
+ + hist->hdata.intvl.steps - 1));
+
+ unsigned int i;
+ for (i = 0; i < hist->hdata.intvl.steps; i++)
+ {
+ fprintf (dump_file, "%d:%" PRId64,
+ hist->hdata.intvl.int_start + i,
+ (int64_t) hist->hvalue.counters[i]);
+ if (i != hist->hdata.intvl.steps - 1)
+ fprintf (dump_file, ", ");
+ }
+ fprintf (dump_file, "] outside range: %" PRId64 ".\n",
+ (int64_t) hist->hvalue.counters[i]);
}
- fprintf (dump_file, ".\n");
break;
case HIST_TYPE_POW2:
- fprintf (dump_file, "Pow2 counter ");
if (hist->hvalue.counters)
- {
- fprintf (dump_file, "pow2:%" PRId64
- " nonpow2:%" PRId64,
- (int64_t) hist->hvalue.counters[1],
- (int64_t) hist->hvalue.counters[0]);
- }
- fprintf (dump_file, ".\n");
+ fprintf (dump_file, "Pow2 counter pow2:%" PRId64
+ " nonpow2:%" PRId64 ".\n",
+ (int64_t) hist->hvalue.counters[1],
+ (int64_t) hist->hvalue.counters[0]);
break;
- case HIST_TYPE_SINGLE_VALUE:
- fprintf (dump_file, "Single value ");
+ case HIST_TYPE_TOPN_VALUES:
+ case HIST_TYPE_INDIR_CALL:
if (hist->hvalue.counters)
{
- fprintf (dump_file, "value:%" PRId64
- " match:%" PRId64
- " wrong:%" PRId64,
- (int64_t) hist->hvalue.counters[0],
- (int64_t) hist->hvalue.counters[1],
- (int64_t) hist->hvalue.counters[2]);
+ fprintf (dump_file,
+ (hist->type == HIST_TYPE_TOPN_VALUES
+ ? "Top N value counter " : "Indirect call counter"));
+ if (hist->hvalue.counters)
+ {
+ fprintf (dump_file, "all: %" PRId64 ", values: ",
+ (int64_t) hist->hvalue.counters[0]);
+ for (unsigned i = 0; i < GCOV_TOPN_VALUES; i++)
+ {
+ fprintf (dump_file, "[%" PRId64 ":%" PRId64 "]",
+ (int64_t) hist->hvalue.counters[2 * i + 1],
+ (int64_t) hist->hvalue.counters[2 * i + 2]);
+ if (i != GCOV_TOPN_VALUES - 1)
+ fprintf (dump_file, ", ");
+ }
+ fprintf (dump_file, ".\n");
+ }
}
- fprintf (dump_file, ".\n");
break;
case HIST_TYPE_AVERAGE:
- fprintf (dump_file, "Average value ");
if (hist->hvalue.counters)
- {
- fprintf (dump_file, "sum:%" PRId64
- " times:%" PRId64,
- (int64_t) hist->hvalue.counters[0],
- (int64_t) hist->hvalue.counters[1]);
- }
- fprintf (dump_file, ".\n");
+ fprintf (dump_file, "Average value sum:%" PRId64
+ " times:%" PRId64 ".\n",
+ (int64_t) hist->hvalue.counters[0],
+ (int64_t) hist->hvalue.counters[1]);
break;
case HIST_TYPE_IOR:
- fprintf (dump_file, "IOR value ");
if (hist->hvalue.counters)
- {
- fprintf (dump_file, "ior:%" PRId64,
- (int64_t) hist->hvalue.counters[0]);
- }
- fprintf (dump_file, ".\n");
+ fprintf (dump_file, "IOR value ior:%" PRId64 ".\n",
+ (int64_t) hist->hvalue.counters[0]);
break;
- case HIST_TYPE_INDIR_CALL:
- fprintf (dump_file, "Indirect call ");
- if (hist->hvalue.counters)
- {
- fprintf (dump_file, "value:%" PRId64
- " match:%" PRId64
- " all:%" PRId64,
- (int64_t) hist->hvalue.counters[0],
- (int64_t) hist->hvalue.counters[1],
- (int64_t) hist->hvalue.counters[2]);
- }
- fprintf (dump_file, ".\n");
- break;
case HIST_TYPE_TIME_PROFILE:
- fprintf (dump_file, "Time profile ");
if (hist->hvalue.counters)
- {
- fprintf (dump_file, "time:%" PRId64,
- (int64_t) hist->hvalue.counters[0]);
- }
- fprintf (dump_file, ".\n");
- break;
- case HIST_TYPE_INDIR_CALL_TOPN:
- fprintf (dump_file, "Indirect call topn ");
- if (hist->hvalue.counters)
- {
- int i;
-
- fprintf (dump_file, "accu:%" PRId64, hist->hvalue.counters[0]);
- for (i = 1; i < (GCOV_ICALL_TOPN_VAL << 2); i += 2)
- {
- fprintf (dump_file, " target:%" PRId64 " value:%" PRId64,
- (int64_t) hist->hvalue.counters[i],
- (int64_t) hist->hvalue.counters[i+1]);
- }
- }
- fprintf (dump_file, ".\n");
+ fprintf (dump_file, "Time profile time:%" PRId64 ".\n",
+ (int64_t) hist->hvalue.counters[0]);
break;
case HIST_TYPE_MAX:
gcc_unreachable ();
@@ -363,7 +331,7 @@ stream_out_histogram_value (struct output_block *ob, histogram_value hist)
/* When user uses an unsigned type with a big value, constant converted
to gcov_type (a signed type) can be negative. */
gcov_type value = hist->hvalue.counters[i];
- if (hist->type == HIST_TYPE_SINGLE_VALUE && i == 0)
+ if (hist->type == HIST_TYPE_TOPN_VALUES && i > 0)
;
else
gcc_assert (value >= 0);
@@ -406,9 +374,9 @@ stream_in_histogram_value (struct lto_input_block *ib, gimple *stmt)
ncounters = 2;
break;
- case HIST_TYPE_SINGLE_VALUE:
+ case HIST_TYPE_TOPN_VALUES:
case HIST_TYPE_INDIR_CALL:
- ncounters = 3;
+ ncounters = GCOV_TOPN_VALUES_COUNTERS;
break;
case HIST_TYPE_IOR:
@@ -416,10 +384,6 @@ stream_in_histogram_value (struct lto_input_block *ib, gimple *stmt)
ncounters = 1;
break;
- case HIST_TYPE_INDIR_CALL_TOPN:
- ncounters = (GCOV_ICALL_TOPN_VAL << 2) + 1;
- break;
-
case HIST_TYPE_MAX:
gcc_unreachable ();
}
@@ -535,7 +499,7 @@ verify_histograms (void)
{
if (hist->hvalue.stmt != stmt)
{
- error ("Histogram value statement does not correspond to "
+ error ("histogram value statement does not correspond to "
"the statement it is associated with");
debug_gimple_stmt (stmt);
dump_histogram_value (stderr, hist);
@@ -547,7 +511,7 @@ verify_histograms (void)
if (VALUE_HISTOGRAMS (cfun))
htab_traverse (VALUE_HISTOGRAMS (cfun), visit_hist, &visited_hists);
if (error_found)
- internal_error ("verify_histograms failed");
+ internal_error ("%qs failed", __func__);
}
/* Helper function for verify_histograms. For each histogram reachable via htab
@@ -749,6 +713,48 @@ gimple_divmod_fixed_value (gassign *stmt, tree value, profile_probability prob,
return tmp2;
}
+/* Return most common value of TOPN_VALUE histogram. If
+ there's a unique value, return true and set VALUE and COUNT
+ arguments. */
+
+bool
+get_most_common_single_value (gimple *stmt, const char *counter_type,
+ histogram_value hist,
+ gcov_type *value, gcov_type *count,
+ gcov_type *all)
+{
+ if (hist->hvalue.counters[2] == -1)
+ return false;
+
+ *count = 0;
+ *value = 0;
+
+ gcov_type read_all = hist->hvalue.counters[0];
+
+ for (unsigned i = 0; i < GCOV_TOPN_VALUES; i++)
+ {
+ gcov_type v = hist->hvalue.counters[2 * i + 1];
+ gcov_type c = hist->hvalue.counters[2 * i + 2];
+
+ /* Indirect calls can't be vereified. */
+ if (stmt && check_counter (stmt, counter_type, &c, &read_all,
+ gimple_bb (stmt)->count))
+ return false;
+
+ *all = read_all;
+
+ if (c > *count)
+ {
+ *value = v;
+ *count = c;
+ }
+ else if (c == *count && v > *value)
+ *value = v;
+ }
+
+ return true;
+}
+
/* Do transform 1) on INSN if applicable. */
static bool
@@ -774,27 +780,23 @@ gimple_divmod_fixed_value_transform (gimple_stmt_iterator *si)
return false;
histogram = gimple_histogram_value_of_type (cfun, stmt,
- HIST_TYPE_SINGLE_VALUE);
+ HIST_TYPE_TOPN_VALUES);
if (!histogram)
return false;
+ if (!get_most_common_single_value (stmt, "divmod", histogram, &val, &count,
+ &all))
+ return false;
+
value = histogram->hvalue.value;
- val = histogram->hvalue.counters[0];
- count = histogram->hvalue.counters[1];
- all = histogram->hvalue.counters[2];
gimple_remove_histogram_value (cfun, stmt, histogram);
- /* We require that count is at least half of all; this means
- that for the transformation to fire the value must be constant
- at least 50% of time (and 75% gives the guarantee of usage). */
+ /* We require that count is at least half of all. */
if (simple_cst_equal (gimple_assign_rhs2 (stmt), value) != 1
|| 2 * count < all
|| optimize_bb_for_size_p (gimple_bb (stmt)))
return false;
- if (check_counter (stmt, "value", &count, &all, gimple_bb (stmt)->count))
- return false;
-
/* Compute probability of taking the optimal path. */
if (all > 0)
prob = profile_probability::probability_in_gcov_type (count, all);
@@ -1113,7 +1115,6 @@ gimple_mod_subtract_transform (gimple_stmt_iterator *si)
count1 = histogram->hvalue.counters[0];
count2 = histogram->hvalue.counters[1];
- /* Compute probability of taking the optimal path. */
if (check_counter (stmt, "interval", &count1, &all, gimple_bb (stmt)->count))
{
gimple_remove_histogram_value (cfun, stmt, histogram);
@@ -1421,7 +1422,7 @@ gimple_ic_transform (gimple_stmt_iterator *gsi)
{
gcall *stmt;
histogram_value histogram;
- gcov_type val, count, all, bb_all;
+ gcov_type val, count, all;
struct cgraph_node *direct_call;
stmt = dyn_cast <gcall *> (gsi_stmt (*gsi));
@@ -1438,21 +1439,9 @@ gimple_ic_transform (gimple_stmt_iterator *gsi)
if (!histogram)
return false;
- val = histogram->hvalue.counters [0];
- count = histogram->hvalue.counters [1];
- all = histogram->hvalue.counters [2];
-
- bb_all = gimple_bb (stmt)->count.ipa ().to_gcov_type ();
- /* The order of CHECK_COUNTER calls is important -
- since check_counter can correct the third parameter
- and we want to make count <= all <= bb_all. */
- if (check_counter (stmt, "ic", &all, &bb_all, gimple_bb (stmt)->count)
- || check_counter (stmt, "ic", &count, &all,
- profile_count::from_gcov_type (all)))
- {
- gimple_remove_histogram_value (cfun, stmt, histogram);
- return false;
- }
+ if (!get_most_common_single_value (NULL, "indirect call", histogram, &val,
+ &count, &all))
+ return false;
if (4 * count <= 3 * all)
return false;
@@ -1664,19 +1653,19 @@ gimple_stringops_transform (gimple_stmt_iterator *gsi)
if (TREE_CODE (blck_size) == INTEGER_CST)
return false;
- histogram = gimple_histogram_value_of_type (cfun, stmt, HIST_TYPE_SINGLE_VALUE);
+ histogram = gimple_histogram_value_of_type (cfun, stmt,
+ HIST_TYPE_TOPN_VALUES);
if (!histogram)
return false;
- val = histogram->hvalue.counters[0];
- count = histogram->hvalue.counters[1];
- all = histogram->hvalue.counters[2];
+ if (!get_most_common_single_value (stmt, "stringops", histogram, &val,
+ &count, &all))
+ return false;
+
gimple_remove_histogram_value (cfun, stmt, histogram);
- /* We require that count is at least half of all; this means
- that for the transformation to fire the value must be constant
- at least 80% of time. */
- if ((6 * count / 5) < all || optimize_bb_for_size_p (gimple_bb (stmt)))
+ /* We require that count is at least half of all. */
+ if (2 * count < all || optimize_bb_for_size_p (gimple_bb (stmt)))
return false;
if (check_counter (stmt, "value", &count, &all, gimple_bb (stmt)->count))
return false;
@@ -1819,7 +1808,7 @@ gimple_divmod_values_to_profile (gimple *stmt, histogram_values *values)
/* Check for the case where the divisor is the same value most
of the time. */
values->quick_push (gimple_alloc_histogram_value (cfun,
- HIST_TYPE_SINGLE_VALUE,
+ HIST_TYPE_TOPN_VALUES,
stmt, divisor));
/* For mod, check whether it is not often a noop (or replaceable by
@@ -1865,12 +1854,8 @@ gimple_indirect_call_to_profile (gimple *stmt, histogram_values *values)
values->reserve (3);
- values->quick_push (gimple_alloc_histogram_value (
- cfun,
- PARAM_VALUE (PARAM_INDIR_CALL_TOPN_PROFILE) ?
- HIST_TYPE_INDIR_CALL_TOPN :
- HIST_TYPE_INDIR_CALL,
- stmt, callee));
+ values->quick_push (gimple_alloc_histogram_value (cfun, HIST_TYPE_INDIR_CALL,
+ stmt, callee));
return;
}
@@ -1902,7 +1887,7 @@ gimple_stringops_values_to_profile (gimple *gs, histogram_values *values)
if (TREE_CODE (blck_size) != INTEGER_CST)
{
values->safe_push (gimple_alloc_histogram_value (cfun,
- HIST_TYPE_SINGLE_VALUE,
+ HIST_TYPE_TOPN_VALUES,
stmt, blck_size));
values->safe_push (gimple_alloc_histogram_value (cfun, HIST_TYPE_AVERAGE,
stmt, blck_size));
@@ -1951,12 +1936,9 @@ gimple_find_values_to_profile (histogram_values *values)
hist->n_counters = 2;
break;
- case HIST_TYPE_SINGLE_VALUE:
- hist->n_counters = 3;
- break;
-
- case HIST_TYPE_INDIR_CALL:
- hist->n_counters = 3;
+ case HIST_TYPE_TOPN_VALUES:
+ case HIST_TYPE_INDIR_CALL:
+ hist->n_counters = GCOV_TOPN_VALUES_COUNTERS;
break;
case HIST_TYPE_TIME_PROFILE:
@@ -1971,10 +1953,6 @@ gimple_find_values_to_profile (histogram_values *values)
hist->n_counters = 1;
break;
- case HIST_TYPE_INDIR_CALL_TOPN:
- hist->n_counters = GCOV_ICALL_TOPN_NCOUNTS;
- break;
-
default:
gcc_unreachable ();
}
diff --git a/gcc/value-prof.h b/gcc/value-prof.h
index 1251fa9..9f69d7d 100644
--- a/gcc/value-prof.h
+++ b/gcc/value-prof.h
@@ -26,15 +26,12 @@ enum hist_type
HIST_TYPE_INTERVAL, /* Measures histogram of values inside a specified
interval. */
HIST_TYPE_POW2, /* Histogram of power of 2 values. */
- HIST_TYPE_SINGLE_VALUE, /* Tries to identify the value that is (almost)
- always constant. */
+ HIST_TYPE_TOPN_VALUES, /* Tries to identify the N most common values. */
HIST_TYPE_INDIR_CALL, /* Tries to identify the function that is (almost)
called in indirect call */
HIST_TYPE_AVERAGE, /* Compute average value (sum of all values). */
HIST_TYPE_IOR, /* Used to compute expected alignment. */
HIST_TYPE_TIME_PROFILE, /* Used for time profile */
- HIST_TYPE_INDIR_CALL_TOPN, /* Tries to identify the top N most frequently
- called functions in indirect call. */
HIST_TYPE_MAX
};
@@ -92,6 +89,10 @@ void free_histograms (function *);
void stringop_block_profile (gimple *, unsigned int *, HOST_WIDE_INT *);
gcall *gimple_ic (gcall *, struct cgraph_node *, profile_probability);
bool check_ic_target (gcall *, struct cgraph_node *);
+bool get_most_common_single_value (gimple *stmt, const char *counter_type,
+ histogram_value hist,
+ gcov_type *value, gcov_type *count,
+ gcov_type *all);
/* In tree-profile.c. */
@@ -99,7 +100,8 @@ extern void gimple_init_gcov_profiler (void);
extern void gimple_gen_edge_profiler (int, edge);
extern void gimple_gen_interval_profiler (histogram_value, unsigned, unsigned);
extern void gimple_gen_pow2_profiler (histogram_value, unsigned, unsigned);
-extern void gimple_gen_one_value_profiler (histogram_value, unsigned, unsigned);
+extern void gimple_gen_topn_values_profiler (histogram_value, unsigned,
+ unsigned);
extern void gimple_gen_ic_profiler (histogram_value, unsigned, unsigned);
extern void gimple_gen_ic_func_profiler (void);
extern void gimple_gen_time_profiler (unsigned, unsigned);
diff --git a/gcc/var-tracking.c b/gcc/var-tracking.c
index c9de934..c2b4204 100644
--- a/gcc/var-tracking.c
+++ b/gcc/var-tracking.c
@@ -8491,7 +8491,7 @@ vt_expand_loc_callback (rtx x, bitmap regs,
/* Invalid SUBREGs are ok in debug info. ??? We could try
alternate expansions for the VALUE as well. */
- if (!result)
+ if (!result && GET_MODE (subreg) != VOIDmode)
result = gen_rtx_raw_SUBREG (GET_MODE (x), subreg, SUBREG_BYTE (x));
return result;
diff --git a/gcc/varasm.c b/gcc/varasm.c
index cb43248..626a4c9 100644
--- a/gcc/varasm.c
+++ b/gcc/varasm.c
@@ -1878,7 +1878,9 @@ assemble_start_function (tree decl, const char *fnname)
if (patch_area_entry > patch_area_size)
{
if (patch_area_size > 0)
- warning (OPT_Wattributes, "patchable function entry > size");
+ warning (OPT_Wattributes,
+ "patchable function entry %wu exceeds size %wu",
+ patch_area_entry, patch_area_size);
patch_area_entry = 0;
}
@@ -5902,7 +5904,7 @@ do_assemble_alias (tree decl, tree target)
else
#endif
error_at (DECL_SOURCE_LOCATION (decl),
- "ifunc is not supported on this target");
+ "%qs is not supported on this target", "ifunc");
}
# ifdef ASM_OUTPUT_DEF_FROM_DECLS
@@ -5960,9 +5962,9 @@ assemble_alias (tree decl, tree target)
ultimate_transparent_alias_target (&target);
if (alias == target)
- error ("weakref %q+D ultimately targets itself", decl);
+ error ("%qs symbol %q+D ultimately targets itself", "weakref", decl);
if (TREE_PUBLIC (decl))
- error ("weakref %q+D must have static linkage", decl);
+ error ("%qs symbol %q+D must have static linkage", "weakref", decl);
}
else
{
@@ -5979,7 +5981,7 @@ assemble_alias (tree decl, tree target)
if (TREE_CODE (decl) == FUNCTION_DECL
&& lookup_attribute ("ifunc", DECL_ATTRIBUTES (decl)))
error_at (DECL_SOURCE_LOCATION (decl),
- "ifunc is not supported in this configuration");
+ "%qs is not supported in this configuration", "ifunc");
else
error_at (DECL_SOURCE_LOCATION (decl),
"only weak aliases are supported in this configuration");
diff --git a/gcc/vector-builder.h b/gcc/vector-builder.h
index 9967daa..9f95b01 100644
--- a/gcc/vector-builder.h
+++ b/gcc/vector-builder.h
@@ -96,6 +96,7 @@ public:
unsigned int encoded_nelts () const;
bool encoded_full_vector_p () const;
T elt (unsigned int) const;
+ unsigned int count_dups (int, int, int) const;
bool operator == (const Derived &) const;
bool operator != (const Derived &x) const { return !operator == (x); }
@@ -223,6 +224,23 @@ vector_builder<T, Derived>::elt (unsigned int i) const
derived ()->step (prev, final));
}
+/* Return the number of leading duplicate elements in the range
+ [START:END:STEP]. The value is always at least 1. */
+
+template<typename T, typename Derived>
+unsigned int
+vector_builder<T, Derived>::count_dups (int start, int end, int step) const
+{
+ gcc_assert ((end - start) % step == 0);
+
+ unsigned int ndups = 1;
+ for (int i = start + step;
+ i != end && derived ()->equal_p (elt (i), elt (start));
+ i += step)
+ ndups++;
+ return ndups;
+}
+
/* Change the encoding to NPATTERNS patterns of NELTS_PER_PATTERN each,
but without changing the underlying vector. */
diff --git a/gcc/vr-values.c b/gcc/vr-values.c
index 0e10aca..3f20c1a 100644
--- a/gcc/vr-values.c
+++ b/gcc/vr-values.c
@@ -118,7 +118,10 @@ vr_values::get_value_range (const_tree var)
if (POINTER_TYPE_P (TREE_TYPE (sym))
&& (nonnull_arg_p (sym)
|| get_ptr_nonnull (var)))
- vr->set_nonnull (TREE_TYPE (sym));
+ {
+ vr->set_nonzero (TREE_TYPE (sym));
+ vr->equiv_clear ();
+ }
else if (INTEGRAL_TYPE_P (TREE_TYPE (sym)))
{
get_range_info (var, *vr);
@@ -130,7 +133,10 @@ vr_values::get_value_range (const_tree var)
}
else if (TREE_CODE (sym) == RESULT_DECL
&& DECL_BY_REFERENCE (sym))
- vr->set_nonnull (TREE_TYPE (sym));
+ {
+ vr->set_nonzero (TREE_TYPE (sym));
+ vr->equiv_clear ();
+ }
}
return vr;
@@ -381,7 +387,10 @@ vr_values::op_with_constant_singleton_value_range (tree op)
if (TREE_CODE (op) != SSA_NAME)
return NULL_TREE;
- return value_range_constant_singleton (get_value_range (op));
+ tree t;
+ if (get_value_range (op)->singleton_p (&t))
+ return t;
+ return NULL;
}
/* Return true if op is in a boolean [0, 1] value-range. */
@@ -713,7 +722,8 @@ vr_values::extract_range_from_ssa_name (value_range *vr, tree var)
else
vr->set (var);
- vr->equiv_add (var, get_value_range (var), &vrp_equiv_obstack);
+ if (!vr->undefined_p ())
+ vr->equiv_add (var, get_value_range (var), &vrp_equiv_obstack);
}
/* Extract range information from a binary expression OP0 CODE OP1 based on
@@ -858,7 +868,10 @@ vr_values::extract_range_from_binary_expr (value_range *vr,
|| (vr1.kind () == VR_ANTI_RANGE
&& vr1.min () == op0
&& vr1.min () == vr1.max ())))
- vr->set_nonnull (expr_type);
+ {
+ vr->set_nonzero (expr_type);
+ vr->equiv_clear ();
+ }
}
/* Extract range information from a unary expression CODE OP0 based on
@@ -1085,7 +1098,8 @@ vr_values::extract_range_basic (value_range *vr, gimple *stmt)
&& TREE_CODE (SSA_NAME_VAR (arg)) == PARM_DECL
&& cfun->after_inlining)
{
- vr->set_null (type);
+ vr->set_zero (type);
+ vr->equiv_clear ();
return;
}
break;
@@ -1392,7 +1406,10 @@ vr_values::extract_range_basic (value_range *vr, gimple *stmt)
&& gimple_stmt_nonnegative_warnv_p (stmt, &sop))
set_value_range_to_nonnegative (vr, type);
else if (vrp_stmt_computes_nonzero (stmt))
- vr->set_nonnull (type);
+ {
+ vr->set_nonzero (type);
+ vr->equiv_clear ();
+ }
else
vr->set_varying ();
}
@@ -1608,7 +1625,7 @@ compare_range_with_value (enum tree_code comp, value_range *vr, tree val,
return NULL_TREE;
/* ~[VAL_1, VAL_2] OP VAL is known if VAL_1 <= VAL <= VAL_2. */
- if (value_inside_range (val, vr->min (), vr->max ()) == 1)
+ if (!vr->may_contain_p (val))
return (comp == NE_EXPR) ? boolean_true_node : boolean_false_node;
return NULL_TREE;
@@ -2343,7 +2360,7 @@ vr_values::vrp_evaluate_conditional_warnv_with_ops (enum tree_code code,
}
else
{
- value_range vro, vri;
+ value_range_base vro, vri;
if (code == GT_EXPR || code == GE_EXPR)
{
vro.set (VR_ANTI_RANGE, TYPE_MIN_VALUE (TREE_TYPE (op0)), x);