aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2015-11-09 10:21:04 +0000
committerJakub Jelinek <jakub@redhat.com>2015-11-09 10:21:04 +0000
commit1a7ad2f1ed99afd9770ae968b900cd18d343f98f (patch)
treed44d9675e4d20413b860ba3dbd98a7d0c8d91745
parente1eb0a700ca6283fdb17bb334a869ef0dedd90d3 (diff)
svn merge -r229832:230008 svn+ssh://gcc.gnu.org/svn/gcc/trunk
git-svn-id: https://gcc.gnu.org/svn/gcc/branches/gomp-4_5-branch@230009 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--gcc/ChangeLog845
-rw-r--r--gcc/DATESTAMP2
-rw-r--r--gcc/ada/ChangeLog29
-rw-r--r--gcc/ada/gcc-interface/decl.c49
-rw-r--r--gcc/ada/gcc-interface/gigi.h3
-rw-r--r--gcc/ada/gcc-interface/trans.c4
-rw-r--r--gcc/ada/gcc-interface/utils.c85
-rw-r--r--gcc/ada/gcc-interface/utils2.c11
-rw-r--r--gcc/alloc-pool.h2
-rw-r--r--gcc/asan.c6
-rw-r--r--gcc/bb-reorder.c6
-rw-r--r--gcc/builtins.c263
-rw-r--r--gcc/builtins.def9
-rw-r--r--gcc/builtins.h1
-rw-r--r--gcc/c-family/ChangeLog30
-rw-r--r--gcc/c-family/c-common.c81
-rw-r--r--gcc/c-family/c-common.h4
-rw-r--r--gcc/c-family/c-pragma.c50
-rw-r--r--gcc/c-family/c-pragma.h1
-rw-r--r--gcc/c-family/c.opt19
-rw-r--r--gcc/c/ChangeLog20
-rw-r--r--gcc/c/c-decl.c51
-rw-r--r--gcc/c/c-errors.c12
-rw-r--r--gcc/c/c-objc-common.c2
-rw-r--r--gcc/c/c-typeck.c66
-rw-r--r--gcc/calls.c10
-rw-r--r--gcc/cfg-flags.def7
-rw-r--r--gcc/cfgexpand.c12
-rw-r--r--gcc/common/config/i386/i386-common.c3
-rw-r--r--gcc/config.gcc2
-rw-r--r--gcc/config/aarch64/aarch64-builtins.c115
-rw-r--r--gcc/config/aarch64/aarch64-protos.h4
-rw-r--r--gcc/config/aarch64/aarch64-simd-builtins.def22
-rw-r--r--gcc/config/aarch64/aarch64-simd.md93
-rw-r--r--gcc/config/aarch64/aarch64-tuning-flags.def1
-rw-r--r--gcc/config/aarch64/aarch64.c140
-rw-r--r--gcc/config/aarch64/aarch64.md3
-rw-r--r--gcc/config/aarch64/aarch64.opt5
-rw-r--r--gcc/config/aarch64/arm_neon.h822
-rw-r--r--gcc/config/arm/aarch-common.c6
-rw-r--r--gcc/config/arm/arm-ldmstm.ml23
-rw-r--r--gcc/config/arm/arm.c157
-rw-r--r--gcc/config/arm/arm.h19
-rw-r--r--gcc/config/arm/arm.md200
-rw-r--r--gcc/config/arm/arm.opt2
-rw-r--r--gcc/config/arm/ldmstm.md126
-rw-r--r--gcc/config/arm/sync.md4
-rw-r--r--gcc/config/arm/thumb2.md12
-rw-r--r--gcc/config/i386/i386-c.c8
-rw-r--r--gcc/config/i386/i386-protos.h8
-rw-r--r--gcc/config/i386/i386.c308
-rw-r--r--gcc/config/i386/i386.h3
-rw-r--r--gcc/config/i386/i386.md91
-rw-r--r--gcc/config/i386/predicates.md8
-rw-r--r--gcc/config/i386/rdos.h2
-rw-r--r--gcc/config/mips/loongson.md56
-rw-r--r--gcc/config/mips/mips.c4
-rw-r--r--gcc/config/s390/s390.c2
-rw-r--r--gcc/config/sparc/sparc.opt2
-rw-r--r--gcc/config/tilegx/tilegx.c2
-rw-r--r--gcc/config/tilepro/tilepro.c2
-rw-r--r--gcc/cp/ChangeLog43
-rw-r--r--gcc/cp/constraint.cc37
-rw-r--r--gcc/cp/error.c5
-rw-r--r--gcc/cp/init.c14
-rw-r--r--gcc/cp/parser.c128
-rw-r--r--gcc/cp/pt.c17
-rw-r--r--gcc/cselib.c22
-rw-r--r--gcc/dbxout.c6
-rw-r--r--gcc/diagnostic-color.c5
-rw-r--r--gcc/diagnostic-core.h8
-rw-r--r--gcc/diagnostic-show-locus.c755
-rw-r--r--gcc/diagnostic.c202
-rw-r--r--gcc/diagnostic.h54
-rw-r--r--gcc/doc/extend.texi116
-rw-r--r--gcc/doc/invoke.texi41
-rw-r--r--gcc/doc/md.texi20
-rw-r--r--gcc/doc/tm.texi10
-rw-r--r--gcc/doc/tm.texi.in4
-rw-r--r--gcc/dwarf2out.c88
-rw-r--r--gcc/expmed.c266
-rw-r--r--gcc/expmed.h8
-rw-r--r--gcc/expr.c328
-rw-r--r--gcc/expr.h5
-rw-r--r--gcc/flag-types.h9
-rw-r--r--gcc/fold-const-call.c256
-rw-r--r--gcc/fold-const.c220
-rw-r--r--gcc/fold-const.h1
-rw-r--r--gcc/fortran/ChangeLog65
-rw-r--r--gcc/fortran/array.c24
-rw-r--r--gcc/fortran/check.c40
-rw-r--r--gcc/fortran/class.c4
-rw-r--r--gcc/fortran/cpp.c13
-rw-r--r--gcc/fortran/decl.c34
-rw-r--r--gcc/fortran/error.c103
-rw-r--r--gcc/fortran/match.c20
-rw-r--r--gcc/fortran/trans-array.c2
-rw-r--r--gcc/fortran/trans-types.c14
-rw-r--r--gcc/function.c39
-rw-r--r--gcc/genmatch.c37
-rw-r--r--gcc/gensupport.c9
-rw-r--r--gcc/gimple-expr.c8
-rw-r--r--gcc/gimple-fold.c13
-rw-r--r--gcc/gimple-laddress.c4
-rw-r--r--gcc/gimple-ssa-strength-reduction.c6
-rw-r--r--gcc/gimple.c13
-rw-r--r--gcc/gimplify.c15
-rw-r--r--gcc/go/gofrontend/MERGE2
-rw-r--r--gcc/graphite-optimize-isl.c22
-rw-r--r--gcc/graphite-poly.c2
-rw-r--r--gcc/graphite-poly.h3
-rw-r--r--gcc/graphite-scop-detection.c18
-rw-r--r--gcc/graphite-sese-to-poly.c240
-rw-r--r--gcc/ifcvt.c4
-rw-r--r--gcc/input.c22
-rw-r--r--gcc/internal-fn.c4
-rw-r--r--gcc/internal-fn.def2
-rw-r--r--gcc/ipa-cp.c2
-rw-r--r--gcc/ipa-inline-analysis.c1
-rw-r--r--gcc/ipa-polymorphic-call.c44
-rw-r--r--gcc/ipa-prop.c30
-rw-r--r--gcc/ipa-prop.h6
-rw-r--r--gcc/jit/ChangeLog4
-rw-r--r--gcc/jit/jit-builtins.c1
-rw-r--r--gcc/lra.c2
-rw-r--r--gcc/lto-streamer-out.c3
-rw-r--r--gcc/lto/ChangeLog8
-rw-r--r--gcc/lto/lto-lang.c1
-rw-r--r--gcc/lto/lto.c5
-rw-r--r--gcc/objc/ChangeLog5
-rw-r--r--gcc/objc/objc-encoding.c10
-rw-r--r--gcc/omp-low.c183
-rw-r--r--gcc/output.h9
-rw-r--r--gcc/postreload-gcse.c2
-rw-r--r--gcc/pretty-print.c21
-rw-r--r--gcc/pretty-print.h25
-rw-r--r--gcc/print-tree.c7
-rw-r--r--gcc/rtl-error.c3
-rw-r--r--gcc/rtl.h1
-rw-r--r--gcc/sched-deps.c4
-rw-r--r--gcc/simplify-rtx.c7
-rw-r--r--gcc/stor-layout.c11
-rw-r--r--gcc/target.def17
-rw-r--r--gcc/targhooks.c17
-rw-r--r--gcc/targhooks.h2
-rw-r--r--gcc/testsuite/ChangeLog200
-rw-r--r--gcc/testsuite/c-c++-common/goacc-gomp/nesting-fail-1.c12
-rw-r--r--gcc/testsuite/c-c++-common/goacc/nesting-fail-1.c24
-rw-r--r--gcc/testsuite/c-c++-common/gomp/cancel-1.c77
-rw-r--r--gcc/testsuite/c-c++-common/gomp/clauses-4.c34
-rw-r--r--gcc/testsuite/c-c++-common/gomp/doacross-1.c4
-rw-r--r--gcc/testsuite/c-c++-common/gomp/nesting-2.c154
-rw-r--r--gcc/testsuite/c-c++-common/gomp/nesting-warn-1.c12
-rw-r--r--gcc/testsuite/c-c++-common/gomp/ordered-3.c12
-rw-r--r--gcc/testsuite/c-c++-common/gomp/ordered-4.c54
-rw-r--r--gcc/testsuite/g++.dg/cilk-plus/CK/pr66326.cc33
-rw-r--r--gcc/testsuite/g++.dg/concepts/generic-fn-err.C4
-rw-r--r--gcc/testsuite/g++.dg/concepts/placeholder6.C10
-rw-r--r--gcc/testsuite/g++.dg/gomp/ordered-2.C2
-rw-r--r--gcc/testsuite/g++.dg/lto/pr68057_0.C23
-rw-r--r--gcc/testsuite/g++.dg/lto/pr68057_1.C17
-rw-r--r--gcc/testsuite/g++.dg/torture/pr68220.C238
-rw-r--r--gcc/testsuite/g++.dg/vect/pr68145.cc41
-rw-r--r--gcc/testsuite/gcc.dg/Wno-frame-address.c2
-rw-r--r--gcc/testsuite/gcc.dg/gomp/ordered-2.c2
-rw-r--r--gcc/testsuite/gcc.dg/graphite/fuse-1.c43
-rw-r--r--gcc/testsuite/gcc.dg/graphite/fuse-2.c43
-rw-r--r--gcc/testsuite/gcc.dg/graphite/interchange-13.c1
-rw-r--r--gcc/testsuite/gcc.dg/lto/20110201-1_0.c4
-rw-r--r--gcc/testsuite/gcc.dg/plugin/diagnostic-test-show-locus-bw.c149
-rw-r--r--gcc/testsuite/gcc.dg/plugin/diagnostic-test-show-locus-color.c158
-rw-r--r--gcc/testsuite/gcc.dg/plugin/diagnostic_plugin_test_show_locus.c326
-rw-r--r--gcc/testsuite/gcc.dg/plugin/plugin.exp3
-rw-r--r--gcc/testsuite/gcc.dg/pr68088_1.c15
-rw-r--r--gcc/testsuite/gcc.dg/pragma-diag-5.c2
-rw-r--r--gcc/testsuite/gcc.dg/sso-1.c19
-rw-r--r--gcc/testsuite/gcc.dg/sso-2.c94
-rw-r--r--gcc/testsuite/gcc.dg/sso-3.c94
-rw-r--r--gcc/testsuite/gcc.dg/sso-4.c20
-rw-r--r--gcc/testsuite/gcc.dg/sso-5.c24
-rw-r--r--gcc/testsuite/gcc.dg/sso-6.c72
-rw-r--r--gcc/testsuite/gcc.dg/sso-7.c44
-rw-r--r--gcc/testsuite/gcc.dg/sso-8.c44
-rw-r--r--gcc/testsuite/gcc.dg/sso/dump.h23
-rw-r--r--gcc/testsuite/gcc.dg/sso/init1.h12
-rw-r--r--gcc/testsuite/gcc.dg/sso/init13.h15
-rw-r--r--gcc/testsuite/gcc.dg/sso/init2.h24
-rw-r--r--gcc/testsuite/gcc.dg/sso/init3.h34
-rw-r--r--gcc/testsuite/gcc.dg/sso/init4.h14
-rw-r--r--gcc/testsuite/gcc.dg/sso/init5.h14
-rw-r--r--gcc/testsuite/gcc.dg/sso/init6.h24
-rw-r--r--gcc/testsuite/gcc.dg/sso/init7.h28
-rw-r--r--gcc/testsuite/gcc.dg/sso/init8.h28
-rw-r--r--gcc/testsuite/gcc.dg/sso/init9.h14
-rw-r--r--gcc/testsuite/gcc.dg/sso/p1.c64
-rw-r--r--gcc/testsuite/gcc.dg/sso/p13.c64
-rw-r--r--gcc/testsuite/gcc.dg/sso/p2.c88
-rw-r--r--gcc/testsuite/gcc.dg/sso/p3.c88
-rw-r--r--gcc/testsuite/gcc.dg/sso/p4.c64
-rw-r--r--gcc/testsuite/gcc.dg/sso/p5.c74
-rw-r--r--gcc/testsuite/gcc.dg/sso/p6.c74
-rw-r--r--gcc/testsuite/gcc.dg/sso/p7.c74
-rw-r--r--gcc/testsuite/gcc.dg/sso/p8.c74
-rw-r--r--gcc/testsuite/gcc.dg/sso/p9.c64
-rw-r--r--gcc/testsuite/gcc.dg/sso/q1.c50
-rw-r--r--gcc/testsuite/gcc.dg/sso/q13.c50
-rw-r--r--gcc/testsuite/gcc.dg/sso/q2.c54
-rw-r--r--gcc/testsuite/gcc.dg/sso/q3.c54
-rw-r--r--gcc/testsuite/gcc.dg/sso/q4.c50
-rw-r--r--gcc/testsuite/gcc.dg/sso/q5.c46
-rw-r--r--gcc/testsuite/gcc.dg/sso/q6.c45
-rw-r--r--gcc/testsuite/gcc.dg/sso/q7.c46
-rw-r--r--gcc/testsuite/gcc.dg/sso/q8.c46
-rw-r--r--gcc/testsuite/gcc.dg/sso/q9.c50
-rw-r--r--gcc/testsuite/gcc.dg/sso/r3.c65
-rw-r--r--gcc/testsuite/gcc.dg/sso/r5.c65
-rw-r--r--gcc/testsuite/gcc.dg/sso/r6.c65
-rw-r--r--gcc/testsuite/gcc.dg/sso/r7.c65
-rw-r--r--gcc/testsuite/gcc.dg/sso/r8.c65
-rw-r--r--gcc/testsuite/gcc.dg/sso/s3.c79
-rw-r--r--gcc/testsuite/gcc.dg/sso/s5.c91
-rw-r--r--gcc/testsuite/gcc.dg/sso/s6.c81
-rw-r--r--gcc/testsuite/gcc.dg/sso/s7.c79
-rw-r--r--gcc/testsuite/gcc.dg/sso/s8.c79
-rw-r--r--gcc/testsuite/gcc.dg/sso/sso.exp40
-rw-r--r--gcc/testsuite/gcc.dg/sso/t1.c56
-rw-r--r--gcc/testsuite/gcc.dg/sso/t13.c56
-rw-r--r--gcc/testsuite/gcc.dg/sso/t2.c92
-rw-r--r--gcc/testsuite/gcc.dg/sso/t3.c92
-rw-r--r--gcc/testsuite/gcc.dg/sso/t4.c56
-rw-r--r--gcc/testsuite/gcc.dg/sso/t5.c72
-rw-r--r--gcc/testsuite/gcc.dg/sso/t6.c72
-rw-r--r--gcc/testsuite/gcc.dg/sso/t7.c72
-rw-r--r--gcc/testsuite/gcc.dg/sso/t8.c72
-rw-r--r--gcc/testsuite/gcc.dg/sso/t9.c56
-rw-r--r--gcc/testsuite/gcc.dg/sso/u5.c52
-rw-r--r--gcc/testsuite/gcc.dg/sso/u6.c52
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/pr66752-3.c4
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-7.c6
-rw-r--r--gcc/testsuite/gcc.dg/vect/bb-slp-38.c44
-rw-r--r--gcc/testsuite/gcc.target/aarch64/advsimd-intrinsics/vqtbX.c519
-rw-r--r--gcc/testsuite/gcc.target/aarch64/advsimd-intrinsics/vtbX.c4
-rw-r--r--gcc/testsuite/gcc.target/arm/combine-movs.c3
-rw-r--r--gcc/testsuite/gcc.target/arm/interrupt-1.c4
-rw-r--r--gcc/testsuite/gcc.target/arm/interrupt-2.c4
-rw-r--r--gcc/testsuite/gcc.target/arm/mincmp.c20
-rw-r--r--gcc/testsuite/gcc.target/arm/unaligned-memcpy-4.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/addr-space-1.c11
-rw-r--r--gcc/testsuite/gcc.target/i386/addr-space-2.c11
-rw-r--r--gcc/testsuite/gcc.target/i386/addr-space-3.c10
-rw-r--r--gcc/testsuite/gcc.target/i386/movbe-3.c19
-rw-r--r--gcc/testsuite/gfortran.dg/allocate_with_arrayspec_1.f9029
-rw-r--r--gcc/testsuite/gfortran.dg/goacc/combined_loop.f903
-rw-r--r--gcc/testsuite/gfortran.dg/goacc/parallel-kernels-regions.f9520
-rw-r--r--gcc/testsuite/gfortran.dg/goacc/private-3.f953
-rw-r--r--gcc/testsuite/gfortran.dg/gomp/target3.f902
-rw-r--r--gcc/testsuite/gfortran.dg/graphite/PR53852.f9037
-rw-r--r--gcc/testsuite/gfortran.dg/graphite/PR67518.f9045
-rw-r--r--gcc/testsuite/gfortran.dg/pr66465.f9023
-rw-r--r--gcc/testsuite/gfortran.dg/pr68053.f9010
-rw-r--r--gcc/testsuite/gfortran.dg/pr68151.f9013
-rw-r--r--gcc/testsuite/gfortran.dg/pr68153.f909
-rw-r--r--gcc/testsuite/gfortran.dg/pr68224.f9010
-rw-r--r--gcc/testsuite/gfortran.dg/proc_ptr_47.f9037
-rw-r--r--gcc/testsuite/gfortran.dg/warn_unused_function_2.f909
-rw-r--r--gcc/testsuite/gnat.dg/specs/sso1.ads19
-rw-r--r--gcc/testsuite/gnat.dg/specs/sso2.ads26
-rw-r--r--gcc/testsuite/gnat.dg/sso/conv1.adb50
-rw-r--r--gcc/testsuite/gnat.dg/sso/dump.adb17
-rw-r--r--gcc/testsuite/gnat.dg/sso/dump.ads3
-rw-r--r--gcc/testsuite/gnat.dg/sso/init1.ads26
-rw-r--r--gcc/testsuite/gnat.dg/sso/init10.ads23
-rw-r--r--gcc/testsuite/gnat.dg/sso/init11.ads34
-rw-r--r--gcc/testsuite/gnat.dg/sso/init12.ads25
-rw-r--r--gcc/testsuite/gnat.dg/sso/init13.ads33
-rw-r--r--gcc/testsuite/gnat.dg/sso/init2.ads69
-rw-r--r--gcc/testsuite/gnat.dg/sso/init3.ads78
-rw-r--r--gcc/testsuite/gnat.dg/sso/init4.ads27
-rw-r--r--gcc/testsuite/gnat.dg/sso/init5.ads39
-rw-r--r--gcc/testsuite/gnat.dg/sso/init6.ads39
-rw-r--r--gcc/testsuite/gnat.dg/sso/init7.ads59
-rw-r--r--gcc/testsuite/gnat.dg/sso/init8.ads59
-rw-r--r--gcc/testsuite/gnat.dg/sso/init9.ads27
-rw-r--r--gcc/testsuite/gnat.dg/sso/p1.adb62
-rw-r--r--gcc/testsuite/gnat.dg/sso/p10.adb63
-rw-r--r--gcc/testsuite/gnat.dg/sso/p11.adb68
-rw-r--r--gcc/testsuite/gnat.dg/sso/p12.adb122
-rw-r--r--gcc/testsuite/gnat.dg/sso/p13.adb63
-rw-r--r--gcc/testsuite/gnat.dg/sso/p2.adb80
-rw-r--r--gcc/testsuite/gnat.dg/sso/p3.adb80
-rw-r--r--gcc/testsuite/gnat.dg/sso/p4.adb63
-rw-r--r--gcc/testsuite/gnat.dg/sso/p5.adb68
-rw-r--r--gcc/testsuite/gnat.dg/sso/p6.adb61
-rw-r--r--gcc/testsuite/gnat.dg/sso/p7.adb61
-rw-r--r--gcc/testsuite/gnat.dg/sso/p8.adb61
-rw-r--r--gcc/testsuite/gnat.dg/sso/p9.adb63
-rw-r--r--gcc/testsuite/gnat.dg/sso/q1.adb52
-rw-r--r--gcc/testsuite/gnat.dg/sso/q10.adb53
-rw-r--r--gcc/testsuite/gnat.dg/sso/q11.adb44
-rw-r--r--gcc/testsuite/gnat.dg/sso/q12.adb43
-rw-r--r--gcc/testsuite/gnat.dg/sso/q13.adb53
-rw-r--r--gcc/testsuite/gnat.dg/sso/q2.adb60
-rw-r--r--gcc/testsuite/gnat.dg/sso/q3.adb60
-rw-r--r--gcc/testsuite/gnat.dg/sso/q4.adb53
-rw-r--r--gcc/testsuite/gnat.dg/sso/q5.adb44
-rw-r--r--gcc/testsuite/gnat.dg/sso/q6.adb44
-rw-r--r--gcc/testsuite/gnat.dg/sso/q7.adb44
-rw-r--r--gcc/testsuite/gnat.dg/sso/q8.adb44
-rw-r--r--gcc/testsuite/gnat.dg/sso/q9.adb53
-rw-r--r--gcc/testsuite/gnat.dg/sso/r11.adb68
-rw-r--r--gcc/testsuite/gnat.dg/sso/r12.adb123
-rw-r--r--gcc/testsuite/gnat.dg/sso/r3.adb68
-rw-r--r--gcc/testsuite/gnat.dg/sso/r5.adb68
-rw-r--r--gcc/testsuite/gnat.dg/sso/r6.adb68
-rw-r--r--gcc/testsuite/gnat.dg/sso/r7.adb68
-rw-r--r--gcc/testsuite/gnat.dg/sso/r8.adb68
-rw-r--r--gcc/testsuite/gnat.dg/sso/s11.adb78
-rw-r--r--gcc/testsuite/gnat.dg/sso/s12.adb77
-rw-r--r--gcc/testsuite/gnat.dg/sso/s3.adb79
-rw-r--r--gcc/testsuite/gnat.dg/sso/s5.adb78
-rw-r--r--gcc/testsuite/gnat.dg/sso/s6.adb79
-rw-r--r--gcc/testsuite/gnat.dg/sso/s7.adb79
-rw-r--r--gcc/testsuite/gnat.dg/sso/s8.adb79
-rw-r--r--gcc/testsuite/gnat.dg/sso/sso.exp40
-rw-r--r--gcc/testsuite/gnat.dg/sso/t1.adb55
-rw-r--r--gcc/testsuite/gnat.dg/sso/t10.adb56
-rw-r--r--gcc/testsuite/gnat.dg/sso/t11.adb67
-rw-r--r--gcc/testsuite/gnat.dg/sso/t12.adb66
-rw-r--r--gcc/testsuite/gnat.dg/sso/t13.adb56
-rw-r--r--gcc/testsuite/gnat.dg/sso/t2.adb84
-rw-r--r--gcc/testsuite/gnat.dg/sso/t3.adb84
-rw-r--r--gcc/testsuite/gnat.dg/sso/t4.adb56
-rw-r--r--gcc/testsuite/gnat.dg/sso/t5.adb67
-rw-r--r--gcc/testsuite/gnat.dg/sso/t6.adb67
-rw-r--r--gcc/testsuite/gnat.dg/sso/t7.adb68
-rw-r--r--gcc/testsuite/gnat.dg/sso/t8.adb68
-rw-r--r--gcc/testsuite/gnat.dg/sso/t9.adb56
-rw-r--r--gcc/testsuite/gnat.dg/sso/u11.adb44
-rw-r--r--gcc/testsuite/gnat.dg/sso/u5.adb44
-rw-r--r--gcc/testsuite/gnat.dg/sso/u6.adb44
-rw-r--r--gcc/testsuite/gnat.dg/sso1.adb77
-rw-r--r--gcc/testsuite/gnat.dg/sso2.adb14
-rw-r--r--gcc/testsuite/gnat.dg/sso2.ads13
-rw-r--r--gcc/testsuite/gnat.dg/sso3.adb52
-rw-r--r--gcc/testsuite/gnat.dg/sso4.adb55
-rw-r--r--gcc/testsuite/gnat.dg/sso5.adb52
-rw-r--r--gcc/testsuite/gnat.dg/sso6.adb54
-rw-r--r--gcc/testsuite/gnat.dg/sso7.adb52
-rw-r--r--gcc/testsuite/lib/gcc-dg.exp1
-rw-r--r--gcc/trans-mem.c3
-rw-r--r--gcc/tree-affine.c10
-rw-r--r--gcc/tree-call-cdce.c37
-rw-r--r--gcc/tree-cfg.c2
-rw-r--r--gcc/tree-core.h15
-rw-r--r--gcc/tree-data-ref.c20
-rw-r--r--gcc/tree-dfa.c11
-rw-r--r--gcc/tree-dfa.h2
-rw-r--r--gcc/tree-diagnostic.c2
-rw-r--r--gcc/tree-hash-traits.h10
-rw-r--r--gcc/tree-inline.c2
-rw-r--r--gcc/tree-into-ssa.c2
-rw-r--r--gcc/tree-into-ssa.h1
-rw-r--r--gcc/tree-outof-ssa.c2
-rw-r--r--gcc/tree-parloops.c2
-rw-r--r--gcc/tree-pretty-print.c2
-rw-r--r--gcc/tree-scalar-evolution.c7
-rw-r--r--gcc/tree-sra.c106
-rw-r--r--gcc/tree-ssa-address.c2
-rw-r--r--gcc/tree-ssa-alias.c18
-rw-r--r--gcc/tree-ssa-dce.c4
-rw-r--r--gcc/tree-ssa-loop-ivopts.c27
-rw-r--r--gcc/tree-ssa-math-opts.c10
-rw-r--r--gcc/tree-ssa-pre.c5
-rw-r--r--gcc/tree-ssa-sccvn.c67
-rw-r--r--gcc/tree-ssa-sccvn.h1
-rw-r--r--gcc/tree-ssa-structalias.c10
-rw-r--r--gcc/tree-ssa-tail-merge.c2
-rw-r--r--gcc/tree-ssa-threadedge.c114
-rw-r--r--gcc/tree-ssa-threadupdate.c288
-rw-r--r--gcc/tree-ssanames.c192
-rw-r--r--gcc/tree-streamer-in.c7
-rw-r--r--gcc/tree-streamer-out.c7
-rw-r--r--gcc/tree-vect-data-refs.c21
-rw-r--r--gcc/tree-vect-patterns.c69
-rw-r--r--gcc/tree-vect-slp.c184
-rw-r--r--gcc/tree-vect-stmts.c28
-rw-r--r--gcc/tree-vectorizer.c35
-rw-r--r--gcc/tree-vectorizer.h3
-rw-r--r--gcc/tree-vrp.c14
-rw-r--r--gcc/tree.c10
-rw-r--r--gcc/tree.h85
-rw-r--r--gcc/tsan.c6
-rw-r--r--gcc/ubsan.c8
-rw-r--r--gcc/var-tracking.c3
-rw-r--r--gcc/varasm.c121
-rw-r--r--gcc/varasm.h2
-rw-r--r--include/ChangeLog10
-rw-r--r--include/obstack.h910
-rw-r--r--libcilkrts/ChangeLog6
-rw-r--r--libcilkrts/runtime/config/x86/os-unix-sysdep.c2
-rw-r--r--libcpp/ChangeLog25
-rw-r--r--libcpp/errors.c7
-rw-r--r--libcpp/include/cpplib.h4
-rw-r--r--libcpp/include/line-map.h220
-rw-r--r--libcpp/line-map.c133
-rw-r--r--libgcc/ChangeLog19
-rw-r--r--libgcc/config/rs6000/atexit.c44
-rw-r--r--libgcc/config/rs6000/cxa_finalize.c4
-rw-r--r--libgcc/config/rs6000/libgcc-aix-cxa.ver4
-rw-r--r--libgcc/config/rs6000/t-aix-cxa3
-rw-r--r--libgcc/config/visium/lib2funcs.c2
-rw-r--r--libgcc/fixed-bit.h10
-rw-r--r--libgcc/fp-bit.h4
-rw-r--r--libgcc/libgcc2.c24
-rw-r--r--libgcc/libgcc2.h8
-rw-r--r--libgcc/libgcov.h4
-rw-r--r--libgo/Makefile.am14
-rw-r--r--libgo/Makefile.in9
-rw-r--r--libgo/go/encoding/json/decode_test.go16
-rw-r--r--libgo/go/encoding/json/encode.go2
-rw-r--r--libgo/go/encoding/xml/marshal_test.go10
-rw-r--r--libgo/go/encoding/xml/typeinfo.go2
-rw-r--r--libgo/go/net/tcpsockopt_solaris.go24
-rw-r--r--libgo/go/reflect/export_test.go4
-rw-r--r--libgo/go/reflect/type.go2
-rw-r--r--libgo/go/reflect/value.go29
-rw-r--r--libgo/go/syscall/exec_bsd.go6
-rw-r--r--libgo/go/syscall/exec_linux.go11
-rw-r--r--libgo/go/syscall/exec_unix.go6
-rw-r--r--libgo/go/syscall/exec_unix_test.go2
-rw-r--r--libgo/go/syscall/libcall_bsd.go27
-rw-r--r--libgo/runtime/go-varargs.c1
-rw-r--r--libgomp/ChangeLog5
-rw-r--r--libgomp/testsuite/libgomp.oacc-c-c++-common/loop-red-v-2.c2
-rw-r--r--libgomp/testsuite/libgomp.oacc-c-c++-common/loop-red-w-2.c2
-rw-r--r--libiberty/ChangeLog34
-rw-r--r--libiberty/config.in3
-rwxr-xr-xlibiberty/configure64
-rw-r--r--libiberty/configure.ac7
-rw-r--r--libiberty/obstack.c570
-rw-r--r--libiberty/obstacks.texi257
-rw-r--r--libobjc/ChangeLog11
-rw-r--r--libobjc/encoding.c35
-rw-r--r--libsanitizer/ChangeLog18
-rw-r--r--libsanitizer/Makefile.in1
-rw-r--r--libsanitizer/asan/Makefile.am2
-rw-r--r--libsanitizer/asan/Makefile.in3
-rwxr-xr-xlibsanitizer/configure38
-rw-r--r--libsanitizer/configure.ac24
-rw-r--r--libsanitizer/interception/Makefile.in1
-rw-r--r--libsanitizer/libbacktrace/Makefile.in1
-rw-r--r--libsanitizer/lsan/Makefile.in1
-rw-r--r--libsanitizer/sanitizer_common/Makefile.in1
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc14
-rw-r--r--libsanitizer/tsan/Makefile.am2
-rw-r--r--libsanitizer/tsan/Makefile.in3
-rw-r--r--libsanitizer/ubsan/Makefile.in1
-rw-r--r--libstdc++-v3/ChangeLog12
-rw-r--r--libstdc++-v3/testsuite/26_numerics/complex/requirements/constexpr_functions.cc2
-rw-r--r--libstdc++-v3/testsuite/26_numerics/complex/value_operations/constexpr.cc2
-rw-r--r--libstdc++-v3/testsuite/lib/libstdc++.exp2
-rw-r--r--libvtv/ChangeLog5
-rw-r--r--libvtv/vtv_malloc.cc7
463 files changed, 18860 insertions, 4004 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index f01e8ec1263..d0b119f0c5b 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,839 @@
+2015-11-09 Richard Henderson <rth@redhat.com>
+
+ * config/i386/i386-c.c (ix86_target_macros): Define __SEG_FS,
+ __SEG_GS, __SEG_TLS.
+ (ix86_register_pragmas): Register address spaces __seg_fs,
+ __seg_gs, __seg_tls.
+ * config/i386/i386-protos.h (enum ix86_address_seg): Remove.
+ (ADDR_SPACE_SEG_FS, ADDR_SPACE_SEG_GS, ADDR_SPACE_SEG_TLS): New.
+ (struct ix86_address): Use addr_space_t instead of ix86_address_seg.
+ * config/i386/i386.c (ix86_decompose_address): Likewise.
+ (ix86_legitimate_address_p): Likewise.
+ (memory_address_length): Likewise. Check mem address space too.
+ (ix86_print_operand): Use ix86_print_operand_address_as.
+ (ix86_print_operand_address_as): Rename from
+ ix86_print_operand_address, add new addr_space_t parameter.
+ Validate that either the parameter or the ix86_address segment
+ is default address space. Handle ADDR_SPACE_SEG_TLS.
+ (ix86_print_operand_address): New.
+ (ix86_addr_space_subset_p, TARGET_ADDR_SPACE_SUBSET_P): New.
+ (ix86_addr_space_convert, TARGET_ADDR_SPACE_CONVERT): New.
+ (ix86_addr_space_debug, TARGET_ADDR_SPACE_DEBUG): New.
+ (ix86_addr_space_zero_address_valid): New.
+ (TARGET_ADDR_SPACE_ZERO_ADDRESS_VALID): New.
+ * config/i386/i386.h (DEFAULT_TLS_SEG_REG): Use addr_space_t constants.
+ * config/i386/rdos.h (DEFAULT_TLS_SEG_REG): Likewise.
+ * config/i386/predicates.md (address_no_seg_operand): Likewise.
+ (vsib_address_operand): Likewise.
+ (address_mpx_no_base_operand): Likewise.
+ (address_mpx_no_index_operand): Likewise.
+ * doc/extend.texi (x86 Named Address Spaces): New section.
+
+ * config/i386/i386.c (ix86_check_no_addr_space): New.
+ (decide_alg): Add have_as parameter.
+ (alg_usable_p): Likewise; disable rep algorithms if set.
+ (ix86_expand_set_or_movmem): Notice if either MEM has a
+ non-default address space.
+ (ix86_expand_strlen): Likewise.
+ * config/i386/i386.md (strmov, strset): Likewise.
+ (*strmovdi_rex_1): Use ix86_check_no_addr_space.
+ (*strmovsi_1, *strmovqi_1, *rep_movdi_rex64, *rep_movsi, *rep_movqi,
+ *strsetdi_rex_1, *strsetsi_1, *strsethi_1, *strsetqi_1,
+ *rep_stosdi_rex64, *rep_stossi, *rep_stosqi, *cmpstrnqi_nz_1,
+ *cmpstrnqi_1, *strlenqi_1): Likewise.
+
+ * config/i386/i386.md (*movabs<mode>_1): Print the full memory rtx.
+ (*movabs<mode>_2): Likewise.
+
+ * dwarf2out.c (modified_type_die): Pass the address space number
+ through TARGET_ADDR_SPACE_DEBUG to produce the dwarf address class.
+ * target.def (TARGET_ADDR_SPACE_DEBUG): New.
+ * targhooks.c (default_addr_space_debug): New.
+ * targhooks.h (default_addr_space_debug): Declare.
+ * doc/tm.texi.in (TARGET_ADDR_SPACE_DEBUG): Mark it.
+ * doc/tm.texi: Rebuild.
+
+ * gimple.c (check_loadstore): Return false when 0 is a valid address.
+ * fold-const.c (const_unop) [ADDR_SPACE_CONVERT_EXPR]: Do not fold
+ null when 0 is valid in the source address space.
+ * target.def (TARGET_ADDR_SPACE_ZERO_ADDRESS_VALID): New.
+ * targhooks.c (default_addr_space_zero_address_valid): New.
+ * targhooks.h (default_addr_space_zero_address_valid): Declare.
+ * doc/tm.texi.in (TARGET_ADDR_SPACE_ZERO_ADDRESS_VALID): Mark it.
+ * doc/tm.texi: Rebuild.
+
+ * cselib.c (add_mem_for_addr): Compare address spaces when
+ matching memories.
+ (cselib_lookup_mem): Likewise.
+ * fold-const.c (operand_equal_p): Check address spaces of
+ pointer types before checking integer constants.
+
+ PR tree-opt/66768
+ * tree-ssa-address.c (create_mem_ref_raw): Use a pointer of
+ the correct type for the base.
+
+2015-11-09 Jeff Law <law@redhat.com>
+
+ * tree-into-ssa.c (names_to_release): No longer static.
+ * tree-into-ssa.h (names_to_release): Declare.
+ * tree-ssanames.c (verify_ssaname_freelists): New debug function.
+ (release_free_names_and_compact_live_names): New function extracted
+ from pass_release_ssa_names::execute.
+ (pass_release_ssa_names::execute): Use it.
+
+2015-11-09 Alan Modra <amodra@gmail.com>
+
+ * gensupport.c (add_mnemonic_string): Make len param a size_t.
+ (gen_mnemonic_setattr): Make "size" var a size_t. Use
+ obstack_blank_fast to shrink obstack. Cast obstack_next_free
+ return value.
+
+2015-11-09 Segher Boessenkool <segher@kernel.crashing.org>
+
+ PR rtl-optimization/68182
+ * gcc/bb-reorder.c (reorder_basic_blocks_simple): Treat a conditional
+ branch with only one successor just like unconditional branches.
+
+2015-11-08 Jeff Law <law@redhat.com>
+
+ * tree-ssa-threadupdate.c (register_jump_thraed): Assert that a
+ non-FSM path has no edges marked with EDGE_DFS_BACK.
+ (ssa_redirect_edges): No longer call mark_loop_for_removal.
+ (thread_single_edge, def_split_header_continue_p): Remove.
+ (bb_ends_with_multiway_branch): Likewise.
+ (thread_through_loop_header): Remove cases of threading from
+ latch through the header. Simplify knowing we won't thread
+ the latch.
+ (thread_through_all_blocks): Simplify knowing that only the FSM
+ threader needs to handle backedges.
+
+2015-11-08 Eric Botcazou <ebotcazou@adacore.com>
+
+ * doc/extend.texi (type attributes): Document scalar_storage_order.
+ (Structure-Packing Pragmas): Rename into...
+ (Structure-Layout Pragmas): ...this. Document scalar_storage_order.
+ * doc/invoke.texi (C Dialect Options): Document -fsso-struct
+ (Warnings): Document -Wno-scalar-storage-order.
+ * flag-types.h (enum scalar_storage_order_kind): New enumeration.
+ * calls.c (store_unaligned_arguments_into_pseudos): Adjust calls to
+ extract_bit_field and store_bit_field.
+ (initialize_argument_information): Adjust call to store_expr.
+ (load_register_parameters): Adjust call to extract_bit_field.
+ * expmed.c (check_reverse_storage_order_support): New function.
+ (check_reverse_float_storage_order_support): Likewise.
+ (flip_storage_order): Likewise.
+ (store_bit_field_1): Add REVERSE parameter. Flip the storage order
+ of the value if it is true. Pass REVERSE to recursive call after
+ adjusting the target offset.
+ Do not use extraction or movstrict instruction if REVERSE is true.
+ Pass REVERSE to store_fixed_bit_field.
+ (store_bit_field): Add REVERSE parameter and pass to it to above.
+ (store_fixed_bit_field): Add REVERSE parameter and pass to it to
+ store_split_bit_field and store_fixed_bit_field_1.
+ (store_fixed_bit_field_1): Add REVERSE parameter. Flip the storage
+ order of the value if it is true and adjust the target offset.
+ (store_split_bit_field): Add REVERSE parameter and pass it to
+ store_fixed_bit_field. Adjust the target offset if it is true.
+ (extract_bit_field_1): Add REVERSE parameter. Flip the storage order
+ of the value if it is true. Pass REVERSE to recursive call after
+ adjusting the target offset.
+ Do not use extraction or subreg instruction if REVERSE is true.
+ Pass REVERSE to extract_fixed_bit_field.
+ (extract_bit_field): Add REVERSE parameter and pass to it to above.
+ (extract_fixed_bit_field): Add REVERSE parameter and pass to it to
+ extract_split_bit_field and extract_fixed_bit_field_1.
+ (extract_fixed_bit_field_1): Add REVERSE parameter. Flip the storage
+ order of the value if it is true and adjust the target offset.
+ (extract_split_bit_field): Add REVERSE parameter and pass it to
+ extract_fixed_bit_field. Adjust the target offset if it is true.
+ * expmed.h (flip_storage_order): Declare.
+ (store_bit_field): Adjust prototype.
+ (extract_bit_field): Likewise.
+ * expr.c (emit_group_load_1): Adjust calls to extract_bit_field.
+ (emit_group_store): Adjust call to store_bit_field.
+ (copy_blkmode_from_reg): Likewise.
+ (copy_blkmode_to_reg): Likewise.
+ (write_complex_part): Likewise.
+ (read_complex_part): Likewise.
+ (optimize_bitfield_assignment_op): Add REVERSE parameter. Assert
+ that it isn't true if the target is a register.
+ <PLUS_EXPR>: If it is, do not optimize unless bitsize is equal to 1,
+ and flip the storage order of the value.
+ <BIT_IOR_EXPR>: Flip the storage order of the value.
+ (get_bit_range): Adjust call to get_inner_reference.
+ (expand_assignment): Adjust calls to get_inner_reference, store_expr,
+ optimize_bitfield_assignment_op and store_field. Handle MEM_EXPRs
+ with reverse storage order.
+ (store_expr_with_bounds): Add REVERSE parameter and pass it to
+ recursive calls and call to store_bit_field. Force the value into a
+ register if it is true and then flip the storage order of the value.
+ (store_expr): Add REVERSE parameter and pass it to above.
+ (categorize_ctor_elements_1): Adjust call to
+ initializer_constant_valid_p.
+ (store_constructor_field): Add REVERSE parameter and pass it to
+ recursive calls and call to store_field.
+ (store_constructor): Add REVERSE parameter and pass it to calls to
+ store_constructor_field and store_expr. Set it to true for an
+ aggregate type with TYPE_REVERSE_STORAGE_ORDER.
+ (store_field): Add REVERSE parameter and pass it to recursive calls
+ and calls to store_expr and store_bit_field. Temporarily flip the
+ storage order of the value with record type and integral mode and
+ adjust the shift if it is true.
+ (get_inner_reference): Add PREVERSEP parameter and set it to true
+ upon encoutering a reference with reverse storage order.
+ (expand_expr_addr_expr_1): Adjust call to get_inner_reference.
+ (expand_constructor): Adjust call to store_constructor.
+ (expand_expr_real_2) <CASE_CONVERT>: Pass TYPE_REVERSE_STORAGE_ORDER
+ of the union type to store_expr in the MEM case and assert that it
+ isn't set in the REG case. Adjust call to store_field.
+ (expand_expr_real_1) <MEM_REF>: Handle reverse storage order.
+ <normal_inner_ref>: Add REVERSEP variable and adjust calls to
+ get_inner_reference and extract_bit_field. Temporarily flip the
+ storage order of the value with record type and integral mode and
+ adjust the shift if it is true. Flip the storage order of the value
+ at the end if it is true.
+ <VIEW_CONVERT_EXPR>: Add REVERSEP variable and adjust call to
+ get_inner_reference. Do not fetch an inner reference if it is true.
+ * expr.h (store_expr_with_bounds): Ajust prototype.
+ (store_expr): Likewise.
+ * fold-const.c (make_bit_field_ref): Add REVERSEP parameter and set
+ REF_REVERSE_STORAGE_ORDER on the reference according to it.
+ (optimize_bit_field_compare): Deal with reverse storage order.
+ Adjust calls to get_inner_reference and make_bit_field_ref.
+ (decode_field_reference): Add PREVERSEP parameter and adjust call to
+ get_inner_reference.
+ (fold_truth_andor_1): Deal with reverse storage order. Adjust calls
+ to decode_field_reference and make_bit_field_ref.
+ (fold_unary_loc) <CASE_CONVERT>: Adjust call to get_inner_reference.
+ <VIEW_CONVERT_EXPR>: Propagate the REF_REVERSE_STORAGE_ORDER flag.
+ (fold_comparison): Adjust call to get_inner_reference.
+ (split_address_to_core_and_offset): Adjust call to
+ get_inner_reference.
+ * gimple-expr.c (useless_type_conversion_p): Return false for array
+ types with different TYPE_REVERSE_STORAGE_ORDER flag.
+ * gimplify.c (gimplify_expr) <MEM_REF>: Propagate the
+ REF_REVERSE_STORAGE_ORDER flag.
+ * lto-streamer-out.c (hash_tree): Deal with
+ TYPE_REVERSE_STORAGE_ORDER.
+ * output.h (assemble_real): Adjust prototype.
+ * print-tree.c (print_node): Convey TYPE_REVERSE_STORAGE_ORDER.
+ * stor-layout.c (finish_record_layout): Propagate the
+ TYPE_REVERSE_STORAGE_ORDER flag to the variants.
+ * tree-core.h (TYPE_REVERSE_STORAGE_ORDER): Document.
+ (TYPE_SATURATING): Adjust.
+ (REF_REVERSE_STORAGE_ORDER): Document.
+ * tree-dfa.c (get_ref_base_and_extent): Add PREVERSE parameter and
+ set it to true upon encoutering a reference with reverse storage
+ order.
+ * tree-dfa.h (get_ref_base_and_extent): Adjust prototype.
+ * tree-inline.c (remap_gimple_op_r): Propagate the
+ REF_REVERSE_STORAGE_ORDER flag.
+ (copy_tree_body_r): Likewise.
+ * tree-outof-ssa.c (insert_value_copy_on_edge): Adjust call to
+ store_expr.
+ * tree-streamer-in.c (unpack_ts_base_value_fields): Deal with
+ TYPE_REVERSE_STORAGE_ORDER and REF_REVERSE_STORAGE_ORDER.
+ * tree-streamer-out.c (pack_ts_base_value_fields): Likewise.
+ * tree.c (stabilize_reference) <BIT_FIELD_REF>: Propagate the
+ REF_REVERSE_STORAGE_ORDER flag.
+ (verify_type_variant): Deal with TYPE_REVERSE_STORAGE_ORDER.
+ (gimple_canonical_types_compatible_p): Likewise.
+ * tree.h (TYPE_REVERSE_STORAGE_ORDER): New flag.
+ (TYPE_SATURATING): Adjust.
+ (REF_REVERSE_STORAGE_ORDER): New flag.
+ (reverse_storage_order_for_component_p): New inline predicate.
+ (storage_order_barrier_p): Likewise.
+ (get_inner_reference): Adjust prototype.
+ * varasm.c: Include expmed.h.
+ (assemble_variable_contents): Adjust call to output_constant.
+ (assemble_real): Add REVERSE parameter. Flip the storage
+ order of the value if REVERSE is true.
+ (compare_constant) <CONSTRUCTOR>: Compare TYPE_REVERSE_STORAGE_ORDER.
+ (assemble_constant_contents): Adjust call to output_constant.
+ (output_constant_pool_2): Adjust call to assemble_real.
+ (initializer_constant_valid_p_1) <CONSTRUCTOR>: Deal with
+ TYPE_REVERSE_STORAGE_ORDER.
+ (initializer_constant_valid_p): Add REVERSE parameter.
+ (output_constant): Add REVERSE parameter.
+ <INTEGER_TYPE>: Flip the storage order of the value if REVERSE is true.
+ <REAL_TYPE>: Adjust call to assemble_real.
+ <COMPLEX_TYPE>: Pass it to recursive calls.
+ <ARRAY_TYPE>: Likewise. Adjust call to output_constructor.
+ <RECORD_TYPE>: Likewise. Adjust call to output_constructor.
+ (struct oc_local_state): Add REVERSE field.
+ (output_constructor_array_range): Adjust calls to output_constant.
+ (output_constructor_regular_field): Likewise.
+ (output_constructor_bitfield): Adjust call to output_constructor.
+ Flip the storage order of the value if REVERSE is true.
+ (output_constructor): Add REVERSE parameter. Set it to true for an
+ aggregate type with TYPE_REVERSE_STORAGE_ORDER. Adjust call to
+ output_constructor_bitfield.
+ * varasm.h (initializer_constant_valid_p): Default REVERSE to false.
+ * asan.c (instrument_derefs): Adjust call to get_inner_reference.
+ * builtins.c (get_object_alignment_2): Likewise.
+ * cfgexpand.c (expand_debug_expr): Adjust call to get_inner_reference
+ and get_ref_base_and_extent.
+ * dbxout.c (dbxout_expand_expr): Likewise.
+ * dwarf2out.c (add_var_loc_to_decl): Likewise.
+ (loc_list_for_address_of_addr_expr_of_indirect_ref): Likewise.
+ (loc_list_from_tree): Likewise.
+ (fortran_common): Likewise.
+ * gimple-fold.c (gimple_fold_builtin_memory_op): Adjust calls to
+ get_ref_base_and_extent.
+ (get_base_constructor): Likewise.
+ (fold_const_aggregate_ref_1): Likewise.
+ * gimple-laddress.c (pass_laddress::execute): Adjust call to
+ get_inner_reference.
+ * gimple-ssa-strength-reduction.c (slsr_process_ref): Adjust call to
+ get_inner_reference and bail out on reverse storage order.
+ * ifcvt.c (noce_emit_move_insn): Adjust calls to store_bit_field.
+ * ipa-cp.c (ipa_get_jf_ancestor_result): Adjust call to
+ build_ref_for_offset.
+ * ipa-polymorphic-call.c (set_by_invariant): Adjust call to
+ get_ref_base_and_extent.
+ (ipa_polymorphic_call_context): Likewise.
+ (extr_type_from_vtbl_ptr_store): Likewise.
+ (check_stmt_for_type_change): Likewise.
+ (get_dynamic_type): Likewise.
+ * ipa-prop.c (ipa_load_from_parm_agg_1): Adjust call to
+ get_ref_base_and_extent.
+ (compute_complex_assign_jump_func): Likewise.
+ (get_ancestor_addr_info): Likewise.
+ (compute_known_type_jump_func): Likewise.
+ (determine_known_aggregate_parts): Likewise.
+ (ipa_get_adjustment_candidate): Likewise.
+ (ipa_modify_call_arguments): Set REF_REVERSE_STORAGE_ORDER on
+ MEM_REF.
+ * ipa-prop.h (ipa_parm_adjustment): Add REVERSE field.
+ (build_ref_for_offset): Adjust prototype.
+ * simplify-rtx.c (delegitimize_mem_from_attrs): Adjust call to
+ get_inner_reference.
+ * tree-affine.c (tree_to_aff_combination): Adjust call to
+ get_inner_reference.
+ (get_inner_reference_aff): Likewise.
+ * tree-data-ref.c (split_constant_offset_1): Likewise.
+ (dr_analyze_innermost): Likewise. Bail out if reverse storage order.
+ * tree-scalar-evolution.c (interpret_rhs_expr): Adjust call to
+ get_inner_reference.
+ * tree-sra.c (struct access): Add REVERSE and move WRITE around.
+ (dump_access): Print new fields.
+ (create_access): Adjust call to get_ref_base_and_extent and set the
+ REVERSE flag according to the result.
+ (completely_scalarize_record): Set the REVERSE flag.
+ (scalarize_elem): Add REVERSE parameter.
+ (build_access_from_expr_1): Preserve storage order barriers.
+ (build_accesses_from_assign): Likewise.
+ (build_ref_for_offset): Add REVERSE parameter and set the
+ REF_REVERSE_STORAGE_ORDER flag accordingly.
+ (build_ref_for_model): Adjust call to build_ref_for_offset and clear
+ the REF_REVERSE_STORAGE_ORDER flag if there are components.
+ (analyze_access_subtree): Likewise.
+ (create_artificial_child_access): Set the REVERSE flag.
+ (get_access_for_expr): Adjust call to get_ref_base_and_extent.
+ (turn_representatives_into_adjustments): Propagate REVERSE flag.
+ (ipa_sra_check_caller): Adjust call to get_inner_reference.
+ * tree-ssa-alias.c (ao_ref_base): Adjust call to
+ get_ref_base_and_extent.
+ (aliasing_component_refs_p): Likewise.
+ (stmt_kills_ref_p_1): Likewise.
+ * tree-ssa-dce.c (mark_aliased_reaching_defs_necessary_1): Likewise.
+ * tree-ssa-loop-ivopts.c (may_be_nonaddressable_p) <MEM_REF>: New.
+ Return true if reverse storage order.
+ <BIT_FIELD_REF>: Likewise.
+ <COMPONENT_REF>: Likewise.
+ <ARRAY_REF>: Likewise.
+ <ARRAY_RANGE_REF>: Likewise.
+ (split_address_cost): Likewise. Bail out if reverse storage order.
+ * tree-ssa-math-opts.c (find_bswap_or_nop_load): Adjust call to
+ get_inner_reference. Bail out if reverse storage order.
+ (bswap_replace): Adjust call to get_inner_reference.
+ * tree-ssa-pre.c (create_component_ref_by_pieces_1) <MEM_REF>: Set
+ the REF_REVERSE_STORAGE_ORDER flag.
+ <BIT_FIELD_REF>: Likewise.
+ * tree-ssa-sccvn.c (vn_reference_eq): Return false on storage order
+ barriers.
+ (copy_reference_ops_from_ref) <MEM_REF>: Set REVERSE field according
+ to the REF_REVERSE_STORAGE_ORDER flag.
+ <BIT_FIELD_REF>: Likewise.
+ <VIEW_CONVERT_EXPR>: Set it for storage order barriers.
+ (contains_storage_order_barrier_p): New predicate.
+ (vn_reference_lookup_3): Adjust calls to get_ref_base_and_extent.
+ Punt on storage order barriers if necessary.
+ * tree-ssa-sccvn.h (struct vn_reference_op_struct): Add REVERSE.
+ * tree-ssa-structalias.c (get_constraint_for_component_ref): Adjust
+ call to get_ref_base_and_extent.
+ (do_structure_copy): Likewise.
+ * tree-vect-data-refs.c (vect_check_gather): Adjust call to
+ get_inner_reference.
+ (vect_analyze_data_refs): Likewise. Bail out if reverse storage
+ order.
+ * tsan.c (instrument_expr): Adjust call to get_inner_reference.
+ * ubsan.c (instrument_bool_enum_load): Likewise.
+ (instrument_object_size): Likewise.
+ * var-tracking.c (track_expr_p): Adjust call to
+ get_ref_base_and_extent
+ * config/mips/mips.c (r10k_safe_mem_expr_p): Adjust call to
+ get_inner_reference.
+ * config/s390/s390.c (s390_expand_atomic): Adjust call to
+ store_bit_field.
+ * config/tilegx/tilegx.c (tilegx_expand_unaligned_load): Adjust call to
+ extract_bit_field.
+ * config/tilepro/tilepro.c (tilepro_expand_unaligned_load): Likewise.
+
+2015-11-07 Eric Botcazou <ebotcazou@adacore.com>
+
+ * config/sparc/sparc.opt (mfix-at697f): Add final period.
+
+2015-11-07 Segher Boessenkool <segher@kernel.crashing.org>
+
+ PR rtl-optimization/67864
+ * common/config/i386/i386-common.c (ix86_option_optimization_table)
+ <OPT_freorder_blocks_algorithm_>: Use REORDER_BLOCKS_ALGORITHM_STC
+ at -Os and up.
+
+2015-11-07 Richard Sandiford <richard.sandiford@arm.com>
+
+ * trans-mem.c (is_tm_pure_call): Use gimple_call_flags for
+ internal functions.
+
+2015-11-07 Richard Sandiford <richard.sandiford@arm.com>
+
+ * builtins.def: #undef DEF_BUILTIN and DEF_BUILTIN_CHKP
+ * builtins.c, genmatch.c, tree-core.h: Don't undef them here.
+
+2015-11-07 Richard Sandiford <richard.sandiford@arm.com>
+
+ * internal-fn.def: #undef DEF_INTERNAL_FN at the end.
+ * internal-fn.c: Don't undef it here.
+ * tree-core.h: Likewise.
+
+2015-11-07 Richard Sandiford <richard.sandiford@arm.com>
+
+ * builtins.c (fold_builtin_nan): Delete.
+ (fold_builtin_memcmp): Remove case where both arguments are constant.
+ (fold_builtin_strcmp, fold_builtin_strncmp): Likewise.
+ (fold_builtin_strspn, fold_builtin_strcspn): Likewise.
+ (fold_builtin_1): Remove BUILT_IN_NAN* handling.
+ * fold-const-call.c: Include fold-const.h.
+ (host_size_t_cst_p): New function.
+ (build_cmp_result, fold_const_builtin_nan): Likewise.
+ (fold_const_call_1): New function, split out from...
+ (fold_const_call): ...here (for all three interfaces). Handle
+ constant nan, nans, strlen, strcmp, strncmp, strspn and strcspn.
+
+2015-11-07 Richard Sandiford <richard.sandiford@arm.com>
+
+ * builtins.c (fold_builtin_bitop, fold_builtin_bswap): Delete.
+ (fold_builtin_1): Don't call them.
+ * fold-const-call.c: Include tm.h.
+ (fold_const_call_ss): New variant for integer-to-integer folds.
+ (fold_const_call): Call it.
+
+2015-11-07 Richard Sandiford <richard.sandiford@arm.com>
+
+ * builtins.c (fold_builtin_classify): Move constant cases to...
+ * fold-const-call.c (fold_const_call_ss): ...here.
+
+2015-11-07 Richard Sandiford <richard.sandiford@arm.com>
+
+ * builtins.h (c_getstr): Move to...
+ * fold-const.h (c_getstr): ...here.
+ * builtins.c (c_getstr): Move to...
+ * fold-const.c (c_getstr): ...here.
+
+2015-11-07 Richard Sandiford <richard.sandiford@arm.com>
+
+ * builtins.def (BUILTIN_RINT, BUILTIN_RINTF, BUILTIN_RINTL): Use
+ ATTR_MATHFN_FPROUNDING rather than ATTR_MATHFN_FPROUNDING_ERRNO.
+
+2015-11-07 Richard Sandiford <richard.sandiford@arm.com>
+
+ * tree-call-cdce.c (shrink_wrap_one_built_in_call): Try to update
+ the dominance info; free it if we can't.
+ (pass_call_cdce::execute): Don't free the dominance info here.
+
+2015-11-06 Jeff Law <law@redhat.com>
+
+ * tree-ssa-threadedge.c (dummy_simplify): Remove.
+ (thread_around_empty_blocks): Remove backedge_seen_p argument.
+ If we thread to a backedge, then return false. Update recursive
+ call to eliminate backedge_seen_p argument.
+ (thread_through_normal_block): Remove backedge_seen_p argument.
+ Remove backedge_seen_p argument from calls to
+ thread_around_empty_blocks. Remove checks on backedge_seen_p.
+ If we thread to a backedge, then return 0.
+ (thread_across_edge): Remove bookkeeping for backedge_seen. Don't
+ pass it to thread_through_normal_block or thread_through_empty_blocks.
+ For joiner handling, if we see a backedge, do not try normal
+ threading.
+
+2015-11-06 Abderrazek Zaafrani <a.zaafrani@samsung.com>
+
+ * graphite-optimize-isl.c (optimize_isl): Call isl_union_map_is_equal.
+ * graphite-poly.c (new_scop): Initialize original_schedule.
+ (free_scop): Free original_schedule.
+ * graphite-poly.h (struct scop): Add field original_schedule.
+ * graphite-sese-to-poly.c (build_scop_original_schedule): New.
+ (build_poly_scop): Call build_scop_original_schedule.
+
+2015-11-06 Abderrazek Zaafrani <a.zaafrani@samsung.com>
+
+ * graphite-sese-to-poly.c (build_pbb_scattering_polyhedrons): Remove.
+ (build_pbb_minimal_scattering_polyhedrons): New.
+ (build_scop_scattering): Remove.
+ (build_scop_minimal_scattering): New.
+ (build_scop_scattering): Call build_pbb_minimal_scattering_polyhedrons.
+ (build_poly_scop): Call build_scop_minimal_scattering.
+
+2015-11-06 Jeff Law <law@redhat.com>
+
+ * cfg-flags.def (IGNORE): New edge flag.
+ * tree-vrp.c (identify_jump_threads): Mark and clear edges
+ scheduled for removal with EDGE_IGNORE around call into
+ jump threader. Do no thread across edges with EDGE_IGNORE,
+ but do allow threading across those with EDGE_DFS_BACK.
+
+2015-11-06 David Wohlferd <dw@LimeGreenSocks.com>
+
+ * doc/md.texi (multi-alternative constraints): Don't document
+ alternatives inherently tied to reload for the user documentation.
+
+2015-11-06 Michael Collison <michael.collison@linaro.org
+ Ramana Radhakrishnan <ramana.radhakrishnan@linaro.org>
+
+ Revert:
+ 2015-08-01 Michael Collison <michael.collison@linaro.org
+ Ramana Radhakrishnan <ramana.radhakrishnan@linaro.org>
+
+ * config/arm/arm.md (*arm_smin_cmp): New pattern.
+ (*arm_umin_cmp): Likewise.
+
+2015-11-06 Jakub Jelinek <jakub@redhat.com>
+
+ * gimplify.c (gimplify_omp_ordered): Fix up diagnostics
+ wording.
+ * omp-low.c (check_omp_nesting_restrictions): Update for the
+ various new OpenMP 4.5 nesting restrictions, clarified
+ nesting glossary, closely nested region relationship clarified
+ to mean explicit or implicit parallel regions (target/teams),
+ use %</%> or %qs where appropriate.
+
+2015-11-06 Aditya Kumar <aditya.k7@samsung.com>
+ Sebastian Pop <s.pop@samsung.com>
+
+ * graphite-scop-detection.c (loop_is_valid_scop): Call
+ optimize_loop_nest_for_speed_p.
+
+2015-11-06 Aditya Kumar <aditya.k7@samsung.com>
+ Sebastian Pop <s.pop@samsung.com>
+
+ * graphite-optimize-isl.c (optimize_isl): Call
+ isl_options_set_schedule_maximize_band_depth.
+
+2015-11-06 Aditya Kumar <aditya.k7@samsung.com>
+ Sebastian Pop <s.pop@samsung.com>
+
+ * graphite-scop-detection.c (scop_detection::merge_sese): Entry
+ and exit edges should not be a part of irreducible loop.
+ (scop_detection::can_represent_loop_1): Loops should not be
+ irreducible.
+ (scop_detection::harmful_stmt_in_region): All the basic block
+ should belong to reducible loops.
+
+2015-11-06 Christophe Lyon <christophe.lyon@linaro.org>
+
+ * config/aarch64/aarch64-simd-builtins.def: Update builtins
+ tables: add tbl3v16qi, qtbl[34]*, tbx4v16qi, qtbx[34]*.
+ * config/aarch64/aarch64-simd.md (aarch64_tbl3v8qi): Rename to...
+ (aarch64_tbl3<mode>) ... this, which supports v16qi too.
+ (aarch64_tbx4v8qi): Rename to...
+ aarch64_tbx4<mode>): ... this.
+ (aarch64_qtbl3<mode>): New pattern.
+ (aarch64_qtbx3<mode>): New pattern.
+ (aarch64_qtbl4<mode>): New pattern.
+ (aarch64_qtbx4<mode>): New pattern.
+ * config/aarch64/arm_neon.h (vqtbl2_s8, vqtbl2_u8, vqtbl2_p8)
+ (vqtbl2q_s8, vqtbl2q_u8, vqtbl2q_p8, vqtbl3_s8, vqtbl3_u8)
+ (vqtbl3_p8, vqtbl3q_s8, vqtbl3q_u8, vqtbl3q_p8, vqtbl4_s8)
+ (vqtbl4_u8, vqtbl4_p8, vqtbl4q_s8, vqtbl4q_u8, vqtbl4q_p8)
+ (vqtbx2_s8, vqtbx2_u8, vqtbx2_p8, vqtbx2q_s8, vqtbx2q_u8)
+ (vqtbx2q_p8, vqtbx3_s8, vqtbx3_u8, vqtbx3_p8, vqtbx3q_s8)
+ (vqtbx3q_u8, vqtbx3q_p8, vqtbx4_s8, vqtbx4_u8, vqtbx4_p8)
+ (vqtbx4q_s8, vqtbx4q_u8, vqtbx4q_p8): Rewrite using builtin
+ functions.
+
+2015-11-06 Mike Stump <mikestump@comcast.net>
+
+ PR debug/66728
+ * dwarf2out.c (get_full_len): Return a value based upon the actual
+ precision needed for the value.
+ (add_const_value_attribute): Use a maximal wide-int for
+ CONST_WIDE_INTs, not VOIDmode.
+ (output_die): Don't ever output NULL with printf.
+
+ * rtl.h (get_precision of rtx_mode_t): Ensure we never process
+ BLKmode nor VOIDmode values.
+
+2015-11-06 David Malcolm <dmalcolm@redhat.com>
+
+ * diagnostic-color.c (color_dict): Eliminate "caret"; add "range1"
+ and "range2".
+ (parse_gcc_colors): Update comment to describe default GCC_COLORS.
+ * diagnostic-core.h (warning_at_rich_loc): New declaration.
+ (error_at_rich_loc): New declaration.
+ (permerror_at_rich_loc): New declaration.
+ (inform_at_rich_loc): New declaration.
+ * diagnostic-show-locus.c (adjust_line): Delete.
+ (struct point_state): New struct.
+ (class colorizer): New class.
+ (class layout_point): New class.
+ (class layout_range): New class.
+ (struct line_bounds): New.
+ (class layout): New class.
+ (colorizer::colorizer): New ctor.
+ (colorizer::~colorizer): New dtor.
+ (layout::layout): New ctor.
+ (layout::print_source_line): New method.
+ (layout::print_annotation_line): New method.
+ (layout::get_state_at_point): New method.
+ (layout::get_x_bound_for_row): New method.
+ (diagnostic_show_locus): Reimplement in terms of class layout.
+ (diagnostic_print_caret_line): Delete.
+ * diagnostic.c (diagnostic_initialize): Replace
+ MAX_LOCATIONS_PER_MESSAGE with rich_location::MAX_RANGES.
+ (diagnostic_set_info_translated): Convert param from location_t
+ to rich_location *. Eliminate calls to set_location on the
+ message in favor of storing the rich_location ptr there.
+ (diagnostic_set_info): Convert param from location_t to
+ rich_location *.
+ (diagnostic_build_prefix): Break out array into...
+ (diagnostic_kind_color): New variable.
+ (diagnostic_get_color_for_kind): New function.
+ (diagnostic_report_diagnostic): Colorize the option_text
+ using the color for the severity.
+ (diagnostic_append_note): Update for change in signature of
+ diagnostic_set_info.
+ (diagnostic_append_note_at_rich_loc): New function.
+ (emit_diagnostic): Update for change in signature of
+ diagnostic_set_info.
+ (inform): Likewise.
+ (inform_at_rich_loc): New function.
+ (inform_n): Update for change in signature of diagnostic_set_info.
+ (warning): Likewise.
+ (warning_at): Likewise.
+ (warning_at_rich_loc): New function.
+ (warning_n): Update for change in signature of diagnostic_set_info.
+ (pedwarn): Likewise.
+ (permerror): Likewise.
+ (permerror_at_rich_loc): New function.
+ (error): Update for change in signature of diagnostic_set_info.
+ (error_n): Likewise.
+ (error_at): Likewise.
+ (error_at_rich_loc): New function.
+ (sorry): Update for change in signature of diagnostic_set_info.
+ (fatal_error): Likewise.
+ (internal_error): Likewise.
+ (internal_error_no_backtrace): Likewise.
+ (source_range::debug): New function.
+ * diagnostic.h (struct diagnostic_info): Eliminate field
+ "override_column". Add field "richloc".
+ (struct diagnostic_context): Add field "colorize_source_p".
+ (diagnostic_override_column): Delete.
+ (diagnostic_set_info): Convert param from location_t to
+ rich_location *.
+ (diagnostic_set_info_translated): Likewise.
+ (diagnostic_append_note_at_rich_loc): New function.
+ (diagnostic_num_locations): New function.
+ (diagnostic_expand_location): Get the location from the
+ rich_location.
+ (diagnostic_print_caret_line): Delete.
+ (diagnostic_get_color_for_kind): New declaration.
+ * genmatch.c (linemap_client_expand_location_to_spelling_point): New.
+ (error_cb): Update for change in signature of "error" callback.
+ (fatal_at): Likewise.
+ (warning_at): Likewise.
+ * input.c (linemap_client_expand_location_to_spelling_point): New.
+ * pretty-print.c (text_info::set_range): New method.
+ (text_info::get_location): New method.
+ * pretty-print.h (MAX_LOCATIONS_PER_MESSAGE): Eliminate this macro.
+ (struct text_info): Eliminate "locations" array in favor of
+ "m_richloc", a rich_location *.
+ (textinfo::set_location): Add a "caret_p" param, and reimplement
+ in terms of a call to set_range.
+ (textinfo::get_location): Eliminate inline implementation in favor of
+ an out-of-line reimplementation.
+ (textinfo::set_range): New method.
+ * rtl-error.c (diagnostic_for_asm): Update for change in signature
+ of diagnostic_set_info.
+ * tree-diagnostic.c (default_tree_printer): Update for new
+ "caret_p" param for textinfo::set_location.
+ * tree-pretty-print.c (percent_K_format): Likewise.
+
+2015-11-06 Ramana Radhakrishnan <ramana.radhakrishnan@arm.com>
+
+ Properly apply.
+ 2015-11-05 Ramana Radhakrishnan <ramana.radhakrishnan@arm.com>
+ * config/aarch64/aarch64.c
+ (aarch64_can_use_per_function_literal_pools_p): New.
+ (aarch64_use_blocks_for_constant_p): Adjust declaration
+ and use aarch64_can_use_function_literal_pools_p.
+ (aarch64_select_rtx_section): Update.
+
+2015-11-06 Ramana Radhakrishnan <ramana.radhakrishnan@arm.com>
+
+ * config/arm/arm-ldmstm.ml: Rewrite to generate unified asm templates.
+ * config/arm/arm.c (arm_asm_trampoline_template): Make unified asm safe.
+ (arm_output_multireg_pop): Likewise.
+ (output_move_double): Likewise.
+ (output_move_quad): Likewise.
+ (output_return_instruction): Likewise.
+ (arm_print_operand): Remove support for %( and %. print modifiers.
+ (arm_output_shift): Make unified asm.
+ (arm_declare_function_name): Likewise.
+ * config/arm/arm.h (TARGET_UNIFIED_ASM): Delete.
+ (ASM_APP_OFF): Adjust.
+ (ASM_OUTPUT_REG_PUSH): Undo special casing for TARGET_ARM.
+ (ASM_OUTPUT_REG_POP): Likewise.
+ * config/arm/arm.md: Adjust uses of %., %(, %)
+ * config/arm/sync.md: Likewise.
+ * config/arm/thumb2.md: Likewise.
+ * config/arm/ldmstm.md: Regenerate.
+ * config/arm/arm.opt (masm-unified-syntax): Do not special case Thumb.
+ * doc/invoke.texi (masm-unified-syntax): Update documentation.
+
+2015-11-06 David Malcolm <dmalcolm@redhat.com>
+
+ * input.c (dump_line_table_statistics): Dump stats on adhoc table.
+
+2015-11-07 Jan Hubicka <hubicka@ucw.cz>
+
+ * tree-core.h (size_type_kind): Remove OEP_CONSTANT_ADDRESS_OF and
+ add OEP_MATCH_SIDE_EFFECTS.
+ * fold-const.c (operand_equal_p): Update documentation; handle
+ OEP_MATCH_SIDE_EFFECTS.
+ * tree-ssa-tail-merge.c (gimple_operand_equal_value_p): Use
+ OEP_MATCH_SIDE_EFFECTS.
+
+2015-11-06 Benedikt Huber <benedikt.huber@theobroma-systems.com>
+ Philipp Tomsich <philipp.tomsich@theobroma-systems.com>
+
+ * config/aarch64/aarch64-builtins.c: Builtins for rsqrt and rsqrtf.
+ * config/aarch64/aarch64-protos.h: Declare.
+ * config/aarch64/aarch64-simd.md: Matching expressions for frsqrte and
+ frsqrts.
+ * config/aarch64/aarch64-tuning-flags.def: Added recip_sqrt.
+ * config/aarch64/aarch64.c: New functions. Emit rsqrt estimation code when
+ applicable.
+ * config/aarch64/aarch64.md: Added enum entries.
+ * config/aarch64/aarch64.opt: Added option -mlow-precision-recip-sqrt.
+ * testsuite/gcc.target/aarch64/rsqrt_asm_check_common.h: Common macros for
+ assembly checks.
+ * testsuite/gcc.target/aarch64/rsqrt_asm_check_negative_1.c: Make sure
+ frsqrts and frsqrte are not emitted.
+ * testsuite/gcc.target/aarch64/rsqrt_asm_check_1.c: Make sure frsqrts and
+ frsqrte are emitted.
+ * testsuite/gcc.target/aarch64/rsqrt_1.c: Functional tests for rsqrt.
+
+2015-11-07 Jan Hubicka <hubicka@ucw.cz>
+
+ PR ipa/68057
+ PR ipa/68220
+ * ipa-polymorphic-call.c
+ (ipa_polymorphic_call_context::restrict_to_inner_type): Fix ordering
+ issue when offset is out of range.
+ (contains_type_p): Fix out of range check, clear dynamic flag.
+
+2015-11-06 Arnout Vandecappelle <arnout@mind.be>
+
+ * config.gcc (e6500): Fix cpu_is_64bit typo.
+
+2015-11-06 Alan Lawrence <alan.lawrence@arm.com>
+
+ * tree-sra.c (completely_scalarize): Properly handle negative array
+ indices using offset_int.
+
+2015-11-06 Richard Biener <rguenther@suse.de>
+
+ * alloc-pool.h (object_allocator::allocate): Default-initialize
+ object.
+
+2015-11-06 Richard Biener <rguenther@suse.de>
+
+ * tree-ssa-sccvn.c (class sccvn_dom_walker): Add destructor.
+ * lra.c (init_reg_info): Truncate copy_vec instead of
+ re-allocating a new one and leaking the old.
+ * ipa-inline-analysis.c (estimate_function_body_sizes): Free
+ bb_infos vec.
+ * sched-deps.c (sched_deps_finish): Free the dn/dl pools.
+ * postreload-gcse.c (free_mem): Free modify_mem_list and
+ canon_modify_mem_list.
+
+2015-11-06 Ilya Enkovich <enkovich.gnu@gmail.com>
+
+ PR tree-optimization/68145
+ * tree-vect-stmts.c (vectorizable_operation): Fix
+ determination for booleans.
+
+2015-11-06 Tom de Vries <tom@codesourcery.com>
+
+ * tree-cfg.c (gimple_split_block_before_cond_jump): Split before
+ cond_jump, instead of split after last nondebug insn before cond_jump.
+ * tree-parloops.c (transform_to_exit_first_loop_alt): Verify ssa before
+ returning.
+
+2015-11-06 Kyrylo Tkachov <kyrylo.tkachov@arm.com>
+
+ PR target/68088
+ * config/arm/aarch-common.c (aarch_accumulator_forwarding): Strip
+ subregs from accumulator and make sure it's a register.
+
+2015-11-06 Simon Dardis <simon.dardis@imgtec.com>
+
+ * config/mips/loongson.md (vec_loongson_extract_lo_<mode>): New, extract
+ low part to scalar.
+ (reduc_uplus_<mode>): Remove.
+ (reduc_plus_scal_<mode>): Rename from reduc_splus_<mode>, Use vec
+ loongson_extract_lo_<mode>.
+ (reduc_smax_scal_<mode>, reduc_smin_scal_<mode>): Rename from
+ reduc_smax_<mode>, reduc_smax_<mode>, use vec
+ loongson_extract_lo_<mode>.
+ (reduc_umax_scal_<mode>, reduc_umin_scal_<mode>): Rename.
+
+2015-11-06 Richard Biener <rguenther@suse.de>
+
+ * tree-vectorizer.h (struct _bb_vec_info): Add region_begin/end
+ members.
+ (vect_stmt_in_region_p): Declare.
+ * tree-vect-slp.c (new_bb_vec_info): Work on a region.
+ (destroy_bb_vec_info): Likewise.
+ (vect_bb_slp_scalar_cost): Use vect_stmt_in_region_p.
+ (vect_get_and_check_slp_defs): Likewise.
+ (vect_slp_analyze_bb_1): Refactor to make it work on sub-BBs.
+ (vect_slp_bb): Likewise.
+ * tree-vect-patterns.c (vect_same_loop_or_bb_p): Implement
+ in terms of vect_stmt_in_region_p.
+ (vect_pattern_recog): Iterate over the BB region.
+ * tree-vect-stmts.c (vect_is_simple_use): Use vect_stmt_in_region_p.
+ * tree-vectorizer.c (vect_stmt_in_region_p): New function.
+ (pass_slp_vectorize::execute): Initialize all stmt UIDs to -1.
+ * config/i386/i386.c: Include gimple-iterator.h.
+ * config/aarch64/aarch64.c: Likewise.
+
+2015-11-06 Alexandre Oliva <aoliva@redhat.com>
+
+ PR rtl-optimization/67753
+ PR rtl-optimization/64164
+ * function.c (assign_parm_setup_block): Avoid allocating a
+ stack slot if we don't have an ABI-reserved one. Emit the
+ copy to target_reg in the conversion seq if the copy from
+ entry_parm is in it too. Don't use the conversion seq to copy
+ a PARALLEL to a REG or a CONCAT.
+
+2015-11-06 Richard Biener <rguenther@suse.de>
+
+ * tree-hash-traits.h (tree_operand_hash): Provide equal, not
+ equal_keys.
+
2015-11-05 Cesar Philippidis <cesar@codesourcery.com>
Thomas Schwinge <thomas@codesourcery.com>
James Norris <jnorris@codesourcery.com>
@@ -17,8 +853,7 @@
2015-11-05 Martin Sebor <msebor@redhat.com>
PR c++/67942
- * invoke.texi (-Wplacement-new): Document new option.
- * gcc/testsuite/g++.dg/warn/Wplacement-new-size.C: New test.
+ * doc/invoke.texi (-Wplacement-new): Document new option.
2015-11-05 Alan Lawrence <alan.lawrence@arm.com>
@@ -422,7 +1257,7 @@
* tree-ssa.c (gimple_uses_undefined_value_p): New.
* tree-ssa.h (gimple_uses_undefined_value_p): Declare.
-2015-11-02 Jeff Law <jeff@redhat.com>
+2015-11-02 Jeff Law <law@redhat.com>
* tree-ssa-threadupdate.c (valid_jump_thread_path): Also detect
cases where the loop latch edge is in the middle of an FSM path.
@@ -486,7 +1321,7 @@
PR middle-end/68166
* fold-const.c: Include "md5.h".
-2015-11-01 Jeff Law <jeff@redhat.com>
+2015-11-01 Jeff Law <law@redhat.com>
* vmsdbgout.c: Revert unused header file reduction patch.
@@ -535,7 +1370,7 @@
* tree-ssa-structalias.c (ipa_pta_execute): Use make_copy_constraint.
-2015-10-30 Jeff Law <jeff@redhat.com>
+2015-10-30 Jeff Law <law@redhat.com>
Nathan Sidwell <nathan@acm.org>
* config/nvptx/nvptx.h (HARD_REGNO_NREGS): Avoid warning on unused
diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP
index 4d10d51aefc..563100ef632 100644
--- a/gcc/DATESTAMP
+++ b/gcc/DATESTAMP
@@ -1 +1 @@
-20151106
+20151109
diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog
index 22afbdc1b10..ca1cb618be6 100644
--- a/gcc/ada/ChangeLog
+++ b/gcc/ada/ChangeLog
@@ -1,3 +1,32 @@
+2015-11-08 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gcc-interface/gigi.h (set_reverse_storage_order_on_pad_type):
+ Declare.
+ * gcc-interface/decl.c (gnat_to_gnu_entity) <discrete_type>: Set the
+ storage order on the enclosing record for a packed array type.
+ <E_Array_Type>: Set the storage order.
+ <E_Array_Subtype>: Likewise.
+ <E_Record_Type>: Likewise.
+ <E_Record_Subtype>: Likewise.
+ (gnat_to_gnu_component_type): Set the reverse storage order on a
+ padded type built for a non-bit-packed array.
+ (gnat_to_gnu_field): Likewise.
+ (components_to_record): Deal with TYPE_REVERSE_STORAGE_ORDER.
+ * gcc-interface/utils.c (make_packable_type): Likewise.
+ (pad_type_hasher::equal): Likewise.
+ (gnat_types_compatible_p): Likewise.
+ (unchecked_convert): Likewise.
+ (set_reverse_storage_order_on_pad_type): New public function.
+ * gcc-interface/trans.c (Attribute_to_gnu): Adjust call to
+ get_inner_reference.
+ * gcc-interface/utils2.c (build_unary_op): Likewise.
+ (gnat_build_constructor): Deal with TYPE_REVERSE_STORAGE_ORDER.
+ (gnat_rewrite_reference): Propagate REF_REVERSE_STORAGE_ORDER.
+
+2015-11-07 Richard Sandiford <richard.sandiford@arm.com>
+
+ * gcc-interface/utils.c: Don't undef DEF_BUILTIN.
+
2015-10-29 Andrew MacLeod <amacleod@redhat.com>
* gcc-interface/decl.c: Reorder #include's and remove duplicates.
diff --git a/gcc/ada/gcc-interface/decl.c b/gcc/ada/gcc-interface/decl.c
index 7f15b7cdf93..627eace9dd2 100644
--- a/gcc/ada/gcc-interface/decl.c
+++ b/gcc/ada/gcc-interface/decl.c
@@ -1805,6 +1805,12 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition)
TYPE_ALIGN (gnu_type)
= align > 0 ? align : TYPE_ALIGN (gnu_field_type);
+ /* Propagate the reverse storage order flag to the record type so
+ that the required byte swapping is performed when retrieving the
+ enclosed modular value. */
+ TYPE_REVERSE_STORAGE_ORDER (gnu_type)
+ = Reverse_Storage_Order (Original_Array_Type (gnat_entity));
+
relate_alias_sets (gnu_type, gnu_field_type, ALIAS_SET_COPY);
/* Don't declare the field as addressable since we won't be taking
@@ -2152,8 +2158,9 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition)
for (index = ndim - 1; index >= 0; index--)
{
tem = build_nonshared_array_type (tem, gnu_index_types[index]);
- if (Reverse_Storage_Order (gnat_entity) && !GNAT_Mode)
- sorry ("non-default Scalar_Storage_Order");
+ if (index == ndim - 1)
+ TYPE_REVERSE_STORAGE_ORDER (tem)
+ = Reverse_Storage_Order (gnat_entity);
TYPE_MULTI_ARRAY_P (tem) = (index > 0);
if (array_type_has_nonaliased_component (tem, gnat_entity))
TYPE_NONALIASED_COMPONENT (tem) = 1;
@@ -2516,6 +2523,9 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition)
{
gnu_type = build_nonshared_array_type (gnu_type,
gnu_index_types[index]);
+ if (index == ndim - 1)
+ TYPE_REVERSE_STORAGE_ORDER (gnu_type)
+ = Reverse_Storage_Order (gnat_entity);
TYPE_MULTI_ARRAY_P (gnu_type) = (index > 0);
if (array_type_has_nonaliased_component (gnu_type, gnat_entity))
TYPE_NONALIASED_COMPONENT (gnu_type) = 1;
@@ -2876,8 +2886,8 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition)
gnu_type = make_node (tree_code_for_record_type (gnat_entity));
TYPE_NAME (gnu_type) = gnu_entity_name;
TYPE_PACKED (gnu_type) = (packed != 0) || has_rep;
- if (Reverse_Storage_Order (gnat_entity) && !GNAT_Mode)
- sorry ("non-default Scalar_Storage_Order");
+ TYPE_REVERSE_STORAGE_ORDER (gnu_type)
+ = Reverse_Storage_Order (gnat_entity);
process_attributes (&gnu_type, &attr_list, true, gnat_entity);
if (!definition)
@@ -3287,6 +3297,8 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition)
gnu_type = make_node (RECORD_TYPE);
TYPE_NAME (gnu_type) = gnu_entity_name;
TYPE_PACKED (gnu_type) = TYPE_PACKED (gnu_base_type);
+ TYPE_REVERSE_STORAGE_ORDER (gnu_type)
+ = Reverse_Storage_Order (gnat_entity);
process_attributes (&gnu_type, &attr_list, true, gnat_entity);
/* Set the size, alignment and alias set of the new type to
@@ -3341,6 +3353,8 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition)
TYPE_NAME (new_variant)
= concat_name (TYPE_NAME (gnu_type),
IDENTIFIER_POINTER (suffix));
+ TYPE_REVERSE_STORAGE_ORDER (new_variant)
+ = TYPE_REVERSE_STORAGE_ORDER (gnu_type);
copy_and_substitute_in_size (new_variant, old_variant,
gnu_subst_list);
v->new_type = new_variant;
@@ -5548,6 +5562,16 @@ gnat_to_gnu_component_type (Entity_Id gnat_array, bool definition,
gnat_array);
}
+ /* If the component type is a padded type made for a non-bit-packed array
+ of scalars with reverse storage order, we need to propagate the reverse
+ storage order to the padding type since it is the innermost enclosing
+ aggregate type around the scalar. */
+ if (TYPE_IS_PADDING_P (gnu_type)
+ && Reverse_Storage_Order (gnat_array)
+ && !Is_Bit_Packed_Array (gnat_array)
+ && Is_Scalar_Type (gnat_type))
+ gnu_type = set_reverse_storage_order_on_pad_type (gnu_type);
+
if (Has_Volatile_Components (gnat_array))
{
const int quals
@@ -6718,6 +6742,15 @@ gnat_to_gnu_field (Entity_Id gnat_field, tree gnu_record_type, int packed,
else
gnu_pos = NULL_TREE;
+ /* If the field's type is a padded type made for a scalar field of a record
+ type with reverse storage order, we need to propagate the reverse storage
+ order to the padding type since it is the innermost enclosing aggregate
+ type around the scalar. */
+ if (TYPE_IS_PADDING_P (gnu_field_type)
+ && TYPE_REVERSE_STORAGE_ORDER (gnu_record_type)
+ && Is_Scalar_Type (gnat_field_type))
+ gnu_field_type = set_reverse_storage_order_on_pad_type (gnu_field_type);
+
gcc_assert (TREE_CODE (gnu_field_type) != RECORD_TYPE
|| !TYPE_CONTAINS_TEMPLATE_P (gnu_field_type));
@@ -7034,6 +7067,8 @@ components_to_record (tree gnu_record_type, Node_Id gnat_component_list,
TYPE_NAME (gnu_union_type) = gnu_union_name;
TYPE_ALIGN (gnu_union_type) = 0;
TYPE_PACKED (gnu_union_type) = TYPE_PACKED (gnu_record_type);
+ TYPE_REVERSE_STORAGE_ORDER (gnu_union_type)
+ = TYPE_REVERSE_STORAGE_ORDER (gnu_record_type);
}
/* If all the fields down to this level have a rep clause, find out
@@ -7085,6 +7120,8 @@ components_to_record (tree gnu_record_type, Node_Id gnat_component_list,
record actually gets only the alignment required. */
TYPE_ALIGN (gnu_variant_type) = TYPE_ALIGN (gnu_record_type);
TYPE_PACKED (gnu_variant_type) = TYPE_PACKED (gnu_record_type);
+ TYPE_REVERSE_STORAGE_ORDER (gnu_variant_type)
+ = TYPE_REVERSE_STORAGE_ORDER (gnu_record_type);
/* Similarly, if the outer record has a size specified and all
the fields have a rep clause, we can propagate the size. */
@@ -7177,6 +7214,8 @@ components_to_record (tree gnu_record_type, Node_Id gnat_component_list,
position at this level. */
tree gnu_rep_type = make_node (RECORD_TYPE);
tree gnu_rep_part;
+ TYPE_REVERSE_STORAGE_ORDER (gnu_rep_type)
+ = TYPE_REVERSE_STORAGE_ORDER (gnu_variant_type);
finish_record_type (gnu_rep_type, NULL_TREE, 0, debug_info);
gnu_rep_part
= create_rep_part (gnu_rep_type, gnu_variant_type,
@@ -7384,6 +7423,8 @@ components_to_record (tree gnu_record_type, Node_Id gnat_component_list,
gnu_field_list = gnu_rep_list;
else
{
+ 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);
/* If FIRST_FREE_POS is nonzero, we need to ensure that the fields
diff --git a/gcc/ada/gcc-interface/gigi.h b/gcc/ada/gcc-interface/gigi.h
index 9420fd83f75..d7a25662e80 100644
--- a/gcc/ada/gcc-interface/gigi.h
+++ b/gcc/ada/gcc-interface/gigi.h
@@ -154,6 +154,9 @@ extern tree maybe_pad_type (tree type, tree size, unsigned int align,
bool is_user_type, bool definition,
bool set_rm_size);
+/* Return a copy of the padded TYPE but with reverse storage order. */
+extern tree set_reverse_storage_order_on_pad_type (tree type);
+
enum alias_set_op
{
ALIAS_SET_COPY,
diff --git a/gcc/ada/gcc-interface/trans.c b/gcc/ada/gcc-interface/trans.c
index 946c91a5df9..5c093fbf161 100644
--- a/gcc/ada/gcc-interface/trans.c
+++ b/gcc/ada/gcc-interface/trans.c
@@ -2172,7 +2172,7 @@ Attribute_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p, int attribute)
tree gnu_field_offset;
tree gnu_inner;
machine_mode mode;
- int unsignedp, volatilep;
+ int unsignedp, reversep, volatilep;
gnu_result_type = get_unpadded_type (Etype (gnat_node));
gnu_prefix = remove_conversions (gnu_prefix, true);
@@ -2194,7 +2194,7 @@ Attribute_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p, int attribute)
&& TREE_CODE (gnu_prefix) == FIELD_DECL));
get_inner_reference (gnu_prefix, &bitsize, &bitpos, &gnu_offset,
- &mode, &unsignedp, &volatilep, false);
+ &mode, &unsignedp, &reversep, &volatilep, false);
if (TREE_CODE (gnu_prefix) == COMPONENT_REF)
{
diff --git a/gcc/ada/gcc-interface/utils.c b/gcc/ada/gcc-interface/utils.c
index 8617a876ae6..224dc002bdb 100644
--- a/gcc/ada/gcc-interface/utils.c
+++ b/gcc/ada/gcc-interface/utils.c
@@ -957,6 +957,7 @@ make_packable_type (tree type, bool in_record)
TYPE_NAME (new_type) = TYPE_NAME (type);
TYPE_JUSTIFIED_MODULAR_P (new_type) = TYPE_JUSTIFIED_MODULAR_P (type);
TYPE_CONTAINS_TEMPLATE_P (new_type) = TYPE_CONTAINS_TEMPLATE_P (type);
+ TYPE_REVERSE_STORAGE_ORDER (new_type) = TYPE_REVERSE_STORAGE_ORDER (type);
if (TREE_CODE (type) == RECORD_TYPE)
TYPE_PADDING_P (new_type) = TYPE_PADDING_P (type);
@@ -1175,14 +1176,15 @@ pad_type_hasher::equal (pad_type_hash *t1, pad_type_hash *t2)
type1 = t1->type;
type2 = t2->type;
- /* We consider that the padded types are equivalent if they pad the same
- type and have the same size, alignment and RM size. Taking the mode
- into account is redundant since it is determined by the others. */
+ /* We consider that the padded types are equivalent if they pad the same type
+ and have the same size, alignment, RM size and storage order. Taking the
+ mode into account is redundant since it is determined by the others. */
return
TREE_TYPE (TYPE_FIELDS (type1)) == TREE_TYPE (TYPE_FIELDS (type2))
&& TYPE_SIZE (type1) == TYPE_SIZE (type2)
&& TYPE_ALIGN (type1) == TYPE_ALIGN (type2)
- && TYPE_ADA_SIZE (type1) == TYPE_ADA_SIZE (type2);
+ && TYPE_ADA_SIZE (type1) == TYPE_ADA_SIZE (type2)
+ && TYPE_REVERSE_STORAGE_ORDER (type1) == TYPE_REVERSE_STORAGE_ORDER (type2);
}
/* Look up the padded TYPE in the hash table and return its canonical version
@@ -1452,6 +1454,31 @@ built:
return record;
}
+
+/* Return a copy of the padded TYPE but with reverse storage order. */
+
+tree
+set_reverse_storage_order_on_pad_type (tree type)
+{
+ tree field, canonical_pad_type;
+
+#ifdef ENABLE_CHECKING
+ /* If the inner type is not scalar then the function does nothing. */
+ tree inner_type = TREE_TYPE (TYPE_FIELDS (type));
+ gcc_assert (!AGGREGATE_TYPE_P (inner_type) && !VECTOR_TYPE_P (inner_type));
+#endif
+
+ /* This is required for the canonicalization. */
+ gcc_assert (TREE_CONSTANT (TYPE_SIZE (type)));
+
+ field = copy_node (TYPE_FIELDS (type));
+ type = copy_type (type);
+ DECL_CONTEXT (field) = type;
+ TYPE_FIELDS (type) = field;
+ TYPE_REVERSE_STORAGE_ORDER (type) = 1;
+ canonical_pad_type = lookup_and_insert_pad_type (type);
+ return canonical_pad_type ? canonical_pad_type : type;
+}
/* Relate the alias sets of GNU_NEW_TYPE and GNU_OLD_TYPE according to OP.
If this is a multi-dimensional array type, do this recursively.
@@ -3357,7 +3384,7 @@ gnat_types_compatible_p (tree t1, tree t2)
return 1;
/* Array types are also compatible if they are constrained and have the same
- domain(s) and the same component type. */
+ domain(s), the same component type and the same scalar storage order. */
if (code == ARRAY_TYPE
&& (TYPE_DOMAIN (t1) == TYPE_DOMAIN (t2)
|| (TYPE_DOMAIN (t1)
@@ -3368,7 +3395,8 @@ gnat_types_compatible_p (tree t1, tree t2)
TYPE_MAX_VALUE (TYPE_DOMAIN (t2)))))
&& (TREE_TYPE (t1) == TREE_TYPE (t2)
|| (TREE_CODE (TREE_TYPE (t1)) == ARRAY_TYPE
- && gnat_types_compatible_p (TREE_TYPE (t1), TREE_TYPE (t2)))))
+ && gnat_types_compatible_p (TREE_TYPE (t1), TREE_TYPE (t2))))
+ && TYPE_REVERSE_STORAGE_ORDER (t1) == TYPE_REVERSE_STORAGE_ORDER (t2))
return 1;
return 0;
@@ -4849,17 +4877,38 @@ unchecked_convert (tree type, tree expr, bool notrunc_p)
}
/* If we are converting to an integral type whose precision is not equal
- to its size, first unchecked convert to a record type that contains an
- field of the given precision. Then extract the field. */
+ to its size, first unchecked convert to a record type that contains a
+ field of the given precision. Then extract the result from the field.
+
+ There is a subtlety if the source type is an aggregate type with reverse
+ storage order because its representation is not contiguous in the native
+ storage order, i.e. a direct unchecked conversion to an integral type
+ with N bits of precision cannot read the first N bits of the aggregate
+ type. To overcome it, we do an unchecked conversion to an integral type
+ with reverse storage order and return the resulting value. This also
+ ensures that the result of the unchecked conversion doesn't depend on
+ the endianness of the target machine, but only on the storage order of
+ the aggregate type.
+
+ Finally, for the sake of consistency, we do the unchecked conversion
+ to an integral type with reverse storage order as soon as the source
+ type is an aggregate type with reverse storage order, even if there
+ are no considerations of precision or size involved. */
else if (INTEGRAL_TYPE_P (type)
&& TYPE_RM_SIZE (type)
- && 0 != compare_tree_int (TYPE_RM_SIZE (type),
- GET_MODE_BITSIZE (TYPE_MODE (type))))
+ && (0 != compare_tree_int (TYPE_RM_SIZE (type),
+ GET_MODE_BITSIZE (TYPE_MODE (type)))
+ || (AGGREGATE_TYPE_P (etype)
+ && TYPE_REVERSE_STORAGE_ORDER (etype))))
{
tree rec_type = make_node (RECORD_TYPE);
unsigned HOST_WIDE_INT prec = TREE_INT_CST_LOW (TYPE_RM_SIZE (type));
tree field_type, field;
+ if (AGGREGATE_TYPE_P (etype))
+ TYPE_REVERSE_STORAGE_ORDER (rec_type)
+ = TYPE_REVERSE_STORAGE_ORDER (etype);
+
if (TYPE_UNSIGNED (type))
field_type = make_unsigned_type (prec);
else
@@ -4878,11 +4927,16 @@ unchecked_convert (tree type, tree expr, bool notrunc_p)
/* Similarly if we are converting from an integral type whose precision is
not equal to its size, first copy into a field of the given precision
- and unchecked convert the record type. */
+ and unchecked convert the record type.
+
+ The same considerations as above apply if the target type is an aggregate
+ type with reverse storage order and we also proceed similarly. */
else if (INTEGRAL_TYPE_P (etype)
&& TYPE_RM_SIZE (etype)
- && 0 != compare_tree_int (TYPE_RM_SIZE (etype),
- GET_MODE_BITSIZE (TYPE_MODE (etype))))
+ && (0 != compare_tree_int (TYPE_RM_SIZE (etype),
+ GET_MODE_BITSIZE (TYPE_MODE (etype)))
+ || (AGGREGATE_TYPE_P (type)
+ && TYPE_REVERSE_STORAGE_ORDER (type))))
{
tree rec_type = make_node (RECORD_TYPE);
unsigned HOST_WIDE_INT prec = TREE_INT_CST_LOW (TYPE_RM_SIZE (etype));
@@ -4890,6 +4944,10 @@ unchecked_convert (tree type, tree expr, bool notrunc_p)
vec_alloc (v, 1);
tree field_type, field;
+ if (AGGREGATE_TYPE_P (type))
+ TYPE_REVERSE_STORAGE_ORDER (rec_type)
+ = TYPE_REVERSE_STORAGE_ORDER (type);
+
if (TYPE_UNSIGNED (etype))
field_type = make_unsigned_type (prec);
else
@@ -6040,7 +6098,6 @@ install_builtin_functions (void)
BOTH_P, FALLBACK_P, NONANSI_P, \
built_in_attributes[(int) ATTRS], IMPLICIT);
#include "builtins.def"
-#undef DEF_BUILTIN
}
/* ----------------------------------------------------------------------- *
diff --git a/gcc/ada/gcc-interface/utils2.c b/gcc/ada/gcc-interface/utils2.c
index 47446ba8969..73a9b10d26f 100644
--- a/gcc/ada/gcc-interface/utils2.c
+++ b/gcc/ada/gcc-interface/utils2.c
@@ -1408,11 +1408,11 @@ build_unary_op (enum tree_code op_code, tree result_type, tree operand)
HOST_WIDE_INT bitpos;
tree offset, inner;
machine_mode mode;
- int unsignedp, volatilep;
+ int unsignedp, reversep, volatilep;
inner = get_inner_reference (operand, &bitsize, &bitpos, &offset,
- &mode, &unsignedp, &volatilep,
- false);
+ &mode, &unsignedp, &reversep,
+ &volatilep, false);
/* If INNER is a padding type whose field has a self-referential
size, convert to that inner type. We know the offset is zero
@@ -1916,7 +1916,9 @@ gnat_build_constructor (tree type, vec<constructor_elt, va_gc> *v)
|| (TREE_CODE (type) == RECORD_TYPE
&& CONSTRUCTOR_BITFIELD_P (obj)
&& !initializer_constant_valid_for_bitfield_p (val))
- || !initializer_constant_valid_p (val, TREE_TYPE (val)))
+ || !initializer_constant_valid_p (val,
+ TREE_TYPE (val),
+ TYPE_REVERSE_STORAGE_ORDER (type)))
allconstant = false;
if (!TREE_READONLY (val))
@@ -2749,6 +2751,7 @@ gnat_rewrite_reference (tree ref, rewrite_fn func, void *data, tree *init)
gnat_rewrite_reference (TREE_OPERAND (ref, 0), func,
data, init),
TREE_OPERAND (ref, 1), TREE_OPERAND (ref, 2));
+ REF_REVERSE_STORAGE_ORDER (result) = REF_REVERSE_STORAGE_ORDER (ref);
break;
case ARRAY_REF:
diff --git a/gcc/alloc-pool.h b/gcc/alloc-pool.h
index 0dc05cdb719..bf9b0ebd6ee 100644
--- a/gcc/alloc-pool.h
+++ b/gcc/alloc-pool.h
@@ -480,7 +480,7 @@ public:
inline T *
allocate () ATTRIBUTE_MALLOC
{
- return ::new (m_allocator.allocate ()) T ();
+ return ::new (m_allocator.allocate ()) T;
}
inline void
diff --git a/gcc/asan.c b/gcc/asan.c
index 869a0002f1e..0df5e3234b5 100644
--- a/gcc/asan.c
+++ b/gcc/asan.c
@@ -1779,9 +1779,9 @@ instrument_derefs (gimple_stmt_iterator *iter, tree t,
HOST_WIDE_INT bitsize, bitpos;
tree offset;
machine_mode mode;
- int volatilep = 0, unsignedp = 0;
- tree inner = get_inner_reference (t, &bitsize, &bitpos, &offset,
- &mode, &unsignedp, &volatilep, false);
+ int unsignedp, reversep, volatilep = 0;
+ tree inner = get_inner_reference (t, &bitsize, &bitpos, &offset, &mode,
+ &unsignedp, &reversep, &volatilep, false);
if (TREE_CODE (t) == COMPONENT_REF
&& DECL_BIT_FIELD_REPRESENTATIVE (TREE_OPERAND (t, 1)) != NULL_TREE)
diff --git a/gcc/bb-reorder.c b/gcc/bb-reorder.c
index 5f1c2ccc6cb..950b1a1089d 100644
--- a/gcc/bb-reorder.c
+++ b/gcc/bb-reorder.c
@@ -2304,7 +2304,9 @@ reorder_basic_blocks_simple (void)
if (JUMP_P (end) && extract_asm_operands (end))
continue;
- if (any_condjump_p (end))
+ if (single_succ_p (bb))
+ edges[n++] = EDGE_SUCC (bb, 0);
+ else if (any_condjump_p (end))
{
edge e0 = EDGE_SUCC (bb, 0);
edge e1 = EDGE_SUCC (bb, 1);
@@ -2315,8 +2317,6 @@ reorder_basic_blocks_simple (void)
edges[n++] = e0;
edges[n++] = e1;
}
- else if (single_succ_p (bb))
- edges[n++] = EDGE_SUCC (bb, 0);
}
/* Sort the edges, the most desirable first. When optimizing for size
diff --git a/gcc/builtins.c b/gcc/builtins.c
index 8f0717c7e1b..85b251ae092 100644
--- a/gcc/builtins.c
+++ b/gcc/builtins.c
@@ -78,7 +78,6 @@ const char * built_in_names[(int) END_BUILTINS] =
{
#include "builtins.def"
};
-#undef DEF_BUILTIN
/* Setup an array of builtin_info_type, make sure each element decl is
initialized to NULL_TREE. */
@@ -143,12 +142,10 @@ static tree fold_builtin_constant_p (tree);
static tree fold_builtin_classify_type (tree);
static tree fold_builtin_strlen (location_t, tree, tree);
static tree fold_builtin_inf (location_t, tree, int);
-static tree fold_builtin_nan (tree, tree, int);
static tree rewrite_call_expr (location_t, tree, int, tree, int, ...);
static bool validate_arg (const_tree, enum tree_code code);
static rtx expand_builtin_fabs (tree, rtx, rtx);
static rtx expand_builtin_signbit (tree, rtx);
-static tree fold_builtin_bitop (tree, tree);
static tree fold_builtin_strchr (location_t, tree, tree, tree);
static tree fold_builtin_memchr (location_t, tree, tree, tree, tree);
static tree fold_builtin_memcmp (location_t, tree, tree, tree);
@@ -255,14 +252,14 @@ get_object_alignment_2 (tree exp, unsigned int *alignp,
HOST_WIDE_INT bitsize, bitpos;
tree offset;
machine_mode mode;
- int unsignedp, volatilep;
+ int unsignedp, reversep, volatilep;
unsigned int align = BITS_PER_UNIT;
bool known_alignment = false;
/* Get the innermost object and the constant (bitpos) and possibly
variable (offset) offset of the access. */
- exp = get_inner_reference (exp, &bitsize, &bitpos, &offset,
- &mode, &unsignedp, &volatilep, true);
+ exp = get_inner_reference (exp, &bitsize, &bitpos, &offset, &mode,
+ &unsignedp, &reversep, &volatilep, true);
/* Extract alignment information from the innermost object and
possibly adjust bitpos and offset. */
@@ -616,27 +613,6 @@ c_strlen (tree src, int only_value)
return ssize_int (strlen (ptr + offset));
}
-/* Return a char pointer for a C string if it is a string constant
- or sum of string constant and integer constant. */
-
-const char *
-c_getstr (tree src)
-{
- tree offset_node;
-
- src = string_constant (src, &offset_node);
- if (src == 0)
- return 0;
-
- if (offset_node == 0)
- return TREE_STRING_POINTER (src);
- else if (!tree_fits_uhwi_p (offset_node)
- || compare_tree_int (offset_node, TREE_STRING_LENGTH (src) - 1) > 0)
- return 0;
-
- return TREE_STRING_POINTER (src) + tree_to_uhwi (offset_node);
-}
-
/* Return a constant integer corresponding to target reading
GET_MODE_BITSIZE (MODE) bits from string constant STR. */
@@ -7286,26 +7262,6 @@ fold_builtin_inf (location_t loc, tree type, int warn)
return build_real (type, real);
}
-/* Fold a call to __builtin_nan or __builtin_nans with argument ARG. */
-
-static tree
-fold_builtin_nan (tree arg, tree type, int quiet)
-{
- REAL_VALUE_TYPE real;
- const char *str;
-
- if (!validate_arg (arg, POINTER_TYPE))
- return NULL_TREE;
- str = c_getstr (arg);
- if (!str)
- return NULL_TREE;
-
- if (!real_nan (&real, str, quiet, TYPE_MODE (type)))
- return NULL_TREE;
-
- return build_real (type, real);
-}
-
/* Fold function call to builtin sincos, sincosf, or sincosl. Return
NULL_TREE if no simplification can be made. */
@@ -7353,99 +7309,6 @@ fold_builtin_sincos (location_t loc,
fold_build1_loc (loc, REALPART_EXPR, type, call)));
}
-/* Fold function call to builtin ffs, clz, ctz, popcount and parity
- and their long and long long variants (i.e. ffsl and ffsll). ARG is
- the argument to the call. Return NULL_TREE if no simplification can
- be made. */
-
-static tree
-fold_builtin_bitop (tree fndecl, tree arg)
-{
- if (!validate_arg (arg, INTEGER_TYPE))
- return NULL_TREE;
-
- /* Optimize for constant argument. */
- if (TREE_CODE (arg) == INTEGER_CST && !TREE_OVERFLOW (arg))
- {
- tree type = TREE_TYPE (arg);
- int result;
-
- switch (DECL_FUNCTION_CODE (fndecl))
- {
- CASE_INT_FN (BUILT_IN_FFS):
- result = wi::ffs (arg);
- break;
-
- CASE_INT_FN (BUILT_IN_CLZ):
- if (wi::ne_p (arg, 0))
- result = wi::clz (arg);
- else if (! CLZ_DEFINED_VALUE_AT_ZERO (TYPE_MODE (type), result))
- result = TYPE_PRECISION (type);
- break;
-
- CASE_INT_FN (BUILT_IN_CTZ):
- if (wi::ne_p (arg, 0))
- result = wi::ctz (arg);
- else if (! CTZ_DEFINED_VALUE_AT_ZERO (TYPE_MODE (type), result))
- result = TYPE_PRECISION (type);
- break;
-
- CASE_INT_FN (BUILT_IN_CLRSB):
- result = wi::clrsb (arg);
- break;
-
- CASE_INT_FN (BUILT_IN_POPCOUNT):
- result = wi::popcount (arg);
- break;
-
- CASE_INT_FN (BUILT_IN_PARITY):
- result = wi::parity (arg);
- break;
-
- default:
- gcc_unreachable ();
- }
-
- return build_int_cst (TREE_TYPE (TREE_TYPE (fndecl)), result);
- }
-
- return NULL_TREE;
-}
-
-/* Fold function call to builtin_bswap and the short, long and long long
- variants. Return NULL_TREE if no simplification can be made. */
-static tree
-fold_builtin_bswap (tree fndecl, tree arg)
-{
- if (! validate_arg (arg, INTEGER_TYPE))
- return NULL_TREE;
-
- /* Optimize constant value. */
- if (TREE_CODE (arg) == INTEGER_CST && !TREE_OVERFLOW (arg))
- {
- tree type = TREE_TYPE (TREE_TYPE (fndecl));
-
- switch (DECL_FUNCTION_CODE (fndecl))
- {
- case BUILT_IN_BSWAP16:
- case BUILT_IN_BSWAP32:
- case BUILT_IN_BSWAP64:
- {
- signop sgn = TYPE_SIGN (type);
- tree result =
- wide_int_to_tree (type,
- wide_int::from (arg, TYPE_PRECISION (type),
- sgn).bswap ());
- return result;
- }
- default:
- gcc_unreachable ();
- }
- }
-
- return NULL_TREE;
-}
-
/* Fold function call to builtin memchr. ARG1, ARG2 and LEN are the
arguments to the call, and TYPE is its return type.
Return NULL_TREE if no simplification can be made. */
@@ -7493,8 +7356,6 @@ fold_builtin_memchr (location_t loc, tree arg1, tree arg2, tree len, tree type)
static tree
fold_builtin_memcmp (location_t loc, tree arg1, tree arg2, tree len)
{
- const char *p1, *p2;
-
if (!validate_arg (arg1, POINTER_TYPE)
|| !validate_arg (arg2, POINTER_TYPE)
|| !validate_arg (len, INTEGER_TYPE))
@@ -7509,25 +7370,6 @@ fold_builtin_memcmp (location_t loc, tree arg1, tree arg2, tree len)
if (operand_equal_p (arg1, arg2, 0))
return omit_one_operand_loc (loc, integer_type_node, integer_zero_node, len);
- p1 = c_getstr (arg1);
- p2 = c_getstr (arg2);
-
- /* If all arguments are constant, and the value of len is not greater
- than the lengths of arg1 and arg2, evaluate at compile-time. */
- if (tree_fits_uhwi_p (len) && p1 && p2
- && compare_tree_int (len, strlen (p1) + 1) <= 0
- && compare_tree_int (len, strlen (p2) + 1) <= 0)
- {
- const int r = memcmp (p1, p2, tree_to_uhwi (len));
-
- if (r > 0)
- return integer_one_node;
- else if (r < 0)
- return integer_minus_one_node;
- else
- return integer_zero_node;
- }
-
/* If len parameter is one, return an expression corresponding to
(*(const unsigned char*)arg1 - (const unsigned char*)arg2). */
if (tree_fits_uhwi_p (len) && tree_to_uhwi (len) == 1)
@@ -7560,8 +7402,6 @@ fold_builtin_memcmp (location_t loc, tree arg1, tree arg2, tree len)
static tree
fold_builtin_strcmp (location_t loc, tree arg1, tree arg2)
{
- const char *p1, *p2;
-
if (!validate_arg (arg1, POINTER_TYPE)
|| !validate_arg (arg2, POINTER_TYPE))
return NULL_TREE;
@@ -7570,21 +7410,8 @@ fold_builtin_strcmp (location_t loc, tree arg1, tree arg2)
if (operand_equal_p (arg1, arg2, 0))
return integer_zero_node;
- p1 = c_getstr (arg1);
- p2 = c_getstr (arg2);
-
- if (p1 && p2)
- {
- const int i = strcmp (p1, p2);
- if (i < 0)
- return integer_minus_one_node;
- else if (i > 0)
- return integer_one_node;
- else
- return integer_zero_node;
- }
-
/* If the second arg is "", return *(const unsigned char*)arg1. */
+ const char *p2 = c_getstr (arg2);
if (p2 && *p2 == '\0')
{
tree cst_uchar_node = build_type_variant (unsigned_char_type_node, 1, 0);
@@ -7599,6 +7426,7 @@ fold_builtin_strcmp (location_t loc, tree arg1, tree arg2)
}
/* If the first arg is "", return -*(const unsigned char*)arg2. */
+ const char *p1 = c_getstr (arg1);
if (p1 && *p1 == '\0')
{
tree cst_uchar_node = build_type_variant (unsigned_char_type_node, 1, 0);
@@ -7623,8 +7451,6 @@ fold_builtin_strcmp (location_t loc, tree arg1, tree arg2)
static tree
fold_builtin_strncmp (location_t loc, tree arg1, tree arg2, tree len)
{
- const char *p1, *p2;
-
if (!validate_arg (arg1, POINTER_TYPE)
|| !validate_arg (arg2, POINTER_TYPE)
|| !validate_arg (len, INTEGER_TYPE))
@@ -7639,22 +7465,9 @@ fold_builtin_strncmp (location_t loc, tree arg1, tree arg2, tree len)
if (operand_equal_p (arg1, arg2, 0))
return omit_one_operand_loc (loc, integer_type_node, integer_zero_node, len);
- p1 = c_getstr (arg1);
- p2 = c_getstr (arg2);
-
- if (tree_fits_uhwi_p (len) && p1 && p2)
- {
- const int i = strncmp (p1, p2, tree_to_uhwi (len));
- if (i > 0)
- return integer_one_node;
- else if (i < 0)
- return integer_minus_one_node;
- else
- return integer_zero_node;
- }
-
/* If the second arg is "", and the length is greater than zero,
return *(const unsigned char*)arg1. */
+ const char *p2 = c_getstr (arg2);
if (p2 && *p2 == '\0'
&& TREE_CODE (len) == INTEGER_CST
&& tree_int_cst_sgn (len) == 1)
@@ -7672,6 +7485,7 @@ fold_builtin_strncmp (location_t loc, tree arg1, tree arg2, tree len)
/* If the first arg is "", and the length is greater than zero,
return -*(const unsigned char*)arg2. */
+ const char *p1 = c_getstr (arg1);
if (p1 && *p1 == '\0'
&& TREE_CODE (len) == INTEGER_CST
&& tree_int_cst_sgn (len) == 1)
@@ -8039,7 +7853,6 @@ static tree
fold_builtin_classify (location_t loc, tree fndecl, tree arg, int builtin_index)
{
tree type = TREE_TYPE (TREE_TYPE (fndecl));
- REAL_VALUE_TYPE r;
if (!validate_arg (arg, REAL_TYPE))
return NULL_TREE;
@@ -8050,16 +7863,6 @@ fold_builtin_classify (location_t loc, tree fndecl, tree arg, int builtin_index)
if (!HONOR_INFINITIES (arg))
return omit_one_operand_loc (loc, type, integer_zero_node, arg);
- if (TREE_CODE (arg) == REAL_CST)
- {
- r = TREE_REAL_CST (arg);
- if (real_isinf (&r))
- return real_compare (GT_EXPR, &r, &dconst0)
- ? integer_one_node : integer_minus_one_node;
- else
- return integer_zero_node;
- }
-
return NULL_TREE;
case BUILT_IN_ISINF_SIGN:
@@ -8099,24 +7902,12 @@ fold_builtin_classify (location_t loc, tree fndecl, tree arg, int builtin_index)
&& !HONOR_INFINITIES (arg))
return omit_one_operand_loc (loc, type, integer_one_node, arg);
- if (TREE_CODE (arg) == REAL_CST)
- {
- r = TREE_REAL_CST (arg);
- return real_isfinite (&r) ? integer_one_node : integer_zero_node;
- }
-
return NULL_TREE;
case BUILT_IN_ISNAN:
if (!HONOR_NANS (arg))
return omit_one_operand_loc (loc, type, integer_zero_node, arg);
- if (TREE_CODE (arg) == REAL_CST)
- {
- r = TREE_REAL_CST (arg);
- return real_isnan (&r) ? integer_one_node : integer_zero_node;
- }
-
arg = builtin_save_expr (arg);
return fold_build2_loc (loc, UNORDERED_EXPR, type, arg, arg);
@@ -8399,28 +8190,6 @@ fold_builtin_1 (location_t loc, tree fndecl, tree arg0)
CASE_FLT_FN (BUILT_IN_CARG):
return fold_builtin_carg (loc, arg0, type);
- CASE_FLT_FN (BUILT_IN_NAN):
- case BUILT_IN_NAND32:
- case BUILT_IN_NAND64:
- case BUILT_IN_NAND128:
- return fold_builtin_nan (arg0, type, true);
-
- CASE_FLT_FN (BUILT_IN_NANS):
- return fold_builtin_nan (arg0, type, false);
-
- case BUILT_IN_BSWAP16:
- case BUILT_IN_BSWAP32:
- case BUILT_IN_BSWAP64:
- return fold_builtin_bswap (fndecl, arg0);
-
- CASE_INT_FN (BUILT_IN_FFS):
- CASE_INT_FN (BUILT_IN_CLZ):
- CASE_INT_FN (BUILT_IN_CTZ):
- CASE_INT_FN (BUILT_IN_CLRSB):
- CASE_INT_FN (BUILT_IN_POPCOUNT):
- CASE_INT_FN (BUILT_IN_PARITY):
- return fold_builtin_bitop (fndecl, arg0);
-
case BUILT_IN_ISASCII:
return fold_builtin_isascii (loc, arg0);
@@ -9226,13 +8995,6 @@ fold_builtin_strspn (location_t loc, tree s1, tree s2)
{
const char *p1 = c_getstr (s1), *p2 = c_getstr (s2);
- /* If both arguments are constants, evaluate at compile-time. */
- if (p1 && p2)
- {
- const size_t r = strspn (p1, p2);
- return build_int_cst (size_type_node, r);
- }
-
/* If either argument is "", return NULL_TREE. */
if ((p1 && *p1 == '\0') || (p2 && *p2 == '\0'))
/* Evaluate and ignore both arguments in case either one has
@@ -9269,16 +9031,8 @@ fold_builtin_strcspn (location_t loc, tree s1, tree s2)
return NULL_TREE;
else
{
- const char *p1 = c_getstr (s1), *p2 = c_getstr (s2);
-
- /* If both arguments are constants, evaluate at compile-time. */
- if (p1 && p2)
- {
- const size_t r = strcspn (p1, p2);
- return build_int_cst (size_type_node, r);
- }
-
/* If the first argument is "", return NULL_TREE. */
+ const char *p1 = c_getstr (s1);
if (p1 && *p1 == '\0')
{
/* Evaluate and ignore argument s2 in case it has
@@ -9288,6 +9042,7 @@ fold_builtin_strcspn (location_t loc, tree s1, tree s2)
}
/* If the second argument is "", return __builtin_strlen(s1). */
+ const char *p2 = c_getstr (s2);
if (p2 && *p2 == '\0')
{
tree fn = builtin_decl_implicit (BUILT_IN_STRLEN);
diff --git a/gcc/builtins.def b/gcc/builtins.def
index 886b45ccec3..ed850df2d01 100644
--- a/gcc/builtins.def
+++ b/gcc/builtins.def
@@ -475,9 +475,9 @@ DEF_C99_BUILTIN (BUILT_IN_REMAINDERL, "remainderl", BT_FN_LONGDOUBLE_LONG
DEF_C99_BUILTIN (BUILT_IN_REMQUO, "remquo", BT_FN_DOUBLE_DOUBLE_DOUBLE_INTPTR, ATTR_MATHFN_FPROUNDING_STORE)
DEF_C99_BUILTIN (BUILT_IN_REMQUOF, "remquof", BT_FN_FLOAT_FLOAT_FLOAT_INTPTR, ATTR_MATHFN_FPROUNDING_STORE)
DEF_C99_BUILTIN (BUILT_IN_REMQUOL, "remquol", BT_FN_LONGDOUBLE_LONGDOUBLE_LONGDOUBLE_INTPTR, ATTR_MATHFN_FPROUNDING_STORE)
-DEF_C99_BUILTIN (BUILT_IN_RINT, "rint", BT_FN_DOUBLE_DOUBLE, ATTR_MATHFN_FPROUNDING_ERRNO)
-DEF_C99_BUILTIN (BUILT_IN_RINTF, "rintf", BT_FN_FLOAT_FLOAT, ATTR_MATHFN_FPROUNDING_ERRNO)
-DEF_C99_BUILTIN (BUILT_IN_RINTL, "rintl", BT_FN_LONGDOUBLE_LONGDOUBLE, ATTR_MATHFN_FPROUNDING_ERRNO)
+DEF_C99_BUILTIN (BUILT_IN_RINT, "rint", BT_FN_DOUBLE_DOUBLE, ATTR_MATHFN_FPROUNDING)
+DEF_C99_BUILTIN (BUILT_IN_RINTF, "rintf", BT_FN_FLOAT_FLOAT, ATTR_MATHFN_FPROUNDING)
+DEF_C99_BUILTIN (BUILT_IN_RINTL, "rintl", BT_FN_LONGDOUBLE_LONGDOUBLE, ATTR_MATHFN_FPROUNDING)
DEF_C99_BUILTIN (BUILT_IN_ROUND, "round", BT_FN_DOUBLE_DOUBLE, ATTR_CONST_NOTHROW_LEAF_LIST)
DEF_C99_BUILTIN (BUILT_IN_ROUNDF, "roundf", BT_FN_FLOAT_FLOAT, ATTR_CONST_NOTHROW_LEAF_LIST)
DEF_C99_BUILTIN (BUILT_IN_ROUNDL, "roundl", BT_FN_LONGDOUBLE_LONGDOUBLE, ATTR_CONST_NOTHROW_LEAF_LIST)
@@ -945,3 +945,6 @@ DEF_GCC_BUILTIN (BUILT_IN_LINE, "LINE", BT_FN_INT, ATTR_NOTHROW_LEAF_LIST)
/* Pointer Bounds Checker builtins. */
#include "chkp-builtins.def"
+
+#undef DEF_BUILTIN_CHKP
+#undef DEF_BUILTIN
diff --git a/gcc/builtins.h b/gcc/builtins.h
index cce9e7507a2..b0396322fa0 100644
--- a/gcc/builtins.h
+++ b/gcc/builtins.h
@@ -87,7 +87,6 @@ extern bool is_simple_builtin (tree);
extern bool is_inexpensive_builtin (tree);
extern bool readonly_data_expr (tree exp);
-extern const char *c_getstr (tree);
extern bool init_target_chars (void);
extern unsigned HOST_WIDE_INT target_newline;
extern unsigned HOST_WIDE_INT target_percent;
diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog
index cc9a6420407..f52b3e354c5 100644
--- a/gcc/c-family/ChangeLog
+++ b/gcc/c-family/ChangeLog
@@ -1,3 +1,33 @@
+2015-11-08 Eric Botcazou <ebotcazou@adacore.com>
+
+ * c-common.c (c_common_attributes): Add scalar_storage_order.
+ (handle_scalar_storage_order_attribute): New function.
+ * c-pragma.c (global_sso): New variable.
+ (maybe_apply_pragma_scalar_storage_order): New function.
+ (handle_pragma_scalar_storage_order): Likewise.
+ (init_pragma): Register scalar_storage_order.
+ * c-pragma.h (maybe_apply_pragma_scalar_storage_order): Declare.
+ * c.opt (Wscalar-storage-order): New warning.
+ (fsso-struct=): New option.
+
+2015-11-08 Martin Sebor <msebor@redhat.com>
+
+ * c.opt (Wplacement-new): Add a period to the end of a sentence.
+
+2015-11-07 Richard Sandiford <richard.sandiford@arm.com>
+
+ * c-common.c: Don't undef DEF_BUILTIN.
+
+2015-11-06 David Malcolm <dmalcolm@redhat.com>
+
+ * c-common.c (c_cpp_error): Convert parameter from location_t to
+ rich_location *. Eliminate the "column_override" parameter and
+ the call to diagnostic_override_column.
+ Update the "done_lexing" clause to set range 0
+ on the rich_location, rather than overwriting a location_t.
+ * c-common.h (c_cpp_error): Convert parameter from location_t to
+ rich_location *. Eliminate the "column_override" parameter.
+
2015-11-05 Cesar Philippidis <cesar@codesourcery.com>
Thomas Schwinge <thomas@codesourcery.com>
James Norris <jnorris@codesourcery.com>
diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c
index de5f8b6cbdf..53c1d81c0c8 100644
--- a/gcc/c-family/c-common.c
+++ b/gcc/c-family/c-common.c
@@ -339,6 +339,8 @@ static tree handle_no_reorder_attribute (tree *, tree, tree, int,
static tree handle_const_attribute (tree *, tree, tree, int, bool *);
static tree handle_transparent_union_attribute (tree *, tree, tree,
int, bool *);
+static tree handle_scalar_storage_order_attribute (tree *, tree, tree,
+ int, bool *);
static tree handle_constructor_attribute (tree *, tree, tree, int, bool *);
static tree handle_destructor_attribute (tree *, tree, tree, int, bool *);
static tree handle_mode_attribute (tree *, tree, tree, int, bool *);
@@ -693,6 +695,8 @@ const struct attribute_spec c_common_attribute_table[] =
/* The same comments as for noreturn attributes apply to const ones. */
{ "const", 0, 0, true, false, false,
handle_const_attribute, false },
+ { "scalar_storage_order", 1, 1, false, false, false,
+ handle_scalar_storage_order_attribute, false },
{ "transparent_union", 0, 0, false, false, false,
handle_transparent_union_attribute, false },
{ "constructor", 0, 1, true, false, false,
@@ -5735,7 +5739,6 @@ c_define_builtins (tree va_list_ref_type_node, tree va_list_arg_type_node)
BOTH_P, FALLBACK_P, NONANSI_P, \
built_in_attributes[(int) ATTRS], IMPLICIT);
#include "builtins.def"
-#undef DEF_BUILTIN
targetm.init_builtins ();
@@ -7669,6 +7672,62 @@ handle_const_attribute (tree *node, tree name, tree ARG_UNUSED (args),
return NULL_TREE;
}
+/* Handle a "scalar_storage_order" attribute; arguments as in
+ struct attribute_spec.handler. */
+
+static tree
+handle_scalar_storage_order_attribute (tree *node, tree name, tree args,
+ int flags, bool *no_add_attrs)
+{
+ tree id = TREE_VALUE (args);
+ tree type;
+
+ if (TREE_CODE (*node) == TYPE_DECL
+ && ! (flags & ATTR_FLAG_CXX11))
+ node = &TREE_TYPE (*node);
+ type = *node;
+
+ if (BYTES_BIG_ENDIAN != WORDS_BIG_ENDIAN)
+ {
+ error ("scalar_storage_order is not supported because endianness "
+ "is not uniform");
+ return NULL_TREE;
+ }
+
+ if (RECORD_OR_UNION_TYPE_P (type) && !c_dialect_cxx ())
+ {
+ bool reverse = false;
+
+ if (TREE_CODE (id) == STRING_CST
+ && strcmp (TREE_STRING_POINTER (id), "big-endian") == 0)
+ reverse = !BYTES_BIG_ENDIAN;
+ else if (TREE_CODE (id) == STRING_CST
+ && strcmp (TREE_STRING_POINTER (id), "little-endian") == 0)
+ reverse = BYTES_BIG_ENDIAN;
+ else
+ {
+ error ("scalar_storage_order argument must be one of \"big-endian\""
+ " or \"little-endian\"");
+ return NULL_TREE;
+ }
+
+ if (!(flags & (int) ATTR_FLAG_TYPE_IN_PLACE))
+ {
+ if (reverse)
+ /* A type variant isn't good enough, since we don't want a cast
+ to such a type to be removed as a no-op. */
+ *node = type = build_duplicate_type (type);
+ }
+
+ TYPE_REVERSE_STORAGE_ORDER (type) = reverse;
+ return NULL_TREE;
+ }
+
+ warning (OPT_Wattributes, "%qE attribute ignored", name);
+ *no_add_attrs = true;
+ return NULL_TREE;
+}
+
/* Handle a "transparent_union" attribute; arguments as in
struct attribute_spec.handler. */
@@ -7681,7 +7740,6 @@ handle_transparent_union_attribute (tree *node, tree name,
*no_add_attrs = true;
-
if (TREE_CODE (*node) == TYPE_DECL
&& ! (flags & ATTR_FLAG_CXX11))
node = &TREE_TYPE (*node);
@@ -7712,8 +7770,8 @@ handle_transparent_union_attribute (tree *node, tree name,
if (c_dialect_cxx ())
goto ignored;
- /* A type variant isn't good enough, since we don't a cast
- to such a type removed as a no-op. */
+ /* A type variant isn't good enough, since we don't want a cast
+ to such a type to be removed as a no-op. */
*node = type = build_duplicate_type (type);
}
@@ -10543,15 +10601,14 @@ c_option_controlling_cpp_error (int reason)
/* Callback from cpp_error for PFILE to print diagnostics from the
preprocessor. The diagnostic is of type LEVEL, with REASON set
to the reason code if LEVEL is represents a warning, at location
- LOCATION unless this is after lexing and the compiler's location
- should be used instead, with column number possibly overridden by
- COLUMN_OVERRIDE if not zero; MSG is the translated message and AP
+ RICHLOC unless this is after lexing and the compiler's location
+ should be used instead; MSG is the translated message and AP
the arguments. Returns true if a diagnostic was emitted, false
otherwise. */
bool
c_cpp_error (cpp_reader *pfile ATTRIBUTE_UNUSED, int level, int reason,
- location_t location, unsigned int column_override,
+ rich_location *richloc,
const char *msg, va_list *ap)
{
diagnostic_info diagnostic;
@@ -10592,11 +10649,11 @@ c_cpp_error (cpp_reader *pfile ATTRIBUTE_UNUSED, int level, int reason,
gcc_unreachable ();
}
if (done_lexing)
- location = input_location;
+ richloc->set_range (0,
+ source_range::from_location (input_location),
+ true, true);
diagnostic_set_info_translated (&diagnostic, msg, ap,
- location, dlevel);
- if (column_override)
- diagnostic_override_column (&diagnostic, column_override);
+ richloc, dlevel);
diagnostic_override_option_index (&diagnostic,
c_option_controlling_cpp_error (reason));
ret = report_diagnostic (&diagnostic);
diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h
index de9768e9214..c82545405e4 100644
--- a/gcc/c-family/c-common.h
+++ b/gcc/c-family/c-common.h
@@ -995,9 +995,9 @@ extern void init_c_lex (void);
extern void c_cpp_builtins (cpp_reader *);
extern void c_cpp_builtins_optimize_pragma (cpp_reader *, tree, tree);
-extern bool c_cpp_error (cpp_reader *, int, int, location_t, unsigned int,
+extern bool c_cpp_error (cpp_reader *, int, int, rich_location *,
const char *, va_list *)
- ATTRIBUTE_GCC_DIAG(6,0);
+ ATTRIBUTE_GCC_DIAG(5,0);
extern int c_common_has_attribute (cpp_reader *);
extern bool parse_optimize_options (tree, bool);
diff --git a/gcc/c-family/c-pragma.c b/gcc/c-family/c-pragma.c
index ac118382816..ffc5b33a4cd 100644
--- a/gcc/c-family/c-pragma.c
+++ b/gcc/c-family/c-pragma.c
@@ -388,6 +388,51 @@ handle_pragma_weak (cpp_reader * ARG_UNUSED (dummy))
}
}
+static enum scalar_storage_order_kind global_sso;
+
+void
+maybe_apply_pragma_scalar_storage_order (tree type)
+{
+ if (global_sso == SSO_NATIVE)
+ return;
+
+ gcc_assert (RECORD_OR_UNION_TYPE_P (type));
+
+ if (lookup_attribute ("scalar_storage_order", TYPE_ATTRIBUTES (type)))
+ return;
+
+ if (global_sso == SSO_BIG_ENDIAN)
+ TYPE_REVERSE_STORAGE_ORDER (type) = !BYTES_BIG_ENDIAN;
+ else if (global_sso == SSO_LITTLE_ENDIAN)
+ TYPE_REVERSE_STORAGE_ORDER (type) = BYTES_BIG_ENDIAN;
+ else
+ gcc_unreachable ();
+}
+
+static void
+handle_pragma_scalar_storage_order (cpp_reader *ARG_UNUSED(dummy))
+{
+ const char *kind_string;
+ enum cpp_ttype token;
+ tree x;
+
+ if (BYTES_BIG_ENDIAN != WORDS_BIG_ENDIAN)
+ error ("scalar_storage_order is not supported");
+
+ token = pragma_lex (&x);
+ if (token != CPP_NAME)
+ GCC_BAD ("missing [big-endian|little-endian|default] after %<#pragma scalar_storage_order%>");
+ kind_string = IDENTIFIER_POINTER (x);
+ if (strcmp (kind_string, "default") == 0)
+ global_sso = default_sso;
+ else if (strcmp (kind_string, "big") == 0)
+ global_sso = SSO_BIG_ENDIAN;
+ else if (strcmp (kind_string, "little") == 0)
+ global_sso = SSO_LITTLE_ENDIAN;
+ else
+ GCC_BAD ("expected [big-endian|little-endian|default] after %<#pragma scalar_storage_order%>");
+}
+
/* GCC supports two #pragma directives for renaming the external
symbol associated with a declaration (DECL_ASSEMBLER_NAME), for
compatibility with the Solaris and VMS system headers. GCC also
@@ -1481,6 +1526,7 @@ init_pragma (void)
c_register_pragma (0, "pack", handle_pragma_pack);
#endif
c_register_pragma (0, "weak", handle_pragma_weak);
+
c_register_pragma ("GCC", "visibility", handle_pragma_visibility);
c_register_pragma ("GCC", "diagnostic", handle_pragma_diagnostic);
@@ -1502,6 +1548,10 @@ init_pragma (void)
REGISTER_TARGET_PRAGMAS ();
#endif
+ global_sso = default_sso;
+ c_register_pragma (0, "scalar_storage_order",
+ handle_pragma_scalar_storage_order);
+
/* Allow plugins to register their own pragmas. */
invoke_plugin_callbacks (PLUGIN_PRAGMAS, NULL);
}
diff --git a/gcc/c-family/c-pragma.h b/gcc/c-family/c-pragma.h
index 953c4e31d04..59231ce030e 100644
--- a/gcc/c-family/c-pragma.h
+++ b/gcc/c-family/c-pragma.h
@@ -227,6 +227,7 @@ extern void c_invoke_pragma_handler (unsigned int);
extern void maybe_apply_pragma_weak (tree);
extern void maybe_apply_pending_pragma_weaks (void);
extern tree maybe_apply_renaming_pragma (tree, tree);
+extern void maybe_apply_pragma_scalar_storage_order (tree);
extern void add_to_renaming_pragma_list (tree, tree);
extern enum cpp_ttype pragma_lex (tree *, location_t *loc = NULL);
diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt
index 5f38018d35e..aafd80207b1 100644
--- a/gcc/c-family/c.opt
+++ b/gcc/c-family/c.opt
@@ -778,7 +778,7 @@ Warn if inherited methods are unimplemented.
Wplacement-new
C++ Var(warn_placement_new) Init(1) Warning
-Warn for placement new expressions with undefined behavior
+Warn for placement new expressions with undefined behavior.
Wredundant-decls
C ObjC C++ ObjC++ Var(warn_redundant_decls) Warning
@@ -792,6 +792,10 @@ Wreturn-type
C ObjC C++ ObjC++ Var(warn_return_type) Warning LangEnabledBy(C ObjC C++ ObjC++,Wall)
Warn whenever a function's return type defaults to \"int\" (C), or about inconsistent return types (C++).
+Wscalar-storage-order
+C ObjC C++ ObjC++ Init(1) Warning
+Warn on suspicious constructs involving reverse scalar storage order.
+
Wselector
ObjC ObjC++ Var(warn_selector) Warning
Warn if a selector has multiple methods.
@@ -1454,6 +1458,19 @@ Enable C++14 sized deallocation support.
fsquangle
C++ ObjC++ Ignore Warn(switch %qs is no longer supported)
+fsso-struct=
+C ObjC Joined Enum(sso_struct) Var(default_sso) Init(SSO_NATIVE)
+-fsso-struct=[big-endian|little-endian] Set the default scalar storage order.
+
+Enum
+Name(sso_struct) Type(enum scalar_storage_order_kind) UnknownError(unrecognized scalar storage order value %qs)
+
+EnumValue
+Enum(sso_struct) String(big-endian) Value(SSO_BIG_ENDIAN)
+
+EnumValue
+Enum(sso_struct) String(little-endian) Value(SSO_LITTLE_ENDIAN)
+
fstats
C++ ObjC++ Var(flag_detailed_statistics)
Display statistics accumulated during compilation.
diff --git a/gcc/c/ChangeLog b/gcc/c/ChangeLog
index c734a81f45c..6fea3a996e9 100644
--- a/gcc/c/ChangeLog
+++ b/gcc/c/ChangeLog
@@ -1,3 +1,23 @@
+2015-11-08 Eric Botcazou <ebotcazou@adacore.com>
+
+ * c-decl.c (finish_struct): If the structure has reverse storage
+ order, rewrite the type of array fields with scalar component. Call
+ maybe_apply_pragma_scalar_storage_order on entry.
+ * c-typeck.c (build_unary_op) <ADDR_EXPR>: Remove left-overs. Issue
+ errors on bit-fields and reverse SSO here and not...
+ (c_mark_addressable): ...here.
+ (output_init_element): Adjust call to initializer_constant_valid_p.
+ (c_build_qualified_type): Propagate TYPE_REVERSE_STORAGE_ORDER.
+
+2015-11-06 David Malcolm <dmalcolm@redhat.com>
+
+ * c-decl.c (warn_defaults_to): Update for change in signature
+ of diagnostic_set_info.
+ * c-errors.c (pedwarn_c99): Likewise.
+ (pedwarn_c90): Likewise.
+ * c-objc-common.c (c_tree_printer): Update for new "caret_p" param
+ for textinfo::set_location.
+
2015-11-05 Cesar Philippidis <cesar@codesourcery.com>
Thomas Schwinge <thomas@codesourcery.com>
James Norris <jnorris@codesourcery.com>
diff --git a/gcc/c/c-decl.c b/gcc/c/c-decl.c
index 8e355bae637..a3d8eada928 100644
--- a/gcc/c/c-decl.c
+++ b/gcc/c/c-decl.c
@@ -5285,9 +5285,10 @@ warn_defaults_to (location_t location, int opt, const char *gmsgid, ...)
{
diagnostic_info diagnostic;
va_list ap;
+ rich_location richloc (location);
va_start (ap, gmsgid);
- diagnostic_set_info (&diagnostic, gmsgid, &ap, location,
+ diagnostic_set_info (&diagnostic, gmsgid, &ap, &richloc,
flag_isoc99 ? DK_PEDWARN : DK_WARNING);
diagnostic.option_index = opt;
report_diagnostic (&diagnostic);
@@ -7723,6 +7724,8 @@ finish_struct (location_t loc, tree t, tree fieldlist, tree attributes,
TYPE_FIELDS (t) = fieldlist;
+ maybe_apply_pragma_scalar_storage_order (t);
+
layout_type (t);
if (TYPE_SIZE_UNIT (t)
@@ -7731,27 +7734,45 @@ finish_struct (location_t loc, tree t, tree fieldlist, tree attributes,
&& !valid_constant_size_p (TYPE_SIZE_UNIT (t)))
error ("type %qT is too large", t);
- /* Give bit-fields their proper types. */
- {
- tree *fieldlistp = &fieldlist;
- while (*fieldlistp)
- if (TREE_CODE (*fieldlistp) == FIELD_DECL && DECL_INITIAL (*fieldlistp)
- && TREE_TYPE (*fieldlistp) != error_mark_node)
+ /* Give bit-fields their proper types and rewrite the type of array fields
+ with scalar component if the enclosing type has reverse storage order. */
+ for (tree field = fieldlist; field; field = DECL_CHAIN (field))
+ {
+ if (TREE_CODE (field) == FIELD_DECL
+ && DECL_INITIAL (field)
+ && TREE_TYPE (field) != error_mark_node)
{
unsigned HOST_WIDE_INT width
- = tree_to_uhwi (DECL_INITIAL (*fieldlistp));
- tree type = TREE_TYPE (*fieldlistp);
+ = tree_to_uhwi (DECL_INITIAL (field));
+ tree type = TREE_TYPE (field);
if (width != TYPE_PRECISION (type))
{
- TREE_TYPE (*fieldlistp)
+ TREE_TYPE (field)
= c_build_bitfield_integer_type (width, TYPE_UNSIGNED (type));
- DECL_MODE (*fieldlistp) = TYPE_MODE (TREE_TYPE (*fieldlistp));
+ DECL_MODE (field) = TYPE_MODE (TREE_TYPE (field));
}
- DECL_INITIAL (*fieldlistp) = 0;
+ DECL_INITIAL (field) = 0;
}
- else
- fieldlistp = &DECL_CHAIN (*fieldlistp);
- }
+ else if (TYPE_REVERSE_STORAGE_ORDER (t)
+ && TREE_CODE (field) == FIELD_DECL
+ && TREE_CODE (TREE_TYPE (field)) == ARRAY_TYPE)
+ {
+ tree ftype = TREE_TYPE (field);
+ tree ctype = strip_array_types (ftype);
+ if (!RECORD_OR_UNION_TYPE_P (ctype) && TYPE_MODE (ctype) != QImode)
+ {
+ tree fmain_type = TYPE_MAIN_VARIANT (ftype);
+ tree *typep = &fmain_type;
+ do {
+ *typep = build_distinct_type_copy (*typep);
+ TYPE_REVERSE_STORAGE_ORDER (*typep) = 1;
+ typep = &TREE_TYPE (*typep);
+ } while (TREE_CODE (*typep) == ARRAY_TYPE);
+ TREE_TYPE (field)
+ = c_build_qualified_type (fmain_type, TYPE_QUALS (ftype));
+ }
+ }
+ }
/* Now we have the truly final field list.
Store it in this type and in the variants. */
diff --git a/gcc/c/c-errors.c b/gcc/c/c-errors.c
index d9176ec0f11..b458957474d 100644
--- a/gcc/c/c-errors.c
+++ b/gcc/c/c-errors.c
@@ -41,13 +41,14 @@ pedwarn_c99 (location_t location, int opt, const char *gmsgid, ...)
diagnostic_info diagnostic;
va_list ap;
bool warned = false;
+ rich_location richloc (location);
va_start (ap, gmsgid);
/* If desired, issue the C99/C11 compat warning, which is more specific
than -pedantic. */
if (warn_c99_c11_compat > 0)
{
- diagnostic_set_info (&diagnostic, gmsgid, &ap, location,
+ diagnostic_set_info (&diagnostic, gmsgid, &ap, &richloc,
(pedantic && !flag_isoc11)
? DK_PEDWARN : DK_WARNING);
diagnostic.option_index = OPT_Wc99_c11_compat;
@@ -59,7 +60,7 @@ pedwarn_c99 (location_t location, int opt, const char *gmsgid, ...)
/* For -pedantic outside C11, issue a pedwarn. */
else if (pedantic && !flag_isoc11)
{
- diagnostic_set_info (&diagnostic, gmsgid, &ap, location, DK_PEDWARN);
+ diagnostic_set_info (&diagnostic, gmsgid, &ap, &richloc, DK_PEDWARN);
diagnostic.option_index = opt;
warned = report_diagnostic (&diagnostic);
}
@@ -79,6 +80,7 @@ pedwarn_c90 (location_t location, int opt, const char *gmsgid, ...)
{
diagnostic_info diagnostic;
va_list ap;
+ rich_location richloc (location);
va_start (ap, gmsgid);
/* Warnings such as -Wvla are the most specific ones. */
@@ -89,7 +91,7 @@ pedwarn_c90 (location_t location, int opt, const char *gmsgid, ...)
goto out;
else if (opt_var > 0)
{
- diagnostic_set_info (&diagnostic, gmsgid, &ap, location,
+ diagnostic_set_info (&diagnostic, gmsgid, &ap, &richloc,
(pedantic && !flag_isoc99)
? DK_PEDWARN : DK_WARNING);
diagnostic.option_index = opt;
@@ -101,7 +103,7 @@ pedwarn_c90 (location_t location, int opt, const char *gmsgid, ...)
specific than -pedantic. */
if (warn_c90_c99_compat > 0)
{
- diagnostic_set_info (&diagnostic, gmsgid, &ap, location,
+ diagnostic_set_info (&diagnostic, gmsgid, &ap, &richloc,
(pedantic && !flag_isoc99)
? DK_PEDWARN : DK_WARNING);
diagnostic.option_index = OPT_Wc90_c99_compat;
@@ -113,7 +115,7 @@ pedwarn_c90 (location_t location, int opt, const char *gmsgid, ...)
/* For -pedantic outside C99, issue a pedwarn. */
else if (pedantic && !flag_isoc99)
{
- diagnostic_set_info (&diagnostic, gmsgid, &ap, location, DK_PEDWARN);
+ diagnostic_set_info (&diagnostic, gmsgid, &ap, &richloc, DK_PEDWARN);
diagnostic.option_index = opt;
report_diagnostic (&diagnostic);
}
diff --git a/gcc/c/c-objc-common.c b/gcc/c/c-objc-common.c
index ac61191c511..270b03da5ca 100644
--- a/gcc/c/c-objc-common.c
+++ b/gcc/c/c-objc-common.c
@@ -100,7 +100,7 @@ c_tree_printer (pretty_printer *pp, text_info *text, const char *spec,
{
t = va_arg (*text->args_ptr, tree);
if (set_locus)
- text->set_location (0, DECL_SOURCE_LOCATION (t));
+ text->set_location (0, DECL_SOURCE_LOCATION (t), true);
}
switch (*spec)
diff --git a/gcc/c/c-typeck.c b/gcc/c/c-typeck.c
index 33f5ead829f..2080db95ebc 100644
--- a/gcc/c/c-typeck.c
+++ b/gcc/c/c-typeck.c
@@ -4169,18 +4169,10 @@ build_unary_op (location_t location,
goto return_build_unary_op;
}
- /* For &x[y], return x+y */
- if (TREE_CODE (arg) == ARRAY_REF)
- {
- tree op0 = TREE_OPERAND (arg, 0);
- if (!c_mark_addressable (op0))
- return error_mark_node;
- }
-
/* Anything not already handled and not a true memory reference
or a non-lvalue array is an error. */
- else if (typecode != FUNCTION_TYPE && !flag
- && !lvalue_or_else (location, arg, lv_addressof))
+ if (typecode != FUNCTION_TYPE && !flag
+ && !lvalue_or_else (location, arg, lv_addressof))
return error_mark_node;
/* Move address operations inside C_MAYBE_CONST_EXPR to simplify
@@ -4218,6 +4210,39 @@ build_unary_op (location_t location,
argtype = c_build_qualified_type (argtype, quals);
}
+ switch (TREE_CODE (arg))
+ {
+ case COMPONENT_REF:
+ if (DECL_C_BIT_FIELD (TREE_OPERAND (arg, 1)))
+ {
+ error ("cannot take address of bit-field %qD",
+ TREE_OPERAND (arg, 1));
+ return error_mark_node;
+ }
+
+ /* ... fall through ... */
+
+ case ARRAY_REF:
+ if (TYPE_REVERSE_STORAGE_ORDER (TREE_TYPE (TREE_OPERAND (arg, 0))))
+ {
+ if (!AGGREGATE_TYPE_P (TREE_TYPE (arg))
+ && !VECTOR_TYPE_P (TREE_TYPE (arg)))
+ {
+ error ("cannot take address of scalar with reverse storage "
+ "order");
+ return error_mark_node;
+ }
+
+ if (TREE_CODE (TREE_TYPE (arg)) == ARRAY_TYPE
+ && TYPE_REVERSE_STORAGE_ORDER (TREE_TYPE (arg)))
+ warning (OPT_Wscalar_storage_order, "address of array with "
+ "reverse scalar storage order requested");
+ }
+
+ default:
+ break;
+ }
+
if (!c_mark_addressable (arg))
return error_mark_node;
@@ -4360,15 +4385,6 @@ c_mark_addressable (tree exp)
switch (TREE_CODE (x))
{
case COMPONENT_REF:
- if (DECL_C_BIT_FIELD (TREE_OPERAND (x, 1)))
- {
- error
- ("cannot take address of bit-field %qD", TREE_OPERAND (x, 1));
- return false;
- }
-
- /* ... fall through ... */
-
case ADDR_EXPR:
case ARRAY_REF:
case REALPART_EXPR:
@@ -8444,7 +8460,11 @@ output_init_element (location_t loc, tree value, tree origtype,
constructor_erroneous = 1;
else if (!TREE_CONSTANT (value))
constructor_constant = 0;
- else if (!initializer_constant_valid_p (value, TREE_TYPE (value))
+ else if (!initializer_constant_valid_p (value,
+ TREE_TYPE (value),
+ AGGREGATE_TYPE_P (constructor_type)
+ && TYPE_REVERSE_STORAGE_ORDER
+ (constructor_type))
|| ((TREE_CODE (constructor_type) == RECORD_TYPE
|| TREE_CODE (constructor_type) == UNION_TYPE)
&& DECL_C_BIT_FIELD (field)
@@ -13238,6 +13258,12 @@ c_build_qualified_type (tree type, int type_quals)
= build_array_type (TYPE_CANONICAL (element_type),
domain? TYPE_CANONICAL (domain)
: NULL_TREE);
+ if (TYPE_REVERSE_STORAGE_ORDER (type))
+ {
+ unqualified_canon
+ = build_distinct_type_copy (unqualified_canon);
+ TYPE_REVERSE_STORAGE_ORDER (unqualified_canon) = 1;
+ }
TYPE_CANONICAL (t)
= c_build_qualified_type (unqualified_canon, type_quals);
}
diff --git a/gcc/calls.c b/gcc/calls.c
index 6db114ad32e..b56556a9d0a 100644
--- a/gcc/calls.c
+++ b/gcc/calls.c
@@ -1065,7 +1065,7 @@ store_unaligned_arguments_into_pseudos (struct arg_data *args, int num_actuals)
args[i].aligned_regs[j] = reg;
word = extract_bit_field (word, bitsize, 0, 1, NULL_RTX,
- word_mode, word_mode);
+ word_mode, word_mode, false);
/* There is no need to restrict this code to loading items
in TYPE_ALIGN sized hunks. The bitfield instructions can
@@ -1082,7 +1082,7 @@ store_unaligned_arguments_into_pseudos (struct arg_data *args, int num_actuals)
bytes -= bitsize / BITS_PER_UNIT;
store_bit_field (reg, bitsize, endian_correction, 0, 0,
- word_mode, word);
+ word_mode, word, false);
}
}
}
@@ -1363,7 +1363,7 @@ initialize_argument_information (int num_actuals ATTRIBUTE_UNUSED,
else
copy = assign_temp (type, 1, 0);
- store_expr (args[i].tree_value, copy, 0, false);
+ store_expr (args[i].tree_value, copy, 0, false, false);
/* Just change the const function to pure and then let
the next test clear the pure based on
@@ -2084,8 +2084,8 @@ load_register_parameters (struct arg_data *args, int num_actuals,
rtx dest = gen_rtx_REG (word_mode, REGNO (reg) + nregs - 1);
unsigned int bitoff = (nregs - 1) * BITS_PER_WORD;
unsigned int bitsize = size * BITS_PER_UNIT - bitoff;
- rtx x = extract_bit_field (mem, bitsize, bitoff, 1,
- dest, word_mode, word_mode);
+ rtx x = extract_bit_field (mem, bitsize, bitoff, 1, dest,
+ word_mode, word_mode, false);
if (BYTES_BIG_ENDIAN)
x = expand_shift (LSHIFT_EXPR, word_mode, x,
BITS_PER_WORD - bitsize, dest, 1);
diff --git a/gcc/cfg-flags.def b/gcc/cfg-flags.def
index eedcd692724..e2bfbed5ecf 100644
--- a/gcc/cfg-flags.def
+++ b/gcc/cfg-flags.def
@@ -78,7 +78,7 @@ DEF_BASIC_BLOCK_FLAG(RTL, 9)
DEF_BASIC_BLOCK_FLAG(FORWARDER_BLOCK, 10)
/* Set on blocks that cannot be threaded through.
- Only used in cfgcleanup.c. */
+ Only used for jump threading. */
DEF_BASIC_BLOCK_FLAG(NONTHREADABLE_BLOCK, 11)
/* Set on blocks that were modified in some way. This bit is set in
@@ -177,6 +177,11 @@ DEF_EDGE_FLAG(TM_UNINSTRUMENTED, 15)
/* Abort (over) edge out of a GIMPLE_TRANSACTION statement. */
DEF_EDGE_FLAG(TM_ABORT, 16)
+/* An edge we should ignore. It should be entirely local to
+ passes. ie, it is never set on any edge upon the completion
+ of any pass. */
+DEF_EDGE_FLAG(IGNORE, 17)
+
#endif
/*
diff --git a/gcc/cfgexpand.c b/gcc/cfgexpand.c
index bfbc958c020..ae893527a0f 100644
--- a/gcc/cfgexpand.c
+++ b/gcc/cfgexpand.c
@@ -4374,9 +4374,10 @@ expand_debug_expr (tree exp)
machine_mode mode1;
HOST_WIDE_INT bitsize, bitpos;
tree offset;
- int volatilep = 0;
- tree tem = get_inner_reference (exp, &bitsize, &bitpos, &offset,
- &mode1, &unsignedp, &volatilep, false);
+ int reversep, volatilep = 0;
+ tree tem
+ = get_inner_reference (exp, &bitsize, &bitpos, &offset, &mode1,
+ &unsignedp, &reversep, &volatilep, false);
rtx orig_op0;
if (bitsize == 0)
@@ -4799,9 +4800,10 @@ expand_debug_expr (tree exp)
if (handled_component_p (TREE_OPERAND (exp, 0)))
{
HOST_WIDE_INT bitoffset, bitsize, maxsize;
+ bool reverse;
tree decl
- = get_ref_base_and_extent (TREE_OPERAND (exp, 0),
- &bitoffset, &bitsize, &maxsize);
+ = get_ref_base_and_extent (TREE_OPERAND (exp, 0), &bitoffset,
+ &bitsize, &maxsize, &reverse);
if ((TREE_CODE (decl) == VAR_DECL
|| TREE_CODE (decl) == PARM_DECL
|| TREE_CODE (decl) == RESULT_DECL)
diff --git a/gcc/common/config/i386/i386-common.c b/gcc/common/config/i386/i386-common.c
index 0f8c3e1df04..49899bd6fa6 100644
--- a/gcc/common/config/i386/i386-common.c
+++ b/gcc/common/config/i386/i386-common.c
@@ -997,6 +997,9 @@ static const struct default_options ix86_option_optimization_table[] =
{ OPT_LEVELS_2_PLUS, OPT_free, NULL, 1 },
/* Enable function splitting at -O2 and higher. */
{ OPT_LEVELS_2_PLUS, OPT_freorder_blocks_and_partition, NULL, 1 },
+ /* The STC algorithm produces the smallest code at -Os, for x86. */
+ { OPT_LEVELS_2_PLUS, OPT_freorder_blocks_algorithm_, NULL,
+ REORDER_BLOCKS_ALGORITHM_STC },
/* Turn off -fschedule-insns by default. It tends to make the
problem with not enough registers even worse. */
{ OPT_LEVELS_ALL, OPT_fschedule_insns, NULL, 0 },
diff --git a/gcc/config.gcc b/gcc/config.gcc
index 4a7cbd20503..9cc765e2bc1 100644
--- a/gcc/config.gcc
+++ b/gcc/config.gcc
@@ -439,7 +439,7 @@ powerpc*-*-*)
cpu_type=rs6000
extra_headers="ppc-asm.h altivec.h spe.h ppu_intrinsics.h paired.h spu2vmx.h vec_types.h si2vmx.h htmintrin.h htmxlintrin.h"
case x$with_cpu in
- xpowerpc64|xdefault64|x6[23]0|x970|xG5|xpower[345678]|xpower6x|xrs64a|xcell|xa2|xe500mc64|xe5500|Xe6500)
+ xpowerpc64|xdefault64|x6[23]0|x970|xG5|xpower[345678]|xpower6x|xrs64a|xcell|xa2|xe500mc64|xe5500|xe6500)
cpu_is_64bit=yes
;;
esac
diff --git a/gcc/config/aarch64/aarch64-builtins.c b/gcc/config/aarch64/aarch64-builtins.c
index a1998ed550a..6b4208ffb4c 100644
--- a/gcc/config/aarch64/aarch64-builtins.c
+++ b/gcc/config/aarch64/aarch64-builtins.c
@@ -324,6 +324,11 @@ enum aarch64_builtins
AARCH64_BUILTIN_GET_FPSR,
AARCH64_BUILTIN_SET_FPSR,
+ AARCH64_BUILTIN_RSQRT_DF,
+ AARCH64_BUILTIN_RSQRT_SF,
+ AARCH64_BUILTIN_RSQRT_V2DF,
+ AARCH64_BUILTIN_RSQRT_V2SF,
+ AARCH64_BUILTIN_RSQRT_V4SF,
AARCH64_SIMD_BUILTIN_BASE,
AARCH64_SIMD_BUILTIN_LANE_CHECK,
#include "aarch64-simd-builtins.def"
@@ -822,6 +827,46 @@ aarch64_init_crc32_builtins ()
}
}
+/* Add builtins for reciprocal square root. */
+
+void
+aarch64_init_builtin_rsqrt (void)
+{
+ tree fndecl = NULL;
+ tree ftype = NULL;
+
+ tree V2SF_type_node = build_vector_type (float_type_node, 2);
+ tree V2DF_type_node = build_vector_type (double_type_node, 2);
+ tree V4SF_type_node = build_vector_type (float_type_node, 4);
+
+ struct builtin_decls_data
+ {
+ tree type_node;
+ const char *builtin_name;
+ int function_code;
+ };
+
+ builtin_decls_data bdda[] =
+ {
+ { double_type_node, "__builtin_aarch64_rsqrt_df", AARCH64_BUILTIN_RSQRT_DF },
+ { float_type_node, "__builtin_aarch64_rsqrt_sf", AARCH64_BUILTIN_RSQRT_SF },
+ { V2DF_type_node, "__builtin_aarch64_rsqrt_v2df", AARCH64_BUILTIN_RSQRT_V2DF },
+ { V2SF_type_node, "__builtin_aarch64_rsqrt_v2sf", AARCH64_BUILTIN_RSQRT_V2SF },
+ { V4SF_type_node, "__builtin_aarch64_rsqrt_v4sf", AARCH64_BUILTIN_RSQRT_V4SF }
+ };
+
+ builtin_decls_data *bdd = bdda;
+ builtin_decls_data *bdd_end = bdd + (sizeof (bdda) / sizeof (builtin_decls_data));
+
+ for (; bdd < bdd_end; bdd++)
+ {
+ ftype = build_function_type_list (bdd->type_node, bdd->type_node, NULL_TREE);
+ fndecl = add_builtin_function (bdd->builtin_name,
+ ftype, bdd->function_code, BUILT_IN_MD, NULL, NULL_TREE);
+ aarch64_builtin_decls[bdd->function_code] = fndecl;
+ }
+}
+
void
aarch64_init_builtins (void)
{
@@ -853,6 +898,7 @@ aarch64_init_builtins (void)
aarch64_init_simd_builtins ();
aarch64_init_crc32_builtins ();
+ aarch64_init_builtin_rsqrt ();
}
tree
@@ -1116,6 +1162,44 @@ aarch64_crc32_expand_builtin (int fcode, tree exp, rtx target)
return target;
}
+/* Function to expand reciprocal square root builtins. */
+
+static rtx
+aarch64_expand_builtin_rsqrt (int fcode, tree exp, rtx target)
+{
+ tree arg0 = CALL_EXPR_ARG (exp, 0);
+ rtx op0 = expand_normal (arg0);
+
+ rtx (*gen) (rtx, rtx);
+
+ switch (fcode)
+ {
+ case AARCH64_BUILTIN_RSQRT_DF:
+ gen = gen_aarch64_rsqrt_df2;
+ break;
+ case AARCH64_BUILTIN_RSQRT_SF:
+ gen = gen_aarch64_rsqrt_sf2;
+ break;
+ case AARCH64_BUILTIN_RSQRT_V2DF:
+ gen = gen_aarch64_rsqrt_v2df2;
+ break;
+ case AARCH64_BUILTIN_RSQRT_V2SF:
+ gen = gen_aarch64_rsqrt_v2sf2;
+ break;
+ case AARCH64_BUILTIN_RSQRT_V4SF:
+ gen = gen_aarch64_rsqrt_v4sf2;
+ break;
+ default: gcc_unreachable ();
+ }
+
+ if (!target)
+ target = gen_reg_rtx (GET_MODE (op0));
+
+ emit_insn (gen (target, op0));
+
+ return target;
+}
+
/* Expand an expression EXP that calls a built-in function,
with result going to TARGET if that's convenient. */
rtx
@@ -1163,6 +1247,13 @@ aarch64_expand_builtin (tree exp,
else if (fcode >= AARCH64_CRC32_BUILTIN_BASE && fcode <= AARCH64_CRC32_BUILTIN_MAX)
return aarch64_crc32_expand_builtin (fcode, exp, target);
+ if (fcode == AARCH64_BUILTIN_RSQRT_DF
+ || fcode == AARCH64_BUILTIN_RSQRT_SF
+ || fcode == AARCH64_BUILTIN_RSQRT_V2DF
+ || fcode == AARCH64_BUILTIN_RSQRT_V2SF
+ || fcode == AARCH64_BUILTIN_RSQRT_V4SF)
+ return aarch64_expand_builtin_rsqrt (fcode, exp, target);
+
gcc_unreachable ();
}
@@ -1320,6 +1411,30 @@ aarch64_builtin_vectorized_function (tree fndecl, tree type_out, tree type_in)
return NULL_TREE;
}
+/* Return builtin for reciprocal square root. */
+
+tree
+aarch64_builtin_rsqrt (unsigned int fn, bool md_fn)
+{
+ if (md_fn)
+ {
+ if (fn == AARCH64_SIMD_BUILTIN_UNOP_sqrtv2df)
+ return aarch64_builtin_decls[AARCH64_BUILTIN_RSQRT_V2DF];
+ if (fn == AARCH64_SIMD_BUILTIN_UNOP_sqrtv2sf)
+ return aarch64_builtin_decls[AARCH64_BUILTIN_RSQRT_V2SF];
+ if (fn == AARCH64_SIMD_BUILTIN_UNOP_sqrtv4sf)
+ return aarch64_builtin_decls[AARCH64_BUILTIN_RSQRT_V4SF];
+ }
+ else
+ {
+ if (fn == BUILT_IN_SQRT)
+ return aarch64_builtin_decls[AARCH64_BUILTIN_RSQRT_DF];
+ if (fn == BUILT_IN_SQRTF)
+ return aarch64_builtin_decls[AARCH64_BUILTIN_RSQRT_SF];
+ }
+ return NULL_TREE;
+}
+
#undef VAR1
#define VAR1(T, N, MAP, A) \
case AARCH64_SIMD_BUILTIN_##T##_##N##A:
diff --git a/gcc/config/aarch64/aarch64-protos.h b/gcc/config/aarch64/aarch64-protos.h
index 81792bcb7da..0f20f604481 100644
--- a/gcc/config/aarch64/aarch64-protos.h
+++ b/gcc/config/aarch64/aarch64-protos.h
@@ -352,6 +352,8 @@ void aarch64_register_pragmas (void);
void aarch64_relayout_simd_types (void);
void aarch64_reset_previous_fndecl (void);
+void aarch64_emit_swrsqrt (rtx, rtx);
+
/* Initialize builtins for SIMD intrinsics. */
void init_aarch64_simd_builtins (void);
@@ -403,6 +405,8 @@ rtx aarch64_expand_builtin (tree exp,
int ignore ATTRIBUTE_UNUSED);
tree aarch64_builtin_decl (unsigned, bool ATTRIBUTE_UNUSED);
+tree aarch64_builtin_rsqrt (unsigned int, bool);
+
tree
aarch64_builtin_vectorized_function (tree fndecl,
tree type_out,
diff --git a/gcc/config/aarch64/aarch64-simd-builtins.def b/gcc/config/aarch64/aarch64-simd-builtins.def
index 04dac6f84db..aad66b134ef 100644
--- a/gcc/config/aarch64/aarch64-simd-builtins.def
+++ b/gcc/config/aarch64/aarch64-simd-builtins.def
@@ -408,8 +408,26 @@
VAR1 (BINOPP, crypto_pmull, 0, di)
VAR1 (BINOPP, crypto_pmull, 0, v2di)
- /* Implemented by aarch64_tbl3v8qi. */
+ /* Implemented by aarch64_tbl3<mode>. */
VAR1 (BINOP, tbl3, 0, v8qi)
+ VAR1 (BINOP, tbl3, 0, v16qi)
- /* Implemented by aarch64_tbx4v8qi. */
+ /* Implemented by aarch64_qtbl3<mode>. */
+ VAR1 (BINOP, qtbl3, 0, v8qi)
+ VAR1 (BINOP, qtbl3, 0, v16qi)
+
+ /* Implemented by aarch64_qtbl4<mode>. */
+ VAR1 (BINOP, qtbl4, 0, v8qi)
+ VAR1 (BINOP, qtbl4, 0, v16qi)
+
+ /* Implemented by aarch64_tbx4<mode>. */
VAR1 (TERNOP, tbx4, 0, v8qi)
+ VAR1 (TERNOP, tbx4, 0, v16qi)
+
+ /* Implemented by aarch64_qtbx3<mode>. */
+ VAR1 (TERNOP, qtbx3, 0, v8qi)
+ VAR1 (TERNOP, qtbx3, 0, v16qi)
+
+ /* Implemented by aarch64_qtbx4<mode>. */
+ VAR1 (TERNOP, qtbx4, 0, v8qi)
+ VAR1 (TERNOP, qtbx4, 0, v16qi)
diff --git a/gcc/config/aarch64/aarch64-simd.md b/gcc/config/aarch64/aarch64-simd.md
index 269e00237bb..0fb81342128 100644
--- a/gcc/config/aarch64/aarch64-simd.md
+++ b/gcc/config/aarch64/aarch64-simd.md
@@ -382,6 +382,33 @@
[(set_attr "type" "neon_fp_mul_d_scalar_q")]
)
+(define_insn "aarch64_rsqrte_<mode>2"
+ [(set (match_operand:VALLF 0 "register_operand" "=w")
+ (unspec:VALLF [(match_operand:VALLF 1 "register_operand" "w")]
+ UNSPEC_RSQRTE))]
+ "TARGET_SIMD"
+ "frsqrte\\t%<v>0<Vmtype>, %<v>1<Vmtype>"
+ [(set_attr "type" "neon_fp_rsqrte_<Vetype><q>")])
+
+(define_insn "aarch64_rsqrts_<mode>3"
+ [(set (match_operand:VALLF 0 "register_operand" "=w")
+ (unspec:VALLF [(match_operand:VALLF 1 "register_operand" "w")
+ (match_operand:VALLF 2 "register_operand" "w")]
+ UNSPEC_RSQRTS))]
+ "TARGET_SIMD"
+ "frsqrts\\t%<v>0<Vmtype>, %<v>1<Vmtype>, %<v>2<Vmtype>"
+ [(set_attr "type" "neon_fp_rsqrts_<Vetype><q>")])
+
+(define_expand "aarch64_rsqrt_<mode>2"
+ [(set (match_operand:VALLF 0 "register_operand" "=w")
+ (unspec:VALLF [(match_operand:VALLF 1 "register_operand" "w")]
+ UNSPEC_RSQRT))]
+ "TARGET_SIMD"
+{
+ aarch64_emit_swrsqrt (operands[0], operands[1]);
+ DONE;
+})
+
(define_insn "*aarch64_mul3_elt_to_64v2df"
[(set (match_operand:DF 0 "register_operand" "=w")
(mult:DF
@@ -4789,24 +4816,70 @@
[(set_attr "type" "neon_tbl2_q")]
)
-(define_insn "aarch64_tbl3v8qi"
- [(set (match_operand:V8QI 0 "register_operand" "=w")
- (unspec:V8QI [(match_operand:OI 1 "register_operand" "w")
- (match_operand:V8QI 2 "register_operand" "w")]
+(define_insn "aarch64_tbl3<mode>"
+ [(set (match_operand:VB 0 "register_operand" "=w")
+ (unspec:VB [(match_operand:OI 1 "register_operand" "w")
+ (match_operand:VB 2 "register_operand" "w")]
UNSPEC_TBL))]
"TARGET_SIMD"
- "tbl\\t%S0.8b, {%S1.16b - %T1.16b}, %S2.8b"
+ "tbl\\t%S0.<Vbtype>, {%S1.16b - %T1.16b}, %S2.<Vbtype>"
[(set_attr "type" "neon_tbl3")]
)
-(define_insn "aarch64_tbx4v8qi"
- [(set (match_operand:V8QI 0 "register_operand" "=w")
- (unspec:V8QI [(match_operand:V8QI 1 "register_operand" "0")
+(define_insn "aarch64_tbx4<mode>"
+ [(set (match_operand:VB 0 "register_operand" "=w")
+ (unspec:VB [(match_operand:VB 1 "register_operand" "0")
(match_operand:OI 2 "register_operand" "w")
- (match_operand:V8QI 3 "register_operand" "w")]
+ (match_operand:VB 3 "register_operand" "w")]
+ UNSPEC_TBX))]
+ "TARGET_SIMD"
+ "tbx\\t%S0.<Vbtype>, {%S2.16b - %T2.16b}, %S3.<Vbtype>"
+ [(set_attr "type" "neon_tbl4")]
+)
+
+;; Three source registers.
+
+(define_insn "aarch64_qtbl3<mode>"
+ [(set (match_operand:VB 0 "register_operand" "=w")
+ (unspec:VB [(match_operand:CI 1 "register_operand" "w")
+ (match_operand:VB 2 "register_operand" "w")]
+ UNSPEC_TBL))]
+ "TARGET_SIMD"
+ "tbl\\t%S0.<Vbtype>, {%S1.16b - %U1.16b}, %S2.<Vbtype>"
+ [(set_attr "type" "neon_tbl3")]
+)
+
+(define_insn "aarch64_qtbx3<mode>"
+ [(set (match_operand:VB 0 "register_operand" "=w")
+ (unspec:VB [(match_operand:VB 1 "register_operand" "0")
+ (match_operand:CI 2 "register_operand" "w")
+ (match_operand:VB 3 "register_operand" "w")]
+ UNSPEC_TBX))]
+ "TARGET_SIMD"
+ "tbx\\t%S0.<Vbtype>, {%S2.16b - %U2.16b}, %S3.<Vbtype>"
+ [(set_attr "type" "neon_tbl3")]
+)
+
+;; Four source registers.
+
+(define_insn "aarch64_qtbl4<mode>"
+ [(set (match_operand:VB 0 "register_operand" "=w")
+ (unspec:VB [(match_operand:XI 1 "register_operand" "w")
+ (match_operand:VB 2 "register_operand" "w")]
+ UNSPEC_TBL))]
+ "TARGET_SIMD"
+ "tbl\\t%S0.<Vbtype>, {%S1.16b - %V1.16b}, %S2.<Vbtype>"
+ [(set_attr "type" "neon_tbl4")]
+)
+
+(define_insn "aarch64_qtbx4<mode>"
+ [(set (match_operand:VB 0 "register_operand" "=w")
+ (unspec:VB [(match_operand:VB 1 "register_operand" "0")
+ (match_operand:XI 2 "register_operand" "w")
+ (match_operand:VB 3 "register_operand" "w")]
UNSPEC_TBX))]
"TARGET_SIMD"
- "tbx\\t%S0.8b, {%S2.16b - %T2.16b}, %S3.8b"
+ "tbx\\t%S0.<Vbtype>, {%S2.16b - %V2.16b}, %S3.<Vbtype>"
[(set_attr "type" "neon_tbl4")]
)
diff --git a/gcc/config/aarch64/aarch64-tuning-flags.def b/gcc/config/aarch64/aarch64-tuning-flags.def
index 628386b5a1d..6f7dbcec03d 100644
--- a/gcc/config/aarch64/aarch64-tuning-flags.def
+++ b/gcc/config/aarch64/aarch64-tuning-flags.def
@@ -29,4 +29,5 @@
AARCH64_TUNE_ to give an enum name. */
AARCH64_EXTRA_TUNING_OPTION ("rename_fma_regs", RENAME_FMA_REGS)
+AARCH64_EXTRA_TUNING_OPTION ("recip_sqrt", RECIP_SQRT)
diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c
index 5c8604ffa72..1b7be838c73 100644
--- a/gcc/config/aarch64/aarch64.c
+++ b/gcc/config/aarch64/aarch64.c
@@ -52,6 +52,7 @@
#include "params.h"
#include "gimplify.h"
#include "dwarf2.h"
+#include "gimple-iterator.h"
#include "tree-vectorizer.h"
#include "aarch64-cost-tables.h"
#include "dumpfile.h"
@@ -402,7 +403,8 @@ static const struct tune_params cortexa57_tunings =
2, /* min_div_recip_mul_sf. */
2, /* min_div_recip_mul_df. */
tune_params::AUTOPREFETCHER_WEAK, /* autoprefetcher_model. */
- (AARCH64_EXTRA_TUNE_RENAME_FMA_REGS) /* tune_flags. */
+ (AARCH64_EXTRA_TUNE_RENAME_FMA_REGS
+ | AARCH64_EXTRA_TUNE_RECIP_SQRT) /* tune_flags. */
};
static const struct tune_params cortexa72_tunings =
@@ -469,7 +471,7 @@ static const struct tune_params xgene1_tunings =
2, /* min_div_recip_mul_sf. */
2, /* min_div_recip_mul_df. */
tune_params::AUTOPREFETCHER_OFF, /* autoprefetcher_model. */
- (AARCH64_EXTRA_TUNE_NONE) /* tune_flags. */
+ (AARCH64_EXTRA_TUNE_RECIP_SQRT) /* tune_flags. */
};
/* Support for fine-grained override of the tuning structures. */
@@ -5235,24 +5237,38 @@ aarch64_uxt_size (int shift, HOST_WIDE_INT mask)
return 0;
}
+/* Constant pools are per function only when PC relative
+ literal loads are true or we are in the large memory
+ model. */
+
+static inline bool
+aarch64_can_use_per_function_literal_pools_p (void)
+{
+ return (!aarch64_nopcrelative_literal_loads
+ || aarch64_cmodel == AARCH64_CMODEL_LARGE);
+}
+
static bool
-aarch64_use_blocks_for_constant_p (machine_mode mode ATTRIBUTE_UNUSED,
- const_rtx x ATTRIBUTE_UNUSED)
+aarch64_use_blocks_for_constant_p (machine_mode, const_rtx)
{
/* We can't use blocks for constants when we're using a per-function
constant pool. */
- return false;
+ return !aarch64_can_use_per_function_literal_pools_p ();
}
+/* Select appropriate section for constants depending
+ on where we place literal pools. */
+
static section *
-aarch64_select_rtx_section (machine_mode mode ATTRIBUTE_UNUSED,
- rtx x ATTRIBUTE_UNUSED,
- unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED)
+aarch64_select_rtx_section (machine_mode mode,
+ rtx x,
+ unsigned HOST_WIDE_INT align)
{
- /* Force all constant pool entries into the current function section. */
- return function_section (current_function_decl);
-}
+ if (aarch64_can_use_per_function_literal_pools_p ())
+ return function_section (current_function_decl);
+ return default_elf_select_rtx_section (mode, x, align);
+}
/* Costs. */
@@ -7030,6 +7046,105 @@ aarch64_memory_move_cost (machine_mode mode ATTRIBUTE_UNUSED,
return aarch64_tune_params.memmov_cost;
}
+/* Function to decide when to use
+ reciprocal square root builtins. */
+
+static tree
+aarch64_builtin_reciprocal (unsigned int fn,
+ bool md_fn,
+ bool)
+{
+ if (flag_trapping_math
+ || !flag_unsafe_math_optimizations
+ || optimize_size
+ || ! (aarch64_tune_params.extra_tuning_flags
+ & AARCH64_EXTRA_TUNE_RECIP_SQRT))
+ {
+ return NULL_TREE;
+ }
+
+ return aarch64_builtin_rsqrt (fn, md_fn);
+}
+
+typedef rtx (*rsqrte_type) (rtx, rtx);
+
+/* Select reciprocal square root initial estimate
+ insn depending on machine mode. */
+
+rsqrte_type
+get_rsqrte_type (machine_mode mode)
+{
+ switch (mode)
+ {
+ case DFmode: return gen_aarch64_rsqrte_df2;
+ case SFmode: return gen_aarch64_rsqrte_sf2;
+ case V2DFmode: return gen_aarch64_rsqrte_v2df2;
+ case V2SFmode: return gen_aarch64_rsqrte_v2sf2;
+ case V4SFmode: return gen_aarch64_rsqrte_v4sf2;
+ default: gcc_unreachable ();
+ }
+}
+
+typedef rtx (*rsqrts_type) (rtx, rtx, rtx);
+
+/* Select reciprocal square root Newton-Raphson step
+ insn depending on machine mode. */
+
+rsqrts_type
+get_rsqrts_type (machine_mode mode)
+{
+ switch (mode)
+ {
+ case DFmode: return gen_aarch64_rsqrts_df3;
+ case SFmode: return gen_aarch64_rsqrts_sf3;
+ case V2DFmode: return gen_aarch64_rsqrts_v2df3;
+ case V2SFmode: return gen_aarch64_rsqrts_v2sf3;
+ case V4SFmode: return gen_aarch64_rsqrts_v4sf3;
+ default: gcc_unreachable ();
+ }
+}
+
+/* Emit instruction sequence to compute
+ reciprocal square root. Use two Newton-Raphson steps
+ for single precision and three for double precision. */
+
+void
+aarch64_emit_swrsqrt (rtx dst, rtx src)
+{
+ machine_mode mode = GET_MODE (src);
+ gcc_assert (
+ mode == SFmode || mode == V2SFmode || mode == V4SFmode
+ || mode == DFmode || mode == V2DFmode);
+
+ rtx xsrc = gen_reg_rtx (mode);
+ emit_move_insn (xsrc, src);
+ rtx x0 = gen_reg_rtx (mode);
+
+ emit_insn ((*get_rsqrte_type (mode)) (x0, xsrc));
+
+ bool double_mode = (mode == DFmode || mode == V2DFmode);
+
+ int iterations = double_mode ? 3 : 2;
+
+ if (flag_mrecip_low_precision_sqrt)
+ iterations--;
+
+ for (int i = 0; i < iterations; ++i)
+ {
+ rtx x1 = gen_reg_rtx (mode);
+ rtx x2 = gen_reg_rtx (mode);
+ rtx x3 = gen_reg_rtx (mode);
+ emit_set_insn (x2, gen_rtx_MULT (mode, x0, x0));
+
+ emit_insn ((*get_rsqrts_type (mode)) (x3, xsrc, x2));
+
+ emit_set_insn (x1, gen_rtx_MULT (mode, x0, x3));
+ x0 = x1;
+ }
+
+ emit_move_insn (dst, x0);
+}
+
/* Return the number of instructions that can be issued per cycle. */
static int
aarch64_sched_issue_rate (void)
@@ -13454,6 +13569,9 @@ aarch64_promoted_type (const_tree t)
#undef TARGET_BUILTIN_DECL
#define TARGET_BUILTIN_DECL aarch64_builtin_decl
+#undef TARGET_BUILTIN_RECIPROCAL
+#define TARGET_BUILTIN_RECIPROCAL aarch64_builtin_reciprocal
+
#undef TARGET_EXPAND_BUILTIN
#define TARGET_EXPAND_BUILTIN aarch64_expand_builtin
diff --git a/gcc/config/aarch64/aarch64.md b/gcc/config/aarch64/aarch64.md
index 6cdddf49102..6b08850e9d0 100644
--- a/gcc/config/aarch64/aarch64.md
+++ b/gcc/config/aarch64/aarch64.md
@@ -126,6 +126,9 @@
UNSPEC_VSTRUCTDUMMY
UNSPEC_SP_SET
UNSPEC_SP_TEST
+ UNSPEC_RSQRT
+ UNSPEC_RSQRTE
+ UNSPEC_RSQRTS
])
(define_c_enum "unspecv" [
diff --git a/gcc/config/aarch64/aarch64.opt b/gcc/config/aarch64/aarch64.opt
index c031bcc7be6..a0fbfd42c09 100644
--- a/gcc/config/aarch64/aarch64.opt
+++ b/gcc/config/aarch64/aarch64.opt
@@ -148,3 +148,8 @@ Enum(aarch64_abi) String(lp64) Value(AARCH64_ABI_LP64)
mpc-relative-literal-loads
Target Report Save Var(nopcrelative_literal_loads) Init(2) Save
PC relative literal loads.
+
+mlow-precision-recip-sqrt
+Common Var(flag_mrecip_low_precision_sqrt) Optimization
+When calculating a sqrt approximation, run fewer steps.
+This reduces precision, but can result in faster computation.
diff --git a/gcc/config/aarch64/arm_neon.h b/gcc/config/aarch64/arm_neon.h
index 265c2667908..7f69043d8a7 100644
--- a/gcc/config/aarch64/arm_neon.h
+++ b/gcc/config/aarch64/arm_neon.h
@@ -10623,224 +10623,6 @@ vqtbl1q_u8 (uint8x16_t a, uint8x16_t b)
}
__extension__ static __inline int8x8_t __attribute__ ((__always_inline__))
-vqtbl2_s8 (int8x16x2_t tab, uint8x8_t idx)
-{
- int8x8_t result;
- __asm__ ("ld1 {v16.16b, v17.16b}, %1\n\t"
- "tbl %0.8b, {v16.16b, v17.16b}, %2.8b\n\t"
- :"=w"(result)
- :"Q"(tab),"w"(idx)
- :"memory", "v16", "v17");
- return result;
-}
-
-__extension__ static __inline uint8x8_t __attribute__ ((__always_inline__))
-vqtbl2_u8 (uint8x16x2_t tab, uint8x8_t idx)
-{
- uint8x8_t result;
- __asm__ ("ld1 {v16.16b, v17.16b}, %1\n\t"
- "tbl %0.8b, {v16.16b, v17.16b}, %2.8b\n\t"
- :"=w"(result)
- :"Q"(tab),"w"(idx)
- :"memory", "v16", "v17");
- return result;
-}
-
-__extension__ static __inline poly8x8_t __attribute__ ((__always_inline__))
-vqtbl2_p8 (poly8x16x2_t tab, uint8x8_t idx)
-{
- poly8x8_t result;
- __asm__ ("ld1 {v16.16b, v17.16b}, %1\n\t"
- "tbl %0.8b, {v16.16b, v17.16b}, %2.8b\n\t"
- :"=w"(result)
- :"Q"(tab),"w"(idx)
- :"memory", "v16", "v17");
- return result;
-}
-
-__extension__ static __inline int8x16_t __attribute__ ((__always_inline__))
-vqtbl2q_s8 (int8x16x2_t tab, uint8x16_t idx)
-{
- int8x16_t result;
- __asm__ ("ld1 {v16.16b, v17.16b}, %1\n\t"
- "tbl %0.16b, {v16.16b, v17.16b}, %2.16b\n\t"
- :"=w"(result)
- :"Q"(tab),"w"(idx)
- :"memory", "v16", "v17");
- return result;
-}
-
-__extension__ static __inline uint8x16_t __attribute__ ((__always_inline__))
-vqtbl2q_u8 (uint8x16x2_t tab, uint8x16_t idx)
-{
- uint8x16_t result;
- __asm__ ("ld1 {v16.16b, v17.16b}, %1\n\t"
- "tbl %0.16b, {v16.16b, v17.16b}, %2.16b\n\t"
- :"=w"(result)
- :"Q"(tab),"w"(idx)
- :"memory", "v16", "v17");
- return result;
-}
-
-__extension__ static __inline poly8x16_t __attribute__ ((__always_inline__))
-vqtbl2q_p8 (poly8x16x2_t tab, uint8x16_t idx)
-{
- poly8x16_t result;
- __asm__ ("ld1 {v16.16b, v17.16b}, %1\n\t"
- "tbl %0.16b, {v16.16b, v17.16b}, %2.16b\n\t"
- :"=w"(result)
- :"Q"(tab),"w"(idx)
- :"memory", "v16", "v17");
- return result;
-}
-
-__extension__ static __inline int8x8_t __attribute__ ((__always_inline__))
-vqtbl3_s8 (int8x16x3_t tab, uint8x8_t idx)
-{
- int8x8_t result;
- __asm__ ("ld1 {v16.16b - v18.16b}, %1\n\t"
- "tbl %0.8b, {v16.16b - v18.16b}, %2.8b\n\t"
- :"=w"(result)
- :"Q"(tab),"w"(idx)
- :"memory", "v16", "v17", "v18");
- return result;
-}
-
-__extension__ static __inline uint8x8_t __attribute__ ((__always_inline__))
-vqtbl3_u8 (uint8x16x3_t tab, uint8x8_t idx)
-{
- uint8x8_t result;
- __asm__ ("ld1 {v16.16b - v18.16b}, %1\n\t"
- "tbl %0.8b, {v16.16b - v18.16b}, %2.8b\n\t"
- :"=w"(result)
- :"Q"(tab),"w"(idx)
- :"memory", "v16", "v17", "v18");
- return result;
-}
-
-__extension__ static __inline poly8x8_t __attribute__ ((__always_inline__))
-vqtbl3_p8 (poly8x16x3_t tab, uint8x8_t idx)
-{
- poly8x8_t result;
- __asm__ ("ld1 {v16.16b - v18.16b}, %1\n\t"
- "tbl %0.8b, {v16.16b - v18.16b}, %2.8b\n\t"
- :"=w"(result)
- :"Q"(tab),"w"(idx)
- :"memory", "v16", "v17", "v18");
- return result;
-}
-
-__extension__ static __inline int8x16_t __attribute__ ((__always_inline__))
-vqtbl3q_s8 (int8x16x3_t tab, uint8x16_t idx)
-{
- int8x16_t result;
- __asm__ ("ld1 {v16.16b - v18.16b}, %1\n\t"
- "tbl %0.16b, {v16.16b - v18.16b}, %2.16b\n\t"
- :"=w"(result)
- :"Q"(tab),"w"(idx)
- :"memory", "v16", "v17", "v18");
- return result;
-}
-
-__extension__ static __inline uint8x16_t __attribute__ ((__always_inline__))
-vqtbl3q_u8 (uint8x16x3_t tab, uint8x16_t idx)
-{
- uint8x16_t result;
- __asm__ ("ld1 {v16.16b - v18.16b}, %1\n\t"
- "tbl %0.16b, {v16.16b - v18.16b}, %2.16b\n\t"
- :"=w"(result)
- :"Q"(tab),"w"(idx)
- :"memory", "v16", "v17", "v18");
- return result;
-}
-
-__extension__ static __inline poly8x16_t __attribute__ ((__always_inline__))
-vqtbl3q_p8 (poly8x16x3_t tab, uint8x16_t idx)
-{
- poly8x16_t result;
- __asm__ ("ld1 {v16.16b - v18.16b}, %1\n\t"
- "tbl %0.16b, {v16.16b - v18.16b}, %2.16b\n\t"
- :"=w"(result)
- :"Q"(tab),"w"(idx)
- :"memory", "v16", "v17", "v18");
- return result;
-}
-
-__extension__ static __inline int8x8_t __attribute__ ((__always_inline__))
-vqtbl4_s8 (int8x16x4_t tab, uint8x8_t idx)
-{
- int8x8_t result;
- __asm__ ("ld1 {v16.16b - v19.16b}, %1\n\t"
- "tbl %0.8b, {v16.16b - v19.16b}, %2.8b\n\t"
- :"=w"(result)
- :"Q"(tab),"w"(idx)
- :"memory", "v16", "v17", "v18", "v19");
- return result;
-}
-
-__extension__ static __inline uint8x8_t __attribute__ ((__always_inline__))
-vqtbl4_u8 (uint8x16x4_t tab, uint8x8_t idx)
-{
- uint8x8_t result;
- __asm__ ("ld1 {v16.16b - v19.16b}, %1\n\t"
- "tbl %0.8b, {v16.16b - v19.16b}, %2.8b\n\t"
- :"=w"(result)
- :"Q"(tab),"w"(idx)
- :"memory", "v16", "v17", "v18", "v19");
- return result;
-}
-
-__extension__ static __inline poly8x8_t __attribute__ ((__always_inline__))
-vqtbl4_p8 (poly8x16x4_t tab, uint8x8_t idx)
-{
- poly8x8_t result;
- __asm__ ("ld1 {v16.16b - v19.16b}, %1\n\t"
- "tbl %0.8b, {v16.16b - v19.16b}, %2.8b\n\t"
- :"=w"(result)
- :"Q"(tab),"w"(idx)
- :"memory", "v16", "v17", "v18", "v19");
- return result;
-}
-
-
-__extension__ static __inline int8x16_t __attribute__ ((__always_inline__))
-vqtbl4q_s8 (int8x16x4_t tab, uint8x16_t idx)
-{
- int8x16_t result;
- __asm__ ("ld1 {v16.16b - v19.16b}, %1\n\t"
- "tbl %0.16b, {v16.16b - v19.16b}, %2.16b\n\t"
- :"=w"(result)
- :"Q"(tab),"w"(idx)
- :"memory", "v16", "v17", "v18", "v19");
- return result;
-}
-
-__extension__ static __inline uint8x16_t __attribute__ ((__always_inline__))
-vqtbl4q_u8 (uint8x16x4_t tab, uint8x16_t idx)
-{
- uint8x16_t result;
- __asm__ ("ld1 {v16.16b - v19.16b}, %1\n\t"
- "tbl %0.16b, {v16.16b - v19.16b}, %2.16b\n\t"
- :"=w"(result)
- :"Q"(tab),"w"(idx)
- :"memory", "v16", "v17", "v18", "v19");
- return result;
-}
-
-__extension__ static __inline poly8x16_t __attribute__ ((__always_inline__))
-vqtbl4q_p8 (poly8x16x4_t tab, uint8x16_t idx)
-{
- poly8x16_t result;
- __asm__ ("ld1 {v16.16b - v19.16b}, %1\n\t"
- "tbl %0.16b, {v16.16b - v19.16b}, %2.16b\n\t"
- :"=w"(result)
- :"Q"(tab),"w"(idx)
- :"memory", "v16", "v17", "v18", "v19");
- return result;
-}
-
-
-__extension__ static __inline int8x8_t __attribute__ ((__always_inline__))
vqtbx1_s8 (int8x8_t r, int8x16_t tab, uint8x8_t idx)
{
int8x8_t result = r;
@@ -10906,227 +10688,6 @@ vqtbx1q_p8 (poly8x16_t r, poly8x16_t tab, uint8x16_t idx)
return result;
}
-__extension__ static __inline int8x8_t __attribute__ ((__always_inline__))
-vqtbx2_s8 (int8x8_t r, int8x16x2_t tab, uint8x8_t idx)
-{
- int8x8_t result = r;
- __asm__ ("ld1 {v16.16b, v17.16b}, %1\n\t"
- "tbx %0.8b, {v16.16b, v17.16b}, %2.8b\n\t"
- :"+w"(result)
- :"Q"(tab),"w"(idx)
- :"memory", "v16", "v17");
- return result;
-}
-
-__extension__ static __inline uint8x8_t __attribute__ ((__always_inline__))
-vqtbx2_u8 (uint8x8_t r, uint8x16x2_t tab, uint8x8_t idx)
-{
- uint8x8_t result = r;
- __asm__ ("ld1 {v16.16b, v17.16b}, %1\n\t"
- "tbx %0.8b, {v16.16b, v17.16b}, %2.8b\n\t"
- :"+w"(result)
- :"Q"(tab),"w"(idx)
- :"memory", "v16", "v17");
- return result;
-}
-
-__extension__ static __inline poly8x8_t __attribute__ ((__always_inline__))
-vqtbx2_p8 (poly8x8_t r, poly8x16x2_t tab, uint8x8_t idx)
-{
- poly8x8_t result = r;
- __asm__ ("ld1 {v16.16b, v17.16b}, %1\n\t"
- "tbx %0.8b, {v16.16b, v17.16b}, %2.8b\n\t"
- :"+w"(result)
- :"Q"(tab),"w"(idx)
- :"memory", "v16", "v17");
- return result;
-}
-
-
-__extension__ static __inline int8x16_t __attribute__ ((__always_inline__))
-vqtbx2q_s8 (int8x16_t r, int8x16x2_t tab, uint8x16_t idx)
-{
- int8x16_t result = r;
- __asm__ ("ld1 {v16.16b, v17.16b}, %1\n\t"
- "tbx %0.16b, {v16.16b, v17.16b}, %2.16b\n\t"
- :"+w"(result)
- :"Q"(tab),"w"(idx)
- :"memory", "v16", "v17");
- return result;
-}
-
-__extension__ static __inline uint8x16_t __attribute__ ((__always_inline__))
-vqtbx2q_u8 (uint8x16_t r, uint8x16x2_t tab, uint8x16_t idx)
-{
- uint8x16_t result = r;
- __asm__ ("ld1 {v16.16b, v17.16b}, %1\n\t"
- "tbx %0.16b, {v16.16b, v17.16b}, %2.16b\n\t"
- :"+w"(result)
- :"Q"(tab),"w"(idx)
- :"memory", "v16", "v17");
- return result;
-}
-
-__extension__ static __inline poly8x16_t __attribute__ ((__always_inline__))
-vqtbx2q_p8 (poly8x16_t r, poly8x16x2_t tab, uint8x16_t idx)
-{
- poly8x16_t result = r;
- __asm__ ("ld1 {v16.16b, v17.16b}, %1\n\t"
- "tbx %0.16b, {v16.16b, v17.16b}, %2.16b\n\t"
- :"+w"(result)
- :"Q"(tab),"w"(idx)
- :"memory", "v16", "v17");
- return result;
-}
-
-
-__extension__ static __inline int8x8_t __attribute__ ((__always_inline__))
-vqtbx3_s8 (int8x8_t r, int8x16x3_t tab, uint8x8_t idx)
-{
- int8x8_t result = r;
- __asm__ ("ld1 {v16.16b - v18.16b}, %1\n\t"
- "tbx %0.8b, {v16.16b - v18.16b}, %2.8b\n\t"
- :"+w"(result)
- :"Q"(tab),"w"(idx)
- :"memory", "v16", "v17", "v18");
- return result;
-}
-
-__extension__ static __inline uint8x8_t __attribute__ ((__always_inline__))
-vqtbx3_u8 (uint8x8_t r, uint8x16x3_t tab, uint8x8_t idx)
-{
- uint8x8_t result = r;
- __asm__ ("ld1 {v16.16b - v18.16b}, %1\n\t"
- "tbx %0.8b, {v16.16b - v18.16b}, %2.8b\n\t"
- :"+w"(result)
- :"Q"(tab),"w"(idx)
- :"memory", "v16", "v17", "v18");
- return result;
-}
-
-__extension__ static __inline poly8x8_t __attribute__ ((__always_inline__))
-vqtbx3_p8 (poly8x8_t r, poly8x16x3_t tab, uint8x8_t idx)
-{
- poly8x8_t result = r;
- __asm__ ("ld1 {v16.16b - v18.16b}, %1\n\t"
- "tbx %0.8b, {v16.16b - v18.16b}, %2.8b\n\t"
- :"+w"(result)
- :"Q"(tab),"w"(idx)
- :"memory", "v16", "v17", "v18");
- return result;
-}
-
-
-__extension__ static __inline int8x16_t __attribute__ ((__always_inline__))
-vqtbx3q_s8 (int8x16_t r, int8x16x3_t tab, uint8x16_t idx)
-{
- int8x16_t result = r;
- __asm__ ("ld1 {v16.16b - v18.16b}, %1\n\t"
- "tbx %0.16b, {v16.16b - v18.16b}, %2.16b\n\t"
- :"+w"(result)
- :"Q"(tab),"w"(idx)
- :"memory", "v16", "v17", "v18");
- return result;
-}
-
-__extension__ static __inline uint8x16_t __attribute__ ((__always_inline__))
-vqtbx3q_u8 (uint8x16_t r, uint8x16x3_t tab, uint8x16_t idx)
-{
- uint8x16_t result = r;
- __asm__ ("ld1 {v16.16b - v18.16b}, %1\n\t"
- "tbx %0.16b, {v16.16b - v18.16b}, %2.16b\n\t"
- :"+w"(result)
- :"Q"(tab),"w"(idx)
- :"memory", "v16", "v17", "v18");
- return result;
-}
-
-__extension__ static __inline poly8x16_t __attribute__ ((__always_inline__))
-vqtbx3q_p8 (poly8x16_t r, poly8x16x3_t tab, uint8x16_t idx)
-{
- poly8x16_t result = r;
- __asm__ ("ld1 {v16.16b - v18.16b}, %1\n\t"
- "tbx %0.16b, {v16.16b - v18.16b}, %2.16b\n\t"
- :"+w"(result)
- :"Q"(tab),"w"(idx)
- :"memory", "v16", "v17", "v18");
- return result;
-}
-
-
-__extension__ static __inline int8x8_t __attribute__ ((__always_inline__))
-vqtbx4_s8 (int8x8_t r, int8x16x4_t tab, uint8x8_t idx)
-{
- int8x8_t result = r;
- __asm__ ("ld1 {v16.16b - v19.16b}, %1\n\t"
- "tbx %0.8b, {v16.16b - v19.16b}, %2.8b\n\t"
- :"+w"(result)
- :"Q"(tab),"w"(idx)
- :"memory", "v16", "v17", "v18", "v19");
- return result;
-}
-
-__extension__ static __inline uint8x8_t __attribute__ ((__always_inline__))
-vqtbx4_u8 (uint8x8_t r, uint8x16x4_t tab, uint8x8_t idx)
-{
- uint8x8_t result = r;
- __asm__ ("ld1 {v16.16b - v19.16b}, %1\n\t"
- "tbx %0.8b, {v16.16b - v19.16b}, %2.8b\n\t"
- :"+w"(result)
- :"Q"(tab),"w"(idx)
- :"memory", "v16", "v17", "v18", "v19");
- return result;
-}
-
-__extension__ static __inline poly8x8_t __attribute__ ((__always_inline__))
-vqtbx4_p8 (poly8x8_t r, poly8x16x4_t tab, uint8x8_t idx)
-{
- poly8x8_t result = r;
- __asm__ ("ld1 {v16.16b - v19.16b}, %1\n\t"
- "tbx %0.8b, {v16.16b - v19.16b}, %2.8b\n\t"
- :"+w"(result)
- :"Q"(tab),"w"(idx)
- :"memory", "v16", "v17", "v18", "v19");
- return result;
-}
-
-
-__extension__ static __inline int8x16_t __attribute__ ((__always_inline__))
-vqtbx4q_s8 (int8x16_t r, int8x16x4_t tab, uint8x16_t idx)
-{
- int8x16_t result = r;
- __asm__ ("ld1 {v16.16b - v19.16b}, %1\n\t"
- "tbx %0.16b, {v16.16b - v19.16b}, %2.16b\n\t"
- :"+w"(result)
- :"Q"(tab),"w"(idx)
- :"memory", "v16", "v17", "v18", "v19");
- return result;
-}
-
-__extension__ static __inline uint8x16_t __attribute__ ((__always_inline__))
-vqtbx4q_u8 (uint8x16_t r, uint8x16x4_t tab, uint8x16_t idx)
-{
- uint8x16_t result = r;
- __asm__ ("ld1 {v16.16b - v19.16b}, %1\n\t"
- "tbx %0.16b, {v16.16b - v19.16b}, %2.16b\n\t"
- :"+w"(result)
- :"Q"(tab),"w"(idx)
- :"memory", "v16", "v17", "v18", "v19");
- return result;
-}
-
-__extension__ static __inline poly8x16_t __attribute__ ((__always_inline__))
-vqtbx4q_p8 (poly8x16_t r, poly8x16x4_t tab, uint8x16_t idx)
-{
- poly8x16_t result = r;
- __asm__ ("ld1 {v16.16b - v19.16b}, %1\n\t"
- "tbx %0.16b, {v16.16b - v19.16b}, %2.16b\n\t"
- :"+w"(result)
- :"Q"(tab),"w"(idx)
- :"memory", "v16", "v17", "v18", "v19");
- return result;
-}
-
/* V7 legacy table intrinsics. */
__extension__ static __inline int8x8_t __attribute__ ((__always_inline__))
@@ -20714,6 +20275,389 @@ vqsubd_u64 (uint64_t __a, uint64_t __b)
return __builtin_aarch64_uqsubdi_uuu (__a, __b);
}
+/* vqtbl2 */
+
+__extension__ static __inline int8x8_t __attribute__ ((__always_inline__))
+vqtbl2_s8 (int8x16x2_t tab, uint8x8_t idx)
+{
+ __builtin_aarch64_simd_oi __o;
+ __o = __builtin_aarch64_set_qregoiv16qi (__o, tab.val[0], 0);
+ __o = __builtin_aarch64_set_qregoiv16qi (__o, tab.val[1], 1);
+ return __builtin_aarch64_tbl3v8qi (__o, (int8x8_t)idx);
+}
+
+__extension__ static __inline uint8x8_t __attribute__ ((__always_inline__))
+vqtbl2_u8 (uint8x16x2_t tab, uint8x8_t idx)
+{
+ __builtin_aarch64_simd_oi __o;
+ __o = __builtin_aarch64_set_qregoiv16qi (__o, (int8x16_t)tab.val[0], 0);
+ __o = __builtin_aarch64_set_qregoiv16qi (__o, (int8x16_t)tab.val[1], 1);
+ return (uint8x8_t)__builtin_aarch64_tbl3v8qi (__o, (int8x8_t)idx);
+}
+
+__extension__ static __inline poly8x8_t __attribute__ ((__always_inline__))
+vqtbl2_p8 (poly8x16x2_t tab, uint8x8_t idx)
+{
+ __builtin_aarch64_simd_oi __o;
+ __o = __builtin_aarch64_set_qregoiv16qi (__o, (int8x16_t)tab.val[0], 0);
+ __o = __builtin_aarch64_set_qregoiv16qi (__o, (int8x16_t)tab.val[1], 1);
+ return (poly8x8_t)__builtin_aarch64_tbl3v8qi (__o, (int8x8_t)idx);
+}
+
+__extension__ static __inline int8x16_t __attribute__ ((__always_inline__))
+vqtbl2q_s8 (int8x16x2_t tab, uint8x16_t idx)
+{
+ __builtin_aarch64_simd_oi __o;
+ __o = __builtin_aarch64_set_qregoiv16qi (__o, (int8x16_t)tab.val[0], 0);
+ __o = __builtin_aarch64_set_qregoiv16qi (__o, (int8x16_t)tab.val[1], 1);
+ return __builtin_aarch64_tbl3v16qi (__o, (int8x16_t)idx);
+}
+
+__extension__ static __inline uint8x16_t __attribute__ ((__always_inline__))
+vqtbl2q_u8 (uint8x16x2_t tab, uint8x16_t idx)
+{
+ __builtin_aarch64_simd_oi __o;
+ __o = __builtin_aarch64_set_qregoiv16qi (__o, (int8x16_t)tab.val[0], 0);
+ __o = __builtin_aarch64_set_qregoiv16qi (__o, (int8x16_t)tab.val[1], 1);
+ return (uint8x16_t)__builtin_aarch64_tbl3v16qi (__o, (int8x16_t)idx);
+}
+
+__extension__ static __inline poly8x16_t __attribute__ ((__always_inline__))
+vqtbl2q_p8 (poly8x16x2_t tab, uint8x16_t idx)
+{
+ __builtin_aarch64_simd_oi __o;
+ __o = __builtin_aarch64_set_qregoiv16qi (__o, (int8x16_t)tab.val[0], 0);
+ __o = __builtin_aarch64_set_qregoiv16qi (__o, (int8x16_t)tab.val[1], 1);
+ return (poly8x16_t)__builtin_aarch64_tbl3v16qi (__o, (int8x16_t)idx);
+}
+
+/* vqtbl3 */
+
+__extension__ static __inline int8x8_t __attribute__ ((__always_inline__))
+vqtbl3_s8 (int8x16x3_t tab, uint8x8_t idx)
+{
+ __builtin_aarch64_simd_ci __o;
+ __o = __builtin_aarch64_set_qregciv16qi (__o, (int8x16_t)tab.val[0], 0);
+ __o = __builtin_aarch64_set_qregciv16qi (__o, (int8x16_t)tab.val[1], 1);
+ __o = __builtin_aarch64_set_qregciv16qi (__o, (int8x16_t)tab.val[2], 2);
+ return __builtin_aarch64_qtbl3v8qi (__o, (int8x8_t)idx);
+}
+
+__extension__ static __inline uint8x8_t __attribute__ ((__always_inline__))
+vqtbl3_u8 (uint8x16x3_t tab, uint8x8_t idx)
+{
+ __builtin_aarch64_simd_ci __o;
+ __o = __builtin_aarch64_set_qregciv16qi (__o, (int8x16_t)tab.val[0], 0);
+ __o = __builtin_aarch64_set_qregciv16qi (__o, (int8x16_t)tab.val[1], 1);
+ __o = __builtin_aarch64_set_qregciv16qi (__o, (int8x16_t)tab.val[2], 2);
+ return (uint8x8_t)__builtin_aarch64_qtbl3v8qi (__o, (int8x8_t)idx);
+}
+
+__extension__ static __inline poly8x8_t __attribute__ ((__always_inline__))
+vqtbl3_p8 (poly8x16x3_t tab, uint8x8_t idx)
+{
+ __builtin_aarch64_simd_ci __o;
+ __o = __builtin_aarch64_set_qregciv16qi (__o, (int8x16_t)tab.val[0], 0);
+ __o = __builtin_aarch64_set_qregciv16qi (__o, (int8x16_t)tab.val[1], 1);
+ __o = __builtin_aarch64_set_qregciv16qi (__o, (int8x16_t)tab.val[2], 2);
+ return (poly8x8_t)__builtin_aarch64_qtbl3v8qi (__o, (int8x8_t)idx);
+}
+
+__extension__ static __inline int8x16_t __attribute__ ((__always_inline__))
+vqtbl3q_s8 (int8x16x3_t tab, uint8x16_t idx)
+{
+ __builtin_aarch64_simd_ci __o;
+ __o = __builtin_aarch64_set_qregciv16qi (__o, (int8x16_t)tab.val[0], 0);
+ __o = __builtin_aarch64_set_qregciv16qi (__o, (int8x16_t)tab.val[1], 1);
+ __o = __builtin_aarch64_set_qregciv16qi (__o, (int8x16_t)tab.val[2], 2);
+ return __builtin_aarch64_qtbl3v16qi (__o, (int8x16_t)idx);
+}
+
+__extension__ static __inline uint8x16_t __attribute__ ((__always_inline__))
+vqtbl3q_u8 (uint8x16x3_t tab, uint8x16_t idx)
+{
+ __builtin_aarch64_simd_ci __o;
+ __o = __builtin_aarch64_set_qregciv16qi (__o, (int8x16_t)tab.val[0], 0);
+ __o = __builtin_aarch64_set_qregciv16qi (__o, (int8x16_t)tab.val[1], 1);
+ __o = __builtin_aarch64_set_qregciv16qi (__o, (int8x16_t)tab.val[2], 2);
+ return (uint8x16_t)__builtin_aarch64_qtbl3v16qi (__o, (int8x16_t)idx);
+}
+
+__extension__ static __inline poly8x16_t __attribute__ ((__always_inline__))
+vqtbl3q_p8 (poly8x16x3_t tab, uint8x16_t idx)
+{
+ __builtin_aarch64_simd_ci __o;
+ __o = __builtin_aarch64_set_qregciv16qi (__o, (int8x16_t)tab.val[0], 0);
+ __o = __builtin_aarch64_set_qregciv16qi (__o, (int8x16_t)tab.val[1], 1);
+ __o = __builtin_aarch64_set_qregciv16qi (__o, (int8x16_t)tab.val[2], 2);
+ return (poly8x16_t)__builtin_aarch64_qtbl3v16qi (__o, (int8x16_t)idx);
+}
+
+/* vqtbl4 */
+
+__extension__ static __inline int8x8_t __attribute__ ((__always_inline__))
+vqtbl4_s8 (int8x16x4_t tab, uint8x8_t idx)
+{
+ __builtin_aarch64_simd_xi __o;
+ __o = __builtin_aarch64_set_qregxiv16qi (__o, (int8x16_t)tab.val[0], 0);
+ __o = __builtin_aarch64_set_qregxiv16qi (__o, (int8x16_t)tab.val[1], 1);
+ __o = __builtin_aarch64_set_qregxiv16qi (__o, (int8x16_t)tab.val[2], 2);
+ __o = __builtin_aarch64_set_qregxiv16qi (__o, (int8x16_t)tab.val[3], 3);
+ return __builtin_aarch64_qtbl4v8qi (__o, (int8x8_t)idx);
+}
+
+__extension__ static __inline uint8x8_t __attribute__ ((__always_inline__))
+vqtbl4_u8 (uint8x16x4_t tab, uint8x8_t idx)
+{
+ __builtin_aarch64_simd_xi __o;
+ __o = __builtin_aarch64_set_qregxiv16qi (__o, (int8x16_t)tab.val[0], 0);
+ __o = __builtin_aarch64_set_qregxiv16qi (__o, (int8x16_t)tab.val[1], 1);
+ __o = __builtin_aarch64_set_qregxiv16qi (__o, (int8x16_t)tab.val[2], 2);
+ __o = __builtin_aarch64_set_qregxiv16qi (__o, (int8x16_t)tab.val[3], 3);
+ return (uint8x8_t)__builtin_aarch64_qtbl4v8qi (__o, (int8x8_t)idx);
+}
+
+__extension__ static __inline poly8x8_t __attribute__ ((__always_inline__))
+vqtbl4_p8 (poly8x16x4_t tab, uint8x8_t idx)
+{
+ __builtin_aarch64_simd_xi __o;
+ __o = __builtin_aarch64_set_qregxiv16qi (__o, (int8x16_t)tab.val[0], 0);
+ __o = __builtin_aarch64_set_qregxiv16qi (__o, (int8x16_t)tab.val[1], 1);
+ __o = __builtin_aarch64_set_qregxiv16qi (__o, (int8x16_t)tab.val[2], 2);
+ __o = __builtin_aarch64_set_qregxiv16qi (__o, (int8x16_t)tab.val[3], 3);
+ return (poly8x8_t)__builtin_aarch64_qtbl4v8qi (__o, (int8x8_t)idx);
+}
+
+__extension__ static __inline int8x16_t __attribute__ ((__always_inline__))
+vqtbl4q_s8 (int8x16x4_t tab, uint8x16_t idx)
+{
+ __builtin_aarch64_simd_xi __o;
+ __o = __builtin_aarch64_set_qregxiv16qi (__o, (int8x16_t)tab.val[0], 0);
+ __o = __builtin_aarch64_set_qregxiv16qi (__o, (int8x16_t)tab.val[1], 1);
+ __o = __builtin_aarch64_set_qregxiv16qi (__o, (int8x16_t)tab.val[2], 2);
+ __o = __builtin_aarch64_set_qregxiv16qi (__o, (int8x16_t)tab.val[3], 3);
+ return __builtin_aarch64_qtbl4v16qi (__o, (int8x16_t)idx);
+}
+
+__extension__ static __inline uint8x16_t __attribute__ ((__always_inline__))
+vqtbl4q_u8 (uint8x16x4_t tab, uint8x16_t idx)
+{
+ __builtin_aarch64_simd_xi __o;
+ __o = __builtin_aarch64_set_qregxiv16qi (__o, (int8x16_t)tab.val[0], 0);
+ __o = __builtin_aarch64_set_qregxiv16qi (__o, (int8x16_t)tab.val[1], 1);
+ __o = __builtin_aarch64_set_qregxiv16qi (__o, (int8x16_t)tab.val[2], 2);
+ __o = __builtin_aarch64_set_qregxiv16qi (__o, (int8x16_t)tab.val[3], 3);
+ return (uint8x16_t)__builtin_aarch64_qtbl4v16qi (__o, (int8x16_t)idx);
+}
+
+__extension__ static __inline poly8x16_t __attribute__ ((__always_inline__))
+vqtbl4q_p8 (poly8x16x4_t tab, uint8x16_t idx)
+{
+ __builtin_aarch64_simd_xi __o;
+ __o = __builtin_aarch64_set_qregxiv16qi (__o, (int8x16_t)tab.val[0], 0);
+ __o = __builtin_aarch64_set_qregxiv16qi (__o, (int8x16_t)tab.val[1], 1);
+ __o = __builtin_aarch64_set_qregxiv16qi (__o, (int8x16_t)tab.val[2], 2);
+ __o = __builtin_aarch64_set_qregxiv16qi (__o, (int8x16_t)tab.val[3], 3);
+ return (poly8x16_t)__builtin_aarch64_qtbl4v16qi (__o, (int8x16_t)idx);
+}
+
+
+/* vqtbx2 */
+__extension__ static __inline int8x8_t __attribute__ ((__always_inline__))
+vqtbx2_s8 (int8x8_t r, int8x16x2_t tab, uint8x8_t idx)
+{
+ __builtin_aarch64_simd_oi __o;
+ __o = __builtin_aarch64_set_qregoiv16qi (__o, tab.val[0], 0);
+ __o = __builtin_aarch64_set_qregoiv16qi (__o, tab.val[1], 1);
+ return __builtin_aarch64_tbx4v8qi (r, __o, (int8x8_t)idx);
+}
+
+__extension__ static __inline uint8x8_t __attribute__ ((__always_inline__))
+vqtbx2_u8 (uint8x8_t r, uint8x16x2_t tab, uint8x8_t idx)
+{
+ __builtin_aarch64_simd_oi __o;
+ __o = __builtin_aarch64_set_qregoiv16qi (__o, (int8x16_t)tab.val[0], 0);
+ __o = __builtin_aarch64_set_qregoiv16qi (__o, (int8x16_t)tab.val[1], 1);
+ return (uint8x8_t)__builtin_aarch64_tbx4v8qi ((int8x8_t)r, __o,
+ (int8x8_t)idx);
+}
+
+__extension__ static __inline poly8x8_t __attribute__ ((__always_inline__))
+vqtbx2_p8 (poly8x8_t r, poly8x16x2_t tab, uint8x8_t idx)
+{
+ __builtin_aarch64_simd_oi __o;
+ __o = __builtin_aarch64_set_qregoiv16qi (__o, (int8x16_t)tab.val[0], 0);
+ __o = __builtin_aarch64_set_qregoiv16qi (__o, (int8x16_t)tab.val[1], 1);
+ return (poly8x8_t)__builtin_aarch64_tbx4v8qi ((int8x8_t)r, __o,
+ (int8x8_t)idx);
+}
+
+__extension__ static __inline int8x16_t __attribute__ ((__always_inline__))
+vqtbx2q_s8 (int8x16_t r, int8x16x2_t tab, uint8x16_t idx)
+{
+ __builtin_aarch64_simd_oi __o;
+ __o = __builtin_aarch64_set_qregoiv16qi (__o, tab.val[0], 0);
+ __o = __builtin_aarch64_set_qregoiv16qi (__o, tab.val[1], 1);
+ return __builtin_aarch64_tbx4v16qi (r, __o, (int8x16_t)idx);
+}
+
+__extension__ static __inline uint8x16_t __attribute__ ((__always_inline__))
+vqtbx2q_u8 (uint8x16_t r, uint8x16x2_t tab, uint8x16_t idx)
+{
+ __builtin_aarch64_simd_oi __o;
+ __o = __builtin_aarch64_set_qregoiv16qi (__o, (int8x16_t)tab.val[0], 0);
+ __o = __builtin_aarch64_set_qregoiv16qi (__o, (int8x16_t)tab.val[1], 1);
+ return (uint8x16_t)__builtin_aarch64_tbx4v16qi ((int8x16_t)r, __o,
+ (int8x16_t)idx);
+}
+
+__extension__ static __inline poly8x16_t __attribute__ ((__always_inline__))
+vqtbx2q_p8 (poly8x16_t r, poly8x16x2_t tab, uint8x16_t idx)
+{
+ __builtin_aarch64_simd_oi __o;
+ __o = __builtin_aarch64_set_qregoiv16qi (__o, (int8x16_t)tab.val[0], 0);
+ __o = __builtin_aarch64_set_qregoiv16qi (__o, (int8x16_t)tab.val[1], 1);
+ return (poly8x16_t)__builtin_aarch64_tbx4v16qi ((int8x16_t)r, __o,
+ (int8x16_t)idx);
+}
+
+/* vqtbx3 */
+__extension__ static __inline int8x8_t __attribute__ ((__always_inline__))
+vqtbx3_s8 (int8x8_t r, int8x16x3_t tab, uint8x8_t idx)
+{
+ __builtin_aarch64_simd_ci __o;
+ __o = __builtin_aarch64_set_qregciv16qi (__o, tab.val[0], 0);
+ __o = __builtin_aarch64_set_qregciv16qi (__o, tab.val[1], 1);
+ __o = __builtin_aarch64_set_qregciv16qi (__o, tab.val[2], 2);
+ return __builtin_aarch64_qtbx3v8qi (r, __o, (int8x8_t)idx);
+}
+
+__extension__ static __inline uint8x8_t __attribute__ ((__always_inline__))
+vqtbx3_u8 (uint8x8_t r, uint8x16x3_t tab, uint8x8_t idx)
+{
+ __builtin_aarch64_simd_ci __o;
+ __o = __builtin_aarch64_set_qregciv16qi (__o, (int8x16_t)tab.val[0], 0);
+ __o = __builtin_aarch64_set_qregciv16qi (__o, (int8x16_t)tab.val[1], 1);
+ __o = __builtin_aarch64_set_qregciv16qi (__o, (int8x16_t)tab.val[2], 2);
+ return (uint8x8_t)__builtin_aarch64_qtbx3v8qi ((int8x8_t)r, __o,
+ (int8x8_t)idx);
+}
+
+__extension__ static __inline poly8x8_t __attribute__ ((__always_inline__))
+vqtbx3_p8 (poly8x8_t r, poly8x16x3_t tab, uint8x8_t idx)
+{
+ __builtin_aarch64_simd_ci __o;
+ __o = __builtin_aarch64_set_qregciv16qi (__o, (int8x16_t)tab.val[0], 0);
+ __o = __builtin_aarch64_set_qregciv16qi (__o, (int8x16_t)tab.val[1], 1);
+ __o = __builtin_aarch64_set_qregciv16qi (__o, (int8x16_t)tab.val[2], 2);
+ return (poly8x8_t)__builtin_aarch64_qtbx3v8qi ((int8x8_t)r, __o,
+ (int8x8_t)idx);
+}
+
+__extension__ static __inline int8x16_t __attribute__ ((__always_inline__))
+vqtbx3q_s8 (int8x16_t r, int8x16x3_t tab, uint8x16_t idx)
+{
+ __builtin_aarch64_simd_ci __o;
+ __o = __builtin_aarch64_set_qregciv16qi (__o, tab.val[0], 0);
+ __o = __builtin_aarch64_set_qregciv16qi (__o, tab.val[1], 1);
+ __o = __builtin_aarch64_set_qregciv16qi (__o, tab.val[2], 2);
+ return __builtin_aarch64_qtbx3v16qi (r, __o, (int8x16_t)idx);
+}
+
+__extension__ static __inline uint8x16_t __attribute__ ((__always_inline__))
+vqtbx3q_u8 (uint8x16_t r, uint8x16x3_t tab, uint8x16_t idx)
+{
+ __builtin_aarch64_simd_ci __o;
+ __o = __builtin_aarch64_set_qregciv16qi (__o, (int8x16_t)tab.val[0], 0);
+ __o = __builtin_aarch64_set_qregciv16qi (__o, (int8x16_t)tab.val[1], 1);
+ __o = __builtin_aarch64_set_qregciv16qi (__o, (int8x16_t)tab.val[2], 2);
+ return (uint8x16_t)__builtin_aarch64_qtbx3v16qi ((int8x16_t)r, __o,
+ (int8x16_t)idx);
+}
+
+__extension__ static __inline poly8x16_t __attribute__ ((__always_inline__))
+vqtbx3q_p8 (poly8x16_t r, poly8x16x3_t tab, uint8x16_t idx)
+{
+ __builtin_aarch64_simd_ci __o;
+ __o = __builtin_aarch64_set_qregciv16qi (__o, (int8x16_t)tab.val[0], 0);
+ __o = __builtin_aarch64_set_qregciv16qi (__o, (int8x16_t)tab.val[1], 1);
+ __o = __builtin_aarch64_set_qregciv16qi (__o, (int8x16_t)tab.val[2], 2);
+ return (poly8x16_t)__builtin_aarch64_qtbx3v16qi ((int8x16_t)r, __o,
+ (int8x16_t)idx);
+}
+
+/* vqtbx4 */
+
+__extension__ static __inline int8x8_t __attribute__ ((__always_inline__))
+vqtbx4_s8 (int8x8_t r, int8x16x4_t tab, uint8x8_t idx)
+{
+ __builtin_aarch64_simd_xi __o;
+ __o = __builtin_aarch64_set_qregxiv16qi (__o, tab.val[0], 0);
+ __o = __builtin_aarch64_set_qregxiv16qi (__o, tab.val[1], 1);
+ __o = __builtin_aarch64_set_qregxiv16qi (__o, tab.val[2], 2);
+ __o = __builtin_aarch64_set_qregxiv16qi (__o, tab.val[3], 3);
+ return __builtin_aarch64_qtbx4v8qi (r, __o, (int8x8_t)idx);
+}
+
+__extension__ static __inline uint8x8_t __attribute__ ((__always_inline__))
+vqtbx4_u8 (uint8x8_t r, uint8x16x4_t tab, uint8x8_t idx)
+{
+ __builtin_aarch64_simd_xi __o;
+ __o = __builtin_aarch64_set_qregxiv16qi (__o, (int8x16_t)tab.val[0], 0);
+ __o = __builtin_aarch64_set_qregxiv16qi (__o, (int8x16_t)tab.val[1], 1);
+ __o = __builtin_aarch64_set_qregxiv16qi (__o, (int8x16_t)tab.val[2], 2);
+ __o = __builtin_aarch64_set_qregxiv16qi (__o, (int8x16_t)tab.val[3], 3);
+ return (uint8x8_t)__builtin_aarch64_qtbx4v8qi ((int8x8_t)r, __o,
+ (int8x8_t)idx);
+}
+
+__extension__ static __inline poly8x8_t __attribute__ ((__always_inline__))
+vqtbx4_p8 (poly8x8_t r, poly8x16x4_t tab, uint8x8_t idx)
+{
+ __builtin_aarch64_simd_xi __o;
+ __o = __builtin_aarch64_set_qregxiv16qi (__o, (int8x16_t)tab.val[0], 0);
+ __o = __builtin_aarch64_set_qregxiv16qi (__o, (int8x16_t)tab.val[1], 1);
+ __o = __builtin_aarch64_set_qregxiv16qi (__o, (int8x16_t)tab.val[2], 2);
+ __o = __builtin_aarch64_set_qregxiv16qi (__o, (int8x16_t)tab.val[3], 3);
+ return (poly8x8_t)__builtin_aarch64_qtbx4v8qi ((int8x8_t)r, __o,
+ (int8x8_t)idx);
+}
+
+__extension__ static __inline int8x16_t __attribute__ ((__always_inline__))
+vqtbx4q_s8 (int8x16_t r, int8x16x4_t tab, uint8x16_t idx)
+{
+ __builtin_aarch64_simd_xi __o;
+ __o = __builtin_aarch64_set_qregxiv16qi (__o, tab.val[0], 0);
+ __o = __builtin_aarch64_set_qregxiv16qi (__o, tab.val[1], 1);
+ __o = __builtin_aarch64_set_qregxiv16qi (__o, tab.val[2], 2);
+ __o = __builtin_aarch64_set_qregxiv16qi (__o, tab.val[3], 3);
+ return __builtin_aarch64_qtbx4v16qi (r, __o, (int8x16_t)idx);
+}
+
+__extension__ static __inline uint8x16_t __attribute__ ((__always_inline__))
+vqtbx4q_u8 (uint8x16_t r, uint8x16x4_t tab, uint8x16_t idx)
+{
+ __builtin_aarch64_simd_xi __o;
+ __o = __builtin_aarch64_set_qregxiv16qi (__o, (int8x16_t)tab.val[0], 0);
+ __o = __builtin_aarch64_set_qregxiv16qi (__o, (int8x16_t)tab.val[1], 1);
+ __o = __builtin_aarch64_set_qregxiv16qi (__o, (int8x16_t)tab.val[2], 2);
+ __o = __builtin_aarch64_set_qregxiv16qi (__o, (int8x16_t)tab.val[3], 3);
+ return (uint8x16_t)__builtin_aarch64_qtbx4v16qi ((int8x16_t)r, __o,
+ (int8x16_t)idx);
+}
+
+__extension__ static __inline poly8x16_t __attribute__ ((__always_inline__))
+vqtbx4q_p8 (poly8x16_t r, poly8x16x4_t tab, uint8x16_t idx)
+{
+ __builtin_aarch64_simd_xi __o;
+ __o = __builtin_aarch64_set_qregxiv16qi (__o, (int8x16_t)tab.val[0], 0);
+ __o = __builtin_aarch64_set_qregxiv16qi (__o, (int8x16_t)tab.val[1], 1);
+ __o = __builtin_aarch64_set_qregxiv16qi (__o, (int8x16_t)tab.val[2], 2);
+ __o = __builtin_aarch64_set_qregxiv16qi (__o, (int8x16_t)tab.val[3], 3);
+ return (poly8x16_t)__builtin_aarch64_qtbx4v16qi ((int8x16_t)r, __o,
+ (int8x16_t)idx);
+}
+
/* vrbit */
__extension__ static __inline poly8x8_t __attribute__ ((__always_inline__))
diff --git a/gcc/config/arm/aarch-common.c b/gcc/config/arm/aarch-common.c
index a940a0232f8..e6668d5742c 100644
--- a/gcc/config/arm/aarch-common.c
+++ b/gcc/config/arm/aarch-common.c
@@ -460,6 +460,12 @@ aarch_accumulator_forwarding (rtx_insn *producer, rtx_insn *consumer)
return 0;
}
+ if (GET_CODE (accumulator) == SUBREG)
+ accumulator = SUBREG_REG (accumulator);
+
+ if (!REG_P (accumulator))
+ return 0;
+
return (REGNO (dest) == REGNO (accumulator));
}
diff --git a/gcc/config/arm/arm-ldmstm.ml b/gcc/config/arm/arm-ldmstm.ml
index bb901922e83..62982df594d 100644
--- a/gcc/config/arm/arm-ldmstm.ml
+++ b/gcc/config/arm/arm-ldmstm.ml
@@ -33,9 +33,20 @@ type amode = IA | IB | DA | DB
type optype = IN | OUT | INOUT
-let rec string_of_addrmode addrmode =
+let rec string_of_addrmode addrmode thumb update =
+ if thumb || update
+then
match addrmode with
- IA -> "ia" | IB -> "ib" | DA -> "da" | DB -> "db"
+ IA -> "ia"
+ | IB -> "ib"
+ | DA -> "da"
+ | DB -> "db"
+else
+ match addrmode with
+ IA -> ""
+ | IB -> "ib"
+ | DA -> "da"
+ | DB -> "db"
let rec initial_offset addrmode nregs =
match addrmode with
@@ -160,7 +171,7 @@ let target addrmode thumb =
| _, _ -> raise (InvalidAddrMode "ERROR: Invalid Addressing mode for Thumb1.")
let write_pattern_1 name ls addrmode nregs write_set_fn update thumb =
- let astr = string_of_addrmode addrmode in
+ let astr = string_of_addrmode addrmode thumb update in
Printf.printf "(define_insn \"*%s%s%d_%s%s\"\n"
(if thumb then "thumb_" else "") name nregs astr
(if update then "_update" else "");
@@ -180,8 +191,10 @@ let write_pattern_1 name ls addrmode nregs write_set_fn update thumb =
Printf.printf ")]\n \"%s && XVECLEN (operands[0], 0) == %d\"\n"
(target addrmode thumb)
(if update then nregs + 1 else nregs);
- Printf.printf " \"%s%%(%s%%)\\t%%%d%s, {"
- name astr (nregs + 1) (if update then "!" else "");
+ if thumb then
+ Printf.printf " \"%s%s\\t%%%d%s, {" name astr (nregs + 1) (if update then "!" else "")
+ else
+ Printf.printf " \"%s%s%%?\\t%%%d%s, {" name astr (nregs + 1) (if update then "!" else "");
for n = 1 to nregs; do
Printf.printf "%%%d%s" n (if n < nregs then ", " else "")
done;
diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
index 43106387c1a..61e2aa23006 100644
--- a/gcc/config/arm/arm.c
+++ b/gcc/config/arm/arm.c
@@ -913,7 +913,7 @@ int arm_regs_in_sequence[] =
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15
};
-#define ARM_LSL_NAME (TARGET_UNIFIED_ASM ? "lsl" : "asl")
+#define ARM_LSL_NAME "lsl"
#define streq(string1, string2) (strcmp (string1, string2) == 0)
#define THUMB2_WORK_REGS (0xff & ~( (1 << THUMB_HARD_FRAME_POINTER_REGNUM) \
@@ -3566,10 +3566,7 @@ arm_warn_func_return (tree decl)
static void
arm_asm_trampoline_template (FILE *f)
{
- if (TARGET_UNIFIED_ASM)
- fprintf (f, "\t.syntax unified\n");
- else
- fprintf (f, "\t.syntax divided\n");
+ fprintf (f, "\t.syntax unified\n");
if (TARGET_ARM)
{
@@ -17637,10 +17634,8 @@ arm_output_multireg_pop (rtx *operands, bool return_pc, rtx cond, bool reverse,
}
conditional = reverse ? "%?%D0" : "%?%d0";
- if ((regno_base == SP_REGNUM) && TARGET_THUMB)
+ if ((regno_base == SP_REGNUM) && update)
{
- /* Output pop (not stmfd) because it has a shorter encoding. */
- gcc_assert (update);
sprintf (pattern, "pop%s\t{", conditional);
}
else
@@ -17648,11 +17643,14 @@ arm_output_multireg_pop (rtx *operands, bool return_pc, rtx cond, bool reverse,
/* Output ldmfd when the base register is SP, otherwise output ldmia.
It's just a convention, their semantics are identical. */
if (regno_base == SP_REGNUM)
- sprintf (pattern, "ldm%sfd\t", conditional);
- else if (TARGET_UNIFIED_ASM)
- sprintf (pattern, "ldmia%s\t", conditional);
+ /* update is never true here, hence there is no need to handle
+ pop here. */
+ sprintf (pattern, "ldmfd%s", conditional);
+
+ if (update)
+ sprintf (pattern, "ldmia%s\t", conditional);
else
- sprintf (pattern, "ldm%sia\t", conditional);
+ sprintf (pattern, "ldm%s\t", conditional);
strcat (pattern, reg_names[regno_base]);
if (update)
@@ -17992,25 +17990,25 @@ output_move_double (rtx *operands, bool emit, int *count)
{
if (TARGET_LDRD
&& !(fix_cm3_ldrd && reg0 == REGNO(XEXP (operands[1], 0))))
- output_asm_insn ("ldr%(d%)\t%0, [%m1]", operands);
+ output_asm_insn ("ldrd%?\t%0, [%m1]", operands);
else
- output_asm_insn ("ldm%(ia%)\t%m1, %M0", operands);
+ output_asm_insn ("ldmia%?\t%m1, %M0", operands);
}
break;
case PRE_INC:
gcc_assert (TARGET_LDRD);
if (emit)
- output_asm_insn ("ldr%(d%)\t%0, [%m1, #8]!", operands);
+ output_asm_insn ("ldrd%?\t%0, [%m1, #8]!", operands);
break;
case PRE_DEC:
if (emit)
{
if (TARGET_LDRD)
- output_asm_insn ("ldr%(d%)\t%0, [%m1, #-8]!", operands);
+ output_asm_insn ("ldrd%?\t%0, [%m1, #-8]!", operands);
else
- output_asm_insn ("ldm%(db%)\t%m1!, %M0", operands);
+ output_asm_insn ("ldmdb%?\t%m1!, %M0", operands);
}
break;
@@ -18018,16 +18016,16 @@ output_move_double (rtx *operands, bool emit, int *count)
if (emit)
{
if (TARGET_LDRD)
- output_asm_insn ("ldr%(d%)\t%0, [%m1], #8", operands);
+ output_asm_insn ("ldrd%?\t%0, [%m1], #8", operands);
else
- output_asm_insn ("ldm%(ia%)\t%m1!, %M0", operands);
+ output_asm_insn ("ldmia%?\t%m1!, %M0", operands);
}
break;
case POST_DEC:
gcc_assert (TARGET_LDRD);
if (emit)
- output_asm_insn ("ldr%(d%)\t%0, [%m1], #-8", operands);
+ output_asm_insn ("ldrd%?\t%0, [%m1], #-8", operands);
break;
case PRE_MODIFY:
@@ -18048,7 +18046,7 @@ output_move_double (rtx *operands, bool emit, int *count)
if (emit)
{
output_asm_insn ("add%?\t%1, %1, %2", otherops);
- output_asm_insn ("ldr%(d%)\t%0, [%1] @split", otherops);
+ output_asm_insn ("ldrd%?\t%0, [%1] @split", otherops);
}
if (count)
*count = 2;
@@ -18064,7 +18062,7 @@ output_move_double (rtx *operands, bool emit, int *count)
&& INTVAL (otherops[2]) < 256))
{
if (emit)
- output_asm_insn ("ldr%(d%)\t%0, [%1, %2]!", otherops);
+ output_asm_insn ("ldrd%?\t%0, [%1, %2]!", otherops);
}
else
{
@@ -18090,7 +18088,7 @@ output_move_double (rtx *operands, bool emit, int *count)
&& INTVAL (otherops[2]) < 256))
{
if (emit)
- output_asm_insn ("ldr%(d%)\t%0, [%1], %2", otherops);
+ output_asm_insn ("ldrd%?\t%0, [%1], %2", otherops);
}
else
{
@@ -18119,9 +18117,9 @@ output_move_double (rtx *operands, bool emit, int *count)
if (emit)
{
if (TARGET_LDRD)
- output_asm_insn ("ldr%(d%)\t%0, [%1]", operands);
+ output_asm_insn ("ldrd%?\t%0, [%1]", operands);
else
- output_asm_insn ("ldm%(ia%)\t%1, %M0", operands);
+ output_asm_insn ("ldmia%?\t%1, %M0", operands);
}
if (count)
@@ -18145,19 +18143,19 @@ output_move_double (rtx *operands, bool emit, int *count)
{
case -8:
if (emit)
- output_asm_insn ("ldm%(db%)\t%1, %M0", otherops);
+ output_asm_insn ("ldmdb%?\t%1, %M0", otherops);
return "";
case -4:
if (TARGET_THUMB2)
break;
if (emit)
- output_asm_insn ("ldm%(da%)\t%1, %M0", otherops);
+ output_asm_insn ("ldmda%?\t%1, %M0", otherops);
return "";
case 4:
if (TARGET_THUMB2)
break;
if (emit)
- output_asm_insn ("ldm%(ib%)\t%1, %M0", otherops);
+ output_asm_insn ("ldmib%?\t%1, %M0", otherops);
return "";
}
}
@@ -18185,7 +18183,7 @@ output_move_double (rtx *operands, bool emit, int *count)
if (emit)
{
output_asm_insn ("add%?\t%0, %1, %2", otherops);
- output_asm_insn ("ldr%(d%)\t%0, [%1]", operands);
+ output_asm_insn ("ldrd%?\t%0, [%1]", operands);
}
if (count)
*count = 2;
@@ -18194,7 +18192,7 @@ output_move_double (rtx *operands, bool emit, int *count)
{
otherops[0] = operands[0];
if (emit)
- output_asm_insn ("ldr%(d%)\t%0, [%1, %2]", otherops);
+ output_asm_insn ("ldrd%?\t%0, [%1, %2]", otherops);
}
return "";
}
@@ -18225,9 +18223,9 @@ output_move_double (rtx *operands, bool emit, int *count)
*count = 2;
if (TARGET_LDRD)
- return "ldr%(d%)\t%0, [%1]";
+ return "ldrd%?\t%0, [%1]";
- return "ldm%(ia%)\t%1, %M0";
+ return "ldmia%?\t%1, %M0";
}
else
{
@@ -18270,25 +18268,25 @@ output_move_double (rtx *operands, bool emit, int *count)
if (emit)
{
if (TARGET_LDRD)
- output_asm_insn ("str%(d%)\t%1, [%m0]", operands);
+ output_asm_insn ("strd%?\t%1, [%m0]", operands);
else
- output_asm_insn ("stm%(ia%)\t%m0, %M1", operands);
+ output_asm_insn ("stm%?\t%m0, %M1", operands);
}
break;
case PRE_INC:
gcc_assert (TARGET_LDRD);
if (emit)
- output_asm_insn ("str%(d%)\t%1, [%m0, #8]!", operands);
+ output_asm_insn ("strd%?\t%1, [%m0, #8]!", operands);
break;
case PRE_DEC:
if (emit)
{
if (TARGET_LDRD)
- output_asm_insn ("str%(d%)\t%1, [%m0, #-8]!", operands);
+ output_asm_insn ("strd%?\t%1, [%m0, #-8]!", operands);
else
- output_asm_insn ("stm%(db%)\t%m0!, %M1", operands);
+ output_asm_insn ("stmdb%?\t%m0!, %M1", operands);
}
break;
@@ -18296,16 +18294,16 @@ output_move_double (rtx *operands, bool emit, int *count)
if (emit)
{
if (TARGET_LDRD)
- output_asm_insn ("str%(d%)\t%1, [%m0], #8", operands);
+ output_asm_insn ("strd%?\t%1, [%m0], #8", operands);
else
- output_asm_insn ("stm%(ia%)\t%m0!, %M1", operands);
+ output_asm_insn ("stm%?\t%m0!, %M1", operands);
}
break;
case POST_DEC:
gcc_assert (TARGET_LDRD);
if (emit)
- output_asm_insn ("str%(d%)\t%1, [%m0], #-8", operands);
+ output_asm_insn ("strd%?\t%1, [%m0], #-8", operands);
break;
case PRE_MODIFY:
@@ -18345,12 +18343,12 @@ output_move_double (rtx *operands, bool emit, int *count)
else if (GET_CODE (XEXP (operands[0], 0)) == PRE_MODIFY)
{
if (emit)
- output_asm_insn ("str%(d%)\t%0, [%1, %2]!", otherops);
+ output_asm_insn ("strd%?\t%0, [%1, %2]!", otherops);
}
else
{
if (emit)
- output_asm_insn ("str%(d%)\t%0, [%1], %2", otherops);
+ output_asm_insn ("strd%?\t%0, [%1], %2", otherops);
}
break;
@@ -18362,21 +18360,21 @@ output_move_double (rtx *operands, bool emit, int *count)
{
case -8:
if (emit)
- output_asm_insn ("stm%(db%)\t%m0, %M1", operands);
+ output_asm_insn ("stmdb%?\t%m0, %M1", operands);
return "";
case -4:
if (TARGET_THUMB2)
break;
if (emit)
- output_asm_insn ("stm%(da%)\t%m0, %M1", operands);
+ output_asm_insn ("stmda%?\t%m0, %M1", operands);
return "";
case 4:
if (TARGET_THUMB2)
break;
if (emit)
- output_asm_insn ("stm%(ib%)\t%m0, %M1", operands);
+ output_asm_insn ("stmib%?\t%m0, %M1", operands);
return "";
}
}
@@ -18390,7 +18388,7 @@ output_move_double (rtx *operands, bool emit, int *count)
otherops[0] = operands[1];
otherops[1] = XEXP (XEXP (operands[0], 0), 0);
if (emit)
- output_asm_insn ("str%(d%)\t%0, [%1, %2]", otherops);
+ output_asm_insn ("strd%?\t%0, [%1, %2]", otherops);
return "";
}
/* Fall through */
@@ -18426,13 +18424,13 @@ output_move_quad (rtx *operands)
switch (GET_CODE (XEXP (operands[1], 0)))
{
case REG:
- output_asm_insn ("ldm%(ia%)\t%m1, %M0", operands);
+ output_asm_insn ("ldmia%?\t%m1, %M0", operands);
break;
case LABEL_REF:
case CONST:
output_asm_insn ("adr%?\t%0, %1", operands);
- output_asm_insn ("ldm%(ia%)\t%0, %M0", operands);
+ output_asm_insn ("ldmia%?\t%0, %M0", operands);
break;
default:
@@ -18476,7 +18474,7 @@ output_move_quad (rtx *operands)
switch (GET_CODE (XEXP (operands[0], 0)))
{
case REG:
- output_asm_insn ("stm%(ia%)\t%m0, %M1", operands);
+ output_asm_insn ("stm%?\t%m0, %M1", operands);
break;
default:
@@ -19510,10 +19508,7 @@ output_return_instruction (rtx operand, bool really_return, bool reverse,
gcc_assert (stack_adjust == 0 || stack_adjust == 4);
if (stack_adjust && arm_arch5 && TARGET_ARM)
- if (TARGET_UNIFIED_ASM)
sprintf (instr, "ldmib%s\t%%|sp, {", conditional);
- else
- sprintf (instr, "ldm%sib\t%%|sp, {", conditional);
else
{
/* If we can't use ldmib (SA110 bug),
@@ -19521,17 +19516,11 @@ output_return_instruction (rtx operand, bool really_return, bool reverse,
if (stack_adjust)
live_regs_mask |= 1 << 3;
- if (TARGET_UNIFIED_ASM)
- sprintf (instr, "ldmfd%s\t%%|sp, {", conditional);
- else
- sprintf (instr, "ldm%sfd\t%%|sp, {", conditional);
+ sprintf (instr, "ldmfd%s\t%%|sp, {", conditional);
}
}
else
- if (TARGET_UNIFIED_ASM)
sprintf (instr, "pop%s\t{", conditional);
- else
- sprintf (instr, "ldm%sfd\t%%|sp!, {", conditional);
p = instr + strlen (instr);
@@ -21804,37 +21793,17 @@ arm_print_operand (FILE *stream, rtx x, int code)
arm_print_condition (stream);
return;
- case '(':
- /* Nothing in unified syntax, otherwise the current condition code. */
- if (!TARGET_UNIFIED_ASM)
- arm_print_condition (stream);
- break;
-
- case ')':
- /* The current condition code in unified syntax, otherwise nothing. */
- if (TARGET_UNIFIED_ASM)
- arm_print_condition (stream);
- break;
-
case '.':
/* The current condition code for a condition code setting instruction.
Preceded by 's' in unified syntax, otherwise followed by 's'. */
- if (TARGET_UNIFIED_ASM)
- {
- fputc('s', stream);
- arm_print_condition (stream);
- }
- else
- {
- arm_print_condition (stream);
- fputc('s', stream);
- }
+ fputc('s', stream);
+ arm_print_condition (stream);
return;
case '!':
/* If the instruction is conditionally executed then print
the current condition code, otherwise print 's'. */
- gcc_assert (TARGET_THUMB2 && TARGET_UNIFIED_ASM);
+ gcc_assert (TARGET_THUMB2);
if (current_insn_predicate)
arm_print_condition (stream);
else
@@ -27243,20 +27212,16 @@ arm_output_shift(rtx * operands, int set_flags)
char c;
c = flag_chars[set_flags];
- if (TARGET_UNIFIED_ASM)
+ shift = shift_op(operands[3], &val);
+ if (shift)
{
- shift = shift_op(operands[3], &val);
- if (shift)
- {
- if (val != -1)
- operands[2] = GEN_INT(val);
- sprintf (pattern, "%s%%%c\t%%0, %%1, %%2", shift, c);
- }
- else
- sprintf (pattern, "mov%%%c\t%%0, %%1", c);
+ if (val != -1)
+ operands[2] = GEN_INT(val);
+ sprintf (pattern, "%s%%%c\t%%0, %%1, %%2", shift, c);
}
else
- sprintf (pattern, "mov%%%c\t%%0, %%1%%S3", c);
+ sprintf (pattern, "mov%%%c\t%%0, %%1", c);
+
output_asm_insn (pattern, operands);
return "";
}
@@ -30005,10 +29970,8 @@ arm_valid_target_attribute_p (tree fndecl, tree ARG_UNUSED (name),
void
arm_declare_function_name (FILE *stream, const char *name, tree decl)
{
- if (TARGET_UNIFIED_ASM)
- fprintf (stream, "\t.syntax unified\n");
- else
- fprintf (stream, "\t.syntax divided\n");
+
+ fprintf (stream, "\t.syntax unified\n");
if (TARGET_THUMB)
{
diff --git a/gcc/config/arm/arm.h b/gcc/config/arm/arm.h
index 585bd1d95f3..a1a04a94ef2 100644
--- a/gcc/config/arm/arm.h
+++ b/gcc/config/arm/arm.h
@@ -237,10 +237,6 @@ extern void (*arm_lang_output_object_attributes_hook)(void);
&& (arm_disable_literal_pool \
|| (!optimize_size && !current_tune->prefer_constant_pool)))
-/* We could use unified syntax for arm mode, but for now we just use it
- for thumb mode. */
-#define TARGET_UNIFIED_ASM (TARGET_THUMB)
-
/* Nonzero if this chip provides the DMB instruction. */
#define TARGET_HAVE_DMB (arm_arch6m || arm_arch7)
@@ -2023,8 +2019,7 @@ extern int making_const_table;
"\t.syntax divided\n")
#undef ASM_APP_OFF
-#define ASM_APP_OFF (TARGET_ARM ? "\t.arm\n\t.syntax divided\n" : \
- "\t.thumb\n\t.syntax unified\n")
+#define ASM_APP_OFF "\t.syntax unified\n"
/* Output a push or a pop instruction (only used when profiling).
We can't push STATIC_CHAIN_REGNUM (r12) directly with Thumb-1. We know
@@ -2035,10 +2030,7 @@ extern int making_const_table;
#define ASM_OUTPUT_REG_PUSH(STREAM, REGNO) \
do \
{ \
- if (TARGET_ARM) \
- asm_fprintf (STREAM,"\tstmfd\t%r!,{%r}\n", \
- STACK_POINTER_REGNUM, REGNO); \
- else if (TARGET_THUMB1 \
+ if (TARGET_THUMB1 \
&& (REGNO) == STATIC_CHAIN_REGNUM) \
{ \
asm_fprintf (STREAM, "\tpush\t{r7}\n"); \
@@ -2054,11 +2046,8 @@ extern int making_const_table;
#define ASM_OUTPUT_REG_POP(STREAM, REGNO) \
do \
{ \
- if (TARGET_ARM) \
- asm_fprintf (STREAM, "\tldmfd\t%r!,{%r}\n", \
- STACK_POINTER_REGNUM, REGNO); \
- else if (TARGET_THUMB1 \
- && (REGNO) == STATIC_CHAIN_REGNUM) \
+ if (TARGET_THUMB1 \
+ && (REGNO) == STATIC_CHAIN_REGNUM) \
{ \
asm_fprintf (STREAM, "\tpop\t{r7}\n"); \
asm_fprintf (STREAM, "\tmov\t%r, r7\n", REGNO);\
diff --git a/gcc/config/arm/arm.md b/gcc/config/arm/arm.md
index 02e147ec4a4..8ebb1bfd221 100644
--- a/gcc/config/arm/arm.md
+++ b/gcc/config/arm/arm.md
@@ -622,9 +622,9 @@
(plus:SI (match_dup 1) (match_dup 2)))]
"TARGET_ARM"
"@
- add%.\\t%0, %1, %2
- sub%.\\t%0, %1, #%n2
- add%.\\t%0, %1, %2"
+ adds%?\\t%0, %1, %2
+ subs%?\\t%0, %1, #%n2
+ adds%?\\t%0, %1, %2"
[(set_attr "conds" "set")
(set_attr "type" "alus_imm,alus_imm,alus_sreg")]
)
@@ -672,8 +672,8 @@
(match_operand:SI 3 "arm_addimm_operand" "I,L")))]
"TARGET_32BIT && INTVAL (operands[2]) == -INTVAL (operands[3])"
"@
- add%.\\t%0, %1, %3
- sub%.\\t%0, %1, #%n3"
+ adds%?\\t%0, %1, %3
+ subs%?\\t%0, %1, #%n3"
[(set_attr "conds" "set")
(set_attr "type" "alus_sreg")]
)
@@ -729,9 +729,9 @@
(plus:SI (match_dup 1) (match_dup 2)))]
"TARGET_32BIT"
"@
- add%.\\t%0, %1, %2
- sub%.\\t%0, %1, #%n2
- add%.\\t%0, %1, %2"
+ adds%?\\t%0, %1, %2
+ subs%?\\t%0, %1, #%n2
+ adds%?\\t%0, %1, %2"
[(set_attr "conds" "set")
(set_attr "type" "alus_imm,alus_imm,alus_sreg")]
)
@@ -746,9 +746,9 @@
(plus:SI (match_dup 1) (match_dup 2)))]
"TARGET_32BIT"
"@
- add%.\\t%0, %1, %2
- add%.\\t%0, %1, %2
- sub%.\\t%0, %1, #%n2"
+ adds%?\\t%0, %1, %2
+ adds%?\\t%0, %1, %2
+ subs%?\\t%0, %1, #%n2"
[(set_attr "conds" "set")
(set_attr "type" "alus_imm,alus_imm,alus_sreg")]
)
@@ -856,7 +856,7 @@
(LTUGEU:SI (reg:<cnb> CC_REGNUM) (const_int 0))))
(clobber (reg:CC CC_REGNUM))]
"TARGET_32BIT"
- "adc%.\\t%0, %1, %2"
+ "adcs%?\\t%0, %1, %2"
[(set_attr "conds" "set")
(set_attr "type" "adcs_reg")]
)
@@ -1239,9 +1239,9 @@
(minus:SI (match_dup 1) (match_dup 2)))]
"TARGET_32BIT"
"@
- sub%.\\t%0, %1, %2
- sub%.\\t%0, %1, %2
- rsb%.\\t%0, %2, %1"
+ subs%?\\t%0, %1, %2
+ subs%?\\t%0, %1, %2
+ rsbs%?\\t%0, %2, %1"
[(set_attr "conds" "set")
(set_attr "type" "alus_imm,alus_sreg,alus_sreg")]
)
@@ -1254,9 +1254,9 @@
(minus:SI (match_dup 1) (match_dup 2)))]
"TARGET_32BIT"
"@
- sub%.\\t%0, %1, %2
- sub%.\\t%0, %1, %2
- rsb%.\\t%0, %2, %1"
+ subs%?\\t%0, %1, %2
+ subs%?\\t%0, %1, %2
+ rsbs%?\\t%0, %2, %1"
[(set_attr "conds" "set")
(set_attr "type" "alus_imm,alus_sreg,alus_sreg")]
)
@@ -1335,7 +1335,7 @@
(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
(mult:SI (match_dup 2) (match_dup 1)))]
"TARGET_ARM && !arm_arch6"
- "mul%.\\t%0, %2, %1"
+ "muls%?\\t%0, %2, %1"
[(set_attr "conds" "set")
(set_attr "type" "muls")]
)
@@ -1349,7 +1349,7 @@
(set (match_operand:SI 0 "s_register_operand" "=r")
(mult:SI (match_dup 2) (match_dup 1)))]
"TARGET_ARM && arm_arch6 && optimize_size"
- "mul%.\\t%0, %2, %1"
+ "muls%?\\t%0, %2, %1"
[(set_attr "conds" "set")
(set_attr "type" "muls")]
)
@@ -1362,7 +1362,7 @@
(const_int 0)))
(clobber (match_scratch:SI 0 "=&r,&r"))]
"TARGET_ARM && !arm_arch6"
- "mul%.\\t%0, %2, %1"
+ "muls%?\\t%0, %2, %1"
[(set_attr "conds" "set")
(set_attr "type" "muls")]
)
@@ -1375,7 +1375,7 @@
(const_int 0)))
(clobber (match_scratch:SI 0 "=r"))]
"TARGET_ARM && arm_arch6 && optimize_size"
- "mul%.\\t%0, %2, %1"
+ "muls%?\\t%0, %2, %1"
[(set_attr "conds" "set")
(set_attr "type" "muls")]
)
@@ -1419,7 +1419,7 @@
(plus:SI (mult:SI (match_dup 2) (match_dup 1))
(match_dup 3)))]
"TARGET_ARM && arm_arch6"
- "mla%.\\t%0, %2, %1, %3"
+ "mlas%?\\t%0, %2, %1, %3"
[(set_attr "conds" "set")
(set_attr "type" "mlas")]
)
@@ -1436,7 +1436,7 @@
(plus:SI (mult:SI (match_dup 2) (match_dup 1))
(match_dup 3)))]
"TARGET_ARM && arm_arch6 && optimize_size"
- "mla%.\\t%0, %2, %1, %3"
+ "mlas%?\\t%0, %2, %1, %3"
[(set_attr "conds" "set")
(set_attr "type" "mlas")]
)
@@ -1451,7 +1451,7 @@
(const_int 0)))
(clobber (match_scratch:SI 0 "=&r,&r,&r,&r"))]
"TARGET_ARM && !arm_arch6"
- "mla%.\\t%0, %2, %1, %3"
+ "mlas%?\\t%0, %2, %1, %3"
[(set_attr "conds" "set")
(set_attr "type" "mlas")]
)
@@ -1466,7 +1466,7 @@
(const_int 0)))
(clobber (match_scratch:SI 0 "=r"))]
"TARGET_ARM && arm_arch6 && optimize_size"
- "mla%.\\t%0, %2, %1, %3"
+ "mlas%?\\t%0, %2, %1, %3"
[(set_attr "conds" "set")
(set_attr "type" "mlas")]
)
@@ -2195,9 +2195,9 @@
(and:SI (match_dup 1) (match_dup 2)))]
"TARGET_32BIT"
"@
- and%.\\t%0, %1, %2
- bic%.\\t%0, %1, #%B2
- and%.\\t%0, %1, %2"
+ ands%?\\t%0, %1, %2
+ bics%?\\t%0, %1, #%B2
+ ands%?\\t%0, %1, %2"
[(set_attr "conds" "set")
(set_attr "type" "logics_imm,logics_imm,logics_reg")]
)
@@ -2212,7 +2212,7 @@
"TARGET_32BIT"
"@
tst%?\\t%0, %1
- bic%.\\t%2, %0, #%B1
+ bics%?\\t%2, %0, #%B1
tst%?\\t%0, %1"
[(set_attr "conds" "set")
(set_attr "type" "logics_imm,logics_imm,logics_reg")]
@@ -2796,7 +2796,7 @@
(const_int 0)))
(clobber (match_scratch:SI 4 "=r"))]
"TARGET_ARM || (TARGET_THUMB2 && CONST_INT_P (operands[2]))"
- "bic%.%?\\t%4, %3, %1%S0"
+ "bics%?\\t%4, %3, %1%S0"
[(set_attr "predicable" "yes")
(set_attr "predicable_short_it" "no")
(set_attr "conds" "set")
@@ -2822,7 +2822,7 @@
(match_dup 2)]))
(match_dup 3)))])]
"TARGET_ARM || (TARGET_THUMB2 && CONST_INT_P (operands[2]))"
- "bic%.%?\\t%4, %3, %1%S0"
+ "bics%?\\t%4, %3, %1%S0"
[(set_attr "predicable" "yes")
(set_attr "predicable_short_it" "no")
(set_attr "conds" "set")
@@ -2841,7 +2841,7 @@
(set (match_operand:SI 0 "s_register_operand" "=r")
(and:SI (not:SI (match_dup 2)) (match_dup 1)))]
"TARGET_32BIT"
- "bic%.\\t%0, %1, %2"
+ "bics\\t%0, %1, %2"
[(set_attr "conds" "set")
(set_attr "type" "logics_shift_reg")]
)
@@ -2854,7 +2854,7 @@
(const_int 0)))
(clobber (match_scratch:SI 0 "=r"))]
"TARGET_32BIT"
- "bic%.\\t%0, %1, %2"
+ "bics\\t%0, %1, %2"
[(set_attr "conds" "set")
(set_attr "type" "logics_shift_reg")]
)
@@ -3023,7 +3023,7 @@
(set (match_operand:SI 0 "s_register_operand" "=r,r")
(ior:SI (match_dup 1) (match_dup 2)))]
"TARGET_32BIT"
- "orr%.\\t%0, %1, %2"
+ "orrs%?\\t%0, %1, %2"
[(set_attr "conds" "set")
(set_attr "type" "logics_imm,logics_reg")]
)
@@ -3035,7 +3035,7 @@
(const_int 0)))
(clobber (match_scratch:SI 0 "=r,r"))]
"TARGET_32BIT"
- "orr%.\\t%0, %1, %2"
+ "orrs%?\\t%0, %1, %2"
[(set_attr "conds" "set")
(set_attr "type" "logics_imm,logics_reg")]
)
@@ -3182,7 +3182,7 @@
(set (match_operand:SI 0 "s_register_operand" "=r,r")
(xor:SI (match_dup 1) (match_dup 2)))]
"TARGET_32BIT"
- "eor%.\\t%0, %1, %2"
+ "eors%?\\t%0, %1, %2"
[(set_attr "conds" "set")
(set_attr "type" "logics_imm,logics_reg")]
)
@@ -3455,44 +3455,6 @@
(set_attr "type" "multiple,multiple")]
)
-;; t = (s/u)min (x, y)
-;; cc = cmp (t, z)
-;; is the same as
-;; cmp x, z
-;; cmpge(u) y, z
-
-(define_insn_and_split "*arm_smin_cmp"
- [(set (reg:CC CC_REGNUM)
- (compare:CC
- (smin:SI (match_operand:SI 0 "s_register_operand" "r")
- (match_operand:SI 1 "s_register_operand" "r"))
- (match_operand:SI 2 "s_register_operand" "r")))]
- "TARGET_32BIT"
- "#"
- "&& reload_completed"
- [(set (reg:CC CC_REGNUM)
- (compare:CC (match_dup 0) (match_dup 2)))
- (cond_exec (ge:CC (reg:CC CC_REGNUM) (const_int 0))
- (set (reg:CC CC_REGNUM)
- (compare:CC (match_dup 1) (match_dup 2))))]
-)
-
-(define_insn_and_split "*arm_umin_cmp"
- [(set (reg:CC CC_REGNUM)
- (compare:CC
- (umin:SI (match_operand:SI 0 "s_register_operand" "r")
- (match_operand:SI 1 "s_register_operand" "r"))
- (match_operand:SI 2 "s_register_operand" "r")))]
- "TARGET_32BIT"
- "#"
- "&& reload_completed"
- [(set (reg:CC CC_REGNUM)
- (compare:CC (match_dup 0) (match_dup 2)))
- (cond_exec (geu:CC (reg:CC CC_REGNUM) (const_int 0))
- (set (reg:CC CC_REGNUM)
- (compare:CC (match_dup 1) (match_dup 2))))]
-)
-
(define_expand "umaxsi3"
[(parallel [
(set (match_operand:SI 0 "s_register_operand" "")
@@ -4066,7 +4028,7 @@
(set (match_operand:SI 0 "s_register_operand" "=r,r")
(not:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])))]
"TARGET_32BIT"
- "mvn%.\\t%0, %1%S3"
+ "mvns%?\\t%0, %1%S3"
[(set_attr "conds" "set")
(set_attr "shift" "1")
(set_attr "arch" "32,a")
@@ -4081,7 +4043,7 @@
(const_int 0)))
(clobber (match_scratch:SI 0 "=r,r"))]
"TARGET_32BIT"
- "mvn%.\\t%0, %1%S3"
+ "mvns%?\\t%0, %1%S3"
[(set_attr "conds" "set")
(set_attr "shift" "1")
(set_attr "arch" "32,a")
@@ -4271,7 +4233,7 @@
(unspec:HI [(match_operand:HI 1 "memory_operand" "Uw,Uh")]
UNSPEC_UNALIGNED_LOAD)))]
"unaligned_access && TARGET_32BIT"
- "ldr%(sh%)\t%0, %1\t@ unaligned"
+ "ldrsh%?\t%0, %1\t@ unaligned"
[(set_attr "arch" "t2,any")
(set_attr "length" "2,4")
(set_attr "predicable" "yes")
@@ -4284,7 +4246,7 @@
(unspec:HI [(match_operand:HI 1 "memory_operand" "Uw,m")]
UNSPEC_UNALIGNED_LOAD)))]
"unaligned_access && TARGET_32BIT"
- "ldr%(h%)\t%0, %1\t@ unaligned"
+ "ldrh%?\t%0, %1\t@ unaligned"
[(set_attr "arch" "t2,any")
(set_attr "length" "2,4")
(set_attr "predicable" "yes")
@@ -4308,7 +4270,7 @@
(unspec:HI [(match_operand:HI 1 "s_register_operand" "l,r")]
UNSPEC_UNALIGNED_STORE))]
"unaligned_access && TARGET_32BIT"
- "str%(h%)\t%1, %0\t@ unaligned"
+ "strh%?\t%1, %0\t@ unaligned"
[(set_attr "arch" "t2,any")
(set_attr "length" "2,4")
(set_attr "predicable" "yes")
@@ -4818,7 +4780,7 @@
(set (match_operand:SI 0 "s_register_operand" "=r")
(not:SI (match_dup 1)))]
"TARGET_32BIT"
- "mvn%.\\t%0, %1"
+ "mvns%?\\t%0, %1"
[(set_attr "conds" "set")
(set_attr "type" "mvn_reg")]
)
@@ -4829,7 +4791,7 @@
(const_int 0)))
(clobber (match_scratch:SI 0 "=r"))]
"TARGET_32BIT"
- "mvn%.\\t%0, %1"
+ "mvns%?\\t%0, %1"
[(set_attr "conds" "set")
(set_attr "type" "mvn_reg")]
)
@@ -5060,7 +5022,7 @@
"TARGET_ARM && arm_arch4 && !arm_arch6"
"@
#
- ldr%(h%)\\t%0, %1"
+ ldrh%?\\t%0, %1"
[(set_attr "type" "alu_shift_reg,load_byte")
(set_attr "predicable" "yes")]
)
@@ -5071,7 +5033,7 @@
"TARGET_ARM && arm_arch6"
"@
uxth%?\\t%0, %1
- ldr%(h%)\\t%0, %1"
+ ldrh%?\\t%0, %1"
[(set_attr "predicable" "yes")
(set_attr "type" "extend,load_byte")]
)
@@ -5130,7 +5092,7 @@
"TARGET_ARM && !arm_arch6"
"@
#
- ldr%(b%)\\t%0, %1\\t%@ zero_extendqisi2"
+ ldrb%?\\t%0, %1\\t%@ zero_extendqisi2"
[(set_attr "length" "8,4")
(set_attr "type" "alu_shift_reg,load_byte")
(set_attr "predicable" "yes")]
@@ -5141,8 +5103,8 @@
(zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,Uh")))]
"TARGET_ARM && arm_arch6"
"@
- uxtb%(%)\\t%0, %1
- ldr%(b%)\\t%0, %1\\t%@ zero_extendqisi2"
+ uxtb%?\\t%0, %1
+ ldrb%?\\t%0, %1\\t%@ zero_extendqisi2"
[(set_attr "type" "extend,load_byte")
(set_attr "predicable" "yes")]
)
@@ -5302,7 +5264,7 @@
"TARGET_ARM && arm_arch4 && !arm_arch6"
"@
#
- ldr%(sh%)\\t%0, %1"
+ ldrsh%?\\t%0, %1"
[(set_attr "length" "8,4")
(set_attr "type" "alu_shift_reg,load_byte")
(set_attr "predicable" "yes")]
@@ -5315,7 +5277,7 @@
"TARGET_32BIT && arm_arch6"
"@
sxth%?\\t%0, %1
- ldr%(sh%)\\t%0, %1"
+ ldrsh%?\\t%0, %1"
[(set_attr "type" "extend,load_byte")
(set_attr "predicable" "yes")
(set_attr "predicable_short_it" "no")]
@@ -5358,7 +5320,7 @@
[(set (match_operand:HI 0 "s_register_operand" "=r")
(sign_extend:HI (match_operand:QI 1 "arm_extendqisi_mem_op" "Uq")))]
"TARGET_ARM && arm_arch4"
- "ldr%(sb%)\\t%0, %1"
+ "ldrsb%?\\t%0, %1"
[(set_attr "type" "load_byte")
(set_attr "predicable" "yes")]
)
@@ -5397,7 +5359,7 @@
"TARGET_ARM && arm_arch4 && !arm_arch6"
"@
#
- ldr%(sb%)\\t%0, %1"
+ ldrsb%?\\t%0, %1"
[(set_attr "length" "8,4")
(set_attr "type" "alu_shift_reg,load_byte")
(set_attr "predicable" "yes")]
@@ -5410,7 +5372,7 @@
"TARGET_ARM && arm_arch6"
"@
sxtb%?\\t%0, %1
- ldr%(sb%)\\t%0, %1"
+ ldrsb%?\\t%0, %1"
[(set_attr "type" "extend,load_byte")
(set_attr "predicable" "yes")]
)
@@ -6065,7 +6027,7 @@
"TARGET_32BIT"
"@
cmp%?\\t%0, #0
- sub%.\\t%0, %1, #0"
+ subs%?\\t%0, %1, #0"
[(set_attr "conds" "set")
(set_attr "type" "alus_imm,alus_imm")]
)
@@ -6441,8 +6403,8 @@
mov%?\\t%0, %1\\t%@ movhi
mvn%?\\t%0, #%B1\\t%@ movhi
movw%?\\t%0, %L1\\t%@ movhi
- str%(h%)\\t%1, %0\\t%@ movhi
- ldr%(h%)\\t%0, %1\\t%@ movhi"
+ strh%?\\t%1, %0\\t%@ movhi
+ ldrh%?\\t%0, %1\\t%@ movhi"
[(set_attr "predicable" "yes")
(set_attr "pool_range" "*,*,*,*,256")
(set_attr "neg_pool_range" "*,*,*,*,244")
@@ -6584,10 +6546,10 @@
mov%?\\t%0, %1
mov%?\\t%0, %1
mvn%?\\t%0, #%B1
- ldr%(b%)\\t%0, %1
- str%(b%)\\t%1, %0
- ldr%(b%)\\t%0, %1
- str%(b%)\\t%1, %0"
+ ldrb%?\\t%0, %1
+ strb%?\\t%1, %0
+ ldrb%?\\t%0, %1
+ strb%?\\t%1, %0"
[(set_attr "type" "mov_reg,mov_reg,mov_imm,mov_imm,mvn_imm,load1,store1,load1,store1")
(set_attr "predicable" "yes")
(set_attr "predicable_short_it" "yes,yes,yes,no,no,no,no,no,no")
@@ -6627,9 +6589,9 @@
switch (which_alternative)
{
case 0: /* ARM register from memory */
- return \"ldr%(h%)\\t%0, %1\\t%@ __fp16\";
+ return \"ldrh%?\\t%0, %1\\t%@ __fp16\";
case 1: /* memory from ARM register */
- return \"str%(h%)\\t%1, %0\\t%@ __fp16\";
+ return \"strh%?\\t%1, %0\\t%@ __fp16\";
case 2: /* ARM register from ARM register */
return \"mov%?\\t%0, %1\\t%@ __fp16\";
case 3: /* ARM register from constant */
@@ -7141,7 +7103,7 @@
(const_int 0)))
(clobber (match_scratch:SI 1 "=r"))]
"TARGET_32BIT"
- "orr%.\\t%1, %Q0, %R0"
+ "orrs%?\\t%1, %Q0, %R0"
[(set_attr "conds" "set")
(set_attr "type" "logics_reg")]
)
@@ -8385,13 +8347,7 @@
(define_insn "nop"
[(const_int 0)]
"TARGET_EITHER"
- "*
- if (TARGET_UNIFIED_ASM)
- return \"nop\";
- if (TARGET_ARM)
- return \"mov%?\\t%|r0, %|r0\\t%@ nop\";
- return \"mov\\tr8, r8\";
- "
+ "nop"
[(set (attr "length")
(if_then_else (eq_attr "is_thumb" "yes")
(const_int 2)
@@ -8479,7 +8435,7 @@
(match_op_dup 1 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
(match_dup 2)]))]
"TARGET_32BIT"
- "%i1%.\\t%0, %2, %4%S3"
+ "%i1s%?\\t%0, %2, %4%S3"
[(set_attr "conds" "set")
(set_attr "shift" "4")
(set_attr "arch" "32,a")
@@ -8496,7 +8452,7 @@
(const_int 0)))
(clobber (match_scratch:SI 0 "=r,r"))]
"TARGET_32BIT"
- "%i1%.\\t%0, %2, %4%S3"
+ "%i1s%?\\t%0, %2, %4%S3"
[(set_attr "conds" "set")
(set_attr "shift" "4")
(set_attr "arch" "32,a")
@@ -8527,7 +8483,7 @@
(minus:SI (match_dup 1)
(match_op_dup 2 [(match_dup 3) (match_dup 4)])))]
"TARGET_32BIT"
- "sub%.\\t%0, %1, %3%S2"
+ "subs%?\\t%0, %1, %3%S2"
[(set_attr "conds" "set")
(set_attr "shift" "3")
(set_attr "arch" "32,a,a")
@@ -8543,7 +8499,7 @@
(const_int 0)))
(clobber (match_scratch:SI 0 "=r,r,r"))]
"TARGET_32BIT"
- "sub%.\\t%0, %1, %3%S2"
+ "subs%?\\t%0, %1, %3%S2"
[(set_attr "conds" "set")
(set_attr "shift" "3")
(set_attr "arch" "32,a,a")
@@ -10247,7 +10203,7 @@
if (val1 == 4 || val2 == 4)
/* Other val must be 8, since we know they are adjacent and neither
is zero. */
- output_asm_insn (\"ldm%(ib%)\\t%0, {%1, %2}\", ldm);
+ output_asm_insn (\"ldmib%?\\t%0, {%1, %2}\", ldm);
else if (const_ok_for_arm (val1) || const_ok_for_arm (-val1))
{
ldm[0] = ops[0] = operands[4];
@@ -10255,9 +10211,9 @@
ops[2] = GEN_INT (val1);
output_add_immediate (ops);
if (val1 < val2)
- output_asm_insn (\"ldm%(ia%)\\t%0, {%1, %2}\", ldm);
+ output_asm_insn (\"ldmia%?\\t%0, {%1, %2}\", ldm);
else
- output_asm_insn (\"ldm%(da%)\\t%0, {%1, %2}\", ldm);
+ output_asm_insn (\"ldmda%?\\t%0, {%1, %2}\", ldm);
}
else
{
@@ -10274,16 +10230,16 @@
else if (val1 != 0)
{
if (val1 < val2)
- output_asm_insn (\"ldm%(da%)\\t%0, {%1, %2}\", ldm);
+ output_asm_insn (\"ldmda%?\\t%0, {%1, %2}\", ldm);
else
- output_asm_insn (\"ldm%(ia%)\\t%0, {%1, %2}\", ldm);
+ output_asm_insn (\"ldmia%?\\t%0, {%1, %2}\", ldm);
}
else
{
if (val1 < val2)
- output_asm_insn (\"ldm%(ia%)\\t%0, {%1, %2}\", ldm);
+ output_asm_insn (\"ldmia%?\\t%0, {%1, %2}\", ldm);
else
- output_asm_insn (\"ldm%(da%)\\t%0, {%1, %2}\", ldm);
+ output_asm_insn (\"ldmda%?\\t%0, {%1, %2}\", ldm);
}
output_asm_insn (\"%I3%?\\t%0, %1, %2\", arith);
return \"\";
@@ -10619,9 +10575,7 @@
int i;
char pattern[100];
- if (TARGET_ARM)
- strcpy (pattern, \"stm%(fd%)\\t%m0!, {%1\");
- else if (TARGET_THUMB2)
+ if (TARGET_32BIT)
strcpy (pattern, \"push%?\\t{%1\");
else
strcpy (pattern, \"push\\t{%1\");
diff --git a/gcc/config/arm/arm.opt b/gcc/config/arm/arm.opt
index 666ff732264..c12f2b13a03 100644
--- a/gcc/config/arm/arm.opt
+++ b/gcc/config/arm/arm.opt
@@ -280,4 +280,4 @@ Assume loading data from flash is slower than fetching instructions.
masm-syntax-unified
Target Report Var(inline_asm_unified) Init(0) Save
-Assume unified syntax for Thumb inline assembly code.
+Assume unified syntax for inline assembly code.
diff --git a/gcc/config/arm/ldmstm.md b/gcc/config/arm/ldmstm.md
index 20d6b4c364a..ebb09ab86e7 100644
--- a/gcc/config/arm/ldmstm.md
+++ b/gcc/config/arm/ldmstm.md
@@ -21,7 +21,7 @@
see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
<http://www.gnu.org/licenses/>. */
-(define_insn "*ldm4_ia"
+(define_insn "*ldm4_"
[(match_parallel 0 "load_multiple_operation"
[(set (match_operand:SI 1 "arm_hard_general_register_operand" "")
(mem:SI (match_operand:SI 5 "s_register_operand" "rk")))
@@ -35,7 +35,7 @@
(mem:SI (plus:SI (match_dup 5)
(const_int 12))))])]
"TARGET_32BIT && XVECLEN (operands[0], 0) == 4"
- "ldm%(ia%)\t%5, {%1, %2, %3, %4}"
+ "ldm%?\t%5, {%1, %2, %3, %4}"
[(set_attr "type" "load4")
(set_attr "predicable" "yes")
(set_attr "predicable_short_it" "no")])
@@ -54,7 +54,7 @@
(mem:SI (plus:SI (match_dup 5)
(const_int 12))))])]
"TARGET_THUMB1 && XVECLEN (operands[0], 0) == 4"
- "ldm%(ia%)\t%5, {%1, %2, %3, %4}"
+ "ldmia\t%5, {%1, %2, %3, %4}"
[(set_attr "type" "load4")])
(define_insn "*ldm4_ia_update"
@@ -73,7 +73,7 @@
(mem:SI (plus:SI (match_dup 5)
(const_int 12))))])]
"TARGET_32BIT && XVECLEN (operands[0], 0) == 5"
- "ldm%(ia%)\t%5!, {%1, %2, %3, %4}"
+ "ldmia%?\t%5!, {%1, %2, %3, %4}"
[(set_attr "type" "load4")
(set_attr "predicable" "yes")
(set_attr "predicable_short_it" "no")])
@@ -94,10 +94,10 @@
(mem:SI (plus:SI (match_dup 5)
(const_int 12))))])]
"TARGET_THUMB1 && XVECLEN (operands[0], 0) == 5"
- "ldm%(ia%)\t%5!, {%1, %2, %3, %4}"
+ "ldmia\t%5!, {%1, %2, %3, %4}"
[(set_attr "type" "load4")])
-(define_insn "*stm4_ia"
+(define_insn "*stm4_"
[(match_parallel 0 "store_multiple_operation"
[(set (mem:SI (match_operand:SI 5 "s_register_operand" "rk"))
(match_operand:SI 1 "arm_hard_general_register_operand" ""))
@@ -108,7 +108,7 @@
(set (mem:SI (plus:SI (match_dup 5) (const_int 12)))
(match_operand:SI 4 "arm_hard_general_register_operand" ""))])]
"TARGET_32BIT && XVECLEN (operands[0], 0) == 4"
- "stm%(ia%)\t%5, {%1, %2, %3, %4}"
+ "stm%?\t%5, {%1, %2, %3, %4}"
[(set_attr "type" "store4")
(set_attr "predicable" "yes")
(set_attr "predicable_short_it" "no")])
@@ -126,7 +126,7 @@
(set (mem:SI (plus:SI (match_dup 5) (const_int 12)))
(match_operand:SI 4 "arm_hard_general_register_operand" ""))])]
"TARGET_32BIT && XVECLEN (operands[0], 0) == 5"
- "stm%(ia%)\t%5!, {%1, %2, %3, %4}"
+ "stmia%?\t%5!, {%1, %2, %3, %4}"
[(set_attr "type" "store4")
(set_attr "predicable" "yes")
(set_attr "predicable_short_it" "no")])
@@ -144,7 +144,7 @@
(set (mem:SI (plus:SI (match_dup 5) (const_int 12)))
(match_operand:SI 4 "low_register_operand" ""))])]
"TARGET_THUMB1 && XVECLEN (operands[0], 0) == 5"
- "stm%(ia%)\t%5!, {%1, %2, %3, %4}"
+ "stmia\t%5!, {%1, %2, %3, %4}"
[(set_attr "type" "store4")])
(define_insn "*ldm4_ib"
@@ -162,7 +162,7 @@
(mem:SI (plus:SI (match_dup 5)
(const_int 16))))])]
"TARGET_ARM && XVECLEN (operands[0], 0) == 4"
- "ldm%(ib%)\t%5, {%1, %2, %3, %4}"
+ "ldmib%?\t%5, {%1, %2, %3, %4}"
[(set_attr "type" "load4")
(set_attr "predicable" "yes")])
@@ -183,7 +183,7 @@
(mem:SI (plus:SI (match_dup 5)
(const_int 16))))])]
"TARGET_ARM && XVECLEN (operands[0], 0) == 5"
- "ldm%(ib%)\t%5!, {%1, %2, %3, %4}"
+ "ldmib%?\t%5!, {%1, %2, %3, %4}"
[(set_attr "type" "load4")
(set_attr "predicable" "yes")])
@@ -198,7 +198,7 @@
(set (mem:SI (plus:SI (match_dup 5) (const_int 16)))
(match_operand:SI 4 "arm_hard_general_register_operand" ""))])]
"TARGET_ARM && XVECLEN (operands[0], 0) == 4"
- "stm%(ib%)\t%5, {%1, %2, %3, %4}"
+ "stmib%?\t%5, {%1, %2, %3, %4}"
[(set_attr "type" "store4")
(set_attr "predicable" "yes")])
@@ -215,7 +215,7 @@
(set (mem:SI (plus:SI (match_dup 5) (const_int 16)))
(match_operand:SI 4 "arm_hard_general_register_operand" ""))])]
"TARGET_ARM && XVECLEN (operands[0], 0) == 5"
- "stm%(ib%)\t%5!, {%1, %2, %3, %4}"
+ "stmib%?\t%5!, {%1, %2, %3, %4}"
[(set_attr "type" "store4")
(set_attr "predicable" "yes")])
@@ -233,7 +233,7 @@
(set (match_operand:SI 4 "arm_hard_general_register_operand" "")
(mem:SI (match_dup 5)))])]
"TARGET_ARM && XVECLEN (operands[0], 0) == 4"
- "ldm%(da%)\t%5, {%1, %2, %3, %4}"
+ "ldmda%?\t%5, {%1, %2, %3, %4}"
[(set_attr "type" "load4")
(set_attr "predicable" "yes")])
@@ -253,7 +253,7 @@
(set (match_operand:SI 4 "arm_hard_general_register_operand" "")
(mem:SI (match_dup 5)))])]
"TARGET_ARM && XVECLEN (operands[0], 0) == 5"
- "ldm%(da%)\t%5!, {%1, %2, %3, %4}"
+ "ldmda%?\t%5!, {%1, %2, %3, %4}"
[(set_attr "type" "load4")
(set_attr "predicable" "yes")])
@@ -268,7 +268,7 @@
(set (mem:SI (match_dup 5))
(match_operand:SI 4 "arm_hard_general_register_operand" ""))])]
"TARGET_ARM && XVECLEN (operands[0], 0) == 4"
- "stm%(da%)\t%5, {%1, %2, %3, %4}"
+ "stmda%?\t%5, {%1, %2, %3, %4}"
[(set_attr "type" "store4")
(set_attr "predicable" "yes")])
@@ -285,7 +285,7 @@
(set (mem:SI (match_dup 5))
(match_operand:SI 4 "arm_hard_general_register_operand" ""))])]
"TARGET_ARM && XVECLEN (operands[0], 0) == 5"
- "stm%(da%)\t%5!, {%1, %2, %3, %4}"
+ "stmda%?\t%5!, {%1, %2, %3, %4}"
[(set_attr "type" "store4")
(set_attr "predicable" "yes")])
@@ -304,7 +304,7 @@
(mem:SI (plus:SI (match_dup 5)
(const_int -4))))])]
"TARGET_32BIT && XVECLEN (operands[0], 0) == 4"
- "ldm%(db%)\t%5, {%1, %2, %3, %4}"
+ "ldmdb%?\t%5, {%1, %2, %3, %4}"
[(set_attr "type" "load4")
(set_attr "predicable" "yes")
(set_attr "predicable_short_it" "no")])
@@ -326,7 +326,7 @@
(mem:SI (plus:SI (match_dup 5)
(const_int -4))))])]
"TARGET_32BIT && XVECLEN (operands[0], 0) == 5"
- "ldm%(db%)\t%5!, {%1, %2, %3, %4}"
+ "ldmdb%?\t%5!, {%1, %2, %3, %4}"
[(set_attr "type" "load4")
(set_attr "predicable" "yes")
(set_attr "predicable_short_it" "no")])
@@ -342,7 +342,7 @@
(set (mem:SI (plus:SI (match_dup 5) (const_int -4)))
(match_operand:SI 4 "arm_hard_general_register_operand" ""))])]
"TARGET_32BIT && XVECLEN (operands[0], 0) == 4"
- "stm%(db%)\t%5, {%1, %2, %3, %4}"
+ "stmdb%?\t%5, {%1, %2, %3, %4}"
[(set_attr "type" "store4")
(set_attr "predicable" "yes")
(set_attr "predicable_short_it" "no")])
@@ -360,7 +360,7 @@
(set (mem:SI (plus:SI (match_dup 5) (const_int -4)))
(match_operand:SI 4 "arm_hard_general_register_operand" ""))])]
"TARGET_32BIT && XVECLEN (operands[0], 0) == 5"
- "stm%(db%)\t%5!, {%1, %2, %3, %4}"
+ "stmdb%?\t%5!, {%1, %2, %3, %4}"
[(set_attr "type" "store4")
(set_attr "predicable" "yes")
(set_attr "predicable_short_it" "no")])
@@ -472,7 +472,7 @@
FAIL;
})
-(define_insn "*ldm3_ia"
+(define_insn "*ldm3_"
[(match_parallel 0 "load_multiple_operation"
[(set (match_operand:SI 1 "arm_hard_general_register_operand" "")
(mem:SI (match_operand:SI 4 "s_register_operand" "rk")))
@@ -483,7 +483,7 @@
(mem:SI (plus:SI (match_dup 4)
(const_int 8))))])]
"TARGET_32BIT && XVECLEN (operands[0], 0) == 3"
- "ldm%(ia%)\t%4, {%1, %2, %3}"
+ "ldm%?\t%4, {%1, %2, %3}"
[(set_attr "type" "load3")
(set_attr "predicable" "yes")
(set_attr "predicable_short_it" "no")])
@@ -499,7 +499,7 @@
(mem:SI (plus:SI (match_dup 4)
(const_int 8))))])]
"TARGET_THUMB1 && XVECLEN (operands[0], 0) == 3"
- "ldm%(ia%)\t%4, {%1, %2, %3}"
+ "ldmia\t%4, {%1, %2, %3}"
[(set_attr "type" "load3")])
(define_insn "*ldm3_ia_update"
@@ -515,7 +515,7 @@
(mem:SI (plus:SI (match_dup 4)
(const_int 8))))])]
"TARGET_32BIT && XVECLEN (operands[0], 0) == 4"
- "ldm%(ia%)\t%4!, {%1, %2, %3}"
+ "ldmia%?\t%4!, {%1, %2, %3}"
[(set_attr "type" "load3")
(set_attr "predicable" "yes")
(set_attr "predicable_short_it" "no")])
@@ -533,10 +533,10 @@
(mem:SI (plus:SI (match_dup 4)
(const_int 8))))])]
"TARGET_THUMB1 && XVECLEN (operands[0], 0) == 4"
- "ldm%(ia%)\t%4!, {%1, %2, %3}"
+ "ldmia\t%4!, {%1, %2, %3}"
[(set_attr "type" "load3")])
-(define_insn "*stm3_ia"
+(define_insn "*stm3_"
[(match_parallel 0 "store_multiple_operation"
[(set (mem:SI (match_operand:SI 4 "s_register_operand" "rk"))
(match_operand:SI 1 "arm_hard_general_register_operand" ""))
@@ -545,7 +545,7 @@
(set (mem:SI (plus:SI (match_dup 4) (const_int 8)))
(match_operand:SI 3 "arm_hard_general_register_operand" ""))])]
"TARGET_32BIT && XVECLEN (operands[0], 0) == 3"
- "stm%(ia%)\t%4, {%1, %2, %3}"
+ "stm%?\t%4, {%1, %2, %3}"
[(set_attr "type" "store3")
(set_attr "predicable" "yes")
(set_attr "predicable_short_it" "no")])
@@ -561,7 +561,7 @@
(set (mem:SI (plus:SI (match_dup 4) (const_int 8)))
(match_operand:SI 3 "arm_hard_general_register_operand" ""))])]
"TARGET_32BIT && XVECLEN (operands[0], 0) == 4"
- "stm%(ia%)\t%4!, {%1, %2, %3}"
+ "stmia%?\t%4!, {%1, %2, %3}"
[(set_attr "type" "store3")
(set_attr "predicable" "yes")
(set_attr "predicable_short_it" "no")])
@@ -577,7 +577,7 @@
(set (mem:SI (plus:SI (match_dup 4) (const_int 8)))
(match_operand:SI 3 "low_register_operand" ""))])]
"TARGET_THUMB1 && XVECLEN (operands[0], 0) == 4"
- "stm%(ia%)\t%4!, {%1, %2, %3}"
+ "stmia\t%4!, {%1, %2, %3}"
[(set_attr "type" "store3")])
(define_insn "*ldm3_ib"
@@ -592,7 +592,7 @@
(mem:SI (plus:SI (match_dup 4)
(const_int 12))))])]
"TARGET_ARM && XVECLEN (operands[0], 0) == 3"
- "ldm%(ib%)\t%4, {%1, %2, %3}"
+ "ldmib%?\t%4, {%1, %2, %3}"
[(set_attr "type" "load3")
(set_attr "predicable" "yes")])
@@ -610,7 +610,7 @@
(mem:SI (plus:SI (match_dup 4)
(const_int 12))))])]
"TARGET_ARM && XVECLEN (operands[0], 0) == 4"
- "ldm%(ib%)\t%4!, {%1, %2, %3}"
+ "ldmib%?\t%4!, {%1, %2, %3}"
[(set_attr "type" "load3")
(set_attr "predicable" "yes")])
@@ -623,7 +623,7 @@
(set (mem:SI (plus:SI (match_dup 4) (const_int 12)))
(match_operand:SI 3 "arm_hard_general_register_operand" ""))])]
"TARGET_ARM && XVECLEN (operands[0], 0) == 3"
- "stm%(ib%)\t%4, {%1, %2, %3}"
+ "stmib%?\t%4, {%1, %2, %3}"
[(set_attr "type" "store3")
(set_attr "predicable" "yes")])
@@ -638,7 +638,7 @@
(set (mem:SI (plus:SI (match_dup 4) (const_int 12)))
(match_operand:SI 3 "arm_hard_general_register_operand" ""))])]
"TARGET_ARM && XVECLEN (operands[0], 0) == 4"
- "stm%(ib%)\t%4!, {%1, %2, %3}"
+ "stmib%?\t%4!, {%1, %2, %3}"
[(set_attr "type" "store3")
(set_attr "predicable" "yes")])
@@ -653,7 +653,7 @@
(set (match_operand:SI 3 "arm_hard_general_register_operand" "")
(mem:SI (match_dup 4)))])]
"TARGET_ARM && XVECLEN (operands[0], 0) == 3"
- "ldm%(da%)\t%4, {%1, %2, %3}"
+ "ldmda%?\t%4, {%1, %2, %3}"
[(set_attr "type" "load3")
(set_attr "predicable" "yes")])
@@ -670,7 +670,7 @@
(set (match_operand:SI 3 "arm_hard_general_register_operand" "")
(mem:SI (match_dup 4)))])]
"TARGET_ARM && XVECLEN (operands[0], 0) == 4"
- "ldm%(da%)\t%4!, {%1, %2, %3}"
+ "ldmda%?\t%4!, {%1, %2, %3}"
[(set_attr "type" "load3")
(set_attr "predicable" "yes")])
@@ -683,7 +683,7 @@
(set (mem:SI (match_dup 4))
(match_operand:SI 3 "arm_hard_general_register_operand" ""))])]
"TARGET_ARM && XVECLEN (operands[0], 0) == 3"
- "stm%(da%)\t%4, {%1, %2, %3}"
+ "stmda%?\t%4, {%1, %2, %3}"
[(set_attr "type" "store3")
(set_attr "predicable" "yes")])
@@ -698,7 +698,7 @@
(set (mem:SI (match_dup 4))
(match_operand:SI 3 "arm_hard_general_register_operand" ""))])]
"TARGET_ARM && XVECLEN (operands[0], 0) == 4"
- "stm%(da%)\t%4!, {%1, %2, %3}"
+ "stmda%?\t%4!, {%1, %2, %3}"
[(set_attr "type" "store3")
(set_attr "predicable" "yes")])
@@ -714,7 +714,7 @@
(mem:SI (plus:SI (match_dup 4)
(const_int -4))))])]
"TARGET_32BIT && XVECLEN (operands[0], 0) == 3"
- "ldm%(db%)\t%4, {%1, %2, %3}"
+ "ldmdb%?\t%4, {%1, %2, %3}"
[(set_attr "type" "load3")
(set_attr "predicable" "yes")
(set_attr "predicable_short_it" "no")])
@@ -733,7 +733,7 @@
(mem:SI (plus:SI (match_dup 4)
(const_int -4))))])]
"TARGET_32BIT && XVECLEN (operands[0], 0) == 4"
- "ldm%(db%)\t%4!, {%1, %2, %3}"
+ "ldmdb%?\t%4!, {%1, %2, %3}"
[(set_attr "type" "load3")
(set_attr "predicable" "yes")
(set_attr "predicable_short_it" "no")])
@@ -747,7 +747,7 @@
(set (mem:SI (plus:SI (match_dup 4) (const_int -4)))
(match_operand:SI 3 "arm_hard_general_register_operand" ""))])]
"TARGET_32BIT && XVECLEN (operands[0], 0) == 3"
- "stm%(db%)\t%4, {%1, %2, %3}"
+ "stmdb%?\t%4, {%1, %2, %3}"
[(set_attr "type" "store3")
(set_attr "predicable" "yes")
(set_attr "predicable_short_it" "no")])
@@ -763,7 +763,7 @@
(set (mem:SI (plus:SI (match_dup 4) (const_int -4)))
(match_operand:SI 3 "arm_hard_general_register_operand" ""))])]
"TARGET_32BIT && XVECLEN (operands[0], 0) == 4"
- "stm%(db%)\t%4!, {%1, %2, %3}"
+ "stmdb%?\t%4!, {%1, %2, %3}"
[(set_attr "type" "store3")
(set_attr "predicable" "yes")
(set_attr "predicable_short_it" "no")])
@@ -861,7 +861,7 @@
FAIL;
})
-(define_insn "*ldm2_ia"
+(define_insn "*ldm2_"
[(match_parallel 0 "load_multiple_operation"
[(set (match_operand:SI 1 "arm_hard_general_register_operand" "")
(mem:SI (match_operand:SI 3 "s_register_operand" "rk")))
@@ -869,7 +869,7 @@
(mem:SI (plus:SI (match_dup 3)
(const_int 4))))])]
"TARGET_32BIT && XVECLEN (operands[0], 0) == 2"
- "ldm%(ia%)\t%3, {%1, %2}"
+ "ldm%?\t%3, {%1, %2}"
[(set_attr "type" "load2")
(set_attr "predicable" "yes")
(set_attr "predicable_short_it" "no")])
@@ -882,7 +882,7 @@
(mem:SI (plus:SI (match_dup 3)
(const_int 4))))])]
"TARGET_THUMB1 && XVECLEN (operands[0], 0) == 2"
- "ldm%(ia%)\t%3, {%1, %2}"
+ "ldmia\t%3, {%1, %2}"
[(set_attr "type" "load2")])
(define_insn "*ldm2_ia_update"
@@ -895,7 +895,7 @@
(mem:SI (plus:SI (match_dup 3)
(const_int 4))))])]
"TARGET_32BIT && XVECLEN (operands[0], 0) == 3"
- "ldm%(ia%)\t%3!, {%1, %2}"
+ "ldmia%?\t%3!, {%1, %2}"
[(set_attr "type" "load2")
(set_attr "predicable" "yes")
(set_attr "predicable_short_it" "no")])
@@ -910,17 +910,17 @@
(mem:SI (plus:SI (match_dup 3)
(const_int 4))))])]
"TARGET_THUMB1 && XVECLEN (operands[0], 0) == 3"
- "ldm%(ia%)\t%3!, {%1, %2}"
+ "ldmia\t%3!, {%1, %2}"
[(set_attr "type" "load2")])
-(define_insn "*stm2_ia"
+(define_insn "*stm2_"
[(match_parallel 0 "store_multiple_operation"
[(set (mem:SI (match_operand:SI 3 "s_register_operand" "rk"))
(match_operand:SI 1 "arm_hard_general_register_operand" ""))
(set (mem:SI (plus:SI (match_dup 3) (const_int 4)))
(match_operand:SI 2 "arm_hard_general_register_operand" ""))])]
"TARGET_32BIT && XVECLEN (operands[0], 0) == 2"
- "stm%(ia%)\t%3, {%1, %2}"
+ "stm%?\t%3, {%1, %2}"
[(set_attr "type" "store2")
(set_attr "predicable" "yes")
(set_attr "predicable_short_it" "no")])
@@ -934,7 +934,7 @@
(set (mem:SI (plus:SI (match_dup 3) (const_int 4)))
(match_operand:SI 2 "arm_hard_general_register_operand" ""))])]
"TARGET_32BIT && XVECLEN (operands[0], 0) == 3"
- "stm%(ia%)\t%3!, {%1, %2}"
+ "stmia%?\t%3!, {%1, %2}"
[(set_attr "type" "store2")
(set_attr "predicable" "yes")
(set_attr "predicable_short_it" "no")])
@@ -948,7 +948,7 @@
(set (mem:SI (plus:SI (match_dup 3) (const_int 4)))
(match_operand:SI 2 "low_register_operand" ""))])]
"TARGET_THUMB1 && XVECLEN (operands[0], 0) == 3"
- "stm%(ia%)\t%3!, {%1, %2}"
+ "stmia\t%3!, {%1, %2}"
[(set_attr "type" "store2")])
(define_insn "*ldm2_ib"
@@ -960,7 +960,7 @@
(mem:SI (plus:SI (match_dup 3)
(const_int 8))))])]
"TARGET_ARM && XVECLEN (operands[0], 0) == 2"
- "ldm%(ib%)\t%3, {%1, %2}"
+ "ldmib%?\t%3, {%1, %2}"
[(set_attr "type" "load2")
(set_attr "predicable" "yes")])
@@ -975,7 +975,7 @@
(mem:SI (plus:SI (match_dup 3)
(const_int 8))))])]
"TARGET_ARM && XVECLEN (operands[0], 0) == 3"
- "ldm%(ib%)\t%3!, {%1, %2}"
+ "ldmib%?\t%3!, {%1, %2}"
[(set_attr "type" "load2")
(set_attr "predicable" "yes")])
@@ -986,7 +986,7 @@
(set (mem:SI (plus:SI (match_dup 3) (const_int 8)))
(match_operand:SI 2 "arm_hard_general_register_operand" ""))])]
"TARGET_ARM && XVECLEN (operands[0], 0) == 2"
- "stm%(ib%)\t%3, {%1, %2}"
+ "stmib%?\t%3, {%1, %2}"
[(set_attr "type" "store2")
(set_attr "predicable" "yes")])
@@ -999,7 +999,7 @@
(set (mem:SI (plus:SI (match_dup 3) (const_int 8)))
(match_operand:SI 2 "arm_hard_general_register_operand" ""))])]
"TARGET_ARM && XVECLEN (operands[0], 0) == 3"
- "stm%(ib%)\t%3!, {%1, %2}"
+ "stmib%?\t%3!, {%1, %2}"
[(set_attr "type" "store2")
(set_attr "predicable" "yes")])
@@ -1011,7 +1011,7 @@
(set (match_operand:SI 2 "arm_hard_general_register_operand" "")
(mem:SI (match_dup 3)))])]
"TARGET_ARM && XVECLEN (operands[0], 0) == 2"
- "ldm%(da%)\t%3, {%1, %2}"
+ "ldmda%?\t%3, {%1, %2}"
[(set_attr "type" "load2")
(set_attr "predicable" "yes")])
@@ -1025,7 +1025,7 @@
(set (match_operand:SI 2 "arm_hard_general_register_operand" "")
(mem:SI (match_dup 3)))])]
"TARGET_ARM && XVECLEN (operands[0], 0) == 3"
- "ldm%(da%)\t%3!, {%1, %2}"
+ "ldmda%?\t%3!, {%1, %2}"
[(set_attr "type" "load2")
(set_attr "predicable" "yes")])
@@ -1036,7 +1036,7 @@
(set (mem:SI (match_dup 3))
(match_operand:SI 2 "arm_hard_general_register_operand" ""))])]
"TARGET_ARM && XVECLEN (operands[0], 0) == 2"
- "stm%(da%)\t%3, {%1, %2}"
+ "stmda%?\t%3, {%1, %2}"
[(set_attr "type" "store2")
(set_attr "predicable" "yes")])
@@ -1049,7 +1049,7 @@
(set (mem:SI (match_dup 3))
(match_operand:SI 2 "arm_hard_general_register_operand" ""))])]
"TARGET_ARM && XVECLEN (operands[0], 0) == 3"
- "stm%(da%)\t%3!, {%1, %2}"
+ "stmda%?\t%3!, {%1, %2}"
[(set_attr "type" "store2")
(set_attr "predicable" "yes")])
@@ -1062,7 +1062,7 @@
(mem:SI (plus:SI (match_dup 3)
(const_int -4))))])]
"TARGET_32BIT && XVECLEN (operands[0], 0) == 2"
- "ldm%(db%)\t%3, {%1, %2}"
+ "ldmdb%?\t%3, {%1, %2}"
[(set_attr "type" "load2")
(set_attr "predicable" "yes")
(set_attr "predicable_short_it" "no")])
@@ -1078,7 +1078,7 @@
(mem:SI (plus:SI (match_dup 3)
(const_int -4))))])]
"TARGET_32BIT && XVECLEN (operands[0], 0) == 3"
- "ldm%(db%)\t%3!, {%1, %2}"
+ "ldmdb%?\t%3!, {%1, %2}"
[(set_attr "type" "load2")
(set_attr "predicable" "yes")
(set_attr "predicable_short_it" "no")])
@@ -1090,7 +1090,7 @@
(set (mem:SI (plus:SI (match_dup 3) (const_int -4)))
(match_operand:SI 2 "arm_hard_general_register_operand" ""))])]
"TARGET_32BIT && XVECLEN (operands[0], 0) == 2"
- "stm%(db%)\t%3, {%1, %2}"
+ "stmdb%?\t%3, {%1, %2}"
[(set_attr "type" "store2")
(set_attr "predicable" "yes")
(set_attr "predicable_short_it" "no")])
@@ -1104,7 +1104,7 @@
(set (mem:SI (plus:SI (match_dup 3) (const_int -4)))
(match_operand:SI 2 "arm_hard_general_register_operand" ""))])]
"TARGET_32BIT && XVECLEN (operands[0], 0) == 3"
- "stm%(db%)\t%3!, {%1, %2}"
+ "stmdb%?\t%3!, {%1, %2}"
[(set_attr "type" "store2")
(set_attr "predicable" "yes")
(set_attr "predicable_short_it" "no")])
diff --git a/gcc/config/arm/sync.md b/gcc/config/arm/sync.md
index 9ee715cd6de..fc7836fea7c 100644
--- a/gcc/config/arm/sync.md
+++ b/gcc/config/arm/sync.md
@@ -72,7 +72,7 @@
{
enum memmodel model = memmodel_from_int (INTVAL (operands[2]));
if (is_mm_relaxed (model) || is_mm_consume (model) || is_mm_release (model))
- return \"ldr%(<sync_sfx>%)\\t%0, %1\";
+ return \"ldr<sync_sfx>%?\\t%0, %1\";
else
return \"lda<sync_sfx>%?\\t%0, %1\";
}
@@ -89,7 +89,7 @@
{
enum memmodel model = memmodel_from_int (INTVAL (operands[2]));
if (is_mm_relaxed (model) || is_mm_consume (model) || is_mm_acquire (model))
- return \"str%(<sync_sfx>%)\t%1, %0\";
+ return \"str<sync_sfx>%?\t%1, %0\";
else
return \"stl<sync_sfx>%?\t%1, %0\";
}
diff --git a/gcc/config/arm/thumb2.md b/gcc/config/arm/thumb2.md
index 8c754d90d58..a724752a39c 100644
--- a/gcc/config/arm/thumb2.md
+++ b/gcc/config/arm/thumb2.md
@@ -330,8 +330,8 @@
mov%?\\t%0, %1\\t%@ movhi
mov%?\\t%0, %1\\t%@ movhi
movw%?\\t%0, %L1\\t%@ movhi
- str%(h%)\\t%1, %0\\t%@ movhi
- ldr%(h%)\\t%0, %1\\t%@ movhi"
+ strh%?\\t%1, %0\\t%@ movhi
+ ldrh%?\\t%0, %1\\t%@ movhi"
[(set_attr "type" "mov_reg,mov_imm,mov_imm,mov_imm,store1,load1")
(set_attr "predicable" "yes")
(set_attr "predicable_short_it" "yes,no,yes,no,no,no")
@@ -1028,7 +1028,7 @@
"TARGET_THUMB2 && arm_arch6"
"@
sxtb%?\\t%0, %1
- ldr%(sb%)\\t%0, %1"
+ ldrsb%?\\t%0, %1"
[(set_attr "type" "extend,load_byte")
(set_attr "predicable" "yes")
(set_attr "predicable_short_it" "no")
@@ -1042,7 +1042,7 @@
"TARGET_THUMB2 && arm_arch6"
"@
uxth%?\\t%0, %1
- ldr%(h%)\\t%0, %1"
+ ldrh%?\\t%0, %1"
[(set_attr "type" "extend,load_byte")
(set_attr "predicable" "yes")
(set_attr "predicable_short_it" "no")
@@ -1055,8 +1055,8 @@
(zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
"TARGET_THUMB2 && arm_arch6"
"@
- uxtb%(%)\\t%0, %1
- ldr%(b%)\\t%0, %1\\t%@ zero_extendqisi2"
+ uxtb%?\\t%0, %1
+ ldrb%?\\t%0, %1\\t%@ zero_extendqisi2"
[(set_attr "type" "extend,load_byte")
(set_attr "predicable" "yes")
(set_attr "predicable_short_it" "no")
diff --git a/gcc/config/i386/i386-c.c b/gcc/config/i386/i386-c.c
index a3c0342950d..e3a301205e6 100644
--- a/gcc/config/i386/i386-c.c
+++ b/gcc/config/i386/i386-c.c
@@ -586,6 +586,10 @@ ix86_target_macros (void)
ix86_tune,
ix86_fpmath,
cpp_define);
+
+ cpp_define (parse_in, "__SEG_FS");
+ cpp_define (parse_in, "__SEG_GS");
+ cpp_define (parse_in, "__SEG_TLS");
}
@@ -600,6 +604,10 @@ ix86_register_pragmas (void)
/* Update pragma hook to allow parsing #pragma GCC target. */
targetm.target_option.pragma_parse = ix86_pragma_target_parse;
+ c_register_addr_space ("__seg_fs", ADDR_SPACE_SEG_FS);
+ c_register_addr_space ("__seg_gs", ADDR_SPACE_SEG_GS);
+ c_register_addr_space ("__seg_tls", ADDR_SPACE_SEG_TLS);
+
#ifdef REGISTER_SUBTARGET_PRAGMAS
REGISTER_SUBTARGET_PRAGMAS ();
#endif
diff --git a/gcc/config/i386/i386-protos.h b/gcc/config/i386/i386-protos.h
index 6a17ef40a2e..026b778f4e3 100644
--- a/gcc/config/i386/i386-protos.h
+++ b/gcc/config/i386/i386-protos.h
@@ -141,6 +141,7 @@ extern void ix86_split_ashr (rtx *, rtx, machine_mode);
extern void ix86_split_lshr (rtx *, rtx, machine_mode);
extern rtx ix86_find_base_term (rtx);
extern bool ix86_check_movabs (rtx, int);
+extern bool ix86_check_no_addr_space (rtx);
extern void ix86_split_idivmod (machine_mode, rtx[], bool);
extern rtx assign_386_stack_local (machine_mode, enum ix86_stack_slot);
@@ -278,12 +279,11 @@ extern rtx maybe_get_pool_constant (rtx);
extern char internal_label_prefix[16];
extern int internal_label_prefix_len;
-enum ix86_address_seg { SEG_DEFAULT, SEG_FS, SEG_GS };
struct ix86_address
{
rtx base, index, disp;
HOST_WIDE_INT scale;
- enum ix86_address_seg seg;
+ addr_space_t seg;
};
extern int ix86_decompose_address (rtx, struct ix86_address *);
@@ -325,3 +325,7 @@ struct ix86_first_cycle_multipass_data_
# define TARGET_SCHED_FIRST_CYCLE_MULTIPASS_DATA_T \
struct ix86_first_cycle_multipass_data_
#endif /* RTX_CODE */
+
+const addr_space_t ADDR_SPACE_SEG_FS = 1;
+const addr_space_t ADDR_SPACE_SEG_GS = 2;
+const addr_space_t ADDR_SPACE_SEG_TLS = 3;
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index 2a965f678a0..0d84cde9cbe 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -64,6 +64,7 @@ along with GCC; see the file COPYING3. If not see
#include "context.h"
#include "pass_manager.h"
#include "target-globals.h"
+#include "gimple-iterator.h"
#include "tree-vectorizer.h"
#include "shrink-wrap.h"
#include "builtins.h"
@@ -79,6 +80,7 @@ along with GCC; see the file COPYING3. If not see
static rtx legitimize_dllimport_symbol (rtx, bool);
static rtx legitimize_pe_coff_extern_decl (rtx, bool);
static rtx legitimize_pe_coff_symbol (rtx, bool);
+static void ix86_print_operand_address_as (FILE *file, rtx addr, addr_space_t);
#ifndef CHECK_STACK_LIMIT
#define CHECK_STACK_LIMIT (-1)
@@ -10537,6 +10539,20 @@ ix86_check_movabs (rtx insn, int opnum)
gcc_assert (MEM_P (mem));
return volatile_ok || !MEM_VOLATILE_P (mem);
}
+
+/* Return false if INSN contains a MEM with a non-default address space. */
+bool
+ix86_check_no_addr_space (rtx insn)
+{
+ subrtx_var_iterator::array_type array;
+ FOR_EACH_SUBRTX_VAR (iter, array, PATTERN (insn), ALL)
+ {
+ rtx x = *iter;
+ if (MEM_P (x) && !ADDR_SPACE_GENERIC_P (MEM_ADDR_SPACE (x)))
+ return false;
+ }
+ return true;
+}
/* Initialize the table of extra 80387 mathematical constants. */
@@ -13973,7 +13989,7 @@ ix86_decompose_address (rtx addr, struct ix86_address *out)
rtx scale_rtx = NULL_RTX;
rtx tmp;
int retval = 1;
- enum ix86_address_seg seg = SEG_DEFAULT;
+ addr_space_t seg = ADDR_SPACE_GENERIC;
/* Allow zero-extended SImode addresses,
they will be emitted with addr32 prefix. */
@@ -14072,7 +14088,7 @@ ix86_decompose_address (rtx addr, struct ix86_address *out)
case UNSPEC:
if (XINT (op, 1) == UNSPEC_TP
&& TARGET_TLS_DIRECT_SEG_REFS
- && seg == SEG_DEFAULT)
+ && seg == ADDR_SPACE_GENERIC)
seg = DEFAULT_TLS_SEG_REG;
else
return 0;
@@ -14660,7 +14676,7 @@ ix86_legitimate_address_p (machine_mode, rtx addr, bool strict)
struct ix86_address parts;
rtx base, index, disp;
HOST_WIDE_INT scale;
- enum ix86_address_seg seg;
+ addr_space_t seg;
if (ix86_decompose_address (addr, &parts) <= 0)
/* Decomposition failed. */
@@ -14706,7 +14722,7 @@ ix86_legitimate_address_p (machine_mode, rtx addr, bool strict)
return false;
/* Address override works only on the (%reg) part of %fs:(%reg). */
- if (seg != SEG_DEFAULT
+ if (seg != ADDR_SPACE_GENERIC
&& ((base && GET_MODE (base) != word_mode)
|| (index && GET_MODE (index) != word_mode)))
return false;
@@ -17113,32 +17129,22 @@ ix86_print_operand (FILE *file, rtx x, int code)
else if (MEM_P (x))
{
- /* No `byte ptr' prefix for call instructions or BLKmode operands. */
- if (ASSEMBLER_DIALECT == ASM_INTEL && code != 'X' && code != 'P'
- && GET_MODE (x) != BLKmode)
+ rtx addr = XEXP (x, 0);
+
+ /* Avoid (%rip) for call operands. */
+ if (code == 'P' && CONSTANT_ADDRESS_P (x) && !CONST_INT_P (x))
{
- const char * size;
- switch (GET_MODE_SIZE (GET_MODE (x)))
- {
- case 1: size = "BYTE"; break;
- case 2: size = "WORD"; break;
- case 4: size = "DWORD"; break;
- case 8: size = "QWORD"; break;
- case 12: size = "TBYTE"; break;
- case 16:
- if (GET_MODE (x) == XFmode)
- size = "TBYTE";
- else
- size = "XMMWORD";
- break;
- case 32: size = "YMMWORD"; break;
- case 64: size = "ZMMWORD"; break;
- default:
- gcc_unreachable ();
- }
+ output_addr_const (file, addr);
+ return;
+ }
+
+ /* No `byte ptr' prefix for call instructions ... */
+ if (ASSEMBLER_DIALECT == ASM_INTEL && code != 'X' && code != 'P')
+ {
+ machine_mode mode = GET_MODE (x);
+ const char *size;
- /* Check for explicit size override (codes 'b', 'w', 'k',
- 'q' and 'x') */
+ /* Check for explicit size override codes. */
if (code == 'b')
size = "BYTE";
else if (code == 'w')
@@ -17149,20 +17155,39 @@ ix86_print_operand (FILE *file, rtx x, int code)
size = "QWORD";
else if (code == 'x')
size = "XMMWORD";
-
- fputs (size, file);
- fputs (" PTR ", file);
+ else if (mode == BLKmode)
+ /* ... or BLKmode operands, when not overridden. */
+ size = NULL;
+ else
+ switch (GET_MODE_SIZE (mode))
+ {
+ case 1: size = "BYTE"; break;
+ case 2: size = "WORD"; break;
+ case 4: size = "DWORD"; break;
+ case 8: size = "QWORD"; break;
+ case 12: size = "TBYTE"; break;
+ case 16:
+ if (mode == XFmode)
+ size = "TBYTE";
+ else
+ size = "XMMWORD";
+ break;
+ case 32: size = "YMMWORD"; break;
+ case 64: size = "ZMMWORD"; break;
+ default:
+ gcc_unreachable ();
+ }
+ if (size)
+ {
+ fputs (size, file);
+ fputs (" PTR ", file);
+ }
}
- x = XEXP (x, 0);
- /* Avoid (%rip) for call operands. */
- if (CONSTANT_ADDRESS_P (x) && code == 'P'
- && !CONST_INT_P (x))
- output_addr_const (file, x);
- else if (this_is_asm_operands && ! address_operand (x, VOIDmode))
+ if (this_is_asm_operands && ! address_operand (addr, VOIDmode))
output_operand_lossage ("invalid constraints for operand");
else
- output_address (x);
+ ix86_print_operand_address_as (file, addr, MEM_ADDR_SPACE (x));
}
else if (CONST_DOUBLE_P (x) && GET_MODE (x) == SFmode)
@@ -17247,7 +17272,7 @@ ix86_print_operand_punct_valid_p (unsigned char code)
/* Print a memory operand whose address is ADDR. */
static void
-ix86_print_operand_address (FILE *file, rtx addr)
+ix86_print_operand_address_as (FILE *file, rtx addr, addr_space_t as)
{
struct ix86_address parts;
rtx base, index, disp;
@@ -17300,18 +17325,24 @@ ix86_print_operand_address (FILE *file, rtx addr)
disp = parts.disp;
scale = parts.scale;
- switch (parts.seg)
+ if (ADDR_SPACE_GENERIC_P (as))
+ as = parts.seg;
+ else
+ gcc_assert (ADDR_SPACE_GENERIC_P (parts.seg));
+
+ if (!ADDR_SPACE_GENERIC_P (as))
{
- case SEG_DEFAULT:
- break;
- case SEG_FS:
- case SEG_GS:
- if (ASSEMBLER_DIALECT == ASM_ATT)
- putc ('%', file);
- fputs ((parts.seg == SEG_FS ? "fs:" : "gs:"), file);
- break;
- default:
- gcc_unreachable ();
+ const char *string;
+
+ if (as == ADDR_SPACE_SEG_TLS)
+ as = DEFAULT_TLS_SEG_REG;
+ if (as == ADDR_SPACE_SEG_FS)
+ string = (ASSEMBLER_DIALECT == ASM_ATT ? "%fs:" : "fs:");
+ else if (as == ADDR_SPACE_SEG_GS)
+ string = (ASSEMBLER_DIALECT == ASM_ATT ? "%gs:" : "gs:");
+ else
+ gcc_unreachable ();
+ fputs (string, file);
}
/* Use one byte shorter RIP relative addressing for 64bit mode. */
@@ -17335,7 +17366,7 @@ ix86_print_operand_address (FILE *file, rtx addr)
if (CONST_INT_P (disp))
{
- if (ASSEMBLER_DIALECT == ASM_INTEL && parts.seg == SEG_DEFAULT)
+ if (ASSEMBLER_DIALECT == ASM_INTEL && parts.seg == ADDR_SPACE_GENERIC)
fputs ("ds:", file);
fprintf (file, HOST_WIDE_INT_PRINT_DEC, INTVAL (disp));
}
@@ -17471,6 +17502,12 @@ ix86_print_operand_address (FILE *file, rtx addr)
}
}
+static void
+ix86_print_operand_address (FILE *file, rtx addr)
+{
+ ix86_print_operand_address_as (file, addr, ADDR_SPACE_GENERIC);
+}
+
/* Implementation of TARGET_ASM_OUTPUT_ADDR_CONST_EXTRA. */
static bool
@@ -25664,7 +25701,7 @@ expand_set_or_movmem_constant_prologue (rtx dst, rtx *srcp, rtx destreg,
/* Return true if ALG can be used in current context.
Assume we expand memset if MEMSET is true. */
static bool
-alg_usable_p (enum stringop_alg alg, bool memset)
+alg_usable_p (enum stringop_alg alg, bool memset, bool have_as)
{
if (alg == no_stringop)
return false;
@@ -25673,12 +25710,19 @@ alg_usable_p (enum stringop_alg alg, bool memset)
/* Algorithms using the rep prefix want at least edi and ecx;
additionally, memset wants eax and memcpy wants esi. Don't
consider such algorithms if the user has appropriated those
- registers for their own purposes. */
+ registers for their own purposes, or if we have a non-default
+ address space, since some string insns cannot override the segment. */
if (alg == rep_prefix_1_byte
|| alg == rep_prefix_4_byte
|| alg == rep_prefix_8_byte)
- return !(fixed_regs[CX_REG] || fixed_regs[DI_REG]
- || (memset ? fixed_regs[AX_REG] : fixed_regs[SI_REG]));
+ {
+ if (have_as)
+ return false;
+ if (fixed_regs[CX_REG]
+ || fixed_regs[DI_REG]
+ || (memset ? fixed_regs[AX_REG] : fixed_regs[SI_REG]))
+ return false;
+ }
return true;
}
@@ -25686,7 +25730,8 @@ alg_usable_p (enum stringop_alg alg, bool memset)
static enum stringop_alg
decide_alg (HOST_WIDE_INT count, HOST_WIDE_INT expected_size,
unsigned HOST_WIDE_INT min_size, unsigned HOST_WIDE_INT max_size,
- bool memset, bool zero_memset, int *dynamic_check, bool *noalign)
+ bool memset, bool zero_memset, bool have_as,
+ int *dynamic_check, bool *noalign)
{
const struct stringop_algs * algs;
bool optimize_for_speed;
@@ -25718,7 +25763,7 @@ decide_alg (HOST_WIDE_INT count, HOST_WIDE_INT expected_size,
for (i = 0; i < MAX_STRINGOP_ALGS; i++)
{
enum stringop_alg candidate = algs->size[i].alg;
- bool usable = alg_usable_p (candidate, memset);
+ bool usable = alg_usable_p (candidate, memset, have_as);
any_alg_usable_p |= usable;
if (candidate != libcall && candidate && usable)
@@ -25734,17 +25779,17 @@ decide_alg (HOST_WIDE_INT count, HOST_WIDE_INT expected_size,
/* If user specified the algorithm, honnor it if possible. */
if (ix86_stringop_alg != no_stringop
- && alg_usable_p (ix86_stringop_alg, memset))
+ && alg_usable_p (ix86_stringop_alg, memset, have_as))
return ix86_stringop_alg;
/* rep; movq or rep; movl is the smallest variant. */
else if (!optimize_for_speed)
{
*noalign = true;
if (!count || (count & 3) || (memset && !zero_memset))
- return alg_usable_p (rep_prefix_1_byte, memset)
+ return alg_usable_p (rep_prefix_1_byte, memset, have_as)
? rep_prefix_1_byte : loop_1_byte;
else
- return alg_usable_p (rep_prefix_4_byte, memset)
+ return alg_usable_p (rep_prefix_4_byte, memset, have_as)
? rep_prefix_4_byte : loop;
}
/* Very tiny blocks are best handled via the loop, REP is expensive to
@@ -25767,7 +25812,8 @@ decide_alg (HOST_WIDE_INT count, HOST_WIDE_INT expected_size,
{
enum stringop_alg candidate = algs->size[i].alg;
- if (candidate != libcall && alg_usable_p (candidate, memset))
+ if (candidate != libcall
+ && alg_usable_p (candidate, memset, have_as))
{
alg = candidate;
alg_noalign = algs->size[i].noalign;
@@ -25787,7 +25833,7 @@ decide_alg (HOST_WIDE_INT count, HOST_WIDE_INT expected_size,
else if (!any_alg_usable_p)
break;
}
- else if (alg_usable_p (candidate, memset))
+ else if (alg_usable_p (candidate, memset, have_as))
{
*noalign = algs->size[i].noalign;
return candidate;
@@ -25804,7 +25850,7 @@ decide_alg (HOST_WIDE_INT count, HOST_WIDE_INT expected_size,
choice in ix86_costs. */
if ((TARGET_INLINE_ALL_STRINGOPS || TARGET_INLINE_STRINGOPS_DYNAMICALLY)
&& (algs->unknown_size == libcall
- || !alg_usable_p (algs->unknown_size, memset)))
+ || !alg_usable_p (algs->unknown_size, memset, have_as)))
{
enum stringop_alg alg;
@@ -25821,7 +25867,7 @@ decide_alg (HOST_WIDE_INT count, HOST_WIDE_INT expected_size,
if (max <= 0)
max = 4096;
alg = decide_alg (count, max / 2, min_size, max_size, memset,
- zero_memset, dynamic_check, noalign);
+ zero_memset, have_as, dynamic_check, noalign);
gcc_assert (*dynamic_check == -1);
if (TARGET_INLINE_STRINGOPS_DYNAMICALLY)
*dynamic_check = max;
@@ -25829,7 +25875,7 @@ decide_alg (HOST_WIDE_INT count, HOST_WIDE_INT expected_size,
gcc_assert (alg != libcall);
return alg;
}
- return (alg_usable_p (algs->unknown_size, memset)
+ return (alg_usable_p (algs->unknown_size, memset, have_as)
? algs->unknown_size : libcall);
}
@@ -26035,6 +26081,7 @@ ix86_expand_set_or_movmem (rtx dst, rtx src, rtx count_exp, rtx val_exp,
unsigned HOST_WIDE_INT max_size = -1;
unsigned HOST_WIDE_INT probable_max_size = -1;
bool misaligned_prologue_used = false;
+ bool have_as;
if (CONST_INT_P (align_exp))
align = INTVAL (align_exp);
@@ -26072,11 +26119,15 @@ ix86_expand_set_or_movmem (rtx dst, rtx src, rtx count_exp, rtx val_exp,
if (count > (HOST_WIDE_INT_1U << 30))
return false;
+ have_as = !ADDR_SPACE_GENERIC_P (MEM_ADDR_SPACE (dst));
+ if (!issetmem)
+ have_as |= !ADDR_SPACE_GENERIC_P (MEM_ADDR_SPACE (src));
+
/* Step 0: Decide on preferred algorithm, desired alignment and
size of chunks to be copied by main loop. */
alg = decide_alg (count, expected_size, min_size, probable_max_size,
issetmem,
- issetmem && val_exp == const0_rtx,
+ issetmem && val_exp == const0_rtx, have_as,
&dynamic_check, &noalign);
if (alg == libcall)
return false;
@@ -26690,6 +26741,9 @@ ix86_expand_strlen (rtx out, rtx src, rtx eoschar, rtx align)
/* Can't use this if the user has appropriated eax, ecx, or edi. */
if (fixed_regs[AX_REG] || fixed_regs[CX_REG] || fixed_regs[DI_REG])
return false;
+ /* Can't use this for non-default address spaces. */
+ if (!ADDR_SPACE_GENERIC_P (MEM_ADDR_SPACE (src)))
+ return false;
scratch2 = gen_reg_rtx (Pmode);
scratch3 = gen_reg_rtx (Pmode);
@@ -27104,7 +27158,7 @@ memory_address_length (rtx addr, bool lea)
ok = ix86_decompose_address (addr, &parts);
gcc_assert (ok);
- len = (parts.seg == SEG_DEFAULT) ? 0 : 1;
+ len = (parts.seg == ADDR_SPACE_GENERIC) ? 0 : 1;
/* If this is not LEA instruction, add the length of addr32 prefix. */
if (TARGET_64BIT && !lea
@@ -27265,25 +27319,35 @@ ix86_attr_length_address_default (rtx_insn *insn)
extract_insn_cached (insn);
for (i = recog_data.n_operands - 1; i >= 0; --i)
- if (MEM_P (recog_data.operand[i]))
- {
- constrain_operands_cached (insn, reload_completed);
- if (which_alternative != -1)
- {
- const char *constraints = recog_data.constraints[i];
- int alt = which_alternative;
-
- while (*constraints == '=' || *constraints == '+')
- constraints++;
- while (alt-- > 0)
- while (*constraints++ != ',')
- ;
- /* Skip ignored operands. */
- if (*constraints == 'X')
- continue;
- }
- return memory_address_length (XEXP (recog_data.operand[i], 0), false);
- }
+ {
+ rtx op = recog_data.operand[i];
+ if (MEM_P (op))
+ {
+ constrain_operands_cached (insn, reload_completed);
+ if (which_alternative != -1)
+ {
+ const char *constraints = recog_data.constraints[i];
+ int alt = which_alternative;
+
+ while (*constraints == '=' || *constraints == '+')
+ constraints++;
+ while (alt-- > 0)
+ while (*constraints++ != ',')
+ ;
+ /* Skip ignored operands. */
+ if (*constraints == 'X')
+ continue;
+ }
+
+ int len = memory_address_length (XEXP (op, 0), false);
+
+ /* Account for segment prefix for non-default addr spaces. */
+ if (!ADDR_SPACE_GENERIC_P (MEM_ADDR_SPACE (op)))
+ len++;
+
+ return len;
+ }
+ }
return 0;
}
@@ -53637,6 +53701,78 @@ ix86_operands_ok_for_move_multiple (rtx *operands, bool load,
return true;
}
+/* Address space support.
+
+ This is not "far pointers" in the 16-bit sense, but an easy way
+ to use %fs and %gs segment prefixes. Therefore:
+
+ (a) All address spaces have the same modes,
+ (b) All address spaces have the same addresss forms,
+ (c) While %fs and %gs are technically subsets of the generic
+ address space, they are probably not subsets of each other.
+ (d) Since we have no access to the segment base register values
+ without resorting to a system call, we cannot convert a
+ non-default address space to a default address space.
+ Therefore we do not claim %fs or %gs are subsets of generic.
+ (e) However, __seg_tls uses UNSPEC_TP as the base (which itself is
+ stored at __seg_tls:0) so we can map between tls and generic. */
+
+static bool
+ix86_addr_space_subset_p (addr_space_t subset, addr_space_t superset)
+{
+ return (subset == superset
+ || (superset == ADDR_SPACE_GENERIC
+ && subset == ADDR_SPACE_SEG_TLS));
+}
+#undef TARGET_ADDR_SPACE_SUBSET_P
+#define TARGET_ADDR_SPACE_SUBSET_P ix86_addr_space_subset_p
+
+static rtx
+ix86_addr_space_convert (rtx op, tree from_type, tree to_type)
+{
+ addr_space_t from_as = TYPE_ADDR_SPACE (TREE_TYPE (from_type));
+ addr_space_t to_as = TYPE_ADDR_SPACE (TREE_TYPE (to_type));
+
+ /* Conversion between SEG_TLS and GENERIC is handled by adding or
+ subtracting the thread pointer. */
+ if ((from_as == ADDR_SPACE_GENERIC && to_as == ADDR_SPACE_SEG_TLS)
+ || (from_as == ADDR_SPACE_SEG_TLS && to_as == ADDR_SPACE_GENERIC))
+ {
+ machine_mode mode = GET_MODE (op);
+ if (mode == VOIDmode)
+ mode = ptr_mode;
+ rtx tp = get_thread_pointer (mode, optimize || mode != ptr_mode);
+ return expand_binop (mode, (to_as == ADDR_SPACE_GENERIC
+ ? add_optab : sub_optab),
+ op, tp, NULL, 1, OPTAB_WIDEN);
+ }
+
+ return op;
+}
+#undef TARGET_ADDR_SPACE_CONVERT
+#define TARGET_ADDR_SPACE_CONVERT ix86_addr_space_convert
+
+static int
+ix86_addr_space_debug (addr_space_t as)
+{
+ /* Fold __seg_tls to __seg_fs or __seg_gs for debugging. */
+ if (as == ADDR_SPACE_SEG_TLS)
+ as = DEFAULT_TLS_SEG_REG;
+ return as;
+}
+#undef TARGET_ADDR_SPACE_DEBUG
+#define TARGET_ADDR_SPACE_DEBUG ix86_addr_space_debug
+
+/* All use of segmentation is assumed to make address 0 valid. */
+
+static bool
+ix86_addr_space_zero_address_valid (addr_space_t as)
+{
+ return as != ADDR_SPACE_GENERIC;
+}
+#undef TARGET_ADDR_SPACE_ZERO_ADDRESS_VALID
+#define TARGET_ADDR_SPACE_ZERO_ADDRESS_VALID ix86_addr_space_zero_address_valid
+
/* Initialize the GCC target structure. */
#undef TARGET_RETURN_IN_MEMORY
#define TARGET_RETURN_IN_MEMORY ix86_return_in_memory
diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h
index be96c75df77..3d5b2b25ced 100644
--- a/gcc/config/i386/i386.h
+++ b/gcc/config/i386/i386.h
@@ -602,7 +602,8 @@ extern tree x86_mfence;
#define DEFAULT_ABI SYSV_ABI
/* The default TLS segment register used by target. */
-#define DEFAULT_TLS_SEG_REG (TARGET_64BIT ? SEG_FS : SEG_GS)
+#define DEFAULT_TLS_SEG_REG \
+ (TARGET_64BIT ? ADDR_SPACE_SEG_FS : ADDR_SPACE_SEG_GS)
/* Subtargets may reset this to 1 in order to enable 96-bit long double
with the rounding mode forced to 53 bits. */
diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md
index d0c0d23df28..2cb94fec34e 100644
--- a/gcc/config/i386/i386.md
+++ b/gcc/config/i386/i386.md
@@ -2595,9 +2595,19 @@
[(set (mem:SWI1248x (match_operand:DI 0 "x86_64_movabs_operand" "i,r"))
(match_operand:SWI1248x 1 "nonmemory_operand" "a,r<i>"))]
"TARGET_LP64 && ix86_check_movabs (insn, 0)"
- "@
- movabs{<imodesuffix>}\t{%1, %P0|[%P0], %1}
- mov{<imodesuffix>}\t{%1, %a0|<iptrsize> PTR %a0, %1}"
+{
+ /* Recover the full memory rtx. */
+ operands[0] = SET_DEST (PATTERN (insn));
+ switch (which_alternative)
+ {
+ case 0:
+ return "movabs{<imodesuffix>}\t{%1, %0|%0, %1}";
+ case 1:
+ return "mov{<imodesuffix>}\t{%1, %0|%0, %1}";
+ default:
+ gcc_unreachable ();
+ }
+}
[(set_attr "type" "imov")
(set_attr "modrm" "0,*")
(set_attr "length_address" "8,0")
@@ -2609,9 +2619,19 @@
[(set (match_operand:SWI1248x 0 "register_operand" "=a,r")
(mem:SWI1248x (match_operand:DI 1 "x86_64_movabs_operand" "i,r")))]
"TARGET_LP64 && ix86_check_movabs (insn, 1)"
- "@
- movabs{<imodesuffix>}\t{%P1, %0|%0, [%P1]}
- mov{<imodesuffix>}\t{%a1, %0|%0, <iptrsize> PTR %a1}"
+{
+ /* Recover the full memory rtx. */
+ operands[1] = SET_SRC (PATTERN (insn));
+ switch (which_alternative)
+ {
+ case 0:
+ return "movabs{<imodesuffix>}\t{%1, %0|%0, %1}";
+ case 1:
+ return "mov{<imodesuffix>}\t{%1, %0|%0, %1}";
+ default:
+ gcc_unreachable ();
+ }
+}
[(set_attr "type" "imov")
(set_attr "modrm" "0,*")
(set_attr "length_address" "8,0")
@@ -16139,6 +16159,10 @@
(clobber (reg:CC FLAGS_REG))])]
""
{
+ /* Can't use this for non-default address spaces. */
+ if (!ADDR_SPACE_GENERIC_P (MEM_ADDR_SPACE (operands[3])))
+ FAIL;
+
rtx adjust = GEN_INT (GET_MODE_SIZE (GET_MODE (operands[1])));
/* If .md ever supports :P for Pmode, these can be directly
@@ -16179,7 +16203,8 @@
(plus:P (match_dup 3)
(const_int 8)))]
"TARGET_64BIT
- && !(fixed_regs[SI_REG] || fixed_regs[DI_REG])"
+ && !(fixed_regs[SI_REG] || fixed_regs[DI_REG])
+ && ix86_check_no_addr_space (insn)"
"%^movsq"
[(set_attr "type" "str")
(set_attr "memory" "both")
@@ -16194,7 +16219,8 @@
(set (match_operand:P 1 "register_operand" "=S")
(plus:P (match_dup 3)
(const_int 4)))]
- "!(fixed_regs[SI_REG] || fixed_regs[DI_REG])"
+ "!(fixed_regs[SI_REG] || fixed_regs[DI_REG])
+ && ix86_check_no_addr_space (insn)"
"%^movs{l|d}"
[(set_attr "type" "str")
(set_attr "memory" "both")
@@ -16209,7 +16235,8 @@
(set (match_operand:P 1 "register_operand" "=S")
(plus:P (match_dup 3)
(const_int 2)))]
- "!(fixed_regs[SI_REG] || fixed_regs[DI_REG])"
+ "!(fixed_regs[SI_REG] || fixed_regs[DI_REG])
+ && ix86_check_no_addr_space (insn)"
"%^movsw"
[(set_attr "type" "str")
(set_attr "memory" "both")
@@ -16225,7 +16252,8 @@
(plus:P (match_dup 3)
(const_int 1)))]
"!(fixed_regs[SI_REG] || fixed_regs[DI_REG])"
- "%^movsb"
+ "%^movsb
+ && ix86_check_no_addr_space (insn)"
[(set_attr "type" "str")
(set_attr "memory" "both")
(set (attr "prefix_rex")
@@ -16260,7 +16288,8 @@
(mem:BLK (match_dup 4)))
(use (match_dup 5))]
"TARGET_64BIT
- && !(fixed_regs[CX_REG] || fixed_regs[SI_REG] || fixed_regs[DI_REG])"
+ && !(fixed_regs[CX_REG] || fixed_regs[SI_REG] || fixed_regs[DI_REG])
+ && ix86_check_no_addr_space (insn)"
"%^rep{%;} movsq"
[(set_attr "type" "str")
(set_attr "prefix_rep" "1")
@@ -16279,7 +16308,8 @@
(set (mem:BLK (match_dup 3))
(mem:BLK (match_dup 4)))
(use (match_dup 5))]
- "!(fixed_regs[CX_REG] || fixed_regs[SI_REG] || fixed_regs[DI_REG])"
+ "!(fixed_regs[CX_REG] || fixed_regs[SI_REG] || fixed_regs[DI_REG])
+ && ix86_check_no_addr_space (insn)"
"%^rep{%;} movs{l|d}"
[(set_attr "type" "str")
(set_attr "prefix_rep" "1")
@@ -16296,7 +16326,8 @@
(set (mem:BLK (match_dup 3))
(mem:BLK (match_dup 4)))
(use (match_dup 5))]
- "!(fixed_regs[CX_REG] || fixed_regs[SI_REG] || fixed_regs[DI_REG])"
+ "!(fixed_regs[CX_REG] || fixed_regs[SI_REG] || fixed_regs[DI_REG])
+ && ix86_check_no_addr_space (insn)"
"%^rep{%;} movsb"
[(set_attr "type" "str")
(set_attr "prefix_rep" "1")
@@ -16336,6 +16367,10 @@
(clobber (reg:CC FLAGS_REG))])]
""
{
+ /* Can't use this for non-default address spaces. */
+ if (!ADDR_SPACE_GENERIC_P (MEM_ADDR_SPACE (operands[1])))
+ FAIL;
+
if (GET_MODE (operands[1]) != GET_MODE (operands[2]))
operands[1] = adjust_address_nv (operands[1], GET_MODE (operands[2]), 0);
@@ -16371,7 +16406,8 @@
(const_int 8)))
(unspec [(const_int 0)] UNSPEC_STOS)]
"TARGET_64BIT
- && !(fixed_regs[AX_REG] || fixed_regs[DI_REG])"
+ && !(fixed_regs[AX_REG] || fixed_regs[DI_REG])
+ && ix86_check_no_addr_space (insn)"
"%^stosq"
[(set_attr "type" "str")
(set_attr "memory" "store")
@@ -16384,7 +16420,8 @@
(plus:P (match_dup 1)
(const_int 4)))
(unspec [(const_int 0)] UNSPEC_STOS)]
- "!(fixed_regs[AX_REG] || fixed_regs[DI_REG])"
+ "!(fixed_regs[AX_REG] || fixed_regs[DI_REG])
+ && ix86_check_no_addr_space (insn)"
"%^stos{l|d}"
[(set_attr "type" "str")
(set_attr "memory" "store")
@@ -16397,7 +16434,8 @@
(plus:P (match_dup 1)
(const_int 2)))
(unspec [(const_int 0)] UNSPEC_STOS)]
- "!(fixed_regs[AX_REG] || fixed_regs[DI_REG])"
+ "!(fixed_regs[AX_REG] || fixed_regs[DI_REG])
+ && ix86_check_no_addr_space (insn)"
"%^stosw"
[(set_attr "type" "str")
(set_attr "memory" "store")
@@ -16410,7 +16448,8 @@
(plus:P (match_dup 1)
(const_int 1)))
(unspec [(const_int 0)] UNSPEC_STOS)]
- "!(fixed_regs[AX_REG] || fixed_regs[DI_REG])"
+ "!(fixed_regs[AX_REG] || fixed_regs[DI_REG])
+ && ix86_check_no_addr_space (insn)"
"%^stosb"
[(set_attr "type" "str")
(set_attr "memory" "store")
@@ -16442,7 +16481,8 @@
(use (match_operand:DI 2 "register_operand" "a"))
(use (match_dup 4))]
"TARGET_64BIT
- && !(fixed_regs[AX_REG] || fixed_regs[CX_REG] || fixed_regs[DI_REG])"
+ && !(fixed_regs[AX_REG] || fixed_regs[CX_REG] || fixed_regs[DI_REG])
+ && ix86_check_no_addr_space (insn)"
"%^rep{%;} stosq"
[(set_attr "type" "str")
(set_attr "prefix_rep" "1")
@@ -16459,7 +16499,8 @@
(const_int 0))
(use (match_operand:SI 2 "register_operand" "a"))
(use (match_dup 4))]
- "!(fixed_regs[AX_REG] || fixed_regs[CX_REG] || fixed_regs[DI_REG])"
+ "!(fixed_regs[AX_REG] || fixed_regs[CX_REG] || fixed_regs[DI_REG])
+ && ix86_check_no_addr_space (insn)"
"%^rep{%;} stos{l|d}"
[(set_attr "type" "str")
(set_attr "prefix_rep" "1")
@@ -16475,7 +16516,8 @@
(const_int 0))
(use (match_operand:QI 2 "register_operand" "a"))
(use (match_dup 4))]
- "!(fixed_regs[AX_REG] || fixed_regs[CX_REG] || fixed_regs[DI_REG])"
+ "!(fixed_regs[AX_REG] || fixed_regs[CX_REG] || fixed_regs[DI_REG])
+ && ix86_check_no_addr_space (insn)"
"%^rep{%;} stosb"
[(set_attr "type" "str")
(set_attr "prefix_rep" "1")
@@ -16596,7 +16638,8 @@
(clobber (match_operand:P 0 "register_operand" "=S"))
(clobber (match_operand:P 1 "register_operand" "=D"))
(clobber (match_operand:P 2 "register_operand" "=c"))]
- "!(fixed_regs[CX_REG] || fixed_regs[SI_REG] || fixed_regs[DI_REG])"
+ "!(fixed_regs[CX_REG] || fixed_regs[SI_REG] || fixed_regs[DI_REG])
+ && ix86_check_no_addr_space (insn)"
"%^repz{%;} cmpsb"
[(set_attr "type" "str")
(set_attr "mode" "QI")
@@ -16636,7 +16679,8 @@
(clobber (match_operand:P 0 "register_operand" "=S"))
(clobber (match_operand:P 1 "register_operand" "=D"))
(clobber (match_operand:P 2 "register_operand" "=c"))]
- "!(fixed_regs[CX_REG] || fixed_regs[SI_REG] || fixed_regs[DI_REG])"
+ "!(fixed_regs[CX_REG] || fixed_regs[SI_REG] || fixed_regs[DI_REG])
+ && ix86_check_no_addr_space (insn)"
"%^repz{%;} cmpsb"
[(set_attr "type" "str")
(set_attr "mode" "QI")
@@ -16677,7 +16721,8 @@
(match_operand:P 4 "register_operand" "0")] UNSPEC_SCAS))
(clobber (match_operand:P 1 "register_operand" "=D"))
(clobber (reg:CC FLAGS_REG))]
- "!(fixed_regs[AX_REG] || fixed_regs[CX_REG] || fixed_regs[DI_REG])"
+ "!(fixed_regs[AX_REG] || fixed_regs[CX_REG] || fixed_regs[DI_REG])
+ && ix86_check_no_addr_space (insn)"
"%^repnz{%;} scasb"
[(set_attr "type" "str")
(set_attr "mode" "QI")
diff --git a/gcc/config/i386/predicates.md b/gcc/config/i386/predicates.md
index 1595142255d..c11f2d7d228 100644
--- a/gcc/config/i386/predicates.md
+++ b/gcc/config/i386/predicates.md
@@ -974,7 +974,7 @@
ok = ix86_decompose_address (op, &parts);
gcc_assert (ok);
- return parts.seg == SEG_DEFAULT;
+ return parts.seg == ADDR_SPACE_GENERIC;
})
;; Return true if op if a valid base register, displacement or
@@ -988,7 +988,7 @@
ok = ix86_decompose_address (op, &parts);
gcc_assert (ok);
- if (parts.index || parts.seg != SEG_DEFAULT)
+ if (parts.index || parts.seg != ADDR_SPACE_GENERIC)
return false;
/* VSIB addressing doesn't support (%rip). */
@@ -1032,7 +1032,7 @@
if (parts.index && parts.base)
return false;
- if (parts.seg != SEG_DEFAULT)
+ if (parts.seg != ADDR_SPACE_GENERIC)
return false;
/* Do not support (%rip). */
@@ -1064,7 +1064,7 @@
if (parts.index)
return false;
- if (parts.seg != SEG_DEFAULT)
+ if (parts.seg != ADDR_SPACE_GENERIC)
return false;
/* Do not support (%rip). */
diff --git a/gcc/config/i386/rdos.h b/gcc/config/i386/rdos.h
index f9bfe6d02e4..ccf6b78824a 100644
--- a/gcc/config/i386/rdos.h
+++ b/gcc/config/i386/rdos.h
@@ -25,7 +25,7 @@ along with GCC; see the file COPYING3. If not see
#define TARGET_TLS_DIRECT_SEG_REFS_DEFAULT MASK_TLS_DIRECT_SEG_REFS
#undef DEFAULT_TLS_SEG_REG
-#define DEFAULT_TLS_SEG_REG SEG_GS
+#define DEFAULT_TLS_SEG_REG ADDR_SPACE_SEG_GS
#undef TARGET_RDOS
#define TARGET_RDOS 1
diff --git a/gcc/config/mips/loongson.md b/gcc/config/mips/loongson.md
index 0b19bd7baf8..b8489ab5ab9 100644
--- a/gcc/config/mips/loongson.md
+++ b/gcc/config/mips/loongson.md
@@ -852,58 +852,66 @@
"dsrl\t%0,%1,%2"
[(set_attr "type" "fcvt")])
-(define_expand "reduc_uplus_<mode>"
- [(match_operand:VWH 0 "register_operand" "")
- (match_operand:VWH 1 "register_operand" "")]
+(define_insn "vec_loongson_extract_lo_<mode>"
+ [(set (match_operand:<V_inner> 0 "register_operand" "=r")
+ (vec_select:<V_inner>
+ (match_operand:VWHB 1 "register_operand" "f")
+ (parallel [(const_int 0)])))]
"TARGET_HARD_FLOAT && TARGET_LOONGSON_VECTORS"
-{
- mips_expand_vec_reduc (operands[0], operands[1], gen_add<mode>3);
- DONE;
-})
+ "mfc1\t%0,%1"
+ [(set_attr "type" "mfc")])
-; ??? Given that we're not describing a widening reduction, we should
-; not have separate optabs for signed and unsigned.
-(define_expand "reduc_splus_<mode>"
- [(match_operand:VWHB 0 "register_operand" "")
+(define_expand "reduc_plus_scal_<mode>"
+ [(match_operand:<V_inner> 0 "register_operand" "")
(match_operand:VWHB 1 "register_operand" "")]
"TARGET_HARD_FLOAT && TARGET_LOONGSON_VECTORS"
{
- emit_insn (gen_reduc_uplus_<mode>(operands[0], operands[1]));
+ rtx tmp = gen_reg_rtx (GET_MODE (operands[1]));
+ mips_expand_vec_reduc (tmp, operands[1], gen_add<mode>3);
+ emit_insn (gen_vec_loongson_extract_lo_<mode> (operands[0], tmp));
DONE;
})
-(define_expand "reduc_smax_<mode>"
- [(match_operand:VWHB 0 "register_operand" "")
+(define_expand "reduc_smax_scal_<mode>"
+ [(match_operand:<V_inner> 0 "register_operand" "")
(match_operand:VWHB 1 "register_operand" "")]
"TARGET_HARD_FLOAT && TARGET_LOONGSON_VECTORS"
{
- mips_expand_vec_reduc (operands[0], operands[1], gen_smax<mode>3);
+ rtx tmp = gen_reg_rtx (GET_MODE (operands[1]));
+ mips_expand_vec_reduc (tmp, operands[1], gen_smax<mode>3);
+ emit_insn (gen_vec_loongson_extract_lo_<mode> (operands[0], tmp));
DONE;
})
-(define_expand "reduc_smin_<mode>"
- [(match_operand:VWHB 0 "register_operand" "")
+(define_expand "reduc_smin_scal_<mode>"
+ [(match_operand:<V_inner> 0 "register_operand" "")
(match_operand:VWHB 1 "register_operand" "")]
"TARGET_HARD_FLOAT && TARGET_LOONGSON_VECTORS"
{
- mips_expand_vec_reduc (operands[0], operands[1], gen_smin<mode>3);
+ rtx tmp = gen_reg_rtx (GET_MODE (operands[1]));
+ mips_expand_vec_reduc (tmp, operands[1], gen_smin<mode>3);
+ emit_insn (gen_vec_loongson_extract_lo_<mode> (operands[0], tmp));
DONE;
})
-(define_expand "reduc_umax_<mode>"
- [(match_operand:VB 0 "register_operand" "")
+(define_expand "reduc_umax_scal_<mode>"
+ [(match_operand:<V_inner> 0 "register_operand" "")
(match_operand:VB 1 "register_operand" "")]
"TARGET_HARD_FLOAT && TARGET_LOONGSON_VECTORS"
{
- mips_expand_vec_reduc (operands[0], operands[1], gen_umax<mode>3);
+ rtx tmp = gen_reg_rtx (GET_MODE (operands[1]));
+ mips_expand_vec_reduc (tmp, operands[1], gen_umax<mode>3);
+ emit_insn (gen_vec_loongson_extract_lo_<mode> (operands[0], tmp));
DONE;
})
-(define_expand "reduc_umin_<mode>"
- [(match_operand:VB 0 "register_operand" "")
+(define_expand "reduc_umin_scal_<mode>"
+ [(match_operand:<V_inner> 0 "register_operand" "")
(match_operand:VB 1 "register_operand" "")]
"TARGET_HARD_FLOAT && TARGET_LOONGSON_VECTORS"
{
- mips_expand_vec_reduc (operands[0], operands[1], gen_umin<mode>3);
+ rtx tmp = gen_reg_rtx (GET_MODE (operands[1]));
+ mips_expand_vec_reduc (tmp, operands[1], gen_umin<mode>3);
+ emit_insn (gen_vec_loongson_extract_lo_<mode> (operands[0], tmp));
DONE;
})
diff --git a/gcc/config/mips/mips.c b/gcc/config/mips/mips.c
index 95d5ca34bef..9d6283fe116 100644
--- a/gcc/config/mips/mips.c
+++ b/gcc/config/mips/mips.c
@@ -15705,10 +15705,10 @@ r10k_safe_mem_expr_p (tree expr, unsigned HOST_WIDE_INT offset)
HOST_WIDE_INT bitoffset, bitsize;
tree inner, var_offset;
machine_mode mode;
- int unsigned_p, volatile_p;
+ int unsigned_p, reverse_p, volatile_p;
inner = get_inner_reference (expr, &bitsize, &bitoffset, &var_offset, &mode,
- &unsigned_p, &volatile_p, false);
+ &unsigned_p, &reverse_p, &volatile_p, false);
if (!DECL_P (inner) || !DECL_SIZE_UNIT (inner) || var_offset)
return false;
diff --git a/gcc/config/s390/s390.c b/gcc/config/s390/s390.c
index 12563a089e1..5e3513a6b89 100644
--- a/gcc/config/s390/s390.c
+++ b/gcc/config/s390/s390.c
@@ -6426,7 +6426,7 @@ s390_expand_atomic (machine_mode mode, enum rtx_code code,
case SET:
if (ac.aligned && MEM_P (val))
store_bit_field (new_rtx, GET_MODE_BITSIZE (mode), 0,
- 0, 0, SImode, val);
+ 0, 0, SImode, val, false);
else
{
new_rtx = expand_simple_binop (SImode, AND, new_rtx, ac.modemaski,
diff --git a/gcc/config/sparc/sparc.opt b/gcc/config/sparc/sparc.opt
index 249d33bc209..16583c38545 100644
--- a/gcc/config/sparc/sparc.opt
+++ b/gcc/config/sparc/sparc.opt
@@ -209,7 +209,7 @@ Enable strict 32-bit psABI struct return checking.
mfix-at697f
Target Report RejectNegative Var(sparc_fix_at697f)
Enable workaround for single erratum of AT697F processor
-(corresponding to erratum #13 of AT697E processor)
+(corresponding to erratum #13 of AT697E processor).
mfix-ut699
Target Report RejectNegative Var(sparc_fix_ut699)
diff --git a/gcc/config/tilegx/tilegx.c b/gcc/config/tilegx/tilegx.c
index 6f83dccd90c..4ef2ca9375e 100644
--- a/gcc/config/tilegx/tilegx.c
+++ b/gcc/config/tilegx/tilegx.c
@@ -1962,7 +1962,7 @@ tilegx_expand_unaligned_load (rtx dest_reg, rtx mem, HOST_WIDE_INT bitsize,
extract_bit_field (gen_lowpart (DImode, wide_result),
bitsize, bit_offset % BITS_PER_UNIT,
!sign, gen_lowpart (DImode, dest_reg),
- DImode, DImode);
+ DImode, DImode, false);
if (extracted != dest_reg)
emit_move_insn (dest_reg, gen_lowpart (DImode, extracted));
diff --git a/gcc/config/tilepro/tilepro.c b/gcc/config/tilepro/tilepro.c
index ef8e24dbad1..4f95f6cb3b8 100644
--- a/gcc/config/tilepro/tilepro.c
+++ b/gcc/config/tilepro/tilepro.c
@@ -1692,7 +1692,7 @@ tilepro_expand_unaligned_load (rtx dest_reg, rtx mem, HOST_WIDE_INT bitsize,
extract_bit_field (gen_lowpart (SImode, wide_result),
bitsize, bit_offset % BITS_PER_UNIT,
!sign, gen_lowpart (SImode, dest_reg),
- SImode, SImode);
+ SImode, SImode, false);
if (extracted != dest_reg)
emit_move_insn (dest_reg, gen_lowpart (SImode, extracted));
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index e780c868b62..11ca9ab584a 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,46 @@
+2015-11-08 Martin Sebor <msebor@redhat.com>
+
+ PR c++/67942
+ * cp/init.c (warn_placement_new_too_small): Convert integer
+ operand of POINTER_PLUS_EXPR to ssize_t to determine its signed
+ value.
+
+2015-11-06 David Malcolm <dmalcolm@redhat.com>
+
+ * error.c (cp_printer): Update for new "caret_p" param for
+ textinfo::set_location.
+ (pedwarn_cxx98): Update for change in signature of
+ diagnostic_set_info.
+
+2015-11-06 Jason Merrill <jason@redhat.com>
+
+ Support non-type constrained-type-specifiers.
+ * parser.c (check_type_concept): Remove.
+ (cp_parser_maybe_constrained_type_specifier): Don't call it.
+ (synthesize_implicit_template_parm): Handle non-type and template
+ template parameters. Also compare extra args. Return the decl.
+ (cp_parser_template_argument): Handle constrained-type-specifiers for
+ non-type template parameters.
+ (finish_constrained_template_template_parm): Split out from
+ cp_parser_constrained_template_template_parm.
+ (cp_parser_nonclass_name): Move some logic into
+ cp_parser_maybe_concept_name.
+ (cp_parser_init_declarator): Fix error recovery.
+ (get_concept_from_constraint): Remove.
+ (cp_parser_simple_type_specifier): Adjust for
+ synthesize_implicit_template_parm returning the decl.
+ * constraint.cc (placeholder_extract_concept_and_args)
+ (equivalent_placeholder_constraints): Also handle TYPE_DECL
+ constrained parms.
+
+ * pt.c (push_inline_template_parms_recursive): Don't recreate the
+ CONST_DECL.
+
+2015-11-06 Kyrylo Tkachov <kyrylo.tkachov@arm.com>
+
+ * init.c (warn_placement_new_too_small): Use %wu format
+ rather than %lu when printing bytes_avail.
+
2015-11-05 Cesar Philippidis <cesar@codesourcery.com>
Thomas Schwinge <thomas@codesourcery.com>
James Norris <jnorris@codesourcery.com>
diff --git a/gcc/cp/constraint.cc b/gcc/cp/constraint.cc
index a1fbf174ee8..c6eaf754606 100644
--- a/gcc/cp/constraint.cc
+++ b/gcc/cp/constraint.cc
@@ -1379,12 +1379,21 @@ make_constrained_auto (tree con, tree args)
return decl;
}
-/* Given the predicate constraint T from a placeholder type, extract its
- TMPL and ARGS. */
+/* Given the predicate constraint T from a constrained-type-specifier, extract
+ its TMPL and ARGS. FIXME why do we need two different forms of
+ constrained-type-specifier? */
void
placeholder_extract_concept_and_args (tree t, tree &tmpl, tree &args)
{
+ if (TREE_CODE (t) == TYPE_DECL)
+ {
+ /* A constrained parameter. */
+ tmpl = DECL_TI_TEMPLATE (CONSTRAINED_PARM_CONCEPT (t));
+ args = CONSTRAINED_PARM_EXTRA_ARGS (t);
+ return;
+ }
+
gcc_assert (TREE_CODE (t) == PRED_CONSTR);
t = PRED_CONSTR_EXPR (t);
gcc_assert (TREE_CODE (t) == CALL_EXPR
@@ -1418,9 +1427,10 @@ placeholder_extract_concept_and_args (tree t, tree &tmpl, tree &args)
bool
equivalent_placeholder_constraints (tree c1, tree c2)
{
- if (TREE_CODE (c1) == TEMPLATE_TYPE_PARM)
+ if (c1 && TREE_CODE (c1) == TEMPLATE_TYPE_PARM)
+ /* A constrained auto. */
c1 = PLACEHOLDER_TYPE_CONSTRAINTS (c1);
- if (TREE_CODE (c2) == TEMPLATE_TYPE_PARM)
+ if (c2 && TREE_CODE (c2) == TEMPLATE_TYPE_PARM)
c2 = PLACEHOLDER_TYPE_CONSTRAINTS (c2);
if (c1 == c2)
@@ -1434,14 +1444,21 @@ equivalent_placeholder_constraints (tree c1, tree c2)
if (t1 != t2)
return false;
- int len = TREE_VEC_LENGTH (a1);
- if (len != TREE_VEC_LENGTH (a2))
- return false;
+
/* Skip the first argument to avoid infinite recursion on the
placeholder auto itself. */
- for (int i = len-1; i > 0; --i)
- if (!cp_tree_equal (TREE_VEC_ELT (a1, i),
- TREE_VEC_ELT (a2, i)))
+ bool skip1 = (TREE_CODE (c1) == PRED_CONSTR);
+ bool skip2 = (TREE_CODE (c2) == PRED_CONSTR);
+
+ int len1 = (a1 ? TREE_VEC_LENGTH (a1) : 0) - skip1;
+ int len2 = (a2 ? TREE_VEC_LENGTH (a2) : 0) - skip2;
+
+ if (len1 != len2)
+ return false;
+
+ for (int i = 0; i < len1; ++i)
+ if (!cp_tree_equal (TREE_VEC_ELT (a1, i + skip1),
+ TREE_VEC_ELT (a2, i + skip2)))
return false;
return true;
}
diff --git a/gcc/cp/error.c b/gcc/cp/error.c
index 75f6abb415f..286389c8aea 100644
--- a/gcc/cp/error.c
+++ b/gcc/cp/error.c
@@ -3563,7 +3563,7 @@ cp_printer (pretty_printer *pp, text_info *text, const char *spec,
pp_string (pp, result);
if (set_locus && t != NULL)
- text->set_location (0, location_of (t));
+ text->set_location (0, location_of (t), true);
return true;
#undef next_tree
#undef next_tcode
@@ -3677,9 +3677,10 @@ pedwarn_cxx98 (location_t location, int opt, const char *gmsgid, ...)
diagnostic_info diagnostic;
va_list ap;
bool ret;
+ rich_location richloc (location);
va_start (ap, gmsgid);
- diagnostic_set_info (&diagnostic, gmsgid, &ap, location,
+ diagnostic_set_info (&diagnostic, gmsgid, &ap, &richloc,
(cxx_dialect == cxx98) ? DK_PEDWARN : DK_WARNING);
diagnostic.option_index = opt;
ret = report_diagnostic (&diagnostic);
diff --git a/gcc/cp/init.c b/gcc/cp/init.c
index 7386499d570..b45281f517d 100644
--- a/gcc/cp/init.c
+++ b/gcc/cp/init.c
@@ -2321,12 +2321,14 @@ warn_placement_new_too_small (tree type, tree nelts, tree size, tree oper)
if (TREE_CODE (oper) == POINTER_PLUS_EXPR)
{
/* If the offset is comple-time constant, use it to compute a more
- accurate estimate of the size of the buffer. Otherwise, use
- the size of the entire array as an optimistic estimate (this
- may lead to false negatives). */
- const_tree adj = TREE_OPERAND (oper, 1);
+ accurate estimate of the size of the buffer. Since the operand
+ of POINTER_PLUS_EXPR is represented as an unsigned type, convert
+ it to signed first.
+ Otherwise, use the size of the entire array as an optimistic
+ estimate (this may lead to false negatives). */
+ tree adj = TREE_OPERAND (oper, 1);
if (CONSTANT_CLASS_P (adj))
- adjust += tree_to_uhwi (adj);
+ adjust += tree_to_shwi (convert (ssizetype, adj));
else
use_obj_size = true;
@@ -2447,7 +2449,7 @@ warn_placement_new_too_small (tree type, tree nelts, tree size, tree oper)
"%<%T [%wu]%> and size %qwu in a region of type %qT "
"and size %qwi"
: "placement new constructing an object of type "
- "%<%T [%lu]%> and size %qwu in a region of type %qT "
+ "%<%T [%wu]%> and size %qwu in a region of type %qT "
"and size at most %qwu",
type, tree_to_uhwi (nelts), bytes_need,
TREE_TYPE (oper),
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index c6f57297e72..d1f4970f1eb 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -13871,18 +13871,9 @@ cp_parser_constrained_type_template_parm (cp_parser *parser,
return error_mark_node;
}
-/* Finish parsing/processing a template template parameter by borrowing
- the template parameter list from the prototype parameter. */
-
static tree
-cp_parser_constrained_template_template_parm (cp_parser *parser,
- tree proto,
- tree id,
- cp_parameter_declarator *parmdecl)
+finish_constrained_template_template_parm (tree proto, tree id)
{
- if (!cp_parser_check_constrained_type_parm (parser, parmdecl))
- return error_mark_node;
-
/* FIXME: This should probably be copied, and we may need to adjust
the template parameter depths. */
tree saved_parms = current_template_parms;
@@ -13896,6 +13887,20 @@ cp_parser_constrained_template_template_parm (cp_parser *parser,
return parm;
}
+/* Finish parsing/processing a template template parameter by borrowing
+ the template parameter list from the prototype parameter. */
+
+static tree
+cp_parser_constrained_template_template_parm (cp_parser *parser,
+ tree proto,
+ tree id,
+ cp_parameter_declarator *parmdecl)
+{
+ if (!cp_parser_check_constrained_type_parm (parser, parmdecl))
+ return error_mark_node;
+ return finish_constrained_template_template_parm (proto, id);
+}
+
/* Create a new non-type template parameter from the given PARM
declarator. */
@@ -14950,8 +14955,12 @@ cp_parser_template_argument (cp_parser* parser)
/*check_dependency=*/true,
/*ambiguous_decls=*/NULL,
argument_start_token->location);
- if (TREE_CODE (argument) != TEMPLATE_DECL
- && TREE_CODE (argument) != UNBOUND_CLASS_TEMPLATE)
+ /* Handle a constrained-type-specifier for a non-type template
+ parameter. */
+ if (tree decl = cp_parser_maybe_concept_name (parser, argument))
+ argument = decl;
+ else if (TREE_CODE (argument) != TEMPLATE_DECL
+ && TREE_CODE (argument) != UNBOUND_CLASS_TEMPLATE)
cp_parser_error (parser, "expected template-name");
}
if (cp_parser_parse_definitely (parser))
@@ -15630,7 +15639,10 @@ cp_parser_simple_type_specifier (cp_parser* parser,
}
if (cxx_dialect >= cxx14)
- type = synthesize_implicit_template_parm (parser, NULL_TREE);
+ {
+ type = synthesize_implicit_template_parm (parser, NULL_TREE);
+ type = TREE_TYPE (type);
+ }
else
type = error_mark_node;
@@ -15949,19 +15961,6 @@ cp_parser_type_name (cp_parser* parser, bool typename_keyword_p)
return type_decl;
}
-/* Returns true if proto is a type parameter, but not a template
- template parameter. */
-static bool
-check_type_concept (tree fn, tree proto)
-{
- if (TREE_CODE (proto) != TYPE_DECL)
- {
- error ("invalid use of non-type concept %qD", fn);
- return false;
- }
- return true;
-}
-
/* Check if DECL and ARGS can form a constrained-type-specifier.
If ARGS is non-null, we try to form a concept check of the
form DECL<?, ARGS> where ? is a wildcard that matches any
@@ -16009,13 +16008,6 @@ cp_parser_maybe_constrained_type_specifier (cp_parser *parser,
if (processing_template_parmlist)
return build_constrained_parameter (conc, proto, args);
- /* In any other context, a concept must be a type concept.
-
- FIXME: A constrained-type-specifier can be a placeholder
- of any kind. */
- if (!check_type_concept (conc, proto))
- return error_mark_node;
-
/* In a parameter-declaration-clause, constrained-type
specifiers result in invented template parameters. */
if (parser->auto_is_implicit_function_template_parm_p)
@@ -16046,7 +16038,13 @@ cp_parser_maybe_constrained_type_specifier (cp_parser *parser,
static tree
cp_parser_maybe_concept_name (cp_parser* parser, tree decl)
{
- return cp_parser_maybe_constrained_type_specifier (parser, decl, NULL_TREE);
+ if (flag_concepts
+ && (TREE_CODE (decl) == OVERLOAD
+ || BASELINK_P (decl)
+ || variable_concept_p (decl)))
+ return cp_parser_maybe_constrained_type_specifier (parser, decl, NULL_TREE);
+ else
+ return NULL_TREE;
}
/* Check if DECL and ARGS form a partial-concept-id. If so,
@@ -16093,15 +16091,8 @@ cp_parser_nonclass_name (cp_parser* parser)
type_decl = strip_using_decl (type_decl);
/* If we found an overload set, then it may refer to a concept-name. */
- if (flag_concepts
- && (TREE_CODE (type_decl) == OVERLOAD
- || BASELINK_P (type_decl)
- || variable_concept_p (type_decl)))
- {
- /* Determine whether the overload refers to a concept. */
- if (tree decl = cp_parser_maybe_concept_name (parser, type_decl))
- return decl;
- }
+ if (tree decl = cp_parser_maybe_concept_name (parser, type_decl))
+ type_decl = decl;
if (TREE_CODE (type_decl) != TYPE_DECL
&& (objc_is_id (identifier) || objc_is_class_name (identifier)))
@@ -18183,7 +18174,7 @@ cp_parser_init_declarator (cp_parser* parser,
"attributes after parenthesized initializer ignored");
/* And now complain about a non-function implicit template. */
- if (bogus_implicit_tmpl)
+ if (bogus_implicit_tmpl && decl != error_mark_node)
error_at (DECL_SOURCE_LOCATION (decl),
"non-function %qD declared as implicit template", decl);
@@ -36681,17 +36672,6 @@ tree_type_is_auto_or_concept (const_tree t)
return TREE_TYPE (t) && is_auto_or_concept (TREE_TYPE (t));
}
-/* Returns the template declaration being called or evaluated as
- part of the constraint check. Note that T must be a predicate
- constraint (it can't be any other kind of constraint). */
-static tree
-get_concept_from_constraint (tree t)
-{
- tree tmpl, args;
- placeholder_extract_concept_and_args (t, tmpl, args);
- return DECL_TEMPLATE_RESULT (tmpl);
-}
-
/* Add an implicit template type parameter to the CURRENT_TEMPLATE_PARMS
(creating a new template parameter list if necessary). Returns the newly
created template type parm. */
@@ -36711,9 +36691,14 @@ synthesize_implicit_template_parm (cp_parser *parser, tree constr)
tree t = parser->implicit_template_parms;
while (t)
{
- tree c = get_concept_from_constraint (TREE_TYPE (t));
- if (c == CONSTRAINED_PARM_CONCEPT (constr))
- return TREE_VALUE (t);
+ if (equivalent_placeholder_constraints (TREE_TYPE (t), constr))
+ {
+ tree d = TREE_VALUE (t);
+ if (TREE_CODE (d) == PARM_DECL)
+ /* Return the TEMPLATE_PARM_INDEX. */
+ d = DECL_INITIAL (d);
+ return d;
+ }
t = TREE_CHAIN (t);
}
}
@@ -36823,9 +36808,23 @@ synthesize_implicit_template_parm (cp_parser *parser, tree constr)
/* Synthesize a new template parameter and track the current template
parameter chain with implicit_template_parms. */
+ tree proto = constr ? DECL_INITIAL (constr) : NULL_TREE;
tree synth_id = make_generic_type_name ();
- tree synth_tmpl_parm = finish_template_type_parm (class_type_node,
- synth_id);
+ tree synth_tmpl_parm;
+ bool non_type = false;
+
+ if (proto == NULL_TREE || TREE_CODE (proto) == TYPE_DECL)
+ synth_tmpl_parm
+ = finish_template_type_parm (class_type_node, synth_id);
+ else if (TREE_CODE (proto) == TEMPLATE_DECL)
+ synth_tmpl_parm
+ = finish_constrained_template_template_parm (proto, synth_id);
+ else
+ {
+ synth_tmpl_parm = copy_decl (proto);
+ DECL_NAME (synth_tmpl_parm) = synth_id;
+ non_type = true;
+ }
// Attach the constraint to the parm before processing.
tree node = build_tree_list (NULL_TREE, synth_tmpl_parm);
@@ -36834,7 +36833,7 @@ synthesize_implicit_template_parm (cp_parser *parser, tree constr)
= process_template_parm (parser->implicit_template_parms,
input_location,
node,
- /*non_type=*/false,
+ /*non_type=*/non_type,
/*param_pack=*/false);
// Chain the new parameter to the list of implicit parameters.
@@ -36844,7 +36843,10 @@ synthesize_implicit_template_parm (cp_parser *parser, tree constr)
else
parser->implicit_template_parms = new_parm;
- tree new_type = TREE_TYPE (getdecls ());
+ tree new_decl = getdecls ();
+ if (non_type)
+ /* Return the TEMPLATE_PARM_INDEX, not the PARM_DECL. */
+ new_decl = DECL_INITIAL (new_decl);
/* If creating a fully implicit function template, start the new implicit
template parameter list with this synthesized type, otherwise grow the
@@ -36878,7 +36880,7 @@ synthesize_implicit_template_parm (cp_parser *parser, tree constr)
current_binding_level = entry_scope;
- return new_type;
+ return new_decl;
}
/* Finish the declaration of a fully implicit function template. Such a
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 45eda3a6d72..bfea8e20257 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -441,21 +441,8 @@ push_inline_template_parms_recursive (tree parmlist, int levels)
break;
case PARM_DECL:
- {
- /* Make a CONST_DECL as is done in process_template_parm.
- It is ugly that we recreate this here; the original
- version built in process_template_parm is no longer
- available. */
- tree decl = build_decl (DECL_SOURCE_LOCATION (parm),
- CONST_DECL, DECL_NAME (parm),
- TREE_TYPE (parm));
- DECL_ARTIFICIAL (decl) = 1;
- TREE_CONSTANT (decl) = 1;
- TREE_READONLY (decl) = 1;
- DECL_INITIAL (decl) = DECL_INITIAL (parm);
- SET_DECL_TEMPLATE_PARM_P (decl);
- pushdecl (decl);
- }
+ /* Push the CONST_DECL. */
+ pushdecl (TEMPLATE_PARM_DECL (DECL_INITIAL (parm)));
break;
default:
diff --git a/gcc/cselib.c b/gcc/cselib.c
index 4fc70971881..8d73f15aa11 100644
--- a/gcc/cselib.c
+++ b/gcc/cselib.c
@@ -1329,15 +1329,15 @@ new_cselib_val (unsigned int hash, machine_mode mode, rtx x)
static void
add_mem_for_addr (cselib_val *addr_elt, cselib_val *mem_elt, rtx x)
{
- struct elt_loc_list *l;
-
addr_elt = canonical_cselib_val (addr_elt);
mem_elt = canonical_cselib_val (mem_elt);
/* Avoid duplicates. */
- for (l = mem_elt->locs; l; l = l->next)
+ addr_space_t as = MEM_ADDR_SPACE (x);
+ for (elt_loc_list *l = mem_elt->locs; l; l = l->next)
if (MEM_P (l->loc)
- && CSELIB_VAL_PTR (XEXP (l->loc, 0)) == addr_elt)
+ && CSELIB_VAL_PTR (XEXP (l->loc, 0)) == addr_elt
+ && MEM_ADDR_SPACE (l->loc) == as)
{
promote_debug_loc (l);
return;
@@ -1364,7 +1364,6 @@ cselib_lookup_mem (rtx x, int create)
cselib_val **slot;
cselib_val *addr;
cselib_val *mem_elt;
- struct elt_list *l;
if (MEM_VOLATILE_P (x) || mode == BLKmode
|| !cselib_record_memory
@@ -1379,14 +1378,19 @@ cselib_lookup_mem (rtx x, int create)
addr = cselib_lookup (XEXP (x, 0), addr_mode, create, mode);
if (! addr)
return 0;
-
addr = canonical_cselib_val (addr);
+
/* Find a value that describes a value of our mode at that address. */
- for (l = addr->addr_list; l; l = l->next)
+ addr_space_t as = MEM_ADDR_SPACE (x);
+ for (elt_list *l = addr->addr_list; l; l = l->next)
if (GET_MODE (l->elt->val_rtx) == mode)
{
- promote_debug_loc (l->elt->locs);
- return l->elt;
+ for (elt_loc_list *l2 = l->elt->locs; l2; l2 = l2->next)
+ if (MEM_P (l2->loc) && MEM_ADDR_SPACE (l2->loc) == as)
+ {
+ promote_debug_loc (l->elt->locs);
+ return l->elt;
+ }
}
if (! create)
diff --git a/gcc/dbxout.c b/gcc/dbxout.c
index c13c68a4eb8..1b4a5eaeb6d 100644
--- a/gcc/dbxout.c
+++ b/gcc/dbxout.c
@@ -2479,11 +2479,11 @@ dbxout_expand_expr (tree expr)
machine_mode mode;
HOST_WIDE_INT bitsize, bitpos;
tree offset, tem;
- int volatilep = 0, unsignedp = 0;
+ int unsignedp, reversep, volatilep = 0;
rtx x;
- tem = get_inner_reference (expr, &bitsize, &bitpos, &offset,
- &mode, &unsignedp, &volatilep, true);
+ tem = get_inner_reference (expr, &bitsize, &bitpos, &offset, &mode,
+ &unsignedp, &reversep, &volatilep, true);
x = dbxout_expand_expr (tem);
if (x == NULL || !MEM_P (x))
diff --git a/gcc/diagnostic-color.c b/gcc/diagnostic-color.c
index 3fe49b2be47..d848dfca52e 100644
--- a/gcc/diagnostic-color.c
+++ b/gcc/diagnostic-color.c
@@ -164,7 +164,8 @@ static struct color_cap color_dict[] =
{ "warning", SGR_SEQ (COLOR_BOLD COLOR_SEPARATOR COLOR_FG_MAGENTA),
7, false },
{ "note", SGR_SEQ (COLOR_BOLD COLOR_SEPARATOR COLOR_FG_CYAN), 4, false },
- { "caret", SGR_SEQ (COLOR_BOLD COLOR_SEPARATOR COLOR_FG_GREEN), 5, false },
+ { "range1", SGR_SEQ (COLOR_FG_GREEN), 6, false },
+ { "range2", SGR_SEQ (COLOR_FG_BLUE), 6, false },
{ "locus", SGR_SEQ (COLOR_BOLD), 5, false },
{ "quote", SGR_SEQ (COLOR_BOLD), 5, false },
{ NULL, NULL, 0, false }
@@ -195,7 +196,7 @@ colorize_stop (bool show_color)
}
/* Parse GCC_COLORS. The default would look like:
- GCC_COLORS='error=01;31:warning=01;35:note=01;36:caret=01;32:locus=01:quote=01'
+ GCC_COLORS='error=01;31:warning=01;35:note=01;36:range1=32:range2=34;locus=01:quote=01'
No character escaping is needed or supported. */
static bool
parse_gcc_colors (void)
diff --git a/gcc/diagnostic-core.h b/gcc/diagnostic-core.h
index 6cc1e6b3ee5..749c847c9ce 100644
--- a/gcc/diagnostic-core.h
+++ b/gcc/diagnostic-core.h
@@ -63,18 +63,26 @@ extern bool warning_n (location_t, int, int, const char *, const char *, ...)
ATTRIBUTE_GCC_DIAG(4,6) ATTRIBUTE_GCC_DIAG(5,6);
extern bool warning_at (location_t, int, const char *, ...)
ATTRIBUTE_GCC_DIAG(3,4);
+extern bool warning_at_rich_loc (rich_location *, int, const char *, ...)
+ ATTRIBUTE_GCC_DIAG(3,4);
extern void error (const char *, ...) ATTRIBUTE_GCC_DIAG(1,2);
extern void error_n (location_t, int, const char *, const char *, ...)
ATTRIBUTE_GCC_DIAG(3,5) ATTRIBUTE_GCC_DIAG(4,5);
extern void error_at (location_t, const char *, ...) ATTRIBUTE_GCC_DIAG(2,3);
+extern void error_at_rich_loc (rich_location *, const char *, ...)
+ ATTRIBUTE_GCC_DIAG(2,3);
extern void fatal_error (location_t, const char *, ...) ATTRIBUTE_GCC_DIAG(2,3)
ATTRIBUTE_NORETURN;
/* Pass one of the OPT_W* from options.h as the second parameter. */
extern bool pedwarn (location_t, int, const char *, ...)
ATTRIBUTE_GCC_DIAG(3,4);
extern bool permerror (location_t, const char *, ...) ATTRIBUTE_GCC_DIAG(2,3);
+extern bool permerror_at_rich_loc (rich_location *, const char *,
+ ...) ATTRIBUTE_GCC_DIAG(2,3);
extern void sorry (const char *, ...) ATTRIBUTE_GCC_DIAG(1,2);
extern void inform (location_t, const char *, ...) ATTRIBUTE_GCC_DIAG(2,3);
+extern void inform_at_rich_loc (rich_location *, const char *,
+ ...) ATTRIBUTE_GCC_DIAG(2,3);
extern void inform_n (location_t, int, const char *, const char *, ...)
ATTRIBUTE_GCC_DIAG(3,5) ATTRIBUTE_GCC_DIAG(4,5);
extern void verbatim (const char *, ...) ATTRIBUTE_GCC_DIAG(1,2);
diff --git a/gcc/diagnostic-show-locus.c b/gcc/diagnostic-show-locus.c
index 147a2b8b71d..22203cdbaa3 100644
--- a/gcc/diagnostic-show-locus.c
+++ b/gcc/diagnostic-show-locus.c
@@ -36,131 +36,686 @@ along with GCC; see the file COPYING3. If not see
# include <sys/ioctl.h>
#endif
-/* If LINE is longer than MAX_WIDTH, and COLUMN is not smaller than
- MAX_WIDTH by some margin, then adjust the start of the line such
- that the COLUMN is smaller than MAX_WIDTH minus the margin. The
- margin is either CARET_LINE_MARGIN characters or the difference
- between the column and the length of the line, whatever is smaller.
- The length of LINE is given by LINE_WIDTH. */
-static const char *
-adjust_line (const char *line, int line_width,
- int max_width, int *column_p)
-{
- int right_margin = CARET_LINE_MARGIN;
- int column = *column_p;
-
- gcc_checking_assert (line_width >= column);
- right_margin = MIN (line_width - column, right_margin);
- right_margin = max_width - right_margin;
- if (line_width >= max_width && column > right_margin)
+/* Classes for rendering source code and diagnostics, within an
+ anonymous namespace.
+ The work is done by "class layout", which embeds and uses
+ "class colorizer" and "class layout_range" to get things done. */
+
+namespace {
+
+/* The state at a given point of the source code, assuming that we're
+ in a range: which range are we in, and whether we should draw a caret at
+ this point. */
+
+struct point_state
+{
+ int range_idx;
+ bool draw_caret_p;
+};
+
+/* A class to inject colorization codes when printing the diagnostic locus.
+
+ It has one kind of colorization for each of:
+ - normal text
+ - range 0 (the "primary location")
+ - range 1
+ - range 2
+
+ The class caches the lookup of the color codes for the above.
+
+ The class also has responsibility for tracking which of the above is
+ active, filtering out unnecessary changes. This allows
+ layout::print_source_line and layout::print_annotation_line
+ to simply request a colorization code for *every* character they print,
+ via this class, and have the filtering be done for them here. */
+
+class colorizer
+{
+ public:
+ colorizer (diagnostic_context *context,
+ const diagnostic_info *diagnostic);
+ ~colorizer ();
+
+ void set_range (int range_idx) { set_state (range_idx); }
+ void set_normal_text () { set_state (STATE_NORMAL_TEXT); }
+
+ private:
+ void set_state (int state);
+ void begin_state (int state);
+ void finish_state (int state);
+
+ private:
+ static const int STATE_NORMAL_TEXT = -1;
+
+ diagnostic_context *m_context;
+ const diagnostic_info *m_diagnostic;
+ int m_current_state;
+ const char *m_caret_cs;
+ const char *m_caret_ce;
+ const char *m_range1_cs;
+ const char *m_range2_cs;
+ const char *m_range_ce;
+};
+
+/* A point within a layout_range; similar to an expanded_location,
+ but after filtering on file. */
+
+class layout_point
+{
+ public:
+ layout_point (const expanded_location &exploc)
+ : m_line (exploc.line),
+ m_column (exploc.column) {}
+
+ int m_line;
+ int m_column;
+};
+
+/* A class for use by "class layout" below: a filtered location_range. */
+
+class layout_range
+{
+ public:
+ layout_range (const location_range *loc_range);
+
+ bool contains_point (int row, int column) const;
+
+ layout_point m_start;
+ layout_point m_finish;
+ bool m_show_caret_p;
+ layout_point m_caret;
+};
+
+/* A struct for use by layout::print_source_line for telling
+ layout::print_annotation_line the extents of the source line that
+ it printed, so that underlines can be clipped appropriately. */
+
+struct line_bounds
+{
+ int m_first_non_ws;
+ int m_last_non_ws;
+};
+
+/* A class to control the overall layout when printing a diagnostic.
+
+ The layout is determined within the constructor.
+ It is then printed by repeatedly calling the "print_source_line"
+ and "print_annotation_line" methods.
+
+ We assume we have disjoint ranges. */
+
+class layout
+{
+ public:
+ layout (diagnostic_context *context,
+ const diagnostic_info *diagnostic);
+
+ int get_first_line () const { return m_first_line; }
+ int get_last_line () const { return m_last_line; }
+
+ bool print_source_line (int row, line_bounds *lbounds_out);
+ void print_annotation_line (int row, const line_bounds lbounds);
+
+ private:
+ bool
+ get_state_at_point (/* Inputs. */
+ int row, int column,
+ int first_non_ws, int last_non_ws,
+ /* Outputs. */
+ point_state *out_state);
+
+ int
+ get_x_bound_for_row (int row, int caret_column,
+ int last_non_ws);
+
+ private:
+ diagnostic_context *m_context;
+ pretty_printer *m_pp;
+ diagnostic_t m_diagnostic_kind;
+ expanded_location m_exploc;
+ colorizer m_colorizer;
+ bool m_colorize_source_p;
+ auto_vec <layout_range> m_layout_ranges;
+ int m_first_line;
+ int m_last_line;
+ int m_x_offset;
+};
+
+/* Implementation of "class colorizer". */
+
+/* The constructor for "colorizer". Lookup and store color codes for the
+ different kinds of things we might need to print. */
+
+colorizer::colorizer (diagnostic_context *context,
+ const diagnostic_info *diagnostic) :
+ m_context (context),
+ m_diagnostic (diagnostic),
+ m_current_state (STATE_NORMAL_TEXT)
+{
+ m_caret_ce = colorize_stop (pp_show_color (context->printer));
+ m_range1_cs = colorize_start (pp_show_color (context->printer), "range1");
+ m_range2_cs = colorize_start (pp_show_color (context->printer), "range2");
+ m_range_ce = colorize_stop (pp_show_color (context->printer));
+}
+
+/* The destructor for "colorize". If colorization is on, print a code to
+ turn it off. */
+
+colorizer::~colorizer ()
+{
+ finish_state (m_current_state);
+}
+
+/* Update state, printing color codes if necessary if there's a state
+ change. */
+
+void
+colorizer::set_state (int new_state)
+{
+ if (m_current_state != new_state)
{
- line += column - right_margin;
- *column_p = right_margin;
+ finish_state (m_current_state);
+ m_current_state = new_state;
+ begin_state (new_state);
}
- return line;
}
-/* Print the physical source line corresponding to the location of
- this diagnostic, and a caret indicating the precise column. This
- function only prints two caret characters if the two locations
- given by DIAGNOSTIC are on the same line according to
- diagnostic_same_line(). */
+/* Turn on any colorization for STATE. */
+
void
-diagnostic_show_locus (diagnostic_context * context,
- const diagnostic_info *diagnostic)
+colorizer::begin_state (int state)
{
- if (!context->show_caret
- || diagnostic_location (diagnostic, 0) <= BUILTINS_LOCATION
- || diagnostic_location (diagnostic, 0) == context->last_location)
- return;
+ switch (state)
+ {
+ case STATE_NORMAL_TEXT:
+ break;
- context->last_location = diagnostic_location (diagnostic, 0);
- expanded_location s0 = diagnostic_expand_location (diagnostic, 0);
- expanded_location s1 = { };
- /* Zero-initialized. This is checked later by diagnostic_print_caret_line. */
+ case 0:
+ /* Make range 0 be the same color as the "kind" text
+ (error vs warning vs note). */
+ pp_string
+ (m_context->printer,
+ colorize_start (pp_show_color (m_context->printer),
+ diagnostic_get_color_for_kind (m_diagnostic->kind)));
+ break;
- if (diagnostic_location (diagnostic, 1) > BUILTINS_LOCATION)
- s1 = diagnostic_expand_location (diagnostic, 1);
+ case 1:
+ pp_string (m_context->printer, m_range1_cs);
+ break;
- diagnostic_print_caret_line (context, s0, s1,
- context->caret_chars[0],
- context->caret_chars[1]);
+ case 2:
+ pp_string (m_context->printer, m_range2_cs);
+ break;
+
+ default:
+ /* We don't expect more than 3 ranges per diagnostic. */
+ gcc_unreachable ();
+ break;
+ }
}
-/* Print (part) of the source line given by xloc1 with caret1 pointing
- at the column. If xloc2.column != 0 and it fits within the same
- line as xloc1 according to diagnostic_same_line (), then caret2 is
- printed at xloc2.colum. Otherwise, the caller has to set up things
- to print a second caret line for xloc2. */
+/* Turn off any colorization for STATE. */
+
void
-diagnostic_print_caret_line (diagnostic_context * context,
- expanded_location xloc1,
- expanded_location xloc2,
- char caret1, char caret2)
-{
- if (!diagnostic_same_line (context, xloc1, xloc2))
- /* This will mean ignore xloc2. */
- xloc2.column = 0;
- else if (xloc1.column == xloc2.column)
- xloc2.column++;
-
- int cmax = MAX (xloc1.column, xloc2.column);
+colorizer::finish_state (int state)
+{
+ switch (state)
+ {
+ case STATE_NORMAL_TEXT:
+ break;
+
+ case 0:
+ pp_string (m_context->printer, m_caret_ce);
+ break;
+
+ default:
+ /* Within a range. */
+ gcc_assert (state > 0);
+ pp_string (m_context->printer, m_range_ce);
+ break;
+ }
+}
+
+/* Implementation of class layout_range. */
+
+/* The constructor for class layout_range.
+ Initialize various layout_point fields from expanded_location
+ equivalents; we've already filtered on file. */
+
+layout_range::layout_range (const location_range *loc_range)
+: m_start (loc_range->m_start),
+ m_finish (loc_range->m_finish),
+ m_show_caret_p (loc_range->m_show_caret_p),
+ m_caret (loc_range->m_caret)
+{
+}
+
+/* Is (column, row) within the given range?
+ We've already filtered on the file.
+
+ Ranges are closed (both limits are within the range).
+
+ Example A: a single-line range:
+ start: (col=22, line=2)
+ finish: (col=38, line=2)
+
+ |00000011111111112222222222333333333344444444444
+ |34567890123456789012345678901234567890123456789
+--+-----------------------------------------------
+01|bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
+02|bbbbbbbbbbbbbbbbbbbSwwwwwwwwwwwwwwwFaaaaaaaaaaa
+03|aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+
+ Example B: a multiline range with
+ start: (col=14, line=3)
+ finish: (col=08, line=5)
+
+ |00000011111111112222222222333333333344444444444
+ |34567890123456789012345678901234567890123456789
+--+-----------------------------------------------
+01|bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
+02|bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
+03|bbbbbbbbbbbSwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww
+04|wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww
+05|wwwwwFaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+06|aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+--+-----------------------------------------------
+
+ Legend:
+ - 'b' indicates a point *before* the range
+ - 'S' indicates the start of the range
+ - 'w' indicates a point within the range
+ - 'F' indicates the finish of the range (which is
+ within it).
+ - 'a' indicates a subsequent point *after* the range. */
+
+bool
+layout_range::contains_point (int row, int column) const
+{
+ gcc_assert (m_start.m_line <= m_finish.m_line);
+ /* ...but the equivalent isn't true for the columns;
+ consider example B in the comment above. */
+
+ if (row < m_start.m_line)
+ /* Points before the first line of the range are
+ outside it (corresponding to line 01 in example A
+ and lines 01 and 02 in example B above). */
+ return false;
+
+ if (row == m_start.m_line)
+ /* On same line as start of range (corresponding
+ to line 02 in example A and line 03 in example B). */
+ {
+ if (column < m_start.m_column)
+ /* Points on the starting line of the range, but
+ before the column in which it begins. */
+ return false;
+
+ if (row < m_finish.m_line)
+ /* This is a multiline range; the point
+ is within it (corresponds to line 03 in example B
+ from column 14 onwards) */
+ return true;
+ else
+ {
+ /* This is a single-line range. */
+ gcc_assert (row == m_finish.m_line);
+ return column <= m_finish.m_column;
+ }
+ }
+
+ /* The point is in a line beyond that containing the
+ start of the range: lines 03 onwards in example A,
+ and lines 04 onwards in example B. */
+ gcc_assert (row > m_start.m_line);
+
+ if (row > m_finish.m_line)
+ /* The point is beyond the final line of the range
+ (lines 03 onwards in example A, and lines 06 onwards
+ in example B). */
+ return false;
+
+ if (row < m_finish.m_line)
+ {
+ /* The point is in a line that's fully within a multiline
+ range (e.g. line 04 in example B). */
+ gcc_assert (m_start.m_line < m_finish.m_line);
+ return true;
+ }
+
+ gcc_assert (row == m_finish.m_line);
+
+ return column <= m_finish.m_column;
+}
+
+/* Given a source line LINE of length LINE_WIDTH, determine the width
+ without any trailing whitespace. */
+
+static int
+get_line_width_without_trailing_whitespace (const char *line, int line_width)
+{
+ int result = line_width;
+ while (result > 0)
+ {
+ char ch = line[result - 1];
+ if (ch == ' ' || ch == '\t')
+ result--;
+ else
+ break;
+ }
+ gcc_assert (result >= 0);
+ gcc_assert (result <= line_width);
+ gcc_assert (result == 0 ||
+ (line[result - 1] != ' '
+ && line[result -1] != '\t'));
+ return result;
+}
+
+/* Implementation of class layout. */
+
+/* Constructor for class layout.
+
+ Filter the ranges from the rich_location to those that we can
+ sanely print, populating m_layout_ranges.
+ Determine the range of lines that we will print.
+ Determine m_x_offset, to ensure that the primary caret
+ will fit within the max_width provided by the diagnostic_context. */
+
+layout::layout (diagnostic_context * context,
+ const diagnostic_info *diagnostic)
+: m_context (context),
+ m_pp (context->printer),
+ m_diagnostic_kind (diagnostic->kind),
+ m_exploc (diagnostic->richloc->lazily_expand_location ()),
+ m_colorizer (context, diagnostic),
+ m_colorize_source_p (context->colorize_source_p),
+ m_layout_ranges (rich_location::MAX_RANGES),
+ m_first_line (m_exploc.line),
+ m_last_line (m_exploc.line),
+ m_x_offset (0)
+{
+ rich_location *richloc = diagnostic->richloc;
+ for (unsigned int idx = 0; idx < richloc->get_num_locations (); idx++)
+ {
+ /* This diagnostic printer can only cope with "sufficiently sane" ranges.
+ Ignore any ranges that are awkward to handle. */
+ location_range *loc_range = richloc->get_range (idx);
+
+ /* If any part of the range isn't in the same file as the primary
+ location of this diagnostic, ignore the range. */
+ if (loc_range->m_start.file != m_exploc.file)
+ continue;
+ if (loc_range->m_finish.file != m_exploc.file)
+ continue;
+ if (loc_range->m_show_caret_p)
+ if (loc_range->m_caret.file != m_exploc.file)
+ continue;
+
+ /* Passed all the tests; add the range to m_layout_ranges so that
+ it will be printed. */
+ layout_range ri (loc_range);
+ m_layout_ranges.safe_push (ri);
+
+ /* Update m_first_line/m_last_line if necessary. */
+ if (loc_range->m_start.line < m_first_line)
+ m_first_line = loc_range->m_start.line;
+ if (loc_range->m_finish.line > m_last_line)
+ m_last_line = loc_range->m_finish.line;
+ }
+
+ /* Adjust m_x_offset.
+ Center the primary caret to fit in max_width; all columns
+ will be adjusted accordingly. */
+ int max_width = m_context->caret_max_width;
int line_width;
- const char *line = location_get_source_line (xloc1.file, xloc1.line,
+ const char *line = location_get_source_line (m_exploc.file, m_exploc.line,
&line_width);
- if (line == NULL || cmax > line_width)
- return;
+ if (line && m_exploc.column <= line_width)
+ {
+ int right_margin = CARET_LINE_MARGIN;
+ int column = m_exploc.column;
+ right_margin = MIN (line_width - column, right_margin);
+ right_margin = max_width - right_margin;
+ if (line_width >= max_width && column > right_margin)
+ m_x_offset = column - right_margin;
+ gcc_assert (m_x_offset >= 0);
+ }
+}
- /* Center the interesting part of the source line to fit in
- max_width, and adjust all columns accordingly. */
- int max_width = context->caret_max_width;
- int offset = (int) cmax;
- line = adjust_line (line, line_width, max_width, &offset);
- offset -= cmax;
- cmax += offset;
- xloc1.column += offset;
- if (xloc2.column)
- xloc2.column += offset;
-
- /* Print the source line. */
- pp_newline (context->printer);
- const char *saved_prefix = pp_get_prefix (context->printer);
- pp_set_prefix (context->printer, NULL);
- pp_space (context->printer);
- while (max_width > 0 && line_width > 0)
+/* Attempt to print line ROW of source code, potentially colorized at any
+ ranges.
+ Return true if the line was printed, populating *LBOUNDS_OUT.
+ Return false if the source line could not be read, leaving *LBOUNDS_OUT
+ untouched. */
+
+bool
+layout::print_source_line (int row, line_bounds *lbounds_out)
+{
+ int line_width;
+ const char *line = location_get_source_line (m_exploc.file, row,
+ &line_width);
+ if (!line)
+ return false;
+
+ line += m_x_offset;
+
+ m_colorizer.set_normal_text ();
+
+ /* We will stop printing the source line at any trailing
+ whitespace. */
+ line_width = get_line_width_without_trailing_whitespace (line,
+ line_width);
+
+ pp_space (m_pp);
+ int first_non_ws = INT_MAX;
+ int last_non_ws = 0;
+ int column;
+ for (column = 1 + m_x_offset; column <= line_width; column++)
{
+ /* Assuming colorization is enabled for the caret and underline
+ characters, we may also colorize the associated characters
+ within the source line.
+
+ For frontends that generate range information, we color the
+ associated characters in the source line the same as the
+ carets and underlines in the annotation line, to make it easier
+ for the reader to see the pertinent code.
+
+ For frontends that only generate carets, we don't colorize the
+ characters above them, since this would look strange (e.g.
+ colorizing just the first character in a token). */
+ if (m_colorize_source_p)
+ {
+ bool in_range_p;
+ point_state state;
+ in_range_p = get_state_at_point (row, column,
+ 0, INT_MAX,
+ &state);
+ if (in_range_p)
+ m_colorizer.set_range (state.range_idx);
+ else
+ m_colorizer.set_normal_text ();
+ }
char c = *line == '\t' ? ' ' : *line;
if (c == '\0')
c = ' ';
- pp_character (context->printer, c);
- max_width--;
- line_width--;
+ if (c != ' ')
+ {
+ last_non_ws = column;
+ if (first_non_ws == INT_MAX)
+ first_non_ws = column;
+ }
+ pp_character (m_pp, c);
line++;
}
- pp_newline (context->printer);
+ pp_newline (m_pp);
+
+ lbounds_out->m_first_non_ws = first_non_ws;
+ lbounds_out->m_last_non_ws = last_non_ws;
+ return true;
+}
+
+/* Print a line consisting of the caret/underlines for the given
+ source line. */
- /* Print the caret under the line. */
- const char *caret_cs, *caret_ce;
- caret_cs = colorize_start (pp_show_color (context->printer), "caret");
- caret_ce = colorize_stop (pp_show_color (context->printer));
- int cmin = xloc2.column
- ? MIN (xloc1.column, xloc2.column) : xloc1.column;
- int caret_min = cmin == xloc1.column ? caret1 : caret2;
- int caret_max = cmin == xloc1.column ? caret2 : caret1;
-
- /* cmin is >= 1, but we indent with an extra space at the start like
- we did above. */
+void
+layout::print_annotation_line (int row, const line_bounds lbounds)
+{
+ int x_bound = get_x_bound_for_row (row, m_exploc.column,
+ lbounds.m_last_non_ws);
+
+ pp_space (m_pp);
+ for (int column = 1 + m_x_offset; column < x_bound; column++)
+ {
+ bool in_range_p;
+ point_state state;
+ in_range_p = get_state_at_point (row, column,
+ lbounds.m_first_non_ws,
+ lbounds.m_last_non_ws,
+ &state);
+ if (in_range_p)
+ {
+ /* Within a range. Draw either the caret or an underline. */
+ m_colorizer.set_range (state.range_idx);
+ if (state.draw_caret_p)
+ /* Draw the caret. */
+ pp_character (m_pp, m_context->caret_chars[state.range_idx]);
+ else
+ pp_character (m_pp, '~');
+ }
+ else
+ {
+ /* Not in a range. */
+ m_colorizer.set_normal_text ();
+ pp_character (m_pp, ' ');
+ }
+ }
+ pp_newline (m_pp);
+}
+
+/* Return true if (ROW/COLUMN) is within a range of the layout.
+ If it returns true, OUT_STATE is written to, with the
+ range index, and whether we should draw the caret at
+ (ROW/COLUMN) (as opposed to an underline). */
+
+bool
+layout::get_state_at_point (/* Inputs. */
+ int row, int column,
+ int first_non_ws, int last_non_ws,
+ /* Outputs. */
+ point_state *out_state)
+{
+ layout_range *range;
int i;
- for (i = 0; i < cmin; i++)
- pp_space (context->printer);
- pp_printf (context->printer, "%s%c%s", caret_cs, caret_min, caret_ce);
+ FOR_EACH_VEC_ELT (m_layout_ranges, i, range)
+ {
+ if (range->contains_point (row, column))
+ {
+ out_state->range_idx = i;
+
+ /* Are we at the range's caret? is it visible? */
+ out_state->draw_caret_p = false;
+ if (row == range->m_caret.m_line
+ && column == range->m_caret.m_column)
+ out_state->draw_caret_p = range->m_show_caret_p;
- if (xloc2.column)
+ /* Within a multiline range, don't display any underline
+ in any leading or trailing whitespace on a line.
+ We do display carets, however. */
+ if (!out_state->draw_caret_p)
+ if (column < first_non_ws || column > last_non_ws)
+ return false;
+
+ /* We are within a range. */
+ return true;
+ }
+ }
+
+ return false;
+}
+
+/* Helper function for use by layout::print_line when printing the
+ annotation line under the source line.
+ Get the column beyond the rightmost one that could contain a caret or
+ range marker, given that we stop rendering at trailing whitespace.
+ ROW is the source line within the given file.
+ CARET_COLUMN is the column of range 0's caret.
+ LAST_NON_WS_COLUMN is the last column containing a non-whitespace
+ character of source (as determined when printing the source line). */
+
+int
+layout::get_x_bound_for_row (int row, int caret_column,
+ int last_non_ws_column)
+{
+ int result = caret_column + 1;
+
+ layout_range *range;
+ int i;
+ FOR_EACH_VEC_ELT (m_layout_ranges, i, range)
{
- for (i++; i < cmax; i++)
- pp_space (context->printer);
- pp_printf (context->printer, "%s%c%s", caret_cs, caret_max, caret_ce);
+ if (row >= range->m_start.m_line)
+ {
+ if (range->m_finish.m_line == row)
+ {
+ /* On the final line within a range; ensure that
+ we render up to the end of the range. */
+ if (result <= range->m_finish.m_column)
+ result = range->m_finish.m_column + 1;
+ }
+ else if (row < range->m_finish.m_line)
+ {
+ /* Within a multiline range; ensure that we render up to the
+ last non-whitespace column. */
+ if (result <= last_non_ws_column)
+ result = last_non_ws_column + 1;
+ }
+ }
}
+
+ return result;
+}
+
+} /* End of anonymous namespace. */
+
+/* Print the physical source code corresponding to the location of
+ this diagnostic, with additional annotations. */
+
+void
+diagnostic_show_locus (diagnostic_context * context,
+ const diagnostic_info *diagnostic)
+{
+ if (!context->show_caret
+ || diagnostic_location (diagnostic, 0) <= BUILTINS_LOCATION
+ || diagnostic_location (diagnostic, 0) == context->last_location)
+ return;
+
+ context->last_location = diagnostic_location (diagnostic, 0);
+
+ pp_newline (context->printer);
+
+ const char *saved_prefix = pp_get_prefix (context->printer);
+ pp_set_prefix (context->printer, NULL);
+
+ {
+ layout layout (context, diagnostic);
+ int last_line = layout.get_last_line ();
+ for (int row = layout.get_first_line ();
+ row <= last_line;
+ row++)
+ {
+ /* Print the source line, followed by an annotation line
+ consisting of any caret/underlines. If the source line can't
+ be read, print nothing. */
+ line_bounds lbounds;
+ if (layout.print_source_line (row, &lbounds))
+ layout.print_annotation_line (row, lbounds);
+ }
+
+ /* The closing scope here leads to the dtor for layout and thus
+ colorizer being called here, which affects the precise
+ place where colorization is turned off in the unittest
+ for colorized output. */
+ }
+
pp_set_prefix (context->printer, saved_prefix);
- pp_needs_newline (context->printer) = true;
}
diff --git a/gcc/diagnostic.c b/gcc/diagnostic.c
index 11c369d8292..ee034e77170 100644
--- a/gcc/diagnostic.c
+++ b/gcc/diagnostic.c
@@ -144,7 +144,7 @@ diagnostic_initialize (diagnostic_context *context, int n_opts)
context->classify_diagnostic[i] = DK_UNSPECIFIED;
context->show_caret = false;
diagnostic_set_caret_max_width (context, pp_line_cutoff (context->printer));
- for (i = 0; i < MAX_LOCATIONS_PER_MESSAGE; i++)
+ for (i = 0; i < rich_location::MAX_RANGES; i++)
context->caret_chars[i] = '^';
context->show_option_requested = false;
context->abort_on_error = false;
@@ -234,16 +234,15 @@ diagnostic_finish (diagnostic_context *context)
translated. */
void
diagnostic_set_info_translated (diagnostic_info *diagnostic, const char *msg,
- va_list *args, location_t location,
+ va_list *args, rich_location *richloc,
diagnostic_t kind)
{
+ gcc_assert (richloc);
diagnostic->message.err_no = errno;
diagnostic->message.args_ptr = args;
diagnostic->message.format_spec = msg;
- diagnostic->message.set_location (0, location);
- for (int i = 1; i < MAX_LOCATIONS_PER_MESSAGE; i++)
- diagnostic->message.set_location (i, UNKNOWN_LOCATION);
- diagnostic->override_column = 0;
+ diagnostic->message.m_richloc = richloc;
+ diagnostic->richloc = richloc;
diagnostic->kind = kind;
diagnostic->option_index = 0;
}
@@ -252,10 +251,27 @@ diagnostic_set_info_translated (diagnostic_info *diagnostic, const char *msg,
translated. */
void
diagnostic_set_info (diagnostic_info *diagnostic, const char *gmsgid,
- va_list *args, location_t location,
+ va_list *args, rich_location *richloc,
diagnostic_t kind)
{
- diagnostic_set_info_translated (diagnostic, _(gmsgid), args, location, kind);
+ gcc_assert (richloc);
+ diagnostic_set_info_translated (diagnostic, _(gmsgid), args, richloc, kind);
+}
+
+static const char *const diagnostic_kind_color[] = {
+#define DEFINE_DIAGNOSTIC_KIND(K, T, C) (C),
+#include "diagnostic.def"
+#undef DEFINE_DIAGNOSTIC_KIND
+ NULL
+};
+
+/* Get a color name for diagnostics of type KIND
+ Result could be NULL. */
+
+const char *
+diagnostic_get_color_for_kind (diagnostic_t kind)
+{
+ return diagnostic_kind_color[kind];
}
/* Return a malloc'd string describing a location. The caller is
@@ -270,12 +286,6 @@ diagnostic_build_prefix (diagnostic_context *context,
#undef DEFINE_DIAGNOSTIC_KIND
"must-not-happen"
};
- static const char *const diagnostic_kind_color[] = {
-#define DEFINE_DIAGNOSTIC_KIND(K, T, C) (C),
-#include "diagnostic.def"
-#undef DEFINE_DIAGNOSTIC_KIND
- NULL
- };
gcc_assert (diagnostic->kind < DK_LAST_DIAGNOSTIC_KIND);
const char *text = _(diagnostic_kind_text[diagnostic->kind]);
@@ -770,10 +780,14 @@ diagnostic_report_diagnostic (diagnostic_context *context,
if (option_text)
{
+ const char *cs
+ = colorize_start (pp_show_color (context->printer),
+ diagnostic_kind_color[diagnostic->kind]);
+ const char *ce = colorize_stop (pp_show_color (context->printer));
diagnostic->message.format_spec
= ACONCAT ((diagnostic->message.format_spec,
" ",
- "[", option_text, "]",
+ "[", cs, option_text, ce, "]",
NULL));
free (option_text);
}
@@ -853,9 +867,40 @@ diagnostic_append_note (diagnostic_context *context,
diagnostic_info diagnostic;
va_list ap;
const char *saved_prefix;
+ rich_location richloc (location);
va_start (ap, gmsgid);
- diagnostic_set_info (&diagnostic, gmsgid, &ap, location, DK_NOTE);
+ diagnostic_set_info (&diagnostic, gmsgid, &ap, &richloc, DK_NOTE);
+ if (context->inhibit_notes_p)
+ {
+ va_end (ap);
+ return;
+ }
+ saved_prefix = pp_get_prefix (context->printer);
+ pp_set_prefix (context->printer,
+ diagnostic_build_prefix (context, &diagnostic));
+ pp_newline (context->printer);
+ pp_format (context->printer, &diagnostic.message);
+ pp_output_formatted_text (context->printer);
+ pp_destroy_prefix (context->printer);
+ pp_set_prefix (context->printer, saved_prefix);
+ diagnostic_show_locus (context, &diagnostic);
+ va_end (ap);
+}
+
+/* Same as diagnostic_append_note, but at RICHLOC. */
+
+void
+diagnostic_append_note_at_rich_loc (diagnostic_context *context,
+ rich_location *richloc,
+ const char * gmsgid, ...)
+{
+ diagnostic_info diagnostic;
+ va_list ap;
+ const char *saved_prefix;
+
+ va_start (ap, gmsgid);
+ diagnostic_set_info (&diagnostic, gmsgid, &ap, richloc, DK_NOTE);
if (context->inhibit_notes_p)
{
va_end (ap);
@@ -880,16 +925,17 @@ emit_diagnostic (diagnostic_t kind, location_t location, int opt,
diagnostic_info diagnostic;
va_list ap;
bool ret;
+ rich_location richloc (location);
va_start (ap, gmsgid);
if (kind == DK_PERMERROR)
{
- diagnostic_set_info (&diagnostic, gmsgid, &ap, location,
+ diagnostic_set_info (&diagnostic, gmsgid, &ap, &richloc,
permissive_error_kind (global_dc));
diagnostic.option_index = permissive_error_option (global_dc);
}
else {
- diagnostic_set_info (&diagnostic, gmsgid, &ap, location, kind);
+ diagnostic_set_info (&diagnostic, gmsgid, &ap, &richloc, kind);
if (kind == DK_WARNING || kind == DK_PEDWARN)
diagnostic.option_index = opt;
}
@@ -906,9 +952,23 @@ inform (location_t location, const char *gmsgid, ...)
{
diagnostic_info diagnostic;
va_list ap;
+ rich_location richloc (location);
+
+ va_start (ap, gmsgid);
+ diagnostic_set_info (&diagnostic, gmsgid, &ap, &richloc, DK_NOTE);
+ report_diagnostic (&diagnostic);
+ va_end (ap);
+}
+
+/* Same as "inform", but at RICHLOC. */
+void
+inform_at_rich_loc (rich_location *richloc, const char *gmsgid, ...)
+{
+ diagnostic_info diagnostic;
+ va_list ap;
va_start (ap, gmsgid);
- diagnostic_set_info (&diagnostic, gmsgid, &ap, location, DK_NOTE);
+ diagnostic_set_info (&diagnostic, gmsgid, &ap, richloc, DK_NOTE);
report_diagnostic (&diagnostic);
va_end (ap);
}
@@ -921,11 +981,12 @@ inform_n (location_t location, int n, const char *singular_gmsgid,
{
diagnostic_info diagnostic;
va_list ap;
+ rich_location richloc (location);
va_start (ap, plural_gmsgid);
diagnostic_set_info_translated (&diagnostic,
ngettext (singular_gmsgid, plural_gmsgid, n),
- &ap, location, DK_NOTE);
+ &ap, &richloc, DK_NOTE);
report_diagnostic (&diagnostic);
va_end (ap);
}
@@ -939,9 +1000,10 @@ warning (int opt, const char *gmsgid, ...)
diagnostic_info diagnostic;
va_list ap;
bool ret;
+ rich_location richloc (input_location);
va_start (ap, gmsgid);
- diagnostic_set_info (&diagnostic, gmsgid, &ap, input_location, DK_WARNING);
+ diagnostic_set_info (&diagnostic, gmsgid, &ap, &richloc, DK_WARNING);
diagnostic.option_index = opt;
ret = report_diagnostic (&diagnostic);
@@ -959,9 +1021,27 @@ warning_at (location_t location, int opt, const char *gmsgid, ...)
diagnostic_info diagnostic;
va_list ap;
bool ret;
+ rich_location richloc (location);
+
+ va_start (ap, gmsgid);
+ diagnostic_set_info (&diagnostic, gmsgid, &ap, &richloc, DK_WARNING);
+ diagnostic.option_index = opt;
+ ret = report_diagnostic (&diagnostic);
+ va_end (ap);
+ return ret;
+}
+
+/* Same as warning at, but using RICHLOC. */
+
+bool
+warning_at_rich_loc (rich_location *richloc, int opt, const char *gmsgid, ...)
+{
+ diagnostic_info diagnostic;
+ va_list ap;
+ bool ret;
va_start (ap, gmsgid);
- diagnostic_set_info (&diagnostic, gmsgid, &ap, location, DK_WARNING);
+ diagnostic_set_info (&diagnostic, gmsgid, &ap, richloc, DK_WARNING);
diagnostic.option_index = opt;
ret = report_diagnostic (&diagnostic);
va_end (ap);
@@ -979,11 +1059,13 @@ warning_n (location_t location, int opt, int n, const char *singular_gmsgid,
diagnostic_info diagnostic;
va_list ap;
bool ret;
+ rich_location richloc (location);
va_start (ap, plural_gmsgid);
diagnostic_set_info_translated (&diagnostic,
ngettext (singular_gmsgid, plural_gmsgid, n),
- &ap, location, DK_WARNING);
+ &ap, &richloc, DK_WARNING
+);
diagnostic.option_index = opt;
ret = report_diagnostic (&diagnostic);
va_end (ap);
@@ -1009,9 +1091,10 @@ pedwarn (location_t location, int opt, const char *gmsgid, ...)
diagnostic_info diagnostic;
va_list ap;
bool ret;
+ rich_location richloc (location);
va_start (ap, gmsgid);
- diagnostic_set_info (&diagnostic, gmsgid, &ap, location, DK_PEDWARN);
+ diagnostic_set_info (&diagnostic, gmsgid, &ap, &richloc, DK_PEDWARN);
diagnostic.option_index = opt;
ret = report_diagnostic (&diagnostic);
va_end (ap);
@@ -1031,9 +1114,28 @@ permerror (location_t location, const char *gmsgid, ...)
diagnostic_info diagnostic;
va_list ap;
bool ret;
+ rich_location richloc (location);
va_start (ap, gmsgid);
- diagnostic_set_info (&diagnostic, gmsgid, &ap, location,
+ diagnostic_set_info (&diagnostic, gmsgid, &ap, &richloc,
+ permissive_error_kind (global_dc));
+ diagnostic.option_index = permissive_error_option (global_dc);
+ ret = report_diagnostic (&diagnostic);
+ va_end (ap);
+ return ret;
+}
+
+/* Same as "permerror", but at RICHLOC. */
+
+bool
+permerror_at_rich_loc (rich_location *richloc, const char *gmsgid, ...)
+{
+ diagnostic_info diagnostic;
+ va_list ap;
+ bool ret;
+
+ va_start (ap, gmsgid);
+ diagnostic_set_info (&diagnostic, gmsgid, &ap, richloc,
permissive_error_kind (global_dc));
diagnostic.option_index = permissive_error_option (global_dc);
ret = report_diagnostic (&diagnostic);
@@ -1048,9 +1150,10 @@ error (const char *gmsgid, ...)
{
diagnostic_info diagnostic;
va_list ap;
+ rich_location richloc (input_location);
va_start (ap, gmsgid);
- diagnostic_set_info (&diagnostic, gmsgid, &ap, input_location, DK_ERROR);
+ diagnostic_set_info (&diagnostic, gmsgid, &ap, &richloc, DK_ERROR);
report_diagnostic (&diagnostic);
va_end (ap);
}
@@ -1063,11 +1166,12 @@ error_n (location_t location, int n, const char *singular_gmsgid,
{
diagnostic_info diagnostic;
va_list ap;
+ rich_location richloc (location);
va_start (ap, plural_gmsgid);
diagnostic_set_info_translated (&diagnostic,
ngettext (singular_gmsgid, plural_gmsgid, n),
- &ap, location, DK_ERROR);
+ &ap, &richloc, DK_ERROR);
report_diagnostic (&diagnostic);
va_end (ap);
}
@@ -1078,9 +1182,25 @@ error_at (location_t loc, const char *gmsgid, ...)
{
diagnostic_info diagnostic;
va_list ap;
+ rich_location richloc (loc);
va_start (ap, gmsgid);
- diagnostic_set_info (&diagnostic, gmsgid, &ap, loc, DK_ERROR);
+ diagnostic_set_info (&diagnostic, gmsgid, &ap, &richloc, DK_ERROR);
+ report_diagnostic (&diagnostic);
+ va_end (ap);
+}
+
+/* Same as above, but use RICH_LOC. */
+
+void
+error_at_rich_loc (rich_location *rich_loc, const char *gmsgid, ...)
+{
+ diagnostic_info diagnostic;
+ va_list ap;
+
+ va_start (ap, gmsgid);
+ diagnostic_set_info (&diagnostic, gmsgid, &ap, rich_loc,
+ DK_ERROR);
report_diagnostic (&diagnostic);
va_end (ap);
}
@@ -1093,9 +1213,10 @@ sorry (const char *gmsgid, ...)
{
diagnostic_info diagnostic;
va_list ap;
+ rich_location richloc (input_location);
va_start (ap, gmsgid);
- diagnostic_set_info (&diagnostic, gmsgid, &ap, input_location, DK_SORRY);
+ diagnostic_set_info (&diagnostic, gmsgid, &ap, &richloc, DK_SORRY);
report_diagnostic (&diagnostic);
va_end (ap);
}
@@ -1116,9 +1237,10 @@ fatal_error (location_t loc, const char *gmsgid, ...)
{
diagnostic_info diagnostic;
va_list ap;
+ rich_location richloc (loc);
va_start (ap, gmsgid);
- diagnostic_set_info (&diagnostic, gmsgid, &ap, loc, DK_FATAL);
+ diagnostic_set_info (&diagnostic, gmsgid, &ap, &richloc, DK_FATAL);
report_diagnostic (&diagnostic);
va_end (ap);
@@ -1134,9 +1256,10 @@ internal_error (const char *gmsgid, ...)
{
diagnostic_info diagnostic;
va_list ap;
+ rich_location richloc (input_location);
va_start (ap, gmsgid);
- diagnostic_set_info (&diagnostic, gmsgid, &ap, input_location, DK_ICE);
+ diagnostic_set_info (&diagnostic, gmsgid, &ap, &richloc, DK_ICE);
report_diagnostic (&diagnostic);
va_end (ap);
@@ -1151,9 +1274,10 @@ internal_error_no_backtrace (const char *gmsgid, ...)
{
diagnostic_info diagnostic;
va_list ap;
+ rich_location richloc (input_location);
va_start (ap, gmsgid);
- diagnostic_set_info (&diagnostic, gmsgid, &ap, input_location, DK_ICE_NOBT);
+ diagnostic_set_info (&diagnostic, gmsgid, &ap, &richloc, DK_ICE_NOBT);
report_diagnostic (&diagnostic);
va_end (ap);
@@ -1217,3 +1341,17 @@ real_abort (void)
{
abort ();
}
+
+/* Display the given source_range instance, with MSG as a descriptive
+ comment. This issues a "note" diagnostic at the range.
+
+ This is declared within libcpp, but implemented here, since it
+ makes use of the diagnostic-printing machinery. */
+
+DEBUG_FUNCTION void
+source_range::debug (const char *msg) const
+{
+ rich_location richloc (m_start);
+ richloc.add_range (m_start, m_finish, false);
+ inform_at_rich_loc (&richloc, "%s", msg);
+}
diff --git a/gcc/diagnostic.h b/gcc/diagnostic.h
index 7fcb6a8cd0e..9096e16eb07 100644
--- a/gcc/diagnostic.h
+++ b/gcc/diagnostic.h
@@ -29,10 +29,12 @@ along with GCC; see the file COPYING3. If not see
list in diagnostic.def. */
struct diagnostic_info
{
- /* Text to be formatted. It also contains the location(s) for this
- diagnostic. */
+ /* Text to be formatted. */
text_info message;
- unsigned int override_column;
+
+ /* The location at which the diagnostic is to be reported. */
+ rich_location *richloc;
+
/* Auxiliary data for client. */
void *x_data;
/* The kind of diagnostic it is about. */
@@ -102,8 +104,8 @@ struct diagnostic_context
/* Maximum width of the source line printed. */
int caret_max_width;
- /* Characters used for caret diagnostics. */
- char caret_chars[MAX_LOCATIONS_PER_MESSAGE];
+ /* Character used for caret diagnostics. */
+ char caret_chars[rich_location::MAX_RANGES];
/* True if we should print the command line option which controls
each diagnostic, if known. */
@@ -181,6 +183,15 @@ struct diagnostic_context
int lock;
bool inhibit_notes_p;
+
+ /* When printing source code, should the characters at carets and ranges
+ be colorized? (assuming colorization is on at all).
+ This should be true for frontends that generate range information
+ (so that the ranges of code are colorized),
+ and false for frontends that merely specify points within the
+ source code (to avoid e.g. colorizing just the first character in
+ a token, which would look strange). */
+ bool colorize_source_p;
};
static inline void
@@ -252,10 +263,6 @@ extern diagnostic_context *global_dc;
#define report_diagnostic(D) diagnostic_report_diagnostic (global_dc, D)
-/* Override the column number to be used for reporting a
- diagnostic. */
-#define diagnostic_override_column(DI, COL) (DI)->override_column = (COL)
-
/* Override the option index to be used for reporting a
diagnostic. */
#define diagnostic_override_option_index(DI, OPTIDX) \
@@ -279,13 +286,17 @@ extern bool diagnostic_report_diagnostic (diagnostic_context *,
diagnostic_info *);
#ifdef ATTRIBUTE_GCC_DIAG
extern void diagnostic_set_info (diagnostic_info *, const char *, va_list *,
- location_t, diagnostic_t) ATTRIBUTE_GCC_DIAG(2,0);
+ rich_location *, diagnostic_t) ATTRIBUTE_GCC_DIAG(2,0);
extern void diagnostic_set_info_translated (diagnostic_info *, const char *,
- va_list *, location_t,
+ va_list *, rich_location *,
diagnostic_t)
ATTRIBUTE_GCC_DIAG(2,0);
extern void diagnostic_append_note (diagnostic_context *, location_t,
const char *, ...) ATTRIBUTE_GCC_DIAG(3,4);
+extern void diagnostic_append_note_at_rich_loc (diagnostic_context *,
+ rich_location *,
+ const char *, ...)
+ ATTRIBUTE_GCC_DIAG(3,4);
#endif
extern char *diagnostic_build_prefix (diagnostic_context *, const diagnostic_info *);
void default_diagnostic_starter (diagnostic_context *, diagnostic_info *);
@@ -306,6 +317,14 @@ diagnostic_location (const diagnostic_info * diagnostic, int which = 0)
return diagnostic->message.get_location (which);
}
+/* Return the number of locations to be printed in DIAGNOSTIC. */
+
+static inline unsigned int
+diagnostic_num_locations (const diagnostic_info * diagnostic)
+{
+ return diagnostic->message.m_richloc->get_num_locations ();
+}
+
/* Expand the location of this diagnostic. Use this function for
consistency. Parameter WHICH specifies which location. By default,
expand the first one. */
@@ -313,12 +332,7 @@ diagnostic_location (const diagnostic_info * diagnostic, int which = 0)
static inline expanded_location
diagnostic_expand_location (const diagnostic_info * diagnostic, int which = 0)
{
- expanded_location s
- = expand_location_to_spelling_point (diagnostic_location (diagnostic,
- which));
- if (which == 0 && diagnostic->override_column)
- s.column = diagnostic->override_column;
- return s;
+ return diagnostic->richloc->get_range (which)->m_caret;
}
/* This is somehow the right-side margin of a caret line, that is, we
@@ -338,11 +352,7 @@ diagnostic_same_line (const diagnostic_context *context,
&& context->caret_max_width - CARET_LINE_MARGIN > abs (s1.column - s2.column);
}
-void
-diagnostic_print_caret_line (diagnostic_context * context,
- expanded_location xloc1,
- expanded_location xloc2,
- char caret1, char caret2);
+extern const char *diagnostic_get_color_for_kind (diagnostic_t kind);
/* Pure text formatting support functions. */
extern char *file_name_as_prefix (diagnostic_context *, const char *);
diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi
index 26afc00c570..aab6bad905c 100644
--- a/gcc/doc/extend.texi
+++ b/gcc/doc/extend.texi
@@ -1261,8 +1261,8 @@ As an extension, GNU C supports named address spaces as
defined in the N1275 draft of ISO/IEC DTR 18037. Support for named
address spaces in GCC will evolve as the draft technical report
changes. Calling conventions for any target might also change. At
-present, only the AVR, SPU, M32C, and RL78 targets support address
-spaces other than the generic address space.
+present, only the AVR, SPU, M32C, RL78, and x86 targets support
+address spaces other than the generic address space.
Address space identifiers may be used exactly like any other C type
qualifier (e.g., @code{const} or @code{volatile}). See the N1275
@@ -1451,6 +1451,49 @@ It may use runtime library
support, or generate special machine instructions to access that address
space.
+@subsection x86 Named Address Spaces
+@cindex x86 named address spaces
+
+On the x86 target, variables may be declared as being relative
+to the @code{%fs} or @code{%gs} segments.
+
+@table @code
+@item __seg_fs
+@itemx __seg_gs
+@cindex @code{__seg_fs} x86 named address space
+@cindex @code{__seg_gs} x86 named address space
+The object is accessed with the respective segment override prefix.
+
+The respective segment base must be set via some method specific to
+the operating system. Rather than require an expensive system call
+to retrieve the segment base, these address spaces are not considered
+to be subspaces of the generic (flat) address space. This means that
+explicit casts are required to convert pointers between these address
+spaces and the generic address space. In practice the application
+should cast to @code{uintptr_t} and apply the segment base offset
+that it installed previously.
+
+The preprocessor symbols @code{__SEG_FS} and @code{__SEG_GS} are
+defined when these address spaces are supported.
+
+@item __seg_tls
+@cindex @code{__seg_tls} x86 named address space
+Some operating systems define either the @code{%fs} or @code{%gs}
+segment as the thread-local storage base for each thread. Objects
+within this address space are accessed with the appropriate
+segment override prefix.
+
+The pointer located at address 0 within the segment contains the
+offset of the segment within the generic address space. Thus this
+address space is considered a subspace of the generic address space,
+and the known segment offset is applied when converting addresses
+to and from the generic address space.
+
+The preprocessor symbol @code{__SEG_TLS} is defined when this
+address space is supported.
+
+@end table
+
@node Zero Length
@section Arrays of Length Zero
@cindex arrays of length zero
@@ -6395,6 +6438,42 @@ of the structure or union is placed to minimize the memory required. When
attached to an @code{enum} definition, it indicates that the smallest
integral type should be used.
+@item scalar_storage_order ("@var{endianness}")
+@cindex @code{scalar_storage_order} type attribute
+When attached to a @code{union} or a @code{struct}, this attribute sets
+the storage order, aka endianness, of the scalar fields of the type, as
+well as the array fields whose component is scalar. The supported
+endianness are @code{big-endian} and @code{little-endian}. The attribute
+has no effects on fields which are themselves a @code{union}, a @code{struct}
+or an array whose component is a @code{union} or a @code{struct}, and it is
+possible to have fields with a different scalar storage order than the
+enclosing type.
+
+This attribute is supported only for targets that use a uniform default
+scalar storage order (fortunately, most of them), i.e. targets that store
+the scalars either all in big-endian or all in little-endian.
+
+Additional restrictions are enforced for types with the reverse scalar
+storage order with regard to the scalar storage order of the target:
+
+@itemize
+@item Taking the address of a scalar field of a @code{union} or a
+@code{struct} with reverse scalar storage order is not permitted and will
+yield an error.
+@item Taking the address of an array field, whose component is scalar, of
+a @code{union} or a @code{struct} with reverse scalar storage order is
+permitted but will yield a warning, unless @option{-Wno-scalar-storage-order}
+is specified.
+@item Taking the address of a @code{union} or a @code{struct} with reverse
+scalar storage order is permitted.
+@end itemize
+
+These restrictions exist because the storage order attribute is lost when
+the address of a scalar or the address of an array with scalar component
+is taken, so storing indirectly through this address will generally not work.
+The second case is nevertheless allowed to be able to perform a block copy
+from or to the array.
+
@item transparent_union
@cindex @code{transparent_union} type attribute
@@ -18432,7 +18511,7 @@ for further explanation.
* Darwin Pragmas::
* Solaris Pragmas::
* Symbol-Renaming Pragmas::
-* Structure-Packing Pragmas::
+* Structure-Layout Pragmas::
* Weak Pragmas::
* Diagnostic Pragmas::
* Visibility Pragmas::
@@ -18708,8 +18787,8 @@ the name does not change.
always the C-language name.
@end enumerate
-@node Structure-Packing Pragmas
-@subsection Structure-Packing Pragmas
+@node Structure-Layout Pragmas
+@subsection Structure-Layout Pragmas
For compatibility with Microsoft Windows compilers, GCC supports a
set of @code{#pragma} directives that change the maximum alignment of
@@ -18732,17 +18811,30 @@ multiple @code{#pragma pack(@var{n})} instances and finalized by a single
@code{#pragma pack(pop)}.
@end enumerate
-Some targets, e.g.@: x86 and PowerPC, support the @code{ms_struct}
-@code{#pragma} which lays out a structure as the documented
-@code{__attribute__ ((ms_struct))}.
+Some targets, e.g.@: x86 and PowerPC, support the @code{#pragma ms_struct}
+directive which lays out structures and unions subsequently defined as the
+documented @code{__attribute__ ((ms_struct))}.
+
@enumerate
-@item @code{#pragma ms_struct on} turns on the layout for structures
-declared.
-@item @code{#pragma ms_struct off} turns off the layout for structures
-declared.
+@item @code{#pragma ms_struct on} turns on the Microsoft layout.
+@item @code{#pragma ms_struct off} turns off the Microsoft layout.
@item @code{#pragma ms_struct reset} goes back to the default layout.
@end enumerate
+Most targets also support the @code{#pragma scalar_storage_order} directive
+which lays out structures and unions subsequently defined as the documented
+@code{__attribute__ ((scalar_storage_order))}.
+
+@enumerate
+@item @code{#pragma scalar_storage_order big-endian} sets the storage order
+of the scalar fields to big-endian.
+@item @code{#pragma scalar_storage_order little-endian} sets the storage order
+of the scalar fields to little-endian.
+@item @code{#pragma scalar_storage_order default} goes back to the endianness
+that was in effect when compilation started (see also command-line option
+@option{-fsso-struct=@var{endianness}} @pxref{C Dialect Options}).
+@end enumerate
+
@node Weak Pragmas
@subsection Weak Pragmas
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index 587e30e613d..dc9a4e73712 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -169,10 +169,11 @@ in the following sections.
-aux-info @var{filename} -fallow-parameterless-variadic-functions @gol
-fno-asm -fno-builtin -fno-builtin-@var{function} @gol
-fhosted -ffreestanding -fopenacc -fopenmp -fopenmp-simd @gol
--fms-extensions -fplan9-extensions -trigraphs -traditional -traditional-cpp @gol
+-fms-extensions -fplan9-extensions -fsso-struct=@var{endianness}
-fallow-single-precision -fcond-mismatch -flax-vector-conversions @gol
-fsigned-bitfields -fsigned-char @gol
--funsigned-bitfields -funsigned-char}
+-funsigned-bitfields -funsigned-char @gol
+-trigraphs -traditional -traditional-cpp}
@item C++ Language Options
@xref{C++ Dialect Options,,Options Controlling C++ Dialect}.
@@ -278,6 +279,7 @@ Objective-C and Objective-C++ Dialects}.
-Wshift-overflow -Wshift-overflow=@var{n} @gol
-Wshift-count-negative -Wshift-count-overflow -Wshift-negative-value @gol
-Wsign-compare -Wsign-conversion -Wfloat-conversion @gol
+-Wno-scalar-storage-order @gol
-Wsizeof-pointer-memaccess -Wsizeof-array-argument @gol
-Wstack-protector -Wstack-usage=@var{len} -Wstrict-aliasing @gol
-Wstrict-aliasing=n @gol -Wstrict-overflow -Wstrict-overflow=@var{n} @gol
@@ -521,6 +523,7 @@ Objective-C and Objective-C++ Dialects}.
-mtls-size=@var{size} @gol
-mfix-cortex-a53-835769 -mno-fix-cortex-a53-835769 @gol
-mfix-cortex-a53-843419 -mno-fix-cortex-a53-843419 @gol
+-mlow-precision-recip-sqrt -mno-low-precision-recip-sqrt@gol
-march=@var{name} -mcpu=@var{name} -mtune=@var{name}}
@emph{Adapteva Epiphany Options}
@@ -2075,6 +2078,17 @@ These options control whether a bit-field is signed or unsigned, when the
declaration does not use either @code{signed} or @code{unsigned}. By
default, such a bit-field is signed, because this is consistent: the
basic integer types such as @code{int} are signed types.
+
+@item -fsso-struct=@var{endianness}
+@opindex fsso-struct
+Set the default scalar storage order of structures and unions to the
+specified endianness. The accepted values are @samp{big-endian} and
+@samp{little-endian}. If the option is not passed, the compiler uses
+the native endianness of the target. This option is not supported for C++.
+
+@strong{Warning:} the @option{-fsso-struct} switch causes GCC to generate
+code that is not binary compatible with code generated without it if the
+specified endianness is not the native endianness of the target.
@end table
@node C++ Dialect Options
@@ -5112,6 +5126,11 @@ This includes conversions from real to integer, and from higher precision
real to lower precision real values. This option is also enabled by
@option{-Wconversion}.
+@item -Wno-scalar-storage-order
+@opindex -Wno-scalar-storage-order
+@opindex -Wscalar-storage-order
+Do not warn on suspicious constructs involving reverse scalar storage order.
+
@item -Wsized-deallocation @r{(C++ and Objective-C++ only)}
@opindex Wsized-deallocation
@opindex Wno-sized-deallocation
@@ -12519,6 +12538,17 @@ Enable or disable the workaround for the ARM Cortex-A53 erratum number 843419.
This erratum workaround is made at link time and this will only pass the
corresponding flag to the linker.
+@item -mlow-precision-recip-sqrt
+@item -mno-low-precision-recip-sqrt
+@opindex -mlow-precision-recip-sqrt
+@opindex -mno-low-precision-recip-sqrt
+The square root estimate uses two steps instead of three for double-precision,
+and one step instead of two for single-precision.
+Thus reducing latency and precision.
+This is only relevant if @option{-ffast-math} activates
+reciprocal square root estimate instructions.
+Which in turn depends on the target processor.
+
@item -march=@var{name}
@opindex march
Specify the name of the target architecture, optionally suffixed by one or
@@ -13745,10 +13775,9 @@ off by default.
@item -masm-syntax-unified
@opindex masm-syntax-unified
Assume inline assembler is using unified asm syntax. The default is
-currently off which implies divided syntax. Currently this option is
-available only for Thumb1 and has no effect on ARM state and Thumb2.
-However, this may change in future releases of GCC. Divided syntax
-should be considered deprecated.
+currently off which implies divided syntax. This option has no impact
+on Thumb2. However, this may change in future releases of GCC.
+Divided syntax should be considered deprecated.
@item -mrestrict-it
@opindex mrestrict-it
diff --git a/gcc/doc/md.texi b/gcc/doc/md.texi
index 619259fc393..ee629e23381 100644
--- a/gcc/doc/md.texi
+++ b/gcc/doc/md.texi
@@ -1465,6 +1465,8 @@ can be described by a series of letters for each operand. The overall
constraint for an operand is made from the letters for this operand
from the first alternative, a comma, the letters for this operand from
the second alternative, a comma, and so on until the last alternative.
+All operands for a single instruction must have the same number of
+alternatives.
@ifset INTERNALS
Here is how it is done for fullword logical-or on the 68000:
@@ -1482,9 +1484,7 @@ operand 1 (meaning it must match operand 0), and @samp{dKs} for operand
@samp{0} for operand 1, and @samp{dmKs} for operand 2. The @samp{=} and
@samp{%} in the constraints apply to all the alternatives; their
meaning is explained in the next section (@pxref{Class Preferences}).
-@end ifset
-@c FIXME Is this ? and ! stuff of use in asm()? If not, hide unless INTERNAL
If all the operands fit any one alternative, the instruction is valid.
Otherwise, for each alternative, the compiler counts how many instructions
must be added to copy the operands so that that alternative applies.
@@ -1521,7 +1521,6 @@ This constraint is analogous to @samp{!} but it disparages severely
the alternative only if the operand with the @samp{$} needs a reload.
@end table
-@ifset INTERNALS
When an insn pattern has multiple alternatives in its constraints, often
the appearance of the assembler code is determined mostly by which
alternative was matched. When this is so, the C code for writing the
@@ -1529,6 +1528,21 @@ assembler code can use the variable @code{which_alternative}, which is
the ordinal number of the alternative that was actually satisfied (0 for
the first, 1 for the second alternative, etc.). @xref{Output Statement}.
@end ifset
+@ifclear INTERNALS
+
+So the first alternative for the 68000's logical-or could be written as
+@code{"+m" (output) : "ir" (input)}. The second could be @code{"+r"
+(output): "irm" (input)}. However, the fact that two memory locations
+cannot be used in a single instruction prevents simply using @code{"+rm"
+(output) : "irm" (input)}. Using multi-alternatives, this might be
+written as @code{"+m,r" (output) : "ir,irm" (input)}. This describes
+all the available alternatives to the compiler, allowing it to choose
+the most efficient one for the current conditions.
+
+There is no way within the template to determine which alternative was
+chosen. However you may be able to wrap your @code{asm} statements with
+builtins such as @code{__builtin_constant_p} to achieve the desired results.
+@end ifclear
@ifset INTERNALS
@node Class Preferences
diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi
index f394db7d0a6..5609a98a430 100644
--- a/gcc/doc/tm.texi
+++ b/gcc/doc/tm.texi
@@ -10365,6 +10365,11 @@ arithmetic operations. Pointers to a superset address space can be
converted to pointers to a subset address space via explicit casts.
@end deftypefn
+@deftypefn {Target Hook} bool TARGET_ADDR_SPACE_ZERO_ADDRESS_VALID (addr_space_t @var{as})
+Define this to modify the default handling of address 0 for the
+address space. Return true if 0 should be considered a valid address.
+@end deftypefn
+
@deftypefn {Target Hook} rtx TARGET_ADDR_SPACE_CONVERT (rtx @var{op}, tree @var{from_type}, tree @var{to_type})
Define this to convert the pointer expression represented by the RTL
@var{op} with type @var{from_type} that points to a named address
@@ -10374,6 +10379,11 @@ guaranteed that one of the two address spaces is a subset of the other,
as determined by the @code{TARGET_ADDR_SPACE_SUBSET_P} target hook.
@end deftypefn
+@deftypefn {Target Hook} int TARGET_ADDR_SPACE_DEBUG (addr_space_t @var{as})
+Define this to define how the address space is encoded in dwarf.
+The result is the value to be used with @code{DW_AT_address_class}.
+@end deftypefn
+
@node Misc
@section Miscellaneous Parameters
@cindex parameters, miscellaneous
diff --git a/gcc/doc/tm.texi.in b/gcc/doc/tm.texi.in
index d188c57b75c..96ca063a391 100644
--- a/gcc/doc/tm.texi.in
+++ b/gcc/doc/tm.texi.in
@@ -7455,8 +7455,12 @@ c_register_addr_space ("__ea", ADDR_SPACE_EA);
@hook TARGET_ADDR_SPACE_SUBSET_P
+@hook TARGET_ADDR_SPACE_ZERO_ADDRESS_VALID
+
@hook TARGET_ADDR_SPACE_CONVERT
+@hook TARGET_ADDR_SPACE_DEBUG
+
@node Misc
@section Miscellaneous Parameters
@cindex parameters, miscellaneous
diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c
index 9ce3f0921fc..f1847500910 100644
--- a/gcc/dwarf2out.c
+++ b/gcc/dwarf2out.c
@@ -368,12 +368,14 @@ dump_struct_debug (tree type, enum debug_info_usage usage,
#endif
/* Get the number of HOST_WIDE_INTs needed to represent the precision
- of the number. */
+ of the number. Some constants have a large uniform precision, so
+ we get the precision needed for the actual value of the number. */
static unsigned int
get_full_len (const wide_int &op)
{
- return ((op.get_precision () + HOST_BITS_PER_WIDE_INT - 1)
+ int prec = wi::min_precision (op, UNSIGNED);
+ return ((prec + HOST_BITS_PER_WIDE_INT - 1)
/ HOST_BITS_PER_WIDE_INT);
}
@@ -5271,9 +5273,10 @@ add_var_loc_to_decl (tree decl, rtx loc_note, const char *label)
&& TREE_CODE (TREE_OPERAND (realdecl, 0)) == ADDR_EXPR))
{
HOST_WIDE_INT maxsize;
- tree innerdecl;
- innerdecl
- = get_ref_base_and_extent (realdecl, &bitpos, &bitsize, &maxsize);
+ bool reverse;
+ tree innerdecl
+ = get_ref_base_and_extent (realdecl, &bitpos, &bitsize, &maxsize,
+ &reverse);
if (!DECL_P (innerdecl)
|| DECL_IGNORED_P (innerdecl)
|| TREE_STATIC (innerdecl)
@@ -9010,14 +9013,14 @@ output_die (dw_die_ref die)
{
dw2_asm_output_data (l, a->dw_attr_val.v.val_wide->elt (i),
"%s", name);
- name = NULL;
+ name = "";
}
else
for (i = 0; i < len; ++i)
{
dw2_asm_output_data (l, a->dw_attr_val.v.val_wide->elt (i),
"%s", name);
- name = NULL;
+ name = "";
}
}
break;
@@ -10896,29 +10899,39 @@ modified_type_die (tree type, int cv_quals, dw_die_ref context_die)
mod_type_die = d;
}
}
- else if (code == POINTER_TYPE)
+ else if (code == POINTER_TYPE || code == REFERENCE_TYPE)
{
- mod_type_die = new_die (DW_TAG_pointer_type, mod_scope, type);
- add_AT_unsigned (mod_type_die, DW_AT_byte_size,
- simple_type_size_in_bits (type) / BITS_PER_UNIT);
- item_type = TREE_TYPE (type);
- if (!ADDR_SPACE_GENERIC_P (TYPE_ADDR_SPACE (item_type)))
- add_AT_unsigned (mod_type_die, DW_AT_address_class,
- TYPE_ADDR_SPACE (item_type));
- }
- else if (code == REFERENCE_TYPE)
- {
- if (TYPE_REF_IS_RVALUE (type) && dwarf_version >= 4)
- mod_type_die = new_die (DW_TAG_rvalue_reference_type, mod_scope,
- type);
- else
- mod_type_die = new_die (DW_TAG_reference_type, mod_scope, type);
+ dwarf_tag tag = DW_TAG_pointer_type;
+ if (code == REFERENCE_TYPE)
+ {
+ if (TYPE_REF_IS_RVALUE (type) && dwarf_version >= 4)
+ tag = DW_TAG_rvalue_reference_type;
+ else
+ tag = DW_TAG_reference_type;
+ }
+ mod_type_die = new_die (tag, mod_scope, type);
+
add_AT_unsigned (mod_type_die, DW_AT_byte_size,
simple_type_size_in_bits (type) / BITS_PER_UNIT);
item_type = TREE_TYPE (type);
- if (!ADDR_SPACE_GENERIC_P (TYPE_ADDR_SPACE (item_type)))
- add_AT_unsigned (mod_type_die, DW_AT_address_class,
- TYPE_ADDR_SPACE (item_type));
+
+ addr_space_t as = TYPE_ADDR_SPACE (item_type);
+ if (!ADDR_SPACE_GENERIC_P (as))
+ {
+ int action = targetm.addr_space.debug (as);
+ if (action >= 0)
+ {
+ /* Positive values indicate an address_class. */
+ add_AT_unsigned (mod_type_die, DW_AT_address_class, action);
+ }
+ else
+ {
+ /* Negative values indicate an (inverted) segment base reg. */
+ dw_loc_descr_ref d
+ = one_reg_loc_descriptor (~action, VAR_INIT_STATUS_INITIALIZED);
+ add_AT_loc (mod_type_die, DW_AT_segment, d);
+ }
+ }
}
else if (code == INTEGER_TYPE
&& TREE_TYPE (type) != NULL_TREE
@@ -14461,12 +14474,12 @@ loc_list_for_address_of_addr_expr_of_indirect_ref (tree loc, bool toplev,
tree obj, offset;
HOST_WIDE_INT bitsize, bitpos, bytepos;
machine_mode mode;
- int unsignedp, volatilep = 0;
+ int unsignedp, reversep, volatilep = 0;
dw_loc_list_ref list_ret = NULL, list_ret1 = NULL;
obj = get_inner_reference (TREE_OPERAND (loc, 0),
&bitsize, &bitpos, &offset, &mode,
- &unsignedp, &volatilep, false);
+ &unsignedp, &reversep, &volatilep, false);
STRIP_NOPS (obj);
if (bitpos % BITS_PER_UNIT)
{
@@ -14795,10 +14808,10 @@ loc_list_from_tree (tree loc, int want_address,
tree obj, offset;
HOST_WIDE_INT bitsize, bitpos, bytepos;
machine_mode mode;
- int unsignedp, volatilep = 0;
+ int unsignedp, reversep, volatilep = 0;
obj = get_inner_reference (loc, &bitsize, &bitpos, &offset, &mode,
- &unsignedp, &volatilep, false);
+ &unsignedp, &reversep, &volatilep, false);
gcc_assert (obj != loc);
@@ -15593,8 +15606,13 @@ add_const_value_attribute (dw_die_ref die, rtx rtl)
return true;
case CONST_WIDE_INT:
- add_AT_wide (die, DW_AT_const_value,
- std::make_pair (rtl, GET_MODE (rtl)));
+ {
+ wide_int w1 = std::make_pair (rtl, MAX_MODE_INT);
+ unsigned int prec = MIN (wi::min_precision (w1, UNSIGNED),
+ (unsigned int)CONST_WIDE_INT_NUNITS (rtl) * HOST_BITS_PER_WIDE_INT);
+ wide_int w = wi::zext (w1, prec);
+ add_AT_wide (die, DW_AT_const_value, w);
+ }
return true;
case CONST_DOUBLE:
@@ -16095,7 +16113,7 @@ fortran_common (tree decl, HOST_WIDE_INT *value)
machine_mode mode;
HOST_WIDE_INT bitsize, bitpos;
tree offset;
- int unsignedp, volatilep = 0;
+ int unsignedp, reversep, volatilep = 0;
/* If the decl isn't a VAR_DECL, or if it isn't static, or if
it does not have a value (the offset into the common area), or if it
@@ -16111,8 +16129,8 @@ fortran_common (tree decl, HOST_WIDE_INT *value)
if (TREE_CODE (val_expr) != COMPONENT_REF)
return NULL_TREE;
- cvar = get_inner_reference (val_expr, &bitsize, &bitpos, &offset,
- &mode, &unsignedp, &volatilep, true);
+ cvar = get_inner_reference (val_expr, &bitsize, &bitpos, &offset, &mode,
+ &unsignedp, &reversep, &volatilep, true);
if (cvar == NULL_TREE
|| TREE_CODE (cvar) != VAR_DECL
diff --git a/gcc/expmed.c b/gcc/expmed.c
index a06576c4fdd..97a15130e4f 100644
--- a/gcc/expmed.c
+++ b/gcc/expmed.c
@@ -48,24 +48,24 @@ static void store_fixed_bit_field (rtx, unsigned HOST_WIDE_INT,
unsigned HOST_WIDE_INT,
unsigned HOST_WIDE_INT,
unsigned HOST_WIDE_INT,
- rtx);
+ rtx, bool);
static void store_fixed_bit_field_1 (rtx, unsigned HOST_WIDE_INT,
unsigned HOST_WIDE_INT,
- rtx);
+ rtx, bool);
static void store_split_bit_field (rtx, unsigned HOST_WIDE_INT,
unsigned HOST_WIDE_INT,
unsigned HOST_WIDE_INT,
unsigned HOST_WIDE_INT,
- rtx);
+ rtx, bool);
static rtx extract_fixed_bit_field (machine_mode, rtx,
unsigned HOST_WIDE_INT,
- unsigned HOST_WIDE_INT, rtx, int);
+ unsigned HOST_WIDE_INT, rtx, int, bool);
static rtx extract_fixed_bit_field_1 (machine_mode, rtx,
unsigned HOST_WIDE_INT,
- unsigned HOST_WIDE_INT, rtx, int);
+ unsigned HOST_WIDE_INT, rtx, int, bool);
static rtx lshift_value (machine_mode, unsigned HOST_WIDE_INT, int);
static rtx extract_split_bit_field (rtx, unsigned HOST_WIDE_INT,
- unsigned HOST_WIDE_INT, int);
+ unsigned HOST_WIDE_INT, int, bool);
static void do_cmp_and_jump (rtx, rtx, enum rtx_code, machine_mode, rtx_code_label *);
static rtx expand_smod_pow2 (machine_mode, rtx, HOST_WIDE_INT);
static rtx expand_sdiv_pow2 (machine_mode, rtx, HOST_WIDE_INT);
@@ -323,6 +323,94 @@ negate_rtx (machine_mode mode, rtx x)
return result;
}
+/* Whether reverse storage order is supported on the target. */
+static int reverse_storage_order_supported = -1;
+
+/* Check whether reverse storage order is supported on the target. */
+
+static void
+check_reverse_storage_order_support (void)
+{
+ if (BYTES_BIG_ENDIAN != WORDS_BIG_ENDIAN)
+ {
+ reverse_storage_order_supported = 0;
+ sorry ("reverse scalar storage order");
+ }
+ else
+ reverse_storage_order_supported = 1;
+}
+
+/* Whether reverse FP storage order is supported on the target. */
+static int reverse_float_storage_order_supported = -1;
+
+/* Check whether reverse FP storage order is supported on the target. */
+
+static void
+check_reverse_float_storage_order_support (void)
+{
+ if (FLOAT_WORDS_BIG_ENDIAN != WORDS_BIG_ENDIAN)
+ {
+ reverse_float_storage_order_supported = 0;
+ sorry ("reverse floating-point scalar storage order");
+ }
+ else
+ reverse_float_storage_order_supported = 1;
+}
+
+/* Return an rtx representing value of X with reverse storage order.
+ MODE is the intended mode of the result,
+ useful if X is a CONST_INT. */
+
+rtx
+flip_storage_order (enum machine_mode mode, rtx x)
+{
+ enum machine_mode int_mode;
+ rtx result;
+
+ if (mode == QImode)
+ return x;
+
+ if (COMPLEX_MODE_P (mode))
+ {
+ rtx real = read_complex_part (x, false);
+ rtx imag = read_complex_part (x, true);
+
+ real = flip_storage_order (GET_MODE_INNER (mode), real);
+ imag = flip_storage_order (GET_MODE_INNER (mode), imag);
+
+ return gen_rtx_CONCAT (mode, real, imag);
+ }
+
+ if (__builtin_expect (reverse_storage_order_supported < 0, 0))
+ check_reverse_storage_order_support ();
+
+ if (SCALAR_INT_MODE_P (mode))
+ int_mode = mode;
+ else
+ {
+ if (FLOAT_MODE_P (mode)
+ && __builtin_expect (reverse_float_storage_order_supported < 0, 0))
+ check_reverse_float_storage_order_support ();
+
+ int_mode = mode_for_size (GET_MODE_PRECISION (mode), MODE_INT, 0);
+ if (int_mode == BLKmode)
+ {
+ sorry ("reverse storage order for %smode", GET_MODE_NAME (mode));
+ return x;
+ }
+ x = gen_lowpart (int_mode, x);
+ }
+
+ result = simplify_unary_operation (BSWAP, int_mode, x, int_mode);
+ if (result == 0)
+ result = expand_unop (int_mode, bswap_optab, x, NULL_RTX, 1);
+
+ if (int_mode != mode)
+ result = gen_lowpart (mode, result);
+
+ return result;
+}
+
/* Adjust bitfield memory MEM so that it points to the first unit of mode
MODE that contains a bitfield of size BITSIZE at bit position BITNUM.
If MODE is BLKmode, return a reference to every byte in the bitfield.
@@ -626,7 +714,7 @@ store_bit_field_1 (rtx str_rtx, unsigned HOST_WIDE_INT bitsize,
unsigned HOST_WIDE_INT bitregion_start,
unsigned HOST_WIDE_INT bitregion_end,
machine_mode fieldmode,
- rtx value, bool fallback_p)
+ rtx value, bool reverse, bool fallback_p)
{
rtx op0 = str_rtx;
rtx orig_value;
@@ -642,7 +730,7 @@ store_bit_field_1 (rtx str_rtx, unsigned HOST_WIDE_INT bitsize,
int outer_mode_size = GET_MODE_SIZE (GET_MODE (op0));
int byte_offset = 0;
- /* Paradoxical subregs need special handling on big endian machines. */
+ /* Paradoxical subregs need special handling on big-endian machines. */
if (SUBREG_BYTE (op0) == 0 && inner_mode_size < outer_mode_size)
{
int difference = inner_mode_size - outer_mode_size;
@@ -704,6 +792,8 @@ store_bit_field_1 (rtx str_rtx, unsigned HOST_WIDE_INT bitsize,
sub = simplify_gen_subreg (GET_MODE (op0), value, fieldmode, 0);
if (sub)
{
+ if (reverse)
+ sub = flip_storage_order (GET_MODE (op0), sub);
emit_move_insn (op0, sub);
return true;
}
@@ -714,6 +804,8 @@ store_bit_field_1 (rtx str_rtx, unsigned HOST_WIDE_INT bitsize,
bitnum / BITS_PER_UNIT);
if (sub)
{
+ if (reverse)
+ value = flip_storage_order (fieldmode, value);
emit_move_insn (sub, value);
return true;
}
@@ -726,6 +818,8 @@ store_bit_field_1 (rtx str_rtx, unsigned HOST_WIDE_INT bitsize,
if (simple_mem_bitfield_p (op0, bitsize, bitnum, fieldmode))
{
op0 = adjust_bitfield_address (op0, fieldmode, bitnum / BITS_PER_UNIT);
+ if (reverse)
+ value = flip_storage_order (fieldmode, value);
emit_move_insn (op0, value);
return true;
}
@@ -752,6 +846,7 @@ store_bit_field_1 (rtx str_rtx, unsigned HOST_WIDE_INT bitsize,
can be done with a movstrict instruction. */
if (!MEM_P (op0)
+ && !reverse
&& lowpart_bit_field_p (bitnum, bitsize, GET_MODE (op0))
&& bitsize == GET_MODE_BITSIZE (fieldmode)
&& optab_handler (movstrict_optab, fieldmode) != CODE_FOR_nothing)
@@ -795,7 +890,7 @@ store_bit_field_1 (rtx str_rtx, unsigned HOST_WIDE_INT bitsize,
be less than full.
However, only do that if the value is not BLKmode. */
- unsigned int backwards = WORDS_BIG_ENDIAN && fieldmode != BLKmode;
+ const bool backwards = WORDS_BIG_ENDIAN && fieldmode != BLKmode;
unsigned int nwords = (bitsize + (BITS_PER_WORD - 1)) / BITS_PER_WORD;
unsigned int i;
rtx_insn *last;
@@ -818,7 +913,7 @@ store_bit_field_1 (rtx str_rtx, unsigned HOST_WIDE_INT bitsize,
? GET_MODE_SIZE (fieldmode) / UNITS_PER_WORD
- i - 1
: i);
- unsigned int bit_offset = (backwards
+ unsigned int bit_offset = (backwards ^ reverse
? MAX ((int) bitsize - ((int) i + 1)
* BITS_PER_WORD,
0)
@@ -828,7 +923,7 @@ store_bit_field_1 (rtx str_rtx, unsigned HOST_WIDE_INT bitsize,
MIN (BITS_PER_WORD, bitsize - i * BITS_PER_WORD);
/* If the remaining chunk doesn't have full wordsize we have
- to make sure that for big endian machines the higher order
+ to make sure that for big-endian machines the higher order
bits are used. */
if (new_bitsize < BITS_PER_WORD && BYTES_BIG_ENDIAN && !backwards)
value_word = simplify_expand_binop (word_mode, lshr_optab,
@@ -842,7 +937,7 @@ store_bit_field_1 (rtx str_rtx, unsigned HOST_WIDE_INT bitsize,
bitnum + bit_offset,
bitregion_start, bitregion_end,
word_mode,
- value_word, fallback_p))
+ value_word, reverse, fallback_p))
{
delete_insns_since (last);
return false;
@@ -878,7 +973,7 @@ store_bit_field_1 (rtx str_rtx, unsigned HOST_WIDE_INT bitsize,
return false;
store_split_bit_field (op0, bitsize, bitnum, bitregion_start,
- bitregion_end, value);
+ bitregion_end, value, reverse);
return true;
}
}
@@ -889,6 +984,7 @@ store_bit_field_1 (rtx str_rtx, unsigned HOST_WIDE_INT bitsize,
extraction_insn insv;
if (!MEM_P (op0)
+ && !reverse
&& get_best_reg_extraction_insn (&insv, EP_insv,
GET_MODE_BITSIZE (GET_MODE (op0)),
fieldmode)
@@ -897,7 +993,7 @@ store_bit_field_1 (rtx str_rtx, unsigned HOST_WIDE_INT bitsize,
/* If OP0 is a memory, try copying it to a register and seeing if a
cheap register alternative is available. */
- if (MEM_P (op0))
+ if (MEM_P (op0) && !reverse)
{
if (get_best_mem_extraction_insn (&insv, EP_insv, bitsize, bitnum,
fieldmode)
@@ -917,7 +1013,7 @@ store_bit_field_1 (rtx str_rtx, unsigned HOST_WIDE_INT bitsize,
rtx tempreg = copy_to_reg (xop0);
if (store_bit_field_1 (tempreg, bitsize, bitpos,
bitregion_start, bitregion_end,
- fieldmode, orig_value, false))
+ fieldmode, orig_value, reverse, false))
{
emit_move_insn (xop0, tempreg);
return true;
@@ -930,7 +1026,7 @@ store_bit_field_1 (rtx str_rtx, unsigned HOST_WIDE_INT bitsize,
return false;
store_fixed_bit_field (op0, bitsize, bitnum, bitregion_start,
- bitregion_end, value);
+ bitregion_end, value, reverse);
return true;
}
@@ -943,7 +1039,9 @@ store_bit_field_1 (rtx str_rtx, unsigned HOST_WIDE_INT bitsize,
These two fields are 0, if the C++ memory model does not apply,
or we are not interested in keeping track of bitfield regions.
- FIELDMODE is the machine-mode of the FIELD_DECL node for this field. */
+ FIELDMODE is the machine-mode of the FIELD_DECL node for this field.
+
+ If REVERSE is true, the store is to be done in reverse order. */
void
store_bit_field (rtx str_rtx, unsigned HOST_WIDE_INT bitsize,
@@ -951,7 +1049,7 @@ store_bit_field (rtx str_rtx, unsigned HOST_WIDE_INT bitsize,
unsigned HOST_WIDE_INT bitregion_start,
unsigned HOST_WIDE_INT bitregion_end,
machine_mode fieldmode,
- rtx value)
+ rtx value, bool reverse)
{
/* Handle -fstrict-volatile-bitfields in the cases where it applies. */
if (strict_volatile_bitfield_p (str_rtx, bitsize, bitnum, fieldmode,
@@ -965,6 +1063,8 @@ store_bit_field (rtx str_rtx, unsigned HOST_WIDE_INT bitsize,
{
str_rtx = adjust_bitfield_address (str_rtx, fieldmode,
bitnum / BITS_PER_UNIT);
+ if (reverse)
+ value = flip_storage_order (fieldmode, value);
gcc_assert (bitnum % BITS_PER_UNIT == 0);
emit_move_insn (str_rtx, value);
}
@@ -977,7 +1077,7 @@ store_bit_field (rtx str_rtx, unsigned HOST_WIDE_INT bitsize,
gcc_assert (bitnum + bitsize <= GET_MODE_BITSIZE (fieldmode));
temp = copy_to_reg (str_rtx);
if (!store_bit_field_1 (temp, bitsize, bitnum, 0, 0,
- fieldmode, value, true))
+ fieldmode, value, reverse, true))
gcc_unreachable ();
emit_move_insn (str_rtx, temp);
@@ -1010,19 +1110,21 @@ store_bit_field (rtx str_rtx, unsigned HOST_WIDE_INT bitsize,
if (!store_bit_field_1 (str_rtx, bitsize, bitnum,
bitregion_start, bitregion_end,
- fieldmode, value, true))
+ fieldmode, value, reverse, true))
gcc_unreachable ();
}
/* Use shifts and boolean operations to store VALUE into a bit field of
- width BITSIZE in OP0, starting at bit BITNUM. */
+ width BITSIZE in OP0, starting at bit BITNUM.
+
+ If REVERSE is true, the store is to be done in reverse order. */
static void
store_fixed_bit_field (rtx op0, unsigned HOST_WIDE_INT bitsize,
unsigned HOST_WIDE_INT bitnum,
unsigned HOST_WIDE_INT bitregion_start,
unsigned HOST_WIDE_INT bitregion_end,
- rtx value)
+ rtx value, bool reverse)
{
/* There is a case not handled here:
a structure with a known alignment of just a halfword
@@ -1045,14 +1147,14 @@ store_fixed_bit_field (rtx op0, unsigned HOST_WIDE_INT bitsize,
/* The only way this should occur is if the field spans word
boundaries. */
store_split_bit_field (op0, bitsize, bitnum, bitregion_start,
- bitregion_end, value);
+ bitregion_end, value, reverse);
return;
}
op0 = narrow_bit_field_mem (op0, mode, bitsize, bitnum, &bitnum);
}
- store_fixed_bit_field_1 (op0, bitsize, bitnum, value);
+ store_fixed_bit_field_1 (op0, bitsize, bitnum, value, reverse);
}
/* Helper function for store_fixed_bit_field, stores
@@ -1061,7 +1163,7 @@ store_fixed_bit_field (rtx op0, unsigned HOST_WIDE_INT bitsize,
static void
store_fixed_bit_field_1 (rtx op0, unsigned HOST_WIDE_INT bitsize,
unsigned HOST_WIDE_INT bitnum,
- rtx value)
+ rtx value, bool reverse)
{
machine_mode mode;
rtx temp;
@@ -1074,7 +1176,7 @@ store_fixed_bit_field_1 (rtx op0, unsigned HOST_WIDE_INT bitsize,
/* Note that bitsize + bitnum can be greater than GET_MODE_BITSIZE (mode)
for invalid input, such as f5 from gcc.dg/pr48335-2.c. */
- if (BYTES_BIG_ENDIAN)
+ if (reverse ? !BYTES_BIG_ENDIAN : BYTES_BIG_ENDIAN)
/* BITNUM is the distance between our msb
and that of the containing datum.
Convert it to the distance from the lsb. */
@@ -1120,6 +1222,9 @@ store_fixed_bit_field_1 (rtx op0, unsigned HOST_WIDE_INT bitsize,
bitnum, NULL_RTX, 1);
}
+ if (reverse)
+ value = flip_storage_order (mode, value);
+
/* Now clear the chosen bits in OP0,
except that if VALUE is -1 we need not bother. */
/* We keep the intermediates in registers to allow CSE to combine
@@ -1129,8 +1234,10 @@ store_fixed_bit_field_1 (rtx op0, unsigned HOST_WIDE_INT bitsize,
if (! all_one)
{
- temp = expand_binop (mode, and_optab, temp,
- mask_rtx (mode, bitnum, bitsize, 1),
+ rtx mask = mask_rtx (mode, bitnum, bitsize, 1);
+ if (reverse)
+ mask = flip_storage_order (mode, mask);
+ temp = expand_binop (mode, and_optab, temp, mask,
NULL_RTX, 1, OPTAB_LIB_WIDEN);
temp = force_reg (mode, temp);
}
@@ -1158,6 +1265,8 @@ store_fixed_bit_field_1 (rtx op0, unsigned HOST_WIDE_INT bitsize,
(within the word).
VALUE is the value to store.
+ If REVERSE is true, the store is to be done in reverse order.
+
This does not yet handle fields wider than BITS_PER_WORD. */
static void
@@ -1165,10 +1274,9 @@ store_split_bit_field (rtx op0, unsigned HOST_WIDE_INT bitsize,
unsigned HOST_WIDE_INT bitpos,
unsigned HOST_WIDE_INT bitregion_start,
unsigned HOST_WIDE_INT bitregion_end,
- rtx value)
+ rtx value, bool reverse)
{
- unsigned int unit;
- unsigned int bitsdone = 0;
+ unsigned int unit, total_bits, bitsdone = 0;
/* Make sure UNIT isn't larger than BITS_PER_WORD, we can only handle that
much at a time. */
@@ -1199,12 +1307,14 @@ store_split_bit_field (rtx op0, unsigned HOST_WIDE_INT bitsize,
: word_mode, value));
}
+ total_bits = GET_MODE_BITSIZE (GET_MODE (value));
+
while (bitsdone < bitsize)
{
unsigned HOST_WIDE_INT thissize;
- rtx part, word;
unsigned HOST_WIDE_INT thispos;
unsigned HOST_WIDE_INT offset;
+ rtx part, word;
offset = (bitpos + bitsdone) / unit;
thispos = (bitpos + bitsdone) % unit;
@@ -1229,13 +1339,18 @@ store_split_bit_field (rtx op0, unsigned HOST_WIDE_INT bitsize,
thissize = MIN (bitsize - bitsdone, BITS_PER_WORD);
thissize = MIN (thissize, unit - thispos);
- if (BYTES_BIG_ENDIAN)
+ if (reverse ? !BYTES_BIG_ENDIAN : BYTES_BIG_ENDIAN)
{
/* Fetch successively less significant portions. */
if (CONST_INT_P (value))
part = GEN_INT (((unsigned HOST_WIDE_INT) (INTVAL (value))
>> (bitsize - bitsdone - thissize))
& (((HOST_WIDE_INT) 1 << thissize) - 1));
+ /* Likewise, but the source is little-endian. */
+ else if (reverse)
+ part = extract_fixed_bit_field (word_mode, value, thissize,
+ bitsize - bitsdone - thissize,
+ NULL_RTX, 1, false);
else
{
int total_bits = GET_MODE_BITSIZE (GET_MODE (value));
@@ -1244,7 +1359,7 @@ store_split_bit_field (rtx op0, unsigned HOST_WIDE_INT bitsize,
endianness compensation) to fetch the piece we want. */
part = extract_fixed_bit_field (word_mode, value, thissize,
total_bits - bitsize + bitsdone,
- NULL_RTX, 1);
+ NULL_RTX, 1, false);
}
}
else
@@ -1254,9 +1369,14 @@ store_split_bit_field (rtx op0, unsigned HOST_WIDE_INT bitsize,
part = GEN_INT (((unsigned HOST_WIDE_INT) (INTVAL (value))
>> bitsdone)
& (((HOST_WIDE_INT) 1 << thissize) - 1));
+ /* Likewise, but the source is big-endian. */
+ else if (reverse)
+ part = extract_fixed_bit_field (word_mode, value, thissize,
+ total_bits - bitsdone - thissize,
+ NULL_RTX, 1, false);
else
part = extract_fixed_bit_field (word_mode, value, thissize,
- bitsdone, NULL_RTX, 1);
+ bitsdone, NULL_RTX, 1, false);
}
/* If OP0 is a register, then handle OFFSET here.
@@ -1294,7 +1414,8 @@ store_split_bit_field (rtx op0, unsigned HOST_WIDE_INT bitsize,
it is just an out-of-bounds access. Ignore it. */
if (word != const0_rtx)
store_fixed_bit_field (word, thissize, offset * unit + thispos,
- bitregion_start, bitregion_end, part);
+ bitregion_start, bitregion_end, part,
+ reverse);
bitsdone += thissize;
}
}
@@ -1419,7 +1540,7 @@ static rtx
extract_bit_field_1 (rtx str_rtx, unsigned HOST_WIDE_INT bitsize,
unsigned HOST_WIDE_INT bitnum, int unsignedp, rtx target,
machine_mode mode, machine_mode tmode,
- bool fallback_p)
+ bool reverse, bool fallback_p)
{
rtx op0 = str_rtx;
machine_mode int_mode;
@@ -1445,6 +1566,8 @@ extract_bit_field_1 (rtx str_rtx, unsigned HOST_WIDE_INT bitsize,
&& bitnum == 0
&& bitsize == GET_MODE_BITSIZE (GET_MODE (op0)))
{
+ if (reverse)
+ op0 = flip_storage_order (mode, op0);
/* We're trying to extract a full register from itself. */
return op0;
}
@@ -1561,6 +1684,7 @@ extract_bit_field_1 (rtx str_rtx, unsigned HOST_WIDE_INT bitsize,
as the least significant bit of the value is the least significant
bit of either OP0 or a word of OP0. */
if (!MEM_P (op0)
+ && !reverse
&& lowpart_bit_field_p (bitnum, bitsize, GET_MODE (op0))
&& bitsize == GET_MODE_BITSIZE (mode1)
&& TRULY_NOOP_TRUNCATION_MODES_P (mode1, GET_MODE (op0)))
@@ -1576,6 +1700,8 @@ extract_bit_field_1 (rtx str_rtx, unsigned HOST_WIDE_INT bitsize,
if (simple_mem_bitfield_p (op0, bitsize, bitnum, mode1))
{
op0 = adjust_bitfield_address (op0, mode1, bitnum / BITS_PER_UNIT);
+ if (reverse)
+ op0 = flip_storage_order (mode1, op0);
return convert_extracted_bit_field (op0, mode, tmode, unsignedp);
}
@@ -1588,7 +1714,7 @@ extract_bit_field_1 (rtx str_rtx, unsigned HOST_WIDE_INT bitsize,
This is because the most significant word is the one which may
be less than full. */
- unsigned int backwards = WORDS_BIG_ENDIAN;
+ const bool backwards = WORDS_BIG_ENDIAN;
unsigned int nwords = (bitsize + (BITS_PER_WORD - 1)) / BITS_PER_WORD;
unsigned int i;
rtx_insn *last;
@@ -1615,7 +1741,7 @@ extract_bit_field_1 (rtx str_rtx, unsigned HOST_WIDE_INT bitsize,
? GET_MODE_SIZE (GET_MODE (target)) / UNITS_PER_WORD - i - 1
: i);
/* Offset from start of field in OP0. */
- unsigned int bit_offset = (backwards
+ unsigned int bit_offset = (backwards ^ reverse
? MAX ((int) bitsize - ((int) i + 1)
* BITS_PER_WORD,
0)
@@ -1625,7 +1751,7 @@ extract_bit_field_1 (rtx str_rtx, unsigned HOST_WIDE_INT bitsize,
= extract_bit_field_1 (op0, MIN (BITS_PER_WORD,
bitsize - i * BITS_PER_WORD),
bitnum + bit_offset, 1, target_part,
- mode, word_mode, fallback_p);
+ mode, word_mode, reverse, fallback_p);
gcc_assert (target_part);
if (!result_part)
@@ -1675,7 +1801,8 @@ extract_bit_field_1 (rtx str_rtx, unsigned HOST_WIDE_INT bitsize,
{
if (!fallback_p)
return NULL_RTX;
- target = extract_split_bit_field (op0, bitsize, bitnum, unsignedp);
+ target = extract_split_bit_field (op0, bitsize, bitnum, unsignedp,
+ reverse);
return convert_extracted_bit_field (target, mode, tmode, unsignedp);
}
}
@@ -1685,6 +1812,7 @@ extract_bit_field_1 (rtx str_rtx, unsigned HOST_WIDE_INT bitsize,
enum extraction_pattern pattern = unsignedp ? EP_extzv : EP_extv;
extraction_insn extv;
if (!MEM_P (op0)
+ && !reverse
/* ??? We could limit the structure size to the part of OP0 that
contains the field, with appropriate checks for endianness
and TRULY_NOOP_TRUNCATION. */
@@ -1701,7 +1829,7 @@ extract_bit_field_1 (rtx str_rtx, unsigned HOST_WIDE_INT bitsize,
/* If OP0 is a memory, try copying it to a register and seeing if a
cheap register alternative is available. */
- if (MEM_P (op0))
+ if (MEM_P (op0) & !reverse)
{
if (get_best_mem_extraction_insn (&extv, pattern, bitsize, bitnum,
tmode))
@@ -1726,7 +1854,7 @@ extract_bit_field_1 (rtx str_rtx, unsigned HOST_WIDE_INT bitsize,
xop0 = copy_to_reg (xop0);
rtx result = extract_bit_field_1 (xop0, bitsize, bitpos,
unsignedp, target,
- mode, tmode, false);
+ mode, tmode, reverse, false);
if (result)
return result;
delete_insns_since (last);
@@ -1744,9 +1872,21 @@ extract_bit_field_1 (rtx str_rtx, unsigned HOST_WIDE_INT bitsize,
/* Should probably push op0 out to memory and then do a load. */
gcc_assert (int_mode != BLKmode);
- target = extract_fixed_bit_field (int_mode, op0, bitsize, bitnum,
- target, unsignedp);
- return convert_extracted_bit_field (target, mode, tmode, unsignedp);
+ target = extract_fixed_bit_field (int_mode, op0, bitsize, bitnum, target,
+ unsignedp, reverse);
+
+ /* Complex values must be reversed piecewise, so we need to undo the global
+ reversal, convert to the complex mode and reverse again. */
+ if (reverse && COMPLEX_MODE_P (tmode))
+ {
+ target = flip_storage_order (int_mode, target);
+ target = convert_extracted_bit_field (target, mode, tmode, unsignedp);
+ target = flip_storage_order (tmode, target);
+ }
+ else
+ target = convert_extracted_bit_field (target, mode, tmode, unsignedp);
+
+ return target;
}
/* Generate code to extract a byte-field from STR_RTX
@@ -1760,6 +1900,8 @@ extract_bit_field_1 (rtx str_rtx, unsigned HOST_WIDE_INT bitsize,
TMODE is the mode the caller would like the value to have;
but the value may be returned with type MODE instead.
+ If REVERSE is true, the extraction is to be done in reverse order.
+
If a TARGET is specified and we can store in it at no extra cost,
we do so, and return TARGET.
Otherwise, we return a REG of mode TMODE or MODE, with TMODE preferred
@@ -1768,7 +1910,7 @@ extract_bit_field_1 (rtx str_rtx, unsigned HOST_WIDE_INT bitsize,
rtx
extract_bit_field (rtx str_rtx, unsigned HOST_WIDE_INT bitsize,
unsigned HOST_WIDE_INT bitnum, int unsignedp, rtx target,
- machine_mode mode, machine_mode tmode)
+ machine_mode mode, machine_mode tmode, bool reverse)
{
machine_mode mode1;
@@ -1790,6 +1932,8 @@ extract_bit_field (rtx str_rtx, unsigned HOST_WIDE_INT bitsize,
{
rtx result = adjust_bitfield_address (str_rtx, mode1,
bitnum / BITS_PER_UNIT);
+ if (reverse)
+ result = flip_storage_order (mode1, result);
gcc_assert (bitnum % BITS_PER_UNIT == 0);
return convert_extracted_bit_field (result, mode, tmode, unsignedp);
}
@@ -1801,13 +1945,15 @@ extract_bit_field (rtx str_rtx, unsigned HOST_WIDE_INT bitsize,
}
return extract_bit_field_1 (str_rtx, bitsize, bitnum, unsignedp,
- target, mode, tmode, true);
+ target, mode, tmode, reverse, true);
}
/* Use shifts and boolean operations to extract a field of BITSIZE bits
from bit BITNUM of OP0.
UNSIGNEDP is nonzero for an unsigned bit field (don't sign-extend value).
+ If REVERSE is true, the extraction is to be done in reverse order.
+
If TARGET is nonzero, attempts to store the value there
and return TARGET, but this is not guaranteed.
If TARGET is not used, create a pseudo-reg of mode TMODE for the value. */
@@ -1816,7 +1962,7 @@ static rtx
extract_fixed_bit_field (machine_mode tmode, rtx op0,
unsigned HOST_WIDE_INT bitsize,
unsigned HOST_WIDE_INT bitnum, rtx target,
- int unsignedp)
+ int unsignedp, bool reverse)
{
if (MEM_P (op0))
{
@@ -1827,13 +1973,14 @@ extract_fixed_bit_field (machine_mode tmode, rtx op0,
if (mode == VOIDmode)
/* The only way this should occur is if the field spans word
boundaries. */
- return extract_split_bit_field (op0, bitsize, bitnum, unsignedp);
+ return extract_split_bit_field (op0, bitsize, bitnum, unsignedp,
+ reverse);
op0 = narrow_bit_field_mem (op0, mode, bitsize, bitnum, &bitnum);
}
return extract_fixed_bit_field_1 (tmode, op0, bitsize, bitnum,
- target, unsignedp);
+ target, unsignedp, reverse);
}
/* Helper function for extract_fixed_bit_field, extracts
@@ -1843,7 +1990,7 @@ static rtx
extract_fixed_bit_field_1 (machine_mode tmode, rtx op0,
unsigned HOST_WIDE_INT bitsize,
unsigned HOST_WIDE_INT bitnum, rtx target,
- int unsignedp)
+ int unsignedp, bool reverse)
{
machine_mode mode = GET_MODE (op0);
gcc_assert (SCALAR_INT_MODE_P (mode));
@@ -1852,13 +1999,15 @@ extract_fixed_bit_field_1 (machine_mode tmode, rtx op0,
for invalid input, such as extract equivalent of f5 from
gcc.dg/pr48335-2.c. */
- if (BYTES_BIG_ENDIAN)
+ if (reverse ? !BYTES_BIG_ENDIAN : BYTES_BIG_ENDIAN)
/* BITNUM is the distance between our msb and that of OP0.
Convert it to the distance from the lsb. */
bitnum = GET_MODE_BITSIZE (mode) - bitsize - bitnum;
/* Now BITNUM is always the distance between the field's lsb and that of OP0.
We have reduced the big-endian case to the little-endian case. */
+ if (reverse)
+ op0 = flip_storage_order (mode, op0);
if (unsignedp)
{
@@ -1930,11 +2079,14 @@ lshift_value (machine_mode mode, unsigned HOST_WIDE_INT value,
OP0 is the REG, SUBREG or MEM rtx for the first of the two words.
BITSIZE is the field width; BITPOS, position of its first bit, in the word.
- UNSIGNEDP is 1 if should zero-extend the contents; else sign-extend. */
+ UNSIGNEDP is 1 if should zero-extend the contents; else sign-extend.
+
+ If REVERSE is true, the extraction is to be done in reverse order. */
static rtx
extract_split_bit_field (rtx op0, unsigned HOST_WIDE_INT bitsize,
- unsigned HOST_WIDE_INT bitpos, int unsignedp)
+ unsigned HOST_WIDE_INT bitpos, int unsignedp,
+ bool reverse)
{
unsigned int unit;
unsigned int bitsdone = 0;
@@ -1989,11 +2141,11 @@ extract_split_bit_field (rtx op0, unsigned HOST_WIDE_INT bitsize,
whose meaning is determined by BYTES_PER_UNIT.
OFFSET is in UNITs, and UNIT is in bits. */
part = extract_fixed_bit_field (word_mode, word, thissize,
- offset * unit + thispos, 0, 1);
+ offset * unit + thispos, 0, 1, reverse);
bitsdone += thissize;
/* Shift this part into place for the result. */
- if (BYTES_BIG_ENDIAN)
+ if (reverse ? !BYTES_BIG_ENDIAN : BYTES_BIG_ENDIAN)
{
if (bitsize != bitsdone)
part = expand_shift (LSHIFT_EXPR, word_mode, part,
diff --git a/gcc/expmed.h b/gcc/expmed.h
index 1378192703b..0a7afd2c3cf 100644
--- a/gcc/expmed.h
+++ b/gcc/expmed.h
@@ -676,6 +676,10 @@ extern rtx emit_cstore (rtx target, enum insn_code icode, enum rtx_code code,
May emit insns. */
extern rtx negate_rtx (machine_mode, rtx);
+/* Arguments MODE, RTX: return an rtx for the flipping of that value.
+ May emit insns. */
+extern rtx flip_storage_order (enum machine_mode, rtx);
+
/* Expand a logical AND operation. */
extern rtx expand_and (machine_mode, rtx, rtx, rtx);
@@ -707,10 +711,10 @@ extern void store_bit_field (rtx, unsigned HOST_WIDE_INT,
unsigned HOST_WIDE_INT,
unsigned HOST_WIDE_INT,
unsigned HOST_WIDE_INT,
- machine_mode, rtx);
+ machine_mode, rtx, bool);
extern rtx extract_bit_field (rtx, unsigned HOST_WIDE_INT,
unsigned HOST_WIDE_INT, int, rtx,
- machine_mode, machine_mode);
+ machine_mode, machine_mode, bool);
extern rtx extract_low_bits (machine_mode, machine_mode, rtx);
extern rtx expand_mult (machine_mode, rtx, rtx, rtx, int);
extern rtx expand_mult_highpart_adjust (machine_mode, rtx, rtx, rtx, rtx, int);
diff --git a/gcc/expr.c b/gcc/expr.c
index 11c25315238..050642daa4f 100644
--- a/gcc/expr.c
+++ b/gcc/expr.c
@@ -121,11 +121,11 @@ static rtx_insn *compress_float_constant (rtx, rtx);
static rtx get_subtarget (rtx);
static void store_constructor_field (rtx, unsigned HOST_WIDE_INT,
HOST_WIDE_INT, machine_mode,
- tree, int, alias_set_type);
-static void store_constructor (tree, rtx, int, HOST_WIDE_INT);
+ tree, int, alias_set_type, bool);
+static void store_constructor (tree, rtx, int, HOST_WIDE_INT, bool);
static rtx store_field (rtx, HOST_WIDE_INT, HOST_WIDE_INT,
unsigned HOST_WIDE_INT, unsigned HOST_WIDE_INT,
- machine_mode, tree, alias_set_type, bool);
+ machine_mode, tree, alias_set_type, bool, bool);
static unsigned HOST_WIDE_INT highest_pow2_factor_for_target (const_tree, const_tree);
@@ -1678,7 +1678,7 @@ emit_group_load_1 (rtx *tmps, rtx dst, rtx orig_src, tree type, int ssize)
&& (!REG_P (tmps[i]) || GET_MODE (tmps[i]) != mode))
tmps[i] = extract_bit_field (tmps[i], bytelen * BITS_PER_UNIT,
(bytepos % slen0) * BITS_PER_UNIT,
- 1, NULL_RTX, mode, mode);
+ 1, NULL_RTX, mode, mode, false);
}
else
{
@@ -1688,7 +1688,7 @@ emit_group_load_1 (rtx *tmps, rtx dst, rtx orig_src, tree type, int ssize)
mem = assign_stack_temp (GET_MODE (src), slen);
emit_move_insn (mem, src);
tmps[i] = extract_bit_field (mem, bytelen * BITS_PER_UNIT,
- 0, 1, NULL_RTX, mode, mode);
+ 0, 1, NULL_RTX, mode, mode, false);
}
}
/* FIXME: A SIMD parallel will eventually lead to a subreg of a
@@ -1731,7 +1731,7 @@ emit_group_load_1 (rtx *tmps, rtx dst, rtx orig_src, tree type, int ssize)
else
tmps[i] = extract_bit_field (src, bytelen * BITS_PER_UNIT,
bytepos * BITS_PER_UNIT, 1, NULL_RTX,
- mode, mode);
+ mode, mode, false);
if (shift)
tmps[i] = expand_shift (LSHIFT_EXPR, mode, tmps[i],
@@ -2039,7 +2039,7 @@ emit_group_store (rtx orig_dst, rtx src, tree type ATTRIBUTE_UNUSED, int ssize)
store_bit_field (dest,
adj_bytelen * BITS_PER_UNIT, bytepos * BITS_PER_UNIT,
bytepos * BITS_PER_UNIT, ssize * BITS_PER_UNIT - 1,
- VOIDmode, tmps[i]);
+ VOIDmode, tmps[i], false);
}
/* Optimize the access just a bit. */
@@ -2052,7 +2052,7 @@ emit_group_store (rtx orig_dst, rtx src, tree type ATTRIBUTE_UNUSED, int ssize)
else
store_bit_field (dest, bytelen * BITS_PER_UNIT, bytepos * BITS_PER_UNIT,
- 0, 0, mode, tmps[i]);
+ 0, 0, mode, tmps[i], false);
}
/* Copy from the pseudo into the (probable) hard reg. */
@@ -2182,7 +2182,9 @@ copy_blkmode_from_reg (rtx target, rtx srcreg, tree type)
store_bit_field (dst, bitsize, bitpos % BITS_PER_WORD, 0, 0, copy_mode,
extract_bit_field (src, bitsize,
xbitpos % BITS_PER_WORD, 1,
- NULL_RTX, copy_mode, copy_mode));
+ NULL_RTX, copy_mode, copy_mode,
+ false),
+ false);
}
}
@@ -2259,7 +2261,9 @@ copy_blkmode_to_reg (machine_mode mode, tree src)
0, 0, word_mode,
extract_bit_field (src_word, bitsize,
bitpos % BITS_PER_WORD, 1,
- NULL_RTX, word_mode, word_mode));
+ NULL_RTX, word_mode, word_mode,
+ false),
+ false);
}
if (mode == BLKmode)
@@ -3004,7 +3008,8 @@ write_complex_part (rtx cplx, rtx val, bool imag_p)
gcc_assert (MEM_P (cplx) && ibitsize < BITS_PER_WORD);
}
- store_bit_field (cplx, ibitsize, imag_p ? ibitsize : 0, 0, 0, imode, val);
+ store_bit_field (cplx, ibitsize, imag_p ? ibitsize : 0, 0, 0, imode, val,
+ false);
}
/* Extract one of the components of the complex value CPLX. Extract the
@@ -3067,7 +3072,7 @@ read_complex_part (rtx cplx, bool imag_p)
}
return extract_bit_field (cplx, ibitsize, imag_p ? ibitsize : 0,
- true, NULL_RTX, imode, imode);
+ true, NULL_RTX, imode, imode, false);
}
/* A subroutine of emit_move_insn_1. Yet another lowpart generator.
@@ -4457,7 +4462,7 @@ optimize_bitfield_assignment_op (unsigned HOST_WIDE_INT bitsize,
unsigned HOST_WIDE_INT bitregion_start,
unsigned HOST_WIDE_INT bitregion_end,
machine_mode mode1, rtx str_rtx,
- tree to, tree src)
+ tree to, tree src, bool reverse)
{
machine_mode str_mode = GET_MODE (str_rtx);
unsigned int str_bitsize = GET_MODE_BITSIZE (str_mode);
@@ -4530,6 +4535,8 @@ optimize_bitfield_assignment_op (unsigned HOST_WIDE_INT bitsize,
}
else if (!REG_P (str_rtx) && GET_CODE (str_rtx) != SUBREG)
return false;
+ else
+ gcc_assert (!reverse);
/* If the bit field covers the whole REG/MEM, store_field
will likely generate better code. */
@@ -4540,7 +4547,7 @@ optimize_bitfield_assignment_op (unsigned HOST_WIDE_INT bitsize,
if (bitpos + bitsize > str_bitsize)
return false;
- if (BYTES_BIG_ENDIAN)
+ if (reverse ? !BYTES_BIG_ENDIAN : BYTES_BIG_ENDIAN)
bitpos = str_bitsize - bitpos - bitsize;
switch (code)
@@ -4553,7 +4560,7 @@ optimize_bitfield_assignment_op (unsigned HOST_WIDE_INT bitsize,
We might win by one instruction for the other bitfields
too if insv/extv instructions aren't used, so that
can be added later. */
- if (bitpos + bitsize != str_bitsize
+ if ((reverse || bitpos + bitsize != str_bitsize)
&& (bitsize != 1 || TREE_CODE (op1) != INTEGER_CST))
break;
@@ -4571,13 +4578,17 @@ optimize_bitfield_assignment_op (unsigned HOST_WIDE_INT bitsize,
set_mem_expr (str_rtx, 0);
}
- binop = code == PLUS_EXPR ? add_optab : sub_optab;
- if (bitsize == 1 && bitpos + bitsize != str_bitsize)
+ if (bitsize == 1 && (reverse || bitpos + bitsize != str_bitsize))
{
value = expand_and (str_mode, value, const1_rtx, NULL);
binop = xor_optab;
}
+ else
+ binop = code == PLUS_EXPR ? add_optab : sub_optab;
+
value = expand_shift (LSHIFT_EXPR, str_mode, value, bitpos, NULL_RTX, 1);
+ if (reverse)
+ value = flip_storage_order (str_mode, value);
result = expand_binop (str_mode, binop, str_rtx,
value, str_rtx, 1, OPTAB_WIDEN);
if (result != str_rtx)
@@ -4610,6 +4621,8 @@ optimize_bitfield_assignment_op (unsigned HOST_WIDE_INT bitsize,
value = expand_and (str_mode, value, mask, NULL_RTX);
}
value = expand_shift (LSHIFT_EXPR, str_mode, value, bitpos, NULL_RTX, 1);
+ if (reverse)
+ value = flip_storage_order (str_mode, value);
result = expand_binop (str_mode, binop, str_rtx,
value, str_rtx, 1, OPTAB_WIDEN);
if (result != str_rtx)
@@ -4664,10 +4677,10 @@ get_bit_range (unsigned HOST_WIDE_INT *bitstart,
machine_mode rmode;
HOST_WIDE_INT rbitsize, rbitpos;
tree roffset;
- int unsignedp;
- int volatilep = 0;
+ int unsignedp, reversep, volatilep = 0;
get_inner_reference (TREE_OPERAND (exp, 0), &rbitsize, &rbitpos,
- &roffset, &rmode, &unsignedp, &volatilep, false);
+ &roffset, &rmode, &unsignedp, &reversep,
+ &volatilep, false);
if ((rbitpos % BITS_PER_UNIT) != 0)
{
*bitstart = *bitend = 0;
@@ -4783,6 +4796,8 @@ expand_assignment (tree to, tree from, bool nontemporal)
reg = expand_expr (from, NULL_RTX, VOIDmode, EXPAND_NORMAL);
reg = force_not_mem (reg);
mem = expand_expr (to, NULL_RTX, VOIDmode, EXPAND_WRITE);
+ if (TREE_CODE (to) == MEM_REF && REF_REVERSE_STORAGE_ORDER (to))
+ reg = flip_storage_order (mode, reg);
if (icode != CODE_FOR_nothing)
{
@@ -4795,7 +4810,8 @@ expand_assignment (tree to, tree from, bool nontemporal)
expand_insn (icode, 2, ops);
}
else
- store_bit_field (mem, GET_MODE_BITSIZE (mode), 0, 0, 0, mode, reg);
+ store_bit_field (mem, GET_MODE_BITSIZE (mode), 0, 0, 0, mode, reg,
+ false);
return;
}
@@ -4806,7 +4822,8 @@ expand_assignment (tree to, tree from, bool nontemporal)
problem. Same for (partially) storing into a non-memory object. */
if (handled_component_p (to)
|| (TREE_CODE (to) == MEM_REF
- && mem_ref_refers_to_non_mem_p (to))
+ && (REF_REVERSE_STORAGE_ORDER (to)
+ || mem_ref_refers_to_non_mem_p (to)))
|| TREE_CODE (TREE_TYPE (to)) == ARRAY_TYPE)
{
machine_mode mode1;
@@ -4814,13 +4831,12 @@ expand_assignment (tree to, tree from, bool nontemporal)
unsigned HOST_WIDE_INT bitregion_start = 0;
unsigned HOST_WIDE_INT bitregion_end = 0;
tree offset;
- int unsignedp;
- int volatilep = 0;
+ int unsignedp, reversep, volatilep = 0;
tree tem;
push_temp_slots ();
tem = get_inner_reference (to, &bitsize, &bitpos, &offset, &mode1,
- &unsignedp, &volatilep, true);
+ &unsignedp, &reversep, &volatilep, true);
/* Make sure bitpos is not negative, it can wreak havoc later. */
if (bitpos < 0)
@@ -4939,22 +4955,22 @@ expand_assignment (tree to, tree from, bool nontemporal)
if (COMPLEX_MODE_P (TYPE_MODE (TREE_TYPE (from)))
&& bitpos == 0
&& bitsize == mode_bitsize)
- result = store_expr (from, to_rtx, false, nontemporal);
+ result = store_expr (from, to_rtx, false, nontemporal, reversep);
else if (bitsize == mode_bitsize / 2
&& (bitpos == 0 || bitpos == mode_bitsize / 2))
result = store_expr (from, XEXP (to_rtx, bitpos != 0), false,
- nontemporal);
+ nontemporal, reversep);
else if (bitpos + bitsize <= mode_bitsize / 2)
result = store_field (XEXP (to_rtx, 0), bitsize, bitpos,
bitregion_start, bitregion_end,
- mode1, from,
- get_alias_set (to), nontemporal);
+ mode1, from, get_alias_set (to),
+ nontemporal, reversep);
else if (bitpos >= mode_bitsize / 2)
result = store_field (XEXP (to_rtx, 1), bitsize,
bitpos - mode_bitsize / 2,
bitregion_start, bitregion_end,
- mode1, from,
- get_alias_set (to), nontemporal);
+ mode1, from, get_alias_set (to),
+ nontemporal, reversep);
else if (bitpos == 0 && bitsize == mode_bitsize)
{
rtx from_rtx;
@@ -4974,8 +4990,8 @@ expand_assignment (tree to, tree from, bool nontemporal)
write_complex_part (temp, XEXP (to_rtx, 1), true);
result = store_field (temp, bitsize, bitpos,
bitregion_start, bitregion_end,
- mode1, from,
- get_alias_set (to), nontemporal);
+ mode1, from, get_alias_set (to),
+ nontemporal, reversep);
emit_move_insn (XEXP (to_rtx, 0), read_complex_part (temp, false));
emit_move_insn (XEXP (to_rtx, 1), read_complex_part (temp, true));
}
@@ -4994,14 +5010,14 @@ expand_assignment (tree to, tree from, bool nontemporal)
if (optimize_bitfield_assignment_op (bitsize, bitpos,
bitregion_start, bitregion_end,
- mode1,
- to_rtx, to, from))
+ mode1, to_rtx, to, from,
+ reversep))
result = NULL;
else
result = store_field (to_rtx, bitsize, bitpos,
bitregion_start, bitregion_end,
- mode1, from,
- get_alias_set (to), nontemporal);
+ mode1, from, get_alias_set (to),
+ nontemporal, reversep);
}
if (result)
@@ -5155,7 +5171,7 @@ expand_assignment (tree to, tree from, bool nontemporal)
/* Compute FROM and store the value in the rtx we got. */
push_temp_slots ();
- result = store_expr_with_bounds (from, to_rtx, 0, nontemporal, to);
+ result = store_expr_with_bounds (from, to_rtx, 0, nontemporal, false, to);
preserve_temp_slots (result);
pop_temp_slots ();
return;
@@ -5194,12 +5210,14 @@ emit_storent_insn (rtx to, rtx from)
If NONTEMPORAL is true, try using a nontemporal store instruction.
+ If REVERSE is true, the store is to be done in reverse order.
+
If BTARGET is not NULL then computed bounds of EXP are
associated with BTARGET. */
rtx
store_expr_with_bounds (tree exp, rtx target, int call_param_p,
- bool nontemporal, tree btarget)
+ bool nontemporal, bool reverse, tree btarget)
{
rtx temp;
rtx alt_rtl = NULL_RTX;
@@ -5221,7 +5239,8 @@ store_expr_with_bounds (tree exp, rtx target, int call_param_p,
expand_expr (TREE_OPERAND (exp, 0), const0_rtx, VOIDmode,
call_param_p ? EXPAND_STACK_PARM : EXPAND_NORMAL);
return store_expr_with_bounds (TREE_OPERAND (exp, 1), target,
- call_param_p, nontemporal, btarget);
+ call_param_p, nontemporal, reverse,
+ btarget);
}
else if (TREE_CODE (exp) == COND_EXPR && GET_MODE (target) == BLKmode)
{
@@ -5236,12 +5255,12 @@ store_expr_with_bounds (tree exp, rtx target, int call_param_p,
NO_DEFER_POP;
jumpifnot (TREE_OPERAND (exp, 0), lab1, -1);
store_expr_with_bounds (TREE_OPERAND (exp, 1), target, call_param_p,
- nontemporal, btarget);
+ nontemporal, reverse, btarget);
emit_jump_insn (targetm.gen_jump (lab2));
emit_barrier ();
emit_label (lab1);
store_expr_with_bounds (TREE_OPERAND (exp, 2), target, call_param_p,
- nontemporal, btarget);
+ nontemporal, reverse, btarget);
emit_label (lab2);
OK_DEFER_POP;
@@ -5380,9 +5399,9 @@ store_expr_with_bounds (tree exp, rtx target, int call_param_p,
rtx tmp_target;
normal_expr:
- /* If we want to use a nontemporal store, force the value to
- register first. */
- tmp_target = nontemporal ? NULL_RTX : target;
+ /* If we want to use a nontemporal or a reverse order store, force the
+ value into a register first. */
+ tmp_target = nontemporal || reverse ? NULL_RTX : target;
temp = expand_expr_real (exp, tmp_target, GET_MODE (target),
(call_param_p
? EXPAND_STACK_PARM : EXPAND_NORMAL),
@@ -5457,7 +5476,7 @@ store_expr_with_bounds (tree exp, rtx target, int call_param_p,
else
store_bit_field (target,
INTVAL (expr_size (exp)) * BITS_PER_UNIT,
- 0, 0, 0, GET_MODE (temp), temp);
+ 0, 0, 0, GET_MODE (temp), temp, reverse);
}
else
convert_move (target, temp, TYPE_UNSIGNED (TREE_TYPE (exp)));
@@ -5556,6 +5575,8 @@ store_expr_with_bounds (tree exp, rtx target, int call_param_p,
;
else
{
+ if (reverse)
+ temp = flip_storage_order (GET_MODE (target), temp);
temp = force_operand (temp, target);
if (temp != target)
emit_move_insn (target, temp);
@@ -5567,9 +5588,11 @@ store_expr_with_bounds (tree exp, rtx target, int call_param_p,
/* Same as store_expr_with_bounds but ignoring bounds of EXP. */
rtx
-store_expr (tree exp, rtx target, int call_param_p, bool nontemporal)
+store_expr (tree exp, rtx target, int call_param_p, bool nontemporal,
+ bool reverse)
{
- return store_expr_with_bounds (exp, target, call_param_p, nontemporal, NULL);
+ return store_expr_with_bounds (exp, target, call_param_p, nontemporal,
+ reverse, NULL);
}
/* Return true if field F of structure TYPE is a flexible array. */
@@ -5789,8 +5812,12 @@ categorize_ctor_elements_1 (const_tree ctor, HOST_WIDE_INT *p_nz_elts,
init_elts += mult * tc;
if (const_from_elts_p && const_p)
- const_p = initializer_constant_valid_p (value, elt_type)
- != NULL_TREE;
+ const_p
+ = initializer_constant_valid_p (value,
+ elt_type,
+ TYPE_REVERSE_STORAGE_ORDER
+ (TREE_TYPE (ctor)))
+ != NULL_TREE;
}
break;
}
@@ -5895,6 +5922,7 @@ all_zeros_p (const_tree exp)
TARGET, BITSIZE, BITPOS, MODE, EXP are as for store_field.
CLEARED is as for store_constructor.
ALIAS_SET is the alias set to use for any stores.
+ If REVERSE is true, the store is to be done in reverse order.
This provides a recursive shortcut back to store_constructor when it isn't
necessary to go through store_field. This is so that we can pass through
@@ -5904,7 +5932,8 @@ all_zeros_p (const_tree exp)
static void
store_constructor_field (rtx target, unsigned HOST_WIDE_INT bitsize,
HOST_WIDE_INT bitpos, machine_mode mode,
- tree exp, int cleared, alias_set_type alias_set)
+ tree exp, int cleared,
+ alias_set_type alias_set, bool reverse)
{
if (TREE_CODE (exp) == CONSTRUCTOR
/* We can only call store_constructor recursively if the size and
@@ -5933,10 +5962,12 @@ store_constructor_field (rtx target, unsigned HOST_WIDE_INT bitsize,
set_mem_alias_set (target, alias_set);
}
- store_constructor (exp, target, cleared, bitsize / BITS_PER_UNIT);
+ store_constructor (exp, target, cleared, bitsize / BITS_PER_UNIT,
+ reverse);
}
else
- store_field (target, bitsize, bitpos, 0, 0, mode, exp, alias_set, false);
+ store_field (target, bitsize, bitpos, 0, 0, mode, exp, alias_set, false,
+ reverse);
}
@@ -5962,10 +5993,12 @@ fields_length (const_tree type)
CLEARED is true if TARGET is known to have been zero'd.
SIZE is the number of bytes of TARGET we are allowed to modify: this
may not be the same as the size of EXP if we are assigning to a field
- which has been packed to exclude padding bits. */
+ which has been packed to exclude padding bits.
+ If REVERSE is true, the store is to be done in reverse order. */
static void
-store_constructor (tree exp, rtx target, int cleared, HOST_WIDE_INT size)
+store_constructor (tree exp, rtx target, int cleared, HOST_WIDE_INT size,
+ bool reverse)
{
tree type = TREE_TYPE (exp);
HOST_WIDE_INT exp_size = int_size_in_bytes (type);
@@ -5979,6 +6012,9 @@ store_constructor (tree exp, rtx target, int cleared, HOST_WIDE_INT size)
unsigned HOST_WIDE_INT idx;
tree field, value;
+ /* The storage order is specified for every aggregate type. */
+ reverse = TYPE_REVERSE_STORAGE_ORDER (type);
+
/* If size is zero or the target is already cleared, do nothing. */
if (size == 0 || cleared)
cleared = 1;
@@ -6122,7 +6158,8 @@ store_constructor (tree exp, rtx target, int cleared, HOST_WIDE_INT size)
store_constructor_field (to_rtx, bitsize, bitpos, mode,
value, cleared,
- get_alias_set (TREE_TYPE (field)));
+ get_alias_set (TREE_TYPE (field)),
+ reverse);
}
break;
}
@@ -6137,6 +6174,9 @@ store_constructor (tree exp, rtx target, int cleared, HOST_WIDE_INT size)
HOST_WIDE_INT minelt = 0;
HOST_WIDE_INT maxelt = 0;
+ /* The storage order is specified for every aggregate type. */
+ reverse = TYPE_REVERSE_STORAGE_ORDER (type);
+
domain = TYPE_DOMAIN (type);
const_bounds_p = (TYPE_MIN_VALUE (domain)
&& TYPE_MAX_VALUE (domain)
@@ -6277,7 +6317,7 @@ store_constructor (tree exp, rtx target, int cleared, HOST_WIDE_INT size)
store_constructor_field
(target, bitsize, bitpos, mode, value, cleared,
- get_alias_set (elttype));
+ get_alias_set (elttype), reverse);
}
}
else
@@ -6292,7 +6332,7 @@ store_constructor (tree exp, rtx target, int cleared, HOST_WIDE_INT size)
VAR_DECL, NULL_TREE, domain);
index_r = gen_reg_rtx (promote_decl_mode (index, NULL));
SET_DECL_RTL (index, index_r);
- store_expr (lo_index, index_r, 0, false);
+ store_expr (lo_index, index_r, 0, false, reverse);
/* Build the head of the loop. */
do_pending_stack_adjust ();
@@ -6317,9 +6357,9 @@ store_constructor (tree exp, rtx target, int cleared, HOST_WIDE_INT size)
xtarget = adjust_address (xtarget, mode, 0);
if (TREE_CODE (value) == CONSTRUCTOR)
store_constructor (value, xtarget, cleared,
- bitsize / BITS_PER_UNIT);
+ bitsize / BITS_PER_UNIT, reverse);
else
- store_expr (value, xtarget, 0, false);
+ store_expr (value, xtarget, 0, false, reverse);
/* Generate a conditional jump to exit the loop. */
exit_cond = build2 (LT_EXPR, integer_type_node,
@@ -6362,7 +6402,7 @@ store_constructor (tree exp, rtx target, int cleared, HOST_WIDE_INT size)
expand_normal (position),
highest_pow2_factor (position));
xtarget = adjust_address (xtarget, mode, 0);
- store_expr (value, xtarget, 0, false);
+ store_expr (value, xtarget, 0, false, reverse);
}
else
{
@@ -6380,7 +6420,8 @@ store_constructor (tree exp, rtx target, int cleared, HOST_WIDE_INT size)
MEM_KEEP_ALIAS_SET_P (target) = 1;
}
store_constructor_field (target, bitsize, bitpos, mode, value,
- cleared, get_alias_set (elttype));
+ cleared, get_alias_set (elttype),
+ reverse);
}
}
break;
@@ -6513,7 +6554,7 @@ store_constructor (tree exp, rtx target, int cleared, HOST_WIDE_INT size)
: eltmode;
bitpos = eltpos * elt_size;
store_constructor_field (target, bitsize, bitpos, value_mode,
- value, cleared, alias);
+ value, cleared, alias, reverse);
}
}
@@ -6546,14 +6587,16 @@ store_constructor (tree exp, rtx target, int cleared, HOST_WIDE_INT size)
(in general) be different from that for TARGET, since TARGET is a
reference to the containing structure.
- If NONTEMPORAL is true, try generating a nontemporal store. */
+ If NONTEMPORAL is true, try generating a nontemporal store.
+
+ If REVERSE is true, the store is to be done in reverse order. */
static rtx
store_field (rtx target, HOST_WIDE_INT bitsize, HOST_WIDE_INT bitpos,
unsigned HOST_WIDE_INT bitregion_start,
unsigned HOST_WIDE_INT bitregion_end,
machine_mode mode, tree exp,
- alias_set_type alias_set, bool nontemporal)
+ alias_set_type alias_set, bool nontemporal, bool reverse)
{
if (TREE_CODE (exp) == ERROR_MARK)
return const0_rtx;
@@ -6568,7 +6611,7 @@ store_field (rtx target, HOST_WIDE_INT bitsize, HOST_WIDE_INT bitpos,
/* We're storing into a struct containing a single __complex. */
gcc_assert (!bitpos);
- return store_expr (exp, target, 0, nontemporal);
+ return store_expr (exp, target, 0, nontemporal, reverse);
}
/* If the structure is in a register or if the component
@@ -6637,16 +6680,27 @@ store_field (rtx target, HOST_WIDE_INT bitsize, HOST_WIDE_INT bitpos,
temp = expand_normal (exp);
- /* If BITSIZE is narrower than the size of the type of EXP
- we will be narrowing TEMP. Normally, what's wanted are the
- low-order bits. However, if EXP's type is a record and this is
- big-endian machine, we want the upper BITSIZE bits. */
- if (BYTES_BIG_ENDIAN && GET_MODE_CLASS (GET_MODE (temp)) == MODE_INT
- && bitsize < (HOST_WIDE_INT) GET_MODE_BITSIZE (GET_MODE (temp))
- && TREE_CODE (TREE_TYPE (exp)) == RECORD_TYPE)
- temp = expand_shift (RSHIFT_EXPR, GET_MODE (temp), temp,
- GET_MODE_BITSIZE (GET_MODE (temp)) - bitsize,
- NULL_RTX, 1);
+ /* If the value has a record type and an integral mode then, if BITSIZE
+ is narrower than this mode and this is for big-endian data, we must
+ first put the value into the low-order bits. Moreover, the field may
+ be not aligned on a byte boundary; in this case, if it has reverse
+ storage order, it needs to be accessed as a scalar field with reverse
+ storage order and we must first put the value into target order. */
+ if (TREE_CODE (TREE_TYPE (exp)) == RECORD_TYPE
+ && GET_MODE_CLASS (GET_MODE (temp)) == MODE_INT)
+ {
+ HOST_WIDE_INT size = GET_MODE_BITSIZE (GET_MODE (temp));
+
+ reverse = TYPE_REVERSE_STORAGE_ORDER (TREE_TYPE (exp));
+
+ if (reverse)
+ temp = flip_storage_order (GET_MODE (temp), temp);
+
+ if (bitsize < size
+ && reverse ? !BYTES_BIG_ENDIAN : BYTES_BIG_ENDIAN)
+ temp = expand_shift (RSHIFT_EXPR, GET_MODE (temp), temp,
+ size - bitsize, NULL_RTX, 1);
+ }
/* Unless MODE is VOIDmode or BLKmode, convert TEMP to MODE. */
if (mode != VOIDmode && mode != BLKmode
@@ -6706,7 +6760,7 @@ store_field (rtx target, HOST_WIDE_INT bitsize, HOST_WIDE_INT bitpos,
temp_target = gen_reg_rtx (mode);
temp_target
= extract_bit_field (temp, size * BITS_PER_UNIT, 0, 1,
- temp_target, mode, mode);
+ temp_target, mode, mode, false);
temp = temp_target;
}
}
@@ -6714,7 +6768,7 @@ store_field (rtx target, HOST_WIDE_INT bitsize, HOST_WIDE_INT bitpos,
/* Store the value in the bitfield. */
store_bit_field (target, bitsize, bitpos,
bitregion_start, bitregion_end,
- mode, temp);
+ mode, temp, reverse);
return const0_rtx;
}
@@ -6734,11 +6788,11 @@ store_field (rtx target, HOST_WIDE_INT bitsize, HOST_WIDE_INT bitpos,
if (TREE_CODE (exp) == CONSTRUCTOR && bitsize >= 0)
{
gcc_assert (bitsize % BITS_PER_UNIT == 0);
- store_constructor (exp, to_rtx, 0, bitsize/BITS_PER_UNIT);
+ store_constructor (exp, to_rtx, 0, bitsize / BITS_PER_UNIT, reverse);
return to_rtx;
}
- return store_expr (exp, to_rtx, 0, nontemporal);
+ return store_expr (exp, to_rtx, 0, nontemporal, reverse);
}
}
@@ -6747,7 +6801,8 @@ store_field (rtx target, HOST_WIDE_INT bitsize, HOST_WIDE_INT bitpos,
codes and find the ultimate containing object, which we return.
We set *PBITSIZE to the size in bits that we want, *PBITPOS to the
- bit position, and *PUNSIGNEDP to the signedness of the field.
+ bit position, *PUNSIGNEDP to the signedness and *PREVERSEP to the
+ storage order of the field.
If the position of the field is variable, we store a tree
giving the variable offset (in units) in *POFFSET.
This offset is in addition to the bit position.
@@ -6781,7 +6836,7 @@ tree
get_inner_reference (tree exp, HOST_WIDE_INT *pbitsize,
HOST_WIDE_INT *pbitpos, tree *poffset,
machine_mode *pmode, int *punsignedp,
- int *pvolatilep, bool keep_aligning)
+ int *preversep, int *pvolatilep, bool keep_aligning)
{
tree size_tree = 0;
machine_mode mode = VOIDmode;
@@ -6789,8 +6844,8 @@ get_inner_reference (tree exp, HOST_WIDE_INT *pbitsize,
tree offset = size_zero_node;
offset_int bit_offset = 0;
- /* First get the mode, signedness, and size. We do this from just the
- outermost expression. */
+ /* First get the mode, signedness, storage order and size. We do this from
+ just the outermost expression. */
*pbitsize = -1;
if (TREE_CODE (exp) == COMPONENT_REF)
{
@@ -6843,6 +6898,8 @@ get_inner_reference (tree exp, HOST_WIDE_INT *pbitsize,
*pbitsize = tree_to_uhwi (size_tree);
}
+ *preversep = reverse_storage_order_for_component_p (exp);
+
/* Compute cumulative bit-offset for nested component-refs and array-refs,
and find the ultimate containing object. */
while (1)
@@ -7519,7 +7576,7 @@ expand_expr_addr_expr_1 (tree exp, rtx target, machine_mode tmode,
rtx result, subtarget;
tree inner, offset;
HOST_WIDE_INT bitsize, bitpos;
- int volatilep, unsignedp;
+ int unsignedp, reversep, volatilep = 0;
machine_mode mode1;
/* If we are taking the address of a constant and are at the top level,
@@ -7626,8 +7683,8 @@ expand_expr_addr_expr_1 (tree exp, rtx target, machine_mode tmode,
handle "aligning nodes" here: we can just bypass them because
they won't change the final object whose address will be returned
(they actually exist only for that purpose). */
- inner = get_inner_reference (exp, &bitsize, &bitpos, &offset,
- &mode1, &unsignedp, &volatilep, false);
+ inner = get_inner_reference (exp, &bitsize, &bitpos, &offset, &mode1,
+ &unsignedp, &reversep, &volatilep, false);
break;
}
@@ -7811,7 +7868,7 @@ expand_constructor (tree exp, rtx target, enum expand_modifier modifier,
target = assign_temp (type, TREE_ADDRESSABLE (exp), 1);
}
- store_constructor (exp, target, 0, int_expr_size (exp));
+ store_constructor (exp, target, 0, int_expr_size (exp), false);
return target;
}
@@ -8084,11 +8141,12 @@ expand_expr_real_2 (sepops ops, rtx target, machine_mode tmode,
store_expr (treeop0,
adjust_address (target, TYPE_MODE (valtype), 0),
modifier == EXPAND_STACK_PARM,
- false);
+ false, TYPE_REVERSE_STORAGE_ORDER (type));
else
{
- gcc_assert (REG_P (target));
+ gcc_assert (REG_P (target)
+ && !TYPE_REVERSE_STORAGE_ORDER (type));
/* Store this field into a union of the proper type. */
store_field (target,
@@ -8096,7 +8154,8 @@ expand_expr_real_2 (sepops ops, rtx target, machine_mode tmode,
(treeop0))
* BITS_PER_UNIT),
(HOST_WIDE_INT) GET_MODE_BITSIZE (mode)),
- 0, 0, 0, TYPE_MODE (valtype), treeop0, 0, false);
+ 0, 0, 0, TYPE_MODE (valtype), treeop0, 0,
+ false, false);
}
/* Return the entire union. */
@@ -9131,7 +9190,7 @@ expand_expr_real_2 (sepops ops, rtx target, machine_mode tmode,
int index = BYTES_BIG_ENDIAN ? GET_MODE_NUNITS (vec_mode) - 1 : 0;
int bitsize = GET_MODE_UNIT_BITSIZE (vec_mode);
temp = extract_bit_field (temp, bitsize, bitsize * index, unsignedp,
- target, mode, mode);
+ target, mode, mode, false);
gcc_assert (temp);
return temp;
}
@@ -9287,14 +9346,14 @@ expand_expr_real_2 (sepops ops, rtx target, machine_mode tmode,
jumpifnot (treeop0, lab0, -1);
store_expr (treeop1, temp,
modifier == EXPAND_STACK_PARM,
- false);
+ false, false);
emit_jump_insn (targetm.gen_jump (lab1));
emit_barrier ();
emit_label (lab0);
store_expr (treeop2, temp,
modifier == EXPAND_STACK_PARM,
- false);
+ false, false);
emit_label (lab1);
OK_DEFER_POP;
@@ -9847,6 +9906,7 @@ expand_expr_real_1 (tree exp, rtx target, machine_mode tmode,
case MEM_REF:
{
+ const bool reverse = REF_REVERSE_STORAGE_ORDER (exp);
addr_space_t as
= TYPE_ADDR_SPACE (TREE_TYPE (TREE_TYPE (TREE_OPERAND (exp, 0))));
machine_mode address_mode;
@@ -9861,6 +9921,7 @@ expand_expr_real_1 (tree exp, rtx target, machine_mode tmode,
HOST_WIDE_INT offset = mem_ref_offset (exp).to_short_addr ();
base = TREE_OPERAND (base, 0);
if (offset == 0
+ && !reverse
&& tree_fits_uhwi_p (TYPE_SIZE (type))
&& (GET_MODE_BITSIZE (DECL_MODE (base))
== tree_to_uhwi (TYPE_SIZE (type))))
@@ -9870,13 +9931,14 @@ expand_expr_real_1 (tree exp, rtx target, machine_mode tmode,
{
temp = assign_stack_temp (DECL_MODE (base),
GET_MODE_SIZE (DECL_MODE (base)));
- store_expr (base, temp, 0, false);
+ store_expr (base, temp, 0, false, false);
temp = adjust_address (temp, BLKmode, offset);
set_mem_size (temp, int_size_in_bytes (type));
return temp;
}
exp = build3 (BIT_FIELD_REF, type, base, TYPE_SIZE (type),
bitsize_int (offset * BITS_PER_UNIT));
+ REF_REVERSE_STORAGE_ORDER (exp) = reverse;
return expand_expr (exp, target, tmode, modifier);
}
address_mode = targetm.addr_space.address_mode (as);
@@ -9926,8 +9988,12 @@ expand_expr_real_1 (tree exp, rtx target, machine_mode tmode,
0, TYPE_UNSIGNED (TREE_TYPE (exp)),
(modifier == EXPAND_STACK_PARM
? NULL_RTX : target),
- mode, mode);
+ mode, mode, false);
}
+ if (reverse
+ && modifier != EXPAND_MEMORY
+ && modifier != EXPAND_WRITE)
+ temp = flip_storage_order (mode, temp);
return temp;
}
@@ -10133,9 +10199,10 @@ expand_expr_real_1 (tree exp, rtx target, machine_mode tmode,
machine_mode mode1, mode2;
HOST_WIDE_INT bitsize, bitpos;
tree offset;
- int volatilep = 0, must_force_mem;
- tree tem = get_inner_reference (exp, &bitsize, &bitpos, &offset,
- &mode1, &unsignedp, &volatilep, true);
+ int reversep, volatilep = 0, must_force_mem;
+ tree tem
+ = get_inner_reference (exp, &bitsize, &bitpos, &offset, &mode1,
+ &unsignedp, &reversep, &volatilep, true);
rtx orig_op0, memloc;
bool clear_mem_expr = false;
@@ -10190,7 +10257,11 @@ expand_expr_real_1 (tree exp, rtx target, machine_mode tmode,
{
if (bitpos == 0
&& bitsize == GET_MODE_BITSIZE (GET_MODE (op0)))
- return op0;
+ {
+ if (reversep)
+ op0 = flip_storage_order (GET_MODE (op0), op0);
+ return op0;
+ }
if (bitpos == 0
&& bitsize == GET_MODE_BITSIZE (GET_MODE (XEXP (op0, 0)))
&& bitsize)
@@ -10376,20 +10447,38 @@ 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
+ 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
+ && GET_MODE_CLASS (ext_mode) == MODE_INT)
+ reversep = TYPE_REVERSE_STORAGE_ORDER (type);
+
op0 = extract_bit_field (op0, bitsize, bitpos, unsignedp,
(modifier == EXPAND_STACK_PARM
? NULL_RTX : target),
- ext_mode, ext_mode);
-
- /* If the result is a record type and BITSIZE is narrower than
- the mode of OP0, an integral mode, and this is a big endian
- machine, we must put the field into the high-order bits. */
- if (TREE_CODE (type) == RECORD_TYPE && BYTES_BIG_ENDIAN
- && GET_MODE_CLASS (GET_MODE (op0)) == MODE_INT
- && bitsize < (HOST_WIDE_INT) GET_MODE_BITSIZE (GET_MODE (op0)))
- op0 = expand_shift (LSHIFT_EXPR, GET_MODE (op0), op0,
- GET_MODE_BITSIZE (GET_MODE (op0))
- - bitsize, op0, 1);
+ ext_mode, ext_mode, reversep);
+
+ /* If the result has a record 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. */
+ if (TREE_CODE (type) == RECORD_TYPE
+ && GET_MODE_CLASS (GET_MODE (op0)) == MODE_INT)
+ {
+ HOST_WIDE_INT size = GET_MODE_BITSIZE (GET_MODE (op0));
+
+ if (bitsize < size
+ && reversep ? !BYTES_BIG_ENDIAN : BYTES_BIG_ENDIAN)
+ op0 = expand_shift (LSHIFT_EXPR, GET_MODE (op0), op0,
+ size - bitsize, op0, 1);
+
+ if (reversep)
+ op0 = flip_storage_order (GET_MODE (op0), op0);
+ }
/* If the result type is BLKmode, store the data into a temporary
of the appropriate type, but with the mode corresponding to the
@@ -10435,6 +10524,12 @@ expand_expr_real_1 (tree exp, rtx target, machine_mode tmode,
set_mem_expr (op0, NULL_TREE);
MEM_VOLATILE_P (op0) |= volatilep;
+
+ if (reversep
+ && modifier != EXPAND_MEMORY
+ && modifier != EXPAND_WRITE)
+ op0 = flip_storage_order (mode1, op0);
+
if (mode == mode1 || mode1 == BLKmode || mode1 == tmode
|| modifier == EXPAND_CONST_ADDRESS
|| modifier == EXPAND_INITIALIZER)
@@ -10498,17 +10593,16 @@ expand_expr_real_1 (tree exp, rtx target, machine_mode tmode,
machine_mode mode1;
HOST_WIDE_INT bitsize, bitpos;
tree offset;
- int unsignedp;
- int volatilep = 0;
+ int unsignedp, reversep, volatilep = 0;
tree tem
- = get_inner_reference (treeop0, &bitsize, &bitpos,
- &offset, &mode1, &unsignedp, &volatilep,
- true);
+ = get_inner_reference (treeop0, &bitsize, &bitpos, &offset, &mode1,
+ &unsignedp, &reversep, &volatilep, true);
rtx orig_op0;
/* ??? We should work harder and deal with non-zero offsets. */
if (!offset
&& (bitpos % BITS_PER_UNIT) == 0
+ && !reversep
&& bitsize >= 0
&& compare_tree_int (TYPE_SIZE (type), bitsize) == 0)
{
@@ -10582,7 +10676,7 @@ expand_expr_real_1 (tree exp, rtx target, machine_mode tmode,
else if (reduce_bit_field)
return extract_bit_field (op0, TYPE_PRECISION (type), 0,
TYPE_UNSIGNED (type), NULL_RTX,
- mode, mode);
+ mode, mode, false);
/* As a last resort, spill op0 to memory, and reload it in a
different mode. */
else if (!MEM_P (op0))
diff --git a/gcc/expr.h b/gcc/expr.h
index a2c8e1d1e57..33a35aa6820 100644
--- a/gcc/expr.h
+++ b/gcc/expr.h
@@ -212,6 +212,7 @@ extern rtx_insn *emit_move_complex_push (machine_mode, rtx, rtx);
extern rtx_insn *emit_move_complex_parts (rtx, rtx);
extern rtx read_complex_part (rtx, bool);
extern void write_complex_part (rtx, rtx, bool);
+extern rtx read_complex_part (rtx, bool);
extern rtx emit_move_resolve_push (machine_mode, rtx);
/* Push a block of length SIZE (perhaps variable)
@@ -229,8 +230,8 @@ extern void expand_assignment (tree, tree, bool);
and storing the value into TARGET.
If SUGGEST_REG is nonzero, copy the value through a register
and return that register, if that is possible. */
-extern rtx store_expr_with_bounds (tree, rtx, int, bool, tree);
-extern rtx store_expr (tree, rtx, int, bool);
+extern rtx store_expr_with_bounds (tree, rtx, int, bool, bool, tree);
+extern rtx store_expr (tree, rtx, int, bool, bool);
/* Given an rtx that may include add and multiply operations,
generate them as insns and return a pseudo-reg containing the value.
diff --git a/gcc/flag-types.h b/gcc/flag-types.h
index 6301cea4807..88a760c5d4e 100644
--- a/gcc/flag-types.h
+++ b/gcc/flag-types.h
@@ -165,7 +165,6 @@ enum stack_check_type
/* Names for the different levels of -Wstrict-overflow=N. The numeric
values here correspond to N. */
-
enum warn_strict_overflow_code
{
/* Overflow warning that should be issued with -Wall: a questionable
@@ -195,6 +194,13 @@ enum fp_contract_mode {
FP_CONTRACT_FAST = 2
};
+/* Scalar storage order kind. */
+enum scalar_storage_order_kind {
+ SSO_NATIVE = 0,
+ SSO_BIG_ENDIAN,
+ SSO_LITTLE_ENDIAN
+};
+
/* Vectorizer cost-model. */
enum vect_cost_model {
VECT_COST_MODEL_UNLIMITED = 0,
@@ -203,7 +209,6 @@ enum vect_cost_model {
VECT_COST_MODEL_DEFAULT = 3
};
-
/* Different instrumentation modes. */
enum sanitize_code {
/* AddressSanitizer. */
diff --git a/gcc/fold-const-call.c b/gcc/fold-const-call.c
index 5af2c635313..49793a5ab6f 100644
--- a/gcc/fold-const-call.c
+++ b/gcc/fold-const-call.c
@@ -24,7 +24,9 @@ along with GCC; see the file COPYING3. If not see
#include "tree.h"
#include "stor-layout.h"
#include "options.h"
+#include "fold-const.h"
#include "fold-const-call.h"
+#include "tm.h" /* For C[LT]Z_DEFINED_AT_ZERO. */
/* Functions that test for certain constant types, abstracting away the
decision about whether to check for overflow. */
@@ -47,6 +49,31 @@ complex_cst_p (tree t)
return TREE_CODE (t) == COMPLEX_CST;
}
+/* Return true if ARG is a constant in the range of the host size_t.
+ Store it in *SIZE_OUT if so. */
+
+static inline bool
+host_size_t_cst_p (tree t, size_t *size_out)
+{
+ if (integer_cst_p (t)
+ && wi::min_precision (t, UNSIGNED) <= sizeof (size_t) * CHAR_BIT)
+ {
+ *size_out = tree_to_uhwi (t);
+ return true;
+ }
+ return false;
+}
+
+/* RES is the result of a comparison in which < 0 means "less", 0 means
+ "equal" and > 0 means "more". Canonicalize it to -1, 0 or 1 and
+ return it in type TYPE. */
+
+static inline tree
+build_cmp_result (tree type, int res)
+{
+ return build_int_cst (type, res < 0 ? -1 : res > 0 ? 1 : 0);
+}
+
/* M is the result of trying to constant-fold an expression (starting
with clear MPFR flags) and INEXACT says whether the result in M is
exact or inexact. Return true if M can be used as a constant-folded
@@ -526,6 +553,20 @@ fold_const_builtin_load_exponent (real_value *result, const real_value *arg0,
return real_equal (&initial_result, result);
}
+/* Fold a call to __builtin_nan or __builtin_nans with argument ARG and
+ return type TYPE. QUIET is true if a quiet rather than signalling
+ NaN is required. */
+
+static tree
+fold_const_builtin_nan (tree type, tree arg, bool quiet)
+{
+ REAL_VALUE_TYPE real;
+ const char *str = c_getstr (arg);
+ if (str && real_nan (&real, str, quiet, TYPE_MODE (type)))
+ return build_real (type, real);
+ return NULL_TREE;
+}
+
/* Try to evaluate:
*RESULT = FN (*ARG)
@@ -736,6 +777,94 @@ fold_const_call_ss (wide_int *result, built_in_function fn,
/* Not yet folded to a constant. */
return false;
+ CASE_FLT_FN (BUILT_IN_FINITE):
+ case BUILT_IN_FINITED32:
+ case BUILT_IN_FINITED64:
+ case BUILT_IN_FINITED128:
+ case BUILT_IN_ISFINITE:
+ *result = wi::shwi (real_isfinite (arg) ? 1 : 0, precision);
+ return true;
+
+ CASE_FLT_FN (BUILT_IN_ISINF):
+ case BUILT_IN_ISINFD32:
+ case BUILT_IN_ISINFD64:
+ case BUILT_IN_ISINFD128:
+ if (real_isinf (arg))
+ *result = wi::shwi (arg->sign ? -1 : 1, precision);
+ else
+ *result = wi::shwi (0, precision);
+ return true;
+
+ CASE_FLT_FN (BUILT_IN_ISNAN):
+ case BUILT_IN_ISNAND32:
+ case BUILT_IN_ISNAND64:
+ case BUILT_IN_ISNAND128:
+ *result = wi::shwi (real_isnan (arg) ? 1 : 0, precision);
+ return true;
+
+ default:
+ return false;
+ }
+}
+
+/* Try to evaluate:
+
+ *RESULT = FN (ARG)
+
+ where ARG_TYPE is the type of ARG and PRECISION is the number of bits
+ in the result. Return true on success. */
+
+static bool
+fold_const_call_ss (wide_int *result, built_in_function fn,
+ const wide_int_ref &arg, unsigned int precision,
+ tree arg_type)
+{
+ switch (fn)
+ {
+ CASE_INT_FN (BUILT_IN_FFS):
+ *result = wi::shwi (wi::ffs (arg), precision);
+ return true;
+
+ CASE_INT_FN (BUILT_IN_CLZ):
+ {
+ int tmp;
+ if (wi::ne_p (arg, 0))
+ tmp = wi::clz (arg);
+ else if (! CLZ_DEFINED_VALUE_AT_ZERO (TYPE_MODE (arg_type), tmp))
+ tmp = TYPE_PRECISION (arg_type);
+ *result = wi::shwi (tmp, precision);
+ return true;
+ }
+
+ CASE_INT_FN (BUILT_IN_CTZ):
+ {
+ int tmp;
+ if (wi::ne_p (arg, 0))
+ tmp = wi::ctz (arg);
+ else if (! CTZ_DEFINED_VALUE_AT_ZERO (TYPE_MODE (arg_type), tmp))
+ tmp = TYPE_PRECISION (arg_type);
+ *result = wi::shwi (tmp, precision);
+ return true;
+ }
+
+ CASE_INT_FN (BUILT_IN_CLRSB):
+ *result = wi::shwi (wi::clrsb (arg), precision);
+ return true;
+
+ CASE_INT_FN (BUILT_IN_POPCOUNT):
+ *result = wi::shwi (wi::popcount (arg), precision);
+ return true;
+
+ CASE_INT_FN (BUILT_IN_PARITY):
+ *result = wi::shwi (wi::parity (arg), precision);
+ return true;
+
+ case BUILT_IN_BSWAP16:
+ case BUILT_IN_BSWAP32:
+ case BUILT_IN_BSWAP64:
+ *result = wide_int::from (arg, precision, TYPE_SIGN (arg_type)).bswap ();
+ return true;
+
default:
return false;
}
@@ -882,15 +1011,27 @@ fold_const_call_cc (real_value *result_real, real_value *result_imag,
}
}
-/* Try to fold FN (ARG) to a constant. Return the constant on success,
- otherwise return null. TYPE is the type of the return value. */
+/* Subroutine of fold_const_call, with the same interface. Handle cases
+ where the arguments and result are numerical. */
-tree
-fold_const_call (built_in_function fn, tree type, tree arg)
+static tree
+fold_const_call_1 (built_in_function fn, tree type, tree arg)
{
machine_mode mode = TYPE_MODE (type);
machine_mode arg_mode = TYPE_MODE (TREE_TYPE (arg));
+ if (integer_cst_p (arg))
+ {
+ if (SCALAR_INT_MODE_P (mode))
+ {
+ wide_int result;
+ if (fold_const_call_ss (&result, fn, arg, TYPE_PRECISION (type),
+ TREE_TYPE (arg)))
+ return wide_int_to_tree (type, result);
+ }
+ return NULL_TREE;
+ }
+
if (real_cst_p (arg))
{
gcc_checking_assert (SCALAR_FLOAT_MODE_P (arg_mode));
@@ -965,6 +1106,33 @@ fold_const_call (built_in_function fn, tree type, tree arg)
return NULL_TREE;
}
+/* Try to fold FN (ARG) to a constant. Return the constant on success,
+ otherwise return null. TYPE is the type of the return value. */
+
+tree
+fold_const_call (built_in_function fn, tree type, tree arg)
+{
+ switch (fn)
+ {
+ case BUILT_IN_STRLEN:
+ if (const char *str = c_getstr (arg))
+ return build_int_cst (type, strlen (str));
+ return NULL_TREE;
+
+ CASE_FLT_FN (BUILT_IN_NAN):
+ case BUILT_IN_NAND32:
+ case BUILT_IN_NAND64:
+ case BUILT_IN_NAND128:
+ return fold_const_builtin_nan (type, arg, true);
+
+ CASE_FLT_FN (BUILT_IN_NANS):
+ return fold_const_builtin_nan (type, arg, false);
+
+ default:
+ return fold_const_call_1 (fn, type, arg);
+ }
+}
+
/* Try to evaluate:
*RESULT = FN (*ARG0, *ARG1)
@@ -1093,11 +1261,11 @@ fold_const_call_ccc (real_value *result_real, real_value *result_imag,
}
}
-/* Try to fold FN (ARG0, ARG1) to a constant. Return the constant on success,
- otherwise return null. TYPE is the type of the return value. */
+/* Subroutine of fold_const_call, with the same interface. Handle cases
+ where the arguments and result are numerical. */
-tree
-fold_const_call (built_in_function fn, tree type, tree arg0, tree arg1)
+static tree
+fold_const_call_1 (built_in_function fn, tree type, tree arg0, tree arg1)
{
machine_mode mode = TYPE_MODE (type);
machine_mode arg0_mode = TYPE_MODE (TREE_TYPE (arg0));
@@ -1185,6 +1353,35 @@ fold_const_call (built_in_function fn, tree type, tree arg0, tree arg1)
return NULL_TREE;
}
+/* Try to fold FN (ARG0, ARG1) to a constant. Return the constant on success,
+ otherwise return null. TYPE is the type of the return value. */
+
+tree
+fold_const_call (built_in_function fn, tree type, tree arg0, tree arg1)
+{
+ const char *p0, *p1;
+ switch (fn)
+ {
+ case BUILT_IN_STRSPN:
+ if ((p0 = c_getstr (arg0)) && (p1 = c_getstr (arg1)))
+ return build_int_cst (type, strspn (p0, p1));
+ return NULL_TREE;
+
+ case BUILT_IN_STRCSPN:
+ if ((p0 = c_getstr (arg0)) && (p1 = c_getstr (arg1)))
+ return build_int_cst (type, strcspn (p0, p1));
+ return NULL_TREE;
+
+ case BUILT_IN_STRCMP:
+ if ((p0 = c_getstr (arg0)) && (p1 = c_getstr (arg1)))
+ return build_cmp_result (type, strcmp (p0, p1));
+ return NULL_TREE;
+
+ default:
+ return fold_const_call_1 (fn, type, arg0, arg1);
+ }
+}
+
/* Try to evaluate:
*RESULT = FN (*ARG0, *ARG1, *ARG2)
@@ -1206,12 +1403,12 @@ fold_const_call_ssss (real_value *result, built_in_function fn,
}
}
-/* Try to fold FN (ARG0, ARG1, ARG2) to a constant. Return the constant on
- success, otherwise return null. TYPE is the type of the return value. */
+/* Subroutine of fold_const_call, with the same interface. Handle cases
+ where the arguments and result are numerical. */
-tree
-fold_const_call (built_in_function fn, tree type, tree arg0, tree arg1,
- tree arg2)
+static tree
+fold_const_call_1 (built_in_function fn, tree type, tree arg0, tree arg1,
+ tree arg2)
{
machine_mode mode = TYPE_MODE (type);
machine_mode arg0_mode = TYPE_MODE (TREE_TYPE (arg0));
@@ -1241,6 +1438,39 @@ fold_const_call (built_in_function fn, tree type, tree arg0, tree arg1,
return NULL_TREE;
}
+/* Try to fold FN (ARG0, ARG1, ARG2) to a constant. Return the constant on
+ success, otherwise return null. TYPE is the type of the return value. */
+
+tree
+fold_const_call (built_in_function fn, tree type, tree arg0, tree arg1,
+ tree arg2)
+{
+ const char *p0, *p1;
+ size_t s2;
+ switch (fn)
+ {
+ case BUILT_IN_STRNCMP:
+ if ((p0 = c_getstr (arg0))
+ && (p1 = c_getstr (arg1))
+ && host_size_t_cst_p (arg2, &s2))
+ return build_int_cst (type, strncmp (p0, p1, s2));
+ return NULL_TREE;
+
+ case BUILT_IN_BCMP:
+ case BUILT_IN_MEMCMP:
+ if ((p0 = c_getstr (arg0))
+ && (p1 = c_getstr (arg1))
+ && host_size_t_cst_p (arg2, &s2)
+ && s2 <= strlen (p0)
+ && s2 <= strlen (p1))
+ return build_cmp_result (type, memcmp (p0, p1, s2));
+ return NULL_TREE;
+
+ default:
+ return fold_const_call_1 (fn, type, arg0, arg1, arg2);
+ }
+}
+
/* Fold a fma operation with arguments ARG[012]. */
tree
diff --git a/gcc/fold-const.c b/gcc/fold-const.c
index ee9b34910df..8b437ab8f26 100644
--- a/gcc/fold-const.c
+++ b/gcc/fold-const.c
@@ -114,12 +114,12 @@ static int operand_equal_for_comparison_p (tree, tree, tree);
static int twoval_comparison_p (tree, tree *, tree *, int *);
static tree eval_subst (location_t, tree, tree, tree, tree, tree);
static tree make_bit_field_ref (location_t, tree, tree,
- HOST_WIDE_INT, HOST_WIDE_INT, int);
+ HOST_WIDE_INT, HOST_WIDE_INT, int, int);
static tree optimize_bit_field_compare (location_t, enum tree_code,
tree, tree, tree);
static tree decode_field_reference (location_t, tree, HOST_WIDE_INT *,
HOST_WIDE_INT *,
- machine_mode *, int *, int *,
+ machine_mode *, int *, int *, int *,
tree *, tree *);
static int simple_operand_p (const_tree);
static bool simple_operand_p_2 (tree);
@@ -1545,7 +1545,11 @@ const_unop (enum tree_code code, tree type, tree arg0)
return fold_convert_const (code, type, arg0);
case ADDR_SPACE_CONVERT_EXPR:
- if (integer_zerop (arg0))
+ /* If the source address is 0, and the source address space
+ cannot have a valid object at 0, fold to dest type null. */
+ if (integer_zerop (arg0)
+ && !(targetm.addr_space.zero_address_valid
+ (TYPE_ADDR_SPACE (TREE_TYPE (TREE_TYPE (arg0))))))
return fold_convert_const (code, type, arg0);
break;
@@ -2649,8 +2653,7 @@ combine_comparisons (location_t loc,
}
/* Return nonzero if two operands (typically of the same tree node)
- are necessarily equal. If either argument has side-effects this
- function returns zero. FLAGS modifies behavior as follows:
+ are necessarily equal. FLAGS modifies behavior as follows:
If OEP_ONLY_CONST is set, only return nonzero for constants.
This function tests whether the operands are indistinguishable;
@@ -2675,9 +2678,14 @@ combine_comparisons (location_t loc,
to ensure that global memory is unchanged in between.
If OEP_ADDRESS_OF is set, we are actually comparing addresses of objects,
- not values of expressions. OEP_CONSTANT_ADDRESS_OF in addition to
- OEP_ADDRESS_OF is used for ADDR_EXPR with TREE_CONSTANT flag set and we
- further ignore any side effects on SAVE_EXPRs then. */
+ not values of expressions.
+
+ Unless OEP_MATCH_SIDE_EFFECTS is set, the function returns false on
+ any operand with side effect. This is unnecesarily conservative in the
+ case we know that arg0 and arg1 are in disjoint code paths (such as in
+ ?: operator). In addition OEP_MATCH_SIDE_EFFECTS is used when comparing
+ addresses with TREE_CONSTANT flag set so we know that &var == &var
+ even if var is volatile. */
int
operand_equal_p (const_tree arg0, const_tree arg1, unsigned int flags)
@@ -2693,14 +2701,20 @@ operand_equal_p (const_tree arg0, const_tree arg1, unsigned int flags)
if (!TREE_TYPE (arg0) || !TREE_TYPE (arg1))
return 0;
+ /* We cannot consider pointers to different address space equal. */
+ if (POINTER_TYPE_P (TREE_TYPE (arg0))
+ && POINTER_TYPE_P (TREE_TYPE (arg1))
+ && (TYPE_ADDR_SPACE (TREE_TYPE (TREE_TYPE (arg0)))
+ != TYPE_ADDR_SPACE (TREE_TYPE (TREE_TYPE (arg1)))))
+ return 0;
+
/* Check equality of integer constants before bailing out due to
precision differences. */
if (TREE_CODE (arg0) == INTEGER_CST && TREE_CODE (arg1) == INTEGER_CST)
{
/* Address of INTEGER_CST is not defined; check that we did not forget
- to drop the OEP_ADDRESS_OF/OEP_CONSTANT_ADDRESS_OF flags. */
- gcc_checking_assert (!(flags
- & (OEP_ADDRESS_OF | OEP_CONSTANT_ADDRESS_OF)));
+ to drop the OEP_ADDRESS_OF flags. */
+ gcc_checking_assert (!(flags & OEP_ADDRESS_OF));
return tree_int_cst_equal (arg0, arg1);
}
@@ -2716,13 +2730,6 @@ operand_equal_p (const_tree arg0, const_tree arg1, unsigned int flags)
!= POINTER_TYPE_P (TREE_TYPE (arg1)))
return 0;
- /* We cannot consider pointers to different address space equal. */
- if (POINTER_TYPE_P (TREE_TYPE (arg0))
- && POINTER_TYPE_P (TREE_TYPE (arg1))
- && (TYPE_ADDR_SPACE (TREE_TYPE (TREE_TYPE (arg0)))
- != TYPE_ADDR_SPACE (TREE_TYPE (TREE_TYPE (arg1)))))
- return 0;
-
/* If both types don't have the same precision, then it is not safe
to strip NOPs. */
if (element_precision (TREE_TYPE (arg0))
@@ -2806,7 +2813,7 @@ operand_equal_p (const_tree arg0, const_tree arg1, unsigned int flags)
they are necessarily equal as well. */
if (arg0 == arg1 && ! (flags & OEP_ONLY_CONST)
&& (TREE_CODE (arg0) == SAVE_EXPR
- || (flags & OEP_CONSTANT_ADDRESS_OF)
+ || (flags & OEP_MATCH_SIDE_EFFECTS)
|| (! TREE_SIDE_EFFECTS (arg0) && ! TREE_SIDE_EFFECTS (arg1))))
return 1;
@@ -2865,11 +2872,10 @@ operand_equal_p (const_tree arg0, const_tree arg1, unsigned int flags)
TREE_STRING_LENGTH (arg0)));
case ADDR_EXPR:
- gcc_checking_assert (!(flags
- & (OEP_ADDRESS_OF | OEP_CONSTANT_ADDRESS_OF)));
+ gcc_checking_assert (!(flags & OEP_ADDRESS_OF));
return operand_equal_p (TREE_OPERAND (arg0, 0), TREE_OPERAND (arg1, 0),
flags | OEP_ADDRESS_OF
- | OEP_CONSTANT_ADDRESS_OF);
+ | OEP_MATCH_SIDE_EFFECTS);
case CONSTRUCTOR:
/* In GIMPLE empty constructors are allowed in initializers of
aggregates. */
@@ -2928,7 +2934,7 @@ operand_equal_p (const_tree arg0, const_tree arg1, unsigned int flags)
/* If either of the pointer (or reference) expressions we are
dereferencing contain a side effect, these cannot be equal,
but their addresses can be. */
- if ((flags & OEP_CONSTANT_ADDRESS_OF) == 0
+ if ((flags & OEP_MATCH_SIDE_EFFECTS) == 0
&& (TREE_SIDE_EFFECTS (arg0)
|| TREE_SIDE_EFFECTS (arg1)))
return 0;
@@ -2936,11 +2942,11 @@ operand_equal_p (const_tree arg0, const_tree arg1, unsigned int flags)
switch (TREE_CODE (arg0))
{
case INDIRECT_REF:
- if (!(flags & (OEP_ADDRESS_OF | OEP_CONSTANT_ADDRESS_OF))
+ if (!(flags & OEP_ADDRESS_OF)
&& (TYPE_ALIGN (TREE_TYPE (arg0))
!= TYPE_ALIGN (TREE_TYPE (arg1))))
return 0;
- flags &= ~(OEP_CONSTANT_ADDRESS_OF|OEP_ADDRESS_OF);
+ flags &= ~OEP_ADDRESS_OF;
return OP_SAME (0);
case REALPART_EXPR:
@@ -2950,7 +2956,7 @@ operand_equal_p (const_tree arg0, const_tree arg1, unsigned int flags)
case TARGET_MEM_REF:
case MEM_REF:
- if (!(flags & (OEP_ADDRESS_OF | OEP_CONSTANT_ADDRESS_OF)))
+ if (!(flags & OEP_ADDRESS_OF))
{
/* Require equal access sizes */
if (TYPE_SIZE (TREE_TYPE (arg0)) != TYPE_SIZE (TREE_TYPE (arg1))
@@ -2975,7 +2981,7 @@ operand_equal_p (const_tree arg0, const_tree arg1, unsigned int flags)
!= TYPE_ALIGN (TREE_TYPE (arg1)))
return 0;
}
- flags &= ~(OEP_CONSTANT_ADDRESS_OF|OEP_ADDRESS_OF);
+ flags &= ~OEP_ADDRESS_OF;
return (OP_SAME (0) && OP_SAME (1)
/* TARGET_MEM_REF require equal extra operands. */
&& (TREE_CODE (arg0) != TARGET_MEM_REF
@@ -2990,7 +2996,7 @@ operand_equal_p (const_tree arg0, const_tree arg1, unsigned int flags)
may have different types but same value here. */
if (!OP_SAME (0))
return 0;
- flags &= ~(OEP_CONSTANT_ADDRESS_OF|OEP_ADDRESS_OF);
+ flags &= ~OEP_ADDRESS_OF;
return ((tree_int_cst_equal (TREE_OPERAND (arg0, 1),
TREE_OPERAND (arg1, 1))
|| OP_SAME (1))
@@ -3003,13 +3009,13 @@ operand_equal_p (const_tree arg0, const_tree arg1, unsigned int flags)
if (!OP_SAME_WITH_NULL (0)
|| !OP_SAME (1))
return 0;
- flags &= ~(OEP_CONSTANT_ADDRESS_OF|OEP_ADDRESS_OF);
+ flags &= ~OEP_ADDRESS_OF;
return OP_SAME_WITH_NULL (2);
case BIT_FIELD_REF:
if (!OP_SAME (0))
return 0;
- flags &= ~(OEP_CONSTANT_ADDRESS_OF|OEP_ADDRESS_OF);
+ flags &= ~OEP_ADDRESS_OF;
return OP_SAME (1) && OP_SAME (2);
default:
@@ -3021,9 +3027,7 @@ operand_equal_p (const_tree arg0, const_tree arg1, unsigned int flags)
{
case ADDR_EXPR:
/* Be sure we pass right ADDRESS_OF flag. */
- gcc_checking_assert (!(flags
- & (OEP_ADDRESS_OF
- | OEP_CONSTANT_ADDRESS_OF)));
+ gcc_checking_assert (!(flags & OEP_ADDRESS_OF));
return operand_equal_p (TREE_OPERAND (arg0, 0),
TREE_OPERAND (arg1, 0),
flags | OEP_ADDRESS_OF);
@@ -3089,6 +3093,7 @@ operand_equal_p (const_tree arg0, const_tree arg1, unsigned int flags)
return 0;
}
+ /* FIXME: We could skip this test for OEP_MATCH_SIDE_EFFECTS. */
{
unsigned int cef = call_expr_flags (arg0);
if (flags & OEP_PURE_SAME)
@@ -3687,15 +3692,17 @@ distribute_real_division (location_t loc, enum tree_code code, tree type,
}
/* Return a BIT_FIELD_REF of type TYPE to refer to BITSIZE bits of INNER
- starting at BITPOS. The field is unsigned if UNSIGNEDP is nonzero. */
+ starting at BITPOS. The field is unsigned if UNSIGNEDP is nonzero
+ and uses reverse storage order if REVERSEP is nonzero. */
static tree
make_bit_field_ref (location_t loc, tree inner, tree type,
- HOST_WIDE_INT bitsize, HOST_WIDE_INT bitpos, int unsignedp)
+ HOST_WIDE_INT bitsize, HOST_WIDE_INT bitpos,
+ int unsignedp, int reversep)
{
tree result, bftype;
- if (bitpos == 0)
+ if (bitpos == 0 && !reversep)
{
tree size = TYPE_SIZE (TREE_TYPE (inner));
if ((INTEGRAL_TYPE_P (TREE_TYPE (inner))
@@ -3712,6 +3719,7 @@ make_bit_field_ref (location_t loc, tree inner, tree type,
result = build3_loc (loc, BIT_FIELD_REF, bftype, inner,
size_int (bitsize), bitsize_int (bitpos));
+ REF_REVERSE_STORAGE_ORDER (result) = reversep;
if (bftype != type)
result = fold_convert_loc (loc, type, result);
@@ -3749,6 +3757,7 @@ optimize_bit_field_compare (location_t loc, enum tree_code code,
int const_p = TREE_CODE (rhs) == INTEGER_CST;
machine_mode lmode, rmode, nmode;
int lunsignedp, runsignedp;
+ int lreversep, rreversep;
int lvolatilep = 0, rvolatilep = 0;
tree linner, rinner = NULL_TREE;
tree mask;
@@ -3760,20 +3769,23 @@ optimize_bit_field_compare (location_t loc, enum tree_code code,
do anything if the inner expression is a PLACEHOLDER_EXPR since we
then will no longer be able to replace it. */
linner = get_inner_reference (lhs, &lbitsize, &lbitpos, &offset, &lmode,
- &lunsignedp, &lvolatilep, false);
+ &lunsignedp, &lreversep, &lvolatilep, false);
if (linner == lhs || lbitsize == GET_MODE_BITSIZE (lmode) || lbitsize < 0
|| offset != 0 || TREE_CODE (linner) == PLACEHOLDER_EXPR || lvolatilep)
return 0;
- if (!const_p)
+ if (const_p)
+ rreversep = lreversep;
+ else
{
/* If this is not a constant, we can only do something if bit positions,
- sizes, and signedness are the same. */
- rinner = get_inner_reference (rhs, &rbitsize, &rbitpos, &offset, &rmode,
- &runsignedp, &rvolatilep, false);
+ sizes, signedness and storage order are the same. */
+ rinner
+ = get_inner_reference (rhs, &rbitsize, &rbitpos, &offset, &rmode,
+ &runsignedp, &rreversep, &rvolatilep, false);
if (rinner == rhs || lbitpos != rbitpos || lbitsize != rbitsize
- || lunsignedp != runsignedp || offset != 0
+ || lunsignedp != runsignedp || lreversep != rreversep || offset != 0
|| TREE_CODE (rinner) == PLACEHOLDER_EXPR || rvolatilep)
return 0;
}
@@ -3801,7 +3813,7 @@ optimize_bit_field_compare (location_t loc, enum tree_code code,
if (nbitsize == lbitsize)
return 0;
- if (BYTES_BIG_ENDIAN)
+ if (lreversep ? !BYTES_BIG_ENDIAN : BYTES_BIG_ENDIAN)
lbitpos = nbitsize - lbitsize - lbitpos;
/* Make the mask to be used against the extracted field. */
@@ -3818,17 +3830,17 @@ optimize_bit_field_compare (location_t loc, enum tree_code code,
make_bit_field_ref (loc, linner,
unsigned_type,
nbitsize, nbitpos,
- 1),
+ 1, lreversep),
mask),
fold_build2_loc (loc, BIT_AND_EXPR, unsigned_type,
make_bit_field_ref (loc, rinner,
unsigned_type,
nbitsize, nbitpos,
- 1),
+ 1, rreversep),
mask));
- /* Otherwise, we are handling the constant case. See if the constant is too
- big for the field. Warn and return a tree of for 0 (false) if so. We do
+ /* Otherwise, we are handling the constant case. See if the constant is too
+ big for the field. Warn and return a tree for 0 (false) if so. We do
this not only for its own sake, but to avoid having to test for this
error case below. If we didn't, we might generate wrong code.
@@ -3866,7 +3878,8 @@ optimize_bit_field_compare (location_t loc, enum tree_code code,
/* Make a new bitfield reference, shift the constant over the
appropriate number of bits and mask it with the computed mask
(in case this was a signed field). If we changed it, make a new one. */
- lhs = make_bit_field_ref (loc, linner, unsigned_type, nbitsize, nbitpos, 1);
+ lhs = make_bit_field_ref (loc, linner, unsigned_type, nbitsize, nbitpos, 1,
+ lreversep);
rhs = const_binop (BIT_AND_EXPR,
const_binop (LSHIFT_EXPR,
@@ -3894,6 +3907,8 @@ optimize_bit_field_compare (location_t loc, enum tree_code code,
*PUNSIGNEDP is set to the signedness of the field.
+ *PREVERSEP is set to the storage order of the field.
+
*PMASK is set to the mask used. This is either contained in a
BIT_AND_EXPR or derived from the width of the field.
@@ -3905,7 +3920,7 @@ optimize_bit_field_compare (location_t loc, enum tree_code code,
static tree
decode_field_reference (location_t loc, tree exp, HOST_WIDE_INT *pbitsize,
HOST_WIDE_INT *pbitpos, machine_mode *pmode,
- int *punsignedp, int *pvolatilep,
+ int *punsignedp, int *preversep, int *pvolatilep,
tree *pmask, tree *pand_mask)
{
tree outer_type = 0;
@@ -3938,7 +3953,7 @@ decode_field_reference (location_t loc, tree exp, HOST_WIDE_INT *pbitsize,
}
inner = get_inner_reference (exp, pbitsize, pbitpos, &offset, pmode,
- punsignedp, pvolatilep, false);
+ punsignedp, preversep, pvolatilep, false);
if ((inner == exp && and_mask == 0)
|| *pbitsize < 0 || offset != 0
|| TREE_CODE (inner) == PLACEHOLDER_EXPR)
@@ -5440,6 +5455,7 @@ fold_truth_andor_1 (location_t loc, enum tree_code code, tree truth_type,
HOST_WIDE_INT xll_bitpos, xlr_bitpos, xrl_bitpos, xrr_bitpos;
HOST_WIDE_INT lnbitsize, lnbitpos, rnbitsize, rnbitpos;
int ll_unsignedp, lr_unsignedp, rl_unsignedp, rr_unsignedp;
+ int ll_reversep, lr_reversep, rl_reversep, rr_reversep;
machine_mode ll_mode, lr_mode, rl_mode, rr_mode;
machine_mode lnmode, rnmode;
tree ll_mask, lr_mask, rl_mask, rr_mask;
@@ -5552,33 +5568,39 @@ fold_truth_andor_1 (location_t loc, enum tree_code code, tree truth_type,
volatilep = 0;
ll_inner = decode_field_reference (loc, ll_arg,
&ll_bitsize, &ll_bitpos, &ll_mode,
- &ll_unsignedp, &volatilep, &ll_mask,
- &ll_and_mask);
+ &ll_unsignedp, &ll_reversep, &volatilep,
+ &ll_mask, &ll_and_mask);
lr_inner = decode_field_reference (loc, lr_arg,
&lr_bitsize, &lr_bitpos, &lr_mode,
- &lr_unsignedp, &volatilep, &lr_mask,
- &lr_and_mask);
+ &lr_unsignedp, &lr_reversep, &volatilep,
+ &lr_mask, &lr_and_mask);
rl_inner = decode_field_reference (loc, rl_arg,
&rl_bitsize, &rl_bitpos, &rl_mode,
- &rl_unsignedp, &volatilep, &rl_mask,
- &rl_and_mask);
+ &rl_unsignedp, &rl_reversep, &volatilep,
+ &rl_mask, &rl_and_mask);
rr_inner = decode_field_reference (loc, rr_arg,
&rr_bitsize, &rr_bitpos, &rr_mode,
- &rr_unsignedp, &volatilep, &rr_mask,
- &rr_and_mask);
+ &rr_unsignedp, &rr_reversep, &volatilep,
+ &rr_mask, &rr_and_mask);
/* It must be true that the inner operation on the lhs of each
comparison must be the same if we are to be able to do anything.
Then see if we have constants. If not, the same must be true for
the rhs's. */
- if (volatilep || ll_inner == 0 || rl_inner == 0
+ if (volatilep
+ || ll_reversep != rl_reversep
+ || ll_inner == 0 || rl_inner == 0
|| ! operand_equal_p (ll_inner, rl_inner, 0))
return 0;
if (TREE_CODE (lr_arg) == INTEGER_CST
&& TREE_CODE (rr_arg) == INTEGER_CST)
- l_const = lr_arg, r_const = rr_arg;
- else if (lr_inner == 0 || rr_inner == 0
+ {
+ l_const = lr_arg, r_const = rr_arg;
+ lr_reversep = ll_reversep;
+ }
+ else if (lr_reversep != rr_reversep
+ || lr_inner == 0 || rr_inner == 0
|| ! operand_equal_p (lr_inner, rr_inner, 0))
return 0;
else
@@ -5631,7 +5653,7 @@ fold_truth_andor_1 (location_t loc, enum tree_code code, tree truth_type,
lntype = lang_hooks.types.type_for_size (lnbitsize, 1);
xll_bitpos = ll_bitpos - lnbitpos, xrl_bitpos = rl_bitpos - lnbitpos;
- if (BYTES_BIG_ENDIAN)
+ if (ll_reversep ? !BYTES_BIG_ENDIAN : BYTES_BIG_ENDIAN)
{
xll_bitpos = lnbitsize - xll_bitpos - ll_bitsize;
xrl_bitpos = lnbitsize - xrl_bitpos - rl_bitsize;
@@ -5696,7 +5718,7 @@ fold_truth_andor_1 (location_t loc, enum tree_code code, tree truth_type,
rntype = lang_hooks.types.type_for_size (rnbitsize, 1);
xlr_bitpos = lr_bitpos - rnbitpos, xrr_bitpos = rr_bitpos - rnbitpos;
- if (BYTES_BIG_ENDIAN)
+ if (lr_reversep ? !BYTES_BIG_ENDIAN : BYTES_BIG_ENDIAN)
{
xlr_bitpos = rnbitsize - xlr_bitpos - lr_bitsize;
xrr_bitpos = rnbitsize - xrr_bitpos - rr_bitsize;
@@ -5719,12 +5741,12 @@ fold_truth_andor_1 (location_t loc, enum tree_code code, tree truth_type,
if (lnbitsize == rnbitsize && xll_bitpos == xlr_bitpos)
{
lhs = make_bit_field_ref (loc, ll_inner, lntype, lnbitsize, lnbitpos,
- ll_unsignedp || rl_unsignedp);
+ ll_unsignedp || rl_unsignedp, ll_reversep);
if (! all_ones_mask_p (ll_mask, lnbitsize))
lhs = build2 (BIT_AND_EXPR, lntype, lhs, ll_mask);
rhs = make_bit_field_ref (loc, lr_inner, rntype, rnbitsize, rnbitpos,
- lr_unsignedp || rr_unsignedp);
+ lr_unsignedp || rr_unsignedp, lr_reversep);
if (! all_ones_mask_p (lr_mask, rnbitsize))
rhs = build2 (BIT_AND_EXPR, rntype, rhs, lr_mask);
@@ -5747,10 +5769,12 @@ fold_truth_andor_1 (location_t loc, enum tree_code code, tree truth_type,
lhs = make_bit_field_ref (loc, ll_inner, lntype,
ll_bitsize + rl_bitsize,
- MIN (ll_bitpos, rl_bitpos), ll_unsignedp);
+ MIN (ll_bitpos, rl_bitpos),
+ ll_unsignedp, ll_reversep);
rhs = make_bit_field_ref (loc, lr_inner, rntype,
lr_bitsize + rr_bitsize,
- MIN (lr_bitpos, rr_bitpos), lr_unsignedp);
+ MIN (lr_bitpos, rr_bitpos),
+ lr_unsignedp, lr_reversep);
ll_mask = const_binop (RSHIFT_EXPR, ll_mask,
size_int (MIN (xll_bitpos, xrl_bitpos)));
@@ -5813,7 +5837,7 @@ fold_truth_andor_1 (location_t loc, enum tree_code code, tree truth_type,
that field, perform the mask operation. Then compare with the
merged constant. */
result = make_bit_field_ref (loc, ll_inner, lntype, lnbitsize, lnbitpos,
- ll_unsignedp || rl_unsignedp);
+ ll_unsignedp || rl_unsignedp, ll_reversep);
ll_mask = const_binop (BIT_IOR_EXPR, ll_mask, rl_mask);
if (! all_ones_mask_p (ll_mask, lnbitsize))
@@ -7677,10 +7701,11 @@ fold_unary_loc (location_t loc, enum tree_code code, tree type, tree op0)
HOST_WIDE_INT bitsize, bitpos;
tree offset;
machine_mode mode;
- int unsignedp, volatilep;
- tree base = TREE_OPERAND (op0, 0);
- base = get_inner_reference (base, &bitsize, &bitpos, &offset,
- &mode, &unsignedp, &volatilep, false);
+ int unsignedp, reversep, volatilep;
+ tree base
+ = get_inner_reference (TREE_OPERAND (op0, 0), &bitsize, &bitpos,
+ &offset, &mode, &unsignedp, &reversep,
+ &volatilep, false);
/* If the reference was to a (constant) zero offset, we can use
the address of the base if it has the same base type
as the result type and the pointer type is unqualified. */
@@ -7816,8 +7841,12 @@ fold_unary_loc (location_t loc, enum tree_code code, tree type, tree op0)
case VIEW_CONVERT_EXPR:
if (TREE_CODE (op0) == MEM_REF)
- return fold_build2_loc (loc, MEM_REF, type,
- TREE_OPERAND (op0, 0), TREE_OPERAND (op0, 1));
+ {
+ tem = fold_build2_loc (loc, MEM_REF, type,
+ TREE_OPERAND (op0, 0), TREE_OPERAND (op0, 1));
+ REF_REVERSE_STORAGE_ORDER (tem) = REF_REVERSE_STORAGE_ORDER (op0);
+ return tem;
+ }
return NULL_TREE;
@@ -8334,7 +8363,7 @@ fold_comparison (location_t loc, enum tree_code code, tree type,
tree base0, base1, offset0 = NULL_TREE, offset1 = NULL_TREE;
HOST_WIDE_INT bitsize, bitpos0 = 0, bitpos1 = 0;
machine_mode mode;
- int volatilep, unsignedp;
+ int volatilep, reversep, unsignedp;
bool indirect_base0 = false, indirect_base1 = false;
/* Get base and offset for the access. Strip ADDR_EXPR for
@@ -8344,9 +8373,10 @@ fold_comparison (location_t loc, enum tree_code code, tree type,
base0 = arg0;
if (TREE_CODE (arg0) == ADDR_EXPR)
{
- base0 = get_inner_reference (TREE_OPERAND (arg0, 0),
- &bitsize, &bitpos0, &offset0, &mode,
- &unsignedp, &volatilep, false);
+ base0
+ = get_inner_reference (TREE_OPERAND (arg0, 0),
+ &bitsize, &bitpos0, &offset0, &mode,
+ &unsignedp, &reversep, &volatilep, false);
if (TREE_CODE (base0) == INDIRECT_REF)
base0 = TREE_OPERAND (base0, 0);
else
@@ -8378,9 +8408,10 @@ fold_comparison (location_t loc, enum tree_code code, tree type,
base1 = arg1;
if (TREE_CODE (arg1) == ADDR_EXPR)
{
- base1 = get_inner_reference (TREE_OPERAND (arg1, 0),
- &bitsize, &bitpos1, &offset1, &mode,
- &unsignedp, &volatilep, false);
+ base1
+ = get_inner_reference (TREE_OPERAND (arg1, 0),
+ &bitsize, &bitpos1, &offset1, &mode,
+ &unsignedp, &reversep, &volatilep, false);
if (TREE_CODE (base1) == INDIRECT_REF)
base1 = TREE_OPERAND (base1, 0);
else
@@ -14310,15 +14341,15 @@ split_address_to_core_and_offset (tree exp,
{
tree core;
machine_mode mode;
- int unsignedp, volatilep;
+ int unsignedp, reversep, volatilep;
HOST_WIDE_INT bitsize;
location_t loc = EXPR_LOCATION (exp);
if (TREE_CODE (exp) == ADDR_EXPR)
{
core = get_inner_reference (TREE_OPERAND (exp, 0), &bitsize, pbitpos,
- poffset, &mode, &unsignedp, &volatilep,
- false);
+ poffset, &mode, &unsignedp, &reversep,
+ &volatilep, false);
core = build_fold_addr_expr_loc (loc, core);
}
else
@@ -14397,3 +14428,24 @@ fold_build_pointer_plus_hwi_loc (location_t loc, tree ptr, HOST_WIDE_INT off)
return fold_build2_loc (loc, POINTER_PLUS_EXPR, TREE_TYPE (ptr),
ptr, size_int (off));
}
+
+/* Return a char pointer for a C string if it is a string constant
+ or sum of string constant and integer constant. */
+
+const char *
+c_getstr (tree src)
+{
+ tree offset_node;
+
+ src = string_constant (src, &offset_node);
+ if (src == 0)
+ return 0;
+
+ if (offset_node == 0)
+ return TREE_STRING_POINTER (src);
+ else if (!tree_fits_uhwi_p (offset_node)
+ || compare_tree_int (offset_node, TREE_STRING_LENGTH (src) - 1) > 0)
+ return 0;
+
+ return TREE_STRING_POINTER (src) + tree_to_uhwi (offset_node);
+}
diff --git a/gcc/fold-const.h b/gcc/fold-const.h
index 97d18cf0e22..94a21b7652a 100644
--- a/gcc/fold-const.h
+++ b/gcc/fold-const.h
@@ -180,6 +180,7 @@ extern tree exact_inverse (tree, tree);
extern tree const_unop (enum tree_code, tree, tree);
extern tree const_binop (enum tree_code, tree, tree, tree);
extern bool negate_mathfn_p (enum built_in_function);
+extern const char *c_getstr (tree);
/* Return OFF converted to a pointer offset type suitable as offset for
POINTER_PLUS_EXPR. Use location LOC for this conversion. */
diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog
index bd3fa7647a5..cd4c94e6764 100644
--- a/gcc/fortran/ChangeLog
+++ b/gcc/fortran/ChangeLog
@@ -1,3 +1,66 @@
+2015-11-08 Steven g. Kargl <kargl@gcc.gnu.org>
+
+ PR fortran/68053
+ * decl.c (add_init_expr_to_sym): Try to reduce initialization expression
+ before testing for a constant value.
+
+2015-11-08 Andre Vehreschild <vehre@gcc.gnu.org>
+
+ PR fortran/68218
+ * trans-array.c (gfc_array_init_size): Add gfc_evaluate_now() when
+ array spec in allocate is a function call.
+
+2015-11-08 Steven G. Kargl <kargl@gc.gnu.org>
+
+ PR fortran/68224
+ * array.c (match_array_element_spec): Check of invalid NULL().
+ While here, fix nearby comments.
+
+2015-11-08 Paul Thomas <pault@gcc.gnu.org>
+
+ PR fortran/68196
+ * class.c (has_finalizer_component): Prevent infinite recursion
+ through this function if the derived type and that of its
+ component are the same.
+ * trans-types.c (gfc_get_derived_type): Do the same for proc
+ pointers by ignoring the explicit interface for the component.
+
+ PR fortran/66465
+ * check.c (same_type_check): If either of the expressions is
+ BT_PROCEDURE, use the typespec from the symbol, rather than the
+ expression.
+
+2015-11-07 Steven G. Kargl <kargl@gcc.gnu.org>
+
+ PR fortran/68153
+ * check.c (gfc_check_reshape): Improve check for valid SHAPE argument.
+
+2015-11-07 Steven G. Kargl <kargl@gcc.gnu.org>
+
+ PR fortran/68151
+ * match.c (match_case_selector): Check for invalid type.
+
+2015-11-06 David Malcolm <dmalcolm@redhat.com>
+
+ * cpp.c (cb_cpp_error): Convert parameter from location_t to
+ rich_location *. Eliminate the "column_override" parameter.
+ * error.c (gfc_warning): Update for change in signature of
+ diagnostic_set_info.
+ (gfc_format_decoder): Update handling of %C/%L for changes
+ to struct text_info.
+ (gfc_diagnostic_starter): Use richloc when determining whether to
+ print one locus or two. When handling a location that will
+ involve a call to diagnostic_show_locus, only attempt to print the
+ locus for the primary location, and don't call into
+ diagnostic_print_caret_line.
+ (gfc_warning_now_at): Update for change in signature of
+ diagnostic_set_info.
+ (gfc_warning_now): Likewise.
+ (gfc_error_now): Likewise.
+ (gfc_fatal_error): Likewise.
+ (gfc_error): Likewise.
+ (gfc_internal_error): Likewise.
+
2015-11-05 Cesar Philippidis <cesar@codesourcery.com>
* openmp.c (gfc_match_omp_clauses): Update support for the tile
@@ -80,7 +143,7 @@
PR fortran/68154
* decl.c (add_init_expr_to_sym): if the char length in the typespec
- is NULL, check for and use a constructor.
+ is NULL, check for and use a constructor.
2015-10-30 Steven G. Kargl <kargl@gcc.gnu.org>
diff --git a/gcc/fortran/array.c b/gcc/fortran/array.c
index 2083044774f..0b676af551e 100644
--- a/gcc/fortran/array.c
+++ b/gcc/fortran/array.c
@@ -147,9 +147,9 @@ matched:
}
-/* Match an array reference, whether it is the whole array or a
- particular elements or a section. If init is set, the reference has
- to consist of init expressions. */
+/* Match an array reference, whether it is the whole array or particular
+ elements or a section. If init is set, the reference has to consist
+ of init expressions. */
match
gfc_match_array_ref (gfc_array_ref *ar, gfc_array_spec *as, int init,
@@ -422,6 +422,13 @@ match_array_element_spec (gfc_array_spec *as)
if (!gfc_expr_check_typed (*upper, gfc_current_ns, false))
return AS_UNKNOWN;
+ if ((*upper)->expr_type == EXPR_FUNCTION && (*upper)->ts.type == BT_UNKNOWN
+ && (*upper)->symtree && strcmp ((*upper)->symtree->name, "null") == 0)
+ {
+ gfc_error ("Expecting a scalar INTEGER expression at %C");
+ return AS_UNKNOWN;
+ }
+
if (gfc_match_char (':') == MATCH_NO)
{
*lower = gfc_get_int_expr (gfc_default_integer_kind, NULL, 1);
@@ -442,13 +449,20 @@ match_array_element_spec (gfc_array_spec *as)
if (!gfc_expr_check_typed (*upper, gfc_current_ns, false))
return AS_UNKNOWN;
+ if ((*upper)->expr_type == EXPR_FUNCTION && (*upper)->ts.type == BT_UNKNOWN
+ && (*upper)->symtree && strcmp ((*upper)->symtree->name, "null") == 0)
+ {
+ gfc_error ("Expecting a scalar INTEGER expression at %C");
+ return AS_UNKNOWN;
+ }
+
return AS_EXPLICIT;
}
/* Matches an array specification, incidentally figuring out what sort
- it is. Match either a normal array specification, or a coarray spec
- or both. Optionally allow [:] for coarrays. */
+ it is. Match either a normal array specification, or a coarray spec
+ or both. Optionally allow [:] for coarrays. */
match
gfc_match_array_spec (gfc_array_spec **asp, bool match_dim, bool match_codim)
diff --git a/gcc/fortran/check.c b/gcc/fortran/check.c
index 6548a017f44..038ee218d94 100644
--- a/gcc/fortran/check.c
+++ b/gcc/fortran/check.c
@@ -399,7 +399,15 @@ less_than_bitsize2 (const char *arg1, gfc_expr *expr1, const char *arg2,
static bool
same_type_check (gfc_expr *e, int n, gfc_expr *f, int m)
{
- if (gfc_compare_types (&e->ts, &f->ts))
+ gfc_typespec *ets = &e->ts;
+ gfc_typespec *fts = &f->ts;
+
+ if (e->ts.type == BT_PROCEDURE && e->symtree->n.sym)
+ ets = &e->symtree->n.sym->ts;
+ if (f->ts.type == BT_PROCEDURE && f->symtree->n.sym)
+ fts = &f->symtree->n.sym->ts;
+
+ if (gfc_compare_types (ets, fts))
return true;
gfc_error ("%qs argument of %qs intrinsic at %L must be the same type "
@@ -3711,6 +3719,36 @@ gfc_check_reshape (gfc_expr *source, gfc_expr *shape,
}
}
}
+ else if (shape->expr_type == EXPR_VARIABLE && shape->ref
+ && shape->ref->u.ar.type == AR_FULL && shape->ref->u.ar.dimen == 1
+ && shape->ref->u.ar.as
+ && shape->ref->u.ar.as->lower[0]->expr_type == EXPR_CONSTANT
+ && shape->ref->u.ar.as->lower[0]->ts.type == BT_INTEGER
+ && shape->ref->u.ar.as->upper[0]->expr_type == EXPR_CONSTANT
+ && shape->ref->u.ar.as->upper[0]->ts.type == BT_INTEGER
+ && shape->symtree->n.sym->attr.flavor == FL_PARAMETER)
+ {
+ int i, extent;
+ gfc_expr *e, *v;
+
+ v = shape->symtree->n.sym->value;
+
+ for (i = 0; i < shape_size; i++)
+ {
+ e = gfc_constructor_lookup_expr (v->value.constructor, i);
+ if (e == NULL)
+ break;
+
+ gfc_extract_int (e, &extent);
+
+ if (extent < 0)
+ {
+ gfc_error ("Element %d of actual argument of RESHAPE at %L "
+ "cannot be negative", i + 1, &shape->where);
+ return false;
+ }
+ }
+ }
if (pad != NULL)
{
diff --git a/gcc/fortran/class.c b/gcc/fortran/class.c
index 7a9e2755a0f..8b49ae95a20 100644
--- a/gcc/fortran/class.c
+++ b/gcc/fortran/class.c
@@ -843,7 +843,11 @@ has_finalizer_component (gfc_symbol *derived)
&& c->ts.u.derived->f2k_derived->finalizers)
return true;
+ /* Stop infinite recursion through this function by inhibiting
+ calls when the derived type and that of the component are
+ the same. */
if (c->ts.type == BT_DERIVED
+ && !gfc_compare_derived_types (derived, c->ts.u.derived)
&& !c->attr.pointer && !c->attr.allocatable
&& has_finalizer_component (c->ts.u.derived))
return true;
diff --git a/gcc/fortran/cpp.c b/gcc/fortran/cpp.c
index 7d296255b42..85a2c79cd70 100644
--- a/gcc/fortran/cpp.c
+++ b/gcc/fortran/cpp.c
@@ -147,9 +147,9 @@ static void cb_include (cpp_reader *, source_location, const unsigned char *,
static void cb_ident (cpp_reader *, source_location, const cpp_string *);
static void cb_used_define (cpp_reader *, source_location, cpp_hashnode *);
static void cb_used_undef (cpp_reader *, source_location, cpp_hashnode *);
-static bool cb_cpp_error (cpp_reader *, int, int, location_t, unsigned int,
+static bool cb_cpp_error (cpp_reader *, int, int, rich_location *,
const char *, va_list *)
- ATTRIBUTE_GCC_DIAG(6,0);
+ ATTRIBUTE_GCC_DIAG(5,0);
void pp_dir_change (cpp_reader *, const char *);
static int dump_macro (cpp_reader *, cpp_hashnode *, void *);
@@ -1024,13 +1024,12 @@ cb_used_define (cpp_reader *pfile, source_location line ATTRIBUTE_UNUSED,
/* Callback from cpp_error for PFILE to print diagnostics from the
preprocessor. The diagnostic is of type LEVEL, with REASON set
to the reason code if LEVEL is represents a warning, at location
- LOCATION, with column number possibly overridden by COLUMN_OVERRIDE
- if not zero; MSG is the translated message and AP the arguments.
+ RICHLOC; MSG is the translated message and AP the arguments.
Returns true if a diagnostic was emitted, false otherwise. */
static bool
cb_cpp_error (cpp_reader *pfile ATTRIBUTE_UNUSED, int level, int reason,
- location_t location, unsigned int column_override,
+ rich_location *richloc,
const char *msg, va_list *ap)
{
diagnostic_info diagnostic;
@@ -1065,9 +1064,7 @@ cb_cpp_error (cpp_reader *pfile ATTRIBUTE_UNUSED, int level, int reason,
gcc_unreachable ();
}
diagnostic_set_info_translated (&diagnostic, msg, ap,
- location, dlevel);
- if (column_override)
- diagnostic_override_column (&diagnostic, column_override);
+ richloc, dlevel);
if (reason == CPP_W_WARNING_DIRECTIVE)
diagnostic_override_option_index (&diagnostic, OPT_Wcpp);
ret = report_diagnostic (&diagnostic);
diff --git a/gcc/fortran/decl.c b/gcc/fortran/decl.c
index 7178aafe5e1..0c3377f7b08 100644
--- a/gcc/fortran/decl.c
+++ b/gcc/fortran/decl.c
@@ -1529,26 +1529,34 @@ add_init_expr_to_sym (const char *name, gfc_expr **initp, locus *var_locus)
for (dim = 0; dim < sym->as->rank; ++dim)
{
int k;
- gfc_expr* lower;
- gfc_expr* e;
+ gfc_expr *e, *lower;
lower = sym->as->lower[dim];
- if (lower->expr_type != EXPR_CONSTANT)
+
+ /* If the lower bound is an array element from another
+ parameterized array, then it is marked with EXPR_VARIABLE and
+ is an initialization expression. Try to reduce it. */
+ if (lower->expr_type == EXPR_VARIABLE)
+ gfc_reduce_init_expr (lower);
+
+ if (lower->expr_type == EXPR_CONSTANT)
+ {
+ /* All dimensions must be without upper bound. */
+ gcc_assert (!sym->as->upper[dim]);
+
+ k = lower->ts.kind;
+ e = gfc_get_constant_expr (BT_INTEGER, k, &sym->declared_at);
+ mpz_add (e->value.integer, lower->value.integer,
+ init->shape[dim]);
+ mpz_sub_ui (e->value.integer, e->value.integer, 1);
+ sym->as->upper[dim] = e;
+ }
+ else
{
gfc_error ("Non-constant lower bound in implied-shape"
" declaration at %L", &lower->where);
return false;
}
-
- /* All dimensions must be without upper bound. */
- gcc_assert (!sym->as->upper[dim]);
-
- k = lower->ts.kind;
- e = gfc_get_constant_expr (BT_INTEGER, k, &sym->declared_at);
- mpz_add (e->value.integer,
- lower->value.integer, init->shape[dim]);
- mpz_sub_ui (e->value.integer, e->value.integer, 1);
- sym->as->upper[dim] = e;
}
sym->as->type = AS_EXPLICIT;
diff --git a/gcc/fortran/error.c b/gcc/fortran/error.c
index 3825751ddd0..4b3d31ce4ba 100644
--- a/gcc/fortran/error.c
+++ b/gcc/fortran/error.c
@@ -773,6 +773,7 @@ gfc_warning (int opt, const char *gmsgid, va_list ap)
va_copy (argp, ap);
diagnostic_info diagnostic;
+ rich_location rich_loc (UNKNOWN_LOCATION);
bool fatal_errors = global_dc->fatal_errors;
pretty_printer *pp = global_dc->printer;
output_buffer *tmp_buffer = pp->buffer;
@@ -787,7 +788,7 @@ gfc_warning (int opt, const char *gmsgid, va_list ap)
--werrorcount;
}
- diagnostic_set_info (&diagnostic, gmsgid, &argp, UNKNOWN_LOCATION,
+ diagnostic_set_info (&diagnostic, gmsgid, &argp, &rich_loc,
DK_WARNING);
diagnostic.option_index = opt;
bool ret = report_diagnostic (&diagnostic);
@@ -938,10 +939,12 @@ gfc_format_decoder (pretty_printer *pp,
/* If location[0] != UNKNOWN_LOCATION means that we already
processed one of %C/%L. */
int loc_num = text->get_location (0) == UNKNOWN_LOCATION ? 0 : 1;
- text->set_location (loc_num,
- linemap_position_for_loc_and_offset (line_table,
- loc->lb->location,
- offset));
+ source_range range
+ = source_range::from_location (
+ linemap_position_for_loc_and_offset (line_table,
+ loc->lb->location,
+ offset));
+ text->set_range (loc_num, range, true);
pp_string (pp, result[loc_num]);
return true;
}
@@ -1024,48 +1027,21 @@ gfc_diagnostic_build_locus_prefix (diagnostic_context *context,
}
/* This function prints the locus (file:line:column), the diagnostic kind
- (Error, Warning) and (optionally) the caret line (a source line
- with '1' and/or '2' below it).
+ (Error, Warning) and (optionally) the relevant lines of code with
+ annotation lines with '1' and/or '2' below them.
- With -fdiagnostic-show-caret (the default) and for valid locations,
- it prints for one location:
+ With -fdiagnostic-show-caret (the default) it prints:
- [locus]:
+ [locus of primary range]:
some code
1
Error: Some error at (1)
- for two locations that fit in the same locus line:
+ With -fno-diagnostic-show-caret or if the primary range is not
+ valid, it prints:
- [locus]:
-
- some code and some more code
- 1 2
- Error: Some error at (1) and (2)
-
- and for two locations that do not fit in the same locus line:
-
- [locus]:
-
- some code
- 1
- [locus2]:
-
- some other code
- 2
- Error: Some error at (1) and (2)
-
- With -fno-diagnostic-show-caret or if one of the locations is not
- valid, it prints for one location (or for two locations that fit in
- the same locus line):
-
- [locus]: Error: Some error at (1) and (2)
-
- and for two locations that do not fit in the same locus line:
-
- [name]:[locus]: Error: (1)
- [name]:[locus2]: Error: Some error at (1) and (2)
+ [locus of primary range]: Error: Some error at (1) and (2)
*/
static void
gfc_diagnostic_starter (diagnostic_context *context,
@@ -1075,7 +1051,7 @@ gfc_diagnostic_starter (diagnostic_context *context,
expanded_location s1 = diagnostic_expand_location (diagnostic);
expanded_location s2;
- bool one_locus = diagnostic_location (diagnostic, 1) == UNKNOWN_LOCATION;
+ bool one_locus = diagnostic->richloc->get_num_locations () < 2;
bool same_locus = false;
if (!one_locus)
@@ -1125,35 +1101,6 @@ gfc_diagnostic_starter (diagnostic_context *context,
/* If the caret line was shown, the prefix does not contain the
locus. */
pp_set_prefix (context->printer, kind_prefix);
-
- if (one_locus || same_locus)
- return;
-
- locus_prefix = gfc_diagnostic_build_locus_prefix (context, s2);
- if (diagnostic_location (diagnostic, 1) <= BUILTINS_LOCATION)
- {
- /* No caret line for the second location. Override the previous
- prefix with [locus2]:[prefix]. */
- pp_set_prefix (context->printer,
- concat (locus_prefix, " ", kind_prefix, NULL));
- free (kind_prefix);
- free (locus_prefix);
- }
- else
- {
- /* We print the caret for the second location. */
- pp_verbatim (context->printer, locus_prefix);
- free (locus_prefix);
- /* Fortran uses an empty line between locus and caret line. */
- pp_newline (context->printer);
- s1.column = 0; /* Print only a caret line for s2. */
- diagnostic_print_caret_line (context, s2, s1,
- context->caret_chars[1], '\0');
- pp_newline (context->printer);
- /* If the caret line was shown, the prefix does not contain the
- locus. */
- pp_set_prefix (context->printer, kind_prefix);
- }
}
}
@@ -1173,10 +1120,11 @@ gfc_warning_now_at (location_t loc, int opt, const char *gmsgid, ...)
{
va_list argp;
diagnostic_info diagnostic;
+ rich_location rich_loc (loc);
bool ret;
va_start (argp, gmsgid);
- diagnostic_set_info (&diagnostic, gmsgid, &argp, loc, DK_WARNING);
+ diagnostic_set_info (&diagnostic, gmsgid, &argp, &rich_loc, DK_WARNING);
diagnostic.option_index = opt;
ret = report_diagnostic (&diagnostic);
va_end (argp);
@@ -1190,10 +1138,11 @@ gfc_warning_now (int opt, const char *gmsgid, ...)
{
va_list argp;
diagnostic_info diagnostic;
+ rich_location rich_loc (UNKNOWN_LOCATION);
bool ret;
va_start (argp, gmsgid);
- diagnostic_set_info (&diagnostic, gmsgid, &argp, UNKNOWN_LOCATION,
+ diagnostic_set_info (&diagnostic, gmsgid, &argp, &rich_loc,
DK_WARNING);
diagnostic.option_index = opt;
ret = report_diagnostic (&diagnostic);
@@ -1209,11 +1158,12 @@ gfc_error_now (const char *gmsgid, ...)
{
va_list argp;
diagnostic_info diagnostic;
+ rich_location rich_loc (UNKNOWN_LOCATION);
error_buffer.flag = true;
va_start (argp, gmsgid);
- diagnostic_set_info (&diagnostic, gmsgid, &argp, UNKNOWN_LOCATION, DK_ERROR);
+ diagnostic_set_info (&diagnostic, gmsgid, &argp, &rich_loc, DK_ERROR);
report_diagnostic (&diagnostic);
va_end (argp);
}
@@ -1226,9 +1176,10 @@ gfc_fatal_error (const char *gmsgid, ...)
{
va_list argp;
diagnostic_info diagnostic;
+ rich_location rich_loc (UNKNOWN_LOCATION);
va_start (argp, gmsgid);
- diagnostic_set_info (&diagnostic, gmsgid, &argp, UNKNOWN_LOCATION, DK_FATAL);
+ diagnostic_set_info (&diagnostic, gmsgid, &argp, &rich_loc, DK_FATAL);
report_diagnostic (&diagnostic);
va_end (argp);
@@ -1291,6 +1242,7 @@ gfc_error (const char *gmsgid, va_list ap)
}
diagnostic_info diagnostic;
+ rich_location richloc (UNKNOWN_LOCATION);
bool fatal_errors = global_dc->fatal_errors;
pretty_printer *pp = global_dc->printer;
output_buffer *tmp_buffer = pp->buffer;
@@ -1306,7 +1258,7 @@ gfc_error (const char *gmsgid, va_list ap)
--errorcount;
}
- diagnostic_set_info (&diagnostic, gmsgid, &argp, UNKNOWN_LOCATION, DK_ERROR);
+ diagnostic_set_info (&diagnostic, gmsgid, &argp, &richloc, DK_ERROR);
report_diagnostic (&diagnostic);
if (buffered_p)
@@ -1336,9 +1288,10 @@ gfc_internal_error (const char *gmsgid, ...)
{
va_list argp;
diagnostic_info diagnostic;
+ rich_location rich_loc (UNKNOWN_LOCATION);
va_start (argp, gmsgid);
- diagnostic_set_info (&diagnostic, gmsgid, &argp, UNKNOWN_LOCATION, DK_ICE);
+ diagnostic_set_info (&diagnostic, gmsgid, &argp, &rich_loc, DK_ICE);
report_diagnostic (&diagnostic);
va_end (argp);
diff --git a/gcc/fortran/match.c b/gcc/fortran/match.c
index 7abb5dee4a9..2844262e0f2 100644
--- a/gcc/fortran/match.c
+++ b/gcc/fortran/match.c
@@ -5018,7 +5018,9 @@ gfc_free_case_list (gfc_case *p)
}
-/* Match a single case selector. */
+/* Match a single case selector. Combining the requirements of F08:C830
+ and F08:C832 (R838) means that the case-value must have either CHARACTER,
+ INTEGER, or LOGICAL type. */
static match
match_case_selector (gfc_case **cp)
@@ -5036,6 +5038,14 @@ match_case_selector (gfc_case **cp)
goto need_expr;
if (m == MATCH_ERROR)
goto cleanup;
+
+ if (c->high->ts.type != BT_LOGICAL && c->high->ts.type != BT_INTEGER
+ && c->high->ts.type != BT_CHARACTER)
+ {
+ gfc_error ("Expression in CASE selector at %L cannot be %s",
+ &c->high->where, gfc_typename (&c->high->ts));
+ goto cleanup;
+ }
}
else
{
@@ -5045,6 +5055,14 @@ match_case_selector (gfc_case **cp)
if (m == MATCH_NO)
goto need_expr;
+ if (c->low->ts.type != BT_LOGICAL && c->low->ts.type != BT_INTEGER
+ && c->low->ts.type != BT_CHARACTER)
+ {
+ gfc_error ("Expression in CASE selector at %L cannot be %s",
+ &c->low->where, gfc_typename (&c->low->ts));
+ goto cleanup;
+ }
+
/* If we're not looking at a ':' now, make a range out of a single
target. Else get the upper bound for the case range. */
if (gfc_match_char (':') != MATCH_YES)
diff --git a/gcc/fortran/trans-array.c b/gcc/fortran/trans-array.c
index 6bbf8cc6279..e28a5ce3c0b 100644
--- a/gcc/fortran/trans-array.c
+++ b/gcc/fortran/trans-array.c
@@ -5150,6 +5150,8 @@ gfc_array_init_size (tree descriptor, int rank, int corank, tree * poffset,
gcc_assert (ubound);
gfc_conv_expr_type (&se, ubound, gfc_array_index_type);
gfc_add_block_to_block (pblock, &se.pre);
+ if (ubound->expr_type == EXPR_FUNCTION)
+ se.expr = gfc_evaluate_now (se.expr, pblock);
}
gfc_conv_descriptor_ubound_set (descriptor_block, descriptor,
gfc_rank_cst[n], se.expr);
diff --git a/gcc/fortran/trans-types.c b/gcc/fortran/trans-types.c
index 780200e5f5d..ad6cee87606 100644
--- a/gcc/fortran/trans-types.c
+++ b/gcc/fortran/trans-types.c
@@ -2366,6 +2366,7 @@ gfc_get_derived_type (gfc_symbol * derived)
gfc_component *c;
gfc_dt_list *dt;
gfc_namespace *ns;
+ tree tmp;
if (derived->attr.unlimited_polymorphic
|| (flag_coarray == GFC_FCOARRAY_LIB
@@ -2517,8 +2518,19 @@ gfc_get_derived_type (gfc_symbol * derived)
node as DECL_CONTEXT of each FIELD_DECL. */
for (c = derived->components; c; c = c->next)
{
- if (c->attr.proc_pointer)
+ /* Prevent infinite recursion, when the procedure pointer type is
+ the same as derived, by forcing the procedure pointer component to
+ be built as if the explicit interface does not exist. */
+ if (c->attr.proc_pointer
+ && ((c->ts.type != BT_DERIVED && c->ts.type != BT_CLASS)
+ || (c->ts.u.derived
+ && !gfc_compare_derived_types (derived, c->ts.u.derived))))
field_type = gfc_get_ppc_type (c);
+ else if (c->attr.proc_pointer && derived->backend_decl)
+ {
+ tmp = build_function_type_list (derived->backend_decl, NULL_TREE);
+ field_type = build_pointer_type (tmp);
+ }
else if (c->ts.type == BT_DERIVED || c->ts.type == BT_CLASS)
field_type = c->ts.u.derived->backend_decl;
else
diff --git a/gcc/function.c b/gcc/function.c
index 0d7cabc1d4c..a637cb39142 100644
--- a/gcc/function.c
+++ b/gcc/function.c
@@ -2879,6 +2879,7 @@ assign_parm_setup_block (struct assign_parm_data_all *all,
rtx entry_parm = data->entry_parm;
rtx stack_parm = data->stack_parm;
rtx target_reg = NULL_RTX;
+ bool in_conversion_seq = false;
HOST_WIDE_INT size;
HOST_WIDE_INT size_stored;
@@ -2895,9 +2896,23 @@ assign_parm_setup_block (struct assign_parm_data_all *all,
if (GET_CODE (reg) != CONCAT)
stack_parm = reg;
else
- /* This will use or allocate a stack slot that we'd rather
- avoid. FIXME: Could we avoid it in more cases? */
- target_reg = reg;
+ {
+ target_reg = reg;
+ /* Avoid allocating a stack slot, if there isn't one
+ preallocated by the ABI. It might seem like we should
+ always prefer a pseudo, but converting between
+ floating-point and integer modes goes through the stack
+ on various machines, so it's better to use the reserved
+ stack slot than to risk wasting it and allocating more
+ for the conversion. */
+ if (stack_parm == NULL_RTX)
+ {
+ int save = generating_concat_p;
+ generating_concat_p = 0;
+ stack_parm = gen_reg_rtx (mode);
+ generating_concat_p = save;
+ }
+ }
data->stack_parm = NULL;
}
@@ -2938,7 +2953,9 @@ assign_parm_setup_block (struct assign_parm_data_all *all,
mem = validize_mem (copy_rtx (stack_parm));
/* Handle values in multiple non-contiguous locations. */
- if (GET_CODE (entry_parm) == PARALLEL)
+ if (GET_CODE (entry_parm) == PARALLEL && !MEM_P (mem))
+ emit_group_store (mem, entry_parm, data->passed_type, size);
+ else if (GET_CODE (entry_parm) == PARALLEL)
{
push_to_sequence2 (all->first_conversion_insn,
all->last_conversion_insn);
@@ -2946,6 +2963,7 @@ assign_parm_setup_block (struct assign_parm_data_all *all,
all->first_conversion_insn = get_insns ();
all->last_conversion_insn = get_last_insn ();
end_sequence ();
+ in_conversion_seq = true;
}
else if (size == 0)
@@ -3025,11 +3043,22 @@ assign_parm_setup_block (struct assign_parm_data_all *all,
all->first_conversion_insn = get_insns ();
all->last_conversion_insn = get_last_insn ();
end_sequence ();
+ in_conversion_seq = true;
}
if (target_reg)
{
- emit_move_insn (target_reg, stack_parm);
+ if (!in_conversion_seq)
+ emit_move_insn (target_reg, stack_parm);
+ else
+ {
+ push_to_sequence2 (all->first_conversion_insn,
+ all->last_conversion_insn);
+ emit_move_insn (target_reg, stack_parm);
+ all->first_conversion_insn = get_insns ();
+ all->last_conversion_insn = get_last_insn ();
+ end_sequence ();
+ }
stack_parm = target_reg;
}
diff --git a/gcc/genmatch.c b/gcc/genmatch.c
index b5a0fffa714..1eb8c24da7d 100644
--- a/gcc/genmatch.c
+++ b/gcc/genmatch.c
@@ -53,14 +53,31 @@ unsigned verbose;
static struct line_maps *line_table;
+/* The rich_location class within libcpp requires a way to expand
+ source_location instances, and relies on the client code
+ providing a symbol named
+ linemap_client_expand_location_to_spelling_point
+ to do this.
+
+ This is the implementation for genmatch. */
+
+expanded_location
+linemap_client_expand_location_to_spelling_point (source_location loc)
+{
+ const struct line_map_ordinary *map;
+ loc = linemap_resolve_location (line_table, loc, LRK_SPELLING_LOCATION, &map);
+ return linemap_expand_location (line_table, map, loc);
+}
+
static bool
#if GCC_VERSION >= 4001
-__attribute__((format (printf, 6, 0)))
+__attribute__((format (printf, 5, 0)))
#endif
-error_cb (cpp_reader *, int errtype, int, source_location location,
- unsigned int, const char *msg, va_list *ap)
+error_cb (cpp_reader *, int errtype, int, rich_location *richloc,
+ const char *msg, va_list *ap)
{
const line_map_ordinary *map;
+ source_location location = richloc->get_loc ();
linemap_resolve_location (line_table, location, LRK_SPELLING_LOCATION, &map);
expanded_location loc = linemap_expand_location (line_table, map, location);
fprintf (stderr, "%s:%d:%d %s: ", loc.file, loc.line, loc.column,
@@ -102,9 +119,10 @@ __attribute__((format (printf, 2, 3)))
#endif
fatal_at (const cpp_token *tk, const char *msg, ...)
{
+ rich_location richloc (tk->src_loc);
va_list ap;
va_start (ap, msg);
- error_cb (NULL, CPP_DL_FATAL, 0, tk->src_loc, 0, msg, &ap);
+ error_cb (NULL, CPP_DL_FATAL, 0, &richloc, msg, &ap);
va_end (ap);
}
@@ -114,9 +132,10 @@ __attribute__((format (printf, 2, 3)))
#endif
fatal_at (source_location loc, const char *msg, ...)
{
+ rich_location richloc (loc);
va_list ap;
va_start (ap, msg);
- error_cb (NULL, CPP_DL_FATAL, 0, loc, 0, msg, &ap);
+ error_cb (NULL, CPP_DL_FATAL, 0, &richloc, msg, &ap);
va_end (ap);
}
@@ -126,9 +145,10 @@ __attribute__((format (printf, 2, 3)))
#endif
warning_at (const cpp_token *tk, const char *msg, ...)
{
+ rich_location richloc (tk->src_loc);
va_list ap;
va_start (ap, msg);
- error_cb (NULL, CPP_DL_WARNING, 0, tk->src_loc, 0, msg, &ap);
+ error_cb (NULL, CPP_DL_WARNING, 0, &richloc, msg, &ap);
va_end (ap);
}
@@ -138,9 +158,10 @@ __attribute__((format (printf, 2, 3)))
#endif
warning_at (source_location loc, const char *msg, ...)
{
+ rich_location richloc (loc);
va_list ap;
va_start (ap, msg);
- error_cb (NULL, CPP_DL_WARNING, 0, loc, 0, msg, &ap);
+ error_cb (NULL, CPP_DL_WARNING, 0, &richloc, msg, &ap);
va_end (ap);
}
@@ -208,7 +229,6 @@ enum built_in_function {
#include "builtins.def"
END_BUILTINS
};
-#undef DEF_BUILTIN
/* Return true if CODE represents a commutative tree code. Otherwise
return false. */
@@ -4598,7 +4618,6 @@ add_operator (VIEW_CONVERT2, "VIEW_CONVERT2", "tcc_unary", 1);
#define DEF_BUILTIN(ENUM, N, C, T, LT, B, F, NA, AT, IM, COND) \
add_builtin (ENUM, # ENUM);
#include "builtins.def"
-#undef DEF_BUILTIN
/* Parse ahead! */
parser p (r);
diff --git a/gcc/gensupport.c b/gcc/gensupport.c
index 0480e17fac3..484ead2f3e7 100644
--- a/gcc/gensupport.c
+++ b/gcc/gensupport.c
@@ -2253,7 +2253,7 @@ htab_eq_string (const void *s1, const void *s2)
and a permanent heap copy of STR is created. */
static void
-add_mnemonic_string (htab_t mnemonic_htab, const char *str, int len)
+add_mnemonic_string (htab_t mnemonic_htab, const char *str, size_t len)
{
char *new_str;
void **slot;
@@ -2306,7 +2306,7 @@ gen_mnemonic_setattr (htab_t mnemonic_htab, rtx insn)
for (i = 0; *cp; )
{
const char *ep, *sp;
- int size = 0;
+ size_t size = 0;
while (ISSPACE (*cp))
cp++;
@@ -2333,8 +2333,7 @@ gen_mnemonic_setattr (htab_t mnemonic_htab, rtx insn)
{
/* Don't set a value if there are more than one
instruction in the string. */
- obstack_next_free (&string_obstack) =
- obstack_next_free (&string_obstack) - size;
+ obstack_blank_fast (&string_obstack, -size);
size = 0;
cp = sp;
@@ -2346,7 +2345,7 @@ gen_mnemonic_setattr (htab_t mnemonic_htab, rtx insn)
obstack_1grow (&string_obstack, '*');
else
add_mnemonic_string (mnemonic_htab,
- obstack_next_free (&string_obstack) - size,
+ (char *) obstack_next_free (&string_obstack) - size,
size);
i++;
}
diff --git a/gcc/gimple-expr.c b/gcc/gimple-expr.c
index dd2550a71c3..e9c631d884d 100644
--- a/gcc/gimple-expr.c
+++ b/gcc/gimple-expr.c
@@ -152,14 +152,16 @@ useless_type_conversion_p (tree outer_type, tree inner_type)
else if (TREE_CODE (inner_type) == ARRAY_TYPE
&& TREE_CODE (outer_type) == ARRAY_TYPE)
{
- /* Preserve string attributes. */
+ /* Preserve various attributes. */
+ if (TYPE_REVERSE_STORAGE_ORDER (inner_type)
+ != TYPE_REVERSE_STORAGE_ORDER (outer_type))
+ return false;
if (TYPE_STRING_FLAG (inner_type) != TYPE_STRING_FLAG (outer_type))
return false;
/* Conversions from array types with unknown extent to
array types with known extent are not useless. */
- if (!TYPE_DOMAIN (inner_type)
- && TYPE_DOMAIN (outer_type))
+ if (!TYPE_DOMAIN (inner_type) && TYPE_DOMAIN (outer_type))
return false;
/* Nor are conversions from array types with non-constant size to
diff --git a/gcc/gimple-fold.c b/gcc/gimple-fold.c
index 45840af22d9..fc095eb5bfc 100644
--- a/gcc/gimple-fold.c
+++ b/gcc/gimple-fold.c
@@ -782,13 +782,14 @@ gimple_fold_builtin_memory_op (gimple_stmt_iterator *gsi,
HOST_WIDE_INT src_offset = 0, dest_offset = 0;
HOST_WIDE_INT size = -1;
HOST_WIDE_INT maxsize = -1;
+ bool reverse;
srcvar = TREE_OPERAND (src, 0);
src_base = get_ref_base_and_extent (srcvar, &src_offset,
- &size, &maxsize);
+ &size, &maxsize, &reverse);
destvar = TREE_OPERAND (dest, 0);
dest_base = get_ref_base_and_extent (destvar, &dest_offset,
- &size, &maxsize);
+ &size, &maxsize, &reverse);
if (tree_fits_uhwi_p (len))
maxsize = tree_to_uhwi (len);
else
@@ -5264,6 +5265,8 @@ get_base_constructor (tree base, HOST_WIDE_INT *bit_offset,
tree (*valueize)(tree))
{
HOST_WIDE_INT bit_offset2, size, max_size;
+ bool reverse;
+
if (TREE_CODE (base) == MEM_REF)
{
if (!integer_zerop (TREE_OPERAND (base, 1)))
@@ -5304,7 +5307,8 @@ get_base_constructor (tree base, HOST_WIDE_INT *bit_offset,
case ARRAY_REF:
case COMPONENT_REF:
- base = get_ref_base_and_extent (base, &bit_offset2, &size, &max_size);
+ base = get_ref_base_and_extent (base, &bit_offset2, &size, &max_size,
+ &reverse);
if (max_size == -1 || size != max_size)
return NULL_TREE;
*bit_offset += bit_offset2;
@@ -5507,6 +5511,7 @@ fold_const_aggregate_ref_1 (tree t, tree (*valueize) (tree))
tree ctor, idx, base;
HOST_WIDE_INT offset, size, max_size;
tree tem;
+ bool reverse;
if (TREE_THIS_VOLATILE (t))
return NULL_TREE;
@@ -5577,7 +5582,7 @@ fold_const_aggregate_ref_1 (tree t, tree (*valueize) (tree))
case BIT_FIELD_REF:
case TARGET_MEM_REF:
case MEM_REF:
- base = get_ref_base_and_extent (t, &offset, &size, &max_size);
+ base = get_ref_base_and_extent (t, &offset, &size, &max_size, &reverse);
ctor = get_base_constructor (base, &offset, valueize);
/* Empty constructor. Always fold to 0. */
diff --git a/gcc/gimple-laddress.c b/gcc/gimple-laddress.c
index ba9198e921a..c2826dff419 100644
--- a/gcc/gimple-laddress.c
+++ b/gcc/gimple-laddress.c
@@ -102,10 +102,10 @@ pass_laddress::execute (function *fun)
HOST_WIDE_INT bitsize, bitpos;
tree base, offset;
machine_mode mode;
- int volatilep = 0, unsignedp = 0;
+ int volatilep = 0, reversep, unsignedp = 0;
base = get_inner_reference (TREE_OPERAND (expr, 0), &bitsize,
&bitpos, &offset, &mode, &unsignedp,
- &volatilep, false);
+ &reversep, &volatilep, false);
gcc_assert (base != NULL_TREE && (bitpos % BITS_PER_UNIT) == 0);
if (offset != NULL_TREE)
{
diff --git a/gcc/gimple-ssa-strength-reduction.c b/gcc/gimple-ssa-strength-reduction.c
index 0e52a86153f..ce32ad33e94 100644
--- a/gcc/gimple-ssa-strength-reduction.c
+++ b/gcc/gimple-ssa-strength-reduction.c
@@ -972,7 +972,7 @@ slsr_process_ref (gimple *gs)
tree ref_expr, base, offset, type;
HOST_WIDE_INT bitsize, bitpos;
machine_mode mode;
- int unsignedp, volatilep;
+ int unsignedp, reversep, volatilep;
slsr_cand_t c;
if (gimple_vdef (gs))
@@ -987,7 +987,9 @@ slsr_process_ref (gimple *gs)
return;
base = get_inner_reference (ref_expr, &bitsize, &bitpos, &offset, &mode,
- &unsignedp, &volatilep, false);
+ &unsignedp, &reversep, &volatilep, false);
+ if (reversep)
+ return;
widest_int index = bitpos;
if (!restructure_reference (&base, &offset, &index, &type))
diff --git a/gcc/gimple.c b/gcc/gimple.c
index 4ce38dadf2f..706b126e5bb 100644
--- a/gcc/gimple.c
+++ b/gcc/gimple.c
@@ -37,6 +37,7 @@ along with GCC; see the file COPYING3. If not see
#include "gimple-iterator.h"
#include "gimple-walk.h"
#include "gimplify.h"
+#include "target.h"
/* All the tuples have their operand vector (if present) at the very bottom
@@ -2624,9 +2625,15 @@ nonfreeing_call_p (gimple *call)
static bool
check_loadstore (gimple *, tree op, tree, void *data)
{
- if ((TREE_CODE (op) == MEM_REF || TREE_CODE (op) == TARGET_MEM_REF)
- && operand_equal_p (TREE_OPERAND (op, 0), (tree)data, 0))
- return true;
+ if (TREE_CODE (op) == MEM_REF || TREE_CODE (op) == TARGET_MEM_REF)
+ {
+ /* Some address spaces may legitimately dereference zero. */
+ addr_space_t as = TYPE_ADDR_SPACE (TREE_TYPE (op));
+ if (targetm.addr_space.zero_address_valid (as))
+ return false;
+
+ return operand_equal_p (TREE_OPERAND (op, 0), (tree)data, 0);
+ }
return false;
}
diff --git a/gcc/gimplify.c b/gcc/gimplify.c
index fa348585a24..287e51e2016 100644
--- a/gcc/gimplify.c
+++ b/gcc/gimplify.c
@@ -6613,14 +6613,14 @@ gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p,
tree offset;
HOST_WIDE_INT bitsize, bitpos;
machine_mode mode;
- int unsignedp, volatilep = 0;
+ int unsignedp, reversep, volatilep = 0;
tree base = OMP_CLAUSE_DECL (c);
while (TREE_CODE (base) == ARRAY_REF)
base = TREE_OPERAND (base, 0);
if (TREE_CODE (base) == INDIRECT_REF)
base = TREE_OPERAND (base, 0);
base = get_inner_reference (base, &bitsize, &bitpos, &offset,
- &mode, &unsignedp,
+ &mode, &unsignedp, &reversep,
&volatilep, false);
gcc_assert (base == decl
&& (offset == NULL_TREE
@@ -6730,7 +6730,8 @@ gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p,
base = get_inner_reference (base, &bitsize2,
&bitpos2, &offset2,
&mode, &unsignedp,
- &volatilep, false);
+ &reversep, &volatilep,
+ false);
if (base != decl)
break;
if (scp)
@@ -9259,9 +9260,9 @@ gimplify_omp_ordered (tree expr, gimple_seq body)
|| OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SOURCE))
{
error_at (OMP_CLAUSE_LOCATION (c),
- "%<depend%> clause must be closely nested "
- "inside a loop with %<ordered%> clause with "
- "a parameter");
+ "%<ordered%> construct with %<depend%> clause must be "
+ "closely nested inside a loop with %<ordered%> clause "
+ "with a parameter");
failures++;
}
else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND
@@ -9734,6 +9735,8 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
TREE_OPERAND (*expr_p, 1));
if (tmp)
{
+ REF_REVERSE_STORAGE_ORDER (tmp)
+ = REF_REVERSE_STORAGE_ORDER (*expr_p);
*expr_p = tmp;
recalculate_side_effects (*expr_p);
ret = GS_OK;
diff --git a/gcc/go/gofrontend/MERGE b/gcc/go/gofrontend/MERGE
index dc042d91656..f325bb33ecb 100644
--- a/gcc/go/gofrontend/MERGE
+++ b/gcc/go/gofrontend/MERGE
@@ -1,4 +1,4 @@
-47f256e1ed527b2eb4041acf90d33e6abc5e1685
+012ab5cb2ef1c26e8023ce90d3a2bba174da7b30
The first line of this file holds the git revision number of the last
merge done from the gofrontend repository.
diff --git a/gcc/graphite-optimize-isl.c b/gcc/graphite-optimize-isl.c
index 53355bb57dc..c09264bf093 100644
--- a/gcc/graphite-optimize-isl.c
+++ b/gcc/graphite-optimize-isl.c
@@ -404,7 +404,7 @@ optimize_isl (scop_p scop)
isl_options_set_schedule_maximize_band_depth (scop->isl_context, 1);
#ifdef HAVE_ISL_OPTIONS_SET_SCHEDULE_SERIALIZE_SCCS
/* ISL-0.15 or later. */
- isl_options_set_schedule_serialize_sccs (scop->isl_context, 1);
+ isl_options_set_schedule_maximize_band_depth (scop->isl_context, 1);
#else
isl_options_set_schedule_fuse (scop->isl_context, ISL_SCHEDULE_FUSE_MIN);
#endif
@@ -441,11 +441,23 @@ optimize_isl (scop_p scop)
#else
isl_union_map *schedule_map = get_schedule_map (schedule);
#endif
- apply_schedule_map_to_scop (scop, schedule_map);
- isl_schedule_free (schedule);
- isl_union_map_free (schedule_map);
- return true;
+ if (isl_union_map_is_equal (scop->original_schedule, schedule_map))
+ {
+ if (dump_file && dump_flags)
+ fprintf (dump_file, "\nISL schedule same as original schedule\n");
+
+ isl_schedule_free (schedule);
+ isl_union_map_free (schedule_map);
+ return false;
+ }
+ else
+ {
+ apply_schedule_map_to_scop (scop, schedule_map);
+ isl_schedule_free (schedule);
+ isl_union_map_free (schedule_map);
+ return true;
+ }
}
#endif /* HAVE_isl */
diff --git a/gcc/graphite-poly.c b/gcc/graphite-poly.c
index 2aa40c055d8..36c3061f618 100644
--- a/gcc/graphite-poly.c
+++ b/gcc/graphite-poly.c
@@ -305,6 +305,7 @@ new_scop (edge entry, edge exit)
scop->must_waw_no_source = NULL;
scop->may_waw_no_source = NULL;
scop_set_region (scop, region);
+ scop->original_schedule = NULL;
scop->pbbs.create (3);
scop->poly_scop_p = false;
scop->drs.create (3);
@@ -341,6 +342,7 @@ free_scop (scop_p scop)
isl_union_map_free (scop->may_waw);
isl_union_map_free (scop->must_waw_no_source);
isl_union_map_free (scop->may_waw_no_source);
+ isl_union_map_free (scop->original_schedule);
XDELETE (scop);
}
diff --git a/gcc/graphite-poly.h b/gcc/graphite-poly.h
index 5298f8547f9..b35431ae59d 100644
--- a/gcc/graphite-poly.h
+++ b/gcc/graphite-poly.h
@@ -436,6 +436,9 @@ struct scop
*must_war, *may_war, *must_war_no_source, *may_war_no_source,
*must_waw, *may_waw, *must_waw_no_source, *may_waw_no_source;
+ /* Original schedule of the SCoP. */
+ isl_union_map *original_schedule;
+
/* True when the scop has been converted to its polyhedral
representation. */
bool poly_scop_p;
diff --git a/gcc/graphite-scop-detection.c b/gcc/graphite-scop-detection.c
index ae8497db79d..9fb82645501 100644
--- a/gcc/graphite-scop-detection.c
+++ b/gcc/graphite-scop-detection.c
@@ -794,7 +794,8 @@ scop_detection::merge_sese (sese_l first, sese_l second) const
get_entry_bb (second));
edge entry = get_nearest_dom_with_single_entry (dom);
- if (!entry)
+
+ if (!entry || (entry->flags & EDGE_IRREDUCIBLE_LOOP))
return invalid_sese;
basic_block pdom = nearest_common_dominator (CDI_POST_DOMINATORS,
@@ -803,7 +804,8 @@ scop_detection::merge_sese (sese_l first, sese_l second) const
pdom = nearest_common_dominator (CDI_POST_DOMINATORS, dom, pdom);
edge exit = get_nearest_pdom_with_single_exit (pdom);
- if (!exit)
+
+ if (!exit || (exit->flags & EDGE_IRREDUCIBLE_LOOP))
return invalid_sese;
sese_l combined (entry, exit);
@@ -923,6 +925,7 @@ scop_detection::can_represent_loop_1 (loop_p loop, sese_l scop)
struct tree_niter_desc niter_desc;
return single_exit (loop)
+ && !(loop_preheader_edge (loop)->flags & EDGE_IRREDUCIBLE_LOOP)
&& number_of_iterations_exit (loop, single_exit (loop), &niter_desc, false)
&& niter_desc.control.no_overflow
&& (niter = number_of_latch_executions (loop))
@@ -956,6 +959,13 @@ scop_detection::loop_is_valid_scop (loop_p loop, sese_l scop) const
if (!scop)
return false;
+ if (!optimize_loop_nest_for_speed_p (loop))
+ {
+ DEBUG_PRINT (dp << "[scop-detection-fail] loop_"
+ << loop->num << " is not on a hot path.\n");
+ return false;
+ }
+
if (!can_represent_loop (loop, scop))
{
DEBUG_PRINT (dp << "[scop-detection-fail] cannot represent loop_"
@@ -1053,6 +1063,10 @@ scop_detection::harmful_stmt_in_region (sese_l scop) const
if (!dominated_by_p (CDI_POST_DOMINATORS, bb, exit_bb))
continue;
+ /* The basic block should not be part of an irreducible loop. */
+ if (bb->flags & BB_IRREDUCIBLE_LOOP)
+ return true;
+
if (harmful_stmt_in_bb (scop, bb))
return true;
}
diff --git a/gcc/graphite-sese-to-poly.c b/gcc/graphite-sese-to-poly.c
index fa33c50a533..ba45199a02a 100644
--- a/gcc/graphite-sese-to-poly.c
+++ b/gcc/graphite-sese-to-poly.c
@@ -231,51 +231,78 @@ isl_id_for_pbb (scop_p s, poly_bb_p pbb)
| 0 0 1 0 0 0 0 0 -5 = 0 */
static void
-build_pbb_scattering_polyhedrons (isl_aff *static_sched,
- poly_bb_p pbb)
+build_pbb_minimal_scattering_polyhedrons (isl_aff *static_sched, poly_bb_p pbb,
+ int *sequence_dims,
+ int nb_sequence_dim)
{
- isl_val *val;
+ int local_dim = isl_set_dim (pbb->domain, isl_dim_set);
+
+ /* Remove a sequence dimension if irrelevant to domain of current pbb. */
+ int actual_nb_dim = 0;
+ for (int i = 0; i < nb_sequence_dim; i++)
+ if (sequence_dims[i] <= local_dim)
+ actual_nb_dim++;
+
+ /* Build an array that combines sequence dimensions and loops dimensions info.
+ This is used later to compute the static scattering polyhedrons. */
+ bool *sequence_and_loop_dims = NULL;
+ if (local_dim + actual_nb_dim > 0)
+ {
+ sequence_and_loop_dims = XNEWVEC (bool, local_dim + actual_nb_dim);
- int scattering_dimensions = isl_set_dim (pbb->domain, isl_dim_set) * 2 + 1;
+ int i = 0, j = 0;
+ for (; i < local_dim; i++)
+ {
+ if (sequence_dims && sequence_dims[j] == i)
+ {
+ /* True for sequence dimension. */
+ sequence_and_loop_dims[i + j] = true;
+ j++;
+ }
+ /* False for loop dimension. */
+ sequence_and_loop_dims[i + j] = false;
+ }
+ /* Fake loops make things shifted by one. */
+ if (sequence_dims && sequence_dims[j] == i)
+ sequence_and_loop_dims[i + j] = true;
+ }
+ int scattering_dimensions = local_dim + actual_nb_dim;
isl_space *dc = isl_set_get_space (pbb->domain);
- isl_space *dm = isl_space_add_dims (isl_space_from_domain (dc),
- isl_dim_out, scattering_dimensions);
+ isl_space *dm = isl_space_add_dims (isl_space_from_domain (dc), isl_dim_out,
+ scattering_dimensions);
pbb->schedule = isl_map_universe (dm);
+ int k = 0;
for (int i = 0; i < scattering_dimensions; i++)
{
- /* Textual order inside this loop. */
- if ((i % 2) == 0)
- {
- isl_constraint *c = isl_equality_alloc
- (isl_local_space_from_space (isl_map_get_space (pbb->schedule)));
-
- val = isl_aff_get_coefficient_val (static_sched, isl_dim_in, i / 2);
- gcc_assert (val && isl_val_is_int (val));
-
- val = isl_val_neg (val);
- c = isl_constraint_set_constant_val (c, val);
- c = isl_constraint_set_coefficient_si (c, isl_dim_out, i, 1);
- pbb->schedule = isl_map_add_constraint (pbb->schedule, c);
- }
-
- /* Iterations of this loop. */
- else /* if ((i % 2) == 1) */
+ if (!sequence_and_loop_dims[i])
{
- int loop = (i - 1) / 2;
- pbb->schedule = isl_map_equate (pbb->schedule, isl_dim_in, loop,
+ /* Iterations of this loop - loop dimension. */
+ pbb->schedule = isl_map_equate (pbb->schedule, isl_dim_in, k,
isl_dim_out, i);
+ k++;
+ continue;
}
+
+ /* Textual order inside this loop - sequence dimension. */
+ isl_space *s = isl_map_get_space (pbb->schedule);
+ isl_local_space *ls = isl_local_space_from_space (s);
+ isl_constraint *c = isl_equality_alloc (ls);
+ isl_val *val = isl_aff_get_coefficient_val (static_sched, isl_dim_in, k);
+ gcc_assert (val && isl_val_is_int (val));
+ val = isl_val_neg (val);
+ c = isl_constraint_set_constant_val (c, val);
+ c = isl_constraint_set_coefficient_si (c, isl_dim_out, i, 1);
+ pbb->schedule = isl_map_add_constraint (pbb->schedule, c);
}
+ XDELETEVEC (sequence_and_loop_dims);
pbb->transformed = isl_map_copy (pbb->schedule);
}
-/* Build for BB the static schedule.
-
- The static schedule is a Dewey numbering of the abstract syntax
- tree: http://en.wikipedia.org/wiki/Dewey_Decimal_Classification
+/* Build the static schedule for BB. This function minimizes the number of
+ dimensions used for pbb sequences.
The following example informally defines the static schedule:
@@ -283,40 +310,94 @@ build_pbb_scattering_polyhedrons (isl_aff *static_sched,
for (i: ...)
{
for (j: ...)
- {
- B
- C
- }
-
+ {
+ B
+ C
+ }
+ }
+ for (i: ...)
+ {
for (k: ...)
- {
- D
- E
- }
+ {
+ D
+ E
+ }
}
F
Static schedules for A to F:
- DEPTH
- 0 1 2
- A 0
- B 1 0 0
- C 1 0 1
- D 1 1 0
- E 1 1 1
- F 2
+ A (0)
+ B (1 i0 i1 0)
+ C (1 i0 i1 1)
+ D (2 i0 i1 2)
+ E (2 i0 i1 3)
+ F (3)
*/
static void
-build_scop_scattering (scop_p scop)
+build_scop_minimal_scattering (scop_p scop)
{
gimple_poly_bb_p previous_gbb = NULL;
- isl_space *dc = isl_set_get_space (scop->param_context);
- isl_aff *static_sched;
+ int *temp_for_sequence_dims = NULL;
+ int i;
+ poly_bb_p pbb;
+
+ /* Go through the pbbs to determine the minimum number of dimensions needed to
+ build the static schedule. */
+ int nb_dims = 0;
+ FOR_EACH_VEC_ELT (scop->pbbs, i, pbb)
+ {
+ int dim = isl_set_dim (pbb->domain, isl_dim_set);
+ if (dim > nb_dims)
+ nb_dims = dim;
+ }
+
+ /* One extra dimension for the outer fake loop. */
+ nb_dims++;
+ temp_for_sequence_dims = XCNEWVEC (int, nb_dims);
+
+ /* Record the number of common loops for each dimension. */
+ FOR_EACH_VEC_ELT (scop->pbbs, i, pbb)
+ {
+ gimple_poly_bb_p gbb = PBB_BLACK_BOX (pbb);
+ int prefix = 0;
+ if (previous_gbb)
+ {
+ prefix = nb_common_loops (scop->scop_info->region, previous_gbb, gbb);
+ temp_for_sequence_dims[prefix] += 1;
+ }
+ previous_gbb = gbb;
+ }
+
+ /* Analyze the info in temp_for_sequence_dim and determine the minimal number
+ of sequence dimensions. A dimension that did not appear as common
+ dimension should not be considered as a sequence dimension. */
+ int nb_sequence_params = 0;
+ for (i = 0; i < nb_dims; i++)
+ if (temp_for_sequence_dims[i] > 0)
+ nb_sequence_params++;
+
+ int *sequence_dims = NULL;
+ if (nb_sequence_params > 0)
+ {
+ int j = 0;
+ sequence_dims = XNEWVEC (int, nb_sequence_params);
+ for (i = 0; i < nb_dims; i++)
+ if (temp_for_sequence_dims[i] > 0)
+ {
+ sequence_dims[j] = i;
+ j++;
+ }
+ }
+
+ XDELETEVEC (temp_for_sequence_dims);
+
+ isl_space *dc = isl_set_get_space (scop->param_context);
dc = isl_space_add_dims (dc, isl_dim_set, number_of_loops (cfun));
- static_sched = isl_aff_zero_on_domain (isl_local_space_from_space (dc));
+ isl_local_space *local_space = isl_local_space_from_space (dc);
+ isl_aff *static_sched = isl_aff_zero_on_domain (local_space);
/* We have to start schedules at 0 on the first component and
because we cannot compare_prefix_loops against a previous loop,
@@ -324,8 +405,7 @@ build_scop_scattering (scop_p scop)
incremented before copying. */
static_sched = isl_aff_add_coefficient_si (static_sched, isl_dim_in, 0, -1);
- int i;
- poly_bb_p pbb;
+ previous_gbb = NULL;
FOR_EACH_VEC_ELT (scop->pbbs, i, pbb)
{
gimple_poly_bb_p gbb = PBB_BLACK_BOX (pbb);
@@ -338,12 +418,63 @@ build_scop_scattering (scop_p scop)
static_sched = isl_aff_add_coefficient_si (static_sched, isl_dim_in,
prefix, 1);
- build_pbb_scattering_polyhedrons (static_sched, pbb);
+ build_pbb_minimal_scattering_polyhedrons (static_sched, pbb,
+ sequence_dims, nb_sequence_params);
}
+ XDELETEVEC (sequence_dims);
isl_aff_free (static_sched);
}
+/* Build the original schedule showing the orginal order of execution
+ of statement instances.
+
+ The following example shows the original schedule:
+
+ for (i: ...)
+ {
+ for (j: ...)
+ {
+ A
+ }
+ B
+ }
+ C
+ for (i: ...)
+ {
+ D
+ }
+
+ Static schedules for A to D expressed in a union map:
+
+ { S_A[i0, i1] -> [i0, i1]; S_B[i0] -> [i0]; S_C[] -> []; S_9[i0] -> [i0] }
+
+*/
+
+static void
+build_scop_original_schedule (scop_p scop)
+{
+ isl_space *space = isl_set_get_space (scop->param_context);
+ isl_union_map *res = isl_union_map_empty (space);
+
+ int i;
+ poly_bb_p pbb;
+ FOR_EACH_VEC_ELT (scop->pbbs, i, pbb)
+ {
+ int nb_dimensions = isl_set_dim (pbb->domain, isl_dim_set);
+ isl_space *dc = isl_set_get_space (pbb->domain);
+ isl_space *dm = isl_space_add_dims (isl_space_from_domain (dc),
+ isl_dim_out, nb_dimensions);
+ isl_map *mp = isl_map_universe (dm);
+ for (int i = 0; i < nb_dimensions; i++)
+ mp = isl_map_equate (mp, isl_dim_in, i, isl_dim_out, i);
+
+ res = isl_union_map_add_map (res, mp);
+ }
+ scop->original_schedule = res;
+}
+
+
static isl_pw_aff *extract_affine (scop_p, tree, __isl_take isl_space *space);
/* Extract an affine expression from the chain of recurrence E. */
@@ -1716,7 +1847,8 @@ build_poly_scop (scop_p scop)
rewrite_cross_bb_scalar_deps_out_of_ssa (scop);
build_scop_drs (scop);
- build_scop_scattering (scop);
+ build_scop_minimal_scattering (scop);
+ build_scop_original_schedule (scop);
/* This SCoP has been translated to the polyhedral
representation. */
diff --git a/gcc/ifcvt.c b/gcc/ifcvt.c
index 1c3328324ad..fff62de02a0 100644
--- a/gcc/ifcvt.c
+++ b/gcc/ifcvt.c
@@ -942,7 +942,7 @@ noce_emit_move_insn (rtx x, rtx y)
}
gcc_assert (start < (MEM_P (op) ? BITS_PER_UNIT : BITS_PER_WORD));
- store_bit_field (op, size, start, 0, 0, GET_MODE (x), y);
+ store_bit_field (op, size, start, 0, 0, GET_MODE (x), y, false);
return;
}
@@ -997,7 +997,7 @@ noce_emit_move_insn (rtx x, rtx y)
outmode = GET_MODE (outer);
bitpos = SUBREG_BYTE (outer) * BITS_PER_UNIT;
store_bit_field (inner, GET_MODE_BITSIZE (outmode), bitpos,
- 0, 0, outmode, y);
+ 0, 0, outmode, y, false);
}
/* Return the CC reg if it is used in COND. */
diff --git a/gcc/input.c b/gcc/input.c
index e7302a42589..0f6d448b546 100644
--- a/gcc/input.c
+++ b/gcc/input.c
@@ -751,6 +751,22 @@ expand_location_to_spelling_point (source_location loc)
return expand_location_1 (loc, /*expansion_point_p=*/false);
}
+/* The rich_location class within libcpp requires a way to expand
+ source_location instances, and relies on the client code
+ providing a symbol named
+ linemap_client_expand_location_to_spelling_point
+ to do this.
+
+ This is the implementation for libcommon.a (all host binaries),
+ which simply calls into expand_location_to_spelling_point. */
+
+expanded_location
+linemap_client_expand_location_to_spelling_point (source_location loc)
+{
+ return expand_location_to_spelling_point (loc);
+}
+
+
/* If LOCATION is in a system header and if it is a virtual location for
a token coming from the expansion of a macro, unwind it to the
location of the expansion point of the macro. Otherwise, just return
@@ -866,6 +882,12 @@ dump_line_table_statistics (void)
fprintf (stderr, "Total used maps size: %5ld%c\n",
SCALE (total_used_map_size),
STAT_LABEL (total_used_map_size));
+ fprintf (stderr, "Ad-hoc table size: %5ld%c\n",
+ SCALE (s.adhoc_table_size),
+ STAT_LABEL (s.adhoc_table_size));
+ fprintf (stderr, "Ad-hoc table entries used: %5ld\n",
+ s.adhoc_table_entries_used);
+
fprintf (stderr, "\n");
}
diff --git a/gcc/internal-fn.c b/gcc/internal-fn.c
index 6fac752af61..afbfae815e5 100644
--- a/gcc/internal-fn.c
+++ b/gcc/internal-fn.c
@@ -43,7 +43,6 @@ along with GCC; see the file COPYING3. If not see
const char *const internal_fn_name_array[] = {
#define DEF_INTERNAL_FN(CODE, FLAGS, FNSPEC) #CODE,
#include "internal-fn.def"
-#undef DEF_INTERNAL_FN
"<invalid-fn>"
};
@@ -51,7 +50,6 @@ const char *const internal_fn_name_array[] = {
const int internal_fn_flags_array[] = {
#define DEF_INTERNAL_FN(CODE, FLAGS, FNSPEC) FLAGS,
#include "internal-fn.def"
-#undef DEF_INTERNAL_FN
0
};
@@ -65,7 +63,6 @@ init_internal_fns ()
if (FNSPEC) internal_fn_fnspec_array[IFN_##CODE] = \
build_string ((int) sizeof (FNSPEC), FNSPEC ? FNSPEC : "");
#include "internal-fn.def"
-#undef DEF_INTERNAL_FN
internal_fn_fnspec_array[IFN_LAST] = 0;
}
@@ -2062,7 +2059,6 @@ expand_GOACC_REDUCTION (gcall *stmt ATTRIBUTE_UNUSED)
static void (*const internal_fn_expanders[]) (gcall *) = {
#define DEF_INTERNAL_FN(CODE, FLAGS, FNSPEC) expand_##CODE,
#include "internal-fn.def"
-#undef DEF_INTERNAL_FN
0
};
diff --git a/gcc/internal-fn.def b/gcc/internal-fn.def
index ca06b10d831..d0eb704bd15 100644
--- a/gcc/internal-fn.def
+++ b/gcc/internal-fn.def
@@ -86,3 +86,5 @@ DEF_INTERNAL_FN (GOACC_LOOP, ECF_PURE | ECF_NOTHROW, NULL)
/* OpenACC reduction abstraction. See internal-fn.h for usage. */
DEF_INTERNAL_FN (GOACC_REDUCTION, ECF_NOTHROW | ECF_LEAF, NULL)
+
+#undef DEF_INTERNAL_FN
diff --git a/gcc/ipa-cp.c b/gcc/ipa-cp.c
index 27104940fd8..6ba2f1493f8 100644
--- a/gcc/ipa-cp.c
+++ b/gcc/ipa-cp.c
@@ -1055,7 +1055,7 @@ ipa_get_jf_ancestor_result (struct ipa_jump_func *jfunc, tree input)
{
tree t = TREE_OPERAND (input, 0);
t = build_ref_for_offset (EXPR_LOCATION (t), t,
- ipa_get_jf_ancestor_offset (jfunc),
+ ipa_get_jf_ancestor_offset (jfunc), false,
ptr_type_node, NULL, false);
return build_fold_addr_expr (t);
}
diff --git a/gcc/ipa-inline-analysis.c b/gcc/ipa-inline-analysis.c
index a3cd769a461..c07b0da9007 100644
--- a/gcc/ipa-inline-analysis.c
+++ b/gcc/ipa-inline-analysis.c
@@ -2853,6 +2853,7 @@ estimate_function_body_sizes (struct cgraph_node *node, bool early)
inline_summaries->get (node)->self_time = time;
inline_summaries->get (node)->self_size = size;
nonconstant_names.release ();
+ fbi.bb_infos.release ();
if (opt_for_fn (node->decl, optimize))
{
if (!early)
diff --git a/gcc/ipa-polymorphic-call.c b/gcc/ipa-polymorphic-call.c
index 2f284950d8d..a577ffab68d 100644
--- a/gcc/ipa-polymorphic-call.c
+++ b/gcc/ipa-polymorphic-call.c
@@ -154,6 +154,8 @@ ipa_polymorphic_call_context::restrict_to_inner_class (tree otr_type,
&& tree_to_shwi (TYPE_SIZE (outer_type)) >= 0
&& tree_to_shwi (TYPE_SIZE (outer_type)) <= offset)
{
+ bool der = maybe_derived_type; /* clear_outer_type will reset it. */
+ bool dyn = dynamic;
clear_outer_type (otr_type);
type = otr_type;
cur_offset = 0;
@@ -162,7 +164,7 @@ ipa_polymorphic_call_context::restrict_to_inner_class (tree otr_type,
For dynamic types, we really do not have information about
size of the memory location. It is possible that completely
different type is stored after outer_type. */
- if (!maybe_derived_type && !dynamic)
+ if (!der && !dyn)
{
clear_speculation ();
invalid = true;
@@ -425,8 +427,10 @@ no_useful_type_info:
return true;
}
else
- clear_speculation ();
- return true;
+ {
+ clear_speculation ();
+ return true;
+ }
}
else
{
@@ -459,15 +463,18 @@ contains_type_p (tree outer_type, HOST_WIDE_INT offset,
if (offset < 0)
return false;
if (TYPE_SIZE (outer_type) && TYPE_SIZE (otr_type)
- && TREE_CODE (outer_type) == INTEGER_CST
- && TREE_CODE (otr_type) == INTEGER_CST
- && wi::ltu_p (wi::to_offset (outer_type), (wi::to_offset (otr_type) + offset)))
+ && TREE_CODE (TYPE_SIZE (outer_type)) == INTEGER_CST
+ && TREE_CODE (TYPE_SIZE (otr_type)) == INTEGER_CST
+ && wi::ltu_p (wi::to_offset (TYPE_SIZE (outer_type)),
+ (wi::to_offset (TYPE_SIZE (otr_type)) + offset)))
return false;
context.offset = offset;
context.outer_type = TYPE_MAIN_VARIANT (outer_type);
context.maybe_derived_type = false;
- return context.restrict_to_inner_class (otr_type, consider_placement_new, consider_bases);
+ context.dynamic = false;
+ return context.restrict_to_inner_class (otr_type, consider_placement_new,
+ consider_bases);
}
@@ -742,6 +749,7 @@ ipa_polymorphic_call_context::set_by_invariant (tree cst,
HOST_WIDE_INT off)
{
HOST_WIDE_INT offset2, size, max_size;
+ bool reverse;
tree base;
invalid = false;
@@ -752,7 +760,7 @@ ipa_polymorphic_call_context::set_by_invariant (tree cst,
return false;
cst = TREE_OPERAND (cst, 0);
- base = get_ref_base_and_extent (cst, &offset2, &size, &max_size);
+ base = get_ref_base_and_extent (cst, &offset2, &size, &max_size, &reverse);
if (!DECL_P (base) || max_size == -1 || max_size != size)
return false;
@@ -882,8 +890,10 @@ ipa_polymorphic_call_context::ipa_polymorphic_call_context (tree fndecl,
{
HOST_WIDE_INT size, max_size;
HOST_WIDE_INT offset2;
- tree base = get_ref_base_and_extent (TREE_OPERAND (base_pointer, 0),
- &offset2, &size, &max_size);
+ bool reverse;
+ tree base
+ = get_ref_base_and_extent (TREE_OPERAND (base_pointer, 0),
+ &offset2, &size, &max_size, &reverse);
if (max_size != -1 && max_size == size)
combine_speculation_with (TYPE_MAIN_VARIANT (TREE_TYPE (base)),
@@ -1151,6 +1161,7 @@ extr_type_from_vtbl_ptr_store (gimple *stmt, struct type_change_info *tci,
{
HOST_WIDE_INT offset, size, max_size;
tree lhs, rhs, base;
+ bool reverse;
if (!gimple_assign_single_p (stmt))
return NULL_TREE;
@@ -1169,7 +1180,7 @@ extr_type_from_vtbl_ptr_store (gimple *stmt, struct type_change_info *tci,
;
else
{
- base = get_ref_base_and_extent (lhs, &offset, &size, &max_size);
+ base = get_ref_base_and_extent (lhs, &offset, &size, &max_size, &reverse);
if (DECL_P (tci->instance))
{
if (base != tci->instance)
@@ -1358,6 +1369,7 @@ check_stmt_for_type_change (ao_ref *ao ATTRIBUTE_UNUSED, tree vdef, void *data)
tree op = walk_ssa_copies (gimple_call_arg (stmt, 0));
tree type = TYPE_METHOD_BASETYPE (TREE_TYPE (fn));
HOST_WIDE_INT offset = 0, size, max_size;
+ bool reverse;
if (dump_file)
{
@@ -1368,8 +1380,8 @@ check_stmt_for_type_change (ao_ref *ao ATTRIBUTE_UNUSED, tree vdef, void *data)
/* See if THIS parameter seems like instance pointer. */
if (TREE_CODE (op) == ADDR_EXPR)
{
- op = get_ref_base_and_extent (TREE_OPERAND (op, 0),
- &offset, &size, &max_size);
+ op = get_ref_base_and_extent (TREE_OPERAND (op, 0), &offset,
+ &size, &max_size, &reverse);
if (size != max_size || max_size == -1)
{
tci->speculative = true;
@@ -1527,6 +1539,7 @@ ipa_polymorphic_call_context::get_dynamic_type (tree instance,
{
tree ref = gimple_call_fn (call);
HOST_WIDE_INT offset2, size, max_size;
+ bool reverse;
if (TREE_CODE (ref) == OBJ_TYPE_REF)
{
@@ -1556,8 +1569,9 @@ ipa_polymorphic_call_context::get_dynamic_type (tree instance,
&& gimple_assign_load_p (SSA_NAME_DEF_STMT (ref)))
{
tree ref_exp = gimple_assign_rhs1 (SSA_NAME_DEF_STMT (ref));
- tree base_ref = get_ref_base_and_extent
- (ref_exp, &offset2, &size, &max_size);
+ tree base_ref
+ = get_ref_base_and_extent (ref_exp, &offset2, &size,
+ &max_size, &reverse);
/* Finally verify that what we found looks like read from
OTR_OBJECT or from INSTANCE with offset OFFSET. */
diff --git a/gcc/ipa-prop.c b/gcc/ipa-prop.c
index 81dc71edf77..d15f0ebed56 100644
--- a/gcc/ipa-prop.c
+++ b/gcc/ipa-prop.c
@@ -952,7 +952,9 @@ ipa_load_from_parm_agg (struct ipa_func_body_info *fbi,
{
int index;
HOST_WIDE_INT size, max_size;
- tree base = get_ref_base_and_extent (op, offset_p, &size, &max_size);
+ bool reverse;
+ tree base
+ = get_ref_base_and_extent (op, offset_p, &size, &max_size, &reverse);
if (max_size == -1 || max_size != size || *offset_p < 0)
return false;
@@ -1077,6 +1079,7 @@ compute_complex_assign_jump_func (struct ipa_func_body_info *fbi,
{
HOST_WIDE_INT offset, size, max_size;
tree op1, tc_ssa, base, ssa;
+ bool reverse;
int index;
op1 = gimple_assign_rhs1 (stmt);
@@ -1124,7 +1127,7 @@ compute_complex_assign_jump_func (struct ipa_func_body_info *fbi,
op1 = TREE_OPERAND (op1, 0);
if (TREE_CODE (TREE_TYPE (op1)) != RECORD_TYPE)
return;
- base = get_ref_base_and_extent (op1, &offset, &size, &max_size);
+ base = get_ref_base_and_extent (op1, &offset, &size, &max_size, &reverse);
if (TREE_CODE (base) != MEM_REF
/* If this is a varying address, punt. */
|| max_size == -1
@@ -1160,6 +1163,7 @@ get_ancestor_addr_info (gimple *assign, tree *obj_p, HOST_WIDE_INT *offset)
{
HOST_WIDE_INT size, max_size;
tree expr, parm, obj;
+ bool reverse;
if (!gimple_assign_single_p (assign))
return NULL_TREE;
@@ -1169,7 +1173,7 @@ get_ancestor_addr_info (gimple *assign, tree *obj_p, HOST_WIDE_INT *offset)
return NULL_TREE;
expr = TREE_OPERAND (expr, 0);
obj = expr;
- expr = get_ref_base_and_extent (expr, offset, &size, &max_size);
+ expr = get_ref_base_and_extent (expr, offset, &size, &max_size, &reverse);
if (TREE_CODE (expr) != MEM_REF
/* If this is a varying address, punt. */
@@ -1435,10 +1439,11 @@ determine_locally_known_aggregate_parts (gcall *call, tree arg,
else if (TREE_CODE (arg) == ADDR_EXPR)
{
HOST_WIDE_INT arg_max_size;
+ bool reverse;
arg = TREE_OPERAND (arg, 0);
arg_base = get_ref_base_and_extent (arg, &arg_offset, &arg_size,
- &arg_max_size);
+ &arg_max_size, &reverse);
if (arg_max_size == -1
|| arg_max_size != arg_size
|| arg_offset < 0)
@@ -1457,13 +1462,14 @@ determine_locally_known_aggregate_parts (gcall *call, tree arg,
else
{
HOST_WIDE_INT arg_max_size;
+ bool reverse;
gcc_checking_assert (AGGREGATE_TYPE_P (TREE_TYPE (arg)));
by_ref = false;
check_ref = false;
arg_base = get_ref_base_and_extent (arg, &arg_offset, &arg_size,
- &arg_max_size);
+ &arg_max_size, &reverse);
if (arg_max_size == -1
|| arg_max_size != arg_size
|| arg_offset < 0)
@@ -1484,6 +1490,7 @@ determine_locally_known_aggregate_parts (gcall *call, tree arg,
gimple *stmt = gsi_stmt (gsi);
HOST_WIDE_INT lhs_offset, lhs_size, lhs_max_size;
tree lhs, rhs, lhs_base;
+ bool reverse;
if (!stmt_may_clobber_ref_p_1 (stmt, &r))
continue;
@@ -1498,7 +1505,7 @@ determine_locally_known_aggregate_parts (gcall *call, tree arg,
break;
lhs_base = get_ref_base_and_extent (lhs, &lhs_offset, &lhs_size,
- &lhs_max_size);
+ &lhs_max_size, &reverse);
if (lhs_max_size == -1
|| lhs_max_size != lhs_size)
break;
@@ -3968,6 +3975,7 @@ ipa_modify_call_arguments (struct cgraph_edge *cs, gcall *stmt,
base = force_gimple_operand_gsi (&gsi, base,
true, NULL, true, GSI_SAME_STMT);
expr = fold_build2_loc (loc, MEM_REF, type, base, off);
+ REF_REVERSE_STORAGE_ORDER (expr) = adj->reverse;
/* If expr is not a valid gimple call argument emit
a load into a temporary. */
if (is_gimple_reg_type (TREE_TYPE (expr)))
@@ -3987,6 +3995,7 @@ ipa_modify_call_arguments (struct cgraph_edge *cs, gcall *stmt,
else
{
expr = fold_build2_loc (loc, MEM_REF, adj->type, base, off);
+ REF_REVERSE_STORAGE_ORDER (expr) = adj->reverse;
expr = build_fold_addr_expr (expr);
expr = force_gimple_operand_gsi (&gsi, expr,
true, NULL, true, GSI_SAME_STMT);
@@ -4091,7 +4100,10 @@ ipa_modify_expr (tree *expr, bool convert,
tree src;
if (cand->by_ref)
- src = build_simple_mem_ref (cand->new_decl);
+ {
+ src = build_simple_mem_ref (cand->new_decl);
+ REF_REVERSE_STORAGE_ORDER (src) = cand->reverse;
+ }
else
src = cand->new_decl;
@@ -4158,7 +4170,9 @@ ipa_get_adjustment_candidate (tree **expr, bool *convert,
}
HOST_WIDE_INT offset, size, max_size;
- tree base = get_ref_base_and_extent (**expr, &offset, &size, &max_size);
+ bool reverse;
+ tree base
+ = get_ref_base_and_extent (**expr, &offset, &size, &max_size, &reverse);
if (!base || size == -1 || max_size == -1)
return NULL;
diff --git a/gcc/ipa-prop.h b/gcc/ipa-prop.h
index 35952dce1ca..b69ee8ab745 100644
--- a/gcc/ipa-prop.h
+++ b/gcc/ipa-prop.h
@@ -737,6 +737,10 @@ struct ipa_parm_adjustment
or one about to be removed. */
enum ipa_parm_op op;
+ /* Storage order of the original parameter (for the cases when the new
+ parameter is a component of an original one). */
+ unsigned reverse : 1;
+
/* The parameter is to be passed by reference. */
unsigned by_ref : 1;
};
@@ -774,7 +778,7 @@ ipa_parm_adjustment *ipa_get_adjustment_candidate (tree **, bool *,
/* From tree-sra.c: */
-tree build_ref_for_offset (location_t, tree, HOST_WIDE_INT, tree,
+tree build_ref_for_offset (location_t, tree, HOST_WIDE_INT, bool, tree,
gimple_stmt_iterator *, bool);
/* In ipa-cp.c */
diff --git a/gcc/jit/ChangeLog b/gcc/jit/ChangeLog
index 301179bbdc0..5da80441c5c 100644
--- a/gcc/jit/ChangeLog
+++ b/gcc/jit/ChangeLog
@@ -1,3 +1,7 @@
+2015-11-07 Richard Sandiford <richard.sandiford@arm.com>
+
+ * jit-builtins.c: Don't undef DEF_BUILTIN.
+
2015-10-29 Andrew MacLeod <amacleod@redhat.com>
* dummy-frontend.c: Reorder #include's and remove duplicates.
diff --git a/gcc/jit/jit-builtins.c b/gcc/jit/jit-builtins.c
index b28a5de21f7..63ff5affb55 100644
--- a/gcc/jit/jit-builtins.c
+++ b/gcc/jit/jit-builtins.c
@@ -62,7 +62,6 @@ static const struct builtin_data builtin_data[] =
{
#include "builtins.def"
};
-#undef DEF_BUILTIN
/* Helper function for find_builtin_by_name. */
diff --git a/gcc/lra.c b/gcc/lra.c
index 0cd37f02032..0995c54aee4 100644
--- a/gcc/lra.c
+++ b/gcc/lra.c
@@ -1293,7 +1293,7 @@ init_reg_info (void)
lra_reg_info = XNEWVEC (struct lra_reg, reg_info_size);
for (i = 0; i < reg_info_size; i++)
initialize_lra_reg_info_element (i);
- copy_vec.create (100);
+ copy_vec.truncate (0);
}
diff --git a/gcc/lto-streamer-out.c b/gcc/lto-streamer-out.c
index f32f8f894a0..3e087d1e124 100644
--- a/gcc/lto-streamer-out.c
+++ b/gcc/lto-streamer-out.c
@@ -958,7 +958,8 @@ hash_tree (struct streamer_tree_cache_d *cache, hash_map<tree, hashval_t> *map,
hstate.add_flag (TREE_PRIVATE (t));
if (TYPE_P (t))
{
- hstate.add_flag (TYPE_SATURATING (t));
+ hstate.add_flag (AGGREGATE_TYPE_P (t)
+ ? TYPE_REVERSE_STORAGE_ORDER (t) : TYPE_SATURATING (t));
hstate.add_flag (TYPE_ADDR_SPACE (t));
}
else if (code == SSA_NAME)
diff --git a/gcc/lto/ChangeLog b/gcc/lto/ChangeLog
index 332251cd62f..d254bee4685 100644
--- a/gcc/lto/ChangeLog
+++ b/gcc/lto/ChangeLog
@@ -1,3 +1,11 @@
+2015-11-08 Eric Botcazou <ebotcazou@adacore.com>
+
+ * lto.c (compare_tree_sccs_1): Deal with TYPE_REVERSE_STORAGE_ORDER.
+
+2015-11-07 Richard Sandiford <richard.sandiford@arm.com>
+
+ * lto-lang.c: Don't undef DEF_BUILTIN.
+
2015-10-29 Andrew MacLeod <amacleod@redhat.com>
* lto-lang.c: Reorder #include's and remove duplicates.
diff --git a/gcc/lto/lto-lang.c b/gcc/lto/lto-lang.c
index be317a42fbe..4805c2a69b1 100644
--- a/gcc/lto/lto-lang.c
+++ b/gcc/lto/lto-lang.c
@@ -731,7 +731,6 @@ lto_define_builtins (tree va_list_ref_type_node ATTRIBUTE_UNUSED,
builtin_types[(int) LIBTYPE], BOTH_P, FALLBACK_P, \
NONANSI_P, built_in_attributes[(int) ATTRS], IMPLICIT);
#include "builtins.def"
-#undef DEF_BUILTIN
}
static GTY(()) tree registered_builtin_types;
diff --git a/gcc/lto/lto.c b/gcc/lto/lto.c
index 8510f6598ba..5dcc4dcd851 100644
--- a/gcc/lto/lto.c
+++ b/gcc/lto/lto.c
@@ -1021,7 +1021,10 @@ compare_tree_sccs_1 (tree t1, tree t2, tree **map)
compare_values (TREE_DEPRECATED);
if (TYPE_P (t1))
{
- compare_values (TYPE_SATURATING);
+ if (AGGREGATE_TYPE_P (t1))
+ compare_values (TYPE_REVERSE_STORAGE_ORDER);
+ else
+ compare_values (TYPE_SATURATING);
compare_values (TYPE_ADDR_SPACE);
}
else if (code == SSA_NAME)
diff --git a/gcc/objc/ChangeLog b/gcc/objc/ChangeLog
index 23721f60005..57b5db48bcb 100644
--- a/gcc/objc/ChangeLog
+++ b/gcc/objc/ChangeLog
@@ -1,3 +1,8 @@
+2015-11-09 Alan Modra <amodra@gmail.com>
+
+ * objc-encoding.c (encode_aggregate_within): Cast obstack_next_free
+ return value.
+
2015-10-29 Andrew MacLeod <amacleod@redhat.com>
* objc-lang.c: Reorder #include's and remove duplicates.
diff --git a/gcc/objc/objc-encoding.c b/gcc/objc/objc-encoding.c
index 48480213534..9c577e93bae 100644
--- a/gcc/objc/objc-encoding.c
+++ b/gcc/objc/objc-encoding.c
@@ -495,13 +495,14 @@ encode_aggregate_within (tree type, int curtype, int format, int left,
if (flag_next_runtime)
{
- if (ob_size > 0 && *(obstack_next_free (&util_obstack) - 1) == '^')
+ if (ob_size > 0
+ && *((char *) obstack_next_free (&util_obstack) - 1) == '^')
pointed_to = true;
if ((format == OBJC_ENCODE_INLINE_DEFS || generating_instance_variables)
&& (!pointed_to || ob_size - curtype == 1
|| (ob_size - curtype == 2
- && *(obstack_next_free (&util_obstack) - 2) == 'r')))
+ && *((char *) obstack_next_free (&util_obstack) - 2) == 'r')))
inline_contents = true;
}
else
@@ -512,9 +513,10 @@ encode_aggregate_within (tree type, int curtype, int format, int left,
comment above applies: in that case we should avoid encoding
the names of instance variables.
*/
- char c1 = ob_size > 1 ? *(obstack_next_free (&util_obstack) - 2) : 0;
- char c0 = ob_size > 0 ? *(obstack_next_free (&util_obstack) - 1) : 0;
+ char c0, c1;
+ c1 = ob_size > 1 ? *((char *) obstack_next_free (&util_obstack) - 2) : 0;
+ c0 = ob_size > 0 ? *((char *) obstack_next_free (&util_obstack) - 1) : 0;
if (c0 == '^' || (c1 == '^' && c0 == 'r'))
pointed_to = true;
diff --git a/gcc/omp-low.c b/gcc/omp-low.c
index 5ffb2765059..45d1927f678 100644
--- a/gcc/omp-low.c
+++ b/gcc/omp-low.c
@@ -3112,9 +3112,9 @@ check_omp_nesting_restrictions (gimple *stmt, omp_context *ctx)
if (!(is_gimple_omp (stmt)
&& is_gimple_omp_oacc (stmt)))
{
- for (omp_context *ctx_ = ctx; ctx_ != NULL; ctx_ = ctx_->outer)
- if (is_gimple_omp (ctx_->stmt)
- && is_gimple_omp_oacc (ctx_->stmt)
+ for (omp_context *octx = ctx; octx != NULL; octx = octx->outer)
+ if (is_gimple_omp (octx->stmt)
+ && is_gimple_omp_oacc (octx->stmt)
/* Except for atomic codes that we share with OpenMP. */
&& ! (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_LOAD
|| gimple_code (stmt) == GIMPLE_OMP_ATOMIC_STORE))
@@ -3134,12 +3134,27 @@ check_omp_nesting_restrictions (gimple *stmt, omp_context *ctx)
if (gimple_code (stmt) == GIMPLE_OMP_ORDERED)
{
c = gimple_omp_ordered_clauses (as_a <gomp_ordered *> (stmt));
- if (c && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SIMD)
- return true;
+ if (find_omp_clause (c, OMP_CLAUSE_SIMD))
+ {
+ if (find_omp_clause (c, OMP_CLAUSE_THREADS)
+ && (ctx->outer == NULL
+ || !gimple_omp_for_combined_into_p (ctx->stmt)
+ || gimple_code (ctx->outer->stmt) != GIMPLE_OMP_FOR
+ || (gimple_omp_for_kind (ctx->outer->stmt)
+ != GF_OMP_FOR_KIND_FOR)
+ || !gimple_omp_for_combined_p (ctx->outer->stmt)))
+ {
+ error_at (gimple_location (stmt),
+ "%<ordered simd threads%> must be closely "
+ "nested inside of %<for simd%> region");
+ return false;
+ }
+ return true;
+ }
}
error_at (gimple_location (stmt),
"OpenMP constructs other than %<#pragma omp ordered simd%>"
- " may not be nested inside simd region");
+ " may not be nested inside %<simd%> region");
return false;
}
else if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
@@ -3150,8 +3165,9 @@ check_omp_nesting_restrictions (gimple *stmt, omp_context *ctx)
&& gimple_code (stmt) != GIMPLE_OMP_PARALLEL)
{
error_at (gimple_location (stmt),
- "only distribute or parallel constructs are allowed to "
- "be closely nested inside teams construct");
+ "only %<distribute%> or %<parallel%> regions are "
+ "allowed to be strictly nested inside %<teams%> "
+ "region");
return false;
}
}
@@ -3166,8 +3182,8 @@ check_omp_nesting_restrictions (gimple *stmt, omp_context *ctx)
if (ctx != NULL && gimple_code (ctx->stmt) != GIMPLE_OMP_TEAMS)
{
error_at (gimple_location (stmt),
- "distribute construct must be closely nested inside "
- "teams construct");
+ "%<distribute%> region must be strictly nested "
+ "inside %<teams%> construct");
return false;
}
return true;
@@ -3222,13 +3238,15 @@ check_omp_nesting_restrictions (gimple *stmt, omp_context *ctx)
{
const char *bad = NULL;
const char *kind = NULL;
+ const char *construct
+ = (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
+ == BUILT_IN_GOMP_CANCEL)
+ ? "#pragma omp cancel"
+ : "#pragma omp cancellation point";
if (ctx == NULL)
{
error_at (gimple_location (stmt), "orphaned %qs construct",
- DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
- == BUILT_IN_GOMP_CANCEL
- ? "#pragma omp cancel"
- : "#pragma omp cancellation point");
+ construct);
return false;
}
switch (tree_fits_shwi_p (gimple_call_arg (stmt, 0))
@@ -3304,7 +3322,33 @@ check_omp_nesting_restrictions (gimple *stmt, omp_context *ctx)
if (gimple_code (ctx->stmt) != GIMPLE_OMP_TASK)
bad = "#pragma omp task";
else
- ctx->cancellable = true;
+ {
+ for (omp_context *octx = ctx->outer;
+ octx; octx = octx->outer)
+ {
+ switch (gimple_code (octx->stmt))
+ {
+ case GIMPLE_OMP_TASKGROUP:
+ break;
+ case GIMPLE_OMP_TARGET:
+ if (gimple_omp_target_kind (octx->stmt)
+ != GF_OMP_TARGET_KIND_REGION)
+ continue;
+ /* FALLTHRU */
+ case GIMPLE_OMP_PARALLEL:
+ case GIMPLE_OMP_TEAMS:
+ error_at (gimple_location (stmt),
+ "%<%s taskgroup%> construct not closely "
+ "nested inside of %<taskgroup%> region",
+ construct);
+ return false;
+ default:
+ continue;
+ }
+ break;
+ }
+ ctx->cancellable = true;
+ }
kind = "taskgroup";
break;
default:
@@ -3315,10 +3359,7 @@ check_omp_nesting_restrictions (gimple *stmt, omp_context *ctx)
{
error_at (gimple_location (stmt),
"%<%s %s%> construct not closely nested inside of %qs",
- DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
- == BUILT_IN_GOMP_CANCEL
- ? "#pragma omp cancel"
- : "#pragma omp cancellation point", kind, bad);
+ construct, kind, bad);
return false;
}
}
@@ -3329,6 +3370,10 @@ check_omp_nesting_restrictions (gimple *stmt, omp_context *ctx)
switch (gimple_code (ctx->stmt))
{
case GIMPLE_OMP_FOR:
+ if (gimple_omp_for_kind (ctx->stmt) != GF_OMP_FOR_KIND_FOR
+ && gimple_omp_for_kind (ctx->stmt) != GF_OMP_FOR_KIND_TASKLOOP)
+ break;
+ /* FALLTHRU */
case GIMPLE_OMP_SECTIONS:
case GIMPLE_OMP_SINGLE:
case GIMPLE_OMP_ORDERED:
@@ -3342,17 +3387,24 @@ check_omp_nesting_restrictions (gimple *stmt, omp_context *ctx)
return true;
error_at (gimple_location (stmt),
"barrier region may not be closely nested inside "
- "of work-sharing, critical, ordered, master or "
- "explicit task region");
+ "of work-sharing, %<critical%>, %<ordered%>, "
+ "%<master%>, explicit %<task%> or %<taskloop%> "
+ "region");
return false;
}
error_at (gimple_location (stmt),
"work-sharing region may not be closely nested inside "
- "of work-sharing, critical, ordered, master or explicit "
- "task region");
+ "of work-sharing, %<critical%>, %<ordered%>, "
+ "%<master%>, explicit %<task%> or %<taskloop%> region");
return false;
case GIMPLE_OMP_PARALLEL:
+ case GIMPLE_OMP_TEAMS:
return true;
+ case GIMPLE_OMP_TARGET:
+ if (gimple_omp_target_kind (ctx->stmt)
+ == GF_OMP_TARGET_KIND_REGION)
+ return true;
+ break;
default:
break;
}
@@ -3362,15 +3414,26 @@ check_omp_nesting_restrictions (gimple *stmt, omp_context *ctx)
switch (gimple_code (ctx->stmt))
{
case GIMPLE_OMP_FOR:
+ if (gimple_omp_for_kind (ctx->stmt) != GF_OMP_FOR_KIND_FOR
+ && gimple_omp_for_kind (ctx->stmt) != GF_OMP_FOR_KIND_TASKLOOP)
+ break;
+ /* FALLTHRU */
case GIMPLE_OMP_SECTIONS:
case GIMPLE_OMP_SINGLE:
case GIMPLE_OMP_TASK:
error_at (gimple_location (stmt),
- "master region may not be closely nested inside "
- "of work-sharing or explicit task region");
+ "%<master%> region may not be closely nested inside "
+ "of work-sharing, explicit %<task%> or %<taskloop%> "
+ "region");
return false;
case GIMPLE_OMP_PARALLEL:
+ case GIMPLE_OMP_TEAMS:
return true;
+ case GIMPLE_OMP_TARGET:
+ if (gimple_omp_target_kind (ctx->stmt)
+ == GF_OMP_TARGET_KIND_REGION)
+ return true;
+ break;
default:
break;
}
@@ -3395,8 +3458,7 @@ check_omp_nesting_restrictions (gimple *stmt, omp_context *ctx)
if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_DEPEND)
{
gcc_assert (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_THREADS
- || (ctx == NULL
- && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SIMD));
+ || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SIMD);
continue;
}
enum omp_clause_depend_kind kind = OMP_CLAUSE_DEPEND_KIND (c);
@@ -3412,23 +3474,40 @@ check_omp_nesting_restrictions (gimple *stmt, omp_context *ctx)
OMP_CLAUSE_ORDERED)) == NULL_TREE)
{
error_at (OMP_CLAUSE_LOCATION (c),
- "%<depend%> clause must be closely nested "
- "inside an ordered loop");
+ "%<ordered%> construct with %<depend%> clause "
+ "must be closely nested inside an %<ordered%> "
+ "loop");
return false;
}
else if (OMP_CLAUSE_ORDERED_EXPR (oclause) == NULL_TREE)
{
error_at (OMP_CLAUSE_LOCATION (c),
- "%<depend%> clause must be closely nested "
- "inside a loop with %<ordered%> clause with "
- "a parameter");
+ "%<ordered%> construct with %<depend%> clause "
+ "must be closely nested inside a loop with "
+ "%<ordered%> clause with a parameter");
return false;
}
}
else
{
error_at (OMP_CLAUSE_LOCATION (c),
- "invalid depend kind in omp ordered depend");
+ "invalid depend kind in omp %<ordered%> %<depend%>");
+ return false;
+ }
+ }
+ c = gimple_omp_ordered_clauses (as_a <gomp_ordered *> (stmt));
+ if (find_omp_clause (c, OMP_CLAUSE_SIMD))
+ {
+ /* ordered simd must be closely nested inside of simd region,
+ and simd region must not encounter constructs other than
+ ordered simd, therefore ordered simd may be either orphaned,
+ or ctx->stmt must be simd. The latter case is handled already
+ earlier. */
+ if (ctx != NULL)
+ {
+ error_at (gimple_location (stmt),
+ "%<ordered%> %<simd%> must be closely nested inside "
+ "%<simd%> region");
return false;
}
}
@@ -3437,24 +3516,35 @@ check_omp_nesting_restrictions (gimple *stmt, omp_context *ctx)
{
case GIMPLE_OMP_CRITICAL:
case GIMPLE_OMP_TASK:
+ case GIMPLE_OMP_ORDERED:
+ ordered_in_taskloop:
error_at (gimple_location (stmt),
- "ordered region may not be closely nested inside "
- "of critical or explicit task region");
+ "%<ordered%> region may not be closely nested inside "
+ "of %<critical%>, %<ordered%>, explicit %<task%> or "
+ "%<taskloop%> region");
return false;
case GIMPLE_OMP_FOR:
+ if (gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_TASKLOOP)
+ goto ordered_in_taskloop;
if (find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
OMP_CLAUSE_ORDERED) == NULL)
{
error_at (gimple_location (stmt),
- "ordered region must be closely nested inside "
- "a loop region with an ordered clause");
+ "%<ordered%> region must be closely nested inside "
+ "a loop region with an %<ordered%> clause");
return false;
}
return true;
+ case GIMPLE_OMP_TARGET:
+ if (gimple_omp_target_kind (ctx->stmt)
+ != GF_OMP_TARGET_KIND_REGION)
+ break;
+ /* FALLTHRU */
case GIMPLE_OMP_PARALLEL:
+ case GIMPLE_OMP_TEAMS:
error_at (gimple_location (stmt),
- "ordered region must be closely nested inside "
- "a loop region with an ordered clause");
+ "%<ordered%> region must be closely nested inside "
+ "a loop region with an %<ordered%> clause");
return false;
default:
break;
@@ -3470,8 +3560,8 @@ check_omp_nesting_restrictions (gimple *stmt, omp_context *ctx)
if (this_stmt_name == gimple_omp_critical_name (other_crit))
{
error_at (gimple_location (stmt),
- "critical region may not be nested inside a critical "
- "region with the same name");
+ "%<critical%> region may not be nested inside "
+ "a %<critical%> region with the same name");
return false;
}
}
@@ -3482,8 +3572,8 @@ check_omp_nesting_restrictions (gimple *stmt, omp_context *ctx)
|| gimple_omp_target_kind (ctx->stmt) != GF_OMP_TARGET_KIND_REGION)
{
error_at (gimple_location (stmt),
- "teams construct not closely nested inside of target "
- "region");
+ "%<teams%> construct not closely nested inside of "
+ "%<target%> construct");
return false;
}
break;
@@ -3549,7 +3639,7 @@ check_omp_nesting_restrictions (gimple *stmt, omp_context *ctx)
!= is_gimple_omp_oacc (ctx->stmt))
{
error_at (gimple_location (stmt),
- "%s %s construct inside of %s %s region",
+ "%s %qs construct inside of %s %qs region",
(is_gimple_omp_oacc (stmt)
? "OpenACC" : "OpenMP"), stmt_name,
(is_gimple_omp_oacc (ctx->stmt)
@@ -3562,15 +3652,14 @@ check_omp_nesting_restrictions (gimple *stmt, omp_context *ctx)
if (is_gimple_omp_oacc (ctx->stmt))
{
error_at (gimple_location (stmt),
- "%s construct inside of %s region",
+ "%qs construct inside of %qs region",
stmt_name, ctx_stmt_name);
return false;
}
else
{
- gcc_checking_assert (!is_gimple_omp_oacc (stmt));
warning_at (gimple_location (stmt), 0,
- "%s construct inside of %s region",
+ "%qs construct inside of %qs region",
stmt_name, ctx_stmt_name);
}
}
diff --git a/gcc/output.h b/gcc/output.h
index 4ce6eeaa2b4..f9ff85886db 100644
--- a/gcc/output.h
+++ b/gcc/output.h
@@ -278,10 +278,11 @@ extern section *get_named_text_section (tree, const char *, const char *);
#define assemble_aligned_integer(SIZE, VALUE) \
assemble_integer (VALUE, SIZE, (SIZE) * BITS_PER_UNIT, 1)
-#ifdef REAL_VALUE_TYPE_SIZE
-/* Assemble the floating-point constant D into an object of size MODE. */
-extern void assemble_real (REAL_VALUE_TYPE, machine_mode, unsigned);
-#endif
+/* Assemble the floating-point constant D into an object of size MODE. ALIGN
+ is the alignment of the constant in bits. If REVERSE is true, D is output
+ in reverse storage order. */
+extern void assemble_real (REAL_VALUE_TYPE, machine_mode, unsigned,
+ bool = false);
/* Write the address of the entity given by SYMBOL to SEC. */
extern void assemble_addr_to_section (rtx, section *);
diff --git a/gcc/postreload-gcse.c b/gcc/postreload-gcse.c
index ea4bba4365e..f8a770e25f2 100644
--- a/gcc/postreload-gcse.c
+++ b/gcc/postreload-gcse.c
@@ -348,6 +348,8 @@ free_mem (void)
BITMAP_FREE (blocks_with_calls);
BITMAP_FREE (modify_mem_list_set);
free (reg_avail_info);
+ free (modify_mem_list);
+ free (canon_modify_mem_list);
}
diff --git a/gcc/pretty-print.c b/gcc/pretty-print.c
index b24402de12d..4a28d3c5fd9 100644
--- a/gcc/pretty-print.c
+++ b/gcc/pretty-print.c
@@ -31,6 +31,27 @@ along with GCC; see the file COPYING3. If not see
#include <iconv.h>
#endif
+/* Overwrite the range within this text_info's rich_location.
+ For use e.g. when implementing "+" in client format decoders. */
+
+void
+text_info::set_range (unsigned int idx, source_range range, bool caret_p)
+{
+ gcc_checking_assert (m_richloc);
+ m_richloc->set_range (idx, range, caret_p, true);
+}
+
+location_t
+text_info::get_location (unsigned int index_of_location) const
+{
+ gcc_checking_assert (m_richloc);
+
+ if (index_of_location == 0)
+ return m_richloc->get_loc ();
+ else
+ return UNKNOWN_LOCATION;
+}
+
// Default construct an output buffer.
output_buffer::output_buffer ()
diff --git a/gcc/pretty-print.h b/gcc/pretty-print.h
index 2654b0fcbec..cdee2535fe0 100644
--- a/gcc/pretty-print.h
+++ b/gcc/pretty-print.h
@@ -27,11 +27,6 @@ along with GCC; see the file COPYING3. If not see
/* Maximum number of format string arguments. */
#define PP_NL_ARGMAX 30
-/* Maximum number of locations associated to each message. If
- location 'i' is UNKNOWN_LOCATION, then location 'i+1' is not
- valid. */
-#define MAX_LOCATIONS_PER_MESSAGE 2
-
/* The type of a text to be formatted according a format specification
along with a list of things. */
struct text_info
@@ -40,21 +35,17 @@ struct text_info
va_list *args_ptr;
int err_no; /* for %m */
void **x_data;
+ rich_location *m_richloc;
- inline void set_location (unsigned int index_of_location, location_t loc)
+ inline void set_location (unsigned int idx, location_t loc, bool caret_p)
{
- gcc_checking_assert (index_of_location < MAX_LOCATIONS_PER_MESSAGE);
- this->locations[index_of_location] = loc;
+ source_range src_range;
+ src_range.m_start = loc;
+ src_range.m_finish = loc;
+ set_range (idx, src_range, caret_p);
}
-
- inline location_t get_location (unsigned int index_of_location) const
- {
- gcc_checking_assert (index_of_location < MAX_LOCATIONS_PER_MESSAGE);
- return this->locations[index_of_location];
- }
-
-private:
- location_t locations[MAX_LOCATIONS_PER_MESSAGE];
+ void set_range (unsigned int idx, source_range range, bool caret_p);
+ location_t get_location (unsigned int index_of_location) const;
};
/* How often diagnostics are prefixed by their locations:
diff --git a/gcc/print-tree.c b/gcc/print-tree.c
index ad66e2f9c25..1b584b87ea0 100644
--- a/gcc/print-tree.c
+++ b/gcc/print-tree.c
@@ -565,6 +565,13 @@ print_node (FILE *file, const char *prefix, tree node, int indent)
if (TYPE_NEEDS_CONSTRUCTING (node))
fputs (" needs-constructing", file);
+ if ((code == RECORD_TYPE
+ || code == UNION_TYPE
+ || code == QUAL_UNION_TYPE
+ || code == ARRAY_TYPE)
+ && TYPE_REVERSE_STORAGE_ORDER (node))
+ fputs (" reverse-storage-order", file);
+
/* The transparent-union flag is used for different things in
different nodes. */
if ((code == UNION_TYPE || code == RECORD_TYPE)
diff --git a/gcc/rtl-error.c b/gcc/rtl-error.c
index d461cd4ba33..96da2bd275d 100644
--- a/gcc/rtl-error.c
+++ b/gcc/rtl-error.c
@@ -67,9 +67,10 @@ diagnostic_for_asm (const rtx_insn *insn, const char *msg, va_list *args_ptr,
diagnostic_t kind)
{
diagnostic_info diagnostic;
+ rich_location richloc (location_for_asm (insn));
diagnostic_set_info (&diagnostic, msg, args_ptr,
- location_for_asm (insn), kind);
+ &richloc, kind);
report_diagnostic (&diagnostic);
}
diff --git a/gcc/rtl.h b/gcc/rtl.h
index fe081ed3085..194ed9ba959 100644
--- a/gcc/rtl.h
+++ b/gcc/rtl.h
@@ -2086,6 +2086,7 @@ namespace wi
inline unsigned int
wi::int_traits <rtx_mode_t>::get_precision (const rtx_mode_t &x)
{
+ gcc_checking_assert (x.second != BLKmode && x.second != VOIDmode);
return GET_MODE_PRECISION (x.second);
}
diff --git a/gcc/sched-deps.c b/gcc/sched-deps.c
index 220eea461f6..4f64fa9d78d 100644
--- a/gcc/sched-deps.c
+++ b/gcc/sched-deps.c
@@ -4092,9 +4092,9 @@ void
sched_deps_finish (void)
{
gcc_assert (deps_pools_are_empty_p ());
- dn_pool->release_if_empty ();
+ delete dn_pool;
+ delete dl_pool;
dn_pool = NULL;
- dl_pool->release_if_empty ();
dl_pool = NULL;
h_d_i_d.release ();
diff --git a/gcc/simplify-rtx.c b/gcc/simplify-rtx.c
index b3c98c26e89..17568baa8b0 100644
--- a/gcc/simplify-rtx.c
+++ b/gcc/simplify-rtx.c
@@ -301,10 +301,11 @@ delegitimize_mem_from_attrs (rtx x)
{
HOST_WIDE_INT bitsize, bitpos;
tree toffset;
- int unsignedp, volatilep = 0;
+ int unsignedp, reversep, volatilep = 0;
- decl = get_inner_reference (decl, &bitsize, &bitpos, &toffset,
- &mode, &unsignedp, &volatilep, false);
+ decl
+ = get_inner_reference (decl, &bitsize, &bitpos, &toffset, &mode,
+ &unsignedp, &reversep, &volatilep, false);
if (bitsize != GET_MODE_BITSIZE (mode)
|| (bitpos % BITS_PER_UNIT)
|| (toffset && !tree_fits_shwi_p (toffset)))
diff --git a/gcc/stor-layout.c b/gcc/stor-layout.c
index 364a0b5454b..fac38951b34 100644
--- a/gcc/stor-layout.c
+++ b/gcc/stor-layout.c
@@ -2035,11 +2035,16 @@ finish_record_layout (record_layout_info rli, int free_p)
/* Compute bitfield representatives. */
finish_bitfield_layout (rli->t);
- /* Propagate TYPE_PACKED to variants. With C++ templates,
- handle_packed_attribute is too early to do this. */
+ /* Propagate TYPE_PACKED and TYPE_REVERSE_STORAGE_ORDER to variants.
+ With C++ templates, it is too early to do this when the attribute
+ is being parsed. */
for (variant = TYPE_NEXT_VARIANT (rli->t); variant;
variant = TYPE_NEXT_VARIANT (variant))
- TYPE_PACKED (variant) = TYPE_PACKED (rli->t);
+ {
+ TYPE_PACKED (variant) = TYPE_PACKED (rli->t);
+ TYPE_REVERSE_STORAGE_ORDER (variant)
+ = TYPE_REVERSE_STORAGE_ORDER (rli->t);
+ }
/* Lay out any static members. This is done now because their type
may use the record's type. */
diff --git a/gcc/target.def b/gcc/target.def
index c7ec2929714..0f7d3e5effb 100644
--- a/gcc/target.def
+++ b/gcc/target.def
@@ -3223,6 +3223,15 @@ converted to pointers to a subset address space via explicit casts.",
bool, (addr_space_t subset, addr_space_t superset),
default_addr_space_subset_p)
+/* True if 0 is a valid address in the address space, or false if
+ 0 is a NULL in the address space. */
+DEFHOOK
+(zero_address_valid,
+ "Define this to modify the default handling of address 0 for the\n\
+address space. Return true if 0 should be considered a valid address.",
+ bool, (addr_space_t as),
+ default_addr_space_zero_address_valid)
+
/* Function to convert an rtl expression from one address space to another. */
DEFHOOK
(convert,
@@ -3235,6 +3244,14 @@ as determined by the @code{TARGET_ADDR_SPACE_SUBSET_P} target hook.",
rtx, (rtx op, tree from_type, tree to_type),
default_addr_space_convert)
+/* Function to encode an address space into dwarf. */
+DEFHOOK
+(debug,
+ "Define this to define how the address space is encoded in dwarf.\n\
+The result is the value to be used with @code{DW_AT_address_class}.",
+ int, (addr_space_t as),
+ default_addr_space_debug)
+
HOOK_VECTOR_END (addr_space)
#undef HOOK_PREFIX
diff --git a/gcc/targhooks.c b/gcc/targhooks.c
index 14324b7addc..c810525be92 100644
--- a/gcc/targhooks.c
+++ b/gcc/targhooks.c
@@ -1268,6 +1268,23 @@ default_addr_space_subset_p (addr_space_t subset, addr_space_t superset)
return (subset == superset);
}
+/* The default hook for determining if 0 within a named address
+ space is a valid address. */
+
+bool
+default_addr_space_zero_address_valid (addr_space_t as ATTRIBUTE_UNUSED)
+{
+ return false;
+}
+
+/* The default hook for debugging the address space is to return the
+ address space number to indicate DW_AT_address_class. */
+int
+default_addr_space_debug (addr_space_t as)
+{
+ return as;
+}
+
/* The default hook for TARGET_ADDR_SPACE_CONVERT. This hook should never be
called for targets with only a generic address space. */
diff --git a/gcc/targhooks.h b/gcc/targhooks.h
index a8e7ebbd8ca..8747f958535 100644
--- a/gcc/targhooks.h
+++ b/gcc/targhooks.h
@@ -177,6 +177,8 @@ extern bool default_addr_space_legitimate_address_p (machine_mode, rtx,
extern rtx default_addr_space_legitimize_address (rtx, rtx, machine_mode,
addr_space_t);
extern bool default_addr_space_subset_p (addr_space_t, addr_space_t);
+extern bool default_addr_space_zero_address_valid (addr_space_t);
+extern int default_addr_space_debug (addr_space_t);
extern rtx default_addr_space_convert (rtx, tree, tree);
extern unsigned int default_case_values_threshold (void);
extern bool default_have_conditional_execution (void);
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index c074e7b55e0..bcca4791eeb 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,203 @@
+2015-11-09 Igor Zamyatin <igor.zamyatin@intel.com>
+
+ PR target/66326
+ * g++.dg/cilk-plus/CK/pr66326.cc: New test.
+
+2015-11-09 Richard Henderson <rth@redhat.com>
+
+ * gcc.target/i386/addr-space-1.c: New test.
+ * gcc.target/i386/addr-space-2.c: New test.
+ * gcc.target/i386/addr-space-3.c: New test.
+
+2015-11-08 Steven g. Kargl <kargl@gcc.gnu.org>
+
+ PR fortran/68053
+ * gfortran.dg/pr68053.f90: New test.
+
+2015-11-06 Jan Hubicka <hubicka@ucw.cz>
+
+ * g++.dg/lto/pr68057_0.C: Fix testcase.
+
+2015-11-08 Joost VandeVondele <vondele@gcc.gnu.org>
+
+ * gfortran.dg/PR67518.f90: move from here...
+ * gfortran.dg/graphite/PR67518.f90: to here.
+ * gfortran.dg/PR53852.f90: move from here...
+ * gfortran.dg/graphite/PR53852.f90: to here.
+
+2015-11-08 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gcc.dg/sso-1.c: New test.
+ * gcc.dg/sso-2.c: Likewise.
+ * gcc.dg/sso-3.c: Likewise.
+ * gcc.dg/sso-4.c: Likewise.
+ * gcc.dg/sso-5.c: Likewise.
+ * gcc.dg/sso-6.c: Likewise.
+ * gcc.dg/sso-7.c: Likewise.
+ * gcc.dg/sso-8.c: Likewise.
+ * gcc.dg/sso: New directory.
+ * gcc.target/i386/movbe-3.c: New test.
+ * gnat.dg/sso1.adb: Likewise.
+ * gnat.dg/sso2.ad[sb]: Likewise.
+ * gnat.dg/sso3.adb: Likewise.
+ * gnat.dg/sso4.adb: Likewise.
+ * gnat.dg/sso5.adb: Likewise.
+ * gnat.dg/sso6.adb: Likewise.
+ * gnat.dg/sso7.adb: Likewise.
+ * gnat.dg/specs/sso1.ads: Likewise.
+ * gnat.dg/specs/sso2.ads: Likewise.
+ * gnat.dg/sso: New directory.
+
+2015-11-08 Andre Vehreschild <vehre@gcc.gnu.org>
+
+ PR fortran/68218
+ * gfortran.dg/allocate_with_arrayspec_1.f90: New test.
+
+2015-11-08 Steven G. Kargl <kargl@gc.gnu.org>
+
+ PR fortran/68224
+ * gfortran.dg/pr68224.f90: New test.
+
+2015-11-08 Paul Thomas <pault@gcc.gnu.org>
+
+ PR fortran/68196
+ * gfortran.dg/proc_ptr_47.f90: New test.
+
+ PR fortran/66465
+ * gfortran.dg/pr66465.f90: New test.
+
+2015-11-07 John David Anglin <danglin@gcc.gnu.org>
+
+ * gcc.dg/Wno-frame-address.c: Skip on hppa*-*-*.
+
+2015-11-07 Steven G. Kargl <kargl@gcc.gnu.org>
+
+ PR fortran/68153
+ * gfortran.dg/pr68153.f90: New test.
+
+2015-11-07 Steven G. Kargl <kargl@gcc.gnu.org>
+
+ PR fortran/68151
+ * gfortran.dg/pr68151.f90: New test.
+
+2015-11-07 Richard Sandiford <richard.sandiford@arm.com>
+
+ PR tree-optimization/68235
+ * gcc.dg/lto/20110201-1_0.c: Add -fno-math-errno.
+
+2015-11-06 Jeff Law <law@redhat.com>
+
+ * gcc.dg/tree-ssa/ssa-dom-thread-7.c: Adjust to look for
+ realized jump threads.
+ * gcc.dg/tree-ssa-pr66752-3.c: Look in vrp1 dump for jump
+ threads rather than dom1 dump.
+
+2015-11-06 Michael Collison <michael.collison@linaro.org
+ Ramana Radhakrishnan <ramana.radhakrishnan@linaro.org>
+
+ Revert:
+ 2015-08-01 Michael Collison <michael.collison@linaro.org
+ Ramana Radhakrishnan <ramana.radhakrishnan@linaro.org>
+
+ * gcc.target/arm/mincmp.c: New test.
+
+2015-11-06 Dominique d'Humieres <dominiq@lps.ens.fr>
+
+ PR fortran/54224
+ * gfortran.dg/warn_unused_function_2.f90: Add two new
+ "defined but not used" subroutines.
+
+2015-11-06 Jakub Jelinek <jakub@redhat.com>
+
+ * gcc.dg/gomp/ordered-2.c (f1): Expect an extra error.
+ * g++.dg/gomp/ordered-2.C (f1): Likewise.
+ * gfortran.dg/goacc/parallel-kernels-regions.f95: Adjust
+ expected diagnostics for the addition of quotes.
+ * gfortran.dg/gomp/target3.f90: Likewise.
+ * c-c++-common/goacc/nesting-fail-1.c: Likewise.
+ * c-c++-common/goacc-gomp/nesting-fail-1.c: Likewise.
+ * c-c++-common/gomp/doacross-1.c: Likewise.
+ * c-c++-common/gomp/nesting-warn-1.c: Likewise.
+ * c-c++-common/gomp/cancel-1.c (f2): Add some new tests.
+ Adjust expected diagnostics wording.
+ * c-c++-common/gomp/clauses-4.c (foo): Likewise.
+ Don't expect error on ordered threads simd when in for simd.
+ * c-c++-common/gomp/nesting-2.c: New test.
+ * c-c++-common/gomp/ordered-3.c (foo): Add some new tests.
+ * c-c++-common/gomp/ordered-4.c: New test.
+
+2015-11-06 Mike Stump <mikestump@comcast.net>
+
+ * gcc.dg/pragma-diag-5.c: Make test cases unique.
+
+2015-11-06 Aditya Kumar <aditya.k7@samsung.com>
+ Sebastian Pop <s.pop@samsung.com>
+
+ * gcc.dg/graphite/fuse-1.c: New.
+ * gcc.dg/graphite/fuse-2.c: New.
+ * gcc.dg/graphite/interchange-13.c: Remove bogus check.
+
+2015-11-06 Christophe Lyon <christophe.lyon@linaro.org>
+
+ * gcc.target/aarch64/advsimd-intrinsics/vqtbX.c: New test.
+
+2015-11-06 David Malcolm <dmalcolm@redhat.com>
+
+ * gcc.dg/plugin/diagnostic-test-show-locus-bw.c: New file.
+ * gcc.dg/plugin/diagnostic-test-show-locus-color.c: New file.
+ * gcc.dg/plugin/diagnostic_plugin_test_show_locus.c: New file.
+ * gcc.dg/plugin/plugin.exp (plugin_test_list): Add the above.
+ * lib/gcc-dg.exp: Load multiline.exp.
+
+2015-11-06 Ramana Radhakrishnan <ramana.radhakrishnan@arm.com>
+
+ * gcc.target/arm/combine-movs.c: Adjust for unified asm.
+ * gcc.target/arm/interrupt-1.c: Likewise.
+ * gcc.target/arm/interrupt-2.c: Likewise.
+ * gcc.target/arm/unaligned-memcpy-4.c: Likewise.
+
+2015-11-06 Thomas Schwinge <thomas@codesourcery.com>
+
+ * gfortran.dg/goacc/combined_loop.f90: XFAIL.
+
+2015-11-06 Jan Hubicka <hubicka@ucw.cz>
+
+ PR ipa/68057
+ PR ipa/68220
+ * g++.dg/lto/pr68057_0.C: New testcase.
+ * g++.dg/lto/pr68057_1.C: New testcase.
+ * g++.dg/torture/pr68220.C: New testcase.
+
+2015-11-06 Christophe Lyon <christophe.lyon@linaro.org>
+
+ * gcc.target/aarch64/advsimd-intrinsics/vtbX.c: Fix typos in
+ comment.
+
+2015-11-06 Ilya Enkovich <enkovich.gnu@gmail.com>
+
+ PR tree-optimization/68145
+ * g++.dg/vect/pr68145.cc: New test.
+
+2015-11-06 Kyrylo Tkachov <kyrylo.tkachov@arm.com>
+
+ PR target/68088
+ * gcc.dg/pr68088_1.c: New test.
+
+2015-11-06 Richard Biener <rguenther@suse.de>
+
+ * gcc.dg/vect/bb-slp-38.c: New testcase.
+
+2015-11-06 Thomas Schwinge <thomas@codesourcery.com>
+
+ * gfortran.dg/goacc/private-3.f95: XFAIL.
+
+2015-11-06 Joost VandeVondele <vondele@gnu.gcc.org>
+
+ PR middle-end/53852
+ PR middle-end/67518
+ * gfortran.dg/PR67518.f90: New test.
+ * gfortran.dg/PR53852.f90: New test.
+
2015-11-05 Cesar Philippidis <cesar@codesourcery.com>
Tom de Vries <tom@codesourcery.com>
Nathan Sidwell <nathan@codesourcery.com>
diff --git a/gcc/testsuite/c-c++-common/goacc-gomp/nesting-fail-1.c b/gcc/testsuite/c-c++-common/goacc-gomp/nesting-fail-1.c
index e98258c3353..1a4472107c6 100644
--- a/gcc/testsuite/c-c++-common/goacc-gomp/nesting-fail-1.c
+++ b/gcc/testsuite/c-c++-common/goacc-gomp/nesting-fail-1.c
@@ -151,15 +151,15 @@ f_omp (void)
#pragma omp target
{
-#pragma acc parallel /* { dg-error "OpenACC parallel construct inside of OpenMP target region" } */
+#pragma acc parallel /* { dg-error "OpenACC .parallel. construct inside of OpenMP .target. region" } */
;
-#pragma acc kernels /* { dg-error "OpenACC kernels construct inside of OpenMP target region" } */
+#pragma acc kernels /* { dg-error "OpenACC .kernels. construct inside of OpenMP .target. region" } */
;
-#pragma acc data /* { dg-error "OpenACC data construct inside of OpenMP target region" } */
+#pragma acc data /* { dg-error "OpenACC .data. construct inside of OpenMP .target. region" } */
;
-#pragma acc update host(i) /* { dg-error "OpenACC update construct inside of OpenMP target region" } */
-#pragma acc enter data copyin(i) /* { dg-error "OpenACC enter/exit data construct inside of OpenMP target region" } */
-#pragma acc exit data delete(i) /* { dg-error "OpenACC enter/exit data construct inside of OpenMP target region" } */
+#pragma acc update host(i) /* { dg-error "OpenACC .update. construct inside of OpenMP .target. region" } */
+#pragma acc enter data copyin(i) /* { dg-error "OpenACC .enter/exit data. construct inside of OpenMP .target. region" } */
+#pragma acc exit data delete(i) /* { dg-error "OpenACC .enter/exit data. construct inside of OpenMP .target. region" } */
#pragma acc loop /* { dg-error "loop directive must be associated with an OpenACC compute region" } */
for (i = 0; i < 2; ++i)
;
diff --git a/gcc/testsuite/c-c++-common/goacc/nesting-fail-1.c b/gcc/testsuite/c-c++-common/goacc/nesting-fail-1.c
index 8af1c8244f0..7a36074ae38 100644
--- a/gcc/testsuite/c-c++-common/goacc/nesting-fail-1.c
+++ b/gcc/testsuite/c-c++-common/goacc/nesting-fail-1.c
@@ -7,15 +7,15 @@ f_acc_parallel (void)
{
#pragma acc parallel
{
-#pragma acc parallel /* { dg-bogus "parallel construct inside of parallel region" "not implemented" { xfail *-*-* } } */
+#pragma acc parallel /* { dg-bogus ".parallel. construct inside of .parallel. region" "not implemented" { xfail *-*-* } } */
;
-#pragma acc kernels /* { dg-bogus "kernels construct inside of parallel region" "not implemented" { xfail *-*-* } } */
+#pragma acc kernels /* { dg-bogus ".kernels. construct inside of .parallel. region" "not implemented" { xfail *-*-* } } */
;
-#pragma acc data /* { dg-error "data construct inside of parallel region" } */
+#pragma acc data /* { dg-error ".data. construct inside of .parallel. region" } */
;
-#pragma acc update host(i) /* { dg-error "update construct inside of parallel region" } */
-#pragma acc enter data copyin(i) /* { dg-error "enter/exit data construct inside of parallel region" } */
-#pragma acc exit data delete(i) /* { dg-error "enter/exit data construct inside of parallel region" } */
+#pragma acc update host(i) /* { dg-error ".update. construct inside of .parallel. region" } */
+#pragma acc enter data copyin(i) /* { dg-error ".enter/exit data. construct inside of .parallel. region" } */
+#pragma acc exit data delete(i) /* { dg-error ".enter/exit data. construct inside of .parallel. region" } */
}
}
@@ -26,14 +26,14 @@ f_acc_kernels (void)
{
#pragma acc kernels
{
-#pragma acc parallel /* { dg-bogus "parallel construct inside of kernels region" "not implemented" { xfail *-*-* } } */
+#pragma acc parallel /* { dg-bogus ".parallel. construct inside of .kernels. region" "not implemented" { xfail *-*-* } } */
;
-#pragma acc kernels /* { dg-bogus "kernels construct inside of kernels region" "not implemented" { xfail *-*-* } } */
+#pragma acc kernels /* { dg-bogus ".kernels. construct inside of .kernels. region" "not implemented" { xfail *-*-* } } */
;
-#pragma acc data /* { dg-error "data construct inside of kernels region" } */
+#pragma acc data /* { dg-error ".data. construct inside of .kernels. region" } */
;
-#pragma acc update host(i) /* { dg-error "update construct inside of kernels region" } */
-#pragma acc enter data copyin(i) /* { dg-error "enter/exit data construct inside of kernels region" } */
-#pragma acc exit data delete(i) /* { dg-error "enter/exit data construct inside of kernels region" } */
+#pragma acc update host(i) /* { dg-error ".update. construct inside of .kernels. region" } */
+#pragma acc enter data copyin(i) /* { dg-error ".enter/exit data. construct inside of .kernels. region" } */
+#pragma acc exit data delete(i) /* { dg-error ".enter/exit data. construct inside of .kernels. region" } */
}
}
diff --git a/gcc/testsuite/c-c++-common/gomp/cancel-1.c b/gcc/testsuite/c-c++-common/gomp/cancel-1.c
index 13de881d049..896a76858bd 100644
--- a/gcc/testsuite/c-c++-common/gomp/cancel-1.c
+++ b/gcc/testsuite/c-c++-common/gomp/cancel-1.c
@@ -77,12 +77,73 @@ f2 (void)
#pragma omp cancel parallel /* { dg-error "not closely nested inside" } */
#pragma omp cancel for /* { dg-error "not closely nested inside" } */
#pragma omp cancel sections /* { dg-error "not closely nested inside" } */
+ #pragma omp cancel taskgroup /* { dg-error "construct not closely nested inside of .taskgroup. region" } */
+ #pragma omp cancellation point parallel /* { dg-error "not closely nested inside" } */
+ #pragma omp cancellation point for /* { dg-error "not closely nested inside" } */
+ #pragma omp cancellation point sections /* { dg-error "not closely nested inside" } */
+ #pragma omp cancellation point taskgroup /* { dg-error "construct not closely nested inside of .taskgroup. region" } */
+ }
+ #pragma omp taskgroup
+ #pragma omp task
+ {
+ #pragma omp cancel parallel /* { dg-error "not closely nested inside" } */
+ #pragma omp cancel for /* { dg-error "not closely nested inside" } */
+ #pragma omp cancel sections /* { dg-error "not closely nested inside" } */
#pragma omp cancel taskgroup
#pragma omp cancellation point parallel /* { dg-error "not closely nested inside" } */
#pragma omp cancellation point for /* { dg-error "not closely nested inside" } */
#pragma omp cancellation point sections /* { dg-error "not closely nested inside" } */
#pragma omp cancellation point taskgroup
}
+ #pragma omp taskgroup
+ {
+ #pragma omp task
+ {
+ #pragma omp task
+ {
+ #pragma omp cancellation point taskgroup
+ #pragma omp cancel taskgroup
+ }
+ }
+ }
+ #pragma omp taskgroup
+ {
+ #pragma omp parallel
+ {
+ #pragma omp task
+ {
+ #pragma omp cancel taskgroup /* { dg-error "construct not closely nested inside of .taskgroup. region" } */
+ #pragma omp cancellation point taskgroup /* { dg-error "construct not closely nested inside of .taskgroup. region" } */
+ }
+ }
+ #pragma omp target
+ {
+ #pragma omp task
+ {
+ #pragma omp cancel taskgroup /* { dg-error "construct not closely nested inside of .taskgroup. region" } */
+ #pragma omp cancellation point taskgroup /* { dg-error "construct not closely nested inside of .taskgroup. region" } */
+ }
+ }
+ #pragma omp target
+ #pragma omp teams
+ #pragma omp distribute
+ for (i = 0; i < 10; i++)
+ {
+ #pragma omp task
+ {
+ #pragma omp cancel taskgroup /* { dg-error "construct not closely nested inside of .taskgroup. region" } */
+ #pragma omp cancellation point taskgroup /* { dg-error "construct not closely nested inside of .taskgroup. region" } */
+ }
+ }
+ #pragma omp target data map(i)
+ {
+ #pragma omp task
+ {
+ #pragma omp cancel taskgroup
+ #pragma omp cancellation point taskgroup
+ }
+ }
+ }
#pragma omp for
for (i = 0; i < 10; i++)
{
@@ -179,14 +240,14 @@ f2 (void)
}
#pragma omp target teams
{
- #pragma omp cancel parallel /* { dg-error "only distribute or parallel constructs are allowed to be closely nested" } */
- #pragma omp cancel for /* { dg-error "only distribute or parallel constructs are allowed to be closely nested" } */
- #pragma omp cancel sections /* { dg-error "only distribute or parallel constructs are allowed to be closely nested" } */
- #pragma omp cancel taskgroup /* { dg-error "only distribute or parallel constructs are allowed to be closely nested" } */
- #pragma omp cancellation point parallel /* { dg-error "only distribute or parallel constructs are allowed to be closely nested" } */
- #pragma omp cancellation point for /* { dg-error "only distribute or parallel constructs are allowed to be closely nested" } */
- #pragma omp cancellation point sections /* { dg-error "only distribute or parallel constructs are allowed to be closely nested" } */
- #pragma omp cancellation point taskgroup /* { dg-error "only distribute or parallel constructs are allowed to be closely nested" } */
+ #pragma omp cancel parallel /* { dg-error "only .distribute. or .parallel. regions are allowed to be strictly nested" } */
+ #pragma omp cancel for /* { dg-error "only .distribute. or .parallel. regions are allowed to be strictly nested" } */
+ #pragma omp cancel sections /* { dg-error "only .distribute. or .parallel. regions are allowed to be strictly nested" } */
+ #pragma omp cancel taskgroup /* { dg-error "only .distribute. or .parallel. regions are allowed to be strictly nested" } */
+ #pragma omp cancellation point parallel /* { dg-error "only .distribute. or .parallel. regions are allowed to be strictly nested" } */
+ #pragma omp cancellation point for /* { dg-error "only .distribute. or .parallel. regions are allowed to be strictly nested" } */
+ #pragma omp cancellation point sections /* { dg-error "only .distribute. or .parallel. regions are allowed to be strictly nested" } */
+ #pragma omp cancellation point taskgroup /* { dg-error "only .distribute. or .parallel. regions are allowed to be strictly nested" } */
}
#pragma omp target teams distribute
for (i = 0; i < 10; i++)
diff --git a/gcc/testsuite/c-c++-common/gomp/clauses-4.c b/gcc/testsuite/c-c++-common/gomp/clauses-4.c
index 104b129a9aa..11e7634e14b 100644
--- a/gcc/testsuite/c-c++-common/gomp/clauses-4.c
+++ b/gcc/testsuite/c-c++-common/gomp/clauses-4.c
@@ -57,40 +57,62 @@ foo (int y, short z)
#pragma omp distribute parallel for ordered /* { dg-error ".ordered. is not valid for .#pragma omp distribute parallel for." } */
for (x = 0; x < 64; x++)
{
- #pragma omp ordered /* { dg-error "ordered region must be closely nested inside a loop region with an ordered clause" } */
+ #pragma omp ordered /* { dg-error ".ordered. region must be closely nested inside a loop region with an .ordered. clause" } */
;
}
#pragma omp target teams
#pragma omp distribute parallel for simd ordered /* { dg-error ".ordered. is not valid for .#pragma omp distribute parallel for simd." } */
for (x = 0; x < 64; x++)
{
- #pragma omp ordered simd, threads /* { dg-error "OpenMP constructs other than .#pragma omp ordered simd. may not be nested inside simd region" } */
+ #pragma omp ordered simd, threads
;
}
#pragma omp target
#pragma omp teams distribute parallel for ordered /* { dg-error ".ordered. is not valid for .#pragma omp teams distribute parallel for." } */
for (x = 0; x < 64; x++)
{
- #pragma omp ordered /* { dg-error "ordered region must be closely nested inside a loop region with an ordered clause" } */
+ #pragma omp ordered /* { dg-error ".ordered. region must be closely nested inside a loop region with an .ordered. clause" } */
;
}
#pragma omp target
#pragma omp teams distribute parallel for simd ordered /* { dg-error ".ordered. is not valid for .#pragma omp teams distribute parallel for simd." } */
for (x = 0; x < 64; x++)
{
- #pragma omp ordered simd, threads /* { dg-error "OpenMP constructs other than .#pragma omp ordered simd. may not be nested inside simd region" } */
+ #pragma omp ordered simd, threads
;
}
#pragma omp target teams distribute parallel for ordered /* { dg-error ".ordered. is not valid for .#pragma omp target teams distribute parallel for." } */
for (x = 0; x < 64; x++)
{
- #pragma omp ordered /* { dg-error "ordered region must be closely nested inside a loop region with an ordered clause" } */
+ #pragma omp ordered /* { dg-error ".ordered. region must be closely nested inside a loop region with an .ordered. clause" } */
;
}
#pragma omp target teams distribute parallel for simd ordered /* { dg-error ".ordered. is not valid for .#pragma omp target teams distribute parallel for simd." } */
for (x = 0; x < 64; x++)
{
- #pragma omp ordered simd, threads /* { dg-error "OpenMP constructs other than .#pragma omp ordered simd. may not be nested inside simd region" } */
+ #pragma omp ordered simd, threads
+ ;
+ }
+ #pragma omp simd
+ for (x = 0; x < 64; x++)
+ {
+ #pragma omp ordered threads simd /* { dg-error ".ordered simd threads. must be closely nested inside of .for simd. region" } */
+ ;
+ }
+ #pragma omp for
+ for (x = 0; x < 64; x++)
+ {
+ #pragma omp simd
+ for (y = 0; y < 16; y++)
+ {
+ #pragma omp ordered simd threads /* { dg-error ".ordered simd threads. must be closely nested inside of .for simd. region" } */
+ ;
+ }
+ }
+ #pragma omp for simd
+ for (x = 0; x < 64; x++)
+ {
+ #pragma omp ordered threads simd
;
}
}
diff --git a/gcc/testsuite/c-c++-common/gomp/doacross-1.c b/gcc/testsuite/c-c++-common/gomp/doacross-1.c
index 89c3dd3c7c6..6244ca08d2c 100644
--- a/gcc/testsuite/c-c++-common/gomp/doacross-1.c
+++ b/gcc/testsuite/c-c++-common/gomp/doacross-1.c
@@ -32,8 +32,8 @@ foo (void)
#pragma omp ordered depend (sink: i - 1, j - 2) /* { dg-error "does not match number" } */
#pragma omp ordered depend (source)
}
- #pragma omp ordered depend (sink: j) /* { dg-error "clause must be closely nested inside an ordered loop" } */
- #pragma omp ordered depend (source) /* { dg-error "clause must be closely nested inside an ordered loop" } */
+ #pragma omp ordered depend (sink: j) /* { dg-error "clause must be closely nested inside an .ordered. loop" } */
+ #pragma omp ordered depend (source) /* { dg-error "clause must be closely nested inside an .ordered. loop" } */
#pragma omp for ordered (1)
for (i = 0; i < 64; i++)
{
diff --git a/gcc/testsuite/c-c++-common/gomp/nesting-2.c b/gcc/testsuite/c-c++-common/gomp/nesting-2.c
new file mode 100644
index 00000000000..7a03430311d
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/gomp/nesting-2.c
@@ -0,0 +1,154 @@
+void
+foo (void)
+{
+ int i;
+ #pragma omp taskloop
+ for (i = 0; i < 64; i++)
+ {
+ int j;
+ #pragma omp for /* { dg-error "region may not be closely nested inside of" } */
+ for (j = 0; j < 10; j++)
+ ;
+ #pragma omp single /* { dg-error "region may not be closely nested inside of" } */
+ ;
+ #pragma omp sections /* { dg-error "region may not be closely nested inside of" } */
+ {
+ #pragma omp section
+ ;
+ }
+ #pragma omp barrier /* { dg-error "region may not be closely nested inside of" } */
+ #pragma omp master /* { dg-error "region may not be closely nested inside of" } */
+ ;
+ #pragma omp ordered /* { dg-error "region may not be closely nested inside of" } */
+ ;
+ #pragma omp ordered threads /* { dg-error "region may not be closely nested inside of" } */
+ ;
+ #pragma omp ordered simd threads /* { dg-error ".ordered. .simd. must be closely nested inside .simd. region" } */
+ ;
+ #pragma omp simd
+ for (j = 0; j < 10; j++)
+ #pragma omp ordered simd
+ ;
+ #pragma omp critical
+ {
+ #pragma omp simd
+ for (j = 0; j < 10; j++)
+ #pragma omp ordered simd
+ ;
+ }
+ }
+ #pragma omp taskloop
+ for (i = 0; i < 64; i++)
+ #pragma omp parallel
+ {
+ int j;
+ #pragma omp for
+ for (j = 0; j < 10; j++)
+ ;
+ #pragma omp single
+ ;
+ #pragma omp sections
+ {
+ #pragma omp section
+ ;
+ }
+ #pragma omp barrier
+ #pragma omp master
+ ;
+ #pragma omp ordered /* { dg-error ".ordered. region must be closely nested inside a loop region with an .ordered. clause" } */
+ ;
+ #pragma omp ordered threads /* { dg-error ".ordered. region must be closely nested inside a loop region with an .ordered. clause" } */
+ ;
+ #pragma omp simd
+ for (j = 0; j < 10; j++)
+ #pragma omp ordered simd
+ ;
+ #pragma omp critical
+ {
+ #pragma omp simd
+ for (j = 0; j < 10; j++)
+ #pragma omp ordered simd
+ ;
+ }
+ }
+ #pragma omp taskloop
+ for (i = 0; i < 64; i++)
+ #pragma omp target
+ {
+ int j;
+ #pragma omp for
+ for (j = 0; j < 10; j++)
+ ;
+ #pragma omp single
+ ;
+ #pragma omp sections
+ {
+ #pragma omp section
+ ;
+ }
+ #pragma omp barrier
+ #pragma omp master
+ ;
+ #pragma omp ordered /* { dg-error ".ordered. region must be closely nested inside a loop region with an .ordered. clause" } */
+ ;
+ #pragma omp ordered threads /* { dg-error ".ordered. region must be closely nested inside a loop region with an .ordered. clause" } */
+ ;
+ #pragma omp simd
+ for (j = 0; j < 10; j++)
+ #pragma omp ordered simd
+ ;
+ #pragma omp critical
+ {
+ #pragma omp simd
+ for (j = 0; j < 10; j++)
+ #pragma omp ordered simd
+ ;
+ }
+ }
+ #pragma omp ordered
+ {
+ #pragma omp ordered /* { dg-error "region may not be closely nested inside of" } */
+ ;
+ }
+ #pragma omp ordered threads
+ {
+ #pragma omp ordered /* { dg-error "region may not be closely nested inside of" } */
+ ;
+ }
+ #pragma omp ordered
+ {
+ #pragma omp ordered threads /* { dg-error "region may not be closely nested inside of" } */
+ ;
+ }
+ #pragma omp ordered threads
+ {
+ #pragma omp ordered threads /* { dg-error "region may not be closely nested inside of" } */
+ ;
+ }
+ #pragma omp critical
+ {
+ #pragma omp ordered simd /* { dg-error ".ordered. .simd. must be closely nested inside .simd. region" } */
+ ;
+ }
+ #pragma omp for ordered
+ for (i = 0; i < 64; i++)
+ #pragma omp parallel
+ {
+ #pragma omp ordered threads /* { dg-error ".ordered. region must be closely nested inside a loop region with an .ordered. clause" } */
+ ;
+ }
+ #pragma omp for ordered
+ for (i = 0; i < 64; i++)
+ #pragma omp parallel
+ {
+ #pragma omp ordered /* { dg-error ".ordered. region must be closely nested inside a loop region with an .ordered. clause" } */
+ ;
+ }
+ #pragma omp for ordered(1)
+ for (i = 0; i < 64; i++)
+ #pragma omp parallel
+ {
+ #pragma omp ordered depend(source) /* { dg-error ".ordered. construct with .depend. clause must be closely nested inside a loop with .ordered. clause with a parameter" } */
+ #pragma omp ordered depend(sink: i - 1) /* { dg-error ".ordered. construct with .depend. clause must be closely nested inside a loop with .ordered. clause with a parameter" } */
+ }
+}
diff --git a/gcc/testsuite/c-c++-common/gomp/nesting-warn-1.c b/gcc/testsuite/c-c++-common/gomp/nesting-warn-1.c
index 92ced709907..800ad532108 100644
--- a/gcc/testsuite/c-c++-common/gomp/nesting-warn-1.c
+++ b/gcc/testsuite/c-c++-common/gomp/nesting-warn-1.c
@@ -5,19 +5,19 @@ f_omp_target (void)
{
#pragma omp target
{
-#pragma omp target /* { dg-warning "target construct inside of target region" } */
+#pragma omp target /* { dg-warning ".target. construct inside of .target. region" } */
;
-#pragma omp target data map(i) /* { dg-warning "target data construct inside of target region" } */
+#pragma omp target data map(i) /* { dg-warning ".target data. construct inside of .target. region" } */
;
-#pragma omp target update to(i) /* { dg-warning "target update construct inside of target region" } */
+#pragma omp target update to(i) /* { dg-warning ".target update. construct inside of .target. region" } */
#pragma omp parallel
{
-#pragma omp target /* { dg-warning "target construct inside of target region" } */
+#pragma omp target /* { dg-warning ".target. construct inside of .target. region" } */
;
-#pragma omp target data map(i) /* { dg-warning "target data construct inside of target region" } */
+#pragma omp target data map(i) /* { dg-warning ".target data. construct inside of .target. region" } */
;
-#pragma omp target update to(i) /* { dg-warning "target update construct inside of target region" } */
+#pragma omp target update to(i) /* { dg-warning ".target update. construct inside of .target. region" } */
}
}
}
diff --git a/gcc/testsuite/c-c++-common/gomp/ordered-3.c b/gcc/testsuite/c-c++-common/gomp/ordered-3.c
index 1d7ff80f743..3c107232c0d 100644
--- a/gcc/testsuite/c-c++-common/gomp/ordered-3.c
+++ b/gcc/testsuite/c-c++-common/gomp/ordered-3.c
@@ -59,6 +59,18 @@ foo (void)
#pragma omp ordered depend(sink: i - 1) /* { dg-error "clause must be closely nested inside a loop with .ordered. clause with a parameter" } */
#pragma omp ordered depend(source) /* { dg-error "clause must be closely nested inside a loop with .ordered. clause with a parameter" } */
}
+ #pragma omp parallel for ordered
+ for (i = 0; i < 64; i++)
+ {
+ #pragma omp ordered depend(sink: i - 1) /* { dg-error "clause must be closely nested inside a loop with .ordered. clause with a parameter" } */
+ #pragma omp ordered depend(source) /* { dg-error "clause must be closely nested inside a loop with .ordered. clause with a parameter" } */
+ }
+ #pragma omp parallel for
+ for (i = 0; i < 64; i++)
+ {
+ #pragma omp ordered depend(sink: i - 1) /* { dg-error "clause must be closely nested inside a loop with .ordered. clause with a parameter" } */
+ #pragma omp ordered depend(source) /* { dg-error "clause must be closely nested inside a loop with .ordered. clause with a parameter" } */
+ }
}
void
diff --git a/gcc/testsuite/c-c++-common/gomp/ordered-4.c b/gcc/testsuite/c-c++-common/gomp/ordered-4.c
new file mode 100644
index 00000000000..b56843c0bb1
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/gomp/ordered-4.c
@@ -0,0 +1,54 @@
+void
+f1 (void)
+{
+ int i, j;
+ #pragma omp critical
+ {
+ #pragma omp simd
+ for (i = 0; i < 64; i++)
+ {
+ #pragma omp ordered simd
+ ;
+ }
+ }
+ #pragma omp ordered threads
+ {
+ #pragma omp simd
+ for (i = 0; i < 64; i++)
+ {
+ #pragma omp ordered simd
+ ;
+ }
+ }
+ #pragma omp task
+ {
+ #pragma omp simd
+ for (i = 0; i < 64; i++)
+ {
+ #pragma omp ordered simd
+ ;
+ }
+ }
+ #pragma omp taskloop
+ for (j = 0; j < 64; j++)
+ #pragma omp simd
+ for (i = 0; i < 64; i++)
+ {
+ #pragma omp ordered simd
+ ;
+ }
+}
+
+void
+f2 (void)
+{
+ #pragma omp ordered simd
+ ;
+}
+
+void
+f3 (void)
+{
+ #pragma omp ordered threads , simd
+ ;
+}
diff --git a/gcc/testsuite/g++.dg/cilk-plus/CK/pr66326.cc b/gcc/testsuite/g++.dg/cilk-plus/CK/pr66326.cc
new file mode 100644
index 00000000000..1114ebdda82
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cilk-plus/CK/pr66326.cc
@@ -0,0 +1,33 @@
+/* { dg-options "-fcilkplus" } */
+/* { dg-do run { target i?86-*-* x86_64-*-* } } */
+/* { dg-options "-fcilkplus -lcilkrts" { target { i?86-*-* x86_64-*-* } } } */
+
+#include <cilk/cilk.h>
+#include <vector>
+#include <random>
+
+template <class T>
+void do_not_optimize_away(T&& x) {
+ asm volatile("" : "+r"(x));
+}
+
+const int N = 1'000'000;
+
+auto compute() {
+ std::vector<double> v(N);
+ auto rng = std::mt19937{std::random_device{}()};
+ std::uniform_real_distribution<double> dist(0, 1);
+ for (int i = 0; i < N; ++i) v[i] = std::log(std::sqrt(dist(rng)));
+ return v;
+}
+
+int main() {
+ std::vector<double> v1, v2, v3;
+ cilk_spawn [&] { v1 = compute(); }();
+ cilk_spawn [&] { v2 = compute(); }();
+ v3 = compute();
+ do_not_optimize_away(v1.data());
+ do_not_optimize_away(v2.data());
+ do_not_optimize_away(v3.data());
+ return 0;
+}
diff --git a/gcc/testsuite/g++.dg/concepts/generic-fn-err.C b/gcc/testsuite/g++.dg/concepts/generic-fn-err.C
index c6b74571954..1e975108257 100644
--- a/gcc/testsuite/g++.dg/concepts/generic-fn-err.C
+++ b/gcc/testsuite/g++.dg/concepts/generic-fn-err.C
@@ -11,8 +11,8 @@ template<template<typename> class X>
struct S { };
-void f1(Int) { } // { dg-error "invalid" }
-void f2(Template) { } // { dg-error "invalid" }
+void f1(Int) { } // { dg-error "" }
+void f2(Template) { } // { dg-error "" }
struct S1 {
void f1(auto x) { }
diff --git a/gcc/testsuite/g++.dg/concepts/placeholder6.C b/gcc/testsuite/g++.dg/concepts/placeholder6.C
new file mode 100644
index 00000000000..7f2e67a9192
--- /dev/null
+++ b/gcc/testsuite/g++.dg/concepts/placeholder6.C
@@ -0,0 +1,10 @@
+// { dg-options -std=c++1z }
+
+template <int I> struct B { static const int i = I; };
+template <int I> concept bool Few = I < 10;
+
+constexpr int g(B<Few> b) { return b.i; }
+
+#define SA(X) static_assert((X),#X)
+SA(g(B<2>{}) == 2);
+SA(g(B<10>{}) == 10); // { dg-error "" }
diff --git a/gcc/testsuite/g++.dg/gomp/ordered-2.C b/gcc/testsuite/g++.dg/gomp/ordered-2.C
index 6c2b4329c64..7ec6333527a 100644
--- a/gcc/testsuite/g++.dg/gomp/ordered-2.C
+++ b/gcc/testsuite/g++.dg/gomp/ordered-2.C
@@ -3,5 +3,5 @@
void f1(void)
{
#pragma omp ordered asdf /* { dg-error "expected" } */
- #pragma omp ordered
+ #pragma omp ordered /* { dg-error "region may not be closely nested inside of" } */
} /* { dg-error "expected" } */
diff --git a/gcc/testsuite/g++.dg/lto/pr68057_0.C b/gcc/testsuite/g++.dg/lto/pr68057_0.C
new file mode 100644
index 00000000000..4e124d7f5e8
--- /dev/null
+++ b/gcc/testsuite/g++.dg/lto/pr68057_0.C
@@ -0,0 +1,23 @@
+// { dg-lto-do link }
+/* { dg-extra-ld-options { -O2 -Wno-odr -r -nostdlib } } */
+struct SPxPricer;
+struct SoPlex {
+ virtual void setPricer(SPxPricer *);
+};
+struct SPxPricer {
+ virtual void load(SoPlex *);
+};
+struct SLUFactor {
+ SLUFactor();
+ virtual ~SLUFactor();
+};
+struct SPxSolver : SoPlex {
+ SPxPricer pr;
+ SLUFactor slu;
+ SPxSolver();
+};
+struct A : SPxSolver {};
+A a;
+
+void SoPlex::setPricer(SPxPricer *p1) { p1->load(this); }
+
diff --git a/gcc/testsuite/g++.dg/lto/pr68057_1.C b/gcc/testsuite/g++.dg/lto/pr68057_1.C
new file mode 100644
index 00000000000..f45a81ec88b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/lto/pr68057_1.C
@@ -0,0 +1,17 @@
+struct SPxPricer;
+struct SoPlex {
+ virtual void setPricer(SPxPricer *);
+};
+struct SPxPricer {
+ virtual void load(SoPlex *);
+};
+struct SLUFactor {
+ SLUFactor();
+ virtual ~SLUFactor();
+};
+struct SPxSolver : SoPlex {
+ SPxPricer pr;
+ SLUFactor slu;
+ SPxSolver();
+};
+SPxSolver::SPxSolver() { setPricer(&pr); }
diff --git a/gcc/testsuite/g++.dg/torture/pr68220.C b/gcc/testsuite/g++.dg/torture/pr68220.C
new file mode 100644
index 00000000000..3b27653219c
--- /dev/null
+++ b/gcc/testsuite/g++.dg/torture/pr68220.C
@@ -0,0 +1,238 @@
+// { dg-do compile }
+namespace mpl {
+template <typename, typename = int> struct lambda;
+template <typename T3> struct if_ { typedef T3 type; };
+template <int> struct arg {
+ template <typename U1, typename> struct apply { typedef U1 type; };
+};
+template <typename> struct begin_impl;
+template <typename Sequence> struct begin {
+ typedef typename Sequence::tag tag_;
+ typedef typename begin_impl<tag_>::template apply<Sequence>::type type;
+};
+template <typename> struct O1_size_impl;
+}
+template <long N> struct long_ { static const long value = N; };
+namespace mpl {
+template <typename Sequence>
+struct O1_size
+ : O1_size_impl<typename Sequence::tag>::template apply<Sequence> {};
+typedef arg<1> _1;
+template <typename T> struct protect : T {};
+template <typename F> struct apply_wrap1 : F::template apply<int> {};
+template <typename F, typename T1, typename T2>
+struct apply_wrap2 : F::template apply<T1, T2> {};
+template <typename F> struct apply_wrap5 : F::template apply<int> {};
+template <typename, typename, typename, typename, typename, typename>
+struct resolve_bind_arg;
+template <typename T, typename> struct replace_unnamed_arg { typedef T type; };
+template <typename F, typename> struct bind1 {
+ template <typename> struct apply {
+ typedef typename apply_wrap1<F>::type type;
+ };
+};
+template <typename F, typename T1, typename U1, typename U2, typename U3,
+ typename U4, typename U5>
+struct resolve_bind_arg<bind1<F, T1>, U1, U2, U3, U4, U5> {
+ typedef typename apply_wrap5<bind1<F, T1>>::type type;
+};
+template <typename F, typename, typename T2> struct bind2 {
+ template <typename U1, typename U2> struct apply {
+ typedef resolve_bind_arg<typename replace_unnamed_arg<T2, arg<1>>::type, U1,
+ U2, int, int, int> t2;
+ typedef typename apply_wrap2<F, typename U1::type, typename t2::type>::type
+ type;
+ };
+};
+template <typename T> struct quote_impl { typedef T type; };
+template <template <typename> class F> struct quote1 {
+ template <typename> struct apply : quote_impl<F<int>> {};
+};
+template <typename T, typename> struct lambda {
+ typedef T type;
+ typedef arg<1> result_;
+};
+template <typename, template <typename> class, typename> struct le_result1;
+template <template <typename> class F, typename L1>
+struct le_result1<int, F, L1> {
+ typedef protect<bind1<quote1<F>, typename L1::result_>> type;
+};
+template <template <typename> class F, typename T1, typename Tag>
+struct lambda<F<T1>, Tag> {
+ typedef typename le_result1<int, F, lambda<T1>>::type type;
+};
+template <int, typename, typename, typename> struct iter_fold_impl;
+template <typename First, typename State, typename ForwardOp>
+struct iter_fold_impl<1, First, State, ForwardOp> {
+ typedef typename apply_wrap2<ForwardOp, State, First>::type state;
+};
+template <typename Sequence, typename State, typename ForwardOp>
+struct iter_fold {
+ typedef typename iter_fold_impl<O1_size<Sequence>::value,
+ typename begin<Sequence>::type, State,
+ ForwardOp>::state type;
+};
+template <typename> struct deref;
+template <typename> struct push_front_impl;
+template <typename T> struct l_item {
+ typedef int tag;
+ typedef l_item type;
+ typedef long_<1> size;
+ typedef T item;
+};
+struct l_end {
+ typedef int tag;
+ typedef l_end type;
+};
+template <> struct push_front_impl<int> {
+ template <typename, typename T> struct apply { typedef l_item<T> type; };
+};
+template <> struct O1_size_impl<int> {
+ template <typename> struct apply : l_item<int>::size {};
+};
+template <typename> struct l_iter;
+template <typename Node> struct deref<l_iter<Node>> {
+ typedef typename Node::item type;
+};
+template <> struct begin_impl<int> {
+ template <typename List> struct apply {
+ typedef l_iter<typename List::type> type;
+ };
+};
+template <typename> struct list : l_item<int> {};
+}
+template <typename T> T &cast_storage(void *storage) {
+ return *static_cast<T *>(storage);
+}
+struct symbol;
+struct visitation_impl_step {
+ typedef symbol type;
+};
+template <typename Visitor, typename VoidPtrCV, typename T>
+void visitation_impl_invoke_impl(int, Visitor visitor, VoidPtrCV storage, T *) {
+ visitor.internal_visit(cast_storage<T>(storage), 1);
+}
+int visitation_impl_invoke_internal_which, visitation_impl_logical_which;
+template <typename Visitor, typename VoidPtrCV, typename T,
+ typename NoBackupFlag>
+void visitation_impl_invoke(Visitor visitor, VoidPtrCV storage, T t,
+ NoBackupFlag, int) {
+ visitation_impl_invoke_impl(visitation_impl_invoke_internal_which, visitor,
+ storage, t);
+}
+template <typename Which, typename step0, typename Visitor, typename VoidPtrCV,
+ typename NoBackupFlag>
+void visitation_impl(int, Visitor visitor, VoidPtrCV storage, int,
+ NoBackupFlag no_backup_flag, Which, step0 *) {
+ switch (visitation_impl_logical_which)
+ case 0:
+ visitation_impl_invoke(visitor, storage,
+ static_cast<typename step0::type *>(0), no_backup_flag,
+ 1);
+}
+template <long N> struct size_t { static const long value = N; };
+struct aligned_storage_imp {};
+template <long> class aligned_storage : aligned_storage_imp {
+public:
+ void *address() { return static_cast<aligned_storage_imp *>(this); }
+};
+namespace mpl {
+template <typename> struct less;
+template <typename> struct select_max {
+ template <typename OldIterator, typename> struct apply {
+ typedef OldIterator type;
+ };
+};
+template <typename Sequence, typename Predicate = less<arg<11>>>
+struct max_element : iter_fold<Sequence, typename begin<Sequence>::type,
+ protect<select_max<Predicate>>> {};
+template <typename Sequence = int, typename T = int>
+struct push_front
+ : push_front_impl<typename Sequence::tag>::template apply<Sequence, T> {};
+template <> struct push_front<> {
+ template <typename T1, typename T2> struct apply : push_front<T1, T2> {};
+};
+template <typename> struct sizeof_ : size_t<sizeof(int)> {};
+template <long, typename, typename, typename, typename>
+struct reverse_fold_impl;
+template <typename First, typename State, typename BackwardOp,
+ typename ForwardOp>
+struct reverse_fold_impl<1, First, State, BackwardOp, ForwardOp> {
+ typedef First iter0;
+ typedef typename apply_wrap2<
+ BackwardOp,
+ typename apply_wrap2<ForwardOp, State, typename deref<iter0>::type>::type,
+ typename deref<iter0>::type>::type state;
+};
+template <typename Sequence, typename State, typename BackwardOp,
+ typename ForwardOp = arg<1>>
+struct reverse_fold {
+ typedef typename reverse_fold_impl<O1_size<Sequence>::value,
+ typename begin<Sequence>::type, State,
+ BackwardOp, ForwardOp>::state type;
+};
+template <typename> struct inserter {
+ typedef mpl::l_end state;
+ typedef mpl::push_front<> operation;
+};
+template <typename Seq, typename Op, typename In>
+struct reverse_transform1_impl
+ : reverse_fold<Seq, typename In::state,
+ bind2<typename lambda<typename In::operation>::type, _1,
+ bind1<typename lambda<Op>::type, arg<2>>>> {};
+template <typename P1, typename P2>
+struct transform1
+ : if_<reverse_transform1_impl<P1, P2, inserter<push_front<>>>>::type {};
+}
+template <typename, typename> struct max_value {
+ typedef mpl::transform1<mpl::list<symbol>, mpl::sizeof_<mpl::arg<1>>>::type
+ transformed_;
+ typedef mpl::max_element<transformed_>::type max_it;
+ typedef mpl::deref<max_it>::type type;
+};
+template <typename> struct make_storage {
+ typedef max_value<int, mpl::sizeof_<int>>::type max_size;
+ typedef aligned_storage<max_size::value> type;
+};
+struct destroyer {
+ template <typename T> void internal_visit(T &operand, int) { operand.~T(); }
+};
+template <typename, typename...> class variant {
+ typedef int internal_types;
+ int which_;
+ make_storage<internal_types>::type storage_;
+public:
+ ~variant() {
+ destroyer visitor;
+ internal_apply_visitor(visitor);
+ }
+ template <typename Visitor, typename VoidPtrCV>
+ void internal_apply_visitor_impl(int internal_which, int, Visitor visitor,
+ VoidPtrCV storage) {
+ visitation_impl(internal_which, visitor, storage, int(), int(),
+ static_cast<int>(0),
+ static_cast<visitation_impl_step *>(0));
+ }
+ int internal_apply_visitor___trans_tmp_1;
+ template <typename Visitor> void internal_apply_visitor(Visitor visitor) {
+ internal_apply_visitor_impl(which_, internal_apply_visitor___trans_tmp_1,
+ visitor, storage_.address());
+ }
+};
+struct symbol {
+ virtual ~symbol();
+};
+using Identifier = variant<int>;
+struct Fragment {
+ virtual void foo() const = 0;
+ virtual ~Fragment();
+};
+struct ProcFrag : Fragment {
+ ~ProcFrag() {}
+ void foo() const;
+ Identifier id;
+};
+struct Fragments {
+ ~Fragments() { delete x; }
+ Fragment *x;
+} fragments;
diff --git a/gcc/testsuite/g++.dg/vect/pr68145.cc b/gcc/testsuite/g++.dg/vect/pr68145.cc
new file mode 100644
index 00000000000..51e663ae636
--- /dev/null
+++ b/gcc/testsuite/g++.dg/vect/pr68145.cc
@@ -0,0 +1,41 @@
+/* { dg-do compile } */
+
+struct A {
+ bool operator()(int p1, int p2) { return p1 && p2; }
+};
+class B {
+public:
+ bool *cbegin();
+ bool *cend();
+};
+template <class T> void operator&&(B p1, T p2) {
+ B a;
+ arrayContTransform(p1, p2, a, A());
+}
+
+template <typename _InputIterator1, typename T, typename _OutputIterator,
+ typename _BinaryOperation>
+void myrtransform(_InputIterator1 p1, _OutputIterator p2, T p3,
+ _BinaryOperation p4) {
+ _InputIterator1 b;
+ for (; b != p1; ++b, ++p2)
+ *p2 = p4(*b, p3);
+}
+
+template <typename L, typename R, typename RES, typename BinaryOperator>
+void arrayContTransform(L p1, R p2, RES p3, BinaryOperator p4) {
+ myrtransform(p1.cend(), p3.cbegin(), p2, p4);
+}
+
+class C {
+public:
+ B getArrayBool();
+};
+class D {
+ B getArrayBool(const int &);
+ C lnode_p;
+};
+bool c;
+B D::getArrayBool(const int &) { lnode_p.getArrayBool() && c; }
+
+// { dg-final { scan-tree-dump "vectorized 1 loops" "vect" { target { i?86-*-* x86_64-*-* } } } }
diff --git a/gcc/testsuite/gcc.dg/Wno-frame-address.c b/gcc/testsuite/gcc.dg/Wno-frame-address.c
index d464ad6f1e1..6409b29d557 100644
--- a/gcc/testsuite/gcc.dg/Wno-frame-address.c
+++ b/gcc/testsuite/gcc.dg/Wno-frame-address.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-skip-if "Cannot access arbitrary stack frames" { arm*-*-* visium-*-* } } */
+/* { dg-skip-if "Cannot access arbitrary stack frames" { arm*-*-* hppa*-*-* visium-*-* } } */
/* { dg-options "-Werror" } */
/* Verify that -Wframe-address is not enabled by default by enabling
diff --git a/gcc/testsuite/gcc.dg/gomp/ordered-2.c b/gcc/testsuite/gcc.dg/gomp/ordered-2.c
index 2884b10261c..1107c37381a 100644
--- a/gcc/testsuite/gcc.dg/gomp/ordered-2.c
+++ b/gcc/testsuite/gcc.dg/gomp/ordered-2.c
@@ -3,5 +3,5 @@
void f1(void)
{
#pragma omp ordered asdf /* { dg-error "expected" } */
- #pragma omp ordered
+ #pragma omp ordered /* { dg-error "region may not be closely nested inside of" } */
} /* { dg-error "expected expression" } */
diff --git a/gcc/testsuite/gcc.dg/graphite/fuse-1.c b/gcc/testsuite/gcc.dg/graphite/fuse-1.c
new file mode 100644
index 00000000000..c9bb67debe1
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/graphite/fuse-1.c
@@ -0,0 +1,43 @@
+/* Check that the two loops are fused and that we manage to fold the two xor
+ operations. */
+/* { dg-options "-O2 -floop-nest-optimize -fdump-tree-forwprop-all" } */
+/* { dg-do run } */
+
+/* Make sure we fuse the loops like this:
+ISL AST generated by ISL:
+for (int c0 = 0; c0 <= 99; c0 += 1) {
+ S_3(c0);
+ S_6(c0);
+ S_9(c0);
+}
+*/
+/* { dg-final { scan-tree-dump-times "ISL AST generated by ISL:.*for (int c0 = 0; c0 <= 99; c0 += 1) \{.*S_.*(c0);.*S_.*(c0);.*S_.*(c0);.*\}" 1 "graphite" } } */
+
+/* Check that after fusing the loops, the scalar computation is also fused. */
+/* { dg-final { scan-tree-dump-times "gimple_simplified to\[^\\n\]*\\^ 12" 1 "forwprop4" } } */
+
+
+
+#define MAX 100
+int A[MAX];
+
+extern void abort ();
+
+int
+main (void)
+{
+ int i;
+
+ for (i = 0; i < MAX; i++)
+ A[i] = i;
+ for(int i=0; i<MAX; i++)
+ A[i] ^= 4;
+ for(int i=0; i<MAX; i++)
+ A[i] ^= 8;
+
+ for (i = 0; i < MAX; i++)
+ if (A[i] != (i ^ 12))
+ abort ();
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/graphite/fuse-2.c b/gcc/testsuite/gcc.dg/graphite/fuse-2.c
new file mode 100644
index 00000000000..aaa5e2f8c36
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/graphite/fuse-2.c
@@ -0,0 +1,43 @@
+/* Check that the three loops are fused. */
+/* { dg-options "-O2 -floop-nest-optimize" } */
+/* { dg-do run } */
+
+/* Make sure we fuse the loops like this:
+ISL AST generated by ISL:
+for (int c0 = 0; c0 <= 99; c0 += 1) {
+ S_3(c0);
+ S_6(c0);
+ S_9(c0);
+}
+*/
+
+/* { dg-final { scan-tree-dump-times "ISL AST generated by ISL:.*for (int c0 = 0; c0 <= 99; c0 += 1) \{.*S_.*(c0);.*S_.*(c0);.*S_.*(c0);.*\}" 1 "graphite" } } */
+
+#define MAX 100
+int A[MAX], B[MAX], C[MAX];
+
+extern void abort ();
+
+int
+main (void)
+{
+ int i;
+
+ /* The next three loops should be fused. */
+ for (i = 0; i < MAX; i++)
+ {
+ A[i] = i;
+ B[i] = i + 2;
+ C[i] = i + 1;
+ }
+ for(int i=0; i<MAX; i++)
+ A[i] += B[i];
+ for(int i=0; i<MAX; i++)
+ A[i] += C[i];
+
+ for (i = 0; i < MAX; i++)
+ if (A[i] != 3*i+3)
+ abort ();
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/graphite/interchange-13.c b/gcc/testsuite/gcc.dg/graphite/interchange-13.c
index 3398de26c24..4e4a83e3df4 100644
--- a/gcc/testsuite/gcc.dg/graphite/interchange-13.c
+++ b/gcc/testsuite/gcc.dg/graphite/interchange-13.c
@@ -49,4 +49,3 @@ main (void)
return 0;
}
-/* { dg-final { scan-tree-dump "tiled" "graphite" } } */
diff --git a/gcc/testsuite/gcc.dg/lto/20110201-1_0.c b/gcc/testsuite/gcc.dg/lto/20110201-1_0.c
index 068dddc3a84..2144f071480 100644
--- a/gcc/testsuite/gcc.dg/lto/20110201-1_0.c
+++ b/gcc/testsuite/gcc.dg/lto/20110201-1_0.c
@@ -1,6 +1,6 @@
/* { dg-lto-do run } */
-/* { dg-lto-options { { -O0 -flto } } } */
-/* { dg-lto-options { "-O0 -flto -mfloat-abi=softfp -mfpu=neon-vfpv4" } { target arm*-*-* } } */
+/* { dg-lto-options { { -O0 -flto -fno-math-errno } } } */
+/* { dg-lto-options { "-O0 -flto -fno-math-errno -mfloat-abi=softfp -mfpu=neon-vfpv4" } { target arm*-*-* } } */
/* { dg-require-linker-plugin "" } */
/* { dg-require-effective-target sqrt_insn } */
diff --git a/gcc/testsuite/gcc.dg/plugin/diagnostic-test-show-locus-bw.c b/gcc/testsuite/gcc.dg/plugin/diagnostic-test-show-locus-bw.c
new file mode 100644
index 00000000000..a4b16da318c
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/plugin/diagnostic-test-show-locus-bw.c
@@ -0,0 +1,149 @@
+/* { dg-do compile } */
+/* { dg-options "-O -fdiagnostics-show-caret" } */
+
+/* This is a collection of unittests for diagnostic_show_locus;
+ see the overview in diagnostic_plugin_test_show_locus.c.
+
+ In particular, note the discussion of why we need a very long line here:
+01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
+ and that we can't use macros in this file. */
+
+void test_simple (void)
+{
+#if 0
+ myvar = myvar.x; /* { dg-warning "test" } */
+
+/* { dg-begin-multiline-output "" }
+ myvar = myvar.x;
+ ~~~~~^~
+ { dg-end-multiline-output "" } */
+#endif
+}
+
+void test_simple_2 (void)
+{
+#if 0
+ x = first_function () + second_function (); /* { dg-warning "test" } */
+
+/* { dg-begin-multiline-output "" }
+ x = first_function () + second_function ();
+ ~~~~~~~~~~~~~~~~~ ^ ~~~~~~~~~~~~~~~~~~
+ { dg-end-multiline-output "" } */
+#endif
+}
+
+
+void test_multiline (void)
+{
+#if 0
+ x = (first_function ()
+ + second_function ()); /* { dg-warning "test" } */
+
+/* { dg-begin-multiline-output "" }
+ x = (first_function ()
+ ~~~~~~~~~~~~~~~~~
+ + second_function ());
+ ^ ~~~~~~~~~~~~~~~~~~
+ { dg-end-multiline-output "" } */
+#endif
+}
+
+void test_many_lines (void)
+{
+#if 0
+ x = (first_function_with_a_very_long_name (lorem, ipsum, dolor, sit, amet,
+ consectetur, adipiscing, elit,
+ sed, eiusmod, tempor,
+ incididunt, ut, labore, et,
+ dolore, magna, aliqua)
+ + second_function_with_a_very_long_name (lorem, ipsum, dolor, sit, /* { dg-warning "test" } */
+ amet, consectetur,
+ adipiscing, elit, sed,
+ eiusmod, tempor, incididunt,
+ ut, labore, et, dolore,
+ magna, aliqua));
+
+/* { dg-begin-multiline-output "" }
+ x = (first_function_with_a_very_long_name (lorem, ipsum, dolor, sit, amet,
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ consectetur, adipiscing, elit,
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ sed, eiusmod, tempor,
+ ~~~~~~~~~~~~~~~~~~~~~
+ incididunt, ut, labore, et,
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ dolore, magna, aliqua)
+ ~~~~~~~~~~~~~~~~~~~~~~
+ + second_function_with_a_very_long_name (lorem, ipsum, dolor, sit,
+ ^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ amet, consectetur,
+ ~~~~~~~~~~~~~~~~~~
+ adipiscing, elit, sed,
+ ~~~~~~~~~~~~~~~~~~~~~~
+ eiusmod, tempor, incididunt,
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ ut, labore, et, dolore,
+ ~~~~~~~~~~~~~~~~~~~~~~~
+ magna, aliqua));
+ ~~~~~~~~~~~~~~
+ { dg-end-multiline-output "" } */
+#endif
+}
+
+void test_richloc_from_proper_range (void)
+{
+#if 0
+ float f = 98.6f; /* { dg-warning "test" } */
+/* { dg-begin-multiline-output "" }
+ float f = 98.6f;
+ ^~~~~
+ { dg-end-multiline-output "" } */
+#endif
+}
+
+void test_caret_within_proper_range (void)
+{
+#if 0
+ float f = foo * bar; /* { dg-warning "17: test" } */
+/* { dg-begin-multiline-output "" }
+ float f = foo * bar;
+ ~~~~^~~~~
+ { dg-end-multiline-output "" } */
+#endif
+}
+
+void test_very_wide_line (void)
+{
+#if 0
+ float f = foo * bar; /* { dg-warning "95: test" } */
+/* { dg-begin-multiline-output "" }
+ float f = foo * bar;
+ ~~~~^~~~~
+ { dg-end-multiline-output "" } */
+#endif
+}
+
+void test_multiple_carets (void)
+{
+#if 0
+ x = x + y /* { dg-warning "8: test" } */
+/* { dg-begin-multiline-output "" }
+ x = x + y
+ A B
+ { dg-end-multiline-output "" } */
+#endif
+}
+
+void test_caret_on_leading_whitespace (void)
+{
+#if 0
+ ASSOCIATE (y => x)
+ y = 5 /* { dg-warning "6: test" } */
+/* { dg-begin-multiline-output "" }
+ ASSOCIATE (y => x)
+ 2
+ y = 5
+ 1
+ { dg-end-multiline-output "" } */
+#endif
+}
diff --git a/gcc/testsuite/gcc.dg/plugin/diagnostic-test-show-locus-color.c b/gcc/testsuite/gcc.dg/plugin/diagnostic-test-show-locus-color.c
new file mode 100644
index 00000000000..47639b22fc9
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/plugin/diagnostic-test-show-locus-color.c
@@ -0,0 +1,158 @@
+/* { dg-do compile } */
+/* { dg-options "-O -fdiagnostics-show-caret -fplugin-arg-diagnostic_plugin_test_show_locus-color" } */
+
+/* This is a collection of unittests for diagnostic_show_locus;
+ see the overview in diagnostic_plugin_test_show_locus.c.
+
+ In particular, note the discussion of why we need a very long line here:
+01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
+ and that we can't use macros in this file. */
+
+void test_simple (void)
+{
+#if 0
+ myvar = myvar.x; /* { dg-warning "test" } */
+
+/* { dg-begin-multiline-output "" }
+ myvar = myvar.x;
+ ~~~~~^~
+
+ { dg-end-multiline-output "" } */
+#endif
+}
+
+void test_simple_2 (void)
+{
+#if 0
+ x = first_function () + second_function (); /* { dg-warning "test" } */
+
+/* { dg-begin-multiline-output "" }
+ x = first_function () + second_function ();
+ ~~~~~~~~~~~~~~~~~ ^ ~~~~~~~~~~~~~~~~~~
+
+ { dg-end-multiline-output "" } */
+#endif
+}
+
+
+void test_multiline (void)
+{
+#if 0
+ x = (first_function ()
+ + second_function ()); /* { dg-warning "test" } */
+
+/* { dg-begin-multiline-output "" }
+ x = (first_function ()
+  ~~~~~~~~~~~~~~~~~
+ + second_function ());
+ ^ ~~~~~~~~~~~~~~~~~~
+
+ { dg-end-multiline-output "" } */
+#endif
+}
+
+void test_many_lines (void)
+{
+#if 0
+ x = (first_function_with_a_very_long_name (lorem, ipsum, dolor, sit, amet,
+ consectetur, adipiscing, elit,
+ sed, eiusmod, tempor,
+ incididunt, ut, labore, et,
+ dolore, magna, aliqua)
+ + second_function_with_a_very_long_name (lorem, ipsum, dolor, sit, /* { dg-warning "test" } */
+ amet, consectetur,
+ adipiscing, elit, sed,
+ eiusmod, tempor, incididunt,
+ ut, labore, et, dolore,
+ magna, aliqua));
+
+/* { dg-begin-multiline-output "" }
+ x = (first_function_with_a_very_long_name (lorem, ipsum, dolor, sit, amet,
+  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+  consectetur, adipiscing, elit,
+  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+  sed, eiusmod, tempor,
+  ~~~~~~~~~~~~~~~~~~~~~
+  incididunt, ut, labore, et,
+  ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+  dolore, magna, aliqua)
+  ~~~~~~~~~~~~~~~~~~~~~~
+ + second_function_with_a_very_long_name (lorem, ipsum, dolor, sit,
+  ^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+  amet, consectetur,
+  ~~~~~~~~~~~~~~~~~~
+  adipiscing, elit, sed,
+  ~~~~~~~~~~~~~~~~~~~~~~
+  eiusmod, tempor, incididunt,
+  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+  ut, labore, et, dolore,
+  ~~~~~~~~~~~~~~~~~~~~~~~
+  magna, aliqua));
+ ~~~~~~~~~~~~~~
+
+ { dg-end-multiline-output "" } */
+#endif
+}
+
+void test_richloc_from_proper_range (void)
+{
+#if 0
+ float f = 98.6f; /* { dg-warning "test" } */
+/* { dg-begin-multiline-output "" }
+ float f = 98.6f;
+ ^~~~~
+
+ { dg-end-multiline-output "" } */
+#endif
+}
+
+void test_caret_within_proper_range (void)
+{
+#if 0
+ float f = foo * bar; /* { dg-warning "17: test" } */
+/* { dg-begin-multiline-output "" }
+ float f = foo * bar;
+ ~~~~^~~~~
+
+ { dg-end-multiline-output "" } */
+#endif
+}
+
+void test_very_wide_line (void)
+{
+#if 0
+ float f = foo * bar; /* { dg-warning "95: test" } */
+/* { dg-begin-multiline-output "" }
+ float f = foo * bar;
+ ~~~~^~~~~
+
+ { dg-end-multiline-output "" } */
+#endif
+}
+
+void test_multiple_carets (void)
+{
+#if 0
+ x = x + y /* { dg-warning "8: test" } */
+/* { dg-begin-multiline-output "" }
+ x = x + y
+ A B
+
+ { dg-end-multiline-output "" } */
+#endif
+}
+
+void test_caret_on_leading_whitespace (void)
+{
+#if 0
+ ASSOCIATE (y => x)
+ y = 5 /* { dg-warning "6: test" } */
+/* { dg-begin-multiline-output "" }
+ ASSOCIATE (y => x)
+ 2
+  y = 5
+ 1
+
+ { dg-end-multiline-output "" } */
+#endif
+}
diff --git a/gcc/testsuite/gcc.dg/plugin/diagnostic_plugin_test_show_locus.c b/gcc/testsuite/gcc.dg/plugin/diagnostic_plugin_test_show_locus.c
new file mode 100644
index 00000000000..8f5724ec27d
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/plugin/diagnostic_plugin_test_show_locus.c
@@ -0,0 +1,326 @@
+/* { dg-options "-O" } */
+
+/* This plugin exercises the diagnostics-printing code.
+
+ The goal is to unit-test the range-printing code without needing any
+ correct range data within the compiler's IR. We can't use any real
+ diagnostics for this, so we have to fake it, hence this plugin.
+
+ There are two test files used with this code:
+
+ diagnostic-test-show-locus-ascii-bw.c
+ ..........................-ascii-color.c
+
+ to exercise uncolored vs colored output by supplying plugin arguments
+ to hack in the desired behavior:
+
+ -fplugin-arg-diagnostic_plugin_test_show_locus-color
+
+ The test files contain functions, but the body of each
+ function is disabled using the preprocessor. The plugin detects
+ the functions by name, and inject diagnostics within them, using
+ hard-coded locations relative to the top of each function.
+
+ The plugin uses a function "get_loc" below to map from line/column
+ numbers to source_location, and this relies on input_location being in
+ the same ordinary line_map as the locations in question. The plugin
+ runs after parsing, so input_location will be at the end of the file.
+
+ This need for all of the test code to be in a single ordinary line map
+ means that each test file needs to have a very long line near the top
+ (potentially to cover the extra byte-count of colorized data),
+ to ensure that further very long lines don't start a new linemap.
+ This also means that we can't use macros in the test files. */
+
+#include "gcc-plugin.h"
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "tm.h"
+#include "tree.h"
+#include "stringpool.h"
+#include "toplev.h"
+#include "basic-block.h"
+#include "hash-table.h"
+#include "vec.h"
+#include "ggc.h"
+#include "basic-block.h"
+#include "tree-ssa-alias.h"
+#include "internal-fn.h"
+#include "gimple-fold.h"
+#include "tree-eh.h"
+#include "gimple-expr.h"
+#include "is-a.h"
+#include "gimple.h"
+#include "gimple-iterator.h"
+#include "tree.h"
+#include "tree-pass.h"
+#include "intl.h"
+#include "plugin-version.h"
+#include "diagnostic.h"
+#include "context.h"
+#include "print-tree.h"
+
+int plugin_is_GPL_compatible;
+
+const pass_data pass_data_test_show_locus =
+{
+ GIMPLE_PASS, /* type */
+ "test_show_locus", /* name */
+ OPTGROUP_NONE, /* optinfo_flags */
+ TV_NONE, /* tv_id */
+ PROP_ssa, /* properties_required */
+ 0, /* properties_provided */
+ 0, /* properties_destroyed */
+ 0, /* todo_flags_start */
+ 0, /* todo_flags_finish */
+};
+
+class pass_test_show_locus : public gimple_opt_pass
+{
+public:
+ pass_test_show_locus(gcc::context *ctxt)
+ : gimple_opt_pass(pass_data_test_show_locus, ctxt)
+ {}
+
+ /* opt_pass methods: */
+ bool gate (function *) { return true; }
+ virtual unsigned int execute (function *);
+
+}; // class pass_test_show_locus
+
+/* Given LINE_NUM and COL_NUM, generate a source_location in the
+ current file, relative to input_location. This relies on the
+ location being expressible in the same ordinary line_map as
+ input_location (which is typically at the end of the source file
+ when this is called). Hence the test files we compile with this
+ plugin must have an initial very long line (to avoid long lines
+ starting a new line map), and must not use macros.
+
+ COL_NUM uses the Emacs convention of 0-based column numbers. */
+
+static source_location
+get_loc (unsigned int line_num, unsigned int col_num)
+{
+ /* Use input_location to get the relevant line_map */
+ const struct line_map_ordinary *line_map
+ = (const line_map_ordinary *)(linemap_lookup (line_table,
+ input_location));
+
+ /* Convert from 0-based column numbers to 1-based column numbers. */
+ source_location loc
+ = linemap_position_for_line_and_column (line_map,
+ line_num, col_num + 1);
+
+ return loc;
+}
+
+/* Was "color" passed in as a plugin argument? */
+static bool force_show_locus_color = false;
+
+/* We want to verify the colorized output of diagnostic_show_locus,
+ but turning on colorization for everything confuses "dg-warning" etc.
+ Hence we special-case it within this plugin by using this modified
+ version of default_diagnostic_finalizer, which, if "color" is
+ passed in as a plugin argument turns on colorization, but just
+ for diagnostic_show_locus. */
+
+static void
+custom_diagnostic_finalizer (diagnostic_context *context,
+ diagnostic_info *diagnostic)
+{
+ bool old_show_color = pp_show_color (context->printer);
+ if (force_show_locus_color)
+ pp_show_color (context->printer) = true;
+ diagnostic_show_locus (context, diagnostic);
+ pp_show_color (context->printer) = old_show_color;
+
+ pp_destroy_prefix (context->printer);
+ pp_newline_and_flush (context->printer);
+}
+
+/* Exercise the diagnostic machinery to emit various warnings,
+ for use by diagnostic-test-show-locus-*.c.
+
+ We inject each warning relative to the start of a function,
+ which avoids lots of hardcoded absolute locations. */
+
+static void
+test_show_locus (function *fun)
+{
+ tree fndecl = fun->decl;
+ tree identifier = DECL_NAME (fndecl);
+ const char *fnname = IDENTIFIER_POINTER (identifier);
+ location_t fnstart = fun->function_start_locus;
+ int fnstart_line = LOCATION_LINE (fnstart);
+
+ diagnostic_finalizer (global_dc) = custom_diagnostic_finalizer;
+
+ /* Hardcode the "terminal width", to verify the behavior of
+ very wide lines. */
+ global_dc->caret_max_width = 70;
+
+ if (0 == strcmp (fnname, "test_simple"))
+ {
+ const int line = fnstart_line + 2;
+ rich_location richloc (get_loc (line, 15));
+ richloc.add_range (get_loc (line, 10), get_loc (line, 14), false);
+ richloc.add_range (get_loc (line, 16), get_loc (line, 16), false);
+ warning_at_rich_loc (&richloc, 0, "test");
+ }
+
+ if (0 == strcmp (fnname, "test_simple_2"))
+ {
+ const int line = fnstart_line + 2;
+ rich_location richloc (get_loc (line, 24));
+ richloc.add_range (get_loc (line, 6),
+ get_loc (line, 22), false);
+ richloc.add_range (get_loc (line, 26),
+ get_loc (line, 43), false);
+ warning_at_rich_loc (&richloc, 0, "test");
+ }
+
+ if (0 == strcmp (fnname, "test_multiline"))
+ {
+ const int line = fnstart_line + 2;
+ rich_location richloc (get_loc (line + 1, 7));
+ richloc.add_range (get_loc (line, 7),
+ get_loc (line, 23), false);
+ richloc.add_range (get_loc (line + 1, 9),
+ get_loc (line + 1, 26), false);
+ warning_at_rich_loc (&richloc, 0, "test");
+ }
+
+ if (0 == strcmp (fnname, "test_many_lines"))
+ {
+ const int line = fnstart_line + 2;
+ rich_location richloc (get_loc (line + 5, 7));
+ richloc.add_range (get_loc (line, 7),
+ get_loc (line + 4, 65), false);
+ richloc.add_range (get_loc (line + 5, 9),
+ get_loc (line + 10, 61), false);
+ warning_at_rich_loc (&richloc, 0, "test");
+ }
+
+ /* Example of a rich_location constructed directly from a
+ source_range where the range is larger than one character. */
+ if (0 == strcmp (fnname, "test_richloc_from_proper_range"))
+ {
+ const int line = fnstart_line + 2;
+ source_range src_range;
+ src_range.m_start = get_loc (line, 12);
+ src_range.m_finish = get_loc (line, 16);
+ rich_location richloc (src_range);
+ warning_at_rich_loc (&richloc, 0, "test");
+ }
+
+ /* Example of a single-range location where the range starts
+ before the caret. */
+ if (0 == strcmp (fnname, "test_caret_within_proper_range"))
+ {
+ const int line = fnstart_line + 2;
+ location_t caret = get_loc (line, 16);
+ source_range src_range;
+ src_range.m_start = get_loc (line, 12);
+ src_range.m_finish = get_loc (line, 20);
+ rich_location richloc (caret);
+ richloc.set_range (0, src_range, true, false);
+ warning_at_rich_loc (&richloc, 0, "test");
+ }
+
+ /* Example of a very wide line, where the information of interest
+ is beyond the width of the terminal (hardcoded above). */
+ if (0 == strcmp (fnname, "test_very_wide_line"))
+ {
+ const int line = fnstart_line + 2;
+ location_t caret = get_loc (line, 94);
+ source_range src_range;
+ src_range.m_start = get_loc (line, 90);
+ src_range.m_finish = get_loc (line, 98);
+ rich_location richloc (caret);
+ richloc.set_range (0, src_range, true, false);
+ warning_at_rich_loc (&richloc, 0, "test");
+ }
+
+ /* Example of multiple carets. */
+ if (0 == strcmp (fnname, "test_multiple_carets"))
+ {
+ const int line = fnstart_line + 2;
+ location_t caret_a = get_loc (line, 7);
+ location_t caret_b = get_loc (line, 11);
+ rich_location richloc (caret_a);
+ richloc.add_range (caret_b, caret_b, true);
+ global_dc->caret_chars[0] = 'A';
+ global_dc->caret_chars[1] = 'B';
+ warning_at_rich_loc (&richloc, 0, "test");
+ global_dc->caret_chars[0] = '^';
+ global_dc->caret_chars[1] = '^';
+ }
+
+ /* Example of two carets where both carets appear to have an off-by-one
+ error appearing one column early.
+ Seen with gfortran.dg/associate_5.f03.
+ In an earlier version of the printer, the printing of caret 0 aka
+ "1" was suppressed due to it appearing within the leading whitespace
+ before the text in its line. Ensure that we at least faithfully
+ print both carets, at the given (erroneous) locations. */
+ if (0 == strcmp (fnname, "test_caret_on_leading_whitespace"))
+ {
+ const int line = fnstart_line + 3;
+ location_t caret_a = get_loc (line, 5);
+ location_t caret_b = get_loc (line - 1, 19);
+ rich_location richloc (caret_a);
+ richloc.add_range (caret_b, caret_b, true);
+ global_dc->caret_chars[0] = '1';
+ global_dc->caret_chars[1] = '2';
+ warning_at_rich_loc (&richloc, 0, "test");
+ global_dc->caret_chars[0] = '^';
+ global_dc->caret_chars[1] = '^';
+ }
+}
+
+unsigned int
+pass_test_show_locus::execute (function *fun)
+{
+ test_show_locus (fun);
+ return 0;
+}
+
+static gimple_opt_pass *
+make_pass_test_show_locus (gcc::context *ctxt)
+{
+ return new pass_test_show_locus (ctxt);
+}
+
+int
+plugin_init (struct plugin_name_args *plugin_info,
+ struct plugin_gcc_version *version)
+{
+ struct register_pass_info pass_info;
+ const char *plugin_name = plugin_info->base_name;
+ int argc = plugin_info->argc;
+ struct plugin_argument *argv = plugin_info->argv;
+
+ if (!plugin_default_version_check (version, &gcc_version))
+ return 1;
+
+ /* For now, tell the dc to expect ranges and thus to colorize the source
+ lines, not just the carets/underlines. This will be redundant
+ once the C frontend generates ranges. */
+ global_dc->colorize_source_p = true;
+
+ for (int i = 0; i < argc; i++)
+ {
+ if (0 == strcmp (argv[i].key, "color"))
+ force_show_locus_color = true;
+ }
+
+ pass_info.pass = make_pass_test_show_locus (g);
+ pass_info.reference_pass_name = "ssa";
+ pass_info.ref_pass_instance_number = 1;
+ pass_info.pos_op = PASS_POS_INSERT_AFTER;
+ register_callback (plugin_name, PLUGIN_PASS_MANAGER_SETUP, NULL,
+ &pass_info);
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/plugin/plugin.exp b/gcc/testsuite/gcc.dg/plugin/plugin.exp
index 39fab6ef019..941bccc4387 100644
--- a/gcc/testsuite/gcc.dg/plugin/plugin.exp
+++ b/gcc/testsuite/gcc.dg/plugin/plugin.exp
@@ -63,6 +63,9 @@ set plugin_test_list [list \
{ start_unit_plugin.c start_unit-test-1.c } \
{ finish_unit_plugin.c finish_unit-test-1.c } \
{ wide-int_plugin.c wide-int-test-1.c } \
+ { diagnostic_plugin_test_show_locus.c \
+ diagnostic-test-show-locus-bw.c \
+ diagnostic-test-show-locus-color.c } \
]
foreach plugin_test $plugin_test_list {
diff --git a/gcc/testsuite/gcc.dg/pr68088_1.c b/gcc/testsuite/gcc.dg/pr68088_1.c
new file mode 100644
index 00000000000..49c6aa14543
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr68088_1.c
@@ -0,0 +1,15 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+void bar (unsigned long);
+
+void
+foo (unsigned long aul, unsigned m, unsigned i)
+{
+ while (1)
+ {
+ aul += i;
+ i = aul % m;
+ bar (aul);
+ }
+}
diff --git a/gcc/testsuite/gcc.dg/pragma-diag-5.c b/gcc/testsuite/gcc.dg/pragma-diag-5.c
index 18f0789f9df..fe820a699eb 100644
--- a/gcc/testsuite/gcc.dg/pragma-diag-5.c
+++ b/gcc/testsuite/gcc.dg/pragma-diag-5.c
@@ -1,6 +1,6 @@
/* { dg-do compile } */
#pragma GCC diagnostic /* { dg-warning "missing" "missing" } */
-/* { dg-warning "24:missing" "missing" { xfail *-*-* } 2 } */
+/* { dg-warning "24:missing" "wrong column" { xfail *-*-* } 2 } */
#pragma GCC diagnostic warn /* { dg-warning "24:expected" } */
diff --git a/gcc/testsuite/gcc.dg/sso-1.c b/gcc/testsuite/gcc.dg/sso-1.c
new file mode 100644
index 00000000000..b2e11bd00d3
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/sso-1.c
@@ -0,0 +1,19 @@
+/* Test support of scalar_storage_order attribute */
+
+/* { dg-do compile } */
+
+int i;
+
+#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
+struct __attribute__((scalar_storage_order("big-endian"))) Rec
+{
+ int *p;
+};
+#else
+struct __attribute__((scalar_storage_order("little-endian"))) Rec
+{
+ int *p;
+};
+#endif
+
+struct Rec r = { &i }; /* { dg-error "element is not constant" } */
diff --git a/gcc/testsuite/gcc.dg/sso-2.c b/gcc/testsuite/gcc.dg/sso-2.c
new file mode 100644
index 00000000000..0f7218c8012
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/sso-2.c
@@ -0,0 +1,94 @@
+/* Test support of scalar_storage_order attribute */
+
+/* { dg-do compile } */
+
+struct __attribute__((scalar_storage_order("big-endian"))) S1
+{
+ int i;
+};
+
+struct __attribute__((scalar_storage_order("little-endian"))) S2
+{
+ int i;
+};
+
+struct __attribute__((scalar_storage_order("other"))) S3 { int i; }; /* { dg-error "must be one of .big-endian. or .little-endian." } */
+
+void incompatible_assign (struct S1 *s1, struct S2 *s2)
+{
+ *s1 = *s2; /* { dg-error "(incompatible types|no match)" } */
+}
+
+int *addr1 (int which, struct S1 *s1, struct S2 *s2)
+{
+ return (which == 1 ? &s1->i : &s2->i); /* { dg-error "address of scalar with reverse storage order" } */
+}
+
+struct __attribute__((scalar_storage_order("big-endian"))) S4
+{
+ int a[4];
+ struct S2 s2;
+};
+
+struct __attribute__((scalar_storage_order("little-endian"))) S5
+{
+ int a[4];
+ struct S1 s1;
+};
+
+void *addr2 (int which, struct S4 *s4, struct S5 *s5)
+{
+ return (which == 1 ? (void *)s4->a : (void *)s5->a); /* { dg-warning "address of array with reverse scalar storage order" } */
+}
+
+void *addr3 (int which, struct S4 *s4, struct S5 *s5)
+{
+ return (which == 1 ? (void *)&s4->a : (void *)&s5->a); /* { dg-warning "address of array with reverse scalar storage order" } */
+}
+
+void *addr4 (int which, struct S4 *s4, struct S5 *s5)
+{
+ return (which == 1 ? (void *)&s4->a[0] : (void *)&s5->a[0]); /* { dg-error "address of scalar with reverse storage order" } */
+}
+
+void *addr5 (int which, struct S4 *s4, struct S5 *s5)
+{
+ return (which == 1 ? (void *)&s4->s2 : (void *) &s5->s1); /* ok */
+}
+
+struct __attribute__((scalar_storage_order("big-endian"))) S6
+{
+ int a[4][2];
+ struct S2 s2[2];
+};
+
+struct __attribute__((scalar_storage_order("little-endian"))) S7
+{
+ int a[4][2];
+ struct S1 s1[2];
+};
+
+void *addr6 (int which, struct S6 *s6, struct S7 *s7)
+{
+ return (which == 1 ? (void *)s6->a : (void *)s7->a); /* { dg-warning "address of array with reverse scalar storage order" } */
+}
+
+void *addr7 (int which, struct S6 *s6, struct S7 *s7)
+{
+ return (which == 1 ? (void *)&s6->a : (void *)&s7->a); /* { dg-warning "address of array with reverse scalar storage order" } */
+}
+
+void *addr8 (int which, struct S6 *s6, struct S7 *s7)
+{
+ return (which == 1 ? (void *)&s6->a[0] : (void *)&s7->a[0]); /* { dg-warning "address of array with reverse scalar storage order" } */
+}
+
+void *addr9 (int which, struct S6 *s6, struct S7 *s7)
+{
+ return (which == 1 ? (void *)&s6->a[0][0] : (void *)&s7->a[0][0]); /* { dg-error "address of scalar with reverse storage order" } */
+}
+
+void *addr10 (int which, struct S6 *s6, struct S7 *s7)
+{
+ return (which == 1 ? (void *)&s6->s2 : (void *)&s7->s1); /* ok */
+}
diff --git a/gcc/testsuite/gcc.dg/sso-3.c b/gcc/testsuite/gcc.dg/sso-3.c
new file mode 100644
index 00000000000..c7877e8fafa
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/sso-3.c
@@ -0,0 +1,94 @@
+/* Test support of scalar_storage_order attribute */
+
+/* { dg-do compile } */
+
+struct S1
+{
+ int i;
+} __attribute__((scalar_storage_order("big-endian")));
+
+struct S2
+{
+ int i;
+} __attribute__((scalar_storage_order("little-endian")));
+
+struct S3 { int i; } __attribute__((scalar_storage_order("other"))); /* { dg-error "must be one of .big-endian. or .little-endian." } */
+
+void incompatible_assign (struct S1 *s1, struct S2 *s2)
+{
+ *s1 = *s2; /* { dg-error "(incompatible types|no match)" } */
+}
+
+int *addr1 (int which, struct S1 *s1, struct S2 *s2)
+{
+ return (which == 1 ? &s1->i : &s2->i); /* { dg-error "address of scalar with reverse storage order" } */
+}
+
+struct S4
+{
+ int a[4];
+ struct S2 s2;
+} __attribute__((scalar_storage_order("big-endian")));
+
+struct S5
+{
+ int a[4];
+ struct S1 s1;
+} __attribute__((scalar_storage_order("little-endian")));
+
+void *addr2 (int which, struct S4 *s4, struct S5 *s5)
+{
+ return (which == 1 ? (void *)s4->a : (void *)s5->a); /* { dg-warning "address of array with reverse scalar storage order" } */
+}
+
+void *addr3 (int which, struct S4 *s4, struct S5 *s5)
+{
+ return (which == 1 ? (void *)&s4->a : (void *)&s5->a); /* { dg-warning "address of array with reverse scalar storage order" } */
+}
+
+void *addr4 (int which, struct S4 *s4, struct S5 *s5)
+{
+ return (which == 1 ? (void *)&s4->a[0] : (void *)&s5->a[0]); /* { dg-error "address of scalar with reverse storage order" } */
+}
+
+void *addr5 (int which, struct S4 *s4, struct S5 *s5)
+{
+ return (which == 1 ? (void *)&s4->s2 : (void *) &s5->s1); /* ok */
+}
+
+struct S6
+{
+ int a[4][2];
+ struct S2 s2[2];
+} __attribute__((scalar_storage_order("big-endian")));
+
+struct S7
+{
+ int a[4][2];
+ struct S1 s1[2];
+} __attribute__((scalar_storage_order("little-endian")));
+
+void *addr6 (int which, struct S6 *s6, struct S7 *s7)
+{
+ return (which == 1 ? (void *)s6->a : (void *)s7->a); /* { dg-warning "address of array with reverse scalar storage order" } */
+}
+
+void *addr7 (int which, struct S6 *s6, struct S7 *s7)
+{
+ return (which == 1 ? (void *)&s6->a : (void *)&s7->a); /* { dg-warning "address of array with reverse scalar storage order" } */
+}
+
+void *addr8 (int which, struct S6 *s6, struct S7 *s7)
+{
+ return (which == 1 ? (void *)&s6->a[0] : (void *)&s7->a[0]); /* { dg-warning "address of array with reverse scalar storage order" } */
+}
+
+void *addr9 (int which, struct S6 *s6, struct S7 *s7)
+{
+ return (which == 1 ? (void *)&s6->a[0][0] : (void *)&s7->a[0][0]); /* { dg-error "address of scalar with reverse storage order" } */
+}
+
+void *addr10 (int which, struct S6 *s6, struct S7 *s7)
+{
+ return (which == 1 ? (void *)&s6->s2 : (void *)&s7->s1); /* ok */
+}
diff --git a/gcc/testsuite/gcc.dg/sso-4.c b/gcc/testsuite/gcc.dg/sso-4.c
new file mode 100644
index 00000000000..9eda11a4602
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/sso-4.c
@@ -0,0 +1,20 @@
+/* Test support of scalar_storage_order attribute */
+
+/* { dg-do compile } */
+
+struct S
+{
+ int i;
+};
+
+typedef struct S __attribute__((scalar_storage_order("big-endian"))) S1;
+
+typedef struct S __attribute__((scalar_storage_order("little-endian"))) S2;
+
+typedef struct S __attribute__((scalar_storage_order("other"))) S3; /* { dg-error "must be one of .big-endian. or .little-endian." } */
+
+void incompatible_assign (struct S *s, S1 *s1, S2 *s2)
+{
+ *s = *s1, *s = *s2; /* { dg-error "(incompatible types|no match)" } */
+ *s1 = *s2; /* { dg-error "(incompatible types|no match)" } */
+}
diff --git a/gcc/testsuite/gcc.dg/sso-5.c b/gcc/testsuite/gcc.dg/sso-5.c
new file mode 100644
index 00000000000..8bbb38bf54b
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/sso-5.c
@@ -0,0 +1,24 @@
+/* Test support of scalar_storage_order attribute */
+
+/* { dg-do compile } */
+
+struct S3
+{
+ struct __attribute__((scalar_storage_order("big-endian"))) S1
+ {
+ int i;
+ } s1;
+};
+
+struct S4
+{
+ struct __attribute__((scalar_storage_order("little-endian"))) S2
+ {
+ int i;
+ } s2;
+};
+
+void incompatible_assign (struct S3 *s3, struct S4 *s4)
+{
+ s3->s1 = s4->s2; /* { dg-error "(incompatible types|no match)" } */
+}
diff --git a/gcc/testsuite/gcc.dg/sso-6.c b/gcc/testsuite/gcc.dg/sso-6.c
new file mode 100644
index 00000000000..48759b41e52
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/sso-6.c
@@ -0,0 +1,72 @@
+/* Test support of scalar_storage_order pragma */
+
+/* { dg-do run } */
+
+#pragma scalar_storage_order /* { dg-warning "missing .big-endian.little-endian.default." } */
+
+#pragma scalar_storage_order big-endian
+
+struct S1
+{
+ int i;
+};
+
+struct __attribute__((scalar_storage_order("little-endian"))) S2
+{
+ int i;
+};
+
+#pragma scalar_storage_order little-endian
+
+struct S3
+{
+ int i;
+};
+
+struct __attribute__((scalar_storage_order("big-endian"))) S4
+{
+ int i;
+};
+
+#pragma scalar_storage_order default
+
+struct S5
+{
+ int i;
+};
+
+#pragma scalar_storage_order other /* { dg-warning "expected .big-endian.little-endian.default." } */
+
+struct S1 my_s1 = { 0x12345678 };
+struct S2 my_s2 = { 0x12345678 };
+struct S3 my_s3 = { 0x12345678 };
+struct S4 my_s4 = { 0x12345678 };
+struct S5 my_s5 = { 0x12345678 };
+
+unsigned char big_endian_pattern[4] = { 0x12, 0x34, 0x56, 0x78 };
+unsigned char little_endian_pattern[4] = { 0x78, 0x56, 0x34, 0x12 };
+
+int main (void)
+{
+ if (__builtin_memcmp (&my_s1, &big_endian_pattern, 4) != 0)
+ __builtin_abort ();
+
+ if (__builtin_memcmp (&my_s2, &little_endian_pattern, 4) != 0)
+ __builtin_abort ();
+
+ if (__builtin_memcmp (&my_s3, &little_endian_pattern, 4) != 0)
+ __builtin_abort ();
+
+ if (__builtin_memcmp (&my_s4, &big_endian_pattern, 4) != 0)
+ __builtin_abort ();
+
+#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
+ if (__builtin_memcmp (&my_s5, &little_endian_pattern, 4) != 0)
+ __builtin_abort ();
+#else
+ if (__builtin_memcmp (&my_s5, &big_endian_pattern, 4) != 0)
+ __builtin_abort ();
+#endif
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/sso-7.c b/gcc/testsuite/gcc.dg/sso-7.c
new file mode 100644
index 00000000000..b4d9d65c391
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/sso-7.c
@@ -0,0 +1,44 @@
+/* Test support of scalar_storage_order pragma */
+
+/* { dg-do run } */
+/* { dg-options "-fsso-struct=big-endian" } */
+
+struct S1
+{
+ int i;
+};
+
+#pragma scalar_storage_order little-endian
+
+struct S2
+{
+ int i;
+};
+
+#pragma scalar_storage_order default
+
+struct S3
+{
+ int i;
+};
+
+struct S1 my_s1 = { 0x12345678 };
+struct S2 my_s2 = { 0x12345678 };
+struct S3 my_s3 = { 0x12345678 };
+
+unsigned char big_endian_pattern[4] = { 0x12, 0x34, 0x56, 0x78 };
+unsigned char little_endian_pattern[4] = { 0x78, 0x56, 0x34, 0x12 };
+
+int main (void)
+{
+ if (__builtin_memcmp (&my_s1, &big_endian_pattern, 4) != 0)
+ __builtin_abort ();
+
+ if (__builtin_memcmp (&my_s2, &little_endian_pattern, 4) != 0)
+ __builtin_abort ();
+
+ if (__builtin_memcmp (&my_s3, &big_endian_pattern, 4) != 0)
+ __builtin_abort ();
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/sso-8.c b/gcc/testsuite/gcc.dg/sso-8.c
new file mode 100644
index 00000000000..19388358ba1
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/sso-8.c
@@ -0,0 +1,44 @@
+/* Test support of scalar_storage_order pragma */
+
+/* { dg-do run } */
+/* { dg-options "-fsso-struct=little-endian" } */
+
+struct S1
+{
+ int i;
+};
+
+#pragma scalar_storage_order big-endian
+
+struct S2
+{
+ int i;
+};
+
+#pragma scalar_storage_order default
+
+struct S3
+{
+ int i;
+};
+
+struct S1 my_s1 = { 0x12345678 };
+struct S2 my_s2 = { 0x12345678 };
+struct S3 my_s3 = { 0x12345678 };
+
+unsigned char big_endian_pattern[4] = { 0x12, 0x34, 0x56, 0x78 };
+unsigned char little_endian_pattern[4] = { 0x78, 0x56, 0x34, 0x12 };
+
+int main (void)
+{
+ if (__builtin_memcmp (&my_s1, &little_endian_pattern, 4) != 0)
+ __builtin_abort ();
+
+ if (__builtin_memcmp (&my_s2, &big_endian_pattern, 4) != 0)
+ __builtin_abort ();
+
+ if (__builtin_memcmp (&my_s3, &little_endian_pattern, 4) != 0)
+ __builtin_abort ();
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/sso/dump.h b/gcc/testsuite/gcc.dg/sso/dump.h
new file mode 100644
index 00000000000..0bcf59682f1
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/sso/dump.h
@@ -0,0 +1,23 @@
+void dump (void *p, unsigned int len)
+{
+ const char digits[17] = "0123456789abcdef";
+ unsigned char *a = (unsigned char *)p;
+ int i;
+
+ for (i = 0; i < len; i++)
+ {
+ putchar (' ');
+ putchar (digits[a[i] / 16]);
+ putchar (digits[a[i] % 16]);
+ }
+}
+
+void put (const char s[])
+{
+ fputs (s, stdout);
+}
+
+void new_line (void)
+{
+ putchar ('\n');
+}
diff --git a/gcc/testsuite/gcc.dg/sso/init1.h b/gcc/testsuite/gcc.dg/sso/init1.h
new file mode 100644
index 00000000000..a4232908af1
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/sso/init1.h
@@ -0,0 +1,12 @@
+struct __attribute__((scalar_storage_order("little-endian"))) R1
+{
+ int I;
+};
+
+struct __attribute__((scalar_storage_order("big-endian"))) R2
+{
+ int I;
+};
+
+struct R1 My_R1 = { 0x12345678 };
+struct R2 My_R2 = { 0x12345678 };
diff --git a/gcc/testsuite/gcc.dg/sso/init13.h b/gcc/testsuite/gcc.dg/sso/init13.h
new file mode 100644
index 00000000000..ee58972cfdd
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/sso/init13.h
@@ -0,0 +1,15 @@
+#define I (__extension__ 1.0iF)
+#define Pi 3.1415927f
+
+struct __attribute__((scalar_storage_order("little-endian"))) R1
+{
+ _Complex float F;
+};
+
+struct __attribute__((scalar_storage_order("big-endian"))) R2
+{
+ _Complex float F;
+};
+
+struct R1 My_R1 = { Pi - Pi * I };
+struct R2 My_R2 = { Pi - Pi * I };
diff --git a/gcc/testsuite/gcc.dg/sso/init2.h b/gcc/testsuite/gcc.dg/sso/init2.h
new file mode 100644
index 00000000000..766aef68057
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/sso/init2.h
@@ -0,0 +1,24 @@
+struct __attribute__((scalar_storage_order("little-endian"), packed)) R1
+{
+ unsigned S1 : 2;
+ unsigned I : 32;
+ unsigned S2 : 2;
+ unsigned A1 : 9;
+ unsigned A2 : 9;
+ unsigned A3 : 9;
+ unsigned B : 1;
+};
+
+struct __attribute__((scalar_storage_order("big-endian"), packed)) R2
+{
+ unsigned S1 : 2;
+ unsigned I : 32;
+ unsigned S2 : 2;
+ unsigned A1 : 9;
+ unsigned A2 : 9;
+ unsigned A3 : 9;
+ unsigned B : 1;
+};
+
+struct R1 My_R1 = { 2, 0x12345678, 1, 0xAB, 0xCD, 0xEF, 1 };
+struct R2 My_R2 = { 2, 0x12345678, 1, 0xAB, 0xCD, 0xEF, 1 };
diff --git a/gcc/testsuite/gcc.dg/sso/init3.h b/gcc/testsuite/gcc.dg/sso/init3.h
new file mode 100644
index 00000000000..4d4ecd0f326
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/sso/init3.h
@@ -0,0 +1,34 @@
+struct __attribute__((scalar_storage_order("little-endian"), packed)) Nested1
+{
+ unsigned C1 : 7;
+ unsigned C2 : 7;
+ unsigned C3 : 7;
+ unsigned B : 3;
+};
+
+struct __attribute__((scalar_storage_order("little-endian"), packed)) R1
+{
+ unsigned S1 : 6;
+ unsigned I : 32;
+ unsigned S2 : 2;
+ struct Nested1 N;
+};
+
+struct __attribute__((scalar_storage_order("big-endian"), packed)) Nested2
+{
+ unsigned C1 : 7;
+ unsigned C2 : 7;
+ unsigned C3 : 7;
+ unsigned B : 3;
+};
+
+struct __attribute__((scalar_storage_order("big-endian"), packed)) R2
+{
+ unsigned S1 : 6;
+ unsigned I : 32;
+ unsigned S2 : 2;
+ struct Nested2 N;
+};
+
+struct R1 My_R1 = { 2, 0x78ABCDEF, 1, { 0x12, 0x34, 0x56, 4 } };
+struct R2 My_R2 = { 2, 0x78ABCDEF, 1, { 0x12, 0x34, 0x56, 4 } };
diff --git a/gcc/testsuite/gcc.dg/sso/init4.h b/gcc/testsuite/gcc.dg/sso/init4.h
new file mode 100644
index 00000000000..4cd9f17e65d
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/sso/init4.h
@@ -0,0 +1,14 @@
+#define Pi 3.1415927f
+
+struct __attribute__((scalar_storage_order("little-endian"))) R1
+{
+ float F;
+};
+
+struct __attribute__((scalar_storage_order("big-endian"))) R2
+{
+ float F;
+};
+
+struct R1 My_R1 = { Pi };
+struct R2 My_R2 = { Pi };
diff --git a/gcc/testsuite/gcc.dg/sso/init5.h b/gcc/testsuite/gcc.dg/sso/init5.h
new file mode 100644
index 00000000000..04f50412320
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/sso/init5.h
@@ -0,0 +1,14 @@
+struct __attribute__((scalar_storage_order("little-endian"))) R1
+{
+ int I;
+ int A[3];
+};
+
+struct __attribute__((scalar_storage_order("big-endian"))) R2
+{
+ int I;
+ int A[3];
+};
+
+struct R1 My_R1 = { 0x12345678, { 0xAB0012, 0xCD0034, 0xEF0056 } };
+struct R2 My_R2 = { 0x12345678, { 0xAB0012, 0xCD0034, 0xEF0056 } };
diff --git a/gcc/testsuite/gcc.dg/sso/init6.h b/gcc/testsuite/gcc.dg/sso/init6.h
new file mode 100644
index 00000000000..4515aca8f3b
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/sso/init6.h
@@ -0,0 +1,24 @@
+struct __attribute__((scalar_storage_order("big-endian"))) Nested1
+{
+ int A[3];
+};
+
+struct __attribute__((scalar_storage_order("little-endian"))) R1
+{
+ int I;
+ struct Nested1 N;
+};
+
+struct __attribute__((scalar_storage_order("little-endian"))) Nested2
+{
+ int A[3];
+};
+
+struct __attribute__((scalar_storage_order("big-endian"))) R2
+{
+ int I;
+ struct Nested2 N;
+};
+
+struct R1 My_R1 = { 0x12345678, { { 0xAB0012, 0xCD0034, 0xEF0056 } } };
+struct R2 My_R2 = { 0x12345678, { { 0xAB0012, 0xCD0034, 0xEF0056 } } };
diff --git a/gcc/testsuite/gcc.dg/sso/init7.h b/gcc/testsuite/gcc.dg/sso/init7.h
new file mode 100644
index 00000000000..ac145ffcb5f
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/sso/init7.h
@@ -0,0 +1,28 @@
+struct __attribute__((scalar_storage_order("little-endian"))) Nested1
+{
+ int C1;
+ int C2;
+ int C3;
+};
+
+struct __attribute__((scalar_storage_order("little-endian"))) R1
+{
+ int I;
+ struct Nested1 N;
+};
+
+struct __attribute__((scalar_storage_order("big-endian"))) Nested2
+{
+ int C1;
+ int C2;
+ int C3;
+};
+
+struct __attribute__((scalar_storage_order("big-endian"))) R2
+{
+ int I;
+ struct Nested2 N;
+};
+
+struct R1 My_R1 = { 0x12345678, { 0xAB0012, 0xCD0034, 0xEF0056 } };
+struct R2 My_R2 = { 0x12345678, { 0xAB0012, 0xCD0034, 0xEF0056 } };
diff --git a/gcc/testsuite/gcc.dg/sso/init8.h b/gcc/testsuite/gcc.dg/sso/init8.h
new file mode 100644
index 00000000000..a273a78e718
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/sso/init8.h
@@ -0,0 +1,28 @@
+struct __attribute__((scalar_storage_order("big-endian"))) Nested1
+{
+ int C1;
+ int C2;
+ int C3;
+};
+
+struct __attribute__((scalar_storage_order("little-endian"))) R1
+{
+ int I;
+ struct Nested1 N;
+};
+
+struct __attribute__((scalar_storage_order("little-endian"))) Nested2
+{
+ int C1;
+ int C2;
+ int C3;
+};
+
+struct __attribute__((scalar_storage_order("big-endian"))) R2
+{
+ int I;
+ struct Nested2 N;
+};
+
+struct R1 My_R1 = { 0x12345678, { 0xAB0012, 0xCD0034, 0xEF0056 } };
+struct R2 My_R2 = { 0x12345678, { 0xAB0012, 0xCD0034, 0xEF0056 } };
diff --git a/gcc/testsuite/gcc.dg/sso/init9.h b/gcc/testsuite/gcc.dg/sso/init9.h
new file mode 100644
index 00000000000..358d3869ddc
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/sso/init9.h
@@ -0,0 +1,14 @@
+#define Pi 3.14159265358979323846
+
+struct __attribute__((scalar_storage_order("little-endian"))) R1
+{
+ double F;
+};
+
+struct __attribute__((scalar_storage_order("big-endian"))) R2
+{
+ double F;
+};
+
+struct R1 My_R1 = { Pi };
+struct R2 My_R2 = { Pi };
diff --git a/gcc/testsuite/gcc.dg/sso/p1.c b/gcc/testsuite/gcc.dg/sso/p1.c
new file mode 100644
index 00000000000..ab6ac5ae4b2
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/sso/p1.c
@@ -0,0 +1,64 @@
+/* { dg-do run } */
+
+#include <stdio.h>
+
+#include "init1.h"
+#include "dump.h"
+
+int main (void)
+{
+ struct R1 Local_R1;
+ struct R2 Local_R2;
+
+ put ("My_R1 :");
+ dump (&My_R1, sizeof (struct R1));
+ new_line ();
+ /* { dg-output "My_R1 : 78 56 34 12\n" } */
+
+ put ("My_R2 :");
+ dump (&My_R2, sizeof (struct R2));
+ new_line ();
+ /* { dg-output "My_R2 : 12 34 56 78\n" } */
+
+ Local_R1 = My_R1;
+ put ("Local_R1 :");
+ dump (&Local_R1, sizeof (struct R1));
+ new_line ();
+ /* { dg-output "Local_R1 : 78 56 34 12\n" } */
+
+ Local_R2 = My_R2;
+ put ("Local_R2 :");
+ dump (&Local_R2, sizeof (struct R2));
+ new_line ();
+ /* { dg-output "Local_R2 : 12 34 56 78\n" } */
+
+ Local_R1.I = 0x12345678;
+
+ put ("Local_R1 :");
+ dump (&Local_R1, sizeof (struct R1));
+ new_line ();
+ /* { dg-output "Local_R1 : 78 56 34 12\n" } */
+
+ Local_R2.I = 0x12345678;
+
+ put ("Local_R2 :");
+ dump (&Local_R2, sizeof (struct R2));
+ new_line ();
+ /* { dg-output "Local_R2 : 12 34 56 78\n" } */
+
+ Local_R1.I = Local_R2.I;
+
+ put ("Local_R1 :");
+ dump (&Local_R1, sizeof (struct R1));
+ new_line ();
+ /* { dg-output "Local_R1 : 78 56 34 12\n" } */
+
+ Local_R2.I = Local_R1.I;
+
+ put ("Local_R2 :");
+ dump (&Local_R2, sizeof (struct R2));
+ new_line ();
+ /* { dg-output "Local_R2 : 12 34 56 78\n" } */
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/sso/p13.c b/gcc/testsuite/gcc.dg/sso/p13.c
new file mode 100644
index 00000000000..08ecf292e44
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/sso/p13.c
@@ -0,0 +1,64 @@
+/* { dg-do run } */
+
+#include <stdio.h>
+
+#include "init13.h"
+#include "dump.h"
+
+int main (void)
+{
+ struct R1 Local_R1;
+ struct R2 Local_R2;
+
+ put ("My_R1 :");
+ dump (&My_R1, sizeof (struct R1));
+ new_line ();
+ /* { dg-output "My_R1 : db 0f 49 40 db 0f 49 c0\n" } */
+
+ put ("My_R2 :");
+ dump (&My_R2, sizeof (struct R2));
+ new_line ();
+ /* { dg-output "My_R2 : 40 49 0f db c0 49 0f db\n" } */
+
+ Local_R1 = My_R1;
+ put ("Local_R1 :");
+ dump (&Local_R1, sizeof (struct R1));
+ new_line ();
+ /* { dg-output "Local_R1 : db 0f 49 40 db 0f 49 c0\n" } */
+
+ Local_R2 = My_R2;
+ put ("Local_R2 :");
+ dump (&Local_R2, sizeof (struct R2));
+ new_line ();
+ /* { dg-output "Local_R2 : 40 49 0f db c0 49 0f db\n" } */
+
+ Local_R1.F = Pi - Pi * I;
+
+ put ("Local_R1 :");
+ dump (&Local_R1, sizeof (struct R1));
+ new_line ();
+ /* { dg-output "Local_R1 : db 0f 49 40 db 0f 49 c0\n" } */
+
+ Local_R2.F = Pi - Pi * I;
+
+ put ("Local_R2 :");
+ dump (&Local_R2, sizeof (struct R2));
+ new_line ();
+ /* { dg-output "Local_R2 : 40 49 0f db c0 49 0f db\n" } */
+
+ Local_R1.F = Local_R2.F;
+
+ put ("Local_R1 :");
+ dump (&Local_R1, sizeof (struct R1));
+ new_line ();
+ /* { dg-output "Local_R1 : db 0f 49 40 db 0f 49 c0\n" } */
+
+ Local_R2.F = Local_R1.F;
+
+ put ("Local_R2 :");
+ dump (&Local_R2, sizeof (struct R2));
+ new_line ();
+ /* { dg-output "Local_R2 : 40 49 0f db c0 49 0f db\n" } */
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/sso/p2.c b/gcc/testsuite/gcc.dg/sso/p2.c
new file mode 100644
index 00000000000..6d605379c15
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/sso/p2.c
@@ -0,0 +1,88 @@
+/* { dg-do run } */
+
+#include <stdio.h>
+
+#include "init2.h"
+#include "dump.h"
+
+int main (void)
+{
+ struct R1 Local_R1;
+ struct R2 Local_R2;
+
+ put ("My_R1 :");
+ dump (&My_R1, sizeof (struct R1));
+ new_line ();
+ /* { dg-output "My_R1 : e2 59 d1 48 b4 aa d9 bb\n" } */
+
+ put ("My_R2 :");
+ dump (&My_R2, sizeof (struct R2));
+ new_line ();
+ /* { dg-output "My_R2 : 84 8d 15 9e 15 5b 35 df\n" } */
+
+ Local_R1 = My_R1;
+ put ("Local_R1 :");
+ dump (&Local_R1, sizeof (struct R1));
+ new_line ();
+ /* { dg-output "Local_R1 : e2 59 d1 48 b4 aa d9 bb\n" } */
+
+ Local_R2 = My_R2;
+ put ("Local_R2 :");
+ dump (&Local_R2, sizeof (struct R2));
+ new_line ();
+ /* { dg-output "Local_R2 : 84 8d 15 9e 15 5b 35 df\n" } */
+
+ Local_R1.S1 = 2;
+ Local_R1.I = 0x12345678;
+ Local_R1.S2 = 1;
+ Local_R1.A1 = 0xAB;
+ Local_R1.A2 = 0xCD;
+ Local_R1.A3 = 0xEF;
+ Local_R1.B = 1;
+
+ put ("Local_R1 :");
+ dump (&Local_R1, sizeof (struct R1));
+ new_line ();
+ /* { dg-output "Local_R1 : e2 59 d1 48 b4 aa d9 bb\n" } */
+
+ Local_R2.S1 = 2;
+ Local_R2.I = 0x12345678;
+ Local_R2.S2 = 1;
+ Local_R2.A1 = 0xAB;
+ Local_R2.A2 = 0xCD;
+ Local_R2.A3 = 0xEF;
+ Local_R2.B = 1;
+
+ put ("Local_R2 :");
+ dump (&Local_R2, sizeof (struct R2));
+ new_line ();
+ /* { dg-output "Local_R2 : 84 8d 15 9e 15 5b 35 df\n" } */
+
+ Local_R1.S1 = Local_R2.S1;
+ Local_R1.I = Local_R2.I;
+ Local_R1.S2 = Local_R2.S2;
+ Local_R1.A1 = Local_R2.A1;
+ Local_R1.A2 = Local_R2.A2;
+ Local_R1.A3 = Local_R2.A3;
+ Local_R1.B = Local_R2.B;
+
+ put ("Local_R1 :");
+ dump (&Local_R1, sizeof (struct R1));
+ new_line ();
+ /* { dg-output "Local_R1 : e2 59 d1 48 b4 aa d9 bb\n" } */
+
+ Local_R2.S1 = Local_R1.S1;
+ Local_R2.I = Local_R1.I;
+ Local_R2.S2 = Local_R1.S2;
+ Local_R2.A1 = Local_R1.A1;
+ Local_R2.A2 = Local_R1.A2;
+ Local_R2.A3 = Local_R1.A3;
+ Local_R2.B = Local_R1.B;
+
+ put ("Local_R2 :");
+ dump (&Local_R2, sizeof (struct R2));
+ new_line ();
+ /* { dg-output "Local_R2 : 84 8d 15 9e 15 5b 35 df\n" } */
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/sso/p3.c b/gcc/testsuite/gcc.dg/sso/p3.c
new file mode 100644
index 00000000000..ce47dbd2443
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/sso/p3.c
@@ -0,0 +1,88 @@
+/* { dg-do run } */
+
+#include <stdio.h>
+
+#include "init3.h"
+#include "dump.h"
+
+int main (void)
+{
+ struct R1 Local_R1;
+ struct R2 Local_R2;
+
+ put ("My_R1 :");
+ dump (&My_R1, sizeof (struct R1));
+ new_line ();
+ /* { dg-output "My_R1 : c2 7b f3 2a 5e 12 9a 95\n" } */
+
+ put ("My_R2 :");
+ dump (&My_R2, sizeof (struct R2));
+ new_line ();
+ /* { dg-output "My_R2 : 09 e2 af 37 bd 24 d2 b4\n" } */
+
+ Local_R1 = My_R1;
+ put ("Local_R1 :");
+ dump (&Local_R1, sizeof (struct R1));
+ new_line ();
+ /* { dg-output "Local_R1 : c2 7b f3 2a 5e 12 9a 95\n" } */
+
+ Local_R2 = My_R2;
+ put ("Local_R2 :");
+ dump (&Local_R2, sizeof (struct R2));
+ new_line ();
+ /* { dg-output "Local_R2 : 09 e2 af 37 bd 24 d2 b4\n" } */
+
+ Local_R1.S1 = 2;
+ Local_R1.I = 0x78ABCDEF;
+ Local_R1.S2 = 1;
+ Local_R1.N.C1 = 0x12;
+ Local_R1.N.C2 = 0x34;
+ Local_R1.N.C3 = 0x56;
+ Local_R1.N.B = 4;
+
+ put ("Local_R1 :");
+ dump (&Local_R1, sizeof (struct R1));
+ new_line ();
+ /* { dg-output "Local_R1 : c2 7b f3 2a 5e 12 9a 95\n" } */
+
+ Local_R2.S1 = 2;
+ Local_R2.I = 0x78ABCDEF;
+ Local_R2.S2 = 1;
+ Local_R2.N.C1 = 0x12;
+ Local_R2.N.C2 = 0x34;
+ Local_R2.N.C3 = 0x56;
+ Local_R2.N.B = 4;
+
+ put ("Local_R2 :");
+ dump (&Local_R2, sizeof (struct R2));
+ new_line ();
+ /* { dg-output "Local_R2 : 09 e2 af 37 bd 24 d2 b4\n" } */
+
+ Local_R1.S1 = Local_R2.S1;
+ Local_R1.I = Local_R2.I;
+ Local_R1.S2 = Local_R2.S2;
+ Local_R1.N.C1 = Local_R2.N.C1;
+ Local_R1.N.C2 = Local_R2.N.C2;
+ Local_R1.N.C3 = Local_R2.N.C3;
+ Local_R1.N.B = Local_R2.N.B;
+
+ put ("Local_R1 :");
+ dump (&Local_R1, sizeof (struct R1));
+ new_line ();
+ /* { dg-output "Local_R1 : c2 7b f3 2a 5e 12 9a 95\n" } */
+
+ Local_R2.S1 = Local_R1.S1;
+ Local_R2.I = Local_R1.I;
+ Local_R2.S2 = Local_R1.S2;
+ Local_R2.N.C1 = Local_R1.N.C1;
+ Local_R2.N.C2 = Local_R1.N.C2;
+ Local_R2.N.C3 = Local_R1.N.C3;
+ Local_R2.N.B = Local_R1.N.B;
+
+ put ("Local_R2 :");
+ dump (&Local_R2, sizeof (struct R2));
+ new_line ();
+ /* { dg-output "Local_R2 : 09 e2 af 37 bd 24 d2 b4\n" } */
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/sso/p4.c b/gcc/testsuite/gcc.dg/sso/p4.c
new file mode 100644
index 00000000000..7d7224d9b30
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/sso/p4.c
@@ -0,0 +1,64 @@
+/* { dg-do run } */
+
+#include <stdio.h>
+
+#include "init4.h"
+#include "dump.h"
+
+int main (void)
+{
+ struct R1 Local_R1;
+ struct R2 Local_R2;
+
+ put ("My_R1 :");
+ dump (&My_R1, sizeof (struct R1));
+ new_line ();
+ /* { dg-output "My_R1 : db 0f 49 40\n" } */
+
+ put ("My_R2 :");
+ dump (&My_R2, sizeof (struct R2));
+ new_line ();
+ /* { dg-output "My_R2 : 40 49 0f db\n" } */
+
+ Local_R1 = My_R1;
+ put ("Local_R1 :");
+ dump (&Local_R1, sizeof (struct R1));
+ new_line ();
+ /* { dg-output "Local_R1 : db 0f 49 40\n" } */
+
+ Local_R2 = My_R2;
+ put ("Local_R2 :");
+ dump (&Local_R2, sizeof (struct R2));
+ new_line ();
+ /* { dg-output "Local_R2 : 40 49 0f db\n" } */
+
+ Local_R1.F = Pi;
+
+ put ("Local_R1 :");
+ dump (&Local_R1, sizeof (struct R1));
+ new_line ();
+ /* { dg-output "Local_R1 : db 0f 49 40\n" } */
+
+ Local_R2.F = Pi;
+
+ put ("Local_R2 :");
+ dump (&Local_R2, sizeof (struct R2));
+ new_line ();
+ /* { dg-output "Local_R2 : 40 49 0f db\n" } */
+
+ Local_R1.F = Local_R2.F;
+
+ put ("Local_R1 :");
+ dump (&Local_R1, sizeof (struct R1));
+ new_line ();
+ /* { dg-output "Local_R1 : db 0f 49 40\n" } */
+
+ Local_R2.F = Local_R1.F;
+
+ put ("Local_R2 :");
+ dump (&Local_R2, sizeof (struct R2));
+ new_line ();
+ /* { dg-output "Local_R2 : 40 49 0f db\n" } */
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/sso/p5.c b/gcc/testsuite/gcc.dg/sso/p5.c
new file mode 100644
index 00000000000..91bd6ba0a48
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/sso/p5.c
@@ -0,0 +1,74 @@
+/* { dg-do run } */
+
+#include <stdio.h>
+
+#include "init5.h"
+#include "dump.h"
+
+int main (void)
+{
+ struct R1 Local_R1;
+ struct R2 Local_R2;
+
+ put ("My_R1 :");
+ dump (&My_R1, sizeof (struct R1));
+ new_line ();
+ /* { dg-output "My_R1 : 78 56 34 12 12 00 ab 00 34 00 cd 00 56 00 ef 00\n" } */
+
+ put ("My_R2 :");
+ dump (&My_R2, sizeof (struct R2));
+ new_line ();
+ /* { dg-output "My_R2 : 12 34 56 78 00 ab 00 12 00 cd 00 34 00 ef 00 56\n" } */
+
+ Local_R1 = My_R1;
+ put ("Local_R1 :");
+ dump (&Local_R1, sizeof (struct R1));
+ new_line ();
+ /* { dg-output "Local_R1 : 78 56 34 12 12 00 ab 00 34 00 cd 00 56 00 ef 00\n" } */
+
+ Local_R2 = My_R2;
+ put ("Local_R2 :");
+ dump (&Local_R2, sizeof (struct R2));
+ new_line ();
+ /* { dg-output "Local_R2 : 12 34 56 78 00 ab 00 12 00 cd 00 34 00 ef 00 56\n" } */
+
+ Local_R1.I = 0x12345678;
+ Local_R1.A[0] = 0xAB0012;
+ Local_R1.A[1] = 0xCD0034;
+ Local_R1.A[2] = 0xEF0056;
+ put ("Local_R1 :");
+ dump (&Local_R1, sizeof (struct R1));
+ new_line ();
+ /* { dg-output "Local_R1 : 78 56 34 12 12 00 ab 00 34 00 cd 00 56 00 ef 00\n" } */
+
+ Local_R2.I = 0x12345678;
+ Local_R2.A[0] = 0xAB0012;
+ Local_R2.A[1] = 0xCD0034;
+ Local_R2.A[2] = 0xEF0056;
+ put ("Local_R2 :");
+ dump (&Local_R2, sizeof (struct R2));
+ new_line ();
+ /* { dg-output "Local_R2 : 12 34 56 78 00 ab 00 12 00 cd 00 34 00 ef 00 56\n" } */
+
+ Local_R1.I = Local_R2.I;
+ Local_R1.A[0] = Local_R2.A[0];
+ Local_R1.A[1] = Local_R2.A[1];
+ Local_R1.A[2] = Local_R2.A[2];
+
+ put ("Local_R1 :");
+ dump (&Local_R1, sizeof (struct R1));
+ new_line ();
+ /* { dg-output "Local_R1 : 78 56 34 12 12 00 ab 00 34 00 cd 00 56 00 ef 00\n" } */
+
+ Local_R2.I = Local_R1.I;
+ Local_R2.A[0] = Local_R1.A[0];
+ Local_R2.A[1] = Local_R1.A[1];
+ Local_R2.A[2] = Local_R1.A[2];
+
+ put ("Local_R2 :");
+ dump (&Local_R2, sizeof (struct R2));
+ new_line ();
+ /* { dg-output "Local_R2 : 12 34 56 78 00 ab 00 12 00 cd 00 34 00 ef 00 56\n" } */
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/sso/p6.c b/gcc/testsuite/gcc.dg/sso/p6.c
new file mode 100644
index 00000000000..8681c303c40
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/sso/p6.c
@@ -0,0 +1,74 @@
+/* { dg-do run } */
+
+#include <stdio.h>
+
+#include "init6.h"
+#include "dump.h"
+
+int main (void)
+{
+ struct R1 Local_R1;
+ struct R2 Local_R2;
+
+ put ("My_R1 :");
+ dump (&My_R1, sizeof (struct R1));
+ new_line ();
+ /* { dg-output "My_R1 : 78 56 34 12 00 ab 00 12 00 cd 00 34 00 ef 00 56\n" } */
+
+ put ("My_R2 :");
+ dump (&My_R2, sizeof (struct R2));
+ new_line ();
+ /* { dg-output "My_R2 : 12 34 56 78 12 00 ab 00 34 00 cd 00 56 00 ef 00\n" } */
+
+ Local_R1 = My_R1;
+ put ("Local_R1 :");
+ dump (&Local_R1, sizeof (struct R1));
+ new_line ();
+ /* { dg-output "Local_R1 : 78 56 34 12 00 ab 00 12 00 cd 00 34 00 ef 00 56\n" } */
+
+ Local_R2 = My_R2;
+ put ("Local_R2 :");
+ dump (&Local_R2, sizeof (struct R2));
+ new_line ();
+ /* { dg-output "Local_R2 : 12 34 56 78 12 00 ab 00 34 00 cd 00 56 00 ef 00\n" } */
+
+ Local_R1.I = 0x12345678;
+ Local_R1.N.A[0] = 0xAB0012;
+ Local_R1.N.A[1] = 0xCD0034;
+ Local_R1.N.A[2] = 0xEF0056;
+ put ("Local_R1 :");
+ dump (&Local_R1, sizeof (struct R1));
+ new_line ();
+ /* { dg-output "Local_R1 : 78 56 34 12 00 ab 00 12 00 cd 00 34 00 ef 00 56\n" } */
+
+ Local_R2.I = 0x12345678;
+ Local_R2.N.A[0] = 0xAB0012;
+ Local_R2.N.A[1] = 0xCD0034;
+ Local_R2.N.A[2] = 0xEF0056;
+ put ("Local_R2 :");
+ dump (&Local_R2, sizeof (struct R2));
+ new_line ();
+ /* { dg-output "Local_R2 : 12 34 56 78 12 00 ab 00 34 00 cd 00 56 00 ef 00\n" } */
+
+ Local_R1.I = Local_R2.I;
+ Local_R1.N.A[0] = Local_R2.N.A[0];
+ Local_R1.N.A[1] = Local_R2.N.A[1];
+ Local_R1.N.A[2] = Local_R2.N.A[2];
+
+ put ("Local_R1 :");
+ dump (&Local_R1, sizeof (struct R1));
+ new_line ();
+ /* { dg-output "Local_R1 : 78 56 34 12 00 ab 00 12 00 cd 00 34 00 ef 00 56\n" } */
+
+ Local_R2.I = Local_R1.I;
+ Local_R2.N.A[0] = Local_R1.N.A[0];
+ Local_R2.N.A[1] = Local_R1.N.A[1];
+ Local_R2.N.A[2] = Local_R1.N.A[2];
+
+ put ("Local_R2 :");
+ dump (&Local_R2, sizeof (struct R2));
+ new_line ();
+ /* { dg-output "Local_R2 : 12 34 56 78 12 00 ab 00 34 00 cd 00 56 00 ef 00\n" } */
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/sso/p7.c b/gcc/testsuite/gcc.dg/sso/p7.c
new file mode 100644
index 00000000000..e6bfa136574
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/sso/p7.c
@@ -0,0 +1,74 @@
+/* { dg-do run } */
+
+#include <stdio.h>
+
+#include "init7.h"
+#include "dump.h"
+
+int main (void)
+{
+ struct R1 Local_R1;
+ struct R2 Local_R2;
+
+ put ("My_R1 :");
+ dump (&My_R1, sizeof (struct R1));
+ new_line ();
+ /* { dg-output "My_R1 : 78 56 34 12 12 00 ab 00 34 00 cd 00 56 00 ef 00\n" } */
+
+ put ("My_R2 :");
+ dump (&My_R2, sizeof (struct R2));
+ new_line ();
+ /* { dg-output "My_R2 : 12 34 56 78 00 ab 00 12 00 cd 00 34 00 ef 00 56\n" } */
+
+ Local_R1 = My_R1;
+ put ("Local_R1 :");
+ dump (&Local_R1, sizeof (struct R1));
+ new_line ();
+ /* { dg-output "Local_R1 : 78 56 34 12 12 00 ab 00 34 00 cd 00 56 00 ef 00\n" } */
+
+ Local_R2 = My_R2;
+ put ("Local_R2 :");
+ dump (&Local_R2, sizeof (struct R2));
+ new_line ();
+ /* { dg-output "Local_R2 : 12 34 56 78 00 ab 00 12 00 cd 00 34 00 ef 00 56\n" } */
+
+ Local_R1.I = 0x12345678;
+ Local_R1.N.C1 = 0xAB0012;
+ Local_R1.N.C2 = 0xCD0034;
+ Local_R1.N.C3 = 0xEF0056;
+ put ("Local_R1 :");
+ dump (&Local_R1, sizeof (struct R1));
+ new_line ();
+ /* { dg-output "Local_R1 : 78 56 34 12 12 00 ab 00 34 00 cd 00 56 00 ef 00\n" } */
+
+ Local_R2.I = 0x12345678;
+ Local_R2.N.C1 = 0xAB0012;
+ Local_R2.N.C2 = 0xCD0034;
+ Local_R2.N.C3 = 0xEF0056;
+ put ("Local_R2 :");
+ dump (&Local_R2, sizeof (struct R2));
+ new_line ();
+ /* { dg-output "Local_R2 : 12 34 56 78 00 ab 00 12 00 cd 00 34 00 ef 00 56\n" } */
+
+ Local_R1.I = Local_R2.I;
+ Local_R1.N.C1 = Local_R2.N.C1;
+ Local_R1.N.C2 = Local_R2.N.C2;
+ Local_R1.N.C3 = Local_R2.N.C3;
+
+ put ("Local_R1 :");
+ dump (&Local_R1, sizeof (struct R1));
+ new_line ();
+ /* { dg-output "Local_R1 : 78 56 34 12 12 00 ab 00 34 00 cd 00 56 00 ef 00\n" } */
+
+ Local_R2.I = Local_R1.I;
+ Local_R2.N.C1 = Local_R1.N.C1;
+ Local_R2.N.C2 = Local_R1.N.C2;
+ Local_R2.N.C3 = Local_R1.N.C3;
+
+ put ("Local_R2 :");
+ dump (&Local_R2, sizeof (struct R2));
+ new_line ();
+ /* { dg-output "Local_R2 : 12 34 56 78 00 ab 00 12 00 cd 00 34 00 ef 00 56\n" } */
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/sso/p8.c b/gcc/testsuite/gcc.dg/sso/p8.c
new file mode 100644
index 00000000000..d2e7bd1b95d
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/sso/p8.c
@@ -0,0 +1,74 @@
+/* { dg-do run } */
+
+#include <stdio.h>
+
+#include "init8.h"
+#include "dump.h"
+
+int main (void)
+{
+ struct R1 Local_R1;
+ struct R2 Local_R2;
+
+ put ("My_R1 :");
+ dump (&My_R1, sizeof (struct R1));
+ new_line ();
+ /* { dg-output "My_R1 : 78 56 34 12 00 ab 00 12 00 cd 00 34 00 ef 00 56\n" } */
+
+ put ("My_R2 :");
+ dump (&My_R2, sizeof (struct R2));
+ new_line ();
+ /* { dg-output "My_R2 : 12 34 56 78 12 00 ab 00 34 00 cd 00 56 00 ef 00\n" } */
+
+ Local_R1 = My_R1;
+ put ("Local_R1 :");
+ dump (&Local_R1, sizeof (struct R1));
+ new_line ();
+ /* { dg-output "Local_R1 : 78 56 34 12 00 ab 00 12 00 cd 00 34 00 ef 00 56\n" } */
+
+ Local_R2 = My_R2;
+ put ("Local_R2 :");
+ dump (&Local_R2, sizeof (struct R2));
+ new_line ();
+ /* { dg-output "Local_R2 : 12 34 56 78 12 00 ab 00 34 00 cd 00 56 00 ef 00\n" } */
+
+ Local_R1.I = 0x12345678;
+ Local_R1.N.C1 = 0xAB0012;
+ Local_R1.N.C2 = 0xCD0034;
+ Local_R1.N.C3 = 0xEF0056;
+ put ("Local_R1 :");
+ dump (&Local_R1, sizeof (struct R1));
+ new_line ();
+ /* { dg-output "Local_R1 : 78 56 34 12 00 ab 00 12 00 cd 00 34 00 ef 00 56\n" } */
+
+ Local_R2.I = 0x12345678;
+ Local_R2.N.C1 = 0xAB0012;
+ Local_R2.N.C2 = 0xCD0034;
+ Local_R2.N.C3 = 0xEF0056;
+ put ("Local_R2 :");
+ dump (&Local_R2, sizeof (struct R2));
+ new_line ();
+ /* { dg-output "Local_R2 : 12 34 56 78 12 00 ab 00 34 00 cd 00 56 00 ef 00\n" } */
+
+ Local_R1.I = Local_R2.I;
+ Local_R1.N.C1 = Local_R2.N.C1;
+ Local_R1.N.C2 = Local_R2.N.C2;
+ Local_R1.N.C3 = Local_R2.N.C3;
+
+ put ("Local_R1 :");
+ dump (&Local_R1, sizeof (struct R1));
+ new_line ();
+ /* { dg-output "Local_R1 : 78 56 34 12 00 ab 00 12 00 cd 00 34 00 ef 00 56\n" } */
+
+ Local_R2.I = Local_R1.I;
+ Local_R2.N.C1 = Local_R1.N.C1;
+ Local_R2.N.C2 = Local_R1.N.C2;
+ Local_R2.N.C3 = Local_R1.N.C3;
+
+ put ("Local_R2 :");
+ dump (&Local_R2, sizeof (struct R2));
+ new_line ();
+ /* { dg-output "Local_R2 : 12 34 56 78 12 00 ab 00 34 00 cd 00 56 00 ef 00\n" } */
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/sso/p9.c b/gcc/testsuite/gcc.dg/sso/p9.c
new file mode 100644
index 00000000000..c3bee117cdc
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/sso/p9.c
@@ -0,0 +1,64 @@
+/* { dg-do run } */
+
+#include <stdio.h>
+
+#include "init9.h"
+#include "dump.h"
+
+int main (void)
+{
+ struct R1 Local_R1;
+ struct R2 Local_R2;
+
+ put ("My_R1 :");
+ dump (&My_R1, sizeof (struct R1));
+ new_line ();
+ /* { dg-output "My_R1 : 18 2d 44 54 fb 21 09 40\n" } */
+
+ put ("My_R2 :");
+ dump (&My_R2, sizeof (struct R2));
+ new_line ();
+ /* { dg-output "My_R2 : 40 09 21 fb 54 44 2d 18\n" } */
+
+ Local_R1 = My_R1;
+ put ("Local_R1 :");
+ dump (&Local_R1, sizeof (struct R1));
+ new_line ();
+ /* { dg-output "Local_R1 : 18 2d 44 54 fb 21 09 40\n" } */
+
+ Local_R2 = My_R2;
+ put ("Local_R2 :");
+ dump (&Local_R2, sizeof (struct R2));
+ new_line ();
+ /* { dg-output "Local_R2 : 40 09 21 fb 54 44 2d 18\n" } */
+
+ Local_R1.F = Pi;
+
+ put ("Local_R1 :");
+ dump (&Local_R1, sizeof (struct R1));
+ new_line ();
+ /* { dg-output "Local_R1 : 18 2d 44 54 fb 21 09 40\n" } */
+
+ Local_R2.F = Pi;
+
+ put ("Local_R2 :");
+ dump (&Local_R2, sizeof (struct R2));
+ new_line ();
+ /* { dg-output "Local_R2 : 40 09 21 fb 54 44 2d 18\n" } */
+
+ Local_R1.F = Local_R2.F;
+
+ put ("Local_R1 :");
+ dump (&Local_R1, sizeof (struct R1));
+ new_line ();
+ /* { dg-output "Local_R1 : 18 2d 44 54 fb 21 09 40\n" } */
+
+ Local_R2.F = Local_R1.F;
+
+ put ("Local_R2 :");
+ dump (&Local_R2, sizeof (struct R2));
+ new_line ();
+ /* { dg-output "Local_R2 : 40 09 21 fb 54 44 2d 18\n" } */
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/sso/q1.c b/gcc/testsuite/gcc.dg/sso/q1.c
new file mode 100644
index 00000000000..6da5a5f4533
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/sso/q1.c
@@ -0,0 +1,50 @@
+/* { dg-do run } */
+
+#include <stdio.h>
+
+#include "init1.h"
+#include "dump.h"
+
+#ifdef __cplusplus
+extern "C"
+#endif
+void abort (void);
+
+int main (void)
+{
+ struct R1 A1 = My_R1;
+ struct R1 B1 = My_R1;
+
+ struct R2 A2 = My_R2;
+ struct R2 B2 = My_R2;
+
+ put ("A1 :");
+ dump (&A1, sizeof (struct R1));
+ new_line ();
+ /* { dg-output "A1 : 78 56 34 12\n" } */
+
+ put ("B1 :");
+ dump (&B1, sizeof (struct R1));
+ new_line ();
+ /* { dg-output "B1 : 78 56 34 12\n" } */
+
+ put ("A2 :");
+ dump (&A2, sizeof (struct R2));
+ new_line ();
+ /* { dg-output "A2 : 12 34 56 78\n" } */
+
+ put ("B2 :");
+ dump (&B2, sizeof (struct R2));
+ new_line ();
+ /* { dg-output "B2 : 12 34 56 78\n" } */
+
+ if (A1.I != B1.I) abort ();
+
+ if (A1.I != 0x12345678) abort ();
+
+ if (A2.I != B2.I) abort ();
+
+ if (A2.I != 0x12345678) abort ();
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/sso/q13.c b/gcc/testsuite/gcc.dg/sso/q13.c
new file mode 100644
index 00000000000..ee34bb2289d
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/sso/q13.c
@@ -0,0 +1,50 @@
+/* { dg-do run } */
+
+#include <stdio.h>
+
+#include "init13.h"
+#include "dump.h"
+
+#ifdef __cplusplus
+extern "C"
+#endif
+void abort (void);
+
+int main (void)
+{
+ struct R1 A1 = My_R1;
+ struct R1 B1 = My_R1;
+
+ struct R2 A2 = My_R2;
+ struct R2 B2 = My_R2;
+
+ put ("A1 :");
+ dump (&A1, sizeof (struct R1));
+ new_line ();
+ /* { dg-output "A1 : db 0f 49 40 db 0f 49 c0\n" } */
+
+ put ("B1 :");
+ dump (&B1, sizeof (struct R1));
+ new_line ();
+ /* { dg-output "B1 : db 0f 49 40 db 0f 49 c0\n" } */
+
+ put ("A2 :");
+ dump (&A2, sizeof (struct R2));
+ new_line ();
+ /* { dg-output "A2 : 40 49 0f db c0 49 0f db\n" } */
+
+ put ("B2 :");
+ dump (&B2, sizeof (struct R2));
+ new_line ();
+ /* { dg-output "B2 : 40 49 0f db c0 49 0f db\n" } */
+
+ if (A1.F != B1.F) abort ();
+
+ if (A1.F != Pi - Pi * I) abort ();
+
+ if (A2.F != B2.F) abort ();
+
+ if (A2.F != Pi - Pi * I) abort ();
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/sso/q2.c b/gcc/testsuite/gcc.dg/sso/q2.c
new file mode 100644
index 00000000000..9e1d1d27ff3
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/sso/q2.c
@@ -0,0 +1,54 @@
+/* { dg-do run } */
+
+#include <stdio.h>
+
+#include "init2.h"
+#include "dump.h"
+
+#ifdef __cplusplus
+extern "C"
+#endif
+void abort (void);
+
+int main (void)
+{
+ struct R1 A1 = My_R1;
+ struct R1 B1 = My_R1;
+
+ struct R2 A2 = My_R2;
+ struct R2 B2 = My_R2;
+
+ put ("A1 :");
+ dump (&A1, sizeof (struct R1));
+ new_line ();
+ /* { dg-output "A1 : e2 59 d1 48 b4 aa d9 bb\n" } */
+
+ put ("B1 :");
+ dump (&B1, sizeof (struct R1));
+ new_line ();
+ /* { dg-output "B1 : e2 59 d1 48 b4 aa d9 bb\n" } */
+
+ put ("A2 :");
+ dump (&A2, sizeof (struct R2));
+ new_line ();
+ /* { dg-output "A2 : 84 8d 15 9e 15 5b 35 df\n" } */
+
+ put ("B2 :");
+ dump (&B2, sizeof (struct R2));
+ new_line ();
+ /* { dg-output "B2 : 84 8d 15 9e 15 5b 35 df\n" } */
+
+ if (A1.S1 != B1.S1) abort ();
+
+ if (A1.S1 != 2) abort ();
+
+ if (A2.S1 != B2.S1) abort ();
+
+ if (A2.S1 != 2) abort ();
+
+ if (A1.I != B1.I || A1.A1 != B1.A1) abort ();
+
+ if (A2.I != B2.I || A2.A1 != B2.A1) abort ();
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/sso/q3.c b/gcc/testsuite/gcc.dg/sso/q3.c
new file mode 100644
index 00000000000..6e72d7efc45
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/sso/q3.c
@@ -0,0 +1,54 @@
+/* { dg-do run } */
+
+#include <stdio.h>
+
+#include "init3.h"
+#include "dump.h"
+
+#ifdef __cplusplus
+extern "C"
+#endif
+void abort (void);
+
+int main (void)
+{
+ struct R1 A1 = My_R1;
+ struct R1 B1 = My_R1;
+
+ struct R2 A2 = My_R2;
+ struct R2 B2 = My_R2;
+
+ put ("A1 :");
+ dump (&A1, sizeof (struct R1));
+ new_line ();
+ /* { dg-output "A1 : c2 7b f3 2a 5e 12 9a 95\n" } */
+
+ put ("B1 :");
+ dump (&B1, sizeof (struct R1));
+ new_line ();
+ /* { dg-output "B1 : c2 7b f3 2a 5e 12 9a 95\n" } */
+
+ put ("A2 :");
+ dump (&A2, sizeof (struct R2));
+ new_line ();
+ /* { dg-output "A2 : 09 e2 af 37 bd 24 d2 b4\n" } */
+
+ put ("B2 :");
+ dump (&B2, sizeof (struct R2));
+ new_line ();
+ /* { dg-output "B2 : 09 e2 af 37 bd 24 d2 b4\n" } */
+
+ if (A1.S1 != B1.S1) abort ();
+
+ if (A1.S1 != 2) abort ();
+
+ if (A2.S1 != B2.S1) abort ();
+
+ if (A2.S1 != 2) abort ();
+
+ if (A1.I != B1.I || A1.N.C1 != B1.N.C1) abort ();
+
+ if (A2.I != B2.I || A2.N.C1 != B2.N.C1) abort ();
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/sso/q4.c b/gcc/testsuite/gcc.dg/sso/q4.c
new file mode 100644
index 00000000000..6966c8f7211
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/sso/q4.c
@@ -0,0 +1,50 @@
+/* { dg-do run } */
+
+#include <stdio.h>
+
+#include "init4.h"
+#include "dump.h"
+
+#ifdef __cplusplus
+extern "C"
+#endif
+void abort (void);
+
+int main (void)
+{
+ struct R1 A1 = My_R1;
+ struct R1 B1 = My_R1;
+
+ struct R2 A2 = My_R2;
+ struct R2 B2 = My_R2;
+
+ put ("A1 :");
+ dump (&A1, sizeof (struct R1));
+ new_line ();
+ /* { dg-output "A1 : db 0f 49 40\n" } */
+
+ put ("B1 :");
+ dump (&B1, sizeof (struct R1));
+ new_line ();
+ /* { dg-output "B1 : db 0f 49 40\n" } */
+
+ put ("A2 :");
+ dump (&A2, sizeof (struct R2));
+ new_line ();
+ /* { dg-output "A2 : 40 49 0f db\n" } */
+
+ put ("B2 :");
+ dump (&B2, sizeof (struct R2));
+ new_line ();
+ /* { dg-output "B2 : 40 49 0f db\n" } */
+
+ if (A1.F != B1.F) abort ();
+
+ if (A1.F != Pi) abort ();
+
+ if (A2.F != B2.F) abort ();
+
+ if (A2.F != Pi) abort ();
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/sso/q5.c b/gcc/testsuite/gcc.dg/sso/q5.c
new file mode 100644
index 00000000000..03dfdb7c35c
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/sso/q5.c
@@ -0,0 +1,46 @@
+/* { dg-do run } */
+
+#include <stdio.h>
+
+#include "init5.h"
+#include "dump.h"
+
+#ifdef __cplusplus
+extern "C"
+#endif
+void abort (void);
+
+int main (void)
+{
+ struct R1 A1 = My_R1;
+ struct R1 B1 = My_R1;
+
+ struct R2 A2 = My_R2;
+ struct R2 B2 = My_R2;
+
+ put ("A1 :");
+ dump (&A1, sizeof (struct R1));
+ new_line ();
+ /* { dg-output "A1 : 78 56 34 12 12 00 ab 00 34 00 cd 00 56 00 ef 00\n" } */
+
+ put ("B1 :");
+ dump (&B1, sizeof (struct R1));
+ new_line ();
+ /* { dg-output "B1 : 78 56 34 12 12 00 ab 00 34 00 cd 00 56 00 ef 00\n" } */
+
+ put ("A2 :");
+ dump (&A2, sizeof (struct R2));
+ new_line ();
+ /* { dg-output "A2 : 12 34 56 78 00 ab 00 12 00 cd 00 34 00 ef 00 56\n" } */
+
+ put ("B2 :");
+ dump (&B2, sizeof (struct R2));
+ new_line ();
+ /* { dg-output "B2 : 12 34 56 78 00 ab 00 12 00 cd 00 34 00 ef 00 56\n" } */
+
+ if (A1.I != B1.I || A1.A[0] != B1.A[0]) abort();
+
+ if (A2.I != B2.I || A2.A[0] != B2.A[0]) abort ();
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/sso/q6.c b/gcc/testsuite/gcc.dg/sso/q6.c
new file mode 100644
index 00000000000..1292f6af7bd
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/sso/q6.c
@@ -0,0 +1,45 @@
+/* { dg-do run } */
+
+#include <stdio.h>
+
+#include "init6.h"
+#include "dump.h"
+
+#ifdef __cplusplus
+extern "C"
+#endif
+void abort (void);
+
+int main (void)
+{
+ struct R1 A1 = My_R1;
+ struct R1 B1 = My_R1;
+
+ struct R2 A2 = My_R2;
+ struct R2 B2 = My_R2;
+
+ put ("A1 :");
+ dump (&A1, sizeof (struct R1));
+ new_line ();
+ /* { dg-output "A1 : 78 56 34 12 00 ab 00 12 00 cd 00 34 00 ef 00 56\n" } */
+
+ put ("B1 :");
+ dump (&B1, sizeof (struct R1));
+ new_line ();
+ /* { dg-output "B1 : 78 56 34 12 00 ab 00 12 00 cd 00 34 00 ef 00 56\n" } */
+ put ("A2 :");
+ dump (&A2, sizeof (struct R2));
+ new_line ();
+ /* { dg-output "A2 : 12 34 56 78 12 00 ab 00 34 00 cd 00 56 00 ef 00\n" } */
+
+ put ("B2 :");
+ dump (&B2, sizeof (struct R2));
+ new_line ();
+ /* { dg-output "B2 : 12 34 56 78 12 00 ab 00 34 00 cd 00 56 00 ef 00\n" } */
+
+ if (A1.I != B1.I || A1.N.A[0] != B1.N.A[0]) abort();
+
+ if (A2.I != B2.I || A2.N.A[0] != B2.N.A[0]) abort ();
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/sso/q7.c b/gcc/testsuite/gcc.dg/sso/q7.c
new file mode 100644
index 00000000000..c088f05a0c7
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/sso/q7.c
@@ -0,0 +1,46 @@
+/* { dg-do run } */
+
+#include <stdio.h>
+
+#include "init7.h"
+#include "dump.h"
+
+#ifdef __cplusplus
+extern "C"
+#endif
+void abort (void);
+
+int main (void)
+{
+ struct R1 A1 = My_R1;
+ struct R1 B1 = My_R1;
+
+ struct R2 A2 = My_R2;
+ struct R2 B2 = My_R2;
+
+ put ("A1 :");
+ dump (&A1, sizeof (struct R1));
+ new_line ();
+ /* { dg-output "A1 : 78 56 34 12 12 00 ab 00 34 00 cd 00 56 00 ef 00\n" } */
+
+ put ("B1 :");
+ dump (&B1, sizeof (struct R1));
+ new_line ();
+ /* { dg-output "B1 : 78 56 34 12 12 00 ab 00 34 00 cd 00 56 00 ef 00\n" } */
+
+ put ("A2 :");
+ dump (&A2, sizeof (struct R2));
+ new_line ();
+ /* { dg-output "A2 : 12 34 56 78 00 ab 00 12 00 cd 00 34 00 ef 00 56\n" } */
+
+ put ("B2 :");
+ dump (&B2, sizeof (struct R2));
+ new_line ();
+ /* { dg-output "B2 : 12 34 56 78 00 ab 00 12 00 cd 00 34 00 ef 00 56\n" } */
+
+ if (A1.I != B1.I || A1.N.C1 != B1.N.C1) abort();
+
+ if (A2.I != B2.I || A2.N.C1 != B2.N.C1) abort ();
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/sso/q8.c b/gcc/testsuite/gcc.dg/sso/q8.c
new file mode 100644
index 00000000000..108afc1822f
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/sso/q8.c
@@ -0,0 +1,46 @@
+/* { dg-do run } */
+
+#include <stdio.h>
+
+#include "init8.h"
+#include "dump.h"
+
+#ifdef __cplusplus
+extern "C"
+#endif
+void abort (void);
+
+int main (void)
+{
+ struct R1 A1 = My_R1;
+ struct R1 B1 = My_R1;
+
+ struct R2 A2 = My_R2;
+ struct R2 B2 = My_R2;
+
+ put ("A1 :");
+ dump (&A1, sizeof (struct R1));
+ new_line ();
+ /* { dg-output "A1 : 78 56 34 12 00 ab 00 12 00 cd 00 34 00 ef 00 56\n" } */
+
+ put ("B1 :");
+ dump (&B1, sizeof (struct R1));
+ new_line ();
+ /* { dg-output "B1 : 78 56 34 12 00 ab 00 12 00 cd 00 34 00 ef 00 56\n" } */
+
+ put ("A2 :");
+ dump (&A2, sizeof (struct R2));
+ new_line ();
+ /* { dg-output "A2 : 12 34 56 78 12 00 ab 00 34 00 cd 00 56 00 ef 00\n" } */
+
+ put ("B2 :");
+ dump (&B2, sizeof (struct R2));
+ new_line ();
+ /* { dg-output "B2 : 12 34 56 78 12 00 ab 00 34 00 cd 00 56 00 ef 00\n" } */
+
+ if (A1.I != B1.I || A1.N.C1 != B1.N.C1) abort();
+
+ if (A2.I != B2.I || A2.N.C1 != B2.N.C1) abort ();
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/sso/q9.c b/gcc/testsuite/gcc.dg/sso/q9.c
new file mode 100644
index 00000000000..ac6c8dd7f8f
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/sso/q9.c
@@ -0,0 +1,50 @@
+/* { dg-do run } */
+
+#include <stdio.h>
+
+#include "init9.h"
+#include "dump.h"
+
+#ifdef __cplusplus
+extern "C"
+#endif
+void abort (void);
+
+int main (void)
+{
+ struct R1 A1 = My_R1;
+ struct R1 B1 = My_R1;
+
+ struct R2 A2 = My_R2;
+ struct R2 B2 = My_R2;
+
+ put ("A1 :");
+ dump (&A1, sizeof (struct R1));
+ new_line ();
+ /* { dg-output "A1 : 18 2d 44 54 fb 21 09 40\n" } */
+
+ put ("B1 :");
+ dump (&B1, sizeof (struct R1));
+ new_line ();
+ /* { dg-output "B1 : 18 2d 44 54 fb 21 09 40\n" } */
+
+ put ("A2 :");
+ dump (&A2, sizeof (struct R2));
+ new_line ();
+ /* { dg-output "A2 : 40 09 21 fb 54 44 2d 18\n" } */
+
+ put ("B2 :");
+ dump (&B2, sizeof (struct R2));
+ new_line ();
+ /* { dg-output "B2 : 40 09 21 fb 54 44 2d 18\n" } */
+
+ if (A1.F != B1.F) abort ();
+
+ if (A1.F != Pi) abort ();
+
+ if (A2.F != B2.F) abort ();
+
+ if (A2.F != Pi) abort ();
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/sso/r3.c b/gcc/testsuite/gcc.dg/sso/r3.c
new file mode 100644
index 00000000000..82b55bda73b
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/sso/r3.c
@@ -0,0 +1,65 @@
+/* { dg-do run } */
+
+#include <stdio.h>
+
+#include "init3.h"
+#include "dump.h"
+
+#ifdef __cplusplus
+extern "C"
+#endif
+void abort (void);
+
+int Get_Elem1 (struct R1 R)
+{
+ struct R1 Tmp = R;
+ return Tmp.I;
+}
+
+void Set_Elem1 (struct R1 *R, int I)
+{
+ struct R1 Tmp = *R;
+ Tmp.I = I;
+ *R = Tmp;
+}
+
+int Get_Elem2 (struct R2 R)
+{
+ struct R2 Tmp = R;
+ return Tmp.I;
+}
+
+void Set_Elem2 (struct R2 *R, int I)
+{
+ struct R2 Tmp = *R;
+ Tmp.I = I;
+ *R = Tmp;
+}
+
+int main (void)
+{
+ struct R1 A1 = My_R1;
+ struct R2 A2 = My_R2;
+
+ put ("A1 :");
+ dump (&A1, sizeof (struct R1));
+ new_line ();
+ /* { dg-output "A1 : c2 7b f3 2a 5e 12 9a 95\n" } */
+
+ put ("A2 :");
+ dump (&A2, sizeof (struct R2));
+ new_line ();
+ /* { dg-output "A2 : 09 e2 af 37 bd 24 d2 b4\n" } */
+
+ if (Get_Elem1 (A1) != 0x78ABCDEF) abort ();
+
+ Set_Elem1 (&A1, 0xCD0034);
+ if (Get_Elem1 (A1) != 0xCD0034) abort ();
+
+ if (Get_Elem2 (A2) != 0x78ABCDEF) abort ();
+
+ Set_Elem2 (&A2, 0xCD0034);
+ if (Get_Elem2 (A2) != 0xCD0034) abort ();
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/sso/r5.c b/gcc/testsuite/gcc.dg/sso/r5.c
new file mode 100644
index 00000000000..6911408eb31
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/sso/r5.c
@@ -0,0 +1,65 @@
+/* { dg-do run } */
+
+#include <stdio.h>
+
+#include "init5.h"
+#include "dump.h"
+
+#ifdef __cplusplus
+extern "C"
+#endif
+void abort (void);
+
+int Get_Elem1 (struct R1 R)
+{
+ struct R1 Tmp = R;
+ return Tmp.A[0];
+}
+
+void Set_Elem1 (struct R1 *R, int I)
+{
+ struct R1 Tmp = *R;
+ Tmp.A[0] = I;
+ *R = Tmp;
+}
+
+int Get_Elem2 (struct R2 R)
+{
+ struct R2 Tmp = R;
+ return Tmp.A[0];
+}
+
+void Set_Elem2 (struct R2 *R, int I)
+{
+ struct R2 Tmp = *R;
+ Tmp.A[0] = I;
+ *R = Tmp;
+}
+
+int main (void)
+{
+ struct R1 A1 = My_R1;
+ struct R2 A2 = My_R2;
+
+ put ("A1 :");
+ dump (&A1, sizeof (struct R1));
+ new_line ();
+ /* { dg-output "A1 : 78 56 34 12 12 00 ab 00 34 00 cd 00 56 00 ef 00\n" } */
+
+ put ("A2 :");
+ dump (&A2, sizeof (struct R2));
+ new_line ();
+ /* { dg-output "A2 : 12 34 56 78 00 ab 00 12 00 cd 00 34 00 ef 00 56\n" } */
+
+ if (Get_Elem1 (A1) != 0xAB0012) abort ();
+
+ Set_Elem1 (&A1, 0xCD0034);
+ if (Get_Elem1 (A1) != 0xCD0034) abort ();
+
+ if (Get_Elem2 (A2) != 0xAB0012) abort ();
+
+ Set_Elem2 (&A2, 0xCD0034);
+ if (Get_Elem2 (A2) != 0xCD0034) abort ();
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/sso/r6.c b/gcc/testsuite/gcc.dg/sso/r6.c
new file mode 100644
index 00000000000..904dd5c0ac3
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/sso/r6.c
@@ -0,0 +1,65 @@
+/* { dg-do run } */
+
+#include <stdio.h>
+
+#include "init6.h"
+#include "dump.h"
+
+#ifdef __cplusplus
+extern "C"
+#endif
+void abort (void);
+
+int Get_Elem1 (struct R1 R)
+{
+ struct R1 Tmp = R;
+ return Tmp.N.A[0];
+}
+
+void Set_Elem1 (struct R1 *R, int I)
+{
+ struct R1 Tmp = *R;
+ Tmp.N.A[0] = I;
+ *R = Tmp;
+}
+
+int Get_Elem2 (struct R2 R)
+{
+ struct R2 Tmp = R;
+ return Tmp.N.A[0];
+}
+
+void Set_Elem2 (struct R2 *R, int I)
+{
+ struct R2 Tmp = *R;
+ Tmp.N.A[0] = I;
+ *R = Tmp;
+}
+
+int main (void)
+{
+ struct R1 A1 = My_R1;
+ struct R2 A2 = My_R2;
+
+ put ("A1 :");
+ dump (&A1, sizeof (struct R1));
+ new_line ();
+ /* { dg-output "A1 : 78 56 34 12 00 ab 00 12 00 cd 00 34 00 ef 00 56\n" } */
+
+ put ("A2 :");
+ dump (&A2, sizeof (struct R2));
+ new_line ();
+ /* { dg-output "A2 : 12 34 56 78 12 00 ab 00 34 00 cd 00 56 00 ef 00\n" } */
+
+ if (Get_Elem1 (A1) != 0xAB0012) abort ();
+
+ Set_Elem1 (&A1, 0xCD0034);
+ if (Get_Elem1 (A1) != 0xCD0034) abort ();
+
+ if (Get_Elem2 (A2) != 0xAB0012) abort ();
+
+ Set_Elem2 (&A2, 0xCD0034);
+ if (Get_Elem2 (A2) != 0xCD0034) abort ();
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/sso/r7.c b/gcc/testsuite/gcc.dg/sso/r7.c
new file mode 100644
index 00000000000..a6450eed8e3
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/sso/r7.c
@@ -0,0 +1,65 @@
+/* { dg-do run } */
+
+#include <stdio.h>
+
+#include "init7.h"
+#include "dump.h"
+
+#ifdef __cplusplus
+extern "C"
+#endif
+void abort (void);
+
+int Get_Elem1 (struct R1 R)
+{
+ struct R1 Tmp = R;
+ return Tmp.N.C1;
+}
+
+void Set_Elem1 (struct R1 *R, int I)
+{
+ struct R1 Tmp = *R;
+ Tmp.N.C1 = I;
+ *R = Tmp;
+}
+
+int Get_Elem2 (struct R2 R)
+{
+ struct R2 Tmp = R;
+ return Tmp.N.C1;
+}
+
+void Set_Elem2 (struct R2 *R, int I)
+{
+ struct R2 Tmp = *R;
+ Tmp.N.C1 = I;
+ *R = Tmp;
+}
+
+int main (void)
+{
+ struct R1 A1 = My_R1;
+ struct R2 A2 = My_R2;
+
+ put ("A1 :");
+ dump (&A1, sizeof (struct R1));
+ new_line ();
+ /* { dg-output "A1 : 78 56 34 12 12 00 ab 00 34 00 cd 00 56 00 ef 00\n" } */
+
+ put ("A2 :");
+ dump (&A2, sizeof (struct R2));
+ new_line ();
+ /* { dg-output "A2 : 12 34 56 78 00 ab 00 12 00 cd 00 34 00 ef 00 56\n" } */
+
+ if (Get_Elem1 (A1) != 0xAB0012) abort ();
+
+ Set_Elem1 (&A1, 0xCD0034);
+ if (Get_Elem1 (A1) != 0xCD0034) abort ();
+
+ if (Get_Elem2 (A2) != 0xAB0012) abort ();
+
+ Set_Elem2 (&A2, 0xCD0034);
+ if (Get_Elem2 (A2) != 0xCD0034) abort ();
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/sso/r8.c b/gcc/testsuite/gcc.dg/sso/r8.c
new file mode 100644
index 00000000000..448da504a7e
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/sso/r8.c
@@ -0,0 +1,65 @@
+/* { dg-do run } */
+
+#include <stdio.h>
+
+#include "init8.h"
+#include "dump.h"
+
+#ifdef __cplusplus
+extern "C"
+#endif
+void abort (void);
+
+int Get_Elem1 (struct R1 R)
+{
+ struct R1 Tmp = R;
+ return Tmp.N.C1;
+}
+
+void Set_Elem1 (struct R1 *R, int I)
+{
+ struct R1 Tmp = *R;
+ Tmp.N.C1 = I;
+ *R = Tmp;
+}
+
+int Get_Elem2 (struct R2 R)
+{
+ struct R2 Tmp = R;
+ return Tmp.N.C1;
+}
+
+void Set_Elem2 (struct R2 *R, int I)
+{
+ struct R2 Tmp = *R;
+ Tmp.N.C1 = I;
+ *R = Tmp;
+}
+
+int main (void)
+{
+ struct R1 A1 = My_R1;
+ struct R2 A2 = My_R2;
+
+ put ("A1 :");
+ dump (&A1, sizeof (struct R1));
+ new_line ();
+ /* { dg-output "A1 : 78 56 34 12 00 ab 00 12 00 cd 00 34 00 ef 00 56\n" } */
+
+ put ("A2 :");
+ dump (&A2, sizeof (struct R2));
+ new_line ();
+ /* { dg-output "A2 : 12 34 56 78 12 00 ab 00 34 00 cd 00 56 00 ef 00\n" } */
+
+ if (Get_Elem1 (A1) != 0xAB0012) abort ();
+
+ Set_Elem1 (&A1, 0xCD0034);
+ if (Get_Elem1 (A1) != 0xCD0034) abort ();
+
+ if (Get_Elem2 (A2) != 0xAB0012) abort ();
+
+ Set_Elem2 (&A2, 0xCD0034);
+ if (Get_Elem2 (A2) != 0xCD0034) abort ();
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/sso/s3.c b/gcc/testsuite/gcc.dg/sso/s3.c
new file mode 100644
index 00000000000..33a07c169bc
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/sso/s3.c
@@ -0,0 +1,79 @@
+/* { dg-do run } */
+
+#include <stdio.h>
+
+#include "init3.h"
+#include "dump.h"
+
+int main (void)
+{
+ struct R1 A1 = My_R1;
+ struct R2 A2 = My_R2;
+
+ struct Nested1 N1;
+ struct Nested2 N2;
+
+ unsigned C1;
+ unsigned C2;
+ unsigned C3;
+
+ put ("A1 :");
+ dump (&A1, sizeof (struct R1));
+ new_line ();
+ /* { dg-output "A1 : c2 7b f3 2a 5e 12 9a 95\n" } */
+
+ put ("A2 :");
+ dump (&A2, sizeof (struct R2));
+ new_line ();
+ /* { dg-output "A2 : 09 e2 af 37 bd 24 d2 b4\n" } */
+
+ N1 = A1.N;
+ C1 = N1.C1;
+ C2 = N1.C2;
+ C3 = N1.C3;
+
+ printf ("C1 : %d\n", C1);
+ /* { dg-output "C1 : 18\n" } */
+
+ printf ("C2 : %d\n", C2);
+ /* { dg-output "C2 : 52\n" } */
+
+ printf ("C3 : %d\n", C3);
+ /* { dg-output "C3 : 86\n" } */
+
+ N1.C1 = C1;
+ N1.C2 = C2;
+ N1.C3 = C3;
+ A1.N = N1;
+
+ N2 = A2.N;
+ C1 = N2.C1;
+ C2 = N2.C2;
+ C3 = N2.C3;
+
+ printf ("C1 : %d\n", C1);
+ /* { dg-output "C1 : 18\n" } */
+
+ printf ("C2 : %d\n", C2);
+ /* { dg-output "C2 : 52\n" } */
+
+ printf ("C3 : %d\n", C3);
+ /* { dg-output "C3 : 86\n" } */
+
+ N2.C1 = C1;
+ N2.C2 = C2;
+ N2.C3 = C3;
+ A2.N = N2;
+
+ put ("A1 :");
+ dump (&A1, sizeof (struct R1));
+ new_line ();
+ /* { dg-output "A1 : c2 7b f3 2a 5e 12 9a 95\n" } */
+
+ put ("A2 :");
+ dump (&A2, sizeof (struct R2));
+ new_line ();
+ /* { dg-output "A2 : 09 e2 af 37 bd 24 d2 b4\n" } */
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/sso/s5.c b/gcc/testsuite/gcc.dg/sso/s5.c
new file mode 100644
index 00000000000..f7f63befc46
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/sso/s5.c
@@ -0,0 +1,91 @@
+/* { dg-do run } */
+
+#include <stdio.h>
+
+#include "init5.h"
+#include "dump.h"
+
+#pragma GCC diagnostic ignored "-Wscalar-storage-order"
+
+int main (void)
+{
+ struct R1 A1 = My_R1;
+ struct R2 A2 = My_R2;
+
+ struct __attribute__((scalar_storage_order("little-endian"))) Nested1
+ {
+ int A[3];
+ };
+
+ struct __attribute__((scalar_storage_order("big-endian"))) Nested2
+ {
+ int A[3];
+ };
+
+ struct Nested1 N1;
+ struct Nested2 N2;
+
+ int C1;
+ int C2;
+ int C3;
+
+ put ("A1 :");
+ dump (&A1, sizeof (struct R1));
+ new_line ();
+ /* { dg-output "A1 : 78 56 34 12 12 00 ab 00 34 00 cd 00 56 00 ef 00\n" } */
+
+ put ("A2 :");
+ dump (&A2, sizeof (struct R2));
+ new_line ();
+ /* { dg-output "A2 : 12 34 56 78 00 ab 00 12 00 cd 00 34 00 ef 00 56\n" } */
+
+ __builtin_memcpy (N1.A, A1.A, sizeof (int) * 3);
+ C1 = N1.A[0];
+ C2 = N1.A[1];
+ C3 = N1.A[2];
+
+ printf ("C1 : %d\n", C1);
+ /* { dg-output "C1 : 11206674\n" } */
+
+ printf ("C2 : %d\n", C2);
+ /* { dg-output "C2 : 13434932\n" } */
+
+ printf ("C3 : %d\n", C3);
+ /* { dg-output "C3 : 15663190\n" } */
+
+ N1.A[0] = C1;
+ N1.A[1] = C2;
+ N1.A[2] = C3;
+ __builtin_memcpy (A1.A, N1.A, sizeof (int) * 3);
+
+ __builtin_memcpy (N2.A, A2.A, sizeof (int) * 3);
+ C1 = N2.A[0];
+ C2 = N2.A[1];
+ C3 = N2.A[2];
+
+ printf ("C1 : %d\n", C1);
+ /* { dg-output "C1 : 11206674\n" } */
+
+ printf ("C2 : %d\n", C2);
+ /* { dg-output "C2 : 13434932\n" } */
+
+ printf ("C3 : %d\n", C3);
+ /* { dg-output "C3 : 15663190\n" } */
+
+ N2.A[0] = C1;
+ N2.A[1] = C2;
+ N2.A[2] = C3;
+ __builtin_memcpy (A2.A, N2.A, sizeof (int) * 3);
+
+ put ("A1 :");
+ dump (&A1, sizeof (struct R1));
+ new_line ();
+ /* { dg-output "A1 : 78 56 34 12 12 00 ab 00 34 00 cd 00 56 00 ef 00\n" } */
+
+ put ("A2 :");
+ dump (&A2, sizeof (struct R2));
+ new_line ();
+ /* { dg-output "A2 : 12 34 56 78 00 ab 00 12 00 cd 00 34 00 ef 00 56\n" } */
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/sso/s6.c b/gcc/testsuite/gcc.dg/sso/s6.c
new file mode 100644
index 00000000000..acd8e3d0d95
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/sso/s6.c
@@ -0,0 +1,81 @@
+/* { dg-do run } */
+
+#include <stdio.h>
+
+#include "init6.h"
+#include "dump.h"
+
+#pragma GCC diagnostic ignored "-Wscalar-storage-order"
+
+int main (void)
+{
+ struct R1 A1 = My_R1;
+ struct R2 A2 = My_R2;
+
+ struct Nested1 N1;
+ struct Nested2 N2;
+
+ int C1;
+ int C2;
+ int C3;
+
+ put ("A1 :");
+ dump (&A1, sizeof (struct R1));
+ new_line ();
+ /* { dg-output "A1 : 78 56 34 12 00 ab 00 12 00 cd 00 34 00 ef 00 56\n" } */
+
+ put ("A2 :");
+ dump (&A2, sizeof (struct R2));
+ new_line ();
+ /* { dg-output "A2 : 12 34 56 78 12 00 ab 00 34 00 cd 00 56 00 ef 00\n" } */
+
+ __builtin_memcpy (N1.A, A1.N.A, sizeof (int) * 3);
+ C1 = N1.A[0];
+ C2 = N1.A[1];
+ C3 = N1.A[2];
+
+ printf ("C1 : %d\n", C1);
+ /* { dg-output "C1 : 11206674\n" } */
+
+ printf ("C2 : %d\n", C2);
+ /* { dg-output "C2 : 13434932\n" } */
+
+ printf ("C3 : %d\n", C3);
+ /* { dg-output "C3 : 15663190\n" } */
+
+ N1.A[0] = C1;
+ N1.A[1] = C2;
+ N1.A[2] = C3;
+ __builtin_memcpy (A1.N.A, N1.A, sizeof (int) * 3);
+
+ __builtin_memcpy (N2.A, A2.N.A, sizeof (int) * 3);
+ C1 = N2.A[0];
+ C2 = N2.A[1];
+ C3 = N2.A[2];
+
+ printf ("C1 : %d\n", C1);
+ /* { dg-output "C1 : 11206674\n" } */
+
+ printf ("C2 : %d\n", C2);
+ /* { dg-output "C2 : 13434932\n" } */
+
+ printf ("C3 : %d\n", C3);
+ /* { dg-output "C3 : 15663190\n" } */
+
+ N2.A[0] = C1;
+ N2.A[1] = C2;
+ N2.A[2] = C3;
+ __builtin_memcpy (A2.N.A, N2.A, sizeof (int) * 3);
+
+ put ("A1 :");
+ dump (&A1, sizeof (struct R1));
+ new_line ();
+ /* { dg-output "A1 : 78 56 34 12 00 ab 00 12 00 cd 00 34 00 ef 00 56\n" } */
+
+ put ("A2 :");
+ dump (&A2, sizeof (struct R2));
+ new_line ();
+ /* { dg-output "A2 : 12 34 56 78 12 00 ab 00 34 00 cd 00 56 00 ef 00\n" } */
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/sso/s7.c b/gcc/testsuite/gcc.dg/sso/s7.c
new file mode 100644
index 00000000000..88e074117da
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/sso/s7.c
@@ -0,0 +1,79 @@
+/* { dg-do run } */
+
+#include <stdio.h>
+
+#include "init7.h"
+#include "dump.h"
+
+int main (void)
+{
+ struct R1 A1 = My_R1;
+ struct R2 A2 = My_R2;
+
+ struct Nested1 N1;
+ struct Nested2 N2;
+
+ int C1;
+ int C2;
+ int C3;
+
+ put ("A1 :");
+ dump (&A1, sizeof (struct R1));
+ new_line ();
+ /* { dg-output "A1 : 78 56 34 12 12 00 ab 00 34 00 cd 00 56 00 ef 00\n" } */
+
+ put ("A2 :");
+ dump (&A2, sizeof (struct R2));
+ new_line ();
+ /* { dg-output "A2 : 12 34 56 78 00 ab 00 12 00 cd 00 34 00 ef 00 56\n" } */
+
+ N1 = A1.N;
+ C1 = N1.C1;
+ C2 = N1.C2;
+ C3 = N1.C3;
+
+ printf ("C1 : %d\n", C1);
+ /* { dg-output "C1 : 11206674\n" } */
+
+ printf ("C2 : %d\n", C2);
+ /* { dg-output "C2 : 13434932\n" } */
+
+ printf ("C3 : %d\n", C3);
+ /* { dg-output "C3 : 15663190\n" } */
+
+ N1.C1 = C1;
+ N1.C2 = C2;
+ N1.C3 = C3;
+ A1.N = N1;
+
+ N2 = A2.N;
+ C1 = N2.C1;
+ C2 = N2.C2;
+ C3 = N2.C3;
+
+ printf ("C1 : %d\n", C1);
+ /* { dg-output "C1 : 11206674\n" } */
+
+ printf ("C2 : %d\n", C2);
+ /* { dg-output "C2 : 13434932\n" } */
+
+ printf ("C3 : %d\n", C3);
+ /* { dg-output "C3 : 15663190\n" } */
+
+ N2.C1 = C1;
+ N2.C2 = C2;
+ N2.C3 = C3;
+ A2.N = N2;
+
+ put ("A1 :");
+ dump (&A1, sizeof (struct R1));
+ new_line ();
+ /* { dg-output "A1 : 78 56 34 12 12 00 ab 00 34 00 cd 00 56 00 ef 00\n" } */
+
+ put ("A2 :");
+ dump (&A2, sizeof (struct R2));
+ new_line ();
+ /* { dg-output "A2 : 12 34 56 78 00 ab 00 12 00 cd 00 34 00 ef 00 56\n" } */
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/sso/s8.c b/gcc/testsuite/gcc.dg/sso/s8.c
new file mode 100644
index 00000000000..1154da3b7f4
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/sso/s8.c
@@ -0,0 +1,79 @@
+/* { dg-do run } */
+
+#include <stdio.h>
+
+#include "init8.h"
+#include "dump.h"
+
+int main (void)
+{
+ struct R1 A1 = My_R1;
+ struct R2 A2 = My_R2;
+
+ struct Nested1 N1;
+ struct Nested2 N2;
+
+ int C1;
+ int C2;
+ int C3;
+
+ put ("A1 :");
+ dump (&A1, sizeof (struct R1));
+ new_line ();
+ /* { dg-output "A1 : 78 56 34 12 00 ab 00 12 00 cd 00 34 00 ef 00 56\n" } */
+
+ put ("A2 :");
+ dump (&A2, sizeof (struct R2));
+ new_line ();
+ /* { dg-output "A2 : 12 34 56 78 12 00 ab 00 34 00 cd 00 56 00 ef 00\n" } */
+
+ N1 = A1.N;
+ C1 = N1.C1;
+ C2 = N1.C2;
+ C3 = N1.C3;
+
+ printf ("C1 : %d\n", C1);
+ /* { dg-output "C1 : 11206674\n" } */
+
+ printf ("C2 : %d\n", C2);
+ /* { dg-output "C2 : 13434932\n" } */
+
+ printf ("C3 : %d\n", C3);
+ /* { dg-output "C3 : 15663190\n" } */
+
+ N1.C1 = C1;
+ N1.C2 = C2;
+ N1.C3 = C3;
+ A1.N = N1;
+
+ N2 = A2.N;
+ C1 = N2.C1;
+ C2 = N2.C2;
+ C3 = N2.C3;
+
+ printf ("C1 : %d\n", C1);
+ /* { dg-output "C1 : 11206674\n" } */
+
+ printf ("C2 : %d\n", C2);
+ /* { dg-output "C2 : 13434932\n" } */
+
+ printf ("C3 : %d\n", C3);
+ /* { dg-output "C3 : 15663190\n" } */
+
+ N2.C1 = C1;
+ N2.C2 = C2;
+ N2.C3 = C3;
+ A2.N = N2;
+
+ put ("A1 :");
+ dump (&A1, sizeof (struct R1));
+ new_line ();
+ /* { dg-output "A1 : 78 56 34 12 00 ab 00 12 00 cd 00 34 00 ef 00 56\n" } */
+
+ put ("A2 :");
+ dump (&A2, sizeof (struct R2));
+ new_line ();
+ /* { dg-output "A2 : 12 34 56 78 12 00 ab 00 34 00 cd 00 56 00 ef 00\n" } */
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/sso/sso.exp b/gcc/testsuite/gcc.dg/sso/sso.exp
new file mode 100644
index 00000000000..ae185d0d77e
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/sso/sso.exp
@@ -0,0 +1,40 @@
+# Copyright (C) 2013 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/>.
+
+# Load support procs.
+load_lib gcc-dg.exp
+load_lib torture-options.exp
+
+# Initialize `dg'.
+torture-init
+dg-init
+
+set SSO_TORTURE_OPTIONS [list \
+ { -O0 } \
+ { -O1 -fno-inline } \
+ { -O2 } \
+ { -O3 -finline-functions } \
+ { -Os } \
+ { -Og -g } ]
+
+set-torture-options $SSO_TORTURE_OPTIONS
+
+# Main loop.
+gcc-dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.c]] "" ""
+
+# All done.
+dg-finish
+torture-finish
diff --git a/gcc/testsuite/gcc.dg/sso/t1.c b/gcc/testsuite/gcc.dg/sso/t1.c
new file mode 100644
index 00000000000..6f7881ee0ed
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/sso/t1.c
@@ -0,0 +1,56 @@
+/* { dg-do run } */
+
+#include <stdio.h>
+
+#include "init1.h"
+#include "dump.h"
+
+int main (void)
+{
+ struct R1 Local_R1;
+ struct R2 Local_R2;
+
+ Local_R1.I = My_R1.I + 1;
+
+ put ("Local_R1 :");
+ dump (&Local_R1, sizeof (struct R1));
+ new_line ();
+ /* { dg-output "Local_R1 : 79 56 34 12\n" } */
+
+ Local_R2.I = My_R2.I + 1;
+
+ put ("Local_R2 :");
+ dump (&Local_R2, sizeof (struct R2));
+ new_line ();
+ /* { dg-output "Local_R2 : 12 34 56 79\n" } */
+
+ Local_R1.I = 0x12345678;
+
+ put ("Local_R1 :");
+ dump (&Local_R1, sizeof (struct R1));
+ new_line ();
+ /* { dg-output "Local_R1 : 78 56 34 12\n" } */
+
+ Local_R2.I = 0x12345678;
+
+ put ("Local_R2 :");
+ dump (&Local_R2, sizeof (struct R2));
+ new_line ();
+ /* { dg-output "Local_R2 : 12 34 56 78\n" } */
+
+ Local_R1.I = Local_R1.I + 1;
+
+ put ("Local_R1 :");
+ dump (&Local_R1, sizeof (struct R1));
+ new_line ();
+ /* { dg-output "Local_R1 : 79 56 34 12\n" } */
+
+ Local_R2.I = Local_R2.I + 1;
+
+ put ("Local_R2 :");
+ dump (&Local_R2, sizeof (struct R2));
+ new_line ();
+ /* { dg-output "Local_R2 : 12 34 56 79\n" } */
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/sso/t13.c b/gcc/testsuite/gcc.dg/sso/t13.c
new file mode 100644
index 00000000000..a0f43413449
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/sso/t13.c
@@ -0,0 +1,56 @@
+/* { dg-do run } */
+
+#include <stdio.h>
+
+#include "init13.h"
+#include "dump.h"
+
+int main (void)
+{
+ struct R1 Local_R1;
+ struct R2 Local_R2;
+
+ Local_R1.F = My_R1.F + (1.0f + 1.0f * I);
+
+ put ("Local_R1 :");
+ dump (&Local_R1, sizeof (struct R1));
+ new_line ();
+ /* { dg-output "Local_R1 : ee 87 84 40 db 0f 09 c0\n" } */
+
+ Local_R2.F = My_R2.F + (1.0f + 1.0f * I);
+
+ put ("Local_R2 :");
+ dump (&Local_R2, sizeof (struct R2));
+ new_line ();
+ /* { dg-output "Local_R2 : 40 84 87 ee c0 09 0f db\n" } */
+
+ Local_R1.F = Pi - Pi * I;
+
+ put ("Local_R1 :");
+ dump (&Local_R1, sizeof (struct R1));
+ new_line ();
+ /* { dg-output "Local_R1 : db 0f 49 40 db 0f 49 c0\n" } */
+
+ Local_R2.F = Pi - Pi * I;
+
+ put ("Local_R2 :");
+ dump (&Local_R2, sizeof (struct R2));
+ new_line ();
+ /* { dg-output "Local_R2 : 40 49 0f db c0 49 0f db\n" } */
+
+ Local_R1.F = Local_R1.F + (1.0f + 1.0f * I);
+
+ put ("Local_R1 :");
+ dump (&Local_R1, sizeof (struct R1));
+ new_line ();
+ /* { dg-output "Local_R1 : ee 87 84 40 db 0f 09 c0\n" } */
+
+ Local_R2.F = Local_R2.F + (1.0f + 1.0f * I);
+
+ put ("Local_R2 :");
+ dump (&Local_R2, sizeof (struct R2));
+ new_line ();
+ /* { dg-output "Local_R2 : 40 84 87 ee c0 09 0f db\n" } */
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/sso/t2.c b/gcc/testsuite/gcc.dg/sso/t2.c
new file mode 100644
index 00000000000..816363284db
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/sso/t2.c
@@ -0,0 +1,92 @@
+/* { dg-do run } */
+
+#include <stdio.h>
+
+#include "init2.h"
+#include "dump.h"
+
+int main (void)
+{
+ struct R1 Local_R1;
+ struct R2 Local_R2;
+
+ Local_R1.S1 = My_R1.S1 - 1;
+ Local_R1.I = My_R1.I + 1;
+ Local_R1.S2 = My_R1.S2 - 1;
+ Local_R1.A1 = My_R1.A1 % 16;
+ Local_R1.A2 = My_R1.A2 % 16;
+ Local_R1.A3 = My_R1.A3 % 16;
+ Local_R1.B = !My_R1.B;
+
+ put ("Local_R1 :");
+ dump (&Local_R1, sizeof (struct R1));
+ new_line ();
+ /* { dg-output "Local_R1 : e5 59 d1 48 b0 a0 c1 03\n" } */
+
+ Local_R2.S1 = My_R2.S1 - 1;
+ Local_R2.I = My_R2.I + 1;
+ Local_R2.S2 = My_R2.S2 - 1;
+ Local_R2.A1 = My_R2.A1 % 16;
+ Local_R2.A2 = My_R2.A2 % 16;
+ Local_R2.A3 = My_R2.A3 % 16;
+ Local_R2.B = !My_R2.B;
+
+ put ("Local_R2 :");
+ dump (&Local_R2, sizeof (struct R2));
+ new_line ();
+ /* { dg-output "Local_R2 : 44 8d 15 9e 40 58 34 1e\n" } */
+
+ Local_R1.S1 = 2;
+ Local_R1.I = 0x12345678;
+ Local_R1.S2 = 1;
+ Local_R1.A1 = 0xAB;
+ Local_R1.A2 = 0xCD;
+ Local_R1.A3 = 0xEF;
+ Local_R1.B = 1;
+
+ put ("Local_R1 :");
+ dump (&Local_R1, sizeof (struct R1));
+ new_line ();
+ /* { dg-output "Local_R1 : e2 59 d1 48 b4 aa d9 bb\n" } */
+
+ Local_R2.S1 = 2;
+ Local_R2.I = 0x12345678;
+ Local_R2.S2 = 1;
+ Local_R2.A1 = 0xAB;
+ Local_R2.A2 = 0xCD;
+ Local_R2.A3 = 0xEF;
+ Local_R2.B = 1;
+
+ put ("Local_R2 :");
+ dump (&Local_R2, sizeof (struct R2));
+ new_line ();
+ /* { dg-output "Local_R2 : 84 8d 15 9e 15 5b 35 df\n" } */
+
+ Local_R1.S1 = Local_R1.S1 - 1;
+ Local_R1.I = Local_R1.I + 1;
+ Local_R1.S2 = Local_R1.S2 - 1;
+ Local_R1.A1 = Local_R1.A1 % 16;
+ Local_R1.A2 = Local_R1.A2 % 16;
+ Local_R1.A3 = Local_R1.A3 % 16;
+ Local_R1.B = !Local_R1.B;
+
+ put ("Local_R1 :");
+ dump (&Local_R1, sizeof (struct R1));
+ new_line ();
+ /* { dg-output "Local_R1 : e5 59 d1 48 b0 a0 c1 03\n" } */
+
+ Local_R2.S1 = Local_R2.S1 - 1;
+ Local_R2.I = Local_R2.I + 1;
+ Local_R2.S2 = Local_R2.S2 - 1;
+ Local_R2.A1 = Local_R2.A1 % 16;
+ Local_R2.A2 = Local_R2.A2 % 16;
+ Local_R2.A3 = Local_R2.A3 % 16;
+ Local_R2.B = !Local_R2.B;
+
+ put ("Local_R2 :");
+ dump (&Local_R2, sizeof (struct R2));
+ new_line ();
+ /* { dg-output "Local_R2 : 44 8d 15 9e 40 58 34 1e\n" } */
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/sso/t3.c b/gcc/testsuite/gcc.dg/sso/t3.c
new file mode 100644
index 00000000000..e2f40704724
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/sso/t3.c
@@ -0,0 +1,92 @@
+/* { dg-do run } */
+
+#include <stdio.h>
+
+#include "init3.h"
+#include "dump.h"
+
+int main (void)
+{
+ struct R1 Local_R1;
+ struct R2 Local_R2;
+
+ Local_R1.S1 = My_R1.S1 - 1;
+ Local_R1.I = My_R1.I + 1;
+ Local_R1.S2 = My_R1.S2 - 1;
+ Local_R1.N.C1 = My_R1.N.C1 % 16;
+ Local_R1.N.C2 = My_R1.N.C2 % 16;
+ Local_R1.N.C3 = My_R1.N.C3 % 16;
+ Local_R1.N.B = My_R1.N.B % 2;
+
+ put ("Local_R1 :");
+ dump (&Local_R1, sizeof (struct R1));
+ new_line ();
+ /* { dg-output "Local_R1 : 01 7c f3 2a 1e 02 82 01\n" } */
+
+ Local_R2.S1 = My_R2.S1 - 1;
+ Local_R2.I = My_R2.I + 1;
+ Local_R2.S2 = My_R2.S2 - 1;
+ Local_R2.N.C1 = My_R2.N.C1 % 16;
+ Local_R2.N.C2 = My_R2.N.C2 % 16;
+ Local_R2.N.C3 = My_R2.N.C3 % 16;
+ Local_R2.N.B = My_R2.N.B % 2;
+
+ put ("Local_R2 :");
+ dump (&Local_R2, sizeof (struct R2));
+ new_line ();
+ /* { dg-output "Local_R2 : 05 e2 af 37 c0 04 10 30\n" } */
+
+ Local_R1.S1 = 2;
+ Local_R1.I = 0x78ABCDEF;
+ Local_R1.S2 = 1;
+ Local_R1.N.C1 = 0x12;
+ Local_R1.N.C2 = 0x34;
+ Local_R1.N.C3 = 0x56;
+ Local_R1.N.B = 4;
+
+ put ("Local_R1 :");
+ dump (&Local_R1, sizeof (struct R1));
+ new_line ();
+ /* { dg-output "Local_R1 : c2 7b f3 2a 5e 12 9a 95\n" } */
+
+ Local_R2.S1 = 2;
+ Local_R2.I = 0x78ABCDEF;
+ Local_R2.S2 = 1;
+ Local_R2.N.C1 = 0x12;
+ Local_R2.N.C2 = 0x34;
+ Local_R2.N.C3 = 0x56;
+ Local_R2.N.B = 4;
+
+ put ("Local_R2 :");
+ dump (&Local_R2, sizeof (struct R2));
+ new_line ();
+ /* { dg-output "Local_R2 : 09 e2 af 37 bd 24 d2 b4\n" } */
+
+ Local_R1.S1 = Local_R1.S1 - 1;
+ Local_R1.I = Local_R1.I + 1;
+ Local_R1.S2 = Local_R1.S2 - 1;
+ Local_R1.N.C1 = Local_R1.N.C1 % 16;
+ Local_R1.N.C2 = Local_R1.N.C2 % 16;
+ Local_R1.N.C3 = Local_R1.N.C3 % 16;
+ Local_R1.N.B = Local_R1.N.B % 2;
+
+ put ("Local_R1 :");
+ dump (&Local_R1, sizeof (struct R1));
+ new_line ();
+ /* { dg-output "Local_R1 : 01 7c f3 2a 1e 02 82 01\n" } */
+
+ Local_R2.S1 = Local_R2.S1 - 1;
+ Local_R2.I = Local_R2.I + 1;
+ Local_R2.S2 = Local_R2.S2 - 1;
+ Local_R2.N.C1 = Local_R2.N.C1 % 16;
+ Local_R2.N.C2 = Local_R2.N.C2 % 16;
+ Local_R2.N.C3 = Local_R2.N.C3 % 16;
+ Local_R2.N.B = Local_R2.N.B % 2;
+
+ put ("Local_R2 :");
+ dump (&Local_R2, sizeof (struct R2));
+ new_line ();
+ /* { dg-output "Local_R2 : 05 e2 af 37 c0 04 10 30\n" } */
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/sso/t4.c b/gcc/testsuite/gcc.dg/sso/t4.c
new file mode 100644
index 00000000000..f5a7eb01627
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/sso/t4.c
@@ -0,0 +1,56 @@
+/* { dg-do run } */
+
+#include <stdio.h>
+
+#include "init4.h"
+#include "dump.h"
+
+int main (void)
+{
+ struct R1 Local_R1;
+ struct R2 Local_R2;
+
+ Local_R1.F = My_R1.F + 1.0f;
+
+ put ("Local_R1 :");
+ dump (&Local_R1, sizeof (struct R1));
+ new_line ();
+ /* { dg-output "Local_R1 : ee 87 84 40\n" } */
+
+ Local_R2.F = My_R2.F + 1.0f;
+
+ put ("Local_R2 :");
+ dump (&Local_R2, sizeof (struct R2));
+ new_line ();
+ /* { dg-output "Local_R2 : 40 84 87 ee\n" } */
+
+ Local_R1.F = Pi;
+
+ put ("Local_R1 :");
+ dump (&Local_R1, sizeof (struct R1));
+ new_line ();
+ /* { dg-output "Local_R1 : db 0f 49 40\n" } */
+
+ Local_R2.F = Pi;
+
+ put ("Local_R2 :");
+ dump (&Local_R2, sizeof (struct R2));
+ new_line ();
+ /* { dg-output "Local_R2 : 40 49 0f db\n" } */
+
+ Local_R1.F = Local_R1.F + 1.0f;
+
+ put ("Local_R1 :");
+ dump (&Local_R1, sizeof (struct R1));
+ new_line ();
+ /* { dg-output "Local_R1 : ee 87 84 40\n" } */
+
+ Local_R2.F = Local_R2.F + 1.0f;
+
+ put ("Local_R2 :");
+ dump (&Local_R2, sizeof (struct R2));
+ new_line ();
+ /* { dg-output "Local_R2 : 40 84 87 ee\n" } */
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/sso/t5.c b/gcc/testsuite/gcc.dg/sso/t5.c
new file mode 100644
index 00000000000..7cefb203dd8
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/sso/t5.c
@@ -0,0 +1,72 @@
+/* { dg-do run } */
+
+#include <stdio.h>
+
+#include "init5.h"
+#include "dump.h"
+
+int main (void)
+{
+ struct R1 Local_R1;
+ struct R2 Local_R2;
+
+ Local_R1.I = My_R1.I + 1;
+ Local_R1.A[0] = My_R1.A[0] + 1;
+ Local_R1.A[1] = My_R1.A[1] + 1;
+ Local_R1.A[2] = My_R1.A[2] + 1;
+
+ put ("Local_R1 :");
+ dump (&Local_R1, sizeof (struct R1));
+ new_line ();
+ /* { dg-output "Local_R1 : 79 56 34 12 13 00 ab 00 35 00 cd 00 57 00 ef 00\n" } */
+
+ Local_R2.I = My_R2.I + 1;
+ Local_R2.A[0] = My_R2.A[0] + 1;
+ Local_R2.A[1] = My_R2.A[1] + 1;
+ Local_R2.A[2] = My_R2.A[2] + 1;
+
+ put ("Local_R2 :");
+ dump (&Local_R2, sizeof (struct R2));
+ new_line ();
+ /* { dg-output "Local_R2 : 12 34 56 79 00 ab 00 13 00 cd 00 35 00 ef 00 57\n" } */
+
+ Local_R1.I = 0x12345678;
+ Local_R1.A[0] = 0xAB0012;
+ Local_R1.A[1] = 0xCD0034;
+ Local_R1.A[2] = 0xEF0056;
+ put ("Local_R1 :");
+ dump (&Local_R1, sizeof (struct R1));
+ new_line ();
+ /* { dg-output "Local_R1 : 78 56 34 12 12 00 ab 00 34 00 cd 00 56 00 ef 00\n" } */
+
+ Local_R2.I = 0x12345678;
+ Local_R2.A[0] = 0xAB0012;
+ Local_R2.A[1] = 0xCD0034;
+ Local_R2.A[2] = 0xEF0056;
+ put ("Local_R2 :");
+ dump (&Local_R2, sizeof (struct R2));
+ new_line ();
+ /* { dg-output "Local_R2 : 12 34 56 78 00 ab 00 12 00 cd 00 34 00 ef 00 56\n" } */
+
+ Local_R1.I = Local_R1.I + 1;
+ Local_R1.A[0] = Local_R1.A[0] + 1;
+ Local_R1.A[1] = Local_R1.A[1] + 1;
+ Local_R1.A[2] = Local_R1.A[2] + 1;
+
+ put ("Local_R1 :");
+ dump (&Local_R1, sizeof (struct R1));
+ new_line ();
+ /* { dg-output "Local_R1 : 79 56 34 12 13 00 ab 00 35 00 cd 00 57 00 ef 00\n" } */
+
+ Local_R2.I = Local_R2.I + 1;
+ Local_R2.A[0] = Local_R2.A[0] + 1;
+ Local_R2.A[1] = Local_R2.A[1] + 1;
+ Local_R2.A[2] = Local_R2.A[2] + 1;
+
+ put ("Local_R2 :");
+ dump (&Local_R2, sizeof (struct R2));
+ new_line ();
+ /* { dg-output "Local_R2 : 12 34 56 79 00 ab 00 13 00 cd 00 35 00 ef 00 57\n" } */
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/sso/t6.c b/gcc/testsuite/gcc.dg/sso/t6.c
new file mode 100644
index 00000000000..8fb550b0ff1
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/sso/t6.c
@@ -0,0 +1,72 @@
+/* { dg-do run } */
+
+#include <stdio.h>
+
+#include "init6.h"
+#include "dump.h"
+
+int main (void)
+{
+ struct R1 Local_R1;
+ struct R2 Local_R2;
+
+ Local_R1.I = My_R1.I + 1;
+ Local_R1.N.A[0] = My_R1.N.A[0] + 1;
+ Local_R1.N.A[1] = My_R1.N.A[1] + 1;
+ Local_R1.N.A[2] = My_R1.N.A[2] + 1;
+
+ put ("Local_R1 :");
+ dump (&Local_R1, sizeof (struct R1));
+ new_line ();
+ /* { dg-output "Local_R1 : 79 56 34 12 00 ab 00 13 00 cd 00 35 00 ef 00 57\n" } */
+
+ Local_R2.I = My_R2.I + 1;
+ Local_R2.N.A[0] = My_R2.N.A[0] + 1;
+ Local_R2.N.A[1] = My_R2.N.A[1] + 1;
+ Local_R2.N.A[2] = My_R2.N.A[2] + 1;
+
+ put ("Local_R2 :");
+ dump (&Local_R2, sizeof (struct R2));
+ new_line ();
+ /* { dg-output "Local_R2 : 12 34 56 79 13 00 ab 00 35 00 cd 00 57 00 ef 00\n" } */
+
+ Local_R1.I = 0x12345678;
+ Local_R1.N.A[0] = 0xAB0012;
+ Local_R1.N.A[1] = 0xCD0034;
+ Local_R1.N.A[2] = 0xEF0056;
+ put ("Local_R1 :");
+ dump (&Local_R1, sizeof (struct R1));
+ new_line ();
+ /* { dg-output "Local_R1 : 78 56 34 12 00 ab 00 12 00 cd 00 34 00 ef 00 56\n" } */
+
+ Local_R2.I = 0x12345678;
+ Local_R2.N.A[0] = 0xAB0012;
+ Local_R2.N.A[1] = 0xCD0034;
+ Local_R2.N.A[2] = 0xEF0056;
+ put ("Local_R2 :");
+ dump (&Local_R2, sizeof (struct R2));
+ new_line ();
+ /* { dg-output "Local_R2 : 12 34 56 78 12 00 ab 00 34 00 cd 00 56 00 ef 00\n" } */
+
+ Local_R1.I = Local_R1.I + 1;
+ Local_R1.N.A[0] = Local_R1.N.A[0] + 1;
+ Local_R1.N.A[1] = Local_R1.N.A[1] + 1;
+ Local_R1.N.A[2] = Local_R1.N.A[2] + 1;
+
+ put ("Local_R1 :");
+ dump (&Local_R1, sizeof (struct R1));
+ new_line ();
+ /* { dg-output "Local_R1 : 79 56 34 12 00 ab 00 13 00 cd 00 35 00 ef 00 57\n" } */
+
+ Local_R2.I = Local_R2.I + 1;
+ Local_R2.N.A[0] = Local_R2.N.A[0] + 1;
+ Local_R2.N.A[1] = Local_R2.N.A[1] + 1;
+ Local_R2.N.A[2] = Local_R2.N.A[2] + 1;
+
+ put ("Local_R2 :");
+ dump (&Local_R2, sizeof (struct R2));
+ new_line ();
+ /* { dg-output "Local_R2 : 12 34 56 79 13 00 ab 00 35 00 cd 00 57 00 ef 00\n" } */
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/sso/t7.c b/gcc/testsuite/gcc.dg/sso/t7.c
new file mode 100644
index 00000000000..59df566cd80
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/sso/t7.c
@@ -0,0 +1,72 @@
+/* { dg-do run } */
+
+#include <stdio.h>
+
+#include "init7.h"
+#include "dump.h"
+
+int main (void)
+{
+ struct R1 Local_R1;
+ struct R2 Local_R2;
+
+ Local_R1.I = My_R1.I + 1;
+ Local_R1.N.C1 = My_R1.N.C1 + 1;
+ Local_R1.N.C2 = My_R1.N.C2 + 1;
+ Local_R1.N.C3 = My_R1.N.C3 + 1;
+
+ put ("Local_R1 :");
+ dump (&Local_R1, sizeof (struct R1));
+ new_line ();
+ /* { dg-output "Local_R1 : 79 56 34 12 13 00 ab 00 35 00 cd 00 57 00 ef 00\n" } */
+
+ Local_R2.I = My_R2.I + 1;
+ Local_R2.N.C1 = My_R2.N.C1 + 1;
+ Local_R2.N.C2 = My_R2.N.C2 + 1;
+ Local_R2.N.C3 = My_R2.N.C3 + 1;
+
+ put ("Local_R2 :");
+ dump (&Local_R2, sizeof (struct R2));
+ new_line ();
+ /* { dg-output "Local_R2 : 12 34 56 79 00 ab 00 13 00 cd 00 35 00 ef 00 57\n" } */
+
+ Local_R1.I = 0x12345678;
+ Local_R1.N.C1 = 0xAB0012;
+ Local_R1.N.C2 = 0xCD0034;
+ Local_R1.N.C3 = 0xEF0056;
+ put ("Local_R1 :");
+ dump (&Local_R1, sizeof (struct R1));
+ new_line ();
+ /* { dg-output "Local_R1 : 78 56 34 12 12 00 ab 00 34 00 cd 00 56 00 ef 00\n" } */
+
+ Local_R2.I = 0x12345678;
+ Local_R2.N.C1 = 0xAB0012;
+ Local_R2.N.C2 = 0xCD0034;
+ Local_R2.N.C3 = 0xEF0056;
+ put ("Local_R2 :");
+ dump (&Local_R2, sizeof (struct R2));
+ new_line ();
+ /* { dg-output "Local_R2 : 12 34 56 78 00 ab 00 12 00 cd 00 34 00 ef 00 56\n" } */
+
+ Local_R1.I = Local_R1.I + 1;
+ Local_R1.N.C1 = Local_R1.N.C1 + 1;
+ Local_R1.N.C2 = Local_R1.N.C2 + 1;
+ Local_R1.N.C3 = Local_R1.N.C3 + 1;
+
+ put ("Local_R1 :");
+ dump (&Local_R1, sizeof (struct R1));
+ new_line ();
+ /* { dg-output "Local_R1 : 79 56 34 12 13 00 ab 00 35 00 cd 00 57 00 ef 00\n" } */
+
+ Local_R2.I = Local_R2.I + 1;
+ Local_R2.N.C1 = Local_R2.N.C1 + 1;
+ Local_R2.N.C2 = Local_R2.N.C2 + 1;
+ Local_R2.N.C3 = Local_R2.N.C3 + 1;
+
+ put ("Local_R2 :");
+ dump (&Local_R2, sizeof (struct R2));
+ new_line ();
+ /* { dg-output "Local_R2 : 12 34 56 79 00 ab 00 13 00 cd 00 35 00 ef 00 57\n" } */
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/sso/t8.c b/gcc/testsuite/gcc.dg/sso/t8.c
new file mode 100644
index 00000000000..28a0bf35640
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/sso/t8.c
@@ -0,0 +1,72 @@
+/* { dg-do run } */
+
+#include <stdio.h>
+
+#include "init8.h"
+#include "dump.h"
+
+int main (void)
+{
+ struct R1 Local_R1;
+ struct R2 Local_R2;
+
+ Local_R1.I = My_R1.I + 1;
+ Local_R1.N.C1 = My_R1.N.C1 + 1;
+ Local_R1.N.C2 = My_R1.N.C2 + 1;
+ Local_R1.N.C3 = My_R1.N.C3 + 1;
+
+ put ("Local_R1 :");
+ dump (&Local_R1, sizeof (struct R1));
+ new_line ();
+ /* { dg-output "Local_R1 : 79 56 34 12 00 ab 00 13 00 cd 00 35 00 ef 00 57\n" } */
+
+ Local_R2.I = My_R2.I + 1;
+ Local_R2.N.C1 = My_R2.N.C1 + 1;
+ Local_R2.N.C2 = My_R2.N.C2 + 1;
+ Local_R2.N.C3 = My_R2.N.C3 + 1;
+
+ put ("Local_R2 :");
+ dump (&Local_R2, sizeof (struct R2));
+ new_line ();
+ /* { dg-output "Local_R2 : 12 34 56 79 13 00 ab 00 35 00 cd 00 57 00 ef 00\n" } */
+
+ Local_R1.I = 0x12345678;
+ Local_R1.N.C1 = 0xAB0012;
+ Local_R1.N.C2 = 0xCD0034;
+ Local_R1.N.C3 = 0xEF0056;
+ put ("Local_R1 :");
+ dump (&Local_R1, sizeof (struct R1));
+ new_line ();
+ /* { dg-output "Local_R1 : 78 56 34 12 00 ab 00 12 00 cd 00 34 00 ef 00 56\n" } */
+
+ Local_R2.I = 0x12345678;
+ Local_R2.N.C1 = 0xAB0012;
+ Local_R2.N.C2 = 0xCD0034;
+ Local_R2.N.C3 = 0xEF0056;
+ put ("Local_R2 :");
+ dump (&Local_R2, sizeof (struct R2));
+ new_line ();
+ /* { dg-output "Local_R2 : 12 34 56 78 12 00 ab 00 34 00 cd 00 56 00 ef 00\n" } */
+
+ Local_R1.I = Local_R1.I + 1;
+ Local_R1.N.C1 = Local_R1.N.C1 + 1;
+ Local_R1.N.C2 = Local_R1.N.C2 + 1;
+ Local_R1.N.C3 = Local_R1.N.C3 + 1;
+
+ put ("Local_R1 :");
+ dump (&Local_R1, sizeof (struct R1));
+ new_line ();
+ /* { dg-output "Local_R1 : 79 56 34 12 00 ab 00 13 00 cd 00 35 00 ef 00 57\n" } */
+
+ Local_R2.I = Local_R2.I + 1;
+ Local_R2.N.C1 = Local_R2.N.C1 + 1;
+ Local_R2.N.C2 = Local_R2.N.C2 + 1;
+ Local_R2.N.C3 = Local_R2.N.C3 + 1;
+
+ put ("Local_R2 :");
+ dump (&Local_R2, sizeof (struct R2));
+ new_line ();
+ /* { dg-output "Local_R2 : 12 34 56 79 13 00 ab 00 35 00 cd 00 57 00 ef 00\n" } */
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/sso/t9.c b/gcc/testsuite/gcc.dg/sso/t9.c
new file mode 100644
index 00000000000..1060bb43f3c
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/sso/t9.c
@@ -0,0 +1,56 @@
+/* { dg-do run } */
+
+#include <stdio.h>
+
+#include "init9.h"
+#include "dump.h"
+
+int main (void)
+{
+ struct R1 Local_R1;
+ struct R2 Local_R2;
+
+ Local_R1.F = My_R1.F + 1.0;
+
+ put ("Local_R1 :");
+ dump (&Local_R1, sizeof (struct R1));
+ new_line ();
+ /* { dg-output "Local_R1 : 8c 16 22 aa fd 90 10 40\n" } */
+
+ Local_R2.F = My_R2.F + 1.0;
+
+ put ("Local_R2 :");
+ dump (&Local_R2, sizeof (struct R2));
+ new_line ();
+ /* { dg-output "Local_R2 : 40 10 90 fd aa 22 16 8c\n" } */
+
+ Local_R1.F = Pi;
+
+ put ("Local_R1 :");
+ dump (&Local_R1, sizeof (struct R1));
+ new_line ();
+ /* { dg-output "Local_R1 : 18 2d 44 54 fb 21 09 40\n" } */
+
+ Local_R2.F = Pi;
+
+ put ("Local_R2 :");
+ dump (&Local_R2, sizeof (struct R2));
+ new_line ();
+ /* { dg-output "Local_R2 : 40 09 21 fb 54 44 2d 18\n" } */
+
+ Local_R1.F = Local_R1.F + 1.0;
+
+ put ("Local_R1 :");
+ dump (&Local_R1, sizeof (struct R1));
+ new_line ();
+ /* { dg-output "Local_R1 : 8c 16 22 aa fd 90 10 40\n" } */
+
+ Local_R2.F = Local_R2.F + 1.0;
+
+ put ("Local_R2 :");
+ dump (&Local_R2, sizeof (struct R2));
+ new_line ();
+ /* { dg-output "Local_R2 : 40 10 90 fd aa 22 16 8c\n" } */
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/sso/u5.c b/gcc/testsuite/gcc.dg/sso/u5.c
new file mode 100644
index 00000000000..01ca8b58f13
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/sso/u5.c
@@ -0,0 +1,52 @@
+/* { dg-do run } */
+
+#include <stdio.h>
+
+#include "init5.h"
+#include "dump.h"
+
+int main (void)
+{
+ struct R1 Local_R1;
+ struct R2 Local_R2;
+ int C1;
+ int C2;
+
+ Local_R1.I = 1;
+ Local_R1.A[0] = 0xAB0012;
+ Local_R1.A[1] = 0xCD0034;
+ Local_R1.A[2] = 0xEF0056;
+ put ("Local_R1 :");
+ dump (&Local_R1, sizeof (struct R1));
+ new_line ();
+ /* { dg-output "Local_R1 : 01 00 00 00 12 00 ab 00 34 00 cd 00 56 00 ef 00\n" } */
+
+ Local_R2.I = 1;
+ Local_R2.A[0] = 0xAB0012;
+ Local_R2.A[1] = 0xCD0034;
+ Local_R2.A[2] = 0xEF0056;
+ put ("Local_R2 :");
+ dump (&Local_R2, sizeof (struct R2));
+ new_line ();
+ /* { dg-output "Local_R2 : 00 00 00 01 00 ab 00 12 00 cd 00 34 00 ef 00 56\n" } */
+
+ C1 = Local_R1.A[Local_R1.I];
+ printf ("C1 : %d\n", C1);
+ /* { dg-output "C1 : 13434932\n" } */
+
+ Local_R1.I++;
+ C1 = Local_R1.A[Local_R1.I];
+ printf ("C1 : %d\n", C1);
+ /* { dg-output "C1 : 15663190\n" } */
+
+ C2 = Local_R2.A[Local_R2.I];
+ printf ("C2 : %d\n", C2);
+ /* { dg-output "C2 : 13434932\n" } */
+
+ Local_R2.I++;
+ C2 = Local_R2.A[Local_R2.I];
+ printf ("C2 : %d\n", C2);
+ /* { dg-output "C2 : 15663190\n" } */
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/sso/u6.c b/gcc/testsuite/gcc.dg/sso/u6.c
new file mode 100644
index 00000000000..ae8172e1ffe
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/sso/u6.c
@@ -0,0 +1,52 @@
+/* { dg-do run } */
+
+#include <stdio.h>
+
+#include "init6.h"
+#include "dump.h"
+
+int main (void)
+{
+ struct R1 Local_R1;
+ struct R2 Local_R2;
+ int C1;
+ int C2;
+
+ Local_R1.I = 1;
+ Local_R1.N.A[0] = 0xAB0012;
+ Local_R1.N.A[1] = 0xCD0034;
+ Local_R1.N.A[2] = 0xEF0056;
+ put ("Local_R1 :");
+ dump (&Local_R1, sizeof (struct R1));
+ new_line ();
+ /* { dg-output "Local_R1 : 01 00 00 00 00 ab 00 12 00 cd 00 34 00 ef 00 56\n" } */
+
+ Local_R2.I = 1;
+ Local_R2.N.A[0] = 0xAB0012;
+ Local_R2.N.A[1] = 0xCD0034;
+ Local_R2.N.A[2] = 0xEF0056;
+ put ("Local_R2 :");
+ dump (&Local_R2, sizeof (struct R2));
+ new_line ();
+ /* { dg-output "Local_R2 : 00 00 00 01 12 00 ab 00 34 00 cd 00 56 00 ef 00\n" } */
+
+ C1 = Local_R1.N.A[Local_R1.I];
+ printf ("C1 : %d\n", C1);
+ /* { dg-output "C1 : 13434932\n" } */
+
+ Local_R1.I++;
+ C1 = Local_R1.N.A[Local_R1.I];
+ printf ("C1 : %d\n", C1);
+ /* { dg-output "C1 : 15663190\n" } */
+
+ C2 = Local_R2.N.A[Local_R2.I];
+ printf ("C2 : %d\n", C2);
+ /* { dg-output "C2 : 13434932\n" } */
+
+ Local_R2.I++;
+ C2 = Local_R2.N.A[Local_R2.I];
+ printf ("C2 : %d\n", C2);
+ /* { dg-output "C2 : 15663190\n" } */
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr66752-3.c b/gcc/testsuite/gcc.dg/tree-ssa/pr66752-3.c
index f15b5986166..577a489dd8c 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/pr66752-3.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr66752-3.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -fdump-tree-dom1-details -fdump-tree-optimized" } */
+/* { dg-options "-O2 -fdump-tree-vrp1-details -fdump-tree-optimized" } */
extern int status, pt;
extern int count;
@@ -33,7 +33,7 @@ foo (int N, int c, int b, int *a)
}
/* There are 3 FSM jump threading opportunities. */
-/* { dg-final { scan-tree-dump-times "FSM" 3 "dom1"} } */
+/* { dg-final { scan-tree-dump-times "FSM" 3 "vrp1"} } */
/* There should be no assignments or references to FLAG. */
/* { dg-final { scan-tree-dump-not "flag" "optimized"} } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-7.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-7.c
index 445f2509dc3..ac12b6ca714 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-7.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-7.c
@@ -1,6 +1,8 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -fdump-tree-dom1-details" } */
-/* { dg-final { scan-tree-dump-times "FSM" 38 "dom1" } } */
+/* { dg-options "-O2 -fdump-tree-vrp1-stats -fdump-tree-dom1-stats -fdump-tree-dom2-stats" } */
+/* { dg-final { scan-tree-dump "Jumps threaded: 7" "vrp1" } } */
+/* { dg-final { scan-tree-dump "Jumps threaded: 12" "dom1" } } */
+/* { dg-final { scan-tree-dump "Jumps threaded: 3" "dom2" } } */
enum STATE {
S0=0,
diff --git a/gcc/testsuite/gcc.dg/vect/bb-slp-38.c b/gcc/testsuite/gcc.dg/vect/bb-slp-38.c
new file mode 100644
index 00000000000..59aec54fffd
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/bb-slp-38.c
@@ -0,0 +1,44 @@
+/* { dg-require-effective-target vect_int } */
+
+#include "tree-vect.h"
+
+extern void abort (void);
+
+int a[8], b[8];
+int x;
+
+void __attribute__((noinline,noclone))
+bar (void)
+{
+ x = 1;
+}
+
+void __attribute__((noinline,noclone))
+foo(void)
+{
+ a[0] = b[0];
+ a[1] = b[0];
+ a[2] = b[3];
+ a[3] = b[3];
+ bar ();
+ a[4] = b[4];
+ a[5] = b[7];
+ a[6] = b[4];
+ a[7] = b[7];
+}
+
+int main()
+{
+ int i;
+ check_vect ();
+ for (i = 0; i < 8; ++i)
+ b[i] = i;
+ foo ();
+ if (a[0] != 0 || a[1] != 0 || a[2] != 3 || a[3] != 3
+ || a[4] != 4 || a[5] != 7 || a[6] != 4 || a[7] != 7)
+ abort ();
+ return 0;
+}
+
+/* { dg-final { scan-tree-dump "basic block vectorized" "slp2" { target vect_perm } } } */
+/* { dg-final { scan-tree-dump-times "basic block part vectorized" 2 "slp2" { target vect_perm } } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/advsimd-intrinsics/vqtbX.c b/gcc/testsuite/gcc.target/aarch64/advsimd-intrinsics/vqtbX.c
new file mode 100644
index 00000000000..129ceafbb65
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/advsimd-intrinsics/vqtbX.c
@@ -0,0 +1,519 @@
+/* { dg-skip-if "" { arm*-*-* } } */
+
+#include <arm_neon.h>
+#include "arm-neon-ref.h"
+#include "compute-ref-data.h"
+
+/* Expected results for vqtbl1. */
+VECT_VAR_DECL(expected_vqtbl1,int,8,8) [] = { 0xfb, 0xf3, 0xf3, 0xf3,
+ 0x0, 0x0, 0xf3, 0xf3 };
+VECT_VAR_DECL(expected_vqtbl1,uint,8,8) [] = { 0xfb, 0xf3, 0xf3, 0xf3,
+ 0x0, 0x0, 0xf3, 0xf3 };
+VECT_VAR_DECL(expected_vqtbl1,poly,8,8) [] = { 0xfb, 0xf3, 0xf3, 0xf3,
+ 0x0, 0x0, 0xf3, 0xf3 };
+
+/* Expected results for vqtbl2. */
+VECT_VAR_DECL(expected_vqtbl2,int,8,8) [] = { 0x5, 0xf5, 0xf5, 0xf5,
+ 0xfa, 0x0, 0xf5, 0xf5 };
+VECT_VAR_DECL(expected_vqtbl2,uint,8,8) [] = { 0x5, 0xf5, 0xf5, 0xf5,
+ 0xfa, 0x0, 0xf5, 0xf5 };
+VECT_VAR_DECL(expected_vqtbl2,poly,8,8) [] = { 0x5, 0xf5, 0xf5, 0xf5,
+ 0xfa, 0x0, 0xf5, 0xf5 };
+
+/* Expected results for vqtbl3. */
+VECT_VAR_DECL(expected_vqtbl3,int,8,8) [] = { 0xf, 0xf7, 0xf7, 0xf7,
+ 0xfe, 0xb, 0xf7, 0xf7 };
+VECT_VAR_DECL(expected_vqtbl3,uint,8,8) [] = { 0xf, 0xf7, 0xf7, 0xf7,
+ 0xfe, 0xb, 0xf7, 0xf7 };
+VECT_VAR_DECL(expected_vqtbl3,poly,8,8) [] = { 0xf, 0xf7, 0xf7, 0xf7,
+ 0xfe, 0xb, 0xf7, 0xf7 };
+
+/* Expected results for vqtbl4. */
+VECT_VAR_DECL(expected_vqtbl4,int,8,8) [] = { 0x19, 0xf9, 0xf9, 0xf9,
+ 0x2, 0x13, 0xf9, 0xf9 };
+VECT_VAR_DECL(expected_vqtbl4,uint,8,8) [] = { 0x19, 0xf9, 0xf9, 0xf9,
+ 0x2, 0x13, 0xf9, 0xf9 };
+VECT_VAR_DECL(expected_vqtbl4,poly,8,8) [] = { 0x19, 0xf9, 0xf9, 0xf9,
+ 0x2, 0x13, 0xf9, 0xf9 };
+
+/* Expected results for vqtbx1. */
+VECT_VAR_DECL(expected_vqtbx1,int,8,8) [] = { 0xfb, 0xf3, 0xf3, 0xf3,
+ 0x33, 0x33, 0xf3, 0xf3 };
+VECT_VAR_DECL(expected_vqtbx1,uint,8,8) [] = { 0xfb, 0xf3, 0xf3, 0xf3,
+ 0xcc, 0xcc, 0xf3, 0xf3 };
+VECT_VAR_DECL(expected_vqtbx1,poly,8,8) [] = { 0xfb, 0xf3, 0xf3, 0xf3,
+ 0xcc, 0xcc, 0xf3, 0xf3 };
+
+/* Expected results for vqtbx2. */
+VECT_VAR_DECL(expected_vqtbx2,int,8,8) [] = { 0x5, 0xf5, 0xf5, 0xf5,
+ 0xfa, 0x33, 0xf5, 0xf5 };
+VECT_VAR_DECL(expected_vqtbx2,uint,8,8) [] = { 0x5, 0xf5, 0xf5, 0xf5,
+ 0xfa, 0xcc, 0xf5, 0xf5 };
+VECT_VAR_DECL(expected_vqtbx2,poly,8,8) [] = { 0x5, 0xf5, 0xf5, 0xf5,
+ 0xfa, 0xcc, 0xf5, 0xf5 };
+
+/* Expected results for vqtbx3. */
+VECT_VAR_DECL(expected_vqtbx3,int,8,8) [] = { 0xf, 0xf7, 0xf7, 0xf7,
+ 0xfe, 0xb, 0xf7, 0xf7 };
+VECT_VAR_DECL(expected_vqtbx3,uint,8,8) [] = { 0xf, 0xf7, 0xf7, 0xf7,
+ 0xfe, 0xb, 0xf7, 0xf7 };
+VECT_VAR_DECL(expected_vqtbx3,poly,8,8) [] = { 0xf, 0xf7, 0xf7, 0xf7,
+ 0xfe, 0xb, 0xf7, 0xf7 };
+
+/* Expected results for vqtbx4. */
+VECT_VAR_DECL(expected_vqtbx4,int,8,8) [] = { 0x19, 0xf9, 0xf9, 0xf9,
+ 0x2, 0x13, 0xf9, 0xf9 };
+VECT_VAR_DECL(expected_vqtbx4,uint,8,8) [] = { 0x19, 0xf9, 0xf9, 0xf9,
+ 0x2, 0x13, 0xf9, 0xf9 };
+VECT_VAR_DECL(expected_vqtbx4,poly,8,8) [] = { 0x19, 0xf9, 0xf9, 0xf9,
+ 0x2, 0x13, 0xf9, 0xf9 };
+
+/* Expected results for vqtbl1q. */
+VECT_VAR_DECL(expected_vqtbl1q,int,8,16) [] = { 0xfb, 0xf3, 0xf3, 0xf3,
+ 0x0, 0x0, 0xf3, 0xf3,
+ 0xf3, 0xf3, 0xf3, 0xf3,
+ 0xf3, 0xf3, 0xf3, 0xf3 };
+VECT_VAR_DECL(expected_vqtbl1q,uint,8,16) [] = { 0xfb, 0xf3, 0xf3, 0xf3,
+ 0x0, 0x0, 0xf3, 0xf3,
+ 0xf3, 0xf3, 0xf3, 0xf3,
+ 0xf3, 0xf3, 0xf3, 0xf3 };
+VECT_VAR_DECL(expected_vqtbl1q,poly,8,16) [] = { 0xfb, 0xf3, 0xf3, 0xf3,
+ 0x0, 0x0, 0xf3, 0xf3,
+ 0xf3, 0xf3, 0xf3, 0xf3,
+ 0xf3, 0xf3, 0xf3, 0xf3 };
+
+/* Expected results for vqtbl2q. */
+VECT_VAR_DECL(expected_vqtbl2q,int,8,16) [] = { 0x5, 0xf5, 0xf5, 0xf5,
+ 0xfa, 0x0, 0xf5, 0xf5,
+ 0xf5, 0xf5, 0xf5, 0xf5,
+ 0xf5, 0xf5, 0xf5, 0xf5 };
+VECT_VAR_DECL(expected_vqtbl2q,uint,8,16) [] = { 0x5, 0xf5, 0xf5, 0xf5,
+ 0xfa, 0x0, 0xf5, 0xf5,
+ 0xf5, 0xf5, 0xf5, 0xf5,
+ 0xf5, 0xf5, 0xf5, 0xf5 };
+VECT_VAR_DECL(expected_vqtbl2q,poly,8,16) [] = { 0x5, 0xf5, 0xf5, 0xf5,
+ 0xfa, 0x0, 0xf5, 0xf5,
+ 0xf5, 0xf5, 0xf5, 0xf5,
+ 0xf5, 0xf5, 0xf5, 0xf5 };
+
+/* Expected results for vqtbl3q. */
+VECT_VAR_DECL(expected_vqtbl3q,int,8,16) [] = { 0xf, 0xf7, 0xf7, 0xf7,
+ 0xfe, 0xb, 0xf7, 0xf7,
+ 0xf7, 0xf7, 0xf7, 0xf7,
+ 0xf7, 0xf7, 0xf7, 0xf7 };
+VECT_VAR_DECL(expected_vqtbl3q,uint,8,16) [] = { 0xf, 0xf7, 0xf7, 0xf7,
+ 0xfe, 0xb, 0xf7, 0xf7,
+ 0xf7, 0xf7, 0xf7, 0xf7,
+ 0xf7, 0xf7, 0xf7, 0xf7 };
+VECT_VAR_DECL(expected_vqtbl3q,poly,8,16) [] = { 0xf, 0xf7, 0xf7, 0xf7,
+ 0xfe, 0xb, 0xf7, 0xf7,
+ 0xf7, 0xf7, 0xf7, 0xf7,
+ 0xf7, 0xf7, 0xf7, 0xf7 };
+
+/* Expected results for vqtbl4q. */
+VECT_VAR_DECL(expected_vqtbl4q,int,8,16) [] = { 0x19, 0xf9, 0xf9, 0xf9,
+ 0x2, 0x13, 0xf9, 0xf9,
+ 0xf9, 0xf9, 0xf9, 0xf9,
+ 0xf9, 0xf9, 0xf9, 0xf9 };
+VECT_VAR_DECL(expected_vqtbl4q,uint,8,16) [] = { 0x19, 0xf9, 0xf9, 0xf9,
+ 0x2, 0x13, 0xf9, 0xf9,
+ 0xf9, 0xf9, 0xf9, 0xf9,
+ 0xf9, 0xf9, 0xf9, 0xf9 };
+VECT_VAR_DECL(expected_vqtbl4q,poly,8,16) [] = { 0x19, 0xf9, 0xf9, 0xf9,
+ 0x2, 0x13, 0xf9, 0xf9,
+ 0xf9, 0xf9, 0xf9, 0xf9,
+ 0xf9, 0xf9, 0xf9, 0xf9 };
+
+/* Expected results for vqtbx1q. */
+VECT_VAR_DECL(expected_vqtbx1q,int,8,16) [] = { 0xfb, 0xf3, 0xf3, 0xf3,
+ 0x33, 0x33, 0xf3, 0xf3,
+ 0xf3, 0xf3, 0xf3, 0xf3,
+ 0xf3, 0xf3, 0xf3, 0xf3 };
+VECT_VAR_DECL(expected_vqtbx1q,uint,8,16) [] = { 0xfb, 0xf3, 0xf3, 0xf3,
+ 0xcc, 0xcc, 0xf3, 0xf3,
+ 0xf3, 0xf3, 0xf3, 0xf3,
+ 0xf3, 0xf3, 0xf3, 0xf3 };
+VECT_VAR_DECL(expected_vqtbx1q,poly,8,16) [] = { 0xfb, 0xf3, 0xf3, 0xf3,
+ 0xcc, 0xcc, 0xf3, 0xf3,
+ 0xf3, 0xf3, 0xf3, 0xf3,
+ 0xf3, 0xf3, 0xf3, 0xf3 };
+
+/* Expected results for vqtbx2q. */
+VECT_VAR_DECL(expected_vqtbx2q,int,8,16) [] = { 0x5, 0xf5, 0xf5, 0xf5,
+ 0xfa, 0x33, 0xf5, 0xf5,
+ 0xf5, 0xf5, 0xf5, 0xf5,
+ 0xf5, 0xf5, 0xf5, 0xf5 };
+VECT_VAR_DECL(expected_vqtbx2q,uint,8,16) [] = { 0x5, 0xf5, 0xf5, 0xf5,
+ 0xfa, 0xcc, 0xf5, 0xf5,
+ 0xf5, 0xf5, 0xf5, 0xf5,
+ 0xf5, 0xf5, 0xf5, 0xf5 };
+VECT_VAR_DECL(expected_vqtbx2q,poly,8,16) [] = { 0x5, 0xf5, 0xf5, 0xf5,
+ 0xfa, 0xcc, 0xf5, 0xf5,
+ 0xf5, 0xf5, 0xf5, 0xf5,
+ 0xf5, 0xf5, 0xf5, 0xf5 };
+
+/* Expected results for vqtbx3q. */
+VECT_VAR_DECL(expected_vqtbx3q,int,8,16) [] = { 0xf, 0xf7, 0xf7, 0xf7,
+ 0xfe, 0xb, 0xf7, 0xf7,
+ 0xf7, 0xf7, 0xf7, 0xf7,
+ 0xf7, 0xf7, 0xf7, 0xf7 };
+VECT_VAR_DECL(expected_vqtbx3q,uint,8,16) [] = { 0xf, 0xf7, 0xf7, 0xf7,
+ 0xfe, 0xb, 0xf7, 0xf7,
+ 0xf7, 0xf7, 0xf7, 0xf7,
+ 0xf7, 0xf7, 0xf7, 0xf7 };
+VECT_VAR_DECL(expected_vqtbx3q,poly,8,16) [] = { 0xf, 0xf7, 0xf7, 0xf7,
+ 0xfe, 0xb, 0xf7, 0xf7,
+ 0xf7, 0xf7, 0xf7, 0xf7,
+ 0xf7, 0xf7, 0xf7, 0xf7 };
+
+/* Expected results for vqtbx4q. */
+VECT_VAR_DECL(expected_vqtbx4q,int,8,16) [] = { 0x19, 0xf9, 0xf9, 0xf9,
+ 0x2, 0x13, 0xf9, 0xf9,
+ 0xf9, 0xf9, 0xf9, 0xf9,
+ 0xf9, 0xf9, 0xf9, 0xf9 };
+VECT_VAR_DECL(expected_vqtbx4q,uint,8,16) [] = { 0x19, 0xf9, 0xf9, 0xf9,
+ 0x2, 0x13, 0xf9, 0xf9,
+ 0xf9, 0xf9, 0xf9, 0xf9,
+ 0xf9, 0xf9, 0xf9, 0xf9 };
+VECT_VAR_DECL(expected_vqtbx4q,poly,8,16) [] = { 0x19, 0xf9, 0xf9, 0xf9,
+ 0x2, 0x13, 0xf9, 0xf9,
+ 0xf9, 0xf9, 0xf9, 0xf9,
+ 0xf9, 0xf9, 0xf9, 0xf9 };
+
+void exec_vqtbX (void)
+{
+ int i;
+
+ /* In this case, input variables are arrays of vectors. */
+#define DECL_VQTBX(T1, W, N, X) \
+ VECT_ARRAY_TYPE(T1, W, N, X) VECT_ARRAY_VAR(table_vector, T1, W, N, X)
+
+ /* The vqtbl1 variant is different from vqtbl{2,3,4} because it takes a
+ vector as 1st param, instead of an array of vectors. */
+#define TEST_VQTBL1(T1, T2, T3, W, N1, N2) \
+ VECT_VAR(table_vector, T1, W, N2) = \
+ vld1##q_##T2##W((T1##W##_t *)lookup_table); \
+ \
+ VECT_VAR(vector_res, T1, W, N1) = \
+ vqtbl1_##T2##W(VECT_VAR(table_vector, T1, W, N2), \
+ VECT_VAR(vector, T3, W, N1)); \
+ vst1_##T2##W(VECT_VAR(result, T1, W, N1), \
+ VECT_VAR(vector_res, T1, W, N1));
+
+#define TEST_VQTBL1Q(T1, T2, T3, W, N1, N2) \
+ VECT_VAR(table_vector, T1, W, N2) = \
+ vld1##q_##T2##W((T1##W##_t *)lookup_table); \
+ \
+ VECT_VAR(vector_res, T1, W, N1) = \
+ vqtbl1q_##T2##W(VECT_VAR(table_vector, T1, W, N2), \
+ VECT_VAR(vector, T3, W, N1)); \
+ vst1q_##T2##W(VECT_VAR(result, T1, W, N1), \
+ VECT_VAR(vector_res, T1, W, N1));
+
+#define TEST_VQTBLX(T1, T2, T3, W, N1, N2, X) \
+ VECT_ARRAY_VAR(table_vector, T1, W, N2, X) = \
+ vld##X##q_##T2##W((T1##W##_t *)lookup_table); \
+ \
+ VECT_VAR(vector_res, T1, W, N1) = \
+ vqtbl##X##_##T2##W(VECT_ARRAY_VAR(table_vector, T1, W, N2, X), \
+ VECT_VAR(vector, T3, W, N1)); \
+ vst1_##T2##W(VECT_VAR(result, T1, W, N1), \
+ VECT_VAR(vector_res, T1, W, N1));
+
+#define TEST_VQTBLXQ(T1, T2, T3, W, N1, N2, X) \
+ VECT_ARRAY_VAR(table_vector, T1, W, N2, X) = \
+ vld##X##q_##T2##W((T1##W##_t *)lookup_table); \
+ \
+ VECT_VAR(vector_res, T1, W, N1) = \
+ vqtbl##X##q_##T2##W(VECT_ARRAY_VAR(table_vector, T1, W, N2, X), \
+ VECT_VAR(vector, T3, W, N1)); \
+ vst1q_##T2##W(VECT_VAR(result, T1, W, N1), \
+ VECT_VAR(vector_res, T1, W, N1));
+
+ /* We need to define a lookup table large enough. */
+ int8_t lookup_table[4*16];
+
+ /* For vqtblX. */
+ DECL_VARIABLE(vector, int, 8, 8);
+ DECL_VARIABLE(vector, uint, 8, 8);
+ DECL_VARIABLE(vector, poly, 8, 8);
+ DECL_VARIABLE(vector_res, int, 8, 8);
+ DECL_VARIABLE(vector_res, uint, 8, 8);
+ DECL_VARIABLE(vector_res, poly, 8, 8);
+
+ /* For vqtblXq. */
+ DECL_VARIABLE(vector, int, 8, 16);
+ DECL_VARIABLE(vector, uint, 8, 16);
+ DECL_VARIABLE(vector, poly, 8, 16);
+ DECL_VARIABLE(vector_res, int, 8, 16);
+ DECL_VARIABLE(vector_res, uint, 8, 16);
+ DECL_VARIABLE(vector_res, poly, 8, 16);
+
+ /* For vqtbl1. */
+ DECL_VARIABLE(table_vector, int, 8, 16);
+ DECL_VARIABLE(table_vector, uint, 8, 16);
+ DECL_VARIABLE(table_vector, poly, 8, 16);
+
+ /* For vqtbx*. */
+ DECL_VARIABLE(default_vector, int, 8, 8);
+ DECL_VARIABLE(default_vector, uint, 8, 8);
+ DECL_VARIABLE(default_vector, poly, 8, 8);
+
+ /* For vqtbx*q. */
+ DECL_VARIABLE(default_vector, int, 8, 16);
+ DECL_VARIABLE(default_vector, uint, 8, 16);
+ DECL_VARIABLE(default_vector, poly, 8, 16);
+
+ /* We need only 8 bits variants. */
+#define DECL_ALL_VQTBLX(X) \
+ DECL_VQTBX(int, 8, 16, X); \
+ DECL_VQTBX(uint, 8, 16, X); \
+ DECL_VQTBX(poly, 8, 16, X)
+
+#define TEST_ALL_VQTBL1() \
+ TEST_VQTBL1(int, s, uint, 8, 8, 16); \
+ TEST_VQTBL1(uint, u, uint, 8, 8, 16); \
+ TEST_VQTBL1(poly, p, uint, 8, 8, 16); \
+ TEST_VQTBL1Q(int, s, uint, 8, 16, 16); \
+ TEST_VQTBL1Q(uint, u, uint, 8, 16, 16); \
+ TEST_VQTBL1Q(poly, p, uint, 8, 16, 16)
+
+#define TEST_ALL_VQTBLX(X) \
+ TEST_VQTBLX(int, s, uint, 8, 8, 16, X); \
+ TEST_VQTBLX(uint, u, uint, 8, 8, 16, X); \
+ TEST_VQTBLX(poly, p, uint, 8, 8, 16, X); \
+ TEST_VQTBLXQ(int, s, uint, 8, 16, 16, X); \
+ TEST_VQTBLXQ(uint, u, uint, 8, 16, 16, X); \
+ TEST_VQTBLXQ(poly, p, uint, 8, 16, 16, X)
+
+ /* Declare the temporary buffers / variables. */
+ DECL_ALL_VQTBLX(2);
+ DECL_ALL_VQTBLX(3);
+ DECL_ALL_VQTBLX(4);
+
+ /* Fill the lookup table. */
+ for (i=0; i<4*16; i++) {
+ lookup_table[i] = i-15;
+ }
+
+ /* Choose init value arbitrarily, will be used as table index. */
+ VDUP(vector, , uint, u, 8, 8, 2);
+ VDUP(vector, q, uint, u, 8, 16, 2);
+
+ /* To ensure coverage, add some indexes larger than 8, 16 and 32
+ except: lane 0 (index 10), lane 4 (index 20) and lane 5 (index
+ 40). */
+ VSET_LANE(vector, , uint, u, 8, 8, 0, 10);
+ VSET_LANE(vector, , uint, u, 8, 8, 4, 20);
+ VSET_LANE(vector, , uint, u, 8, 8, 5, 40);
+
+ VSET_LANE(vector, q, uint, u, 8, 16, 0, 10);
+ VSET_LANE(vector, q, uint, u, 8, 16, 4, 20);
+ VSET_LANE(vector, q, uint, u, 8, 16, 5, 40);
+
+ /* Check vqtbl1. */
+ clean_results ();
+#define TEST_MSG "VQTBL1"
+ TEST_ALL_VQTBL1();
+
+ CHECK(TEST_MSG, int, 8, 8, PRIx8, expected_vqtbl1, "");
+ CHECK(TEST_MSG, uint, 8, 8, PRIx8, expected_vqtbl1, "");
+ CHECK(TEST_MSG, poly, 8, 8, PRIx8, expected_vqtbl1, "");
+
+#undef TEST_MSG
+#define TEST_MSG "VQTBL1Q"
+ CHECK(TEST_MSG, int, 8, 16, PRIx8, expected_vqtbl1q, "");
+ CHECK(TEST_MSG, uint, 8, 16, PRIx8, expected_vqtbl1q, "");
+ CHECK(TEST_MSG, poly, 8, 16, PRIx8, expected_vqtbl1q, "");
+
+ /* Check vqtbl2. */
+ clean_results ();
+#undef TEST_MSG
+#define TEST_MSG "VQTBL2"
+ TEST_ALL_VQTBLX(2);
+
+ CHECK(TEST_MSG, int, 8, 8, PRIx8, expected_vqtbl2, "");
+ CHECK(TEST_MSG, uint, 8, 8, PRIx8, expected_vqtbl2, "");
+ CHECK(TEST_MSG, poly, 8, 8, PRIx8, expected_vqtbl2, "");
+
+#undef TEST_MSG
+#define TEST_MSG "VQTBL2Q"
+ CHECK(TEST_MSG, int, 8, 16, PRIx8, expected_vqtbl2q, "");
+ CHECK(TEST_MSG, uint, 8, 16, PRIx8, expected_vqtbl2q, "");
+ CHECK(TEST_MSG, poly, 8, 16, PRIx8, expected_vqtbl2q, "");
+
+ /* Check vqtbl3. */
+ clean_results ();
+#undef TEST_MSG
+#define TEST_MSG "VQTBL3"
+ TEST_ALL_VQTBLX(3);
+
+ CHECK(TEST_MSG, int, 8, 8, PRIx8, expected_vqtbl3, "");
+ CHECK(TEST_MSG, uint, 8, 8, PRIx8, expected_vqtbl3, "");
+ CHECK(TEST_MSG, poly, 8, 8, PRIx8, expected_vqtbl3, "");
+
+#undef TEST_MSG
+#define TEST_MSG "VQTBL3Q"
+ CHECK(TEST_MSG, int, 8, 16, PRIx8, expected_vqtbl3q, "");
+ CHECK(TEST_MSG, uint, 8, 16, PRIx8, expected_vqtbl3q, "");
+ CHECK(TEST_MSG, poly, 8, 16, PRIx8, expected_vqtbl3q, "");
+
+ /* Check vqtbl4. */
+ clean_results ();
+#undef TEST_MSG
+#define TEST_MSG "VQTBL4"
+ TEST_ALL_VQTBLX(4);
+
+ CHECK(TEST_MSG, int, 8, 8, PRIx8, expected_vqtbl4, "");
+ CHECK(TEST_MSG, uint, 8, 8, PRIx8, expected_vqtbl4, "");
+ CHECK(TEST_MSG, poly, 8, 8, PRIx8, expected_vqtbl4, "");
+
+#undef TEST_MSG
+#define TEST_MSG "VQTBL4Q"
+ CHECK(TEST_MSG, int, 8, 16, PRIx8, expected_vqtbl4q, "");
+ CHECK(TEST_MSG, uint, 8, 16, PRIx8, expected_vqtbl4q, "");
+ CHECK(TEST_MSG, poly, 8, 16, PRIx8, expected_vqtbl4q, "");
+
+
+ /* Now test VQTBX. */
+
+ /* The vqtbx1 variant is different from vqtbx{2,3,4} because it takes a
+ vector as 1st param, instead of an array of vectors. */
+#define TEST_VQTBX1(T1, T2, T3, W, N1, N2) \
+ VECT_VAR(table_vector, T1, W, N2) = \
+ vld1##q_##T2##W((T1##W##_t *)lookup_table); \
+ \
+ VECT_VAR(vector_res, T1, W, N1) = \
+ vqtbx1_##T2##W(VECT_VAR(default_vector, T1, W, N1), \
+ VECT_VAR(table_vector, T1, W, N2), \
+ VECT_VAR(vector, T3, W, N1)); \
+ vst1_##T2##W(VECT_VAR(result, T1, W, N1), \
+ VECT_VAR(vector_res, T1, W, N1));
+
+#define TEST_VQTBX1Q(T1, T2, T3, W, N1, N2) \
+ VECT_VAR(table_vector, T1, W, N2) = \
+ vld1##q_##T2##W((T1##W##_t *)lookup_table); \
+ \
+ VECT_VAR(vector_res, T1, W, N1) = \
+ vqtbx1q_##T2##W(VECT_VAR(default_vector, T1, W, N1),\
+ VECT_VAR(table_vector, T1, W, N2), \
+ VECT_VAR(vector, T3, W, N1)); \
+ vst1q_##T2##W(VECT_VAR(result, T1, W, N1), \
+ VECT_VAR(vector_res, T1, W, N1));
+
+#define TEST_VQTBXX(T1, T2, T3, W, N1, N2, X) \
+ VECT_ARRAY_VAR(table_vector, T1, W, N2, X) = \
+ vld##X##q_##T2##W((T1##W##_t *)lookup_table); \
+ \
+ VECT_VAR(vector_res, T1, W, N1) = \
+ vqtbx##X##_##T2##W(VECT_VAR(default_vector, T1, W, N1), \
+ VECT_ARRAY_VAR(table_vector, T1, W, N2, X), \
+ VECT_VAR(vector, T3, W, N1)); \
+ vst1_##T2##W(VECT_VAR(result, T1, W, N1), \
+ VECT_VAR(vector_res, T1, W, N1));
+
+#define TEST_VQTBXXQ(T1, T2, T3, W, N1, N2, X) \
+ VECT_ARRAY_VAR(table_vector, T1, W, N2, X) = \
+ vld##X##q_##T2##W((T1##W##_t *)lookup_table); \
+ \
+ VECT_VAR(vector_res, T1, W, N1) = \
+ vqtbx##X##q_##T2##W(VECT_VAR(default_vector, T1, W, N1), \
+ VECT_ARRAY_VAR(table_vector, T1, W, N2, X), \
+ VECT_VAR(vector, T3, W, N1)); \
+ vst1q_##T2##W(VECT_VAR(result, T1, W, N1), \
+ VECT_VAR(vector_res, T1, W, N1));
+
+#define TEST_ALL_VQTBX1() \
+ TEST_VQTBX1(int, s, uint, 8, 8, 16); \
+ TEST_VQTBX1(uint, u, uint, 8, 8, 16); \
+ TEST_VQTBX1(poly, p, uint, 8, 8, 16); \
+ TEST_VQTBX1Q(int, s, uint, 8, 16, 16); \
+ TEST_VQTBX1Q(uint, u, uint, 8, 16, 16); \
+ TEST_VQTBX1Q(poly, p, uint, 8, 16, 16)
+
+#define TEST_ALL_VQTBXX(X) \
+ TEST_VQTBXX(int, s, uint, 8, 8, 16, X); \
+ TEST_VQTBXX(uint, u, uint, 8, 8, 16, X); \
+ TEST_VQTBXX(poly, p, uint, 8, 8, 16, X); \
+ TEST_VQTBXXQ(int, s, uint, 8, 16, 16, X); \
+ TEST_VQTBXXQ(uint, u, uint, 8, 16, 16, X); \
+ TEST_VQTBXXQ(poly, p, uint, 8, 16, 16, X)
+
+ /* Choose init value arbitrarily, will be used as default value. */
+ VDUP(default_vector, , int, s, 8, 8, 0x33);
+ VDUP(default_vector, , uint, u, 8, 8, 0xCC);
+ VDUP(default_vector, , poly, p, 8, 8, 0xCC);
+ VDUP(default_vector, q, int, s, 8, 16, 0x33);
+ VDUP(default_vector, q, uint, u, 8, 16, 0xCC);
+ VDUP(default_vector, q, poly, p, 8, 16, 0xCC);
+
+ /* Check vqtbx1. */
+ clean_results ();
+#undef TEST_MSG
+#define TEST_MSG "VQTBX1"
+ TEST_ALL_VQTBX1();
+
+ CHECK(TEST_MSG, int, 8, 8, PRIx8, expected_vqtbx1, "");
+ CHECK(TEST_MSG, uint, 8, 8, PRIx8, expected_vqtbx1, "");
+ CHECK(TEST_MSG, poly, 8, 8, PRIx8, expected_vqtbx1, "");
+
+#undef TEST_MSG
+#define TEST_MSG "VQTBX1Q"
+ CHECK(TEST_MSG, int, 8, 16, PRIx8, expected_vqtbx1q, "");
+ CHECK(TEST_MSG, uint, 8, 16, PRIx8, expected_vqtbx1q, "");
+ CHECK(TEST_MSG, poly, 8, 16, PRIx8, expected_vqtbx1q, "");
+
+ /* Check vqtbx2. */
+ clean_results ();
+#undef TEST_MSG
+#define TEST_MSG "VQTBX2"
+ TEST_ALL_VQTBXX(2);
+
+ CHECK(TEST_MSG, int, 8, 8, PRIx8, expected_vqtbx2, "");
+ CHECK(TEST_MSG, uint, 8, 8, PRIx8, expected_vqtbx2, "");
+ CHECK(TEST_MSG, poly, 8, 8, PRIx8, expected_vqtbx2, "");
+
+#undef TEST_MSG
+#define TEST_MSG "VQTBX2Q"
+ CHECK(TEST_MSG, int, 8, 16, PRIx8, expected_vqtbx2q, "");
+ CHECK(TEST_MSG, uint, 8, 16, PRIx8, expected_vqtbx2q, "");
+ CHECK(TEST_MSG, poly, 8, 16, PRIx8, expected_vqtbx2q, "");
+
+ /* Check vqtbx3. */
+ clean_results ();
+#undef TEST_MSG
+#define TEST_MSG "VQTBX3"
+ TEST_ALL_VQTBXX(3);
+
+ CHECK(TEST_MSG, int, 8, 8, PRIx8, expected_vqtbx3, "");
+ CHECK(TEST_MSG, uint, 8, 8, PRIx8, expected_vqtbx3, "");
+ CHECK(TEST_MSG, poly, 8, 8, PRIx8, expected_vqtbx3, "");
+
+#undef TEST_MSG
+#define TEST_MSG "VQTBX3Q"
+ CHECK(TEST_MSG, int, 8, 16, PRIx8, expected_vqtbx3q, "");
+ CHECK(TEST_MSG, uint, 8, 16, PRIx8, expected_vqtbx3q, "");
+ CHECK(TEST_MSG, poly, 8, 16, PRIx8, expected_vqtbx3q, "");
+
+ /* Check vqtbx4. */
+ clean_results ();
+#undef TEST_MSG
+#define TEST_MSG "VQTBX4"
+ TEST_ALL_VQTBXX(4);
+
+ CHECK(TEST_MSG, int, 8, 8, PRIx8, expected_vqtbx4, "");
+ CHECK(TEST_MSG, uint, 8, 8, PRIx8, expected_vqtbx4, "");
+ CHECK(TEST_MSG, poly, 8, 8, PRIx8, expected_vqtbx4, "");
+
+#undef TEST_MSG
+#define TEST_MSG "VQTBX4Q"
+ CHECK(TEST_MSG, int, 8, 16, PRIx8, expected_vqtbx4q, "");
+ CHECK(TEST_MSG, uint, 8, 16, PRIx8, expected_vqtbx4q, "");
+ CHECK(TEST_MSG, poly, 8, 16, PRIx8, expected_vqtbx4q, "");
+}
+
+int main (void)
+{
+ exec_vqtbX ();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/advsimd-intrinsics/vtbX.c b/gcc/testsuite/gcc.target/aarch64/advsimd-intrinsics/vtbX.c
index 0557efd6e7e..2a08886ae25 100644
--- a/gcc/testsuite/gcc.target/aarch64/advsimd-intrinsics/vtbX.c
+++ b/gcc/testsuite/gcc.target/aarch64/advsimd-intrinsics/vtbX.c
@@ -147,8 +147,8 @@ void exec_vtbX (void)
VDUP(vector, , uint, u, 8, 8, 2);
VDUP(vector, , poly, p, 8, 8, 2);
- /* To ensure coverage, add some indexes larger than 8,16 and 32
- except: lane 0 (by 6), lane 1 (by 8) and lane 2 (by 9). */
+ /* To ensure coverage, add some indexes larger than 8, 16 and 32
+ except: lane 0 (by 10), lane 4 (by 20) and lane 5 (by 40). */
VSET_LANE(vector, , int, s, 8, 8, 0, 10);
VSET_LANE(vector, , int, s, 8, 8, 4, 20);
VSET_LANE(vector, , int, s, 8, 8, 5, 40);
diff --git a/gcc/testsuite/gcc.target/arm/combine-movs.c b/gcc/testsuite/gcc.target/arm/combine-movs.c
index e9fd6cb45d6..3487743257c 100644
--- a/gcc/testsuite/gcc.target/arm/combine-movs.c
+++ b/gcc/testsuite/gcc.target/arm/combine-movs.c
@@ -9,5 +9,4 @@ void foo (unsigned long r[], unsigned int d)
r[i] = 0;
}
-/* { dg-final { scan-assembler "lsrs\tr\[0-9\]" { target arm_thumb2 } } } */
-/* { dg-final { scan-assembler "movs\tr\[0-9\]" { target { ! arm_thumb2 } } } } */
+/* { dg-final { scan-assembler "lsrs\tr\[0-9\]" } } */
diff --git a/gcc/testsuite/gcc.target/arm/interrupt-1.c b/gcc/testsuite/gcc.target/arm/interrupt-1.c
index a38424228cf..debbaf78cc8 100644
--- a/gcc/testsuite/gcc.target/arm/interrupt-1.c
+++ b/gcc/testsuite/gcc.target/arm/interrupt-1.c
@@ -13,5 +13,5 @@ void foo ()
bar (0);
}
-/* { dg-final { scan-assembler "stmfd\tsp!, {r0, r1, r2, r3, r4, fp, ip, lr}" } } */
-/* { dg-final { scan-assembler "ldmfd\tsp!, {r0, r1, r2, r3, r4, fp, ip, pc}\\^" } } */
+/* { dg-final { scan-assembler "push\t{r0, r1, r2, r3, r4, fp, ip, lr}" } } */
+/* { dg-final { scan-assembler "pop\t{r0, r1, r2, r3, r4, fp, ip, pc}\\^" } } */
diff --git a/gcc/testsuite/gcc.target/arm/interrupt-2.c b/gcc/testsuite/gcc.target/arm/interrupt-2.c
index 61d31305367..92f8630e016 100644
--- a/gcc/testsuite/gcc.target/arm/interrupt-2.c
+++ b/gcc/testsuite/gcc.target/arm/interrupt-2.c
@@ -15,5 +15,5 @@ void test()
foo = 0;
}
-/* { dg-final { scan-assembler "stmfd\tsp!, {r0, r1, r2, r3, r4, r5, ip, lr}" } } */
-/* { dg-final { scan-assembler "ldmfd\tsp!, {r0, r1, r2, r3, r4, r5, ip, pc}\\^" } } */
+/* { dg-final { scan-assembler "push\t{r0, r1, r2, r3, r4, r5, ip, lr}" } } */
+/* { dg-final { scan-assembler "pop\t{r0, r1, r2, r3, r4, r5, ip, pc}\\^" } } */
diff --git a/gcc/testsuite/gcc.target/arm/mincmp.c b/gcc/testsuite/gcc.target/arm/mincmp.c
deleted file mode 100644
index ade3bd9e149..00000000000
--- a/gcc/testsuite/gcc.target/arm/mincmp.c
+++ /dev/null
@@ -1,20 +0,0 @@
-/* { dg-do compile } */
-/* { dg-options "-O2" } */
-/* { dg-require-effective-target arm32 } */
-
-#define min(x, y) ((x) <= (y)) ? (x) : (y)
-
-unsigned int
-foo (unsigned int i, unsigned int x, unsigned int y)
-{
- return i < (min (x, y));
-}
-
-int
-bar (int i, int x, int y)
-{
- return i < (min (x, y));
-}
-
-/* { dg-final { scan-assembler "cmpcs" } } */
-/* { dg-final { scan-assembler "cmpge" } } */
diff --git a/gcc/testsuite/gcc.target/arm/unaligned-memcpy-4.c b/gcc/testsuite/gcc.target/arm/unaligned-memcpy-4.c
index 830e22e09df..d2365131d88 100644
--- a/gcc/testsuite/gcc.target/arm/unaligned-memcpy-4.c
+++ b/gcc/testsuite/gcc.target/arm/unaligned-memcpy-4.c
@@ -14,7 +14,7 @@ void aligned_both (void)
/* We know both src and dest to be aligned: expect multiword loads/stores. */
-/* { dg-final { scan-assembler-times "ldmia" 1 { target { ! { arm_prefer_ldrd_strd } } } } } */
+/* { dg-final { scan-assembler-times "ldm" 1 { target { ! { arm_prefer_ldrd_strd } } } } } */
/* { dg-final { scan-assembler-times "stmia" 1 { target { ! { arm_prefer_ldrd_strd } } } } } */
/* { dg-final { scan-assembler "ldrd" { target { arm_prefer_ldrd_strd } } } } */
/* { dg-final { scan-assembler-times "ldm" 0 { target { arm_prefer_ldrd_strd } } } } */
diff --git a/gcc/testsuite/gcc.target/i386/addr-space-1.c b/gcc/testsuite/gcc.target/i386/addr-space-1.c
new file mode 100644
index 00000000000..1e1314760e2
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/addr-space-1.c
@@ -0,0 +1,11 @@
+/* { dg-do compile */
+/* { dg-options "-O2" } */
+/* { dg-final { scan-assembler "movl\[ \t\]%gs:\\((%eax|%rax)\\), %eax" } } */
+
+extern __seg_gs int *call_me (void);
+
+int
+read_seg_gs (void)
+{
+ return *call_me();
+}
diff --git a/gcc/testsuite/gcc.target/i386/addr-space-2.c b/gcc/testsuite/gcc.target/i386/addr-space-2.c
new file mode 100644
index 00000000000..d5c24b61096
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/addr-space-2.c
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-options "-O" } */
+/* { dg-final { scan-assembler "fs:16" } } */
+/* { dg-final { scan-assembler "gs:16" } } */
+
+int test(void)
+{
+ int __seg_fs *f = (int __seg_fs *)16;
+ int __seg_gs *g = (int __seg_gs *)16;
+ return *f + *g;
+}
diff --git a/gcc/testsuite/gcc.target/i386/addr-space-3.c b/gcc/testsuite/gcc.target/i386/addr-space-3.c
new file mode 100644
index 00000000000..63f1f031a08
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/addr-space-3.c
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { dg-options "-O" } */
+/* { dg-final { scan-assembler "[fg]s:0" } } */
+
+void test(int *y)
+{
+ int *x = (int __seg_tls *)0;
+ if (x == y)
+ asm("");
+}
diff --git a/gcc/testsuite/gcc.target/i386/movbe-3.c b/gcc/testsuite/gcc.target/i386/movbe-3.c
new file mode 100644
index 00000000000..985bc1eb29e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/movbe-3.c
@@ -0,0 +1,19 @@
+/* { dg-do compile } */
+/* { dg-options "-O -mmovbe" } */
+
+struct __attribute__((scalar_storage_order("big-endian"))) S
+{
+ int i;
+};
+
+int get (struct S *s)
+{
+ return s->i;
+}
+
+void set (struct S *s, int i)
+{
+ s->i = i;
+}
+
+/* { dg-final { scan-assembler-times "movbe\[ \t\]" 2 } } */
diff --git a/gcc/testsuite/gfortran.dg/allocate_with_arrayspec_1.f90 b/gcc/testsuite/gfortran.dg/allocate_with_arrayspec_1.f90
new file mode 100644
index 00000000000..686b612408a
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/allocate_with_arrayspec_1.f90
@@ -0,0 +1,29 @@
+! { dg-do run }
+! { dg-options "-fdump-tree-original" }
+
+MODULE mo_test
+
+ integer :: n = 0
+CONTAINS
+
+ FUNCTION nquery()
+ INTEGER :: nquery
+ WRITE (0,*) "hello!"
+ n = n + 1
+ nquery = n
+ END FUNCTION nquery
+
+END MODULE mo_test
+
+
+! ----------------------------------------------------------------------
+! MAIN PROGRAM
+! ----------------------------------------------------------------------
+PROGRAM example
+ USE mo_test
+ INTEGER, ALLOCATABLE :: query_buf(:)
+ ALLOCATE(query_buf(nquery()))
+ if (n /= 1 .or. size(query_buf) /= n) call abort()
+END PROGRAM example
+
+! { dg-final { scan-tree-dump-times "nquery" 5 "original" } }
diff --git a/gcc/testsuite/gfortran.dg/goacc/combined_loop.f90 b/gcc/testsuite/gfortran.dg/goacc/combined_loop.f90
index abb10f93067..e0ea87af86d 100644
--- a/gcc/testsuite/gfortran.dg/goacc/combined_loop.f90
+++ b/gcc/testsuite/gfortran.dg/goacc/combined_loop.f90
@@ -1,4 +1,7 @@
! { dg-do compile }
+! <http://news.gmane.org/find-root.php?message_id=%3C563B78B5.5090506%40acm.org%3E>
+! { dg-xfail-if "TODO" { *-*-* } }
+
!
! PR fortran/64726
!
diff --git a/gcc/testsuite/gfortran.dg/goacc/parallel-kernels-regions.f95 b/gcc/testsuite/gfortran.dg/goacc/parallel-kernels-regions.f95
index 8b8e9893995..7d8fb928659 100644
--- a/gcc/testsuite/gfortran.dg/goacc/parallel-kernels-regions.f95
+++ b/gcc/testsuite/gfortran.dg/goacc/parallel-kernels-regions.f95
@@ -9,46 +9,46 @@ program test
integer :: i
!$acc parallel
- !$acc kernels ! { dg-bogus "kernels construct inside of parallel region" "not implemented" { xfail *-*-* } }
+ !$acc kernels ! { dg-bogus ".kernels. construct inside of .parallel. region" "not implemented" { xfail *-*-* } }
!$acc end kernels
!$acc end parallel
!$acc parallel
- !$acc parallel ! { dg-bogus "parallel construct inside of parallel region" "not implemented" { xfail *-*-* } }
+ !$acc parallel ! { dg-bogus ".parallel. construct inside of .parallel. region" "not implemented" { xfail *-*-* } }
!$acc end parallel
!$acc end parallel
!$acc parallel
- !$acc parallel ! { dg-bogus "parallel construct inside of parallel region" "not implemented" { xfail *-*-* } }
+ !$acc parallel ! { dg-bogus ".parallel. construct inside of .parallel. region" "not implemented" { xfail *-*-* } }
!$acc end parallel
- !$acc kernels ! { dg-bogus "kernels construct inside of parallel region" "not implemented" { xfail *-*-* } }
+ !$acc kernels ! { dg-bogus ".kernels. construct inside of .parallel. region" "not implemented" { xfail *-*-* } }
!$acc end kernels
!$acc end parallel
!$acc kernels
- !$acc kernels ! { dg-bogus "kernels construct inside of kernels region" "not implemented" { xfail *-*-* } }
+ !$acc kernels ! { dg-bogus ".kernels. construct inside of .kernels. region" "not implemented" { xfail *-*-* } }
!$acc end kernels
!$acc end kernels
!$acc kernels
- !$acc parallel ! { dg-bogus "parallel construct inside of kernels region" "not implemented" { xfail *-*-* } }
+ !$acc parallel ! { dg-bogus ".parallel. construct inside of .kernels. region" "not implemented" { xfail *-*-* } }
!$acc end parallel
!$acc end kernels
!$acc kernels
- !$acc parallel ! { dg-bogus "parallel construct inside of kernels region" "not implemented" { xfail *-*-* } }
+ !$acc parallel ! { dg-bogus ".parallel. construct inside of .kernels. region" "not implemented" { xfail *-*-* } }
!$acc end parallel
- !$acc kernels ! { dg-bogus "kernels construct inside of kernels region" "not implemented" { xfail *-*-* } }
+ !$acc kernels ! { dg-bogus ".kernels. construct inside of .kernels. region" "not implemented" { xfail *-*-* } }
!$acc end kernels
!$acc end kernels
!$acc parallel
- !$acc data ! { dg-error "data construct inside of parallel region" }
+ !$acc data ! { dg-error ".data. construct inside of .parallel. region" }
!$acc end data
!$acc end parallel
!$acc kernels
- !$acc data ! { dg-error "data construct inside of kernels region" }
+ !$acc data ! { dg-error ".data. construct inside of .kernels. region" }
!$acc end data
!$acc end kernels
diff --git a/gcc/testsuite/gfortran.dg/goacc/private-3.f95 b/gcc/testsuite/gfortran.dg/goacc/private-3.f95
index aa12a56f110..af7d683f818 100644
--- a/gcc/testsuite/gfortran.dg/goacc/private-3.f95
+++ b/gcc/testsuite/gfortran.dg/goacc/private-3.f95
@@ -1,4 +1,6 @@
! { dg-do compile }
+! <http://news.gmane.org/find-root.php?message_id=%3C563B78B5.5090506%40acm.org%3E>
+! { dg-xfail-if "TODO" { *-*-* } }
! test for private variables in a reduction clause
@@ -7,7 +9,6 @@ program test
integer, parameter :: n = 100
integer :: i, k
-! FIXME: This causes an ICE in the gimplifier.
! !$acc parallel private (k) reduction (+:k)
! do i = 1, n
! k = k + 1
diff --git a/gcc/testsuite/gfortran.dg/gomp/target3.f90 b/gcc/testsuite/gfortran.dg/gomp/target3.f90
index 53a9682bf96..7ba42a04037 100644
--- a/gcc/testsuite/gfortran.dg/gomp/target3.f90
+++ b/gcc/testsuite/gfortran.dg/gomp/target3.f90
@@ -4,7 +4,7 @@
subroutine foo (r)
integer :: i, r
!$omp target
- !$omp target teams distribute parallel do reduction (+: r) ! { dg-warning "target construct inside of target region" }
+ !$omp target teams distribute parallel do reduction (+: r) ! { dg-warning ".target. construct inside of .target. region" }
do i = 1, 10
r = r + 1
end do
diff --git a/gcc/testsuite/gfortran.dg/graphite/PR53852.f90 b/gcc/testsuite/gfortran.dg/graphite/PR53852.f90
new file mode 100644
index 00000000000..f1f1fc5c790
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/graphite/PR53852.f90
@@ -0,0 +1,37 @@
+! { dg-do compile }
+! { dg-options "-floop-nest-optimize -O2 -ffast-math" }
+! PR53852 : compile time / memory hog
+SUBROUTINE build_d_tensor_gks(d5f,v,d5)
+ INTEGER, PARAMETER :: dp=8
+ REAL(KIND=dp), DIMENSION(3, 3, 3, 3, 3), &
+ INTENT(OUT) :: d5f
+ REAL(KIND=dp), DIMENSION(3), INTENT(IN) :: v
+ REAL(KIND=dp), INTENT(IN) :: d5
+ INTEGER :: k1, k2, k3, k4, k5
+ REAL(KIND=dp) :: w
+
+ d5f = 0.0_dp
+ DO k1=1,3
+ DO k2=1,3
+ DO k3=1,3
+ DO k4=1,3
+ DO k5=1,3
+ d5f(k5,k4,k3,k2,k1)=d5f(k5,k4,k3,k2,k1)+ &
+ v(k1)*v(k2)*v(k3)*v(k4)*v(k5)*d5
+ ENDDO
+ w=v(k1)*v(k2)*v(k3)*d4
+ d5f(k1,k2,k3,k4,k4)=d5f(k1,k2,k3,k4,k4)+w
+ d5f(k1,k2,k4,k3,k4)=d5f(k1,k2,k4,k3,k4)+w
+ d5f(k1,k4,k2,k3,k4)=d5f(k1,k4,k2,k3,k4)+w
+ d5f(k4,k1,k2,k3,k4)=d5f(k4,k1,k2,k3,k4)+w
+ d5f(k1,k2,k4,k4,k3)=d5f(k1,k2,k4,k4,k3)+w
+ d5f(k1,k4,k2,k4,k3)=d5f(k1,k4,k2,k4,k3)+w
+ d5f(k4,k1,k2,k4,k3)=d5f(k4,k1,k2,k4,k3)+w
+ d5f(k1,k4,k4,k2,k3)=d5f(k1,k4,k4,k2,k3)+w
+ d5f(k4,k1,k4,k2,k3)=d5f(k4,k1,k4,k2,k3)+w
+ d5f(k4,k4,k1,k2,k3)=d5f(k4,k4,k1,k2,k3)+w
+ ENDDO
+ ENDDO
+ ENDDO
+ ENDDO
+END SUBROUTINE build_d_tensor_gks
diff --git a/gcc/testsuite/gfortran.dg/graphite/PR67518.f90 b/gcc/testsuite/gfortran.dg/graphite/PR67518.f90
new file mode 100644
index 00000000000..beb343e6057
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/graphite/PR67518.f90
@@ -0,0 +1,45 @@
+! { dg-do compile }
+! { dg-options "-floop-nest-optimize -O2 -ffast-math" }
+! PR67518 : isl: position out of bounds
+MODULE ao_util
+ INTEGER, PARAMETER :: dp=8
+CONTAINS
+ FUNCTION exp_radius(l,alpha,threshold,prefactor,epsin) RESULT(radius)
+ REAL(KIND=dp), INTENT(IN) :: alpha, threshold, prefactor
+ REAL(KIND=dp), INTENT(IN), OPTIONAL :: epsin
+ DO
+ IF (iter.gt.maxiter) THEN
+ CALL stop_program(routineN,moduleN,1,"exceeded")
+ ENDIF
+ ENDDO
+ CALL stop_program(routineN,moduleN,1,"exceeded")
+ END FUNCTION exp_radius
+ FUNCTION exp_radius_very_extended(la_min,la_max,lb_min,lb_max,pab,o1,o2,ra,rb,rp,&
+ zetp,eps,prefactor,cutoff,epsin) RESULT(radius)
+ REAL(KIND=dp), DIMENSION(:, :), &
+ OPTIONAL, POINTER :: pab
+ REAL(KIND=dp), INTENT(IN) :: ra(3), rb(3), rp(3), zetp, &
+ eps, prefactor, cutoff
+ REAL(KIND=dp) :: bini, binj, coef(0:20), &
+ epsin_local, polycoef(0:60), &
+ rad_b, s1, s2
+ IF (PRESENT(pab)) THEN
+ ENDIF
+ DO lxa=0,la_max
+ DO lxb=0,lb_max
+ coef(0:la_max+lb_max)=0.0_dp
+ DO i=0,lxa
+ DO j=0,lxb
+ coef(lxa+lxb-i-j)=coef(lxa+lxb-i-j) + bini*binj*s1*s2
+ ENDDO
+ ENDDO
+ DO i=0,lxa+lxb
+ polycoef(i)=MAX(polycoef(i),coef(i))
+ ENDDO
+ ENDDO
+ ENDDO
+ DO i=0,la_max+lb_max
+ radius=MAX(radius,exp_radius(i,zetp,eps,polycoef(i),epsin_local) )
+ ENDDO
+ END FUNCTION exp_radius_very_extended
+END MODULE ao_util
diff --git a/gcc/testsuite/gfortran.dg/pr66465.f90 b/gcc/testsuite/gfortran.dg/pr66465.f90
new file mode 100644
index 00000000000..ab868305051
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/pr66465.f90
@@ -0,0 +1,23 @@
+! { dg-do compile }
+!
+! Tests the fix for PR66465, in which the arguments of the call to
+! ASSOCIATED were falsly detected to have different type/kind.
+!
+! Contributed by Damian Rouson <damian@sourceryinstitute.org>
+!
+ interface
+ real function HandlerInterface (arg)
+ real :: arg
+ end
+ end interface
+
+ type TextHandlerTestCase
+ procedure (HandlerInterface), nopass, pointer :: handlerOut=>null()
+ end type
+
+ type(TextHandlerTestCase) this
+
+ procedure (HandlerInterface), pointer :: procPtr=>null()
+
+ print*, associated(procPtr, this%handlerOut)
+end
diff --git a/gcc/testsuite/gfortran.dg/pr68053.f90 b/gcc/testsuite/gfortran.dg/pr68053.f90
new file mode 100644
index 00000000000..e59693c5f66
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/pr68053.f90
@@ -0,0 +1,10 @@
+! { dg-do run }
+! PR fortran/68053
+! Original code contributed by Gerhard Steinmetz
+! <gerhard dot steinmetx dot fortran at t-online dot de>
+program p
+ integer, parameter :: n(3) = [1,2,3]
+ integer, parameter :: x(1) = 7
+ integer, parameter :: z(n(2):*) = x
+ if (lbound(z,1) /= 2) call abort
+end
diff --git a/gcc/testsuite/gfortran.dg/pr68151.f90 b/gcc/testsuite/gfortran.dg/pr68151.f90
new file mode 100644
index 00000000000..830d9f4f437
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/pr68151.f90
@@ -0,0 +1,13 @@
+! { dg-do compile }
+! PR fortran/68151
+! Original code contribute by Gerhard Steinmetz
+! <gerhard dot steinmetz dot fortran at t-online dot de>
+!
+program p
+ integer :: k = 1
+ select case (k)
+ case (:huge(1._4)) ! { dg-error "Expression in CASE" }
+ case (:huge(2._8)) ! { dg-error "Expression in CASE" }
+ case ((1.0,2.0)) ! { dg-error "Expression in CASE" }
+ end select
+end
diff --git a/gcc/testsuite/gfortran.dg/pr68153.f90 b/gcc/testsuite/gfortran.dg/pr68153.f90
new file mode 100644
index 00000000000..1a360f80cd6
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/pr68153.f90
@@ -0,0 +1,9 @@
+! { dg-do compile }
+! PR fortran/68153
+! Original code contribute by Gerhard Steinmetz
+! <gerhard dot steinmetz dot fortran at t-online dot de>
+!
+program foo
+ integer, parameter :: a(2) = [2, -2]
+ integer, parameter :: b(2,2) = reshape([1, 2, 3, 4], a) ! { dg-error "cannot be negative" }
+end program foo
diff --git a/gcc/testsuite/gfortran.dg/pr68224.f90 b/gcc/testsuite/gfortran.dg/pr68224.f90
new file mode 100644
index 00000000000..a5962bb8661
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/pr68224.f90
@@ -0,0 +1,10 @@
+! { dg-do compile }
+! PR fortran/68224
+! Original code contribute by Gerhard Steinmetz
+! <gerhard dot steinmetz dot fortran at t-online dot de>
+!
+program p
+ integer, parameter :: a(null()) = [1, 2] ! { dg-error "scalar INTEGER expression" }
+ integer, parameter :: b(null():*) = [1, 2] ! { dg-error "scalar INTEGER expression" }
+ integer, parameter :: c(1:null()) = [1, 2] ! { dg-error "scalar INTEGER expression" }
+end program p
diff --git a/gcc/testsuite/gfortran.dg/proc_ptr_47.f90 b/gcc/testsuite/gfortran.dg/proc_ptr_47.f90
new file mode 100644
index 00000000000..43084f67e40
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/proc_ptr_47.f90
@@ -0,0 +1,37 @@
+! { dg-do run }
+! Tests the fix for PR68196
+!
+! Contributed by Damian Rouson <damian@sourceryinstitute.org>
+!
+ type AA
+ integer :: i
+ procedure(foo), pointer :: funct
+ end type
+ class(AA), allocatable :: my_AA
+ type(AA) :: res
+
+ allocate (my_AA, source = AA (1, foo))
+
+ res = my_AA%funct ()
+
+ if (res%i .ne. 3) call abort
+ if (.not.associated (res%funct)) call abort
+ if (my_AA%i .ne. 4) call abort
+ if (associated (my_AA%funct)) call abort
+
+contains
+ function foo(A)
+ class(AA), allocatable :: A
+ type(AA) foo
+
+ if (.not.allocated (A)) then
+ allocate (A, source = AA (2, foo))
+ endif
+
+ select type (A)
+ type is (AA)
+ foo = AA (3, foo)
+ A = AA (4, NULL ())
+ end select
+ end function
+end
diff --git a/gcc/testsuite/gfortran.dg/warn_unused_function_2.f90 b/gcc/testsuite/gfortran.dg/warn_unused_function_2.f90
index 8d65dabef89..958cc969253 100644
--- a/gcc/testsuite/gfortran.dg/warn_unused_function_2.f90
+++ b/gcc/testsuite/gfortran.dg/warn_unused_function_2.f90
@@ -2,6 +2,7 @@
! { dg-options "-Wall" }
!
! [4.8 Regression] PR 54997: -Wunused-function gives false warnings
+! PR 54224: missing warnings with -Wunused-function
!
! Contributed by Janus Weil <janus@gcc.gnu.org>
@@ -14,6 +15,9 @@ contains
subroutine s1 ! { dg-warning "defined but not used" }
call s2(s3)
+ contains
+ subroutine s4 ! { dg-warning "defined but not used" }
+ end subroutine
end subroutine
subroutine s2(dummy) ! { dg-warning "Unused dummy argument" }
@@ -30,5 +34,10 @@ subroutine sub
entry en
end subroutine
+program test
+contains
+ subroutine s5 ! { dg-warning "defined but not used" }
+ end subroutine
+end
! { dg-final { cleanup-modules "m" } }
diff --git a/gcc/testsuite/gnat.dg/specs/sso1.ads b/gcc/testsuite/gnat.dg/specs/sso1.ads
new file mode 100644
index 00000000000..48172a5a6b9
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/specs/sso1.ads
@@ -0,0 +1,19 @@
+-- { dg-do compile }
+
+with System;
+
+package SSO1 is
+
+ type R is record -- { dg-error "inconsistent with bit order" }
+ B : Boolean;
+ end record;
+ for R'Bit_Order use System.Low_Order_First;
+ for R'Scalar_Storage_Order use System.High_Order_First; -- { dg-warning "no component clause" }
+
+ type RW is record
+ B : Boolean;
+ end record;
+ for RW'Bit_Order use System.Low_Order_First;
+ for RW'Scalar_Storage_Order use System.Low_Order_First; -- { dg-warning "no component clause" }
+
+end SSO1;
diff --git a/gcc/testsuite/gnat.dg/specs/sso2.ads b/gcc/testsuite/gnat.dg/specs/sso2.ads
new file mode 100644
index 00000000000..328ca6461af
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/specs/sso2.ads
@@ -0,0 +1,26 @@
+-- { dg-do compile }
+-- { dg-options "-gnatws" }
+
+with System;
+
+package SSO2 is
+
+ I : Integer;
+
+ type Rec1 is record
+ A : System.Address;
+ end record;
+ for Rec1'Bit_Order use System.High_Order_First;
+ for Rec1'Scalar_Storage_Order use System.High_Order_First;
+
+ R1 : Rec1 := (A => I'Address);
+
+ type Rec2 is record
+ A : System.Address;
+ end record;
+ for Rec2'Bit_Order use System.Low_Order_First;
+ for Rec2'Scalar_Storage_Order use System.Low_Order_First;
+
+ R2 : Rec2 := (A => I'Address);
+
+end SSO2;
diff --git a/gcc/testsuite/gnat.dg/sso/conv1.adb b/gcc/testsuite/gnat.dg/sso/conv1.adb
new file mode 100644
index 00000000000..8cdb612d0a3
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/sso/conv1.adb
@@ -0,0 +1,50 @@
+-- { dg-do run }
+
+with System; use System;
+with Ada.Text_IO; use Ada.Text_IO;
+
+procedure Conv1 is
+ type Short is mod 2**16;
+
+ type R_L is record
+ S : Short;
+ C : Character;
+ end record;
+ for R_L'Bit_Order use Low_Order_First;
+ for R_L'Scalar_Storage_Order use Low_Order_First;
+ for R_L use record
+ S at 0 range 0 .. 15;
+ C at 2 range 0 .. 7;
+ end record;
+
+ type R_H is new R_L;
+ for R_H'Bit_Order use High_Order_First;
+ for R_H'Scalar_Storage_Order use High_Order_First;
+ for R_H use record
+ S at 0 range 0 .. 15;
+ C at 2 range 0 .. 7;
+ end record;
+
+ procedure Dump (Name : String; S : Short; C : Character) is
+ begin
+ Put_Line (Name & " = (S =>" & S'Img & ", C => '" & C & "')");
+ end Dump;
+
+ X_L : R_L;
+ X_H : R_H;
+begin
+ X_L.S := 12345;
+ X_L.C := 'a';
+ Dump ("X_L", X_L.S, X_L.C);
+ -- { dg-output "X_L = \\(S => 12345, C => 'a'\\)\n" }
+
+ X_H.S := 23456;
+ X_H.C := 'b';
+ Dump ("X_H", X_H.S, X_H.C);
+ -- { dg-output "X_H = \\(S => 23456, C => 'b'\\)\n" }
+
+ X_H := R_H (X_L);
+ Dump ("X_H", X_H.S, X_H.C);
+ -- { dg-output "X_H = \\(S => 12345, C => 'a'\\)\n" }
+
+end;
diff --git a/gcc/testsuite/gnat.dg/sso/dump.adb b/gcc/testsuite/gnat.dg/sso/dump.adb
new file mode 100644
index 00000000000..4e1d0ff7e9d
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/sso/dump.adb
@@ -0,0 +1,17 @@
+-- { dg-do compile }
+
+with Text_IO; use Text_IO;
+
+procedure Dump (A : System.Address; Len : Storage_Offset) is
+
+ Arr : Storage_Array (1 .. Len);
+ for Arr'Address use A;
+ pragma Import (Ada, Arr);
+
+ H : constant array (Storage_Element range 0 .. 15) of Character :=
+ "0123456789abcdef";
+begin
+ for J in Arr'Range loop
+ Put (' ' & H (Arr (J) / 16) & H (Arr (J) mod 16));
+ end loop;
+end;
diff --git a/gcc/testsuite/gnat.dg/sso/dump.ads b/gcc/testsuite/gnat.dg/sso/dump.ads
new file mode 100644
index 00000000000..ce6a7fa83e6
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/sso/dump.ads
@@ -0,0 +1,3 @@
+with System.Storage_Elements; use System.Storage_Elements;
+
+procedure Dump (A : System.Address; Len : Storage_Offset);
diff --git a/gcc/testsuite/gnat.dg/sso/init1.ads b/gcc/testsuite/gnat.dg/sso/init1.ads
new file mode 100644
index 00000000000..16cb6e0193d
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/sso/init1.ads
@@ -0,0 +1,26 @@
+with System;
+
+package Init1 is
+
+ type R1 is record
+ I : Integer;
+ end record;
+ for R1'Bit_Order use System.Low_Order_First;
+ for R1'Scalar_Storage_Order use System.Low_Order_First;
+ for R1 use record
+ I at 0 range 0 .. 31;
+ end record;
+
+ type R2 is record
+ I : Integer;
+ end record;
+ for R2'Bit_Order use System.High_Order_First;
+ for R2'Scalar_Storage_Order use System.High_Order_First;
+ for R2 use record
+ I at 0 range 0 .. 31;
+ end record;
+
+ My_R1 : constant R1 := (I => 16#12345678#);
+ My_R2 : constant R2 := (I => 16#12345678#);
+
+end Init1;
diff --git a/gcc/testsuite/gnat.dg/sso/init10.ads b/gcc/testsuite/gnat.dg/sso/init10.ads
new file mode 100644
index 00000000000..a32ec7eb38e
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/sso/init10.ads
@@ -0,0 +1,23 @@
+with System;
+
+package Init10 is
+
+ type My_Integer is new Integer;
+ for My_Integer'Alignment use 1;
+
+ type R1 is record
+ I : My_Integer;
+ end record;
+ for R1'Bit_Order use System.Low_Order_First;
+ for R1'Scalar_Storage_Order use System.Low_Order_First;
+
+ type R2 is record
+ I : My_Integer;
+ end record;
+ for R2'Bit_Order use System.High_Order_First;
+ for R2'Scalar_Storage_Order use System.High_Order_First;
+
+ My_R1 : constant R1 := (I => 16#12345678#);
+ My_R2 : constant R2 := (I => 16#12345678#);
+
+end Init10;
diff --git a/gcc/testsuite/gnat.dg/sso/init11.ads b/gcc/testsuite/gnat.dg/sso/init11.ads
new file mode 100644
index 00000000000..a3ca4117a2f
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/sso/init11.ads
@@ -0,0 +1,34 @@
+with System;
+
+package Init11 is
+
+ type My_Integer is new Integer;
+ for My_Integer'Alignment use 1;
+
+ type Arr1 is array (1 .. 3) of My_Integer;
+ for Arr1'Scalar_Storage_Order use System.Low_Order_First;
+
+ type R1 is record
+ I : My_Integer;
+ A : Arr1;
+ end record;
+ for R1'Bit_Order use System.Low_Order_First;
+ for R1'Scalar_Storage_Order use System.Low_Order_First;
+
+ type Arr2 is array (1 .. 3) of My_Integer;
+ for Arr2'Scalar_Storage_Order use System.High_Order_First;
+
+ type R2 is record
+ I : My_Integer;
+ A : Arr2;
+ end record;
+ for R2'Bit_Order use System.High_Order_First;
+ for R2'Scalar_Storage_Order use System.High_Order_First;
+
+ My_R1 : constant R1 := (I => 16#12345678#,
+ A => (16#AB0012#, 16#CD0034#, 16#EF0056#));
+
+ My_R2 : constant R2 := (I => 16#12345678#,
+ A => (16#AB0012#, 16#CD0034#, 16#EF0056#));
+
+end Init11;
diff --git a/gcc/testsuite/gnat.dg/sso/init12.ads b/gcc/testsuite/gnat.dg/sso/init12.ads
new file mode 100644
index 00000000000..c70794b9b6a
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/sso/init12.ads
@@ -0,0 +1,25 @@
+with System;
+
+package Init12 is
+
+ type Arr1 is array (1 .. 3) of Integer;
+ for Arr1'Scalar_Storage_Order use System.Low_Order_First;
+
+ type Arr11 is array (1 .. 2, 1 .. 2) of Integer;
+ for Arr11'Scalar_Storage_Order use System.Low_Order_First;
+
+ type Arr2 is array (1 .. 3) of Integer;
+ for Arr2'Scalar_Storage_Order use System.High_Order_First;
+
+ type Arr22 is array (1 .. 2, 1 .. 2) of Integer;
+ for Arr22'Scalar_Storage_Order use System.High_Order_First;
+
+ My_A1 : constant Arr1 := (16#AB0012#, 16#CD0034#, 16#EF0056#);
+ My_A11 : constant Arr11 := (1 => (16#AB0012#, 16#CD0034#),
+ 2 => (16#AB0012#, 16#CD0034#));
+
+ My_A2 : constant Arr2 := (16#AB0012#, 16#CD0034#, 16#EF0056#);
+ My_A22 : constant Arr22 := (1 => (16#AB0012#, 16#CD0034#),
+ 2 => (16#AB0012#, 16#CD0034#));
+
+end Init12;
diff --git a/gcc/testsuite/gnat.dg/sso/init13.ads b/gcc/testsuite/gnat.dg/sso/init13.ads
new file mode 100644
index 00000000000..9cac9e9c567
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/sso/init13.ads
@@ -0,0 +1,33 @@
+with Ada.Numerics; use Ada.Numerics;
+with System;
+
+package Init13 is
+
+ type Complex is record
+ R : Float;
+ I : Float;
+ end record;
+ pragma Complex_Representation (Complex);
+
+ type R1 is record
+ F : Complex;
+ end record;
+ for R1'Bit_Order use System.Low_Order_First;
+ for R1'Scalar_Storage_Order use System.Low_Order_First;
+ for R1 use record
+ F at 0 range 0 .. 63;
+ end record;
+
+ type R2 is record
+ F : Complex;
+ end record;
+ for R2'Bit_Order use System.High_Order_First;
+ for R2'Scalar_Storage_Order use System.High_Order_First;
+ for R2 use record
+ F at 0 range 0 .. 63;
+ end record;
+
+ My_R1 : constant R1 := (F => (Pi, -Pi));
+ My_R2 : constant R2 := (F => (Pi, -Pi));
+
+end Init13;
diff --git a/gcc/testsuite/gnat.dg/sso/init2.ads b/gcc/testsuite/gnat.dg/sso/init2.ads
new file mode 100644
index 00000000000..48a1962b3bd
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/sso/init2.ads
@@ -0,0 +1,69 @@
+with System;
+
+package Init2 is
+
+ type Small is mod 2**2;
+ for Small'Size use 2;
+
+ type Count is mod 2**9;
+ for Count'Size use 9;
+
+ type Arr1 is array (1 .. 3) of Count;
+ pragma Pack (Arr1);
+ for Arr1'Size use 27;
+ for Arr1'Scalar_Storage_Order use System.Low_Order_First;
+
+ type R1 is record
+ S1 : Small;
+ I : Integer;
+ S2 : Small;
+ A : Arr1;
+ B : Boolean;
+ end record;
+ for R1'Bit_Order use System.Low_Order_First;
+ for R1'Scalar_Storage_Order use System.Low_Order_First;
+ for R1 use record
+ S1 at 0 range 0 .. 1;
+ I at 0 range 2 .. 33;
+ S2 at 0 range 34 .. 35;
+ A at 0 range 36 .. 62;
+ B at 0 range 63 .. 63;
+ end record;
+ for R1'Size use 64;
+
+ type Arr2 is array (1 .. 3) of Count;
+ pragma Pack (Arr2);
+ for Arr2'Size use 27;
+ for Arr2'Scalar_Storage_Order use System.High_Order_First;
+
+ type R2 is record
+ S1 : Small;
+ I : Integer;
+ S2 : Small;
+ A : Arr2;
+ B : Boolean;
+ end record;
+ for R2'Bit_Order use System.High_Order_First;
+ for R2'Scalar_Storage_Order use System.High_Order_First;
+ for R2 use record
+ S1 at 0 range 0 .. 1;
+ I at 0 range 2 .. 33;
+ S2 at 0 range 34 .. 35;
+ A at 0 range 36 .. 62;
+ B at 0 range 63 .. 63;
+ end record;
+ for R2'Size use 64;
+
+ My_R1 : constant R1 := (S1 => 2,
+ I => 16#12345678#,
+ S2 => 1,
+ A => (16#AB#, 16#CD#, 16#EF#),
+ B => True);
+
+ My_R2 : constant R2 := (S1 => 2,
+ I => 16#12345678#,
+ S2 => 1,
+ A => (16#AB#, 16#CD#, 16#EF#),
+ B => True);
+
+end Init2;
diff --git a/gcc/testsuite/gnat.dg/sso/init3.ads b/gcc/testsuite/gnat.dg/sso/init3.ads
new file mode 100644
index 00000000000..1dd8c56c1a2
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/sso/init3.ads
@@ -0,0 +1,78 @@
+with System;
+
+package Init3 is
+
+ type Small is mod 2**2;
+ for Small'Size use 2;
+
+ type Count is mod 2**9;
+ for Count'Size use 9;
+
+ type Nested1 is record
+ C1 : Count;
+ C2 : Count;
+ C3 : Count;
+ end record;
+ pragma Pack (Nested1);
+ for Nested1'Size use 27;
+ for Nested1'Bit_Order use System.Low_Order_First;
+ for Nested1'Scalar_Storage_Order use System.Low_Order_First;
+
+ type R1 is record
+ S1 : Small;
+ I : Integer;
+ S2 : Small;
+ N : Nested1;
+ B : Boolean;
+ end record;
+ for R1'Bit_Order use System.Low_Order_First;
+ for R1'Scalar_Storage_Order use System.Low_Order_First;
+ for R1 use record
+ S1 at 0 range 0 .. 1;
+ I at 0 range 2 .. 33;
+ S2 at 0 range 34 .. 35;
+ N at 0 range 36 .. 62;
+ B at 0 range 63 .. 63;
+ end record;
+ for R1'Size use 64;
+
+ type Nested2 is record
+ C1 : Count;
+ C2 : Count;
+ C3 : Count;
+ end record;
+ pragma Pack (Nested2);
+ for Nested2'Size use 27;
+ for Nested2'Bit_Order use System.High_Order_First;
+ for Nested2'Scalar_Storage_Order use System.High_Order_First;
+ type R2 is record
+ S1 : Small;
+ I : Integer;
+ S2 : Small;
+ N : Nested2;
+ B : Boolean;
+ end record;
+ for R2'Bit_Order use System.High_Order_First;
+ for R2'Scalar_Storage_Order use System.High_Order_First;
+ for R2 use record
+ S1 at 0 range 0 .. 1;
+ I at 0 range 2 .. 33;
+ S2 at 0 range 34 .. 35;
+ N at 0 range 36 .. 62;
+ B at 0 range 63 .. 63;
+ end record;
+ for R2'Size use 64;
+
+ My_R1 : constant R1 := (S1 => 2,
+ I => 16#12345678#,
+ S2 => 1,
+ N => (16#AB#, 16#CD#, 16#EF#),
+ B => True);
+
+ My_R2 : constant R2 := (S1 => 2,
+ I => 16#12345678#,
+ S2 => 1,
+ N => (16#AB#, 16#CD#, 16#EF#),
+ B => True);
+
+end Init3;
diff --git a/gcc/testsuite/gnat.dg/sso/init4.ads b/gcc/testsuite/gnat.dg/sso/init4.ads
new file mode 100644
index 00000000000..f533a8e8514
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/sso/init4.ads
@@ -0,0 +1,27 @@
+with Ada.Numerics; use Ada.Numerics;
+with System;
+
+package Init4 is
+
+ type R1 is record
+ F : Float;
+ end record;
+ for R1'Bit_Order use System.Low_Order_First;
+ for R1'Scalar_Storage_Order use System.Low_Order_First;
+ for R1 use record
+ F at 0 range 0 .. 31;
+ end record;
+
+ type R2 is record
+ F : Float;
+ end record;
+ for R2'Bit_Order use System.High_Order_First;
+ for R2'Scalar_Storage_Order use System.High_Order_First;
+ for R2 use record
+ F at 0 range 0 .. 31;
+ end record;
+
+ My_R1 : constant R1 := (F => Pi);
+ My_R2 : constant R2 := (F => Pi);
+
+end Init4;
diff --git a/gcc/testsuite/gnat.dg/sso/init5.ads b/gcc/testsuite/gnat.dg/sso/init5.ads
new file mode 100644
index 00000000000..3ea8d1162a0
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/sso/init5.ads
@@ -0,0 +1,39 @@
+with System;
+
+package Init5 is
+
+ type Arr1 is array (1 .. 3) of Integer;
+ for Arr1'Scalar_Storage_Order use System.Low_Order_First;
+
+ type R1 is record
+ I : Integer;
+ A : Arr1;
+ end record;
+ for R1'Bit_Order use System.Low_Order_First;
+ for R1'Scalar_Storage_Order use System.Low_Order_First;
+ for R1 use record
+ I at 0 range 0 .. 31;
+ A at 4 range 0 .. 95;
+ end record;
+
+ type Arr2 is array (1 .. 3) of Integer;
+ for Arr2'Scalar_Storage_Order use System.High_Order_First;
+
+ type R2 is record
+ I : Integer;
+ A : Arr2;
+ end record;
+ for R2'Bit_Order use System.High_Order_First;
+ for R2'Scalar_Storage_Order use System.High_Order_First;
+ for R2 use record
+ I at 0 range 0 .. 31;
+ A at 4 range 0 .. 95;
+ end record;
+
+ My_R1 : constant R1 := (I => 16#12345678#,
+ A => (16#AB0012#, 16#CD0034#, 16#EF0056#));
+
+ My_R2 : constant R2 := (I => 16#12345678#,
+ A => (16#AB0012#, 16#CD0034#, 16#EF0056#));
+
+end Init5;
diff --git a/gcc/testsuite/gnat.dg/sso/init6.ads b/gcc/testsuite/gnat.dg/sso/init6.ads
new file mode 100644
index 00000000000..81351c1267d
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/sso/init6.ads
@@ -0,0 +1,39 @@
+with System;
+
+package Init6 is
+
+ type Arr1 is array (1 .. 3) of Integer;
+ for Arr1'Scalar_Storage_Order use System.High_Order_First;
+
+ type R1 is record
+ I : Integer;
+ A : Arr1;
+ end record;
+ for R1'Bit_Order use System.Low_Order_First;
+ for R1'Scalar_Storage_Order use System.Low_Order_First;
+ for R1 use record
+ I at 0 range 0 .. 31;
+ A at 4 range 0 .. 95;
+ end record;
+
+ type Arr2 is array (1 .. 3) of Integer;
+ for Arr2'Scalar_Storage_Order use System.Low_Order_First;
+
+ type R2 is record
+ I : Integer;
+ A : Arr2;
+ end record;
+ for R2'Bit_Order use System.High_Order_First;
+ for R2'Scalar_Storage_Order use System.High_Order_First;
+ for R2 use record
+ I at 0 range 0 .. 31;
+ A at 4 range 0 .. 95;
+ end record;
+
+ My_R1 : constant R1 := (I => 16#12345678#,
+ A => (16#AB0012#, 16#CD0034#, 16#EF0056#));
+
+ My_R2 : constant R2 := (I => 16#12345678#,
+ A => (16#AB0012#, 16#CD0034#, 16#EF0056#));
+
+end Init6;
diff --git a/gcc/testsuite/gnat.dg/sso/init7.ads b/gcc/testsuite/gnat.dg/sso/init7.ads
new file mode 100644
index 00000000000..a7965250d98
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/sso/init7.ads
@@ -0,0 +1,59 @@
+with System;
+
+package Init7 is
+
+ type Nested1 is record
+ C1 : Integer;
+ C2 : Integer;
+ C3 : Integer;
+ end record;
+ for Nested1'Bit_Order use System.Low_Order_First;
+ for Nested1'Scalar_Storage_Order use System.Low_Order_First;
+ for Nested1 use record
+ C1 at 0 range 0 .. 31;
+ C2 at 4 range 0 .. 31;
+ C3 at 8 range 0 .. 31;
+ end record;
+
+ type R1 is record
+ I : Integer;
+ N : Nested1;
+ end record;
+ for R1'Bit_Order use System.Low_Order_First;
+ for R1'Scalar_Storage_Order use System.Low_Order_First;
+ for R1 use record
+ I at 0 range 0 .. 31;
+ N at 4 range 0 .. 95;
+ end record;
+
+ type Nested2 is record
+ C1 : Integer;
+ C2 : Integer;
+ C3 : Integer;
+ end record;
+ for Nested2'Bit_Order use System.High_Order_First;
+ for Nested2'Scalar_Storage_Order use System.High_Order_First;
+ for Nested2 use record
+ C1 at 0 range 0 .. 31;
+ C2 at 4 range 0 .. 31;
+ C3 at 8 range 0 .. 31;
+ end record;
+
+ type R2 is record
+ I : Integer;
+ N : Nested2;
+ end record;
+ for R2'Bit_Order use System.High_Order_First;
+ for R2'Scalar_Storage_Order use System.High_Order_First;
+ for R2 use record
+ I at 0 range 0 .. 31;
+ N at 4 range 0 .. 95;
+ end record;
+
+ My_R1 : constant R1 := (I => 16#12345678#,
+ N => (16#AB0012#, 16#CD0034#, 16#EF0056#));
+
+ My_R2 : constant R2 := (I => 16#12345678#,
+ N => (16#AB0012#, 16#CD0034#, 16#EF0056#));
+
+end Init7;
diff --git a/gcc/testsuite/gnat.dg/sso/init8.ads b/gcc/testsuite/gnat.dg/sso/init8.ads
new file mode 100644
index 00000000000..ce912f6e0a0
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/sso/init8.ads
@@ -0,0 +1,59 @@
+with System;
+
+package Init8 is
+
+ type Nested1 is record
+ C1 : Integer;
+ C2 : Integer;
+ C3 : Integer;
+ end record;
+ for Nested1'Bit_Order use System.High_Order_First;
+ for Nested1'Scalar_Storage_Order use System.High_Order_First;
+ for Nested1 use record
+ C1 at 0 range 0 .. 31;
+ C2 at 4 range 0 .. 31;
+ C3 at 8 range 0 .. 31;
+ end record;
+
+ type R1 is record
+ I : Integer;
+ N : Nested1;
+ end record;
+ for R1'Bit_Order use System.Low_Order_First;
+ for R1'Scalar_Storage_Order use System.Low_Order_First;
+ for R1 use record
+ I at 0 range 0 .. 31;
+ N at 4 range 0 .. 95;
+ end record;
+
+ type Nested2 is record
+ C1 : Integer;
+ C2 : Integer;
+ C3 : Integer;
+ end record;
+ for Nested2'Bit_Order use System.Low_Order_First;
+ for Nested2'Scalar_Storage_Order use System.Low_Order_First;
+ for Nested2 use record
+ C1 at 0 range 0 .. 31;
+ C2 at 4 range 0 .. 31;
+ C3 at 8 range 0 .. 31;
+ end record;
+
+ type R2 is record
+ I : Integer;
+ N : Nested2;
+ end record;
+ for R2'Bit_Order use System.High_Order_First;
+ for R2'Scalar_Storage_Order use System.High_Order_First;
+ for R2 use record
+ I at 0 range 0 .. 31;
+ N at 4 range 0 .. 95;
+ end record;
+
+ My_R1 : constant R1 := (I => 16#12345678#,
+ N => (16#AB0012#, 16#CD0034#, 16#EF0056#));
+
+ My_R2 : constant R2 := (I => 16#12345678#,
+ N => (16#AB0012#, 16#CD0034#, 16#EF0056#));
+
+end Init8;
diff --git a/gcc/testsuite/gnat.dg/sso/init9.ads b/gcc/testsuite/gnat.dg/sso/init9.ads
new file mode 100644
index 00000000000..b8d8c8bd702
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/sso/init9.ads
@@ -0,0 +1,27 @@
+with Ada.Numerics; use Ada.Numerics;
+with System;
+
+package Init9 is
+
+ type R1 is record
+ F : Long_Float;
+ end record;
+ for R1'Bit_Order use System.Low_Order_First;
+ for R1'Scalar_Storage_Order use System.Low_Order_First;
+ for R1 use record
+ F at 0 range 0 .. 63;
+ end record;
+
+ type R2 is record
+ F : Long_Float;
+ end record;
+ for R2'Bit_Order use System.High_Order_First;
+ for R2'Scalar_Storage_Order use System.High_Order_First;
+ for R2 use record
+ F at 0 range 0 .. 63;
+ end record;
+
+ My_R1 : constant R1 := (F => Pi);
+ My_R2 : constant R2 := (F => Pi);
+
+end Init9;
diff --git a/gcc/testsuite/gnat.dg/sso/p1.adb b/gcc/testsuite/gnat.dg/sso/p1.adb
new file mode 100644
index 00000000000..514fa7eeda3
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/sso/p1.adb
@@ -0,0 +1,62 @@
+-- { dg-do run }
+
+with Init1; use Init1;
+with Text_IO; use Text_IO;
+with Dump;
+
+procedure P1 is
+
+ Local_R1 : R1;
+ Local_R2 : R2;
+
+begin
+ Put ("My_R1 :");
+ Dump (My_R1'Address, R1'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "My_R1 : 78 56 34 12\n" }
+
+ Put ("My_R2 :");
+ Dump (My_R2'Address, R2'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "My_R2 : 12 34 56 78\n" }
+
+ Local_R1 := My_R1;
+ Put ("Local_R1 :");
+ Dump (Local_R1'Address, R1'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "Local_R1 : 78 56 34 12\n" }
+
+ Local_R2 := My_R2;
+ Put ("Local_R2 :");
+ Dump (Local_R2'Address, R2'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "Local_R2 : 12 34 56 78\n" }
+
+ Local_R1.I := 16#12345678#;
+
+ Put ("Local_R1 :");
+ Dump (Local_R1'Address, R1'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "Local_R1 : 78 56 34 12\n" }
+
+ Local_R2.I := 16#12345678#;
+
+ Put ("Local_R2 :");
+ Dump (Local_R2'Address, R2'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "Local_R2 : 12 34 56 78\n" }
+
+ Local_R1.I := Local_R2.I;
+
+ Put ("Local_R1 :");
+ Dump (Local_R1'Address, R1'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "Local_R1 : 78 56 34 12\n" }
+
+ Local_R2.I := Local_R1.I;
+
+ Put ("Local_R2 :");
+ Dump (Local_R2'Address, R2'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "Local_R2 : 12 34 56 78\n" }
+end;
diff --git a/gcc/testsuite/gnat.dg/sso/p10.adb b/gcc/testsuite/gnat.dg/sso/p10.adb
new file mode 100644
index 00000000000..067a57ece31
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/sso/p10.adb
@@ -0,0 +1,63 @@
+-- { dg-do run }
+-- { dg-options "-gnatws" }
+
+with Init10; use Init10;
+with Text_IO; use Text_IO;
+with Dump;
+
+procedure P10 is
+
+ Local_R1 : R1;
+ Local_R2 : R2;
+
+begin
+ Put ("My_R1 :");
+ Dump (My_R1'Address, R1'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "My_R1 : 78 56 34 12\n" }
+
+ Put ("My_R2 :");
+ Dump (My_R2'Address, R2'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "My_R2 : 12 34 56 78\n" }
+
+ Local_R1 := My_R1;
+ Put ("Local_R1 :");
+ Dump (Local_R1'Address, R1'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "Local_R1 : 78 56 34 12\n" }
+
+ Local_R2 := My_R2;
+ Put ("Local_R2 :");
+ Dump (Local_R2'Address, R2'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "Local_R2 : 12 34 56 78\n" }
+
+ Local_R1.I := 16#12345678#;
+
+ Put ("Local_R1 :");
+ Dump (Local_R1'Address, R1'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "Local_R1 : 78 56 34 12\n" }
+
+ Local_R2.I := 16#12345678#;
+
+ Put ("Local_R2 :");
+ Dump (Local_R2'Address, R2'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "Local_R2 : 12 34 56 78\n" }
+
+ Local_R1.I := Local_R2.I;
+
+ Put ("Local_R1 :");
+ Dump (Local_R1'Address, R1'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "Local_R1 : 78 56 34 12\n" }
+
+ Local_R2.I := Local_R1.I;
+
+ Put ("Local_R2 :");
+ Dump (Local_R2'Address, R2'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "Local_R2 : 12 34 56 78\n" }
+end;
diff --git a/gcc/testsuite/gnat.dg/sso/p11.adb b/gcc/testsuite/gnat.dg/sso/p11.adb
new file mode 100644
index 00000000000..c6f6166473e
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/sso/p11.adb
@@ -0,0 +1,68 @@
+-- { dg-do run }
+
+with Init11; use Init11;
+with Text_IO; use Text_IO;
+with Dump;
+
+procedure P11 is
+
+ Local_R1 : R1;
+ Local_R2 : R2;
+
+begin
+ Put ("My_R1 :");
+ Dump (My_R1'Address, R1'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "My_R1 : 78 56 34 12 12 00 ab 00 34 00 cd 00 56 00 ef 00\n" }
+
+ Put ("My_R2 :");
+ Dump (My_R2'Address, R2'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "My_R2 : 12 34 56 78 00 ab 00 12 00 cd 00 34 00 ef 00 56\n" }
+
+ Local_R1 := My_R1;
+ Put ("Local_R1 :");
+ Dump (Local_R1'Address, R1'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "Local_R1 : 78 56 34 12 12 00 ab 00 34 00 cd 00 56 00 ef 00\n" }
+
+ Local_R2 := My_R2;
+ Put ("Local_R2 :");
+ Dump (Local_R2'Address, R2'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "Local_R2 : 12 34 56 78 00 ab 00 12 00 cd 00 34 00 ef 00 56\n" }
+
+ Local_R1 := (I => 16#12345678#,
+ A => (16#AB0012#, 16#CD0034#, 16#EF0056#));
+ Put ("Local_R1 :");
+ Dump (Local_R1'Address, R1'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "Local_R1 : 78 56 34 12 12 00 ab 00 34 00 cd 00 56 00 ef 00\n" }
+
+ Local_R2 := (I => 16#12345678#,
+ A => (16#AB0012#, 16#CD0034#, 16#EF0056#));
+ Put ("Local_R2 :");
+ Dump (Local_R2'Address, R2'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "Local_R2 : 12 34 56 78 00 ab 00 12 00 cd 00 34 00 ef 00 56\n" }
+
+ Local_R1.I := Local_R2.I;
+ Local_R1.A(1) := Local_R2.A(1);
+ Local_R1.A(2) := Local_R2.A(2);
+ Local_R1.A(3) := Local_R2.A(3);
+
+ Put ("Local_R1 :");
+ Dump (Local_R1'Address, R1'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "Local_R1 : 78 56 34 12 12 00 ab 00 34 00 cd 00 56 00 ef 00\n" }
+
+ Local_R2.I := Local_R1.I;
+ Local_R2.A(1) := Local_R1.A(1);
+ Local_R2.A(2) := Local_R1.A(2);
+ Local_R2.A(3) := Local_R1.A(3);
+
+ Put ("Local_R2 :");
+ Dump (Local_R2'Address, R2'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "Local_R2 : 12 34 56 78 00 ab 00 12 00 cd 00 34 00 ef 00 56\n" }
+end;
diff --git a/gcc/testsuite/gnat.dg/sso/p12.adb b/gcc/testsuite/gnat.dg/sso/p12.adb
new file mode 100644
index 00000000000..03e5e65e9f6
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/sso/p12.adb
@@ -0,0 +1,122 @@
+-- { dg-do run }
+
+with Init12; use Init12;
+with Text_IO; use Text_IO;
+with Dump;
+
+procedure P12 is
+
+ Local_A1 : Arr1;
+ Local_A11 : Arr11;
+ Local_A2 : Arr2;
+ Local_A22 : Arr22;
+
+begin
+ Put ("My_A1 :");
+ Dump (My_A1'Address, Arr1'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "My_A1 : 12 00 ab 00 34 00 cd 00 56 00 ef 00\n" }
+
+ Put ("My_A11 :");
+ Dump (My_A11'Address, Arr11'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "My_A11 : 12 00 ab 00 34 00 cd 00 12 00 ab 00 34 00 cd 00\n" }
+
+ Put ("My_A2 :");
+ Dump (My_A2'Address, Arr2'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "My_A2 : 00 ab 00 12 00 cd 00 34 00 ef 00 56\n" }
+
+ Put ("My_A22 :");
+ Dump (My_A22'Address, Arr22'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "My_A22 : 00 ab 00 12 00 cd 00 34 00 ab 00 12 00 cd 00 34\n" }
+
+ Local_A1 := My_A1;
+ Put ("Local_A1 :");
+ Dump (Local_A1'Address, Arr1'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "Local_A1 : 12 00 ab 00 34 00 cd 00 56 00 ef 00\n" }
+
+ Local_A11 := My_A11;
+ Put ("Local_A11 :");
+ Dump (Local_A11'Address, Arr11'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "Local_A11 : 12 00 ab 00 34 00 cd 00 12 00 ab 00 34 00 cd 00\n" }
+
+ Local_A2 := My_A2;
+ Put ("Local_A2 :");
+ Dump (Local_A2'Address, Arr2'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "Local_A2 : 00 ab 00 12 00 cd 00 34 00 ef 00 56\n" }
+
+ Local_A22 := My_A22;
+ Put ("Local_A22 :");
+ Dump (Local_A22'Address, Arr22'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "Local_A22 : 00 ab 00 12 00 cd 00 34 00 ab 00 12 00 cd 00 34\n" }
+
+ Local_A1 := (16#AB0012#, 16#CD0034#, 16#EF0056#);
+ Put ("Local_A1 :");
+ Dump (Local_A1'Address, Arr1'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "Local_A1 : 12 00 ab 00 34 00 cd 00 56 00 ef 00\n" }
+
+ Local_A11 := (1 => (16#AB0012#, 16#CD0034#),
+ 2 => (16#AB0012#, 16#CD0034#));
+ Put ("Local_A11 :");
+ Dump (Local_A11'Address, Arr11'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "Local_A11 : 12 00 ab 00 34 00 cd 00 12 00 ab 00 34 00 cd 00\n" }
+
+ Local_A2 := (16#AB0012#, 16#CD0034#, 16#EF0056#);
+ Put ("Local_A2 :");
+ Dump (Local_A2'Address, Arr2'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "Local_A2 : 00 ab 00 12 00 cd 00 34 00 ef 00 56\n" }
+
+ Local_A22 := (1 => (16#AB0012#, 16#CD0034#),
+ 2 => (16#AB0012#, 16#CD0034#));
+ Put ("Local_A22 :");
+ Dump (Local_A22'Address, Arr22'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "Local_A22 : 00 ab 00 12 00 cd 00 34 00 ab 00 12 00 cd 00 34\n" }
+
+ Local_A1(1) := Local_A2(1);
+ Local_A1(2) := Local_A2(2);
+ Local_A1(3) := Local_A2(3);
+
+ Put ("Local_A1 :");
+ Dump (Local_A1'Address, Arr1'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "Local_A1 : 12 00 ab 00 34 00 cd 00 56 00 ef 00\n" }
+
+ Local_A11(1,1) := Local_A22(1,1);
+ Local_A11(1,2) := Local_A22(1,2);
+ Local_A11(2,1) := Local_A22(2,1);
+ Local_A11(2,2) := Local_A22(2,2);
+
+ Put ("Local_A11 :");
+ Dump (Local_A11'Address, Arr11'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "Local_A11 : 12 00 ab 00 34 00 cd 00 12 00 ab 00 34 00 cd 00\n" }
+
+ Local_A2(1) := Local_A1(1);
+ Local_A2(2) := Local_A1(2);
+ Local_A2(3) := Local_A1(3);
+
+ Put ("Local_A2 :");
+ Dump (Local_A2'Address, Arr2'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "Local_A2 : 00 ab 00 12 00 cd 00 34 00 ef 00 56\n" }
+
+ Local_A22(1,1) := Local_A11(1,1);
+ Local_A22(1,2) := Local_A11(1,2);
+ Local_A22(2,1) := Local_A11(2,1);
+ Local_A22(2,2) := Local_A11(2,2);
+
+ Put ("Local_A22 :");
+ Dump (Local_A22'Address, Arr22'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "Local_A22 : 00 ab 00 12 00 cd 00 34 00 ab 00 12 00 cd 00 34\n" }
+end;
diff --git a/gcc/testsuite/gnat.dg/sso/p13.adb b/gcc/testsuite/gnat.dg/sso/p13.adb
new file mode 100644
index 00000000000..49db1114c68
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/sso/p13.adb
@@ -0,0 +1,63 @@
+-- { dg-do run }
+
+with Init13; use Init13;
+with Ada.Numerics; use Ada.Numerics;
+with Text_IO; use Text_IO;
+with Dump;
+
+procedure P13 is
+
+ Local_R1 : R1;
+ Local_R2 : R2;
+
+begin
+ Put ("My_R1 :");
+ Dump (My_R1'Address, R1'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "My_R1 : db 0f 49 40 db 0f 49 c0\n" }
+
+ Put ("My_R2 :");
+ Dump (My_R2'Address, R2'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "My_R2 : 40 49 0f db c0 49 0f db\n" }
+
+ Local_R1 := My_R1;
+ Put ("Local_R1 :");
+ Dump (Local_R1'Address, R1'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "Local_R1 : db 0f 49 40 db 0f 49 c0\n" }
+
+ Local_R2 := My_R2;
+ Put ("Local_R2 :");
+ Dump (Local_R2'Address, R2'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "Local_R2 : 40 49 0f db c0 49 0f db\n" }
+
+ Local_R1.F := (Pi, -Pi);
+
+ Put ("Local_R1 :");
+ Dump (Local_R1'Address, R1'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "Local_R1 : db 0f 49 40 db 0f 49 c0\n" }
+
+ Local_R2.F := (Pi, -Pi);
+
+ Put ("Local_R2 :");
+ Dump (Local_R2'Address, R2'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "Local_R2 : 40 49 0f db c0 49 0f db\n" }
+
+ Local_R1.F := Local_R2.F;
+
+ Put ("Local_R1 :");
+ Dump (Local_R1'Address, R1'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "Local_R1 : db 0f 49 40 db 0f 49 c0\n" }
+
+ Local_R2.F := Local_R1.F;
+
+ Put ("Local_R2 :");
+ Dump (Local_R2'Address, R2'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "Local_R2 : 40 49 0f db c0 49 0f db\n" }
+end;
diff --git a/gcc/testsuite/gnat.dg/sso/p2.adb b/gcc/testsuite/gnat.dg/sso/p2.adb
new file mode 100644
index 00000000000..5312e0aac34
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/sso/p2.adb
@@ -0,0 +1,80 @@
+-- { dg-do run }
+
+with Init2; use Init2;
+with Text_IO; use Text_IO;
+with Dump;
+
+procedure P2 is
+
+ Local_R1 : R1;
+ Local_R2 : R2;
+
+begin
+ Put ("My_R1 :");
+ Dump (My_R1'Address, R1'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "My_R1 : e2 59 d1 48 b4 aa d9 bb\n" }
+
+ Put ("My_R2 :");
+ Dump (My_R2'Address, R2'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "My_R2 : 84 8d 15 9e 15 5b 35 df\n" }
+
+ Local_R1 := My_R1;
+ Put ("Local_R1 :");
+ Dump (Local_R1'Address, R1'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "Local_R1 : e2 59 d1 48 b4 aa d9 bb\n" }
+
+ Local_R2 := My_R2;
+ Put ("Local_R2 :");
+ Dump (Local_R2'Address, R2'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "Local_R2 : 84 8d 15 9e 15 5b 35 df\n" }
+
+ Local_R1 := (S1 => 2,
+ I => 16#12345678#,
+ S2 => 1,
+ A => (16#AB#, 16#CD#, 16#EF#),
+ B => True);
+ Put ("Local_R1 :");
+ Dump (Local_R1'Address, R1'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "Local_R1 : e2 59 d1 48 b4 aa d9 bb\n" }
+
+ Local_R2 := (S1 => 2,
+ I => 16#12345678#,
+ S2 => 1,
+ A => (16#AB#, 16#CD#, 16#EF#),
+ B => True);
+ Put ("Local_R2 :");
+ Dump (Local_R2'Address, R2'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "Local_R2 : 84 8d 15 9e 15 5b 35 df\n" }
+
+ Local_R1.S1 := Local_R2.S1;
+ Local_R1.I := Local_R2.I;
+ Local_R1.S2 := Local_R2.S2;
+ Local_R1.A(1) := Local_R2.A(1);
+ Local_R1.A(2) := Local_R2.A(2);
+ Local_R1.A(3) := Local_R2.A(3);
+ Local_R1.B := Local_R2.B;
+
+ Put ("Local_R1 :");
+ Dump (Local_R1'Address, R1'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "Local_R1 : e2 59 d1 48 b4 aa d9 bb\n" }
+
+ Local_R2.S1 := Local_R1.S1;
+ Local_R2.I := Local_R1.I;
+ Local_R2.S2 := Local_R1.S2;
+ Local_R2.A(1) := Local_R1.A(1);
+ Local_R2.A(2) := Local_R1.A(2);
+ Local_R2.A(3) := Local_R1.A(3);
+ Local_R2.B := Local_R1.B;
+
+ Put ("Local_R2 :");
+ Dump (Local_R2'Address, R2'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "Local_R2 : 84 8d 15 9e 15 5b 35 df\n" }
+end;
diff --git a/gcc/testsuite/gnat.dg/sso/p3.adb b/gcc/testsuite/gnat.dg/sso/p3.adb
new file mode 100644
index 00000000000..c138f2416d9
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/sso/p3.adb
@@ -0,0 +1,80 @@
+-- { dg-do run }
+
+with Init3; use Init3;
+with Text_IO; use Text_IO;
+with Dump;
+
+procedure P3 is
+
+ Local_R1 : R1;
+ Local_R2 : R2;
+
+begin
+ Put ("My_R1 :");
+ Dump (My_R1'Address, R1'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "My_R1 : e2 59 d1 48 b4 aa d9 bb\n" }
+
+ Put ("My_R2 :");
+ Dump (My_R2'Address, R2'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "My_R2 : 84 8d 15 9e 15 5b 35 df\n" }
+
+ Local_R1 := My_R1;
+ Put ("Local_R1 :");
+ Dump (Local_R1'Address, R1'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "Local_R1 : e2 59 d1 48 b4 aa d9 bb\n" }
+
+ Local_R2 := My_R2;
+ Put ("Local_R2 :");
+ Dump (Local_R2'Address, R2'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "Local_R2 : 84 8d 15 9e 15 5b 35 df\n" }
+
+ Local_R1 := (S1 => 2,
+ I => 16#12345678#,
+ S2 => 1,
+ N => (16#AB#, 16#CD#, 16#EF#),
+ B => True);
+ Put ("Local_R1 :");
+ Dump (Local_R1'Address, R1'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "Local_R1 : e2 59 d1 48 b4 aa d9 bb\n" }
+
+ Local_R2 := (S1 => 2,
+ I => 16#12345678#,
+ S2 => 1,
+ N => (16#AB#, 16#CD#, 16#EF#),
+ B => True);
+ Put ("Local_R2 :");
+ Dump (Local_R2'Address, R2'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "Local_R2 : 84 8d 15 9e 15 5b 35 df\n" }
+
+ Local_R1.S1 := Local_R2.S1;
+ Local_R1.I := Local_R2.I;
+ Local_R1.S2 := Local_R2.S2;
+ Local_R1.N.C1 := Local_R2.N.C1;
+ Local_R1.N.C2 := Local_R2.N.C2;
+ Local_R1.N.C3 := Local_R2.N.C3;
+ Local_R1.B := Local_R2.B;
+
+ Put ("Local_R1 :");
+ Dump (Local_R1'Address, R1'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "Local_R1 : e2 59 d1 48 b4 aa d9 bb\n" }
+
+ Local_R2.S1 := Local_R1.S1;
+ Local_R2.I := Local_R1.I;
+ Local_R2.S2 := Local_R1.S2;
+ Local_R2.N.C1 := Local_R1.N.C1;
+ Local_R2.N.C2 := Local_R1.N.C2;
+ Local_R2.N.C3 := Local_R1.N.C3;
+ Local_R2.B := Local_R1.B;
+
+ Put ("Local_R2 :");
+ Dump (Local_R2'Address, R2'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "Local_R2 : 84 8d 15 9e 15 5b 35 df\n" }
+end;
diff --git a/gcc/testsuite/gnat.dg/sso/p4.adb b/gcc/testsuite/gnat.dg/sso/p4.adb
new file mode 100644
index 00000000000..a22c0449e08
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/sso/p4.adb
@@ -0,0 +1,63 @@
+-- { dg-do run }
+
+with Init4; use Init4;
+with Ada.Numerics; use Ada.Numerics;
+with Text_IO; use Text_IO;
+with Dump;
+
+procedure P4 is
+
+ Local_R1 : R1;
+ Local_R2 : R2;
+
+begin
+ Put ("My_R1 :");
+ Dump (My_R1'Address, R1'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "My_R1 : db 0f 49 40\n" }
+
+ Put ("My_R2 :");
+ Dump (My_R2'Address, R2'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "My_R2 : 40 49 0f db\n" }
+
+ Local_R1 := My_R1;
+ Put ("Local_R1 :");
+ Dump (Local_R1'Address, R1'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "Local_R1 : db 0f 49 40\n" }
+
+ Local_R2 := My_R2;
+ Put ("Local_R2 :");
+ Dump (Local_R2'Address, R2'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "Local_R2 : 40 49 0f db\n" }
+
+ Local_R1.F := Pi;
+
+ Put ("Local_R1 :");
+ Dump (Local_R1'Address, R1'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "Local_R1 : db 0f 49 40\n" }
+
+ Local_R2.F := Pi;
+
+ Put ("Local_R2 :");
+ Dump (Local_R2'Address, R2'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "Local_R2 : 40 49 0f db\n" }
+
+ Local_R1.F := Local_R2.F;
+
+ Put ("Local_R1 :");
+ Dump (Local_R1'Address, R1'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "Local_R1 : db 0f 49 40\n" }
+
+ Local_R2.F := Local_R1.F;
+
+ Put ("Local_R2 :");
+ Dump (Local_R2'Address, R2'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "Local_R2 : 40 49 0f db\n" }
+end;
diff --git a/gcc/testsuite/gnat.dg/sso/p5.adb b/gcc/testsuite/gnat.dg/sso/p5.adb
new file mode 100644
index 00000000000..6a692ae5364
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/sso/p5.adb
@@ -0,0 +1,68 @@
+-- { dg-do run }
+
+with Init5; use Init5;
+with Text_IO; use Text_IO;
+with Dump;
+
+procedure P5 is
+
+ Local_R1 : R1;
+ Local_R2 : R2;
+
+begin
+ Put ("My_R1 :");
+ Dump (My_R1'Address, R1'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "My_R1 : 78 56 34 12 12 00 ab 00 34 00 cd 00 56 00 ef 00\n" }
+
+ Put ("My_R2 :");
+ Dump (My_R2'Address, R2'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "My_R2 : 12 34 56 78 00 ab 00 12 00 cd 00 34 00 ef 00 56\n" }
+
+ Local_R1 := My_R1;
+ Put ("Local_R1 :");
+ Dump (Local_R1'Address, R1'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "Local_R1 : 78 56 34 12 12 00 ab 00 34 00 cd 00 56 00 ef 00\n" }
+
+ Local_R2 := My_R2;
+ Put ("Local_R2 :");
+ Dump (Local_R2'Address, R2'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "Local_R2 : 12 34 56 78 00 ab 00 12 00 cd 00 34 00 ef 00 56\n" }
+
+ Local_R1 := (I => 16#12345678#,
+ A => (16#AB0012#, 16#CD0034#, 16#EF0056#));
+ Put ("Local_R1 :");
+ Dump (Local_R1'Address, R1'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "Local_R1 : 78 56 34 12 12 00 ab 00 34 00 cd 00 56 00 ef 00\n" }
+
+ Local_R2 := (I => 16#12345678#,
+ A => (16#AB0012#, 16#CD0034#, 16#EF0056#));
+ Put ("Local_R2 :");
+ Dump (Local_R2'Address, R2'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "Local_R2 : 12 34 56 78 00 ab 00 12 00 cd 00 34 00 ef 00 56\n" }
+
+ Local_R1.I := Local_R2.I;
+ Local_R1.A(1) := Local_R2.A(1);
+ Local_R1.A(2) := Local_R2.A(2);
+ Local_R1.A(3) := Local_R2.A(3);
+
+ Put ("Local_R1 :");
+ Dump (Local_R1'Address, R1'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "Local_R1 : 78 56 34 12 12 00 ab 00 34 00 cd 00 56 00 ef 00\n" }
+
+ Local_R2.I := Local_R1.I;
+ Local_R2.A(1) := Local_R1.A(1);
+ Local_R2.A(2) := Local_R1.A(2);
+ Local_R2.A(3) := Local_R1.A(3);
+
+ Put ("Local_R2 :");
+ Dump (Local_R2'Address, R2'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "Local_R2 : 12 34 56 78 00 ab 00 12 00 cd 00 34 00 ef 00 56\n" }
+end;
diff --git a/gcc/testsuite/gnat.dg/sso/p6.adb b/gcc/testsuite/gnat.dg/sso/p6.adb
new file mode 100644
index 00000000000..35c1b1a201e
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/sso/p6.adb
@@ -0,0 +1,61 @@
+-- { dg-do run }
+
+with Init6; use Init6;
+with Text_IO; use Text_IO;
+with Dump;
+
+procedure P6 is
+
+ Local_R1 : R1;
+ Local_R2 : R2;
+
+begin
+ Put ("My_R1 :");
+ Dump (My_R1'Address, R1'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "My_R1 : 78 56 34 12 00 ab 00 12 00 cd 00 34 00 ef 00 56\n" }
+ Put ("My_R2 :");
+ Dump (My_R2'Address, R2'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "My_R2 : 12 34 56 78 12 00 ab 00 34 00 cd 00 56 00 ef 00\n" }
+ Local_R1 := My_R1;
+ Put ("Local_R1 :");
+ Dump (Local_R1'Address, R1'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "Local_R1 : 78 56 34 12 00 ab 00 12 00 cd 00 34 00 ef 00 56\n" }
+ Local_R2 := My_R2;
+ Put ("Local_R2 :");
+ Dump (Local_R2'Address, R2'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "Local_R2 : 12 34 56 78 12 00 ab 00 34 00 cd 00 56 00 ef 00\n" }
+ Local_R1 := (I => 16#12345678#,
+ A => (16#AB0012#, 16#CD0034#, 16#EF0056#));
+ Put ("Local_R1 :");
+ Dump (Local_R1'Address, R1'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "Local_R1 : 78 56 34 12 00 ab 00 12 00 cd 00 34 00 ef 00 56\n" }
+ Local_R2 := (I => 16#12345678#,
+ A => (16#AB0012#, 16#CD0034#, 16#EF0056#));
+ Put ("Local_R2 :");
+ Dump (Local_R2'Address, R2'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "Local_R2 : 12 34 56 78 12 00 ab 00 34 00 cd 00 56 00 ef 00\n" }
+ Local_R1.I := Local_R2.I;
+ Local_R1.A(1) := Local_R2.A(1);
+ Local_R1.A(2) := Local_R2.A(2);
+ Local_R1.A(3) := Local_R2.A(3);
+
+ Put ("Local_R1 :");
+ Dump (Local_R1'Address, R1'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "Local_R1 : 78 56 34 12 00 ab 00 12 00 cd 00 34 00 ef 00 56\n" }
+ Local_R2.I := Local_R1.I;
+ Local_R2.A(1) := Local_R1.A(1);
+ Local_R2.A(2) := Local_R1.A(2);
+ Local_R2.A(3) := Local_R1.A(3);
+
+ Put ("Local_R2 :");
+ Dump (Local_R2'Address, R2'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "Local_R2 : 12 34 56 78 12 00 ab 00 34 00 cd 00 56 00 ef 00\n" }
+end;
diff --git a/gcc/testsuite/gnat.dg/sso/p7.adb b/gcc/testsuite/gnat.dg/sso/p7.adb
new file mode 100644
index 00000000000..01354befbab
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/sso/p7.adb
@@ -0,0 +1,61 @@
+-- { dg-do run }
+
+with Init7; use Init7;
+with Text_IO; use Text_IO;
+with Dump;
+
+procedure P7 is
+
+ Local_R1 : R1;
+ Local_R2 : R2;
+
+begin
+ Put ("My_R1 :");
+ Dump (My_R1'Address, R1'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "My_R1 : 78 56 34 12 12 00 ab 00 34 00 cd 00 56 00 ef 00\n" }
+ Put ("My_R2 :");
+ Dump (My_R2'Address, R2'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "My_R2 : 12 34 56 78 00 ab 00 12 00 cd 00 34 00 ef 00 56\n" }
+ Local_R1 := My_R1;
+ Put ("Local_R1 :");
+ Dump (Local_R1'Address, R1'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "Local_R1 : 78 56 34 12 12 00 ab 00 34 00 cd 00 56 00 ef 00\n" }
+ Local_R2 := My_R2;
+ Put ("Local_R2 :");
+ Dump (Local_R2'Address, R2'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "Local_R2 : 12 34 56 78 00 ab 00 12 00 cd 00 34 00 ef 00 56\n" }
+ Local_R1 := (I => 16#12345678#,
+ N => (16#AB0012#, 16#CD0034#, 16#EF0056#));
+ Put ("Local_R1 :");
+ Dump (Local_R1'Address, R1'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "Local_R1 : 78 56 34 12 12 00 ab 00 34 00 cd 00 56 00 ef 00\n" }
+ Local_R2 := (I => 16#12345678#,
+ N => (16#AB0012#, 16#CD0034#, 16#EF0056#));
+ Put ("Local_R2 :");
+ Dump (Local_R2'Address, R2'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "Local_R2 : 12 34 56 78 00 ab 00 12 00 cd 00 34 00 ef 00 56\n" }
+ Local_R1.I := Local_R2.I;
+ Local_R1.N.C1 := Local_R2.N.C1;
+ Local_R1.N.C2 := Local_R2.N.C2;
+ Local_R1.N.C3 := Local_R2.N.C3;
+
+ Put ("Local_R1 :");
+ Dump (Local_R1'Address, R1'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "Local_R1 : 78 56 34 12 12 00 ab 00 34 00 cd 00 56 00 ef 00\n" }
+ Local_R2.I := Local_R1.I;
+ Local_R2.N.C1 := Local_R1.N.C1;
+ Local_R2.N.C2 := Local_R1.N.C2;
+ Local_R2.N.C3 := Local_R1.N.C3;
+
+ Put ("Local_R2 :");
+ Dump (Local_R2'Address, R2'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "Local_R2 : 12 34 56 78 00 ab 00 12 00 cd 00 34 00 ef 00 56\n" }
+end;
diff --git a/gcc/testsuite/gnat.dg/sso/p8.adb b/gcc/testsuite/gnat.dg/sso/p8.adb
new file mode 100644
index 00000000000..e6f80e4029c
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/sso/p8.adb
@@ -0,0 +1,61 @@
+-- { dg-do run }
+
+with Init8; use Init8;
+with Text_IO; use Text_IO;
+with Dump;
+
+procedure P8 is
+
+ Local_R1 : R1;
+ Local_R2 : R2;
+
+begin
+ Put ("My_R1 :");
+ Dump (My_R1'Address, R1'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "My_R1 : 78 56 34 12 00 ab 00 12 00 cd 00 34 00 ef 00 56\n" }
+ Put ("My_R2 :");
+ Dump (My_R2'Address, R2'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "My_R2 : 12 34 56 78 12 00 ab 00 34 00 cd 00 56 00 ef 00\n" }
+ Local_R1 := My_R1;
+ Put ("Local_R1 :");
+ Dump (Local_R1'Address, R1'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "Local_R1 : 78 56 34 12 00 ab 00 12 00 cd 00 34 00 ef 00 56\n" }
+ Local_R2 := My_R2;
+ Put ("Local_R2 :");
+ Dump (Local_R2'Address, R2'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "Local_R2 : 12 34 56 78 12 00 ab 00 34 00 cd 00 56 00 ef 00\n" }
+ Local_R1 := (I => 16#12345678#,
+ N => (16#AB0012#, 16#CD0034#, 16#EF0056#));
+ Put ("Local_R1 :");
+ Dump (Local_R1'Address, R1'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "Local_R1 : 78 56 34 12 00 ab 00 12 00 cd 00 34 00 ef 00 56\n" }
+ Local_R2 := (I => 16#12345678#,
+ N => (16#AB0012#, 16#CD0034#, 16#EF0056#));
+ Put ("Local_R2 :");
+ Dump (Local_R2'Address, R2'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "Local_R2 : 12 34 56 78 12 00 ab 00 34 00 cd 00 56 00 ef 00\n" }
+ Local_R1.I := Local_R2.I;
+ Local_R1.N.C1 := Local_R2.N.C1;
+ Local_R1.N.C2 := Local_R2.N.C2;
+ Local_R1.N.C3 := Local_R2.N.C3;
+
+ Put ("Local_R1 :");
+ Dump (Local_R1'Address, R1'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "Local_R1 : 78 56 34 12 00 ab 00 12 00 cd 00 34 00 ef 00 56\n" }
+ Local_R2.I := Local_R1.I;
+ Local_R2.N.C1 := Local_R1.N.C1;
+ Local_R2.N.C2 := Local_R1.N.C2;
+ Local_R2.N.C3 := Local_R1.N.C3;
+
+ Put ("Local_R2 :");
+ Dump (Local_R2'Address, R2'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "Local_R2 : 12 34 56 78 12 00 ab 00 34 00 cd 00 56 00 ef 00\n" }
+end;
diff --git a/gcc/testsuite/gnat.dg/sso/p9.adb b/gcc/testsuite/gnat.dg/sso/p9.adb
new file mode 100644
index 00000000000..1aab12b604b
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/sso/p9.adb
@@ -0,0 +1,63 @@
+-- { dg-do run }
+
+with Init9; use Init9;
+with Ada.Numerics; use Ada.Numerics;
+with Text_IO; use Text_IO;
+with Dump;
+
+procedure P9 is
+
+ Local_R1 : R1;
+ Local_R2 : R2;
+
+begin
+ Put ("My_R1 :");
+ Dump (My_R1'Address, R1'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "My_R1 : 18 2d 44 54 fb 21 09 40\n" }
+
+ Put ("My_R2 :");
+ Dump (My_R2'Address, R2'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "My_R2 : 40 09 21 fb 54 44 2d 18\n" }
+
+ Local_R1 := My_R1;
+ Put ("Local_R1 :");
+ Dump (Local_R1'Address, R1'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "Local_R1 : 18 2d 44 54 fb 21 09 40\n" }
+
+ Local_R2 := My_R2;
+ Put ("Local_R2 :");
+ Dump (Local_R2'Address, R2'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "Local_R2 : 40 09 21 fb 54 44 2d 18\n" }
+
+ Local_R1.F := Pi;
+
+ Put ("Local_R1 :");
+ Dump (Local_R1'Address, R1'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "Local_R1 : 18 2d 44 54 fb 21 09 40\n" }
+
+ Local_R2.F := Pi;
+
+ Put ("Local_R2 :");
+ Dump (Local_R2'Address, R2'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "Local_R2 : 40 09 21 fb 54 44 2d 18\n" }
+
+ Local_R1.F := Local_R2.F;
+
+ Put ("Local_R1 :");
+ Dump (Local_R1'Address, R1'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "Local_R1 : 18 2d 44 54 fb 21 09 40\n" }
+
+ Local_R2.F := Local_R1.F;
+
+ Put ("Local_R2 :");
+ Dump (Local_R2'Address, R2'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "Local_R2 : 40 09 21 fb 54 44 2d 18\n" }
+end;
diff --git a/gcc/testsuite/gnat.dg/sso/q1.adb b/gcc/testsuite/gnat.dg/sso/q1.adb
new file mode 100644
index 00000000000..6c8303cf981
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/sso/q1.adb
@@ -0,0 +1,52 @@
+-- { dg-do run }
+
+with Init1; use Init1;
+with Text_IO; use Text_IO;
+with Dump;
+
+procedure Q1 is
+
+ A1 : R1 := My_R1;
+ B1 : R1 := My_R1;
+
+ A2 : R2 := My_R2;
+ B2 : R2 := My_R2;
+
+begin
+ Put ("A1 :");
+ Dump (A1'Address, R1'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "A1 : 78 56 34 12\n" }
+
+ Put ("B1 :");
+ Dump (B1'Address, R1'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "B1 : 78 56 34 12\n" }
+
+ Put ("A2 :");
+ Dump (A2'Address, R2'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "A2 : 12 34 56 78\n" }
+
+ Put ("B2 :");
+ Dump (B2'Address, R2'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "B2 : 12 34 56 78\n" }
+
+ if A1.I /= B1.I then
+ raise Program_Error;
+ end if;
+
+ if A1.I /= 16#12345678# then
+ raise Program_Error;
+ end if;
+
+ if A2.I /= B2.I then
+ raise Program_Error;
+ end if;
+
+ if A2.I /= 16#12345678# then
+ raise Program_Error;
+ end if;
+
+end;
diff --git a/gcc/testsuite/gnat.dg/sso/q10.adb b/gcc/testsuite/gnat.dg/sso/q10.adb
new file mode 100644
index 00000000000..94d21522d0d
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/sso/q10.adb
@@ -0,0 +1,53 @@
+-- { dg-do run }
+-- { dg-options "-gnatws" }
+
+with Init10; use Init10;
+with Text_IO; use Text_IO;
+with Dump;
+
+procedure Q10 is
+
+ A1 : R1 := My_R1;
+ B1 : R1 := My_R1;
+
+ A2 : R2 := My_R2;
+ B2 : R2 := My_R2;
+
+begin
+ Put ("A1 :");
+ Dump (A1'Address, R1'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "A1 : 78 56 34 12\n" }
+
+ Put ("B1 :");
+ Dump (B1'Address, R1'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "B1 : 78 56 34 12\n" }
+
+ Put ("A2 :");
+ Dump (A2'Address, R2'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "A2 : 12 34 56 78\n" }
+
+ Put ("B2 :");
+ Dump (B2'Address, R2'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "B2 : 12 34 56 78\n" }
+
+ if A1.I /= B1.I then
+ raise Program_Error;
+ end if;
+
+ if A1.I /= 16#12345678# then
+ raise Program_Error;
+ end if;
+
+ if A2.I /= B2.I then
+ raise Program_Error;
+ end if;
+
+ if A2.I /= 16#12345678# then
+ raise Program_Error;
+ end if;
+
+end;
diff --git a/gcc/testsuite/gnat.dg/sso/q11.adb b/gcc/testsuite/gnat.dg/sso/q11.adb
new file mode 100644
index 00000000000..84951de3019
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/sso/q11.adb
@@ -0,0 +1,44 @@
+-- { dg-do run }
+
+with Init11; use Init11;
+with Text_IO; use Text_IO;
+with Dump;
+
+procedure Q11 is
+
+ A1 : R1 := My_R1;
+ B1 : R1 := My_R1;
+
+ A2 : R2 := My_R2;
+ B2 : R2 := My_R2;
+
+begin
+ Put ("A1 :");
+ Dump (A1'Address, R1'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "A1 : 78 56 34 12 12 00 ab 00 34 00 cd 00 56 00 ef 00\n" }
+
+ Put ("B1 :");
+ Dump (B1'Address, R1'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "B1 : 78 56 34 12 12 00 ab 00 34 00 cd 00 56 00 ef 00\n" }
+
+ Put ("A2 :");
+ Dump (A2'Address, R2'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "A2 : 12 34 56 78 00 ab 00 12 00 cd 00 34 00 ef 00 56\n" }
+
+ Put ("B2 :");
+ Dump (B2'Address, R2'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "B2 : 12 34 56 78 00 ab 00 12 00 cd 00 34 00 ef 00 56\n"}
+
+ if A1.I /= B1.I or A1.A(1) /= B1.A(1) then
+ raise Program_Error;
+ end if;
+
+ if A2.I /= B2.I or A2.A(1) /= B2.A(1) then
+ raise Program_Error;
+ end if;
+
+end;
diff --git a/gcc/testsuite/gnat.dg/sso/q12.adb b/gcc/testsuite/gnat.dg/sso/q12.adb
new file mode 100644
index 00000000000..2018582607f
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/sso/q12.adb
@@ -0,0 +1,43 @@
+-- { dg-do run }
+
+with Init12; use Init12;
+with Text_IO; use Text_IO;
+with Dump;
+
+procedure Q12 is
+
+ A1 : Arr1 := My_A1;
+ A11 : Arr11 := My_A11;
+
+ A2 : Arr2 := My_A2;
+ A22 : Arr22 := My_A22;
+
+begin
+ Put ("A1 :");
+ Dump (A1'Address, Arr1'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "A1 : 12 00 ab 00 34 00 cd 00 56 00 ef 00\n" }
+
+ Put ("A11 :");
+ Dump (A11'Address, Arr11'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "A11 : 12 00 ab 00 34 00 cd 00 12 00 ab 00 34 00 cd 00\n" }
+
+ Put ("A2 :");
+ Dump (A2'Address, Arr2'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "A2 : 00 ab 00 12 00 cd 00 34 00 ef 00 56\n" }
+
+ Put ("A22 :");
+ Dump (A22'Address, Arr22'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "A22 : 00 ab 00 12 00 cd 00 34 00 ab 00 12 00 cd 00 34\n" }
+
+ if A1(1) /= A11(1,1) then
+ raise Program_Error;
+ end if;
+
+ if A2(1) /= A22(1,1) then
+ raise Program_Error;
+ end if;
+end;
diff --git a/gcc/testsuite/gnat.dg/sso/q13.adb b/gcc/testsuite/gnat.dg/sso/q13.adb
new file mode 100644
index 00000000000..e07530fb2aa
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/sso/q13.adb
@@ -0,0 +1,53 @@
+-- { dg-do run }
+
+with Init13; use Init13;
+with Ada.Numerics; use Ada.Numerics;
+with Text_IO; use Text_IO;
+with Dump;
+
+procedure Q13 is
+
+ A1 : R1 := My_R1;
+ B1 : R1 := My_R1;
+
+ A2 : R2 := My_R2;
+ B2 : R2 := My_R2;
+
+begin
+ Put ("A1 :");
+ Dump (A1'Address, R1'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "A1 : db 0f 49 40 db 0f 49 c0\n" }
+
+ Put ("B1 :");
+ Dump (B1'Address, R1'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "B1 : db 0f 49 40 db 0f 49 c0\n" }
+
+ Put ("A2 :");
+ Dump (A2'Address, R2'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "A2 : 40 49 0f db c0 49 0f db\n" }
+
+ Put ("B2 :");
+ Dump (B2'Address, R2'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "B2 : 40 49 0f db c0 49 0f db\n" }
+
+ if A1.F /= B1.F then
+ raise Program_Error;
+ end if;
+
+ if A1.F /= (Pi, -Pi) then
+ raise Program_Error;
+ end if;
+
+ if A2.F /= B2.F then
+ raise Program_Error;
+ end if;
+
+ if A2.F /= (Pi, -Pi) then
+ raise Program_Error;
+ end if;
+
+end;
diff --git a/gcc/testsuite/gnat.dg/sso/q2.adb b/gcc/testsuite/gnat.dg/sso/q2.adb
new file mode 100644
index 00000000000..be11fe15294
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/sso/q2.adb
@@ -0,0 +1,60 @@
+-- { dg-do run }
+
+with Init2; use Init2;
+with Text_IO; use Text_IO;
+with Dump;
+
+procedure Q2 is
+
+ A1 : R1 := My_R1;
+ B1 : R1 := My_R1;
+
+ A2 : R2 := My_R2;
+ B2 : R2 := My_R2;
+
+begin
+ Put ("A1 :");
+ Dump (A1'Address, R1'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "A1 : e2 59 d1 48 b4 aa d9 bb\n" }
+
+ Put ("B1 :");
+ Dump (B1'Address, R1'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "B1 : e2 59 d1 48 b4 aa d9 bb\n" }
+
+ Put ("A2 :");
+ Dump (A2'Address, R2'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "A2 : 84 8d 15 9e 15 5b 35 df\n" }
+
+ Put ("B2 :");
+ Dump (B2'Address, R2'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "B2 : 84 8d 15 9e 15 5b 35 df\n" }
+
+ if A1.S1 /= B1.S1 then
+ raise Program_Error;
+ end if;
+
+ if A1.S1 /= 2 then
+ raise Program_Error;
+ end if;
+
+ if A2.S1 /= B2.S1 then
+ raise Program_Error;
+ end if;
+
+ if A2.S1 /= 2 then
+ raise Program_Error;
+ end if;
+
+ if A1.I /= B1.I or A1.A(1) /= B1.A(1) then
+ raise Program_Error;
+ end if;
+
+ if A2.I /= B2.I or A2.A(1) /= B2.A(1) then
+ raise Program_Error;
+ end if;
+
+end;
diff --git a/gcc/testsuite/gnat.dg/sso/q3.adb b/gcc/testsuite/gnat.dg/sso/q3.adb
new file mode 100644
index 00000000000..383a88b6125
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/sso/q3.adb
@@ -0,0 +1,60 @@
+-- { dg-do run }
+
+with Init3; use Init3;
+with Text_IO; use Text_IO;
+with Dump;
+
+procedure Q3 is
+
+ A1 : R1 := My_R1;
+ B1 : R1 := My_R1;
+
+ A2 : R2 := My_R2;
+ B2 : R2 := My_R2;
+
+begin
+ Put ("A1 :");
+ Dump (A1'Address, R1'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "A1 : e2 59 d1 48 b4 aa d9 bb\n" }
+
+ Put ("B1 :");
+ Dump (B1'Address, R1'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "B1 : e2 59 d1 48 b4 aa d9 bb\n" }
+
+ Put ("A2 :");
+ Dump (A2'Address, R2'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "A2 : 84 8d 15 9e 15 5b 35 df\n" }
+
+ Put ("B2 :");
+ Dump (B2'Address, R2'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "B2 : 84 8d 15 9e 15 5b 35 df\n" }
+
+ if A1.S1 /= B1.S1 then
+ raise Program_Error;
+ end if;
+
+ if A1.S1 /= 2 then
+ raise Program_Error;
+ end if;
+
+ if A2.S1 /= B2.S1 then
+ raise Program_Error;
+ end if;
+
+ if A2.S1 /= 2 then
+ raise Program_Error;
+ end if;
+
+ if A1.I /= B1.I or A1.N.C1 /= B1.N.C1 then
+ raise Program_Error;
+ end if;
+
+ if A2.I /= B2.I or A2.N.C1 /= B2.N.C1 then
+ raise Program_Error;
+ end if;
+
+end;
diff --git a/gcc/testsuite/gnat.dg/sso/q4.adb b/gcc/testsuite/gnat.dg/sso/q4.adb
new file mode 100644
index 00000000000..0cef27de219
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/sso/q4.adb
@@ -0,0 +1,53 @@
+-- { dg-do run }
+
+with Init4; use Init4;
+with Ada.Numerics; use Ada.Numerics;
+with Text_IO; use Text_IO;
+with Dump;
+
+procedure Q4 is
+
+ A1 : R1 := My_R1;
+ B1 : R1 := My_R1;
+
+ A2 : R2 := My_R2;
+ B2 : R2 := My_R2;
+
+begin
+ Put ("A1 :");
+ Dump (A1'Address, R1'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "A1 : db 0f 49 40\n" }
+
+ Put ("B1 :");
+ Dump (B1'Address, R1'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "B1 : db 0f 49 40\n" }
+
+ Put ("A2 :");
+ Dump (A2'Address, R2'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "A2 : 40 49 0f db\n" }
+
+ Put ("B2 :");
+ Dump (B2'Address, R2'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "B2 : 40 49 0f db\n" }
+
+ if A1.F /= B1.F then
+ raise Program_Error;
+ end if;
+
+ if A1.F /= Pi then
+ raise Program_Error;
+ end if;
+
+ if A2.F /= B2.F then
+ raise Program_Error;
+ end if;
+
+ if A2.F /= Pi then
+ raise Program_Error;
+ end if;
+
+end;
diff --git a/gcc/testsuite/gnat.dg/sso/q5.adb b/gcc/testsuite/gnat.dg/sso/q5.adb
new file mode 100644
index 00000000000..965d145f680
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/sso/q5.adb
@@ -0,0 +1,44 @@
+-- { dg-do run }
+
+with Init5; use Init5;
+with Text_IO; use Text_IO;
+with Dump;
+
+procedure Q5 is
+
+ A1 : R1 := My_R1;
+ B1 : R1 := My_R1;
+
+ A2 : R2 := My_R2;
+ B2 : R2 := My_R2;
+
+begin
+ Put ("A1 :");
+ Dump (A1'Address, R1'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "A1 : 78 56 34 12 12 00 ab 00 34 00 cd 00 56 00 ef 00\n" }
+
+ Put ("B1 :");
+ Dump (B1'Address, R1'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "B1 : 78 56 34 12 12 00 ab 00 34 00 cd 00 56 00 ef 00\n" }
+
+ Put ("A2 :");
+ Dump (A2'Address, R2'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "A2 : 12 34 56 78 00 ab 00 12 00 cd 00 34 00 ef 00 56\n" }
+
+ Put ("B2 :");
+ Dump (B2'Address, R2'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "B2 : 12 34 56 78 00 ab 00 12 00 cd 00 34 00 ef 00 56\n"}
+
+ if A1.I /= B1.I or A1.A(1) /= B1.A(1) then
+ raise Program_Error;
+ end if;
+
+ if A2.I /= B2.I or A2.A(1) /= B2.A(1) then
+ raise Program_Error;
+ end if;
+
+end;
diff --git a/gcc/testsuite/gnat.dg/sso/q6.adb b/gcc/testsuite/gnat.dg/sso/q6.adb
new file mode 100644
index 00000000000..f90b32f623d
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/sso/q6.adb
@@ -0,0 +1,44 @@
+-- { dg-do run }
+
+with Init6; use Init6;
+with Text_IO; use Text_IO;
+with Dump;
+
+procedure Q6 is
+
+ A1 : R1 := My_R1;
+ B1 : R1 := My_R1;
+
+ A2 : R2 := My_R2;
+ B2 : R2 := My_R2;
+
+begin
+ Put ("A1 :");
+ Dump (A1'Address, R1'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "A1 : 78 56 34 12 00 ab 00 12 00 cd 00 34 00 ef 00 56\n" }
+
+ Put ("B1 :");
+ Dump (B1'Address, R1'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "B1 : 78 56 34 12 00 ab 00 12 00 cd 00 34 00 ef 00 56\n" }
+
+ Put ("A2 :");
+ Dump (A2'Address, R2'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "A2 : 12 34 56 78 12 00 ab 00 34 00 cd 00 56 00 ef 00\n" }
+
+ Put ("B2 :");
+ Dump (B2'Address, R2'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "B2 : 12 34 56 78 12 00 ab 00 34 00 cd 00 56 00 ef 00\n" }
+
+ if A1.I /= B1.I or A1.A(1) /= B1.A(1) then
+ raise Program_Error;
+ end if;
+
+ if A2.I /= B2.I or A2.A(1) /= B2.A(1) then
+ raise Program_Error;
+ end if;
+
+end;
diff --git a/gcc/testsuite/gnat.dg/sso/q7.adb b/gcc/testsuite/gnat.dg/sso/q7.adb
new file mode 100644
index 00000000000..72ab6106ad5
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/sso/q7.adb
@@ -0,0 +1,44 @@
+-- { dg-do run }
+
+with Init7; use Init7;
+with Text_IO; use Text_IO;
+with Dump;
+
+procedure Q7 is
+
+ A1 : R1 := My_R1;
+ B1 : R1 := My_R1;
+
+ A2 : R2 := My_R2;
+ B2 : R2 := My_R2;
+
+begin
+ Put ("A1 :");
+ Dump (A1'Address, R1'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "A1 : 78 56 34 12 12 00 ab 00 34 00 cd 00 56 00 ef 00\n" }
+
+ Put ("B1 :");
+ Dump (B1'Address, R1'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "B1 : 78 56 34 12 12 00 ab 00 34 00 cd 00 56 00 ef 00\n" }
+
+ Put ("A2 :");
+ Dump (A2'Address, R2'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "A2 : 12 34 56 78 00 ab 00 12 00 cd 00 34 00 ef 00 56\n" }
+
+ Put ("B2 :");
+ Dump (B2'Address, R2'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "B2 : 12 34 56 78 00 ab 00 12 00 cd 00 34 00 ef 00 56\n" }
+
+ if A1.I /= B1.I or A1.N.C1 /= B1.N.C1 then
+ raise Program_Error;
+ end if;
+
+ if A2.I /= B2.I or A2.N.C1 /= B2.N.C1 then
+ raise Program_Error;
+ end if;
+
+end;
diff --git a/gcc/testsuite/gnat.dg/sso/q8.adb b/gcc/testsuite/gnat.dg/sso/q8.adb
new file mode 100644
index 00000000000..7931179d6f1
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/sso/q8.adb
@@ -0,0 +1,44 @@
+-- { dg-do run }
+
+with Init8; use Init8;
+with Text_IO; use Text_IO;
+with Dump;
+
+procedure Q8 is
+
+ A1 : R1 := My_R1;
+ B1 : R1 := My_R1;
+
+ A2 : R2 := My_R2;
+ B2 : R2 := My_R2;
+
+begin
+ Put ("A1 :");
+ Dump (A1'Address, R1'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "A1 : 78 56 34 12 00 ab 00 12 00 cd 00 34 00 ef 00 56\n" }
+
+ Put ("B1 :");
+ Dump (B1'Address, R1'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "B1 : 78 56 34 12 00 ab 00 12 00 cd 00 34 00 ef 00 56\n" }
+
+ Put ("A2 :");
+ Dump (A2'Address, R2'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "A2 : 12 34 56 78 12 00 ab 00 34 00 cd 00 56 00 ef 00\n" }
+
+ Put ("B2 :");
+ Dump (B2'Address, R2'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "B2 : 12 34 56 78 12 00 ab 00 34 00 cd 00 56 00 ef 00\n" }
+
+ if A1.I /= B1.I or A1.N.C1 /= B1.N.C1 then
+ raise Program_Error;
+ end if;
+
+ if A2.I /= B2.I or A2.N.C1 /= B2.N.C1 then
+ raise Program_Error;
+ end if;
+
+end;
diff --git a/gcc/testsuite/gnat.dg/sso/q9.adb b/gcc/testsuite/gnat.dg/sso/q9.adb
new file mode 100644
index 00000000000..f5d4a559a42
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/sso/q9.adb
@@ -0,0 +1,53 @@
+-- { dg-do run }
+
+with Init9; use Init9;
+with Ada.Numerics; use Ada.Numerics;
+with Text_IO; use Text_IO;
+with Dump;
+
+procedure Q9 is
+
+ A1 : R1 := My_R1;
+ B1 : R1 := My_R1;
+
+ A2 : R2 := My_R2;
+ B2 : R2 := My_R2;
+
+begin
+ Put ("A1 :");
+ Dump (A1'Address, R1'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "A1 : 18 2d 44 54 fb 21 09 40\n" }
+
+ Put ("B1 :");
+ Dump (B1'Address, R1'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "B1 : 18 2d 44 54 fb 21 09 40\n" }
+
+ Put ("A2 :");
+ Dump (A2'Address, R2'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "A2 : 40 09 21 fb 54 44 2d 18\n" }
+
+ Put ("B2 :");
+ Dump (B2'Address, R2'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "B2 : 40 09 21 fb 54 44 2d 18\n" }
+
+ if A1.F /= B1.F then
+ raise Program_Error;
+ end if;
+
+ if A1.F /= Pi then
+ raise Program_Error;
+ end if;
+
+ if A2.F /= B2.F then
+ raise Program_Error;
+ end if;
+
+ if A2.F /= Pi then
+ raise Program_Error;
+ end if;
+
+end;
diff --git a/gcc/testsuite/gnat.dg/sso/r11.adb b/gcc/testsuite/gnat.dg/sso/r11.adb
new file mode 100644
index 00000000000..e472078c5c6
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/sso/r11.adb
@@ -0,0 +1,68 @@
+-- { dg-do run }
+
+with Init11; use Init11;
+with Text_IO; use Text_IO;
+with Dump;
+
+procedure R11 is
+
+ function Get_Elem (R : R1) return My_Integer is
+ Tmp : R1 := R;
+ begin
+ return Tmp.A(1);
+ end;
+
+ procedure Set_Elem (R : access R1; I : My_Integer) is
+ Tmp : R1 := R.all;
+ begin
+ Tmp.A(1) := I;
+ R.all := Tmp;
+ end;
+
+ function Get_Elem (R : R2) return My_Integer is
+ Tmp : R2 := R;
+ begin
+ return Tmp.A(1);
+ end;
+
+ procedure Set_Elem (R : access R2; I : My_Integer) is
+ Tmp : R2 := R.all;
+ begin
+ Tmp.A(1) := I;
+ R.all := Tmp;
+ end;
+
+ A1 : aliased R1 := My_R1;
+ A2 : aliased R2 := My_R2;
+
+begin
+
+ Put ("A1 :");
+ Dump (A1'Address, R1'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "A1 : 78 56 34 12 12 00 ab 00 34 00 cd 00 56 00 ef 00\n" }
+
+ Put ("A2 :");
+ Dump (A2'Address, R1'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "A2 : 12 34 56 78 00 ab 00 12 00 cd 00 34 00 ef 00 56\n" }
+
+ if Get_Elem (A1) /= 16#AB0012# then
+ raise Program_Error;
+ end if;
+
+ Set_Elem (A1'Access, 16#CD0034#);
+ if Get_Elem (A1) /= 16#CD0034# then
+ raise Program_Error;
+ end if;
+
+ if Get_Elem (A2) /= 16#AB0012# then
+ raise Program_Error;
+ end if;
+
+ Set_Elem (A2'Access, 16#CD0034#);
+ if Get_Elem (A2) /= 16#CD0034# then
+ raise Program_Error;
+ end if;
+
+end;
diff --git a/gcc/testsuite/gnat.dg/sso/r12.adb b/gcc/testsuite/gnat.dg/sso/r12.adb
new file mode 100644
index 00000000000..b6e2cf76189
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/sso/r12.adb
@@ -0,0 +1,123 @@
+-- { dg-do run }
+
+with Init12; use Init12;
+with Text_IO; use Text_IO;
+with Dump;
+
+procedure R12 is
+
+ function Get_Elem (A : Arr1) return Integer is
+ Tmp : Arr1 := A;
+ begin
+ return Tmp(1);
+ end;
+
+ procedure Set_Elem (A : access Arr1; I : Integer) is
+ Tmp : Arr1 := A.all;
+ begin
+ Tmp(1) := I;
+ A.all := Tmp;
+ end;
+
+ function Get_Elem (A : Arr11) return Integer is
+ Tmp : Arr11 := A;
+ begin
+ return Tmp(1,1);
+ end;
+
+ procedure Set_Elem (A : access Arr11; I : Integer) is
+ Tmp : Arr11 := A.all;
+ begin
+ Tmp(1,1) := I;
+ A.all := Tmp;
+ end;
+
+ function Get_Elem (A : Arr2) return Integer is
+ Tmp : Arr2 := A;
+ begin
+ return Tmp(1);
+ end;
+
+ procedure Set_Elem (A : access Arr2; I : Integer) is
+ Tmp : Arr2 := A.all;
+ begin
+ Tmp(1) := I;
+ A.all := Tmp;
+ end;
+
+ function Get_Elem (A : Arr22) return Integer is
+ Tmp : Arr22 := A;
+ begin
+ return Tmp(1,1);
+ end;
+
+ procedure Set_Elem (A : access Arr22; I : Integer) is
+ Tmp : Arr22 := A.all;
+ begin
+ Tmp(1,1) := I;
+ A.all := Tmp;
+ end;
+
+ A1 : aliased Arr1 := My_A1;
+ A11 : aliased Arr11 := My_A11;
+
+ A2 : aliased Arr2 := My_A2;
+ A22 : aliased Arr22 := My_A22;
+
+begin
+ Put ("A1 :");
+ Dump (A1'Address, Arr1'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "A1 : 12 00 ab 00 34 00 cd 00 56 00 ef 00\n" }
+
+ Put ("A11 :");
+ Dump (A11'Address, Arr11'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "A11 : 12 00 ab 00 34 00 cd 00 12 00 ab 00 34 00 cd 00\n" }
+
+ Put ("A2 :");
+ Dump (A2'Address, Arr2'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "A2 : 00 ab 00 12 00 cd 00 34 00 ef 00 56\n" }
+
+ Put ("A22 :");
+ Dump (A22'Address, Arr22'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "A22 : 00 ab 00 12 00 cd 00 34 00 ab 00 12 00 cd 00 34\n" }
+
+ if Get_Elem (A1) /= 16#AB0012# then
+ raise Program_Error;
+ end if;
+
+ Set_Elem (A1'Access, 16#CD0034#);
+ if Get_Elem (A1) /= 16#CD0034# then
+ raise Program_Error;
+ end if;
+
+ if Get_Elem (A11) /= 16#AB0012# then
+ raise Program_Error;
+ end if;
+
+ Set_Elem (A11'Access, 16#CD0034#);
+ if Get_Elem (A11) /= 16#CD0034# then
+ raise Program_Error;
+ end if;
+
+ if Get_Elem (A2) /= 16#AB0012# then
+ raise Program_Error;
+ end if;
+
+ Set_Elem (A2'Access, 16#CD0034#);
+ if Get_Elem (A2) /= 16#CD0034# then
+ raise Program_Error;
+ end if;
+
+ if Get_Elem (A22) /= 16#AB0012# then
+ raise Program_Error;
+ end if;
+
+ Set_Elem (A22'Access, 16#CD0034#);
+ if Get_Elem (A22) /= 16#CD0034# then
+ raise Program_Error;
+ end if;
+end;
diff --git a/gcc/testsuite/gnat.dg/sso/r3.adb b/gcc/testsuite/gnat.dg/sso/r3.adb
new file mode 100644
index 00000000000..746109688c9
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/sso/r3.adb
@@ -0,0 +1,68 @@
+-- { dg-do run }
+
+with Init3; use Init3;
+with Text_IO; use Text_IO;
+with Dump;
+
+procedure R3 is
+
+ function Get_Elem (R : R1) return Integer is
+ Tmp : R1 := R;
+ begin
+ return Tmp.I;
+ end;
+
+ procedure Set_Elem (R : access R1; I : Integer) is
+ Tmp : R1 := R.all;
+ begin
+ Tmp.I := I;
+ R.all := Tmp;
+ end;
+
+ function Get_Elem (R : R2) return Integer is
+ Tmp : R2 := R;
+ begin
+ return Tmp.I;
+ end;
+
+ procedure Set_Elem (R : access R2; I : Integer) is
+ Tmp : R2 := R.all;
+ begin
+ Tmp.I := I;
+ R.all := Tmp;
+ end;
+
+ A1 : aliased R1 := My_R1;
+ A2 : aliased R2 := My_R2;
+
+begin
+
+ Put ("A1 :");
+ Dump (A1'Address, R1'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "A1 : e2 59 d1 48 b4 aa d9 bb\n" }
+
+ Put ("A2 :");
+ Dump (A2'Address, R1'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "A2 : 84 8d 15 9e 15 5b 35 df\n" }
+
+ if Get_Elem (A1) /= 16#12345678# then
+ raise Program_Error;
+ end if;
+
+ Set_Elem (A1'Access, 16#CD0034#);
+ if Get_Elem (A1) /= 16#CD0034# then
+ raise Program_Error;
+ end if;
+
+ if Get_Elem (A2) /= 16#12345678# then
+ raise Program_Error;
+ end if;
+
+ Set_Elem (A2'Access, 16#CD0034#);
+ if Get_Elem (A2) /= 16#CD0034# then
+ raise Program_Error;
+ end if;
+
+end;
diff --git a/gcc/testsuite/gnat.dg/sso/r5.adb b/gcc/testsuite/gnat.dg/sso/r5.adb
new file mode 100644
index 00000000000..6dcb87f8b6e
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/sso/r5.adb
@@ -0,0 +1,68 @@
+-- { dg-do run }
+
+with Init5; use Init5;
+with Text_IO; use Text_IO;
+with Dump;
+
+procedure R5 is
+
+ function Get_Elem (R : R1) return Integer is
+ Tmp : R1 := R;
+ begin
+ return Tmp.A(1);
+ end;
+
+ procedure Set_Elem (R : access R1; I : Integer) is
+ Tmp : R1 := R.all;
+ begin
+ Tmp.A(1) := I;
+ R.all := Tmp;
+ end;
+
+ function Get_Elem (R : R2) return Integer is
+ Tmp : R2 := R;
+ begin
+ return Tmp.A(1);
+ end;
+
+ procedure Set_Elem (R : access R2; I : Integer) is
+ Tmp : R2 := R.all;
+ begin
+ Tmp.A(1) := I;
+ R.all := Tmp;
+ end;
+
+ A1 : aliased R1 := My_R1;
+ A2 : aliased R2 := My_R2;
+
+begin
+
+ Put ("A1 :");
+ Dump (A1'Address, R1'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "A1 : 78 56 34 12 12 00 ab 00 34 00 cd 00 56 00 ef 00\n" }
+
+ Put ("A2 :");
+ Dump (A2'Address, R1'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "A2 : 12 34 56 78 00 ab 00 12 00 cd 00 34 00 ef 00 56\n" }
+
+ if Get_Elem (A1) /= 16#AB0012# then
+ raise Program_Error;
+ end if;
+
+ Set_Elem (A1'Access, 16#CD0034#);
+ if Get_Elem (A1) /= 16#CD0034# then
+ raise Program_Error;
+ end if;
+
+ if Get_Elem (A2) /= 16#AB0012# then
+ raise Program_Error;
+ end if;
+
+ Set_Elem (A2'Access, 16#CD0034#);
+ if Get_Elem (A2) /= 16#CD0034# then
+ raise Program_Error;
+ end if;
+
+end;
diff --git a/gcc/testsuite/gnat.dg/sso/r6.adb b/gcc/testsuite/gnat.dg/sso/r6.adb
new file mode 100644
index 00000000000..5ef59893552
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/sso/r6.adb
@@ -0,0 +1,68 @@
+-- { dg-do run }
+
+with Init6; use Init6;
+with Text_IO; use Text_IO;
+with Dump;
+
+procedure R6 is
+
+ function Get_Elem (R : R1) return Integer is
+ Tmp : R1 := R;
+ begin
+ return Tmp.A(1);
+ end;
+
+ procedure Set_Elem (R : access R1; I : Integer) is
+ Tmp : R1 := R.all;
+ begin
+ Tmp.A(1) := I;
+ R.all := Tmp;
+ end;
+
+ function Get_Elem (R : R2) return Integer is
+ Tmp : R2 := R;
+ begin
+ return Tmp.A(1);
+ end;
+
+ procedure Set_Elem (R : access R2; I : Integer) is
+ Tmp : R2 := R.all;
+ begin
+ Tmp.A(1) := I;
+ R.all := Tmp;
+ end;
+
+ A1 : aliased R1 := My_R1;
+ A2 : aliased R2 := My_R2;
+
+begin
+
+ Put ("A1 :");
+ Dump (A1'Address, R1'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "A1 : 78 56 34 12 00 ab 00 12 00 cd 00 34 00 ef 00 56\n" }
+
+ Put ("A2 :");
+ Dump (A2'Address, R1'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "A2 : 12 34 56 78 12 00 ab 00 34 00 cd 00 56 00 ef 00\n" }
+
+ if Get_Elem (A1) /= 16#AB0012# then
+ raise Program_Error;
+ end if;
+
+ Set_Elem (A1'Access, 16#CD0034#);
+ if Get_Elem (A1) /= 16#CD0034# then
+ raise Program_Error;
+ end if;
+
+ if Get_Elem (A2) /= 16#AB0012# then
+ raise Program_Error;
+ end if;
+
+ Set_Elem (A2'Access, 16#CD0034#);
+ if Get_Elem (A2) /= 16#CD0034# then
+ raise Program_Error;
+ end if;
+
+end;
diff --git a/gcc/testsuite/gnat.dg/sso/r7.adb b/gcc/testsuite/gnat.dg/sso/r7.adb
new file mode 100644
index 00000000000..58a015beb15
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/sso/r7.adb
@@ -0,0 +1,68 @@
+-- { dg-do run }
+
+with Init7; use Init7;
+with Text_IO; use Text_IO;
+with Dump;
+
+procedure R7 is
+
+ function Get_Elem (R : R1) return Integer is
+ Tmp : R1 := R;
+ begin
+ return Tmp.N.C1;
+ end;
+
+ procedure Set_Elem (R : access R1; I : Integer) is
+ Tmp : R1 := R.all;
+ begin
+ Tmp.N.C1 := I;
+ R.all := Tmp;
+ end;
+
+ function Get_Elem (R : R2) return Integer is
+ Tmp : R2 := R;
+ begin
+ return Tmp.N.C1;
+ end;
+
+ procedure Set_Elem (R : access R2; I : Integer) is
+ Tmp : R2 := R.all;
+ begin
+ Tmp.N.C1 := I;
+ R.all := Tmp;
+ end;
+
+ A1 : aliased R1 := My_R1;
+ A2 : aliased R2 := My_R2;
+
+begin
+
+ Put ("A1 :");
+ Dump (A1'Address, R1'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "A1 : 78 56 34 12 12 00 ab 00 34 00 cd 00 56 00 ef 00\n" }
+
+ Put ("A2 :");
+ Dump (A2'Address, R1'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "A2 : 12 34 56 78 00 ab 00 12 00 cd 00 34 00 ef 00 56\n" }
+
+ if Get_Elem (A1) /= 16#AB0012# then
+ raise Program_Error;
+ end if;
+
+ Set_Elem (A1'Access, 16#CD0034#);
+ if Get_Elem (A1) /= 16#CD0034# then
+ raise Program_Error;
+ end if;
+
+ if Get_Elem (A2) /= 16#AB0012# then
+ raise Program_Error;
+ end if;
+
+ Set_Elem (A2'Access, 16#CD0034#);
+ if Get_Elem (A2) /= 16#CD0034# then
+ raise Program_Error;
+ end if;
+
+end;
diff --git a/gcc/testsuite/gnat.dg/sso/r8.adb b/gcc/testsuite/gnat.dg/sso/r8.adb
new file mode 100644
index 00000000000..cbb1d5b617d
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/sso/r8.adb
@@ -0,0 +1,68 @@
+-- { dg-do run }
+
+with Init8; use Init8;
+with Text_IO; use Text_IO;
+with Dump;
+
+procedure R8 is
+
+ function Get_Elem (R : R1) return Integer is
+ Tmp : R1 := R;
+ begin
+ return Tmp.N.C1;
+ end;
+
+ procedure Set_Elem (R : access R1; I : Integer) is
+ Tmp : R1 := R.all;
+ begin
+ Tmp.N.C1 := I;
+ R.all := Tmp;
+ end;
+
+ function Get_Elem (R : R2) return Integer is
+ Tmp : R2 := R;
+ begin
+ return Tmp.N.C1;
+ end;
+
+ procedure Set_Elem (R : access R2; I : Integer) is
+ Tmp : R2 := R.all;
+ begin
+ Tmp.N.C1 := I;
+ R.all := Tmp;
+ end;
+
+ A1 : aliased R1 := My_R1;
+ A2 : aliased R2 := My_R2;
+
+begin
+
+ Put ("A1 :");
+ Dump (A1'Address, R1'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "A1 : 78 56 34 12 00 ab 00 12 00 cd 00 34 00 ef 00 56\n" }
+
+ Put ("A2 :");
+ Dump (A2'Address, R1'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "A2 : 12 34 56 78 12 00 ab 00 34 00 cd 00 56 00 ef 00\n" }
+
+ if Get_Elem (A1) /= 16#AB0012# then
+ raise Program_Error;
+ end if;
+
+ Set_Elem (A1'Access, 16#CD0034#);
+ if Get_Elem (A1) /= 16#CD0034# then
+ raise Program_Error;
+ end if;
+
+ if Get_Elem (A2) /= 16#AB0012# then
+ raise Program_Error;
+ end if;
+
+ Set_Elem (A2'Access, 16#CD0034#);
+ if Get_Elem (A2) /= 16#CD0034# then
+ raise Program_Error;
+ end if;
+
+end;
diff --git a/gcc/testsuite/gnat.dg/sso/s11.adb b/gcc/testsuite/gnat.dg/sso/s11.adb
new file mode 100644
index 00000000000..6fb715f8a01
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/sso/s11.adb
@@ -0,0 +1,78 @@
+-- { dg-do run }
+
+with Init11; use Init11;
+with Text_IO; use Text_IO;
+with Dump;
+
+procedure S11 is
+
+ A1 : R1 := My_R1;
+ A2 : R2 := My_R2;
+
+ AA1 : Arr1;
+ AA2 : Arr2;
+
+ C1 : My_Integer;
+ C2 : My_Integer;
+ C3 : My_Integer;
+
+begin
+
+ Put ("A1 :");
+ Dump (A1'Address, R1'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "A1 : 78 56 34 12 12 00 ab 00 34 00 cd 00 56 00 ef 00\n" }
+
+ Put ("A2 :");
+ Dump (A2'Address, R1'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "A2 : 12 34 56 78 00 ab 00 12 00 cd 00 34 00 ef 00 56\n" }
+
+ AA1 := A1.A;
+ C1 := AA1(1);
+ C2 := AA1(2);
+ C3 := AA1(3);
+
+ Put_Line("C1 :" & C1'Img);
+ -- { dg-output "C1 : 11206674\n" }
+
+ Put_Line("C2 :" & C2'Img);
+ -- { dg-output "C2 : 13434932\n" }
+
+ Put_Line("C3 :" & C3'Img);
+ -- { dg-output "C3 : 15663190\n" }
+
+ AA1(1) := C1;
+ AA1(2) := C2;
+ AA1(3) := C3;
+ A1.A := AA1;
+
+ AA2 := A2.A;
+ C1 := AA2(1);
+ C2 := AA2(2);
+ C3 := AA2(3);
+
+ Put_Line("C1 :" & C1'Img);
+ -- { dg-output "C1 : 11206674\n" }
+
+ Put_Line("C2 :" & C2'Img);
+ -- { dg-output "C2 : 13434932\n" }
+
+ Put_Line("C3 :" & C3'Img);
+ -- { dg-output "C3 : 15663190\n" }
+
+ AA2(1) := C1;
+ AA2(2) := C2;
+ AA2(3) := C3;
+ A2.A := AA2;
+
+ Put ("A1 :");
+ Dump (A1'Address, R1'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "A1 : 78 56 34 12 12 00 ab 00 34 00 cd 00 56 00 ef 00\n" }
+
+ Put ("A2 :");
+ Dump (A2'Address, R1'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "A2 : 12 34 56 78 00 ab 00 12 00 cd 00 34 00 ef 00 56\n" }
+end;
diff --git a/gcc/testsuite/gnat.dg/sso/s12.adb b/gcc/testsuite/gnat.dg/sso/s12.adb
new file mode 100644
index 00000000000..1bc624e3468
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/sso/s12.adb
@@ -0,0 +1,77 @@
+-- { dg-do run }
+
+with Init12; use Init12;
+with Text_IO; use Text_IO;
+with Dump;
+
+procedure S12 is
+
+ A11 : Arr11 := My_A11;
+ A22 : Arr22 := My_A22;
+
+ A1 : Arr1;
+ A2 : Arr2;
+
+ C1 : Integer;
+ C2 : Integer;
+ C3 : Integer;
+
+begin
+ Put ("A11 :");
+ Dump (A11'Address, Arr11'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "A11 : 12 00 ab 00 34 00 cd 00 12 00 ab 00 34 00 cd 00\n" }
+
+ Put ("A22 :");
+ Dump (A22'Address, Arr22'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "A22 : 00 ab 00 12 00 cd 00 34 00 ab 00 12 00 cd 00 34\n" }
+
+ A1 := (A11(1,1), A11(1,2), A11(2,1));
+ C1 := A1(1);
+ C2 := A1(2);
+ C3 := A1(3);
+
+ Put_Line("C1 :" & C1'Img);
+ -- { dg-output "C1 : 11206674\n" }
+
+ Put_Line("C2 :" & C2'Img);
+ -- { dg-output "C2 : 13434932\n" }
+
+ Put_Line("C3 :" & C3'Img);
+ -- { dg-output "C3 : 11206674\n" }
+
+ A1(1) := C1;
+ A1(2) := C2;
+ A1(3) := C3;
+ A11(1,1) := A1(1); A11(1,2) := A1(2); A11(2,1) := A1(3);
+
+ A2 := (A22(1,1), A22(1,2), A22(2,1));
+ C1 := A2(1);
+ C2 := A2(2);
+ C3 := A2(3);
+
+ Put_Line("C1 :" & C1'Img);
+ -- { dg-output "C1 : 11206674\n" }
+
+ Put_Line("C2 :" & C2'Img);
+ -- { dg-output "C2 : 13434932\n" }
+
+ Put_Line("C3 :" & C3'Img);
+ -- { dg-output "C3 : 11206674\n" }
+
+ A2(1) := C1;
+ A2(2) := C2;
+ A2(3) := C3;
+ A22(1,1) := A2(1); A22(1,2) := A2(2); A22(2,1) := A2(3);
+
+ Put ("A11 :");
+ Dump (A11'Address, Arr11'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "A11 : 12 00 ab 00 34 00 cd 00 12 00 ab 00 34 00 cd 00\n" }
+
+ Put ("A22 :");
+ Dump (A22'Address, Arr22'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "A22 : 00 ab 00 12 00 cd 00 34 00 ab 00 12 00 cd 00 34\n" }
+end;
diff --git a/gcc/testsuite/gnat.dg/sso/s3.adb b/gcc/testsuite/gnat.dg/sso/s3.adb
new file mode 100644
index 00000000000..833525d333e
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/sso/s3.adb
@@ -0,0 +1,79 @@
+-- { dg-do run }
+
+with Init3; use Init3;
+with Text_IO; use Text_IO;
+with Dump;
+
+procedure S3 is
+
+ A1 : R1 := My_R1;
+ A2 : R2 := My_R2;
+
+ N1 : Nested1;
+ N2 : Nested2;
+
+ C1 : Init3.Count;
+ C2 : Init3.Count;
+ C3 : Init3.Count;
+
+begin
+
+ Put ("A1 :");
+ Dump (A1'Address, R1'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "A1 : e2 59 d1 48 b4 aa d9 bb\n" }
+
+ Put ("A2 :");
+ Dump (A2'Address, R1'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "A2 : 84 8d 15 9e 15 5b 35 df\n" }
+
+ N1 := A1.N;
+ C1 := N1.C1;
+ C2 := N1.C2;
+ C3 := N1.C3;
+
+ Put_Line("C1 :" & C1'Img);
+ -- { dg-output "C1 : 171\n" }
+
+ Put_Line("C2 :" & C2'Img);
+ -- { dg-output "C2 : 205\n" }
+
+ Put_Line("C3 :" & C3'Img);
+ -- { dg-output "C3 : 239\n" }
+
+ N1.C1 := C1;
+ N1.C2 := C2;
+ N1.C3 := C3;
+ A1.N := N1;
+
+ N2 := A2.N;
+ C1 := N2.C1;
+ C2 := N2.C2;
+ C3 := N2.C3;
+
+ Put_Line("C1 :" & C1'Img);
+ -- { dg-output "C1 : 171\n" }
+
+ Put_Line("C2 :" & C2'Img);
+ -- { dg-output "C2 : 205\n" }
+
+ Put_Line("C3 :" & C3'Img);
+ -- { dg-output "C3 : 239\n" }
+
+ N2.C1 := C1;
+ N2.C2 := C2;
+ N2.C3 := C3;
+ A2.N := N2;
+
+ Put ("A1 :");
+ Dump (A1'Address, R1'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "A1 : e2 59 d1 48 b4 aa d9 bb\n" }
+
+ Put ("A2 :");
+ Dump (A2'Address, R1'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "A2 : 84 8d 15 9e 15 5b 35 df\n" }
+
+end;
diff --git a/gcc/testsuite/gnat.dg/sso/s5.adb b/gcc/testsuite/gnat.dg/sso/s5.adb
new file mode 100644
index 00000000000..dc3b3011537
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/sso/s5.adb
@@ -0,0 +1,78 @@
+-- { dg-do run }
+
+with Init5; use Init5;
+with Text_IO; use Text_IO;
+with Dump;
+
+procedure S5 is
+
+ A1 : R1 := My_R1;
+ A2 : R2 := My_R2;
+
+ AA1 : Arr1;
+ AA2 : Arr2;
+
+ C1 : Integer;
+ C2 : Integer;
+ C3 : Integer;
+
+begin
+
+ Put ("A1 :");
+ Dump (A1'Address, R1'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "A1 : 78 56 34 12 12 00 ab 00 34 00 cd 00 56 00 ef 00\n" }
+
+ Put ("A2 :");
+ Dump (A2'Address, R1'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "A2 : 12 34 56 78 00 ab 00 12 00 cd 00 34 00 ef 00 56\n" }
+
+ AA1 := A1.A;
+ C1 := AA1(1);
+ C2 := AA1(2);
+ C3 := AA1(3);
+
+ Put_Line("C1 :" & C1'Img);
+ -- { dg-output "C1 : 11206674\n" }
+
+ Put_Line("C2 :" & C2'Img);
+ -- { dg-output "C2 : 13434932\n" }
+
+ Put_Line("C3 :" & C3'Img);
+ -- { dg-output "C3 : 15663190\n" }
+
+ AA1(1) := C1;
+ AA1(2) := C2;
+ AA1(3) := C3;
+ A1.A := AA1;
+
+ AA2 := A2.A;
+ C1 := AA2(1);
+ C2 := AA2(2);
+ C3 := AA2(3);
+
+ Put_Line("C1 :" & C1'Img);
+ -- { dg-output "C1 : 11206674\n" }
+
+ Put_Line("C2 :" & C2'Img);
+ -- { dg-output "C2 : 13434932\n" }
+
+ Put_Line("C3 :" & C3'Img);
+ -- { dg-output "C3 : 15663190\n" }
+
+ AA2(1) := C1;
+ AA2(2) := C2;
+ AA2(3) := C3;
+ A2.A := AA2;
+
+ Put ("A1 :");
+ Dump (A1'Address, R1'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "A1 : 78 56 34 12 12 00 ab 00 34 00 cd 00 56 00 ef 00\n" }
+
+ Put ("A2 :");
+ Dump (A2'Address, R1'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "A2 : 12 34 56 78 00 ab 00 12 00 cd 00 34 00 ef 00 56\n" }
+end;
diff --git a/gcc/testsuite/gnat.dg/sso/s6.adb b/gcc/testsuite/gnat.dg/sso/s6.adb
new file mode 100644
index 00000000000..48d769b1795
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/sso/s6.adb
@@ -0,0 +1,79 @@
+-- { dg-do run }
+
+with Init6; use Init6;
+with Text_IO; use Text_IO;
+with Dump;
+
+procedure S6 is
+
+ A1 : R1 := My_R1;
+ A2 : R2 := My_R2;
+
+ AA1 : Arr1;
+ AA2 : Arr2;
+
+ C1 : Integer;
+ C2 : Integer;
+ C3 : Integer;
+
+begin
+
+ Put ("A1 :");
+ Dump (A1'Address, R1'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "A1 : 78 56 34 12 00 ab 00 12 00 cd 00 34 00 ef 00 56\n" }
+
+ Put ("A2 :");
+ Dump (A2'Address, R1'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "A2 : 12 34 56 78 12 00 ab 00 34 00 cd 00 56 00 ef 00\n" }
+
+ AA1 := A1.A;
+ C1 := AA1(1);
+ C2 := AA1(2);
+ C3 := AA1(3);
+
+ Put_Line("C1 :" & C1'Img);
+ -- { dg-output "C1 : 11206674\n" }
+
+ Put_Line("C2 :" & C2'Img);
+ -- { dg-output "C2 : 13434932\n" }
+
+ Put_Line("C3 :" & C3'Img);
+ -- { dg-output "C3 : 15663190\n" }
+
+ AA1(1) := C1;
+ AA1(2) := C2;
+ AA1(3) := C3;
+ A1.A := AA1;
+
+ AA2 := A2.A;
+ C1 := AA2(1);
+ C2 := AA2(2);
+ C3 := AA2(3);
+
+ Put_Line("C1 :" & C1'Img);
+ -- { dg-output "C1 : 11206674\n" }
+
+ Put_Line("C2 :" & C2'Img);
+ -- { dg-output "C2 : 13434932\n" }
+
+ Put_Line("C3 :" & C3'Img);
+ -- { dg-output "C3 : 15663190\n" }
+
+ AA2(1) := C1;
+ AA2(2) := C2;
+ AA2(3) := C3;
+ A2.A := AA2;
+
+ Put ("A1 :");
+ Dump (A1'Address, R1'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "A1 : 78 56 34 12 00 ab 00 12 00 cd 00 34 00 ef 00 56\n" }
+
+ Put ("A2 :");
+ Dump (A2'Address, R1'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "A2 : 12 34 56 78 12 00 ab 00 34 00 cd 00 56 00 ef 00\n" }
+
+end;
diff --git a/gcc/testsuite/gnat.dg/sso/s7.adb b/gcc/testsuite/gnat.dg/sso/s7.adb
new file mode 100644
index 00000000000..f4725d78c93
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/sso/s7.adb
@@ -0,0 +1,79 @@
+-- { dg-do run }
+
+with Init7; use Init7;
+with Text_IO; use Text_IO;
+with Dump;
+
+procedure S7 is
+
+ A1 : R1 := My_R1;
+ A2 : R2 := My_R2;
+
+ N1 : Nested1;
+ N2 : Nested2;
+
+ C1 : Integer;
+ C2 : Integer;
+ C3 : Integer;
+
+begin
+
+ Put ("A1 :");
+ Dump (A1'Address, R1'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "A1 : 78 56 34 12 12 00 ab 00 34 00 cd 00 56 00 ef 00\n" }
+
+ Put ("A2 :");
+ Dump (A2'Address, R1'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "A2 : 12 34 56 78 00 ab 00 12 00 cd 00 34 00 ef 00 56\n" }
+
+ N1 := A1.N;
+ C1 := N1.C1;
+ C2 := N1.C2;
+ C3 := N1.C3;
+
+ Put_Line("C1 :" & C1'Img);
+ -- { dg-output "C1 : 11206674\n" }
+
+ Put_Line("C2 :" & C2'Img);
+ -- { dg-output "C2 : 13434932\n" }
+
+ Put_Line("C3 :" & C3'Img);
+ -- { dg-output "C3 : 15663190\n" }
+
+ N1.C1 := C1;
+ N1.C2 := C2;
+ N1.C3 := C3;
+ A1.N := N1;
+
+ N2 := A2.N;
+ C1 := N2.C1;
+ C2 := N2.C2;
+ C3 := N2.C3;
+
+ Put_Line("C1 :" & C1'Img);
+ -- { dg-output "C1 : 11206674\n" }
+
+ Put_Line("C2 :" & C2'Img);
+ -- { dg-output "C2 : 13434932\n" }
+
+ Put_Line("C3 :" & C3'Img);
+ -- { dg-output "C3 : 15663190\n" }
+
+ N2.C1 := C1;
+ N2.C2 := C2;
+ N2.C3 := C3;
+ A2.N := N2;
+
+ Put ("A1 :");
+ Dump (A1'Address, R1'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "A1 : 78 56 34 12 12 00 ab 00 34 00 cd 00 56 00 ef 00\n" }
+
+ Put ("A2 :");
+ Dump (A2'Address, R1'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "A2 : 12 34 56 78 00 ab 00 12 00 cd 00 34 00 ef 00 56\n" }
+
+end;
diff --git a/gcc/testsuite/gnat.dg/sso/s8.adb b/gcc/testsuite/gnat.dg/sso/s8.adb
new file mode 100644
index 00000000000..0545932f4e1
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/sso/s8.adb
@@ -0,0 +1,79 @@
+-- { dg-do run }
+
+with Init8; use Init8;
+with Text_IO; use Text_IO;
+with Dump;
+
+procedure S8 is
+
+ A1 : R1 := My_R1;
+ A2 : R2 := My_R2;
+
+ N1 : Nested1;
+ N2 : Nested2;
+
+ C1 : Integer;
+ C2 : Integer;
+ C3 : Integer;
+
+begin
+
+ Put ("A1 :");
+ Dump (A1'Address, R1'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "A1 : 78 56 34 12 00 ab 00 12 00 cd 00 34 00 ef 00 56\n" }
+
+ Put ("A2 :");
+ Dump (A2'Address, R1'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "A2 : 12 34 56 78 12 00 ab 00 34 00 cd 00 56 00 ef 00\n" }
+
+ N1 := A1.N;
+ C1 := N1.C1;
+ C2 := N1.C2;
+ C3 := N1.C3;
+
+ Put_Line("C1 :" & C1'Img);
+ -- { dg-output "C1 : 11206674\n" }
+
+ Put_Line("C2 :" & C2'Img);
+ -- { dg-output "C2 : 13434932\n" }
+
+ Put_Line("C3 :" & C3'Img);
+ -- { dg-output "C3 : 15663190\n" }
+
+ N1.C1 := C1;
+ N1.C2 := C2;
+ N1.C3 := C3;
+ A1.N := N1;
+
+ N2 := A2.N;
+ C1 := N2.C1;
+ C2 := N2.C2;
+ C3 := N2.C3;
+
+ Put_Line("C1 :" & C1'Img);
+ -- { dg-output "C1 : 11206674\n" }
+
+ Put_Line("C2 :" & C2'Img);
+ -- { dg-output "C2 : 13434932\n" }
+
+ Put_Line("C3 :" & C3'Img);
+ -- { dg-output "C3 : 15663190\n" }
+
+ N2.C1 := C1;
+ N2.C2 := C2;
+ N2.C3 := C3;
+ A2.N := N2;
+
+ Put ("A1 :");
+ Dump (A1'Address, R1'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "A1 : 78 56 34 12 00 ab 00 12 00 cd 00 34 00 ef 00 56\n" }
+
+ Put ("A2 :");
+ Dump (A2'Address, R1'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "A2 : 12 34 56 78 12 00 ab 00 34 00 cd 00 56 00 ef 00\n" }
+
+end;
diff --git a/gcc/testsuite/gnat.dg/sso/sso.exp b/gcc/testsuite/gnat.dg/sso/sso.exp
new file mode 100644
index 00000000000..ae8be2c6092
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/sso/sso.exp
@@ -0,0 +1,40 @@
+# Copyright (C) 2013 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/>.
+
+# Load support procs.
+load_lib gnat-dg.exp
+load_lib torture-options.exp
+
+# Initialize `dg'.
+torture-init
+dg-init
+
+set SSO_TORTURE_OPTIONS [list \
+ { -O0 } \
+ { -O1 -fno-inline } \
+ { -O2 } \
+ { -O3 -finline-functions } \
+ { -Os } \
+ { -Og -g } ]
+
+set-torture-options $SSO_TORTURE_OPTIONS
+
+# Main loop.
+gcc-dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.adb]] "" ""
+
+# All done.
+dg-finish
+torture-finish
diff --git a/gcc/testsuite/gnat.dg/sso/t1.adb b/gcc/testsuite/gnat.dg/sso/t1.adb
new file mode 100644
index 00000000000..dd289476363
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/sso/t1.adb
@@ -0,0 +1,55 @@
+-- { dg-do run }
+
+with Init1; use Init1;
+with Text_IO; use Text_IO;
+with Dump;
+
+procedure T1 is
+
+ Local_R1 : R1;
+ Local_R2 : R2;
+
+begin
+ Local_R1.I := My_R1.I + 1;
+
+ Put ("Local_R1 :");
+ Dump (Local_R1'Address, R1'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "Local_R1 : 79 56 34 12\n" }
+
+ Local_R2.I := My_R2.I + 1;
+
+ Put ("Local_R2 :");
+ Dump (Local_R2'Address, R2'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "Local_R2 : 12 34 56 79\n" }
+
+ Local_R1.I := 16#12345678#;
+
+ Put ("Local_R1 :");
+ Dump (Local_R1'Address, R1'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "Local_R1 : 78 56 34 12\n" }
+
+ Local_R2.I := 16#12345678#;
+
+ Put ("Local_R2 :");
+ Dump (Local_R2'Address, R2'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "Local_R2 : 12 34 56 78\n" }
+
+ Local_R1.I := Local_R1.I + 1;
+
+ Put ("Local_R1 :");
+ Dump (Local_R1'Address, R1'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "Local_R1 : 79 56 34 12\n" }
+
+ Local_R2.I := Local_R2.I + 1;
+
+ Put ("Local_R2 :");
+ Dump (Local_R2'Address, R2'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "Local_R2 : 12 34 56 79\n" }
+
+end;
diff --git a/gcc/testsuite/gnat.dg/sso/t10.adb b/gcc/testsuite/gnat.dg/sso/t10.adb
new file mode 100644
index 00000000000..152268a6edc
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/sso/t10.adb
@@ -0,0 +1,56 @@
+-- { dg-do run }
+-- { dg-options "-gnatws" }
+
+with Init10; use Init10;
+with Text_IO; use Text_IO;
+with Dump;
+
+procedure T10 is
+
+ Local_R1 : R1;
+ Local_R2 : R2;
+
+begin
+ Local_R1.I := My_R1.I + 1;
+
+ Put ("Local_R1 :");
+ Dump (Local_R1'Address, R1'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "Local_R1 : 79 56 34 12\n" }
+
+ Local_R2.I := My_R2.I + 1;
+
+ Put ("Local_R2 :");
+ Dump (Local_R2'Address, R2'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "Local_R2 : 12 34 56 79\n" }
+
+ Local_R1.I := 16#12345678#;
+
+ Put ("Local_R1 :");
+ Dump (Local_R1'Address, R1'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "Local_R1 : 78 56 34 12\n" }
+
+ Local_R2.I := 16#12345678#;
+
+ Put ("Local_R2 :");
+ Dump (Local_R2'Address, R2'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "Local_R2 : 12 34 56 78\n" }
+
+ Local_R1.I := Local_R1.I + 1;
+
+ Put ("Local_R1 :");
+ Dump (Local_R1'Address, R1'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "Local_R1 : 79 56 34 12\n" }
+
+ Local_R2.I := Local_R2.I + 1;
+
+ Put ("Local_R2 :");
+ Dump (Local_R2'Address, R2'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "Local_R2 : 12 34 56 79\n" }
+
+end;
diff --git a/gcc/testsuite/gnat.dg/sso/t11.adb b/gcc/testsuite/gnat.dg/sso/t11.adb
new file mode 100644
index 00000000000..b0c3ff4dfa4
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/sso/t11.adb
@@ -0,0 +1,67 @@
+-- { dg-do run }
+
+with Init11; use Init11;
+with Text_IO; use Text_IO;
+with Dump;
+
+procedure T11 is
+
+ Local_R1 : R1;
+ Local_R2 : R2;
+
+begin
+ Local_R1.I := My_R1.I + 1;
+ Local_R1.A(1) := My_R1.A(1) + 1;
+ Local_R1.A(2) := My_R1.A(2) + 1;
+ Local_R1.A(3) := My_R1.A(3) + 1;
+
+ Put ("Local_R1 :");
+ Dump (Local_R1'Address, R1'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "Local_R1 : 79 56 34 12 13 00 ab 00 35 00 cd 00 57 00 ef 00\n" }
+
+ Local_R2.I := My_R2.I + 1;
+ Local_R2.A(1) := My_R2.A(1) + 1;
+ Local_R2.A(2) := My_R2.A(2) + 1;
+ Local_R2.A(3) := My_R2.A(3) + 1;
+
+ Put ("Local_R2 :");
+ Dump (Local_R2'Address, R2'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "Local_R2 : 12 34 56 79 00 ab 00 13 00 cd 00 35 00 ef 00 57\n" }
+
+ Local_R1 := (I => 16#12345678#,
+ A => (16#AB0012#, 16#CD0034#, 16#EF0056#));
+ Put ("Local_R1 :");
+ Dump (Local_R1'Address, R1'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "Local_R1 : 78 56 34 12 12 00 ab 00 34 00 cd 00 56 00 ef 00\n" }
+
+ Local_R2 := (I => 16#12345678#,
+ A => (16#AB0012#, 16#CD0034#, 16#EF0056#));
+ Put ("Local_R2 :");
+ Dump (Local_R2'Address, R2'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "Local_R2 : 12 34 56 78 00 ab 00 12 00 cd 00 34 00 ef 00 56\n" }
+
+ Local_R1.I := Local_R1.I + 1;
+ Local_R1.A(1) := Local_R1.A(1) + 1;
+ Local_R1.A(2) := Local_R1.A(2) + 1;
+ Local_R1.A(3) := Local_R1.A(3) + 1;
+
+ Put ("Local_R1 :");
+ Dump (Local_R1'Address, R1'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "Local_R1 : 79 56 34 12 13 00 ab 00 35 00 cd 00 57 00 ef 00\n" }
+
+ Local_R2.I := Local_R2.I + 1;
+ Local_R2.A(1) := Local_R2.A(1) + 1;
+ Local_R2.A(2) := Local_R2.A(2) + 1;
+ Local_R2.A(3) := Local_R2.A(3) + 1;
+
+ Put ("Local_R2 :");
+ Dump (Local_R2'Address, R2'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "Local_R2 : 12 34 56 79 00 ab 00 13 00 cd 00 35 00 ef 00 57\n" }
+
+end;
diff --git a/gcc/testsuite/gnat.dg/sso/t12.adb b/gcc/testsuite/gnat.dg/sso/t12.adb
new file mode 100644
index 00000000000..b62046053dd
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/sso/t12.adb
@@ -0,0 +1,66 @@
+-- { dg-do run }
+--
+with Init12; use Init12;
+with Text_IO; use Text_IO;
+with Dump;
+
+procedure T12 is
+
+ Local_A11 : Arr11;
+ Local_A22 : Arr22;
+
+begin
+ Local_A11(1,1) := My_A11(1,1) + 1;
+ Local_A11(1,2) := My_A11(1,2) + 1;
+ Local_A11(2,1) := My_A11(2,1) + 1;
+ Local_A11(2,2) := My_A11(2,2) + 1;
+
+ Put ("Local_A11 :");
+ Dump (Local_A11'Address, Arr11'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "Local_A11 : 13 00 ab 00 35 00 cd 00 13 00 ab 00 35 00 cd 00\n" }
+
+ Local_A22(1,1) := My_A22(1,1) + 1;
+ Local_A22(1,2) := My_A22(1,2) + 1;
+ Local_A22(2,1) := My_A22(2,1) + 1;
+ Local_A22(2,2) := My_A22(2,2) + 1;
+
+ Put ("Local_A22 :");
+ Dump (Local_A22'Address, Arr22'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "Local_A22 : 00 ab 00 13 00 cd 00 35 00 ab 00 13 00 cd 00 35\n" }
+
+ Local_A11 := (1 => (16#AB0012#, 16#CD0034#),
+ 2 => (16#AB0012#, 16#CD0034#));
+ Put ("Local_A11 :");
+ Dump (Local_A11'Address, Arr11'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "Local_A11 : 12 00 ab 00 34 00 cd 00 12 00 ab 00 34 00 cd 00\\n" }
+
+ Local_A22 := (1 => (16#AB0012#, 16#CD0034#),
+ 2 => (16#AB0012#, 16#CD0034#));
+ Put ("Local_A22 :");
+ Dump (Local_A22'Address, Arr22'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "Local_A22 : 00 ab 00 12 00 cd 00 34 00 ab 00 12 00 cd 00 34\n" }
+
+ Local_A11(1,1) := Local_A11(1,1) + 1;
+ Local_A11(1,2) := Local_A11(1,2) + 1;
+ Local_A11(2,1) := Local_A11(2,1) + 1;
+ Local_A11(2,2) := Local_A11(2,2) + 1;
+
+ Put ("Local_A11 :");
+ Dump (Local_A11'Address, Arr11'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "Local_A11 : 13 00 ab 00 35 00 cd 00 13 00 ab 00 35 00 cd 00\n" }
+
+ Local_A22(1,1) := Local_A22(1,1) + 1;
+ Local_A22(1,2) := Local_A22(1,2) + 1;
+ Local_A22(2,1) := Local_A22(2,1) + 1;
+ Local_A22(2,2) := Local_A22(2,2) + 1;
+
+ Put ("Local_A22 :");
+ Dump (Local_A22'Address, Arr22'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "Local_A22 : 00 ab 00 13 00 cd 00 35 00 ab 00 13 00 cd 00 35\n" }
+end;
diff --git a/gcc/testsuite/gnat.dg/sso/t13.adb b/gcc/testsuite/gnat.dg/sso/t13.adb
new file mode 100644
index 00000000000..e00371f7520
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/sso/t13.adb
@@ -0,0 +1,56 @@
+-- { dg-do run }
+
+with Init13; use Init13;
+with Ada.Numerics; use Ada.Numerics;
+with Text_IO; use Text_IO;
+with Dump;
+
+procedure T13 is
+
+ Local_R1 : R1;
+ Local_R2 : R2;
+
+begin
+ Local_R1.F := (My_R1.F.R + 1.0, My_R1.F.I + 1.0);
+
+ Put ("Local_R1 :");
+ Dump (Local_R1'Address, R1'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "Local_R1 : ee 87 84 40 db 0f 09 c0\n" }
+
+ Local_R2.F := (My_R2.F.R + 1.0, My_R2.F.I + 1.0);
+
+ Put ("Local_R2 :");
+ Dump (Local_R2'Address, R2'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "Local_R2 : 40 84 87 ee c0 09 0f db\n" }
+
+ Local_R1.F := (Pi, -Pi);
+
+ Put ("Local_R1 :");
+ Dump (Local_R1'Address, R1'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "Local_R1 : db 0f 49 40 db 0f 49 c0\n" }
+
+ Local_R2.F := (Pi, -Pi);
+
+ Put ("Local_R2 :");
+ Dump (Local_R2'Address, R2'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "Local_R2 : 40 49 0f db c0 49 0f db\n" }
+
+ Local_R1.F := (Local_R1.F.R + 1.0, Local_R1.F.I + 1.0);
+
+ Put ("Local_R1 :");
+ Dump (Local_R1'Address, R1'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "Local_R1 : ee 87 84 40 db 0f 09 c0\n" }
+
+ Local_R2.F := (Local_R2.F.R + 1.0, Local_R2.F.I + 1.0);
+
+ Put ("Local_R2 :");
+ Dump (Local_R2'Address, R2'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "Local_R2 : 40 84 87 ee c0 09 0f db\n" }
+
+end;
diff --git a/gcc/testsuite/gnat.dg/sso/t2.adb b/gcc/testsuite/gnat.dg/sso/t2.adb
new file mode 100644
index 00000000000..04ce7752133
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/sso/t2.adb
@@ -0,0 +1,84 @@
+-- { dg-do run }
+
+with Init2; use Init2;
+with Text_IO; use Text_IO;
+with Dump;
+
+procedure T2 is
+
+ Local_R1 : R1;
+ Local_R2 : R2;
+
+begin
+ Local_R1.S1 := My_R1.S1 - 1;
+ Local_R1.I := My_R1.I + 1;
+ Local_R1.S2 := My_R1.S2 - 1;
+ Local_R1.A(1) := My_R1.A(1) mod 16;
+ Local_R1.A(2) := My_R1.A(2) mod 16;
+ Local_R1.A(3) := My_R1.A(3) mod 16;
+ Local_R1.B := not My_R1.B;
+
+ Put ("Local_R1 :");
+ Dump (Local_R1'Address, R1'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "Local_R1 : e5 59 d1 48 b0 a0 c1 03\n" }
+
+ Local_R2.S1 := My_R2.S1 - 1;
+ Local_R2.I := My_R2.I + 1;
+ Local_R2.S2 := My_R2.S2 - 1;
+ Local_R2.A(1) := My_R2.A(1) mod 16;
+ Local_R2.A(2) := My_R2.A(2) mod 16;
+ Local_R2.A(3) := My_R2.A(3) mod 16;
+ Local_R2.B := not My_R2.B;
+
+ Put ("Local_R2 :");
+ Dump (Local_R2'Address, R2'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "Local_R2 : 44 8d 15 9e 40 58 34 1e\n" }
+
+ Local_R1 := (S1 => 2,
+ I => 16#12345678#,
+ S2 => 1,
+ A => (16#AB#, 16#CD#, 16#EF#),
+ B => True);
+ Put ("Local_R1 :");
+ Dump (Local_R1'Address, R1'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "Local_R1 : e2 59 d1 48 b4 aa d9 bb\n" }
+
+ Local_R2 := (S1 => 2,
+ I => 16#12345678#,
+ S2 => 1,
+ A => (16#AB#, 16#CD#, 16#EF#),
+ B => True);
+ Put ("Local_R2 :");
+ Dump (Local_R2'Address, R2'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "Local_R2 : 84 8d 15 9e 15 5b 35 df\n" }
+
+ Local_R1.S1 := Local_R1.S1 - 1;
+ Local_R1.I := Local_R1.I + 1;
+ Local_R1.S2 := Local_R1.S2 - 1;
+ Local_R1.A(1) := Local_R1.A(1) mod 16;
+ Local_R1.A(2) := Local_R1.A(2) mod 16;
+ Local_R1.A(3) := Local_R1.A(3) mod 16;
+ Local_R1.B := not Local_R1.B;
+
+ Put ("Local_R1 :");
+ Dump (Local_R1'Address, R1'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "Local_R1 : e5 59 d1 48 b0 a0 c1 03\n" }
+
+ Local_R2.S1 := Local_R2.S1 - 1;
+ Local_R2.I := Local_R2.I + 1;
+ Local_R2.S2 := Local_R2.S2 - 1;
+ Local_R2.A(1) := Local_R2.A(1) mod 16;
+ Local_R2.A(2) := Local_R2.A(2) mod 16;
+ Local_R2.A(3) := Local_R2.A(3) mod 16;
+ Local_R2.B := not Local_R2.B;
+
+ Put ("Local_R2 :");
+ Dump (Local_R2'Address, R2'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "Local_R2 : 44 8d 15 9e 40 58 34 1e\n" }
+end;
diff --git a/gcc/testsuite/gnat.dg/sso/t3.adb b/gcc/testsuite/gnat.dg/sso/t3.adb
new file mode 100644
index 00000000000..3ecbf6893b2
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/sso/t3.adb
@@ -0,0 +1,84 @@
+-- { dg-do run }
+
+with Init3; use Init3;
+with Text_IO; use Text_IO;
+with Dump;
+
+procedure T3 is
+
+ Local_R1 : R1;
+ Local_R2 : R2;
+
+begin
+ Local_R1.S1 := My_R1.S1 - 1;
+ Local_R1.I := My_R1.I + 1;
+ Local_R1.S2 := My_R1.S2 - 1;
+ Local_R1.N.C1 := My_R1.N.C1 mod 16;
+ Local_R1.N.C2 := My_R1.N.C2 mod 16;
+ Local_R1.N.C3 := My_R1.N.C3 mod 16;
+ Local_R1.B := not My_R1.B;
+
+ Put ("Local_R1 :");
+ Dump (Local_R1'Address, R1'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "Local_R1 : e5 59 d1 48 b0 a0 c1 03\n" }
+
+ Local_R2.S1 := My_R2.S1 - 1;
+ Local_R2.I := My_R2.I + 1;
+ Local_R2.S2 := My_R2.S2 - 1;
+ Local_R2.N.C1 := My_R2.N.C1 mod 16;
+ Local_R2.N.C2 := My_R2.N.C2 mod 16;
+ Local_R2.N.C3 := My_R2.N.C3 mod 16;
+ Local_R2.B := not My_R2.B;
+
+ Put ("Local_R2 :");
+ Dump (Local_R2'Address, R2'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "Local_R2 : 44 8d 15 9e 40 58 34 1e\n" }
+
+ Local_R1 := (S1 => 2,
+ I => 16#12345678#,
+ S2 => 1,
+ N => (16#AB#, 16#CD#, 16#EF#),
+ B => True);
+ Put ("Local_R1 :");
+ Dump (Local_R1'Address, R1'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "Local_R1 : e2 59 d1 48 b4 aa d9 bb\n" }
+
+ Local_R2 := (S1 => 2,
+ I => 16#12345678#,
+ S2 => 1,
+ N => (16#AB#, 16#CD#, 16#EF#),
+ B => True);
+ Put ("Local_R2 :");
+ Dump (Local_R2'Address, R2'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "Local_R2 : 84 8d 15 9e 15 5b 35 df\n" }
+
+ Local_R1.S1 := Local_R1.S1 - 1;
+ Local_R1.I := Local_R1.I + 1;
+ Local_R1.S2 := Local_R1.S2 - 1;
+ Local_R1.N.C1 := Local_R1.N.C1 mod 16;
+ Local_R1.N.C2 := Local_R1.N.C2 mod 16;
+ Local_R1.N.C3 := Local_R1.N.C3 mod 16;
+ Local_R1.B := not Local_R1.B;
+
+ Put ("Local_R1 :");
+ Dump (Local_R1'Address, R1'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "Local_R1 : e5 59 d1 48 b0 a0 c1 03\n" }
+
+ Local_R2.S1 := Local_R2.S1 - 1;
+ Local_R2.I := Local_R2.I + 1;
+ Local_R2.S2 := Local_R2.S2 - 1;
+ Local_R2.N.C1 := Local_R2.N.C1 mod 16;
+ Local_R2.N.C2 := Local_R2.N.C2 mod 16;
+ Local_R2.N.C3 := Local_R2.N.C3 mod 16;
+ Local_R2.B := not Local_R2.B;
+
+ Put ("Local_R2 :");
+ Dump (Local_R2'Address, R2'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "Local_R2 : 44 8d 15 9e 40 58 34 1e\n" }
+end;
diff --git a/gcc/testsuite/gnat.dg/sso/t4.adb b/gcc/testsuite/gnat.dg/sso/t4.adb
new file mode 100644
index 00000000000..ecaee90b28e
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/sso/t4.adb
@@ -0,0 +1,56 @@
+-- { dg-do run }
+
+with Init4; use Init4;
+with Ada.Numerics; use Ada.Numerics;
+with Text_IO; use Text_IO;
+with Dump;
+
+procedure T4 is
+
+ Local_R1 : R1;
+ Local_R2 : R2;
+
+begin
+ Local_R1.F := My_R1.F + 1.0;
+
+ Put ("Local_R1 :");
+ Dump (Local_R1'Address, R1'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "Local_R1 : ee 87 84 40\n" }
+
+ Local_R2.F := My_R2.F + 1.0;
+
+ Put ("Local_R2 :");
+ Dump (Local_R2'Address, R2'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "Local_R2 : 40 84 87 ee\n" }
+
+ Local_R1.F := Pi;
+
+ Put ("Local_R1 :");
+ Dump (Local_R1'Address, R1'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "Local_R1 : db 0f 49 40\n" }
+
+ Local_R2.F := Pi;
+
+ Put ("Local_R2 :");
+ Dump (Local_R2'Address, R2'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "Local_R2 : 40 49 0f db\n" }
+
+ Local_R1.F := Local_R1.F + 1.0;
+
+ Put ("Local_R1 :");
+ Dump (Local_R1'Address, R1'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "Local_R1 : ee 87 84 40\n" }
+
+ Local_R2.F := Local_R2.F + 1.0;
+
+ Put ("Local_R2 :");
+ Dump (Local_R2'Address, R2'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "Local_R2 : 40 84 87 ee\n" }
+
+end;
diff --git a/gcc/testsuite/gnat.dg/sso/t5.adb b/gcc/testsuite/gnat.dg/sso/t5.adb
new file mode 100644
index 00000000000..c737bf3a50a
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/sso/t5.adb
@@ -0,0 +1,67 @@
+-- { dg-do run }
+
+with Init5; use Init5;
+with Text_IO; use Text_IO;
+with Dump;
+
+procedure T5 is
+
+ Local_R1 : R1;
+ Local_R2 : R2;
+
+begin
+ Local_R1.I := My_R1.I + 1;
+ Local_R1.A(1) := My_R1.A(1) + 1;
+ Local_R1.A(2) := My_R1.A(2) + 1;
+ Local_R1.A(3) := My_R1.A(3) + 1;
+
+ Put ("Local_R1 :");
+ Dump (Local_R1'Address, R1'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "Local_R1 : 79 56 34 12 13 00 ab 00 35 00 cd 00 57 00 ef 00\n" }
+
+ Local_R2.I := My_R2.I + 1;
+ Local_R2.A(1) := My_R2.A(1) + 1;
+ Local_R2.A(2) := My_R2.A(2) + 1;
+ Local_R2.A(3) := My_R2.A(3) + 1;
+
+ Put ("Local_R2 :");
+ Dump (Local_R2'Address, R2'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "Local_R2 : 12 34 56 79 00 ab 00 13 00 cd 00 35 00 ef 00 57\n" }
+
+ Local_R1 := (I => 16#12345678#,
+ A => (16#AB0012#, 16#CD0034#, 16#EF0056#));
+ Put ("Local_R1 :");
+ Dump (Local_R1'Address, R1'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "Local_R1 : 78 56 34 12 12 00 ab 00 34 00 cd 00 56 00 ef 00\n" }
+
+ Local_R2 := (I => 16#12345678#,
+ A => (16#AB0012#, 16#CD0034#, 16#EF0056#));
+ Put ("Local_R2 :");
+ Dump (Local_R2'Address, R2'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "Local_R2 : 12 34 56 78 00 ab 00 12 00 cd 00 34 00 ef 00 56\n" }
+
+ Local_R1.I := Local_R1.I + 1;
+ Local_R1.A(1) := Local_R1.A(1) + 1;
+ Local_R1.A(2) := Local_R1.A(2) + 1;
+ Local_R1.A(3) := Local_R1.A(3) + 1;
+
+ Put ("Local_R1 :");
+ Dump (Local_R1'Address, R1'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "Local_R1 : 79 56 34 12 13 00 ab 00 35 00 cd 00 57 00 ef 00\n" }
+
+ Local_R2.I := Local_R2.I + 1;
+ Local_R2.A(1) := Local_R2.A(1) + 1;
+ Local_R2.A(2) := Local_R2.A(2) + 1;
+ Local_R2.A(3) := Local_R2.A(3) + 1;
+
+ Put ("Local_R2 :");
+ Dump (Local_R2'Address, R2'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "Local_R2 : 12 34 56 79 00 ab 00 13 00 cd 00 35 00 ef 00 57\n" }
+
+end;
diff --git a/gcc/testsuite/gnat.dg/sso/t6.adb b/gcc/testsuite/gnat.dg/sso/t6.adb
new file mode 100644
index 00000000000..49661cb1215
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/sso/t6.adb
@@ -0,0 +1,67 @@
+-- { dg-do run }
+
+with Init6; use Init6;
+with Text_IO; use Text_IO;
+with Dump;
+
+procedure T6 is
+
+ Local_R1 : R1;
+ Local_R2 : R2;
+
+begin
+ Local_R1.I := My_R1.I + 1;
+ Local_R1.A(1) := My_R1.A(1) + 1;
+ Local_R1.A(2) := My_R1.A(2) + 1;
+ Local_R1.A(3) := My_R1.A(3) + 1;
+
+ Put ("Local_R1 :");
+ Dump (Local_R1'Address, R1'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "Local_R1 : 79 56 34 12 00 ab 00 13 00 cd 00 35 00 ef 00 57\n" }
+
+ Local_R2.I := My_R2.I + 1;
+ Local_R2.A(1) := My_R2.A(1) + 1;
+ Local_R2.A(2) := My_R2.A(2) + 1;
+ Local_R2.A(3) := My_R2.A(3) + 1;
+
+ Put ("Local_R2 :");
+ Dump (Local_R2'Address, R2'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "Local_R2 : 12 34 56 79 13 00 ab 00 35 00 cd 00 57 00 ef 00\n" }
+
+ Local_R1 := (I => 16#12345678#,
+ A => (16#AB0012#, 16#CD0034#, 16#EF0056#));
+ Put ("Local_R1 :");
+ Dump (Local_R1'Address, R1'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "Local_R1 : 78 56 34 12 00 ab 00 12 00 cd 00 34 00 ef 00 56\n" }
+
+ Local_R2 := (I => 16#12345678#,
+ A => (16#AB0012#, 16#CD0034#, 16#EF0056#));
+ Put ("Local_R2 :");
+ Dump (Local_R2'Address, R2'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "Local_R2 : 12 34 56 78 12 00 ab 00 34 00 cd 00 56 00 ef 00\n" }
+
+ Local_R1.I := Local_R1.I + 1;
+ Local_R1.A(1) := Local_R1.A(1) + 1;
+ Local_R1.A(2) := Local_R1.A(2) + 1;
+ Local_R1.A(3) := Local_R1.A(3) + 1;
+
+ Put ("Local_R1 :");
+ Dump (Local_R1'Address, R1'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "Local_R1 : 79 56 34 12 00 ab 00 13 00 cd 00 35 00 ef 00 57\n" }
+
+ Local_R2.I := Local_R2.I + 1;
+ Local_R2.A(1) := Local_R2.A(1) + 1;
+ Local_R2.A(2) := Local_R2.A(2) + 1;
+ Local_R2.A(3) := Local_R2.A(3) + 1;
+
+ Put ("Local_R2 :");
+ Dump (Local_R2'Address, R2'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "Local_R2 : 12 34 56 79 13 00 ab 00 35 00 cd 00 57 00 ef 00\n" }
+
+end;
diff --git a/gcc/testsuite/gnat.dg/sso/t7.adb b/gcc/testsuite/gnat.dg/sso/t7.adb
new file mode 100644
index 00000000000..da51bd535b4
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/sso/t7.adb
@@ -0,0 +1,68 @@
+-- { dg-do run }
+
+with Init7; use Init7;
+with Text_IO; use Text_IO;
+with Dump;
+
+procedure T7 is
+ Verbose : constant Boolean := False;
+
+ Local_R1 : R1;
+ Local_R2 : R2;
+
+begin
+ Local_R1.I := My_R1.I + 1;
+ Local_R1.N.C1 := My_R1.N.C1 + 1;
+ Local_R1.N.C2 := My_R1.N.C2 + 1;
+ Local_R1.N.C3 := My_R1.N.C3 + 1;
+
+ Put ("Local_R1 :");
+ Dump (Local_R1'Address, R1'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "Local_R1 : 79 56 34 12 13 00 ab 00 35 00 cd 00 57 00 ef 00\n" }
+
+ Local_R2.I := My_R2.I + 1;
+ Local_R2.N.C1 := My_R2.N.C1 + 1;
+ Local_R2.N.C2 := My_R2.N.C2 + 1;
+ Local_R2.N.C3 := My_R2.N.C3 + 1;
+
+ Put ("Local_R2 :");
+ Dump (Local_R2'Address, R2'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "Local_R2 : 12 34 56 79 00 ab 00 13 00 cd 00 35 00 ef 00 57\n" }
+--
+ Local_R1 := (I => 16#12345678#,
+ N => (16#AB0012#, 16#CD0034#, 16#EF0056#));
+ Put ("Local_R1 :");
+ Dump (Local_R1'Address, R1'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "Local_R1 : 78 56 34 12 12 00 ab 00 34 00 cd 00 56 00 ef 00\n" }
+
+ Local_R2 := (I => 16#12345678#,
+ N => (16#AB0012#, 16#CD0034#, 16#EF0056#));
+ Put ("Local_R2 :");
+ Dump (Local_R2'Address, R2'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "Local_R2 : 12 34 56 78 00 ab 00 12 00 cd 00 34 00 ef 00 56\n" }
+
+ Local_R1.I := Local_R1.I + 1;
+ Local_R1.N.C1 := Local_R1.N.C1 + 1;
+ Local_R1.N.C2 := Local_R1.N.C2 + 1;
+ Local_R1.N.C3 := Local_R1.N.C3 + 1;
+
+ Put ("Local_R1 :");
+ Dump (Local_R1'Address, R1'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "Local_R1 : 79 56 34 12 13 00 ab 00 35 00 cd 00 57 00 ef 00\n" }
+
+ Local_R2.I := Local_R2.I + 1;
+ Local_R2.N.C1 := Local_R2.N.C1 + 1;
+ Local_R2.N.C2 := Local_R2.N.C2 + 1;
+ Local_R2.N.C3 := Local_R2.N.C3 + 1;
+
+ Put ("Local_R2 :");
+ Dump (Local_R2'Address, R2'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "Local_R2 : 12 34 56 79 00 ab 00 13 00 cd 00 35 00 ef 00 57\n" }
+
+end;
diff --git a/gcc/testsuite/gnat.dg/sso/t8.adb b/gcc/testsuite/gnat.dg/sso/t8.adb
new file mode 100644
index 00000000000..a9976a6e69e
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/sso/t8.adb
@@ -0,0 +1,68 @@
+-- { dg-do run }
+
+with Init8; use Init8;
+with Text_IO; use Text_IO;
+with Dump;
+
+procedure T8 is
+ Verbose : constant Boolean := False;
+
+ Local_R1 : R1;
+ Local_R2 : R2;
+
+begin
+ Local_R1.I := My_R1.I + 1;
+ Local_R1.N.C1 := My_R1.N.C1 + 1;
+ Local_R1.N.C2 := My_R1.N.C2 + 1;
+ Local_R1.N.C3 := My_R1.N.C3 + 1;
+
+ Put ("Local_R1 :");
+ Dump (Local_R1'Address, R1'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "Local_R1 : 79 56 34 12 00 ab 00 13 00 cd 00 35 00 ef 00 57\n" }
+
+ Local_R2.I := My_R2.I + 1;
+ Local_R2.N.C1 := My_R2.N.C1 + 1;
+ Local_R2.N.C2 := My_R2.N.C2 + 1;
+ Local_R2.N.C3 := My_R2.N.C3 + 1;
+
+ Put ("Local_R2 :");
+ Dump (Local_R2'Address, R2'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "Local_R2 : 12 34 56 79 13 00 ab 00 35 00 cd 00 57 00 ef 00\n" }
+
+ Local_R1 := (I => 16#12345678#,
+ N => (16#AB0012#, 16#CD0034#, 16#EF0056#));
+ Put ("Local_R1 :");
+ Dump (Local_R1'Address, R1'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "Local_R1 : 78 56 34 12 00 ab 00 12 00 cd 00 34 00 ef 00 56\n" }
+
+ Local_R2 := (I => 16#12345678#,
+ N => (16#AB0012#, 16#CD0034#, 16#EF0056#));
+ Put ("Local_R2 :");
+ Dump (Local_R2'Address, R2'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "Local_R2 : 12 34 56 78 12 00 ab 00 34 00 cd 00 56 00 ef 00\n" }
+
+ Local_R1.I := Local_R1.I + 1;
+ Local_R1.N.C1 := Local_R1.N.C1 + 1;
+ Local_R1.N.C2 := Local_R1.N.C2 + 1;
+ Local_R1.N.C3 := Local_R1.N.C3 + 1;
+
+ Put ("Local_R1 :");
+ Dump (Local_R1'Address, R1'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "Local_R1 : 79 56 34 12 00 ab 00 13 00 cd 00 35 00 ef 00 57\n" }
+
+ Local_R2.I := Local_R2.I + 1;
+ Local_R2.N.C1 := Local_R2.N.C1 + 1;
+ Local_R2.N.C2 := Local_R2.N.C2 + 1;
+ Local_R2.N.C3 := Local_R2.N.C3 + 1;
+
+ Put ("Local_R2 :");
+ Dump (Local_R2'Address, R2'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "Local_R2 : 12 34 56 79 13 00 ab 00 35 00 cd 00 57 00 ef 00\n" }
+
+end;
diff --git a/gcc/testsuite/gnat.dg/sso/t9.adb b/gcc/testsuite/gnat.dg/sso/t9.adb
new file mode 100644
index 00000000000..e38cabc21d8
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/sso/t9.adb
@@ -0,0 +1,56 @@
+-- { dg-do run }
+
+with Init9; use Init9;
+with Ada.Numerics; use Ada.Numerics;
+with Text_IO; use Text_IO;
+with Dump;
+
+procedure T9 is
+
+ Local_R1 : R1;
+ Local_R2 : R2;
+
+begin
+ Local_R1.F := My_R1.F + 1.0;
+
+ Put ("Local_R1 :");
+ Dump (Local_R1'Address, R1'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "Local_R1 : 8c 16 22 aa fd 90 10 40\n" }
+
+ Local_R2.F := My_R2.F + 1.0;
+
+ Put ("Local_R2 :");
+ Dump (Local_R2'Address, R2'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "Local_R2 : 40 10 90 fd aa 22 16 8c\n" }
+
+ Local_R1.F := Pi;
+
+ Put ("Local_R1 :");
+ Dump (Local_R1'Address, R1'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "Local_R1 : 18 2d 44 54 fb 21 09 40\n" }
+
+ Local_R2.F := Pi;
+
+ Put ("Local_R2 :");
+ Dump (Local_R2'Address, R2'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "Local_R2 : 40 09 21 fb 54 44 2d 18\n" }
+
+ Local_R1.F := Local_R1.F + 1.0;
+
+ Put ("Local_R1 :");
+ Dump (Local_R1'Address, R1'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "Local_R1 : 8c 16 22 aa fd 90 10 40\n" }
+
+ Local_R2.F := Local_R2.F + 1.0;
+
+ Put ("Local_R2 :");
+ Dump (Local_R2'Address, R2'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "Local_R2 : 40 10 90 fd aa 22 16 8c\n" }
+
+end;
diff --git a/gcc/testsuite/gnat.dg/sso/u11.adb b/gcc/testsuite/gnat.dg/sso/u11.adb
new file mode 100644
index 00000000000..9f7c770951d
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/sso/u11.adb
@@ -0,0 +1,44 @@
+-- { dg-do run }
+
+with Init11; use Init11;
+with Text_IO; use Text_IO;
+with Dump;
+
+procedure U11 is
+
+ Local_R1 : R1;
+ Local_R2 : R2;
+ C1 : My_Integer;
+ C2 : My_Integer;
+
+begin
+ Local_R1 := (I => 1, A => (16#AB0012#, 16#CD0034#, 16#EF0056#));
+ Put ("Local_R1 :");
+ Dump (Local_R1'Address, R1'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "Local_R1 : 01 00 00 00 12 00 ab 00 34 00 cd 00 56 00 ef 00\n" }
+
+ Local_R2 := (I => 1, A => (16#AB0012#, 16#CD0034#, 16#EF0056#));
+ Put ("Local_R2 :");
+ Dump (Local_R2'Address, R2'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "Local_R2 : 00 00 00 01 00 ab 00 12 00 cd 00 34 00 ef 00 56\n" }
+
+ C1 := Local_R1.A (Integer(Local_R1.I));
+ Put_Line ("C1 :" & C1'Img);
+ -- { dg-output "C1 : 11206674\n" }
+
+ Local_R1.I := Local_R1.I + 1;
+ C1 := Local_R1.A (Integer(Local_R1.I));
+ Put_Line ("C1 :" & C1'Img);
+ -- { dg-output "C1 : 13434932\n" }
+
+ C2 := Local_R2.A (Integer(Local_R2.I));
+ Put_Line ("C2 :" & C2'Img);
+ -- { dg-output "C2 : 11206674\n" }
+
+ Local_R2.I := Local_R2.I + 1;
+ C2 := Local_R2.A (Integer(Local_R2.I));
+ Put_Line ("C2 :" & C2'Img);
+ -- { dg-output "C2 : 13434932\n" }
+end;
diff --git a/gcc/testsuite/gnat.dg/sso/u5.adb b/gcc/testsuite/gnat.dg/sso/u5.adb
new file mode 100644
index 00000000000..5d9d4ccbceb
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/sso/u5.adb
@@ -0,0 +1,44 @@
+-- { dg-do run }
+
+with Init5; use Init5;
+with Text_IO; use Text_IO;
+with Dump;
+
+procedure U5 is
+
+ Local_R1 : R1;
+ Local_R2 : R2;
+ C1 : Integer;
+ C2 : Integer;
+
+begin
+ Local_R1 := (I => 1, A => (16#AB0012#, 16#CD0034#, 16#EF0056#));
+ Put ("Local_R1 :");
+ Dump (Local_R1'Address, R1'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "Local_R1 : 01 00 00 00 12 00 ab 00 34 00 cd 00 56 00 ef 00\n" }
+
+ Local_R2 := (I => 1, A => (16#AB0012#, 16#CD0034#, 16#EF0056#));
+ Put ("Local_R2 :");
+ Dump (Local_R2'Address, R2'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "Local_R2 : 00 00 00 01 00 ab 00 12 00 cd 00 34 00 ef 00 56\n" }
+
+ C1 := Local_R1.A (Local_R1.I);
+ Put_Line ("C1 :" & C1'Img);
+ -- { dg-output "C1 : 11206674\n" }
+
+ Local_R1.I := Local_R1.I + 1;
+ C1 := Local_R1.A (Local_R1.I);
+ Put_Line ("C1 :" & C1'Img);
+ -- { dg-output "C1 : 13434932\n" }
+
+ C2 := Local_R2.A (Local_R2.I);
+ Put_Line ("C2 :" & C2'Img);
+ -- { dg-output "C2 : 11206674\n" }
+
+ Local_R2.I := Local_R2.I + 1;
+ C2 := Local_R2.A (Local_R2.I);
+ Put_Line ("C2 :" & C2'Img);
+ -- { dg-output "C2 : 13434932\n" }
+end;
diff --git a/gcc/testsuite/gnat.dg/sso/u6.adb b/gcc/testsuite/gnat.dg/sso/u6.adb
new file mode 100644
index 00000000000..ca8a0d4ff5f
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/sso/u6.adb
@@ -0,0 +1,44 @@
+-- { dg-do run }
+
+with Init6; use Init6;
+with Text_IO; use Text_IO;
+with Dump;
+
+procedure U6 is
+
+ Local_R1 : R1;
+ Local_R2 : R2;
+ C1 : Integer;
+ C2 : Integer;
+
+begin
+ Local_R1 := (I => 1, A => (16#AB0012#, 16#CD0034#, 16#EF0056#));
+ Put ("Local_R1 :");
+ Dump (Local_R1'Address, R1'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "Local_R1 : 01 00 00 00 00 ab 00 12 00 cd 00 34 00 ef 00 56\n" }
+
+ Local_R2 := (I => 1, A => (16#AB0012#, 16#CD0034#, 16#EF0056#));
+ Put ("Local_R2 :");
+ Dump (Local_R2'Address, R2'Max_Size_In_Storage_Elements);
+ New_Line;
+ -- { dg-output "Local_R2 : 00 00 00 01 12 00 ab 00 34 00 cd 00 56 00 ef 00\n" }
+
+ C1 := Local_R1.A (Local_R1.I);
+ Put_Line ("C1 :" & C1'Img);
+ -- { dg-output "C1 : 11206674\n" }
+
+ Local_R1.I := Local_R1.I + 1;
+ C1 := Local_R1.A (Local_R1.I);
+ Put_Line ("C1 :" & C1'Img);
+ -- { dg-output "C1 : 13434932\n" }
+
+ C2 := Local_R2.A (Local_R2.I);
+ Put_Line ("C2 :" & C2'Img);
+ -- { dg-output "C2 : 11206674\n" }
+
+ Local_R2.I := Local_R2.I + 1;
+ C2 := Local_R2.A (Local_R2.I);
+ Put_Line ("C2 :" & C2'Img);
+ -- { dg-output "C2 : 13434932\n" }
+end;
diff --git a/gcc/testsuite/gnat.dg/sso1.adb b/gcc/testsuite/gnat.dg/sso1.adb
new file mode 100644
index 00000000000..1b2cd5f1707
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/sso1.adb
@@ -0,0 +1,77 @@
+-- { dg-do run }
+
+with System;
+with Ada.Unchecked_Conversion;
+with Ada.Streams; use Ada.Streams;
+with Ada.Text_IO;
+
+procedure SSO1 is
+
+ type Unsigned_Integer_4 is mod 2 ** 32;
+ for Unsigned_Integer_4'Size use 32;
+
+ Default_Bit_Order_Pos : constant Natural := System.Bit_Order'Pos (System.Default_Bit_Order);
+
+ Opposite_Bit_Order_Pos : constant Natural := 1 - Default_Bit_Order_Pos;
+
+ Opposite_Bit_Order : constant System.Bit_Order := System.Bit_Order'Val (Opposite_Bit_Order_Pos);
+
+ type Rec is
+ record
+ X, Y : Unsigned_Integer_4;
+ end record;
+ for Rec'Bit_Order use System.Default_Bit_Order;
+ for Rec'Scalar_Storage_Order use System.Default_Bit_Order;
+
+ for Rec use
+ record
+ X at 0 * 4 range 0 .. 31;
+ Y at 1 * 4 range 0 .. 31;
+ end record;
+
+ type Nested_Rec is
+ record
+ I : Unsigned_Integer_4;
+ R : Rec;
+ J : Unsigned_Integer_4;
+ end record;
+ for Nested_Rec use
+ record
+ I at 0 * 4 range 0 .. 31;
+ R at 1 * 4 range 0 .. 63;
+ J at 3 * 4 range 0 .. 31;
+ end record;
+
+ for Nested_Rec'Bit_Order use Opposite_Bit_Order;
+ for Nested_Rec'Scalar_Storage_Order use Opposite_Bit_Order;
+
+ Nr : Nested_Rec
+ := (I => 1,
+ R => (X => 1,
+ Y => 1),
+ J => 1);
+
+ subtype Nested_Rec_As_Stream is Ada.Streams.Stream_Element_Array (1 ..16);
+
+ function To_Stream is
+ new Ada.Unchecked_Conversion (Nested_Rec, Nested_Rec_As_Stream);
+
+ Nr_Stream : constant Nested_Rec_As_Stream := To_Stream (Nr);
+
+ Expected : constant array (System.Bit_Order) of Nested_Rec_As_Stream :=
+ (System.Low_Order_First =>
+ (0, 0, 0, 1,
+ 1, 0, 0, 0,
+ 1, 0, 0, 0,
+ 0, 0, 0, 1),
+ System.High_Order_First =>
+ (1, 0, 0, 0,
+ 0, 0, 0, 1,
+ 0, 0, 0, 1,
+ 1, 0, 0, 0));
+
+begin
+ if Nr_Stream /= Expected (System.Default_Bit_Order) then
+ raise Program_Error;
+ end if;
+end;
diff --git a/gcc/testsuite/gnat.dg/sso2.adb b/gcc/testsuite/gnat.dg/sso2.adb
new file mode 100644
index 00000000000..dc5b8cc5653
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/sso2.adb
@@ -0,0 +1,14 @@
+-- { dg-do compile }
+
+with Ada.Unchecked_Conversion;
+
+package body SSO2 is
+
+ function Conv is new Ada.Unchecked_Conversion (Arr1, Arr2);
+
+ procedure Proc (A1 : Arr1; A2 : out Arr2) is
+ begin
+ A2 := Conv (A1);
+ end;
+
+end SSO2;
diff --git a/gcc/testsuite/gnat.dg/sso2.ads b/gcc/testsuite/gnat.dg/sso2.ads
new file mode 100644
index 00000000000..36d37bc92ae
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/sso2.ads
@@ -0,0 +1,13 @@
+with System;
+
+package SSO2 is
+
+ type Arr1 is array (1 .. 4) of Character;
+ for Arr1'Scalar_Storage_Order use System.High_Order_First;
+
+ type Arr2 is array (1 .. 4) of Character;
+ for Arr2'Scalar_Storage_Order use System.Low_Order_First;
+
+ procedure Proc (A1 : Arr1; A2 : out Arr2);
+
+end SSO2;
diff --git a/gcc/testsuite/gnat.dg/sso3.adb b/gcc/testsuite/gnat.dg/sso3.adb
new file mode 100644
index 00000000000..d4b65697a1b
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/sso3.adb
@@ -0,0 +1,52 @@
+-- { dg-do run }
+
+with System; use System;
+
+procedure SSO3 is
+ Rev_SSO : constant Bit_Order
+ := Bit_Order'Val (1 - Bit_Order'Pos (Default_Bit_Order));
+
+ type R (D : Integer) is record
+ Common : Integer;
+ case D is
+ when 0 =>
+ V1 : Integer;
+ when others =>
+ V2 : Integer;
+ end case;
+ end record;
+
+ for R use record
+ D at 0 range 0 .. 31;
+ V1 at 4 range 0 .. 31;
+ V2 at 4 range 0 .. 31;
+ Common at 8 range 0 .. 31;
+ end record;
+ for R'Scalar_Storage_Order use Rev_SSO;
+ for R'Bit_Order use Rev_SSO;
+
+ procedure Check (Common, V : Integer; X : R) is
+ begin
+ if Common /= X.Common then
+ raise Program_Error;
+ end if;
+
+ case X.D is
+ when 0 =>
+ if V /= X.V1 then
+ raise Program_Error;
+ end if;
+ when others =>
+ if V /= X.V2 then
+ raise Program_Error;
+ end if;
+ end case;
+ end Check;
+
+ X0 : R := (D => 0, Common => 1111, V1 => 1234);
+ X1 : R := (D => 31337, Common => 2222, V2 => 5678);
+
+begin
+ Check (1111, 1234, X0);
+ Check (2222, 5678, X1);
+end;
diff --git a/gcc/testsuite/gnat.dg/sso4.adb b/gcc/testsuite/gnat.dg/sso4.adb
new file mode 100644
index 00000000000..6a409e92a5f
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/sso4.adb
@@ -0,0 +1,55 @@
+-- { dg-do run }
+
+with System;
+
+procedure SSO4 is
+
+ type Short_Int is mod 2**16;
+
+ type Rec1 is record
+ F1 : Short_Int;
+ F2 : Short_Int;
+ end record;
+ for Rec1 use record
+ F1 at 0 range 0 .. 15;
+ F2 at 0 range 16 .. 31;
+ end record;
+
+ for Rec1'Bit_Order use System.High_Order_First;
+ for Rec1'Scalar_Storage_Order use System.High_Order_First;
+
+ type Rec2 is record
+ I1 : Integer;
+ R1 : Rec1;
+ end record;
+ for Rec2 use record
+ I1 at 0 range 0 .. 31;
+ R1 at 4 range 0 .. 31;
+ end record;
+ for Rec2'Bit_Order use System.High_Order_First;
+ for Rec2'Scalar_Storage_Order use System.High_Order_First;
+
+ type Rec3 is record
+ Data : Rec1;
+ end record;
+ for Rec3 use record
+ Data at 0 range 0 .. 31;
+ end record;
+ for Rec3'Bit_Order use System.High_Order_First;
+ for Rec3'Scalar_Storage_Order use System.High_Order_First;
+
+ procedure Copy (Message : in Rec3) is
+ Local : Rec2;
+ begin
+ Local := (I1 => 1, R1 => Message.Data);
+ if Local.R1 /= Message.Data then
+ raise Program_Error;
+ end if;
+ end;
+
+ Message : Rec3;
+
+begin
+ Message := (Data => (2, 3));
+ Copy(Message);
+end;
diff --git a/gcc/testsuite/gnat.dg/sso5.adb b/gcc/testsuite/gnat.dg/sso5.adb
new file mode 100644
index 00000000000..b755846dfb0
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/sso5.adb
@@ -0,0 +1,52 @@
+-- { dg-do run }
+
+with System;
+
+procedure SSO5 is
+
+ type Short_Int is mod 2**16;
+
+ type Rec1 is record
+ F1 : Short_Int;
+ F2 : Short_Int;
+ end record;
+ for Rec1 use record
+ F1 at 0 range 0 .. 15;
+ F2 at 0 range 16 .. 31;
+ end record;
+ for Rec1'Bit_Order use System.High_Order_First;
+ for Rec1'Scalar_Storage_Order use System.High_Order_First;
+
+ type Rec2 is record
+ R1 : Rec1;
+ end record;
+ for Rec2 use record
+ R1 at 0 range 1 .. 32;
+ end record;
+ for Rec2'Bit_Order use System.High_Order_First;
+ for Rec2'Scalar_Storage_Order use System.High_Order_First;
+
+ type Rec3 is record
+ Data : Rec1;
+ end record;
+ for Rec3 use record
+ Data at 0 range 0 .. 31;
+ end record;
+ for Rec3'Bit_Order use System.High_Order_First;
+ for Rec3'Scalar_Storage_Order use System.High_Order_First;
+
+ procedure Copy (Message : in Rec3) is
+ Local : Rec2;
+ begin
+ Local := (R1 => Message.Data);
+ if Local.R1 /= Message.Data then
+ raise Program_Error;
+ end if;
+ end;
+
+ Message : Rec3;
+
+begin
+ Message := (Data => (2, 3));
+ Copy(Message);
+end;
diff --git a/gcc/testsuite/gnat.dg/sso6.adb b/gcc/testsuite/gnat.dg/sso6.adb
new file mode 100644
index 00000000000..6d351a43ffd
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/sso6.adb
@@ -0,0 +1,54 @@
+-- { dg-do run }
+
+with System;
+
+procedure SSO6 is
+
+ type Short_Int is mod 2**16;
+
+ type Rec1 is record
+ F1 : Short_Int;
+ F2 : Short_Int;
+ end record;
+ for Rec1 use record
+ F1 at 0 range 0 .. 15;
+ F2 at 0 range 16 .. 31;
+ end record;
+ for Rec1'Bit_Order use System.High_Order_First;
+ for Rec1'Scalar_Storage_Order use System.High_Order_First;
+
+ type Rec2 is record
+ I1 : Integer;
+ R1 : Rec1;
+ end record;
+ for Rec2 use record
+ I1 at 0 range 0 .. 31;
+ R1 at 4 range 0 .. 31;
+ end record;
+ for Rec2'Bit_Order use System.High_Order_First;
+ for Rec2'Scalar_Storage_Order use System.High_Order_First;
+
+ type Rec3 is record
+ Data : Rec1;
+ end record;
+ for Rec3 use record
+ Data at 0 range 1 .. 32;
+ end record;
+ for Rec3'Bit_Order use System.High_Order_First;
+ for Rec3'Scalar_Storage_Order use System.High_Order_First;
+
+ procedure Copy (Message : in Rec3) is
+ Local : Rec2;
+ begin
+ Local := (I1 => 1, R1 => Message.Data);
+ if Local.R1 /= Message.Data then
+ raise Program_Error;
+ end if;
+ end;
+
+ Message : Rec3;
+
+begin
+ Message := (Data => (2, 3));
+ Copy(Message);
+end;
diff --git a/gcc/testsuite/gnat.dg/sso7.adb b/gcc/testsuite/gnat.dg/sso7.adb
new file mode 100644
index 00000000000..114373deeca
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/sso7.adb
@@ -0,0 +1,52 @@
+-- { dg-do run }
+
+with System;
+
+procedure SSO7 is
+
+ type Short_Int is mod 2**16;
+
+ type Rec1 is record
+ F1 : Short_Int;
+ F2 : Short_Int;
+ end record;
+ for Rec1 use record
+ F1 at 0 range 0 .. 15;
+ F2 at 0 range 16 .. 31;
+ end record;
+ for Rec1'Bit_Order use System.High_Order_First;
+ for Rec1'Scalar_Storage_Order use System.High_Order_First;
+
+ type Rec2 is record
+ R1 : Rec1;
+ end record;
+ for Rec2 use record
+ R1 at 0 range 0 .. 31;
+ end record;
+ for Rec2'Bit_Order use System.High_Order_First;
+ for Rec2'Scalar_Storage_Order use System.High_Order_First;
+
+ type Rec3 is record
+ Data : Rec1;
+ end record;
+ for Rec3 use record
+ Data at 0 range 1 .. 32;
+ end record;
+ for Rec3'Bit_Order use System.High_Order_First;
+ for Rec3'Scalar_Storage_Order use System.High_Order_First;
+
+ procedure Copy (Message : in Rec3) is
+ Local : Rec2;
+ begin
+ Local := (R1 => Message.Data);
+ if Local.R1 /= Message.Data then
+ raise Program_Error;
+ end if;
+ end;
+
+ Message : Rec3;
+
+begin
+ Message := (Data => (2, 3));
+ Copy(Message);
+end;
diff --git a/gcc/testsuite/lib/gcc-dg.exp b/gcc/testsuite/lib/gcc-dg.exp
index 7c1ab85f32e..8cc1d87d649 100644
--- a/gcc/testsuite/lib/gcc-dg.exp
+++ b/gcc/testsuite/lib/gcc-dg.exp
@@ -29,6 +29,7 @@ load_lib libgloss.exp
load_lib target-libpath.exp
load_lib torture-options.exp
load_lib fortran-modules.exp
+load_lib multiline.exp
# We set LC_ALL and LANG to C so that we get the same error messages as expected.
setenv LC_ALL C
diff --git a/gcc/trans-mem.c b/gcc/trans-mem.c
index 45bc75967e5..4583bd50fdd 100644
--- a/gcc/trans-mem.c
+++ b/gcc/trans-mem.c
@@ -266,6 +266,9 @@ is_tm_safe (const_tree x)
static bool
is_tm_pure_call (gimple *call)
{
+ if (gimple_call_internal_p (call))
+ return (gimple_call_flags (call) & (ECF_CONST | ECF_TM_PURE)) != 0;
+
tree fn = gimple_call_fn (call);
if (TREE_CODE (fn) == ADDR_EXPR)
diff --git a/gcc/tree-affine.c b/gcc/tree-affine.c
index 97fb13bb886..68d056cf1fc 100644
--- a/gcc/tree-affine.c
+++ b/gcc/tree-affine.c
@@ -260,7 +260,7 @@ tree_to_aff_combination (tree expr, tree type, aff_tree *comb)
tree cst, core, toffset;
HOST_WIDE_INT bitpos, bitsize;
machine_mode mode;
- int unsignedp, volatilep;
+ int unsignedp, reversep, volatilep;
STRIP_NOPS (expr);
@@ -317,8 +317,8 @@ tree_to_aff_combination (tree expr, tree type, aff_tree *comb)
return;
}
core = get_inner_reference (TREE_OPERAND (expr, 0), &bitsize, &bitpos,
- &toffset, &mode, &unsignedp, &volatilep,
- false);
+ &toffset, &mode, &unsignedp, &reversep,
+ &volatilep, false);
if (bitpos % BITS_PER_UNIT != 0)
break;
aff_combination_const (comb, type, bitpos / BITS_PER_UNIT);
@@ -885,10 +885,10 @@ get_inner_reference_aff (tree ref, aff_tree *addr, widest_int *size)
HOST_WIDE_INT bitsize, bitpos;
tree toff;
machine_mode mode;
- int uns, vol;
+ int uns, rev, vol;
aff_tree tmp;
tree base = get_inner_reference (ref, &bitsize, &bitpos, &toff, &mode,
- &uns, &vol, false);
+ &uns, &rev, &vol, false);
tree base_addr = build_fold_addr_expr (base);
/* ADDR = &BASE + TOFF + BITPOS / BITS_PER_UNIT. */
diff --git a/gcc/tree-call-cdce.c b/gcc/tree-call-cdce.c
index ffc1c4ecc4f..a5f38ce1331 100644
--- a/gcc/tree-call-cdce.c
+++ b/gcc/tree-call-cdce.c
@@ -731,6 +731,32 @@ shrink_wrap_one_built_in_call (gcall *bi_call)
if (nconds == 0)
return false;
+ /* 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)
+ |
+ 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]
+
+ We punt for the more complex case case of [join] being old and
+ simply free the dominance info. We also punt on postdominators,
+ which aren't expected to be available at this point anyway. */
bi_call_bb = gimple_bb (bi_call);
/* Now find the join target bb -- split bi_call_bb if needed. */
@@ -741,6 +767,7 @@ shrink_wrap_one_built_in_call (gcall *bi_call)
join_tgt_in_edge_from_call = find_fallthru_edge (bi_call_bb->succs);
if (join_tgt_in_edge_from_call == NULL)
return false;
+ free_dominance_info (CDI_DOMINATORS);
}
else
join_tgt_in_edge_from_call = split_block (bi_call_bb, bi_call);
@@ -820,6 +847,15 @@ shrink_wrap_one_built_in_call (gcall *bi_call)
guard_bb_in_edge->count = guard_bb->count - bi_call_in_edge->count;
}
+ if (dom_info_available_p (CDI_DOMINATORS))
+ {
+ /* The split_blocks leave [guard 0] as the immediate dominator
+ of [call] and [call] as the immediate dominator of [join].
+ Fix them up. */
+ set_immediate_dominator (CDI_DOMINATORS, bi_call_bb, guard_bb);
+ set_immediate_dominator (CDI_DOMINATORS, join_tgt_bb, guard_bb);
+ }
+
if (dump_file && (dump_flags & TDF_DETAILS))
{
location_t loc;
@@ -927,7 +963,6 @@ pass_call_cdce::execute (function *fun)
if (something_changed)
{
- free_dominance_info (CDI_DOMINATORS);
free_dominance_info (CDI_POST_DOMINATORS);
/* As we introduced new control-flow we need to insert PHI-nodes
for the call-clobbers of the remaining call. */
diff --git a/gcc/tree-cfg.c b/gcc/tree-cfg.c
index cfed3c2195c..5d98eec9f18 100644
--- a/gcc/tree-cfg.c
+++ b/gcc/tree-cfg.c
@@ -5783,7 +5783,7 @@ gimple_split_block_before_cond_jump (basic_block bb)
if (gimple_code (last) != GIMPLE_COND
&& gimple_code (last) != GIMPLE_SWITCH)
return NULL;
- gsi_prev_nondebug (&gsi);
+ gsi_prev (&gsi);
split_point = gsi_stmt (gsi);
return split_block (bb, split_point)->dest;
}
diff --git a/gcc/tree-core.h b/gcc/tree-core.h
index f2299f28442..d7b4ca4914a 100644
--- a/gcc/tree-core.h
+++ b/gcc/tree-core.h
@@ -159,13 +159,10 @@ enum built_in_function {
BEGIN_CHKP_BUILTINS,
-#undef DEF_BUILTIN
#define DEF_BUILTIN(ENUM, N, C, T, LT, B, F, NA, AT, IM, COND)
-#undef DEF_BUILTIN_CHKP
#define DEF_BUILTIN_CHKP(ENUM, N, C, T, LT, B, F, NA, AT, IM, COND) \
ENUM##_CHKP = ENUM + BEGIN_CHKP_BUILTINS + 1,
#include "builtins.def"
-#undef DEF_BUILTIN_CHKP
END_CHKP_BUILTINS = BEGIN_CHKP_BUILTINS * 2 + 1,
@@ -186,7 +183,6 @@ enum built_in_function {
/* Upper bound on non-language-specific builtins. */
END_BUILTINS
};
-#undef DEF_BUILTIN
/* Tree code classes. Each tree_code has an associated code class
represented by a TREE_CODE_CLASS. */
@@ -737,7 +733,7 @@ enum size_type_kind {
enum operand_equal_flag {
OEP_ONLY_CONST = 1,
OEP_PURE_SAME = 2,
- OEP_CONSTANT_ADDRESS_OF = 4,
+ OEP_MATCH_SIDE_EFFECTS = 4,
OEP_ADDRESS_OF = 8
};
@@ -774,7 +770,6 @@ enum annot_expr_kind {
enum internal_fn {
#define DEF_INTERNAL_FN(CODE, FLAGS, FNSPEC) IFN_##CODE,
#include "internal-fn.def"
-#undef DEF_INTERNAL_FN
IFN_LAST
};
@@ -1156,8 +1151,14 @@ struct GTY(()) tree_base {
saturating_flag:
+ TYPE_REVERSE_STORAGE_ORDER in
+ RECORD_TYPE, UNION_TYPE, QUAL_UNION_TYPE, ARRAY_TYPE
+
TYPE_SATURATING in
- all types
+ other types
+
+ REF_REVERSE_STORAGE_ORDER in
+ BIT_FIELD_REF, MEM_REF
VAR_DECL_IS_VIRTUAL_OPERAND in
VAR_DECL
diff --git a/gcc/tree-data-ref.c b/gcc/tree-data-ref.c
index 0004fea846e..74f7614ff93 100644
--- a/gcc/tree-data-ref.c
+++ b/gcc/tree-data-ref.c
@@ -613,11 +613,12 @@ split_constant_offset_1 (tree type, tree op0, enum tree_code code, tree op1,
tree base, poffset;
HOST_WIDE_INT pbitsize, pbitpos;
machine_mode pmode;
- int punsignedp, pvolatilep;
+ int punsignedp, preversep, pvolatilep;
op0 = TREE_OPERAND (op0, 0);
- base = get_inner_reference (op0, &pbitsize, &pbitpos, &poffset,
- &pmode, &punsignedp, &pvolatilep, false);
+ base
+ = get_inner_reference (op0, &pbitsize, &pbitpos, &poffset, &pmode,
+ &punsignedp, &preversep, &pvolatilep, false);
if (pbitpos % BITS_PER_UNIT != 0)
return false;
@@ -761,7 +762,7 @@ dr_analyze_innermost (struct data_reference *dr, struct loop *nest)
HOST_WIDE_INT pbitsize, pbitpos;
tree base, poffset;
machine_mode pmode;
- int punsignedp, pvolatilep;
+ int punsignedp, preversep, pvolatilep;
affine_iv base_iv, offset_iv;
tree init, dinit, step;
bool in_loop = (loop && loop->num);
@@ -769,8 +770,8 @@ dr_analyze_innermost (struct data_reference *dr, struct loop *nest)
if (dump_file && (dump_flags & TDF_DETAILS))
fprintf (dump_file, "analyze_innermost: ");
- base = get_inner_reference (ref, &pbitsize, &pbitpos, &poffset,
- &pmode, &punsignedp, &pvolatilep, false);
+ base = get_inner_reference (ref, &pbitsize, &pbitpos, &poffset, &pmode,
+ &punsignedp, &preversep, &pvolatilep, false);
gcc_assert (base != NULL_TREE);
if (pbitpos % BITS_PER_UNIT != 0)
@@ -780,6 +781,13 @@ dr_analyze_innermost (struct data_reference *dr, struct loop *nest)
return false;
}
+ if (preversep)
+ {
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ fprintf (dump_file, "failed: reverse storage order.\n");
+ return false;
+ }
+
if (TREE_CODE (base) == MEM_REF)
{
if (!integer_zerop (TREE_OPERAND (base, 1)))
diff --git a/gcc/tree-dfa.c b/gcc/tree-dfa.c
index 952d136858d..bb5cd496126 100644
--- a/gcc/tree-dfa.c
+++ b/gcc/tree-dfa.c
@@ -368,12 +368,14 @@ get_or_create_ssa_default_def (struct function *fn, tree var)
base variable. The access range is delimited by bit positions *POFFSET and
*POFFSET + *PMAX_SIZE. The access size is *PSIZE bits. If either
*PSIZE or *PMAX_SIZE is -1, they could not be determined. If *PSIZE
- and *PMAX_SIZE are equal, the access is non-variable. */
+ and *PMAX_SIZE are equal, the access is non-variable. If *PREVERSE is
+ true, the storage order of the reference is reversed. */
tree
get_ref_base_and_extent (tree exp, HOST_WIDE_INT *poffset,
HOST_WIDE_INT *psize,
- HOST_WIDE_INT *pmax_size)
+ HOST_WIDE_INT *pmax_size,
+ bool *preverse)
{
offset_int bitsize = -1;
offset_int maxsize;
@@ -381,7 +383,8 @@ get_ref_base_and_extent (tree exp, HOST_WIDE_INT *poffset,
offset_int bit_offset = 0;
bool seen_variable_array_ref = false;
- /* First get the final access size from just the outermost expression. */
+ /* First get the final access size and the storage order from just the
+ outermost expression. */
if (TREE_CODE (exp) == COMPONENT_REF)
size_tree = DECL_SIZE (TREE_OPERAND (exp, 1));
else if (TREE_CODE (exp) == BIT_FIELD_REF)
@@ -398,6 +401,8 @@ get_ref_base_and_extent (tree exp, HOST_WIDE_INT *poffset,
&& TREE_CODE (size_tree) == INTEGER_CST)
bitsize = wi::to_offset (size_tree);
+ *preverse = reverse_storage_order_for_component_p (exp);
+
/* Initially, maxsize is the same as the accessed element size.
In the following it will only grow (or become -1). */
maxsize = bitsize;
diff --git a/gcc/tree-dfa.h b/gcc/tree-dfa.h
index c4f95eebe7a..3503398be84 100644
--- a/gcc/tree-dfa.h
+++ b/gcc/tree-dfa.h
@@ -30,7 +30,7 @@ extern tree ssa_default_def (struct function *, tree);
extern void set_ssa_default_def (struct function *, tree, tree);
extern tree get_or_create_ssa_default_def (struct function *, tree);
extern tree get_ref_base_and_extent (tree, HOST_WIDE_INT *,
- HOST_WIDE_INT *, HOST_WIDE_INT *);
+ HOST_WIDE_INT *, HOST_WIDE_INT *, bool *);
extern tree get_addr_base_and_unit_offset_1 (tree, HOST_WIDE_INT *,
tree (*) (tree));
extern tree get_addr_base_and_unit_offset (tree, HOST_WIDE_INT *);
diff --git a/gcc/tree-diagnostic.c b/gcc/tree-diagnostic.c
index 4ee21b9b277..bbb830b3e06 100644
--- a/gcc/tree-diagnostic.c
+++ b/gcc/tree-diagnostic.c
@@ -286,7 +286,7 @@ default_tree_printer (pretty_printer *pp, text_info *text, const char *spec,
}
if (set_locus)
- text->set_location (0, DECL_SOURCE_LOCATION (t));
+ text->set_location (0, DECL_SOURCE_LOCATION (t), true);
if (DECL_P (t))
{
diff --git a/gcc/tree-hash-traits.h b/gcc/tree-hash-traits.h
index 1edc49eda46..5143a9d79fa 100644
--- a/gcc/tree-hash-traits.h
+++ b/gcc/tree-hash-traits.h
@@ -23,18 +23,20 @@ along with GCC; see the file COPYING3. If not see
/* Hash for trees based on operand_equal_p. */
struct tree_operand_hash : ggc_ptr_hash <tree_node>
{
- static inline hashval_t hash (const_tree);
- static inline bool equal_keys (const_tree, const_tree);
+ static inline hashval_t hash (const value_type &);
+ static inline bool equal (const value_type &,
+ const compare_type &);
};
inline hashval_t
-tree_operand_hash::hash (const_tree t)
+tree_operand_hash::hash (const value_type &t)
{
return iterative_hash_expr (t, 0);
}
inline bool
-tree_operand_hash::equal_keys (const_tree t1, const_tree t2)
+tree_operand_hash::equal (const value_type &t1,
+ const compare_type &t2)
{
return operand_equal_p (t1, t2, 0);
}
diff --git a/gcc/tree-inline.c b/gcc/tree-inline.c
index 884131fc8f7..17d97a8712e 100644
--- a/gcc/tree-inline.c
+++ b/gcc/tree-inline.c
@@ -952,6 +952,7 @@ remap_gimple_op_r (tree *tp, int *walk_subtrees, void *data)
&& (!is_parm (TREE_OPERAND (old, 0))
|| (!id->transform_parameter && is_parm (ptr))))
TREE_THIS_NOTRAP (*tp) = 1;
+ REF_REVERSE_STORAGE_ORDER (*tp) = REF_REVERSE_STORAGE_ORDER (old);
*walk_subtrees = 0;
return NULL;
}
@@ -1209,6 +1210,7 @@ copy_tree_body_r (tree *tp, int *walk_subtrees, void *data)
&& (!is_parm (TREE_OPERAND (old, 0))
|| (!id->transform_parameter && is_parm (ptr))))
TREE_THIS_NOTRAP (*tp) = 1;
+ REF_REVERSE_STORAGE_ORDER (*tp) = REF_REVERSE_STORAGE_ORDER (old);
*walk_subtrees = 0;
return NULL;
}
diff --git a/gcc/tree-into-ssa.c b/gcc/tree-into-ssa.c
index 6533998fadc..3086f8247cb 100644
--- a/gcc/tree-into-ssa.c
+++ b/gcc/tree-into-ssa.c
@@ -94,7 +94,7 @@ static sbitmap interesting_blocks;
/* Set of SSA names that have been marked to be released after they
were registered in the replacement table. They will be finally
released after we finish updating the SSA web. */
-static bitmap names_to_release;
+bitmap names_to_release;
/* vec of vec of PHIs to rewrite in a basic block. Element I corresponds
the to basic block with index I. Allocated once per compilation, *not*
diff --git a/gcc/tree-into-ssa.h b/gcc/tree-into-ssa.h
index c053f785200..aed1e9588fd 100644
--- a/gcc/tree-into-ssa.h
+++ b/gcc/tree-into-ssa.h
@@ -48,5 +48,6 @@ extern void dump_names_replaced_by (FILE *, tree);
extern void debug_names_replaced_by (tree);
extern void dump_update_ssa (FILE *);
extern void debug_update_ssa (void);
+extern bitmap names_to_release;
#endif /* GCC_TREE_INTO_SSA_H */
diff --git a/gcc/tree-outof-ssa.c b/gcc/tree-outof-ssa.c
index 9de52e5ff0a..8800209d39b 100644
--- a/gcc/tree-outof-ssa.c
+++ b/gcc/tree-outof-ssa.c
@@ -305,7 +305,7 @@ insert_value_copy_on_edge (edge e, int dest, tree src, source_location locus)
else if (src_mode == BLKmode)
{
x = dest_rtx;
- store_expr (src, x, 0, false);
+ store_expr (src, x, 0, false, false);
}
else
x = expand_expr (src, dest_rtx, dest_mode, EXPAND_NORMAL);
diff --git a/gcc/tree-parloops.c b/gcc/tree-parloops.c
index 6c856340b96..3d41275c4d3 100644
--- a/gcc/tree-parloops.c
+++ b/gcc/tree-parloops.c
@@ -1737,6 +1737,8 @@ transform_to_exit_first_loop_alt (struct loop *loop,
/* Recalculate dominance info. */
free_dominance_info (CDI_DOMINATORS);
calculate_dominance_info (CDI_DOMINATORS);
+
+ checking_verify_ssa (true, true);
}
/* Tries to moves the exit condition of LOOP to the beginning of its header
diff --git a/gcc/tree-pretty-print.c b/gcc/tree-pretty-print.c
index b1685fd1018..3f0a4e6cfe0 100644
--- a/gcc/tree-pretty-print.c
+++ b/gcc/tree-pretty-print.c
@@ -3770,7 +3770,7 @@ void
percent_K_format (text_info *text)
{
tree t = va_arg (*text->args_ptr, tree), block;
- text->set_location (0, EXPR_LOCATION (t));
+ text->set_location (0, EXPR_LOCATION (t), true);
gcc_assert (pp_ti_abstract_origin (text) != NULL);
block = TREE_BLOCK (t);
*pp_ti_abstract_origin (text) = NULL;
diff --git a/gcc/tree-scalar-evolution.c b/gcc/tree-scalar-evolution.c
index 5cd7b1522ba..e90aafb771c 100644
--- a/gcc/tree-scalar-evolution.c
+++ b/gcc/tree-scalar-evolution.c
@@ -1715,15 +1715,16 @@ interpret_rhs_expr (struct loop *loop, gimple *at_stmt,
{
machine_mode mode;
HOST_WIDE_INT bitsize, bitpos;
- int unsignedp;
+ int unsignedp, reversep;
int volatilep = 0;
tree base, offset;
tree chrec3;
tree unitpos;
base = get_inner_reference (TREE_OPERAND (rhs1, 0),
- &bitsize, &bitpos, &offset,
- &mode, &unsignedp, &volatilep, false);
+ &bitsize, &bitpos, &offset, &mode,
+ &unsignedp, &reversep, &volatilep,
+ false);
if (TREE_CODE (base) == MEM_REF)
{
diff --git a/gcc/tree-sra.c b/gcc/tree-sra.c
index 2ddc9349aef..a89630876c7 100644
--- a/gcc/tree-sra.c
+++ b/gcc/tree-sra.c
@@ -179,12 +179,15 @@ struct access
when grp_to_be_replaced flag is set. */
tree replacement_decl;
- /* Is this particular access write access? */
- unsigned write : 1;
-
/* Is this access an access to a non-addressable field? */
unsigned non_addressable : 1;
+ /* Is this access made in reverse storage order? */
+ unsigned reverse : 1;
+
+ /* Is this particular access write access? */
+ unsigned write : 1;
+
/* Is this access currently in the work queue? */
unsigned grp_queued : 1;
@@ -423,6 +426,8 @@ dump_access (FILE *f, struct access *access, bool grp)
print_generic_expr (f, access->expr, 0);
fprintf (f, ", type = ");
print_generic_expr (f, access->type, 0);
+ fprintf (f, ", non_addressable = %d, reverse = %d",
+ access->non_addressable, access->reverse);
if (grp)
fprintf (f, ", grp_read = %d, grp_write = %d, grp_assignment_read = %d, "
"grp_assignment_write = %d, grp_scalar_read = %d, "
@@ -839,9 +844,9 @@ create_access (tree expr, gimple *stmt, bool write)
struct access *access;
HOST_WIDE_INT offset, size, max_size;
tree base = expr;
- bool ptr, unscalarizable_region = false;
+ bool reverse, ptr, unscalarizable_region = false;
- base = get_ref_base_and_extent (expr, &offset, &size, &max_size);
+ base = get_ref_base_and_extent (expr, &offset, &size, &max_size, &reverse);
if (sra_mode == SRA_MODE_EARLY_IPA
&& TREE_CODE (base) == MEM_REF)
@@ -895,6 +900,7 @@ create_access (tree expr, gimple *stmt, bool write)
access->write = write;
access->grp_unscalarizable_region = unscalarizable_region;
access->stmt = stmt;
+ access->reverse = reverse;
if (TREE_CODE (expr) == COMPONENT_REF
&& DECL_NONADDRESSABLE_P (TREE_OPERAND (expr, 1)))
@@ -959,7 +965,7 @@ scalarizable_type_p (tree type)
}
}
-static void scalarize_elem (tree, HOST_WIDE_INT, HOST_WIDE_INT, tree, tree);
+static void scalarize_elem (tree, HOST_WIDE_INT, HOST_WIDE_INT, bool, tree, tree);
/* Create total_scalarization accesses for all scalar fields of a member
of type DECL_TYPE conforming to scalarizable_type_p. BASE
@@ -980,8 +986,9 @@ completely_scalarize (tree base, tree decl_type, HOST_WIDE_INT offset, tree ref)
tree ft = TREE_TYPE (fld);
tree nref = build3 (COMPONENT_REF, ft, ref, fld, NULL_TREE);
- scalarize_elem (base, pos, tree_to_uhwi (DECL_SIZE (fld)), nref,
- ft);
+ scalarize_elem (base, pos, tree_to_uhwi (DECL_SIZE (fld)),
+ TYPE_REVERSE_STORAGE_ORDER (decl_type),
+ nref, ft);
}
break;
case ARRAY_TYPE:
@@ -999,18 +1006,27 @@ completely_scalarize (tree base, tree decl_type, HOST_WIDE_INT offset, tree ref)
if (maxidx)
{
gcc_assert (TREE_CODE (maxidx) == INTEGER_CST);
- /* MINIDX and MAXIDX are inclusive. Try to avoid overflow. */
- unsigned HOST_WIDE_INT lenp1 = tree_to_shwi (maxidx)
- - tree_to_shwi (minidx);
- unsigned HOST_WIDE_INT idx = 0;
- do
+ tree domain = TYPE_DOMAIN (decl_type);
+ /* MINIDX and MAXIDX are inclusive, and must be interpreted in
+ DOMAIN (e.g. signed int, whereas min/max may be size_int). */
+ offset_int idx = wi::to_offset (minidx);
+ offset_int max = wi::to_offset (maxidx);
+ if (!TYPE_UNSIGNED (domain))
{
- tree nref = build4 (ARRAY_REF, elemtype, ref, size_int (idx),
+ idx = wi::sext (idx, TYPE_PRECISION (domain));
+ max = wi::sext (max, TYPE_PRECISION (domain));
+ }
+ for (int el_off = offset; wi::les_p (idx, max); ++idx)
+ {
+ tree nref = build4 (ARRAY_REF, elemtype,
+ ref,
+ wide_int_to_tree (domain, idx),
NULL_TREE, NULL_TREE);
- int el_off = offset + idx * el_size;
- scalarize_elem (base, el_off, el_size, nref, elemtype);
+ scalarize_elem (base, el_off, el_size,
+ TYPE_REVERSE_STORAGE_ORDER (decl_type),
+ nref, elemtype);
+ el_off += el_size;
}
- while (++idx <= lenp1);
}
}
break;
@@ -1022,11 +1038,12 @@ completely_scalarize (tree base, tree decl_type, HOST_WIDE_INT offset, tree ref)
/* Create total_scalarization accesses for a member of type TYPE, which must
satisfy either is_gimple_reg_type or scalarizable_type_p. BASE must be the
top-most VAR_DECL representing the variable; within that, POS and SIZE locate
- the member and REF must be the reference expression for it. */
+ the member, REVERSE gives its torage order. and REF must be the reference
+ expression for it. */
static void
-scalarize_elem (tree base, HOST_WIDE_INT pos, HOST_WIDE_INT size,
- tree ref, tree type)
+scalarize_elem (tree base, HOST_WIDE_INT pos, HOST_WIDE_INT size, bool reverse,
+ tree ref, tree type)
{
if (is_gimple_reg_type (type))
{
@@ -1034,6 +1051,7 @@ scalarize_elem (tree base, HOST_WIDE_INT pos, HOST_WIDE_INT size,
access->expr = ref;
access->type = type;
access->grp_total_scalarization = 1;
+ access->reverse = reverse;
/* Accesses for intraprocedural SRA can have their stmt NULL. */
}
else
@@ -1109,7 +1127,7 @@ build_access_from_expr_1 (tree expr, gimple *stmt, bool write)
and not the result type. Ada produces such statements. We are also
capable of handling the topmost V_C_E but not any of those buried in other
handled components. */
- if (TREE_CODE (expr) == VIEW_CONVERT_EXPR)
+ if (TREE_CODE (expr) == VIEW_CONVERT_EXPR && !storage_order_barrier_p (expr))
expr = TREE_OPERAND (expr, 0);
if (contains_view_convert_expr_p (expr))
@@ -1242,7 +1260,11 @@ build_accesses_from_assign (gimple *stmt)
lacc = build_access_from_expr_1 (lhs, stmt, true);
if (lacc)
- lacc->grp_assignment_write = 1;
+ {
+ lacc->grp_assignment_write = 1;
+ if (storage_order_barrier_p (rhs))
+ lacc->grp_unscalarizable_region = 1;
+ }
if (racc)
{
@@ -1250,6 +1272,8 @@ build_accesses_from_assign (gimple *stmt)
if (should_scalarize_away_bitmap && !gimple_has_volatile_ops (stmt)
&& !is_gimple_reg_type (racc->type))
bitmap_set_bit (should_scalarize_away_bitmap, DECL_UID (racc->base));
+ if (storage_order_barrier_p (lhs))
+ racc->grp_unscalarizable_region = 1;
}
if (lacc && racc
@@ -1557,17 +1581,15 @@ make_fancy_name (tree expr)
}
/* Construct a MEM_REF that would reference a part of aggregate BASE of type
- EXP_TYPE at the given OFFSET. If BASE is something for which
- get_addr_base_and_unit_offset returns NULL, gsi must be non-NULL and is used
- to insert new statements either before or below the current one as specified
- by INSERT_AFTER. This function is not capable of handling bitfields.
-
- BASE must be either a declaration or a memory reference that has correct
- alignment ifformation embeded in it (e.g. a pre-existing one in SRA). */
+ EXP_TYPE at the given OFFSET and with storage order REVERSE. If BASE is
+ something for which get_addr_base_and_unit_offset returns NULL, gsi must
+ be non-NULL and is used to insert new statements either before or below
+ the current one as specified by INSERT_AFTER. This function is not capable
+ of handling bitfields. */
tree
build_ref_for_offset (location_t loc, tree base, HOST_WIDE_INT offset,
- tree exp_type, gimple_stmt_iterator *gsi,
+ bool reverse, tree exp_type, gimple_stmt_iterator *gsi,
bool insert_after)
{
tree prev_base = base;
@@ -1624,6 +1646,7 @@ build_ref_for_offset (location_t loc, tree base, HOST_WIDE_INT offset,
exp_type = build_aligned_type (exp_type, align);
mem_ref = fold_build2_loc (loc, MEM_REF, exp_type, base, off);
+ REF_REVERSE_STORAGE_ORDER (mem_ref) = reverse;
if (TREE_THIS_VOLATILE (prev_base))
TREE_THIS_VOLATILE (mem_ref) = 1;
if (TREE_SIDE_EFFECTS (prev_base))
@@ -1650,13 +1673,17 @@ build_ref_for_model (location_t loc, tree base, HOST_WIDE_INT offset,
offset -= int_bit_position (fld);
exp_type = TREE_TYPE (TREE_OPERAND (model->expr, 0));
- t = build_ref_for_offset (loc, base, offset, exp_type, gsi, insert_after);
+ t = build_ref_for_offset (loc, base, offset, model->reverse, exp_type,
+ gsi, insert_after);
+ /* The flag will be set on the record type. */
+ REF_REVERSE_STORAGE_ORDER (t) = 0;
return fold_build3_loc (loc, COMPONENT_REF, TREE_TYPE (fld), t, fld,
NULL_TREE);
}
else
- return build_ref_for_offset (loc, base, offset, model->type,
- gsi, insert_after);
+ 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
@@ -2313,8 +2340,8 @@ analyze_access_subtree (struct access *root, struct access *parent,
&& (root->size % BITS_PER_UNIT) == 0);
root->type = build_nonstandard_integer_type (root->size,
TYPE_UNSIGNED (rt));
- root->expr = build_ref_for_offset (UNKNOWN_LOCATION,
- root->base, root->offset,
+ root->expr = build_ref_for_offset (UNKNOWN_LOCATION, root->base,
+ root->offset, root->reverse,
root->type, NULL, false);
if (dump_file && (dump_flags & TDF_DETAILS))
@@ -2438,6 +2465,7 @@ create_artificial_child_access (struct access *parent, struct access *model,
access->type = model->type;
access->grp_write = true;
access->grp_read = false;
+ access->reverse = model->reverse;
child = &parent->first_child;
while (*child && (*child)->offset < new_offset)
@@ -2822,6 +2850,7 @@ get_access_for_expr (tree expr)
{
HOST_WIDE_INT offset, size, max_size;
tree base;
+ bool reverse;
/* FIXME: This should not be necessary but Ada produces V_C_Es with a type of
a different size than the size of its argument and we need the latter
@@ -2829,7 +2858,7 @@ get_access_for_expr (tree expr)
if (TREE_CODE (expr) == VIEW_CONVERT_EXPR)
expr = TREE_OPERAND (expr, 0);
- base = get_ref_base_and_extent (expr, &offset, &size, &max_size);
+ base = get_ref_base_and_extent (expr, &offset, &size, &max_size, &reverse);
if (max_size == -1 || !DECL_P (base))
return NULL;
@@ -4462,6 +4491,7 @@ turn_representatives_into_adjustments (vec<access_p> representatives,
adj.type = repr->type;
adj.alias_ptr_type = reference_alias_ptr_type (repr->expr);
adj.offset = repr->offset;
+ adj.reverse = repr->reverse;
adj.by_ref = (POINTER_TYPE_P (TREE_TYPE (repr->base))
&& (repr->grp_maybe_modified
|| repr->grp_not_necessarilly_dereferenced));
@@ -5092,9 +5122,9 @@ ipa_sra_check_caller (struct cgraph_node *node, void *data)
tree offset;
HOST_WIDE_INT bitsize, bitpos;
machine_mode mode;
- int unsignedp, volatilep = 0;
+ int unsignedp, reversep, volatilep = 0;
get_inner_reference (arg, &bitsize, &bitpos, &offset, &mode,
- &unsignedp, &volatilep, false);
+ &unsignedp, &reversep, &volatilep, false);
if (bitpos % BITS_PER_UNIT)
{
iscc->bad_arg_alignment = true;
diff --git a/gcc/tree-ssa-address.c b/gcc/tree-ssa-address.c
index 2c63f87dd00..62b89e61d53 100644
--- a/gcc/tree-ssa-address.c
+++ b/gcc/tree-ssa-address.c
@@ -377,7 +377,7 @@ create_mem_ref_raw (tree type, tree alias_ptr_type, struct mem_address *addr,
}
else
{
- base = build_int_cst (ptr_type_node, 0);
+ base = build_int_cst (build_pointer_type (type), 0);
index2 = addr->base;
}
diff --git a/gcc/tree-ssa-alias.c b/gcc/tree-ssa-alias.c
index 234033036fc..e1d9cda8fe8 100644
--- a/gcc/tree-ssa-alias.c
+++ b/gcc/tree-ssa-alias.c
@@ -541,10 +541,12 @@ ao_ref_init (ao_ref *r, tree ref)
tree
ao_ref_base (ao_ref *ref)
{
+ bool reverse;
+
if (ref->base)
return ref->base;
ref->base = get_ref_base_and_extent (ref->ref, &ref->offset, &ref->size,
- &ref->max_size);
+ &ref->max_size, &reverse);
return ref->base;
}
@@ -725,9 +727,10 @@ aliasing_component_refs_p (tree ref1,
else if (same_p == 1)
{
HOST_WIDE_INT offadj, sztmp, msztmp;
- get_ref_base_and_extent (*refp, &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);
+ get_ref_base_and_extent (base1, &offadj, &sztmp, &msztmp, &reverse);
offset1 -= offadj;
return ranges_overlap_p (offset1, max_size1, offset2, max_size2);
}
@@ -743,9 +746,10 @@ aliasing_component_refs_p (tree ref1,
else if (same_p == 1)
{
HOST_WIDE_INT offadj, sztmp, msztmp;
- get_ref_base_and_extent (*refp, &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);
+ get_ref_base_and_extent (base2, &offadj, &sztmp, &msztmp, &reverse);
offset2 -= offadj;
return ranges_overlap_p (offset1, max_size1, offset2, max_size2);
}
@@ -2281,7 +2285,9 @@ stmt_kills_ref_p (gimple *stmt, ao_ref *ref)
if (ref->max_size == -1)
return false;
HOST_WIDE_INT size, offset, max_size, ref_offset = ref->offset;
- tree base = get_ref_base_and_extent (lhs, &offset, &size, &max_size);
+ bool reverse;
+ tree base
+ = get_ref_base_and_extent (lhs, &offset, &size, &max_size, &reverse);
/* We can get MEM[symbol: sZ, index: D.8862_1] here,
so base == ref->base does not always hold. */
if (base != ref->base)
diff --git a/gcc/tree-ssa-dce.c b/gcc/tree-ssa-dce.c
index f4a94740725..67f2603ab17 100644
--- a/gcc/tree-ssa-dce.c
+++ b/gcc/tree-ssa-dce.c
@@ -474,8 +474,10 @@ mark_aliased_reaching_defs_necessary_1 (ao_ref *ref, tree vdef, void *data)
{
tree base, lhs = gimple_get_lhs (def_stmt);
HOST_WIDE_INT size, offset, max_size;
+ bool reverse;
ao_ref_base (ref);
- base = get_ref_base_and_extent (lhs, &offset, &size, &max_size);
+ base
+ = get_ref_base_and_extent (lhs, &offset, &size, &max_size, &reverse);
/* We can get MEM[symbol: sZ, index: D.8862_1] here,
so base == refd->base does not always hold. */
if (base == ref->base)
diff --git a/gcc/tree-ssa-loop-ivopts.c b/gcc/tree-ssa-loop-ivopts.c
index 1f952a7ca0e..5ae5e72458b 100644
--- a/gcc/tree-ssa-loop-ivopts.c
+++ b/gcc/tree-ssa-loop-ivopts.c
@@ -1983,10 +1983,27 @@ may_be_nonaddressable_p (tree expr)
target, thus they are always addressable. */
return false;
+ case MEM_REF:
+ /* Likewise for MEM_REFs, modulo the storage order. */
+ return REF_REVERSE_STORAGE_ORDER (expr);
+
+ case BIT_FIELD_REF:
+ if (REF_REVERSE_STORAGE_ORDER (expr))
+ return true;
+ return may_be_nonaddressable_p (TREE_OPERAND (expr, 0));
+
case COMPONENT_REF:
+ if (TYPE_REVERSE_STORAGE_ORDER (TREE_TYPE (TREE_OPERAND (expr, 0))))
+ return true;
return DECL_NONADDRESSABLE_P (TREE_OPERAND (expr, 1))
|| may_be_nonaddressable_p (TREE_OPERAND (expr, 0));
+ case ARRAY_REF:
+ case ARRAY_RANGE_REF:
+ if (TYPE_REVERSE_STORAGE_ORDER (TREE_TYPE (TREE_OPERAND (expr, 0))))
+ return true;
+ return may_be_nonaddressable_p (TREE_OPERAND (expr, 0));
+
case VIEW_CONVERT_EXPR:
/* This kind of view-conversions may wrap non-addressable objects
and make them look addressable. After some processing the
@@ -1995,11 +2012,6 @@ may_be_nonaddressable_p (tree expr)
if (is_gimple_reg (TREE_OPERAND (expr, 0))
|| !is_gimple_addressable (TREE_OPERAND (expr, 0)))
return true;
-
- /* ... fall through ... */
-
- case ARRAY_REF:
- case ARRAY_RANGE_REF:
return may_be_nonaddressable_p (TREE_OPERAND (expr, 0));
CASE_CONVERT:
@@ -4306,13 +4318,14 @@ split_address_cost (struct ivopts_data *data,
HOST_WIDE_INT bitpos;
tree toffset;
machine_mode mode;
- int unsignedp, volatilep;
+ int unsignedp, reversep, volatilep;
core = get_inner_reference (addr, &bitsize, &bitpos, &toffset, &mode,
- &unsignedp, &volatilep, false);
+ &unsignedp, &reversep, &volatilep, false);
if (toffset != 0
|| bitpos % BITS_PER_UNIT != 0
+ || reversep
|| TREE_CODE (core) != VAR_DECL)
{
*symbol_present = false;
diff --git a/gcc/tree-ssa-math-opts.c b/gcc/tree-ssa-math-opts.c
index 41fcabfc0eb..6368ddf8266 100644
--- a/gcc/tree-ssa-math-opts.c
+++ b/gcc/tree-ssa-math-opts.c
@@ -2024,7 +2024,7 @@ find_bswap_or_nop_load (gimple *stmt, tree ref, struct symbolic_number *n)
offset from base to compare to other such leaf node. */
HOST_WIDE_INT bitsize, bitpos;
machine_mode mode;
- int unsignedp, volatilep;
+ int unsignedp, reversep, volatilep;
tree offset, base_addr;
/* Not prepared to handle PDP endian. */
@@ -2035,7 +2035,7 @@ find_bswap_or_nop_load (gimple *stmt, tree ref, struct symbolic_number *n)
return false;
base_addr = get_inner_reference (ref, &bitsize, &bitpos, &offset, &mode,
- &unsignedp, &volatilep, false);
+ &unsignedp, &reversep, &volatilep, false);
if (TREE_CODE (base_addr) == MEM_REF)
{
@@ -2074,6 +2074,8 @@ find_bswap_or_nop_load (gimple *stmt, tree ref, struct symbolic_number *n)
return false;
if (bitsize % BITS_PER_UNIT)
return false;
+ if (reversep)
+ return false;
if (!init_symbolic_number (n, ref))
return false;
@@ -2522,11 +2524,11 @@ bswap_replace (gimple *cur_stmt, gimple *src_stmt, tree fndecl,
{
HOST_WIDE_INT bitsize, bitpos;
machine_mode mode;
- int unsignedp, volatilep;
+ int unsignedp, reversep, volatilep;
tree offset;
get_inner_reference (src, &bitsize, &bitpos, &offset, &mode,
- &unsignedp, &volatilep, false);
+ &unsignedp, &reversep, &volatilep, false);
if (n->range < (unsigned HOST_WIDE_INT) bitsize)
{
load_offset = (bitsize - n->range) / BITS_PER_UNIT;
diff --git a/gcc/tree-ssa-pre.c b/gcc/tree-ssa-pre.c
index f3d3480b5eb..baafa34d40b 100644
--- a/gcc/tree-ssa-pre.c
+++ b/gcc/tree-ssa-pre.c
@@ -2481,6 +2481,7 @@ create_component_ref_by_pieces_1 (basic_block block, vn_reference_t ref,
genop = build2 (MEM_REF, currop->type, baseop, offset);
MR_DEPENDENCE_CLIQUE (genop) = currop->clique;
MR_DEPENDENCE_BASE (genop) = currop->base;
+ REF_REVERSE_STORAGE_ORDER (genop) = currop->reverse;
return genop;
}
@@ -2550,7 +2551,9 @@ create_component_ref_by_pieces_1 (basic_block block, vn_reference_t ref,
return NULL_TREE;
tree op1 = currop->op0;
tree op2 = currop->op1;
- return fold_build3 (BIT_FIELD_REF, currop->type, genop0, op1, op2);
+ tree t = build3 (BIT_FIELD_REF, currop->type, genop0, op1, op2);
+ REF_REVERSE_STORAGE_ORDER (t) = currop->reverse;
+ return fold (t);
}
/* For array ref vn_reference_op's, operand 1 of the array ref
diff --git a/gcc/tree-ssa-sccvn.c b/gcc/tree-ssa-sccvn.c
index 159a7b60f81..9585f905438 100644
--- a/gcc/tree-ssa-sccvn.c
+++ b/gcc/tree-ssa-sccvn.c
@@ -637,6 +637,9 @@ vn_reference_eq (const_vn_reference_t const vr1, const_vn_reference_t const vr2)
{
if (vro1->opcode == MEM_REF)
deref1 = true;
+ /* Do not look through a storage order barrier. */
+ else if (vro1->opcode == VIEW_CONVERT_EXPR && vro1->reverse)
+ return false;
if (vro1->off == -1)
break;
off1 += vro1->off;
@@ -645,6 +648,9 @@ vn_reference_eq (const_vn_reference_t const vr1, const_vn_reference_t const vr2)
{
if (vro2->opcode == MEM_REF)
deref2 = true;
+ /* Do not look through a storage order barrier. */
+ else if (vro2->opcode == VIEW_CONVERT_EXPR && vro2->reverse)
+ return false;
if (vro2->off == -1)
break;
off2 += vro2->off;
@@ -748,9 +754,10 @@ copy_reference_ops_from_ref (tree ref, vec<vn_reference_op_s> *result)
temp.off = tree_to_shwi (TREE_OPERAND (ref, 1));
temp.clique = MR_DEPENDENCE_CLIQUE (ref);
temp.base = MR_DEPENDENCE_BASE (ref);
+ temp.reverse = REF_REVERSE_STORAGE_ORDER (ref);
break;
case BIT_FIELD_REF:
- /* Record bits and position. */
+ /* Record bits, position and storage order. */
temp.op0 = TREE_OPERAND (ref, 1);
temp.op1 = TREE_OPERAND (ref, 2);
if (tree_fits_shwi_p (TREE_OPERAND (ref, 2)))
@@ -759,6 +766,7 @@ copy_reference_ops_from_ref (tree ref, vec<vn_reference_op_s> *result)
if (off % BITS_PER_UNIT == 0)
temp.off = off / BITS_PER_UNIT;
}
+ temp.reverse = REF_REVERSE_STORAGE_ORDER (ref);
break;
case COMPONENT_REF:
/* The field decl is enough to unambiguously specify the field,
@@ -855,8 +863,11 @@ copy_reference_ops_from_ref (tree ref, vec<vn_reference_op_s> *result)
operand), so we don't have to put anything
for op* as it will be handled by the iteration */
case REALPART_EXPR:
+ temp.off = 0;
+ break;
case VIEW_CONVERT_EXPR:
temp.off = 0;
+ temp.reverse = storage_order_barrier_p (ref);
break;
case IMAGPART_EXPR:
/* This is only interesting for its constant offset. */
@@ -1365,6 +1376,21 @@ fully_constant_vn_reference_p (vn_reference_t ref)
return NULL_TREE;
}
+/* Return true if OPS contain a storage order barrier. */
+
+static bool
+contains_storage_order_barrier_p (vec<vn_reference_op_s> ops)
+{
+ vn_reference_op_t op;
+ unsigned i;
+
+ FOR_EACH_VEC_ELT (ops, i, op)
+ if (op->opcode == VIEW_CONVERT_EXPR && op->reverse)
+ return true;
+
+ return false;
+}
+
/* Transform any SSA_NAME's in a vector of vn_reference_op_s
structures into their value numbers. This is done in-place, and
the vector passed in is returned. *VALUEIZED_ANYTHING will specify
@@ -1702,7 +1728,9 @@ vn_reference_lookup_3 (ao_ref *ref, tree vuse, void *vr_,
tree ref2 = TREE_OPERAND (gimple_call_arg (def_stmt, 0), 0);
tree base2;
HOST_WIDE_INT offset2, size2, maxsize2;
- base2 = get_ref_base_and_extent (ref2, &offset2, &size2, &maxsize2);
+ bool reverse;
+ base2 = get_ref_base_and_extent (ref2, &offset2, &size2, &maxsize2,
+ &reverse);
size2 = tree_to_uhwi (gimple_call_arg (def_stmt, 2)) * 8;
if ((unsigned HOST_WIDE_INT)size2 / 8
== tree_to_uhwi (gimple_call_arg (def_stmt, 2))
@@ -1725,8 +1753,9 @@ vn_reference_lookup_3 (ao_ref *ref, tree vuse, void *vr_,
{
tree base2;
HOST_WIDE_INT offset2, size2, maxsize2;
+ bool reverse;
base2 = get_ref_base_and_extent (gimple_assign_lhs (def_stmt),
- &offset2, &size2, &maxsize2);
+ &offset2, &size2, &maxsize2, &reverse);
if (maxsize2 != -1
&& operand_equal_p (base, base2, 0)
&& offset2 <= offset
@@ -1746,14 +1775,17 @@ vn_reference_lookup_3 (ao_ref *ref, tree vuse, void *vr_,
&& maxsize % BITS_PER_UNIT == 0
&& offset % BITS_PER_UNIT == 0
&& is_gimple_reg_type (vr->type)
+ && !contains_storage_order_barrier_p (vr->operands)
&& gimple_assign_single_p (def_stmt)
&& is_gimple_min_invariant (gimple_assign_rhs1 (def_stmt)))
{
tree base2;
HOST_WIDE_INT offset2, size2, maxsize2;
+ bool reverse;
base2 = get_ref_base_and_extent (gimple_assign_lhs (def_stmt),
- &offset2, &size2, &maxsize2);
- if (maxsize2 != -1
+ &offset2, &size2, &maxsize2, &reverse);
+ if (!reverse
+ && maxsize2 != -1
&& maxsize2 == size2
&& size2 % BITS_PER_UNIT == 0
&& offset2 % BITS_PER_UNIT == 0
@@ -1785,6 +1817,7 @@ vn_reference_lookup_3 (ao_ref *ref, tree vuse, void *vr_,
to access pieces from. */
else if (ref->size == maxsize
&& is_gimple_reg_type (vr->type)
+ && !contains_storage_order_barrier_p (vr->operands)
&& gimple_assign_single_p (def_stmt)
&& TREE_CODE (gimple_assign_rhs1 (def_stmt)) == SSA_NAME)
{
@@ -1797,10 +1830,13 @@ vn_reference_lookup_3 (ao_ref *ref, tree vuse, void *vr_,
{
tree base2;
HOST_WIDE_INT offset2, size2, maxsize2, off;
+ bool reverse;
base2 = get_ref_base_and_extent (gimple_assign_lhs (def_stmt),
- &offset2, &size2, &maxsize2);
+ &offset2, &size2, &maxsize2,
+ &reverse);
off = offset - offset2;
- if (maxsize2 != -1
+ if (!reverse
+ && maxsize2 != -1
&& maxsize2 == size2
&& operand_equal_p (base, base2, 0)
&& offset2 <= offset
@@ -1849,7 +1885,7 @@ vn_reference_lookup_3 (ao_ref *ref, tree vuse, void *vr_,
{
tree base2;
HOST_WIDE_INT maxsize2;
- int i, j;
+ int i, j, k;
auto_vec<vn_reference_op_s> rhs;
vn_reference_op_t vro;
ao_ref r;
@@ -1909,6 +1945,14 @@ vn_reference_lookup_3 (ao_ref *ref, tree vuse, void *vr_,
if (j != -1)
return (void *)-1;
+ /* Punt if the additional ops contain a storage order barrier. */
+ for (k = i; k >= 0; k--)
+ {
+ vro = &vr->operands[k];
+ if (vro->opcode == VIEW_CONVERT_EXPR && vro->reverse)
+ return (void *)-1;
+ }
+
/* Now re-write REF to be based on the rhs of the assignment. */
copy_reference_ops_from_ref (gimple_assign_rhs1 (def_stmt), &rhs);
@@ -1983,7 +2027,6 @@ vn_reference_lookup_3 (ao_ref *ref, tree vuse, void *vr_,
vn_reference_op_s op;
HOST_WIDE_INT at;
-
/* Only handle non-variable, addressable refs. */
if (ref->size != maxsize
|| offset % BITS_PER_UNIT != 0
@@ -4154,6 +4197,7 @@ class sccvn_dom_walker : public dom_walker
public:
sccvn_dom_walker ()
: dom_walker (CDI_DOMINATORS), fail (false), cond_stack (vNULL) {}
+ ~sccvn_dom_walker ();
virtual void before_dom_children (basic_block);
virtual void after_dom_children (basic_block);
@@ -4168,6 +4212,11 @@ public:
cond_stack;
};
+sccvn_dom_walker::~sccvn_dom_walker ()
+{
+ cond_stack.release ();
+}
+
/* Record a temporary condition for the BB and its dominated blocks. */
void
diff --git a/gcc/tree-ssa-sccvn.h b/gcc/tree-ssa-sccvn.h
index c8b918aa4e9..bbdca65ce46 100644
--- a/gcc/tree-ssa-sccvn.h
+++ b/gcc/tree-ssa-sccvn.h
@@ -92,6 +92,7 @@ typedef struct vn_reference_op_struct
tree op0;
tree op1;
tree op2;
+ bool reverse;
} vn_reference_op_s;
typedef vn_reference_op_s *vn_reference_op_t;
typedef const vn_reference_op_s *const_vn_reference_op_t;
diff --git a/gcc/tree-ssa-structalias.c b/gcc/tree-ssa-structalias.c
index 52a35f6ab51..f24ebeba815 100644
--- a/gcc/tree-ssa-structalias.c
+++ b/gcc/tree-ssa-structalias.c
@@ -3168,6 +3168,7 @@ get_constraint_for_component_ref (tree t, vec<ce_s> *results,
HOST_WIDE_INT bitsize = -1;
HOST_WIDE_INT bitmaxsize = -1;
HOST_WIDE_INT bitpos;
+ bool reverse;
tree forzero;
/* Some people like to do cute things like take the address of
@@ -3189,7 +3190,7 @@ get_constraint_for_component_ref (tree t, vec<ce_s> *results,
return;
}
- t = get_ref_base_and_extent (t, &bitpos, &bitsize, &bitmaxsize);
+ t = get_ref_base_and_extent (t, &bitpos, &bitsize, &bitmaxsize, &reverse);
/* Pretend to take the address of the base, we'll take care of
adding the required subset of sub-fields below. */
@@ -3615,9 +3616,12 @@ do_structure_copy (tree lhsop, tree rhsop)
{
HOST_WIDE_INT lhssize, lhsmaxsize, lhsoffset;
HOST_WIDE_INT rhssize, rhsmaxsize, rhsoffset;
+ bool reverse;
unsigned k = 0;
- get_ref_base_and_extent (lhsop, &lhsoffset, &lhssize, &lhsmaxsize);
- get_ref_base_and_extent (rhsop, &rhsoffset, &rhssize, &rhsmaxsize);
+ get_ref_base_and_extent (lhsop, &lhsoffset, &lhssize, &lhsmaxsize,
+ &reverse);
+ get_ref_base_and_extent (rhsop, &rhsoffset, &rhssize, &rhsmaxsize,
+ &reverse);
for (j = 0; lhsc.iterate (j, &lhsp);)
{
varinfo_t lhsv, rhsv;
diff --git a/gcc/tree-ssa-tail-merge.c b/gcc/tree-ssa-tail-merge.c
index 3e9718b7da5..7ea092ab650 100644
--- a/gcc/tree-ssa-tail-merge.c
+++ b/gcc/tree-ssa-tail-merge.c
@@ -1081,7 +1081,7 @@ gimple_operand_equal_value_p (tree t1, tree t2)
|| t2 == NULL_TREE)
return false;
- if (operand_equal_p (t1, t2, 0))
+ if (operand_equal_p (t1, t2, OEP_MATCH_SIDE_EFFECTS))
return true;
return gvn_uses_equal (t1, t2);
diff --git a/gcc/tree-ssa-threadedge.c b/gcc/tree-ssa-threadedge.c
index 9379198901f..971fc528f63 100644
--- a/gcc/tree-ssa-threadedge.c
+++ b/gcc/tree-ssa-threadedge.c
@@ -376,17 +376,6 @@ record_temporary_equivalences_from_stmts_at_dest (edge e,
return stmt;
}
-/* Once we have passed a backedge in the CFG when threading, we do not want to
- utilize edge equivalences for simplification purpose. They are no longer
- necessarily valid. We use this callback rather than the ones provided by
- DOM/VRP to achieve that effect. */
-static tree
-dummy_simplify (gimple *stmt1 ATTRIBUTE_UNUSED, gimple *stmt2 ATTRIBUTE_UNUSED,
- class avail_exprs_stack *avail_exprs_stack ATTRIBUTE_UNUSED)
-{
- return NULL_TREE;
-}
-
/* Simplify the control statement at the end of the block E->dest.
To avoid allocating memory unnecessarily, a scratch GIMPLE_COND
@@ -396,7 +385,7 @@ dummy_simplify (gimple *stmt1 ATTRIBUTE_UNUSED, gimple *stmt2 ATTRIBUTE_UNUSED,
a condition using pass specific information.
Return the simplified condition or NULL if simplification could
- not be performed.
+ not be performed.
The available expression table is referenced via AVAIL_EXPRS_STACK. */
@@ -707,7 +696,7 @@ propagate_threaded_block_debug_into (basic_block dest, basic_block src)
return false.
DUMMY_COND, HANDLE_DOMINATING_ASSERTS and SIMPLIFY are used to
- try and simplify the condition at the end of TAKEN_EDGE->dest.
+ try and simplify the condition at the end of TAKEN_EDGE->dest.
The available expression table is referenced via AVAIL_EXPRS_STACK. */
@@ -718,8 +707,7 @@ thread_around_empty_blocks (edge taken_edge,
bool handle_dominating_asserts,
pfn_simplify simplify,
bitmap visited,
- vec<jump_thread_edge *> *path,
- bool *backedge_seen_p)
+ vec<jump_thread_edge *> *path)
{
basic_block bb = taken_edge->dest;
gimple_stmt_iterator gsi;
@@ -754,23 +742,23 @@ thread_around_empty_blocks (edge taken_edge,
if (single_succ_p (bb))
{
taken_edge = single_succ_edge (bb);
+
+ if ((taken_edge->flags & EDGE_DFS_BACK) != 0)
+ return false;
+
if (!bitmap_bit_p (visited, taken_edge->dest->index))
{
jump_thread_edge *x
= new jump_thread_edge (taken_edge, EDGE_NO_COPY_SRC_BLOCK);
path->safe_push (x);
bitmap_set_bit (visited, taken_edge->dest->index);
- *backedge_seen_p |= ((taken_edge->flags & EDGE_DFS_BACK) != 0);
- if (*backedge_seen_p)
- simplify = dummy_simplify;
return thread_around_empty_blocks (taken_edge,
dummy_cond,
avail_exprs_stack,
handle_dominating_asserts,
simplify,
visited,
- path,
- backedge_seen_p);
+ path);
}
}
@@ -786,13 +774,6 @@ thread_around_empty_blocks (edge taken_edge,
&& gimple_code (stmt) != GIMPLE_SWITCH)
return false;
- /* If we have traversed a backedge, then we do not want to look
- at certain expressions in the table that can not be relied upon.
- Luckily the only code that looked at those expressions is the
- SIMPLIFY callback, which we replace if we can no longer use it. */
- if (*backedge_seen_p)
- simplify = dummy_simplify;
-
/* Extract and simplify the condition. */
cond = simplify_control_stmt_condition (taken_edge, stmt,
avail_exprs_stack, dummy_cond,
@@ -805,6 +786,9 @@ thread_around_empty_blocks (edge taken_edge,
{
taken_edge = find_taken_edge (bb, cond);
+ if ((taken_edge->flags & EDGE_DFS_BACK) != 0)
+ return false;
+
if (bitmap_bit_p (visited, taken_edge->dest->index))
return false;
bitmap_set_bit (visited, taken_edge->dest->index);
@@ -812,9 +796,6 @@ thread_around_empty_blocks (edge taken_edge,
jump_thread_edge *x
= new jump_thread_edge (taken_edge, EDGE_NO_COPY_SRC_BLOCK);
path->safe_push (x);
- *backedge_seen_p |= ((taken_edge->flags & EDGE_DFS_BACK) != 0);
- if (*backedge_seen_p)
- simplify = dummy_simplify;
thread_around_empty_blocks (taken_edge,
dummy_cond,
@@ -822,8 +803,7 @@ thread_around_empty_blocks (edge taken_edge,
handle_dominating_asserts,
simplify,
visited,
- path,
- backedge_seen_p);
+ path);
return true;
}
@@ -871,14 +851,8 @@ thread_through_normal_block (edge e,
avail_exprs_stack *avail_exprs_stack,
pfn_simplify simplify,
vec<jump_thread_edge *> *path,
- bitmap visited,
- bool *backedge_seen_p)
+ bitmap visited)
{
- /* If we have seen a backedge, then we rely solely on the FSM threader
- to find jump threads. */
- if (*backedge_seen_p)
- return 0;
-
/* We want to record any equivalences created by traversing E. */
if (!handle_dominating_asserts)
record_temporary_equivalences (e, const_and_copies, avail_exprs_stack);
@@ -948,6 +922,7 @@ thread_through_normal_block (edge e,
address. */
if (dest == NULL
|| dest == e->dest
+ || (taken_edge->flags & EDGE_DFS_BACK) != 0
|| bitmap_bit_p (visited, dest->index))
return 0;
@@ -958,15 +933,11 @@ thread_through_normal_block (edge e,
jump_thread_edge *x
= new jump_thread_edge (e, EDGE_START_JUMP_THREAD);
path->safe_push (x);
- *backedge_seen_p |= ((e->flags & EDGE_DFS_BACK) != 0);
}
jump_thread_edge *x
= new jump_thread_edge (taken_edge, EDGE_COPY_SRC_BLOCK);
path->safe_push (x);
- *backedge_seen_p |= ((taken_edge->flags & EDGE_DFS_BACK) != 0);
- if (*backedge_seen_p)
- simplify = dummy_simplify;
/* See if we can thread through DEST as well, this helps capture
secondary effects of threading without having to re-run DOM or
@@ -982,8 +953,7 @@ thread_through_normal_block (edge e,
handle_dominating_asserts,
simplify,
visited,
- path,
- backedge_seen_p);
+ path);
return 1;
}
}
@@ -993,18 +963,6 @@ thread_through_normal_block (edge e,
/* We are exiting E->src, see if E->dest ends with a conditional
jump which has a known value when reached via E.
- Special care is necessary if E is a back edge in the CFG as we
- may have already recorded equivalences for E->dest into our
- various tables, including the result of the conditional at
- the end of E->dest. Threading opportunities are severely
- limited in that case to avoid short-circuiting the loop
- incorrectly.
-
- Note it is quite common for the first block inside a loop to
- end with a conditional which is either always true or always
- false when reached via the loop backedge. Thus we do not want
- to blindly disable threading across a loop backedge.
-
DUMMY_COND is a shared cond_expr used by condition simplification as scratch,
to avoid allocating memory.
@@ -1029,7 +987,6 @@ thread_across_edge (gcond *dummy_cond,
class avail_exprs_stack *))
{
bitmap visited = BITMAP_ALLOC (NULL);
- bool backedge_seen;
stmt_count = 0;
@@ -1037,16 +994,18 @@ thread_across_edge (gcond *dummy_cond,
bitmap_clear (visited);
bitmap_set_bit (visited, e->src->index);
bitmap_set_bit (visited, e->dest->index);
- backedge_seen = ((e->flags & EDGE_DFS_BACK) != 0);
- if (backedge_seen)
- simplify = dummy_simplify;
-
- int threaded = thread_through_normal_block (e, dummy_cond,
- handle_dominating_asserts,
- const_and_copies,
- avail_exprs_stack,
- simplify, path,
- visited, &backedge_seen);
+
+ int threaded;
+ if ((e->flags & EDGE_DFS_BACK) == 0)
+ threaded = thread_through_normal_block (e, dummy_cond,
+ handle_dominating_asserts,
+ const_and_copies,
+ avail_exprs_stack,
+ simplify, path,
+ visited);
+ else
+ threaded = 0;
+
if (threaded > 0)
{
propagate_threaded_block_debug_into (path->last ()->e->dest,
@@ -1111,6 +1070,13 @@ thread_across_edge (gcond *dummy_cond,
/* Look at each successor of E->dest to see if we can thread through it. */
FOR_EACH_EDGE (taken_edge, ei, e->dest->succs)
{
+ if ((e->flags & EDGE_DFS_BACK) != 0
+ || (taken_edge->flags & EDGE_DFS_BACK) != 0)
+ {
+ find_jump_threads_backwards (taken_edge);
+ continue;
+ }
+
/* Push a fresh marker so we can unwind the equivalences created
for each of E->dest's successors. */
const_and_copies->push_marker ();
@@ -1132,21 +1098,13 @@ thread_across_edge (gcond *dummy_cond,
x = new jump_thread_edge (taken_edge, EDGE_COPY_SRC_JOINER_BLOCK);
path->safe_push (x);
found = false;
- backedge_seen = ((e->flags & EDGE_DFS_BACK) != 0);
- backedge_seen |= ((taken_edge->flags & EDGE_DFS_BACK) != 0);
- if (backedge_seen)
- simplify = dummy_simplify;
found = thread_around_empty_blocks (taken_edge,
dummy_cond,
avail_exprs_stack,
handle_dominating_asserts,
simplify,
visited,
- path,
- &backedge_seen);
-
- if (backedge_seen)
- simplify = dummy_simplify;
+ path);
if (!found)
found = thread_through_normal_block (path->last ()->e, dummy_cond,
@@ -1154,7 +1112,7 @@ thread_across_edge (gcond *dummy_cond,
const_and_copies,
avail_exprs_stack,
simplify, path,
- visited, &backedge_seen) > 0;
+ visited) > 0;
/* If we were able to thread through a successor of E->dest, then
record the jump threading opportunity. */
diff --git a/gcc/tree-ssa-threadupdate.c b/gcc/tree-ssa-threadupdate.c
index 68650e598fe..184cf3402a9 100644
--- a/gcc/tree-ssa-threadupdate.c
+++ b/gcc/tree-ssa-threadupdate.c
@@ -1406,10 +1406,6 @@ ssa_redirect_edges (struct redirection_data **slot,
fprintf (dump_file, " Threaded jump %d --> %d to %d\n",
e->src->index, e->dest->index, rd->dup_blocks[0]->index);
- /* If we redirect a loop latch edge cancel its loop. */
- if (e->src == e->src->loop_father->latch)
- mark_loop_for_removal (e->src->loop_father);
-
/* Redirect the incoming edge (possibly to the joiner block) to the
appropriate duplicate block. */
e2 = redirect_edge_and_branch (e, rd->dup_blocks[0]);
@@ -1630,67 +1626,6 @@ thread_block (basic_block bb, bool noloop_only)
return retval;
}
-
-/* Threads edge E through E->dest to the edge THREAD_TARGET (E). Returns the
- copy of E->dest created during threading, or E->dest if it was not necessary
- to copy it (E is its single predecessor). */
-
-static basic_block
-thread_single_edge (edge e)
-{
- basic_block bb = e->dest;
- struct redirection_data rd;
- vec<jump_thread_edge *> *path = THREAD_PATH (e);
- edge eto = (*path)[1]->e;
-
- delete_jump_thread_path (path);
- e->aux = NULL;
-
- thread_stats.num_threaded_edges++;
-
- if (single_pred_p (bb))
- {
- /* If BB has just a single predecessor, we should only remove the
- control statements at its end, and successors except for ETO. */
- remove_ctrl_stmt_and_useless_edges (bb, eto->dest);
-
- /* And fixup the flags on the single remaining edge. */
- eto->flags &= ~(EDGE_TRUE_VALUE | EDGE_FALSE_VALUE | EDGE_ABNORMAL);
- eto->flags |= EDGE_FALLTHRU;
-
- return bb;
- }
-
- /* Otherwise, we need to create a copy. */
- if (e->dest == eto->src)
- update_bb_profile_for_threading (bb, EDGE_FREQUENCY (e), e->count, eto);
-
- vec<jump_thread_edge *> *npath = new vec<jump_thread_edge *> ();
- jump_thread_edge *x = new jump_thread_edge (e, EDGE_START_JUMP_THREAD);
- npath->safe_push (x);
-
- x = new jump_thread_edge (eto, EDGE_COPY_SRC_BLOCK);
- npath->safe_push (x);
- rd.path = npath;
-
- create_block_for_threading (bb, &rd, 0, NULL);
- remove_ctrl_stmt_and_useless_edges (rd.dup_blocks[0], NULL);
- create_edge_and_update_destination_phis (&rd, rd.dup_blocks[0], 0);
-
- if (dump_file && (dump_flags & TDF_DETAILS))
- fprintf (dump_file, " Threaded jump %d --> %d to %d\n",
- e->src->index, e->dest->index, rd.dup_blocks[0]->index);
-
- rd.dup_blocks[0]->count = e->count;
- rd.dup_blocks[0]->frequency = EDGE_FREQUENCY (e);
- single_succ_edge (rd.dup_blocks[0])->count = e->count;
- redirect_edge_and_branch (e, rd.dup_blocks[0]);
- flush_pending_stmts (e);
-
- delete_jump_thread_path (npath);
- return rd.dup_blocks[0];
-}
-
/* Callback for dfs_enumerate_from. Returns true if BB is different
from STOP and DBDS_CE_STOP. */
@@ -1769,24 +1704,6 @@ determine_bb_domination_status (struct loop *loop, basic_block bb)
return (bb_reachable ? DOMST_DOMINATING : DOMST_LOOP_BROKEN);
}
-/* Return true if BB is part of the new pre-header that is created
- when threading the latch to DATA. */
-
-static bool
-def_split_header_continue_p (const_basic_block bb, const void *data)
-{
- const_basic_block new_header = (const_basic_block) data;
- const struct loop *l;
-
- if (bb == new_header
- || loop_depth (bb->loop_father) < loop_depth (new_header->loop_father))
- return false;
- for (l = bb->loop_father; l; l = loop_outer (l))
- if (l == new_header->loop_father)
- return true;
- return false;
-}
-
/* Thread jumps through the header of LOOP. Returns true if cfg changes.
If MAY_PEEL_LOOP_HEADERS is false, we avoid threading from entry edges
to the inside of the loop. */
@@ -1869,27 +1786,7 @@ thread_through_loop_header (struct loop *loop, bool may_peel_loop_headers)
if (single_succ_p (header))
goto fail;
- /* If we threaded the latch using a joiner block, we cancel the
- threading opportunity out of an abundance of caution. However,
- still allow threading from outside to inside the loop. */
- if (latch->aux)
- {
- vec<jump_thread_edge *> *path = THREAD_PATH (latch);
- if ((*path)[1]->type == EDGE_COPY_SRC_JOINER_BLOCK)
- {
- delete_jump_thread_path (path);
- latch->aux = NULL;
- }
- }
-
- if (latch->aux)
- {
- vec<jump_thread_edge *> *path = THREAD_PATH (latch);
- tgt_edge = (*path)[1]->e;
- tgt_bb = tgt_edge->dest;
- }
- else if (!may_peel_loop_headers
- && !redirection_block_p (loop->header))
+ if (!may_peel_loop_headers && !redirection_block_p (loop->header))
goto fail;
else
{
@@ -1961,96 +1858,34 @@ thread_through_loop_header (struct loop *loop, bool may_peel_loop_headers)
tgt_bb = split_edge (tgt_edge);
}
- if (latch->aux)
- {
- basic_block *bblocks;
- unsigned nblocks, i;
-
- /* First handle the case latch edge is redirected. We are copying
- the loop header but not creating a multiple entry loop. Make the
- cfg manipulation code aware of that fact. */
- set_loop_copy (loop, loop);
- loop->latch = thread_single_edge (latch);
- set_loop_copy (loop, NULL);
- gcc_assert (single_succ (loop->latch) == tgt_bb);
- loop->header = tgt_bb;
-
- /* Remove the new pre-header blocks from our loop. */
- bblocks = XCNEWVEC (basic_block, loop->num_nodes);
- nblocks = dfs_enumerate_from (header, 0, def_split_header_continue_p,
- bblocks, loop->num_nodes, tgt_bb);
- for (i = 0; i < nblocks; i++)
- if (bblocks[i]->loop_father == loop)
- {
- remove_bb_from_loops (bblocks[i]);
- add_bb_to_loop (bblocks[i], loop_outer (loop));
- }
- free (bblocks);
-
- /* If the new header has multiple latches mark it so. */
- FOR_EACH_EDGE (e, ei, loop->header->preds)
- if (e->src->loop_father == loop
- && e->src != loop->latch)
- {
- loop->latch = NULL;
- loops_state_set (LOOPS_MAY_HAVE_MULTIPLE_LATCHES);
- }
-
- /* Cancel remaining threading requests that would make the
- loop a multiple entry loop. */
- FOR_EACH_EDGE (e, ei, header->preds)
- {
- edge e2;
-
- if (e->aux == NULL)
- continue;
+ basic_block new_preheader;
- vec<jump_thread_edge *> *path = THREAD_PATH (e);
- e2 = path->last ()->e;
-
- if (e->src->loop_father != e2->dest->loop_father
- && e2->dest != loop->header)
- {
- delete_jump_thread_path (path);
- e->aux = NULL;
- }
- }
-
- /* Thread the remaining edges through the former header. */
- thread_block (header, false);
- }
- else
+ /* Now consider the case entry edges are redirected to the new entry
+ block. Remember one entry edge, so that we can find the new
+ preheader (its destination after threading). */
+ FOR_EACH_EDGE (e, ei, header->preds)
{
- basic_block new_preheader;
+ if (e->aux)
+ break;
+ }
- /* Now consider the case entry edges are redirected to the new entry
- block. Remember one entry edge, so that we can find the new
- preheader (its destination after threading). */
- FOR_EACH_EDGE (e, ei, header->preds)
- {
- if (e->aux)
- break;
- }
+ /* The duplicate of the header is the new preheader of the loop. Ensure
+ that it is placed correctly in the loop hierarchy. */
+ set_loop_copy (loop, loop_outer (loop));
- /* The duplicate of the header is the new preheader of the loop. Ensure
- that it is placed correctly in the loop hierarchy. */
- set_loop_copy (loop, loop_outer (loop));
-
- thread_block (header, false);
- set_loop_copy (loop, NULL);
- new_preheader = e->dest;
-
- /* Create the new latch block. This is always necessary, as the latch
- must have only a single successor, but the original header had at
- least two successors. */
- loop->latch = NULL;
- mfb_kj_edge = single_succ_edge (new_preheader);
- loop->header = mfb_kj_edge->dest;
- latch = make_forwarder_block (tgt_bb, mfb_keep_just, NULL);
- loop->header = latch->dest;
- loop->latch = latch->src;
- }
+ thread_block (header, false);
+ set_loop_copy (loop, NULL);
+ new_preheader = e->dest;
+ /* Create the new latch block. This is always necessary, as the latch
+ must have only a single successor, but the original header had at
+ least two successors. */
+ loop->latch = NULL;
+ mfb_kj_edge = single_succ_edge (new_preheader);
+ loop->header = mfb_kj_edge->dest;
+ latch = make_forwarder_block (tgt_bb, mfb_keep_just, NULL);
+ loop->header = latch->dest;
+ loop->latch = latch->src;
return true;
fail:
@@ -2332,20 +2167,6 @@ mark_threaded_blocks (bitmap threaded_blocks)
}
-/* Return TRUE if BB ends with a switch statement or a computed goto.
- Otherwise return false. */
-static bool
-bb_ends_with_multiway_branch (basic_block bb ATTRIBUTE_UNUSED)
-{
- gimple *stmt = last_stmt (bb);
- if (stmt && gimple_code (stmt) == GIMPLE_SWITCH)
- return true;
- if (stmt && gimple_code (stmt) == GIMPLE_GOTO
- && TREE_CODE (gimple_goto_dest (stmt)) == SSA_NAME)
- return true;
- return false;
-}
-
/* Verify that the REGION is a valid jump thread. A jump thread is a special
case of SEME Single Entry Multiple Exits region in which all nodes in the
REGION have exactly one incoming edge. The only exception is the first block
@@ -2788,36 +2609,7 @@ thread_through_all_blocks (bool may_peel_loop_headers)
e->aux = NULL;
ei_next (&ei);
}
- else if (bb_ends_with_multiway_branch (path->last ()->e->src))
- {
- /* The code to thread through loop headers may have
- split a block with jump threads attached to it.
-
- We can identify this with a disjoint jump threading
- path. If found, just remove it. */
- for (unsigned int i = 0; i < path->length () - 1; i++)
- if ((*path)[i]->e->dest != (*path)[i + 1]->e->src)
- {
- delete_jump_thread_path (path);
- e->aux = NULL;
- ei_next (&ei);
- break;
- }
-
- /* Our path is still valid, thread it. */
- if (e->aux)
- {
- if (thread_block ((*path)[0]->e->dest, false))
- e->aux = NULL;
- else
- {
- delete_jump_thread_path (path);
- e->aux = NULL;
- ei_next (&ei);
- }
- }
- }
- else
+ else
{
delete_jump_thread_path (path);
e->aux = NULL;
@@ -2878,18 +2670,26 @@ register_jump_thread (vec<jump_thread_edge *> *path)
/* First make sure there are no NULL outgoing edges on the jump threading
path. That can happen for jumping to a constant address. */
for (unsigned int i = 0; i < path->length (); i++)
- if ((*path)[i]->e == NULL)
- {
- if (dump_file && (dump_flags & TDF_DETAILS))
- {
- fprintf (dump_file,
- "Found NULL edge in jump threading path. Cancelling jump thread:\n");
- dump_jump_thread_path (dump_file, *path, false);
- }
+ {
+ if ((*path)[i]->e == NULL)
+ {
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ {
+ fprintf (dump_file,
+ "Found NULL edge in jump threading path. Cancelling jump thread:\n");
+ dump_jump_thread_path (dump_file, *path, false);
+ }
- delete_jump_thread_path (path);
- return;
- }
+ delete_jump_thread_path (path);
+ return;
+ }
+
+ /* Only the FSM threader is allowed to thread across
+ backedges in the CFG. */
+ if (flag_checking
+ && (*path)[0]->type != EDGE_FSM_THREAD)
+ gcc_assert (((*path)[i]->e->flags & EDGE_DFS_BACK) == 0);
+ }
if (dump_file && (dump_flags & TDF_DETAILS))
dump_jump_thread_path (dump_file, *path, true);
diff --git a/gcc/tree-ssanames.c b/gcc/tree-ssanames.c
index 12235f6a902..096b75b10e0 100644
--- a/gcc/tree-ssanames.c
+++ b/gcc/tree-ssanames.c
@@ -114,6 +114,133 @@ ssanames_print_statistics (void)
fprintf (stderr, "SSA_NAME nodes reused: %u\n", ssa_name_nodes_reused);
}
+/* Verify the state of the SSA_NAME lists.
+
+ There must be no duplicates on the free list.
+ Every name on the free list must be marked as on the free list.
+ Any name on the free list must not appear in the IL.
+ No names can be leaked. */
+
+DEBUG_FUNCTION void
+verify_ssaname_freelists (struct function *fun)
+{
+ /* Do nothing if we are in RTL format. */
+ basic_block bb;
+ FOR_EACH_BB_FN (bb, fun)
+ {
+ if (bb->flags & BB_RTL)
+ return;
+ }
+
+ bitmap names_in_il = BITMAP_ALLOC (NULL);
+
+ /* Walk the entire IL noting every SSA_NAME we see. */
+ FOR_EACH_BB_FN (bb, fun)
+ {
+ tree t;
+ /* First note the result and arguments of PHI nodes. */
+ for (gphi_iterator gsi = gsi_start_phis (bb);
+ !gsi_end_p (gsi);
+ gsi_next (&gsi))
+ {
+ gphi *phi = gsi.phi ();
+ t = gimple_phi_result (phi);
+ bitmap_set_bit (names_in_il, SSA_NAME_VERSION (t));
+
+ for (unsigned int i = 0; i < gimple_phi_num_args (phi); i++)
+ {
+ t = gimple_phi_arg_def (phi, i);
+ if (TREE_CODE (t) == SSA_NAME)
+ bitmap_set_bit (names_in_il, SSA_NAME_VERSION (t));
+ }
+ }
+
+ /* Then note the operands of each statement. */
+ for (gimple_stmt_iterator gsi = gsi_start_bb (bb);
+ !gsi_end_p (gsi);
+ gsi_next (&gsi))
+ {
+ ssa_op_iter iter;
+ gimple *stmt = gsi_stmt (gsi);
+ FOR_EACH_SSA_TREE_OPERAND (t, stmt, iter, SSA_OP_ALL_OPERANDS)
+ if (TREE_CODE (t) == SSA_NAME)
+ bitmap_set_bit (names_in_il, SSA_NAME_VERSION (t));
+ }
+ }
+
+ /* Now walk the free list noting what we find there and verifying
+ there are no duplicates. */
+ bitmap names_in_freelists = BITMAP_ALLOC (NULL);
+ if (FREE_SSANAMES (fun))
+ {
+ for (unsigned int i = 0; i < FREE_SSANAMES (fun)->length (); i++)
+ {
+ tree t = (*FREE_SSANAMES (fun))[i];
+
+ /* Verify that the name is marked as being in the free list. */
+ gcc_assert (SSA_NAME_IN_FREE_LIST (t));
+
+ /* Verify the name has not already appeared in the free list and
+ note it in the list of names found in the free list. */
+ gcc_assert (!bitmap_bit_p (names_in_freelists, SSA_NAME_VERSION (t)));
+ bitmap_set_bit (names_in_freelists, SSA_NAME_VERSION (t));
+ }
+ }
+
+ /* Similarly for the names in the pending free list. */
+ if (FREE_SSANAMES_QUEUE (fun))
+ {
+ for (unsigned int i = 0; i < FREE_SSANAMES_QUEUE (fun)->length (); i++)
+ {
+ tree t = (*FREE_SSANAMES_QUEUE (fun))[i];
+
+ /* Verify that the name is marked as being in the free list. */
+ gcc_assert (SSA_NAME_IN_FREE_LIST (t));
+
+ /* Verify the name has not already appeared in the free list and
+ note it in the list of names found in the free list. */
+ gcc_assert (!bitmap_bit_p (names_in_freelists, SSA_NAME_VERSION (t)));
+ bitmap_set_bit (names_in_freelists, SSA_NAME_VERSION (t));
+ }
+ }
+
+ /* If any name appears in both the IL and the freelists, then
+ something horrible has happened. */
+ bool intersect_p = bitmap_intersect_p (names_in_il, names_in_freelists);
+ gcc_assert (!intersect_p);
+
+ /* Names can be queued up for release if there is an ssa update
+ pending. Pretend we saw them in the IL. */
+ if (names_to_release)
+ bitmap_ior_into (names_in_il, names_to_release);
+
+ /* Function splitting can "lose" SSA_NAMEs in an effort to ensure that
+ debug/non-debug compilations have the same SSA_NAMEs. So for each
+ lost SSA_NAME, see if it's likely one from that wart. These will always
+ be marked as default definitions. So we loosely assume that anything
+ marked as a default definition isn't leaked by pretening they are
+ in the IL. */
+ for (unsigned int i = UNUSED_NAME_VERSION + 1; i < num_ssa_names; i++)
+ if (ssa_name (i) && SSA_NAME_IS_DEFAULT_DEF (ssa_name (i)))
+ bitmap_set_bit (names_in_il, i);
+
+ unsigned int i;
+ bitmap_iterator bi;
+ bitmap all_names = BITMAP_ALLOC (NULL);
+ bitmap_set_range (all_names, UNUSED_NAME_VERSION + 1, num_ssa_names - 1);
+ bitmap_ior_into (names_in_il, names_in_freelists);
+
+ /* Any name not mentioned in the IL and not in the feelists
+ has been leaked. */
+ EXECUTE_IF_AND_COMPL_IN_BITMAP(all_names, names_in_il,
+ UNUSED_NAME_VERSION + 1, i, bi)
+ gcc_assert (!ssa_name (i));
+
+ BITMAP_FREE (all_names);
+ BITMAP_FREE (names_in_freelists);
+ BITMAP_FREE (names_in_il);
+}
+
/* Move all SSA_NAMEs from FREE_SSA_NAMES_QUEUE to FREE_SSA_NAMES.
We do not, but should have a mode to verify the state of the SSA_NAMEs
@@ -604,6 +731,42 @@ replace_ssa_name_symbol (tree ssa_name, tree sym)
TREE_TYPE (ssa_name) = TREE_TYPE (sym);
}
+/* Release the vector of free SSA_NAMEs and compact the the
+ vector of SSA_NAMEs that are live. */
+
+static void
+release_free_names_and_compact_live_names (function *fun)
+{
+ unsigned i, j;
+ int n = vec_safe_length (FREE_SSANAMES (fun));
+
+ /* Now release the freelist. */
+ vec_free (FREE_SSANAMES (fun));
+
+ /* And compact the SSA number space. We make sure to not change the
+ relative order of SSA versions. */
+ for (i = 1, j = 1; i < fun->gimple_df->ssa_names->length (); ++i)
+ {
+ tree name = ssa_name (i);
+ if (name)
+ {
+ if (i != j)
+ {
+ SSA_NAME_VERSION (name) = j;
+ (*fun->gimple_df->ssa_names)[j] = name;
+ }
+ j++;
+ }
+ }
+ fun->gimple_df->ssa_names->truncate (j);
+
+ statistics_counter_event (fun, "SSA names released", n);
+ statistics_counter_event (fun, "SSA name holes removed", i - j);
+ if (dump_file)
+ fprintf (dump_file, "Released %i names, %.2f%%, removed %i holes\n",
+ n, n * 100.0 / num_ssa_names, i - j);
+}
+
/* Return SSA names that are unused to GGC memory and compact the SSA
version namespace. This is used to keep footprint of compiler during
interprocedural optimization. */
@@ -638,34 +801,7 @@ public:
unsigned int
pass_release_ssa_names::execute (function *fun)
{
- unsigned i, j;
- int n = vec_safe_length (FREE_SSANAMES (fun));
-
- /* Now release the freelist. */
- vec_free (FREE_SSANAMES (fun));
-
- /* And compact the SSA number space. We make sure to not change the
- relative order of SSA versions. */
- for (i = 1, j = 1; i < fun->gimple_df->ssa_names->length (); ++i)
- {
- tree name = ssa_name (i);
- if (name)
- {
- if (i != j)
- {
- SSA_NAME_VERSION (name) = j;
- (*fun->gimple_df->ssa_names)[j] = name;
- }
- j++;
- }
- }
- fun->gimple_df->ssa_names->truncate (j);
-
- statistics_counter_event (fun, "SSA names released", n);
- statistics_counter_event (fun, "SSA name holes removed", i - j);
- if (dump_file)
- fprintf (dump_file, "Released %i names, %.2f%%, removed %i holes\n",
- n, n * 100.0 / num_ssa_names, i - j);
+ release_free_names_and_compact_live_names (fun);
return 0;
}
diff --git a/gcc/tree-streamer-in.c b/gcc/tree-streamer-in.c
index 0dca02ece51..7417eaf81e7 100644
--- a/gcc/tree-streamer-in.c
+++ b/gcc/tree-streamer-in.c
@@ -136,9 +136,14 @@ unpack_ts_base_value_fields (struct bitpack_d *bp, tree expr)
TREE_DEPRECATED (expr) = (unsigned) bp_unpack_value (bp, 1);
if (TYPE_P (expr))
{
- TYPE_SATURATING (expr) = (unsigned) bp_unpack_value (bp, 1);
+ if (AGGREGATE_TYPE_P (expr))
+ TYPE_REVERSE_STORAGE_ORDER (expr) = (unsigned) bp_unpack_value (bp, 1);
+ else
+ TYPE_SATURATING (expr) = (unsigned) bp_unpack_value (bp, 1);
TYPE_ADDR_SPACE (expr) = (unsigned) bp_unpack_value (bp, 8);
}
+ else if (TREE_CODE (expr) == BIT_FIELD_REF || TREE_CODE (expr) == MEM_REF)
+ REF_REVERSE_STORAGE_ORDER (expr) = (unsigned) bp_unpack_value (bp, 1);
else if (TREE_CODE (expr) == SSA_NAME)
{
SSA_NAME_IS_DEFAULT_DEF (expr) = (unsigned) bp_unpack_value (bp, 1);
diff --git a/gcc/tree-streamer-out.c b/gcc/tree-streamer-out.c
index 7e1c34bc609..9ca02719a19 100644
--- a/gcc/tree-streamer-out.c
+++ b/gcc/tree-streamer-out.c
@@ -110,9 +110,14 @@ pack_ts_base_value_fields (struct bitpack_d *bp, tree expr)
bp_pack_value (bp, TREE_DEPRECATED (expr), 1);
if (TYPE_P (expr))
{
- bp_pack_value (bp, TYPE_SATURATING (expr), 1);
+ if (AGGREGATE_TYPE_P (expr))
+ bp_pack_value (bp, TYPE_REVERSE_STORAGE_ORDER (expr), 1);
+ else
+ bp_pack_value (bp, TYPE_SATURATING (expr), 1);
bp_pack_value (bp, TYPE_ADDR_SPACE (expr), 8);
}
+ else if (TREE_CODE (expr) == BIT_FIELD_REF || TREE_CODE (expr) == MEM_REF)
+ bp_pack_value (bp, REF_REVERSE_STORAGE_ORDER (expr), 1);
else if (TREE_CODE (expr) == SSA_NAME)
{
bp_pack_value (bp, SSA_NAME_IS_DEFAULT_DEF (expr), 1);
diff --git a/gcc/tree-vect-data-refs.c b/gcc/tree-vect-data-refs.c
index 3de71fb3094..11bce795a5e 100644
--- a/gcc/tree-vect-data-refs.c
+++ b/gcc/tree-vect-data-refs.c
@@ -3027,7 +3027,7 @@ vect_check_gather_scatter (gimple *stmt, loop_vec_info loop_vinfo, tree *basep,
tree offtype = NULL_TREE;
tree decl, base, off;
machine_mode pmode;
- int punsignedp, pvolatilep;
+ int punsignedp, reversep, pvolatilep = 0;
base = DR_REF (dr);
/* For masked loads/stores, DR_REF (dr) is an artificial MEM_REF,
@@ -3059,9 +3059,9 @@ vect_check_gather_scatter (gimple *stmt, loop_vec_info loop_vinfo, tree *basep,
vectorized. The following code attempts to find such a preexistng
SSA_NAME OFF and put the loop invariants into a tree BASE
that can be gimplified before the loop. */
- base = get_inner_reference (base, &pbitsize, &pbitpos, &off,
- &pmode, &punsignedp, &pvolatilep, false);
- gcc_assert (base != NULL_TREE && (pbitpos % BITS_PER_UNIT) == 0);
+ base = get_inner_reference (base, &pbitsize, &pbitpos, &off, &pmode,
+ &punsignedp, &reversep, &pvolatilep, false);
+ gcc_assert (base && (pbitpos % BITS_PER_UNIT) == 0 && !reversep);
if (TREE_CODE (base) == MEM_REF)
{
@@ -3515,7 +3515,7 @@ again:
HOST_WIDE_INT pbitsize, pbitpos;
tree poffset;
machine_mode pmode;
- int punsignedp, pvolatilep;
+ int punsignedp, preversep, pvolatilep;
affine_iv base_iv, offset_iv;
tree dinit;
@@ -3534,7 +3534,8 @@ again:
}
outer_base = get_inner_reference (inner_base, &pbitsize, &pbitpos,
- &poffset, &pmode, &punsignedp, &pvolatilep, false);
+ &poffset, &pmode, &punsignedp,
+ &preversep, &pvolatilep, false);
gcc_assert (outer_base != NULL_TREE);
if (pbitpos % BITS_PER_UNIT != 0)
@@ -3545,6 +3546,14 @@ again:
return false;
}
+ if (preversep)
+ {
+ if (dump_enabled_p ())
+ dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
+ "failed: reverse storage order.\n");
+ return false;
+ }
+
outer_base = build_fold_addr_expr (outer_base);
if (!simple_iv (loop, loop_containing_stmt (stmt), outer_base,
&base_iv, false))
diff --git a/gcc/tree-vect-patterns.c b/gcc/tree-vect-patterns.c
index f1de690f89c..d003d335f5d 100644
--- a/gcc/tree-vect-patterns.c
+++ b/gcc/tree-vect-patterns.c
@@ -107,27 +107,7 @@ static bool
vect_same_loop_or_bb_p (gimple *stmt1, gimple *stmt2)
{
stmt_vec_info stmt_vinfo = vinfo_for_stmt (stmt1);
- loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_vinfo);
- bb_vec_info bb_vinfo = STMT_VINFO_BB_VINFO (stmt_vinfo);
-
- if (!gimple_bb (stmt2))
- return false;
-
- if (loop_vinfo)
- {
- struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
- if (!flow_bb_inside_loop_p (loop, gimple_bb (stmt2)))
- return false;
- }
- else
- {
- if (gimple_bb (stmt2) != BB_VINFO_BB (bb_vinfo)
- || gimple_code (stmt2) == GIMPLE_PHI)
- return false;
- }
-
- gcc_assert (vinfo_for_stmt (stmt2));
- return true;
+ return vect_stmt_in_region_p (stmt_vinfo->vinfo, stmt2);
}
/* If the LHS of DEF_STMT has a single use, and that statement is
@@ -3611,33 +3591,42 @@ vect_pattern_recog (vec_info *vinfo)
loop = LOOP_VINFO_LOOP (loop_vinfo);
bbs = LOOP_VINFO_BBS (loop_vinfo);
nbbs = loop->num_nodes;
+
+ /* Scan through the loop stmts, applying the pattern recognition
+ functions starting at each stmt visited: */
+ for (i = 0; i < nbbs; i++)
+ {
+ basic_block bb = bbs[i];
+ for (si = gsi_start_bb (bb); !gsi_end_p (si); gsi_next (&si))
+ {
+ /* Scan over all generic vect_recog_xxx_pattern functions. */
+ for (j = 0; j < NUM_PATTERNS; j++)
+ {
+ vect_recog_func = vect_vect_recog_func_ptrs[j];
+ vect_pattern_recog_1 (vect_recog_func, si,
+ &stmts_to_replace);
+ }
+ }
+ }
}
else
{
- bbs = &as_a <bb_vec_info> (vinfo)->bb;
- nbbs = 1;
- }
-
- /* Scan through the loop stmts, applying the pattern recognition
- functions starting at each stmt visited: */
- for (i = 0; i < nbbs; i++)
- {
- basic_block bb = bbs[i];
- for (si = gsi_start_bb (bb); !gsi_end_p (si); gsi_next (&si))
- {
- if (is_a <bb_vec_info> (vinfo)
- && (stmt = gsi_stmt (si))
+ bb_vec_info bb_vinfo = as_a <bb_vec_info> (vinfo);
+ for (si = bb_vinfo->region_begin;
+ gsi_stmt (si) != gsi_stmt (bb_vinfo->region_end); gsi_next (&si))
+ {
+ if ((stmt = gsi_stmt (si))
&& vinfo_for_stmt (stmt)
&& !STMT_VINFO_VECTORIZABLE (vinfo_for_stmt (stmt)))
- continue;
+ continue;
- /* Scan over all generic vect_recog_xxx_pattern functions. */
- for (j = 0; j < NUM_PATTERNS; j++)
- {
+ /* Scan over all generic vect_recog_xxx_pattern functions. */
+ for (j = 0; j < NUM_PATTERNS; j++)
+ {
vect_recog_func = vect_vect_recog_func_ptrs[j];
vect_pattern_recog_1 (vect_recog_func, si,
&stmts_to_replace);
- }
- }
+ }
+ }
}
}
diff --git a/gcc/tree-vect-slp.c b/gcc/tree-vect-slp.c
index 35808eb9c8a..cfdfc2936a1 100644
--- a/gcc/tree-vect-slp.c
+++ b/gcc/tree-vect-slp.c
@@ -209,7 +209,6 @@ vect_get_and_check_slp_defs (vec_info *vinfo,
unsigned int i, number_of_oprnds;
gimple *def_stmt;
enum vect_def_type dt = vect_uninitialized_def;
- struct loop *loop = NULL;
bool pattern = false;
slp_oprnd_info oprnd_info;
int first_op_idx = 1;
@@ -218,9 +217,6 @@ vect_get_and_check_slp_defs (vec_info *vinfo,
bool first = stmt_num == 0;
bool second = stmt_num == 1;
- if (is_a <loop_vec_info> (vinfo))
- loop = LOOP_VINFO_LOOP (as_a <loop_vec_info> (vinfo));
-
if (is_gimple_call (stmt))
{
number_of_oprnds = gimple_call_num_args (stmt);
@@ -276,11 +272,7 @@ again:
from the pattern. Check that all the stmts of the node are in the
pattern. */
if (def_stmt && gimple_bb (def_stmt)
- && ((is_a <loop_vec_info> (vinfo)
- && flow_bb_inside_loop_p (loop, gimple_bb (def_stmt)))
- || (is_a <bb_vec_info> (vinfo)
- && gimple_bb (def_stmt) == as_a <bb_vec_info> (vinfo)->bb
- && gimple_code (def_stmt) != GIMPLE_PHI))
+ && vect_stmt_in_region_p (vinfo, def_stmt)
&& vinfo_for_stmt (def_stmt)
&& STMT_VINFO_IN_PATTERN_P (vinfo_for_stmt (def_stmt))
&& !STMT_VINFO_RELEVANT (vinfo_for_stmt (def_stmt))
@@ -2076,16 +2068,21 @@ vect_detect_hybrid_slp (loop_vec_info loop_vinfo)
stmt_vec_info structs for all the stmts in it. */
static bb_vec_info
-new_bb_vec_info (basic_block bb)
+new_bb_vec_info (gimple_stmt_iterator region_begin,
+ gimple_stmt_iterator region_end)
{
+ basic_block bb = gsi_bb (region_begin);
bb_vec_info res = NULL;
gimple_stmt_iterator gsi;
res = (bb_vec_info) xcalloc (1, sizeof (struct _bb_vec_info));
res->kind = vec_info::bb;
BB_VINFO_BB (res) = bb;
+ res->region_begin = region_begin;
+ res->region_end = region_end;
- for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
+ for (gsi = region_begin; gsi_stmt (gsi) != gsi_stmt (region_end);
+ gsi_next (&gsi))
{
gimple *stmt = gsi_stmt (gsi);
gimple_set_uid (stmt, 0);
@@ -2118,7 +2115,8 @@ destroy_bb_vec_info (bb_vec_info bb_vinfo)
bb = BB_VINFO_BB (bb_vinfo);
- for (si = gsi_start_bb (bb); !gsi_end_p (si); gsi_next (&si))
+ for (si = bb_vinfo->region_begin;
+ gsi_stmt (si) != gsi_stmt (bb_vinfo->region_end); gsi_next (&si))
{
gimple *stmt = gsi_stmt (si);
stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
@@ -2126,6 +2124,9 @@ destroy_bb_vec_info (bb_vec_info bb_vinfo)
if (stmt_info)
/* Free stmt_vec_info. */
free_stmt_vec_info (stmt);
+
+ /* Reset region marker. */
+ gimple_set_uid (stmt, -1);
}
vect_destroy_datarefs (bb_vinfo);
@@ -2247,8 +2248,8 @@ vect_bb_slp_scalar_cost (basic_block bb,
gimple *use_stmt;
FOR_EACH_IMM_USE_STMT (use_stmt, use_iter, DEF_FROM_PTR (def_p))
if (!is_gimple_debug (use_stmt)
- && (gimple_code (use_stmt) == GIMPLE_PHI
- || gimple_bb (use_stmt) != bb
+ && (! vect_stmt_in_region_p (vinfo_for_stmt (stmt)->vinfo,
+ use_stmt)
|| !STMT_VINFO_VECTORIZABLE (vinfo_for_stmt (use_stmt))))
{
(*life)[i] = true;
@@ -2327,40 +2328,31 @@ vect_bb_vectorization_profitable_p (bb_vec_info bb_vinfo)
/* Check if the basic block can be vectorized. */
static bb_vec_info
-vect_slp_analyze_bb_1 (basic_block bb)
+vect_slp_analyze_bb_1 (gimple_stmt_iterator region_begin,
+ gimple_stmt_iterator region_end,
+ vec<data_reference_p> datarefs, int n_stmts)
{
bb_vec_info bb_vinfo;
vec<slp_instance> slp_instances;
slp_instance instance;
int i;
int min_vf = 2;
- unsigned n_stmts = 0;
- bb_vinfo = new_bb_vec_info (bb);
+ if (n_stmts > PARAM_VALUE (PARAM_SLP_MAX_INSNS_IN_BB))
+ {
+ if (dump_enabled_p ())
+ dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
+ "not vectorized: too many instructions in "
+ "basic block.\n");
+ free_data_refs (datarefs);
+ return NULL;
+ }
+
+ bb_vinfo = new_bb_vec_info (region_begin, region_end);
if (!bb_vinfo)
return NULL;
- /* Gather all data references in the basic-block. */
-
- for (gimple_stmt_iterator gsi = gsi_start_bb (bb);
- !gsi_end_p (gsi); gsi_next (&gsi))
- {
- gimple *stmt = gsi_stmt (gsi);
- if (is_gimple_debug (stmt))
- continue;
- ++n_stmts;
- if (!find_data_references_in_stmt (NULL, stmt,
- &BB_VINFO_DATAREFS (bb_vinfo)))
- {
- /* Mark the rest of the basic-block as unvectorizable. */
- for (; !gsi_end_p (gsi); gsi_next (&gsi))
- {
- stmt = gsi_stmt (gsi);
- STMT_VINFO_VECTORIZABLE (vinfo_for_stmt (stmt)) = false;
- }
- break;
- }
- }
+ BB_VINFO_DATAREFS (bb_vinfo) = datarefs;
/* Analyze the data references. */
@@ -2438,8 +2430,8 @@ vect_slp_analyze_bb_1 (basic_block bb)
}
/* Mark all the statements that we do not want to vectorize. */
- for (gimple_stmt_iterator gsi = gsi_start_bb (BB_VINFO_BB (bb_vinfo));
- !gsi_end_p (gsi); gsi_next (&gsi))
+ for (gimple_stmt_iterator gsi = bb_vinfo->region_begin;
+ gsi_stmt (gsi) != gsi_stmt (bb_vinfo->region_end); gsi_next (&gsi))
{
stmt_vec_info vinfo = vinfo_for_stmt (gsi_stmt (gsi));
if (STMT_SLP_TYPE (vinfo) != pure_slp)
@@ -2509,77 +2501,105 @@ bool
vect_slp_bb (basic_block bb)
{
bb_vec_info bb_vinfo;
- int insns = 0;
gimple_stmt_iterator gsi;
unsigned int vector_sizes;
+ bool any_vectorized = false;
if (dump_enabled_p ())
dump_printf_loc (MSG_NOTE, vect_location, "===vect_slp_analyze_bb===\n");
- for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
- {
- gimple *stmt = gsi_stmt (gsi);
- if (!is_gimple_debug (stmt)
- && !gimple_nop_p (stmt)
- && gimple_code (stmt) != GIMPLE_LABEL)
- insns++;
- if (gimple_location (stmt) != UNKNOWN_LOCATION)
- vect_location = gimple_location (stmt);
- }
-
- if (insns > PARAM_VALUE (PARAM_SLP_MAX_INSNS_IN_BB))
- {
- if (dump_enabled_p ())
- dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
- "not vectorized: too many instructions in "
- "basic block.\n");
-
- return false;
- }
-
/* Autodetect first vector size we try. */
current_vector_size = 0;
vector_sizes = targetm.vectorize.autovectorize_vector_sizes ();
+ gsi = gsi_start_bb (bb);
+
while (1)
{
- bb_vinfo = vect_slp_analyze_bb_1 (bb);
- if (bb_vinfo)
+ if (gsi_end_p (gsi))
+ break;
+
+ gimple_stmt_iterator region_begin = gsi;
+ vec<data_reference_p> datarefs = vNULL;
+ int insns = 0;
+
+ for (; !gsi_end_p (gsi); gsi_next (&gsi))
{
- if (!dbg_cnt (vect_slp))
- {
- destroy_bb_vec_info (bb_vinfo);
- return false;
- }
+ gimple *stmt = gsi_stmt (gsi);
+ if (is_gimple_debug (stmt))
+ continue;
+ insns++;
+
+ if (gimple_location (stmt) != UNKNOWN_LOCATION)
+ vect_location = gimple_location (stmt);
+
+ if (!find_data_references_in_stmt (NULL, stmt, &datarefs))
+ break;
+ }
+
+ /* Skip leading unhandled stmts. */
+ if (gsi_stmt (region_begin) == gsi_stmt (gsi))
+ {
+ gsi_next (&gsi);
+ continue;
+ }
+ gimple_stmt_iterator region_end = gsi;
+
+ bool vectorized = false;
+ bb_vinfo = vect_slp_analyze_bb_1 (region_begin, region_end,
+ datarefs, insns);
+ if (bb_vinfo
+ && dbg_cnt (vect_slp))
+ {
if (dump_enabled_p ())
- dump_printf_loc (MSG_NOTE, vect_location, "SLPing BB\n");
+ dump_printf_loc (MSG_NOTE, vect_location, "SLPing BB part\n");
vect_schedule_slp (bb_vinfo);
if (dump_enabled_p ())
dump_printf_loc (MSG_NOTE, vect_location,
- "BASIC BLOCK VECTORIZED\n");
+ "basic block part vectorized\n");
destroy_bb_vec_info (bb_vinfo);
- return true;
+ vectorized = true;
}
+ else
+ destroy_bb_vec_info (bb_vinfo);
- destroy_bb_vec_info (bb_vinfo);
+ any_vectorized |= vectorized;
vector_sizes &= ~current_vector_size;
- if (vector_sizes == 0
- || current_vector_size == 0)
- return false;
+ if (vectorized
+ || vector_sizes == 0
+ || current_vector_size == 0)
+ {
+ if (gsi_end_p (region_end))
+ break;
- /* Try the next biggest vector size. */
- current_vector_size = 1 << floor_log2 (vector_sizes);
- if (dump_enabled_p ())
- dump_printf_loc (MSG_NOTE, vect_location,
- "***** Re-trying analysis with "
- "vector size %d\n", current_vector_size);
+ /* Skip the unhandled stmt. */
+ gsi_next (&gsi);
+
+ /* And reset vector sizes. */
+ current_vector_size = 0;
+ vector_sizes = targetm.vectorize.autovectorize_vector_sizes ();
+ }
+ else
+ {
+ /* Try the next biggest vector size. */
+ current_vector_size = 1 << floor_log2 (vector_sizes);
+ if (dump_enabled_p ())
+ dump_printf_loc (MSG_NOTE, vect_location,
+ "***** Re-trying analysis with "
+ "vector size %d\n", current_vector_size);
+
+ /* Start over. */
+ gsi = region_begin;
+ }
}
+
+ return any_vectorized;
}
diff --git a/gcc/tree-vect-stmts.c b/gcc/tree-vect-stmts.c
index 378973bb8c5..51dff9eb19e 100644
--- a/gcc/tree-vect-stmts.c
+++ b/gcc/tree-vect-stmts.c
@@ -4703,7 +4703,26 @@ vectorizable_operation (gimple *stmt, gimple_stmt_iterator *gsi,
/* If op0 is an external or constant def use a vector type with
the same size as the output vector type. */
if (!vectype)
- vectype = get_same_sized_vectype (TREE_TYPE (op0), vectype_out);
+ {
+ /* For boolean type we cannot determine vectype by
+ invariant value (don't know whether it is a vector
+ of booleans or vector of integers). We use output
+ vectype because operations on boolean don't change
+ type. */
+ if (TREE_CODE (TREE_TYPE (op0)) == BOOLEAN_TYPE)
+ {
+ if (TREE_CODE (TREE_TYPE (scalar_dest)) != BOOLEAN_TYPE)
+ {
+ if (dump_enabled_p ())
+ dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
+ "not supported operation on bool value.\n");
+ return false;
+ }
+ vectype = vectype_out;
+ }
+ else
+ vectype = get_same_sized_vectype (TREE_TYPE (op0), vectype_out);
+ }
if (vec_stmt)
gcc_assert (vectype);
if (!vectype)
@@ -8141,12 +8160,7 @@ vect_is_simple_use (tree operand, vec_info *vinfo,
dump_gimple_stmt (MSG_NOTE, TDF_SLIM, *def_stmt, 0);
}
- basic_block bb = gimple_bb (*def_stmt);
- if ((is_a <loop_vec_info> (vinfo)
- && !flow_bb_inside_loop_p (as_a <loop_vec_info> (vinfo)->loop, bb))
- || (is_a <bb_vec_info> (vinfo)
- && (bb != as_a <bb_vec_info> (vinfo)->bb
- || gimple_code (*def_stmt) == GIMPLE_PHI)))
+ if (! vect_stmt_in_region_p (vinfo, *def_stmt))
*dt = vect_external_def;
else
{
diff --git a/gcc/tree-vectorizer.c b/gcc/tree-vectorizer.c
index 7b3d9a331a9..41e87a8d9bd 100644
--- a/gcc/tree-vectorizer.c
+++ b/gcc/tree-vectorizer.c
@@ -350,6 +350,33 @@ vect_destroy_datarefs (vec_info *vinfo)
}
+/* Return whether STMT is inside the region we try to vectorize. */
+
+bool
+vect_stmt_in_region_p (vec_info *vinfo, gimple *stmt)
+{
+ if (!gimple_bb (stmt))
+ return false;
+
+ if (loop_vec_info loop_vinfo = dyn_cast <loop_vec_info> (vinfo))
+ {
+ struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
+ if (!flow_bb_inside_loop_p (loop, gimple_bb (stmt)))
+ return false;
+ }
+ else
+ {
+ bb_vec_info bb_vinfo = as_a <bb_vec_info> (vinfo);
+ if (gimple_bb (stmt) != BB_VINFO_BB (bb_vinfo)
+ || gimple_uid (stmt) == -1U
+ || gimple_code (stmt) == GIMPLE_PHI)
+ return false;
+ }
+
+ return true;
+}
+
+
/* If LOOP has been versioned during ifcvt, return the internal call
guarding it. */
@@ -692,6 +719,14 @@ pass_slp_vectorize::execute (function *fun)
scev_initialize ();
}
+ /* Mark all stmts as not belonging to the current region. */
+ FOR_EACH_BB_FN (bb, fun)
+ {
+ for (gimple_stmt_iterator gsi = gsi_start_bb (bb); !gsi_end_p (gsi);
+ gsi_next (&gsi))
+ gimple_set_uid (gsi_stmt (gsi), -1);
+ }
+
init_stmt_vec_info_vec ();
FOR_EACH_BB_FN (bb, fun)
diff --git a/gcc/tree-vectorizer.h b/gcc/tree-vectorizer.h
index f77a4eb4313..9cde091bde9 100644
--- a/gcc/tree-vectorizer.h
+++ b/gcc/tree-vectorizer.h
@@ -390,6 +390,8 @@ nested_in_vect_loop_p (struct loop *loop, gimple *stmt)
typedef struct _bb_vec_info : public vec_info
{
basic_block bb;
+ gimple_stmt_iterator region_begin;
+ gimple_stmt_iterator region_end;
} *bb_vec_info;
#define BB_VINFO_BB(B) (B)->bb
@@ -1085,5 +1087,6 @@ void vect_pattern_recog (vec_info *);
/* In tree-vectorizer.c. */
unsigned vectorize_loops (void);
void vect_destroy_datarefs (vec_info *);
+bool vect_stmt_in_region_p (vec_info *, gimple *);
#endif /* GCC_TREE_VECTORIZER_H */
diff --git a/gcc/tree-vrp.c b/gcc/tree-vrp.c
index c0b6cfc1444..87c02654c48 100644
--- a/gcc/tree-vrp.c
+++ b/gcc/tree-vrp.c
@@ -10076,9 +10076,9 @@ identify_jump_threads (void)
mark_dfs_back_edges ();
/* Do not thread across edges we are about to remove. Just marking
- them as EDGE_DFS_BACK will do. */
+ them as EDGE_IGNORE will do. */
FOR_EACH_VEC_ELT (to_remove_edges, i, e)
- e->flags |= EDGE_DFS_BACK;
+ e->flags |= EDGE_IGNORE;
/* Allocate our unwinder stack to unwind any temporary equivalences
that might be recorded. */
@@ -10135,9 +10135,9 @@ identify_jump_threads (void)
it to a specific successor. */
FOR_EACH_EDGE (e, ei, bb->preds)
{
- /* Do not thread across back edges or abnormal edges
- in the CFG. */
- if (e->flags & (EDGE_DFS_BACK | EDGE_COMPLEX))
+ /* Do not thread across edges marked to ignoreor abnormal
+ edges in the CFG. */
+ if (e->flags & (EDGE_IGNORE | EDGE_COMPLEX))
continue;
thread_across_edge (dummy, e, true, equiv_stack, NULL,
@@ -10146,6 +10146,10 @@ identify_jump_threads (void)
}
}
+ /* Clear EDGE_IGNORE. */
+ FOR_EACH_VEC_ELT (to_remove_edges, i, e)
+ e->flags &= ~EDGE_IGNORE;
+
/* We do not actually update the CFG or SSA graphs at this point as
ASSERT_EXPRs are still in the IL and cfg cleanup code does not yet
handle ASSERT_EXPRs gracefully. */
diff --git a/gcc/tree.c b/gcc/tree.c
index 5b9a7bdc2fe..ff414f7a62d 100644
--- a/gcc/tree.c
+++ b/gcc/tree.c
@@ -4207,6 +4207,7 @@ stabilize_reference (tree ref)
result = build_nt (BIT_FIELD_REF,
stabilize_reference (TREE_OPERAND (ref, 0)),
TREE_OPERAND (ref, 1), TREE_OPERAND (ref, 2));
+ REF_REVERSE_STORAGE_ORDER (result) = REF_REVERSE_STORAGE_ORDER (ref);
break;
case ARRAY_REF:
@@ -12943,7 +12944,10 @@ verify_type_variant (const_tree t, tree tv)
verify_variant_match (TYPE_PACKED);
if (TREE_CODE (t) == REFERENCE_TYPE)
verify_variant_match (TYPE_REF_IS_RVALUE);
- verify_variant_match (TYPE_SATURATING);
+ if (AGGREGATE_TYPE_P (t))
+ verify_variant_match (TYPE_REVERSE_STORAGE_ORDER);
+ else
+ verify_variant_match (TYPE_SATURATING);
/* FIXME: This check trigger during libstdc++ build. */
if (RECORD_OR_UNION_TYPE_P (t) && COMPLETE_TYPE_P (t) && 0)
verify_variant_match (TYPE_FINAL_P);
@@ -13265,6 +13269,7 @@ gimple_canonical_types_compatible_p (const_tree t1, const_tree t2,
if (!gimple_canonical_types_compatible_p (TREE_TYPE (t1), TREE_TYPE (t2),
trust_type_canonical)
|| TYPE_STRING_FLAG (t1) != TYPE_STRING_FLAG (t2)
+ || TYPE_REVERSE_STORAGE_ORDER (t1) != TYPE_REVERSE_STORAGE_ORDER (t2)
|| TYPE_NONALIASED_COMPONENT (t1) != TYPE_NONALIASED_COMPONENT (t2))
return false;
else
@@ -13338,6 +13343,9 @@ gimple_canonical_types_compatible_p (const_tree t1, const_tree t2,
{
tree f1, f2;
+ if (TYPE_REVERSE_STORAGE_ORDER (t1) != TYPE_REVERSE_STORAGE_ORDER (t2))
+ return false;
+
/* For aggregate types, all the fields must be the same. */
for (f1 = TYPE_FIELDS (t1), f2 = TYPE_FIELDS (t2);
f1 || f2;
diff --git a/gcc/tree.h b/gcc/tree.h
index 6768b3bb29b..e71eba43d50 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -905,8 +905,29 @@ extern void omp_clause_range_check_failed (const_tree, const char *, int,
#define IDENTIFIER_TRANSPARENT_ALIAS(NODE) \
(IDENTIFIER_NODE_CHECK (NODE)->base.deprecated_flag)
-/* In fixed-point types, means a saturating type. */
-#define TYPE_SATURATING(NODE) (TYPE_CHECK (NODE)->base.u.bits.saturating_flag)
+/* In an aggregate type, indicates that the scalar fields of the type are
+ stored in reverse order from the target order. This effectively
+ toggles BYTES_BIG_ENDIAN and WORDS_BIG_ENDIAN within the type. */
+#define TYPE_REVERSE_STORAGE_ORDER(NODE) \
+ (TREE_CHECK4 (NODE, RECORD_TYPE, UNION_TYPE, QUAL_UNION_TYPE, ARRAY_TYPE)->base.u.bits.saturating_flag)
+
+/* In a non-aggregate type, indicates a saturating type. */
+#define TYPE_SATURATING(NODE) \
+ (TREE_NOT_CHECK4 (NODE, RECORD_TYPE, UNION_TYPE, QUAL_UNION_TYPE, ARRAY_TYPE)->base.u.bits.saturating_flag)
+
+/* In a BIT_FIELD_REF and MEM_REF, indicates that the reference is to a group
+ of bits stored in reverse order from the target order. This effectively
+ toggles both BYTES_BIG_ENDIAN and WORDS_BIG_ENDIAN for the reference.
+
+ The overall strategy is to preserve the invariant that every scalar in
+ memory is associated with a single storage order, i.e. all accesses to
+ this scalar are done with the same storage order. This invariant makes
+ it possible to factor out the storage order in most transformations, as
+ only the address and/or the value (in target order) matter for them.
+ But, of course, the storage order must be preserved when the accesses
+ themselves are rewritten or transformed. */
+#define REF_REVERSE_STORAGE_ORDER(NODE) \
+ (TREE_CHECK2 (NODE, BIT_FIELD_REF, MEM_REF)->base.u.bits.saturating_flag)
/* These flags are available for each language front end to use internally. */
#define TREE_LANG_FLAG_0(NODE) \
@@ -4350,6 +4371,64 @@ handled_component_p (const_tree t)
}
}
+/* Return true T is a component with reverse storage order. */
+
+static inline bool
+reverse_storage_order_for_component_p (tree t)
+{
+ /* The storage order only applies to scalar components. */
+ if (AGGREGATE_TYPE_P (TREE_TYPE (t)) || VECTOR_TYPE_P (TREE_TYPE (t)))
+ return false;
+
+ if (TREE_CODE (t) == REALPART_EXPR || TREE_CODE (t) == IMAGPART_EXPR)
+ t = TREE_OPERAND (t, 0);
+
+ switch (TREE_CODE (t))
+ {
+ case ARRAY_REF:
+ case COMPONENT_REF:
+ /* ??? Fortran can take COMPONENT_REF of a void type. */
+ return !VOID_TYPE_P (TREE_TYPE (TREE_OPERAND (t, 0)))
+ && TYPE_REVERSE_STORAGE_ORDER (TREE_TYPE (TREE_OPERAND (t, 0)));
+
+ case BIT_FIELD_REF:
+ case MEM_REF:
+ return REF_REVERSE_STORAGE_ORDER (t);
+
+ case ARRAY_RANGE_REF:
+ case VIEW_CONVERT_EXPR:
+ default:
+ return false;
+ }
+
+ gcc_unreachable ();
+}
+
+/* Return true if T is a storage order barrier, i.e. a VIEW_CONVERT_EXPR
+ that can modify the storage order of objects. Note that, even if the
+ TYPE_REVERSE_STORAGE_ORDER flag is set on both the inner type and the
+ outer type, a VIEW_CONVERT_EXPR can modify the storage order because
+ it can change the partition of the aggregate object into scalars. */
+
+static inline bool
+storage_order_barrier_p (const_tree t)
+{
+ if (TREE_CODE (t) != VIEW_CONVERT_EXPR)
+ return false;
+
+ if (AGGREGATE_TYPE_P (TREE_TYPE (t))
+ && TYPE_REVERSE_STORAGE_ORDER (TREE_TYPE (t)))
+ return true;
+
+ tree op = TREE_OPERAND (t, 0);
+
+ if (AGGREGATE_TYPE_P (TREE_TYPE (op))
+ && TYPE_REVERSE_STORAGE_ORDER (TREE_TYPE (op)))
+ return true;
+
+ return false;
+}
+
/* Given a DECL or TYPE, return the scope in which it was declared, or
NUL_TREE if there is no containing scope. */
@@ -5152,7 +5231,7 @@ extern bool complete_ctor_at_level_p (const_tree, HOST_WIDE_INT, const_tree);
the access position and size. */
extern tree get_inner_reference (tree, HOST_WIDE_INT *, HOST_WIDE_INT *,
tree *, machine_mode *, int *, int *,
- bool);
+ int *, bool);
extern tree build_personality_function (const char *);
diff --git a/gcc/tsan.c b/gcc/tsan.c
index 05a3a147a39..e3263f8538a 100644
--- a/gcc/tsan.c
+++ b/gcc/tsan.c
@@ -108,9 +108,9 @@ instrument_expr (gimple_stmt_iterator gsi, tree expr, bool is_write)
HOST_WIDE_INT bitsize, bitpos;
tree offset;
machine_mode mode;
- int volatilep = 0, unsignedp = 0;
- base = get_inner_reference (expr, &bitsize, &bitpos, &offset,
- &mode, &unsignedp, &volatilep, false);
+ int unsignedp, reversep, volatilep = 0;
+ base = get_inner_reference (expr, &bitsize, &bitpos, &offset, &mode,
+ &unsignedp, &reversep, &volatilep, false);
/* No need to instrument accesses to decls that don't escape,
they can't escape to other threads then. */
diff --git a/gcc/ubsan.c b/gcc/ubsan.c
index 5ea6bef0c31..6fc6233c035 100644
--- a/gcc/ubsan.c
+++ b/gcc/ubsan.c
@@ -1359,9 +1359,9 @@ instrument_bool_enum_load (gimple_stmt_iterator *gsi)
HOST_WIDE_INT bitsize, bitpos;
tree offset;
machine_mode mode;
- int volatilep = 0, unsignedp = 0;
+ int volatilep = 0, reversep, unsignedp = 0;
tree base = get_inner_reference (rhs, &bitsize, &bitpos, &offset, &mode,
- &unsignedp, &volatilep, false);
+ &unsignedp, &reversep, &volatilep, false);
tree utype = build_nonstandard_integer_type (modebitsize, 1);
if ((TREE_CODE (base) == VAR_DECL && DECL_HARD_REGISTER (base))
@@ -1779,9 +1779,9 @@ instrument_object_size (gimple_stmt_iterator *gsi, bool is_lhs)
HOST_WIDE_INT bitsize, bitpos;
tree offset;
machine_mode mode;
- int volatilep = 0, unsignedp = 0;
+ int volatilep = 0, reversep, unsignedp = 0;
tree inner = get_inner_reference (t, &bitsize, &bitpos, &offset, &mode,
- &unsignedp, &volatilep, false);
+ &unsignedp, &reversep, &volatilep, false);
if (bitpos % BITS_PER_UNIT != 0
|| bitsize != size_in_bytes * BITS_PER_UNIT)
diff --git a/gcc/var-tracking.c b/gcc/var-tracking.c
index 72f2e81f059..388b5348e5b 100644
--- a/gcc/var-tracking.c
+++ b/gcc/var-tracking.c
@@ -5058,9 +5058,10 @@ track_expr_p (tree expr, bool need_rtl)
&& TREE_CODE (TREE_OPERAND (realdecl, 0)) == ADDR_EXPR))
{
HOST_WIDE_INT bitsize, bitpos, maxsize;
+ bool reverse;
tree innerdecl
= get_ref_base_and_extent (realdecl, &bitpos, &bitsize,
- &maxsize);
+ &maxsize, &reverse);
if (!DECL_P (innerdecl)
|| DECL_IGNORED_P (innerdecl)
/* Do not track declarations for parts of tracked parameters
diff --git a/gcc/varasm.c b/gcc/varasm.c
index 9ffe9149a63..ec6aabf3d8e 100644
--- a/gcc/varasm.c
+++ b/gcc/varasm.c
@@ -45,6 +45,7 @@ along with GCC; see the file COPYING3. If not see
#include "flags.h"
#include "stmt.h"
#include "expr.h"
+#include "expmed.h"
#include "output.h"
#include "langhooks.h"
#include "debug.h"
@@ -106,7 +107,7 @@ static int compare_constant (const tree, const tree);
static void output_constant_def_contents (rtx);
static void output_addressed_constants (tree);
static unsigned HOST_WIDE_INT output_constant (tree, unsigned HOST_WIDE_INT,
- unsigned int);
+ unsigned int, bool);
static void globalize_decl (tree);
static bool decl_readonly_section_1 (enum section_category);
#ifdef BSS_SECTION_ASM_OP
@@ -2054,7 +2055,8 @@ assemble_variable_contents (tree decl, const char *name,
/* Output the actual data. */
output_constant (DECL_INITIAL (decl),
tree_to_uhwi (DECL_SIZE_UNIT (decl)),
- get_variable_align (decl));
+ get_variable_align (decl),
+ false);
else
/* Leave space for it. */
assemble_zeros (tree_to_uhwi (DECL_SIZE_UNIT (decl)));
@@ -2733,12 +2735,17 @@ assemble_integer (rtx x, unsigned int size, unsigned int align, int force)
return false;
}
+/* Assemble the floating-point constant D into an object of size MODE. ALIGN
+ is the alignment of the constant in bits. If REVERSE is true, D is output
+ in reverse storage order. */
+
void
-assemble_real (REAL_VALUE_TYPE d, machine_mode mode, unsigned int align)
+assemble_real (REAL_VALUE_TYPE d, machine_mode mode, unsigned int align,
+ bool reverse)
{
long data[4] = {0, 0, 0, 0};
- int i;
int bitsize, nelts, nunits, units_per;
+ rtx elt;
/* This is hairy. We have a quantity of known size. real_to_target
will put it into an array of *host* longs, 32 bits per element
@@ -2760,15 +2767,24 @@ assemble_real (REAL_VALUE_TYPE d, machine_mode mode, unsigned int align)
real_to_target (data, &d, mode);
/* Put out the first word with the specified alignment. */
- assemble_integer (GEN_INT (data[0]), MIN (nunits, units_per), align, 1);
+ if (reverse)
+ elt = flip_storage_order (SImode, gen_int_mode (data[nelts - 1], SImode));
+ else
+ elt = GEN_INT (data[0]);
+ assemble_integer (elt, MIN (nunits, units_per), align, 1);
nunits -= units_per;
/* Subsequent words need only 32-bit alignment. */
align = min_align (align, 32);
- for (i = 1; i < nelts; i++)
+ for (int i = 1; i < nelts; i++)
{
- assemble_integer (GEN_INT (data[i]), MIN (nunits, units_per), align, 1);
+ if (reverse)
+ elt = flip_storage_order (SImode,
+ gen_int_mode (data[nelts - 1 - i], SImode));
+ else
+ elt = GEN_INT (data[i]);
+ assemble_integer (elt, MIN (nunits, units_per), align, 1);
nunits -= units_per;
}
}
@@ -3070,10 +3086,12 @@ compare_constant (const tree t1, const tree t2)
if (typecode == ARRAY_TYPE)
{
HOST_WIDE_INT size_1 = int_size_in_bytes (TREE_TYPE (t1));
- /* For arrays, check that the sizes all match. */
+ /* For arrays, check that mode, size and storage order match. */
if (TYPE_MODE (TREE_TYPE (t1)) != TYPE_MODE (TREE_TYPE (t2))
|| size_1 == -1
- || size_1 != int_size_in_bytes (TREE_TYPE (t2)))
+ || size_1 != int_size_in_bytes (TREE_TYPE (t2))
+ || TYPE_REVERSE_STORAGE_ORDER (TREE_TYPE (t1))
+ != TYPE_REVERSE_STORAGE_ORDER (TREE_TYPE (t2)))
return 0;
}
else
@@ -3357,7 +3375,7 @@ assemble_constant_contents (tree exp, const char *label, unsigned int align)
targetm.asm_out.declare_constant_name (asm_out_file, label, exp, size);
/* Output the value of EXP. */
- output_constant (exp, size, align);
+ output_constant (exp, size, align, false);
targetm.asm_out.decl_end ();
}
@@ -3788,7 +3806,7 @@ output_constant_pool_2 (machine_mode mode, rtx x, unsigned int align)
case MODE_DECIMAL_FLOAT:
{
gcc_assert (CONST_DOUBLE_AS_FLOAT_P (x));
- assemble_real (*CONST_DOUBLE_REAL_VALUE (x), mode, align);
+ assemble_real (*CONST_DOUBLE_REAL_VALUE (x), mode, align, false);
break;
}
@@ -4288,7 +4306,11 @@ initializer_constant_valid_p_1 (tree value, tree endtype, tree *cache)
tree reloc;
reloc = initializer_constant_valid_p_1 (elt, TREE_TYPE (elt),
NULL);
- if (!reloc)
+ if (!reloc
+ /* An absolute value is required with reverse SSO. */
+ || (reloc != null_pointer_node
+ && TYPE_REVERSE_STORAGE_ORDER (TREE_TYPE (value))
+ && !AGGREGATE_TYPE_P (TREE_TYPE (elt))))
{
if (cache)
{
@@ -4528,9 +4550,19 @@ initializer_constant_valid_p_1 (tree value, tree endtype, tree *cache)
therefore, we do not need to check for such things as
arithmetic-combinations of integers. */
tree
-initializer_constant_valid_p (tree value, tree endtype)
+initializer_constant_valid_p (tree value, tree endtype, bool reverse)
{
- return initializer_constant_valid_p_1 (value, endtype, NULL);
+ tree reloc = initializer_constant_valid_p_1 (value, endtype, NULL);
+
+ /* An absolute value is required with reverse storage order. */
+ if (reloc
+ && reloc != null_pointer_node
+ && reverse
+ && !AGGREGATE_TYPE_P (endtype)
+ && !VECTOR_TYPE_P (endtype))
+ reloc = NULL_TREE;
+
+ return reloc;
}
/* Return true if VALUE is a valid constant-valued expression
@@ -4580,8 +4612,8 @@ struct oc_outer_state {
};
static unsigned HOST_WIDE_INT
- output_constructor (tree, unsigned HOST_WIDE_INT, unsigned int,
- oc_outer_state *);
+output_constructor (tree, unsigned HOST_WIDE_INT, unsigned int, bool,
+ oc_outer_state *);
/* Output assembler code for constant EXP, with no label.
This includes the pseudo-op such as ".int" or ".byte", and a newline.
@@ -4603,13 +4635,17 @@ static unsigned HOST_WIDE_INT
for a structure constructor that wants to produce more than SIZE bytes.
But such constructors will never be generated for any possible input.
- ALIGN is the alignment of the data in bits. */
+ ALIGN is the alignment of the data in bits.
+
+ If REVERSE is true, EXP is output in reverse storage order. */
static unsigned HOST_WIDE_INT
-output_constant (tree exp, unsigned HOST_WIDE_INT size, unsigned int align)
+output_constant (tree exp, unsigned HOST_WIDE_INT size, unsigned int align,
+ bool reverse)
{
enum tree_code code;
unsigned HOST_WIDE_INT thissize;
+ rtx cst;
if (size == 0 || flag_syntax_only)
return size;
@@ -4704,9 +4740,10 @@ output_constant (tree exp, unsigned HOST_WIDE_INT size, unsigned int align)
case FIXED_POINT_TYPE:
case POINTER_BOUNDS_TYPE:
case NULLPTR_TYPE:
- if (! assemble_integer (expand_expr (exp, NULL_RTX, VOIDmode,
- EXPAND_INITIALIZER),
- MIN (size, thissize), align, 0))
+ cst = expand_expr (exp, NULL_RTX, VOIDmode, EXPAND_INITIALIZER);
+ if (reverse)
+ cst = flip_storage_order (TYPE_MODE (TREE_TYPE (exp)), cst);
+ if (!assemble_integer (cst, MIN (size, thissize), align, 0))
error ("initializer for integer/fixed-point value is too complicated");
break;
@@ -4714,13 +4751,15 @@ output_constant (tree exp, unsigned HOST_WIDE_INT size, unsigned int align)
if (TREE_CODE (exp) != REAL_CST)
error ("initializer for floating value is not a floating constant");
else
- assemble_real (TREE_REAL_CST (exp), TYPE_MODE (TREE_TYPE (exp)), align);
+ assemble_real (TREE_REAL_CST (exp), TYPE_MODE (TREE_TYPE (exp)),
+ align, reverse);
break;
case COMPLEX_TYPE:
- output_constant (TREE_REALPART (exp), thissize / 2, align);
+ output_constant (TREE_REALPART (exp), thissize / 2, align, reverse);
output_constant (TREE_IMAGPART (exp), thissize / 2,
- min_align (align, BITS_PER_UNIT * (thissize / 2)));
+ min_align (align, BITS_PER_UNIT * (thissize / 2)),
+ reverse);
break;
case ARRAY_TYPE:
@@ -4728,7 +4767,7 @@ output_constant (tree exp, unsigned HOST_WIDE_INT size, unsigned int align)
switch (TREE_CODE (exp))
{
case CONSTRUCTOR:
- return output_constructor (exp, size, align, NULL);
+ return output_constructor (exp, size, align, reverse, NULL);
case STRING_CST:
thissize
= MIN ((unsigned HOST_WIDE_INT)TREE_STRING_LENGTH (exp), size);
@@ -4739,11 +4778,13 @@ output_constant (tree exp, unsigned HOST_WIDE_INT size, unsigned int align)
machine_mode inner = TYPE_MODE (TREE_TYPE (TREE_TYPE (exp)));
unsigned int nalign = MIN (align, GET_MODE_ALIGNMENT (inner));
int elt_size = GET_MODE_SIZE (inner);
- output_constant (VECTOR_CST_ELT (exp, 0), elt_size, align);
+ output_constant (VECTOR_CST_ELT (exp, 0), elt_size, align,
+ reverse);
thissize = elt_size;
for (unsigned int i = 1; i < VECTOR_CST_NELTS (exp); i++)
{
- output_constant (VECTOR_CST_ELT (exp, i), elt_size, nalign);
+ output_constant (VECTOR_CST_ELT (exp, i), elt_size, nalign,
+ reverse);
thissize += elt_size;
}
break;
@@ -4756,7 +4797,7 @@ output_constant (tree exp, unsigned HOST_WIDE_INT size, unsigned int align)
case RECORD_TYPE:
case UNION_TYPE:
gcc_assert (TREE_CODE (exp) == CONSTRUCTOR);
- return output_constructor (exp, size, align, NULL);
+ return output_constructor (exp, size, align, reverse, NULL);
case ERROR_MARK:
return 0;
@@ -4770,7 +4811,6 @@ output_constant (tree exp, unsigned HOST_WIDE_INT size, unsigned int align)
return size;
}
-
/* Subroutine of output_constructor, used for computing the size of
arrays of unspecified length. VAL must be a CONSTRUCTOR of an array
@@ -4832,6 +4872,7 @@ struct oc_local_state {
int last_relative_index; /* Implicit or explicit index of the last
array element output within a bitfield. */
bool byte_buffer_in_use; /* Whether BYTE is in use. */
+ bool reverse; /* Whether reverse storage order is in use. */
/* Current element. */
tree field; /* Current field decl in a record. */
@@ -4864,7 +4905,8 @@ output_constructor_array_range (oc_local_state *local)
if (local->val == NULL_TREE)
assemble_zeros (fieldsize);
else
- fieldsize = output_constant (local->val, fieldsize, align2);
+ fieldsize
+ = output_constant (local->val, fieldsize, align2, local->reverse);
/* Count its size. */
local->total_bytes += fieldsize;
@@ -4950,7 +4992,8 @@ output_constructor_regular_field (oc_local_state *local)
if (local->val == NULL_TREE)
assemble_zeros (fieldsize);
else
- fieldsize = output_constant (local->val, fieldsize, align2);
+ fieldsize
+ = output_constant (local->val, fieldsize, align2, local->reverse);
/* Count its size. */
local->total_bytes += fieldsize;
@@ -5048,7 +5091,7 @@ output_constructor_bitfield (oc_local_state *local, unsigned int bit_offset)
temp_state.bit_offset = next_offset % BITS_PER_UNIT;
temp_state.byte = local->byte;
local->total_bytes
- += output_constructor (local->val, 0, 0, &temp_state);
+ += output_constructor (local->val, 0, 0, local->reverse, &temp_state);
local->byte = temp_state.byte;
return;
}
@@ -5074,9 +5117,9 @@ output_constructor_bitfield (oc_local_state *local, unsigned int bit_offset)
/* Number of bits we can process at once (all part of the same byte). */
this_time = MIN (end_offset - next_offset, BITS_PER_UNIT - next_bit);
- if (BYTES_BIG_ENDIAN)
+ if (local->reverse ? !BYTES_BIG_ENDIAN : BYTES_BIG_ENDIAN)
{
- /* On big-endian machine, take the most significant bits (of the
+ /* For big-endian data, take the most significant bits (of the
bits that are significant) first and put them into bytes from
the most significant end. */
shift = end_offset - next_offset - this_time;
@@ -5138,12 +5181,11 @@ output_constructor_bitfield (oc_local_state *local, unsigned int bit_offset)
caller output state of relevance in recursive invocations. */
static unsigned HOST_WIDE_INT
-output_constructor (tree exp, unsigned HOST_WIDE_INT size,
- unsigned int align, oc_outer_state *outer)
+output_constructor (tree exp, unsigned HOST_WIDE_INT size, unsigned int align,
+ bool reverse, oc_outer_state *outer)
{
unsigned HOST_WIDE_INT cnt;
constructor_elt *ce;
-
oc_local_state local;
/* Setup our local state to communicate with helpers. */
@@ -5160,6 +5202,11 @@ output_constructor (tree exp, unsigned HOST_WIDE_INT size,
local.byte_buffer_in_use = outer != NULL;
local.byte = outer ? outer->byte : 0;
local.last_relative_index = -1;
+ /* The storage order is specified for every aggregate type. */
+ if (AGGREGATE_TYPE_P (local.type))
+ local.reverse = TYPE_REVERSE_STORAGE_ORDER (local.type);
+ else
+ local.reverse = reverse;
gcc_assert (HOST_BITS_PER_WIDE_INT >= BITS_PER_UNIT);
diff --git a/gcc/varasm.h b/gcc/varasm.h
index 0d7d5638f2a..8025e7c47ab 100644
--- a/gcc/varasm.h
+++ b/gcc/varasm.h
@@ -60,7 +60,7 @@ extern void assemble_alias (tree, tree);
We assume that VALUE has been folded as much as possible;
therefore, we do not need to check for such things as
arithmetic-combinations of integers. */
-extern tree initializer_constant_valid_p (tree, tree);
+extern tree initializer_constant_valid_p (tree, tree, bool = false);
/* Return true if VALUE is a valid constant-valued expression
for use in initializing a static bit-field; one that can be
diff --git a/include/ChangeLog b/include/ChangeLog
index 136041cd244..004d355228a 100644
--- a/include/ChangeLog
+++ b/include/ChangeLog
@@ -1,3 +1,13 @@
+2015-11-09 Alan Modra <amodra@gmail.com>
+
+ PR gdb/17133
+ * obstack.h (__attribute_pure__): Expand _GL_ATTRIBUTE_PURE.
+
+2015-11-09 Alan Modra <amodra@gmail.com>
+
+ PR gdb/17133
+ * obstack.h: Import current gnulib file.
+
2015-11-05 Jakub Jelinek <jakub@redhat.com>
Ilya Verbin <ilya.verbin@intel.com>
diff --git a/include/obstack.h b/include/obstack.h
index 9759af48ffe..0d13c72d056 100644
--- a/include/obstack.h
+++ b/include/obstack.h
@@ -1,106 +1,102 @@
/* obstack.h - object stack macros
Copyright (C) 1988-2015 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ The GNU C 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.
- NOTE: The canonical source of this file is maintained with the GNU C Library.
- Bugs can be reported to bug-glibc@gnu.org.
-
- This program is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License as published by the
- Free Software Foundation; either version 2, or (at your option) any
- later version.
-
- This program is distributed in the hope that it will be useful,
+ The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
+ 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 General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301,
- USA. */
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
/* Summary:
-All the apparent functions defined here are macros. The idea
-is that you would use these pre-tested macros to solve a
-very specific set of problems, and they would run fast.
-Caution: no side-effects in arguments please!! They may be
-evaluated MANY times!!
-
-These macros operate a stack of objects. Each object starts life
-small, and may grow to maturity. (Consider building a word syllable
-by syllable.) An object can move while it is growing. Once it has
-been "finished" it never changes address again. So the "top of the
-stack" is typically an immature growing object, while the rest of the
-stack is of mature, fixed size and fixed address objects.
-
-These routines grab large chunks of memory, using a function you
-supply, called `obstack_chunk_alloc'. On occasion, they free chunks,
-by calling `obstack_chunk_free'. You must define them and declare
-them before using any obstack macros.
-
-Each independent stack is represented by a `struct obstack'.
-Each of the obstack macros expects a pointer to such a structure
-as the first argument.
-
-One motivation for this package is the problem of growing char strings
-in symbol tables. Unless you are "fascist pig with a read-only mind"
---Gosper's immortal quote from HAKMEM item 154, out of context--you
-would not like to put any arbitrary upper limit on the length of your
-symbols.
-
-In practice this often means you will build many short symbols and a
-few long symbols. At the time you are reading a symbol you don't know
-how long it is. One traditional method is to read a symbol into a
-buffer, realloc()ating the buffer every time you try to read a symbol
-that is longer than the buffer. This is beaut, but you still will
-want to copy the symbol from the buffer to a more permanent
-symbol-table entry say about half the time.
-
-With obstacks, you can work differently. Use one obstack for all symbol
-names. As you read a symbol, grow the name in the obstack gradually.
-When the name is complete, finalize it. Then, if the symbol exists already,
-free the newly read name.
-
-The way we do this is to take a large chunk, allocating memory from
-low addresses. When you want to build a symbol in the chunk you just
-add chars above the current "high water mark" in the chunk. When you
-have finished adding chars, because you got to the end of the symbol,
-you know how long the chars are, and you can create a new object.
-Mostly the chars will not burst over the highest address of the chunk,
-because you would typically expect a chunk to be (say) 100 times as
-long as an average object.
-
-In case that isn't clear, when we have enough chars to make up
-the object, THEY ARE ALREADY CONTIGUOUS IN THE CHUNK (guaranteed)
-so we just point to it where it lies. No moving of chars is
-needed and this is the second win: potentially long strings need
-never be explicitly shuffled. Once an object is formed, it does not
-change its address during its lifetime.
-
-When the chars burst over a chunk boundary, we allocate a larger
-chunk, and then copy the partly formed object from the end of the old
-chunk to the beginning of the new larger chunk. We then carry on
-accreting characters to the end of the object as we normally would.
-
-A special macro is provided to add a single char at a time to a
-growing object. This allows the use of register variables, which
-break the ordinary 'growth' macro.
-
-Summary:
- We allocate large chunks.
- We carve out one object at a time from the current chunk.
- Once carved, an object never moves.
- We are free to append data of any size to the currently
- growing object.
- Exactly one object is growing in an obstack at any one time.
- You can run one obstack per control block.
- You may have as many control blocks as you dare.
- Because of the way we do it, you can `unwind' an obstack
- back to a previous state. (You may remove objects much
- as you would with a stack.)
-*/
+ All the apparent functions defined here are macros. The idea
+ is that you would use these pre-tested macros to solve a
+ very specific set of problems, and they would run fast.
+ Caution: no side-effects in arguments please!! They may be
+ evaluated MANY times!!
+
+ These macros operate a stack of objects. Each object starts life
+ small, and may grow to maturity. (Consider building a word syllable
+ by syllable.) An object can move while it is growing. Once it has
+ been "finished" it never changes address again. So the "top of the
+ stack" is typically an immature growing object, while the rest of the
+ stack is of mature, fixed size and fixed address objects.
+
+ These routines grab large chunks of memory, using a function you
+ supply, called 'obstack_chunk_alloc'. On occasion, they free chunks,
+ by calling 'obstack_chunk_free'. You must define them and declare
+ them before using any obstack macros.
+
+ Each independent stack is represented by a 'struct obstack'.
+ Each of the obstack macros expects a pointer to such a structure
+ as the first argument.
+
+ One motivation for this package is the problem of growing char strings
+ in symbol tables. Unless you are "fascist pig with a read-only mind"
+ --Gosper's immortal quote from HAKMEM item 154, out of context--you
+ would not like to put any arbitrary upper limit on the length of your
+ symbols.
+
+ In practice this often means you will build many short symbols and a
+ few long symbols. At the time you are reading a symbol you don't know
+ how long it is. One traditional method is to read a symbol into a
+ buffer, realloc()ating the buffer every time you try to read a symbol
+ that is longer than the buffer. This is beaut, but you still will
+ want to copy the symbol from the buffer to a more permanent
+ symbol-table entry say about half the time.
+
+ With obstacks, you can work differently. Use one obstack for all symbol
+ names. As you read a symbol, grow the name in the obstack gradually.
+ When the name is complete, finalize it. Then, if the symbol exists already,
+ free the newly read name.
+
+ The way we do this is to take a large chunk, allocating memory from
+ low addresses. When you want to build a symbol in the chunk you just
+ add chars above the current "high water mark" in the chunk. When you
+ have finished adding chars, because you got to the end of the symbol,
+ you know how long the chars are, and you can create a new object.
+ Mostly the chars will not burst over the highest address of the chunk,
+ because you would typically expect a chunk to be (say) 100 times as
+ long as an average object.
+
+ In case that isn't clear, when we have enough chars to make up
+ the object, THEY ARE ALREADY CONTIGUOUS IN THE CHUNK (guaranteed)
+ so we just point to it where it lies. No moving of chars is
+ needed and this is the second win: potentially long strings need
+ never be explicitly shuffled. Once an object is formed, it does not
+ change its address during its lifetime.
+
+ When the chars burst over a chunk boundary, we allocate a larger
+ chunk, and then copy the partly formed object from the end of the old
+ chunk to the beginning of the new larger chunk. We then carry on
+ accreting characters to the end of the object as we normally would.
+
+ A special macro is provided to add a single char at a time to a
+ growing object. This allows the use of register variables, which
+ break the ordinary 'growth' macro.
+
+ Summary:
+ We allocate large chunks.
+ We carve out one object at a time from the current chunk.
+ Once carved, an object never moves.
+ We are free to append data of any size to the currently
+ growing object.
+ Exactly one object is growing in an obstack at any one time.
+ You can run one obstack per control block.
+ You may have as many control blocks as you dare.
+ Because of the way we do it, you can "unwind" an obstack
+ back to a previous state. (You may remove objects much
+ as you would with a stack.)
+ */
/* Don't do the contents of this file more than once. */
@@ -108,144 +104,128 @@ Summary:
#ifndef _OBSTACK_H
#define _OBSTACK_H 1
-#ifdef __cplusplus
-extern "C" {
+#ifndef _OBSTACK_INTERFACE_VERSION
+# define _OBSTACK_INTERFACE_VERSION 2
#endif
-
-/* We use subtraction of (char *) 0 instead of casting to int
- because on word-addressable machines a simple cast to int
- may ignore the byte-within-word field of the pointer. */
-#ifndef __PTR_TO_INT
-# define __PTR_TO_INT(P) ((P) - (char *) 0)
-#endif
+#include <stddef.h> /* For size_t and ptrdiff_t. */
+#include <string.h> /* For __GNU_LIBRARY__, and memcpy. */
-#ifndef __INT_TO_PTR
-# define __INT_TO_PTR(P) ((P) + (char *) 0)
+#if _OBSTACK_INTERFACE_VERSION == 1
+/* For binary compatibility with obstack version 1, which used "int"
+ and "long" for these two types. */
+# define _OBSTACK_SIZE_T unsigned int
+# define _CHUNK_SIZE_T unsigned long
+# define _OBSTACK_CAST(type, expr) ((type) (expr))
+#else
+/* Version 2 with sane types, especially for 64-bit hosts. */
+# define _OBSTACK_SIZE_T size_t
+# define _CHUNK_SIZE_T size_t
+# define _OBSTACK_CAST(type, expr) (expr)
#endif
-/* We need the type of the resulting object. If __PTRDIFF_TYPE__ is
- defined, as with GNU C, use that; that way we don't pollute the
- namespace with <stddef.h>'s symbols. Otherwise, if <stddef.h> is
- available, include it and use ptrdiff_t. In traditional C, long is
- the best that we can do. */
+/* If B is the base of an object addressed by P, return the result of
+ aligning P to the next multiple of A + 1. B and P must be of type
+ char *. A + 1 must be a power of 2. */
-#ifdef __PTRDIFF_TYPE__
-# define PTR_INT_TYPE __PTRDIFF_TYPE__
-#else
-# ifdef HAVE_STDDEF_H
-# include <stddef.h>
-# define PTR_INT_TYPE ptrdiff_t
+#define __BPTR_ALIGN(B, P, A) ((B) + (((P) - (B) + (A)) & ~(A)))
+
+/* Similar to __BPTR_ALIGN (B, P, A), except optimize the common case
+ where pointers can be converted to integers, aligned as integers,
+ and converted back again. If ptrdiff_t is narrower than a
+ pointer (e.g., the AS/400), play it safe and compute the alignment
+ relative to B. Otherwise, use the faster strategy of computing the
+ alignment relative to 0. */
+
+#define __PTR_ALIGN(B, P, A) \
+ __BPTR_ALIGN (sizeof (ptrdiff_t) < sizeof (void *) ? (B) : (char *) 0, \
+ P, A)
+
+#ifndef __attribute_pure__
+# if defined __GNUC_MINOR__ && __GNUC__ * 1000 + __GNUC_MINOR__ >= 2096
+# define __attribute_pure__ __attribute__ ((__pure__))
# else
-# define PTR_INT_TYPE long
+# define __attribute_pure__
# endif
#endif
-#if defined _LIBC || defined HAVE_STRING_H
-# include <string.h>
-# define _obstack_memcpy(To, From, N) memcpy ((To), (From), (N))
-#else
-# ifdef memcpy
-# define _obstack_memcpy(To, From, N) memcpy ((To), (char *)(From), (N))
-# else
-# define _obstack_memcpy(To, From, N) bcopy ((char *)(From), (To), (N))
-# endif
+#ifdef __cplusplus
+extern "C" {
#endif
-struct _obstack_chunk /* Lives at front of each chunk. */
+struct _obstack_chunk /* Lives at front of each chunk. */
{
- char *limit; /* 1 past end of this chunk */
- struct _obstack_chunk *prev; /* address of prior chunk or NULL */
- char contents[4]; /* objects begin here */
+ char *limit; /* 1 past end of this chunk */
+ struct _obstack_chunk *prev; /* address of prior chunk or NULL */
+ char contents[4]; /* objects begin here */
};
-struct obstack /* control current object in current chunk */
+struct obstack /* control current object in current chunk */
{
- long chunk_size; /* preferred size to allocate chunks in */
- struct _obstack_chunk *chunk; /* address of current struct obstack_chunk */
- char *object_base; /* address of object we are building */
- char *next_free; /* where to add next char to current object */
- char *chunk_limit; /* address of char after current chunk */
- PTR_INT_TYPE temp; /* Temporary for some macros. */
- int alignment_mask; /* Mask of alignment for each object. */
- /* These prototypes vary based on `use_extra_arg', and we use
- casts to the prototypeless function type in all assignments,
- but having prototypes here quiets -Wstrict-prototypes. */
- struct _obstack_chunk *(*chunkfun) (void *, long);
- void (*freefun) (void *, struct _obstack_chunk *);
- void *extra_arg; /* first arg for chunk alloc/dealloc funcs */
- unsigned use_extra_arg:1; /* chunk alloc/dealloc funcs take extra arg */
- unsigned maybe_empty_object:1;/* There is a possibility that the current
- chunk contains a zero-length object. This
- prevents freeing the chunk if we allocate
- a bigger chunk to replace it. */
- unsigned alloc_failed:1; /* No longer used, as we now call the failed
- handler on error, but retained for binary
- compatibility. */
+ _CHUNK_SIZE_T chunk_size; /* preferred size to allocate chunks in */
+ struct _obstack_chunk *chunk; /* address of current struct obstack_chunk */
+ char *object_base; /* address of object we are building */
+ char *next_free; /* where to add next char to current object */
+ char *chunk_limit; /* address of char after current chunk */
+ union
+ {
+ _OBSTACK_SIZE_T i;
+ void *p;
+ } temp; /* Temporary for some macros. */
+ _OBSTACK_SIZE_T alignment_mask; /* Mask of alignment for each object. */
+
+ /* These prototypes vary based on 'use_extra_arg'. */
+ union
+ {
+ void *(*plain) (size_t);
+ void *(*extra) (void *, size_t);
+ } chunkfun;
+ union
+ {
+ void (*plain) (void *);
+ void (*extra) (void *, void *);
+ } freefun;
+
+ void *extra_arg; /* first arg for chunk alloc/dealloc funcs */
+ unsigned use_extra_arg : 1; /* chunk alloc/dealloc funcs take extra arg */
+ unsigned maybe_empty_object : 1; /* There is a possibility that the current
+ chunk contains a zero-length object. This
+ prevents freeing the chunk if we allocate
+ a bigger chunk to replace it. */
+ unsigned alloc_failed : 1; /* No longer used, as we now call the failed
+ handler on error, but retained for binary
+ compatibility. */
};
/* Declare the external functions we use; they are in obstack.c. */
-extern void _obstack_newchunk (struct obstack *, int);
+extern void _obstack_newchunk (struct obstack *, _OBSTACK_SIZE_T);
extern void _obstack_free (struct obstack *, void *);
-extern int _obstack_begin (struct obstack *, int, int,
- void *(*) (long), void (*) (void *));
-extern int _obstack_begin_1 (struct obstack *, int, int,
- void *(*) (void *, long),
- void (*) (void *, void *), void *);
-extern int _obstack_memory_used (struct obstack *);
-
-/* Do the function-declarations after the structs
- but before defining the macros. */
-
-void obstack_init (struct obstack *obstack);
-
-void * obstack_alloc (struct obstack *obstack, int size);
-
-void * obstack_copy (struct obstack *obstack, void *address, int size);
-void * obstack_copy0 (struct obstack *obstack, void *address, int size);
-
-void obstack_free (struct obstack *obstack, void *block);
-
-void obstack_blank (struct obstack *obstack, int size);
-
-void obstack_grow (struct obstack *obstack, void *data, int size);
-void obstack_grow0 (struct obstack *obstack, void *data, int size);
-
-void obstack_1grow (struct obstack *obstack, int data_char);
-void obstack_ptr_grow (struct obstack *obstack, void *data);
-void obstack_int_grow (struct obstack *obstack, int data);
-
-void * obstack_finish (struct obstack *obstack);
-
-int obstack_object_size (struct obstack *obstack);
-
-int obstack_room (struct obstack *obstack);
-void obstack_make_room (struct obstack *obstack, int size);
-void obstack_1grow_fast (struct obstack *obstack, int data_char);
-void obstack_ptr_grow_fast (struct obstack *obstack, void *data);
-void obstack_int_grow_fast (struct obstack *obstack, int data);
-void obstack_blank_fast (struct obstack *obstack, int size);
-
-void * obstack_base (struct obstack *obstack);
-void * obstack_next_free (struct obstack *obstack);
-int obstack_alignment_mask (struct obstack *obstack);
-int obstack_chunk_size (struct obstack *obstack);
-int obstack_memory_used (struct obstack *obstack);
-
-/* Error handler called when `obstack_chunk_alloc' failed to allocate
- more memory. This can be set to a user defined function. The
- default action is to print a message and abort. */
+extern int _obstack_begin (struct obstack *,
+ _OBSTACK_SIZE_T, _OBSTACK_SIZE_T,
+ void *(*) (size_t), void (*) (void *));
+extern int _obstack_begin_1 (struct obstack *,
+ _OBSTACK_SIZE_T, _OBSTACK_SIZE_T,
+ void *(*) (void *, size_t),
+ void (*) (void *, void *), void *);
+extern _OBSTACK_SIZE_T _obstack_memory_used (struct obstack *)
+ __attribute_pure__;
+
+
+/* Error handler called when 'obstack_chunk_alloc' failed to allocate
+ more memory. This can be set to a user defined function which
+ should either abort gracefully or use longjump - but shouldn't
+ return. The default action is to print a message and abort. */
extern void (*obstack_alloc_failed_handler) (void);
-/* Exit value used when `print_and_abort' is used. */
+/* Exit value used when 'print_and_abort' is used. */
extern int obstack_exit_failure;
-
+
/* Pointer to beginning of object being allocated or to be allocated next.
Note that this might not be the final address of the object
because a new chunk might be needed to hold the final size. */
-#define obstack_base(h) ((h)->object_base)
+#define obstack_base(h) ((void *) (h)->object_base)
/* Size for allocating ordinary chunks. */
@@ -253,203 +233,210 @@ extern int obstack_exit_failure;
/* Pointer to next byte not yet allocated in current chunk. */
-#define obstack_next_free(h) ((h)->next_free)
+#define obstack_next_free(h) ((void *) (h)->next_free)
/* Mask specifying low bits that should be clear in address of an object. */
#define obstack_alignment_mask(h) ((h)->alignment_mask)
-/* To prevent prototype warnings provide complete argument list in
- standard C version. */
-# define obstack_init(h) \
- _obstack_begin ((h), 0, 0, \
- (void *(*) (long)) obstack_chunk_alloc, (void (*) (void *)) obstack_chunk_free)
+/* To prevent prototype warnings provide complete argument list. */
+#define obstack_init(h) \
+ _obstack_begin ((h), 0, 0, \
+ _OBSTACK_CAST (void *(*) (size_t), obstack_chunk_alloc), \
+ _OBSTACK_CAST (void (*) (void *), obstack_chunk_free))
-# define obstack_begin(h, size) \
- _obstack_begin ((h), (size), 0, \
- (void *(*) (long)) obstack_chunk_alloc, (void (*) (void *)) obstack_chunk_free)
+#define obstack_begin(h, size) \
+ _obstack_begin ((h), (size), 0, \
+ _OBSTACK_CAST (void *(*) (size_t), obstack_chunk_alloc), \
+ _OBSTACK_CAST (void (*) (void *), obstack_chunk_free))
-# define obstack_specify_allocation(h, size, alignment, chunkfun, freefun) \
- _obstack_begin ((h), (size), (alignment), \
- (void *(*) (long)) (chunkfun), (void (*) (void *)) (freefun))
+#define obstack_specify_allocation(h, size, alignment, chunkfun, freefun) \
+ _obstack_begin ((h), (size), (alignment), \
+ _OBSTACK_CAST (void *(*) (size_t), chunkfun), \
+ _OBSTACK_CAST (void (*) (void *), freefun))
-# define obstack_specify_allocation_with_arg(h, size, alignment, chunkfun, freefun, arg) \
- _obstack_begin_1 ((h), (size), (alignment), \
- (void *(*) (void *, long)) (chunkfun), \
- (void (*) (void *, void *)) (freefun), (arg))
+#define obstack_specify_allocation_with_arg(h, size, alignment, chunkfun, freefun, arg) \
+ _obstack_begin_1 ((h), (size), (alignment), \
+ _OBSTACK_CAST (void *(*) (void *, size_t), chunkfun), \
+ _OBSTACK_CAST (void (*) (void *, void *), freefun), arg)
-# define obstack_chunkfun(h, newchunkfun) \
- ((h) -> chunkfun = (struct _obstack_chunk *(*)(void *, long)) (newchunkfun))
+#define obstack_chunkfun(h, newchunkfun) \
+ ((void) ((h)->chunkfun.extra = (void *(*) (void *, size_t)) (newchunkfun)))
-# define obstack_freefun(h, newfreefun) \
- ((h) -> freefun = (void (*)(void *, struct _obstack_chunk *)) (newfreefun))
+#define obstack_freefun(h, newfreefun) \
+ ((void) ((h)->freefun.extra = (void *(*) (void *, void *)) (newfreefun)))
-#define obstack_1grow_fast(h,achar) (*((h)->next_free)++ = (achar))
+#define obstack_1grow_fast(h, achar) ((void) (*((h)->next_free)++ = (achar)))
-#define obstack_blank_fast(h,n) ((h)->next_free += (n))
+#define obstack_blank_fast(h, n) ((void) ((h)->next_free += (n)))
#define obstack_memory_used(h) _obstack_memory_used (h)
-
-#if defined __GNUC__ && defined __STDC__ && __STDC__
-/* NextStep 2.0 cc is really gcc 1.93 but it defines __GNUC__ = 2 and
- does not implement __extension__. But that compiler doesn't define
- __GNUC_MINOR__. */
-# if __GNUC__ < 2 || (__NeXT__ && !__GNUC_MINOR__)
+
+#if defined __GNUC__
+# if !defined __GNUC_MINOR__ || __GNUC__ * 1000 + __GNUC_MINOR__ < 2008
# define __extension__
# endif
/* For GNU C, if not -traditional,
we can define these macros to compute all args only once
without using a global variable.
- Also, we can avoid using the `temp' slot, to make faster code. */
-
-# define obstack_object_size(OBSTACK) \
- __extension__ \
- ({ struct obstack *__o = (OBSTACK); \
- (unsigned) (__o->next_free - __o->object_base); })
-
-# define obstack_room(OBSTACK) \
- __extension__ \
- ({ struct obstack *__o = (OBSTACK); \
- (unsigned) (__o->chunk_limit - __o->next_free); })
-
-# define obstack_make_room(OBSTACK,length) \
-__extension__ \
-({ struct obstack *__o = (OBSTACK); \
- int __len = (length); \
- if (__o->chunk_limit - __o->next_free < __len) \
- _obstack_newchunk (__o, __len); \
- (void) 0; })
-
-# define obstack_empty_p(OBSTACK) \
- __extension__ \
- ({ struct obstack *__o = (OBSTACK); \
- (__o->chunk->prev == 0 && __o->next_free - __o->chunk->contents == 0); })
-
-# define obstack_grow(OBSTACK,where,length) \
-__extension__ \
-({ struct obstack *__o = (OBSTACK); \
- int __len = (length); \
- if (__o->next_free + __len > __o->chunk_limit) \
- _obstack_newchunk (__o, __len); \
- _obstack_memcpy (__o->next_free, (where), __len); \
- __o->next_free += __len; \
- (void) 0; })
-
-# define obstack_grow0(OBSTACK,where,length) \
-__extension__ \
-({ struct obstack *__o = (OBSTACK); \
- int __len = (length); \
- if (__o->next_free + __len + 1 > __o->chunk_limit) \
- _obstack_newchunk (__o, __len + 1); \
- _obstack_memcpy (__o->next_free, (where), __len); \
- __o->next_free += __len; \
- *(__o->next_free)++ = 0; \
- (void) 0; })
-
-# define obstack_1grow(OBSTACK,datum) \
-__extension__ \
-({ struct obstack *__o = (OBSTACK); \
- if (__o->next_free + 1 > __o->chunk_limit) \
- _obstack_newchunk (__o, 1); \
- obstack_1grow_fast (__o, datum); \
- (void) 0; })
-
-/* These assume that the obstack alignment is good enough for pointers or ints,
- and that the data added so far to the current object
+ Also, we can avoid using the 'temp' slot, to make faster code. */
+
+# define obstack_object_size(OBSTACK) \
+ __extension__ \
+ ({ struct obstack const *__o = (OBSTACK); \
+ (_OBSTACK_SIZE_T) (__o->next_free - __o->object_base); })
+
+/* The local variable is named __o1 to avoid a shadowed variable
+ warning when invoked from other obstack macros. */
+# define obstack_room(OBSTACK) \
+ __extension__ \
+ ({ struct obstack const *__o1 = (OBSTACK); \
+ (_OBSTACK_SIZE_T) (__o1->chunk_limit - __o1->next_free); })
+
+# define obstack_make_room(OBSTACK, length) \
+ __extension__ \
+ ({ struct obstack *__o = (OBSTACK); \
+ _OBSTACK_SIZE_T __len = (length); \
+ if (obstack_room (__o) < __len) \
+ _obstack_newchunk (__o, __len); \
+ (void) 0; })
+
+# define obstack_empty_p(OBSTACK) \
+ __extension__ \
+ ({ struct obstack const *__o = (OBSTACK); \
+ (__o->chunk->prev == 0 \
+ && __o->next_free == __PTR_ALIGN ((char *) __o->chunk, \
+ __o->chunk->contents, \
+ __o->alignment_mask)); })
+
+# define obstack_grow(OBSTACK, where, length) \
+ __extension__ \
+ ({ struct obstack *__o = (OBSTACK); \
+ _OBSTACK_SIZE_T __len = (length); \
+ if (obstack_room (__o) < __len) \
+ _obstack_newchunk (__o, __len); \
+ memcpy (__o->next_free, where, __len); \
+ __o->next_free += __len; \
+ (void) 0; })
+
+# define obstack_grow0(OBSTACK, where, length) \
+ __extension__ \
+ ({ struct obstack *__o = (OBSTACK); \
+ _OBSTACK_SIZE_T __len = (length); \
+ if (obstack_room (__o) < __len + 1) \
+ _obstack_newchunk (__o, __len + 1); \
+ memcpy (__o->next_free, where, __len); \
+ __o->next_free += __len; \
+ *(__o->next_free)++ = 0; \
+ (void) 0; })
+
+# define obstack_1grow(OBSTACK, datum) \
+ __extension__ \
+ ({ struct obstack *__o = (OBSTACK); \
+ if (obstack_room (__o) < 1) \
+ _obstack_newchunk (__o, 1); \
+ obstack_1grow_fast (__o, datum); })
+
+/* These assume that the obstack alignment is good enough for pointers
+ or ints, and that the data added so far to the current object
shares that much alignment. */
-# define obstack_ptr_grow(OBSTACK,datum) \
-__extension__ \
-({ struct obstack *__o = (OBSTACK); \
- if (__o->next_free + sizeof (void *) > __o->chunk_limit) \
- _obstack_newchunk (__o, sizeof (void *)); \
- obstack_ptr_grow_fast (__o, datum); })
-
-# define obstack_int_grow(OBSTACK,datum) \
-__extension__ \
-({ struct obstack *__o = (OBSTACK); \
- if (__o->next_free + sizeof (int) > __o->chunk_limit) \
- _obstack_newchunk (__o, sizeof (int)); \
- obstack_int_grow_fast (__o, datum); })
-
-# define obstack_ptr_grow_fast(OBSTACK,aptr) \
-__extension__ \
-({ struct obstack *__o1 = (OBSTACK); \
- *(const void **) __o1->next_free = (aptr); \
- __o1->next_free += sizeof (const void *); \
- (void) 0; })
-
-# define obstack_int_grow_fast(OBSTACK,aint) \
-__extension__ \
-({ struct obstack *__o1 = (OBSTACK); \
- *(int *) __o1->next_free = (aint); \
- __o1->next_free += sizeof (int); \
- (void) 0; })
-
-# define obstack_blank(OBSTACK,length) \
-__extension__ \
-({ struct obstack *__o = (OBSTACK); \
- int __len = (length); \
- if (__o->chunk_limit - __o->next_free < __len) \
- _obstack_newchunk (__o, __len); \
- obstack_blank_fast (__o, __len); \
- (void) 0; })
-
-# define obstack_alloc(OBSTACK,length) \
-__extension__ \
-({ struct obstack *__h = (OBSTACK); \
- obstack_blank (__h, (length)); \
- obstack_finish (__h); })
-
-# define obstack_copy(OBSTACK,where,length) \
-__extension__ \
-({ struct obstack *__h = (OBSTACK); \
- obstack_grow (__h, (where), (length)); \
- obstack_finish (__h); })
-
-# define obstack_copy0(OBSTACK,where,length) \
-__extension__ \
-({ struct obstack *__h = (OBSTACK); \
- obstack_grow0 (__h, (where), (length)); \
- obstack_finish (__h); })
-
-/* The local variable is named __o1 to avoid a name conflict
- when obstack_blank is called. */
-# define obstack_finish(OBSTACK) \
-__extension__ \
-({ struct obstack *__o1 = (OBSTACK); \
- void *value; \
- value = (void *) __o1->object_base; \
- if (__o1->next_free == value) \
- __o1->maybe_empty_object = 1; \
- __o1->next_free \
- = __INT_TO_PTR ((__PTR_TO_INT (__o1->next_free)+__o1->alignment_mask)\
- & ~ (__o1->alignment_mask)); \
- if (__o1->next_free - (char *)__o1->chunk \
- > __o1->chunk_limit - (char *)__o1->chunk) \
- __o1->next_free = __o1->chunk_limit; \
- __o1->object_base = __o1->next_free; \
- value; })
-
-# define obstack_free(OBSTACK, OBJ) \
-__extension__ \
-({ struct obstack *__o = (OBSTACK); \
- void *__obj = (void *) (OBJ); \
- if (__obj > (void *)__o->chunk && __obj < (void *)__o->chunk_limit) \
- __o->next_free = __o->object_base = (char *) __obj; \
- else (obstack_free) (__o, __obj); })
-
-#else /* not __GNUC__ or not __STDC__ */
-
-# define obstack_object_size(h) \
- (unsigned) ((h)->next_free - (h)->object_base)
-
-# define obstack_room(h) \
- (unsigned) ((h)->chunk_limit - (h)->next_free)
-
-# define obstack_empty_p(h) \
- ((h)->chunk->prev == 0 && (h)->next_free - (h)->chunk->contents == 0)
+# define obstack_ptr_grow(OBSTACK, datum) \
+ __extension__ \
+ ({ struct obstack *__o = (OBSTACK); \
+ if (obstack_room (__o) < sizeof (void *)) \
+ _obstack_newchunk (__o, sizeof (void *)); \
+ obstack_ptr_grow_fast (__o, datum); })
+
+# define obstack_int_grow(OBSTACK, datum) \
+ __extension__ \
+ ({ struct obstack *__o = (OBSTACK); \
+ if (obstack_room (__o) < sizeof (int)) \
+ _obstack_newchunk (__o, sizeof (int)); \
+ obstack_int_grow_fast (__o, datum); })
+
+# define obstack_ptr_grow_fast(OBSTACK, aptr) \
+ __extension__ \
+ ({ struct obstack *__o1 = (OBSTACK); \
+ void *__p1 = __o1->next_free; \
+ *(const void **) __p1 = (aptr); \
+ __o1->next_free += sizeof (const void *); \
+ (void) 0; })
+
+# define obstack_int_grow_fast(OBSTACK, aint) \
+ __extension__ \
+ ({ struct obstack *__o1 = (OBSTACK); \
+ void *__p1 = __o1->next_free; \
+ *(int *) __p1 = (aint); \
+ __o1->next_free += sizeof (int); \
+ (void) 0; })
+
+# define obstack_blank(OBSTACK, length) \
+ __extension__ \
+ ({ struct obstack *__o = (OBSTACK); \
+ _OBSTACK_SIZE_T __len = (length); \
+ if (obstack_room (__o) < __len) \
+ _obstack_newchunk (__o, __len); \
+ obstack_blank_fast (__o, __len); })
+
+# define obstack_alloc(OBSTACK, length) \
+ __extension__ \
+ ({ struct obstack *__h = (OBSTACK); \
+ obstack_blank (__h, (length)); \
+ obstack_finish (__h); })
+
+# define obstack_copy(OBSTACK, where, length) \
+ __extension__ \
+ ({ struct obstack *__h = (OBSTACK); \
+ obstack_grow (__h, (where), (length)); \
+ obstack_finish (__h); })
+
+# define obstack_copy0(OBSTACK, where, length) \
+ __extension__ \
+ ({ struct obstack *__h = (OBSTACK); \
+ obstack_grow0 (__h, (where), (length)); \
+ obstack_finish (__h); })
+
+/* The local variable is named __o1 to avoid a shadowed variable
+ warning when invoked from other obstack macros, typically obstack_free. */
+# define obstack_finish(OBSTACK) \
+ __extension__ \
+ ({ struct obstack *__o1 = (OBSTACK); \
+ void *__value = (void *) __o1->object_base; \
+ if (__o1->next_free == __value) \
+ __o1->maybe_empty_object = 1; \
+ __o1->next_free \
+ = __PTR_ALIGN (__o1->object_base, __o1->next_free, \
+ __o1->alignment_mask); \
+ if ((size_t) (__o1->next_free - (char *) __o1->chunk) \
+ > (size_t) (__o1->chunk_limit - (char *) __o1->chunk)) \
+ __o1->next_free = __o1->chunk_limit; \
+ __o1->object_base = __o1->next_free; \
+ __value; })
+
+# define obstack_free(OBSTACK, OBJ) \
+ __extension__ \
+ ({ struct obstack *__o = (OBSTACK); \
+ void *__obj = (void *) (OBJ); \
+ if (__obj > (void *) __o->chunk && __obj < (void *) __o->chunk_limit) \
+ __o->next_free = __o->object_base = (char *) __obj; \
+ else \
+ _obstack_free (__o, __obj); })
+
+#else /* not __GNUC__ */
+
+# define obstack_object_size(h) \
+ ((_OBSTACK_SIZE_T) ((h)->next_free - (h)->object_base))
+
+# define obstack_room(h) \
+ ((_OBSTACK_SIZE_T) ((h)->chunk_limit - (h)->next_free))
+
+# define obstack_empty_p(h) \
+ ((h)->chunk->prev == 0 \
+ && (h)->next_free == __PTR_ALIGN ((char *) (h)->chunk, \
+ (h)->chunk->contents, \
+ (h)->alignment_mask))
/* Note that the call to _obstack_newchunk is enclosed in (..., 0)
so that we can avoid having void expressions
@@ -457,87 +444,92 @@ __extension__ \
Casting the third operand to void was tried before,
but some compilers won't accept it. */
-# define obstack_make_room(h,length) \
-( (h)->temp = (length), \
- (((h)->next_free + (h)->temp > (h)->chunk_limit) \
- ? (_obstack_newchunk ((h), (h)->temp), 0) : 0))
-
-# define obstack_grow(h,where,length) \
-( (h)->temp = (length), \
- (((h)->next_free + (h)->temp > (h)->chunk_limit) \
- ? (_obstack_newchunk ((h), (h)->temp), 0) : 0), \
- _obstack_memcpy ((h)->next_free, (where), (h)->temp), \
- (h)->next_free += (h)->temp)
-
-# define obstack_grow0(h,where,length) \
-( (h)->temp = (length), \
- (((h)->next_free + (h)->temp + 1 > (h)->chunk_limit) \
- ? (_obstack_newchunk ((h), (h)->temp + 1), 0) : 0), \
- _obstack_memcpy ((h)->next_free, (where), (h)->temp), \
- (h)->next_free += (h)->temp, \
- *((h)->next_free)++ = 0)
-
-# define obstack_1grow(h,datum) \
-( (((h)->next_free + 1 > (h)->chunk_limit) \
- ? (_obstack_newchunk ((h), 1), 0) : 0), \
- obstack_1grow_fast (h, datum))
-
-# define obstack_ptr_grow(h,datum) \
-( (((h)->next_free + sizeof (char *) > (h)->chunk_limit) \
- ? (_obstack_newchunk ((h), sizeof (char *)), 0) : 0), \
- obstack_ptr_grow_fast (h, datum))
-
-# define obstack_int_grow(h,datum) \
-( (((h)->next_free + sizeof (int) > (h)->chunk_limit) \
- ? (_obstack_newchunk ((h), sizeof (int)), 0) : 0), \
- obstack_int_grow_fast (h, datum))
-
-# define obstack_ptr_grow_fast(h,aptr) \
- (((const void **) ((h)->next_free += sizeof (void *)))[-1] = (aptr))
-
-# define obstack_int_grow_fast(h,aint) \
- (((int *) ((h)->next_free += sizeof (int)))[-1] = (aptr))
-
-# define obstack_blank(h,length) \
-( (h)->temp = (length), \
- (((h)->chunk_limit - (h)->next_free < (h)->temp) \
- ? (_obstack_newchunk ((h), (h)->temp), 0) : 0), \
- obstack_blank_fast (h, (h)->temp))
-
-# define obstack_alloc(h,length) \
- (obstack_blank ((h), (length)), obstack_finish ((h)))
-
-# define obstack_copy(h,where,length) \
- (obstack_grow ((h), (where), (length)), obstack_finish ((h)))
-
-# define obstack_copy0(h,where,length) \
- (obstack_grow0 ((h), (where), (length)), obstack_finish ((h)))
-
-# define obstack_finish(h) \
-( ((h)->next_free == (h)->object_base \
- ? (((h)->maybe_empty_object = 1), 0) \
- : 0), \
- (h)->temp = __PTR_TO_INT ((h)->object_base), \
- (h)->next_free \
- = __INT_TO_PTR ((__PTR_TO_INT ((h)->next_free)+(h)->alignment_mask) \
- & ~ ((h)->alignment_mask)), \
- (((h)->next_free - (char *) (h)->chunk \
- > (h)->chunk_limit - (char *) (h)->chunk) \
- ? ((h)->next_free = (h)->chunk_limit) : 0), \
- (h)->object_base = (h)->next_free, \
- (void *) __INT_TO_PTR ((h)->temp))
-
-# define obstack_free(h,obj) \
-( (h)->temp = (char *) (obj) - (char *) (h)->chunk, \
- (((h)->temp > 0 && (h)->temp < (h)->chunk_limit - (char *) (h)->chunk)\
- ? (((h)->next_free = (h)->object_base \
- = (h)->temp + (char *) (h)->chunk), 0) \
- : ((obstack_free) ((h), (h)->temp + (char *) (h)->chunk), 0)))
-
-#endif /* not __GNUC__ or not __STDC__ */
+# define obstack_make_room(h, length) \
+ ((h)->temp.i = (length), \
+ ((obstack_room (h) < (h)->temp.i) \
+ ? (_obstack_newchunk (h, (h)->temp.i), 0) : 0), \
+ (void) 0)
+
+# define obstack_grow(h, where, length) \
+ ((h)->temp.i = (length), \
+ ((obstack_room (h) < (h)->temp.i) \
+ ? (_obstack_newchunk ((h), (h)->temp.i), 0) : 0), \
+ memcpy ((h)->next_free, where, (h)->temp.i), \
+ (h)->next_free += (h)->temp.i, \
+ (void) 0)
+
+# define obstack_grow0(h, where, length) \
+ ((h)->temp.i = (length), \
+ ((obstack_room (h) < (h)->temp.i + 1) \
+ ? (_obstack_newchunk ((h), (h)->temp.i + 1), 0) : 0), \
+ memcpy ((h)->next_free, where, (h)->temp.i), \
+ (h)->next_free += (h)->temp.i, \
+ *((h)->next_free)++ = 0, \
+ (void) 0)
+
+# define obstack_1grow(h, datum) \
+ (((obstack_room (h) < 1) \
+ ? (_obstack_newchunk ((h), 1), 0) : 0), \
+ obstack_1grow_fast (h, datum))
+
+# define obstack_ptr_grow(h, datum) \
+ (((obstack_room (h) < sizeof (char *)) \
+ ? (_obstack_newchunk ((h), sizeof (char *)), 0) : 0), \
+ obstack_ptr_grow_fast (h, datum))
+
+# define obstack_int_grow(h, datum) \
+ (((obstack_room (h) < sizeof (int)) \
+ ? (_obstack_newchunk ((h), sizeof (int)), 0) : 0), \
+ obstack_int_grow_fast (h, datum))
+
+# define obstack_ptr_grow_fast(h, aptr) \
+ (((const void **) ((h)->next_free += sizeof (void *)))[-1] = (aptr), \
+ (void) 0)
+
+# define obstack_int_grow_fast(h, aint) \
+ (((int *) ((h)->next_free += sizeof (int)))[-1] = (aint), \
+ (void) 0)
+
+# define obstack_blank(h, length) \
+ ((h)->temp.i = (length), \
+ ((obstack_room (h) < (h)->temp.i) \
+ ? (_obstack_newchunk ((h), (h)->temp.i), 0) : 0), \
+ obstack_blank_fast (h, (h)->temp.i))
+
+# define obstack_alloc(h, length) \
+ (obstack_blank ((h), (length)), obstack_finish ((h)))
+
+# define obstack_copy(h, where, length) \
+ (obstack_grow ((h), (where), (length)), obstack_finish ((h)))
+
+# define obstack_copy0(h, where, length) \
+ (obstack_grow0 ((h), (where), (length)), obstack_finish ((h)))
+
+# define obstack_finish(h) \
+ (((h)->next_free == (h)->object_base \
+ ? (((h)->maybe_empty_object = 1), 0) \
+ : 0), \
+ (h)->temp.p = (h)->object_base, \
+ (h)->next_free \
+ = __PTR_ALIGN ((h)->object_base, (h)->next_free, \
+ (h)->alignment_mask), \
+ (((size_t) ((h)->next_free - (char *) (h)->chunk) \
+ > (size_t) ((h)->chunk_limit - (char *) (h)->chunk)) \
+ ? ((h)->next_free = (h)->chunk_limit) : 0), \
+ (h)->object_base = (h)->next_free, \
+ (h)->temp.p)
+
+# define obstack_free(h, obj) \
+ ((h)->temp.p = (void *) (obj), \
+ (((h)->temp.p > (void *) (h)->chunk \
+ && (h)->temp.p < (void *) (h)->chunk_limit) \
+ ? (void) ((h)->next_free = (h)->object_base = (char *) (h)->temp.p) \
+ : _obstack_free ((h), (h)->temp.p)))
+
+#endif /* not __GNUC__ */
#ifdef __cplusplus
-} /* C++ */
+} /* C++ */
#endif
-#endif /* obstack.h */
+#endif /* _OBSTACK_H */
diff --git a/libcilkrts/ChangeLog b/libcilkrts/ChangeLog
index 903f7a5a618..ed26a3a1e1b 100644
--- a/libcilkrts/ChangeLog
+++ b/libcilkrts/ChangeLog
@@ -1,3 +1,9 @@
+2015-11-09 Igor Zamyatin <igor.zamyatin@intel.com>
+
+ PR target/66326
+ * runtime/config/x86/os-unix-sysdep.c (sysdep_save_fp_ctrl_state):
+ Use fnstcw instead fnstsw.
+
2015-05-13 Michael Haubenwallner <michael.haubenwallner@ssi-schaefer.com>
* Makefile.in: Regenerated with automake-1.11.6.
diff --git a/libcilkrts/runtime/config/x86/os-unix-sysdep.c b/libcilkrts/runtime/config/x86/os-unix-sysdep.c
index b505ddfb96f..cbc77343215 100644
--- a/libcilkrts/runtime/config/x86/os-unix-sysdep.c
+++ b/libcilkrts/runtime/config/x86/os-unix-sysdep.c
@@ -135,7 +135,7 @@ void sysdep_save_fp_ctrl_state(__cilkrts_stack_frame *sf)
{
__asm__ ("stmxcsr %0" : "=m" (sf->mxcsr));
}
- __asm__ ("fnstsw %0" : "=m" (sf->fpcsr));
+ __asm__ ("fnstcw %0" : "=m" (sf->fpcsr));
}
#endif
}
diff --git a/libcpp/ChangeLog b/libcpp/ChangeLog
index f2ce57abebd..57ac5bfbde1 100644
--- a/libcpp/ChangeLog
+++ b/libcpp/ChangeLog
@@ -1,3 +1,28 @@
+2015-11-06 David Malcolm <dmalcolm@redhat.com>
+
+ * errors.c (cpp_diagnostic): Update for change in signature
+ of "error" callback.
+ (cpp_diagnostic_with_line): Likewise, calling override_column
+ on the rich_location.
+ * include/cpplib.h (struct cpp_callbacks): Within "error"
+ callback, convert param from source_location to rich_location *,
+ and drop column_override param.
+ * include/line-map.h (struct source_range): New struct.
+ (struct location_range): New struct.
+ (class rich_location): New class.
+ (linemap_client_expand_location_to_spelling_point): New declaration.
+ * line-map.c (rich_location::rich_location): New ctors.
+ (rich_location::lazily_expand_location): New method.
+ (rich_location::override_column): New method.
+ (rich_location::add_range): New methods.
+ (rich_location::set_range): New method.
+
+2015-11-06 David Malcolm <dmalcolm@redhat.com>
+
+ * include/line-map.h (struct linemap_stats): Add fields
+ "adhoc_table_size" and "adhoc_table_entries_used".
+ * line-map.c (linemap_get_statistics): Populate above fields.
+
2015-11-04 Mikhail Maltsev <maltsevm@gmail.com>
* config.in: Regenerate.
diff --git a/libcpp/errors.c b/libcpp/errors.c
index a33196e9157..c351c112ad1 100644
--- a/libcpp/errors.c
+++ b/libcpp/errors.c
@@ -57,7 +57,8 @@ cpp_diagnostic (cpp_reader * pfile, int level, int reason,
if (!pfile->cb.error)
abort ();
- ret = pfile->cb.error (pfile, level, reason, src_loc, 0, _(msgid), ap);
+ rich_location richloc (src_loc);
+ ret = pfile->cb.error (pfile, level, reason, &richloc, _(msgid), ap);
return ret;
}
@@ -139,7 +140,9 @@ cpp_diagnostic_with_line (cpp_reader * pfile, int level, int reason,
if (!pfile->cb.error)
abort ();
- ret = pfile->cb.error (pfile, level, reason, src_loc, column, _(msgid), ap);
+ rich_location richloc (src_loc);
+ richloc.override_column (column);
+ ret = pfile->cb.error (pfile, level, reason, &richloc, _(msgid), ap);
return ret;
}
diff --git a/libcpp/include/cpplib.h b/libcpp/include/cpplib.h
index 5eaea6b60d7..a2bdfa0c808 100644
--- a/libcpp/include/cpplib.h
+++ b/libcpp/include/cpplib.h
@@ -573,9 +573,9 @@ struct cpp_callbacks
/* Called to emit a diagnostic. This callback receives the
translated message. */
- bool (*error) (cpp_reader *, int, int, source_location, unsigned int,
+ bool (*error) (cpp_reader *, int, int, rich_location *,
const char *, va_list *)
- ATTRIBUTE_FPTR_PRINTF(6,0);
+ ATTRIBUTE_FPTR_PRINTF(5,0);
/* Callbacks for when a macro is expanded, or tested (whether
defined or not at the time) in #ifdef, #ifndef or "defined". */
diff --git a/libcpp/include/line-map.h b/libcpp/include/line-map.h
index e5867edf4e8..c9340a6eaef 100644
--- a/libcpp/include/line-map.h
+++ b/libcpp/include/line-map.h
@@ -131,6 +131,47 @@ typedef unsigned int linenum_type;
libcpp/location-example.txt. */
typedef unsigned int source_location;
+/* A range of source locations.
+
+ Ranges are closed:
+ m_start is the first location within the range,
+ m_finish is the last location within the range.
+
+ We may need a more compact way to store these, but for now,
+ let's do it the simple way, as a pair. */
+struct GTY(()) source_range
+{
+ source_location m_start;
+ source_location m_finish;
+
+ /* Display this source_range instance, with MSG as a descriptive
+ comment. This issues a "note" diagnostic at the range, using
+ gcc's diagnostic machinery.
+
+ This is declared here, but is implemented within gcc/diagnostic.c,
+ since it makes use of gcc's diagnostic-printing machinery. This
+ is a slight layering violation, but this is sufficiently useful
+ for debugging that it's worth it.
+
+ This declaration would have a DEBUG_FUNCTION annotation, but that
+ is implemented in gcc/system.h and thus is not available here in
+ libcpp. */
+ void debug (const char *msg) const;
+
+ /* We avoid using constructors, since various structs that
+ don't yet have constructors will embed instances of
+ source_range. */
+
+ /* Make a source_range from a source_location. */
+ static source_range from_location (source_location loc)
+ {
+ source_range result;
+ result.m_start = loc;
+ result.m_finish = loc;
+ return result;
+ }
+};
+
/* Memory allocation function typedef. Works like xrealloc. */
typedef void *(*line_map_realloc) (void *, size_t);
@@ -1028,6 +1069,174 @@ typedef struct
bool sysp;
} expanded_location;
+/* Both gcc and emacs number source *lines* starting at 1, but
+ they have differing conventions for *columns*.
+
+ GCC uses a 1-based convention for source columns,
+ whereas Emacs's M-x column-number-mode uses a 0-based convention.
+
+ For example, an error in the initial, left-hand
+ column of source line 3 is reported by GCC as:
+
+ some-file.c:3:1: error: ...etc...
+
+ On navigating to the location of that error in Emacs
+ (e.g. via "next-error"),
+ the locus is reported in the Mode Line
+ (assuming M-x column-number-mode) as:
+
+ some-file.c 10% (3, 0)
+
+ i.e. "3:1:" in GCC corresponds to "(3, 0)" in Emacs. */
+
+/* Ranges are closed
+ m_start is the first location within the range, and
+ m_finish is the last location within the range. */
+struct location_range
+{
+ expanded_location m_start;
+ expanded_location m_finish;
+
+ /* Should a caret be drawn for this range? Typically this is
+ true for the 0th range, and false for subsequent ranges,
+ but the Fortran frontend overrides this for rendering things like:
+
+ x = x + y
+ 1 2
+ Error: Shapes for operands at (1) and (2) are not conformable
+
+ where "1" and "2" are notionally carets. */
+ bool m_show_caret_p;
+ expanded_location m_caret;
+};
+
+/* A "rich" source code location, for use when printing diagnostics.
+ A rich_location has one or more ranges, each optionally with
+ a caret. Typically the zeroth range has a caret; other ranges
+ sometimes have carets.
+
+ The "primary" location of a rich_location is the caret of range 0,
+ used for determining the line/column when printing diagnostic
+ text, such as:
+
+ some-file.c:3:1: error: ...etc...
+
+ Additional ranges may be added to help the user identify other
+ pertinent clauses in a diagnostic.
+
+ rich_location instances are intended to be allocated on the stack
+ when generating diagnostics, and to be short-lived.
+
+ Examples of rich locations
+ --------------------------
+
+ Example A
+ *********
+ int i = "foo";
+ ^
+ This "rich" location is simply a single range (range 0), with
+ caret = start = finish at the given point.
+
+ Example B
+ *********
+ a = (foo && bar)
+ ~~~~~^~~~~~~
+ This rich location has a single range (range 0), with the caret
+ at the first "&", and the start/finish at the parentheses.
+ Compare with example C below.
+
+ Example C
+ *********
+ a = (foo && bar)
+ ~~~ ^~ ~~~
+ This rich location has three ranges:
+ - Range 0 has its caret and start location at the first "&" and
+ end at the second "&.
+ - Range 1 has its start and finish at the "f" and "o" of "foo";
+ the caret is not flagged for display, but is perhaps at the "f"
+ of "foo".
+ - Similarly, range 2 has its start and finish at the "b" and "r" of
+ "bar"; the caret is not flagged for display, but is perhaps at the
+ "b" of "bar".
+ Compare with example B above.
+
+ Example D (Fortran frontend)
+ ****************************
+ x = x + y
+ 1 2
+ This rich location has range 0 at "1", and range 1 at "2".
+ Both are flagged for caret display. Both ranges have start/finish
+ equal to their caret point. The frontend overrides the diagnostic
+ context's default caret character for these ranges.
+
+ Example E
+ *********
+ printf ("arg0: %i arg1: %s arg2: %i",
+ ^~
+ 100, 101, 102);
+ ~~~
+ This rich location has two ranges:
+ - range 0 is at the "%s" with start = caret = "%" and finish at
+ the "s".
+ - range 1 has start/finish covering the "101" and is not flagged for
+ caret printing; it is perhaps at the start of "101". */
+
+class rich_location
+{
+ public:
+ /* Constructors. */
+
+ /* Constructing from a location. */
+ rich_location (source_location loc);
+
+ /* Constructing from a source_range. */
+ rich_location (source_range src_range);
+
+ /* Accessors. */
+ source_location get_loc () const { return m_loc; }
+
+ source_location *get_loc_addr () { return &m_loc; }
+
+ void
+ add_range (source_location start, source_location finish,
+ bool show_caret_p);
+
+ void
+ add_range (source_range src_range, bool show_caret_p);
+
+ void
+ add_range (location_range *src_range);
+
+ void
+ set_range (unsigned int idx, source_range src_range,
+ bool show_caret_p, bool overwrite_loc_p);
+
+ unsigned int get_num_locations () const { return m_num_ranges; }
+
+ location_range *get_range (unsigned int idx)
+ {
+ linemap_assert (idx < m_num_ranges);
+ return &m_ranges[idx];
+ }
+
+ expanded_location lazily_expand_location ();
+
+ void
+ override_column (int column);
+
+public:
+ static const int MAX_RANGES = 3;
+
+protected:
+ source_location m_loc;
+
+ unsigned int m_num_ranges;
+ location_range m_ranges[MAX_RANGES];
+
+ bool m_have_expanded_location;
+ expanded_location m_expanded_location;
+};
+
/* This is enum is used by the function linemap_resolve_location
below. The meaning of the values is explained in the comment of
that function. */
@@ -1143,6 +1352,8 @@ struct linemap_stats
long macro_maps_used_size;
long macro_maps_locations_size;
long duplicated_macro_maps_locations_size;
+ long adhoc_table_size;
+ long adhoc_table_entries_used;
};
/* Return the highest location emitted for a given file for which
@@ -1171,4 +1382,13 @@ void linemap_dump (FILE *, struct line_maps *, unsigned, bool);
specifies how many macro maps to dump. */
void line_table_dump (FILE *, struct line_maps *, unsigned int, unsigned int);
+/* The rich_location class requires a way to expand source_location instances.
+ We would directly use expand_location_to_spelling_point, which is
+ implemented in gcc/input.c, but we also need to use it for rich_location
+ within genmatch.c.
+ Hence we require client code of libcpp to implement the following
+ symbol. */
+extern expanded_location
+linemap_client_expand_location_to_spelling_point (source_location );
+
#endif /* !LIBCPP_LINE_MAP_H */
diff --git a/libcpp/line-map.c b/libcpp/line-map.c
index 3d82e9bfca9..3c19f93b7a5 100644
--- a/libcpp/line-map.c
+++ b/libcpp/line-map.c
@@ -1712,6 +1712,9 @@ linemap_get_statistics (struct line_maps *set,
s->macro_maps_used_size = macro_maps_used_size;
s->duplicated_macro_maps_locations_size =
duplicated_macro_maps_locations_size;
+ s->adhoc_table_size = (set->location_adhoc_data_map.allocated
+ * sizeof (struct location_adhoc_data));
+ s->adhoc_table_entries_used = set->location_adhoc_data_map.curr_loc;
}
@@ -1752,3 +1755,133 @@ line_table_dump (FILE *stream, struct line_maps *set, unsigned int num_ordinary,
fprintf (stream, "\n");
}
}
+
+/* class rich_location. */
+
+/* Construct a rich_location with location LOC as its initial range. */
+
+rich_location::rich_location (source_location loc) :
+ m_loc (loc),
+ m_num_ranges (0),
+ m_have_expanded_location (false)
+{
+ /* Set up the 0th range: */
+ add_range (loc, loc, true);
+ m_ranges[0].m_caret = lazily_expand_location ();
+}
+
+/* Construct a rich_location with source_range SRC_RANGE as its
+ initial range. */
+
+rich_location::rich_location (source_range src_range)
+: m_loc (src_range.m_start),
+ m_num_ranges (0),
+ m_have_expanded_location (false)
+{
+ /* Set up the 0th range: */
+ add_range (src_range, true);
+}
+
+/* Get an expanded_location for this rich_location's primary
+ location. */
+
+expanded_location
+rich_location::lazily_expand_location ()
+{
+ if (!m_have_expanded_location)
+ {
+ m_expanded_location
+ = linemap_client_expand_location_to_spelling_point (m_loc);
+ m_have_expanded_location = true;
+ }
+
+ return m_expanded_location;
+}
+
+/* Set the column of the primary location. */
+
+void
+rich_location::override_column (int column)
+{
+ lazily_expand_location ();
+ m_expanded_location.column = column;
+}
+
+/* Add the given range. */
+
+void
+rich_location::add_range (source_location start, source_location finish,
+ bool show_caret_p)
+{
+ linemap_assert (m_num_ranges < MAX_RANGES);
+
+ location_range *range = &m_ranges[m_num_ranges++];
+ range->m_start = linemap_client_expand_location_to_spelling_point (start);
+ range->m_finish = linemap_client_expand_location_to_spelling_point (finish);
+ range->m_caret = range->m_start;
+ range->m_show_caret_p = show_caret_p;
+}
+
+/* Add the given range. */
+
+void
+rich_location::add_range (source_range src_range, bool show_caret_p)
+{
+ linemap_assert (m_num_ranges < MAX_RANGES);
+
+ add_range (src_range.m_start, src_range.m_finish, show_caret_p);
+}
+
+void
+rich_location::add_range (location_range *src_range)
+{
+ linemap_assert (m_num_ranges < MAX_RANGES);
+
+ m_ranges[m_num_ranges++] = *src_range;
+}
+
+/* Add or overwrite the range given by IDX. It must either
+ overwrite an existing range, or add one *exactly* on the end of
+ the array.
+
+ This is primarily for use by gcc when implementing diagnostic
+ format decoders e.g. the "+" in the C/C++ frontends, for handling
+ format codes like "%q+D" (which writes the source location of a
+ tree back into range 0 of the rich_location).
+
+ If SHOW_CARET_P is true, then the range should be rendered with
+ a caret at its starting location. This
+ is for use by the Fortran frontend, for implementing the
+ "%C" and "%L" format codes. */
+
+void
+rich_location::set_range (unsigned int idx, source_range src_range,
+ bool show_caret_p, bool overwrite_loc_p)
+{
+ linemap_assert (idx < MAX_RANGES);
+
+ /* We can either overwrite an existing range, or add one exactly
+ on the end of the array. */
+ linemap_assert (idx <= m_num_ranges);
+
+ location_range *locrange = &m_ranges[idx];
+ locrange->m_start
+ = linemap_client_expand_location_to_spelling_point (src_range.m_start);
+ locrange->m_finish
+ = linemap_client_expand_location_to_spelling_point (src_range.m_finish);
+
+ locrange->m_show_caret_p = show_caret_p;
+ if (overwrite_loc_p)
+ locrange->m_caret = locrange->m_start;
+
+ /* Are we adding a range onto the end? */
+ if (idx == m_num_ranges)
+ m_num_ranges = idx + 1;
+
+ if (idx == 0 && overwrite_loc_p)
+ {
+ m_loc = src_range.m_start;
+ /* Mark any cached value here as dirty. */
+ m_have_expanded_location = false;
+ }
+}
diff --git a/libgcc/ChangeLog b/libgcc/ChangeLog
index d964b243879..e4fb81bad0b 100644
--- a/libgcc/ChangeLog
+++ b/libgcc/ChangeLog
@@ -1,3 +1,22 @@
+2015-11-07 Trevor Saunders <tbsaunde+gcc@tbsaunde.org>
+
+ * config/visium/lib2funcs.c (__set_trampoline_parity): Use
+ __CHAR_BIT__ instead of BITS_PER_UNIT.
+ * fixed-bit.h: Likewise.
+ * fp-bit.h: Likewise.
+ * libgcc2.c (__popcountSI2): Likewise.
+ (__popcountDI2): Likewise.
+ * libgcc2.h: Likewise.
+ * libgcov.h: Likewise.
+
+2015-11-07 David Edelsohn <dje.gcc@gmail.com>
+
+ * config/rs6000/atexit.c: New file.
+ * config/rs6000/t-aix-cxa (LIB2ADDEH): Build atexit.c.
+ * config/rs6000/libgcc-aix-cxa.ver (atexit): Add symbol to exports.
+ * config/rs6000/cxa_finalize.c
+ (catomic_compare_and_exchange_bool_acq): Negate return value.
+
2015-10-30 Venkataramanan Kumar <venkataramanan.kumar@amd.com>
* config/i386/cpuinfo.c (enum processor_types): Add AMDFAM17H.
diff --git a/libgcc/config/rs6000/atexit.c b/libgcc/config/rs6000/atexit.c
new file mode 100644
index 00000000000..f12eb36fe0d
--- /dev/null
+++ b/libgcc/config/rs6000/atexit.c
@@ -0,0 +1,44 @@
+/* Copyright (C) 1999-2015 Free Software Foundation, Inc.
+
+ NOTE: This source is derived from an old version taken from the GNU C
+ Library (glibc).
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 3, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+<http://www.gnu.org/licenses/>. */
+
+#include <stdlib.h>
+#include "exit.h"
+
+
+/* This is defined by newer gcc version unique for each module. */
+extern void *__dso_handle __attribute__ ((__weak__));
+
+
+/* Register FUNC to be executed by `exit'. */
+int
+#ifndef atexit
+attribute_hidden
+#endif
+atexit (void (*func) (void))
+{
+ return __cxa_atexit ((void (*) (void *)) func, NULL,
+ &__dso_handle == NULL ? NULL : __dso_handle);
+}
diff --git a/libgcc/config/rs6000/cxa_finalize.c b/libgcc/config/rs6000/cxa_finalize.c
index 71f8579248a..1fc9d605bbf 100644
--- a/libgcc/config/rs6000/cxa_finalize.c
+++ b/libgcc/config/rs6000/cxa_finalize.c
@@ -32,8 +32,8 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
static boolean_t
catomic_compare_and_exchange_bool_acq (long *mem, long newval, long oldval)
{
- return __atomic_compare_exchange (mem, &oldval, &newval, 0,
- __ATOMIC_ACQUIRE, __ATOMIC_ACQUIRE);
+ return ! __atomic_compare_exchange (mem, &oldval, &newval, 0,
+ __ATOMIC_ACQUIRE, __ATOMIC_ACQUIRE);
}
/* If D is non-NULL, call all functions registered with `__cxa_atexit'
diff --git a/libgcc/config/rs6000/libgcc-aix-cxa.ver b/libgcc/config/rs6000/libgcc-aix-cxa.ver
index f89df2312a3..c729b585a44 100644
--- a/libgcc/config/rs6000/libgcc-aix-cxa.ver
+++ b/libgcc/config/rs6000/libgcc-aix-cxa.ver
@@ -7,3 +7,7 @@ GCC_4.9 {
_GLOBAL__AIXI_shr_o
_GLOBAL__AIXD_shr_o
}
+
+GCC_5 {
+ atexit
+}
diff --git a/libgcc/config/rs6000/t-aix-cxa b/libgcc/config/rs6000/t-aix-cxa
index f230a88d47f..77d7b5336f3 100644
--- a/libgcc/config/rs6000/t-aix-cxa
+++ b/libgcc/config/rs6000/t-aix-cxa
@@ -1,5 +1,6 @@
LIB2ADDEH += $(srcdir)/config/rs6000/cxa_atexit.c \
- $(srcdir)/config/rs6000/cxa_finalize.c
+ $(srcdir)/config/rs6000/cxa_finalize.c \
+ $(srcdir)/config/rs6000/atexit.c
LIB2ADD_ST += $(srcdir)/config/rs6000/aixinitfini.c
diff --git a/libgcc/config/visium/lib2funcs.c b/libgcc/config/visium/lib2funcs.c
index ba720a36d9e..ed9561f20f1 100644
--- a/libgcc/config/visium/lib2funcs.c
+++ b/libgcc/config/visium/lib2funcs.c
@@ -315,7 +315,7 @@ __set_trampoline_parity (UWtype *addr)
{
int i;
- for (i = 0; i < (TRAMPOLINE_SIZE * BITS_PER_UNIT) / W_TYPE_SIZE; i++)
+ for (i = 0; i < (TRAMPOLINE_SIZE * __CHAR_BIT__) / W_TYPE_SIZE; i++)
addr[i] |= parity_bit (addr[i]);
}
#endif
diff --git a/libgcc/fixed-bit.h b/libgcc/fixed-bit.h
index 2efe01d3d36..7f51f7b1111 100644
--- a/libgcc/fixed-bit.h
+++ b/libgcc/fixed-bit.h
@@ -434,7 +434,7 @@ typedef union
} INTunion;
#endif
-#define FIXED_WIDTH (FIXED_SIZE * BITS_PER_UNIT) /* in bits. */
+#define FIXED_WIDTH (FIXED_SIZE * __CHAR_BIT__) /* in bits. */
#define FIXED_C_TYPE1(NAME) NAME ## type
#define FIXED_C_TYPE2(NAME) FIXED_C_TYPE1(NAME)
#define FIXED_C_TYPE FIXED_C_TYPE2(MODE_NAME)
@@ -1108,17 +1108,17 @@ extern FIXED_C_TYPE FIXED_USASHL (FIXED_C_TYPE, word_type);
#if defined (FROM_MODE_NAME_S) && defined (TO_MODE_NAME_S)
#if FROM_TYPE == 1 /* Signed integer. */
-#define FROM_INT_WIDTH (FROM_INT_SIZE * BITS_PER_UNIT)
+#define FROM_INT_WIDTH (FROM_INT_SIZE * __CHAR_BIT__)
#endif
#if FROM_TYPE == 2 /* Unsigned integer. */
-#define FROM_INT_WIDTH (FROM_INT_SIZE * BITS_PER_UNIT)
+#define FROM_INT_WIDTH (FROM_INT_SIZE * __CHAR_BIT__)
#endif
#if FROM_TYPE == 4 /* Fixed-point. */
#define FROM_FIXED_C_TYPE FIXED_C_TYPE2(FROM_MODE_NAME)
#define FROM_FBITS FBITS2(FROM_MODE_NAME)
-#define FROM_FIXED_WIDTH (FROM_FIXED_SIZE * BITS_PER_UNIT)
+#define FROM_FIXED_WIDTH (FROM_FIXED_SIZE * __CHAR_BIT__)
#define FROM_FBITS FBITS2(FROM_MODE_NAME)
#define FROM_IBITS IBITS2(FROM_MODE_NAME)
#define FROM_I_F_BITS (FROM_FBITS + FROM_IBITS)
@@ -1136,7 +1136,7 @@ extern FIXED_C_TYPE FIXED_USASHL (FIXED_C_TYPE, word_type);
#if TO_TYPE == 4 /* Fixed-point. */
#define TO_FIXED_C_TYPE FIXED_C_TYPE2(TO_MODE_NAME)
#define TO_FBITS FBITS2(TO_MODE_NAME)
-#define TO_FIXED_WIDTH (TO_FIXED_SIZE * BITS_PER_UNIT)
+#define TO_FIXED_WIDTH (TO_FIXED_SIZE * __CHAR_BIT__)
#define TO_FBITS FBITS2(TO_MODE_NAME)
#define TO_IBITS IBITS2(TO_MODE_NAME)
#define TO_I_F_BITS (TO_FBITS + TO_IBITS)
diff --git a/libgcc/fp-bit.h b/libgcc/fp-bit.h
index d844f420fc6..29661be8a31 100644
--- a/libgcc/fp-bit.h
+++ b/libgcc/fp-bit.h
@@ -117,11 +117,11 @@ typedef unsigned int UTItype __attribute__ ((mode (TI)));
#define MAX_USI_INT (~(USItype)0)
#define MAX_SI_INT ((SItype) (MAX_USI_INT >> 1))
-#define BITS_PER_SI (4 * BITS_PER_UNIT)
+#define BITS_PER_SI (4 * __CHAR_BIT__)
#ifdef TMODES
#define MAX_UDI_INT (~(UDItype)0)
#define MAX_DI_INT ((DItype) (MAX_UDI_INT >> 1))
-#define BITS_PER_DI (8 * BITS_PER_UNIT)
+#define BITS_PER_DI (8 * __CHAR_BIT__)
#endif
#ifdef FLOAT_ONLY
diff --git a/libgcc/libgcc2.c b/libgcc/libgcc2.c
index c7376206d64..90dba06ed72 100644
--- a/libgcc/libgcc2.c
+++ b/libgcc/libgcc2.c
@@ -160,7 +160,7 @@ __mulvSI3 (Wtype a, Wtype b)
}
#ifdef COMPAT_SIMODE_TRAPPING_ARITHMETIC
#undef WORD_SIZE
-#define WORD_SIZE (sizeof (SItype) * BITS_PER_UNIT)
+#define WORD_SIZE (sizeof (SItype) * __CHAR_BIT__)
SItype
__mulvsi3 (SItype a, SItype b)
{
@@ -820,16 +820,16 @@ const UQItype __popcount_tab[256] =
#endif
#if defined(L_popcountsi2) || defined(L_popcountdi2)
-#define POPCOUNTCST2(x) (((UWtype) x << BITS_PER_UNIT) | x)
-#define POPCOUNTCST4(x) (((UWtype) x << (2 * BITS_PER_UNIT)) | x)
-#define POPCOUNTCST8(x) (((UWtype) x << (4 * BITS_PER_UNIT)) | x)
-#if W_TYPE_SIZE == BITS_PER_UNIT
+#define POPCOUNTCST2(x) (((UWtype) x << __CHAR_BIT__) | x)
+#define POPCOUNTCST4(x) (((UWtype) x << (2 * __CHAR_BIT__)) | x)
+#define POPCOUNTCST8(x) (((UWtype) x << (4 * __CHAR_BIT__)) | x)
+#if W_TYPE_SIZE == __CHAR_BIT__
#define POPCOUNTCST(x) x
-#elif W_TYPE_SIZE == 2 * BITS_PER_UNIT
+#elif W_TYPE_SIZE == 2 * __CHAR_BIT__
#define POPCOUNTCST(x) POPCOUNTCST2 (x)
-#elif W_TYPE_SIZE == 4 * BITS_PER_UNIT
+#elif W_TYPE_SIZE == 4 * __CHAR_BIT__
#define POPCOUNTCST(x) POPCOUNTCST4 (POPCOUNTCST2 (x))
-#elif W_TYPE_SIZE == 8 * BITS_PER_UNIT
+#elif W_TYPE_SIZE == 8 * __CHAR_BIT__
#define POPCOUNTCST(x) POPCOUNTCST8 (POPCOUNTCST4 (POPCOUNTCST2 (x)))
#endif
#endif
@@ -842,11 +842,11 @@ __popcountSI2 (UWtype x)
/* Force table lookup on targets like AVR and RL78 which only
pretend they have LIBGCC2_UNITS_PER_WORD 4, but actually
have 1, and other small word targets. */
-#if __SIZEOF_INT__ > 2 && defined (POPCOUNTCST) && BITS_PER_UNIT == 8
+#if __SIZEOF_INT__ > 2 && defined (POPCOUNTCST) && __CHAR_BIT__ == 8
x = x - ((x >> 1) & POPCOUNTCST (0x55));
x = (x & POPCOUNTCST (0x33)) + ((x >> 2) & POPCOUNTCST (0x33));
x = (x + (x >> 4)) & POPCOUNTCST (0x0F);
- return (x * POPCOUNTCST (0x01)) >> (W_TYPE_SIZE - BITS_PER_UNIT);
+ return (x * POPCOUNTCST (0x01)) >> (W_TYPE_SIZE - __CHAR_BIT__);
#else
int i, ret = 0;
@@ -866,7 +866,7 @@ __popcountDI2 (UDWtype x)
/* Force table lookup on targets like AVR and RL78 which only
pretend they have LIBGCC2_UNITS_PER_WORD 4, but actually
have 1, and other small word targets. */
-#if __SIZEOF_INT__ > 2 && defined (POPCOUNTCST) && BITS_PER_UNIT == 8
+#if __SIZEOF_INT__ > 2 && defined (POPCOUNTCST) && __CHAR_BIT__ == 8
const DWunion uu = {.ll = x};
UWtype x1 = uu.s.low, x2 = uu.s.high;
x1 = x1 - ((x1 >> 1) & POPCOUNTCST (0x55));
@@ -876,7 +876,7 @@ __popcountDI2 (UDWtype x)
x1 = (x1 + (x1 >> 4)) & POPCOUNTCST (0x0F);
x2 = (x2 + (x2 >> 4)) & POPCOUNTCST (0x0F);
x1 += x2;
- return (x1 * POPCOUNTCST (0x01)) >> (W_TYPE_SIZE - BITS_PER_UNIT);
+ return (x1 * POPCOUNTCST (0x01)) >> (W_TYPE_SIZE - __CHAR_BIT__);
#else
int i, ret = 0;
diff --git a/libgcc/libgcc2.h b/libgcc/libgcc2.h
index 98bb2742582..d689f3433da 100644
--- a/libgcc/libgcc2.h
+++ b/libgcc/libgcc2.h
@@ -178,7 +178,7 @@ typedef int shift_count_type __attribute__((mode (__libgcc_shift_count__)));
if it existed. */
#if LIBGCC2_UNITS_PER_WORD == 8
-#define W_TYPE_SIZE (8 * BITS_PER_UNIT)
+#define W_TYPE_SIZE (8 * __CHAR_BIT__)
#define Wtype DItype
#define UWtype UDItype
#define HWtype DItype
@@ -194,7 +194,7 @@ typedef int shift_count_type __attribute__((mode (__libgcc_shift_count__)));
#endif
#define COMPAT_SIMODE_TRAPPING_ARITHMETIC
#elif LIBGCC2_UNITS_PER_WORD == 4
-#define W_TYPE_SIZE (4 * BITS_PER_UNIT)
+#define W_TYPE_SIZE (4 * __CHAR_BIT__)
#define Wtype SItype
#define UWtype USItype
#define HWtype SItype
@@ -209,7 +209,7 @@ typedef int shift_count_type __attribute__((mode (__libgcc_shift_count__)));
#define __NDW(a,b) __ ## a ## di ## b
#endif
#elif LIBGCC2_UNITS_PER_WORD == 2
-#define W_TYPE_SIZE (2 * BITS_PER_UNIT)
+#define W_TYPE_SIZE (2 * __CHAR_BIT__)
#define Wtype HItype
#define UWtype UHItype
#define HWtype HItype
@@ -224,7 +224,7 @@ typedef int shift_count_type __attribute__((mode (__libgcc_shift_count__)));
#define __NDW(a,b) __ ## a ## si ## b
#endif
#else
-#define W_TYPE_SIZE BITS_PER_UNIT
+#define W_TYPE_SIZE __CHAR_BIT__
#define Wtype QItype
#define UWtype UQItype
#define HWtype QItype
diff --git a/libgcc/libgcov.h b/libgcc/libgcov.h
index 5f54907029b..363492ea2ad 100644
--- a/libgcc/libgcov.h
+++ b/libgcc/libgcov.h
@@ -43,7 +43,7 @@
#include "tm.h"
#include "libgcc_tm.h"
-#if BITS_PER_UNIT == 8
+#if __CHAR_BIT__ == 8
typedef unsigned gcov_unsigned_t __attribute__ ((mode (SI)));
typedef unsigned gcov_position_t __attribute__ ((mode (SI)));
#if LONG_LONG_TYPE_SIZE > 32
@@ -54,7 +54,7 @@ typedef signed gcov_type __attribute__ ((mode (SI)));
typedef unsigned gcov_type_unsigned __attribute__ ((mode (SI)));
#endif
#else
-#if BITS_PER_UNIT == 16
+#if __CHAR_BIT__ == 16
typedef unsigned gcov_unsigned_t __attribute__ ((mode (HI)));
typedef unsigned gcov_position_t __attribute__ ((mode (HI)));
#if LONG_LONG_TYPE_SIZE > 32
diff --git a/libgo/Makefile.am b/libgo/Makefile.am
index ef671c4a547..bf26a4cb667 100644
--- a/libgo/Makefile.am
+++ b/libgo/Makefile.am
@@ -787,10 +787,14 @@ endif
endif
if LIBGO_IS_LINUX
-go_net_cloexec_file = go/net/sock_cloexec.go
+go_net_cloexec_file = go/net/sock_cloexec.go go/net/hook_cloexec.go
+else
+if LIBGO_IS_FREEBSD
+go_net_cloexec_file = go/net/sock_cloexec.go go/net/hook_cloexec.go
else
go_net_cloexec_file = go/net/sys_cloexec.go
endif
+endif
if LIBGO_IS_OPENBSD
go_net_tcpsockopt_file = go/net/tcpsockopt_openbsd.go
@@ -825,7 +829,6 @@ go_net_common_files = \
go/net/file.go \
go/net/file_unix.go \
go/net/hook.go \
- go/net/hook_cloexec.go \
go/net/hook_unix.go \
go/net/hosts.go \
go/net/interface.go \
@@ -1985,6 +1988,12 @@ else
syscall_exec_test_file =
endif
+if LIBGO_IS_LINUX
+syscall_os_file =
+else
+syscall_os_file = go/syscall/libcall_bsd.go
+endif
+
go_base_syscall_files = \
go/syscall/env_unix.go \
go/syscall/syscall_errno.go \
@@ -2003,6 +2012,7 @@ go_base_syscall_files = \
$(syscall_sleep_file) \
$(syscall_errstr_file) \
$(syscall_size_file) \
+ $(syscall_os_file) \
$(syscall_socket_file) \
$(syscall_socket_os_file) \
$(syscall_socket_type_file) \
diff --git a/libgo/Makefile.in b/libgo/Makefile.in
index 44175b96dbf..bcfed74b927 100644
--- a/libgo/Makefile.in
+++ b/libgo/Makefile.in
@@ -1089,8 +1089,9 @@ go_mime_files = \
@LIBGO_IS_DRAGONFLY_TRUE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_NETBSD_FALSE@go_net_interface_file = go/net/interface_dragonfly.go
@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_NETBSD_TRUE@go_net_interface_file = go/net/interface_netbsd.go
@LIBGO_IS_LINUX_TRUE@go_net_interface_file = go/net/interface_linux.go
-@LIBGO_IS_LINUX_FALSE@go_net_cloexec_file = go/net/sys_cloexec.go
-@LIBGO_IS_LINUX_TRUE@go_net_cloexec_file = go/net/sock_cloexec.go
+@LIBGO_IS_FREEBSD_FALSE@@LIBGO_IS_LINUX_FALSE@go_net_cloexec_file = go/net/sys_cloexec.go
+@LIBGO_IS_FREEBSD_TRUE@@LIBGO_IS_LINUX_FALSE@go_net_cloexec_file = go/net/sock_cloexec.go go/net/hook_cloexec.go
+@LIBGO_IS_LINUX_TRUE@go_net_cloexec_file = go/net/sock_cloexec.go go/net/hook_cloexec.go
@LIBGO_IS_DARWIN_FALSE@@LIBGO_IS_DRAGONFLY_FALSE@@LIBGO_IS_OPENBSD_FALSE@@LIBGO_IS_SOLARIS_FALSE@go_net_tcpsockopt_file = go/net/tcpsockopt_unix.go
@LIBGO_IS_DARWIN_FALSE@@LIBGO_IS_DRAGONFLY_TRUE@@LIBGO_IS_OPENBSD_FALSE@@LIBGO_IS_SOLARIS_FALSE@go_net_tcpsockopt_file = go/net/tcpsockopt_dragonfly.go
@LIBGO_IS_DARWIN_FALSE@@LIBGO_IS_OPENBSD_FALSE@@LIBGO_IS_SOLARIS_TRUE@go_net_tcpsockopt_file = go/net/tcpsockopt_solaris.go
@@ -1111,7 +1112,6 @@ go_net_common_files = \
go/net/file.go \
go/net/file_unix.go \
go/net/hook.go \
- go/net/hook_cloexec.go \
go/net/hook_unix.go \
go/net/hosts.go \
go/net/interface.go \
@@ -2076,6 +2076,8 @@ go_unicode_utf8_files = \
@LIBGO_IS_LINUX_TRUE@syscall_creds_test_file = go/syscall/creds_test.go
@LIBGO_IS_LINUX_FALSE@syscall_exec_test_file =
@LIBGO_IS_LINUX_TRUE@syscall_exec_test_file = go/syscall/exec_linux_test.go go/syscall/syscall_linux_test.go
+@LIBGO_IS_LINUX_FALSE@syscall_os_file = go/syscall/libcall_bsd.go
+@LIBGO_IS_LINUX_TRUE@syscall_os_file =
go_base_syscall_files = \
go/syscall/env_unix.go \
go/syscall/syscall_errno.go \
@@ -2094,6 +2096,7 @@ go_base_syscall_files = \
$(syscall_sleep_file) \
$(syscall_errstr_file) \
$(syscall_size_file) \
+ $(syscall_os_file) \
$(syscall_socket_file) \
$(syscall_socket_os_file) \
$(syscall_socket_type_file) \
diff --git a/libgo/go/encoding/json/decode_test.go b/libgo/go/encoding/json/decode_test.go
index 8aa158f08cd..51b15ef997c 100644
--- a/libgo/go/encoding/json/decode_test.go
+++ b/libgo/go/encoding/json/decode_test.go
@@ -118,6 +118,7 @@ type Top struct {
Loop
Embed0p // has Point with X, Y, used
Embed0q // has Point with Z, used
+ embed // contains exported field
}
type Embed0 struct {
@@ -148,6 +149,10 @@ type Embed0q struct {
Point
}
+type embed struct {
+ Q int
+}
+
type Loop struct {
Loop1 int `json:",omitempty"`
Loop2 int `json:",omitempty"`
@@ -331,7 +336,8 @@ var unmarshalTests = []unmarshalTest{
"Loop2": 14,
"X": 15,
"Y": 16,
- "Z": 17
+ "Z": 17,
+ "Q": 18
}`,
ptr: new(Top),
out: Top{
@@ -361,6 +367,9 @@ var unmarshalTests = []unmarshalTest{
Embed0q: Embed0q{
Point: Point{Z: 17},
},
+ embed: embed{
+ Q: 18,
+ },
},
},
{
@@ -507,12 +516,15 @@ func TestMarshalEmbeds(t *testing.T) {
Embed0q: Embed0q{
Point: Point{Z: 17},
},
+ embed: embed{
+ Q: 18,
+ },
}
b, err := Marshal(top)
if err != nil {
t.Fatal(err)
}
- want := "{\"Level0\":1,\"Level1b\":2,\"Level1c\":3,\"Level1a\":5,\"LEVEL1B\":6,\"e\":{\"Level1a\":8,\"Level1b\":9,\"Level1c\":10,\"Level1d\":11,\"x\":12},\"Loop1\":13,\"Loop2\":14,\"X\":15,\"Y\":16,\"Z\":17}"
+ want := "{\"Level0\":1,\"Level1b\":2,\"Level1c\":3,\"Level1a\":5,\"LEVEL1B\":6,\"e\":{\"Level1a\":8,\"Level1b\":9,\"Level1c\":10,\"Level1d\":11,\"x\":12},\"Loop1\":13,\"Loop2\":14,\"X\":15,\"Y\":16,\"Z\":17,\"Q\":18}"
if string(b) != want {
t.Errorf("Wrong marshal result.\n got: %q\nwant: %q", b, want)
}
diff --git a/libgo/go/encoding/json/encode.go b/libgo/go/encoding/json/encode.go
index 90782deb70b..e829a930768 100644
--- a/libgo/go/encoding/json/encode.go
+++ b/libgo/go/encoding/json/encode.go
@@ -1022,7 +1022,7 @@ func typeFields(t reflect.Type) []field {
// Scan f.typ for fields to include.
for i := 0; i < f.typ.NumField(); i++ {
sf := f.typ.Field(i)
- if sf.PkgPath != "" { // unexported
+ if sf.PkgPath != "" && !sf.Anonymous { // unexported
continue
}
tag := sf.Tag.Get("json")
diff --git a/libgo/go/encoding/xml/marshal_test.go b/libgo/go/encoding/xml/marshal_test.go
index 66675d7abc4..ef6c20e949b 100644
--- a/libgo/go/encoding/xml/marshal_test.go
+++ b/libgo/go/encoding/xml/marshal_test.go
@@ -139,6 +139,7 @@ type EmbedA struct {
EmbedC
EmbedB EmbedB
FieldA string
+ embedD
}
type EmbedB struct {
@@ -153,6 +154,11 @@ type EmbedC struct {
FieldC string
}
+type embedD struct {
+ fieldD string
+ FieldE string // Promoted and visible when embedD is embedded.
+}
+
type NameCasing struct {
XMLName struct{} `xml:"casing"`
Xy string
@@ -711,6 +717,9 @@ var marshalTests = []struct {
},
},
FieldA: "A.A",
+ embedD: embedD{
+ FieldE: "A.D.E",
+ },
},
ExpectXML: `<EmbedA>` +
`<FieldB>A.C.B</FieldB>` +
@@ -724,6 +733,7 @@ var marshalTests = []struct {
`<FieldC>A.B.C.C</FieldC>` +
`</EmbedB>` +
`<FieldA>A.A</FieldA>` +
+ `<FieldE>A.D.E</FieldE>` +
`</EmbedA>`,
},
diff --git a/libgo/go/encoding/xml/typeinfo.go b/libgo/go/encoding/xml/typeinfo.go
index 22248d20a6d..6766b88f09a 100644
--- a/libgo/go/encoding/xml/typeinfo.go
+++ b/libgo/go/encoding/xml/typeinfo.go
@@ -60,7 +60,7 @@ func getTypeInfo(typ reflect.Type) (*typeInfo, error) {
n := typ.NumField()
for i := 0; i < n; i++ {
f := typ.Field(i)
- if f.PkgPath != "" || f.Tag.Get("xml") == "-" {
+ if (f.PkgPath != "" && !f.Anonymous) || f.Tag.Get("xml") == "-" {
continue // Private field
}
diff --git a/libgo/go/net/tcpsockopt_solaris.go b/libgo/go/net/tcpsockopt_solaris.go
index 31f5df0526f..eaab6b6787b 100644
--- a/libgo/go/net/tcpsockopt_solaris.go
+++ b/libgo/go/net/tcpsockopt_solaris.go
@@ -1,7 +1,9 @@
-// Copyright 2015 The Go Authors. All rights reserved.
+// Copyright 2013 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
+// TCP socket options for solaris
+
package net
import (
@@ -10,26 +12,16 @@ import (
"time"
)
+// Set keep alive period.
func setKeepAlivePeriod(fd *netFD, d time.Duration) error {
if err := fd.incref(); err != nil {
return err
}
defer fd.decref()
- // The kernel expects milliseconds so round to next highest
- // millisecond.
- d += (time.Millisecond - time.Nanosecond)
- msecs := int(d / time.Millisecond)
- // Normally we'd do
- // syscall.SetsockoptInt(fd.sysfd, syscall.IPPROTO_TCP, syscall.TCP_KEEPINTVL, secs)
- // here, but we can't because Solaris does not have TCP_KEEPINTVL.
- // Solaris has TCP_KEEPALIVE_ABORT_THRESHOLD, but it's not the same
- // thing, it refers to the total time until aborting (not between
- // probes), and it uses an exponential backoff algorithm instead of
- // waiting the same time between probes. We can't hope for the best
- // and do it anyway, like on Darwin, because Solaris might eventually
- // allocate a constant with a different meaning for the value of
- // TCP_KEEPINTVL on illumos.
+ // The kernel expects seconds so round to next highest second.
+ d += (time.Second - time.Nanosecond)
+ secs := int(d.Seconds())
- return os.NewSyscallError("setsockopt", syscall.SetsockoptInt(fd.sysfd, syscall.IPPROTO_TCP, syscall.TCP_KEEPALIVE_THRESHOLD, msecs))
+ return os.NewSyscallError("setsockopt", syscall.SetsockoptInt(fd.sysfd, syscall.IPPROTO_TCP, syscall.SO_KEEPALIVE, secs))
}
diff --git a/libgo/go/reflect/export_test.go b/libgo/go/reflect/export_test.go
index 89473d352a7..bdbd60074ac 100644
--- a/libgo/go/reflect/export_test.go
+++ b/libgo/go/reflect/export_test.go
@@ -6,13 +6,13 @@ package reflect
// MakeRO returns a copy of v with the read-only flag set.
func MakeRO(v Value) Value {
- v.flag |= flagRO
+ v.flag |= flagStickyRO
return v
}
// IsRO reports whether v's read-only flag is set.
func IsRO(v Value) bool {
- return v.flag&flagRO != 0
+ return v.flag&flagStickyRO != 0
}
var CallGC = &callGC
diff --git a/libgo/go/reflect/type.go b/libgo/go/reflect/type.go
index e488938a13f..180a364de35 100644
--- a/libgo/go/reflect/type.go
+++ b/libgo/go/reflect/type.go
@@ -516,7 +516,7 @@ func (t *uncommonType) Method(i int) (m Method) {
fl := flag(Func)
if p.pkgPath != nil {
m.PkgPath = *p.pkgPath
- fl |= flagRO
+ fl |= flagStickyRO
}
mt := p.typ
m.Type = toType(mt)
diff --git a/libgo/go/reflect/value.go b/libgo/go/reflect/value.go
index a924d8639a2..8374370cfa6 100644
--- a/libgo/go/reflect/value.go
+++ b/libgo/go/reflect/value.go
@@ -44,7 +44,8 @@ type Value struct {
// flag holds metadata about the value.
// The lowest bits are flag bits:
- // - flagRO: obtained via unexported field, so read-only
+ // - flagStickyRO: obtained via unexported not embedded field, so read-only
+ // - flagEmbedRO: obtained via unexported embedded field, so read-only
// - flagIndir: val holds a pointer to the data
// - flagAddr: v.CanAddr is true (implies flagIndir)
// - flagMethod: v is a method value.
@@ -67,12 +68,14 @@ type flag uintptr
const (
flagKindWidth = 5 // there are 27 kinds
flagKindMask flag = 1<<flagKindWidth - 1
- flagRO flag = 1 << 5
- flagIndir flag = 1 << 6
- flagAddr flag = 1 << 7
- flagMethod flag = 1 << 8
- flagMethodFn flag = 1 << 9 // gccgo: first fn parameter is always pointer
- flagMethodShift = 10
+ flagStickyRO flag = 1 << 5
+ flagEmbedRO flag = 1 << 6
+ flagIndir flag = 1 << 7
+ flagAddr flag = 1 << 8
+ flagMethod flag = 1 << 9
+ flagMethodFn flag = 1 << 10 // gccgo: first fn parameter is always pointer
+ flagMethodShift = 11
+ flagRO flag = flagStickyRO | flagEmbedRO
)
func (f flag) kind() Kind {
@@ -617,11 +620,15 @@ func (v Value) Field(i int) Value {
field := &tt.fields[i]
typ := field.typ
- // Inherit permission bits from v.
- fl := v.flag&(flagRO|flagIndir|flagAddr) | flag(typ.Kind())
+ // Inherit permission bits from v, but clear flagEmbedRO.
+ fl := v.flag&(flagStickyRO|flagIndir|flagAddr) | flag(typ.Kind())
// Using an unexported field forces flagRO.
if field.pkgPath != nil {
- fl |= flagRO
+ if field.name == nil {
+ fl |= flagEmbedRO
+ } else {
+ fl |= flagStickyRO
+ }
}
// Either flagIndir is set and v.ptr points at struct,
// or flagIndir is not set and v.ptr is the actual struct data.
@@ -986,7 +993,7 @@ func (v Value) Method(i int) Value {
if v.typ.Kind() == Interface && v.IsNil() {
panic("reflect: Method on nil interface value")
}
- fl := v.flag & (flagRO | flagIndir)
+ fl := v.flag & (flagStickyRO | flagIndir) // Clear flagEmbedRO
fl |= flag(Func)
fl |= flag(i)<<flagMethodShift | flagMethod
return Value{v.typ, v.ptr, fl}
diff --git a/libgo/go/syscall/exec_bsd.go b/libgo/go/syscall/exec_bsd.go
index f44e897f39b..9042ce263aa 100644
--- a/libgo/go/syscall/exec_bsd.go
+++ b/libgo/go/syscall/exec_bsd.go
@@ -102,11 +102,9 @@ func forkAndExecInChild(argv0 *byte, argv, envv []*byte, chroot, dir *byte, attr
}
if sys.Foreground {
- pgrp := sys.Pgid
+ pgrp := Pid_t(sys.Pgid)
if pgrp == 0 {
- r1 = raw_getpid()
-
- pgrp = int(r1)
+ pgrp = raw_getpid()
}
// Place process group in foreground.
diff --git a/libgo/go/syscall/exec_linux.go b/libgo/go/syscall/exec_linux.go
index d9600a142ae..540efb3a6d8 100644
--- a/libgo/go/syscall/exec_linux.go
+++ b/libgo/go/syscall/exec_linux.go
@@ -171,14 +171,9 @@ func forkAndExecInChild(argv0 *byte, argv, envv []*byte, chroot, dir *byte, attr
}
if sys.Foreground {
- pgrp := int32(sys.Pgid)
+ pgrp := Pid_t(sys.Pgid)
if pgrp == 0 {
- r1 = uintptr(raw_getpid())
- if err1 != 0 {
- goto childerror
- }
-
- pgrp = int32(r1)
+ pgrp = raw_getpid()
}
// Place process group in foreground.
@@ -236,7 +231,7 @@ func forkAndExecInChild(argv0 *byte, argv, envv []*byte, chroot, dir *byte, attr
// using SIGKILL.
r1 := raw_getppid()
if r1 != ppid {
- pid = raw_getpid()
+ pid := raw_getpid()
err1 = raw_kill(pid, sys.Pdeathsig)
if err1 != 0 {
goto childerror
diff --git a/libgo/go/syscall/exec_unix.go b/libgo/go/syscall/exec_unix.go
index 218d78cf146..d1927de9b4b 100644
--- a/libgo/go/syscall/exec_unix.go
+++ b/libgo/go/syscall/exec_unix.go
@@ -17,10 +17,10 @@ import (
//sysnb raw_fork() (pid Pid_t, err Errno)
//fork() Pid_t
-//sysnb raw_getpid() (pid int)
+//sysnb raw_getpid() (pid Pid_t)
//getpid() Pid_t
-//sysnb raw_getppid() (pid int)
+//sysnb raw_getppid() (pid Pid_t)
//getppid() Pid_t
//sysnb raw_setsid() (err Errno)
@@ -59,7 +59,7 @@ import (
//sysnb raw_dup2(oldfd int, newfd int) (err Errno)
//dup2(oldfd _C_int, newfd _C_int) _C_int
-//sysnb raw_kill(pid int, sig Signal) (err Errno)
+//sysnb raw_kill(pid Pid_t, sig Signal) (err Errno)
//kill(pid Pid_t, sig _C_int) _C_int
//sysnb raw_setgroups(size int, list unsafe.Pointer) (err Errno)
diff --git a/libgo/go/syscall/exec_unix_test.go b/libgo/go/syscall/exec_unix_test.go
index 9bb95c0f395..69c4a1f1798 100644
--- a/libgo/go/syscall/exec_unix_test.go
+++ b/libgo/go/syscall/exec_unix_test.go
@@ -169,7 +169,7 @@ func TestForeground(t *testing.T) {
t.Skipf("Can't test Foreground. Couldn't open /dev/tty: %s", err)
}
- fpgrp := 0
+ fpgrp := syscall.Pid_t(0)
errno := syscall.Ioctl(tty.Fd(), syscall.TIOCGPGRP, uintptr(unsafe.Pointer(&fpgrp)))
if errno != 0 {
diff --git a/libgo/go/syscall/libcall_bsd.go b/libgo/go/syscall/libcall_bsd.go
new file mode 100644
index 00000000000..4501f88ad48
--- /dev/null
+++ b/libgo/go/syscall/libcall_bsd.go
@@ -0,0 +1,27 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// BSD library calls.
+
+package syscall
+
+import "unsafe"
+
+//sys sendfile(outfd int, infd int, offset *Offset_t, count int) (written int, err error)
+//sendfile(outfd _C_int, infd _C_int, offset *Offset_t, count Size_t) Ssize_t
+func Sendfile(outfd int, infd int, offset *int64, count int) (written int, err error) {
+ if raceenabled {
+ raceReleaseMerge(unsafe.Pointer(&ioSync))
+ }
+ var soff Offset_t
+ var psoff *Offset_t
+ if offset != nil {
+ psoff = &soff
+ }
+ written, err = sendfile(outfd, infd, psoff, count)
+ if offset != nil {
+ *offset = int64(soff)
+ }
+ return
+}
diff --git a/libgo/runtime/go-varargs.c b/libgo/runtime/go-varargs.c
index 534c0db94fa..691ee56582d 100644
--- a/libgo/runtime/go-varargs.c
+++ b/libgo/runtime/go-varargs.c
@@ -8,6 +8,7 @@
#include <errno.h>
#include <stdint.h>
+#include <unistd.h>
#include <sys/types.h>
#include <fcntl.h>
#include <sys/ioctl.h>
diff --git a/libgomp/ChangeLog b/libgomp/ChangeLog
index 26377b64060..ab2a25a1133 100644
--- a/libgomp/ChangeLog
+++ b/libgomp/ChangeLog
@@ -1,3 +1,8 @@
+2015-11-06 Thomas Schwinge <thomas@codesourcery.com>
+
+ * testsuite/libgomp.oacc-c-c++-common/loop-red-v-2.c: XFAIL.
+ * testsuite/libgomp.oacc-c-c++-common/loop-red-w-2.c: Likewise.
+
2015-11-05 Jakub Jelinek <jakub@redhat.com>
Ilya Verbin <ilya.verbin@intel.com>
diff --git a/libgomp/testsuite/libgomp.oacc-c-c++-common/loop-red-v-2.c b/libgomp/testsuite/libgomp.oacc-c-c++-common/loop-red-v-2.c
index e66732da32c..fbed589e146 100644
--- a/libgomp/testsuite/libgomp.oacc-c-c++-common/loop-red-v-2.c
+++ b/libgomp/testsuite/libgomp.oacc-c-c++-common/loop-red-v-2.c
@@ -1,5 +1,7 @@
/* { dg-do run } */
/* { dg-additional-options "-O2" */
+/* <http://news.gmane.org/find-root.php?message_id=%3C563B78B5.5090506%40acm.org%3E>
+ { dg-xfail-if "TODO" { *-*-* } } */
#include <stdio.h>
diff --git a/libgomp/testsuite/libgomp.oacc-c-c++-common/loop-red-w-2.c b/libgomp/testsuite/libgomp.oacc-c-c++-common/loop-red-w-2.c
index 0059077b685..47f1da02e2e 100644
--- a/libgomp/testsuite/libgomp.oacc-c-c++-common/loop-red-w-2.c
+++ b/libgomp/testsuite/libgomp.oacc-c-c++-common/loop-red-w-2.c
@@ -1,5 +1,7 @@
/* { dg-do run } */
/* { dg-additional-options "-O2" */
+/* <http://news.gmane.org/find-root.php?message_id=%3C563B78B5.5090506%40acm.org%3E>
+ { dg-xfail-if "TODO" { *-*-* } } */
#include <stdio.h>
diff --git a/libiberty/ChangeLog b/libiberty/ChangeLog
index b5ac8363c36..ca9b61a80af 100644
--- a/libiberty/ChangeLog
+++ b/libiberty/ChangeLog
@@ -1,3 +1,37 @@
+2015-11-09 Alan Modra <amodra@gmail.com>
+
+ * configure.ac: Check size of size_t.
+ * configure: Regenerate.
+ * config.in: Regenerate.
+
+2015-11-09 Alan Modra <amodra@gmail.com>
+
+ * obstack.c (_obstack_newchunk): Silence -Wc++compat warning.
+ (_obstack_begin_worker): Likewise. Move assignment to h->chunk
+ after alloc failure check.
+
+2015-11-09 Alan Modra <amodra@gmail.com>
+
+ PR gdb/17133
+ * obstack.c (__alignof__): Expand alignof_type from alignof.h.
+ (obstack_exit_failure): Don't use exitfail.h.
+ (_): Include libintl.h when HAVE_LIBINTL_H and nls enabled.
+ Provide default. Don't include gettext.h.
+ (_Noreturn): Define.
+ * obstacks.texi: Adjust node references to external libc info files.
+
+2015-11-09 Alan Modra <amodra@gmail.com>
+
+ PR gdb/17133
+ * obstack.c: Import current gnulib file.
+ * obstacks.texi: Updated doc, from glibc's manual/memory.texi.
+
+2015-11-06 Joel Brobecker <brobecker@adacore.com>
+
+ * configure.ac: Set AC_CV_FUNC_GETPAGESIZE to "yes" on
+ Android hosts.
+ * configure: Regenerate.
+
2015-10-28 Jason Merrill <jason@redhat.com>
* Makefile.in (TAGS): Fix for separate build directory.
diff --git a/libiberty/config.in b/libiberty/config.in
index 0dedbf08e0f..1ff50c67f60 100644
--- a/libiberty/config.in
+++ b/libiberty/config.in
@@ -470,6 +470,9 @@
/* The size of `long long', as computed by sizeof. */
#undef SIZEOF_LONG_LONG
+/* The size of `size_t', as computed by sizeof. */
+#undef SIZEOF_SIZE_T
+
/* Define if you know the direction of stack growth for your system; otherwise
it will be automatically deduced at run-time. STACK_DIRECTION > 0 => grows
toward higher addresses STACK_DIRECTION < 0 => grows toward lower addresses
diff --git a/libiberty/configure b/libiberty/configure
index da2df4ec740..bde78ffd25d 100755
--- a/libiberty/configure
+++ b/libiberty/configure
@@ -4389,6 +4389,12 @@ fi
ac_c_preproc_warn_flag=yes
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
ac_libiberty_warn_cflags=
save_CFLAGS="$CFLAGS"
for real_option in -W -Wall -Wwrite-strings -Wc++-compat \
@@ -4434,6 +4440,18 @@ $as_echo "$ac_res" >&6; }
fi
done
CFLAGS="$save_CFLAGS"
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
# Do the check with the no- prefix removed from the warning options
# since gcc silently accepts any -Wno-* option on purpose
@@ -4471,6 +4489,12 @@ if test $acx_cv_prog_cc_pedantic_ = yes; then :
fi
fi
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
if test "x$CC" != xcc; then
@@ -5381,6 +5405,40 @@ cat >>confdefs.h <<_ACEOF
_ACEOF
+# The cast to long int works around a bug in the HP C Compiler
+# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects
+# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'.
+# This bug is HP SR number 8606223364.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of size_t" >&5
+$as_echo_n "checking size of size_t... " >&6; }
+if test "${ac_cv_sizeof_size_t+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (size_t))" "ac_cv_sizeof_size_t" "$ac_includes_default"; then :
+
+else
+ if test "$ac_cv_type_size_t" = yes; then
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+{ as_fn_set_status 77
+as_fn_error "cannot compute sizeof (size_t)
+See \`config.log' for more details." "$LINENO" 5; }; }
+ else
+ ac_cv_sizeof_size_t=0
+ fi
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_size_t" >&5
+$as_echo "$ac_cv_sizeof_size_t" >&6; }
+
+
+
+cat >>confdefs.h <<_ACEOF
+#define SIZEOF_SIZE_T $ac_cv_sizeof_size_t
+_ACEOF
+
+
# Check for presense of long long
ac_fn_c_check_type "$LINENO" "long long" "ac_cv_type_long_long" "$ac_includes_default"
@@ -6224,6 +6282,12 @@ if test -z "${setobjs}"; then
case "${host}" in
+ *-*-android*)
+ # On android, getpagesize is defined in unistd.h as a static inline
+ # function, which AC_CHECK_FUNCS does not handle properly.
+ ac_cv_func_getpagesize=yes
+ ;;
+
*-*-mingw32*)
# Under mingw32, sys_nerr and sys_errlist exist, but they are
# macros, so the test below won't find them.
diff --git a/libiberty/configure.ac b/libiberty/configure.ac
index 868be8e72d1..9d3f2988d5d 100644
--- a/libiberty/configure.ac
+++ b/libiberty/configure.ac
@@ -276,6 +276,7 @@ libiberty_AC_DECLARE_ERRNO
# Determine sizes of some types.
AC_CHECK_SIZEOF([int])
AC_CHECK_SIZEOF([long])
+AC_CHECK_SIZEOF([size_t])
# Check for presense of long long
AC_CHECK_TYPE([long long],
@@ -600,6 +601,12 @@ if test -z "${setobjs}"; then
case "${host}" in
+ *-*-android*)
+ # On android, getpagesize is defined in unistd.h as a static inline
+ # function, which AC_CHECK_FUNCS does not handle properly.
+ ac_cv_func_getpagesize=yes
+ ;;
+
*-*-mingw32*)
# Under mingw32, sys_nerr and sys_errlist exist, but they are
# macros, so the test below won't find them.
diff --git a/libiberty/obstack.c b/libiberty/obstack.c
index a6dbaf095df..6d8d67261dd 100644
--- a/libiberty/obstack.c
+++ b/libiberty/obstack.c
@@ -1,35 +1,32 @@
/* obstack.c - subroutines used implicitly by object stack macros
- Copyright (C) 1988,89,90,91,92,93,94,96,97 Free Software Foundation, Inc.
+ Copyright (C) 1988-2015 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ The GNU C 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.
- NOTE: This source is derived from an old version taken from the GNU C
- Library (glibc).
-
- This program is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License as published by the
- Free Software Foundation; either version 2, or (at your option) any
- later version.
-
- This program is distributed in the hope that it will be useful,
+ The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
+ 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 General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301,
- USA. */
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-#include "obstack.h"
+#ifdef _LIBC
+# include <obstack.h>
+#else
+# include <config.h>
+# include "obstack.h"
+#endif
-/* NOTE BEFORE MODIFYING THIS FILE: This version number must be
- incremented whenever callers compiled using an old obstack.h can no
- longer properly call the functions in this obstack.c. */
-#define OBSTACK_INTERFACE_VERSION 1
+/* NOTE BEFORE MODIFYING THIS FILE: _OBSTACK_INTERFACE_VERSION in
+ obstack.h must be incremented whenever callers compiled using an old
+ obstack.h can no longer properly call the functions in this file. */
/* Comment out all this code if we are using the GNU C Library, and are not
actually compiling the library itself, and the installed library
@@ -37,144 +34,117 @@
C Library, but also included in many other GNU distributions. Compiling
and linking in this code is a waste when using the GNU C library
(especially if it is a shared library). Rather than having every GNU
- program understand `configure --with-gnu-libc' and omit the object
+ program understand 'configure --with-gnu-libc' and omit the object
files, it is simpler to just do this in the source for each such file. */
-
-#include <stdio.h> /* Random thing to get __GNU_LIBRARY__. */
-#if !defined (_LIBC) && defined (__GNU_LIBRARY__) && __GNU_LIBRARY__ > 1
-#include <gnu-versions.h>
-#if _GNU_OBSTACK_INTERFACE_VERSION == OBSTACK_INTERFACE_VERSION
-#define ELIDE_CODE
-#endif
+#if !defined _LIBC && defined __GNU_LIBRARY__ && __GNU_LIBRARY__ > 1
+# include <gnu-versions.h>
+# if (_GNU_OBSTACK_INTERFACE_VERSION == _OBSTACK_INTERFACE_VERSION \
+ || (_GNU_OBSTACK_INTERFACE_VERSION == 1 \
+ && _OBSTACK_INTERFACE_VERSION == 2 \
+ && defined SIZEOF_INT && defined SIZEOF_SIZE_T \
+ && SIZEOF_INT == SIZEOF_SIZE_T))
+# define _OBSTACK_ELIDE_CODE
+# endif
#endif
+#ifndef _OBSTACK_ELIDE_CODE
+/* If GCC, or if an oddball (testing?) host that #defines __alignof__,
+ use the already-supplied __alignof__. Otherwise, this must be Gnulib
+ (as glibc assumes GCC); defer to Gnulib's alignof_type. */
+# if !defined __GNUC__ && !defined __IBM__ALIGNOF__ && !defined __alignof__
+# if defined __cplusplus
+template <class type> struct alignof_helper { char __slot1; type __slot2; };
+# define __alignof__(type) offsetof (alignof_helper<type>, __slot2)
+# else
+# define __alignof__(type) \
+ offsetof (struct { char __slot1; type __slot2; }, __slot2)
+# endif
+# endif
+# include <stdlib.h>
+# include <stdint.h>
-#ifndef ELIDE_CODE
-
-
-#define POINTER void *
+# ifndef MAX
+# define MAX(a,b) ((a) > (b) ? (a) : (b))
+# endif
/* Determine default alignment. */
-struct fooalign {char x; double d;};
-#define DEFAULT_ALIGNMENT \
- ((PTR_INT_TYPE) ((char *) &((struct fooalign *) 0)->d - (char *) 0))
+
/* If malloc were really smart, it would round addresses to DEFAULT_ALIGNMENT.
But in fact it might be less smart and round addresses to as much as
- DEFAULT_ROUNDING. So we prepare for it to do that. */
-union fooround {long x; double d;};
-#define DEFAULT_ROUNDING (sizeof (union fooround))
-
-/* When we copy a long block of data, this is the unit to do it with.
- On some machines, copying successive ints does not work;
- in such a case, redefine COPYING_UNIT to `long' (if that works)
- or `char' as a last resort. */
-#ifndef COPYING_UNIT
-#define COPYING_UNIT int
-#endif
-
-
-/* The functions allocating more room by calling `obstack_chunk_alloc'
- jump to the handler pointed to by `obstack_alloc_failed_handler'.
- This variable by default points to the internal function
- `print_and_abort'. */
-static void print_and_abort (void);
-void (*obstack_alloc_failed_handler) (void) = print_and_abort;
+ DEFAULT_ROUNDING. So we prepare for it to do that.
+
+ DEFAULT_ALIGNMENT cannot be an enum constant; see gnulib's alignof.h. */
+#define DEFAULT_ALIGNMENT MAX (__alignof__ (long double), \
+ MAX (__alignof__ (uintmax_t), \
+ __alignof__ (void *)))
+#define DEFAULT_ROUNDING MAX (sizeof (long double), \
+ MAX (sizeof (uintmax_t), \
+ sizeof (void *)))
+
+/* Call functions with either the traditional malloc/free calling
+ interface, or the mmalloc/mfree interface (that adds an extra first
+ argument), based on the value of use_extra_arg. */
+
+static void *
+call_chunkfun (struct obstack *h, size_t size)
+{
+ if (h->use_extra_arg)
+ return h->chunkfun.extra (h->extra_arg, size);
+ else
+ return h->chunkfun.plain (size);
+}
-/* Exit value used when `print_and_abort' is used. */
-#if defined __GNU_LIBRARY__ || defined HAVE_STDLIB_H
-#include <stdlib.h>
-#endif
-#ifndef EXIT_FAILURE
-#define EXIT_FAILURE 1
-#endif
-int obstack_exit_failure = EXIT_FAILURE;
+static void
+call_freefun (struct obstack *h, void *old_chunk)
+{
+ if (h->use_extra_arg)
+ h->freefun.extra (h->extra_arg, old_chunk);
+ else
+ h->freefun.plain (old_chunk);
+}
-/* The non-GNU-C macros copy the obstack into this global variable
- to avoid multiple evaluation. */
-
-struct obstack *_obstack;
-
-/* Define a macro that either calls functions with the traditional malloc/free
- calling interface, or calls functions with the mmalloc/mfree interface
- (that adds an extra first argument), based on the state of use_extra_arg.
- For free, do not use ?:, since some compilers, like the MIPS compilers,
- do not allow (expr) ? void : void. */
-
-#if defined (__STDC__) && __STDC__
-#define CALL_CHUNKFUN(h, size) \
- (((h) -> use_extra_arg) \
- ? (*(h)->chunkfun) ((h)->extra_arg, (size)) \
- : (*(struct _obstack_chunk *(*) (long)) (h)->chunkfun) ((size)))
-
-#define CALL_FREEFUN(h, old_chunk) \
- do { \
- if ((h) -> use_extra_arg) \
- (*(h)->freefun) ((h)->extra_arg, (old_chunk)); \
- else \
- (*(void (*) (void *)) (h)->freefun) ((old_chunk)); \
- } while (0)
-#else
-#define CALL_CHUNKFUN(h, size) \
- (((h) -> use_extra_arg) \
- ? (*(h)->chunkfun) ((h)->extra_arg, (size)) \
- : (*(struct _obstack_chunk *(*) ()) (h)->chunkfun) ((size)))
-
-#define CALL_FREEFUN(h, old_chunk) \
- do { \
- if ((h) -> use_extra_arg) \
- (*(h)->freefun) ((h)->extra_arg, (old_chunk)); \
- else \
- (*(void (*) ()) (h)->freefun) ((old_chunk)); \
- } while (0)
-#endif
-
/* Initialize an obstack H for use. Specify chunk size SIZE (0 means default).
Objects start on multiples of ALIGNMENT (0 means use default).
- CHUNKFUN is the function to use to allocate chunks,
- and FREEFUN the function to free them.
- Return nonzero if successful, zero if out of memory.
- To recover from an out of memory error,
- free up some memory, then call this again. */
+ Return nonzero if successful, calls obstack_alloc_failed_handler if
+ allocation fails. */
-int
-_obstack_begin (struct obstack *h, int size, int alignment,
- POINTER (*chunkfun) (long), void (*freefun) (void *))
+static int
+_obstack_begin_worker (struct obstack *h,
+ _OBSTACK_SIZE_T size, _OBSTACK_SIZE_T alignment)
{
- register struct _obstack_chunk *chunk; /* points to new chunk */
+ struct _obstack_chunk *chunk; /* points to new chunk */
if (alignment == 0)
- alignment = (int) DEFAULT_ALIGNMENT;
+ alignment = DEFAULT_ALIGNMENT;
if (size == 0)
/* Default size is what GNU malloc can fit in a 4096-byte block. */
{
/* 12 is sizeof (mhead) and 4 is EXTRA from GNU malloc.
- Use the values for range checking, because if range checking is off,
- the extra bytes won't be missed terribly, but if range checking is on
- and we used a larger request, a whole extra 4096 bytes would be
- allocated.
+ Use the values for range checking, because if range checking is off,
+ the extra bytes won't be missed terribly, but if range checking is on
+ and we used a larger request, a whole extra 4096 bytes would be
+ allocated.
- These number are irrelevant to the new GNU malloc. I suspect it is
- less sensitive to the size of the request. */
+ These number are irrelevant to the new GNU malloc. I suspect it is
+ less sensitive to the size of the request. */
int extra = ((((12 + DEFAULT_ROUNDING - 1) & ~(DEFAULT_ROUNDING - 1))
- + 4 + DEFAULT_ROUNDING - 1)
- & ~(DEFAULT_ROUNDING - 1));
+ + 4 + DEFAULT_ROUNDING - 1)
+ & ~(DEFAULT_ROUNDING - 1));
size = 4096 - extra;
}
- h->chunkfun = (struct _obstack_chunk * (*)(void *, long)) chunkfun;
- h->freefun = (void (*) (void *, struct _obstack_chunk *)) freefun;
h->chunk_size = size;
h->alignment_mask = alignment - 1;
- h->use_extra_arg = 0;
- chunk = h->chunk = CALL_CHUNKFUN (h, h -> chunk_size);
+ chunk = (struct _obstack_chunk *) call_chunkfun (h, h->chunk_size);
if (!chunk)
(*obstack_alloc_failed_handler) ();
- h->next_free = h->object_base = chunk->contents;
- h->chunk_limit = chunk->limit
- = (char *) chunk + h->chunk_size;
+ h->chunk = chunk;
+ h->next_free = h->object_base = __PTR_ALIGN ((char *) chunk, chunk->contents,
+ alignment - 1);
+ h->chunk_limit = chunk->limit = (char *) chunk + h->chunk_size;
chunk->prev = 0;
/* The initial chunk now contains no empty object. */
h->maybe_empty_object = 0;
@@ -183,49 +153,29 @@ _obstack_begin (struct obstack *h, int size, int alignment,
}
int
-_obstack_begin_1 (struct obstack *h, int size, int alignment,
- POINTER (*chunkfun) (POINTER, long),
- void (*freefun) (POINTER, POINTER), POINTER arg)
+_obstack_begin (struct obstack *h,
+ _OBSTACK_SIZE_T size, _OBSTACK_SIZE_T alignment,
+ void *(*chunkfun) (size_t),
+ void (*freefun) (void *))
{
- register struct _obstack_chunk *chunk; /* points to new chunk */
-
- if (alignment == 0)
- alignment = (int) DEFAULT_ALIGNMENT;
- if (size == 0)
- /* Default size is what GNU malloc can fit in a 4096-byte block. */
- {
- /* 12 is sizeof (mhead) and 4 is EXTRA from GNU malloc.
- Use the values for range checking, because if range checking is off,
- the extra bytes won't be missed terribly, but if range checking is on
- and we used a larger request, a whole extra 4096 bytes would be
- allocated.
-
- These number are irrelevant to the new GNU malloc. I suspect it is
- less sensitive to the size of the request. */
- int extra = ((((12 + DEFAULT_ROUNDING - 1) & ~(DEFAULT_ROUNDING - 1))
- + 4 + DEFAULT_ROUNDING - 1)
- & ~(DEFAULT_ROUNDING - 1));
- size = 4096 - extra;
- }
+ h->chunkfun.plain = chunkfun;
+ h->freefun.plain = freefun;
+ h->use_extra_arg = 0;
+ return _obstack_begin_worker (h, size, alignment);
+}
- h->chunkfun = (struct _obstack_chunk * (*)(void *,long)) chunkfun;
- h->freefun = (void (*) (void *, struct _obstack_chunk *)) freefun;
- h->chunk_size = size;
- h->alignment_mask = alignment - 1;
+int
+_obstack_begin_1 (struct obstack *h,
+ _OBSTACK_SIZE_T size, _OBSTACK_SIZE_T alignment,
+ void *(*chunkfun) (void *, size_t),
+ void (*freefun) (void *, void *),
+ void *arg)
+{
+ h->chunkfun.extra = chunkfun;
+ h->freefun.extra = freefun;
h->extra_arg = arg;
h->use_extra_arg = 1;
-
- chunk = h->chunk = CALL_CHUNKFUN (h, h -> chunk_size);
- if (!chunk)
- (*obstack_alloc_failed_handler) ();
- h->next_free = h->object_base = chunk->contents;
- h->chunk_limit = chunk->limit
- = (char *) chunk + h->chunk_size;
- chunk->prev = 0;
- /* The initial chunk now contains no empty object. */
- h->maybe_empty_object = 0;
- h->alloc_failed = 0;
- return 1;
+ return _obstack_begin_worker (h, size, alignment);
}
/* Allocate a new current chunk for the obstack *H
@@ -235,58 +185,51 @@ _obstack_begin_1 (struct obstack *h, int size, int alignment,
to the beginning of the new one. */
void
-_obstack_newchunk (struct obstack *h, int length)
+_obstack_newchunk (struct obstack *h, _OBSTACK_SIZE_T length)
{
- register struct _obstack_chunk *old_chunk = h->chunk;
- register struct _obstack_chunk *new_chunk;
- register long new_size;
- register long obj_size = h->next_free - h->object_base;
- register long i;
- long already;
+ struct _obstack_chunk *old_chunk = h->chunk;
+ struct _obstack_chunk *new_chunk = 0;
+ size_t obj_size = h->next_free - h->object_base;
+ char *object_base;
/* Compute size for new chunk. */
- new_size = (obj_size + length) + (obj_size >> 3) + 100;
+ size_t sum1 = obj_size + length;
+ size_t sum2 = sum1 + h->alignment_mask;
+ size_t new_size = sum2 + (obj_size >> 3) + 100;
+ if (new_size < sum2)
+ new_size = sum2;
if (new_size < h->chunk_size)
new_size = h->chunk_size;
/* Allocate and initialize the new chunk. */
- new_chunk = CALL_CHUNKFUN (h, new_size);
+ if (obj_size <= sum1 && sum1 <= sum2)
+ new_chunk = (struct _obstack_chunk *) call_chunkfun (h, new_size);
if (!new_chunk)
- (*obstack_alloc_failed_handler) ();
+ (*obstack_alloc_failed_handler)();
h->chunk = new_chunk;
new_chunk->prev = old_chunk;
new_chunk->limit = h->chunk_limit = (char *) new_chunk + new_size;
- /* Move the existing object to the new chunk.
- Word at a time is fast and is safe if the object
- is sufficiently aligned. */
- if (h->alignment_mask + 1 >= DEFAULT_ALIGNMENT)
- {
- for (i = obj_size / sizeof (COPYING_UNIT) - 1;
- i >= 0; i--)
- ((COPYING_UNIT *)new_chunk->contents)[i]
- = ((COPYING_UNIT *)h->object_base)[i];
- /* We used to copy the odd few remaining bytes as one extra COPYING_UNIT,
- but that can cross a page boundary on a machine
- which does not do strict alignment for COPYING_UNITS. */
- already = obj_size / sizeof (COPYING_UNIT) * sizeof (COPYING_UNIT);
- }
- else
- already = 0;
- /* Copy remaining bytes one by one. */
- for (i = already; i < obj_size; i++)
- new_chunk->contents[i] = h->object_base[i];
+ /* Compute an aligned object_base in the new chunk */
+ object_base =
+ __PTR_ALIGN ((char *) new_chunk, new_chunk->contents, h->alignment_mask);
+
+ /* Move the existing object to the new chunk. */
+ memcpy (object_base, h->object_base, obj_size);
/* If the object just copied was the only data in OLD_CHUNK,
free that chunk and remove it from the chain.
But not if that chunk might contain an empty object. */
- if (h->object_base == old_chunk->contents && ! h->maybe_empty_object)
+ if (!h->maybe_empty_object
+ && (h->object_base
+ == __PTR_ALIGN ((char *) old_chunk, old_chunk->contents,
+ h->alignment_mask)))
{
new_chunk->prev = old_chunk->prev;
- CALL_FREEFUN (h, old_chunk);
+ call_freefun (h, old_chunk);
}
- h->object_base = new_chunk->contents;
+ h->object_base = object_base;
h->next_free = h->object_base + obj_size;
/* The new chunk certainly contains no empty object yet. */
h->maybe_empty_object = 0;
@@ -298,51 +241,46 @@ _obstack_newchunk (struct obstack *h, int length)
/* Suppress -Wmissing-prototypes warning. We don't want to declare this in
obstack.h because it is just for debugging. */
-int _obstack_allocated_p (struct obstack *h, POINTER obj);
+int _obstack_allocated_p (struct obstack *h, void *obj) __attribute_pure__;
int
-_obstack_allocated_p (struct obstack *h, POINTER obj)
+_obstack_allocated_p (struct obstack *h, void *obj)
{
- register struct _obstack_chunk *lp; /* below addr of any objects in this chunk */
- register struct _obstack_chunk *plp; /* point to previous chunk if any */
+ struct _obstack_chunk *lp; /* below addr of any objects in this chunk */
+ struct _obstack_chunk *plp; /* point to previous chunk if any */
lp = (h)->chunk;
/* We use >= rather than > since the object cannot be exactly at
the beginning of the chunk but might be an empty object exactly
at the end of an adjacent chunk. */
- while (lp != 0 && ((POINTER) lp >= obj || (POINTER) (lp)->limit < obj))
+ while (lp != 0 && ((void *) lp >= obj || (void *) (lp)->limit < obj))
{
plp = lp->prev;
lp = plp;
}
return lp != 0;
}
-
+
/* Free objects in obstack H, including OBJ and everything allocate
more recently than OBJ. If OBJ is zero, free everything in H. */
-#undef obstack_free
-
-/* This function has two names with identical definitions.
- This is the first one, called from non-ANSI code. */
-
void
-_obstack_free (struct obstack *h, POINTER obj)
+_obstack_free (struct obstack *h, void *obj)
{
- register struct _obstack_chunk *lp; /* below addr of any objects in this chunk */
- register struct _obstack_chunk *plp; /* point to previous chunk if any */
+ struct _obstack_chunk *lp; /* below addr of any objects in this chunk */
+ struct _obstack_chunk *plp; /* point to previous chunk if any */
lp = h->chunk;
/* We use >= because there cannot be an object at the beginning of a chunk.
But there can be an empty object at that address
at the end of another chunk. */
- while (lp != 0 && ((POINTER) lp >= obj || (POINTER) (lp)->limit < obj))
+ while (lp != 0 && ((void *) lp >= obj || (void *) (lp)->limit < obj))
{
plp = lp->prev;
- CALL_FREEFUN (h, lp);
+ call_freefun (h, lp);
lp = plp;
/* If we switch chunks, we can't tell whether the new current
- chunk contains an empty object, so assume that it may. */
+ chunk contains an empty object, so assume that it may. */
h->maybe_empty_object = 1;
}
if (lp)
@@ -356,43 +294,11 @@ _obstack_free (struct obstack *h, POINTER obj)
abort ();
}
-/* This function is used from ANSI code. */
-
-void
-obstack_free (struct obstack *h, POINTER obj)
-{
- register struct _obstack_chunk *lp; /* below addr of any objects in this chunk */
- register struct _obstack_chunk *plp; /* point to previous chunk if any */
-
- lp = h->chunk;
- /* We use >= because there cannot be an object at the beginning of a chunk.
- But there can be an empty object at that address
- at the end of another chunk. */
- while (lp != 0 && ((POINTER) lp >= obj || (POINTER) (lp)->limit < obj))
- {
- plp = lp->prev;
- CALL_FREEFUN (h, lp);
- lp = plp;
- /* If we switch chunks, we can't tell whether the new current
- chunk contains an empty object, so assume that it may. */
- h->maybe_empty_object = 1;
- }
- if (lp)
- {
- h->object_base = h->next_free = (char *) (obj);
- h->chunk_limit = lp->limit;
- h->chunk = lp;
- }
- else if (obj != 0)
- /* obj is not in any of the chunks! */
- abort ();
-}
-
-int
+_OBSTACK_SIZE_T
_obstack_memory_used (struct obstack *h)
{
- register struct _obstack_chunk* lp;
- register int nbytes = 0;
+ struct _obstack_chunk *lp;
+ _OBSTACK_SIZE_T nbytes = 0;
for (lp = h->chunk; lp != 0; lp = lp->prev)
{
@@ -400,111 +306,71 @@ _obstack_memory_used (struct obstack *h)
}
return nbytes;
}
-
-/* Define the error handler. */
-#ifndef _
-# if (HAVE_LIBINTL_H && ENABLE_NLS) || defined _LIBC
-# include <libintl.h>
-# ifndef _
-# define _(Str) gettext (Str)
-# endif
-# else
-# define _(Str) (Str)
-# endif
-#endif
-
-static void
-print_and_abort (void)
-{
- fputs (_("memory exhausted\n"), stderr);
- exit (obstack_exit_failure);
-}
-
-#if 0
-/* These are now turned off because the applications do not use it
- and it uses bcopy via obstack_grow, which causes trouble on sysV. */
-
-/* Now define the functional versions of the obstack macros.
- Define them to simply use the corresponding macros to do the job. */
-
-/* The function names appear in parentheses in order to prevent
- the macro-definitions of the names from being expanded there. */
-
-POINTER (obstack_base) (struct obstack *obstack)
-{
- return obstack_base (obstack);
-}
-
-POINTER (obstack_next_free) (struct obstack *obstack)
-{
- return obstack_next_free (obstack);
-}
-
-int (obstack_object_size) (struct obstack *obstack)
-{
- return obstack_object_size (obstack);
-}
-
-int (obstack_room) (struct obstack *obstack)
-{
- return obstack_room (obstack);
-}
-
-int (obstack_make_room) (struct obstack *obstack, int length)
-{
- return obstack_make_room (obstack, length);
-}
-
-void (obstack_grow) (struct obstack *obstack, POINTER pointer, int length)
-{
- obstack_grow (obstack, pointer, length);
-}
-
-void (obstack_grow0) (struct obstack *obstack, POINTER pointer, int length)
-{
- obstack_grow0 (obstack, pointer, length);
-}
-void (obstack_1grow) (struct obstack *obstack, int character)
-{
- obstack_1grow (obstack, character);
-}
-
-void (obstack_blank) (struct obstack *obstack, int length)
-{
- obstack_blank (obstack, length);
-}
-
-void (obstack_1grow_fast) (struct obstack *obstack, int character)
-{
- obstack_1grow_fast (obstack, character);
-}
+# ifndef _OBSTACK_NO_ERROR_HANDLER
+/* Define the error handler. */
+# include <stdio.h>
-void (obstack_blank_fast) (struct obstack *obstack, int length)
-{
- obstack_blank_fast (obstack, length);
-}
+/* Exit value used when 'print_and_abort' is used. */
+# ifdef _LIBC
+int obstack_exit_failure = EXIT_FAILURE;
+# else
+# ifndef EXIT_FAILURE
+# define EXIT_FAILURE 1
+# endif
+# define obstack_exit_failure EXIT_FAILURE
+# endif
-POINTER (obstack_finish) (struct obstack *obstack)
-{
- return obstack_finish (obstack);
-}
+# if defined _LIBC || (HAVE_LIBINTL_H && ENABLE_NLS)
+# include <libintl.h>
+# ifndef _
+# define _(msgid) gettext (msgid)
+# endif
+# else
+# ifndef _
+# define _(msgid) (msgid)
+# endif
+# endif
-POINTER (obstack_alloc) (struct obstack *obstack, int length)
-{
- return obstack_alloc (obstack, length);
-}
+# if !(defined _Noreturn \
+ || (defined __STDC_VERSION__ && __STDC_VERSION__ >= 201112))
+# if ((defined __GNUC__ \
+ && (__GNUC__ >= 3 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 8))) \
+ || (defined __SUNPRO_C && __SUNPRO_C >= 0x5110))
+# define _Noreturn __attribute__ ((__noreturn__))
+# elif defined _MSC_VER && _MSC_VER >= 1200
+# define _Noreturn __declspec (noreturn)
+# else
+# define _Noreturn
+# endif
+# endif
-POINTER (obstack_copy) (struct obstack *obstack, POINTER pointer, int length)
-{
- return obstack_copy (obstack, pointer, length);
-}
+# ifdef _LIBC
+# include <libio/iolibio.h>
+# endif
-POINTER (obstack_copy0) (struct obstack *obstack, POINTER pointer, int length)
+static _Noreturn void
+print_and_abort (void)
{
- return obstack_copy0 (obstack, pointer, length);
+ /* Don't change any of these strings. Yes, it would be possible to add
+ the newline to the string and use fputs or so. But this must not
+ happen because the "memory exhausted" message appears in other places
+ like this and the translation should be reused instead of creating
+ a very similar string which requires a separate translation. */
+# ifdef _LIBC
+ (void) __fxprintf (NULL, "%s\n", _("memory exhausted"));
+# else
+ fprintf (stderr, "%s\n", _("memory exhausted"));
+# endif
+ exit (obstack_exit_failure);
}
-#endif /* 0 */
-
-#endif /* !ELIDE_CODE */
+/* The functions allocating more room by calling 'obstack_chunk_alloc'
+ jump to the handler pointed to by 'obstack_alloc_failed_handler'.
+ This can be set to a user defined function which should either
+ abort gracefully or use longjump - but shouldn't return. This
+ variable by default points to the internal function
+ 'print_and_abort'. */
+void (*obstack_alloc_failed_handler) (void) = print_and_abort;
+# endif /* !_OBSTACK_NO_ERROR_HANDLER */
+#endif /* !_OBSTACK_ELIDE_CODE */
diff --git a/libiberty/obstacks.texi b/libiberty/obstacks.texi
index adcd8103da8..b2d2403210b 100644
--- a/libiberty/obstacks.texi
+++ b/libiberty/obstacks.texi
@@ -20,8 +20,7 @@ the padding needed to start each object on a suitable boundary.
use obstacks.
* Allocation in an Obstack:: Allocating objects in an obstack.
* Freeing Obstack Objects:: Freeing objects in an obstack.
-* Obstack Functions:: The obstack functions are both
- functions and macros.
+* Obstack Functions:: The obstack functions are really macros.
* Growing Objects:: Making an object bigger by stages.
* Extra Fast Growing:: Extra-high-efficiency (though more
complicated) growing objects.
@@ -46,7 +45,7 @@ An obstack is represented by a data structure of type @code{struct
obstack}. This structure has a small fixed size; it records the status
of the obstack and how to find the space in which objects are allocated.
It does not contain any of the objects themselves. You should not try
-to access the contents of the structure directly; use only the functions
+to access the contents of the structure directly; use only the macros
described in this chapter.
@end deftp
@@ -56,7 +55,7 @@ of object. Dynamic allocation of obstacks allows your program to have a
variable number of different stacks. (You can even allocate an
obstack structure in another obstack, but this is rarely useful.)
-All the functions that work with obstacks require you to specify which
+All the macros that work with obstacks require you to specify which
obstack to use. You do this with a pointer of type @code{struct obstack
*}. In the following, we often say ``an obstack'' when strictly
speaking the object at hand is such a pointer.
@@ -76,7 +75,7 @@ These matters are described in the following section.
@node Preparing for Obstacks
@subsubsection Preparing for Using Obstacks
-Each source file in which you plan to use the obstack functions
+Each source file in which you plan to use obstacks
must include the header file @file{obstack.h}, like this:
@smallexample
@@ -86,7 +85,7 @@ must include the header file @file{obstack.h}, like this:
@findex obstack_chunk_alloc
@findex obstack_chunk_free
Also, if the source file uses the macro @code{obstack_init}, it must
-declare or define two functions or macros that will be called by the
+declare or define two macros that will be called by the
obstack library. One, @code{obstack_chunk_alloc}, is used to allocate
the chunks of memory into which objects are packed. The other,
@code{obstack_chunk_free}, is used to return chunks when the objects in
@@ -109,16 +108,18 @@ larger blocks of memory. @xref{Obstack Chunks}, for full details.
At run time, before the program can use a @code{struct obstack} object
as an obstack, it must initialize the obstack by calling
-@code{obstack_init}.
+@code{obstack_init} or one of its variants, @code{obstack_begin},
+@code{obstack_specify_allocation}, or
+@code{obstack_specify_allocation_with_arg}.
@comment obstack.h
@comment GNU
@deftypefun int obstack_init (struct obstack *@var{obstack-ptr})
Initialize obstack @var{obstack-ptr} for allocation of objects. This
-function calls the obstack's @code{obstack_chunk_alloc} function. If
+macro calls the obstack's @code{obstack_chunk_alloc} function. If
allocation of memory fails, the function pointed to by
@code{obstack_alloc_failed_handler} is called. The @code{obstack_init}
-function always returns 1 (Compatibility notice: Former versions of
+macro always returns 1 (Compatibility notice: Former versions of
obstack returned 0 if allocation failed).
@end deftypefun
@@ -143,6 +144,29 @@ obstack_init (myobstack_ptr);
@comment obstack.h
@comment GNU
+@deftypefun int obstack_begin (struct obstack *@var{obstack-ptr}, size_t chunk_size)
+Like @code{obstack_init}, but specify chunks to be at least
+@var{chunk_size} bytes in size.
+@end deftypefun
+
+@comment obstack.h
+@comment GNU
+@deftypefun int obstack_specify_allocation (struct obstack *@var{obstack-ptr}, size_t chunk_size, size_t alignment, void *(*chunkfun) (size_t), void (*freefun) (void *))
+Like @code{obstack_init}, specifying chunk size, chunk
+alignment, and memory allocation functions. A @var{chunk_size} or
+@var{alignment} of zero results in the default size or alignment
+respectively being used.
+@end deftypefun
+
+@comment obstack.h
+@comment GNU
+@deftypefun int obstack_specify_allocation_with_arg (struct obstack *@var{obstack-ptr}, size_t chunk_size, size_t alignment, void *(*chunkfun) (void *, size_t), void (*freefun) (void *, void *), void *arg)
+Like @code{obstack_specify_allocation}, but specifying memory
+allocation functions that take an extra first argument, @var{arg}.
+@end deftypefun
+
+@comment obstack.h
+@comment GNU
@defvar obstack_alloc_failed_handler
The value of this variable is a pointer to a function that
@code{obstack} uses when @code{obstack_chunk_alloc} fails to allocate
@@ -168,14 +192,14 @@ The most direct way to allocate an object in an obstack is with
@comment obstack.h
@comment GNU
-@deftypefun {void *} obstack_alloc (struct obstack *@var{obstack-ptr}, int @var{size})
+@deftypefun {void *} obstack_alloc (struct obstack *@var{obstack-ptr}, size_t @var{size})
This allocates an uninitialized block of @var{size} bytes in an obstack
and returns its address. Here @var{obstack-ptr} specifies which obstack
to allocate the block in; it is the address of the @code{struct obstack}
-object which represents the obstack. Each obstack function or macro
+object which represents the obstack. Each obstack macro
requires you to specify an @var{obstack-ptr} as the first argument.
-This function calls the obstack's @code{obstack_chunk_alloc} function if
+This macro calls the obstack's @code{obstack_chunk_alloc} function if
it needs to allocate a new chunk of memory; it calls
@code{obstack_alloc_failed_handler} if allocation of memory by
@code{obstack_chunk_alloc} failed.
@@ -197,12 +221,11 @@ copystring (char *string)
@}
@end smallexample
-To allocate a block with specified contents, use the function
-@code{obstack_copy}, declared like this:
+To allocate a block with specified contents, use the macro @code{obstack_copy}.
@comment obstack.h
@comment GNU
-@deftypefun {void *} obstack_copy (struct obstack *@var{obstack-ptr}, void *@var{address}, int @var{size})
+@deftypefun {void *} obstack_copy (struct obstack *@var{obstack-ptr}, void *@var{address}, size_t @var{size})
This allocates a block and initializes it by copying @var{size}
bytes of data starting at @var{address}. It calls
@code{obstack_alloc_failed_handler} if allocation of memory by
@@ -211,18 +234,18 @@ bytes of data starting at @var{address}. It calls
@comment obstack.h
@comment GNU
-@deftypefun {void *} obstack_copy0 (struct obstack *@var{obstack-ptr}, void *@var{address}, int @var{size})
+@deftypefun {void *} obstack_copy0 (struct obstack *@var{obstack-ptr}, void *@var{address}, size_t @var{size})
Like @code{obstack_copy}, but appends an extra byte containing a null
character. This extra byte is not counted in the argument @var{size}.
@end deftypefun
-The @code{obstack_copy0} function is convenient for copying a sequence
+The @code{obstack_copy0} macro is convenient for copying a sequence
of characters into an obstack as a null-terminated string. Here is an
example of its use:
@smallexample
char *
-obstack_savestring (char *addr, int size)
+obstack_savestring (char *addr, size_t size)
@{
return obstack_copy0 (&myobstack, addr, size);
@}
@@ -236,7 +259,7 @@ Contrast this with the previous example of @code{savestring} using
@subsubsection Freeing Objects in an Obstack
@cindex freeing (obstacks)
-To free an object allocated in an obstack, use the function
+To free an object allocated in an obstack, use the macro
@code{obstack_free}. Since the obstack is a stack of objects, freeing
one object automatically frees all other objects allocated more recently
in the same obstack.
@@ -268,15 +291,12 @@ obstacks, or non-obstack allocation, can reuse the space of the chunk.
@subsubsection Obstack Functions and Macros
@cindex macros
-The interfaces for using obstacks may be defined either as functions or
-as macros, depending on the compiler. The obstack facility works with
-all C compilers, including both @w{ISO C} and traditional C, but there are
-precautions you must take if you plan to use compilers other than GNU C.
-
-If you are using an old-fashioned @w{non-ISO C} compiler, all the obstack
-``functions'' are actually defined only as macros. You can call these
-macros like functions, but you cannot use them in any other way (for
-example, you cannot take their address).
+The interfaces for using obstacks are shown here as functions to
+specify the return type and argument types, but they are really
+defined as macros. This means that the arguments don't actually have
+types, but they generally behave as if they have the types shown.
+You can call these macros like functions, but you cannot use them in
+any other way (for example, you cannot take their address).
Calling the macros requires a special precaution: namely, the first
operand (the obstack pointer) may not contain any side effects, because
@@ -292,34 +312,18 @@ If you use @code{*obstack_list_ptr++} as the obstack pointer argument,
you will get very strange results since the incrementation may occur
several times.
-In @w{ISO C}, each function has both a macro definition and a function
-definition. The function definition is used if you take the address of the
-function without calling it. An ordinary call uses the macro definition by
-default, but you can request the function definition instead by writing the
-function name in parentheses, as shown here:
-
-@smallexample
-char *x;
-void *(*funcp) ();
-/* @r{Use the macro}. */
-x = (char *) obstack_alloc (obptr, size);
-/* @r{Call the function}. */
-x = (char *) (obstack_alloc) (obptr, size);
-/* @r{Take the address of the function}. */
-funcp = obstack_alloc;
-@end smallexample
-
-@noindent
-This is the same situation that exists in @w{ISO C} for the standard library
-functions. @xref{Macro Definitions, , , libc, The GNU C Library Reference Manual}.
-
-@strong{Warning:} When you do use the macros, you must observe the
-precaution of avoiding side effects in the first operand, even in @w{ISO C}.
-
If you use the GNU C compiler, this precaution is not necessary, because
various language extensions in GNU C permit defining the macros so as to
compute each argument only once.
+Note that arguments other than the first will only be evaluated once,
+even when not using GNU C.
+
+@code{obstack.h} does declare a number of functions,
+@code{_obstack_begin}, @code{_obstack_begin_1},
+@code{_obstack_newchunk}, @code{_obstack_free}, and
+@code{_obstack_memory_used}. You should not call these directly.
+
@node Growing Objects
@subsubsection Growing Objects
@cindex growing objects (in obstacks)
@@ -329,13 +333,13 @@ Because memory in obstack chunks is used sequentially, it is possible to
build up an object step by step, adding one or more bytes at a time to the
end of the object. With this technique, you do not need to know how much
data you will put in the object until you come to the end of it. We call
-this the technique of @dfn{growing objects}. The special functions
+this the technique of @dfn{growing objects}. The special macros
for adding data to the growing object are described in this section.
You don't need to do anything special when you start to grow an object.
-Using one of the functions to add data to the object automatically
+Using one of the macros to add data to the object automatically
starts it. However, it is necessary to say explicitly when the object is
-finished. This is done with the function @code{obstack_finish}.
+finished. This is done with @code{obstack_finish}.
The actual address of the object thus built up is not known until the
object is finished. Until then, it always remains possible that you will
@@ -347,14 +351,14 @@ already added to the growing object will become part of the other object.
@comment obstack.h
@comment GNU
-@deftypefun void obstack_blank (struct obstack *@var{obstack-ptr}, int @var{size})
-The most basic function for adding to a growing object is
+@deftypefun void obstack_blank (struct obstack *@var{obstack-ptr}, size_t @var{size})
+The most basic macro for adding to a growing object is
@code{obstack_blank}, which adds space without initializing it.
@end deftypefun
@comment obstack.h
@comment GNU
-@deftypefun void obstack_grow (struct obstack *@var{obstack-ptr}, void *@var{data}, int @var{size})
+@deftypefun void obstack_grow (struct obstack *@var{obstack-ptr}, void *@var{data}, size_t @var{size})
To add a block of initialized space, use @code{obstack_grow}, which is
the growing-object analogue of @code{obstack_copy}. It adds @var{size}
bytes of data to the growing object, copying the contents from
@@ -363,7 +367,7 @@ bytes of data to the growing object, copying the contents from
@comment obstack.h
@comment GNU
-@deftypefun void obstack_grow0 (struct obstack *@var{obstack-ptr}, void *@var{data}, int @var{size})
+@deftypefun void obstack_grow0 (struct obstack *@var{obstack-ptr}, void *@var{data}, size_t @var{size})
This is the growing-object analogue of @code{obstack_copy0}. It adds
@var{size} bytes copied from @var{data}, followed by an additional null
character.
@@ -372,14 +376,14 @@ character.
@comment obstack.h
@comment GNU
@deftypefun void obstack_1grow (struct obstack *@var{obstack-ptr}, char @var{c})
-To add one character at a time, use the function @code{obstack_1grow}.
+To add one character at a time, use @code{obstack_1grow}.
It adds a single byte containing @var{c} to the growing object.
@end deftypefun
@comment obstack.h
@comment GNU
@deftypefun void obstack_ptr_grow (struct obstack *@var{obstack-ptr}, void *@var{data})
-Adding the value of a pointer one can use the function
+Adding the value of a pointer one can use
@code{obstack_ptr_grow}. It adds @code{sizeof (void *)} bytes
containing the value of @var{data}.
@end deftypefun
@@ -387,35 +391,31 @@ containing the value of @var{data}.
@comment obstack.h
@comment GNU
@deftypefun void obstack_int_grow (struct obstack *@var{obstack-ptr}, int @var{data})
-A single value of type @code{int} can be added by using the
-@code{obstack_int_grow} function. It adds @code{sizeof (int)} bytes to
+A single value of type @code{int} can be added by using
+@code{obstack_int_grow}. It adds @code{sizeof (int)} bytes to
the growing object and initializes them with the value of @var{data}.
@end deftypefun
@comment obstack.h
@comment GNU
@deftypefun {void *} obstack_finish (struct obstack *@var{obstack-ptr})
-When you are finished growing the object, use the function
+When you are finished growing the object, use
@code{obstack_finish} to close it off and return its final address.
Once you have finished the object, the obstack is available for ordinary
allocation or for growing another object.
-
-This function can return a null pointer under the same conditions as
-@code{obstack_alloc} (@pxref{Allocation in an Obstack}).
@end deftypefun
When you build an object by growing it, you will probably need to know
afterward how long it became. You need not keep track of this as you grow
-the object, because you can find out the length from the obstack just
-before finishing the object with the function @code{obstack_object_size},
-declared as follows:
+the object, because you can find out the length from the obstack
+with @code{obstack_object_size}, before finishing the object.
@comment obstack.h
@comment GNU
-@deftypefun int obstack_object_size (struct obstack *@var{obstack-ptr})
-This function returns the current size of the growing object, in bytes.
-Remember to call this function @emph{before} finishing the object.
+@deftypefun size_t obstack_object_size (struct obstack *@var{obstack-ptr})
+This macro returns the current size of the growing object, in bytes.
+Remember to call @code{obstack_object_size} @emph{before} finishing the object.
After it is finished, @code{obstack_object_size} will return zero.
@end deftypefun
@@ -429,53 +429,48 @@ obstack_free (obstack_ptr, obstack_finish (obstack_ptr));
@noindent
This has no effect if no object was growing.
-@cindex shrinking objects
-You can use @code{obstack_blank} with a negative size argument to make
-the current object smaller. Just don't try to shrink it beyond zero
-length---there's no telling what will happen if you do that.
-
@node Extra Fast Growing
@subsubsection Extra Fast Growing Objects
@cindex efficiency and obstacks
-The usual functions for growing objects incur overhead for checking
+The usual macros for growing objects incur overhead for checking
whether there is room for the new growth in the current chunk. If you
are frequently constructing objects in small steps of growth, this
overhead can be significant.
You can reduce the overhead by using special ``fast growth''
-functions that grow the object without checking. In order to have a
+macros that grow the object without checking. In order to have a
robust program, you must do the checking yourself. If you do this checking
in the simplest way each time you are about to add data to the object, you
have not saved anything, because that is what the ordinary growth
-functions do. But if you can arrange to check less often, or check
+macros do. But if you can arrange to check less often, or check
more efficiently, then you make the program faster.
-The function @code{obstack_room} returns the amount of room available
-in the current chunk. It is declared as follows:
+@code{obstack_room} returns the amount of room available
+in the current chunk.
@comment obstack.h
@comment GNU
-@deftypefun int obstack_room (struct obstack *@var{obstack-ptr})
+@deftypefun size_t obstack_room (struct obstack *@var{obstack-ptr})
This returns the number of bytes that can be added safely to the current
growing object (or to an object about to be started) in obstack
-@var{obstack} using the fast growth functions.
+@var{obstack} using the fast growth macros.
@end deftypefun
-While you know there is room, you can use these fast growth functions
+While you know there is room, you can use these fast growth macros
for adding data to a growing object:
@comment obstack.h
@comment GNU
@deftypefun void obstack_1grow_fast (struct obstack *@var{obstack-ptr}, char @var{c})
-The function @code{obstack_1grow_fast} adds one byte containing the
+@code{obstack_1grow_fast} adds one byte containing the
character @var{c} to the growing object in obstack @var{obstack-ptr}.
@end deftypefun
@comment obstack.h
@comment GNU
@deftypefun void obstack_ptr_grow_fast (struct obstack *@var{obstack-ptr}, void *@var{data})
-The function @code{obstack_ptr_grow_fast} adds @code{sizeof (void *)}
+@code{obstack_ptr_grow_fast} adds @code{sizeof (void *)}
bytes containing the value of @var{data} to the growing object in
obstack @var{obstack-ptr}.
@end deftypefun
@@ -483,42 +478,42 @@ obstack @var{obstack-ptr}.
@comment obstack.h
@comment GNU
@deftypefun void obstack_int_grow_fast (struct obstack *@var{obstack-ptr}, int @var{data})
-The function @code{obstack_int_grow_fast} adds @code{sizeof (int)} bytes
+@code{obstack_int_grow_fast} adds @code{sizeof (int)} bytes
containing the value of @var{data} to the growing object in obstack
@var{obstack-ptr}.
@end deftypefun
@comment obstack.h
@comment GNU
-@deftypefun void obstack_blank_fast (struct obstack *@var{obstack-ptr}, int @var{size})
-The function @code{obstack_blank_fast} adds @var{size} bytes to the
+@deftypefun void obstack_blank_fast (struct obstack *@var{obstack-ptr}, size_t @var{size})
+@code{obstack_blank_fast} adds @var{size} bytes to the
growing object in obstack @var{obstack-ptr} without initializing them.
@end deftypefun
When you check for space using @code{obstack_room} and there is not
-enough room for what you want to add, the fast growth functions
+enough room for what you want to add, the fast growth macros
are not safe. In this case, simply use the corresponding ordinary
-growth function instead. Very soon this will copy the object to a
+growth macro instead. Very soon this will copy the object to a
new chunk; then there will be lots of room available again.
-So, each time you use an ordinary growth function, check afterward for
+So, each time you use an ordinary growth macro, check afterward for
sufficient space using @code{obstack_room}. Once the object is copied
to a new chunk, there will be plenty of space again, so the program will
-start using the fast growth functions again.
+start using the fast growth macros again.
Here is an example:
@smallexample
@group
void
-add_string (struct obstack *obstack, const char *ptr, int len)
+add_string (struct obstack *obstack, const char *ptr, size_t len)
@{
while (len > 0)
@{
- int room = obstack_room (obstack);
+ size_t room = obstack_room (obstack);
if (room == 0)
@{
- /* @r{Not enough room. Add one character slowly,}
+ /* @r{Not enough room. Add one character slowly,}
@r{which may copy to a new chunk and make room.} */
obstack_1grow (obstack, *ptr++);
len--;
@@ -537,19 +532,26 @@ add_string (struct obstack *obstack, const char *ptr, int len)
@end group
@end smallexample
+@cindex shrinking objects
+You can use @code{obstack_blank_fast} with a ``negative'' size
+argument to make the current object smaller. Just don't try to shrink
+it beyond zero length---there's no telling what will happen if you do
+that. Earlier versions of obstacks allowed you to use
+@code{obstack_blank} to shrink objects. This will no longer work.
+
@node Status of an Obstack
@subsubsection Status of an Obstack
@cindex obstack status
@cindex status of obstack
-Here are functions that provide information on the current status of
+Here are macros that provide information on the current status of
allocation in an obstack. You can use them to learn about an object while
still growing it.
@comment obstack.h
@comment GNU
@deftypefun {void *} obstack_base (struct obstack *@var{obstack-ptr})
-This function returns the tentative address of the beginning of the
+This macro returns the tentative address of the beginning of the
currently growing object in @var{obstack-ptr}. If you finish the object
immediately, it will have that address. If you make it larger first, it
may outgrow the current chunk---then its address will change!
@@ -562,7 +564,7 @@ chunk).
@comment obstack.h
@comment GNU
@deftypefun {void *} obstack_next_free (struct obstack *@var{obstack-ptr})
-This function returns the address of the first free byte in the current
+This macro returns the address of the first free byte in the current
chunk of obstack @var{obstack-ptr}. This is the end of the currently
growing object. If no object is growing, @code{obstack_next_free}
returns the same value as @code{obstack_base}.
@@ -570,12 +572,12 @@ returns the same value as @code{obstack_base}.
@comment obstack.h
@comment GNU
-@deftypefun int obstack_object_size (struct obstack *@var{obstack-ptr})
-This function returns the size in bytes of the currently growing object.
+@deftypefun size_t obstack_object_size (struct obstack *@var{obstack-ptr})
+This macro returns the size in bytes of the currently growing object.
This is equivalent to
@smallexample
-obstack_next_free (@var{obstack-ptr}) - obstack_base (@var{obstack-ptr})
+((size_t) (obstack_next_free (@var{obstack-ptr}) - obstack_base (@var{obstack-ptr})))
@end smallexample
@end deftypefun
@@ -589,12 +591,11 @@ specified boundary. By default, this boundary is aligned so that
the object can hold any type of data.
To access an obstack's alignment boundary, use the macro
-@code{obstack_alignment_mask}, whose function prototype looks like
-this:
+@code{obstack_alignment_mask}.
@comment obstack.h
@comment GNU
-@deftypefn Macro int obstack_alignment_mask (struct obstack *@var{obstack-ptr})
+@deftypefn Macro size_t obstack_alignment_mask (struct obstack *@var{obstack-ptr})
The value is a bit mask; a bit that is 1 indicates that the corresponding
bit in the address of an object should be 0. The mask value should be one
less than a power of 2; the effect is that all object addresses are
@@ -661,7 +662,7 @@ not to waste too much memory in the portion of the last chunk not yet used.
@comment obstack.h
@comment GNU
-@deftypefn Macro int obstack_chunk_size (struct obstack *@var{obstack-ptr})
+@deftypefn Macro size_t obstack_chunk_size (struct obstack *@var{obstack-ptr})
This returns the chunk size of the given obstack.
@end deftypefn
@@ -679,25 +680,37 @@ if (obstack_chunk_size (obstack_ptr) < @var{new-chunk-size})
@end smallexample
@node Summary of Obstacks
-@subsubsection Summary of Obstack Functions
+@subsubsection Summary of Obstack Macros
-Here is a summary of all the functions associated with obstacks. Each
+Here is a summary of all the macros associated with obstacks. Each
takes the address of an obstack (@code{struct obstack *}) as its first
argument.
@table @code
-@item void obstack_init (struct obstack *@var{obstack-ptr})
+@item int obstack_init (struct obstack *@var{obstack-ptr})
Initialize use of an obstack. @xref{Creating Obstacks}.
-@item void *obstack_alloc (struct obstack *@var{obstack-ptr}, int @var{size})
+@item int obstack_begin (struct obstack *@var{obstack-ptr}, size_t chunk_size)
+Initialize use of an obstack, with an initial chunk of
+@var{chunk_size} bytes.
+
+@item int obstack_specify_allocation (struct obstack *@var{obstack-ptr}, size_t chunk_size, size_t alignment, void *(*chunkfun) (size_t), void (*freefun) (void *))
+Initialize use of an obstack, specifying intial chunk size, chunk
+alignment, and memory allocation functions.
+
+@item int obstack_specify_allocation_with_arg (struct obstack *@var{obstack-ptr}, size_t chunk_size, size_t alignment, void *(*chunkfun) (void *, size_t), void (*freefun) (void *, void *), void *arg)
+Like @code{obstack_specify_allocation}, but specifying memory
+allocation functions that take an extra first argument, @var{arg}.
+
+@item void *obstack_alloc (struct obstack *@var{obstack-ptr}, size_t @var{size})
Allocate an object of @var{size} uninitialized bytes.
@xref{Allocation in an Obstack}.
-@item void *obstack_copy (struct obstack *@var{obstack-ptr}, void *@var{address}, int @var{size})
+@item void *obstack_copy (struct obstack *@var{obstack-ptr}, void *@var{address}, size_t @var{size})
Allocate an object of @var{size} bytes, with contents copied from
@var{address}. @xref{Allocation in an Obstack}.
-@item void *obstack_copy0 (struct obstack *@var{obstack-ptr}, void *@var{address}, int @var{size})
+@item void *obstack_copy0 (struct obstack *@var{obstack-ptr}, void *@var{address}, size_t @var{size})
Allocate an object of @var{size}+1 bytes, with @var{size} of them copied
from @var{address}, followed by a null character at the end.
@xref{Allocation in an Obstack}.
@@ -706,15 +719,15 @@ from @var{address}, followed by a null character at the end.
Free @var{object} (and everything allocated in the specified obstack
more recently than @var{object}). @xref{Freeing Obstack Objects}.
-@item void obstack_blank (struct obstack *@var{obstack-ptr}, int @var{size})
+@item void obstack_blank (struct obstack *@var{obstack-ptr}, size_t @var{size})
Add @var{size} uninitialized bytes to a growing object.
@xref{Growing Objects}.
-@item void obstack_grow (struct obstack *@var{obstack-ptr}, void *@var{address}, int @var{size})
+@item void obstack_grow (struct obstack *@var{obstack-ptr}, void *@var{address}, size_t @var{size})
Add @var{size} bytes, copied from @var{address}, to a growing object.
@xref{Growing Objects}.
-@item void obstack_grow0 (struct obstack *@var{obstack-ptr}, void *@var{address}, int @var{size})
+@item void obstack_grow0 (struct obstack *@var{obstack-ptr}, void *@var{address}, size_t @var{size})
Add @var{size} bytes, copied from @var{address}, to a growing object,
and then add another byte containing a null character. @xref{Growing
Objects}.
@@ -727,11 +740,11 @@ Add one byte containing @var{data-char} to a growing object.
Finalize the object that is growing and return its permanent address.
@xref{Growing Objects}.
-@item int obstack_object_size (struct obstack *@var{obstack-ptr})
+@item size_t obstack_object_size (struct obstack *@var{obstack-ptr})
Get the current size of the currently growing object. @xref{Growing
Objects}.
-@item void obstack_blank_fast (struct obstack *@var{obstack-ptr}, int @var{size})
+@item void obstack_blank_fast (struct obstack *@var{obstack-ptr}, size_t @var{size})
Add @var{size} uninitialized bytes to a growing object without checking
that there is enough room. @xref{Extra Fast Growing}.
@@ -739,15 +752,15 @@ that there is enough room. @xref{Extra Fast Growing}.
Add one byte containing @var{data-char} to a growing object without
checking that there is enough room. @xref{Extra Fast Growing}.
-@item int obstack_room (struct obstack *@var{obstack-ptr})
+@item size_t obstack_room (struct obstack *@var{obstack-ptr})
Get the amount of room now available for growing the current object.
@xref{Extra Fast Growing}.
-@item int obstack_alignment_mask (struct obstack *@var{obstack-ptr})
+@item size_t obstack_alignment_mask (struct obstack *@var{obstack-ptr})
The mask used for aligning the beginning of an object. This is an
lvalue. @xref{Obstacks Data Alignment}.
-@item int obstack_chunk_size (struct obstack *@var{obstack-ptr})
+@item size_t obstack_chunk_size (struct obstack *@var{obstack-ptr})
The size for allocating chunks. This is an lvalue. @xref{Obstack Chunks}.
@item void *obstack_base (struct obstack *@var{obstack-ptr})
diff --git a/libobjc/ChangeLog b/libobjc/ChangeLog
index 3405ba71bef..e853396e8e4 100644
--- a/libobjc/ChangeLog
+++ b/libobjc/ChangeLog
@@ -1,3 +1,14 @@
+2015-11-07 Trevor Saunders <tbsaunde+gcc@tbsaunde.org>
+
+ PR libobjc/24775
+ * encoding.c (_darwin_rs6000_special_round_type_align): Use
+ __CHAR_BIT__ instead of BITS_PER_UNIT.
+ (objc_sizeof_type): Likewise.
+ (objc_layout_structure): Likewise.
+ (objc_layout_structure_next_member): Likewise.
+ (objc_layout_finish_structure): Likewise.
+ (objc_layout_structure_get_info): Likewise.
+
2015-11-03 Trevor Saunders <tbsaunde+gcc@tbsaunde.org>
PR libobjc/24775
diff --git a/libobjc/encoding.c b/libobjc/encoding.c
index 7de768f4509..ca34c7d525a 100644
--- a/libobjc/encoding.c
+++ b/libobjc/encoding.c
@@ -94,11 +94,8 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
/* Some ports (eg ARM) allow the structure size boundary to be
selected at compile-time. We override the normal definition with
one that has a constant value for this compilation. */
-#ifndef BITS_PER_UNIT
-#define BITS_PER_UNIT 8
-#endif
#undef STRUCTURE_SIZE_BOUNDARY
-#define STRUCTURE_SIZE_BOUNDARY (BITS_PER_UNIT * sizeof (struct{char a;}))
+#define STRUCTURE_SIZE_BOUNDARY (__CHAR_BIT__ * sizeof (struct{char a;}))
/* Some ROUND_TYPE_ALIGN macros use TARGET_foo, and consequently
target_flags. Define a dummy entry here to so we don't die.
@@ -163,7 +160,7 @@ _darwin_rs6000_special_round_type_align (const char *struc, int comp, int spec)
{
case RECORD_TYPE:
case UNION_TYPE:
- return MAX (MAX (comp, spec), objc_alignof_type (_stp) * BITS_PER_UNIT);
+ return MAX (MAX (comp, spec), objc_alignof_type (_stp) * __CHAR_BIT__);
break;
case DFmode:
case _C_LNG_LNG:
@@ -335,8 +332,8 @@ objc_sizeof_type (const char *type)
;
size = atoi (type + 1);
- startByte = position / BITS_PER_UNIT;
- endByte = (position + size) / BITS_PER_UNIT;
+ startByte = position / __CHAR_BIT__;
+ endByte = (position + size) / __CHAR_BIT__;
return endByte - startByte;
}
@@ -1093,7 +1090,7 @@ objc_layout_structure (const char *type,
layout->type = type;
layout->prev_type = NULL;
layout->record_size = 0;
- layout->record_align = BITS_PER_UNIT;
+ layout->record_align = __CHAR_BIT__;
layout->record_align = MAX (layout->record_align, STRUCTURE_SIZE_BOUNDARY);
}
@@ -1117,10 +1114,10 @@ objc_layout_structure_next_member (struct objc_struct_layout *layout)
type = objc_skip_type_qualifiers (layout->prev_type);
if (unionp)
layout->record_size = MAX (layout->record_size,
- objc_sizeof_type (type) * BITS_PER_UNIT);
+ objc_sizeof_type (type) * __CHAR_BIT__);
else if (*type != _C_BFLD)
- layout->record_size += objc_sizeof_type (type) * BITS_PER_UNIT;
+ layout->record_size += objc_sizeof_type (type) * __CHAR_BIT__;
else {
/* Get the bitfield's type */
for (bfld_type = type + 1;
@@ -1128,7 +1125,7 @@ objc_layout_structure_next_member (struct objc_struct_layout *layout)
bfld_type++)
/* do nothing */;
- bfld_type_align = objc_alignof_type (bfld_type) * BITS_PER_UNIT;
+ bfld_type_align = objc_alignof_type (bfld_type) * __CHAR_BIT__;
bfld_field_size = atoi (objc_skip_typespec (bfld_type));
layout->record_size += bfld_field_size;
}
@@ -1143,7 +1140,7 @@ objc_layout_structure_next_member (struct objc_struct_layout *layout)
type = objc_skip_type_qualifiers (layout->type);
if (*type != _C_BFLD)
- desired_align = objc_alignof_type (type) * BITS_PER_UNIT;
+ desired_align = objc_alignof_type (type) * __CHAR_BIT__;
else
{
desired_align = 1;
@@ -1153,7 +1150,7 @@ objc_layout_structure_next_member (struct objc_struct_layout *layout)
bfld_type++)
/* do nothing */;
- bfld_type_align = objc_alignof_type (bfld_type) * BITS_PER_UNIT;
+ bfld_type_align = objc_alignof_type (bfld_type) * __CHAR_BIT__;
bfld_field_size = atoi (objc_skip_typespec (bfld_type));
}
@@ -1180,7 +1177,7 @@ objc_layout_structure_next_member (struct objc_struct_layout *layout)
if (bfld_field_size)
layout->record_align = MAX (layout->record_align, desired_align);
else
- desired_align = objc_alignof_type (bfld_type) * BITS_PER_UNIT;
+ desired_align = objc_alignof_type (bfld_type) * __CHAR_BIT__;
/* A named bit field of declared type `int'
forces the entire structure to have `int' alignment.
@@ -1194,7 +1191,7 @@ objc_layout_structure_next_member (struct objc_struct_layout *layout)
if (maximum_field_alignment != 0)
type_align = MIN (type_align, maximum_field_alignment);
else if (DECL_PACKED (field))
- type_align = MIN (type_align, BITS_PER_UNIT);
+ type_align = MIN (type_align, __CHAR_BIT__);
#endif
layout->record_align = MAX (layout->record_align, type_align);
@@ -1251,9 +1248,9 @@ void objc_layout_finish_structure (struct objc_struct_layout *layout,
layout->type = NULL;
}
if (size)
- *size = layout->record_size / BITS_PER_UNIT;
+ *size = layout->record_size / __CHAR_BIT__;
if (align)
- *align = layout->record_align / BITS_PER_UNIT;
+ *align = layout->record_align / __CHAR_BIT__;
}
void objc_layout_structure_get_info (struct objc_struct_layout *layout,
@@ -1262,9 +1259,9 @@ void objc_layout_structure_get_info (struct objc_struct_layout *layout,
const char **type)
{
if (offset)
- *offset = layout->record_size / BITS_PER_UNIT;
+ *offset = layout->record_size / __CHAR_BIT__;
if (align)
- *align = layout->record_align / BITS_PER_UNIT;
+ *align = layout->record_align / __CHAR_BIT__;
if (type)
*type = layout->prev_type;
}
diff --git a/libsanitizer/ChangeLog b/libsanitizer/ChangeLog
index f105e47b9f0..7de18c88eaf 100644
--- a/libsanitizer/ChangeLog
+++ b/libsanitizer/ChangeLog
@@ -1,3 +1,21 @@
+2015-11-09 Alan Modra <amodra@gmail.com>
+
+ * sanitizer_common/sanitizer_common_interceptors.inc: Update size
+ params for _obstack_begin_1, _obstack_begin, _obstack_newchunk
+ interceptors.
+ * configure.ac: Substitute OBSTACK_DEFS.
+ * asan/Makefile.am: Add OBSTACK_DEFS to DEFS.
+ * tsan/Makefile.am: Likewise.
+ * configure: Regenerate.
+ * Makefile.in: Regenerate.
+ * asan/Makefile.in: Regenerate.
+ * interception/Makefile.in: Regenerate.
+ * libbacktrace/Makefile.in: Regenerate.
+ * lsan/Makefile.in: Regenerate.
+ * sanitizer_common/Makefile.in: Regenerate.
+ * tsan/Makefile.in: Regenerate.
+ * ubsan/Makefile.in: Regenerate.
+
2015-10-22 Maxim Ostapenko <m.ostapenko@partner.samsung.com>
PR bootstrap/68041
diff --git a/libsanitizer/Makefile.in b/libsanitizer/Makefile.in
index 1278900c0d4..b362a897fd1 100644
--- a/libsanitizer/Makefile.in
+++ b/libsanitizer/Makefile.in
@@ -198,6 +198,7 @@ NM = @NM@
NMEDIT = @NMEDIT@
OBJDUMP = @OBJDUMP@
OBJEXT = @OBJEXT@
+OBSTACK_DEFS = @OBSTACK_DEFS@
OTOOL = @OTOOL@
OTOOL64 = @OTOOL64@
PACKAGE = @PACKAGE@
diff --git a/libsanitizer/asan/Makefile.am b/libsanitizer/asan/Makefile.am
index bd3cd735a98..4500e2130da 100644
--- a/libsanitizer/asan/Makefile.am
+++ b/libsanitizer/asan/Makefile.am
@@ -3,7 +3,7 @@ AM_CPPFLAGS = -I $(top_srcdir)/include -I $(top_srcdir)
# May be used by toolexeclibdir.
gcc_version := $(shell cat $(top_srcdir)/../gcc/BASE-VER)
-DEFS = -D_GNU_SOURCE -D_DEBUG -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS -DASAN_HAS_EXCEPTIONS=1 -DASAN_NEEDS_SEGV=1 -DCAN_SANITIZE_UB=0
+DEFS = -D_GNU_SOURCE -D_DEBUG -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS -DASAN_HAS_EXCEPTIONS=1 -DASAN_NEEDS_SEGV=1 -DCAN_SANITIZE_UB=0 @OBSTACK_DEFS@
if USING_MAC_INTERPOSE
DEFS += -DMAC_INTERPOSE_FUNCTIONS -DMISSING_BLOCKS_SUPPORT
endif
diff --git a/libsanitizer/asan/Makefile.in b/libsanitizer/asan/Makefile.in
index 229c7b400d1..881d1d394d5 100644
--- a/libsanitizer/asan/Makefile.in
+++ b/libsanitizer/asan/Makefile.in
@@ -173,7 +173,7 @@ CYGPATH_W = @CYGPATH_W@
DEFS = -D_GNU_SOURCE -D_DEBUG -D__STDC_CONSTANT_MACROS \
-D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS \
-DASAN_HAS_EXCEPTIONS=1 -DASAN_NEEDS_SEGV=1 \
- -DCAN_SANITIZE_UB=0 $(am__append_1)
+ -DCAN_SANITIZE_UB=0 @OBSTACK_DEFS@ $(am__append_1)
DEPDIR = @DEPDIR@
DSYMUTIL = @DSYMUTIL@
DUMPBIN = @DUMPBIN@
@@ -207,6 +207,7 @@ NM = @NM@
NMEDIT = @NMEDIT@
OBJDUMP = @OBJDUMP@
OBJEXT = @OBJEXT@
+OBSTACK_DEFS = @OBSTACK_DEFS@
OTOOL = @OTOOL@
OTOOL64 = @OTOOL64@
PACKAGE = @PACKAGE@
diff --git a/libsanitizer/configure b/libsanitizer/configure
index 2701ee7a8ee..a0fc860bfce 100755
--- a/libsanitizer/configure
+++ b/libsanitizer/configure
@@ -607,6 +607,7 @@ LIBOBJS
TSAN_TARGET_DEPENDENT_OBJECTS
LIBBACKTRACE_SUPPORTED_FALSE
LIBBACKTRACE_SUPPORTED_TRUE
+OBSTACK_DEFS
RPC_DEFS
BACKTRACE_SUPPORTS_THREADS
BACKTRACE_USES_MALLOC
@@ -12027,7 +12028,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF
-#line 12030 "configure"
+#line 12031 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@@ -12133,7 +12134,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF
-#line 12136 "configure"
+#line 12137 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@@ -16431,6 +16432,39 @@ fi
RPC_DEFS=$rpc_defs
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking obstack params" >&5
+$as_echo_n "checking obstack params... " >&6; }
+if test "${libsanitizer_cv_sys_obstack+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ save_cppflags=$CPPFLAGS
+CPPFLAGS="-I${srcdir}/../include -o conftest.iii $CPPFLAGS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+#include "obstack.h"
+#ifdef _OBSTACK_SIZE_T
+_OBSTACK_SIZE_T
+#else
+int
+#endif
+
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+ libsanitizer_cv_sys_obstack=`sed -e '/^#/d;/^[ ]*$/d' conftest.iii | sed -e '$!d;s/size_t/SIZE_T/'`
+else
+ libsanitizer_cv_sys_obstack=int
+fi
+rm -f conftest.err conftest.$ac_ext
+CPPFLAGS=$save_cppflags
+rm -f conftest.iii
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libsanitizer_cv_sys_obstack" >&5
+$as_echo "$libsanitizer_cv_sys_obstack" >&6; }
+OBSTACK_DEFS=-D_OBSTACK_SIZE_T=\"$libsanitizer_cv_sys_obstack\"
+
+
if test "x${BACKTRACE_SUPPORTED}x${BACKTRACE_USES_MALLOC}" = "x1x0"; then
LIBBACKTRACE_SUPPORTED_TRUE=
LIBBACKTRACE_SUPPORTED_FALSE='#'
diff --git a/libsanitizer/configure.ac b/libsanitizer/configure.ac
index 81fd46d2980..72b13a10367 100644
--- a/libsanitizer/configure.ac
+++ b/libsanitizer/configure.ac
@@ -335,6 +335,30 @@ fi
AC_SUBST([RPC_DEFS], [$rpc_defs])
+dnl If this file is processed by autoconf-2.67 or later then the CPPFLAGS
+dnl "-o conftest.iii" can disappear, conftest.iii be replaced with
+dnl conftest.i in the sed command line, and the rm deleted.
+dnl Not all cpp's accept -o, and gcc -E does not accept a second file
+dnl argument as the output file.
+AC_CACHE_CHECK([obstack params],
+[libsanitizer_cv_sys_obstack],
+[save_cppflags=$CPPFLAGS
+CPPFLAGS="-I${srcdir}/../include -o conftest.iii $CPPFLAGS"
+AC_PREPROC_IFELSE([AC_LANG_SOURCE([
+#include "obstack.h"
+#ifdef _OBSTACK_SIZE_T
+_OBSTACK_SIZE_T
+#else
+int
+#endif
+])],
+[libsanitizer_cv_sys_obstack=`sed -e '/^#/d;/^[ ]*$/d' conftest.iii | sed -e '$!d;s/size_t/SIZE_T/'`],
+[libsanitizer_cv_sys_obstack=int])
+CPPFLAGS=$save_cppflags
+rm -f conftest.iii
+])
+AC_SUBST([OBSTACK_DEFS], [-D_OBSTACK_SIZE_T=\"$libsanitizer_cv_sys_obstack\"])
+
AM_CONDITIONAL(LIBBACKTRACE_SUPPORTED,
[test "x${BACKTRACE_SUPPORTED}x${BACKTRACE_USES_MALLOC}" = "x1x0"])
diff --git a/libsanitizer/interception/Makefile.in b/libsanitizer/interception/Makefile.in
index 3dfa7746779..c7ccb51a177 100644
--- a/libsanitizer/interception/Makefile.in
+++ b/libsanitizer/interception/Makefile.in
@@ -157,6 +157,7 @@ NM = @NM@
NMEDIT = @NMEDIT@
OBJDUMP = @OBJDUMP@
OBJEXT = @OBJEXT@
+OBSTACK_DEFS = @OBSTACK_DEFS@
OTOOL = @OTOOL@
OTOOL64 = @OTOOL64@
PACKAGE = @PACKAGE@
diff --git a/libsanitizer/libbacktrace/Makefile.in b/libsanitizer/libbacktrace/Makefile.in
index ff37a81e4ec..57eaaf0f3cf 100644
--- a/libsanitizer/libbacktrace/Makefile.in
+++ b/libsanitizer/libbacktrace/Makefile.in
@@ -199,6 +199,7 @@ NM = @NM@
NMEDIT = @NMEDIT@
OBJDUMP = @OBJDUMP@
OBJEXT = @OBJEXT@
+OBSTACK_DEFS = @OBSTACK_DEFS@
OTOOL = @OTOOL@
OTOOL64 = @OTOOL64@
PACKAGE = @PACKAGE@
diff --git a/libsanitizer/lsan/Makefile.in b/libsanitizer/lsan/Makefile.in
index b02c3736a49..4802ed43971 100644
--- a/libsanitizer/lsan/Makefile.in
+++ b/libsanitizer/lsan/Makefile.in
@@ -198,6 +198,7 @@ NM = @NM@
NMEDIT = @NMEDIT@
OBJDUMP = @OBJDUMP@
OBJEXT = @OBJEXT@
+OBSTACK_DEFS = @OBSTACK_DEFS@
OTOOL = @OTOOL@
OTOOL64 = @OTOOL64@
PACKAGE = @PACKAGE@
diff --git a/libsanitizer/sanitizer_common/Makefile.in b/libsanitizer/sanitizer_common/Makefile.in
index 4b008ad7ae6..765efd186d3 100644
--- a/libsanitizer/sanitizer_common/Makefile.in
+++ b/libsanitizer/sanitizer_common/Makefile.in
@@ -186,6 +186,7 @@ NM = @NM@
NMEDIT = @NMEDIT@
OBJDUMP = @OBJDUMP@
OBJEXT = @OBJEXT@
+OBSTACK_DEFS = @OBSTACK_DEFS@
OTOOL = @OTOOL@
OTOOL64 = @OTOOL64@
PACKAGE = @PACKAGE@
diff --git a/libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc b/libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc
index 9b8c77e6901..92b90278d2d 100644
--- a/libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc
+++ b/libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc
@@ -4874,8 +4874,9 @@ static void initialize_obstack(__sanitizer_obstack *obstack) {
sizeof(*obstack->chunk));
}
-INTERCEPTOR(int, _obstack_begin_1, __sanitizer_obstack *obstack, int sz,
- int align, void *(*alloc_fn)(uptr arg, uptr sz),
+INTERCEPTOR(int, _obstack_begin_1, __sanitizer_obstack *obstack,
+ _OBSTACK_SIZE_T sz, _OBSTACK_SIZE_T align,
+ void *(*alloc_fn)(uptr arg, SIZE_T sz),
void (*free_fn)(uptr arg, void *p)) {
void *ctx;
COMMON_INTERCEPTOR_ENTER(ctx, _obstack_begin_1, obstack, sz, align, alloc_fn,
@@ -4884,8 +4885,10 @@ INTERCEPTOR(int, _obstack_begin_1, __sanitizer_obstack *obstack, int sz,
if (res) initialize_obstack(obstack);
return res;
}
-INTERCEPTOR(int, _obstack_begin, __sanitizer_obstack *obstack, int sz,
- int align, void *(*alloc_fn)(uptr sz), void (*free_fn)(void *p)) {
+INTERCEPTOR(int, _obstack_begin, __sanitizer_obstack *obstack,
+ _OBSTACK_SIZE_T sz, _OBSTACK_SIZE_T align,
+ void *(*alloc_fn)(SIZE_T sz),
+ void (*free_fn)(void *p)) {
void *ctx;
COMMON_INTERCEPTOR_ENTER(ctx, _obstack_begin, obstack, sz, align, alloc_fn,
free_fn);
@@ -4893,7 +4896,8 @@ INTERCEPTOR(int, _obstack_begin, __sanitizer_obstack *obstack, int sz,
if (res) initialize_obstack(obstack);
return res;
}
-INTERCEPTOR(void, _obstack_newchunk, __sanitizer_obstack *obstack, int length) {
+INTERCEPTOR(void, _obstack_newchunk, __sanitizer_obstack *obstack,
+ _OBSTACK_SIZE_T length) {
void *ctx;
COMMON_INTERCEPTOR_ENTER(ctx, _obstack_newchunk, obstack, length);
REAL(_obstack_newchunk)(obstack, length);
diff --git a/libsanitizer/tsan/Makefile.am b/libsanitizer/tsan/Makefile.am
index 5c732cb50c3..dc22db5d446 100644
--- a/libsanitizer/tsan/Makefile.am
+++ b/libsanitizer/tsan/Makefile.am
@@ -3,7 +3,7 @@ AM_CPPFLAGS = -I $(top_srcdir) -I $(top_srcdir)/include
# May be used by toolexeclibdir.
gcc_version := $(shell cat $(top_srcdir)/../gcc/BASE-VER)
-DEFS = -D_GNU_SOURCE -D_DEBUG -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS -DCAN_SANITIZE_UB=0
+DEFS = -D_GNU_SOURCE -D_DEBUG -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS -DCAN_SANITIZE_UB=0 @OBSTACK_DEFS@
AM_CXXFLAGS = -Wall -W -Wno-unused-parameter -Wwrite-strings -pedantic -Wno-long-long -fPIC -fno-builtin -fno-exceptions -fno-rtti -fomit-frame-pointer -funwind-tables -fvisibility=hidden -Wno-variadic-macros
AM_CXXFLAGS += $(LIBSTDCXX_RAW_CXX_CXXFLAGS)
AM_CXXFLAGS += -std=gnu++11
diff --git a/libsanitizer/tsan/Makefile.in b/libsanitizer/tsan/Makefile.in
index bd196073e03..6d5d2efbf57 100644
--- a/libsanitizer/tsan/Makefile.in
+++ b/libsanitizer/tsan/Makefile.in
@@ -177,7 +177,7 @@ CXXCPP = @CXXCPP@
CXXDEPMODE = @CXXDEPMODE@
CXXFLAGS = @CXXFLAGS@
CYGPATH_W = @CYGPATH_W@
-DEFS = -D_GNU_SOURCE -D_DEBUG -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS -DCAN_SANITIZE_UB=0
+DEFS = -D_GNU_SOURCE -D_DEBUG -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS -DCAN_SANITIZE_UB=0 @OBSTACK_DEFS@
DEPDIR = @DEPDIR@
DSYMUTIL = @DSYMUTIL@
DUMPBIN = @DUMPBIN@
@@ -211,6 +211,7 @@ NM = @NM@
NMEDIT = @NMEDIT@
OBJDUMP = @OBJDUMP@
OBJEXT = @OBJEXT@
+OBSTACK_DEFS = @OBSTACK_DEFS@
OTOOL = @OTOOL@
OTOOL64 = @OTOOL64@
PACKAGE = @PACKAGE@
diff --git a/libsanitizer/ubsan/Makefile.in b/libsanitizer/ubsan/Makefile.in
index 51d4da58516..f5b06d06d41 100644
--- a/libsanitizer/ubsan/Makefile.in
+++ b/libsanitizer/ubsan/Makefile.in
@@ -196,6 +196,7 @@ NM = @NM@
NMEDIT = @NMEDIT@
OBJDUMP = @OBJDUMP@
OBJEXT = @OBJEXT@
+OBSTACK_DEFS = @OBSTACK_DEFS@
OTOOL = @OTOOL@
OTOOL64 = @OTOOL64@
PACKAGE = @PACKAGE@
diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog
index abd4482ca95..9b50f1cd17e 100644
--- a/libstdc++-v3/ChangeLog
+++ b/libstdc++-v3/ChangeLog
@@ -1,3 +1,15 @@
+2015-11-06 Kai Tietz <ktietz70@googlemail.com>
+
+ * testsuite/26_numerics/complex/requirements/constexpr.cc
+ * testsuite/26_numerics/complex/requirements/constexpr_functions.cc:
+ Use constexpr where needed.
+
+2015-11-06 David Malcolm <dmalcolm@redhat.com>
+
+ * testsuite/lib/libstdc++.exp (v3_target_compile): Add
+ -fno-diagnostics-show-caret -fdiagnostics-color=never to
+ option's additional_flags.
+
2015-11-03 Jason Merrill <jason@redhat.com>
* libsupc++/new: Declare sized deletes.
diff --git a/libstdc++-v3/testsuite/26_numerics/complex/requirements/constexpr_functions.cc b/libstdc++-v3/testsuite/26_numerics/complex/requirements/constexpr_functions.cc
index c125a32ca6a..28a6d2cca2c 100644
--- a/libstdc++-v3/testsuite/26_numerics/complex/requirements/constexpr_functions.cc
+++ b/libstdc++-v3/testsuite/26_numerics/complex/requirements/constexpr_functions.cc
@@ -34,7 +34,7 @@ namespace __gnu_test
void __constraint()
{
typedef typename _Ttesttype::_ComplexT _ComplexT;
- const _ComplexT cc = { 1.1 };
+ constexpr _ComplexT cc = { 1.1 };
constexpr _Ttesttype a(cc);
constexpr auto v1 __attribute__((unused)) = a.real();
constexpr auto v2 __attribute__((unused)) = a.imag();
diff --git a/libstdc++-v3/testsuite/26_numerics/complex/value_operations/constexpr.cc b/libstdc++-v3/testsuite/26_numerics/complex/value_operations/constexpr.cc
index c7089a953a4..c3170c15fcd 100644
--- a/libstdc++-v3/testsuite/26_numerics/complex/value_operations/constexpr.cc
+++ b/libstdc++-v3/testsuite/26_numerics/complex/value_operations/constexpr.cc
@@ -34,7 +34,7 @@ namespace __gnu_test
void __constraint()
{
typedef typename _Ttesttype::_ComplexT _ComplexT;
- const _ComplexT cc = { 1.1 };
+ constexpr _ComplexT cc = { 1.1 };
constexpr _Ttesttype a(cc);
constexpr auto v1 __attribute__((unused)) = real(a);
constexpr auto v2 __attribute__((unused)) = imag(a);
diff --git a/libstdc++-v3/testsuite/lib/libstdc++.exp b/libstdc++-v3/testsuite/lib/libstdc++.exp
index 769ac9434b2..9a6726c8ce7 100644
--- a/libstdc++-v3/testsuite/lib/libstdc++.exp
+++ b/libstdc++-v3/testsuite/lib/libstdc++.exp
@@ -467,6 +467,8 @@ proc v3_target_compile { source dest type options } {
global STATIC_LIBCXXFLAGS
global tool
+ lappend options "additional_flags=-fno-diagnostics-show-caret -fdiagnostics-color=never"
+
if { [target_info needs_status_wrapper] != "" && [info exists gluefile] } {
lappend options "libs=${gluefile}"
lappend options "ldflags=${wrap_flags}"
diff --git a/libvtv/ChangeLog b/libvtv/ChangeLog
index 57fe850bff5..4f216ac7703 100644
--- a/libvtv/ChangeLog
+++ b/libvtv/ChangeLog
@@ -1,3 +1,8 @@
+2015-11-09 Alan Modra <amodra@gmail.com>
+
+ * vtv_malloc.cc (obstack_chunk_free): Correct param type.
+ (__vtv_malloc_init): Use obstack_specify_allocation.
+
2015-10-20 Ramana Radhakrishnan <ramana.radhakrishnan@arm.com>
* configure.tgt (aarch64*-*-linux): Enable.
diff --git a/libvtv/vtv_malloc.cc b/libvtv/vtv_malloc.cc
index ecd07eb709c..ea26b8245c3 100644
--- a/libvtv/vtv_malloc.cc
+++ b/libvtv/vtv_malloc.cc
@@ -194,7 +194,7 @@ obstack_chunk_alloc (size_t size)
}
static void
-obstack_chunk_free (size_t)
+obstack_chunk_free (void *)
{
/* Do nothing. For our purposes there should be very little
de-allocation. */
@@ -217,14 +217,13 @@ __vtv_malloc_init (void)
#endif
VTV_error ();
- obstack_chunk_size (&vtv_obstack) = VTV_PAGE_SIZE;
- obstack_alignment_mask (&vtv_obstack) = sizeof (long) - 1;
/* We guarantee that the obstack alloc failed handler will never be
called because in case the allocation of the chunk fails, it will
never return */
obstack_alloc_failed_handler = NULL;
- obstack_init (&vtv_obstack);
+ obstack_specify_allocation (&vtv_obstack, VTV_PAGE_SIZE, sizeof (long),
+ obstack_chunk_alloc, obstack_chunk_free);
malloc_initialized = 1;
}